[
  {
    "path": ".cargo/config.toml",
    "content": "[alias]\nbuild-man = \"run --package xtask-build-man --\"\nstale-label = \"run --package xtask-stale-label --\"\nbump-check = \"run --package xtask-bump-check --\"\nlint-docs = \"run --package xtask-lint-docs --\"\nspellcheck = \"run --package xtask-spellcheck --\"\n\n[env]\n# HACK: Until this is stabilized, `snapbox`s polyfill could get confused\n# inside of the rust-lang/rust repo because it looks for the furthest-away `Cargo.toml`\nCARGO_RUSTC_CURRENT_DIR = { value = \"\", relative = true }\n"
  },
  {
    "path": ".git-blame-ignore-revs",
    "content": "# Use `git config blame.ignorerevsfile .git-blame-ignore-revs` to make `git blame` ignore the following commits.\n\n# refactor: rustfmt for tracing\ne84cc17db6ac48620e2723f51bce0703f5590060\n# Rustfmt with latest nightly.\n43c253e69a20321cdfd73d632fa5ec641b1aace3\n#  reformat with rustfmt\ndf62c36b214449003997d8ee630c7d5c1c08a90c\n# rustfmt\nc973a6d0af55785f3072623b4d29127051a84b90\n# Apply rustfmt\nebd0d58c1c11f98e804c80b3378d00f9e1000a95\n# rustfmt\n4787dd3acfb32c6d608342bca115094e1ed866e7\n# Fix for rustfmt\nad44f0e898721f35173b59f32dae344b964dff22\n# rustfmt\nb9554f37abe4f802dd615a550773105a8b2eb386\n# Normalize raw string indentation.\n6f8c7d5a87526d10e3bbfa4098a1002076386068\n# rustfmt\ndcae5fcf2dc6e040d1cadac14276fd306c058b74\n# Rustfmt\n0dfdba6f7a7702a7f45d523b028c896084411de8\n# Run rustfmt\ne06a911de616b3f402f1e142b5202445d333f4eb\n# rustfmt\nd02f476804ae73d79059e3243ecb4c814f53bea1\n# Update for nightly rustfmt.\n4b6c26dd16786b416190bd0a36e7646d33b9846a\n# Run rustfmt\nd0430dd2b11e6ac004e8f39a712ee6425b81e12d\n# Run rustfmt\nc56cb4287fa98a42dafea36d0b88bb4441f63c1f\n# Run rustfmt\nc3f8cd3cd2999949c49c8f0e76108ffe7a37bec0\n# Run code through rustfmt\n648b39e98101f9b6417fc6ebc88fa7f397a5f509\n# Run rustfmt\nba81441f297c6d9799473a62af021236b8bc9ed8\n# Wrap some really long lines.\nd6d15141f8ef21f1cebeaa4d42606f29e7d00239\n# rustfmt for nightly changes.\n384c311692e6ff537b51bcf57f804b917a702c9c\n# Rustfmt lint\n9dc70a3dabb291052a4d117b8348c9b461d1b570\n# Run rustfmt\n3a6cd74434cc1fdd57266740d4827ed162580005\n# rustfmt, even if I disagree\n189fef1173118ee3be47fa59e22fd2d21bb05bbd\n# Fix zalgo formatting.\n56f8848a51e5db5214ec27bb41c7d99ebac21af8\n# Rustfmt adjustments\na50be59a70af64b83c07f40bc2faef80a73bc908\n# Run rustfmt\nebd10526f3526b695872a8ecb381f65aaf74c019\n# Rustfmt fixes\nac2a4382ee5d927d917df026d2236ff5cd668717\n# Rustfmt fixes\nfc4ee774483dc6b40f1edbd259879dc4cbcf20a5\n# Fixed formatting with rustfmt\na82de176952f7c244adbd392d444baaafdfc819c\n# Fix some formatting for some strings.\na4e9611453cb4ba3f9bcc34f2851546f57152229\n# fix(fingerprint): rustfmt\n009876a88af659c10b022ec4c4956f77b983d531\n# Make rustfmt happy\n2415a2980f455238e9422cc07abcfa4cbec9be6b\n# run rustfmt\ndac967ce27d4eeb496dcd98ba91641fbe29df957\n# $cargo fmt --all\ndb09895f3c123c36e05175e2c0273bf487068b37\n# Reformat everything with rustfmt from stable 1.26\nd85336084d8855bfbfd431b85beaa5c094dc5e72\n# rustfmt\na4947c2b47fd38857c7332d333fda7bcc405de0c\n# rustfmt\n404970f2261e2d6c9ba4eac410065fa6226271d9\n# Prettify rustfmted single-line strings\nb0c181d91ccfe1d27d4c7133049a6bfe5bacf29b\n# cargo fmt\n1e6828485eea0f550ed7be46ef96107b46aeb162\n# rustfmt for bin/cargo.rs\nef4c09f986c0b1f701c765d894da911c2de44724\n# rustfmt cargo_doc.rs\n87124d5ade897b3fb38ce5cd0a2f19a9038dd8a7\n# run rustfmt on core/source.rs\n76fb87e2bab025acaff2d6dd919dde0e328267da\n# cargo fmt\n7a67e88baf0f73196973cadf887bf9a31c13e95f\n# cargo fmt\n7a6ff7f068acde98230d712637e934c58fc84805\n# cargo fmt\n7c8ee49bffdeeb138db5e22f14abbf88cf99c547\n# cargo fmt\n72d6c5411a215ce5ab0ff22b1e1e1525883b7c33\n# rust fmt\nddd5c83b8cf63458bf67ae504bb289ed4e987d38\n# cargo fmt\n1179e7ef6b88a6940168cbc2e806d48ed20d92ef\n# cargo fmt\n0c07056bfeffee213e21cdf1e48875f59f834282\n# cargo fmt\nc7a79be6f8a8da1d6dee54fe3f5c137d293692b0\n# cargo fmt\n1839ded4aa5607d3564f02b36e517289ad6ed8e8\n# cargo fmt\nf2b5271a09a13f89a50861ebd71da333836bded3\n# Run `cargo fmt --all`\n3aa99422ca7808f1bc5621fda3a8f32f27273d9b\n# cargo fmt\n4538ade2d55d7353cfac8a0ce320e3c4a29bc450\n# style: cargo fmt\n3d042688a851d985013ee8ff64a9caef47b7b495\n# run cargo fmt to pass the CI build\na4e3b81a55b8c142ab1b84f4f209414a72727e86\n# Run 'cargo fmt'\n60afaa77335ab464a5b6c913883ad145ae97d750\n# Run 'cargo fmt'\n511050baefa2ec21c2be8c3eaee2aade1da2c06b\n# cargo fmt\n577968e44828457dfa62fc10ccd29f42a359b746\n# cargo fmt\nd0f7c0ee31c81cd405dc2c163e4ca7638895610c\n# appease cargo fmt\nc4922052fc7470264f3df491213f74142ac67ebf\n# named-profiles: formatting fixes from 'cargo fmt'\n29b7e90ba37f311baaf448894bbf04721bed5791\n# cargo fmt\nf39302f432f62e29910c876f766eb8a324cee843\n# cargo fmt\n6b07c8da63c0896cc31fa6cb8b47a71fe29c88e2\n# run cargo fmt --all\nb48ae60e67096f7cda80a17dfa2a9ff7a916bbf7\n# $cargo fmt --all\n63a9c7aa6d54ff0580288f1a01795a29b3ea1c75\n# Run `cargo fmt`\nf16efff1509be313f4bed825e7ab974673dd03fc\n# cargo fmt tests/testsuite/rustflags.rs\n3ca98adbbac5752cdef337f5ac803e7843ab601a\n# Format with `cargo fmt`\nfecb72464328846dacd0ff8252d105b7818733ab\n# cargo fmt\n9b2295d11fd2816aa3032403a88d7c055cd2cf58\n# Run `cargo fmt`\n5d201944d7aba8380082dcb9e0c340d92e92850f\n# Correct formatting with cargo fmt\n90954d700ccb71b3df6ecf8ff83891dd3570f887\n# Correct formatting with cargo fmt\n5c241e102756e340991365d7b376997a9ae95f62\n# Fix formatting issues with cargo fmt\n5c7979cdf879a6cc9011432098f7ef68ed7f5e37\n# cargo fmt\na6ad2de0484f1910d42793f3ec73b111403099b7\n# cargo fmt\nb0fbc89c33780ca3e1f2bfeacc67922ee7abe1dc\n# Rustfmt 2024\n1ce80236261a3cd42a95b1f1abcffede87cafef4\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug Report\ndescription: Create a report to help us improve\nlabels: [\"C-bug\", \"S-triage\"]\nbody:\n  - type: markdown\n    attributes:\n      value: Thanks for filing a 🐛 bug report 😄!\n  - type: textarea\n    id: problem\n    attributes:\n      label: Problem\n      description: >\n        Please provide a clear and concise description of what the bug is,\n        including what currently happens and what you expected to happen.\n    validations:\n      required: true\n  - type: textarea\n    id: steps\n    attributes:\n      label: Steps\n      description: Please list the steps to reproduce the bug.\n      placeholder: |\n        1.\n        2.\n        3.\n  - type: textarea\n    id: possible-solutions\n    attributes:\n      label: Possible Solution(s)\n      description: >\n        Not obligatory, but suggest a fix/reason for the bug,\n        or ideas how to implement the addition or change.\n  - type: textarea\n    id: notes\n    attributes:\n      label: Notes\n      description: Provide any additional notes that might be helpful.\n  - type: textarea\n    id: version\n    attributes:\n      label: Version\n      description: Please paste the output of running `cargo version --verbose`.\n      render: text\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "contact_links:\n  - name: Question\n    url: https://users.rust-lang.org\n    about: >\n      Got a question about Cargo? Ask the community on the user forum.\n  - name: Inspiring Idea\n    url: https://internals.rust-lang.org/c/tools-and-infrastructure/cargo\n    about: >\n      Need more discussions with your next big idea?\n      Reach out the community on the internals forum.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: Feature Request\ndescription: Suggest an idea for enhancing Cargo\nlabels: [\"C-feature-request\", \"S-triage\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for filing a 🙋 feature request 😄!\n\n        If the feature request is relatively small and already with a possible solution, this might be the place for you.\n\n        If you are brewing a big feature that needs feedback from the community, [the internal forum] is the best fit, especially for pre-RFC. You can also talk the idea over with other developers in [#t-cargo Zulip stream].\n\n        [the internal forum]: https://internals.rust-lang.org/c/tools-and-infrastructure/cargo/15\n        [#t-cargo Zulip stream]: https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo\n  - type: textarea\n    id: problem\n    attributes:\n      label: Problem\n      description: >\n        Please provide a clear description of your use case and the problem\n        this feature request is trying to solve.\n    validations:\n      required: true\n  - type: textarea\n    id: solution\n    attributes:\n      label: Proposed Solution\n      description: >\n        Please provide a clear and concise description of what you want to happen.\n  - type: textarea\n    id: notes\n    attributes:\n      label: Notes\n      description: Provide any additional context or information that might be helpful.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/new_lint.yml",
    "content": "name: New lint suggestion\ndescription: Suggest a new Cargo lint.\nlabels: [\"A-new-lint\", \"S-triage\"]\nbody:\n  - type: markdown\n    attributes:\n      value: Thank you for your lint idea!\n  - type: textarea\n    id: what\n    attributes:\n      label: What it does\n      description: What does this lint do?\n    validations:\n      required: true\n  - type: textarea\n    id: advantage\n    attributes:\n      label: Advantage\n      description: >\n        What is the advantage of the recommended code over the original code?\n      placeholder: |\n        - Remove bounds check inserted by ...\n        - Remove the need to duplicate/store ...\n        - Remove typo ...\n  - type: textarea\n    id: drawbacks\n    attributes:\n      label: Drawbacks\n      description: What might be possible drawbacks of such a lint?\n  - type: textarea\n    id: example\n    attributes:\n      label: Example\n      description: >\n        Include a short example showing when the lint should trigger together\n        with the improved code.\n      value: |\n        ```toml\n        <code>\n        ```\n\n        Could be written as:\n\n        ```toml\n        <code>\n        ```\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/tracking_issue.yml",
    "content": "name: Tracking Issue\ndescription: A tracking issue for an accepted feature or RFC in Cargo.\ntitle: \"Tracking Issue for _FEATURE_NAME_\"\nlabels: [\"C-tracking-issue\"]\nbody:\n  - type: markdown\n    attributes:\n      value: >\n        Thank you for creating a tracking issue! Tracking issues are for tracking an\n        accepted feature or RFC from implementation to stabilization. Please do not\n        file a tracking issue until the feature or RFC has been approved.\n  - type: textarea\n    id: summary\n    attributes:\n      label: Summary\n      description: Please provide a very brief summary of the feature.\n      value: |\n        RFC: [#NNNN](https://github.com/rust-lang/rfcs/pull/NNNN) <!-- If this is an RFC -->\n        Original issue: #NNNN <!-- if there is a related issue that spawned this feature -->\n        Implementation: #NNNN <!-- link to the PR that implemented this feature if applicable -->\n        Documentation: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#my-feature\n\n        Please enter a short, one-sentence description here.\n    validations:\n      required: true\n  - type: textarea\n    id: unresolved\n    attributes:\n      label: Unresolved Issues\n      description: List issues that have not yet been resolved.\n      placeholder: |\n        * [ ] Make a list of any known implementation or design issues.\n  - type: textarea\n    id: future\n    attributes:\n      label: Future Extensions\n      description: >\n        An optional section where you can mention where the feature may be\n        extended in the future, but is explicitly not intended to\n        address.\n  - type: textarea\n    id: about\n    attributes:\n      label: About tracking issues\n      description: Please include this notice in the issue.\n      value: |\n        Tracking issues are used to record the overall progress of implementation.\n        They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.\n        A tracking issue is however *not* meant for large scale discussion, questions, or bug reports about a feature.\n        Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "_Thanks for the pull request 🎉!_\n_Please read the contribution guide: <https://doc.crates.io/contrib/>._\n\n### What does this PR try to resolve?\n\n_Explain the motivation behind this change._\n_A clear overview along with an in-depth explanation are helpful._\n\n### How to test and review this PR?\n\n_Demonstrate how you test this change and guide reviewers through your PR._\n_With a smooth review process, a pull request usually gets reviewed quicker._\n"
  },
  {
    "path": ".github/renovate.json5",
    "content": "{\n  schedule: [\n    'before 5am on the first day of the month',\n  ],\n  semanticCommits: 'enabled',\n  configMigration: true,\n  dependencyDashboard: true,\n  ignorePaths: [\n    '**/tests/**',\n  ],\n  // Ignore curl-sys, for now\n  // https://github.com/rust-lang/cargo/issues/16357\n  ignoreDeps: ['curl-sys'],\n  customManagers: [\n    {\n      customType: 'regex',\n      managerFilePatterns: [\n        '/Cargo.toml$/',\n      ],\n      matchStrings: [\n        '\\\\bMSRV:1\\\\b.*?(?<currentValue>\\\\d+\\\\.\\\\d+(\\\\.\\\\d+)?)',\n        '(?<currentValue>\\\\d+\\\\.\\\\d+(\\\\.\\\\d+)?).*?\\\\bMSRV:1\\\\b',\n      ],\n      depNameTemplate: 'MSRV:1',  // Support 1 version of rustc\n      packageNameTemplate: 'rust-lang/rust',\n      datasourceTemplate: 'github-releases',\n    },\n    {\n      customType: 'regex',\n      managerFilePatterns: [\n        '/Cargo.toml$/',\n      ],\n      matchStrings: [\n        '\\\\bMSRV:3\\\\b.*?(?<currentValue>\\\\d+\\\\.\\\\d+(\\\\.\\\\d+)?)',\n        '(?<currentValue>\\\\d+\\\\.\\\\d+(\\\\.\\\\d+)?).*?\\\\bMSRV:3\\\\b',\n      ],\n      depNameTemplate: 'MSRV:3',  // Support 3 versions of rustc\n      packageNameTemplate: 'rust-lang/rust',\n      datasourceTemplate: 'github-releases',\n    },\n    {\n      customType: 'regex',\n      managerFilePatterns: [\n        '/^.github.workflows.main.yml$/',\n      ],\n      matchStrings: [\n        'cargo-semver-checks.releases.download.v(?<currentValue>\\\\d+\\\\.\\\\d+(\\\\.\\\\d+)?)',\n      ],\n      depNameTemplate: 'cargo-semver-checks',\n      packageNameTemplate: 'obi1kenobi/cargo-semver-checks',\n      datasourceTemplate: 'github-releases',\n    },\n  ],\n  packageRules: [\n    {\n      commitMessageTopic: 'MSRV (1 version)',\n      matchManagers: [\n        'custom.regex',\n      ],\n      matchDepNames: [\n        'MSRV:1',\n      ],\n      extractVersion: '^(?<version>\\\\d+\\\\.\\\\d+)',  // Drop the patch version\n      schedule: [\n        '* * * * *',\n      ],\n      groupName: 'msrv',\n    },\n    {\n      commitMessageTopic: 'MSRV (3 versions)',\n      matchManagers: [\n        'custom.regex',\n      ],\n      matchDepNames: [\n        'MSRV:3',\n      ],\n      extractVersion: '^(?<version>\\\\d+\\\\.\\\\d+)',  // Drop the patch version\n      schedule: [\n        '* * * * *',\n      ],\n      minimumReleaseAge: '85 days',  // 2 releases back * 6 weeks per release * 7 days per week + 1\n      internalChecksFilter: 'strict',\n      groupName: 'msrv',\n    },\n    {\n      commitMessageTopic: 'cargo-semver-checks',\n      matchManagers: [\n        'custom.regex',\n      ],\n      matchDepNames: [\n        'cargo-semver-checks',\n      ],\n      extractVersion: '^v(?<version>\\\\d+\\\\.\\\\d+\\\\.\\\\d+)',\n      schedule: [\n        '* * * * *',\n      ],\n      internalChecksFilter: 'strict',\n    },\n    // Goals:\n    // - Rollup safe upgrades to reduce CI runner load\n    // - Have lockfile and manifest in-sync (implicit rules)\n    {\n      matchManagers: [\n        'cargo',\n      ],\n      matchCurrentVersion: '>=0.1.0',\n      matchUpdateTypes: [\n        'patch',\n      ],\n      automerge: false,\n      groupName: 'compatible',\n    },\n    {\n      matchManagers: [\n        'cargo',\n      ],\n      matchCurrentVersion: '>=1.0.0',\n      matchUpdateTypes: [\n        'minor',\n      ],\n      automerge: false,\n      groupName: 'compatible',\n    },\n  ],\n}\n"
  },
  {
    "path": ".github/workflows/audit.yml",
    "content": "name: Security audit\n\npermissions:\n  contents: read\n\non:\n  pull_request:\n    paths:\n      - '**/Cargo.toml'\n      - '**/Cargo.lock'\n  push:\n    branches:\n    - master\n\njobs:\n  cargo_deny:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        checks:\n          - advisories\n          - bans licenses sources\n    steps:\n    - uses: actions/checkout@v5\n    - uses: EmbarkStudios/cargo-deny-action@v2\n      # Prevent sudden announcement of a new advisory from failing ci:\n      continue-on-error: ${{ matrix.checks == 'advisories' }}\n      with:\n        command: check ${{ matrix.checks }}\n        rust-version: stable\n"
  },
  {
    "path": ".github/workflows/contrib.yml",
    "content": "name: Contrib Deploy\non:\n  push:\n    branches:\n      - master\n\nconcurrency:\n  cancel-in-progress: false\n  group: \"gh-pages\"\n\npermissions:\n  contents: read\n\nenv:\n  MDBOOK_VERSION: 0.5.1\n\njobs:\n  deploy:\n    permissions:\n      contents: write  # for Git to git push\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v5\n      with:\n        fetch-depth: 0\n    - name: Install mdbook\n      run: |\n        mkdir mdbook\n        curl -Lf https://github.com/rust-lang/mdBook/releases/download/v${MDBOOK_VERSION}/mdbook-v${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook\n        echo `pwd`/mdbook >> $GITHUB_PATH\n    - name: Deploy docs\n      run: |\n        GENERATE_PY=\"$(pwd)/ci/generate.py\"\n\n        cd src/doc/contrib\n        mdbook build\n\n        # Override previous ref to avoid keeping history.\n        git worktree add --orphan -B gh-pages gh-pages\n        git config user.name \"Deploy from CI\"\n        git config user.email \"\"\n        cd gh-pages\n        mv ../book contrib\n        git add contrib\n\n        # Generate HTML for link redirections.\n        python3 \"$GENERATE_PY\"\n        git add *.html\n        # WARN: The CNAME file is for GitHub to redirect requests to the custom domain.\n        # Missing this may entail security hazard and domain takeover.\n        # See <https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/managing-a-custom-domain-for-your-github-pages-site#securing-your-custom-domain>\n        git add CNAME\n\n        git commit -m \"Deploy $GITHUB_SHA to gh-pages\"\n        git push origin +gh-pages\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: CI\non:\n  merge_group:\n  pull_request:\n    branches:\n      - \"**\"\n\ndefaults:\n  run:\n    shell: bash\n\npermissions:\n  contents: read\n\nconcurrency:\n  group: \"${{ github.workflow }}-${{ github.ref }}\"\n  cancel-in-progress: true\n\nenv:\n  MDBOOK_VERSION: 0.5.1\n\njobs:\n  conclusion:\n    needs:\n      - build_std\n      - clippy\n      - msrv\n      - docs\n      - lint-docs\n      - lockfile\n      - resolver\n      - report-timings\n      - rustfmt\n      - schema\n      - spellcheck\n      - test\n      - test_gitoxide\n    permissions:\n      contents: none\n    # We need to ensure this job does *not* get skipped if its dependencies fail,\n    # because a skipped job is considered a success by GitHub. So we have to\n    # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run\n    # when the workflow is canceled manually.\n    #\n    # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!\n    if: ${{ !cancelled() }}\n    runs-on: ubuntu-latest\n    steps:\n      # Manually check the status of all dependencies. `if: failure()` does not work.\n      - name: Conclusion\n        run: |\n          # Print the dependent jobs to see them in the CI log\n          jq -C <<< '${{ toJson(needs) }}'\n          # Check if all jobs that we depend on (in the needs array) were successful.\n          jq --exit-status 'all(.result == \"success\")' <<< '${{ toJson(needs) }}'\n\n  # Check Code style quickly by running `rustfmt` over all code\n  rustfmt:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v5\n    - run: rustup update stable && rustup default stable\n    - run: rustup component add rustfmt\n    - run: cargo fmt --all --check\n\n  # Ensure there are no clippy warnings\n  clippy:\n    strategy:\n      matrix:\n        include:\n        - name: Linux x86_64\n          os: ubuntu-latest\n        - name: macOS aarch64\n          os: macos-14\n        - name: Windows x86_64 MSVC\n          os: windows-latest\n    name: Clippy ${{ matrix.name }}\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v5\n      - run: rustup update stable && rustup default stable\n      - run: rustup component add clippy\n      - run: cargo clippy --workspace --all-targets --no-deps -- -D warnings\n\n  stale-label:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v5\n      - run: rustup update stable && rustup default stable\n      - run: cargo stale-label\n\n  lint-docs:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v5\n      - run: rustup update stable && rustup default stable\n      - run: cargo lint-docs --check\n\n  # Ensure Cargo.lock is up-to-date\n  lockfile:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v5\n      - run: rustup update stable && rustup default stable\n      - run: cargo update -p cargo --locked\n\n  check-version-bump:\n    runs-on: ubuntu-latest\n    if: github.repository_owner == 'rust-lang'\n    env:\n      BASE_SHA: ${{ github.event.pull_request.base.sha }}\n      HEAD_SHA: ${{ github.event.pull_request.head.sha != '' && github.event.pull_request.head.sha || github.sha  }}\n    steps:\n      - uses: actions/checkout@v5\n        with:\n          fetch-depth: 0\n      - run: rustup update stable && rustup default stable\n      - name: Install cargo-semver-checks\n        run: |\n          mkdir installed-bins\n          curl -Lf https://github.com/obi1kenobi/cargo-semver-checks/releases/download/v0.47.0/cargo-semver-checks-x86_64-unknown-linux-gnu.tar.gz \\\n            | tar -xz --directory=./installed-bins\n          echo `pwd`/installed-bins >> $GITHUB_PATH\n      - run: ci/validate-version-bump.sh\n\n  test:\n    runs-on: ${{ matrix.os }}\n    env:\n      CARGO_PROFILE_DEV_DEBUG: 1\n      CARGO_PROFILE_TEST_DEBUG: 1\n      CARGO_INCREMENTAL: 0\n      CARGO_PUBLIC_NETWORK_TESTS: 1\n      # Workaround for https://github.com/rust-lang/rustup/issues/3036\n      RUSTUP_WINDOWS_PATH_ADD_BIN: 0\n    strategy:\n      matrix:\n        include:\n        - name: Linux x86_64 stable\n          os: ubuntu-latest\n          rust: stable\n          other: i686-unknown-linux-gnu\n        - name: Linux x86_64 beta\n          os: ubuntu-latest\n          rust: beta\n          other: i686-unknown-linux-gnu\n        - name: Linux x86_64 nightly\n          os: ubuntu-latest\n          rust: nightly\n          other: i686-unknown-linux-gnu\n        - name: Linux aarch64 stable\n          os: ubuntu-24.04-arm\n          rust: stable\n          other: TODO # cross-compile tests are disabled, this shouldn't matter.\n        - name: Linux aarch64 nightly\n          os: ubuntu-24.04-arm\n          rust: nightly\n          other: TODO # cross-compile tests are disabled, this shouldn't matter.\n        - name: macOS aarch64 stable\n          os: macos-14\n          rust: stable\n          other: x86_64-apple-darwin\n        - name: macOS aarch64 nightly\n          os: macos-14\n          rust: nightly\n          other: x86_64-apple-darwin\n        - name: Windows x86_64 MSVC stable\n          os: windows-latest\n          rust: stable-msvc\n          other: i686-pc-windows-msvc\n        - name: Windows x86_64 MSVC nightly\n          os: windows-latest\n          rust: nightly-msvc\n          other: i686-pc-windows-msvc\n        - name: Windows aarch64 MSVC stable\n          os: windows-11-arm\n          rust: stable-msvc\n          other: i686-pc-windows-msvc\n        - name: Windows aarch64 MSVC nightly\n          os: windows-11-arm\n          rust: nightly-msvc\n          other: i686-pc-windows-msvc\n        - name: Windows x86_64 gnu nightly # runs out of space while trying to link the test suite\n          os: windows-latest\n          rust: nightly-gnu\n          other: i686-pc-windows-gnu\n    name: Tests ${{ matrix.name }}\n    steps:\n    - uses: actions/checkout@v5\n    - name: Dump Environment\n      run: ci/dump-environment.sh\n    # Some tests require stable. Make sure it is set to the most recent stable\n    # so that we can predictably handle updates if necessary (and not randomly\n    # when GitHub updates its image).\n    - run: rustup update --no-self-update stable\n    - run: rustup update --no-self-update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}\n    - run: rustup target add ${{ matrix.other }}\n      if: matrix.os != 'ubuntu-24.04-arm' # cross-compile tests are disabled on ARM machines\n    - run: rustup target add wasm32-unknown-unknown\n    - run: rustup target add aarch64-unknown-none # need this for build-std mock tests\n      if: startsWith(matrix.rust, 'nightly')\n    - run: rustup component add rustc-dev llvm-tools-preview rust-docs\n      if: startsWith(matrix.rust, 'nightly')\n    - run: sudo apt update -y && sudo apt install lldb gcc-multilib libsecret-1-0 libsecret-1-dev -y\n      if: matrix.os == 'ubuntu-latest'\n    - run: rustup component add rustfmt || echo \"rustfmt not available\"\n    - name: Add Windows debuggers bin to PATH\n      shell: pwsh\n      run: Add-Content $env:GITHUB_PATH \"C:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\x64\"\n      if: matrix.os == 'windows-latest'\n    - name: Add Windows debuggers bin to PATH\n      shell: pwsh\n      run: Add-Content $env:GITHUB_PATH \"C:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\arm64\"\n      if: matrix.os == 'windows-11-arm'\n    - name: Configure extra test environment\n      run: echo CARGO_CONTAINER_TESTS=1 >> $GITHUB_ENV\n      if: matrix.os == 'ubuntu-latest'\n    - run: cargo test -p cargo\n    - name: Clear intermediate test output\n      run: ci/clean-test-output.sh\n\n    - name: gitoxide tests (all git-related tests)\n      run: cargo test -p cargo git\n      env:\n        __CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2: 1\n      # The testsuite generates a huge amount of data, and fetch-smoke-test was\n    # running out of disk space.\n    - name: Clear test output\n      run: ci/clean-test-output.sh\n\n    # This only tests `cargo fix` because fix-proxy-mode is one of the most\n    # complicated subprocess management in Cargo.\n    - name: Check operability of rustc invocation with argfile\n      run: 'cargo test -p cargo --test testsuite -- fix::'\n      env:\n        __CARGO_TEST_FORCE_ARGFILE: 1\n    - run: cargo test --workspace --exclude cargo --exclude benchsuite --exclude resolver-tests\n    - name: Check benchmarks\n      run: |\n        # This only tests one benchmark since it can take over 10 minutes to\n        # download all workspaces.\n        cargo test -p benchsuite --all-targets -- cargo\n        cargo check -p capture\n    # The testsuite generates a huge amount of data, and fetch-smoke-test was\n    # running out of disk space.\n    - name: Clear benchmark output\n      run: ci/clean-test-output.sh\n\n    - name: Fetch smoke test\n      run: ci/fetch-smoke-test.sh\n\n  schema:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v5\n    - run: rustup update stable && rustup default stable\n    - run: cargo test -p cargo-util-schemas -F unstable-schema\n\n  resolver:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v5\n    - run: rustup update stable && rustup default stable\n    - run: cargo test -p resolver-tests\n\n  test_gitoxide:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v5\n      - run: rustup update --no-self-update stable && rustup default stable\n      - run: rustup target add i686-unknown-linux-gnu\n      - run: rustup target add wasm32-unknown-unknown\n      - run: sudo apt update -y && sudo apt install gcc-multilib libsecret-1-0 libsecret-1-dev -y\n      - run: rustup component add rustfmt || echo \"rustfmt not available\"\n      - run: cargo test -p cargo\n        env:\n          __CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2: 1\n\n  build_std:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v5\n    - run: rustup update nightly && rustup default nightly\n    - run: rustup component add rust-src\n    - run: cargo build\n    - run: cargo test -p cargo --test build-std\n      env:\n        CARGO_RUN_BUILD_STD_TESTS: 1\n  docs:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v5\n    - run: rustup update nightly && rustup default nightly\n    - run: rustup update stable\n    - run: rustup component add rust-docs\n    - run: rustup component add rustfmt --toolchain stable\n    - run: ci/validate-man.sh\n    # This requires rustfmt, use stable.\n    - name: Run semver-check\n      run: cargo +stable run -p semver-check\n    - name: Ensure intradoc links are valid\n      run: cargo doc --workspace --document-private-items --no-deps\n      env:\n        RUSTDOCFLAGS: -D warnings\n    - name: Install mdbook\n      run: |\n        mkdir mdbook\n        curl -Lf https://github.com/rust-lang/mdBook/releases/download/v${MDBOOK_VERSION}/mdbook-v${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook\n        echo `pwd`/mdbook >> $GITHUB_PATH\n    - run: cd src/doc && mdbook build --dest-dir ../../target/doc\n    - name: Run linkchecker.sh\n      run: |\n        cd target\n        curl -sSLO https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh\n        sh linkcheck.sh --all --path ../src/doc cargo\n\n  msrv:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v5\n    - uses: taiki-e/install-action@cargo-hack\n    - run: cargo hack check --all-targets --rust-version --workspace --ignore-private --locked\n\n  spellcheck:\n    name: Spell Check with Typos\n    runs-on: ubuntu-latest\n    steps:\n    - name: Checkout Actions Repository\n      uses: actions/checkout@v5\n    - name: Spell Check Repo\n      uses: crate-ci/typos@v1.44.0\n\n  report-timings:\n    name: Timing HTML report\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v5\n    - run: rustup update nightly && rustup default nightly\n    - run: cargo build\n    - name: Generate timing report for rustfix\n      run: |\n        cargo run -- build -p rustfix -Zbuild-analysis -Zsection-timings --config build.analysis.enabled=true --config 'build.build-dir=\"tmp\"'\n        cargo run -- report timings -Zbuild-analysis\n    - uses: actions/upload-artifact@v6\n      with:\n        name: timing-report\n        path: target/cargo-timings/*.html\n        if-no-files-found: error\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "# Publish Cargo to crates.io whenever a new tag is pushed. Tags are pushed by\n# the Rust release process (https://github.com/rust-lang/promote-release),\n# which will cause this workflow to run.\n\nname: Release\non:\n  push:\n    tags:\n      - \"0.*\"\n\n# Prevent multiple releases from starting at the same time.\nconcurrency:\n  group: release\n\njobs:\n  crates-io:\n    name: Publish on crates.io\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n\n    # Gain access to the crates.io publishing token.\n    environment:\n      name: release\n\n    steps:\n      - name: Checkout the source code\n        uses: actions/checkout@v5\n\n      - name: Publish Cargo to crates.io\n        run: ./publish.py\n        env:\n          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "/target\n/Cargo.lock\n/config.stamp\n/Makefile\n/config.mk\n/src/doc/build\n/src/etc/*.pyc\n/src/registry/target\nrustc\n__pycache__\n.idea/\n.vscode/\n*.iml\n*.swp\n"
  },
  {
    "path": ".ignore",
    "content": "# Output generated from src/doc/man\n#\n# The goal is to help people find the right file to edit\nsrc/doc/man/generated_txt\nsrc/doc/src/commands/*\nsrc/etc/man\n!src/doc/src/commands/build-commands.md\n!src/doc/src/commands/cargo-clippy.md\n!src/doc/src/commands/cargo-fmt.md\n!src/doc/src/commands/cargo-miri.md\n!src/doc/src/commands/general-commands.md\n!src/doc/src/commands/index.md\n!src/doc/src/commands/manifest-commands.md\n!src/doc/src/commands/package-commands.md\n!src/doc/src/commands/publishing-commands.md\n!src/doc/src/commands/report-commands.md\n\n# Snapshots of HTML reports and log files are just too large\ntests/testsuite/**/*.jsonl\ntests/testsuite/**/*.html\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nThe changelog has moved to the [Cargo Book](https://doc.rust-lang.org/nightly/cargo/CHANGELOG.html).\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# The Rust Code of Conduct\n\nThe Code of Conduct for this repository [can be found online](https://www.rust-lang.org/conduct.html).\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Cargo\n\nContributing documentation has moved to the **[Cargo Contributor Guide]**.\n\n[Cargo Contributor Guide]: https://rust-lang.github.io/cargo/contrib/\n\n## Before hacking on Cargo\n\nWe encourage people to discuss their design before hacking on code. Typically,\nyou [file an issue] or start a thread on the [internals forum] before submitting\na pull request.\n\nPlease read [the process] of how features and bugs are managed in Cargo.\n**Only issues that have been explicitly marked as [accepted] will be reviewed.**\n\n[internals forum]: https://internals.rust-lang.org/c/tools-and-infrastructure/cargo\n[file an issue]: https://github.com/rust-lang/cargo/issues\n[the process]: https://doc.crates.io/contrib/process/index.html\n[accepted]: https://github.com/rust-lang/cargo/issues?q=is%3Aissue+is%3Aopen+label%3AS-accepted\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\n  \"crates/*\",\n  \"credential/*\",\n  \"benches/benchsuite\",\n  \"benches/capture\",\n]\nexclude = [\n  \"target/\", # exclude bench testing\n]\n\n[workspace.package]\nrust-version = \"1.92\"  # MSRV:3\nedition = \"2024\"\nlicense = \"MIT OR Apache-2.0\"\nrepository = \"https://github.com/rust-lang/cargo\"\n\n[workspace.dependencies]\nannotate-snippets = { version = \"0.12.12\", features = [\"simd\"] }\nanstream = \"1.0.0\"\nanstyle = \"1.0.13\"\nanstyle-hyperlink = \"1.0.1\"\nanstyle-progress = \"0.1.0\"\nanyhow = \"1.0.102\"\nbase64 = \"0.22.1\"\nblake3 = \"1.8.3\"\nbuild-rs = { version = \"0.3.4\", path = \"crates/build-rs\" }\ncargo = { path = \"\" }\ncargo-credential = { version = \"0.4.10\", path = \"credential/cargo-credential\" }\ncargo-credential-libsecret = { version = \"0.5.6\", path = \"credential/cargo-credential-libsecret\" }\ncargo-credential-macos-keychain = { version = \"0.4.21\", path = \"credential/cargo-credential-macos-keychain\" }\ncargo-credential-wincred = { version = \"0.4.21\", path = \"credential/cargo-credential-wincred\" }\ncargo-platform = { path = \"crates/cargo-platform\", version = \"0.3.3\" }\ncargo-test-macro = { version = \"0.4.10\", path = \"crates/cargo-test-macro\" }\ncargo-test-support = { version = \"0.11.0\", path = \"crates/cargo-test-support\" }\ncargo-util = { version = \"0.2.28\", path = \"crates/cargo-util\" }\ncargo-util-schemas = { version = \"0.13.0\", path = \"crates/cargo-util-schemas\" }\ncargo_metadata = \"0.23.1\"\nclap = \"4.5.60\"\nclap_complete = { version = \"4.5.66\", features = [\"unstable-dynamic\"] }\ncolor-print = \"0.3.7\"\ncore-foundation = { version = \"0.10.1\", features = [\"mac_os_10_7_support\"] }\ncrates-io = { version = \"0.40.18\", path = \"crates/crates-io\" }\ncriterion = { version = \"0.8.2\", features = [\"html_reports\"] }\ncurl = \"0.4.49\"\n# Do not upgrade curl-sys past 0.4.83\n# https://github.com/rust-lang/cargo/issues/16357\ncurl-sys = \"=0.4.83\"\nfiletime = \"0.2.27\"\nflate2 = { version = \"1.1.9\", default-features = false, features = [\"zlib-rs\"] }\ngit2 = \"0.20.4\"\ngit2-curl = \"0.21.0\"\n# When updating this, also see if `gix-transport` further down needs updating or some auth-related tests will fail.\ngix = { version = \"0.80.0\", default-features = false, features = [\"progress-tree\", \"parallel\", \"dirwalk\", \"status\"] }\ngix-transport = \"0.55.0\"\nglob = \"0.3.3\"\nhandlebars = { version = \"6.4.0\", features = [\"dir_source\"] }\nheck = \"0.5.0\"\nhex = \"0.4.3\"\nhmac = \"0.12.1\"\nhome = \"0.5.12\"\nhttp-auth = { version = \"0.1.10\", default-features = false }\nignore = \"0.4.25\"\nim-rc = \"15.1.0\"\nindexmap = \"2.13.0\"\nitertools = \"0.14.0\"\njiff = { version = \"0.2.22\", default-features = false, features = [ \"std\" ] }\njobserver = \"0.1.34\"\nlibc = \"0.2.180\"\nlibgit2-sys = \"0.18.3\"\nlibloading = \"0.9.0\"\nmemchr = \"2.8.0\"\nmemfd = \"0.6.5\"\nmiow = \"0.6.1\"\nopener = \"0.8.4\"\nopenssl = \"0.10.75\"\n# Pinned due to ppc64 ELFv1/v2 ABI issue in 3.5.5\n# https://github.com/openssl/openssl/issues/29815\nopenssl-src = \"=300.5.4\"\nos_info = { version = \"3.14.0\", default-features = false }\npasetors = { version = \"0.7.8\", features = [\"v3\", \"paserk\", \"std\", \"serde\"] }\npathdiff = \"0.2.3\"\npercent-encoding = \"2.3.2\"\nproptest = \"1.10.0\"\npulldown-cmark = { version = \"0.13.1\", default-features = false, features = [\"html\"] }\nrand = \"0.10.0\"\nregex = \"1.12.3\"\nrusqlite = { version = \"0.38.0\", features = [\"bundled\"] }\nrustc-hash = \"2.1.1\"\nrustc-stable-hash = \"0.1.2\"\nrustfix = { version = \"0.9.5\", path = \"crates/rustfix\" }\nsame-file = \"1.0.6\"\nschemars = \"1.2.1\"\nsecurity-framework = \"3.7.0\"\nsemver = { version = \"1.0.27\", features = [\"serde\"] }\nserde = \"1.0.228\"\nserde_core = \"1.0.228\"\nserde-untagged = \"0.1.9\"\nserde-value = \"0.7.0\"\nserde_ignored = \"0.1.14\"\nserde_json = \"1.0.149\"\nsha1 = \"0.10.6\"\nsha2 = \"0.10.9\"\nshell-escape = \"0.1.5\"\nsimilar = \"2.7.0\"\nsupports-hyperlinks = \"3.2.0\"\nsupports-unicode = \"3.0.0\"\nsnapbox = { version = \"1.0.0\", features = [\"diff\", \"dir\", \"term-svg\", \"regex\", \"json\"] }\ntar = { version = \"0.4.45\", default-features = false }\ntempfile = \"3.25.0\"\nthiserror = \"2.0.18\"\ntime = { version = \"0.3.47\", features = [\"parsing\", \"formatting\", \"serde\"] }\ntoml = { version = \"1.0.3\", default-features = false }\ntoml_edit = { version = \"0.25.3\", features = [\"serde\"] }\ntracing = { version = \"0.1.44\", default-features = false, features = [\"std\"] } # be compatible with rustc_log: https://github.com/rust-lang/rust/blob/e51e98dde6a/compiler/rustc_log/Cargo.toml#L9\ntracing-chrome = \"0.7.2\"\ntracing-subscriber = { version = \"0.3.22\", features = [\"env-filter\"] }\nunicase = \"2.9.0\"\nunicode-ident = \"1.0.24\"\nunicode-width = \"0.2.2\"\nurl = \"2.5.8\"\nvarisat = \"0.2.2\"\nwalkdir = \"2.5.0\"\nwindows-sys = \"0.61\"\nwinnow = \"0.7.14\"\n\n[workspace.lints.rust]\nrust_2018_idioms = \"warn\" # TODO: could this be removed?\n\n[workspace.lints.rustdoc]\nprivate_intra_doc_links = \"allow\"\n\n[workspace.lints.clippy]\nall = { level = \"allow\", priority = -2 }\ncorrectness = { level = \"warn\", priority = -1 }\ndbg_macro = \"warn\"\ndisallowed_methods = \"warn\"\nprint_stderr = \"warn\"\nprint_stdout = \"warn\"\nself_named_module_files = \"warn\"\n\n[package]\nname = \"cargo\"\nversion = \"0.97.0\"\nedition.workspace = true\nlicense.workspace = true\nrust-version = \"1.94\"  # MSRV:1\nhomepage = \"https://doc.rust-lang.org/cargo/index.html\"\nrepository.workspace = true\ndocumentation = \"https://docs.rs/cargo\"\ndescription = \"\"\"\nCargo, a package manager for Rust.\n\"\"\"\n\n[lib]\nname = \"cargo\"\npath = \"src/cargo/lib.rs\"\n\n[dependencies]\nannotate-snippets.workspace = true\nanstream.workspace = true\nanstyle.workspace = true\nanstyle-hyperlink = { workspace = true, features = [\"file\"] }\nanstyle-progress.workspace = true\nanyhow.workspace = true\nbase64.workspace = true\nblake3.workspace = true\ncargo-credential.workspace = true\ncargo-platform.workspace = true\ncargo-util-schemas.workspace = true\ncargo-util.workspace = true\nclap = { workspace = true, features = [\"wrap_help\"] }\nclap_complete.workspace = true\ncolor-print.workspace = true\ncrates-io.workspace = true\ncurl = { workspace = true, features = [\"http2\"] }\ncurl-sys.workspace = true\nfiletime.workspace = true\nflate2.workspace = true\ngit2.workspace = true\ngit2-curl.workspace = true\ngix.workspace = true\nglob.workspace = true\nheck.workspace = true\nhex.workspace = true\nhmac.workspace = true\nhome.workspace = true\nhttp-auth.workspace = true\nignore.workspace = true\nim-rc.workspace = true\nindexmap.workspace = true\nitertools.workspace = true\njiff = { workspace = true, features = [\"serde\", \"std\"] }\njobserver.workspace = true\nlibgit2-sys.workspace = true\nmemchr.workspace = true\nopener.workspace = true\nos_info.workspace = true\npasetors.workspace = true\npathdiff.workspace = true\nrand.workspace = true\nregex.workspace = true\nrusqlite = { workspace = true, features = [\"fallible_uint\"] }\nrustc-hash.workspace = true\nrustc-stable-hash.workspace = true\nrustfix.workspace = true\nsame-file.workspace = true\nsemver.workspace = true\nserde = { workspace = true, features = [\"derive\"] }\nserde-untagged.workspace = true\nserde_ignored.workspace = true\nserde_json = { workspace = true, features = [\"raw_value\"] }\nsha1.workspace = true\nshell-escape.workspace = true\nsupports-hyperlinks.workspace = true\nsupports-unicode.workspace = true\ntar.workspace = true\ntempfile.workspace = true\nthiserror.workspace = true\ntime.workspace = true\ntoml = { workspace = true, features = [\"std\", \"serde\", \"parse\", \"display\", \"preserve_order\"] }\ntoml_edit.workspace = true\ntracing = { workspace = true, features = [\"attributes\"] }\ntracing-subscriber.workspace = true\nunicase.workspace = true\nunicode-width.workspace = true\nunicode-ident.workspace = true\nurl.workspace = true\nwalkdir.workspace = true\nwinnow.workspace = true\n\n[target.'cfg(target_has_atomic = \"64\")'.dependencies]\ntracing-chrome.workspace = true\n\n[target.'cfg(unix)'.dependencies]\nlibc.workspace = true\n\n[target.'cfg(target_os = \"linux\")'.dependencies]\ncargo-credential-libsecret.workspace = true\n\n[target.'cfg(target_os = \"macos\")'.dependencies]\ncargo-credential-macos-keychain.workspace = true\n\n[target.'cfg(not(windows))'.dependencies]\nopenssl = { workspace = true, optional = true }\nopenssl-src = { workspace = true, optional = true }\n\n[target.'cfg(windows)'.dependencies]\ncargo-credential-wincred.workspace = true\n\n[target.'cfg(windows)'.dependencies.windows-sys]\nworkspace = true\nfeatures = [\n  \"Win32_Foundation\",\n  \"Win32_Security\",\n  \"Win32_Storage_FileSystem\",\n  \"Win32_System_IO\",\n  \"Win32_System_Console\",\n  \"Win32_System_JobObjects\",\n  \"Win32_System_Threading\",\n]\n\n[dev-dependencies]\nannotate-snippets = { workspace = true, features = [\"testing-colors\"] }\ncargo-test-support.workspace = true\ngix = { workspace = true, features = [\"revision\"] }\n# When building Cargo for tests, a safety-measure in `gix` needs to be disabled\n# to allow sending credentials over HTTP connections.\ngix-transport = { workspace = true, features = [\"http-client-insecure-credentials\"] }\nsame-file.workspace = true\nsnapbox.workspace = true\n\n[target.'cfg(target_os = \"linux\")'.dev-dependencies]\nmemfd.workspace = true\n\n[build-dependencies]\nflate2.workspace = true\ntar.workspace = true\n\n[[bin]]\nname = \"cargo\"\ntest = false\ndoc = false\n\n[features]\ndefault = [\"http-transport-curl\"]\nvendored-openssl = [\"openssl/vendored\"]\nvendored-libgit2 = [\"libgit2-sys/vendored\"]\n# This is primarily used by rust-lang/rust distributing cargo the executable.\nall-static = ['vendored-openssl', 'curl/static-curl', 'curl/force-system-lib-on-osx', 'vendored-libgit2']\n# Exactly one of 'http-transport-curl' or 'http-transport-reqwest' must be enabled\n# when using Cargo as a library. By default, it is 'http-transport-curl'.\nhttp-transport-curl = [\"gix/blocking-http-transport-curl\"]\nhttp-transport-reqwest = [\"gix/blocking-http-transport-reqwest\"]\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     https://www.apache.org/licenses/LICENSE-2.0\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n   To apply the Apache License to your work, attach the following\n   boilerplate notice, with the fields enclosed by brackets \"[]\"\n   replaced with your own identifying information. (Don't include\n   the brackets!)  The text should be enclosed in the appropriate\n   comment syntax for the file format. We also recommend that a\n   file or class name and description of purpose be included on the\n   same \"printed page\" as the copyright notice for easier\n   identification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttps://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "Permission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "LICENSE-THIRD-PARTY",
    "content": "The Cargo source code itself does not bundle any third party libraries, but it\ndepends on a number of libraries which carry their own copyright notices and\nlicense terms. These libraries are normally all linked static into the binary\ndistributions of Cargo:\n\n* OpenSSL - https://www.openssl.org/source/license.html\n\n    Copyright (c) 1998-2011 The OpenSSL Project.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n    1. Redistributions of source code must retain the above copyright\n       notice, this list of conditions and the following disclaimer.\n\n    2. Redistributions in binary form must reproduce the above copyright\n       notice, this list of conditions and the following disclaimer in\n       the documentation and/or other materials provided with the\n       distribution.\n\n    3. All advertising materials mentioning features or use of this\n       software must display the following acknowledgment:\n       \"This product includes software developed by the OpenSSL Project\n       for use in the OpenSSL Toolkit. (https://www.openssl.org/)\"\n\n    4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n       endorse or promote products derived from this software without\n       prior written permission. For written permission, please contact\n       openssl-core@openssl.org.\n\n    5. Products derived from this software may not be called \"OpenSSL\"\n       nor may \"OpenSSL\" appear in their names without prior written\n       permission of the OpenSSL Project.\n\n    6. Redistributions of any form whatsoever must retain the following\n       acknowledgment:\n       \"This product includes software developed by the OpenSSL Project\n       for use in the OpenSSL Toolkit (https://www.openssl.org/)\"\n\n    THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n    EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n    ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n    OF THE POSSIBILITY OF SUCH DAMAGE.\n    ====================================================================\n\n    This product includes cryptographic software written by Eric Young\n    (eay@cryptsoft.com).  This product includes software written by Tim\n    Hudson (tjh@cryptsoft.com).\n\n    ---\n\n    Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n    All rights reserved.\n\n    This package is an SSL implementation written\n    by Eric Young (eay@cryptsoft.com).\n    The implementation was written so as to conform with Netscapes SSL.\n\n    This library is free for commercial and non-commercial use as long as\n    the following conditions are aheared to.  The following conditions\n    apply to all code found in this distribution, be it the RC4, RSA,\n    lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n    included with this distribution is covered by the same copyright terms\n    except that the holder is Tim Hudson (tjh@cryptsoft.com).\n\n    Copyright remains Eric Young's, and as such any Copyright notices in\n    the code are not to be removed.\n    If this package is used in a product, Eric Young should be given attribution\n    as the author of the parts of the library used.\n    This can be in the form of a textual message at program startup or\n    in documentation (online or textual) provided with the package.\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n    1. Redistributions of source code must retain the copyright\n       notice, this list of conditions and the following disclaimer.\n    2. Redistributions in binary form must reproduce the above copyright\n       notice, this list of conditions and the following disclaimer in the\n       documentation and/or other materials provided with the distribution.\n    3. All advertising materials mentioning features or use of this software\n       must display the following acknowledgement:\n       \"This product includes cryptographic software written by\n        Eric Young (eay@cryptsoft.com)\"\n       The word 'cryptographic' can be left out if the rouines from the library\n       being used are not cryptographic related :-).\n    4. If you include any Windows specific code (or a derivative thereof) from\n       the apps directory (application code) you must include an acknowledgement:\n       \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n\n    THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n    The licence and distribution terms for any publically available version or\n    derivative of this code cannot be changed.  i.e. this code cannot simply be\n    copied and put under another distribution licence\n    [including the GNU Public Licence.]\n\n* libgit2 - https://github.com/libgit2/libgit2/blob/master/COPYING\n\n     libgit2 is Copyright (C) the libgit2 contributors,\n     unless otherwise stated. See the AUTHORS file for details.\n\n     Note that the only valid version of the GPL as far as this project\n     is concerned is _this_ particular version of the license (ie v2, not\n     v2.2 or v3.x or whatever), unless explicitly otherwise stated.\n\n    ----------------------------------------------------------------------\n\n          LINKING EXCEPTION\n\n     In addition to the permissions in the GNU General Public License,\n     the authors give you unlimited permission to link the compiled\n     version of this library into combinations with other programs,\n     and to distribute those combinations without any restriction\n     coming from the use of this file.  (The General Public License\n     restrictions do apply in other respects; for example, they cover\n     modification of the file, and distribution when not linked into\n     a combined executable.)\n\n    ----------------------------------------------------------------------\n\n            GNU GENERAL PUBLIC LICENSE\n               Version 2, June 1991\n\n     Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n                           59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n     Everyone is permitted to copy and distribute verbatim copies\n     of this license document, but changing it is not allowed.\n\n              Preamble\n\n      The licenses for most software are designed to take away your\n    freedom to share and change it.  By contrast, the GNU General Public\n    License is intended to guarantee your freedom to share and change free\n    software--to make sure the software is free for all its users.  This\n    General Public License applies to most of the Free Software\n    Foundation's software and to any other program whose authors commit to\n    using it.  (Some other Free Software Foundation software is covered by\n    the GNU Library General Public License instead.)  You can apply it to\n    your programs, too.\n\n      When we speak of free software, we are referring to freedom, not\n    price.  Our General Public Licenses are designed to make sure that you\n    have the freedom to distribute copies of free software (and charge for\n    this service if you wish), that you receive source code or can get it\n    if you want it, that you can change the software or use pieces of it\n    in new free programs; and that you know you can do these things.\n\n      To protect your rights, we need to make restrictions that forbid\n    anyone to deny you these rights or to ask you to surrender the rights.\n    These restrictions translate to certain responsibilities for you if you\n    distribute copies of the software, or if you modify it.\n\n      For example, if you distribute copies of such a program, whether\n    gratis or for a fee, you must give the recipients all the rights that\n    you have.  You must make sure that they, too, receive or can get the\n    source code.  And you must show them these terms so they know their\n    rights.\n\n      We protect your rights with two steps: (1) copyright the software, and\n    (2) offer you this license which gives you legal permission to copy,\n    distribute and/or modify the software.\n\n      Also, for each author's protection and ours, we want to make certain\n    that everyone understands that there is no warranty for this free\n    software.  If the software is modified by someone else and passed on, we\n    want its recipients to know that what they have is not the original, so\n    that any problems introduced by others will not reflect on the original\n    authors' reputations.\n\n      Finally, any free program is threatened constantly by software\n    patents.  We wish to avoid the danger that redistributors of a free\n    program will individually obtain patent licenses, in effect making the\n    program proprietary.  To prevent this, we have made it clear that any\n    patent must be licensed for everyone's free use or not licensed at all.\n\n      The precise terms and conditions for copying, distribution and\n    modification follow.\n\n            GNU GENERAL PUBLIC LICENSE\n       TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n      0. This License applies to any program or other work which contains\n    a notice placed by the copyright holder saying it may be distributed\n    under the terms of this General Public License.  The \"Program\", below,\n    refers to any such program or work, and a \"work based on the Program\"\n    means either the Program or any derivative work under copyright law:\n    that is to say, a work containing the Program or a portion of it,\n    either verbatim or with modifications and/or translated into another\n    language.  (Hereinafter, translation is included without limitation in\n    the term \"modification\".)  Each licensee is addressed as \"you\".\n\n    Activities other than copying, distribution and modification are not\n    covered by this License; they are outside its scope.  The act of\n    running the Program is not restricted, and the output from the Program\n    is covered only if its contents constitute a work based on the\n    Program (independent of having been made by running the Program).\n    Whether that is true depends on what the Program does.\n\n      1. You may copy and distribute verbatim copies of the Program's\n    source code as you receive it, in any medium, provided that you\n    conspicuously and appropriately publish on each copy an appropriate\n    copyright notice and disclaimer of warranty; keep intact all the\n    notices that refer to this License and to the absence of any warranty;\n    and give any other recipients of the Program a copy of this License\n    along with the Program.\n\n    You may charge a fee for the physical act of transferring a copy, and\n    you may at your option offer warranty protection in exchange for a fee.\n\n      2. You may modify your copy or copies of the Program or any portion\n    of it, thus forming a work based on the Program, and copy and\n    distribute such modifications or work under the terms of Section 1\n    above, provided that you also meet all of these conditions:\n\n        a) You must cause the modified files to carry prominent notices\n        stating that you changed the files and the date of any change.\n\n        b) You must cause any work that you distribute or publish, that in\n        whole or in part contains or is derived from the Program or any\n        part thereof, to be licensed as a whole at no charge to all third\n        parties under the terms of this License.\n\n        c) If the modified program normally reads commands interactively\n        when run, you must cause it, when started running for such\n        interactive use in the most ordinary way, to print or display an\n        announcement including an appropriate copyright notice and a\n        notice that there is no warranty (or else, saying that you provide\n        a warranty) and that users may redistribute the program under\n        these conditions, and telling the user how to view a copy of this\n        License.  (Exception: if the Program itself is interactive but\n        does not normally print such an announcement, your work based on\n        the Program is not required to print an announcement.)\n\n    These requirements apply to the modified work as a whole.  If\n    identifiable sections of that work are not derived from the Program,\n    and can be reasonably considered independent and separate works in\n    themselves, then this License, and its terms, do not apply to those\n    sections when you distribute them as separate works.  But when you\n    distribute the same sections as part of a whole which is a work based\n    on the Program, the distribution of the whole must be on the terms of\n    this License, whose permissions for other licensees extend to the\n    entire whole, and thus to each and every part regardless of who wrote it.\n\n    Thus, it is not the intent of this section to claim rights or contest\n    your rights to work written entirely by you; rather, the intent is to\n    exercise the right to control the distribution of derivative or\n    collective works based on the Program.\n\n    In addition, mere aggregation of another work not based on the Program\n    with the Program (or with a work based on the Program) on a volume of\n    a storage or distribution medium does not bring the other work under\n    the scope of this License.\n\n      3. You may copy and distribute the Program (or a work based on it,\n    under Section 2) in object code or executable form under the terms of\n    Sections 1 and 2 above provided that you also do one of the following:\n\n        a) Accompany it with the complete corresponding machine-readable\n        source code, which must be distributed under the terms of Sections\n        1 and 2 above on a medium customarily used for software interchange; or,\n\n        b) Accompany it with a written offer, valid for at least three\n        years, to give any third party, for a charge no more than your\n        cost of physically performing source distribution, a complete\n        machine-readable copy of the corresponding source code, to be\n        distributed under the terms of Sections 1 and 2 above on a medium\n        customarily used for software interchange; or,\n\n        c) Accompany it with the information you received as to the offer\n        to distribute corresponding source code.  (This alternative is\n        allowed only for noncommercial distribution and only if you\n        received the program in object code or executable form with such\n        an offer, in accord with Subsection b above.)\n\n    The source code for a work means the preferred form of the work for\n    making modifications to it.  For an executable work, complete source\n    code means all the source code for all modules it contains, plus any\n    associated interface definition files, plus the scripts used to\n    control compilation and installation of the executable.  However, as a\n    special exception, the source code distributed need not include\n    anything that is normally distributed (in either source or binary\n    form) with the major components (compiler, kernel, and so on) of the\n    operating system on which the executable runs, unless that component\n    itself accompanies the executable.\n\n    If distribution of executable or object code is made by offering\n    access to copy from a designated place, then offering equivalent\n    access to copy the source code from the same place counts as\n    distribution of the source code, even though third parties are not\n    compelled to copy the source along with the object code.\n\n      4. You may not copy, modify, sublicense, or distribute the Program\n    except as expressly provided under this License.  Any attempt\n    otherwise to copy, modify, sublicense or distribute the Program is\n    void, and will automatically terminate your rights under this License.\n    However, parties who have received copies, or rights, from you under\n    this License will not have their licenses terminated so long as such\n    parties remain in full compliance.\n\n      5. You are not required to accept this License, since you have not\n    signed it.  However, nothing else grants you permission to modify or\n    distribute the Program or its derivative works.  These actions are\n    prohibited by law if you do not accept this License.  Therefore, by\n    modifying or distributing the Program (or any work based on the\n    Program), you indicate your acceptance of this License to do so, and\n    all its terms and conditions for copying, distributing or modifying\n    the Program or works based on it.\n\n      6. Each time you redistribute the Program (or any work based on the\n    Program), the recipient automatically receives a license from the\n    original licensor to copy, distribute or modify the Program subject to\n    these terms and conditions.  You may not impose any further\n    restrictions on the recipients' exercise of the rights granted herein.\n    You are not responsible for enforcing compliance by third parties to\n    this License.\n\n      7. If, as a consequence of a court judgment or allegation of patent\n    infringement or for any other reason (not limited to patent issues),\n    conditions are imposed on you (whether by court order, agreement or\n    otherwise) that contradict the conditions of this License, they do not\n    excuse you from the conditions of this License.  If you cannot\n    distribute so as to satisfy simultaneously your obligations under this\n    License and any other pertinent obligations, then as a consequence you\n    may not distribute the Program at all.  For example, if a patent\n    license would not permit royalty-free redistribution of the Program by\n    all those who receive copies directly or indirectly through you, then\n    the only way you could satisfy both it and this License would be to\n    refrain entirely from distribution of the Program.\n\n    If any portion of this section is held invalid or unenforceable under\n    any particular circumstance, the balance of the section is intended to\n    apply and the section as a whole is intended to apply in other\n    circumstances.\n\n    It is not the purpose of this section to induce you to infringe any\n    patents or other property right claims or to contest validity of any\n    such claims; this section has the sole purpose of protecting the\n    integrity of the free software distribution system, which is\n    implemented by public license practices.  Many people have made\n    generous contributions to the wide range of software distributed\n    through that system in reliance on consistent application of that\n    system; it is up to the author/donor to decide if he or she is willing\n    to distribute software through any other system and a licensee cannot\n    impose that choice.\n\n    This section is intended to make thoroughly clear what is believed to\n    be a consequence of the rest of this License.\n\n      8. If the distribution and/or use of the Program is restricted in\n    certain countries either by patents or by copyrighted interfaces, the\n    original copyright holder who places the Program under this License\n    may add an explicit geographical distribution limitation excluding\n    those countries, so that distribution is permitted only in or among\n    countries not thus excluded.  In such case, this License incorporates\n    the limitation as if written in the body of this License.\n\n      9. The Free Software Foundation may publish revised and/or new versions\n    of the General Public License from time to time.  Such new versions will\n    be similar in spirit to the present version, but may differ in detail to\n    address new problems or concerns.\n\n    Each version is given a distinguishing version number.  If the Program\n    specifies a version number of this License which applies to it and \"any\n    later version\", you have the option of following the terms and conditions\n    either of that version or of any later version published by the Free\n    Software Foundation.  If the Program does not specify a version number of\n    this License, you may choose any version ever published by the Free Software\n    Foundation.\n\n      10. If you wish to incorporate parts of the Program into other free\n    programs whose distribution conditions are different, write to the author\n    to ask for permission.  For software which is copyrighted by the Free\n    Software Foundation, write to the Free Software Foundation; we sometimes\n    make exceptions for this.  Our decision will be guided by the two goals\n    of preserving the free status of all derivatives of our free software and\n    of promoting the sharing and reuse of software generally.\n\n              NO WARRANTY\n\n      11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n    PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n    OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n    TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n    PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n    REPAIR OR CORRECTION.\n\n      12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n    INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n    OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n    TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n    YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n    PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n    POSSIBILITY OF SUCH DAMAGES.\n\n             END OF TERMS AND CONDITIONS\n\n          How to Apply These Terms to Your New Programs\n\n      If you develop a new program, and you want it to be of the greatest\n    possible use to the public, the best way to achieve this is to make it\n    free software which everyone can redistribute and change under these terms.\n\n      To do so, attach the following notices to the program.  It is safest\n    to attach them to the start of each source file to most effectively\n    convey the exclusion of warranty; and each file should have at least\n    the \"copyright\" line and a pointer to where the full notice is found.\n\n        <one line to give the program's name and a brief idea of what it does.>\n        Copyright (C) <year>  <name of author>\n\n        This program is free software; you can redistribute it and/or modify\n        it under the terms of the GNU General Public License as published by\n        the Free Software Foundation; either version 2 of the License, or\n        (at your option) any later version.\n\n        This program is distributed in the hope that it will be useful,\n        but WITHOUT ANY WARRANTY; without even the implied warranty of\n        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n        GNU General Public License for more details.\n\n        You should have received a copy of the GNU General Public License\n        along with this program; if not, write to the Free Software\n        Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\n\n    Also add information on how to contact you by electronic and paper mail.\n\n    If the program is interactive, make it output a short notice like this\n    when it starts in an interactive mode:\n\n        Gnomovision version 69, Copyright (C) year name of author\n        Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n        This is free software, and you are welcome to redistribute it\n        under certain conditions; type `show c' for details.\n\n    The hypothetical commands `show w' and `show c' should show the appropriate\n    parts of the General Public License.  Of course, the commands you use may\n    be called something other than `show w' and `show c'; they could even be\n    mouse-clicks or menu items--whatever suits your program.\n\n    You should also get your employer (if you work as a programmer) or your\n    school, if any, to sign a \"copyright disclaimer\" for the program, if\n    necessary.  Here is a sample; alter the names:\n\n      Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n      `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n      <signature of Ty Coon>, 1 April 1989\n      Ty Coon, President of Vice\n\n    This General Public License does not permit incorporating your program into\n    proprietary programs.  If your program is a subroutine library, you may\n    consider it more useful to permit linking proprietary applications with the\n    library.  If this is what you want to do, use the GNU Library General\n    Public License instead of this License.\n\n    ----------------------------------------------------------------------\n\n    The bundled ZLib code is licensed under the ZLib license:\n\n    Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler\n\n      This software is provided 'as-is', without any express or implied\n      warranty.  In no event will the authors be held liable for any damages\n      arising from the use of this software.\n\n      Permission is granted to anyone to use this software for any purpose,\n      including commercial applications, and to alter it and redistribute it\n      freely, subject to the following restrictions:\n\n      1. The origin of this software must not be misrepresented; you must not\n         claim that you wrote the original software. If you use this software\n         in a product, an acknowledgment in the product documentation would be\n         appreciated but is not required.\n      2. Altered source versions must be plainly marked as such, and must not be\n         misrepresented as being the original software.\n      3. This notice may not be removed or altered from any source distribution.\n\n      Jean-loup Gailly        Mark Adler\n      jloup@gzip.org          madler@alumni.caltech.edu\n\n    ----------------------------------------------------------------------\n\n    The Clar framework is licensed under the MIT license:\n\n    Copyright (C) 2011 by Vicent Marti\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n    ----------------------------------------------------------------------\n\n    The regex library (deps/regex/) is licensed under the GNU LGPL\n\n                      GNU LESSER GENERAL PUBLIC LICENSE\n                           Version 2.1, February 1999\n\n     Copyright (C) 1991, 1999 Free Software Foundation, Inc.\n     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n     Everyone is permitted to copy and distribute verbatim copies\n     of this license document, but changing it is not allowed.\n\n    [This is the first released version of the Lesser GPL.  It also counts\n     as the successor of the GNU Library Public License, version 2, hence\n     the version number 2.1.]\n\n                                Preamble\n\n      The licenses for most software are designed to take away your\n    freedom to share and change it.  By contrast, the GNU General Public\n    Licenses are intended to guarantee your freedom to share and change\n    free software--to make sure the software is free for all its users.\n\n      This license, the Lesser General Public License, applies to some\n    specially designated software packages--typically libraries--of the\n    Free Software Foundation and other authors who decide to use it.  You\n    can use it too, but we suggest you first think carefully about whether\n    this license or the ordinary General Public License is the better\n    strategy to use in any particular case, based on the explanations below.\n\n      When we speak of free software, we are referring to freedom of use,\n    not price.  Our General Public Licenses are designed to make sure that\n    you have the freedom to distribute copies of free software (and charge\n    for this service if you wish); that you receive source code or can get\n    it if you want it; that you can change the software and use pieces of\n    it in new free programs; and that you are informed that you can do\n    these things.\n\n      To protect your rights, we need to make restrictions that forbid\n    distributors to deny you these rights or to ask you to surrender these\n    rights.  These restrictions translate to certain responsibilities for\n    you if you distribute copies of the library or if you modify it.\n\n      For example, if you distribute copies of the library, whether gratis\n    or for a fee, you must give the recipients all the rights that we gave\n    you.  You must make sure that they, too, receive or can get the source\n    code.  If you link other code with the library, you must provide\n    complete object files to the recipients, so that they can relink them\n    with the library after making changes to the library and recompiling\n    it.  And you must show them these terms so they know their rights.\n\n      We protect your rights with a two-step method: (1) we copyright the\n    library, and (2) we offer you this license, which gives you legal\n    permission to copy, distribute and/or modify the library.\n\n      To protect each distributor, we want to make it very clear that\n    there is no warranty for the free library.  Also, if the library is\n    modified by someone else and passed on, the recipients should know\n    that what they have is not the original version, so that the original\n    author's reputation will not be affected by problems that might be\n    introduced by others.\n\n      Finally, software patents pose a constant threat to the existence of\n    any free program.  We wish to make sure that a company cannot\n    effectively restrict the users of a free program by obtaining a\n    restrictive license from a patent holder.  Therefore, we insist that\n    any patent license obtained for a version of the library must be\n    consistent with the full freedom of use specified in this license.\n\n      Most GNU software, including some libraries, is covered by the\n    ordinary GNU General Public License.  This license, the GNU Lesser\n    General Public License, applies to certain designated libraries, and\n    is quite different from the ordinary General Public License.  We use\n    this license for certain libraries in order to permit linking those\n    libraries into non-free programs.\n\n      When a program is linked with a library, whether statically or using\n    a shared library, the combination of the two is legally speaking a\n    combined work, a derivative of the original library.  The ordinary\n    General Public License therefore permits such linking only if the\n    entire combination fits its criteria of freedom.  The Lesser General\n    Public License permits more lax criteria for linking other code with\n    the library.\n\n      We call this license the \"Lesser\" General Public License because it\n    does Less to protect the user's freedom than the ordinary General\n    Public License.  It also provides other free software developers Less\n    of an advantage over competing non-free programs.  These disadvantages\n    are the reason we use the ordinary General Public License for many\n    libraries.  However, the Lesser license provides advantages in certain\n    special circumstances.\n\n      For example, on rare occasions, there may be a special need to\n    encourage the widest possible use of a certain library, so that it becomes\n    a de-facto standard.  To achieve this, non-free programs must be\n    allowed to use the library.  A more frequent case is that a free\n    library does the same job as widely used non-free libraries.  In this\n    case, there is little to gain by limiting the free library to free\n    software only, so we use the Lesser General Public License.\n\n      In other cases, permission to use a particular library in non-free\n    programs enables a greater number of people to use a large body of\n    free software.  For example, permission to use the GNU C Library in\n    non-free programs enables many more people to use the whole GNU\n    operating system, as well as its variant, the GNU/Linux operating\n    system.\n\n      Although the Lesser General Public License is Less protective of the\n    users' freedom, it does ensure that the user of a program that is\n    linked with the Library has the freedom and the wherewithal to run\n    that program using a modified version of the Library.\n\n      The precise terms and conditions for copying, distribution and\n    modification follow.  Pay close attention to the difference between a\n    \"work based on the library\" and a \"work that uses the library\".  The\n    former contains code derived from the library, whereas the latter must\n    be combined with the library in order to run.\n\n                      GNU LESSER GENERAL PUBLIC LICENSE\n       TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n      0. This License Agreement applies to any software library or other\n    program which contains a notice placed by the copyright holder or\n    other authorized party saying it may be distributed under the terms of\n    this Lesser General Public License (also called \"this License\").\n    Each licensee is addressed as \"you\".\n\n      A \"library\" means a collection of software functions and/or data\n    prepared so as to be conveniently linked with application programs\n    (which use some of those functions and data) to form executables.\n\n      The \"Library\", below, refers to any such software library or work\n    which has been distributed under these terms.  A \"work based on the\n    Library\" means either the Library or any derivative work under\n    copyright law: that is to say, a work containing the Library or a\n    portion of it, either verbatim or with modifications and/or translated\n    straightforwardly into another language.  (Hereinafter, translation is\n    included without limitation in the term \"modification\".)\n\n      \"Source code\" for a work means the preferred form of the work for\n    making modifications to it.  For a library, complete source code means\n    all the source code for all modules it contains, plus any associated\n    interface definition files, plus the scripts used to control compilation\n    and installation of the library.\n\n      Activities other than copying, distribution and modification are not\n    covered by this License; they are outside its scope.  The act of\n    running a program using the Library is not restricted, and output from\n    such a program is covered only if its contents constitute a work based\n    on the Library (independent of the use of the Library in a tool for\n    writing it).  Whether that is true depends on what the Library does\n    and what the program that uses the Library does.\n\n      1. You may copy and distribute verbatim copies of the Library's\n    complete source code as you receive it, in any medium, provided that\n    you conspicuously and appropriately publish on each copy an\n    appropriate copyright notice and disclaimer of warranty; keep intact\n    all the notices that refer to this License and to the absence of any\n    warranty; and distribute a copy of this License along with the\n    Library.\n\n      You may charge a fee for the physical act of transferring a copy,\n    and you may at your option offer warranty protection in exchange for a\n    fee.\n\n      2. You may modify your copy or copies of the Library or any portion\n    of it, thus forming a work based on the Library, and copy and\n    distribute such modifications or work under the terms of Section 1\n    above, provided that you also meet all of these conditions:\n\n        a) The modified work must itself be a software library.\n\n        b) You must cause the files modified to carry prominent notices\n        stating that you changed the files and the date of any change.\n\n        c) You must cause the whole of the work to be licensed at no\n        charge to all third parties under the terms of this License.\n\n        d) If a facility in the modified Library refers to a function or a\n        table of data to be supplied by an application program that uses\n        the facility, other than as an argument passed when the facility\n        is invoked, then you must make a good faith effort to ensure that,\n        in the event an application does not supply such function or\n        table, the facility still operates, and performs whatever part of\n        its purpose remains meaningful.\n\n        (For example, a function in a library to compute square roots has\n        a purpose that is entirely well-defined independent of the\n        application.  Therefore, Subsection 2d requires that any\n        application-supplied function or table used by this function must\n        be optional: if the application does not supply it, the square\n        root function must still compute square roots.)\n\n    These requirements apply to the modified work as a whole.  If\n    identifiable sections of that work are not derived from the Library,\n    and can be reasonably considered independent and separate works in\n    themselves, then this License, and its terms, do not apply to those\n    sections when you distribute them as separate works.  But when you\n    distribute the same sections as part of a whole which is a work based\n    on the Library, the distribution of the whole must be on the terms of\n    this License, whose permissions for other licensees extend to the\n    entire whole, and thus to each and every part regardless of who wrote\n    it.\n\n    Thus, it is not the intent of this section to claim rights or contest\n    your rights to work written entirely by you; rather, the intent is to\n    exercise the right to control the distribution of derivative or\n    collective works based on the Library.\n\n    In addition, mere aggregation of another work not based on the Library\n    with the Library (or with a work based on the Library) on a volume of\n    a storage or distribution medium does not bring the other work under\n    the scope of this License.\n\n      3. You may opt to apply the terms of the ordinary GNU General Public\n    License instead of this License to a given copy of the Library.  To do\n    this, you must alter all the notices that refer to this License, so\n    that they refer to the ordinary GNU General Public License, version 2,\n    instead of to this License.  (If a newer version than version 2 of the\n    ordinary GNU General Public License has appeared, then you can specify\n    that version instead if you wish.)  Do not make any other change in\n    these notices.\n\n      Once this change is made in a given copy, it is irreversible for\n    that copy, so the ordinary GNU General Public License applies to all\n    subsequent copies and derivative works made from that copy.\n\n      This option is useful when you wish to copy part of the code of\n    the Library into a program that is not a library.\n\n      4. You may copy and distribute the Library (or a portion or\n    derivative of it, under Section 2) in object code or executable form\n    under the terms of Sections 1 and 2 above provided that you accompany\n    it with the complete corresponding machine-readable source code, which\n    must be distributed under the terms of Sections 1 and 2 above on a\n    medium customarily used for software interchange.\n\n      If distribution of object code is made by offering access to copy\n    from a designated place, then offering equivalent access to copy the\n    source code from the same place satisfies the requirement to\n    distribute the source code, even though third parties are not\n    compelled to copy the source along with the object code.\n\n      5. A program that contains no derivative of any portion of the\n    Library, but is designed to work with the Library by being compiled or\n    linked with it, is called a \"work that uses the Library\".  Such a\n    work, in isolation, is not a derivative work of the Library, and\n    therefore falls outside the scope of this License.\n\n      However, linking a \"work that uses the Library\" with the Library\n    creates an executable that is a derivative of the Library (because it\n    contains portions of the Library), rather than a \"work that uses the\n    library\".  The executable is therefore covered by this License.\n    Section 6 states terms for distribution of such executables.\n\n      When a \"work that uses the Library\" uses material from a header file\n    that is part of the Library, the object code for the work may be a\n    derivative work of the Library even though the source code is not.\n    Whether this is true is especially significant if the work can be\n    linked without the Library, or if the work is itself a library.  The\n    threshold for this to be true is not precisely defined by law.\n\n      If such an object file uses only numerical parameters, data\n    structure layouts and accessors, and small macros and small inline\n    functions (ten lines or less in length), then the use of the object\n    file is unrestricted, regardless of whether it is legally a derivative\n    work.  (Executables containing this object code plus portions of the\n    Library will still fall under Section 6.)\n\n      Otherwise, if the work is a derivative of the Library, you may\n    distribute the object code for the work under the terms of Section 6.\n    Any executables containing that work also fall under Section 6,\n    whether or not they are linked directly with the Library itself.\n\n      6. As an exception to the Sections above, you may also combine or\n    link a \"work that uses the Library\" with the Library to produce a\n    work containing portions of the Library, and distribute that work\n    under terms of your choice, provided that the terms permit\n    modification of the work for the customer's own use and reverse\n    engineering for debugging such modifications.\n\n      You must give prominent notice with each copy of the work that the\n    Library is used in it and that the Library and its use are covered by\n    this License.  You must supply a copy of this License.  If the work\n    during execution displays copyright notices, you must include the\n    copyright notice for the Library among them, as well as a reference\n    directing the user to the copy of this License.  Also, you must do one\n    of these things:\n\n        a) Accompany the work with the complete corresponding\n        machine-readable source code for the Library including whatever\n        changes were used in the work (which must be distributed under\n        Sections 1 and 2 above); and, if the work is an executable linked\n        with the Library, with the complete machine-readable \"work that\n        uses the Library\", as object code and/or source code, so that the\n        user can modify the Library and then relink to produce a modified\n        executable containing the modified Library.  (It is understood\n        that the user who changes the contents of definitions files in the\n        Library will not necessarily be able to recompile the application\n        to use the modified definitions.)\n\n        b) Use a suitable shared library mechanism for linking with the\n        Library.  A suitable mechanism is one that (1) uses at run time a\n        copy of the library already present on the user's computer system,\n        rather than copying library functions into the executable, and (2)\n        will operate properly with a modified version of the library, if\n        the user installs one, as long as the modified version is\n        interface-compatible with the version that the work was made with.\n\n        c) Accompany the work with a written offer, valid for at\n        least three years, to give the same user the materials\n        specified in Subsection 6a, above, for a charge no more\n        than the cost of performing this distribution.\n\n        d) If distribution of the work is made by offering access to copy\n        from a designated place, offer equivalent access to copy the above\n        specified materials from the same place.\n\n        e) Verify that the user has already received a copy of these\n        materials or that you have already sent this user a copy.\n\n      For an executable, the required form of the \"work that uses the\n    Library\" must include any data and utility programs needed for\n    reproducing the executable from it.  However, as a special exception,\n    the materials to be distributed need not include anything that is\n    normally distributed (in either source or binary form) with the major\n    components (compiler, kernel, and so on) of the operating system on\n    which the executable runs, unless that component itself accompanies\n    the executable.\n\n      It may happen that this requirement contradicts the license\n    restrictions of other proprietary libraries that do not normally\n    accompany the operating system.  Such a contradiction means you cannot\n    use both them and the Library together in an executable that you\n    distribute.\n\n      7. You may place library facilities that are a work based on the\n    Library side-by-side in a single library together with other library\n    facilities not covered by this License, and distribute such a combined\n    library, provided that the separate distribution of the work based on\n    the Library and of the other library facilities is otherwise\n    permitted, and provided that you do these two things:\n\n        a) Accompany the combined library with a copy of the same work\n        based on the Library, uncombined with any other library\n        facilities.  This must be distributed under the terms of the\n        Sections above.\n\n        b) Give prominent notice with the combined library of the fact\n        that part of it is a work based on the Library, and explaining\n        where to find the accompanying uncombined form of the same work.\n\n      8. You may not copy, modify, sublicense, link with, or distribute\n    the Library except as expressly provided under this License.  Any\n    attempt otherwise to copy, modify, sublicense, link with, or\n    distribute the Library is void, and will automatically terminate your\n    rights under this License.  However, parties who have received copies,\n    or rights, from you under this License will not have their licenses\n    terminated so long as such parties remain in full compliance.\n\n      9. You are not required to accept this License, since you have not\n    signed it.  However, nothing else grants you permission to modify or\n    distribute the Library or its derivative works.  These actions are\n    prohibited by law if you do not accept this License.  Therefore, by\n    modifying or distributing the Library (or any work based on the\n    Library), you indicate your acceptance of this License to do so, and\n    all its terms and conditions for copying, distributing or modifying\n    the Library or works based on it.\n\n      10. Each time you redistribute the Library (or any work based on the\n    Library), the recipient automatically receives a license from the\n    original licensor to copy, distribute, link with or modify the Library\n    subject to these terms and conditions.  You may not impose any further\n    restrictions on the recipients' exercise of the rights granted herein.\n    You are not responsible for enforcing compliance by third parties with\n    this License.\n\n      11. If, as a consequence of a court judgment or allegation of patent\n    infringement or for any other reason (not limited to patent issues),\n    conditions are imposed on you (whether by court order, agreement or\n    otherwise) that contradict the conditions of this License, they do not\n    excuse you from the conditions of this License.  If you cannot\n    distribute so as to satisfy simultaneously your obligations under this\n    License and any other pertinent obligations, then as a consequence you\n    may not distribute the Library at all.  For example, if a patent\n    license would not permit royalty-free redistribution of the Library by\n    all those who receive copies directly or indirectly through you, then\n    the only way you could satisfy both it and this License would be to\n    refrain entirely from distribution of the Library.\n\n    If any portion of this section is held invalid or unenforceable under any\n    particular circumstance, the balance of the section is intended to apply,\n    and the section as a whole is intended to apply in other circumstances.\n\n    It is not the purpose of this section to induce you to infringe any\n    patents or other property right claims or to contest validity of any\n    such claims; this section has the sole purpose of protecting the\n    integrity of the free software distribution system which is\n    implemented by public license practices.  Many people have made\n    generous contributions to the wide range of software distributed\n    through that system in reliance on consistent application of that\n    system; it is up to the author/donor to decide if he or she is willing\n    to distribute software through any other system and a licensee cannot\n    impose that choice.\n\n    This section is intended to make thoroughly clear what is believed to\n    be a consequence of the rest of this License.\n\n      12. If the distribution and/or use of the Library is restricted in\n    certain countries either by patents or by copyrighted interfaces, the\n    original copyright holder who places the Library under this License may add\n    an explicit geographical distribution limitation excluding those countries,\n    so that distribution is permitted only in or among countries not thus\n    excluded.  In such case, this License incorporates the limitation as if\n    written in the body of this License.\n\n      13. The Free Software Foundation may publish revised and/or new\n    versions of the Lesser General Public License from time to time.\n    Such new versions will be similar in spirit to the present version,\n    but may differ in detail to address new problems or concerns.\n\n    Each version is given a distinguishing version number.  If the Library\n    specifies a version number of this License which applies to it and\n    \"any later version\", you have the option of following the terms and\n    conditions either of that version or of any later version published by\n    the Free Software Foundation.  If the Library does not specify a\n    license version number, you may choose any version ever published by\n    the Free Software Foundation.\n\n      14. If you wish to incorporate parts of the Library into other free\n    programs whose distribution conditions are incompatible with these,\n    write to the author to ask for permission.  For software which is\n    copyrighted by the Free Software Foundation, write to the Free\n    Software Foundation; we sometimes make exceptions for this.  Our\n    decision will be guided by the two goals of preserving the free status\n    of all derivatives of our free software and of promoting the sharing\n    and reuse of software generally.\n\n                                NO WARRANTY\n\n      15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\n    WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\n    EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\n    OTHER PARTIES PROVIDE THE LIBRARY \"AS IS\" WITHOUT WARRANTY OF ANY\n    KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\n    LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\n    THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n      16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\n    WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\n    AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU\n    FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\n    CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\n    LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\n    RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\n    FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\n    SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\n    DAMAGES.\n\n                         END OF TERMS AND CONDITIONS\n\n               How to Apply These Terms to Your New Libraries\n\n      If you develop a new library, and you want it to be of the greatest\n    possible use to the public, we recommend making it free software that\n    everyone can redistribute and change.  You can do so by permitting\n    redistribution under these terms (or, alternatively, under the terms of the\n    ordinary General Public License).\n\n      To apply these terms, attach the following notices to the library.  It is\n    safest to attach them to the start of each source file to most effectively\n    convey the exclusion of warranty; and each file should have at least the\n    \"copyright\" line and a pointer to where the full notice is found.\n\n        <one line to give the library's name and a brief idea of what it does.>\n        Copyright (C) <year>  <name of author>\n\n        This library is free software; you can redistribute it and/or\n        modify it under the terms of the GNU Lesser General Public\n        License as published by the Free Software Foundation; either\n        version 2.1 of the License, or (at your option) any later version.\n\n        This library is distributed in the hope that it will be useful,\n        but WITHOUT ANY WARRANTY; without even the implied warranty of\n        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n        Lesser General Public License for more details.\n\n        You should have received a copy of the GNU Lesser General Public\n        License along with this library; if not, write to the Free Software\n        Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n\n    Also add information on how to contact you by electronic and paper mail.\n\n    You should also get your employer (if you work as a programmer) or your\n    school, if any, to sign a \"copyright disclaimer\" for the library, if\n    necessary.  Here is a sample; alter the names:\n\n      Yoyodyne, Inc., hereby disclaims all copyright interest in the\n      library `Frob' (a library for tweaking knobs) written by James Random Hacker.\n\n      <signature of Ty Coon>, 1 April 1990\n      Ty Coon, President of Vice\n\n    That's all there is to it!\n\n    ----------------------------------------------------------------------\n\n* libssh2 - https://www.libssh2.org/license.html\n\n    Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>\n    Copyright (c) 2005,2006 Mikhail Gusarov <dottedmag@dottedmag.net>\n    Copyright (c) 2006-2007 The Written Word, Inc.\n    Copyright (c) 2007 Eli Fant <elifantu@mail.ru>\n    Copyright (c) 2009 Daniel Stenberg\n    Copyright (C) 2008, 2009 Simon Josefsson\n    All rights reserved.\n\n    Redistribution and use in source and binary forms,\n    with or without modification, are permitted provided\n    that the following conditions are met:\n\n      Redistributions of source code must retain the above\n      copyright notice, this list of conditions and the\n      following disclaimer.\n\n      Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials\n      provided with the distribution.\n\n      Neither the name of the copyright holder nor the names\n      of any other contributors may be used to endorse or\n      promote products derived from this software without\n      specific prior written permission.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n    CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\n    USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\n    OF SUCH DAMAGE.\n\n* libcurl - https://curl.haxx.se/docs/copyright.html\n\n    COPYRIGHT AND PERMISSION NOTICE\n\n    Copyright (c) 1996 - 2014, Daniel Stenberg, daniel@haxx.se.\n\n    All rights reserved.\n\n    Permission to use, copy, modify, and distribute this software for any\n    purpose with or without fee is hereby granted, provided that the above\n    copyright notice and this permission notice appear in all copies.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n    USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n    Except as contained in this notice, the name of a copyright holder shall not\n    be used in advertising or otherwise to promote the sale, use or other\n    dealings in this Software without prior written authorization of the\n    copyright holder.\n\n* flate2-rs - https://github.com/alexcrichton/flate2-rs/blob/master/LICENSE-MIT\n* link-config - https://github.com/alexcrichton/link-config/blob/master/LICENSE-MIT\n* openssl-static-sys - https://github.com/alexcrichton/openssl-static-sys/blob/master/LICENSE-MIT\n* toml-rs - https://github.com/alexcrichton/toml-rs/blob/master/LICENSE-MIT\n* libssh2-static-sys - https://github.com/alexcrichton/libssh2-static-sys/blob/master/LICENSE-MIT\n* git2-rs - https://github.com/alexcrichton/git2-rs/blob/master/LICENSE-MIT\n* tar-rs - https://github.com/alexcrichton/tar-rs/blob/master/LICENSE-MIT\n\n    Copyright (c) 2014 Alex Crichton\n\n    Permission is hereby granted, free of charge, to any\n    person obtaining a copy of this software and associated\n    documentation files (the \"Software\"), to deal in the\n    Software without restriction, including without\n    limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of\n    the Software, and to permit persons to whom the Software\n    is furnished to do so, subject to the following\n    conditions:\n\n    The above copyright notice and this permission notice\n    shall be included in all copies or substantial portions\n    of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\n    ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\n    TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n    PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\n    SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\n    IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n    DEALINGS IN THE SOFTWARE.\n\n* glob - https://github.com/rust-lang/glob/blob/master/LICENSE-MIT\n* semver - https://github.com/rust-lang/semver/blob/master/LICENSE-MIT\n\n    Copyright (c) 2014 The Rust Project Developers\n\n    Permission is hereby granted, free of charge, to any\n    person obtaining a copy of this software and associated\n    documentation files (the \"Software\"), to deal in the\n    Software without restriction, including without\n    limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of\n    the Software, and to permit persons to whom the Software\n    is furnished to do so, subject to the following\n    conditions:\n\n    The above copyright notice and this permission notice\n    shall be included in all copies or substantial portions\n    of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\n    ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\n    TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n    PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\n    SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\n    IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n    DEALINGS IN THE SOFTWARE.\n\n* rust-url - https://github.com/servo/rust-url/blob/master/LICENSE-MIT\n\n    Copyright (c) 2006-2009 Graydon Hoare\n    Copyright (c) 2009-2013 Mozilla Foundation\n\n    Permission is hereby granted, free of charge, to any\n    person obtaining a copy of this software and associated\n    documentation files (the \"Software\"), to deal in the\n    Software without restriction, including without\n    limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of\n    the Software, and to permit persons to whom the Software\n    is furnished to do so, subject to the following\n    conditions:\n\n    The above copyright notice and this permission notice\n    shall be included in all copies or substantial portions\n    of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\n    ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\n    TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n    PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\n    SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\n    IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n    DEALINGS IN THE SOFTWARE.\n\n* rust-encoding - https://github.com/lifthrasiir/rust-encoding/blob/master/LICENSE.txt\n\n    The MIT License (MIT)\n\n    Copyright (c) 2013, Kang Seonghoon.\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n* curl-rust - https://github.com/carllerche/curl-rust/blob/master/LICENSE\n\n    Copyright (c) 2014 Carl Lerche\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in\n    all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n    THE SOFTWARE.\n\n* docopt.rs - https://github.com/docopt/docopt.rs/blob/master/UNLICENSE\n\n    This is free and unencumbered software released into the public domain.\n\n    Anyone is free to copy, modify, publish, use, compile, sell, or\n    distribute this software, either in source code form or as a compiled\n    binary, for any purpose, commercial or non-commercial, and by any\n    means.\n\n    In jurisdictions that recognize copyright laws, the author or authors\n    of this software dedicate any and all copyright interest in the\n    software to the public domain. We make this dedication for the benefit\n    of the public at large and to the detriment of our heirs and\n    successors. We intend this dedication to be an overt act of\n    relinquishment in perpetuity of all present and future rights to this\n    software under copyright law.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\n    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n    OTHER DEALINGS IN THE SOFTWARE.\n\n    For more information, please refer to <https://unlicense.org/>\n\n"
  },
  {
    "path": "README.md",
    "content": "# Cargo\n\nCargo downloads your Rust project’s dependencies and compiles your project.\n\n**To start using Cargo**, learn more at [The Cargo Book].\n\n**To start developing Cargo itself**, read the [Cargo Contributor Guide].\n\n[The Cargo Book]: https://doc.rust-lang.org/cargo/\n[Cargo Contributor Guide]: https://rust-lang.github.io/cargo/contrib/\n\n> The Cargo binary distributed through with Rust is maintained by the Cargo\n> team for use by the wider ecosystem.\n> For all other uses of this crate (as a binary or library) this is maintained\n> by the Cargo team, primarily for use by Cargo and not intended for external\n> use (except as a transitive dependency). This crate may make major changes to\n> its APIs.\n\n## Code Status\n\n[![CI](https://github.com/rust-lang/cargo/actions/workflows/main.yml/badge.svg?branch=auto-cargo)](https://github.com/rust-lang/cargo/actions/workflows/main.yml)\n\nCode documentation: <https://doc.rust-lang.org/nightly/nightly-rustc/cargo/>\n\n## Compiling from Source\n\n### Requirements\n\nCargo requires the following tools and packages to build:\n\n* `cargo` and `rustc`\n* A C compiler [for your platform](https://github.com/rust-lang/cc-rs#compile-time-requirements)\n* `git` (to clone this repository)\n\n**Other requirements:**\n\nThe following are optional based on your platform and needs.\n\n* `pkg-config` — This is used to help locate system packages, such as `libssl` headers/libraries. This may not be required in all cases, such as using vendored OpenSSL, or on Windows.\n* OpenSSL — Only needed on Unix-like systems and only if the `vendored-openssl` Cargo feature is not used.\n\n  This requires the development headers, which can be obtained from the `libssl-dev` package on Ubuntu or `openssl-devel` with apk or yum or the `openssl` package from Homebrew on macOS.\n\n  If using the `vendored-openssl` Cargo feature, then a static copy of OpenSSL will be built from source instead of using the system OpenSSL.\n  This may require additional tools such as `perl` and `make`.\n\n  On macOS, common installation directories from Homebrew, MacPorts, or pkgsrc will be checked. Otherwise it will fall back to `pkg-config`.\n\n  On Windows, the system-provided Schannel will be used instead.\n\n  LibreSSL is also supported.\n\n**Optional system libraries:**\n\nThe build will automatically use vendored versions of the following libraries. However, if they are provided by the system and can be found with `pkg-config`, then the system libraries will be used instead:\n\n* [`libcurl`](https://curl.se/libcurl/) — Used for network transfers.\n* [`libgit2`](https://libgit2.org/) — Used for fetching git dependencies.\n* [`libssh2`](https://www.libssh2.org/) — Used for SSH access to git repositories.\n* [`libz`](https://zlib.net/) (AKA zlib) — Used by the above C libraries for data compression. (Rust code uses [`zlib-rs`](https://github.com/trifectatechfoundation/zlib-rs) instead.)\n\nIt is recommended to use the vendored versions as they are the versions that are tested to work with Cargo.\n\n### Compiling\n\nFirst, you'll want to check out this repository\n\n```\ngit clone https://github.com/rust-lang/cargo.git\ncd cargo\n```\n\nWith `cargo` already installed, you can simply run:\n\n```\ncargo build --release\n```\n\n## Adding new subcommands to Cargo\n\nCargo is designed to be extensible with new subcommands without having to modify\nCargo itself. See [the Wiki page][third-party-subcommands] for more details and\na list of known community-developed subcommands.\n\n[third-party-subcommands]: https://github.com/rust-lang/cargo/wiki/Third-party-cargo-subcommands\n\n\n## Releases\n\nCargo releases coincide with Rust releases.\nHigh level release notes are available as part of [Rust's release notes][rel].\nDetailed release notes are available in the [changelog].\n\n[rel]: https://github.com/rust-lang/rust/blob/master/RELEASES.md\n[changelog]: https://doc.rust-lang.org/nightly/cargo/CHANGELOG.html\n\n## Reporting issues\n\nFound a bug? We'd love to know about it!\n\nPlease report all issues on the GitHub [issue tracker][issues].\n\n[issues]: https://github.com/rust-lang/cargo/issues\n\n## Contributing\n\nSee the **[Cargo Contributor Guide]** for a complete introduction\nto contributing to Cargo.\n\n## License\n\nCargo is primarily distributed under the terms of both the MIT license\nand the Apache License (Version 2.0).\n\nSee [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for details.\n\n### Third party software\n\nThis product includes software developed by the OpenSSL Project\nfor use in the OpenSSL Toolkit (https://www.openssl.org/).\n\nIn binary form, this product includes software that is licensed under the\nterms of the GNU General Public License, version 2, with a linking exception,\nwhich can be obtained from the [upstream repository][1].\n\nSee [LICENSE-THIRD-PARTY](LICENSE-THIRD-PARTY) for details.\n\n[1]: https://github.com/libgit2/libgit2\n\n"
  },
  {
    "path": "benches/README.md",
    "content": "# Cargo Benchmarking\n\nThis directory contains some benchmarks for cargo itself. This uses\n[Criterion] for running benchmarks. It is recommended to read the Criterion\nbook to get familiar with how to use it. A basic usage would be:\n\n```sh\ncd benches/benchsuite\ncargo bench\n```\n\nHowever, running all benchmarks would take many minutes, so in most cases it\nis recommended to just run the benchmarks relevant to whatever section of code\nyou are working on.\n\n## Benchmarks\n\nThere are several different kinds of benchmarks in the `benchsuite/benches` directory:\n\n* `global_cache_tracker` — Benchmarks saving data to the global cache tracker\n  database using samples of real-world data.\n* `resolve` — Benchmarks the resolver against simulations of real-world workspaces.\n* `workspace_initialization` — Benchmarks initialization of a workspace\n  against simulations of real-world workspaces.\n\n### Resolve benchmarks\n\nThe resolve benchmarks involve downloading the index and benchmarking against some\nreal-world and artificial workspaces located in the [`workspaces`](workspaces)\ndirectory.\n\n**Beware** that the initial download can take a fairly long amount of time (10\nminutes minimum on an extremely fast network) and require significant disk\nspace (around 4.5GB). The benchsuite will cache the index and downloaded\ncrates in the `target/tmp/bench` directory, so subsequent runs should be\nfaster. You can (and probably should) specify individual benchmarks to run to\nnarrow it down to a more reasonable set, for example:\n\n```sh\ncargo bench -p benchsuite --bench resolve -- resolve_ws/rust\n```\n\nThis will only download what's necessary for the rust-lang/rust workspace\n(which is about 330MB) and run the benchmarks against it (which should take\nabout a minute). To get a list of all the benchmarks, run:\n\n```sh\ncargo bench -p benchsuite --bench resolve -- --list\n```\n\n### Global cache tracker\n\nThe `global_cache_tracker` benchmark tests saving data to the global cache\ntracker database using samples of real-world data. This benchmark should run\nrelatively quickly.\n\nThe real-world data is based on a capture of my personal development\nenvironment which has accumulated a large cache. So it is somewhat arbitrary,\nbut hopefully representative of a challenging environment. Capturing of the\ndata is done with the `capture-last-use` binary, which you can run if you need\nto rebuild the database. Just try to run on a system with a relatively full\ncache in your cargo home directory.\n\n```sh\ncargo bench -p benchsuite --bench global_cache_tracker\n```\n\n## Viewing reports\n\nThe benchmarks display some basic information on the command-line while they\nrun. A more complete HTML report can be found at\n`target/criterion/report/index.html` which contains links to all the\nbenchmarks and summaries. Check out the Criterion book for more information on\nthe extensive reporting capabilities.\n\n## Comparing implementations\n\nKnowing the raw numbers can be useful, but what you're probably most\ninterested in is checking if your changes help or hurt performance. To do\nthat, you need to run the benchmarks multiple times.\n\nFirst, run the benchmarks from the master branch of cargo without any changes.\nTo make it easier to compare, Criterion supports naming the baseline so that\nyou can iterate on your code and compare against it multiple times.\n\n```sh\ncargo bench -- --save-baseline master\n```\n\nNow you can switch to your branch with your changes. Re-run the benchmarks\ncompared against the baseline:\n\n```sh\ncargo bench -- --baseline master\n```\n\nYou can repeat the last command as you make changes to re-compare against the\nmaster baseline.\n\nWithout the baseline arguments, it will compare against the last run, which\ncan be helpful for comparing incremental changes.\n\n## Capturing workspaces\n\nThe [`workspaces`](workspaces) directory contains several workspaces that\nprovide a variety of different workspaces intended to provide good exercises\nfor benchmarks. Some of these are shadow copies of real-world workspaces. This\nis done with the tool in the [`capture`](capture) directory. The tool will\ncopy `Cargo.lock` and all of the `Cargo.toml` files of the workspace members.\nIt also adds an empty `lib.rs` so Cargo won't error, and sanitizes the\n`Cargo.toml` to some degree, removing unwanted elements. Finally, it\ncompresses everything into a `tgz`.\n\nTo run it, do:\n\n```sh\ncd benches/capture\ncargo run -- /path/to/workspace/foo\n```\n\nThe resolver benchmarks also support the `CARGO_BENCH_WORKSPACES` environment\nvariable, which you can point to a Cargo workspace if you want to try\ndifferent workspaces. For example:\n\n```sh\nCARGO_BENCH_WORKSPACES=/path/to/some/workspace cargo bench\n```\n\n## TODO\n\nThis is just a start for establishing a benchmarking suite for Cargo. There's\na lot that can be added. Some ideas:\n\n* Fix the benchmarks so that the resolver setup doesn't run every iteration.\n* Benchmark [this section of\n  code](https://github.com/rust-lang/cargo/blob/a821e2cb24d7b6013433f069ab3bad53d160e100/src/cargo/ops/cargo_compile.rs#L470-L549)\n  which builds the unit graph. The performance there isn't great, and it would\n  be good to keep an eye on it. Unfortunately that would mean doing a bit of\n  work to make `generate_targets` publicly visible, and there is a bunch of\n  setup code that may need to be duplicated.\n* Benchmark the fingerprinting code.\n* Benchmark running the `cargo` executable. Running something like `cargo\n  build` or `cargo check` with everything \"Fresh\" would be a good end-to-end\n  exercise to measure the overall overhead of Cargo.\n* Benchmark pathological resolver scenarios. There might be some cases where\n  the resolver can spend a significant amount of time. It would be good to\n  identify if these exist, and create benchmarks for them. This may require\n  creating an artificial index, similar to the `resolver-tests`. This should\n  also consider scenarios where the resolver ultimately fails.\n* Benchmark without `Cargo.lock`. I'm not sure if this is particularly\n  valuable, since we are mostly concerned with incremental builds which will\n  always have a lock file.\n* Benchmark just\n  [`resolve::resolve`](https://github.com/rust-lang/cargo/blob/a821e2cb24d7b6013433f069ab3bad53d160e100/src/cargo/core/resolver/mod.rs#L122)\n  without anything else. This can help focus on just the resolver.\n\n[Criterion]: https://bheisler.github.io/criterion.rs/book/\n"
  },
  {
    "path": "benches/benchsuite/Cargo.toml",
    "content": "[package]\nname = \"benchsuite\"\nversion = \"0.0.0\"\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"Benchmarking suite for Cargo.\"\npublish = false\n\n[dependencies]\ncargo.workspace = true\ncargo-util.workspace = true\ncriterion.workspace = true\nflate2.workspace = true\nrand.workspace = true\ntar.workspace = true\nurl.workspace = true\n\n[lib]\nbench = false\n\n[[bench]]\nname = \"resolve\"\nharness = false\n\n[[bench]]\nname = \"workspace_initialization\"\nharness = false\n\n[[bench]]\nname = \"global_cache_tracker\"\nharness = false\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "benches/benchsuite/README.md",
    "content": "> This crate is maintained by the Cargo team, primarily for use by Cargo\n> and not intended for external use. This\n> crate may make major changes to its APIs or be deprecated without warning.\n"
  },
  {
    "path": "benches/benchsuite/benches/global_cache_tracker.rs",
    "content": "//! Benchmarks for the global cache tracker.\n\nuse cargo::core::global_cache_tracker::{self, DeferredGlobalLastUse, GlobalCacheTracker};\nuse cargo::util::GlobalContext;\nuse cargo::util::cache_lock::CacheLockMode;\nuse cargo::util::interning::InternedString;\nuse criterion::{Criterion, criterion_group, criterion_main};\nuse std::fs;\nuse std::path::{Path, PathBuf};\n\n// Samples of real-world data.\nconst GLOBAL_CACHE_SAMPLE: &str = \"global-cache-tracker/global-cache-sample\";\nconst GLOBAL_CACHE_RANDOM: &str = \"global-cache-tracker/random-sample\";\n\n/// A scratch directory where the benchmark can place some files.\nfn root() -> PathBuf {\n    let mut p = PathBuf::from(env!(\"CARGO_TARGET_TMPDIR\"));\n    p.push(\"bench_global_cache_tracker\");\n    p\n}\n\nfn cargo_home() -> PathBuf {\n    let mut p = root();\n    p.push(\"chome\");\n    p\n}\n\nfn initialize_context() -> GlobalContext {\n    // Set up config.\n    let shell = cargo::core::Shell::new();\n    let homedir = cargo_home();\n    if !homedir.exists() {\n        fs::create_dir_all(&homedir).unwrap();\n    }\n    let cwd = homedir.clone();\n    let mut gctx = GlobalContext::new(shell, cwd, homedir);\n    gctx.nightly_features_allowed = true;\n    gctx.set_search_stop_path(root());\n    gctx.configure(\n        0,\n        false,\n        None,\n        false,\n        false,\n        false,\n        &None,\n        &[\"gc\".to_string()],\n        &[],\n    )\n    .unwrap();\n    // Set up database sample.\n    let db_path = GlobalCacheTracker::db_path(&gctx).into_path_unlocked();\n    if db_path.exists() {\n        fs::remove_file(&db_path).unwrap();\n    }\n    let sample = Path::new(env!(\"CARGO_MANIFEST_DIR\")).join(GLOBAL_CACHE_SAMPLE);\n    fs::copy(sample, &db_path).unwrap();\n    gctx\n}\n\n/// Benchmarks how long it takes to initialize `GlobalCacheTracker` with an already\n/// existing full database.\nfn global_tracker_init(c: &mut Criterion) {\n    let gctx = initialize_context();\n    let _lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)\n        .unwrap();\n    c.bench_function(\"global_tracker_init\", |b| {\n        b.iter(|| {\n            GlobalCacheTracker::new(&gctx).unwrap();\n        })\n    });\n}\n\n/// Benchmarks how long it takes to save a `GlobalCacheTracker` when there are zero\n/// updates.\nfn global_tracker_empty_save(c: &mut Criterion) {\n    let gctx = initialize_context();\n    let _lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)\n        .unwrap();\n    let mut deferred = DeferredGlobalLastUse::new();\n    let mut tracker = GlobalCacheTracker::new(&gctx).unwrap();\n\n    c.bench_function(\"global_tracker_empty_save\", |b| {\n        b.iter(|| {\n            deferred.save(&mut tracker).unwrap();\n        })\n    });\n}\n\nfn load_random_sample() -> Vec<(InternedString, InternedString, u64)> {\n    let path = Path::new(env!(\"CARGO_MANIFEST_DIR\")).join(GLOBAL_CACHE_RANDOM);\n    fs::read_to_string(path)\n        .unwrap()\n        .lines()\n        .map(|s| {\n            let mut s = s.split(',');\n            (\n                s.next().unwrap().into(),\n                s.next().unwrap().into(),\n                s.next().unwrap().parse().unwrap(),\n            )\n        })\n        .collect()\n}\n\n/// Tests performance of updating the last-use timestamps in an already\n/// populated database.\n///\n/// This runs for different sizes of number of crates to update (selecting\n/// from the random sample stored on disk).\nfn global_tracker_update(c: &mut Criterion) {\n    let gctx = initialize_context();\n    let _lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)\n        .unwrap();\n    let sample = Path::new(env!(\"CARGO_MANIFEST_DIR\")).join(GLOBAL_CACHE_SAMPLE);\n    let db_path = GlobalCacheTracker::db_path(&gctx).into_path_unlocked();\n\n    let random_sample = load_random_sample();\n\n    let mut group = c.benchmark_group(\"global_tracker_update\");\n    for size in [1, 10, 100, 500] {\n        if db_path.exists() {\n            fs::remove_file(&db_path).unwrap();\n        }\n\n        fs::copy(&sample, &db_path).unwrap();\n        let mut deferred = DeferredGlobalLastUse::new();\n        let mut tracker = GlobalCacheTracker::new(&gctx).unwrap();\n        group.bench_with_input(size.to_string(), &size, |b, &size| {\n            b.iter(|| {\n                for (encoded_registry_name, name, size) in &random_sample[..size] {\n                    deferred.mark_registry_crate_used(global_cache_tracker::RegistryCrate {\n                        encoded_registry_name: *encoded_registry_name,\n                        crate_filename: format!(\"{}.crate\", name).into(),\n                        size: *size,\n                    });\n                    deferred.mark_registry_src_used(global_cache_tracker::RegistrySrc {\n                        encoded_registry_name: *encoded_registry_name,\n                        package_dir: *name,\n                        size: Some(*size),\n                    });\n                }\n                deferred.save(&mut tracker).unwrap();\n            })\n        });\n    }\n}\n\ncriterion_group!(\n    benches,\n    global_tracker_init,\n    global_tracker_empty_save,\n    global_tracker_update\n);\ncriterion_main!(benches);\n"
  },
  {
    "path": "benches/benchsuite/benches/resolve.rs",
    "content": "use benchsuite::fixtures;\nuse cargo::GlobalContext;\nuse cargo::core::compiler::{CompileKind, RustcTargetData};\nuse cargo::core::resolver::features::{FeatureOpts, FeatureResolver};\nuse cargo::core::resolver::{CliFeatures, ForceAllTargets, HasDevUnits, ResolveBehavior};\nuse cargo::core::{PackageIdSpec, Workspace};\nuse cargo::ops::WorkspaceResolve;\nuse criterion::{Criterion, criterion_group, criterion_main};\nuse std::path::Path;\n\nstruct ResolveInfo<'gctx> {\n    ws: Workspace<'gctx>,\n    requested_kinds: [CompileKind; 1],\n    target_data: RustcTargetData<'gctx>,\n    cli_features: CliFeatures,\n    specs: Vec<PackageIdSpec>,\n    has_dev_units: HasDevUnits,\n    force_all_targets: ForceAllTargets,\n    ws_resolve: WorkspaceResolve<'gctx>,\n}\n\n/// Helper for resolving a workspace. This will run the resolver once to\n/// download everything, and returns all the data structures that are used\n/// during resolution.\nfn do_resolve<'gctx>(gctx: &'gctx GlobalContext, ws_root: &Path) -> ResolveInfo<'gctx> {\n    let requested_kinds = [CompileKind::Host];\n    let ws = Workspace::new(&ws_root.join(\"Cargo.toml\"), gctx).unwrap();\n    let mut target_data = RustcTargetData::new(&ws, &requested_kinds).unwrap();\n    let cli_features = CliFeatures::from_command_line(&[], false, true).unwrap();\n    let pkgs = cargo::ops::Packages::Default;\n    let specs = pkgs.to_package_id_specs(&ws).unwrap();\n    let has_dev_units = HasDevUnits::Yes;\n    let force_all_targets = ForceAllTargets::No;\n    // Do an initial run to download anything necessary so that it does\n    // not confuse criterion's warmup.\n    let dry_run = false;\n    let ws_resolve = cargo::ops::resolve_ws_with_opts(\n        &ws,\n        &mut target_data,\n        &requested_kinds,\n        &cli_features,\n        &specs,\n        has_dev_units,\n        force_all_targets,\n        dry_run,\n    )\n    .unwrap();\n    ResolveInfo {\n        ws,\n        requested_kinds,\n        target_data,\n        cli_features,\n        specs,\n        has_dev_units,\n        force_all_targets,\n        ws_resolve,\n    }\n}\n\n/// Benchmark of the full `resolve_ws_with_opts` which runs the resolver\n/// twice, the feature resolver, and more. This is a major component of a\n/// regular cargo build.\nfn resolve_ws(c: &mut Criterion) {\n    let fixtures = fixtures!();\n    let mut group = c.benchmark_group(\"resolve_ws\");\n    for (ws_name, ws_root) in fixtures.workspaces() {\n        let gctx = fixtures.make_context(&ws_root);\n        // The resolver info is initialized only once in a lazy fashion. This\n        // allows criterion to skip this workspace if the user passes a filter\n        // on the command-line (like `cargo bench -- resolve_ws/tikv`).\n        //\n        // Due to the way criterion works, it tends to only run the inner\n        // iterator once, and we don't want to call `do_resolve` in every\n        // \"step\", since that would just be some useless work.\n        let mut lazy_info = None;\n        let dry_run = false;\n        group.bench_function(&ws_name, |b| {\n            let ResolveInfo {\n                ws,\n                requested_kinds,\n                target_data,\n                cli_features,\n                specs,\n                has_dev_units,\n                force_all_targets,\n                ..\n            } = lazy_info.get_or_insert_with(|| do_resolve(&gctx, &ws_root));\n            b.iter(|| {\n                cargo::ops::resolve_ws_with_opts(\n                    ws,\n                    target_data,\n                    requested_kinds,\n                    cli_features,\n                    specs,\n                    *has_dev_units,\n                    *force_all_targets,\n                    dry_run,\n                )\n                .unwrap();\n            })\n        });\n    }\n    group.finish();\n}\n\n/// Benchmark of the feature resolver.\nfn feature_resolver(c: &mut Criterion) {\n    let fixtures = fixtures!();\n    let mut group = c.benchmark_group(\"feature_resolver\");\n    for (ws_name, ws_root) in fixtures.workspaces() {\n        let gctx = fixtures.make_context(&ws_root);\n        let mut lazy_info = None;\n        group.bench_function(&ws_name, |b| {\n            let ResolveInfo {\n                ws,\n                requested_kinds,\n                target_data,\n                cli_features,\n                specs,\n                has_dev_units,\n                ws_resolve,\n                ..\n            } = lazy_info.get_or_insert_with(|| do_resolve(&gctx, &ws_root));\n            b.iter(|| {\n                let feature_opts = FeatureOpts::new_behavior(ResolveBehavior::V2, *has_dev_units);\n                FeatureResolver::resolve(\n                    ws,\n                    target_data,\n                    &ws_resolve.targeted_resolve,\n                    &ws_resolve.pkg_set,\n                    cli_features,\n                    specs,\n                    requested_kinds,\n                    feature_opts,\n                )\n                .unwrap();\n            })\n        });\n    }\n    group.finish();\n}\n\n// Criterion complains about the measurement time being too small, but the\n// measurement time doesn't seem important to me, what is more important is\n// the number of iterations which defaults to 100, which seems like a\n// reasonable default. Otherwise, the measurement time would need to be\n// changed per workspace. We wouldn't want to spend 60s on every workspace,\n// that would take too long and isn't necessary for the smaller workspaces.\ncriterion_group!(benches, resolve_ws, feature_resolver);\ncriterion_main!(benches);\n"
  },
  {
    "path": "benches/benchsuite/benches/workspace_initialization.rs",
    "content": "use benchsuite::fixtures;\nuse cargo::core::Workspace;\nuse criterion::{Criterion, criterion_group, criterion_main};\n\nfn workspace_initialization(c: &mut Criterion) {\n    let fixtures = fixtures!();\n    let mut group = c.benchmark_group(\"workspace_initialization\");\n    for (ws_name, ws_root) in fixtures.workspaces() {\n        let gctx = fixtures.make_context(&ws_root);\n        // The resolver info is initialized only once in a lazy fashion. This\n        // allows criterion to skip this workspace if the user passes a filter\n        // on the command-line (like `cargo bench -- workspace_initialization/tikv`).\n        group.bench_function(ws_name, |b| {\n            b.iter(|| Workspace::new(&ws_root.join(\"Cargo.toml\"), &gctx).unwrap())\n        });\n    }\n    group.finish();\n}\n\n// Criterion complains about the measurement time being too small, but the\n// measurement time doesn't seem important to me, what is more important is\n// the number of iterations which defaults to 100, which seems like a\n// reasonable default. Otherwise, the measurement time would need to be\n// changed per workspace. We wouldn't want to spend 60s on every workspace,\n// that would take too long and isn't necessary for the smaller workspaces.\ncriterion_group!(benches, workspace_initialization);\ncriterion_main!(benches);\n"
  },
  {
    "path": "benches/benchsuite/global-cache-tracker/random-sample",
    "content": "github.com-1ecc6299db9ec823,tungstenite-0.18.0,218740\ngithub.com-1ecc6299db9ec823,integer-encoding-1.1.5,30672\ngithub.com-1ecc6299db9ec823,tungstenite-0.14.0,315676\ngithub.com-1ecc6299db9ec823,oxcable-0.5.1,163196\ngithub.com-1ecc6299db9ec823,swc_ecma_transforms_typescript-0.32.0,245522\ngithub.com-1ecc6299db9ec823,hyper-0.12.35,601153\ngithub.com-1ecc6299db9ec823,resiter-0.4.0,59880\ngithub.com-1ecc6299db9ec823,net2-0.2.37,115813\ngithub.com-1ecc6299db9ec823,str_inflector-0.12.0,182460\ngithub.com-1ecc6299db9ec823,derive_builder_macro-0.10.2,16441\ngithub.com-1ecc6299db9ec823,smol_str-0.1.23,42436\ngithub.com-1ecc6299db9ec823,wasm-bindgen-multi-value-xform-0.2.83,35347\ngithub.com-1ecc6299db9ec823,time-macros-0.1.0,1620\ngithub.com-1ecc6299db9ec823,unicode-bidi-0.3.7,140153\ngithub.com-1ecc6299db9ec823,socket2-0.4.0,167295\ngithub.com-1ecc6299db9ec823,ppv-lite86-0.2.10,125234\ngithub.com-1ecc6299db9ec823,tracing-wasm-0.2.1,31449\ngithub.com-1ecc6299db9ec823,eframe-0.19.0,158130\ngithub.com-1ecc6299db9ec823,block-modes-0.7.0,42530\ngithub.com-1ecc6299db9ec823,rangemap-0.1.11,144157\ngithub.com-1ecc6299db9ec823,metal-0.23.1,1038699\ngithub.com-1ecc6299db9ec823,os_str_bytes-6.0.1,86390\ngithub.com-1ecc6299db9ec823,plotters-backend-0.3.4,53018\ngithub.com-1ecc6299db9ec823,spidev-0.4.0,45301\ngithub.com-1ecc6299db9ec823,axum-macros-0.2.3,102058\ngithub.com-1ecc6299db9ec823,embedded-time-0.12.1,246450\ngithub.com-1ecc6299db9ec823,envmnt-0.10.4,2328079\ngithub.com-1ecc6299db9ec823,camino-1.1.1,133976\ngithub.com-1ecc6299db9ec823,siphasher-0.3.5,46666\ngithub.com-1ecc6299db9ec823,lexical-write-integer-0.8.5,388374\ngithub.com-1ecc6299db9ec823,reqwest-0.11.14,686608\ngithub.com-1ecc6299db9ec823,enum-map-2.4.1,51184\ngithub.com-1ecc6299db9ec823,sentry-panic-0.29.0,18211\ngithub.com-1ecc6299db9ec823,msf-srtp-0.2.0,73164\ngithub.com-1ecc6299db9ec823,near-sandbox-utils-0.4.1,7543\ngithub.com-1ecc6299db9ec823,ablescript-0.5.2,129318\ngithub.com-1ecc6299db9ec823,apecs-derive-0.2.3,10620\ngithub.com-1ecc6299db9ec823,libc-0.2.133,3417382\ngithub.com-1ecc6299db9ec823,tracing-0.1.35,380627\ngithub.com-1ecc6299db9ec823,serde-wasm-bindgen-0.3.1,55371\ngithub.com-1ecc6299db9ec823,compiler_builtins-0.1.71,692853\ngithub.com-1ecc6299db9ec823,mockito-0.7.2,1179718\ngithub.com-1ecc6299db9ec823,tonic-0.5.2,420299\ngithub.com-1ecc6299db9ec823,tracing-core-0.1.30,240058\ngithub.com-1ecc6299db9ec823,tower-timeout-0.3.0-alpha.2,7486\ngithub.com-1ecc6299db9ec823,js-intern-0.3.1,7026\ngithub.com-1ecc6299db9ec823,json-ld-context-processing-0.12.1,78101\ngithub.com-1ecc6299db9ec823,generic-array-0.14.6,67349\ngithub.com-1ecc6299db9ec823,synstructure-0.12.3,93523\ngithub.com-1ecc6299db9ec823,version-compare-0.0.10,74950\ngithub.com-1ecc6299db9ec823,dirs-1.0.5,51075\ngithub.com-1ecc6299db9ec823,worker-kv-0.5.1,67351\ngithub.com-1ecc6299db9ec823,vsimd-0.8.0,170805\ngithub.com-1ecc6299db9ec823,mockall-0.9.1,187734\ngithub.com-1ecc6299db9ec823,nan-preserving-float-0.1.0,6341\ngithub.com-1ecc6299db9ec823,wasmer-types-2.3.0,192436\ngithub.com-1ecc6299db9ec823,sodiumoxide-0.2.7,5131115\ngithub.com-1ecc6299db9ec823,tracing-attributes-0.1.11,74857\ngithub.com-1ecc6299db9ec823,treediff-4.0.2,72588\ngithub.com-1ecc6299db9ec823,wiggle-generate-5.0.0,103044\ngithub.com-1ecc6299db9ec823,lapin-1.6.6,497368\ngithub.com-1ecc6299db9ec823,cranelift-entity-0.93.1,114206\ngithub.com-1ecc6299db9ec823,pcap-parser-0.13.3,184131\ngithub.com-1ecc6299db9ec823,rustfft-5.1.1,1638221\ngithub.com-1ecc6299db9ec823,string_cache-0.7.5,75074\ngithub.com-1ecc6299db9ec823,maybe-uninit-2.0.0,38492\ngithub.com-1ecc6299db9ec823,diesel_full_text_search-2.0.0,10179\ngithub.com-1ecc6299db9ec823,quinn-proto-0.8.4,687565\ngithub.com-1ecc6299db9ec823,semver-0.5.1,73365\ngithub.com-1ecc6299db9ec823,rocket_http-0.5.0-rc.2,409939\ngithub.com-1ecc6299db9ec823,dialoguer-0.7.1,95159\ngithub.com-1ecc6299db9ec823,fallible_collections-0.4.5,244152\ngithub.com-1ecc6299db9ec823,parking_lot_core-0.9.0,138932\ngithub.com-1ecc6299db9ec823,relative-path-1.6.0,103315\ngithub.com-1ecc6299db9ec823,lua52-sys-0.1.2,584054\ngithub.com-1ecc6299db9ec823,actix-files-0.6.0,126121\ngithub.com-1ecc6299db9ec823,crates-io-0.35.1,29498\ngithub.com-1ecc6299db9ec823,sentry-backtrace-0.19.1,20268\ngithub.com-1ecc6299db9ec823,text_unit-0.1.10,26100\ngithub.com-1ecc6299db9ec823,ascii-1.0.0,143025\ngithub.com-1ecc6299db9ec823,crossbeam-utils-0.8.6,169542\ngithub.com-1ecc6299db9ec823,nelf-0.1.0,28868\ngithub.com-1ecc6299db9ec823,colorsys-0.6.5,86989\ngithub.com-1ecc6299db9ec823,enum-iterator-1.2.0,31042\ngithub.com-1ecc6299db9ec823,ansi-str-0.7.2,111689\ngithub.com-1ecc6299db9ec823,anyhow-1.0.68,209123\ngithub.com-1ecc6299db9ec823,gix-lock-5.0.1,65110\ngithub.com-1ecc6299db9ec823,nom-supreme-0.8.0,147530\ngithub.com-1ecc6299db9ec823,path-slash-0.1.4,28655\ngithub.com-1ecc6299db9ec823,crates-io-0.35.0,29406\ngithub.com-1ecc6299db9ec823,stb_truetype-0.2.8,22939\ngithub.com-1ecc6299db9ec823,proc-macro2-1.0.50,185288\ngithub.com-1ecc6299db9ec823,snapbox-0.4.1,169526\ngithub.com-1ecc6299db9ec823,hyper-0.14.9,764075\ngithub.com-1ecc6299db9ec823,ab_glyph-0.2.15,61722\ngithub.com-1ecc6299db9ec823,uuid-0.1.18,47889\ngithub.com-1ecc6299db9ec823,data-url-0.2.0,123480\ngithub.com-1ecc6299db9ec823,threadpool-1.7.1,59558\ngithub.com-1ecc6299db9ec823,thiserror-impl-1.0.29,65149\ngithub.com-1ecc6299db9ec823,sha1-0.6.0,31102\ngithub.com-1ecc6299db9ec823,tokio-tls-0.2.1,51467\ngithub.com-1ecc6299db9ec823,locspan-derive-0.6.0,59360\ngithub.com-1ecc6299db9ec823,ureq-1.5.1,249335\ngithub.com-1ecc6299db9ec823,protoc-rust-2.24.1,13459\ngithub.com-1ecc6299db9ec823,serde-1.0.159,509060\ngithub.com-1ecc6299db9ec823,unescape-0.1.0,6047\ngithub.com-1ecc6299db9ec823,data-encoding-2.2.0,113191\ngithub.com-1ecc6299db9ec823,bytestring-1.1.0,23705\ngithub.com-1ecc6299db9ec823,ab_glyph_rasterizer-0.1.8,34773\ngithub.com-1ecc6299db9ec823,syn-0.12.15,912964\ngithub.com-1ecc6299db9ec823,reqwest-0.11.9,656209\ngithub.com-1ecc6299db9ec823,rustls-0.17.0,903717\ngithub.com-1ecc6299db9ec823,term_size-0.3.2,36226\ngithub.com-1ecc6299db9ec823,ordered-float-3.1.0,91357\ngithub.com-1ecc6299db9ec823,cookie-0.2.5,44912\ngithub.com-1ecc6299db9ec823,debugid-0.8.0,44521\ngithub.com-1ecc6299db9ec823,conrod-0.51.1,2154016\ngithub.com-1ecc6299db9ec823,indexmap-1.6.1,247801\ngithub.com-1ecc6299db9ec823,target-spec-1.3.1,68315\ngithub.com-1ecc6299db9ec823,lexical-parse-integer-0.8.6,139671\ngithub.com-1ecc6299db9ec823,time-0.1.38,131629\ngithub.com-1ecc6299db9ec823,glib-macros-0.14.1,102959\ngithub.com-1ecc6299db9ec823,metrics-macros-0.6.0,37750\ngithub.com-1ecc6299db9ec823,structopt-0.3.12,224213\ngithub.com-1ecc6299db9ec823,criterion-0.3.2,439241\ngithub.com-1ecc6299db9ec823,lyon_path-0.17.7,186745\ngithub.com-1ecc6299db9ec823,miette-5.5.0,312945\ngithub.com-1ecc6299db9ec823,tokio-codec-0.2.0-alpha.6,118193\ngithub.com-1ecc6299db9ec823,structopt-derive-0.4.14,84883\ngithub.com-1ecc6299db9ec823,objekt-0.1.2,24191\ngithub.com-1ecc6299db9ec823,sqlx-macros-0.5.7,110890\ngithub.com-1ecc6299db9ec823,systemstat-0.1.10,127295\ngithub.com-1ecc6299db9ec823,colorful-0.2.2,99698\ngithub.com-1ecc6299db9ec823,quick-xml-0.20.0,645935\ngithub.com-1ecc6299db9ec823,selinux-sys-0.6.2,27060\ngithub.com-1ecc6299db9ec823,vsmtp-mail-parser-1.4.0-rc.10,137699\ngithub.com-1ecc6299db9ec823,sec1-0.7.2,64870\ngithub.com-1ecc6299db9ec823,nix-0.22.1,1161830\ngithub.com-1ecc6299db9ec823,snow-0.9.0,2658286\ngithub.com-1ecc6299db9ec823,per_test_directory_macros-0.1.0,2962\ngithub.com-1ecc6299db9ec823,syn-helpers-0.4.3,58801\ngithub.com-1ecc6299db9ec823,terminal_size-0.2.2,29633\ngithub.com-1ecc6299db9ec823,bevy_hierarchy-0.7.0,41018\ngithub.com-1ecc6299db9ec823,dynamic_reload-0.4.0,74455\ngithub.com-1ecc6299db9ec823,http-signature-normalization-actix-0.5.0-beta.14,126857\ngithub.com-1ecc6299db9ec823,http-body-0.4.1,24138\ngithub.com-1ecc6299db9ec823,gix-index-0.13.0,207795\ngithub.com-1ecc6299db9ec823,darling_macro-0.13.1,4156\ngithub.com-1ecc6299db9ec823,serde_json-1.0.66,543072\ngithub.com-1ecc6299db9ec823,minreq-1.4.1,41355\ngithub.com-1ecc6299db9ec823,sct-0.6.1,60974\ngithub.com-1ecc6299db9ec823,openssl-0.10.50,1173941\ngithub.com-1ecc6299db9ec823,bevy_pbr-0.6.0,201163\ngithub.com-1ecc6299db9ec823,security-framework-2.3.1,290512\ngithub.com-1ecc6299db9ec823,pin-project-internal-0.4.30,128419\ngithub.com-1ecc6299db9ec823,serde_yaml-0.7.5,158524\ngithub.com-1ecc6299db9ec823,cid-0.3.2,17269\ngithub.com-1ecc6299db9ec823,plotters-backend-0.3.0,51995\ngithub.com-1ecc6299db9ec823,serde_yaml-0.8.12,179579\ngithub.com-1ecc6299db9ec823,cosmwasm-schema-derive-1.1.9,34956\ngithub.com-1ecc6299db9ec823,docopt-0.6.86,175553\ngithub.com-1ecc6299db9ec823,git-testament-0.2.4,27685\ngithub.com-1ecc6299db9ec823,htmlescape-0.3.1,143378\ngithub.com-1ecc6299db9ec823,is_proc_translated-0.1.1,16533\ngithub.com-1ecc6299db9ec823,futures-macro-0.3.4,33147\ngithub.com-1ecc6299db9ec823,futures-intrusive-0.4.2,520476\ngithub.com-1ecc6299db9ec823,rustix-0.35.13,1581355\ngithub.com-1ecc6299db9ec823,glsl-layout-0.3.2,75515\ngithub.com-1ecc6299db9ec823,darling-0.12.0,67446\ngithub.com-1ecc6299db9ec823,blake3-0.1.5,394136\ngithub.com-1ecc6299db9ec823,async-stripe-0.15.0,3157635\ngithub.com-1ecc6299db9ec823,hbs-common-sys-0.2.1,1034\ngithub.com-1ecc6299db9ec823,base58-0.1.0,7019\ngithub.com-1ecc6299db9ec823,time-0.2.23,342720\ngithub.com-1ecc6299db9ec823,memoffset-0.5.6,27595\ngithub.com-1ecc6299db9ec823,colored-1.9.3,85161\ngithub.com-1ecc6299db9ec823,lrpar-0.13.1,153317\ngithub.com-1ecc6299db9ec823,clap-2.34.0,975823\ngithub.com-1ecc6299db9ec823,chalk-engine-0.55.0,203718\ngithub.com-1ecc6299db9ec823,cosmic-space-0.3.6,800331\ngithub.com-1ecc6299db9ec823,syn-1.0.93,1886902\ngithub.com-1ecc6299db9ec823,futures-core-0.3.5,43430\ngithub.com-1ecc6299db9ec823,prost-derive-0.11.6,99428\ngithub.com-1ecc6299db9ec823,toml_edit-0.15.0,491549\ngithub.com-1ecc6299db9ec823,pcb-llvm-0.2.0,17328\ngithub.com-1ecc6299db9ec823,rusticata-macros-2.1.0,35537\ngithub.com-1ecc6299db9ec823,rustyline-with-hint-fix-10.1.0,548833\ngithub.com-1ecc6299db9ec823,sharded-slab-0.1.1,239224\ngithub.com-1ecc6299db9ec823,literally-0.1.3,20415\ngithub.com-1ecc6299db9ec823,riff-1.0.1,20582\ngithub.com-1ecc6299db9ec823,futures-macro-0.3.23,38691\ngithub.com-1ecc6299db9ec823,criterion-0.3.1,431723\ngithub.com-1ecc6299db9ec823,atty-0.2.14,14567\ngithub.com-1ecc6299db9ec823,vergen-3.1.0,49089\ngithub.com-1ecc6299db9ec823,peeking_take_while-0.1.2,18604\ngithub.com-1ecc6299db9ec823,serde_derive-1.0.156,316173\ngithub.com-1ecc6299db9ec823,geo-0.23.1,1022596\ngithub.com-1ecc6299db9ec823,persy-1.4.3,778219\ngithub.com-1ecc6299db9ec823,futures-lite-1.13.0,214632\ngithub.com-1ecc6299db9ec823,ms_dtyp-0.0.3,44387\ngithub.com-1ecc6299db9ec823,thiserror-1.0.33,66618\ngithub.com-1ecc6299db9ec823,marksman_escape-0.1.2,587235\ngithub.com-1ecc6299db9ec823,serde_derive-1.0.101,289156\ngithub.com-1ecc6299db9ec823,gix-ref-0.29.0,214105\ngithub.com-1ecc6299db9ec823,der-0.7.5,384316\ngithub.com-1ecc6299db9ec823,promptly-0.3.0,35216\ngithub.com-1ecc6299db9ec823,libc-0.2.115,3166629\ngithub.com-1ecc6299db9ec823,ppv-lite86-0.1.2,33514\ngithub.com-1ecc6299db9ec823,gfx-hal-0.6.0,254453\ngithub.com-1ecc6299db9ec823,as-slice-0.1.3,20306\ngithub.com-1ecc6299db9ec823,gpu-alloc-0.3.0,78823\ngithub.com-1ecc6299db9ec823,arc-swap-0.4.8,167950\ngithub.com-1ecc6299db9ec823,libusb1-sys-0.5.0,1458763\ngithub.com-1ecc6299db9ec823,sysinfo-0.26.8,609932\ngithub.com-1ecc6299db9ec823,refinery-macros-0.8.7,6514\ngithub.com-1ecc6299db9ec823,assert_float_eq-1.1.3,38445\ngithub.com-1ecc6299db9ec823,tinyvec-1.1.0,363582\ngithub.com-1ecc6299db9ec823,predicates-1.0.7,1168580\ngithub.com-1ecc6299db9ec823,pulldown-cmark-0.9.3,595681\ngithub.com-1ecc6299db9ec823,aws-sigv4-0.46.0,97885\ngithub.com-1ecc6299db9ec823,fastrand-1.5.0,39175\ngithub.com-1ecc6299db9ec823,futures-channel-0.3.17,131816\ngithub.com-1ecc6299db9ec823,usbd_scsi-0.1.0,172205\ngithub.com-1ecc6299db9ec823,tinyvec-1.4.0,379505\ngithub.com-1ecc6299db9ec823,structsy-0.5.1,513822\ngithub.com-1ecc6299db9ec823,aws-sdk-ssm-0.21.0,9755619\ngithub.com-1ecc6299db9ec823,pin-project-lite-0.1.1,63942\ngithub.com-1ecc6299db9ec823,tokio-rustls-0.13.0,78252\ngithub.com-1ecc6299db9ec823,tinyvec_macros-0.1.0,2912\ngithub.com-1ecc6299db9ec823,extended_matrix_float-1.0.0,6233\ngithub.com-1ecc6299db9ec823,displaydoc-0.2.3,68676\ngithub.com-1ecc6299db9ec823,typed-arena-2.0.2,43549\ngithub.com-1ecc6299db9ec823,cranelift-0.86.1,16294\ngithub.com-1ecc6299db9ec823,modular-bitfield-impl-0.10.0,64389\ngithub.com-1ecc6299db9ec823,schemafy_core-0.5.2,7696\ngithub.com-1ecc6299db9ec823,sea-orm-macros-0.8.0,86930\ngithub.com-1ecc6299db9ec823,core-foundation-sys-0.4.6,61859\ngithub.com-1ecc6299db9ec823,move-symbol-pool-0.3.2,14473\ngithub.com-1ecc6299db9ec823,glutin-0.25.1,300518\ngithub.com-1ecc6299db9ec823,postcard-cobs-0.2.0,41524\ngithub.com-1ecc6299db9ec823,quote-0.6.11,69636\ngithub.com-1ecc6299db9ec823,encoding_rs-0.8.32,5022316\ngithub.com-1ecc6299db9ec823,clap-2.32.0,946148\ngithub.com-1ecc6299db9ec823,term-0.6.1,181220\ngithub.com-1ecc6299db9ec823,enumset-1.0.12,85911\ngithub.com-1ecc6299db9ec823,ctest2-0.4.1,100745\ngithub.com-1ecc6299db9ec823,serde-xml-any-0.0.3,70554\ngithub.com-1ecc6299db9ec823,proc-macro-hack-0.5.11,39025\ngithub.com-1ecc6299db9ec823,remove_dir_all-0.5.1,23418\ngithub.com-1ecc6299db9ec823,weezl-0.1.5,134218\ngithub.com-1ecc6299db9ec823,windows_x86_64_gnullvm-0.42.1,3254874\ngithub.com-1ecc6299db9ec823,rocket-0.5.0-rc.2,1225987\ngithub.com-1ecc6299db9ec823,pin-project-0.4.27,282004\ngithub.com-1ecc6299db9ec823,criterion-cycles-per-byte-0.1.3,18296\ngithub.com-1ecc6299db9ec823,coco-0.1.1,107143\ngithub.com-1ecc6299db9ec823,solana-bloom-1.15.1,22207\ngithub.com-1ecc6299db9ec823,qoqo_calculator-1.1.1,163666\ngithub.com-1ecc6299db9ec823,aes-gcm-0.9.4,381036\ngithub.com-1ecc6299db9ec823,blowfish-0.9.1,39658\ngithub.com-1ecc6299db9ec823,pango-0.14.3,258440\ngithub.com-1ecc6299db9ec823,clap_derive-3.0.0,129105\ngithub.com-1ecc6299db9ec823,content_inspector-0.2.4,27568\ngithub.com-1ecc6299db9ec823,jsona-0.2.0,104104\ngithub.com-1ecc6299db9ec823,gix-quote-0.4.3,32314\ngithub.com-1ecc6299db9ec823,bcs-0.1.3,93194\ngithub.com-1ecc6299db9ec823,statrs-0.14.0,681982\ngithub.com-1ecc6299db9ec823,cw-controllers-0.16.0,32195\ngithub.com-1ecc6299db9ec823,hyper-0.12.36,578470\ngithub.com-1ecc6299db9ec823,argon2-0.4.1,112707\ngithub.com-1ecc6299db9ec823,fraction-0.12.2,482976\ngithub.com-1ecc6299db9ec823,quickcheck-0.7.2,89884\ngithub.com-1ecc6299db9ec823,typetag-0.1.8,135149\ngithub.com-1ecc6299db9ec823,object-0.20.0,916661\ngithub.com-1ecc6299db9ec823,pest_derive-2.2.1,60318\ngithub.com-1ecc6299db9ec823,coremidi-sys-3.1.0,40849\ngithub.com-1ecc6299db9ec823,either-1.6.0,48881\ngithub.com-1ecc6299db9ec823,tarpc-0.29.0,244416\ngithub.com-1ecc6299db9ec823,num-integer-0.1.42,88403\ngithub.com-1ecc6299db9ec823,oid-registry-0.6.0,46996\ngithub.com-1ecc6299db9ec823,historian-3.0.11,23818\ngithub.com-1ecc6299db9ec823,ui-sys-0.1.3,1784250\ngithub.com-1ecc6299db9ec823,cranelift-frontend-0.92.0,166902\ngithub.com-1ecc6299db9ec823,pin-project-lite-0.1.12,77882\ngithub.com-1ecc6299db9ec823,piston2d-gfx_graphics-0.72.0,91826\ngithub.com-1ecc6299db9ec823,stylist-macros-0.9.2,78647\ngithub.com-1ecc6299db9ec823,valico-3.4.0,1394467\ngithub.com-1ecc6299db9ec823,inventory-0.3.3,40329\ngithub.com-1ecc6299db9ec823,wrapping_arithmetic-0.1.0,8774\ngithub.com-1ecc6299db9ec823,serde-1.0.138,502921\ngithub.com-1ecc6299db9ec823,ra_common-0.1.3,16920\ngithub.com-1ecc6299db9ec823,markup5ever-0.10.0,213742\ngithub.com-1ecc6299db9ec823,libp2p-core-0.20.1,460422\ngithub.com-1ecc6299db9ec823,inout-0.1.2,40474\ngithub.com-1ecc6299db9ec823,flatbuffers-23.1.21,103944\ngithub.com-1ecc6299db9ec823,gdk-pixbuf-sys-0.10.0,42914\ngithub.com-1ecc6299db9ec823,miniz_oxide-0.5.1,223551\ngithub.com-1ecc6299db9ec823,merge-0.1.0,70214\ngithub.com-1ecc6299db9ec823,pagecache-0.6.0,260742\ngithub.com-1ecc6299db9ec823,ritelinked-0.3.2,142063\ngithub.com-1ecc6299db9ec823,ethers-contract-1.0.2,589452\ngithub.com-1ecc6299db9ec823,color_quant-1.1.0,21284\ngithub.com-1ecc6299db9ec823,libykpers-sys-0.3.1,14270\ngithub.com-1ecc6299db9ec823,cgmath-0.17.0,367702\ngithub.com-1ecc6299db9ec823,clap-4.0.18,1096299\ngithub.com-1ecc6299db9ec823,ears-0.5.1,165152\ngithub.com-1ecc6299db9ec823,h2-0.2.5,765073\ngithub.com-1ecc6299db9ec823,image-0.22.5,725576\ngithub.com-1ecc6299db9ec823,digest-0.10.1,83013\ngithub.com-1ecc6299db9ec823,js-sys-0.3.46,410849\ngithub.com-1ecc6299db9ec823,psl-types-2.0.11,25329\ngithub.com-1ecc6299db9ec823,apub-core-0.2.0,52434\ngithub.com-1ecc6299db9ec823,thiserror-1.0.22,59077\ngithub.com-1ecc6299db9ec823,num-complex-0.4.3,139539\ngithub.com-1ecc6299db9ec823,autocfg-1.0.1,41521\ngithub.com-1ecc6299db9ec823,amethyst_locale-0.15.3,4896\ngithub.com-1ecc6299db9ec823,tokio-timer-0.2.11,167147\ngithub.com-1ecc6299db9ec823,pipe-trait-0.2.1,11031\ngithub.com-1ecc6299db9ec823,http-muncher-0.3.2,259101\ngithub.com-1ecc6299db9ec823,thin-dst-1.1.0,46297\ngithub.com-1ecc6299db9ec823,float-ord-0.2.0,21145\ngithub.com-1ecc6299db9ec823,trust-dns-proto-0.21.2,1312809\ngithub.com-1ecc6299db9ec823,ordered-multimap-0.4.3,178966\ngithub.com-1ecc6299db9ec823,bitflags-0.4.0,33932\ngithub.com-1ecc6299db9ec823,windows_x86_64_gnullvm-0.42.0,3240134\ngithub.com-1ecc6299db9ec823,cargo-util-0.1.2,72189\ngithub.com-1ecc6299db9ec823,serde_with_macros-1.5.2,72325\ngithub.com-1ecc6299db9ec823,wasmer-2.3.0,529984\ngithub.com-1ecc6299db9ec823,tokio-codec-0.1.2,30428\ngithub.com-1ecc6299db9ec823,pico-args-0.5.0,54991\ngithub.com-1ecc6299db9ec823,migformatting-0.1.1,1680\ngithub.com-1ecc6299db9ec823,lexical-core-0.6.7,2382284\ngithub.com-1ecc6299db9ec823,katex-wasmbind-0.10.0,274096\ngithub.com-1ecc6299db9ec823,blender-armature-0.0.1,51371\ngithub.com-1ecc6299db9ec823,twoway-0.2.1,129719\ngithub.com-1ecc6299db9ec823,sha3-0.10.0,540582\ngithub.com-1ecc6299db9ec823,ringbuf-0.2.8,92733\ngithub.com-1ecc6299db9ec823,pest_meta-2.1.3,175833\ngithub.com-1ecc6299db9ec823,selectme-macros-0.7.1,79130\ngithub.com-1ecc6299db9ec823,secp256k1-sys-0.7.0,5303296\ngithub.com-1ecc6299db9ec823,panic-probe-0.3.0,18841\ngithub.com-1ecc6299db9ec823,ron-0.6.6,208755\ngithub.com-1ecc6299db9ec823,defmt-macros-0.3.3,78405\ngithub.com-1ecc6299db9ec823,winapi-x86_64-pc-windows-gnu-0.4.0,53158182\ngithub.com-1ecc6299db9ec823,aph-0.2.0,30088\ngithub.com-1ecc6299db9ec823,winnow-0.4.6,959730\ngithub.com-1ecc6299db9ec823,syntex_syntax-0.54.0,1272567\ngithub.com-1ecc6299db9ec823,prost-derive-0.11.9,99428\ngithub.com-1ecc6299db9ec823,commoncrypto-sys-0.2.0,16095\ngithub.com-1ecc6299db9ec823,yew-router-macro-0.15.0,42667\ngithub.com-1ecc6299db9ec823,http-range-header-0.3.0,29647\ngithub.com-1ecc6299db9ec823,crossbeam-queue-0.2.3,60131\ngithub.com-1ecc6299db9ec823,slice-deque-0.3.0,271889\ngithub.com-1ecc6299db9ec823,libc-0.2.65,2334946\ngithub.com-1ecc6299db9ec823,minidom-0.14.0,102507\ngithub.com-1ecc6299db9ec823,tokio-native-tls-0.3.0,60313\ngithub.com-1ecc6299db9ec823,glam-0.17.3,1191013\ngithub.com-1ecc6299db9ec823,semver-1.0.6,114819\ngithub.com-1ecc6299db9ec823,cortex-m-rtfm-macros-0.5.1,112048\ngithub.com-1ecc6299db9ec823,bitvec-1.0.0,1006982\ngithub.com-1ecc6299db9ec823,gfx-backend-metal-0.6.5,660301\ngithub.com-1ecc6299db9ec823,object-0.30.1,1467041\ngithub.com-1ecc6299db9ec823,proc-macro-error-attr-0.4.11,18220\ngithub.com-1ecc6299db9ec823,proteus-0.5.0,179567\ngithub.com-1ecc6299db9ec823,crunchy-0.1.6,6678\ngithub.com-1ecc6299db9ec823,once_cell-1.7.2,121632\ngithub.com-1ecc6299db9ec823,rel-0.2.0,14524\ngithub.com-1ecc6299db9ec823,lexical-core-0.7.5,2355166\ngithub.com-1ecc6299db9ec823,windows_x86_64_gnu-0.42.1,10581222\ngithub.com-1ecc6299db9ec823,thread_local-1.1.5,49409\ngithub.com-1ecc6299db9ec823,openssl-sys-0.9.63,285709\ngithub.com-1ecc6299db9ec823,simplelog-0.11.2,85170\ngithub.com-1ecc6299db9ec823,thiserror-impl-1.0.25,55249\ngithub.com-1ecc6299db9ec823,quanta-0.10.0,82241\ngithub.com-1ecc6299db9ec823,vsmtp-common-1.4.0-rc.10,122740\ngithub.com-1ecc6299db9ec823,tonic-0.1.0-alpha.6,302938\ngithub.com-1ecc6299db9ec823,ecdsa-0.16.1,121203\ngithub.com-1ecc6299db9ec823,deltae-0.3.0,2871017\ngithub.com-1ecc6299db9ec823,phf_shared-0.11.1,30454\ngithub.com-1ecc6299db9ec823,trustfall-rustdoc-adapter-22.5.2,5348192\ngithub.com-1ecc6299db9ec823,mockall_derive-0.11.0,227736\ngithub.com-1ecc6299db9ec823,wasm-bindgen-0.2.64,584320\ngithub.com-1ecc6299db9ec823,sg-std-0.12.0,27020\ngithub.com-1ecc6299db9ec823,chalk-ir-0.87.0,288472\ngithub.com-1ecc6299db9ec823,environment-0.1.1,9957\ngithub.com-1ecc6299db9ec823,crash-handler-0.3.3,125183\ngithub.com-1ecc6299db9ec823,bindgen-0.59.2,958852\ngithub.com-1ecc6299db9ec823,serde_path_to_error-0.1.7,101591\ngithub.com-1ecc6299db9ec823,tinyvec-0.3.3,77508\ngithub.com-1ecc6299db9ec823,precomputed-hash-0.1.1,2853\ngithub.com-1ecc6299db9ec823,rustc-rayon-core-0.4.1,264995\ngithub.com-1ecc6299db9ec823,gix-sec-0.6.2,57428\ngithub.com-1ecc6299db9ec823,pistoncore-input-0.19.0,83490\ngithub.com-1ecc6299db9ec823,gloo-utils-0.1.5,15602\ngithub.com-1ecc6299db9ec823,redox_intelflash-0.1.3,28056\ngithub.com-1ecc6299db9ec823,block2-0.2.0-alpha.6,39192\ngithub.com-1ecc6299db9ec823,fastly-shared-0.9.1,19292\ngithub.com-1ecc6299db9ec823,ibc-chain-registry-0.1.0,48243\ngithub.com-1ecc6299db9ec823,socket2-0.4.4,205035\ngithub.com-1ecc6299db9ec823,futures-channel-0.3.19,132274\ngithub.com-1ecc6299db9ec823,structopt-0.3.16,217443\ngithub.com-1ecc6299db9ec823,rusty-fork-0.2.2,64570\ngithub.com-1ecc6299db9ec823,parking_lot_core-0.9.7,139601\ngithub.com-1ecc6299db9ec823,async-lock-2.6.0,99844\ngithub.com-1ecc6299db9ec823,bindgen-0.56.0,923373\ngithub.com-1ecc6299db9ec823,quad-rand-0.2.1,9108\ngithub.com-1ecc6299db9ec823,wasmflow-codec-0.10.0,12343\ngithub.com-1ecc6299db9ec823,gix-0.38.0,883190\ngithub.com-1ecc6299db9ec823,futures-macro-0.3.27,38519\ngithub.com-1ecc6299db9ec823,portable-atomic-0.3.13,549649\ngithub.com-1ecc6299db9ec823,portable-atomic-1.3.2,799707\ngithub.com-1ecc6299db9ec823,bevy-crevice-derive-0.6.0,16165\ngithub.com-1ecc6299db9ec823,gltf-json-0.15.2,118263\ngithub.com-1ecc6299db9ec823,struple-impl-0.1.0,4096\ngithub.com-1ecc6299db9ec823,annotate-snippets-0.9.1,153174\ngithub.com-1ecc6299db9ec823,futures-core-0.3.28,46207\ngithub.com-1ecc6299db9ec823,wezterm-bidi-0.2.2,361283\ngithub.com-1ecc6299db9ec823,mildew-0.1.2,3002\ngithub.com-1ecc6299db9ec823,bytecount-0.6.3,46567\ngithub.com-1ecc6299db9ec823,numext-fixed-hash-core-0.1.6,7403\ngithub.com-1ecc6299db9ec823,bytesize-1.1.0,34012\ngithub.com-1ecc6299db9ec823,oxsdatatypes-0.1.0,174662\ngithub.com-1ecc6299db9ec823,hostname-0.1.5,4811\ngithub.com-1ecc6299db9ec823,io-lifetimes-1.0.4,207652\ngithub.com-1ecc6299db9ec823,derive_builder_core-0.11.2,135502\ngithub.com-1ecc6299db9ec823,ttf-parser-0.15.2,711615\ngithub.com-1ecc6299db9ec823,tracing-opentelemetry-0.17.4,187675\ngithub.com-1ecc6299db9ec823,ab_glyph_rasterizer-0.1.7,34278\ngithub.com-1ecc6299db9ec823,bevy_diagnostic-0.6.0,14396\ngithub.com-1ecc6299db9ec823,toml_datetime-0.5.0,34801\ngithub.com-1ecc6299db9ec823,wasm-parser-0.1.7,39726\ngithub.com-1ecc6299db9ec823,ppv-null-0.1.2,26098\ngithub.com-1ecc6299db9ec823,ci_info-0.10.2,1197933\ngithub.com-1ecc6299db9ec823,jobserver-0.1.21,72720\ngithub.com-1ecc6299db9ec823,sentencepiece-sys-0.10.0,10055292\ngithub.com-1ecc6299db9ec823,zstd-sys-2.0.1+zstd.1.5.2,3387955\ngithub.com-1ecc6299db9ec823,byte-strings-proc_macros-0.2.2,7886\ngithub.com-1ecc6299db9ec823,snapbox-0.4.11,193312\ngithub.com-1ecc6299db9ec823,ron-0.6.4,198516\ngithub.com-1ecc6299db9ec823,gix-object-0.28.0,102536\ngithub.com-1ecc6299db9ec823,strum_macros-0.23.1,87403\ngithub.com-1ecc6299db9ec823,defmt-0.3.2,93568\ngithub.com-1ecc6299db9ec823,openssl-0.10.35,971227\ngithub.com-1ecc6299db9ec823,gtk-sys-0.14.0,1376726\ngithub.com-1ecc6299db9ec823,gpu-alloc-0.4.7,99476\ngithub.com-1ecc6299db9ec823,colored-2.0.0,91075\ngithub.com-1ecc6299db9ec823,fixedbitset-0.4.2,67872\ngithub.com-1ecc6299db9ec823,argparse-0.2.2,95032\ngithub.com-1ecc6299db9ec823,bevy_mod_raycast-0.6.2,456756\ngithub.com-1ecc6299db9ec823,byte-strings-0.2.2,35209\ngithub.com-1ecc6299db9ec823,mem_tools-0.1.0,937956\ngithub.com-1ecc6299db9ec823,deno_core-0.167.0,11067700\ngithub.com-1ecc6299db9ec823,rocksdb-0.19.0,628015\ngithub.com-1ecc6299db9ec823,num-traits-0.2.12,231414\ngithub.com-1ecc6299db9ec823,type-info-derive-0.2.0,56221\ngithub.com-1ecc6299db9ec823,structopt-derive-0.3.4,68017\ngithub.com-1ecc6299db9ec823,extendr-macros-0.3.1,49695\ngithub.com-1ecc6299db9ec823,secret-cosmwasm-std-1.0.0,632711\ngithub.com-1ecc6299db9ec823,skim-0.7.0,380243\ngithub.com-1ecc6299db9ec823,serde-1.0.135,501463\ngithub.com-1ecc6299db9ec823,lock_api-0.1.5,109183\ngithub.com-1ecc6299db9ec823,cw-multi-test-0.16.2,445599\ngithub.com-1ecc6299db9ec823,quote-1.0.10,120640\ngithub.com-1ecc6299db9ec823,safemem-0.3.2,17382\ngithub.com-1ecc6299db9ec823,gloo-dialogs-0.1.1,4653\ngithub.com-1ecc6299db9ec823,dashmap-4.0.2,105438\ngithub.com-1ecc6299db9ec823,oorandom-11.1.0,31893\ngithub.com-1ecc6299db9ec823,polars-core-0.21.1,1678691\ngithub.com-1ecc6299db9ec823,claxon-0.4.2,259276\ngithub.com-1ecc6299db9ec823,cc-1.0.35,179169\ngithub.com-1ecc6299db9ec823,cocoa-0.19.1,296083\ngithub.com-1ecc6299db9ec823,tokio-1.9.0,2490393\ngithub.com-1ecc6299db9ec823,gix-refspec-0.10.1,105495\ngithub.com-1ecc6299db9ec823,futures-task-0.3.12,39561\ngithub.com-1ecc6299db9ec823,sqlx-core-0.4.2,1064795\ngithub.com-1ecc6299db9ec823,futures-task-0.3.14,39566\ngithub.com-1ecc6299db9ec823,datastore_grpc-0.4.0,18233399\ngithub.com-1ecc6299db9ec823,directories-4.0.1,74013\ngithub.com-1ecc6299db9ec823,wgpu-hal-0.15.1,1201034\ngithub.com-1ecc6299db9ec823,discard-1.0.4,14342\ngithub.com-1ecc6299db9ec823,tinytga-0.1.0,102322\ngithub.com-1ecc6299db9ec823,prost-types-0.10.1,126121\ngithub.com-1ecc6299db9ec823,assert2-0.3.6,36145\ngithub.com-1ecc6299db9ec823,syn-inline-mod-0.5.0,35740\ngithub.com-1ecc6299db9ec823,bat-0.22.1,5407476\ngithub.com-1ecc6299db9ec823,minidumper-child-0.1.0,32329\ngithub.com-1ecc6299db9ec823,libp2p-kad-0.21.0,416675\ngithub.com-1ecc6299db9ec823,asn1_der-0.6.3,1102166\ngithub.com-1ecc6299db9ec823,h2-0.2.4,764682\ngithub.com-1ecc6299db9ec823,ena-0.14.2,90713\ngithub.com-1ecc6299db9ec823,prost-build-0.8.0,31248726\ngithub.com-1ecc6299db9ec823,wasmer-compiler-cranelift-3.1.1,300456\ngithub.com-1ecc6299db9ec823,gfx-hal-0.7.0,238750\ngithub.com-1ecc6299db9ec823,nom-4.2.3,644514\ngithub.com-1ecc6299db9ec823,os_str_bytes-2.4.0,52159\ngithub.com-1ecc6299db9ec823,sourcemap-6.2.1,135303\ngithub.com-1ecc6299db9ec823,actix-router-0.5.1,150753\ngithub.com-1ecc6299db9ec823,markup5ever-0.9.0,229731\ngithub.com-1ecc6299db9ec823,gloo-worker-0.2.1,31624\ngithub.com-1ecc6299db9ec823,object-0.25.3,1313095\ngithub.com-1ecc6299db9ec823,rustversion-1.0.0,41602\n"
  },
  {
    "path": "benches/benchsuite/src/bin/capture-last-use.rs",
    "content": "//! Utility for capturing a global cache last-use database based on the files\n//! on a real-world system.\n//!\n//! This will look in the `CARGO_HOME` of the current system and record last-use\n//! data for all files in the cache. This is intended to provide a real-world\n//! example for a benchmark that should be close to what a real set of data\n//! should look like.\n//!\n//! See `benches/global_cache_tracker.rs` for the benchmark that uses this\n//! data.\n//!\n//! The database is kept in git. It usually shouldn't need to be re-generated\n//! unless there is a change in the schema or the benchmark.\n\nuse cargo::GlobalContext;\nuse cargo::core::global_cache_tracker::{self, DeferredGlobalLastUse, GlobalCacheTracker};\nuse cargo::util::cache_lock::CacheLockMode;\nuse rand::prelude::*;\nuse std::collections::HashMap;\nuse std::fs;\nuse std::fs::File;\nuse std::io::Write;\nuse std::path::Path;\n\nfn main() {\n    // Set up config.\n    let shell = cargo::core::Shell::new();\n    let homedir = Path::new(env!(\"CARGO_MANIFEST_DIR\")).join(\"global-cache-tracker\");\n    let cwd = homedir.clone();\n    let mut gctx = GlobalContext::new(shell, cwd, homedir.clone());\n    gctx.configure(\n        0,\n        false,\n        None,\n        false,\n        false,\n        false,\n        &None,\n        &[\"gc\".to_string()],\n        &[],\n    )\n    .unwrap();\n    let db_path = GlobalCacheTracker::db_path(&gctx).into_path_unlocked();\n    if db_path.exists() {\n        fs::remove_file(&db_path).unwrap();\n    }\n\n    let _lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)\n        .unwrap();\n    let mut deferred = DeferredGlobalLastUse::new();\n    let mut tracker = GlobalCacheTracker::new(&gctx).unwrap();\n\n    let real_home = cargo::util::homedir(&std::env::current_dir().unwrap()).unwrap();\n\n    let cache_dir = real_home.join(\"registry/cache\");\n    for dir_ent in fs::read_dir(cache_dir).unwrap() {\n        let registry = dir_ent.unwrap();\n        let encoded_registry_name = registry.file_name().to_string_lossy().into();\n        for krate in fs::read_dir(registry.path()).unwrap() {\n            let krate = krate.unwrap();\n            let meta = krate.metadata().unwrap();\n            deferred.mark_registry_crate_used_stamp(\n                global_cache_tracker::RegistryCrate {\n                    encoded_registry_name,\n                    crate_filename: krate.file_name().to_string_lossy().as_ref().into(),\n                    size: meta.len(),\n                },\n                Some(&meta.modified().unwrap()),\n            );\n        }\n    }\n\n    let mut src_entries = Vec::new();\n\n    let cache_dir = real_home.join(\"registry/src\");\n    for dir_ent in fs::read_dir(cache_dir).unwrap() {\n        let registry = dir_ent.unwrap();\n        let encoded_registry_name = registry.file_name().to_string_lossy().into();\n        for krate in fs::read_dir(registry.path()).unwrap() {\n            let krate = krate.unwrap();\n            let meta = krate.metadata().unwrap();\n            let src = global_cache_tracker::RegistrySrc {\n                encoded_registry_name,\n                package_dir: krate.file_name().to_string_lossy().as_ref().into(),\n                size: Some(cargo_util::du(&krate.path(), &[]).unwrap()),\n            };\n            src_entries.push(src.clone());\n            let timestamp = meta.modified().unwrap();\n            deferred.mark_registry_src_used_stamp(src, Some(&timestamp));\n        }\n    }\n\n    let git_co_dir = real_home.join(\"git/checkouts\");\n    for dir_ent in fs::read_dir(git_co_dir).unwrap() {\n        let git_source = dir_ent.unwrap();\n        let encoded_git_name = git_source.file_name().to_string_lossy().into();\n        for co in fs::read_dir(git_source.path()).unwrap() {\n            let co = co.unwrap();\n            let meta = co.metadata().unwrap();\n            deferred.mark_git_checkout_used_stamp(\n                global_cache_tracker::GitCheckout {\n                    encoded_git_name,\n                    short_name: co.file_name().to_string_lossy().as_ref().into(),\n                    size: Some(cargo_util::du(&co.path(), &[]).unwrap()),\n                },\n                Some(&meta.modified().unwrap()),\n            );\n        }\n    }\n\n    deferred.save(&mut tracker).unwrap();\n    drop(deferred);\n    drop(tracker);\n    fs::rename(&db_path, homedir.join(\"global-cache-sample\")).unwrap();\n    // Clean up the lock file created above.\n    fs::remove_file(homedir.join(\".package-cache\")).unwrap();\n\n    // Save a random sample of crates that the benchmark should update.\n    // Pick whichever registry has the most entries. This is to be somewhat\n    // realistic for the common case that all dependencies come from one\n    // registry (crates.io).\n    let mut counts = HashMap::new();\n    for src in &src_entries {\n        let c: &mut u32 = counts.entry(src.encoded_registry_name).or_default();\n        *c += 1;\n    }\n    let mut counts: Vec<_> = counts.into_iter().map(|(k, v)| (v, k)).collect();\n    counts.sort();\n    let biggest = counts.last().unwrap().1;\n\n    src_entries.retain(|src| src.encoded_registry_name == biggest);\n    let mut rng = &mut rand::rng();\n    let sample: Vec<_> = src_entries.sample(&mut rng, 500).collect();\n    let mut f = File::create(homedir.join(\"random-sample\")).unwrap();\n    for src in sample {\n        writeln!(\n            f,\n            \"{},{},{}\",\n            src.encoded_registry_name,\n            src.package_dir,\n            src.size.unwrap()\n        )\n        .unwrap();\n    }\n}\n"
  },
  {
    "path": "benches/benchsuite/src/lib.rs",
    "content": "//! > This crate is maintained by the Cargo team, primarily for use by Cargo\n//! > and not intended for external use. This\n//! > crate may make major changes to its APIs or be deprecated without warning.\n\n#![allow(clippy::disallowed_methods)]\n\nuse cargo::GlobalContext;\nuse std::fs;\nuse std::path::{Path, PathBuf};\nuse std::process::Command;\nuse url::Url;\n\n#[macro_export]\nmacro_rules! fixtures {\n    () => {\n        $crate::Fixtures::new(env!(\"CARGO_TARGET_TMPDIR\"))\n    };\n}\n\n// This is an arbitrary commit that existed when I started. This helps\n// ensure consistent results. It can be updated if needed, but that can\n// make it harder to compare results with older versions of cargo.\nconst CRATES_IO_COMMIT: &str = \"85f7bfd61ea4fee08ec68c468762e886b2aebec6\";\n\npub struct Fixtures {\n    cargo_target_tmpdir: PathBuf,\n}\n\nimpl Fixtures {\n    pub fn new(cargo_target_tmpdir: &str) -> Self {\n        let bench = Self {\n            cargo_target_tmpdir: PathBuf::from(cargo_target_tmpdir),\n        };\n        bench.create_home();\n        bench.create_target_dir();\n        bench.clone_index();\n        bench.unpack_workspaces();\n        bench\n    }\n\n    fn root(&self) -> PathBuf {\n        self.cargo_target_tmpdir.join(\"bench\")\n    }\n\n    fn target_dir(&self) -> PathBuf {\n        let mut p = self.root();\n        p.push(\"target\");\n        p\n    }\n\n    fn cargo_home(&self) -> PathBuf {\n        let mut p = self.root();\n        p.push(\"chome\");\n        p\n    }\n\n    fn index(&self) -> PathBuf {\n        let mut p = self.root();\n        p.push(\"index\");\n        p\n    }\n\n    fn workspaces_path(&self) -> PathBuf {\n        let mut p = self.root();\n        p.push(\"workspaces\");\n        p\n    }\n\n    fn registry_url(&self) -> Url {\n        Url::from_file_path(self.index()).unwrap()\n    }\n\n    fn create_home(&self) {\n        let home = self.cargo_home();\n        if !home.exists() {\n            fs::create_dir_all(&home).unwrap();\n        }\n        fs::write(\n            home.join(\"config.toml\"),\n            format!(\n                r#\"\n                [source.crates-io]\n                replace-with = 'local-snapshot'\n\n                [source.local-snapshot]\n                registry = '{}'\n            \"#,\n                self.registry_url()\n            ),\n        )\n        .unwrap();\n    }\n\n    fn create_target_dir(&self) {\n        // This is necessary to ensure the .rustc_info.json file is written.\n        // Otherwise it won't be written, and it is very expensive to create.\n        if !self.target_dir().exists() {\n            fs::create_dir_all(self.target_dir()).unwrap();\n        }\n    }\n\n    /// This clones crates.io at a specific point in time into tmp/index.\n    fn clone_index(&self) {\n        let index = self.index();\n        let maybe_git = |command: &str| {\n            let status = Command::new(\"git\")\n                .current_dir(&index)\n                .args(command.split_whitespace().collect::<Vec<_>>())\n                .status()\n                .expect(\"git should be installed\");\n            status.success()\n        };\n        let git = |command: &str| {\n            if !maybe_git(command) {\n                panic!(\"failed to run git command: {}\", command);\n            }\n        };\n        if index.exists() {\n            if maybe_git(&format!(\n                \"rev-parse -q --verify {}^{{commit}}\",\n                CRATES_IO_COMMIT\n            )) {\n                // Already fetched.\n                return;\n            }\n        } else {\n            fs::create_dir_all(&index).unwrap();\n            // git 2.48.0 changed the behavior of setting HEAD when doing a\n            // fetch, so let's just force it to match\n            // crates.io-index-archive's default branch. This also accounts\n            // for users who may override init.defaultBranch.\n            git(\"init --bare --initial-branch=main\");\n            git(\"remote add origin https://github.com/rust-lang/crates.io-index-archive\");\n        }\n        git(&format!(\"fetch origin {}\", CRATES_IO_COMMIT));\n        git(\"branch -f main FETCH_HEAD\");\n    }\n\n    /// This unpacks the compressed workspace skeletons into tmp/workspaces.\n    fn unpack_workspaces(&self) {\n        let ws_dir = Path::new(env!(\"CARGO_MANIFEST_DIR\"))\n            .parent()\n            .unwrap()\n            .join(\"workspaces\");\n        let archives = fs::read_dir(ws_dir)\n            .unwrap()\n            .map(|e| e.unwrap().path())\n            .filter(|p| p.extension() == Some(std::ffi::OsStr::new(\"tgz\")));\n        for archive in archives {\n            let name = archive.file_stem().unwrap();\n            let f = fs::File::open(&archive).unwrap();\n            let f = flate2::read::GzDecoder::new(f);\n            let dest = self.workspaces_path().join(&name);\n            if dest.exists() {\n                fs::remove_dir_all(&dest).unwrap();\n            }\n            let mut archive = tar::Archive::new(f);\n            archive.unpack(self.workspaces_path()).unwrap();\n        }\n    }\n\n    /// Vec of `(ws_name, ws_root)`.\n    pub fn workspaces(&self) -> Vec<(String, PathBuf)> {\n        // CARGO_BENCH_WORKSPACES can be used to override, otherwise it just uses\n        // the workspaces in the workspaces directory.\n        let mut ps: Vec<_> = match std::env::var_os(\"CARGO_BENCH_WORKSPACES\") {\n            Some(s) => std::env::split_paths(&s).collect(),\n            None => fs::read_dir(self.workspaces_path())\n                .unwrap()\n                .map(|e| e.unwrap().path())\n                // These currently fail in most cases on Windows due to long\n                // filenames in the git checkouts.\n                .filter(|p| {\n                    !(cfg!(windows)\n                        && matches!(p.file_name().unwrap().to_str().unwrap(), \"servo\" | \"tikv\"))\n                })\n                .collect(),\n        };\n        // Sort so it is consistent.\n        ps.sort();\n        ps.into_iter()\n            .map(|p| (p.file_name().unwrap().to_str().unwrap().to_owned(), p))\n            .collect()\n    }\n\n    /// Creates a new Context.\n    pub fn make_context(&self, ws_root: &Path) -> GlobalContext {\n        let shell = cargo::core::Shell::new();\n        let mut gctx = GlobalContext::new(shell, ws_root.to_path_buf(), self.cargo_home());\n        // Configure is needed to set the target_dir which is needed to write\n        // the .rustc_info.json file which is very expensive.\n        gctx.configure(\n            0,\n            false,\n            None,\n            false,\n            false,\n            false,\n            &Some(self.target_dir()),\n            &[],\n            &[],\n        )\n        .unwrap();\n        gctx\n    }\n}\n"
  },
  {
    "path": "benches/capture/Cargo.toml",
    "content": "[package]\nname = \"capture\"\nversion = \"0.1.0\"\nedition.workspace = true\nlicense.workspace = true\ndescription = \"Tool for capturing a real-world workspace for benchmarking.\"\npublish = false\n\n[dependencies]\ncargo_metadata.workspace = true\nflate2.workspace = true\ntar.workspace = true\ntoml = { workspace = true, features = [\"display\", \"parse\", \"serde\"] }\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "benches/capture/src/main.rs",
    "content": "//! This tool helps to capture the `Cargo.toml` files of a workspace.\n//!\n//! Run it by passing a list of workspaces to capture.\n//! Use the `-f` flag to allow it to overwrite existing captures.\n//! The workspace will be saved in a `.tgz` file in the `../workspaces` directory.\n\n#![allow(clippy::disallowed_methods)]\n#![allow(clippy::print_stderr)]\n\nuse flate2::{Compression, GzBuilder};\nuse std::fs;\nuse std::path::{Path, PathBuf};\nuse std::process::Command;\n\nfn main() {\n    let force = std::env::args().any(|arg| arg == \"-f\");\n    let dest = Path::new(env!(\"CARGO_MANIFEST_DIR\"))\n        .parent()\n        .unwrap()\n        .join(\"workspaces\");\n    if !dest.exists() {\n        panic!(\"expected {} to exist\", dest.display());\n    }\n    for arg in std::env::args().skip(1).filter(|arg| !arg.starts_with(\"-\")) {\n        let source_root = fs::canonicalize(arg).unwrap();\n        capture(&source_root, &dest, force);\n    }\n}\n\nfn capture(source_root: &Path, dest: &Path, force: bool) {\n    let name = Path::new(source_root.file_name().unwrap());\n    let mut dest_gz = PathBuf::from(dest);\n    dest_gz.push(name);\n    dest_gz.set_extension(\"tgz\");\n    if dest_gz.exists() {\n        if !force {\n            panic!(\n                \"dest {:?} already exists, use -f to force overwriting\",\n                dest_gz\n            );\n        }\n        fs::remove_file(&dest_gz).unwrap();\n    }\n    let vcs_info = capture_vcs_info(source_root, force);\n    let dst = fs::File::create(&dest_gz).unwrap();\n    let encoder = GzBuilder::new()\n        .filename(format!(\"{}.tar\", name.to_str().unwrap()))\n        .write(dst, Compression::best());\n    let mut ar = tar::Builder::new(encoder);\n    ar.mode(tar::HeaderMode::Deterministic);\n    if let Some(info) = &vcs_info {\n        add_ar_file(&mut ar, &name.join(\".cargo_vcs_info.json\"), info);\n    }\n\n    // Gather all local packages.\n    let metadata = cargo_metadata::MetadataCommand::new()\n        .manifest_path(source_root.join(\"Cargo.toml\"))\n        .features(cargo_metadata::CargoOpt::AllFeatures)\n        .exec()\n        .expect(\"cargo_metadata failed\");\n    let mut found_root = false;\n    for package in &metadata.packages {\n        if package.source.is_some() {\n            continue;\n        }\n        let manifest_path = package.manifest_path.as_std_path();\n        copy_manifest(&manifest_path, &mut ar, name, &source_root);\n        found_root |= manifest_path == source_root.join(\"Cargo.toml\");\n    }\n    if !found_root {\n        // A virtual workspace.\n        let contents = fs::read_to_string(source_root.join(\"Cargo.toml\")).unwrap();\n        assert!(!contents.contains(\"[package]\"));\n        add_ar_file(&mut ar, &name.join(\"Cargo.toml\"), &contents);\n    }\n    let lock = fs::read_to_string(source_root.join(\"Cargo.lock\")).unwrap();\n    add_ar_file(&mut ar, &name.join(\"Cargo.lock\"), &lock);\n    let encoder = ar.into_inner().unwrap();\n    encoder.finish().unwrap();\n    eprintln!(\"created {}\", dest_gz.display());\n}\n\nfn copy_manifest<W: std::io::Write>(\n    manifest_path: &Path,\n    ar: &mut tar::Builder<W>,\n    name: &Path,\n    source_root: &Path,\n) {\n    let relative_path = manifest_path\n        .parent()\n        .unwrap()\n        .strip_prefix(source_root)\n        .expect(\"workspace member should be under workspace root\");\n    let relative_path = name.join(relative_path);\n    let contents = fs::read_to_string(&manifest_path).unwrap();\n    let mut manifest: toml::Value = toml::from_str(&contents).unwrap();\n    let remove = |obj: &mut toml::Value, name| {\n        let table = obj.as_table_mut().unwrap();\n        if table.contains_key(name) {\n            table.remove(name);\n        }\n    };\n    remove(&mut manifest, \"lib\");\n    remove(&mut manifest, \"bin\");\n    remove(&mut manifest, \"example\");\n    remove(&mut manifest, \"test\");\n    remove(&mut manifest, \"bench\");\n    remove(&mut manifest, \"profile\");\n    if let Some(package) = manifest.get_mut(\"package\") {\n        remove(package, \"default-run\");\n    }\n    let contents = toml::to_string(&manifest).unwrap();\n    add_ar_file(ar, &relative_path.join(\"Cargo.toml\"), &contents);\n    add_ar_file(ar, &relative_path.join(\"src\").join(\"lib.rs\"), \"\");\n}\n\nfn add_ar_file<W: std::io::Write>(ar: &mut tar::Builder<W>, path: &Path, contents: &str) {\n    let mut header = tar::Header::new_gnu();\n    header.set_entry_type(tar::EntryType::file());\n    header.set_mode(0o644);\n    header.set_size(contents.len() as u64);\n    header.set_mtime(123456789);\n    header.set_cksum();\n    ar.append_data(&mut header, path, contents.as_bytes())\n        .unwrap();\n}\n\nfn capture_vcs_info(ws_root: &Path, force: bool) -> Option<String> {\n    let maybe_git = |command: &str| {\n        Command::new(\"git\")\n            .current_dir(ws_root)\n            .args(command.split_whitespace().collect::<Vec<_>>())\n            .output()\n            .expect(\"git should be installed\")\n    };\n    assert!(ws_root.join(\"Cargo.toml\").exists());\n    let relative = maybe_git(\"ls-files --full-name Cargo.toml\");\n    if !relative.status.success() {\n        if !force {\n            panic!(\"git repository not detected, use -f to force\");\n        }\n        return None;\n    }\n    let p = Path::new(std::str::from_utf8(&relative.stdout).unwrap().trim());\n    let relative = p.parent().unwrap();\n    if !force {\n        let has_changes = !maybe_git(\"diff-index --quiet HEAD .\").status.success();\n        if has_changes {\n            panic!(\"git repo appears to have changes, use -f to force, or clean the repo\");\n        }\n    }\n    let commit = maybe_git(\"rev-parse HEAD\");\n    assert!(commit.status.success());\n    let commit = std::str::from_utf8(&commit.stdout).unwrap().trim();\n    let remote = maybe_git(\"remote get-url origin\");\n    assert!(remote.status.success());\n    let remote = std::str::from_utf8(&remote.stdout).unwrap().trim();\n    let info = format!(\n        \"{{\\n  \\\"git\\\": {{\\n    \\\"sha1\\\": \\\"{}\\\",\\n     \\\"remote\\\": \\\"{}\\\"\\n  }},\\\n         \\n  \\\"path_in_vcs\\\": \\\"{}\\\"\\n}}\\n\",\n        commit,\n        remote,\n        relative.display()\n    );\n    eprintln!(\"recording vcs info:\\n{}\", info);\n    Some(info)\n}\n"
  },
  {
    "path": "build.rs",
    "content": "use flate2::{Compression, GzBuilder};\nuse std::ffi::OsStr;\nuse std::fs;\nuse std::path::Path;\nuse std::process::Command;\n\nfn main() {\n    commit_info();\n    compress_man();\n    windows_manifest();\n    #[expect(\n        clippy::disallowed_methods,\n        reason = \"not `cargo`, not needing to load from config\"\n    )]\n    let target = std::env::var(\"TARGET\").unwrap();\n    println!(\"cargo:rustc-env=RUST_HOST_TARGET={target}\");\n}\n\nfn compress_man() {\n    #[expect(\n        clippy::disallowed_methods,\n        reason = \"not `cargo`, not needing to load from config\"\n    )]\n    let out_path = Path::new(&std::env::var(\"OUT_DIR\").unwrap()).join(\"man.tgz\");\n    let dst = fs::File::create(out_path).unwrap();\n    let encoder = GzBuilder::new()\n        .filename(\"man.tar\")\n        .write(dst, Compression::best());\n    let mut ar = tar::Builder::new(encoder);\n    ar.mode(tar::HeaderMode::Deterministic);\n\n    let mut add_files = |dir, extension| {\n        let mut files = fs::read_dir(dir)\n            .unwrap()\n            .map(|e| e.unwrap().path())\n            .collect::<Vec<_>>();\n        files.sort();\n        for path in files {\n            if path.extension() != Some(extension) {\n                continue;\n            }\n            println!(\"cargo:rerun-if-changed={}\", path.display());\n            ar.append_path_with_name(&path, path.file_name().unwrap())\n                .unwrap();\n        }\n    };\n\n    add_files(Path::new(\"src/etc/man\"), OsStr::new(\"1\"));\n    add_files(Path::new(\"src/doc/man/generated_txt\"), OsStr::new(\"txt\"));\n    let encoder = ar.into_inner().unwrap();\n    encoder.finish().unwrap();\n}\n\nstruct CommitInfo {\n    hash: String,\n    short_hash: String,\n    date: String,\n}\n\nfn commit_info_from_git() -> Option<CommitInfo> {\n    if !Path::new(\".git\").exists() {\n        return None;\n    }\n\n    let output = match Command::new(\"git\")\n        .arg(\"log\")\n        .arg(\"-1\")\n        .arg(\"--date=short\")\n        .arg(\"--format=%H %h %cd\")\n        .arg(\"--abbrev=9\")\n        .output()\n    {\n        Ok(output) if output.status.success() => output,\n        _ => return None,\n    };\n\n    let stdout = String::from_utf8(output.stdout).unwrap();\n    let mut parts = stdout.split_whitespace().map(|s| s.to_string());\n\n    Some(CommitInfo {\n        hash: parts.next()?,\n        short_hash: parts.next()?,\n        date: parts.next()?,\n    })\n}\n\n// The rustc source tarball is meant to contain all the source code to build an exact copy of the\n// toolchain, but it doesn't include the git repository itself. It wouldn't thus be possible to\n// populate the version information with the commit hash and the commit date.\n//\n// To work around this, the rustc build process obtains the git information when creating the\n// source tarball and writes it to the `git-commit-info` file. The build process actually creates\n// at least *two* of those files, one for Rust as a whole (in the root of the tarball) and one\n// specifically for Cargo (in src/tools/cargo). This function loads that file.\n//\n// The file is a newline-separated list of full commit hash, short commit hash, and commit date.\nfn commit_info_from_rustc_source_tarball() -> Option<CommitInfo> {\n    let path = Path::new(\"git-commit-info\");\n    if !path.exists() {\n        return None;\n    }\n\n    // Dependency tracking is a nice to have for this (git doesn't do it), so if the path is not\n    // valid UTF-8 just avoid doing it rather than erroring out.\n    if let Some(utf8) = path.to_str() {\n        println!(\"cargo:rerun-if-changed={utf8}\");\n    }\n\n    let content = std::fs::read_to_string(&path).ok()?;\n    let mut parts = content.split('\\n').map(|s| s.to_string());\n    Some(CommitInfo {\n        hash: parts.next()?,\n        short_hash: parts.next()?,\n        date: parts.next()?,\n    })\n}\n\nfn commit_info() {\n    // Var set by bootstrap whenever omit-git-hash is enabled in rust-lang/rust's config.toml.\n    println!(\"cargo:rerun-if-env-changed=CFG_OMIT_GIT_HASH\");\n    #[expect(\n        clippy::disallowed_methods,\n        reason = \"not `cargo`, not needing to load from config\"\n    )]\n    if std::env::var_os(\"CFG_OMIT_GIT_HASH\").is_some() {\n        return;\n    }\n\n    let Some(git) = commit_info_from_git().or_else(commit_info_from_rustc_source_tarball) else {\n        return;\n    };\n\n    println!(\"cargo:rustc-env=CARGO_COMMIT_HASH={}\", git.hash);\n    println!(\"cargo:rustc-env=CARGO_COMMIT_SHORT_HASH={}\", git.short_hash);\n    println!(\"cargo:rustc-env=CARGO_COMMIT_DATE={}\", git.date);\n}\n\n#[expect(\n    clippy::disallowed_methods,\n    reason = \"not `cargo`, not needing to load from config\"\n)]\nfn windows_manifest() {\n    use std::env;\n    let target_os = env::var(\"CARGO_CFG_TARGET_OS\");\n    let target_env = env::var(\"CARGO_CFG_TARGET_ENV\");\n    if Ok(\"windows\") == target_os.as_deref() && Ok(\"msvc\") == target_env.as_deref() {\n        static WINDOWS_MANIFEST_FILE: &str = \"windows.manifest.xml\";\n\n        let mut manifest = env::current_dir().unwrap();\n        manifest.push(WINDOWS_MANIFEST_FILE);\n\n        println!(\"cargo:rerun-if-changed={WINDOWS_MANIFEST_FILE}\");\n        // Embed the Windows application manifest file.\n        println!(\"cargo:rustc-link-arg-bin=cargo=/MANIFEST:EMBED\");\n        println!(\n            \"cargo:rustc-link-arg-bin=cargo=/MANIFESTINPUT:{}\",\n            manifest.to_str().unwrap()\n        );\n        // Turn linker warnings into errors.\n        println!(\"cargo:rustc-link-arg-bin=cargo=/WX\");\n    }\n}\n"
  },
  {
    "path": "ci/clean-test-output.sh",
    "content": "#!/bin/bash\n# This script remove test and benchmark output and displays disk usage.\n\nset -euo pipefail\n\ndf -h\nrm -rf target/tmp\ndf -h\n"
  },
  {
    "path": "ci/dump-environment.sh",
    "content": "#!/bin/bash\n# This script dumps information about the build environment to stdout.\n\nset -euo pipefail\nIFS=$'\\n\\t'\n\necho \"environment variables:\"\nprintenv | sort\necho\n\necho \"disk usage:\"\ndf -h\necho\n\necho \"CPU info:\"\nif [[ \"${OSTYPE}\" = \"darwin\"* ]]; then\n    system_profiler SPHardwareDataType || true\n    sysctl hw || true\nelse\n    cat /proc/cpuinfo || true\n    cat /proc/meminfo || true\nfi\n"
  },
  {
    "path": "ci/fetch-smoke-test.sh",
    "content": "#!/bin/bash\n# This script builds with static curl, and verifies that fetching works.\n\nset -ex\n\nif [[ -z \"$RUNNER_TEMP\" ]]\nthen\n    echo \"RUNNER_TEMP must be set\"\n    exit 1\nfi\n\nif [ ! -f Cargo.toml ]; then\n    echo \"Must be run from root of project.\"\n    exit 1\nfi\n\n\n# Building openssl on Windows is a pain.\nif [[ $(rustc -Vv | grep host:) != *windows* ]]; then\n    FEATURES='vendored-openssl,curl-sys/static-curl,curl-sys/force-system-lib-on-osx'\n    export LIBZ_SYS_STATIC=1\nfi\n\ncargo build --features \"$FEATURES\"\nexport CARGO_HOME=$RUNNER_TEMP/chome\ntarget/debug/cargo fetch\nrm -rf $CARGO_HOME\n"
  },
  {
    "path": "ci/generate.py",
    "content": "#!/usr/bin/env python3\n\nMAPPING = {\n    \"build-script.html\": \"https://doc.rust-lang.org/cargo/reference/build-scripts.html\",\n    \"config.html\": None,\n    \"crates-io.html\": \"https://doc.rust-lang.org/cargo/reference/publishing.html\",\n    \"environment-variables.html\": None,\n    \"external-tools.html\": None,\n    \"faq.html\": \"https://doc.rust-lang.org/cargo/faq.html\",\n    \"guide.html\": \"https://doc.rust-lang.org/cargo/guide/\",\n    \"index.html\": \"https://doc.rust-lang.org/cargo/\",\n    \"manifest.html\": None,\n    \"pkgid-spec.html\": None,\n    \"policies.html\": \"https://crates.io/policies\",\n    \"source-replacement.html\": None,\n    \"specifying-dependencies.html\": None,\n}\n\nTEMPLATE = \"\"\"\\\n<html>\n<head>\n<meta http-equiv=\"refresh\" content=\"0; url={mapped}\" />\n<script>\nwindow.location.replace(\"{mapped}\" + window.location.hash);\n</script>\n<title>Page Moved</title>\n</head>\n<body>\nThis page has moved. Click <a href=\"{mapped}\">here</a> to go to the new page.\n</body>\n</html>\n\"\"\"\n\ndef main():\n    for name in sorted(MAPPING):\n        with open(name, 'w') as f:\n            mapped = MAPPING[name]\n            if mapped is None:\n                mapped = \"https://doc.rust-lang.org/cargo/reference/{}\".format(name)\n            f.write(TEMPLATE.format(name=name, mapped=mapped))\n\n    # WARN: The CNAME file is for GitHub to redirect requests to the custom domain.\n    # Missing this may entail security hazard and domain takeover.\n    # See <https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/managing-a-custom-domain-for-your-github-pages-site#securing-your-custom-domain>\n    with open('CNAME', 'w') as f:\n        f.write('doc.crates.io')\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "ci/validate-man.sh",
    "content": "#!/bin/bash\n# This script validates that there aren't any changes to the man pages.\n\nset -e\n\ncargo_man=\"src/doc\"\nmdman_man=\"crates/mdman/doc\"\nman_out=\"src/etc/man\"\n\nchanges=$(git status --porcelain -- $cargo_man $mdman_man $man_out)\nif [ -n \"$changes\" ]\nthen\n    echo \"git directory must be clean before running this script.\"\n    exit 1\nfi\n\ncargo build-man\n\nchanges=$(git status --porcelain -- $cargo_man $mdman_man $man_out)\nif [ -n \"$changes\" ]\nthen\n    echo \"Detected changes of man pages:\"\n    echo \"$changes\"\n    echo\n    echo 'Please run `cargo build-man` to rebuild the man pages'\n    echo \"and commit the changes.\"\n    exit 1\nfi\n"
  },
  {
    "path": "ci/validate-version-bump.sh",
    "content": "#!/bin/bash\n# This script checks if a crate needs a version bump.\n#\n# At the time of writing, it doesn't check what kind of bump is required.\n# In the future, we could take SemVer compatibility into account, like\n# integrating `cargo-semver-checks` of else\n#\n# Inputs:\n#     BASE_SHA    The commit SHA of the branch where the PR wants to merge into.\n#     HEAD_SHA    The commit SHA that triggered the workflow.\n\nset -euo pipefail\n\n# When `BASE_SHA` is missing, we assume it is from GitHub merge queue merge commit,\n# so hope `HEAD~` to find the previous commit on master branch.\nbase_sha=$(git rev-parse \"${BASE_SHA:-HEAD~1}\")\nhead_sha=$(git rev-parse \"${HEAD_SHA:-HEAD}\")\n\necho \"Base revision is $base_sha\"\necho \"Head revision is $head_sha\"\n\necho \"::group::Building xtask\"\ncargo bump-check --help\necho \"::endgroup::\"\ncargo bump-check --github --base-rev \"$base_sha\" --head-rev \"$head_sha\"\n"
  },
  {
    "path": "clippy.toml",
    "content": "allow-print-in-tests = true\nallow-dbg-in-tests = true\ndisallowed-methods = [\n    { path = \"std::env::var\", reason = \"use `Config::get_env` instead. See rust-lang/cargo#11588\" },\n    { path = \"std::env::var_os\", reason = \"use `Config::get_env_os` instead. See rust-lang/cargo#11588\" },\n    { path = \"std::env::vars\", reason = \"not recommended to use in Cargo. See rust-lang/cargo#11588\" },\n    { path = \"std::env::vars_os\", reason = \"not recommended to use in Cargo. See rust-lang/cargo#11588\" },\n]\ndisallowed-types = [\n    { path = \"std::sync::atomic::AtomicU64\", reason = \"not portable. See rust-lang/cargo#12988\" },\n]\n"
  },
  {
    "path": "crates/build-rs/Cargo.toml",
    "content": "[package]\nname = \"build-rs\"\nversion = \"0.3.4\"\nrust-version.workspace = true\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"API for writing Cargo `build.rs` files\"\n\n[features]\n## Experimental API. This feature flag is **NOT** semver stable.\nunstable = []\n\n[dependencies]\nunicode-ident.workspace = true\n"
  },
  {
    "path": "crates/build-rs/README.md",
    "content": "> This crate is maintained by the Cargo team for use by the wider\n> ecosystem. This crate follows semver compatibility for its APIs.\n"
  },
  {
    "path": "crates/build-rs/src/ident.rs",
    "content": "use unicode_ident::{is_xid_continue, is_xid_start};\n\npub(crate) fn is_feature_name(s: &str) -> bool {\n    s.chars()\n        .all(|ch| is_xid_continue(ch) || matches!(ch, '-' | '+' | '.'))\n}\n\npub(crate) fn is_ident(s: &str) -> bool {\n    let mut cs = s.chars();\n    cs.next()\n        .is_some_and(|ch| is_xid_start(ch) || matches!(ch, '_'))\n        && cs.all(is_xid_continue)\n}\n\npub(crate) fn is_ascii_ident(s: &str) -> bool {\n    let mut cs = s.chars();\n    cs.next()\n        .is_some_and(|ch| ch.is_ascii_alphabetic() || matches!(ch, '_'))\n        && cs.all(|ch| ch.is_ascii_alphanumeric() || matches!(ch, '_'))\n}\n\npub(crate) fn is_crate_name(s: &str) -> bool {\n    let mut cs = s.chars();\n    cs.next()\n        .is_some_and(|ch| is_xid_start(ch) || matches!(ch, '-' | '_'))\n        && cs.all(|ch| is_xid_continue(ch) || matches!(ch, '-'))\n}\n"
  },
  {
    "path": "crates/build-rs/src/input.rs",
    "content": "//! Inputs from the build system to the build script.\n//!\n//! This crate does not do any caching or interpreting of the values provided by\n//! Cargo beyond the communication protocol itself. It is up to the build script\n//! to interpret the string values and decide what to do with them.\n//!\n//! Reference: <https://doc.rust-lang.org/stable/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>\n\nuse std::path::PathBuf;\n\nuse crate::ident::{is_ascii_ident, is_crate_name, is_feature_name};\nuse crate::output::rerun_if_env_changed;\n\n/// [`ProcessEnv`] wrapper that implicit calls [`rerun_if_env_changed`]\nconst ENV: RerunIfEnvChanged<ProcessEnv> = RerunIfEnvChanged::new();\n\n/// Abstraction over environment variables\ntrait Env {\n    /// Fetches the environment variable `key`, returning `None` if the variable isn’t set or if\n    /// there is another error.\n    ///\n    /// It may return `None` if the environment variable’s name contains the equal sign character\n    /// (`=`) or the NUL character.\n    ///\n    /// Note that this function will not check if the environment variable is valid Unicode.\n    fn get(&self, key: &str) -> Option<std::ffi::OsString>;\n\n    /// Checks the environment variable `key` is present\n    ///\n    /// It may not be considered present if the environment variable’s name contains the equal sign character\n    /// (`=`) or the NUL character.\n    fn is_present(&self, key: &str) -> bool;\n}\n\n/// Fetches environment variables from the current process\nstruct ProcessEnv;\n\nimpl Env for ProcessEnv {\n    fn get(&self, key: &str) -> Option<std::ffi::OsString> {\n        std::env::var_os(key)\n    }\n\n    fn is_present(&self, key: &str) -> bool {\n        self.get(key).is_some()\n    }\n}\n\n/// [`Env`] wrapper that implicitly calls [`rerun_if_env_changed`]\nstruct RerunIfEnvChanged<E: Env>(E);\n\nimpl RerunIfEnvChanged<ProcessEnv> {\n    const fn new() -> Self {\n        Self(ProcessEnv)\n    }\n}\n\nimpl<E: Env> Env for RerunIfEnvChanged<E> {\n    #[track_caller]\n    fn get(&self, key: &str) -> Option<std::ffi::OsString> {\n        rerun_if_env_changed(key);\n        self.0.get(key)\n    }\n\n    #[track_caller]\n    fn is_present(&self, key: &str) -> bool {\n        self.get(key).is_some()\n    }\n}\n\n/// Path to the `cargo` binary performing the build.\n#[track_caller]\npub fn cargo() -> PathBuf {\n    to_path(var_or_panic(\"CARGO\"))\n}\n\n/// The directory containing the manifest for the package being built (the package\n/// containing the build script).\n///\n/// Also note that this is the value of the current\n/// working directory of the build script when it starts.\n#[track_caller]\npub fn cargo_manifest_dir() -> PathBuf {\n    to_path(var_or_panic(\"CARGO_MANIFEST_DIR\"))\n}\n\n/// The path to the manifest of your package.\n#[track_caller]\npub fn cargo_manifest_path() -> PathBuf {\n    ENV.get(\"CARGO_MANIFEST_PATH\")\n        .map(to_path)\n        .unwrap_or_else(|| {\n            let mut path = cargo_manifest_dir();\n            path.push(\"Cargo.toml\");\n            path\n        })\n}\n\n/// The manifest `links` value.\n#[track_caller]\npub fn cargo_manifest_links() -> Option<String> {\n    ENV.get(\"CARGO_MANIFEST_LINKS\").map(to_string)\n}\n\n/// Contains parameters needed for Cargo’s [jobserver] implementation to parallelize\n/// subprocesses.\n///\n/// Rustc or cargo invocations from build.rs can already read\n/// `CARGO_MAKEFLAGS`, but GNU Make requires the flags to be specified either\n/// directly as arguments, or through the `MAKEFLAGS` environment variable.\n/// Currently Cargo doesn’t set the `MAKEFLAGS` variable, but it’s free for build\n/// scripts invoking GNU Make to set it to the contents of `CARGO_MAKEFLAGS`.\n///\n/// [jobserver]: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html\n#[track_caller]\npub fn cargo_makeflags() -> Option<String> {\n    ENV.get(\"CARGO_MAKEFLAGS\").map(to_string)\n}\n\n/// For each activated feature of the package being built, this will be `true`.\n#[track_caller]\npub fn cargo_feature(name: &str) -> bool {\n    if !is_feature_name(name) {\n        panic!(\"invalid feature name {name:?}\")\n    }\n    let name = name.to_uppercase().replace('-', \"_\");\n    let key = format!(\"CARGO_FEATURE_{name}\");\n    ENV.is_present(&key)\n}\n\n/// For each [configuration option] of the package being built, this will contain\n/// the value of the configuration.\n///\n/// This includes values built-in to the compiler\n/// (which can be seen with `rustc --print=cfg`) and values set by build scripts\n/// and extra flags passed to rustc (such as those defined in `RUSTFLAGS`).\n///\n/// [configuration option]: https://doc.rust-lang.org/stable/reference/conditional-compilation.html\n#[track_caller]\npub fn cargo_cfg(cfg: &str) -> Option<Vec<String>> {\n    let var = cargo_cfg_var(cfg);\n    ENV.get(&var).map(|v| to_strings(v, ','))\n}\n\n#[track_caller]\nfn cargo_cfg_var(cfg: &str) -> String {\n    if !is_ascii_ident(cfg) {\n        panic!(\"invalid configuration option {cfg:?}\")\n    }\n    let cfg = cfg.to_uppercase().replace('-', \"_\");\n    let key = format!(\"CARGO_CFG_{cfg}\");\n    key\n}\n\npub use self::cfg::*;\nmod cfg {\n    use super::*;\n\n    // those disabled with #[cfg(any())] don't seem meaningfully useful\n    // but we list all cfg that are default known to check-cfg\n\n    /// Each activated feature of the package being built\n    #[doc = requires_msrv!(\"1.85\")]\n    #[track_caller]\n    pub fn cargo_cfg_feature() -> Vec<String> {\n        to_strings(var_or_panic(&cargo_cfg_var(\"feature\")), ',')\n    }\n\n    #[cfg(any())]\n    #[track_caller]\n    pub fn cargo_cfg_clippy() -> bool {\n        ENV.is_present(\"CARGO_CFG_CLIPPY\")\n    }\n\n    /// If we are compiling with debug assertions enabled.\n    #[track_caller]\n    pub fn cargo_cfg_debug_assertions() -> bool {\n        ENV.is_present(\"CARGO_CFG_DEBUG_ASSERTIONS\")\n    }\n\n    #[cfg(any())]\n    #[track_caller]\n    pub fn cargo_cfg_doc() -> bool {\n        ENV.is_present(\"CARGO_CFG_DOC\")\n    }\n\n    #[cfg(any())]\n    #[track_caller]\n    pub fn cargo_cfg_docsrs() -> bool {\n        ENV.is_present(\"CARGO_CFG_DOCSRS\")\n    }\n\n    #[cfg(any())]\n    #[track_caller]\n    pub fn cargo_cfg_doctest() -> bool {\n        ENV.is_present(\"CARGO_CFG_DOCTEST\")\n    }\n\n    /// The level of detail provided by derived [`Debug`] implementations.\n    #[doc = unstable!(fmt_dbg, 129709)]\n    #[cfg(feature = \"unstable\")]\n    #[track_caller]\n    pub fn cargo_cfg_fmt_debug() -> String {\n        to_string(var_or_panic(\"CARGO_CFG_FMT_DEBUG\"))\n    }\n\n    #[cfg(any())]\n    #[track_caller]\n    pub fn cargo_cfg_miri() -> bool {\n        ENV.is_present(\"CARGO_CFG_MIRI\")\n    }\n\n    /// If we are compiling with overflow checks enabled.\n    #[doc = unstable!(cfg_overflow_checks, 111466)]\n    #[cfg(feature = \"unstable\")]\n    #[track_caller]\n    pub fn cargo_cfg_overflow_checks() -> bool {\n        ENV.is_present(\"CARGO_CFG_OVERFLOW_CHECKS\")\n    }\n\n    /// The [panic strategy](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#panic).\n    #[track_caller]\n    pub fn cargo_cfg_panic() -> String {\n        to_string(var_or_panic(\"CARGO_CFG_PANIC\"))\n    }\n\n    /// If the crate is being compiled as a procedural macro.\n    #[track_caller]\n    pub fn cargo_cfg_proc_macro() -> bool {\n        ENV.is_present(\"CARGO_CFG_PROC_MACRO\")\n    }\n\n    /// The target relocation model.\n    #[doc = unstable!(cfg_relocation_model, 114929)]\n    #[cfg(feature = \"unstable\")]\n    #[track_caller]\n    pub fn cargo_cfg_relocation_model() -> String {\n        to_string(var_or_panic(\"CARGO_CFG_RELOCATION_MODEL\"))\n    }\n\n    #[cfg(any())]\n    #[track_caller]\n    pub fn cargo_cfg_rustfmt() -> bool {\n        ENV.is_present(\"CARGO_CFG_RUSTFMT\")\n    }\n\n    /// Sanitizers enabled for the crate being compiled.\n    #[doc = unstable!(cfg_sanitize, 39699)]\n    #[cfg(feature = \"unstable\")]\n    #[track_caller]\n    pub fn cargo_cfg_sanitize() -> Option<Vec<String>> {\n        ENV.get(\"CARGO_CFG_SANITIZE\").map(|v| to_strings(v, ','))\n    }\n\n    /// If CFI sanitization is generalizing pointers.\n    #[doc = unstable!(cfg_sanitizer_cfi, 89653)]\n    #[cfg(feature = \"unstable\")]\n    #[track_caller]\n    pub fn cargo_cfg_sanitizer_cfi_generalize_pointers() -> bool {\n        ENV.is_present(\"CARGO_CFG_SANITIZER_CFI_GENERALIZE_POINTERS\")\n    }\n\n    /// If CFI sanitization is normalizing integers.\n    #[doc = unstable!(cfg_sanitizer_cfi, 89653)]\n    #[cfg(feature = \"unstable\")]\n    #[track_caller]\n    pub fn cargo_cfg_sanitizer_cfi_normalize_integers() -> bool {\n        ENV.is_present(\"CARGO_CFG_SANITIZER_CFI_NORMALIZE_INTEGERS\")\n    }\n\n    /// Disambiguation of the [target ABI](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_abi)\n    /// when the [target env](cargo_cfg_target_env) isn't sufficient.\n    ///\n    /// For historical reasons, this value is only defined as `Some` when\n    /// actually needed for disambiguation. Thus, for example, on many GNU platforms,\n    /// this value will be `None`.\n    #[track_caller]\n    pub fn cargo_cfg_target_abi() -> Option<String> {\n        to_opt(var_or_panic(\"CARGO_CFG_TARGET_ABI\")).map(to_string)\n    }\n\n    /// The CPU [target architecture](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_arch).\n    /// This is similar to the first element of the platform's target triple, but not identical.\n    #[track_caller]\n    pub fn cargo_cfg_target_arch() -> String {\n        to_string(var_or_panic(\"CARGO_CFG_TARGET_ARCH\"))\n    }\n\n    /// The CPU [target endianness](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_endian).\n    #[track_caller]\n    pub fn cargo_cfg_target_endian() -> String {\n        to_string(var_or_panic(\"CARGO_CFG_TARGET_ENDIAN\"))\n    }\n\n    /// The [target environment](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_env) ABI.\n    /// This value is similar to the fourth element of the platform's target triple.\n    ///\n    /// For historical reasons, this value is only defined as not the empty-string when\n    /// actually needed for disambiguation. Thus, for example, on many GNU platforms,\n    /// this value will be empty.\n    #[track_caller]\n    pub fn cargo_cfg_target_env() -> String {\n        to_string(var_or_panic(\"CARGO_CFG_TARGET_ENV\"))\n    }\n\n    /// The [target family](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_family).\n    #[track_caller]\n    pub fn cargo_target_family() -> Vec<String> {\n        to_strings(var_or_panic(&cargo_cfg_var(\"target_family\")), ',')\n    }\n\n    /// List of CPU [target features](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_feature) enabled.\n    #[track_caller]\n    pub fn cargo_cfg_target_feature() -> Vec<String> {\n        to_strings(var_or_panic(&cargo_cfg_var(\"target_feature\")), ',')\n    }\n\n    /// List of CPU [supported atomic widths](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_has_atomic).\n    #[track_caller]\n    pub fn cargo_cfg_target_has_atomic() -> Vec<String> {\n        to_strings(var_or_panic(&cargo_cfg_var(\"target_has_atomic\")), ',')\n    }\n\n    /// List of atomic widths that have equal alignment requirements.\n    #[doc = unstable!(cfg_target_has_atomic_equal_alignment, 93822)]\n    #[cfg(feature = \"unstable\")]\n    #[track_caller]\n    pub fn cargo_cfg_target_has_atomic_equal_alignment() -> Vec<String> {\n        to_strings(\n            var_or_panic(&cargo_cfg_var(\"target_has_atomic_equal_alignment\")),\n            ',',\n        )\n    }\n\n    /// List of atomic widths that have atomic load and store operations.\n    #[doc = unstable!(cfg_target_has_atomic_load_store, 94039)]\n    #[cfg(feature = \"unstable\")]\n    #[track_caller]\n    pub fn cargo_cfg_target_has_atomic_load_store() -> Vec<String> {\n        to_strings(\n            var_or_panic(&cargo_cfg_var(\"target_has_atomic_load_store\")),\n            ',',\n        )\n    }\n\n    /// The [target operating system](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_os).\n    /// This value is similar to the second and third element of the platform's target triple.\n    #[track_caller]\n    pub fn cargo_cfg_target_os() -> String {\n        to_string(var_or_panic(\"CARGO_CFG_TARGET_OS\"))\n    }\n\n    /// The CPU [pointer width](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_pointer_width).\n    #[track_caller]\n    pub fn cargo_cfg_target_pointer_width() -> u32 {\n        to_parsed(var_or_panic(\"CARGO_CFG_TARGET_POINTER_WIDTH\"))\n    }\n\n    /// If the target supports thread-local storage.\n    #[doc = unstable!(cfg_target_thread_local, 29594)]\n    #[cfg(feature = \"unstable\")]\n    #[track_caller]\n    pub fn cargo_cfg_target_thread_local() -> bool {\n        ENV.is_present(\"CARGO_CFG_TARGET_THREAD_LOCAL\")\n    }\n\n    /// The [target vendor](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#target_vendor).\n    #[track_caller]\n    pub fn cargo_cfg_target_vendor() -> String {\n        to_string(var_or_panic(\"CARGO_CFG_TARGET_VENDOR\"))\n    }\n\n    #[cfg(any())]\n    #[track_caller]\n    pub fn cargo_cfg_test() -> bool {\n        ENV.is_present(\"CARGO_CFG_TEST\")\n    }\n\n    /// If we are compiling with UB checks enabled.\n    #[doc = unstable!(cfg_ub_checks, 123499)]\n    #[cfg(feature = \"unstable\")]\n    #[track_caller]\n    pub fn cargo_cfg_ub_checks() -> bool {\n        ENV.is_present(\"CARGO_CFG_UB_CHECKS\")\n    }\n\n    /// Set on [unix-like platforms](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#unix-and-windows).\n    #[track_caller]\n    pub fn cargo_cfg_unix() -> bool {\n        ENV.is_present(\"CARGO_CFG_UNIX\")\n    }\n\n    /// Set on [windows-like platforms](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#unix-and-windows).\n    #[track_caller]\n    pub fn cargo_cfg_windows() -> bool {\n        ENV.is_present(\"CARGO_CFG_WINDOWS\")\n    }\n}\n\n/// The folder in which all output and intermediate artifacts should be placed.\n///\n/// This folder is inside the build directory for the package being built, and\n/// it is unique for the package in question.\n#[track_caller]\npub fn out_dir() -> PathBuf {\n    to_path(var_or_panic(\"OUT_DIR\"))\n}\n\n/// The [target triple] that is being compiled for. Native code should be compiled\n///  for this triple.\n///\n/// [target triple]: https://doc.rust-lang.org/stable/cargo/appendix/glossary.html#target\n#[track_caller]\npub fn target() -> String {\n    to_string(var_or_panic(\"TARGET\"))\n}\n\n/// The host triple of the Rust compiler.\n#[track_caller]\npub fn host() -> String {\n    to_string(var_or_panic(\"HOST\"))\n}\n\n/// The parallelism specified as the top-level parallelism.\n///\n/// This can be useful to\n/// pass a `-j` parameter to a system like `make`. Note that care should be taken\n/// when interpreting this value. For historical purposes this is still provided\n/// but Cargo, for example, does not need to run `make -j`, and instead can set the\n/// `MAKEFLAGS` env var to the content of `CARGO_MAKEFLAGS` to activate the use of\n/// Cargo’s GNU Make compatible [jobserver] for sub-make invocations.\n///\n/// [jobserver]: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html\n#[track_caller]\npub fn num_jobs() -> u32 {\n    to_parsed(var_or_panic(\"NUM_JOBS\"))\n}\n\n/// The [level of optimization](https://doc.rust-lang.org/stable/cargo/reference/profiles.html#opt-level).\n#[track_caller]\npub fn opt_level() -> String {\n    to_string(var_or_panic(\"OPT_LEVEL\"))\n}\n\n/// The amount of [debug information](https://doc.rust-lang.org/stable/cargo/reference/profiles.html#debug) included.\n#[track_caller]\npub fn debug() -> String {\n    to_string(var_or_panic(\"DEBUG\"))\n}\n\n/// `release` for release builds, `debug` for other builds.\n///\n/// This is determined based\n/// on if the [profile] inherits from the [`dev`] or [`release`] profile. Using this\n/// function is not recommended. Using other functions like [`opt_level`] provides\n/// a more correct view of the actual settings being used.\n///\n/// [profile]: https://doc.rust-lang.org/stable/cargo/reference/profiles.html\n/// [`dev`]: https://doc.rust-lang.org/stable/cargo/reference/profiles.html#dev\n/// [`release`]: https://doc.rust-lang.org/stable/cargo/reference/profiles.html#release\n#[track_caller]\npub fn profile() -> String {\n    to_string(var_or_panic(\"PROFILE\"))\n}\n\n/// [Metadata] set by dependencies. For more information, see build script\n/// documentation about [the `links` manifest key][links].\n///\n/// [metadata]: crate::output::metadata\n/// [links]: https://doc.rust-lang.org/stable/cargo/reference/build-scripts.html#the-links-manifest-key\n#[track_caller]\npub fn dep_metadata(name: &str, key: &str) -> Option<String> {\n    if !is_crate_name(name) {\n        panic!(\"invalid dependency name {name:?}\")\n    }\n    if !is_ascii_ident(key) {\n        panic!(\"invalid metadata key {key:?}\")\n    }\n\n    let name = name.to_uppercase().replace('-', \"_\");\n    let key = key.to_uppercase().replace('-', \"_\");\n    let key = format!(\"DEP_{name}_{key}\");\n    ENV.get(&key).map(to_string)\n}\n\n/// The compiler that Cargo has resolved to use.\n#[track_caller]\npub fn rustc() -> PathBuf {\n    to_path(var_or_panic(\"RUSTC\"))\n}\n\n/// The documentation generator that Cargo has resolved to use.\n#[track_caller]\npub fn rustdoc() -> PathBuf {\n    to_path(var_or_panic(\"RUSTDOC\"))\n}\n\n/// The rustc wrapper, if any, that Cargo is using. See [`build.rustc-wrapper`].\n///\n/// [`build.rustc-wrapper`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#buildrustc-wrapper\n#[track_caller]\npub fn rustc_wrapper() -> Option<PathBuf> {\n    ENV.get(\"RUSTC_WRAPPER\").map(to_path)\n}\n\n/// The rustc wrapper, if any, that Cargo is using for workspace members. See\n/// [`build.rustc-workspace-wrapper`].\n///\n/// [`build.rustc-workspace-wrapper`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#buildrustc-workspace-wrapper\n#[track_caller]\npub fn rustc_workspace_wrapper() -> Option<PathBuf> {\n    ENV.get(\"RUSTC_WORKSPACE_WRAPPER\").map(to_path)\n}\n\n/// The linker that Cargo has resolved to use for the current target, if specified.\n///\n/// [`target.*.linker`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#targettriplelinker\n#[track_caller]\npub fn rustc_linker() -> Option<PathBuf> {\n    ENV.get(\"RUSTC_LINKER\").map(to_path)\n}\n\n/// Extra flags that Cargo invokes rustc with. See [`build.rustflags`].\n///\n/// [`build.rustflags`]: https://doc.rust-lang.org/stable/cargo/reference/config.html#buildrustflags\n#[track_caller]\npub fn cargo_encoded_rustflags() -> Vec<String> {\n    to_strings(var_or_panic(\"CARGO_ENCODED_RUSTFLAGS\"), '\\x1f')\n}\n\n/// The full version of your package.\n#[track_caller]\npub fn cargo_pkg_version() -> String {\n    to_string(var_or_panic(\"CARGO_PKG_VERSION\"))\n}\n\n/// The major version of your package.\n#[track_caller]\npub fn cargo_pkg_version_major() -> u64 {\n    to_parsed(var_or_panic(\"CARGO_PKG_VERSION_MAJOR\"))\n}\n\n/// The minor version of your package.\n#[track_caller]\npub fn cargo_pkg_version_minor() -> u64 {\n    to_parsed(var_or_panic(\"CARGO_PKG_VERSION_MINOR\"))\n}\n\n/// The patch version of your package.\n#[track_caller]\npub fn cargo_pkg_version_patch() -> u64 {\n    to_parsed(var_or_panic(\"CARGO_PKG_VERSION_PATCH\"))\n}\n\n/// The pre-release version of your package.\n#[track_caller]\npub fn cargo_pkg_version_pre() -> Option<String> {\n    to_opt(var_or_panic(\"CARGO_PKG_VERSION_PRE\")).map(to_string)\n}\n\n/// The authors from the manifest of your package.\n#[track_caller]\npub fn cargo_pkg_authors() -> Vec<String> {\n    to_strings(var_or_panic(\"CARGO_PKG_AUTHORS\"), ':')\n}\n\n/// The name of your package.\n#[track_caller]\npub fn cargo_pkg_name() -> String {\n    to_string(var_or_panic(\"CARGO_PKG_NAME\"))\n}\n\n/// The description from the manifest of your package.\n#[track_caller]\npub fn cargo_pkg_description() -> Option<String> {\n    to_opt(var_or_panic(\"CARGO_PKG_DESCRIPTION\")).map(to_string)\n}\n\n/// The home page from the manifest of your package.\n#[track_caller]\npub fn cargo_pkg_homepage() -> Option<String> {\n    to_opt(var_or_panic(\"CARGO_PKG_HOMEPAGE\")).map(to_string)\n}\n\n/// The repository from the manifest of your package.\n#[track_caller]\npub fn cargo_pkg_repository() -> Option<String> {\n    to_opt(var_or_panic(\"CARGO_PKG_REPOSITORY\")).map(to_string)\n}\n\n/// The license from the manifest of your package.\n#[track_caller]\npub fn cargo_pkg_license() -> Option<String> {\n    to_opt(var_or_panic(\"CARGO_PKG_LICENSE\")).map(to_string)\n}\n\n/// The license file from the manifest of your package.\n#[track_caller]\npub fn cargo_pkg_license_file() -> Option<PathBuf> {\n    to_opt(var_or_panic(\"CARGO_PKG_LICENSE_FILE\")).map(to_path)\n}\n\n/// The Rust version from the manifest of your package. Note that this is the\n/// minimum Rust version supported by the package, not the current Rust version.\n#[track_caller]\npub fn cargo_pkg_rust_version() -> Option<String> {\n    to_opt(var_or_panic(\"CARGO_PKG_RUST_VERSION\")).map(to_string)\n}\n\n/// Path to the README file of your package.\n#[track_caller]\npub fn cargo_pkg_readme() -> Option<PathBuf> {\n    to_opt(var_or_panic(\"CARGO_PKG_README\")).map(to_path)\n}\n\n#[track_caller]\nfn var_or_panic(key: &str) -> std::ffi::OsString {\n    ENV.get(key)\n        .unwrap_or_else(|| panic!(\"cargo environment variable `{key}` is missing\"))\n}\n\nfn to_path(value: std::ffi::OsString) -> PathBuf {\n    PathBuf::from(value)\n}\n\n#[track_caller]\nfn to_string(value: std::ffi::OsString) -> String {\n    match value.into_string() {\n        Ok(s) => s,\n        Err(value) => {\n            let err = std::str::from_utf8(value.as_encoded_bytes()).unwrap_err();\n            panic!(\"{err}\")\n        }\n    }\n}\n\nfn to_opt(value: std::ffi::OsString) -> Option<std::ffi::OsString> {\n    (!value.is_empty()).then_some(value)\n}\n\n#[track_caller]\nfn to_strings(value: std::ffi::OsString, sep: char) -> Vec<String> {\n    if value.is_empty() {\n        return Vec::new();\n    }\n    let value = to_string(value);\n    value.split(sep).map(str::to_owned).collect()\n}\n\n#[track_caller]\nfn to_parsed<T>(value: std::ffi::OsString) -> T\nwhere\n    T: std::str::FromStr,\n    T::Err: std::fmt::Display,\n{\n    let value = to_string(value);\n    match value.parse() {\n        Ok(s) => s,\n        Err(err) => {\n            panic!(\"{err}\")\n        }\n    }\n}\n"
  },
  {
    "path": "crates/build-rs/src/lib.rs",
    "content": "//! build-rs provides a strongly typed interface around the Cargo build script\n//! protocol. Cargo provides inputs to the build script by environment variable\n//! and accepts commands by printing to stdout.\n//!\n//! > This crate is maintained by the Cargo team for use by the wider\n//! > ecosystem. This crate follows semver compatibility for its APIs.\n#![cfg_attr(all(doc, feature = \"unstable\"), feature(doc_auto_cfg, doc_cfg))]\n#![allow(clippy::disallowed_methods)] // HACK: deferred resoling this\n#![allow(clippy::print_stdout)] // HACK: deferred resoling this\n\n#[cfg(feature = \"unstable\")]\nmacro_rules! unstable {\n    ($feature:ident, $issue:literal) => {\n        concat!(\n            r#\"<div class=\"stab unstable\">\"#,\n            r#\"<span class=\"emoji\">🔬</span>\"#,\n            r#\"<span>This is a nightly-only experimental API. (<code>\"#,\n            stringify!($feature),\n            r#\"</code>&nbsp;<a href=\"https://github.com/rust-lang/rust/issues/\"#,\n            $issue,\n            r#\"\">#\"#,\n            $issue,\n            r#\"</a>)</span>\"#,\n            r#\"</div>\"#\n        )\n    };\n}\n\nmacro_rules! respected_msrv {\n    ($ver:literal) => {\n        concat!(\n            r#\"<div class=\"warning\">\n\nMSRV: Respected as of \"#,\n            $ver,\n            r#\".\n\n</div>\"#\n        )\n    };\n}\n\nmacro_rules! requires_msrv {\n    ($ver:literal) => {\n        concat!(\n            r#\"<div class=\"warning\">\n\nMSRV: Requires \"#,\n            $ver,\n            r#\".\n\n</div>\"#\n        )\n    };\n}\n\nmod ident;\n\npub mod input;\npub mod output;\n"
  },
  {
    "path": "crates/build-rs/src/output.rs",
    "content": "//! Outputs from the build script to the build system.\n//!\n//! This crate assumes that stdout is at a new line whenever an output directive\n//! is called. Printing to stdout without a terminating newline (i.e. not using\n//! [`println!`]) may lead to surprising behavior.\n//!\n//! Reference: <https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script>\n\nuse std::ffi::OsStr;\nuse std::path::Path;\nuse std::{fmt::Display, fmt::Write as _};\n\nuse crate::ident::{is_ascii_ident, is_ident};\n\nfn emit(directive: &str, value: impl Display) {\n    println!(\"cargo::{directive}={value}\");\n}\n\n/// The `rerun-if-changed` instruction tells Cargo to re-run the build script if the\n/// file at the given path has changed.\n///\n/// Currently, Cargo only uses the filesystem\n/// last-modified “mtime” timestamp to determine if the file has changed. It\n/// compares against an internal cached timestamp of when the build script last ran.\n///\n/// If the path points to a directory, it will scan the entire directory for any\n/// modifications.\n///\n/// If the build script inherently does not need to re-run under any circumstance,\n/// then calling `rerun_if_changed(\"build.rs\")` is a simple way to prevent it from\n/// being re-run (otherwise, the default if no `rerun-if` instructions are emitted\n/// is to scan the entire package directory for changes). Cargo automatically\n/// handles whether or not the script itself needs to be recompiled, and of course\n/// the script will be re-run after it has been recompiled. Otherwise, specifying\n/// `build.rs` is redundant and unnecessary.\n#[track_caller]\npub fn rerun_if_changed(path: impl AsRef<Path>) {\n    let Some(path) = path.as_ref().to_str() else {\n        panic!(\"cannot emit rerun-if-changed: path is not UTF-8\");\n    };\n    if path.contains('\\n') {\n        panic!(\"cannot emit rerun-if-changed: path contains newline\");\n    }\n    emit(\"rerun-if-changed\", path);\n}\n\n/// The `rerun-if-env-changed` instruction tells Cargo to re-run the build script\n/// if the value of an environment variable of the given name has changed.\n///\n/// Note that the environment variables here are intended for global environment\n/// variables like `CC` and such, it is not possible to use this for environment\n/// variables like `TARGET` that [Cargo sets for build scripts][build-env]. The\n/// environment variables in use are those received by cargo invocations, not\n/// those received by the executable of the build script.\n///\n/// [build-env]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts\n#[track_caller]\npub fn rerun_if_env_changed(key: impl AsRef<OsStr>) {\n    let Some(key) = key.as_ref().to_str() else {\n        panic!(\"cannot emit rerun-if-env-changed: key is not UTF-8\");\n    };\n    if key.contains('\\n') {\n        panic!(\"cannot emit rerun-if-env-changed: key contains newline\");\n    }\n    emit(\"rerun-if-env-changed\", key);\n}\n\n/// The `rustc-link-arg` instruction tells Cargo to pass the\n/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building\n/// supported targets (benchmarks, binaries, cdylib crates, examples, and tests).\n///\n/// Its usage is highly platform specific. It is useful to set the shared library\n/// version or linker script.\n///\n/// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg\n#[track_caller]\npub fn rustc_link_arg(flag: &str) {\n    if flag.contains([' ', '\\n']) {\n        panic!(\"cannot emit rustc-link-arg: invalid flag {flag:?}\");\n    }\n    emit(\"rustc-link-arg\", flag);\n}\n\n/// The `rustc-link-arg-bin` instruction tells Cargo to pass the\n/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building\n/// the binary target with name `BIN`. Its usage is highly platform specific.\n///\n/// It\n/// is useful to set a linker script or other linker options.\n///\n/// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg\n#[track_caller]\npub fn rustc_link_arg_bin(bin: &str, flag: &str) {\n    if !is_ident(bin) {\n        panic!(\"cannot emit rustc-link-arg-bin: invalid bin name {bin:?}\");\n    }\n    if flag.contains([' ', '\\n']) {\n        panic!(\"cannot emit rustc-link-arg-bin: invalid flag {flag:?}\");\n    }\n    emit(\"rustc-link-arg-bin\", format_args!(\"{bin}={flag}\"));\n}\n\n/// The `rustc-link-arg-bins` instruction tells Cargo to pass the\n/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building\n/// the binary target.\n///\n/// Its usage is highly platform specific. It is useful to set\n/// a linker script or other linker options.\n///\n/// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg\n#[track_caller]\npub fn rustc_link_arg_bins(flag: &str) {\n    if flag.contains([' ', '\\n']) {\n        panic!(\"cannot emit rustc-link-arg-bins: invalid flag {flag:?}\");\n    }\n    emit(\"rustc-link-arg-bins\", flag);\n}\n\n/// The `rustc-link-arg-tests` instruction tells Cargo to pass the\n/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building\n/// a tests target.\n///\n/// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg\n#[track_caller]\npub fn rustc_link_arg_tests(flag: &str) {\n    if flag.contains([' ', '\\n']) {\n        panic!(\"cannot emit rustc-link-arg-tests: invalid flag {flag:?}\");\n    }\n    emit(\"rustc-link-arg-tests\", flag);\n}\n\n/// The `rustc-link-arg-examples` instruction tells Cargo to pass the\n/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building\n/// an examples target.\n///\n/// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg\n#[track_caller]\npub fn rustc_link_arg_examples(flag: &str) {\n    if flag.contains([' ', '\\n']) {\n        panic!(\"cannot emit rustc-link-arg-examples: invalid flag {flag:?}\");\n    }\n    emit(\"rustc-link-arg-examples\", flag);\n}\n\n/// The `rustc-link-arg-benches` instruction tells Cargo to pass the\n/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building\n/// a benchmark target.\n///\n/// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg\n#[track_caller]\npub fn rustc_link_arg_benches(flag: &str) {\n    if flag.contains([' ', '\\n']) {\n        panic!(\"cannot emit rustc-link-arg-benches: invalid flag {flag:?}\");\n    }\n    emit(\"rustc-link-arg-benches\", flag);\n}\n\n/// The `rustc-link-lib` instruction tells Cargo to link the given library using\n/// the compiler’s [`-l` flag][-l].\n///\n/// This is typically used to link a native library\n/// using [FFI].\n///\n/// The `LIB` string is passed directly to rustc, so it supports any syntax that\n/// `-l` does. Currently the full supported syntax for `LIB` is\n/// `[KIND[:MODIFIERS]=]NAME[:RENAME]`.\n///\n/// The `-l` flag is only passed to the library target of the package, unless there\n/// is no library target, in which case it is passed to all targets. This is done\n/// because all other targets have an implicit dependency on the library target,\n/// and the given library to link should only be included once. This means that\n/// if a package has both a library and a binary target, the library has access\n/// to the symbols from the given lib, and the binary should access them through\n/// the library target’s public API.\n///\n/// The optional `KIND` may be one of `dylib`, `static`, or `framework`. See the\n/// [rustc book][-l] for more detail.\n///\n/// [-l]: https://doc.rust-lang.org/stable/rustc/command-line-arguments.html#option-l-link-lib\n/// [FFI]: https://doc.rust-lang.org/stable/nomicon/ffi.html\n#[track_caller]\npub fn rustc_link_lib(lib: &str) {\n    if lib.contains([' ', '\\n']) {\n        panic!(\"cannot emit rustc-link-lib: invalid lib {lib:?}\");\n    }\n    emit(\"rustc-link-lib\", lib);\n}\n\n/// Like [`rustc_link_lib`], but with `KIND[:MODIFIERS]` specified separately.\n#[track_caller]\npub fn rustc_link_lib_kind(kind: &str, lib: &str) {\n    if kind.contains(['=', ' ', '\\n']) {\n        panic!(\"cannot emit rustc-link-lib: invalid kind {kind:?}\");\n    }\n    if lib.contains([' ', '\\n']) {\n        panic!(\"cannot emit rustc-link-lib: invalid lib {lib:?}\");\n    }\n    emit(\"rustc-link-lib\", format_args!(\"{kind}={lib}\"));\n}\n\n/// The `rustc-link-search` instruction tells Cargo to pass the [`-L` flag] to the\n/// compiler to add a directory to the library search path.\n///\n/// The optional `KIND` may be one of `dependency`, `crate`, `native`, `framework`,\n/// or `all`. See the [rustc book][-L] for more detail.\n///\n/// These paths are also added to the\n/// [dynamic library search path environment variable][search-path] if they are\n/// within the `OUT_DIR`. Depending on this behavior is discouraged since this\n/// makes it difficult to use the resulting binary. In general, it is best to\n/// avoid creating dynamic libraries in a build script (using existing system\n/// libraries is fine).\n///\n/// [-L]: https://doc.rust-lang.org/stable/rustc/command-line-arguments.html#option-l-search-path\n/// [search-path]: https://doc.rust-lang.org/stable/cargo/reference/environment-variables.html#dynamic-library-paths\n#[track_caller]\npub fn rustc_link_search(path: impl AsRef<Path>) {\n    let Some(path) = path.as_ref().to_str() else {\n        panic!(\"cannot emit rustc-link-search: path is not UTF-8\");\n    };\n    if path.contains('\\n') {\n        panic!(\"cannot emit rustc-link-search: path contains newline\");\n    }\n    emit(\"rustc-link-search\", path);\n}\n\n/// Like [`rustc_link_search`], but with KIND specified separately.\n#[track_caller]\npub fn rustc_link_search_kind(kind: &str, path: impl AsRef<Path>) {\n    if kind.contains(['=', '\\n']) {\n        panic!(\"cannot emit rustc-link-search: invalid kind {kind:?}\");\n    }\n    let Some(path) = path.as_ref().to_str() else {\n        panic!(\"cannot emit rustc-link-search: path is not UTF-8\");\n    };\n    if path.contains('\\n') {\n        panic!(\"cannot emit rustc-link-search: path contains newline\");\n    }\n    emit(\"rustc-link-search\", format_args!(\"{kind}={path}\"));\n}\n\n/// The `rustc-flags` instruction tells Cargo to pass the given space-separated\n/// flags to the compiler.\n///\n/// This only allows the `-l` and `-L` flags, and is\n/// equivalent to using [`rustc_link_lib`] and [`rustc_link_search`].\n#[track_caller]\npub fn rustc_flags(flags: &str) {\n    if flags.contains('\\n') {\n        panic!(\"cannot emit rustc-flags: invalid flags\");\n    }\n    emit(\"rustc-flags\", flags);\n}\n\n/// The `rustc-cfg` instruction tells Cargo to pass the given value to the\n/// [`--cfg` flag][cfg] to the compiler.\n///\n/// This may be used for compile-time\n/// detection of features to enable conditional compilation.\n///\n/// Note that this does not affect Cargo’s dependency resolution. This cannot\n/// be used to enable an optional dependency, or enable other Cargo features.\n///\n/// Be aware that [Cargo features] use the form `feature=\"foo\"`. `cfg` values\n/// passed with this flag are not restricted to that form, and may provide just\n/// a single identifier, or any arbitrary key/value pair. For example, emitting\n/// `rustc_cfg(\"abc\")` will then allow code to use `#[cfg(abc)]` (note the lack\n/// of `feature=`). Or an arbitrary key/value pair may be used with an `=` symbol\n/// like `rustc_cfg(r#\"my_component=\"foo\"\"#)`. The key should be a Rust identifier,\n/// the value should be a string.\n///\n/// [cfg]: https://doc.rust-lang.org/rustc/command-line-arguments.html#option-cfg\n/// [Cargo features]: https://doc.rust-lang.org/cargo/reference/features.html\n#[track_caller]\npub fn rustc_cfg(key: &str) {\n    if !is_ident(key) {\n        panic!(\"cannot emit rustc-cfg: invalid key {key:?}\");\n    }\n    emit(\"rustc-cfg\", key);\n}\n\n/// Like [`rustc_cfg`], but with the value specified separately.\n///\n/// To replace the\n/// less convenient `rustc_cfg(r#\"my_component=\"foo\"\"#)`, you can instead use\n/// `rustc_cfg_value(\"my_component\", \"foo\")`.\n#[track_caller]\npub fn rustc_cfg_value(key: &str, value: &str) {\n    if !is_ident(key) {\n        panic!(\"cannot emit rustc-cfg-value: invalid key\");\n    }\n    let value = value.escape_default();\n    emit(\"rustc-cfg\", format_args!(\"{key}=\\\"{value}\\\"\"));\n}\n\n/// Add to the list of expected config names that is used when checking the\n/// *reachable* cfg expressions with the [`unexpected_cfgs`] lint.\n///\n/// This form is for keys without an expected value, such as `cfg(name)`.\n///\n/// It is recommended to group the `rustc_check_cfg` and `rustc_cfg` calls as\n/// closely as possible in order to avoid typos, missing check_cfg, stale cfgs,\n/// and other mistakes.\n///\n/// [`unexpected_cfgs`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unexpected-cfgs\n#[doc = respected_msrv!(\"1.80\")]\n#[track_caller]\npub fn rustc_check_cfgs(keys: &[&str]) {\n    if keys.is_empty() {\n        return;\n    }\n    for key in keys {\n        if !is_ident(key) {\n            panic!(\"cannot emit rustc-check-cfg: invalid key {key:?}\");\n        }\n    }\n\n    let mut directive = keys[0].to_string();\n    for key in &keys[1..] {\n        write!(directive, \", {key}\").expect(\"writing to string should be infallible\");\n    }\n    emit(\"rustc-check-cfg\", format_args!(\"cfg({directive})\"));\n}\n\n/// Add to the list of expected config names that is used when checking the\n/// *reachable* cfg expressions with the [`unexpected_cfgs`] lint.\n///\n/// This form is for keys with expected values, such as `cfg(name = \"value\")`.\n///\n/// It is recommended to group the `rustc_check_cfg` and `rustc_cfg` calls as\n/// closely as possible in order to avoid typos, missing check_cfg, stale cfgs,\n/// and other mistakes.\n///\n/// [`unexpected_cfgs`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unexpected-cfgs\n#[doc = respected_msrv!(\"1.80\")]\n#[track_caller]\npub fn rustc_check_cfg_values(key: &str, values: &[&str]) {\n    if !is_ident(key) {\n        panic!(\"cannot emit rustc-check-cfg: invalid key {key:?}\");\n    }\n    if values.is_empty() {\n        rustc_check_cfgs(&[key]);\n        return;\n    }\n\n    let mut directive = format!(\"\\\"{}\\\"\", values[0].escape_default());\n    for value in &values[1..] {\n        write!(directive, \", \\\"{}\\\"\", value.escape_default())\n            .expect(\"writing to string should be infallible\");\n    }\n    emit(\n        \"rustc-check-cfg\",\n        format_args!(\"cfg({key}, values({directive}))\"),\n    );\n}\n\n/// The `rustc-env` instruction tells Cargo to set the given environment variable\n/// when compiling the package.\n///\n/// The value can be then retrieved by the\n/// [`env!` macro][env!] in the compiled crate. This is useful for embedding\n/// additional metadata in crate’s code, such as the hash of git HEAD or the\n/// unique identifier of a continuous integration server.\n///\n/// See also the [environment variables automatically included by Cargo][cargo-env].\n///\n/// [cargo-env]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates\n#[track_caller]\npub fn rustc_env(key: &str, value: &str) {\n    if key.contains(['=', '\\n']) {\n        panic!(\"cannot emit rustc-env: invalid key {key:?}\");\n    }\n    if value.contains('\\n') {\n        panic!(\"cannot emit rustc-env: invalid value {value:?}\");\n    }\n    emit(\"rustc-env\", format_args!(\"{key}={value}\"));\n}\n\n/// The `rustc-cdylib-link-arg` instruction tells Cargo to pass the\n/// [`-C link-arg=FLAG` option][link-arg] to the compiler, but only when building\n/// a `cdylib` library target.\n///\n/// Its usage is highly platform specific. It is useful\n/// to set the shared library version or the runtime-path.\n///\n/// [link-arg]: https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg\n#[track_caller]\npub fn rustc_cdylib_link_arg(flag: &str) {\n    if flag.contains('\\n') {\n        panic!(\"cannot emit rustc-cdylib-link-arg: invalid flag {flag:?}\");\n    }\n    emit(\"rustc-cdylib-link-arg\", flag);\n}\n\n/// The `warning` instruction tells Cargo to display a warning after the build\n/// script has finished running.\n///\n/// Warnings are only shown for path dependencies\n/// (that is, those you’re working on locally), so for example warnings printed\n/// out in [crates.io] crates are not emitted by default. The `-vv` “very verbose”\n/// flag may be used to have Cargo display warnings for all crates.\n///\n/// [crates.io]: https://crates.io/\n#[track_caller]\npub fn warning(message: &str) {\n    if message.contains('\\n') {\n        panic!(\"cannot emit warning: message contains newline\");\n    }\n    emit(\"warning\", message);\n}\n\n/// The `error` instruction tells Cargo to display an error after the build script has finished\n/// running, and then fail the build.\n///\n/// <div class=\"warning\">\n///\n/// Build script libraries should carefully consider if they want to use [`error`] versus\n/// returning a `Result`. It may be better to return a `Result`, and allow the caller to decide if the\n/// error is fatal or not. The caller can then decide whether or not to display the `Err` variant\n/// using [`error`].\n///\n/// </div>\n#[doc = respected_msrv!(\"1.84\")]\n#[track_caller]\npub fn error(message: &str) {\n    if message.contains('\\n') {\n        panic!(\"cannot emit error: message contains newline\");\n    }\n    emit(\"error\", message);\n}\n\n/// Metadata, used by `links` scripts.\n#[track_caller]\npub fn metadata(key: &str, val: &str) {\n    if !is_ascii_ident(key) {\n        panic!(\"cannot emit metadata: invalid key {key:?}\");\n    }\n    if val.contains('\\n') {\n        panic!(\"cannot emit metadata: invalid value {val:?}\");\n    }\n\n    emit(\"metadata\", format_args!(\"{key}={val}\"));\n}\n"
  },
  {
    "path": "crates/build-rs-test-lib/Cargo.toml",
    "content": "[package]\nname = \"build-rs-test-lib\"\nversion = \"0.0.0\"\nedition.workspace = true\npublish = false\n\n[features]\nunstable = [\"build-rs/unstable\"]\n\n[build-dependencies]\nbuild-rs.workspace = true\n"
  },
  {
    "path": "crates/build-rs-test-lib/build.rs",
    "content": "fn main() {\n    smoke_test_inputs();\n\n    build_rs::output::rerun_if_changed(\"build.rs\");\n    build_rs::output::rustc_check_cfgs(&[\"did_run_build_script\"]);\n    build_rs::output::rustc_cfg(\"did_run_build_script\");\n}\n\nfn smoke_test_inputs() {\n    use build_rs::input::*;\n    dbg!(cargo());\n    dbg!(cargo_cfg_feature());\n    dbg!(cargo_cfg(\"careful\"));\n    dbg!(cargo_cfg_debug_assertions());\n    #[cfg(feature = \"unstable\")]\n    dbg!(cargo_cfg_fmt_debug());\n    #[cfg(feature = \"unstable\")]\n    dbg!(cargo_cfg_overflow_checks());\n    dbg!(cargo_cfg_panic());\n    dbg!(cargo_cfg_proc_macro());\n    #[cfg(feature = \"unstable\")]\n    dbg!(cargo_cfg_relocation_model());\n    #[cfg(feature = \"unstable\")]\n    dbg!(cargo_cfg_sanitize());\n    #[cfg(feature = \"unstable\")]\n    dbg!(cargo_cfg_sanitizer_cfi_generalize_pointers());\n    #[cfg(feature = \"unstable\")]\n    dbg!(cargo_cfg_sanitizer_cfi_normalize_integers());\n    dbg!(cargo_cfg_target_abi());\n    dbg!(cargo_cfg_target_arch());\n    dbg!(cargo_cfg_target_endian());\n    dbg!(cargo_cfg_target_env());\n    dbg!(cargo_cfg_target_feature());\n    dbg!(cargo_cfg_target_has_atomic());\n    #[cfg(feature = \"unstable\")]\n    dbg!(cargo_cfg_target_has_atomic_equal_alignment());\n    #[cfg(feature = \"unstable\")]\n    dbg!(cargo_cfg_target_has_atomic_load_store());\n    dbg!(cargo_cfg_target_os());\n    dbg!(cargo_cfg_target_pointer_width());\n    #[cfg(feature = \"unstable\")]\n    dbg!(cargo_cfg_target_thread_local());\n    dbg!(cargo_cfg_target_vendor());\n    #[cfg(feature = \"unstable\")]\n    dbg!(cargo_cfg_ub_checks());\n    dbg!(cargo_cfg_unix());\n    dbg!(cargo_cfg_windows());\n    dbg!(cargo_encoded_rustflags());\n    dbg!(cargo_feature(\"unstable\"));\n    dbg!(cargo_manifest_dir());\n    dbg!(cargo_manifest_path());\n    dbg!(cargo_manifest_links());\n    dbg!(cargo_pkg_authors());\n    dbg!(cargo_pkg_description());\n    dbg!(cargo_pkg_homepage());\n    dbg!(cargo_pkg_license());\n    dbg!(cargo_pkg_license_file());\n    dbg!(cargo_pkg_name());\n    dbg!(cargo_pkg_readme());\n    dbg!(cargo_pkg_repository());\n    dbg!(cargo_pkg_rust_version());\n    dbg!(cargo_pkg_version());\n    dbg!(cargo_pkg_version_major());\n    dbg!(cargo_pkg_version_minor());\n    dbg!(cargo_pkg_version_patch());\n    dbg!(cargo_pkg_version_pre());\n    dbg!(debug());\n    dbg!(dep_metadata(\"z\", \"include\"));\n    dbg!(host());\n    dbg!(num_jobs());\n    dbg!(opt_level());\n    dbg!(out_dir());\n    dbg!(profile());\n    dbg!(rustc());\n    dbg!(rustc_linker());\n    dbg!(rustc_workspace_wrapper());\n    dbg!(rustc_wrapper());\n    dbg!(rustdoc());\n    dbg!(target());\n}\n"
  },
  {
    "path": "crates/build-rs-test-lib/src/lib.rs",
    "content": "#[test]\nfn test() {\n    const { assert!(cfg!(did_run_build_script)) };\n}\n"
  },
  {
    "path": "crates/cargo-platform/Cargo.toml",
    "content": "[package]\nname = \"cargo-platform\"\nversion = \"0.3.3\"\nedition.workspace = true\nlicense.workspace = true\nrust-version.workspace = true\nrepository.workspace = true\ndocumentation = \"https://docs.rs/cargo-platform\"\ndescription = \"Cargo's representation of a target platform.\"\n\n[dependencies]\nserde_core.workspace = true\n\n# serde v1.0.220 is the first version that released with `serde_core`.\n# This is required to avoid conflict with other `serde` users which may require an older version.\n[target.'cfg(any())'.dependencies]\nserde.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/cargo-platform/README.md",
    "content": "> This crate is maintained by the Cargo team for use by the wider\n> ecosystem. This crate follows semver compatibility for its APIs.\n"
  },
  {
    "path": "crates/cargo-platform/examples/matches.rs",
    "content": "//! This example demonstrates how to filter a Platform based on the current\n//! host target.\n\n#![allow(clippy::print_stdout)]\n\nuse cargo_platform::{Cfg, Platform};\nuse std::process::Command;\nuse std::str::FromStr;\n\nstatic EXAMPLES: &[&str] = &[\n    \"cfg(windows)\",\n    \"cfg(unix)\",\n    \"cfg(target_os=\\\"macos\\\")\",\n    \"cfg(target_os=\\\"linux\\\")\",\n    \"cfg(any(target_arch=\\\"x86\\\", target_arch=\\\"x86_64\\\"))\",\n];\n\nfn main() {\n    let target = get_target();\n    let cfgs = get_cfgs();\n    println!(\"host target={} cfgs:\", target);\n    for cfg in &cfgs {\n        println!(\"  {}\", cfg);\n    }\n    let mut examples: Vec<&str> = EXAMPLES.iter().copied().collect();\n    examples.push(target.as_str());\n    for example in examples {\n        let p = Platform::from_str(example).unwrap();\n        println!(\"{:?} matches: {:?}\", example, p.matches(&target, &cfgs));\n    }\n}\n\nfn get_target() -> String {\n    let output = Command::new(\"rustc\")\n        .arg(\"-Vv\")\n        .output()\n        .expect(\"rustc failed to run\");\n    let stdout = String::from_utf8(output.stdout).unwrap();\n    for line in stdout.lines() {\n        if let Some(line) = line.strip_prefix(\"host: \") {\n            return String::from(line);\n        }\n    }\n    panic!(\"Failed to find host: {}\", stdout);\n}\n\nfn get_cfgs() -> Vec<Cfg> {\n    let output = Command::new(\"rustc\")\n        .arg(\"--print=cfg\")\n        .output()\n        .expect(\"rustc failed to run\");\n    let stdout = String::from_utf8(output.stdout).unwrap();\n    stdout\n        .lines()\n        .map(|line| Cfg::from_str(line).unwrap())\n        .collect()\n}\n"
  },
  {
    "path": "crates/cargo-platform/src/cfg.rs",
    "content": "use crate::error::{ParseError, ParseErrorKind::*};\nuse std::fmt;\nuse std::hash::{Hash, Hasher};\nuse std::iter;\nuse std::str::{self, FromStr};\n\n/// A cfg expression.\n#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]\npub enum CfgExpr {\n    Not(Box<CfgExpr>),\n    All(Vec<CfgExpr>),\n    Any(Vec<CfgExpr>),\n    Value(Cfg),\n    True,\n    False,\n}\n\n/// A cfg value.\n#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]\npub enum Cfg {\n    /// A named cfg value, like `unix`.\n    Name(Ident),\n    /// A key/value cfg pair, like `target_os = \"linux\"`.\n    KeyPair(Ident, String),\n}\n\n/// A identifier\n#[derive(Eq, Ord, PartialOrd, Clone, Debug)]\npub struct Ident {\n    /// The identifier\n    pub name: String,\n    /// Is this a raw ident: `r#async`\n    ///\n    /// It's mainly used for display and doesn't take\n    /// part in the hash or equality (`foo` == `r#foo`).\n    pub raw: bool,\n}\n\n#[derive(PartialEq)]\nenum Token<'a> {\n    LeftParen,\n    RightParen,\n    Ident(bool, &'a str),\n    Comma,\n    Equals,\n    String(&'a str),\n}\n\n/// The list of keywords.\n///\n/// We should consider all the keywords, but some are conditional on\n/// the edition so for now we just consider true/false.\n///\n/// <https://doc.rust-lang.org/reference/keywords.html>\npub(crate) const KEYWORDS: &[&str; 2] = &[\"true\", \"false\"];\n\n#[derive(Clone)]\nstruct Tokenizer<'a> {\n    s: iter::Peekable<str::CharIndices<'a>>,\n    orig: &'a str,\n}\n\nstruct Parser<'a> {\n    t: Tokenizer<'a>,\n}\n\nimpl Ident {\n    pub fn as_str(&self) -> &str {\n        &self.name\n    }\n}\n\nimpl Hash for Ident {\n    fn hash<H: Hasher>(&self, state: &mut H) {\n        self.name.hash(state);\n    }\n}\n\nimpl PartialEq<str> for Ident {\n    fn eq(&self, other: &str) -> bool {\n        self.name == other\n    }\n}\n\nimpl PartialEq<&str> for Ident {\n    fn eq(&self, other: &&str) -> bool {\n        self.name == *other\n    }\n}\n\nimpl PartialEq<Ident> for Ident {\n    fn eq(&self, other: &Ident) -> bool {\n        self.name == other.name\n    }\n}\n\nimpl fmt::Display for Ident {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        if self.raw {\n            f.write_str(\"r#\")?;\n        }\n        f.write_str(&*self.name)\n    }\n}\n\nimpl FromStr for Cfg {\n    type Err = ParseError;\n\n    fn from_str(s: &str) -> Result<Cfg, Self::Err> {\n        let mut p = Parser::new(s);\n        let e = p.cfg()?;\n        if let Some(rest) = p.rest() {\n            return Err(ParseError::new(\n                p.t.orig,\n                UnterminatedExpression(rest.to_string()),\n            ));\n        }\n        Ok(e)\n    }\n}\n\nimpl fmt::Display for Cfg {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match *self {\n            Cfg::Name(ref s) => s.fmt(f),\n            Cfg::KeyPair(ref k, ref v) => write!(f, \"{} = \\\"{}\\\"\", k, v),\n        }\n    }\n}\n\nimpl CfgExpr {\n    /// Utility function to check if the key, \"cfg(..)\" matches the `target_cfg`\n    pub fn matches_key(key: &str, target_cfg: &[Cfg]) -> bool {\n        if key.starts_with(\"cfg(\") && key.ends_with(')') {\n            let cfg = &key[4..key.len() - 1];\n\n            CfgExpr::from_str(cfg)\n                .ok()\n                .map(|ce| ce.matches(target_cfg))\n                .unwrap_or(false)\n        } else {\n            false\n        }\n    }\n\n    pub fn matches(&self, cfg: &[Cfg]) -> bool {\n        match *self {\n            CfgExpr::Not(ref e) => !e.matches(cfg),\n            CfgExpr::All(ref e) => e.iter().all(|e| e.matches(cfg)),\n            CfgExpr::Any(ref e) => e.iter().any(|e| e.matches(cfg)),\n            CfgExpr::Value(ref e) => cfg.contains(e),\n            CfgExpr::True => true,\n            CfgExpr::False => false,\n        }\n    }\n}\n\nimpl FromStr for CfgExpr {\n    type Err = ParseError;\n\n    fn from_str(s: &str) -> Result<CfgExpr, Self::Err> {\n        let mut p = Parser::new(s);\n        let e = p.expr()?;\n        if let Some(rest) = p.rest() {\n            return Err(ParseError::new(\n                p.t.orig,\n                UnterminatedExpression(rest.to_string()),\n            ));\n        }\n        Ok(e)\n    }\n}\n\nimpl fmt::Display for CfgExpr {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match *self {\n            CfgExpr::Not(ref e) => write!(f, \"not({})\", e),\n            CfgExpr::All(ref e) => write!(f, \"all({})\", CommaSep(e)),\n            CfgExpr::Any(ref e) => write!(f, \"any({})\", CommaSep(e)),\n            CfgExpr::Value(ref e) => write!(f, \"{}\", e),\n            CfgExpr::True => write!(f, \"true\"),\n            CfgExpr::False => write!(f, \"false\"),\n        }\n    }\n}\n\nstruct CommaSep<'a, T>(&'a [T]);\n\nimpl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        for (i, v) in self.0.iter().enumerate() {\n            if i > 0 {\n                write!(f, \", \")?;\n            }\n            write!(f, \"{}\", v)?;\n        }\n        Ok(())\n    }\n}\n\nimpl<'a> Parser<'a> {\n    fn new(s: &'a str) -> Parser<'a> {\n        Parser {\n            t: Tokenizer {\n                s: s.char_indices().peekable(),\n                orig: s,\n            },\n        }\n    }\n\n    fn expr(&mut self) -> Result<CfgExpr, ParseError> {\n        match self.peek() {\n            Some(Ok(Token::Ident(false, op @ \"all\")))\n            | Some(Ok(Token::Ident(false, op @ \"any\"))) => {\n                self.t.next();\n                let mut e = Vec::new();\n                self.eat(&Token::LeftParen)?;\n                while !self.r#try(&Token::RightParen) {\n                    e.push(self.expr()?);\n                    if !self.r#try(&Token::Comma) {\n                        self.eat(&Token::RightParen)?;\n                        break;\n                    }\n                }\n                if op == \"all\" {\n                    Ok(CfgExpr::All(e))\n                } else {\n                    Ok(CfgExpr::Any(e))\n                }\n            }\n            Some(Ok(Token::Ident(false, \"not\"))) => {\n                self.t.next();\n                self.eat(&Token::LeftParen)?;\n                let e = self.expr()?;\n                self.eat(&Token::RightParen)?;\n                Ok(CfgExpr::Not(Box::new(e)))\n            }\n            Some(Ok(..)) => self.cfg().map(|v| match v {\n                Cfg::Name(n) if n == \"true\" => CfgExpr::True,\n                Cfg::Name(n) if n == \"false\" => CfgExpr::False,\n                v => CfgExpr::Value(v),\n            }),\n            Some(Err(..)) => Err(self.t.next().unwrap().err().unwrap()),\n            None => Err(ParseError::new(\n                self.t.orig,\n                IncompleteExpr(\"start of a cfg expression\"),\n            )),\n        }\n    }\n\n    fn cfg(&mut self) -> Result<Cfg, ParseError> {\n        match self.t.next() {\n            Some(Ok(Token::Ident(raw, name))) => {\n                let e = if self.r#try(&Token::Equals) {\n                    let val = match self.t.next() {\n                        Some(Ok(Token::String(s))) => s,\n                        Some(Ok(t)) => {\n                            return Err(ParseError::new(\n                                self.t.orig,\n                                UnexpectedToken {\n                                    expected: \"a string\",\n                                    found: t.classify(),\n                                },\n                            ));\n                        }\n                        Some(Err(e)) => return Err(e),\n                        None => {\n                            return Err(ParseError::new(self.t.orig, IncompleteExpr(\"a string\")));\n                        }\n                    };\n                    Cfg::KeyPair(\n                        Ident {\n                            name: name.to_string(),\n                            raw,\n                        },\n                        val.to_string(),\n                    )\n                } else {\n                    Cfg::Name(Ident {\n                        name: name.to_string(),\n                        raw,\n                    })\n                };\n                Ok(e)\n            }\n            Some(Ok(t)) => Err(ParseError::new(\n                self.t.orig,\n                UnexpectedToken {\n                    expected: \"identifier\",\n                    found: t.classify(),\n                },\n            )),\n            Some(Err(e)) => Err(e),\n            None => Err(ParseError::new(self.t.orig, IncompleteExpr(\"identifier\"))),\n        }\n    }\n\n    fn peek(&mut self) -> Option<Result<Token<'a>, ParseError>> {\n        self.t.clone().next()\n    }\n\n    fn r#try(&mut self, token: &Token<'a>) -> bool {\n        match self.peek() {\n            Some(Ok(ref t)) if token == t => {}\n            _ => return false,\n        }\n        self.t.next();\n        true\n    }\n\n    fn eat(&mut self, token: &Token<'a>) -> Result<(), ParseError> {\n        match self.t.next() {\n            Some(Ok(ref t)) if token == t => Ok(()),\n            Some(Ok(t)) => Err(ParseError::new(\n                self.t.orig,\n                UnexpectedToken {\n                    expected: token.classify(),\n                    found: t.classify(),\n                },\n            )),\n            Some(Err(e)) => Err(e),\n            None => Err(ParseError::new(\n                self.t.orig,\n                IncompleteExpr(token.classify()),\n            )),\n        }\n    }\n\n    /// Returns the rest of the input from the current location.\n    fn rest(&self) -> Option<&str> {\n        let mut s = self.t.s.clone();\n        loop {\n            match s.next() {\n                Some((_, ' ')) => {}\n                Some((start, _ch)) => return Some(&self.t.orig[start..]),\n                None => return None,\n            }\n        }\n    }\n}\n\nimpl<'a> Iterator for Tokenizer<'a> {\n    type Item = Result<Token<'a>, ParseError>;\n\n    fn next(&mut self) -> Option<Result<Token<'a>, ParseError>> {\n        loop {\n            match self.s.next() {\n                Some((_, ' ')) => {}\n                Some((_, '(')) => return Some(Ok(Token::LeftParen)),\n                Some((_, ')')) => return Some(Ok(Token::RightParen)),\n                Some((_, ',')) => return Some(Ok(Token::Comma)),\n                Some((_, '=')) => return Some(Ok(Token::Equals)),\n                Some((start, '\"')) => {\n                    while let Some((end, ch)) = self.s.next() {\n                        if ch == '\"' {\n                            return Some(Ok(Token::String(&self.orig[start + 1..end])));\n                        }\n                    }\n                    return Some(Err(ParseError::new(self.orig, UnterminatedString)));\n                }\n                Some((start, ch)) if is_ident_start(ch) => {\n                    let (start, raw) = if ch == 'r' {\n                        if let Some(&(_pos, '#')) = self.s.peek() {\n                            // starts with `r#` is a raw ident\n                            self.s.next();\n                            if let Some((start, ch)) = self.s.next() {\n                                if is_ident_start(ch) {\n                                    (start, true)\n                                } else {\n                                    // not a starting ident character\n                                    return Some(Err(ParseError::new(\n                                        self.orig,\n                                        UnexpectedChar(ch),\n                                    )));\n                                }\n                            } else {\n                                // not followed by a ident, error out\n                                return Some(Err(ParseError::new(\n                                    self.orig,\n                                    IncompleteExpr(\"identifier\"),\n                                )));\n                            }\n                        } else {\n                            // starts with `r` but not does continue with `#`\n                            // cannot be a raw ident\n                            (start, false)\n                        }\n                    } else {\n                        // do not start with `r`, cannot be a raw ident\n                        (start, false)\n                    };\n                    while let Some(&(end, ch)) = self.s.peek() {\n                        if !is_ident_rest(ch) {\n                            return Some(Ok(Token::Ident(raw, &self.orig[start..end])));\n                        } else {\n                            self.s.next();\n                        }\n                    }\n                    return Some(Ok(Token::Ident(raw, &self.orig[start..])));\n                }\n                Some((_, ch)) => {\n                    return Some(Err(ParseError::new(self.orig, UnexpectedChar(ch))));\n                }\n                None => return None,\n            }\n        }\n    }\n}\n\nfn is_ident_start(ch: char) -> bool {\n    ch == '_' || ch.is_ascii_alphabetic()\n}\n\nfn is_ident_rest(ch: char) -> bool {\n    is_ident_start(ch) || ch.is_ascii_digit()\n}\n\nimpl<'a> Token<'a> {\n    fn classify(&self) -> &'static str {\n        match *self {\n            Token::LeftParen => \"`(`\",\n            Token::RightParen => \"`)`\",\n            Token::Ident(..) => \"an identifier\",\n            Token::Comma => \"`,`\",\n            Token::Equals => \"`=`\",\n            Token::String(..) => \"a string\",\n        }\n    }\n}\n"
  },
  {
    "path": "crates/cargo-platform/src/error.rs",
    "content": "use std::fmt;\n\n#[derive(Debug)]\npub struct ParseError {\n    kind: ParseErrorKind,\n    orig: String,\n}\n\n#[non_exhaustive]\n#[derive(Debug)]\npub enum ParseErrorKind {\n    UnterminatedString,\n    UnexpectedChar(char),\n    UnexpectedToken {\n        expected: &'static str,\n        found: &'static str,\n    },\n    IncompleteExpr(&'static str),\n    UnterminatedExpression(String),\n    InvalidTarget(String),\n}\n\nimpl fmt::Display for ParseError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(\n            f,\n            \"failed to parse `{}` as a cfg expression: {}\",\n            self.orig, self.kind\n        )\n    }\n}\n\nimpl fmt::Display for ParseErrorKind {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        use ParseErrorKind::*;\n        match self {\n            UnterminatedString => write!(f, \"unterminated string in cfg\"),\n            UnexpectedChar(ch) => write!(\n                f,\n                \"unexpected character `{}` in cfg, expected parens, a comma, \\\n                 an identifier, or a string\",\n                ch\n            ),\n            UnexpectedToken { expected, found } => {\n                write!(f, \"expected {}, found {}\", expected, found)\n            }\n            IncompleteExpr(expected) => {\n                write!(f, \"expected {}, but cfg expression ended\", expected)\n            }\n            UnterminatedExpression(s) => {\n                write!(f, \"unexpected content `{}` found after cfg expression\", s)\n            }\n            InvalidTarget(s) => write!(f, \"invalid target specifier: {}\", s),\n        }\n    }\n}\n\nimpl std::error::Error for ParseError {}\n\nimpl ParseError {\n    pub fn new(orig: &str, kind: ParseErrorKind) -> ParseError {\n        ParseError {\n            kind,\n            orig: orig.to_string(),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/cargo-platform/src/lib.rs",
    "content": "//! Platform definition used by Cargo.\n//!\n//! This defines a [`Platform`] type which is used in Cargo to specify a target platform.\n//! There are two kinds, a named target like `x86_64-apple-darwin`, and a \"cfg expression\"\n//! like `cfg(any(target_os = \"macos\", target_os = \"ios\"))`.\n//!\n//! See `examples/matches.rs` for an example of how to match against a `Platform`.\n//!\n//! > This crate is maintained by the Cargo team for use by the wider\n//! > ecosystem. This crate follows semver compatibility for its APIs.\n//!\n//! [`Platform`]: enum.Platform.html\n\nuse std::str::FromStr;\nuse std::{fmt, path::Path};\n\nmod cfg;\nmod error;\n\nuse cfg::KEYWORDS;\npub use cfg::{Cfg, CfgExpr, Ident};\npub use error::{ParseError, ParseErrorKind};\n\n/// Platform definition.\n#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]\npub enum Platform {\n    /// A named platform, like `x86_64-apple-darwin`.\n    Name(String),\n    /// A cfg expression, like `cfg(windows)`.\n    Cfg(CfgExpr),\n}\n\nimpl Platform {\n    /// Returns whether the Platform matches the given target and cfg.\n    ///\n    /// The named target and cfg values should be obtained from `rustc`.\n    pub fn matches(&self, name: &str, cfg: &[Cfg]) -> bool {\n        match *self {\n            Platform::Name(ref p) => p == name,\n            Platform::Cfg(ref p) => p.matches(cfg),\n        }\n    }\n\n    fn validate_named_platform(name: &str) -> Result<(), ParseError> {\n        if let Some(ch) = name\n            .chars()\n            .find(|&c| !(c.is_alphanumeric() || c == '_' || c == '-' || c == '.'))\n        {\n            if name.chars().any(|c| c == '(') {\n                return Err(ParseError::new(\n                    name,\n                    ParseErrorKind::InvalidTarget(\n                        \"unexpected `(` character, cfg expressions must start with `cfg(`\"\n                            .to_string(),\n                    ),\n                ));\n            }\n            return Err(ParseError::new(\n                name,\n                ParseErrorKind::InvalidTarget(format!(\n                    \"unexpected character {} in target name\",\n                    ch\n                )),\n            ));\n        }\n        Ok(())\n    }\n\n    pub fn check_cfg_attributes(&self, warnings: &mut Vec<String>) {\n        fn check_cfg_expr(expr: &CfgExpr, warnings: &mut Vec<String>) {\n            match *expr {\n                CfgExpr::Not(ref e) => check_cfg_expr(e, warnings),\n                CfgExpr::All(ref e) | CfgExpr::Any(ref e) => {\n                    for e in e {\n                        check_cfg_expr(e, warnings);\n                    }\n                }\n                CfgExpr::Value(ref e) => match e {\n                    Cfg::Name(name) => match name.as_str() {\n                        \"test\" | \"debug_assertions\" | \"proc_macro\" =>\n                            warnings.push(format!(\n                                \"Found `{}` in `target.'cfg(...)'.dependencies`. \\\n                                 This value is not supported for selecting dependencies \\\n                                 and will not work as expected. \\\n                                 To learn more visit \\\n                                 https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies\",\n                                 name\n                            )),\n                        _ => (),\n                    },\n                    Cfg::KeyPair(name, _) => if name.as_str() == \"feature\" {\n                        warnings.push(String::from(\n                            \"Found `feature = ...` in `target.'cfg(...)'.dependencies`. \\\n                             This key is not supported for selecting dependencies \\\n                             and will not work as expected. \\\n                             Use the [features] section instead: \\\n                             https://doc.rust-lang.org/cargo/reference/features.html\"\n                        ))\n                    },\n                }\n                CfgExpr::True | CfgExpr::False => {},\n            }\n        }\n\n        if let Platform::Cfg(cfg) = self {\n            check_cfg_expr(cfg, warnings);\n        }\n    }\n\n    pub fn check_cfg_keywords(&self, warnings: &mut Vec<String>, path: &Path) {\n        fn check_cfg_expr(expr: &CfgExpr, warnings: &mut Vec<String>, path: &Path) {\n            match *expr {\n                CfgExpr::Not(ref e) => check_cfg_expr(e, warnings, path),\n                CfgExpr::All(ref e) | CfgExpr::Any(ref e) => {\n                    for e in e {\n                        check_cfg_expr(e, warnings, path);\n                    }\n                }\n                CfgExpr::True | CfgExpr::False => {}\n                CfgExpr::Value(ref e) => match e {\n                    Cfg::Name(name) | Cfg::KeyPair(name, _) => {\n                        if !name.raw && KEYWORDS.contains(&name.as_str()) {\n                            warnings.push(format!(\n                                \"[{}] future-incompatibility: `cfg({e})` is deprecated as `{name}` is a keyword \\\n                                 and not an identifier and should not have have been accepted in this position.\\n \\\n                                 | this was previously accepted by Cargo but is being phased out; it will become a hard error in a future release!\\n \\\n                                 |\\n \\\n                                 | help: use raw-idents instead: `cfg(r#{name})`\",\n                                 path.display()\n                            ));\n                        }\n                    }\n                },\n            }\n        }\n\n        if let Platform::Cfg(cfg) = self {\n            check_cfg_expr(cfg, warnings, path);\n        }\n    }\n}\n\nimpl serde_core::Serialize for Platform {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: serde_core::Serializer,\n    {\n        self.to_string().serialize(s)\n    }\n}\n\nimpl<'de> serde_core::Deserialize<'de> for Platform {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde_core::Deserializer<'de>,\n    {\n        let s = String::deserialize(deserializer)?;\n        FromStr::from_str(&s).map_err(serde_core::de::Error::custom)\n    }\n}\n\nimpl FromStr for Platform {\n    type Err = ParseError;\n\n    fn from_str(s: &str) -> Result<Platform, ParseError> {\n        if let Some(s) = s.strip_prefix(\"cfg(\").and_then(|s| s.strip_suffix(')')) {\n            s.parse().map(Platform::Cfg)\n        } else {\n            Platform::validate_named_platform(s)?;\n            Ok(Platform::Name(s.to_string()))\n        }\n    }\n}\n\nimpl fmt::Display for Platform {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match *self {\n            Platform::Name(ref n) => n.fmt(f),\n            Platform::Cfg(ref e) => write!(f, \"cfg({})\", e),\n        }\n    }\n}\n"
  },
  {
    "path": "crates/cargo-platform/tests/test_cfg.rs",
    "content": "use cargo_platform::{Cfg, CfgExpr, Ident, Platform};\nuse std::fmt;\nuse std::str::FromStr;\n\nmacro_rules! c {\n    ($a:ident) => {\n        Cfg::Name(Ident {\n            name: stringify!($a).to_string(),\n            raw: false,\n        })\n    };\n    (r # $a:ident) => {\n        Cfg::Name(Ident {\n            name: stringify!($a).to_string(),\n            raw: true,\n        })\n    };\n    ($a:ident = $e:expr) => {\n        Cfg::KeyPair(\n            Ident {\n                name: stringify!($a).to_string(),\n                raw: false,\n            },\n            $e.to_string(),\n        )\n    };\n    (r # $a:ident = $e:expr) => {\n        Cfg::KeyPair(\n            Ident {\n                name: stringify!($a).to_string(),\n                raw: true,\n            },\n            $e.to_string(),\n        )\n    };\n}\n\nmacro_rules! e {\n    (any($($t:tt),*)) => (CfgExpr::Any(vec![$(e!($t)),*]));\n    (all($($t:tt),*)) => (CfgExpr::All(vec![$(e!($t)),*]));\n    (not($($t:tt)*)) => (CfgExpr::Not(Box::new(e!($($t)*))));\n    (true) => (CfgExpr::True);\n    (false) => (CfgExpr::False);\n    (($($t:tt)*)) => (e!($($t)*));\n    ($($t:tt)*) => (CfgExpr::Value(c!($($t)*)));\n}\n\nfn good<T>(s: &str, expected: T)\nwhere\n    T: FromStr + PartialEq + fmt::Debug,\n    T::Err: fmt::Display,\n{\n    let c = match T::from_str(s) {\n        Ok(c) => c,\n        Err(e) => panic!(\"failed to parse `{}`: {}\", s, e),\n    };\n    assert_eq!(c, expected);\n}\n\nfn bad<T>(s: &str, err: &str)\nwhere\n    T: FromStr + fmt::Display,\n    T::Err: fmt::Display,\n{\n    let e = match T::from_str(s) {\n        Ok(cfg) => panic!(\"expected `{}` to not parse but got {}\", s, cfg),\n        Err(e) => e.to_string(),\n    };\n    assert!(\n        e.contains(err),\n        \"when parsing `{}`,\\n\\\"{}\\\" not contained \\\n         inside: {}\",\n        s,\n        err,\n        e\n    );\n}\n\n#[test]\nfn cfg_syntax() {\n    good(\"foo\", c!(foo));\n    good(\"_bar\", c!(_bar));\n    good(\" foo\", c!(foo));\n    good(\" foo  \", c!(foo));\n    good(\"r#foo\", c!(r # foo));\n    good(\" foo  = \\\"bar\\\"\", c!(foo = \"bar\"));\n    good(\"foo=\\\"\\\"\", c!(foo = \"\"));\n    good(\"r#foo=\\\"\\\"\", c!(r # foo = \"\"));\n    good(\" foo=\\\"3\\\"      \", c!(foo = \"3\"));\n    good(\"foo = \\\"3 e\\\"\", c!(foo = \"3 e\"));\n    good(\" r#foo = \\\"3 e\\\"\", c!(r # foo = \"3 e\"));\n}\n\n#[test]\nfn cfg_syntax_bad() {\n    bad::<Cfg>(\"\", \"but cfg expression ended\");\n    bad::<Cfg>(\" \", \"but cfg expression ended\");\n    bad::<Cfg>(\"\\t\", \"unexpected character\");\n    bad::<Cfg>(\"7\", \"unexpected character\");\n    bad::<Cfg>(\"=\", \"expected identifier\");\n    bad::<Cfg>(\",\", \"expected identifier\");\n    bad::<Cfg>(\"(\", \"expected identifier\");\n    bad::<Cfg>(\"foo (\", \"unexpected content `(` found after cfg expression\");\n    bad::<Cfg>(\"bar =\", \"expected a string\");\n    bad::<Cfg>(\"bar = \\\"\", \"unterminated string\");\n    bad::<Cfg>(\n        \"foo, bar\",\n        \"unexpected content `, bar` found after cfg expression\",\n    );\n    bad::<Cfg>(\"r# foo\", \"unexpected character\");\n    bad::<Cfg>(\"r #foo\", \"unexpected content\");\n    bad::<Cfg>(\"r#\\\"foo\\\"\", \"unexpected character\");\n    bad::<Cfg>(\"foo = r#\\\"\\\"\", \"unexpected character\");\n}\n\n#[test]\nfn cfg_expr() {\n    good(\"foo\", e!(foo));\n    good(\"_bar\", e!(_bar));\n    good(\" foo\", e!(foo));\n    good(\" foo  \", e!(foo));\n    good(\" foo  = \\\"bar\\\"\", e!(foo = \"bar\"));\n    good(\"foo=\\\"\\\"\", e!(foo = \"\"));\n    good(\" foo=\\\"3\\\"      \", e!(foo = \"3\"));\n    good(\"foo = \\\"3 e\\\"\", e!(foo = \"3 e\"));\n\n    good(\"true\", e!(true));\n    good(\"false\", e!(false));\n\n    good(\"all()\", e!(all()));\n    good(\"all(a)\", e!(all(a)));\n    good(\"all(a, b)\", e!(all(a, b)));\n    good(\"all(a, )\", e!(all(a)));\n    good(\"not(a = \\\"b\\\")\", e!(not(a = \"b\")));\n    good(\"not(all(a))\", e!(not(all(a))));\n}\n\n#[test]\nfn cfg_expr_bad() {\n    bad::<CfgExpr>(\" \", \"but cfg expression ended\");\n    bad::<CfgExpr>(\" all\", \"expected `(`\");\n    bad::<CfgExpr>(\"all(a\", \"expected `)`\");\n    bad::<CfgExpr>(\"not\", \"expected `(`\");\n    bad::<CfgExpr>(\"not(a\", \"expected `)`\");\n    bad::<CfgExpr>(\"a = \", \"expected a string\");\n    bad::<CfgExpr>(\"all(not())\", \"expected identifier\");\n    bad::<CfgExpr>(\n        \"foo(a)\",\n        \"unexpected content `(a)` found after cfg expression\",\n    );\n}\n\n#[test]\nfn cfg_matches() {\n    assert!(e!(foo).matches(&[c!(bar), c!(foo), c!(baz)]));\n    assert!(e!(any(foo)).matches(&[c!(bar), c!(foo), c!(baz)]));\n    assert!(e!(any(foo, bar)).matches(&[c!(bar)]));\n    assert!(e!(any(foo, bar)).matches(&[c!(foo)]));\n    assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)]));\n    assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)]));\n    assert!(e!(not(foo)).matches(&[c!(bar)]));\n    assert!(e!(not(foo)).matches(&[]));\n    assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(bar)]));\n    assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo), c!(bar)]));\n    assert!(e!(foo).matches(&[c!(r # foo)]));\n    assert!(e!(r # foo).matches(&[c!(foo)]));\n    assert!(e!(r # foo).matches(&[c!(r # foo)]));\n\n    assert!(!e!(foo).matches(&[]));\n    assert!(!e!(foo).matches(&[c!(bar)]));\n    assert!(!e!(foo).matches(&[c!(fo)]));\n    assert!(!e!(any(foo)).matches(&[]));\n    assert!(!e!(any(foo)).matches(&[c!(bar)]));\n    assert!(!e!(any(foo)).matches(&[c!(bar), c!(baz)]));\n    assert!(!e!(all(foo)).matches(&[c!(bar), c!(baz)]));\n    assert!(!e!(all(foo, bar)).matches(&[c!(bar)]));\n    assert!(!e!(all(foo, bar)).matches(&[c!(foo)]));\n    assert!(!e!(all(foo, bar)).matches(&[]));\n    assert!(!e!(not(bar)).matches(&[c!(bar)]));\n    assert!(!e!(not(bar)).matches(&[c!(baz), c!(bar)]));\n    assert!(!e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo)]));\n}\n\n#[test]\nfn bad_target_name() {\n    bad::<Platform>(\n        \"any(cfg(unix), cfg(windows))\",\n        \"failed to parse `any(cfg(unix), cfg(windows))` as a cfg expression: \\\n         invalid target specifier: unexpected `(` character, \\\n         cfg expressions must start with `cfg(`\",\n    );\n    bad::<Platform>(\n        \"!foo\",\n        \"failed to parse `!foo` as a cfg expression: \\\n         invalid target specifier: unexpected character ! in target name\",\n    );\n}\n\n#[test]\nfn round_trip_platform() {\n    fn rt(s: &str) {\n        let p = Platform::from_str(s).unwrap();\n        let s2 = p.to_string();\n        let p2 = Platform::from_str(&s2).unwrap();\n        assert_eq!(p, p2);\n    }\n    rt(\"x86_64-apple-darwin\");\n    rt(\"foo\");\n    rt(\"cfg(windows)\");\n    rt(\"cfg(target_os = \\\"windows\\\")\");\n    rt(\n        \"cfg(any(all(any(target_os = \\\"android\\\", target_os = \\\"linux\\\"), \\\n         any(target_arch = \\\"aarch64\\\", target_arch = \\\"arm\\\", target_arch = \\\"powerpc64\\\", \\\n         target_arch = \\\"x86\\\", target_arch = \\\"x86_64\\\")), \\\n         all(target_os = \\\"freebsd\\\", target_arch = \\\"x86_64\\\")))\",\n    );\n}\n\n#[test]\nfn check_cfg_attributes() {\n    fn ok(s: &str) {\n        let p = Platform::Cfg(s.parse().unwrap());\n        let mut warnings = Vec::new();\n        p.check_cfg_attributes(&mut warnings);\n        assert!(\n            warnings.is_empty(),\n            \"Expected no warnings but got: {:?}\",\n            warnings,\n        );\n    }\n\n    fn warn(s: &str, names: &[&str]) {\n        let p = Platform::Cfg(s.parse().unwrap());\n        let mut warnings = Vec::new();\n        p.check_cfg_attributes(&mut warnings);\n        assert_eq!(\n            warnings.len(),\n            names.len(),\n            \"Expecter warnings about {:?} but got {:?}\",\n            names,\n            warnings,\n        );\n        for (name, warning) in names.iter().zip(warnings.iter()) {\n            assert!(\n                warning.contains(name),\n                \"Expected warning about '{}' but got: {}\",\n                name,\n                warning,\n            );\n        }\n    }\n\n    ok(\"unix\");\n    ok(\"windows\");\n    ok(\"any(not(unix), windows)\");\n    ok(\"foo\");\n    ok(\"true\");\n    ok(\"false\");\n\n    ok(\"target_arch = \\\"abc\\\"\");\n    ok(\"target_feature = \\\"abc\\\"\");\n    ok(\"target_os = \\\"abc\\\"\");\n    ok(\"target_family = \\\"abc\\\"\");\n    ok(\"target_env = \\\"abc\\\"\");\n    ok(\"target_endian = \\\"abc\\\"\");\n    ok(\"target_pointer_width = \\\"abc\\\"\");\n    ok(\"target_vendor = \\\"abc\\\"\");\n    ok(\"bar = \\\"def\\\"\");\n\n    warn(\"test\", &[\"test\"]);\n    warn(\"debug_assertions\", &[\"debug_assertions\"]);\n    warn(\"proc_macro\", &[\"proc_macro\"]);\n    warn(\"feature = \\\"abc\\\"\", &[\"feature\"]);\n\n    warn(\"any(not(debug_assertions), windows)\", &[\"debug_assertions\"]);\n    warn(\n        \"any(not(feature = \\\"def\\\"), target_arch = \\\"abc\\\")\",\n        &[\"feature\"],\n    );\n    warn(\n        \"any(not(target_os = \\\"windows\\\"), proc_macro)\",\n        &[\"proc_macro\"],\n    );\n    warn(\n        \"any(not(feature = \\\"windows\\\"), proc_macro)\",\n        &[\"feature\", \"proc_macro\"],\n    );\n    warn(\n        \"all(not(debug_assertions), any(windows, proc_macro))\",\n        &[\"debug_assertions\", \"proc_macro\"],\n    );\n}\n"
  },
  {
    "path": "crates/cargo-test-macro/Cargo.toml",
    "content": "[package]\nname = \"cargo-test-macro\"\nversion = \"0.4.11\"\nedition.workspace = true\nrust-version = \"1.94\"  # MSRV:1\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"Helper proc-macro for Cargo's testsuite.\"\n\n[lib]\nproc-macro = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/cargo-test-macro/README.md",
    "content": "> This crate is maintained by the Cargo team, primarily for use by Cargo\n> and not intended for external use. This\n> crate may make major changes to its APIs or be deprecated without warning.\n"
  },
  {
    "path": "crates/cargo-test-macro/src/lib.rs",
    "content": "//! # Cargo test macro.\n//!\n//! This is meant to be consumed alongside `cargo-test-support`. See\n//! <https://rust-lang.github.io/cargo/contrib/> for a guide on writing tests.\n//!\n//! > This crate is maintained by the Cargo team, primarily for use by Cargo\n//! > and not intended for external use. This\n//! > crate may make major changes to its APIs or be deprecated without warning.\n\nuse proc_macro::*;\nuse std::path::Path;\nuse std::process::Command;\nuse std::sync::LazyLock;\n\n/// Replacement for `#[test]`\n///\n/// The `#[cargo_test]` attribute extends `#[test]` with some setup before starting the test.\n/// It will create a filesystem \"sandbox\" under the \"cargo integration test\" directory for each test, such as `/path/to/cargo/target/tmp/cit/t123/`.\n/// The sandbox will contain a `home` directory that will be used instead of your normal home directory.\n///\n/// The `#[cargo_test]` attribute takes several options that will affect how the test is generated.\n/// They are listed in parentheses separated with commas, such as:\n///\n/// ```rust,ignore\n/// #[cargo_test(nightly, reason = \"-Zfoo is unstable\")]\n/// ```\n///\n/// The options it supports are:\n///\n/// * `>=1.64` --- This indicates that the test will only run with the given version of `rustc` or newer.\n///   This can be used when a new `rustc` feature has been stabilized that the test depends on.\n///   If this is specified, a `reason` is required to explain why it is being checked.\n/// * `nightly` --- This will cause the test to be ignored if not running on the nightly toolchain.\n///   This is useful for tests that use unstable options in `rustc` or `rustdoc`.\n///   These tests are run in Cargo's CI, but are disabled in rust-lang/rust's CI due to the difficulty of updating both repos simultaneously.\n///   A `reason` field is required to explain why it is nightly-only.\n/// * `requires = \"<cmd>\"` --- This indicates a command that is required to be installed to be run.\n///   For example, `requires = \"rustfmt\"` means the test will only run if the executable `rustfmt` is installed.\n///   These tests are *always* run on CI.\n///   This is mainly used to avoid requiring contributors from having every dependency installed.\n/// * `build_std_real` --- This is a \"real\" `-Zbuild-std` test (in the `build_std` integration test).\n///   This only runs on nightly, and only if the environment variable `CARGO_RUN_BUILD_STD_TESTS` is set (these tests on run on Linux).\n/// * `build_std_mock` --- This is a \"mock\" `-Zbuild-std` test (which uses a mock standard library).\n///   This only runs on nightly, and is disabled for windows-gnu.\n/// * `public_network_test` --- This tests contacts the public internet.\n///   These tests are disabled unless the `CARGO_PUBLIC_NETWORK_TESTS` environment variable is set.\n///   Use of this should be *extremely rare*, please avoid using it if possible.\n///   The hosts it contacts should have a relatively high confidence that they are reliable and stable (such as github.com), especially in CI.\n///   The tests should be carefully considered for developer security and privacy as well.\n/// * `container_test` --- This indicates that it is a test that uses Docker.\n///   These tests are disabled unless the `CARGO_CONTAINER_TESTS` environment variable is set.\n///   This requires that you have Docker installed.\n///   The SSH tests also assume that you have OpenSSH installed.\n///   These should work on Linux, macOS, and Windows where possible.\n///   Unfortunately these tests are not run in CI for macOS or Windows (no Docker on macOS, and Windows does not support Linux images).\n///   See [`cargo-test-support::containers`](https://doc.rust-lang.org/nightly/nightly-rustc/cargo_test_support/containers) for more on writing these tests.\n/// * `ignore_windows=\"reason\"` --- Indicates that the test should be ignored on windows for the given reason.\n#[proc_macro_attribute]\npub fn cargo_test(attr: TokenStream, item: TokenStream) -> TokenStream {\n    // Ideally these options would be embedded in the test itself. However, I\n    // find it very helpful to have the test clearly state whether or not it\n    // is ignored. It would be nice to have some kind of runtime ignore\n    // support (such as\n    // https://internals.rust-lang.org/t/pre-rfc-skippable-tests/14611).\n    //\n    // Unfortunately a big drawback here is that if the environment changes\n    // (such as the existence of the `git` CLI), this will not trigger a\n    // rebuild and the test will still be ignored. In theory, something like\n    // `tracked_env` or `tracked_path`\n    // (https://github.com/rust-lang/rust/issues/99515) could help with this,\n    // but they don't really handle the absence of files well.\n    let mut ignore = false;\n    let mut requires_reason = false;\n    let mut explicit_reason = None;\n    let mut implicit_reasons = Vec::new();\n    macro_rules! set_ignore {\n        ($predicate:expr, $($arg:tt)*) => {\n            let p = $predicate;\n            ignore |= p;\n            if p {\n                implicit_reasons.push(std::fmt::format(format_args!($($arg)*)));\n            }\n        };\n    }\n    let is_not_nightly = !version().1;\n    for rule in split_rules(attr) {\n        match rule.as_str() {\n            \"build_std_real\" => {\n                // Only run the \"real\" build-std tests on nightly and with an\n                // explicit opt-in (these generally only work on linux, and\n                // have some extra requirements, and are slow, and can pollute\n                // the environment since it downloads dependencies).\n                set_ignore!(is_not_nightly, \"requires nightly\");\n                set_ignore!(\n                    option_env!(\"CARGO_RUN_BUILD_STD_TESTS\").is_none(),\n                    \"CARGO_RUN_BUILD_STD_TESTS must be set\"\n                );\n            }\n            \"build_std_mock\" => {\n                // Only run the \"mock\" build-std tests on nightly and disable\n                // for windows-gnu which is missing object files (see\n                // https://github.com/rust-lang/wg-cargo-std-aware/issues/46).\n                set_ignore!(is_not_nightly, \"requires nightly\");\n                set_ignore!(\n                    cfg!(all(target_os = \"windows\", target_env = \"gnu\")),\n                    \"does not work on windows-gnu\"\n                );\n            }\n            \"container_test\" => {\n                // These tests must be opt-in because they require docker.\n                set_ignore!(\n                    option_env!(\"CARGO_CONTAINER_TESTS\").is_none(),\n                    \"CARGO_CONTAINER_TESTS must be set\"\n                );\n            }\n            \"public_network_test\" => {\n                // These tests must be opt-in because they touch the public\n                // network. The use of these should be **EXTREMELY RARE**, and\n                // should only touch things which would nearly certainly work\n                // in CI (like github.com).\n                set_ignore!(\n                    option_env!(\"CARGO_PUBLIC_NETWORK_TESTS\").is_none(),\n                    \"CARGO_PUBLIC_NETWORK_TESTS must be set\"\n                );\n            }\n            \"nightly\" => {\n                requires_reason = true;\n                set_ignore!(is_not_nightly, \"requires nightly\");\n            }\n            \"requires_rustup_stable\" => {\n                set_ignore!(\n                    !has_rustup_stable(),\n                    \"rustup or stable toolchain not installed\"\n                );\n            }\n            s if s.starts_with(\"requires=\") => {\n                let command = &s[9..];\n                let Ok(literal) = command.parse::<Literal>() else {\n                    panic!(\"expect a string literal, found: {command}\");\n                };\n                let literal = literal.to_string();\n                let Some(command) = literal\n                    .strip_prefix('\"')\n                    .and_then(|lit| lit.strip_suffix('\"'))\n                else {\n                    panic!(\"expect a quoted string literal, found: {literal}\");\n                };\n                set_ignore!(!has_command(command), \"{command} not installed\");\n            }\n            s if s.starts_with(\">=1.\") => {\n                requires_reason = true;\n                let min_minor = s[4..].parse().unwrap();\n                let minor = version().0;\n                set_ignore!(minor < min_minor, \"requires rustc 1.{minor} or newer\");\n            }\n            s if s.starts_with(\"reason=\") => {\n                explicit_reason = Some(s[7..].parse().unwrap());\n            }\n            s if s.starts_with(\"ignore_windows=\") => {\n                set_ignore!(cfg!(windows), \"{}\", &s[16..s.len() - 1]);\n            }\n            _ => panic!(\"unknown rule {:?}\", rule),\n        }\n    }\n    if requires_reason && explicit_reason.is_none() {\n        panic!(\n            \"#[cargo_test] with a rule also requires a reason, \\\n            such as #[cargo_test(nightly, reason = \\\"needs -Z unstable-thing\\\")]\"\n        );\n    }\n\n    // Construct the appropriate attributes.\n    let span = Span::call_site();\n    let mut ret = TokenStream::new();\n    let add_attr = |ret: &mut TokenStream, attr_name, attr_input| {\n        ret.extend(Some(TokenTree::from(Punct::new('#', Spacing::Alone))));\n        let attr = TokenTree::from(Ident::new(attr_name, span));\n        let mut attr_stream: TokenStream = attr.into();\n        if let Some(input) = attr_input {\n            attr_stream.extend(input);\n        }\n        ret.extend(Some(TokenTree::from(Group::new(\n            Delimiter::Bracket,\n            attr_stream,\n        ))));\n    };\n    add_attr(&mut ret, \"test\", None);\n    if ignore {\n        let reason = explicit_reason\n            .or_else(|| {\n                (!implicit_reasons.is_empty())\n                    .then(|| TokenTree::from(Literal::string(&implicit_reasons.join(\", \"))).into())\n            })\n            .map(|reason: TokenStream| {\n                let mut stream = TokenStream::new();\n                stream.extend(Some(TokenTree::from(Punct::new('=', Spacing::Alone))));\n                stream.extend(Some(reason));\n                stream\n            });\n        add_attr(&mut ret, \"ignore\", reason);\n    }\n\n    let mut test_name = None;\n    let mut num = 0;\n\n    // Find where the function body starts, and add the boilerplate at the start.\n    for token in item {\n        let group = match token {\n            TokenTree::Group(g) => {\n                if g.delimiter() == Delimiter::Brace {\n                    g\n                } else {\n                    ret.extend(Some(TokenTree::Group(g)));\n                    continue;\n                }\n            }\n            TokenTree::Ident(i) => {\n                // The first time through it will be `fn` the second time is the\n                // name of the test.\n                if test_name.is_none() && num == 1 {\n                    test_name = Some(i.to_string())\n                } else {\n                    num += 1;\n                }\n                ret.extend(Some(TokenTree::Ident(i)));\n                continue;\n            }\n            other => {\n                ret.extend(Some(other));\n                continue;\n            }\n        };\n\n        let name = &test_name\n            .clone()\n            .map(|n| n.split(\"::\").next().unwrap().to_string())\n            .unwrap();\n\n        let mut new_body = to_token_stream(&format!(\n            r#\"let _test_guard = {{\n                let tmp_dir = env!(\"CARGO_TARGET_TMPDIR\");\n                let test_dir = cargo_test_support::paths::test_dir(std::file!(), \"{name}\");\n                cargo_test_support::paths::init_root(tmp_dir, test_dir)\n            }};\"#\n        ));\n\n        new_body.extend(group.stream());\n        ret.extend(Some(TokenTree::from(Group::new(\n            group.delimiter(),\n            new_body,\n        ))));\n    }\n\n    ret\n}\n\nfn split_rules(t: TokenStream) -> Vec<String> {\n    let tts: Vec<_> = t.into_iter().collect();\n    tts.split(|tt| match tt {\n        TokenTree::Punct(p) => p.as_char() == ',',\n        _ => false,\n    })\n    .filter(|parts| !parts.is_empty())\n    .map(|parts| {\n        parts\n            .into_iter()\n            .map(|part| part.to_string())\n            .collect::<String>()\n    })\n    .collect()\n}\n\nfn to_token_stream(code: &str) -> TokenStream {\n    code.parse().unwrap()\n}\n\nstatic VERSION: std::sync::LazyLock<(u32, bool)> = LazyLock::new(|| {\n    let output = Command::new(\"rustc\")\n        .arg(\"-V\")\n        .output()\n        .expect(\"rustc should run\");\n    let stdout = std::str::from_utf8(&output.stdout).expect(\"utf8\");\n    let vers = stdout.split_whitespace().skip(1).next().unwrap();\n    let is_nightly = option_env!(\"CARGO_TEST_DISABLE_NIGHTLY\").is_none()\n        && (vers.contains(\"-nightly\") || vers.contains(\"-dev\"));\n    let minor = vers.split('.').skip(1).next().unwrap().parse().unwrap();\n    (minor, is_nightly)\n});\n\nfn version() -> (u32, bool) {\n    LazyLock::force(&VERSION).clone()\n}\n\nfn check_command(command_path: &Path, args: &[&str]) -> bool {\n    let mut command = Command::new(command_path);\n    let command_name = command.get_program().to_str().unwrap().to_owned();\n    command.args(args);\n    let output = match command.output() {\n        Ok(output) => output,\n        Err(e) => {\n            // * hg is not installed on GitHub macOS or certain constrained\n            //   environments like Docker. Consider installing it if Cargo\n            //   gains more hg support, but otherwise it isn't critical.\n            // * lldb is not pre-installed on Ubuntu and Windows, so skip.\n            if is_ci() && !matches!(command_name.as_str(), \"hg\" | \"lldb\") {\n                panic!(\"expected command `{command_name}` to be somewhere in PATH: {e}\",);\n            }\n            return false;\n        }\n    };\n    if !output.status.success() {\n        panic!(\n            \"expected command `{command_name}` to be runnable, got error {}:\\n\\\n            stderr:{}\\n\\\n            stdout:{}\\n\",\n            output.status,\n            String::from_utf8_lossy(&output.stderr),\n            String::from_utf8_lossy(&output.stdout)\n        );\n    }\n    true\n}\n\nfn has_command(command: &str) -> bool {\n    use std::env::consts::EXE_EXTENSION;\n    // ALLOWED: For testing cargo itself only.\n    #[allow(clippy::disallowed_methods)]\n    let Some(paths) = std::env::var_os(\"PATH\") else {\n        return false;\n    };\n    std::env::split_paths(&paths)\n        .flat_map(|path| {\n            let candidate = path.join(&command);\n            let with_exe = if EXE_EXTENSION.is_empty() {\n                None\n            } else {\n                Some(candidate.with_extension(EXE_EXTENSION))\n            };\n            std::iter::once(candidate).chain(with_exe)\n        })\n        .find(|p| is_executable(p))\n        .is_some()\n}\n\n#[cfg(unix)]\nfn is_executable<P: AsRef<Path>>(path: P) -> bool {\n    use std::os::unix::prelude::*;\n    std::fs::metadata(path)\n        .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0)\n        .unwrap_or(false)\n}\n\n#[cfg(windows)]\nfn is_executable<P: AsRef<Path>>(path: P) -> bool {\n    path.as_ref().is_file()\n}\n\nfn has_rustup_stable() -> bool {\n    if option_env!(\"CARGO_TEST_DISABLE_NIGHTLY\").is_some() {\n        // This cannot run on rust-lang/rust CI due to the lack of rustup.\n        return false;\n    }\n    // Cargo mucks with PATH on Windows, adding sysroot host libdir, which is\n    // \"bin\", which circumvents the rustup wrapper. Use the path directly from\n    // CARGO_HOME.\n    let home = match option_env!(\"CARGO_HOME\") {\n        Some(home) => home,\n        None if is_ci() => panic!(\"expected to run under rustup\"),\n        None => return false,\n    };\n    let cargo = Path::new(home).join(\"bin/cargo\");\n    check_command(&cargo, &[\"+stable\", \"--version\"])\n}\n\n/// Whether or not this running in a Continuous Integration environment.\nfn is_ci() -> bool {\n    // Consider using `tracked_env` instead of option_env! when it is stabilized.\n    // `tracked_env` will handle changes, but not require rebuilding the macro\n    // itself like option_env does.\n    option_env!(\"CI\").is_some() || option_env!(\"TF_BUILD\").is_some()\n}\n"
  },
  {
    "path": "crates/cargo-test-support/Cargo.toml",
    "content": "[package]\nname = \"cargo-test-support\"\nversion = \"0.11.1\"\nedition.workspace = true\nrust-version = \"1.94\"  # MSRV:1\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"Testing framework for Cargo's testsuite.\"\n\n[dependencies]\nanstream.workspace = true\nanstyle.workspace = true\nanyhow.workspace = true\ncargo-test-macro.workspace = true\ncargo-util.workspace = true\ncrates-io.workspace = true\nfiletime.workspace = true\nflate2.workspace = true\ngit2.workspace = true\nglob.workspace = true\nitertools.workspace = true\npasetors.workspace = true\nregex.workspace = true\nserde = { workspace = true, features = [\"derive\"] }\nserde_json.workspace = true\nsnapbox.workspace = true\ntar.workspace = true\ntime.workspace = true\ntoml = { workspace = true, features = [\"display\", \"serde\"] }\nurl.workspace = true\nwalkdir.workspace = true\n\n[target.'cfg(windows)'.dependencies]\nwindows-sys = { workspace = true, features = [\"Win32_Storage_FileSystem\"] }\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/cargo-test-support/README.md",
    "content": "> This crate is maintained by the Cargo team, primarily for use by Cargo\n> and not intended for external use. This\n> crate may make major changes to its APIs or be deprecated without warning.\n"
  },
  {
    "path": "crates/cargo-test-support/build.rs",
    "content": "#![allow(clippy::disallowed_methods)]\n\nfn main() {\n    println!(\"cargo:rustc-check-cfg=cfg(emulate_second_only_system)\");\n    println!(\n        \"cargo:rustc-env=NATIVE_ARCH={}\",\n        std::env::var(\"TARGET\").unwrap()\n    );\n    println!(\"cargo:rerun-if-changed=build.rs\");\n}\n"
  },
  {
    "path": "crates/cargo-test-support/containers/apache/Dockerfile",
    "content": "FROM httpd:2.4-alpine\n\nRUN apk add --no-cache git git-daemon openssl\n\nCOPY bar /repos/bar\nWORKDIR /repos/bar\nRUN git config --global user.email \"testuser@example.com\" &&\\\n    git config --global user.name \"Test User\" &&\\\n    git config --system --add safe.directory '*' &&\\\n    git init -b master . &&\\\n    git add Cargo.toml src &&\\\n    git commit -m \"Initial commit\" &&\\\n    cd .. &&\\\n    git clone --bare bar bar.git &&\\\n    rm -rf bar\nWORKDIR /\n\nEXPOSE 443\n\nWORKDIR /usr/local/apache2/conf\nCOPY httpd-cargo.conf .\nRUN cat httpd-cargo.conf >> httpd.conf\nRUN openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \\\n    -keyout server.key -out server.crt \\\n    -subj \"/emailAddress=webmaster@example.com/C=US/ST=California/L=San Francisco/O=Rust/OU=Cargo/CN=127.0.0.1\"\nWORKDIR /\n"
  },
  {
    "path": "crates/cargo-test-support/containers/apache/bar/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"1.0.0\"\nedition = \"2021\"\n"
  },
  {
    "path": "crates/cargo-test-support/containers/apache/bar/src/lib.rs",
    "content": "// Intentionally blank.\n"
  },
  {
    "path": "crates/cargo-test-support/containers/apache/httpd-cargo.conf",
    "content": "SetEnv GIT_PROJECT_ROOT /repos\nSetEnv GIT_HTTP_EXPORT_ALL\nScriptAlias /repos /usr/libexec/git-core/git-http-backend/\nLoadModule cgid_module modules/mod_cgid.so\n\n<Files \"git-http-backend\">\n    Require all granted\n</Files>\n\nInclude conf/extra/httpd-ssl.conf\nLoadModule ssl_module modules/mod_ssl.so\nLoadModule socache_shmcb_module modules/mod_socache_shmcb.so\n"
  },
  {
    "path": "crates/cargo-test-support/containers/sshd/Dockerfile",
    "content": "FROM alpine:3.23\n\nRUN apk add --no-cache openssh git\nRUN apk upgrade --no-cache libcrypto3\nRUN ssh-keygen -A\n\nRUN addgroup -S testuser && adduser -S testuser -G testuser -s /bin/ash\n# NOTE: Ideally the password should be set to *, but I am uncertain how to do\n# that in alpine. It shouldn't matter since PermitEmptyPasswords is \"no\".\nRUN passwd -u testuser\n\nRUN mkdir /repos && chown testuser /repos\nCOPY --chown=testuser:testuser bar /repos/bar\nUSER testuser\nWORKDIR /repos/bar\nRUN git config --global user.email \"testuser@example.com\" &&\\\n    git config --global user.name \"Test User\" &&\\\n    git init -b master . &&\\\n    git add Cargo.toml src &&\\\n    git commit -m \"Initial commit\" &&\\\n    cd .. &&\\\n    git clone --bare bar bar.git &&\\\n    rm -rf bar\nWORKDIR /\nUSER root\n\nEXPOSE 22\n\nENTRYPOINT [\"/usr/sbin/sshd\", \"-D\", \"-E\", \"/var/log/auth.log\"]\n"
  },
  {
    "path": "crates/cargo-test-support/containers/sshd/bar/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"1.0.0\"\nedition = \"2021\"\n"
  },
  {
    "path": "crates/cargo-test-support/containers/sshd/bar/src/lib.rs",
    "content": "// Intentionally blank.\n"
  },
  {
    "path": "crates/cargo-test-support/src/compare.rs",
    "content": "//! Routines for comparing and diffing output.\n//!\n//! # Deprecated comparisons\n//!\n//! Cargo's tests are in transition from internal-only pattern and normalization routines used in\n//! asserts like [`crate::Execs::with_stdout_contains`] to [`assert_e2e`] and [`assert_ui`].\n//!\n//! ## Patterns\n//!\n//! Many of these functions support special markup to assist with comparing\n//! text that may vary or is otherwise uninteresting for the test at hand. The\n//! supported patterns are:\n//!\n//! - `[..]` is a wildcard that matches 0 or more characters on the same line\n//!   (similar to `.*` in a regex). It is non-greedy.\n//! - `[EXE]` optionally adds `.exe` on Windows (empty string on other\n//!   platforms).\n//! - `[ROOT]` is the path to the test directory's root.\n//! - `[CWD]` is the working directory of the process that was run.\n//! - There is a wide range of substitutions (such as `[COMPILING]` or\n//!   `[WARNING]`) to match cargo's \"status\" output and allows you to ignore\n//!   the alignment. See the source of `substitute_macros` for a complete list\n//!   of substitutions.\n//! - `[DIRTY-MSVC]` (only when the line starts with it) would be replaced by\n//!   `[DIRTY]` when `cfg(target_env = \"msvc\")` or the line will be ignored otherwise.\n//!   Tests that work around [issue 7358](https://github.com/rust-lang/cargo/issues/7358)\n//!   can use this to avoid duplicating the `with_stderr` call like:\n//!   `if cfg!(target_env = \"msvc\") {e.with_stderr(\"...[DIRTY]...\");} else {e.with_stderr(\"...\");}`.\n//!\n//! ## Normalization\n//!\n//! In addition to the patterns described above, the strings are normalized\n//! in such a way to avoid unwanted differences. The normalizations are:\n//!\n//! - Raw tab characters are converted to the string `<tab>`. This is helpful\n//!   so that raw tabs do not need to be written in the expected string, and\n//!   to avoid confusion of tabs vs spaces.\n//! - Backslashes are converted to forward slashes to deal with Windows paths.\n//!   This helps so that all tests can be written assuming forward slashes.\n//!   Other heuristics are applied to try to ensure Windows-style paths aren't\n//!   a problem.\n//! - Carriage returns are removed, which can help when running on Windows.\n\nuse crate::cross_compile::try_alternate;\nuse crate::paths;\nuse crate::rustc_host;\nuse anyhow::{Result, bail};\nuse snapbox::Data;\nuse snapbox::IntoData;\nuse std::fmt;\nuse std::path::Path;\nuse std::path::PathBuf;\nuse std::str;\n\n/// This makes it easier to write regex replacements that are guaranteed to only\n/// get compiled once\nmacro_rules! regex {\n    ($re:literal $(,)?) => {{\n        static RE: std::sync::OnceLock<regex::Regex> = std::sync::OnceLock::new();\n        RE.get_or_init(|| regex::Regex::new($re).unwrap())\n    }};\n}\n\n/// Assertion policy for UI tests\n///\n/// This emphasizes showing as much content as possible at the cost of more brittleness\n///\n/// # Snapshots\n///\n/// Updating of snapshots is controlled with the `SNAPSHOTS` environment variable:\n///\n/// - `skip`: do not run the tests\n/// - `ignore`: run the tests but ignore their failure\n/// - `verify`: run the tests\n/// - `overwrite`: update the snapshots based on the output of the tests\n///\n/// # Patterns\n///\n/// - `[..]` is a character wildcard, stopping at line breaks\n/// - `\\n...\\n` is a multi-line wildcard\n/// - `[EXE]` matches the exe suffix for the current platform\n/// - `[ROOT]` matches [`paths::root()`][crate::paths::root]\n/// - `[ROOTURL]` matches [`paths::root()`][crate::paths::root] as a URL\n///\n/// # Normalization\n///\n/// In addition to the patterns described above, text is normalized\n/// in such a way to avoid unwanted differences. The normalizations are:\n///\n/// - Backslashes are converted to forward slashes to deal with Windows paths.\n///   This helps so that all tests can be written assuming forward slashes.\n///   Other heuristics are applied to try to ensure Windows-style paths aren't\n///   a problem.\n/// - Carriage returns are removed, which can help when running on Windows.\n///\n/// # Example\n///\n/// ```no_run\n/// # use cargo_test_support::compare::assert_e2e;\n/// # use cargo_test_support::file;\n/// # let p = cargo_test_support::project().build();\n/// # let stdout = \"\";\n/// assert_e2e().eq(stdout, file![\"stderr.term.svg\"]);\n/// ```\n/// ```console\n/// $ SNAPSHOTS=overwrite cargo test\n/// ```\npub fn assert_ui() -> snapbox::Assert {\n    let mut subs = snapbox::Redactions::new();\n    subs.extend(MIN_LITERAL_REDACTIONS.into_iter().cloned())\n        .unwrap();\n    add_test_support_redactions(&mut subs);\n    add_regex_redactions(&mut subs);\n\n    snapbox::Assert::new()\n        .action_env(snapbox::assert::DEFAULT_ACTION_ENV)\n        .redact_with(subs)\n}\n\n/// Assertion policy for functional end-to-end tests\n///\n/// This emphasizes showing as much content as possible at the cost of more brittleness\n///\n/// # Snapshots\n///\n/// Updating of snapshots is controlled with the `SNAPSHOTS` environment variable:\n///\n/// - `skip`: do not run the tests\n/// - `ignore`: run the tests but ignore their failure\n/// - `verify`: run the tests\n/// - `overwrite`: update the snapshots based on the output of the tests\n///\n/// # Patterns\n///\n/// - `[..]` is a character wildcard, stopping at line breaks\n/// - `\\n...\\n` is a multi-line wildcard\n/// - `[EXE]` matches the exe suffix for the current platform\n/// - `[ROOT]` matches [`paths::root()`][crate::paths::root]\n/// - `[ROOTURL]` matches [`paths::root()`][crate::paths::root] as a URL\n///\n/// # Normalization\n///\n/// In addition to the patterns described above, text is normalized\n/// in such a way to avoid unwanted differences. The normalizations are:\n///\n/// - Backslashes are converted to forward slashes to deal with Windows paths.\n///   This helps so that all tests can be written assuming forward slashes.\n///   Other heuristics are applied to try to ensure Windows-style paths aren't\n///   a problem.\n/// - Carriage returns are removed, which can help when running on Windows.\n///\n/// # Example\n///\n/// ```no_run\n/// # use cargo_test_support::compare::assert_e2e;\n/// # use cargo_test_support::str;\n/// # let p = cargo_test_support::project().build();\n/// assert_e2e().eq(p.read_lockfile(), str![]);\n/// ```\n/// ```console\n/// $ SNAPSHOTS=overwrite cargo test\n/// ```\npub fn assert_e2e() -> snapbox::Assert {\n    let mut subs = snapbox::Redactions::new();\n    subs.extend(MIN_LITERAL_REDACTIONS.into_iter().cloned())\n        .unwrap();\n    subs.extend(E2E_LITERAL_REDACTIONS.into_iter().cloned())\n        .unwrap();\n    add_test_support_redactions(&mut subs);\n    add_regex_redactions(&mut subs);\n\n    snapbox::Assert::new()\n        .action_env(snapbox::assert::DEFAULT_ACTION_ENV)\n        .redact_with(subs)\n}\n\nfn add_test_support_redactions(subs: &mut snapbox::Redactions) {\n    let root = paths::root();\n    // Use `from_file_path` instead of `from_dir_path` so the trailing slash is\n    // put in the users output, rather than hidden in the variable\n    let root_url = url::Url::from_file_path(&root).unwrap().to_string();\n\n    subs.insert(\"[ROOT]\", root).unwrap();\n    subs.insert(\"[ROOTURL]\", root_url).unwrap();\n    subs.insert(\"[HOST_TARGET]\", rustc_host()).unwrap();\n    if let Some(alt_target) = try_alternate() {\n        subs.insert(\"[ALT_TARGET]\", alt_target).unwrap();\n    }\n}\n\nfn add_regex_redactions(subs: &mut snapbox::Redactions) {\n    // For e2e tests\n    subs.insert(\n        \"[ELAPSED]\",\n        regex!(r\"\\[FINISHED\\].*in (?<redacted>[0-9]+(\\.[0-9]+)?(m [0-9]+)?)s\"),\n    )\n    .unwrap();\n    // for UI tests\n    subs.insert(\n        \"[ELAPSED]\",\n        regex!(r\"Finished.*in (?<redacted>[0-9]+(\\.[0-9]+)?(m [0-9]+)?)s\"),\n    )\n    .unwrap();\n    // output from libtest\n    subs.insert(\n        \"[ELAPSED]\",\n        regex!(r\"; finished in (?<redacted>[0-9]+(\\.[0-9]+)?(m [0-9]+)?)s\"),\n    )\n    .unwrap();\n    subs.insert(\n        \"[FILE_NUM]\",\n        regex!(r\"\\[(REMOVED|SUMMARY)\\] (?<redacted>[1-9][0-9]*) files\"),\n    )\n    .unwrap();\n    subs.insert(\n        \"[FILE_SIZE]\",\n        regex!(r\"(?<redacted>[0-9]+(\\.[0-9]+)?([a-zA-Z]i)?)B\\s\"),\n    )\n    .unwrap();\n    subs.insert(\n        \"[HASH]\",\n        regex!(r\"home/\\.cargo/registry/(cache|index|src)/-(?<redacted>[a-z0-9]+)\"),\n    )\n    .unwrap();\n    subs.insert(\n        \"[HASH]\",\n        regex!(r\"\\.cargo/target/(?<redacted>[0-9a-f]{2}/[0-9a-f]{14})\"),\n    )\n    .unwrap();\n    subs.insert(\"[HASH]\", regex!(r\"/[a-z0-9\\-_]+-(?<redacted>[0-9a-f]{16})\"))\n        .unwrap();\n    // Match multi-part hashes like `06/b451d0d6f88b1d` used in directory paths\n    subs.insert(\"[HASH]\", regex!(r\"/(?<redacted>[a-f0-9]{2}\\/[0-9a-f]{14})\"))\n        .unwrap();\n    // Match file name hashes like `foo-06b451d0d6f88b1d`\n    subs.insert(\"[HASH]\", regex!(r\"[a-z0-9]+-(?<redacted>[a-f0-9]{16})\"))\n        .unwrap();\n    // Match path hashes like `../06b451d0d6f88b1d/..` used in directory paths\n    subs.insert(\"[HASH]\", regex!(r\"\\/(?<redacted>[0-9a-f]{16})\\/\"))\n        .unwrap();\n    subs.insert(\n        \"[AVG_ELAPSED]\",\n        regex!(r\"(?<redacted>[0-9]+(\\.[0-9]+)?) ns/iter\"),\n    )\n    .unwrap();\n    subs.insert(\n        \"[JITTER]\",\n        regex!(r\"ns/iter \\(\\+/- (?<redacted>[0-9]+(\\.[0-9]+)?)\\)\"),\n    )\n    .unwrap();\n\n    // Following 3 subs redact:\n    //   \"1719325877.527949100s, 61549498ns after last build at 1719325877.466399602s\"\n    //   \"1719503592.218193216s, 1h 1s after last build at 1719499991.982681034s\"\n    // into \"[DIRTY_REASON_NEW_TIME], [DIRTY_REASON_DIFF] after last build at [DIRTY_REASON_OLD_TIME]\"\n    subs.insert(\n        \"[TIME_DIFF_AFTER_LAST_BUILD]\",\n        regex!(r\"(?<redacted>[0-9]+(\\.[0-9]+)?s, (\\s?[0-9]+(\\.[0-9]+)?(s|ns|h))+ after last build at [0-9]+(\\.[0-9]+)?s)\"),\n       )\n       .unwrap();\n}\n\nstatic MIN_LITERAL_REDACTIONS: &[(&str, &str)] = &[\n    (\"[EXE]\", std::env::consts::EXE_SUFFIX),\n    (\"[BROKEN_PIPE]\", \"Broken pipe (os error 32)\"),\n    (\"[BROKEN_PIPE]\", \"The pipe is being closed. (os error 232)\"),\n    // Unix message for an entity was not found\n    (\"[NOT_FOUND]\", \"No such file or directory (os error 2)\"),\n    // Windows message for an entity was not found\n    (\n        \"[NOT_FOUND]\",\n        \"The system cannot find the file specified. (os error 2)\",\n    ),\n    (\n        \"[NOT_FOUND]\",\n        \"The system cannot find the path specified. (os error 3)\",\n    ),\n    (\"[NOT_FOUND]\", \"Access is denied. (os error 5)\"),\n    (\"[NOT_FOUND]\", \"program not found\"),\n    // Unix message for exit status\n    (\"[EXIT_STATUS]\", \"exit status\"),\n    // Windows message for exit status\n    (\"[EXIT_STATUS]\", \"exit code\"),\n];\nstatic E2E_LITERAL_REDACTIONS: &[(&str, &str)] = &[\n    (\"[RUNNING]\", \"     Running\"),\n    (\"[COMPILING]\", \"   Compiling\"),\n    (\"[CHECKING]\", \"    Checking\"),\n    (\"[COMPLETED]\", \"   Completed\"),\n    (\"[CREATED]\", \"     Created\"),\n    (\"[CREATING]\", \"    Creating\"),\n    (\"[CREDENTIAL]\", \"  Credential\"),\n    (\"[DOWNGRADING]\", \" Downgrading\"),\n    (\"[FINISHED]\", \"    Finished\"),\n    (\"[ERROR]\", \"error:\"),\n    (\"[WARNING]\", \"warning:\"),\n    (\"[NOTE]\", \"note:\"),\n    (\"[HELP]\", \"help:\"),\n    (\"[DOCUMENTING]\", \" Documenting\"),\n    (\"[SCRAPING]\", \"    Scraping\"),\n    (\"[FRESH]\", \"       Fresh\"),\n    (\"[DIRTY]\", \"       Dirty\"),\n    (\"[LOCKING]\", \"     Locking\"),\n    (\"[UPDATING]\", \"    Updating\"),\n    (\"[UPGRADING]\", \"   Upgrading\"),\n    (\"[ADDING]\", \"      Adding\"),\n    (\"[REMOVING]\", \"    Removing\"),\n    (\"[REMOVED]\", \"     Removed\"),\n    (\"[UNCHANGED]\", \"   Unchanged\"),\n    (\"[DOCTEST]\", \"   Doc-tests\"),\n    (\"[PACKAGING]\", \"   Packaging\"),\n    (\"[PACKAGED]\", \"    Packaged\"),\n    (\"[DOWNLOADING]\", \" Downloading\"),\n    (\"[DOWNLOADED]\", \"  Downloaded\"),\n    (\"[UPLOADING]\", \"   Uploading\"),\n    (\"[UPLOADED]\", \"    Uploaded\"),\n    (\"[VERIFYING]\", \"   Verifying\"),\n    (\"[ARCHIVING]\", \"   Archiving\"),\n    (\"[INSTALLING]\", \"  Installing\"),\n    (\"[REPLACING]\", \"   Replacing\"),\n    (\"[UNPACKING]\", \"   Unpacking\"),\n    (\"[SUMMARY]\", \"     Summary\"),\n    (\"[FIXED]\", \"       Fixed\"),\n    (\"[FIXING]\", \"      Fixing\"),\n    (\"[IGNORED]\", \"     Ignored\"),\n    (\"[INSTALLED]\", \"   Installed\"),\n    (\"[REPLACED]\", \"    Replaced\"),\n    (\"[BUILDING]\", \"    Building\"),\n    (\"[LOGIN]\", \"       Login\"),\n    (\"[LOGOUT]\", \"      Logout\"),\n    (\"[YANK]\", \"        Yank\"),\n    (\"[OWNER]\", \"       Owner\"),\n    (\"[MIGRATING]\", \"   Migrating\"),\n    (\"[EXECUTABLE]\", \"  Executable\"),\n    (\"[SKIPPING]\", \"    Skipping\"),\n    (\"[WAITING]\", \"     Waiting\"),\n    (\"[PUBLISHED]\", \"   Published\"),\n    (\"[BLOCKING]\", \"    Blocking\"),\n    (\"[GENERATED]\", \"   Generated\"),\n    (\"[OPENING]\", \"     Opening\"),\n    (\"[MERGING]\", \"     Merging\"),\n];\n\n/// Checks that the given string contains the given contiguous lines\n/// somewhere.\n///\n/// See [Patterns](index.html#patterns) for more information on pattern matching.\npub(crate) fn match_contains(\n    expected: &str,\n    actual: &str,\n    redactions: &snapbox::Redactions,\n) -> Result<()> {\n    let expected = normalize_expected(expected, redactions);\n    let actual = normalize_actual(actual, redactions);\n    let e: Vec<_> = expected.lines().map(|line| WildStr::new(line)).collect();\n    let a: Vec<_> = actual.lines().collect();\n    if e.len() == 0 {\n        bail!(\"expected length must not be zero\");\n    }\n    for window in a.windows(e.len()) {\n        if e == window {\n            return Ok(());\n        }\n    }\n    bail!(\n        \"expected to find:\\n\\\n         {}\\n\\n\\\n         did not find in output:\\n\\\n         {}\",\n        expected,\n        actual\n    );\n}\n\n/// Checks that the given string does not contain the given contiguous lines\n/// anywhere.\n///\n/// See [Patterns](index.html#patterns) for more information on pattern matching.\npub(crate) fn match_does_not_contain(\n    expected: &str,\n    actual: &str,\n    redactions: &snapbox::Redactions,\n) -> Result<()> {\n    if match_contains(expected, actual, redactions).is_ok() {\n        bail!(\n            \"expected not to find:\\n\\\n             {}\\n\\n\\\n             but found in output:\\n\\\n             {}\",\n            expected,\n            actual\n        );\n    } else {\n        Ok(())\n    }\n}\n\n/// Checks that the given string has a line that contains the given patterns,\n/// and that line also does not contain the `without` patterns.\n///\n/// See [Patterns](index.html#patterns) for more information on pattern matching.\n///\n/// See [`crate::Execs::with_stderr_line_without`] for an example and cautions\n/// against using.\npub(crate) fn match_with_without(\n    actual: &str,\n    with: &[String],\n    without: &[String],\n    redactions: &snapbox::Redactions,\n) -> Result<()> {\n    let actual = normalize_actual(actual, redactions);\n    let norm = |s: &String| format!(\"[..]{}[..]\", normalize_expected(s, redactions));\n    let with: Vec<_> = with.iter().map(norm).collect();\n    let without: Vec<_> = without.iter().map(norm).collect();\n    let with_wild: Vec<_> = with.iter().map(|w| WildStr::new(w)).collect();\n    let without_wild: Vec<_> = without.iter().map(|w| WildStr::new(w)).collect();\n\n    let matches: Vec<_> = actual\n        .lines()\n        .filter(|line| with_wild.iter().all(|with| with == line))\n        .filter(|line| !without_wild.iter().any(|without| without == line))\n        .collect();\n    match matches.len() {\n        0 => bail!(\n            \"Could not find expected line in output.\\n\\\n             With contents: {:?}\\n\\\n             Without contents: {:?}\\n\\\n             Actual stderr:\\n\\\n             {}\\n\",\n            with,\n            without,\n            actual\n        ),\n        1 => Ok(()),\n        _ => bail!(\n            \"Found multiple matching lines, but only expected one.\\n\\\n             With contents: {:?}\\n\\\n             Without contents: {:?}\\n\\\n             Matching lines:\\n\\\n             {}\\n\",\n            with,\n            without,\n            itertools::join(matches, \"\\n\")\n        ),\n    }\n}\n\n/// Normalizes the output so that it can be compared against the expected value.\nfn normalize_actual(content: &str, redactions: &snapbox::Redactions) -> String {\n    use snapbox::filter::Filter as _;\n    let content = snapbox::filter::FilterPaths.filter(content.into_data());\n    let content = snapbox::filter::FilterNewlines.filter(content);\n    let content = content.render().expect(\"came in as a String\");\n    let content = redactions.redact(&content);\n    content\n}\n\n/// Normalizes the expected string so that it can be compared against the actual output.\nfn normalize_expected(content: &str, redactions: &snapbox::Redactions) -> String {\n    use snapbox::filter::Filter as _;\n    let content = snapbox::filter::FilterPaths.filter(content.into_data());\n    let content = snapbox::filter::FilterNewlines.filter(content);\n    // Remove any conditionally absent redactions like `[EXE]`\n    let content = content.render().expect(\"came in as a String\");\n    let content = redactions.clear_unused(&content);\n    content.into_owned()\n}\n\n/// A single line string that supports `[..]` wildcard matching.\nstruct WildStr<'a> {\n    has_meta: bool,\n    line: &'a str,\n}\n\nimpl<'a> WildStr<'a> {\n    fn new(line: &'a str) -> WildStr<'a> {\n        WildStr {\n            has_meta: line.contains(\"[..]\"),\n            line,\n        }\n    }\n}\n\nimpl PartialEq<&str> for WildStr<'_> {\n    fn eq(&self, other: &&str) -> bool {\n        if self.has_meta {\n            meta_cmp(self.line, other)\n        } else {\n            self.line == *other\n        }\n    }\n}\n\nfn meta_cmp(a: &str, mut b: &str) -> bool {\n    for (i, part) in a.split(\"[..]\").enumerate() {\n        match b.find(part) {\n            Some(j) => {\n                if i == 0 && j != 0 {\n                    return false;\n                }\n                b = &b[j + part.len()..];\n            }\n            None => return false,\n        }\n    }\n    b.is_empty() || a.ends_with(\"[..]\")\n}\n\nimpl fmt::Display for WildStr<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(&self.line)\n    }\n}\n\nimpl fmt::Debug for WildStr<'_> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{:?}\", self.line)\n    }\n}\n\npub struct InMemoryDir {\n    files: Vec<(PathBuf, Data)>,\n}\n\nimpl InMemoryDir {\n    pub fn paths(&self) -> impl Iterator<Item = &Path> {\n        self.files.iter().map(|(p, _)| p.as_path())\n    }\n\n    #[track_caller]\n    pub fn assert_contains(&self, expected: &Self) {\n        use std::fmt::Write as _;\n        let assert = assert_e2e();\n        let mut errs = String::new();\n        for (path, expected_data) in &expected.files {\n            let actual_data = self\n                .files\n                .iter()\n                .find_map(|(p, d)| (path == p).then(|| d.clone()))\n                .unwrap_or_else(|| Data::new());\n            if let Err(err) =\n                assert.try_eq(Some(&path.display()), actual_data, expected_data.clone())\n            {\n                let _ = write!(&mut errs, \"{err}\");\n            }\n        }\n        if !errs.is_empty() {\n            panic!(\"{errs}\")\n        }\n    }\n}\n\nimpl<P, D> FromIterator<(P, D)> for InMemoryDir\nwhere\n    P: Into<std::path::PathBuf>,\n    D: IntoData,\n{\n    fn from_iter<I: IntoIterator<Item = (P, D)>>(files: I) -> Self {\n        let files = files\n            .into_iter()\n            .map(|(p, d)| (p.into(), d.into_data()))\n            .collect();\n        Self { files }\n    }\n}\n\nimpl<const N: usize, P, D> From<[(P, D); N]> for InMemoryDir\nwhere\n    P: Into<PathBuf>,\n    D: IntoData,\n{\n    fn from(files: [(P, D); N]) -> Self {\n        let files = files\n            .into_iter()\n            .map(|(p, d)| (p.into(), d.into_data()))\n            .collect();\n        Self { files }\n    }\n}\n\nimpl<P, D> From<std::collections::HashMap<P, D>> for InMemoryDir\nwhere\n    P: Into<PathBuf>,\n    D: IntoData,\n{\n    fn from(files: std::collections::HashMap<P, D>) -> Self {\n        let files = files\n            .into_iter()\n            .map(|(p, d)| (p.into(), d.into_data()))\n            .collect();\n        Self { files }\n    }\n}\n\nimpl<P, D> From<std::collections::BTreeMap<P, D>> for InMemoryDir\nwhere\n    P: Into<PathBuf>,\n    D: IntoData,\n{\n    fn from(files: std::collections::BTreeMap<P, D>) -> Self {\n        let files = files\n            .into_iter()\n            .map(|(p, d)| (p.into(), d.into_data()))\n            .collect();\n        Self { files }\n    }\n}\n\nimpl From<()> for InMemoryDir {\n    fn from(_files: ()) -> Self {\n        let files = Vec::new();\n        Self { files }\n    }\n}\n\n/// Create an `impl _ for InMemoryDir` for a generic tuple\n///\n/// Must pass in names for each tuple parameter for\n/// - internal variable name\n/// - `Path` type\n/// - `Data` type\nmacro_rules! impl_from_tuple_for_inmemorydir {\n    ($($var:ident $path:ident $data:ident),+) => {\n        impl<$($path: Into<PathBuf>, $data: IntoData),+> From<($(($path, $data)),+ ,)> for InMemoryDir {\n            fn from(files: ($(($path, $data)),+,)) -> Self {\n                let ($($var),+ ,) = files;\n                let files = [$(($var.0.into(), $var.1.into_data())),+];\n                files.into()\n            }\n        }\n    };\n}\n\n/// Extend `impl_from_tuple_for_inmemorydir` to generate for the specified tuple and all smaller\n/// tuples\nmacro_rules! impl_from_tuples_for_inmemorydir {\n    ($var1:ident $path1:ident $data1:ident, $($var:ident $path:ident $data:ident),+) => {\n        impl_from_tuples_for_inmemorydir!(__impl $var1 $path1 $data1; $($var $path $data),+);\n    };\n    (__impl $($var:ident $path:ident $data:ident),+; $var1:ident $path1:ident $data1:ident $(,$var2:ident $path2:ident $data2:ident)*) => {\n        impl_from_tuple_for_inmemorydir!($($var $path $data),+);\n        impl_from_tuples_for_inmemorydir!(__impl $($var $path $data),+, $var1 $path1 $data1; $($var2 $path2 $data2),*);\n    };\n    (__impl $($var:ident $path:ident $data:ident),+;) => {\n        impl_from_tuple_for_inmemorydir!($($var $path $data),+);\n    }\n}\n\n// Generate for tuples of size `1..=7`\nimpl_from_tuples_for_inmemorydir!(\n    s1 P1 D1,\n    s2 P2 D2,\n    s3 P3 D3,\n    s4 P4 D4,\n    s5 P5 D5,\n    s6 P6 D6,\n    s7 P7 D7\n);\n\n#[cfg(test)]\nmod test {\n    use snapbox::assert_data_eq;\n    use snapbox::prelude::*;\n    use snapbox::str;\n\n    use super::*;\n\n    #[test]\n    fn wild_str_cmp() {\n        for (a, b) in &[\n            (\"a b\", \"a b\"),\n            (\"a[..]b\", \"a b\"),\n            (\"a[..]\", \"a b\"),\n            (\"[..]\", \"a b\"),\n            (\"[..]b\", \"a b\"),\n        ] {\n            assert_eq!(WildStr::new(a), b);\n        }\n        for (a, b) in &[(\"[..]b\", \"c\"), (\"b\", \"c\"), (\"b\", \"cb\")] {\n            assert_ne!(WildStr::new(a), b);\n        }\n    }\n\n    #[test]\n    fn redact_elapsed_time() {\n        let mut subs = snapbox::Redactions::new();\n        add_regex_redactions(&mut subs);\n\n        assert_data_eq!(\n            subs.redact(\"[FINISHED] `release` profile [optimized] target(s) in 5.5s\"),\n            str![\"[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\"].raw()\n        );\n        assert_data_eq!(\n            subs.redact(\"[FINISHED] `release` profile [optimized] target(s) in 1m 05s\"),\n            str![\"[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\"].raw()\n        );\n    }\n}\n"
  },
  {
    "path": "crates/cargo-test-support/src/containers.rs",
    "content": "//! Support for testing using Docker containers.\n//!\n//! The [`Container`] type is a builder for configuring a container to run.\n//! After you call `launch`, you can use the [`ContainerHandle`] to interact\n//! with the running container.\n//!\n//! Tests using containers must use `#[cargo_test(container_test)]` to disable\n//! them unless the `CARGO_CONTAINER_TESTS` environment variable is set.\n\nuse cargo_util::ProcessBuilder;\nuse std::collections::HashMap;\nuse std::io::Read;\nuse std::path::PathBuf;\nuse std::process::Command;\nuse std::sync::Mutex;\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse tar::Header;\n\n/// A builder for configuring a container to run.\npub struct Container {\n    /// The host directory that forms the basis of the Docker image.\n    build_context: PathBuf,\n    /// Files to copy over to the image.\n    files: Vec<MkFile>,\n}\n\n/// A handle to a running container.\n///\n/// You can use this to interact with the container.\npub struct ContainerHandle {\n    /// The name of the container.\n    name: String,\n    /// Port mappings of `container_port` to `host_port` for ports exposed via EXPOSE.\n    pub port_mappings: HashMap<u16, u16>,\n}\n\nimpl Container {\n    pub fn new(context_dir: &str) -> Container {\n        assert!(std::env::var_os(\"CARGO_CONTAINER_TESTS\").is_some());\n        let mut build_context = PathBuf::from(env!(\"CARGO_MANIFEST_DIR\"));\n        build_context.push(\"containers\");\n        build_context.push(context_dir);\n        Container {\n            build_context,\n            files: Vec::new(),\n        }\n    }\n\n    /// Adds a file to be copied into the container.\n    pub fn file(mut self, file: MkFile) -> Self {\n        self.files.push(file);\n        self\n    }\n\n    /// Starts the container.\n    pub fn launch(mut self) -> ContainerHandle {\n        static NEXT_ID: AtomicUsize = AtomicUsize::new(0);\n\n        let id = NEXT_ID.fetch_add(1, Ordering::SeqCst);\n        let name = format!(\"cargo_test_{id}\");\n        remove_if_exists(&name);\n        self.create_container(&name);\n        self.copy_files(&name);\n        self.start_container(&name);\n        let info = self.container_inspect(&name);\n        let port_mappings = self.port_mappings(&info);\n        self.wait_till_ready(&port_mappings);\n\n        ContainerHandle {\n            name,\n            port_mappings,\n        }\n    }\n\n    fn create_container(&self, name: &str) {\n        static BUILD_LOCK: Mutex<()> = Mutex::new(());\n\n        let image_base = self.build_context.file_name().unwrap();\n        let image_name = format!(\"cargo-test-{}\", image_base.to_str().unwrap());\n        let _lock = BUILD_LOCK\n            .lock()\n            .map_err(|_| panic!(\"previous docker build failed, unable to run test\"));\n        ProcessBuilder::new(\"docker\")\n            .args(&[\"build\", \"--tag\", image_name.as_str()])\n            .arg(&self.build_context)\n            .exec_with_output()\n            .unwrap();\n\n        ProcessBuilder::new(\"docker\")\n            .args(&[\n                \"container\",\n                \"create\",\n                \"--publish-all\",\n                \"--rm\",\n                \"--name\",\n                name,\n            ])\n            .arg(image_name)\n            .exec_with_output()\n            .unwrap();\n    }\n\n    fn copy_files(&mut self, name: &str) {\n        if self.files.is_empty() {\n            return;\n        }\n        let mut ar = tar::Builder::new(Vec::new());\n        ar.sparse(false);\n        let files = std::mem::replace(&mut self.files, Vec::new());\n        for mut file in files {\n            ar.append_data(&mut file.header, &file.path, file.contents.as_slice())\n                .unwrap();\n        }\n        let ar = ar.into_inner().unwrap();\n        ProcessBuilder::new(\"docker\")\n            .args(&[\"cp\", \"-\"])\n            .arg(format!(\"{name}:/\"))\n            .stdin(ar)\n            .exec_with_output()\n            .unwrap();\n    }\n\n    fn start_container(&self, name: &str) {\n        ProcessBuilder::new(\"docker\")\n            .args(&[\"container\", \"start\"])\n            .arg(name)\n            .exec_with_output()\n            .unwrap();\n    }\n\n    fn container_inspect(&self, name: &str) -> serde_json::Value {\n        let output = ProcessBuilder::new(\"docker\")\n            .args(&[\"inspect\", name])\n            .exec_with_output()\n            .unwrap();\n        serde_json::from_slice(&output.stdout).unwrap()\n    }\n\n    /// Returns the mapping of container_port->host_port for ports that were\n    /// exposed with EXPOSE.\n    fn port_mappings(&self, info: &serde_json::Value) -> HashMap<u16, u16> {\n        info[0][\"NetworkSettings\"][\"Ports\"]\n            .as_object()\n            .unwrap()\n            .iter()\n            .map(|(key, value)| {\n                let key = key\n                    .strip_suffix(\"/tcp\")\n                    .expect(\"expected TCP only ports\")\n                    .parse()\n                    .unwrap();\n                let values = value.as_array().unwrap();\n                let value = values\n                    .iter()\n                    .find(|value| value[\"HostIp\"].as_str().unwrap() == \"0.0.0.0\")\n                    .expect(\"expected localhost IP\");\n                let host_port = value[\"HostPort\"].as_str().unwrap().parse().unwrap();\n                (key, host_port)\n            })\n            .collect()\n    }\n\n    fn wait_till_ready(&self, port_mappings: &HashMap<u16, u16>) {\n        for port in port_mappings.values() {\n            let mut ok = false;\n            for _ in 0..30 {\n                match std::net::TcpStream::connect(format!(\"127.0.0.1:{port}\")) {\n                    Ok(_) => {\n                        ok = true;\n                        break;\n                    }\n                    Err(e) => {\n                        if e.kind() != std::io::ErrorKind::ConnectionRefused {\n                            panic!(\"unexpected localhost connection error: {e:?}\");\n                        }\n                        std::thread::sleep(std::time::Duration::new(1, 0));\n                    }\n                }\n            }\n            if !ok {\n                panic!(\"no listener on localhost port {port}\");\n            }\n        }\n    }\n}\n\nimpl ContainerHandle {\n    /// Executes a program inside a running container.\n    pub fn exec(&self, args: &[&str]) -> std::process::Output {\n        ProcessBuilder::new(\"docker\")\n            .args(&[\"container\", \"exec\", &self.name])\n            .args(args)\n            .exec_with_output()\n            .unwrap()\n    }\n\n    /// Returns the contents of a file inside the container.\n    pub fn read_file(&self, path: &str) -> String {\n        let output = ProcessBuilder::new(\"docker\")\n            .args(&[\"cp\", &format!(\"{}:{}\", self.name, path), \"-\"])\n            .exec_with_output()\n            .unwrap();\n        let mut ar = tar::Archive::new(output.stdout.as_slice());\n        let mut entry = ar.entries().unwrap().next().unwrap().unwrap();\n        let mut contents = String::new();\n        entry.read_to_string(&mut contents).unwrap();\n        contents\n    }\n}\n\nimpl Drop for ContainerHandle {\n    fn drop(&mut self) {\n        // To help with debugging, this will keep the container alive.\n        if std::env::var_os(\"CARGO_CONTAINER_TEST_KEEP\").is_some() {\n            return;\n        }\n        remove_if_exists(&self.name);\n    }\n}\n\nfn remove_if_exists(name: &str) {\n    if let Err(e) = Command::new(\"docker\")\n        .args(&[\"container\", \"rm\", \"--force\", name])\n        .output()\n    {\n        panic!(\"failed to run docker: {e}\");\n    }\n}\n\n/// Builder for configuring a file to copy into a container.\npub struct MkFile {\n    path: String,\n    contents: Vec<u8>,\n    header: Header,\n}\n\nimpl MkFile {\n    /// Defines a file to add to the container.\n    ///\n    /// This should be passed to `Container::file`.\n    ///\n    /// The path is the path inside the container to create the file.\n    pub fn path(path: &str) -> MkFile {\n        MkFile {\n            path: path.to_string(),\n            contents: Vec::new(),\n            header: Header::new_gnu(),\n        }\n    }\n\n    pub fn contents(mut self, contents: impl Into<Vec<u8>>) -> Self {\n        self.contents = contents.into();\n        self.header.set_size(self.contents.len() as u64);\n        self\n    }\n\n    pub fn mode(mut self, mode: u32) -> Self {\n        self.header.set_mode(mode);\n        self\n    }\n\n    pub fn uid(mut self, uid: u64) -> Self {\n        self.header.set_uid(uid);\n        self\n    }\n\n    pub fn gid(mut self, gid: u64) -> Self {\n        self.header.set_gid(gid);\n        self\n    }\n}\n"
  },
  {
    "path": "crates/cargo-test-support/src/cross_compile.rs",
    "content": "//! Support for cross-compile tests with the `--target` flag.\n//!\n//! Note that cross-testing is very limited. You need to install the\n//! \"alternate\" target to the host (32-bit for 64-bit hosts or vice-versa).\n//!\n//! Set `CFG_DISABLE_CROSS_TESTS=1` environment variable to disable these tests\n//! if you are unable to use the alternate target. Unfortunately 32-bit\n//! support on macOS is going away, so macOS users are out of luck.\n//!\n//! These tests are all disabled on rust-lang/rust's CI, but run in Cargo's CI.\n\nuse std::env;\n\n/// The arch triple of the test-running host.\npub fn native() -> &'static str {\n    env!(\"NATIVE_ARCH\")\n}\n\npub fn native_arch() -> &'static str {\n    match native()\n        .split(\"-\")\n        .next()\n        .expect(\"Target triple has unexpected format\")\n    {\n        \"x86_64\" => \"x86_64\",\n        \"aarch64\" => \"aarch64\",\n        \"i686\" => \"x86\",\n        _ => panic!(\"This test should be gated on cross_compile::disabled.\"),\n    }\n}\n\n/// The alternate target-triple to build with.\n///\n/// Only use this function on tests that check `cross_compile::disabled`.\npub fn alternate() -> &'static str {\n    try_alternate().expect(\"This test should be gated on cross_compile::disabled.\")\n}\n\n/// A possible alternate target-triple to build with.\npub(crate) fn try_alternate() -> Option<&'static str> {\n    if cfg!(target_os = \"macos\") {\n        Some(\"x86_64-apple-darwin\")\n    } else if cfg!(target_os = \"linux\") {\n        Some(\"i686-unknown-linux-gnu\")\n    } else if cfg!(all(target_os = \"windows\", target_env = \"msvc\")) {\n        Some(\"i686-pc-windows-msvc\")\n    } else if cfg!(all(target_os = \"windows\", target_env = \"gnu\")) {\n        Some(\"i686-pc-windows-gnu\")\n    } else {\n        None\n    }\n}\n\npub fn alternate_arch() -> &'static str {\n    if cfg!(target_os = \"macos\") {\n        \"x86_64\"\n    } else {\n        \"x86\"\n    }\n}\n\n/// A target-triple that is neither the host nor the target.\n///\n/// Rustc may not work with it and it's alright, apart from being a\n/// valid target triple it is supposed to be used only as a\n/// placeholder for targets that should not be considered.\npub fn unused() -> &'static str {\n    \"wasm32-unknown-unknown\"\n}\n\n/// Check if the given target has been installed.\n///\n/// Generally `testsuite::utils::cross_compile::disabled` should be used to check if cross-compilation is allowed.\n/// And [`alternate`] to get the cross target.\n///\n/// You should only use this as a last resort to skip tests,\n/// because it doesn't report skipped tests as ignored.\npub fn requires_target_installed(target: &str) -> bool {\n    let has_target = std::process::Command::new(\"rustup\")\n        .args([\"target\", \"list\", \"--installed\"])\n        .output()\n        .ok()\n        .map(|output| {\n            String::from_utf8(output.stdout)\n                .map(|stdout| stdout.contains(target))\n                .unwrap_or_default()\n        })\n        .unwrap_or_default();\n    if !has_target {\n        let msg =\n            format!(\"to run this test, run `rustup target add {target} --toolchain <toolchain>`\",);\n        if cargo_util::is_ci() {\n            panic!(\"{msg}\");\n        } else {\n            eprintln!(\"{msg}\");\n        }\n    }\n    has_target\n}\n"
  },
  {
    "path": "crates/cargo-test-support/src/git.rs",
    "content": "//! # Git Testing Support\n//!\n//! ## Creating a git dependency\n//! [`new()`] is an easy way to create a new git repository containing a\n//! project that you can then use as a dependency. It will automatically add all\n//! the files you specify in the project and commit them to the repository.\n//!\n//! ### Example:\n//!\n//! ```no_run\n//! # use cargo_test_support::project;\n//! # use cargo_test_support::basic_manifest;\n//! # use cargo_test_support::git;\n//! let git_project = git::new(\"dep1\", |project| {\n//!     project\n//!         .file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"1.0.0\"))\n//!         .file(\"src/lib.rs\", r#\"pub fn f() { println!(\"hi!\"); } \"#)\n//! });\n//!\n//! // Use the `url()` method to get the file url to the new repository.\n//! let p = project()\n//!     .file(\"Cargo.toml\", &format!(r#\"\n//!         [package]\n//!         name = \"a\"\n//!         version = \"1.0.0\"\n//!\n//!         [dependencies]\n//!         dep1 = {{ git = '{}' }}\n//!     \"#, git_project.url()))\n//!     .file(\"src/lib.rs\", \"extern crate dep1;\")\n//!     .build();\n//! ```\n//!\n//! ## Manually creating repositories\n//!\n//! [`repo()`] can be used to create a [`RepoBuilder`] which provides a way of\n//! adding files to a blank repository and committing them.\n//!\n//! If you want to then manipulate the repository (such as adding new files or\n//! tags), you can use `git2::Repository::open()` to open the repository and then\n//! use some of the helper functions in this file to interact with the repository.\n\nuse crate::{Project, ProjectBuilder, SymlinkBuilder, paths::CargoPathExt, project};\nuse std::fs;\nuse std::path::{Path, PathBuf};\nuse std::sync::Once;\nuse url::Url;\n\n/// Manually construct a [`Repository`]\n///\n/// See also [`new`], [`repo`]\n#[must_use]\npub struct RepoBuilder {\n    repo: git2::Repository,\n    files: Vec<PathBuf>,\n}\n\n/// See [`new`]\npub struct Repository(git2::Repository);\n\n/// Create a [`RepoBuilder`] to build a new git repository.\n///\n/// Call [`RepoBuilder::build()`] to finalize and create the repository.\npub fn repo(p: &Path) -> RepoBuilder {\n    RepoBuilder::init(p)\n}\n\nimpl RepoBuilder {\n    pub fn init(p: &Path) -> RepoBuilder {\n        t!(fs::create_dir_all(p.parent().unwrap()));\n        let repo = init(p);\n        RepoBuilder {\n            repo,\n            files: Vec::new(),\n        }\n    }\n\n    /// Add a file to the repository.\n    pub fn file(self, path: &str, contents: &str) -> RepoBuilder {\n        let mut me = self.nocommit_file(path, contents);\n        me.files.push(PathBuf::from(path));\n        me\n    }\n\n    /// Create a symlink to a directory\n    pub fn nocommit_symlink_dir<T: AsRef<Path>>(self, dst: T, src: T) -> Self {\n        let workdir = self.repo.workdir().unwrap();\n        SymlinkBuilder::new_dir(workdir.join(dst), workdir.join(src)).mk();\n        self\n    }\n\n    /// Add a file that will be left in the working directory, but not added\n    /// to the repository.\n    pub fn nocommit_file(self, path: &str, contents: &str) -> RepoBuilder {\n        let dst = self.repo.workdir().unwrap().join(path);\n        t!(fs::create_dir_all(dst.parent().unwrap()));\n        t!(fs::write(&dst, contents));\n        self\n    }\n\n    /// Create the repository and commit the new files.\n    pub fn build(self) -> Repository {\n        {\n            let mut index = t!(self.repo.index());\n            for file in self.files.iter() {\n                t!(index.add_path(file));\n            }\n            t!(index.write());\n            let id = t!(index.write_tree());\n            let tree = t!(self.repo.find_tree(id));\n            let sig = t!(self.repo.signature());\n            t!(self\n                .repo\n                .commit(Some(\"HEAD\"), &sig, &sig, \"Initial commit\", &tree, &[]));\n        }\n        let RepoBuilder { repo, .. } = self;\n        Repository(repo)\n    }\n}\n\nimpl Repository {\n    pub fn root(&self) -> &Path {\n        self.0.workdir().unwrap()\n    }\n\n    pub fn url(&self) -> Url {\n        self.0.workdir().unwrap().to_url()\n    }\n\n    pub fn revparse_head(&self) -> String {\n        self.0\n            .revparse_single(\"HEAD\")\n            .expect(\"revparse HEAD\")\n            .id()\n            .to_string()\n    }\n}\n\n/// *(`git2`)* Initialize a new repository at the given path.\npub fn init(path: &Path) -> git2::Repository {\n    default_search_path();\n    let repo = t!(git2::Repository::init(path));\n    default_repo_cfg(&repo);\n    repo\n}\n\nfn default_search_path() {\n    use crate::paths::global_root;\n    use git2::{ConfigLevel, opts::set_search_path};\n\n    static INIT: Once = Once::new();\n    INIT.call_once(|| unsafe {\n        let path = global_root().join(\"blank_git_search_path\");\n        t!(set_search_path(ConfigLevel::System, &path));\n        t!(set_search_path(ConfigLevel::Global, &path));\n        t!(set_search_path(ConfigLevel::XDG, &path));\n        t!(set_search_path(ConfigLevel::ProgramData, &path));\n    })\n}\n\nfn default_repo_cfg(repo: &git2::Repository) {\n    let mut cfg = t!(repo.config());\n    t!(cfg.set_str(\"user.email\", \"foo@bar.com\"));\n    t!(cfg.set_str(\"user.name\", \"Foo Bar\"));\n}\n\n/// Create a new [`Project`] in a git [`Repository`]\npub fn new<F>(name: &str, callback: F) -> Project\nwhere\n    F: FnOnce(ProjectBuilder) -> ProjectBuilder,\n{\n    new_repo(name, callback).0\n}\n\n/// Create a new [`Project`] with access to the [`Repository`]\npub fn new_repo<F>(name: &str, callback: F) -> (Project, git2::Repository)\nwhere\n    F: FnOnce(ProjectBuilder) -> ProjectBuilder,\n{\n    let mut git_project = project().at(name);\n    git_project = callback(git_project);\n    let git_project = git_project.build();\n\n    let repo = init(&git_project.root());\n    add(&repo);\n    commit(&repo);\n    (git_project, repo)\n}\n\n/// *(`git2`)* Add all files in the working directory to the git index\npub fn add(repo: &git2::Repository) {\n    let mut index = t!(repo.index());\n    t!(index.add_all([\"*\"].iter(), git2::IndexAddOption::DEFAULT, None));\n    t!(index.write());\n}\n\n/// *(`git2`)* Add a git submodule to the repository\npub fn add_submodule<'a>(\n    repo: &'a git2::Repository,\n    url: &str,\n    path: &Path,\n) -> git2::Submodule<'a> {\n    let path = path.to_str().unwrap().replace(r\"\\\", \"/\");\n    let mut s = t!(repo.submodule(url, Path::new(&path), false));\n    let subrepo = t!(s.open());\n    default_repo_cfg(&subrepo);\n    t!(subrepo.remote_add_fetch(\"origin\", \"refs/heads/*:refs/heads/*\"));\n    let mut origin = t!(subrepo.find_remote(\"origin\"));\n    t!(origin.fetch(&Vec::<String>::new(), None, None));\n    t!(subrepo.checkout_head(None));\n    t!(s.add_finalize());\n    s\n}\n\n/// *(`git2`)* Commit changes to the git repository\npub fn commit(repo: &git2::Repository) -> git2::Oid {\n    let tree_id = t!(t!(repo.index()).write_tree());\n    let sig = t!(repo.signature());\n    let mut parents = Vec::new();\n    if let Some(parent) = repo.head().ok().map(|h| h.target().unwrap()) {\n        parents.push(t!(repo.find_commit(parent)))\n    }\n    let parents = parents.iter().collect::<Vec<_>>();\n    t!(repo.commit(\n        Some(\"HEAD\"),\n        &sig,\n        &sig,\n        \"test\",\n        &t!(repo.find_tree(tree_id)),\n        &parents\n    ))\n}\n\n/// *(`git2`)* Create a new tag in the git repository\npub fn tag(repo: &git2::Repository, name: &str) {\n    let head = repo.head().unwrap().target().unwrap();\n    t!(repo.tag(\n        name,\n        &t!(repo.find_object(head, None)),\n        &t!(repo.signature()),\n        \"make a new tag\",\n        false\n    ));\n}\n\n/// Returns true if gitoxide is globally activated.\n///\n/// That way, tests that normally use `git2` can transparently use `gitoxide`.\npub fn cargo_uses_gitoxide() -> bool {\n    std::env::var_os(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\").map_or(false, |value| value == \"1\")\n}\n"
  },
  {
    "path": "crates/cargo-test-support/src/install.rs",
    "content": "//! Helpers for testing `cargo install`\n\nuse std::env::consts::EXE_SUFFIX;\nuse std::path::Path;\n\n/// Used by `cargo install` tests to assert an executable binary\n/// has been installed. Example usage:\n/// ```no_run\n/// use cargo_test_support::install::assert_has_installed_exe;\n/// use cargo_test_support::paths;\n///\n/// assert_has_installed_exe(paths::cargo_home(), \"foo\");\n/// ```\n#[track_caller]\npub fn assert_has_installed_exe<P: AsRef<Path>>(path: P, name: &'static str) {\n    assert!(check_has_installed_exe(path, name));\n}\n\n#[track_caller]\npub fn assert_has_not_installed_exe<P: AsRef<Path>>(path: P, name: &'static str) {\n    assert!(!check_has_installed_exe(path, name));\n}\n\nfn check_has_installed_exe<P: AsRef<Path>>(path: P, name: &'static str) -> bool {\n    path.as_ref().join(\"bin\").join(exe(name)).is_file()\n}\n\n/// `$name$EXE`\npub fn exe(name: &str) -> String {\n    format!(\"{}{}\", name, EXE_SUFFIX)\n}\n"
  },
  {
    "path": "crates/cargo-test-support/src/lib.rs",
    "content": "//! # Cargo test support.\n//!\n//! See <https://rust-lang.github.io/cargo/contrib/> for a guide on writing tests.\n//!\n//! There are two places you can find API documentation\n//!\n//! - <https://docs.rs/cargo-test-support>:\n//!   targeted at external tool developers testing cargo-related code\n//!   - Released with every rustc release\n//! - <https://doc.rust-lang.org/nightly/nightly-rustc/cargo_test_support>:\n//!   targeted at cargo contributors\n//!   - Updated on each update of the `cargo` submodule in `rust-lang/rust`\n//!\n//! > This crate is maintained by the Cargo team, primarily for use by Cargo\n//! > and not intended for external use. This\n//! > crate may make major changes to its APIs or be deprecated without warning.\n//!\n//! # Example\n//!\n//! ```rust,no_run\n//! use cargo_test_support::prelude::*;\n//! use cargo_test_support::str;\n//! use cargo_test_support::project;\n//!\n//! #[cargo_test]\n//! fn some_test() {\n//!     let p = project()\n//!         .file(\"src/main.rs\", r#\"fn main() { println!(\"hi!\"); }\"#)\n//!         .build();\n//!\n//!     p.cargo(\"run --bin foo\")\n//!         .with_stderr_data(str![[r#\"\n//! [COMPILING] foo [..]\n//! [FINISHED] [..]\n//! [RUNNING] `target/debug/foo`\n//! \"#]])\n//!         .with_stdout_data(str![[\"hi!\"]])\n//!         .run();\n//! }\n//! ```\n\n#![allow(clippy::disallowed_methods)]\n#![allow(clippy::print_stderr)]\n#![allow(clippy::print_stdout)]\n\nuse std::env;\nuse std::ffi::OsStr;\nuse std::fmt::Write;\nuse std::fs;\nuse std::os;\nuse std::path::{Path, PathBuf};\nuse std::process::{Command, Output};\nuse std::sync::LazyLock;\nuse std::sync::OnceLock;\nuse std::thread::JoinHandle;\nuse std::time::{self, Duration};\n\nuse anyhow::{Result, bail};\nuse cargo_util::{ProcessError, is_ci};\nuse snapbox::IntoData as _;\nuse url::Url;\n\nuse self::paths::CargoPathExt;\n\n/// Unwrap a `Result` with a useful panic message\n///\n/// # Example\n///\n/// ```rust\n/// use cargo_test_support::t;\n/// t!(std::fs::read_to_string(\"Cargo.toml\"));\n/// ```\n#[macro_export]\nmacro_rules! t {\n    ($e:expr) => {\n        match $e {\n            Ok(e) => e,\n            Err(e) => $crate::panic_error(&format!(\"failed running {}\", stringify!($e)), e),\n        }\n    };\n}\n\npub use cargo_util::ProcessBuilder;\npub use snapbox::file;\npub use snapbox::str;\npub use snapbox::utils::current_dir;\n\n/// `panic!`, reporting the specified error , see also [`t!`]\n#[track_caller]\npub fn panic_error(what: &str, err: impl Into<anyhow::Error>) -> ! {\n    let err = err.into();\n    pe(what, err);\n    #[track_caller]\n    fn pe(what: &str, err: anyhow::Error) -> ! {\n        let mut result = format!(\"{}\\nerror: {}\", what, err);\n        for cause in err.chain().skip(1) {\n            let _ = writeln!(result, \"\\nCaused by:\");\n            let _ = write!(result, \"{}\", cause);\n        }\n        panic!(\"\\n{}\", result);\n    }\n}\n\npub use cargo_test_macro::cargo_test;\n\npub mod compare;\npub mod containers;\npub mod cross_compile;\npub mod git;\npub mod install;\npub mod paths;\npub mod publish;\npub mod registry;\n\npub mod prelude {\n    pub use crate::ArgLineCommandExt;\n    pub use crate::ChannelChangerCommandExt;\n    pub use crate::TestEnvCommandExt;\n    pub use crate::cargo_test;\n    pub use crate::paths::CargoPathExt;\n    pub use snapbox::IntoData;\n}\n\n/*\n *\n * ===== Builders =====\n *\n */\n\n#[derive(PartialEq, Clone)]\nstruct FileBuilder {\n    path: PathBuf,\n    body: String,\n    executable: bool,\n}\n\nimpl FileBuilder {\n    pub fn new(path: PathBuf, body: &str, executable: bool) -> FileBuilder {\n        FileBuilder {\n            path,\n            body: body.to_string(),\n            executable: executable,\n        }\n    }\n\n    fn mk(&mut self) {\n        if self.executable {\n            let mut path = self.path.clone().into_os_string();\n            write!(path, \"{}\", env::consts::EXE_SUFFIX).unwrap();\n            self.path = path.into();\n        }\n\n        self.dirname().mkdir_p();\n        fs::write(&self.path, &self.body)\n            .unwrap_or_else(|e| panic!(\"could not create file {}: {}\", self.path.display(), e));\n\n        #[cfg(unix)]\n        if self.executable {\n            use std::os::unix::fs::PermissionsExt;\n\n            let mut perms = fs::metadata(&self.path).unwrap().permissions();\n            let mode = perms.mode();\n            perms.set_mode(mode | 0o111);\n            fs::set_permissions(&self.path, perms).unwrap();\n        }\n    }\n\n    fn dirname(&self) -> &Path {\n        self.path.parent().unwrap()\n    }\n}\n\n#[derive(PartialEq, Clone)]\nstruct SymlinkBuilder {\n    dst: PathBuf,\n    src: PathBuf,\n    src_is_dir: bool,\n}\n\nimpl SymlinkBuilder {\n    pub fn new(dst: PathBuf, src: PathBuf) -> SymlinkBuilder {\n        SymlinkBuilder {\n            dst,\n            src,\n            src_is_dir: false,\n        }\n    }\n\n    pub fn new_dir(dst: PathBuf, src: PathBuf) -> SymlinkBuilder {\n        SymlinkBuilder {\n            dst,\n            src,\n            src_is_dir: true,\n        }\n    }\n\n    #[cfg(unix)]\n    fn mk(&self) {\n        self.dirname().mkdir_p();\n        t!(os::unix::fs::symlink(&self.dst, &self.src));\n    }\n\n    #[cfg(windows)]\n    fn mk(&mut self) {\n        self.dirname().mkdir_p();\n        if self.src_is_dir {\n            t!(os::windows::fs::symlink_dir(&self.dst, &self.src));\n        } else {\n            if let Some(ext) = self.dst.extension() {\n                if ext == env::consts::EXE_EXTENSION {\n                    self.src.set_extension(ext);\n                }\n            }\n            t!(os::windows::fs::symlink_file(&self.dst, &self.src));\n        }\n    }\n\n    fn dirname(&self) -> &Path {\n        self.src.parent().unwrap()\n    }\n}\n\n/// A cargo project to run tests against.\n///\n/// See [`ProjectBuilder`] or [`Project::from_template`] to get started.\npub struct Project {\n    root: PathBuf,\n}\n\n/// Create a project to run tests against\n///\n/// - Creates a [`basic_manifest`] if one isn't supplied\n///\n/// To get started, see:\n/// - [`project`]\n/// - [`project_in`]\n/// - [`project_in_home`]\n/// - [`Project::from_template`]\n#[must_use]\npub struct ProjectBuilder {\n    root: Project,\n    files: Vec<FileBuilder>,\n    symlinks: Vec<SymlinkBuilder>,\n    no_manifest: bool,\n}\n\nimpl ProjectBuilder {\n    /// Root of the project\n    ///\n    /// ex: `$CARGO_TARGET_TMPDIR/cit/t0/foo`\n    pub fn root(&self) -> PathBuf {\n        self.root.root()\n    }\n\n    /// Project's debug dir\n    ///\n    /// ex: `$CARGO_TARGET_TMPDIR/cit/t0/foo/target/debug`\n    pub fn target_debug_dir(&self) -> PathBuf {\n        self.root.target_debug_dir()\n    }\n\n    /// Create project in `root`\n    pub fn new(root: PathBuf) -> ProjectBuilder {\n        ProjectBuilder {\n            root: Project { root },\n            files: vec![],\n            symlinks: vec![],\n            no_manifest: false,\n        }\n    }\n\n    /// Create project, relative to [`paths::root`]\n    pub fn at<P: AsRef<Path>>(mut self, path: P) -> Self {\n        self.root = Project {\n            root: paths::root().join(path),\n        };\n        self\n    }\n\n    /// Adds a file to the project.\n    pub fn file<B: AsRef<Path>>(mut self, path: B, body: &str) -> Self {\n        self._file(path.as_ref(), body, false);\n        self\n    }\n\n    /// Adds an executable file to the project.\n    pub fn executable<B: AsRef<Path>>(mut self, path: B, body: &str) -> Self {\n        self._file(path.as_ref(), body, true);\n        self\n    }\n\n    fn _file(&mut self, path: &Path, body: &str, executable: bool) {\n        self.files.push(FileBuilder::new(\n            self.root.root().join(path),\n            body,\n            executable,\n        ));\n    }\n\n    /// Adds a symlink to a file to the project.\n    pub fn symlink(mut self, dst: impl AsRef<Path>, src: impl AsRef<Path>) -> Self {\n        self.symlinks.push(SymlinkBuilder::new(\n            self.root.root().join(dst),\n            self.root.root().join(src),\n        ));\n        self\n    }\n\n    /// Create a symlink to a directory\n    pub fn symlink_dir(mut self, dst: impl AsRef<Path>, src: impl AsRef<Path>) -> Self {\n        self.symlinks.push(SymlinkBuilder::new_dir(\n            self.root.root().join(dst),\n            self.root.root().join(src),\n        ));\n        self\n    }\n\n    pub fn no_manifest(mut self) -> Self {\n        self.no_manifest = true;\n        self\n    }\n\n    /// Creates the project.\n    pub fn build(mut self) -> Project {\n        // First, clean the directory if it already exists\n        self.rm_root();\n\n        // Create the empty directory\n        self.root.root().mkdir_p();\n\n        let manifest_path = self.root.root().join(\"Cargo.toml\");\n        if !self.no_manifest && self.files.iter().all(|fb| fb.path != manifest_path) {\n            self._file(\n                Path::new(\"Cargo.toml\"),\n                &basic_manifest(\"foo\", \"0.0.1\"),\n                false,\n            )\n        }\n\n        let past = time::SystemTime::now() - Duration::new(1, 0);\n        let ftime = filetime::FileTime::from_system_time(past);\n\n        for file in self.files.iter_mut() {\n            file.mk();\n            if is_coarse_mtime() {\n                // Place the entire project 1 second in the past to ensure\n                // that if cargo is called multiple times, the 2nd call will\n                // see targets as \"fresh\". Without this, if cargo finishes in\n                // under 1 second, the second call will see the mtime of\n                // source == mtime of output and consider it dirty.\n                filetime::set_file_times(&file.path, ftime, ftime).unwrap();\n            }\n        }\n\n        for symlink in self.symlinks.iter_mut() {\n            symlink.mk();\n        }\n\n        let ProjectBuilder { root, .. } = self;\n        root\n    }\n\n    fn rm_root(&self) {\n        self.root.root().rm_rf()\n    }\n}\n\nimpl Project {\n    /// Copy the test project from a fixed state\n    pub fn from_template(template_path: impl AsRef<Path>) -> Self {\n        let root = paths::root();\n        let project_root = root.join(\"case\");\n        snapbox::dir::copy_template(template_path.as_ref(), &project_root).unwrap();\n        Self { root: project_root }\n    }\n\n    /// Root of the project\n    ///\n    /// ex: `$CARGO_TARGET_TMPDIR/cit/t0/foo`\n    pub fn root(&self) -> PathBuf {\n        self.root.clone()\n    }\n\n    /// Project's target dir\n    ///\n    /// ex: `$CARGO_TARGET_TMPDIR/cit/t0/foo/target`\n    pub fn build_dir(&self) -> PathBuf {\n        self.root().join(\"target\")\n    }\n\n    /// Project's debug dir\n    ///\n    /// ex: `$CARGO_TARGET_TMPDIR/cit/t0/foo/target/debug`\n    pub fn target_debug_dir(&self) -> PathBuf {\n        self.build_dir().join(\"debug\")\n    }\n\n    /// File url for root\n    ///\n    /// ex: `file://$CARGO_TARGET_TMPDIR/cit/t0/foo`\n    pub fn url(&self) -> Url {\n        use paths::CargoPathExt;\n        self.root().to_url()\n    }\n\n    /// Path to an example built as a library.\n    ///\n    /// `kind` should be one of: \"lib\", \"rlib\", \"staticlib\", \"dylib\", \"proc-macro\"\n    ///\n    /// ex: `$CARGO_TARGET_TMPDIR/cit/t0/foo/target/debug/examples/libex.rlib`\n    pub fn example_lib(&self, name: &str, kind: &str) -> PathBuf {\n        self.target_debug_dir()\n            .join(\"examples\")\n            .join(paths::get_lib_filename(name, kind))\n    }\n\n    /// Path to a dynamic library.\n    /// ex: `/path/to/cargo/target/cit/t0/foo/target/debug/examples/libex.dylib`\n    pub fn dylib(&self, name: &str) -> PathBuf {\n        self.target_debug_dir().join(format!(\n            \"{}{name}{}\",\n            env::consts::DLL_PREFIX,\n            env::consts::DLL_SUFFIX\n        ))\n    }\n\n    /// Path to a debug binary.\n    ///\n    /// ex: `$CARGO_TARGET_TMPDIR/cit/t0/foo/target/debug/foo`\n    pub fn bin(&self, b: &str) -> PathBuf {\n        self.build_dir()\n            .join(\"debug\")\n            .join(&format!(\"{}{}\", b, env::consts::EXE_SUFFIX))\n    }\n\n    /// Path to a release binary.\n    ///\n    /// ex: `$CARGO_TARGET_TMPDIR/cit/t0/foo/target/release/foo`\n    pub fn release_bin(&self, b: &str) -> PathBuf {\n        self.build_dir()\n            .join(\"release\")\n            .join(&format!(\"{}{}\", b, env::consts::EXE_SUFFIX))\n    }\n\n    /// Path to a debug binary for a specific target triple.\n    ///\n    /// ex: `$CARGO_TARGET_TMPDIR/cit/t0/foo/target/i686-apple-darwin/debug/foo`\n    pub fn target_bin(&self, target: &str, b: &str) -> PathBuf {\n        self.build_dir().join(target).join(\"debug\").join(&format!(\n            \"{}{}\",\n            b,\n            env::consts::EXE_SUFFIX\n        ))\n    }\n\n    /// Returns an iterator of paths within [`Project::root`] matching the glob pattern\n    pub fn glob<P: AsRef<Path>>(&self, pattern: P) -> glob::Paths {\n        let pattern = self.root().join(pattern);\n        glob::glob(pattern.to_str().expect(\"failed to convert pattern to str\"))\n            .expect(\"failed to glob\")\n    }\n\n    /// Overwrite a file with new content\n    ///\n    // # Example:\n    ///\n    /// ```no_run\n    /// # let p = cargo_test_support::project().build();\n    /// p.change_file(\"src/lib.rs\", \"fn new_fn() {}\");\n    /// ```\n    pub fn change_file(&self, path: impl AsRef<Path>, body: &str) {\n        FileBuilder::new(self.root().join(path), body, false).mk()\n    }\n\n    /// Creates a `ProcessBuilder` to run a program in the project\n    /// and wrap it in an Execs to assert on the execution.\n    ///\n    /// # Example:\n    ///\n    /// ```no_run\n    /// # use cargo_test_support::str;\n    /// # let p = cargo_test_support::project().build();\n    /// p.process(&p.bin(\"foo\"))\n    ///     .with_stdout_data(str![\"bar\\n\"])\n    ///     .run();\n    /// ```\n    pub fn process<T: AsRef<OsStr>>(&self, program: T) -> Execs {\n        let mut p = process(program);\n        p.cwd(self.root());\n        execs().with_process_builder(p)\n    }\n\n    /// Safely run a process after `cargo build`.\n    ///\n    /// Windows has a problem where a process cannot be reliably\n    /// be replaced, removed, or renamed immediately after executing it.\n    /// The action may fail (with errors like Access is denied), or\n    /// it may succeed, but future attempts to use the same filename\n    /// will fail with \"Already Exists\".\n    ///\n    /// If you have a test that needs to do `cargo run` multiple\n    /// times, you should instead use `cargo build` and use this\n    /// method to run the executable. Each time you call this,\n    /// use a new name for `dst`.\n    /// See rust-lang/cargo#5481.\n    pub fn rename_run(&self, src: &str, dst: &str) -> Execs {\n        let src = self.bin(src);\n        let dst = self.bin(dst);\n        fs::rename(&src, &dst)\n            .unwrap_or_else(|e| panic!(\"Failed to rename `{:?}` to `{:?}`: {}\", src, dst, e));\n        self.process(dst)\n    }\n\n    /// Returns the contents of `Cargo.lock`.\n    pub fn read_lockfile(&self) -> String {\n        self.read_file(\"Cargo.lock\")\n    }\n\n    /// Returns the contents of a path in the project root\n    pub fn read_file(&self, path: impl AsRef<Path>) -> String {\n        let full = self.root().join(path);\n        fs::read_to_string(&full)\n            .unwrap_or_else(|e| panic!(\"could not read file {}: {}\", full.display(), e))\n    }\n\n    /// Modifies `Cargo.toml` to remove all commented lines.\n    pub fn uncomment_root_manifest(&self) {\n        let contents = self.read_file(\"Cargo.toml\").replace(\"#\", \"\");\n        fs::write(self.root().join(\"Cargo.toml\"), contents).unwrap();\n    }\n\n    pub fn symlink(&self, src: impl AsRef<Path>, dst: impl AsRef<Path>) {\n        let src = self.root().join(src.as_ref());\n        let dst = self.root().join(dst.as_ref());\n        #[cfg(unix)]\n        {\n            if let Err(e) = os::unix::fs::symlink(&src, &dst) {\n                panic!(\"failed to symlink {:?} to {:?}: {:?}\", src, dst, e);\n            }\n        }\n        #[cfg(windows)]\n        {\n            if src.is_dir() {\n                if let Err(e) = os::windows::fs::symlink_dir(&src, &dst) {\n                    panic!(\"failed to symlink {:?} to {:?}: {:?}\", src, dst, e);\n                }\n            } else {\n                if let Err(e) = os::windows::fs::symlink_file(&src, &dst) {\n                    panic!(\"failed to symlink {:?} to {:?}: {:?}\", src, dst, e);\n                }\n            }\n        }\n    }\n}\n\n/// Generates a project layout, see [`ProjectBuilder`]\npub fn project() -> ProjectBuilder {\n    ProjectBuilder::new(paths::root().join(\"foo\"))\n}\n\n/// Generates a project layout in given directory, see [`ProjectBuilder`]\npub fn project_in(dir: impl AsRef<Path>) -> ProjectBuilder {\n    ProjectBuilder::new(paths::root().join(dir).join(\"foo\"))\n}\n\n/// Generates a project layout inside our fake home dir, see [`ProjectBuilder`]\npub fn project_in_home(name: impl AsRef<Path>) -> ProjectBuilder {\n    ProjectBuilder::new(paths::home().join(name))\n}\n\n// === Helpers ===\n\n/// Generate a `main.rs` printing the specified text\n///\n/// ```rust\n/// # use cargo_test_support::main_file;\n/// # mod dep {\n/// #     fn bar() -> &'static str {\n/// #         \"world\"\n/// #     }\n/// # }\n/// main_file(\n///     r#\"\"hello {}\", dep::bar()\"#,\n///     &[]\n/// );\n/// ```\npub fn main_file(println: &str, externed_deps: &[&str]) -> String {\n    let mut buf = String::new();\n\n    for dep in externed_deps.iter() {\n        buf.push_str(&format!(\"extern crate {};\\n\", dep));\n    }\n\n    buf.push_str(\"fn main() { println!(\");\n    buf.push_str(println);\n    buf.push_str(\"); }\\n\");\n\n    buf\n}\n\n/// This is the raw output from the process.\n///\n/// This is similar to `std::process::Output`, however the `status` is\n/// translated to the raw `code`. This is necessary because `ProcessError`\n/// does not have access to the raw `ExitStatus` because `ProcessError` needs\n/// to be serializable (for the Rustc cache), and `ExitStatus` does not\n/// provide a constructor.\npub struct RawOutput {\n    pub code: Option<i32>,\n    pub stdout: Vec<u8>,\n    pub stderr: Vec<u8>,\n}\n\n/// Run and verify a [`ProcessBuilder`]\n///\n/// Construct with\n/// - [`execs`]\n/// - [`Project`] methods\n/// - `cargo_process` in testsuite\n#[must_use]\n#[derive(Clone)]\npub struct Execs {\n    ran: bool,\n    process_builder: Option<ProcessBuilder>,\n    expect_stdin: Option<String>,\n    expect_exit_code: Option<i32>,\n    expect_stdout_data: Option<snapbox::Data>,\n    expect_stderr_data: Option<snapbox::Data>,\n    expect_stdout_contains: Vec<String>,\n    expect_stderr_contains: Vec<String>,\n    expect_stdout_not_contains: Vec<String>,\n    expect_stderr_not_contains: Vec<String>,\n    expect_stderr_with_without: Vec<(Vec<String>, Vec<String>)>,\n    stream_output: bool,\n    assert: snapbox::Assert,\n}\n\nimpl Execs {\n    pub fn with_process_builder(mut self, p: ProcessBuilder) -> Execs {\n        self.process_builder = Some(p);\n        self\n    }\n}\n\n/// # Configure assertions\nimpl Execs {\n    /// Verifies that stdout is equal to the given lines.\n    ///\n    /// See [`compare::assert_e2e`] for assertion details.\n    ///\n    /// <div class=\"warning\">\n    ///\n    /// Prefer passing in [`str!`] for `expected` to get snapshot updating.\n    ///\n    /// If `format!` is needed for content that changes from run to run that you don't care about,\n    /// consider whether you could have [`compare::assert_e2e`] redact the content.\n    /// If nothing else, a wildcard (`[..]`, `...`) may be useful.\n    ///\n    /// However, `\"\"` may be preferred for intentionally empty output so people don't accidentally\n    /// bless a change.\n    ///\n    /// </div>\n    ///\n    /// # Examples\n    ///\n    /// ```no_run\n    /// use cargo_test_support::prelude::*;\n    /// use cargo_test_support::str;\n    /// use cargo_test_support::execs;\n    ///\n    /// execs().with_stdout_data(str![r#\"\n    /// Hello world!\n    /// \"#]);\n    /// ```\n    ///\n    /// Non-deterministic compiler output\n    /// ```no_run\n    /// use cargo_test_support::prelude::*;\n    /// use cargo_test_support::str;\n    /// use cargo_test_support::execs;\n    ///\n    /// execs().with_stdout_data(str![r#\"\n    /// [COMPILING] foo\n    /// [COMPILING] bar\n    /// \"#].unordered());\n    /// ```\n    ///\n    /// jsonlines\n    /// ```no_run\n    /// use cargo_test_support::prelude::*;\n    /// use cargo_test_support::str;\n    /// use cargo_test_support::execs;\n    ///\n    /// execs().with_stdout_data(str![r#\"\n    /// [\n    ///   {},\n    ///   {}\n    /// ]\n    /// \"#].is_json().against_jsonlines());\n    /// ```\n    pub fn with_stdout_data(&mut self, expected: impl snapbox::IntoData) -> &mut Self {\n        self.expect_stdout_data = Some(expected.into_data());\n        self\n    }\n\n    /// Verifies that stderr is equal to the given lines.\n    ///\n    /// See [`compare::assert_e2e`] for assertion details.\n    ///\n    /// <div class=\"warning\">\n    ///\n    /// Prefer passing in [`str!`] for `expected` to get snapshot updating.\n    ///\n    /// If `format!` is needed for content that changes from run to run that you don't care about,\n    /// consider whether you could have [`compare::assert_e2e`] redact the content.\n    /// If nothing else, a wildcard (`[..]`, `...`) may be useful.\n    ///\n    /// However, `\"\"` may be preferred for intentionally empty output so people don't accidentally\n    /// bless a change.\n    ///\n    /// </div>\n    ///\n    /// # Examples\n    ///\n    /// ```no_run\n    /// use cargo_test_support::prelude::*;\n    /// use cargo_test_support::str;\n    /// use cargo_test_support::execs;\n    ///\n    /// execs().with_stderr_data(str![r#\"\n    /// Hello world!\n    /// \"#]);\n    /// ```\n    ///\n    /// Non-deterministic compiler output\n    /// ```no_run\n    /// use cargo_test_support::prelude::*;\n    /// use cargo_test_support::str;\n    /// use cargo_test_support::execs;\n    ///\n    /// execs().with_stderr_data(str![r#\"\n    /// [COMPILING] foo\n    /// [COMPILING] bar\n    /// \"#].unordered());\n    /// ```\n    ///\n    /// jsonlines\n    /// ```no_run\n    /// use cargo_test_support::prelude::*;\n    /// use cargo_test_support::str;\n    /// use cargo_test_support::execs;\n    ///\n    /// execs().with_stderr_data(str![r#\"\n    /// [\n    ///   {},\n    ///   {}\n    /// ]\n    /// \"#].is_json().against_jsonlines());\n    /// ```\n    pub fn with_stderr_data(&mut self, expected: impl snapbox::IntoData) -> &mut Self {\n        self.expect_stderr_data = Some(expected.into_data());\n        self\n    }\n\n    /// Writes the given lines to stdin.\n    pub fn with_stdin<S: ToString>(&mut self, expected: S) -> &mut Self {\n        self.expect_stdin = Some(expected.to_string());\n        self\n    }\n\n    /// Verifies the exit code from the process.\n    ///\n    /// This is not necessary if the expected exit code is `0`.\n    pub fn with_status(&mut self, expected: i32) -> &mut Self {\n        self.expect_exit_code = Some(expected);\n        self\n    }\n\n    /// Removes exit code check for the process.\n    ///\n    /// By default, the expected exit code is `0`.\n    pub fn without_status(&mut self) -> &mut Self {\n        self.expect_exit_code = None;\n        self\n    }\n\n    /// Verifies that stdout contains the given contiguous lines somewhere in\n    /// its output.\n    ///\n    /// See [`compare`] for supported patterns.\n    ///\n    /// <div class=\"warning\">\n    ///\n    /// Prefer [`Execs::with_stdout_data`] where possible.\n    /// - `expected` cannot be snapshotted\n    /// - `expected` can end up being ambiguous, causing the assertion to succeed when it should fail\n    ///\n    /// </div>\n    pub fn with_stdout_contains<S: ToString>(&mut self, expected: S) -> &mut Self {\n        self.expect_stdout_contains.push(expected.to_string());\n        self\n    }\n\n    /// Verifies that stderr contains the given contiguous lines somewhere in\n    /// its output.\n    ///\n    /// See [`compare`] for supported patterns.\n    ///\n    /// <div class=\"warning\">\n    ///\n    /// Prefer [`Execs::with_stderr_data`] where possible.\n    /// - `expected` cannot be snapshotted\n    /// - `expected` can end up being ambiguous, causing the assertion to succeed when it should fail\n    ///\n    /// </div>\n    pub fn with_stderr_contains<S: ToString>(&mut self, expected: S) -> &mut Self {\n        self.expect_stderr_contains.push(expected.to_string());\n        self\n    }\n\n    /// Verifies that stdout does not contain the given contiguous lines.\n    ///\n    /// See [`compare`] for supported patterns.\n    ///\n    /// See note on [`Self::with_stderr_does_not_contain`].\n    ///\n    /// <div class=\"warning\">\n    ///\n    /// Prefer [`Execs::with_stdout_data`] where possible.\n    /// - `expected` cannot be snapshotted\n    /// - The absence of `expected` can either mean success or that the string being looked for\n    ///   changed.\n    ///\n    /// To mitigate this, consider matching this up with\n    /// [`Execs::with_stdout_contains`].\n    ///\n    /// </div>\n    pub fn with_stdout_does_not_contain<S: ToString>(&mut self, expected: S) -> &mut Self {\n        self.expect_stdout_not_contains.push(expected.to_string());\n        self\n    }\n\n    /// Verifies that stderr does not contain the given contiguous lines.\n    ///\n    /// See [`compare`] for supported patterns.\n    ///\n    /// <div class=\"warning\">\n    ///\n    /// Prefer [`Execs::with_stdout_data`] where possible.\n    /// - `expected` cannot be snapshotted\n    /// - The absence of `expected` can either mean success or that the string being looked for\n    ///   changed.\n    ///\n    /// To mitigate this, consider either matching this up with\n    /// [`Execs::with_stdout_contains`] or replace it\n    /// with [`Execs::with_stderr_line_without`].\n    ///\n    /// </div>\n    pub fn with_stderr_does_not_contain<S: ToString>(&mut self, expected: S) -> &mut Self {\n        self.expect_stderr_not_contains.push(expected.to_string());\n        self\n    }\n\n    /// Verify that a particular line appears in stderr with and without the\n    /// given substrings. Exactly one line must match.\n    ///\n    /// The substrings are matched as `contains`.\n    ///\n    /// <div class=\"warning\">\n    ///\n    /// Prefer [`Execs::with_stdout_data`] where possible.\n    /// - `with` cannot be snapshotted\n    /// - The absence of `without` can either mean success or that the string being looked for\n    ///   changed.\n    ///\n    /// </div>\n    ///\n    /// # Example\n    ///\n    /// ```no_run\n    /// use cargo_test_support::execs;\n    ///\n    /// execs().with_stderr_line_without(\n    ///     &[\n    ///         \"[RUNNING] `rustc --crate-name build_script_build\",\n    ///         \"-C opt-level=3\",\n    ///     ],\n    ///     &[\"-C debuginfo\", \"-C incremental\"],\n    /// );\n    /// ```\n    ///\n    /// This will check that a build line includes `-C opt-level=3` but does\n    /// not contain `-C debuginfo` or `-C incremental`.\n    ///\n    pub fn with_stderr_line_without<S: ToString>(\n        &mut self,\n        with: &[S],\n        without: &[S],\n    ) -> &mut Self {\n        let with = with.iter().map(|s| s.to_string()).collect();\n        let without = without.iter().map(|s| s.to_string()).collect();\n        self.expect_stderr_with_without.push((with, without));\n        self\n    }\n}\n\n/// # Configure the process\nimpl Execs {\n    /// Forward subordinate process stdout/stderr to the terminal.\n    /// Useful for printf debugging of the tests.\n    /// CAUTION: CI will fail if you leave this in your test!\n    #[allow(unused)]\n    pub fn stream(&mut self) -> &mut Self {\n        self.stream_output = true;\n        self\n    }\n\n    pub fn arg<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut Self {\n        if let Some(ref mut p) = self.process_builder {\n            p.arg(arg);\n        }\n        self\n    }\n\n    pub fn args<T: AsRef<OsStr>>(&mut self, args: &[T]) -> &mut Self {\n        if let Some(ref mut p) = self.process_builder {\n            p.args(args);\n        }\n        self\n    }\n\n    pub fn cwd<T: AsRef<OsStr>>(&mut self, path: T) -> &mut Self {\n        if let Some(ref mut p) = self.process_builder {\n            if let Some(cwd) = p.get_cwd() {\n                let new_path = cwd.join(path.as_ref());\n                p.cwd(new_path);\n            } else {\n                p.cwd(path);\n            }\n        }\n        self\n    }\n\n    pub fn env<T: AsRef<OsStr>>(&mut self, key: &str, val: T) -> &mut Self {\n        if let Some(ref mut p) = self.process_builder {\n            p.env(key, val);\n        }\n        self\n    }\n\n    pub fn env_remove(&mut self, key: &str) -> &mut Self {\n        if let Some(ref mut p) = self.process_builder {\n            p.env_remove(key);\n        }\n        self\n    }\n\n    /// Enables nightly features for testing\n    ///\n    /// The list of reasons should be why nightly cargo is needed. If it is\n    /// because of an unstable feature put the name of the feature as the reason,\n    /// e.g. `&[\"print-im-a-teapot\"]`\n    pub fn masquerade_as_nightly_cargo(&mut self, reasons: &[&str]) -> &mut Self {\n        if let Some(ref mut p) = self.process_builder {\n            p.masquerade_as_nightly_cargo(reasons);\n        }\n        self\n    }\n\n    /// Overrides the crates.io URL for testing.\n    ///\n    /// Can be used for testing crates-io functionality where alt registries\n    /// cannot be used.\n    pub fn replace_crates_io(&mut self, url: &Url) -> &mut Self {\n        if let Some(ref mut p) = self.process_builder {\n            p.env(\"__CARGO_TEST_CRATES_IO_URL_DO_NOT_USE_THIS\", url.as_str());\n        }\n        self\n    }\n\n    pub fn overlay_registry(&mut self, url: &Url, path: &str) -> &mut Self {\n        if let Some(ref mut p) = self.process_builder {\n            let env_value = format!(\"{}={}\", url, path);\n            p.env(\n                \"__CARGO_TEST_DEPENDENCY_CONFUSION_VULNERABILITY_DO_NOT_USE_THIS\",\n                env_value,\n            );\n        }\n        self\n    }\n\n    pub fn enable_split_debuginfo_packed(&mut self) -> &mut Self {\n        self.env(\"CARGO_PROFILE_DEV_SPLIT_DEBUGINFO\", \"packed\")\n            .env(\"CARGO_PROFILE_TEST_SPLIT_DEBUGINFO\", \"packed\")\n            .env(\"CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO\", \"packed\")\n            .env(\"CARGO_PROFILE_BENCH_SPLIT_DEBUGINFO\", \"packed\");\n        self\n    }\n\n    pub fn enable_mac_dsym(&mut self) -> &mut Self {\n        if cfg!(target_os = \"macos\") {\n            return self.enable_split_debuginfo_packed();\n        }\n        self\n    }\n}\n\n/// # Run and verify the process\nimpl Execs {\n    pub fn exec_with_output(&mut self) -> Result<Output> {\n        self.ran = true;\n        // TODO avoid unwrap\n        let p = (&self.process_builder).clone().unwrap();\n        p.exec_with_output()\n    }\n\n    pub fn build_command(&mut self) -> Command {\n        self.ran = true;\n        // TODO avoid unwrap\n        let p = (&self.process_builder).clone().unwrap();\n        p.build_command()\n    }\n\n    #[track_caller]\n    pub fn run(&mut self) -> RawOutput {\n        self.ran = true;\n        let mut p = (&self.process_builder).clone().unwrap();\n        if let Some(stdin) = self.expect_stdin.take() {\n            p.stdin(stdin);\n        }\n\n        match self.match_process(&p) {\n            Err(e) => panic_error(&format!(\"test failed running {}\", p), e),\n            Ok(output) => output,\n        }\n    }\n\n    /// Runs the process, checks the expected output, and returns the first\n    /// JSON object on stdout.\n    #[track_caller]\n    pub fn run_json(&mut self) -> serde_json::Value {\n        let output = self.run();\n        serde_json::from_slice(&output.stdout).unwrap_or_else(|e| {\n            panic!(\n                \"\\nfailed to parse JSON: {}\\n\\\n                     output was:\\n{}\\n\",\n                e,\n                String::from_utf8_lossy(&output.stdout)\n            );\n        })\n    }\n\n    #[track_caller]\n    pub fn run_output(&mut self, output: &Output) {\n        self.ran = true;\n        if let Err(e) = self.match_output(output.status.code(), &output.stdout, &output.stderr) {\n            panic_error(\"process did not return the expected result\", e)\n        }\n    }\n\n    #[track_caller]\n    fn verify_checks_output(&self, stdout: &[u8], stderr: &[u8]) {\n        if self.expect_exit_code.unwrap_or(0) != 0\n            && self.expect_stdin.is_none()\n            && self.expect_stdout_data.is_none()\n            && self.expect_stderr_data.is_none()\n            && self.expect_stdout_contains.is_empty()\n            && self.expect_stderr_contains.is_empty()\n            && self.expect_stdout_not_contains.is_empty()\n            && self.expect_stderr_not_contains.is_empty()\n            && self.expect_stderr_with_without.is_empty()\n        {\n            panic!(\n                \"`with_status()` is used, but no output is checked.\\n\\\n                 The test must check the output to ensure the correct error is triggered.\\n\\\n                 --- stdout\\n{}\\n--- stderr\\n{}\",\n                String::from_utf8_lossy(stdout),\n                String::from_utf8_lossy(stderr),\n            );\n        }\n    }\n\n    #[track_caller]\n    fn match_process(&self, process: &ProcessBuilder) -> Result<RawOutput> {\n        println!(\"running {}\", process);\n        let res = if self.stream_output {\n            if is_ci() {\n                panic!(\"`.stream()` is for local debugging\")\n            }\n            process.exec_with_streaming(\n                &mut |out| {\n                    println!(\"{}\", out);\n                    Ok(())\n                },\n                &mut |err| {\n                    eprintln!(\"{}\", err);\n                    Ok(())\n                },\n                true,\n            )\n        } else {\n            process.exec_with_output()\n        };\n\n        match res {\n            Ok(out) => {\n                self.match_output(out.status.code(), &out.stdout, &out.stderr)?;\n                return Ok(RawOutput {\n                    stdout: out.stdout,\n                    stderr: out.stderr,\n                    code: out.status.code(),\n                });\n            }\n            Err(e) => {\n                if let Some(ProcessError {\n                    stdout: Some(stdout),\n                    stderr: Some(stderr),\n                    code,\n                    ..\n                }) = e.downcast_ref::<ProcessError>()\n                {\n                    self.match_output(*code, stdout, stderr)?;\n                    return Ok(RawOutput {\n                        stdout: stdout.to_vec(),\n                        stderr: stderr.to_vec(),\n                        code: *code,\n                    });\n                }\n                bail!(\"could not exec process {}: {:?}\", process, e)\n            }\n        }\n    }\n\n    #[track_caller]\n    fn match_output(&self, code: Option<i32>, stdout: &[u8], stderr: &[u8]) -> Result<()> {\n        self.verify_checks_output(stdout, stderr);\n        let stdout = std::str::from_utf8(stdout).expect(\"stdout is not utf8\");\n        let stderr = std::str::from_utf8(stderr).expect(\"stderr is not utf8\");\n\n        match self.expect_exit_code {\n            None => {}\n            Some(expected) if code == Some(expected) => {}\n            Some(expected) => bail!(\n                \"process exited with code {} (expected {})\\n--- stdout\\n{}\\n--- stderr\\n{}\",\n                code.unwrap_or(-1),\n                expected,\n                stdout,\n                stderr\n            ),\n        }\n\n        if let Some(expect_stdout_data) = &self.expect_stdout_data {\n            if let Err(err) = self.assert.try_eq(\n                Some(&\"stdout\"),\n                stdout.into_data(),\n                expect_stdout_data.clone(),\n            ) {\n                panic!(\"{err}\")\n            }\n        }\n        if let Some(expect_stderr_data) = &self.expect_stderr_data {\n            if let Err(err) = self.assert.try_eq(\n                Some(&\"stderr\"),\n                stderr.into_data(),\n                expect_stderr_data.clone(),\n            ) {\n                panic!(\"{err}\")\n            }\n        }\n        for expect in self.expect_stdout_contains.iter() {\n            compare::match_contains(expect, stdout, self.assert.redactions())?;\n        }\n        for expect in self.expect_stderr_contains.iter() {\n            compare::match_contains(expect, stderr, self.assert.redactions())?;\n        }\n        for expect in self.expect_stdout_not_contains.iter() {\n            compare::match_does_not_contain(expect, stdout, self.assert.redactions())?;\n        }\n        for expect in self.expect_stderr_not_contains.iter() {\n            compare::match_does_not_contain(expect, stderr, self.assert.redactions())?;\n        }\n        for (with, without) in self.expect_stderr_with_without.iter() {\n            compare::match_with_without(stderr, with, without, self.assert.redactions())?;\n        }\n        Ok(())\n    }\n}\n\nimpl Drop for Execs {\n    fn drop(&mut self) {\n        if !self.ran && !std::thread::panicking() {\n            panic!(\"forgot to run this command\");\n        }\n    }\n}\n\n/// Run and verify a process, see [`Execs`]\npub fn execs() -> Execs {\n    Execs {\n        ran: false,\n        process_builder: None,\n        expect_stdin: None,\n        expect_exit_code: Some(0),\n        expect_stdout_data: None,\n        expect_stderr_data: None,\n        expect_stdout_contains: Vec::new(),\n        expect_stderr_contains: Vec::new(),\n        expect_stdout_not_contains: Vec::new(),\n        expect_stderr_not_contains: Vec::new(),\n        expect_stderr_with_without: Vec::new(),\n        stream_output: false,\n        assert: compare::assert_e2e(),\n    }\n}\n\n/// Generate a basic `Cargo.toml`\npub fn basic_manifest(name: &str, version: &str) -> String {\n    format!(\n        r#\"\n        [package]\n        name = \"{}\"\n        version = \"{}\"\n        authors = []\n        edition = \"2015\"\n    \"#,\n        name, version\n    )\n}\n\n/// Generate a `Cargo.toml` with the specified `bin.name`\npub fn basic_bin_manifest(name: &str) -> String {\n    format!(\n        r#\"\n        [package]\n\n        name = \"{}\"\n        version = \"0.5.0\"\n        authors = [\"wycats@example.com\"]\n        edition = \"2015\"\n\n        [[bin]]\n\n        name = \"{}\"\n    \"#,\n        name, name\n    )\n}\n\n/// Generate a `Cargo.toml` with the specified `lib.name`\npub fn basic_lib_manifest(name: &str) -> String {\n    format!(\n        r#\"\n        [package]\n\n        name = \"{}\"\n        version = \"0.5.0\"\n        authors = [\"wycats@example.com\"]\n        edition = \"2015\"\n\n        [lib]\n\n        name = \"{}\"\n    \"#,\n        name, name\n    )\n}\n\n/// Gets a valid target spec JSON from rustc.\n///\n/// To avoid any hardcoded value, this fetches `x86_64-unknown-none` target\n/// spec JSON directly from `rustc`, as Cargo shouldn't know the JSON schema.\npub fn target_spec_json() -> &'static str {\n    static TARGET_SPEC_JSON: LazyLock<String> = LazyLock::new(|| {\n        let json = std::process::Command::new(\"rustc\")\n            .env(\"RUSTC_BOOTSTRAP\", \"1\")\n            .arg(\"--print\")\n            .arg(\"target-spec-json\")\n            .arg(\"-Zunstable-options\")\n            .arg(\"--target\")\n            .arg(\"x86_64-unknown-none\")\n            .output()\n            .expect(\"rustc --print target-spec-json\")\n            .stdout;\n        String::from_utf8(json).expect(\"utf8 target spec json\")\n    });\n\n    TARGET_SPEC_JSON.as_str()\n}\n\nstruct RustcInfo {\n    verbose_version: String,\n    host: String,\n}\n\nimpl RustcInfo {\n    fn new() -> RustcInfo {\n        let output = ProcessBuilder::new(\"rustc\")\n            .arg(\"-vV\")\n            .exec_with_output()\n            .expect(\"rustc should exec\");\n        let verbose_version = String::from_utf8(output.stdout).expect(\"utf8 output\");\n        let host = verbose_version\n            .lines()\n            .filter_map(|line| line.strip_prefix(\"host: \"))\n            .next()\n            .expect(\"verbose version has host: field\")\n            .to_string();\n        RustcInfo {\n            verbose_version,\n            host,\n        }\n    }\n}\n\nfn rustc_info() -> &'static RustcInfo {\n    static RUSTC_INFO: OnceLock<RustcInfo> = OnceLock::new();\n    RUSTC_INFO.get_or_init(RustcInfo::new)\n}\n\n/// The rustc host such as `x86_64-unknown-linux-gnu`.\npub fn rustc_host() -> &'static str {\n    &rustc_info().host\n}\n\n/// The host triple suitable for use in a cargo environment variable (uppercased).\npub fn rustc_host_env() -> String {\n    rustc_host().to_uppercase().replace('-', \"_\")\n}\n\npub fn is_nightly() -> bool {\n    let vv = &rustc_info().verbose_version;\n    // CARGO_TEST_DISABLE_NIGHTLY is set in rust-lang/rust's CI so that all\n    // nightly-only tests are disabled there. Otherwise, it could make it\n    // difficult to land changes which would need to be made simultaneously in\n    // rust-lang/cargo and rust-lan/rust, which isn't possible.\n    env::var(\"CARGO_TEST_DISABLE_NIGHTLY\").is_err()\n        && (vv.contains(\"-nightly\") || vv.contains(\"-dev\"))\n}\n\n/// Run `$bin` in the test's environment, see [`ProcessBuilder`]\n///\n/// For more on the test environment, see\n/// - [`paths::root`]\n/// - [`TestEnvCommandExt`]\npub fn process<T: AsRef<OsStr>>(bin: T) -> ProcessBuilder {\n    _process(bin.as_ref())\n}\n\nfn _process(t: &OsStr) -> ProcessBuilder {\n    let mut p = ProcessBuilder::new(t);\n    p.cwd(&paths::root()).test_env();\n    p\n}\n\n/// Enable nightly features for testing\npub trait ChannelChangerCommandExt {\n    /// The list of reasons should be why nightly cargo is needed. If it is\n    /// because of an unstable feature put the name of the feature as the reason,\n    /// e.g. `&[\"print-im-a-teapot\"]`.\n    fn masquerade_as_nightly_cargo(self, _reasons: &[&str]) -> Self;\n}\n\nimpl ChannelChangerCommandExt for &mut ProcessBuilder {\n    fn masquerade_as_nightly_cargo(self, _reasons: &[&str]) -> Self {\n        self.env(\"__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS\", \"nightly\")\n    }\n}\n\nimpl ChannelChangerCommandExt for snapbox::cmd::Command {\n    fn masquerade_as_nightly_cargo(self, _reasons: &[&str]) -> Self {\n        self.env(\"__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS\", \"nightly\")\n    }\n}\n\n/// Establish a process's test environment\npub trait TestEnvCommandExt: Sized {\n    fn test_env(mut self) -> Self {\n        // In general just clear out all cargo-specific configuration already in the\n        // environment. Our tests all assume a \"default configuration\" unless\n        // specified otherwise.\n        for (k, _v) in env::vars() {\n            if k.starts_with(\"CARGO_\") {\n                self = self.env_remove(&k);\n            }\n        }\n        if env::var_os(\"RUSTUP_TOOLCHAIN\").is_some() {\n            // Override the PATH to avoid executing the rustup wrapper thousands\n            // of times. This makes the testsuite run substantially faster.\n            static RUSTC_DIR: OnceLock<PathBuf> = OnceLock::new();\n            let rustc_dir = RUSTC_DIR.get_or_init(|| {\n                match ProcessBuilder::new(\"rustup\")\n                    .args(&[\"which\", \"rustc\"])\n                    .exec_with_output()\n                {\n                    Ok(output) => {\n                        let s = std::str::from_utf8(&output.stdout).expect(\"utf8\").trim();\n                        let mut p = PathBuf::from(s);\n                        p.pop();\n                        p\n                    }\n                    Err(e) => {\n                        panic!(\"RUSTUP_TOOLCHAIN was set, but could not run rustup: {}\", e);\n                    }\n                }\n            });\n            let path = env::var_os(\"PATH\").unwrap_or_default();\n            let paths = env::split_paths(&path);\n            let new_path =\n                env::join_paths(std::iter::once(rustc_dir.clone()).chain(paths)).unwrap();\n            self = self.env(\"PATH\", new_path);\n        }\n\n        self = self\n            .current_dir(&paths::root())\n            .env(\"HOME\", paths::home())\n            .env(\"CARGO_HOME\", paths::cargo_home())\n            .env(\"__CARGO_TEST_ROOT\", paths::global_root())\n            // Force Cargo to think it's on the stable channel for all tests, this\n            // should hopefully not surprise us as we add cargo features over time and\n            // cargo rides the trains.\n            .env(\"__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS\", \"stable\")\n            // Keeps cargo within its sandbox.\n            .env(\"__CARGO_TEST_DISABLE_GLOBAL_KNOWN_HOST\", \"1\")\n            // Set retry sleep to 1 millisecond.\n            .env(\"__CARGO_TEST_FIXED_RETRY_SLEEP_MS\", \"1\")\n            // Setting this to a large number helps avoid problems with long\n            // paths getting trimmed in snapshot tests.\n            //\n            // When updating this value, keep in mind that the `CARGO_TARGET_DIR`\n            // that gets set when Cargo's tests get run in `rust-lang/rust` can\n            // easily cause path lengths to exceed 200 characters.\n            .env(\"__CARGO_TEST_TTY_WIDTH_DO_NOT_USE_THIS\", \"400\")\n            // Incremental generates a huge amount of data per test, which we\n            // don't particularly need. Tests that specifically need to check\n            // the incremental behavior should turn this back on.\n            .env(\"CARGO_INCREMENTAL\", \"0\")\n            // Don't read the system git config which is out of our control.\n            .env(\"GIT_CONFIG_NOSYSTEM\", \"1\")\n            .env_remove(\"__CARGO_DEFAULT_LIB_METADATA\")\n            .env_remove(\"ALL_PROXY\")\n            .env_remove(\"EMAIL\")\n            .env_remove(\"GIT_AUTHOR_EMAIL\")\n            .env_remove(\"GIT_AUTHOR_NAME\")\n            .env_remove(\"GIT_COMMITTER_EMAIL\")\n            .env_remove(\"GIT_COMMITTER_NAME\")\n            .env_remove(\"http_proxy\")\n            .env_remove(\"HTTPS_PROXY\")\n            .env_remove(\"https_proxy\")\n            .env_remove(\"MAKEFLAGS\")\n            .env_remove(\"MFLAGS\")\n            .env_remove(\"MSYSTEM\") // assume cmd.exe everywhere on windows\n            .env_remove(\"RUSTC\")\n            .env_remove(\"RUST_BACKTRACE\")\n            .env_remove(\"RUSTC_WORKSPACE_WRAPPER\")\n            .env_remove(\"RUSTC_WRAPPER\")\n            .env_remove(\"RUSTDOC\")\n            .env_remove(\"RUSTDOCFLAGS\")\n            .env_remove(\"RUSTFLAGS\")\n            .env_remove(\"SSH_AUTH_SOCK\") // ensure an outer agent is never contacted\n            .env_remove(\"USER\") // not set on some rust-lang docker images\n            .env_remove(\"XDG_CONFIG_HOME\") // see #2345\n            .env_remove(\"OUT_DIR\"); // see #13204\n        if cfg!(windows) {\n            self = self.env(\"USERPROFILE\", paths::home());\n        }\n        self\n    }\n\n    fn current_dir<S: AsRef<std::path::Path>>(self, path: S) -> Self;\n    fn env<S: AsRef<std::ffi::OsStr>>(self, key: &str, value: S) -> Self;\n    fn env_remove(self, key: &str) -> Self;\n}\n\nimpl TestEnvCommandExt for &mut ProcessBuilder {\n    fn current_dir<S: AsRef<std::path::Path>>(self, path: S) -> Self {\n        let path = path.as_ref();\n        self.cwd(path)\n    }\n    fn env<S: AsRef<std::ffi::OsStr>>(self, key: &str, value: S) -> Self {\n        self.env(key, value)\n    }\n    fn env_remove(self, key: &str) -> Self {\n        self.env_remove(key)\n    }\n}\n\nimpl TestEnvCommandExt for snapbox::cmd::Command {\n    fn current_dir<S: AsRef<std::path::Path>>(self, path: S) -> Self {\n        self.current_dir(path)\n    }\n    fn env<S: AsRef<std::ffi::OsStr>>(self, key: &str, value: S) -> Self {\n        self.env(key, value)\n    }\n    fn env_remove(self, key: &str) -> Self {\n        self.env_remove(key)\n    }\n}\n\n/// Add a list of arguments as a line\npub trait ArgLineCommandExt: Sized {\n    fn arg_line(mut self, s: &str) -> Self {\n        for mut arg in s.split_whitespace() {\n            if (arg.starts_with('\"') && arg.ends_with('\"'))\n                || (arg.starts_with('\\'') && arg.ends_with('\\''))\n            {\n                arg = &arg[1..(arg.len() - 1).max(1)];\n            } else if arg.contains(&['\"', '\\''][..]) {\n                panic!(\"shell-style argument parsing is not supported\")\n            }\n            self = self.arg(arg);\n        }\n        self\n    }\n\n    fn arg<S: AsRef<std::ffi::OsStr>>(self, s: S) -> Self;\n}\n\nimpl ArgLineCommandExt for &mut ProcessBuilder {\n    fn arg<S: AsRef<std::ffi::OsStr>>(self, s: S) -> Self {\n        self.arg(s)\n    }\n}\n\nimpl ArgLineCommandExt for &mut Execs {\n    fn arg<S: AsRef<std::ffi::OsStr>>(self, s: S) -> Self {\n        self.arg(s)\n    }\n}\n\nimpl ArgLineCommandExt for snapbox::cmd::Command {\n    fn arg<S: AsRef<std::ffi::OsStr>>(self, s: S) -> Self {\n        self.arg(s)\n    }\n}\n\n/// Run `git $arg_line`, see [`ProcessBuilder`]\npub fn git_process(arg_line: &str) -> ProcessBuilder {\n    let mut p = process(\"git\");\n    p.arg_line(arg_line);\n    p\n}\n\npub fn sleep_ms(ms: u64) {\n    ::std::thread::sleep(Duration::from_millis(ms));\n}\n\n/// Returns `true` if the local filesystem has low-resolution mtimes.\npub fn is_coarse_mtime() -> bool {\n    // If the filetime crate is being used to emulate HFS then\n    // return `true`, without looking at the actual hardware.\n    cfg!(emulate_second_only_system) ||\n    // This should actually be a test that `$CARGO_TARGET_DIR` is on an HFS\n    // filesystem, (or any filesystem with low-resolution mtimes). However,\n    // that's tricky to detect, so for now just deal with CI.\n    cfg!(target_os = \"macos\") && is_ci()\n}\n\n/// A way for to increase the cut off for all the time based test.\n///\n/// Some CI setups are much slower then the equipment used by Cargo itself.\n/// Architectures that do not have a modern processor, hardware emulation, etc.\npub fn slow_cpu_multiplier(main: u64) -> Duration {\n    static SLOW_CPU_MULTIPLIER: OnceLock<u64> = OnceLock::new();\n    let slow_cpu_multiplier = SLOW_CPU_MULTIPLIER.get_or_init(|| {\n        env::var(\"CARGO_TEST_SLOW_CPU_MULTIPLIER\")\n            .ok()\n            .and_then(|m| m.parse().ok())\n            .unwrap_or(1)\n    });\n    Duration::from_secs(slow_cpu_multiplier * main)\n}\n\n#[cfg(windows)]\npub fn symlink_supported() -> bool {\n    if is_ci() {\n        // We want to be absolutely sure this runs on CI.\n        return true;\n    }\n    let src = paths::root().join(\"symlink_src\");\n    fs::write(&src, \"\").unwrap();\n    let dst = paths::root().join(\"symlink_dst\");\n    let result = match os::windows::fs::symlink_file(&src, &dst) {\n        Ok(_) => {\n            fs::remove_file(&dst).unwrap();\n            true\n        }\n        Err(e) => {\n            eprintln!(\n                \"symlinks not supported: {:?}\\n\\\n                 Windows 10 users should enable developer mode.\",\n                e\n            );\n            false\n        }\n    };\n    fs::remove_file(&src).unwrap();\n    return result;\n}\n\n#[cfg(not(windows))]\npub fn symlink_supported() -> bool {\n    true\n}\n\n/// The error message for ENOENT.\npub fn no_such_file_err_msg() -> String {\n    std::io::Error::from_raw_os_error(2).to_string()\n}\n\n/// Helper to retry a function `n` times.\n///\n/// The function should return `Some` when it is ready.\n#[track_caller]\npub fn retry<F, R>(n: u32, mut f: F) -> R\nwhere\n    F: FnMut() -> Option<R>,\n{\n    let mut count = 0;\n    let start = std::time::Instant::now();\n    loop {\n        if let Some(r) = f() {\n            return r;\n        }\n        count += 1;\n        if count > n {\n            panic!(\n                \"test did not finish within {n} attempts ({:?} total)\",\n                start.elapsed()\n            );\n        }\n        sleep_ms(100);\n    }\n}\n\n#[test]\n#[should_panic(expected = \"test did not finish\")]\nfn retry_fails() {\n    retry(2, || None::<()>);\n}\n\n/// Helper that waits for a thread to finish, up to `n` tenths of a second.\n#[track_caller]\npub fn thread_wait_timeout<T>(n: u32, thread: JoinHandle<T>) -> T {\n    retry(n, || thread.is_finished().then_some(()));\n    thread.join().unwrap()\n}\n\n/// Helper that runs some function, and waits up to `n` tenths of a second for\n/// it to finish.\n#[track_caller]\npub fn threaded_timeout<F, R>(n: u32, f: F) -> R\nwhere\n    F: FnOnce() -> R + Send + 'static,\n    R: Send + 'static,\n{\n    let thread = std::thread::spawn(|| f());\n    thread_wait_timeout(n, thread)\n}\n\n// Helper for testing dep-info files in the fingerprint dir.\n#[track_caller]\npub fn assert_deps(project: &Project, fingerprint: &str, test_cb: impl Fn(&Path, &[(u8, &str)])) {\n    let mut files = project\n        .glob(fingerprint)\n        .map(|f| f.expect(\"unwrap glob result\"))\n        // Filter out `.json` entries.\n        .filter(|f| f.extension().is_none());\n    let info_path = files\n        .next()\n        .unwrap_or_else(|| panic!(\"expected 1 dep-info file at {}, found 0\", fingerprint));\n    assert!(files.next().is_none(), \"expected only 1 dep-info file\");\n    let dep_info = fs::read(&info_path).unwrap();\n    let dep_info = &mut &dep_info[..];\n\n    // Consume the magic marker and version. Here they don't really matter.\n    read_usize(dep_info);\n    read_u8(dep_info);\n    read_u8(dep_info);\n\n    let deps = (0..read_usize(dep_info))\n        .map(|_| {\n            let ty = read_u8(dep_info);\n            let path = std::str::from_utf8(read_bytes(dep_info)).unwrap();\n            let checksum_present = read_bool(dep_info);\n            if checksum_present {\n                // Read out the checksum info without using it\n                let _file_len = read_u64(dep_info);\n                let _checksum = read_bytes(dep_info);\n            }\n            (ty, path)\n        })\n        .collect::<Vec<_>>();\n    test_cb(&info_path, &deps);\n\n    fn read_usize(bytes: &mut &[u8]) -> usize {\n        let ret = &bytes[..4];\n        *bytes = &bytes[4..];\n\n        u32::from_le_bytes(ret.try_into().unwrap()) as usize\n    }\n\n    fn read_u8(bytes: &mut &[u8]) -> u8 {\n        let ret = bytes[0];\n        *bytes = &bytes[1..];\n        ret\n    }\n\n    fn read_bool(bytes: &mut &[u8]) -> bool {\n        read_u8(bytes) != 0\n    }\n\n    fn read_u64(bytes: &mut &[u8]) -> u64 {\n        let ret = &bytes[..8];\n        *bytes = &bytes[8..];\n\n        u64::from_le_bytes(ret.try_into().unwrap())\n    }\n\n    fn read_bytes<'a>(bytes: &mut &'a [u8]) -> &'a [u8] {\n        let n = read_usize(bytes);\n        let ret = &bytes[..n];\n        *bytes = &bytes[n..];\n        ret\n    }\n}\n\n#[track_caller]\npub fn assert_deps_contains(project: &Project, fingerprint: &str, expected: &[(u8, &str)]) {\n    assert_deps(project, fingerprint, |info_path, entries| {\n        for (e_kind, e_path) in expected {\n            let pattern = glob::Pattern::new(e_path).unwrap();\n            let count = entries\n                .iter()\n                .filter(|(kind, path)| kind == e_kind && pattern.matches(path))\n                .count();\n            if count != 1 {\n                panic!(\n                    \"Expected 1 match of {} {} in {:?}, got {}:\\n{:#?}\",\n                    e_kind, e_path, info_path, count, entries\n                );\n            }\n        }\n    })\n}\n\n#[track_caller]\npub fn assert_deterministic_mtime(path: impl AsRef<Path>) {\n    // Hardcoded value be removed once alexcrichton/tar-rs#420 is merged and released.\n    // See also rust-lang/cargo#16237\n    const DETERMINISTIC_TIMESTAMP: u64 = 1153704088;\n\n    let path = path.as_ref();\n    let mtime = path.metadata().unwrap().modified().unwrap();\n    let timestamp = mtime\n        .duration_since(std::time::UNIX_EPOCH)\n        .unwrap()\n        .as_secs();\n    assert_eq!(\n        timestamp, DETERMINISTIC_TIMESTAMP,\n        \"expected deterministic mtime for {path:?}, got {timestamp}\"\n    );\n}\n"
  },
  {
    "path": "crates/cargo-test-support/src/paths.rs",
    "content": "//! Access common paths and manipulate the filesystem\n\nuse filetime::FileTime;\nuse itertools::Itertools;\nuse walkdir::WalkDir;\n\nuse std::cell::RefCell;\nuse std::fs;\nuse std::io::{self, ErrorKind};\nuse std::path::{Path, PathBuf};\nuse std::process::Command;\nuse std::sync::Mutex;\nuse std::sync::OnceLock;\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\nuse crate::compare::assert_e2e;\nuse crate::compare::match_contains;\n\nstatic CARGO_INTEGRATION_TEST_DIR: &str = \"cit\";\n\nstatic GLOBAL_ROOT: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new();\n\nfn set_global_root(tmp_dir: &'static str) {\n    let mut lock = GLOBAL_ROOT\n        .get_or_init(|| Default::default())\n        .lock()\n        .unwrap();\n    if lock.is_none() {\n        let mut root = PathBuf::from(tmp_dir);\n        root.push(CARGO_INTEGRATION_TEST_DIR);\n        *lock = Some(root);\n    }\n}\n\n/// Path to the parent directory of all test [`root`]s\n///\n/// ex: `$CARGO_TARGET_TMPDIR/cit`\npub fn global_root() -> PathBuf {\n    let lock = GLOBAL_ROOT\n        .get_or_init(|| Default::default())\n        .lock()\n        .unwrap();\n    match lock.as_ref() {\n        Some(p) => p.clone(),\n        None => unreachable!(\"GLOBAL_ROOT not set yet\"),\n    }\n}\n\n// We need to give each test a unique id. The test name serve this\n// purpose. We are able to get the test name by having the `cargo-test-macro`\n// crate automatically insert an init function for each test that sets the\n// test name in a thread local variable.\nthread_local! {\n    static TEST_ID: RefCell<Option<usize>> = const { RefCell::new(None) };\n    static TEST_DIR: RefCell<Option<PathBuf>> = const { RefCell::new(None) };\n}\n\n/// See [`init_root`]\npub struct TestIdGuard {\n    _private: (),\n}\n\n/// For test harnesses like [`crate::cargo_test`]\npub fn init_root(tmp_dir: &'static str, test_dir: PathBuf) -> TestIdGuard {\n    static NEXT_ID: AtomicUsize = AtomicUsize::new(0);\n    let id = NEXT_ID.fetch_add(1, Ordering::SeqCst);\n    TEST_ID.with(|n| *n.borrow_mut() = Some(id));\n    if cfg!(windows) {\n        // Due to path-length limits, Windows doesn't use the full test name.\n        TEST_DIR.with(|n| *n.borrow_mut() = Some(PathBuf::from(format!(\"t{id}\"))));\n    } else {\n        TEST_DIR.with(|n| *n.borrow_mut() = Some(test_dir));\n    }\n    let guard = TestIdGuard { _private: () };\n    set_global_root(tmp_dir);\n    let r = root();\n    r.rm_rf();\n    r.mkdir_p();\n    #[cfg(not(windows))]\n    if id == 0 {\n        // Create a symlink from `t0` to the first test to make it easier to\n        // find and reuse when running a single test.\n        use crate::SymlinkBuilder;\n        let mut alias = global_root();\n        alias.push(\"t0\");\n        alias.rm_rf();\n        SymlinkBuilder::new_dir(r, alias).mk();\n    }\n    guard\n}\n\nimpl Drop for TestIdGuard {\n    fn drop(&mut self) {\n        TEST_ID.with(|n| *n.borrow_mut() = None);\n        TEST_DIR.with(|n| *n.borrow_mut() = None);\n    }\n}\n\n/// Path to the test's filesystem scratchpad\n///\n/// ex: `$CARGO_TARGET_TMPDIR/cit/<integration test>/<module>/<fn name>/`\n/// or `$CARGO_TARGET_TMPDIR/cit/t0` on Windows\npub fn root() -> PathBuf {\n    let test_dir = TEST_DIR.with(|n| {\n        n.borrow().clone().expect(\n            \"Tests must use the `#[cargo_test]` attribute in \\\n             order to be able to use the crate root.\",\n        )\n    });\n    let mut root = global_root();\n    root.push(&test_dir);\n    root\n}\n/// Path to the current test's `$HOME`\n///\n/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/home`\npub fn home() -> PathBuf {\n    let mut path = root();\n    path.push(\"home\");\n    path.mkdir_p();\n    path\n}\n\n/// Path to the current test's `$CARGO_HOME`\n///\n/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/home/.cargo`\npub fn cargo_home() -> PathBuf {\n    home().join(\".cargo\")\n}\n\n/// Path to the current test's `$CARGO_LOG`\n///\n/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/home/.cargo/log`\npub fn log_dir() -> PathBuf {\n    cargo_home().join(\"log\")\n}\n\n/// Path to the current test's `$CARGO_LOG` file\n///\n/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/home/.cargo/log/<id>.jsonl`\n///\n/// This also asserts the number of log files is exactly the same as `idx + 1`.\npub fn log_file(idx: usize) -> PathBuf {\n    let log_dir = log_dir();\n\n    let entries = std::fs::read_dir(&log_dir).unwrap();\n    let mut log_files: Vec<_> = entries\n        .filter_map(Result::ok)\n        .filter(|e| e.path().extension().and_then(|s| s.to_str()) == Some(\"jsonl\"))\n        .collect();\n\n    // Sort them to get chronological order\n    log_files.sort_unstable_by(|a, b| a.file_name().to_str().cmp(&b.file_name().to_str()));\n\n    assert_eq!(\n        idx + 1,\n        log_files.len(),\n        \"unexpected number of log files: {}, expected {}\",\n        log_files.len(),\n        idx + 1\n    );\n\n    log_files[idx].path()\n}\n\n/// Common path and file operations\npub trait CargoPathExt {\n    fn to_url(&self) -> url::Url;\n\n    fn rm_rf(&self);\n    fn mkdir_p(&self);\n\n    /// Returns a list of all files and directories underneath the given\n    /// directory, recursively, including the starting path.\n    fn ls_r(&self) -> Vec<PathBuf>;\n\n    fn move_into_the_past(&self) {\n        self.move_in_time(|sec, nsec| (sec - 3600, nsec))\n    }\n\n    fn move_into_the_future(&self) {\n        self.move_in_time(|sec, nsec| (sec + 3600, nsec))\n    }\n\n    fn move_in_time<F>(&self, travel_amount: F)\n    where\n        F: Fn(i64, u32) -> (i64, u32);\n\n    fn assert_build_dir_layout(&self, expected: impl snapbox::IntoData);\n\n    fn assert_dir_layout(&self, expected: impl snapbox::IntoData, ignored_path_patterns: &[String]);\n}\n\nimpl CargoPathExt for Path {\n    fn to_url(&self) -> url::Url {\n        url::Url::from_file_path(self).ok().unwrap()\n    }\n\n    fn rm_rf(&self) {\n        let meta = match self.symlink_metadata() {\n            Ok(meta) => meta,\n            Err(e) => {\n                if e.kind() == ErrorKind::NotFound {\n                    return;\n                }\n                panic!(\"failed to remove {:?}, could not read: {:?}\", self, e);\n            }\n        };\n        // There is a race condition between fetching the metadata and\n        // actually performing the removal, but we don't care all that much\n        // for our tests.\n        if meta.is_dir() {\n            if let Err(e) = fs::remove_dir_all(self) {\n                panic!(\"failed to remove {:?}: {:?}\", self, e)\n            }\n        } else if let Err(e) = fs::remove_file(self) {\n            panic!(\"failed to remove {:?}: {:?}\", self, e)\n        }\n    }\n\n    fn mkdir_p(&self) {\n        fs::create_dir_all(self)\n            .unwrap_or_else(|e| panic!(\"failed to mkdir_p {}: {}\", self.display(), e))\n    }\n\n    fn ls_r(&self) -> Vec<PathBuf> {\n        walkdir::WalkDir::new(self)\n            .sort_by_file_name()\n            .into_iter()\n            .filter_map(|e| e.map(|e| e.path().to_owned()).ok())\n            .collect()\n    }\n\n    fn move_in_time<F>(&self, travel_amount: F)\n    where\n        F: Fn(i64, u32) -> (i64, u32),\n    {\n        if self.is_file() {\n            time_travel(self, &travel_amount);\n        } else {\n            recurse(self, &self.join(\"target\"), &travel_amount);\n        }\n\n        fn recurse<F>(p: &Path, bad: &Path, travel_amount: &F)\n        where\n            F: Fn(i64, u32) -> (i64, u32),\n        {\n            if p.is_file() {\n                time_travel(p, travel_amount)\n            } else if !p.starts_with(bad) {\n                for f in t!(fs::read_dir(p)) {\n                    let f = t!(f).path();\n                    recurse(&f, bad, travel_amount);\n                }\n            }\n        }\n\n        fn time_travel<F>(path: &Path, travel_amount: &F)\n        where\n            F: Fn(i64, u32) -> (i64, u32),\n        {\n            let stat = t!(path.symlink_metadata());\n\n            let mtime = FileTime::from_last_modification_time(&stat);\n\n            let (sec, nsec) = travel_amount(mtime.unix_seconds(), mtime.nanoseconds());\n            let newtime = FileTime::from_unix_time(sec, nsec);\n\n            // Sadly change_file_times has a failure mode where a readonly file\n            // cannot have its times changed on windows.\n            do_op(path, \"set file times\", |path| {\n                filetime::set_file_times(path, newtime, newtime)\n            });\n        }\n    }\n\n    #[track_caller]\n    fn assert_build_dir_layout(&self, expected: impl snapbox::IntoData) {\n        // We call `unordered()` here to because the build-dir has some scenarios that make\n        // consistent ordering not possible.\n        // Notably:\n        // 1. Binaries with `.exe` on Windows causing the ordering to change with the dep-info `.d`\n        //    file.\n        // 2. Directories with hashes are often reordered differently by platform.\n        self.assert_dir_layout(expected.unordered(), &build_dir_ignored_path_patterns());\n    }\n\n    #[track_caller]\n    fn assert_dir_layout(\n        &self,\n        expected: impl snapbox::IntoData,\n        ignored_path_patterns: &[String],\n    ) {\n        let assert = assert_e2e();\n        let actual = WalkDir::new(self)\n            .sort_by_file_name()\n            .into_iter()\n            .filter_map(|e| e.ok())\n            .filter(|e| e.file_type().is_file())\n            .map(|e| e.path().to_string_lossy().into_owned())\n            .filter(|file| {\n                for ignored in ignored_path_patterns {\n                    if match_contains(&ignored, file, &assert.redactions()).is_ok() {\n                        return false;\n                    }\n                }\n                return true;\n            })\n            .join(\"\\n\");\n\n        assert.eq(format!(\"{actual}\\n\"), expected);\n    }\n}\n\nimpl CargoPathExt for PathBuf {\n    fn to_url(&self) -> url::Url {\n        self.as_path().to_url()\n    }\n\n    fn rm_rf(&self) {\n        self.as_path().rm_rf()\n    }\n    fn mkdir_p(&self) {\n        self.as_path().mkdir_p()\n    }\n\n    fn ls_r(&self) -> Vec<PathBuf> {\n        self.as_path().ls_r()\n    }\n\n    fn move_in_time<F>(&self, travel_amount: F)\n    where\n        F: Fn(i64, u32) -> (i64, u32),\n    {\n        self.as_path().move_in_time(travel_amount)\n    }\n\n    #[track_caller]\n    fn assert_build_dir_layout(&self, expected: impl snapbox::IntoData) {\n        self.as_path().assert_build_dir_layout(expected);\n    }\n\n    #[track_caller]\n    fn assert_dir_layout(\n        &self,\n        expected: impl snapbox::IntoData,\n        ignored_path_patterns: &[String],\n    ) {\n        self.as_path()\n            .assert_dir_layout(expected, ignored_path_patterns);\n    }\n}\n\nfn do_op<F>(path: &Path, desc: &str, mut f: F)\nwhere\n    F: FnMut(&Path) -> io::Result<()>,\n{\n    match f(path) {\n        Ok(()) => {}\n        Err(ref e) if e.kind() == ErrorKind::PermissionDenied => {\n            let mut p = t!(path.metadata()).permissions();\n            p.set_readonly(false);\n            t!(fs::set_permissions(path, p));\n\n            // Unix also requires the parent to not be readonly for example when\n            // removing files\n            let parent = path.parent().unwrap();\n            let mut p = t!(parent.metadata()).permissions();\n            p.set_readonly(false);\n            t!(fs::set_permissions(parent, p));\n\n            f(path).unwrap_or_else(|e| {\n                panic!(\"failed to {} {}: {}\", desc, path.display(), e);\n            })\n        }\n        Err(e) => {\n            panic!(\"failed to {} {}: {}\", desc, path.display(), e);\n        }\n    }\n}\n\n/// The paths to ignore when [`CargoPathExt::assert_build_dir_layout`] is called\nfn build_dir_ignored_path_patterns() -> Vec<String> {\n    vec![\n        // Ignore MacOS debug symbols as there are many files/directories that would clutter up\n        // tests few not a lot of benefit.\n        \"[..].dSYM/[..]\",\n        // Ignore Windows debug symbols files (.pdb)\n        \"[..].pdb\",\n    ]\n    .into_iter()\n    .map(ToString::to_string)\n    .collect()\n}\n\n/// Get the filename for a library.\n///\n/// `kind` should be one of:\n/// - `lib`\n/// - `rlib`\n/// - `staticlib`\n/// - `dylib`\n/// - `proc-macro`\n///\n/// # Examples\n/// ```\n/// # use cargo_test_support::paths::get_lib_filename;\n/// get_lib_filename(\"foo\", \"dylib\");\n/// ```\n/// would return:\n/// - macOS: `\"libfoo.dylib\"`\n/// - Windows: `\"foo.dll\"`\n/// - Unix: `\"libfoo.so\"`\npub fn get_lib_filename(name: &str, kind: &str) -> String {\n    let prefix = get_lib_prefix(kind);\n    let extension = get_lib_extension(kind);\n    format!(\"{}{}.{}\", prefix, name, extension)\n}\n\n/// See [`get_lib_filename`] for more details\npub fn get_lib_prefix(kind: &str) -> &str {\n    match kind {\n        \"lib\" | \"rlib\" => \"lib\",\n        \"staticlib\" | \"dylib\" | \"proc-macro\" => {\n            if cfg!(windows) {\n                \"\"\n            } else {\n                \"lib\"\n            }\n        }\n        _ => unreachable!(),\n    }\n}\n\n/// See [`get_lib_filename`] for more details\npub fn get_lib_extension(kind: &str) -> &str {\n    match kind {\n        \"lib\" | \"rlib\" => \"rlib\",\n        \"staticlib\" => {\n            if cfg!(windows) {\n                \"lib\"\n            } else {\n                \"a\"\n            }\n        }\n        \"dylib\" | \"proc-macro\" => {\n            if cfg!(windows) {\n                \"dll\"\n            } else if cfg!(target_os = \"macos\") {\n                \"dylib\"\n            } else {\n                \"so\"\n            }\n        }\n        _ => unreachable!(),\n    }\n}\n\n/// Path to `rustc`s sysroot\npub fn sysroot() -> String {\n    let output = Command::new(\"rustc\")\n        .arg(\"--print=sysroot\")\n        .output()\n        .expect(\"rustc to run\");\n    assert!(output.status.success());\n    let sysroot = String::from_utf8(output.stdout).unwrap();\n    sysroot.trim().to_string()\n}\n\n/// Returns true if names such as aux.* are allowed.\n///\n/// Traditionally, Windows did not allow a set of file names (see `is_windows_reserved`\n/// for a list). More recent versions of Windows have relaxed this restriction. This test\n/// determines whether we are running in a mode that allows Windows reserved names.\n#[cfg(windows)]\npub fn windows_reserved_names_are_allowed() -> bool {\n    use std::ffi::OsStr;\n    use std::os::windows::ffi::OsStrExt;\n    use std::ptr;\n    use windows_sys::Win32::Storage::FileSystem::GetFullPathNameW;\n\n    let test_file_name: Vec<_> = OsStr::new(\"aux.rs\").encode_wide().chain([0]).collect();\n\n    let buffer_length =\n        unsafe { GetFullPathNameW(test_file_name.as_ptr(), 0, ptr::null_mut(), ptr::null_mut()) };\n\n    if buffer_length == 0 {\n        // This means the call failed, so we'll conservatively assume reserved names are not allowed.\n        return false;\n    }\n\n    let mut buffer = vec![0u16; buffer_length as usize];\n\n    let result = unsafe {\n        GetFullPathNameW(\n            test_file_name.as_ptr(),\n            buffer_length,\n            buffer.as_mut_ptr(),\n            ptr::null_mut(),\n        )\n    };\n\n    if result == 0 {\n        // Once again, conservatively assume reserved names are not allowed if the\n        // GetFullPathNameW call failed.\n        return false;\n    }\n\n    // Under the old rules, a file name like aux.rs would get converted into \\\\.\\aux, so\n    // we detect this case by checking if the string starts with \\\\.\\\n    //\n    // Otherwise, the filename will be something like C:\\Users\\Foo\\Documents\\aux.rs\n    let prefix: Vec<_> = OsStr::new(\"\\\\\\\\.\\\\\").encode_wide().collect();\n    if buffer.starts_with(&prefix) {\n        false\n    } else {\n        true\n    }\n}\n\n/// This takes the test location (std::file!() should be passed) and the test name\n/// and outputs the location the test should be places in, inside of `target/tmp/cit`\n///\n/// `path: tests/testsuite/workspaces.rs`\n/// `name: `workspace_in_git\n/// `output: \"testsuite/workspaces/workspace_in_git`\npub fn test_dir(path: &str, name: &str) -> std::path::PathBuf {\n    let test_dir: std::path::PathBuf = std::path::PathBuf::from(path)\n        .components()\n        // Trim .rs from any files\n        .map(|c| c.as_os_str().to_str().unwrap().trim_end_matches(\".rs\"))\n        // We only want to take once we have reached `tests` or `src`. This helps when in a\n        // workspace: `workspace/more/src/...` would result in `src/...`\n        .skip_while(|c| c != &\"tests\" && c != &\"src\")\n        // We want to skip \"tests\" since it is taken in `skip_while`.\n        // \"src\" is fine since you could have test in \"src\" named the same as one in \"tests\"\n        // Skip \"mod\" since `snapbox` tests have a folder per test not a file and the files\n        // are named \"mod.rs\"\n        .filter(|c| c != &\"tests\" && c != &\"mod\")\n        .collect();\n    test_dir.join(name)\n}\n"
  },
  {
    "path": "crates/cargo-test-support/src/publish.rs",
    "content": "//! Helpers for testing `cargo package` / `cargo publish`\n//!\n//! # Example\n//!\n//! ```no_run\n//! # use cargo_test_support::registry::RegistryBuilder;\n//! # use cargo_test_support::publish::validate_upload;\n//! # use cargo_test_support::project;\n//! validate_upload(\n//!     r#\"\n//!     {\n//!       \"authors\": [],\n//!       \"badges\": {},\n//!       \"categories\": [],\n//!       \"deps\": [],\n//!       \"description\": \"foo\",\n//!       \"documentation\": null,\n//!       \"features\": {},\n//!       \"homepage\": null,\n//!       \"keywords\": [],\n//!       \"license\": \"MIT\",\n//!       \"license_file\": null,\n//!       \"links\": null,\n//!       \"name\": \"foo\",\n//!       \"readme\": null,\n//!       \"readme_file\": null,\n//!       \"repository\": null,\n//!       \"rust_version\": null,\n//!       \"vers\": \"0.0.1\"\n//!       }\n//!     \"#,\n//!     \"foo-0.0.1.crate\",\n//!     &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n//! );\n//! ```\n\nuse crate::compare::InMemoryDir;\nuse crate::registry::{self, FeatureMap, alt_api_path};\nuse flate2::read::GzDecoder;\nuse snapbox::prelude::*;\nuse std::collections::HashSet;\nuse std::fs;\nuse std::fs::File;\nuse std::io::{self, SeekFrom, prelude::*};\nuse std::path::Path;\nuse tar::Archive;\n\nfn read_le_u32<R>(mut reader: R) -> io::Result<u32>\nwhere\n    R: Read,\n{\n    let mut buf = [0; 4];\n    reader.read_exact(&mut buf)?;\n    Ok(u32::from_le_bytes(buf))\n}\n\n/// Check the `cargo publish` API call\n#[track_caller]\npub fn validate_upload(expected_json: &str, expected_crate_name: &str, expected_files: &[&str]) {\n    let new_path = registry::api_path().join(\"api/v1/crates/new\");\n    _validate_upload(\n        &new_path,\n        expected_json,\n        expected_crate_name,\n        expected_files,\n        (),\n    );\n}\n\n/// Check the `cargo publish` API call, with file contents\n#[track_caller]\npub fn validate_upload_with_contents(\n    expected_json: &str,\n    expected_crate_name: &str,\n    expected_files: &[&str],\n    expected_contents: impl Into<InMemoryDir>,\n) {\n    let new_path = registry::api_path().join(\"api/v1/crates/new\");\n    _validate_upload(\n        &new_path,\n        expected_json,\n        expected_crate_name,\n        expected_files,\n        expected_contents,\n    );\n}\n\n/// Check the `cargo publish` API call to the alternative test registry\n#[track_caller]\npub fn validate_alt_upload(\n    expected_json: &str,\n    expected_crate_name: &str,\n    expected_files: &[&str],\n) {\n    let new_path = alt_api_path().join(\"api/v1/crates/new\");\n    _validate_upload(\n        &new_path,\n        expected_json,\n        expected_crate_name,\n        expected_files,\n        (),\n    );\n}\n\n#[track_caller]\nfn _validate_upload(\n    new_path: &Path,\n    expected_json: &str,\n    expected_crate_name: &str,\n    expected_files: &[&str],\n    expected_contents: impl Into<InMemoryDir>,\n) {\n    let (actual_json, krate_bytes) = read_new_post(new_path);\n\n    snapbox::assert_data_eq!(actual_json, expected_json.is_json());\n\n    // Verify the tarball.\n    validate_crate_contents(\n        &krate_bytes[..],\n        expected_crate_name,\n        expected_files,\n        expected_contents,\n    );\n}\n\n#[track_caller]\nfn read_new_post(new_path: &Path) -> (Vec<u8>, Vec<u8>) {\n    let mut f = File::open(new_path).unwrap();\n\n    // 32-bit little-endian integer of length of JSON data.\n    let json_sz = read_le_u32(&mut f).expect(\"read json length\");\n    let mut json_bytes = vec![0; json_sz as usize];\n    f.read_exact(&mut json_bytes).expect(\"read JSON data\");\n\n    // 32-bit little-endian integer of length of crate file.\n    let crate_sz = read_le_u32(&mut f).expect(\"read crate length\");\n    let mut krate_bytes = vec![0; crate_sz as usize];\n    f.read_exact(&mut krate_bytes).expect(\"read crate data\");\n\n    // Check at end.\n    let current = f.seek(SeekFrom::Current(0)).unwrap();\n    assert_eq!(f.seek(SeekFrom::End(0)).unwrap(), current);\n\n    (json_bytes, krate_bytes)\n}\n\n/// Checks the contents of a `.crate` file.\n///\n/// - `expected_crate_name` should be something like `foo-0.0.1.crate`.\n/// - `expected_files` should be a complete list of files in the crate\n///   (relative to `expected_crate_name`).\n/// - `expected_contents` should be a list of `(file_name, contents)` tuples\n///   to validate the contents of the given file. Only the listed files will\n///   be checked (others will be ignored).\n#[track_caller]\npub fn validate_crate_contents(\n    reader: impl Read,\n    expected_crate_name: &str,\n    expected_files: &[&str],\n    expected_contents: impl Into<InMemoryDir>,\n) {\n    let expected_contents = expected_contents.into();\n    validate_crate_contents_(\n        reader,\n        expected_crate_name,\n        expected_files,\n        expected_contents,\n    )\n}\n\n#[track_caller]\nfn validate_crate_contents_(\n    reader: impl Read,\n    expected_crate_name: &str,\n    expected_files: &[&str],\n    expected_contents: InMemoryDir,\n) {\n    let mut rdr = GzDecoder::new(reader);\n    snapbox::assert_data_eq!(rdr.header().unwrap().filename().unwrap(), {\n        let expected: snapbox::Data = expected_crate_name.into();\n        expected.raw()\n    });\n\n    let mut contents = Vec::new();\n    rdr.read_to_end(&mut contents).unwrap();\n    let mut ar = Archive::new(&contents[..]);\n    let base_crate_name = Path::new(\n        expected_crate_name\n            .strip_suffix(\".crate\")\n            .expect(\"must end with .crate\"),\n    );\n    let actual_contents: InMemoryDir = ar\n        .entries()\n        .unwrap()\n        .map(|entry| {\n            let mut entry = entry.unwrap();\n            let name = entry\n                .path()\n                .unwrap()\n                .strip_prefix(base_crate_name)\n                .unwrap()\n                .to_owned();\n            let mut contents = String::new();\n            entry.read_to_string(&mut contents).unwrap();\n            (name, contents)\n        })\n        .collect();\n    let actual_files: HashSet<&Path> = actual_contents.paths().collect();\n    let expected_files: HashSet<&Path> =\n        expected_files.iter().map(|name| Path::new(name)).collect();\n    let missing: Vec<&&Path> = expected_files.difference(&actual_files).collect();\n    let extra: Vec<&&Path> = actual_files.difference(&expected_files).collect();\n    if !missing.is_empty() || !extra.is_empty() {\n        panic!(\n            \"uploaded archive does not match.\\nMissing: {:?}\\nExtra: {:?}\\n\",\n            missing, extra\n        );\n    }\n    actual_contents.assert_contains(&expected_contents);\n}\n\npub(crate) fn create_index_line(\n    name: serde_json::Value,\n    vers: &str,\n    deps: Vec<serde_json::Value>,\n    cksum: &str,\n    features: crate::registry::FeatureMap,\n    yanked: bool,\n    links: Option<String>,\n    rust_version: Option<&str>,\n    pubtime: Option<&str>,\n    v: Option<u32>,\n) -> String {\n    // This emulates what crates.io does to retain backwards compatibility.\n    let (features, features2) = split_index_features(features.clone());\n    let mut json = serde_json::json!({\n        \"name\": name,\n        \"vers\": vers,\n        \"deps\": deps,\n        \"cksum\": cksum,\n        \"features\": features,\n        \"yanked\": yanked,\n        \"links\": links,\n    });\n    if let Some(f2) = &features2 {\n        json[\"features2\"] = serde_json::json!(f2);\n        json[\"v\"] = serde_json::json!(2);\n    }\n    if let Some(v) = v {\n        json[\"v\"] = serde_json::json!(v);\n    }\n    if let Some(rust_version) = rust_version {\n        json[\"rust_version\"] = serde_json::json!(rust_version);\n    }\n    if let Some(pubtime) = pubtime {\n        json[\"pubtime\"] = serde_json::json!(pubtime);\n    }\n\n    json.to_string()\n}\n\npub(crate) fn write_to_index(registry_path: &Path, name: &str, line: String, local: bool) {\n    let file = cargo_util::registry::make_dep_path(name, false);\n\n    // Write file/line in the index.\n    let dst = if local {\n        registry_path.join(\"index\").join(&file)\n    } else {\n        registry_path.join(&file)\n    };\n    let prev = fs::read_to_string(&dst).unwrap_or_default();\n    t!(fs::create_dir_all(dst.parent().unwrap()));\n    t!(fs::write(&dst, prev + &line[..] + \"\\n\"));\n\n    // Add the new file to the index.\n    if !local {\n        let repo = t!(git2::Repository::open(&registry_path));\n        let mut index = t!(repo.index());\n        t!(index.add_path(Path::new(&file)));\n        t!(index.write());\n        let id = t!(index.write_tree());\n\n        // Commit this change.\n        let tree = t!(repo.find_tree(id));\n        let sig = t!(repo.signature());\n        let parent = t!(repo.refname_to_id(\"refs/heads/master\"));\n        let parent = t!(repo.find_commit(parent));\n        t!(repo.commit(\n            Some(\"HEAD\"),\n            &sig,\n            &sig,\n            \"Another commit\",\n            &tree,\n            &[&parent]\n        ));\n    }\n}\n\nfn split_index_features(mut features: FeatureMap) -> (FeatureMap, Option<FeatureMap>) {\n    let mut features2 = FeatureMap::new();\n    for (feat, values) in features.iter_mut() {\n        if values\n            .iter()\n            .any(|value| value.starts_with(\"dep:\") || value.contains(\"?/\"))\n        {\n            let new_values = std::mem::take(values);\n            features2.insert(feat.clone(), new_values);\n        }\n    }\n    if features2.is_empty() {\n        (features, None)\n    } else {\n        (features, Some(features2))\n    }\n}\n"
  },
  {
    "path": "crates/cargo-test-support/src/registry.rs",
    "content": "//! Interact with the [`TestRegistry`]\n//!\n//! # Example\n//!\n//! ```no_run\n//! use cargo_test_support::registry::Package;\n//! use cargo_test_support::project;\n//! use cargo_test_support::str;\n//!\n//! // Publish package \"a\" depending on \"b\".\n//! Package::new(\"a\", \"1.0.0\")\n//!     .dep(\"b\", \"1.0.0\")\n//!     .file(\"src/lib.rs\", r#\"\n//!         extern crate b;\n//!         pub fn f() -> i32 { b::f() * 2 }\n//!     \"#)\n//!     .publish();\n//!\n//! // Publish package \"b\".\n//! Package::new(\"b\", \"1.0.0\")\n//!     .file(\"src/lib.rs\", r#\"\n//!         pub fn f() -> i32 { 12 }\n//!     \"#)\n//!     .publish();\n//!\n//! // Create a project that uses package \"a\".\n//! let p = project()\n//!     .file(\"Cargo.toml\", r#\"\n//!         [package]\n//!         name = \"foo\"\n//!         version = \"0.0.1\"\n//!\n//!         [dependencies]\n//!         a = \"1.0\"\n//!     \"#)\n//!     .file(\"src/main.rs\", r#\"\n//!         extern crate a;\n//!         fn main() { println!(\"{}\", a::f()); }\n//!     \"#)\n//!     .build();\n//!\n//! // p.cargo(\"run\").with_stdout_data(str![\"24\"]).run();\n//! ```\n\nuse crate::git::repo;\nuse crate::paths;\nuse crate::publish::{create_index_line, write_to_index};\nuse cargo_util::Sha256;\nuse cargo_util::paths::append;\nuse flate2::Compression;\nuse flate2::write::GzEncoder;\nuse pasetors::keys::{AsymmetricPublicKey, AsymmetricSecretKey};\nuse pasetors::paserk::FormatAsPaserk;\nuse pasetors::token::UntrustedToken;\nuse std::collections::{BTreeMap, HashMap};\nuse std::fmt;\nuse std::fs::{self, File};\nuse std::io::{BufRead, BufReader, Read, Write};\nuse std::net::{SocketAddr, TcpListener, TcpStream};\nuse std::path::{Path, PathBuf};\nuse std::thread::{self, JoinHandle};\nuse tar::{Builder, Header};\nuse time::format_description::well_known::Rfc3339;\nuse time::{Duration, OffsetDateTime};\nuse url::Url;\n\n/// Path to the local index for pseudo-crates.io.\n///\n/// This is a Git repo\n/// initialized with a `config.json` file pointing to `dl_path` for downloads\n/// and `api_path` for uploads.\n///\n/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/registry`\npub fn registry_path() -> PathBuf {\n    generate_path(\"registry\")\n}\n\n/// Path to the local web API uploads\n///\n/// Cargo will place the contents of a web API\n/// request here. For example, `api/v1/crates/new` is the result of publishing a crate.\n///\n/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/api`\npub fn api_path() -> PathBuf {\n    generate_path(\"api\")\n}\n\n/// Path to download `.crate` files using the web API endpoint.\n///\n/// Crates\n/// should be organized as `{name}/{version}/download` to match the web API\n/// endpoint. This is rarely used and must be manually set up.\n///\n/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/dl`\npub fn dl_path() -> PathBuf {\n    generate_path(\"dl\")\n}\n\n/// Path to the alternative-registry version of [`registry_path`]\n///\n/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/alternative-registry`\npub fn alt_registry_path() -> PathBuf {\n    generate_path(\"alternative-registry\")\n}\n\n/// URL to the alternative-registry version of `registry_url`\nfn alt_registry_url() -> Url {\n    generate_url(\"alternative-registry\")\n}\n\n/// Path to the alternative-registry version of [`dl_path`]\n///\n/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/alternative-dl`\npub fn alt_dl_path() -> PathBuf {\n    generate_path(\"alternative-dl\")\n}\n\n/// Path to the alternative-registry version of [`api_path`]\n///\n/// ex: `$CARGO_TARGET_TMPDIR/cit/t0/alternative-api`\npub fn alt_api_path() -> PathBuf {\n    generate_path(\"alternative-api\")\n}\n\nfn generate_path(name: &str) -> PathBuf {\n    paths::root().join(name)\n}\nfn generate_url(name: &str) -> Url {\n    Url::from_file_path(generate_path(name)).ok().unwrap()\n}\n\n/// Auth-token for publishing, see [`RegistryBuilder::token`]\n#[derive(Clone)]\npub enum Token {\n    Plaintext(String),\n    Keys(String, Option<String>),\n}\n\nimpl Token {\n    /// This is a valid PASETO secret key.\n    ///\n    /// This one is already publicly available as part of the text of the RFC so is safe to use for tests.\n    pub fn rfc_key() -> Token {\n        Token::Keys(\n            \"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\"\n                .to_string(),\n            Some(\"sub\".to_string()),\n        )\n    }\n}\n\ntype RequestCallback = Box<dyn Send + Fn(&Request, &HttpServer) -> Response>;\n\n/// Prepare a local [`TestRegistry`] fixture\n///\n/// See also [`init`] and [`alt_init`]\npub struct RegistryBuilder {\n    /// If set, configures an alternate registry with the given name.\n    alternative: Option<String>,\n    /// The authorization token for the registry.\n    token: Option<Token>,\n    /// If set, the registry requires authorization for all operations.\n    auth_required: bool,\n    /// If set, serves the index over http.\n    http_index: bool,\n    /// If set, serves the API over http.\n    http_api: bool,\n    /// If set, config.json includes 'api'\n    api: bool,\n    /// Write the token in the configuration.\n    configure_token: bool,\n    /// Write the registry in configuration.\n    configure_registry: bool,\n    /// API responders.\n    custom_responders: HashMap<String, RequestCallback>,\n    /// Handler for 404 responses.\n    not_found_handler: RequestCallback,\n    /// If nonzero, the git index update to be delayed by the given number of seconds.\n    delayed_index_update: usize,\n    /// Credential provider in configuration\n    credential_provider: Option<String>,\n}\n\n/// A local registry fixture\n///\n/// Most tests won't need to call this directly but instead interact with [`Package`]\npub struct TestRegistry {\n    server: Option<HttpServerHandle>,\n    index_url: Url,\n    path: PathBuf,\n    api_url: Url,\n    dl_url: Url,\n    token: Token,\n}\n\nimpl TestRegistry {\n    pub fn index_url(&self) -> &Url {\n        &self.index_url\n    }\n\n    pub fn api_url(&self) -> &Url {\n        &self.api_url\n    }\n\n    pub fn token(&self) -> &str {\n        match &self.token {\n            Token::Plaintext(s) => s,\n            Token::Keys(_, _) => panic!(\"registry was not configured with a plaintext token\"),\n        }\n    }\n\n    pub fn key(&self) -> &str {\n        match &self.token {\n            Token::Plaintext(_) => panic!(\"registry was not configured with a secret key\"),\n            Token::Keys(s, _) => s,\n        }\n    }\n\n    /// Shutdown the server thread and wait for it to stop.\n    /// `Drop` automatically stops the server, but this additionally\n    /// waits for the thread to stop.\n    pub fn join(self) {\n        if let Some(mut server) = self.server {\n            server.stop();\n            let handle = server.handle.take().unwrap();\n            handle.join().unwrap();\n        }\n    }\n}\n\nimpl RegistryBuilder {\n    #[must_use]\n    pub fn new() -> RegistryBuilder {\n        let not_found = |_req: &Request, _server: &HttpServer| -> Response {\n            Response {\n                code: 404,\n                headers: vec![],\n                body: b\"not found\".to_vec(),\n            }\n        };\n        RegistryBuilder {\n            alternative: None,\n            token: None,\n            auth_required: false,\n            http_api: false,\n            http_index: false,\n            api: true,\n            configure_registry: true,\n            configure_token: true,\n            custom_responders: HashMap::new(),\n            not_found_handler: Box::new(not_found),\n            delayed_index_update: 0,\n            credential_provider: None,\n        }\n    }\n\n    /// Adds a custom HTTP response for a specific url\n    #[must_use]\n    pub fn add_responder<R: 'static + Send + Fn(&Request, &HttpServer) -> Response>(\n        mut self,\n        url: impl Into<String>,\n        responder: R,\n    ) -> Self {\n        self.custom_responders\n            .insert(url.into(), Box::new(responder));\n        self\n    }\n\n    #[must_use]\n    pub fn not_found_handler<R: 'static + Send + Fn(&Request, &HttpServer) -> Response>(\n        mut self,\n        responder: R,\n    ) -> Self {\n        self.not_found_handler = Box::new(responder);\n        self\n    }\n\n    /// Configures the git index update to be delayed by the given number of seconds.\n    #[must_use]\n    pub fn delayed_index_update(mut self, delay: usize) -> Self {\n        self.delayed_index_update = delay;\n        self\n    }\n\n    /// Initializes as an alternative registry with the given name.\n    #[must_use]\n    pub fn alternative_named(mut self, alt: &str) -> Self {\n        self.alternative = Some(alt.to_string());\n        self\n    }\n\n    /// Initializes as an alternative registry named \"alternative\".\n    #[must_use]\n    pub fn alternative(self) -> Self {\n        self.alternative_named(\"alternative\")\n    }\n\n    /// Prevents placing a token in the configuration\n    #[must_use]\n    pub fn no_configure_token(mut self) -> Self {\n        self.configure_token = false;\n        self\n    }\n\n    /// Prevents adding the registry to the configuration.\n    #[must_use]\n    pub fn no_configure_registry(mut self) -> Self {\n        self.configure_registry = false;\n        self\n    }\n\n    /// Sets the token value\n    #[must_use]\n    pub fn token(mut self, token: Token) -> Self {\n        self.token = Some(token);\n        self\n    }\n\n    /// Sets this registry to require the authentication token for\n    /// all operations.\n    #[must_use]\n    pub fn auth_required(mut self) -> Self {\n        self.auth_required = true;\n        self\n    }\n\n    /// Operate the index over http\n    #[must_use]\n    pub fn http_index(mut self) -> Self {\n        self.http_index = true;\n        self\n    }\n\n    /// Operate the api over http\n    #[must_use]\n    pub fn http_api(mut self) -> Self {\n        self.http_api = true;\n        self\n    }\n\n    /// The registry has no api.\n    #[must_use]\n    pub fn no_api(mut self) -> Self {\n        self.api = false;\n        self\n    }\n\n    /// The credential provider to configure for this registry.\n    #[must_use]\n    pub fn credential_provider(mut self, provider: &[&str]) -> Self {\n        self.credential_provider = Some(format!(\"['{}']\", provider.join(\"','\")));\n        self\n    }\n\n    /// Initializes the registry.\n    #[must_use]\n    pub fn build(self) -> TestRegistry {\n        let config_path = paths::cargo_home().join(\"config.toml\");\n        t!(fs::create_dir_all(config_path.parent().unwrap()));\n        let prefix = if let Some(alternative) = &self.alternative {\n            format!(\"{alternative}-\")\n        } else {\n            String::new()\n        };\n        let registry_path = generate_path(&format!(\"{prefix}registry\"));\n        let index_url = generate_url(&format!(\"{prefix}registry\"));\n        let api_url = generate_url(&format!(\"{prefix}api\"));\n        let dl_url = generate_url(&format!(\"{prefix}dl\"));\n        let dl_path = generate_path(&format!(\"{prefix}dl\"));\n        let api_path = generate_path(&format!(\"{prefix}api\"));\n        let token = self\n            .token\n            .unwrap_or_else(|| Token::Plaintext(format!(\"{prefix}sekrit\")));\n\n        let (server, index_url, api_url, dl_url) = if !self.http_index && !self.http_api {\n            // No need to start the HTTP server.\n            (None, index_url, api_url, dl_url)\n        } else {\n            let server = HttpServer::new(\n                registry_path.clone(),\n                dl_path,\n                api_path.clone(),\n                token.clone(),\n                self.auth_required,\n                self.custom_responders,\n                self.not_found_handler,\n                self.delayed_index_update,\n            );\n            let index_url = if self.http_index {\n                server.index_url()\n            } else {\n                index_url\n            };\n            let api_url = if self.http_api {\n                server.api_url()\n            } else {\n                api_url\n            };\n            let dl_url = server.dl_url();\n            (Some(server), index_url, api_url, dl_url)\n        };\n\n        let registry = TestRegistry {\n            api_url,\n            index_url,\n            server,\n            dl_url,\n            path: registry_path,\n            token,\n        };\n\n        if self.configure_registry {\n            if let Some(alternative) = &self.alternative {\n                append(\n                    &config_path,\n                    format!(\n                        \"\n                        [registries.{alternative}]\n                        index = '{}'\",\n                        registry.index_url\n                    )\n                    .as_bytes(),\n                )\n                .unwrap();\n                if let Some(p) = &self.credential_provider {\n                    append(\n                        &config_path,\n                        &format!(\n                            \"\n                        credential-provider = {p}\n                        \"\n                        )\n                        .as_bytes(),\n                    )\n                    .unwrap()\n                }\n            } else {\n                append(\n                    &config_path,\n                    format!(\n                        \"\n                        [source.crates-io]\n                        replace-with = 'dummy-registry'\n\n                        [registries.dummy-registry]\n                        index = '{}'\",\n                        registry.index_url\n                    )\n                    .as_bytes(),\n                )\n                .unwrap();\n\n                if let Some(p) = &self.credential_provider {\n                    append(\n                        &config_path,\n                        &format!(\n                            \"\n                        [registry]\n                        credential-provider = {p}\n                        \"\n                        )\n                        .as_bytes(),\n                    )\n                    .unwrap()\n                }\n            }\n        }\n\n        if self.configure_token {\n            let credentials = paths::cargo_home().join(\"credentials.toml\");\n            match &registry.token {\n                Token::Plaintext(token) => {\n                    if let Some(alternative) = &self.alternative {\n                        append(\n                            &credentials,\n                            format!(\n                                r#\"\n                                    [registries.{alternative}]\n                                    token = \"{token}\"\n                                \"#\n                            )\n                            .as_bytes(),\n                        )\n                        .unwrap();\n                    } else {\n                        append(\n                            &credentials,\n                            format!(\n                                r#\"\n                                    [registry]\n                                    token = \"{token}\"\n                                \"#\n                            )\n                            .as_bytes(),\n                        )\n                        .unwrap();\n                    }\n                }\n                Token::Keys(key, subject) => {\n                    let mut out = if let Some(alternative) = &self.alternative {\n                        format!(\"\\n[registries.{alternative}]\\n\")\n                    } else {\n                        format!(\"\\n[registry]\\n\")\n                    };\n                    out += &format!(\"secret-key = \\\"{key}\\\"\\n\");\n                    if let Some(subject) = subject {\n                        out += &format!(\"secret-key-subject = \\\"{subject}\\\"\\n\");\n                    }\n\n                    append(&credentials, out.as_bytes()).unwrap();\n                }\n            }\n        }\n\n        let auth = if self.auth_required {\n            r#\",\"auth-required\":true\"#\n        } else {\n            \"\"\n        };\n        let api = if self.api {\n            format!(r#\",\"api\":\"{}\"\"#, registry.api_url)\n        } else {\n            String::new()\n        };\n        // Initialize a new registry.\n        repo(&registry.path)\n            .file(\n                \"config.json\",\n                &format!(r#\"{{\"dl\":\"{}\"{api}{auth}}}\"#, registry.dl_url),\n            )\n            .build();\n        fs::create_dir_all(api_path.join(\"api/v1/crates\")).unwrap();\n\n        registry\n    }\n}\n\n/// Published package builder for [`TestRegistry`]\n///\n/// This uses \"source replacement\" using an automatically generated\n/// `.cargo/config` file to ensure that dependencies will use these packages\n/// instead of contacting crates.io. See `source-replacement.md` for more\n/// details on how source replacement works.\n///\n/// Call [`Package::publish`] to finalize and create the package.\n///\n/// If no files are specified, an empty `lib.rs` file is automatically created.\n///\n/// The `Cargo.toml` file is automatically generated based on the methods\n/// called on `Package` (for example, calling [`Package::dep()`] will add to the\n/// `[dependencies]` automatically). You may also specify a `Cargo.toml` file\n/// to override the generated one.\n///\n/// This supports different registry types:\n/// - Regular source replacement that replaces `crates.io` (the default).\n/// - A \"local registry\" which is a subset for vendoring (see\n///   [`Package::local`]).\n/// - An \"alternative registry\" which requires specifying the registry name\n///   (see [`Package::alternative`]).\n///\n/// This does not support \"directory sources\". See `directory.rs` for\n/// `VendorPackage` which implements directory sources.\n#[must_use]\npub struct Package {\n    name: String,\n    vers: String,\n    deps: Vec<Dependency>,\n    files: Vec<PackageFile>,\n    yanked: bool,\n    features: FeatureMap,\n    local: bool,\n    alternative: bool,\n    invalid_index_line: bool,\n    index_line: Option<String>,\n    edition: Option<String>,\n    resolver: Option<String>,\n    proc_macro: bool,\n    links: Option<String>,\n    rust_version: Option<String>,\n    cargo_features: Vec<String>,\n    pubtime: Option<String>,\n    v: Option<u32>,\n}\n\npub(crate) type FeatureMap = BTreeMap<String, Vec<String>>;\n\n/// Published package dependency builder, see [`Package::add_dep`]\n#[derive(Clone)]\npub struct Dependency {\n    name: String,\n    vers: String,\n    kind: String,\n    artifact: Option<String>,\n    bindep_target: Option<String>,\n    lib: bool,\n    target: Option<String>,\n    features: Vec<String>,\n    registry: Option<String>,\n    package: Option<String>,\n    optional: bool,\n    default_features: bool,\n    public: bool,\n}\n\n/// Entry with data that corresponds to [`tar::EntryType`].\n#[non_exhaustive]\nenum EntryData {\n    Regular(String),\n    Symlink(PathBuf),\n    Directory,\n}\n\n/// A file to be created in a package.\nstruct PackageFile {\n    path: String,\n    contents: EntryData,\n    /// The Unix mode for the file. Note that when extracted on Windows, this\n    /// is mostly ignored since it doesn't have the same style of permissions.\n    mode: u32,\n    /// If `true`, the file is created in the root of the tarfile, used for\n    /// testing invalid packages.\n    extra: bool,\n}\n\nconst DEFAULT_MODE: u32 = 0o644;\n\n/// Setup a local pseudo-crates.io [`TestRegistry`]\n///\n/// This is implicitly called by [`Package::new`].\n///\n/// When calling `cargo publish`, see instead [`crate::publish`].\npub fn init() -> TestRegistry {\n    RegistryBuilder::new().build()\n}\n\n/// Setup a local \"alternative\" [`TestRegistry`]\n///\n/// When calling `cargo publish`, see instead [`crate::publish`].\npub fn alt_init() -> TestRegistry {\n    init();\n    RegistryBuilder::new().alternative().build()\n}\n\npub struct HttpServerHandle {\n    addr: SocketAddr,\n    handle: Option<JoinHandle<()>>,\n}\n\nimpl HttpServerHandle {\n    pub fn index_url(&self) -> Url {\n        Url::parse(&format!(\"sparse+http://{}/index/\", self.addr)).unwrap()\n    }\n\n    pub fn api_url(&self) -> Url {\n        Url::parse(&format!(\"http://{}/\", self.addr)).unwrap()\n    }\n\n    pub fn dl_url(&self) -> Url {\n        Url::parse(&format!(\"http://{}/dl\", self.addr)).unwrap()\n    }\n\n    fn stop(&self) {\n        if let Ok(mut stream) = TcpStream::connect(self.addr) {\n            // shutdown the server\n            let _ = stream.write_all(b\"stop\");\n            let _ = stream.flush();\n        }\n    }\n}\n\nimpl Drop for HttpServerHandle {\n    fn drop(&mut self) {\n        self.stop();\n    }\n}\n\n/// Request to the test http server\n#[derive(Clone)]\npub struct Request {\n    pub url: Url,\n    pub method: String,\n    pub body: Option<Vec<u8>>,\n    pub authorization: Option<String>,\n    pub if_modified_since: Option<String>,\n    pub if_none_match: Option<String>,\n}\n\nimpl fmt::Debug for Request {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        // body is not included as it can produce long debug outputs\n        f.debug_struct(\"Request\")\n            .field(\"url\", &self.url)\n            .field(\"method\", &self.method)\n            .field(\"authorization\", &self.authorization)\n            .field(\"if_modified_since\", &self.if_modified_since)\n            .field(\"if_none_match\", &self.if_none_match)\n            .finish()\n    }\n}\n\n/// Response from the test http server\npub struct Response {\n    pub code: u32,\n    pub headers: Vec<String>,\n    pub body: Vec<u8>,\n}\n\npub struct HttpServer {\n    listener: TcpListener,\n    registry_path: PathBuf,\n    dl_path: PathBuf,\n    api_path: PathBuf,\n    addr: SocketAddr,\n    token: Token,\n    auth_required: bool,\n    custom_responders: HashMap<String, RequestCallback>,\n    not_found_handler: RequestCallback,\n    delayed_index_update: usize,\n}\n\n/// A helper struct that collects the arguments for [`HttpServer::check_authorized`].\n/// Based on looking at the request, these are the fields that the authentication header should attest to.\nstruct Mutation<'a> {\n    mutation: &'a str,\n    name: Option<&'a str>,\n    vers: Option<&'a str>,\n    cksum: Option<&'a str>,\n}\n\nimpl HttpServer {\n    pub fn new(\n        registry_path: PathBuf,\n        dl_path: PathBuf,\n        api_path: PathBuf,\n        token: Token,\n        auth_required: bool,\n        custom_responders: HashMap<String, RequestCallback>,\n        not_found_handler: RequestCallback,\n        delayed_index_update: usize,\n    ) -> HttpServerHandle {\n        let listener = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n        let addr = listener.local_addr().unwrap();\n        let server = HttpServer {\n            listener,\n            registry_path,\n            dl_path,\n            api_path,\n            addr,\n            token,\n            auth_required,\n            custom_responders,\n            not_found_handler,\n            delayed_index_update,\n        };\n        let handle = Some(thread::spawn(move || server.start()));\n        HttpServerHandle { addr, handle }\n    }\n\n    fn start(&self) {\n        let mut line = String::new();\n        'server: loop {\n            let (socket, _) = self.listener.accept().unwrap();\n            let mut buf = BufReader::new(socket);\n            line.clear();\n            if buf.read_line(&mut line).unwrap() == 0 {\n                // Connection terminated.\n                continue;\n            }\n            // Read the \"GET path HTTP/1.1\" line.\n            let mut parts = line.split_ascii_whitespace();\n            let method = parts.next().unwrap().to_ascii_lowercase();\n            if method == \"stop\" {\n                // Shutdown the server.\n                return;\n            }\n            let addr = self.listener.local_addr().unwrap();\n            let url = format!(\n                \"http://{}/{}\",\n                addr,\n                parts.next().unwrap().trim_start_matches('/')\n            );\n            let url = Url::parse(&url).unwrap();\n\n            // Grab headers we care about.\n            let mut if_modified_since = None;\n            let mut if_none_match = None;\n            let mut authorization = None;\n            let mut content_len = None;\n            loop {\n                line.clear();\n                if buf.read_line(&mut line).unwrap() == 0 {\n                    continue 'server;\n                }\n                if line == \"\\r\\n\" {\n                    // End of headers.\n                    line.clear();\n                    break;\n                }\n                let (name, value) = line.split_once(':').unwrap();\n                let name = name.trim().to_ascii_lowercase();\n                let value = value.trim().to_string();\n                match name.as_str() {\n                    \"if-modified-since\" => if_modified_since = Some(value),\n                    \"if-none-match\" => if_none_match = Some(value),\n                    \"authorization\" => authorization = Some(value),\n                    \"content-length\" => content_len = Some(value),\n                    _ => {}\n                }\n            }\n\n            let mut body = None;\n            if let Some(con_len) = content_len {\n                let len = con_len.parse::<u64>().unwrap();\n                let mut content = vec![0u8; len as usize];\n                buf.read_exact(&mut content).unwrap();\n                body = Some(content)\n            }\n\n            let req = Request {\n                authorization,\n                if_modified_since,\n                if_none_match,\n                method,\n                url,\n                body,\n            };\n            let response = self.route(&req);\n            let buf = buf.get_mut();\n            write!(buf, \"HTTP/1.1 {}\\r\\n\", response.code).unwrap();\n            write!(buf, \"Content-Length: {}\\r\\n\", response.body.len()).unwrap();\n            write!(buf, \"Connection: close\\r\\n\").unwrap();\n            for header in response.headers {\n                write!(buf, \"{}\\r\\n\", header).unwrap();\n            }\n            write!(buf, \"\\r\\n\").unwrap();\n            buf.write_all(&response.body).unwrap();\n            buf.flush().unwrap();\n        }\n    }\n\n    fn check_authorized(&self, req: &Request, mutation: Option<Mutation<'_>>) -> bool {\n        let (private_key, private_key_subject) = if mutation.is_some() || self.auth_required {\n            match &self.token {\n                Token::Plaintext(token) => return Some(token) == req.authorization.as_ref(),\n                Token::Keys(private_key, private_key_subject) => {\n                    (private_key.as_str(), private_key_subject)\n                }\n            }\n        } else {\n            assert!(req.authorization.is_none(), \"unexpected token\");\n            return true;\n        };\n\n        macro_rules! t {\n            ($e:expr) => {\n                match $e {\n                    Some(e) => e,\n                    None => return false,\n                }\n            };\n        }\n\n        let secret: AsymmetricSecretKey<pasetors::version3::V3> = private_key.try_into().unwrap();\n        let public: AsymmetricPublicKey<pasetors::version3::V3> = (&secret).try_into().unwrap();\n        let pub_key_id: pasetors::paserk::Id = (&public).into();\n        let mut paserk_pub_key_id = String::new();\n        FormatAsPaserk::fmt(&pub_key_id, &mut paserk_pub_key_id).unwrap();\n        // https://github.com/rust-lang/rfcs/blob/master/text/3231-cargo-asymmetric-tokens.md#how-the-registry-server-will-validate-an-asymmetric-token\n\n        // - The PASETO is in v3.public format.\n        let authorization = t!(&req.authorization);\n        let untrusted_token = t!(\n            UntrustedToken::<pasetors::Public, pasetors::version3::V3>::try_from(authorization)\n                .ok()\n        );\n\n        // - The PASETO validates using the public key it looked up based on the key ID.\n        #[derive(serde::Deserialize, Debug)]\n        struct Footer<'a> {\n            url: &'a str,\n            kip: &'a str,\n        }\n        let footer: Footer<'_> =\n            t!(serde_json::from_slice(untrusted_token.untrusted_footer()).ok());\n        if footer.kip != paserk_pub_key_id {\n            return false;\n        }\n        let trusted_token =\n            t!(\n                pasetors::version3::PublicToken::verify(&public, &untrusted_token, None, None,)\n                    .ok()\n            );\n\n        // - The URL matches the registry base URL\n        if footer.url != \"https://github.com/rust-lang/crates.io-index\"\n            && footer.url != &format!(\"sparse+http://{}/index/\", self.addr)\n        {\n            return false;\n        }\n\n        // - The PASETO is still within its valid time period.\n        #[derive(serde::Deserialize)]\n        struct Message<'a> {\n            iat: &'a str,\n            sub: Option<&'a str>,\n            mutation: Option<&'a str>,\n            name: Option<&'a str>,\n            vers: Option<&'a str>,\n            cksum: Option<&'a str>,\n            _challenge: Option<&'a str>, // todo: PASETO with challenges\n            v: Option<u8>,\n        }\n        let message: Message<'_> = t!(serde_json::from_str(trusted_token.payload()).ok());\n        let token_time = t!(OffsetDateTime::parse(message.iat, &Rfc3339).ok());\n        let now = OffsetDateTime::now_utc();\n        if (now - token_time) > Duration::MINUTE {\n            return false;\n        }\n        if private_key_subject.as_deref() != message.sub {\n            return false;\n        }\n        // - If the claim v is set, that it has the value of 1.\n        if let Some(v) = message.v {\n            if v != 1 {\n                return false;\n            }\n        }\n        // - If the server issues challenges, that the challenge has not yet been answered.\n        // todo: PASETO with challenges\n        // - If the operation is a mutation:\n        if let Some(mutation) = mutation {\n            //  - That the operation matches the mutation field and is one of publish, yank, or unyank.\n            if message.mutation != Some(mutation.mutation) {\n                return false;\n            }\n            //  - That the package, and version match the request.\n            if message.name != mutation.name {\n                return false;\n            }\n            if message.vers != mutation.vers {\n                return false;\n            }\n            //  - If the mutation is publish, that the version has not already been published, and that the hash matches the request.\n            if mutation.mutation == \"publish\" {\n                if message.cksum != mutation.cksum {\n                    return false;\n                }\n            }\n        } else {\n            // - If the operation is a read, that the mutation field is not set.\n            if message.mutation.is_some()\n                || message.name.is_some()\n                || message.vers.is_some()\n                || message.cksum.is_some()\n            {\n                return false;\n            }\n        }\n        true\n    }\n\n    /// Route the request\n    fn route(&self, req: &Request) -> Response {\n        // Check for custom responder\n        if let Some(responder) = self.custom_responders.get(req.url.path()) {\n            return responder(&req, self);\n        }\n        let path: Vec<_> = req.url.path()[1..].split('/').collect();\n        match (req.method.as_str(), path.as_slice()) {\n            (\"get\", [\"index\", ..]) => {\n                if !self.check_authorized(req, None) {\n                    self.unauthorized(req)\n                } else {\n                    self.index(&req)\n                }\n            }\n            (\"get\", [\"dl\", ..]) => {\n                if !self.check_authorized(req, None) {\n                    self.unauthorized(req)\n                } else {\n                    self.dl(&req)\n                }\n            }\n            // publish\n            (\"put\", [\"api\", \"v1\", \"crates\", \"new\"]) => self.check_authorized_publish(req),\n            // The remainder of the operators in the test framework do nothing other than responding 'ok'.\n            //\n            // Note: We don't need to support anything real here because there are no tests that\n            // currently require anything other than publishing via the http api.\n\n            // yank / unyank\n            (\"delete\" | \"put\", [\"api\", \"v1\", \"crates\", crate_name, version, mutation]) => {\n                if !self.check_authorized(\n                    req,\n                    Some(Mutation {\n                        mutation,\n                        name: Some(crate_name),\n                        vers: Some(version),\n                        cksum: None,\n                    }),\n                ) {\n                    self.unauthorized(req)\n                } else {\n                    self.ok(&req)\n                }\n            }\n            // owners\n            (\"get\" | \"put\" | \"delete\", [\"api\", \"v1\", \"crates\", crate_name, \"owners\"]) => {\n                if !self.check_authorized(\n                    req,\n                    Some(Mutation {\n                        mutation: \"owners\",\n                        name: Some(crate_name),\n                        vers: None,\n                        cksum: None,\n                    }),\n                ) {\n                    self.unauthorized(req)\n                } else {\n                    self.ok(&req)\n                }\n            }\n            _ => self.not_found(&req),\n        }\n    }\n\n    /// Unauthorized response\n    pub fn unauthorized(&self, _req: &Request) -> Response {\n        Response {\n            code: 401,\n            headers: vec![\n                r#\"www-authenticate: Cargo login_url=\"https://test-registry-login/me\"\"#.to_string(),\n            ],\n            body: b\"Unauthorized message from server.\".to_vec(),\n        }\n    }\n\n    /// Not found response\n    pub fn not_found(&self, req: &Request) -> Response {\n        (self.not_found_handler)(req, self)\n    }\n\n    /// Respond OK without doing anything\n    pub fn ok(&self, _req: &Request) -> Response {\n        Response {\n            code: 200,\n            headers: vec![],\n            body: br#\"{\"ok\": true, \"msg\": \"completed!\"}\"#.to_vec(),\n        }\n    }\n\n    /// Return an internal server error (HTTP 500)\n    pub fn internal_server_error(&self, _req: &Request) -> Response {\n        Response {\n            code: 500,\n            headers: vec![],\n            body: br#\"internal server error\"#.to_vec(),\n        }\n    }\n\n    /// Return too many requests (HTTP 429)\n    pub fn too_many_requests(&self, _req: &Request, delay: std::time::Duration) -> Response {\n        Response {\n            code: 429,\n            headers: vec![format!(\"Retry-After: {}\", delay.as_secs())],\n            body: format!(\n                \"too many requests, try again in {} seconds\",\n                delay.as_secs()\n            )\n            .into_bytes(),\n        }\n    }\n\n    /// Serve the download endpoint\n    pub fn dl(&self, req: &Request) -> Response {\n        let file = self\n            .dl_path\n            .join(req.url.path().strip_prefix(\"/dl/\").unwrap());\n        println!(\"{}\", file.display());\n        if !file.exists() {\n            return self.not_found(req);\n        }\n        return Response {\n            body: fs::read(&file).unwrap(),\n            code: 200,\n            headers: vec![],\n        };\n    }\n\n    /// Serve the registry index\n    pub fn index(&self, req: &Request) -> Response {\n        let file = self\n            .registry_path\n            .join(req.url.path().strip_prefix(\"/index/\").unwrap());\n        if !file.exists() {\n            return self.not_found(req);\n        } else {\n            // Now grab info about the file.\n            let data = fs::read(&file).unwrap();\n            let etag = Sha256::new().update(&data).finish_hex();\n            let last_modified = format!(\"{:?}\", file.metadata().unwrap().modified().unwrap());\n\n            // Start to construct our response:\n            let mut any_match = false;\n            let mut all_match = true;\n            if let Some(expected) = &req.if_none_match {\n                if &etag != expected {\n                    all_match = false;\n                } else {\n                    any_match = true;\n                }\n            }\n            if let Some(expected) = &req.if_modified_since {\n                // NOTE: Equality comparison is good enough for tests.\n                if &last_modified != expected {\n                    all_match = false;\n                } else {\n                    any_match = true;\n                }\n            }\n\n            if any_match && all_match {\n                return Response {\n                    body: Vec::new(),\n                    code: 304,\n                    headers: vec![],\n                };\n            } else {\n                return Response {\n                    body: data,\n                    code: 200,\n                    headers: vec![\n                        format!(\"ETag: \\\"{}\\\"\", etag),\n                        format!(\"Last-Modified: {}\", last_modified),\n                    ],\n                };\n            }\n        }\n    }\n\n    pub fn check_authorized_publish(&self, req: &Request) -> Response {\n        if let Some(body) = &req.body {\n            // Mimic the publish behavior for local registries by writing out the request\n            // so tests can verify publishes made to either registry type.\n            let path = self.api_path.join(\"api/v1/crates/new\");\n            t!(fs::create_dir_all(path.parent().unwrap()));\n            t!(fs::write(&path, body));\n\n            // Get the metadata of the package\n            let (len, remaining) = body.split_at(4);\n            let json_len = u32::from_le_bytes(len.try_into().unwrap());\n            let (json, remaining) = remaining.split_at(json_len as usize);\n            let new_crate = serde_json::from_slice::<crates_io::NewCrate>(json).unwrap();\n            // Get the `.crate` file\n            let (len, remaining) = remaining.split_at(4);\n            let file_len = u32::from_le_bytes(len.try_into().unwrap());\n            let (file, _remaining) = remaining.split_at(file_len as usize);\n            let file_cksum = cksum(&file);\n\n            if !self.check_authorized(\n                req,\n                Some(Mutation {\n                    mutation: \"publish\",\n                    name: Some(&new_crate.name),\n                    vers: Some(&new_crate.vers),\n                    cksum: Some(&file_cksum),\n                }),\n            ) {\n                return self.unauthorized(req);\n            }\n\n            let dst = self\n                .dl_path\n                .join(&new_crate.name)\n                .join(&new_crate.vers)\n                .join(\"download\");\n\n            if self.delayed_index_update == 0 {\n                save_new_crate(dst, new_crate, file, file_cksum, &self.registry_path);\n            } else {\n                let delayed_index_update = self.delayed_index_update;\n                let registry_path = self.registry_path.clone();\n                let file = Vec::from(file);\n                thread::spawn(move || {\n                    thread::sleep(std::time::Duration::new(delayed_index_update as u64, 0));\n                    save_new_crate(dst, new_crate, &file, file_cksum, &registry_path);\n                });\n            }\n\n            self.ok(&req)\n        } else {\n            Response {\n                code: 400,\n                headers: vec![],\n                body: b\"The request was missing a body\".to_vec(),\n            }\n        }\n    }\n}\n\nfn save_new_crate(\n    dst: PathBuf,\n    new_crate: crates_io::NewCrate,\n    file: &[u8],\n    file_cksum: String,\n    registry_path: &Path,\n) {\n    // Write the `.crate`\n    t!(fs::create_dir_all(dst.parent().unwrap()));\n    t!(fs::write(&dst, file));\n\n    let deps = new_crate\n        .deps\n        .iter()\n        .map(|dep| {\n            let (name, package) = match &dep.explicit_name_in_toml {\n                Some(explicit) => (explicit.to_string(), Some(dep.name.to_string())),\n                None => (dep.name.to_string(), None),\n            };\n            serde_json::json!({\n                \"name\": name,\n                \"req\": dep.version_req,\n                \"features\": dep.features,\n                \"default_features\": dep.default_features,\n                \"target\": dep.target,\n                \"optional\": dep.optional,\n                \"kind\": dep.kind,\n                \"registry\": dep.registry,\n                \"package\": package,\n                \"artifact\": dep.artifact,\n                \"bindep_target\": dep.bindep_target,\n                \"lib\": dep.lib,\n            })\n        })\n        .collect::<Vec<_>>();\n\n    let line = create_index_line(\n        serde_json::json!(new_crate.name),\n        &new_crate.vers,\n        deps,\n        &file_cksum,\n        new_crate.features,\n        false,\n        new_crate.links,\n        new_crate.rust_version.as_deref(),\n        None,\n        None,\n    );\n\n    write_to_index(registry_path, &new_crate.name, line, false);\n}\n\nimpl Package {\n    /// Creates a new package builder.\n    /// Call `publish()` to finalize and build the package.\n    pub fn new(name: &str, vers: &str) -> Package {\n        let config = paths::cargo_home().join(\"config.toml\");\n        if !config.exists() {\n            init();\n        }\n        Package {\n            name: name.to_string(),\n            vers: vers.to_string(),\n            deps: Vec::new(),\n            files: Vec::new(),\n            yanked: false,\n            features: BTreeMap::new(),\n            local: false,\n            alternative: false,\n            invalid_index_line: false,\n            index_line: None,\n            edition: None,\n            resolver: None,\n            proc_macro: false,\n            links: None,\n            rust_version: None,\n            cargo_features: Vec::new(),\n            pubtime: None,\n            v: None,\n        }\n    }\n\n    /// Call with `true` to publish in a \"local registry\".\n    ///\n    /// See `source-replacement.html#local-registry-sources` for more details\n    /// on local registries. See `local_registry.rs` for the tests that use\n    /// this.\n    pub fn local(&mut self, local: bool) -> &mut Package {\n        self.local = local;\n        self\n    }\n\n    /// Call with `true` to publish in an \"alternative registry\".\n    ///\n    /// The name of the alternative registry is called \"alternative\".\n    ///\n    /// See `src/doc/src/reference/registries.md` for more details on\n    /// alternative registries. See `alt_registry.rs` for the tests that use\n    /// this.\n    ///\n    /// **Requires:** [`alt_init`]\n    pub fn alternative(&mut self, alternative: bool) -> &mut Package {\n        self.alternative = alternative;\n        self\n    }\n\n    /// Adds a file to the package.\n    pub fn file(&mut self, name: &str, contents: &str) -> &mut Package {\n        self.file_with_mode(name, DEFAULT_MODE, contents)\n    }\n\n    /// Adds a file with a specific Unix mode.\n    pub fn file_with_mode(&mut self, path: &str, mode: u32, contents: &str) -> &mut Package {\n        self.files.push(PackageFile {\n            path: path.to_string(),\n            contents: EntryData::Regular(contents.into()),\n            mode,\n            extra: false,\n        });\n        self\n    }\n\n    /// Adds a symlink to a path to the package.\n    pub fn symlink(&mut self, dst: &str, src: &str) -> &mut Package {\n        self.files.push(PackageFile {\n            path: dst.to_string(),\n            contents: EntryData::Symlink(src.into()),\n            mode: DEFAULT_MODE,\n            extra: false,\n        });\n        self\n    }\n\n    /// Adds an empty directory at the given path.\n    pub fn directory(&mut self, path: &str) -> &mut Package {\n        self.files.push(PackageFile {\n            path: path.to_string(),\n            contents: EntryData::Directory,\n            mode: DEFAULT_MODE,\n            extra: false,\n        });\n        self\n    }\n\n    /// Adds an \"extra\" file that is not rooted within the package.\n    ///\n    /// Normal files are automatically placed within a directory named\n    /// `$PACKAGE-$VERSION`. This allows you to override that behavior,\n    /// typically for testing invalid behavior.\n    pub fn extra_file(&mut self, path: &str, contents: &str) -> &mut Package {\n        self.files.push(PackageFile {\n            path: path.to_string(),\n            contents: EntryData::Regular(contents.to_string()),\n            mode: DEFAULT_MODE,\n            extra: true,\n        });\n        self\n    }\n\n    /// Adds a normal dependency. Example:\n    /// ```toml\n    /// [dependencies]\n    /// foo = {version = \"1.0\"}\n    /// ```\n    pub fn dep(&mut self, name: &str, vers: &str) -> &mut Package {\n        self.add_dep(&Dependency::new(name, vers))\n    }\n\n    /// Adds a dependency with the given feature. Example:\n    /// ```toml\n    /// [dependencies]\n    /// foo = {version = \"1.0\", \"features\": [\"feat1\", \"feat2\"]}\n    /// ```\n    pub fn feature_dep(&mut self, name: &str, vers: &str, features: &[&str]) -> &mut Package {\n        self.add_dep(Dependency::new(name, vers).enable_features(features))\n    }\n\n    /// Adds a platform-specific dependency. Example:\n    /// ```toml\n    /// [target.'cfg(windows)'.dependencies]\n    /// foo = {version = \"1.0\"}\n    /// ```\n    pub fn target_dep(&mut self, name: &str, vers: &str, target: &str) -> &mut Package {\n        self.add_dep(Dependency::new(name, vers).target(target))\n    }\n\n    /// Adds a dependency to the alternative registry.\n    pub fn registry_dep(&mut self, name: &str, vers: &str) -> &mut Package {\n        self.add_dep(Dependency::new(name, vers).registry(\"alternative\"))\n    }\n\n    /// Adds a dev-dependency. Example:\n    /// ```toml\n    /// [dev-dependencies]\n    /// foo = {version = \"1.0\"}\n    /// ```\n    pub fn dev_dep(&mut self, name: &str, vers: &str) -> &mut Package {\n        self.add_dep(Dependency::new(name, vers).dev())\n    }\n\n    /// Adds a build-dependency. Example:\n    /// ```toml\n    /// [build-dependencies]\n    /// foo = {version = \"1.0\"}\n    /// ```\n    pub fn build_dep(&mut self, name: &str, vers: &str) -> &mut Package {\n        self.add_dep(Dependency::new(name, vers).build())\n    }\n\n    pub fn add_dep(&mut self, dep: &Dependency) -> &mut Package {\n        self.deps.push(dep.clone());\n        self\n    }\n\n    /// Specifies whether or not the package is \"yanked\".\n    pub fn yanked(&mut self, yanked: bool) -> &mut Package {\n        self.yanked = yanked;\n        self\n    }\n\n    /// Specifies `package.edition`\n    pub fn edition(&mut self, edition: &str) -> &mut Package {\n        self.edition = Some(edition.to_owned());\n        self\n    }\n\n    /// Specifies `package.resolver`\n    pub fn resolver(&mut self, resolver: &str) -> &mut Package {\n        self.resolver = Some(resolver.to_owned());\n        self\n    }\n\n    /// Specifies whether or not this is a proc macro.\n    pub fn proc_macro(&mut self, proc_macro: bool) -> &mut Package {\n        self.proc_macro = proc_macro;\n        self\n    }\n\n    /// Adds an entry in the `[features]` section.\n    pub fn feature(&mut self, name: &str, deps: &[&str]) -> &mut Package {\n        let deps = deps.iter().map(|s| s.to_string()).collect();\n        self.features.insert(name.to_string(), deps);\n        self\n    }\n\n    /// Specify a minimal Rust version.\n    pub fn rust_version(&mut self, rust_version: &str) -> &mut Package {\n        self.rust_version = Some(rust_version.into());\n        self\n    }\n\n    /// Causes the JSON line emitted in the index to be invalid, presumably\n    /// causing Cargo to skip over this version.\n    pub fn invalid_index_line(&mut self, invalid: bool) -> &mut Package {\n        self.invalid_index_line = invalid;\n        self\n    }\n\n    /// Override the auto-generated index line\n    ///\n    /// This can give more control over error cases than [`Package::invalid_index_line`]\n    pub fn index_line(&mut self, line: &str) -> &mut Package {\n        self.index_line = Some(line.to_owned());\n        self\n    }\n\n    pub fn links(&mut self, links: &str) -> &mut Package {\n        self.links = Some(links.to_string());\n        self\n    }\n\n    pub fn cargo_feature(&mut self, feature: &str) -> &mut Package {\n        self.cargo_features.push(feature.to_owned());\n        self\n    }\n\n    /// The publish time for the package in ISO8601 with UTC timezone (e.g. 2025-11-12T19:30:12Z)\n    pub fn pubtime(&mut self, time: &str) -> &mut Package {\n        self.pubtime = Some(time.to_owned());\n        self\n    }\n\n    /// Sets the index schema version for this package.\n    ///\n    /// See `cargo::sources::registry::IndexPackage` for more information.\n    pub fn schema_version(&mut self, version: u32) -> &mut Package {\n        self.v = Some(version);\n        self\n    }\n\n    /// Creates the package and place it in the registry.\n    ///\n    /// This does not actually use Cargo's publishing system, but instead\n    /// manually creates the entry in the registry on the filesystem.\n    ///\n    /// Returns the checksum for the package.\n    pub fn publish(&self) -> String {\n        self.make_archive();\n\n        // Figure out what we're going to write into the index.\n        let deps = self\n            .deps\n            .iter()\n            .map(|dep| {\n                // In the index, the `registry` is null if it is from the same registry.\n                // In Cargo.toml, it is None if it is from crates.io.\n                let registry_url = match (self.alternative, dep.registry.as_deref()) {\n                    (false, None) => None,\n                    (false, Some(\"alternative\")) => Some(alt_registry_url().to_string()),\n                    (true, None) => {\n                        Some(\"https://github.com/rust-lang/crates.io-index\".to_string())\n                    }\n                    (true, Some(\"alternative\")) => None,\n                    _ => panic!(\"registry_dep currently only supports `alternative`\"),\n                };\n                let artifact = if let Some(artifact) = &dep.artifact {\n                    serde_json::json!([artifact])\n                } else {\n                    serde_json::json!(null)\n                };\n                serde_json::json!({\n                    \"name\": dep.name,\n                    \"req\": dep.vers,\n                    \"features\": dep.features,\n                    \"default_features\": dep.default_features,\n                    \"target\": dep.target,\n                    \"artifact\": artifact,\n                    \"bindep_target\": dep.bindep_target,\n                    \"lib\": dep.lib,\n                    \"optional\": dep.optional,\n                    \"kind\": dep.kind,\n                    \"registry\": registry_url,\n                    \"package\": dep.package,\n                    \"public\": dep.public,\n                })\n            })\n            .collect::<Vec<_>>();\n        let cksum = {\n            let c = t!(fs::read(&self.archive_dst()));\n            cksum(&c)\n        };\n        let line = if let Some(line) = self.index_line.clone() {\n            line\n        } else {\n            let name = if self.invalid_index_line {\n                serde_json::json!(1)\n            } else {\n                serde_json::json!(self.name)\n            };\n            create_index_line(\n                name,\n                &self.vers,\n                deps,\n                &cksum,\n                self.features.clone(),\n                self.yanked,\n                self.links.clone(),\n                self.rust_version.as_deref(),\n                self.pubtime.as_deref(),\n                self.v,\n            )\n        };\n\n        let registry_path = if self.alternative {\n            alt_registry_path()\n        } else {\n            registry_path()\n        };\n\n        write_to_index(&registry_path, &self.name, line, self.local);\n\n        cksum\n    }\n\n    fn make_archive(&self) {\n        let dst = self.archive_dst();\n        t!(fs::create_dir_all(dst.parent().unwrap()));\n        let f = t!(File::create(&dst));\n        let mut a = Builder::new(GzEncoder::new(f, Compression::none()));\n        a.sparse(false);\n\n        if !self\n            .files\n            .iter()\n            .any(|PackageFile { path, .. }| path == \"Cargo.toml\")\n        {\n            self.append_manifest(&mut a);\n        }\n        if self.files.is_empty() {\n            self.append(\n                &mut a,\n                \"src/lib.rs\",\n                DEFAULT_MODE,\n                &EntryData::Regular(\"\".into()),\n            );\n        } else {\n            for PackageFile {\n                path,\n                contents,\n                mode,\n                extra,\n            } in &self.files\n            {\n                if *extra {\n                    self.append_raw(&mut a, path, *mode, contents);\n                } else {\n                    self.append(&mut a, path, *mode, contents);\n                }\n            }\n        }\n    }\n\n    fn append_manifest<W: Write>(&self, ar: &mut Builder<W>) {\n        let mut manifest = String::new();\n\n        if !self.cargo_features.is_empty() {\n            let mut features = String::new();\n            serde::Serialize::serialize(\n                &self.cargo_features,\n                toml::ser::ValueSerializer::new(&mut features),\n            )\n            .unwrap();\n            manifest.push_str(&format!(\"cargo-features = {}\\n\\n\", features));\n        }\n\n        manifest.push_str(&format!(\n            r#\"\n            [package]\n            name = \"{}\"\n            version = \"{}\"\n            authors = []\n        \"#,\n            self.name, self.vers\n        ));\n\n        if let Some(version) = &self.rust_version {\n            manifest.push_str(&format!(\"rust-version = \\\"{}\\\"\\n\", version));\n        }\n\n        if let Some(edition) = &self.edition {\n            manifest.push_str(&format!(\"edition = \\\"{}\\\"\\n\", edition));\n        }\n\n        if let Some(resolver) = &self.resolver {\n            manifest.push_str(&format!(\"resolver = \\\"{}\\\"\\n\", resolver));\n        }\n\n        if !self.features.is_empty() {\n            let features: Vec<String> = self\n                .features\n                .iter()\n                .map(|(feature, features)| {\n                    if features.is_empty() {\n                        format!(\"{} = []\", feature)\n                    } else {\n                        format!(\n                            \"{} = [{}]\",\n                            feature,\n                            features\n                                .iter()\n                                .map(|s| format!(\"\\\"{}\\\"\", s))\n                                .collect::<Vec<_>>()\n                                .join(\", \")\n                        )\n                    }\n                })\n                .collect();\n\n            manifest.push_str(&format!(\"\\n[features]\\n{}\", features.join(\"\\n\")));\n        }\n\n        for dep in self.deps.iter() {\n            let target = match dep.target {\n                None => String::new(),\n                Some(ref s) => format!(\"target.'{}'.\", s),\n            };\n            let kind = match &dep.kind[..] {\n                \"build\" => \"build-\",\n                \"dev\" => \"dev-\",\n                _ => \"\",\n            };\n            manifest.push_str(&format!(\n                r#\"\n                [{}{}dependencies.{}]\n                version = \"{}\"\n            \"#,\n                target, kind, dep.name, dep.vers\n            ));\n            if dep.optional {\n                manifest.push_str(\"optional = true\\n\");\n            }\n            if let Some(artifact) = &dep.artifact {\n                manifest.push_str(&format!(\"artifact = \\\"{}\\\"\\n\", artifact));\n            }\n            if let Some(target) = &dep.bindep_target {\n                manifest.push_str(&format!(\"target = \\\"{}\\\"\\n\", target));\n            }\n            if dep.lib {\n                manifest.push_str(\"lib = true\\n\");\n            }\n            if let Some(registry) = &dep.registry {\n                assert_eq!(registry, \"alternative\");\n                manifest.push_str(&format!(\"registry-index = \\\"{}\\\"\", alt_registry_url()));\n            }\n            if !dep.default_features {\n                manifest.push_str(\"default-features = false\\n\");\n            }\n            if !dep.features.is_empty() {\n                let mut features = String::new();\n                serde::Serialize::serialize(\n                    &dep.features,\n                    toml::ser::ValueSerializer::new(&mut features),\n                )\n                .unwrap();\n                manifest.push_str(&format!(\"features = {}\\n\", features));\n            }\n            if let Some(package) = &dep.package {\n                manifest.push_str(&format!(\"package = \\\"{}\\\"\\n\", package));\n            }\n        }\n        if self.proc_macro {\n            manifest.push_str(\"[lib]\\nproc-macro = true\\n\");\n        }\n\n        self.append(\n            ar,\n            \"Cargo.toml\",\n            DEFAULT_MODE,\n            &EntryData::Regular(manifest.into()),\n        );\n    }\n\n    fn append<W: Write>(&self, ar: &mut Builder<W>, file: &str, mode: u32, contents: &EntryData) {\n        self.append_raw(\n            ar,\n            &format!(\"{}-{}/{}\", self.name, self.vers, file),\n            mode,\n            contents,\n        );\n    }\n\n    fn append_raw<W: Write>(\n        &self,\n        ar: &mut Builder<W>,\n        path: &str,\n        mode: u32,\n        contents: &EntryData,\n    ) {\n        let mut header = Header::new_ustar();\n        let contents = match contents {\n            EntryData::Regular(contents) => contents.as_str(),\n            EntryData::Symlink(src) => {\n                header.set_entry_type(tar::EntryType::Symlink);\n                t!(header.set_link_name(src));\n                \"\" // Symlink has no contents.\n            }\n            EntryData::Directory => {\n                header.set_entry_type(tar::EntryType::Directory);\n                \"\"\n            }\n        };\n        header.set_size(contents.len() as u64);\n        t!(header.set_path(path));\n        header.set_mode(mode);\n        header.set_cksum();\n        t!(ar.append(&header, contents.as_bytes()));\n    }\n\n    /// Returns the path to the compressed package file.\n    pub fn archive_dst(&self) -> PathBuf {\n        if self.local {\n            let path = if self.alternative {\n                alt_registry_path()\n            } else {\n                registry_path()\n            };\n            path.join(format!(\"{}-{}.crate\", self.name, self.vers))\n        } else if self.alternative {\n            alt_dl_path()\n                .join(&self.name)\n                .join(&self.vers)\n                .join(\"download\")\n        } else {\n            dl_path().join(&self.name).join(&self.vers).join(\"download\")\n        }\n    }\n}\n\n/// Generate a checksum\npub fn cksum(s: &[u8]) -> String {\n    Sha256::new().update(s).finish_hex()\n}\n\nimpl Dependency {\n    pub fn new(name: &str, vers: &str) -> Dependency {\n        Dependency {\n            name: name.to_string(),\n            vers: vers.to_string(),\n            kind: \"normal\".to_string(),\n            artifact: None,\n            bindep_target: None,\n            lib: false,\n            target: None,\n            features: Vec::new(),\n            package: None,\n            optional: false,\n            registry: None,\n            default_features: true,\n            public: false,\n        }\n    }\n\n    /// Changes this to `[build-dependencies]`.\n    pub fn build(&mut self) -> &mut Self {\n        self.kind = \"build\".to_string();\n        self\n    }\n\n    /// Changes this to `[dev-dependencies]`.\n    pub fn dev(&mut self) -> &mut Self {\n        self.kind = \"dev\".to_string();\n        self\n    }\n\n    /// Changes this to `[target.$target.dependencies]`.\n    pub fn target(&mut self, target: &str) -> &mut Self {\n        self.target = Some(target.to_string());\n        self\n    }\n\n    /// Change the artifact to be of the given kind, like \"bin\", or \"staticlib\",\n    /// along with a specific target triple if provided.\n    pub fn artifact(&mut self, kind: &str, target: Option<String>) -> &mut Self {\n        self.artifact = Some(kind.to_string());\n        self.bindep_target = target;\n        self\n    }\n\n    /// Adds `registry = $registry` to this dependency.\n    pub fn registry(&mut self, registry: &str) -> &mut Self {\n        self.registry = Some(registry.to_string());\n        self\n    }\n\n    /// Adds `features = [ ... ]` to this dependency.\n    pub fn enable_features(&mut self, features: &[&str]) -> &mut Self {\n        self.features.extend(features.iter().map(|s| s.to_string()));\n        self\n    }\n\n    /// Adds `package = ...` to this dependency.\n    pub fn package(&mut self, pkg: &str) -> &mut Self {\n        self.package = Some(pkg.to_string());\n        self\n    }\n\n    /// Changes this to an optional dependency.\n    pub fn optional(&mut self, optional: bool) -> &mut Self {\n        self.optional = optional;\n        self\n    }\n\n    /// Changes this to an public dependency.\n    pub fn public(&mut self, public: bool) -> &mut Self {\n        self.public = public;\n        self\n    }\n\n    /// Adds `default-features = false` if the argument is `false`.\n    pub fn default_features(&mut self, default_features: bool) -> &mut Self {\n        self.default_features = default_features;\n        self\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util/Cargo.toml",
    "content": "[package]\nname = \"cargo-util\"\nversion = \"0.2.29\"\nrust-version = \"1.94\"  # MSRV:1\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"Miscellaneous support code used by Cargo.\"\n\n[dependencies]\nanyhow.workspace = true\nfiletime.workspace = true\nhex.workspace = true\nignore.workspace = true\njobserver.workspace = true\nsame-file.workspace = true\nsha2.workspace = true\nshell-escape.workspace = true\ntempfile.workspace = true\ntracing.workspace = true\nwalkdir.workspace = true\n\n[target.'cfg(target_os = \"macos\")'.dependencies]\ncore-foundation.workspace = true\n\n[target.'cfg(unix)'.dependencies]\nlibc.workspace = true\n\n[target.'cfg(windows)'.dependencies]\nmiow.workspace = true\nwindows-sys = { workspace = true, features = [\"Win32_Storage_FileSystem\", \"Win32_Foundation\", \"Win32_System_Console\"] }\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/cargo-util/README.md",
    "content": "> This crate is maintained by the Cargo team, primarily for use by Cargo\n> and not intended for external use (except as a transitive dependency). This\n> crate may make major changes to its APIs or be deprecated without warning.\n"
  },
  {
    "path": "crates/cargo-util/src/du.rs",
    "content": "//! A simple disk usage estimator.\n\nuse anyhow::{Context, Result};\nuse ignore::overrides::OverrideBuilder;\nuse ignore::{WalkBuilder, WalkState};\nuse std::path::Path;\nuse std::sync::{Arc, Mutex};\n\n/// Determines the disk usage of all files in the given directory.\n///\n/// The given patterns are gitignore style patterns relative to the given\n/// path. If there are patterns, it will only count things matching that\n/// pattern. `!` can be used to exclude things. See [`OverrideBuilder::add`]\n/// for more info.\n///\n/// This is a primitive implementation that doesn't handle hard links, and\n/// isn't particularly fast (for example, not using `getattrlistbulk` on\n/// macOS). It also only uses actual byte sizes instead of block counts (and\n/// thus vastly undercounts directories with lots of small files). It would be\n/// nice to improve this or replace it with something better.\npub fn du(path: &Path, patterns: &[&str]) -> Result<u64> {\n    du_inner(path, patterns).with_context(|| format!(\"failed to walk `{}`\", path.display()))\n}\n\nfn du_inner(path: &Path, patterns: &[&str]) -> Result<u64> {\n    let mut builder = OverrideBuilder::new(path);\n    for pattern in patterns {\n        builder.add(pattern)?;\n    }\n    let overrides = builder.build()?;\n\n    let mut builder = WalkBuilder::new(path);\n    builder\n        .overrides(overrides)\n        .hidden(false)\n        .parents(false)\n        .ignore(false)\n        .git_global(false)\n        .git_ignore(false)\n        .git_exclude(false);\n    let walker = builder.build_parallel();\n\n    // Platforms like PowerPC don't support AtomicU64, so we use a Mutex instead.\n    //\n    // See:\n    // - https://github.com/rust-lang/cargo/pull/12981\n    // - https://github.com/rust-lang/rust/pull/117916#issuecomment-1812635848\n    let total = Arc::new(Mutex::new(0u64));\n\n    // A slot used to indicate there was an error while walking.\n    //\n    // It is possible that more than one error happens (such as in different\n    // threads). The error returned is arbitrary in that case.\n    let err = Arc::new(Mutex::new(None));\n    walker.run(|| {\n        Box::new(|entry| {\n            match entry {\n                Ok(entry) => match entry.metadata() {\n                    Ok(meta) => {\n                        if meta.is_file() {\n                            let mut lock = total.lock().unwrap();\n                            *lock += meta.len();\n                        }\n                    }\n                    Err(e) => {\n                        *err.lock().unwrap() = Some(e.into());\n                        return WalkState::Quit;\n                    }\n                },\n                Err(e) => {\n                    *err.lock().unwrap() = Some(e.into());\n                    return WalkState::Quit;\n                }\n            }\n            WalkState::Continue\n        })\n    });\n\n    if let Some(e) = err.lock().unwrap().take() {\n        return Err(e);\n    }\n\n    let total = *total.lock().unwrap();\n    Ok(total)\n}\n"
  },
  {
    "path": "crates/cargo-util/src/lib.rs",
    "content": "//! Miscellaneous support code used by Cargo.\n//!\n//! > This crate is maintained by the Cargo team, primarily for use by Cargo\n//! > and not intended for external use (except as a transitive dependency). This\n//! > crate may make major changes to its APIs or be deprecated without warning.\n\n#![allow(clippy::disallowed_methods)]\n\npub use self::read2::read2;\npub use du::du;\npub use process_builder::ProcessBuilder;\npub use process_error::{ProcessError, exit_status_to_string, is_simple_exit_code};\npub use sha256::Sha256;\n\nmod du;\npub mod paths;\nmod process_builder;\nmod process_error;\nmod read2;\npub mod registry;\nmod sha256;\n\n/// Whether or not this running in a Continuous Integration environment.\npub fn is_ci() -> bool {\n    std::env::var(\"CI\").is_ok() || std::env::var(\"TF_BUILD\").is_ok()\n}\n"
  },
  {
    "path": "crates/cargo-util/src/paths.rs",
    "content": "//! Various utilities for working with files and paths.\n\nuse anyhow::{Context, Result};\nuse filetime::FileTime;\nuse std::env;\nuse std::ffi::{OsStr, OsString};\nuse std::fs::{self, File, Metadata, OpenOptions};\nuse std::io;\nuse std::io::prelude::*;\nuse std::iter;\nuse std::path::{Component, Path, PathBuf};\nuse tempfile::Builder as TempFileBuilder;\n\n/// Joins paths into a string suitable for the `PATH` environment variable.\n///\n/// This is equivalent to [`std::env::join_paths`], but includes a more\n/// detailed error message. The given `env` argument is the name of the\n/// environment variable this is will be used for, which is included in the\n/// error message.\npub fn join_paths<T: AsRef<OsStr>>(paths: &[T], env: &str) -> Result<OsString> {\n    env::join_paths(paths.iter()).with_context(|| {\n        let mut message = format!(\n            \"failed to join paths from `${env}` together\\n\\n\\\n             Check if any of path segments listed below contain an \\\n             unterminated quote character or path separator:\"\n        );\n        for path in paths {\n            use std::fmt::Write;\n            write!(&mut message, \"\\n    {:?}\", Path::new(path)).unwrap();\n        }\n\n        message\n    })\n}\n\n/// Returns the name of the environment variable used for searching for\n/// dynamic libraries.\npub fn dylib_path_envvar() -> &'static str {\n    if cfg!(windows) {\n        \"PATH\"\n    } else if cfg!(target_os = \"macos\") {\n        // When loading and linking a dynamic library or bundle, dlopen\n        // searches in LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, PWD, and\n        // DYLD_FALLBACK_LIBRARY_PATH.\n        // In the Mach-O format, a dynamic library has an \"install path.\"\n        // Clients linking against the library record this path, and the\n        // dynamic linker, dyld, uses it to locate the library.\n        // dyld searches DYLD_LIBRARY_PATH *before* the install path.\n        // dyld searches DYLD_FALLBACK_LIBRARY_PATH only if it cannot\n        // find the library in the install path.\n        // Setting DYLD_LIBRARY_PATH can easily have unintended\n        // consequences.\n        //\n        // Also, DYLD_LIBRARY_PATH appears to have significant performance\n        // penalty starting in 10.13. Cargo's testsuite ran more than twice as\n        // slow with it on CI.\n        \"DYLD_FALLBACK_LIBRARY_PATH\"\n    } else if cfg!(target_os = \"aix\") {\n        \"LIBPATH\"\n    } else {\n        \"LD_LIBRARY_PATH\"\n    }\n}\n\n/// Returns a list of directories that are searched for dynamic libraries.\n///\n/// Note that some operating systems will have defaults if this is empty that\n/// will need to be dealt with.\npub fn dylib_path() -> Vec<PathBuf> {\n    match env::var_os(dylib_path_envvar()) {\n        Some(var) => env::split_paths(&var).collect(),\n        None => Vec::new(),\n    }\n}\n\n/// Normalize a path, removing things like `.` and `..`.\n///\n/// CAUTION: This does not resolve symlinks (unlike\n/// [`std::fs::canonicalize`]). This may cause incorrect or surprising\n/// behavior at times. This should be used carefully. Unfortunately,\n/// [`std::fs::canonicalize`] can be hard to use correctly, since it can often\n/// fail, or on Windows returns annoying device paths. This is a problem Cargo\n/// needs to improve on.\npub fn normalize_path(path: &Path) -> PathBuf {\n    let mut components = path.components().peekable();\n    let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {\n        components.next();\n        PathBuf::from(c.as_os_str())\n    } else {\n        PathBuf::new()\n    };\n\n    for component in components {\n        match component {\n            Component::Prefix(..) => unreachable!(),\n            Component::RootDir => {\n                ret.push(Component::RootDir);\n            }\n            Component::CurDir => {}\n            Component::ParentDir => {\n                if ret.ends_with(Component::ParentDir) {\n                    ret.push(Component::ParentDir);\n                } else {\n                    let popped = ret.pop();\n                    if !popped && !ret.has_root() {\n                        ret.push(Component::ParentDir);\n                    }\n                }\n            }\n            Component::Normal(c) => {\n                ret.push(c);\n            }\n        }\n    }\n    ret\n}\n\n/// Returns the absolute path of where the given executable is located based\n/// on searching the `PATH` environment variable.\n///\n/// Returns an error if it cannot be found.\npub fn resolve_executable(exec: &Path) -> Result<PathBuf> {\n    if exec.components().count() == 1 {\n        let paths = env::var_os(\"PATH\").ok_or_else(|| anyhow::format_err!(\"no PATH\"))?;\n        let candidates = env::split_paths(&paths).flat_map(|path| {\n            let candidate = path.join(&exec);\n            let with_exe = if env::consts::EXE_EXTENSION.is_empty() {\n                None\n            } else {\n                Some(candidate.with_extension(env::consts::EXE_EXTENSION))\n            };\n            iter::once(candidate).chain(with_exe)\n        });\n        for candidate in candidates {\n            if candidate.is_file() {\n                return Ok(candidate);\n            }\n        }\n\n        anyhow::bail!(\"no executable for `{}` found in PATH\", exec.display())\n    } else {\n        Ok(exec.into())\n    }\n}\n\n/// Returns metadata for a file (follows symlinks).\n///\n/// Equivalent to [`std::fs::metadata`] with better error messages.\npub fn metadata<P: AsRef<Path>>(path: P) -> Result<Metadata> {\n    let path = path.as_ref();\n    std::fs::metadata(path)\n        .with_context(|| format!(\"failed to load metadata for path `{}`\", path.display()))\n}\n\n/// Returns metadata for a file without following symlinks.\n///\n/// Equivalent to [`std::fs::metadata`] with better error messages.\npub fn symlink_metadata<P: AsRef<Path>>(path: P) -> Result<Metadata> {\n    let path = path.as_ref();\n    std::fs::symlink_metadata(path)\n        .with_context(|| format!(\"failed to load metadata for path `{}`\", path.display()))\n}\n\n/// Reads a file to a string.\n///\n/// Equivalent to [`std::fs::read_to_string`] with better error messages.\npub fn read(path: &Path) -> Result<String> {\n    match String::from_utf8(read_bytes(path)?) {\n        Ok(s) => Ok(s),\n        Err(_) => anyhow::bail!(\"path at `{}` was not valid utf-8\", path.display()),\n    }\n}\n\n/// Reads a file into a bytes vector.\n///\n/// Equivalent to [`std::fs::read`] with better error messages.\npub fn read_bytes(path: &Path) -> Result<Vec<u8>> {\n    fs::read(path).with_context(|| format!(\"failed to read `{}`\", path.display()))\n}\n\n/// Writes a file to disk.\n///\n/// Equivalent to [`std::fs::write`] with better error messages.\npub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()> {\n    let path = path.as_ref();\n    fs::write(path, contents.as_ref())\n        .with_context(|| format!(\"failed to write `{}`\", path.display()))\n}\n\n/// Writes a file to disk atomically.\n///\n/// This uses `tempfile::persist` to accomplish atomic writes.\n/// If the path is a symlink, it will follow the symlink and write to the actual target.\npub fn write_atomic<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()> {\n    let path = path.as_ref();\n\n    // Check if the path is a symlink and follow it if it is\n    let resolved_path;\n    let path = if path.is_symlink() {\n        resolved_path = fs::read_link(path)\n            .with_context(|| format!(\"failed to read symlink at `{}`\", path.display()))?;\n        &resolved_path\n    } else {\n        path\n    };\n\n    // On unix platforms, get the permissions of the original file. Copy only the user/group/other\n    // read/write/execute permission bits. The tempfile lib defaults to an initial mode of 0o600,\n    // and we'll set the proper permissions after creating the file.\n    #[cfg(unix)]\n    let perms = path.metadata().ok().map(|meta| {\n        use std::os::unix::fs::PermissionsExt;\n\n        // these constants are u16 on macOS\n        let mask = u32::from(libc::S_IRWXU | libc::S_IRWXG | libc::S_IRWXO);\n        let mode = meta.permissions().mode() & mask;\n\n        std::fs::Permissions::from_mode(mode)\n    });\n\n    let mut tmp = TempFileBuilder::new()\n        .prefix(path.file_name().unwrap())\n        .tempfile_in(path.parent().unwrap())?;\n    tmp.write_all(contents.as_ref())?;\n\n    // On unix platforms, set the permissions on the newly created file. We can use fchmod (called\n    // by the std lib; subject to change) which ignores the umask so that the new file has the same\n    // permissions as the old file.\n    #[cfg(unix)]\n    if let Some(perms) = perms {\n        tmp.as_file().set_permissions(perms)?;\n    }\n\n    tmp.persist(path)?;\n    Ok(())\n}\n\n/// Equivalent to [`write()`], but does not write anything if the file contents\n/// are identical to the given contents.\npub fn write_if_changed<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()> {\n    (|| -> Result<()> {\n        let contents = contents.as_ref();\n        let mut f = OpenOptions::new()\n            .read(true)\n            .write(true)\n            .create(true)\n            .open(&path)?;\n        let mut orig = Vec::new();\n        f.read_to_end(&mut orig)?;\n        if orig != contents {\n            f.set_len(0)?;\n            f.seek(io::SeekFrom::Start(0))?;\n            f.write_all(contents)?;\n        }\n        Ok(())\n    })()\n    .with_context(|| format!(\"failed to write `{}`\", path.as_ref().display()))?;\n    Ok(())\n}\n\n/// Equivalent to [`write()`], but appends to the end instead of replacing the\n/// contents.\npub fn append(path: &Path, contents: &[u8]) -> Result<()> {\n    (|| -> Result<()> {\n        let mut f = OpenOptions::new()\n            .write(true)\n            .append(true)\n            .create(true)\n            .open(path)?;\n\n        f.write_all(contents)?;\n        Ok(())\n    })()\n    .with_context(|| format!(\"failed to write `{}`\", path.display()))?;\n    Ok(())\n}\n\n/// Creates a new file.\npub fn create<P: AsRef<Path>>(path: P) -> Result<File> {\n    let path = path.as_ref();\n    File::create(path).with_context(|| format!(\"failed to create file `{}`\", path.display()))\n}\n\n/// Opens an existing file.\npub fn open<P: AsRef<Path>>(path: P) -> Result<File> {\n    let path = path.as_ref();\n    File::open(path).with_context(|| format!(\"failed to open file `{}`\", path.display()))\n}\n\n/// Returns the last modification time of a file.\npub fn mtime(path: &Path) -> Result<FileTime> {\n    let meta = metadata(path)?;\n    Ok(FileTime::from_last_modification_time(&meta))\n}\n\n/// Returns the maximum mtime of the given path, recursing into\n/// subdirectories, and following symlinks.\npub fn mtime_recursive(path: &Path) -> Result<FileTime> {\n    let meta = metadata(path)?;\n    if !meta.is_dir() {\n        return Ok(FileTime::from_last_modification_time(&meta));\n    }\n    let max_meta = walkdir::WalkDir::new(path)\n        .follow_links(true)\n        .into_iter()\n        .filter_map(|e| match e {\n            Ok(e) => Some(e),\n            Err(e) => {\n                // Ignore errors while walking. If Cargo can't access it, the\n                // build script probably can't access it, either.\n                tracing::debug!(\"failed to determine mtime while walking directory: {}\", e);\n                None\n            }\n        })\n        .filter_map(|e| {\n            if e.path_is_symlink() {\n                // Use the mtime of both the symlink and its target, to\n                // handle the case where the symlink is modified to a\n                // different target.\n                let sym_meta = match std::fs::symlink_metadata(e.path()) {\n                    Ok(m) => m,\n                    Err(err) => {\n                        // I'm not sure when this is really possible (maybe a\n                        // race with unlinking?). Regardless, if Cargo can't\n                        // read it, the build script probably can't either.\n                        tracing::debug!(\n                            \"failed to determine mtime while fetching symlink metadata of {}: {}\",\n                            e.path().display(),\n                            err\n                        );\n                        return None;\n                    }\n                };\n                let sym_mtime = FileTime::from_last_modification_time(&sym_meta);\n                // Walkdir follows symlinks.\n                match e.metadata() {\n                    Ok(target_meta) => {\n                        let target_mtime = FileTime::from_last_modification_time(&target_meta);\n                        Some(sym_mtime.max(target_mtime))\n                    }\n                    Err(err) => {\n                        // Can't access the symlink target. If Cargo can't\n                        // access it, the build script probably can't access\n                        // it either.\n                        tracing::debug!(\n                            \"failed to determine mtime of symlink target for {}: {}\",\n                            e.path().display(),\n                            err\n                        );\n                        Some(sym_mtime)\n                    }\n                }\n            } else {\n                let meta = match e.metadata() {\n                    Ok(m) => m,\n                    Err(err) => {\n                        // I'm not sure when this is really possible (maybe a\n                        // race with unlinking?). Regardless, if Cargo can't\n                        // read it, the build script probably can't either.\n                        tracing::debug!(\n                            \"failed to determine mtime while fetching metadata of {}: {}\",\n                            e.path().display(),\n                            err\n                        );\n                        return None;\n                    }\n                };\n                Some(FileTime::from_last_modification_time(&meta))\n            }\n        })\n        .max()\n        // or_else handles the case where there are no files in the directory.\n        .unwrap_or_else(|| FileTime::from_last_modification_time(&meta));\n    Ok(max_meta)\n}\n\n/// Record the current time on the filesystem (using the filesystem's clock)\n/// using a file at the given directory. Returns the current time.\npub fn set_invocation_time(path: &Path) -> Result<FileTime> {\n    // note that if `FileTime::from_system_time(SystemTime::now());` is determined to be sufficient,\n    // then this can be removed.\n    let timestamp = path.join(\"invoked.timestamp\");\n    write(\n        &timestamp,\n        \"This file has an mtime of when this was started.\",\n    )?;\n    let ft = mtime(&timestamp)?;\n    tracing::debug!(\"invocation time for {:?} is {}\", path, ft);\n    Ok(ft)\n}\n\n/// Converts a path to UTF-8 bytes.\npub fn path2bytes(path: &Path) -> Result<&[u8]> {\n    #[cfg(unix)]\n    {\n        use std::os::unix::prelude::*;\n        Ok(path.as_os_str().as_bytes())\n    }\n    #[cfg(windows)]\n    {\n        match path.as_os_str().to_str() {\n            Some(s) => Ok(s.as_bytes()),\n            None => Err(anyhow::format_err!(\n                \"invalid non-unicode path: {}\",\n                path.display()\n            )),\n        }\n    }\n}\n\n/// Converts UTF-8 bytes to a path.\npub fn bytes2path(bytes: &[u8]) -> Result<PathBuf> {\n    #[cfg(unix)]\n    {\n        use std::os::unix::prelude::*;\n        Ok(PathBuf::from(OsStr::from_bytes(bytes)))\n    }\n    #[cfg(windows)]\n    {\n        use std::str;\n        match str::from_utf8(bytes) {\n            Ok(s) => Ok(PathBuf::from(s)),\n            Err(..) => Err(anyhow::format_err!(\"invalid non-unicode path\")),\n        }\n    }\n}\n\n/// Returns an iterator that walks up the directory hierarchy towards the root.\n///\n/// Each item is a [`Path`]. It will start with the given path, finishing at\n/// the root. If the `stop_root_at` parameter is given, it will stop at the\n/// given path (which will be the last item).\npub fn ancestors<'a>(path: &'a Path, stop_root_at: Option<&Path>) -> PathAncestors<'a> {\n    PathAncestors::new(path, stop_root_at)\n}\n\npub struct PathAncestors<'a> {\n    current: Option<&'a Path>,\n    stop_at: Option<PathBuf>,\n}\n\nimpl<'a> PathAncestors<'a> {\n    fn new(path: &'a Path, stop_root_at: Option<&Path>) -> PathAncestors<'a> {\n        let stop_at = env::var(\"__CARGO_TEST_ROOT\")\n            .ok()\n            .map(PathBuf::from)\n            .or_else(|| stop_root_at.map(|p| p.to_path_buf()));\n        PathAncestors {\n            current: Some(path),\n            //HACK: avoid reading `~/.cargo/config` when testing Cargo itself.\n            stop_at,\n        }\n    }\n}\n\nimpl<'a> Iterator for PathAncestors<'a> {\n    type Item = &'a Path;\n\n    fn next(&mut self) -> Option<&'a Path> {\n        if let Some(path) = self.current {\n            self.current = path.parent();\n\n            if let Some(ref stop_at) = self.stop_at {\n                if path == stop_at {\n                    self.current = None;\n                }\n            }\n\n            Some(path)\n        } else {\n            None\n        }\n    }\n}\n\n/// Equivalent to [`std::fs::create_dir_all`] with better error messages.\npub fn create_dir_all(p: impl AsRef<Path>) -> Result<()> {\n    _create_dir_all(p.as_ref())\n}\n\nfn _create_dir_all(p: &Path) -> Result<()> {\n    fs::create_dir_all(p)\n        .with_context(|| format!(\"failed to create directory `{}`\", p.display()))?;\n    Ok(())\n}\n\n/// Equivalent to [`std::fs::remove_dir_all`] with better error messages.\n///\n/// This does *not* follow symlinks.\npub fn remove_dir_all<P: AsRef<Path>>(p: P) -> Result<()> {\n    _remove_dir_all(p.as_ref()).or_else(|prev_err| {\n        // `std::fs::remove_dir_all` is highly specialized for different platforms\n        // and may be more reliable than a simple walk. We try the walk first in\n        // order to report more detailed errors.\n        fs::remove_dir_all(p.as_ref()).with_context(|| {\n            format!(\n                \"{:?}\\n\\nError: failed to remove directory `{}`\",\n                prev_err,\n                p.as_ref().display(),\n            )\n        })\n    })\n}\n\nfn _remove_dir_all(p: &Path) -> Result<()> {\n    if symlink_metadata(p)?.is_symlink() {\n        return remove_file(p);\n    }\n    let entries = p\n        .read_dir()\n        .with_context(|| format!(\"failed to read directory `{}`\", p.display()))?;\n    for entry in entries {\n        let entry = entry?;\n        let path = entry.path();\n        if entry.file_type()?.is_dir() {\n            remove_dir_all(&path)?;\n        } else {\n            remove_file(&path)?;\n        }\n    }\n    remove_dir(&p)\n}\n\n/// Equivalent to [`std::fs::remove_dir`] with better error messages.\npub fn remove_dir<P: AsRef<Path>>(p: P) -> Result<()> {\n    _remove_dir(p.as_ref())\n}\n\nfn _remove_dir(p: &Path) -> Result<()> {\n    fs::remove_dir(p).with_context(|| format!(\"failed to remove directory `{}`\", p.display()))?;\n    Ok(())\n}\n\n/// Equivalent to [`std::fs::remove_file`] with better error messages.\n///\n/// If the file is readonly, this will attempt to change the permissions to\n/// force the file to be deleted.\n/// On Windows, if the file is a symlink to a directory, this will attempt to remove\n/// the symlink itself.\npub fn remove_file<P: AsRef<Path>>(p: P) -> Result<()> {\n    _remove_file(p.as_ref())\n}\n\nfn _remove_file(p: &Path) -> Result<()> {\n    // For Windows, we need to check if the file is a symlink to a directory\n    // and remove the symlink itself by calling `remove_dir` instead of\n    // `remove_file`.\n    #[cfg(target_os = \"windows\")]\n    {\n        use std::os::windows::fs::FileTypeExt;\n        let metadata = symlink_metadata(p)?;\n        let file_type = metadata.file_type();\n        if file_type.is_symlink_dir() {\n            return remove_symlink_dir_with_permission_check(p);\n        }\n    }\n\n    remove_file_with_permission_check(p)\n}\n\n#[cfg(target_os = \"windows\")]\nfn remove_symlink_dir_with_permission_check(p: &Path) -> Result<()> {\n    remove_with_permission_check(fs::remove_dir, p)\n        .with_context(|| format!(\"failed to remove symlink dir `{}`\", p.display()))\n}\n\nfn remove_file_with_permission_check(p: &Path) -> Result<()> {\n    remove_with_permission_check(fs::remove_file, p)\n        .with_context(|| format!(\"failed to remove file `{}`\", p.display()))\n}\n\nfn remove_with_permission_check<F, P>(remove_func: F, p: P) -> io::Result<()>\nwhere\n    F: Fn(P) -> io::Result<()>,\n    P: AsRef<Path> + Clone,\n{\n    match remove_func(p.clone()) {\n        Ok(()) => Ok(()),\n        Err(e) => {\n            if e.kind() == io::ErrorKind::PermissionDenied\n                && set_not_readonly(p.as_ref()).unwrap_or(false)\n            {\n                remove_func(p)\n            } else {\n                Err(e)\n            }\n        }\n    }\n}\n\nfn set_not_readonly(p: &Path) -> io::Result<bool> {\n    let mut perms = p.metadata()?.permissions();\n    if !perms.readonly() {\n        return Ok(false);\n    }\n    perms.set_readonly(false);\n    fs::set_permissions(p, perms)?;\n    Ok(true)\n}\n\n/// Hardlink (file) or symlink (dir) src to dst if possible, otherwise copy it.\n///\n/// If the destination already exists, it is removed before linking.\npub fn link_or_copy(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {\n    let src = src.as_ref();\n    let dst = dst.as_ref();\n    _link_or_copy(src, dst)\n}\n\nfn _link_or_copy(src: &Path, dst: &Path) -> Result<()> {\n    tracing::debug!(\"linking {} to {}\", src.display(), dst.display());\n    if same_file::is_same_file(src, dst).unwrap_or(false) {\n        return Ok(());\n    }\n\n    // NB: we can't use dst.exists(), as if dst is a broken symlink,\n    // dst.exists() will return false. This is problematic, as we still need to\n    // unlink dst in this case. symlink_metadata(dst).is_ok() will tell us\n    // whether dst exists *without* following symlinks, which is what we want.\n    if fs::symlink_metadata(dst).is_ok() {\n        remove_file(&dst)?;\n    }\n\n    let link_result = if src.is_dir() {\n        #[cfg(unix)]\n        use std::os::unix::fs::symlink;\n        #[cfg(windows)]\n        // FIXME: This should probably panic or have a copy fallback. Symlinks\n        // are not supported in all windows environments. Currently symlinking\n        // is only used for .dSYM directories on macos, but this shouldn't be\n        // accidentally relied upon.\n        use std::os::windows::fs::symlink_dir as symlink;\n\n        let dst_dir = dst.parent().unwrap();\n        let src = if src.starts_with(dst_dir) {\n            src.strip_prefix(dst_dir).unwrap()\n        } else {\n            src\n        };\n        symlink(src, dst)\n    } else {\n        if cfg!(target_os = \"macos\") {\n            // There seems to be a race condition with APFS when hard-linking\n            // binaries. Gatekeeper does not have signing or hash information\n            // stored in kernel when running the process. Therefore killing it.\n            // This problem does not appear when copying files as kernel has\n            // time to process it. Note that: fs::copy on macos is using\n            // CopyOnWrite (syscall fclonefileat) which should be as fast as\n            // hardlinking. See these issues for the details:\n            //\n            // * https://github.com/rust-lang/cargo/issues/7821\n            // * https://github.com/rust-lang/cargo/issues/10060\n            fs::copy(src, dst).map_or_else(\n                |e| {\n                    if e.raw_os_error()\n                        .map_or(false, |os_err| os_err == 35 /* libc::EAGAIN */)\n                    {\n                        tracing::info!(\"copy failed {e:?}. falling back to fs::hard_link\");\n\n                        // Working around an issue copying too fast with zfs (probably related to\n                        // https://github.com/openzfsonosx/zfs/issues/809)\n                        // See https://github.com/rust-lang/cargo/issues/13838\n                        fs::hard_link(src, dst)\n                    } else {\n                        Err(e)\n                    }\n                },\n                |_| Ok(()),\n            )\n        } else {\n            fs::hard_link(src, dst)\n        }\n    };\n    link_result\n        .or_else(|err| {\n            tracing::debug!(\"link failed {}. falling back to fs::copy\", err);\n            fs::copy(src, dst).map(|_| ())\n        })\n        .with_context(|| {\n            format!(\n                \"failed to link or copy `{}` to `{}`\",\n                src.display(),\n                dst.display()\n            )\n        })?;\n    Ok(())\n}\n\n/// Copies a file from one location to another.\n///\n/// Equivalent to [`std::fs::copy`] with better error messages.\npub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<u64> {\n    let from = from.as_ref();\n    let to = to.as_ref();\n    fs::copy(from, to)\n        .with_context(|| format!(\"failed to copy `{}` to `{}`\", from.display(), to.display()))\n}\n\n/// Changes the filesystem mtime (and atime if possible) for the given file.\n///\n/// This intentionally does not return an error, as this is sometimes not\n/// supported on network filesystems. For the current uses in Cargo, this is a\n/// \"best effort\" approach, and errors shouldn't be propagated.\npub fn set_file_time_no_err<P: AsRef<Path>>(path: P, time: FileTime) {\n    let path = path.as_ref();\n    match filetime::set_file_times(path, time, time) {\n        Ok(()) => tracing::debug!(\"set file mtime {} to {}\", path.display(), time),\n        Err(e) => tracing::warn!(\n            \"could not set mtime of {} to {}: {:?}\",\n            path.display(),\n            time,\n            e\n        ),\n    }\n}\n\n/// Strips `base` from `path`.\n///\n/// This canonicalizes both paths before stripping. This is useful if the\n/// paths are obtained in different ways, and one or the other may or may not\n/// have been normalized in some way.\npub fn strip_prefix_canonical(\n    path: impl AsRef<Path>,\n    base: impl AsRef<Path>,\n) -> Result<PathBuf, std::path::StripPrefixError> {\n    // Not all filesystems support canonicalize. Just ignore if it doesn't work.\n    let safe_canonicalize = |path: &Path| match path.canonicalize() {\n        Ok(p) => p,\n        Err(e) => {\n            tracing::warn!(\"cannot canonicalize {:?}: {:?}\", path, e);\n            path.to_path_buf()\n        }\n    };\n    let canon_path = safe_canonicalize(path.as_ref());\n    let canon_base = safe_canonicalize(base.as_ref());\n    canon_path.strip_prefix(canon_base).map(|p| p.to_path_buf())\n}\n\n/// Creates an excluded from cache directory atomically with its parents as needed.\n///\n/// The atomicity only covers creating the leaf directory and exclusion from cache. Any missing\n/// parent directories will not be created in an atomic manner.\n///\n/// This function is idempotent and in addition to that it won't exclude ``p`` from cache if it\n/// already exists.\npub fn create_dir_all_excluded_from_backups_atomic(p: impl AsRef<Path>) -> Result<()> {\n    let path = p.as_ref();\n    if path.is_dir() {\n        return Ok(());\n    }\n\n    let parent = path.parent().unwrap();\n    let base = path.file_name().unwrap();\n    create_dir_all(parent)?;\n    // We do this in two steps (first create a temporary directory and exclude\n    // it from backups, then rename it to the desired name. If we created the\n    // directory directly where it should be and then excluded it from backups\n    // we would risk a situation where cargo is interrupted right after the directory\n    // creation but before the exclusion the directory would remain non-excluded from\n    // backups because we only perform exclusion right after we created the directory\n    // ourselves.\n    //\n    // We need the tempdir created in parent instead of $TMP, because only then we can be\n    // easily sure that rename() will succeed (the new name needs to be on the same mount\n    // point as the old one).\n    let tempdir = TempFileBuilder::new().prefix(base).tempdir_in(parent)?;\n    exclude_from_backups(tempdir.path());\n    exclude_from_content_indexing(tempdir.path());\n    // Previously std::fs::create_dir_all() (through paths::create_dir_all()) was used\n    // here to create the directory directly and fs::create_dir_all() explicitly treats\n    // the directory being created concurrently by another thread or process as success,\n    // hence the check below to follow the existing behavior. If we get an error at\n    // rename() and suddenly the directory (which didn't exist a moment earlier) exists\n    // we can infer from it's another cargo process doing work.\n    if let Err(e) = fs::rename(tempdir.path(), path) {\n        if !path.exists() {\n            return Err(anyhow::Error::from(e))\n                .with_context(|| format!(\"failed to create directory `{}`\", path.display()));\n        }\n    }\n    Ok(())\n}\n\n/// Mark an existing directory as excluded from backups and indexing.\n///\n/// Errors in marking it are ignored.\npub fn exclude_from_backups_and_indexing(p: impl AsRef<Path>) {\n    let path = p.as_ref();\n    exclude_from_backups(path);\n    exclude_from_content_indexing(path);\n}\n\n/// Marks the directory as excluded from archives/backups.\n///\n/// This is recommended to prevent derived/temporary files from bloating backups. There are two\n/// mechanisms used to achieve this right now:\n///\n/// * A dedicated resource property excluding from Time Machine backups on macOS\n/// * CACHEDIR.TAG files supported by various tools in a platform-independent way\nfn exclude_from_backups(path: &Path) {\n    exclude_from_time_machine_and_cloud_sync(path);\n    let file = path.join(\"CACHEDIR.TAG\");\n    if !file.exists() {\n        let _ = std::fs::write(\n            file,\n            \"Signature: 8a477f597d28d172789f06886806bc55\n# This file is a cache directory tag created by cargo.\n# For information about cache directory tags see https://bford.info/cachedir/\n\",\n        );\n        // Similarly to exclude_from_time_machine_and_cloud_sync() we ignore errors here as it's an optional feature.\n    }\n}\n\n/// Marks the directory as excluded from content indexing.\n///\n/// This is recommended to prevent the content of derived/temporary files from being indexed.\n/// This is very important for Windows users, as the live content indexing significantly slows\n/// cargo's I/O operations.\n///\n/// This is currently a no-op on non-Windows platforms.\nfn exclude_from_content_indexing(path: &Path) {\n    #[cfg(windows)]\n    {\n        use std::iter::once;\n        use std::os::windows::prelude::OsStrExt;\n        use windows_sys::Win32::Storage::FileSystem::{\n            FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, GetFileAttributesW, SetFileAttributesW,\n        };\n\n        let path: Vec<u16> = path.as_os_str().encode_wide().chain(once(0)).collect();\n        unsafe {\n            SetFileAttributesW(\n                path.as_ptr(),\n                GetFileAttributesW(path.as_ptr()) | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,\n            );\n        }\n    }\n    #[cfg(not(windows))]\n    {\n        let _ = path;\n    }\n}\n\n#[cfg(not(target_os = \"macos\"))]\nfn exclude_from_time_machine_and_cloud_sync(_: &Path) {}\n\n#[cfg(target_os = \"macos\")]\n/// Marks files or directories as excluded from Time Machine and iCloud Drive on macOS\nfn exclude_from_time_machine_and_cloud_sync(path: &Path) {\n    use core_foundation::base::TCFType;\n    use core_foundation::{number, string, url};\n    use std::ptr;\n\n    let path = match url::CFURL::from_path(path, false) {\n        Some(url) => url,\n        None => return,\n    };\n\n    // For compatibility with old systems strings are used instead of global symbols\n    const KEY_NAMES: [&str; 2] = [\n        \"NSURLIsExcludedFromBackupKey\", // kCFURLIsExcludedFromBackupKey\n        \"NSURLUbiquitousItemIsExcludedFromSyncKey\", // kCFURLUbiquitousItemIsExcludedFromSyncKey\n    ];\n\n    for key_name in KEY_NAMES {\n        let is_excluded_key = match key_name.parse::<string::CFString>() {\n            Ok(key) => key,\n            Err(_) => continue,\n        };\n        unsafe {\n            url::CFURLSetResourcePropertyForKey(\n                path.as_concrete_TypeRef(),\n                is_excluded_key.as_concrete_TypeRef(),\n                number::kCFBooleanTrue as *const _,\n                ptr::null_mut(),\n            );\n        }\n    }\n    // Errors are ignored, since it's an optional feature and failure\n    // doesn't prevent Cargo from working\n}\n\n#[cfg(test)]\nmod tests {\n    use super::join_paths;\n    use super::normalize_path;\n    use super::write;\n    use super::write_atomic;\n\n    #[test]\n    fn test_normalize_path() {\n        let cases = &[\n            (\"\", \"\"),\n            (\".\", \"\"),\n            (\".////./.\", \"\"),\n            (\"/\", \"/\"),\n            (\"/..\", \"/\"),\n            (\"/foo/bar\", \"/foo/bar\"),\n            (\"/foo/bar/\", \"/foo/bar\"),\n            (\"/foo/bar/./././///\", \"/foo/bar\"),\n            (\"/foo/bar/..\", \"/foo\"),\n            (\"/foo/bar/../..\", \"/\"),\n            (\"/foo/bar/../../..\", \"/\"),\n            (\"foo/bar\", \"foo/bar\"),\n            (\"foo/bar/\", \"foo/bar\"),\n            (\"foo/bar/./././///\", \"foo/bar\"),\n            (\"foo/bar/..\", \"foo\"),\n            (\"foo/bar/../..\", \"\"),\n            (\"foo/bar/../../..\", \"..\"),\n            (\"../../foo/bar\", \"../../foo/bar\"),\n            (\"../../foo/bar/\", \"../../foo/bar\"),\n            (\"../../foo/bar/./././///\", \"../../foo/bar\"),\n            (\"../../foo/bar/..\", \"../../foo\"),\n            (\"../../foo/bar/../..\", \"../..\"),\n            (\"../../foo/bar/../../..\", \"../../..\"),\n        ];\n        for (input, expected) in cases {\n            let actual = normalize_path(std::path::Path::new(input));\n            assert_eq!(actual, std::path::Path::new(expected), \"input: {input}\");\n        }\n    }\n\n    #[test]\n    fn write_works() {\n        let original_contents = \"[dependencies]\\nfoo = 0.1.0\";\n\n        let tmpdir = tempfile::tempdir().unwrap();\n        let path = tmpdir.path().join(\"Cargo.toml\");\n        write(&path, original_contents).unwrap();\n        let contents = std::fs::read_to_string(&path).unwrap();\n        assert_eq!(contents, original_contents);\n    }\n    #[test]\n    fn write_atomic_works() {\n        let original_contents = \"[dependencies]\\nfoo = 0.1.0\";\n\n        let tmpdir = tempfile::tempdir().unwrap();\n        let path = tmpdir.path().join(\"Cargo.toml\");\n        write_atomic(&path, original_contents).unwrap();\n        let contents = std::fs::read_to_string(&path).unwrap();\n        assert_eq!(contents, original_contents);\n    }\n\n    #[test]\n    #[cfg(unix)]\n    fn write_atomic_permissions() {\n        use std::os::unix::fs::PermissionsExt;\n\n        let original_perms = std::fs::Permissions::from_mode(u32::from(\n            libc::S_IRWXU | libc::S_IRGRP | libc::S_IWGRP | libc::S_IROTH,\n        ));\n\n        let tmp = tempfile::Builder::new().tempfile().unwrap();\n\n        // need to set the permissions after creating the file to avoid umask\n        tmp.as_file()\n            .set_permissions(original_perms.clone())\n            .unwrap();\n\n        // after this call, the file at `tmp.path()` will not be the same as the file held by `tmp`\n        write_atomic(tmp.path(), \"new\").unwrap();\n        assert_eq!(std::fs::read_to_string(tmp.path()).unwrap(), \"new\");\n\n        let new_perms = std::fs::metadata(tmp.path()).unwrap().permissions();\n\n        let mask = u32::from(libc::S_IRWXU | libc::S_IRWXG | libc::S_IRWXO);\n        assert_eq!(original_perms.mode(), new_perms.mode() & mask);\n    }\n\n    #[test]\n    fn join_paths_lists_paths_on_error() {\n        let valid_paths = vec![\"/testing/one\", \"/testing/two\"];\n        // does not fail on valid input\n        let _joined = join_paths(&valid_paths, \"TESTING1\").unwrap();\n\n        #[cfg(unix)]\n        {\n            let invalid_paths = vec![\"/testing/one\", \"/testing/t:wo/three\"];\n            let err = join_paths(&invalid_paths, \"TESTING2\").unwrap_err();\n            assert_eq!(\n                err.to_string(),\n                \"failed to join paths from `$TESTING2` together\\n\\n\\\n             Check if any of path segments listed below contain an \\\n             unterminated quote character or path separator:\\\n             \\n    \\\"/testing/one\\\"\\\n             \\n    \\\"/testing/t:wo/three\\\"\\\n             \"\n            );\n        }\n        #[cfg(windows)]\n        {\n            let invalid_paths = vec![\"/testing/one\", \"/testing/t\\\"wo/three\"];\n            let err = join_paths(&invalid_paths, \"TESTING2\").unwrap_err();\n            assert_eq!(\n                err.to_string(),\n                \"failed to join paths from `$TESTING2` together\\n\\n\\\n             Check if any of path segments listed below contain an \\\n             unterminated quote character or path separator:\\\n             \\n    \\\"/testing/one\\\"\\\n             \\n    \\\"/testing/t\\\\\\\"wo/three\\\"\\\n             \"\n            );\n        }\n    }\n\n    #[test]\n    fn write_atomic_symlink() {\n        let tmpdir = tempfile::tempdir().unwrap();\n        let target_path = tmpdir.path().join(\"target.txt\");\n        let symlink_path = tmpdir.path().join(\"symlink.txt\");\n\n        // Create initial file\n        write(&target_path, \"initial\").unwrap();\n\n        // Create symlink\n        #[cfg(unix)]\n        std::os::unix::fs::symlink(&target_path, &symlink_path).unwrap();\n        #[cfg(windows)]\n        std::os::windows::fs::symlink_file(&target_path, &symlink_path).unwrap();\n\n        // Write through symlink\n        write_atomic(&symlink_path, \"updated\").unwrap();\n\n        // Verify both paths show the updated content\n        assert_eq!(std::fs::read_to_string(&target_path).unwrap(), \"updated\");\n        assert_eq!(std::fs::read_to_string(&symlink_path).unwrap(), \"updated\");\n\n        // Verify symlink still exists and points to the same target\n        assert!(symlink_path.is_symlink());\n        assert_eq!(std::fs::read_link(&symlink_path).unwrap(), target_path);\n    }\n\n    #[test]\n    #[cfg(windows)]\n    fn test_remove_symlink_dir() {\n        use super::*;\n        use std::fs;\n        use std::os::windows::fs::symlink_dir;\n\n        let tmpdir = tempfile::tempdir().unwrap();\n        let dir_path = tmpdir.path().join(\"testdir\");\n        let symlink_path = tmpdir.path().join(\"symlink\");\n\n        fs::create_dir(&dir_path).unwrap();\n\n        symlink_dir(&dir_path, &symlink_path).expect(\"failed to create symlink\");\n\n        assert!(symlink_path.exists());\n\n        assert!(remove_file(symlink_path.clone()).is_ok());\n\n        assert!(!symlink_path.exists());\n        assert!(dir_path.exists());\n    }\n\n    #[test]\n    #[cfg(windows)]\n    fn test_remove_symlink_file() {\n        use super::*;\n        use std::fs;\n        use std::os::windows::fs::symlink_file;\n\n        let tmpdir = tempfile::tempdir().unwrap();\n        let file_path = tmpdir.path().join(\"testfile\");\n        let symlink_path = tmpdir.path().join(\"symlink\");\n\n        fs::write(&file_path, b\"test\").unwrap();\n\n        symlink_file(&file_path, &symlink_path).expect(\"failed to create symlink\");\n\n        assert!(symlink_path.exists());\n\n        assert!(remove_file(symlink_path.clone()).is_ok());\n\n        assert!(!symlink_path.exists());\n        assert!(file_path.exists());\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util/src/process_builder.rs",
    "content": "use crate::process_error::ProcessError;\nuse crate::read2;\n\nuse anyhow::{Context, Result, bail};\nuse jobserver::Client;\nuse shell_escape::escape;\nuse tempfile::NamedTempFile;\n\nuse std::collections::BTreeMap;\nuse std::env;\nuse std::ffi::{OsStr, OsString};\nuse std::fmt;\nuse std::io::{self, Write};\nuse std::iter::once;\nuse std::path::Path;\nuse std::process::{Command, ExitStatus, Output, Stdio};\n\n/// A builder object for an external process, similar to [`std::process::Command`].\n#[derive(Clone, Debug)]\npub struct ProcessBuilder {\n    /// The program to execute.\n    program: OsString,\n    /// Best-effort replacement for arg0\n    arg0: Option<OsString>,\n    /// A list of arguments to pass to the program.\n    args: Vec<OsString>,\n    /// Any environment variables that should be set for the program.\n    env: BTreeMap<String, Option<OsString>>,\n    /// The directory to run the program from.\n    cwd: Option<OsString>,\n    /// A list of wrappers that wrap the original program when calling\n    /// [`ProcessBuilder::wrapped`]. The last one is the outermost one.\n    wrappers: Vec<OsString>,\n    /// The `make` jobserver. See the [jobserver crate] for\n    /// more information.\n    ///\n    /// [jobserver crate]: https://docs.rs/jobserver/\n    jobserver: Option<Client>,\n    /// `true` to include environment variable in display.\n    display_env_vars: bool,\n    /// `true` to retry with an argfile if hitting \"command line too big\" error.\n    /// See [`ProcessBuilder::retry_with_argfile`] for more information.\n    retry_with_argfile: bool,\n    /// Data to write to stdin.\n    stdin: Option<Vec<u8>>,\n}\n\nimpl fmt::Display for ProcessBuilder {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"`\")?;\n\n        if self.display_env_vars {\n            for (key, val) in self.env.iter() {\n                if let Some(val) = val {\n                    let val = escape(val.to_string_lossy());\n                    if cfg!(windows) {\n                        write!(f, \"set {}={}&& \", key, val)?;\n                    } else {\n                        write!(f, \"{}={} \", key, val)?;\n                    }\n                }\n            }\n        }\n\n        write!(f, \"{}\", self.get_program().to_string_lossy())?;\n\n        for arg in self.get_args() {\n            write!(f, \" {}\", escape(arg.to_string_lossy()))?;\n        }\n\n        write!(f, \"`\")\n    }\n}\n\nimpl ProcessBuilder {\n    /// Creates a new [`ProcessBuilder`] with the given executable path.\n    pub fn new<T: AsRef<OsStr>>(cmd: T) -> ProcessBuilder {\n        ProcessBuilder {\n            program: cmd.as_ref().to_os_string(),\n            arg0: None,\n            args: Vec::new(),\n            cwd: None,\n            env: BTreeMap::new(),\n            wrappers: Vec::new(),\n            jobserver: None,\n            display_env_vars: false,\n            retry_with_argfile: false,\n            stdin: None,\n        }\n    }\n\n    /// (chainable) Sets the executable for the process.\n    pub fn program<T: AsRef<OsStr>>(&mut self, program: T) -> &mut ProcessBuilder {\n        self.program = program.as_ref().to_os_string();\n        self\n    }\n\n    /// (chainable) Overrides `arg0` for this program.\n    pub fn arg0<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut ProcessBuilder {\n        self.arg0 = Some(arg.as_ref().to_os_string());\n        self\n    }\n\n    /// (chainable) Adds `arg` to the args list.\n    pub fn arg<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut ProcessBuilder {\n        self.args.push(arg.as_ref().to_os_string());\n        self\n    }\n\n    /// (chainable) Adds multiple `args` to the args list.\n    pub fn args<T: AsRef<OsStr>>(&mut self, args: &[T]) -> &mut ProcessBuilder {\n        self.args\n            .extend(args.iter().map(|t| t.as_ref().to_os_string()));\n        self\n    }\n\n    /// (chainable) Replaces the args list with the given `args`.\n    pub fn args_replace<T: AsRef<OsStr>>(&mut self, args: &[T]) -> &mut ProcessBuilder {\n        if let Some(program) = self.wrappers.pop() {\n            // User intend to replace all args, so we\n            // - use the outermost wrapper as the main program, and\n            // - cleanup other inner wrappers.\n            self.program = program;\n            self.wrappers = Vec::new();\n        }\n        self.args = args.iter().map(|t| t.as_ref().to_os_string()).collect();\n        self\n    }\n\n    /// (chainable) Sets the current working directory of the process.\n    pub fn cwd<T: AsRef<OsStr>>(&mut self, path: T) -> &mut ProcessBuilder {\n        self.cwd = Some(path.as_ref().to_os_string());\n        self\n    }\n\n    /// (chainable) Sets an environment variable for the process.\n    pub fn env<T: AsRef<OsStr>>(&mut self, key: &str, val: T) -> &mut ProcessBuilder {\n        self.env\n            .insert(key.to_string(), Some(val.as_ref().to_os_string()));\n        self\n    }\n\n    /// (chainable) Unsets an environment variable for the process.\n    pub fn env_remove(&mut self, key: &str) -> &mut ProcessBuilder {\n        self.env.insert(key.to_string(), None);\n        self\n    }\n\n    /// Gets the executable name.\n    pub fn get_program(&self) -> &OsString {\n        self.wrappers.last().unwrap_or(&self.program)\n    }\n\n    /// Gets the program arg0.\n    pub fn get_arg0(&self) -> Option<&OsStr> {\n        self.arg0.as_deref()\n    }\n\n    /// Gets the program arguments.\n    pub fn get_args(&self) -> impl Iterator<Item = &OsString> {\n        self.wrappers\n            .iter()\n            .rev()\n            .chain(once(&self.program))\n            .chain(self.args.iter())\n            .skip(1) // Skip the main `program\n    }\n\n    /// Gets the current working directory for the process.\n    pub fn get_cwd(&self) -> Option<&Path> {\n        self.cwd.as_ref().map(Path::new)\n    }\n\n    /// Gets an environment variable as the process will see it (will inherit from environment\n    /// unless explicitly unset).\n    pub fn get_env(&self, var: &str) -> Option<OsString> {\n        self.env\n            .get(var)\n            .cloned()\n            .or_else(|| Some(env::var_os(var)))\n            .and_then(|s| s)\n    }\n\n    /// Gets all environment variables explicitly set or unset for the process (not inherited\n    /// vars).\n    pub fn get_envs(&self) -> &BTreeMap<String, Option<OsString>> {\n        &self.env\n    }\n\n    /// Sets the `make` jobserver. See the [jobserver crate][jobserver_docs] for\n    /// more information.\n    ///\n    /// [jobserver_docs]: https://docs.rs/jobserver/latest/jobserver/\n    pub fn inherit_jobserver(&mut self, jobserver: &Client) -> &mut Self {\n        self.jobserver = Some(jobserver.clone());\n        self\n    }\n\n    /// Enables environment variable display.\n    pub fn display_env_vars(&mut self) -> &mut Self {\n        self.display_env_vars = true;\n        self\n    }\n\n    /// Enables retrying with an argfile if hitting \"command line too big\" error\n    ///\n    /// This is primarily for the `@path` arg of rustc and rustdoc, which treat\n    /// each line as an command-line argument, so `LF` and `CRLF` bytes are not\n    /// valid as an argument for argfile at this moment.\n    /// For example, `RUSTDOCFLAGS=\"--crate-version foo\\nbar\" cargo doc` is\n    /// valid when invoking from command-line but not from argfile.\n    ///\n    /// To sum up, the limitations of the argfile are:\n    ///\n    /// - Must be valid UTF-8 encoded.\n    /// - Must not contain any newlines in each argument.\n    ///\n    /// Ref:\n    ///\n    /// - <https://doc.rust-lang.org/rustdoc/command-line-arguments.html#path-load-command-line-flags-from-a-path>\n    /// - <https://doc.rust-lang.org/rustc/command-line-arguments.html#path-load-command-line-flags-from-a-path>\n    pub fn retry_with_argfile(&mut self, enabled: bool) -> &mut Self {\n        self.retry_with_argfile = enabled;\n        self\n    }\n\n    /// Sets a value that will be written to stdin of the process on launch.\n    pub fn stdin<T: Into<Vec<u8>>>(&mut self, stdin: T) -> &mut Self {\n        self.stdin = Some(stdin.into());\n        self\n    }\n\n    fn should_retry_with_argfile(&self, err: &io::Error) -> bool {\n        self.retry_with_argfile && imp::command_line_too_big(err)\n    }\n\n    /// Like [`Command::status`] but with a better error message.\n    pub fn status(&self) -> Result<ExitStatus> {\n        self._status()\n            .with_context(|| ProcessError::could_not_execute(self))\n    }\n\n    fn _status(&self) -> io::Result<ExitStatus> {\n        if !debug_force_argfile(self.retry_with_argfile) {\n            let mut cmd = self.build_command();\n            match cmd.spawn() {\n                Err(ref e) if self.should_retry_with_argfile(e) => {}\n                Err(e) => return Err(e),\n                Ok(mut child) => return child.wait(),\n            }\n        }\n        let (mut cmd, argfile) = self.build_command_with_argfile()?;\n        let status = cmd.spawn()?.wait();\n        close_tempfile_and_log_error(argfile);\n        status\n    }\n\n    /// Runs the process, waiting for completion, and mapping non-success exit codes to an error.\n    pub fn exec(&self) -> Result<()> {\n        let exit = self.status()?;\n        if exit.success() {\n            Ok(())\n        } else {\n            Err(ProcessError::new(\n                &format!(\"process didn't exit successfully: {}\", self),\n                Some(exit),\n                None,\n            )\n            .into())\n        }\n    }\n\n    /// Replaces the current process with the target process.\n    ///\n    /// On Unix, this executes the process using the Unix syscall `execvp`, which will block\n    /// this process, and will only return if there is an error.\n    ///\n    /// On Windows this isn't technically possible. Instead we emulate it to the best of our\n    /// ability. One aspect we fix here is that we specify a handler for the Ctrl-C handler.\n    /// In doing so (and by effectively ignoring it) we should emulate proxying Ctrl-C\n    /// handling to the application at hand, which will either terminate or handle it itself.\n    /// According to Microsoft's documentation at\n    /// <https://docs.microsoft.com/en-us/windows/console/ctrl-c-and-ctrl-break-signals>.\n    /// the Ctrl-C signal is sent to all processes attached to a terminal, which should\n    /// include our child process. If the child terminates then we'll reap them in Cargo\n    /// pretty quickly, and if the child handles the signal then we won't terminate\n    /// (and we shouldn't!) until the process itself later exits.\n    pub fn exec_replace(&self) -> Result<()> {\n        imp::exec_replace(self)\n    }\n\n    /// Like [`Command::output`] but with a better error message.\n    pub fn output(&self) -> Result<Output> {\n        self._output()\n            .with_context(|| ProcessError::could_not_execute(self))\n    }\n\n    fn _output(&self) -> io::Result<Output> {\n        if !debug_force_argfile(self.retry_with_argfile) {\n            let mut cmd = self.build_command();\n            match piped(&mut cmd, self.stdin.is_some()).spawn() {\n                Err(ref e) if self.should_retry_with_argfile(e) => {}\n                Err(e) => return Err(e),\n                Ok(mut child) => {\n                    if let Some(stdin) = &self.stdin {\n                        child.stdin.take().unwrap().write_all(stdin)?;\n                    }\n                    return child.wait_with_output();\n                }\n            }\n        }\n        let (mut cmd, argfile) = self.build_command_with_argfile()?;\n        let mut child = piped(&mut cmd, self.stdin.is_some()).spawn()?;\n        if let Some(stdin) = &self.stdin {\n            child.stdin.take().unwrap().write_all(stdin)?;\n        }\n        let output = child.wait_with_output();\n        close_tempfile_and_log_error(argfile);\n        output\n    }\n\n    /// Executes the process, returning the stdio output, or an error if non-zero exit status.\n    pub fn exec_with_output(&self) -> Result<Output> {\n        let output = self.output()?;\n        if output.status.success() {\n            Ok(output)\n        } else {\n            Err(ProcessError::new(\n                &format!(\"process didn't exit successfully: {}\", self),\n                Some(output.status),\n                Some(&output),\n            )\n            .into())\n        }\n    }\n\n    /// Executes a command, passing each line of stdout and stderr to the supplied callbacks, which\n    /// can mutate the string data.\n    ///\n    /// If any invocations of these function return an error, it will be propagated.\n    ///\n    /// If `capture_output` is true, then all the output will also be buffered\n    /// and stored in the returned `Output` object. If it is false, no caching\n    /// is done, and the callbacks are solely responsible for handling the\n    /// output.\n    pub fn exec_with_streaming(\n        &self,\n        on_stdout_line: &mut dyn FnMut(&str) -> Result<()>,\n        on_stderr_line: &mut dyn FnMut(&str) -> Result<()>,\n        capture_output: bool,\n    ) -> Result<Output> {\n        let mut stdout = Vec::new();\n        let mut stderr = Vec::new();\n\n        let mut callback_error = None;\n        let mut stdout_pos = 0;\n        let mut stderr_pos = 0;\n\n        let spawn = |mut cmd| {\n            if !debug_force_argfile(self.retry_with_argfile) {\n                match piped(&mut cmd, false).spawn() {\n                    Err(ref e) if self.should_retry_with_argfile(e) => {}\n                    Err(e) => return Err(e),\n                    Ok(child) => return Ok((child, None)),\n                }\n            }\n            let (mut cmd, argfile) = self.build_command_with_argfile()?;\n            Ok((piped(&mut cmd, false).spawn()?, Some(argfile)))\n        };\n\n        let status = (|| {\n            let cmd = self.build_command();\n            let (mut child, argfile) = spawn(cmd)?;\n            let out = child.stdout.take().unwrap();\n            let err = child.stderr.take().unwrap();\n            read2(out, err, &mut |is_out, data, eof| {\n                let pos = if is_out {\n                    &mut stdout_pos\n                } else {\n                    &mut stderr_pos\n                };\n                let idx = if eof {\n                    data.len()\n                } else {\n                    match data[*pos..].iter().rposition(|b| *b == b'\\n') {\n                        Some(i) => *pos + i + 1,\n                        None => {\n                            *pos = data.len();\n                            return;\n                        }\n                    }\n                };\n\n                let new_lines = &data[..idx];\n\n                for line in String::from_utf8_lossy(new_lines).lines() {\n                    if callback_error.is_some() {\n                        break;\n                    }\n                    let callback_result = if is_out {\n                        on_stdout_line(line)\n                    } else {\n                        on_stderr_line(line)\n                    };\n                    if let Err(e) = callback_result {\n                        callback_error = Some(e);\n                        break;\n                    }\n                }\n\n                if capture_output {\n                    let dst = if is_out { &mut stdout } else { &mut stderr };\n                    dst.extend(new_lines);\n                }\n\n                data.drain(..idx);\n                *pos = 0;\n            })?;\n            let status = child.wait();\n            if let Some(argfile) = argfile {\n                close_tempfile_and_log_error(argfile);\n            }\n            status\n        })()\n        .with_context(|| ProcessError::could_not_execute(self))?;\n        let output = Output {\n            status,\n            stdout,\n            stderr,\n        };\n\n        {\n            let to_print = if capture_output { Some(&output) } else { None };\n            if let Some(e) = callback_error {\n                let cx = ProcessError::new(\n                    &format!(\"failed to parse process output: {}\", self),\n                    Some(output.status),\n                    to_print,\n                );\n                bail!(anyhow::Error::new(cx).context(e));\n            } else if !output.status.success() {\n                bail!(ProcessError::new(\n                    &format!(\"process didn't exit successfully: {}\", self),\n                    Some(output.status),\n                    to_print,\n                ));\n            }\n        }\n\n        Ok(output)\n    }\n\n    /// Builds the command with an `@<path>` argfile that contains all the\n    /// arguments. This is primarily served for rustc/rustdoc command family.\n    fn build_command_with_argfile(&self) -> io::Result<(Command, NamedTempFile)> {\n        use std::io::Write as _;\n\n        let mut tmp = tempfile::Builder::new()\n            .prefix(\"cargo-argfile.\")\n            .tempfile()?;\n\n        let mut arg = OsString::from(\"@\");\n        arg.push(tmp.path());\n        let mut cmd = self.build_command_without_args();\n        cmd.arg(arg);\n        tracing::debug!(\"created argfile at {} for {self}\", tmp.path().display());\n\n        let cap = self.get_args().map(|arg| arg.len() + 1).sum::<usize>();\n        let mut buf = Vec::with_capacity(cap);\n        for arg in &self.args {\n            let arg = arg.to_str().ok_or_else(|| {\n                io::Error::new(\n                    io::ErrorKind::Other,\n                    format!(\n                        \"argument for argfile contains invalid UTF-8 characters: `{}`\",\n                        arg.to_string_lossy()\n                    ),\n                )\n            })?;\n            if arg.contains('\\n') {\n                return Err(io::Error::new(\n                    io::ErrorKind::Other,\n                    format!(\"argument for argfile contains newlines: `{arg}`\"),\n                ));\n            }\n            writeln!(buf, \"{arg}\")?;\n        }\n        tmp.write_all(&mut buf)?;\n        Ok((cmd, tmp))\n    }\n\n    /// Builds a command from `ProcessBuilder` for everything but not `args`.\n    fn build_command_without_args(&self) -> Command {\n        let mut command = {\n            let mut iter = self.wrappers.iter().rev().chain(once(&self.program));\n            let mut cmd = Command::new(iter.next().expect(\"at least one `program` exists\"));\n            cmd.args(iter);\n            cmd\n        };\n        #[cfg(unix)]\n        if let Some(arg0) = self.get_arg0() {\n            use std::os::unix::process::CommandExt as _;\n            command.arg0(arg0);\n        }\n        if let Some(cwd) = self.get_cwd() {\n            command.current_dir(cwd);\n        }\n        for (k, v) in &self.env {\n            match *v {\n                Some(ref v) => {\n                    command.env(k, v);\n                }\n                None => {\n                    command.env_remove(k);\n                }\n            }\n        }\n        if let Some(ref c) = self.jobserver {\n            c.configure(&mut command);\n        }\n        command\n    }\n\n    /// Converts `ProcessBuilder` into a `std::process::Command`, and handles\n    /// the jobserver, if present.\n    ///\n    /// Note that this method doesn't take argfile fallback into account. The\n    /// caller should handle it by themselves.\n    pub fn build_command(&self) -> Command {\n        let mut command = self.build_command_without_args();\n        for arg in &self.args {\n            command.arg(arg);\n        }\n        command\n    }\n\n    /// Wraps an existing command with the provided wrapper, if it is present and valid.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use cargo_util::ProcessBuilder;\n    /// // Running this would execute `rustc`\n    /// let cmd = ProcessBuilder::new(\"rustc\");\n    ///\n    /// // Running this will execute `sccache rustc`\n    /// let cmd = cmd.wrapped(Some(\"sccache\"));\n    /// ```\n    pub fn wrapped(mut self, wrapper: Option<impl AsRef<OsStr>>) -> Self {\n        if let Some(wrapper) = wrapper.as_ref() {\n            let wrapper = wrapper.as_ref();\n            if !wrapper.is_empty() {\n                self.wrappers.push(wrapper.to_os_string());\n            }\n        }\n        self\n    }\n}\n\n/// Forces the command to use `@path` argfile.\n///\n/// You should set `__CARGO_TEST_FORCE_ARGFILE` to enable this.\nfn debug_force_argfile(retry_enabled: bool) -> bool {\n    cfg!(debug_assertions) && env::var(\"__CARGO_TEST_FORCE_ARGFILE\").is_ok() && retry_enabled\n}\n\n/// Creates new pipes for stderr, stdout, and optionally stdin.\nfn piped(cmd: &mut Command, pipe_stdin: bool) -> &mut Command {\n    cmd.stdout(Stdio::piped())\n        .stderr(Stdio::piped())\n        .stdin(if pipe_stdin {\n            Stdio::piped()\n        } else {\n            Stdio::null()\n        })\n}\n\nfn close_tempfile_and_log_error(file: NamedTempFile) {\n    file.close().unwrap_or_else(|e| {\n        tracing::warn!(\"failed to close temporary file: {e}\");\n    });\n}\n\n#[cfg(unix)]\nmod imp {\n    use super::{ProcessBuilder, ProcessError, close_tempfile_and_log_error, debug_force_argfile};\n    use anyhow::Result;\n    use std::io;\n    use std::os::unix::process::CommandExt;\n\n    pub fn exec_replace(process_builder: &ProcessBuilder) -> Result<()> {\n        let mut error;\n        let mut file = None;\n        if debug_force_argfile(process_builder.retry_with_argfile) {\n            let (mut command, argfile) = process_builder.build_command_with_argfile()?;\n            file = Some(argfile);\n            error = command.exec()\n        } else {\n            let mut command = process_builder.build_command();\n            error = command.exec();\n            if process_builder.should_retry_with_argfile(&error) {\n                let (mut command, argfile) = process_builder.build_command_with_argfile()?;\n                file = Some(argfile);\n                error = command.exec()\n            }\n        }\n        if let Some(file) = file {\n            close_tempfile_and_log_error(file);\n        }\n\n        Err(anyhow::Error::from(error).context(ProcessError::new(\n            &format!(\"could not execute process {}\", process_builder),\n            None,\n            None,\n        )))\n    }\n\n    pub fn command_line_too_big(err: &io::Error) -> bool {\n        err.raw_os_error() == Some(libc::E2BIG)\n    }\n}\n\n#[cfg(windows)]\nmod imp {\n    use super::{ProcessBuilder, ProcessError};\n    use anyhow::Result;\n    use std::io;\n    use windows_sys::Win32::Foundation::{FALSE, TRUE};\n    use windows_sys::Win32::System::Console::SetConsoleCtrlHandler;\n    use windows_sys::core::BOOL;\n\n    unsafe extern \"system\" fn ctrlc_handler(_: u32) -> BOOL {\n        // Do nothing; let the child process handle it.\n        TRUE\n    }\n\n    pub fn exec_replace(process_builder: &ProcessBuilder) -> Result<()> {\n        unsafe {\n            if SetConsoleCtrlHandler(Some(ctrlc_handler), TRUE) == FALSE {\n                return Err(ProcessError::new(\"Could not set Ctrl-C handler.\", None, None).into());\n            }\n        }\n\n        // Just execute the process as normal.\n        process_builder.exec()\n    }\n\n    pub fn command_line_too_big(err: &io::Error) -> bool {\n        use windows_sys::Win32::Foundation::ERROR_FILENAME_EXCED_RANGE;\n        err.raw_os_error() == Some(ERROR_FILENAME_EXCED_RANGE as i32)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::ProcessBuilder;\n    use std::fs;\n\n    #[test]\n    fn argfile_build_succeeds() {\n        let mut cmd = ProcessBuilder::new(\"echo\");\n        cmd.args([\"foo\", \"bar\"].as_slice());\n        let (cmd, argfile) = cmd.build_command_with_argfile().unwrap();\n\n        assert_eq!(cmd.get_program(), \"echo\");\n        let cmd_args: Vec<_> = cmd.get_args().map(|s| s.to_str().unwrap()).collect();\n        assert_eq!(cmd_args.len(), 1);\n        assert!(cmd_args[0].starts_with(\"@\"));\n        assert!(cmd_args[0].contains(\"cargo-argfile.\"));\n\n        let buf = fs::read_to_string(argfile.path()).unwrap();\n        assert_eq!(buf, \"foo\\nbar\\n\");\n    }\n\n    #[test]\n    fn argfile_build_fails_if_arg_contains_newline() {\n        let mut cmd = ProcessBuilder::new(\"echo\");\n        cmd.arg(\"foo\\n\");\n        let err = cmd.build_command_with_argfile().unwrap_err();\n        assert_eq!(\n            err.to_string(),\n            \"argument for argfile contains newlines: `foo\\n`\"\n        );\n    }\n\n    #[test]\n    fn argfile_build_fails_if_arg_contains_invalid_utf8() {\n        let mut cmd = ProcessBuilder::new(\"echo\");\n\n        #[cfg(windows)]\n        let invalid_arg = {\n            use std::os::windows::prelude::*;\n            std::ffi::OsString::from_wide(&[0x0066, 0x006f, 0xD800, 0x006f])\n        };\n\n        #[cfg(unix)]\n        let invalid_arg = {\n            use std::os::unix::ffi::OsStrExt;\n            std::ffi::OsStr::from_bytes(&[0x66, 0x6f, 0x80, 0x6f]).to_os_string()\n        };\n\n        cmd.arg(invalid_arg);\n        let err = cmd.build_command_with_argfile().unwrap_err();\n        assert_eq!(\n            err.to_string(),\n            \"argument for argfile contains invalid UTF-8 characters: `fo�o`\"\n        );\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util/src/process_error.rs",
    "content": "//! Error value for [`crate::ProcessBuilder`] when a process fails.\n\nuse std::fmt;\nuse std::process::{ExitStatus, Output};\nuse std::str;\n\n#[derive(Debug)]\npub struct ProcessError {\n    /// A detailed description to show to the user why the process failed.\n    pub desc: String,\n\n    /// The exit status of the process.\n    ///\n    /// This can be `None` if the process failed to launch (like process not\n    /// found) or if the exit status wasn't a code but was instead something\n    /// like termination via a signal.\n    pub code: Option<i32>,\n\n    /// The stdout from the process.\n    ///\n    /// This can be `None` if the process failed to launch, or the output was\n    /// not captured.\n    pub stdout: Option<Vec<u8>>,\n\n    /// The stderr from the process.\n    ///\n    /// This can be `None` if the process failed to launch, or the output was\n    /// not captured.\n    pub stderr: Option<Vec<u8>>,\n}\n\nimpl fmt::Display for ProcessError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.desc.fmt(f)\n    }\n}\n\nimpl std::error::Error for ProcessError {}\n\nimpl ProcessError {\n    /// Creates a new [`ProcessError`].\n    ///\n    /// * `status` can be `None` if the process did not launch.\n    /// * `output` can be `None` if the process did not launch, or output was not captured.\n    pub fn new(msg: &str, status: Option<ExitStatus>, output: Option<&Output>) -> ProcessError {\n        let exit = match status {\n            Some(s) => exit_status_to_string(s),\n            None => \"never executed\".to_string(),\n        };\n\n        Self::new_raw(\n            msg,\n            status.and_then(|s| s.code()),\n            &exit,\n            output.map(|s| s.stdout.as_slice()),\n            output.map(|s| s.stderr.as_slice()),\n        )\n    }\n\n    /// Creates a new [`ProcessError`] with the raw output data.\n    ///\n    /// * `code` can be `None` for situations like being killed by a signal on unix.\n    pub fn new_raw(\n        msg: &str,\n        code: Option<i32>,\n        status: &str,\n        stdout: Option<&[u8]>,\n        stderr: Option<&[u8]>,\n    ) -> ProcessError {\n        let mut desc = format!(\"{} ({})\", msg, status);\n\n        if let Some(out) = stdout {\n            match str::from_utf8(out) {\n                Ok(s) if !s.trim().is_empty() => {\n                    desc.push_str(\"\\n--- stdout\\n\");\n                    desc.push_str(s);\n                }\n                Ok(..) | Err(..) => {}\n            }\n        }\n        if let Some(out) = stderr {\n            match str::from_utf8(out) {\n                Ok(s) if !s.trim().is_empty() => {\n                    desc.push_str(\"\\n--- stderr\\n\");\n                    desc.push_str(s);\n                }\n                Ok(..) | Err(..) => {}\n            }\n        }\n\n        ProcessError {\n            desc,\n            code,\n            stdout: stdout.map(|s| s.to_vec()),\n            stderr: stderr.map(|s| s.to_vec()),\n        }\n    }\n\n    /// Creates a [`ProcessError`] with \"could not execute process {cmd}\".\n    ///\n    /// * `cmd` is usually but not limited to [`std::process::Command`].\n    pub fn could_not_execute(cmd: impl fmt::Display) -> ProcessError {\n        ProcessError::new(&format!(\"could not execute process {cmd}\"), None, None)\n    }\n}\n\n/// Converts an [`ExitStatus`]  to a human-readable string suitable for\n/// displaying to a user.\npub fn exit_status_to_string(status: ExitStatus) -> String {\n    return status_to_string(status);\n\n    #[cfg(unix)]\n    fn status_to_string(status: ExitStatus) -> String {\n        use std::os::unix::process::*;\n\n        if let Some(signal) = status.signal() {\n            let name = match signal as libc::c_int {\n                libc::SIGABRT => \", SIGABRT: process abort signal\",\n                libc::SIGALRM => \", SIGALRM: alarm clock\",\n                libc::SIGFPE => \", SIGFPE: erroneous arithmetic operation\",\n                libc::SIGHUP => \", SIGHUP: hangup\",\n                libc::SIGILL => \", SIGILL: illegal instruction\",\n                libc::SIGINT => \", SIGINT: terminal interrupt signal\",\n                libc::SIGKILL => \", SIGKILL: kill\",\n                libc::SIGPIPE => \", SIGPIPE: write on a pipe with no one to read\",\n                libc::SIGQUIT => \", SIGQUIT: terminal quit signal\",\n                libc::SIGSEGV => \", SIGSEGV: invalid memory reference\",\n                libc::SIGTERM => \", SIGTERM: termination signal\",\n                libc::SIGBUS => \", SIGBUS: access to undefined memory\",\n                #[cfg(not(target_os = \"haiku\"))]\n                libc::SIGSYS => \", SIGSYS: bad system call\",\n                libc::SIGTRAP => \", SIGTRAP: trace/breakpoint trap\",\n                _ => \"\",\n            };\n            format!(\"signal: {}{}\", signal, name)\n        } else {\n            status.to_string()\n        }\n    }\n\n    #[cfg(windows)]\n    fn status_to_string(status: ExitStatus) -> String {\n        use windows_sys::Win32::Foundation::*;\n\n        let mut base = status.to_string();\n        let extra = match status.code().unwrap() as i32 {\n            STATUS_ACCESS_VIOLATION => \"STATUS_ACCESS_VIOLATION\",\n            STATUS_IN_PAGE_ERROR => \"STATUS_IN_PAGE_ERROR\",\n            STATUS_INVALID_HANDLE => \"STATUS_INVALID_HANDLE\",\n            STATUS_INVALID_PARAMETER => \"STATUS_INVALID_PARAMETER\",\n            STATUS_NO_MEMORY => \"STATUS_NO_MEMORY\",\n            STATUS_ILLEGAL_INSTRUCTION => \"STATUS_ILLEGAL_INSTRUCTION\",\n            STATUS_NONCONTINUABLE_EXCEPTION => \"STATUS_NONCONTINUABLE_EXCEPTION\",\n            STATUS_INVALID_DISPOSITION => \"STATUS_INVALID_DISPOSITION\",\n            STATUS_ARRAY_BOUNDS_EXCEEDED => \"STATUS_ARRAY_BOUNDS_EXCEEDED\",\n            STATUS_FLOAT_DENORMAL_OPERAND => \"STATUS_FLOAT_DENORMAL_OPERAND\",\n            STATUS_FLOAT_DIVIDE_BY_ZERO => \"STATUS_FLOAT_DIVIDE_BY_ZERO\",\n            STATUS_FLOAT_INEXACT_RESULT => \"STATUS_FLOAT_INEXACT_RESULT\",\n            STATUS_FLOAT_INVALID_OPERATION => \"STATUS_FLOAT_INVALID_OPERATION\",\n            STATUS_FLOAT_OVERFLOW => \"STATUS_FLOAT_OVERFLOW\",\n            STATUS_FLOAT_STACK_CHECK => \"STATUS_FLOAT_STACK_CHECK\",\n            STATUS_FLOAT_UNDERFLOW => \"STATUS_FLOAT_UNDERFLOW\",\n            STATUS_INTEGER_DIVIDE_BY_ZERO => \"STATUS_INTEGER_DIVIDE_BY_ZERO\",\n            STATUS_INTEGER_OVERFLOW => \"STATUS_INTEGER_OVERFLOW\",\n            STATUS_PRIVILEGED_INSTRUCTION => \"STATUS_PRIVILEGED_INSTRUCTION\",\n            STATUS_STACK_OVERFLOW => \"STATUS_STACK_OVERFLOW\",\n            STATUS_DLL_NOT_FOUND => \"STATUS_DLL_NOT_FOUND\",\n            STATUS_ORDINAL_NOT_FOUND => \"STATUS_ORDINAL_NOT_FOUND\",\n            STATUS_ENTRYPOINT_NOT_FOUND => \"STATUS_ENTRYPOINT_NOT_FOUND\",\n            STATUS_CONTROL_C_EXIT => \"STATUS_CONTROL_C_EXIT\",\n            STATUS_DLL_INIT_FAILED => \"STATUS_DLL_INIT_FAILED\",\n            STATUS_FLOAT_MULTIPLE_FAULTS => \"STATUS_FLOAT_MULTIPLE_FAULTS\",\n            STATUS_FLOAT_MULTIPLE_TRAPS => \"STATUS_FLOAT_MULTIPLE_TRAPS\",\n            STATUS_REG_NAT_CONSUMPTION => \"STATUS_REG_NAT_CONSUMPTION\",\n            STATUS_HEAP_CORRUPTION => \"STATUS_HEAP_CORRUPTION\",\n            STATUS_STACK_BUFFER_OVERRUN => \"STATUS_STACK_BUFFER_OVERRUN\",\n            STATUS_ASSERTION_FAILURE => \"STATUS_ASSERTION_FAILURE\",\n            _ => return base,\n        };\n        base.push_str(\", \");\n        base.push_str(extra);\n        base\n    }\n}\n\n/// Returns `true` if the given process exit code is something a normal\n/// process would exit with.\n///\n/// This helps differentiate from abnormal termination codes, such as\n/// segmentation faults or signals.\npub fn is_simple_exit_code(code: i32) -> bool {\n    // Typical unix exit codes are 0 to 127.\n    // Windows doesn't have anything \"typical\", and is a\n    // 32-bit number (which appears signed here, but is really\n    // unsigned). However, most of the interesting NTSTATUS\n    // codes are very large. This is just a rough\n    // approximation of which codes are \"normal\" and which\n    // ones are abnormal termination.\n    code >= 0 && code <= 127\n}\n"
  },
  {
    "path": "crates/cargo-util/src/read2.rs",
    "content": "pub use self::imp::read2;\n\n#[cfg(unix)]\nmod imp {\n    use libc::{F_GETFL, F_SETFL, O_NONBLOCK, c_int, fcntl};\n    use std::io;\n    use std::io::prelude::*;\n    use std::mem;\n    use std::os::unix::prelude::*;\n    use std::process::{ChildStderr, ChildStdout};\n\n    fn set_nonblock(fd: c_int) -> io::Result<()> {\n        let flags = unsafe { fcntl(fd, F_GETFL) };\n        if flags == -1 || unsafe { fcntl(fd, F_SETFL, flags | O_NONBLOCK) } == -1 {\n            return Err(io::Error::last_os_error());\n        }\n        Ok(())\n    }\n\n    pub fn read2(\n        mut out_pipe: ChildStdout,\n        mut err_pipe: ChildStderr,\n        data: &mut dyn FnMut(bool, &mut Vec<u8>, bool),\n    ) -> io::Result<()> {\n        set_nonblock(out_pipe.as_raw_fd())?;\n        set_nonblock(err_pipe.as_raw_fd())?;\n\n        let mut out_done = false;\n        let mut err_done = false;\n        let mut out = Vec::new();\n        let mut err = Vec::new();\n\n        let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };\n        fds[0].fd = out_pipe.as_raw_fd();\n        fds[0].events = libc::POLLIN;\n        fds[1].fd = err_pipe.as_raw_fd();\n        fds[1].events = libc::POLLIN;\n        let mut nfds = 2;\n        let mut errfd = 1;\n\n        while nfds > 0 {\n            // wait for either pipe to become readable using `poll`\n            let r = unsafe { libc::poll(fds.as_mut_ptr(), nfds, -1) };\n            if r == -1 {\n                let err = io::Error::last_os_error();\n                if err.kind() == io::ErrorKind::Interrupted {\n                    continue;\n                }\n                return Err(err);\n            }\n\n            // Read as much as we can from each pipe, ignoring EWOULDBLOCK or\n            // EAGAIN. If we hit EOF, then this will happen because the underlying\n            // reader will return Ok(0), in which case we'll see `Ok` ourselves. In\n            // this case we flip the other fd back into blocking mode and read\n            // whatever's leftover on that file descriptor.\n            let handle = |res: io::Result<_>| match res {\n                Ok(_) => Ok(true),\n                Err(e) => {\n                    if e.kind() == io::ErrorKind::WouldBlock {\n                        Ok(false)\n                    } else {\n                        Err(e)\n                    }\n                }\n            };\n            if !err_done && fds[errfd].revents != 0 && handle(err_pipe.read_to_end(&mut err))? {\n                err_done = true;\n                nfds -= 1;\n            }\n            data(false, &mut err, err_done);\n            if !out_done && fds[0].revents != 0 && handle(out_pipe.read_to_end(&mut out))? {\n                out_done = true;\n                fds[0].fd = err_pipe.as_raw_fd();\n                errfd = 0;\n                nfds -= 1;\n            }\n            data(true, &mut out, out_done);\n        }\n        Ok(())\n    }\n}\n\n#[cfg(windows)]\nmod imp {\n    use std::io;\n    use std::os::windows::prelude::*;\n    use std::process::{ChildStderr, ChildStdout};\n    use std::slice;\n\n    use miow::Overlapped;\n    use miow::iocp::{CompletionPort, CompletionStatus};\n    use miow::pipe::NamedPipe;\n    use windows_sys::Win32::Foundation::ERROR_BROKEN_PIPE;\n\n    struct Pipe<'a> {\n        dst: &'a mut Vec<u8>,\n        overlapped: Overlapped,\n        pipe: NamedPipe,\n        done: bool,\n    }\n\n    pub fn read2(\n        out_pipe: ChildStdout,\n        err_pipe: ChildStderr,\n        data: &mut dyn FnMut(bool, &mut Vec<u8>, bool),\n    ) -> io::Result<()> {\n        let mut out = Vec::new();\n        let mut err = Vec::new();\n\n        let port = CompletionPort::new(1)?;\n        port.add_handle(0, &out_pipe)?;\n        port.add_handle(1, &err_pipe)?;\n\n        unsafe {\n            let mut out_pipe = Pipe::new(out_pipe, &mut out);\n            let mut err_pipe = Pipe::new(err_pipe, &mut err);\n\n            out_pipe.read()?;\n            err_pipe.read()?;\n\n            let mut status = [CompletionStatus::zero(), CompletionStatus::zero()];\n\n            while !out_pipe.done || !err_pipe.done {\n                for status in port.get_many(&mut status, None)? {\n                    if status.token() == 0 {\n                        out_pipe.complete(status);\n                        data(true, out_pipe.dst, out_pipe.done);\n                        out_pipe.read()?;\n                    } else {\n                        err_pipe.complete(status);\n                        data(false, err_pipe.dst, err_pipe.done);\n                        err_pipe.read()?;\n                    }\n                }\n            }\n\n            Ok(())\n        }\n    }\n\n    impl<'a> Pipe<'a> {\n        unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> {\n            // SAFETY: Handle must be owned, open, and closeable with CloseHandle.\n            let pipe = unsafe { NamedPipe::from_raw_handle(p.into_raw_handle()) };\n            Pipe {\n                dst,\n                pipe,\n                overlapped: Overlapped::zero(),\n                done: false,\n            }\n        }\n\n        unsafe fn read(&mut self) -> io::Result<()> {\n            let dst = unsafe { slice_to_end(self.dst) };\n            // SAFETY: The buffer must be valid until the end of the I/O,\n            // which is handled in `read2`.\n            match unsafe { self.pipe.read_overlapped(dst, self.overlapped.raw()) } {\n                Ok(_) => Ok(()),\n                Err(e) => {\n                    if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {\n                        self.done = true;\n                        Ok(())\n                    } else {\n                        Err(e)\n                    }\n                }\n            }\n        }\n\n        unsafe fn complete(&mut self, status: &CompletionStatus) {\n            let prev = self.dst.len();\n            unsafe { self.dst.set_len(prev + status.bytes_transferred() as usize) };\n            if status.bytes_transferred() == 0 {\n                self.done = true;\n            }\n        }\n    }\n\n    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {\n        if v.capacity() == 0 {\n            v.reserve(16);\n        }\n        if v.capacity() == v.len() {\n            v.reserve(1);\n        }\n        unsafe { slice::from_raw_parts_mut(v.as_mut_ptr().add(v.len()), v.capacity() - v.len()) }\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util/src/registry.rs",
    "content": "/// Make a path to a dependency, which aligns to\n///\n/// - [index from of Cargo's index on filesystem][1], and\n/// - [index from Crates.io][2].\n///\n/// <div class=\"warning\">\n///\n/// Note: For index files, `dep_name` must have had `to_lowercase` called on it.\n///\n/// </div>\n///\n/// [1]: https://docs.rs/cargo/latest/cargo/sources/registry/index.html#the-format-of-the-index\n/// [2]: https://github.com/rust-lang/crates.io-index\npub fn make_dep_path(dep_name: &str, prefix_only: bool) -> String {\n    let (slash, name) = if prefix_only {\n        (\"\", \"\")\n    } else {\n        (\"/\", dep_name)\n    };\n    match dep_name.len() {\n        1 => format!(\"1{}{}\", slash, name),\n        2 => format!(\"2{}{}\", slash, name),\n        3 => format!(\"3/{}{}{}\", &dep_name[..1], slash, name),\n        _ => format!(\"{}/{}{}{}\", &dep_name[0..2], &dep_name[2..4], slash, name),\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::make_dep_path;\n\n    #[test]\n    fn prefix_only() {\n        assert_eq!(make_dep_path(\"a\", true), \"1\");\n        assert_eq!(make_dep_path(\"ab\", true), \"2\");\n        assert_eq!(make_dep_path(\"abc\", true), \"3/a\");\n        assert_eq!(make_dep_path(\"Abc\", true), \"3/A\");\n        assert_eq!(make_dep_path(\"AbCd\", true), \"Ab/Cd\");\n        assert_eq!(make_dep_path(\"aBcDe\", true), \"aB/cD\");\n    }\n\n    #[test]\n    fn full() {\n        assert_eq!(make_dep_path(\"a\", false), \"1/a\");\n        assert_eq!(make_dep_path(\"ab\", false), \"2/ab\");\n        assert_eq!(make_dep_path(\"abc\", false), \"3/a/abc\");\n        assert_eq!(make_dep_path(\"Abc\", false), \"3/A/Abc\");\n        assert_eq!(make_dep_path(\"AbCd\", false), \"Ab/Cd/AbCd\");\n        assert_eq!(make_dep_path(\"aBcDe\", false), \"aB/cD/aBcDe\");\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util/src/sha256.rs",
    "content": "use super::paths;\nuse anyhow::{Context, Result};\nuse sha2::{Digest, Sha256 as Sha2_sha256};\nuse std::fs::File;\nuse std::io::{self, Read};\nuse std::path::Path;\n\npub struct Sha256(Sha2_sha256);\n\nimpl Sha256 {\n    pub fn new() -> Sha256 {\n        let hasher = Sha2_sha256::new();\n        Sha256(hasher)\n    }\n\n    pub fn update(&mut self, bytes: &[u8]) -> &mut Sha256 {\n        let _ = self.0.update(bytes);\n        self\n    }\n\n    pub fn update_file(&mut self, mut file: &File) -> io::Result<&mut Sha256> {\n        let mut buf = [0; 64 * 1024];\n        loop {\n            let n = file.read(&mut buf)?;\n            if n == 0 {\n                break Ok(self);\n            }\n            self.update(&buf[..n]);\n        }\n    }\n\n    pub fn update_path<P: AsRef<Path>>(&mut self, path: P) -> Result<&mut Sha256> {\n        let path = path.as_ref();\n        let file = paths::open(path)?;\n        self.update_file(&file)\n            .with_context(|| format!(\"failed to read `{}`\", path.display()))?;\n        Ok(self)\n    }\n\n    pub fn finish(&mut self) -> [u8; 32] {\n        self.0.finalize_reset().into()\n    }\n\n    pub fn finish_hex(&mut self) -> String {\n        hex::encode(self.finish())\n    }\n}\n\nimpl Default for Sha256 {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util-schemas/Cargo.toml",
    "content": "[package]\nname = \"cargo-util-schemas\"\nversion = \"0.13.1\"\nrust-version = \"1.94\"  # MSRV:1\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"Deserialization schemas for Cargo\"\n\n[dependencies]\njiff = { workspace = true, features = [\"std\", \"serde\"] }\nschemars = { workspace = true, features = [\"preserve_order\", \"semver1\"], optional = true }\nsemver.workspace = true\nserde = { workspace = true, features = [\"derive\"] }\nserde_json = { workspace = true, optional = true }\nserde-untagged.workspace = true\nserde-value.workspace = true\nthiserror.workspace = true\ntoml = { workspace = true, features = [\"serde\"] }\nunicode-ident.workspace = true\nurl.workspace = true\n\n[lints]\nworkspace = true\n\n[dev-dependencies]\nsnapbox.workspace = true\nserde_json.workspace = true\n\n[features]\nunstable-schema = [\"dep:schemars\", \"dep:serde_json\"]\n"
  },
  {
    "path": "crates/cargo-util-schemas/README.md",
    "content": "> This crate is maintained by the Cargo team for use by the wider\n> ecosystem. This crate follows semver compatibility for its APIs.\n"
  },
  {
    "path": "crates/cargo-util-schemas/index.schema.json",
    "content": "{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"title\": \"IndexPackage\",\n  \"description\": \"A single line in the index representing a single version of a package.\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"name\": {\n      \"description\": \"Name of the package.\",\n      \"type\": \"string\"\n    },\n    \"vers\": {\n      \"description\": \"The version of this dependency.\",\n      \"$ref\": \"#/$defs/SemVer\"\n    },\n    \"deps\": {\n      \"description\": \"All kinds of direct dependencies of the package, including dev and\\nbuild dependencies.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"$ref\": \"#/$defs/RegistryDependency\"\n      }\n    },\n    \"features\": {\n      \"description\": \"Set of features defined for the package, i.e., `[features]` table.\",\n      \"type\": \"object\",\n      \"additionalProperties\": {\n        \"type\": \"array\",\n        \"items\": {\n          \"type\": \"string\"\n        }\n      },\n      \"default\": {}\n    },\n    \"features2\": {\n      \"description\": \"This field contains features with new, extended syntax. Specifically,\\nnamespaced features (`dep:`) and weak dependencies (`pkg?/feat`).\\n\\nThis is separated from `features` because versions older than 1.19\\nwill fail to load due to not being able to parse the new syntax, even\\nwith a `Cargo.lock` file.\",\n      \"type\": [\n        \"object\",\n        \"null\"\n      ],\n      \"additionalProperties\": {\n        \"type\": \"array\",\n        \"items\": {\n          \"type\": \"string\"\n        }\n      }\n    },\n    \"cksum\": {\n      \"description\": \"Checksum for verifying the integrity of the corresponding downloaded package.\",\n      \"type\": \"string\"\n    },\n    \"yanked\": {\n      \"description\": \"If `true`, Cargo will skip this version when resolving.\\n\\nThis was added in 2014. Everything in the crates.io index has this set\\nnow, so this probably doesn't need to be an option anymore.\",\n      \"type\": [\n        \"boolean\",\n        \"null\"\n      ]\n    },\n    \"links\": {\n      \"description\": \"Native library name this package links to.\\n\\nAdded early 2018 (see <https://github.com/rust-lang/cargo/pull/4978>),\\ncan be `None` if published before then.\",\n      \"type\": [\n        \"string\",\n        \"null\"\n      ]\n    },\n    \"rust_version\": {\n      \"description\": \"Required version of rust\\n\\nCorresponds to `package.rust-version`.\\n\\nAdded in 2023 (see <https://github.com/rust-lang/crates.io/pull/6267>),\\ncan be `None` if published before then or if not set in the manifest.\",\n      \"type\": [\n        \"string\",\n        \"null\"\n      ]\n    },\n    \"pubtime\": {\n      \"description\": \"The publish time of this package version (optional).\\n\\nThe format is a subset of ISO8601:\\n- `yyyy-mm-ddThh:mm:ssZ`\\n- no fractional seconds\\n- always `Z` for UTC timezone, no timezone offsets supported\\n- fields are 0-padded\\n\\nExample: 2025-11-12T19:30:12Z\\n\\nThis should be the original publish time and not changed on any status changes,\\nlike [`IndexPackage::yanked`].\",\n      \"type\": [\n        \"string\",\n        \"null\"\n      ],\n      \"default\": null\n    },\n    \"v\": {\n      \"description\": \"The schema version for this entry.\\n\\nIf this is None, it defaults to version `1`. Entries with unknown\\nversions are ignored.\\n\\nVersion `2` schema adds the `features2` field.\\n\\nVersion `3` schema adds `artifact`, `bindep_targes`, and `lib` for\\nartifact dependencies support.\\n\\nThis provides a method to safely introduce changes to index entries\\nand allow older versions of cargo to ignore newer entries it doesn't\\nunderstand. This is honored as of 1.51, so unfortunately older\\nversions will ignore it, and potentially misinterpret version 2 and\\nnewer entries.\\n\\nThe intent is that versions older than 1.51 will work with a\\npre-existing `Cargo.lock`, but they may not correctly process `cargo\\nupdate` or build a lock from scratch. In that case, cargo may\\nincorrectly select a new package that uses a new index schema. A\\nworkaround is to downgrade any packages that are incompatible with the\\n`--precise` flag of `cargo update`.\",\n      \"type\": [\n        \"integer\",\n        \"null\"\n      ],\n      \"format\": \"uint32\",\n      \"minimum\": 0\n    }\n  },\n  \"required\": [\n    \"name\",\n    \"vers\",\n    \"deps\",\n    \"cksum\"\n  ],\n  \"$defs\": {\n    \"SemVer\": {\n      \"type\": \"string\",\n      \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n    },\n    \"RegistryDependency\": {\n      \"description\": \"A dependency as encoded in the [`IndexPackage`] index JSON.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"name\": {\n          \"description\": \"Name of the dependency. If the dependency is renamed, the original\\nwould be stored in [`RegistryDependency::package`].\",\n          \"type\": \"string\"\n        },\n        \"req\": {\n          \"description\": \"The SemVer requirement for this dependency.\",\n          \"type\": \"string\"\n        },\n        \"features\": {\n          \"description\": \"Set of features enabled for this dependency.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          },\n          \"default\": []\n        },\n        \"optional\": {\n          \"description\": \"Whether or not this is an optional dependency.\",\n          \"type\": \"boolean\",\n          \"default\": false\n        },\n        \"default_features\": {\n          \"description\": \"Whether or not default features are enabled.\",\n          \"type\": \"boolean\",\n          \"default\": true\n        },\n        \"target\": {\n          \"description\": \"The target platform for this dependency.\",\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"kind\": {\n          \"description\": \"The dependency kind. \\\"dev\\\", \\\"build\\\", and \\\"normal\\\".\",\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"registry\": {\n          \"description\": \"The URL of the index of the registry where this dependency is from.\\n`None` if it is from the same index.\",\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"package\": {\n          \"description\": \"The original name if the dependency is renamed.\",\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"public\": {\n          \"description\": \"Whether or not this is a public dependency. Unstable. See [RFC 1977].\\n\\n[RFC 1977]: https://rust-lang.github.io/rfcs/1977-public-private-dependencies.html\",\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"artifact\": {\n          \"description\": \"The artifacts to build from this dependency.\",\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"bindep_target\": {\n          \"description\": \"The target for bindep.\",\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"lib\": {\n          \"description\": \"Whether or not this is a library dependency.\",\n          \"type\": \"boolean\",\n          \"default\": false\n        }\n      },\n      \"required\": [\n        \"name\",\n        \"req\"\n      ]\n    }\n  }\n}"
  },
  {
    "path": "crates/cargo-util-schemas/lockfile.schema.json",
    "content": "{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"title\": \"TomlLockfile\",\n  \"description\": \"Serialization of `Cargo.lock`\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"version\": {\n      \"description\": \"The lockfile format version (`version =` field).\\n\\nThis field is optional for backward compatibility. Older lockfiles, i.e. V1 and V2, does\\nnot have the version field serialized.\",\n      \"type\": [\n        \"integer\",\n        \"null\"\n      ],\n      \"format\": \"uint32\",\n      \"minimum\": 0\n    },\n    \"package\": {\n      \"description\": \"The list of `[[package]]` entries describing each resolved dependency.\",\n      \"type\": [\n        \"array\",\n        \"null\"\n      ],\n      \"items\": {\n        \"$ref\": \"#/$defs/TomlLockfileDependency\"\n      }\n    },\n    \"root\": {\n      \"description\": \"The `[root]` table describing the root package.\\n\\nThis field is optional for backward compatibility. Older lockfiles have the root package\\nseparated, whereas newer lockfiles have the root package as part of `[[package]]`.\",\n      \"anyOf\": [\n        {\n          \"$ref\": \"#/$defs/TomlLockfileDependency\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ]\n    },\n    \"metadata\": {\n      \"description\": \"The `[metadata]` table\\n\\n\\nIn older lockfile versions, dependency checksums were stored here instead of alongside each\\npackage entry.\",\n      \"type\": [\n        \"object\",\n        \"null\"\n      ],\n      \"additionalProperties\": {\n        \"type\": \"string\"\n      }\n    },\n    \"patch\": {\n      \"description\": \"The `[patch]` table describing unused patches.\\n\\nThe lockfile stores them as a list of `[[patch.unused]]` entries.\",\n      \"$ref\": \"#/$defs/TomlLockfilePatch\"\n    }\n  },\n  \"$defs\": {\n    \"TomlLockfileDependency\": {\n      \"description\": \"Serialization of lockfiles dependencies\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"name\": {\n          \"description\": \"The name of the dependency.\",\n          \"type\": \"string\"\n        },\n        \"version\": {\n          \"description\": \"The version of the dependency.\",\n          \"type\": \"string\"\n        },\n        \"source\": {\n          \"description\": \"The source of the dependency.\\n\\nCargo does not serialize path dependencies.\",\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/TomlLockfileSourceId\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"checksum\": {\n          \"description\": \"The checksum of the dependency.\\n\\nIn older lockfiles, checksums were not stored here and instead on a separate `[metadata]`\\ntable (see [`TomlLockfileMetadata`]).\",\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"dependencies\": {\n          \"description\": \"The transitive dependencies used by this dependency.\",\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"$ref\": \"#/$defs/TomlLockfilePackageId\"\n          }\n        },\n        \"replace\": {\n          \"description\": \"The replace of the dependency.\",\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/TomlLockfilePackageId\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        }\n      },\n      \"required\": [\n        \"name\",\n        \"version\"\n      ]\n    },\n    \"TomlLockfileSourceId\": {\n      \"description\": \"Serialization of dependency's source\",\n      \"type\": \"string\"\n    },\n    \"TomlLockfilePackageId\": {\n      \"description\": \"Serialization of package IDs.\\n\\nThe version and source are only included when necessary to disambiguate between packages:\\n- If multiple packages share the same name, the version is included.\\n- If multiple packages share the same name and version, the source is included.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"name\": {\n          \"type\": \"string\"\n        },\n        \"version\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"source\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/TomlLockfileSourceId\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        }\n      },\n      \"required\": [\n        \"name\"\n      ]\n    },\n    \"TomlLockfilePatch\": {\n      \"description\": \"Serialization of unused patches\\n\\nCargo stores patches that were declared but not used during resolution.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"unused\": {\n          \"description\": \"The list of unused dependency patches.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"#/$defs/TomlLockfileDependency\"\n          }\n        }\n      },\n      \"required\": [\n        \"unused\"\n      ]\n    }\n  }\n}"
  },
  {
    "path": "crates/cargo-util-schemas/manifest.schema.json",
    "content": "{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"title\": \"TomlManifest\",\n  \"description\": \"This type is used to deserialize `Cargo.toml` files.\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"cargo-features\": {\n      \"type\": [\n        \"array\",\n        \"null\"\n      ],\n      \"items\": {\n        \"type\": \"string\"\n      }\n    },\n    \"package\": {\n      \"anyOf\": [\n        {\n          \"$ref\": \"#/$defs/TomlPackage\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ]\n    },\n    \"project\": {\n      \"anyOf\": [\n        {\n          \"$ref\": \"#/$defs/TomlPackage\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ]\n    },\n    \"badges\": {\n      \"type\": [\n        \"object\",\n        \"null\"\n      ],\n      \"additionalProperties\": {\n        \"type\": \"object\",\n        \"additionalProperties\": {\n          \"type\": \"string\"\n        }\n      }\n    },\n    \"features\": {\n      \"type\": [\n        \"object\",\n        \"null\"\n      ],\n      \"additionalProperties\": {\n        \"type\": \"array\",\n        \"items\": {\n          \"type\": \"string\"\n        }\n      }\n    },\n    \"lib\": {\n      \"anyOf\": [\n        {\n          \"$ref\": \"#/$defs/TomlTarget\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ]\n    },\n    \"bin\": {\n      \"type\": [\n        \"array\",\n        \"null\"\n      ],\n      \"items\": {\n        \"$ref\": \"#/$defs/TomlTarget\"\n      }\n    },\n    \"example\": {\n      \"type\": [\n        \"array\",\n        \"null\"\n      ],\n      \"items\": {\n        \"$ref\": \"#/$defs/TomlTarget\"\n      }\n    },\n    \"test\": {\n      \"type\": [\n        \"array\",\n        \"null\"\n      ],\n      \"items\": {\n        \"$ref\": \"#/$defs/TomlTarget\"\n      }\n    },\n    \"bench\": {\n      \"type\": [\n        \"array\",\n        \"null\"\n      ],\n      \"items\": {\n        \"$ref\": \"#/$defs/TomlTarget\"\n      }\n    },\n    \"dependencies\": {\n      \"type\": [\n        \"object\",\n        \"null\"\n      ],\n      \"additionalProperties\": {\n        \"$ref\": \"#/$defs/InheritableDependency\"\n      }\n    },\n    \"dev-dependencies\": {\n      \"type\": [\n        \"object\",\n        \"null\"\n      ],\n      \"additionalProperties\": {\n        \"$ref\": \"#/$defs/InheritableDependency\"\n      }\n    },\n    \"dev_dependencies\": {\n      \"type\": [\n        \"object\",\n        \"null\"\n      ],\n      \"additionalProperties\": {\n        \"$ref\": \"#/$defs/InheritableDependency\"\n      }\n    },\n    \"build-dependencies\": {\n      \"type\": [\n        \"object\",\n        \"null\"\n      ],\n      \"additionalProperties\": {\n        \"$ref\": \"#/$defs/InheritableDependency\"\n      }\n    },\n    \"build_dependencies\": {\n      \"type\": [\n        \"object\",\n        \"null\"\n      ],\n      \"additionalProperties\": {\n        \"$ref\": \"#/$defs/InheritableDependency\"\n      }\n    },\n    \"target\": {\n      \"type\": [\n        \"object\",\n        \"null\"\n      ],\n      \"additionalProperties\": {\n        \"$ref\": \"#/$defs/TomlPlatform\"\n      }\n    },\n    \"lints\": {\n      \"anyOf\": [\n        {\n          \"$ref\": \"#/$defs/InheritableLints\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ]\n    },\n    \"hints\": {\n      \"anyOf\": [\n        {\n          \"$ref\": \"#/$defs/Hints\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ]\n    },\n    \"workspace\": {\n      \"anyOf\": [\n        {\n          \"$ref\": \"#/$defs/TomlWorkspace\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ]\n    },\n    \"profile\": {\n      \"anyOf\": [\n        {\n          \"$ref\": \"#/$defs/TomlProfiles\"\n        },\n        {\n          \"type\": \"null\"\n        }\n      ]\n    },\n    \"patch\": {\n      \"type\": [\n        \"object\",\n        \"null\"\n      ],\n      \"additionalProperties\": {\n        \"type\": \"object\",\n        \"additionalProperties\": {\n          \"$ref\": \"#/$defs/TomlDependency\"\n        }\n      }\n    },\n    \"replace\": {\n      \"type\": [\n        \"object\",\n        \"null\"\n      ],\n      \"additionalProperties\": {\n        \"$ref\": \"#/$defs/TomlDependency\"\n      }\n    }\n  },\n  \"$defs\": {\n    \"TomlPackage\": {\n      \"description\": \"Represents the `package`/`project` sections of a `Cargo.toml`.\\n\\nNote that the order of the fields matters, since this is the order they\\nare serialized to a TOML file. For example, you cannot have values after\\nthe field `metadata`, since it is a table and values cannot appear after\\ntables.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"edition\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"rust-version\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"name\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"version\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField2\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"authors\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField3\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"build\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/TomlPackageBuild\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"metabuild\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/StringOrVec\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"default-target\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"forced-target\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"links\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"exclude\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField3\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"include\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField3\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"publish\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField4\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"workspace\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"im-a-teapot\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"autolib\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"autobins\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"autoexamples\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"autotests\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"autobenches\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"default-run\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"description\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"homepage\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"documentation\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"readme\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField5\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"keywords\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField3\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"categories\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField3\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"license\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"license-file\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"repository\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritableField\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"resolver\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"metadata\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/TomlValue\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        }\n      }\n    },\n    \"InheritableField\": {\n      \"description\": \"An enum that allows for inheriting keys from a workspace in a Cargo.toml.\",\n      \"anyOf\": [\n        {\n          \"description\": \"The type that is used when not inheriting from a workspace.\",\n          \"type\": \"string\"\n        },\n        {\n          \"description\": \"The type when inheriting from a workspace.\",\n          \"$ref\": \"#/$defs/TomlInheritedField\"\n        }\n      ]\n    },\n    \"TomlInheritedField\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"workspace\": {\n          \"$ref\": \"#/$defs/WorkspaceValue\"\n        }\n      },\n      \"required\": [\n        \"workspace\"\n      ]\n    },\n    \"WorkspaceValue\": {\n      \"type\": \"boolean\"\n    },\n    \"InheritableField2\": {\n      \"description\": \"An enum that allows for inheriting keys from a workspace in a Cargo.toml.\",\n      \"anyOf\": [\n        {\n          \"description\": \"The type that is used when not inheriting from a workspace.\",\n          \"$ref\": \"#/$defs/SemVer\"\n        },\n        {\n          \"description\": \"The type when inheriting from a workspace.\",\n          \"$ref\": \"#/$defs/TomlInheritedField\"\n        }\n      ]\n    },\n    \"SemVer\": {\n      \"type\": \"string\",\n      \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n    },\n    \"InheritableField3\": {\n      \"description\": \"An enum that allows for inheriting keys from a workspace in a Cargo.toml.\",\n      \"anyOf\": [\n        {\n          \"description\": \"The type that is used when not inheriting from a workspace.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        {\n          \"description\": \"The type when inheriting from a workspace.\",\n          \"$ref\": \"#/$defs/TomlInheritedField\"\n        }\n      ]\n    },\n    \"TomlPackageBuild\": {\n      \"anyOf\": [\n        {\n          \"description\": \"If build scripts are disabled or enabled.\\nIf true, `build.rs` in the root folder will be the build script.\",\n          \"type\": \"boolean\"\n        },\n        {\n          \"description\": \"Path of Build Script if there's just one script.\",\n          \"type\": \"string\"\n        },\n        {\n          \"description\": \"Vector of paths if multiple build script are to be used.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        }\n      ]\n    },\n    \"StringOrVec\": {\n      \"description\": \"This can be parsed from either a TOML string or array,\\nbut is always stored as a vector.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"string\"\n      }\n    },\n    \"InheritableField4\": {\n      \"description\": \"An enum that allows for inheriting keys from a workspace in a Cargo.toml.\",\n      \"anyOf\": [\n        {\n          \"description\": \"The type that is used when not inheriting from a workspace.\",\n          \"$ref\": \"#/$defs/VecStringOrBool\"\n        },\n        {\n          \"description\": \"The type when inheriting from a workspace.\",\n          \"$ref\": \"#/$defs/TomlInheritedField\"\n        }\n      ]\n    },\n    \"VecStringOrBool\": {\n      \"anyOf\": [\n        {\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        {\n          \"type\": \"boolean\"\n        }\n      ]\n    },\n    \"InheritableField5\": {\n      \"description\": \"An enum that allows for inheriting keys from a workspace in a Cargo.toml.\",\n      \"anyOf\": [\n        {\n          \"description\": \"The type that is used when not inheriting from a workspace.\",\n          \"$ref\": \"#/$defs/StringOrBool\"\n        },\n        {\n          \"description\": \"The type when inheriting from a workspace.\",\n          \"$ref\": \"#/$defs/TomlInheritedField\"\n        }\n      ]\n    },\n    \"StringOrBool\": {\n      \"anyOf\": [\n        {\n          \"type\": \"string\"\n        },\n        {\n          \"type\": \"boolean\"\n        }\n      ]\n    },\n    \"TomlValue\": true,\n    \"TomlTarget\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"name\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"crate-type\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"crate_type\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"path\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"filename\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"test\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"doctest\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"bench\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"doc\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"doc-scrape-examples\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"proc-macro\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"proc_macro\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"harness\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"required-features\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"edition\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        }\n      }\n    },\n    \"InheritableDependency\": {\n      \"anyOf\": [\n        {\n          \"description\": \"The type that is used when not inheriting from a workspace.\",\n          \"$ref\": \"#/$defs/TomlDependency\"\n        },\n        {\n          \"description\": \"The type when inheriting from a workspace.\",\n          \"$ref\": \"#/$defs/TomlInheritedDependency\"\n        }\n      ]\n    },\n    \"TomlDependency\": {\n      \"anyOf\": [\n        {\n          \"description\": \"In the simple format, only a version is specified, eg.\\n`package = \\\"<version>\\\"`\",\n          \"type\": \"string\"\n        },\n        {\n          \"description\": \"The simple format is equivalent to a detailed dependency\\nspecifying only a version, eg.\\n`package = { version = \\\"<version>\\\" }`\",\n          \"$ref\": \"#/$defs/TomlDetailedDependency\"\n        }\n      ]\n    },\n    \"TomlDetailedDependency\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"version\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"registry\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"registry-index\": {\n          \"description\": \"The URL of the `registry` field.\\nThis is an internal implementation detail. When Cargo creates a\\npackage, it replaces `registry` with `registry-index` so that the\\nmanifest contains the correct URL. All users won't have the same\\nregistry names configured, so Cargo can't rely on just the name for\\ncrates published by other users.\",\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"path\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"base\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"git\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"branch\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"tag\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"rev\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"features\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"optional\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"default-features\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"default_features\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"package\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"public\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"artifact\": {\n          \"description\": \"One or more of `bin`, `cdylib`, `staticlib`, `bin:<name>`.\",\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/StringOrVec\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"lib\": {\n          \"description\": \"If set, the artifact should also be a dependency\",\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"target\": {\n          \"description\": \"A platform name, like `x86_64-apple-darwin`\",\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        }\n      }\n    },\n    \"TomlInheritedDependency\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"workspace\": {\n          \"type\": \"boolean\"\n        },\n        \"features\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"default-features\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"default_features\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"optional\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        },\n        \"public\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ]\n        }\n      },\n      \"required\": [\n        \"workspace\"\n      ]\n    },\n    \"TomlPlatform\": {\n      \"description\": \"Corresponds to a `target` entry, but `TomlTarget` is already used.\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"dependencies\": {\n          \"type\": [\n            \"object\",\n            \"null\"\n          ],\n          \"additionalProperties\": {\n            \"$ref\": \"#/$defs/InheritableDependency\"\n          }\n        },\n        \"build-dependencies\": {\n          \"type\": [\n            \"object\",\n            \"null\"\n          ],\n          \"additionalProperties\": {\n            \"$ref\": \"#/$defs/InheritableDependency\"\n          }\n        },\n        \"build_dependencies\": {\n          \"type\": [\n            \"object\",\n            \"null\"\n          ],\n          \"additionalProperties\": {\n            \"$ref\": \"#/$defs/InheritableDependency\"\n          }\n        },\n        \"dev-dependencies\": {\n          \"type\": [\n            \"object\",\n            \"null\"\n          ],\n          \"additionalProperties\": {\n            \"$ref\": \"#/$defs/InheritableDependency\"\n          }\n        },\n        \"dev_dependencies\": {\n          \"type\": [\n            \"object\",\n            \"null\"\n          ],\n          \"additionalProperties\": {\n            \"$ref\": \"#/$defs/InheritableDependency\"\n          }\n        }\n      }\n    },\n    \"InheritableLints\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"workspace\": {\n          \"type\": \"boolean\"\n        }\n      },\n      \"additionalProperties\": {\n        \"type\": \"object\",\n        \"additionalProperties\": {\n          \"$ref\": \"#/$defs/TomlLint\"\n        }\n      }\n    },\n    \"TomlLint\": {\n      \"anyOf\": [\n        {\n          \"$ref\": \"#/$defs/TomlLintLevel\"\n        },\n        {\n          \"$ref\": \"#/$defs/TomlLintConfig\"\n        }\n      ]\n    },\n    \"TomlLintLevel\": {\n      \"type\": \"string\",\n      \"enum\": [\n        \"forbid\",\n        \"deny\",\n        \"warn\",\n        \"allow\"\n      ]\n    },\n    \"TomlLintConfig\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"level\": {\n          \"$ref\": \"#/$defs/TomlLintLevel\"\n        },\n        \"priority\": {\n          \"type\": \"integer\",\n          \"format\": \"int8\",\n          \"minimum\": -128,\n          \"maximum\": 127,\n          \"default\": 0\n        }\n      },\n      \"required\": [\n        \"level\"\n      ],\n      \"additionalProperties\": {\n        \"$ref\": \"#/$defs/TomlValue\"\n      }\n    },\n    \"Hints\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"mostly-unused\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/TomlValue\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        }\n      }\n    },\n    \"TomlWorkspace\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"members\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"exclude\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"default-members\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"resolver\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"metadata\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/TomlValue\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"package\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/InheritablePackage\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"dependencies\": {\n          \"type\": [\n            \"object\",\n            \"null\"\n          ],\n          \"additionalProperties\": {\n            \"$ref\": \"#/$defs/TomlDependency\"\n          }\n        },\n        \"lints\": {\n          \"type\": [\n            \"object\",\n            \"null\"\n          ],\n          \"additionalProperties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": {\n              \"$ref\": \"#/$defs/TomlLint\"\n            }\n          }\n        }\n      }\n    },\n    \"InheritablePackage\": {\n      \"description\": \"A group of fields that are inheritable by members of the workspace\",\n      \"type\": \"object\",\n      \"properties\": {\n        \"version\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/SemVer\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"authors\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"description\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"homepage\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"documentation\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"readme\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/StringOrBool\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"keywords\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"categories\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"license\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"license-file\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"repository\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"publish\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/VecStringOrBool\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"edition\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        },\n        \"badges\": {\n          \"type\": [\n            \"object\",\n            \"null\"\n          ],\n          \"additionalProperties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": {\n              \"type\": \"string\"\n            }\n          }\n        },\n        \"exclude\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"include\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"rust-version\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ]\n        }\n      }\n    },\n    \"TomlProfiles\": {\n      \"type\": \"object\",\n      \"additionalProperties\": {\n        \"$ref\": \"#/$defs/TomlProfile\"\n      }\n    },\n    \"TomlProfile\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"opt-level\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/TomlOptLevel\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"default\": null\n        },\n        \"lto\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/StringOrBool\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"default\": null\n        },\n        \"codegen-backend\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ],\n          \"default\": null\n        },\n        \"codegen-units\": {\n          \"type\": [\n            \"integer\",\n            \"null\"\n          ],\n          \"format\": \"uint32\",\n          \"minimum\": 0,\n          \"default\": null\n        },\n        \"debug\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/TomlDebugInfo\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"default\": null\n        },\n        \"split-debuginfo\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ],\n          \"default\": null\n        },\n        \"debug-assertions\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ],\n          \"default\": null\n        },\n        \"rpath\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ],\n          \"default\": null\n        },\n        \"panic\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ],\n          \"default\": null\n        },\n        \"overflow-checks\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ],\n          \"default\": null\n        },\n        \"incremental\": {\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ],\n          \"default\": null\n        },\n        \"dir-name\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ],\n          \"default\": null\n        },\n        \"inherits\": {\n          \"type\": [\n            \"string\",\n            \"null\"\n          ],\n          \"default\": null\n        },\n        \"strip\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/StringOrBool\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"default\": null\n        },\n        \"rustflags\": {\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"type\": \"string\"\n          },\n          \"default\": null\n        },\n        \"package\": {\n          \"type\": [\n            \"object\",\n            \"null\"\n          ],\n          \"additionalProperties\": {\n            \"$ref\": \"#/$defs/TomlProfile\"\n          },\n          \"default\": null\n        },\n        \"build-override\": {\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/TomlProfile\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"default\": null\n        },\n        \"trim-paths\": {\n          \"description\": \"Unstable feature `-Ztrim-paths`.\",\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/$defs/TomlTrimPaths\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ],\n          \"default\": null\n        },\n        \"hint-mostly-unused\": {\n          \"description\": \"Unstable feature `hint-mostly-unused`\",\n          \"type\": [\n            \"boolean\",\n            \"null\"\n          ],\n          \"default\": null\n        }\n      }\n    },\n    \"TomlOptLevel\": {\n      \"type\": \"string\"\n    },\n    \"TomlDebugInfo\": {\n      \"type\": \"string\",\n      \"enum\": [\n        \"None\",\n        \"LineDirectivesOnly\",\n        \"LineTablesOnly\",\n        \"Limited\",\n        \"Full\"\n      ]\n    },\n    \"PackageIdSpec\": {\n      \"type\": \"string\"\n    },\n    \"TomlTrimPaths\": {\n      \"anyOf\": [\n        {\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"#/$defs/TomlTrimPathsValue\"\n          }\n        },\n        {\n          \"type\": \"null\"\n        }\n      ]\n    },\n    \"TomlTrimPathsValue\": {\n      \"type\": \"string\",\n      \"enum\": [\n        \"diagnostics\",\n        \"macro\",\n        \"object\"\n      ]\n    }\n  }\n}"
  },
  {
    "path": "crates/cargo-util-schemas/src/core/mod.rs",
    "content": "mod package_id_spec;\nmod partial_version;\nmod source_kind;\n\npub use package_id_spec::PackageIdSpec;\npub use package_id_spec::PackageIdSpecError;\npub use partial_version::PartialVersion;\npub use partial_version::PartialVersionError;\npub use source_kind::GitReference;\npub use source_kind::SourceKind;\n"
  },
  {
    "path": "crates/cargo-util-schemas/src/core/package_id_spec.rs",
    "content": "use std::fmt;\n\nuse semver::Version;\nuse serde::{de, ser};\nuse url::Url;\n\nuse crate::core::GitReference;\nuse crate::core::PartialVersion;\nuse crate::core::PartialVersionError;\nuse crate::core::SourceKind;\nuse crate::manifest::PackageName;\nuse crate::restricted_names::NameValidationError;\n\ntype Result<T> = std::result::Result<T, PackageIdSpecError>;\n\n/// Some or all of the data required to identify a package:\n///\n///  1. the package name (a `String`, required)\n///  2. the package version (a `Version`, optional)\n///  3. the package source (a `Url`, optional)\n///\n/// If any of the optional fields are omitted, then the package ID may be ambiguous, there may be\n/// more than one package/version/url combo that will match. However, often just the name is\n/// sufficient to uniquely define a package ID.\n#[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]\npub struct PackageIdSpec {\n    name: String,\n    version: Option<PartialVersion>,\n    url: Option<Url>,\n    kind: Option<SourceKind>,\n}\n\nimpl PackageIdSpec {\n    pub fn new(name: String) -> Self {\n        Self {\n            name,\n            version: None,\n            url: None,\n            kind: None,\n        }\n    }\n\n    pub fn with_version(mut self, version: PartialVersion) -> Self {\n        self.version = Some(version);\n        self\n    }\n\n    pub fn with_url(mut self, url: Url) -> Self {\n        self.url = Some(url);\n        self\n    }\n\n    pub fn with_kind(mut self, kind: SourceKind) -> Self {\n        self.kind = Some(kind);\n        self\n    }\n\n    /// Parses a spec string and returns a `PackageIdSpec` if the string was valid.\n    ///\n    /// # Examples\n    /// Some examples of valid strings\n    ///\n    /// ```\n    /// use cargo_util_schemas::core::PackageIdSpec;\n    ///\n    /// let specs = vec![\n    ///     \"foo\",\n    ///     \"foo@1.4\",\n    ///     \"foo@1.4.3\",\n    ///     \"foo:1.2.3\",\n    ///     \"https://github.com/rust-lang/crates.io-index#foo\",\n    ///     \"https://github.com/rust-lang/crates.io-index#foo@1.4.3\",\n    ///     \"ssh://git@github.com/rust-lang/foo.git#foo@1.4.3\",\n    ///     \"file:///path/to/my/project/foo\",\n    ///     \"file:///path/to/my/project/foo#1.1.8\"\n    /// ];\n    /// for spec in specs {\n    ///     assert!(PackageIdSpec::parse(spec).is_ok());\n    /// }\n    pub fn parse(spec: &str) -> Result<PackageIdSpec> {\n        if spec.contains(\"://\") {\n            if let Ok(url) = Url::parse(spec) {\n                return PackageIdSpec::from_url(url);\n            }\n        } else if spec.contains('/') || spec.contains('\\\\') {\n            let abs = std::env::current_dir().unwrap_or_default().join(spec);\n            if abs.exists() {\n                let maybe_url = Url::from_file_path(abs)\n                    .map_or_else(|_| \"a file:// URL\".to_string(), |url| url.to_string());\n                return Err(ErrorKind::MaybeFilePath {\n                    spec: spec.into(),\n                    maybe_url,\n                }\n                .into());\n            }\n        }\n        let (name, version) = parse_spec(spec)?.unwrap_or_else(|| (spec.to_owned(), None));\n        PackageName::new(&name)?;\n        Ok(PackageIdSpec {\n            name: String::from(name),\n            version,\n            url: None,\n            kind: None,\n        })\n    }\n\n    /// Tries to convert a valid `Url` to a `PackageIdSpec`.\n    fn from_url(mut url: Url) -> Result<PackageIdSpec> {\n        let mut kind = None;\n        if let Some((kind_str, scheme)) = url.scheme().split_once('+') {\n            match kind_str {\n                \"git\" => {\n                    let git_ref = GitReference::from_query(url.query_pairs());\n                    url.set_query(None);\n                    kind = Some(SourceKind::Git(git_ref));\n                    url = strip_url_protocol(&url);\n                }\n                \"registry\" => {\n                    if url.query().is_some() {\n                        return Err(ErrorKind::UnexpectedQueryString(url).into());\n                    }\n                    kind = Some(SourceKind::Registry);\n                    url = strip_url_protocol(&url);\n                }\n                \"sparse\" => {\n                    if url.query().is_some() {\n                        return Err(ErrorKind::UnexpectedQueryString(url).into());\n                    }\n                    kind = Some(SourceKind::SparseRegistry);\n                    // Leave `sparse` as part of URL, see `SourceId::new`\n                    // url = strip_url_protocol(&url);\n                }\n                \"path\" => {\n                    if url.query().is_some() {\n                        return Err(ErrorKind::UnexpectedQueryString(url).into());\n                    }\n                    if scheme != \"file\" {\n                        return Err(ErrorKind::UnsupportedPathPlusScheme(scheme.into()).into());\n                    }\n                    kind = Some(SourceKind::Path);\n                    url = strip_url_protocol(&url);\n                }\n                kind => return Err(ErrorKind::UnsupportedProtocol(kind.into()).into()),\n            }\n        } else {\n            if url.query().is_some() {\n                return Err(ErrorKind::UnexpectedQueryString(url).into());\n            }\n        }\n\n        let frag = url.fragment().map(|s| s.to_owned());\n        url.set_fragment(None);\n\n        let (name, version) = {\n            let Some(path_name) = url.path_segments().and_then(|mut p| p.next_back()) else {\n                return Err(ErrorKind::MissingUrlPath(url).into());\n            };\n            match frag {\n                Some(fragment) => match parse_spec(&fragment)? {\n                    Some((name, ver)) => (name, ver),\n                    None => {\n                        let Some(f) = fragment.chars().next() else {\n                            return Err(PackageIdSpecError(ErrorKind::EmptyFragment));\n                        };\n\n                        if f.is_alphabetic() {\n                            (String::from(fragment.as_str()), None)\n                        } else {\n                            let version = fragment.parse::<PartialVersion>()?;\n                            (String::from(path_name), Some(version))\n                        }\n                    }\n                },\n                None => (String::from(path_name), None),\n            }\n        };\n        PackageName::new(&name)?;\n        Ok(PackageIdSpec {\n            name,\n            version,\n            url: Some(url),\n            kind,\n        })\n    }\n\n    pub fn name(&self) -> &str {\n        self.name.as_str()\n    }\n\n    /// Full `semver::Version`, if present\n    pub fn version(&self) -> Option<Version> {\n        self.version.as_ref().and_then(|v| v.to_version())\n    }\n\n    pub fn partial_version(&self) -> Option<&PartialVersion> {\n        self.version.as_ref()\n    }\n\n    pub fn url(&self) -> Option<&Url> {\n        self.url.as_ref()\n    }\n\n    pub fn set_url(&mut self, url: Url) {\n        self.url = Some(url);\n    }\n\n    pub fn kind(&self) -> Option<&SourceKind> {\n        self.kind.as_ref()\n    }\n\n    pub fn set_kind(&mut self, kind: SourceKind) {\n        self.kind = Some(kind);\n    }\n}\n\nfn parse_spec(spec: &str) -> Result<Option<(String, Option<PartialVersion>)>> {\n    let Some((name, ver)) = spec\n        .rsplit_once('@')\n        .or_else(|| spec.rsplit_once(':').filter(|(n, _)| !n.ends_with(':')))\n    else {\n        return Ok(None);\n    };\n    let name = name.to_owned();\n    let ver = ver.parse::<PartialVersion>()?;\n    Ok(Some((name, Some(ver))))\n}\n\nfn strip_url_protocol(url: &Url) -> Url {\n    // Ridiculous hoop because `Url::set_scheme` errors when changing to http/https\n    let raw = url.to_string();\n    raw.split_once('+').unwrap().1.parse().unwrap()\n}\n\nimpl fmt::Display for PackageIdSpec {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let mut printed_name = false;\n        match self.url {\n            Some(ref url) => {\n                if let Some(protocol) = self.kind.as_ref().and_then(|k| k.protocol()) {\n                    write!(f, \"{protocol}+\")?;\n                }\n                write!(f, \"{}\", url)?;\n                if let Some(SourceKind::Git(git_ref)) = self.kind.as_ref() {\n                    if let Some(pretty) = git_ref.pretty_ref(true) {\n                        write!(f, \"?{}\", pretty)?;\n                    }\n                }\n                if url.path_segments().unwrap().next_back().unwrap() != &*self.name {\n                    printed_name = true;\n                    write!(f, \"#{}\", self.name)?;\n                }\n            }\n            None => {\n                printed_name = true;\n                write!(f, \"{}\", self.name)?;\n            }\n        }\n        if let Some(ref v) = self.version {\n            write!(f, \"{}{}\", if printed_name { \"@\" } else { \"#\" }, v)?;\n        }\n        Ok(())\n    }\n}\n\nimpl ser::Serialize for PackageIdSpec {\n    fn serialize<S>(&self, s: S) -> std::result::Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        self.to_string().serialize(s)\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for PackageIdSpec {\n    fn deserialize<D>(d: D) -> std::result::Result<PackageIdSpec, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        let string = String::deserialize(d)?;\n        PackageIdSpec::parse(&string).map_err(de::Error::custom)\n    }\n}\n\n#[cfg(feature = \"unstable-schema\")]\nimpl schemars::JsonSchema for PackageIdSpec {\n    fn schema_name() -> std::borrow::Cow<'static, str> {\n        \"PackageIdSpec\".into()\n    }\n    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {\n        <String as schemars::JsonSchema>::json_schema(generator)\n    }\n}\n\n#[derive(Debug, thiserror::Error)]\n#[error(transparent)]\npub struct PackageIdSpecError(#[from] ErrorKind);\n\nimpl From<PartialVersionError> for PackageIdSpecError {\n    fn from(value: PartialVersionError) -> Self {\n        ErrorKind::PartialVersion(value).into()\n    }\n}\n\nimpl From<NameValidationError> for PackageIdSpecError {\n    fn from(value: NameValidationError) -> Self {\n        ErrorKind::NameValidation(value).into()\n    }\n}\n\n/// Non-public error kind for [`PackageIdSpecError`].\n#[non_exhaustive]\n#[derive(Debug, thiserror::Error)]\nenum ErrorKind {\n    #[error(\"unsupported source protocol: {0}\")]\n    UnsupportedProtocol(String),\n\n    #[error(\"`path+{0}` is unsupported; `path+file` and `file` schemes are supported\")]\n    UnsupportedPathPlusScheme(String),\n\n    #[error(\"cannot have a query string in a pkgid: {0}\")]\n    UnexpectedQueryString(Url),\n\n    #[error(\"pkgid urls must have at least one path component: {0}\")]\n    MissingUrlPath(Url),\n\n    #[error(\"package ID specification `{spec}` looks like a file path, maybe try {maybe_url}\")]\n    MaybeFilePath { spec: String, maybe_url: String },\n\n    #[error(\"pkgid url cannot have an empty fragment\")]\n    EmptyFragment,\n\n    #[error(transparent)]\n    NameValidation(#[from] crate::restricted_names::NameValidationError),\n\n    #[error(transparent)]\n    PartialVersion(#[from] crate::core::PartialVersionError),\n}\n\n#[cfg(test)]\nmod tests {\n    use super::ErrorKind;\n    use super::PackageIdSpec;\n    use crate::core::{GitReference, SourceKind};\n    use url::Url;\n\n    #[track_caller]\n    fn ok(spec: &str, expected: PackageIdSpec, expected_rendered: &str) {\n        let parsed = PackageIdSpec::parse(spec).unwrap();\n        assert_eq!(parsed, expected);\n        let rendered = parsed.to_string();\n        assert_eq!(rendered, expected_rendered);\n        let reparsed = PackageIdSpec::parse(&rendered).unwrap();\n        assert_eq!(reparsed, expected);\n    }\n\n    macro_rules! err {\n        ($spec:expr, $expected:pat) => {\n            let err = PackageIdSpec::parse($spec).unwrap_err();\n            let kind = err.0;\n            assert!(\n                matches!(kind, $expected),\n                \"`{}` parse error mismatch, got {kind:?}\",\n                $spec\n            );\n        };\n    }\n\n    #[test]\n    fn good_parsing() {\n        ok(\n            \"https://crates.io/foo\",\n            PackageIdSpec {\n                name: String::from(\"foo\"),\n                version: None,\n                url: Some(Url::parse(\"https://crates.io/foo\").unwrap()),\n                kind: None,\n            },\n            \"https://crates.io/foo\",\n        );\n        ok(\n            \"https://crates.io/foo#1.2.3\",\n            PackageIdSpec {\n                name: String::from(\"foo\"),\n                version: Some(\"1.2.3\".parse().unwrap()),\n                url: Some(Url::parse(\"https://crates.io/foo\").unwrap()),\n                kind: None,\n            },\n            \"https://crates.io/foo#1.2.3\",\n        );\n        ok(\n            \"https://crates.io/foo#1.2\",\n            PackageIdSpec {\n                name: String::from(\"foo\"),\n                version: Some(\"1.2\".parse().unwrap()),\n                url: Some(Url::parse(\"https://crates.io/foo\").unwrap()),\n                kind: None,\n            },\n            \"https://crates.io/foo#1.2\",\n        );\n        ok(\n            \"https://crates.io/foo#bar:1.2.3\",\n            PackageIdSpec {\n                name: String::from(\"bar\"),\n                version: Some(\"1.2.3\".parse().unwrap()),\n                url: Some(Url::parse(\"https://crates.io/foo\").unwrap()),\n                kind: None,\n            },\n            \"https://crates.io/foo#bar@1.2.3\",\n        );\n        ok(\n            \"https://crates.io/foo#bar@1.2.3\",\n            PackageIdSpec {\n                name: String::from(\"bar\"),\n                version: Some(\"1.2.3\".parse().unwrap()),\n                url: Some(Url::parse(\"https://crates.io/foo\").unwrap()),\n                kind: None,\n            },\n            \"https://crates.io/foo#bar@1.2.3\",\n        );\n        ok(\n            \"https://crates.io/foo#bar@1.2\",\n            PackageIdSpec {\n                name: String::from(\"bar\"),\n                version: Some(\"1.2\".parse().unwrap()),\n                url: Some(Url::parse(\"https://crates.io/foo\").unwrap()),\n                kind: None,\n            },\n            \"https://crates.io/foo#bar@1.2\",\n        );\n        ok(\n            \"registry+https://crates.io/foo#bar@1.2\",\n            PackageIdSpec {\n                name: String::from(\"bar\"),\n                version: Some(\"1.2\".parse().unwrap()),\n                url: Some(Url::parse(\"https://crates.io/foo\").unwrap()),\n                kind: Some(SourceKind::Registry),\n            },\n            \"registry+https://crates.io/foo#bar@1.2\",\n        );\n        ok(\n            \"sparse+https://crates.io/foo#bar@1.2\",\n            PackageIdSpec {\n                name: String::from(\"bar\"),\n                version: Some(\"1.2\".parse().unwrap()),\n                url: Some(Url::parse(\"sparse+https://crates.io/foo\").unwrap()),\n                kind: Some(SourceKind::SparseRegistry),\n            },\n            \"sparse+https://crates.io/foo#bar@1.2\",\n        );\n        ok(\n            \"foo\",\n            PackageIdSpec {\n                name: String::from(\"foo\"),\n                version: None,\n                url: None,\n                kind: None,\n            },\n            \"foo\",\n        );\n        ok(\n            \"foo::bar\",\n            PackageIdSpec {\n                name: String::from(\"foo::bar\"),\n                version: None,\n                url: None,\n                kind: None,\n            },\n            \"foo::bar\",\n        );\n        ok(\n            \"foo:1.2.3\",\n            PackageIdSpec {\n                name: String::from(\"foo\"),\n                version: Some(\"1.2.3\".parse().unwrap()),\n                url: None,\n                kind: None,\n            },\n            \"foo@1.2.3\",\n        );\n        ok(\n            \"foo::bar:1.2.3\",\n            PackageIdSpec {\n                name: String::from(\"foo::bar\"),\n                version: Some(\"1.2.3\".parse().unwrap()),\n                url: None,\n                kind: None,\n            },\n            \"foo::bar@1.2.3\",\n        );\n        ok(\n            \"foo@1.2.3\",\n            PackageIdSpec {\n                name: String::from(\"foo\"),\n                version: Some(\"1.2.3\".parse().unwrap()),\n                url: None,\n                kind: None,\n            },\n            \"foo@1.2.3\",\n        );\n        ok(\n            \"foo::bar@1.2.3\",\n            PackageIdSpec {\n                name: String::from(\"foo::bar\"),\n                version: Some(\"1.2.3\".parse().unwrap()),\n                url: None,\n                kind: None,\n            },\n            \"foo::bar@1.2.3\",\n        );\n        ok(\n            \"foo@1.2\",\n            PackageIdSpec {\n                name: String::from(\"foo\"),\n                version: Some(\"1.2\".parse().unwrap()),\n                url: None,\n                kind: None,\n            },\n            \"foo@1.2\",\n        );\n\n        // pkgid-spec.md\n        ok(\n            \"regex\",\n            PackageIdSpec {\n                name: String::from(\"regex\"),\n                version: None,\n                url: None,\n                kind: None,\n            },\n            \"regex\",\n        );\n        ok(\n            \"regex@1.4\",\n            PackageIdSpec {\n                name: String::from(\"regex\"),\n                version: Some(\"1.4\".parse().unwrap()),\n                url: None,\n                kind: None,\n            },\n            \"regex@1.4\",\n        );\n        ok(\n            \"regex@1.4.3\",\n            PackageIdSpec {\n                name: String::from(\"regex\"),\n                version: Some(\"1.4.3\".parse().unwrap()),\n                url: None,\n                kind: None,\n            },\n            \"regex@1.4.3\",\n        );\n        ok(\n            \"https://github.com/rust-lang/crates.io-index#regex\",\n            PackageIdSpec {\n                name: String::from(\"regex\"),\n                version: None,\n                url: Some(Url::parse(\"https://github.com/rust-lang/crates.io-index\").unwrap()),\n                kind: None,\n            },\n            \"https://github.com/rust-lang/crates.io-index#regex\",\n        );\n        ok(\n            \"https://github.com/rust-lang/crates.io-index#regex@1.4.3\",\n            PackageIdSpec {\n                name: String::from(\"regex\"),\n                version: Some(\"1.4.3\".parse().unwrap()),\n                url: Some(Url::parse(\"https://github.com/rust-lang/crates.io-index\").unwrap()),\n                kind: None,\n            },\n            \"https://github.com/rust-lang/crates.io-index#regex@1.4.3\",\n        );\n        ok(\n            \"sparse+https://github.com/rust-lang/crates.io-index#regex@1.4.3\",\n            PackageIdSpec {\n                name: String::from(\"regex\"),\n                version: Some(\"1.4.3\".parse().unwrap()),\n                url: Some(\n                    Url::parse(\"sparse+https://github.com/rust-lang/crates.io-index\").unwrap(),\n                ),\n                kind: Some(SourceKind::SparseRegistry),\n            },\n            \"sparse+https://github.com/rust-lang/crates.io-index#regex@1.4.3\",\n        );\n        ok(\n            \"https://github.com/rust-lang/cargo#0.52.0\",\n            PackageIdSpec {\n                name: String::from(\"cargo\"),\n                version: Some(\"0.52.0\".parse().unwrap()),\n                url: Some(Url::parse(\"https://github.com/rust-lang/cargo\").unwrap()),\n                kind: None,\n            },\n            \"https://github.com/rust-lang/cargo#0.52.0\",\n        );\n        ok(\n            \"https://github.com/rust-lang/cargo#cargo-platform@0.1.2\",\n            PackageIdSpec {\n                name: String::from(\"cargo-platform\"),\n                version: Some(\"0.1.2\".parse().unwrap()),\n                url: Some(Url::parse(\"https://github.com/rust-lang/cargo\").unwrap()),\n                kind: None,\n            },\n            \"https://github.com/rust-lang/cargo#cargo-platform@0.1.2\",\n        );\n        ok(\n            \"ssh://git@github.com/rust-lang/regex.git#regex@1.4.3\",\n            PackageIdSpec {\n                name: String::from(\"regex\"),\n                version: Some(\"1.4.3\".parse().unwrap()),\n                url: Some(Url::parse(\"ssh://git@github.com/rust-lang/regex.git\").unwrap()),\n                kind: None,\n            },\n            \"ssh://git@github.com/rust-lang/regex.git#regex@1.4.3\",\n        );\n        ok(\n            \"git+ssh://git@github.com/rust-lang/regex.git#regex@1.4.3\",\n            PackageIdSpec {\n                name: String::from(\"regex\"),\n                version: Some(\"1.4.3\".parse().unwrap()),\n                url: Some(Url::parse(\"ssh://git@github.com/rust-lang/regex.git\").unwrap()),\n                kind: Some(SourceKind::Git(GitReference::DefaultBranch)),\n            },\n            \"git+ssh://git@github.com/rust-lang/regex.git#regex@1.4.3\",\n        );\n        ok(\n            \"git+ssh://git@github.com/rust-lang/regex.git?branch=dev#regex@1.4.3\",\n            PackageIdSpec {\n                name: String::from(\"regex\"),\n                version: Some(\"1.4.3\".parse().unwrap()),\n                url: Some(Url::parse(\"ssh://git@github.com/rust-lang/regex.git\").unwrap()),\n                kind: Some(SourceKind::Git(GitReference::Branch(\"dev\".to_owned()))),\n            },\n            \"git+ssh://git@github.com/rust-lang/regex.git?branch=dev#regex@1.4.3\",\n        );\n        ok(\n            \"file:///path/to/my/project/foo\",\n            PackageIdSpec {\n                name: String::from(\"foo\"),\n                version: None,\n                url: Some(Url::parse(\"file:///path/to/my/project/foo\").unwrap()),\n                kind: None,\n            },\n            \"file:///path/to/my/project/foo\",\n        );\n        ok(\n            \"file:///path/to/my/project/foo::bar\",\n            PackageIdSpec {\n                name: String::from(\"foo::bar\"),\n                version: None,\n                url: Some(Url::parse(\"file:///path/to/my/project/foo::bar\").unwrap()),\n                kind: None,\n            },\n            \"file:///path/to/my/project/foo::bar\",\n        );\n        ok(\n            \"file:///path/to/my/project/foo#1.1.8\",\n            PackageIdSpec {\n                name: String::from(\"foo\"),\n                version: Some(\"1.1.8\".parse().unwrap()),\n                url: Some(Url::parse(\"file:///path/to/my/project/foo\").unwrap()),\n                kind: None,\n            },\n            \"file:///path/to/my/project/foo#1.1.8\",\n        );\n        ok(\n            \"path+file:///path/to/my/project/foo#1.1.8\",\n            PackageIdSpec {\n                name: String::from(\"foo\"),\n                version: Some(\"1.1.8\".parse().unwrap()),\n                url: Some(Url::parse(\"file:///path/to/my/project/foo\").unwrap()),\n                kind: Some(SourceKind::Path),\n            },\n            \"path+file:///path/to/my/project/foo#1.1.8\",\n        );\n        ok(\n            \"path+file:///path/to/my/project/foo#bar\",\n            PackageIdSpec {\n                name: String::from(\"bar\"),\n                version: None,\n                url: Some(Url::parse(\"file:///path/to/my/project/foo\").unwrap()),\n                kind: Some(SourceKind::Path),\n            },\n            \"path+file:///path/to/my/project/foo#bar\",\n        );\n        ok(\n            \"path+file:///path/to/my/project/foo#foo::bar\",\n            PackageIdSpec {\n                name: String::from(\"foo::bar\"),\n                version: None,\n                url: Some(Url::parse(\"file:///path/to/my/project/foo\").unwrap()),\n                kind: Some(SourceKind::Path),\n            },\n            \"path+file:///path/to/my/project/foo#foo::bar\",\n        );\n        ok(\n            \"path+file:///path/to/my/project/foo#bar:1.1.8\",\n            PackageIdSpec {\n                name: String::from(\"bar\"),\n                version: Some(\"1.1.8\".parse().unwrap()),\n                url: Some(Url::parse(\"file:///path/to/my/project/foo\").unwrap()),\n                kind: Some(SourceKind::Path),\n            },\n            \"path+file:///path/to/my/project/foo#bar@1.1.8\",\n        );\n        ok(\n            \"path+file:///path/to/my/project/foo#foo::bar:1.1.8\",\n            PackageIdSpec {\n                name: String::from(\"foo::bar\"),\n                version: Some(\"1.1.8\".parse().unwrap()),\n                url: Some(Url::parse(\"file:///path/to/my/project/foo\").unwrap()),\n                kind: Some(SourceKind::Path),\n            },\n            \"path+file:///path/to/my/project/foo#foo::bar@1.1.8\",\n        );\n        ok(\n            \"path+file:///path/to/my/project/foo#bar@1.1.8\",\n            PackageIdSpec {\n                name: String::from(\"bar\"),\n                version: Some(\"1.1.8\".parse().unwrap()),\n                url: Some(Url::parse(\"file:///path/to/my/project/foo\").unwrap()),\n                kind: Some(SourceKind::Path),\n            },\n            \"path+file:///path/to/my/project/foo#bar@1.1.8\",\n        );\n        ok(\n            \"path+file:///path/to/my/project/foo#foo::bar@1.1.8\",\n            PackageIdSpec {\n                name: String::from(\"foo::bar\"),\n                version: Some(\"1.1.8\".parse().unwrap()),\n                url: Some(Url::parse(\"file:///path/to/my/project/foo\").unwrap()),\n                kind: Some(SourceKind::Path),\n            },\n            \"path+file:///path/to/my/project/foo#foo::bar@1.1.8\",\n        );\n    }\n\n    #[test]\n    fn bad_parsing() {\n        err!(\"baz:\", ErrorKind::PartialVersion(_));\n        err!(\"baz:*\", ErrorKind::PartialVersion(_));\n        err!(\"baz@\", ErrorKind::PartialVersion(_));\n        err!(\"baz@*\", ErrorKind::PartialVersion(_));\n        err!(\"baz@^1.0\", ErrorKind::PartialVersion(_));\n        err!(\"https://baz:1.0\", ErrorKind::NameValidation(_));\n        err!(\"https://#baz:1.0\", ErrorKind::NameValidation(_));\n        err!(\n            \"foobar+https://github.com/rust-lang/crates.io-index\",\n            ErrorKind::UnsupportedProtocol(_)\n        );\n        err!(\n            \"path+https://github.com/rust-lang/crates.io-index\",\n            ErrorKind::UnsupportedPathPlusScheme(_)\n        );\n\n        // Only `git+` can use `?`\n        err!(\n            \"file:///path/to/my/project/foo?branch=dev\",\n            ErrorKind::UnexpectedQueryString(_)\n        );\n        err!(\n            \"path+file:///path/to/my/project/foo?branch=dev\",\n            ErrorKind::UnexpectedQueryString(_)\n        );\n        err!(\n            \"registry+https://github.com/rust-lang/cargo?branch=dev#0.52.0\",\n            ErrorKind::UnexpectedQueryString(_)\n        );\n        err!(\n            \"sparse+https://github.com/rust-lang/cargo?branch=dev#0.52.0\",\n            ErrorKind::UnexpectedQueryString(_)\n        );\n        err!(\"@1.2.3\", ErrorKind::NameValidation(_));\n        err!(\"registry+https://github.com\", ErrorKind::NameValidation(_));\n        err!(\"https://crates.io/1foo#1.2.3\", ErrorKind::NameValidation(_));\n        err!(\"https://example.com/foo#\", ErrorKind::EmptyFragment);\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util-schemas/src/core/partial_version.rs",
    "content": "use std::fmt::{self, Display};\n\nuse semver::{Comparator, Version, VersionReq};\nuse serde_untagged::UntaggedEnumVisitor;\n\n#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug)]\npub struct PartialVersion {\n    pub major: u64,\n    pub minor: Option<u64>,\n    pub patch: Option<u64>,\n    pub pre: Option<semver::Prerelease>,\n    pub build: Option<semver::BuildMetadata>,\n}\n\nimpl PartialVersion {\n    pub fn to_version(&self) -> Option<Version> {\n        Some(Version {\n            major: self.major,\n            minor: self.minor?,\n            patch: self.patch?,\n            pre: self.pre.clone().unwrap_or_default(),\n            build: self.build.clone().unwrap_or_default(),\n        })\n    }\n\n    pub fn to_caret_req(&self) -> VersionReq {\n        VersionReq {\n            comparators: vec![Comparator {\n                op: semver::Op::Caret,\n                major: self.major,\n                minor: self.minor,\n                patch: self.patch,\n                pre: self.pre.as_ref().cloned().unwrap_or_default(),\n            }],\n        }\n    }\n\n    /// Check if this matches a version, including build metadata\n    ///\n    /// Build metadata does not affect version precedence but may be necessary for uniquely\n    /// identifying a package.\n    pub fn matches(&self, version: &Version) -> bool {\n        if !version.pre.is_empty() && self.pre.is_none() {\n            // Pre-release versions must be explicitly opted into, if for no other reason than to\n            // give us room to figure out and define the semantics\n            return false;\n        }\n        self.major == version.major\n            && self.minor.map(|f| f == version.minor).unwrap_or(true)\n            && self.patch.map(|f| f == version.patch).unwrap_or(true)\n            && self.pre.as_ref().map(|f| f == &version.pre).unwrap_or(true)\n            && self\n                .build\n                .as_ref()\n                .map(|f| f == &version.build)\n                .unwrap_or(true)\n    }\n}\n\nimpl From<semver::Version> for PartialVersion {\n    fn from(ver: semver::Version) -> Self {\n        let pre = if ver.pre.is_empty() {\n            None\n        } else {\n            Some(ver.pre)\n        };\n        let build = if ver.build.is_empty() {\n            None\n        } else {\n            Some(ver.build)\n        };\n        Self {\n            major: ver.major,\n            minor: Some(ver.minor),\n            patch: Some(ver.patch),\n            pre,\n            build,\n        }\n    }\n}\n\nimpl std::str::FromStr for PartialVersion {\n    type Err = PartialVersionError;\n\n    fn from_str(value: &str) -> Result<Self, Self::Err> {\n        match semver::Version::parse(value) {\n            Ok(ver) => Ok(ver.into()),\n            Err(_) => {\n                // HACK: Leverage `VersionReq` for partial version parsing\n                let mut version_req = match semver::VersionReq::parse(value) {\n                    Ok(req) => req,\n                    Err(_) if value.contains('-') => return Err(ErrorKind::Prerelease.into()),\n                    Err(_) if value.contains('+') => return Err(ErrorKind::BuildMetadata.into()),\n                    Err(_) => return Err(ErrorKind::Unexpected.into()),\n                };\n                if version_req.comparators.len() != 1 {\n                    return Err(ErrorKind::VersionReq.into());\n                }\n                let comp = version_req.comparators.pop().unwrap();\n                if comp.op != semver::Op::Caret {\n                    return Err(ErrorKind::VersionReq.into());\n                } else if value.starts_with('^') {\n                    // Can't distinguish between `^` present or not\n                    return Err(ErrorKind::VersionReq.into());\n                }\n                let pre = if comp.pre.is_empty() {\n                    None\n                } else {\n                    Some(comp.pre)\n                };\n                Ok(Self {\n                    major: comp.major,\n                    minor: comp.minor,\n                    patch: comp.patch,\n                    pre,\n                    build: None,\n                })\n            }\n        }\n    }\n}\n\nimpl Display for PartialVersion {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let major = self.major;\n        write!(f, \"{major}\")?;\n        if let Some(minor) = self.minor {\n            write!(f, \".{minor}\")?;\n        }\n        if let Some(patch) = self.patch {\n            write!(f, \".{patch}\")?;\n        }\n        if let Some(pre) = self.pre.as_ref() {\n            write!(f, \"-{pre}\")?;\n        }\n        if let Some(build) = self.build.as_ref() {\n            write!(f, \"+{build}\")?;\n        }\n        Ok(())\n    }\n}\n\nimpl serde::Serialize for PartialVersion {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: serde::Serializer,\n    {\n        serializer.collect_str(self)\n    }\n}\n\nimpl<'de> serde::Deserialize<'de> for PartialVersion {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        UntaggedEnumVisitor::new()\n            .expecting(\"SemVer version\")\n            .string(|value| value.parse().map_err(serde::de::Error::custom))\n            .deserialize(deserializer)\n    }\n}\n\n/// Error parsing a [`PartialVersion`].\n#[derive(Debug, thiserror::Error)]\n#[error(transparent)]\npub struct PartialVersionError(#[from] ErrorKind);\n\n/// Non-public error kind for [`PartialVersionError`].\n#[non_exhaustive]\n#[derive(Debug, thiserror::Error)]\nenum ErrorKind {\n    #[error(\"unexpected version requirement, expected a version like \\\"1.32\\\"\")]\n    VersionReq,\n\n    #[error(\"unexpected prerelease field, expected a version like \\\"1.32\\\"\")]\n    Prerelease,\n\n    #[error(\"unexpected build field, expected a version like \\\"1.32\\\"\")]\n    BuildMetadata,\n\n    #[error(\"expected a version like \\\"1.32\\\"\")]\n    Unexpected,\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use snapbox::prelude::*;\n    use snapbox::str;\n\n    #[test]\n    fn parse_success() {\n        let cases = &[\n            // Valid pre-release\n            (\"1.43.0-beta.1\", str![\"1.43.0-beta.1\"]),\n            // Valid pre-release with wildcard\n            (\"1.43.0-beta.1.x\", str![\"1.43.0-beta.1.x\"]),\n        ];\n        for (input, expected) in cases {\n            let actual: Result<PartialVersion, _> = input.parse();\n            let actual = match actual {\n                Ok(result) => result.to_string(),\n                Err(err) => format!(\"didn't pass: {err}\"),\n            };\n            snapbox::assert_data_eq!(actual, expected.clone().raw());\n        }\n    }\n\n    #[test]\n    fn parse_errors() {\n        let cases = &[\n            // Disallow caret\n            (\n                \"^1.43\",\n                str![[r#\"unexpected version requirement, expected a version like \"1.32\"\"#]],\n            ),\n            // Bad pre-release\n            (\n                \"1.43-beta.1\",\n                str![[r#\"unexpected prerelease field, expected a version like \"1.32\"\"#]],\n            ),\n            // Weird wildcard\n            (\n                \"x\",\n                str![[r#\"unexpected version requirement, expected a version like \"1.32\"\"#]],\n            ),\n            (\n                \"1.x\",\n                str![[r#\"unexpected version requirement, expected a version like \"1.32\"\"#]],\n            ),\n            (\n                \"1.1.x\",\n                str![[r#\"unexpected version requirement, expected a version like \"1.32\"\"#]],\n            ),\n            // Non-sense\n            (\"foodaddle\", str![[r#\"expected a version like \"1.32\"\"#]]),\n        ];\n        for (input, expected) in cases {\n            let actual: Result<PartialVersion, _> = input.parse();\n            let actual = match actual {\n                Ok(result) => format!(\"didn't fail: {result:?}\"),\n                Err(err) => err.to_string(),\n            };\n            snapbox::assert_data_eq!(actual, expected.clone().raw());\n        }\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util-schemas/src/core/source_kind.rs",
    "content": "use std::cmp::Ordering;\n\n/// The possible kinds of code source.\n#[derive(Debug, Clone, PartialEq, Eq)]\npub enum SourceKind {\n    /// A git repository.\n    Git(GitReference),\n    /// A local path.\n    Path,\n    /// A remote registry.\n    Registry,\n    /// A sparse registry.\n    SparseRegistry,\n    /// A local filesystem-based registry.\n    LocalRegistry,\n    /// A directory-based registry.\n    Directory,\n}\n\n// The hash here is important for what folder packages get downloaded into.\n// Changes trigger all users to download another copy of their crates.\n// So the `stable_hash` test checks that we only change it intentionally.\n// We implement hash manually to callout the stability impact.\nimpl std::hash::Hash for SourceKind {\n    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n        core::mem::discriminant(self).hash(state);\n        if let SourceKind::Git(git) = self {\n            git.hash(state);\n        }\n    }\n}\n\nimpl SourceKind {\n    pub fn protocol(&self) -> Option<&str> {\n        match self {\n            SourceKind::Path => Some(\"path\"),\n            SourceKind::Git(_) => Some(\"git\"),\n            SourceKind::Registry => Some(\"registry\"),\n            // Sparse registry URL already includes the `sparse+` prefix, see `SourceId::new`\n            SourceKind::SparseRegistry => None,\n            SourceKind::LocalRegistry => Some(\"local-registry\"),\n            SourceKind::Directory => Some(\"directory\"),\n        }\n    }\n}\n\n// The ordering here is important for how packages are serialized into lock files.\n// We implement it manually to callout the stability guarantee.\n// See https://github.com/rust-lang/cargo/pull/9397 for the history.\nimpl Ord for SourceKind {\n    fn cmp(&self, other: &SourceKind) -> Ordering {\n        match (self, other) {\n            (SourceKind::Path, SourceKind::Path) => Ordering::Equal,\n            (SourceKind::Path, _) => Ordering::Less,\n            (_, SourceKind::Path) => Ordering::Greater,\n\n            (SourceKind::Registry, SourceKind::Registry) => Ordering::Equal,\n            (SourceKind::Registry, _) => Ordering::Less,\n            (_, SourceKind::Registry) => Ordering::Greater,\n\n            (SourceKind::SparseRegistry, SourceKind::SparseRegistry) => Ordering::Equal,\n            (SourceKind::SparseRegistry, _) => Ordering::Less,\n            (_, SourceKind::SparseRegistry) => Ordering::Greater,\n\n            (SourceKind::LocalRegistry, SourceKind::LocalRegistry) => Ordering::Equal,\n            (SourceKind::LocalRegistry, _) => Ordering::Less,\n            (_, SourceKind::LocalRegistry) => Ordering::Greater,\n\n            (SourceKind::Directory, SourceKind::Directory) => Ordering::Equal,\n            (SourceKind::Directory, _) => Ordering::Less,\n            (_, SourceKind::Directory) => Ordering::Greater,\n\n            (SourceKind::Git(a), SourceKind::Git(b)) => a.cmp(b),\n        }\n    }\n}\n\n/// Forwards to `Ord`\nimpl PartialOrd for SourceKind {\n    fn partial_cmp(&self, other: &SourceKind) -> Option<Ordering> {\n        Some(self.cmp(other))\n    }\n}\n\n/// Information to find a specific commit in a Git repository.\n#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]\npub enum GitReference {\n    /// From a tag.\n    Tag(String),\n    /// From a branch.\n    Branch(String),\n    /// From a specific revision. Can be a commit hash (either short or full),\n    /// or a named reference like `refs/pull/493/head`.\n    Rev(String),\n    /// The default branch of the repository, the reference named `HEAD`.\n    DefaultBranch,\n}\n\nimpl GitReference {\n    pub fn from_query(\n        query_pairs: impl Iterator<Item = (impl AsRef<str>, impl AsRef<str>)>,\n    ) -> Self {\n        let mut reference = GitReference::DefaultBranch;\n        for (k, v) in query_pairs {\n            let v = v.as_ref();\n            match k.as_ref() {\n                // Map older 'ref' to branch.\n                \"branch\" | \"ref\" => reference = GitReference::Branch(v.to_owned()),\n\n                \"rev\" => reference = GitReference::Rev(v.to_owned()),\n                \"tag\" => reference = GitReference::Tag(v.to_owned()),\n                _ => {}\n            }\n        }\n        reference\n    }\n\n    /// Returns a `Display`able view of this git reference, or None if using\n    /// the head of the default branch\n    pub fn pretty_ref(&self, url_encoded: bool) -> Option<PrettyRef<'_>> {\n        match self {\n            GitReference::DefaultBranch => None,\n            _ => Some(PrettyRef {\n                inner: self,\n                url_encoded,\n            }),\n        }\n    }\n}\n\n/// A git reference that can be `Display`ed\npub struct PrettyRef<'a> {\n    inner: &'a GitReference,\n    url_encoded: bool,\n}\n\nimpl<'a> std::fmt::Display for PrettyRef<'a> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let value: &str;\n        match self.inner {\n            GitReference::Branch(s) => {\n                write!(f, \"branch=\")?;\n                value = s;\n            }\n            GitReference::Tag(s) => {\n                write!(f, \"tag=\")?;\n                value = s;\n            }\n            GitReference::Rev(s) => {\n                write!(f, \"rev=\")?;\n                value = s;\n            }\n            GitReference::DefaultBranch => unreachable!(),\n        }\n        if self.url_encoded {\n            for value in url::form_urlencoded::byte_serialize(value.as_bytes()) {\n                write!(f, \"{value}\")?;\n            }\n        } else {\n            write!(f, \"{value}\")?;\n        }\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util-schemas/src/index.rs",
    "content": "use crate::manifest::RustVersion;\nuse semver::Version;\nuse serde::{Deserialize, Serialize};\nuse std::{borrow::Cow, collections::BTreeMap};\n\n/// A single line in the index representing a single version of a package.\n#[derive(Deserialize, Serialize)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct IndexPackage<'a> {\n    /// Name of the package.\n    #[serde(borrow)]\n    pub name: Cow<'a, str>,\n    /// The version of this dependency.\n    pub vers: Version,\n    /// All kinds of direct dependencies of the package, including dev and\n    /// build dependencies.\n    #[serde(borrow)]\n    pub deps: Vec<RegistryDependency<'a>>,\n    /// Set of features defined for the package, i.e., `[features]` table.\n    #[serde(default)]\n    pub features: BTreeMap<Cow<'a, str>, Vec<Cow<'a, str>>>,\n    /// This field contains features with new, extended syntax. Specifically,\n    /// namespaced features (`dep:`) and weak dependencies (`pkg?/feat`).\n    ///\n    /// This is separated from `features` because versions older than 1.19\n    /// will fail to load due to not being able to parse the new syntax, even\n    /// with a `Cargo.lock` file.\n    pub features2: Option<BTreeMap<Cow<'a, str>, Vec<Cow<'a, str>>>>,\n    /// Checksum for verifying the integrity of the corresponding downloaded package.\n    pub cksum: String,\n    /// If `true`, Cargo will skip this version when resolving.\n    ///\n    /// This was added in 2014. Everything in the crates.io index has this set\n    /// now, so this probably doesn't need to be an option anymore.\n    pub yanked: Option<bool>,\n    /// Native library name this package links to.\n    ///\n    /// Added early 2018 (see <https://github.com/rust-lang/cargo/pull/4978>),\n    /// can be `None` if published before then.\n    pub links: Option<Cow<'a, str>>,\n    /// Required version of rust\n    ///\n    /// Corresponds to `package.rust-version`.\n    ///\n    /// Added in 2023 (see <https://github.com/rust-lang/crates.io/pull/6267>),\n    /// can be `None` if published before then or if not set in the manifest.\n    #[cfg_attr(feature = \"unstable-schema\", schemars(with = \"Option<String>\"))]\n    pub rust_version: Option<RustVersion>,\n    /// The publish time of this package version (optional).\n    ///\n    /// The format is a subset of ISO8601:\n    /// - `yyyy-mm-ddThh:mm:ssZ`\n    /// - no fractional seconds\n    /// - always `Z` for UTC timezone, no timezone offsets supported\n    /// - fields are 0-padded\n    ///\n    /// Example: 2025-11-12T19:30:12Z\n    ///\n    /// This should be the original publish time and not changed on any status changes,\n    /// like [`IndexPackage::yanked`].\n    #[cfg_attr(feature = \"unstable-schema\", schemars(with = \"Option<String>\"))]\n    #[serde(with = \"serde_pubtime\")]\n    #[serde(default)]\n    pub pubtime: Option<jiff::Timestamp>,\n    /// The schema version for this entry.\n    ///\n    /// If this is None, it defaults to version `1`. Entries with unknown\n    /// versions are ignored.\n    ///\n    /// Version `2` schema adds the `features2` field.\n    ///\n    /// Version `3` schema adds `artifact`, `bindep_targes`, and `lib` for\n    /// artifact dependencies support.\n    ///\n    /// This provides a method to safely introduce changes to index entries\n    /// and allow older versions of cargo to ignore newer entries it doesn't\n    /// understand. This is honored as of 1.51, so unfortunately older\n    /// versions will ignore it, and potentially misinterpret version 2 and\n    /// newer entries.\n    ///\n    /// The intent is that versions older than 1.51 will work with a\n    /// pre-existing `Cargo.lock`, but they may not correctly process `cargo\n    /// update` or build a lock from scratch. In that case, cargo may\n    /// incorrectly select a new package that uses a new index schema. A\n    /// workaround is to downgrade any packages that are incompatible with the\n    /// `--precise` flag of `cargo update`.\n    pub v: Option<u32>,\n}\n\n/// A dependency as encoded in the [`IndexPackage`] index JSON.\n#[derive(Deserialize, Serialize, Clone)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct RegistryDependency<'a> {\n    /// Name of the dependency. If the dependency is renamed, the original\n    /// would be stored in [`RegistryDependency::package`].\n    #[serde(borrow)]\n    pub name: Cow<'a, str>,\n    /// The SemVer requirement for this dependency.\n    #[serde(borrow)]\n    pub req: Cow<'a, str>,\n    /// Set of features enabled for this dependency.\n    #[serde(default)]\n    pub features: Vec<Cow<'a, str>>,\n    /// Whether or not this is an optional dependency.\n    #[serde(default)]\n    pub optional: bool,\n    /// Whether or not default features are enabled.\n    #[serde(default = \"default_true\")]\n    pub default_features: bool,\n    /// The target platform for this dependency.\n    pub target: Option<Cow<'a, str>>,\n    /// The dependency kind. \"dev\", \"build\", and \"normal\".\n    pub kind: Option<Cow<'a, str>>,\n    /// The URL of the index of the registry where this dependency is from.\n    /// `None` if it is from the same index.\n    pub registry: Option<Cow<'a, str>>,\n    /// The original name if the dependency is renamed.\n    pub package: Option<Cow<'a, str>>,\n    /// Whether or not this is a public dependency. Unstable. See [RFC 1977].\n    ///\n    /// [RFC 1977]: https://rust-lang.github.io/rfcs/1977-public-private-dependencies.html\n    pub public: Option<bool>,\n    /// The artifacts to build from this dependency.\n    pub artifact: Option<Vec<Cow<'a, str>>>,\n    /// The target for bindep.\n    pub bindep_target: Option<Cow<'a, str>>,\n    /// Whether or not this is a library dependency.\n    #[serde(default)]\n    pub lib: bool,\n}\n\npub fn parse_pubtime(s: &str) -> Result<jiff::Timestamp, jiff::Error> {\n    let dt = jiff::civil::DateTime::strptime(\"%Y-%m-%dT%H:%M:%SZ\", s)?;\n    if s.len() == 20 {\n        let zoned = dt.to_zoned(jiff::tz::TimeZone::UTC)?;\n        let timestamp = zoned.timestamp();\n        Ok(timestamp)\n    } else {\n        Err(jiff::Error::from_args(format_args!(\n            \"padding required for `{s}`\"\n        )))\n    }\n}\n\npub fn format_pubtime(t: jiff::Timestamp) -> String {\n    t.strftime(\"%Y-%m-%dT%H:%M:%SZ\").to_string()\n}\n\nmod serde_pubtime {\n    #[inline]\n    pub(super) fn serialize<S: serde::Serializer>(\n        timestamp: &Option<jiff::Timestamp>,\n        se: S,\n    ) -> Result<S::Ok, S::Error> {\n        match *timestamp {\n            None => se.serialize_none(),\n            Some(ref ts) => {\n                let s = super::format_pubtime(*ts);\n                se.serialize_str(&s)\n            }\n        }\n    }\n\n    #[inline]\n    pub(super) fn deserialize<'de, D: serde::Deserializer<'de>>(\n        de: D,\n    ) -> Result<Option<jiff::Timestamp>, D::Error> {\n        de.deserialize_option(OptionalVisitor(\n            serde_untagged::UntaggedEnumVisitor::new()\n                .expecting(\"date time\")\n                .string(|value| super::parse_pubtime(&value).map_err(serde::de::Error::custom)),\n        ))\n    }\n\n    /// A generic visitor for `Option<DateTime>`.\n    struct OptionalVisitor<V>(V);\n\n    impl<'de, V: serde::de::Visitor<'de, Value = jiff::Timestamp>> serde::de::Visitor<'de>\n        for OptionalVisitor<V>\n    {\n        type Value = Option<jiff::Timestamp>;\n\n        fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n            f.write_str(\"date time\")\n        }\n\n        #[inline]\n        fn visit_some<D: serde::de::Deserializer<'de>>(\n            self,\n            de: D,\n        ) -> Result<Option<jiff::Timestamp>, D::Error> {\n            de.deserialize_str(self.0).map(Some)\n        }\n\n        #[inline]\n        fn visit_none<E: serde::de::Error>(self) -> Result<Option<jiff::Timestamp>, E> {\n            Ok(None)\n        }\n    }\n}\n\nfn default_true() -> bool {\n    true\n}\n\n#[test]\nfn escaped_char_in_index_json_blob() {\n    let _: IndexPackage<'_> = serde_json::from_str(\n        r#\"{\"name\":\"a\",\"vers\":\"0.0.1\",\"deps\":[],\"cksum\":\"bae3\",\"features\":{}}\"#,\n    )\n    .unwrap();\n    let _: IndexPackage<'_> = serde_json::from_str(\n        r#\"{\"name\":\"a\",\"vers\":\"0.0.1\",\"deps\":[],\"cksum\":\"bae3\",\"features\":{\"test\":[\"k\",\"q\"]},\"links\":\"a-sys\"}\"#\n    ).unwrap();\n\n    // Now we add escaped cher all the places they can go\n    // these are not valid, but it should error later than json parsing\n    let _: IndexPackage<'_> = serde_json::from_str(\n        r#\"{\n        \"name\":\"This name has a escaped cher in it \\n\\t\\\" \",\n        \"vers\":\"0.0.1\",\n        \"deps\":[{\n            \"name\": \" \\n\\t\\\" \",\n            \"req\": \" \\n\\t\\\" \",\n            \"features\": [\" \\n\\t\\\" \"],\n            \"optional\": true,\n            \"default_features\": true,\n            \"target\": \" \\n\\t\\\" \",\n            \"kind\": \" \\n\\t\\\" \",\n            \"registry\": \" \\n\\t\\\" \"\n        }],\n        \"cksum\":\"bae3\",\n        \"features\":{\"test \\n\\t\\\" \":[\"k \\n\\t\\\" \",\"q \\n\\t\\\" \"]},\n        \"links\":\" \\n\\t\\\" \"}\"#,\n    )\n    .unwrap();\n}\n\n#[cfg(feature = \"unstable-schema\")]\n#[test]\nfn dump_index_schema() {\n    let schema = schemars::schema_for!(crate::index::IndexPackage<'_>);\n    let dump = serde_json::to_string_pretty(&schema).unwrap();\n    snapbox::assert_data_eq!(dump, snapbox::file!(\"../index.schema.json\").raw());\n}\n\n#[test]\nfn pubtime_format() {\n    use snapbox::str;\n\n    let input = [\n        (\"2025-11-12T19:30:12Z\", Some(str![\"2025-11-12T19:30:12Z\"])),\n        // Padded values\n        (\"2025-01-02T09:03:02Z\", Some(str![\"2025-01-02T09:03:02Z\"])),\n        // Alt timezone format\n        (\"2025-11-12T19:30:12-04\", None),\n        // Alt date/time separator\n        (\"2025-11-12 19:30:12Z\", None),\n        // Non-padded values\n        (\"2025-11-12T19:30:12+4\", None),\n        (\"2025-1-12T19:30:12+4\", None),\n        (\"2025-11-2T19:30:12+4\", None),\n        (\"2025-11-12T9:30:12Z\", None),\n        (\"2025-11-12T19:3:12Z\", None),\n        (\"2025-11-12T19:30:2Z\", None),\n    ];\n    for (input, expected) in input {\n        let (parsed, expected) = match (parse_pubtime(input), expected) {\n            (Ok(_), None) => {\n                panic!(\"`{input}` did not error\");\n            }\n            (Ok(parsed), Some(expected)) => (parsed, expected),\n            (Err(err), Some(_)) => {\n                panic!(\"`{input}` did not parse successfully: {err}\");\n            }\n            _ => {\n                continue;\n            }\n        };\n        let output = format_pubtime(parsed);\n        snapbox::assert_data_eq!(output, expected);\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util-schemas/src/lib.rs",
    "content": "//! Low-level Cargo format schemas\n//!\n//! This is types with logic mostly focused on `serde` and `FromStr` for use in reading files and\n//! parsing command-lines.\n//! Any logic for getting final semantics from these will likely need other tools to process, like\n//! `cargo metadata`.\n//!\n//! > This crate is maintained by the Cargo team for use by the wider\n//! > ecosystem. This crate follows semver compatibility for its APIs.\n\npub mod core;\npub mod index;\npub mod lockfile;\npub mod manifest;\npub mod messages;\n#[cfg(feature = \"unstable-schema\")]\npub mod schema;\n\nmod restricted_names;\n"
  },
  {
    "path": "crates/cargo-util-schemas/src/lockfile.rs",
    "content": "//! `Cargo.lock` / Lockfile schema definition\n\nuse std::collections::BTreeMap;\nuse std::fmt;\nuse std::{cmp::Ordering, str::FromStr};\n\nuse serde::{Deserialize, Serialize, de, ser};\nuse url::Url;\n\nuse crate::core::{GitReference, SourceKind};\n\n/// Serialization of `Cargo.lock`\n#[derive(Serialize, Deserialize, Debug)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlLockfile {\n    /// The lockfile format version (`version =` field).\n    ///\n    /// This field is optional for backward compatibility. Older lockfiles, i.e. V1 and V2, does\n    /// not have the version field serialized.\n    pub version: Option<u32>,\n    /// The list of `[[package]]` entries describing each resolved dependency.\n    pub package: Option<Vec<TomlLockfileDependency>>,\n    /// The `[root]` table describing the root package.\n    ///\n    /// This field is optional for backward compatibility. Older lockfiles have the root package\n    /// separated, whereas newer lockfiles have the root package as part of `[[package]]`.\n    pub root: Option<TomlLockfileDependency>,\n    /// The `[metadata]` table\n    ///\n    ///\n    /// In older lockfile versions, dependency checksums were stored here instead of alongside each\n    /// package entry.\n    pub metadata: Option<TomlLockfileMetadata>,\n    /// The `[patch]` table describing unused patches.\n    ///\n    /// The lockfile stores them as a list of `[[patch.unused]]` entries.\n    #[serde(default, skip_serializing_if = \"TomlLockfilePatch::is_empty\")]\n    pub patch: TomlLockfilePatch,\n}\n\n/// Serialization of lockfiles metadata\n///\n/// Older versions of lockfiles have their dependencies' checksums on this `[metadata]` table.\npub type TomlLockfileMetadata = BTreeMap<String, String>;\n\n/// Serialization of unused patches\n///\n/// Cargo stores patches that were declared but not used during resolution.\n#[derive(Serialize, Deserialize, Debug, Default)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlLockfilePatch {\n    /// The list of unused dependency patches.\n    pub unused: Vec<TomlLockfileDependency>,\n}\n\nimpl TomlLockfilePatch {\n    fn is_empty(&self) -> bool {\n        self.unused.is_empty()\n    }\n}\n\n/// Serialization of lockfiles dependencies\n#[derive(Serialize, Deserialize, Debug, PartialOrd, Ord, PartialEq, Eq)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlLockfileDependency {\n    /// The name of the dependency.\n    pub name: String,\n    /// The version of the dependency.\n    pub version: String,\n    /// The source of the dependency.\n    ///\n    /// Cargo does not serialize path dependencies.\n    pub source: Option<TomlLockfileSourceId>,\n    /// The checksum of the dependency.\n    ///\n    /// In older lockfiles, checksums were not stored here and instead on a separate `[metadata]`\n    /// table (see [`TomlLockfileMetadata`]).\n    pub checksum: Option<String>,\n    /// The transitive dependencies used by this dependency.\n    pub dependencies: Option<Vec<TomlLockfilePackageId>>,\n    /// The replace of the dependency.\n    pub replace: Option<TomlLockfilePackageId>,\n}\n\n/// Serialization of dependency's source\n#[derive(Debug, Clone)]\n#[cfg_attr(\n    feature = \"unstable-schema\",\n    derive(schemars::JsonSchema),\n    schemars(with = \"String\")\n)]\npub struct TomlLockfileSourceId {\n    /// The string representation of the source as it appears in the lockfile.\n    source_str: String,\n    /// The parsed source type, e.g. `git`, `registry`.\n    ///\n    /// Used for sources ordering.\n    kind: SourceKind,\n    /// The parsed URL of the source.\n    ///\n    /// Used for sources ordering.\n    url: Url,\n}\n\nimpl TomlLockfileSourceId {\n    pub fn new(source: String) -> Result<Self, TomlLockfileSourceIdError> {\n        let source_str = source.clone();\n        let (kind, url) = source\n            .split_once('+')\n            .ok_or_else(|| TomlLockfileSourceIdErrorKind::InvalidSource(source.clone()))?;\n\n        // Sparse URLs store the kind prefix (sparse+) in the URL. Therefore, for sparse kinds, we\n        // want to use the raw `source` instead of the split `url`.\n        let url = Url::parse(if kind == \"sparse\" { &source } else { url }).map_err(|msg| {\n            TomlLockfileSourceIdErrorKind::InvalidUrl {\n                url: url.to_string(),\n                msg: msg.to_string(),\n            }\n        })?;\n\n        let kind = match kind {\n            \"git\" => {\n                let reference = GitReference::from_query(url.query_pairs());\n                SourceKind::Git(reference)\n            }\n            \"registry\" => SourceKind::Registry,\n            \"sparse\" => SourceKind::SparseRegistry,\n            \"path\" => SourceKind::Path,\n            kind => {\n                return Err(\n                    TomlLockfileSourceIdErrorKind::UnsupportedSource(kind.to_string()).into(),\n                );\n            }\n        };\n\n        Ok(Self {\n            source_str,\n            kind,\n            url,\n        })\n    }\n\n    pub fn kind(&self) -> &SourceKind {\n        &self.kind\n    }\n\n    pub fn url(&self) -> &Url {\n        &self.url\n    }\n\n    pub fn source_str(&self) -> &String {\n        &self.source_str\n    }\n\n    pub fn as_url(&self) -> impl fmt::Display + '_ {\n        self.source_str.clone()\n    }\n}\n\nimpl ser::Serialize for TomlLockfileSourceId {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        s.collect_str(&self.as_url())\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for TomlLockfileSourceId {\n    fn deserialize<D>(d: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        let s = String::deserialize(d)?;\n        Ok(TomlLockfileSourceId::new(s).map_err(de::Error::custom)?)\n    }\n}\n\nimpl std::hash::Hash for TomlLockfileSourceId {\n    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n        self.kind.hash(state);\n        self.url.hash(state);\n    }\n}\n\nimpl std::cmp::PartialEq for TomlLockfileSourceId {\n    fn eq(&self, other: &Self) -> bool {\n        self.kind == other.kind && self.url == other.url\n    }\n}\n\nimpl std::cmp::Eq for TomlLockfileSourceId {}\n\nimpl PartialOrd for TomlLockfileSourceId {\n    fn partial_cmp(&self, other: &TomlLockfileSourceId) -> Option<Ordering> {\n        Some(self.cmp(other))\n    }\n}\n\nimpl Ord for TomlLockfileSourceId {\n    fn cmp(&self, other: &TomlLockfileSourceId) -> Ordering {\n        self.kind\n            .cmp(&other.kind)\n            .then_with(|| self.url.cmp(&other.url))\n    }\n}\n\n/// Serialization of package IDs.\n///\n/// The version and source are only included when necessary to disambiguate between packages:\n/// - If multiple packages share the same name, the version is included.\n/// - If multiple packages share the same name and version, the source is included.\n#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Clone)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlLockfilePackageId {\n    pub name: String,\n    pub version: Option<String>,\n    pub source: Option<TomlLockfileSourceId>,\n}\n\nimpl fmt::Display for TomlLockfilePackageId {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{}\", self.name)?;\n        if let Some(s) = &self.version {\n            write!(f, \" {}\", s)?;\n        }\n        if let Some(s) = &self.source {\n            write!(f, \" ({})\", s.as_url())?;\n        }\n        Ok(())\n    }\n}\n\nimpl FromStr for TomlLockfilePackageId {\n    type Err = TomlLockfilePackageIdError;\n\n    fn from_str(s: &str) -> Result<TomlLockfilePackageId, Self::Err> {\n        let mut s = s.splitn(3, ' ');\n        let name = s.next().unwrap();\n        let version = s.next();\n        let source_id = match s.next() {\n            Some(s) => {\n                if let Some(s) = s.strip_prefix('(').and_then(|s| s.strip_suffix(')')) {\n                    Some(TomlLockfileSourceId::new(s.to_string())?)\n                } else {\n                    return Err(TomlLockfilePackageIdErrorKind::InvalidSerializedPackageId.into());\n                }\n            }\n            None => None,\n        };\n\n        Ok(TomlLockfilePackageId {\n            name: name.to_string(),\n            version: version.map(|v| v.to_string()),\n            source: source_id,\n        })\n    }\n}\n\nimpl ser::Serialize for TomlLockfilePackageId {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        s.collect_str(self)\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for TomlLockfilePackageId {\n    fn deserialize<D>(d: D) -> Result<TomlLockfilePackageId, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        String::deserialize(d).and_then(|string| {\n            string\n                .parse::<TomlLockfilePackageId>()\n                .map_err(de::Error::custom)\n        })\n    }\n}\n\n#[derive(Debug, thiserror::Error)]\n#[error(transparent)]\npub struct TomlLockfileSourceIdError(#[from] TomlLockfileSourceIdErrorKind);\n\n#[non_exhaustive]\n#[derive(Debug, thiserror::Error)]\nenum TomlLockfileSourceIdErrorKind {\n    #[error(\"invalid source `{0}`\")]\n    InvalidSource(String),\n\n    #[error(\"invalid url `{url}`: {msg}\")]\n    InvalidUrl { url: String, msg: String },\n\n    #[error(\"unsupported source protocol: {0}\")]\n    UnsupportedSource(String),\n}\n\n#[derive(Debug, thiserror::Error)]\n#[error(transparent)]\npub struct TomlLockfilePackageIdError(#[from] TomlLockfilePackageIdErrorKind);\n\nimpl From<TomlLockfileSourceIdError> for TomlLockfilePackageIdError {\n    fn from(value: TomlLockfileSourceIdError) -> Self {\n        TomlLockfilePackageIdErrorKind::Source(value).into()\n    }\n}\n\n#[non_exhaustive]\n#[derive(Debug, thiserror::Error)]\nenum TomlLockfilePackageIdErrorKind {\n    #[error(\"invalid serialied PackageId\")]\n    InvalidSerializedPackageId,\n\n    #[error(transparent)]\n    Source(#[from] TomlLockfileSourceIdError),\n}\n\n#[cfg(feature = \"unstable-schema\")]\n#[test]\nfn dump_lockfile_schema() {\n    let schema = schemars::schema_for!(crate::lockfile::TomlLockfile);\n    let dump = serde_json::to_string_pretty(&schema).unwrap();\n    snapbox::assert_data_eq!(dump, snapbox::file!(\"../lockfile.schema.json\").raw());\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::core::{GitReference, SourceKind};\n    use crate::lockfile::{TomlLockfileSourceId, TomlLockfileSourceIdErrorKind};\n\n    #[track_caller]\n    fn ok(source_str: &str, source_kind: SourceKind, url: &str) {\n        let source_str = source_str.to_owned();\n        let source_id = TomlLockfileSourceId::new(source_str).unwrap();\n        assert_eq!(source_id.kind, source_kind);\n        assert_eq!(source_id.url().to_string(), url);\n    }\n\n    macro_rules! err {\n        ($src:expr, $expected:pat) => {\n            let kind = TomlLockfileSourceId::new($src.to_owned()).unwrap_err().0;\n            assert!(\n                matches!(kind, $expected),\n                \"`{}` parse error mismatch, got {kind:?}\",\n                $src,\n            );\n        };\n    }\n\n    #[test]\n    fn good_sources() {\n        ok(\n            \"sparse+https://my-crates.io\",\n            SourceKind::SparseRegistry,\n            \"sparse+https://my-crates.io\",\n        );\n        ok(\n            \"registry+https://github.com/rust-lang/crates.io-index\",\n            SourceKind::Registry,\n            \"https://github.com/rust-lang/crates.io-index\",\n        );\n        ok(\n            \"git+https://github.com/rust-lang/cargo\",\n            SourceKind::Git(GitReference::DefaultBranch),\n            \"https://github.com/rust-lang/cargo\",\n        );\n        ok(\n            \"git+https://github.com/rust-lang/cargo?branch=dev\",\n            SourceKind::Git(GitReference::Branch(\"dev\".to_owned())),\n            \"https://github.com/rust-lang/cargo?branch=dev\",\n        );\n        ok(\n            \"git+https://github.com/rust-lang/cargo?tag=v1.0\",\n            SourceKind::Git(GitReference::Tag(\"v1.0\".to_owned())),\n            \"https://github.com/rust-lang/cargo?tag=v1.0\",\n        );\n        ok(\n            \"git+https://github.com/rust-lang/cargo?rev=refs/pull/493/head\",\n            SourceKind::Git(GitReference::Rev(\"refs/pull/493/head\".to_owned())),\n            \"https://github.com/rust-lang/cargo?rev=refs/pull/493/head\",\n        );\n        ok(\n            \"path+file:///path/to/root\",\n            SourceKind::Path,\n            \"file:///path/to/root\",\n        );\n    }\n\n    #[test]\n    fn bad_sources() {\n        err!(\n            \"unknown+https://my-crates.io\",\n            TomlLockfileSourceIdErrorKind::UnsupportedSource(..)\n        );\n        err!(\n            \"registry+https//github.com/rust-lang/crates.io-index\",\n            TomlLockfileSourceIdErrorKind::InvalidUrl { .. }\n        );\n        err!(\n            \"https//github.com/rust-lang/crates.io-index\",\n            TomlLockfileSourceIdErrorKind::InvalidSource(..)\n        );\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util-schemas/src/manifest/mod.rs",
    "content": "//! `Cargo.toml` / Manifest schema definition\n//!\n//! ## Style\n//!\n//! - Fields duplicated for an alias will have an accessor with the primary field's name\n//! - Keys that exist for bookkeeping but don't correspond to the schema have a `_` prefix\n\nuse std::collections::BTreeMap;\nuse std::collections::BTreeSet;\n#[cfg(feature = \"unstable-schema\")]\nuse std::collections::HashMap;\nuse std::fmt::{self, Display, Write};\nuse std::path::PathBuf;\nuse std::str;\n\nuse serde::de::{self, IntoDeserializer as _, Unexpected};\nuse serde::ser;\nuse serde::{Deserialize, Serialize};\nuse serde_untagged::UntaggedEnumVisitor;\n\nuse crate::core::PackageIdSpec;\nuse crate::restricted_names;\n\nmod rust_version;\n\npub use crate::restricted_names::NameValidationError;\npub use rust_version::RustVersion;\npub use rust_version::RustVersionError;\n\n#[cfg(feature = \"unstable-schema\")]\nuse crate::schema::TomlValueWrapper;\n\n/// This type is used to deserialize `Cargo.toml` files.\n#[derive(Default, Clone, Debug, Deserialize, Serialize)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlManifest {\n    pub cargo_features: Option<Vec<String>>,\n\n    // Update `requires_package` when adding new package-specific fields\n    pub package: Option<Box<TomlPackage>>,\n    pub project: Option<Box<TomlPackage>>,\n    pub badges: Option<BTreeMap<String, BTreeMap<String, String>>>,\n    pub features: Option<BTreeMap<FeatureName, Vec<String>>>,\n    pub lib: Option<TomlLibTarget>,\n    pub bin: Option<Vec<TomlBinTarget>>,\n    pub example: Option<Vec<TomlExampleTarget>>,\n    pub test: Option<Vec<TomlTestTarget>>,\n    pub bench: Option<Vec<TomlTestTarget>>,\n    pub dependencies: Option<BTreeMap<PackageName, InheritableDependency>>,\n    pub dev_dependencies: Option<BTreeMap<PackageName, InheritableDependency>>,\n    #[serde(rename = \"dev_dependencies\")]\n    pub dev_dependencies2: Option<BTreeMap<PackageName, InheritableDependency>>,\n    pub build_dependencies: Option<BTreeMap<PackageName, InheritableDependency>>,\n    #[serde(rename = \"build_dependencies\")]\n    pub build_dependencies2: Option<BTreeMap<PackageName, InheritableDependency>>,\n    pub target: Option<BTreeMap<String, TomlPlatform>>,\n    pub lints: Option<InheritableLints>,\n    pub hints: Option<Hints>,\n\n    pub workspace: Option<TomlWorkspace>,\n    pub profile: Option<TomlProfiles>,\n    pub patch: Option<BTreeMap<String, BTreeMap<PackageName, TomlDependency>>>,\n    pub replace: Option<BTreeMap<String, TomlDependency>>,\n\n    /// Report unused keys (see also nested `_unused_keys`)\n    /// Note: this is populated by the caller, rather than automatically\n    #[serde(skip)]\n    pub _unused_keys: BTreeSet<String>,\n}\n\nimpl TomlManifest {\n    pub fn requires_package(&self) -> impl Iterator<Item = &'static str> {\n        [\n            self.badges.as_ref().map(|_| \"badges\"),\n            self.features.as_ref().map(|_| \"features\"),\n            self.lib.as_ref().map(|_| \"lib\"),\n            self.bin.as_ref().map(|_| \"bin\"),\n            self.example.as_ref().map(|_| \"example\"),\n            self.test.as_ref().map(|_| \"test\"),\n            self.bench.as_ref().map(|_| \"bench\"),\n            self.dependencies.as_ref().map(|_| \"dependencies\"),\n            self.dev_dependencies().as_ref().map(|_| \"dev-dependencies\"),\n            self.build_dependencies()\n                .as_ref()\n                .map(|_| \"build-dependencies\"),\n            self.target.as_ref().map(|_| \"target\"),\n            self.lints.as_ref().map(|_| \"lints\"),\n            self.hints.as_ref().map(|_| \"hints\"),\n        ]\n        .into_iter()\n        .flatten()\n    }\n\n    pub fn has_profiles(&self) -> bool {\n        self.profile.is_some()\n    }\n\n    pub fn package(&self) -> Option<&Box<TomlPackage>> {\n        self.package.as_ref().or(self.project.as_ref())\n    }\n\n    pub fn dev_dependencies(&self) -> Option<&BTreeMap<PackageName, InheritableDependency>> {\n        self.dev_dependencies\n            .as_ref()\n            .or(self.dev_dependencies2.as_ref())\n    }\n\n    pub fn build_dependencies(&self) -> Option<&BTreeMap<PackageName, InheritableDependency>> {\n        self.build_dependencies\n            .as_ref()\n            .or(self.build_dependencies2.as_ref())\n    }\n\n    pub fn features(&self) -> Option<&BTreeMap<FeatureName, Vec<String>>> {\n        self.features.as_ref()\n    }\n\n    pub fn normalized_lints(&self) -> Result<Option<&TomlLints>, UnresolvedError> {\n        self.lints.as_ref().map(|l| l.normalized()).transpose()\n    }\n}\n\n#[derive(Debug, Default, Deserialize, Serialize, Clone)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlWorkspace {\n    pub members: Option<Vec<String>>,\n    pub exclude: Option<Vec<String>>,\n    pub default_members: Option<Vec<String>>,\n    pub resolver: Option<String>,\n\n    #[cfg_attr(\n        feature = \"unstable-schema\",\n        schemars(with = \"Option<TomlValueWrapper>\")\n    )]\n    pub metadata: Option<toml::Value>,\n\n    // Properties that can be inherited by members.\n    pub package: Option<InheritablePackage>,\n    pub dependencies: Option<BTreeMap<PackageName, TomlDependency>>,\n    pub lints: Option<TomlLints>,\n}\n\n/// A group of fields that are inheritable by members of the workspace\n#[derive(Clone, Debug, Default, Deserialize, Serialize)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct InheritablePackage {\n    pub version: Option<semver::Version>,\n    pub authors: Option<Vec<String>>,\n    pub description: Option<String>,\n    pub homepage: Option<String>,\n    pub documentation: Option<String>,\n    pub readme: Option<StringOrBool>,\n    pub keywords: Option<Vec<String>>,\n    pub categories: Option<Vec<String>>,\n    pub license: Option<String>,\n    pub license_file: Option<String>,\n    pub repository: Option<String>,\n    pub publish: Option<VecStringOrBool>,\n    pub edition: Option<String>,\n    pub badges: Option<BTreeMap<String, BTreeMap<String, String>>>,\n    pub exclude: Option<Vec<String>>,\n    pub include: Option<Vec<String>>,\n    #[cfg_attr(feature = \"unstable-schema\", schemars(with = \"Option<String>\"))]\n    pub rust_version: Option<RustVersion>,\n}\n\n/// Represents the `package`/`project` sections of a `Cargo.toml`.\n///\n/// Note that the order of the fields matters, since this is the order they\n/// are serialized to a TOML file. For example, you cannot have values after\n/// the field `metadata`, since it is a table and values cannot appear after\n/// tables.\n#[derive(Deserialize, Serialize, Clone, Debug, Default)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlPackage {\n    pub edition: Option<InheritableString>,\n    #[cfg_attr(feature = \"unstable-schema\", schemars(with = \"Option<String>\"))]\n    pub rust_version: Option<InheritableRustVersion>,\n    #[cfg_attr(feature = \"unstable-schema\", schemars(with = \"Option<String>\"))]\n    pub name: Option<PackageName>,\n    pub version: Option<InheritableSemverVersion>,\n    pub authors: Option<InheritableVecString>,\n    pub build: Option<TomlPackageBuild>,\n    pub metabuild: Option<StringOrVec>,\n    pub default_target: Option<String>,\n    pub forced_target: Option<String>,\n    pub links: Option<String>,\n    pub exclude: Option<InheritableVecString>,\n    pub include: Option<InheritableVecString>,\n    pub publish: Option<InheritableVecStringOrBool>,\n    pub workspace: Option<String>,\n    pub im_a_teapot: Option<bool>,\n    pub autolib: Option<bool>,\n    pub autobins: Option<bool>,\n    pub autoexamples: Option<bool>,\n    pub autotests: Option<bool>,\n    pub autobenches: Option<bool>,\n    pub default_run: Option<String>,\n\n    // Package metadata.\n    pub description: Option<InheritableString>,\n    pub homepage: Option<InheritableString>,\n    pub documentation: Option<InheritableString>,\n    pub readme: Option<InheritableStringOrBool>,\n    pub keywords: Option<InheritableVecString>,\n    pub categories: Option<InheritableVecString>,\n    pub license: Option<InheritableString>,\n    pub license_file: Option<InheritableString>,\n    pub repository: Option<InheritableString>,\n    pub resolver: Option<String>,\n\n    #[cfg_attr(\n        feature = \"unstable-schema\",\n        schemars(with = \"Option<TomlValueWrapper>\")\n    )]\n    pub metadata: Option<toml::Value>,\n\n    /// Provide a helpful error message for a common user error.\n    #[serde(rename = \"cargo-features\", skip_serializing)]\n    #[cfg_attr(feature = \"unstable-schema\", schemars(skip))]\n    pub _invalid_cargo_features: Option<InvalidCargoFeatures>,\n}\n\nimpl TomlPackage {\n    pub fn new(name: PackageName) -> Self {\n        Self {\n            name: Some(name),\n            ..Default::default()\n        }\n    }\n\n    pub fn normalized_name(&self) -> Result<&PackageName, UnresolvedError> {\n        self.name.as_ref().ok_or(UnresolvedError)\n    }\n\n    pub fn normalized_edition(&self) -> Result<Option<&String>, UnresolvedError> {\n        self.edition.as_ref().map(|v| v.normalized()).transpose()\n    }\n\n    pub fn normalized_rust_version(&self) -> Result<Option<&RustVersion>, UnresolvedError> {\n        self.rust_version\n            .as_ref()\n            .map(|v| v.normalized())\n            .transpose()\n    }\n\n    pub fn normalized_version(&self) -> Result<Option<&semver::Version>, UnresolvedError> {\n        self.version.as_ref().map(|v| v.normalized()).transpose()\n    }\n\n    pub fn normalized_authors(&self) -> Result<Option<&Vec<String>>, UnresolvedError> {\n        self.authors.as_ref().map(|v| v.normalized()).transpose()\n    }\n\n    pub fn normalized_build(&self) -> Result<Option<&[String]>, UnresolvedError> {\n        let build = self.build.as_ref().ok_or(UnresolvedError)?;\n        match build {\n            TomlPackageBuild::Auto(false) => Ok(None),\n            TomlPackageBuild::Auto(true) => Err(UnresolvedError),\n            TomlPackageBuild::SingleScript(value) => Ok(Some(std::slice::from_ref(value))),\n            TomlPackageBuild::MultipleScript(scripts) => Ok(Some(scripts)),\n        }\n    }\n\n    pub fn normalized_exclude(&self) -> Result<Option<&Vec<String>>, UnresolvedError> {\n        self.exclude.as_ref().map(|v| v.normalized()).transpose()\n    }\n\n    pub fn normalized_include(&self) -> Result<Option<&Vec<String>>, UnresolvedError> {\n        self.include.as_ref().map(|v| v.normalized()).transpose()\n    }\n\n    pub fn normalized_publish(&self) -> Result<Option<&VecStringOrBool>, UnresolvedError> {\n        self.publish.as_ref().map(|v| v.normalized()).transpose()\n    }\n\n    pub fn normalized_description(&self) -> Result<Option<&String>, UnresolvedError> {\n        self.description\n            .as_ref()\n            .map(|v| v.normalized())\n            .transpose()\n    }\n\n    pub fn normalized_homepage(&self) -> Result<Option<&String>, UnresolvedError> {\n        self.homepage.as_ref().map(|v| v.normalized()).transpose()\n    }\n\n    pub fn normalized_documentation(&self) -> Result<Option<&String>, UnresolvedError> {\n        self.documentation\n            .as_ref()\n            .map(|v| v.normalized())\n            .transpose()\n    }\n\n    pub fn normalized_readme(&self) -> Result<Option<&String>, UnresolvedError> {\n        let readme = self.readme.as_ref().ok_or(UnresolvedError)?;\n        readme.normalized().and_then(|sb| match sb {\n            StringOrBool::Bool(false) => Ok(None),\n            StringOrBool::Bool(true) => Err(UnresolvedError),\n            StringOrBool::String(value) => Ok(Some(value)),\n        })\n    }\n\n    pub fn normalized_keywords(&self) -> Result<Option<&Vec<String>>, UnresolvedError> {\n        self.keywords.as_ref().map(|v| v.normalized()).transpose()\n    }\n\n    pub fn normalized_categories(&self) -> Result<Option<&Vec<String>>, UnresolvedError> {\n        self.categories.as_ref().map(|v| v.normalized()).transpose()\n    }\n\n    pub fn normalized_license(&self) -> Result<Option<&String>, UnresolvedError> {\n        self.license.as_ref().map(|v| v.normalized()).transpose()\n    }\n\n    pub fn normalized_license_file(&self) -> Result<Option<&String>, UnresolvedError> {\n        self.license_file\n            .as_ref()\n            .map(|v| v.normalized())\n            .transpose()\n    }\n\n    pub fn normalized_repository(&self) -> Result<Option<&String>, UnresolvedError> {\n        self.repository.as_ref().map(|v| v.normalized()).transpose()\n    }\n}\n\n/// An enum that allows for inheriting keys from a workspace in a Cargo.toml.\n#[derive(Serialize, Copy, Clone, Debug)]\n#[serde(untagged)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub enum InheritableField<T> {\n    /// The type that is used when not inheriting from a workspace.\n    Value(T),\n    /// The type when inheriting from a workspace.\n    Inherit(TomlInheritedField),\n}\n\nimpl<T> InheritableField<T> {\n    pub fn normalized(&self) -> Result<&T, UnresolvedError> {\n        self.as_value().ok_or(UnresolvedError)\n    }\n\n    pub fn as_value(&self) -> Option<&T> {\n        match self {\n            InheritableField::Inherit(_) => None,\n            InheritableField::Value(defined) => Some(defined),\n        }\n    }\n\n    pub fn into_value(self) -> Option<T> {\n        match self {\n            Self::Inherit(_) => None,\n            Self::Value(defined) => Some(defined),\n        }\n    }\n\n    pub fn is_inherited(&self) -> bool {\n        matches!(self, Self::Inherit(_))\n    }\n}\n\n//. This already has a `Deserialize` impl from version_trim_whitespace\npub type InheritableSemverVersion = InheritableField<semver::Version>;\nimpl<'de> de::Deserialize<'de> for InheritableSemverVersion {\n    fn deserialize<D>(d: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        UntaggedEnumVisitor::new()\n            .expecting(\"SemVer version\")\n            .string(\n                |value| match value.trim().parse().map_err(de::Error::custom) {\n                    Ok(parsed) => Ok(InheritableField::Value(parsed)),\n                    Err(e) => Err(e),\n                },\n            )\n            .map(|value| value.deserialize().map(InheritableField::Inherit))\n            .deserialize(d)\n    }\n}\n\npub type InheritableString = InheritableField<String>;\nimpl<'de> de::Deserialize<'de> for InheritableString {\n    fn deserialize<D>(d: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        struct Visitor;\n\n        impl<'de> de::Visitor<'de> for Visitor {\n            type Value = InheritableString;\n\n            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {\n                f.write_str(\"a string or workspace\")\n            }\n\n            fn visit_string<E>(self, value: String) -> Result<Self::Value, E>\n            where\n                E: de::Error,\n            {\n                Ok(InheritableString::Value(value))\n            }\n\n            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>\n            where\n                E: de::Error,\n            {\n                self.visit_string(value.to_owned())\n            }\n\n            fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>\n            where\n                V: de::MapAccess<'de>,\n            {\n                let mvd = de::value::MapAccessDeserializer::new(map);\n                TomlInheritedField::deserialize(mvd).map(InheritableField::Inherit)\n            }\n        }\n\n        d.deserialize_any(Visitor)\n    }\n}\n\npub type InheritableRustVersion = InheritableField<RustVersion>;\nimpl<'de> de::Deserialize<'de> for InheritableRustVersion {\n    fn deserialize<D>(d: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        struct Visitor;\n\n        impl<'de> de::Visitor<'de> for Visitor {\n            type Value = InheritableRustVersion;\n\n            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {\n                f.write_str(\"a semver or workspace\")\n            }\n\n            fn visit_string<E>(self, value: String) -> Result<Self::Value, E>\n            where\n                E: de::Error,\n            {\n                let value = value.parse::<RustVersion>().map_err(|e| E::custom(e))?;\n                Ok(InheritableRustVersion::Value(value))\n            }\n\n            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>\n            where\n                E: de::Error,\n            {\n                self.visit_string(value.to_owned())\n            }\n\n            fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>\n            where\n                V: de::MapAccess<'de>,\n            {\n                let mvd = de::value::MapAccessDeserializer::new(map);\n                TomlInheritedField::deserialize(mvd).map(InheritableField::Inherit)\n            }\n        }\n\n        d.deserialize_any(Visitor)\n    }\n}\n\npub type InheritableVecString = InheritableField<Vec<String>>;\nimpl<'de> de::Deserialize<'de> for InheritableVecString {\n    fn deserialize<D>(d: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        struct Visitor;\n\n        impl<'de> de::Visitor<'de> for Visitor {\n            type Value = InheritableVecString;\n\n            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {\n                f.write_str(\"a vector of strings or workspace\")\n            }\n            fn visit_seq<A>(self, v: A) -> Result<Self::Value, A::Error>\n            where\n                A: de::SeqAccess<'de>,\n            {\n                let seq = de::value::SeqAccessDeserializer::new(v);\n                Vec::deserialize(seq).map(InheritableField::Value)\n            }\n\n            fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>\n            where\n                V: de::MapAccess<'de>,\n            {\n                let mvd = de::value::MapAccessDeserializer::new(map);\n                TomlInheritedField::deserialize(mvd).map(InheritableField::Inherit)\n            }\n        }\n\n        d.deserialize_any(Visitor)\n    }\n}\n\npub type InheritableStringOrBool = InheritableField<StringOrBool>;\nimpl<'de> de::Deserialize<'de> for InheritableStringOrBool {\n    fn deserialize<D>(d: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        struct Visitor;\n\n        impl<'de> de::Visitor<'de> for Visitor {\n            type Value = InheritableStringOrBool;\n\n            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {\n                f.write_str(\"a string, a bool, or workspace\")\n            }\n\n            fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>\n            where\n                E: de::Error,\n            {\n                let b = de::value::BoolDeserializer::new(v);\n                StringOrBool::deserialize(b).map(InheritableField::Value)\n            }\n\n            fn visit_string<E>(self, v: String) -> Result<Self::Value, E>\n            where\n                E: de::Error,\n            {\n                let string = de::value::StringDeserializer::new(v);\n                StringOrBool::deserialize(string).map(InheritableField::Value)\n            }\n\n            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>\n            where\n                E: de::Error,\n            {\n                self.visit_string(value.to_owned())\n            }\n\n            fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>\n            where\n                V: de::MapAccess<'de>,\n            {\n                let mvd = de::value::MapAccessDeserializer::new(map);\n                TomlInheritedField::deserialize(mvd).map(InheritableField::Inherit)\n            }\n        }\n\n        d.deserialize_any(Visitor)\n    }\n}\n\npub type InheritableVecStringOrBool = InheritableField<VecStringOrBool>;\nimpl<'de> de::Deserialize<'de> for InheritableVecStringOrBool {\n    fn deserialize<D>(d: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        struct Visitor;\n\n        impl<'de> de::Visitor<'de> for Visitor {\n            type Value = InheritableVecStringOrBool;\n\n            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {\n                f.write_str(\"a boolean, a vector of strings, or workspace\")\n            }\n\n            fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>\n            where\n                E: de::Error,\n            {\n                let b = de::value::BoolDeserializer::new(v);\n                VecStringOrBool::deserialize(b).map(InheritableField::Value)\n            }\n\n            fn visit_seq<A>(self, v: A) -> Result<Self::Value, A::Error>\n            where\n                A: de::SeqAccess<'de>,\n            {\n                let seq = de::value::SeqAccessDeserializer::new(v);\n                VecStringOrBool::deserialize(seq).map(InheritableField::Value)\n            }\n\n            fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>\n            where\n                V: de::MapAccess<'de>,\n            {\n                let mvd = de::value::MapAccessDeserializer::new(map);\n                TomlInheritedField::deserialize(mvd).map(InheritableField::Inherit)\n            }\n        }\n\n        d.deserialize_any(Visitor)\n    }\n}\n\npub type InheritableBtreeMap = InheritableField<BTreeMap<String, BTreeMap<String, String>>>;\n\nimpl<'de> de::Deserialize<'de> for InheritableBtreeMap {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        let value = serde_value::Value::deserialize(deserializer)?;\n\n        if let Ok(w) = TomlInheritedField::deserialize(\n            serde_value::ValueDeserializer::<D::Error>::new(value.clone()),\n        ) {\n            return Ok(InheritableField::Inherit(w));\n        }\n        BTreeMap::deserialize(serde_value::ValueDeserializer::<D::Error>::new(value))\n            .map(InheritableField::Value)\n    }\n}\n\n#[derive(Deserialize, Serialize, Copy, Clone, Debug)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlInheritedField {\n    workspace: WorkspaceValue,\n}\n\nimpl TomlInheritedField {\n    pub fn new() -> Self {\n        TomlInheritedField {\n            workspace: WorkspaceValue,\n        }\n    }\n}\n\nimpl Default for TomlInheritedField {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\n#[derive(Deserialize, Serialize, Copy, Clone, Debug)]\n#[serde(try_from = \"bool\")]\n#[serde(into = \"bool\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\nstruct WorkspaceValue;\n\nimpl TryFrom<bool> for WorkspaceValue {\n    type Error = String;\n    fn try_from(other: bool) -> Result<WorkspaceValue, Self::Error> {\n        if other {\n            Ok(WorkspaceValue)\n        } else {\n            Err(\"`workspace` cannot be false\".to_owned())\n        }\n    }\n}\n\nimpl From<WorkspaceValue> for bool {\n    fn from(_: WorkspaceValue) -> bool {\n        true\n    }\n}\n\n#[derive(Serialize, Clone, Debug)]\n#[serde(untagged)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub enum InheritableDependency {\n    /// The type that is used when not inheriting from a workspace.\n    Value(TomlDependency),\n    /// The type when inheriting from a workspace.\n    Inherit(TomlInheritedDependency),\n}\n\nimpl InheritableDependency {\n    pub fn unused_keys(&self) -> Vec<String> {\n        match self {\n            InheritableDependency::Value(d) => d.unused_keys(),\n            InheritableDependency::Inherit(w) => w._unused_keys.keys().cloned().collect(),\n        }\n    }\n\n    pub fn normalized(&self) -> Result<&TomlDependency, UnresolvedError> {\n        match self {\n            InheritableDependency::Value(d) => Ok(d),\n            InheritableDependency::Inherit(_) => Err(UnresolvedError),\n        }\n    }\n\n    pub fn is_inherited(&self) -> bool {\n        matches!(self, InheritableDependency::Inherit(_))\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for InheritableDependency {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        let value = serde_value::Value::deserialize(deserializer)?;\n\n        if let Ok(w) = TomlInheritedDependency::deserialize(serde_value::ValueDeserializer::<\n            D::Error,\n        >::new(value.clone()))\n        {\n            return if w.workspace {\n                Ok(InheritableDependency::Inherit(w))\n            } else {\n                Err(de::Error::custom(\"`workspace` cannot be false\"))\n            };\n        }\n        TomlDependency::deserialize(serde_value::ValueDeserializer::<D::Error>::new(value))\n            .map(InheritableDependency::Value)\n    }\n}\n\n#[derive(Deserialize, Serialize, Clone, Debug)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlInheritedDependency {\n    pub workspace: bool,\n    pub features: Option<Vec<String>>,\n    pub default_features: Option<bool>,\n    #[serde(rename = \"default_features\")]\n    pub default_features2: Option<bool>,\n    pub optional: Option<bool>,\n    pub public: Option<bool>,\n\n    /// This is here to provide a way to see the \"unused manifest keys\" when deserializing\n    #[serde(skip_serializing)]\n    #[serde(flatten)]\n    #[cfg_attr(feature = \"unstable-schema\", schemars(skip))]\n    pub _unused_keys: BTreeMap<String, toml::Value>,\n}\n\nimpl TomlInheritedDependency {\n    pub fn default_features(&self) -> Option<bool> {\n        self.default_features.or(self.default_features2)\n    }\n}\n\n#[derive(Clone, Debug, Serialize)]\n#[serde(untagged)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub enum TomlDependency<P: Clone = String> {\n    /// In the simple format, only a version is specified, eg.\n    /// `package = \"<version>\"`\n    Simple(String),\n    /// The simple format is equivalent to a detailed dependency\n    /// specifying only a version, eg.\n    /// `package = { version = \"<version>\" }`\n    Detailed(TomlDetailedDependency<P>),\n}\n\nimpl TomlDependency {\n    pub fn is_version_specified(&self) -> bool {\n        match self {\n            TomlDependency::Detailed(d) => d.version.is_some(),\n            TomlDependency::Simple(..) => true,\n        }\n    }\n\n    pub fn is_optional(&self) -> bool {\n        match self {\n            TomlDependency::Detailed(d) => d.optional.unwrap_or(false),\n            TomlDependency::Simple(..) => false,\n        }\n    }\n\n    pub fn is_public(&self) -> bool {\n        match self {\n            TomlDependency::Detailed(d) => d.public.unwrap_or(false),\n            TomlDependency::Simple(..) => false,\n        }\n    }\n\n    pub fn default_features(&self) -> Option<bool> {\n        match self {\n            TomlDependency::Detailed(d) => d.default_features(),\n            TomlDependency::Simple(..) => None,\n        }\n    }\n\n    pub fn unused_keys(&self) -> Vec<String> {\n        match self {\n            TomlDependency::Simple(_) => vec![],\n            TomlDependency::Detailed(detailed) => detailed._unused_keys.keys().cloned().collect(),\n        }\n    }\n}\n\nimpl<'de, P: Deserialize<'de> + Clone> de::Deserialize<'de> for TomlDependency<P> {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        use serde::de::Error as _;\n        let expected = \"a version string like \\\"0.9.8\\\" or a \\\n                     detailed dependency like { version = \\\"0.9.8\\\" }\";\n        UntaggedEnumVisitor::new()\n            .expecting(expected)\n            .string(|value| Ok(TomlDependency::Simple(value.to_owned())))\n            .bool(|value| {\n                let expected = format!(\"invalid type: boolean `{value}`, expected {expected}\");\n                let err = if value {\n                    format!(\n                        \"{expected}\\n\\\n                    note: if you meant to use a workspace member, you can write\\n \\\n                      dep.workspace = {value}\"\n                    )\n                } else {\n                    expected\n                };\n\n                Err(serde_untagged::de::Error::custom(err))\n            })\n            .map(|value| value.deserialize().map(TomlDependency::Detailed))\n            .deserialize(deserializer)\n    }\n}\n\n#[derive(Deserialize, Serialize, Clone, Debug)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlDetailedDependency<P: Clone = String> {\n    pub version: Option<String>,\n\n    #[cfg_attr(feature = \"unstable-schema\", schemars(with = \"Option<String>\"))]\n    pub registry: Option<RegistryName>,\n    /// The URL of the `registry` field.\n    /// This is an internal implementation detail. When Cargo creates a\n    /// package, it replaces `registry` with `registry-index` so that the\n    /// manifest contains the correct URL. All users won't have the same\n    /// registry names configured, so Cargo can't rely on just the name for\n    /// crates published by other users.\n    pub registry_index: Option<String>,\n    // `path` is relative to the file it appears in. If that's a `Cargo.toml`, it'll be relative to\n    // that TOML file, and if it's a `.cargo/config` file, it'll be relative to that file.\n    pub path: Option<P>,\n    #[cfg_attr(feature = \"unstable-schema\", schemars(with = \"Option<String>\"))]\n    pub base: Option<PathBaseName>,\n    pub git: Option<String>,\n    pub branch: Option<String>,\n    pub tag: Option<String>,\n    pub rev: Option<String>,\n    pub features: Option<Vec<String>>,\n    pub optional: Option<bool>,\n    pub default_features: Option<bool>,\n    #[serde(rename = \"default_features\")]\n    pub default_features2: Option<bool>,\n    #[cfg_attr(feature = \"unstable-schema\", schemars(with = \"Option<String>\"))]\n    pub package: Option<PackageName>,\n    pub public: Option<bool>,\n\n    /// One or more of `bin`, `cdylib`, `staticlib`, `bin:<name>`.\n    pub artifact: Option<StringOrVec>,\n    /// If set, the artifact should also be a dependency\n    pub lib: Option<bool>,\n    /// A platform name, like `x86_64-apple-darwin`\n    pub target: Option<String>,\n\n    /// This is here to provide a way to see the \"unused manifest keys\" when deserializing\n    #[serde(skip_serializing)]\n    #[serde(flatten)]\n    #[cfg_attr(feature = \"unstable-schema\", schemars(skip))]\n    pub _unused_keys: BTreeMap<String, toml::Value>,\n}\n\nimpl<P: Clone> TomlDetailedDependency<P> {\n    pub fn default_features(&self) -> Option<bool> {\n        self.default_features.or(self.default_features2)\n    }\n}\n\n// Explicit implementation so we avoid pulling in P: Default\nimpl<P: Clone> Default for TomlDetailedDependency<P> {\n    fn default() -> Self {\n        Self {\n            version: Default::default(),\n            registry: Default::default(),\n            registry_index: Default::default(),\n            path: Default::default(),\n            base: Default::default(),\n            git: Default::default(),\n            branch: Default::default(),\n            tag: Default::default(),\n            rev: Default::default(),\n            features: Default::default(),\n            optional: Default::default(),\n            default_features: Default::default(),\n            default_features2: Default::default(),\n            package: Default::default(),\n            public: Default::default(),\n            artifact: Default::default(),\n            lib: Default::default(),\n            target: Default::default(),\n            _unused_keys: Default::default(),\n        }\n    }\n}\n\n#[derive(Deserialize, Serialize, Clone, Debug, Default)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlProfiles(pub BTreeMap<ProfileName, TomlProfile>);\n\nimpl TomlProfiles {\n    pub fn get_all(&self) -> &BTreeMap<ProfileName, TomlProfile> {\n        &self.0\n    }\n\n    pub fn get(&self, name: &str) -> Option<&TomlProfile> {\n        self.0.get(name)\n    }\n}\n\n#[derive(Deserialize, Serialize, Clone, Debug, Default, Eq, PartialEq)]\n#[serde(default, rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlProfile {\n    pub opt_level: Option<TomlOptLevel>,\n    pub lto: Option<StringOrBool>,\n    pub codegen_backend: Option<String>,\n    pub codegen_units: Option<u32>,\n    pub debug: Option<TomlDebugInfo>,\n    pub split_debuginfo: Option<String>,\n    pub debug_assertions: Option<bool>,\n    pub rpath: Option<bool>,\n    pub panic: Option<String>,\n    pub overflow_checks: Option<bool>,\n    pub incremental: Option<bool>,\n    pub dir_name: Option<String>,\n    pub inherits: Option<String>,\n    pub strip: Option<StringOrBool>,\n    // Note that `rustflags` is used for the cargo-feature `profile_rustflags`\n    pub rustflags: Option<Vec<String>>,\n    // These two fields must be last because they are sub-tables, and TOML\n    // requires all non-tables to be listed first.\n    pub package: Option<BTreeMap<ProfilePackageSpec, TomlProfile>>,\n    pub build_override: Option<Box<TomlProfile>>,\n    /// Unstable feature `-Ztrim-paths`.\n    pub trim_paths: Option<TomlTrimPaths>,\n    /// Unstable feature `hint-mostly-unused`\n    pub hint_mostly_unused: Option<bool>,\n}\n\nimpl TomlProfile {\n    /// Overwrite self's values with the given profile.\n    pub fn merge(&mut self, profile: &Self) {\n        if let Some(v) = &profile.opt_level {\n            self.opt_level = Some(v.clone());\n        }\n\n        if let Some(v) = &profile.lto {\n            self.lto = Some(v.clone());\n        }\n\n        if let Some(v) = &profile.codegen_backend {\n            self.codegen_backend = Some(v.clone());\n        }\n\n        if let Some(v) = profile.codegen_units {\n            self.codegen_units = Some(v);\n        }\n\n        if let Some(v) = profile.debug {\n            self.debug = Some(v);\n        }\n\n        if let Some(v) = profile.debug_assertions {\n            self.debug_assertions = Some(v);\n        }\n\n        if let Some(v) = &profile.split_debuginfo {\n            self.split_debuginfo = Some(v.clone());\n        }\n\n        if let Some(v) = profile.rpath {\n            self.rpath = Some(v);\n        }\n\n        if let Some(v) = &profile.panic {\n            self.panic = Some(v.clone());\n        }\n\n        if let Some(v) = profile.overflow_checks {\n            self.overflow_checks = Some(v);\n        }\n\n        if let Some(v) = profile.incremental {\n            self.incremental = Some(v);\n        }\n\n        if let Some(v) = &profile.rustflags {\n            self.rustflags = Some(v.clone());\n        }\n\n        if let Some(other_package) = &profile.package {\n            match &mut self.package {\n                Some(self_package) => {\n                    for (spec, other_pkg_profile) in other_package {\n                        match self_package.get_mut(spec) {\n                            Some(p) => p.merge(other_pkg_profile),\n                            None => {\n                                self_package.insert(spec.clone(), other_pkg_profile.clone());\n                            }\n                        }\n                    }\n                }\n                None => self.package = Some(other_package.clone()),\n            }\n        }\n\n        if let Some(other_bo) = &profile.build_override {\n            match &mut self.build_override {\n                Some(self_bo) => self_bo.merge(other_bo),\n                None => self.build_override = Some(other_bo.clone()),\n            }\n        }\n\n        if let Some(v) = &profile.inherits {\n            self.inherits = Some(v.clone());\n        }\n\n        if let Some(v) = &profile.dir_name {\n            self.dir_name = Some(v.clone());\n        }\n\n        if let Some(v) = &profile.strip {\n            self.strip = Some(v.clone());\n        }\n\n        if let Some(v) = &profile.trim_paths {\n            self.trim_paths = Some(v.clone())\n        }\n\n        if let Some(v) = profile.hint_mostly_unused {\n            self.hint_mostly_unused = Some(v);\n        }\n    }\n}\n\n#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub enum ProfilePackageSpec {\n    Spec(PackageIdSpec),\n    All,\n}\n\nimpl fmt::Display for ProfilePackageSpec {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            ProfilePackageSpec::Spec(spec) => spec.fmt(f),\n            ProfilePackageSpec::All => f.write_str(\"*\"),\n        }\n    }\n}\n\nimpl ser::Serialize for ProfilePackageSpec {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        self.to_string().serialize(s)\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for ProfilePackageSpec {\n    fn deserialize<D>(d: D) -> Result<ProfilePackageSpec, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        let string = String::deserialize(d)?;\n        if string == \"*\" {\n            Ok(ProfilePackageSpec::All)\n        } else {\n            PackageIdSpec::parse(&string)\n                .map_err(de::Error::custom)\n                .map(ProfilePackageSpec::Spec)\n        }\n    }\n}\n\n#[derive(Clone, Debug, Eq, PartialEq)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlOptLevel(pub String);\n\nimpl ser::Serialize for TomlOptLevel {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        match self.0.parse::<u32>() {\n            Ok(n) => n.serialize(serializer),\n            Err(_) => self.0.serialize(serializer),\n        }\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for TomlOptLevel {\n    fn deserialize<D>(d: D) -> Result<TomlOptLevel, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        use serde::de::Error as _;\n        UntaggedEnumVisitor::new()\n            .expecting(\"an optimization level\")\n            .i64(|value| Ok(TomlOptLevel(value.to_string())))\n            .string(|value| {\n                if value == \"s\" || value == \"z\" {\n                    Ok(TomlOptLevel(value.to_string()))\n                } else {\n                    Err(serde_untagged::de::Error::custom(format!(\n                        \"must be `0`, `1`, `2`, `3`, `s` or `z`, \\\n                         but found the string: \\\"{}\\\"\",\n                        value\n                    )))\n                }\n            })\n            .deserialize(d)\n    }\n}\n\n#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub enum TomlDebugInfo {\n    None,\n    LineDirectivesOnly,\n    LineTablesOnly,\n    Limited,\n    Full,\n}\n\nimpl Display for TomlDebugInfo {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            TomlDebugInfo::None => f.write_char('0'),\n            TomlDebugInfo::Limited => f.write_char('1'),\n            TomlDebugInfo::Full => f.write_char('2'),\n            TomlDebugInfo::LineDirectivesOnly => f.write_str(\"line-directives-only\"),\n            TomlDebugInfo::LineTablesOnly => f.write_str(\"line-tables-only\"),\n        }\n    }\n}\n\nimpl ser::Serialize for TomlDebugInfo {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        match self {\n            Self::None => 0.serialize(serializer),\n            Self::LineDirectivesOnly => \"line-directives-only\".serialize(serializer),\n            Self::LineTablesOnly => \"line-tables-only\".serialize(serializer),\n            Self::Limited => 1.serialize(serializer),\n            Self::Full => 2.serialize(serializer),\n        }\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for TomlDebugInfo {\n    fn deserialize<D>(d: D) -> Result<TomlDebugInfo, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        use serde::de::Error as _;\n        let expecting = \"a boolean, 0, 1, 2, \\\"none\\\", \\\"limited\\\", \\\"full\\\", \\\"line-tables-only\\\", or \\\"line-directives-only\\\"\";\n        UntaggedEnumVisitor::new()\n            .expecting(expecting)\n            .bool(|value| {\n                Ok(if value {\n                    TomlDebugInfo::Full\n                } else {\n                    TomlDebugInfo::None\n                })\n            })\n            .i64(|value| {\n                let debuginfo = match value {\n                    0 => TomlDebugInfo::None,\n                    1 => TomlDebugInfo::Limited,\n                    2 => TomlDebugInfo::Full,\n                    _ => {\n                        return Err(serde_untagged::de::Error::invalid_value(\n                            Unexpected::Signed(value),\n                            &expecting,\n                        ));\n                    }\n                };\n                Ok(debuginfo)\n            })\n            .string(|value| {\n                let debuginfo = match value {\n                    \"none\" => TomlDebugInfo::None,\n                    \"limited\" => TomlDebugInfo::Limited,\n                    \"full\" => TomlDebugInfo::Full,\n                    \"line-directives-only\" => TomlDebugInfo::LineDirectivesOnly,\n                    \"line-tables-only\" => TomlDebugInfo::LineTablesOnly,\n                    _ => {\n                        return Err(serde_untagged::de::Error::invalid_value(\n                            Unexpected::Str(value),\n                            &expecting,\n                        ));\n                    }\n                };\n                Ok(debuginfo)\n            })\n            .deserialize(d)\n    }\n}\n\n#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Serialize)]\n#[serde(untagged, rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub enum TomlTrimPaths {\n    Values(Vec<TomlTrimPathsValue>),\n    All,\n}\n\nimpl TomlTrimPaths {\n    pub fn none() -> Self {\n        TomlTrimPaths::Values(Vec::new())\n    }\n\n    pub fn is_none(&self) -> bool {\n        match self {\n            TomlTrimPaths::Values(v) => v.is_empty(),\n            TomlTrimPaths::All => false,\n        }\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for TomlTrimPaths {\n    fn deserialize<D>(d: D) -> Result<TomlTrimPaths, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        use serde::de::Error as _;\n        let expecting = r#\"a boolean, \"none\", \"diagnostics\", \"macro\", \"object\", \"all\", or an array with these options\"#;\n        UntaggedEnumVisitor::new()\n            .expecting(expecting)\n            .bool(|value| {\n                Ok(if value {\n                    TomlTrimPaths::All\n                } else {\n                    TomlTrimPaths::none()\n                })\n            })\n            .string(|v| match v {\n                \"none\" => Ok(TomlTrimPaths::none()),\n                \"all\" => Ok(TomlTrimPaths::All),\n                v => {\n                    let d = v.into_deserializer();\n                    let err = |_: D::Error| {\n                        serde_untagged::de::Error::custom(format!(\"expected {expecting}\"))\n                    };\n                    TomlTrimPathsValue::deserialize(d)\n                        .map_err(err)\n                        .map(|v| v.into())\n                }\n            })\n            .seq(|seq| {\n                let seq: Vec<String> = seq.deserialize()?;\n                let seq: Vec<_> = seq\n                    .into_iter()\n                    .map(|s| TomlTrimPathsValue::deserialize(s.into_deserializer()))\n                    .collect::<Result<_, _>>()?;\n                Ok(seq.into())\n            })\n            .deserialize(d)\n    }\n}\n\nimpl fmt::Display for TomlTrimPaths {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            TomlTrimPaths::All => write!(f, \"all\"),\n            TomlTrimPaths::Values(v) if v.is_empty() => write!(f, \"none\"),\n            TomlTrimPaths::Values(v) => {\n                let mut iter = v.iter();\n                if let Some(value) = iter.next() {\n                    write!(f, \"{value}\")?;\n                }\n                for value in iter {\n                    write!(f, \",{value}\")?;\n                }\n                Ok(())\n            }\n        }\n    }\n}\n\nimpl From<TomlTrimPathsValue> for TomlTrimPaths {\n    fn from(value: TomlTrimPathsValue) -> Self {\n        TomlTrimPaths::Values(vec![value])\n    }\n}\n\nimpl From<Vec<TomlTrimPathsValue>> for TomlTrimPaths {\n    fn from(value: Vec<TomlTrimPathsValue>) -> Self {\n        TomlTrimPaths::Values(value)\n    }\n}\n\n#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Serialize, Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub enum TomlTrimPathsValue {\n    Diagnostics,\n    Macro,\n    Object,\n}\n\nimpl TomlTrimPathsValue {\n    pub fn as_str(&self) -> &'static str {\n        match self {\n            TomlTrimPathsValue::Diagnostics => \"diagnostics\",\n            TomlTrimPathsValue::Macro => \"macro\",\n            TomlTrimPathsValue::Object => \"object\",\n        }\n    }\n}\n\nimpl fmt::Display for TomlTrimPathsValue {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{}\", self.as_str())\n    }\n}\n\npub type TomlLibTarget = TomlTarget;\npub type TomlBinTarget = TomlTarget;\npub type TomlExampleTarget = TomlTarget;\npub type TomlTestTarget = TomlTarget;\npub type TomlBenchTarget = TomlTarget;\n\n#[derive(Default, Serialize, Deserialize, Debug, Clone)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlTarget {\n    pub name: Option<String>,\n\n    // The intention was to only accept `crate-type` here but historical\n    // versions of Cargo also accepted `crate_type`, so look for both.\n    pub crate_type: Option<Vec<String>>,\n    #[serde(rename = \"crate_type\")]\n    pub crate_type2: Option<Vec<String>>,\n\n    #[cfg_attr(feature = \"unstable-schema\", schemars(with = \"Option<String>\"))]\n    pub path: Option<PathValue>,\n    // Note that `filename` is used for the cargo-feature `different_binary_name`\n    pub filename: Option<String>,\n    pub test: Option<bool>,\n    pub doctest: Option<bool>,\n    pub bench: Option<bool>,\n    pub doc: Option<bool>,\n    pub doc_scrape_examples: Option<bool>,\n    pub proc_macro: Option<bool>,\n    #[serde(rename = \"proc_macro\")]\n    pub proc_macro2: Option<bool>,\n    pub harness: Option<bool>,\n    pub required_features: Option<Vec<String>>,\n    pub edition: Option<String>,\n}\n\nimpl TomlTarget {\n    pub fn new() -> TomlTarget {\n        TomlTarget::default()\n    }\n\n    pub fn proc_macro(&self) -> Option<bool> {\n        self.proc_macro.or(self.proc_macro2).or_else(|| {\n            if let Some(types) = self.crate_types() {\n                if types.contains(&\"proc-macro\".to_string()) {\n                    return Some(true);\n                }\n            }\n            None\n        })\n    }\n\n    pub fn crate_types(&self) -> Option<&Vec<String>> {\n        self.crate_type\n            .as_ref()\n            .or_else(|| self.crate_type2.as_ref())\n    }\n}\n\nmacro_rules! str_newtype {\n    ($name:ident) => {\n        /// Verified string newtype\n        #[derive(Serialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]\n        #[serde(transparent)]\n        #[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\n        pub struct $name<T: AsRef<str> = String>(T);\n\n        impl<T: AsRef<str>> $name<T> {\n            pub fn into_inner(self) -> T {\n                self.0\n            }\n        }\n\n        impl<T: AsRef<str>> AsRef<str> for $name<T> {\n            fn as_ref(&self) -> &str {\n                self.0.as_ref()\n            }\n        }\n\n        impl<T: AsRef<str>> std::ops::Deref for $name<T> {\n            type Target = T;\n\n            fn deref(&self) -> &Self::Target {\n                &self.0\n            }\n        }\n\n        impl<T: AsRef<str>> std::borrow::Borrow<str> for $name<T> {\n            fn borrow(&self) -> &str {\n                self.0.as_ref()\n            }\n        }\n\n        impl<'a> std::str::FromStr for $name<String> {\n            type Err = restricted_names::NameValidationError;\n\n            fn from_str(value: &str) -> Result<Self, Self::Err> {\n                Self::new(value.to_owned())\n            }\n        }\n\n        impl<'de, T: AsRef<str> + serde::Deserialize<'de>> serde::Deserialize<'de> for $name<T> {\n            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n            where\n                D: serde::Deserializer<'de>,\n            {\n                let inner = T::deserialize(deserializer)?;\n                Self::new(inner).map_err(serde::de::Error::custom)\n            }\n        }\n\n        impl<T: AsRef<str>> Display for $name<T> {\n            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n                self.0.as_ref().fmt(f)\n            }\n        }\n    };\n}\n\nstr_newtype!(PackageName);\n\nimpl<T: AsRef<str>> PackageName<T> {\n    /// Validated package name\n    pub fn new(name: T) -> Result<Self, NameValidationError> {\n        restricted_names::validate_package_name(name.as_ref())?;\n        Ok(Self(name))\n    }\n}\n\nimpl PackageName {\n    /// Coerce a value to be a validate package name\n    ///\n    /// Replaces invalid values with `placeholder`\n    pub fn sanitize(name: impl AsRef<str>, placeholder: char) -> Self {\n        PackageName(restricted_names::sanitize_package_name(\n            name.as_ref(),\n            placeholder,\n        ))\n    }\n}\n\nstr_newtype!(RegistryName);\n\nimpl<T: AsRef<str>> RegistryName<T> {\n    /// Validated registry name\n    pub fn new(name: T) -> Result<Self, NameValidationError> {\n        restricted_names::validate_registry_name(name.as_ref())?;\n        Ok(Self(name))\n    }\n}\n\nstr_newtype!(ProfileName);\n\nimpl<T: AsRef<str>> ProfileName<T> {\n    /// Validated profile name\n    pub fn new(name: T) -> Result<Self, NameValidationError> {\n        restricted_names::validate_profile_name(name.as_ref())?;\n        Ok(Self(name))\n    }\n}\n\nstr_newtype!(FeatureName);\n\nimpl<T: AsRef<str>> FeatureName<T> {\n    /// Validated feature name\n    pub fn new(name: T) -> Result<Self, NameValidationError> {\n        restricted_names::validate_feature_name(name.as_ref())?;\n        Ok(Self(name))\n    }\n}\n\nstr_newtype!(PathBaseName);\n\nimpl<T: AsRef<str>> PathBaseName<T> {\n    /// Validated path base name\n    pub fn new(name: T) -> Result<Self, NameValidationError> {\n        restricted_names::validate_path_base_name(name.as_ref())?;\n        Ok(Self(name))\n    }\n}\n\n/// Corresponds to a `target` entry, but `TomlTarget` is already used.\n#[derive(Serialize, Deserialize, Debug, Clone)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlPlatform {\n    pub dependencies: Option<BTreeMap<PackageName, InheritableDependency>>,\n    pub build_dependencies: Option<BTreeMap<PackageName, InheritableDependency>>,\n    #[serde(rename = \"build_dependencies\")]\n    pub build_dependencies2: Option<BTreeMap<PackageName, InheritableDependency>>,\n    pub dev_dependencies: Option<BTreeMap<PackageName, InheritableDependency>>,\n    #[serde(rename = \"dev_dependencies\")]\n    pub dev_dependencies2: Option<BTreeMap<PackageName, InheritableDependency>>,\n}\n\nimpl TomlPlatform {\n    pub fn dev_dependencies(&self) -> Option<&BTreeMap<PackageName, InheritableDependency>> {\n        self.dev_dependencies\n            .as_ref()\n            .or(self.dev_dependencies2.as_ref())\n    }\n\n    pub fn build_dependencies(&self) -> Option<&BTreeMap<PackageName, InheritableDependency>> {\n        self.build_dependencies\n            .as_ref()\n            .or(self.build_dependencies2.as_ref())\n    }\n}\n\n#[derive(Serialize, Debug, Clone)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct InheritableLints {\n    #[serde(skip_serializing_if = \"std::ops::Not::not\")]\n    #[cfg_attr(feature = \"unstable-schema\", schemars(default))]\n    pub workspace: bool,\n    #[serde(flatten)]\n    pub lints: TomlLints,\n}\n\nimpl InheritableLints {\n    pub fn normalized(&self) -> Result<&TomlLints, UnresolvedError> {\n        if self.workspace {\n            Err(UnresolvedError)\n        } else {\n            Ok(&self.lints)\n        }\n    }\n}\n\nimpl<'de> Deserialize<'de> for InheritableLints {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        struct InheritableLintsVisitor;\n\n        impl<'de> de::Visitor<'de> for InheritableLintsVisitor {\n            // The type that our Visitor is going to produce.\n            type Value = InheritableLints;\n\n            // Format a message stating what data this Visitor expects to receive.\n            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n                formatter.write_str(\"a lints table\")\n            }\n\n            // Deserialize MyMap from an abstract \"map\" provided by the\n            // Deserializer. The MapAccess input is a callback provided by\n            // the Deserializer to let us see each entry in the map.\n            fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>\n            where\n                M: de::MapAccess<'de>,\n            {\n                let mut lints = TomlLints::new();\n                let mut workspace = false;\n\n                // While there are entries remaining in the input, add them\n                // into our map.\n                while let Some(key) = access.next_key()? {\n                    if key == \"workspace\" {\n                        workspace = match access.next_value()? {\n                            Some(WorkspaceValue) => true,\n                            None => false,\n                        };\n                    } else {\n                        let value = access.next_value()?;\n                        lints.insert(key, value);\n                    }\n                }\n\n                Ok(InheritableLints { workspace, lints })\n            }\n        }\n\n        deserializer.deserialize_map(InheritableLintsVisitor)\n    }\n}\n\npub type TomlLints = BTreeMap<String, TomlToolLints>;\n\npub type TomlToolLints = BTreeMap<String, TomlLint>;\n\n#[derive(Serialize, Debug, Clone)]\n#[serde(untagged)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub enum TomlLint {\n    Level(TomlLintLevel),\n    Config(TomlLintConfig),\n}\n\nimpl<'de> Deserialize<'de> for TomlLint {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        UntaggedEnumVisitor::new()\n            .string(|string| {\n                TomlLintLevel::deserialize(string.into_deserializer()).map(TomlLint::Level)\n            })\n            .map(|map| map.deserialize().map(TomlLint::Config))\n            .deserialize(deserializer)\n    }\n}\n\nimpl TomlLint {\n    pub fn level(&self) -> TomlLintLevel {\n        match self {\n            Self::Level(level) => *level,\n            Self::Config(config) => config.level,\n        }\n    }\n\n    pub fn priority(&self) -> i8 {\n        match self {\n            Self::Level(_) => 0,\n            Self::Config(config) => config.priority,\n        }\n    }\n\n    pub fn config(&self) -> Option<&toml::Table> {\n        match self {\n            Self::Level(_) => None,\n            Self::Config(config) => Some(&config.config),\n        }\n    }\n}\n\n#[derive(Serialize, Deserialize, Debug, Clone)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct TomlLintConfig {\n    pub level: TomlLintLevel,\n    #[serde(default)]\n    pub priority: i8,\n    #[serde(flatten)]\n    #[cfg_attr(\n        feature = \"unstable-schema\",\n        schemars(with = \"HashMap<String, TomlValueWrapper>\")\n    )]\n    pub config: toml::Table,\n}\n\n#[derive(Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub enum TomlLintLevel {\n    Forbid,\n    Deny,\n    Warn,\n    Allow,\n}\n\n#[derive(Serialize, Deserialize, Debug, Default, Clone)]\n#[serde(rename_all = \"kebab-case\")]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct Hints {\n    #[cfg_attr(\n        feature = \"unstable-schema\",\n        schemars(with = \"Option<TomlValueWrapper>\")\n    )]\n    pub mostly_unused: Option<toml::Value>,\n}\n\n#[derive(Copy, Clone, Debug)]\npub struct InvalidCargoFeatures {}\n\nimpl<'de> de::Deserialize<'de> for InvalidCargoFeatures {\n    fn deserialize<D>(_d: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        use serde::de::Error as _;\n\n        Err(D::Error::custom(\n            \"the field `cargo-features` should be set at the top of Cargo.toml before any tables\",\n        ))\n    }\n}\n\n/// This can be parsed from either a TOML string or array,\n/// but is always stored as a vector.\n#[derive(Clone, Debug, Serialize, Eq, PartialEq, PartialOrd, Ord)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct StringOrVec(pub Vec<String>);\n\nimpl StringOrVec {\n    pub fn iter<'a>(&'a self) -> std::slice::Iter<'a, String> {\n        self.0.iter()\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for StringOrVec {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        UntaggedEnumVisitor::new()\n            .expecting(\"string or list of strings\")\n            .string(|value| Ok(StringOrVec(vec![value.to_owned()])))\n            .seq(|value| value.deserialize().map(StringOrVec))\n            .deserialize(deserializer)\n    }\n}\n\n#[derive(Clone, Debug, Serialize, Eq, PartialEq)]\n#[serde(untagged)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub enum StringOrBool {\n    String(String),\n    Bool(bool),\n}\n\nimpl<'de> Deserialize<'de> for StringOrBool {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        UntaggedEnumVisitor::new()\n            .bool(|b| Ok(StringOrBool::Bool(b)))\n            .string(|s| Ok(StringOrBool::String(s.to_owned())))\n            .deserialize(deserializer)\n    }\n}\n\n#[derive(Clone, Debug, Serialize, Eq, PartialEq)]\n#[serde(untagged)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub enum TomlPackageBuild {\n    /// If build scripts are disabled or enabled.\n    /// If true, `build.rs` in the root folder will be the build script.\n    Auto(bool),\n\n    /// Path of Build Script if there's just one script.\n    SingleScript(String),\n\n    /// Vector of paths if multiple build script are to be used.\n    MultipleScript(Vec<String>),\n}\n\nimpl<'de> Deserialize<'de> for TomlPackageBuild {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        UntaggedEnumVisitor::new()\n            .bool(|b| Ok(TomlPackageBuild::Auto(b)))\n            .string(|s| Ok(TomlPackageBuild::SingleScript(s.to_owned())))\n            .seq(|value| value.deserialize().map(TomlPackageBuild::MultipleScript))\n            .deserialize(deserializer)\n    }\n}\n\n#[derive(PartialEq, Clone, Debug, Serialize)]\n#[serde(untagged)]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub enum VecStringOrBool {\n    VecString(Vec<String>),\n    Bool(bool),\n}\n\nimpl<'de> de::Deserialize<'de> for VecStringOrBool {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        UntaggedEnumVisitor::new()\n            .expecting(\"a boolean or vector of strings\")\n            .bool(|value| Ok(VecStringOrBool::Bool(value)))\n            .seq(|value| value.deserialize().map(VecStringOrBool::VecString))\n            .deserialize(deserializer)\n    }\n}\n\n#[derive(Clone, PartialEq, Eq)]\npub struct PathValue(pub PathBuf);\n\nimpl fmt::Debug for PathValue {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.0.fmt(f)\n    }\n}\n\nimpl ser::Serialize for PathValue {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        self.0.serialize(serializer)\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for PathValue {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        Ok(PathValue(String::deserialize(deserializer)?.into()))\n    }\n}\n\n/// Error validating names in Cargo.\n#[derive(Debug, thiserror::Error)]\n#[error(\"manifest field was not resolved\")]\n#[non_exhaustive]\n#[cfg_attr(feature = \"unstable-schema\", derive(schemars::JsonSchema))]\npub struct UnresolvedError;\n\n#[cfg(feature = \"unstable-schema\")]\n#[test]\nfn dump_manifest_schema() {\n    let schema = schemars::schema_for!(crate::manifest::TomlManifest);\n    let dump = serde_json::to_string_pretty(&schema).unwrap();\n    snapbox::assert_data_eq!(dump, snapbox::file!(\"../../manifest.schema.json\").raw());\n}\n"
  },
  {
    "path": "crates/cargo-util-schemas/src/manifest/rust_version.rs",
    "content": "use std::fmt;\nuse std::fmt::Display;\n\nuse serde_untagged::UntaggedEnumVisitor;\n\nuse crate::core::PartialVersion;\nuse crate::core::PartialVersionError;\n\n#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone, Debug)]\npub struct RustVersion {\n    major: u64,\n    minor: Option<u64>,\n    patch: Option<u64>,\n}\n\nimpl RustVersion {\n    pub const fn new(major: u64, minor: u64, patch: u64) -> Self {\n        Self {\n            major,\n            minor: Some(minor),\n            patch: Some(patch),\n        }\n    }\n\n    pub fn is_compatible_with(&self, rustc: &PartialVersion) -> bool {\n        let msrv = self.to_partial().to_caret_req();\n        // Remove any pre-release identifiers for easier comparison\n        let rustc = semver::Version {\n            major: rustc.major,\n            minor: rustc.minor.unwrap_or_default(),\n            patch: rustc.patch.unwrap_or_default(),\n            pre: Default::default(),\n            build: Default::default(),\n        };\n        msrv.matches(&rustc)\n    }\n\n    pub fn to_partial(&self) -> PartialVersion {\n        let Self {\n            major,\n            minor,\n            patch,\n        } = *self;\n        PartialVersion {\n            major,\n            minor,\n            patch,\n            pre: None,\n            build: None,\n        }\n    }\n}\n\nimpl std::str::FromStr for RustVersion {\n    type Err = RustVersionError;\n\n    fn from_str(value: &str) -> Result<Self, Self::Err> {\n        let partial = value.parse::<PartialVersion>();\n        let partial = partial.map_err(RustVersionErrorKind::PartialVersion)?;\n        partial.try_into()\n    }\n}\n\nimpl TryFrom<semver::Version> for RustVersion {\n    type Error = RustVersionError;\n\n    fn try_from(version: semver::Version) -> Result<Self, Self::Error> {\n        let version = PartialVersion::from(version);\n        Self::try_from(version)\n    }\n}\n\nimpl TryFrom<PartialVersion> for RustVersion {\n    type Error = RustVersionError;\n\n    fn try_from(partial: PartialVersion) -> Result<Self, Self::Error> {\n        let PartialVersion {\n            major,\n            minor,\n            patch,\n            pre,\n            build,\n        } = partial;\n        if pre.is_some() {\n            return Err(RustVersionErrorKind::Prerelease.into());\n        }\n        if build.is_some() {\n            return Err(RustVersionErrorKind::BuildMetadata.into());\n        }\n        Ok(Self {\n            major,\n            minor,\n            patch,\n        })\n    }\n}\n\nimpl serde::Serialize for RustVersion {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: serde::Serializer,\n    {\n        serializer.collect_str(self)\n    }\n}\n\nimpl<'de> serde::Deserialize<'de> for RustVersion {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        UntaggedEnumVisitor::new()\n            .expecting(\"SemVer version\")\n            .string(|value| value.parse().map_err(serde::de::Error::custom))\n            .deserialize(deserializer)\n    }\n}\n\nimpl Display for RustVersion {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.to_partial().fmt(f)\n    }\n}\n\n/// Error parsing a [`RustVersion`].\n#[derive(Debug, thiserror::Error)]\n#[error(transparent)]\npub struct RustVersionError(#[from] RustVersionErrorKind);\n\n/// Non-public error kind for [`RustVersionError`].\n#[non_exhaustive]\n#[derive(Debug, thiserror::Error)]\nenum RustVersionErrorKind {\n    #[error(\"unexpected prerelease field, expected a version like \\\"1.32\\\"\")]\n    Prerelease,\n\n    #[error(\"unexpected build field, expected a version like \\\"1.32\\\"\")]\n    BuildMetadata,\n\n    #[error(transparent)]\n    PartialVersion(#[from] PartialVersionError),\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use snapbox::prelude::*;\n    use snapbox::str;\n\n    #[test]\n    fn is_compatible_with_rustc() {\n        let cases = &[\n            (\"1\", \"1.70.0\", true),\n            (\"1.30\", \"1.70.0\", true),\n            (\"1.30.10\", \"1.70.0\", true),\n            (\"1.70\", \"1.70.0\", true),\n            (\"1.70.0\", \"1.70.0\", true),\n            (\"1.70.1\", \"1.70.0\", false),\n            (\"1.70\", \"1.70.0-nightly\", true),\n            (\"1.70.0\", \"1.70.0-nightly\", true),\n            (\"1.71\", \"1.70.0\", false),\n            (\"2\", \"1.70.0\", false),\n        ];\n        let mut passed = true;\n        for (msrv, rustc, expected) in cases {\n            let msrv: RustVersion = msrv.parse().unwrap();\n            let rustc = PartialVersion::from(semver::Version::parse(rustc).unwrap());\n            if msrv.is_compatible_with(&rustc) != *expected {\n                println!(\"failed: {msrv} is_compatible_with {rustc} == {expected}\");\n                passed = false;\n            }\n        }\n        assert!(passed);\n    }\n\n    #[test]\n    fn is_compatible_with_workspace_msrv() {\n        let cases = &[\n            (\"1\", \"1\", true),\n            (\"1\", \"1.70\", true),\n            (\"1\", \"1.70.0\", true),\n            (\"1.30\", \"1\", false),\n            (\"1.30\", \"1.70\", true),\n            (\"1.30\", \"1.70.0\", true),\n            (\"1.30.10\", \"1\", false),\n            (\"1.30.10\", \"1.70\", true),\n            (\"1.30.10\", \"1.70.0\", true),\n            (\"1.70\", \"1\", false),\n            (\"1.70\", \"1.70\", true),\n            (\"1.70\", \"1.70.0\", true),\n            (\"1.70.0\", \"1\", false),\n            (\"1.70.0\", \"1.70\", true),\n            (\"1.70.0\", \"1.70.0\", true),\n            (\"1.70.1\", \"1\", false),\n            (\"1.70.1\", \"1.70\", false),\n            (\"1.70.1\", \"1.70.0\", false),\n            (\"1.71\", \"1\", false),\n            (\"1.71\", \"1.70\", false),\n            (\"1.71\", \"1.70.0\", false),\n            (\"2\", \"1.70.0\", false),\n        ];\n        let mut passed = true;\n        for (dep_msrv, ws_msrv, expected) in cases {\n            let dep_msrv: RustVersion = dep_msrv.parse().unwrap();\n            let ws_msrv = ws_msrv.parse::<RustVersion>().unwrap().to_partial();\n            if dep_msrv.is_compatible_with(&ws_msrv) != *expected {\n                println!(\"failed: {dep_msrv} is_compatible_with {ws_msrv} == {expected}\");\n                passed = false;\n            }\n        }\n        assert!(passed);\n    }\n\n    #[test]\n    fn parse_errors() {\n        let cases = &[\n            // Disallow caret\n            (\n                \"^1.43\",\n                str![[r#\"unexpected version requirement, expected a version like \"1.32\"\"#]],\n            ),\n            // Valid pre-release\n            (\n                \"1.43.0-beta.1\",\n                str![[r#\"unexpected prerelease field, expected a version like \"1.32\"\"#]],\n            ),\n            // Bad pre-release\n            (\n                \"1.43-beta.1\",\n                str![[r#\"unexpected prerelease field, expected a version like \"1.32\"\"#]],\n            ),\n            // Weird wildcard\n            (\n                \"x\",\n                str![[r#\"unexpected version requirement, expected a version like \"1.32\"\"#]],\n            ),\n            (\n                \"1.x\",\n                str![[r#\"unexpected version requirement, expected a version like \"1.32\"\"#]],\n            ),\n            (\n                \"1.1.x\",\n                str![[r#\"unexpected version requirement, expected a version like \"1.32\"\"#]],\n            ),\n            // Non-sense\n            (\"foodaddle\", str![[r#\"expected a version like \"1.32\"\"#]]),\n        ];\n        for (input, expected) in cases {\n            let actual: Result<RustVersion, _> = input.parse();\n            let actual = match actual {\n                Ok(result) => format!(\"didn't fail: {result:?}\"),\n                Err(err) => err.to_string(),\n            };\n            snapbox::assert_data_eq!(actual, expected.clone().raw());\n        }\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util-schemas/src/messages.rs",
    "content": "//! Schemas for JSON messages emitted by Cargo.\n\nuse std::collections::BTreeMap;\nuse std::path::PathBuf;\n\n/// File information of a package archive generated by `cargo package --list`.\n#[derive(Debug, serde::Serialize)]\n#[serde(rename_all = \"snake_case\")]\npub struct PackageList {\n    /// The Package ID Spec of the package.\n    pub id: crate::core::PackageIdSpec,\n    /// A map of relative paths in the archive to their detailed file information.\n    pub files: BTreeMap<PathBuf, PackageFile>,\n}\n\n/// Where the file is from.\n#[derive(Debug, serde::Serialize)]\n#[serde(rename_all = \"snake_case\", tag = \"kind\")]\npub enum PackageFile {\n    /// File being copied from another location.\n    Copy {\n        /// An absolute path to the actual file content\n        path: PathBuf,\n    },\n    /// File being generated during packaging\n    Generate {\n        /// An absolute path to the original file the generated one is based on.\n        /// if any.\n        #[serde(skip_serializing_if = \"Option::is_none\")]\n        path: Option<PathBuf>,\n    },\n}\n"
  },
  {
    "path": "crates/cargo-util-schemas/src/restricted_names.rs",
    "content": "//! Helpers for validating and checking names like package and crate names.\n\ntype Result<T> = std::result::Result<T, NameValidationError>;\n\n/// Error validating names in Cargo.\n#[derive(Debug, thiserror::Error)]\n#[error(transparent)]\npub struct NameValidationError(#[from] ErrorKind);\n\n/// Non-public error kind for [`NameValidationError`].\n#[non_exhaustive]\n#[derive(Debug, thiserror::Error)]\nenum ErrorKind {\n    #[error(\"{0} cannot be empty\")]\n    Empty(&'static str),\n\n    #[error(\"invalid character `{ch}` in {what}: `{name}`, {reason}\")]\n    InvalidCharacter {\n        ch: char,\n        what: &'static str,\n        name: String,\n        reason: &'static str,\n    },\n\n    #[error(\n        \"profile name `{name}` is reserved\\n{help}\\n\\\n         See https://doc.rust-lang.org/cargo/reference/profiles.html \\\n         for more on configuring profiles.\"\n    )]\n    ProfileNameReservedKeyword { name: String, help: &'static str },\n\n    #[error(\"feature named `{0}` is not allowed to start with `dep:`\")]\n    FeatureNameStartsWithDepColon(String),\n}\n\npub(crate) fn validate_package_name(name: &str) -> Result<()> {\n    for part in name.split(\"::\") {\n        validate_name(part, \"package name\")?;\n    }\n    Ok(())\n}\n\npub(crate) fn validate_registry_name(name: &str) -> Result<()> {\n    validate_name(name, \"registry name\")\n}\n\npub(crate) fn validate_name(name: &str, what: &'static str) -> Result<()> {\n    if name.is_empty() {\n        return Err(ErrorKind::Empty(what).into());\n    }\n\n    let mut chars = name.chars();\n    if let Some(ch) = chars.next() {\n        if ch.is_digit(10) {\n            // A specific error for a potentially common case.\n            return Err(ErrorKind::InvalidCharacter {\n                ch,\n                what,\n                name: name.into(),\n                reason: \"the name cannot start with a digit\",\n            }\n            .into());\n        }\n        if !(unicode_ident::is_xid_start(ch) || ch == '_') {\n            return Err(ErrorKind::InvalidCharacter {\n                ch,\n                what,\n                name: name.into(),\n                reason: \"the first character must be a Unicode XID start character \\\n                 (most letters or `_`)\",\n            }\n            .into());\n        }\n    }\n    for ch in chars {\n        if !(unicode_ident::is_xid_continue(ch) || ch == '-') {\n            return Err(ErrorKind::InvalidCharacter {\n                ch,\n                what,\n                name: name.into(),\n                reason: \"characters must be Unicode XID characters \\\n                 (numbers, `-`, `_`, or most letters)\",\n            }\n            .into());\n        }\n    }\n    Ok(())\n}\n\n/// Ensure a package name is [valid][validate_package_name]\npub(crate) fn sanitize_package_name(name: &str, placeholder: char) -> String {\n    let mut slug = String::new();\n    for part in name.split(\"::\") {\n        if !slug.is_empty() {\n            slug.push_str(\"::\");\n        }\n        slug.push_str(&sanitize_name(part, placeholder));\n    }\n    slug\n}\n\npub(crate) fn sanitize_name(name: &str, placeholder: char) -> String {\n    let mut slug = String::new();\n    let mut chars = name.chars();\n    while let Some(ch) = chars.next() {\n        if (unicode_ident::is_xid_start(ch) || ch == '_') && !ch.is_digit(10) {\n            slug.push(ch);\n            break;\n        }\n    }\n    while let Some(ch) = chars.next() {\n        if unicode_ident::is_xid_continue(ch) || ch == '-' {\n            slug.push(ch);\n        } else {\n            slug.push(placeholder);\n        }\n    }\n    if slug.is_empty() {\n        slug.push_str(\"package\");\n    }\n    slug\n}\n\n/// Validate dir-names and profile names according to RFC 2678.\npub(crate) fn validate_profile_name(name: &str) -> Result<()> {\n    if let Some(ch) = name\n        .chars()\n        .find(|ch| !ch.is_alphanumeric() && *ch != '_' && *ch != '-')\n    {\n        return Err(ErrorKind::InvalidCharacter {\n            ch,\n            what: \"profile name\",\n            name: name.into(),\n            reason: \"allowed characters are letters, numbers, underscore, and hyphen\",\n        }\n        .into());\n    }\n\n    let lower_name = name.to_lowercase();\n    if lower_name == \"debug\" {\n        return Err(ErrorKind::ProfileNameReservedKeyword {\n            name: name.into(),\n            help: \"To configure the default development profile, \\\n                use the name `dev` as in [profile.dev]\",\n        }\n        .into());\n    }\n    if lower_name == \"build-override\" {\n        return Err(ErrorKind::ProfileNameReservedKeyword {\n            name: name.into(),\n            help: \"To configure build dependency settings, use [profile.dev.build-override] \\\n                 and [profile.release.build-override]\",\n        }\n        .into());\n    }\n\n    // These are some arbitrary reservations. We have no plans to use\n    // these, but it seems safer to reserve a few just in case we want to\n    // add more built-in profiles in the future. We can also uses special\n    // syntax like cargo:foo if needed. But it is unlikely these will ever\n    // be used.\n    if matches!(\n        lower_name.as_str(),\n        \"build\"\n            | \"check\"\n            | \"clean\"\n            | \"config\"\n            | \"fetch\"\n            | \"fix\"\n            | \"install\"\n            | \"metadata\"\n            | \"package\"\n            | \"publish\"\n            | \"report\"\n            | \"root\"\n            | \"run\"\n            | \"rust\"\n            | \"rustc\"\n            | \"rustdoc\"\n            | \"target\"\n            | \"tmp\"\n            | \"uninstall\"\n    ) || lower_name.starts_with(\"cargo\")\n    {\n        return Err(ErrorKind::ProfileNameReservedKeyword {\n            name: name.into(),\n            help: \"Please choose a different name.\",\n        }\n        .into());\n    }\n\n    Ok(())\n}\n\npub(crate) fn validate_feature_name(name: &str) -> Result<()> {\n    let what = \"feature name\";\n    if name.is_empty() {\n        return Err(ErrorKind::Empty(what).into());\n    }\n\n    if name.starts_with(\"dep:\") {\n        return Err(ErrorKind::FeatureNameStartsWithDepColon(name.into()).into());\n    }\n    if name.contains('/') {\n        return Err(ErrorKind::InvalidCharacter {\n            ch: '/',\n            what,\n            name: name.into(),\n            reason: \"feature name is not allowed to contain slashes\",\n        }\n        .into());\n    }\n    let mut chars = name.chars();\n    if let Some(ch) = chars.next() {\n        if !(unicode_ident::is_xid_start(ch) || ch == '_' || ch.is_digit(10)) {\n            return Err(ErrorKind::InvalidCharacter {\n                ch,\n                what,\n                name: name.into(),\n                reason: \"the first character must be a Unicode XID start character or digit \\\n                 (most letters or `_` or `0` to `9`)\",\n            }\n            .into());\n        }\n    }\n    for ch in chars {\n        if !(unicode_ident::is_xid_continue(ch) || ch == '-' || ch == '+' || ch == '.') {\n            return Err(ErrorKind::InvalidCharacter {\n                ch,\n                what,\n                name: name.into(),\n                reason: \"characters must be Unicode XID characters, '-', `+`, or `.` \\\n                 (numbers, `+`, `-`, `_`, `.`, or most letters)\",\n            }\n            .into());\n        }\n    }\n    Ok(())\n}\n\npub(crate) fn validate_path_base_name(name: &str) -> Result<()> {\n    validate_name(name, \"path base name\")\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn valid_feature_names() {\n        assert!(validate_feature_name(\"c++17\").is_ok());\n        assert!(validate_feature_name(\"128bit\").is_ok());\n        assert!(validate_feature_name(\"_foo\").is_ok());\n        assert!(validate_feature_name(\"feat-name\").is_ok());\n        assert!(validate_feature_name(\"feat_name\").is_ok());\n        assert!(validate_feature_name(\"foo.bar\").is_ok());\n\n        assert!(validate_feature_name(\"\").is_err());\n        assert!(validate_feature_name(\"+foo\").is_err());\n        assert!(validate_feature_name(\"-foo\").is_err());\n        assert!(validate_feature_name(\".foo\").is_err());\n        assert!(validate_feature_name(\"dep:bar\").is_err());\n        assert!(validate_feature_name(\"foo/bar\").is_err());\n        assert!(validate_feature_name(\"foo:bar\").is_err());\n        assert!(validate_feature_name(\"foo?\").is_err());\n        assert!(validate_feature_name(\"?foo\").is_err());\n        assert!(validate_feature_name(\"ⒶⒷⒸ\").is_err());\n        assert!(validate_feature_name(\"a¼\").is_err());\n        assert!(validate_feature_name(\"\").is_err());\n    }\n}\n"
  },
  {
    "path": "crates/cargo-util-schemas/src/schema.rs",
    "content": "use schemars::JsonSchema;\n\nuse serde::{Deserialize, Serialize};\n\nuse toml::Value as TomlValue;\n\n#[derive(Serialize, Deserialize)]\npub struct TomlValueWrapper(pub TomlValue);\n\nimpl JsonSchema for TomlValueWrapper {\n    fn schema_name() -> std::borrow::Cow<'static, str> {\n        \"TomlValue\".into()\n    }\n\n    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {\n        // HACK: this is both more and less permissive than `TomlValue` but its close\n        generator.subschema_for::<serde_json::Value>().into()\n    }\n}\n"
  },
  {
    "path": "crates/crates-io/Cargo.toml",
    "content": "[package]\nname = \"crates-io\"\nversion = \"0.40.19\"\nrust-version = \"1.94\"  # MSRV:1\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"\"\"\nHelpers for interacting with crates.io\n\"\"\"\n\n[lib]\nname = \"crates_io\"\npath = \"lib.rs\"\n\n[dependencies]\ncurl.workspace = true\npercent-encoding.workspace = true\nserde = { workspace = true, features = [\"derive\"] }\nserde_json.workspace = true\nthiserror.workspace = true\nurl.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/crates-io/README.md",
    "content": "> This crate is maintained by the Cargo team for use by the wider\n> ecosystem. This crate follows semver compatibility for its APIs.\n"
  },
  {
    "path": "crates/crates-io/lib.rs",
    "content": "//! > This crate is maintained by the Cargo team for use by the wider\n//! > ecosystem. This crate follows semver compatibility for its APIs.\n\nuse std::collections::BTreeMap;\nuse std::fs::File;\nuse std::io::prelude::*;\nuse std::io::{Cursor, SeekFrom};\nuse std::time::Instant;\n\nuse curl::easy::{Easy, List};\nuse percent_encoding::{NON_ALPHANUMERIC, percent_encode};\nuse serde::{Deserialize, Serialize};\nuse url::Url;\n\npub type Result<T> = std::result::Result<T, Error>;\n\npub struct Registry {\n    /// The base URL for issuing API requests.\n    host: String,\n    /// Optional authorization token.\n    /// If None, commands requiring authorization will fail.\n    token: Option<String>,\n    /// Curl handle for issuing requests.\n    handle: Easy,\n    /// Whether to include the authorization token with all requests.\n    auth_required: bool,\n}\n\n#[derive(PartialEq, Clone, Copy)]\npub enum Auth {\n    Authorized,\n    Unauthorized,\n}\n\n#[derive(Deserialize)]\npub struct Crate {\n    pub name: String,\n    pub description: Option<String>,\n    pub max_version: String,\n}\n\n/// This struct is serialized as JSON and sent as metadata ahead of the crate\n/// tarball when publishing crates to a crate registry like crates.io.\n///\n/// see <https://doc.rust-lang.org/cargo/reference/registry-web-api.html#publish>\n#[derive(Serialize, Deserialize)]\npub struct NewCrate {\n    pub name: String,\n    pub vers: String,\n    pub deps: Vec<NewCrateDependency>,\n    pub features: BTreeMap<String, Vec<String>>,\n    pub authors: Vec<String>,\n    pub description: Option<String>,\n    pub documentation: Option<String>,\n    pub homepage: Option<String>,\n    pub readme: Option<String>,\n    pub readme_file: Option<String>,\n    pub keywords: Vec<String>,\n    pub categories: Vec<String>,\n    pub license: Option<String>,\n    pub license_file: Option<String>,\n    pub repository: Option<String>,\n    pub badges: BTreeMap<String, BTreeMap<String, String>>,\n    pub links: Option<String>,\n    pub rust_version: Option<String>,\n}\n\n#[derive(Serialize, Deserialize)]\npub struct NewCrateDependency {\n    pub optional: bool,\n    pub default_features: bool,\n    pub name: String,\n    pub features: Vec<String>,\n    pub version_req: String,\n    pub target: Option<String>,\n    pub kind: String,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    pub registry: Option<String>,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    pub explicit_name_in_toml: Option<String>,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    pub artifact: Option<Vec<String>>,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    pub bindep_target: Option<String>,\n    #[serde(default, skip_serializing_if = \"std::ops::Not::not\")]\n    pub lib: bool,\n}\n\n#[derive(Deserialize)]\npub struct User {\n    pub id: u32,\n    pub login: String,\n    pub avatar: Option<String>,\n    pub email: Option<String>,\n    pub name: Option<String>,\n}\n\npub struct Warnings {\n    pub invalid_categories: Vec<String>,\n    pub invalid_badges: Vec<String>,\n    pub other: Vec<String>,\n}\n\n#[derive(Deserialize)]\nstruct R {\n    ok: bool,\n}\n#[derive(Deserialize)]\nstruct OwnerResponse {\n    ok: bool,\n    msg: String,\n}\n#[derive(Deserialize)]\nstruct ApiErrorList {\n    errors: Vec<ApiError>,\n}\n#[derive(Deserialize)]\nstruct ApiError {\n    detail: String,\n}\n#[derive(Serialize)]\nstruct OwnersReq<'a> {\n    users: &'a [&'a str],\n}\n#[derive(Deserialize)]\nstruct Users {\n    users: Vec<User>,\n}\n#[derive(Deserialize)]\nstruct TotalCrates {\n    total: u32,\n}\n#[derive(Deserialize)]\nstruct Crates {\n    crates: Vec<Crate>,\n    meta: TotalCrates,\n}\n\n/// Error returned when interacting with a registry.\n#[derive(Debug, thiserror::Error)]\npub enum Error {\n    /// Error from libcurl.\n    #[error(transparent)]\n    Curl(#[from] curl::Error),\n\n    /// Error from serializing the request payload and deserializing the\n    /// response body (like response body didn't match expected structure).\n    #[error(transparent)]\n    Json(#[from] serde_json::Error),\n\n    /// Error from IO. Mostly from reading the tarball to upload.\n    #[error(\"failed to seek tarball\")]\n    Io(#[from] std::io::Error),\n\n    /// Response body was not valid utf8.\n    #[error(\"invalid response body from server\")]\n    Utf8(#[from] std::string::FromUtf8Error),\n\n    /// Error from API response containing JSON field `errors.details`.\n    #[error(\n        \"the remote server responded with an error{}: {}\",\n        status(*code),\n        errors.join(\", \"),\n    )]\n    Api {\n        code: u32,\n        headers: Vec<String>,\n        errors: Vec<String>,\n    },\n\n    /// Error from API response which didn't have pre-programmed `errors.details`.\n    #[error(\n        \"failed to get a 200 OK response, got {code}\\nheaders:\\n\\t{}\\nbody:\\n{body}\",\n        headers.join(\"\\n\\t\"),\n    )]\n    Code {\n        code: u32,\n        headers: Vec<String>,\n        body: String,\n    },\n\n    /// Reason why the token was invalid.\n    #[error(\"{0}\")]\n    InvalidToken(&'static str),\n\n    /// Server was unavailable and timed out. Happened when uploading a way\n    /// too large tarball to crates.io.\n    #[error(\n        \"Request timed out after 30 seconds. If you're trying to \\\n         upload a crate it may be too large. If the crate is under \\\n         10MB in size, you can email help@crates.io for assistance.\\n\\\n         Total size was {0}.\"\n    )]\n    Timeout(u64),\n}\n\nimpl Registry {\n    /// Creates a new `Registry`.\n    ///\n    /// ## Example\n    ///\n    /// ```rust\n    /// use curl::easy::Easy;\n    /// use crates_io::Registry;\n    ///\n    /// let mut handle = Easy::new();\n    /// // If connecting to crates.io, a user-agent is required.\n    /// handle.useragent(\"my_crawler (example.com/info)\");\n    /// let mut reg = Registry::new_handle(String::from(\"https://crates.io\"), None, handle, true);\n    /// ```\n    pub fn new_handle(\n        host: String,\n        token: Option<String>,\n        handle: Easy,\n        auth_required: bool,\n    ) -> Registry {\n        Registry {\n            host,\n            token,\n            handle,\n            auth_required,\n        }\n    }\n\n    pub fn set_token(&mut self, token: Option<String>) {\n        self.token = token;\n    }\n\n    fn token(&self) -> Result<&str> {\n        let token = self.token.as_ref().ok_or_else(|| {\n            Error::InvalidToken(\"no upload token found, please run `cargo login`\")\n        })?;\n        check_token(token)?;\n        Ok(token)\n    }\n\n    pub fn host(&self) -> &str {\n        &self.host\n    }\n\n    pub fn host_is_crates_io(&self) -> bool {\n        is_url_crates_io(&self.host)\n    }\n\n    pub fn add_owners(&mut self, krate: &str, owners: &[&str]) -> Result<String> {\n        let body = serde_json::to_string(&OwnersReq { users: owners })?;\n        let body = self.put(&format!(\"/crates/{}/owners\", krate), body.as_bytes())?;\n        assert!(serde_json::from_str::<OwnerResponse>(&body)?.ok);\n        Ok(serde_json::from_str::<OwnerResponse>(&body)?.msg)\n    }\n\n    pub fn remove_owners(&mut self, krate: &str, owners: &[&str]) -> Result<()> {\n        let body = serde_json::to_string(&OwnersReq { users: owners })?;\n        let body = self.delete(&format!(\"/crates/{}/owners\", krate), Some(body.as_bytes()))?;\n        assert!(serde_json::from_str::<OwnerResponse>(&body)?.ok);\n        Ok(())\n    }\n\n    pub fn list_owners(&mut self, krate: &str) -> Result<Vec<User>> {\n        let body = self.get(&format!(\"/crates/{}/owners\", krate))?;\n        Ok(serde_json::from_str::<Users>(&body)?.users)\n    }\n\n    pub fn publish(&mut self, krate: &NewCrate, mut tarball: &File) -> Result<Warnings> {\n        let json = serde_json::to_string(krate)?;\n        // Prepare the body. The format of the upload request is:\n        //\n        //      <le u32 of json>\n        //      <json request> (metadata for the package)\n        //      <le u32 of tarball>\n        //      <source tarball>\n\n        // NOTE: This can be replaced with `stream_len` if it is ever stabilized.\n        //\n        // This checks the length using seeking instead of metadata, because\n        // on some filesystems, getting the metadata will fail because\n        // the file was renamed in ops::package.\n        let tarball_len = tarball.seek(SeekFrom::End(0))?;\n        tarball.seek(SeekFrom::Start(0))?;\n        let header = {\n            let mut w = Vec::new();\n            w.extend(&(json.len() as u32).to_le_bytes());\n            w.extend(json.as_bytes().iter().cloned());\n            w.extend(&(tarball_len as u32).to_le_bytes());\n            w\n        };\n        let size = tarball_len as usize + header.len();\n        let mut body = Cursor::new(header).chain(tarball);\n\n        let url = format!(\"{}/api/v1/crates/new\", self.host);\n\n        self.handle.put(true)?;\n        self.handle.url(&url)?;\n        self.handle.in_filesize(size as u64)?;\n        let mut headers = List::new();\n        headers.append(\"Accept: application/json\")?;\n        headers.append(&format!(\"Authorization: {}\", self.token()?))?;\n        self.handle.http_headers(headers)?;\n\n        let started = Instant::now();\n        let body = self\n            .handle(&mut |buf| body.read(buf).unwrap_or(0))\n            .map_err(|e| match e {\n                Error::Code { code, .. }\n                    if code == 503\n                        && started.elapsed().as_secs() >= 29\n                        && self.host_is_crates_io() =>\n                {\n                    Error::Timeout(tarball_len)\n                }\n                _ => e.into(),\n            })?;\n\n        let response = if body.is_empty() {\n            \"{}\".parse()?\n        } else {\n            body.parse::<serde_json::Value>()?\n        };\n\n        let invalid_categories: Vec<String> = response\n            .get(\"warnings\")\n            .and_then(|j| j.get(\"invalid_categories\"))\n            .and_then(|j| j.as_array())\n            .map(|x| x.iter().flat_map(|j| j.as_str()).map(Into::into).collect())\n            .unwrap_or_else(Vec::new);\n\n        let invalid_badges: Vec<String> = response\n            .get(\"warnings\")\n            .and_then(|j| j.get(\"invalid_badges\"))\n            .and_then(|j| j.as_array())\n            .map(|x| x.iter().flat_map(|j| j.as_str()).map(Into::into).collect())\n            .unwrap_or_else(Vec::new);\n\n        let other: Vec<String> = response\n            .get(\"warnings\")\n            .and_then(|j| j.get(\"other\"))\n            .and_then(|j| j.as_array())\n            .map(|x| x.iter().flat_map(|j| j.as_str()).map(Into::into).collect())\n            .unwrap_or_else(Vec::new);\n\n        Ok(Warnings {\n            invalid_categories,\n            invalid_badges,\n            other,\n        })\n    }\n\n    pub fn search(&mut self, query: &str, limit: u32) -> Result<(Vec<Crate>, u32)> {\n        let formatted_query = percent_encode(query.as_bytes(), NON_ALPHANUMERIC);\n        let body = self.req(\n            &format!(\"/crates?q={}&per_page={}\", formatted_query, limit),\n            None,\n            Auth::Unauthorized,\n        )?;\n\n        let crates = serde_json::from_str::<Crates>(&body)?;\n        Ok((crates.crates, crates.meta.total))\n    }\n\n    pub fn yank(&mut self, krate: &str, version: &str) -> Result<()> {\n        let body = self.delete(&format!(\"/crates/{}/{}/yank\", krate, version), None)?;\n        assert!(serde_json::from_str::<R>(&body)?.ok);\n        Ok(())\n    }\n\n    pub fn unyank(&mut self, krate: &str, version: &str) -> Result<()> {\n        let body = self.put(&format!(\"/crates/{}/{}/unyank\", krate, version), &[])?;\n        assert!(serde_json::from_str::<R>(&body)?.ok);\n        Ok(())\n    }\n\n    fn put(&mut self, path: &str, b: &[u8]) -> Result<String> {\n        self.handle.put(true)?;\n        self.req(path, Some(b), Auth::Authorized)\n    }\n\n    fn get(&mut self, path: &str) -> Result<String> {\n        self.handle.get(true)?;\n        self.req(path, None, Auth::Authorized)\n    }\n\n    fn delete(&mut self, path: &str, b: Option<&[u8]>) -> Result<String> {\n        self.handle.custom_request(\"DELETE\")?;\n        self.req(path, b, Auth::Authorized)\n    }\n\n    fn req(&mut self, path: &str, body: Option<&[u8]>, authorized: Auth) -> Result<String> {\n        self.handle.url(&format!(\"{}/api/v1{}\", self.host, path))?;\n        let mut headers = List::new();\n        headers.append(\"Accept: application/json\")?;\n        if body.is_some() {\n            headers.append(\"Content-Type: application/json\")?;\n        }\n\n        if self.auth_required || authorized == Auth::Authorized {\n            headers.append(&format!(\"Authorization: {}\", self.token()?))?;\n        }\n        self.handle.http_headers(headers)?;\n        match body {\n            Some(mut body) => {\n                self.handle.upload(true)?;\n                self.handle.in_filesize(body.len() as u64)?;\n                self.handle(&mut |buf| body.read(buf).unwrap_or(0))\n                    .map_err(|e| e.into())\n            }\n            None => self.handle(&mut |_| 0).map_err(|e| e.into()),\n        }\n    }\n\n    fn handle(&mut self, read: &mut dyn FnMut(&mut [u8]) -> usize) -> Result<String> {\n        let mut headers = Vec::new();\n        let mut body = Vec::new();\n        {\n            let mut handle = self.handle.transfer();\n            handle.read_function(|buf| Ok(read(buf)))?;\n            handle.write_function(|data| {\n                body.extend_from_slice(data);\n                Ok(data.len())\n            })?;\n            handle.header_function(|data| {\n                // Headers contain trailing \\r\\n, trim them to make it easier\n                // to work with.\n                let s = String::from_utf8_lossy(data).trim().to_string();\n                // Don't let server sneak extra lines anywhere.\n                if s.contains('\\n') {\n                    return true;\n                }\n                headers.push(s);\n                true\n            })?;\n            handle.perform()?;\n        }\n\n        let body = String::from_utf8(body)?;\n        let errors = serde_json::from_str::<ApiErrorList>(&body)\n            .ok()\n            .map(|s| s.errors.into_iter().map(|s| s.detail).collect::<Vec<_>>());\n\n        match (self.handle.response_code()?, errors) {\n            (0, None) => Ok(body),\n            (code, None) if is_success(code) => Ok(body),\n            (code, Some(errors)) => Err(Error::Api {\n                code,\n                headers,\n                errors,\n            }),\n            (code, None) => Err(Error::Code {\n                code,\n                headers,\n                body,\n            }),\n        }\n    }\n}\n\nfn is_success(code: u32) -> bool {\n    code >= 200 && code < 300\n}\n\nfn status(code: u32) -> String {\n    if is_success(code) {\n        String::new()\n    } else {\n        let reason = reason(code);\n        format!(\" (status {code} {reason})\")\n    }\n}\n\nfn reason(code: u32) -> &'static str {\n    // Taken from https://developer.mozilla.org/en-US/docs/Web/HTTP/Status\n    match code {\n        100 => \"Continue\",\n        101 => \"Switching Protocol\",\n        103 => \"Early Hints\",\n        200 => \"OK\",\n        201 => \"Created\",\n        202 => \"Accepted\",\n        203 => \"Non-Authoritative Information\",\n        204 => \"No Content\",\n        205 => \"Reset Content\",\n        206 => \"Partial Content\",\n        300 => \"Multiple Choice\",\n        301 => \"Moved Permanently\",\n        302 => \"Found\",\n        303 => \"See Other\",\n        304 => \"Not Modified\",\n        307 => \"Temporary Redirect\",\n        308 => \"Permanent Redirect\",\n        400 => \"Bad Request\",\n        401 => \"Unauthorized\",\n        402 => \"Payment Required\",\n        403 => \"Forbidden\",\n        404 => \"Not Found\",\n        405 => \"Method Not Allowed\",\n        406 => \"Not Acceptable\",\n        407 => \"Proxy Authentication Required\",\n        408 => \"Request Timeout\",\n        409 => \"Conflict\",\n        410 => \"Gone\",\n        411 => \"Length Required\",\n        412 => \"Precondition Failed\",\n        413 => \"Payload Too Large\",\n        414 => \"URI Too Long\",\n        415 => \"Unsupported Media Type\",\n        416 => \"Request Range Not Satisfiable\",\n        417 => \"Expectation Failed\",\n        429 => \"Too Many Requests\",\n        431 => \"Request Header Fields Too Large\",\n        500 => \"Internal Server Error\",\n        501 => \"Not Implemented\",\n        502 => \"Bad Gateway\",\n        503 => \"Service Unavailable\",\n        504 => \"Gateway Timeout\",\n        _ => \"<unknown>\",\n    }\n}\n\n/// Returns `true` if the host of the given URL is \"crates.io\".\npub fn is_url_crates_io(url: &str) -> bool {\n    Url::parse(url)\n        .map(|u| u.host_str() == Some(\"crates.io\"))\n        .unwrap_or(false)\n}\n\n/// Checks if a token is valid or malformed.\n///\n/// This check is necessary to prevent sending tokens which create an invalid HTTP request.\n/// It would be easier to check just for alphanumeric tokens, but we can't be sure that all\n/// registries only create tokens in that format so that is as less restricted as possible.\npub fn check_token(token: &str) -> Result<()> {\n    if token.is_empty() {\n        return Err(Error::InvalidToken(\"please provide a non-empty token\"));\n    }\n    if token.bytes().all(|b| {\n        // This is essentially the US-ASCII limitation of\n        // https://www.rfc-editor.org/rfc/rfc9110#name-field-values. That is,\n        // visible ASCII characters (0x21-0x7e), space, and tab. We want to be\n        // able to pass this in an HTTP header without encoding.\n        b >= 32 && b < 127 || b == b'\\t'\n    }) {\n        Ok(())\n    } else {\n        Err(Error::InvalidToken(\n            \"token contains invalid characters.\\nOnly printable ISO-8859-1 characters \\\n             are allowed as it is sent in a HTTPS header.\",\n        ))\n    }\n}\n"
  },
  {
    "path": "crates/home/CHANGELOG.md",
    "content": "# Changelog\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## 0.5.11 - 2024-12-16\n\nNote: 0.5.10 was not published.\n\n- Updated package metadata.\n  [#13184](https://github.com/rust-lang/cargo/pull/13184)\n- Updated minimum Rust version to 1.81.\n  [#13266](https://github.com/rust-lang/cargo/pull/13266)\n  [#13324](https://github.com/rust-lang/cargo/pull/13324)\n  [#14871](https://github.com/rust-lang/cargo/pull/14871)\n- Updated windows-sys to 0.59.\n  [#14335](https://github.com/rust-lang/cargo/pull/14335)\n- Clarified support level of this crate (not intended for external use).\n  [#14600](https://github.com/rust-lang/cargo/pull/14600)\n- Docs cleanup.\n  [#14823]()\n- Add notice that this crate should not be used, and to use the standard library's `home_dir` instead.\n  [#14939](https://github.com/rust-lang/cargo/pull/14939)\n\n## 0.5.9 - 2023-12-15\n\n- Replace SHGetFolderPathW with SHGetKnownFolderPath\n  [#13173](https://github.com/rust-lang/cargo/pull/13173)\n- Update windows-sys to 0.52\n  [#13089](https://github.com/rust-lang/cargo/pull/13089)\n- Set MSRV to 1.70.0\n  [#12654](https://github.com/rust-lang/cargo/pull/12654)\n- Fixed & enhanced documentation.\n  [#12047](https://github.com/rust-lang/cargo/pull/12047)\n\n## 0.5.5 - 2023-04-25\n- The `home` crate has migrated to the <https://github.com/rust-lang/cargo/> repository.\n  [#11359](https://github.com/rust-lang/cargo/pull/11359)\n- Replaced the winapi dependency with windows-sys.\n  [#11656](https://github.com/rust-lang/cargo/pull/11656)\n\n## [0.5.4] - 2022-10-10\n- Add `_with_env` variants of functions to support in-process threaded tests for\n  rustup.\n\n## [0.5.3] - 2020-01-07\n\nUse Rust 1.36.0 as minimum Rust version.\n\n## [0.5.2] - 2020-01-05\n\n*YANKED since it cannot be built on Rust 1.36.0*\n\n### Changed\n- Check for emptiness of `CARGO_HOME` and `RUSTUP_HOME` environment variables.\n- Windows: Use `SHGetFolderPath` to replace `GetUserProfileDirectory` syscall.\n  * Remove `scopeguard` dependency.\n\n## [0.5.1] - 2019-10-12\n### Changed\n- Disable unnecessary features for `scopeguard`. Thanks @mati865.\n\n## [0.5.0] - 2019-08-21\n### Added\n- Add `home_dir` implementation for Windows UWP platforms.\n\n### Fixed\n- Fix `rustup_home` implementation when `RUSTUP_HOME` is an absolute directory.\n- Fix `cargo_home` implementation when `CARGO_HOME` is an absolute directory.\n\n### Removed\n- Remove support for `multirust` folder used in old version of `rustup`.\n\n[0.5.4]: https://github.com/brson/home/compare/v0.5.3...v0.5.4\n[0.5.3]: https://github.com/brson/home/compare/v0.5.2...v0.5.3\n[0.5.2]: https://github.com/brson/home/compare/v0.5.1...v0.5.2\n[0.5.1]: https://github.com/brson/home/compare/v0.5.0...v0.5.1\n[0.5.0]: https://github.com/brson/home/compare/0.4.2...v0.5.0\n"
  },
  {
    "path": "crates/home/Cargo.toml",
    "content": "[package]\nname = \"home\"\nversion = \"0.5.13\"\nauthors = [\"Brian Anderson <andersrb@gmail.com>\"]\nrust-version.workspace = true\ndocumentation = \"https://docs.rs/home\"\nedition.workspace = true\ninclude = [\n    \"/src\",\n    \"/Cargo.toml\",\n    \"/CHANGELOG\",\n    \"/LICENSE-*\",\n    \"/README.md\",\n]\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"Shared definitions of home directories.\"\n\n[target.'cfg(windows)'.dependencies]\nwindows-sys = { workspace = true, features = [\"Win32_Foundation\", \"Win32_UI_Shell\", \"Win32_System_Com\"] }\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/home/README.md",
    "content": "[![Documentation](https://docs.rs/home/badge.svg)](https://docs.rs/home)\n[![crates.io](https://img.shields.io/crates/v/home.svg)](https://crates.io/crates/home)\n\nCanonical definitions of `home_dir`, `cargo_home`, and `rustup_home`.\n\nThis provides the definition of `home_dir` used by Cargo and rustup,\nas well functions to find the correct value of `CARGO_HOME` and\n`RUSTUP_HOME`.\n\nThe definition of [`home_dir`] provided by the standard library is\nincorrect because it considers the `HOME` environment variable on\nWindows. This causes surprising situations where a Rust program will\nbehave differently depending on whether it is run under a Unix\nemulation environment like Cygwin or MinGW. Neither Cargo nor rustup\nuse the standard library's definition - they use the definition here.\n\n**Note:** This has been fixed in Rust 1.85 to no longer use the `HOME`\nenvironment variable on Windows. If you are still using this crate for the\npurpose of getting a home directory, you are strongly encouraged to switch to\nusing the standard library's [`home_dir`] instead. It is planned to have the\ndeprecation notice removed in 1.87.\n\nThis crate further provides two functions, `cargo_home` and\n`rustup_home`, which are the canonical way to determine the location\nthat Cargo and rustup store their data.\n\nSee [rust-lang/rust#43321].\n\n> This crate is maintained by the Cargo team, primarily for use by Cargo and Rustup\n> and not intended for external use. This\n> crate may make major changes to its APIs or be deprecated without warning.\n\n[rust-lang/rust#43321]: https://github.com/rust-lang/rust/issues/43321\n[`home_dir`]: https://doc.rust-lang.org/nightly/std/env/fn.home_dir.html\n\n## License\n\nMIT OR Apache-2.0\n"
  },
  {
    "path": "crates/home/src/env.rs",
    "content": "//! Lower-level utilities for mocking the process environment.\n\nuse std::{\n    ffi::OsString,\n    io,\n    path::{Path, PathBuf},\n};\n\n/// Permits parameterizing the home functions via the _from variants - used for\n/// in-process unit testing by rustup.\npub trait Env {\n    /// Return the path to the users home dir, or None if any error occurs:\n    /// see `home_inner`.\n    fn home_dir(&self) -> Option<PathBuf>;\n    /// Return the current working directory.\n    fn current_dir(&self) -> io::Result<PathBuf>;\n    /// Get an environment variable, as per `std::env::var_os`.\n    fn var_os(&self, key: &str) -> Option<OsString>;\n}\n\n/// Implements Env for the OS context, both Unix style and Windows.\n///\n/// This is trait permits in-process testing by providing a control point to\n/// allow in-process divergence on what is normally process wide state.\n///\n/// Implementations should be provided by whatever testing framework the caller\n/// is using. Code that is not performing in-process threaded testing requiring\n/// isolated rustup/cargo directories does not need this trait or the _from\n/// functions.\npub struct OsEnv;\nimpl Env for OsEnv {\n    fn home_dir(&self) -> Option<PathBuf> {\n        crate::home_dir_inner()\n    }\n    fn current_dir(&self) -> io::Result<PathBuf> {\n        std::env::current_dir()\n    }\n    fn var_os(&self, key: &str) -> Option<OsString> {\n        std::env::var_os(key)\n    }\n}\n\npub const OS_ENV: OsEnv = OsEnv {};\n\n/// Returns the path of the current user's home directory from [`Env::home_dir`].\npub fn home_dir_with_env(env: &dyn Env) -> Option<PathBuf> {\n    env.home_dir()\n}\n\n/// Variant of `cargo_home` where the environment source is parameterized.\n///\n/// This is\n/// specifically to support in-process testing scenarios as environment\n/// variables and user home metadata are normally process global state. See the\n/// [`Env`] trait.\npub fn cargo_home_with_env(env: &dyn Env) -> io::Result<PathBuf> {\n    let cwd = env.current_dir()?;\n    cargo_home_with_cwd_env(env, &cwd)\n}\n\n/// Variant of `cargo_home_with_cwd` where the environment source is\n/// parameterized.\n///\n/// This is specifically to support in-process testing scenarios\n/// as environment variables and user home metadata are normally process global\n/// state. See the `OsEnv` trait.\npub fn cargo_home_with_cwd_env(env: &dyn Env, cwd: &Path) -> io::Result<PathBuf> {\n    match env.var_os(\"CARGO_HOME\").filter(|h| !h.is_empty()) {\n        Some(home) => {\n            let home = PathBuf::from(home);\n            if home.is_absolute() {\n                Ok(home)\n            } else {\n                Ok(cwd.join(&home))\n            }\n        }\n        _ => home_dir_with_env(env)\n            .map(|p| p.join(\".cargo\"))\n            .ok_or_else(|| io::Error::new(io::ErrorKind::Other, \"could not find cargo home dir\")),\n    }\n}\n\n/// Variant of `cargo_home_with_cwd` where the environment source is\n/// parameterized.\n///\n/// This is specifically to support in-process testing scenarios\n/// as environment variables and user home metadata are normally process global\n/// state. See the `OsEnv` trait.\npub fn rustup_home_with_env(env: &dyn Env) -> io::Result<PathBuf> {\n    let cwd = env.current_dir()?;\n    rustup_home_with_cwd_env(env, &cwd)\n}\n\n/// Variant of `cargo_home_with_cwd` where the environment source is\n/// parameterized.\n///\n/// This is specifically to support in-process testing scenarios\n/// as environment variables and user home metadata are normally process global\n/// state. See the `OsEnv` trait.\npub fn rustup_home_with_cwd_env(env: &dyn Env, cwd: &Path) -> io::Result<PathBuf> {\n    match env.var_os(\"RUSTUP_HOME\").filter(|h| !h.is_empty()) {\n        Some(home) => {\n            let home = PathBuf::from(home);\n            if home.is_absolute() {\n                Ok(home)\n            } else {\n                Ok(cwd.join(&home))\n            }\n        }\n        _ => home_dir_with_env(env)\n            .map(|d| d.join(\".rustup\"))\n            .ok_or_else(|| io::Error::new(io::ErrorKind::Other, \"could not find rustup home dir\")),\n    }\n}\n"
  },
  {
    "path": "crates/home/src/lib.rs",
    "content": "//! Canonical definitions of `home_dir`, `cargo_home`, and `rustup_home`.\n//!\n//! The definition of `home_dir` provided by the standard library is\n//! incorrect because it considers the `HOME` environment variable on\n//! Windows. This causes surprising situations where a Rust program\n//! will behave differently depending on whether it is run under a\n//! Unix emulation environment like Cygwin or MinGW. Neither Cargo nor\n//! rustup use the standard libraries definition - they use the\n//! definition here.\n//!\n//! This crate provides two additional functions, `cargo_home` and\n//! `rustup_home`, which are the canonical way to determine the\n//! location that Cargo and rustup use to store their data.\n//! The `env` module contains utilities for mocking the process environment\n//! by Cargo and rustup.\n//!\n//! See also this [discussion].\n//!\n//! > This crate is maintained by the Cargo team, primarily for use by Cargo and Rustup\n//! > and not intended for external use. This\n//! > crate may make major changes to its APIs or be deprecated without warning.\n//!\n//! [discussion]: https://github.com/rust-lang/rust/pull/46799#issuecomment-361156935\n\n#![allow(clippy::disallowed_methods)]\n\npub mod env;\n\n#[cfg(target_os = \"windows\")]\nmod windows;\n\nuse std::io;\nuse std::path::{Path, PathBuf};\n\n/// Returns the path of the current user's home directory using environment\n/// variables or OS-specific APIs.\n///\n/// # Unix\n///\n/// Returns the value of the `HOME` environment variable if it is set\n/// **even** if it is an empty string. Otherwise, it tries to determine the\n/// home directory by invoking the [`getpwuid_r`][getpwuid] function with\n/// the UID of the current user.\n///\n/// [getpwuid]: https://linux.die.net/man/3/getpwuid_r\n///\n/// # Windows\n///\n/// Returns the value of the `USERPROFILE` environment variable if it is set\n/// **and** it is not an empty string. Otherwise, it tries to determine the\n/// home directory by invoking the [`SHGetKnownFolderPath`][shgkfp] function with\n/// [`FOLDERID_Profile`][knownfolderid].\n///\n/// [shgkfp]: https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath\n/// [knownfolderid]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid\n///\n/// # Examples\n///\n/// ```\n/// match home::home_dir() {\n///     Some(path) if !path.as_os_str().is_empty() => println!(\"{}\", path.display()),\n///     _ => println!(\"Unable to get your home dir!\"),\n/// }\n/// ```\npub fn home_dir() -> Option<PathBuf> {\n    env::home_dir_with_env(&env::OS_ENV)\n}\n\n#[cfg(windows)]\nuse windows::home_dir_inner;\n\n#[cfg(unix)]\nfn home_dir_inner() -> Option<PathBuf> {\n    #[allow(deprecated)]\n    std::env::home_dir()\n}\n\n/// Returns the storage directory used by Cargo, often known as\n/// `.cargo` or `CARGO_HOME`.\n///\n/// It returns one of the following values, in this order of\n/// preference:\n///\n/// - The value of the `CARGO_HOME` environment variable, if it is\n///   an absolute path.\n/// - The value of the current working directory joined with the value\n///   of the `CARGO_HOME` environment variable, if `CARGO_HOME` is a\n///   relative directory.\n/// - The `.cargo` directory in the user's home directory, as reported\n///   by the `home_dir` function.\n///\n/// # Errors\n///\n/// This function fails if it fails to retrieve the current directory,\n/// or if the home directory cannot be determined.\n///\n/// # Examples\n///\n/// ```\n/// match home::cargo_home() {\n///     Ok(path) => println!(\"{}\", path.display()),\n///     Err(err) => eprintln!(\"Cannot get your cargo home dir: {:?}\", err),\n/// }\n/// ```\npub fn cargo_home() -> io::Result<PathBuf> {\n    env::cargo_home_with_env(&env::OS_ENV)\n}\n\n/// Returns the storage directory used by Cargo within `cwd`.\n/// For more details, see [`cargo_home`](fn.cargo_home.html).\npub fn cargo_home_with_cwd(cwd: &Path) -> io::Result<PathBuf> {\n    env::cargo_home_with_cwd_env(&env::OS_ENV, cwd)\n}\n\n/// Returns the storage directory used by rustup, often known as\n/// `.rustup` or `RUSTUP_HOME`.\n///\n/// It returns one of the following values, in this order of\n/// preference:\n///\n/// - The value of the `RUSTUP_HOME` environment variable, if it is\n///   an absolute path.\n/// - The value of the current working directory joined with the value\n///   of the `RUSTUP_HOME` environment variable, if `RUSTUP_HOME` is a\n///   relative directory.\n/// - The `.rustup` directory in the user's home directory, as reported\n///   by the `home_dir` function.\n///\n/// # Errors\n///\n/// This function fails if it fails to retrieve the current directory,\n/// or if the home directory cannot be determined.\n///\n/// # Examples\n///\n/// ```\n/// match home::rustup_home() {\n///     Ok(path) => println!(\"{}\", path.display()),\n///     Err(err) => eprintln!(\"Cannot get your rustup home dir: {:?}\", err),\n/// }\n/// ```\npub fn rustup_home() -> io::Result<PathBuf> {\n    env::rustup_home_with_env(&env::OS_ENV)\n}\n\n/// Returns the storage directory used by rustup within `cwd`.\n/// For more details, see [`rustup_home`](fn.rustup_home.html).\npub fn rustup_home_with_cwd(cwd: &Path) -> io::Result<PathBuf> {\n    env::rustup_home_with_cwd_env(&env::OS_ENV, cwd)\n}\n"
  },
  {
    "path": "crates/home/src/windows.rs",
    "content": "use std::env;\nuse std::ffi::OsString;\nuse std::os::windows::ffi::OsStringExt;\nuse std::path::PathBuf;\nuse std::ptr;\nuse std::slice;\n\nuse windows_sys::Win32::Foundation::S_OK;\nuse windows_sys::Win32::System::Com::CoTaskMemFree;\nuse windows_sys::Win32::UI::Shell::{FOLDERID_Profile, KF_FLAG_DONT_VERIFY, SHGetKnownFolderPath};\n\npub fn home_dir_inner() -> Option<PathBuf> {\n    env::var_os(\"USERPROFILE\")\n        .filter(|s| !s.is_empty())\n        .map(PathBuf::from)\n        .or_else(home_dir_crt)\n}\n\n#[cfg(not(target_vendor = \"uwp\"))]\nfn home_dir_crt() -> Option<PathBuf> {\n    unsafe {\n        let mut path = ptr::null_mut();\n        match SHGetKnownFolderPath(\n            &FOLDERID_Profile,\n            KF_FLAG_DONT_VERIFY as u32,\n            std::ptr::null_mut(),\n            &mut path,\n        ) {\n            S_OK => {\n                let path_slice = slice::from_raw_parts(path, wcslen(path));\n                let s = OsString::from_wide(&path_slice);\n                CoTaskMemFree(path.cast());\n                Some(PathBuf::from(s))\n            }\n            _ => {\n                // Free any allocated memory even on failure. A null ptr is a no-op for `CoTaskMemFree`.\n                CoTaskMemFree(path.cast());\n                None\n            }\n        }\n    }\n}\n\n#[cfg(target_vendor = \"uwp\")]\nfn home_dir_crt() -> Option<PathBuf> {\n    None\n}\n\nunsafe extern \"C\" {\n    fn wcslen(buf: *const u16) -> usize;\n}\n\n#[cfg(not(target_vendor = \"uwp\"))]\n#[cfg(test)]\nmod tests {\n    use super::home_dir_inner;\n    use std::env;\n    use std::ops::Deref;\n    use std::path::{Path, PathBuf};\n\n    #[test]\n    fn test_with_without() {\n        let olduserprofile = env::var_os(\"USERPROFILE\").unwrap();\n\n        unsafe {\n            env::remove_var(\"HOME\");\n            env::remove_var(\"USERPROFILE\");\n        }\n\n        assert_eq!(home_dir_inner(), Some(PathBuf::from(olduserprofile)));\n\n        let home = Path::new(r\"C:\\Users\\foo tar baz\");\n\n        unsafe {\n            env::set_var(\"HOME\", home.as_os_str());\n        }\n        assert_ne!(home_dir_inner().as_ref().map(Deref::deref), Some(home));\n\n        unsafe {\n            env::set_var(\"USERPROFILE\", home.as_os_str());\n        }\n        assert_eq!(home_dir_inner().as_ref().map(Deref::deref), Some(home));\n    }\n}\n"
  },
  {
    "path": "crates/mdman/Cargo.toml",
    "content": "[package]\nname = \"mdman\"\nversion = \"0.0.0\"\nedition.workspace = true\nlicense.workspace = true\ndescription = \"Creates a man page from markdown.\"\npublish = false\n\n[dependencies]\nanyhow.workspace = true\nhandlebars.workspace = true\npulldown-cmark.workspace = true\nsame-file.workspace = true\nserde_json.workspace = true\nurl.workspace = true\n\n[dev-dependencies]\nsnapbox.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/mdman/README.md",
    "content": "# mdman\n\nmdman is a small utility for creating man pages from markdown text files.\n\n> This crate is maintained by the Cargo team, primarily for use by Cargo\n> and not intended for external use (except as a transitive dependency). This\n> crate may make major changes to its APIs or be deprecated without warning.\n\n## Usage\n\nSee the [man page](doc/out/mdman.md) generated by this tool.\n"
  },
  {
    "path": "crates/mdman/doc/mdman.md",
    "content": "# mdman(1)\n\n## NAME\n\nmdman - Converts markdown to a man page\n\n## SYNOPSIS\n\n`mdman` [_options_] `-t` _type_ `-o` _outdir_ _sources..._\n\n## DESCRIPTION\n\nConverts a markdown file to a man page.\n\nThe source file is first processed as a\n[handlebars](https://handlebarsjs.com/) template. Then, it is processed as\nmarkdown into the target format. This supports different output formats,\nsuch as troff or plain text.\n\nEvery man page should start with a level-1 header with the man name and\nsection, such as `# mdman(1)`.\n\nThe handlebars template has several special tags to assist with generating the\nman page:\n\n{{{{raw}}}}\n- Every block of command-line options must be wrapped between `{{#options}}`\n  and `{{/options}}` tags. This tells the processor where the options start\n  and end.\n- Each option must be expressed with a `{{#option}}` block. The parameters to\n  the block are a sequence of strings indicating the option. For example,\n  ```{{#option \"`-p` _spec_...\" \"`--package` _spec_...\"}}``` is an option that\n  has two different forms. The text within the string is processed as markdown.\n  It is recommended to use formatting similar to this example.\n\n  The content of the `{{#option}}` block should contain a detailed description\n  of the option.\n\n  Use the `{{/option}}` tag to end the option block.\n- References to other man pages should use the `{{man name section}}`\n  expression. For example, `{{man \"mdman\" 1}}` will generate a reference to\n  the `mdman(1)` man page. For non-troff output, the `--man` option will tell\n  `mdman` how to create links to the man page. If there is no matching `--man`\n  option, then it links to a file named _name_`.md` in the same directory.\n- Variables can be set with `{{*set name=\"value\"}}`. These variables can\n  then be referenced with `{{name}}` expressions.\n- Partial templates should be placed in a directory named `includes`\n  next to the source file. Templates can be included with an expression like\n  `{{> template-name}}`.\n- Other helpers include:\n    - `{{lower value}}` Converts the given value to lowercase.\n{{{{/raw}}}}\n\n## OPTIONS\n\n{{#options}}\n\n{{#option \"`-t` _type_\"}}\nSpecifies the output type. The following output types are supported:\n- `man` — A troff-style man page. Outputs with a numbered extension (like\n  `.1`) matching the man page section.\n- `md` — A markdown file, after all handlebars processing has been finished.\n  Outputs with the `.md` extension.\n- `txt` — A text file, rendered for situations where a man page viewer isn't\n  available. Outputs with the `.txt` extension.\n{{/option}}\n\n{{#option \"`-o` _outdir_\"}}\nSpecifies the directory where to save the output.\n{{/option}}\n\n{{#option \"`--url` _base_url_\"}}\nSpecifies a base URL to use for relative URLs within the document. Any\nrelative URL will be joined with this URL.\n{{/option}}\n\n{{#option \"`--man` _name_`:`_section_`=`_url_\"}}\nSpecifies a URL to use for the given man page. When the `\\{{man name\nsection}}` expression is used, the given URL will be inserted as a link. This\nmay be specified multiple times. If a man page reference does not have a\nmatching `--man` entry, then a relative link to a file named _name_`.md` will\nbe used.\n{{/option}}\n\n{{#option \"_sources..._\"}}\nThe source input filename, may be specified multiple times.\n{{/option}}\n\n{{/options}}\n\n## EXAMPLES\n\n1. Convert the given documents to man pages:\n\n       mdman -t man -o doc doc/mdman.md\n"
  },
  {
    "path": "crates/mdman/doc/out/mdman.1",
    "content": "'\\\" t\n.TH \"MDMAN\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\nmdman \\- Converts markdown to a man page\n.SH \"SYNOPSIS\"\n\\fBmdman\\fR [\\fIoptions\\fR] \\fB\\-t\\fR \\fItype\\fR \\fB\\-o\\fR \\fIoutdir\\fR \\fIsources\\[u2026]\\fR\n.SH \"DESCRIPTION\"\nConverts a markdown file to a man page.\n.sp\nThe source file is first processed as a\n\\fIhandlebars\\fR <https://handlebarsjs.com/> template. Then, it is processed as\nmarkdown into the target format. This supports different output formats,\nsuch as troff or plain text.\n.sp\nEvery man page should start with a level\\-1 header with the man name and\nsection, such as \\fB# mdman(1)\\fR\\&.\n.sp\nThe handlebars template has several special tags to assist with generating the\nman page:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Every block of command\\-line options must be wrapped between \\fB{{#options}}\\fR\nand \\fB{{/options}}\\fR tags. This tells the processor where the options start\nand end.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Each option must be expressed with a \\fB{{#option}}\\fR block. The parameters to\nthe block are a sequence of strings indicating the option. For example,\n\\fB{{#option \"`\\-p` _spec_...\" \"`\\-\\-package` _spec_...\"}}\\fR is an option that\nhas two different forms. The text within the string is processed as markdown.\nIt is recommended to use formatting similar to this example.\n.sp\nThe content of the \\fB{{#option}}\\fR block should contain a detailed description\nof the option.\n.sp\nUse the \\fB{{/option}}\\fR tag to end the option block.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'References to other man pages should use the \\fB{{man name section}}\\fR\nexpression. For example, \\fB{{man \"mdman\" 1}}\\fR will generate a reference to\nthe \\fBmdman(1)\\fR man page. For non\\-troff output, the \\fB\\-\\-man\\fR option will tell\n\\fBmdman\\fR how to create links to the man page. If there is no matching \\fB\\-\\-man\\fR\noption, then it links to a file named \\fIname\\fR\\fB\\&.md\\fR in the same directory.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Variables can be set with \\fB{{*set name=\"value\"}}\\fR\\&. These variables can\nthen be referenced with \\fB{{name}}\\fR expressions.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Partial templates should be placed in a directory named \\fBincludes\\fR\nnext to the source file. Templates can be included with an expression like\n\\fB{{> template\\-name}}\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Other helpers include:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB{{lower value}}\\fR Converts the given value to lowercase.\n.RE\n.RE\n.SH \"OPTIONS\"\n.sp\n\\fB\\-t\\fR \\fItype\\fR\n.RS 4\nSpecifies the output type. The following output types are supported:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBman\\fR \\[em] A troff\\-style man page. Outputs with a numbered extension (like\n\\fB\\&.1\\fR) matching the man page section.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBmd\\fR \\[em] A markdown file, after all handlebars processing has been finished.\nOutputs with the \\fB\\&.md\\fR extension.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBtxt\\fR \\[em] A text file, rendered for situations where a man page viewer isn\\[cq]t\navailable. Outputs with the \\fB\\&.txt\\fR extension.\n.RE\n.RE\n.sp\n\\fB\\-o\\fR \\fIoutdir\\fR\n.RS 4\nSpecifies the directory where to save the output.\n.RE\n.sp\n\\fB\\-\\-url\\fR \\fIbase_url\\fR\n.RS 4\nSpecifies a base URL to use for relative URLs within the document. Any\nrelative URL will be joined with this URL.\n.RE\n.sp\n\\fB\\-\\-man\\fR \\fIname\\fR\\fB:\\fR\\fIsection\\fR\\fB=\\fR\\fIurl\\fR\n.RS 4\nSpecifies a URL to use for the given man page. When the \\fB{{man name section}}\\fR expression is used, the given URL will be inserted as a link. This\nmay be specified multiple times. If a man page reference does not have a\nmatching \\fB\\-\\-man\\fR entry, then a relative link to a file named \\fIname\\fR\\fB\\&.md\\fR will\nbe used.\n.RE\n.sp\n\\fIsources\\[u2026]\\fR\n.RS 4\nThe source input filename, may be specified multiple times.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Convert the given documents to man pages:\n.sp\n.RS 4\n.nf\nmdman \\-t man \\-o doc doc/mdman.md\n.fi\n.RE\n.RE\n"
  },
  {
    "path": "crates/mdman/doc/out/mdman.md",
    "content": "# mdman(1)\n\n## NAME\n\nmdman - Converts markdown to a man page\n\n## SYNOPSIS\n\n`mdman` [_options_] `-t` _type_ `-o` _outdir_ _sources..._\n\n## DESCRIPTION\n\nConverts a markdown file to a man page.\n\nThe source file is first processed as a\n[handlebars](https://handlebarsjs.com/) template. Then, it is processed as\nmarkdown into the target format. This supports different output formats,\nsuch as troff or plain text.\n\nEvery man page should start with a level-1 header with the man name and\nsection, such as `# mdman(1)`.\n\nThe handlebars template has several special tags to assist with generating the\nman page:\n\n- Every block of command-line options must be wrapped between `{{#options}}`\n  and `{{/options}}` tags. This tells the processor where the options start\n  and end.\n- Each option must be expressed with a `{{#option}}` block. The parameters to\n  the block are a sequence of strings indicating the option. For example,\n  ```{{#option \"`-p` _spec_...\" \"`--package` _spec_...\"}}``` is an option that\n  has two different forms. The text within the string is processed as markdown.\n  It is recommended to use formatting similar to this example.\n\n  The content of the `{{#option}}` block should contain a detailed description\n  of the option.\n\n  Use the `{{/option}}` tag to end the option block.\n- References to other man pages should use the `{{man name section}}`\n  expression. For example, `{{man \"mdman\" 1}}` will generate a reference to\n  the `mdman(1)` man page. For non-troff output, the `--man` option will tell\n  `mdman` how to create links to the man page. If there is no matching `--man`\n  option, then it links to a file named _name_`.md` in the same directory.\n- Variables can be set with `{{*set name=\"value\"}}`. These variables can\n  then be referenced with `{{name}}` expressions.\n- Partial templates should be placed in a directory named `includes`\n  next to the source file. Templates can be included with an expression like\n  `{{> template-name}}`.\n- Other helpers include:\n    - `{{lower value}}` Converts the given value to lowercase.\n\n## OPTIONS\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-mdman--t\"><a class=\"option-anchor\" href=\"#option-mdman--t\"><code>-t</code> <em>type</em></a></dt>\n<dd class=\"option-desc\"><p>Specifies the output type. The following output types are supported:</p>\n<ul>\n<li><code>man</code> — A troff-style man page. Outputs with a numbered extension (like\n<code>.1</code>) matching the man page section.</li>\n<li><code>md</code> — A markdown file, after all handlebars processing has been finished.\nOutputs with the <code>.md</code> extension.</li>\n<li><code>txt</code> — A text file, rendered for situations where a man page viewer isn’t\navailable. Outputs with the <code>.txt</code> extension.</li>\n</ul>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-mdman--o\"><a class=\"option-anchor\" href=\"#option-mdman--o\"><code>-o</code> <em>outdir</em></a></dt>\n<dd class=\"option-desc\"><p>Specifies the directory where to save the output.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-mdman---url\"><a class=\"option-anchor\" href=\"#option-mdman---url\"><code>--url</code> <em>base_url</em></a></dt>\n<dd class=\"option-desc\"><p>Specifies a base URL to use for relative URLs within the document. Any\nrelative URL will be joined with this URL.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-mdman---man\"><a class=\"option-anchor\" href=\"#option-mdman---man\"><code>--man</code> <em>name</em><code>:</code><em>section</em><code>=</code><em>url</em></a></dt>\n<dd class=\"option-desc\"><p>Specifies a URL to use for the given man page. When the <code>{{man name section}}</code> expression is used, the given URL will be inserted as a link. This\nmay be specified multiple times. If a man page reference does not have a\nmatching <code>--man</code> entry, then a relative link to a file named <em>name</em><code>.md</code> will\nbe used.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-mdman-sources…\"><a class=\"option-anchor\" href=\"#option-mdman-sources…\"><em>sources…</em></a></dt>\n<dd class=\"option-desc\"><p>The source input filename, may be specified multiple times.</p>\n</dd>\n\n\n</dl>\n\n## EXAMPLES\n\n1. Convert the given documents to man pages:\n\n       mdman -t man -o doc doc/mdman.md\n"
  },
  {
    "path": "crates/mdman/doc/out/mdman.txt",
    "content": "MDMAN(1)\n\nNAME\n       mdman - Converts markdown to a man page\n\nSYNOPSIS\n       mdman [options] -t type -o outdir sources…\n\nDESCRIPTION\n       Converts a markdown file to a man page.\n\n       The source file is first processed as a handlebars\n       <https://handlebarsjs.com/> template. Then, it is processed as markdown\n       into the target format. This supports different output formats, such as\n       troff or plain text.\n\n       Every man page should start with a level-1 header with the man name and\n       section, such as # mdman(1).\n\n       The handlebars template has several special tags to assist with\n       generating the man page:\n\n       o  Every block of command-line options must be wrapped between\n          {{#options}} and {{/options}} tags. This tells the processor where\n          the options start and end.\n\n       o  Each option must be expressed with a {{#option}} block. The\n          parameters to the block are a sequence of strings indicating the\n          option. For example, {{#option \"`-p` _spec_...\" \"`--package`\n          _spec_...\"}} is an option that has two different forms. The text\n          within the string is processed as markdown. It is recommended to use\n          formatting similar to this example.\n\n          The content of the {{#option}} block should contain a detailed\n          description of the option.\n\n          Use the {{/option}} tag to end the option block.\n\n       o  References to other man pages should use the {{man name section}}\n          expression. For example, {{man \"mdman\" 1}} will generate a reference\n          to the mdman(1) man page. For non-troff output, the --man option will\n          tell mdman how to create links to the man page. If there is no\n          matching --man option, then it links to a file named name.md in the\n          same directory.\n\n       o  Variables can be set with {{*set name=\"value\"}}. These variables can\n          then be referenced with {{name}} expressions.\n\n       o  Partial templates should be placed in a directory named includes next\n          to the source file. Templates can be included with an expression like\n          {{> template-name}}.\n\n       o  Other helpers include:\n\n          o  {{lower value}} Converts the given value to lowercase.\n\nOPTIONS\n       -t type\n           Specifies the output type. The following output types are supported:\n\n           o  man — A troff-style man page. Outputs with a numbered extension\n              (like .1) matching the man page section.\n\n           o  md — A markdown file, after all handlebars processing has been\n              finished. Outputs with the .md extension.\n\n           o  txt — A text file, rendered for situations where a man page\n              viewer isn’t available. Outputs with the .txt extension.\n\n       -o outdir\n           Specifies the directory where to save the output.\n\n       --url base_url\n           Specifies a base URL to use for relative URLs within the document.\n           Any relative URL will be joined with this URL.\n\n       --man name:section=url\n           Specifies a URL to use for the given man page. When the {{man name\n           section}} expression is used, the given URL will be inserted as a\n           link. This may be specified multiple times. If a man page reference\n           does not have a matching --man entry, then a relative link to a file\n           named name.md will be used.\n\n       sources…\n           The source input filename, may be specified multiple times.\n\nEXAMPLES\n       1. Convert the given documents to man pages:\n\n              mdman -t man -o doc doc/mdman.md\n\n"
  },
  {
    "path": "crates/mdman/src/format/man.rs",
    "content": "//! Man-page formatter.\n\nuse crate::EventIter;\nuse crate::util::{header_text, parse_name_and_section};\nuse anyhow::{Error, bail};\nuse pulldown_cmark::{Alignment, Event, HeadingLevel, LinkType, Tag, TagEnd};\nuse std::fmt::Write;\nuse url::Url;\n\npub struct ManFormatter {\n    url: Option<Url>,\n}\n\nimpl ManFormatter {\n    pub fn new(url: Option<Url>) -> ManFormatter {\n        ManFormatter { url }\n    }\n}\n\nimpl super::Formatter for ManFormatter {\n    fn render(&self, input: &str) -> Result<String, Error> {\n        ManRenderer::render(input, self.url.clone())\n    }\n\n    fn render_options_start(&self) -> &'static str {\n        // Tell pulldown_cmark to ignore this.\n        // This will be stripped out later.\n        \"<![CDATA[\"\n    }\n\n    fn render_options_end(&self) -> &'static str {\n        \"]]>\"\n    }\n\n    fn render_option(\n        &self,\n        params: &[&str],\n        block: &str,\n        _man_name: &str,\n    ) -> Result<String, Error> {\n        let rendered_options = params\n            .iter()\n            .map(|param| {\n                let r = self.render(param)?;\n                Ok(r.trim().trim_start_matches(\".sp\").to_string())\n            })\n            .collect::<Result<Vec<_>, Error>>()?;\n        let rendered_block = self.render(block)?;\n        let rendered_block = rendered_block.trim().trim_start_matches(\".sp\").trim();\n        // .RS = move left margin to right 4.\n        // .RE = move margin back one level.\n        Ok(format!(\n            \"\\n.sp\\n{}\\n.RS 4\\n{}\\n.RE\\n\",\n            rendered_options.join(\", \"),\n            rendered_block\n        ))\n    }\n\n    fn linkify_man_to_md(&self, name: &str, section: u8) -> Result<String, Error> {\n        Ok(format!(\"`{}`({})\", name, section))\n    }\n}\n\n#[derive(Copy, Clone)]\nenum Font {\n    Bold,\n    Italic,\n}\n\nimpl Font {\n    fn str_from_stack(font_stack: &[Font]) -> &'static str {\n        let has_bold = font_stack.iter().any(|font| matches!(font, Font::Bold));\n        let has_italic = font_stack.iter().any(|font| matches!(font, Font::Italic));\n        match (has_bold, has_italic) {\n            (false, false) => \"\\\\fR\", // roman (normal)\n            (false, true) => \"\\\\fI\",  // italic\n            (true, false) => \"\\\\fB\",  // bold\n            (true, true) => \"\\\\f(BI\", // bold italic\n        }\n    }\n}\n\nstruct ManRenderer<'e> {\n    output: String,\n    parser: EventIter<'e>,\n    font_stack: Vec<Font>,\n}\n\nimpl<'e> ManRenderer<'e> {\n    fn render(input: &str, url: Option<Url>) -> Result<String, Error> {\n        let parser = crate::md_parser(input, url);\n        let output = String::with_capacity(input.len() * 3 / 2);\n        let mut mr = ManRenderer {\n            parser,\n            output,\n            font_stack: Vec::new(),\n        };\n        mr.push_man()?;\n        Ok(mr.output)\n    }\n\n    fn push_man(&mut self) -> Result<(), Error> {\n        // If this is true, this is inside a cdata block used for hiding\n        // content from pulldown_cmark.\n        let mut in_cdata = false;\n        // The current list stack. None if unordered, Some if ordered with the\n        // given number as the current index.\n        let mut list: Vec<Option<u64>> = Vec::new();\n        // Used in some cases where spacing isn't desired.\n        let mut suppress_paragraph = false;\n        let mut table_cell_index = 0;\n\n        let mut last_seen_link_data = None;\n        while let Some((event, range)) = self.parser.next() {\n            let this_suppress_paragraph = suppress_paragraph;\n            suppress_paragraph = false;\n            match event {\n                Event::Start(tag) => {\n                    match tag {\n                        Tag::Paragraph => {\n                            if !this_suppress_paragraph {\n                                self.flush();\n                                self.output.push_str(\".sp\\n\");\n                            }\n                        }\n                        Tag::Heading { level, .. } => {\n                            if level == HeadingLevel::H1 {\n                                self.push_top_header()?;\n                            } else if level == HeadingLevel::H2 {\n                                // Section header\n                                let text = header_text(&mut self.parser)?;\n                                self.flush();\n                                write!(self.output, \".SH \\\"{}\\\"\\n\", text)?;\n                                suppress_paragraph = true;\n                            } else {\n                                // Subsection header\n                                let text = header_text(&mut self.parser)?;\n                                self.flush();\n                                write!(self.output, \".SS \\\"{}\\\"\\n\", text)?;\n                                suppress_paragraph = true;\n                            }\n                        }\n                        Tag::BlockQuote(..) => {\n                            self.flush();\n                            // .RS = move left margin over 3\n                            // .ll = shrink line length\n                            self.output.push_str(\".RS 3\\n.ll -5\\n.sp\\n\");\n                            suppress_paragraph = true;\n                        }\n                        Tag::CodeBlock(_kind) => {\n                            // space down, indent 4, no-fill mode\n                            self.flush();\n                            self.output.push_str(\".sp\\n.RS 4\\n.nf\\n\");\n                        }\n                        Tag::List(start) => list.push(start),\n                        Tag::Item => {\n                            // Note: This uses explicit movement instead of .IP\n                            // because the spacing on .IP looks weird to me.\n                            // space down, indent 4\n                            self.flush();\n                            self.output.push_str(\".sp\\n.RS 4\\n\");\n                            match list.last_mut().expect(\"item must have list start\") {\n                                // Ordered list.\n                                Some(n) => {\n                                    // move left 4, output the list index number, move right 1.\n                                    write!(self.output, \"\\\\h'-04' {}.\\\\h'+01'\", n)?;\n                                    *n += 1;\n                                }\n                                // Unordered list.\n                                None => self.output.push_str(\"\\\\h'-04'\\\\(bu\\\\h'+03'\"),\n                            }\n                            suppress_paragraph = true;\n                        }\n                        Tag::FootnoteDefinition(_label) => unimplemented!(),\n                        Tag::Table(alignment) => {\n                            // Table start\n                            // allbox = draw a box around all the cells\n                            // tab(:) = Use `:` to separate cell data (instead of tab)\n                            // ; = end of options\n                            self.output.push_str(\n                                \"\\n.TS\\n\\\n                                allbox tab(:);\\n\",\n                            );\n                            let alignments: Vec<_> = alignment\n                                .iter()\n                                .map(|a| match a {\n                                    Alignment::Left | Alignment::None => \"lt\",\n                                    Alignment::Center => \"ct\",\n                                    Alignment::Right => \"rt\",\n                                })\n                                .collect();\n                            self.output.push_str(&alignments.join(\" \"));\n                            self.output.push_str(\".\\n\");\n                            table_cell_index = 0;\n                        }\n                        Tag::TableHead => {\n                            table_cell_index = 0;\n                        }\n                        Tag::TableRow => {\n                            table_cell_index = 0;\n                            self.output.push('\\n');\n                        }\n                        Tag::TableCell => {\n                            if table_cell_index != 0 {\n                                // Separator between columns.\n                                self.output.push(':');\n                            }\n                            // Start a text block.\n                            self.output.push_str(\"T{\\n\");\n                            table_cell_index += 1\n                        }\n                        Tag::Emphasis => self.push_font(Font::Italic),\n                        Tag::Strong => self.push_font(Font::Bold),\n                        // Strikethrough isn't usually supported for TTY.\n                        Tag::Strikethrough => self.output.push_str(\"~~\"),\n                        Tag::Link {\n                            link_type,\n                            dest_url,\n                            ..\n                        } => {\n                            last_seen_link_data = Some((link_type.clone(), dest_url.to_owned()));\n                            if dest_url.starts_with('#') {\n                                // In a man page, page-relative anchors don't\n                                // have much meaning.\n                                continue;\n                            }\n                            match link_type {\n                                LinkType::Autolink | LinkType::Email => {\n                                    // The text is a copy of the URL, which is not needed.\n                                    match self.parser.next() {\n                                        Some((Event::Text(_), _range)) => {}\n                                        _ => bail!(\"expected text after autolink\"),\n                                    }\n                                }\n                                LinkType::Inline\n                                | LinkType::Reference\n                                | LinkType::Collapsed\n                                | LinkType::Shortcut => {\n                                    self.push_font(Font::Italic);\n                                }\n                                // This is currently unused. This is only\n                                // emitted with a broken link callback, but I\n                                // felt it is too annoying to escape `[` in\n                                // option descriptions.\n                                LinkType::ReferenceUnknown\n                                | LinkType::CollapsedUnknown\n                                | LinkType::ShortcutUnknown => {\n                                    bail!(\n                                        \"link with missing reference `{}` located at offset {}\",\n                                        dest_url,\n                                        range.start\n                                    );\n                                }\n                                LinkType::WikiLink { .. } => {\n                                    panic!(\"wikilink unsupported\");\n                                }\n                            }\n                        }\n                        Tag::Image { .. } => {\n                            bail!(\"images are not currently supported\")\n                        }\n                        Tag::HtmlBlock { .. }\n                        | Tag::MetadataBlock { .. }\n                        | Tag::DefinitionList\n                        | Tag::DefinitionListTitle\n                        | Tag::DefinitionListDefinition\n                        | Tag::Superscript\n                        | Tag::Subscript => {}\n                    }\n                }\n                Event::End(tag_end) => {\n                    match &tag_end {\n                        TagEnd::Paragraph => self.flush(),\n                        TagEnd::Heading(..) => {}\n                        TagEnd::BlockQuote(..) => {\n                            self.flush();\n                            // restore left margin, restore line length\n                            self.output.push_str(\".br\\n.RE\\n.ll\\n\");\n                        }\n                        TagEnd::CodeBlock => {\n                            self.flush();\n                            // Restore fill mode, move margin back one level.\n                            self.output.push_str(\".fi\\n.RE\\n\");\n                        }\n                        TagEnd::List(_) => {\n                            list.pop();\n                        }\n                        TagEnd::Item => {\n                            self.flush();\n                            // Move margin back one level.\n                            self.output.push_str(\".RE\\n\");\n                        }\n                        TagEnd::FootnoteDefinition => {}\n                        TagEnd::Table => {\n                            // Table end\n                            // I don't know why, but the .sp is needed to provide\n                            // space with the following content.\n                            self.output.push_str(\"\\n.TE\\n.sp\\n\");\n                        }\n                        TagEnd::TableHead => {}\n                        TagEnd::TableRow => {}\n                        TagEnd::TableCell => {\n                            // End text block.\n                            self.output.push_str(\"\\nT}\");\n                        }\n                        TagEnd::Emphasis | TagEnd::Strong => self.pop_font(),\n                        TagEnd::Strikethrough => self.output.push_str(\"~~\"),\n                        TagEnd::Link => {\n                            if let Some((link_type, ref dest_url)) = last_seen_link_data {\n                                if dest_url.starts_with('#') {\n                                    continue;\n                                }\n                                match link_type {\n                                    LinkType::Autolink | LinkType::Email => {}\n                                    LinkType::Inline\n                                    | LinkType::Reference\n                                    | LinkType::Collapsed\n                                    | LinkType::Shortcut => {\n                                        self.pop_font();\n                                        self.output.push(' ');\n                                    }\n                                    _ => {\n                                        panic!(\"unexpected tag {:?}\", tag_end);\n                                    }\n                                }\n                                write!(self.output, \"<{}>\", escape(&dest_url)?)?;\n                            }\n                        }\n                        TagEnd::Image\n                        | TagEnd::HtmlBlock\n                        | TagEnd::MetadataBlock(..)\n                        | TagEnd::DefinitionListDefinition\n                        | TagEnd::DefinitionListTitle\n                        | TagEnd::DefinitionList\n                        | TagEnd::Superscript\n                        | TagEnd::Subscript => {}\n                    }\n                }\n                Event::Text(t) => {\n                    self.output.push_str(&escape(&t)?);\n                }\n                Event::Code(t) => {\n                    self.push_font(Font::Bold);\n                    self.output.push_str(&escape(&t)?);\n                    self.pop_font();\n                }\n                Event::Html(t) => {\n                    if t.starts_with(\"<![CDATA[\") {\n                        // CDATA is a special marker used for handling options.\n                        in_cdata = true;\n                    } else if in_cdata {\n                        if t.trim().ends_with(\"]]>\") {\n                            in_cdata = false;\n                        } else if !t.trim().is_empty() {\n                            self.output.push_str(&t);\n                        }\n                    } else {\n                        self.output.push_str(&escape(&t)?);\n                    }\n                }\n                Event::FootnoteReference(_t) => {}\n                Event::SoftBreak => self.output.push('\\n'),\n                Event::HardBreak => {\n                    self.flush();\n                    self.output.push_str(\".br\\n\");\n                }\n                Event::Rule => {\n                    self.flush();\n                    // \\l' **length** '   Draw horizontal line (default underscore).\n                    // \\n(.lu  Gets value from register \"lu\" (current line length)\n                    self.output.push_str(\"\\\\l'\\\\n(.lu'\\n\");\n                }\n                Event::TaskListMarker(_b) => unimplemented!(),\n                Event::InlineHtml(..) => unimplemented!(),\n                Event::InlineMath(..) => unimplemented!(),\n                Event::DisplayMath(..) => unimplemented!(),\n            }\n        }\n        Ok(())\n    }\n\n    fn flush(&mut self) {\n        if !self.output.ends_with('\\n') {\n            self.output.push('\\n');\n        }\n    }\n\n    /// Switch to the given font.\n    ///\n    /// Because the troff sequence `\\fP` for switching to the \"previous\" font\n    /// doesn't support nesting, this needs to emulate it here. This is needed\n    /// for situations like **hi _there_**.\n    fn push_font(&mut self, font: Font) {\n        self.font_stack.push(font);\n        self.output.push_str(Font::str_from_stack(&self.font_stack));\n    }\n\n    fn pop_font(&mut self) {\n        self.font_stack.pop();\n        self.output.push_str(Font::str_from_stack(&self.font_stack));\n    }\n\n    /// Parse and render the first top-level header of the document.\n    fn push_top_header(&mut self) -> Result<(), Error> {\n        // This enables the tbl preprocessor for tables.\n        // This seems to be enabled by default on every modern system I could\n        // find, but it doesn't seem to hurt to enable this.\n        self.output.push_str(\"'\\\\\\\" t\\n\");\n        // Extract the name of the man page.\n        let text = header_text(&mut self.parser)?;\n        let (name, section) = parse_name_and_section(&text)?;\n        // .TH = Table header\n        // .nh = disable hyphenation\n        // .ad l = Left-adjust mode (disable justified).\n        // .ss sets sentence_space_size to 0 (prevents double spaces after .\n        //     if . is last on the line)\n        write!(\n            self.output,\n            \".TH \\\"{}\\\" \\\"{}\\\"\\n\\\n            .nh\\n\\\n            .ad l\\n\\\n            .ss \\\\n[.ss] 0\\n\",\n            escape(&name.to_uppercase())?,\n            section\n        )?;\n        Ok(())\n    }\n}\n\n#[allow(clippy::collapsible_str_replace)]\nfn escape(s: &str) -> Result<String, Error> {\n    // Note: Possible source on output escape sequences: https://man7.org/linux/man-pages/man7/groff_char.7.html.\n    //       Otherwise, use generic escaping in the form `\\[u1EE7]` or `\\[u1F994]`.\n\n    let mut replaced = s\n        .replace('\\\\', \"\\\\(rs\")\n        .replace('-', \"\\\\-\")\n        .replace('\\u{00A0}', \"\\\\ \") // non-breaking space (non-stretchable)\n        .replace('–', \"\\\\[en]\") // \\u{2013} en-dash\n        .replace('—', \"\\\\[em]\") // \\u{2014} em-dash\n        .replace('‘', \"\\\\[oq]\") // \\u{2018} left single quote\n        .replace('’', \"\\\\[cq]\") // \\u{2019} right single quote or apostrophe\n        .replace('“', \"\\\\[lq]\") // \\u{201C} left double quote\n        .replace('”', \"\\\\[rq]\") // \\u{201D} right double quote\n        .replace('…', \"\\\\[u2026]\") // \\u{2026} ellipsis\n        .replace('│', \"|\") // \\u{2502} box drawing light vertical (could use \\[br])\n        .replace('├', \"|\") // \\u{251C} box drawings light vertical and right\n        .replace('└', \"`\") // \\u{2514} box drawings light up and right\n        .replace('─', \"\\\\-\") // \\u{2500} box drawing light horizontal\n    ;\n    if replaced.starts_with('.') {\n        replaced = format!(\"\\\\&.{}\", &replaced[1..]);\n    }\n\n    if let Some(ch) = replaced.chars().find(|ch| {\n        !matches!(ch, '\\n' | ' ' | '!'..='/' | '0'..='9'\n            | ':'..='@' | 'A'..='Z' | '['..='`' | 'a'..='z' | '{'..='~')\n    }) {\n        bail!(\n            \"character {:?} is not allowed (update the translation table if needed)\",\n            ch\n        );\n    }\n    Ok(replaced)\n}\n"
  },
  {
    "path": "crates/mdman/src/format/md.rs",
    "content": "//! Markdown formatter.\n\nuse crate::ManMap;\nuse crate::util::unwrap;\nuse anyhow::{Error, bail, format_err};\nuse std::fmt::Write;\n\npub struct MdFormatter {\n    man_map: ManMap,\n}\n\nimpl MdFormatter {\n    pub fn new(man_map: ManMap) -> MdFormatter {\n        MdFormatter { man_map }\n    }\n}\n\nimpl MdFormatter {\n    fn render_html(&self, input: &str) -> Result<String, Error> {\n        let parser = crate::md_parser(input, None);\n        let mut html_output: String = String::with_capacity(input.len() * 3 / 2);\n        pulldown_cmark::html::push_html(&mut html_output, parser.map(|(e, _r)| e));\n        Ok(html_output)\n    }\n}\n\nimpl super::Formatter for MdFormatter {\n    fn render(&self, input: &str) -> Result<String, Error> {\n        Ok(input.replace(\"\\r\\n\", \"\\n\"))\n    }\n\n    fn render_options_start(&self) -> &'static str {\n        \"<dl>\\n\"\n    }\n\n    fn render_options_end(&self) -> &'static str {\n        \"</dl>\\n\"\n    }\n\n    fn render_option(&self, params: &[&str], block: &str, man_name: &str) -> Result<String, Error> {\n        let mut result = String::new();\n        fn unwrap_p(t: &str) -> &str {\n            unwrap(t, \"<p>\", \"</p>\")\n        }\n\n        for param in params {\n            let rendered = self.render_html(param)?;\n            let no_p = unwrap_p(&rendered);\n            // split out first term to use as the id.\n            let first = no_p\n                .split_whitespace()\n                .next()\n                .ok_or_else(|| format_err!(\"did not expect option `{}` to be empty\", param))?;\n            let no_tags = trim_tags(first);\n            if no_tags.is_empty() {\n                bail!(\"unexpected empty option with no tags `{}`\", param);\n            }\n            let id = format!(\"option-{}-{}\", man_name, no_tags);\n            write!(\n                result,\n                \"<dt class=\\\"option-term\\\" id=\\\"{id}\\\">\\\n                <a class=\\\"option-anchor\\\" href=\\\"#{id}\\\">{no_p}</a></dt>\\n\",\n            )?;\n        }\n        let rendered_block = self.render_html(block)?;\n        write!(\n            result,\n            \"<dd class=\\\"option-desc\\\">{rendered_block}</dd>\\n\\n\",\n        )?;\n        Ok(result)\n    }\n\n    fn linkify_man_to_md(&self, name: &str, section: u8) -> Result<String, Error> {\n        let s = match self.man_map.get(&(name.to_string(), section)) {\n            Some(link) => format!(\"[{}({})]({})\", name, section, link),\n            None => format!(\"[{}({})]({}.html)\", name, section, name),\n        };\n        Ok(s)\n    }\n}\n\nfn trim_tags(s: &str) -> String {\n    // This is a hack. It removes all HTML tags.\n    let mut in_tag = false;\n    let mut in_char_ref = false;\n    s.chars()\n        .filter(|&ch| match ch {\n            '<' if in_tag => panic!(\"unexpected nested tag\"),\n            '&' if in_char_ref => panic!(\"unexpected nested char ref\"),\n            '<' => {\n                in_tag = true;\n                false\n            }\n            '&' => {\n                in_char_ref = true;\n                false\n            }\n            '>' if in_tag => {\n                in_tag = false;\n                false\n            }\n            ';' if in_char_ref => {\n                in_char_ref = false;\n                false\n            }\n            _ => !in_tag && !in_char_ref,\n        })\n        .collect()\n}\n"
  },
  {
    "path": "crates/mdman/src/format/mod.rs",
    "content": "use anyhow::Error;\n\npub mod man;\npub mod md;\npub mod text;\n\npub trait Formatter {\n    /// Renders the given markdown to the formatter's output.\n    fn render(&self, input: &str) -> Result<String, Error>;\n    /// Renders the start of a block of options (triggered by `{{#options}}`).\n    fn render_options_start(&self) -> &'static str;\n    /// Renders the end of a block of options (triggered by `{{/options}}`).\n    fn render_options_end(&self) -> &'static str;\n    /// Renders an option (triggered by `{{#option}}`).\n    fn render_option(&self, params: &[&str], block: &str, man_name: &str) -> Result<String, Error>;\n    /// Converts a man page reference into markdown that is appropriate for this format.\n    ///\n    /// Triggered by `{{man name section}}`.\n    fn linkify_man_to_md(&self, name: &str, section: u8) -> Result<String, Error>;\n}\n"
  },
  {
    "path": "crates/mdman/src/format/text.rs",
    "content": "//! Text formatter.\n\nuse crate::EventIter;\nuse crate::util::{header_text, unwrap};\nuse anyhow::{Error, bail};\nuse pulldown_cmark::{Alignment, Event, HeadingLevel, LinkType, Tag, TagEnd};\nuse std::fmt::Write;\nuse std::mem;\nuse url::Url;\n\npub struct TextFormatter {\n    url: Option<Url>,\n}\n\nimpl TextFormatter {\n    pub fn new(url: Option<Url>) -> TextFormatter {\n        TextFormatter { url }\n    }\n}\n\nimpl super::Formatter for TextFormatter {\n    fn render(&self, input: &str) -> Result<String, Error> {\n        TextRenderer::render(input, self.url.clone(), 0)\n    }\n\n    fn render_options_start(&self) -> &'static str {\n        // Tell pulldown_cmark to ignore this.\n        // This will be stripped out later.\n        \"<![CDATA[\\n\"\n    }\n\n    fn render_options_end(&self) -> &'static str {\n        \"]]>\\n\"\n    }\n\n    fn render_option(\n        &self,\n        params: &[&str],\n        block: &str,\n        _man_name: &str,\n    ) -> Result<String, Error> {\n        let rendered_options = params\n            .iter()\n            .map(|param| TextRenderer::render(param, self.url.clone(), 0))\n            .collect::<Result<Vec<_>, Error>>()?;\n        let trimmed: Vec<_> = rendered_options.iter().map(|o| o.trim()).collect();\n        // Wrap in HTML tags, they will be stripped out during rendering.\n        Ok(format!(\n            \"<dt>{}</dt>\\n<dd>\\n{}</dd>\\n<br>\\n\",\n            trimmed.join(\", \"),\n            block\n        ))\n    }\n\n    fn linkify_man_to_md(&self, name: &str, section: u8) -> Result<String, Error> {\n        Ok(format!(\"`{}`({})\", name, section))\n    }\n}\n\nstruct TextRenderer<'e> {\n    output: String,\n    indent: usize,\n    /// The current line being written. Once a line break is encountered (such\n    /// as starting a new paragraph), this will be written to `output` via\n    /// `flush`.\n    line: String,\n    /// The current word being written. Once a break is encountered (such as a\n    /// space) this will be written to `line` via `flush_word`.\n    word: String,\n    parser: EventIter<'e>,\n    /// The base URL used for relative URLs.\n    url: Option<Url>,\n    table: Table,\n}\n\nimpl<'e> TextRenderer<'e> {\n    fn render(input: &str, url: Option<Url>, indent: usize) -> Result<String, Error> {\n        let parser = crate::md_parser(input, url.clone());\n        let output = String::with_capacity(input.len() * 3 / 2);\n        let mut mr = TextRenderer {\n            output,\n            indent,\n            line: String::new(),\n            word: String::new(),\n            parser,\n            url,\n            table: Table::new(),\n        };\n        mr.push_md()?;\n        Ok(mr.output)\n    }\n\n    fn push_md(&mut self) -> Result<(), Error> {\n        // If this is true, this is inside a cdata block used for hiding\n        // content from pulldown_cmark.\n        let mut in_cdata = false;\n        // The current list stack. None if unordered, Some if ordered with the\n        // given number as the current index.\n        let mut list: Vec<Option<u64>> = Vec::new();\n        // Used in some cases where spacing isn't desired.\n        let mut suppress_paragraph = false;\n        // Whether or not word-wrapping is enabled.\n        let mut wrap_text = true;\n\n        let mut last_seen_link_data = None;\n        while let Some((event, range)) = self.parser.next() {\n            let this_suppress_paragraph = suppress_paragraph;\n            // Always reset suppression, even if the next event isn't a\n            // paragraph. This is in essence, a 1-token lookahead where the\n            // suppression is only enabled if the next event is a paragraph.\n            suppress_paragraph = false;\n            match event {\n                Event::Start(tag) => {\n                    match tag {\n                        Tag::Paragraph => {\n                            if !this_suppress_paragraph {\n                                self.flush();\n                            }\n                        }\n                        Tag::Heading { level, .. } => {\n                            self.flush();\n                            if level == HeadingLevel::H1 {\n                                let text = header_text(&mut self.parser)?;\n                                self.push_to_line(&text.to_uppercase());\n                                self.hard_break();\n                                self.hard_break();\n                            } else if level == HeadingLevel::H2 {\n                                let text = header_text(&mut self.parser)?;\n                                self.push_to_line(&text.to_uppercase());\n                                self.flush();\n                                self.indent = 7;\n                            } else {\n                                let text = header_text(&mut self.parser)?;\n                                self.push_indent((level as usize - 2) * 3);\n                                self.push_to_line(&text);\n                                self.flush();\n                                self.indent = (level as usize - 1) * 3 + 1;\n                            }\n                        }\n                        Tag::BlockQuote(_kind) => {\n                            self.indent += 3;\n                        }\n                        Tag::CodeBlock(_kind) => {\n                            self.flush();\n                            wrap_text = false;\n                            self.indent += 4;\n                        }\n                        Tag::List(start) => list.push(start),\n                        Tag::Item => {\n                            self.flush();\n                            match list.last_mut().expect(\"item must have list start\") {\n                                // Ordered list.\n                                Some(n) => {\n                                    self.push_indent(self.indent);\n                                    write!(self.line, \"{}.\", n)?;\n                                    *n += 1;\n                                }\n                                // Unordered list.\n                                None => {\n                                    self.push_indent(self.indent);\n                                    self.push_to_line(\"o \")\n                                }\n                            }\n                            self.indent += 3;\n                            suppress_paragraph = true;\n                        }\n                        Tag::FootnoteDefinition(_label) => unimplemented!(),\n                        Tag::Table(alignment) => {\n                            assert!(self.table.alignment.is_empty());\n                            self.flush();\n                            self.table.alignment.extend(alignment);\n                            let table = self.table.process(&mut self.parser, self.indent)?;\n                            self.output.push_str(&table);\n                            self.hard_break();\n                            self.table = Table::new();\n                        }\n                        Tag::TableHead | Tag::TableRow | Tag::TableCell => {\n                            bail!(\"unexpected table element\")\n                        }\n                        Tag::Emphasis => {}\n                        Tag::Strong => {}\n                        // Strikethrough isn't usually supported for TTY.\n                        Tag::Strikethrough => self.word.push_str(\"~~\"),\n                        Tag::Link {\n                            link_type,\n                            dest_url,\n                            ..\n                        } => {\n                            last_seen_link_data = Some((link_type.clone(), dest_url.to_owned()));\n                            if dest_url.starts_with('#') {\n                                // In a man page, page-relative anchors don't\n                                // have much meaning.\n                                continue;\n                            }\n                            match link_type {\n                                LinkType::Autolink | LinkType::Email => {\n                                    // The text is a copy of the URL, which is not needed.\n                                    match self.parser.next() {\n                                        Some((Event::Text(_), _range)) => {}\n                                        _ => bail!(\"expected text after autolink\"),\n                                    }\n                                }\n                                LinkType::Inline\n                                | LinkType::Reference\n                                | LinkType::Collapsed\n                                | LinkType::Shortcut => {}\n                                // This is currently unused. This is only\n                                // emitted with a broken link callback, but I\n                                // felt it is too annoying to escape `[` in\n                                // option descriptions.\n                                LinkType::ReferenceUnknown\n                                | LinkType::CollapsedUnknown\n                                | LinkType::ShortcutUnknown => {\n                                    bail!(\n                                        \"link with missing reference `{}` located at offset {}\",\n                                        dest_url,\n                                        range.start\n                                    );\n                                }\n                                LinkType::WikiLink { .. } => {\n                                    panic!(\"wikilink unsupported\");\n                                }\n                            }\n                        }\n                        Tag::Image { .. } => {\n                            bail!(\"images are not currently supported\")\n                        }\n                        Tag::HtmlBlock { .. }\n                        | Tag::MetadataBlock { .. }\n                        | Tag::DefinitionList\n                        | Tag::DefinitionListTitle\n                        | Tag::DefinitionListDefinition\n                        | Tag::Superscript\n                        | Tag::Subscript => {}\n                    }\n                }\n                Event::End(tag_end) => match &tag_end {\n                    TagEnd::Paragraph => {\n                        self.flush();\n                        self.hard_break();\n                    }\n                    TagEnd::Heading(..) => {}\n                    TagEnd::BlockQuote(..) => {\n                        self.indent -= 3;\n                    }\n                    TagEnd::CodeBlock => {\n                        self.hard_break();\n                        wrap_text = true;\n                        self.indent -= 4;\n                    }\n                    TagEnd::List(..) => {\n                        list.pop();\n                    }\n                    TagEnd::Item => {\n                        self.flush();\n                        self.indent -= 3;\n                        self.hard_break();\n                    }\n                    TagEnd::FootnoteDefinition => {}\n                    TagEnd::Table => {}\n                    TagEnd::TableHead => {}\n                    TagEnd::TableRow => {}\n                    TagEnd::TableCell => {}\n                    TagEnd::Emphasis => {}\n                    TagEnd::Strong => {}\n                    TagEnd::Strikethrough => self.word.push_str(\"~~\"),\n                    TagEnd::Link => {\n                        if let Some((link_type, ref dest_url)) = last_seen_link_data {\n                            if dest_url.starts_with('#') {\n                                continue;\n                            }\n                            match link_type {\n                                LinkType::Autolink | LinkType::Email => {}\n                                LinkType::Inline\n                                | LinkType::Reference\n                                | LinkType::Collapsed\n                                | LinkType::Shortcut => self.flush_word(),\n                                _ => {\n                                    panic!(\"unexpected tag {:?}\", tag_end);\n                                }\n                            }\n                            self.flush_word();\n                            write!(self.word, \"<{}>\", dest_url)?;\n                        }\n                    }\n                    TagEnd::HtmlBlock { .. }\n                    | TagEnd::MetadataBlock { .. }\n                    | TagEnd::DefinitionList\n                    | TagEnd::DefinitionListTitle\n                    | TagEnd::Image\n                    | TagEnd::DefinitionListDefinition\n                    | TagEnd::Superscript\n                    | TagEnd::Subscript => {}\n                },\n                Event::Text(t) | Event::Code(t) => {\n                    if wrap_text {\n                        let chunks = split_chunks(&t);\n                        for chunk in chunks {\n                            if chunk == \" \" {\n                                self.flush_word();\n                            } else {\n                                self.word.push_str(chunk);\n                            }\n                        }\n                    } else {\n                        for line in t.lines() {\n                            self.push_indent(self.indent);\n                            self.push_to_line(line);\n                            self.flush();\n                        }\n                    }\n                }\n                Event::Html(t) => {\n                    if t.starts_with(\"<![CDATA[\") {\n                        // CDATA is a special marker used for handling options.\n                        in_cdata = true;\n                        self.flush();\n                    } else if in_cdata {\n                        if t.trim().ends_with(\"]]>\") {\n                            in_cdata = false;\n                        } else {\n                            let trimmed = t.trim();\n                            if trimmed.is_empty() {\n                                continue;\n                            }\n                            if trimmed == \"<br>\" {\n                                self.hard_break();\n                            } else if trimmed.starts_with(\"<dt>\") {\n                                let opts = unwrap(trimmed, \"<dt>\", \"</dt>\");\n                                self.push_indent(self.indent);\n                                self.push_to_line(opts);\n                                self.flush();\n                            } else if trimmed.starts_with(\"<dd>\") {\n                                let mut def = String::new();\n                                while let Some((Event::Html(t), _range)) = self.parser.next() {\n                                    if t.starts_with(\"</dd>\") {\n                                        break;\n                                    }\n                                    def.push_str(&t);\n                                }\n                                let rendered =\n                                    TextRenderer::render(&def, self.url.clone(), self.indent + 4)?;\n                                self.push_to_line(rendered.trim_end());\n                                self.flush();\n                            } else {\n                                self.push_to_line(&t);\n                                self.flush();\n                            }\n                        }\n                    } else {\n                        self.push_to_line(&t);\n                        self.flush();\n                    }\n                }\n                Event::FootnoteReference(_t) => {}\n                Event::SoftBreak => self.flush_word(),\n                Event::HardBreak => self.flush(),\n                Event::Rule => {\n                    self.flush();\n                    self.push_indent(self.indent);\n                    self.push_to_line(&\"_\".repeat(79 - self.indent * 2));\n                    self.flush();\n                }\n                Event::TaskListMarker(_b) => unimplemented!(),\n                Event::InlineHtml(..) => unimplemented!(),\n                Event::InlineMath(..) => unimplemented!(),\n                Event::DisplayMath(..) => unimplemented!(),\n            }\n        }\n        Ok(())\n    }\n\n    fn flush(&mut self) {\n        self.flush_word();\n        if !self.line.is_empty() {\n            self.output.push_str(&self.line);\n            self.output.push('\\n');\n            self.line.clear();\n        }\n    }\n\n    fn hard_break(&mut self) {\n        self.flush();\n        if !self.output.ends_with(\"\\n\\n\") {\n            self.output.push('\\n');\n        }\n    }\n\n    fn flush_word(&mut self) {\n        if self.word.is_empty() {\n            return;\n        }\n        if self.line.len() + self.word.len() >= 79 {\n            self.output.push_str(&self.line);\n            self.output.push('\\n');\n            self.line.clear();\n        }\n        if self.line.is_empty() {\n            self.push_indent(self.indent);\n            self.line.push_str(&self.word);\n        } else {\n            self.line.push(' ');\n            self.line.push_str(&self.word);\n        }\n        self.word.clear();\n    }\n\n    fn push_indent(&mut self, indent: usize) {\n        for _ in 0..indent {\n            self.line.push(' ');\n        }\n    }\n\n    fn push_to_line(&mut self, text: &str) {\n        self.flush_word();\n        self.line.push_str(text);\n    }\n}\n\n/// Splits the text on whitespace.\n///\n/// Consecutive whitespace is collapsed to a single ' ', and is included as a\n/// separate element in the result.\nfn split_chunks(text: &str) -> Vec<&str> {\n    let mut result = Vec::new();\n    let mut start = 0;\n    while start < text.len() {\n        match text[start..].find(' ') {\n            Some(i) => {\n                if i != 0 {\n                    result.push(&text[start..start + i]);\n                }\n                result.push(\" \");\n                // Skip past whitespace.\n                match text[start + i..].find(|c| c != ' ') {\n                    Some(n) => {\n                        start = start + i + n;\n                    }\n                    None => {\n                        break;\n                    }\n                }\n            }\n            None => {\n                result.push(&text[start..]);\n                break;\n            }\n        }\n    }\n    result\n}\n\nstruct Table {\n    alignment: Vec<Alignment>,\n    rows: Vec<Vec<String>>,\n    row: Vec<String>,\n    cell: String,\n}\n\nimpl Table {\n    fn new() -> Table {\n        Table {\n            alignment: Vec::new(),\n            rows: Vec::new(),\n            row: Vec::new(),\n            cell: String::new(),\n        }\n    }\n\n    /// Processes table events and generates a text table.\n    fn process(&mut self, parser: &mut EventIter<'_>, indent: usize) -> Result<String, Error> {\n        while let Some((event, _range)) = parser.next() {\n            match event {\n                Event::Start(tag) => match tag {\n                    Tag::TableHead\n                    | Tag::TableRow\n                    | Tag::TableCell\n                    | Tag::Emphasis\n                    | Tag::Strong => {}\n                    Tag::Strikethrough => self.cell.push_str(\"~~\"),\n                    // Links not yet supported, they usually won't fit.\n                    Tag::Link { .. } => {}\n                    _ => bail!(\"unexpected tag in table: {:?}\", tag),\n                },\n                Event::End(tag_end) => match tag_end {\n                    TagEnd::Table => return self.render(indent),\n                    TagEnd::TableCell => {\n                        let cell = mem::replace(&mut self.cell, String::new());\n                        self.row.push(cell);\n                    }\n                    TagEnd::TableHead | TagEnd::TableRow => {\n                        let row = mem::replace(&mut self.row, Vec::new());\n                        self.rows.push(row);\n                    }\n                    TagEnd::Strikethrough => self.cell.push_str(\"~~\"),\n                    _ => {}\n                },\n                Event::Text(t) | Event::Code(t) => {\n                    self.cell.push_str(&t);\n                }\n                Event::Html(t) => bail!(\"html unsupported in tables: {:?}\", t),\n                _ => bail!(\"unexpected event in table: {:?}\", event),\n            }\n        }\n        bail!(\"table end not reached\");\n    }\n\n    fn render(&self, indent: usize) -> Result<String, Error> {\n        // This is an extremely primitive layout routine.\n        // First compute the potential maximum width of each cell.\n        // 2 for 1 space margin on left and right.\n        let width_acc = vec![2; self.alignment.len()];\n        let mut col_widths = self\n            .rows\n            .iter()\n            .map(|row| row.iter().map(|cell| cell.len()))\n            .fold(width_acc, |mut acc, row| {\n                acc.iter_mut()\n                    .zip(row)\n                    // +3 for left/right margin and | symbol\n                    .for_each(|(a, b)| *a = (*a).max(b + 3));\n                acc\n            });\n        // Shrink each column until it fits the total width, proportional to\n        // the columns total percent width.\n        let max_width = 78 - indent;\n        // Include total len for | characters, and +1 for final |.\n        let total_width = col_widths.iter().sum::<usize>() + col_widths.len() + 1;\n        if total_width > max_width {\n            let to_shrink = total_width - max_width;\n            // Compute percentage widths, and shrink each column based on its\n            // total percentage.\n            for width in &mut col_widths {\n                let percent = *width as f64 / total_width as f64;\n                *width -= (to_shrink as f64 * percent).ceil() as usize;\n            }\n        }\n        // Start rendering.\n        let mut result = String::new();\n\n        // Draw the horizontal line separating each row.\n        let mut row_line = String::new();\n        row_line.push_str(&\" \".repeat(indent));\n        row_line.push('+');\n        let lines = col_widths\n            .iter()\n            .map(|width| \"-\".repeat(*width))\n            .collect::<Vec<_>>();\n        row_line.push_str(&lines.join(\"+\"));\n        row_line.push('+');\n        row_line.push('\\n');\n\n        // Draw top of the table.\n        result.push_str(&row_line);\n        // Draw each row.\n        for row in &self.rows {\n            // Word-wrap and fill each column as needed.\n            let filled = fill_row(row, &col_widths, &self.alignment);\n            // Need to transpose the cells across rows for cells that span\n            // multiple rows.\n            let height = filled.iter().map(|c| c.len()).max().unwrap();\n            for row_i in 0..height {\n                result.push_str(&\" \".repeat(indent));\n                result.push('|');\n                for filled_row in &filled {\n                    let cell = &filled_row[row_i];\n                    result.push_str(cell);\n                    result.push('|');\n                }\n                result.push('\\n');\n            }\n            result.push_str(&row_line);\n        }\n        Ok(result)\n    }\n}\n\n/// Formats a row, filling cells with spaces and word-wrapping text.\n///\n/// Returns a vec of cells, where each cell is split into multiple lines.\nfn fill_row(row: &[String], col_widths: &[usize], alignment: &[Alignment]) -> Vec<Vec<String>> {\n    let mut cell_lines = row\n        .iter()\n        .zip(col_widths)\n        .zip(alignment)\n        .map(|((cell, width), alignment)| fill_cell(cell, *width - 2, *alignment))\n        .collect::<Vec<_>>();\n    // Fill each cell to match the maximum vertical height of the tallest cell.\n    let max_lines = cell_lines.iter().map(|cell| cell.len()).max().unwrap();\n    for (cell, width) in cell_lines.iter_mut().zip(col_widths) {\n        if cell.len() < max_lines {\n            cell.extend(std::iter::repeat(\" \".repeat(*width)).take(max_lines - cell.len()));\n        }\n    }\n    cell_lines\n}\n\n/// Formats a cell. Word-wraps based on width, and adjusts based on alignment.\n///\n/// Returns a vec of lines for the cell.\nfn fill_cell(text: &str, width: usize, alignment: Alignment) -> Vec<String> {\n    let fill_width = |text: &str| match alignment {\n        Alignment::None | Alignment::Left => format!(\" {:<width$} \", text, width = width),\n        Alignment::Center => format!(\" {:^width$} \", text, width = width),\n        Alignment::Right => format!(\" {:>width$} \", text, width = width),\n    };\n    if text.len() < width {\n        // No wrapping necessary, just format.\n        vec![fill_width(text)]\n    } else {\n        // Word-wrap the cell.\n        let mut result = Vec::new();\n        let mut line = String::new();\n        for word in text.split_whitespace() {\n            if line.len() + word.len() >= width {\n                // todo: word.len() > width\n                result.push(fill_width(&line));\n                line.clear();\n            }\n            if line.is_empty() {\n                line.push_str(word);\n            } else {\n                line.push(' ');\n                line.push_str(&word);\n            }\n        }\n        if !line.is_empty() {\n            result.push(fill_width(&line));\n        }\n\n        result\n    }\n}\n"
  },
  {
    "path": "crates/mdman/src/hbs.rs",
    "content": "//! Handlebars template processing.\n\nuse std::collections::HashMap;\nuse std::path::Path;\n\nuse anyhow::Error;\nuse handlebars::{\n    Context, Decorator, DirectorySourceOptions, Handlebars, Helper, HelperDef, HelperResult,\n    Output, RenderContext, RenderError, RenderErrorReason, Renderable, handlebars_helper,\n};\n\nuse crate::format::Formatter;\n\ntype FormatterRef<'a> = &'a (dyn Formatter + Send + Sync);\n\n/// Processes the handlebars template at the given file.\npub fn expand(file: &Path, formatter: FormatterRef<'_>) -> Result<String, Error> {\n    let mut handlebars = Handlebars::new();\n    handlebars.set_strict_mode(true);\n    handlebars.register_helper(\"lower\", Box::new(lower));\n    handlebars.register_helper(\"options\", Box::new(OptionsHelper { formatter }));\n    handlebars.register_helper(\"option\", Box::new(OptionHelper { formatter }));\n    handlebars.register_helper(\"man\", Box::new(ManLinkHelper { formatter }));\n    handlebars.register_decorator(\"set\", Box::new(set_decorator));\n    handlebars.register_template_file(\"template\", file)?;\n    let includes = file.parent().unwrap().join(\"includes\");\n    let mut options = DirectorySourceOptions::default();\n    options.tpl_extension = \".md\".to_string();\n    handlebars.register_templates_directory(includes, options)?;\n    let man_name = file\n        .file_stem()\n        .expect(\"expected filename\")\n        .to_str()\n        .expect(\"utf8 filename\")\n        .to_string();\n    let data = HashMap::from([(\"man_name\", man_name)]);\n    let expanded = handlebars.render(\"template\", &data)?;\n    Ok(expanded)\n}\n\n/// Helper for `{{#options}}` block.\nstruct OptionsHelper<'a> {\n    formatter: FormatterRef<'a>,\n}\n\nimpl HelperDef for OptionsHelper<'_> {\n    fn call<'reg: 'rc, 'rc>(\n        &self,\n        h: &Helper<'rc>,\n        r: &'reg Handlebars<'reg>,\n        ctx: &'rc Context,\n        rc: &mut RenderContext<'reg, 'rc>,\n        out: &mut dyn Output,\n    ) -> HelperResult {\n        if in_options(rc) {\n            return Err(\n                RenderErrorReason::Other(\"options blocks cannot be nested\".to_string()).into(),\n            );\n        }\n        // Prevent nested {{#options}}.\n        set_in_context(rc, \"__MDMAN_IN_OPTIONS\", serde_json::Value::Bool(true));\n        let s = self.formatter.render_options_start();\n        out.write(&s)?;\n        let t = match h.template() {\n            Some(t) => t,\n            None => {\n                return Err(RenderErrorReason::Other(\n                    \"options block must not be empty\".to_string(),\n                )\n                .into());\n            }\n        };\n        let block = t.renders(r, ctx, rc)?;\n        out.write(&block)?;\n\n        let s = self.formatter.render_options_end();\n        out.write(&s)?;\n        remove_from_context(rc, \"__MDMAN_IN_OPTIONS\");\n        Ok(())\n    }\n}\n\n/// Whether or not the context is currently inside a `{{#options}}` block.\nfn in_options(rc: &RenderContext<'_, '_>) -> bool {\n    rc.context()\n        .map_or(false, |ctx| ctx.data().get(\"__MDMAN_IN_OPTIONS\").is_some())\n}\n\n/// Helper for `{{#option}}` block.\nstruct OptionHelper<'a> {\n    formatter: FormatterRef<'a>,\n}\n\nimpl HelperDef for OptionHelper<'_> {\n    fn call<'reg: 'rc, 'rc>(\n        &self,\n        h: &Helper<'rc>,\n        r: &'reg Handlebars<'reg>,\n        gctx: &'rc Context,\n        rc: &mut RenderContext<'reg, 'rc>,\n        out: &mut dyn Output,\n    ) -> HelperResult {\n        if !in_options(rc) {\n            return Err(\n                RenderErrorReason::Other(\"option must be in options block\".to_string()).into(),\n            );\n        }\n        let params = h.params();\n        if params.is_empty() {\n            return Err(RenderErrorReason::Other(\n                \"option block must have at least one param\".to_string(),\n            )\n            .into());\n        }\n        // Convert params to strings.\n        let params = params\n            .iter()\n            .map(|param| {\n                param\n                    .value()\n                    .as_str()\n                    .ok_or_else(|| {\n                        RenderErrorReason::Other(\"option params must be strings\".to_string())\n                    })\n                    .into()\n            })\n            .collect::<Result<Vec<&str>, RenderErrorReason>>()?;\n        let t = match h.template() {\n            Some(t) => t,\n            None => {\n                return Err(\n                    RenderErrorReason::Other(\"option block must not be empty\".to_string()).into(),\n                );\n            }\n        };\n        // Render the block.\n        let block = t.renders(r, gctx, rc)?;\n\n        // Windows newlines can break some rendering, so normalize.\n        let block = block.replace(\"\\r\\n\", \"\\n\");\n\n        // Get the name of this page.\n        let man_name = gctx\n            .data()\n            .get(\"man_name\")\n            .expect(\"expected man_name in context\")\n            .as_str()\n            .expect(\"expect man_name str\");\n\n        // Ask the formatter to convert this option to its format.\n        let option = self\n            .formatter\n            .render_option(&params, &block, man_name)\n            .map_err(|e| RenderErrorReason::Other(format!(\"option render failed: {}\", e)))?;\n        out.write(&option)?;\n        Ok(())\n    }\n}\n\n/// Helper for `{{man name section}}` expression.\nstruct ManLinkHelper<'a> {\n    formatter: FormatterRef<'a>,\n}\n\nimpl HelperDef for ManLinkHelper<'_> {\n    fn call<'reg: 'rc, 'rc>(\n        &self,\n        h: &Helper<'rc>,\n        _r: &'reg Handlebars<'reg>,\n        _ctx: &'rc Context,\n        _rc: &mut RenderContext<'reg, 'rc>,\n        out: &mut dyn Output,\n    ) -> HelperResult {\n        let params = h.params();\n        if params.len() != 2 {\n            return Err(\n                RenderErrorReason::Other(\"{{man}} must have two arguments\".to_string()).into(),\n            );\n        }\n        let name = params[0].value().as_str().ok_or_else(|| {\n            RenderErrorReason::Other(\"man link name must be a string\".to_string())\n        })?;\n        let section = params[1].value().as_u64().ok_or_else(|| {\n            RenderErrorReason::Other(\"man link section must be an integer\".to_string())\n        })?;\n        let section = u8::try_from(section)\n            .map_err(|_e| RenderErrorReason::Other(\"section number too large\".to_string()))?;\n        let link = self\n            .formatter\n            .linkify_man_to_md(name, section)\n            .map_err(|e| RenderErrorReason::Other(format!(\"failed to linkify man: {}\", e)))?;\n        out.write(&link)?;\n        Ok(())\n    }\n}\n\n/// `{{*set var=value}}` decorator.\n///\n/// This sets a variable to a value within the template context.\nfn set_decorator(\n    d: &Decorator<'_>,\n    _: &Handlebars<'_>,\n    _ctx: &Context,\n    rc: &mut RenderContext<'_, '_>,\n) -> Result<(), RenderError> {\n    let data_to_set = d.hash();\n    for (k, v) in data_to_set {\n        set_in_context(rc, k, v.value().clone());\n    }\n    Ok(())\n}\n\n/// Sets a variable to a value within the context.\nfn set_in_context(rc: &mut RenderContext<'_, '_>, key: &str, value: serde_json::Value) {\n    let mut gctx = match rc.context() {\n        Some(c) => (*c).clone(),\n        None => Context::wraps(serde_json::Value::Object(serde_json::Map::new())).unwrap(),\n    };\n    if let serde_json::Value::Object(m) = gctx.data_mut() {\n        m.insert(key.to_string(), value);\n        rc.set_context(gctx);\n    } else {\n        panic!(\"expected object in context\");\n    }\n}\n\n/// Removes a variable from the context.\nfn remove_from_context(rc: &mut RenderContext<'_, '_>, key: &str) {\n    let gctx = rc.context().expect(\"cannot remove from null context\");\n    let mut gctx = (*gctx).clone();\n    if let serde_json::Value::Object(m) = gctx.data_mut() {\n        m.remove(key);\n        rc.set_context(gctx);\n    } else {\n        panic!(\"expected object in context\");\n    }\n}\n\nhandlebars_helper!(lower: |s: str| s.to_lowercase());\n"
  },
  {
    "path": "crates/mdman/src/lib.rs",
    "content": "//! mdman markdown to man converter.\n//!\n//! > This crate is maintained by the Cargo team, primarily for use by Cargo\n//! > and not intended for external use (except as a transitive dependency). This\n//! > crate may make major changes to its APIs or be deprecated without warning.\n\nuse anyhow::{Context, Error, bail};\nuse pulldown_cmark::{CowStr, Event, LinkType, Options, Parser, Tag, TagEnd};\nuse std::collections::HashMap;\nuse std::fs;\nuse std::io::{self, BufRead};\nuse std::ops::Range;\nuse std::path::Path;\nuse url::Url;\n\nmod format;\nmod hbs;\nmod util;\n\nuse format::Formatter;\n\n/// Mapping of `(name, section)` of a man page to a URL.\npub type ManMap = HashMap<(String, u8), String>;\n\n/// A man section.\npub type Section = u8;\n\n/// The output formats supported by mdman.\n#[derive(Copy, Clone)]\npub enum Format {\n    Man,\n    Md,\n    Text,\n}\n\nimpl Format {\n    /// The filename extension for the format.\n    pub fn extension(&self, section: Section) -> String {\n        match self {\n            Format::Man => section.to_string(),\n            Format::Md => \"md\".to_string(),\n            Format::Text => \"txt\".to_string(),\n        }\n    }\n}\n\n/// Converts the handlebars markdown file at the given path into the given\n/// format, returning the translated result.\npub fn convert(\n    file: &Path,\n    format: Format,\n    url: Option<Url>,\n    man_map: ManMap,\n) -> Result<String, Error> {\n    let formatter: Box<dyn Formatter + Send + Sync> = match format {\n        Format::Man => Box::new(format::man::ManFormatter::new(url)),\n        Format::Md => Box::new(format::md::MdFormatter::new(man_map)),\n        Format::Text => Box::new(format::text::TextFormatter::new(url)),\n    };\n    let expanded = hbs::expand(file, &*formatter)?;\n    // pulldown-cmark can behave a little differently with Windows newlines,\n    // just normalize it.\n    let expanded = expanded.replace(\"\\r\\n\", \"\\n\");\n    formatter.render(&expanded)\n}\n\n/// Pulldown-cmark iterator yielding an `(event, range)` tuple.\ntype EventIter<'a> = Box<dyn Iterator<Item = (Event<'a>, Range<usize>)> + 'a>;\n\n/// Creates a new markdown parser with the given input.\npub(crate) fn md_parser(input: &str, url: Option<Url>) -> EventIter<'_> {\n    let mut options = Options::empty();\n    options.insert(Options::ENABLE_TABLES);\n    options.insert(Options::ENABLE_FOOTNOTES);\n    options.insert(Options::ENABLE_STRIKETHROUGH);\n    options.insert(Options::ENABLE_SMART_PUNCTUATION);\n    let parser = Parser::new_ext(input, options);\n    let parser = parser.into_offset_iter();\n    // Translate all links to include the base url.\n    let parser = parser.map(move |(event, range)| match event {\n        Event::Start(Tag::Link {\n            link_type,\n            dest_url,\n            title,\n            id,\n        }) if !matches!(link_type, LinkType::Email) => (\n            Event::Start(Tag::Link {\n                link_type,\n                dest_url: join_url(url.as_ref(), dest_url),\n                title,\n                id,\n            }),\n            range,\n        ),\n        Event::End(TagEnd::Link) => (Event::End(TagEnd::Link), range),\n        _ => (event, range),\n    });\n    Box::new(parser)\n}\n\nfn join_url<'a>(base: Option<&Url>, dest: CowStr<'a>) -> CowStr<'a> {\n    match base {\n        Some(base_url) => {\n            // Absolute URL or page-relative anchor doesn't need to be translated.\n            if dest.contains(':') || dest.starts_with('#') {\n                dest\n            } else {\n                let joined = base_url.join(&dest).unwrap_or_else(|e| {\n                    panic!(\"failed to join URL `{}` to `{}`: {}\", dest, base_url, e)\n                });\n                String::from(joined).into()\n            }\n        }\n        None => dest,\n    }\n}\n\npub fn extract_section(file: &Path) -> Result<Section, Error> {\n    let f = fs::File::open(file).with_context(|| format!(\"could not open `{}`\", file.display()))?;\n    let mut f = io::BufReader::new(f);\n    let mut line = String::new();\n    f.read_line(&mut line)?;\n    if !line.starts_with(\"# \") {\n        bail!(\"expected input file to start with # header\");\n    }\n    let (_name, section) = util::parse_name_and_section(&line[2..].trim()).with_context(|| {\n        format!(\n            \"expected input file to have header with the format `# command-name(1)`, found: `{}`\",\n            line\n        )\n    })?;\n    Ok(section)\n}\n"
  },
  {
    "path": "crates/mdman/src/main.rs",
    "content": "#![allow(clippy::print_stderr)]\n\nuse anyhow::{Context, Error, bail, format_err};\nuse mdman::{Format, ManMap};\nuse std::collections::HashMap;\nuse std::path::{Path, PathBuf};\nuse url::Url;\n\n/// Command-line options.\nstruct Options {\n    format: Format,\n    output_dir: PathBuf,\n    sources: Vec<PathBuf>,\n    url: Option<Url>,\n    man_map: ManMap,\n}\n\nfn main() {\n    if let Err(e) = run() {\n        eprintln!(\"error: {}\", e);\n        for cause in e.chain().skip(1) {\n            eprintln!(\"\\nCaused by:\");\n            for line in cause.to_string().lines() {\n                if line.is_empty() {\n                    eprintln!();\n                } else {\n                    eprintln!(\"  {}\", line);\n                }\n            }\n        }\n        std::process::exit(1);\n    }\n}\n\nfn run() -> Result<(), Error> {\n    let opts = process_args()?;\n    if !opts.output_dir.exists() {\n        std::fs::create_dir_all(&opts.output_dir).with_context(|| {\n            format!(\n                \"failed to create output directory {}\",\n                opts.output_dir.display()\n            )\n        })?;\n    }\n    for source in &opts.sources {\n        let section = mdman::extract_section(source)?;\n        let filename =\n            Path::new(source.file_name().unwrap()).with_extension(opts.format.extension(section));\n        let out_path = opts.output_dir.join(filename);\n        if same_file::is_same_file(source, &out_path).unwrap_or(false) {\n            bail!(\"cannot output to the same file as the source\");\n        }\n        eprintln!(\"Converting {} -> {}\", source.display(), out_path.display());\n        let result = mdman::convert(&source, opts.format, opts.url.clone(), opts.man_map.clone())\n            .with_context(|| format!(\"failed to translate {}\", source.display()))?;\n\n        std::fs::write(out_path, result)?;\n    }\n    Ok(())\n}\n\nfn process_args() -> Result<Options, Error> {\n    let mut format = None;\n    let mut output = None;\n    let mut url = None;\n    let mut man_map: ManMap = HashMap::new();\n    let mut sources = Vec::new();\n    let mut args = std::env::args().skip(1);\n    while let Some(arg) = args.next() {\n        match arg.as_str() {\n            \"-t\" => {\n                format = match args.next().as_deref() {\n                    Some(\"man\") => Some(Format::Man),\n                    Some(\"md\") => Some(Format::Md),\n                    Some(\"txt\") => Some(Format::Text),\n                    Some(s) => bail!(\"unknown output format: {}\", s),\n                    None => bail!(\"-t requires a value (man, md, txt)\"),\n                };\n            }\n            \"-o\" => {\n                output = match args.next() {\n                    Some(s) => Some(PathBuf::from(s)),\n                    None => bail!(\"-o requires a value\"),\n                };\n            }\n            \"--url\" => {\n                url = match args.next() {\n                    Some(s) => {\n                        let url = Url::parse(&s)\n                            .with_context(|| format!(\"could not convert `{}` to a url\", s))?;\n                        if !url.path().ends_with('/') {\n                            bail!(\"url `{}` should end with a /\", url);\n                        }\n                        Some(url)\n                    }\n                    None => bail!(\"--url requires a value\"),\n                }\n            }\n            \"--man\" => {\n                let man = args\n                    .next()\n                    .ok_or_else(|| format_err!(\"--man requires a value\"))?;\n                let parts = man.split_once('=').ok_or_else(|| {\n                    anyhow::format_err!(\"--man expected value with form name:1=link\")\n                })?;\n                let key_parts = parts.0.split_once(':').ok_or_else(|| {\n                    anyhow::format_err!(\"--man expected value with form name:1=link\")\n                })?;\n                let section: u8 = key_parts.1.parse().with_context(|| {\n                    format!(\"expected unsigned integer for section, got `{}`\", parts.1)\n                })?;\n                man_map.insert((key_parts.0.to_string(), section), parts.1.to_string());\n            }\n            s => {\n                sources.push(PathBuf::from(s));\n            }\n        }\n    }\n    if format.is_none() {\n        bail!(\"-t must be specified (man, md, txt)\");\n    }\n    if output.is_none() {\n        bail!(\"-o must be specified (output directory)\");\n    }\n    if sources.is_empty() {\n        bail!(\"at least one source must be specified\");\n    }\n    let opts = Options {\n        format: format.unwrap(),\n        output_dir: output.unwrap(),\n        sources,\n        url,\n        man_map,\n    };\n    Ok(opts)\n}\n"
  },
  {
    "path": "crates/mdman/src/util.rs",
    "content": "///! General utilities.\nuse crate::EventIter;\nuse anyhow::{Context, Error, bail, format_err};\nuse pulldown_cmark::{CowStr, Event, TagEnd};\n\n/// Splits the text `foo(1)` into \"foo\" and `1`.\npub fn parse_name_and_section(text: &str) -> Result<(&str, u8), Error> {\n    let mut i = text.split_terminator(&['(', ')'][..]);\n    let name = i\n        .next()\n        .ok_or_else(|| format_err!(\"man reference must have a name\"))?;\n    let section = i\n        .next()\n        .ok_or_else(|| format_err!(\"man reference must have a section such as mycommand(1)\"))?;\n    if let Some(s) = i.next() {\n        bail!(\n            \"man reference must have the form mycommand(1), got extra part `{}`\",\n            s\n        );\n    }\n    let section: u8 = section\n        .parse()\n        .with_context(|| format!(\"section must be a number, got {}\", section))?;\n    Ok((name, section))\n}\n\n/// Extracts the text from a header after `Tag::Heading` has been received.\npub fn header_text<'e>(parser: &mut EventIter<'e>) -> Result<CowStr<'e>, Error> {\n    let text = match parser.next() {\n        Some((Event::Text(t), _range)) => t,\n        e => bail!(\"expected plain text in man header, got {:?}\", e),\n    };\n    match parser.next() {\n        Some((Event::End(TagEnd::Heading(..)), _range)) => {\n            return Ok(text);\n        }\n        e => bail!(\"expected plain text in man header, got {:?}\", e),\n    }\n}\n\n/// Removes tags from the front and back of a string.\npub fn unwrap<'t>(text: &'t str, front: &str, back: &str) -> &'t str {\n    text.trim().trim_start_matches(front).trim_end_matches(back)\n}\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/formatting.1",
    "content": "'\\\" t\n.TH \"FORMATTING\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.sp\nThis is \\fBnested \\f(BIformatting\\fB \\fBtext\\fB\\fR\\&.\n.SH \"SECOND HEADING\"\nSome text at second level.\n.SS \"Third heading\"\nSome text at third level.\n.SS \"Fourth heading\"\nSome text at fourth level.\n.SH \"Quotes and blocks.\"\nHere are some quotes and blocks.\n.RS 3\n.ll -5\n.sp\nThis is a block quote. Ambidextrously koala apart that prudent blindly alas\nfar amid dear goodness turgid so exact inside oh and alas much fanciful that\ndark on spoon\\-fed adequately insolent walking crud.\n.br\n.RE\n.ll\n.sp\n.RS 4\n.nf\nThis is a code block. Groundhog watchfully sudden firefly some self\\-consciously hotly jeepers satanic after that this parrot this at virtuous\nsome mocking the leaned jeez nightingale as much mallard so because jeez\nturned dear crud grizzly strenuously.\n\n    Indented and should be unmodified.\n.fi\n.RE\n.sp\n.RS 4\n.nf\nThis is an indented code block. Egregiously yikes animatedly since outside beseechingly a badger hey shakily giraffe a one wow one this\ngoodness regarding reindeer so astride before.\n\n    Doubly indented\n.fi\n.RE\n.SH \"Lists\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Ordered list\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Unordered list\n.sp\nWith a second paragraph inside it\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Inner ordered list\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Another\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Eggs\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Milk\n.sp\n.RS 4\n\\h'-04' 5.\\h'+01'Don\\[cq]t start at one.\n.RE\n.sp\n.RS 4\n\\h'-04' 6.\\h'+01'tamarind\n.RE\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Second element\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Third element\n.RE\n.SH \"Breaks\"\nThis has a\n.br\nhard break in it\nand a soft one.\n.SH \"Horizontal rule\"\nThis should contain a line:\n\\l'\\n(.lu'\n.sp\nNice!\n.SH \"Strange characters\"\nHandles escaping for characters\n.sp\n\\&.dot at the start of a line.\n.sp\n\\(rsfBnot really troff\n.sp\nVarious characters \\(rs \\- \\[en] \\[em] \\- | | `\n.sp\n.RS 4\n.nf\ntree\n`\\-\\- example\n    |\\-\\- salamander\n    |   |\\-\\- honey\n    |   `\\-\\- some\n    |\\-\\- fancifully\n    `\\-\\- trout\n.fi\n.RE\n.sp\n\\ \\ \\ \\ non\\-breaking space.\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/formatting.md",
    "content": "# formatting(1)\n\nThis is **nested _formatting_ `text`**.\n\n## SECOND HEADING\n\nSome text at second level.\n\n### Third heading\n\nSome text at third level.\n\n#### Fourth heading\n\nSome text at fourth level.\n\n## Quotes and blocks.\n\nHere are some quotes and blocks.\n\n> This is a block quote. Ambidextrously koala apart that prudent blindly alas\n> far amid dear goodness turgid so exact inside oh and alas much fanciful that\n> dark on spoon-fed adequately insolent walking crud.\n\n```\nThis is a code block. Groundhog watchfully sudden firefly some self-consciously hotly jeepers satanic after that this parrot this at virtuous\nsome mocking the leaned jeez nightingale as much mallard so because jeez\nturned dear crud grizzly strenuously.\n\n    Indented and should be unmodified.\n```\n\n    This is an indented code block. Egregiously yikes animatedly since outside beseechingly a badger hey shakily giraffe a one wow one this\n    goodness regarding reindeer so astride before.\n\n        Doubly indented\n\n## Lists\n\n1. Ordered list\n\n    * Unordered list\n\n      With a second paragraph inside it\n\n        1. Inner ordered list\n\n        1. Another\n\n    * Eggs\n\n    * Milk\n\n        5. Don't start at one.\n        6. tamarind\n\n1. Second element\n\n1. Third element\n\n## Breaks\n\nThis has a\\\nhard break in it\nand a soft one.\n\n## Horizontal rule\n\nThis should contain a line:\n\n---\n\nNice!\n\n## Strange characters\n\nHandles escaping for characters\n\n.dot at the start of a line.\n\n\\fBnot really troff\n\nVarious characters \\ - – — ─ │ ├ └\n\n```\ntree\n└── example\n    ├── salamander\n    │   ├── honey\n    │   └── some\n    ├── fancifully\n    └── trout\n```\n\n&nbsp;&nbsp;&nbsp;&nbsp;non-breaking space.\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/formatting.txt",
    "content": "FORMATTING(1)\n\nThis is nested formatting text.\n\nSECOND HEADING\n       Some text at second level.\n\n   Third heading\n       Some text at third level.\n\n      Fourth heading\n          Some text at fourth level.\n\nQUOTES AND BLOCKS.\n       Here are some quotes and blocks.\n\n          This is a block quote. Ambidextrously koala apart that prudent\n          blindly alas far amid dear goodness turgid so exact inside oh and\n          alas much fanciful that dark on spoon-fed adequately insolent walking\n          crud.\n\n           This is a code block. Groundhog watchfully sudden firefly some self-consciously hotly jeepers satanic after that this parrot this at virtuous\n           some mocking the leaned jeez nightingale as much mallard so because jeez\n           turned dear crud grizzly strenuously.\n           \n               Indented and should be unmodified.\n\n           This is an indented code block. Egregiously yikes animatedly since outside beseechingly a badger hey shakily giraffe a one wow one this\n           goodness regarding reindeer so astride before.\n           \n               Doubly indented\n\nLISTS\n       1. Ordered list\n\n          o  Unordered list\n\n             With a second paragraph inside it\n\n             1. Inner ordered list\n\n             2. Another\n\n          o  Eggs\n\n          o  Milk\n\n             5. Don’t start at one.\n\n             6. tamarind\n\n       2. Second element\n\n       3. Third element\n\nBREAKS\n       This has a\n       hard break in it and a soft one.\n\nHORIZONTAL RULE\n       This should contain a line:\n\n       _________________________________________________________________\n       Nice!\n\nSTRANGE CHARACTERS\n       Handles escaping for characters\n\n       .dot at the start of a line.\n\n       \\fBnot really troff\n\n       Various characters \\ - – — ─ │ ├ └\n\n           tree\n           └── example\n               ├── salamander\n               │   ├── honey\n               │   └── some\n               ├── fancifully\n               └── trout\n\n           non-breaking space.\n\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/links.1",
    "content": "'\\\" t\n.TH \"LINKS\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\nlinks \\- Test of different link kinds\n.SH \"DESCRIPTION\"\nInline link: \\fIinline link\\fR <https://example.com/inline>\n.sp\nReference link: \\fIthis is a link\\fR <https://example.com/bar>\n.sp\nCollapsed: \\fIcollapsed\\fR <https://example.com/collapsed>\n.sp\nShortcut: \\fIshortcut\\fR <https://example.com/shortcut>\n.sp\nAutolink: <https://example.com/auto>\n.sp\nEmail: <foo@example.com>\n.sp\nRelative link: \\fIrelative link\\fR <https://example.org/foo/bar.html>\n.sp\nCollapsed unknown: [collapsed unknown][]\n.sp\nReference unknown: [foo][unknown]\n.sp\nShortcut unknown: [shortcut unknown]\n.sp\n\\fBother\\-cmd\\fR(1)\n.sp\n\\fBlocal\\-cmd\\fR(1)\n.sp\n\\fISome link\\fR <https://example.org/foo.html>\n.sp\n\\fB\\-\\-include\\fR\n.RS 4\nTesting an \\fIincluded link\\fR <https://example.org/included_link.html>\\&.\n.RE\n.SH \"OPTIONS\"\n.sp\n\\fB\\-\\-foo\\-bar\\fR\n.RS 4\nExample \\fIlink\\fR <https://example.org/bar.html>\\&.\nSee \\fBother\\-cmd\\fR(1), \\fBlocal\\-cmd\\fR(1)\n.RE\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/links.md",
    "content": "# links(1)\n\n## NAME\n\nlinks - Test of different link kinds\n\n## DESCRIPTION\n\nInline link: [inline link](https://example.com/inline)\n\nReference link: [this is a link][bar]\n\nCollapsed: [collapsed][]\n\nShortcut: [shortcut]\n\nAutolink: <https://example.com/auto>\n\nEmail: <foo@example.com>\n\nRelative link: [relative link](foo/bar.html)\n\nCollapsed unknown: [collapsed unknown][]\n\nReference unknown: [foo][unknown]\n\nShortcut unknown: [shortcut unknown]\n\n[other-cmd(1)](https://example.org/commands/other-cmd.html)\n\n[local-cmd(1)](local-cmd.html)\n\n[Some link](foo.html)\n\n<dl>\n<dt class=\"option-term\" id=\"option-links---include\"><a class=\"option-anchor\" href=\"#option-links---include\"><code>--include</code></a></dt>\n<dd class=\"option-desc\"><p>Testing an <a href=\"included_link.html\">included link</a>.</p>\n</dd>\n\n</dl>\n\n\n## OPTIONS\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-links---foo-bar\"><a class=\"option-anchor\" href=\"#option-links---foo-bar\"><code>--foo-bar</code></a></dt>\n<dd class=\"option-desc\"><p>Example <a href=\"bar.html\">link</a>.\nSee <a href=\"https://example.org/commands/other-cmd.html\">other-cmd(1)</a>, <a href=\"local-cmd.html\">local-cmd(1)</a></p>\n</dd>\n\n\n</dl>\n\n\n[bar]: https://example.com/bar\n[collapsed]: https://example.com/collapsed\n[shortcut]: https://example.com/shortcut\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/links.txt",
    "content": "LINKS(1)\n\nNAME\n       links - Test of different link kinds\n\nDESCRIPTION\n       Inline link: inline link <https://example.com/inline>\n\n       Reference link: this is a link <https://example.com/bar>\n\n       Collapsed: collapsed <https://example.com/collapsed>\n\n       Shortcut: shortcut <https://example.com/shortcut>\n\n       Autolink: <https://example.com/auto>\n\n       Email: <foo@example.com>\n\n       Relative link: relative link <https://example.org/foo/bar.html>\n\n       Collapsed unknown: [collapsed unknown][]\n\n       Reference unknown: [foo][unknown]\n\n       Shortcut unknown: [shortcut unknown]\n\n       other-cmd(1)\n\n       local-cmd(1)\n\n       Some link <https://example.org/foo.html>\n\n       --include\n           Testing an included link <https://example.org/included_link.html>.\n\nOPTIONS\n       --foo-bar\n           Example link <https://example.org/bar.html>. See other-cmd(1),\n           local-cmd(1)\n\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/options.1",
    "content": "'\\\" t\n.TH \"MY\\-COMMAND\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\nmy\\-command \\- A brief description\n.SH \"SYNOPSIS\"\n\\fBmy\\-command\\fR [\\fB\\-\\-abc\\fR | \\fB\\-\\-xyz\\fR] \\fIname\\fR\n.br\n\\fBmy\\-command\\fR [\\fB\\-f\\fR \\fIfile\\fR]\n.br\n\\fBmy\\-command\\fR (\\fB\\-m\\fR | \\fB\\-M\\fR) [\\fIoldbranch\\fR] \\fInewbranch\\fR\n.br\n\\fBmy\\-command\\fR (\\fB\\-d\\fR | \\fB\\-D\\fR) [\\fB\\-r\\fR] \\fIbranchname\\fR\\[u2026]\n.SH \"DESCRIPTION\"\nA description of the command.\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'One\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Sub one\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Sub two\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Two\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Three\n.RE\n.SH \"OPTIONS\"\n.SS \"Command options\"\n.sp\n\\fB\\-\\-foo\\-bar\\fR\n.RS 4\nDemo \\fIemphasis\\fR, \\fBstrong\\fR, ~~strike~~\n.RE\n.sp\n\\fB\\-p\\fR \\fIspec\\fR, \n\\fB\\-\\-package\\fR \\fIspec\\fR\n.RS 4\nThis has multiple flags.\n.RE\n.sp\n\\fInamed\\-arg\\[u2026]\\fR\n.RS 4\nA named argument.\n.RE\n.sp\n\\fB\\-\\-complex\\fR\n.RS 4\nThis option has a list.\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'alpha\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'beta\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'gamma\n.RE\n.sp\nThen text continues here.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB@\\fR\\fIfilename\\fR\n.RS 4\nLoad from filename.\n.RE\n.sp\n\\fB\\-\\-foo\\fR [\\fIbar\\fR]\n.RS 4\nFlag with optional value.\n.RE\n.sp\n\\fB\\-\\-foo\\fR[\\fB=\\fR\\fIbar\\fR]\n.RS 4\nAlternate syntax for optional value (with required = for disambiguation).\n.RE\n.sp\n\\fB\\-\\-split\\-block\\fR\n.RS 4\nAn option where the description has a \\fBblock statement that is split across multiple lines\\fR\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'An example\n.sp\n.RS 4\n.nf\nmy\\-command \\-\\-abc\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Another example\n.sp\n.RS 4\n.nf\nmy\\-command \\-\\-xyz\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBother\\-command\\fR(1) \\fBabc\\fR(7)\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/options.md",
    "content": "# my-command(1)\n\n## NAME\n\nmy-command - A brief description\n\n## SYNOPSIS\n\n`my-command` [`--abc` | `--xyz`] _name_\\\n`my-command` [`-f` _file_]\\\n`my-command` (`-m` | `-M`) [_oldbranch_] _newbranch_\\\n`my-command` (`-d` | `-D`) [`-r`] _branchname_...\n\n## DESCRIPTION\n\nA description of the command.\n\n* One\n    * Sub one\n    * Sub two\n* Two\n* Three\n\n\n## OPTIONS\n\n### Command options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-options---foo-bar\"><a class=\"option-anchor\" href=\"#option-options---foo-bar\"><code>--foo-bar</code></a></dt>\n<dd class=\"option-desc\"><p>Demo <em>emphasis</em>, <strong>strong</strong>, <del>strike</del></p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-options--p\"><a class=\"option-anchor\" href=\"#option-options--p\"><code>-p</code> <em>spec</em></a></dt>\n<dt class=\"option-term\" id=\"option-options---package\"><a class=\"option-anchor\" href=\"#option-options---package\"><code>--package</code> <em>spec</em></a></dt>\n<dd class=\"option-desc\"><p>This has multiple flags.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-options-named-arg…\"><a class=\"option-anchor\" href=\"#option-options-named-arg…\"><em>named-arg…</em></a></dt>\n<dd class=\"option-desc\"><p>A named argument.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-options---complex\"><a class=\"option-anchor\" href=\"#option-options---complex\"><code>--complex</code></a></dt>\n<dd class=\"option-desc\"><p>This option has a list.</p>\n<ul>\n<li>alpha</li>\n<li>beta</li>\n<li>gamma</li>\n</ul>\n<p>Then text continues here.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-options-@filename\"><a class=\"option-anchor\" href=\"#option-options-@filename\"><code>@</code><em>filename</em></a></dt>\n<dd class=\"option-desc\"><p>Load from filename.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-options---foo\"><a class=\"option-anchor\" href=\"#option-options---foo\"><code>--foo</code> [<em>bar</em>]</a></dt>\n<dd class=\"option-desc\"><p>Flag with optional value.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-options---foo[=bar]\"><a class=\"option-anchor\" href=\"#option-options---foo[=bar]\"><code>--foo</code>[<code>=</code><em>bar</em>]</a></dt>\n<dd class=\"option-desc\"><p>Alternate syntax for optional value (with required = for disambiguation).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-options---split-block\"><a class=\"option-anchor\" href=\"#option-options---split-block\"><code>--split-block</code></a></dt>\n<dd class=\"option-desc\"><p>An option where the description has a <code>block statement that is split across multiple lines</code></p>\n</dd>\n\n\n</dl>\n\n\n## EXAMPLES\n\n1. An example\n\n   ```\n   my-command --abc\n   ```\n\n1. Another example\n\n       my-command --xyz\n\n## SEE ALSO\n[other-command(1)](other-command.html) [abc(7)](abc.html)\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/options.txt",
    "content": "MY-COMMAND(1)\n\nNAME\n       my-command - A brief description\n\nSYNOPSIS\n       my-command [--abc | --xyz] name\n       my-command [-f file]\n       my-command (-m | -M) [oldbranch] newbranch\n       my-command (-d | -D) [-r] branchname…\n\nDESCRIPTION\n       A description of the command.\n\n       o  One\n          o  Sub one\n\n          o  Sub two\n\n       o  Two\n\n       o  Three\n\nOPTIONS\n   Command options\n       --foo-bar\n           Demo emphasis, strong, ~~strike~~\n\n       -p spec, --package spec\n           This has multiple flags.\n\n       named-arg…\n           A named argument.\n\n       --complex\n           This option has a list.\n\n           o  alpha\n\n           o  beta\n\n           o  gamma\n\n           Then text continues here.\n\n   Common Options\n       @filename\n           Load from filename.\n\n       --foo [bar]\n           Flag with optional value.\n\n       --foo[=bar]\n           Alternate syntax for optional value (with required = for\n           disambiguation).\n\n       --split-block\n           An option where the description has a block statement that is split\n           across multiple lines\n\nEXAMPLES\n       1. An example\n\n              my-command --abc\n\n       2. Another example\n\n              my-command --xyz\n\nSEE ALSO\n       other-command(1) abc(7)\n\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/tables.1",
    "content": "'\\\" t\n.TH \"TABLES\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"DESCRIPTION\"\nTesting tables.\n\n.TS\nallbox tab(:);\nlt.\nT{\nSingle col\nT}\nT{\nHi! :)\nT}\n.TE\n.sp\n\n.TS\nallbox tab(:);\nlt lt lt.\nT{\nHeader content\nT}:T{\nWith \\fBformat\\fR \\fItext\\fR\nT}:T{\nAnother column\nT}\nT{\nSome data\nT}:T{\nMore data\nT}:T{\n\nT}\nT{\nExtra long amount of text within a column\nT}:T{\nhi\nT}:T{\nthere\nT}\n.TE\n.sp\n\n.TS\nallbox tab(:);\nlt ct rt.\nT{\nLeft aligned\nT}:T{\nCenter aligned\nT}:T{\nRight aligned\nT}\nT{\nabc\nT}:T{\ndef\nT}:T{\nghi\nT}\n.TE\n.sp\n\n.TS\nallbox tab(:);\nlt ct rt.\nT{\nLeft aligned\nT}:T{\nCenter aligned\nT}:T{\nRight aligned\nT}\nT{\nX\nT}:T{\nX\nT}:T{\nX\nT}\nT{\nExtra long text 123456789012 with mixed widths.\nT}:T{\nExtra long text 123456789012 with mixed widths.\nT}:T{\nExtra long text 123456789012 with mixed widths.\nT}\n.TE\n.sp\n\n.TS\nallbox tab(:);\nlt.\nT{\nLink check\nT}\nT{\n\\fIfoo\\fR <https://example.com/>\nT}\nT{\n<https://example.com/>\nT}\n.TE\n.sp\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/tables.md",
    "content": "# tables(1)\n\n## DESCRIPTION\n\nTesting tables.\n\n| Single col |\n|------------|\n| Hi! :) |\n\n\nHeader content | With `format` *text* | Another column\n---------------|----------------------|----------------\nSome data      | More data            |\nExtra long amount of text within a column | hi | there\n\n\nLeft aligned | Center aligned | Right aligned\n-------------|:--------------:|--------------:\nabc | def | ghi\n\n\nLeft aligned | Center aligned | Right aligned\n-------------|:--------------:|--------------:\nX | X | X\nExtra long text 123456789012 with mixed widths. | Extra long text 123456789012 with mixed widths. | Extra long text 123456789012 with mixed widths.\n\n\n| Link check |\n|------------|\n| [foo] |\n| <https://example.com/> |\n\n\n[foo]: https://example.com/\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/tables.txt",
    "content": "TABLES(1)\n\nDESCRIPTION\n       Testing tables.\n\n       +-------------+\n       | Single col  |\n       +-------------+\n       | Hi! :)      |\n       +-------------+\n\n       +-------------------------------------+----------------+--------------+\n       | Header content                      | With format    | Another      |\n       |                                     | text           | column       |\n       +-------------------------------------+----------------+--------------+\n       | Some data                           | More data      |              |\n       +-------------------------------------+----------------+--------------+\n       | Extra long amount of text within a  | hi             | there        |\n       | column                              |                |              |\n       +-------------------------------------+----------------+--------------+\n\n       +---------------+-----------------+----------------+\n       | Left aligned  | Center aligned  |  Right aligned |\n       +---------------+-----------------+----------------+\n       | abc           |       def       |            ghi |\n       +---------------+-----------------+----------------+\n\n       +-----------------------+-----------------------+-----------------------+\n       | Left aligned          |    Center aligned     |         Right aligned |\n       +-----------------------+-----------------------+-----------------------+\n       | X                     |           X           |                     X |\n       +-----------------------+-----------------------+-----------------------+\n       | Extra long text       |    Extra long text    |       Extra long text |\n       | 123456789012 with     |   123456789012 with   |     123456789012 with |\n       | mixed widths.         |     mixed widths.     |         mixed widths. |\n       +-----------------------+-----------------------+-----------------------+\n\n       +-----------------------+\n       | Link check            |\n       +-----------------------+\n       | foo                   |\n       +-----------------------+\n       | https://example.com/  |\n       +-----------------------+\n\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/vars.7",
    "content": "'\\\" t\n.TH \"VARS\" \"7\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.sp\nBar\n.sp\nbar\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/vars.md",
    "content": "# vars(7)\n\n\n\nBar\n\nbar\n"
  },
  {
    "path": "crates/mdman/tests/compare/expected/vars.txt",
    "content": "VARS(7)\n\nBar\n\nbar\n\n"
  },
  {
    "path": "crates/mdman/tests/compare/formatting.md",
    "content": "# formatting(1)\n\nThis is **nested _formatting_ `text`**.\n\n## SECOND HEADING\n\nSome text at second level.\n\n### Third heading\n\nSome text at third level.\n\n#### Fourth heading\n\nSome text at fourth level.\n\n## Quotes and blocks.\n\nHere are some quotes and blocks.\n\n> This is a block quote. Ambidextrously koala apart that prudent blindly alas\n> far amid dear goodness turgid so exact inside oh and alas much fanciful that\n> dark on spoon-fed adequately insolent walking crud.\n\n```\nThis is a code block. Groundhog watchfully sudden firefly some self-consciously hotly jeepers satanic after that this parrot this at virtuous\nsome mocking the leaned jeez nightingale as much mallard so because jeez\nturned dear crud grizzly strenuously.\n\n    Indented and should be unmodified.\n```\n\n    This is an indented code block. Egregiously yikes animatedly since outside beseechingly a badger hey shakily giraffe a one wow one this\n    goodness regarding reindeer so astride before.\n\n        Doubly indented\n\n## Lists\n\n1. Ordered list\n\n    * Unordered list\n\n      With a second paragraph inside it\n\n        1. Inner ordered list\n\n        1. Another\n\n    * Eggs\n\n    * Milk\n\n        5. Don't start at one.\n        6. tamarind\n\n1. Second element\n\n1. Third element\n\n## Breaks\n\nThis has a\\\nhard break in it\nand a soft one.\n\n## Horizontal rule\n\nThis should contain a line:\n\n---\n\nNice!\n\n## Strange characters\n\nHandles escaping for characters\n\n.dot at the start of a line.\n\n\\fBnot really troff\n\nVarious characters \\ - – — ─ │ ├ └\n\n```\ntree\n└── example\n    ├── salamander\n    │   ├── honey\n    │   └── some\n    ├── fancifully\n    └── trout\n```\n\n&nbsp;&nbsp;&nbsp;&nbsp;non-breaking space.\n"
  },
  {
    "path": "crates/mdman/tests/compare/includes/links-include.md",
    "content": "[Some link](foo.html)\n\n{{#options}}\n{{#option \"`--include`\"}}\nTesting an [included link](included_link.html).\n{{/option}}\n{{/options}}\n"
  },
  {
    "path": "crates/mdman/tests/compare/includes/options-common.md",
    "content": "{{#options}}\n{{#option \"`@`_filename_\"}}\nLoad from filename.\n{{/option}}\n\n{{#option \"`--foo` [_bar_]\"}}\nFlag with optional value.\n{{/option}}\n\n{{#option \"`--foo`[`=`_bar_]\"}}\nAlternate syntax for optional value (with required = for disambiguation).\n{{/option}}\n\n{{#option \"`--split-block`\"}}\nAn option where the description has a `block statement\nthat is split across multiple lines`\n{{/option}}\n\n{{/options}}\n"
  },
  {
    "path": "crates/mdman/tests/compare/links.md",
    "content": "# links(1)\n\n## NAME\n\nlinks - Test of different link kinds\n\n## DESCRIPTION\n\nInline link: [inline link](https://example.com/inline)\n\nReference link: [this is a link][bar]\n\nCollapsed: [collapsed][]\n\nShortcut: [shortcut]\n\nAutolink: <https://example.com/auto>\n\nEmail: <foo@example.com>\n\nRelative link: [relative link](foo/bar.html)\n\nCollapsed unknown: [collapsed unknown][]\n\nReference unknown: [foo][unknown]\n\nShortcut unknown: [shortcut unknown]\n\n{{man \"other-cmd\" 1}}\n\n{{man \"local-cmd\" 1}}\n\n{{> links-include}}\n\n\n## OPTIONS\n\n{{#options}}\n\n{{#option \"`--foo-bar`\"}}\nExample [link](bar.html).\nSee {{man \"other-cmd\" 1}}, {{man \"local-cmd\" 1}}\n{{/option}}\n\n{{/options}}\n\n\n[bar]: https://example.com/bar\n[collapsed]: https://example.com/collapsed\n[shortcut]: https://example.com/shortcut\n"
  },
  {
    "path": "crates/mdman/tests/compare/options.md",
    "content": "# my-command(1)\n\n## NAME\n\nmy-command - A brief description\n\n## SYNOPSIS\n\n`my-command` [`--abc` | `--xyz`] _name_\\\n`my-command` [`-f` _file_]\\\n`my-command` (`-m` | `-M`) [_oldbranch_] _newbranch_\\\n`my-command` (`-d` | `-D`) [`-r`] _branchname_...\n\n## DESCRIPTION\n\nA description of the command.\n\n* One\n    * Sub one\n    * Sub two\n* Two\n* Three\n\n\n## OPTIONS\n\n### Command options\n\n{{#options}}\n\n{{#option \"`--foo-bar`\"}}\nDemo *emphasis*, **strong**, ~~strike~~\n{{/option}}\n\n{{#option \"`-p` _spec_\" \"`--package` _spec_\"}}\nThis has multiple flags.\n{{/option}}\n\n{{#option \"_named-arg..._\"}}\nA named argument.\n{{/option}}\n\n{{#option \"`--complex`\"}}\nThis option has a list.\n\n- alpha\n- beta\n- gamma\n\nThen text continues here.\n{{/option}}\n\n{{/options}}\n\n### Common Options\n\n{{> options-common}}\n\n\n## EXAMPLES\n\n1. An example\n\n   ```\n   my-command --abc\n   ```\n\n1. Another example\n\n       my-command --xyz\n\n## SEE ALSO\n{{man \"other-command\" 1}} {{man \"abc\" 7}}\n"
  },
  {
    "path": "crates/mdman/tests/compare/tables.md",
    "content": "# tables(1)\n\n## DESCRIPTION\n\nTesting tables.\n\n| Single col |\n|------------|\n| Hi! :) |\n\n\nHeader content | With `format` *text* | Another column\n---------------|----------------------|----------------\nSome data      | More data            |\nExtra long amount of text within a column | hi | there\n\n\nLeft aligned | Center aligned | Right aligned\n-------------|:--------------:|--------------:\nabc | def | ghi\n\n\nLeft aligned | Center aligned | Right aligned\n-------------|:--------------:|--------------:\nX | X | X\nExtra long text 123456789012 with mixed widths. | Extra long text 123456789012 with mixed widths. | Extra long text 123456789012 with mixed widths.\n\n\n| Link check |\n|------------|\n| [foo] |\n| <https://example.com/> |\n\n\n[foo]: https://example.com/\n"
  },
  {
    "path": "crates/mdman/tests/compare/vars.md",
    "content": "# vars(7)\n\n{{*set foo=\"Bar\"}}\n\n\n{{foo}}\n\n{{lower foo}}\n"
  },
  {
    "path": "crates/mdman/tests/compare.rs",
    "content": "//! Compares input to expected output.\n\nuse std::path::PathBuf;\n\nuse mdman::{Format, ManMap};\nuse url::Url;\n\nfn run(name: &str) {\n    let input = PathBuf::from(format!(\"tests/compare/{}.md\", name));\n    let url = Some(Url::parse(\"https://example.org/\").unwrap());\n    let mut map = ManMap::new();\n    map.insert(\n        (\"other-cmd\".to_string(), 1),\n        \"https://example.org/commands/other-cmd.html\".to_string(),\n    );\n\n    for &format in &[Format::Man, Format::Md, Format::Text] {\n        let section = mdman::extract_section(&input).unwrap();\n        let result = mdman::convert(&input, format, url.clone(), map.clone()).unwrap();\n        let expected_path = PathBuf::from(format!(\n            \"tests/compare/expected/{}.{}\",\n            name,\n            format.extension(section)\n        ));\n        snapbox::assert_data_eq!(result, snapbox::Data::read_from(&expected_path, None).raw());\n    }\n}\n\nmacro_rules! test( ($name:ident) => (\n    #[test]\n    fn $name() { run(stringify!($name)); }\n) );\n\ntest!(formatting);\ntest!(links);\ntest!(options);\ntest!(tables);\ntest!(vars);\n"
  },
  {
    "path": "crates/mdman/tests/invalid/nested.md",
    "content": "# nested(1)\n\n{{#options}}\n{{#options}}\n{{/options}}\n{{/options}}\n"
  },
  {
    "path": "crates/mdman/tests/invalid/not-inside-options.md",
    "content": "# not-inside-options(1)\n\n{{#option \"`-o`\"}}\nTesting without options block.\n{{/option}}\n"
  },
  {
    "path": "crates/mdman/tests/invalid.rs",
    "content": "//! Tests for errors and invalid input.\n\nuse std::path::PathBuf;\n\nuse mdman::{Format, ManMap};\nuse snapbox::prelude::*;\n\nfn run(name: &str, expected_error: impl IntoData) {\n    let input = PathBuf::from(format!(\"tests/invalid/{}\", name));\n    match mdman::convert(&input, Format::Man, None, ManMap::new()) {\n        Ok(_) => {\n            panic!(\"expected {} to fail\", name);\n        }\n        Err(e) => {\n            snapbox::assert_data_eq!(e.to_string(), expected_error.raw());\n        }\n    }\n}\n\nmacro_rules! test( ($name:ident, $file_name:expr, $error:expr) => (\n    #[test]\n    fn $name() { run($file_name, $error); }\n) );\n\ntest!(\n    nested,\n    \"nested.md\",\n    \"Error rendering \\\"template\\\" line 4, col 1: options blocks cannot be nested\"\n);\n\ntest!(\n    not_inside_options,\n    \"not-inside-options.md\",\n    \"Error rendering \\\"template\\\" line 3, col 1: option must be in options block\"\n);\n"
  },
  {
    "path": "crates/resolver-tests/Cargo.toml",
    "content": "[package]\nname = \"resolver-tests\"\nversion = \"0.0.0\"\nedition.workspace = true\npublish = false\n\n[dependencies]\ncargo.workspace = true\ncargo-platform.workspace = true\ncargo-util-schemas.workspace = true\ncargo-util.workspace = true\nproptest.workspace = true\nvarisat.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/resolver-tests/README.md",
    "content": "# resolver-tests\n\n## The aim\n\nThis crate aims to test the resolution of Cargo's resolver. It implements a [SAT solver](https://en.wikipedia.org/wiki/SAT_solver) to compare with resolution of Cargo's resolver.    \nThis ensures that Cargo's dependency resolution is proven valid by lowering to [SAT problem](https://en.wikipedia.org/wiki/Boolean_satisfiability_problem). \n\n> This crate is maintained by the Cargo team, primarily for use by Cargo\n> and not intended for external use (except as a transitive dependency). This\n> crate may make major changes to its APIs or be deprecated without warning.\n\n## About the test\n\nThe Cargo's resolver is very sensitive to what order it tries to evaluate constraints. This makes it incredibly difficult     \nto be sure that a handful of tests actually covers all the important permutations of decision-making. The tests not only needs    \nto hit all the corner cases, it needs to try all of the orders of evaluation. So we use fuzz testing to cover more permutations.    \n\n"
  },
  {
    "path": "crates/resolver-tests/src/helpers.rs",
    "content": "use std::collections::BTreeMap;\nuse std::fmt::Debug;\nuse std::sync::OnceLock;\n\nuse cargo::core::dependency::DepKind;\nuse cargo::core::{Dependency, GitReference, PackageId, SourceId, Summary};\nuse cargo::util::IntoUrl;\n\npub trait ToDep {\n    fn to_dep(self) -> Dependency;\n    fn opt(self) -> Dependency;\n    fn with(self, features: &[&'static str]) -> Dependency;\n    fn with_default(self) -> Dependency;\n    fn rename(self, name: &str) -> Dependency;\n}\n\nimpl ToDep for &'static str {\n    fn to_dep(self) -> Dependency {\n        Dependency::parse(self, Some(\"1.0.0\"), registry_loc()).unwrap()\n    }\n    fn opt(self) -> Dependency {\n        let mut dep = self.to_dep();\n        dep.set_optional(true);\n        dep\n    }\n    fn with(self, features: &[&'static str]) -> Dependency {\n        let mut dep = self.to_dep();\n        dep.set_default_features(false);\n        dep.set_features(features.into_iter().copied());\n        dep\n    }\n    fn with_default(self) -> Dependency {\n        let mut dep = self.to_dep();\n        dep.set_default_features(true);\n        dep\n    }\n    fn rename(self, name: &str) -> Dependency {\n        let mut dep = self.to_dep();\n        dep.set_explicit_name_in_toml(name);\n        dep\n    }\n}\n\nimpl ToDep for Dependency {\n    fn to_dep(self) -> Dependency {\n        self\n    }\n    fn opt(mut self) -> Dependency {\n        self.set_optional(true);\n        self\n    }\n    fn with(mut self, features: &[&'static str]) -> Dependency {\n        self.set_default_features(false);\n        self.set_features(features.into_iter().copied());\n        self\n    }\n    fn with_default(mut self) -> Dependency {\n        self.set_default_features(true);\n        self\n    }\n    fn rename(mut self, name: &str) -> Dependency {\n        self.set_explicit_name_in_toml(name);\n        self\n    }\n}\n\npub trait ToPkgId {\n    fn to_pkgid(&self) -> PackageId;\n}\n\nimpl ToPkgId for PackageId {\n    fn to_pkgid(&self) -> PackageId {\n        *self\n    }\n}\n\nimpl<'a> ToPkgId for &'a str {\n    fn to_pkgid(&self) -> PackageId {\n        PackageId::try_new(*self, \"1.0.0\", registry_loc()).unwrap()\n    }\n}\n\nimpl<T: AsRef<str>, U: AsRef<str>> ToPkgId for (T, U) {\n    fn to_pkgid(&self) -> PackageId {\n        let (name, vers) = self;\n        PackageId::try_new(name.as_ref(), vers.as_ref(), registry_loc()).unwrap()\n    }\n}\n\n#[macro_export]\nmacro_rules! pkg {\n    ($pkgid:expr => [$($deps:expr),* $(,)? ]) => ({\n        use $crate::helpers::ToDep;\n        let d: Vec<Dependency> = vec![$($deps.to_dep()),*];\n        $crate::helpers::pkg_dep($pkgid, d)\n    });\n\n    ($pkgid:expr) => ({\n        $crate::helpers::pkg($pkgid)\n    })\n}\n\nfn registry_loc() -> SourceId {\n    static EXAMPLE_DOT_COM: OnceLock<SourceId> = OnceLock::new();\n    let example_dot = EXAMPLE_DOT_COM.get_or_init(|| {\n        SourceId::for_registry(&\"https://example.com\".into_url().unwrap()).unwrap()\n    });\n    *example_dot\n}\n\npub fn pkg<T: ToPkgId>(name: T) -> Summary {\n    pkg_dep(name, Vec::new())\n}\n\npub fn pkg_dep<T: ToPkgId>(name: T, dep: Vec<Dependency>) -> Summary {\n    let pkgid = name.to_pkgid();\n    let link = if pkgid.name().ends_with(\"-sys\") {\n        Some(pkgid.name())\n    } else {\n        None\n    };\n    Summary::new(name.to_pkgid(), dep, &BTreeMap::new(), link, None).unwrap()\n}\n\npub fn pkg_dep_with<T: ToPkgId>(\n    name: T,\n    dep: Vec<Dependency>,\n    features: &[(&'static str, &[&'static str])],\n) -> Summary {\n    let pkgid = name.to_pkgid();\n    let link = if pkgid.name().ends_with(\"-sys\") {\n        Some(pkgid.name())\n    } else {\n        None\n    };\n    let features = features\n        .into_iter()\n        .map(|&(name, values)| (name.into(), values.into_iter().map(|&v| v.into()).collect()))\n        .collect();\n    Summary::new(name.to_pkgid(), dep, &features, link, None).unwrap()\n}\n\npub fn pkg_dep_link<T: ToPkgId>(name: T, link: &str, dep: Vec<Dependency>) -> Summary {\n    Summary::new(name.to_pkgid(), dep, &BTreeMap::new(), Some(link), None).unwrap()\n}\n\npub fn pkg_id(name: &str) -> PackageId {\n    PackageId::try_new(name, \"1.0.0\", registry_loc()).unwrap()\n}\n\npub fn pkg_id_source(name: &str, source: &str) -> PackageId {\n    PackageId::try_new(\n        name,\n        \"1.0.0\",\n        SourceId::for_registry(&source.into_url().unwrap()).unwrap(),\n    )\n    .unwrap()\n}\n\nfn pkg_id_loc(name: &str, loc: &str) -> PackageId {\n    let remote = loc.into_url();\n    let master = GitReference::Branch(\"master\".to_string());\n    let source_id = SourceId::for_git(&remote.unwrap(), master).unwrap();\n\n    PackageId::try_new(name, \"1.0.0\", source_id).unwrap()\n}\n\npub fn pkg_loc(name: &str, loc: &str) -> Summary {\n    let link = if name.ends_with(\"-sys\") {\n        Some(name)\n    } else {\n        None\n    };\n    Summary::new(\n        pkg_id_loc(name, loc),\n        Vec::new(),\n        &BTreeMap::new(),\n        link,\n        None,\n    )\n    .unwrap()\n}\n\npub fn remove_dep(sum: &Summary, ind: usize) -> Summary {\n    let mut deps = sum.dependencies().to_vec();\n    deps.remove(ind);\n    // note: more things will need to be copied over in the future, but it works for now.\n    Summary::new(sum.package_id(), deps, &BTreeMap::new(), sum.links(), None).unwrap()\n}\n\npub fn dep(name: &str) -> Dependency {\n    dep_req(name, \"*\")\n}\n\npub fn dep_req(name: &str, req: &str) -> Dependency {\n    Dependency::parse(name, Some(req), registry_loc()).unwrap()\n}\n\npub fn dep_req_kind(name: &str, req: &str, kind: DepKind) -> Dependency {\n    let mut dep = dep_req(name, req);\n    dep.set_kind(kind);\n    dep\n}\n\npub fn dep_req_platform(name: &str, req: &str, platform: &str) -> Dependency {\n    let mut dep = dep_req(name, req);\n    dep.set_platform(Some(platform.parse().unwrap()));\n    dep\n}\n\npub fn dep_loc(name: &str, location: &str) -> Dependency {\n    let url = location.into_url().unwrap();\n    let master = GitReference::Branch(\"master\".to_string());\n    let source_id = SourceId::for_git(&url, master).unwrap();\n    Dependency::parse(name, Some(\"1.0.0\"), source_id).unwrap()\n}\n\npub fn dep_kind(name: &str, kind: DepKind) -> Dependency {\n    let mut dep = dep(name);\n    dep.set_kind(kind);\n    dep\n}\n\npub fn dep_platform(name: &str, platform: &str) -> Dependency {\n    let mut dep = dep(name);\n    dep.set_platform(Some(platform.parse().unwrap()));\n    dep\n}\n\npub fn registry(pkgs: Vec<Summary>) -> Vec<Summary> {\n    pkgs\n}\n\npub fn names<P: ToPkgId>(names: &[P]) -> Vec<PackageId> {\n    names.iter().map(|name| name.to_pkgid()).collect()\n}\n\npub fn loc_names(names: &[(&'static str, &'static str)]) -> Vec<PackageId> {\n    names\n        .iter()\n        .map(|&(name, loc)| pkg_id_loc(name, loc))\n        .collect()\n}\n\n/// Assert `xs` contains `elems`\n#[track_caller]\npub fn assert_contains<A: PartialEq + Debug>(xs: &[A], elems: &[A]) {\n    for elem in elems {\n        assert!(\n            xs.contains(elem),\n            \"missing element\\nset: {xs:?}\\nmissing: {elem:?}\"\n        );\n    }\n}\n\n#[track_caller]\npub fn assert_same<A: PartialEq + Debug>(a: &[A], b: &[A]) {\n    assert_eq!(a.len(), b.len(), \"not equal\\n{a:?}\\n{b:?}\");\n    assert_contains(b, a);\n}\n"
  },
  {
    "path": "crates/resolver-tests/src/lib.rs",
    "content": "//! > This crate is maintained by the Cargo team, primarily for use by Cargo\n//! > and not intended for external use (except as a transitive dependency). This\n//! > crate may make major changes to its APIs or be deprecated without warning.\n\n#![allow(clippy::print_stderr)]\n\npub mod helpers;\npub mod sat;\n\nuse std::cmp::{max, min};\nuse std::collections::{BTreeMap, HashSet};\nuse std::fmt;\nuse std::task::Poll;\nuse std::time::Instant;\n\nuse cargo::core::Resolve;\nuse cargo::core::ResolveVersion;\nuse cargo::core::SourceId;\nuse cargo::core::dependency::DepKind;\nuse cargo::core::resolver::{self, ResolveOpts, VersionOrdering, VersionPreferences};\nuse cargo::core::{Dependency, PackageId, Registry, Summary};\nuse cargo::sources::IndexSummary;\nuse cargo::sources::source::QueryKind;\nuse cargo::util::interning::InternedString;\nuse cargo::util::{CargoResult, GlobalContext};\n\nuse crate::helpers::{ToPkgId, dep_req, dep_req_kind, pkg_dep, pkg_id};\nuse crate::sat::SatResolver;\n\nuse proptest::collection::{btree_map, vec};\nuse proptest::prelude::*;\nuse proptest::sample::Index;\nuse proptest::string::string_regex;\n\npub fn resolve(deps: Vec<Dependency>, registry: &[Summary]) -> CargoResult<Vec<PackageId>> {\n    Ok(\n        resolve_with_global_context(deps, registry, &GlobalContext::default().unwrap())?\n            .into_iter()\n            .map(|(pkg, _)| pkg)\n            .collect(),\n    )\n}\n\npub fn resolve_and_validated(\n    deps: Vec<Dependency>,\n    registry: &[Summary],\n    sat_resolver: &mut SatResolver,\n) -> CargoResult<Vec<(PackageId, Vec<InternedString>)>> {\n    resolve_and_validated_raw(deps, registry, pkg_id(\"root\"), sat_resolver)\n}\n\n// Verify that the resolution of cargo resolver can pass the verification of SAT\npub fn resolve_and_validated_raw(\n    deps: Vec<Dependency>,\n    registry: &[Summary],\n    root_pkg_id: PackageId,\n    sat_resolver: &mut SatResolver,\n) -> CargoResult<Vec<(PackageId, Vec<InternedString>)>> {\n    let resolve = resolve_with_global_context_raw(\n        deps.clone(),\n        registry,\n        root_pkg_id,\n        &GlobalContext::default().unwrap(),\n    );\n\n    match resolve {\n        Err(e) => {\n            if sat_resolver.sat_resolve(&deps) {\n                panic!(\n                    \"`resolve()` returned an error but the sat resolver thinks this will work:\\n{}\",\n                    sat_resolver.used_packages().unwrap()\n                );\n            }\n            Err(e)\n        }\n        Ok(resolve) => {\n            let mut stack = vec![root_pkg_id];\n            let mut used = HashSet::new();\n            let mut links = HashSet::new();\n            while let Some(p) = stack.pop() {\n                assert!(resolve.contains(&p));\n                if used.insert(p) {\n                    // in the tests all `links` crates end in `-sys`\n                    if p.name().ends_with(\"-sys\") {\n                        assert!(links.insert(p.name()));\n                    }\n                    stack.extend(resolve.deps(p).map(|(dp, deps)| {\n                        for d in deps {\n                            assert!(d.matches_id(dp));\n                        }\n                        dp\n                    }));\n                }\n            }\n            let out = collect_features(&resolve);\n            assert_eq!(out.len(), used.len());\n\n            if !sat_resolver.sat_is_valid_solution(&out) {\n                panic!(\n                    \"`resolve()` thinks this will work, but the solution is \\\n                     invalid according to the sat resolver:\\n{resolve:?}\",\n                );\n            }\n            Ok(out)\n        }\n    }\n}\n\nfn collect_features(resolve: &Resolve) -> Vec<(PackageId, Vec<InternedString>)> {\n    resolve\n        .sort()\n        .iter()\n        .map(|&pkg| (pkg, resolve.features(pkg).to_vec()))\n        .collect()\n}\n\npub fn resolve_with_global_context(\n    deps: Vec<Dependency>,\n    registry: &[Summary],\n    gctx: &GlobalContext,\n) -> CargoResult<Vec<(PackageId, Vec<InternedString>)>> {\n    let resolve = resolve_with_global_context_raw(deps, registry, pkg_id(\"root\"), gctx)?;\n    Ok(collect_features(&resolve))\n}\n\npub fn resolve_with_global_context_raw(\n    deps: Vec<Dependency>,\n    registry: &[Summary],\n    root_pkg_id: PackageId,\n    gctx: &GlobalContext,\n) -> CargoResult<Resolve> {\n    struct MyRegistry<'a> {\n        list: &'a [Summary],\n        used: HashSet<PackageId>,\n    }\n    impl<'a> Registry for MyRegistry<'a> {\n        fn query(\n            &mut self,\n            dep: &Dependency,\n            kind: QueryKind,\n            f: &mut dyn FnMut(IndexSummary),\n        ) -> Poll<CargoResult<()>> {\n            for summary in self.list.iter() {\n                let matched = match kind {\n                    QueryKind::Exact => dep.matches(summary),\n                    QueryKind::RejectedVersions => dep.matches(summary),\n                    QueryKind::AlternativeNames => true,\n                    QueryKind::Normalized => true,\n                };\n                if matched {\n                    self.used.insert(summary.package_id());\n                    f(IndexSummary::Candidate(summary.clone()));\n                }\n            }\n            Poll::Ready(Ok(()))\n        }\n\n        fn describe_source(&self, _src: SourceId) -> String {\n            String::new()\n        }\n\n        fn is_replaced(&self, _src: SourceId) -> bool {\n            false\n        }\n\n        fn block_until_ready(&mut self) -> CargoResult<()> {\n            Ok(())\n        }\n    }\n    impl<'a> Drop for MyRegistry<'a> {\n        fn drop(&mut self) {\n            if std::thread::panicking() && self.list.len() != self.used.len() {\n                // we found a case that causes a panic and did not use all of the input.\n                // lets print the part of the input that was used for minimization.\n                eprintln!(\n                    \"Part used before drop: {:?}\",\n                    PrettyPrintRegistry(\n                        self.list\n                            .iter()\n                            .filter(|s| { self.used.contains(&s.package_id()) })\n                            .cloned()\n                            .collect()\n                    )\n                );\n            }\n        }\n    }\n    let mut registry = MyRegistry {\n        list: registry,\n        used: HashSet::new(),\n    };\n\n    let root_summary =\n        Summary::new(root_pkg_id, deps, &BTreeMap::new(), None::<&String>, None).unwrap();\n\n    let opts = ResolveOpts::everything();\n\n    let start = Instant::now();\n    let mut version_prefs = VersionPreferences::default();\n    if gctx.cli_unstable().minimal_versions {\n        version_prefs.version_ordering(VersionOrdering::MinimumVersionsFirst)\n    }\n\n    let resolve = resolver::resolve(\n        &[(root_summary, opts)],\n        &[],\n        &mut registry,\n        &version_prefs,\n        ResolveVersion::with_rust_version(None),\n        Some(gctx),\n    );\n\n    // The largest test in our suite takes less then 30 secs.\n    // So let's fail the test if we have been running for more than 60 secs.\n    assert!(start.elapsed().as_secs() < 60);\n    resolve\n}\n\n/// By default `Summary` and `Dependency` have a very verbose `Debug` representation.\n/// This replaces with a representation that uses constructors from this file.\n///\n/// If `registry_strategy` is improved to modify more fields\n/// then this needs to update to display the corresponding constructor.\npub struct PrettyPrintRegistry(pub Vec<Summary>);\n\nimpl fmt::Debug for PrettyPrintRegistry {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"vec![\")?;\n        for s in &self.0 {\n            if s.dependencies().is_empty() {\n                write!(f, \"pkg!((\\\"{}\\\", \\\"{}\\\")),\", s.name(), s.version())?;\n            } else {\n                write!(f, \"pkg!((\\\"{}\\\", \\\"{}\\\") => [\", s.name(), s.version())?;\n                for d in s.dependencies() {\n                    if d.kind() == DepKind::Normal\n                        && &d.version_req().to_string() == \"*\"\n                        && !d.is_public()\n                    {\n                        write!(f, \"dep(\\\"{}\\\"),\", d.name_in_toml())?;\n                    } else if d.kind() == DepKind::Normal && !d.is_public() {\n                        write!(\n                            f,\n                            \"dep_req(\\\"{}\\\", \\\"{}\\\"),\",\n                            d.name_in_toml(),\n                            d.version_req()\n                        )?;\n                    } else {\n                        write!(\n                            f,\n                            \"dep_req_kind(\\\"{}\\\", \\\"{}\\\", {}, {}),\",\n                            d.name_in_toml(),\n                            d.version_req(),\n                            match d.kind() {\n                                DepKind::Development => \"DepKind::Development\",\n                                DepKind::Build => \"DepKind::Build\",\n                                DepKind::Normal => \"DepKind::Normal\",\n                            },\n                            d.is_public()\n                        )?;\n                    }\n                }\n                write!(f, \"]),\")?;\n            }\n        }\n        write!(f, \"]\")\n    }\n}\n\n/// This generates a random registry index.\n/// Unlike `vec((Name, Ver, vec((Name, VerRq), ..), ..)`,\n/// this strategy has a high probability of having valid dependencies.\npub fn registry_strategy(\n    max_crates: usize,\n    max_versions: usize,\n    shrinkage: usize,\n) -> impl Strategy<Value = PrettyPrintRegistry> {\n    let name = string_regex(\"[A-Za-z][A-Za-z0-9_-]*(-sys)?\").unwrap();\n\n    let raw_version = ..max_versions.pow(3);\n    let version_from_raw = move |r: usize| {\n        let major = ((r / max_versions) / max_versions) % max_versions;\n        let minor = (r / max_versions) % max_versions;\n        let patch = r % max_versions;\n        format!(\"{}.{}.{}\", major, minor, patch)\n    };\n\n    // If this is false then the crate will depend on the nonexistent \"bad\"\n    // instead of the complex set we generated for it.\n    let allow_deps = prop::bool::weighted(0.99);\n\n    let list_of_versions =\n        btree_map(raw_version, allow_deps, 1..=max_versions).prop_map(move |ver| {\n            ver.into_iter()\n                .map(|a| (version_from_raw(a.0), a.1))\n                .collect::<Vec<_>>()\n        });\n\n    let list_of_crates_with_versions =\n        btree_map(name, list_of_versions, 1..=max_crates).prop_map(|mut vers| {\n            // root is the name of the thing being compiled\n            // so it would be confusing to have it in the index\n            vers.remove(\"root\");\n            // bad is a name reserved for a dep that won't work\n            vers.remove(\"bad\");\n            vers\n        });\n\n    // each version of each crate can depend on each crate smaller than it.\n    // In theory shrinkage should be 2, but in practice we get better trees with a larger value.\n    let max_deps = max_versions * (max_crates * (max_crates - 1)) / shrinkage;\n\n    let raw_version_range = (any::<Index>(), any::<Index>());\n    let raw_dependency = (any::<Index>(), any::<Index>(), raw_version_range, 0..=1);\n\n    fn order_index(a: Index, b: Index, size: usize) -> (usize, usize) {\n        let (a, b) = (a.index(size), b.index(size));\n        (min(a, b), max(a, b))\n    }\n\n    let list_of_raw_dependency = vec(raw_dependency, ..=max_deps);\n\n    // By default a package depends only on other packages that have a smaller name,\n    // this helps make sure that all things in the resulting index are DAGs.\n    // If this is true then the DAG is maintained with grater instead.\n    let reverse_alphabetical = any::<bool>().no_shrink();\n\n    (\n        list_of_crates_with_versions,\n        list_of_raw_dependency,\n        reverse_alphabetical,\n    )\n        .prop_map(\n            |(crate_vers_by_name, raw_dependencies, reverse_alphabetical)| {\n                let list_of_pkgid: Vec<_> = crate_vers_by_name\n                    .iter()\n                    .flat_map(|(name, vers)| vers.iter().map(move |x| ((name.as_str(), &x.0), x.1)))\n                    .collect();\n                let len_all_pkgid = list_of_pkgid.len();\n                let mut dependency_by_pkgid = vec![vec![]; len_all_pkgid];\n                for (a, b, (c, d), k) in raw_dependencies {\n                    let (a, b) = order_index(a, b, len_all_pkgid);\n                    let (a, b) = if reverse_alphabetical { (b, a) } else { (a, b) };\n                    let ((dep_name, _), _) = list_of_pkgid[a];\n                    if (list_of_pkgid[b].0).0 == dep_name {\n                        continue;\n                    }\n                    let s = &crate_vers_by_name[dep_name];\n                    let s_last_index = s.len() - 1;\n                    let (c, d) = order_index(c, d, s.len());\n\n                    dependency_by_pkgid[b].push(dep_req_kind(\n                        dep_name,\n                        &if c == 0 && d == s_last_index {\n                            \"*\".to_string()\n                        } else if c == 0 {\n                            format!(\"<={}\", s[d].0)\n                        } else if d == s_last_index {\n                            format!(\">={}\", s[c].0)\n                        } else if c == d {\n                            format!(\"={}\", s[c].0)\n                        } else {\n                            format!(\">={}, <={}\", s[c].0, s[d].0)\n                        },\n                        match k {\n                            0 => DepKind::Normal,\n                            1 => DepKind::Build,\n                            // => DepKind::Development, // Development has no impact so don't gen\n                            _ => panic!(\"bad index for DepKind\"),\n                        },\n                    ))\n                }\n\n                let mut out: Vec<Summary> = list_of_pkgid\n                    .into_iter()\n                    .zip(dependency_by_pkgid.into_iter())\n                    .map(|(((name, ver), allow_deps), deps)| {\n                        pkg_dep(\n                            (name, ver).to_pkgid(),\n                            if !allow_deps {\n                                vec![dep_req(\"bad\", \"*\")]\n                            } else {\n                                let mut deps = deps;\n                                deps.sort_by_key(|d| d.name_in_toml());\n                                deps.dedup_by_key(|d| d.name_in_toml());\n                                deps\n                            },\n                        )\n                    })\n                    .collect();\n\n                if reverse_alphabetical {\n                    // make sure the complicated cases are at the end\n                    out.reverse();\n                }\n\n                PrettyPrintRegistry(out)\n            },\n        )\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::helpers::registry;\n\n    #[test]\n    fn meta_test_deep_pretty_print_registry() {\n        assert_eq!(\n            &format!(\n                \"{:?}\",\n                PrettyPrintRegistry(vec![\n                    pkg!((\"foo\", \"1.0.1\") => [dep_req(\"bar\", \"1\")]),\n                    pkg!((\"foo\", \"1.0.0\") => [dep_req(\"bar\", \"2\")]),\n                    pkg!((\"foo\", \"2.0.0\") => [dep_req(\"bar\", \"*\")]),\n                    pkg!((\"bar\", \"1.0.0\") => [dep_req(\"baz\", \"=1.0.2\"),\n                                          dep_req(\"other\", \"1\")]),\n                    pkg!((\"bar\", \"2.0.0\") => [dep_req(\"baz\", \"=1.0.1\")]),\n                    pkg!((\"baz\", \"1.0.2\") => [dep_req(\"other\", \"2\")]),\n                    pkg!((\"baz\", \"1.0.1\")),\n                    pkg!((\"cat\", \"1.0.2\") => [dep_req_kind(\"other\", \"2\", DepKind::Build)]),\n                    pkg!((\"cat\", \"1.0.3\") => [dep_req_kind(\"other\", \"2\", DepKind::Development)]),\n                    pkg!((\"dep_req\", \"1.0.0\")),\n                    pkg!((\"dep_req\", \"2.0.0\")),\n                ])\n            ),\n            \"vec![pkg!((\\\"foo\\\", \\\"1.0.1\\\") => [dep_req(\\\"bar\\\", \\\"^1\\\"),]),\\\n         pkg!((\\\"foo\\\", \\\"1.0.0\\\") => [dep_req(\\\"bar\\\", \\\"^2\\\"),]),\\\n         pkg!((\\\"foo\\\", \\\"2.0.0\\\") => [dep(\\\"bar\\\"),]),\\\n         pkg!((\\\"bar\\\", \\\"1.0.0\\\") => [dep_req(\\\"baz\\\", \\\"=1.0.2\\\"),dep_req(\\\"other\\\", \\\"^1\\\"),]),\\\n         pkg!((\\\"bar\\\", \\\"2.0.0\\\") => [dep_req(\\\"baz\\\", \\\"=1.0.1\\\"),]),\\\n         pkg!((\\\"baz\\\", \\\"1.0.2\\\") => [dep_req(\\\"other\\\", \\\"^2\\\"),]),\\\n         pkg!((\\\"baz\\\", \\\"1.0.1\\\")),\\\n         pkg!((\\\"cat\\\", \\\"1.0.2\\\") => [dep_req_kind(\\\"other\\\", \\\"^2\\\", DepKind::Build, false),]),\\\n         pkg!((\\\"cat\\\", \\\"1.0.3\\\") => [dep_req_kind(\\\"other\\\", \\\"^2\\\", DepKind::Development, false),]),\\\n         pkg!((\\\"dep_req\\\", \\\"1.0.0\\\")),\\\n         pkg!((\\\"dep_req\\\", \\\"2.0.0\\\")),]\"\n        )\n    }\n\n    /// This test is to test the generator to ensure\n    /// that it makes registries with large dependency trees\n    #[test]\n    fn meta_test_deep_trees_from_strategy() {\n        use proptest::strategy::ValueTree;\n        use proptest::test_runner::TestRunner;\n\n        let mut dis = [0; 21];\n\n        let strategy = registry_strategy(50, 20, 60);\n        let mut test_runner = TestRunner::deterministic();\n        for _ in 0..128 {\n            let PrettyPrintRegistry(input) = strategy\n                .new_tree(&mut TestRunner::new_with_rng(\n                    Default::default(),\n                    test_runner.new_rng(),\n                ))\n                .unwrap()\n                .current();\n            let reg = registry(input.clone());\n            for this in input.iter().rev().take(10) {\n                let res = resolve(\n                    vec![dep_req(&this.name(), &format!(\"={}\", this.version()))],\n                    &reg,\n                );\n                dis[res\n                    .as_ref()\n                    .map(|x| min(x.len(), dis.len()) - 1)\n                    .unwrap_or(0)] += 1;\n                if dis.iter().all(|&x| x > 0) {\n                    return;\n                }\n            }\n        }\n\n        panic!(\n            \"In 1280 tries we did not see a wide enough distribution \\\n             of dependency trees! dis: {dis:?}\"\n        );\n    }\n\n    /// This test is to test the generator to ensure\n    /// that it makes registries that include multiple versions of the same library\n    #[test]\n    fn meta_test_multiple_versions_strategy() {\n        use proptest::strategy::ValueTree;\n        use proptest::test_runner::TestRunner;\n\n        let mut dis = [0; 10];\n\n        let strategy = registry_strategy(50, 20, 60);\n        let mut test_runner = TestRunner::deterministic();\n        for _ in 0..128 {\n            let PrettyPrintRegistry(input) = strategy\n                .new_tree(&mut TestRunner::new_with_rng(\n                    Default::default(),\n                    test_runner.new_rng(),\n                ))\n                .unwrap()\n                .current();\n            let reg = registry(input.clone());\n            for this in input.iter().rev().take(10) {\n                let res = resolve(\n                    vec![dep_req(&this.name(), &format!(\"={}\", this.version()))],\n                    &reg,\n                );\n                if let Ok(mut res) = res {\n                    let res_len = res.len();\n                    res.sort_by_key(|s| s.name());\n                    res.dedup_by_key(|s| s.name());\n                    dis[min(res_len - res.len(), dis.len() - 1)] += 1;\n                }\n                if dis.iter().all(|&x| x > 0) {\n                    return;\n                }\n            }\n        }\n        panic!(\n            \"In 1280 tries we did not see a wide enough distribution \\\n             of multiple versions of the same library! dis: {dis:?}\"\n        );\n    }\n}\n"
  },
  {
    "path": "crates/resolver-tests/src/sat.rs",
    "content": "use std::collections::hash_map::Entry;\nuse std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};\nuse std::fmt::Write;\n\nuse cargo::core::dependency::DepKind;\nuse cargo::core::{Dependency, FeatureMap, FeatureValue, PackageId, Summary};\nuse cargo::util::interning::{INTERNED_DEFAULT, InternedString};\nuse cargo_platform::Platform;\nuse varisat::ExtendFormula;\n\nconst fn num_bits<T>() -> usize {\n    std::mem::size_of::<T>() * 8\n}\n\nfn log_bits(x: usize) -> usize {\n    if x == 0 {\n        return 0;\n    }\n    assert!(x > 0);\n    (num_bits::<usize>() as u32 - x.leading_zeros()) as usize\n}\n\n/// At this point is possible to select every version of every package.\n///\n/// So we need to mark certain versions as incompatible with each other.\n/// We could add a clause not A, not B for all A and B that are incompatible,\nfn sat_at_most_one(solver: &mut varisat::Solver<'_>, vars: &[varisat::Var]) {\n    if vars.len() <= 1 {\n        return;\n    } else if vars.len() == 2 {\n        solver.add_clause(&[vars[0].negative(), vars[1].negative()]);\n        return;\n    } else if vars.len() == 3 {\n        solver.add_clause(&[vars[0].negative(), vars[1].negative()]);\n        solver.add_clause(&[vars[0].negative(), vars[2].negative()]);\n        solver.add_clause(&[vars[1].negative(), vars[2].negative()]);\n        return;\n    }\n    // There are more efficient ways to do it for large numbers of versions.\n    //\n    // Use the \"Binary Encoding\" from\n    // https://www.it.uu.se/research/group/astra/ModRef10/papers/Alan%20M.%20Frisch%20and%20Paul%20A.%20Giannoros.%20SAT%20Encodings%20of%20the%20At-Most-k%20Constraint%20-%20ModRef%202010.pdf\n    let bits: Vec<varisat::Var> = solver.new_var_iter(log_bits(vars.len())).collect();\n    for (i, p) in vars.iter().enumerate() {\n        for b in 0..bits.len() {\n            solver.add_clause(&[p.negative(), bits[b].lit(((1 << b) & i) > 0)]);\n        }\n    }\n}\n\nfn sat_at_most_one_by_key<K: std::hash::Hash + Eq>(\n    solver: &mut varisat::Solver<'_>,\n    data: impl Iterator<Item = (K, varisat::Var)>,\n) -> HashMap<K, Vec<varisat::Var>> {\n    // No two packages with the same keys set\n    let mut by_keys: HashMap<K, Vec<varisat::Var>> = HashMap::new();\n    for (p, v) in data {\n        by_keys.entry(p).or_default().push(v)\n    }\n    for key in by_keys.values() {\n        sat_at_most_one(solver, key);\n    }\n    by_keys\n}\n\ntype DependencyVarMap<'a> =\n    HashMap<InternedString, HashMap<(DepKind, Option<&'a Platform>), varisat::Var>>;\n\ntype DependencyFeatureVarMap<'a> = HashMap<\n    InternedString,\n    HashMap<(DepKind, Option<&'a Platform>), HashMap<InternedString, varisat::Var>>,\n>;\n\nfn create_dependencies_vars<'a>(\n    solver: &mut varisat::Solver<'_>,\n    pkg_var: varisat::Var,\n    pkg_dependencies: &'a [Dependency],\n    pkg_features: &FeatureMap,\n) -> (DependencyVarMap<'a>, DependencyFeatureVarMap<'a>) {\n    let mut var_for_is_dependencies_used = DependencyVarMap::new();\n    let mut var_for_is_dependencies_features_used = DependencyFeatureVarMap::new();\n\n    for dep in pkg_dependencies {\n        let (name, kind, platform) = (dep.name_in_toml(), dep.kind(), dep.platform());\n\n        var_for_is_dependencies_used\n            .entry(name)\n            .or_default()\n            .insert((kind, platform), solver.new_var());\n\n        let dep_feature_vars = var_for_is_dependencies_features_used\n            .entry(name)\n            .or_default()\n            .entry((kind, platform))\n            .or_default();\n\n        for &feature_name in dep.features() {\n            if let Entry::Vacant(entry) = dep_feature_vars.entry(feature_name) {\n                entry.insert(solver.new_var());\n            }\n        }\n    }\n\n    for feature_values in pkg_features.values() {\n        for feature_value in feature_values {\n            let FeatureValue::DepFeature {\n                dep_name,\n                dep_feature,\n                weak: _,\n            } = *feature_value\n            else {\n                continue;\n            };\n\n            for dep_feature_vars in var_for_is_dependencies_features_used\n                .get_mut(&dep_name)\n                .expect(\"feature dep name exists\")\n                .values_mut()\n            {\n                if let Entry::Vacant(entry) = dep_feature_vars.entry(dep_feature) {\n                    entry.insert(solver.new_var());\n                }\n            }\n        }\n    }\n\n    // If a package dependency is used, then the package is used\n    for dep_var_map in var_for_is_dependencies_used.values() {\n        for dep_var in dep_var_map.values() {\n            solver.add_clause(&[dep_var.negative(), pkg_var.positive()]);\n        }\n    }\n\n    // If a dependency feature is used, then the dependency is used\n    for (&dep_name, map) in &mut var_for_is_dependencies_features_used {\n        for (&(dep_kind, dep_platform), dep_feature_var_map) in map {\n            for dep_feature_var in dep_feature_var_map.values() {\n                let dep_var_map = &var_for_is_dependencies_used[&dep_name];\n                let dep_var = dep_var_map[&(dep_kind, dep_platform)];\n                solver.add_clause(&[dep_feature_var.negative(), dep_var.positive()]);\n            }\n        }\n    }\n\n    (\n        var_for_is_dependencies_used,\n        var_for_is_dependencies_features_used,\n    )\n}\n\nfn process_pkg_dependencies(\n    solver: &mut varisat::Solver<'_>,\n    var_for_is_dependencies_used: &DependencyVarMap<'_>,\n    var_for_is_dependencies_features_used: &DependencyFeatureVarMap<'_>,\n    pkg_var: varisat::Var,\n    pkg_dependencies: &[Dependency],\n) {\n    // Add clauses for package dependencies\n    for dep in pkg_dependencies {\n        let (name, kind, platform) = (dep.name_in_toml(), dep.kind(), dep.platform());\n        let dep_var_map = &var_for_is_dependencies_used[&name];\n        let dep_var = dep_var_map[&(kind, platform)];\n\n        if !dep.is_optional() {\n            solver.add_clause(&[pkg_var.negative(), dep_var.positive()]);\n        }\n\n        for &feature_name in dep.features() {\n            let dep_feature_var =\n                &var_for_is_dependencies_features_used[&name][&(kind, platform)][&feature_name];\n\n            solver.add_clause(&[dep_var.negative(), dep_feature_var.positive()]);\n        }\n    }\n}\n\nfn process_pkg_features(\n    solver: &mut varisat::Solver<'_>,\n    var_for_is_dependencies_used: &DependencyVarMap<'_>,\n    var_for_is_dependencies_features_used: &DependencyFeatureVarMap<'_>,\n    pkg_feature_var_map: &HashMap<InternedString, varisat::Var>,\n    pkg_dependencies: &[Dependency],\n    pkg_features: &FeatureMap,\n) {\n    let optional_dependencies = pkg_dependencies\n        .iter()\n        .filter(|dep| dep.is_optional())\n        .map(|dep| (dep.kind(), dep.platform(), dep.name_in_toml()))\n        .collect::<HashSet<_>>();\n\n    // Add clauses for package features\n    for (&feature_name, feature_values) in pkg_features {\n        for feature_value in feature_values {\n            let pkg_feature_var = pkg_feature_var_map[&feature_name];\n\n            match *feature_value {\n                FeatureValue::Feature(other_feature_name) => {\n                    solver.add_clause(&[\n                        pkg_feature_var.negative(),\n                        pkg_feature_var_map[&other_feature_name].positive(),\n                    ]);\n                }\n                FeatureValue::Dep { dep_name } => {\n                    // Add a clause for each dependency with the provided name (normal/build/dev with target)\n                    for (&(dep_kind, _), &dep_var) in &var_for_is_dependencies_used[&dep_name] {\n                        if dep_kind == DepKind::Development {\n                            continue;\n                        }\n                        solver.add_clause(&[pkg_feature_var.negative(), dep_var.positive()]);\n                    }\n                }\n                FeatureValue::DepFeature {\n                    dep_name,\n                    dep_feature: dep_feature_name,\n                    weak,\n                } => {\n                    // Behavior of the feature:\n                    // * if dependency `dep_name` is not optional, its feature `\"dep_feature_name\"` is activated.\n                    // * if dependency `dep_name` is optional:\n                    //     - if this is a weak dependency feature:\n                    //         - feature `\"dep_feature_name\"` of dependency `dep_name` is activated if `dep_name` has been activated via another feature.\n                    //     - if this is not a weak dependency feature:\n                    //         - feature `dep_name` is activated if it exists.\n                    //         - dependency `dep_name` is activated.\n                    //         - feature `\"dep_feature_name\"` of dependency `dep_name` is activated.\n\n                    // Add clauses for each dependency with the provided name (normal/build/dev with target)\n                    let dep_var_map = &var_for_is_dependencies_used[&dep_name];\n                    for (&(dep_kind, dep_platform), &dep_var) in dep_var_map {\n                        if dep_kind == DepKind::Development {\n                            continue;\n                        }\n\n                        let dep_feature_var = &var_for_is_dependencies_features_used[&dep_name]\n                            [&(dep_kind, dep_platform)][&dep_feature_name];\n\n                        solver.add_clause(&[\n                            pkg_feature_var.negative(),\n                            dep_var.negative(),\n                            dep_feature_var.positive(),\n                        ]);\n\n                        let key = (dep_kind, dep_platform, dep_name);\n                        if !weak && optional_dependencies.contains(&key) {\n                            solver.add_clause(&[pkg_feature_var.negative(), dep_var.positive()]);\n\n                            if let Some(other_feature_var) = pkg_feature_var_map.get(&dep_name) {\n                                solver.add_clause(&[\n                                    pkg_feature_var.negative(),\n                                    other_feature_var.positive(),\n                                ]);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\nfn process_compatible_dep_summaries(\n    solver: &mut varisat::Solver<'_>,\n    var_for_is_dependencies_used: &DependencyVarMap<'_>,\n    var_for_is_dependencies_features_used: &DependencyFeatureVarMap<'_>,\n    var_for_is_packages_used: &HashMap<PackageId, varisat::Var>,\n    var_for_is_packages_features_used: &HashMap<PackageId, HashMap<InternedString, varisat::Var>>,\n    by_name: &HashMap<InternedString, Vec<Summary>>,\n    pkg_dependencies: &[Dependency],\n    check_dev_dependencies: bool,\n) {\n    for dep in pkg_dependencies {\n        if dep.kind() == DepKind::Development && !check_dev_dependencies {\n            continue;\n        }\n\n        let (name, kind, platform) = (dep.name_in_toml(), dep.kind(), dep.platform());\n        let dep_var = var_for_is_dependencies_used[&name][&(kind, platform)];\n        let dep_feature_var_map = &var_for_is_dependencies_features_used[&name][&(kind, platform)];\n\n        let compatible_pkg_ids = by_name\n            .get(&dep.package_name())\n            .into_iter()\n            .flatten()\n            .filter(|s| dep.matches(s))\n            .filter(|s| dep.features().iter().all(|f| s.features().contains_key(f)))\n            .map(|s| s.package_id())\n            .collect::<Vec<_>>();\n\n        // At least one compatible package should be activated\n        let dep_clause = compatible_pkg_ids\n            .iter()\n            .map(|id| var_for_is_packages_used[&id].positive())\n            .chain([dep_var.negative()])\n            .collect::<Vec<_>>();\n\n        solver.add_clause(&dep_clause);\n\n        for (&feature_name, &dep_feature_var) in dep_feature_var_map {\n            // At least one compatible package with the additional feature should be activated\n            let dep_feature_clause = compatible_pkg_ids\n                .iter()\n                .filter_map(|id| var_for_is_packages_features_used[&id].get(&feature_name))\n                .map(|var| var.positive())\n                .chain([dep_feature_var.negative()])\n                .collect::<Vec<_>>();\n\n            solver.add_clause(&dep_feature_clause);\n        }\n\n        if dep.uses_default_features() {\n            // For the selected package for this dependency, the `\"default\"` feature should be activated if it exists\n            let mut dep_default_clause = vec![dep_var.negative()];\n\n            for &id in &compatible_pkg_ids {\n                let s_var = var_for_is_packages_used[&id];\n                let s_feature_var_map = &var_for_is_packages_features_used[&id];\n\n                if let Some(s_default_feature_var) = s_feature_var_map.get(&INTERNED_DEFAULT) {\n                    dep_default_clause\n                        .extend_from_slice(&[s_var.negative(), s_default_feature_var.positive()]);\n                } else {\n                    dep_default_clause.push(s_var.positive());\n                }\n            }\n\n            solver.add_clause(&dep_default_clause);\n        }\n    }\n}\n\n/// Resolution can be reduced to the SAT problem.\n///\n/// So this is an alternative implementation\n/// of the resolver that uses a SAT library for the hard work. This is intended to be easy to read,\n/// as compared to the real resolver.\n///\n/// For the subset of functionality that are currently made by `registry_strategy`,\n/// this will find a valid resolution if one exists.\n///\n/// The SAT library does not optimize for the newer version,\n/// so the selected packages may not match the real resolver.\npub struct SatResolver {\n    solver: varisat::Solver<'static>,\n    old_root_vars: Vec<varisat::Var>,\n    var_for_is_packages_used: HashMap<PackageId, varisat::Var>,\n    var_for_is_packages_features_used: HashMap<PackageId, HashMap<InternedString, varisat::Var>>,\n    by_name: HashMap<InternedString, Vec<Summary>>,\n}\n\nimpl SatResolver {\n    pub fn new<'a>(registry: impl IntoIterator<Item = &'a Summary>) -> Self {\n        let mut by_name: HashMap<InternedString, Vec<Summary>> = HashMap::new();\n        for pkg in registry {\n            by_name.entry(pkg.name()).or_default().push(pkg.clone());\n        }\n\n        let mut solver = varisat::Solver::new();\n\n        // Create boolean variables for packages and packages features\n        let mut var_for_is_packages_used = HashMap::new();\n        let mut var_for_is_packages_features_used = HashMap::<_, HashMap<_, _>>::new();\n\n        for pkg in by_name.values().flatten() {\n            let pkg_id = pkg.package_id();\n\n            var_for_is_packages_used.insert(pkg_id, solver.new_var());\n\n            var_for_is_packages_features_used.insert(\n                pkg_id,\n                (pkg.features().keys().map(|&f| (f, solver.new_var()))).collect(),\n            );\n        }\n\n        // If a package feature is used, then the package is used\n        for (&pkg_id, pkg_feature_var_map) in &var_for_is_packages_features_used {\n            for pkg_feature_var in pkg_feature_var_map.values() {\n                let pkg_var = var_for_is_packages_used[&pkg_id];\n                solver.add_clause(&[pkg_feature_var.negative(), pkg_var.positive()]);\n            }\n        }\n\n        // No two packages with the same links set\n        sat_at_most_one_by_key(\n            &mut solver,\n            by_name\n                .values()\n                .flatten()\n                .map(|s| (s.links(), var_for_is_packages_used[&s.package_id()]))\n                .filter(|(l, _)| l.is_some()),\n        );\n\n        // No two semver compatible versions of the same package\n        sat_at_most_one_by_key(\n            &mut solver,\n            var_for_is_packages_used\n                .iter()\n                .map(|(p, &v)| (p.as_activations_key(), v)),\n        );\n\n        for pkg in by_name.values().flatten() {\n            let pkg_id = pkg.package_id();\n            let pkg_dependencies = pkg.dependencies();\n            let pkg_features = pkg.features();\n            let pkg_var = var_for_is_packages_used[&pkg_id];\n\n            // Create boolean variables for dependencies and dependencies features\n            let (var_for_is_dependencies_used, var_for_is_dependencies_features_used) =\n                create_dependencies_vars(&mut solver, pkg_var, pkg_dependencies, pkg_features);\n\n            process_pkg_dependencies(\n                &mut solver,\n                &var_for_is_dependencies_used,\n                &var_for_is_dependencies_features_used,\n                pkg_var,\n                pkg_dependencies,\n            );\n\n            process_pkg_features(\n                &mut solver,\n                &var_for_is_dependencies_used,\n                &var_for_is_dependencies_features_used,\n                &var_for_is_packages_features_used[&pkg_id],\n                pkg_dependencies,\n                pkg_features,\n            );\n\n            process_compatible_dep_summaries(\n                &mut solver,\n                &var_for_is_dependencies_used,\n                &var_for_is_dependencies_features_used,\n                &var_for_is_packages_used,\n                &var_for_is_packages_features_used,\n                &by_name,\n                pkg_dependencies,\n                false,\n            );\n        }\n\n        // We don't need to `solve` now. We know that \"use nothing\" will satisfy all the clauses so far.\n        // But things run faster if we let it spend some time figuring out how the constraints interact before we add assumptions.\n        solver\n            .solve()\n            .expect(\"docs say it can't error in default config\");\n\n        SatResolver {\n            solver,\n            old_root_vars: Vec::new(),\n            var_for_is_packages_used,\n            var_for_is_packages_features_used,\n            by_name,\n        }\n    }\n\n    pub fn sat_resolve(&mut self, root_dependencies: &[Dependency]) -> bool {\n        let SatResolver {\n            solver,\n            old_root_vars,\n            var_for_is_packages_used,\n            var_for_is_packages_features_used,\n            by_name,\n        } = self;\n\n        let root_var = solver.new_var();\n\n        // Create boolean variables for dependencies and dependencies features\n        let (var_for_is_dependencies_used, var_for_is_dependencies_features_used) =\n            create_dependencies_vars(solver, root_var, root_dependencies, &FeatureMap::new());\n\n        process_pkg_dependencies(\n            solver,\n            &var_for_is_dependencies_used,\n            &var_for_is_dependencies_features_used,\n            root_var,\n            root_dependencies,\n        );\n\n        process_compatible_dep_summaries(\n            solver,\n            &var_for_is_dependencies_used,\n            &var_for_is_dependencies_features_used,\n            var_for_is_packages_used,\n            var_for_is_packages_features_used,\n            by_name,\n            root_dependencies,\n            true,\n        );\n\n        // Root package is always used.\n        // Root vars from previous runs are deactivated.\n        let assumption = old_root_vars\n            .iter()\n            .map(|v| v.negative())\n            .chain([root_var.positive()])\n            .collect::<Vec<_>>();\n\n        old_root_vars.push(root_var);\n\n        solver.assume(&assumption);\n\n        solver\n            .solve()\n            .expect(\"docs say it can't error in default config\")\n    }\n\n    pub fn sat_is_valid_solution(&mut self, pkgs: &[(PackageId, Vec<InternedString>)]) -> bool {\n        let contains_pkg = |pkg| pkgs.iter().any(|(p, _)| p == pkg);\n        let contains_pkg_feature =\n            |pkg, f| pkgs.iter().any(|(p, flist)| p == pkg && flist.contains(f));\n\n        for (p, _) in pkgs {\n            if p.name() != \"root\" && !self.var_for_is_packages_used.contains_key(p) {\n                return false;\n            }\n        }\n\n        // Root vars from previous runs are deactivated\n        let assumption = (self.old_root_vars.iter().map(|v| v.negative()))\n            .chain(\n                self.var_for_is_packages_used\n                    .iter()\n                    .map(|(p, v)| v.lit(contains_pkg(p))),\n            )\n            .chain(\n                self.var_for_is_packages_features_used\n                    .iter()\n                    .flat_map(|(p, fmap)| {\n                        fmap.iter()\n                            .map(move |(f, v)| v.lit(contains_pkg_feature(p, f)))\n                    }),\n            )\n            .collect::<Vec<_>>();\n\n        self.solver.assume(&assumption);\n\n        self.solver\n            .solve()\n            .expect(\"docs say it can't error in default config\")\n    }\n\n    pub fn used_packages(&self) -> Option<String> {\n        self.solver.model().map(|lits| {\n            let lits: HashSet<_> = lits\n                .iter()\n                .filter(|l| l.is_positive())\n                .map(|l| l.var())\n                .collect();\n\n            let mut used_packages = BTreeMap::<PackageId, BTreeSet<InternedString>>::new();\n            for (&p, v) in self.var_for_is_packages_used.iter() {\n                if lits.contains(v) {\n                    used_packages.entry(p).or_default();\n                }\n            }\n            for (&p, map) in &self.var_for_is_packages_features_used {\n                for (&f, v) in map {\n                    if lits.contains(v) {\n                        used_packages\n                            .get_mut(&p)\n                            .expect(\"the feature is activated without the package being activated\")\n                            .insert(f);\n                    }\n                }\n            }\n\n            let mut out = String::from(\"used:\\n\");\n            for (package, feature_names) in used_packages {\n                writeln!(&mut out, \"  {package}\").unwrap();\n                for feature_name in feature_names {\n                    writeln!(&mut out, \"    + {feature_name}\").unwrap();\n                }\n            }\n\n            out\n        })\n    }\n}\n"
  },
  {
    "path": "crates/resolver-tests/tests/proptests.rs",
    "content": "use std::io::IsTerminal;\n\nuse cargo::util::GlobalContext;\nuse cargo_util::is_ci;\n\nuse resolver_tests::{\n    PrettyPrintRegistry,\n    helpers::{dep_req, registry, remove_dep},\n    registry_strategy, resolve, resolve_and_validated, resolve_with_global_context,\n    sat::SatResolver,\n};\n\nuse proptest::prelude::*;\n\n// NOTE: proptest is a form of fuzz testing. It generates random input and makes sure that\n// certain universal truths are upheld. Therefore, it can pass when there is a problem,\n// but if it fails then there really is something wrong. When testing something as\n// complicated as the resolver, the problems can be very subtle and hard to generate.\n// We have had a history of these tests only failing on PRs long after a bug is introduced.\n// If you have one of these test fail please report it on #6258,\n// and if you did not change the resolver then feel free to retry without concern.\nproptest! {\n    #![proptest_config(ProptestConfig {\n        max_shrink_iters:\n            if is_ci() || !std::io::stderr().is_terminal() {\n                // This attempts to make sure that CI will fail fast,\n                0\n            } else {\n                // but that local builds will give a small clear test case.\n                u32::MAX\n            },\n        result_cache: prop::test_runner::basic_result_cache,\n        .. ProptestConfig::default()\n    })]\n\n    /// NOTE: if you think this test has failed spuriously see the note at the top of this macro.\n    #[test]\n    fn prop_passes_validation(\n        PrettyPrintRegistry(input) in registry_strategy(50, 20, 60)\n    )  {\n        let reg = registry(input.clone());\n        let mut sat_resolver = SatResolver::new(&reg);\n\n        // There is only a small chance that a crate will be interesting.\n        // So we try some of the most complicated.\n        for this in input.iter().rev().take(20) {\n            let _ = resolve_and_validated(\n                vec![dep_req(&this.name(), &format!(\"={}\", this.version()))],\n                &reg,\n                &mut sat_resolver,\n            );\n        }\n    }\n\n    /// NOTE: if you think this test has failed spuriously see the note at the top of this macro.\n    #[test]\n    fn prop_minimum_version_errors_the_same(\n            PrettyPrintRegistry(input) in registry_strategy(50, 20, 60)\n    ) {\n        let mut gctx = GlobalContext::default().unwrap();\n        gctx.nightly_features_allowed = true;\n        gctx\n            .configure(\n                1,\n                false,\n                None,\n                false,\n                false,\n                false,\n                &None,\n                &[\"minimal-versions\".to_string()],\n                &[],\n            )\n            .unwrap();\n\n        let reg = registry(input.clone());\n\n        // There is only a small chance that a crate will be interesting.\n        // So we try some of the most complicated.\n        for this in input.iter().rev().take(10) {\n            let deps = vec![dep_req(&this.name(), &format!(\"={}\", this.version()))];\n            let res = resolve(deps.clone(), &reg);\n            let mres = resolve_with_global_context(deps, &reg, &gctx);\n\n            // `minimal-versions` changes what order the candidates are tried but not the existence of a solution.\n            prop_assert_eq!(\n                res.is_ok(),\n                mres.is_ok(),\n                \"minimal-versions and regular resolver disagree about whether `{} = \\\"={}\\\"` can resolve\",\n                this.name(),\n                this.version()\n            )\n        }\n    }\n\n    /// NOTE: if you think this test has failed spuriously see the note at the top of this macro.\n    #[test]\n    fn prop_direct_minimum_version_error_implications(\n            PrettyPrintRegistry(input) in registry_strategy(50, 20, 60)\n    ) {\n        let mut gctx = GlobalContext::default().unwrap();\n        gctx.nightly_features_allowed = true;\n        gctx\n            .configure(\n                1,\n                false,\n                None,\n                false,\n                false,\n                false,\n                &None,\n                &[\"direct-minimal-versions\".to_string()],\n                &[],\n            )\n            .unwrap();\n\n        let reg = registry(input.clone());\n\n        // There is only a small chance that a crate will be interesting.\n        // So we try some of the most complicated.\n        for this in input.iter().rev().take(10) {\n            let deps = vec![dep_req(&this.name(), &format!(\"={}\", this.version()))];\n            let res = resolve(deps.clone(), &reg);\n            let mres = resolve_with_global_context(deps, &reg, &gctx);\n\n            // `direct-minimal-versions` reduces the number of available solutions,\n            //  so we verify that we do not come up with solutions not seen in `maximal-versions`.\n            if res.is_err() {\n                prop_assert!(\n                    mres.is_err(),\n                    \"direct-minimal-versions should not have more solutions than the regular, maximal resolver but found one when resolving `{} = \\\"={}\\\"`\",\n                    this.name(),\n                    this.version()\n                )\n            }\n            if mres.is_ok() {\n                prop_assert!(\n                    res.is_ok(),\n                    \"direct-minimal-versions should not have more solutions than the regular, maximal resolver but found one when resolving `{} = \\\"={}\\\"`\",\n                    this.name(),\n                    this.version()\n                )\n            }\n        }\n    }\n\n    /// NOTE: if you think this test has failed spuriously see the note at the top of this macro.\n    #[test]\n    fn prop_removing_a_dep_cant_break(\n            PrettyPrintRegistry(input) in registry_strategy(50, 20, 60),\n            indexes_to_remove in prop::collection::vec((any::<prop::sample::Index>(), any::<prop::sample::Index>()), ..10)\n    ) {\n        let reg = registry(input.clone());\n        let mut removed_input = input.clone();\n        for (summary_idx, dep_idx) in indexes_to_remove {\n            if !removed_input.is_empty() {\n                let summary_idx = summary_idx.index(removed_input.len());\n                let deps = removed_input[summary_idx].dependencies();\n                if !deps.is_empty() {\n                    let new = remove_dep(&removed_input[summary_idx], dep_idx.index(deps.len()));\n                    removed_input[summary_idx] = new;\n                }\n            }\n        }\n        let removed_reg = registry(removed_input);\n\n        // There is only a small chance that a crate will be interesting.\n        // So we try some of the most complicated.\n        for this in input.iter().rev().take(10) {\n            if resolve(\n                vec![dep_req(&this.name(), &format!(\"={}\", this.version()))],\n                &reg,\n            ).is_ok() {\n                prop_assert!(\n                    resolve(\n                        vec![dep_req(&this.name(), &format!(\"={}\", this.version()))],\n                        &removed_reg,\n                    ).is_ok(),\n                    \"full index worked for `{} = \\\"={}\\\"` but removing some deps broke it!\",\n                    this.name(),\n                    this.version(),\n                )\n            }\n        }\n    }\n\n    /// NOTE: if you think this test has failed spuriously see the note at the top of this macro.\n    #[test]\n    fn prop_limited_independence_of_irrelevant_alternatives(\n        PrettyPrintRegistry(input) in registry_strategy(50, 20, 60),\n        indexes_to_unpublish in prop::collection::vec(any::<prop::sample::Index>(), ..10)\n    )  {\n        let reg = registry(input.clone());\n\n        // There is only a small chance that a crate will be interesting.\n        // So we try some of the most complicated.\n        for this in input.iter().rev().take(10) {\n            let res = resolve(\n                vec![dep_req(&this.name(), &format!(\"={}\", this.version()))],\n                &reg,\n            );\n\n            match res {\n                Ok(r) => {\n                    // If resolution was successful, then unpublishing a version of a crate\n                    // that was not selected should not change that.\n                    let not_selected: Vec<_> = input\n                        .iter().filter(|&x| !r.contains(&x.package_id())).cloned()\n                        .collect();\n\n                    if !not_selected.is_empty() {\n                        let indexes_to_unpublish: Vec<_> = indexes_to_unpublish.iter().map(|x| x.get(&not_selected)).collect();\n\n                        let new_reg = registry(\n                            input\n                                .iter().filter(|&x| !indexes_to_unpublish.contains(&x)).cloned()\n                                .collect(),\n                        );\n\n                        let res = resolve(\n                            vec![dep_req(&this.name(), &format!(\"={}\", this.version()))],\n                            &new_reg,\n                        );\n\n                        // Note: that we can not assert that the two `res` are identical\n                        // as the resolver does depend on irrelevant alternatives.\n                        // It uses how constrained a dependency requirement is\n                        // to determine what order to evaluate requirements.\n\n                        prop_assert!(\n                            res.is_ok(),\n                            \"unpublishing {:?} stopped `{} = \\\"={}\\\"` from working\",\n                            indexes_to_unpublish.iter().map(|x| x.package_id()).collect::<Vec<_>>(),\n                            this.name(),\n                            this.version()\n                        )\n                    }\n                }\n\n                Err(_) => {\n                    // If resolution was unsuccessful, then it should stay unsuccessful\n                    // even if any version of a crate is unpublished.\n                    let indexes_to_unpublish: Vec<_> = indexes_to_unpublish.iter().map(|x| x.get(&input)).collect();\n\n                    let new_reg = registry(\n                        input\n                            .iter().filter(|&x| !indexes_to_unpublish.contains(&x)).cloned()\n                            .collect(),\n                    );\n\n                    let res = resolve(\n                        vec![dep_req(&this.name(), &format!(\"={}\", this.version()))],\n                        &new_reg,\n                    );\n\n                    prop_assert!(\n                        res.is_err(),\n                        \"full index did not work for `{} = \\\"={}\\\"` but unpublishing {:?} fixed it!\",\n                        this.name(),\n                        this.version(),\n                        indexes_to_unpublish.iter().map(|x| x.package_id()).collect::<Vec<_>>(),\n                    )\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "crates/resolver-tests/tests/pubgrub.rs",
    "content": "use cargo::core::{Dependency, dependency::DepKind};\n\nuse resolver_tests::{\n    helpers::{\n        ToDep, dep, dep_kind, dep_req, dep_req_kind, pkg, pkg_dep, pkg_dep_link, pkg_dep_with,\n        pkg_id_source, registry,\n    },\n    pkg, resolve, resolve_and_validated, resolve_and_validated_raw,\n    sat::SatResolver,\n};\n\n#[test]\nfn test_01_renamed_package() {\n    let reg = registry(vec![\n        pkg_dep_with(\n            \"a\",\n            vec![\"b\".opt().rename(\"b_package\")],\n            &[(\"default\", &[\"b_package\"])],\n        ),\n        pkg(\"b\"),\n    ]);\n\n    let deps = vec![\"a\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn test_02_renamed_package_no_shadowing() {\n    let reg = registry(vec![\n        pkg(\"url\"),\n        pkg_dep(\"wasmi\", vec![\"wasmparser-nostd\".rename(\"wasmparser\")]),\n        pkg_dep(\"wasmparser\", vec![\"url\".to_dep()]),\n    ]);\n\n    let deps = vec![dep(\"wasmi\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn test_03_prerelease_semver() {\n    let reg = registry(vec![\n        pkg!(\"parking_lot_core\" => [dep_req(\"smallvec\", \"^1.6.1\")]),\n        pkg((\"smallvec\", \"2.0.0-alpha.3\")),\n        pkg_dep_with(\n            (\"tokio\", \"1.35.1\"),\n            vec![\"parking_lot_core\".opt()],\n            &[(\"default\", &[\"parking_lot_core\"])],\n        ),\n    ]);\n\n    let deps = vec![\"tokio\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn test_04_cyclic_features() {\n    let reg = registry(vec![pkg_dep_with(\n        \"windows\",\n        vec![],\n        &[\n            (\"Win32\", &[\"Win32_Foundation\"]),\n            (\"Win32_Foundation\", &[\"Win32\"]),\n        ],\n    )]);\n\n    let deps = vec![\"windows\".with(&[\"Win32_Foundation\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn test_05_cyclic_optional_dependencies() {\n    let reg = registry(vec![\n        pkg_dep(\"async-global-executor\", vec![\"io-lifetimes\".opt()]),\n        pkg_dep(\n            \"io-lifetimes\",\n            vec![\"test\".with(&[\"async-global-executor\"])],\n        ),\n        pkg_dep_with(\n            \"test\",\n            vec![\"async-global-executor\".opt().with(&[\"io-lifetimes\"])],\n            &[],\n        ),\n    ]);\n\n    let deps = vec![dep(\"test\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn test_06_cyclic_dependencies() {\n    let reg = registry(vec![\n        pkg((\"a\", \"1.0.0\")),\n        pkg_dep((\"a\", \"1.0.1\"), vec![dep(\"dep\")]),\n        pkg_dep(\"dep\", vec![dep(\"a\")]),\n    ]);\n\n    let deps = vec![dep(\"dep\")];\n\n    // Cyclic dependencies are not checked in the SAT resolver\n    assert!(resolve(deps.clone(), &reg).is_err());\n    assert!(SatResolver::new(&reg).sat_resolve(&deps));\n}\n\n#[test]\nfn test_07_self_dependency() {\n    let reg = registry(vec![pkg_dep(\"dep\", vec![dep(\"dep\")])]);\n\n    let deps = vec![dep(\"dep\")];\n\n    // Cyclic dependencies are not checked in the SAT resolver\n    assert!(resolve(deps.clone(), &reg).is_err());\n    assert!(SatResolver::new(&reg).sat_resolve(&deps));\n}\n\n#[test]\nfn test_08_activated_optional_self_dependency() {\n    let reg = registry(vec![pkg_dep(\"a\", vec![\"a\".opt()])]);\n\n    let deps = vec![\"a\".with(&[\"a\"])];\n\n    // Cyclic dependencies are not checked in the SAT resolver\n    assert!(resolve(deps.clone(), &reg).is_err());\n    assert!(SatResolver::new(&reg).sat_resolve(&deps));\n}\n\n#[test]\nfn test_09_build_dependency_with_same_name() {\n    let reg = registry(vec![\n        pkg(\"memchr\"),\n        pkg_dep_with(\n            (\"regex\", \"1.4.6\"),\n            vec![\"memchr\".opt()],\n            &[(\"default\", &[\"memchr\"])],\n        ),\n        pkg_dep(\"sv-parser\", vec![\"regex\".with(&[\"default\"])]),\n        pkg_dep(\n            \"svlint\",\n            vec![\n                dep_req(\"regex\", \"^1.5\"),\n                dep_req_kind(\"regex\", \"^1\", DepKind::Build),\n                dep(\"sv-parser\"),\n            ],\n        ),\n    ]);\n\n    let deps = vec![dep(\"svlint\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn test_10_root_dev_dependency_with_same_name() {\n    let reg = registry(vec![pkg((\"root\", \"1.0.1\"))]);\n\n    let deps = vec![dep_req_kind(\"root\", \"=1.0.1\", DepKind::Development).rename(\"root101\")];\n    let source = pkg_id_source(\"root\", \"https://root.example.com\");\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated_raw(deps, &reg, source, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn test_11_dev_dependency() {\n    let reg = registry(vec![pkg_dep_with(\n        \"burn-core\",\n        vec![dep_kind(\"burn-ndarray\", DepKind::Development)],\n        &[(\"default\", &[\"burn-ndarray/std\"])],\n    )]);\n\n    let deps = vec![\"burn-core\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn test_12_weak_dependencies() {\n    let reg = registry(vec![\n        pkg_dep_with(\"borsh\", vec![\"borsh-derive\".opt()], &[(\"std\", &[])]),\n        pkg_dep_with(\n            \"rust_decimal\",\n            vec![\"borsh\".opt().with(&[\"borsh-derive\"])],\n            &[(\"default\", &[\"borsh?/std\"])],\n        ),\n    ]);\n\n    let deps = vec![\"rust_decimal\".with(&[\"default\"])];\n\n    // Weak dependencies are not supported yet in the dependency resolver\n    assert!(resolve(deps.clone(), &reg).is_err());\n    assert!(SatResolver::new(&reg).sat_resolve(&deps));\n}\n\n#[test]\nfn test_13_weak_dependencies() {\n    let reg = registry(vec![\n        pkg_dep_with(\"memchr\", vec![\"std\".opt()], &[(\"std\", &[\"dep:std\"])]),\n        pkg_dep_with(\n            \"winnow\",\n            vec![\"memchr\".opt()],\n            &[(\"default\", &[\"memchr?/std\"]), (\"simd\", &[\"dep:memchr\"])],\n        ),\n    ]);\n\n    let deps = vec![\"winnow\".with(&[\"default\"])];\n\n    // Weak dependencies are not supported yet in the dependency resolver\n    assert!(resolve(deps.clone(), &reg).is_err());\n    assert!(SatResolver::new(&reg).sat_resolve(&deps));\n}\n\n#[test]\nfn test_14_weak_dependencies() {\n    let reg = registry(vec![\n        pkg_dep(\"a\", vec![dep(\"bad\")]),\n        pkg_dep_with(\"b\", vec![\"a\".opt()], &[(\"perf-literal\", &[\"dep:a\"])]),\n        pkg_dep_with(\n            \"c\",\n            vec![\"b\".opt()],\n            &[\n                (\"perf-literal\", &[\"b?/perf-literal\"]),\n                (\"perf-literal-multisubstring\", &[\"dep:b\"]),\n            ],\n        ),\n        pkg_dep_with(\"dep\", vec![dep(\"c\")], &[(\"default\", &[\"c/perf-literal\"])]),\n    ]);\n\n    let deps = vec![\"dep\".with(&[\"default\"])];\n\n    // Weak dependencies are not supported yet in the dependency resolver\n    assert!(resolve(deps.clone(), &reg).is_err());\n    assert!(SatResolver::new(&reg).sat_resolve(&deps));\n}\n\n#[test]\nfn test_15_duplicate_sys_crate() {\n    let reg = registry(vec![\n        pkg_dep_link(\"js\", \"js\", vec![]),\n        pkg_dep_link(\"dep\", \"js\", vec![dep(\"js\")]),\n    ]);\n\n    let deps = vec![dep(\"dep\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn test_16_missing_optional_dependency() {\n    let reg = registry(vec![\n        pkg_dep(\"b\", vec![\"c\".opt()]),\n        pkg_dep_with(\"dep\", vec![dep(\"b\")], &[(\"d\", &[\"b/c\"])]),\n    ]);\n\n    let deps = vec![\"dep\".with(&[\"d\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn test_17_feature_shadowing_missing_optional_dependency() {\n    let reg = registry(vec![pkg_dep_with(\n        \"rustix\",\n        vec![\"alloc\".opt()],\n        &[\n            (\"alloc\", &[]),\n            (\"default\", &[\"alloc\"]),\n            (\"rustc-dep-of-std\", &[\"dep:alloc\"]),\n        ],\n    )]);\n\n    let deps = vec![\"rustix\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn test_18_feature_shadowing_activated_optional_dependency() {\n    let reg = registry(vec![\n        pkg_dep(\"alloc\", vec![dep(\"bad\")]),\n        pkg_dep_with(\n            \"rustix\",\n            vec![\"alloc\".opt()],\n            &[\n                (\"alloc\", &[]),\n                (\"default\", &[\"dep:alloc\"]),\n                (\"rustc-dep-of-std\", &[\"alloc\"]),\n            ],\n        ),\n    ]);\n\n    let deps = vec![\"rustix\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn test_19_same_dep_twice_feature_unification() {\n    let reg = registry(vec![\n        pkg_dep_with(\n            \"iced\",\n            vec![\"iced_wgpu\".opt(), \"iced_wgpu\".opt().with(&[\"webgl\"])],\n            &[(\"default\", &[\"iced_wgpu\"])],\n        ),\n        pkg_dep_with(\"iced_wgpu\", vec![], &[(\"webgl\", &[])]),\n    ]);\n\n    let deps = vec![\"iced\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn test_20_no_implicit_feature() {\n    let reg = registry(vec![\n        pkg(\"c\"),\n        pkg_dep_with(\"ureq\", vec![\"c\".opt()], &[(\"cookies\", &[\"dep:c\"])]),\n        pkg_dep_with(\"dep\", vec![dep(\"ureq\")], &[(\"cookies\", &[\"ureq/c\"])]),\n    ]);\n\n    let deps = vec![\"dep\".with(&[\"cookies\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn test_21_implicit_feature() {\n    let reg = registry(vec![\n        pkg(\"c\"),\n        pkg_dep(\"ureq\", vec![\"c\".opt()]),\n        pkg_dep_with(\"dep\", vec![dep(\"ureq\")], &[(\"cookies\", &[\"ureq/c\"])]),\n    ]);\n\n    let deps = vec![\"dep\".with(&[\"cookies\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn test_22_missing_explicit_default_feature() {\n    let reg = registry(vec![\n        pkg_dep_with(\n            \"fuel-tx\",\n            vec![dep(\"serde\"), \"serde_json\".opt()],\n            &[(\"default\", &[\"serde/default\"]), (\"serde\", &[\"serde_json\"])],\n        ),\n        pkg(\"serde\"),\n    ]);\n\n    let deps = vec![\"fuel-tx\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn test_23_no_need_for_explicit_default_feature() {\n    let reg = registry(vec![\n        pkg(\"a\"),\n        pkg_dep_with(\n            \"b\",\n            vec![\"a\".with_default()],\n            &[(\"default\", &[\"std\"]), (\"std\", &[])],\n        ),\n    ]);\n\n    let deps = vec![\"b\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn test_24_dep_feature() {\n    let reg = registry(vec![\n        pkg_dep_with(\"proc-macro2\", vec![], &[(\"proc-macro\", &[])]),\n        pkg_dep_with(\n            \"syn\",\n            vec![dep(\"proc-macro2\")],\n            &[(\"proc-macro\", &[\"proc-macro2/proc-macro\"])],\n        ),\n        pkg_dep(\"serde_derive\", vec![\"syn\".with(&[\"proc-macro\"])]),\n    ]);\n\n    let deps = vec![dep(\"serde_derive\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn test_25_dep_feature() {\n    let reg = registry(vec![\n        pkg_dep_with(\"proc-macro2\", vec![], &[(\"proc-macro\", &[])]),\n        pkg_dep_with(\n            \"syn\",\n            vec![dep(\"proc-macro2\")],\n            &[(\"proc-macro\", &[\"proc-macro2/proc-macro\"])],\n        ),\n    ]);\n\n    let deps = vec![\"syn\".with(&[\"proc-macro\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn test_26_implicit_feature_with_dep_feature() {\n    let reg = registry(vec![\n        pkg_dep_with(\"quote\", vec![], &[(\"proc-macro\", &[])]),\n        pkg_dep_with(\n            \"syn\",\n            vec![\"quote\".opt()],\n            &[(\"default\", &[\"quote\", \"quote/proc-macro\"])],\n        ),\n    ]);\n\n    let deps = vec![\"syn\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn test_27_dep_feature_activating_shadowing_feature() {\n    let reg = registry(vec![\n        pkg_dep_with(\n            \"a\",\n            vec![\"b\".opt(), \"x\".opt()],\n            &[(\"b\", &[\"x\"]), (\"default\", &[\"b/native\"])],\n        ),\n        pkg_dep_with(\"b\", vec![], &[(\"native\", &[])]),\n    ]);\n\n    let deps = vec![\"a\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn test_28_dep_feature_not_activating_shadowing_feature() {\n    let reg = registry(vec![\n        pkg_dep_with(\n            \"fuel-tx\",\n            vec![dep(\"serde\"), \"serde_json\".opt()],\n            &[(\"default\", &[\"serde/default\"]), (\"serde\", &[\"serde_json\"])],\n        ),\n        pkg_dep_with(\"serde\", vec![], &[(\"default\", &[])]),\n    ]);\n\n    let deps = vec![\"fuel-tx\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n"
  },
  {
    "path": "crates/resolver-tests/tests/resolve.rs",
    "content": "use cargo::core::Dependency;\nuse cargo::core::dependency::DepKind;\nuse cargo::util::GlobalContext;\n\nuse resolver_tests::{\n    helpers::{\n        ToDep, ToPkgId, assert_contains, assert_same, dep, dep_kind, dep_loc, dep_req, loc_names,\n        names, pkg, pkg_dep, pkg_dep_with, pkg_id, pkg_loc, registry,\n    },\n    pkg, resolve, resolve_with_global_context,\n};\n\n#[test]\n#[should_panic(expected = \"assertion failed: !name.is_empty()\")]\nfn test_dependency_with_empty_name() {\n    // Bug 5229, dependency-names must not be empty\n    dep(\"\");\n}\n\n#[test]\nfn test_resolving_empty_dependency_list() {\n    let res = resolve(Vec::new(), &registry(vec![])).unwrap();\n\n    assert_eq!(res, names(&[\"root\"]));\n}\n\n#[test]\nfn test_resolving_only_package() {\n    let reg = registry(vec![pkg!(\"foo\")]);\n    let res = resolve(vec![dep(\"foo\")], &reg).unwrap();\n    assert_same(&res, &names(&[\"root\", \"foo\"]));\n}\n\n#[test]\nfn test_resolving_one_dep() {\n    let reg = registry(vec![pkg!(\"foo\"), pkg!(\"bar\")]);\n    let res = resolve(vec![dep(\"foo\")], &reg).unwrap();\n    assert_same(&res, &names(&[\"root\", \"foo\"]));\n}\n\n#[test]\nfn test_resolving_multiple_deps() {\n    let reg = registry(vec![pkg!(\"foo\"), pkg!(\"bar\"), pkg!(\"baz\")]);\n    let res = resolve(vec![dep(\"foo\"), dep(\"baz\")], &reg).unwrap();\n    assert_same(&res, &names(&[\"root\", \"foo\", \"baz\"]));\n}\n\n#[test]\nfn test_resolving_transitive_deps() {\n    let reg = registry(vec![pkg!(\"foo\"), pkg!(\"bar\" => [\"foo\"])]);\n    let res = resolve(vec![dep(\"bar\")], &reg).unwrap();\n\n    assert_same(&res, &names(&[\"root\", \"foo\", \"bar\"]));\n}\n\n#[test]\nfn test_resolving_common_transitive_deps() {\n    let reg = registry(vec![pkg!(\"foo\" => [\"bar\"]), pkg!(\"bar\")]);\n    let res = resolve(vec![dep(\"foo\"), dep(\"bar\")], &reg).unwrap();\n\n    assert_same(&res, &names(&[\"root\", \"foo\", \"bar\"]));\n}\n\n#[test]\nfn test_resolving_with_same_name() {\n    let list = vec![\n        pkg_loc(\"foo\", \"https://first.example.com\"),\n        pkg_loc(\"bar\", \"https://second.example.com\"),\n    ];\n\n    let reg = registry(list);\n    let res = resolve(\n        vec![\n            dep_loc(\"foo\", \"https://first.example.com\"),\n            dep_loc(\"bar\", \"https://second.example.com\"),\n        ],\n        &reg,\n    )\n    .unwrap();\n\n    let mut names = loc_names(&[\n        (\"foo\", \"https://first.example.com\"),\n        (\"bar\", \"https://second.example.com\"),\n    ]);\n\n    names.push(pkg_id(\"root\"));\n    assert_same(&res, &names);\n}\n\n#[test]\nfn test_resolving_with_dev_deps() {\n    let reg = registry(vec![\n        pkg!(\"foo\" => [\"bar\", dep_kind(\"baz\", DepKind::Development)]),\n        pkg!(\"baz\" => [\"bat\", dep_kind(\"bam\", DepKind::Development)]),\n        pkg!(\"bar\"),\n        pkg!(\"bat\"),\n    ]);\n\n    let res = resolve(\n        vec![dep(\"foo\"), dep_kind(\"baz\", DepKind::Development)],\n        &reg,\n    )\n    .unwrap();\n\n    assert_same(&res, &names(&[\"root\", \"foo\", \"bar\", \"baz\", \"bat\"]));\n}\n\n#[test]\nfn resolving_with_many_versions() {\n    let reg = registry(vec![pkg!((\"foo\", \"1.0.1\")), pkg!((\"foo\", \"1.0.2\"))]);\n\n    let res = resolve(vec![dep(\"foo\")], &reg).unwrap();\n\n    assert_same(&res, &names(&[(\"root\", \"1.0.0\"), (\"foo\", \"1.0.2\")]));\n}\n\n#[test]\nfn resolving_with_specific_version() {\n    let reg = registry(vec![pkg!((\"foo\", \"1.0.1\")), pkg!((\"foo\", \"1.0.2\"))]);\n\n    let res = resolve(vec![dep_req(\"foo\", \"=1.0.1\")], &reg).unwrap();\n\n    assert_same(&res, &names(&[(\"root\", \"1.0.0\"), (\"foo\", \"1.0.1\")]));\n}\n\n#[test]\nfn test_resolving_maximum_version_with_transitive_deps() {\n    let reg = registry(vec![\n        pkg!((\"util\", \"1.2.2\")),\n        pkg!((\"util\", \"1.0.0\")),\n        pkg!((\"util\", \"1.1.1\")),\n        pkg!(\"foo\" => [dep_req(\"util\", \"1.0.0\")]),\n        pkg!(\"bar\" => [dep_req(\"util\", \">=1.0.1\")]),\n    ]);\n\n    let res = resolve(vec![dep_req(\"foo\", \"1.0.0\"), dep_req(\"bar\", \"1.0.0\")], &reg).unwrap();\n\n    assert_contains(\n        &res,\n        &names(&[\n            (\"root\", \"1.0.0\"),\n            (\"foo\", \"1.0.0\"),\n            (\"bar\", \"1.0.0\"),\n            (\"util\", \"1.2.2\"),\n        ]),\n    );\n    assert!(!res.contains(&(\"util\", \"1.0.1\").to_pkgid()));\n    assert!(!res.contains(&(\"util\", \"1.1.1\").to_pkgid()));\n}\n\n#[test]\nfn test_resolving_minimum_version_with_transitive_deps() {\n    let reg = registry(vec![\n        pkg!((\"util\", \"1.2.2\")),\n        pkg!((\"util\", \"1.0.0\")),\n        pkg!((\"util\", \"1.1.1\")),\n        pkg!(\"foo\" => [dep_req(\"util\", \"1.0.0\")]),\n        pkg!(\"bar\" => [dep_req(\"util\", \">=1.0.1\")]),\n    ]);\n\n    let mut gctx = GlobalContext::default().unwrap();\n    // -Z minimal-versions\n    // When the minimal-versions config option is specified then the lowest\n    // possible version of a package should be selected. \"util 1.0.0\" can't be\n    // selected because of the requirements of \"bar\", so the minimum version\n    // must be 1.1.1.\n    gctx.nightly_features_allowed = true;\n    gctx.configure(\n        1,\n        false,\n        None,\n        false,\n        false,\n        false,\n        &None,\n        &[\"minimal-versions\".to_string()],\n        &[],\n    )\n    .unwrap();\n\n    let res = resolve_with_global_context(\n        vec![dep_req(\"foo\", \"1.0.0\"), dep_req(\"bar\", \"1.0.0\")],\n        &reg,\n        &gctx,\n    )\n    .unwrap()\n    .into_iter()\n    .map(|(pkg, _)| pkg)\n    .collect::<Vec<_>>();\n\n    assert_contains(\n        &res,\n        &names(&[\n            (\"root\", \"1.0.0\"),\n            (\"foo\", \"1.0.0\"),\n            (\"bar\", \"1.0.0\"),\n            (\"util\", \"1.1.1\"),\n        ]),\n    );\n    assert!(!res.contains(&(\"util\", \"1.2.2\").to_pkgid()));\n    assert!(!res.contains(&(\"util\", \"1.0.0\").to_pkgid()));\n}\n\n#[test]\nfn resolving_incompat_versions() {\n    let reg = registry(vec![\n        pkg!((\"foo\", \"1.0.1\")),\n        pkg!((\"foo\", \"1.0.2\")),\n        pkg!(\"bar\" => [dep_req(\"foo\", \"=1.0.2\")]),\n    ]);\n\n    assert!(resolve(vec![dep_req(\"foo\", \"=1.0.1\"), dep(\"bar\")], &reg).is_err());\n}\n\n#[test]\nfn resolving_wrong_case_from_registry() {\n    // In the future we may #5678 allow this to happen.\n    // For back compatibility reasons, we probably won't.\n    // But we may want to future prove ourselves by understanding it.\n    // This test documents the current behavior.\n    let reg = registry(vec![pkg!((\"foo\", \"1.0.0\")), pkg!(\"bar\" => [\"Foo\"])]);\n\n    assert!(resolve(vec![dep(\"bar\")], &reg).is_err());\n}\n\n#[test]\nfn resolving_mis_hyphenated_from_registry() {\n    // In the future we may #2775 allow this to happen.\n    // For back compatibility reasons, we probably won't.\n    // But we may want to future prove ourselves by understanding it.\n    // This test documents the current behavior.\n    let reg = registry(vec![pkg!((\"fo-o\", \"1.0.0\")), pkg!(\"bar\" => [\"fo_o\"])]);\n\n    assert!(resolve(vec![dep(\"bar\")], &reg).is_err());\n}\n\n#[test]\nfn resolving_backtrack() {\n    let reg = registry(vec![\n        pkg!((\"foo\", \"1.0.2\") => [dep(\"bar\")]),\n        pkg!((\"foo\", \"1.0.1\") => [dep(\"baz\")]),\n        pkg!(\"bar\" => [dep_req(\"foo\", \"=2.0.2\")]),\n        pkg!(\"baz\"),\n    ]);\n\n    let res = resolve(vec![dep_req(\"foo\", \"^1\")], &reg).unwrap();\n\n    assert_contains(\n        &res,\n        &names(&[(\"root\", \"1.0.0\"), (\"foo\", \"1.0.1\"), (\"baz\", \"1.0.0\")]),\n    );\n}\n\n#[test]\nfn resolving_backtrack_features() {\n    // test for cargo/issues/4347\n    let mut bad = dep(\"bar\");\n    bad.set_features(vec![\"bad\"]);\n\n    let reg = registry(vec![\n        pkg!((\"foo\", \"1.0.2\") => [bad]),\n        pkg!((\"foo\", \"1.0.1\") => [dep(\"bar\")]),\n        pkg!(\"bar\"),\n    ]);\n\n    let res = resolve(vec![dep_req(\"foo\", \"^1\")], &reg).unwrap();\n\n    assert_contains(\n        &res,\n        &names(&[(\"root\", \"1.0.0\"), (\"foo\", \"1.0.1\"), (\"bar\", \"1.0.0\")]),\n    );\n}\n\n#[test]\nfn resolving_allows_multiple_compatible_versions() {\n    let reg = registry(vec![\n        pkg!((\"foo\", \"1.0.0\")),\n        pkg!((\"foo\", \"2.0.0\")),\n        pkg!((\"foo\", \"0.1.0\")),\n        pkg!((\"foo\", \"0.2.0\")),\n        pkg!(\"bar\" => [\"d1\", \"d2\", \"d3\", \"d4\"]),\n        pkg!(\"d1\" => [dep_req(\"foo\", \"1\")]),\n        pkg!(\"d2\" => [dep_req(\"foo\", \"2\")]),\n        pkg!(\"d3\" => [dep_req(\"foo\", \"0.1\")]),\n        pkg!(\"d4\" => [dep_req(\"foo\", \"0.2\")]),\n    ]);\n\n    let res = resolve(vec![dep(\"bar\")], &reg).unwrap();\n\n    assert_same(\n        &res,\n        &names(&[\n            (\"root\", \"1.0.0\"),\n            (\"foo\", \"1.0.0\"),\n            (\"foo\", \"2.0.0\"),\n            (\"foo\", \"0.1.0\"),\n            (\"foo\", \"0.2.0\"),\n            (\"d1\", \"1.0.0\"),\n            (\"d2\", \"1.0.0\"),\n            (\"d3\", \"1.0.0\"),\n            (\"d4\", \"1.0.0\"),\n            (\"bar\", \"1.0.0\"),\n        ]),\n    );\n}\n\n#[test]\nfn resolving_with_deep_backtracking() {\n    let reg = registry(vec![\n        pkg!((\"foo\", \"1.0.1\") => [dep_req(\"bar\", \"1\")]),\n        pkg!((\"foo\", \"1.0.0\") => [dep_req(\"bar\", \"2\")]),\n        pkg!((\"bar\", \"1.0.0\") => [dep_req(\"baz\", \"=1.0.2\"),\n                                  dep_req(\"other\", \"1\")]),\n        pkg!((\"bar\", \"2.0.0\") => [dep_req(\"baz\", \"=1.0.1\")]),\n        pkg!((\"baz\", \"1.0.2\") => [dep_req(\"other\", \"2\")]),\n        pkg!((\"baz\", \"1.0.1\")),\n        pkg!((\"dep_req\", \"1.0.0\")),\n        pkg!((\"dep_req\", \"2.0.0\")),\n    ]);\n\n    let res = resolve(vec![dep_req(\"foo\", \"1\")], &reg).unwrap();\n\n    assert_same(\n        &res,\n        &names(&[\n            (\"root\", \"1.0.0\"),\n            (\"foo\", \"1.0.0\"),\n            (\"bar\", \"2.0.0\"),\n            (\"baz\", \"1.0.1\"),\n        ]),\n    );\n}\n\n#[test]\nfn resolving_with_sys_crates() {\n    // This is based on issues/4902\n    // With `l` a normal library we get 2copies so everyone gets the newest compatible.\n    // But `l-sys` a library with a links attribute we make sure there is only one.\n    let reg = registry(vec![\n        pkg!((\"l-sys\", \"0.9.1\")),\n        pkg!((\"l-sys\", \"0.10.0\")),\n        pkg!((\"l\", \"0.9.1\")),\n        pkg!((\"l\", \"0.10.0\")),\n        pkg!((\"d\", \"1.0.0\") => [dep_req(\"l-sys\", \">=0.8.0, <=0.10.0\"), dep_req(\"l\", \">=0.8.0, <=0.10.0\")]),\n        pkg!((\"r\", \"1.0.0\") => [dep_req(\"l-sys\", \"0.9\"), dep_req(\"l\", \"0.9\")]),\n    ]);\n\n    let res = resolve(vec![dep_req(\"d\", \"1\"), dep_req(\"r\", \"1\")], &reg).unwrap();\n\n    assert_same(\n        &res,\n        &names(&[\n            (\"root\", \"1.0.0\"),\n            (\"d\", \"1.0.0\"),\n            (\"r\", \"1.0.0\"),\n            (\"l-sys\", \"0.9.1\"),\n            (\"l\", \"0.9.1\"),\n            (\"l\", \"0.10.0\"),\n        ]),\n    );\n}\n\n#[test]\nfn resolving_with_constrained_sibling_backtrack_parent() {\n    // There is no point in considering all of the backtrack_trap{1,2}\n    // candidates since they can't change the result of failing to\n    // resolve 'constrained'. Cargo should (ideally) skip past them and resume\n    // resolution once the activation of the parent, 'bar', is rolled back.\n    // Note that the traps are slightly more constrained to make sure they\n    // get picked first.\n    let mut reglist = vec![\n        pkg!((\"foo\", \"1.0.0\") => [dep_req(\"bar\", \"1.0\"),\n                                  dep_req(\"constrained\", \"=1.0.0\")]),\n        pkg!((\"bar\", \"1.0.0\") => [dep_req(\"backtrack_trap1\", \"1.0.2\"),\n                                  dep_req(\"backtrack_trap2\", \"1.0.2\"),\n                                  dep_req(\"constrained\", \"1.0.0\")]),\n        pkg!((\"constrained\", \"1.0.0\")),\n        pkg!((\"backtrack_trap1\", \"1.0.0\")),\n        pkg!((\"backtrack_trap2\", \"1.0.0\")),\n    ];\n    // Bump this to make the test harder - it adds more versions of bar that will\n    // fail to resolve, and more versions of the traps to consider.\n    const NUM_BARS_AND_TRAPS: usize = 50; // minimum 2\n    for i in 1..NUM_BARS_AND_TRAPS {\n        let vsn = format!(\"1.0.{}\", i);\n        reglist.push(\n            pkg!((\"bar\", vsn.clone()) => [dep_req(\"backtrack_trap1\", \"1.0.2\"),\n                                          dep_req(\"backtrack_trap2\", \"1.0.2\"),\n                                          dep_req(\"constrained\", \"1.0.1\")]),\n        );\n        reglist.push(pkg!((\"backtrack_trap1\", vsn.clone())));\n        reglist.push(pkg!((\"backtrack_trap2\", vsn.clone())));\n        reglist.push(pkg!((\"constrained\", vsn.clone())));\n    }\n    let reg = registry(reglist);\n\n    let res = resolve(vec![dep_req(\"foo\", \"1\")], &reg).unwrap();\n\n    assert_contains(\n        &res,\n        &names(&[\n            (\"root\", \"1.0.0\"),\n            (\"foo\", \"1.0.0\"),\n            (\"bar\", \"1.0.0\"),\n            (\"constrained\", \"1.0.0\"),\n        ]),\n    );\n}\n\n#[test]\nfn resolving_with_many_equivalent_backtracking() {\n    let mut reglist = Vec::new();\n\n    const DEPTH: usize = 200;\n    const BRANCHING_FACTOR: usize = 100;\n\n    // Each level depends on the next but the last level does not exist.\n    // Without cashing we need to test every path to the last level O(BRANCHING_FACTOR ^ DEPTH)\n    // and this test will time out. With cashing we need to discover that none of these\n    // can be activated O(BRANCHING_FACTOR * DEPTH)\n    for l in 0..DEPTH {\n        let name = format!(\"level{}\", l);\n        let next = format!(\"level{}\", l + 1);\n        for i in 1..BRANCHING_FACTOR {\n            let vsn = format!(\"1.0.{}\", i);\n            reglist.push(pkg!((name.as_str(), vsn.as_str()) => [dep(next.as_str())]));\n        }\n    }\n\n    let reg = registry(reglist.clone());\n\n    let res = resolve(vec![dep(\"level0\")], &reg);\n\n    assert!(res.is_err());\n\n    // It is easy to write code that quickly returns an error.\n    // Lets make sure we can find a good answer if it is there.\n    reglist.push(pkg!((\"level0\", \"1.0.0\")));\n\n    let reg = registry(reglist.clone());\n\n    let res = resolve(vec![dep(\"level0\")], &reg).unwrap();\n\n    assert_contains(&res, &names(&[(\"root\", \"1.0.0\"), (\"level0\", \"1.0.0\")]));\n\n    // Make sure we have not special case no candidates.\n    reglist.push(pkg!((\"constrained\", \"1.1.0\")));\n    reglist.push(pkg!((\"constrained\", \"1.0.0\")));\n    reglist.push(\n        pkg!((format!(\"level{}\", DEPTH).as_str(), \"1.0.0\") => [dep_req(\"constrained\", \"=1.0.0\")]),\n    );\n\n    let reg = registry(reglist.clone());\n\n    let res = resolve(vec![dep(\"level0\"), dep(\"constrained\")], &reg).unwrap();\n\n    assert_contains(\n        &res,\n        &names(&[\n            (\"root\", \"1.0.0\"),\n            (\"level0\", \"1.0.0\"),\n            (\"constrained\", \"1.1.0\"),\n        ]),\n    );\n\n    let reg = registry(reglist.clone());\n\n    let res = resolve(vec![dep_req(\"level0\", \"1.0.1\"), dep(\"constrained\")], &reg).unwrap();\n\n    assert_contains(\n        &res,\n        &names(&[\n            (\"root\", \"1.0.0\"),\n            (format!(\"level{}\", DEPTH).as_str(), \"1.0.0\"),\n            (\"constrained\", \"1.0.0\"),\n        ]),\n    );\n\n    let reg = registry(reglist);\n\n    let res = resolve(\n        vec![dep_req(\"level0\", \"1.0.1\"), dep_req(\"constrained\", \"1.1.0\")],\n        &reg,\n    );\n\n    assert!(res.is_err());\n}\n\n#[test]\nfn resolving_with_deep_traps() {\n    let mut reglist = Vec::new();\n\n    const DEPTH: usize = 200;\n    const BRANCHING_FACTOR: usize = 100;\n\n    // Each backtrack_trap depends on the next, and adds a backtrack frame.\n    // None of witch is going to help with `bad`.\n    for l in 0..DEPTH {\n        let name = format!(\"backtrack_trap{}\", l);\n        let next = format!(\"backtrack_trap{}\", l + 1);\n        for i in 1..BRANCHING_FACTOR {\n            let vsn = format!(\"1.0.{}\", i);\n            reglist.push(pkg!((name.as_str(), vsn.as_str()) => [dep(next.as_str())]));\n        }\n    }\n    {\n        let name = format!(\"backtrack_trap{}\", DEPTH);\n        for i in 1..BRANCHING_FACTOR {\n            let vsn = format!(\"1.0.{}\", i);\n            reglist.push(pkg!((name.as_str(), vsn.as_str())));\n        }\n    }\n    {\n        // slightly less constrained to make sure `cloaking` gets picked last.\n        for i in 1..(BRANCHING_FACTOR + 10) {\n            let vsn = format!(\"1.0.{}\", i);\n            reglist.push(pkg!((\"cloaking\", vsn.as_str()) => [dep_req(\"bad\", \"1.0.1\")]));\n        }\n    }\n\n    let reg = registry(reglist);\n\n    let res = resolve(vec![dep(\"backtrack_trap0\"), dep(\"cloaking\")], &reg);\n\n    assert!(res.is_err());\n}\n\n#[test]\nfn resolving_with_constrained_cousins_backtrack() {\n    let mut reglist = Vec::new();\n\n    const DEPTH: usize = 100;\n    const BRANCHING_FACTOR: usize = 50;\n\n    // Each backtrack_trap depends on the next.\n    // The last depends on a specific ver of constrained.\n    for l in 0..DEPTH {\n        let name = format!(\"backtrack_trap{}\", l);\n        let next = format!(\"backtrack_trap{}\", l + 1);\n        for i in 1..BRANCHING_FACTOR {\n            let vsn = format!(\"1.0.{}\", i);\n            reglist.push(pkg!((name.as_str(), vsn.as_str()) => [dep(next.as_str())]));\n        }\n    }\n    {\n        let name = format!(\"backtrack_trap{}\", DEPTH);\n        for i in 1..BRANCHING_FACTOR {\n            let vsn = format!(\"1.0.{}\", i);\n            reglist.push(\n                pkg!((name.as_str(), vsn.as_str()) => [dep_req(\"constrained\", \">=1.1.0, <=2.0.0\")]),\n            );\n        }\n    }\n    {\n        // slightly less constrained to make sure `constrained` gets picked last.\n        for i in 0..(BRANCHING_FACTOR + 10) {\n            let vsn = format!(\"1.0.{}\", i);\n            reglist.push(pkg!((\"constrained\", vsn.as_str())));\n        }\n        reglist.push(pkg!((\"constrained\", \"1.1.0\")));\n        reglist.push(pkg!((\"constrained\", \"2.0.0\")));\n        reglist.push(pkg!((\"constrained\", \"2.0.1\")));\n    }\n    reglist.push(pkg!((\"cloaking\", \"1.0.0\") => [dep_req(\"constrained\", \"~1.0.0\")]));\n\n    let reg = registry(reglist.clone());\n\n    // `backtrack_trap0 = \"*\"` is a lot of ways of saying `constrained = \">=1.1.0, <=2.0.0\"`\n    // but `constrained= \"2.0.1\"` is already picked.\n    // Only then to try and solve `constrained= \"~1.0.0\"` which is incompatible.\n    let res = resolve(\n        vec![\n            dep(\"backtrack_trap0\"),\n            dep_req(\"constrained\", \"2.0.1\"),\n            dep(\"cloaking\"),\n        ],\n        &reg,\n    );\n\n    assert!(res.is_err());\n\n    // Each level depends on the next but the last depends on incompatible deps.\n    // Let's make sure that we can cache that a dep has incompatible deps.\n    for l in 0..DEPTH {\n        let name = format!(\"level{}\", l);\n        let next = format!(\"level{}\", l + 1);\n        for i in 1..BRANCHING_FACTOR {\n            let vsn = format!(\"1.0.{}\", i);\n            reglist.push(pkg!((name.as_str(), vsn.as_str()) => [dep(next.as_str())]));\n        }\n    }\n    reglist.push(\n        pkg!((format!(\"level{}\", DEPTH).as_str(), \"1.0.0\") => [dep(\"backtrack_trap0\"),\n            dep(\"cloaking\")\n        ]),\n    );\n\n    let reg = registry(reglist);\n\n    let res = resolve(vec![dep(\"level0\"), dep_req(\"constrained\", \"2.0.1\")], &reg);\n\n    assert!(res.is_err());\n\n    let res = resolve(vec![dep(\"level0\"), dep_req(\"constrained\", \"2.0.0\")], &reg).unwrap();\n\n    assert_contains(\n        &res,\n        &names(&[(\"constrained\", \"2.0.0\"), (\"cloaking\", \"1.0.0\")]),\n    );\n}\n\n#[test]\nfn resolving_with_constrained_sibling_backtrack_activation() {\n    // It makes sense to resolve most-constrained deps first, but\n    // with that logic the backtrack traps here come between the two\n    // attempted resolutions of 'constrained'. When backtracking,\n    // cargo should skip past them and resume resolution once the\n    // number of activations for 'constrained' changes.\n    let mut reglist = vec![\n        pkg!((\"foo\", \"1.0.0\") => [dep_req(\"bar\", \"=1.0.0\"),\n                                  dep_req(\"backtrack_trap1\", \"1.0\"),\n                                  dep_req(\"backtrack_trap2\", \"1.0\"),\n                                  dep_req(\"constrained\", \"<=1.0.60\")]),\n        pkg!((\"bar\", \"1.0.0\") => [dep_req(\"constrained\", \">=1.0.60\")]),\n    ];\n    // Bump these to make the test harder, but you'll also need to\n    // change the version constraints on `constrained` above. To correctly\n    // exercise Cargo, the relationship between the values is:\n    // NUM_CONSTRAINED - vsn < NUM_TRAPS < vsn\n    // to make sure the traps are resolved between `constrained`.\n    const NUM_TRAPS: usize = 45; // min 1\n    const NUM_CONSTRAINED: usize = 100; // min 1\n    for i in 0..NUM_TRAPS {\n        let vsn = format!(\"1.0.{}\", i);\n        reglist.push(pkg!((\"backtrack_trap1\", vsn.clone())));\n        reglist.push(pkg!((\"backtrack_trap2\", vsn.clone())));\n    }\n    for i in 0..NUM_CONSTRAINED {\n        let vsn = format!(\"1.0.{}\", i);\n        reglist.push(pkg!((\"constrained\", vsn.clone())));\n    }\n    let reg = registry(reglist);\n\n    let res = resolve(vec![dep_req(\"foo\", \"1\")], &reg).unwrap();\n\n    assert_contains(\n        &res,\n        &names(&[\n            (\"root\", \"1.0.0\"),\n            (\"foo\", \"1.0.0\"),\n            (\"bar\", \"1.0.0\"),\n            (\"constrained\", \"1.0.60\"),\n        ]),\n    );\n}\n\n#[test]\nfn resolving_with_constrained_sibling_transitive_dep_effects() {\n    // When backtracking due to a failed dependency, if Cargo is\n    // trying to be clever and skip irrelevant dependencies, care must\n    // be taken to not miss the transitive effects of alternatives. E.g.\n    // in the right-to-left resolution of the graph below, B may\n    // affect whether D is successfully resolved.\n    //\n    //    A\n    //  / | \\\n    // B  C  D\n    // |  |\n    // C  D\n    let reg = registry(vec![\n        pkg!((\"A\", \"1.0.0\") => [dep_req(\"B\", \"1.0\"),\n                                dep_req(\"C\", \"1.0\"),\n                                dep_req(\"D\", \"1.0.100\")]),\n        pkg!((\"B\", \"1.0.0\") => [dep_req(\"C\", \">=1.0.0\")]),\n        pkg!((\"B\", \"1.0.1\") => [dep_req(\"C\", \">=1.0.1\")]),\n        pkg!((\"C\", \"1.0.0\") => [dep_req(\"D\", \"1.0.0\")]),\n        pkg!((\"C\", \"1.0.1\") => [dep_req(\"D\", \">=1.0.1,<1.0.100\")]),\n        pkg!((\"C\", \"1.0.2\") => [dep_req(\"D\", \">=1.0.2,<1.0.100\")]),\n        pkg!((\"D\", \"1.0.0\")),\n        pkg!((\"D\", \"1.0.1\")),\n        pkg!((\"D\", \"1.0.2\")),\n        pkg!((\"D\", \"1.0.100\")),\n        pkg!((\"D\", \"1.0.101\")),\n        pkg!((\"D\", \"1.0.102\")),\n        pkg!((\"D\", \"1.0.103\")),\n        pkg!((\"D\", \"1.0.104\")),\n        pkg!((\"D\", \"1.0.105\")),\n    ]);\n\n    let res = resolve(vec![dep_req(\"A\", \"1\")], &reg).unwrap();\n\n    assert_same(\n        &res,\n        &names(&[\n            (\"root\", \"1.0.0\"),\n            (\"A\", \"1.0.0\"),\n            (\"B\", \"1.0.0\"),\n            (\"C\", \"1.0.0\"),\n            (\"D\", \"1.0.105\"),\n        ]),\n    );\n}\n\n#[test]\nfn incomplete_information_skipping() {\n    // When backtracking due to a failed dependency, if Cargo is\n    // trying to be clever and skip irrelevant dependencies, care must\n    // be taken to not miss the transitive effects of alternatives.\n    // Fuzzing discovered that for some reason cargo was skipping based\n    // on incomplete information in the following case:\n    // minimized bug found in:\n    // https://github.com/rust-lang/cargo/commit/003c29b0c71e5ea28fbe8e72c148c755c9f3f8d9\n    let input = vec![\n        pkg!((\"a\", \"1.0.0\")),\n        pkg!((\"a\", \"1.1.0\")),\n        pkg!(\"b\" => [dep(\"a\")]),\n        pkg!((\"c\", \"1.0.0\")),\n        pkg!((\"c\", \"1.1.0\")),\n        pkg!(\"d\" => [dep_req(\"c\", \"=1.0\")]),\n        pkg!((\"e\", \"1.0.0\")),\n        pkg!((\"e\", \"1.1.0\") => [dep_req(\"c\", \"1.1\")]),\n        pkg!(\"to_yank\"),\n        pkg!((\"f\", \"1.0.0\") => [\n            dep(\"to_yank\"),\n            dep(\"d\"),\n        ]),\n        pkg!((\"f\", \"1.1.0\") => [dep(\"d\")]),\n        pkg!(\"g\" => [\n            dep(\"b\"),\n            dep(\"e\"),\n            dep(\"f\"),\n        ]),\n    ];\n    let reg = registry(input.clone());\n\n    let res = resolve(vec![dep(\"g\")], &reg).unwrap();\n    let package_to_yank = \"to_yank\".to_pkgid();\n    // this package is not used in the resolution.\n    assert!(!res.contains(&package_to_yank));\n    // so when we yank it\n    let new_reg = registry(\n        input\n            .iter()\n            .filter(|&x| package_to_yank != x.package_id())\n            .cloned()\n            .collect(),\n    );\n    assert_eq!(input.len(), new_reg.len() + 1);\n    // it should still build\n    assert!(resolve(vec![dep(\"g\")], &new_reg).is_ok());\n}\n\n#[test]\nfn incomplete_information_skipping_2() {\n    // When backtracking due to a failed dependency, if Cargo is\n    // trying to be clever and skip irrelevant dependencies, care must\n    // be taken to not miss the transitive effects of alternatives.\n    // Fuzzing discovered that for some reason cargo was skipping based\n    // on incomplete information in the following case:\n    // https://github.com/rust-lang/cargo/commit/003c29b0c71e5ea28fbe8e72c148c755c9f3f8d9\n    let input = vec![\n        pkg!((\"b\", \"3.8.10\")),\n        pkg!((\"b\", \"8.7.4\")),\n        pkg!((\"b\", \"9.4.6\")),\n        pkg!((\"c\", \"1.8.8\")),\n        pkg!((\"c\", \"10.2.5\")),\n        pkg!((\"d\", \"4.1.2\") => [\n            dep_req(\"bad\", \"=6.10.9\"),\n        ]),\n        pkg!((\"d\", \"5.5.6\")),\n        pkg!((\"d\", \"5.6.10\")),\n        pkg!((\"to_yank\", \"8.0.1\")),\n        pkg!((\"to_yank\", \"8.8.1\")),\n        pkg!((\"e\", \"4.7.8\") => [\n            dep_req(\"d\", \">=5.5.6, <=5.6.10\"),\n            dep_req(\"to_yank\", \"=8.0.1\"),\n        ]),\n        pkg!((\"e\", \"7.4.9\") => [\n            dep_req(\"bad\", \"=4.7.5\"),\n        ]),\n        pkg!(\"f\" => [\n            dep_req(\"d\", \">=4.1.2, <=5.5.6\"),\n        ]),\n        pkg!(\"g\" => [\n            dep(\"bad\"),\n        ]),\n        pkg!((\"h\", \"3.8.3\") => [\n            dep(\"g\"),\n        ]),\n        pkg!((\"h\", \"6.8.3\") => [\n            dep(\"f\"),\n        ]),\n        pkg!((\"h\", \"8.1.9\") => [\n            dep_req(\"to_yank\", \"=8.8.1\"),\n        ]),\n        pkg!(\"i\" => [\n            dep(\"b\"),\n            dep(\"c\"),\n            dep(\"e\"),\n            dep(\"h\"),\n        ]),\n    ];\n    let reg = registry(input.clone());\n\n    let res = resolve(vec![dep(\"i\")], &reg).unwrap();\n    let package_to_yank = (\"to_yank\", \"8.8.1\").to_pkgid();\n    // this package is not used in the resolution.\n    assert!(!res.contains(&package_to_yank));\n    // so when we yank it\n    let new_reg = registry(\n        input\n            .iter()\n            .filter(|&x| package_to_yank != x.package_id())\n            .cloned()\n            .collect(),\n    );\n    assert_eq!(input.len(), new_reg.len() + 1);\n    // it should still build\n    assert!(resolve(vec![dep(\"i\")], &new_reg).is_ok());\n}\n\n#[test]\nfn incomplete_information_skipping_3() {\n    // When backtracking due to a failed dependency, if Cargo is\n    // trying to be clever and skip irrelevant dependencies, care must\n    // be taken to not miss the transitive effects of alternatives.\n    // Fuzzing discovered that for some reason cargo was skipping based\n    // on incomplete information in the following case:\n    // minimized bug found in:\n    // https://github.com/rust-lang/cargo/commit/003c29b0c71e5ea28fbe8e72c148c755c9f3f8d9\n    let input = vec![\n        pkg! {(\"to_yank\", \"3.0.3\")},\n        pkg! {(\"to_yank\", \"3.3.0\")},\n        pkg! {(\"to_yank\", \"3.3.1\")},\n        pkg! {(\"a\", \"3.3.0\") => [\n            dep_req(\"to_yank\", \"=3.0.3\"),\n        ] },\n        pkg! {(\"a\", \"3.3.2\") => [\n            dep_req(\"to_yank\", \"<=3.3.0\"),\n        ] },\n        pkg! {(\"b\", \"0.1.3\") => [\n            dep_req(\"a\", \"=3.3.0\"),\n        ] },\n        pkg! {(\"b\", \"2.0.2\") => [\n            dep_req(\"to_yank\", \"3.3.0\"),\n            dep(\"a\"),\n        ] },\n        pkg! {(\"b\", \"2.3.3\") => [\n            dep_req(\"to_yank\", \"3.3.0\"),\n            dep_req(\"a\", \"=3.3.0\"),\n        ] },\n    ];\n    let reg = registry(input.clone());\n\n    let res = resolve(vec![dep(\"b\")], &reg).unwrap();\n    let package_to_yank = (\"to_yank\", \"3.0.3\").to_pkgid();\n    // this package is not used in the resolution.\n    assert!(!res.contains(&package_to_yank));\n    // so when we yank it\n    let new_reg = registry(\n        input\n            .iter()\n            .filter(|&x| package_to_yank != x.package_id())\n            .cloned()\n            .collect(),\n    );\n    assert_eq!(input.len(), new_reg.len() + 1);\n    // it should still build\n    assert!(resolve(vec![dep(\"b\")], &new_reg).is_ok());\n}\n\n#[test]\nfn resolving_but_no_exists() {\n    let reg = registry(vec![]);\n\n    let res = resolve(vec![dep_req(\"foo\", \"1\")], &reg);\n    assert!(res.is_err());\n\n    assert_eq!(\n        res.err().unwrap().to_string(),\n        \"no matching package named `foo` found\\n\\\n         location searched: registry `https://example.com/`\\n\\\n         required by package `root v1.0.0 (registry `https://example.com/`)`\\\n         \"\n    );\n}\n\n#[test]\nfn resolving_cycle() {\n    let reg = registry(vec![pkg!(\"foo\" => [\"foo\"])]);\n\n    let _ = resolve(vec![dep_req(\"foo\", \"1\")], &reg);\n}\n\n#[test]\nfn hard_equality() {\n    let reg = registry(vec![\n        pkg!((\"foo\", \"1.0.1\")),\n        pkg!((\"foo\", \"1.0.0\")),\n        pkg!((\"bar\", \"1.0.0\") => [dep_req(\"foo\", \"1.0.0\")]),\n    ]);\n\n    let res = resolve(vec![dep_req(\"bar\", \"1\"), dep_req(\"foo\", \"=1.0.0\")], &reg).unwrap();\n\n    assert_same(\n        &res,\n        &names(&[(\"root\", \"1.0.0\"), (\"foo\", \"1.0.0\"), (\"bar\", \"1.0.0\")]),\n    );\n}\n\n#[test]\nfn large_conflict_cache() {\n    let mut input = vec![\n        pkg!((\"last\", \"0.0.0\") => [dep(\"bad\")]), // just to make sure last is less constrained\n    ];\n    let mut root_deps = vec![dep(\"last\")];\n    const NUM_VERSIONS: u8 = 20;\n    for name in 0..=NUM_VERSIONS {\n        // a large number of conflicts can easily be generated by a sys crate.\n        let sys_name = format!(\"{}-sys\", (b'a' + name) as char);\n        let in_len = input.len();\n        input.push(pkg!((\"last\", format!(\"{}.0.0\", in_len)) => [dep_req(&sys_name, \"=0.0.0\")]));\n        root_deps.push(dep_req(&sys_name, \">= 0.0.1\"));\n\n        // a large number of conflicts can also easily be generated by a major release version.\n        let plane_name = format!(\"{}\", (b'a' + name) as char);\n        let in_len = input.len();\n        input.push(pkg!((\"last\", format!(\"{}.0.0\", in_len)) => [dep_req(&plane_name, \"=1.0.0\")]));\n        root_deps.push(dep_req(&plane_name, \">= 1.0.1\"));\n\n        for i in 0..=NUM_VERSIONS {\n            input.push(pkg!((&sys_name, format!(\"{}.0.0\", i))));\n            input.push(pkg!((&plane_name, format!(\"1.0.{}\", i))));\n        }\n    }\n    let reg = registry(input);\n    let _ = resolve(root_deps, &reg);\n}\n\n#[test]\nfn resolving_slow_case_missing_feature() {\n    let mut reg = Vec::new();\n\n    const LAST_CRATE_VERSION_COUNT: usize = 50;\n\n    // increase in resolve time is at least cubic over `INTERMEDIATE_CRATES_VERSION_COUNT`.\n    // it should be `>= LAST_CRATE_VERSION_COUNT` to reproduce slowdown.\n    const INTERMEDIATE_CRATES_VERSION_COUNT: usize = LAST_CRATE_VERSION_COUNT + 5;\n\n    // should be `>= 2` to reproduce slowdown\n    const TRANSITIVE_CRATES_COUNT: usize = 3;\n\n    reg.push(pkg_dep_with((\"last\", \"1.0.0\"), vec![], &[(\"f\", &[])]));\n    for v in 1..LAST_CRATE_VERSION_COUNT {\n        reg.push(pkg((\"last\", format!(\"1.0.{v}\"))));\n    }\n\n    reg.push(pkg_dep(\n        (\"dep\", \"1.0.0\"),\n        vec![\n            dep(\"last\"), // <-- needed to reproduce slowdown\n            dep_req(\"intermediate-1\", \"1.0.0\"),\n        ],\n    ));\n\n    for n in 0..INTERMEDIATE_CRATES_VERSION_COUNT {\n        let version = format!(\"1.0.{n}\");\n        for c in 1..TRANSITIVE_CRATES_COUNT {\n            reg.push(pkg_dep(\n                (format!(\"intermediate-{c}\"), &version),\n                vec![dep_req(&format!(\"intermediate-{}\", c + 1), &version)],\n            ));\n        }\n        reg.push(pkg_dep(\n            (format!(\"intermediate-{TRANSITIVE_CRATES_COUNT}\"), &version),\n            vec![dep_req(\"last\", \"1.0.0\").with(&[\"f\"])],\n        ));\n    }\n\n    let deps = vec![dep(\"dep\")];\n    let _ = resolve(deps, &reg);\n}\n\n#[test]\nfn cyclic_good_error_message() {\n    let input = vec![\n        pkg!((\"A\", \"0.0.0\") => [dep(\"C\")]),\n        pkg!((\"B\", \"0.0.0\") => [dep(\"C\")]),\n        pkg!((\"C\", \"0.0.0\") => [dep(\"A\")]),\n    ];\n    let reg = registry(input);\n    let error = resolve(vec![dep(\"A\"), dep(\"B\")], &reg).unwrap_err();\n    println!(\"{}\", error);\n    assert_eq!(\"\\\ncyclic package dependency: package `A v0.0.0 (registry `https://example.com/`)` depends on itself. Cycle:\npackage `A v0.0.0 (registry `https://example.com/`)`\n    ... which satisfies dependency `A = \\\"*\\\"` of package `C v0.0.0 (registry `https://example.com/`)`\n    ... which satisfies dependency `C = \\\"*\\\"` of package `A v0.0.0 (registry `https://example.com/`)`\\\n\", error.to_string());\n}\n\n#[test]\nfn shortest_path_in_error_message() {\n    let input = vec![\n        pkg!((\"F\", \"0.1.2\")),\n        pkg!((\"F\", \"0.1.1\") => [dep(\"bad\"),]),\n        pkg!((\"F\", \"0.1.0\") => [dep(\"bad\"),]),\n        pkg!(\"E\" => [dep_req(\"F\", \"^0.1.2\"),]),\n        pkg!(\"D\" => [dep_req(\"F\", \"^0.1.2\"),]),\n        pkg!(\"C\" => [dep(\"D\"),]),\n        pkg!(\"A\" => [dep(\"C\"),dep(\"E\"),dep_req(\"F\", \"<=0.1.1\"),]),\n    ];\n    let error = resolve(vec![dep(\"A\")], &registry(input)).unwrap_err();\n    println!(\"{}\", error);\n    assert_eq!(\n        \"\\\nfailed to select a version for `F`.\n    ... required by package `A v1.0.0 (registry `https://example.com/`)`\n    ... which satisfies dependency `A = \\\"*\\\"` of package `root v1.0.0 (registry `https://example.com/`)`\nversions that meet the requirements `<=0.1.1` are: 0.1.1, 0.1.0\n\nall possible versions conflict with previously selected packages.\n\n  previously selected package `F v0.1.2 (registry `https://example.com/`)`\n    ... which satisfies dependency `F = \\\"^0.1.2\\\"` of package `E v1.0.0 (registry `https://example.com/`)`\n    ... which satisfies dependency `E = \\\"*\\\"` of package `A v1.0.0 (registry `https://example.com/`)`\n    ... which satisfies dependency `A = \\\"*\\\"` of package `root v1.0.0 (registry `https://example.com/`)`\n\nfailed to select a version for `F` which could resolve this conflict\\\n    \",\n        error.to_string()\n    );\n}\n"
  },
  {
    "path": "crates/resolver-tests/tests/validated.rs",
    "content": "use cargo::core::{Dependency, dependency::DepKind};\n\nuse resolver_tests::{\n    helpers::{\n        ToDep, dep, dep_kind, dep_platform, dep_req, dep_req_kind, dep_req_platform, pkg, pkg_dep,\n        pkg_dep_with, registry,\n    },\n    pkg, resolve, resolve_and_validated,\n    sat::SatResolver,\n};\n\n#[test]\nfn off_by_one_bug() {\n    let input = vec![\n        pkg!((\"A-sys\", \"0.0.1\")),\n        pkg!((\"A-sys\", \"0.0.4\")),\n        pkg!((\"A-sys\", \"0.0.6\")),\n        pkg!((\"A-sys\", \"0.0.7\")),\n        pkg!((\"NA\", \"0.0.0\") => [dep_req(\"A-sys\", \"<= 0.0.5\"),]),\n        pkg!((\"NA\", \"0.0.1\") => [dep_req(\"A-sys\", \">= 0.0.6, <= 0.0.8\"),]),\n        pkg!((\"a\", \"0.0.1\")),\n        pkg!((\"a\", \"0.0.2\")),\n        pkg!((\"aa\", \"0.0.0\") => [dep_req(\"A-sys\", \">= 0.0.4, <= 0.0.6\"),dep_req(\"NA\", \"<= 0.0.0\"),]),\n        pkg!((\"f\", \"0.0.3\") => [dep(\"NA\"),dep_req(\"a\", \"<= 0.0.2\"),dep(\"aa\"),]),\n    ];\n\n    let reg = registry(input);\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(vec![dep(\"f\")], &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn conflict_store_bug() {\n    let input = vec![\n        pkg!((\"A\", \"0.0.3\")),\n        pkg!((\"A\", \"0.0.5\")),\n        pkg!((\"A\", \"0.0.9\") => [dep(\"bad\"),]),\n        pkg!((\"A\", \"0.0.10\") => [dep(\"bad\"),]),\n        pkg!((\"L-sys\", \"0.0.1\") => [dep(\"bad\"),]),\n        pkg!((\"L-sys\", \"0.0.5\")),\n        pkg!((\"R\", \"0.0.4\") => [\n            dep_req(\"L-sys\", \"= 0.0.5\"),\n        ]),\n        pkg!((\"R\", \"0.0.6\")),\n        pkg!((\"a-sys\", \"0.0.5\")),\n        pkg!((\"a-sys\", \"0.0.11\")),\n        pkg!((\"c\", \"0.0.12\") => [\n            dep_req(\"R\", \">= 0.0.3, <= 0.0.4\"),\n        ]),\n        pkg!((\"c\", \"0.0.13\") => [\n            dep_req(\"a-sys\", \">= 0.0.8, <= 0.0.11\"),\n        ]),\n        pkg!((\"c0\", \"0.0.6\") => [\n            dep_req(\"L-sys\", \"<= 0.0.2\"),\n        ]),\n        pkg!((\"c0\", \"0.0.10\") => [\n            dep_req(\"A\", \">= 0.0.9, <= 0.0.10\"),\n            dep_req(\"a-sys\", \"= 0.0.5\"),\n        ]),\n        pkg!(\"j\" => [\n            dep_req(\"A\", \">= 0.0.3, <= 0.0.5\"),\n            dep_req(\"R\", \">=0.0.4, <= 0.0.6\"),\n            dep_req(\"c\", \">= 0.0.9\"),\n            dep_req(\"c0\", \">= 0.0.6\"),\n        ]),\n    ];\n\n    let reg = registry(input);\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(vec![dep(\"j\")], &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn conflict_store_more_then_one_match() {\n    let input = vec![\n        pkg!((\"A\", \"0.0.0\")),\n        pkg!((\"A\", \"0.0.1\")),\n        pkg!((\"A-sys\", \"0.0.0\")),\n        pkg!((\"A-sys\", \"0.0.1\")),\n        pkg!((\"A-sys\", \"0.0.2\")),\n        pkg!((\"A-sys\", \"0.0.3\")),\n        pkg!((\"A-sys\", \"0.0.12\")),\n        pkg!((\"A-sys\", \"0.0.16\")),\n        pkg!((\"B-sys\", \"0.0.0\")),\n        pkg!((\"B-sys\", \"0.0.1\")),\n        pkg!((\"B-sys\", \"0.0.2\") => [dep_req(\"A-sys\", \"= 0.0.12\"),]),\n        pkg!((\"BA-sys\", \"0.0.0\") => [dep_req(\"A-sys\",\"= 0.0.16\"),]),\n        pkg!((\"BA-sys\", \"0.0.1\") => [dep(\"bad\"),]),\n        pkg!((\"BA-sys\", \"0.0.2\") => [dep(\"bad\"),]),\n        pkg!(\"nA\" => [\n            dep(\"A\"),\n            dep_req(\"A-sys\", \"<= 0.0.3\"),\n            dep(\"B-sys\"),\n            dep(\"BA-sys\"),\n        ]),\n    ];\n    let reg = registry(input);\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(vec![dep(\"nA\")], &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn bad_lockfile_from_8249() {\n    let input = vec![\n        pkg!((\"a-sys\", \"0.2.0\")),\n        pkg!((\"a-sys\", \"0.1.0\")),\n        pkg!((\"b\", \"0.1.0\") => [\n            dep_req(\"a-sys\", \"0.1\"), // should be optional: true, but not needed for now\n        ]),\n        pkg!((\"c\", \"1.0.0\") => [\n            dep_req(\"b\", \"=0.1.0\"),\n        ]),\n        pkg!(\"foo\" => [\n            dep_req(\"a-sys\", \"=0.2.0\"),\n            {\n                let mut b = dep_req(\"b\", \"=0.1.0\");\n                b.set_features(vec![\"a-sys\"]);\n                b\n            },\n            dep_req(\"c\", \"=1.0.0\"),\n        ]),\n    ];\n    let reg = registry(input);\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(vec![dep(\"foo\")], &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn registry_with_features() {\n    let reg = registry(vec![\n        pkg!(\"a\"),\n        pkg!(\"b\"),\n        pkg_dep_with(\n            \"image\",\n            vec![\"a\".opt(), \"b\".opt(), \"jpg\".to_dep()],\n            &[(\"default\", &[\"a\"]), (\"b\", &[\"dep:b\"])],\n        ),\n        pkg!(\"jpg\"),\n        pkg!(\"log\"),\n        pkg!(\"man\"),\n        pkg_dep_with(\"rgb\", vec![\"man\".opt()], &[(\"man\", &[\"dep:man\"])]),\n        pkg_dep_with(\n            \"dep\",\n            vec![\"image\".with(&[\"b\"]), \"log\".opt(), \"rgb\".opt()],\n            &[\n                (\"default\", &[\"log\", \"image/default\"]),\n                (\"man\", &[\"rgb?/man\"]),\n            ],\n        ),\n    ]);\n\n    for deps in [\n        vec![\"dep\".with(&[\"default\", \"man\", \"log\", \"rgb\"])],\n        vec![\"dep\".with(&[\"default\"])],\n        vec![\"dep\".with(&[])],\n        vec![\"dep\".with(&[\"man\"])],\n        vec![\"dep\".with(&[\"man\", \"rgb\"])],\n    ] {\n        let mut sat_resolver = SatResolver::new(&reg);\n        assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n    }\n}\n\n#[test]\nfn missing_feature() {\n    let reg = registry(vec![pkg!(\"a\")]);\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(vec![\"a\".with(&[\"f\"])], &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn missing_dep_feature() {\n    let reg = registry(vec![\n        pkg(\"a\"),\n        pkg_dep_with(\"dep\", vec![dep(\"a\")], &[(\"f\", &[\"a/a\"])]),\n    ]);\n\n    let deps = vec![dep(\"dep\").with(&[\"f\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn missing_weak_dep_feature() {\n    let reg = registry(vec![\n        pkg(\"a\"),\n        pkg_dep_with(\"dep1\", vec![dep(\"a\")], &[(\"f\", &[\"a/a\"])]),\n        pkg_dep_with(\"dep2\", vec![\"a\".opt()], &[(\"f\", &[\"a/a\"])]),\n        pkg_dep_with(\"dep3\", vec![\"a\".opt()], &[(\"f\", &[\"a?/a\"])]),\n        pkg_dep_with(\"dep4\", vec![\"x\".opt()], &[(\"f\", &[\"x?/a\"])]),\n    ]);\n\n    let deps = vec![dep(\"dep1\").with(&[\"f\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n\n    let deps = vec![dep(\"dep2\").with(&[\"f\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n\n    let deps = vec![dep(\"dep2\").with(&[\"a\", \"f\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n\n    // Weak dependencies are not supported yet in the dependency resolver\n    let deps = vec![dep(\"dep3\").with(&[\"f\"])];\n    assert!(resolve(deps.clone(), &reg).is_err());\n    assert!(SatResolver::new(&reg).sat_resolve(&deps));\n\n    let deps = vec![dep(\"dep3\").with(&[\"a\", \"f\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n\n    // Weak dependencies are not supported yet in the dependency resolver\n    let deps = vec![dep(\"dep4\").with(&[\"f\"])];\n    assert!(resolve(deps.clone(), &reg).is_err());\n    assert!(SatResolver::new(&reg).sat_resolve(&deps));\n\n    let deps = vec![dep(\"dep4\").with(&[\"x\", \"f\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn conflict_feature_and_sys() {\n    let reg = registry(vec![\n        pkg((\"a-sys\", \"1.0.0\")),\n        pkg((\"a-sys\", \"2.0.0\")),\n        pkg_dep_with(\n            (\"a\", \"1.0.0\"),\n            vec![dep_req(\"a-sys\", \"1.0.0\")],\n            &[(\"f\", &[])],\n        ),\n        pkg_dep_with(\n            (\"a\", \"2.0.0\"),\n            vec![dep_req(\"a-sys\", \"2.0.0\")],\n            &[(\"g\", &[])],\n        ),\n        pkg_dep(\"dep\", vec![dep_req(\"a\", \"2.0.0\")]),\n    ]);\n\n    let deps = vec![dep_req(\"a\", \"*\").with(&[\"f\"]), dep(\"dep\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn conflict_weak_features() {\n    let reg = registry(vec![\n        pkg((\"a-sys\", \"1.0.0\")),\n        pkg((\"a-sys\", \"2.0.0\")),\n        pkg_dep(\"a1\", vec![dep_req(\"a-sys\", \"1.0.0\").opt()]),\n        pkg_dep(\"a2\", vec![dep_req(\"a-sys\", \"2.0.0\").opt()]),\n        pkg_dep_with(\n            \"dep\",\n            vec![\"a1\".opt(), \"a2\".opt()],\n            &[(\"a1\", &[\"a1?/a-sys\"]), (\"a2\", &[\"a2?/a-sys\"])],\n        ),\n    ]);\n\n    let deps = vec![dep(\"dep\").with(&[\"a1\", \"a2\"])];\n\n    // Weak dependencies are not supported yet in the dependency resolver\n    assert!(resolve(deps.clone(), &reg).is_err());\n    assert!(SatResolver::new(&reg).sat_resolve(&deps));\n}\n\n#[test]\nfn multiple_dep_kinds_and_targets() {\n    let reg = registry(vec![\n        pkg((\"a-sys\", \"1.0.0\")),\n        pkg((\"a-sys\", \"2.0.0\")),\n        pkg_dep_with(\n            \"dep1\",\n            vec![\n                dep_req_platform(\"a-sys\", \"1.0.0\", \"cfg(all())\").opt(),\n                dep_req(\"a-sys\", \"1.0.0\").opt(),\n                dep_req_kind(\"a-sys\", \"2.0.0\", DepKind::Build).opt(),\n            ],\n            &[(\"default\", &[\"dep:a-sys\"])],\n        ),\n        pkg_dep_with(\n            \"dep2\",\n            vec![\n                dep_req_platform(\"a-sys\", \"1.0.0\", \"cfg(all())\").opt(),\n                dep_req(\"a-sys\", \"1.0.0\").opt(),\n                dep_req_kind(\"a-sys\", \"2.0.0\", DepKind::Development).rename(\"a-sys-dev\"),\n            ],\n            &[(\"default\", &[\"dep:a-sys\", \"a-sys-dev/bad\"])],\n        ),\n    ]);\n\n    let deps = vec![dep(\"dep1\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n\n    let deps = vec![dep(\"dep2\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n\n    let deps = vec![\n        dep_req(\"a-sys\", \"1.0.0\"),\n        dep_req_kind(\"a-sys\", \"2.0.0\", DepKind::Build).rename(\"a2\"),\n    ];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n\n    let deps = vec![\n        dep_req(\"a-sys\", \"1.0.0\"),\n        dep_req_kind(\"a-sys\", \"2.0.0\", DepKind::Development).rename(\"a2\"),\n    ];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn multiple_dep_kinds_and_targets_with_different_packages() {\n    let reg = registry(vec![\n        pkg_dep_with(\"a\", vec![], &[(\"f\", &[])]),\n        pkg_dep_with(\"b\", vec![], &[(\"f\", &[])]),\n        pkg_dep_with(\"c\", vec![], &[(\"g\", &[])]),\n        pkg_dep_with(\n            \"dep1\",\n            vec![\n                \"a\".opt().rename(\"x\").with(&[\"f\"]),\n                dep_platform(\"a\", \"cfg(all())\").opt().rename(\"x\"),\n                dep_kind(\"b\", DepKind::Build).opt().rename(\"x\").with(&[\"f\"]),\n            ],\n            &[(\"default\", &[\"x\"])],\n        ),\n        pkg_dep_with(\n            \"dep2\",\n            vec![\n                \"a\".opt().rename(\"x\").with(&[\"f\"]),\n                dep_platform(\"a\", \"cfg(all())\").opt().rename(\"x\"),\n                dep_kind(\"c\", DepKind::Build).opt().rename(\"x\").with(&[\"f\"]),\n            ],\n            &[(\"default\", &[\"x\"])],\n        ),\n    ]);\n\n    let deps = vec![\"dep1\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n\n    let deps = vec![\"dep2\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn dep_feature_with_shadowing_feature() {\n    let reg = registry(vec![\n        pkg_dep_with(\"a\", vec![], &[(\"b\", &[])]),\n        pkg_dep_with(\n            \"dep\",\n            vec![\"a\".opt().rename(\"aa\"), \"c\".opt()],\n            &[(\"default\", &[\"aa/b\"]), (\"aa\", &[\"c\"])],\n        ),\n    ]);\n\n    let deps = vec![\"dep\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn dep_feature_not_optional_with_shadowing_feature() {\n    let reg = registry(vec![\n        pkg_dep_with(\"a\", vec![], &[(\"b\", &[])]),\n        pkg_dep_with(\n            \"dep\",\n            vec![\"a\".rename(\"aa\"), \"c\".opt()],\n            &[(\"default\", &[\"aa/b\"]), (\"aa\", &[\"c\"])],\n        ),\n    ]);\n\n    let deps = vec![\"dep\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn dep_feature_weak_with_shadowing_feature() {\n    let reg = registry(vec![\n        pkg_dep_with(\"a\", vec![], &[(\"b\", &[])]),\n        pkg_dep_with(\n            \"dep\",\n            vec![\"a\".opt().rename(\"aa\"), \"c\".opt()],\n            &[(\"default\", &[\"aa?/b\"]), (\"aa\", &[\"c\"])],\n        ),\n    ]);\n\n    let deps = vec![\"dep\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn dep_feature_duplicate_with_shadowing_feature() {\n    let reg = registry(vec![\n        pkg_dep_with(\"a\", vec![], &[(\"b\", &[])]),\n        pkg_dep_with(\n            \"dep\",\n            vec![\n                \"a\".opt().rename(\"aa\"),\n                dep_kind(\"a\", DepKind::Build).rename(\"aa\"),\n                \"c\".opt(),\n            ],\n            &[(\"default\", &[\"aa/b\"]), (\"aa\", &[\"c\"])],\n        ),\n    ]);\n\n    let deps = vec![\"dep\".with(&[\"default\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n}\n\n#[test]\nfn optional_dep_features() {\n    let reg = registry(vec![\n        pkg_dep(\"a\", vec![\"bad\".opt()]),\n        pkg_dep(\"b\", vec![\"a\".opt().with(&[\"bad\"])]),\n        pkg_dep(\"dep\", vec![dep(\"a\"), dep(\"b\")]),\n    ]);\n\n    let deps = vec![dep(\"dep\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn optional_dep_features_with_rename() {\n    let reg = registry(vec![\n        pkg(\"x1\"),\n        pkg_dep(\"a\", vec![\"x1\".opt(), \"x2\".opt(), \"x3\".opt()]),\n        pkg_dep(\n            \"dep1\",\n            vec![\n                \"a\".opt().with(&[\"x1\"]),\n                dep_kind(\"a\", DepKind::Build).opt().with(&[\"x2\"]),\n            ],\n        ),\n        pkg_dep(\n            \"dep2\",\n            vec![\n                \"a\".opt().with(&[\"x1\"]),\n                \"a\".opt().rename(\"a2\").with(&[\"x3\"]),\n            ],\n        ),\n    ]);\n\n    let deps = vec![\"dep1\".with(&[\"a\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_err());\n\n    let deps = vec![\"dep2\".with(&[\"a\"])];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n\n#[test]\nfn optional_weak_dep_features() {\n    let reg = registry(vec![\n        pkg_dep(\"a\", vec![\"bad\".opt()]),\n        pkg_dep(\"b\", vec![dep(\"a\")]),\n        pkg_dep_with(\"dep\", vec![\"a\".opt(), dep(\"b\")], &[(\"f\", &[\"a?/bad\"])]),\n    ]);\n\n    let deps = vec![\"dep\".with(&[\"f\"])];\n\n    // Weak dependencies are not supported yet in the dependency resolver\n    assert!(resolve(deps.clone(), &reg).is_err());\n    assert!(SatResolver::new(&reg).sat_resolve(&deps));\n}\n\n#[test]\nfn default_feature_multiple_major_versions() {\n    let reg = registry(vec![\n        pkg_dep_with((\"a\", \"0.2.0\"), vec![], &[(\"default\", &[])]),\n        pkg((\"a\", \"0.3.0\")),\n        pkg_dep_with((\"a\", \"0.4.0\"), vec![], &[(\"default\", &[])]),\n        pkg_dep(\n            \"dep1\",\n            vec![\n                dep_req(\"a\", \">=0.2, <0.4\").with_default(),\n                dep_req(\"a\", \"0.2\").rename(\"a2\").with(&[]),\n            ],\n        ),\n        pkg_dep(\n            \"dep2\",\n            vec![\n                dep_req(\"a\", \">=0.2, <0.4\").with_default(),\n                dep_req(\"a\", \"0.3\").rename(\"a2\").with(&[]),\n            ],\n        ),\n        pkg_dep(\n            \"dep3\",\n            vec![\n                dep_req(\"a\", \">=0.2, <0.4\").with_default(),\n                dep_req(\"a\", \"0.2\").rename(\"a1\").with(&[]),\n                dep_req(\"a\", \"0.3\").rename(\"a2\").with(&[]),\n            ],\n        ),\n        pkg_dep(\"dep4\", vec![dep_req(\"a\", \">=0.2, <0.4\").with_default()]),\n        pkg_dep(\"dep5\", vec![dep_req(\"a\", \">=0.3, <0.5\").with_default()]),\n    ]);\n\n    let deps = vec![dep(\"dep1\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n\n    let deps = vec![dep(\"dep2\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n\n    let deps = vec![dep(\"dep3\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n\n    let deps = vec![dep(\"dep4\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n\n    let deps = vec![dep(\"dep5\")];\n    let mut sat_resolver = SatResolver::new(&reg);\n    assert!(resolve_and_validated(deps, &reg, &mut sat_resolver).is_ok());\n}\n"
  },
  {
    "path": "crates/rustfix/CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n## [0.4.6] - 2019-07-16\n\n### Changed\n\nInternal changes:\n\n- Change example to automatically determine filename\n- Migrate to Rust 2018\n- use `derive` feature over `serde_derive` crate\n\n## [0.4.5] - 2019-03-26\n\n### Added\n\n- Implement common traits for Diagnostic and related types\n\n### Fixed\n\n- Fix out of bounds access in parse_snippet\n\n## [0.4.4] - 2018-12-13\n\n### Added\n\n- Make Diagnostic::rendered public.\n\n### Changed\n\n- Revert faulty \"Allow multiple solutions in a suggestion\"\n\n## [0.4.3] - 2018-12-09 - *yanked!*\n\n### Added\n\n- Allow multiple solutions in a suggestion\n\n### Changed\n\n- use `RUSTC` environment var if present\n\n## [0.4.2] - 2018-07-31\n\n### Added\n\n- Expose an interface to apply fixes on-by-one\n\n### Changed\n\n- Handle invalid snippets instead of panicking\n\n## [0.4.1] - 2018-07-26\n\n### Changed\n\n- Ignore duplicate replacements\n\n## [0.4.0] - 2018-05-23\n\n### Changed\n\n- Filter by machine applicability by default\n\n[Unreleased]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.6...HEAD\n[0.4.6]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.5...rustfix-0.4.6\n[0.4.5]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.4...rustfix-0.4.5\n[0.4.4]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.3...rustfix-0.4.4\n[0.4.3]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.2...rustfix-0.4.3\n[0.4.2]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.1...rustfix-0.4.2\n[0.4.1]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.0...rustfix-0.4.1\n[0.4.0]: https://github.com/rust-lang-nursery/rustfix/compare/rustfix-0.4.0\n"
  },
  {
    "path": "crates/rustfix/Cargo.toml",
    "content": "[package]\nname = \"rustfix\"\nversion = \"0.9.5\"\nauthors = [\n    \"Pascal Hertleif <killercup@gmail.com>\",\n    \"Oliver Schneider <oli-obk@users.noreply.github.com>\",\n]\nrust-version.workspace = true\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"Automatically apply the suggestions made by rustc\"\ndocumentation = \"https://docs.rs/rustfix\"\nexclude = [\n    \"examples/*\",\n    \"tests/*\",\n]\n\n[dependencies]\nserde = { workspace = true, features = [\"derive\"] }\nserde_json.workspace = true\nthiserror.workspace = true\ntracing.workspace = true\n\n[dev-dependencies]\nanyhow.workspace = true\nproptest.workspace = true\nsimilar.workspace = true\ntempfile.workspace = true\ntracing-subscriber.workspace = true\nsnapbox.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/rustfix/README.md",
    "content": "# rustfix\n\n[![Latest Version](https://img.shields.io/crates/v/rustfix.svg)](https://crates.io/crates/rustfix)\n[![Rust Documentation](https://docs.rs/rustfix/badge.svg)](https://docs.rs/rustfix)\n\nRustfix is a library defining useful structures that represent fix suggestions from rustc.\n\nThis is a low-level library. You pass it the JSON output from `rustc`, and you can then use it to apply suggestions to in-memory strings. This library doesn't execute commands, or read or write from the filesystem.\n\nIf you are looking for the [`cargo fix`] implementation, the core of it is located in [`cargo::ops::fix`].\n\n> This crate is maintained by the Cargo team, primarily for use by Cargo and Rust compiler test suite\n> and not intended for external use (except as a transitive dependency). This\n> crate may make major changes to its APIs or be deprecated without warning.\n\n[`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html\n[`cargo::ops::fix`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/ops/fix.rs\n\n## License\n\nLicensed under either of\n\n- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)\n- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)\n\nat your option.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally\nsubmitted for inclusion in the work by you, as defined in the Apache-2.0\nlicense, shall be dual licensed as above, without any additional terms or\nconditions.\n"
  },
  {
    "path": "crates/rustfix/examples/fix-json.rs",
    "content": "#![allow(clippy::print_stderr)]\n\nuse std::io::{BufReader, Read, stdin};\nuse std::{collections::HashMap, collections::HashSet, env, fs};\n\nuse anyhow::Error;\n\nfn main() -> Result<(), Error> {\n    let suggestions_file = env::args().nth(1).expect(\"USAGE: fix-json <file or -->\");\n    let suggestions = if suggestions_file == \"--\" {\n        let mut buffer = String::new();\n        BufReader::new(stdin()).read_to_string(&mut buffer)?;\n        buffer\n    } else {\n        fs::read_to_string(&suggestions_file)?\n    };\n    let suggestions = rustfix::get_suggestions_from_json(\n        &suggestions,\n        &HashSet::new(),\n        rustfix::Filter::Everything,\n    )?;\n\n    let mut files = HashMap::new();\n    for suggestion in suggestions {\n        let file = suggestion.solutions[0].replacements[0]\n            .snippet\n            .file_name\n            .clone();\n        files.entry(file).or_insert_with(Vec::new).push(suggestion);\n    }\n\n    for (source_file, suggestions) in &files {\n        let source = fs::read_to_string(source_file)?;\n        let mut fix = rustfix::CodeFix::new(&source);\n        for suggestion in suggestions.iter().rev() {\n            if let Err(e) = fix.apply(suggestion) {\n                eprintln!(\"Failed to apply suggestion to {}: {}\", source_file, e);\n            }\n        }\n        let fixes = fix.finish()?;\n        fs::write(source_file, fixes)?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "crates/rustfix/proptest-regressions/replace.txt",
    "content": "# Seeds for failure cases proptest has generated in the past. It is\n# automatically read and these particular cases re-run before any\n# novel cases are generated.\n#\n# It is recommended to check this file in to source control so that\n# everyone who runs the test benefits from these saved cases.\nxs 358148376 3634975642 2528447681 3675516813 # shrinks to ref s = \"\"\nxs 3127423015 3362740891 2605681441 2390162043 # shrinks to ref data = \"\", ref replacements = [(0..0, [])]\n"
  },
  {
    "path": "crates/rustfix/src/diagnostics.rs",
    "content": "//! Rustc Diagnostic JSON Output.\n//!\n//! The following data types are copied from [rust-lang/rust](https://github.com/rust-lang/rust/blob/4fd68eb47bad1c121417ac4450b2f0456150db86/compiler/rustc_errors/src/json.rs).\n//!\n//! For examples of the JSON output, see JSON fixture files under `tests/` directory.\n\nuse serde::Deserialize;\n\n/// The root diagnostic JSON output emitted by the compiler.\n#[derive(Clone, Deserialize, Debug, Hash, Eq, PartialEq)]\npub struct Diagnostic {\n    /// The primary error message.\n    pub message: String,\n    pub code: Option<DiagnosticCode>,\n    /// \"error: internal compiler error\", \"error\", \"warning\", \"note\", \"help\".\n    level: String,\n    pub spans: Vec<DiagnosticSpan>,\n    /// Associated diagnostic messages.\n    pub children: Vec<Diagnostic>,\n    /// The message as rustc would render it.\n    pub rendered: Option<String>,\n}\n\n/// Span information of a diagnostic item.\n#[derive(Clone, Deserialize, Debug, Hash, Eq, PartialEq)]\npub struct DiagnosticSpan {\n    pub file_name: String,\n    pub byte_start: u32,\n    pub byte_end: u32,\n    /// 1-based.\n    pub line_start: usize,\n    pub line_end: usize,\n    /// 1-based, character offset.\n    pub column_start: usize,\n    pub column_end: usize,\n    /// Is this a \"primary\" span -- meaning the point, or one of the points,\n    /// where the error occurred?\n    pub is_primary: bool,\n    /// Source text from the start of `line_start` to the end of `line_end`.\n    pub text: Vec<DiagnosticSpanLine>,\n    /// Label that should be placed at this location (if any)\n    label: Option<String>,\n    /// If we are suggesting a replacement, this will contain text\n    /// that should be sliced in atop this span.\n    pub suggested_replacement: Option<String>,\n    /// If the suggestion is approximate\n    pub suggestion_applicability: Option<Applicability>,\n    /// Macro invocations that created the code at this span, if any.\n    expansion: Option<Box<DiagnosticSpanMacroExpansion>>,\n}\n\n/// Indicates the confidence in the correctness of a suggestion.\n///\n/// All suggestions are marked with an `Applicability`. Tools use the applicability of a suggestion\n/// to determine whether it should be automatically applied or if the user should be consulted\n/// before applying the suggestion.\n#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Hash, Eq)]\npub enum Applicability {\n    /// The suggestion is definitely what the user intended, or maintains the exact meaning of the code.\n    /// This suggestion should be automatically applied.\n    ///\n    /// In case of multiple `MachineApplicable` suggestions (whether as part of\n    /// the same `multipart_suggestion` or not), all of them should be\n    /// automatically applied.\n    MachineApplicable,\n\n    /// The suggestion may be what the user intended, but it is uncertain. The suggestion should\n    /// result in valid Rust code if it is applied.\n    MaybeIncorrect,\n\n    /// The suggestion contains placeholders like `(...)` or `{ /* fields */ }`. The suggestion\n    /// cannot be applied automatically because it will not result in valid Rust code. The user\n    /// will need to fill in the placeholders.\n    HasPlaceholders,\n\n    /// The applicability of the suggestion is unknown.\n    Unspecified,\n}\n\n/// Span information of a single line.\n#[derive(Clone, Deserialize, Debug, Eq, PartialEq, Hash)]\npub struct DiagnosticSpanLine {\n    pub text: String,\n\n    /// 1-based, character offset in self.text.\n    pub highlight_start: usize,\n\n    pub highlight_end: usize,\n}\n\n/// Span information for macro expansions.\n#[derive(Clone, Deserialize, Debug, Eq, PartialEq, Hash)]\nstruct DiagnosticSpanMacroExpansion {\n    /// span where macro was applied to generate this code; note that\n    /// this may itself derive from a macro (if\n    /// `span.expansion.is_some()`)\n    span: DiagnosticSpan,\n\n    /// name of macro that was applied (e.g., \"foo!\" or \"#[derive(Eq)]\")\n    macro_decl_name: String,\n\n    /// span where macro was defined (if known)\n    def_site_span: Option<DiagnosticSpan>,\n}\n\n/// The error code emitted by the compiler. See [Rust error codes index].\n///\n/// [Rust error codes index]: https://doc.rust-lang.org/error_codes/error-index.html\n#[derive(Clone, Deserialize, Debug, Eq, PartialEq, Hash)]\npub struct DiagnosticCode {\n    /// The code itself.\n    pub code: String,\n    /// An explanation for the code.\n    explanation: Option<String>,\n}\n"
  },
  {
    "path": "crates/rustfix/src/error.rs",
    "content": "//! Error types.\n\nuse std::ops::Range;\n\n#[non_exhaustive]\n#[derive(Debug, thiserror::Error)]\npub enum Error {\n    #[error(\"invalid range {0:?}, start is larger than end\")]\n    InvalidRange(Range<usize>),\n\n    #[error(\"invalid range {0:?}, original data is only {1} byte long\")]\n    DataLengthExceeded(Range<usize>, usize),\n\n    #[non_exhaustive]\n    #[error(\"cannot replace slice of data that was already replaced\")]\n    AlreadyReplaced {\n        /// The location of the intended replacement.\n        range: Range<usize>,\n        /// Whether the modification exactly matches (both range and data) the one it conflicts with.\n        /// Some clients may wish to simply ignore this condition.\n        is_identical: bool,\n    },\n\n    #[error(transparent)]\n    Utf8(#[from] std::string::FromUtf8Error),\n}\n"
  },
  {
    "path": "crates/rustfix/src/lib.rs",
    "content": "//! Library for applying diagnostic suggestions to source code.\n//!\n//! This is a low-level library. You pass it the [JSON output] from `rustc`,\n//! and you can then use it to apply suggestions to in-memory strings.\n//! This library doesn't execute commands, or read or write from the filesystem.\n//!\n//! If you are looking for the [`cargo fix`] implementation, the core of it is\n//! located in [`cargo::ops::fix`].\n//!\n//! [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html\n//! [`cargo::ops::fix`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/ops/fix.rs\n//! [JSON output]: diagnostics\n//!\n//! The general outline of how to use this library is:\n//!\n//! 1. Call `rustc` and collect the JSON data.\n//! 2. Pass the json data to [`get_suggestions_from_json`].\n//! 3. Create a [`CodeFix`] with the source of a file to modify.\n//! 4. Call [`CodeFix::apply`] to apply a change.\n//! 5. Call [`CodeFix::finish`] to get the result and write it back to disk.\n//!\n//! > This crate is maintained by the Cargo team, primarily for use by Cargo and Rust compiler test suite\n//! > and not intended for external use (except as a transitive dependency). This\n//! > crate may make major changes to its APIs or be deprecated without warning.\n\nuse std::collections::HashSet;\nuse std::ops::Range;\n\npub mod diagnostics;\nmod error;\nmod replace;\n\nuse diagnostics::Diagnostic;\nuse diagnostics::DiagnosticSpan;\npub use error::Error;\n\n/// A filter to control which suggestion should be applied.\n#[derive(Debug, Clone, Copy)]\npub enum Filter {\n    /// For [`diagnostics::Applicability::MachineApplicable`] only.\n    MachineApplicableOnly,\n    /// Everything is included. YOLO!\n    Everything,\n}\n\n/// Collects code [`Suggestion`]s from one or more compiler diagnostic lines.\n///\n/// Fails if any of diagnostic line `input` is not a valid [`Diagnostic`] JSON.\n///\n/// * `only` --- only diagnostics with code in a set of error codes would be collected.\npub fn get_suggestions_from_json<S: ::std::hash::BuildHasher>(\n    input: &str,\n    only: &HashSet<String, S>,\n    filter: Filter,\n) -> serde_json::error::Result<Vec<Suggestion>> {\n    let mut result = Vec::new();\n    for cargo_msg in serde_json::Deserializer::from_str(input).into_iter::<Diagnostic>() {\n        // One diagnostic line might have multiple suggestions\n        result.extend(collect_suggestions(&cargo_msg?, only, filter));\n    }\n    Ok(result)\n}\n\n#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]\npub struct LinePosition {\n    pub line: usize,\n    pub column: usize,\n}\n\nimpl std::fmt::Display for LinePosition {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}:{}\", self.line, self.column)\n    }\n}\n\n#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]\npub struct LineRange {\n    pub start: LinePosition,\n    pub end: LinePosition,\n}\n\nimpl std::fmt::Display for LineRange {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}-{}\", self.start, self.end)\n    }\n}\n\n/// An error/warning and possible solutions for fixing it\n#[derive(Debug, Clone, Hash, PartialEq, Eq)]\npub struct Suggestion {\n    pub message: String,\n    pub snippets: Vec<Snippet>,\n    pub solutions: Vec<Solution>,\n}\n\n/// Solution to a diagnostic item.\n#[derive(Debug, Clone, Hash, PartialEq, Eq)]\npub struct Solution {\n    /// The error message of the diagnostic item.\n    pub message: String,\n    /// Possible solutions to fix the error.\n    pub replacements: Vec<Replacement>,\n}\n\n/// Represents code that will get replaced.\n#[derive(Debug, Clone, Hash, PartialEq, Eq)]\npub struct Snippet {\n    pub file_name: String,\n    pub line_range: LineRange,\n    pub range: Range<usize>,\n}\n\n/// Represents a replacement of a `snippet`.\n#[derive(Debug, Clone, Hash, PartialEq, Eq)]\npub struct Replacement {\n    /// Code snippet that gets replaced.\n    pub snippet: Snippet,\n    /// The replacement of the snippet.\n    pub replacement: String,\n}\n\n/// Converts a [`DiagnosticSpan`] to a [`Snippet`].\nfn span_to_snippet(span: &DiagnosticSpan) -> Snippet {\n    Snippet {\n        file_name: span.file_name.clone(),\n        line_range: LineRange {\n            start: LinePosition {\n                line: span.line_start,\n                column: span.column_start,\n            },\n            end: LinePosition {\n                line: span.line_end,\n                column: span.column_end,\n            },\n        },\n        range: (span.byte_start as usize)..(span.byte_end as usize),\n    }\n}\n\n/// Converts a [`DiagnosticSpan`] into a [`Replacement`].\nfn collect_span(span: &DiagnosticSpan) -> Option<Replacement> {\n    let snippet = span_to_snippet(span);\n    let replacement = span.suggested_replacement.clone()?;\n    Some(Replacement {\n        snippet,\n        replacement,\n    })\n}\n\n/// Collects code [`Suggestion`]s from a single compiler diagnostic line.\n///\n/// * `only` --- only diagnostics with code in a set of error codes would be collected.\npub fn collect_suggestions<S: ::std::hash::BuildHasher>(\n    diagnostic: &Diagnostic,\n    only: &HashSet<String, S>,\n    filter: Filter,\n) -> Option<Suggestion> {\n    if !only.is_empty() {\n        if let Some(ref code) = diagnostic.code {\n            if !only.contains(&code.code) {\n                // This is not the code we are looking for\n                return None;\n            }\n        } else {\n            // No code, probably a weird builtin warning/error\n            return None;\n        }\n    }\n\n    let solutions: Vec<_> = diagnostic\n        .children\n        .iter()\n        .filter_map(|child| {\n            let replacements: Vec<_> = child\n                .spans\n                .iter()\n                .filter(|span| {\n                    use crate::Filter::*;\n                    use crate::diagnostics::Applicability::*;\n\n                    match (filter, &span.suggestion_applicability) {\n                        (MachineApplicableOnly, Some(MachineApplicable)) => true,\n                        (MachineApplicableOnly, _) => false,\n                        (Everything, _) => true,\n                    }\n                })\n                .filter_map(collect_span)\n                .collect();\n            if !replacements.is_empty() {\n                Some(Solution {\n                    message: child.message.clone(),\n                    replacements,\n                })\n            } else {\n                None\n            }\n        })\n        .collect();\n\n    if solutions.is_empty() {\n        None\n    } else {\n        Some(Suggestion {\n            message: diagnostic.message.clone(),\n            snippets: diagnostic.spans.iter().map(span_to_snippet).collect(),\n            solutions,\n        })\n    }\n}\n\n/// Represents a code fix. This doesn't write to disks but is only in memory.\n///\n/// The general way to use this is:\n///\n/// 1. Feeds the source of a file to [`CodeFix::new`].\n/// 2. Calls [`CodeFix::apply`] to apply suggestions to the source code.\n/// 3. Calls [`CodeFix::finish`] to get the \"fixed\" code.\n#[derive(Clone)]\npub struct CodeFix {\n    data: replace::Data,\n    /// Whether or not the data has been modified.\n    modified: bool,\n}\n\nimpl CodeFix {\n    /// Creates a `CodeFix` with the source of a file to modify.\n    pub fn new(s: &str) -> CodeFix {\n        CodeFix {\n            data: replace::Data::new(s.as_bytes()),\n            modified: false,\n        }\n    }\n\n    /// Applies a suggestion to the code.\n    pub fn apply(&mut self, suggestion: &Suggestion) -> Result<(), Error> {\n        for solution in &suggestion.solutions {\n            for r in &solution.replacements {\n                self.data\n                    .replace_range(r.snippet.range.clone(), r.replacement.as_bytes())\n                    .inspect_err(|_| self.data.restore())?;\n            }\n        }\n        self.data.commit();\n        self.modified = true;\n        Ok(())\n    }\n\n    /// Applies an individual solution from a [`Suggestion`].\n    pub fn apply_solution(&mut self, solution: &Solution) -> Result<(), Error> {\n        for r in &solution.replacements {\n            self.data\n                .replace_range(r.snippet.range.clone(), r.replacement.as_bytes())\n                .inspect_err(|_| self.data.restore())?;\n        }\n        self.data.commit();\n        self.modified = true;\n        Ok(())\n    }\n\n    /// Gets the result of the \"fixed\" code.\n    pub fn finish(&self) -> Result<String, Error> {\n        Ok(String::from_utf8(self.data.to_vec())?)\n    }\n\n    /// Returns whether or not the data has been modified.\n    pub fn modified(&self) -> bool {\n        self.modified\n    }\n}\n\n/// Applies multiple `suggestions` to the given `code`, handling certain conflicts automatically.\n///\n/// If a replacement in a suggestion exactly matches a replacement of a previously applied solution,\n/// that entire suggestion will be skipped without generating an error.\n/// This is currently done to alleviate issues like rust-lang/rust#51211,\n/// although it may be removed if that's fixed deeper in the compiler.\n///\n/// The intent of this design is that the overall application process\n/// should repeatedly apply non-conflicting suggestions then rëevaluate the result,\n/// looping until either there are no more suggestions to apply or some budget is exhausted.\npub fn apply_suggestions(code: &str, suggestions: &[Suggestion]) -> Result<String, Error> {\n    let mut fix = CodeFix::new(code);\n    for suggestion in suggestions.iter().rev() {\n        fix.apply(suggestion).or_else(|err| match err {\n            Error::AlreadyReplaced {\n                is_identical: true, ..\n            } => Ok(()),\n            _ => Err(err),\n        })?;\n    }\n    fix.finish()\n}\n"
  },
  {
    "path": "crates/rustfix/src/replace.rs",
    "content": "//! A small module giving you a simple container that allows\n//! easy and cheap replacement of parts of its content,\n//! with the ability to commit or rollback pending changes.\n//!\n//! Create a new [`Data`] struct with some initial set of code,\n//! then record changes with [`Data::replace_range`],\n//! which will validate that the changes do not conflict with one another.\n//! At any time, you can \"checkpoint\" the current changes with [`Data::commit`]\n//! or roll them back (perhaps due to a conflict) with [`Data::restore`].\n//! When you're done, use [`Data::to_vec`]\n//! to merge the original data with the changes.\n//!\n//! # Notes\n//!\n//! The [`Data::to_vec`] method includes uncommitted changes, if present.\n//! The reason for including uncommitted changes is that typically, once you're calling those,\n//! you're done with edits and will be dropping the [`Data`] struct in a moment.\n//! In this case, requiring an extra call to `commit` would be unnecessary work.\n//! Of course, there's no harm in calling `commit`---it's just not strictly necessary.\n//!\n//! Put another way, the main point of `commit` is to checkpoint a set of known-good changes\n//! before applying additional sets of as-of-yet unvalidated changes.\n//! If no future changes are expected, you aren't _required_ to pay the cost of `commit`.\n//! If you want to discard uncommitted changes, simply call [`Data::restore`] first.\n\nuse std::ops::Range;\nuse std::rc::Rc;\n\nuse crate::error::Error;\n\n/// Data that should replace a particular range of the original.\n#[derive(Clone)]\nstruct Span {\n    /// Span of the parent data to be replaced, inclusive of the start, exclusive of the end.\n    range: Range<usize>,\n    /// New data to insert at the `start` position of the `original` data.\n    data: Rc<[u8]>,\n    /// Whether this data is committed or provisional.\n    committed: bool,\n}\n\nimpl std::fmt::Debug for Span {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let state = if self.is_insert() {\n            \"inserted\"\n        } else {\n            \"replaced\"\n        };\n\n        let committed = if self.committed {\n            \"committed\"\n        } else {\n            \"uncommitted\"\n        };\n\n        write!(\n            f,\n            \"({}, {}: {state}, {committed})\",\n            self.range.start, self.range.end\n        )\n    }\n}\n\nimpl Span {\n    fn new(range: Range<usize>, data: &[u8]) -> Self {\n        Self {\n            range,\n            data: data.into(),\n            committed: false,\n        }\n    }\n\n    /// Returns `true` if and only if this is a \"pure\" insertion,\n    /// i.e. does not remove any existing data.\n    ///\n    /// The insertion point is the `start` position of the range.\n    fn is_insert(&self) -> bool {\n        self.range.start == self.range.end\n    }\n}\n\nimpl PartialEq for Span {\n    /// Returns `true` if and only if this `Span` and `other` have the same range and data,\n    /// regardless of `committed` status.\n    fn eq(&self, other: &Self) -> bool {\n        self.range == other.range && self.data == other.data\n    }\n}\n\n/// A container that allows easily replacing chunks of its data.\n#[derive(Debug, Clone, Default)]\npub struct Data {\n    /// Original data.\n    original: Vec<u8>,\n    /// [`Span`]s covering the full range of the original data.\n    /// Important: it's expected that the underlying implementation maintains this in order,\n    /// sorted ascending by start position.\n    parts: Vec<Span>,\n}\n\nimpl Data {\n    /// Create a new data container from a slice of bytes\n    pub fn new(data: &[u8]) -> Self {\n        Data {\n            original: data.into(),\n            parts: vec![],\n        }\n    }\n\n    /// Commit the current changes.\n    pub fn commit(&mut self) {\n        self.parts.iter_mut().for_each(|span| span.committed = true);\n    }\n\n    /// Discard uncommitted changes.\n    pub fn restore(&mut self) {\n        self.parts.retain(|parts| parts.committed);\n    }\n\n    /// Merge the original data with changes, **including** uncommitted changes.\n    ///\n    /// See the module-level documentation for more information on why uncommitted changes are included.\n    pub fn to_vec(&self) -> Vec<u8> {\n        let mut prev_end = 0;\n        let mut s = self.parts.iter().fold(Vec::new(), |mut acc, span| {\n            // Hedge against potential implementation errors.\n            debug_assert!(\n                prev_end <= span.range.start,\n                \"expected parts in sorted order\"\n            );\n\n            acc.extend_from_slice(&self.original[prev_end..span.range.start]);\n            acc.extend_from_slice(&span.data);\n            prev_end = span.range.end;\n            acc\n        });\n\n        // Append remaining data, if any.\n        s.extend_from_slice(&self.original[prev_end..]);\n        s\n    }\n\n    /// Record a provisional change.\n    ///\n    /// If committed, the original data in the given `range` will be replaced by the given data.\n    /// If there already exist changes for data in the given range (committed or not),\n    /// this method will return an error.\n    /// It will also return an error if the beginning of the range comes before its end,\n    /// or if the range is outside that of the original data.\n    pub fn replace_range(&mut self, range: Range<usize>, data: &[u8]) -> Result<(), Error> {\n        if range.start > range.end {\n            return Err(Error::InvalidRange(range));\n        }\n\n        if range.end > self.original.len() {\n            return Err(Error::DataLengthExceeded(range, self.original.len()));\n        }\n\n        // Keep sorted by start position, or by end position if the start position is the same,\n        // which has the effect of keeping a pure insertion ahead of a replacement.\n        // That limits the kinds of conflicts that can happen, simplifying the checks below.\n        let ins_point = self.parts.partition_point(|span| {\n            span.range.start < range.start\n                || (span.range.start == range.start && span.range.end < range.end)\n        });\n\n        let incoming = Span::new(range, data.as_ref());\n\n        // Reject if the change starts before the previous one ends.\n        if let Some(before) = ins_point.checked_sub(1).and_then(|i| self.parts.get(i)) {\n            if incoming.range.start < before.range.end {\n                return Err(Error::AlreadyReplaced {\n                    is_identical: incoming == *before,\n                    range: incoming.range,\n                });\n            }\n        }\n\n        // Reject if the change ends after the next one starts,\n        // or if this is an insert and there's already an insert there.\n        if let Some(after) = self.parts.get(ins_point) {\n            if incoming.range.end > after.range.start || incoming.range == after.range {\n                return Err(Error::AlreadyReplaced {\n                    is_identical: incoming == *after,\n                    range: incoming.range,\n                });\n            }\n        }\n\n        self.parts.insert(ins_point, incoming);\n        Ok(())\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use proptest::prelude::*;\n\n    fn str(i: &[u8]) -> &str {\n        ::std::str::from_utf8(i).unwrap()\n    }\n\n    #[test]\n    fn insert_at_beginning() {\n        let mut d = Data::new(b\"foo bar baz\");\n        d.replace_range(0..0, b\"oh no \").unwrap();\n        assert_eq!(\"oh no foo bar baz\", str(&d.to_vec()));\n    }\n\n    #[test]\n    fn insert_at_end() {\n        let mut d = Data::new(b\"foo bar baz\");\n        d.replace_range(11..11, b\" oh no\").unwrap();\n        assert_eq!(\"foo bar baz oh no\", str(&d.to_vec()));\n    }\n\n    #[test]\n    fn replace_some_stuff() {\n        let mut d = Data::new(b\"foo bar baz\");\n        d.replace_range(4..7, b\"lol\").unwrap();\n        assert_eq!(\"foo lol baz\", str(&d.to_vec()));\n    }\n\n    #[test]\n    fn replace_a_single_char() {\n        let mut d = Data::new(b\"let y = true;\");\n        d.replace_range(4..5, b\"mut y\").unwrap();\n        assert_eq!(\"let mut y = true;\", str(&d.to_vec()));\n    }\n\n    #[test]\n    fn replace_multiple_lines() {\n        let mut d = Data::new(b\"lorem\\nipsum\\ndolor\");\n\n        d.replace_range(6..11, b\"lol\").unwrap();\n        assert_eq!(\"lorem\\nlol\\ndolor\", str(&d.to_vec()));\n\n        d.replace_range(12..17, b\"lol\").unwrap();\n        assert_eq!(\"lorem\\nlol\\nlol\", str(&d.to_vec()));\n    }\n\n    #[test]\n    fn replace_multiple_lines_with_insert_only() {\n        let mut d = Data::new(b\"foo!\");\n\n        d.replace_range(3..3, b\"bar\").unwrap();\n        assert_eq!(\"foobar!\", str(&d.to_vec()));\n\n        d.replace_range(0..3, b\"baz\").unwrap();\n        assert_eq!(\"bazbar!\", str(&d.to_vec()));\n\n        d.replace_range(3..4, b\"?\").unwrap();\n        assert_eq!(\"bazbar?\", str(&d.to_vec()));\n    }\n\n    #[test]\n    #[allow(clippy::reversed_empty_ranges)]\n    fn replace_invalid_range() {\n        let mut d = Data::new(b\"foo!\");\n\n        assert!(d.replace_range(2..1, b\"bar\").is_err());\n        assert!(d.replace_range(0..3, b\"bar\").is_ok());\n    }\n\n    #[test]\n    fn empty_to_vec_roundtrip() {\n        let s = \"\";\n        assert_eq!(s.as_bytes(), Data::new(s.as_bytes()).to_vec().as_slice());\n    }\n\n    #[test]\n    fn replace_same_range_diff_data() {\n        let mut d = Data::new(b\"foo bar baz\");\n\n        d.replace_range(4..7, b\"lol\").unwrap();\n        assert_eq!(\"foo lol baz\", str(&d.to_vec()));\n\n        assert!(matches!(\n            d.replace_range(4..7, b\"lol2\").unwrap_err(),\n            Error::AlreadyReplaced {\n                is_identical: false,\n                ..\n            },\n        ));\n    }\n\n    #[test]\n    fn replace_same_range_same_data() {\n        let mut d = Data::new(b\"foo bar baz\");\n\n        d.replace_range(4..7, b\"lol\").unwrap();\n        assert_eq!(\"foo lol baz\", str(&d.to_vec()));\n\n        assert!(matches!(\n            d.replace_range(4..7, b\"lol\").unwrap_err(),\n            Error::AlreadyReplaced {\n                is_identical: true,\n                ..\n            },\n        ));\n    }\n\n    #[test]\n    fn broken_replacements() {\n        let mut d = Data::new(b\"foo\");\n        assert!(matches!(\n            d.replace_range(4..8, b\"lol\").unwrap_err(),\n            Error::DataLengthExceeded(std::ops::Range { start: 4, end: 8 }, 3),\n        ));\n    }\n\n    #[test]\n    fn insert_same_twice() {\n        let mut d = Data::new(b\"foo\");\n        d.replace_range(1..1, b\"b\").unwrap();\n        assert_eq!(\"fboo\", str(&d.to_vec()));\n        assert!(matches!(\n            d.replace_range(1..1, b\"b\").unwrap_err(),\n            Error::AlreadyReplaced {\n                is_identical: true,\n                ..\n            },\n        ));\n        assert_eq!(\"fboo\", str(&d.to_vec()));\n    }\n\n    #[test]\n    fn commit_restore() {\n        let mut d = Data::new(b\", \");\n        assert_eq!(\", \", str(&d.to_vec()));\n\n        d.replace_range(2..2, b\"world\").unwrap();\n        d.replace_range(0..0, b\"hello\").unwrap();\n        assert_eq!(\"hello, world\", str(&d.to_vec()));\n\n        d.restore();\n        assert_eq!(\", \", str(&d.to_vec()));\n\n        d.commit();\n        assert_eq!(\", \", str(&d.to_vec()));\n\n        d.replace_range(2..2, b\"world\").unwrap();\n        assert_eq!(\", world\", str(&d.to_vec()));\n        d.commit();\n        assert_eq!(\", world\", str(&d.to_vec()));\n        d.restore();\n        assert_eq!(\", world\", str(&d.to_vec()));\n\n        d.replace_range(0..0, b\"hello\").unwrap();\n        assert_eq!(\"hello, world\", str(&d.to_vec()));\n        d.commit();\n        assert_eq!(\"hello, world\", str(&d.to_vec()));\n        d.restore();\n        assert_eq!(\"hello, world\", str(&d.to_vec()));\n    }\n\n    proptest! {\n        #[test]\n        fn new_to_vec_roundtrip(ref s in \"\\\\PC*\") {\n            assert_eq!(s.as_bytes(), Data::new(s.as_bytes()).to_vec().as_slice());\n        }\n\n        #[test]\n        fn replace_random_chunks(\n            ref data in \"\\\\PC*\",\n            ref replacements in prop::collection::vec(\n                (any::<::std::ops::Range<usize>>(), any::<Vec<u8>>()),\n                1..100,\n            )\n        ) {\n            let mut d = Data::new(data.as_bytes());\n            for &(ref range, ref bytes) in replacements {\n                let _ = d.replace_range(range.clone(), bytes);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "crates/rustfix/tests/edge-cases/empty.json",
    "content": "{\n  \"message\": \"`main` function not found in crate `empty`\",\n  \"code\": {\n    \"code\": \"E0601\",\n    \"explanation\": \"No `main` function was found in a binary crate. To fix this error, add a\\n`main` function. For example:\\n\\n```\\nfn main() {\\n    // Your program will start here.\\n    println!(\\\"Hello world!\\\");\\n}\\n```\\n\\nIf you don't know the basics of Rust, you can go look to the Rust Book to get\\nstarted: https://doc.rust-lang.org/book/\\n\"\n  },\n  \"level\": \"error\",\n  \"spans\": [\n    {\n      \"file_name\": \"empty.rs\",\n      \"byte_start\": 0,\n      \"byte_end\": 0,\n      \"line_start\": 0,\n      \"line_end\": 0,\n      \"column_start\": 1,\n      \"column_end\": 1,\n      \"is_primary\": true,\n      \"text\": [\n        {\n          \"text\": \"\",\n          \"highlight_start\": 1,\n          \"highlight_end\": 1\n        }\n      ],\n      \"label\": null,\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"expansion\": null\n    }\n  ],\n  \"children\": [\n    {\n      \"message\": \"consider adding a `main` function to `empty.rs`\",\n      \"code\": null,\n      \"level\": \"note\",\n      \"spans\": [],\n      \"children\": [],\n      \"rendered\": null\n    }\n  ],\n  \"rendered\": \"error[E0601]: `main` function not found in crate `empty`\\n  |\\n  = note: consider adding a `main` function to `empty.rs`\\n\\n\"\n}\n"
  },
  {
    "path": "crates/rustfix/tests/edge-cases/empty.rs",
    "content": ""
  },
  {
    "path": "crates/rustfix/tests/edge-cases/indented_whitespace.json",
    "content": "{\n    \"message\": \"non-ASCII whitespace symbol '\\\\u{a0}' is not skipped\",\n    \"code\": null,\n    \"level\": \"warning\",\n    \"spans\":\n    [\n        {\n            \"file_name\": \"lib.rs\",\n            \"byte_start\": 26,\n            \"byte_end\": 28,\n            \"line_start\": 2,\n            \"line_end\": 2,\n            \"column_start\": 1,\n            \"column_end\": 2,\n            \"is_primary\": false,\n            \"text\":\n            [\n                {\n                    \"text\": \" indented\\\";\",\n                    \"highlight_start\": 1,\n                    \"highlight_end\": 2\n                }\n            ],\n            \"label\": \"non-ASCII whitespace symbol '\\\\u{a0}' is not skipped\",\n            \"suggested_replacement\": null,\n            \"suggestion_applicability\": null,\n            \"expansion\": null\n        },\n        {\n            \"file_name\": \"lib.rs\",\n            \"byte_start\": 24,\n            \"byte_end\": 28,\n            \"line_start\": 1,\n            \"line_end\": 2,\n            \"column_start\": 25,\n            \"column_end\": 2,\n            \"is_primary\": true,\n            \"text\":\n            [\n                {\n                    \"text\": \"pub static FOO: &str = \\\"\\\\\",\n                    \"highlight_start\": 25,\n                    \"highlight_end\": 26\n                },\n                {\n                    \"text\": \" indented\\\";\",\n                    \"highlight_start\": 1,\n                    \"highlight_end\": 2\n                }\n            ],\n            \"label\": null,\n            \"suggested_replacement\": null,\n            \"suggestion_applicability\": null,\n            \"expansion\": null\n        }\n    ],\n    \"children\":\n    [],\n    \"rendered\": \"warning: non-ASCII whitespace symbol '\\\\u{a0}' is not skipped\\n --> lib.rs:1:25\\n  |\\n1 |   pub static FOO: &str = \\\"\\\\\\n  |  _________________________^\\n2 | |  indented\\\";\\n  | | ^ non-ASCII whitespace symbol '\\\\u{a0}' is not skipped\\n  | |_|\\n  | \\n\\n\"\n}\n"
  },
  {
    "path": "crates/rustfix/tests/edge-cases/no_main.json",
    "content": "{\n  \"message\": \"`main` function not found in crate `no_main`\",\n  \"code\": {\n    \"code\": \"E0601\",\n    \"explanation\": \"No `main` function was found in a binary crate. To fix this error, add a\\n`main` function. For example:\\n\\n```\\nfn main() {\\n    // Your program will start here.\\n    println!(\\\"Hello world!\\\");\\n}\\n```\\n\\nIf you don't know the basics of Rust, you can go look to the Rust Book to get\\nstarted: https://doc.rust-lang.org/book/\\n\"\n  },\n  \"level\": \"error\",\n  \"spans\": [\n    {\n      \"file_name\": \"no_main.rs\",\n      \"byte_start\": 26,\n      \"byte_end\": 26,\n      \"line_start\": 1,\n      \"line_end\": 1,\n      \"column_start\": 27,\n      \"column_end\": 27,\n      \"is_primary\": true,\n      \"text\": [\n        {\n          \"text\": \"// This file has no main.\",\n          \"highlight_start\": 27,\n          \"highlight_end\": 27\n        }\n      ],\n      \"label\": \"consider adding a `main` function to `no_main.rs`\",\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"expansion\": null\n    }\n  ],\n  \"children\": [],\n  \"rendered\": \"error[E0601]: `main` function not found in crate `no_main`\\n --> no_main.rs:1:27\\n  |\\n1 | // This file has no main.\\n  |                           ^ consider adding a `main` function to `no_main.rs`\\n\\n\"\n}\n"
  },
  {
    "path": "crates/rustfix/tests/edge-cases/no_main.rs",
    "content": "// This file has no main.\n"
  },
  {
    "path": "crates/rustfix/tests/edge-cases/out_of_bounds.recorded.json",
    "content": "{\n  \"message\": \"unterminated double quote string\",\n  \"code\": null,\n  \"level\": \"error\",\n  \"spans\": [\n    {\n      \"file_name\": \"./tests/everything/tab_2.rs\",\n      \"byte_start\": 485,\n      \"byte_end\": 526,\n      \"line_start\": 12,\n      \"line_end\": 13,\n      \"column_start\": 7,\n      \"column_end\": 3,\n      \"is_primary\": true,\n      \"text\": [\n        {\n          \"text\": \"    \\\"\\\"\\\"; //~ ERROR unterminated double quote\",\n          \"highlight_start\": 7,\n          \"highlight_end\": 45\n        },\n        {\n          \"text\": \"}\",\n          \"highlight_start\": 1,\n          \"highlight_end\": 3\n        }\n      ],\n      \"label\": null,\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"expansion\": null\n    }\n  ],\n  \"children\": [],\n  \"rendered\": \"error: unterminated double quote string\\n  --> ./tests/everything/tab_2.rs:12:7\\n   |\\n12 |       \\\"\\\"\\\"; //~ ERROR unterminated double quote\\n   |  _______^\\n13 | | }\\n   | |__^\\n\\n\"\n}\n{\n  \"message\": \"aborting due to previous error\",\n  \"code\": null,\n  \"level\": \"error\",\n  \"spans\": [],\n  \"children\": [],\n  \"rendered\": \"error: aborting due to previous error\\n\\n\"\n}\n"
  },
  {
    "path": "crates/rustfix/tests/edge-cases/utf8_idents.recorded.json",
    "content": "{\n  \"message\": \"expected one of `,`, `:`, `=`, or `>`, found `'β`\",\n  \"code\": null,\n  \"level\": \"error\",\n  \"spans\": [\n    {\n      \"file_name\": \"./tests/everything/utf8_idents.rs\",\n      \"byte_start\": 14,\n      \"byte_end\": 14,\n      \"line_start\": 2,\n      \"line_end\": 2,\n      \"column_start\": 6,\n      \"column_end\": 6,\n      \"is_primary\": false,\n      \"text\": [\n        {\n          \"text\": \"    γ  //~ ERROR non-ascii idents are not fully supported\",\n          \"highlight_start\": 6,\n          \"highlight_end\": 6\n        }\n      ],\n      \"label\": \"expected one of `,`, `:`, `=`, or `>` here\",\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"expansion\": null\n    },\n    {\n      \"file_name\": \"./tests/everything/utf8_idents.rs\",\n      \"byte_start\": 145,\n      \"byte_end\": 148,\n      \"line_start\": 4,\n      \"line_end\": 4,\n      \"column_start\": 5,\n      \"column_end\": 7,\n      \"is_primary\": true,\n      \"text\": [\n        {\n          \"text\": \"    'β, //~ ERROR non-ascii idents are not fully supported\",\n          \"highlight_start\": 5,\n          \"highlight_end\": 7\n        }\n      ],\n      \"label\": \"unexpected token\",\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"expansion\": null\n    }\n  ],\n  \"children\": [],\n  \"rendered\": \"error: expected one of `,`, `:`, `=`, or `>`, found `'β`\\n --> ./tests/everything/utf8_idents.rs:4:5\\n  |\\n2 |     γ  //~ ERROR non-ascii idents are not fully supported\\n  |      - expected one of `,`, `:`, `=`, or `>` here\\n3 |        //~^ WARN type parameter `γ` should have an upper camel case name\\n4 |     'β, //~ ERROR non-ascii idents are not fully supported\\n  |     ^^ unexpected token\\n\\n\"\n}\n{\n  \"message\": \"aborting due to previous error\",\n  \"code\": null,\n  \"level\": \"error\",\n  \"spans\": [],\n  \"children\": [],\n  \"rendered\": \"error: aborting due to previous error\\n\\n\"\n}\n"
  },
  {
    "path": "crates/rustfix/tests/edge_cases.rs",
    "content": "use std::collections::HashSet;\nuse std::fs;\n\nmacro_rules! expect_empty_json_test {\n    ($name:ident, $file:expr) => {\n        #[test]\n        fn $name() {\n            let json = fs::read_to_string(concat!(\"./tests/edge-cases/\", $file)).unwrap();\n            let expected_suggestions = rustfix::get_suggestions_from_json(\n                &json,\n                &HashSet::new(),\n                rustfix::Filter::Everything,\n            )\n            .unwrap();\n            assert!(expected_suggestions.is_empty());\n        }\n    };\n}\n\nexpect_empty_json_test! {out_of_bounds_test, \"out_of_bounds.recorded.json\"}\nexpect_empty_json_test! {utf8_identifiers_test, \"utf8_idents.recorded.json\"}\nexpect_empty_json_test! {empty, \"empty.json\"}\nexpect_empty_json_test! {no_main, \"no_main.json\"}\nexpect_empty_json_test! {indented_whitespace, \"indented_whitespace.json\"}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/.gitignore",
    "content": "*.recorded.json\n*.recorded.rs\n"
  },
  {
    "path": "crates/rustfix/tests/everything/E0178.fixed.rs",
    "content": "#![allow(dead_code)]\n\ntrait Foo {}\n\nstruct Bar<'a> {\n    w: &'a (dyn Foo + Send),\n}\n\nfn main() {\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/E0178.json",
    "content": "{\n  \"message\": \"expected a path on the left-hand side of `+`, not `&'a Foo`\",\n  \"code\": {\n    \"code\": \"E0178\",\n    \"explanation\": \"\\nIn types, the `+` type operator has low precedence, so it is often necessary\\nto use parentheses.\\n\\nFor example:\\n\\n```compile_fail,E0178\\ntrait Foo {}\\n\\nstruct Bar<'a> {\\n    w: &'a Foo + Copy,   // error, use &'a (Foo + Copy)\\n    x: &'a Foo + 'a,     // error, use &'a (Foo + 'a)\\n    y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)\\n    z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)\\n}\\n```\\n\\nMore details can be found in [RFC 438].\\n\\n[RFC 438]: https://github.com/rust-lang/rfcs/pull/438\\n\"\n  },\n  \"level\": \"error\",\n  \"spans\": [\n    {\n      \"file_name\": \"./tests/everything/E0178.rs\",\n      \"byte_start\": 60,\n      \"byte_end\": 74,\n      \"line_start\": 6,\n      \"line_end\": 6,\n      \"column_start\": 8,\n      \"column_end\": 22,\n      \"is_primary\": true,\n      \"text\": [\n        {\n          \"text\": \"    w: &'a Foo + Send,\",\n          \"highlight_start\": 8,\n          \"highlight_end\": 22\n        }\n      ],\n      \"label\": null,\n      \"suggested_replacement\": null,\n      \"expansion\": null\n    }\n  ],\n  \"children\": [\n    {\n      \"message\": \"try adding parentheses\",\n      \"code\": null,\n      \"level\": \"help\",\n      \"spans\": [\n        {\n          \"file_name\": \"./tests/everything/E0178.rs\",\n          \"byte_start\": 60,\n          \"byte_end\": 74,\n          \"line_start\": 6,\n          \"line_end\": 6,\n          \"column_start\": 8,\n          \"column_end\": 22,\n          \"is_primary\": true,\n          \"text\": [\n            {\n              \"text\": \"    w: &'a Foo + Send,\",\n              \"highlight_start\": 8,\n              \"highlight_end\": 22\n            }\n          ],\n          \"label\": null,\n          \"suggested_replacement\": \"&'a (Foo + Send)\",\n          \"expansion\": null\n        }\n      ],\n      \"children\": [],\n      \"rendered\": null\n    }\n  ],\n  \"rendered\": \"error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo`\\n --> ./tests/everything/E0178.rs:6:8\\n  |\\n6 |     w: &'a Foo + Send,\\n  |        ^^^^^^^^^^^^^^ help: try adding parentheses: `&'a (Foo + Send)`\\n\\nIf you want more information on this error, try using \\\"rustc --explain E0178\\\"\\n\"\n}\n{\n  \"message\": \"aborting due to previous error\",\n  \"code\": null,\n  \"level\": \"error\",\n  \"spans\": [],\n  \"children\": [],\n  \"rendered\": \"error: aborting due to previous error\\n\\n\"\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/E0178.rs",
    "content": "#![allow(dead_code)]\n\ntrait Foo {}\n\nstruct Bar<'a> {\n    w: &'a dyn Foo + Send,\n}\n\nfn main() {\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/closure-immutable-outer-variable.fixed.rs",
    "content": "// Point at the captured immutable outer variable\n\n// Suppress unrelated warnings\n#![allow(unused)]\n\nfn foo(mut f: Box<dyn FnMut()>) {\n    f();\n}\n\nfn main() {\n    let mut y = true;\n    foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/closure-immutable-outer-variable.json",
    "content": "{\n  \"$message_type\": \"diagnostic\",\n  \"children\": [\n    {\n      \"children\": [],\n      \"code\": null,\n      \"level\": \"help\",\n      \"message\": \"consider changing this to be mutable\",\n      \"rendered\": null,\n      \"spans\": [\n        {\n          \"byte_end\": 167,\n          \"byte_start\": 167,\n          \"column_end\": 9,\n          \"column_start\": 9,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/closure-immutable-outer-variable.rs\",\n          \"is_primary\": true,\n          \"label\": null,\n          \"line_end\": 11,\n          \"line_start\": 11,\n          \"suggested_replacement\": \"mut \",\n          \"suggestion_applicability\": \"MachineApplicable\",\n          \"text\": [\n            {\n              \"highlight_end\": 9,\n              \"highlight_start\": 9,\n              \"text\": \"    let y = true;\"\n            }\n          ]\n        }\n      ]\n    }\n  ],\n  \"code\": {\n    \"code\": \"E0594\",\n    \"explanation\": \"A non-mutable value was assigned a value./n/nErroneous code example:/n/n```compile_fail,E0594/nstruct SolarSystem {/n    earth: i32,/n}/n/nlet ss = SolarSystem { earth: 3 };/nss.earth = 2; // error!/n```/n/nTo fix this error, declare `ss` as mutable by using the `mut` keyword:/n/n```/nstruct SolarSystem {/n    earth: i32,/n}/n/nlet mut ss = SolarSystem { earth: 3 }; // declaring `ss` as mutable/nss.earth = 2; // ok!/n```/n\"\n  },\n  \"level\": \"error\",\n  \"message\": \"cannot assign to `y`, as it is not declared as mutable\",\n  \"rendered\": \"error[E0594]: cannot assign to `y`, as it is not declared as mutable/n  --> ./tests/everything/closure-immutable-outer-variable.rs:12:26/n   |/n12 |     foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable/n   |                          ^^^^^^^^^ cannot assign/n   |/nhelp: consider changing this to be mutable/n   |/n11 |     let mut y = true;/n   |         +++/n/n\",\n  \"spans\": [\n    {\n      \"byte_end\": 211,\n      \"byte_start\": 202,\n      \"column_end\": 35,\n      \"column_start\": 26,\n      \"expansion\": null,\n      \"file_name\": \"./tests/everything/closure-immutable-outer-variable.rs\",\n      \"is_primary\": true,\n      \"label\": \"cannot assign\",\n      \"line_end\": 12,\n      \"line_start\": 12,\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"text\": [\n        {\n          \"highlight_end\": 35,\n          \"highlight_start\": 26,\n          \"text\": \"    foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable\"\n        }\n      ]\n    }\n  ]\n}\n{\n  \"$message_type\": \"diagnostic\",\n  \"children\": [],\n  \"code\": null,\n  \"level\": \"error\",\n  \"message\": \"aborting due to 1 previous error\",\n  \"rendered\": \"error: aborting due to 1 previous error/n/n\",\n  \"spans\": []\n}\n{\n  \"$message_type\": \"diagnostic\",\n  \"children\": [],\n  \"code\": null,\n  \"level\": \"failure-note\",\n  \"message\": \"For more information about this error, try `rustc --explain E0594`.\",\n  \"rendered\": \"For more information about this error, try `rustc --explain E0594`./n\",\n  \"spans\": []\n}"
  },
  {
    "path": "crates/rustfix/tests/everything/closure-immutable-outer-variable.rs",
    "content": "// Point at the captured immutable outer variable\n\n// Suppress unrelated warnings\n#![allow(unused)]\n\nfn foo(mut f: Box<dyn FnMut()>) {\n    f();\n}\n\nfn main() {\n    let y = true;\n    foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/dedup-suggestions.fixed.rs",
    "content": "// See <https://github.com/rust-lang/cargo/issues/13027>\nmacro_rules! foo {\n    () => {\n        let x = Box::new(1);\n        let _ = &x;\n    };\n}\n\nfn main() {\n    foo!();\n    foo!();\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/dedup-suggestions.json",
    "content": "{\n  \"$message_type\": \"diagnostic\",\n  \"children\": [\n    {\n      \"children\": [],\n      \"code\": null,\n      \"level\": \"note\",\n      \"message\": \"`#[warn(forgetting_references)]` on by default\",\n      \"rendered\": null,\n      \"spans\": []\n    },\n    {\n      \"children\": [],\n      \"code\": null,\n      \"level\": \"help\",\n      \"message\": \"use `let _ = ...` to ignore the expression or result\",\n      \"rendered\": null,\n      \"spans\": [\n        {\n          \"byte_end\": 142,\n          \"byte_start\": 125,\n          \"column_end\": 26,\n          \"column_start\": 9,\n          \"expansion\": {\n            \"def_site_span\": {\n              \"byte_end\": 73,\n              \"byte_start\": 57,\n              \"column_end\": 17,\n              \"column_start\": 1,\n              \"expansion\": null,\n              \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n              \"is_primary\": false,\n              \"label\": null,\n              \"line_end\": 2,\n              \"line_start\": 2,\n              \"suggested_replacement\": null,\n              \"suggestion_applicability\": null,\n              \"text\": [\n                {\n                  \"highlight_end\": 17,\n                  \"highlight_start\": 1,\n                  \"text\": \"macro_rules! foo {\"\n                }\n              ]\n            },\n            \"macro_decl_name\": \"foo!\",\n            \"span\": {\n              \"byte_end\": 179,\n              \"byte_start\": 173,\n              \"column_end\": 11,\n              \"column_start\": 5,\n              \"expansion\": null,\n              \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n              \"is_primary\": false,\n              \"label\": null,\n              \"line_end\": 10,\n              \"line_start\": 10,\n              \"suggested_replacement\": null,\n              \"suggestion_applicability\": null,\n              \"text\": [\n                {\n                  \"highlight_end\": 11,\n                  \"highlight_start\": 5,\n                  \"text\": \"    foo!();\"\n                }\n              ]\n            }\n          },\n          \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n          \"is_primary\": true,\n          \"label\": null,\n          \"line_end\": 5,\n          \"line_start\": 5,\n          \"suggested_replacement\": \"let _ = \",\n          \"suggestion_applicability\": \"MaybeIncorrect\",\n          \"text\": [\n            {\n              \"highlight_end\": 26,\n              \"highlight_start\": 9,\n              \"text\": \"        std::mem::forget(&x);\"\n            }\n          ]\n        },\n        {\n          \"byte_end\": 145,\n          \"byte_start\": 144,\n          \"column_end\": 29,\n          \"column_start\": 28,\n          \"expansion\": {\n            \"def_site_span\": {\n              \"byte_end\": 73,\n              \"byte_start\": 57,\n              \"column_end\": 17,\n              \"column_start\": 1,\n              \"expansion\": null,\n              \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n              \"is_primary\": false,\n              \"label\": null,\n              \"line_end\": 2,\n              \"line_start\": 2,\n              \"suggested_replacement\": null,\n              \"suggestion_applicability\": null,\n              \"text\": [\n                {\n                  \"highlight_end\": 17,\n                  \"highlight_start\": 1,\n                  \"text\": \"macro_rules! foo {\"\n                }\n              ]\n            },\n            \"macro_decl_name\": \"foo!\",\n            \"span\": {\n              \"byte_end\": 179,\n              \"byte_start\": 173,\n              \"column_end\": 11,\n              \"column_start\": 5,\n              \"expansion\": null,\n              \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n              \"is_primary\": false,\n              \"label\": null,\n              \"line_end\": 10,\n              \"line_start\": 10,\n              \"suggested_replacement\": null,\n              \"suggestion_applicability\": null,\n              \"text\": [\n                {\n                  \"highlight_end\": 11,\n                  \"highlight_start\": 5,\n                  \"text\": \"    foo!();\"\n                }\n              ]\n            }\n          },\n          \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n          \"is_primary\": true,\n          \"label\": null,\n          \"line_end\": 5,\n          \"line_start\": 5,\n          \"suggested_replacement\": \"\",\n          \"suggestion_applicability\": \"MaybeIncorrect\",\n          \"text\": [\n            {\n              \"highlight_end\": 29,\n              \"highlight_start\": 28,\n              \"text\": \"        std::mem::forget(&x);\"\n            }\n          ]\n        }\n      ]\n    }\n  ],\n  \"code\": {\n    \"code\": \"forgetting_references\",\n    \"explanation\": null\n  },\n  \"level\": \"warning\",\n  \"message\": \"calls to `std::mem::forget` with a reference instead of an owned value does nothing\",\n  \"rendered\": \"warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing/n  --> ./tests/everything/dedup-suggestions.rs:5:9/n   |/n5  |         std::mem::forget(&x);/n   |         ^^^^^^^^^^^^^^^^^--^/n   |                          |/n   |                          argument has type `&Box<i32>`/n.../n10 |     foo!();/n   |     ------ in this macro invocation/n   |/n   = note: `#[warn(forgetting_references)]` on by default/n   = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)/nhelp: use `let _ = ...` to ignore the expression or result/n   |/n5  -         std::mem::forget(&x);/n5  +         let _ = &x;/n   |/n/n\",\n  \"spans\": [\n    {\n      \"byte_end\": 144,\n      \"byte_start\": 142,\n      \"column_end\": 28,\n      \"column_start\": 26,\n      \"expansion\": {\n        \"def_site_span\": {\n          \"byte_end\": 73,\n          \"byte_start\": 57,\n          \"column_end\": 17,\n          \"column_start\": 1,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n          \"is_primary\": false,\n          \"label\": null,\n          \"line_end\": 2,\n          \"line_start\": 2,\n          \"suggested_replacement\": null,\n          \"suggestion_applicability\": null,\n          \"text\": [\n            {\n              \"highlight_end\": 17,\n              \"highlight_start\": 1,\n              \"text\": \"macro_rules! foo {\"\n            }\n          ]\n        },\n        \"macro_decl_name\": \"foo!\",\n        \"span\": {\n          \"byte_end\": 179,\n          \"byte_start\": 173,\n          \"column_end\": 11,\n          \"column_start\": 5,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n          \"is_primary\": false,\n          \"label\": null,\n          \"line_end\": 10,\n          \"line_start\": 10,\n          \"suggested_replacement\": null,\n          \"suggestion_applicability\": null,\n          \"text\": [\n            {\n              \"highlight_end\": 11,\n              \"highlight_start\": 5,\n              \"text\": \"    foo!();\"\n            }\n          ]\n        }\n      },\n      \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n      \"is_primary\": false,\n      \"label\": \"argument has type `&Box<i32>`\",\n      \"line_end\": 5,\n      \"line_start\": 5,\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"text\": [\n        {\n          \"highlight_end\": 28,\n          \"highlight_start\": 26,\n          \"text\": \"        std::mem::forget(&x);\"\n        }\n      ]\n    },\n    {\n      \"byte_end\": 145,\n      \"byte_start\": 125,\n      \"column_end\": 29,\n      \"column_start\": 9,\n      \"expansion\": {\n        \"def_site_span\": {\n          \"byte_end\": 73,\n          \"byte_start\": 57,\n          \"column_end\": 17,\n          \"column_start\": 1,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n          \"is_primary\": false,\n          \"label\": null,\n          \"line_end\": 2,\n          \"line_start\": 2,\n          \"suggested_replacement\": null,\n          \"suggestion_applicability\": null,\n          \"text\": [\n            {\n              \"highlight_end\": 17,\n              \"highlight_start\": 1,\n              \"text\": \"macro_rules! foo {\"\n            }\n          ]\n        },\n        \"macro_decl_name\": \"foo!\",\n        \"span\": {\n          \"byte_end\": 179,\n          \"byte_start\": 173,\n          \"column_end\": 11,\n          \"column_start\": 5,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n          \"is_primary\": false,\n          \"label\": null,\n          \"line_end\": 10,\n          \"line_start\": 10,\n          \"suggested_replacement\": null,\n          \"suggestion_applicability\": null,\n          \"text\": [\n            {\n              \"highlight_end\": 11,\n              \"highlight_start\": 5,\n              \"text\": \"    foo!();\"\n            }\n          ]\n        }\n      },\n      \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n      \"is_primary\": true,\n      \"label\": null,\n      \"line_end\": 5,\n      \"line_start\": 5,\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"text\": [\n        {\n          \"highlight_end\": 29,\n          \"highlight_start\": 9,\n          \"text\": \"        std::mem::forget(&x);\"\n        }\n      ]\n    }\n  ]\n}\n{\n  \"$message_type\": \"diagnostic\",\n  \"children\": [\n    {\n      \"children\": [],\n      \"code\": null,\n      \"level\": \"help\",\n      \"message\": \"use `let _ = ...` to ignore the expression or result\",\n      \"rendered\": null,\n      \"spans\": [\n        {\n          \"byte_end\": 142,\n          \"byte_start\": 125,\n          \"column_end\": 26,\n          \"column_start\": 9,\n          \"expansion\": {\n            \"def_site_span\": {\n              \"byte_end\": 73,\n              \"byte_start\": 57,\n              \"column_end\": 17,\n              \"column_start\": 1,\n              \"expansion\": null,\n              \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n              \"is_primary\": false,\n              \"label\": null,\n              \"line_end\": 2,\n              \"line_start\": 2,\n              \"suggested_replacement\": null,\n              \"suggestion_applicability\": null,\n              \"text\": [\n                {\n                  \"highlight_end\": 17,\n                  \"highlight_start\": 1,\n                  \"text\": \"macro_rules! foo {\"\n                }\n              ]\n            },\n            \"macro_decl_name\": \"foo!\",\n            \"span\": {\n              \"byte_end\": 191,\n              \"byte_start\": 185,\n              \"column_end\": 11,\n              \"column_start\": 5,\n              \"expansion\": null,\n              \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n              \"is_primary\": false,\n              \"label\": null,\n              \"line_end\": 11,\n              \"line_start\": 11,\n              \"suggested_replacement\": null,\n              \"suggestion_applicability\": null,\n              \"text\": [\n                {\n                  \"highlight_end\": 11,\n                  \"highlight_start\": 5,\n                  \"text\": \"    foo!();\"\n                }\n              ]\n            }\n          },\n          \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n          \"is_primary\": true,\n          \"label\": null,\n          \"line_end\": 5,\n          \"line_start\": 5,\n          \"suggested_replacement\": \"let _ = \",\n          \"suggestion_applicability\": \"MaybeIncorrect\",\n          \"text\": [\n            {\n              \"highlight_end\": 26,\n              \"highlight_start\": 9,\n              \"text\": \"        std::mem::forget(&x);\"\n            }\n          ]\n        },\n        {\n          \"byte_end\": 145,\n          \"byte_start\": 144,\n          \"column_end\": 29,\n          \"column_start\": 28,\n          \"expansion\": {\n            \"def_site_span\": {\n              \"byte_end\": 73,\n              \"byte_start\": 57,\n              \"column_end\": 17,\n              \"column_start\": 1,\n              \"expansion\": null,\n              \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n              \"is_primary\": false,\n              \"label\": null,\n              \"line_end\": 2,\n              \"line_start\": 2,\n              \"suggested_replacement\": null,\n              \"suggestion_applicability\": null,\n              \"text\": [\n                {\n                  \"highlight_end\": 17,\n                  \"highlight_start\": 1,\n                  \"text\": \"macro_rules! foo {\"\n                }\n              ]\n            },\n            \"macro_decl_name\": \"foo!\",\n            \"span\": {\n              \"byte_end\": 191,\n              \"byte_start\": 185,\n              \"column_end\": 11,\n              \"column_start\": 5,\n              \"expansion\": null,\n              \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n              \"is_primary\": false,\n              \"label\": null,\n              \"line_end\": 11,\n              \"line_start\": 11,\n              \"suggested_replacement\": null,\n              \"suggestion_applicability\": null,\n              \"text\": [\n                {\n                  \"highlight_end\": 11,\n                  \"highlight_start\": 5,\n                  \"text\": \"    foo!();\"\n                }\n              ]\n            }\n          },\n          \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n          \"is_primary\": true,\n          \"label\": null,\n          \"line_end\": 5,\n          \"line_start\": 5,\n          \"suggested_replacement\": \"\",\n          \"suggestion_applicability\": \"MaybeIncorrect\",\n          \"text\": [\n            {\n              \"highlight_end\": 29,\n              \"highlight_start\": 28,\n              \"text\": \"        std::mem::forget(&x);\"\n            }\n          ]\n        }\n      ]\n    }\n  ],\n  \"code\": {\n    \"code\": \"forgetting_references\",\n    \"explanation\": null\n  },\n  \"level\": \"warning\",\n  \"message\": \"calls to `std::mem::forget` with a reference instead of an owned value does nothing\",\n  \"rendered\": \"warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing/n  --> ./tests/everything/dedup-suggestions.rs:5:9/n   |/n5  |         std::mem::forget(&x);/n   |         ^^^^^^^^^^^^^^^^^--^/n   |                          |/n   |                          argument has type `&Box<i32>`/n.../n11 |     foo!();/n   |     ------ in this macro invocation/n   |/n   = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)/nhelp: use `let _ = ...` to ignore the expression or result/n   |/n5  -         std::mem::forget(&x);/n5  +         let _ = &x;/n   |/n/n\",\n  \"spans\": [\n    {\n      \"byte_end\": 144,\n      \"byte_start\": 142,\n      \"column_end\": 28,\n      \"column_start\": 26,\n      \"expansion\": {\n        \"def_site_span\": {\n          \"byte_end\": 73,\n          \"byte_start\": 57,\n          \"column_end\": 17,\n          \"column_start\": 1,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n          \"is_primary\": false,\n          \"label\": null,\n          \"line_end\": 2,\n          \"line_start\": 2,\n          \"suggested_replacement\": null,\n          \"suggestion_applicability\": null,\n          \"text\": [\n            {\n              \"highlight_end\": 17,\n              \"highlight_start\": 1,\n              \"text\": \"macro_rules! foo {\"\n            }\n          ]\n        },\n        \"macro_decl_name\": \"foo!\",\n        \"span\": {\n          \"byte_end\": 191,\n          \"byte_start\": 185,\n          \"column_end\": 11,\n          \"column_start\": 5,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n          \"is_primary\": false,\n          \"label\": null,\n          \"line_end\": 11,\n          \"line_start\": 11,\n          \"suggested_replacement\": null,\n          \"suggestion_applicability\": null,\n          \"text\": [\n            {\n              \"highlight_end\": 11,\n              \"highlight_start\": 5,\n              \"text\": \"    foo!();\"\n            }\n          ]\n        }\n      },\n      \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n      \"is_primary\": false,\n      \"label\": \"argument has type `&Box<i32>`\",\n      \"line_end\": 5,\n      \"line_start\": 5,\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"text\": [\n        {\n          \"highlight_end\": 28,\n          \"highlight_start\": 26,\n          \"text\": \"        std::mem::forget(&x);\"\n        }\n      ]\n    },\n    {\n      \"byte_end\": 145,\n      \"byte_start\": 125,\n      \"column_end\": 29,\n      \"column_start\": 9,\n      \"expansion\": {\n        \"def_site_span\": {\n          \"byte_end\": 73,\n          \"byte_start\": 57,\n          \"column_end\": 17,\n          \"column_start\": 1,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n          \"is_primary\": false,\n          \"label\": null,\n          \"line_end\": 2,\n          \"line_start\": 2,\n          \"suggested_replacement\": null,\n          \"suggestion_applicability\": null,\n          \"text\": [\n            {\n              \"highlight_end\": 17,\n              \"highlight_start\": 1,\n              \"text\": \"macro_rules! foo {\"\n            }\n          ]\n        },\n        \"macro_decl_name\": \"foo!\",\n        \"span\": {\n          \"byte_end\": 191,\n          \"byte_start\": 185,\n          \"column_end\": 11,\n          \"column_start\": 5,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n          \"is_primary\": false,\n          \"label\": null,\n          \"line_end\": 11,\n          \"line_start\": 11,\n          \"suggested_replacement\": null,\n          \"suggestion_applicability\": null,\n          \"text\": [\n            {\n              \"highlight_end\": 11,\n              \"highlight_start\": 5,\n              \"text\": \"    foo!();\"\n            }\n          ]\n        }\n      },\n      \"file_name\": \"./tests/everything/dedup-suggestions.rs\",\n      \"is_primary\": true,\n      \"label\": null,\n      \"line_end\": 5,\n      \"line_start\": 5,\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"text\": [\n        {\n          \"highlight_end\": 29,\n          \"highlight_start\": 9,\n          \"text\": \"        std::mem::forget(&x);\"\n        }\n      ]\n    }\n  ]\n}\n{\n  \"$message_type\": \"diagnostic\",\n  \"children\": [],\n  \"code\": null,\n  \"level\": \"warning\",\n  \"message\": \"2 warnings emitted\",\n  \"rendered\": \"warning: 2 warnings emitted/n/n\",\n  \"spans\": []\n}"
  },
  {
    "path": "crates/rustfix/tests/everything/dedup-suggestions.rs",
    "content": "// See <https://github.com/rust-lang/cargo/issues/13027>\nmacro_rules! foo {\n    () => {\n        let x = Box::new(1);\n        std::mem::forget(&x);\n    };\n}\n\nfn main() {\n    foo!();\n    foo!();\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/handle-insert-only.fixed.rs",
    "content": "fn main() {\n    // insert only fix, adds `,` to first match arm\n    // why doesnt this replace 1 with 1,?\n    match &Some(3) {\n        &None => 1,\n        &Some(x) => x,\n    };\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/handle-insert-only.json",
    "content": "{\n  \"message\": \"expected one of `,`, `.`, `?`, `}`, or an operator, found `=>`\",\n  \"code\": null,\n  \"level\": \"error\",\n  \"spans\": [\n    {\n      \"file_name\": \"./tests/everything/handle-insert-only.rs\",\n      \"byte_start\": 163,\n      \"byte_end\": 165,\n      \"line_start\": 6,\n      \"line_end\": 6,\n      \"column_start\": 18,\n      \"column_end\": 20,\n      \"is_primary\": true,\n      \"text\": [\n        {\n          \"text\": \"        &Some(x) => x,\",\n          \"highlight_start\": 18,\n          \"highlight_end\": 20\n        }\n      ],\n      \"label\": \"expected one of `,`, `.`, `?`, `}`, or an operator here\",\n      \"suggested_replacement\": null,\n      \"expansion\": null\n    }\n  ],\n  \"children\": [\n    {\n      \"message\": \"missing a comma here to end this `match` arm\",\n      \"code\": null,\n      \"level\": \"help\",\n      \"spans\": [\n        {\n          \"file_name\": \"./tests/everything/handle-insert-only.rs\",\n          \"byte_start\": 145,\n          \"byte_end\": 145,\n          \"line_start\": 5,\n          \"line_end\": 5,\n          \"column_start\": 19,\n          \"column_end\": 19,\n          \"is_primary\": true,\n          \"text\": [\n            {\n              \"text\": \"        &None => 1\",\n              \"highlight_start\": 19,\n              \"highlight_end\": 19\n            }\n          ],\n          \"label\": null,\n          \"suggested_replacement\": \",\",\n          \"suggestion_applicability\": \"Unspecified\",\n          \"expansion\": null\n        }\n      ],\n      \"children\": [],\n      \"rendered\": null\n    }\n  ],\n  \"rendered\": \"error: expected one of `,`, `.`, `?`, `}`, or an operator, found `=>`\\n --> ./tests/everything/handle-insert-only.rs:6:18\\n  |\\n5 |         &None => 1\\n  |                   - help: missing a comma here to end this `match` arm\\n6 |         &Some(x) => x,\\n  |                  ^^ expected one of `,`, `.`, `?`, `}`, or an operator here\\n\\n\"\n}\n{\n  \"message\": \"aborting due to previous error\",\n  \"code\": null,\n  \"level\": \"error\",\n  \"spans\": [],\n  \"children\": [],\n  \"rendered\": \"error: aborting due to previous error\\n\\n\"\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/handle-insert-only.rs",
    "content": "fn main() {\n    // insert only fix, adds `,` to first match arm\n    // why doesnt this replace 1 with 1,?\n    match &Some(3) {\n        &None => 1\n        &Some(x) => x,\n    };\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/lt-generic-comp.fixed.rs",
    "content": "fn main() {\n    let x = 5i64;\n\n    if (x as u32) < 4 {\n        println!(\"yay\");\n    }\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/lt-generic-comp.json",
    "content": "{\n  \"message\": \"`<` is interpreted as a start of generic arguments for `u32`, not a comparison\",\n  \"code\": null,\n  \"level\": \"error\",\n  \"spans\": [\n    {\n      \"file_name\": \"./tests/everything/lt-generic-comp.rs\",\n      \"byte_start\": 49,\n      \"byte_end\": 50,\n      \"line_start\": 4,\n      \"line_end\": 4,\n      \"column_start\": 19,\n      \"column_end\": 20,\n      \"is_primary\": false,\n      \"text\": [\n        {\n          \"text\": \"    if x as u32 < 4 {\",\n          \"highlight_start\": 19,\n          \"highlight_end\": 20\n        }\n      ],\n      \"label\": \"interpreted as generic arguments\",\n      \"suggested_replacement\": null,\n      \"expansion\": null\n    },\n    {\n      \"file_name\": \"./tests/everything/lt-generic-comp.rs\",\n      \"byte_start\": 47,\n      \"byte_end\": 48,\n      \"line_start\": 4,\n      \"line_end\": 4,\n      \"column_start\": 17,\n      \"column_end\": 18,\n      \"is_primary\": true,\n      \"text\": [\n        {\n          \"text\": \"    if x as u32 < 4 {\",\n          \"highlight_start\": 17,\n          \"highlight_end\": 18\n        }\n      ],\n      \"label\": \"not interpreted as comparison\",\n      \"suggested_replacement\": null,\n      \"expansion\": null\n    }\n  ],\n  \"children\": [\n    {\n      \"message\": \"try comparing the cast value\",\n      \"code\": null,\n      \"level\": \"help\",\n      \"spans\": [\n        {\n          \"file_name\": \"./tests/everything/lt-generic-comp.rs\",\n          \"byte_start\": 38,\n          \"byte_end\": 46,\n          \"line_start\": 4,\n          \"line_end\": 4,\n          \"column_start\": 8,\n          \"column_end\": 16,\n          \"is_primary\": true,\n          \"text\": [\n            {\n              \"text\": \"    if x as u32 < 4 {\",\n              \"highlight_start\": 8,\n              \"highlight_end\": 16\n            }\n          ],\n          \"label\": null,\n          \"suggested_replacement\": \"(x as u32)\",\n          \"expansion\": null\n        }\n      ],\n      \"children\": [],\n      \"rendered\": null\n    }\n  ],\n  \"rendered\": \"error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison\\n --> ./tests/everything/lt-generic-comp.rs:4:17\\n  |\\n4 |     if x as u32 < 4 {\\n  |        -------- ^ - interpreted as generic arguments\\n  |        |        |\\n  |        |        not interpreted as comparison\\n  |        help: try comparing the cast value: `(x as u32)`\\n\\n\"\n}\n{\n  \"message\": \"aborting due to previous error\",\n  \"code\": null,\n  \"level\": \"error\",\n  \"spans\": [],\n  \"children\": [],\n  \"rendered\": \"error: aborting due to previous error\\n\\n\"\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/lt-generic-comp.rs",
    "content": "fn main() {\n    let x = 5i64;\n\n    if x as u32 < 4 {\n        println!(\"yay\");\n    }\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/multiple-solutions.fixed.rs",
    "content": "use std::collections::HashSet;\n\nfn main() {\n    let _: HashSet<()>;\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/multiple-solutions.json",
    "content": "{\n  \"$message_type\": \"diagnostic\",\n  \"children\": [\n    {\n      \"children\": [],\n      \"code\": null,\n      \"level\": \"note\",\n      \"message\": \"`#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default\",\n      \"rendered\": null,\n      \"spans\": []\n    },\n    {\n      \"children\": [],\n      \"code\": null,\n      \"level\": \"help\",\n      \"message\": \"remove the unused imports\",\n      \"rendered\": null,\n      \"spans\": [\n        {\n          \"byte_end\": 32,\n          \"byte_start\": 23,\n          \"column_end\": 33,\n          \"column_start\": 24,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/multiple-solutions.rs\",\n          \"is_primary\": true,\n          \"label\": null,\n          \"line_end\": 1,\n          \"line_start\": 1,\n          \"suggested_replacement\": \"\",\n          \"suggestion_applicability\": \"MachineApplicable\",\n          \"text\": [\n            {\n              \"highlight_end\": 33,\n              \"highlight_start\": 24,\n              \"text\": \"use std::collections::{HashMap, HashSet, VecDeque};\"\n            }\n          ]\n        },\n        {\n          \"byte_end\": 49,\n          \"byte_start\": 39,\n          \"column_end\": 50,\n          \"column_start\": 40,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/multiple-solutions.rs\",\n          \"is_primary\": true,\n          \"label\": null,\n          \"line_end\": 1,\n          \"line_start\": 1,\n          \"suggested_replacement\": \"\",\n          \"suggestion_applicability\": \"MachineApplicable\",\n          \"text\": [\n            {\n              \"highlight_end\": 50,\n              \"highlight_start\": 40,\n              \"text\": \"use std::collections::{HashMap, HashSet, VecDeque};\"\n            }\n          ]\n        },\n        {\n          \"byte_end\": 23,\n          \"byte_start\": 22,\n          \"column_end\": 24,\n          \"column_start\": 23,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/multiple-solutions.rs\",\n          \"is_primary\": true,\n          \"label\": null,\n          \"line_end\": 1,\n          \"line_start\": 1,\n          \"suggested_replacement\": \"\",\n          \"suggestion_applicability\": \"MachineApplicable\",\n          \"text\": [\n            {\n              \"highlight_end\": 24,\n              \"highlight_start\": 23,\n              \"text\": \"use std::collections::{HashMap, HashSet, VecDeque};\"\n            }\n          ]\n        },\n        {\n          \"byte_end\": 50,\n          \"byte_start\": 49,\n          \"column_end\": 51,\n          \"column_start\": 50,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/multiple-solutions.rs\",\n          \"is_primary\": true,\n          \"label\": null,\n          \"line_end\": 1,\n          \"line_start\": 1,\n          \"suggested_replacement\": \"\",\n          \"suggestion_applicability\": \"MachineApplicable\",\n          \"text\": [\n            {\n              \"highlight_end\": 51,\n              \"highlight_start\": 50,\n              \"text\": \"use std::collections::{HashMap, HashSet, VecDeque};\"\n            }\n          ]\n        }\n      ]\n    }\n  ],\n  \"code\": {\n    \"code\": \"unused_imports\",\n    \"explanation\": null\n  },\n  \"level\": \"warning\",\n  \"message\": \"unused imports: `HashMap` and `VecDeque`\",\n  \"rendered\": \"warning: unused imports: `HashMap` and `VecDeque`/n --> ./tests/everything/multiple-solutions.rs:1:24/n  |/n1 | use std::collections::{HashMap, HashSet, VecDeque};/n  |                        ^^^^^^^           ^^^^^^^^/n  |/n  = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default/n/n\",\n  \"spans\": [\n    {\n      \"byte_end\": 30,\n      \"byte_start\": 23,\n      \"column_end\": 31,\n      \"column_start\": 24,\n      \"expansion\": null,\n      \"file_name\": \"./tests/everything/multiple-solutions.rs\",\n      \"is_primary\": true,\n      \"label\": null,\n      \"line_end\": 1,\n      \"line_start\": 1,\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"text\": [\n        {\n          \"highlight_end\": 31,\n          \"highlight_start\": 24,\n          \"text\": \"use std::collections::{HashMap, HashSet, VecDeque};\"\n        }\n      ]\n    },\n    {\n      \"byte_end\": 49,\n      \"byte_start\": 41,\n      \"column_end\": 50,\n      \"column_start\": 42,\n      \"expansion\": null,\n      \"file_name\": \"./tests/everything/multiple-solutions.rs\",\n      \"is_primary\": true,\n      \"label\": null,\n      \"line_end\": 1,\n      \"line_start\": 1,\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"text\": [\n        {\n          \"highlight_end\": 50,\n          \"highlight_start\": 42,\n          \"text\": \"use std::collections::{HashMap, HashSet, VecDeque};\"\n        }\n      ]\n    }\n  ]\n}\n{\n  \"$message_type\": \"diagnostic\",\n  \"children\": [],\n  \"code\": null,\n  \"level\": \"warning\",\n  \"message\": \"1 warning emitted\",\n  \"rendered\": \"warning: 1 warning emitted/n/n\",\n  \"spans\": []\n}"
  },
  {
    "path": "crates/rustfix/tests/everything/multiple-solutions.rs",
    "content": "use std::collections::{HashMap, HashSet, VecDeque};\n\nfn main() {\n    let _: HashSet<()>;\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/replace-only-one-char.fixed.rs",
    "content": "fn main() {\n    let _x = 42;\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/replace-only-one-char.json",
    "content": "{\n  \"$message_type\": \"diagnostic\",\n  \"children\": [\n    {\n      \"children\": [],\n      \"code\": null,\n      \"level\": \"note\",\n      \"message\": \"`#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default\",\n      \"rendered\": null,\n      \"spans\": []\n    },\n    {\n      \"children\": [],\n      \"code\": null,\n      \"level\": \"help\",\n      \"message\": \"if this is intentional, prefix it with an underscore\",\n      \"rendered\": null,\n      \"spans\": [\n        {\n          \"byte_end\": 21,\n          \"byte_start\": 20,\n          \"column_end\": 10,\n          \"column_start\": 9,\n          \"expansion\": null,\n          \"file_name\": \"./tests/everything/replace-only-one-char.rs\",\n          \"is_primary\": true,\n          \"label\": null,\n          \"line_end\": 2,\n          \"line_start\": 2,\n          \"suggested_replacement\": \"_x\",\n          \"suggestion_applicability\": \"MaybeIncorrect\",\n          \"text\": [\n            {\n              \"highlight_end\": 10,\n              \"highlight_start\": 9,\n              \"text\": \"    let x = 42;\"\n            }\n          ]\n        }\n      ]\n    }\n  ],\n  \"code\": {\n    \"code\": \"unused_variables\",\n    \"explanation\": null\n  },\n  \"level\": \"warning\",\n  \"message\": \"unused variable: `x`\",\n  \"rendered\": \"warning: unused variable: `x`/n --> ./tests/everything/replace-only-one-char.rs:2:9/n  |/n2 |     let x = 42;/n  |         ^ help: if this is intentional, prefix it with an underscore: `_x`/n  |/n  = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default/n/n\",\n  \"spans\": [\n    {\n      \"byte_end\": 21,\n      \"byte_start\": 20,\n      \"column_end\": 10,\n      \"column_start\": 9,\n      \"expansion\": null,\n      \"file_name\": \"./tests/everything/replace-only-one-char.rs\",\n      \"is_primary\": true,\n      \"label\": null,\n      \"line_end\": 2,\n      \"line_start\": 2,\n      \"suggested_replacement\": null,\n      \"suggestion_applicability\": null,\n      \"text\": [\n        {\n          \"highlight_end\": 10,\n          \"highlight_start\": 9,\n          \"text\": \"    let x = 42;\"\n        }\n      ]\n    }\n  ]\n}\n{\n  \"$message_type\": \"diagnostic\",\n  \"children\": [],\n  \"code\": null,\n  \"level\": \"warning\",\n  \"message\": \"1 warning emitted\",\n  \"rendered\": \"warning: 1 warning emitted/n/n\",\n  \"spans\": []\n}"
  },
  {
    "path": "crates/rustfix/tests/everything/replace-only-one-char.rs",
    "content": "fn main() {\n    let x = 42;\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/str-lit-type-mismatch.fixed.rs",
    "content": "fn main() {\n    let x: &[u8] = b\"foo\"; //~ ERROR mismatched types\n    let y: &[u8; 4] = b\"baaa\"; //~ ERROR mismatched types\n    let z: &str = \"foo\"; //~ ERROR mismatched types\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/str-lit-type-mismatch.json",
    "content": "{\n  \"message\": \"mismatched types\",\n  \"code\": {\n    \"code\": \"E0308\",\n    \"explanation\": \"\\nThis error occurs when the compiler was unable to infer the concrete type of a\\nvariable. It can occur for several cases, the most common of which is a\\nmismatch in the expected type that the compiler inferred for a variable's\\ninitializing expression, and the actual type explicitly assigned to the\\nvariable.\\n\\nFor example:\\n\\n```compile_fail,E0308\\nlet x: i32 = \\\"I am not a number!\\\";\\n//     ~~~   ~~~~~~~~~~~~~~~~~~~~\\n//      |             |\\n//      |    initializing expression;\\n//      |    compiler infers type `&str`\\n//      |\\n//    type `i32` assigned to variable `x`\\n```\\n\"\n  },\n  \"level\": \"error\",\n  \"spans\": [\n    {\n      \"file_name\": \"./tests/everything/str-lit-type-mismatch.rs\",\n      \"byte_start\": 499,\n      \"byte_end\": 504,\n      \"line_start\": 13,\n      \"line_end\": 13,\n      \"column_start\": 20,\n      \"column_end\": 25,\n      \"is_primary\": true,\n      \"text\": [\n        {\n          \"text\": \"    let x: &[u8] = \\\"foo\\\"; //~ ERROR mismatched types\",\n          \"highlight_start\": 20,\n          \"highlight_end\": 25\n        }\n      ],\n      \"label\": \"expected slice, found str\",\n      \"suggested_replacement\": null,\n      \"expansion\": null\n    }\n  ],\n  \"children\": [\n    {\n      \"message\": \"expected type `&[u8]`\\n   found type `&'static str`\",\n      \"code\": null,\n      \"level\": \"note\",\n      \"spans\": [],\n      \"children\": [],\n      \"rendered\": null\n    },\n    {\n      \"message\": \"consider adding a leading `b`\",\n      \"code\": null,\n      \"level\": \"help\",\n      \"spans\": [\n        {\n          \"file_name\": \"./tests/everything/str-lit-type-mismatch.rs\",\n          \"byte_start\": 499,\n          \"byte_end\": 504,\n          \"line_start\": 13,\n          \"line_end\": 13,\n          \"column_start\": 20,\n          \"column_end\": 25,\n          \"is_primary\": true,\n          \"text\": [\n            {\n              \"text\": \"    let x: &[u8] = \\\"foo\\\"; //~ ERROR mismatched types\",\n              \"highlight_start\": 20,\n              \"highlight_end\": 25\n            }\n          ],\n          \"label\": null,\n          \"suggested_replacement\": \"b\\\"foo\\\"\",\n          \"expansion\": null\n        }\n      ],\n      \"children\": [],\n      \"rendered\": null\n    }\n  ],\n  \"rendered\": \"error[E0308]: mismatched types\\n  --> ./tests/everything/str-lit-type-mismatch.rs:13:20\\n   |\\n13 |     let x: &[u8] = \\\"foo\\\"; //~ ERROR mismatched types\\n   |                    ^^^^^\\n   |                    |\\n   |                    expected slice, found str\\n   |                    help: consider adding a leading `b`: `b\\\"foo\\\"`\\n   |\\n   = note: expected type `&[u8]`\\n              found type `&'static str`\\n\\nIf you want more information on this error, try using \\\"rustc --explain E0308\\\"\\n\"\n}\n{\n  \"message\": \"mismatched types\",\n  \"code\": {\n    \"code\": \"E0308\",\n    \"explanation\": \"\\nThis error occurs when the compiler was unable to infer the concrete type of a\\nvariable. It can occur for several cases, the most common of which is a\\nmismatch in the expected type that the compiler inferred for a variable's\\ninitializing expression, and the actual type explicitly assigned to the\\nvariable.\\n\\nFor example:\\n\\n```compile_fail,E0308\\nlet x: i32 = \\\"I am not a number!\\\";\\n//     ~~~   ~~~~~~~~~~~~~~~~~~~~\\n//      |             |\\n//      |    initializing expression;\\n//      |    compiler infers type `&str`\\n//      |\\n//    type `i32` assigned to variable `x`\\n```\\n\"\n  },\n  \"level\": \"error\",\n  \"spans\": [\n    {\n      \"file_name\": \"./tests/everything/str-lit-type-mismatch.rs\",\n      \"byte_start\": 555,\n      \"byte_end\": 561,\n      \"line_start\": 14,\n      \"line_end\": 14,\n      \"column_start\": 23,\n      \"column_end\": 29,\n      \"is_primary\": true,\n      \"text\": [\n        {\n          \"text\": \"    let y: &[u8; 4] = \\\"baaa\\\"; //~ ERROR mismatched types\",\n          \"highlight_start\": 23,\n          \"highlight_end\": 29\n        }\n      ],\n      \"label\": \"expected array of 4 elements, found str\",\n      \"suggested_replacement\": null,\n      \"expansion\": null\n    }\n  ],\n  \"children\": [\n    {\n      \"message\": \"expected type `&[u8; 4]`\\n   found type `&'static str`\",\n      \"code\": null,\n      \"level\": \"note\",\n      \"spans\": [],\n      \"children\": [],\n      \"rendered\": null\n    },\n    {\n      \"message\": \"consider adding a leading `b`\",\n      \"code\": null,\n      \"level\": \"help\",\n      \"spans\": [\n        {\n          \"file_name\": \"./tests/everything/str-lit-type-mismatch.rs\",\n          \"byte_start\": 555,\n          \"byte_end\": 561,\n          \"line_start\": 14,\n          \"line_end\": 14,\n          \"column_start\": 23,\n          \"column_end\": 29,\n          \"is_primary\": true,\n          \"text\": [\n            {\n              \"text\": \"    let y: &[u8; 4] = \\\"baaa\\\"; //~ ERROR mismatched types\",\n              \"highlight_start\": 23,\n              \"highlight_end\": 29\n            }\n          ],\n          \"label\": null,\n          \"suggested_replacement\": \"b\\\"baaa\\\"\",\n          \"expansion\": null\n        }\n      ],\n      \"children\": [],\n      \"rendered\": null\n    }\n  ],\n  \"rendered\": \"error[E0308]: mismatched types\\n  --> ./tests/everything/str-lit-type-mismatch.rs:14:23\\n   |\\n14 |     let y: &[u8; 4] = \\\"baaa\\\"; //~ ERROR mismatched types\\n   |                       ^^^^^^\\n   |                       |\\n   |                       expected array of 4 elements, found str\\n   |                       help: consider adding a leading `b`: `b\\\"baaa\\\"`\\n   |\\n   = note: expected type `&[u8; 4]`\\n              found type `&'static str`\\n\\nIf you want more information on this error, try using \\\"rustc --explain E0308\\\"\\n\"\n}\n{\n  \"message\": \"mismatched types\",\n  \"code\": {\n    \"code\": \"E0308\",\n    \"explanation\": \"\\nThis error occurs when the compiler was unable to infer the concrete type of a\\nvariable. It can occur for several cases, the most common of which is a\\nmismatch in the expected type that the compiler inferred for a variable's\\ninitializing expression, and the actual type explicitly assigned to the\\nvariable.\\n\\nFor example:\\n\\n```compile_fail,E0308\\nlet x: i32 = \\\"I am not a number!\\\";\\n//     ~~~   ~~~~~~~~~~~~~~~~~~~~\\n//      |             |\\n//      |    initializing expression;\\n//      |    compiler infers type `&str`\\n//      |\\n//    type `i32` assigned to variable `x`\\n```\\n\"\n  },\n  \"level\": \"error\",\n  \"spans\": [\n    {\n      \"file_name\": \"./tests/everything/str-lit-type-mismatch.rs\",\n      \"byte_start\": 608,\n      \"byte_end\": 614,\n      \"line_start\": 15,\n      \"line_end\": 15,\n      \"column_start\": 19,\n      \"column_end\": 25,\n      \"is_primary\": true,\n      \"text\": [\n        {\n          \"text\": \"    let z: &str = b\\\"foo\\\"; //~ ERROR mismatched types\",\n          \"highlight_start\": 19,\n          \"highlight_end\": 25\n        }\n      ],\n      \"label\": \"expected str, found array of 3 elements\",\n      \"suggested_replacement\": null,\n      \"expansion\": null\n    }\n  ],\n  \"children\": [\n    {\n      \"message\": \"expected type `&str`\\n   found type `&'static [u8; 3]`\",\n      \"code\": null,\n      \"level\": \"note\",\n      \"spans\": [],\n      \"children\": [],\n      \"rendered\": null\n    },\n    {\n      \"message\": \"consider removing the leading `b`\",\n      \"code\": null,\n      \"level\": \"help\",\n      \"spans\": [\n        {\n          \"file_name\": \"./tests/everything/str-lit-type-mismatch.rs\",\n          \"byte_start\": 608,\n          \"byte_end\": 614,\n          \"line_start\": 15,\n          \"line_end\": 15,\n          \"column_start\": 19,\n          \"column_end\": 25,\n          \"is_primary\": true,\n          \"text\": [\n            {\n              \"text\": \"    let z: &str = b\\\"foo\\\"; //~ ERROR mismatched types\",\n              \"highlight_start\": 19,\n              \"highlight_end\": 25\n            }\n          ],\n          \"label\": null,\n          \"suggested_replacement\": \"\\\"foo\\\"\",\n          \"expansion\": null\n        }\n      ],\n      \"children\": [],\n      \"rendered\": null\n    }\n  ],\n  \"rendered\": \"error[E0308]: mismatched types\\n  --> ./tests/everything/str-lit-type-mismatch.rs:15:19\\n   |\\n15 |     let z: &str = b\\\"foo\\\"; //~ ERROR mismatched types\\n   |                   ^^^^^^\\n   |                   |\\n   |                   expected str, found array of 3 elements\\n   |                   help: consider removing the leading `b`: `\\\"foo\\\"`\\n   |\\n   = note: expected type `&str`\\n              found type `&'static [u8; 3]`\\n\\nIf you want more information on this error, try using \\\"rustc --explain E0308\\\"\\n\"\n}\n{\n  \"message\": \"aborting due to 3 previous errors\",\n  \"code\": null,\n  \"level\": \"error\",\n  \"spans\": [],\n  \"children\": [],\n  \"rendered\": \"error: aborting due to 3 previous errors\\n\\n\"\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/str-lit-type-mismatch.rs",
    "content": "fn main() {\n    let x: &[u8] = \"foo\"; //~ ERROR mismatched types\n    let y: &[u8; 4] = \"baaa\"; //~ ERROR mismatched types\n    let z: &str = b\"foo\"; //~ ERROR mismatched types\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/use-insert.fixed.rs",
    "content": "use a::f;\n\nmod a {\n    pub fn f() {}\n}\n\nfn main() {\n    f();\n}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/use-insert.json",
    "content": "{\"$message_type\":\"diagnostic\",\"message\":\"cannot find function `f` in this scope\",\"code\":{\"code\":\"E0425\",\"explanation\":\"An unresolved name was used.\\n\\nErroneous code examples:\\n\\n```compile_fail,E0425\\nsomething_that_doesnt_exist::foo;\\n// error: unresolved name `something_that_doesnt_exist::foo`\\n\\n// or:\\n\\ntrait Foo {\\n    fn bar() {\\n        Self; // error: unresolved name `Self`\\n    }\\n}\\n\\n// or:\\n\\nlet x = unknown_variable;  // error: unresolved name `unknown_variable`\\n```\\n\\nPlease verify that the name wasn't misspelled and ensure that the\\nidentifier being referred to is valid for the given situation. Example:\\n\\n```\\nenum something_that_does_exist {\\n    Foo,\\n}\\n```\\n\\nOr:\\n\\n```\\nmod something_that_does_exist {\\n    pub static foo : i32 = 0i32;\\n}\\n\\nsomething_that_does_exist::foo; // ok!\\n```\\n\\nOr:\\n\\n```\\nlet unknown_variable = 12u32;\\nlet x = unknown_variable; // ok!\\n```\\n\\nIf the item is not defined in the current module, it must be imported using a\\n`use` statement, like so:\\n\\n```\\n# mod foo { pub fn bar() {} }\\n# fn main() {\\nuse foo::bar;\\nbar();\\n# }\\n```\\n\\nIf the item you are importing is not defined in some super-module of the\\ncurrent module, then it must also be declared as public (e.g., `pub fn`).\\n\"},\"level\":\"error\",\"spans\":[{\"file_name\":\"./tests/everything/use-insert.rs\",\"byte_start\":45,\"byte_end\":46,\"line_start\":6,\"line_end\":6,\"column_start\":5,\"column_end\":6,\"is_primary\":true,\"text\":[{\"text\":\"    f();\",\"highlight_start\":5,\"highlight_end\":6}],\"label\":\"not found in this scope\",\"suggested_replacement\":null,\"suggestion_applicability\":null,\"expansion\":null}],\"children\":[{\"message\":\"consider importing this function\",\"code\":null,\"level\":\"help\",\"spans\":[{\"file_name\":\"./tests/everything/use-insert.rs\",\"byte_start\":0,\"byte_end\":0,\"line_start\":1,\"line_end\":1,\"column_start\":1,\"column_end\":1,\"is_primary\":true,\"text\":[],\"label\":null,\"suggested_replacement\":\"use a::f;\\n\\n\",\"suggestion_applicability\":\"MaybeIncorrect\",\"expansion\":null}],\"children\":[],\"rendered\":null}],\"rendered\":\"error[E0425]: cannot find function `f` in this scope\\n --> ./tests/everything/use-insert.rs:6:5\\n  |\\n6 |     f();\\n  |     ^ not found in this scope\\n  |\\nhelp: consider importing this function\\n  |\\n1 + use a::f;\\n  |\\n\\n\"}\n{\"$message_type\":\"diagnostic\",\"message\":\"aborting due to 1 previous error\",\"code\":null,\"level\":\"error\",\"spans\":[],\"children\":[],\"rendered\":\"error: aborting due to 1 previous error\\n\\n\"}\n{\"$message_type\":\"diagnostic\",\"message\":\"For more information about this error, try `rustc --explain E0425`.\",\"code\":null,\"level\":\"failure-note\",\"spans\":[],\"children\":[],\"rendered\":\"For more information about this error, try `rustc --explain E0425`.\\n\"}\n"
  },
  {
    "path": "crates/rustfix/tests/everything/use-insert.rs",
    "content": "mod a {\n    pub fn f() {}\n}\n\nfn main() {\n    f();\n}\n"
  },
  {
    "path": "crates/rustfix/tests/parse_and_replace.rs",
    "content": "//! Tests that verify rustfix applies the appropriate changes to a file.\n//!\n//! This test works by reading a series of `*.rs` files in the\n//! `tests/everything` directory. For each `.rs` file, it runs `rustc` to\n//! collect JSON diagnostics from the file. It feeds that JSON data into\n//! rustfix and applies the recommended suggestions to the `.rs` file. It then\n//! compares the result with the corresponding `.fixed.rs` file. If they don't\n//! match, then the test fails.\n//!\n//! The files ending in `.nightly.rs` will run only on the nightly toolchain\n//!\n//! To override snapshots, run `SNAPSHOTS=overwrite cargo test`.\n//! See [`snapbox::assert::Action`] for different actions.\n\n#![allow(clippy::disallowed_methods, clippy::print_stdout, clippy::print_stderr)]\n\nuse anyhow::{Context, Error, anyhow};\nuse rustfix::apply_suggestions;\nuse serde_json::Value;\nuse snapbox::data::DataFormat;\nuse snapbox::{Assert, Data};\nuse std::collections::HashSet;\nuse std::env;\nuse std::ffi::OsString;\nuse std::fs;\nuse std::path::Path;\nuse std::process::{Command, Output};\nuse tempfile::tempdir;\n\nmod fixmode {\n    pub const EVERYTHING: &str = \"yolo\";\n}\n\nstatic mut VERSION: (u32, bool) = (0, false);\n\n// Temporarily copy from `cargo_test_macro::version`.\nfn version() -> (u32, bool) {\n    static INIT: std::sync::Once = std::sync::Once::new();\n    INIT.call_once(|| {\n        let output = Command::new(\"rustc\")\n            .arg(\"-V\")\n            .output()\n            .expect(\"cargo should run\");\n        let stdout = std::str::from_utf8(&output.stdout).expect(\"utf8\");\n        let vers = stdout.split_whitespace().skip(1).next().unwrap();\n        let is_nightly = option_env!(\"CARGO_TEST_DISABLE_NIGHTLY\").is_none()\n            && (vers.contains(\"-nightly\") || vers.contains(\"-dev\"));\n        let minor = vers.split('.').skip(1).next().unwrap().parse().unwrap();\n        unsafe { VERSION = (minor, is_nightly) }\n    });\n    unsafe { VERSION }\n}\n\nfn compile(file: &Path) -> Result<Output, Error> {\n    let tmp = tempdir()?;\n\n    let args: Vec<OsString> = vec![\n        file.into(),\n        \"--error-format=json\".into(),\n        \"--emit=metadata\".into(),\n        \"--crate-name=rustfix_test\".into(),\n        \"--out-dir\".into(),\n        tmp.path().into(),\n    ];\n\n    let res = Command::new(env::var_os(\"RUSTC\").unwrap_or(\"rustc\".into()))\n        .args(&args)\n        .env(\"CLIPPY_DISABLE_DOCS_LINKS\", \"true\")\n        .env_remove(\"RUST_LOG\")\n        .output()?;\n\n    Ok(res)\n}\n\nfn compile_and_get_json_errors(file: &Path) -> Result<String, Error> {\n    let res = compile(file)?;\n    let stderr = String::from_utf8(res.stderr)?;\n    if stderr.contains(\"is only accepted on the nightly compiler\") {\n        panic!(\"rustfix tests require a nightly compiler\");\n    }\n\n    match res.status.code() {\n        Some(0) | Some(1) | Some(101) => Ok(stderr),\n        _ => Err(anyhow!(\n            \"failed with status {:?}: {}\",\n            res.status.code(),\n            stderr\n        )),\n    }\n}\n\nfn compiles_without_errors(file: &Path) -> Result<(), Error> {\n    let res = compile(file)?;\n\n    match res.status.code() {\n        Some(0) => Ok(()),\n        _ => Err(anyhow!(\n            \"file {:?} failed compile with status {:?}:\\n {}\",\n            file,\n            res.status.code(),\n            String::from_utf8(res.stderr)?\n        )),\n    }\n}\n\nfn test_rustfix_with_file<P: AsRef<Path>>(file: P, mode: &str) {\n    let file: &Path = file.as_ref();\n    let json_file = file.with_extension(\"json\");\n    let expected_fixed_file = file.with_extension(\"fixed.rs\");\n\n    let filter_suggestions = if mode == fixmode::EVERYTHING {\n        rustfix::Filter::Everything\n    } else {\n        rustfix::Filter::MachineApplicableOnly\n    };\n\n    let code = fs::read_to_string(file).unwrap();\n\n    let json = compile_and_get_json_errors(file)\n        .with_context(|| format!(\"could not compile {}\", file.display()))\n        .unwrap();\n\n    let suggestions =\n        rustfix::get_suggestions_from_json(&json, &HashSet::new(), filter_suggestions)\n            .context(\"could not load suggestions\")\n            .unwrap();\n\n    let fixed = apply_suggestions(&code, &suggestions)\n        .with_context(|| format!(\"could not apply suggestions to {}\", file.display()))\n        .unwrap()\n        .replace('\\r', \"\");\n\n    let assert = Assert::new().action_env(snapbox::assert::DEFAULT_ACTION_ENV);\n    let (actual_fix, expected_fix) = assert.normalize(\n        Data::text(&fixed),\n        Data::read_from(expected_fixed_file.as_path(), Some(DataFormat::Text)),\n    );\n\n    if actual_fix != expected_fix {\n        let fixed_assert = assert.try_eq(Some(&\"Current Fix\"), actual_fix, expected_fix);\n        assert!(fixed_assert.is_ok(), \"{}\", fixed_assert.err().unwrap());\n\n        let expected_json = Data::read_from(json_file.as_path(), Some(DataFormat::Text));\n\n        let pretty_json = json\n            .split(\"\\n\")\n            .filter(|j| !j.is_empty())\n            .map(|j| {\n                serde_json::to_string_pretty(&serde_json::from_str::<Value>(j).unwrap()).unwrap()\n            })\n            .collect::<Vec<String>>()\n            .join(\"\\n\");\n\n        let json_assert = assert.try_eq(\n            Some(&\"Compiler Error\"),\n            Data::text(pretty_json),\n            expected_json,\n        );\n        assert!(json_assert.is_ok(), \"{}\", json_assert.err().unwrap());\n    }\n\n    compiles_without_errors(&expected_fixed_file).unwrap();\n}\n\nmacro_rules! run_test {\n    ($name:ident, $file:expr) => {\n        #[test]\n        #[allow(non_snake_case)]\n        fn $name() {\n            let (_, nightly) = version();\n            if !$file.ends_with(\".nightly.rs\") || nightly {\n                let file = Path::new(concat!(\"./tests/everything/\", $file));\n                assert!(file.is_file(), \"could not load {}\", $file);\n                test_rustfix_with_file(file, fixmode::EVERYTHING);\n            }\n        }\n    };\n}\n\nrun_test! {\n    closure_immutable_outer_variable,\n    \"closure-immutable-outer-variable.rs\"\n}\nrun_test! {dedup_suggestions, \"dedup-suggestions.rs\"}\nrun_test! {E0178, \"E0178.rs\"}\nrun_test! {handle_insert_only, \"handle-insert-only.rs\"}\nrun_test! {lt_generic_comp, \"lt-generic-comp.rs\"}\nrun_test! {multiple_solutions, \"multiple-solutions.rs\"}\nrun_test! {replace_only_one_char, \"replace-only-one-char.rs\"}\nrun_test! {str_lit_type_mismatch, \"str-lit-type-mismatch.rs\"}\nrun_test! {use_insert, \"use-insert.rs\"}\n"
  },
  {
    "path": "crates/semver-check/Cargo.toml",
    "content": "[package]\nname = \"semver-check\"\nversion = \"0.0.0\"\nauthors = [\"Eric Huss\"]\nedition.workspace = true\npublish = false\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\ntempfile.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/semver-check/src/main.rs",
    "content": "//! Test runner for the semver compatibility doc chapter.\n//!\n//! This extracts all the \"rust\" annotated code blocks and tests that they\n//! either fail or succeed as expected. This also checks that the examples are\n//! formatted correctly.\n//!\n//! An example with the word \"MINOR\" at the top is expected to successfully\n//! build against the before and after. Otherwise it should fail. A comment of\n//! \"// Error:\" will check that the given message appears in the error output.\n//!\n//! The code block can also include the annotations:\n//! - `run-fail`: The test should fail at runtime, not compiletime.\n//! - `dont-deny`: By default tests have a `#![deny(warnings)]`. This option\n//!   avoids this attribute. Note that `#![allow(unused)]` is always added.\n\n#![allow(clippy::print_stderr)]\n\nuse std::error::Error;\nuse std::fs;\nuse std::path::Path;\nuse std::process::{Command, Output};\n\nfn main() {\n    if let Err(e) = doit() {\n        eprintln!(\"error: {}\", e);\n        std::process::exit(1);\n    }\n}\n\nconst SEPARATOR: &str = \"///////////////////////////////////////////////////////////\";\n\nfn doit() -> Result<(), Box<dyn Error>> {\n    let filename = std::env::args().nth(1).unwrap_or_else(|| {\n        Path::new(env!(\"CARGO_MANIFEST_DIR\"))\n            .join(\"../../src/doc/src/reference/semver.md\")\n            .to_str()\n            .unwrap()\n            .to_string()\n    });\n    let contents = fs::read_to_string(filename)?;\n    let mut lines = contents.lines().enumerate();\n\n    loop {\n        // Find a rust block.\n        let (block_start, run_program, deny_warnings) = loop {\n            match lines.next() {\n                Some((lineno, line)) => {\n                    if line.trim().starts_with(\"```rust\") && !line.contains(\"skip\") {\n                        break (\n                            lineno + 1,\n                            line.contains(\"run-fail\"),\n                            !line.contains(\"dont-deny\"),\n                        );\n                    }\n                }\n                None => return Ok(()),\n            }\n        };\n        // Read in the code block.\n        let mut block = Vec::new();\n        loop {\n            match lines.next() {\n                Some((_, line)) => {\n                    if line.trim() == \"```\" {\n                        break;\n                    }\n                    // Support rustdoc/mdbook hidden lines.\n                    let line = line.strip_prefix(\"# \").unwrap_or(line);\n                    if line == \"#\" {\n                        block.push(\"\");\n                    } else {\n                        block.push(line);\n                    }\n                }\n                None => {\n                    return Err(format!(\n                        \"rust block did not end for example starting on line {}\",\n                        block_start\n                    )\n                    .into());\n                }\n            }\n        }\n        // Split it into the separate source files.\n        let parts: Vec<_> = block.split(|line| line.trim() == SEPARATOR).collect();\n        if parts.len() != 4 {\n            return Err(format!(\n                \"expected 4 sections in example starting on line {}, got {}:\\n{:?}\",\n                block_start,\n                parts.len(),\n                parts\n            )\n            .into());\n        }\n        let join = |part: &[&str]| {\n            let mut result = String::new();\n            result.push_str(\"#![allow(unused)]\\n\");\n            if deny_warnings {\n                result.push_str(\"#![deny(warnings)]\\n\");\n            }\n            result.push_str(&part.join(\"\\n\"));\n            if !result.ends_with('\\n') {\n                result.push('\\n');\n            }\n            result\n        };\n        let expect_success = parts[0][0].contains(\"MINOR\");\n        eprintln!(\"Running test from line {}\", block_start);\n\n        let result = run_test(\n            join(parts[1]),\n            join(parts[2]),\n            join(parts[3]),\n            expect_success,\n            run_program,\n        );\n\n        if let Err(e) = result {\n            return Err(format!(\n                \"test failed for example starting on line {}: {}\",\n                block_start, e\n            )\n            .into());\n        }\n    }\n}\n\nconst CRATE_NAME: &str = \"updated_crate\";\n\nfn run_test(\n    before: String,\n    after: String,\n    example: String,\n    expect_success: bool,\n    run_program: bool,\n) -> Result<(), Box<dyn Error>> {\n    let tempdir = tempfile::TempDir::new()?;\n    let before_p = tempdir.path().join(\"before.rs\");\n    let after_p = tempdir.path().join(\"after.rs\");\n    let example_p = tempdir.path().join(\"example.rs\");\n\n    let check_fn = if run_program {\n        run_check\n    } else {\n        compile_check\n    };\n\n    compile_check(before, &before_p, CRATE_NAME, false, true)?;\n    check_fn(example.clone(), &example_p, \"example\", true, true)?;\n    compile_check(after, &after_p, CRATE_NAME, false, true)?;\n    check_fn(example, &example_p, \"example\", true, expect_success)?;\n    Ok(())\n}\n\nfn check_formatting(path: &Path) -> Result<(), Box<dyn Error>> {\n    match Command::new(\"rustfmt\")\n        .args(&[\"--edition=2018\", \"--check\"])\n        .arg(path)\n        .status()\n    {\n        Ok(status) => {\n            if !status.success() {\n                return Err(format!(\"failed to run rustfmt: {}\", status).into());\n            }\n            Ok(())\n        }\n        Err(e) => Err(format!(\"failed to run rustfmt: {}\", e).into()),\n    }\n}\n\nfn compile(\n    contents: &str,\n    path: &Path,\n    crate_name: &str,\n    extern_path: bool,\n) -> Result<Output, Box<dyn Error>> {\n    let crate_type = if contents.contains(\"fn main()\") {\n        \"bin\"\n    } else {\n        \"rlib\"\n    };\n\n    fs::write(path, &contents)?;\n    check_formatting(path)?;\n    let out_dir = path.parent().unwrap();\n    let mut cmd = Command::new(\"rustc\");\n    cmd.args(&[\n        \"--edition=2021\",\n        \"--crate-type\",\n        crate_type,\n        \"--crate-name\",\n        crate_name,\n        \"--out-dir\",\n    ]);\n    cmd.arg(&out_dir);\n    if extern_path {\n        let epath = out_dir.join(format!(\"lib{}.rlib\", CRATE_NAME));\n        cmd.arg(\"--extern\")\n            .arg(format!(\"{}={}\", CRATE_NAME, epath.display()));\n    }\n    cmd.arg(path);\n    cmd.output().map_err(Into::into)\n}\n\nfn compile_check(\n    mut contents: String,\n    path: &Path,\n    crate_name: &str,\n    extern_path: bool,\n    expect_success: bool,\n) -> Result<(), Box<dyn Error>> {\n    // If the example has an error message, remove it so that it can be\n    // compared with the actual output, and also to avoid issues with rustfmt\n    // moving it around.\n    let expected_error = match contents.find(\"// Error:\") {\n        Some(index) => {\n            let start = contents[..index].rfind(|ch| ch != ' ').unwrap();\n            let end = contents[index..].find('\\n').unwrap();\n            let error = contents[index + 9..index + end].trim().to_string();\n            contents.replace_range(start + 1..index + end, \"\");\n            Some(error)\n        }\n        None => None,\n    };\n\n    let output = compile(&contents, path, crate_name, extern_path)?;\n\n    let stderr = std::str::from_utf8(&output.stderr).unwrap();\n    match (output.status.success(), expect_success) {\n        (true, true) => Ok(()),\n        (true, false) => Err(format!(\n            \"expected failure, got success {}\\n===== Contents:\\n{}\\n===== Output:\\n{}\\n\",\n            path.display(),\n            contents,\n            stderr\n        )\n        .into()),\n        (false, true) => Err(format!(\n            \"expected success, got error {}\\n===== Contents:\\n{}\\n===== Output:\\n{}\\n\",\n            path.display(),\n            contents,\n            stderr\n        )\n        .into()),\n        (false, false) => {\n            if expected_error.is_none() {\n                return Err(\"failing test should have an \\\"// Error:\\\" annotation \".into());\n            }\n            let expected_error = expected_error.unwrap();\n            if !stderr.contains(&expected_error) {\n                Err(format!(\n                    \"expected error message not found in compiler output\\nExpected: {}\\nGot:\\n{}\\n\",\n                    expected_error, stderr\n                )\n                .into())\n            } else {\n                Ok(())\n            }\n        }\n    }\n}\n\nfn run_check(\n    contents: String,\n    path: &Path,\n    crate_name: &str,\n    extern_path: bool,\n    expect_success: bool,\n) -> Result<(), Box<dyn Error>> {\n    let compile_output = compile(&contents, path, crate_name, extern_path)?;\n\n    if !compile_output.status.success() {\n        let stderr = std::str::from_utf8(&compile_output.stderr).unwrap();\n        return Err(format!(\n            \"expected success, got error {}\\n===== Contents:\\n{}\\n===== Output:\\n{}\\n\",\n            path.display(),\n            contents,\n            stderr\n        )\n        .into());\n    }\n\n    let binary_path = path.parent().unwrap().join(crate_name);\n\n    let output = Command::new(binary_path).output()?;\n\n    let stderr = std::str::from_utf8(&output.stderr).unwrap();\n\n    match (output.status.success(), expect_success) {\n        (true, false) => Err(format!(\n            \"expected panic, got success {}\\n===== Contents:\\n{}\\n===== Output:\\n{}\\n\",\n            path.display(),\n            contents,\n            stderr\n        )\n        .into()),\n        (false, true) => Err(format!(\n            \"expected success, got panic {}\\n===== Contents:\\n{}\\n===== Output:\\n{}\\n\",\n            path.display(),\n            contents,\n            stderr,\n        )\n        .into()),\n        (_, _) => Ok(()),\n    }\n}\n"
  },
  {
    "path": "crates/xtask-build-man/Cargo.toml",
    "content": "[package]\nname = \"xtask-build-man\"\nversion = \"0.0.0\"\nedition.workspace = true\npublish = false\n\n[dependencies]\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/xtask-build-man/src/main.rs",
    "content": "//! ```text\n//! NAME\n//!         build-man\n//!\n//! SYNOPSIS\n//!         build-man\n//!\n//! DESCRIPTION\n//!         Build the man pages for packages `mdman` and `cargo`.\n//!         For more, read their doc comments.\n//! ```\n\n#![allow(clippy::print_stderr)]\n\nuse std::fs;\nuse std::io;\nuse std::path::PathBuf;\nuse std::process;\nuse std::process::Command;\n\nfn main() -> io::Result<()> {\n    build_mdman()?;\n    build_cargo()?;\n    Ok(())\n}\n\n/// Builds the man pages for `mdman`.\nfn build_mdman() -> io::Result<()> {\n    cwd_to_workspace_root()?;\n\n    let src_paths = &[\"crates/mdman/doc/mdman.md\".into()];\n    let dst_path = \"crates/mdman/doc/out\";\n    let outs = [(\"md\", dst_path), (\"txt\", dst_path), (\"man\", dst_path)];\n\n    build_man(\"mdman\", src_paths, &outs, &[])\n}\n\n/// Builds the man pages for Cargo.\n///\n/// The source for the man pages are located in src/doc/man/ in markdown format.\n/// These also are handlebars templates, see crates/mdman/README.md for details.\n///\n/// The generated man pages are placed in the src/etc/man/ directory. The pages\n/// are also expanded into markdown (after being expanded by handlebars) and\n/// saved in the src/doc/src/commands/ directory. These are included in the\n/// Cargo book, which is converted to HTML by mdbook.\nfn build_cargo() -> io::Result<()> {\n    // Find all `src/doc/man/cargo*.md`\n    let src_paths = {\n        let mut src_paths = Vec::new();\n        for entry in fs::read_dir(\"src/doc/man\")? {\n            let entry = entry?;\n            let file_name = entry.file_name();\n            let file_name = file_name.to_str().unwrap();\n            if file_name.starts_with(\"cargo\") && file_name.ends_with(\".md\") {\n                src_paths.push(entry.path());\n            }\n        }\n        src_paths\n    };\n    let outs = [\n        (\"md\", \"src/doc/src/commands\"),\n        (\"txt\", \"src/doc/man/generated_txt\"),\n        (\"man\", \"src/etc/man\"),\n    ];\n    let args = [\n        \"--url\",\n        \"https://doc.rust-lang.org/cargo/commands/\",\n        \"--man\",\n        \"rustc:1=https://doc.rust-lang.org/rustc/index.html\",\n        \"--man\",\n        \"rustdoc:1=https://doc.rust-lang.org/rustdoc/index.html\",\n    ];\n    build_man(\"cargo\", &src_paths[..], &outs, &args)\n}\n\n/// Change to workspace root.\n///\n/// Assumed this xtask is located in `[WORKSPACE]/crates/xtask-build-man`.\nfn cwd_to_workspace_root() -> io::Result<()> {\n    let pkg_root = std::env!(\"CARGO_MANIFEST_DIR\");\n    let ws_root = format!(\"{pkg_root}/../..\");\n    std::env::set_current_dir(ws_root)\n}\n\n/// Builds the man pages.\nfn build_man(\n    pkg_name: &str,\n    src_paths: &[PathBuf],\n    outs: &[(&str, &str)],\n    extra_args: &[&str],\n) -> io::Result<()> {\n    for (format, dst_path) in outs {\n        eprintln!(\"Start converting `{format}` for package `{pkg_name}`...\");\n        let mut cmd = Command::new(std::env!(\"CARGO\"));\n        cmd.args([\"run\", \"--package\", \"mdman\", \"--\"])\n            .args([\"-t\", format, \"-o\", dst_path])\n            .args(src_paths)\n            .args(extra_args);\n\n        let status = cmd.status()?;\n        if !status.success() {\n            eprintln!(\"failed to build the man pages for package `{pkg_name}`\");\n            eprintln!(\"failed command: `{cmd:?}`\");\n            process::exit(status.code().unwrap_or(1));\n        }\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "crates/xtask-bump-check/Cargo.toml",
    "content": "[package]\nname = \"xtask-bump-check\"\nversion = \"0.0.0\"\nedition.workspace = true\npublish = false\n\n[dependencies]\nanyhow.workspace = true\ncargo.workspace = true\ncargo-util.workspace = true\nclap.workspace = true\ngit2.workspace = true\nsemver.workspace = true\ntracing-subscriber.workspace = true\ntracing.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/xtask-bump-check/src/main.rs",
    "content": "mod xtask;\n\nfn main() {\n    setup_logger();\n\n    let cli = xtask::cli();\n    let matches = cli.get_matches();\n\n    let mut gctx = cargo::util::context::GlobalContext::default().unwrap_or_else(|e| {\n        let mut eval = cargo::core::shell::Shell::new();\n        cargo::exit_with_error(e.into(), &mut eval)\n    });\n    if let Err(e) = xtask::exec(&matches, &mut gctx) {\n        cargo::exit_with_error(e, &mut gctx.shell())\n    }\n}\n\n// In sync with `src/bin/cargo/main.rs@setup_logger`.\nfn setup_logger() {\n    let env = tracing_subscriber::EnvFilter::from_env(\"CARGO_LOG\");\n\n    tracing_subscriber::fmt()\n        .with_timer(tracing_subscriber::fmt::time::Uptime::default())\n        .with_ansi(std::io::IsTerminal::is_terminal(&std::io::stderr()))\n        .with_writer(std::io::stderr)\n        .with_env_filter(env)\n        .init();\n}\n"
  },
  {
    "path": "crates/xtask-bump-check/src/xtask.rs",
    "content": "//! ```text\n//! NAME\n//!         xtask-bump-check\n//!\n//! SYNOPSIS\n//!         xtask-bump-check --base-rev <REV> --head-rev <REV>\n//!\n//! DESCRIPTION\n//!         Checks if there is any member got changed since a base commit\n//!         but forgot to bump its version.\n//! ```\n\n#![allow(clippy::print_stdout)] // Fine for build utilities\n\nuse std::collections::HashMap;\nuse std::fmt::Write;\nuse std::fs;\nuse std::task;\n\nuse cargo::CargoResult;\nuse cargo::core::Package;\nuse cargo::core::Registry;\nuse cargo::core::SourceId;\nuse cargo::core::Workspace;\nuse cargo::core::dependency::Dependency;\nuse cargo::sources::source::QueryKind;\nuse cargo::util::cache_lock::CacheLockMode;\nuse cargo::util::command_prelude::*;\nuse cargo_util::ProcessBuilder;\n\nconst UPSTREAM_BRANCH: &str = \"master\";\nconst STATUS: &str = \"BumpCheck\";\n\npub fn cli() -> clap::Command {\n    clap::Command::new(\"xtask-bump-check\")\n        .arg(\n            opt(\n                \"verbose\",\n                \"Use verbose output (-vv very verbose/build.rs output)\",\n            )\n            .short('v')\n            .action(ArgAction::Count)\n            .global(true),\n        )\n        .arg(\n            flag(\"quiet\", \"Do not print cargo log messages\")\n                .short('q')\n                .global(true),\n        )\n        .arg(\n            opt(\"color\", \"Coloring: auto, always, never\")\n                .value_name(\"WHEN\")\n                .global(true),\n        )\n        .arg(opt(\"base-rev\", \"Git revision to lookup for a baseline\"))\n        .arg(opt(\"head-rev\", \"Git revision with changes\"))\n        .arg(flag(\"frozen\", \"Require Cargo.lock and cache to be up-to-date\").global(true))\n        .arg(flag(\"locked\", \"Require Cargo.lock to be up-to-date\").global(true))\n        .arg(flag(\"offline\", \"Run without accessing the network\").global(true))\n        .arg(multi_opt(\"config\", \"KEY=VALUE\", \"Override a configuration value\").global(true))\n        .arg(flag(\"github\", \"Group output using GitHub's syntax\"))\n        .arg(\n            Arg::new(\"unstable-features\")\n                .help(\"Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details\")\n                .short('Z')\n                .value_name(\"FLAG\")\n                .action(ArgAction::Append)\n                .global(true),\n        )\n}\n\npub fn exec(args: &clap::ArgMatches, gctx: &mut cargo::util::GlobalContext) -> cargo::CliResult {\n    global_context_configure(gctx, args)?;\n\n    bump_check(args, gctx)?;\n\n    Ok(())\n}\n\nfn global_context_configure(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let verbose = args.verbose();\n    // quiet is unusual because it is redefined in some subcommands in order\n    // to provide custom help text.\n    let quiet = args.flag(\"quiet\");\n    let color = args.get_one::<String>(\"color\").map(String::as_str);\n    let frozen = args.flag(\"frozen\");\n    let locked = args.flag(\"locked\");\n    let offline = args.flag(\"offline\");\n    let mut unstable_flags = vec![];\n    if let Some(values) = args.get_many::<String>(\"unstable-features\") {\n        unstable_flags.extend(values.cloned());\n    }\n    let mut config_args = vec![];\n    if let Some(values) = args.get_many::<String>(\"config\") {\n        config_args.extend(values.cloned());\n    }\n    gctx.configure(\n        verbose,\n        quiet,\n        color,\n        frozen,\n        locked,\n        offline,\n        &None,\n        &unstable_flags,\n        &config_args,\n    )?;\n    Ok(())\n}\n\n/// Main entry of `xtask-bump-check`.\n///\n/// Assumption: version number are incremental. We never have point release for old versions.\nfn bump_check(args: &clap::ArgMatches, gctx: &cargo::util::GlobalContext) -> CargoResult<()> {\n    let ws = args.workspace(gctx)?;\n    let repo = git2::Repository::open(ws.root())?;\n    let base_commit = get_base_commit(gctx, args, &repo)?;\n    let head_commit = get_head_commit(args, &repo)?;\n    let referenced_commit = get_referenced_commit(&repo, &base_commit)?;\n    let github = args.get_flag(\"github\");\n    let status = |msg: &str| gctx.shell().status(STATUS, msg);\n\n    let crates_not_check_against_channels = [\n        // High false positive rate between beta branch and requisite version bump soon after\n        //\n        // Low risk because we always bump the \"major\" version after beta branch; we are\n        // only losing out on checks for patch releases.\n        //\n        // Note: this is already skipped in `changed`\n        \"cargo\",\n        // Don't check against beta and stable branches,\n        // as the publish of these crates are not tied with Rust release process.\n        // See `TO_PUBLISH` in publish.py.\n        \"home\",\n    ];\n\n    status(&format!(\"base commit `{}`\", base_commit.id()))?;\n    status(&format!(\"head commit `{}`\", head_commit.id()))?;\n\n    let mut needs_bump = Vec::new();\n    if github {\n        println!(\"::group::Checking for bumps of changed packages\");\n    }\n    let changed_members = changed(&ws, &repo, &base_commit, &head_commit)?;\n    check_crates_io(&ws, &changed_members, &mut needs_bump)?;\n    if let Some(referenced_commit) = referenced_commit.as_ref() {\n        status(&format!(\"compare against `{}`\", referenced_commit.id()))?;\n        for referenced_member in checkout_ws(&ws, &repo, referenced_commit)?.members() {\n            let pkg_name = referenced_member.name().as_str();\n\n            if crates_not_check_against_channels.contains(&pkg_name) {\n                continue;\n            }\n\n            let Some(changed_member) = changed_members.get(pkg_name) else {\n                tracing::trace!(\"skipping {pkg_name}, may be removed or not published\");\n                continue;\n            };\n\n            if changed_member.version() <= referenced_member.version() {\n                needs_bump.push(*changed_member);\n            }\n        }\n    }\n    if !needs_bump.is_empty() {\n        needs_bump.sort();\n        needs_bump.dedup();\n        let mut msg = String::new();\n        msg.push_str(\"Detected changes in these crates but no version bump found:\\n\");\n        for pkg in needs_bump {\n            writeln!(&mut msg, \"  {}@{}\", pkg.name(), pkg.version())?;\n        }\n        msg.push_str(\"\\nPlease bump at least one patch version in each corresponding Cargo.toml.\");\n        anyhow::bail!(msg)\n    }\n    if github {\n        println!(\"::endgroup::\");\n    }\n\n    if let Some(referenced_commit) = referenced_commit.as_ref() {\n        if github {\n            println!(\"::group::SemVer Checks against {}\", referenced_commit.id());\n        }\n        let mut cmd = ProcessBuilder::new(\"cargo\");\n        cmd.arg(\"semver-checks\")\n            .arg(\"--workspace\")\n            .arg(\"--baseline-rev\")\n            .arg(referenced_commit.id().to_string());\n        for krate in crates_not_check_against_channels {\n            cmd.args(&[\"--exclude\", krate]);\n        }\n        gctx.shell().status(\"Running\", &cmd)?;\n        cmd.exec()?;\n        if github {\n            println!(\"::endgroup::\");\n        }\n    }\n\n    // Even when we test against baseline-rev, we still need to make sure a\n    // change doesn't violate SemVer rules against crates.io releases. The\n    // possibility of this happening is nearly zero but no harm to check twice.\n    if github {\n        println!(\"::group::SemVer Checks against crates.io\");\n    }\n\n    let mut cmd = ProcessBuilder::new(\"cargo\");\n    cmd.arg(\"semver-checks\")\n        .arg(\"check-release\")\n        .arg(\"--workspace\")\n        .args(&[\"--exclude\", \"cargo\"]);\n\n    gctx.shell().status(\"Running\", &cmd)?;\n    cmd.exec()?;\n\n    // Cargo has mutually exclusive features for different HTTP backends, so\n    // pass a specific `--features` instead of including this in the\n    // `--all-features` performed by the previous command.\n    let mut cmd = ProcessBuilder::new(\"cargo\");\n    cmd.arg(\"semver-checks\")\n        .arg(\"check-release\")\n        .args(&[\"--package\", \"cargo\"])\n        .arg(\"--default-features\")\n        .args(&[\"--features\", \"all-static\"]);\n\n    gctx.shell().status(\"Running\", &cmd)?;\n    cmd.exec()?;\n\n    if github {\n        println!(\"::endgroup::\");\n    }\n\n    status(\"no version bump needed for member crates.\")?;\n\n    Ok(())\n}\n\n/// Returns the commit of upstream `master` branch if `base-rev` is missing.\nfn get_base_commit<'a>(\n    gctx: &GlobalContext,\n    args: &clap::ArgMatches,\n    repo: &'a git2::Repository,\n) -> CargoResult<git2::Commit<'a>> {\n    let base_commit = match args.get_one::<String>(\"base-rev\") {\n        Some(sha) => {\n            let obj = repo.revparse_single(sha)?;\n            obj.peel_to_commit()?\n        }\n        None => {\n            let upstream_branches = repo\n                .branches(Some(git2::BranchType::Remote))?\n                .filter_map(|r| r.ok())\n                .filter(|(b, _)| {\n                    b.name()\n                        .ok()\n                        .flatten()\n                        .unwrap_or_default()\n                        .ends_with(&format!(\"/{UPSTREAM_BRANCH}\"))\n                })\n                .map(|(b, _)| b)\n                .collect::<Vec<_>>();\n            if upstream_branches.is_empty() {\n                anyhow::bail!(\n                    \"could not find `base-sha` for `{UPSTREAM_BRANCH}`, pass it in directly\"\n                );\n            }\n            let upstream_ref = upstream_branches[0].get();\n            if upstream_branches.len() > 1 {\n                let name = upstream_ref.name().expect(\"name is valid UTF-8\");\n                let _ = gctx.shell().warn(format!(\n                    \"multiple `{UPSTREAM_BRANCH}` found, picking {name}\"\n                ));\n            }\n            upstream_ref.peel_to_commit()?\n        }\n    };\n    Ok(base_commit)\n}\n\n/// Returns `HEAD` of the Git repository if `head-rev` is missing.\nfn get_head_commit<'a>(\n    args: &clap::ArgMatches,\n    repo: &'a git2::Repository,\n) -> CargoResult<git2::Commit<'a>> {\n    let head_commit = match args.get_one::<String>(\"head-rev\") {\n        Some(sha) => {\n            let head_obj = repo.revparse_single(sha)?;\n            head_obj.peel_to_commit()?\n        }\n        None => {\n            let head_ref = repo.head()?;\n            head_ref.peel_to_commit()?\n        }\n    };\n    Ok(head_commit)\n}\n\n/// Gets the referenced commit to compare if version bump needed.\n///\n/// * When merging into nightly, check the version with beta branch\n/// * When merging into beta, check the version with stable branch\n/// * When merging into stable, check against crates.io registry directly\nfn get_referenced_commit<'a>(\n    repo: &'a git2::Repository,\n    base: &git2::Commit<'a>,\n) -> CargoResult<Option<git2::Commit<'a>>> {\n    let [beta, stable] = beta_and_stable_branch(repo)?;\n    let rev_id = base.id();\n    let stable_commit = stable.get().peel_to_commit()?;\n    let beta_commit = beta.get().peel_to_commit()?;\n\n    let referenced_commit = if rev_id == stable_commit.id() {\n        None\n    } else if rev_id == beta_commit.id() {\n        tracing::trace!(\"stable branch from `{}`\", stable.name().unwrap().unwrap());\n        Some(stable_commit)\n    } else {\n        tracing::trace!(\"beta branch from `{}`\", beta.name().unwrap().unwrap());\n        Some(beta_commit)\n    };\n\n    Ok(referenced_commit)\n}\n\n/// Get the current beta and stable branch in cargo repository.\n///\n/// Assumptions:\n///\n/// * The repository contains the full history of `<remote>/rust-1.*.0` branches.\n/// * The version part of `<remote>/rust-1.*.0` always ends with a zero.\n/// * The maximum version is for beta channel, and the second one is for stable.\nfn beta_and_stable_branch(repo: &git2::Repository) -> CargoResult<[git2::Branch<'_>; 2]> {\n    let mut release_branches = Vec::new();\n    for branch in repo.branches(Some(git2::BranchType::Remote))? {\n        let (branch, _) = branch?;\n        let name = branch.name()?.unwrap();\n        let Some((_, version)) = name.split_once(\"/rust-\") else {\n            tracing::trace!(\"branch `{name}` is not in the format of `<remote>/rust-<semver>`\");\n            continue;\n        };\n        let Ok(version) = version.parse::<semver::Version>() else {\n            tracing::trace!(\"branch `{name}` is not a valid semver: `{version}`\");\n            continue;\n        };\n        release_branches.push((version, branch));\n    }\n    release_branches.sort_unstable_by(|a, b| a.0.cmp(&b.0));\n    release_branches.dedup_by(|a, b| a.0 == b.0);\n\n    let beta = release_branches.pop().unwrap();\n    let stable = release_branches.pop().unwrap();\n\n    assert_eq!(beta.0.major, 1);\n    assert_eq!(beta.0.patch, 0);\n    assert_eq!(stable.0.major, 1);\n    assert_eq!(stable.0.patch, 0);\n    assert_ne!(beta.0.minor, stable.0.minor);\n\n    Ok([beta.1, stable.1])\n}\n\n/// Lists all changed workspace members between two commits.\nfn changed<'r, 'ws>(\n    ws: &'ws Workspace<'_>,\n    repo: &'r git2::Repository,\n    base_commit: &git2::Commit<'r>,\n    head: &git2::Commit<'r>,\n) -> CargoResult<HashMap<&'ws str, &'ws Package>> {\n    let root_pkg_name = ws.current()?.name(); // `cargo` crate.\n    let ws_members = ws\n        .members()\n        .filter(|pkg| pkg.name() != root_pkg_name) // Only take care of sub crates here.\n        .filter(|pkg| pkg.publish() != &Some(vec![])) // filter out `publish = false`\n        .map(|pkg| {\n            // Having relative package root path so that we can compare with\n            // paths of changed files to determine which package has changed.\n            let relative_pkg_root = pkg.root().strip_prefix(ws.root()).unwrap();\n            (relative_pkg_root, pkg)\n        })\n        .collect::<Vec<_>>();\n\n    let diff = symmetric_diff(repo, base_commit, head)?;\n    let mut changed_members = HashMap::new();\n\n    for delta in diff.deltas() {\n        let old = delta.old_file().path().unwrap();\n        let new = delta.new_file().path().unwrap();\n        for (pkg_root, pkg) in ws_members.iter() {\n            if old.starts_with(pkg_root) || new.starts_with(pkg_root) {\n                changed_members.insert(pkg.name().as_str(), *pkg);\n                break;\n            }\n        }\n    }\n\n    tracing::trace!(\"changed_members: {:?}\", changed_members.keys());\n    Ok(changed_members)\n}\n\n/// Using a \"symmetric difference\" between base and head.\nfn symmetric_diff<'a>(\n    repo: &'a git2::Repository,\n    base: &'a git2::Commit<'a>,\n    head: &'a git2::Commit<'a>,\n) -> CargoResult<git2::Diff<'a>> {\n    let ancestor_oid = repo.merge_base(base.id(), head.id())?;\n    let ancestor_commit = repo.find_commit(ancestor_oid)?;\n    let ancestor_tree = ancestor_commit.as_object().peel_to_tree()?;\n    let head_tree = head.as_object().peel_to_tree()?;\n    let diff =\n        repo.diff_tree_to_tree(Some(&ancestor_tree), Some(&head_tree), Default::default())?;\n    tracing::info!(merge_base = %ancestor_commit.id(), base = %base.id(), head = %head.id(), \"git diff base...head\");\n    Ok(diff)\n}\n\n/// Compares version against published crates on crates.io.\n///\n/// Assumption: We always release a version larger than all existing versions.\nfn check_crates_io<'a>(\n    ws: &Workspace<'a>,\n    changed_members: &HashMap<&'a str, &'a Package>,\n    needs_bump: &mut Vec<&'a Package>,\n) -> CargoResult<()> {\n    let gctx = ws.gctx();\n    let source_id = SourceId::crates_io(gctx)?;\n    let mut registry = ws.package_registry()?;\n    let _lock = gctx.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n    registry.lock_patches();\n    gctx.shell().status(\n        STATUS,\n        format_args!(\"compare against `{}`\", source_id.display_registry_name()),\n    )?;\n    for (name, member) in changed_members {\n        let current = member.version();\n        let version_req = format!(\">={current}\");\n        let query = Dependency::parse(*name, Some(&version_req), source_id)?;\n        let possibilities = loop {\n            // Exact to avoid returning all for path/git\n            match registry.query_vec(&query, QueryKind::Exact) {\n                task::Poll::Ready(res) => {\n                    break res?;\n                }\n                task::Poll::Pending => registry.block_until_ready()?,\n            }\n        };\n        if possibilities.is_empty() {\n            tracing::trace!(\"dep `{name}` has no version greater than or equal to `{current}`\");\n        } else {\n            tracing::trace!(\n                \"`{name}@{current}` needs a bump because its should have a version newer than crates.io: {:?}`\",\n                possibilities\n                    .iter()\n                    .map(|s| s.as_summary())\n                    .map(|s| format!(\"{}@{}\", s.name(), s.version()))\n                    .collect::<Vec<_>>(),\n            );\n            needs_bump.push(member);\n        }\n    }\n\n    Ok(())\n}\n\n/// Checkouts a temporary workspace to do further version comparisons.\nfn checkout_ws<'gctx, 'a>(\n    ws: &Workspace<'gctx>,\n    repo: &'a git2::Repository,\n    referenced_commit: &git2::Commit<'a>,\n) -> CargoResult<Workspace<'gctx>> {\n    let repo_path = repo.path().as_os_str().to_str().unwrap();\n    // Put it under `target/cargo-<short-id>`\n    let short_id = &referenced_commit.id().to_string()[..7];\n    let checkout_path = ws.target_dir().join(format!(\"cargo-{short_id}\"));\n    let checkout_path = checkout_path.as_path_unlocked();\n    let _ = fs::remove_dir_all(checkout_path);\n    let new_repo = git2::build::RepoBuilder::new()\n        .clone_local(git2::build::CloneLocal::Local)\n        .clone(repo_path, checkout_path)?;\n    let obj = new_repo.find_object(referenced_commit.id(), None)?;\n    new_repo.reset(&obj, git2::ResetType::Hard, None)?;\n    Workspace::new(&checkout_path.join(\"Cargo.toml\"), ws.gctx())\n}\n\n#[test]\nfn verify_cli() {\n    cli().debug_assert();\n}\n"
  },
  {
    "path": "crates/xtask-lint-docs/Cargo.toml",
    "content": "[package]\nname = \"xtask-lint-docs\"\nversion = \"0.1.0\"\nedition.workspace = true\npublish = false\n\n[dependencies]\nanyhow.workspace = true\ncargo.workspace = true\nclap.workspace = true\nitertools.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/xtask-lint-docs/src/main.rs",
    "content": "use std::fmt::Write;\nuse std::path::PathBuf;\n\nuse cargo::lints::Lint;\nuse cargo::lints::LintLevel;\nuse cargo::util::command_prelude::{ArgMatchesExt, flag};\nuse itertools::Itertools;\n\nfn cli() -> clap::Command {\n    clap::Command::new(\"xtask-lint-docs\").arg(flag(\"check\", \"Check that the docs are up-to-date\"))\n}\n\nfn main() -> anyhow::Result<()> {\n    let args = cli().get_matches();\n    let check = args.flag(\"check\");\n\n    let mut allow = Vec::new();\n    let mut warn = Vec::new();\n    let mut deny = Vec::new();\n    let mut forbid = Vec::new();\n\n    let mut lint_docs = String::new();\n    for lint in cargo::lints::LINTS.iter().sorted_by_key(|lint| lint.name) {\n        if lint.docs.is_some() {\n            let sectipn = match lint.primary_group.default_level {\n                LintLevel::Allow => &mut allow,\n                LintLevel::Warn => &mut warn,\n                LintLevel::Deny => &mut deny,\n                LintLevel::Forbid => &mut forbid,\n            };\n            sectipn.push(lint.name);\n            add_lint(lint, &mut lint_docs)?;\n        }\n    }\n\n    let mut buf = String::new();\n    writeln!(buf, \"# Lints\\n\")?;\n    writeln!(\n        buf,\n        \"Note: [Cargo's linting system is unstable](unstable.md#lintscargo) and can only be used on nightly toolchains\"\n    )?;\n    writeln!(buf)?;\n\n    lint_groups(&mut buf)?;\n\n    if !allow.is_empty() {\n        add_level_section(LintLevel::Allow, &allow, &mut buf)?;\n    }\n    if !warn.is_empty() {\n        add_level_section(LintLevel::Warn, &warn, &mut buf)?;\n    }\n    if !deny.is_empty() {\n        add_level_section(LintLevel::Deny, &deny, &mut buf)?;\n    }\n    if !forbid.is_empty() {\n        add_level_section(LintLevel::Forbid, &forbid, &mut buf)?;\n    }\n\n    buf.push_str(&lint_docs);\n\n    if check {\n        let old = std::fs::read_to_string(lint_docs_path())?;\n        if old != buf {\n            anyhow::bail!(\n                \"The lints documentation is out-of-date. Run `cargo lint-docs` to update it.\"\n            );\n        }\n    } else {\n        std::fs::write(lint_docs_path(), buf)?;\n    }\n    Ok(())\n}\n\nfn lint_groups(buf: &mut String) -> anyhow::Result<()> {\n    let (max_name_len, max_desc_len) = cargo::lints::LINT_GROUPS.iter().filter(|g| !g.hidden).fold(\n        (0, 0),\n        |(max_name_len, max_desc_len), group| {\n            // We add 9 to account for the \"cargo::\" prefix and backticks\n            let name_len = group.name.chars().count() + 9;\n            let desc_len = group.desc.chars().count();\n            (max_name_len.max(name_len), max_desc_len.max(desc_len))\n        },\n    );\n    let default_level_len = \"Default level\".chars().count();\n    writeln!(buf, \"\\n\")?;\n    writeln!(\n        buf,\n        \"| {:<max_name_len$} | {:<max_desc_len$} | Default level |\",\n        \"Group\", \"Description\",\n    )?;\n    writeln!(\n        buf,\n        \"|-{}-|-{}-|-{}-|\",\n        \"-\".repeat(max_name_len),\n        \"-\".repeat(max_desc_len),\n        \"-\".repeat(default_level_len)\n    )?;\n    for group in cargo::lints::LINT_GROUPS.iter() {\n        if group.hidden {\n            continue;\n        }\n        let group_name = format!(\"`cargo::{}`\", group.name);\n        writeln!(\n            buf,\n            \"| {:<max_name_len$} | {:<max_desc_len$} | {:<default_level_len$} |\",\n            group_name,\n            group.desc,\n            group.default_level.to_string(),\n        )?;\n    }\n    writeln!(buf, \"\\n\")?;\n    Ok(())\n}\n\nfn add_lint(lint: &Lint, buf: &mut String) -> std::fmt::Result {\n    writeln!(buf, \"## `{}`\", lint.name)?;\n    writeln!(buf, \"Group: `{}`\", lint.primary_group.name)?;\n    writeln!(buf)?;\n    writeln!(buf, \"Level: `{}`\", lint.primary_group.default_level)?;\n    if let Some(msrv) = &lint.msrv {\n        writeln!(buf)?;\n        writeln!(buf, \"MSRV: `{msrv}`\")?;\n    }\n    writeln!(buf, \"{}\\n\", lint.docs.as_ref().unwrap())\n}\n\nfn add_level_section(level: LintLevel, lint_names: &[&str], buf: &mut String) -> std::fmt::Result {\n    let title = match level {\n        LintLevel::Allow => \"Allowed-by-default\",\n        LintLevel::Warn => \"Warn-by-default\",\n        LintLevel::Deny => \"Deny-by-default\",\n        LintLevel::Forbid => \"Forbid-by-default\",\n    };\n    writeln!(buf, \"## {title}\\n\")?;\n    writeln!(\n        buf,\n        \"These lints are all set to the '{}' level by default.\",\n        level\n    )?;\n\n    for name in lint_names {\n        writeln!(buf, \"- [`{}`](#{})\", name, name)?;\n    }\n    writeln!(buf)?;\n    Ok(())\n}\n\nfn lint_docs_path() -> PathBuf {\n    let pkg_root = env!(\"CARGO_MANIFEST_DIR\");\n    let ws_root = PathBuf::from(format!(\"{pkg_root}/../..\"));\n    let path = {\n        let path = ws_root.join(\"src/doc/src/reference/lints.md\");\n        path.canonicalize().unwrap_or(path)\n    };\n    path\n}\n"
  },
  {
    "path": "crates/xtask-spellcheck/Cargo.toml",
    "content": "[package]\nname = \"xtask-spellcheck\"\nversion = \"0.0.0\"\nedition.workspace = true\npublish = false\n\n[dependencies]\nanyhow.workspace = true\ncargo_metadata.workspace = true\ncargo-util.workspace = true\nclap.workspace = true\nsemver.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/xtask-spellcheck/src/main.rs",
    "content": "#![allow(clippy::disallowed_methods)]\n#![allow(clippy::print_stderr)]\n#![allow(clippy::print_stdout)]\n\nuse anyhow::Result;\nuse cargo_metadata::{Metadata, MetadataCommand};\nuse clap::{Arg, ArgAction};\nuse semver::Version;\nuse std::{\n    env, io,\n    path::{Path, PathBuf},\n    process::Command,\n};\n\nconst BIN_NAME: &str = \"typos\";\nconst PKG_NAME: &str = \"typos-cli\";\n\nfn main() -> anyhow::Result<()> {\n    let cli = cli();\n    exec(&cli.get_matches())?;\n    Ok(())\n}\n\npub fn cli() -> clap::Command {\n    clap::Command::new(\"xtask-spellcheck\")\n        .arg(\n            Arg::new(\"color\")\n                .long(\"color\")\n                .help(\"Coloring: auto, always, never\")\n                .action(ArgAction::Set)\n                .value_name(\"WHEN\")\n                .global(true),\n        )\n        .arg(\n            Arg::new(\"quiet\")\n                .long(\"quiet\")\n                .short('q')\n                .help(\"Do not print cargo log messages\")\n                .action(ArgAction::SetTrue)\n                .global(true),\n        )\n        .arg(\n            Arg::new(\"verbose\")\n                .long(\"verbose\")\n                .short('v')\n                .help(\"Use verbose output (-vv very verbose/build.rs output)\")\n                .action(ArgAction::Count)\n                .global(true),\n        )\n        .arg(\n            Arg::new(\"write-changes\")\n                .long(\"write-changes\")\n                .short('w')\n                .help(\"Write fixes out\")\n                .action(ArgAction::SetTrue)\n                .global(true),\n        )\n}\n\npub fn exec(matches: &clap::ArgMatches) -> Result<()> {\n    let mut args = vec![];\n\n    match matches.get_one::<String>(\"color\") {\n        Some(c) if matches!(c.as_str(), \"auto\" | \"always\" | \"never\") => {\n            args.push(\"--color\");\n            args.push(c);\n        }\n        Some(c) => {\n            anyhow::bail!(\n                \"argument for --color must be auto, always, or \\\n                 never, but found `{}`\",\n                c\n            );\n        }\n        _ => {}\n    }\n\n    if matches.get_flag(\"quiet\") {\n        args.push(\"--quiet\");\n    }\n\n    let verbose_count = matches.get_count(\"verbose\");\n\n    for _ in 0..verbose_count {\n        args.push(\"--verbose\");\n    }\n    if matches.get_flag(\"write-changes\") {\n        args.push(\"--write-changes\");\n    }\n\n    let metadata = MetadataCommand::new()\n        .exec()\n        .expect(\"cargo_metadata failed\");\n\n    let required_version = extract_workflow_typos_version(&metadata)?;\n\n    let outdir = metadata\n        .build_directory\n        .unwrap_or_else(|| metadata.target_directory)\n        .as_std_path()\n        .join(\"tmp\");\n    let workspace_root = metadata.workspace_root.as_path().as_std_path();\n    let bin_path = crate::ensure_version_or_cargo_install(&outdir, required_version)?;\n\n    eprintln!(\"running {BIN_NAME}\");\n    Command::new(bin_path)\n        .current_dir(workspace_root)\n        .args(args)\n        .status()?;\n\n    Ok(())\n}\n\nfn extract_workflow_typos_version(metadata: &Metadata) -> anyhow::Result<Version> {\n    let ws_root = metadata.workspace_root.as_path().as_std_path();\n    let workflow_path = ws_root.join(\".github\").join(\"workflows\").join(\"main.yml\");\n    let file_content = std::fs::read_to_string(workflow_path)?;\n\n    extract_typos_version_from_content(&file_content)\n}\n\nfn extract_typos_version_from_content(file_content: &str) -> anyhow::Result<Version> {\n    file_content\n        .lines()\n        .find_map(|line| {\n            line.trim()\n                .strip_prefix(\"uses: crate-ci/typos@v\")\n                .and_then(|v| Version::parse(v).ok())\n        })\n        .ok_or_else(|| anyhow::anyhow!(\"Could not find typos version in workflow\"))\n}\n\n/// If the given executable is installed with the given version, use that,\n/// otherwise install via cargo.\npub fn ensure_version_or_cargo_install(\n    build_dir: &Path,\n    required_version: Version,\n) -> io::Result<PathBuf> {\n    // Check if the user has a sufficient version already installed\n    let bin_path = PathBuf::from(BIN_NAME).with_extension(env::consts::EXE_EXTENSION);\n    if let Some(user_version) = get_typos_version(&bin_path) {\n        if user_version >= required_version {\n            return Ok(bin_path);\n        }\n    }\n\n    let tool_root_dir = build_dir.join(\"misc-tools\");\n    let tool_bin_dir = tool_root_dir.join(\"bin\");\n    let bin_path = tool_bin_dir\n        .join(BIN_NAME)\n        .with_extension(env::consts::EXE_EXTENSION);\n\n    // Check if we have already installed sufficient version\n    if let Some(misc_tools_version) = get_typos_version(&bin_path) {\n        if misc_tools_version >= required_version {\n            return Ok(bin_path);\n        }\n    }\n\n    eprintln!(\"required `typos` version ({required_version}) not found, building from source\");\n\n    let mut cmd = Command::new(\"cargo\");\n    // use --force to ensure that if the required version is bumped, we update it.\n    cmd.args([\"install\", \"--locked\", \"--force\", \"--quiet\"])\n        .arg(\"--root\")\n        .arg(&tool_root_dir)\n        // use --target-dir to ensure we have a build cache so repeated invocations aren't slow.\n        .arg(\"--target-dir\")\n        .arg(tool_root_dir.join(\"target\"))\n        .arg(format!(\"{PKG_NAME}@{required_version}\"))\n        // modify PATH so that cargo doesn't print a warning telling the user to modify the path.\n        .env(\n            \"PATH\",\n            env::join_paths(\n                env::split_paths(&env::var(\"PATH\").unwrap())\n                    .chain(std::iter::once(tool_bin_dir.clone())),\n            )\n            .expect(\"build dir contains invalid char\"),\n        );\n\n    let cargo_exit_code = cmd.spawn()?.wait()?;\n    if !cargo_exit_code.success() {\n        return Err(io::Error::other(\"cargo install failed\"));\n    }\n    assert!(\n        matches!(bin_path.try_exists(), Ok(true)),\n        \"cargo install did not produce the expected binary\"\n    );\n    eprintln!(\"finished {BIN_NAME}\");\n    Ok(bin_path)\n}\n\nfn get_typos_version(bin: &PathBuf) -> Option<Version> {\n    // ignore the process exit code here and instead just let the version number check fail\n    if let Ok(output) = Command::new(&bin).arg(\"--version\").output()\n        && let Ok(s) = String::from_utf8(output.stdout)\n        && let Some(version_str) = s.trim().split_whitespace().last()\n    {\n        Version::parse(version_str).ok()\n    } else {\n        None\n    }\n}\n"
  },
  {
    "path": "crates/xtask-stale-label/Cargo.toml",
    "content": "[package]\nname = \"xtask-stale-label\"\nversion = \"0.0.0\"\nedition.workspace = true\npublish = false\n\n[dependencies]\ntoml_edit.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "crates/xtask-stale-label/src/main.rs",
    "content": "//! ```text\n//! NAME\n//!         stale-label\n//!\n//! SYNOPSIS\n//!         stale-label\n//!\n//! DESCRIPTION\n//!         Detect stale paths in autolabel definitions in triagebot.toml.\n//!         Probably autofix them in the future.\n//! ```\n\n#![allow(clippy::print_stderr)]\n\nuse std::fmt::Write as _;\nuse std::path::PathBuf;\nuse std::process;\nuse toml_edit::DocumentMut;\n\nfn main() {\n    let pkg_root = std::env!(\"CARGO_MANIFEST_DIR\");\n    let ws_root = PathBuf::from(format!(\"{pkg_root}/../..\"));\n    let path = {\n        let path = ws_root.join(\"triagebot.toml\");\n        path.canonicalize().unwrap_or(path)\n    };\n\n    eprintln!(\"Checking file {path:?}\\n\");\n\n    let mut failed = 0;\n    let mut passed = 0;\n\n    let toml = std::fs::read_to_string(path).expect(\"read from file\");\n    let doc = toml.parse::<DocumentMut>().expect(\"a toml\");\n    let autolabel = doc[\"autolabel\"].as_table().expect(\"a toml table\");\n\n    for (label, value) in autolabel.iter() {\n        let Some(trigger_files) = value.get(\"trigger_files\") else {\n            continue;\n        };\n        let trigger_files = trigger_files.as_array().expect(\"an array\");\n        let missing_files: Vec<_> = trigger_files\n            .iter()\n            // Hey TOML content is strict UTF-8.\n            .map(|v| v.as_str().unwrap())\n            .filter(|f| {\n                // triagebot checks with `starts_with` only.\n                // See https://github.com/rust-lang/triagebot/blob/0e4b48ca86ffede9cc70fb1611e658e4d013bce2/src/handlers/autolabel.rs#L45\n                let path = ws_root.join(f);\n                if path.exists() {\n                    return false;\n                }\n                let Some(mut read_dir) = path.parent().and_then(|p| p.read_dir().ok()) else {\n                    return true;\n                };\n                !read_dir.any(|e| {\n                    e.unwrap()\n                        .path()\n                        .strip_prefix(&ws_root)\n                        .unwrap()\n                        .to_str()\n                        .unwrap()\n                        .starts_with(f)\n                })\n            })\n            .collect();\n\n        failed += missing_files.len();\n        passed += trigger_files.len() - missing_files.len();\n\n        if missing_files.is_empty() {\n            continue;\n        }\n\n        let mut msg = String::new();\n        writeln!(\n            &mut msg,\n            \"missing files defined in `autolabel.{label}.trigger_files`:\"\n        )\n        .unwrap();\n        for f in missing_files.iter() {\n            writeln!(&mut msg, \"\\t {f}\").unwrap();\n        }\n        eprintln!(\"{msg}\");\n    }\n\n    let result = if failed == 0 { \"ok\" } else { \"FAILED\" };\n    eprintln!(\"test result: {result}. {passed} passed; {failed} failed;\");\n\n    if failed > 0 {\n        process::exit(1);\n    }\n}\n"
  },
  {
    "path": "credential/README.md",
    "content": "# Cargo Credential Packages\n\nThis directory contains Cargo packages for handling storage of tokens in a\nsecure manner.\n\n`cargo-credential` is a generic library to assist writing a credential\nprocess. The other directories contain implementations that integrate with\nspecific credential systems.\n"
  },
  {
    "path": "credential/cargo-credential/Cargo.toml",
    "content": "[package]\nname = \"cargo-credential\"\nversion = \"0.4.10\"\nrust-version.workspace = true\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"A library to assist writing Cargo credential helpers.\"\n\n[dependencies]\nanyhow.workspace = true\nserde = { workspace = true, features = [\"derive\"] }\nserde_json.workspace = true\nthiserror.workspace = true\ntime.workspace = true\n\n[target.'cfg(unix)'.dependencies]\nlibc.workspace = true\n\n[target.'cfg(windows)'.dependencies]\nwindows-sys = { workspace = true, features = [\"Win32_System_Console\", \"Win32_Foundation\"] }\n\n[dev-dependencies]\nsnapbox = { workspace = true, features = [\"examples\"] }\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "credential/cargo-credential/README.md",
    "content": "# cargo-credential\n\nThis package is a library to assist writing a Cargo credential helper, which\nprovides an interface to store tokens for authorizing access to a registry\nsuch as https://crates.io/.\n\nDocumentation about credential processes may be found at\nhttps://doc.rust-lang.org/nightly/cargo/reference/credential-provider-protocol.html\n\nExample implementations may be found at\nhttps://github.com/rust-lang/cargo/tree/master/credential\n\n> This crate is maintained by the Cargo team for use by the wider\n> ecosystem. This crate follows semver compatibility for its APIs.\n\n## Usage\n\nCreate a Cargo project with this as a dependency:\n\n```toml\n# Add this to your Cargo.toml:\n\n[dependencies]\ncargo-credential = \"0.4\"\n```\n\nAnd then include a `main.rs` binary which implements the `Credential` trait, and calls\nthe `main` function which will call the appropriate method of the trait:\n\n```rust\n// src/main.rs\n\nuse cargo_credential::{Credential, Error};\n\nstruct MyCredential;\n\nimpl Credential for MyCredential {\n    /// implement trait methods here...\n}\n\nfn main() {\n    cargo_credential::main(MyCredential);\n}\n```\n"
  },
  {
    "path": "credential/cargo-credential/examples/file-provider.rs",
    "content": "//! Example credential provider that stores credentials in a JSON file.\n//! This is not secure\n\nuse cargo_credential::{\n    Action, CacheControl, Credential, CredentialResponse, RegistryInfo, Secret,\n};\nuse std::{collections::HashMap, fs::File, io::ErrorKind};\ntype Error = Box<dyn std::error::Error + Send + Sync + 'static>;\n\nstruct FileCredential;\n\nimpl Credential for FileCredential {\n    fn perform(\n        &self,\n        registry: &RegistryInfo<'_>,\n        action: &Action<'_>,\n        _args: &[&str],\n    ) -> Result<CredentialResponse, cargo_credential::Error> {\n        if registry.index_url != \"https://github.com/rust-lang/crates.io-index\" {\n            // Restrict this provider to only work for crates.io. Cargo will skip it and attempt\n            // another provider for any other registry.\n            //\n            // If a provider supports any registry, then this check should be omitted.\n            return Err(cargo_credential::Error::UrlNotSupported);\n        }\n\n        // `Error::Other` takes a boxed `std::error::Error` type that causes Cargo to show the error.\n        let mut creds = FileCredential::read().map_err(cargo_credential::Error::Other)?;\n\n        match action {\n            Action::Get(_) => {\n                // Cargo requested a token, look it up.\n                if let Some(token) = creds.get(registry.index_url) {\n                    Ok(CredentialResponse::Get {\n                        token: token.clone(),\n                        cache: CacheControl::Session,\n                        operation_independent: true,\n                    })\n                } else {\n                    // Credential providers should respond with `NotFound` when a credential can not be\n                    // found, allowing Cargo to attempt another provider.\n                    Err(cargo_credential::Error::NotFound)\n                }\n            }\n            Action::Login(login_options) => {\n                // The token for `cargo login` can come from the `login_options` parameter or i\n                // interactively reading from stdin.\n                //\n                // `cargo_credential::read_token` automatically handles this.\n                let token = cargo_credential::read_token(login_options, registry)?;\n                creds.insert(registry.index_url.to_string(), token);\n\n                FileCredential::write(&creds).map_err(cargo_credential::Error::Other)?;\n\n                // Credentials were successfully stored.\n                Ok(CredentialResponse::Login)\n            }\n            Action::Logout => {\n                if creds.remove(registry.index_url).is_none() {\n                    // If the user attempts to log out from a registry that has no credentials\n                    // stored, then NotFound is the appropriate error.\n                    Err(cargo_credential::Error::NotFound)\n                } else {\n                    // Credentials were successfully erased.\n                    Ok(CredentialResponse::Logout)\n                }\n            }\n            // If a credential provider doesn't support a given operation, it should respond with `OperationNotSupported`.\n            _ => Err(cargo_credential::Error::OperationNotSupported),\n        }\n    }\n}\n\nimpl FileCredential {\n    fn read() -> Result<HashMap<String, Secret<String>>, Error> {\n        match File::open(\"cargo-credentials.json\") {\n            Ok(f) => Ok(serde_json::from_reader(f)?),\n            Err(e) if e.kind() == ErrorKind::NotFound => Ok(HashMap::new()),\n            Err(e) => Err(e)?,\n        }\n    }\n    fn write(value: &HashMap<String, Secret<String>>) -> Result<(), Error> {\n        let file = File::create(\"cargo-credentials.json\")?;\n        Ok(serde_json::to_writer_pretty(file, value)?)\n    }\n}\n\nfn main() {\n    cargo_credential::main(FileCredential);\n}\n"
  },
  {
    "path": "credential/cargo-credential/examples/stdout-redirected.rs",
    "content": "//! Provider used for testing redirection of stdout.\n\n#![allow(clippy::print_stderr)]\n#![allow(clippy::print_stdout)]\n\nuse cargo_credential::{Action, Credential, CredentialResponse, Error, RegistryInfo};\n\nstruct MyCredential;\n\nimpl Credential for MyCredential {\n    fn perform(\n        &self,\n        _registry: &RegistryInfo<'_>,\n        _action: &Action<'_>,\n        _args: &[&str],\n    ) -> Result<CredentialResponse, Error> {\n        // Informational messages should be sent on stderr.\n        eprintln!(\"message on stderr should be sent to the parent process\");\n\n        // Reading from stdin and writing to stdout will go to the attached console (tty).\n        println!(\"message from test credential provider\");\n        Err(Error::OperationNotSupported)\n    }\n}\n\nfn main() {\n    cargo_credential::main(MyCredential);\n}\n"
  },
  {
    "path": "credential/cargo-credential/src/error.rs",
    "content": "use serde::{Deserialize, Serialize};\nuse std::error::Error as StdError;\nuse thiserror::Error as ThisError;\n\n/// Credential provider error type.\n///\n/// `UrlNotSupported` and `NotFound` errors both cause Cargo\n/// to attempt another provider, if one is available. The other\n/// variants are fatal.\n///\n/// Note: Do not add a tuple variant, as it cannot be serialized.\n#[derive(Serialize, Deserialize, ThisError, Debug)]\n#[serde(rename_all = \"kebab-case\", tag = \"kind\")]\n#[non_exhaustive]\npub enum Error {\n    /// Registry URL is not supported. This should be used if\n    /// the provider only works for some registries. Cargo will\n    /// try another provider, if available\n    #[error(\"registry not supported\")]\n    UrlNotSupported,\n\n    /// Credentials could not be found. Cargo will try another\n    /// provider, if available\n    #[error(\"credential not found\")]\n    NotFound,\n\n    /// The provider doesn't support this operation, such as\n    /// a provider that can't support 'login' / 'logout'\n    #[error(\"requested operation not supported\")]\n    OperationNotSupported,\n\n    /// The provider failed to perform the operation. Other\n    /// providers will not be attempted\n    #[error(transparent)]\n    #[serde(with = \"error_serialize\")]\n    Other(Box<dyn StdError + Sync + Send>),\n\n    /// A new variant was added to this enum since Cargo was built\n    #[error(\"unknown error kind; try updating Cargo?\")]\n    #[serde(other)]\n    Unknown,\n}\n\nimpl From<String> for Error {\n    fn from(message: String) -> Self {\n        Box::new(StringTypedError {\n            message,\n            source: None,\n        })\n        .into()\n    }\n}\n\nimpl From<&str> for Error {\n    fn from(err: &str) -> Self {\n        err.to_string().into()\n    }\n}\n\nimpl From<anyhow::Error> for Error {\n    fn from(value: anyhow::Error) -> Self {\n        let mut prev = None;\n        for e in value.chain().rev() {\n            prev = Some(Box::new(StringTypedError {\n                message: e.to_string(),\n                source: prev,\n            }));\n        }\n        Error::Other(prev.unwrap())\n    }\n}\n\nimpl<T: StdError + Send + Sync + 'static> From<Box<T>> for Error {\n    fn from(value: Box<T>) -> Self {\n        Error::Other(value)\n    }\n}\n\n/// String-based error type with an optional source\n#[derive(Debug)]\nstruct StringTypedError {\n    message: String,\n    source: Option<Box<StringTypedError>>,\n}\n\nimpl StdError for StringTypedError {\n    fn source(&self) -> Option<&(dyn StdError + 'static)> {\n        self.source.as_ref().map(|err| err as &dyn StdError)\n    }\n}\n\nimpl std::fmt::Display for StringTypedError {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.message.fmt(f)\n    }\n}\n\n/// Serializer / deserializer for any boxed error.\n/// The string representation of the error, and its `source` chain can roundtrip across\n/// the serialization. The actual types are lost (downcast will not work).\nmod error_serialize {\n    use std::error::Error as StdError;\n    use std::ops::Deref;\n\n    use serde::{Deserialize, Deserializer, Serializer, ser::SerializeStruct};\n\n    use crate::error::StringTypedError;\n\n    pub fn serialize<S>(\n        e: &Box<dyn StdError + Send + Sync>,\n        serializer: S,\n    ) -> Result<S::Ok, S::Error>\n    where\n        S: Serializer,\n    {\n        let mut state = serializer.serialize_struct(\"StringTypedError\", 2)?;\n        state.serialize_field(\"message\", &format!(\"{}\", e))?;\n\n        // Serialize the source error chain recursively\n        let mut current_source: &dyn StdError = e.deref();\n        let mut sources = Vec::new();\n        while let Some(err) = current_source.source() {\n            sources.push(err.to_string());\n            current_source = err;\n        }\n        state.serialize_field(\"caused-by\", &sources)?;\n        state.end()\n    }\n\n    pub fn deserialize<'de, D>(deserializer: D) -> Result<Box<dyn StdError + Sync + Send>, D::Error>\n    where\n        D: Deserializer<'de>,\n    {\n        #[derive(Deserialize)]\n        #[serde(rename_all = \"kebab-case\")]\n        struct ErrorData {\n            message: String,\n            caused_by: Option<Vec<String>>,\n        }\n        let data = ErrorData::deserialize(deserializer)?;\n        let mut prev = None;\n        if let Some(source) = data.caused_by {\n            for e in source.into_iter().rev() {\n                prev = Some(Box::new(StringTypedError {\n                    message: e,\n                    source: prev,\n                }));\n            }\n        }\n        let e = Box::new(StringTypedError {\n            message: data.message,\n            source: prev,\n        });\n        Ok(e)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::Error;\n\n    #[test]\n    pub fn unknown_kind() {\n        let json = r#\"{\n            \"kind\": \"unexpected-kind\",\n            \"unexpected-content\": \"test\"\n          }\"#;\n        let e: Error = serde_json::from_str(&json).unwrap();\n        assert!(matches!(e, Error::Unknown));\n    }\n\n    #[test]\n    pub fn roundtrip() {\n        // Construct an error with context\n        let e = anyhow::anyhow!(\"E1\").context(\"E2\").context(\"E3\");\n        // Convert to a string with contexts.\n        let s1 = format!(\"{:?}\", e);\n        // Convert the error into an `Error`\n        let e: Error = e.into();\n        // Convert that error into JSON\n        let json = serde_json::to_string_pretty(&e).unwrap();\n        // Convert that error back to anyhow\n        let e: anyhow::Error = e.into();\n        let s2 = format!(\"{:?}\", e);\n        assert_eq!(s1, s2);\n\n        // Convert the error back from JSON\n        let e: Error = serde_json::from_str(&json).unwrap();\n        // Convert to back to anyhow\n        let e: anyhow::Error = e.into();\n        let s3 = format!(\"{:?}\", e);\n        assert_eq!(s2, s3);\n\n        assert_eq!(\n            r#\"{\n  \"kind\": \"other\",\n  \"message\": \"E3\",\n  \"caused-by\": [\n    \"E2\",\n    \"E1\"\n  ]\n}\"#,\n            json\n        );\n    }\n}\n"
  },
  {
    "path": "credential/cargo-credential/src/lib.rs",
    "content": "//! Helper library for writing Cargo credential providers.\n//!\n//! A credential process should have a `struct` that implements the `Credential` trait.\n//! The `main` function should be called with an instance of that struct, such as:\n//!\n//! ```rust,ignore\n//! fn main() {\n//!     cargo_credential::main(MyCredential);\n//! }\n//! ```\n//!\n//! While in the `perform` function, stdin and stdout will be re-attached to the\n//! active console. This allows credential providers to be interactive if necessary.\n//!\n//! > This crate is maintained by the Cargo team for use by the wider\n//! > ecosystem. This crate follows semver compatibility for its APIs.\n//!\n//! ## Error handling\n//! ### [`Error::UrlNotSupported`]\n//! A credential provider may only support some registry URLs. If this is the case\n//! and an unsupported index URL is passed to the provider, it should respond with\n//! [`Error::UrlNotSupported`]. Other credential providers may be attempted by Cargo.\n//!\n//! ### [`Error::NotFound`]\n//! When attempting an [`Action::Get`] or [`Action::Logout`], if a credential can not\n//! be found, the provider should respond with [`Error::NotFound`]. Other credential\n//! providers may be attempted by Cargo.\n//!\n//! ### [`Error::OperationNotSupported`]\n//! A credential provider might not support all operations. For example if the provider\n//! only supports [`Action::Get`], [`Error::OperationNotSupported`] should be returned\n//! for all other requests.\n//!\n//! ### [`Error::Other`]\n//! All other errors go here. The error will be shown to the user in Cargo, including\n//! the full error chain using [`std::error::Error::source`].\n//!\n//! ## Example\n//! ```rust,ignore\n#![doc = include_str!(\"../examples/file-provider.rs\")]\n//! ```\n\n#![allow(clippy::print_stderr)]\n#![allow(clippy::print_stdout)]\n\nuse serde::{Deserialize, Serialize};\nuse std::{fmt::Display, io};\nuse time::OffsetDateTime;\n\nmod error;\nmod secret;\nmod stdio;\n\npub use error::Error;\npub use secret::Secret;\nuse stdio::stdin_stdout_to_console;\n\n/// Message sent by the credential helper on startup\n#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]\npub struct CredentialHello {\n    // Protocol versions supported by the credential process.\n    pub v: Vec<u32>,\n}\n\n/// Credential provider that doesn't support any registries.\npub struct UnsupportedCredential;\nimpl Credential for UnsupportedCredential {\n    fn perform(\n        &self,\n        _registry: &RegistryInfo<'_>,\n        _action: &Action<'_>,\n        _args: &[&str],\n    ) -> Result<CredentialResponse, Error> {\n        Err(Error::UrlNotSupported)\n    }\n}\n\n/// Message sent by Cargo to the credential helper after the hello\n#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]\n#[serde(rename_all = \"kebab-case\")]\npub struct CredentialRequest<'a> {\n    // Cargo will respond with the highest common protocol supported by both.\n    pub v: u32,\n    #[serde(borrow)]\n    pub registry: RegistryInfo<'a>,\n    #[serde(borrow, flatten)]\n    pub action: Action<'a>,\n    /// Additional command-line arguments passed to the credential provider.\n    #[serde(skip_serializing_if = \"Vec::is_empty\", default)]\n    pub args: Vec<&'a str>,\n}\n\n#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]\n#[serde(rename_all = \"kebab-case\")]\npub struct RegistryInfo<'a> {\n    /// Registry index url\n    pub index_url: &'a str,\n    /// Name of the registry in configuration. May not be available.\n    /// The crates.io registry will be `crates-io` (`CRATES_IO_REGISTRY`).\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    pub name: Option<&'a str>,\n    /// Headers from attempting to access a registry that resulted in a HTTP 401.\n    #[serde(skip_serializing_if = \"Vec::is_empty\", default)]\n    pub headers: Vec<String>,\n}\n\n#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]\n#[non_exhaustive]\n#[serde(tag = \"kind\", rename_all = \"kebab-case\")]\npub enum Action<'a> {\n    #[serde(borrow)]\n    Get(Operation<'a>),\n    Login(LoginOptions<'a>),\n    Logout,\n    #[serde(other)]\n    Unknown,\n}\n\nimpl<'a> Display for Action<'a> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            Action::Get(_) => f.write_str(\"get\"),\n            Action::Login(_) => f.write_str(\"login\"),\n            Action::Logout => f.write_str(\"logout\"),\n            Action::Unknown => f.write_str(\"<unknown>\"),\n        }\n    }\n}\n\n#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]\n#[serde(rename_all = \"kebab-case\")]\npub struct LoginOptions<'a> {\n    /// Token passed on the command line via --token or from stdin\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    pub token: Option<Secret<&'a str>>,\n    /// Optional URL that the user can visit to log in to the registry\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    pub login_url: Option<&'a str>,\n}\n\n/// A record of what kind of operation is happening that we should generate a token for.\n#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]\n#[non_exhaustive]\n#[serde(tag = \"operation\", rename_all = \"kebab-case\")]\npub enum Operation<'a> {\n    /// The user is attempting to fetch a crate.\n    Read,\n    /// The user is attempting to publish a crate.\n    Publish {\n        /// The name of the crate\n        name: &'a str,\n        /// The version of the crate\n        vers: &'a str,\n        /// The checksum of the crate file being uploaded\n        cksum: &'a str,\n    },\n    /// The user is attempting to yank a crate.\n    Yank {\n        /// The name of the crate\n        name: &'a str,\n        /// The version of the crate\n        vers: &'a str,\n    },\n    /// The user is attempting to unyank a crate.\n    Unyank {\n        /// The name of the crate\n        name: &'a str,\n        /// The version of the crate\n        vers: &'a str,\n    },\n    /// The user is attempting to modify the owners of a crate.\n    Owners {\n        /// The name of the crate\n        name: &'a str,\n    },\n    #[serde(other)]\n    Unknown,\n}\n\n/// Message sent by the credential helper\n#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]\n#[serde(tag = \"kind\", rename_all = \"kebab-case\")]\n#[non_exhaustive]\npub enum CredentialResponse {\n    Get {\n        token: Secret<String>,\n        #[serde(flatten)]\n        cache: CacheControl,\n        operation_independent: bool,\n    },\n    Login,\n    Logout,\n    #[serde(other)]\n    Unknown,\n}\n\n#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]\n#[serde(tag = \"cache\", rename_all = \"kebab-case\")]\n#[non_exhaustive]\npub enum CacheControl {\n    /// Do not cache this result.\n    Never,\n    /// Cache this result and use it for subsequent requests in the current Cargo invocation until the specified time.\n    Expires {\n        #[serde(with = \"time::serde::timestamp\")]\n        expiration: OffsetDateTime,\n    },\n    /// Cache this result and use it for all subsequent requests in the current Cargo invocation.\n    Session,\n    #[serde(other)]\n    Unknown,\n}\n\n/// Credential process JSON protocol version.\n///\n/// If the protocol needs to make\n/// a breaking change, a new protocol version should be defined (`PROTOCOL_VERSION_2`).\n/// This library should offer support for both protocols if possible, by signaling\n/// in the `CredentialHello` message. Cargo will then choose which protocol to use,\n/// or it will error if there are no common protocol versions available.\npub const PROTOCOL_VERSION_1: u32 = 1;\npub trait Credential {\n    /// Retrieves a token for the given registry.\n    fn perform(\n        &self,\n        registry: &RegistryInfo<'_>,\n        action: &Action<'_>,\n        args: &[&str],\n    ) -> Result<CredentialResponse, Error>;\n}\n\n/// Runs the credential interaction\npub fn main(credential: impl Credential) {\n    let result = doit(credential).map_err(|e| Error::Other(e));\n    if result.is_err() {\n        serde_json::to_writer(std::io::stdout(), &result)\n            .expect(\"failed to serialize credential provider error\");\n        println!();\n    }\n}\n\nfn doit(\n    credential: impl Credential,\n) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {\n    let hello = CredentialHello {\n        v: vec![PROTOCOL_VERSION_1],\n    };\n    serde_json::to_writer(std::io::stdout(), &hello)?;\n    println!();\n\n    loop {\n        let mut buffer = String::new();\n        let len = std::io::stdin().read_line(&mut buffer)?;\n        if len == 0 {\n            return Ok(());\n        }\n        let request = deserialize_request(&buffer)?;\n        let response = stdin_stdout_to_console(|| {\n            credential.perform(&request.registry, &request.action, &request.args)\n        })?;\n\n        serde_json::to_writer(std::io::stdout(), &response)?;\n        println!();\n    }\n}\n\n/// Deserialize a request from Cargo.\nfn deserialize_request(\n    value: &str,\n) -> Result<CredentialRequest<'_>, Box<dyn std::error::Error + Send + Sync>> {\n    let request: CredentialRequest<'_> = serde_json::from_str(&value)?;\n    if request.v != PROTOCOL_VERSION_1 {\n        return Err(format!(\"unsupported protocol version {}\", request.v).into());\n    }\n    Ok(request)\n}\n\n/// Read a line of text from stdin.\npub fn read_line() -> Result<String, io::Error> {\n    let mut buf = String::new();\n    io::stdin().read_line(&mut buf)?;\n    Ok(buf.trim().to_string())\n}\n\n/// Prompt the user for a token.\npub fn read_token(\n    login_options: &LoginOptions<'_>,\n    registry: &RegistryInfo<'_>,\n) -> Result<Secret<String>, Error> {\n    if let Some(token) = &login_options.token {\n        return Ok(token.to_owned());\n    }\n\n    if let Some(url) = login_options.login_url {\n        eprintln!(\"please paste the token found on {url} below\");\n    } else if let Some(name) = registry.name {\n        eprintln!(\"please paste the token for {name} below\");\n    } else {\n        eprintln!(\"please paste the token for {} below\", registry.index_url);\n    }\n\n    Ok(Secret::from(read_line().map_err(Box::new)?))\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn unsupported_version() {\n        // This shouldn't ever happen in practice, since the credential provider signals to Cargo which\n        // protocol versions it supports, and Cargo should only attempt to use one of those.\n        let msg = r#\"{\"v\":999, \"registry\": {\"index-url\":\"\"}, \"args\":[], \"kind\": \"unexpected\"}\"#;\n        assert_eq!(\n            \"unsupported protocol version 999\",\n            deserialize_request(msg).unwrap_err().to_string()\n        );\n    }\n\n    #[test]\n    fn cache_control() {\n        let cc = CacheControl::Expires {\n            expiration: OffsetDateTime::from_unix_timestamp(1693928537).unwrap(),\n        };\n        let json = serde_json::to_string(&cc).unwrap();\n        assert_eq!(json, r#\"{\"cache\":\"expires\",\"expiration\":1693928537}\"#);\n\n        let cc = CacheControl::Session;\n        let json = serde_json::to_string(&cc).unwrap();\n        assert_eq!(json, r#\"{\"cache\":\"session\"}\"#);\n\n        let cc: CacheControl = serde_json::from_str(r#\"{\"cache\":\"unknown-kind\"}\"#).unwrap();\n        assert_eq!(cc, CacheControl::Unknown);\n\n        assert_eq!(\n            \"missing field `expiration`\",\n            serde_json::from_str::<CacheControl>(r#\"{\"cache\":\"expires\"}\"#)\n                .unwrap_err()\n                .to_string()\n        );\n    }\n\n    #[test]\n    fn credential_response() {\n        let cr = CredentialResponse::Get {\n            cache: CacheControl::Never,\n            operation_independent: true,\n            token: Secret::from(\"value\".to_string()),\n        };\n        let json = serde_json::to_string(&cr).unwrap();\n        assert_eq!(\n            json,\n            r#\"{\"kind\":\"get\",\"token\":\"value\",\"cache\":\"never\",\"operation_independent\":true}\"#\n        );\n\n        let cr = CredentialResponse::Login;\n        let json = serde_json::to_string(&cr).unwrap();\n        assert_eq!(json, r#\"{\"kind\":\"login\"}\"#);\n\n        let cr: CredentialResponse =\n            serde_json::from_str(r#\"{\"kind\":\"unknown-kind\",\"extra-data\":true}\"#).unwrap();\n        assert_eq!(cr, CredentialResponse::Unknown);\n\n        let cr: CredentialResponse =\n            serde_json::from_str(r#\"{\"kind\":\"login\",\"extra-data\":true}\"#).unwrap();\n        assert_eq!(cr, CredentialResponse::Login);\n\n        let cr: CredentialResponse = serde_json::from_str(r#\"{\"kind\":\"get\",\"token\":\"value\",\"cache\":\"never\",\"operation_independent\":true,\"extra-field-ignored\":123}\"#).unwrap();\n        assert_eq!(\n            cr,\n            CredentialResponse::Get {\n                cache: CacheControl::Never,\n                operation_independent: true,\n                token: Secret::from(\"value\".to_string())\n            }\n        );\n    }\n\n    #[test]\n    fn credential_request() {\n        let get_oweners = CredentialRequest {\n            v: PROTOCOL_VERSION_1,\n            args: vec![],\n            registry: RegistryInfo {\n                index_url: \"url\",\n                name: None,\n                headers: vec![],\n            },\n            action: Action::Get(Operation::Owners { name: \"pkg\" }),\n        };\n\n        let json = serde_json::to_string(&get_oweners).unwrap();\n        assert_eq!(\n            json,\n            r#\"{\"v\":1,\"registry\":{\"index-url\":\"url\"},\"kind\":\"get\",\"operation\":\"owners\",\"name\":\"pkg\"}\"#\n        );\n\n        let cr: CredentialRequest<'_> =\n            serde_json::from_str(r#\"{\"extra-1\":true,\"v\":1,\"registry\":{\"index-url\":\"url\",\"extra-2\":true},\"kind\":\"get\",\"operation\":\"owners\",\"name\":\"pkg\",\"args\":[]}\"#).unwrap();\n        assert_eq!(cr, get_oweners);\n    }\n\n    #[test]\n    fn credential_request_logout() {\n        let unknown = CredentialRequest {\n            v: PROTOCOL_VERSION_1,\n            args: vec![],\n            registry: RegistryInfo {\n                index_url: \"url\",\n                name: None,\n                headers: vec![],\n            },\n            action: Action::Logout,\n        };\n\n        let cr: CredentialRequest<'_> = serde_json::from_str(\n            r#\"{\"v\":1,\"registry\":{\"index-url\":\"url\"},\"kind\":\"logout\",\"extra-1\":true,\"args\":[]}\"#,\n        )\n        .unwrap();\n        assert_eq!(cr, unknown);\n    }\n\n    #[test]\n    fn credential_request_unknown() {\n        let unknown = CredentialRequest {\n            v: PROTOCOL_VERSION_1,\n            args: vec![],\n            registry: RegistryInfo {\n                index_url: \"\",\n                name: None,\n                headers: vec![],\n            },\n            action: Action::Unknown,\n        };\n\n        let cr: CredentialRequest<'_> = serde_json::from_str(\n            r#\"{\"v\":1,\"registry\":{\"index-url\":\"\"},\"kind\":\"unexpected-1\",\"extra-1\":true,\"args\":[]}\"#,\n        )\n        .unwrap();\n        assert_eq!(cr, unknown);\n    }\n}\n"
  },
  {
    "path": "credential/cargo-credential/src/secret.rs",
    "content": "use std::fmt;\nuse std::ops::Deref;\n\nuse serde::{Deserialize, Serialize};\n\n/// A wrapper for values that should not be printed.\n///\n/// This type does not implement `Display`, and has a `Debug` impl that hides\n/// the contained value.\n///\n/// ```\n/// # use cargo_credential::Secret;\n/// let token = Secret::from(\"super secret string\");\n/// assert_eq!(format!(\"{:?}\", token), \"Secret { inner: \\\"REDACTED\\\" }\");\n/// ```\n///\n/// Currently, we write a borrowed `Secret<T>` as `Secret<&T>`.\n/// The [`as_deref`](Secret::as_deref) and [`to_owned`](Secret::to_owned) methods can\n/// be used to convert back and forth between `Secret<String>` and `Secret<&str>`.\n#[derive(Default, Clone, PartialEq, Eq, Serialize, Deserialize)]\n#[serde(transparent)]\npub struct Secret<T> {\n    inner: T,\n}\n\nimpl<T> Secret<T> {\n    /// Unwraps the contained value.\n    ///\n    /// Use of this method marks the boundary of where the contained value is\n    /// hidden.\n    pub fn expose(self) -> T {\n        self.inner\n    }\n\n    /// Converts a `Secret<T>` to a `Secret<&T::Target>`.\n    /// ```\n    /// # use cargo_credential::Secret;\n    /// let owned: Secret<String> = Secret::from(String::from(\"token\"));\n    /// let borrowed: Secret<&str> = owned.as_deref();\n    /// ```\n    pub fn as_deref(&self) -> Secret<&<T as Deref>::Target>\n    where\n        T: Deref,\n    {\n        Secret::from(self.inner.deref())\n    }\n\n    /// Converts a `Secret<T>` to a `Secret<&T>`.\n    pub fn as_ref(&self) -> Secret<&T> {\n        Secret::from(&self.inner)\n    }\n\n    /// Converts a `Secret<T>` to a `Secret<U>` by applying `f` to the contained value.\n    pub fn map<U, F>(self, f: F) -> Secret<U>\n    where\n        F: FnOnce(T) -> U,\n    {\n        Secret::from(f(self.inner))\n    }\n}\n\nimpl<T: ToOwned + ?Sized> Secret<&T> {\n    /// Converts a `Secret` containing a borrowed type to a `Secret` containing the\n    /// corresponding owned type.\n    /// ```\n    /// # use cargo_credential::Secret;\n    /// let borrowed: Secret<&str> = Secret::from(\"token\");\n    /// let owned: Secret<String> = borrowed.to_owned();\n    /// ```\n    pub fn to_owned(&self) -> Secret<<T as ToOwned>::Owned> {\n        Secret::from(self.inner.to_owned())\n    }\n}\n\nimpl<T, E> Secret<Result<T, E>> {\n    /// Converts a `Secret<Result<T, E>>` to a `Result<Secret<T>, E>`.\n    pub fn transpose(self) -> Result<Secret<T>, E> {\n        self.inner.map(|v| Secret::from(v))\n    }\n}\n\nimpl<T: AsRef<str>> Secret<T> {\n    /// Checks if the contained value is empty.\n    pub fn is_empty(&self) -> bool {\n        self.inner.as_ref().is_empty()\n    }\n}\n\nimpl<T> From<T> for Secret<T> {\n    fn from(inner: T) -> Self {\n        Self { inner }\n    }\n}\n\nimpl<T> fmt::Debug for Secret<T> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Secret\")\n            .field(\"inner\", &\"REDACTED\")\n            .finish()\n    }\n}\n"
  },
  {
    "path": "credential/cargo-credential/src/stdio.rs",
    "content": "use std::{fs::File, io::Error};\n\n/// Reset stdin and stdout to the attached console / tty for the duration of the closure.\n/// If no console is available, stdin and stdout will be redirected to null.\npub fn stdin_stdout_to_console<F, T>(f: F) -> Result<T, Error>\nwhere\n    F: FnOnce() -> T,\n{\n    let open_write = |f| std::fs::OpenOptions::new().write(true).open(f);\n\n    let mut stdin = File::open(imp::IN_DEVICE).or_else(|_| File::open(imp::NULL_DEVICE))?;\n    let mut stdout = open_write(imp::OUT_DEVICE).or_else(|_| open_write(imp::NULL_DEVICE))?;\n\n    let _stdin_guard = imp::ReplacementGuard::new(Stdio::Stdin, &mut stdin)?;\n    let _stdout_guard = imp::ReplacementGuard::new(Stdio::Stdout, &mut stdout)?;\n    Ok(f())\n}\n\nenum Stdio {\n    Stdin,\n    Stdout,\n}\n\n#[cfg(windows)]\nmod imp {\n    use super::Stdio;\n    use std::{fs::File, io::Error, os::windows::prelude::AsRawHandle};\n    use windows_sys::Win32::{\n        Foundation::{HANDLE, INVALID_HANDLE_VALUE},\n        System::Console::{\n            GetStdHandle, STD_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, SetStdHandle,\n        },\n    };\n    pub const OUT_DEVICE: &str = \"CONOUT$\";\n    pub const IN_DEVICE: &str = \"CONIN$\";\n    pub const NULL_DEVICE: &str = \"NUL\";\n\n    /// Restores previous stdio when dropped.\n    pub struct ReplacementGuard {\n        std_handle: STD_HANDLE,\n        previous: HANDLE,\n    }\n\n    impl ReplacementGuard {\n        pub(super) fn new(stdio: Stdio, replacement: &mut File) -> Result<ReplacementGuard, Error> {\n            let std_handle = match stdio {\n                Stdio::Stdin => STD_INPUT_HANDLE,\n                Stdio::Stdout => STD_OUTPUT_HANDLE,\n            };\n\n            let previous;\n            unsafe {\n                // Make a copy of the current handle\n                previous = GetStdHandle(std_handle);\n                if previous == INVALID_HANDLE_VALUE {\n                    return Err(std::io::Error::last_os_error());\n                }\n\n                // Replace stdin with the replacement handle\n                if SetStdHandle(std_handle, replacement.as_raw_handle() as HANDLE) == 0 {\n                    return Err(std::io::Error::last_os_error());\n                }\n            }\n\n            Ok(ReplacementGuard {\n                previous,\n                std_handle,\n            })\n        }\n    }\n\n    impl Drop for ReplacementGuard {\n        fn drop(&mut self) {\n            unsafe {\n                // Put previous handle back in to stdin\n                SetStdHandle(self.std_handle, self.previous);\n            }\n        }\n    }\n}\n\n#[cfg(unix)]\nmod imp {\n    use super::Stdio;\n    use libc::{STDIN_FILENO, STDOUT_FILENO, close, dup, dup2};\n    use std::{fs::File, io::Error, os::fd::AsRawFd};\n    pub const IN_DEVICE: &str = \"/dev/tty\";\n    pub const OUT_DEVICE: &str = \"/dev/tty\";\n    pub const NULL_DEVICE: &str = \"/dev/null\";\n\n    /// Restores previous stdio when dropped.\n    pub struct ReplacementGuard {\n        std_fileno: i32,\n        previous: i32,\n    }\n\n    impl ReplacementGuard {\n        pub(super) fn new(stdio: Stdio, replacement: &mut File) -> Result<ReplacementGuard, Error> {\n            let std_fileno = match stdio {\n                Stdio::Stdin => STDIN_FILENO,\n                Stdio::Stdout => STDOUT_FILENO,\n            };\n\n            let previous;\n            unsafe {\n                // Duplicate the existing stdin file to a new descriptor\n                previous = dup(std_fileno);\n                if previous == -1 {\n                    return Err(std::io::Error::last_os_error());\n                }\n                // Replace stdin with the replacement file\n                if dup2(replacement.as_raw_fd(), std_fileno) == -1 {\n                    return Err(std::io::Error::last_os_error());\n                }\n            }\n\n            Ok(ReplacementGuard {\n                previous,\n                std_fileno,\n            })\n        }\n    }\n\n    impl Drop for ReplacementGuard {\n        fn drop(&mut self) {\n            unsafe {\n                // Put previous file back in to stdin\n                dup2(self.previous, self.std_fileno);\n                // Close the file descriptor we used as a backup\n                close(self.previous);\n            }\n        }\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use std::fs::OpenOptions;\n    use std::io::{Seek, Write};\n\n    use super::Stdio;\n    use super::imp::ReplacementGuard;\n\n    #[test]\n    fn stdin() {\n        let tempdir = snapbox::dir::DirRoot::mutable_temp().unwrap();\n        let file = tempdir.path().unwrap().join(\"stdin\");\n        let mut file = OpenOptions::new()\n            .read(true)\n            .write(true)\n            .create(true)\n            .open(file)\n            .unwrap();\n\n        writeln!(&mut file, \"hello\").unwrap();\n        file.seek(std::io::SeekFrom::Start(0)).unwrap();\n        {\n            let _guard = ReplacementGuard::new(Stdio::Stdin, &mut file).unwrap();\n            let line = std::io::stdin().lines().next().unwrap().unwrap();\n            assert_eq!(line, \"hello\");\n        }\n    }\n}\n"
  },
  {
    "path": "credential/cargo-credential/tests/examples.rs",
    "content": "use std::path::Path;\n\nuse snapbox::cmd::Command;\nuse snapbox::prelude::*;\n\n#[test]\nfn stdout_redirected() {\n    let bin = snapbox::cmd::compile_example(\"stdout-redirected\", []).unwrap();\n\n    let hello = r#\"{\"v\":[1]}\"#;\n    let get_request = r#\"{\"v\": 1, \"registry\": {\"index-url\":\"sparse+https://test/\",\"name\":\"alternative\"},\"kind\": \"get\",\"operation\": \"read\",\"args\": []}\"#;\n    let err_not_supported = r#\"{\"Err\":{\"kind\":\"operation-not-supported\"}}\"#;\n\n    Command::new(bin)\n        .stdin(format!(\"{get_request}\\n\"))\n        .arg(\"--cargo-plugin\")\n        .assert()\n        .stdout_eq(format!(\"{hello}\\n{err_not_supported}\\n\").raw())\n        .stderr_eq(\"message on stderr should be sent to the parent process\\n\".raw())\n        .success();\n}\n\n#[test]\nfn file_provider() {\n    let bin = snapbox::cmd::compile_example(\"file-provider\", []).unwrap();\n\n    let hello = r#\"{\"v\":[1]}\"#;\n    let login_request = r#\"{\"v\": 1,\"registry\": {\"index-url\":\"https://github.com/rust-lang/crates.io-index\",\"name\":\"crates-io\"},\"kind\": \"login\",\"token\": \"s3krit\",\"args\": []}\"#;\n    let login_response = r#\"{\"Ok\":{\"kind\":\"login\"}}\"#;\n\n    let get_request = r#\"{\"v\": 1,\"registry\": {\"index-url\":\"https://github.com/rust-lang/crates.io-index\",\"name\":\"crates-io\"},\"kind\": \"get\",\"operation\": \"read\",\"args\": []}\"#;\n    let get_response =\n        r#\"{\"Ok\":{\"kind\":\"get\",\"token\":\"s3krit\",\"cache\":\"session\",\"operation_independent\":true}}\"#;\n\n    let dir = Path::new(env!(\"CARGO_TARGET_TMPDIR\")).join(\"cargo-credential-tests\");\n    std::fs::create_dir(&dir).unwrap();\n    Command::new(bin)\n        .current_dir(&dir)\n        .stdin(format!(\"{login_request}\\n{get_request}\\n\"))\n        .arg(\"--cargo-plugin\")\n        .assert()\n        .stdout_eq(format!(\"{hello}\\n{login_response}\\n{get_response}\\n\").raw())\n        .stderr_eq(\"\".raw())\n        .success();\n    std::fs::remove_dir_all(&dir).unwrap();\n}\n"
  },
  {
    "path": "credential/cargo-credential-1password/Cargo.toml",
    "content": "[package]\nname = \"cargo-credential-1password\"\nversion = \"0.4.6\"\nrust-version.workspace = true\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"A Cargo credential process that stores tokens in a 1password vault.\"\n\n[dependencies]\ncargo-credential.workspace = true\nserde = { workspace = true, features = [\"derive\"] }\nserde_json.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "credential/cargo-credential-1password/README.md",
    "content": "# cargo-credential-1password\n\nA Cargo [credential provider] for [1password].\n\n> This crate is maintained by the Cargo team as a part of an experiment around\n> 1password integration. We encourage people to try to use this crate in their projects and\n> provide feedback through [issues](https://github.com/rust-lang/cargo/issues/), but do not\n> guarantee long term maintenance.\n\n## Usage\n\n`cargo-credential-1password` uses the 1password `op` CLI to store the token. You\nmust install the `op` CLI from the [1password\nwebsite](https://1password.com/downloads/command-line/).\n\nAfterward you need to configure `cargo` to use `cargo-credential-1password` as\nthe credential provider. You can do this by adding something like the following\nto your [cargo config file][credential provider]:\n\n```toml\n[registry]\nglobal-credential-providers = [\"cargo-credential-1password --account my.1password.com\"]\n```\n\nFinally, run `cargo login` to save your registry token in 1password.\n\n## CLI Arguments\n\n`cargo-credential-1password` supports the following command-line arguments:\n\n* `--account`: The account name to use. For a list of available accounts, \n  run `op account list`.\n* `--vault`: The vault name to use. For a list of available vaults,\n  run `op vault list`.\n\n[1password]: https://1password.com/\n[credential provider]: https://doc.rust-lang.org/stable/cargo/reference/registry-authentication.html\n"
  },
  {
    "path": "credential/cargo-credential-1password/src/main.rs",
    "content": "//! Cargo registry 1password credential process.\n//!\n//! > This crate is maintained by the Cargo team as a part of an experiment around\n//! > 1password integration. We encourage people to try to use this crate in their projects and\n//! > provide feedback through [issues](https://github.com/rust-lang/cargo/issues/), but do not\n//! > guarantee long term maintenance.\n\n#![allow(clippy::disallowed_methods)]\n#![allow(clippy::print_stderr)]\n\nuse cargo_credential::{\n    Action, CacheControl, Credential, CredentialResponse, Error, RegistryInfo, Secret,\n};\nuse serde::Deserialize;\nuse std::io::Read;\nuse std::process::{Command, Stdio};\n\nconst CARGO_TAG: &str = \"cargo-registry\";\n\n/// Implementation of 1password keychain access for Cargo registries.\nstruct OnePasswordKeychain {\n    account: Option<String>,\n    vault: Option<String>,\n}\n\n/// 1password Login item type, used for the JSON output of `op item get`.\n#[derive(Deserialize)]\nstruct Login {\n    fields: Vec<Field>,\n}\n\n#[derive(Deserialize)]\nstruct Field {\n    id: String,\n    value: Option<String>,\n}\n\n/// 1password item from `op items list`.\n#[derive(Deserialize)]\nstruct ListItem {\n    id: String,\n    urls: Vec<Url>,\n}\n\n#[derive(Deserialize)]\nstruct Url {\n    href: String,\n}\n\nimpl OnePasswordKeychain {\n    fn new(args: &[&str]) -> Result<OnePasswordKeychain, Error> {\n        let mut args = args.iter();\n        let mut action = false;\n        let mut account = None;\n        let mut vault = None;\n        while let Some(arg) = args.next() {\n            match *arg {\n                \"--account\" => {\n                    account = Some(args.next().ok_or(\"--account needs an arg\")?);\n                }\n                \"--vault\" => {\n                    vault = Some(args.next().ok_or(\"--vault needs an arg\")?);\n                }\n                s if s.starts_with('-') => {\n                    return Err(format!(\"unknown option {}\", s).into());\n                }\n                _ => {\n                    if action {\n                        return Err(\"too many arguments\".into());\n                    } else {\n                        action = true;\n                    }\n                }\n            }\n        }\n        Ok(OnePasswordKeychain {\n            account: account.map(|s| s.to_string()),\n            vault: vault.map(|s| s.to_string()),\n        })\n    }\n\n    fn signin(&self) -> Result<Option<String>, Error> {\n        // If there are any session env vars, we'll assume that this is the\n        // correct account, and that the user knows what they are doing.\n        if std::env::vars().any(|(name, _)| name.starts_with(\"OP_SESSION_\")) {\n            return Ok(None);\n        }\n        let mut cmd = Command::new(\"op\");\n        cmd.args([\"signin\", \"--raw\"]);\n        if let Some(account) = &self.account {\n            cmd.arg(\"--account\");\n            cmd.arg(account);\n        }\n        cmd.stdout(Stdio::piped());\n        let mut child = cmd\n            .spawn()\n            .map_err(|e| format!(\"failed to spawn `op`: {}\", e))?;\n        let mut buffer = String::new();\n        child\n            .stdout\n            .as_mut()\n            .unwrap()\n            .read_to_string(&mut buffer)\n            .map_err(|e| format!(\"failed to get session from `op`: {}\", e))?;\n        if let Some(end) = buffer.find('\\n') {\n            buffer.truncate(end);\n        }\n        let status = child\n            .wait()\n            .map_err(|e| format!(\"failed to wait for `op`: {}\", e))?;\n        if !status.success() {\n            return Err(format!(\"failed to run `op signin`: {}\", status).into());\n        }\n        if buffer.is_empty() {\n            // When using CLI integration, `op signin` returns no output,\n            // so there is no need to set the session.\n            return Ok(None);\n        }\n        Ok(Some(buffer))\n    }\n\n    fn make_cmd(&self, session: &Option<String>, args: &[&str]) -> Command {\n        let mut cmd = Command::new(\"op\");\n        cmd.args(args);\n        if let Some(account) = &self.account {\n            cmd.arg(\"--account\");\n            cmd.arg(account);\n        }\n        if let Some(vault) = &self.vault {\n            cmd.arg(\"--vault\");\n            cmd.arg(vault);\n        }\n        if let Some(session) = session {\n            cmd.arg(\"--session\");\n            cmd.arg(session);\n        }\n        cmd\n    }\n\n    fn run_cmd(&self, mut cmd: Command) -> Result<String, Error> {\n        cmd.stdout(Stdio::piped());\n        let mut child = cmd\n            .spawn()\n            .map_err(|e| format!(\"failed to spawn `op`: {}\", e))?;\n        let mut buffer = String::new();\n        child\n            .stdout\n            .as_mut()\n            .unwrap()\n            .read_to_string(&mut buffer)\n            .map_err(|e| format!(\"failed to read `op` output: {}\", e))?;\n        let status = child\n            .wait()\n            .map_err(|e| format!(\"failed to wait for `op`: {}\", e))?;\n        if !status.success() {\n            return Err(format!(\"`op` command exit error: {}\", status).into());\n        }\n        Ok(buffer)\n    }\n\n    fn search(&self, session: &Option<String>, index_url: &str) -> Result<Option<String>, Error> {\n        let cmd = self.make_cmd(\n            session,\n            &[\n                \"items\",\n                \"list\",\n                \"--categories\",\n                \"Login\",\n                \"--tags\",\n                CARGO_TAG,\n                \"--format\",\n                \"json\",\n            ],\n        );\n        let buffer = self.run_cmd(cmd)?;\n        let items: Vec<ListItem> = serde_json::from_str(&buffer)\n            .map_err(|e| format!(\"failed to deserialize JSON from 1password list: {}\", e))?;\n        let mut matches = items\n            .into_iter()\n            .filter(|item| item.urls.iter().any(|url| url.href == index_url));\n        match matches.next() {\n            Some(login) => {\n                // Should this maybe just sort on `updatedAt` and return the newest one?\n                if matches.next().is_some() {\n                    return Err(format!(\n                        \"too many 1password logins match registry `{}`, \\\n                        consider deleting the excess entries\",\n                        index_url\n                    )\n                    .into());\n                }\n                Ok(Some(login.id))\n            }\n            None => Ok(None),\n        }\n    }\n\n    fn modify(\n        &self,\n        session: &Option<String>,\n        id: &str,\n        token: Secret<&str>,\n        _name: Option<&str>,\n    ) -> Result<(), Error> {\n        let cmd = self.make_cmd(\n            session,\n            &[\"item\", \"edit\", id, &format!(\"password={}\", token.expose())],\n        );\n        self.run_cmd(cmd)?;\n        Ok(())\n    }\n\n    fn create(\n        &self,\n        session: &Option<String>,\n        index_url: &str,\n        token: Secret<&str>,\n        name: Option<&str>,\n    ) -> Result<(), Error> {\n        let title = match name {\n            Some(name) => format!(\"Cargo registry token for {}\", name),\n            None => \"Cargo registry token\".to_string(),\n        };\n        let cmd = self.make_cmd(\n            session,\n            &[\n                \"item\",\n                \"create\",\n                \"--category\",\n                \"Login\",\n                &format!(\"password={}\", token.expose()),\n                &format!(\"url={}\", index_url),\n                \"--title\",\n                &title,\n                \"--tags\",\n                CARGO_TAG,\n            ],\n        );\n        self.run_cmd(cmd)?;\n        Ok(())\n    }\n\n    fn get_token(&self, session: &Option<String>, id: &str) -> Result<Secret<String>, Error> {\n        let cmd = self.make_cmd(session, &[\"item\", \"get\", \"--format=json\", id]);\n        let buffer = self.run_cmd(cmd)?;\n        let item: Login = serde_json::from_str(&buffer)\n            .map_err(|e| format!(\"failed to deserialize JSON from 1password get: {}\", e))?;\n        let password = item.fields.into_iter().find(|item| item.id == \"password\");\n        match password {\n            Some(password) => password\n                .value\n                .map(Secret::from)\n                .ok_or(\"missing password value for entry\".into()),\n            None => Err(\"could not find password field\".into()),\n        }\n    }\n\n    fn delete(&self, session: &Option<String>, id: &str) -> Result<(), Error> {\n        let cmd = self.make_cmd(session, &[\"item\", \"delete\", id]);\n        self.run_cmd(cmd)?;\n        Ok(())\n    }\n}\n\npub struct OnePasswordCredential {}\n\nimpl Credential for OnePasswordCredential {\n    fn perform(\n        &self,\n        registry: &RegistryInfo<'_>,\n        action: &Action<'_>,\n        args: &[&str],\n    ) -> Result<CredentialResponse, Error> {\n        let op = OnePasswordKeychain::new(args)?;\n        match action {\n            Action::Get(_) => {\n                let session = op.signin()?;\n                if let Some(id) = op.search(&session, registry.index_url)? {\n                    op.get_token(&session, &id)\n                        .map(|token| CredentialResponse::Get {\n                            token,\n                            cache: CacheControl::Session,\n                            operation_independent: true,\n                        })\n                } else {\n                    Err(Error::NotFound)\n                }\n            }\n            Action::Login(options) => {\n                let session = op.signin()?;\n                // Check if an item already exists.\n                if let Some(id) = op.search(&session, registry.index_url)? {\n                    eprintln!(\"note: token already exists for `{}`\", registry.index_url);\n                    let token = cargo_credential::read_token(options, registry)?;\n                    op.modify(&session, &id, token.as_deref(), None)?;\n                } else {\n                    let token = cargo_credential::read_token(options, registry)?;\n                    op.create(&session, registry.index_url, token.as_deref(), None)?;\n                }\n                Ok(CredentialResponse::Login)\n            }\n            Action::Logout => {\n                let session = op.signin()?;\n                // Check if an item already exists.\n                if let Some(id) = op.search(&session, registry.index_url)? {\n                    op.delete(&session, &id)?;\n                    Ok(CredentialResponse::Logout)\n                } else {\n                    Err(Error::NotFound)\n                }\n            }\n            _ => Err(Error::OperationNotSupported),\n        }\n    }\n}\n\nfn main() {\n    cargo_credential::main(OnePasswordCredential {});\n}\n"
  },
  {
    "path": "credential/cargo-credential-libsecret/Cargo.toml",
    "content": "[package]\nname = \"cargo-credential-libsecret\"\nversion = \"0.5.7\"\nrust-version = \"1.94\"  # MSRV:1\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"A Cargo credential process that stores tokens with GNOME libsecret.\"\n\n[dependencies]\nanyhow.workspace = true\ncargo-credential.workspace = true\nlibloading.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "credential/cargo-credential-libsecret/README.md",
    "content": "# cargo-credential-libsecret\n\nThis is the implementation for the Cargo credential helper for [GNOME libsecret].\nSee the [credential-provider] documentation for how to use this.\n\nThis credential provider is built-in to cargo as `cargo:libsecret`.\n\n> This crate is maintained by the Cargo team, primarily for use by Cargo\n> and not intended for external use (except as a transitive dependency). This\n> crate may make major changes to its APIs or be deprecated without warning.\n\n[GNOME libsecret]: https://wiki.gnome.org/Projects/Libsecret\n[credential-provider]: https://doc.rust-lang.org/nightly/cargo/reference/registry-authentication.html\n"
  },
  {
    "path": "credential/cargo-credential-libsecret/src/lib.rs",
    "content": "//! > This crate is maintained by the Cargo team, primarily for use by Cargo\n//! > and not intended for external use (except as a transitive dependency). This\n//! > crate may make major changes to its APIs or be deprecated without warning.\n\n#[cfg(target_os = \"linux\")]\nmod linux {\n    //! Implementation of the libsecret credential helper.\n\n    use anyhow::Context;\n    use cargo_credential::{\n        Action, CacheControl, Credential, CredentialResponse, Error, RegistryInfo, Secret,\n        read_token,\n    };\n    use libloading::{Library, Symbol};\n    use std::ffi::{CStr, CString};\n    use std::os::raw::{c_char, c_int};\n    use std::ptr::{null, null_mut};\n\n    #[allow(non_camel_case_types)]\n    type gchar = c_char;\n\n    #[allow(non_camel_case_types)]\n    type gboolean = c_int;\n\n    #[allow(non_camel_case_types)]\n    type gint = c_int;\n\n    #[allow(non_camel_case_types)]\n    type gpointer = *mut ();\n\n    type GQuark = u32;\n\n    #[repr(C)]\n    struct GError {\n        domain: GQuark,\n        code: c_int,\n        message: *mut gchar,\n    }\n\n    #[repr(C)]\n    struct GCancellable {\n        _private: [u8; 0],\n    }\n\n    #[repr(C)]\n    struct SecretSchema {\n        name: *const gchar,\n        flags: SecretSchemaFlags,\n        attributes: [SecretSchemaAttribute; 32],\n        reserved: gint,\n        reserved1: gpointer,\n        reserved2: gpointer,\n        reserved3: gpointer,\n        reserved4: gpointer,\n        reserved5: gpointer,\n        reserved6: gpointer,\n        reserved7: gpointer,\n    }\n\n    #[repr(C)]\n    #[derive(Copy, Clone)]\n    struct SecretSchemaAttribute {\n        name: *const gchar,\n        attr_type: SecretSchemaAttributeType,\n    }\n\n    #[repr(C)]\n    enum SecretSchemaFlags {\n        None = 0,\n    }\n\n    #[repr(C)]\n    #[derive(Copy, Clone)]\n    enum SecretSchemaAttributeType {\n        String = 0,\n    }\n\n    type SecretPasswordStoreSync = extern \"C\" fn(\n        schema: *const SecretSchema,\n        collection: *const gchar,\n        label: *const gchar,\n        password: *const gchar,\n        cancellable: *mut GCancellable,\n        error: *mut *mut GError,\n        ...\n    ) -> gboolean;\n    type SecretPasswordClearSync = extern \"C\" fn(\n        schema: *const SecretSchema,\n        cancellable: *mut GCancellable,\n        error: *mut *mut GError,\n        ...\n    ) -> gboolean;\n    type SecretPasswordLookupSync = extern \"C\" fn(\n        schema: *const SecretSchema,\n        cancellable: *mut GCancellable,\n        error: *mut *mut GError,\n        ...\n    ) -> *mut gchar;\n\n    pub struct LibSecretCredential {\n        libsecret: Library,\n    }\n\n    fn label(index_url: &str) -> CString {\n        CString::new(format!(\"cargo-registry:{}\", index_url)).unwrap()\n    }\n\n    fn schema() -> SecretSchema {\n        let mut attributes = [SecretSchemaAttribute {\n            name: null(),\n            attr_type: SecretSchemaAttributeType::String,\n        }; 32];\n        attributes[0] = SecretSchemaAttribute {\n            name: c\"url\".as_ptr() as *const gchar,\n            attr_type: SecretSchemaAttributeType::String,\n        };\n        SecretSchema {\n            name: c\"org.rust-lang.cargo.registry\".as_ptr() as *const gchar,\n            flags: SecretSchemaFlags::None,\n            attributes,\n            reserved: 0,\n            reserved1: null_mut(),\n            reserved2: null_mut(),\n            reserved3: null_mut(),\n            reserved4: null_mut(),\n            reserved5: null_mut(),\n            reserved6: null_mut(),\n            reserved7: null_mut(),\n        }\n    }\n\n    impl LibSecretCredential {\n        pub fn new() -> Result<LibSecretCredential, Error> {\n            // Dynamically load libsecret to avoid users needing to install\n            // additional -dev packages when building this provider.\n            let libsecret = unsafe { Library::new(\"libsecret-1.so.0\") }.context(\n                \"failed to load libsecret: try installing the `libsecret` \\\n                or `libsecret-1-0` package with the system package manager\",\n            )?;\n            Ok(Self { libsecret })\n        }\n    }\n\n    impl Credential for &LibSecretCredential {\n        fn perform(\n            &self,\n            registry: &RegistryInfo<'_>,\n            action: &Action<'_>,\n            _args: &[&str],\n        ) -> Result<CredentialResponse, Error> {\n            let secret_password_lookup_sync: Symbol<'_, SecretPasswordLookupSync>;\n            let secret_password_store_sync: Symbol<'_, SecretPasswordStoreSync>;\n            let secret_password_clear_sync: Symbol<'_, SecretPasswordClearSync>;\n            unsafe {\n                secret_password_lookup_sync = self\n                    .libsecret\n                    .get(b\"secret_password_lookup_sync\\0\")\n                    .map_err(Box::new)?;\n                secret_password_store_sync = self\n                    .libsecret\n                    .get(b\"secret_password_store_sync\\0\")\n                    .map_err(Box::new)?;\n                secret_password_clear_sync = self\n                    .libsecret\n                    .get(b\"secret_password_clear_sync\\0\")\n                    .map_err(Box::new)?;\n            }\n\n            let index_url_c = CString::new(registry.index_url).unwrap();\n            let mut error: *mut GError = null_mut();\n            let attr_url = c\"url\".as_ptr() as *const gchar;\n            let schema = schema();\n            match action {\n                cargo_credential::Action::Get(_) => unsafe {\n                    let token_c = secret_password_lookup_sync(\n                        &schema,\n                        null_mut(),\n                        &mut error,\n                        attr_url,\n                        index_url_c.as_ptr(),\n                        null() as *const gchar,\n                    );\n                    if !error.is_null() {\n                        return Err(format!(\n                            \"failed to get token: {}\",\n                            CStr::from_ptr((*error).message)\n                                .to_str()\n                                .unwrap_or_default()\n                        )\n                        .into());\n                    }\n                    if token_c.is_null() {\n                        return Err(Error::NotFound);\n                    }\n                    let token = Secret::from(\n                        CStr::from_ptr(token_c)\n                            .to_str()\n                            .map_err(|e| format!(\"expected utf8 token: {}\", e))?\n                            .to_string(),\n                    );\n                    Ok(CredentialResponse::Get {\n                        token,\n                        cache: CacheControl::Session,\n                        operation_independent: true,\n                    })\n                },\n                cargo_credential::Action::Login(options) => {\n                    let label = label(registry.name.unwrap_or(registry.index_url));\n                    let token = CString::new(read_token(options, registry)?.expose()).unwrap();\n                    unsafe {\n                        secret_password_store_sync(\n                            &schema,\n                            c\"default\".as_ptr() as *const gchar,\n                            label.as_ptr(),\n                            token.as_ptr(),\n                            null_mut(),\n                            &mut error,\n                            attr_url,\n                            index_url_c.as_ptr(),\n                            null() as *const gchar,\n                        );\n                        if !error.is_null() {\n                            return Err(format!(\n                                \"failed to store token: {}\",\n                                CStr::from_ptr((*error).message)\n                                    .to_str()\n                                    .unwrap_or_default()\n                            )\n                            .into());\n                        }\n                    }\n                    Ok(CredentialResponse::Login)\n                }\n                cargo_credential::Action::Logout => {\n                    unsafe {\n                        secret_password_clear_sync(\n                            &schema,\n                            null_mut(),\n                            &mut error,\n                            attr_url,\n                            index_url_c.as_ptr(),\n                            null() as *const gchar,\n                        );\n                        if !error.is_null() {\n                            return Err(format!(\n                                \"failed to erase token: {}\",\n                                CStr::from_ptr((*error).message)\n                                    .to_str()\n                                    .unwrap_or_default()\n                            )\n                            .into());\n                        }\n                    }\n                    Ok(CredentialResponse::Logout)\n                }\n                _ => Err(Error::OperationNotSupported),\n            }\n        }\n    }\n}\n\n#[cfg(not(target_os = \"linux\"))]\npub use cargo_credential::UnsupportedCredential as LibSecretCredential;\n#[cfg(target_os = \"linux\")]\npub use linux::LibSecretCredential;\n"
  },
  {
    "path": "credential/cargo-credential-macos-keychain/Cargo.toml",
    "content": "[package]\nname = \"cargo-credential-macos-keychain\"\nversion = \"0.4.22\"\nrust-version = \"1.94\"  # MSRV:1\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"A Cargo credential process that stores tokens in a macOS keychain.\"\n\n[dependencies]\ncargo-credential.workspace = true\n\n[target.'cfg(target_os = \"macos\")'.dependencies]\nsecurity-framework.workspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "credential/cargo-credential-macos-keychain/README.md",
    "content": "# cargo-credential-macos-keychain\n\nThis is the implementation for the Cargo credential helper for [macOS Keychain].\nSee the [credential-provider] documentation for how to use this.\n\nThis credential provider is built-in to cargo as `cargo:macos-keychain`.\n\n> This crate is maintained by the Cargo team, primarily for use by Cargo\n> and not intended for external use (except as a transitive dependency). This\n> crate may make major changes to its APIs or be deprecated without warning.\n\n[macOS Keychain]: https://support.apple.com/guide/keychain-access/welcome/mac\n[credential-provider]: https://doc.rust-lang.org/nightly/cargo/reference/registry-authentication.html\n\n"
  },
  {
    "path": "credential/cargo-credential-macos-keychain/src/lib.rs",
    "content": "//! Cargo registry macos keychain credential process.\n//!\n//! > This crate is maintained by the Cargo team, primarily for use by Cargo\n//! > and not intended for external use (except as a transitive dependency). This\n//! > crate may make major changes to its APIs or be deprecated without warning.\n\n#![allow(clippy::print_stderr)]\n\n#[cfg(target_os = \"macos\")]\nmod macos {\n    use cargo_credential::{\n        Action, CacheControl, Credential, CredentialResponse, Error, RegistryInfo, read_token,\n    };\n    use security_framework::os::macos::keychain::SecKeychain;\n\n    pub struct MacKeychain;\n\n    /// The account name is not used.\n    const ACCOUNT: &'static str = \"\";\n    const NOT_FOUND: i32 = -25300; // errSecItemNotFound\n\n    fn registry(index_url: &str) -> String {\n        format!(\"cargo-registry:{}\", index_url)\n    }\n\n    impl Credential for MacKeychain {\n        fn perform(\n            &self,\n            reg: &RegistryInfo<'_>,\n            action: &Action<'_>,\n            _args: &[&str],\n        ) -> Result<CredentialResponse, Error> {\n            let keychain = SecKeychain::default().unwrap();\n            let service_name = registry(reg.index_url);\n            let not_found = security_framework::base::Error::from(NOT_FOUND).code();\n            match action {\n                Action::Get(_) => match keychain.find_generic_password(&service_name, ACCOUNT) {\n                    Err(e) if e.code() == not_found => Err(Error::NotFound),\n                    Err(e) => Err(Box::new(e).into()),\n                    Ok((pass, _)) => {\n                        let token = String::from_utf8(pass.as_ref().to_vec()).map_err(Box::new)?;\n                        Ok(CredentialResponse::Get {\n                            token: token.into(),\n                            cache: CacheControl::Session,\n                            operation_independent: true,\n                        })\n                    }\n                },\n                Action::Login(options) => {\n                    let token = read_token(options, reg)?;\n                    match keychain.find_generic_password(&service_name, ACCOUNT) {\n                        Err(e) => {\n                            if e.code() == not_found {\n                                keychain\n                                    .add_generic_password(\n                                        &service_name,\n                                        ACCOUNT,\n                                        token.expose().as_bytes(),\n                                    )\n                                    .map_err(Box::new)?;\n                            }\n                        }\n                        Ok((_, mut item)) => {\n                            item.set_password(token.expose().as_bytes())\n                                .map_err(Box::new)?;\n                        }\n                    }\n                    Ok(CredentialResponse::Login)\n                }\n                Action::Logout => match keychain.find_generic_password(&service_name, ACCOUNT) {\n                    Err(e) if e.code() == not_found => Err(Error::NotFound),\n                    Err(e) => Err(Box::new(e).into()),\n                    Ok((_, item)) => {\n                        item.delete();\n                        Ok(CredentialResponse::Logout)\n                    }\n                },\n                _ => Err(Error::OperationNotSupported),\n            }\n        }\n    }\n}\n\n#[cfg(not(target_os = \"macos\"))]\npub use cargo_credential::UnsupportedCredential as MacKeychain;\n#[cfg(target_os = \"macos\")]\npub use macos::MacKeychain;\n"
  },
  {
    "path": "credential/cargo-credential-wincred/Cargo.toml",
    "content": "[package]\nname = \"cargo-credential-wincred\"\nversion = \"0.4.22\"\nrust-version = \"1.94\"  # MSRV:1\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = true\ndescription = \"A Cargo credential process that stores tokens with Windows Credential Manager.\"\n\n[dependencies]\ncargo-credential.workspace = true\n\n[target.'cfg(windows)'.dependencies.windows-sys]\nfeatures = [\"Win32_Foundation\", \"Win32_Security_Credentials\"]\nworkspace = true\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "credential/cargo-credential-wincred/README.md",
    "content": "# cargo-credential-wincred\n\nThis is the implementation for the Cargo credential helper for [Windows Credential Manager].\nSee the [credential-provider] documentation for how to use this.\n\nThis credential provider is built-in to cargo as `cargo:wincred`.\n\n> This crate is maintained by the Cargo team, primarily for use by Cargo\n> and not intended for external use (except as a transitive dependency). This\n> crate may make major changes to its APIs or be deprecated without warning.\n\n[Windows Credential Manager]: https://support.microsoft.com/en-us/windows/accessing-credential-manager-1b5c916a-6a16-889f-8581-fc16e8165ac0\n[credential-provider]: https://doc.rust-lang.org/nightly/cargo/reference/registry-authentication.html\n"
  },
  {
    "path": "credential/cargo-credential-wincred/src/lib.rs",
    "content": "//! Cargo registry windows credential process.\n//!\n//! > This crate is maintained by the Cargo team, primarily for use by Cargo\n//! > and not intended for external use (except as a transitive dependency). This\n//! > crate may make major changes to its APIs or be deprecated without warning.\n\n#[cfg(windows)]\nmod win {\n    use cargo_credential::{Action, CacheControl, CredentialResponse, RegistryInfo, read_token};\n    use cargo_credential::{Credential, Error};\n    use std::ffi::OsStr;\n\n    use std::os::windows::ffi::OsStrExt;\n\n    use windows_sys::Win32::Foundation::ERROR_NOT_FOUND;\n    use windows_sys::Win32::Foundation::FILETIME;\n    use windows_sys::Win32::Foundation::TRUE;\n    use windows_sys::Win32::Security::Credentials::CRED_PERSIST_LOCAL_MACHINE;\n    use windows_sys::Win32::Security::Credentials::CRED_TYPE_GENERIC;\n    use windows_sys::Win32::Security::Credentials::CREDENTIALW;\n    use windows_sys::Win32::Security::Credentials::CredReadW;\n    use windows_sys::Win32::Security::Credentials::CredWriteW;\n    use windows_sys::Win32::Security::Credentials::{CredDeleteW, CredFree};\n    use windows_sys::core::PWSTR;\n\n    pub struct WindowsCredential;\n\n    /// Converts a string to a nul-terminated wide UTF-16 byte sequence.\n    fn wstr(s: &str) -> Vec<u16> {\n        let mut wide: Vec<u16> = OsStr::new(s).encode_wide().collect();\n        if wide.iter().any(|b| *b == 0) {\n            panic!(\"nul byte in wide string\");\n        }\n        wide.push(0);\n        wide\n    }\n\n    fn target_name(index_url: &str) -> Vec<u16> {\n        wstr(&format!(\"cargo-registry:{}\", index_url))\n    }\n\n    impl Credential for WindowsCredential {\n        fn perform(\n            &self,\n            registry: &RegistryInfo<'_>,\n            action: &Action<'_>,\n            _args: &[&str],\n        ) -> Result<CredentialResponse, Error> {\n            match action {\n                Action::Get(_) => {\n                    let target_name = target_name(registry.index_url);\n                    let mut p_credential: *mut CREDENTIALW = std::ptr::null_mut() as *mut _;\n                    let bytes = unsafe {\n                        if CredReadW(\n                            target_name.as_ptr(),\n                            CRED_TYPE_GENERIC,\n                            0,\n                            &mut p_credential as *mut _,\n                        ) != TRUE\n                        {\n                            let err = std::io::Error::last_os_error();\n                            if err.raw_os_error() == Some(ERROR_NOT_FOUND as i32) {\n                                return Err(Error::NotFound);\n                            }\n                            return Err(Box::new(err).into());\n                        }\n                        std::slice::from_raw_parts(\n                            (*p_credential).CredentialBlob,\n                            (*p_credential).CredentialBlobSize as usize,\n                        )\n                    };\n                    let token = String::from_utf8(bytes.to_vec()).map_err(Box::new);\n                    unsafe { CredFree(p_credential as *mut _) };\n                    Ok(CredentialResponse::Get {\n                        token: token?.into(),\n                        cache: CacheControl::Session,\n                        operation_independent: true,\n                    })\n                }\n                Action::Login(options) => {\n                    let token = read_token(options, registry)?.expose();\n                    let target_name = target_name(registry.index_url);\n                    let comment = wstr(\"Cargo registry token\");\n                    let credential = CREDENTIALW {\n                        Flags: 0,\n                        Type: CRED_TYPE_GENERIC,\n                        TargetName: target_name.as_ptr() as PWSTR,\n                        Comment: comment.as_ptr() as PWSTR,\n                        LastWritten: FILETIME {\n                            dwLowDateTime: 0,\n                            dwHighDateTime: 0,\n                        },\n                        CredentialBlobSize: token.len() as u32,\n                        CredentialBlob: token.as_bytes().as_ptr() as *mut u8,\n                        Persist: CRED_PERSIST_LOCAL_MACHINE,\n                        AttributeCount: 0,\n                        Attributes: std::ptr::null_mut(),\n                        TargetAlias: std::ptr::null_mut(),\n                        UserName: std::ptr::null_mut(),\n                    };\n                    let result = unsafe { CredWriteW(&credential, 0) };\n                    if result != TRUE {\n                        let err = std::io::Error::last_os_error();\n                        return Err(Box::new(err).into());\n                    }\n                    Ok(CredentialResponse::Login)\n                }\n                Action::Logout => {\n                    let target_name = target_name(registry.index_url);\n                    let result = unsafe { CredDeleteW(target_name.as_ptr(), CRED_TYPE_GENERIC, 0) };\n                    if result != TRUE {\n                        let err = std::io::Error::last_os_error();\n                        if err.raw_os_error() == Some(ERROR_NOT_FOUND as i32) {\n                            return Err(Error::NotFound);\n                        }\n                        return Err(Box::new(err).into());\n                    }\n                    Ok(CredentialResponse::Logout)\n                }\n                _ => Err(Error::OperationNotSupported),\n            }\n        }\n    }\n}\n\n#[cfg(not(windows))]\npub use cargo_credential::UnsupportedCredential as WindowsCredential;\n#[cfg(windows)]\npub use win::WindowsCredential;\n"
  },
  {
    "path": "deny.toml",
    "content": "# This template contains all of the possible sections and their default values\n\n# Note that all fields that take a lint level have these possible values:\n# * deny - An error will be produced and the check will fail\n# * warn - A warning will be produced, but the check will not fail\n# * allow - No warning or error will be produced, though in some cases a note\n# will be\n\n# The values provided in this template are the default values that will be used\n# when any section or field is not specified in your own configuration\n\n# Root options\n\n# The graph table configures how the dependency graph is constructed and thus\n# which crates the checks are performed against\n[graph]\n# If 1 or more target triples (and optionally, target_features) are specified,\n# only the specified targets will be checked when running `cargo deny check`.\n# This means, if a particular package is only ever used as a target specific\n# dependency, such as, for example, the `nix` crate only being used via the\n# `target_family = \"unix\"` configuration, that only having windows targets in\n# this list would mean the nix crate, as well as any of its exclusive\n# dependencies not shared by any other crates, would be ignored, as the target\n# list here is effectively saying which targets you are building for.\ntargets = [\n    # The triple can be any string, but only the target triples built in to\n    # rustc (as of 1.40) can be checked against actual config expressions\n    #\"x86_64-unknown-linux-musl\",\n    # You can also specify which target_features you promise are enabled for a\n    # particular target. target_features are currently not validated against\n    # the actual valid features supported by the target architecture.\n    #{ triple = \"wasm32-unknown-unknown\", features = [\"atomics\"] },\n]\n# When creating the dependency graph used as the source of truth when checks are\n# executed, this field can be used to prune crates from the graph, removing them\n# from the view of cargo-deny. This is an extremely heavy hammer, as if a crate\n# is pruned from the graph, all of its dependencies will also be pruned unless\n# they are connected to another crate in the graph that hasn't been pruned,\n# so it should be used with care. The identifiers are [Package ID Specifications]\n# (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html)\n#exclude = []\n# If true, metadata will be collected with `--all-features`. Note that this can't\n# be toggled off if true, if you want to conditionally enable `--all-features` it\n# is recommended to pass `--all-features` on the cmd line instead\nall-features = false\n# If true, metadata will be collected with `--no-default-features`. The same\n# caveat with `all-features` applies\nno-default-features = false\n# If set, these feature will be enabled when collecting metadata. If `--features`\n# is specified on the cmd line they will take precedence over this option.\n#features = []\n\n# The output table provides options for how/if diagnostics are outputted\n[output]\n# When outputting inclusion graphs in diagnostics that include features, this\n# option can be used to specify the depth at which feature edges will be added.\n# This option is included since the graphs can be quite large and the addition\n# of features from the crate(s) to all of the graph roots can be far too verbose.\n# This option can be overridden via `--feature-depth` on the cmd line\nfeature-depth = 1\n\n# This section is considered when running `cargo deny check advisories`\n# More documentation for the advisories section can be found here:\n# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html\n[advisories]\n# The path where the advisory databases are cloned/fetched into\n#db-path = \"$CARGO_HOME/advisory-dbs\"\n# The url(s) of the advisory databases to use\n#db-urls = [\"https://github.com/rustsec/advisory-db\"]\nyanked = \"warn\"\n# A list of advisory IDs to ignore. Note that ignored advisories will still\n# output a note when they are encountered.\nignore = [\n    #\"RUSTSEC-0000-0000\",\n    #{ id = \"RUSTSEC-0000-0000\", reason = \"you can specify a reason the advisory is ignored\" },\n    #\"a-crate-that-is-yanked@0.1.1\", # you can also ignore yanked crate versions if you wish\n    #{ crate = \"a-crate-that-is-yanked@0.1.1\", reason = \"you can specify why you are ignoring the yanked crate\" },\n]\n# If this is true, then cargo deny will use the git executable to fetch advisory database.\n# If this is false, then it uses a built-in git library.\n# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support.\n# See Git Authentication for more information about setting up git authentication.\n#git-fetch-with-cli = true\n\n# This section is considered when running `cargo deny check licenses`\n# More documentation for the licenses section can be found here:\n# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html\n[licenses]\n# List of explicitly allowed licenses\n# See https://spdx.org/licenses/ for list of possible licenses\n# [possible values: any SPDX 3.11 short identifier (+ optional exception)].\nallow = [\n    \"MIT\",\n    \"MIT-0\",\n    \"Apache-2.0\",\n    \"BSD-2-Clause\",\n    \"BSD-3-Clause\",\n    \"MPL-2.0\",\n    \"Unicode-3.0\",\n    \"CC0-1.0\",\n    \"ISC\",\n    \"Zlib\",\n]\n# The confidence threshold for detecting a license from license text.\n# The higher the value, the more closely the license text must be to the\n# canonical license text of a valid SPDX license file.\n# [possible values: any between 0.0 and 1.0].\nconfidence-threshold = 0.8\n# Allow 1 or more licenses on a per-crate basis, so that particular licenses\n# aren't accepted for every possible crate as with the normal allow list\nexceptions = [\n    # Each entry is the crate and version constraint, and its specific allow\n    # list\n    #{ allow = [\"Zlib\"], crate = \"adler32\" },\n]\n\n# Some crates don't have (easily) machine readable licensing information,\n# adding a clarification entry for it allows you to manually specify the\n# licensing information\n#[[licenses.clarify]]\n# The package spec the clarification applies to\n#crate = \"ring\"\n# The SPDX expression for the license requirements of the crate\n#expression = \"MIT AND ISC AND OpenSSL\"\n# One or more files in the crate's source used as the \"source of truth\" for\n# the license expression. If the contents match, the clarification will be used\n# when running the license check, otherwise the clarification will be ignored\n# and the crate will be checked normally, which may produce warnings or errors\n# depending on the rest of your configuration\n#license-files = [\n# Each entry is a crate relative path, and the (opaque) hash of its contents\n#{ path = \"LICENSE\", hash = 0xbd0eed23 }\n#]\n\n[licenses.private]\n# If true, ignores workspace crates that aren't published, or are only\n# published to private registries.\n# To see how to mark a crate as unpublished (to the official registry),\n# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field.\nignore = false\n# One or more private registries that you might publish crates to, if a crate\n# is only published to private registries, and ignore is true, the crate will\n# not have its license(s) checked\nregistries = [\n    #\"https://sekretz.com/registry\n]\n\n# This section is considered when running `cargo deny check bans`.\n# More documentation about the 'bans' section can be found here:\n# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html\n[bans]\n# Lint level for when multiple versions of the same crate are detected\nmultiple-versions = \"warn\"\n# Lint level for when a crate version requirement is `*`\nwildcards = \"allow\"\n# The graph highlighting used when creating dotgraphs for crates\n# with multiple versions\n# * lowest-version - The path to the lowest versioned duplicate is highlighted\n# * simplest-path - The path to the version with the fewest edges is highlighted\n# * all - Both lowest-version and simplest-path are used\nhighlight = \"all\"\n# The default lint level for `default` features for crates that are members of\n# the workspace that is being checked. This can be overridden by allowing/denying\n# `default` on a crate-by-crate basis if desired.\nworkspace-default-features = \"allow\"\n# The default lint level for `default` features for external crates that are not\n# members of the workspace. This can be overridden by allowing/denying `default`\n# on a crate-by-crate basis if desired.\nexternal-default-features = \"allow\"\n# List of crates that are allowed. Use with care!\nallow = [\n    #\"ansi_term@0.11.0\",\n    #{ crate = \"ansi_term@0.11.0\", reason = \"you can specify a reason it is allowed\" },\n]\n# List of crates to deny\ndeny = [\n    #\"ansi_term@0.11.0\",\n    #{ crate = \"ansi_term@0.11.0\", reason = \"you can specify a reason it is banned\" },\n    # Wrapper crates can optionally be specified to allow the crate when it\n    # is a direct dependency of the otherwise banned crate\n    #{ crate = \"ansi_term@0.11.0\", wrappers = [\"this-crate-directly-depends-on-ansi_term\"] },\n]\n\n# List of features to allow/deny\n# Each entry the name of a crate and a version range. If version is\n# not specified, all versions will be matched.\n#[[bans.features]]\n#crate = \"reqwest\"\n# Features to not allow\n#deny = [\"json\"]\n# Features to allow\n#allow = [\n#    \"rustls\",\n#    \"__rustls\",\n#    \"__tls\",\n#    \"hyper-rustls\",\n#    \"rustls\",\n#    \"rustls-pemfile\",\n#    \"rustls-tls-webpki-roots\",\n#    \"tokio-rustls\",\n#    \"webpki-roots\",\n#]\n# If true, the allowed features must exactly match the enabled feature set. If\n# this is set there is no point setting `deny`\n#exact = true\n\n# Certain crates/versions that will be skipped when doing duplicate detection.\nskip = [\n    #\"ansi_term@0.11.0\",\n    #{ crate = \"ansi_term@0.11.0\", reason = \"you can specify a reason why it can't be updated/removed\" },\n]\n# Similarly to `skip` allows you to skip certain crates during duplicate\n# detection. Unlike skip, it also includes the entire tree of transitive\n# dependencies starting at the specified crate, up to a certain depth, which is\n# by default infinite.\nskip-tree = [\n    #\"ansi_term@0.11.0\", # will be skipped along with _all_ of its direct and transitive dependencies\n    #{ crate = \"ansi_term@0.11.0\", depth = 20 },\n]\n\n# This section is considered when running `cargo deny check sources`.\n# More documentation about the 'sources' section can be found here:\n# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html\n[sources]\n# Lint level for what to happen when a crate from a crate registry that is not\n# in the allow list is encountered\nunknown-registry = \"warn\"\n# Lint level for what to happen when a crate from a git repository that is not\n# in the allow list is encountered\nunknown-git = \"warn\"\n# List of URLs for allowed crate registries. Defaults to the crates.io index\n# if not specified. If it is specified but empty, no registries are allowed.\nallow-registry = [\"https://github.com/rust-lang/crates.io-index\"]\n# List of URLs for allowed Git repositories\nallow-git = []\n\n[sources.allow-org]\n# github.com organizations to allow git sources for\ngithub = []\n# gitlab.com organizations to allow git sources for\ngitlab = []\n# bitbucket.org organizations to allow git sources for\nbitbucket = []\n"
  },
  {
    "path": "publish.py",
    "content": "#!/usr/bin/env python3\n\n# This script is used to publish Cargo to crates.io.\n#\n# This is run automatically every 6 weeks by the Release team's automation\n# whose source is at https://github.com/rust-lang/simpleinfra/.\n#\n# See https://doc.crates.io/contrib/process/release.html for more about\n# Cargo's release process.\n\nimport os\nimport re\nimport subprocess\nimport urllib.request\nfrom urllib.error import HTTPError\n\n\n# Whenever you add a new crate to this list that does NOT start with \"cargo-\"\n# you must reach out to the infra team to add the crate to the list of crates\n# allowed to be published from the \"cargo CI\" crates.io token.\nTO_PUBLISH = [\n    'credential/cargo-credential',\n    'credential/cargo-credential-libsecret',\n    'credential/cargo-credential-wincred',\n    'credential/cargo-credential-1password',\n    'credential/cargo-credential-macos-keychain',\n    'crates/rustfix',\n    'crates/cargo-platform',\n    'crates/cargo-util',\n    'crates/crates-io',\n    'crates/cargo-util-schemas',\n    'crates/cargo-test-macro',\n    'crates/cargo-test-support',\n    'crates/build-rs',\n    '.',\n]\n\n\ndef already_published(name, version):\n    url = f'https://static.crates.io/crates/{name}/{version}/download'\n    try:\n        urllib.request.urlopen(url)\n    except HTTPError as e:\n        # 403 and 404 are common responses to assume it is not published\n        if 400 <= e.code < 500:\n            return False\n        print(f'error: failed to check if {name} {version} is already published')\n        print(f'    HTTP response error code {e.code} checking {url}')\n        raise\n    return True\n\n\ndef maybe_publish(path):\n    content = open(os.path.join(path, 'Cargo.toml')).read()\n    name = re.search('^name = \"([^\"]+)\"', content, re.M).group(1)\n    version = re.search('^version = \"([^\"]+)\"', content, re.M).group(1)\n    if already_published(name, version):\n        print('%s %s is already published, skipping' % (name, version))\n        return False\n    subprocess.check_call(['cargo', 'publish', '--no-verify'], cwd=path)\n    return True\n\n\ndef main():\n    print('Starting publish...')\n    for path in TO_PUBLISH:\n        maybe_publish(path)\n\n    print('Publish complete!')\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "rustfmt.toml",
    "content": "style_edition = \"2024\"\n"
  },
  {
    "path": "src/bin/cargo/cli.rs",
    "content": "use annotate_snippets::Level;\nuse anyhow::{Context as _, anyhow};\nuse cargo::core::{CliUnstable, features};\nuse cargo::util::context::TermConfig;\nuse cargo::{CargoResult, drop_print, drop_println};\nuse clap::builder::UnknownArgumentValueParser;\nuse itertools::Itertools;\nuse std::collections::HashMap;\nuse std::ffi::OsStr;\nuse std::ffi::OsString;\nuse std::fmt::Write;\n\nuse super::commands;\nuse super::list_commands;\nuse super::third_party_subcommands;\nuse super::user_defined_aliases;\nuse crate::command_prelude::*;\nuse crate::util::is_rustup;\nuse cargo::core::shell::ColorChoice;\nuse cargo::util::style;\n\n#[tracing::instrument(skip_all)]\npub fn main(gctx: &mut GlobalContext) -> CliResult {\n    // CAUTION: Be careful with using `config` until it is configured below.\n    // In general, try to avoid loading config values unless necessary (like\n    // the [alias] table).\n\n    let args = cli(gctx).try_get_matches()?;\n\n    // Update the process-level notion of cwd\n    if let Some(new_cwd) = args.get_one::<std::path::PathBuf>(\"directory\") {\n        // This is a temporary hack.\n        // This cannot access `GlobalContext`, so this is a bit messy.\n        // This does not properly parse `-Z` flags that appear after the subcommand.\n        // The error message is not as helpful as the standard one.\n        let nightly_features_allowed = matches!(&*features::channel(), \"nightly\" | \"dev\");\n        if !nightly_features_allowed\n            || (nightly_features_allowed\n                && !args\n                    .get_many(\"unstable-features\")\n                    .map(|mut z| z.any(|value: &String| value == \"unstable-options\"))\n                    .unwrap_or(false))\n        {\n            return Err(anyhow::format_err!(\n                \"the `-C` flag is unstable, \\\n                 pass `-Z unstable-options` on the nightly channel to enable it\"\n            )\n            .into());\n        }\n        std::env::set_current_dir(&new_cwd).context(\"could not change to requested directory\")?;\n        gctx.reload_cwd()?;\n    }\n\n    let (expanded_args, global_args) = expand_aliases(gctx, args, vec![])?;\n\n    let is_verbose = expanded_args.verbose() > 0;\n\n    if expanded_args\n        .get_one::<String>(\"unstable-features\")\n        .map(String::as_str)\n        == Some(\"help\")\n    {\n        // Don't let config errors get in the way of parsing arguments\n        let _ = configure_gctx(gctx, &expanded_args, None, global_args, None);\n        print_zhelp(gctx);\n    } else if expanded_args.flag(\"version\") {\n        // Don't let config errors get in the way of parsing arguments\n        let _ = configure_gctx(gctx, &expanded_args, None, global_args, None);\n        let version = get_version_string(is_verbose);\n        drop_print!(gctx, \"{}\", version);\n    } else if let Some(code) = expanded_args.get_one::<String>(\"explain\") {\n        // Don't let config errors get in the way of parsing arguments\n        let _ = configure_gctx(gctx, &expanded_args, None, global_args, None);\n        let mut process = gctx.load_global_rustc(None)?.process();\n        process.arg(\"--explain\").arg(code).exec()?;\n    } else if expanded_args.flag(\"list\") {\n        // Don't let config errors get in the way of parsing arguments\n        let _ = configure_gctx(gctx, &expanded_args, None, global_args, None);\n        print_list(gctx, is_verbose);\n    } else {\n        let (cmd, subcommand_args) = match expanded_args.subcommand() {\n            Some((cmd, args)) => (cmd, args),\n            _ => {\n                // No subcommand provided.\n                cli(gctx).print_help()?;\n                return Ok(());\n            }\n        };\n        let exec = Exec::infer(cmd)?;\n        configure_gctx(\n            gctx,\n            &expanded_args,\n            Some(subcommand_args),\n            global_args,\n            Some(&exec),\n        )?;\n        super::init_git(gctx);\n\n        exec.exec(gctx, subcommand_args)?;\n    }\n    Ok(())\n}\n\nfn print_zhelp(gctx: &GlobalContext) {\n    let header = style::HEADER;\n    let literal = style::LITERAL;\n    let placeholder = style::PLACEHOLDER;\n\n    let options = CliUnstable::help();\n    let max_length = options\n        .iter()\n        .filter(|(_, help)| help.is_some())\n        .map(|(option_name, _)| option_name.len())\n        .max()\n        .unwrap_or(0);\n    let z_flags = options\n        .iter()\n        .filter(|(_, help)| help.is_some())\n        .map(|(opt, help)| {\n            let opt = opt.replace(\"_\", \"-\");\n            let help = help.unwrap();\n            format!(\"    {literal}-Z {opt:<max_length$}{literal:#}  {help}\")\n        })\n        .join(\"\\n\");\n    drop_println!(\n        gctx,\n        \"\\\n{header}Available unstable (nightly-only) flags:{header:#}\n\n{z_flags}\n\nRun with `{literal}cargo -Z{literal:#} {placeholder}[FLAG] [COMMAND]{placeholder:#}`\",\n    );\n    if !gctx.nightly_features_allowed {\n        drop_println!(\n            gctx,\n            \"\\nUnstable flags are only available on the nightly channel \\\n                 of Cargo, but this is the `{}` channel.\\n\\\n                 {}\",\n            features::channel(),\n            features::SEE_CHANNELS\n        );\n    }\n    drop_println!(\n        gctx,\n        \"\\nSee https://doc.rust-lang.org/nightly/cargo/reference/unstable.html \\\n             for more information about these flags.\"\n    );\n}\n\nfn print_list(gctx: &GlobalContext, is_verbose: bool) {\n    // Maps from commonly known external commands (not builtin to cargo)\n    // to their description, for the help page. Reserved for external\n    // subcommands that are core within the rust ecosystem (esp ones that\n    // might become internal in the future).\n    let known_external_command_descriptions = HashMap::from([\n        (\n            \"clippy\",\n            \"Checks a package to catch common mistakes and improve your Rust code.\",\n        ),\n        (\n            \"fmt\",\n            \"Formats all bin and lib files of the current crate using rustfmt.\",\n        ),\n    ]);\n    drop_println!(\n        gctx,\n        color_print::cstr!(\"<bright-green,bold>Installed Commands:</>\")\n    );\n    for (name, command) in list_commands(gctx) {\n        let known_external_desc = known_external_command_descriptions.get(name.as_str());\n        let literal = style::LITERAL;\n        match command {\n            CommandInfo::BuiltIn { about } => {\n                assert!(\n                    known_external_desc.is_none(),\n                    \"known_external_commands shouldn't contain builtin `{name}`\",\n                );\n                let summary = about.unwrap_or_default();\n                let summary = summary.lines().next().unwrap_or(&summary); // display only the first line\n                drop_println!(gctx, \"    {literal}{name:<20}{literal:#} {summary}\");\n            }\n            CommandInfo::External { path } => {\n                if let Some(desc) = known_external_desc {\n                    drop_println!(gctx, \"    {literal}{name:<20}{literal:#} {desc}\");\n                } else if is_verbose {\n                    drop_println!(\n                        gctx,\n                        \"    {literal}{name:<20}{literal:#} {}\",\n                        path.display()\n                    );\n                } else {\n                    drop_println!(gctx, \"    {literal}{name}{literal:#}\");\n                }\n            }\n            CommandInfo::Alias { target } => {\n                drop_println!(\n                    gctx,\n                    \"    {literal}{name:<20}{literal:#} alias: {}\",\n                    target.iter().join(\" \")\n                );\n            }\n        }\n    }\n}\n\npub fn get_version_string(is_verbose: bool) -> String {\n    let version = cargo::version();\n    let mut version_string = format!(\"cargo {}\\n\", version);\n    if is_verbose {\n        version_string.push_str(&format!(\"release: {}\\n\", version.version));\n        if let Some(ref ci) = version.commit_info {\n            version_string.push_str(&format!(\"commit-hash: {}\\n\", ci.commit_hash));\n            version_string.push_str(&format!(\"commit-date: {}\\n\", ci.commit_date));\n        }\n        writeln!(version_string, \"host: {}\", env!(\"RUST_HOST_TARGET\")).unwrap();\n        add_libgit2(&mut version_string);\n        add_curl(&mut version_string);\n        add_ssl(&mut version_string);\n        writeln!(version_string, \"os: {}\", os_info::get()).unwrap();\n    }\n    version_string\n}\n\nfn add_libgit2(version_string: &mut String) {\n    let git2_v = git2::Version::get();\n    let lib_v = git2_v.libgit2_version();\n    let vendored = if git2_v.vendored() {\n        format!(\"vendored\")\n    } else {\n        format!(\"system\")\n    };\n    writeln!(\n        version_string,\n        \"libgit2: {}.{}.{} (sys:{} {})\",\n        lib_v.0,\n        lib_v.1,\n        lib_v.2,\n        git2_v.crate_version(),\n        vendored\n    )\n    .unwrap();\n}\n\nfn add_curl(version_string: &mut String) {\n    let curl_v = curl::Version::get();\n    let vendored = if curl_v.vendored() {\n        format!(\"vendored\")\n    } else {\n        format!(\"system\")\n    };\n    writeln!(\n        version_string,\n        \"libcurl: {} (sys:{} {} ssl:{})\",\n        curl_v.version(),\n        curl_sys::rust_crate_version(),\n        vendored,\n        curl_v.ssl_version().unwrap_or(\"none\")\n    )\n    .unwrap();\n}\n\nfn add_ssl(version_string: &mut String) {\n    #[cfg(feature = \"openssl\")]\n    {\n        writeln!(version_string, \"ssl: {}\", openssl::version::version()).unwrap();\n    }\n    #[cfg(not(feature = \"openssl\"))]\n    {\n        let _ = version_string; // Silence unused warning.\n    }\n}\n\n/// Expands aliases recursively to collect all the command line arguments.\n///\n/// [`GlobalArgs`] need to be extracted before expanding aliases because the\n/// clap code for extracting a subcommand discards global options\n/// (appearing before the subcommand).\n#[tracing::instrument(skip_all)]\nfn expand_aliases(\n    gctx: &mut GlobalContext,\n    args: ArgMatches,\n    mut already_expanded: Vec<String>,\n) -> Result<(ArgMatches, GlobalArgs), CliError> {\n    if let Some((cmd, sub_args)) = args.subcommand() {\n        let exec = commands::builtin_exec(cmd);\n        let aliased_cmd = super::aliased_command(gctx, cmd);\n\n        match (exec, aliased_cmd) {\n            (Some(_), Ok(Some(_))) => {\n                // User alias conflicts with a built-in subcommand\n                gctx.shell().warn(format!(\n                    \"user-defined alias `{}` is ignored, because it is shadowed by a built-in command\",\n                    cmd,\n                ))?;\n            }\n            (Some(_), Ok(None) | Err(_)) => {\n                // Here we ignore errors from aliasing as we already favor built-in command,\n                // and alias doesn't involve in this context.\n\n                if let Some(values) = sub_args.get_many::<OsString>(\"\") {\n                    // Command is built-in and is not conflicting with alias, but contains ignored values.\n                    return Err(anyhow::format_err!(\n                        \"\\\ntrailing arguments after built-in command `{}` are unsupported: `{}`\n\nTo pass the arguments to the subcommand, remove `--`\",\n                        cmd,\n                        values.map(|s| s.to_string_lossy()).join(\" \"),\n                    )\n                    .into());\n                }\n            }\n            (None, Ok(None)) => {}\n            (None, Ok(Some(alias))) => {\n                // Check if a user-defined alias is shadowing an external subcommand\n                // (binary of the form `cargo-<subcommand>`)\n                // Currently this is only a warning, but after a transition period this will become\n                // a hard error.\n                if super::builtin_aliases_execs(cmd).is_none() {\n                    if let Some(path) = super::find_external_subcommand(gctx, cmd) {\n                        gctx.shell().print_report(\n                            &[\n                                Level::WARNING.secondary_title(format!(\n                                    \"user-defined alias `{}` is shadowing an external subcommand found at `{}`\",\n                                    cmd,\n                                    path.display()\n                                )).element(\n                                    Level::NOTE.message(\n                                        \"this was previously accepted but will become a hard error in the future; \\\n                                        see <https://github.com/rust-lang/cargo/issues/10049>\"\n                                    )\n                                )\n                            ],\n                            false,\n                        )?;\n                    }\n                }\n                if commands::run::is_manifest_command(cmd) {\n                    if gctx.cli_unstable().script {\n                        return Ok((args, GlobalArgs::default()));\n                    } else {\n                        gctx.shell().print_report(\n                            &[\n                                Level::WARNING.secondary_title(\n                                    format!(\"user-defined alias `{cmd}` has the appearance of a manifest-command\")\n                                ).element(\n                                    Level::NOTE.message(\n                                        \"this was previously accepted but will be phased out when `-Zscript` is stabilized; \\\n                                        see <https://github.com/rust-lang/cargo/issues/12207>\"\n                                    )\n                                )\n                            ],\n                            false\n                        )?;\n                    }\n                }\n\n                let mut alias = alias\n                    .into_iter()\n                    .map(|s| OsString::from(s))\n                    .collect::<Vec<_>>();\n                alias.extend(\n                    sub_args\n                        .get_many::<OsString>(\"\")\n                        .unwrap_or_default()\n                        .cloned(),\n                );\n                // new_args strips out everything before the subcommand, so\n                // capture those global options now.\n                // Note that an alias to an external command will not receive\n                // these arguments. That may be confusing, but such is life.\n                let global_args = GlobalArgs::new(sub_args);\n                let new_args = cli(gctx).no_binary_name(true).try_get_matches_from(alias)?;\n\n                let Some(new_cmd) = new_args.subcommand_name() else {\n                    return Err(anyhow!(\n                        \"subcommand is required, add a subcommand to the command alias `alias.{cmd}`\"\n                    )\n                        .into());\n                };\n\n                already_expanded.push(cmd.to_string());\n                if already_expanded.contains(&new_cmd.to_string()) {\n                    // Crash if the aliases are corecursive / unresolvable\n                    return Err(anyhow!(\n                        \"alias {} has unresolvable recursive definition: {} -> {}\",\n                        already_expanded[0],\n                        already_expanded.join(\" -> \"),\n                        new_cmd,\n                    )\n                    .into());\n                }\n\n                let (expanded_args, _) = expand_aliases(gctx, new_args, already_expanded)?;\n                return Ok((expanded_args, global_args));\n            }\n            (None, Err(e)) => return Err(e.into()),\n        }\n    };\n\n    Ok((args, GlobalArgs::default()))\n}\n\n#[tracing::instrument(skip_all)]\nfn configure_gctx(\n    gctx: &mut GlobalContext,\n    args: &ArgMatches,\n    subcommand_args: Option<&ArgMatches>,\n    global_args: GlobalArgs,\n    exec: Option<&Exec>,\n) -> CliResult {\n    let arg_target_dir = &subcommand_args.and_then(|a| a.value_of_path(\"target-dir\", gctx));\n    let mut verbose = global_args.verbose + args.verbose();\n    // quiet is unusual because it is redefined in some subcommands in order\n    // to provide custom help text.\n    let mut quiet = args.flag(\"quiet\")\n        || subcommand_args.map(|a| a.flag(\"quiet\")).unwrap_or_default()\n        || global_args.quiet;\n    if matches!(exec, Some(Exec::Manifest(_))) && !quiet {\n        // Verbosity is shifted quieter for `Exec::Manifest` as it is can be used as if you ran\n        // `cargo install` and we especially shouldn't pollute programmatic output.\n        //\n        // For now, interactive output has the same default output as `cargo run` but that is\n        // subject to change.\n        if let Some(lower) = verbose.checked_sub(1) {\n            verbose = lower;\n        } else if !gctx.shell().is_err_tty() {\n            // Don't pollute potentially-scripted output\n            quiet = true;\n        }\n    }\n    let global_color = global_args.color; // Extract so it can take reference.\n    let color = args\n        .get_one::<String>(\"color\")\n        .map(String::as_str)\n        .or_else(|| global_color.as_deref());\n    let frozen = args.flag(\"frozen\") || global_args.frozen;\n    let locked = args.flag(\"locked\") || global_args.locked;\n    let offline = args.flag(\"offline\") || global_args.offline;\n    let mut unstable_flags = global_args.unstable_flags;\n    if let Some(values) = args.get_many::<String>(\"unstable-features\") {\n        unstable_flags.extend(values.cloned());\n    }\n    let mut config_args = global_args.config_args;\n    if let Some(values) = args.get_many::<String>(\"config\") {\n        config_args.extend(values.cloned());\n    }\n    gctx.configure(\n        verbose,\n        quiet,\n        color,\n        frozen,\n        locked,\n        offline,\n        arg_target_dir,\n        &unstable_flags,\n        &config_args,\n    )?;\n    Ok(())\n}\n\nenum Exec {\n    Builtin(commands::Exec),\n    Manifest(String),\n    External(String),\n}\n\nimpl Exec {\n    /// Precedence isn't the most obvious from this function because\n    /// - Some is determined by `expand_aliases`\n    /// - Some is enforced by `avoid_ambiguity_between_builtins_and_manifest_commands`\n    ///\n    /// In actuality, it is:\n    /// 1. built-ins xor manifest-command\n    /// 2. aliases\n    /// 3. external subcommands\n    fn infer(cmd: &str) -> CargoResult<Self> {\n        if let Some(exec) = commands::builtin_exec(cmd) {\n            Ok(Self::Builtin(exec))\n        } else if commands::run::is_manifest_command(cmd) {\n            Ok(Self::Manifest(cmd.to_owned()))\n        } else {\n            Ok(Self::External(cmd.to_owned()))\n        }\n    }\n\n    #[tracing::instrument(skip_all)]\n    fn exec(self, gctx: &mut GlobalContext, subcommand_args: &ArgMatches) -> CliResult {\n        match self {\n            Self::Builtin(exec) => exec(gctx, subcommand_args),\n            Self::Manifest(cmd) => {\n                let ext_path = super::find_external_subcommand(gctx, &cmd);\n                if !gctx.cli_unstable().script && ext_path.is_some() {\n                    gctx.shell().print_report(\n                        &[\n                            Level::WARNING.secondary_title(\n                                format!(\"external subcommand `{cmd}` has the appearance of a manifest-command\")\n                            ).element(\n                                Level::NOTE.message(\n                                    \"this was previously accepted but will be phased out when `-Zscript` is stabilized; \\\n                                    see <https://github.com/rust-lang/cargo/issues/12207>\"\n                                )\n                            )\n                        ],\n                        false\n                    )?;\n\n                    Self::External(cmd).exec(gctx, subcommand_args)\n                } else {\n                    let ext_args: Vec<OsString> = subcommand_args\n                        .get_many::<OsString>(\"\")\n                        .unwrap_or_default()\n                        .cloned()\n                        .collect();\n                    commands::run::exec_manifest_command(gctx, &cmd, &ext_args)\n                }\n            }\n            Self::External(cmd) => {\n                let mut ext_args = vec![OsStr::new(&cmd)];\n                ext_args.extend(\n                    subcommand_args\n                        .get_many::<OsString>(\"\")\n                        .unwrap_or_default()\n                        .map(OsString::as_os_str),\n                );\n                super::execute_external_subcommand(gctx, &cmd, &ext_args)\n            }\n        }\n    }\n}\n\n#[derive(Default)]\nstruct GlobalArgs {\n    verbose: u32,\n    quiet: bool,\n    color: Option<String>,\n    frozen: bool,\n    locked: bool,\n    offline: bool,\n    unstable_flags: Vec<String>,\n    config_args: Vec<String>,\n}\n\nimpl GlobalArgs {\n    fn new(args: &ArgMatches) -> GlobalArgs {\n        GlobalArgs {\n            verbose: args.verbose(),\n            quiet: args.flag(\"quiet\"),\n            color: args.get_one::<String>(\"color\").cloned(),\n            frozen: args.flag(\"frozen\"),\n            locked: args.flag(\"locked\"),\n            offline: args.flag(\"offline\"),\n            unstable_flags: args\n                .get_many::<String>(\"unstable-features\")\n                .unwrap_or_default()\n                .cloned()\n                .collect(),\n            config_args: args\n                .get_many::<String>(\"config\")\n                .unwrap_or_default()\n                .cloned()\n                .collect(),\n        }\n    }\n}\n\n#[tracing::instrument(skip_all)]\npub fn cli(gctx: &GlobalContext) -> Command {\n    // Don't let config errors get in the way of parsing arguments\n    let term = gctx.get::<TermConfig>(\"term\").unwrap_or_default();\n    let color = term\n        .color\n        .and_then(|c| c.parse().ok())\n        .unwrap_or(ColorChoice::CargoAuto);\n    let color = match color {\n        ColorChoice::Always => clap::ColorChoice::Always,\n        ColorChoice::Never => clap::ColorChoice::Never,\n        ColorChoice::CargoAuto => clap::ColorChoice::Auto,\n    };\n\n    let usage = if is_rustup() {\n        color_print::cstr!(\n            \"<bright-cyan,bold>cargo</> <cyan>[+toolchain] [OPTIONS] [COMMAND]</>\\n       <bright-cyan,bold>cargo</> <cyan>[+toolchain] [OPTIONS]</> <bright-cyan,bold>-Zscript</> <cyan><<MANIFEST_RS>> [ARGS]...</>\"\n        )\n    } else {\n        color_print::cstr!(\n            \"<bright-cyan,bold>cargo</> <cyan>[OPTIONS] [COMMAND]</>\\n       <bright-cyan,bold>cargo</> <cyan>[OPTIONS]</> <bright-cyan,bold>-Zscript</> <cyan><<MANIFEST_RS>> [ARGS]...</>\"\n        )\n    };\n\n    let styles = {\n        clap::builder::styling::Styles::styled()\n            .header(style::HEADER)\n            .usage(style::USAGE)\n            .literal(style::LITERAL)\n            .placeholder(style::PLACEHOLDER)\n            .error(style::ERROR)\n            .valid(style::VALID)\n            .invalid(style::INVALID)\n    };\n\n    Command::new(\"cargo\")\n        // Subcommands all count their args' display order independently (from 0),\n        // which makes their args interspersed with global args. This puts global args last.\n        //\n        // We also want these to come before auto-generated `--help`\n        .next_display_order(800)\n        .allow_external_subcommands(true)\n        .color(color)\n        .styles(styles)\n        // Provide a custom help subcommand for calling into man pages\n        .disable_help_subcommand(true)\n        .override_usage(usage)\n        .help_template(color_print::cstr!(\n            \"\\\nRust's package manager\n\n<bright-green,bold>Usage:</> {usage}\n\n<bright-green,bold>Options:</>\n{options}\n\n<bright-green,bold>Commands:</>\n    <bright-cyan,bold>build</>, <bright-cyan,bold>b</>    Compile the current package\n    <bright-cyan,bold>check</>, <bright-cyan,bold>c</>    Analyze the current package and report errors, but don't build object files\n    <bright-cyan,bold>clean</>       Remove the target directory\n    <bright-cyan,bold>doc</>, <bright-cyan,bold>d</>      Build this package's and its dependencies' documentation\n    <bright-cyan,bold>new</>         Create a new cargo package\n    <bright-cyan,bold>init</>        Create a new cargo package in an existing directory\n    <bright-cyan,bold>add</>         Add dependencies to a manifest file\n    <bright-cyan,bold>remove</>      Remove dependencies from a manifest file\n    <bright-cyan,bold>run</>, <bright-cyan,bold>r</>      Run a binary or example of the local package\n    <bright-cyan,bold>test</>, <bright-cyan,bold>t</>     Run the tests\n    <bright-cyan,bold>bench</>       Run the benchmarks\n    <bright-cyan,bold>update</>      Update dependencies listed in Cargo.lock\n    <bright-cyan,bold>search</>      Search registry for crates\n    <bright-cyan,bold>publish</>     Package and upload this package to the registry\n    <bright-cyan,bold>install</>     Install a Rust binary\n    <bright-cyan,bold>uninstall</>   Uninstall a Rust binary\n    <cyan>...</>         See all commands with <bright-cyan,bold>--list</>\n\nSee '<bright-cyan,bold>cargo help</> <cyan><<command>></>' for more information on a specific command.\\n\",\n        ))\n        .arg(flag(\"version\", \"Print version info and exit\").short('V'))\n        .arg(flag(\"list\", \"List installed commands\"))\n        .arg(\n            opt(\n                \"explain\",\n                \"Provide a detailed explanation of a rustc error message\",\n            )\n            .value_name(\"CODE\"),\n        )\n        .arg(\n            opt(\n                \"verbose\",\n                \"Use verbose output (-vv very verbose/build.rs output)\",\n            )\n            .short('v')\n            .action(ArgAction::Count)\n            .global(true),\n        )\n        .arg(flag(\"quiet\", \"Do not print cargo log messages\").short('q').global(true))\n        .arg(\n            opt(\"color\", \"Coloring\")\n                .value_name(\"WHEN\")\n                .global(true)\n                .value_parser([\"auto\", \"always\", \"never\"])\n                .ignore_case(true),\n        )\n        .arg(\n            Arg::new(\"directory\")\n                .help(\"Change to DIRECTORY before doing anything (nightly-only)\")\n                .short('C')\n                .value_name(\"DIRECTORY\")\n                .value_hint(clap::ValueHint::DirPath)\n                .value_parser(clap::builder::ValueParser::path_buf()),\n        )\n        .arg(\n            flag(\"locked\", \"Assert that `Cargo.lock` will remain unchanged\")\n                .help_heading(heading::MANIFEST_OPTIONS)\n                .global(true),\n        )\n        .arg(\n            flag(\"offline\", \"Run without accessing the network\")\n                .help_heading(heading::MANIFEST_OPTIONS)\n                .global(true),\n        )\n        .arg(\n            flag(\"frozen\", \"Equivalent to specifying both --locked and --offline\")\n                .help_heading(heading::MANIFEST_OPTIONS)\n                .global(true),\n        )\n        // Better suggestion for the unsupported short config flag.\n        .arg( Arg::new(\"unsupported-short-config-flag\")\n            .help(\"\")\n            .short('c')\n            .value_parser(UnknownArgumentValueParser::suggest_arg(\"--config\"))\n            .action(ArgAction::SetTrue)\n            .global(true)\n            .hide(true))\n        .arg(multi_opt(\"config\", \"KEY=VALUE|PATH\", \"Override a configuration value\").global(true))\n        // Better suggestion for the unsupported lowercase unstable feature flag.\n        .arg( Arg::new(\"unsupported-lowercase-unstable-feature-flag\")\n            .help(\"\")\n            .short('z')\n            .value_parser(UnknownArgumentValueParser::suggest_arg(\"-Z\"))\n            .action(ArgAction::SetTrue)\n            .global(true)\n            .hide(true))\n        .arg(Arg::new(\"unstable-features\")\n            .help(\"Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details\")\n            .short('Z')\n            .value_name(\"FLAG\")\n            .action(ArgAction::Append)\n            .global(true)\n        .add(clap_complete::ArgValueCandidates::new(|| {\n            let flags = CliUnstable::help();\n            flags.into_iter().map(|flag| {\n                clap_complete::CompletionCandidate::new(flag.0.replace(\"_\", \"-\")).help(flag.1.map(|help| {\n                    help.into()\n                }))\n            }).collect()\n        })))\n        .add(clap_complete::engine::SubcommandCandidates::new(move || {\n            let mut candidates = get_toolchains_from_rustup()\n                .into_iter()\n                .map(|t| clap_complete::CompletionCandidate::new(t))\n                .collect::<Vec<_>>();\n            if let Ok(gctx) = new_gctx_for_completions() {\n                candidates.extend(get_command_candidates(&gctx));\n            }\n            candidates\n        }))\n        .subcommands(commands::builtin())\n}\n\nfn get_toolchains_from_rustup() -> Vec<String> {\n    let output = std::process::Command::new(\"rustup\")\n        .arg(\"toolchain\")\n        .arg(\"list\")\n        .arg(\"-q\")\n        .output()\n        .unwrap();\n\n    if !output.status.success() {\n        return vec![];\n    }\n\n    let stdout = String::from_utf8(output.stdout).unwrap();\n\n    stdout.lines().map(|line| format!(\"+{}\", line)).collect()\n}\n\nfn get_command_candidates(gctx: &GlobalContext) -> Vec<clap_complete::CompletionCandidate> {\n    let mut commands = user_defined_aliases(gctx);\n    commands.extend(third_party_subcommands(gctx));\n    commands\n        .iter()\n        .map(|(name, cmd_info)| {\n            let help_text = match cmd_info {\n                CommandInfo::Alias { target } => {\n                    let cmd_str = target\n                        .iter()\n                        .map(String::as_str)\n                        .collect::<Vec<_>>()\n                        .join(\" \");\n                    format!(\"alias for {}\", cmd_str)\n                }\n                CommandInfo::BuiltIn { .. } => {\n                    unreachable!(\"BuiltIn command shouldn't appear in alias map\")\n                }\n                CommandInfo::External { path } => {\n                    format!(\"from {}\", path.display())\n                }\n            };\n            clap_complete::CompletionCandidate::new(name.clone()).help(Some(help_text.into()))\n        })\n        .collect()\n}\n\n#[test]\nfn verify_cli() {\n    let gctx = GlobalContext::default().unwrap();\n    cli(&gctx).debug_assert();\n}\n\n#[test]\nfn avoid_ambiguity_between_builtins_and_manifest_commands() {\n    for cmd in commands::builtin() {\n        let name = cmd.get_name();\n        assert!(\n            !commands::run::is_manifest_command(&name),\n            \"built-in command {name} is ambiguous with manifest-commands\"\n        )\n    }\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/add.rs",
    "content": "use cargo::sources::CRATES_IO_REGISTRY;\nuse cargo::util::print_available_packages;\nuse indexmap::IndexMap;\nuse indexmap::IndexSet;\n\nuse cargo::CargoResult;\nuse cargo::core::FeatureValue;\nuse cargo::core::dependency::DepKind;\nuse cargo::ops::cargo_add::AddOptions;\nuse cargo::ops::cargo_add::DepOp;\nuse cargo::ops::cargo_add::add;\nuse cargo::ops::resolve_ws;\nuse cargo::util::command_prelude::*;\nuse cargo::util::toml_mut::manifest::DepTable;\n\npub fn cli() -> Command {\n    clap::Command::new(\"add\")\n        .about(\"Add dependencies to a Cargo.toml manifest file\")\n        .override_usage(\n            color_print::cstr!(\"\\\n       <bright-cyan,bold>cargo add</> <cyan>[OPTIONS] <<DEP>>[@<<VERSION>>] ...</>\n       <bright-cyan,bold>cargo add</> <cyan>[OPTIONS]</> <bright-cyan,bold>--path</> <cyan><<PATH>> ...</>\n       <bright-cyan,bold>cargo add</> <cyan>[OPTIONS]</> <bright-cyan,bold>--git</> <cyan><<URL>> ...</>\"\n        ))\n        .after_help(color_print::cstr!(\"Run `<bright-cyan,bold>cargo help add</>` for more detailed information.\\n\"))\n        .group(clap::ArgGroup::new(\"selected\").multiple(true).required(true))\n        .args([\n            clap::Arg::new(\"crates\")\n                .value_name(\"DEP_ID\")\n                .num_args(0..)\n                .help(\"Reference to a package to add as a dependency\")\n                .long_help(\n                \"Reference to a package to add as a dependency\n\nYou can reference a package by:\n- `<name>`, like `cargo add serde` (latest version will be used)\n- `<name>@<version-req>`, like `cargo add serde@1` or `cargo add serde@=1.0.38`\"\n            )\n                .group(\"selected\"),\n            flag(\"no-default-features\",\n                \"Disable the default features\"),\n            flag(\"default-features\",\n                \"Re-enable the default features\")\n                .overrides_with(\"no-default-features\"),\n            clap::Arg::new(\"features\")\n                .short('F')\n                .long(\"features\")\n                .value_name(\"FEATURES\")\n                .action(ArgAction::Append)\n                .help(\"Space or comma separated list of features to activate\"),\n            flag(\"optional\",\n                \"Mark the dependency as optional\")\n                .long_help(\"Mark the dependency as optional\n\nThe package name will be exposed as feature of your crate.\")\n                .conflicts_with(\"dev\"),\n            flag(\"no-optional\",\n                \"Mark the dependency as required\")\n                .long_help(\"Mark the dependency as required\n\nThe package will be removed from your features.\")\n                .conflicts_with(\"dev\")\n                .overrides_with(\"optional\"),\n            flag(\"public\", \"Mark the dependency as public (unstable)\")\n                .conflicts_with(\"dev\")\n                .conflicts_with(\"build\")\n                .long_help(\"Mark the dependency as public (unstable)\n\nThe dependency can be referenced in your library's public API.\"),\n            flag(\"no-public\", \"Mark the dependency as private (unstable)\")\n                .conflicts_with(\"dev\")\n                .conflicts_with(\"build\")\n                .overrides_with(\"public\")\n                .long_help(\"Mark the dependency as private (unstable)\n\nWhile you can use the crate in your implementation, it cannot be referenced in your public API.\"),\n            clap::Arg::new(\"rename\")\n                .long(\"rename\")\n                .action(ArgAction::Set)\n                .value_name(\"NAME\")\n                .help(\"Rename the dependency\")\n                .long_help(\"Rename the dependency\n\nExample uses:\n- Depending on multiple versions of a crate\n- Depend on crates with the same name from different registries\"),\n        ])\n        .arg_manifest_path_without_unsupported_path_tip()\n        .arg_package(\"Package to modify\")\n        .arg_ignore_rust_version()\n        .arg_dry_run(\"Don't actually write the manifest\")\n        .arg_silent_suggestion()\n        .next_help_heading(\"Source\")\n        .args([\n            clap::Arg::new(\"path\")\n                .long(\"path\")\n                .action(ArgAction::Set)\n                .value_name(\"PATH\")\n                .help(\"Filesystem path to local crate to add\")\n                .group(\"selected\")\n                .conflicts_with(\"git\")\n                .add(clap_complete::engine::ArgValueCompleter::new(\n                    clap_complete::engine::PathCompleter::any()\n                        .filter(|path| path.join(\"Cargo.toml\").exists()),\n                )),\n            clap::Arg::new(\"base\")\n                .long(\"base\")\n                .action(ArgAction::Set)\n                .value_name(\"BASE\")\n                .help(\"The path base to use when adding from a local crate (unstable).\")\n                .requires(\"path\"),\n            clap::Arg::new(\"git\")\n                .long(\"git\")\n                .action(ArgAction::Set)\n                .value_name(\"URI\")\n                .help(\"Git repository location\")\n                .long_help(\"Git repository location\n\nWithout any other information, cargo will use latest commit on the main branch.\")\n                .group(\"selected\"),\n            clap::Arg::new(\"branch\")\n                .long(\"branch\")\n                .action(ArgAction::Set)\n                .value_name(\"BRANCH\")\n                .help(\"Git branch to download the crate from\")\n                .requires(\"git\")\n                .group(\"git-ref\"),\n            clap::Arg::new(\"tag\")\n                .long(\"tag\")\n                .action(ArgAction::Set)\n                .value_name(\"TAG\")\n                .help(\"Git tag to download the crate from\")\n                .requires(\"git\")\n                .group(\"git-ref\"),\n            clap::Arg::new(\"rev\")\n                .long(\"rev\")\n                .action(ArgAction::Set)\n                .value_name(\"REV\")\n                .help(\"Git reference to download the crate from\")\n                .long_help(\"Git reference to download the crate from\n\nThis is the catch all, handling hashes to named references in remote repositories.\")\n                .requires(\"git\")\n                .group(\"git-ref\"),\n            clap::Arg::new(\"registry\")\n                .long(\"registry\")\n                .action(ArgAction::Set)\n                .value_name(\"NAME\")\n                .help(\"Package registry for this dependency\")\n                .add(clap_complete::ArgValueCandidates::new(|| {\n                    let candidates = get_registry_candidates();\n                    candidates.unwrap_or_default()\n                })),\n        ])\n        .next_help_heading(\"Section\")\n        .args([\n            flag(\"dev\",\n                \"Add as development dependency\")\n                .long_help(\"Add as development dependency\n\nDev-dependencies are not used when compiling a package for building, but are used for compiling tests, examples, and benchmarks.\n\nThese dependencies are not propagated to other packages which depend on this package.\")\n                .group(\"section\"),\n            flag(\"build\",\n                \"Add as build dependency\")\n                .long_help(\"Add as build dependency\n\nBuild-dependencies are the only dependencies available for use by build scripts (`build.rs` files).\")\n                .group(\"section\"),\n            clap::Arg::new(\"target\")\n                .long(\"target\")\n                .action(ArgAction::Set)\n                .value_name(\"TARGET\")\n                .value_parser(clap::builder::NonEmptyStringValueParser::new())\n                .help(\"Add as dependency to the given target platform\")\n        ])\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let dry_run = args.dry_run();\n    let section = parse_section(args);\n\n    let ws = args.workspace(gctx)?;\n\n    if args.is_present_with_zero_values(\"package\") {\n        print_available_packages(&ws)?;\n    }\n\n    let packages = args.packages_from_flags()?;\n    let packages = packages.get_packages(&ws)?;\n    let spec = match packages.len() {\n        0 => {\n            return Err(CliError::new(\n                anyhow::format_err!(\n                    \"no packages selected to modify.  Please specify one with `-p <PKGID>`\"\n                ),\n                101,\n            ));\n        }\n        1 => packages[0],\n        _ => {\n            let names = packages.iter().map(|p| p.name()).collect::<Vec<_>>();\n            return Err(CliError::new(\n                anyhow::format_err!(\n                    \"`cargo add` could not determine which package to modify. \\\n                    Use the `--package` option to specify a package. \\n\\\n                    available packages: {}\",\n                    names.join(\", \")\n                ),\n                101,\n            ));\n        }\n    };\n\n    let dependencies = parse_dependencies(gctx, args)?;\n\n    let honor_rust_version = args.honor_rust_version();\n\n    let options = AddOptions {\n        gctx,\n        spec,\n        dependencies,\n        section,\n        dry_run,\n        honor_rust_version,\n    };\n    add(&ws, &options)?;\n\n    // Reload the workspace since we've changed dependencies\n    let ws = args.workspace(gctx)?;\n    resolve_ws(&ws, dry_run)?;\n\n    Ok(())\n}\n\nfn parse_dependencies(gctx: &GlobalContext, matches: &ArgMatches) -> CargoResult<Vec<DepOp>> {\n    let path = matches.get_one::<String>(\"path\");\n    let base = matches.get_one::<String>(\"base\");\n    let git = matches.get_one::<String>(\"git\");\n    let branch = matches.get_one::<String>(\"branch\");\n    let rev = matches.get_one::<String>(\"rev\");\n    let tag = matches.get_one::<String>(\"tag\");\n    let rename = matches.get_one::<String>(\"rename\");\n    let registry = match matches.registry(gctx)? {\n        Some(reg) if reg == CRATES_IO_REGISTRY => None,\n        reg => reg,\n    };\n    let default_features = default_features(matches);\n    let optional = optional(matches);\n    let public = public(matches);\n\n    let mut crates = matches\n        .get_many::<String>(\"crates\")\n        .into_iter()\n        .flatten()\n        .map(|c| (Some(c.clone()), None))\n        .collect::<IndexMap<_, _>>();\n\n    let mut infer_crate_name = false;\n\n    for (crate_name, _) in crates.iter() {\n        let crate_name = crate_name.as_ref().unwrap();\n\n        if let Some(toolchain) = crate_name.strip_prefix(\"+\") {\n            anyhow::bail!(\n                \"invalid character `+` in dependency name: `+{toolchain}`\n    Use `cargo +{toolchain} add` if you meant to use the `{toolchain}` toolchain.\"\n            );\n        }\n    }\n\n    if crates.is_empty() {\n        if path.is_some() || git.is_some() {\n            crates.insert(None, None);\n            infer_crate_name = true;\n        } else {\n            unreachable!(\"clap should ensure we have some source selected\");\n        }\n    }\n    for feature in matches\n        .get_many::<String>(\"features\")\n        .into_iter()\n        .flatten()\n        .map(String::as_str)\n        .flat_map(parse_feature)\n    {\n        let parsed_value = FeatureValue::new(feature.into());\n        match parsed_value {\n            FeatureValue::Feature(_) => {\n                if 1 < crates.len() {\n                    let candidates = crates\n                        .keys()\n                        .map(|c| {\n                            format!(\n                                \"`{}/{}`\",\n                                c.as_deref().expect(\"only none when there is 1\"),\n                                feature\n                            )\n                        })\n                        .collect::<Vec<_>>();\n                    anyhow::bail!(\n                        \"feature `{feature}` must be qualified by the dependency it's being activated for, like {}\",\n                        candidates.join(\", \")\n                    );\n                }\n                crates\n                    .first_mut()\n                    .expect(\"always at least one crate\")\n                    .1\n                    .get_or_insert_with(IndexSet::new)\n                    .insert(feature.to_owned());\n            }\n            FeatureValue::Dep { .. } => {\n                anyhow::bail!(\"feature `{feature}` is not allowed to use explicit `dep:` syntax\",)\n            }\n            FeatureValue::DepFeature {\n                dep_name,\n                dep_feature,\n                ..\n            } => {\n                if infer_crate_name {\n                    anyhow::bail!(\n                        \"`{feature}` is unsupported when inferring the crate name, use `{dep_feature}`\"\n                    );\n                }\n                if dep_feature.contains('/') {\n                    anyhow::bail!(\"multiple slashes in feature `{feature}` is not allowed\");\n                }\n                crates.get_mut(&Some(dep_name.as_str().to_owned())).ok_or_else(|| {\n                    anyhow::format_err!(\"feature `{dep_feature}` activated for crate `{dep_name}` but the crate wasn't specified\")\n                })?\n                    .get_or_insert_with(IndexSet::new)\n                    .insert(dep_feature.as_str().to_owned());\n            }\n        }\n    }\n\n    let mut deps: Vec<DepOp> = Vec::new();\n    for (crate_spec, features) in crates {\n        let dep = DepOp {\n            crate_spec,\n            rename: rename.map(String::from),\n            features,\n            default_features,\n            optional,\n            public,\n            registry: registry.clone(),\n            path: path.map(String::from),\n            base: base.map(String::from),\n            git: git.map(String::from),\n            branch: branch.map(String::from),\n            rev: rev.map(String::from),\n            tag: tag.map(String::from),\n        };\n        deps.push(dep);\n    }\n\n    if deps.len() > 1 && rename.is_some() {\n        anyhow::bail!(\"cannot specify multiple crates with `--rename`\");\n    }\n\n    Ok(deps)\n}\n\nfn default_features(matches: &ArgMatches) -> Option<bool> {\n    resolve_bool_arg(\n        matches.flag(\"default-features\"),\n        matches.flag(\"no-default-features\"),\n    )\n}\n\nfn optional(matches: &ArgMatches) -> Option<bool> {\n    resolve_bool_arg(matches.flag(\"optional\"), matches.flag(\"no-optional\"))\n}\n\nfn public(matches: &ArgMatches) -> Option<bool> {\n    resolve_bool_arg(matches.flag(\"public\"), matches.flag(\"no-public\"))\n}\n\nfn resolve_bool_arg(yes: bool, no: bool) -> Option<bool> {\n    match (yes, no) {\n        (true, false) => Some(true),\n        (false, true) => Some(false),\n        (false, false) => None,\n        (_, _) => unreachable!(\"clap should make this impossible\"),\n    }\n}\n\nfn parse_section(matches: &ArgMatches) -> DepTable {\n    let kind = if matches.flag(\"dev\") {\n        DepKind::Development\n    } else if matches.flag(\"build\") {\n        DepKind::Build\n    } else {\n        DepKind::Normal\n    };\n\n    let mut table = DepTable::new().set_kind(kind);\n\n    if let Some(target) = matches.get_one::<String>(\"target\") {\n        assert!(!target.is_empty(), \"Target specification may not be empty\");\n        table = table.set_target(target);\n    }\n\n    table\n}\n\n/// Split feature flag list\nfn parse_feature(feature: &str) -> impl Iterator<Item = &str> {\n    // Not re-using `CliFeatures` because it uses a BTreeSet and loses user's ordering\n    feature\n        .split_whitespace()\n        .flat_map(|s| s.split(','))\n        .filter(|s| !s.is_empty())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/bench.rs",
    "content": "use crate::command_prelude::*;\nuse cargo::ops::{self, TestOptions};\n\npub fn cli() -> Command {\n    subcommand(\"bench\")\n        .about(\"Execute all benchmarks of a local package\")\n        .next_display_order(0)\n        .arg(\n            Arg::new(\"BENCHNAME\")\n                .action(ArgAction::Set)\n                .help(\"If specified, only run benches containing this string in their names\"),\n        )\n        .arg(\n            Arg::new(\"args\")\n                .value_name(\"ARGS\")\n                .help(\"Arguments for the bench binary\")\n                .num_args(0..)\n                .last(true),\n        )\n        .arg(flag(\"no-run\", \"Compile, but don't run benchmarks\"))\n        .arg(flag(\n            \"no-fail-fast\",\n            \"Run all benchmarks regardless of failure\",\n        ))\n        .arg_message_format()\n        .arg_silent_suggestion()\n        .arg_package_spec(\n            \"Package to run benchmarks for\",\n            \"Benchmark all packages in the workspace\",\n            \"Exclude packages from the benchmark\",\n        )\n        .arg_targets_all(\n            \"Benchmark only this package's library\",\n            \"Benchmark only the specified binary\",\n            \"Benchmark all binaries\",\n            \"Benchmark only the specified example\",\n            \"Benchmark all examples\",\n            \"Benchmark only the specified test target\",\n            \"Benchmark all targets that have `test = true` set\",\n            \"Benchmark only the specified bench target\",\n            \"Benchmark all targets that have `bench = true` set\",\n            \"Benchmark all targets\",\n        )\n        .arg_features()\n        .arg_jobs()\n        .arg_unsupported_keep_going()\n        .arg_profile(\"Build artifacts with the specified profile\")\n        .arg_target_triple(\"Build for the target triple\")\n        .arg_target_dir()\n        .arg_unit_graph()\n        .arg_timings()\n        .arg_manifest_path()\n        .arg_ignore_rust_version()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help bench</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n\n    let mut compile_opts =\n        args.compile_options(gctx, UserIntent::Bench, Some(&ws), ProfileChecking::Custom)?;\n\n    compile_opts.build_config.requested_profile =\n        args.get_profile_name(\"bench\", ProfileChecking::Custom)?;\n\n    let ops = TestOptions {\n        no_run: args.flag(\"no-run\"),\n        no_fail_fast: args.flag(\"no-fail-fast\"),\n        compile_opts,\n    };\n\n    let bench_args = args.get_one::<String>(\"BENCHNAME\").into_iter();\n    let bench_args = bench_args.chain(args.get_many::<String>(\"args\").unwrap_or_default());\n    let bench_args = bench_args.map(String::as_str).collect::<Vec<_>>();\n\n    ops::run_benches(&ws, &ops, &bench_args)\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/build.rs",
    "content": "use crate::command_prelude::*;\n\nuse cargo::ops;\n\npub fn cli() -> Command {\n    subcommand(\"build\")\n        // subcommand aliases are handled in aliased_command()\n        // .alias(\"b\")\n        .about(\"Compile a local package and all of its dependencies\")\n        .arg_future_incompat_report()\n        .arg_message_format()\n        .arg_silent_suggestion()\n        .arg_package_spec(\n            \"Package to build (see `cargo help pkgid`)\",\n            \"Build all packages in the workspace\",\n            \"Exclude packages from the build\",\n        )\n        .arg_targets_all(\n            \"Build only this package's library\",\n            \"Build only the specified binary\",\n            \"Build all binaries\",\n            \"Build only the specified example\",\n            \"Build all examples\",\n            \"Build only the specified test target\",\n            \"Build all targets that have `test = true` set\",\n            \"Build only the specified bench target\",\n            \"Build all targets that have `bench = true` set\",\n            \"Build all targets\",\n        )\n        .arg_features()\n        .arg_release(\"Build artifacts in release mode, with optimizations\")\n        .arg_redundant_default_mode(\"debug\", \"build\", \"release\")\n        .arg_profile(\"Build artifacts with the specified profile\")\n        .arg_parallel()\n        .arg_target_triple(\"Build for the target triple\")\n        .arg_target_dir()\n        .arg_artifact_dir()\n        .arg_unit_graph()\n        .arg_timings()\n        .arg_compile_time_deps()\n        .arg_manifest_path()\n        .arg_ignore_rust_version()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help build</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n    let mut compile_opts =\n        args.compile_options(gctx, UserIntent::Build, Some(&ws), ProfileChecking::Custom)?;\n\n    if let Some(artifact_dir) = args.value_of_path(\"artifact-dir\", gctx) {\n        // If the user specifies `--artifact-dir`, use that\n        compile_opts.build_config.export_dir = Some(artifact_dir);\n    } else if let Some(artifact_dir) = gctx.build_config()?.artifact_dir.as_ref() {\n        // If a CLI option is not specified for choosing the artifact dir, use the `artifact-dir` from the build config, if\n        // present\n        let artifact_dir = artifact_dir.resolve_path(gctx);\n        compile_opts.build_config.export_dir = Some(artifact_dir);\n    }\n\n    if compile_opts.build_config.export_dir.is_some() {\n        gctx.cli_unstable()\n            .fail_if_stable_opt(\"--artifact-dir\", 6790)?;\n    }\n\n    ops::compile(&ws, &compile_opts)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/check.rs",
    "content": "use crate::command_prelude::*;\n\nuse cargo::ops;\n\npub fn cli() -> Command {\n    subcommand(\"check\")\n        // subcommand aliases are handled in aliased_command()\n        // .alias(\"c\")\n        .about(\"Check a local package and all of its dependencies for errors\")\n        .arg_future_incompat_report()\n        .arg_message_format()\n        .arg_silent_suggestion()\n        .arg_package_spec(\n            \"Package(s) to check\",\n            \"Check all packages in the workspace\",\n            \"Exclude packages from the check\",\n        )\n        .arg_targets_all(\n            \"Check only this package's library\",\n            \"Check only the specified binary\",\n            \"Check all binaries\",\n            \"Check only the specified example\",\n            \"Check all examples\",\n            \"Check only the specified test target\",\n            \"Check all targets that have `test = true` set\",\n            \"Check only the specified bench target\",\n            \"Check all targets that have `bench = true` set\",\n            \"Check all targets\",\n        )\n        .arg_features()\n        .arg_parallel()\n        .arg_release(\"Check artifacts in release mode, with optimizations\")\n        .arg_profile(\"Check artifacts with the specified profile\")\n        .arg_target_triple(\"Check for the target triple\")\n        .arg_target_dir()\n        .arg_unit_graph()\n        .arg_timings()\n        .arg_compile_time_deps()\n        .arg_manifest_path()\n        .arg_ignore_rust_version()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help check</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n    // This is a legacy behavior that causes `cargo check` to pass `--test`.\n    let test = matches!(\n        args.get_one::<String>(\"profile\").map(String::as_str),\n        Some(\"test\")\n    );\n    let intent = UserIntent::Check { test };\n    let compile_opts =\n        args.compile_options(gctx, intent, Some(&ws), ProfileChecking::LegacyTestOnly)?;\n\n    ops::compile(&ws, &compile_opts)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/clean.rs",
    "content": "use crate::command_prelude::*;\nuse crate::util::cache_lock::CacheLockMode;\nuse cargo::core::gc::Gc;\nuse cargo::core::gc::{GcOpts, parse_human_size, parse_time_span};\nuse cargo::core::global_cache_tracker::GlobalCacheTracker;\nuse cargo::ops::CleanContext;\nuse cargo::ops::{self, CleanOptions};\nuse cargo::util::print_available_packages;\nuse clap_complete::ArgValueCandidates;\nuse indexmap::IndexSet;\nuse std::time::Duration;\n\npub fn cli() -> Command {\n    subcommand(\"clean\")\n        .about(\"Remove artifacts that cargo has generated in the past\")\n        .arg_doc(\"Whether or not to clean just the documentation directory\")\n        .arg_silent_suggestion()\n        .arg_package_spec_simple(\n            \"Package to clean artifacts for\",\n            ArgValueCandidates::new(get_pkg_name_candidates),\n        )\n        .arg(\n            flag(\"workspace\", \"Clean artifacts of the workspace members\")\n                .help_heading(heading::PACKAGE_SELECTION),\n        )\n        .arg_release(\"Whether or not to clean release artifacts\")\n        .arg_profile(\"Clean artifacts of the specified profile\")\n        .arg_target_triple(\"Target triple to clean output for\")\n        .arg_target_dir()\n        .arg_manifest_path()\n        .arg_dry_run(\"Display what would be deleted without deleting anything\")\n        .args_conflicts_with_subcommands(true)\n        .subcommand(\n            subcommand(\"gc\")\n                .about(\"Clean global caches\")\n                .hide(true)\n                .arg_silent_suggestion()\n                .arg_dry_run(\"Display what would be deleted without deleting anything\")\n                // NOTE: Not all of these options may get stabilized. Some of them are\n                // very low-level details, and may not be something typical users need.\n                .arg(\n                    opt(\n                        \"max-src-age\",\n                        \"Deletes source cache files that have not been used \\\n                        since the given age (unstable)\",\n                    )\n                    .value_name(\"DURATION\")\n                    .value_parser(parse_time_span),\n                )\n                .arg(\n                    opt(\n                        \"max-crate-age\",\n                        \"Deletes crate cache files that have not been used \\\n                        since the given age (unstable)\",\n                    )\n                    .value_name(\"DURATION\")\n                    .value_parser(parse_time_span),\n                )\n                .arg(\n                    opt(\n                        \"max-index-age\",\n                        \"Deletes registry indexes that have not been used \\\n                        since the given age (unstable)\",\n                    )\n                    .value_name(\"DURATION\")\n                    .value_parser(parse_time_span),\n                )\n                .arg(\n                    opt(\n                        \"max-git-co-age\",\n                        \"Deletes git dependency checkouts that have not been used \\\n                        since the given age (unstable)\",\n                    )\n                    .value_name(\"DURATION\")\n                    .value_parser(parse_time_span),\n                )\n                .arg(\n                    opt(\n                        \"max-git-db-age\",\n                        \"Deletes git dependency clones that have not been used \\\n                        since the given age (unstable)\",\n                    )\n                    .value_name(\"DURATION\")\n                    .value_parser(parse_time_span),\n                )\n                .arg(\n                    opt(\n                        \"max-download-age\",\n                        \"Deletes any downloaded cache data that has not been used \\\n                        since the given age (unstable)\",\n                    )\n                    .value_name(\"DURATION\")\n                    .value_parser(parse_time_span),\n                )\n                .arg(\n                    opt(\n                        \"max-src-size\",\n                        \"Deletes source cache files until the cache is under the \\\n                        given size (unstable)\",\n                    )\n                    .value_name(\"SIZE\")\n                    .value_parser(parse_human_size),\n                )\n                .arg(\n                    opt(\n                        \"max-crate-size\",\n                        \"Deletes crate cache files until the cache is under the \\\n                        given size (unstable)\",\n                    )\n                    .value_name(\"SIZE\")\n                    .value_parser(parse_human_size),\n                )\n                .arg(\n                    opt(\n                        \"max-git-size\",\n                        \"Deletes git dependency caches until the cache is under \\\n                        the given size (unstable)\",\n                    )\n                    .value_name(\"SIZE\")\n                    .value_parser(parse_human_size),\n                )\n                .arg(\n                    opt(\n                        \"max-download-size\",\n                        \"Deletes downloaded cache data until the cache is under \\\n                        the given size (unstable)\",\n                    )\n                    .value_name(\"SIZE\")\n                    .value_parser(parse_human_size),\n                ),\n        )\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help clean</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    match args.subcommand() {\n        Some((\"gc\", args)) => {\n            return gc(gctx, args);\n        }\n        Some((cmd, _)) => {\n            unreachable!(\"unexpected command {}\", cmd)\n        }\n        None => {}\n    }\n\n    let ws = args.workspace(gctx)?;\n\n    if args.is_present_with_zero_values(\"package\") {\n        print_available_packages(&ws)?;\n    }\n    let mut spec = IndexSet::from_iter(values(args, \"package\"));\n\n    if args.flag(\"workspace\") {\n        spec.extend(ws.members().map(|package| package.name().to_string()))\n    };\n    let opts = CleanOptions {\n        gctx,\n        spec,\n        targets: args.targets()?,\n        requested_profile: args.get_profile_name(\"dev\", ProfileChecking::Custom)?,\n        profile_specified: args.contains_id(\"profile\") || args.flag(\"release\"),\n        doc: args.flag(\"doc\"),\n        dry_run: args.dry_run(),\n    };\n    ops::clean(&ws, &opts)?;\n    Ok(())\n}\n\nfn gc(gctx: &GlobalContext, args: &ArgMatches) -> CliResult {\n    gctx.cli_unstable().fail_if_stable_command(\n        gctx,\n        \"clean gc\",\n        12633,\n        \"gc\",\n        gctx.cli_unstable().gc,\n    )?;\n\n    let size_opt = |opt| -> Option<u64> { args.get_one::<u64>(opt).copied() };\n    let duration_opt = |opt| -> Option<Duration> { args.get_one::<Duration>(opt).copied() };\n    let mut gc_opts = GcOpts {\n        max_src_age: duration_opt(\"max-src-age\"),\n        max_crate_age: duration_opt(\"max-crate-age\"),\n        max_index_age: duration_opt(\"max-index-age\"),\n        max_git_co_age: duration_opt(\"max-git-co-age\"),\n        max_git_db_age: duration_opt(\"max-git-db-age\"),\n        max_src_size: size_opt(\"max-src-size\"),\n        max_crate_size: size_opt(\"max-crate-size\"),\n        max_git_size: size_opt(\"max-git-size\"),\n        max_download_size: size_opt(\"max-download-size\"),\n    };\n    if let Some(age) = duration_opt(\"max-download-age\") {\n        gc_opts.set_max_download_age(age);\n    }\n    // If the user sets any options, then only perform the options requested.\n    // If no options are set, do the default behavior.\n    if !gc_opts.is_download_cache_opt_set() {\n        gc_opts.update_for_auto_gc(gctx)?;\n    }\n\n    let _lock = gctx.acquire_package_cache_lock(CacheLockMode::MutateExclusive)?;\n    let mut cache_track = GlobalCacheTracker::new(&gctx)?;\n    let mut gc = Gc::new(gctx, &mut cache_track)?;\n    let mut clean_ctx = CleanContext::new(gctx);\n    clean_ctx.dry_run = args.dry_run();\n    gc.gc(&mut clean_ctx, &gc_opts)?;\n    clean_ctx.display_summary()?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/config.rs",
    "content": "use crate::command_prelude::*;\nuse cargo::ops::cargo_config;\n\npub fn cli() -> Command {\n    subcommand(\"config\")\n        .about(\"Inspect configuration values\")\n        .subcommand_required(true)\n        .arg_required_else_help(true)\n        .subcommand(\n            subcommand(\"get\")\n                .arg(\n                    Arg::new(\"key\")\n                        .action(ArgAction::Set)\n                        .help(\"The config key to display\"),\n                )\n                .arg(\n                    opt(\"format\", \"Display format\")\n                        .value_parser(cargo_config::ConfigFormat::POSSIBLE_VALUES)\n                        .default_value(\"toml\"),\n                )\n                .arg(flag(\n                    \"show-origin\",\n                    \"Display where the config value is defined\",\n                ))\n                .arg(\n                    opt(\"merged\", \"Whether or not to merge config values\")\n                        .value_parser([\"yes\", \"no\"])\n                        .default_value(\"yes\"),\n                ),\n        )\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    gctx.cli_unstable().fail_if_stable_command(\n        gctx,\n        \"config\",\n        9301,\n        \"unstable-options\",\n        gctx.cli_unstable().unstable_options,\n    )?;\n    match args.subcommand() {\n        Some((\"get\", args)) => {\n            let opts = cargo_config::GetOptions {\n                key: args.get_one::<String>(\"key\").map(String::as_str),\n                format: args.get_one::<String>(\"format\").unwrap().parse()?,\n                show_origin: args.flag(\"show-origin\"),\n                merged: args.get_one::<String>(\"merged\").map(String::as_str) == Some(\"yes\"),\n            };\n            cargo_config::get(gctx, &opts)?;\n        }\n        Some((cmd, _)) => {\n            unreachable!(\"unexpected command {}\", cmd)\n        }\n        None => {\n            unreachable!(\"unexpected command\")\n        }\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/doc.rs",
    "content": "use crate::command_prelude::*;\n\nuse cargo::ops::{self, DocOptions};\n\npub fn cli() -> Command {\n    subcommand(\"doc\")\n        // subcommand aliases are handled in aliased_command()\n        // .alias(\"d\")\n        .about(\"Build a package's documentation\")\n        .arg(flag(\n            \"open\",\n            \"Opens the docs in a browser after the operation\",\n        ))\n        .arg(flag(\n            \"no-deps\",\n            \"Don't build documentation for dependencies\",\n        ))\n        .arg(flag(\"document-private-items\", \"Document private items\"))\n        .arg_message_format()\n        .arg_silent_suggestion()\n        .arg_package_spec(\n            \"Package to document\",\n            \"Document all packages in the workspace\",\n            \"Exclude packages from the build\",\n        )\n        .arg_features()\n        .arg_targets_lib_bin_example(\n            \"Document only this package's library\",\n            \"Document only the specified binary\",\n            \"Document all binaries\",\n            \"Document only the specified example\",\n            \"Document all examples\",\n        )\n        .arg_parallel()\n        .arg_release(\"Build artifacts in release mode, with optimizations\")\n        .arg_profile(\"Build artifacts with the specified profile\")\n        .arg_target_triple(\"Build for the target triple\")\n        .arg_target_dir()\n        .arg_unit_graph()\n        .arg_timings()\n        .arg_manifest_path()\n        .arg_ignore_rust_version()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help doc</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n    let intent = UserIntent::Doc {\n        deps: !args.flag(\"no-deps\"),\n        json: false,\n    };\n    let mut compile_opts =\n        args.compile_options(gctx, intent, Some(&ws), ProfileChecking::Custom)?;\n    compile_opts.rustdoc_document_private_items = args.flag(\"document-private-items\");\n\n    let doc_opts = DocOptions {\n        open_result: args.flag(\"open\"),\n        output_format: ops::OutputFormat::Html,\n        compile_opts,\n    };\n    ops::doc(&ws, &doc_opts)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/fetch.rs",
    "content": "use crate::command_prelude::*;\n\nuse cargo::ops;\nuse cargo::ops::FetchOptions;\n\npub fn cli() -> Command {\n    subcommand(\"fetch\")\n        .about(\"Fetch dependencies of a package from the network\")\n        .arg_silent_suggestion()\n        .arg_target_triple(\"Fetch dependencies for the target triple\")\n        .arg_manifest_path()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help fetch</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n\n    let opts = FetchOptions {\n        gctx,\n        targets: args.targets()?,\n    };\n    let _ = ops::fetch(&ws, &opts)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/fix.rs",
    "content": "use crate::command_prelude::*;\nuse cargo::core::Workspace;\n\nuse cargo::ops;\n\npub fn cli() -> Command {\n    subcommand(\"fix\")\n        .about(\"Automatically fix lint warnings reported by rustc\")\n        .arg(flag(\"edition\", \"Fix in preparation for the next edition\"))\n        .arg(flag(\n            \"edition-idioms\",\n            \"Fix warnings to migrate to the idioms of an edition\",\n        ))\n        .arg(flag(\n            \"broken-code\",\n            \"Fix code even if it already has compiler errors\",\n        ))\n        .arg(flag(\n            \"allow-no-vcs\",\n            \"Fix code even if a VCS was not detected\",\n        ))\n        .arg(flag(\n            \"allow-dirty\",\n            \"Fix code even if the working directory is dirty or has staged changes\",\n        ))\n        .arg(flag(\n            \"allow-staged\",\n            \"Fix code even if the working directory has staged changes\",\n        ))\n        .arg_message_format()\n        .arg_silent_suggestion()\n        .arg_package_spec(\n            \"Package(s) to fix\",\n            \"Fix all packages in the workspace\",\n            \"Exclude packages from the fixes\",\n        )\n        .arg_targets_all(\n            \"Fix only this package's library\",\n            \"Fix only the specified binary\",\n            \"Fix all binaries\",\n            \"Fix only the specified example\",\n            \"Fix all examples\",\n            \"Fix only the specified test target\",\n            \"Fix all targets that have `test = true` set\",\n            \"Fix only the specified bench target\",\n            \"Fix all targets that have `bench = true` set\",\n            \"Fix all targets (default)\",\n        )\n        .arg_features()\n        .arg_parallel()\n        .arg_release(\"Fix artifacts in release mode, with optimizations\")\n        .arg_profile(\"Build artifacts with the specified profile\")\n        .arg_target_triple(\"Fix for the target triple\")\n        .arg_target_dir()\n        .arg_timings()\n        .arg_manifest_path()\n        .arg_ignore_rust_version()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help fix</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    // This is a legacy behavior that causes `cargo fix` to pass `--test`.\n    let test = matches!(\n        args.get_one::<String>(\"profile\").map(String::as_str),\n        Some(\"test\")\n    );\n    let intent = UserIntent::Check { test };\n\n    // Unlike other commands default `cargo fix` to all targets to fix as much\n    // code as we can.\n    let root_manifest = args.root_manifest(gctx)?;\n\n    // Can't use workspace() to avoid using -Zavoid-dev-deps (if passed)\n    let mut ws = Workspace::new(&root_manifest, gctx)?;\n    ws.set_resolve_honors_rust_version(args.honor_rust_version());\n\n    let mut opts =\n        args.compile_options(gctx, intent, Some(&ws), ProfileChecking::LegacyTestOnly)?;\n\n    let edition = args.flag(\"edition\") || args.flag(\"edition-idioms\");\n    if !opts.filter.is_specific() && edition {\n        // When `cargo fix` is run without specifying targets but with `--edition` or `--edition-idioms`,\n        // it should default to fixing all targets.\n        // See: https://github.com/rust-lang/cargo/issues/13527\n        opts.filter = ops::CompileFilter::new_all_targets();\n    }\n\n    let allow_dirty = args.flag(\"allow-dirty\");\n\n    let mut opts = ops::FixOptions {\n        edition: args\n            .flag(\"edition\")\n            .then_some(ops::EditionFixMode::NextRelative),\n        idioms: args.flag(\"edition-idioms\"),\n        compile_opts: opts,\n        allow_dirty,\n        allow_staged: allow_dirty || args.flag(\"allow-staged\"),\n        allow_no_vcs: args.flag(\"allow-no-vcs\"),\n        broken_code: args.flag(\"broken-code\"),\n    };\n\n    if let Some(fe) = &gctx.cli_unstable().fix_edition {\n        ops::fix_edition(gctx, &ws, &mut opts, fe)?;\n    } else {\n        ops::fix(gctx, &ws, &mut opts)?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/generate_lockfile.rs",
    "content": "use clap_complete::engine::ArgValueCompleter;\nuse clap_complete::engine::CompletionCandidate;\n\nuse crate::command_prelude::*;\n\nuse cargo::ops;\n\npub fn cli() -> Command {\n    subcommand(\"generate-lockfile\")\n        .about(\"Generate the lockfile for a package\")\n        .arg_silent_suggestion()\n        .arg_manifest_path()\n        .arg_ignore_rust_version_with_help(\"Ignore `rust-version` specification in packages\")\n        .arg(\n            clap::Arg::new(\"publish-time\")\n                .long(\"publish-time\")\n                .value_name(\"yyyy-mm-ddThh:mm:ssZ\")\n                .add(ArgValueCompleter::new(datetime_completer))\n                .help(\"Latest publish time allowed for registry packages (unstable)\")\n                .help_heading(heading::MANIFEST_OPTIONS)\n        )\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help generate-lockfile</>` for more detailed information.\\n\"\n        ))\n}\n\nfn datetime_completer(current: &std::ffi::OsStr) -> Vec<CompletionCandidate> {\n    let mut completions = vec![];\n    let Some(current) = current.to_str() else {\n        return completions;\n    };\n\n    if current.is_empty() {\n        // While not likely what people want, it can at least give them a starting point to edit\n        let timestamp = jiff::Timestamp::now();\n        completions.push(CompletionCandidate::new(timestamp.to_string()));\n    } else if let Ok(date) = current.parse::<jiff::civil::Date>() {\n        if let Ok(zoned) = jiff::Zoned::default().with().date(date).build() {\n            let timestamp = zoned.timestamp();\n            completions.push(CompletionCandidate::new(timestamp.to_string()));\n        }\n    }\n    completions\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let publish_time = args.get_one::<String>(\"publish-time\");\n    let mut ws = args.workspace(gctx)?;\n    if let Some(publish_time) = publish_time {\n        gctx.cli_unstable()\n            .fail_if_stable_opt(\"--publish-time\", 5221)?;\n        let publish_time =\n            cargo_util_schemas::index::parse_pubtime(publish_time).map_err(anyhow::Error::from)?;\n        ws.set_resolve_publish_time(publish_time);\n    }\n    ops::generate_lockfile(&ws)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/git_checkout.rs",
    "content": "//! Removed.\n\nuse crate::command_prelude::*;\n\nconst REMOVED: &str = \"The `git-checkout` command has been removed.\";\n\npub fn cli() -> Command {\n    subcommand(\"git-checkout\")\n        .about(\"REMOVED: This command has been removed\")\n        .hide(true)\n        .override_help(REMOVED)\n}\n\npub fn exec(_gctx: &mut GlobalContext, _args: &ArgMatches) -> CliResult {\n    Err(anyhow::format_err!(REMOVED).into())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/help.rs",
    "content": "use crate::aliased_command;\nuse crate::command_prelude::*;\n\nuse cargo::drop_println;\nuse cargo::util::errors::CargoResult;\nuse cargo_util::paths::resolve_executable;\nuse flate2::read::GzDecoder;\n\nuse std::ffi::OsStr;\nuse std::ffi::OsString;\nuse std::io::Read;\nuse std::io::Write;\nuse std::path::Path;\n\nconst COMPRESSED_MAN: &[u8] = include_bytes!(concat!(env!(\"OUT_DIR\"), \"/man.tgz\"));\n\npub fn cli() -> Command {\n    subcommand(\"help\")\n        .about(\"Displays help for a cargo command\")\n        .arg(\n            Arg::new(\"COMMAND\")\n                .num_args(1..)\n                .action(ArgAction::Append)\n                .add(clap_complete::ArgValueCandidates::new(\n                    get_completion_candidates,\n                )),\n        )\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let args_command = args\n        .get_many::<String>(\"COMMAND\")\n        .map(|vals| vals.map(String::as_str).collect::<Vec<_>>())\n        .unwrap_or_default();\n\n    if args_command.is_empty() {\n        let _ = crate::cli::cli(gctx).print_help();\n        return Ok(());\n    }\n\n    let cmd: String;\n    let lookup_parts: Vec<&str> = if args_command.len() == 1 {\n        // Expand alias first\n        let subcommand = args_command.first().unwrap();\n        match aliased_command(gctx, subcommand).ok().flatten() {\n            Some(argv) if argv.len() > 1 => {\n                // If this alias is more than a simple subcommand pass-through, show the alias.\n                let alias = argv.join(\" \");\n                drop_println!(gctx, \"`{}` is aliased to `{}`\", subcommand, alias);\n                return Ok(());\n            }\n            // Otherwise, resolve the alias into its subcommand.\n            Some(argv) => {\n                // An alias with an empty argv can be created via `\"empty-alias\" = \"\"`.\n                cmd = argv\n                    .into_iter()\n                    .next()\n                    .unwrap_or_else(|| subcommand.to_string());\n                vec![cmd.as_str()]\n            }\n            None => args_command.clone(),\n        }\n    } else {\n        args_command.clone()\n    };\n\n    match find_builtin_cmd(&lookup_parts) {\n        Ok(path) => {\n            let man_page_name = path.join(\"-\");\n            if try_help(&man_page_name)? {\n                return Ok(());\n            }\n            crate::execute_internal_subcommand(\n                gctx,\n                &[OsStr::new(&man_page_name), OsStr::new(\"--help\")],\n            )?;\n        }\n        Err(FindError::UnknownCommand(cmd)) => {\n            if lookup_parts.len() == 1 {\n                if let Some(man_page_name) = find_builtin_cmd_dash_joined(cmd) {\n                    if try_help(&man_page_name)? {\n                        return Ok(());\n                    }\n                    crate::execute_internal_subcommand(\n                        gctx,\n                        &[OsStr::new(&man_page_name), OsStr::new(\"--help\")],\n                    )?;\n                } else {\n                    crate::execute_external_subcommand(\n                        gctx,\n                        cmd,\n                        &[OsStr::new(cmd), OsStr::new(\"--help\")],\n                    )?;\n                }\n            } else {\n                let err = anyhow::format_err!(\n                    \"no such command: `{cmd}`\\n\\n\\\n                     help: view all installed commands with `cargo --list`\",\n                );\n                return Err(err.into());\n            }\n        }\n        Err(FindError::UnknownSubcommand {\n            valid_prefix,\n            invalid,\n        }) => {\n            let valid_prefix = valid_prefix.join(\" \");\n            let err = anyhow::format_err!(\n                \"no such command: `cargo {valid_prefix} {invalid}` \\n\\n\\\n                 help: view available subcommands with `cargo {valid_prefix} --help`\",\n            );\n            return Err(err.into());\n        }\n    }\n\n    Ok(())\n}\n\nfn try_help(subcommand: &str) -> CargoResult<bool> {\n    #[expect(\n        clippy::disallowed_methods,\n        reason = \"testing only, no reason for config support\"\n    )]\n    let force_help_text = std::env::var(\"__CARGO_TEST_FORCE_HELP_TXT\").is_ok();\n\n    if resolve_executable(Path::new(\"man\")).is_ok() && !force_help_text {\n        let Some(man) = extract_man(subcommand, \"1\") else {\n            return Ok(false);\n        };\n        write_and_spawn(subcommand, &man, \"man\")?;\n    } else {\n        let Some(txt) = extract_man(subcommand, \"txt\") else {\n            return Ok(false);\n        };\n        if force_help_text {\n            drop(std::io::stdout().write_all(&txt));\n        } else if resolve_executable(Path::new(\"less\")).is_ok() {\n            write_and_spawn(subcommand, &txt, \"less\")?;\n        } else if resolve_executable(Path::new(\"more\")).is_ok() {\n            write_and_spawn(subcommand, &txt, \"more\")?;\n        } else {\n            drop(std::io::stdout().write_all(&txt));\n        }\n    }\n    Ok(true)\n}\n\n/// Extracts the given man page from the compressed archive.\n///\n/// Returns None if the command wasn't found.\nfn extract_man(subcommand: &str, extension: &str) -> Option<Vec<u8>> {\n    let extract_name = OsString::from(format!(\"cargo-{}.{}\", subcommand, extension));\n    let gz = GzDecoder::new(COMPRESSED_MAN);\n    let mut ar = tar::Archive::new(gz);\n    // Unwraps should be safe here, since this is a static archive generated\n    // by our build script. It should never be an invalid format!\n    for entry in ar.entries().unwrap() {\n        let mut entry = entry.unwrap();\n        let path = entry.path().unwrap();\n        if path.file_name().unwrap() != extract_name {\n            continue;\n        }\n        let mut result = Vec::new();\n        entry.read_to_end(&mut result).unwrap();\n        return Some(result);\n    }\n    None\n}\n\n/// Write the contents of a man page to disk and spawn the given command to\n/// display it.\nfn write_and_spawn(name: &str, contents: &[u8], command: &str) -> CargoResult<()> {\n    let prefix = format!(\"cargo-{}.\", name);\n    let mut tmp = tempfile::Builder::new().prefix(&prefix).tempfile()?;\n    let f = tmp.as_file_mut();\n    f.write_all(contents)?;\n    f.flush()?;\n    let path = tmp.path();\n    // Use a path relative to the temp directory so that it can work on\n    // cygwin/msys systems which don't handle windows-style paths.\n    let mut relative_name = std::ffi::OsString::from(\"./\");\n    relative_name.push(path.file_name().unwrap());\n    let mut cmd = std::process::Command::new(command)\n        .arg(relative_name)\n        .current_dir(path.parent().unwrap())\n        .spawn()?;\n    drop(cmd.wait());\n    Ok(())\n}\n\nenum FindError<'a> {\n    /// The primary command was not found.\n    UnknownCommand(&'a str),\n    /// A subcommand in the path was not found.\n    UnknownSubcommand {\n        valid_prefix: Vec<&'a str>,\n        invalid: &'a str,\n    },\n}\n\n/// Finds a auiltin command.\nfn find_builtin_cmd<'a>(parts: &[&'a str]) -> Result<Vec<String>, FindError<'a>> {\n    let Some((first, rest)) = parts.split_first() else {\n        return Err(FindError::UnknownCommand(\"\"));\n    };\n\n    let builtins = super::builtin();\n\n    let Some(mut current) = builtins\n        .iter()\n        .find(|cmd| cmd.get_name() == *first || cmd.get_all_aliases().any(|a| a == *first))\n    else {\n        return Err(FindError::UnknownCommand(first));\n    };\n\n    let mut path = vec![current.get_name().to_string()];\n\n    for (i, &part) in rest.iter().enumerate() {\n        let next = current\n            .get_subcommands()\n            .find(|cmd| cmd.get_name() == part || cmd.get_all_aliases().any(|a| a == part));\n        if let Some(next) = next {\n            path.push(next.get_name().to_string());\n            current = next;\n        } else {\n            let valid_prefix = [*first]\n                .into_iter()\n                .chain(rest[..i].iter().copied())\n                .collect::<Vec<_>>();\n            return Err(FindError::UnknownSubcommand {\n                valid_prefix,\n                invalid: part,\n            });\n        };\n    }\n\n    Ok(path)\n}\n\nfn find_builtin_cmd_dash_joined(s: &str) -> Option<String> {\n    let builtins = super::builtin();\n\n    for cmd in builtins.iter() {\n        if let Some(result) = try_match_cmd(cmd, s) {\n            return Some(result);\n        }\n    }\n    None\n}\n\n/// Tries to match a single dash-joined argument against commands\nfn try_match_cmd(cmd: &Command, arg: &str) -> Option<String> {\n    let name = cmd.get_name();\n\n    if arg == name || cmd.get_all_aliases().any(|alias| alias == arg) {\n        return Some(name.to_string());\n    }\n\n    if let Some(rest) = arg.strip_prefix(name).and_then(|r| r.strip_prefix('-')) {\n        for cmd in cmd.get_subcommands() {\n            if let Some(sub_cmds) = try_match_cmd(cmd, rest) {\n                return Some(format!(\"{name}-{sub_cmds}\"));\n            }\n        }\n    }\n\n    for alias in cmd.get_all_aliases() {\n        if let Some(rest) = arg.strip_prefix(alias).and_then(|r| r.strip_prefix('-')) {\n            for cmd in cmd.get_subcommands() {\n                if let Some(sub_cmds) = try_match_cmd(cmd, rest) {\n                    return Some(format!(\"{name}-{sub_cmds}\"));\n                }\n            }\n        }\n    }\n\n    None\n}\n\n/// Returns dash-joined names for nested commands,\n/// so they can be completed as single tokens.\nfn get_completion_candidates() -> Vec<clap_complete::CompletionCandidate> {\n    fn walk(\n        cmd: Command,\n        prefix: Option<&String>,\n        candidates: &mut Vec<clap_complete::CompletionCandidate>,\n    ) {\n        let name = cmd.get_name();\n        let key = match prefix {\n            Some(prefix) => format!(\"{prefix}-{name}\"),\n            None => name.to_string(),\n        };\n\n        for cmd in cmd.get_subcommands() {\n            walk(cmd.clone(), Some(&key), candidates);\n        }\n\n        let candidate = clap_complete::CompletionCandidate::new(&key)\n            .help(cmd.get_about().cloned())\n            .hide(cmd.is_hide_set());\n        candidates.push(candidate);\n    }\n\n    let mut candidates = Vec::new();\n    for cmd in super::builtin() {\n        walk(cmd, None, &mut candidates);\n    }\n    candidates\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/info.rs",
    "content": "use anyhow::Context;\nuse cargo::ops::info;\nuse cargo::util::command_prelude::*;\nuse cargo_util_schemas::core::PackageIdSpec;\n\npub fn cli() -> Command {\n    Command::new(\"info\")\n        .about(\"Display information about a package\")\n        .arg(\n            Arg::new(\"package\")\n                .required(true)\n                .value_name(\"SPEC\")\n                .help_heading(heading::PACKAGE_SELECTION)\n                .help(\"Package to inspect\"),\n        )\n        .arg_index(\"Registry index URL to search packages in\")\n        .arg_registry(\"Registry to search packages in\")\n        .arg_silent_suggestion()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help info</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let package = args\n        .get_one::<String>(\"package\")\n        .map(String::as_str)\n        .unwrap();\n    let spec = PackageIdSpec::parse(package)\n        .with_context(|| format!(\"invalid package ID specification: `{package}`\"))?;\n\n    // Check if --registry or --index was explicitly provided\n    let explicit_registry = args._contains(\"registry\") || args._contains(\"index\");\n    let reg_or_index = args.registry_or_index(gctx)?;\n    info(&spec, gctx, reg_or_index, explicit_registry)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/init.rs",
    "content": "use crate::command_prelude::*;\n\nuse cargo::ops;\n\npub fn cli() -> Command {\n    subcommand(\"init\")\n        .about(\"Create a new cargo package in an existing directory\")\n        .arg(\n            Arg::new(\"path\")\n                .value_name(\"PATH\")\n                .action(ArgAction::Set)\n                .default_value(\".\"),\n        )\n        .arg_new_opts()\n        .arg_registry(\"Registry to use\")\n        .arg_silent_suggestion()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help init</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let opts = args.new_options(gctx)?;\n    ops::init(&opts, gctx)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/install.rs",
    "content": "use crate::command_prelude::*;\n\nuse anyhow::anyhow;\nuse anyhow::bail;\nuse anyhow::format_err;\nuse cargo::CargoResult;\nuse cargo::core::{GitReference, SourceId, Workspace};\nuse cargo::ops;\nuse cargo::util::IntoUrl;\nuse cargo::util::VersionExt;\nuse cargo_util_schemas::manifest::PackageName;\nuse itertools::Itertools;\nuse semver::VersionReq;\n\nuse cargo_util::paths;\n\npub fn cli() -> Command {\n    subcommand(\"install\")\n        .about(\"Install a Rust binary\")\n        .arg(\n            Arg::new(\"crate\")\n                .value_name(\"CRATE[@<VER>]\")\n                .help(\"Select the package from the given source\")\n                .value_parser(parse_crate)\n                .num_args(0..),\n        )\n        .arg(\n            opt(\"version\", \"Specify a version to install\")\n                .alias(\"vers\")\n                .value_name(\"VERSION\")\n                .value_parser(parse_semver_flag)\n                .requires(\"crate\"),\n        )\n        .arg(\n            opt(\"index\", \"Registry index to install from\")\n                .value_name(\"INDEX\")\n                .requires(\"crate\")\n                .conflicts_with_all(&[\"git\", \"path\", \"registry\"]),\n        )\n        .arg(\n            opt(\"registry\", \"Registry to use\")\n                .value_name(\"REGISTRY\")\n                .requires(\"crate\")\n                .conflicts_with_all(&[\"git\", \"path\", \"index\"]),\n        )\n        .arg(\n            opt(\"git\", \"Git URL to install the specified crate from\")\n                .value_name(\"URL\")\n                .conflicts_with_all(&[\"path\", \"index\", \"registry\"]),\n        )\n        .arg(\n            opt(\"branch\", \"Branch to use when installing from git\")\n                .value_name(\"BRANCH\")\n                .requires(\"git\"),\n        )\n        .arg(\n            opt(\"tag\", \"Tag to use when installing from git\")\n                .value_name(\"TAG\")\n                .requires(\"git\"),\n        )\n        .arg(\n            opt(\"rev\", \"Specific commit to use when installing from git\")\n                .value_name(\"SHA\")\n                .requires(\"git\"),\n        )\n        .arg(\n            opt(\"path\", \"Filesystem path to local crate to install from\")\n                .value_name(\"PATH\")\n                .conflicts_with_all(&[\"git\", \"index\", \"registry\"])\n                .add(clap_complete::engine::ArgValueCompleter::new(\n                    clap_complete::engine::PathCompleter::any()\n                        .filter(|path| path.join(\"Cargo.toml\").exists()),\n                )),\n        )\n        .arg(opt(\"root\", \"Directory to install packages into\").value_name(\"DIR\"))\n        .arg(flag(\"force\", \"Force overwriting existing crates or binaries\").short('f'))\n        .arg_dry_run(\"Perform all checks without installing (unstable)\")\n        .arg(flag(\"no-track\", \"Do not save tracking information\"))\n        .arg(flag(\n            \"list\",\n            \"List all installed packages and their versions\",\n        ))\n        .arg_ignore_rust_version()\n        .arg_message_format()\n        .arg_silent_suggestion()\n        .arg_targets_bins_examples(\n            \"Install only the specified binary\",\n            \"Install all binaries\",\n            \"Install only the specified example\",\n            \"Install all examples\",\n        )\n        .arg_features()\n        .arg_parallel()\n        .arg(\n            flag(\n                \"debug\",\n                \"Build in debug mode (with the 'dev' profile) instead of release mode\",\n            )\n            .conflicts_with(\"profile\"),\n        )\n        .arg_redundant_default_mode(\"release\", \"install\", \"debug\")\n        .arg_profile(\"Install artifacts with the specified profile\")\n        .arg_target_triple(\"Build for the target triple\")\n        .arg_target_dir()\n        .arg_timings()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help install</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let path = args.value_of_path(\"path\", gctx);\n    if let Some(path) = &path {\n        gctx.reload_rooted_at(path)?;\n    } else {\n        // TODO: Consider calling set_search_stop_path(home).\n        gctx.reload_rooted_at(gctx.home().clone().into_path_unlocked())?;\n    }\n\n    // In general, we try to avoid normalizing paths in Cargo,\n    // but in these particular cases we need it to fix rust-lang/cargo#10283.\n    // (Handle `SourceId::for_path` and `Workspace::new`,\n    // but not `GlobalContext::reload_rooted_at` which is always cwd)\n    let path = path.map(|p| paths::normalize_path(&p));\n\n    let version = args.get_one::<VersionReq>(\"version\");\n    let krates = args\n        .get_many::<CrateVersion>(\"crate\")\n        .unwrap_or_default()\n        .cloned()\n        .dedup_by(|x, y| x == y)\n        .map(|(krate, local_version)| resolve_crate(krate, local_version, version))\n        .collect::<crate::CargoResult<Vec<_>>>()?;\n\n    for (crate_name, _) in krates.iter() {\n        let package_name = PackageName::new(crate_name);\n        if !crate_name.contains(\"@\") && package_name.is_err() {\n            for (idx, ch) in crate_name.char_indices() {\n                if !(unicode_ident::is_xid_continue(ch) || ch == '-') {\n                    let mut suggested_crate_name = crate_name.to_string();\n                    suggested_crate_name.insert_str(idx, \"@\");\n                    if let Ok((_, Some(_))) = parse_crate(&suggested_crate_name.as_str()) {\n                        let err = package_name.unwrap_err();\n                        return Err(\n                            anyhow::format_err!(\"{err}\\n\\n\\\n                                help: if this is meant to be a package name followed by a version, insert an `@` like `{suggested_crate_name}`\").into());\n                    }\n                }\n            }\n        }\n\n        if let Some(toolchain) = crate_name.strip_prefix(\"+\") {\n            return Err(anyhow!(\n                \"invalid character `+` in package name: `+{toolchain}`\n    Use `cargo +{toolchain} install` if you meant to use the `{toolchain}` toolchain.\"\n            )\n            .into());\n        }\n\n        if let Ok(url) = crate_name.into_url() {\n            if matches!(url.scheme(), \"http\" | \"https\") {\n                return Err(anyhow!(\n                    \"invalid package name: `{url}`\n    Use `cargo install --git {url}` if you meant to install from a git repository.\"\n                )\n                .into());\n            }\n        }\n\n        if crate_name != \".\"\n            && let Err(e) = package_name\n        {\n            return Err(anyhow::format_err!(\"{e}\").into());\n        }\n    }\n\n    let mut from_cwd = false;\n\n    let source = if let Some(url) = args.get_one::<String>(\"git\") {\n        let url = url.into_url()?;\n        let gitref = if let Some(branch) = args.get_one::<String>(\"branch\") {\n            GitReference::Branch(branch.clone())\n        } else if let Some(tag) = args.get_one::<String>(\"tag\") {\n            GitReference::Tag(tag.clone())\n        } else if let Some(rev) = args.get_one::<String>(\"rev\") {\n            GitReference::Rev(rev.clone())\n        } else {\n            GitReference::DefaultBranch\n        };\n        SourceId::for_git(&url, gitref)?\n    } else if let Some(path) = &path {\n        SourceId::for_path(path)?\n    } else if krates.is_empty() {\n        from_cwd = true;\n        SourceId::for_path(gctx.cwd())?\n    } else if let Some(reg_or_index) = args.registry_or_index(gctx)? {\n        match reg_or_index {\n            ops::RegistryOrIndex::Registry(r) => SourceId::alt_registry(gctx, &r)?,\n            ops::RegistryOrIndex::Index(url) => SourceId::for_registry(&url)?,\n        }\n    } else {\n        SourceId::crates_io(gctx)?\n    };\n\n    let root = args.get_one::<String>(\"root\").map(String::as_str);\n\n    // We only provide workspace information for local crate installation from\n    // one of the following sources:\n    // - From current working directory (only work for edition 2015).\n    // - From a specific local file path (from `--path` arg).\n    //\n    // This workspace information is for emitting helpful messages from\n    // `ArgMatchesExt::compile_options` and won't affect the actual compilation.\n    let workspace = if from_cwd {\n        args.workspace(gctx).ok()\n    } else if let Some(path) = &path {\n        Workspace::new(&path.join(\"Cargo.toml\"), gctx).ok()\n    } else {\n        None\n    };\n\n    let mut compile_opts = args.compile_options(\n        gctx,\n        UserIntent::Build,\n        workspace.as_ref(),\n        ProfileChecking::Custom,\n    )?;\n\n    compile_opts.build_config.requested_profile =\n        args.get_profile_name(\"release\", ProfileChecking::Custom)?;\n    if args.dry_run() {\n        gctx.cli_unstable().fail_if_stable_opt(\"--dry-run\", 11123)?;\n    }\n\n    if args.flag(\"list\") {\n        ops::install_list(root, gctx)?;\n    } else {\n        ops::install(\n            gctx,\n            root,\n            krates,\n            source,\n            from_cwd,\n            &compile_opts,\n            args.flag(\"force\"),\n            args.flag(\"no-track\"),\n            args.dry_run(),\n        )?;\n    }\n    Ok(())\n}\n\ntype CrateVersion = (String, Option<VersionReq>);\n\nfn parse_crate(krate: &str) -> crate::CargoResult<CrateVersion> {\n    let (krate, version) = if let Some((k, v)) = krate.split_once('@') {\n        if k.is_empty() {\n            // by convention, arguments starting with `@` are response files\n            anyhow::bail!(\"missing crate name before '@'\");\n        }\n        let krate = k.to_owned();\n        let version = Some(parse_semver_flag(v)?);\n        (krate, version)\n    } else {\n        let krate = krate.to_owned();\n        let version = None;\n        (krate, version)\n    };\n\n    if krate.is_empty() {\n        anyhow::bail!(\"crate name is empty\");\n    }\n\n    Ok((krate, version))\n}\n\n/// Parses x.y.z as if it were =x.y.z, and gives CLI-specific error messages in the case of invalid\n/// values.\nfn parse_semver_flag(v: &str) -> CargoResult<VersionReq> {\n    // If the version begins with character <, >, =, ^, ~ parse it as a\n    // version range, otherwise parse it as a specific version\n    let first = v\n        .chars()\n        .next()\n        .ok_or_else(|| format_err!(\"no version provided for the `--version` flag\"))?;\n\n    if let Some(stripped) = v.strip_prefix(\"v\") {\n        bail!(\n            \"the version provided, `{v}` is not a valid SemVer requirement\\n\\n\\\n            help: try changing the version to `{stripped}`\",\n        )\n    }\n    let is_req = \"<>=^~\".contains(first) || v.contains('*');\n    if is_req {\n        match v.parse::<VersionReq>() {\n            Ok(v) => Ok(v),\n            Err(_) => bail!(\n                \"the `--version` provided, `{}`, is \\\n                     not a valid semver version requirement\\n\\n\\\n                     Please have a look at \\\n                     https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html \\\n                     for the correct format\",\n                v\n            ),\n        }\n    } else {\n        match v.trim().parse::<semver::Version>() {\n            Ok(v) => Ok(v.to_exact_req()),\n            Err(e) => {\n                let mut msg = e.to_string();\n\n                // If it is not a valid version but it is a valid version\n                // requirement, add a note to the warning\n                if v.parse::<VersionReq>().is_ok() {\n                    msg.push_str(&format!(\n                        \"\\n\\n  tip: if you want to specify SemVer range, \\\n                             add an explicit qualifier, like '^{}'\",\n                        v\n                    ));\n                }\n                bail!(msg);\n            }\n        }\n    }\n}\n\nfn resolve_crate(\n    krate: String,\n    local_version: Option<VersionReq>,\n    version: Option<&VersionReq>,\n) -> crate::CargoResult<CrateVersion> {\n    let version = match (local_version, version) {\n        (Some(_), Some(_)) => {\n            anyhow::bail!(\"cannot specify both `@<VERSION>` and `--version <VERSION>`\");\n        }\n        (Some(l), None) => Some(l),\n        (None, Some(g)) => Some(g.to_owned()),\n        (None, None) => None,\n    };\n    Ok((krate, version))\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/locate_project.rs",
    "content": "use crate::command_prelude::*;\nuse anyhow::bail;\nuse cargo::{CargoResult, drop_println};\nuse serde::Serialize;\n\npub fn cli() -> Command {\n    subcommand(\"locate-project\")\n        .about(\"Print a JSON representation of a Cargo.toml file's location\")\n        .arg(flag(\"workspace\", \"Locate Cargo.toml of the workspace root\"))\n        .arg(\n            opt(\"message-format\", \"Output representation\")\n                .value_name(\"FMT\")\n                .value_parser([\"json\", \"plain\"])\n                .ignore_case(true),\n        )\n        .arg_silent_suggestion()\n        .arg_manifest_path()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help locate-project</>` for more detailed information.\\n\"\n        ))\n}\n\n#[derive(Serialize)]\npub struct ProjectLocation<'a> {\n    root: &'a str,\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let root_manifest;\n    let workspace_root;\n    let workspace;\n    let root = match WhatToFind::parse(args) {\n        WhatToFind::CurrentManifest => {\n            root_manifest = args.root_manifest(gctx)?;\n            &root_manifest\n        }\n        WhatToFind::Workspace => {\n            root_manifest = args.root_manifest(gctx)?;\n            // Try fast path first - only works when package is explicitly listed in members\n            if let Some(ws_root) =\n                cargo::core::find_workspace_root_with_membership_check(&root_manifest, gctx)?\n            {\n                workspace_root = ws_root;\n                &workspace_root\n            } else {\n                // Fallback to full workspace loading for path dependency membership.\n                // If loading fails, we must propagate the error to avoid false results.\n                workspace = args.workspace(gctx)?;\n                workspace.root_manifest()\n            }\n        }\n    };\n\n    let root = root\n        .to_str()\n        .ok_or_else(|| {\n            anyhow::format_err!(\n                \"your package path contains characters \\\n                 not representable in Unicode\"\n            )\n        })\n        .map_err(|e| CliError::new(e, 1))?;\n\n    let location = ProjectLocation { root };\n\n    match MessageFormat::parse(args)? {\n        MessageFormat::Json => gctx.shell().print_json(&location)?,\n        MessageFormat::Plain => drop_println!(gctx, \"{}\", location.root),\n    }\n\n    Ok(())\n}\n\nenum WhatToFind {\n    CurrentManifest,\n    Workspace,\n}\n\nimpl WhatToFind {\n    fn parse(args: &ArgMatches) -> Self {\n        if args.flag(\"workspace\") {\n            WhatToFind::Workspace\n        } else {\n            WhatToFind::CurrentManifest\n        }\n    }\n}\n\nenum MessageFormat {\n    Json,\n    Plain,\n}\n\nimpl MessageFormat {\n    fn parse(args: &ArgMatches) -> CargoResult<Self> {\n        let fmt = match args.get_one::<String>(\"message-format\") {\n            Some(fmt) => fmt,\n            None => return Ok(MessageFormat::Json),\n        };\n        match fmt.to_ascii_lowercase().as_str() {\n            \"json\" => Ok(MessageFormat::Json),\n            \"plain\" => Ok(MessageFormat::Plain),\n            s => bail!(\"invalid message format specifier: `{}`\", s),\n        }\n    }\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/login.rs",
    "content": "use cargo::ops;\nuse cargo::ops::RegistryOrIndex;\n\nuse crate::command_prelude::*;\n\npub fn cli() -> Command {\n    subcommand(\"login\")\n        .about(\"Log in to a registry.\")\n        .arg(\n            Arg::new(\"token\")\n                .value_name(\"TOKEN\")\n                .action(ArgAction::Set)\n                .hide(true),\n        )\n        .arg_registry(\"Registry to use\")\n        .arg(\n            Arg::new(\"args\")\n                .help(\"Additional arguments for the credential provider\")\n                .num_args(0..)\n                .last(true),\n        )\n        .arg_silent_suggestion()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help login</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let reg = args.registry_or_index(gctx)?;\n    assert!(\n        !matches!(reg, Some(RegistryOrIndex::Index(..))),\n        \"must not be index URL\"\n    );\n\n    let token = args.get_one::<String>(\"token\").map(|s| s.as_str().into());\n    if token.is_some() {\n        let _ = gctx\n            .shell()\n            .warn(\"`cargo login <token>` is deprecated in favor of reading `<token>` from stdin\");\n    }\n\n    let extra_args = args\n        .get_many::<String>(\"args\")\n        .unwrap_or_default()\n        .map(String::as_str)\n        .collect::<Vec<_>>();\n    ops::registry_login(gctx, token, reg.as_ref(), &extra_args)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/logout.rs",
    "content": "use cargo::ops;\nuse cargo::ops::RegistryOrIndex;\n\nuse crate::command_prelude::*;\n\npub fn cli() -> Command {\n    subcommand(\"logout\")\n        .about(\"Remove an API token from the registry locally\")\n        .arg_registry(\"Registry to use\")\n        .arg_silent_suggestion()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help logout</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let reg = args.registry_or_index(gctx)?;\n    assert!(\n        !matches!(reg, Some(RegistryOrIndex::Index(..))),\n        \"must not be index URL\"\n    );\n\n    ops::registry_logout(gctx, reg)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/metadata.rs",
    "content": "use cargo::ops::{self, OutputMetadataOptions};\n\nuse crate::command_prelude::*;\n\npub fn cli() -> Command {\n    subcommand(\"metadata\")\n        .about(\n            \"Output the resolved dependencies of a package, \\\n             the concrete used versions including overrides, \\\n             in machine-readable format\",\n        )\n        .arg(multi_opt(\n            \"filter-platform\",\n            \"TRIPLE\",\n            \"Only include resolve dependencies matching the given target-triple\",\n        ))\n        .arg(flag(\n            \"no-deps\",\n            \"Output information only about the workspace members \\\n             and don't fetch dependencies\",\n        ))\n        .arg(\n            opt(\"format-version\", \"Format version\")\n                .value_name(\"VERSION\")\n                .value_parser([\"1\"]),\n        )\n        .arg_silent_suggestion()\n        .arg_features()\n        .arg_manifest_path()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help metadata</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n\n    let version = match args.get_one::<String>(\"format-version\") {\n        None => {\n            gctx.shell().warn(\n                \"please specify `--format-version` flag explicitly \\\n                 to avoid compatibility problems\",\n            )?;\n            1\n        }\n        Some(version) => version.parse().unwrap(),\n    };\n\n    let options = OutputMetadataOptions {\n        cli_features: args.cli_features()?,\n        no_deps: args.flag(\"no-deps\"),\n        filter_platforms: args._values_of(\"filter-platform\"),\n        version,\n    };\n\n    let result = ops::output_metadata(&ws, &options)?;\n    gctx.shell().print_json(&result)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/mod.rs",
    "content": "use crate::command_prelude::*;\n\npub fn builtin() -> Vec<Command> {\n    vec![\n        add::cli(),\n        bench::cli(),\n        build::cli(),\n        check::cli(),\n        clean::cli(),\n        config::cli(),\n        doc::cli(),\n        fetch::cli(),\n        fix::cli(),\n        generate_lockfile::cli(),\n        git_checkout::cli(),\n        help::cli(),\n        info::cli(),\n        init::cli(),\n        install::cli(),\n        locate_project::cli(),\n        login::cli(),\n        logout::cli(),\n        metadata::cli(),\n        new::cli(),\n        owner::cli(),\n        package::cli(),\n        pkgid::cli(),\n        publish::cli(),\n        read_manifest::cli(),\n        remove::cli(),\n        report::cli(),\n        run::cli(),\n        rustc::cli(),\n        rustdoc::cli(),\n        search::cli(),\n        test::cli(),\n        tree::cli(),\n        uninstall::cli(),\n        update::cli(),\n        vendor::cli(),\n        verify_project::cli(),\n        version::cli(),\n        yank::cli(),\n    ]\n}\n\npub type Exec = fn(&mut GlobalContext, &ArgMatches) -> CliResult;\n\npub fn builtin_exec(cmd: &str) -> Option<Exec> {\n    let f = match cmd {\n        \"add\" => add::exec,\n        \"bench\" => bench::exec,\n        \"build\" => build::exec,\n        \"check\" => check::exec,\n        \"clean\" => clean::exec,\n        \"config\" => config::exec,\n        \"doc\" => doc::exec,\n        \"fetch\" => fetch::exec,\n        \"fix\" => fix::exec,\n        \"generate-lockfile\" => generate_lockfile::exec,\n        \"git-checkout\" => git_checkout::exec,\n        \"help\" => help::exec,\n        \"info\" => info::exec,\n        \"init\" => init::exec,\n        \"install\" => install::exec,\n        \"locate-project\" => locate_project::exec,\n        \"login\" => login::exec,\n        \"logout\" => logout::exec,\n        \"metadata\" => metadata::exec,\n        \"new\" => new::exec,\n        \"owner\" => owner::exec,\n        \"package\" => package::exec,\n        \"pkgid\" => pkgid::exec,\n        \"publish\" => publish::exec,\n        \"read-manifest\" => read_manifest::exec,\n        \"remove\" => remove::exec,\n        \"report\" => report::exec,\n        \"run\" => run::exec,\n        \"rustc\" => rustc::exec,\n        \"rustdoc\" => rustdoc::exec,\n        \"search\" => search::exec,\n        \"test\" => test::exec,\n        \"tree\" => tree::exec,\n        \"uninstall\" => uninstall::exec,\n        \"update\" => update::exec,\n        \"vendor\" => vendor::exec,\n        \"verify-project\" => verify_project::exec,\n        \"version\" => version::exec,\n        \"yank\" => yank::exec,\n        _ => return None,\n    };\n    Some(f)\n}\n\npub mod add;\npub mod bench;\npub mod build;\npub mod check;\npub mod clean;\npub mod config;\npub mod doc;\npub mod fetch;\npub mod fix;\npub mod generate_lockfile;\npub mod git_checkout;\npub mod help;\npub mod info;\npub mod init;\npub mod install;\npub mod locate_project;\npub mod login;\npub mod logout;\npub mod metadata;\npub mod new;\npub mod owner;\npub mod package;\npub mod pkgid;\npub mod publish;\npub mod read_manifest;\npub mod remove;\npub mod report;\npub mod run;\npub mod rustc;\npub mod rustdoc;\npub mod search;\npub mod test;\npub mod tree;\npub mod uninstall;\npub mod update;\npub mod vendor;\npub mod verify_project;\npub mod version;\npub mod yank;\n"
  },
  {
    "path": "src/bin/cargo/commands/new.rs",
    "content": "use crate::command_prelude::*;\n\nuse cargo::ops;\n\npub fn cli() -> Command {\n    subcommand(\"new\")\n        .about(\"Create a new cargo package at <path>\")\n        .arg(\n            Arg::new(\"path\")\n                .value_name(\"PATH\")\n                .action(ArgAction::Set)\n                .required(true),\n        )\n        .arg_new_opts()\n        .arg_registry(\"Registry to use\")\n        .arg_silent_suggestion()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help new</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let opts = args.new_options(gctx)?;\n\n    ops::new(&opts, gctx)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/owner.rs",
    "content": "use crate::command_prelude::*;\n\nuse cargo::ops::{self, OwnersOptions};\nuse cargo_credential::Secret;\n\npub fn cli() -> Command {\n    subcommand(\"owner\")\n        .about(\"Manage the owners of a crate on the registry\")\n        .arg(Arg::new(\"crate\").value_name(\"CRATE\").action(ArgAction::Set))\n        .arg(\n            multi_opt(\n                \"add\",\n                \"LOGIN\",\n                \"Name of a user or team to invite as an owner\",\n            )\n            .short('a'),\n        )\n        .arg(\n            multi_opt(\n                \"remove\",\n                \"LOGIN\",\n                \"Name of a user or team to remove as an owner\",\n            )\n            .short('r'),\n        )\n        .arg(flag(\"list\", \"List owners of a crate\").short('l'))\n        .arg_index(\"Registry index URL to modify owners for\")\n        .arg_registry(\"Registry to modify owners for\")\n        .arg(opt(\"token\", \"API token to use when authenticating\").value_name(\"TOKEN\"))\n        .arg_silent_suggestion()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help owner</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let opts = OwnersOptions {\n        krate: args.get_one::<String>(\"crate\").cloned(),\n        token: args.get_one::<String>(\"token\").cloned().map(Secret::from),\n        reg_or_index: args.registry_or_index(gctx)?,\n        to_add: args\n            .get_many::<String>(\"add\")\n            .map(|xs| xs.cloned().collect()),\n        to_remove: args\n            .get_many::<String>(\"remove\")\n            .map(|xs| xs.cloned().collect()),\n        list: args.flag(\"list\"),\n    };\n    ops::modify_owners(gctx, &opts)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/package.rs",
    "content": "use crate::command_prelude::*;\n\nuse cargo::ops;\nuse cargo::ops::PackageMessageFormat;\nuse cargo::ops::PackageOpts;\nuse clap_complete::ArgValueCandidates;\n\npub fn cli() -> Command {\n    subcommand(\"package\")\n        .about(\"Assemble the local package into a distributable tarball\")\n        .arg_index(\"Registry index URL to prepare the package for\")\n        .arg_registry(\"Registry to prepare the package for\")\n        .arg(\n            flag(\n                \"list\",\n                \"Print files included in a package without making one\",\n            )\n            .short('l'),\n        )\n        .arg(flag(\n            \"no-verify\",\n            \"Don't verify the contents by building them\",\n        ))\n        .arg(flag(\n            \"no-metadata\",\n            \"Ignore warnings about a lack of human-usable metadata\",\n        ))\n        .arg(flag(\n            \"allow-dirty\",\n            \"Allow dirty working directories to be packaged\",\n        ))\n        .arg(flag(\n            \"exclude-lockfile\",\n            \"Don't include the lock file when packaging\",\n        ))\n        .arg(\n            opt(\"message-format\", \"Output representation (unstable)\")\n                .value_name(\"FMT\")\n                // This currently requires and only works with `--list`.\n                .requires(\"list\")\n                .value_parser(PackageMessageFormat::POSSIBLE_VALUES),\n        )\n        .arg_silent_suggestion()\n        .arg_package_spec_no_all(\n            \"Package(s) to assemble\",\n            \"Assemble all packages in the workspace\",\n            \"Don't assemble specified packages\",\n            ArgValueCandidates::new(get_ws_member_candidates),\n        )\n        .arg_features()\n        .arg_target_triple(\"Build for the target triple\")\n        .arg_target_dir()\n        .arg_parallel()\n        .arg_manifest_path()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help package</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let reg_or_index = args.registry_or_index(gctx)?;\n    let ws = args.workspace(gctx)?;\n    if ws.root_maybe().is_embedded() {\n        return Err(anyhow::format_err!(\n            \"{} is unsupported by `cargo package`\",\n            ws.root_manifest().display()\n        )\n        .into());\n    }\n    let specs = args.packages_from_flags()?;\n\n    let fmt = if let Some(fmt) = args._value_of(\"message-format\") {\n        gctx.cli_unstable()\n            .fail_if_stable_opt(\"--message-format\", 15353)?;\n        fmt.parse()?\n    } else {\n        PackageMessageFormat::Human\n    };\n\n    ops::package(\n        &ws,\n        &PackageOpts {\n            gctx,\n            verify: !args.flag(\"no-verify\"),\n            list: args.flag(\"list\"),\n            fmt,\n            check_metadata: !args.flag(\"no-metadata\"),\n            allow_dirty: args.flag(\"allow-dirty\"),\n            include_lockfile: !args.flag(\"exclude-lockfile\"),\n            to_package: specs,\n            targets: args.targets()?,\n            jobs: args.jobs()?,\n            keep_going: args.keep_going(),\n            cli_features: args.cli_features()?,\n            reg_or_index,\n            dry_run: false,\n        },\n    )?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/pkgid.rs",
    "content": "use crate::command_prelude::*;\n\nuse cargo::ops;\nuse cargo::util::print_available_packages;\n\npub fn cli() -> Command {\n    subcommand(\"pkgid\")\n        .about(\"Print a fully qualified package specification\")\n        .arg(Arg::new(\"spec\").value_name(\"SPEC\").action(ArgAction::Set))\n        .arg_silent_suggestion()\n        .arg_package(\"Argument to get the package ID specifier for\")\n        .arg_manifest_path()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help pkgid</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n    if args.is_present_with_zero_values(\"package\") {\n        print_available_packages(&ws)?\n    }\n    let spec = args\n        .get_one::<String>(\"spec\")\n        .or_else(|| args.get_one::<String>(\"package\"))\n        .map(String::as_str);\n    let spec = ops::pkgid(&ws, spec)?;\n    cargo::drop_println!(gctx, \"{}\", spec);\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/publish.rs",
    "content": "use crate::command_prelude::*;\n\nuse cargo::ops::{self, PublishOpts};\nuse cargo_credential::Secret;\nuse clap_complete::ArgValueCandidates;\n\npub fn cli() -> Command {\n    subcommand(\"publish\")\n        .about(\"Upload a package to the registry\")\n        .arg_dry_run(\"Perform all checks without uploading\")\n        .arg_index(\"Registry index URL to upload the package to\")\n        .arg_registry(\"Registry to upload the package to\")\n        .arg(\n            opt(\"token\", \"Token to use when uploading\")\n                .value_name(\"TOKEN\")\n                .hide(true),\n        )\n        .arg(flag(\n            \"no-verify\",\n            \"Don't verify the contents by building them\",\n        ))\n        .arg(flag(\n            \"allow-dirty\",\n            \"Allow dirty working directories to be packaged\",\n        ))\n        .arg_silent_suggestion()\n        .arg_package_spec_no_all(\n            \"Package(s) to publish\",\n            \"Publish all packages in the workspace\",\n            \"Don't publish specified packages\",\n            ArgValueCandidates::new(get_ws_member_candidates),\n        )\n        .arg_features()\n        .arg_parallel()\n        .arg_target_triple(\"Build for the target triple\")\n        .arg_target_dir()\n        .arg_manifest_path()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help publish</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let reg_or_index = args.registry_or_index(gctx)?;\n    let ws = args.workspace(gctx)?;\n    if ws.root_maybe().is_embedded() {\n        return Err(anyhow::format_err!(\n            \"{} is unsupported by `cargo publish`\",\n            ws.root_manifest().display()\n        )\n        .into());\n    }\n\n    let token = args.get_one::<String>(\"token\").cloned().map(Secret::from);\n    if token.is_some() {\n        let _ = gctx.shell().warn(\"`cargo publish --token` is deprecated in favor of using `cargo login` and environment variables\");\n    }\n\n    ops::publish(\n        &ws,\n        &PublishOpts {\n            gctx,\n            token,\n            reg_or_index,\n            verify: !args.flag(\"no-verify\"),\n            allow_dirty: args.flag(\"allow-dirty\"),\n            to_publish: args.packages_from_flags()?,\n            targets: args.targets()?,\n            jobs: args.jobs()?,\n            keep_going: args.keep_going(),\n            dry_run: args.dry_run(),\n            cli_features: args.cli_features()?,\n        },\n    )?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/read_manifest.rs",
    "content": "//! Deprecated.\n\nuse crate::command_prelude::*;\n\npub fn cli() -> Command {\n    subcommand(\"read-manifest\")\n        .hide(true)\n        .about(color_print::cstr!(\n            \"\\\nDEPRECATED: Print a JSON representation of a Cargo.toml manifest.\n\nUse `<bright-cyan,bold>cargo metadata --no-deps</>` instead.\\\n\"\n        ))\n        .arg_silent_suggestion()\n        .arg_manifest_path()\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n    gctx.shell().print_json(\n        &ws.current()?\n            .serialized(gctx.cli_unstable(), ws.unstable_features()),\n    )?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/remove.rs",
    "content": "use cargo::CargoResult;\nuse cargo::core::PackageIdSpec;\nuse cargo::core::PackageIdSpecQuery;\nuse cargo::core::Resolve;\nuse cargo::core::Workspace;\nuse cargo::core::dependency::DepKind;\nuse cargo::ops::cargo_remove::RemoveOptions;\nuse cargo::ops::cargo_remove::remove;\nuse cargo::ops::resolve_ws;\nuse cargo::util::command_prelude::*;\nuse cargo::util::print_available_packages;\nuse cargo::util::toml_mut::dependency::Dependency;\nuse cargo::util::toml_mut::dependency::MaybeWorkspace;\nuse cargo::util::toml_mut::dependency::Source;\nuse cargo::util::toml_mut::manifest::DepTable;\nuse cargo::util::toml_mut::manifest::LocalManifest;\n\npub fn cli() -> clap::Command {\n    clap::Command::new(\"remove\")\n        // Subcommand aliases are handled in `aliased_command()`.\n        // .alias(\"rm\")\n        .about(\"Remove dependencies from a Cargo.toml manifest file\")\n        .args([clap::Arg::new(\"dependencies\")\n            .action(clap::ArgAction::Append)\n            .required(true)\n            .num_args(1..)\n            .value_name(\"DEP_ID\")\n            .help(\"Dependencies to be removed\")\n            .add(clap_complete::ArgValueCandidates::new(\n                get_direct_dependencies_pkg_name_candidates,\n            ))])\n        .arg_dry_run(\"Don't actually write the manifest\")\n        .arg_silent_suggestion()\n        .next_help_heading(\"Section\")\n        .args([\n            clap::Arg::new(\"dev\")\n                .long(\"dev\")\n                .conflicts_with(\"build\")\n                .action(clap::ArgAction::SetTrue)\n                .group(\"section\")\n                .help(\"Remove from dev-dependencies\"),\n            clap::Arg::new(\"build\")\n                .long(\"build\")\n                .conflicts_with(\"dev\")\n                .action(clap::ArgAction::SetTrue)\n                .group(\"section\")\n                .help(\"Remove from build-dependencies\"),\n            clap::Arg::new(\"target\")\n                .long(\"target\")\n                .num_args(1)\n                .value_name(\"TARGET\")\n                .value_parser(clap::builder::NonEmptyStringValueParser::new())\n                .help(\"Remove from target-dependencies\"),\n        ])\n        .arg_package(\"Package to remove from\")\n        .arg_manifest_path()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help remove</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let dry_run = args.dry_run();\n\n    let workspace = args.workspace(gctx)?;\n\n    if args.is_present_with_zero_values(\"package\") {\n        print_available_packages(&workspace)?;\n    }\n\n    let packages = args.packages_from_flags()?;\n    let packages = packages.get_packages(&workspace)?;\n    let spec = match packages.len() {\n        0 => {\n            return Err(CliError::new(\n                anyhow::format_err!(\n                    \"no package selected to modify\nhelp: specify a package with `-p <PKGID>`\"\n                ),\n                101,\n            ));\n        }\n        1 => packages[0],\n        _ => {\n            let names = packages.iter().map(|p| p.name()).collect::<Vec<_>>();\n            return Err(CliError::new(\n                anyhow::format_err!(\n                    \"no package selected to modify\nhelp: specify a package with `-p <PKGID>`\n      available packages: {}\",\n                    names.join(\", \")\n                ),\n                101,\n            ));\n        }\n    };\n\n    let dependencies = args\n        .get_many::<String>(\"dependencies\")\n        .expect(\"required(true)\")\n        .cloned()\n        .collect::<Vec<_>>();\n\n    let section = parse_section(args);\n\n    let options = RemoveOptions {\n        gctx,\n        spec,\n        dependencies,\n        section,\n        dry_run,\n    };\n    remove(&options)?;\n\n    if !dry_run {\n        // Clean up the workspace\n        gc_workspace(&workspace)?;\n\n        // Reload the workspace since we've changed dependencies\n        let ws = args.workspace(gctx)?;\n        let resolve = {\n            // HACK: Avoid unused patch warnings by temporarily changing the verbosity.\n            // In rare cases, this might cause index update messages to not show up\n            let verbosity = ws.gctx().shell().verbosity();\n            ws.gctx()\n                .shell()\n                .set_verbosity(cargo::core::Verbosity::Quiet);\n            let resolve = resolve_ws(&ws, dry_run);\n            ws.gctx().shell().set_verbosity(verbosity);\n            resolve?.1\n        };\n\n        // Attempt to gc unused patches and re-resolve if anything is removed\n        if gc_unused_patches(&workspace, &resolve)? {\n            let ws = args.workspace(gctx)?;\n            resolve_ws(&ws, dry_run)?;\n        }\n    }\n    Ok(())\n}\n\nfn parse_section(args: &ArgMatches) -> DepTable {\n    let dev = args.flag(\"dev\");\n    let build = args.flag(\"build\");\n\n    let kind = if dev {\n        DepKind::Development\n    } else if build {\n        DepKind::Build\n    } else {\n        DepKind::Normal\n    };\n\n    let mut table = DepTable::new().set_kind(kind);\n\n    if let Some(target) = args.get_one::<String>(\"target\") {\n        assert!(!target.is_empty(), \"Target specification may not be empty\");\n        table = table.set_target(target);\n    }\n\n    table\n}\n\n/// Clean up the workspace.dependencies, profile, patch, and replace sections of the root manifest\n/// by removing dependencies which no longer have a reference to them.\nfn gc_workspace(workspace: &Workspace<'_>) -> CargoResult<()> {\n    let mut workspace_manifest = LocalManifest::try_new(workspace.root_manifest())?;\n    let mut is_modified = true;\n\n    let members = workspace\n        .members()\n        .map(|p| {\n            Ok((\n                LocalManifest::try_new(p.manifest_path())?,\n                p.manifest().unstable_features(),\n            ))\n        })\n        .collect::<CargoResult<Vec<_>>>()?;\n\n    let mut dependencies = members\n        .into_iter()\n        .flat_map(|(member_manifest, unstable_features)| {\n            member_manifest\n                .get_sections()\n                .into_iter()\n                .flat_map(move |(_, table)| {\n                    table\n                        .as_table_like()\n                        .unwrap()\n                        .iter()\n                        .map(|(key, item)| {\n                            Dependency::from_toml(\n                                workspace.gctx(),\n                                workspace.root(),\n                                &member_manifest.path,\n                                &unstable_features,\n                                key,\n                                item,\n                            )\n                        })\n                        .collect::<Vec<_>>()\n                })\n        })\n        .collect::<CargoResult<Vec<_>>>()?;\n\n    // Clean up the workspace.dependencies section and replace instances of\n    // workspace dependencies with their definitions\n    if let Some(toml_edit::Item::Table(deps_table)) = workspace_manifest\n        .data\n        .get_mut(\"workspace\")\n        .and_then(|t| t.get_mut(\"dependencies\"))\n    {\n        deps_table.set_implicit(true);\n        for (key, item) in deps_table.iter_mut() {\n            let ws_dep = Dependency::from_toml(\n                workspace.gctx(),\n                workspace.root(),\n                &workspace.root(),\n                workspace.unstable_features(),\n                key.get(),\n                item,\n            )?;\n\n            // search for uses of this workspace dependency\n            let mut is_used = false;\n            for dep in dependencies.iter_mut().filter(|d| {\n                d.toml_key() == key.get() && matches!(d.source(), Some(Source::Workspace(_)))\n            }) {\n                // HACK: Replace workspace references in `dependencies` to simplify later GC steps:\n                // 1. Avoid having to look it up again to determine the dependency source / spec\n                // 2. The entry might get deleted, preventing us from looking it up again\n                //\n                // This does lose extra information, like features enabled, but that shouldn't be a\n                // problem for GC\n                *dep = ws_dep.clone();\n\n                is_used = true;\n            }\n\n            if !is_used {\n                *item = toml_edit::Item::None;\n                is_modified = true;\n            }\n        }\n    }\n\n    // Clean up the profile section\n    //\n    // Example tables:\n    // - profile.dev.package.foo\n    // - profile.release.package.\"foo:2.1.0\"\n    if let Some(toml_edit::Item::Table(profile_section_table)) =\n        workspace_manifest.data.get_mut(\"profile\")\n    {\n        profile_section_table.set_implicit(true);\n\n        for (_, item) in profile_section_table.iter_mut() {\n            if let toml_edit::Item::Table(profile_table) = item {\n                profile_table.set_implicit(true);\n\n                if let Some(toml_edit::Item::Table(package_table)) =\n                    profile_table.get_mut(\"package\")\n                {\n                    package_table.set_implicit(true);\n\n                    for (key, item) in package_table.iter_mut() {\n                        let key = key.get();\n                        // Skip globs. Can't do anything with them.\n                        // For example, profile.release.package.\"*\".\n                        if crate::util::restricted_names::is_glob_pattern(key) {\n                            continue;\n                        }\n                        if !spec_has_match(\n                            &PackageIdSpec::parse(key)?,\n                            &dependencies,\n                            workspace.gctx(),\n                        )? {\n                            *item = toml_edit::Item::None;\n                            is_modified = true;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Clean up the replace section\n    if let Some(toml_edit::Item::Table(table)) = workspace_manifest.data.get_mut(\"replace\") {\n        table.set_implicit(true);\n\n        for (key, item) in table.iter_mut() {\n            if !spec_has_match(\n                &PackageIdSpec::parse(key.get())?,\n                &dependencies,\n                workspace.gctx(),\n            )? {\n                *item = toml_edit::Item::None;\n                is_modified = true;\n            }\n        }\n    }\n\n    if is_modified {\n        workspace_manifest.write()?;\n    }\n\n    Ok(())\n}\n\n/// Check whether or not a package ID spec matches any non-workspace dependencies.\nfn spec_has_match(\n    spec: &PackageIdSpec,\n    dependencies: &[Dependency],\n    gctx: &GlobalContext,\n) -> CargoResult<bool> {\n    for dep in dependencies {\n        if spec.name() != &dep.name {\n            continue;\n        }\n\n        let version_matches = match (spec.version(), dep.version()) {\n            (Some(v), Some(vq)) => semver::VersionReq::parse(vq)?.matches(&v),\n            (Some(_), None) => false,\n            (None, None | Some(_)) => true,\n        };\n        if !version_matches {\n            continue;\n        }\n\n        match dep.source_id(gctx)? {\n            MaybeWorkspace::Other(source_id) => {\n                if spec.url().map(|u| u == source_id.url()).unwrap_or(true) {\n                    return Ok(true);\n                }\n            }\n            MaybeWorkspace::Workspace(_) => {}\n        }\n    }\n\n    Ok(false)\n}\n\n/// Removes unused patches from the manifest\nfn gc_unused_patches(workspace: &Workspace<'_>, resolve: &Resolve) -> CargoResult<bool> {\n    let mut workspace_manifest = LocalManifest::try_new(workspace.root_manifest())?;\n    let mut modified = false;\n\n    // Clean up the patch section\n    if let Some(toml_edit::Item::Table(patch_section_table)) =\n        workspace_manifest.data.get_mut(\"patch\")\n    {\n        patch_section_table.set_implicit(true);\n\n        for (_, item) in patch_section_table.iter_mut() {\n            if let toml_edit::Item::Table(patch_table) = item {\n                patch_table.set_implicit(true);\n\n                for (key, item) in patch_table.iter_mut() {\n                    let dep = Dependency::from_toml(\n                        workspace.gctx(),\n                        workspace.root(),\n                        &workspace.root_manifest(),\n                        workspace.unstable_features(),\n                        key.get(),\n                        item,\n                    )?;\n\n                    // Generate a PackageIdSpec url for querying\n                    let url = if let MaybeWorkspace::Other(source_id) =\n                        dep.source_id(workspace.gctx())?\n                    {\n                        format!(\"{}#{}\", source_id.url(), dep.name)\n                    } else {\n                        continue;\n                    };\n\n                    if PackageIdSpec::query_str(&url, resolve.unused_patches().iter().cloned())\n                        .is_ok()\n                    {\n                        *item = toml_edit::Item::None;\n                        modified = true;\n                    }\n                }\n            }\n        }\n    }\n\n    if modified {\n        workspace_manifest.write()?;\n    }\n\n    Ok(modified)\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/report.rs",
    "content": "use crate::command_prelude::*;\n\nuse cargo::CargoResult;\nuse cargo::core::compiler::future_incompat::OnDiskReports;\nuse cargo::core::compiler::future_incompat::REPORT_PREAMBLE;\nuse cargo::drop_println;\nuse cargo::ops;\n\npub fn cli() -> Command {\n    subcommand(\"report\")\n        .about(\"Generate and display various kinds of reports\")\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help report</>` for more detailed information.\\n\"\n        ))\n        .subcommand_required(true)\n        .arg_required_else_help(true)\n        .subcommand(\n            subcommand(\"future-incompatibilities\")\n                .alias(\"future-incompat\")\n                .about(\"Reports any crates which will eventually stop compiling\")\n                .arg(\n                    opt(\n                        \"id\",\n                        \"identifier of the report generated by a Cargo command invocation\",\n                    )\n                    .value_name(\"id\"),\n                )\n                .arg_package(\"Package to display a report for\")\n                .after_help(color_print::cstr!(\n                    \"Run `<bright-cyan,bold>cargo help report future-incompatibilities</>` for more detailed information.\\n\"\n                )),\n        )\n        .subcommand(\n            subcommand(\"timings\")\n                .about(\"Reports the build timings of previous sessions (unstable)\")\n                .arg_manifest_path()\n                .arg(flag(\"open\", \"Opens the timing report in a browser\"))\n                .arg(opt(\"id\", \"Session ID to report on\").value_name(\"ID\")),\n        )\n        .subcommand(\n            subcommand(\"sessions\")\n                .about(\"Reports the previous sessions (unstable)\")\n                .arg_manifest_path()\n                .arg(\n                    opt(\"limit\", \"Limit the number of results\")\n                        .value_name(\"N\")\n                        .value_parser(clap::value_parser!(u64).range(1..))\n                        .default_value(\"10\"),\n                ),\n        )\n        .subcommand(\n            subcommand(\"rebuilds\")\n                .about(\"Reports rebuild reasons from previous sessions (unstable)\")\n                .arg_manifest_path()\n                .arg(opt(\"id\", \"Session ID to report on\").value_name(\"ID\")),\n        )\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    match args.subcommand() {\n        Some((\"future-incompatibilities\", args)) => report_future_incompatibilities(gctx, args),\n        Some((\"timings\", args)) => {\n            gctx.cli_unstable().fail_if_stable_command(\n                gctx,\n                \"report timings\",\n                15844,\n                \"build-analysis\",\n                gctx.cli_unstable().build_analysis,\n            )?;\n            let opts = timings_opts(gctx, args)?;\n            let ws = args.workspace(gctx).ok();\n            ops::report_timings(gctx, ws.as_ref(), opts)?;\n            Ok(())\n        }\n        Some((\"sessions\", args)) => {\n            gctx.cli_unstable().fail_if_stable_command(\n                gctx,\n                \"report sessions\",\n                15844,\n                \"build-analysis\",\n                gctx.cli_unstable().build_analysis,\n            )?;\n            let ws = args.workspace(gctx).ok();\n            let opts = sessions_opts(args)?;\n            ops::report_sessions(gctx, ws.as_ref(), opts)?;\n            Ok(())\n        }\n        Some((\"rebuilds\", args)) => {\n            gctx.cli_unstable().fail_if_stable_command(\n                gctx,\n                \"report rebuilds\",\n                15844,\n                \"build-analysis\",\n                gctx.cli_unstable().build_analysis,\n            )?;\n            let ws = args.workspace(gctx).ok();\n            let opts = rebuilds_opts(args)?;\n            ops::report_rebuilds(gctx, ws.as_ref(), opts)?;\n            Ok(())\n        }\n        Some((cmd, _)) => {\n            unreachable!(\"unexpected command {}\", cmd)\n        }\n        None => {\n            unreachable!(\"unexpected command\")\n        }\n    }\n}\n\nfn report_future_incompatibilities(gctx: &GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n    let reports = OnDiskReports::load(&ws)?;\n    let id = args\n        .value_of_u32(\"id\")?\n        .unwrap_or_else(|| reports.last_id());\n    let krate = args.get_one::<String>(\"package\").map(String::as_str);\n    let report = reports.get_report(id, krate)?;\n    drop_println!(gctx, \"{}\", REPORT_PREAMBLE);\n    drop(gctx.shell().print_ansi_stdout(report.as_bytes()));\n    Ok(())\n}\n\nfn timings_opts<'a>(\n    gctx: &'a GlobalContext,\n    args: &ArgMatches,\n) -> CargoResult<ops::ReportTimingsOptions<'a>> {\n    let open_result = args.get_flag(\"open\");\n    let id = args\n        .get_one::<String>(\"id\")\n        .map(|s| s.parse())\n        .transpose()?;\n\n    Ok(ops::ReportTimingsOptions {\n        open_result,\n        gctx,\n        id,\n    })\n}\n\nfn sessions_opts(args: &ArgMatches) -> CargoResult<ops::ReportSessionsOptions> {\n    let limit = *args.get_one::<u64>(\"limit\").unwrap_or(&10);\n    let limit = limit.min(usize::MAX as u64) as usize;\n\n    Ok(ops::ReportSessionsOptions { limit })\n}\n\nfn rebuilds_opts(args: &ArgMatches) -> CargoResult<ops::ReportRebuildsOptions> {\n    let id = args\n        .get_one::<String>(\"id\")\n        .map(|s| s.parse())\n        .transpose()?;\n\n    Ok(ops::ReportRebuildsOptions { id })\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/run.rs",
    "content": "use std::ffi::OsStr;\nuse std::ffi::OsString;\nuse std::path::Path;\n\nuse crate::command_prelude::*;\nuse crate::util::restricted_names::is_glob_pattern;\nuse cargo::core::Verbosity;\nuse cargo::core::Workspace;\nuse cargo::ops::{self, CompileFilter, Packages};\nuse cargo::util::closest;\nuse cargo_util::ProcessError;\nuse itertools::Itertools as _;\n\npub fn cli() -> Command {\n    subcommand(\"run\")\n        // subcommand aliases are handled in aliased_command()\n        // .alias(\"r\")\n        .about(\"Run a binary or example of the local package\")\n        .arg(\n            Arg::new(\"args\")\n                .value_name(\"ARGS\")\n                .help(\"Arguments for the binary or example to run\")\n                .value_parser(value_parser!(OsString))\n                .num_args(0..)\n                .trailing_var_arg(true),\n        )\n        .arg_message_format()\n        .arg_silent_suggestion()\n        .arg_package(\"Package with the target to run\")\n        .arg_targets_bin_example(\n            \"Name of the bin target to run\",\n            \"Name of the example target to run\",\n        )\n        .arg_features()\n        .arg_parallel()\n        .arg_release(\"Build artifacts in release mode, with optimizations\")\n        .arg_profile(\"Build artifacts with the specified profile\")\n        .arg_target_triple(\"Build for the target triple\")\n        .arg_target_dir()\n        .arg_manifest_path()\n        .arg_ignore_rust_version()\n        .arg_unit_graph()\n        .arg_timings()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help run</>` for more detailed information.\\n\\\n             To pass `--help` to the specified binary, use `<bright-cyan,bold>-- --help</>`.\\n\",\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n\n    let mut compile_opts =\n        args.compile_options(gctx, UserIntent::Build, Some(&ws), ProfileChecking::Custom)?;\n\n    // Disallow `spec` to be an glob pattern\n    if let Packages::Packages(opt_in) = &compile_opts.spec {\n        if let Some(pattern) = opt_in.iter().find(|s| is_glob_pattern(s)) {\n            return Err(anyhow::anyhow!(\n                \"`cargo run` does not support glob pattern `{}` on package selection\",\n                pattern,\n            )\n            .into());\n        }\n    }\n\n    if !args.contains_id(\"example\") && !args.contains_id(\"bin\") {\n        let default_runs: Vec<_> = compile_opts\n            .spec\n            .get_packages(&ws)?\n            .iter()\n            .filter_map(|pkg| pkg.manifest().default_run())\n            .collect();\n        if let [bin] = &default_runs[..] {\n            compile_opts.filter = CompileFilter::single_bin(bin.to_string());\n        } else {\n            // ops::run will take care of errors if len pkgs != 1.\n            compile_opts.filter = CompileFilter::Default {\n                // Force this to false because the code in ops::run is not\n                // able to pre-check features before compilation starts to\n                // enforce that only 1 binary is built.\n                required_features_filterable: false,\n            };\n        }\n    };\n\n    ops::run(&ws, &compile_opts, &values_os(args, \"args\")).map_err(|err| to_run_error(gctx, err))\n}\n\n/// See also `util/toml/mod.rs`s `is_embedded`\npub fn is_manifest_command(arg: &str) -> bool {\n    let path = Path::new(arg);\n    1 < path.components().count() || path.extension() == Some(OsStr::new(\"rs\"))\n}\n\npub fn exec_manifest_command(gctx: &mut GlobalContext, cmd: &str, args: &[OsString]) -> CliResult {\n    let manifest_path = Path::new(cmd);\n    match (manifest_path.is_file(), gctx.cli_unstable().script) {\n        (true, true) => {}\n        (true, false) => {\n            return Err(anyhow::anyhow!(\"running the file `{cmd}` requires `-Zscript`\").into());\n        }\n        (false, true) => {\n            let possible_commands = crate::list_commands(gctx);\n            let is_dir = if manifest_path.is_dir() {\n                format!(\": `{cmd}` is a directory\")\n            } else {\n                \"\".to_owned()\n            };\n            let suggested_command = if let Some(suggested_command) = possible_commands\n                .keys()\n                .filter(|c| cmd.starts_with(c.as_str()))\n                .max_by_key(|c| c.len())\n            {\n                let actual_args = cmd.strip_prefix(suggested_command).unwrap();\n                let args = if args.is_empty() {\n                    \"\".to_owned()\n                } else {\n                    format!(\n                        \" {}\",\n                        args.into_iter().map(|os| os.to_string_lossy()).join(\" \")\n                    )\n                };\n                format!(\n                    \"\\nhelp: there is a command with a similar name: `{suggested_command} {actual_args}{args}`\"\n                )\n            } else {\n                \"\".to_owned()\n            };\n            let suggested_script = if let Some(suggested_script) = suggested_script(cmd) {\n                format!(\"\\nhelp: there is a script with a similar name: `{suggested_script}`\")\n            } else {\n                \"\".to_owned()\n            };\n            return Err(anyhow::anyhow!(\n                \"no such file or subcommand `{cmd}`{is_dir}{suggested_command}{suggested_script}\"\n            )\n            .into());\n        }\n        (false, false) => {\n            // HACK: duplicating the above for minor tweaks but this will all go away on\n            // stabilization\n            let possible_commands = crate::list_commands(gctx);\n            let suggested_command = if let Some(suggested_command) = possible_commands\n                .keys()\n                .filter(|c| cmd.starts_with(c.as_str()))\n                .max_by_key(|c| c.len())\n            {\n                let actual_args = cmd.strip_prefix(suggested_command).unwrap();\n                let args = if args.is_empty() {\n                    \"\".to_owned()\n                } else {\n                    format!(\n                        \" {}\",\n                        args.into_iter().map(|os| os.to_string_lossy()).join(\" \")\n                    )\n                };\n                format!(\n                    \"\\nhelp: there is a command with a similar name: `{suggested_command} {actual_args}{args}`\"\n                )\n            } else {\n                \"\".to_owned()\n            };\n            let suggested_script = if let Some(suggested_script) = suggested_script(cmd) {\n                format!(\n                    \"\\nhelp: there is a script with a similar name: `{suggested_script}` (requires `-Zscript`)\"\n                )\n            } else {\n                \"\".to_owned()\n            };\n            return Err(anyhow::anyhow!(\n                \"no such subcommand `{cmd}`{suggested_command}{suggested_script}\"\n            )\n            .into());\n        }\n    }\n\n    let manifest_path = root_manifest(Some(manifest_path), gctx)?;\n\n    // Treat `cargo foo.rs` like `cargo install --path foo` and re-evaluate the config based on the\n    // location where the script resides, rather than the environment from where it's being run.\n    let parent_path = manifest_path\n        .parent()\n        .expect(\"a file should always have a parent\");\n    gctx.reload_rooted_at(parent_path)?;\n\n    let mut ws = Workspace::new(&manifest_path, gctx)?;\n    if gctx.cli_unstable().avoid_dev_deps {\n        ws.set_require_optional_deps(false);\n    }\n\n    let mut compile_opts =\n        cargo::ops::CompileOptions::new(gctx, cargo::core::compiler::UserIntent::Build)?;\n    compile_opts.spec = cargo::ops::Packages::Default;\n\n    cargo::ops::run(&ws, &compile_opts, args).map_err(|err| to_run_error(gctx, err))\n}\n\nfn suggested_script(cmd: &str) -> Option<String> {\n    let cmd_path = Path::new(cmd);\n    let mut suggestion = Path::new(\".\").to_owned();\n    for cmd_part in cmd_path.components() {\n        let exact_match = suggestion.join(cmd_part);\n        suggestion = if exact_match.exists() {\n            exact_match\n        } else {\n            let possible: Vec<_> = std::fs::read_dir(suggestion)\n                .into_iter()\n                .flatten()\n                .filter_map(|e| e.ok())\n                .map(|e| e.path())\n                .filter(|p| p.to_str().is_some())\n                .collect();\n            if let Some(possible) = closest(\n                cmd_part.as_os_str().to_str().unwrap(),\n                possible.iter(),\n                |p| p.file_name().unwrap().to_str().unwrap(),\n            ) {\n                possible.to_owned()\n            } else {\n                return None;\n            }\n        };\n    }\n    if suggestion.is_dir() {\n        None\n    } else {\n        suggestion.into_os_string().into_string().ok()\n    }\n}\n\nfn to_run_error(gctx: &GlobalContext, err: anyhow::Error) -> CliError {\n    let proc_err = match err.downcast_ref::<ProcessError>() {\n        Some(e) => e,\n        None => return CliError::new(err, 101),\n    };\n\n    // If we never actually spawned the process then that sounds pretty\n    // bad and we always want to forward that up.\n    let exit_code = match proc_err.code {\n        Some(exit) => exit,\n        None => return CliError::new(err, 101),\n    };\n\n    // If `-q` was passed then we suppress extra error information about\n    // a failed process, we assume the process itself printed out enough\n    // information about why it failed so we don't do so as well\n    let is_quiet = gctx.shell().verbosity() == Verbosity::Quiet;\n    if is_quiet {\n        CliError::code(exit_code)\n    } else {\n        CliError::new(err, exit_code)\n    }\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/rustc.rs",
    "content": "use crate::command_prelude::*;\nuse cargo::ops;\n\nconst PRINT_ARG_NAME: &str = \"print\";\nconst CRATE_TYPE_ARG_NAME: &str = \"crate-type\";\n\npub fn cli() -> Command {\n    subcommand(\"rustc\")\n        .about(\"Compile a package, and pass extra options to the compiler\")\n        .arg(\n            Arg::new(\"args\")\n                .value_name(\"ARGS\")\n                .num_args(0..)\n                .help(\"Extra rustc flags\")\n                .trailing_var_arg(true),\n        )\n        .arg(\n            opt(\n                PRINT_ARG_NAME,\n                \"Output compiler information without compiling\",\n            )\n            .value_name(\"INFO\"),\n        )\n        .arg(multi_opt(\n            CRATE_TYPE_ARG_NAME,\n            \"CRATE-TYPE\",\n            \"Comma separated list of types of crates for the compiler to emit\",\n        ))\n        .arg_future_incompat_report()\n        .arg_message_format()\n        .arg_silent_suggestion()\n        .arg_package(\"Package to build\")\n        .arg_targets_all(\n            \"Build only this package's library\",\n            \"Build only the specified binary\",\n            \"Build all binaries\",\n            \"Build only the specified example\",\n            \"Build all examples\",\n            \"Build only the specified test target\",\n            \"Build all targets that have `test = true` set\",\n            \"Build only the specified bench target\",\n            \"Build all targets that have `bench = true` set\",\n            \"Build all targets\",\n        )\n        .arg_features()\n        .arg_parallel()\n        .arg_release(\"Build artifacts in release mode, with optimizations\")\n        .arg_profile(\"Build artifacts with the specified profile\")\n        .arg_target_triple(\"Target triple which compiles will be for\")\n        .arg_target_dir()\n        .arg_unit_graph()\n        .arg_timings()\n        .arg_manifest_path()\n        .arg_ignore_rust_version()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help rustc</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n    // This is a legacy behavior that changes the behavior based on the profile.\n    // If we want to support this more formally, I think adding a --mode flag\n    // would be warranted.\n    let intent = match args.get_one::<String>(\"profile\").map(String::as_str) {\n        Some(\"test\") => UserIntent::Test,\n        Some(\"bench\") => UserIntent::Bench,\n        Some(\"check\") => UserIntent::Check { test: false },\n        _ => UserIntent::Build,\n    };\n    let mut compile_opts = args.compile_options_for_single_package(\n        gctx,\n        intent,\n        Some(&ws),\n        ProfileChecking::LegacyRustc,\n    )?;\n    if compile_opts.build_config.requested_profile == \"check\" {\n        compile_opts.build_config.requested_profile = \"dev\".into();\n    }\n    let target_args = values(args, \"args\");\n    compile_opts.target_rustc_args = if target_args.is_empty() {\n        None\n    } else {\n        Some(target_args)\n    };\n    if let Some(opt_value) = args.get_one::<String>(PRINT_ARG_NAME) {\n        gctx.cli_unstable()\n            .fail_if_stable_opt(PRINT_ARG_NAME, 9357)?;\n        ops::print(&ws, &compile_opts, opt_value)?;\n        return Ok(());\n    }\n\n    let crate_types = {\n        let mut seen = std::collections::HashSet::new();\n        args.get_many::<String>(CRATE_TYPE_ARG_NAME)\n            .into_iter()\n            .flatten()\n            .flat_map(|s| s.split(','))\n            .filter(|s| !s.is_empty())\n            .map(String::from)\n            .filter(|s| seen.insert(s.clone()))\n            .collect::<Vec<String>>()\n    };\n\n    compile_opts.target_rustc_crate_types = if crate_types.is_empty() {\n        None\n    } else {\n        Some(crate_types)\n    };\n    ops::compile(&ws, &compile_opts)?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/rustdoc.rs",
    "content": "use cargo::ops::{self, DocOptions, OutputFormat};\n\nuse crate::command_prelude::*;\n\npub fn cli() -> Command {\n    subcommand(\"rustdoc\")\n        .about(\"Build a package's documentation, using specified custom flags.\")\n        .arg(\n            Arg::new(\"args\")\n                .value_name(\"ARGS\")\n                .help(\"Extra rustdoc flags\")\n                .num_args(0..)\n                .trailing_var_arg(true),\n        )\n        .arg(flag(\n            \"open\",\n            \"Opens the docs in a browser after the operation\",\n        ))\n        .arg_message_format()\n        .arg_silent_suggestion()\n        .arg_package(\"Package to document\")\n        .arg_targets_all(\n            \"Build only this package's library\",\n            \"Build only the specified binary\",\n            \"Build all binaries\",\n            \"Build only the specified example\",\n            \"Build all examples\",\n            \"Build only the specified test target\",\n            \"Build all targets that have `test = true` set\",\n            \"Build only the specified bench target\",\n            \"Build all targets that have `bench = true` set\",\n            \"Build all targets\",\n        )\n        .arg_features()\n        .arg_parallel()\n        .arg_release(\"Build artifacts in release mode, with optimizations\")\n        .arg_profile(\"Build artifacts with the specified profile\")\n        .arg_target_triple(\"Build for the target triple\")\n        .arg_target_dir()\n        .arg(\n            opt(\"output-format\", \"The output type to write (unstable)\")\n                .value_name(\"FMT\")\n                .value_parser(OutputFormat::POSSIBLE_VALUES),\n        )\n        .arg_unit_graph()\n        .arg_timings()\n        .arg_manifest_path()\n        .arg_ignore_rust_version()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help rustdoc</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n    let output_format = if let Some(output_format) = args._value_of(\"output-format\") {\n        gctx.cli_unstable()\n            .fail_if_stable_opt(\"--output-format\", 12103)?;\n        output_format.parse()?\n    } else {\n        OutputFormat::Html\n    };\n\n    let mut compile_opts = args.compile_options_for_single_package(\n        gctx,\n        UserIntent::Doc {\n            deps: false,\n            json: matches!(output_format, OutputFormat::Json),\n        },\n        Some(&ws),\n        ProfileChecking::Custom,\n    )?;\n    let target_args = values(args, \"args\");\n\n    compile_opts.target_rustdoc_args = if target_args.is_empty() {\n        None\n    } else {\n        Some(target_args)\n    };\n\n    let doc_opts = DocOptions {\n        open_result: args.flag(\"open\"),\n        output_format,\n        compile_opts,\n    };\n    ops::doc(&ws, &doc_opts)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/search.rs",
    "content": "use crate::command_prelude::*;\n\nuse std::cmp::min;\n\nuse cargo::ops;\n\npub fn cli() -> Command {\n    subcommand(\"search\")\n        .about(\"Search packages in the registry. Default registry is crates.io\")\n        .arg(Arg::new(\"query\").value_name(\"QUERY\").num_args(0..))\n        .arg(\n            opt(\n                \"limit\",\n                \"Limit the number of results (default: 10, max: 100)\",\n            )\n            .value_name(\"LIMIT\"),\n        )\n        .arg_index(\"Registry index URL to search packages in\")\n        .arg_registry(\"Registry to search packages in\")\n        .arg_silent_suggestion()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help search</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let reg_or_index = args.registry_or_index(gctx)?;\n    let limit = args.value_of_u32(\"limit\")?;\n    let limit = min(100, limit.unwrap_or(10));\n    let query: Vec<&str> = args\n        .get_many::<String>(\"query\")\n        .unwrap_or_default()\n        .map(String::as_str)\n        .collect();\n    let query: String = query.join(\"+\");\n    ops::search(&query, gctx, reg_or_index, limit)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/test.rs",
    "content": "use crate::command_prelude::*;\nuse cargo::ops;\n\npub fn cli() -> Command {\n    subcommand(\"test\")\n        // Subcommand aliases are handled in `aliased_command()`.\n        // .alias(\"t\")\n        .about(\"Execute all unit and integration tests and build examples of a local package\")\n        .arg(\n            Arg::new(\"TESTNAME\")\n                .action(ArgAction::Set)\n                .help(\"If specified, only run tests containing this string in their names\"),\n        )\n        .arg(\n            Arg::new(\"args\")\n                .value_name(\"ARGS\")\n                .help(\"Arguments for the test binary\")\n                .num_args(0..)\n                .last(true),\n        )\n        .arg(flag(\"no-run\", \"Compile, but don't run tests\"))\n        .arg(flag(\"no-fail-fast\", \"Run all tests regardless of failure\"))\n        .arg_future_incompat_report()\n        .arg_message_format()\n        .arg(\n            flag(\n                \"quiet\",\n                \"Display one character per test instead of one line\",\n            )\n            .short('q'),\n        )\n        .arg_package_spec(\n            \"Package to run tests for\",\n            \"Test all packages in the workspace\",\n            \"Exclude packages from the test\",\n        )\n        .arg_targets_all(\n            \"Test only this package's library\",\n            \"Test only the specified binary\",\n            \"Test all binaries\",\n            \"Test only the specified example\",\n            \"Test all examples\",\n            \"Test only the specified test target\",\n            \"Test all targets that have `test = true` set\",\n            \"Test only the specified bench target\",\n            \"Test all targets that have `bench = true` set\",\n            \"Test all targets (does not include doctests)\",\n        )\n        .arg(\n            flag(\"doc\", \"Test only this library's documentation\")\n                .help_heading(heading::TARGET_SELECTION),\n        )\n        .arg_features()\n        .arg_jobs()\n        .arg_unsupported_keep_going()\n        .arg_release(\"Build artifacts in release mode, with optimizations\")\n        .arg_profile(\"Build artifacts with the specified profile\")\n        .arg_target_triple(\"Build for the target triple\")\n        .arg_target_dir()\n        .arg_unit_graph()\n        .arg_timings()\n        .arg_manifest_path()\n        .arg_ignore_rust_version()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help test</>` for more detailed information.\\n\\\n             Run `<bright-cyan,bold>cargo test -- --help</>` for test binary options.\\n\",\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let ws = args.workspace(gctx)?;\n\n    let mut compile_opts =\n        args.compile_options(gctx, UserIntent::Test, Some(&ws), ProfileChecking::Custom)?;\n\n    compile_opts.build_config.requested_profile =\n        args.get_profile_name(\"test\", ProfileChecking::Custom)?;\n\n    // `TESTNAME` is actually an argument of the test binary, but it's\n    // important, so we explicitly mention it and reconfigure.\n    let test_name = args.get_one::<String>(\"TESTNAME\");\n    let test_args = args.get_one::<String>(\"TESTNAME\").into_iter();\n    let test_args = test_args.chain(args.get_many::<String>(\"args\").unwrap_or_default());\n    let test_args = test_args.map(String::as_str).collect::<Vec<_>>();\n\n    let no_run = args.flag(\"no-run\");\n    let doc = args.flag(\"doc\");\n    if doc {\n        if compile_opts.filter.is_specific() {\n            return Err(\n                anyhow::format_err!(\"can't mix --doc with other target selecting options\").into(),\n            );\n        }\n        if no_run {\n            return Err(anyhow::format_err!(\"can't skip running doc tests with --no-run\").into());\n        }\n        compile_opts.build_config.intent = UserIntent::Doctest;\n        compile_opts.filter = ops::CompileFilter::lib_only();\n    } else if test_name.is_some() && !compile_opts.filter.is_specific() {\n        // If arg `TESTNAME` is provided, assumed that the user knows what\n        // exactly they wants to test, so we use `all_test_targets` to\n        // avoid compiling unnecessary targets such as examples, which are\n        // included by the logic of default target filter.\n        compile_opts.filter = ops::CompileFilter::all_test_targets();\n    }\n\n    let ops = ops::TestOptions {\n        no_run,\n        no_fail_fast: args.flag(\"no-fail-fast\"),\n        compile_opts,\n    };\n\n    ops::run_tests(&ws, &ops, &test_args)\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/tree.rs",
    "content": "use crate::cli;\nuse crate::command_prelude::*;\nuse annotate_snippets::Level;\nuse anyhow::{bail, format_err};\nuse cargo::core::dependency::DepKind;\nuse cargo::ops::Packages;\nuse cargo::ops::tree::{self, DisplayDepth, EdgeKind};\nuse cargo::util::CargoResult;\nuse cargo::util::print_available_packages;\nuse clap_complete::ArgValueCandidates;\nuse std::collections::HashSet;\nuse std::str::FromStr;\n\npub fn cli() -> Command {\n    subcommand(\"tree\")\n        .about(\"Display a tree visualization of a dependency graph\")\n        .arg(\n            flag(\"all\", \"Deprecated, use --no-dedupe instead\")\n                .short('a')\n                .hide(true),\n        )\n        .arg_silent_suggestion()\n        .arg(flag(\"no-dev-dependencies\", \"Deprecated, use -e=no-dev instead\").hide(true))\n        .arg(\n            multi_opt(\"edges\", \"KINDS\", \"The kinds of dependencies to display\")\n                .short('e')\n                .value_delimiter(',')\n                .value_parser([\n                    \"all\",\n                    \"normal\",\n                    \"build\",\n                    \"dev\",\n                    \"features\",\n                    \"public\",\n                    \"no-normal\",\n                    \"no-build\",\n                    \"no-dev\",\n                    \"no-proc-macro\",\n                ]),\n        )\n        .arg(\n            optional_multi_opt(\n                \"invert\",\n                \"SPEC\",\n                \"Invert the tree direction and focus on the given package\",\n            )\n            .short('i')\n            .add(clap_complete::ArgValueCandidates::new(\n                get_pkg_id_spec_candidates,\n            )),\n        )\n        .arg(\n            multi_opt(\n                \"prune\",\n                \"SPEC\",\n                \"Prune the given package from the display of the dependency tree\",\n            )\n            .add(clap_complete::ArgValueCandidates::new(\n                get_pkg_id_spec_candidates,\n            )),\n        )\n        .arg(opt(\"depth\", \"Maximum display depth of the dependency tree\").value_name(\"DEPTH\"))\n        .arg(flag(\"no-indent\", \"Deprecated, use --prefix=none instead\").hide(true))\n        .arg(flag(\"prefix-depth\", \"Deprecated, use --prefix=depth instead\").hide(true))\n        .arg(\n            opt(\n                \"prefix\",\n                \"Change the prefix (indentation) of how each entry is displayed\",\n            )\n            .value_name(\"PREFIX\")\n            .value_parser([\"depth\", \"indent\", \"none\"])\n            .default_value(\"indent\"),\n        )\n        .arg(flag(\n            \"no-dedupe\",\n            \"Do not de-duplicate (repeats all shared dependencies)\",\n        ))\n        .arg(\n            flag(\n                \"duplicates\",\n                \"Show only dependencies which come in multiple versions (implies -i)\",\n            )\n            .short('d')\n            .alias(\"duplicate\"),\n        )\n        .arg(\n            opt(\"charset\", \"Character set to use in output\")\n                .value_name(\"CHARSET\")\n                .value_parser([\"utf8\", \"ascii\"]),\n        )\n        .arg(\n            opt(\"format\", \"Format string used for printing dependencies\")\n                .value_name(\"FORMAT\")\n                .short('f')\n                .default_value(\"{p}\"),\n        )\n        .arg(\n            // Backwards compatibility with old cargo-tree.\n            flag(\"version\", \"Print version info and exit\")\n                .short('V')\n                .hide(true),\n        )\n        .arg_package_spec_no_all(\n            \"Package to be used as the root of the tree\",\n            \"Display the tree for all packages in the workspace\",\n            \"Exclude specific workspace members\",\n            ArgValueCandidates::new(get_pkg_id_spec_candidates),\n        )\n        .arg_features()\n        .arg(flag(\"all-targets\", \"Deprecated, use --target=all instead\").hide(true))\n        .arg_target_triple_with_candidates(\n            \"Filter dependencies matching the given target-triple (default host platform). \\\n            Pass `all` to include all targets.\",\n            ArgValueCandidates::new(get_target_triples_with_all),\n        )\n        .arg_manifest_path()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help tree</>` for more detailed information.\\n\"\n        ))\n}\n\n#[derive(Copy, Clone)]\npub enum Charset {\n    Utf8,\n    Ascii,\n}\n\nimpl FromStr for Charset {\n    type Err = &'static str;\n\n    fn from_str(s: &str) -> Result<Charset, &'static str> {\n        match s {\n            \"utf8\" => Ok(Charset::Utf8),\n            \"ascii\" => Ok(Charset::Ascii),\n            _ => Err(\"invalid charset\"),\n        }\n    }\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    if args.flag(\"version\") {\n        let verbose = args.verbose() > 0;\n        let version = cli::get_version_string(verbose);\n        cargo::drop_print!(gctx, \"{}\", version);\n        return Ok(());\n    }\n    let prefix = if args.flag(\"no-indent\") {\n        gctx.shell()\n            .warn(\"the --no-indent flag has been changed to --prefix=none\")?;\n        \"none\"\n    } else if args.flag(\"prefix-depth\") {\n        gctx.shell()\n            .warn(\"the --prefix-depth flag has been changed to --prefix=depth\")?;\n        \"depth\"\n    } else {\n        args.get_one::<String>(\"prefix\").unwrap().as_str()\n    };\n    let prefix = tree::Prefix::from_str(prefix).map_err(|e| anyhow::anyhow!(\"{}\", e))?;\n\n    let no_dedupe = args.flag(\"no-dedupe\") || args.flag(\"all\");\n    if args.flag(\"all\") {\n        gctx.shell().print_report(\n            &[Level::WARNING\n                .secondary_title(\n                    \"the `cargo tree` --all flag has been changed to --no-dedupe, \\\n                    and may be removed in a future version\",\n                )\n                .element(Level::HELP.message(\n                    \"if you are looking to display all workspace members, use the --workspace flag\",\n                ))],\n            false,\n        )?;\n    }\n\n    let targets = if args.flag(\"all-targets\") {\n        gctx.shell()\n            .warn(\"the --all-targets flag has been changed to --target=all\")?;\n        vec![\"all\".to_string()]\n    } else {\n        args.targets()?\n    };\n    let target = tree::Target::from_cli(targets);\n\n    let (edge_kinds, no_proc_macro, public) = parse_edge_kinds(gctx, args)?;\n    let graph_features = edge_kinds.contains(&EdgeKind::Feature);\n\n    let pkgs_to_prune = args._values_of(\"prune\");\n\n    let display_depth = args\n        ._value_of(\"depth\")\n        .map(|s| s.parse::<DisplayDepth>())\n        .transpose()?\n        .unwrap_or(DisplayDepth::MaxDisplayDepth(u32::MAX));\n\n    let packages = args.packages_from_flags()?;\n    let mut invert = args\n        .get_many::<String>(\"invert\")\n        .map_or_else(|| Vec::new(), |is| is.map(|s| s.to_string()).collect());\n    if args.is_present_with_zero_values(\"invert\") {\n        match &packages {\n            Packages::Packages(ps) => {\n                // Backwards compatibility with old syntax of `cargo tree -i -p foo`.\n                invert.extend(ps.clone());\n            }\n            _ => {\n                return Err(format_err!(\n                    \"The `-i` flag requires a package name.\\n\\\n\\n\\\nThe `-i` flag is used to inspect the reverse dependencies of a specific\\n\\\npackage. It will invert the tree and display the packages that depend on the\\n\\\ngiven package.\\n\\\n\\n\\\nNote that in a workspace, by default it will only display the package's\\n\\\nreverse dependencies inside the tree of the workspace member in the current\\n\\\ndirectory. The --workspace flag can be used to extend it so that it will show\\n\\\nthe package's reverse dependencies across the entire workspace. The -p flag\\n\\\ncan be used to display the package's reverse dependencies only with the\\n\\\nsubtree of the package given to -p.\\n\\\n\"\n                )\n                .into());\n            }\n        }\n    }\n\n    let ws = args.workspace(gctx)?;\n\n    if args.is_present_with_zero_values(\"package\") {\n        print_available_packages(&ws)?;\n    }\n\n    let charset = args.get_one::<String>(\"charset\");\n    if let Some(charset) = charset\n        .map(|c| Charset::from_str(c))\n        .transpose()\n        .map_err(|e| anyhow::anyhow!(\"{}\", e))?\n    {\n        match charset {\n            Charset::Utf8 => gctx.shell().set_unicode(true)?,\n            Charset::Ascii => gctx.shell().set_unicode(false)?,\n        }\n    }\n    let opts = tree::TreeOptions {\n        cli_features: args.cli_features()?,\n        packages,\n        target,\n        edge_kinds,\n        invert,\n        pkgs_to_prune,\n        prefix,\n        no_dedupe,\n        duplicates: args.flag(\"duplicates\"),\n        format: args.get_one::<String>(\"format\").cloned().unwrap(),\n        graph_features,\n        display_depth,\n        no_proc_macro,\n        public,\n    };\n\n    if opts.graph_features && opts.duplicates {\n        return Err(format_err!(\"the `-e features` flag does not support `--duplicates`\").into());\n    }\n\n    tree::build_and_print(&ws, &opts)?;\n    Ok(())\n}\n\n/// Parses `--edges` option.\n///\n/// Returns a tuple of `EdgeKind` map and `no_proc_marco` flag.\nfn parse_edge_kinds(\n    gctx: &GlobalContext,\n    args: &ArgMatches,\n) -> CargoResult<(HashSet<EdgeKind>, bool, bool)> {\n    let (kinds, no_proc_macro, public) = {\n        let mut no_proc_macro = false;\n        let mut public = false;\n        let mut kinds = args.get_many::<String>(\"edges\").map_or_else(\n            || Vec::new(),\n            |es| {\n                es.map(|e| e.as_str())\n                    .filter(|e| {\n                        if *e == \"no-proc-macro\" {\n                            no_proc_macro = true;\n                            false\n                        } else if *e == \"public\" {\n                            public = true;\n                            false\n                        } else {\n                            true\n                        }\n                    })\n                    .collect()\n            },\n        );\n\n        if args.flag(\"no-dev-dependencies\") {\n            gctx.shell()\n                .warn(\"the --no-dev-dependencies flag has changed to -e=no-dev\")?;\n            kinds.push(\"no-dev\");\n        }\n\n        if kinds.is_empty() {\n            kinds.extend(&[\"normal\", \"build\", \"dev\"]);\n        }\n\n        if public && !gctx.cli_unstable().unstable_options {\n            anyhow::bail!(\"`--edges public` requires `-Zunstable-options`\");\n        }\n\n        (kinds, no_proc_macro, public)\n    };\n\n    let mut result = HashSet::new();\n    let insert_defaults = |result: &mut HashSet<EdgeKind>| {\n        result.insert(EdgeKind::Dep(DepKind::Normal));\n        result.insert(EdgeKind::Dep(DepKind::Build));\n        result.insert(EdgeKind::Dep(DepKind::Development));\n    };\n    if kinds.iter().any(|k| k.starts_with(\"no-\")) {\n        insert_defaults(&mut result);\n        for kind in &kinds {\n            match *kind {\n                \"no-normal\" => result.remove(&EdgeKind::Dep(DepKind::Normal)),\n                \"no-build\" => result.remove(&EdgeKind::Dep(DepKind::Build)),\n                \"no-dev\" => result.remove(&EdgeKind::Dep(DepKind::Development)),\n                \"features\" => result.insert(EdgeKind::Feature),\n                \"normal\" | \"build\" | \"dev\" | \"all\" => {\n                    bail!(\n                        \"`{}` dependency kind cannot be mixed with \\\n                            \\\"no-normal\\\", \\\"no-build\\\", or \\\"no-dev\\\" \\\n                            dependency kinds\",\n                        kind\n                    )\n                }\n                _ => unreachable!(\"`{kind}` was validated by clap\"),\n            };\n        }\n        return Ok((result, no_proc_macro, public));\n    }\n    for kind in &kinds {\n        match *kind {\n            \"all\" => {\n                insert_defaults(&mut result);\n                result.insert(EdgeKind::Feature);\n            }\n            \"features\" => {\n                result.insert(EdgeKind::Feature);\n            }\n            \"normal\" => {\n                result.insert(EdgeKind::Dep(DepKind::Normal));\n            }\n            \"build\" => {\n                result.insert(EdgeKind::Dep(DepKind::Build));\n            }\n            \"dev\" => {\n                result.insert(EdgeKind::Dep(DepKind::Development));\n            }\n            _ => unreachable!(\"`{kind}` was validated by clap\"),\n        }\n    }\n    if kinds.len() == 1 && kinds[0] == \"features\" {\n        insert_defaults(&mut result);\n    }\n    Ok((result, no_proc_macro, public))\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/uninstall.rs",
    "content": "use crate::command_prelude::*;\n\nuse cargo::{CargoResult, core::PackageId, ops};\nuse clap_complete::ArgValueCandidates;\n\nuse std::collections::BTreeSet;\n\npub fn cli() -> Command {\n    subcommand(\"uninstall\")\n        .about(\"Remove a Rust binary\")\n        .arg(\n            Arg::new(\"spec\")\n                .value_name(\"SPEC\")\n                .num_args(0..)\n                .add::<clap_complete::ArgValueCandidates>(clap_complete::ArgValueCandidates::new(\n                    || get_installed_crates(),\n                )),\n        )\n        .arg(opt(\"root\", \"Directory to uninstall packages from\").value_name(\"DIR\"))\n        .arg_silent_suggestion()\n        .arg_package_spec_simple(\n            \"Package to uninstall\",\n            ArgValueCandidates::new(get_installed_package_candidates),\n        )\n        .arg(\n            multi_opt(\"bin\", \"NAME\", \"Only uninstall the binary NAME\")\n                .help_heading(heading::TARGET_SELECTION),\n        )\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help uninstall</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let root = args.get_one::<String>(\"root\").map(String::as_str);\n\n    if args.is_present_with_zero_values(\"package\") {\n        return Err(anyhow::anyhow!(\n            \"\\\"--package <SPEC>\\\" requires a SPEC format value.\\n\\\n            Run `cargo help pkgid` for more information about SPEC format.\"\n        )\n        .into());\n    }\n\n    let specs = args\n        .get_many::<String>(\"spec\")\n        .unwrap_or_else(|| args.get_many::<String>(\"package\").unwrap_or_default())\n        .map(String::as_str)\n        .collect();\n    ops::uninstall(root, specs, &values(args, \"bin\"), gctx)?;\n    Ok(())\n}\n\nfn get_installed_crates() -> Vec<clap_complete::CompletionCandidate> {\n    get_installed_crates_().unwrap_or_default()\n}\n\nfn get_installed_crates_() -> Option<Vec<clap_complete::CompletionCandidate>> {\n    let mut candidates = Vec::new();\n\n    let gctx = new_gctx_for_completions().ok()?;\n\n    let root = ops::resolve_root(None, &gctx).ok()?;\n\n    let tracker = ops::InstallTracker::load(&gctx, &root).ok()?;\n\n    for (_, v) in tracker.all_installed_bins() {\n        for bin in v {\n            candidates.push(clap_complete::CompletionCandidate::new(bin));\n        }\n    }\n\n    Some(candidates)\n}\n\nfn get_installed_package_candidates() -> Vec<clap_complete::CompletionCandidate> {\n    get_installed_packages()\n        .unwrap_or_default()\n        .into_iter()\n        .map(|(pkg, bins)| {\n            let single_binary = bins.iter().next().take_if(|_| bins.len() == 1);\n\n            let help = if single_binary.is_some_and(|bin| bin == pkg.name().as_str()) {\n                None\n            } else {\n                let binaries = bins.into_iter().collect::<Vec<_>>().as_slice().join(\", \");\n                Some(binaries)\n            };\n\n            clap_complete::CompletionCandidate::new(pkg.name().as_str()).help(help.map(From::from))\n        })\n        .collect()\n}\n\nfn get_installed_packages() -> CargoResult<Vec<(PackageId, BTreeSet<String>)>> {\n    let gctx = new_gctx_for_completions()?;\n    let root = ops::resolve_root(None, &gctx)?;\n\n    let tracker = ops::InstallTracker::load(&gctx, &root)?;\n    Ok(tracker\n        .all_installed_bins()\n        .map(|(package_id, bins)| (*package_id, bins.clone()))\n        .collect())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/update.rs",
    "content": "use crate::command_prelude::*;\n\nuse anyhow::anyhow;\nuse cargo::ops::{self, UpdateOptions};\nuse cargo::util::print_available_packages;\n\npub fn cli() -> Command {\n    subcommand(\"update\")\n        .about(\"Update dependencies as recorded in the local lock file\")\n        .args([clap::Arg::new(\"package2\")\n            .action(clap::ArgAction::Append)\n            .num_args(1..)\n            .value_name(\"SPEC\")\n            .help_heading(heading::PACKAGE_SELECTION)\n            .group(\"package-group\")\n            .help(\"Package to update\")\n            .add(clap_complete::ArgValueCandidates::new(\n                get_pkg_id_spec_candidates,\n            ))])\n        .arg(\n            optional_multi_opt(\"package\", \"SPEC\", \"Package to update\")\n                .short('p')\n                .hide(true)\n                .help_heading(heading::PACKAGE_SELECTION)\n                .group(\"package-group\"),\n        )\n        .arg_dry_run(\"Don't actually write the lockfile\")\n        .arg(\n            flag(\n                \"recursive\",\n                \"Force updating all dependencies of [SPEC]... as well\",\n            )\n            .alias(\"aggressive\")\n            .conflicts_with(\"precise\"),\n        )\n        .arg(\n            opt(\"precise\", \"Update [SPEC] to exactly PRECISE\")\n                .value_name(\"PRECISE\")\n                .requires(\"package-group\"),\n        )\n        .arg(\n            flag(\n                \"breaking\",\n                \"Update [SPEC] to latest SemVer-breaking version (unstable)\",\n            )\n            .short('b'),\n        )\n        .arg_silent_suggestion()\n        .arg(\n            flag(\"workspace\", \"Only update the workspace packages\")\n                .short('w')\n                .help_heading(heading::PACKAGE_SELECTION),\n        )\n        .arg_manifest_path()\n        .arg_ignore_rust_version_with_help(\"Ignore `rust-version` specification in packages\")\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help update</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let mut ws = args.workspace(gctx)?;\n\n    if args.is_present_with_zero_values(\"package\") {\n        print_available_packages(&ws)?;\n    }\n\n    let to_update = if args.contains_id(\"package\") {\n        \"package\"\n    } else {\n        \"package2\"\n    };\n    let to_update = values(args, to_update);\n    for crate_name in to_update.iter() {\n        if let Some(toolchain) = crate_name.strip_prefix(\"+\") {\n            return Err(anyhow!(\n                \"invalid character `+` in package name: `+{toolchain}`\n    Use `cargo +{toolchain} update` if you meant to use the `{toolchain}` toolchain.\"\n            )\n            .into());\n        }\n    }\n\n    let update_opts = UpdateOptions {\n        recursive: args.flag(\"recursive\"),\n        precise: args.get_one::<String>(\"precise\").map(String::as_str),\n        to_update,\n        dry_run: args.dry_run(),\n        workspace: args.flag(\"workspace\"),\n        gctx,\n    };\n\n    if args.flag(\"breaking\") {\n        gctx.cli_unstable()\n            .fail_if_stable_opt(\"--breaking\", 12425)?;\n\n        let upgrades = ops::upgrade_manifests(&mut ws, &update_opts.to_update)?;\n        ops::resolve_ws(&ws, update_opts.dry_run)?;\n        ops::write_manifest_upgrades(&ws, &upgrades, update_opts.dry_run)?;\n\n        if update_opts.dry_run {\n            update_opts\n                .gctx\n                .shell()\n                .warn(\"aborting update due to dry run\")?;\n        }\n    } else {\n        ops::update_lockfile(&ws, &update_opts)?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/vendor.rs",
    "content": "use crate::command_prelude::*;\nuse cargo::ops;\nuse std::path::PathBuf;\n\npub fn cli() -> Command {\n    subcommand(\"vendor\")\n        .about(\"Vendor all dependencies for a project locally\")\n        .arg(\n            Arg::new(\"path\")\n                .action(ArgAction::Set)\n                .value_parser(clap::value_parser!(PathBuf))\n                .help(\"Where to vendor crates (`vendor` by default)\"),\n        )\n        .arg(flag(\n            \"no-delete\",\n            \"Don't delete older crates in the vendor directory\",\n        ))\n        .arg(\n            Arg::new(\"tomls\")\n                .short('s')\n                .long(\"sync\")\n                .help(\"Additional `Cargo.toml` to sync and vendor\")\n                .value_name(\"TOML\")\n                .value_parser(clap::value_parser!(PathBuf))\n                .action(clap::ArgAction::Append),\n        )\n        .arg(flag(\n            \"respect-source-config\",\n            \"Respect `[source]` config in `.cargo/config`\",\n        ))\n        .arg(flag(\n            \"versioned-dirs\",\n            \"Always include version in subdir name\",\n        ))\n        .arg(unsupported(\"no-merge-sources\"))\n        .arg(unsupported(\"relative-path\"))\n        .arg(unsupported(\"only-git-deps\"))\n        .arg(unsupported(\"disallow-duplicates\"))\n        .arg_manifest_path()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help vendor</>` for more detailed information.\\n\"\n        ))\n}\n\nfn unsupported(name: &'static str) -> Arg {\n    // When we moved `cargo vendor` into Cargo itself we didn't stabilize a few\n    // flags, so try to provide a helpful error message in that case to ensure\n    // that users currently using the flag aren't tripped up.\n    let value_parser = clap::builder::UnknownArgumentValueParser::suggest(\"the crates.io `cargo vendor` command has been merged into Cargo\")\n        .and_suggest(format!(\"and the flag `--{name}` isn't supported currently\"))\n        .and_suggest(\"to continue using the flag, execute `cargo-vendor vendor ...`\")\n        .and_suggest(\"to suggest this flag supported in Cargo, file an issue at <https://github.com/rust-lang/cargo/issues/new>\");\n\n    flag(name, \"\").value_parser(value_parser).hide(true)\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    // We're doing the vendoring operation ourselves, so we don't actually want\n    // to respect any of the `source` configuration in Cargo itself. That's\n    // intended for other consumers of Cargo, but we want to go straight to the\n    // source, e.g. crates.io, to fetch crates.\n    let respect_source_config = args.flag(\"respect-source-config\");\n    if !respect_source_config {\n        gctx.values_mut()?.remove(\"source\");\n    }\n\n    let ws = args.workspace(gctx)?;\n    let path = args\n        .get_one::<PathBuf>(\"path\")\n        .cloned()\n        .unwrap_or_else(|| PathBuf::from(\"vendor\"));\n    ops::vendor(\n        &ws,\n        &ops::VendorOptions {\n            no_delete: args.flag(\"no-delete\"),\n            destination: &path,\n            versioned_dirs: args.flag(\"versioned-dirs\"),\n            extra: args\n                .get_many::<PathBuf>(\"tomls\")\n                .unwrap_or_default()\n                .cloned()\n                .collect(),\n            respect_source_config,\n        },\n    )?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/verify_project.rs",
    "content": "//! Deprecated.\n\nuse crate::command_prelude::*;\n\nuse std::collections::HashMap;\nuse std::process;\n\npub fn cli() -> Command {\n    subcommand(\"verify-project\")\n        .hide(true)\n        .about(\n            \"\\\nDEPRECATED: Check correctness of crate manifest.\n\nSee https://github.com/rust-lang/cargo/issues/14679.\",\n        )\n        .arg_silent_suggestion()\n        .arg_manifest_path()\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    if let Err(e) = args.workspace(gctx) {\n        gctx.shell()\n            .print_json(&HashMap::from([(\"invalid\", e.to_string())]))?;\n        process::exit(1)\n    }\n\n    gctx.shell()\n        .print_json(&HashMap::from([(\"success\", \"true\")]))?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/version.rs",
    "content": "use crate::cli;\nuse crate::command_prelude::*;\n\npub fn cli() -> Command {\n    subcommand(\"version\")\n        .about(\"Show version information\")\n        .arg_silent_suggestion()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help version</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let verbose = args.verbose() > 0;\n    let version = cli::get_version_string(verbose);\n    cargo::drop_print!(gctx, \"{}\", version);\n    Ok(())\n}\n"
  },
  {
    "path": "src/bin/cargo/commands/yank.rs",
    "content": "use crate::command_prelude::*;\n\nuse anyhow::Context;\nuse cargo::ops;\nuse cargo_credential::Secret;\n\npub fn cli() -> Command {\n    subcommand(\"yank\")\n        .about(\"Remove a pushed crate from the index\")\n        .arg(Arg::new(\"crate\").value_name(\"CRATE\").action(ArgAction::Set))\n        .arg(\n            opt(\"version\", \"The version to yank or un-yank\")\n                .alias(\"vers\")\n                .value_name(\"VERSION\"),\n        )\n        .arg(flag(\n            \"undo\",\n            \"Undo a yank, putting a version back into the index\",\n        ))\n        .arg_index(\"Registry index URL to yank from\")\n        .arg_registry(\"Registry to yank from\")\n        .arg(opt(\"token\", \"API token to use when authenticating\").value_name(\"TOKEN\"))\n        .arg_silent_suggestion()\n        .after_help(color_print::cstr!(\n            \"Run `<bright-cyan,bold>cargo help yank</>` for more detailed information.\\n\"\n        ))\n}\n\npub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {\n    let (krate, version) = resolve_crate(\n        args.get_one::<String>(\"crate\").map(String::as_str),\n        args.get_one::<String>(\"version\").map(String::as_str),\n    )?;\n    if version.is_none() {\n        return Err(anyhow::format_err!(\"`--version` is required\").into());\n    }\n\n    ops::yank(\n        gctx,\n        krate.map(|s| s.to_string()),\n        version.map(|s| s.to_string()),\n        args.get_one::<String>(\"token\").cloned().map(Secret::from),\n        args.registry_or_index(gctx)?,\n        args.flag(\"undo\"),\n    )?;\n    Ok(())\n}\n\nfn resolve_crate<'k>(\n    mut krate: Option<&'k str>,\n    mut version: Option<&'k str>,\n) -> crate::CargoResult<(Option<&'k str>, Option<&'k str>)> {\n    if let Some((k, v)) = krate.and_then(|k| k.split_once('@')) {\n        if version.is_some() {\n            anyhow::bail!(\"cannot specify both `@{v}` and `--version`\");\n        }\n        if k.is_empty() {\n            // by convention, arguments starting with `@` are response files\n            anyhow::bail!(\"missing crate name for `@{v}`\");\n        }\n        krate = Some(k);\n        version = Some(v);\n    }\n\n    if let Some(version) = version {\n        semver::Version::parse(version).with_context(|| {\n            if let Some(stripped) = version.strip_prefix(\"v\") {\n                return format!(\n                    \"the version provided, `{version}` is not a \\\n                    valid SemVer version\\n\\n\\\n                    help: try changing the version to `{stripped}`\",\n                );\n            }\n            format!(\"invalid version `{version}`\")\n        })?;\n    }\n\n    Ok((krate, version))\n}\n"
  },
  {
    "path": "src/bin/cargo/main.rs",
    "content": "use cargo::core::features;\nuse cargo::core::shell::Shell;\nuse cargo::util::network::http::http_handle;\nuse cargo::util::network::http::needs_custom_http_transport;\nuse cargo::util::{self, CargoResult, closest_msg, command_prelude};\nuse cargo_util::{ProcessBuilder, ProcessError};\nuse cargo_util_schemas::manifest::StringOrVec;\nuse std::collections::BTreeMap;\nuse std::env;\nuse std::ffi::OsStr;\nuse std::fs;\nuse std::path::{Path, PathBuf};\n\nmod cli;\nmod commands;\n\nuse crate::command_prelude::*;\n\nfn main() {\n    let _guard = setup_logger();\n\n    let mut gctx = match GlobalContext::default() {\n        Ok(gctx) => gctx,\n        Err(e) => {\n            let mut shell = Shell::new();\n            cargo::exit_with_error(e.into(), &mut shell)\n        }\n    };\n\n    let nightly_features_allowed = matches!(&*features::channel(), \"nightly\" | \"dev\");\n    if nightly_features_allowed {\n        let _span = tracing::span!(tracing::Level::TRACE, \"completions\").entered();\n        let args = std::env::args_os();\n        let current_dir = std::env::current_dir().ok();\n        let completer = clap_complete::CompleteEnv::with_factory(|| {\n            let mut gctx = GlobalContext::default().expect(\"already loaded without errors\");\n            cli::cli(&mut gctx)\n        })\n        .var(\"CARGO_COMPLETE\");\n        if completer\n            .try_complete(args, current_dir.as_deref())\n            .unwrap_or_else(|e| {\n                let mut shell = Shell::new();\n                cargo::exit_with_error(e.into(), &mut shell)\n            })\n        {\n            return;\n        }\n    }\n\n    let result = if let Some(lock_addr) = cargo::ops::fix_get_proxy_lock_addr() {\n        cargo::ops::fix_exec_rustc(&gctx, &lock_addr).map_err(|e| CliError::from(e))\n    } else {\n        let _token = cargo::util::job::setup();\n        cli::main(&mut gctx)\n    };\n\n    match result {\n        Err(e) => cargo::exit_with_error(e, &mut *gctx.shell()),\n        Ok(()) => {}\n    }\n}\n\nfn setup_logger() -> Option<ChromeFlushGuard> {\n    use tracing_subscriber::prelude::*;\n\n    let env = tracing_subscriber::EnvFilter::from_env(\"CARGO_LOG\");\n    let fmt_layer = tracing_subscriber::fmt::layer()\n        .with_timer(tracing_subscriber::fmt::time::Uptime::default())\n        .with_ansi(std::io::IsTerminal::is_terminal(&std::io::stderr()))\n        .with_writer(std::io::stderr)\n        .with_filter(env);\n\n    let (profile_layer, profile_guard) = chrome_layer();\n\n    let registry = tracing_subscriber::registry()\n        .with(fmt_layer)\n        .with(profile_layer);\n    registry.init();\n    tracing::trace!(start = jiff::Timestamp::now().to_string());\n    profile_guard\n}\n\n#[cfg(target_has_atomic = \"64\")]\ntype ChromeFlushGuard = tracing_chrome::FlushGuard;\n#[cfg(target_has_atomic = \"64\")]\nfn chrome_layer<S>() -> (\n    Option<tracing_chrome::ChromeLayer<S>>,\n    Option<ChromeFlushGuard>,\n)\nwhere\n    S: tracing::Subscriber\n        + for<'span> tracing_subscriber::registry::LookupSpan<'span>\n        + Send\n        + Sync,\n{\n    #![expect(clippy::disallowed_methods, reason = \"runs before config is loaded\")]\n\n    if env_to_bool(std::env::var_os(\"CARGO_LOG_PROFILE\").as_deref()) {\n        let capture_args =\n            env_to_bool(std::env::var_os(\"CARGO_LOG_PROFILE_CAPTURE_ARGS\").as_deref());\n        let (layer, guard) = tracing_chrome::ChromeLayerBuilder::new()\n            .include_args(capture_args)\n            .build();\n        (Some(layer), Some(guard))\n    } else {\n        (None, None)\n    }\n}\n\n#[cfg(not(target_has_atomic = \"64\"))]\ntype ChromeFlushGuard = ();\n#[cfg(not(target_has_atomic = \"64\"))]\nfn chrome_layer() -> (\n    Option<tracing_subscriber::layer::Identity>,\n    Option<ChromeFlushGuard>,\n) {\n    (None, None)\n}\n\n#[cfg(target_has_atomic = \"64\")]\nfn env_to_bool(os: Option<&OsStr>) -> bool {\n    match os.and_then(|os| os.to_str()) {\n        Some(\"1\") | Some(\"true\") => true,\n        _ => false,\n    }\n}\n\n/// Table for defining the aliases which come builtin in `Cargo`.\n/// The contents are structured as: `(alias, aliased_command, description)`.\nconst BUILTIN_ALIASES: [(&str, &str, &str); 6] = [\n    (\"b\", \"build\", \"alias: build\"),\n    (\"c\", \"check\", \"alias: check\"),\n    (\"d\", \"doc\", \"alias: doc\"),\n    (\"r\", \"run\", \"alias: run\"),\n    (\"t\", \"test\", \"alias: test\"),\n    (\"rm\", \"remove\", \"alias: remove\"),\n];\n\n/// Function which contains the list of all of the builtin aliases and it's\n/// corresponding execs represented as &str.\nfn builtin_aliases_execs(cmd: &str) -> Option<&(&str, &str, &str)> {\n    BUILTIN_ALIASES.iter().find(|alias| alias.0 == cmd)\n}\n\n/// Resolve the aliased command from the [`GlobalContext`] with a given command string.\n///\n/// The search fallback chain is:\n///\n/// 1. Get the aliased command as a string.\n/// 2. If an `Err` occurs (missing key, type mismatch, or any possible error),\n///    try to get it as an array again.\n/// 3. If still cannot find any, finds one insides [`BUILTIN_ALIASES`].\nfn aliased_command(gctx: &GlobalContext, command: &str) -> CargoResult<Option<Vec<String>>> {\n    let alias_name = format!(\"alias.{}\", command);\n    let user_alias = match gctx.get_string(&alias_name) {\n        Ok(Some(record)) => Some(\n            record\n                .val\n                .split_whitespace()\n                .map(|s| s.to_string())\n                .collect(),\n        ),\n        Ok(None) => None,\n        Err(_) => gctx.get::<Option<Vec<String>>>(&alias_name)?,\n    };\n\n    let result = user_alias.or_else(|| {\n        builtin_aliases_execs(command).map(|command_str| vec![command_str.1.to_string()])\n    });\n    if result\n        .as_ref()\n        .map(|alias| alias.is_empty())\n        .unwrap_or_default()\n    {\n        anyhow::bail!(\"subcommand is required, but `{alias_name}` is empty\");\n    }\n    Ok(result)\n}\n\n/// List all runnable commands\nfn list_commands(gctx: &GlobalContext) -> BTreeMap<String, CommandInfo> {\n    let mut commands = third_party_subcommands(gctx);\n\n    for cmd in commands::builtin() {\n        commands.insert(\n            cmd.get_name().to_string(),\n            CommandInfo::BuiltIn {\n                about: cmd.get_about().map(|s| s.to_string()),\n            },\n        );\n    }\n\n    // Add the builtin_aliases and them descriptions to the\n    // `commands` `BTreeMap`.\n    for command in &BUILTIN_ALIASES {\n        commands.insert(\n            command.0.to_string(),\n            CommandInfo::BuiltIn {\n                about: Some(command.2.to_string()),\n            },\n        );\n    }\n\n    // Add the user-defined aliases\n    let alias_commands = user_defined_aliases(gctx);\n    commands.extend(alias_commands);\n\n    // `help` is special, so it needs to be inserted separately.\n    commands.insert(\n        \"help\".to_string(),\n        CommandInfo::BuiltIn {\n            about: Some(\"Displays help for a cargo command\".to_string()),\n        },\n    );\n\n    commands\n}\n\nfn third_party_subcommands(gctx: &GlobalContext) -> BTreeMap<String, CommandInfo> {\n    let prefix = \"cargo-\";\n    let suffix = env::consts::EXE_SUFFIX;\n    let mut commands = BTreeMap::new();\n    for dir in search_directories(gctx) {\n        let entries = match fs::read_dir(dir) {\n            Ok(entries) => entries,\n            _ => continue,\n        };\n        for entry in entries.filter_map(|e| e.ok()) {\n            let path = entry.path();\n            let Some(filename) = path.file_name().and_then(|s| s.to_str()) else {\n                continue;\n            };\n            let Some(name) = filename\n                .strip_prefix(prefix)\n                .and_then(|s| s.strip_suffix(suffix))\n            else {\n                continue;\n            };\n            if is_executable(entry.path()) {\n                commands.insert(\n                    name.to_string(),\n                    CommandInfo::External { path: path.clone() },\n                );\n            }\n        }\n    }\n    commands\n}\n\nfn user_defined_aliases(gctx: &GlobalContext) -> BTreeMap<String, CommandInfo> {\n    let mut commands = BTreeMap::new();\n    if let Ok(aliases) = gctx.get::<BTreeMap<String, StringOrVec>>(\"alias\") {\n        for (name, target) in aliases.iter() {\n            commands.insert(\n                name.to_string(),\n                CommandInfo::Alias {\n                    target: target.clone(),\n                },\n            );\n        }\n    }\n    commands\n}\n\nfn find_external_subcommand(gctx: &GlobalContext, cmd: &str) -> Option<PathBuf> {\n    let command_exe = format!(\"cargo-{}{}\", cmd, env::consts::EXE_SUFFIX);\n    search_directories(gctx)\n        .iter()\n        .map(|dir| dir.join(&command_exe))\n        .find(|file| is_executable(file))\n}\n\nfn execute_external_subcommand(gctx: &GlobalContext, cmd: &str, args: &[&OsStr]) -> CliResult {\n    let path = find_external_subcommand(gctx, cmd);\n    let command = match path {\n        Some(command) => command,\n        None => {\n            let script_suggestion = if gctx.cli_unstable().script\n                && std::path::Path::new(cmd).is_file()\n            {\n                let sep = std::path::MAIN_SEPARATOR;\n                format!(\n                    \"\\nhelp: to run the file `{cmd}`, provide a relative path like `.{sep}{cmd}`\"\n                )\n            } else {\n                \"\".to_owned()\n            };\n            let err = if cmd.starts_with('+') {\n                anyhow::format_err!(\n                    \"no such command: `{cmd}`\\n\\n\\\n                    help: invoke `cargo` through `rustup` to handle `+toolchain` directives{script_suggestion}\",\n                )\n            } else {\n                let suggestions = list_commands(gctx);\n                let did_you_mean = closest_msg(cmd, suggestions.keys(), |c| c, \"command\");\n\n                anyhow::format_err!(\n                    \"no such command: `{cmd}`{did_you_mean}\\n\\n\\\n                    help: view all installed commands with `cargo --list`\\n\\\n                    help: find a package to install `{cmd}` with `cargo search cargo-{cmd}`{script_suggestion}\",\n                )\n            };\n\n            return Err(CliError::new(err, 101));\n        }\n    };\n    execute_subcommand(gctx, Some(&command), args)\n}\n\nfn execute_internal_subcommand(gctx: &GlobalContext, args: &[&OsStr]) -> CliResult {\n    execute_subcommand(gctx, None, args)\n}\n\n// This function is used to execute a subcommand. It is used to execute both\n// internal and external subcommands.\n// If `cmd_path` is `None`, then the subcommand is an internal subcommand.\nfn execute_subcommand(\n    gctx: &GlobalContext,\n    cmd_path: Option<&PathBuf>,\n    args: &[&OsStr],\n) -> CliResult {\n    let cargo_exe = gctx.cargo_exe()?;\n    let mut cmd = match cmd_path {\n        Some(cmd_path) => ProcessBuilder::new(cmd_path),\n        None => ProcessBuilder::new(&cargo_exe),\n    };\n    cmd.env(cargo::CARGO_ENV, cargo_exe).args(args);\n    if let Some(client) = gctx.jobserver_from_env() {\n        cmd.inherit_jobserver(client);\n    }\n    let err = match cmd.exec_replace() {\n        Ok(()) => return Ok(()),\n        Err(e) => e,\n    };\n\n    if let Some(perr) = err.downcast_ref::<ProcessError>() {\n        if let Some(code) = perr.code {\n            return Err(CliError::code(code));\n        }\n    }\n    Err(CliError::new(err, 101))\n}\n\n#[cfg(unix)]\nfn is_executable<P: AsRef<Path>>(path: P) -> bool {\n    use std::os::unix::prelude::*;\n    fs::metadata(path)\n        .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0)\n        .unwrap_or(false)\n}\n#[cfg(windows)]\nfn is_executable<P: AsRef<Path>>(path: P) -> bool {\n    path.as_ref().is_file()\n}\n\nfn search_directories(gctx: &GlobalContext) -> Vec<PathBuf> {\n    let mut path_dirs = if let Some(val) = gctx.get_env_os(\"PATH\") {\n        env::split_paths(&val).collect()\n    } else {\n        vec![]\n    };\n\n    let home_bin = gctx.home().clone().into_path_unlocked().join(\"bin\");\n\n    // If any of that PATH elements contains `home_bin`, do not\n    // add it again. This is so that the users can control priority\n    // of it using PATH, while preserving the historical\n    // behavior of preferring it over system global directories even\n    // when not in PATH at all.\n    // See https://github.com/rust-lang/cargo/issues/11020 for details.\n    //\n    // Note: `p == home_bin` will ignore trailing slash, but we don't\n    // `canonicalize` the paths.\n    if !path_dirs.iter().any(|p| p == &home_bin) {\n        path_dirs.insert(0, home_bin);\n    };\n\n    path_dirs\n}\n\n/// Initialize libgit2.\n#[tracing::instrument(skip_all)]\nfn init_git(gctx: &GlobalContext) {\n    // Disabling the owner validation in git can, in theory, lead to code execution\n    // vulnerabilities. However, libgit2 does not launch executables, which is the foundation of\n    // the original security issue. Meanwhile, issues with refusing to load git repos in\n    // `CARGO_HOME` for example will likely be very frustrating for users. So, we disable the\n    // validation.\n    //\n    // For further discussion of Cargo's current interactions with git, see\n    //\n    //   https://github.com/rust-lang/rfcs/pull/3279\n    //\n    // and in particular the subsection on \"Git support\".\n    //\n    // Note that we only disable this when Cargo is run as a binary. If Cargo is used as a library,\n    // this code won't be invoked. Instead, developers will need to explicitly disable the\n    // validation in their code. This is inconvenient, but won't accidentally open consuming\n    // applications up to security issues if they use git2 to open repositories elsewhere in their\n    // code.\n    unsafe {\n        git2::opts::set_verify_owner_validation(false)\n            .expect(\"set_verify_owner_validation should never fail\");\n    }\n\n    init_git_transports(gctx);\n}\n\n/// Configure libgit2 to use libcurl if necessary.\n///\n/// If the user has a non-default network configuration, then libgit2 will be\n/// configured to use libcurl instead of the built-in networking support so\n/// that those configuration settings can be used.\n#[tracing::instrument(skip_all)]\nfn init_git_transports(gctx: &GlobalContext) {\n    match needs_custom_http_transport(gctx) {\n        Ok(true) => {}\n        _ => return,\n    }\n\n    let handle = match http_handle(gctx) {\n        Ok(handle) => handle,\n        Err(..) => return,\n    };\n\n    // The unsafety of the registration function derives from two aspects:\n    //\n    // 1. This call must be synchronized with all other registration calls as\n    //    well as construction of new transports.\n    // 2. The argument is leaked.\n    //\n    // We're clear on point (1) because this is only called at the start of this\n    // binary (we know what the state of the world looks like) and we're mostly\n    // clear on point (2) because we'd only free it after everything is done\n    // anyway\n    unsafe {\n        git2_curl::register(handle);\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/artifact.rs",
    "content": "//! Generate artifact information from unit dependencies for configuring the compiler environment.\n\nuse crate::CargoResult;\nuse crate::core::compiler::unit_graph::UnitDep;\nuse crate::core::compiler::{BuildRunner, CrateType, FileFlavor, Unit};\nuse crate::core::dependency::ArtifactKind;\nuse crate::core::{Dependency, Target, TargetKind};\nuse std::collections::{HashMap, HashSet};\nuse std::ffi::OsString;\n\n/// Return all environment variables for the given unit-dependencies\n/// if artifacts are present.\npub fn get_env(\n    build_runner: &BuildRunner<'_, '_>,\n    unit: &Unit,\n    dependencies: &[UnitDep],\n) -> CargoResult<HashMap<String, OsString>> {\n    let mut env = HashMap::new();\n\n    // Add `CARGO_BIN_EXE_` environment variables for building tests.\n    //\n    // These aren't built for `cargo check`, so can't use `dependencies`\n    if unit.target.is_test() || unit.target.is_bench() {\n        for bin_target in unit\n            .pkg\n            .manifest()\n            .targets()\n            .iter()\n            .filter(|target| target.is_bin())\n        {\n            let name = bin_target\n                .binary_filename()\n                .unwrap_or_else(|| bin_target.name().to_string());\n\n            // For `cargo check` builds we do not uplift the CARGO_BIN_EXE_ artifacts to the\n            // artifact-dir. We do not want to provide a path to a non-existent binary but we still\n            // need to provide *something* so `env!(\"CARGO_BIN_EXE_...\")` macros will compile.\n            let exe_path = build_runner\n                .files()\n                .bin_link_for_target(bin_target, unit.kind, build_runner.bcx)?\n                .map(|path| path.as_os_str().to_os_string())\n                .unwrap_or_else(|| OsString::from(format!(\"placeholder:{name}\")));\n\n            let key = format!(\"CARGO_BIN_EXE_{name}\");\n            env.insert(key, exe_path);\n        }\n    }\n\n    for unit_dep in dependencies.iter().filter(|d| d.unit.artifact.is_true()) {\n        for artifact_path in build_runner\n            .outputs(&unit_dep.unit)?\n            .iter()\n            .filter_map(|f| (f.flavor == FileFlavor::Normal).then(|| &f.path))\n        {\n            let artifact_type_upper = unit_artifact_type_name_upper(&unit_dep.unit);\n            let dep_name = unit_dep.dep_name.unwrap_or(unit_dep.unit.pkg.name());\n            let dep_name_upper = dep_name.to_uppercase().replace(\"-\", \"_\");\n\n            let var = format!(\"CARGO_{}_DIR_{}\", artifact_type_upper, dep_name_upper);\n            let path = artifact_path.parent().expect(\"parent dir for artifacts\");\n            env.insert(var, path.to_owned().into());\n\n            let var_file = format!(\n                \"CARGO_{}_FILE_{}_{}\",\n                artifact_type_upper,\n                dep_name_upper,\n                unit_dep.unit.target.name()\n            );\n\n            // In older releases, lib-targets defaulted to the name of the package. Newer releases\n            // use the same name as default, but with dashes replaced. Hence, if the name of the\n            // target was inferred by Cargo, we also set the env-var with the unconverted name for\n            // backwards compatibility.\n            let need_compat = unit_dep.unit.target.is_lib() && unit_dep.unit.target.name_inferred();\n            if need_compat {\n                let var_compat = format!(\n                    \"CARGO_{}_FILE_{}_{}\",\n                    artifact_type_upper,\n                    dep_name_upper,\n                    unit_dep.unit.pkg.name(),\n                );\n                if var_compat != var_file {\n                    env.insert(var_compat, artifact_path.to_owned().into());\n                }\n            }\n\n            env.insert(var_file, artifact_path.to_owned().into());\n\n            // If the name of the target matches the name of the dependency, we strip the\n            // repetition and provide the simpler env-var as well.\n            // For backwards-compatibility of inferred names, we compare against the name of the\n            // package as well, since that used to be the default for library targets.\n            if unit_dep.unit.target.name() == dep_name.as_str()\n                || (need_compat && unit_dep.unit.pkg.name() == dep_name.as_str())\n            {\n                let var = format!(\"CARGO_{}_FILE_{}\", artifact_type_upper, dep_name_upper,);\n                env.insert(var, artifact_path.to_owned().into());\n            }\n        }\n    }\n    Ok(env)\n}\n\nfn unit_artifact_type_name_upper(unit: &Unit) -> &'static str {\n    match unit.target.kind() {\n        TargetKind::Lib(kinds) => match kinds.as_slice() {\n            &[CrateType::Cdylib] => \"CDYLIB\",\n            &[CrateType::Staticlib] => \"STATICLIB\",\n            invalid => unreachable!(\"BUG: artifacts cannot be of type {:?}\", invalid),\n        },\n        TargetKind::Bin => \"BIN\",\n        invalid => unreachable!(\"BUG: artifacts cannot be of type {:?}\", invalid),\n    }\n}\n\n/// Given a dependency with an artifact `artifact_dep` and a set of available `targets`\n/// of its package, find a target for each kind of artifacts that are to be built.\n///\n/// Failure to match any target results in an error mentioning the parent manifests\n/// `parent_package` name.\npub(crate) fn match_artifacts_kind_with_targets<'t, 'd>(\n    artifact_dep: &'d Dependency,\n    targets: &'t [Target],\n    parent_package: &str,\n) -> CargoResult<HashSet<(&'d ArtifactKind, &'t Target)>> {\n    let mut out = HashSet::new();\n    let artifact_requirements = artifact_dep.artifact().expect(\"artifact present\");\n    for artifact_kind in artifact_requirements.kinds() {\n        let mut extend = |kind, filter: &dyn Fn(&&Target) -> bool| {\n            let mut iter = targets.iter().filter(filter).peekable();\n            let found = iter.peek().is_some();\n            out.extend(std::iter::repeat(kind).zip(iter));\n            found\n        };\n        let found = match artifact_kind {\n            ArtifactKind::Cdylib => extend(artifact_kind, &|t| t.is_cdylib()),\n            ArtifactKind::Staticlib => extend(artifact_kind, &|t| t.is_staticlib()),\n            ArtifactKind::AllBinaries => extend(artifact_kind, &|t| t.is_bin()),\n            ArtifactKind::SelectedBinary(bin_name) => extend(artifact_kind, &|t| {\n                t.is_bin() && t.name() == bin_name.as_str()\n            }),\n        };\n        if !found {\n            anyhow::bail!(\n                \"dependency `{}` in package `{}` requires a `{}` artifact to be present.\",\n                artifact_dep.name_in_toml(),\n                parent_package,\n                artifact_kind\n            );\n        }\n    }\n    Ok(out)\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/build_config.rs",
    "content": "use crate::core::compiler::CompileKind;\nuse crate::util::context::JobsConfig;\nuse crate::util::interning::InternedString;\nuse crate::util::{CargoResult, GlobalContext, RustfixDiagnosticServer};\nuse anyhow::{Context as _, bail};\nuse cargo_util::ProcessBuilder;\nuse serde::ser;\nuse std::cell::RefCell;\nuse std::path::PathBuf;\nuse std::rc::Rc;\nuse std::thread::available_parallelism;\n\n/// Configuration information for a rustc build.\n#[derive(Debug, Clone)]\npub struct BuildConfig {\n    /// The requested kind of compilation for this session\n    pub requested_kinds: Vec<CompileKind>,\n    /// Number of rustc jobs to run in parallel.\n    pub jobs: u32,\n    /// Do not abort the build as soon as there is an error.\n    pub keep_going: bool,\n    /// Build profile\n    pub requested_profile: InternedString,\n    /// The intent we are compiling in.\n    pub intent: UserIntent,\n    /// `true` to print stdout in JSON format (for machine reading).\n    pub message_format: MessageFormat,\n    /// Force Cargo to do a full rebuild and treat each target as changed.\n    pub force_rebuild: bool,\n    /// Output the unit graph to stdout instead of actually compiling.\n    pub unit_graph: bool,\n    /// `true` to avoid really compiling.\n    pub dry_run: bool,\n    /// An optional override of the rustc process for primary units\n    pub primary_unit_rustc: Option<ProcessBuilder>,\n    /// A thread used by `cargo fix` to receive messages on a socket regarding\n    /// the success/failure of applying fixes.\n    pub rustfix_diagnostic_server: Rc<RefCell<Option<RustfixDiagnosticServer>>>,\n    /// The directory to copy final artifacts to. Note that even if\n    /// `artifact-dir` is set, a copy of artifacts still can be found at\n    /// `target/(debug\\release)` as usual.\n    /// Named `export_dir` to avoid confusion with\n    /// `CompilationFiles::artifact_dir`.\n    pub export_dir: Option<PathBuf>,\n    /// `true` to output a future incompatibility report at the end of the build\n    pub future_incompat_report: bool,\n    /// Output timing report at the end of the build\n    pub timing_report: bool,\n    /// Output SBOM precursor files.\n    pub sbom: bool,\n    /// Build compile time dependencies only, e.g., build scripts and proc macros\n    pub compile_time_deps_only: bool,\n}\n\nfn default_parallelism() -> CargoResult<u32> {\n    Ok(available_parallelism()\n        .context(\"failed to determine the amount of parallelism available\")?\n        .get() as u32)\n}\n\nimpl BuildConfig {\n    /// Parses all config files to learn about build configuration. Currently\n    /// configured options are:\n    ///\n    /// * `build.jobs`\n    /// * `build.target`\n    /// * `target.$target.ar`\n    /// * `target.$target.linker`\n    /// * `target.$target.libfoo.metadata`\n    pub fn new(\n        gctx: &GlobalContext,\n        jobs: Option<JobsConfig>,\n        keep_going: bool,\n        requested_targets: &[String],\n        intent: UserIntent,\n    ) -> CargoResult<BuildConfig> {\n        let cfg = gctx.build_config()?;\n        let requested_kinds = CompileKind::from_requested_targets(gctx, requested_targets)?;\n        if jobs.is_some() && gctx.jobserver_from_env().is_some() {\n            gctx.shell().warn(\n                \"a `-j` argument was passed to Cargo but Cargo is \\\n                 also configured with an external jobserver in \\\n                 its environment, ignoring the `-j` parameter\",\n            )?;\n        }\n        let jobs = match jobs.or(cfg.jobs.clone()) {\n            None => default_parallelism()?,\n            Some(value) => match value {\n                JobsConfig::Integer(j) => match j {\n                    0 => anyhow::bail!(\"jobs may not be 0\"),\n                    j if j < 0 => (default_parallelism()? as i32 + j).max(1) as u32,\n                    j => j as u32,\n                },\n                JobsConfig::String(j) => match j.as_str() {\n                    \"default\" => default_parallelism()?,\n                    _ => {\n                        anyhow::bail!(format!(\n                            \"could not parse `{j}`. Number of parallel jobs should be `default` or a number.\"\n                        ))\n                    }\n                },\n            },\n        };\n\n        // If sbom flag is set, it requires the unstable feature\n        let sbom = match (cfg.sbom, gctx.cli_unstable().sbom) {\n            (Some(sbom), true) => sbom,\n            (Some(_), false) => {\n                gctx.shell()\n                    .warn(\"ignoring 'sbom' config, pass `-Zsbom` to enable it\")?;\n                false\n            }\n            (None, _) => false,\n        };\n\n        Ok(BuildConfig {\n            requested_kinds,\n            jobs,\n            keep_going,\n            requested_profile: \"dev\".into(),\n            intent,\n            message_format: MessageFormat::Human,\n            force_rebuild: false,\n            unit_graph: false,\n            dry_run: false,\n            primary_unit_rustc: None,\n            rustfix_diagnostic_server: Rc::new(RefCell::new(None)),\n            export_dir: None,\n            future_incompat_report: false,\n            timing_report: false,\n            sbom,\n            compile_time_deps_only: false,\n        })\n    }\n\n    /// Whether or not the *user* wants JSON output. Whether or not rustc\n    /// actually uses JSON is decided in `add_error_format`.\n    pub fn emit_json(&self) -> bool {\n        matches!(self.message_format, MessageFormat::Json { .. })\n    }\n\n    pub fn single_requested_kind(&self) -> CargoResult<CompileKind> {\n        match self.requested_kinds.len() {\n            1 => Ok(self.requested_kinds[0]),\n            _ => bail!(\"only one `--target` argument is supported\"),\n        }\n    }\n}\n\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npub enum MessageFormat {\n    Human,\n    Json {\n        /// Whether rustc diagnostics are rendered by cargo or included into the\n        /// output stream.\n        render_diagnostics: bool,\n        /// Whether the `rendered` field of rustc diagnostics are using the\n        /// \"short\" rendering.\n        short: bool,\n        /// Whether the `rendered` field of rustc diagnostics embed ansi color\n        /// codes.\n        ansi: bool,\n    },\n    Short,\n}\n\n/// The specific action to be performed on each `Unit` of work.\n#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)]\npub enum CompileMode {\n    /// Test with `rustc`.\n    Test,\n    /// Compile with `rustc`.\n    Build,\n    /// Type-check with `rustc` by emitting `rmeta` metadata only.\n    ///\n    /// If `test` is true, then it is also compiled with `--test` to check it like\n    /// a test.\n    Check { test: bool },\n    /// Document with `rustdoc`.\n    Doc,\n    /// Test with `rustdoc`.\n    Doctest,\n    /// Scrape for function calls by `rustdoc`.\n    Docscrape,\n    /// Execute the binary built from the `build.rs` script.\n    RunCustomBuild,\n}\n\nimpl ser::Serialize for CompileMode {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        use self::CompileMode::*;\n        match *self {\n            Test => \"test\".serialize(s),\n            Build => \"build\".serialize(s),\n            Check { .. } => \"check\".serialize(s),\n            Doc { .. } => \"doc\".serialize(s),\n            Doctest => \"doctest\".serialize(s),\n            Docscrape => \"docscrape\".serialize(s),\n            RunCustomBuild => \"run-custom-build\".serialize(s),\n        }\n    }\n}\n\nimpl<'de> serde::Deserialize<'de> for CompileMode {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        let s = String::deserialize(deserializer)?;\n        match s.as_str() {\n            \"test\" => Ok(CompileMode::Test),\n            \"build\" => Ok(CompileMode::Build),\n            \"check\" => Ok(CompileMode::Check { test: false }),\n            \"doc\" => Ok(CompileMode::Doc),\n            \"doctest\" => Ok(CompileMode::Doctest),\n            \"docscrape\" => Ok(CompileMode::Docscrape),\n            \"run-custom-build\" => Ok(CompileMode::RunCustomBuild),\n            other => Err(serde::de::Error::unknown_variant(\n                other,\n                &[\n                    \"test\",\n                    \"build\",\n                    \"check\",\n                    \"doc\",\n                    \"doctest\",\n                    \"docscrape\",\n                    \"run-custom-build\",\n                ],\n            )),\n        }\n    }\n}\n\nimpl CompileMode {\n    /// Returns `true` if the unit is being checked.\n    pub fn is_check(self) -> bool {\n        matches!(self, CompileMode::Check { .. })\n    }\n\n    /// Returns `true` if this is generating documentation.\n    pub fn is_doc(self) -> bool {\n        matches!(self, CompileMode::Doc { .. })\n    }\n\n    /// Returns `true` if this a doc test.\n    pub fn is_doc_test(self) -> bool {\n        self == CompileMode::Doctest\n    }\n\n    /// Returns `true` if this is scraping examples for documentation.\n    pub fn is_doc_scrape(self) -> bool {\n        self == CompileMode::Docscrape\n    }\n\n    /// Returns `true` if this is any type of test (test, benchmark, doc test, or\n    /// check test).\n    pub fn is_any_test(self) -> bool {\n        matches!(\n            self,\n            CompileMode::Test | CompileMode::Check { test: true } | CompileMode::Doctest\n        )\n    }\n\n    /// Returns `true` if this is something that passes `--test` to rustc.\n    pub fn is_rustc_test(self) -> bool {\n        matches!(self, CompileMode::Test | CompileMode::Check { test: true })\n    }\n\n    /// Returns `true` if this is the *execution* of a `build.rs` script.\n    pub fn is_run_custom_build(self) -> bool {\n        self == CompileMode::RunCustomBuild\n    }\n\n    /// Returns `true` if this mode may generate an executable.\n    ///\n    /// Note that this also returns `true` for building libraries, so you also\n    /// have to check the target.\n    pub fn generates_executable(self) -> bool {\n        matches!(self, CompileMode::Test | CompileMode::Build)\n    }\n}\n\n/// Represents the high-level operation requested by the user.\n///\n/// It determines which \"Cargo targets\" are selected by default and influences\n/// how they will be processed. This is derived from the Cargo command the user\n/// invoked (like `cargo build` or `cargo test`).\n///\n/// Unlike [`CompileMode`], which describes the specific compilation steps for\n/// individual units, [`UserIntent`] represents the overall goal of the build\n/// process as specified by the user.\n///\n/// For example, when a user runs `cargo test`, the intent is [`UserIntent::Test`],\n/// but this might result in multiple [`CompileMode`]s for different units.\n#[derive(Clone, Copy, Debug)]\npub enum UserIntent {\n    /// Build benchmark binaries, e.g., `cargo bench`\n    Bench,\n    /// Build binaries and libraries, e.g., `cargo run`, `cargo install`, `cargo build`.\n    Build,\n    /// Perform type-check, e.g., `cargo check`.\n    Check { test: bool },\n    /// Document packages.\n    ///\n    /// If `deps` is true, then it will also document all dependencies.\n    /// if `json` is true, the documentation output is in json format.\n    Doc { deps: bool, json: bool },\n    /// Build doctest binaries, e.g., `cargo test --doc`\n    Doctest,\n    /// Build test binaries, e.g., `cargo test`\n    Test,\n}\n\nimpl UserIntent {\n    /// Returns `true` if this is generating documentation.\n    pub fn is_doc(self) -> bool {\n        matches!(self, UserIntent::Doc { .. })\n    }\n\n    /// User wants rustdoc output in JSON format.\n    pub fn wants_doc_json_output(self) -> bool {\n        matches!(self, UserIntent::Doc { json: true, .. })\n    }\n\n    /// User wants to document also for dependencies.\n    pub fn wants_deps_docs(self) -> bool {\n        matches!(self, UserIntent::Doc { deps: true, .. })\n    }\n\n    /// Returns `true` if this is any type of test (test, benchmark, doc test, or\n    /// check test).\n    pub fn is_any_test(self) -> bool {\n        matches!(\n            self,\n            UserIntent::Test\n                | UserIntent::Bench\n                | UserIntent::Check { test: true }\n                | UserIntent::Doctest\n        )\n    }\n\n    /// Returns `true` if this is something that passes `--test` to rustc.\n    pub fn is_rustc_test(self) -> bool {\n        matches!(\n            self,\n            UserIntent::Test | UserIntent::Bench | UserIntent::Check { test: true }\n        )\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/build_context/mod.rs",
    "content": "//! [`BuildContext`] is a (mostly) static information about a build task.\n\nuse crate::core::PackageSet;\nuse crate::core::Workspace;\nuse crate::core::compiler::BuildConfig;\nuse crate::core::compiler::CompileKind;\nuse crate::core::compiler::Unit;\nuse crate::core::compiler::UnitIndex;\nuse crate::core::compiler::unit_graph::UnitGraph;\nuse crate::core::profiles::Profiles;\nuse crate::util::Rustc;\nuse crate::util::context::GlobalContext;\nuse crate::util::errors::CargoResult;\nuse crate::util::interning::InternedString;\nuse crate::util::logger::BuildLogger;\nuse std::collections::{HashMap, HashSet};\n\nmod target_info;\npub use self::target_info::FileFlavor;\npub use self::target_info::FileType;\npub use self::target_info::RustcTargetData;\npub use self::target_info::TargetInfo;\n\n/// The build context, containing complete information needed for a build task\n/// before it gets started.\n///\n/// It is intended that this is mostly static information. Stuff that mutates\n/// during the build can be found in the parent [`BuildRunner`]. (I say mostly,\n/// because this has internal caching, but nothing that should be observable\n/// or require &mut.)\n///\n/// As a result, almost every field on `BuildContext` is public, including\n///\n/// * a resolved [`UnitGraph`] of your dependencies,\n/// * a [`Profiles`] containing compiler flags presets,\n/// * a [`RustcTargetData`] containing host and target platform information,\n/// * and a [`PackageSet`] for further package downloads,\n///\n/// just to name a few. Learn more on each own documentation.\n///\n/// # How to use\n///\n/// To prepare a build task, you may not want to use [`BuildContext::new`] directly,\n/// since it is often too lower-level.\n/// Instead, [`ops::create_bcx`] is usually what you are looking for.\n///\n/// After a `BuildContext` is built, the next stage of building is handled in [`BuildRunner`].\n///\n/// [`BuildRunner`]: crate::core::compiler::BuildRunner\n/// [`ops::create_bcx`]: crate::ops::create_bcx\npub struct BuildContext<'a, 'gctx> {\n    /// The workspace the build is for.\n    pub ws: &'a Workspace<'gctx>,\n\n    /// The cargo context.\n    pub gctx: &'gctx GlobalContext,\n\n    /// Build logger for `-Zbuild-analysis`.\n    pub logger: Option<&'a BuildLogger>,\n\n    /// This contains a collection of compiler flags presets.\n    pub profiles: Profiles,\n\n    /// Configuration information for a rustc build.\n    pub build_config: &'a BuildConfig,\n\n    /// Extra compiler args for either `rustc` or `rustdoc`.\n    pub extra_compiler_args: HashMap<Unit, Vec<String>>,\n\n    /// Package downloader.\n    ///\n    /// This holds ownership of the `Package` objects.\n    pub packages: PackageSet<'gctx>,\n\n    /// Information about rustc and the target platform.\n    pub target_data: RustcTargetData<'gctx>,\n\n    /// The root units of `unit_graph` (units requested on the command-line).\n    pub roots: Vec<Unit>,\n\n    /// The dependency graph of units to compile.\n    pub unit_graph: UnitGraph,\n\n    /// A map from unit to index.\n    pub unit_to_index: HashMap<Unit, UnitIndex>,\n\n    /// Reverse-dependencies of documented units, used by the `rustdoc --scrape-examples` flag.\n    pub scrape_units: Vec<Unit>,\n\n    /// The list of all kinds that are involved in this build\n    pub all_kinds: HashSet<CompileKind>,\n}\n\nimpl<'a, 'gctx> BuildContext<'a, 'gctx> {\n    pub fn new(\n        ws: &'a Workspace<'gctx>,\n        logger: Option<&'a BuildLogger>,\n        packages: PackageSet<'gctx>,\n        build_config: &'a BuildConfig,\n        profiles: Profiles,\n        extra_compiler_args: HashMap<Unit, Vec<String>>,\n        target_data: RustcTargetData<'gctx>,\n        roots: Vec<Unit>,\n        unit_graph: UnitGraph,\n        unit_to_index: HashMap<Unit, UnitIndex>,\n        scrape_units: Vec<Unit>,\n    ) -> CargoResult<BuildContext<'a, 'gctx>> {\n        let all_kinds = unit_graph\n            .keys()\n            .map(|u| u.kind)\n            .chain(build_config.requested_kinds.iter().copied())\n            .chain(std::iter::once(CompileKind::Host))\n            .collect();\n\n        Ok(BuildContext {\n            ws,\n            gctx: ws.gctx(),\n            logger,\n            packages,\n            build_config,\n            profiles,\n            extra_compiler_args,\n            target_data,\n            roots,\n            unit_graph,\n            unit_to_index,\n            scrape_units,\n            all_kinds,\n        })\n    }\n\n    /// Information of the `rustc` this build task will use.\n    pub fn rustc(&self) -> &Rustc {\n        &self.target_data.rustc\n    }\n\n    /// Gets the host architecture triple.\n    ///\n    /// For example, `x86_64-unknown-linux-gnu`, would be\n    /// - machine: `x86_64`,\n    /// - hardware-platform: `unknown`,\n    /// - operating system: `linux-gnu`.\n    pub fn host_triple(&self) -> InternedString {\n        self.target_data.rustc.host\n    }\n\n    /// Gets the number of jobs specified for this build.\n    pub fn jobs(&self) -> u32 {\n        self.build_config.jobs\n    }\n\n    /// Extra compiler args for either `rustc` or `rustdoc`.\n    ///\n    /// As of now, these flags come from the trailing args of either\n    /// `cargo rustc` or `cargo rustdoc`.\n    pub fn extra_args_for(&self, unit: &Unit) -> Option<&Vec<String>> {\n        self.extra_compiler_args.get(unit)\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/build_context/target_info.rs",
    "content": "//! This modules contains types storing information of target platforms.\n//!\n//! Normally, call [`RustcTargetData::new`] to construct all the target\n//! platform once, and then query info on your demand. For example,\n//!\n//! * [`RustcTargetData::dep_platform_activated`] to check if platform is activated.\n//! * [`RustcTargetData::info`] to get a [`TargetInfo`] for an in-depth query.\n//! * [`TargetInfo::rustc_outputs`] to get a list of supported file types.\n\nuse crate::core::compiler::CompileKind;\nuse crate::core::compiler::CompileMode;\nuse crate::core::compiler::CompileTarget;\nuse crate::core::compiler::CrateType;\nuse crate::core::compiler::apply_env_config;\nuse crate::core::{Dependency, Package, Target, TargetKind, Workspace};\nuse crate::util::context::{GlobalContext, StringList, TargetConfig};\nuse crate::util::interning::InternedString;\nuse crate::util::{CargoResult, Rustc};\n\nuse anyhow::Context as _;\nuse cargo_platform::{Cfg, CfgExpr};\nuse cargo_util::ProcessBuilder;\nuse serde::Deserialize;\n\nuse std::cell::RefCell;\nuse std::collections::hash_map::{Entry, HashMap};\nuse std::path::PathBuf;\nuse std::rc::Rc;\nuse std::str::{self, FromStr};\n\n/// Information about the platform target gleaned from querying rustc.\n///\n/// [`RustcTargetData`] keeps several of these, one for the host and the others\n/// for other specified targets. If no target is specified, it uses a clone from\n/// the host.\n#[derive(Clone)]\npub struct TargetInfo {\n    /// A base process builder for discovering crate type information. In\n    /// particular, this is used to determine the output filename prefix and\n    /// suffix for a crate type.\n    crate_type_process: ProcessBuilder,\n    /// Cache of output filename prefixes and suffixes.\n    ///\n    /// The key is the crate type name (like `cdylib`) and the value is\n    /// `Some((prefix, suffix))`, for example `libcargo.so` would be\n    /// `Some((\"lib\", \".so\"))`. The value is `None` if the crate type is not\n    /// supported.\n    crate_types: RefCell<HashMap<CrateType, Option<(String, String)>>>,\n    /// `cfg` information extracted from `rustc --print=cfg`.\n    cfg: Vec<Cfg>,\n    /// `supports_std` information extracted from `rustc --print=target-spec-json`\n    pub supports_std: Option<bool>,\n    /// Supported values for `-Csplit-debuginfo=` flag, queried from rustc\n    support_split_debuginfo: Vec<String>,\n    /// Path to the sysroot.\n    pub sysroot: PathBuf,\n    /// Path to the \"lib\" directory in the sysroot which rustc uses for linking\n    /// target libraries.\n    pub sysroot_target_libdir: PathBuf,\n    /// Extra flags to pass to `rustc`, see [`extra_args`].\n    pub rustflags: Rc<[String]>,\n    /// Extra flags to pass to `rustdoc`, see [`extra_args`].\n    pub rustdocflags: Rc<[String]>,\n}\n\n/// Kind of each file generated by a Unit, part of `FileType`.\n#[derive(Clone, PartialEq, Eq, Debug)]\npub enum FileFlavor {\n    /// Not a special file type.\n    Normal,\n    /// Like `Normal`, but not directly executable.\n    /// For example, a `.wasm` file paired with the \"normal\" `.js` file.\n    Auxiliary,\n    /// Something you can link against (e.g., a library).\n    Linkable,\n    /// An `.rmeta` Rust metadata file.\n    Rmeta,\n    /// Piece of external debug information (e.g., `.dSYM`/`.pdb` file).\n    DebugInfo,\n    /// SBOM (Software Bill of Materials pre-cursor) file (e.g. cargo-sbon.json).\n    Sbom,\n    /// Cross-crate info JSON files generated by rustdoc.\n    DocParts,\n}\n\n/// Type of each file generated by a Unit.\n#[derive(Debug)]\npub struct FileType {\n    /// The kind of file.\n    pub flavor: FileFlavor,\n    /// The crate-type that generates this file.\n    ///\n    /// `None` for things that aren't associated with a specific crate type,\n    /// for example `rmeta` files.\n    pub crate_type: Option<CrateType>,\n    /// The suffix for the file (for example, `.rlib`).\n    /// This is an empty string for executables on Unix-like platforms.\n    suffix: String,\n    /// The prefix for the file (for example, `lib`).\n    /// This is an empty string for things like executables.\n    prefix: String,\n    /// Flag to convert hyphen to underscore when uplifting.\n    should_replace_hyphens: bool,\n}\n\nimpl FileType {\n    /// The filename for this `FileType` created by rustc.\n    pub fn output_filename(&self, target: &Target, metadata: Option<&str>) -> String {\n        match metadata {\n            Some(metadata) => format!(\n                \"{}{}-{}{}\",\n                self.prefix,\n                target.crate_name(),\n                metadata,\n                self.suffix\n            ),\n            None => format!(\"{}{}{}\", self.prefix, target.crate_name(), self.suffix),\n        }\n    }\n\n    /// The filename for this `FileType` that Cargo should use when \"uplifting\"\n    /// it to the destination directory.\n    pub fn uplift_filename(&self, target: &Target) -> String {\n        let name = match target.binary_filename() {\n            Some(name) => name,\n            None => {\n                // For binary crate type, `should_replace_hyphens` will always be false.\n                if self.should_replace_hyphens {\n                    target.crate_name()\n                } else {\n                    target.name().to_string()\n                }\n            }\n        };\n\n        format!(\"{}{}{}\", self.prefix, name, self.suffix)\n    }\n\n    /// Creates a new instance representing a `.rmeta` file.\n    pub fn new_rmeta() -> FileType {\n        // Note that even binaries use the `lib` prefix.\n        FileType {\n            flavor: FileFlavor::Rmeta,\n            crate_type: None,\n            suffix: \".rmeta\".to_string(),\n            prefix: \"lib\".to_string(),\n            should_replace_hyphens: true,\n        }\n    }\n\n    pub fn output_prefix_suffix(&self, target: &Target) -> (String, String) {\n        (\n            format!(\"{}{}-\", self.prefix, target.crate_name()),\n            self.suffix.clone(),\n        )\n    }\n}\n\nimpl TargetInfo {\n    /// Learns the information of target platform from `rustc` invocation(s).\n    ///\n    /// Generally, the first time calling this function is expensive, as it may\n    /// query `rustc` several times. To reduce the cost, output of each `rustc`\n    /// invocation is cached by [`Rustc::cached_output`].\n    ///\n    /// Search `Tricky` to learn why querying `rustc` several times is needed.\n    #[tracing::instrument(skip_all)]\n    pub fn new(\n        gctx: &GlobalContext,\n        requested_kinds: &[CompileKind],\n        rustc: &Rustc,\n        kind: CompileKind,\n    ) -> CargoResult<TargetInfo> {\n        let mut rustflags =\n            extra_args(gctx, requested_kinds, &rustc.host, None, kind, Flags::Rust)?;\n        let mut turn = 0;\n        loop {\n            let extra_fingerprint = kind.fingerprint_hash();\n\n            // Query rustc for several kinds of info from each line of output:\n            // 0) file-names (to determine output file prefix/suffix for given crate type)\n            // 1) sysroot\n            // 2) split-debuginfo\n            // 3) cfg\n            //\n            // Search `--print` to see what we query so far.\n            let mut process = rustc.workspace_process();\n            apply_env_config(gctx, &mut process)?;\n            process\n                .arg(\"-\")\n                .arg(\"--crate-name\")\n                .arg(\"___\")\n                .arg(\"--print=file-names\")\n                .args(&rustflags)\n                .env_remove(\"RUSTC_LOG\");\n\n            // Removes `FD_CLOEXEC` set by `jobserver::Client` to pass jobserver\n            // as environment variables specify.\n            if let Some(client) = gctx.jobserver_from_env() {\n                process.inherit_jobserver(client);\n            }\n\n            kind.add_target_arg(&mut process);\n\n            let crate_type_process = process.clone();\n            const KNOWN_CRATE_TYPES: &[CrateType] = &[\n                CrateType::Bin,\n                CrateType::Rlib,\n                CrateType::Dylib,\n                CrateType::Cdylib,\n                CrateType::Staticlib,\n                CrateType::ProcMacro,\n            ];\n            for crate_type in KNOWN_CRATE_TYPES.iter() {\n                process.arg(\"--crate-type\").arg(crate_type.as_str());\n            }\n\n            process.arg(\"--print=sysroot\");\n            process.arg(\"--print=split-debuginfo\");\n            process.arg(\"--print=crate-name\"); // `___` as a delimiter.\n            process.arg(\"--print=cfg\");\n\n            // parse_crate_type() relies on \"unsupported/unknown crate type\" error message,\n            // so make warnings always emitted as warnings.\n            process.arg(\"-Wwarnings\");\n\n            let (output, error) = rustc\n                .cached_output(&process, extra_fingerprint)\n                .with_context(\n                    || \"failed to run `rustc` to learn about target-specific information\",\n                )?;\n\n            let mut lines = output.lines();\n            let mut map = HashMap::new();\n            for crate_type in KNOWN_CRATE_TYPES {\n                let out = parse_crate_type(crate_type, &process, &output, &error, &mut lines)?;\n                map.insert(crate_type.clone(), out);\n            }\n\n            let Some(line) = lines.next() else {\n                return error_missing_print_output(\"sysroot\", &process, &output, &error);\n            };\n            let sysroot = PathBuf::from(line);\n            let sysroot_target_libdir = {\n                let mut libdir = sysroot.clone();\n                libdir.push(\"lib\");\n                libdir.push(\"rustlib\");\n                libdir.push(match &kind {\n                    CompileKind::Host => rustc.host.as_str(),\n                    CompileKind::Target(target) => target.short_name(),\n                });\n                libdir.push(\"lib\");\n                libdir\n            };\n\n            let support_split_debuginfo = {\n                // HACK: abuse `--print=crate-name` to use `___` as a delimiter.\n                let mut res = Vec::new();\n                loop {\n                    match lines.next() {\n                        Some(line) if line == \"___\" => break,\n                        Some(line) => res.push(line.into()),\n                        None => {\n                            return error_missing_print_output(\n                                \"split-debuginfo\",\n                                &process,\n                                &output,\n                                &error,\n                            );\n                        }\n                    }\n                }\n                res\n            };\n\n            let cfg = lines\n                .map(|line| Ok(Cfg::from_str(line)?))\n                .filter(TargetInfo::not_user_specific_cfg)\n                .collect::<CargoResult<Vec<_>>>()\n                .with_context(|| {\n                    format!(\n                        \"failed to parse the cfg from `rustc --print=cfg`, got:\\n{}\",\n                        output\n                    )\n                })?;\n\n            // recalculate `rustflags` from above now that we have `cfg`\n            // information\n            let new_flags = extra_args(\n                gctx,\n                requested_kinds,\n                &rustc.host,\n                Some(&cfg),\n                kind,\n                Flags::Rust,\n            )?;\n\n            // Tricky: `RUSTFLAGS` defines the set of active `cfg` flags, active\n            // `cfg` flags define which `.cargo/config` sections apply, and they\n            // in turn can affect `RUSTFLAGS`! This is a bona fide mutual\n            // dependency, and it can even diverge (see `cfg_paradox` test).\n            //\n            // So what we do here is running at most *two* iterations of\n            // fixed-point iteration, which should be enough to cover\n            // practically useful cases, and warn if that's not enough for\n            // convergence.\n            let reached_fixed_point = new_flags == rustflags;\n            if !reached_fixed_point && turn == 0 {\n                turn += 1;\n                rustflags = new_flags;\n                continue;\n            }\n            if !reached_fixed_point {\n                gctx.shell().warn(\"non-trivial mutual dependency between target-specific configuration and RUSTFLAGS\")?;\n            }\n\n            let mut supports_std: Option<bool> = None;\n\n            // The '--print=target-spec-json' is an unstable option of rustc, therefore only\n            // try to fetch this information if rustc allows nightly features. Additionally,\n            // to avoid making two rustc queries when not required, only try to fetch the\n            // target-spec when the '-Zbuild-std' option is passed.\n            if gctx.cli_unstable().build_std.is_some() {\n                let mut target_spec_process = rustc.workspace_process();\n                apply_env_config(gctx, &mut target_spec_process)?;\n                target_spec_process\n                    .arg(\"--print=target-spec-json\")\n                    .arg(\"-Zunstable-options\")\n                    .args(&rustflags)\n                    .env_remove(\"RUSTC_LOG\");\n\n                kind.add_target_arg(&mut target_spec_process);\n\n                #[derive(Deserialize)]\n                struct Metadata {\n                    pub std: Option<bool>,\n                }\n\n                #[derive(Deserialize)]\n                struct TargetSpec {\n                    pub metadata: Metadata,\n                }\n\n                if let Ok(output) = target_spec_process.output() {\n                    if let Ok(spec) = serde_json::from_slice::<TargetSpec>(&output.stdout) {\n                        supports_std = spec.metadata.std;\n                    }\n                }\n            }\n\n            return Ok(TargetInfo {\n                crate_type_process,\n                crate_types: RefCell::new(map),\n                sysroot,\n                sysroot_target_libdir,\n                rustflags: rustflags.into(),\n                rustdocflags: extra_args(\n                    gctx,\n                    requested_kinds,\n                    &rustc.host,\n                    Some(&cfg),\n                    kind,\n                    Flags::Rustdoc,\n                )?\n                .into(),\n                cfg,\n                supports_std,\n                support_split_debuginfo,\n            });\n        }\n    }\n\n    fn not_user_specific_cfg(cfg: &CargoResult<Cfg>) -> bool {\n        if let Ok(Cfg::Name(cfg_name)) = cfg {\n            // This should also include \"debug_assertions\", but it causes\n            // regressions. Maybe some day in the distant future it can be\n            // added (and possibly change the warning to an error).\n            if cfg_name == \"proc_macro\" {\n                return false;\n            }\n        }\n        true\n    }\n\n    /// All the target [`Cfg`] settings.\n    pub fn cfg(&self) -> &[Cfg] {\n        &self.cfg\n    }\n\n    /// Returns the list of file types generated by the given crate type.\n    ///\n    /// Returns `None` if the target does not support the given crate type.\n    fn file_types(\n        &self,\n        crate_type: &CrateType,\n        flavor: FileFlavor,\n        target_triple: &str,\n    ) -> CargoResult<Option<Vec<FileType>>> {\n        let crate_type = if *crate_type == CrateType::Lib {\n            CrateType::Rlib\n        } else {\n            crate_type.clone()\n        };\n\n        let mut crate_types = self.crate_types.borrow_mut();\n        let entry = crate_types.entry(crate_type.clone());\n        let crate_type_info = match entry {\n            Entry::Occupied(o) => &*o.into_mut(),\n            Entry::Vacant(v) => {\n                let value = self.discover_crate_type(v.key())?;\n                &*v.insert(value)\n            }\n        };\n        let Some((prefix, suffix)) = crate_type_info else {\n            return Ok(None);\n        };\n        let mut ret = vec![FileType {\n            suffix: suffix.clone(),\n            prefix: prefix.clone(),\n            flavor,\n            crate_type: Some(crate_type.clone()),\n            should_replace_hyphens: crate_type != CrateType::Bin,\n        }];\n\n        // Window shared library import/export files.\n        if crate_type.is_dynamic() {\n            // Note: Custom JSON specs can alter the suffix. For now, we'll\n            // just ignore non-DLL suffixes.\n            if target_triple.ends_with(\"-windows-msvc\") && suffix == \".dll\" {\n                // See https://docs.microsoft.com/en-us/cpp/build/reference/working-with-import-libraries-and-export-files\n                // for more information about DLL import/export files.\n                ret.push(FileType {\n                    suffix: \".dll.lib\".to_string(),\n                    prefix: prefix.clone(),\n                    flavor: FileFlavor::Auxiliary,\n                    crate_type: Some(crate_type.clone()),\n                    should_replace_hyphens: true,\n                });\n                // NOTE: lld does not produce these\n                ret.push(FileType {\n                    suffix: \".dll.exp\".to_string(),\n                    prefix: prefix.clone(),\n                    flavor: FileFlavor::Auxiliary,\n                    crate_type: Some(crate_type.clone()),\n                    should_replace_hyphens: true,\n                });\n            } else if suffix == \".dll\"\n                && (target_triple.ends_with(\"windows-gnu\")\n                    || target_triple.ends_with(\"windows-gnullvm\")\n                    || target_triple.ends_with(\"cygwin\"))\n            {\n                // See https://cygwin.com/cygwin-ug-net/dll.html for more\n                // information about GNU import libraries.\n                // LD can link DLL directly, but LLD requires the import library.\n                ret.push(FileType {\n                    suffix: \".dll.a\".to_string(),\n                    prefix: \"lib\".to_string(),\n                    flavor: FileFlavor::Auxiliary,\n                    crate_type: Some(crate_type.clone()),\n                    should_replace_hyphens: true,\n                })\n            }\n        }\n\n        if target_triple.starts_with(\"wasm32-\") && crate_type == CrateType::Bin && suffix == \".js\" {\n            // emscripten binaries generate a .js file, which loads a .wasm\n            // file.\n            ret.push(FileType {\n                suffix: \".wasm\".to_string(),\n                prefix: prefix.clone(),\n                flavor: FileFlavor::Auxiliary,\n                crate_type: Some(crate_type.clone()),\n                // Name `foo-bar` will generate a `foo_bar.js` and\n                // `foo_bar.wasm`. Cargo will translate the underscore and\n                // copy `foo_bar.js` to `foo-bar.js`. However, the wasm\n                // filename is embedded in the .js file with an underscore, so\n                // it should not contain hyphens.\n                should_replace_hyphens: true,\n            });\n            // And a map file for debugging. This is only emitted with debug=2\n            // (-g4 for emcc).\n            ret.push(FileType {\n                suffix: \".wasm.map\".to_string(),\n                prefix: prefix.clone(),\n                flavor: FileFlavor::DebugInfo,\n                crate_type: Some(crate_type.clone()),\n                should_replace_hyphens: true,\n            });\n        }\n\n        // Handle separate debug files.\n        let is_apple = target_triple.contains(\"-apple-\");\n        if matches!(\n            crate_type,\n            CrateType::Bin | CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro\n        ) {\n            if is_apple {\n                let suffix = if crate_type == CrateType::Bin {\n                    \".dSYM\".to_string()\n                } else {\n                    \".dylib.dSYM\".to_string()\n                };\n                ret.push(FileType {\n                    suffix,\n                    prefix: prefix.clone(),\n                    flavor: FileFlavor::DebugInfo,\n                    crate_type: Some(crate_type),\n                    // macOS tools like lldb use all sorts of magic to locate\n                    // dSYM files. See https://lldb.llvm.org/use/symbols.html\n                    // for some details. It seems like a `.dSYM` located next\n                    // to the executable with the same name is one method. The\n                    // dSYM should have the same hyphens as the executable for\n                    // the names to match.\n                    should_replace_hyphens: false,\n                })\n            } else if target_triple.ends_with(\"-msvc\") || target_triple.ends_with(\"-uefi\") {\n                ret.push(FileType {\n                    suffix: \".pdb\".to_string(),\n                    prefix: prefix.clone(),\n                    flavor: FileFlavor::DebugInfo,\n                    crate_type: Some(crate_type),\n                    // The absolute path to the pdb file is embedded in the\n                    // executable. If the exe/pdb pair is moved to another\n                    // machine, then debuggers will look in the same directory\n                    // of the exe with the original pdb filename. Since the\n                    // original name contains underscores, they need to be\n                    // preserved.\n                    should_replace_hyphens: true,\n                })\n            } else {\n                // Because DWARF Package (dwp) files are produced after the\n                // fact by another tool, there is nothing in the binary that\n                // provides a means to locate them. By convention, debuggers\n                // take the binary filename and append \".dwp\" (including to\n                // binaries that already have an extension such as shared libs)\n                // to find the dwp.\n                ret.push(FileType {\n                    // It is important to preserve the existing suffix for\n                    // e.g. shared libraries, where the dwp for libfoo.so is\n                    // expected to be at libfoo.so.dwp.\n                    suffix: format!(\"{suffix}.dwp\"),\n                    prefix: prefix.clone(),\n                    flavor: FileFlavor::DebugInfo,\n                    crate_type: Some(crate_type.clone()),\n                    // Likewise, the dwp needs to match the primary artifact's\n                    // hyphenation exactly.\n                    should_replace_hyphens: crate_type != CrateType::Bin,\n                })\n            }\n        }\n\n        Ok(Some(ret))\n    }\n\n    fn discover_crate_type(&self, crate_type: &CrateType) -> CargoResult<Option<(String, String)>> {\n        let mut process = self.crate_type_process.clone();\n\n        process.arg(\"--crate-type\").arg(crate_type.as_str());\n\n        let output = process.exec_with_output().with_context(|| {\n            format!(\n                \"failed to run `rustc` to learn about crate-type {} information\",\n                crate_type\n            )\n        })?;\n\n        let error = str::from_utf8(&output.stderr).unwrap();\n        let output = str::from_utf8(&output.stdout).unwrap();\n        parse_crate_type(crate_type, &process, output, error, &mut output.lines())\n    }\n\n    /// Returns all the file types generated by rustc for the given `mode`/`target_kind`.\n    ///\n    /// The first value is a Vec of file types generated, the second value is\n    /// a list of `CrateTypes` that are not supported by the given target.\n    pub fn rustc_outputs(\n        &self,\n        mode: CompileMode,\n        target_kind: &TargetKind,\n        target_triple: &str,\n        gctx: &GlobalContext,\n    ) -> CargoResult<(Vec<FileType>, Vec<CrateType>)> {\n        match mode {\n            CompileMode::Build => self.calc_rustc_outputs(target_kind, target_triple, gctx),\n            CompileMode::Test => {\n                match self.file_types(&CrateType::Bin, FileFlavor::Normal, target_triple)? {\n                    Some(fts) => Ok((fts, Vec::new())),\n                    None => Ok((Vec::new(), vec![CrateType::Bin])),\n                }\n            }\n            CompileMode::Check { .. } => Ok((vec![FileType::new_rmeta()], Vec::new())),\n            CompileMode::Doc { .. }\n            | CompileMode::Doctest\n            | CompileMode::Docscrape\n            | CompileMode::RunCustomBuild => {\n                panic!(\"asked for rustc output for non-rustc mode\")\n            }\n        }\n    }\n\n    fn calc_rustc_outputs(\n        &self,\n        target_kind: &TargetKind,\n        target_triple: &str,\n        gctx: &GlobalContext,\n    ) -> CargoResult<(Vec<FileType>, Vec<CrateType>)> {\n        let mut unsupported = Vec::new();\n        let mut result = Vec::new();\n        let crate_types = target_kind.rustc_crate_types();\n        for crate_type in &crate_types {\n            let flavor = if crate_type.is_linkable() {\n                FileFlavor::Linkable\n            } else {\n                FileFlavor::Normal\n            };\n            let file_types = self.file_types(crate_type, flavor, target_triple)?;\n            match file_types {\n                Some(types) => {\n                    result.extend(types);\n                }\n                None => {\n                    unsupported.push(crate_type.clone());\n                }\n            }\n        }\n        if !result.is_empty() {\n            if gctx.cli_unstable().no_embed_metadata\n                && crate_types\n                    .iter()\n                    .any(|ct| ct.benefits_from_no_embed_metadata())\n            {\n                // Add .rmeta when we apply -Zembed-metadata=no to the unit.\n                result.push(FileType::new_rmeta());\n            } else if !crate_types.iter().any(|ct| ct.requires_upstream_objects()) {\n                // Only add rmeta if pipelining\n                result.push(FileType::new_rmeta());\n            }\n        }\n        Ok((result, unsupported))\n    }\n\n    /// Checks if the debuginfo-split value is supported by this target\n    pub fn supports_debuginfo_split(&self, split: InternedString) -> bool {\n        self.support_split_debuginfo\n            .iter()\n            .any(|sup| sup.as_str() == split.as_str())\n    }\n\n    /// Checks if a target maybe support std.\n    ///\n    /// If no explicitly stated in target spec json, we treat it as \"maybe support\".\n    ///\n    /// This is only useful for `-Zbuild-std` to determine the default set of\n    /// crates it is going to build.\n    pub fn maybe_support_std(&self) -> bool {\n        matches!(self.supports_std, Some(true) | None)\n    }\n}\n\n/// Takes rustc output (using specialized command line args), and calculates the file prefix and\n/// suffix for the given crate type, or returns `None` if the type is not supported. (e.g., for a\n/// Rust library like `libcargo.rlib`, we have prefix \"lib\" and suffix \"rlib\").\n///\n/// The caller needs to ensure that the lines object is at the correct line for the given crate\n/// type: this is not checked.\n///\n/// This function can not handle more than one file per type (with wasm32-unknown-emscripten, there\n/// are two files for bin (`.wasm` and `.js`)).\nfn parse_crate_type(\n    crate_type: &CrateType,\n    cmd: &ProcessBuilder,\n    output: &str,\n    error: &str,\n    lines: &mut str::Lines<'_>,\n) -> CargoResult<Option<(String, String)>> {\n    let not_supported = error.lines().any(|line| {\n        (line.contains(\"unsupported crate type\") || line.contains(\"unknown crate type\"))\n            && line.contains(&format!(\"crate type `{}`\", crate_type))\n    });\n    if not_supported {\n        return Ok(None);\n    }\n    let Some(line) = lines.next() else {\n        anyhow::bail!(\n            \"malformed output when learning about crate-type {} information\\n{}\",\n            crate_type,\n            output_err_info(cmd, output, error)\n        )\n    };\n    let mut parts = line.trim().split(\"___\");\n    let prefix = parts.next().unwrap();\n    let Some(suffix) = parts.next() else {\n        return error_missing_print_output(\"file-names\", cmd, output, error);\n    };\n\n    Ok(Some((prefix.to_string(), suffix.to_string())))\n}\n\n/// Helper for creating an error message for missing output from a certain `--print` request.\nfn error_missing_print_output<T>(\n    request: &str,\n    cmd: &ProcessBuilder,\n    stdout: &str,\n    stderr: &str,\n) -> CargoResult<T> {\n    let err_info = output_err_info(cmd, stdout, stderr);\n    anyhow::bail!(\n        \"output of --print={request} missing when learning about \\\n     target-specific information from rustc\\n{err_info}\",\n    )\n}\n\n/// Helper for creating an error message when parsing rustc output fails.\nfn output_err_info(cmd: &ProcessBuilder, stdout: &str, stderr: &str) -> String {\n    let mut result = format!(\"command was: {}\\n\", cmd);\n    if !stdout.is_empty() {\n        result.push_str(\"\\n--- stdout\\n\");\n        result.push_str(stdout);\n    }\n    if !stderr.is_empty() {\n        result.push_str(\"\\n--- stderr\\n\");\n        result.push_str(stderr);\n    }\n    if stdout.is_empty() && stderr.is_empty() {\n        result.push_str(\"(no output received)\");\n    }\n    result\n}\n\n/// Compiler flags for either rustc or rustdoc.\n#[derive(Debug, Copy, Clone)]\nenum Flags {\n    Rust,\n    Rustdoc,\n}\n\nimpl Flags {\n    fn as_key(self) -> &'static str {\n        match self {\n            Flags::Rust => \"rustflags\",\n            Flags::Rustdoc => \"rustdocflags\",\n        }\n    }\n\n    fn as_env(self) -> &'static str {\n        match self {\n            Flags::Rust => \"RUSTFLAGS\",\n            Flags::Rustdoc => \"RUSTDOCFLAGS\",\n        }\n    }\n}\n\n/// Acquire extra flags to pass to the compiler from various locations.\n///\n/// The locations are:\n///\n///  - the `CARGO_ENCODED_RUSTFLAGS` environment variable\n///  - the `RUSTFLAGS` environment variable\n///\n/// then if none of those were found\n///\n///  - `target.*.rustflags` from the config (.cargo/config)\n///  - `target.cfg(..).rustflags` from the config\n///  - `host.*.rustflags` from the config if compiling a host artifact or without `--target`\n///     (requires `-Zhost-config`)\n///\n/// then if none of those were found\n///\n///  - `build.rustflags` from the config\n///\n/// The behavior differs slightly when cross-compiling (or, specifically, when `--target` is\n/// provided) for artifacts that are always built for the host (plugins, build scripts, ...).\n/// For those artifacts, _only_ `host.*.rustflags` is respected, and no other configuration\n/// sources, _regardless of the value of `target-applies-to-host`_. This is counterintuitive, but\n/// necessary to retain backwards compatibility with older versions of Cargo.\n///\n/// Rules above also applies to rustdoc. Just the key would be `rustdocflags`/`RUSTDOCFLAGS`.\nfn extra_args(\n    gctx: &GlobalContext,\n    requested_kinds: &[CompileKind],\n    host_triple: &str,\n    target_cfg: Option<&[Cfg]>,\n    kind: CompileKind,\n    flags: Flags,\n) -> CargoResult<Vec<String>> {\n    let target_applies_to_host = gctx.target_applies_to_host()?;\n\n    // Host artifacts should not generally pick up rustflags from anywhere except [host].\n    //\n    // The one exception to this is if `target-applies-to-host = true`, which opts into a\n    // particular (inconsistent) past Cargo behavior where host artifacts _do_ pick up rustflags\n    // set elsewhere when `--target` isn't passed.\n    if kind.is_host() {\n        if target_applies_to_host && requested_kinds == [CompileKind::Host] {\n            // This is the past Cargo behavior where we fall back to the same logic as for other\n            // artifacts without --target.\n        } else {\n            // In all other cases, host artifacts just get flags from [host], regardless of\n            // --target. Or, phrased differently, no `--target` behaves the same as `--target\n            // <host>`, and host artifacts are always \"special\" (they don't pick up `RUSTFLAGS` for\n            // example).\n            return Ok(rustflags_from_host(gctx, flags, host_triple)?.unwrap_or_else(Vec::new));\n        }\n    }\n\n    // All other artifacts pick up the RUSTFLAGS, [target.*], and [build], in that order.\n    // NOTE: It is impossible to have a [host] section and reach this logic with kind.is_host(),\n    // since [host] implies `target-applies-to-host = false`, which always early-returns above.\n\n    if let Some(rustflags) = rustflags_from_env(gctx, flags) {\n        Ok(rustflags)\n    } else if let Some(rustflags) =\n        rustflags_from_target(gctx, host_triple, target_cfg, kind, flags)?\n    {\n        Ok(rustflags)\n    } else if let Some(rustflags) = rustflags_from_build(gctx, flags)? {\n        Ok(rustflags)\n    } else {\n        Ok(Vec::new())\n    }\n}\n\n/// Gets compiler flags from environment variables.\n/// See [`extra_args`] for more.\nfn rustflags_from_env(gctx: &GlobalContext, flags: Flags) -> Option<Vec<String>> {\n    // First try CARGO_ENCODED_RUSTFLAGS from the environment.\n    // Prefer this over RUSTFLAGS since it's less prone to encoding errors.\n    if let Ok(a) = gctx.get_env(format!(\"CARGO_ENCODED_{}\", flags.as_env())) {\n        if a.is_empty() {\n            return Some(Vec::new());\n        }\n        return Some(a.split('\\x1f').map(str::to_string).collect());\n    }\n\n    // Then try RUSTFLAGS from the environment\n    if let Ok(a) = gctx.get_env(flags.as_env()) {\n        let args = a\n            .split(' ')\n            .map(str::trim)\n            .filter(|s| !s.is_empty())\n            .map(str::to_string);\n        return Some(args.collect());\n    }\n\n    // No rustflags to be collected from the environment\n    None\n}\n\n/// Gets compiler flags from `[target]` section in the config.\n/// See [`extra_args`] for more.\nfn rustflags_from_target(\n    gctx: &GlobalContext,\n    host_triple: &str,\n    target_cfg: Option<&[Cfg]>,\n    kind: CompileKind,\n    flag: Flags,\n) -> CargoResult<Option<Vec<String>>> {\n    let mut rustflags = Vec::new();\n\n    // Then the target.*.rustflags value...\n    let target = match &kind {\n        CompileKind::Host => host_triple,\n        CompileKind::Target(target) => target.short_name(),\n    };\n    let key = format!(\"target.{}.{}\", target, flag.as_key());\n    if let Some(args) = gctx.get::<Option<StringList>>(&key)? {\n        rustflags.extend(args.as_slice().iter().cloned());\n    }\n    // ...including target.'cfg(...)'.rustflags\n    if let Some(target_cfg) = target_cfg {\n        gctx.target_cfgs()?\n            .iter()\n            .filter_map(|(key, cfg)| {\n                match flag {\n                    Flags::Rust => cfg\n                        .rustflags\n                        .as_ref()\n                        .map(|rustflags| (key, &rustflags.val)),\n                    // `target.cfg(…).rustdocflags` is currently not supported.\n                    Flags::Rustdoc => None,\n                }\n            })\n            .filter(|(key, _rustflags)| CfgExpr::matches_key(key, target_cfg))\n            .for_each(|(_key, cfg_rustflags)| {\n                rustflags.extend(cfg_rustflags.as_slice().iter().cloned());\n            });\n    }\n\n    if rustflags.is_empty() {\n        Ok(None)\n    } else {\n        Ok(Some(rustflags))\n    }\n}\n\n/// Gets compiler flags from `[host]` section in the config.\n/// See [`extra_args`] for more.\nfn rustflags_from_host(\n    gctx: &GlobalContext,\n    flag: Flags,\n    host_triple: &str,\n) -> CargoResult<Option<Vec<String>>> {\n    let target_cfg = gctx.host_cfg_triple(host_triple)?;\n    let list = match flag {\n        Flags::Rust => &target_cfg.rustflags,\n        Flags::Rustdoc => {\n            // host.rustdocflags is not a thing, since it does not make sense\n            return Ok(None);\n        }\n    };\n    Ok(list.as_ref().map(|l| l.val.as_slice().to_vec()))\n}\n\n/// Gets compiler flags from `[build]` section in the config.\n/// See [`extra_args`] for more.\nfn rustflags_from_build(gctx: &GlobalContext, flag: Flags) -> CargoResult<Option<Vec<String>>> {\n    // Then the `build.rustflags` value.\n    let build = gctx.build_config()?;\n    let list = match flag {\n        Flags::Rust => &build.rustflags,\n        Flags::Rustdoc => &build.rustdocflags,\n    };\n    Ok(list.as_ref().map(|l| l.as_slice().to_vec()))\n}\n\n/// Collection of information about `rustc` and the host and target.\npub struct RustcTargetData<'gctx> {\n    /// Information about `rustc` itself.\n    pub rustc: Rustc,\n\n    /// Config\n    pub gctx: &'gctx GlobalContext,\n    requested_kinds: Vec<CompileKind>,\n\n    /// Build information for the \"host\", which is information about when\n    /// `rustc` is invoked without a `--target` flag. This is used for\n    /// selecting a linker, and applying link overrides.\n    ///\n    /// The configuration read into this depends on whether or not\n    /// `target-applies-to-host=true`.\n    host_config: TargetConfig,\n    /// Information about the host platform.\n    host_info: TargetInfo,\n\n    /// Build information for targets that we're building for.\n    target_config: HashMap<CompileTarget, TargetConfig>,\n    /// Information about the target platform that we're building for.\n    target_info: HashMap<CompileTarget, TargetInfo>,\n}\n\nimpl<'gctx> RustcTargetData<'gctx> {\n    #[tracing::instrument(skip_all)]\n    pub fn new(\n        ws: &Workspace<'gctx>,\n        requested_kinds: &[CompileKind],\n    ) -> CargoResult<RustcTargetData<'gctx>> {\n        let gctx = ws.gctx();\n        let rustc = gctx.load_global_rustc(Some(ws))?;\n        let mut target_config = HashMap::new();\n        let mut target_info = HashMap::new();\n        let target_applies_to_host = gctx.target_applies_to_host()?;\n        let host_target = CompileTarget::new(&rustc.host, gctx.cli_unstable().json_target_spec)?;\n        let host_info = TargetInfo::new(gctx, requested_kinds, &rustc, CompileKind::Host)?;\n\n        // This config is used for link overrides and choosing a linker.\n        let host_config = if target_applies_to_host {\n            gctx.target_cfg_triple(&rustc.host)?\n        } else {\n            gctx.host_cfg_triple(&rustc.host)?\n        };\n\n        // This is a hack. The unit_dependency graph builder \"pretends\" that\n        // `CompileKind::Host` is `CompileKind::Target(host)` if the\n        // `--target` flag is not specified. Since the unit_dependency code\n        // needs access to the target config data, create a copy so that it\n        // can be found. See `rebuild_unit_graph_shared` for why this is done.\n        if requested_kinds.iter().any(CompileKind::is_host) {\n            target_config.insert(host_target, gctx.target_cfg_triple(&rustc.host)?);\n\n            // If target_applies_to_host is true, the host_info is the target info,\n            // otherwise we need to build target info for the target.\n            if target_applies_to_host {\n                target_info.insert(host_target, host_info.clone());\n            } else {\n                let host_target_info = TargetInfo::new(\n                    gctx,\n                    requested_kinds,\n                    &rustc,\n                    CompileKind::Target(host_target),\n                )?;\n                target_info.insert(host_target, host_target_info);\n            }\n        };\n\n        let mut res = RustcTargetData {\n            rustc,\n            gctx,\n            requested_kinds: requested_kinds.into(),\n            host_config,\n            host_info,\n            target_config,\n            target_info,\n        };\n\n        // Get all kinds we currently know about.\n        //\n        // For now, targets can only ever come from the root workspace\n        // units and artifact dependencies, so this\n        // correctly represents all the kinds that can happen. When we have\n        // other ways for targets to appear at places that are not the root units,\n        // we may have to revisit this.\n        fn artifact_targets(package: &Package) -> impl Iterator<Item = CompileKind> + '_ {\n            package\n                .manifest()\n                .dependencies()\n                .iter()\n                .filter_map(|d| d.artifact()?.target()?.to_compile_kind())\n        }\n        let all_kinds = requested_kinds\n            .iter()\n            .copied()\n            .chain(ws.members().flat_map(|p| {\n                p.manifest()\n                    .default_kind()\n                    .into_iter()\n                    .chain(p.manifest().forced_kind())\n                    .chain(artifact_targets(p))\n            }));\n        for kind in all_kinds {\n            res.merge_compile_kind(kind)?;\n        }\n\n        Ok(res)\n    }\n\n    /// Insert `kind` into our `target_info` and `target_config` members if it isn't present yet.\n    pub fn merge_compile_kind(&mut self, kind: CompileKind) -> CargoResult<()> {\n        if let CompileKind::Target(target) = kind {\n            if !self.target_config.contains_key(&target) {\n                self.target_config\n                    .insert(target, self.gctx.target_cfg_triple(target.short_name())?);\n            }\n            if !self.target_info.contains_key(&target) {\n                self.target_info.insert(\n                    target,\n                    TargetInfo::new(self.gctx, &self.requested_kinds, &self.rustc, kind)?,\n                );\n            }\n        }\n        Ok(())\n    }\n\n    /// Returns a \"short\" name for the given kind, suitable for keying off\n    /// configuration in Cargo or presenting to users.\n    pub fn short_name<'a>(&'a self, kind: &'a CompileKind) -> &'a str {\n        match kind {\n            CompileKind::Host => &self.rustc.host,\n            CompileKind::Target(target) => target.short_name(),\n        }\n    }\n\n    /// Whether a dependency should be compiled for the host or target platform,\n    /// specified by `CompileKind`.\n    pub fn dep_platform_activated(&self, dep: &Dependency, kind: CompileKind) -> bool {\n        // If this dependency is only available for certain platforms,\n        // make sure we're only enabling it for that platform.\n        let Some(platform) = dep.platform() else {\n            return true;\n        };\n        let name = self.short_name(&kind);\n        platform.matches(name, self.cfg(kind))\n    }\n\n    /// Gets the list of `cfg`s printed out from the compiler for the specified kind.\n    pub fn cfg(&self, kind: CompileKind) -> &[Cfg] {\n        self.info(kind).cfg()\n    }\n\n    /// Information about the given target platform, learned by querying rustc.\n    ///\n    /// # Panics\n    ///\n    /// Panics, if the target platform described by `kind` can't be found.\n    /// See [`get_info`](Self::get_info) for a non-panicking alternative.\n    pub fn info(&self, kind: CompileKind) -> &TargetInfo {\n        self.get_info(kind).unwrap()\n    }\n\n    /// Information about the given target platform, learned by querying rustc.\n    ///\n    /// Returns `None` if the target platform described by `kind` can't be found.\n    pub fn get_info(&self, kind: CompileKind) -> Option<&TargetInfo> {\n        match kind {\n            CompileKind::Host => Some(&self.host_info),\n            CompileKind::Target(s) => self.target_info.get(&s),\n        }\n    }\n\n    /// Gets the target configuration for a particular host or target.\n    pub fn target_config(&self, kind: CompileKind) -> &TargetConfig {\n        match kind {\n            CompileKind::Host => &self.host_config,\n            CompileKind::Target(s) => &self.target_config[&s],\n        }\n    }\n\n    pub fn get_unsupported_std_targets(&self) -> Vec<&str> {\n        let mut unsupported = Vec::new();\n        for (target, target_info) in &self.target_info {\n            if target_info.supports_std == Some(false) {\n                unsupported.push(target.short_name());\n            }\n        }\n        unsupported\n    }\n\n    pub fn requested_kinds(&self) -> &[CompileKind] {\n        &self.requested_kinds\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/build_runner/compilation_files.rs",
    "content": "//! See [`CompilationFiles`].\n\nuse std::cell::OnceCell;\nuse std::collections::HashMap;\nuse std::fmt;\nuse std::hash::{Hash, Hasher};\nuse std::path::{Path, PathBuf};\nuse std::sync::Arc;\n\nuse tracing::debug;\n\nuse super::{BuildContext, BuildRunner, CompileKind, FileFlavor, Layout};\nuse crate::core::compiler::{CompileMode, CompileTarget, CrateType, FileType, Unit};\nuse crate::core::{Target, TargetKind, Workspace};\nuse crate::util::{self, CargoResult, OnceExt, StableHasher};\n\n/// This is a generic version number that can be changed to make\n/// backwards-incompatible changes to any file structures in the output\n/// directory. For example, the fingerprint files or the build-script\n/// output files.\n///\n/// Normally cargo updates ship with rustc updates which will\n/// cause a new hash due to the rustc version changing, but this allows\n/// cargo to be extra careful to deal with different versions of cargo that\n/// use the same rustc version.\nconst METADATA_VERSION: u8 = 2;\n\n/// Uniquely identify a [`Unit`] under specific circumstances, see [`Metadata`] for more.\n#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]\npub struct UnitHash(u64);\n\nimpl fmt::Display for UnitHash {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{:016x}\", self.0)\n    }\n}\n\nimpl fmt::Debug for UnitHash {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"UnitHash({:016x})\", self.0)\n    }\n}\n\n/// [`Metadata`] tracks several [`UnitHash`]s, including\n/// [`Metadata::unit_id`], [`Metadata::c_metadata`], and [`Metadata::c_extra_filename`].\n///\n/// We use a hash because it is an easy way to guarantee\n/// that all the inputs can be converted to a valid path.\n///\n/// [`Metadata::unit_id`] is used to uniquely identify a unit in the build graph.\n/// This serves as a similar role as [`Metadata::c_extra_filename`] in that it uniquely identifies output\n/// on the filesystem except that its always present.\n///\n/// [`Metadata::c_extra_filename`] is needed for cases like:\n/// - A project may depend on crate `A` and crate `B`, so the package name must be in the file name.\n/// - Similarly a project may depend on two versions of `A`, so the version must be in the file name.\n///\n/// This also acts as the main layer of caching provided by Cargo\n/// so this must include all things that need to be distinguished in different parts of\n/// the same build. This is absolutely required or we override things before\n/// we get chance to use them.\n///\n/// For example, we want to cache `cargo build` and `cargo doc` separately, so that running one\n/// does not invalidate the artifacts for the other. We do this by including [`CompileMode`] in the\n/// hash, thus the artifacts go in different folders and do not override each other.\n/// If we don't add something that we should have, for this reason, we get the\n/// correct output but rebuild more than is needed.\n///\n/// Some things that need to be tracked to ensure the correct output should definitely *not*\n/// go in the `Metadata`. For example, the modification time of a file, should be tracked to make a\n/// rebuild when the file changes. However, it would be wasteful to include in the `Metadata`. The\n/// old artifacts are never going to be needed again. We can save space by just overwriting them.\n/// If we add something that we should not have, for this reason, we get the correct output but take\n/// more space than needed. This makes not including something in `Metadata`\n/// a form of cache invalidation.\n///\n/// Note that the `Fingerprint` is in charge of tracking everything needed to determine if a\n/// rebuild is needed.\n///\n/// [`Metadata::c_metadata`] is used for symbol mangling, because if you have two versions of\n/// the same crate linked together, their symbols need to be differentiated.\n///\n/// You should avoid anything that would interfere with reproducible\n/// builds. For example, *any* absolute path should be avoided. This is one\n/// reason that `RUSTFLAGS` is not in [`Metadata::c_metadata`], because it often has\n/// absolute paths (like `--remap-path-prefix` which is fundamentally used for\n/// reproducible builds and has absolute paths in it). Also, in some cases the\n/// mangled symbols need to be stable between different builds with different\n/// settings. For example, profile-guided optimizations need to swap\n/// `RUSTFLAGS` between runs, but needs to keep the same symbol names.\n#[derive(Copy, Clone, Debug)]\npub struct Metadata {\n    unit_id: UnitHash,\n    c_metadata: UnitHash,\n    c_extra_filename: bool,\n    pkg_dir: bool,\n}\n\nimpl Metadata {\n    /// A hash to identify a given [`Unit`] in the build graph\n    pub fn unit_id(&self) -> UnitHash {\n        self.unit_id\n    }\n\n    /// A hash to add to symbol naming through `-C metadata`\n    pub fn c_metadata(&self) -> UnitHash {\n        self.c_metadata\n    }\n\n    /// A hash to add to file names through `-C extra-filename`\n    pub fn c_extra_filename(&self) -> Option<UnitHash> {\n        self.c_extra_filename.then_some(self.unit_id)\n    }\n\n    /// A hash to add to Cargo directory names\n    pub fn pkg_dir(&self) -> Option<UnitHash> {\n        self.pkg_dir.then_some(self.unit_id)\n    }\n}\n\n/// Collection of information about the files emitted by the compiler, and the\n/// output directory structure.\npub struct CompilationFiles<'a, 'gctx> {\n    /// The target directory layout for the host (and target if it is the same as host).\n    pub(super) host: Layout,\n    /// The target directory layout for the target (if different from then host).\n    pub(super) target: HashMap<CompileTarget, Layout>,\n    /// Additional directory to include a copy of the outputs.\n    export_dir: Option<PathBuf>,\n    /// The root targets requested by the user on the command line (does not\n    /// include dependencies).\n    roots: Vec<Unit>,\n    ws: &'a Workspace<'gctx>,\n    /// Metadata hash to use for each unit.\n    metas: HashMap<Unit, Metadata>,\n    /// For each Unit, a list all files produced.\n    outputs: HashMap<Unit, OnceCell<Arc<Vec<OutputFile>>>>,\n}\n\n/// Info about a single file emitted by the compiler.\n#[derive(Debug)]\npub struct OutputFile {\n    /// Absolute path to the file that will be produced by the build process.\n    pub path: PathBuf,\n    /// If it should be linked into `target`, and what it should be called\n    /// (e.g., without metadata).\n    pub hardlink: Option<PathBuf>,\n    /// If `--artifact-dir` is specified, the absolute path to the exported file.\n    pub export_path: Option<PathBuf>,\n    /// Type of the file (library / debug symbol / else).\n    pub flavor: FileFlavor,\n}\n\nimpl OutputFile {\n    /// Gets the hard link if present; otherwise, returns the path.\n    pub fn bin_dst(&self) -> &PathBuf {\n        match self.hardlink {\n            Some(ref link_dst) => link_dst,\n            None => &self.path,\n        }\n    }\n}\n\nimpl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> {\n    pub(super) fn new(\n        build_runner: &BuildRunner<'a, 'gctx>,\n        host: Layout,\n        target: HashMap<CompileTarget, Layout>,\n    ) -> CompilationFiles<'a, 'gctx> {\n        let mut metas = HashMap::new();\n        for unit in &build_runner.bcx.roots {\n            metadata_of(unit, build_runner, &mut metas);\n        }\n        let outputs = metas\n            .keys()\n            .cloned()\n            .map(|unit| (unit, OnceCell::new()))\n            .collect();\n        CompilationFiles {\n            ws: build_runner.bcx.ws,\n            host,\n            target,\n            export_dir: build_runner.bcx.build_config.export_dir.clone(),\n            roots: build_runner.bcx.roots.clone(),\n            metas,\n            outputs,\n        }\n    }\n\n    /// Returns the appropriate directory layout for either a plugin or not.\n    pub fn layout(&self, kind: CompileKind) -> &Layout {\n        match kind {\n            CompileKind::Host => &self.host,\n            CompileKind::Target(target) => &self.target[&target],\n        }\n    }\n\n    /// Gets the metadata for the given unit.\n    ///\n    /// See [`Metadata`] and [`fingerprint`] module for more.\n    ///\n    /// [`fingerprint`]: super::super::fingerprint#fingerprints-and-metadata\n    pub fn metadata(&self, unit: &Unit) -> Metadata {\n        self.metas[unit]\n    }\n\n    /// Gets the short hash based only on the `PackageId`.\n    /// Used for the metadata when `c_extra_filename` returns `None`.\n    fn target_short_hash(&self, unit: &Unit) -> String {\n        let hashable = unit.pkg.package_id().stable_hash(self.ws.root());\n        util::short_hash(&(METADATA_VERSION, hashable))\n    }\n\n    /// Returns the directory where the artifacts for the given unit are\n    /// initially created.\n    pub fn output_dir(&self, unit: &Unit) -> PathBuf {\n        // Docscrape units need to have doc/ set as the out_dir so sources for reverse-dependencies\n        // will be put into doc/ and not into deps/ where the *.examples files are stored.\n        if unit.mode.is_doc() || unit.mode.is_doc_scrape() {\n            self.layout(unit.kind)\n                .artifact_dir()\n                .expect(\"artifact-dir was not locked\")\n                .doc()\n                .to_path_buf()\n        } else if unit.mode.is_doc_test() {\n            panic!(\"doc tests do not have an out dir\");\n        } else if unit.target.is_custom_build() {\n            self.build_script_dir(unit)\n        } else if unit.target.is_example() && !self.ws.gctx().cli_unstable().build_dir_new_layout {\n            self.layout(unit.kind).build_dir().examples().to_path_buf()\n        } else if unit.artifact.is_true() {\n            self.artifact_dir(unit)\n        } else {\n            self.deps_dir(unit).to_path_buf()\n        }\n    }\n\n    /// Additional export directory from `--artifact-dir`.\n    pub fn export_dir(&self) -> Option<PathBuf> {\n        self.export_dir.clone()\n    }\n\n    /// Directory name to use for a package in the form `{NAME}/{HASH}`.\n    ///\n    /// Note that some units may share the same directory, so care should be\n    /// taken in those cases!\n    fn pkg_dir(&self, unit: &Unit) -> String {\n        let separator = match self.ws.gctx().cli_unstable().build_dir_new_layout {\n            true => \"/\",\n            false => \"-\",\n        };\n        let name = unit.pkg.package_id().name();\n        let hash = self.unit_hash(unit);\n        format!(\"{name}{separator}{hash}\")\n    }\n\n    /// The directory hash to use for a given unit\n    pub fn unit_hash(&self, unit: &Unit) -> String {\n        self.metas[unit]\n            .pkg_dir()\n            .map(|h| h.to_string())\n            .unwrap_or_else(|| self.target_short_hash(unit))\n    }\n\n    /// Returns the final artifact path for the host (`/…/target/debug`)\n    pub fn host_dest(&self) -> Option<&Path> {\n        self.host.artifact_dir().map(|v| v.dest())\n    }\n\n    /// Returns the root of the build output tree for the host (`/…/build-dir`)\n    pub fn host_build_root(&self) -> &Path {\n        self.host.build_dir().root()\n    }\n\n    /// Returns the host `deps` directory path for a given build unit.\n    pub fn host_deps(&self, unit: &Unit) -> PathBuf {\n        let dir = self.pkg_dir(unit);\n        self.host.build_dir().deps(&dir)\n    }\n\n    /// Returns the directories where Rust crate dependencies are found for the\n    /// specified unit.\n    pub fn deps_dir(&self, unit: &Unit) -> PathBuf {\n        let dir = self.pkg_dir(unit);\n        self.layout(unit.kind).build_dir().deps(&dir)\n    }\n\n    /// Returns the directories where Rust crate dependencies are found for the\n    /// specified unit. (new layout)\n    ///\n    /// New features should consider using this so we can avoid their migrations.\n    pub fn out_dir_new_layout(&self, unit: &Unit) -> PathBuf {\n        let dir = self.pkg_dir(unit);\n        self.layout(unit.kind)\n            .build_dir()\n            .out_force_new_layout(&dir)\n    }\n\n    /// Directory where the fingerprint for the given unit should go.\n    pub fn fingerprint_dir(&self, unit: &Unit) -> PathBuf {\n        let dir = self.pkg_dir(unit);\n        self.layout(unit.kind).build_dir().fingerprint(&dir)\n    }\n\n    /// The lock location for a given build unit.\n    pub fn build_unit_lock(&self, unit: &Unit) -> PathBuf {\n        let dir = self.pkg_dir(unit);\n        self.layout(unit.kind)\n            .build_dir()\n            .build_unit(&dir)\n            .join(\".lock\")\n    }\n\n    /// Directory where incremental output for the given unit should go.\n    pub fn incremental_dir(&self, unit: &Unit) -> &Path {\n        self.layout(unit.kind).build_dir().incremental()\n    }\n\n    /// Directory where timing output should go.\n    pub fn timings_dir(&self) -> Option<&Path> {\n        self.host.artifact_dir().map(|v| v.timings())\n    }\n\n    /// Returns the path for a file in the fingerprint directory.\n    ///\n    /// The \"prefix\" should be something to distinguish the file from other\n    /// files in the fingerprint directory.\n    pub fn fingerprint_file_path(&self, unit: &Unit, prefix: &str) -> PathBuf {\n        // Different targets need to be distinguished in the\n        let kind = unit.target.kind().description();\n        let flavor = if unit.mode.is_any_test() {\n            \"test-\"\n        } else if unit.mode.is_doc() {\n            \"doc-\"\n        } else if unit.mode.is_run_custom_build() {\n            \"run-\"\n        } else {\n            \"\"\n        };\n        let name = format!(\"{}{}{}-{}\", prefix, flavor, kind, unit.target.name());\n        self.fingerprint_dir(unit).join(name)\n    }\n\n    /// Path where compiler output is cached.\n    pub fn message_cache_path(&self, unit: &Unit) -> PathBuf {\n        self.fingerprint_file_path(unit, \"output-\")\n    }\n\n    /// Returns the directory where a compiled build script is stored.\n    /// `/path/to/target/{debug,release}/build/PKG-HASH`\n    pub fn build_script_dir(&self, unit: &Unit) -> PathBuf {\n        assert!(unit.target.is_custom_build());\n        assert!(!unit.mode.is_run_custom_build());\n        assert!(self.metas.contains_key(unit));\n        let dir = self.pkg_dir(unit);\n        self.layout(CompileKind::Host)\n            .build_dir()\n            .build_script(&dir)\n    }\n\n    /// Returns the directory for compiled artifacts files.\n    /// `/path/to/target/{debug,release}/deps/artifact/KIND/PKG-HASH`\n    fn artifact_dir(&self, unit: &Unit) -> PathBuf {\n        assert!(self.metas.contains_key(unit));\n        assert!(unit.artifact.is_true());\n        let dir = self.pkg_dir(unit);\n        let kind = match unit.target.kind() {\n            TargetKind::Bin => \"bin\",\n            TargetKind::Lib(lib_kinds) => match lib_kinds.as_slice() {\n                &[CrateType::Cdylib] => \"cdylib\",\n                &[CrateType::Staticlib] => \"staticlib\",\n                invalid => unreachable!(\n                    \"BUG: unexpected artifact library type(s): {:?} - these should have been split\",\n                    invalid\n                ),\n            },\n            invalid => unreachable!(\n                \"BUG: {:?} are not supposed to be used as artifacts\",\n                invalid\n            ),\n        };\n        self.layout(unit.kind).build_dir().artifact(&dir, kind)\n    }\n\n    /// Returns the directory where information about running a build script\n    /// is stored.\n    /// `/path/to/target/{debug,release}/build/PKG-HASH`\n    pub fn build_script_run_dir(&self, unit: &Unit) -> PathBuf {\n        assert!(unit.target.is_custom_build());\n        assert!(unit.mode.is_run_custom_build());\n        let dir = self.pkg_dir(unit);\n        self.layout(unit.kind)\n            .build_dir()\n            .build_script_execution(&dir)\n    }\n\n    /// Returns the \"`OUT_DIR`\" directory for running a build script.\n    /// `/path/to/target/{debug,release}/build/PKG-HASH/out`\n    pub fn build_script_out_dir(&self, unit: &Unit) -> PathBuf {\n        self.build_script_run_dir(unit).join(\"out\")\n    }\n\n    /// Returns the path to the executable binary for the given bin target.\n    ///\n    /// This should only to be used when a `Unit` is not available.\n    pub fn bin_link_for_target(\n        &self,\n        target: &Target,\n        kind: CompileKind,\n        bcx: &BuildContext<'_, '_>,\n    ) -> CargoResult<Option<PathBuf>> {\n        assert!(target.is_bin());\n        let Some(dest) = self.layout(kind).artifact_dir().map(|v| v.dest()) else {\n            return Ok(None);\n        };\n        let info = bcx.target_data.info(kind);\n        let (file_types, _) = info\n            .rustc_outputs(\n                CompileMode::Build,\n                &TargetKind::Bin,\n                bcx.target_data.short_name(&kind),\n                bcx.gctx,\n            )\n            .expect(\"target must support `bin`\");\n\n        let file_type = file_types\n            .iter()\n            .find(|file_type| file_type.flavor == FileFlavor::Normal)\n            .expect(\"target must support `bin`\");\n\n        Ok(Some(dest.join(file_type.uplift_filename(target))))\n    }\n\n    /// Returns the filenames that the given unit will generate.\n    ///\n    /// Note: It is not guaranteed that all of the files will be generated.\n    pub(super) fn outputs(\n        &self,\n        unit: &Unit,\n        bcx: &BuildContext<'a, 'gctx>,\n    ) -> CargoResult<Arc<Vec<OutputFile>>> {\n        self.outputs[unit]\n            .try_borrow_with(|| self.calc_outputs(unit, bcx))\n            .map(Arc::clone)\n    }\n\n    /// Returns the path where the output for the given unit and `FileType`\n    /// should be uplifted to.\n    ///\n    /// Returns `None` if the unit shouldn't be uplifted (for example, a\n    /// dependent rlib).\n    fn uplift_to(&self, unit: &Unit, file_type: &FileType, from_path: &Path) -> Option<PathBuf> {\n        // Tests, check, doc, etc. should not be uplifted.\n        if unit.mode != CompileMode::Build || file_type.flavor == FileFlavor::Rmeta {\n            return None;\n        }\n\n        // Artifact dependencies are never uplifted.\n        if unit.artifact.is_true() {\n            return None;\n        }\n\n        // - Binaries: The user always wants to see these, even if they are\n        //   implicitly built (for example for integration tests).\n        // - dylibs: This ensures that the dynamic linker pulls in all the\n        //   latest copies (even if the dylib was built from a previous cargo\n        //   build). There are complex reasons for this, see #8139, #6167, #6162.\n        // - Things directly requested from the command-line (the \"roots\").\n        //   This one is a little questionable for rlibs (see #6131), but is\n        //   historically how Cargo has operated. This is primarily useful to\n        //   give the user access to staticlibs and cdylibs.\n        if !unit.target.is_bin()\n            && !unit.target.is_custom_build()\n            && file_type.crate_type != Some(CrateType::Dylib)\n            && !self.roots.contains(unit)\n        {\n            return None;\n        }\n\n        let filename = file_type.uplift_filename(&unit.target);\n        let uplift_path = if unit.target.is_example() {\n            // Examples live in their own little world.\n            self.layout(unit.kind)\n                .artifact_dir()?\n                .examples()\n                .join(filename)\n        } else if unit.target.is_custom_build() {\n            self.build_script_dir(unit).join(filename)\n        } else {\n            self.layout(unit.kind).artifact_dir()?.dest().join(filename)\n        };\n        if from_path == uplift_path {\n            // This can happen with things like examples that reside in the\n            // same directory, do not have a metadata hash (like on Windows),\n            // and do not have hyphens.\n            return None;\n        }\n        Some(uplift_path)\n    }\n\n    /// Calculates the filenames that the given unit will generate.\n    /// Should use [`CompilationFiles::outputs`] instead\n    /// as it caches the result of this function.\n    fn calc_outputs(\n        &self,\n        unit: &Unit,\n        bcx: &BuildContext<'a, 'gctx>,\n    ) -> CargoResult<Arc<Vec<OutputFile>>> {\n        let ret = match unit.mode {\n            _ if unit.skip_non_compile_time_dep => {\n                // This skips compilations so no outputs\n                vec![]\n            }\n            CompileMode::Doc => {\n                let path = if bcx.build_config.intent.wants_doc_json_output() {\n                    self.output_dir(unit)\n                        .join(format!(\"{}.json\", unit.target.crate_name()))\n                } else {\n                    self.output_dir(unit)\n                        .join(unit.target.crate_name())\n                        .join(\"index.html\")\n                };\n\n                let mut outputs = vec![OutputFile {\n                    path,\n                    hardlink: None,\n                    export_path: None,\n                    flavor: FileFlavor::Normal,\n                }];\n\n                if bcx.gctx.cli_unstable().rustdoc_mergeable_info {\n                    // `-Zrustdoc-mergeable-info` always uses the new layout.\n                    outputs.push(OutputFile {\n                        path: self\n                            .out_dir_new_layout(unit)\n                            .join(unit.target.crate_name())\n                            .with_extension(\"json\"),\n                        hardlink: None,\n                        export_path: None,\n                        flavor: FileFlavor::DocParts,\n                    })\n                }\n\n                outputs\n            }\n            CompileMode::RunCustomBuild => {\n                // At this time, this code path does not handle build script\n                // outputs.\n                vec![]\n            }\n            CompileMode::Doctest => {\n                // Doctests are built in a temporary directory and then\n                // deleted. There is the `--persist-doctests` unstable flag,\n                // but Cargo does not know about that.\n                vec![]\n            }\n            CompileMode::Docscrape => {\n                // The file name needs to be stable across Cargo sessions.\n                // This originally used unit.buildkey(), but that isn't stable,\n                // so we use metadata instead (prefixed with name for debugging).\n                let file_name = format!(\n                    \"{}-{}.examples\",\n                    unit.pkg.name(),\n                    self.metadata(unit).unit_id()\n                );\n                let path = self.deps_dir(unit).join(file_name);\n                vec![OutputFile {\n                    path,\n                    hardlink: None,\n                    export_path: None,\n                    flavor: FileFlavor::Normal,\n                }]\n            }\n            CompileMode::Test | CompileMode::Build | CompileMode::Check { .. } => {\n                let mut outputs = self.calc_outputs_rustc(unit, bcx)?;\n                if bcx.build_config.sbom && bcx.gctx.cli_unstable().sbom {\n                    let sbom_files: Vec<_> = outputs\n                        .iter()\n                        .filter(|o| matches!(o.flavor, FileFlavor::Normal | FileFlavor::Linkable))\n                        .map(|output| OutputFile {\n                            path: Self::append_sbom_suffix(&output.path),\n                            hardlink: output.hardlink.as_ref().map(Self::append_sbom_suffix),\n                            export_path: output.export_path.as_ref().map(Self::append_sbom_suffix),\n                            flavor: FileFlavor::Sbom,\n                        })\n                        .collect();\n                    outputs.extend(sbom_files.into_iter());\n                }\n                outputs\n            }\n        };\n        debug!(\"Target filenames: {:?}\", ret);\n\n        Ok(Arc::new(ret))\n    }\n\n    /// Append the SBOM suffix to the file name.\n    fn append_sbom_suffix(link: &PathBuf) -> PathBuf {\n        const SBOM_FILE_EXTENSION: &str = \".cargo-sbom.json\";\n        let mut link_buf = link.clone().into_os_string();\n        link_buf.push(SBOM_FILE_EXTENSION);\n        PathBuf::from(link_buf)\n    }\n\n    /// Computes the actual, full pathnames for all the files generated by rustc.\n    ///\n    /// The `OutputFile` also contains the paths where those files should be\n    /// \"uplifted\" to.\n    fn calc_outputs_rustc(\n        &self,\n        unit: &Unit,\n        bcx: &BuildContext<'a, 'gctx>,\n    ) -> CargoResult<Vec<OutputFile>> {\n        let out_dir = self.output_dir(unit);\n\n        let info = bcx.target_data.info(unit.kind);\n        let triple = bcx.target_data.short_name(&unit.kind);\n        let (file_types, unsupported) =\n            info.rustc_outputs(unit.mode, unit.target.kind(), triple, bcx.gctx)?;\n        if file_types.is_empty() {\n            if !unsupported.is_empty() {\n                let unsupported_strs: Vec<_> = unsupported.iter().map(|ct| ct.as_str()).collect();\n                anyhow::bail!(\n                    \"cannot produce {} for `{}` as the target `{}` \\\n                     does not support these crate types\",\n                    unsupported_strs.join(\", \"),\n                    unit.pkg,\n                    triple,\n                )\n            }\n            anyhow::bail!(\n                \"cannot compile `{}` as the target `{}` does not \\\n                 support any of the output crate types\",\n                unit.pkg,\n                triple,\n            );\n        }\n\n        // Convert FileType to OutputFile.\n        let mut outputs = Vec::new();\n        for file_type in file_types {\n            let meta = self.metas[unit];\n            let meta_opt = meta.c_extra_filename().map(|h| h.to_string());\n            let path = out_dir.join(file_type.output_filename(&unit.target, meta_opt.as_deref()));\n\n            // If, the `different_binary_name` feature is enabled, the name of the hardlink will\n            // be the name of the binary provided by the user in `Cargo.toml`.\n            let hardlink = self.uplift_to(unit, &file_type, &path);\n            let export_path = if unit.target.is_custom_build() {\n                None\n            } else {\n                self.export_dir.as_ref().and_then(|export_dir| {\n                    hardlink\n                        .as_ref()\n                        .map(|hardlink| export_dir.join(hardlink.file_name().unwrap()))\n                })\n            };\n            outputs.push(OutputFile {\n                path,\n                hardlink,\n                export_path,\n                flavor: file_type.flavor,\n            });\n        }\n        Ok(outputs)\n    }\n}\n\n/// Gets the metadata hash for the given [`Unit`].\n///\n/// When a metadata hash doesn't exist for the given unit,\n/// this calls itself recursively to compute metadata hashes of all its dependencies.\n/// See [`compute_metadata`] for how a single metadata hash is computed.\nfn metadata_of<'a>(\n    unit: &Unit,\n    build_runner: &BuildRunner<'_, '_>,\n    metas: &'a mut HashMap<Unit, Metadata>,\n) -> &'a Metadata {\n    if !metas.contains_key(unit) {\n        let meta = compute_metadata(unit, build_runner, metas);\n        metas.insert(unit.clone(), meta);\n        for dep in build_runner.unit_deps(unit) {\n            metadata_of(&dep.unit, build_runner, metas);\n        }\n    }\n    &metas[unit]\n}\n\n/// Computes the metadata hash for the given [`Unit`].\nfn compute_metadata(\n    unit: &Unit,\n    build_runner: &BuildRunner<'_, '_>,\n    metas: &mut HashMap<Unit, Metadata>,\n) -> Metadata {\n    let bcx = &build_runner.bcx;\n    let deps_metadata = build_runner\n        .unit_deps(unit)\n        .iter()\n        .map(|dep| *metadata_of(&dep.unit, build_runner, metas))\n        .collect::<Vec<_>>();\n    let c_extra_filename = use_extra_filename(bcx, unit);\n    let pkg_dir = use_pkg_dir(bcx, unit);\n\n    let mut shared_hasher = StableHasher::new();\n\n    METADATA_VERSION.hash(&mut shared_hasher);\n\n    let ws_root = if unit.is_std {\n        // SourceId for stdlib crates is an absolute path inside the sysroot.\n        // Pass the sysroot as workspace root so that we hash a relative path.\n        // This avoids the metadata hash changing depending on where the user installed rustc.\n        &bcx.target_data.get_info(unit.kind).unwrap().sysroot\n    } else {\n        bcx.ws.root()\n    };\n\n    // Unique metadata per (name, source, version) triple. This'll allow us\n    // to pull crates from anywhere without worrying about conflicts.\n    unit.pkg\n        .package_id()\n        .stable_hash(ws_root)\n        .hash(&mut shared_hasher);\n\n    // Also mix in enabled features to our metadata. This'll ensure that\n    // when changing feature sets each lib is separately cached.\n    unit.features.hash(&mut shared_hasher);\n\n    // Throw in the profile we're compiling with. This helps caching\n    // `panic=abort` and `panic=unwind` artifacts, additionally with various\n    // settings like debuginfo and whatnot.\n    unit.profile.hash(&mut shared_hasher);\n    unit.mode.hash(&mut shared_hasher);\n    build_runner.lto[unit].hash(&mut shared_hasher);\n\n    // Artifacts compiled for the host should have a different\n    // metadata piece than those compiled for the target, so make sure\n    // we throw in the unit's `kind` as well.  Use `fingerprint_hash`\n    // so that the StableHash doesn't change based on the pathnames\n    // of the custom target JSON spec files.\n    unit.kind.fingerprint_hash().hash(&mut shared_hasher);\n\n    // Finally throw in the target name/kind. This ensures that concurrent\n    // compiles of targets in the same crate don't collide.\n    unit.target.name().hash(&mut shared_hasher);\n    unit.target.kind().hash(&mut shared_hasher);\n\n    hash_rustc_version(bcx, &mut shared_hasher, unit);\n\n    if build_runner.bcx.ws.is_member(&unit.pkg) {\n        // This is primarily here for clippy. This ensures that the clippy\n        // artifacts are separate from the `check` ones.\n        if let Some(path) = &build_runner.bcx.rustc().workspace_wrapper {\n            path.hash(&mut shared_hasher);\n        }\n    }\n\n    // Seed the contents of `__CARGO_DEFAULT_LIB_METADATA` to the hasher if present.\n    // This should be the release channel, to get a different hash for each channel.\n    if let Ok(ref channel) = build_runner\n        .bcx\n        .gctx\n        .get_env(\"__CARGO_DEFAULT_LIB_METADATA\")\n    {\n        channel.hash(&mut shared_hasher);\n    }\n\n    // std units need to be kept separate from user dependencies. std crates\n    // are differentiated in the Unit with `is_std` (for things like\n    // `-Zforce-unstable-if-unmarked`), so they are always built separately.\n    // This isn't strictly necessary for build dependencies which probably\n    // don't need unstable support. A future experiment might be to set\n    // `is_std` to false for build dependencies so that they can be shared\n    // with user dependencies.\n    unit.is_std.hash(&mut shared_hasher);\n\n    // While we don't hash RUSTFLAGS because it may contain absolute paths that\n    // hurts reproducibility, we track whether a unit's RUSTFLAGS is from host\n    // config, so that we can generate a different metadata hash for runtime\n    // and compile-time units.\n    //\n    // HACK: This is a temporary hack for fixing rust-lang/cargo#14253\n    // Need to find a long-term solution to replace this fragile workaround.\n    // See https://github.com/rust-lang/cargo/pull/14432#discussion_r1725065350\n    if unit.kind.is_host() && !bcx.gctx.target_applies_to_host().unwrap_or_default() {\n        let host_info = bcx.target_data.info(CompileKind::Host);\n        let target_configs_are_different = unit.rustflags != host_info.rustflags\n            || unit.rustdocflags != host_info.rustdocflags\n            || bcx\n                .target_data\n                .target_config(CompileKind::Host)\n                .links_overrides\n                != unit.links_overrides;\n        target_configs_are_different.hash(&mut shared_hasher);\n    }\n\n    let mut c_metadata_hasher = shared_hasher.clone();\n    // Mix in the target-metadata of all the dependencies of this target.\n    let mut dep_c_metadata_hashes = deps_metadata\n        .iter()\n        .map(|m| m.c_metadata)\n        .collect::<Vec<_>>();\n    dep_c_metadata_hashes.sort();\n    dep_c_metadata_hashes.hash(&mut c_metadata_hasher);\n\n    let mut unit_id_hasher = shared_hasher.clone();\n    // Mix in the target-metadata of all the dependencies of this target.\n    let mut dep_unit_id_hashes = deps_metadata.iter().map(|m| m.unit_id).collect::<Vec<_>>();\n    dep_unit_id_hashes.sort();\n    dep_unit_id_hashes.hash(&mut unit_id_hasher);\n    // Avoid trashing the caches on RUSTFLAGS changing via `unit_id`\n    //\n    // Limited to `unit_id` to help with reproducible build / PGO issues.\n    let default = Vec::new();\n    let extra_args = build_runner.bcx.extra_args_for(unit).unwrap_or(&default);\n    if !has_remap_path_prefix(&extra_args) {\n        extra_args.hash(&mut unit_id_hasher);\n    }\n    if unit.mode.is_doc() || unit.mode.is_doc_scrape() {\n        if !has_remap_path_prefix(&unit.rustdocflags) {\n            unit.rustdocflags.hash(&mut unit_id_hasher);\n        }\n    } else {\n        if !has_remap_path_prefix(&unit.rustflags) {\n            unit.rustflags.hash(&mut unit_id_hasher);\n        }\n    }\n\n    let c_metadata = UnitHash(Hasher::finish(&c_metadata_hasher));\n    let unit_id = UnitHash(Hasher::finish(&unit_id_hasher));\n\n    Metadata {\n        unit_id,\n        c_metadata,\n        c_extra_filename,\n        pkg_dir,\n    }\n}\n\n/// HACK: Detect the *potential* presence of `--remap-path-prefix`\n///\n/// As CLI parsing is contextual and dependent on the CLI definition to understand the context, we\n/// can't say for sure whether `--remap-path-prefix` is present, so we guess if anything looks like\n/// it.\n/// If we could, we'd strip it out for hashing.\n/// Instead, we use this to avoid hashing rustflags if it might be present to avoid the risk of taking\n/// a flag that is trying to make things reproducible and making things less reproducible by the\n/// `-Cextra-filename` showing up in the rlib, even with `split-debuginfo`.\nfn has_remap_path_prefix(args: &[String]) -> bool {\n    args.iter()\n        .any(|s| s.starts_with(\"--remap-path-prefix=\") || s == \"--remap-path-prefix\")\n}\n\n/// Hash the version of rustc being used during the build process.\nfn hash_rustc_version(bcx: &BuildContext<'_, '_>, hasher: &mut StableHasher, unit: &Unit) {\n    let vers = &bcx.rustc().version;\n    if vers.pre.is_empty() || bcx.gctx.cli_unstable().separate_nightlies {\n        // For stable, keep the artifacts separate. This helps if someone is\n        // testing multiple versions, to avoid recompiles. Note though that for\n        // cross-compiled builds the `host:` line of `verbose_version` is\n        // omitted since rustc should produce the same output for each target\n        // regardless of the host.\n        for line in bcx.rustc().verbose_version.lines() {\n            if unit.kind.is_host() || !line.starts_with(\"host: \") {\n                line.hash(hasher);\n            }\n        }\n        return;\n    }\n    // On \"nightly\"/\"beta\"/\"dev\"/etc, keep each \"channel\" separate. Don't hash\n    // the date/git information, so that whenever someone updates \"nightly\",\n    // they won't have a bunch of stale artifacts in the target directory.\n    //\n    // This assumes that the first segment is the important bit (\"nightly\",\n    // \"beta\", \"dev\", etc.). Skip other parts like the `.3` in `-beta.3`.\n    vers.pre.split('.').next().hash(hasher);\n    // Keep \"host\" since some people switch hosts to implicitly change\n    // targets, (like gnu vs musl or gnu vs msvc). In the future, we may want\n    // to consider hashing `unit.kind.short_name()` instead.\n    if unit.kind.is_host() {\n        bcx.rustc().host.hash(hasher);\n    }\n    // None of the other lines are important. Currently they are:\n    // binary: rustc  <-- or \"rustdoc\"\n    // commit-hash: 38114ff16e7856f98b2b4be7ab4cd29b38bed59a\n    // commit-date: 2020-03-21\n    // host: x86_64-apple-darwin\n    // release: 1.44.0-nightly\n    // LLVM version: 9.0\n    //\n    // The backend version (\"LLVM version\") might become more relevant in\n    // the future when cranelift sees more use, and people want to switch\n    // between different backends without recompiling.\n}\n\n/// Returns whether or not this unit should use a hash in the filename to make it unique.\nfn use_extra_filename(bcx: &BuildContext<'_, '_>, unit: &Unit) -> bool {\n    if unit.mode.is_doc_test() || unit.mode.is_doc() {\n        // Doc tests do not have metadata.\n        return false;\n    }\n    if bcx.gctx.cli_unstable().build_dir_new_layout {\n        if unit.mode.is_any_test() || unit.mode.is_check() {\n            // These always use metadata.\n            return true;\n        }\n        // No metadata in these cases:\n        //\n        // - dylib, cdylib, executable: `pkg_dir` avoids collisions for us and rustc isn't looking these\n        //   up by `-Cextra-filename`\n        //\n        // The __CARGO_DEFAULT_LIB_METADATA env var is used to override this to\n        // force metadata in the hash. This is only used for building libstd. For\n        // example, if libstd is placed in a common location, we don't want a file\n        // named /usr/lib/libstd.so which could conflict with other rustc\n        // installs. In addition it prevents accidentally loading a libstd of a\n        // different compiler at runtime.\n        // See https://github.com/rust-lang/cargo/issues/3005\n        if (unit.target.is_dylib() || unit.target.is_cdylib() || unit.target.is_executable())\n            && bcx.gctx.get_env(\"__CARGO_DEFAULT_LIB_METADATA\").is_err()\n        {\n            return false;\n        }\n    } else {\n        if unit.mode.is_any_test() || unit.mode.is_check() {\n            // These always use metadata.\n            return true;\n        }\n        // No metadata in these cases:\n        //\n        // - dylibs:\n        //   - if any dylib names are encoded in executables, so they can't be renamed.\n        //   - TODO: Maybe use `-install-name` on macOS or `-soname` on other UNIX systems\n        //     to specify the dylib name to be used by the linker instead of the filename.\n        // - Windows MSVC executables: The path to the PDB is embedded in the\n        //   executable, and we don't want the PDB path to include the hash in it.\n        // - wasm32-unknown-emscripten executables: When using emscripten, the path to the\n        //   .wasm file is embedded in the .js file, so we don't want the hash in there.\n        //\n        // This is only done for local packages, as we don't expect to export\n        // dependencies.\n        //\n        // The __CARGO_DEFAULT_LIB_METADATA env var is used to override this to\n        // force metadata in the hash. This is only used for building libstd. For\n        // example, if libstd is placed in a common location, we don't want a file\n        // named /usr/lib/libstd.so which could conflict with other rustc\n        // installs. In addition it prevents accidentally loading a libstd of a\n        // different compiler at runtime.\n        // See https://github.com/rust-lang/cargo/issues/3005\n        let short_name = bcx.target_data.short_name(&unit.kind);\n        if (unit.target.is_dylib()\n            || unit.target.is_cdylib()\n            || (unit.target.is_executable() && short_name == \"wasm32-unknown-emscripten\")\n            || (unit.target.is_executable() && short_name.contains(\"msvc\")))\n            && unit.pkg.package_id().source_id().is_path()\n            && bcx.gctx.get_env(\"__CARGO_DEFAULT_LIB_METADATA\").is_err()\n        {\n            return false;\n        }\n    }\n    true\n}\n\n/// Returns whether or not this unit should use a hash in the pkg_dir to make it unique.\nfn use_pkg_dir(bcx: &BuildContext<'_, '_>, unit: &Unit) -> bool {\n    if unit.mode.is_doc_test() || unit.mode.is_doc() {\n        // Doc tests do not have metadata.\n        return false;\n    }\n    if bcx.gctx.cli_unstable().build_dir_new_layout {\n        // These always use metadata.\n        return true;\n    }\n    if unit.mode.is_any_test() || unit.mode.is_check() {\n        // These always use metadata.\n        return true;\n    }\n    // No metadata in these cases:\n    //\n    // - dylibs:\n    //   - if any dylib names are encoded in executables, so they can't be renamed.\n    //   - TODO: Maybe use `-install-name` on macOS or `-soname` on other UNIX systems\n    //     to specify the dylib name to be used by the linker instead of the filename.\n    // - Windows MSVC executables: The path to the PDB is embedded in the\n    //   executable, and we don't want the PDB path to include the hash in it.\n    // - wasm32-unknown-emscripten executables: When using emscripten, the path to the\n    //   .wasm file is embedded in the .js file, so we don't want the hash in there.\n    //\n    // This is only done for local packages, as we don't expect to export\n    // dependencies.\n    //\n    // The __CARGO_DEFAULT_LIB_METADATA env var is used to override this to\n    // force metadata in the hash. This is only used for building libstd. For\n    // example, if libstd is placed in a common location, we don't want a file\n    // named /usr/lib/libstd.so which could conflict with other rustc\n    // installs. In addition it prevents accidentally loading a libstd of a\n    // different compiler at runtime.\n    // See https://github.com/rust-lang/cargo/issues/3005\n    let short_name = bcx.target_data.short_name(&unit.kind);\n    if (unit.target.is_dylib()\n        || unit.target.is_cdylib()\n        || (unit.target.is_executable() && short_name == \"wasm32-unknown-emscripten\")\n        || (unit.target.is_executable() && short_name.contains(\"msvc\")))\n        && unit.pkg.package_id().source_id().is_path()\n        && bcx.gctx.get_env(\"__CARGO_DEFAULT_LIB_METADATA\").is_err()\n    {\n        return false;\n    }\n    true\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/build_runner/mod.rs",
    "content": "//! [`BuildRunner`] is the mutable state used during the build process.\n\nuse std::collections::{HashMap, HashSet};\nuse std::path::{Path, PathBuf};\nuse std::sync::{Arc, Mutex};\n\nuse crate::core::PackageId;\nuse crate::core::compiler::compilation::{self, UnitOutput};\nuse crate::core::compiler::locking::LockManager;\nuse crate::core::compiler::{self, Unit, UserIntent, artifact};\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::errors::CargoResult;\nuse annotate_snippets::{Level, Message};\nuse anyhow::{Context as _, bail};\nuse cargo_util::paths;\nuse filetime::FileTime;\nuse itertools::Itertools;\nuse jobserver::Client;\n\nuse super::RustdocFingerprint;\nuse super::custom_build::{self, BuildDeps, BuildScriptOutputs, BuildScripts};\nuse super::fingerprint::{Checksum, Fingerprint};\nuse super::job_queue::JobQueue;\nuse super::layout::Layout;\nuse super::lto::Lto;\nuse super::unit_graph::UnitDep;\nuse super::{BuildContext, Compilation, CompileKind, CompileMode, Executor, FileFlavor};\n\nmod compilation_files;\nuse self::compilation_files::CompilationFiles;\npub use self::compilation_files::{Metadata, OutputFile, UnitHash};\n\n/// Collection of all the stuff that is needed to perform a build.\n///\n/// Different from the [`BuildContext`], `Context` is a _mutable_ state used\n/// throughout the entire build process. Everything is coordinated through this.\n///\n/// [`BuildContext`]: crate::core::compiler::BuildContext\npub struct BuildRunner<'a, 'gctx> {\n    /// Mostly static information about the build task.\n    pub bcx: &'a BuildContext<'a, 'gctx>,\n    /// A large collection of information about the result of the entire compilation.\n    pub compilation: Compilation<'gctx>,\n    /// Output from build scripts, updated after each build script runs.\n    pub build_script_outputs: Arc<Mutex<BuildScriptOutputs>>,\n    /// Dependencies (like rerun-if-changed) declared by a build script.\n    /// This is *only* populated from the output from previous runs.\n    /// If the build script hasn't ever been run, then it must be run.\n    pub build_explicit_deps: HashMap<Unit, BuildDeps>,\n    /// Fingerprints used to detect if a unit is out-of-date.\n    pub fingerprints: HashMap<Unit, Arc<Fingerprint>>,\n    /// Cache of file mtimes to reduce filesystem hits.\n    pub mtime_cache: HashMap<PathBuf, FileTime>,\n    /// Cache of file checksums to reduce filesystem reads.\n    pub checksum_cache: HashMap<PathBuf, Checksum>,\n    /// A set used to track which units have been compiled.\n    /// A unit may appear in the job graph multiple times as a dependency of\n    /// multiple packages, but it only needs to run once.\n    pub compiled: HashSet<Unit>,\n    /// Linking information for each `Unit`.\n    /// See `build_map` for details.\n    pub build_scripts: HashMap<Unit, Arc<BuildScripts>>,\n    /// Job server client to manage concurrency with other processes.\n    pub jobserver: Client,\n    /// \"Primary\" packages are the ones the user selected on the command-line\n    /// with `-p` flags. If no flags are specified, then it is the defaults\n    /// based on the current directory and the default workspace members.\n    primary_packages: HashSet<PackageId>,\n    /// An abstraction of the files and directories that will be generated by\n    /// the compilation. This is `None` until after `unit_dependencies` has\n    /// been computed.\n    files: Option<CompilationFiles<'a, 'gctx>>,\n\n    /// A set of units which are compiling rlibs and are expected to produce\n    /// metadata files in addition to the rlib itself.\n    rmeta_required: HashSet<Unit>,\n\n    /// Map of the LTO-status of each unit. This indicates what sort of\n    /// compilation is happening (only object, only bitcode, both, etc), and is\n    /// precalculated early on.\n    pub lto: HashMap<Unit, Lto>,\n\n    /// Map of Doc/Docscrape units to metadata for their -Cmetadata flag.\n    /// See `Context::find_metadata_units` for more details.\n    pub metadata_for_doc_units: HashMap<Unit, Metadata>,\n\n    /// Set of metadata of Docscrape units that fail before completion, e.g.\n    /// because the target has a type error. This is in an Arc<Mutex<..>>\n    /// because it is continuously updated as the job progresses.\n    pub failed_scrape_units: Arc<Mutex<HashSet<UnitHash>>>,\n\n    /// Manages locks for build units when fine grain locking is enabled.\n    pub lock_manager: Arc<LockManager>,\n}\n\nimpl<'a, 'gctx> BuildRunner<'a, 'gctx> {\n    pub fn new(bcx: &'a BuildContext<'a, 'gctx>) -> CargoResult<Self> {\n        // Load up the jobserver that we'll use to manage our parallelism. This\n        // is the same as the GNU make implementation of a jobserver, and\n        // intentionally so! It's hoped that we can interact with GNU make and\n        // all share the same jobserver.\n        //\n        // Note that if we don't have a jobserver in our environment then we\n        // create our own, and we create it with `n` tokens, but immediately\n        // acquire one, because one token is ourself, a running process.\n        let jobserver = match bcx.gctx.jobserver_from_env() {\n            Some(c) => c.clone(),\n            None => {\n                let client =\n                    Client::new(bcx.jobs() as usize).context(\"failed to create jobserver\")?;\n                client.acquire_raw()?;\n                client\n            }\n        };\n\n        Ok(Self {\n            bcx,\n            compilation: Compilation::new(bcx)?,\n            build_script_outputs: Arc::new(Mutex::new(BuildScriptOutputs::default())),\n            fingerprints: HashMap::new(),\n            mtime_cache: HashMap::new(),\n            checksum_cache: HashMap::new(),\n            compiled: HashSet::new(),\n            build_scripts: HashMap::new(),\n            build_explicit_deps: HashMap::new(),\n            jobserver,\n            primary_packages: HashSet::new(),\n            files: None,\n            rmeta_required: HashSet::new(),\n            lto: HashMap::new(),\n            metadata_for_doc_units: HashMap::new(),\n            failed_scrape_units: Arc::new(Mutex::new(HashSet::new())),\n            lock_manager: Arc::new(LockManager::new()),\n        })\n    }\n\n    /// Dry-run the compilation without actually running it.\n    ///\n    /// This is expected to collect information like the location of output artifacts.\n    /// Please keep in sync with non-compilation part in [`BuildRunner::compile`].\n    pub fn dry_run(mut self) -> CargoResult<Compilation<'gctx>> {\n        let _lock = self\n            .bcx\n            .gctx\n            .acquire_package_cache_lock(CacheLockMode::Shared)?;\n        self.lto = super::lto::generate(self.bcx)?;\n        self.prepare_units()?;\n        self.prepare()?;\n        self.check_collisions()?;\n\n        for unit in &self.bcx.roots {\n            self.collect_tests_and_executables(unit)?;\n        }\n\n        Ok(self.compilation)\n    }\n\n    /// Starts compilation, waits for it to finish, and returns information\n    /// about the result of compilation.\n    ///\n    /// See [`ops::cargo_compile`] for a higher-level view of the compile process.\n    ///\n    /// [`ops::cargo_compile`]: crate::ops::cargo_compile\n    #[tracing::instrument(skip_all)]\n    pub fn compile(mut self, exec: &Arc<dyn Executor>) -> CargoResult<Compilation<'gctx>> {\n        // A shared lock is held during the duration of the build since rustc\n        // needs to read from the `src` cache, and we don't want other\n        // commands modifying the `src` cache while it is running.\n        let _lock = self\n            .bcx\n            .gctx\n            .acquire_package_cache_lock(CacheLockMode::Shared)?;\n        let mut queue = JobQueue::new(self.bcx);\n        self.lto = super::lto::generate(self.bcx)?;\n        self.prepare_units()?;\n        self.prepare()?;\n        custom_build::build_map(&mut self)?;\n        self.check_collisions()?;\n        self.compute_metadata_for_doc_units();\n\n        // We need to make sure that if there were any previous docs already compiled,\n        // they were compiled with the same Rustc version that we're currently using.\n        // See the function doc comment for more.\n        if self.bcx.build_config.intent.is_doc() {\n            RustdocFingerprint::check_rustdoc_fingerprint(&self)?\n        }\n\n        for unit in &self.bcx.roots {\n            let force_rebuild = self.bcx.build_config.force_rebuild;\n            super::compile(&mut self, &mut queue, unit, exec, force_rebuild)?;\n        }\n\n        // Now that we've got the full job queue and we've done all our\n        // fingerprint analysis to determine what to run, bust all the memoized\n        // fingerprint hashes to ensure that during the build they all get the\n        // most up-to-date values. In theory we only need to bust hashes that\n        // transitively depend on a dirty build script, but it shouldn't matter\n        // that much for performance anyway.\n        for fingerprint in self.fingerprints.values() {\n            fingerprint.clear_memoized();\n        }\n\n        // Now that we've figured out everything that we're going to do, do it!\n        queue.execute(&mut self)?;\n\n        // Add `OUT_DIR` to env vars if unit has a build script.\n        let units_with_build_script = &self\n            .bcx\n            .roots\n            .iter()\n            .filter(|unit| self.build_scripts.contains_key(unit))\n            .dedup_by(|x, y| x.pkg.package_id() == y.pkg.package_id())\n            .collect::<Vec<_>>();\n        for unit in units_with_build_script {\n            for dep in &self.bcx.unit_graph[unit] {\n                if dep.unit.mode.is_run_custom_build() {\n                    let out_dir = if self.bcx.gctx.cli_unstable().build_dir_new_layout {\n                        self.files().out_dir_new_layout(&dep.unit)\n                    } else {\n                        self.files().build_script_out_dir(&dep.unit)\n                    };\n                    let script_meta = self.get_run_build_script_metadata(&dep.unit);\n                    self.compilation\n                        .extra_env\n                        .entry(script_meta)\n                        .or_insert_with(Vec::new)\n                        .push((\"OUT_DIR\".to_string(), out_dir.display().to_string()));\n                }\n            }\n        }\n\n        self.collect_doc_merge_info()?;\n\n        // Collect the result of the build into `self.compilation`.\n        for unit in &self.bcx.roots {\n            self.collect_tests_and_executables(unit)?;\n\n            // Collect information for `rustdoc --test`.\n            if unit.mode.is_doc_test() {\n                let mut unstable_opts = false;\n                let mut args = compiler::extern_args(&self, unit, &mut unstable_opts)?;\n                args.extend(compiler::lib_search_paths(&self, unit)?);\n                args.extend(compiler::lto_args(&self, unit));\n                args.extend(compiler::features_args(unit));\n                args.extend(compiler::check_cfg_args(unit));\n\n                let script_metas = self.find_build_script_metadatas(unit);\n                if let Some(meta_vec) = script_metas.clone() {\n                    for meta in meta_vec {\n                        if let Some(output) = self.build_script_outputs.lock().unwrap().get(meta) {\n                            for cfg in &output.cfgs {\n                                args.push(\"--cfg\".into());\n                                args.push(cfg.into());\n                            }\n\n                            for check_cfg in &output.check_cfgs {\n                                args.push(\"--check-cfg\".into());\n                                args.push(check_cfg.into());\n                            }\n\n                            for (lt, arg) in &output.linker_args {\n                                if lt.applies_to(&unit.target, unit.mode) {\n                                    args.push(\"-C\".into());\n                                    args.push(format!(\"link-arg={}\", arg).into());\n                                }\n                            }\n                        }\n                    }\n                }\n                args.extend(unit.rustdocflags.iter().map(Into::into));\n\n                use super::MessageFormat;\n                let format = match self.bcx.build_config.message_format {\n                    MessageFormat::Short => \"short\",\n                    MessageFormat::Human => \"human\",\n                    MessageFormat::Json { .. } => \"json\",\n                };\n                args.push(\"--error-format\".into());\n                args.push(format.into());\n\n                self.compilation.to_doc_test.push(compilation::Doctest {\n                    unit: unit.clone(),\n                    args,\n                    unstable_opts,\n                    linker: self\n                        .compilation\n                        .target_linker(unit.kind)\n                        .map(|p| p.to_path_buf()),\n                    script_metas,\n                    env: artifact::get_env(&self, unit, self.unit_deps(unit))?,\n                });\n            }\n\n            super::output_depinfo(&mut self, unit)?;\n        }\n\n        for (script_meta, output) in self.build_script_outputs.lock().unwrap().iter() {\n            self.compilation\n                .extra_env\n                .entry(*script_meta)\n                .or_insert_with(Vec::new)\n                .extend(output.env.iter().cloned());\n\n            for dir in output.library_paths.iter() {\n                self.compilation\n                    .native_dirs\n                    .insert(dir.clone().into_path_buf());\n            }\n        }\n        Ok(self.compilation)\n    }\n\n    fn collect_tests_and_executables(&mut self, unit: &Unit) -> CargoResult<()> {\n        for output in self.outputs(unit)?.iter() {\n            if matches!(\n                output.flavor,\n                FileFlavor::DebugInfo | FileFlavor::Auxiliary | FileFlavor::Sbom\n            ) {\n                continue;\n            }\n\n            let bindst = output.bin_dst();\n\n            if unit.mode == CompileMode::Test {\n                self.compilation\n                    .tests\n                    .push(self.unit_output(unit, &output.path)?);\n            } else if unit.target.is_executable() {\n                self.compilation\n                    .binaries\n                    .push(self.unit_output(unit, bindst)?);\n            } else if unit.target.is_cdylib()\n                && !self.compilation.cdylibs.iter().any(|uo| uo.unit == *unit)\n            {\n                self.compilation\n                    .cdylibs\n                    .push(self.unit_output(unit, bindst)?);\n            }\n        }\n        Ok(())\n    }\n\n    fn collect_doc_merge_info(&mut self) -> CargoResult<()> {\n        if !self.bcx.gctx.cli_unstable().rustdoc_mergeable_info {\n            return Ok(());\n        }\n\n        if !self.bcx.build_config.intent.is_doc() {\n            return Ok(());\n        }\n\n        if self.bcx.build_config.intent.wants_doc_json_output() {\n            // rustdoc JSON output doesn't support merge (yet?)\n            return Ok(());\n        }\n\n        let mut doc_parts_map: HashMap<_, Vec<_>> = HashMap::new();\n\n        let unit_iter = if self.bcx.build_config.intent.wants_deps_docs() {\n            itertools::Either::Left(self.bcx.unit_graph.keys())\n        } else {\n            itertools::Either::Right(self.bcx.roots.iter())\n        };\n\n        for unit in unit_iter {\n            if !unit.mode.is_doc() {\n                continue;\n            }\n            // Assumption: one `rustdoc` call generates only one cross-crate info JSON.\n            let outputs = self.outputs(unit)?;\n\n            let Some(doc_parts) = outputs\n                .iter()\n                .find(|o| matches!(o.flavor, FileFlavor::DocParts))\n            else {\n                continue;\n            };\n\n            doc_parts_map\n                .entry(unit.kind)\n                .or_default()\n                .push(doc_parts.path.to_owned());\n        }\n\n        self.compilation.rustdoc_fingerprints = Some(\n            doc_parts_map\n                .into_iter()\n                .map(|(kind, doc_parts)| (kind, RustdocFingerprint::new(self, kind, doc_parts)))\n                .collect(),\n        );\n\n        Ok(())\n    }\n\n    /// Returns the executable for the specified unit (if any).\n    pub fn get_executable(&mut self, unit: &Unit) -> CargoResult<Option<PathBuf>> {\n        let is_binary = unit.target.is_executable();\n        let is_test = unit.mode.is_any_test();\n        if !unit.mode.generates_executable() || !(is_binary || is_test) {\n            return Ok(None);\n        }\n        Ok(self\n            .outputs(unit)?\n            .iter()\n            .find(|o| o.flavor == FileFlavor::Normal)\n            .map(|output| output.bin_dst().clone()))\n    }\n\n    #[tracing::instrument(skip_all)]\n    pub fn prepare_units(&mut self) -> CargoResult<()> {\n        let dest = self.bcx.profiles.get_dir_name();\n        // We try to only lock the artifact-dir if we need to.\n        // For example, `cargo check` does not write any files to the artifact-dir so we don't need\n        // to lock it.\n        let must_take_artifact_dir_lock = match self.bcx.build_config.intent {\n            UserIntent::Check { .. } => {\n                // Generally cargo check does not need to take the artifact-dir lock but there is\n                // one exception: If check has `--timings` we still need to lock artifact-dir since\n                // we will output the report files.\n                self.bcx.build_config.timing_report\n            }\n            UserIntent::Build\n            | UserIntent::Test\n            | UserIntent::Doc { .. }\n            | UserIntent::Doctest\n            | UserIntent::Bench => true,\n        };\n        let host_layout =\n            Layout::new(self.bcx.ws, None, &dest, must_take_artifact_dir_lock, false)?;\n        let mut targets = HashMap::new();\n        for kind in self.bcx.all_kinds.iter() {\n            if let CompileKind::Target(target) = *kind {\n                let layout = Layout::new(\n                    self.bcx.ws,\n                    Some(target),\n                    &dest,\n                    must_take_artifact_dir_lock,\n                    false,\n                )?;\n                targets.insert(target, layout);\n            }\n        }\n        self.primary_packages\n            .extend(self.bcx.roots.iter().map(|u| u.pkg.package_id()));\n        self.compilation\n            .root_crate_names\n            .extend(self.bcx.roots.iter().map(|u| u.target.crate_name()));\n\n        self.record_units_requiring_metadata();\n\n        let files = CompilationFiles::new(self, host_layout, targets);\n        self.files = Some(files);\n        Ok(())\n    }\n\n    /// Prepare this context, ensuring that all filesystem directories are in\n    /// place.\n    #[tracing::instrument(skip_all)]\n    pub fn prepare(&mut self) -> CargoResult<()> {\n        self.files\n            .as_mut()\n            .unwrap()\n            .host\n            .prepare()\n            .context(\"couldn't prepare build directories\")?;\n        for target in self.files.as_mut().unwrap().target.values_mut() {\n            target\n                .prepare()\n                .context(\"couldn't prepare build directories\")?;\n        }\n\n        let files = self.files.as_ref().unwrap();\n        for &kind in self.bcx.all_kinds.iter() {\n            let layout = files.layout(kind);\n            if let Some(artifact_dir) = layout.artifact_dir() {\n                self.compilation\n                    .root_output\n                    .insert(kind, artifact_dir.dest().to_path_buf());\n            }\n            if self.bcx.gctx.cli_unstable().build_dir_new_layout {\n                for (unit, _) in self.bcx.unit_graph.iter() {\n                    let dep_dir = self.files().deps_dir(unit);\n                    paths::create_dir_all(&dep_dir)?;\n                    self.compilation.deps_output.insert(kind, dep_dir);\n                }\n            } else {\n                self.compilation\n                    .deps_output\n                    .insert(kind, layout.build_dir().legacy_deps().to_path_buf());\n            }\n        }\n        Ok(())\n    }\n\n    pub fn files(&self) -> &CompilationFiles<'a, 'gctx> {\n        self.files.as_ref().unwrap()\n    }\n\n    /// Returns the filenames that the given unit will generate.\n    pub fn outputs(&self, unit: &Unit) -> CargoResult<Arc<Vec<OutputFile>>> {\n        self.files.as_ref().unwrap().outputs(unit, self.bcx)\n    }\n\n    /// Direct dependencies for the given unit.\n    pub fn unit_deps(&self, unit: &Unit) -> &[UnitDep] {\n        &self.bcx.unit_graph[unit]\n    }\n\n    /// Returns the `RunCustomBuild` Units associated with the given Unit.\n    ///\n    /// If the package does not have a build script, this returns None.\n    pub fn find_build_script_units(&self, unit: &Unit) -> Option<Vec<Unit>> {\n        if unit.mode.is_run_custom_build() {\n            return Some(vec![unit.clone()]);\n        }\n\n        let build_script_units: Vec<Unit> = self.bcx.unit_graph[unit]\n            .iter()\n            .filter(|unit_dep| {\n                unit_dep.unit.mode.is_run_custom_build()\n                    && unit_dep.unit.pkg.package_id() == unit.pkg.package_id()\n            })\n            .map(|unit_dep| unit_dep.unit.clone())\n            .collect();\n        if build_script_units.is_empty() {\n            None\n        } else {\n            Some(build_script_units)\n        }\n    }\n\n    /// Returns the metadata hash for the `RunCustomBuild` Unit associated with\n    /// the given unit.\n    ///\n    /// If the package does not have a build script, this returns None.\n    pub fn find_build_script_metadatas(&self, unit: &Unit) -> Option<Vec<UnitHash>> {\n        self.find_build_script_units(unit).map(|units| {\n            units\n                .iter()\n                .map(|u| self.get_run_build_script_metadata(u))\n                .collect()\n        })\n    }\n\n    /// Returns the metadata hash for a `RunCustomBuild` unit.\n    pub fn get_run_build_script_metadata(&self, unit: &Unit) -> UnitHash {\n        assert!(unit.mode.is_run_custom_build());\n        self.files().metadata(unit).unit_id()\n    }\n\n    /// Returns the list of SBOM output file paths for a given [`Unit`].\n    pub fn sbom_output_files(&self, unit: &Unit) -> CargoResult<Vec<PathBuf>> {\n        Ok(self\n            .outputs(unit)?\n            .iter()\n            .filter(|o| o.flavor == FileFlavor::Sbom)\n            .map(|o| o.path.clone())\n            .collect())\n    }\n\n    pub fn is_primary_package(&self, unit: &Unit) -> bool {\n        self.primary_packages.contains(&unit.pkg.package_id())\n    }\n\n    /// Returns a [`UnitOutput`] which represents some information about the\n    /// output of a unit.\n    pub fn unit_output(&self, unit: &Unit, path: &Path) -> CargoResult<UnitOutput> {\n        let script_metas = self.find_build_script_metadatas(unit);\n        let env = artifact::get_env(&self, unit, self.unit_deps(unit))?;\n        Ok(UnitOutput {\n            unit: unit.clone(),\n            path: path.to_path_buf(),\n            script_metas,\n            env,\n        })\n    }\n\n    /// Check if any output file name collision happens.\n    /// See <https://github.com/rust-lang/cargo/issues/6313> for more.\n    #[tracing::instrument(skip_all)]\n    fn check_collisions(&self) -> CargoResult<()> {\n        let mut output_collisions = HashMap::new();\n        let describe_collision = |unit: &Unit, other_unit: &Unit| -> String {\n            format!(\n                \"the {} target `{}` in package `{}` has the same output filename as the {} target `{}` in package `{}`\",\n                unit.target.kind().description(),\n                unit.target.name(),\n                unit.pkg.package_id(),\n                other_unit.target.kind().description(),\n                other_unit.target.name(),\n                other_unit.pkg.package_id(),\n            )\n        };\n        let suggestion = [\n            Level::NOTE.message(\"this may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>\"),\n            Level::HELP.message(\"consider changing their names to be unique or compiling them separately\")\n        ];\n        let rustdoc_suggestion = [\n            Level::NOTE.message(\"this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>\")\n        ];\n        let report_collision = |unit: &Unit,\n                                other_unit: &Unit,\n                                path: &PathBuf,\n                                messages: &[Message<'_>]|\n         -> CargoResult<()> {\n            if unit.target.name() == other_unit.target.name() {\n                self.bcx.gctx.shell().print_report(\n                    &[Level::WARNING\n                        .secondary_title(format!(\"output filename collision at {}\", path.display()))\n                        .elements(\n                            [Level::NOTE.message(describe_collision(unit, other_unit))]\n                                .into_iter()\n                                .chain(messages.iter().cloned()),\n                        )],\n                    false,\n                )\n            } else {\n                self.bcx.gctx.shell().print_report(\n                    &[Level::WARNING\n                        .secondary_title(format!(\"output filename collision at {}\", path.display()))\n                        .elements([\n                            Level::NOTE.message(describe_collision(unit, other_unit)),\n                            Level::NOTE.message(\"if this looks unexpected, it may be a bug in Cargo. Please file a bug \\\n                                report at https://github.com/rust-lang/cargo/issues/ with as much information as you \\\n                                can provide.\"),\n                            Level::NOTE.message(format!(\"cargo {} running on `{}` target `{}`\",\n                                crate::version(), self.bcx.host_triple(), self.bcx.target_data.short_name(&unit.kind))),\n                            Level::NOTE.message(format!(\"first unit: {unit:?}\")),\n                            Level::NOTE.message(format!(\"second unit: {other_unit:?}\")),\n                        ])],\n                    false,\n                )\n            }\n        };\n\n        fn doc_collision_error(unit: &Unit, other_unit: &Unit) -> CargoResult<()> {\n            bail!(\n                \"document output filename collision\\n\\\n                 The {} `{}` in package `{}` has the same name as the {} `{}` in package `{}`.\\n\\\n                 Only one may be documented at once since they output to the same path.\\n\\\n                 Consider documenting only one, renaming one, \\\n                 or marking one with `doc = false` in Cargo.toml.\",\n                unit.target.kind().description(),\n                unit.target.name(),\n                unit.pkg,\n                other_unit.target.kind().description(),\n                other_unit.target.name(),\n                other_unit.pkg,\n            );\n        }\n\n        let mut keys = self\n            .bcx\n            .unit_graph\n            .keys()\n            .filter(|unit| !unit.mode.is_run_custom_build())\n            .collect::<Vec<_>>();\n        // Sort for consistent error messages.\n        keys.sort_unstable();\n        // These are kept separate to retain compatibility with older\n        // versions, which generated an error when there was a duplicate lib\n        // or bin (but the old code did not check bin<->lib collisions). To\n        // retain backwards compatibility, this only generates an error for\n        // duplicate libs or duplicate bins (but not both). Ideally this\n        // shouldn't be here, but since there isn't a complete workaround,\n        // yet, this retains the old behavior.\n        let mut doc_libs = HashMap::new();\n        let mut doc_bins = HashMap::new();\n        for unit in keys {\n            if unit.mode.is_doc() && self.is_primary_package(unit) {\n                // These situations have been an error since before 1.0, so it\n                // is not a warning like the other situations.\n                if unit.target.is_lib() {\n                    if let Some(prev) = doc_libs.insert((unit.target.crate_name(), unit.kind), unit)\n                    {\n                        doc_collision_error(unit, prev)?;\n                    }\n                } else if let Some(prev) =\n                    doc_bins.insert((unit.target.crate_name(), unit.kind), unit)\n                {\n                    doc_collision_error(unit, prev)?;\n                }\n            }\n            for output in self.outputs(unit)?.iter() {\n                if let Some(other_unit) = output_collisions.insert(output.path.clone(), unit) {\n                    if unit.mode.is_doc() {\n                        // See https://github.com/rust-lang/rust/issues/56169\n                        // and https://github.com/rust-lang/rust/issues/61378\n                        report_collision(unit, other_unit, &output.path, &rustdoc_suggestion)?;\n                    } else {\n                        report_collision(unit, other_unit, &output.path, &suggestion)?;\n                    }\n                }\n                if let Some(hardlink) = output.hardlink.as_ref() {\n                    if let Some(other_unit) = output_collisions.insert(hardlink.clone(), unit) {\n                        report_collision(unit, other_unit, hardlink, &suggestion)?;\n                    }\n                }\n                if let Some(ref export_path) = output.export_path {\n                    if let Some(other_unit) = output_collisions.insert(export_path.clone(), unit) {\n                        self.bcx.gctx.shell().print_report(\n                            &[Level::WARNING\n                                .secondary_title(format!(\n                                    \"`--artifact-dir` filename collision at {}\",\n                                    export_path.display()\n                                ))\n                                .elements(\n                                    [Level::NOTE.message(describe_collision(unit, other_unit))]\n                                        .into_iter()\n                                        .chain(suggestion.iter().cloned()),\n                                )],\n                            false,\n                        )?;\n                    }\n                }\n            }\n        }\n        Ok(())\n    }\n\n    /// Records the list of units which are required to emit metadata.\n    ///\n    /// Units which depend only on the metadata of others requires the others to\n    /// actually produce metadata, so we'll record that here.\n    fn record_units_requiring_metadata(&mut self) {\n        for (key, deps) in self.bcx.unit_graph.iter() {\n            for dep in deps {\n                if self.only_requires_rmeta(key, &dep.unit) {\n                    self.rmeta_required.insert(dep.unit.clone());\n                }\n            }\n        }\n    }\n\n    /// Returns whether when `parent` depends on `dep` if it only requires the\n    /// metadata file from `dep`.\n    pub fn only_requires_rmeta(&self, parent: &Unit, dep: &Unit) -> bool {\n        // We're only a candidate for requiring an `rmeta` file if we\n        // ourselves are building an rlib,\n        !parent.requires_upstream_objects()\n            && parent.mode == CompileMode::Build\n            // Our dependency must also be built as an rlib, otherwise the\n            // object code must be useful in some fashion\n            && !dep.requires_upstream_objects()\n            && dep.mode == CompileMode::Build\n    }\n\n    /// Returns whether when `unit` is built whether it should emit metadata as\n    /// well because some compilations rely on that.\n    pub fn rmeta_required(&self, unit: &Unit) -> bool {\n        self.rmeta_required.contains(unit)\n    }\n\n    /// Finds metadata for Doc/Docscrape units.\n    ///\n    /// rustdoc needs a -Cmetadata flag in order to recognize StableCrateIds that refer to\n    /// items in the crate being documented. The -Cmetadata flag used by reverse-dependencies\n    /// will be the metadata of the Cargo unit that generated the current library's rmeta file,\n    /// which should be a Check unit.\n    ///\n    /// If the current crate has reverse-dependencies, such a Check unit should exist, and so\n    /// we use that crate's metadata. If not, we use the crate's Doc unit so at least examples\n    /// scraped from the current crate can be used when documenting the current crate.\n    #[tracing::instrument(skip_all)]\n    pub fn compute_metadata_for_doc_units(&mut self) {\n        for unit in self.bcx.unit_graph.keys() {\n            if !unit.mode.is_doc() && !unit.mode.is_doc_scrape() {\n                continue;\n            }\n\n            let matching_units = self\n                .bcx\n                .unit_graph\n                .keys()\n                .filter(|other| {\n                    unit.pkg == other.pkg\n                        && unit.target == other.target\n                        && !other.mode.is_doc_scrape()\n                })\n                .collect::<Vec<_>>();\n            let metadata_unit = matching_units\n                .iter()\n                .find(|other| other.mode.is_check())\n                .or_else(|| matching_units.iter().find(|other| other.mode.is_doc()))\n                .unwrap_or(&unit);\n            self.metadata_for_doc_units\n                .insert(unit.clone(), self.files().metadata(metadata_unit));\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/compilation.rs",
    "content": "//! Type definitions for the result of a compilation.\n\nuse std::collections::{BTreeSet, HashMap};\nuse std::ffi::{OsStr, OsString};\nuse std::path::Path;\nuse std::path::PathBuf;\n\nuse cargo_platform::CfgExpr;\nuse cargo_util::{ProcessBuilder, paths};\n\nuse crate::core::Package;\nuse crate::core::compiler::BuildContext;\nuse crate::core::compiler::CompileTarget;\nuse crate::core::compiler::RustdocFingerprint;\nuse crate::core::compiler::apply_env_config;\nuse crate::core::compiler::{CompileKind, Unit, UnitHash};\nuse crate::util::{CargoResult, GlobalContext};\n\n/// Represents the kind of process we are creating.\n#[derive(Debug)]\nenum ToolKind {\n    /// See [`Compilation::rustc_process`].\n    Rustc,\n    /// See [`Compilation::rustdoc_process`].\n    Rustdoc,\n    /// See [`Compilation::host_process`].\n    HostProcess,\n    /// See [`Compilation::target_process`].\n    TargetProcess,\n}\n\nimpl ToolKind {\n    fn is_rustc_tool(&self) -> bool {\n        matches!(self, ToolKind::Rustc | ToolKind::Rustdoc)\n    }\n}\n\n/// Structure with enough information to run `rustdoc --test`.\npub struct Doctest {\n    /// What's being doctested\n    pub unit: Unit,\n    /// Arguments needed to pass to rustdoc to run this test.\n    pub args: Vec<OsString>,\n    /// Whether or not -Zunstable-options is needed.\n    pub unstable_opts: bool,\n    /// The -Clinker value to use.\n    pub linker: Option<PathBuf>,\n    /// The script metadata, if this unit's package has a build script.\n    ///\n    /// This is used for indexing [`Compilation::extra_env`].\n    pub script_metas: Option<Vec<UnitHash>>,\n\n    /// Environment variables to set in the rustdoc process.\n    pub env: HashMap<String, OsString>,\n}\n\n/// Information about the output of a unit.\npub struct UnitOutput {\n    /// The unit that generated this output.\n    pub unit: Unit,\n    /// Path to the unit's primary output (an executable or cdylib).\n    pub path: PathBuf,\n    /// The script metadata, if this unit's package has a build script.\n    ///\n    /// This is used for indexing [`Compilation::extra_env`].\n    pub script_metas: Option<Vec<UnitHash>>,\n\n    /// Environment variables to set in the unit's process.\n    pub env: HashMap<String, OsString>,\n}\n\n/// A structure returning the result of a compilation.\npub struct Compilation<'gctx> {\n    /// An array of all tests created during this compilation.\n    pub tests: Vec<UnitOutput>,\n\n    /// An array of all binaries created.\n    pub binaries: Vec<UnitOutput>,\n\n    /// An array of all cdylibs created.\n    pub cdylibs: Vec<UnitOutput>,\n\n    /// The crate names of the root units specified on the command-line.\n    pub root_crate_names: Vec<String>,\n\n    /// All directories for the output of native build commands.\n    ///\n    /// This is currently used to drive some entries which are added to the\n    /// `LD_LIBRARY_PATH` as appropriate.\n    ///\n    /// The order should be deterministic.\n    pub native_dirs: BTreeSet<PathBuf>,\n\n    /// Root output directory (for the local package's artifacts)\n    pub root_output: HashMap<CompileKind, PathBuf>,\n\n    /// Output directory for rust dependencies.\n    /// May be for the host or for a specific target.\n    pub deps_output: HashMap<CompileKind, PathBuf>,\n\n    /// The path to libstd for each target\n    sysroot_target_libdir: HashMap<CompileKind, PathBuf>,\n\n    /// Extra environment variables that were passed to compilations and should\n    /// be passed to future invocations of programs.\n    ///\n    /// The key is the build script metadata for uniquely identifying the\n    /// `RunCustomBuild` unit that generated these env vars.\n    pub extra_env: HashMap<UnitHash, Vec<(String, String)>>,\n\n    /// Libraries to test with rustdoc.\n    pub to_doc_test: Vec<Doctest>,\n\n    /// Rustdoc fingerprint files to determine whether we need to run `rustdoc --merge=finalize`.\n    ///\n    /// See `-Zrustdoc-mergeable-info` for more.\n    pub rustdoc_fingerprints: Option<HashMap<CompileKind, RustdocFingerprint>>,\n\n    /// The target host triple.\n    pub host: String,\n\n    gctx: &'gctx GlobalContext,\n\n    /// Rustc process to be used by default\n    rustc_process: ProcessBuilder,\n    /// Rustc process to be used for workspace crates instead of `rustc_process`\n    rustc_workspace_wrapper_process: ProcessBuilder,\n    /// Optional rustc process to be used for primary crates instead of either `rustc_process` or\n    /// `rustc_workspace_wrapper_process`\n    primary_rustc_process: Option<ProcessBuilder>,\n\n    /// The runner to use for each host or target process.\n    runners: HashMap<CompileKind, Option<(PathBuf, Vec<String>)>>,\n    /// The linker to use for each host or target.\n    linkers: HashMap<CompileKind, Option<PathBuf>>,\n\n    /// The total number of lint warnings emitted by the compilation.\n    pub lint_warning_count: usize,\n}\n\nimpl<'gctx> Compilation<'gctx> {\n    pub fn new<'a>(bcx: &BuildContext<'a, 'gctx>) -> CargoResult<Compilation<'gctx>> {\n        let rustc_process = bcx.rustc().process();\n        let primary_rustc_process = bcx.build_config.primary_unit_rustc.clone();\n        let rustc_workspace_wrapper_process = bcx.rustc().workspace_process();\n        let host = bcx.host_triple().to_string();\n\n        // When `target-applies-to-host=false`, and without `--target`,\n        // there will be only `CompileKind::Host` in requested_kinds.\n        // Need to insert target config explicitly for target-applies-to-host=false\n        // to find the correct configs.\n        let insert_explicit_host_runner = !bcx.gctx.target_applies_to_host()?\n            && bcx\n                .build_config\n                .requested_kinds\n                .iter()\n                .any(CompileKind::is_host);\n        let mut runners = bcx\n            .build_config\n            .requested_kinds\n            .iter()\n            .chain(Some(&CompileKind::Host))\n            .map(|kind| Ok((*kind, target_runner(bcx, *kind)?)))\n            .collect::<CargoResult<HashMap<_, _>>>()?;\n        if insert_explicit_host_runner {\n            let kind = explicit_host_kind(&host);\n            runners.insert(kind, target_runner(bcx, kind)?);\n        }\n\n        let mut linkers = bcx\n            .build_config\n            .requested_kinds\n            .iter()\n            .chain(Some(&CompileKind::Host))\n            .map(|kind| Ok((*kind, target_linker(bcx, *kind)?)))\n            .collect::<CargoResult<HashMap<_, _>>>()?;\n        if insert_explicit_host_runner {\n            let kind = explicit_host_kind(&host);\n            linkers.insert(kind, target_linker(bcx, kind)?);\n        }\n        Ok(Compilation {\n            native_dirs: BTreeSet::new(),\n            root_output: HashMap::new(),\n            deps_output: HashMap::new(),\n            sysroot_target_libdir: get_sysroot_target_libdir(bcx)?,\n            tests: Vec::new(),\n            binaries: Vec::new(),\n            cdylibs: Vec::new(),\n            root_crate_names: Vec::new(),\n            extra_env: HashMap::new(),\n            to_doc_test: Vec::new(),\n            rustdoc_fingerprints: None,\n            gctx: bcx.gctx,\n            host,\n            rustc_process,\n            rustc_workspace_wrapper_process,\n            primary_rustc_process,\n            runners,\n            linkers,\n            lint_warning_count: 0,\n        })\n    }\n\n    /// Returns a [`ProcessBuilder`] for running `rustc`.\n    ///\n    /// `is_primary` is true if this is a \"primary package\", which means it\n    /// was selected by the user on the command-line (such as with a `-p`\n    /// flag), see [`crate::core::compiler::BuildRunner::primary_packages`].\n    ///\n    /// `is_workspace` is true if this is a workspace member.\n    pub fn rustc_process(\n        &self,\n        unit: &Unit,\n        is_primary: bool,\n        is_workspace: bool,\n    ) -> CargoResult<ProcessBuilder> {\n        let mut rustc = if is_primary && self.primary_rustc_process.is_some() {\n            self.primary_rustc_process.clone().unwrap()\n        } else if is_workspace {\n            self.rustc_workspace_wrapper_process.clone()\n        } else {\n            self.rustc_process.clone()\n        };\n        if self.gctx.extra_verbose() {\n            rustc.display_env_vars();\n        }\n        let cmd = fill_rustc_tool_env(rustc, unit);\n        self.fill_env(cmd, &unit.pkg, None, unit.kind, ToolKind::Rustc)\n    }\n\n    /// Returns a [`ProcessBuilder`] for running `rustdoc`.\n    pub fn rustdoc_process(\n        &self,\n        unit: &Unit,\n        script_metas: Option<&Vec<UnitHash>>,\n    ) -> CargoResult<ProcessBuilder> {\n        let mut rustdoc = ProcessBuilder::new(&*self.gctx.rustdoc()?);\n        if self.gctx.extra_verbose() {\n            rustdoc.display_env_vars();\n        }\n        let cmd = fill_rustc_tool_env(rustdoc, unit);\n        let mut cmd = self.fill_env(cmd, &unit.pkg, script_metas, unit.kind, ToolKind::Rustdoc)?;\n        cmd.retry_with_argfile(true);\n        unit.target.edition().cmd_edition_arg(&mut cmd);\n\n        for crate_type in unit.target.rustc_crate_types() {\n            cmd.arg(\"--crate-type\").arg(crate_type.as_str());\n        }\n\n        Ok(cmd)\n    }\n\n    /// Returns a [`ProcessBuilder`] appropriate for running a process for the\n    /// host platform.\n    ///\n    /// This is currently only used for running build scripts. If you use this\n    /// for anything else, please be extra careful on how environment\n    /// variables are set!\n    pub fn host_process<T: AsRef<OsStr>>(\n        &self,\n        cmd: T,\n        pkg: &Package,\n    ) -> CargoResult<ProcessBuilder> {\n        // Only use host runner when -Zhost-config is enabled\n        // to ensure `target.<host>.runner` does not wrap build scripts.\n        let builder = if !self.gctx.target_applies_to_host()?\n            && let Some((runner, args)) = self\n                .runners\n                .get(&CompileKind::Host)\n                .and_then(|x| x.as_ref())\n        {\n            let mut builder = ProcessBuilder::new(runner);\n            builder.args(args);\n            builder.arg(cmd);\n            builder\n        } else {\n            ProcessBuilder::new(cmd)\n        };\n        self.fill_env(builder, pkg, None, CompileKind::Host, ToolKind::HostProcess)\n    }\n\n    pub fn target_runner(&self, kind: CompileKind) -> Option<&(PathBuf, Vec<String>)> {\n        let target_applies_to_host = self.gctx.target_applies_to_host().unwrap_or(true);\n        let kind = if !target_applies_to_host && kind.is_host() {\n            // Use explicit host target triple when `target-applies-to-host=false`\n            // This ensures `host.runner` won't be accidentally applied to `cargo run` / `cargo test`.\n            explicit_host_kind(&self.host)\n        } else {\n            kind\n        };\n        self.runners.get(&kind).and_then(|x| x.as_ref())\n    }\n\n    /// Gets the `[host.linker]` for host build target (build scripts and proc macros).\n    pub fn host_linker(&self) -> Option<&Path> {\n        self.linkers\n            .get(&CompileKind::Host)\n            .and_then(|x| x.as_ref())\n            .map(|x| x.as_path())\n    }\n\n    /// Gets the user-specified linker for a particular host or target.\n    pub fn target_linker(&self, kind: CompileKind) -> Option<&Path> {\n        let target_applies_to_host = self.gctx.target_applies_to_host().unwrap_or(true);\n        let kind = if !target_applies_to_host && kind.is_host() {\n            // Use explicit host target triple when `target-applies-to-host=false`\n            // This ensures `host.linker` won't be accidentally applied to normal builds\n            explicit_host_kind(&self.host)\n        } else {\n            kind\n        };\n        self.linkers\n            .get(&kind)\n            .and_then(|x| x.as_ref())\n            .map(|x| x.as_path())\n    }\n\n    /// Returns a [`ProcessBuilder`] appropriate for running a process for the\n    /// target platform. This is typically used for `cargo run` and `cargo\n    /// test`.\n    ///\n    /// `script_metas` is the metadata for the `RunCustomBuild` unit that this\n    /// unit used for its build script. Use `None` if the package did not have\n    /// a build script.\n    pub fn target_process<T: AsRef<OsStr>>(\n        &self,\n        cmd: T,\n        kind: CompileKind,\n        pkg: &Package,\n        script_metas: Option<&Vec<UnitHash>>,\n    ) -> CargoResult<ProcessBuilder> {\n        let builder = if let Some((runner, args)) = self.target_runner(kind) {\n            let mut builder = ProcessBuilder::new(runner);\n            builder.args(args);\n            builder.arg(cmd);\n            builder\n        } else {\n            ProcessBuilder::new(cmd)\n        };\n        let tool_kind = ToolKind::TargetProcess;\n        let mut builder = self.fill_env(builder, pkg, script_metas, kind, tool_kind)?;\n\n        if let Some(client) = self.gctx.jobserver_from_env() {\n            builder.inherit_jobserver(client);\n        }\n\n        Ok(builder)\n    }\n\n    /// Prepares a new process with an appropriate environment to run against\n    /// the artifacts produced by the build process.\n    ///\n    /// The package argument is also used to configure environment variables as\n    /// well as the working directory of the child process.\n    fn fill_env(\n        &self,\n        mut cmd: ProcessBuilder,\n        pkg: &Package,\n        script_metas: Option<&Vec<UnitHash>>,\n        kind: CompileKind,\n        tool_kind: ToolKind,\n    ) -> CargoResult<ProcessBuilder> {\n        let mut search_path = Vec::new();\n        if tool_kind.is_rustc_tool() {\n            if matches!(tool_kind, ToolKind::Rustdoc) {\n                // HACK: `rustdoc --test` not only compiles but executes doctests.\n                // Ideally only execution phase should have search paths appended,\n                // so the executions can find native libs just like other tests.\n                // However, there is no way to separate these two phase, so this\n                // hack is added for both phases.\n                // TODO: handle doctest-xcompile\n                search_path.extend(super::filter_dynamic_search_path(\n                    self.native_dirs.iter(),\n                    &self.root_output[&CompileKind::Host],\n                ));\n            }\n            search_path.push(self.deps_output[&CompileKind::Host].clone());\n        } else {\n            if let Some(path) = self.root_output.get(&kind) {\n                search_path.extend(super::filter_dynamic_search_path(\n                    self.native_dirs.iter(),\n                    path,\n                ));\n                search_path.push(path.clone());\n            }\n            search_path.push(self.deps_output[&kind].clone());\n            // For build-std, we don't want to accidentally pull in any shared\n            // libs from the sysroot that ships with rustc. This may not be\n            // required (at least I cannot craft a situation where it\n            // matters), but is here to be safe.\n            if self.gctx.cli_unstable().build_std.is_none() ||\n                // Proc macros dynamically link to std, so set it anyway.\n                pkg.proc_macro()\n            {\n                search_path.push(self.sysroot_target_libdir[&kind].clone());\n            }\n        }\n\n        let dylib_path = paths::dylib_path();\n        let dylib_path_is_empty = dylib_path.is_empty();\n        if dylib_path.starts_with(&search_path) {\n            search_path = dylib_path;\n        } else {\n            search_path.extend(dylib_path.into_iter());\n        }\n        if cfg!(target_os = \"macos\") && dylib_path_is_empty {\n            // These are the defaults when DYLD_FALLBACK_LIBRARY_PATH isn't\n            // set or set to an empty string. Since Cargo is explicitly setting\n            // the value, make sure the defaults still work.\n            if let Some(home) = self.gctx.get_env_os(\"HOME\") {\n                search_path.push(PathBuf::from(home).join(\"lib\"));\n            }\n            search_path.push(PathBuf::from(\"/usr/local/lib\"));\n            search_path.push(PathBuf::from(\"/usr/lib\"));\n        }\n        let search_path = paths::join_paths(&search_path, paths::dylib_path_envvar())?;\n\n        cmd.env(paths::dylib_path_envvar(), &search_path);\n        if let Some(meta_vec) = script_metas {\n            for meta in meta_vec {\n                if let Some(env) = self.extra_env.get(meta) {\n                    for (k, v) in env {\n                        cmd.env(k, v);\n                    }\n                }\n            }\n        }\n\n        let cargo_exe = self.gctx.cargo_exe()?;\n        cmd.env(crate::CARGO_ENV, cargo_exe);\n\n        // When adding new environment variables depending on\n        // crate properties which might require rebuild upon change\n        // consider adding the corresponding properties to the hash\n        // in BuildContext::target_metadata()\n        cmd.env(\"CARGO_MANIFEST_DIR\", pkg.root())\n            .env(\"CARGO_MANIFEST_PATH\", pkg.manifest_path())\n            .env(\"CARGO_PKG_VERSION_MAJOR\", &pkg.version().major.to_string())\n            .env(\"CARGO_PKG_VERSION_MINOR\", &pkg.version().minor.to_string())\n            .env(\"CARGO_PKG_VERSION_PATCH\", &pkg.version().patch.to_string())\n            .env(\"CARGO_PKG_VERSION_PRE\", pkg.version().pre.as_str())\n            .env(\"CARGO_PKG_VERSION\", &pkg.version().to_string())\n            .env(\"CARGO_PKG_NAME\", &*pkg.name());\n\n        for (key, value) in pkg.manifest().metadata().env_vars() {\n            cmd.env(key, value.as_ref());\n        }\n\n        cmd.cwd(pkg.root());\n\n        apply_env_config(self.gctx, &mut cmd)?;\n\n        Ok(cmd)\n    }\n}\n\n/// Prepares a `rustc_tool` process with additional environment variables\n/// that are only relevant in a context that has a unit\nfn fill_rustc_tool_env(mut cmd: ProcessBuilder, unit: &Unit) -> ProcessBuilder {\n    if unit.target.is_executable() {\n        let name = unit\n            .target\n            .binary_filename()\n            .unwrap_or(unit.target.name().to_string());\n\n        cmd.env(\"CARGO_BIN_NAME\", name);\n    }\n    cmd.env(\"CARGO_CRATE_NAME\", unit.target.crate_name());\n    cmd\n}\n\nfn get_sysroot_target_libdir(\n    bcx: &BuildContext<'_, '_>,\n) -> CargoResult<HashMap<CompileKind, PathBuf>> {\n    bcx.all_kinds\n        .iter()\n        .map(|&kind| {\n            let Some(info) = bcx.target_data.get_info(kind) else {\n                let target = match kind {\n                    CompileKind::Host => \"host\".to_owned(),\n                    CompileKind::Target(s) => s.short_name().to_owned(),\n                };\n\n                let dependency = bcx\n                    .unit_graph\n                    .iter()\n                    .find_map(|(u, _)| (u.kind == kind).then_some(u.pkg.summary().package_id()))\n                    .unwrap();\n\n                anyhow::bail!(\n                    \"could not find specification for target `{target}`.\\n  \\\n                    Dependency `{dependency}` requires to build for target `{target}`.\"\n                )\n            };\n\n            Ok((kind, info.sysroot_target_libdir.clone()))\n        })\n        .collect()\n}\n\nfn target_runner(\n    bcx: &BuildContext<'_, '_>,\n    kind: CompileKind,\n) -> CargoResult<Option<(PathBuf, Vec<String>)>> {\n    if let Some(runner) = bcx.target_data.target_config(kind).runner.as_ref() {\n        let path = runner.val.path.clone().resolve_program(bcx.gctx);\n        return Ok(Some((path, runner.val.args.clone())));\n    }\n\n    // try target.'cfg(...)'.runner\n    let target_cfg = bcx.target_data.info(kind).cfg();\n    let mut cfgs = bcx\n        .gctx\n        .target_cfgs()?\n        .iter()\n        .filter_map(|(key, cfg)| cfg.runner.as_ref().map(|runner| (key, runner)))\n        .filter(|(key, _runner)| CfgExpr::matches_key(key, target_cfg));\n    let matching_runner = cfgs.next();\n    if let Some((key, runner)) = cfgs.next() {\n        anyhow::bail!(\n            \"several matching instances of `target.'cfg(..)'.runner` in configurations\\n\\\n             first match `{}` located in {}\\n\\\n             second match `{}` located in {}\",\n            matching_runner.unwrap().0,\n            matching_runner.unwrap().1.definition,\n            key,\n            runner.definition\n        );\n    }\n    Ok(matching_runner.map(|(_k, runner)| {\n        (\n            runner.val.path.clone().resolve_program(bcx.gctx),\n            runner.val.args.clone(),\n        )\n    }))\n}\n\n/// Gets the user-specified linker for a particular host or target from the configuration.\nfn target_linker(bcx: &BuildContext<'_, '_>, kind: CompileKind) -> CargoResult<Option<PathBuf>> {\n    // Try host.linker and target.{}.linker.\n    if let Some(path) = bcx\n        .target_data\n        .target_config(kind)\n        .linker\n        .as_ref()\n        .map(|l| l.val.clone().resolve_program(bcx.gctx))\n    {\n        return Ok(Some(path));\n    }\n\n    // Try target.'cfg(...)'.linker.\n    let target_cfg = bcx.target_data.info(kind).cfg();\n    let mut cfgs = bcx\n        .gctx\n        .target_cfgs()?\n        .iter()\n        .filter_map(|(key, cfg)| cfg.linker.as_ref().map(|linker| (key, linker)))\n        .filter(|(key, _linker)| CfgExpr::matches_key(key, target_cfg));\n    let matching_linker = cfgs.next();\n    if let Some((key, linker)) = cfgs.next() {\n        anyhow::bail!(\n            \"several matching instances of `target.'cfg(..)'.linker` in configurations\\n\\\n             first match `{}` located in {}\\n\\\n             second match `{}` located in {}\",\n            matching_linker.unwrap().0,\n            matching_linker.unwrap().1.definition,\n            key,\n            linker.definition\n        );\n    }\n    Ok(matching_linker.map(|(_k, linker)| linker.val.clone().resolve_program(bcx.gctx)))\n}\n\nfn explicit_host_kind(host: &str) -> CompileKind {\n    let target = CompileTarget::new(host, false).expect(\"must be a host tuple\");\n    CompileKind::Target(target)\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/compile_kind.rs",
    "content": "//! Type definitions for cross-compilation.\n\nuse crate::core::Target;\nuse crate::util::errors::CargoResult;\nuse crate::util::interning::InternedString;\nuse crate::util::{GlobalContext, StableHasher, try_canonicalize};\nuse anyhow::Context as _;\nuse anyhow::bail;\nuse cargo_util::ProcessBuilder;\nuse serde::Serialize;\nuse std::collections::BTreeSet;\nuse std::fs;\nuse std::hash::{Hash, Hasher};\nuse std::path::Path;\n\n/// Indicator for how a unit is being compiled.\n///\n/// This is used primarily for organizing cross compilations vs host\n/// compilations, where cross compilations happen at the request of `--target`\n/// and host compilations happen for things like build scripts and procedural\n/// macros.\n#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord)]\npub enum CompileKind {\n    /// Attached to a unit that is compiled for the \"host\" system or otherwise\n    /// is compiled without a `--target` flag. This is used for procedural\n    /// macros and build scripts, or if the `--target` flag isn't passed.\n    Host,\n\n    /// Attached to a unit to be compiled for a particular target. This is used\n    /// for units when the `--target` flag is passed.\n    Target(CompileTarget),\n}\n\n/// Fallback behavior in the\n/// [`CompileKind::from_requested_targets_with_fallback`] function when\n/// no targets are specified.\npub enum CompileKindFallback {\n    /// The build configuration is consulted to find the default target, such as\n    /// `$CARGO_BUILD_TARGET` or reading `build.target`.\n    BuildConfig,\n\n    /// Only the host should be returned when targets aren't explicitly\n    /// specified. This is used by `cargo metadata` for example where \"only\n    /// host\" has a special meaning in terms of the returned metadata.\n    JustHost,\n}\n\nimpl CompileKind {\n    pub fn is_host(&self) -> bool {\n        matches!(self, CompileKind::Host)\n    }\n\n    pub fn for_target(self, target: &Target) -> CompileKind {\n        // Once we start compiling for the `Host` kind we continue doing so, but\n        // if we are a `Target` kind and then we start compiling for a target\n        // that needs to be on the host we lift ourselves up to `Host`.\n        match self {\n            CompileKind::Host => CompileKind::Host,\n            CompileKind::Target(_) if target.for_host() => CompileKind::Host,\n            CompileKind::Target(n) => CompileKind::Target(n),\n        }\n    }\n\n    /// Creates a new list of `CompileKind` based on the requested list of\n    /// targets.\n    ///\n    /// If no targets are given then this returns a single-element vector with\n    /// `CompileKind::Host`.\n    pub fn from_requested_targets(\n        gctx: &GlobalContext,\n        targets: &[String],\n    ) -> CargoResult<Vec<CompileKind>> {\n        CompileKind::from_requested_targets_with_fallback(\n            gctx,\n            targets,\n            CompileKindFallback::BuildConfig,\n        )\n    }\n\n    /// Same as [`CompileKind::from_requested_targets`] except that if `targets`\n    /// doesn't explicitly mention anything the behavior of what to return is\n    /// controlled by the `fallback` argument.\n    pub fn from_requested_targets_with_fallback(\n        gctx: &GlobalContext,\n        targets: &[String],\n        fallback: CompileKindFallback,\n    ) -> CargoResult<Vec<CompileKind>> {\n        let dedup = |targets: &[String]| {\n            let deduplicated_targets = targets\n                .iter()\n                .map(|value| {\n                    // This neatly substitutes the manually-specified `host-tuple` target directive\n                    // with the compiling machine's target triple.\n\n                    if value.as_str() == \"host-tuple\" {\n                        let host_triple = env!(\"RUST_HOST_TARGET\");\n                        Ok(CompileKind::Target(CompileTarget::new(\n                            host_triple,\n                            gctx.cli_unstable().json_target_spec,\n                        )?))\n                    } else {\n                        Ok(CompileKind::Target(CompileTarget::new(\n                            value.as_str(),\n                            gctx.cli_unstable().json_target_spec,\n                        )?))\n                    }\n                })\n                // First collect into a set to deduplicate any `--target` passed\n                // more than once...\n                .collect::<CargoResult<BTreeSet<_>>>()?\n                // ... then generate a flat list for everything else to use.\n                .into_iter()\n                .collect();\n\n            Ok(deduplicated_targets)\n        };\n\n        if !targets.is_empty() {\n            return dedup(targets);\n        }\n\n        let kinds = match (fallback, &gctx.build_config()?.target) {\n            (_, None) | (CompileKindFallback::JustHost, _) => Ok(vec![CompileKind::Host]),\n            (CompileKindFallback::BuildConfig, Some(build_target_config)) => {\n                dedup(&build_target_config.values(gctx.cwd())?)\n            }\n        };\n\n        kinds\n    }\n\n    /// Hash used for fingerprinting.\n    ///\n    /// Metadata hashing uses the normal Hash trait, which does not\n    /// differentiate on `.json` file contents. The fingerprint hash does\n    /// check the contents.\n    pub fn fingerprint_hash(&self) -> u64 {\n        match self {\n            CompileKind::Host => 0,\n            CompileKind::Target(target) => target.fingerprint_hash(),\n        }\n    }\n\n    /// Adds the `--target` flag to the given [`ProcessBuilder`] if this is a\n    /// non-host build.\n    pub fn add_target_arg(&self, builder: &mut ProcessBuilder) {\n        if let CompileKind::Target(target) = self {\n            builder.arg(\"--target\").arg(target.rustc_target());\n            if matches!(target, CompileTarget::Json { .. }) {\n                builder.arg(\"-Zunstable-options\");\n            }\n        }\n    }\n}\n\nimpl serde::ser::Serialize for CompileKind {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: serde::ser::Serializer,\n    {\n        match self {\n            CompileKind::Host => None::<&str>.serialize(s),\n            CompileKind::Target(t) => Some(t.rustc_target()).serialize(s),\n        }\n    }\n}\n\n/// Abstraction for the representation of a compilation target that Cargo has.\n///\n/// Compilation targets are one of two things right now:\n///\n/// 1. A raw target string, like `x86_64-unknown-linux-gnu`.\n/// 2. The path to a JSON file, such as `/path/to/my-target.json`.\n///\n/// Raw target strings are typically dictated by `rustc` itself and represent\n/// built-in targets. Custom JSON files are somewhat unstable, but supported\n/// here in Cargo. Note that for JSON target files this `CompileTarget` stores a\n/// full canonicalized path to the target.\n///\n/// The main reason for this existence is to handle JSON target files where when\n/// we call rustc we pass full paths but when we use it for Cargo's purposes\n/// like naming directories or looking up configuration keys we only check the\n/// file stem of JSON target files. For built-in rustc targets this is just an\n/// uninterpreted string basically.\n#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord, Serialize)]\npub enum CompileTarget {\n    Tuple(InternedString),\n    Json {\n        short: InternedString,\n        path: InternedString,\n    },\n}\n\nimpl CompileTarget {\n    pub fn new(name: &str, unstable_json: bool) -> CargoResult<CompileTarget> {\n        let name = name.trim();\n        if name.is_empty() {\n            bail!(\"target was empty\");\n        }\n        if !name.ends_with(\".json\") {\n            return Ok(CompileTarget::Tuple(name.into()));\n        }\n\n        if !unstable_json {\n            bail!(\"`.json` target specs require -Zjson-target-spec\");\n        }\n\n        // If `name` ends in `.json` then it's likely a custom target\n        // specification. Canonicalize the path to ensure that different builds\n        // with different paths always produce the same result.\n        let p = try_canonicalize(Path::new(name))\n            .with_context(|| format!(\"target path `{name}` is not a valid file\"))?;\n        let path = p\n            .to_str()\n            .ok_or_else(|| anyhow::format_err!(\"target path `{name}` is not valid unicode\"))?\n            .into();\n        let short = p.file_stem().unwrap().to_str().unwrap().into();\n        Ok(CompileTarget::Json { short, path })\n    }\n\n    /// Returns the full unqualified name of this target, suitable for passing\n    /// to `rustc` directly.\n    ///\n    /// Typically this is pretty much the same as `short_name`, but for the case\n    /// of JSON target files this will be a full canonicalized path name for the\n    /// current filesystem.\n    pub fn rustc_target(&self) -> InternedString {\n        match self {\n            CompileTarget::Tuple(name) => *name,\n            CompileTarget::Json { path, .. } => *path,\n        }\n    }\n\n    /// Returns a \"short\" version of the target name suitable for usage within\n    /// Cargo for configuration and such.\n    ///\n    /// This is typically the same as `rustc_target`, or the full name, but for\n    /// JSON target files this returns just the file stem (e.g. `foo` out of\n    /// `foo.json`) instead of the full path.\n    pub fn short_name(&self) -> &str {\n        match self {\n            CompileTarget::Tuple(name) => name,\n            CompileTarget::Json { short, .. } => short,\n        }\n    }\n\n    /// See [`CompileKind::fingerprint_hash`].\n    pub fn fingerprint_hash(&self) -> u64 {\n        let mut hasher = StableHasher::new();\n        match self {\n            CompileTarget::Tuple(name) => name.hash(&mut hasher),\n            CompileTarget::Json { path, .. } => {\n                // This may have some performance concerns, since it is called\n                // fairly often. If that ever seems worth fixing, consider\n                // embedding this in `CompileTarget`.\n                match fs::read_to_string(path) {\n                    Ok(contents) => contents.hash(&mut hasher),\n                    Err(_) => path.hash(&mut hasher),\n                }\n            }\n        }\n        Hasher::finish(&hasher)\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/crate_type.rs",
    "content": "use std::fmt;\n\n/// Types of the output artifact that the compiler emits.\n/// Usually distributable or linkable either statically or dynamically.\n///\n/// See <https://doc.rust-lang.org/nightly/reference/linkage.html>.\n#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]\npub enum CrateType {\n    Bin,\n    Lib,\n    Rlib,\n    Dylib,\n    Cdylib,\n    Staticlib,\n    ProcMacro,\n    Other(String),\n}\n\nimpl CrateType {\n    pub fn as_str(&self) -> &str {\n        match self {\n            CrateType::Bin => \"bin\",\n            CrateType::Lib => \"lib\",\n            CrateType::Rlib => \"rlib\",\n            CrateType::Dylib => \"dylib\",\n            CrateType::Cdylib => \"cdylib\",\n            CrateType::Staticlib => \"staticlib\",\n            CrateType::ProcMacro => \"proc-macro\",\n            CrateType::Other(s) => s,\n        }\n    }\n\n    pub fn can_lto(&self) -> bool {\n        match self {\n            CrateType::Bin | CrateType::Staticlib | CrateType::Cdylib => true,\n            CrateType::Lib\n            | CrateType::Rlib\n            | CrateType::Dylib\n            | CrateType::ProcMacro\n            | CrateType::Other(..) => false,\n        }\n    }\n\n    pub fn is_linkable(&self) -> bool {\n        match self {\n            CrateType::Lib | CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true,\n            CrateType::Bin | CrateType::Cdylib | CrateType::Staticlib | CrateType::Other(..) => {\n                false\n            }\n        }\n    }\n\n    pub fn is_dynamic(&self) -> bool {\n        match self {\n            CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => true,\n            CrateType::Lib\n            | CrateType::Rlib\n            | CrateType::Bin\n            | CrateType::Staticlib\n            | CrateType::Other(..) => false,\n        }\n    }\n\n    /// Returns whether production of this crate type requires the object files\n    /// from dependencies to be available.\n    ///\n    /// See also [`TargetKind::requires_upstream_objects`].\n    ///\n    /// [`TargetKind::requires_upstream_objects`]: crate::core::manifest::TargetKind::requires_upstream_objects\n    pub fn requires_upstream_objects(&self) -> bool {\n        // \"lib\" == \"rlib\" and is a compilation that doesn't actually\n        // require upstream object files to exist, only upstream metadata\n        // files. As a result, it doesn't require upstream artifacts\n\n        !matches!(self, CrateType::Lib | CrateType::Rlib)\n        // Everything else, however, is some form of \"linkable output\" or\n        // something that requires upstream object files.\n    }\n\n    /// Returns whether production of this crate type could benefit from splitting metadata\n    /// into a .rmeta file.\n    ///\n    /// See also [`TargetKind::benefits_from_no_embed_metadata`].\n    ///\n    /// [`TargetKind::benefits_from_no_embed_metadata`]: crate::core::manifest::TargetKind::benefits_from_no_embed_metadata\n    pub fn benefits_from_no_embed_metadata(&self) -> bool {\n        match self {\n            // rlib/libs generate .rmeta files for pipelined compilation.\n            // If we also include metadata inside of them, we waste disk space, since the metadata\n            // will be located both in the lib/rlib and the .rmeta file.\n            CrateType::Lib |\n            CrateType::Rlib |\n            // Dylibs do not have to contain metadata when they are used as a runtime dependency.\n            // If we split the metadata into a separate .rmeta file, the dylib file (that\n            // can be shipped as a runtime dependency) can be smaller.\n            CrateType::Dylib => true,\n            // Proc macros contain metadata that specifies what macro functions are available in\n            // it, but the metadata is typically very small. The metadata of proc macros is also\n            // self-contained (unlike rlibs/dylibs), so let's not unnecessarily split it into\n            // multiple files.\n            CrateType::ProcMacro |\n            // cdylib and staticlib produce artifacts that are used through the C ABI and do not\n            // contain Rust-specific metadata.\n            CrateType::Cdylib |\n            CrateType::Staticlib |\n            // Binaries also do not contain metadata\n            CrateType::Bin |\n            CrateType::Other(_) => false\n        }\n    }\n}\n\nimpl fmt::Display for CrateType {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.as_str().fmt(f)\n    }\n}\n\nimpl<'a> From<&'a String> for CrateType {\n    fn from(s: &'a String) -> Self {\n        match s.as_str() {\n            \"bin\" => CrateType::Bin,\n            \"lib\" => CrateType::Lib,\n            \"rlib\" => CrateType::Rlib,\n            \"dylib\" => CrateType::Dylib,\n            \"cdylib\" => CrateType::Cdylib,\n            \"staticlib\" => CrateType::Staticlib,\n            \"procmacro\" => CrateType::ProcMacro,\n            _ => CrateType::Other(s.clone()),\n        }\n    }\n}\n\nimpl fmt::Debug for CrateType {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.to_string().fmt(f)\n    }\n}\n\nimpl serde::Serialize for CrateType {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: serde::ser::Serializer,\n    {\n        self.to_string().serialize(s)\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/custom_build.rs",
    "content": "//! How to execute a build script and parse its output.\n//!\n//! ## Preparing a build script run\n//!\n//! A [build script] is an optional Rust script Cargo will run before building\n//! your package. As of this writing, two kinds of special [`Unit`]s will be\n//! constructed when there is a build script in a package.\n//!\n//! * Build script compilation --- This unit is generally the same as units\n//!   that would compile other Cargo targets. It will recursively creates units\n//!   of its dependencies. One biggest difference is that the [`Unit`] of\n//!   compiling a build script is flagged as [`TargetKind::CustomBuild`].\n//! * Build script execution --- During the construction of the [`UnitGraph`],\n//!   Cargo inserts a [`Unit`] with [`CompileMode::RunCustomBuild`]. This unit\n//!   depends on the unit of compiling the associated build script, to ensure\n//!   the executable is available before running. The [`Work`] of running the\n//!   build script is prepared in the function [`prepare`].\n//!\n//! ## Running a build script\n//!\n//! When running a build script, Cargo is aware of the progress and the result\n//! of a build script. Standard output is the chosen interprocess communication\n//! between Cargo and build script processes. A set of strings is defined for\n//! that purpose. These strings, a.k.a. instructions, are interpreted by\n//! [`BuildOutput::parse`] and stored in [`BuildRunner::build_script_outputs`].\n//! The entire execution work is constructed by [`build_work`].\n//!\n//! [build script]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html\n//! [`TargetKind::CustomBuild`]: crate::core::manifest::TargetKind::CustomBuild\n//! [`UnitGraph`]: super::unit_graph::UnitGraph\n//! [`CompileMode::RunCustomBuild`]: crate::core::compiler::CompileMode::RunCustomBuild\n//! [instructions]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script\n\nuse super::{BuildRunner, Job, Unit, Work, fingerprint, get_dynamic_search_path};\nuse crate::core::compiler::CompileMode;\nuse crate::core::compiler::artifact;\nuse crate::core::compiler::build_runner::UnitHash;\nuse crate::core::compiler::job_queue::JobState;\nuse crate::core::{PackageId, Target, profiles::ProfileRoot};\nuse crate::util::errors::CargoResult;\nuse crate::util::internal;\nuse crate::util::machine_message::{self, Message};\nuse anyhow::{Context as _, bail};\nuse cargo_platform::Cfg;\nuse cargo_util::paths;\nuse cargo_util_schemas::manifest::RustVersion;\nuse std::collections::hash_map::{Entry, HashMap};\nuse std::collections::{BTreeSet, HashSet};\nuse std::path::{Path, PathBuf};\nuse std::str;\nuse std::sync::{Arc, Mutex};\n\n/// A build script instruction that tells Cargo to display an error after the\n/// build script has finished running. Read [the doc] for more.\n///\n/// [the doc]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargo-error\nconst CARGO_ERROR_SYNTAX: &str = \"cargo::error=\";\n/// Deprecated: A build script instruction that tells Cargo to display a warning after the\n/// build script has finished running. Read [the doc] for more.\n///\n/// [the doc]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargo-warning\nconst OLD_CARGO_WARNING_SYNTAX: &str = \"cargo:warning=\";\n/// A build script instruction that tells Cargo to display a warning after the\n/// build script has finished running. Read [the doc] for more.\n///\n/// [the doc]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargo-warning\nconst NEW_CARGO_WARNING_SYNTAX: &str = \"cargo::warning=\";\n\n#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]\npub enum Severity {\n    Error,\n    Warning,\n}\n\npub type LogMessage = (Severity, String);\n\n/// Represents a path added to the library search path.\n///\n/// We need to keep track of requests to add search paths within the cargo build directory\n/// separately from paths outside of Cargo. The reason is that we want to give precedence to linking\n/// against libraries within the Cargo build directory even if a similar library exists in the\n/// system (e.g. crate A adds `/usr/lib` to the search path and then a later build of crate B adds\n/// `target/debug/...` to satisfy its request to link against the library B that it built, but B is\n/// also found in `/usr/lib`).\n///\n/// There's some nuance here because we want to preserve relative order of paths of the same type.\n/// For example, if the build process would in declaration order emit the following linker line:\n/// ```bash\n/// -L/usr/lib -Ltarget/debug/build/crate1/libs -L/lib -Ltarget/debug/build/crate2/libs)\n/// ```\n///\n/// we want the linker to actually receive:\n/// ```bash\n/// -Ltarget/debug/build/crate1/libs -Ltarget/debug/build/crate2/libs) -L/usr/lib -L/lib\n/// ```\n///\n/// so that the library search paths within the crate artifacts directory come first but retain\n/// relative ordering while the system library paths come after while still retaining relative\n/// ordering among them; ordering is the order they are emitted within the build process,\n/// not lexicographic order.\n///\n/// WARNING: Even though this type implements PartialOrd + Ord, this is a lexicographic ordering.\n/// The linker line will require an explicit sorting algorithm. PartialOrd + Ord is derived because\n/// BuildOutput requires it but that ordering is different from the one for the linker search path,\n/// at least today. It may be worth reconsidering & perhaps it's ok if BuildOutput doesn't have\n/// a lexicographic ordering for the library_paths? I'm not sure the consequence of that.\n#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]\npub enum LibraryPath {\n    /// The path is pointing within the output folder of the crate and takes priority over\n    /// external paths when passed to the linker.\n    CargoArtifact(PathBuf),\n    /// The path is pointing outside of the crate's build location. The linker will always\n    /// receive such paths after `CargoArtifact`.\n    External(PathBuf),\n}\n\nimpl LibraryPath {\n    fn new(p: PathBuf, script_out_dir: &Path) -> Self {\n        let search_path = get_dynamic_search_path(&p);\n        if search_path.starts_with(script_out_dir) {\n            Self::CargoArtifact(p)\n        } else {\n            Self::External(p)\n        }\n    }\n\n    pub fn into_path_buf(self) -> PathBuf {\n        match self {\n            LibraryPath::CargoArtifact(p) | LibraryPath::External(p) => p,\n        }\n    }\n}\n\nimpl AsRef<PathBuf> for LibraryPath {\n    fn as_ref(&self) -> &PathBuf {\n        match self {\n            LibraryPath::CargoArtifact(p) | LibraryPath::External(p) => p,\n        }\n    }\n}\n\n/// Contains the parsed output of a custom build script.\n#[derive(Clone, Debug, Hash, Default, PartialEq, Eq, PartialOrd, Ord)]\npub struct BuildOutput {\n    /// Paths to pass to rustc with the `-L` flag.\n    pub library_paths: Vec<LibraryPath>,\n    /// Names and link kinds of libraries, suitable for the `-l` flag.\n    pub library_links: Vec<String>,\n    /// Linker arguments suitable to be passed to `-C link-arg=<args>`\n    pub linker_args: Vec<(LinkArgTarget, String)>,\n    /// Various `--cfg` flags to pass to the compiler.\n    pub cfgs: Vec<String>,\n    /// Various `--check-cfg` flags to pass to the compiler.\n    pub check_cfgs: Vec<String>,\n    /// Additional environment variables to run the compiler with.\n    pub env: Vec<(String, String)>,\n    /// Metadata to pass to the immediate dependencies.\n    pub metadata: Vec<(String, String)>,\n    /// Paths to trigger a rerun of this build script.\n    /// May be absolute or relative paths (relative to package root).\n    pub rerun_if_changed: Vec<PathBuf>,\n    /// Environment variables which, when changed, will cause a rebuild.\n    pub rerun_if_env_changed: Vec<String>,\n    /// Errors and warnings generated by this build.\n    ///\n    /// These are only displayed if this is a \"local\" package, `-vv` is used, or\n    /// there is a build error for any target in this package. Note that any log\n    /// message of severity `Error` will by itself cause a build error, and will\n    /// cause all log messages to be displayed.\n    pub log_messages: Vec<LogMessage>,\n}\n\n/// Map of packages to build script output.\n///\n/// This initially starts out as empty. Overridden build scripts get\n/// inserted during `build_map`. The rest of the entries are added\n/// immediately after each build script runs.\n///\n/// The [`UnitHash`] is the unique metadata hash for the `RunCustomBuild` Unit of\n/// the package. It needs a unique key, since the build script can be run\n/// multiple times with different profiles or features. We can't embed a\n/// `Unit` because this structure needs to be shareable between threads.\n#[derive(Default)]\npub struct BuildScriptOutputs {\n    outputs: HashMap<UnitHash, BuildOutput>,\n}\n\n/// Linking information for a `Unit`.\n///\n/// See [`build_map`] for more details.\n#[derive(Default)]\npub struct BuildScripts {\n    /// List of build script outputs this Unit needs to include for linking. Each\n    /// element is an index into `BuildScriptOutputs`.\n    ///\n    /// Cargo will use this `to_link` vector to add `-L` flags to compiles as we\n    /// propagate them upwards towards the final build. Note, however, that we\n    /// need to preserve the ordering of `to_link` to be topologically sorted.\n    /// This will ensure that build scripts which print their paths properly will\n    /// correctly pick up the files they generated (if there are duplicates\n    /// elsewhere).\n    ///\n    /// To preserve this ordering, the (id, metadata) is stored in two places, once\n    /// in the `Vec` and once in `seen_to_link` for a fast lookup. We maintain\n    /// this as we're building interactively below to ensure that the memory\n    /// usage here doesn't blow up too much.\n    ///\n    /// For more information, see #2354.\n    pub to_link: Vec<(PackageId, UnitHash)>,\n    /// This is only used while constructing `to_link` to avoid duplicates.\n    seen_to_link: HashSet<(PackageId, UnitHash)>,\n    /// Host-only dependencies that have build scripts. Each element is an\n    /// index into `BuildScriptOutputs`.\n    ///\n    /// This is the set of transitive dependencies that are host-only\n    /// (proc-macro, plugin, build-dependency) that contain a build script.\n    /// Any `BuildOutput::library_paths` path relative to `target` will be\n    /// added to `LD_LIBRARY_PATH` so that the compiler can find any dynamic\n    /// libraries a build script may have generated.\n    pub plugins: BTreeSet<(PackageId, UnitHash)>,\n}\n\n/// Dependency information as declared by a build script that might trigger\n/// a recompile of itself.\n#[derive(Debug)]\npub struct BuildDeps {\n    /// Absolute path to the file in the target directory that stores the\n    /// output of the build script.\n    pub build_script_output: PathBuf,\n    /// Files that trigger a rebuild if they change.\n    pub rerun_if_changed: Vec<PathBuf>,\n    /// Environment variables that trigger a rebuild if they change.\n    pub rerun_if_env_changed: Vec<String>,\n}\n\n/// Represents one of the instructions from `cargo::rustc-link-arg-*` build\n/// script instruction family.\n///\n/// In other words, indicates targets that custom linker arguments applies to.\n///\n/// See the [build script documentation][1] for more.\n///\n/// [1]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargorustc-link-argflag\n#[derive(Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord)]\npub enum LinkArgTarget {\n    /// Represents `cargo::rustc-link-arg=FLAG`.\n    All,\n    /// Represents `cargo::rustc-cdylib-link-arg=FLAG`.\n    Cdylib,\n    /// Represents `cargo::rustc-link-arg-bins=FLAG`.\n    Bin,\n    /// Represents `cargo::rustc-link-arg-bin=BIN=FLAG`.\n    SingleBin(String),\n    /// Represents `cargo::rustc-link-arg-tests=FLAG`.\n    Test,\n    /// Represents `cargo::rustc-link-arg-benches=FLAG`.\n    Bench,\n    /// Represents `cargo::rustc-link-arg-examples=FLAG`.\n    Example,\n}\n\nimpl LinkArgTarget {\n    /// Checks if this link type applies to a given [`Target`].\n    pub fn applies_to(&self, target: &Target, mode: CompileMode) -> bool {\n        let is_test = mode.is_any_test();\n        match self {\n            LinkArgTarget::All => true,\n            LinkArgTarget::Cdylib => !is_test && target.is_cdylib(),\n            LinkArgTarget::Bin => target.is_bin(),\n            LinkArgTarget::SingleBin(name) => target.is_bin() && target.name() == name,\n            LinkArgTarget::Test => target.is_test(),\n            LinkArgTarget::Bench => target.is_bench(),\n            LinkArgTarget::Example => target.is_exe_example(),\n        }\n    }\n}\n\n/// Prepares a `Work` that executes the target as a custom build script.\n#[tracing::instrument(skip_all)]\npub fn prepare(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<Job> {\n    let metadata = build_runner.get_run_build_script_metadata(unit);\n    if build_runner\n        .build_script_outputs\n        .lock()\n        .unwrap()\n        .contains_key(metadata)\n    {\n        // The output is already set, thus the build script is overridden.\n        fingerprint::prepare_target(build_runner, unit, false)\n    } else {\n        build_work(build_runner, unit)\n    }\n}\n\n/// Emits the output of a build script as a [`machine_message::BuildScript`]\n/// JSON string to standard output.\nfn emit_build_output(\n    state: &JobState<'_, '_>,\n    output: &BuildOutput,\n    out_dir: &Path,\n    package_id: PackageId,\n) -> CargoResult<()> {\n    let library_paths = output\n        .library_paths\n        .iter()\n        .map(|l| l.as_ref().display().to_string())\n        .collect::<Vec<_>>();\n\n    let msg = machine_message::BuildScript {\n        package_id: package_id.to_spec(),\n        linked_libs: &output.library_links,\n        linked_paths: &library_paths,\n        cfgs: &output.cfgs,\n        env: &output.env,\n        out_dir,\n    }\n    .to_json_string();\n    state.stdout(msg)?;\n    Ok(())\n}\n\n/// Constructs the unit of work of running a build script.\n///\n/// The construction includes:\n///\n/// * Set environment variables for the build script run.\n/// * Create the output dir (`OUT_DIR`) for the build script output.\n/// * Determine if the build script needs a re-run.\n/// * Run the build script and store its output.\nfn build_work(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<Job> {\n    assert!(unit.mode.is_run_custom_build());\n    let bcx = &build_runner.bcx;\n    let dependencies = build_runner.unit_deps(unit);\n    let build_script_unit = dependencies\n        .iter()\n        .find(|d| !d.unit.mode.is_run_custom_build() && d.unit.target.is_custom_build())\n        .map(|d| &d.unit)\n        .expect(\"running a script not depending on an actual script\");\n    let script_dir = build_runner.files().build_script_dir(build_script_unit);\n\n    let script_out_dir = if bcx.gctx.cli_unstable().build_dir_new_layout {\n        build_runner.files().out_dir_new_layout(unit)\n    } else {\n        build_runner.files().build_script_out_dir(unit)\n    };\n\n    if let Some(deps) = unit.pkg.manifest().metabuild() {\n        prepare_metabuild(build_runner, build_script_unit, deps)?;\n    }\n\n    // Building the command to execute\n    let to_exec = script_dir.join(unit.target.name());\n\n    // Start preparing the process to execute, starting out with some\n    // environment variables. Note that the profile-related environment\n    // variables are not set with this the build script's profile but rather the\n    // package's library profile.\n    // NOTE: if you add any profile flags, be sure to update\n    // `Profiles::get_profile_run_custom_build` so that those flags get\n    // carried over.\n    let to_exec = to_exec.into_os_string();\n    let mut cmd = build_runner.compilation.host_process(to_exec, &unit.pkg)?;\n    let debug = unit.profile.debuginfo.is_turned_on();\n    cmd.env(\"OUT_DIR\", &script_out_dir)\n        .env(\"CARGO_MANIFEST_DIR\", unit.pkg.root())\n        .env(\"CARGO_MANIFEST_PATH\", unit.pkg.manifest_path())\n        .env(\"NUM_JOBS\", &bcx.jobs().to_string())\n        .env(\"TARGET\", bcx.target_data.short_name(&unit.kind))\n        .env(\"DEBUG\", debug.to_string())\n        .env(\"OPT_LEVEL\", &unit.profile.opt_level)\n        .env(\n            \"PROFILE\",\n            match unit.profile.root {\n                ProfileRoot::Release => \"release\",\n                ProfileRoot::Debug => \"debug\",\n            },\n        )\n        .env(\"HOST\", &bcx.host_triple())\n        .env(\"RUSTC\", &bcx.rustc().path)\n        .env(\"RUSTDOC\", &*bcx.gctx.rustdoc()?)\n        .inherit_jobserver(&build_runner.jobserver);\n\n    // Find all artifact dependencies and make their file and containing directory discoverable using environment variables.\n    for (var, value) in artifact::get_env(build_runner, unit, dependencies)? {\n        cmd.env(&var, value);\n    }\n\n    if let Some(linker) = &build_runner.compilation.target_linker(unit.kind) {\n        cmd.env(\"RUSTC_LINKER\", linker);\n    }\n\n    if let Some(links) = unit.pkg.manifest().links() {\n        cmd.env(\"CARGO_MANIFEST_LINKS\", links);\n    }\n\n    if let Some(trim_paths) = unit.profile.trim_paths.as_ref() {\n        cmd.env(\"CARGO_TRIM_PATHS\", trim_paths.to_string());\n    }\n\n    // Be sure to pass along all enabled features for this package, this is the\n    // last piece of statically known information that we have.\n    for feat in &unit.features {\n        cmd.env(&format!(\"CARGO_FEATURE_{}\", super::envify(feat)), \"1\");\n    }\n\n    let mut cfg_map = HashMap::new();\n    cfg_map.insert(\n        \"feature\",\n        unit.features.iter().map(|s| s.as_str()).collect::<Vec<_>>(),\n    );\n    // Manually inject debug_assertions based on the profile setting.\n    // The cfg query from rustc doesn't include profile settings and would always be true,\n    // so we override it with the actual profile setting.\n    if unit.profile.debug_assertions {\n        cfg_map.insert(\"debug_assertions\", Vec::new());\n    }\n    for cfg in bcx.target_data.cfg(unit.kind) {\n        match *cfg {\n            Cfg::Name(ref n) => {\n                // Skip debug_assertions from rustc query; we use the profile setting instead\n                if n.as_str() == \"debug_assertions\" {\n                    continue;\n                }\n                cfg_map.insert(n.as_str(), Vec::new());\n            }\n            Cfg::KeyPair(ref k, ref v) => {\n                let values = cfg_map.entry(k.as_str()).or_default();\n                values.push(v.as_str());\n            }\n        }\n    }\n    for (k, v) in cfg_map {\n        // FIXME: We should handle raw-idents somehow instead of pretending they\n        // don't exist here\n        let k = format!(\"CARGO_CFG_{}\", super::envify(k));\n        cmd.env(&k, v.join(\",\"));\n    }\n\n    // Also inform the build script of the rustc compiler context.\n    if let Some(wrapper) = bcx.rustc().wrapper.as_ref() {\n        cmd.env(\"RUSTC_WRAPPER\", wrapper);\n    } else {\n        cmd.env_remove(\"RUSTC_WRAPPER\");\n    }\n    cmd.env_remove(\"RUSTC_WORKSPACE_WRAPPER\");\n    if build_runner.bcx.ws.is_member(&unit.pkg) {\n        if let Some(wrapper) = bcx.rustc().workspace_wrapper.as_ref() {\n            cmd.env(\"RUSTC_WORKSPACE_WRAPPER\", wrapper);\n        }\n    }\n    cmd.env(\"CARGO_ENCODED_RUSTFLAGS\", unit.rustflags.join(\"\\x1f\"));\n    cmd.env_remove(\"RUSTFLAGS\");\n\n    if build_runner.bcx.ws.gctx().extra_verbose() {\n        cmd.display_env_vars();\n    }\n\n    let any_build_script_metadata = bcx.gctx.cli_unstable().any_build_script_metadata;\n\n    // Gather the set of native dependencies that this package has along with\n    // some other variables to close over.\n    //\n    // This information will be used at build-time later on to figure out which\n    // sorts of variables need to be discovered at that time.\n    let lib_deps = dependencies\n        .iter()\n        .filter_map(|dep| {\n            if dep.unit.mode.is_run_custom_build() {\n                let dep_metadata = build_runner.get_run_build_script_metadata(&dep.unit);\n\n                let dep_name = dep.dep_name.unwrap_or(dep.unit.pkg.name());\n\n                Some((\n                    dep_name,\n                    dep.unit\n                        .pkg\n                        .manifest()\n                        .links()\n                        .map(|links| links.to_string()),\n                    dep.unit.pkg.package_id(),\n                    dep_metadata,\n                ))\n            } else {\n                None\n            }\n        })\n        .collect::<Vec<_>>();\n    let library_name = unit.pkg.library().map(|t| t.crate_name());\n    let pkg_descr = unit.pkg.to_string();\n    let build_script_outputs = Arc::clone(&build_runner.build_script_outputs);\n    let id = unit.pkg.package_id();\n    let run_files = BuildScriptRunFiles::for_unit(build_runner, unit);\n    let host_target_root = build_runner.files().host_dest().map(|v| v.to_path_buf());\n    let all = (\n        id,\n        library_name.clone(),\n        pkg_descr.clone(),\n        Arc::clone(&build_script_outputs),\n        run_files.stdout.clone(),\n        script_out_dir.clone(),\n    );\n    let build_scripts = build_runner.build_scripts.get(unit).cloned();\n    let json_messages = bcx.build_config.emit_json();\n    let extra_verbose = bcx.gctx.extra_verbose();\n    let (prev_output, prev_script_out_dir) = prev_build_output(build_runner, unit);\n    let metadata_hash = build_runner.get_run_build_script_metadata(unit);\n\n    paths::create_dir_all(&script_dir)?;\n    paths::create_dir_all(&script_out_dir)?;\n    paths::create_dir_all(&run_files.root)?;\n\n    let nightly_features_allowed = build_runner.bcx.gctx.nightly_features_allowed;\n    let targets: Vec<Target> = unit.pkg.targets().to_vec();\n    let msrv = unit.pkg.rust_version().cloned();\n    // Need a separate copy for the fresh closure.\n    let targets_fresh = targets.clone();\n    let msrv_fresh = msrv.clone();\n\n    let env_profile_name = unit.profile.name.to_uppercase();\n    let built_with_debuginfo = build_runner\n        .bcx\n        .unit_graph\n        .get(unit)\n        .and_then(|deps| deps.iter().find(|dep| dep.unit.target == unit.target))\n        .map(|dep| dep.unit.profile.debuginfo.is_turned_on())\n        .unwrap_or(false);\n\n    // Prepare the unit of \"dirty work\" which will actually run the custom build\n    // command.\n    //\n    // Note that this has to do some extra work just before running the command\n    // to determine extra environment variables and such.\n    let dirty = Work::new(move |state| {\n        // Make sure that OUT_DIR exists.\n        //\n        // If we have an old build directory, then just move it into place,\n        // otherwise create it!\n        paths::create_dir_all(&script_out_dir)\n            .context(\"failed to create script output directory for build command\")?;\n\n        // For all our native lib dependencies, pick up their metadata to pass\n        // along to this custom build command. We're also careful to augment our\n        // dynamic library search path in case the build script depended on any\n        // native dynamic libraries.\n        {\n            let build_script_outputs = build_script_outputs.lock().unwrap();\n            for (name, links, dep_id, dep_metadata) in lib_deps {\n                let script_output = build_script_outputs.get(dep_metadata).ok_or_else(|| {\n                    internal(format!(\n                        \"failed to locate build state for env vars: {}/{}\",\n                        dep_id, dep_metadata\n                    ))\n                })?;\n                let data = &script_output.metadata;\n                for (key, value) in data.iter() {\n                    if let Some(ref links) = links {\n                        cmd.env(\n                            &format!(\"DEP_{}_{}\", super::envify(&links), super::envify(key)),\n                            value,\n                        );\n                    }\n                    if any_build_script_metadata {\n                        cmd.env(\n                            &format!(\"CARGO_DEP_{}_{}\", super::envify(&name), super::envify(key)),\n                            value,\n                        );\n                    }\n                }\n            }\n            if let Some(build_scripts) = build_scripts\n                && let Some(ref host_target_root) = host_target_root\n            {\n                super::add_plugin_deps(\n                    &mut cmd,\n                    &build_script_outputs,\n                    &build_scripts,\n                    host_target_root,\n                )?;\n            }\n        }\n\n        // And now finally, run the build command itself!\n        state.running(&cmd);\n        let timestamp = paths::set_invocation_time(&run_files.root)?;\n        let prefix = format!(\"[{} {}] \", id.name(), id.version());\n        let mut log_messages_in_case_of_panic = Vec::new();\n        let span = tracing::debug_span!(\"build_script\", process = cmd.to_string());\n        let output = span.in_scope(|| {\n            cmd.exec_with_streaming(\n                &mut |stdout| {\n                    if let Some(error) = stdout.strip_prefix(CARGO_ERROR_SYNTAX) {\n                        log_messages_in_case_of_panic.push((Severity::Error, error.to_owned()));\n                    }\n                    if let Some(warning) = stdout\n                        .strip_prefix(OLD_CARGO_WARNING_SYNTAX)\n                        .or(stdout.strip_prefix(NEW_CARGO_WARNING_SYNTAX))\n                    {\n                        log_messages_in_case_of_panic.push((Severity::Warning, warning.to_owned()));\n                    }\n                    if extra_verbose {\n                        state.stdout(format!(\"{}{}\", prefix, stdout))?;\n                    }\n                    Ok(())\n                },\n                &mut |stderr| {\n                    if extra_verbose {\n                        state.stderr(format!(\"{}{}\", prefix, stderr))?;\n                    }\n                    Ok(())\n                },\n                true,\n            )\n            .with_context(|| {\n                let mut build_error_context =\n                    format!(\"failed to run custom build command for `{}`\", pkg_descr);\n\n                // If we're opting into backtraces, mention that build dependencies' backtraces can\n                // be improved by requesting debuginfo to be built, if we're not building with\n                // debuginfo already.\n                #[expect(clippy::disallowed_methods, reason = \"consistency with rustc\")]\n                if let Ok(show_backtraces) = std::env::var(\"RUST_BACKTRACE\") {\n                    if !built_with_debuginfo && show_backtraces != \"0\" {\n                        build_error_context.push_str(&format!(\n                            \"\\n\\\n                            note: To improve backtraces for build dependencies, set the \\\n                            CARGO_PROFILE_{env_profile_name}_BUILD_OVERRIDE_DEBUG=true environment \\\n                            variable to enable debug information generation.\",\n                        ));\n                    }\n                }\n\n                build_error_context\n            })\n        });\n\n        // If the build failed\n        if let Err(error) = output {\n            insert_log_messages_in_build_outputs(\n                build_script_outputs,\n                id,\n                metadata_hash,\n                log_messages_in_case_of_panic,\n            );\n            return Err(error);\n        }\n        // ... or it logged any errors\n        else if log_messages_in_case_of_panic\n            .iter()\n            .any(|(severity, _)| *severity == Severity::Error)\n        {\n            insert_log_messages_in_build_outputs(\n                build_script_outputs,\n                id,\n                metadata_hash,\n                log_messages_in_case_of_panic,\n            );\n            anyhow::bail!(\"build script logged errors\");\n        }\n\n        let output = output.unwrap();\n\n        // After the build command has finished running, we need to be sure to\n        // remember all of its output so we can later discover precisely what it\n        // was, even if we don't run the build command again (due to freshness).\n        //\n        // This is also the location where we provide feedback into the build\n        // state informing what variables were discovered via our script as\n        // well.\n        paths::write(&run_files.stdout, &output.stdout)?;\n        // This mtime shift allows Cargo to detect if a source file was\n        // modified in the middle of the build.\n        paths::set_file_time_no_err(run_files.stdout, timestamp);\n        paths::write(&run_files.stderr, &output.stderr)?;\n        paths::write(&run_files.root_output, paths::path2bytes(&script_out_dir)?)?;\n        let parsed_output = BuildOutput::parse(\n            &output.stdout,\n            library_name,\n            &pkg_descr,\n            &script_out_dir,\n            &script_out_dir,\n            nightly_features_allowed,\n            &targets,\n            &msrv,\n        )?;\n\n        if json_messages {\n            emit_build_output(state, &parsed_output, script_out_dir.as_path(), id)?;\n        }\n        build_script_outputs\n            .lock()\n            .unwrap()\n            .insert(id, metadata_hash, parsed_output);\n        Ok(())\n    });\n\n    // Now that we've prepared our work-to-do, we need to prepare the fresh work\n    // itself to run when we actually end up just discarding what we calculated\n    // above.\n    let fresh = Work::new(move |state| {\n        let (id, library_name, pkg_descr, build_script_outputs, output_file, script_out_dir) = all;\n        let output = match prev_output {\n            Some(output) => output,\n            None => BuildOutput::parse_file(\n                &output_file,\n                library_name,\n                &pkg_descr,\n                &prev_script_out_dir,\n                &script_out_dir,\n                nightly_features_allowed,\n                &targets_fresh,\n                &msrv_fresh,\n            )?,\n        };\n\n        if json_messages {\n            emit_build_output(state, &output, script_out_dir.as_path(), id)?;\n        }\n\n        build_script_outputs\n            .lock()\n            .unwrap()\n            .insert(id, metadata_hash, output);\n        Ok(())\n    });\n\n    let mut job = fingerprint::prepare_target(build_runner, unit, false)?;\n    if job.freshness().is_dirty() {\n        job.before(dirty);\n    } else {\n        job.before(fresh);\n    }\n    Ok(job)\n}\n\n/// When a build script run fails, store only log messages, and nuke other\n/// outputs, as they are likely broken.\nfn insert_log_messages_in_build_outputs(\n    build_script_outputs: Arc<Mutex<BuildScriptOutputs>>,\n    id: PackageId,\n    metadata_hash: UnitHash,\n    log_messages: Vec<LogMessage>,\n) {\n    let build_output_with_only_log_messages = BuildOutput {\n        log_messages,\n        ..BuildOutput::default()\n    };\n    build_script_outputs.lock().unwrap().insert(\n        id,\n        metadata_hash,\n        build_output_with_only_log_messages,\n    );\n}\n\nimpl BuildOutput {\n    /// Like [`BuildOutput::parse`] but from a file path.\n    pub fn parse_file(\n        path: &Path,\n        library_name: Option<String>,\n        pkg_descr: &str,\n        script_out_dir_when_generated: &Path,\n        script_out_dir: &Path,\n        nightly_features_allowed: bool,\n        targets: &[Target],\n        msrv: &Option<RustVersion>,\n    ) -> CargoResult<BuildOutput> {\n        let contents = paths::read_bytes(path)?;\n        BuildOutput::parse(\n            &contents,\n            library_name,\n            pkg_descr,\n            script_out_dir_when_generated,\n            script_out_dir,\n            nightly_features_allowed,\n            targets,\n            msrv,\n        )\n    }\n\n    /// Parses the output instructions of a build script.\n    ///\n    /// * `pkg_descr` --- for error messages\n    /// * `library_name` --- for determining if `RUSTC_BOOTSTRAP` should be allowed\n    pub fn parse(\n        input: &[u8],\n        // Takes String instead of InternedString so passing `unit.pkg.name()` will give a compile error.\n        library_name: Option<String>,\n        pkg_descr: &str,\n        script_out_dir_when_generated: &Path,\n        script_out_dir: &Path,\n        nightly_features_allowed: bool,\n        targets: &[Target],\n        msrv: &Option<RustVersion>,\n    ) -> CargoResult<BuildOutput> {\n        let mut library_paths = Vec::new();\n        let mut library_links = Vec::new();\n        let mut linker_args = Vec::new();\n        let mut cfgs = Vec::new();\n        let mut check_cfgs = Vec::new();\n        let mut env = Vec::new();\n        let mut metadata = Vec::new();\n        let mut rerun_if_changed = Vec::new();\n        let mut rerun_if_env_changed = Vec::new();\n        let mut log_messages = Vec::new();\n        let whence = format!(\"build script of `{}`\", pkg_descr);\n        // Old syntax:\n        //    cargo:rustc-flags=VALUE\n        //    cargo:KEY=VALUE (for other unreserved keys)\n        // New syntax:\n        //    cargo::rustc-flags=VALUE\n        //    cargo::metadata=KEY=VALUE (for other unreserved keys)\n        // Due to backwards compatibility, no new keys can be added to this old format.\n        const RESERVED_PREFIXES: &[&str] = &[\n            \"rustc-flags=\",\n            \"rustc-link-lib=\",\n            \"rustc-link-search=\",\n            \"rustc-link-arg-cdylib=\",\n            \"rustc-cdylib-link-arg=\",\n            \"rustc-link-arg-bins=\",\n            \"rustc-link-arg-bin=\",\n            \"rustc-link-arg-tests=\",\n            \"rustc-link-arg-benches=\",\n            \"rustc-link-arg-examples=\",\n            \"rustc-link-arg=\",\n            \"rustc-cfg=\",\n            \"rustc-check-cfg=\",\n            \"rustc-env=\",\n            \"warning=\",\n            \"rerun-if-changed=\",\n            \"rerun-if-env-changed=\",\n        ];\n        const DOCS_LINK_SUGGESTION: &str = \"See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script \\\n                for more information about build script outputs.\";\n\n        fn has_reserved_prefix(flag: &str) -> bool {\n            RESERVED_PREFIXES\n                .iter()\n                .any(|reserved_prefix| flag.starts_with(reserved_prefix))\n        }\n\n        fn check_minimum_supported_rust_version_for_new_syntax(\n            pkg_descr: &str,\n            msrv: &Option<RustVersion>,\n            flag: &str,\n        ) -> CargoResult<()> {\n            if let Some(msrv) = msrv {\n                let new_syntax_added_in = RustVersion::new(1, 77, 0);\n                if !new_syntax_added_in.is_compatible_with(&msrv.to_partial()) {\n                    let old_syntax_suggestion = if has_reserved_prefix(flag) {\n                        format!(\n                            \"Switch to the old `cargo:{flag}` syntax (note the single colon).\\n\"\n                        )\n                    } else if flag.starts_with(\"metadata=\") {\n                        let old_format_flag = flag.strip_prefix(\"metadata=\").unwrap();\n                        format!(\n                            \"Switch to the old `cargo:{old_format_flag}` syntax instead of `cargo::{flag}` (note the single colon).\\n\"\n                        )\n                    } else {\n                        String::new()\n                    };\n\n                    bail!(\n                        \"the `cargo::` syntax for build script output instructions was added in \\\n                        Rust 1.77.0, but the minimum supported Rust version of `{pkg_descr}` is {msrv}.\\n\\\n                        {old_syntax_suggestion}\\\n                        {DOCS_LINK_SUGGESTION}\"\n                    );\n                }\n            }\n\n            Ok(())\n        }\n\n        fn parse_directive<'a>(\n            whence: &str,\n            line: &str,\n            data: &'a str,\n            old_syntax: bool,\n        ) -> CargoResult<(&'a str, &'a str)> {\n            let mut iter = data.splitn(2, \"=\");\n            let key = iter.next();\n            let value = iter.next();\n            match (key, value) {\n                (Some(a), Some(b)) => Ok((a, b.trim_end())),\n                _ => bail!(\n                    \"invalid output in {whence}: `{line}`\\n\\\n                    Expected a line with `{syntax}KEY=VALUE` with an `=` character, \\\n                    but none was found.\\n\\\n                    {DOCS_LINK_SUGGESTION}\",\n                    syntax = if old_syntax { \"cargo:\" } else { \"cargo::\" },\n                ),\n            }\n        }\n\n        fn parse_metadata<'a>(\n            whence: &str,\n            line: &str,\n            data: &'a str,\n            old_syntax: bool,\n        ) -> CargoResult<(&'a str, &'a str)> {\n            let mut iter = data.splitn(2, \"=\");\n            let key = iter.next();\n            let value = iter.next();\n            match (key, value) {\n                (Some(a), Some(b)) => Ok((a, b.trim_end())),\n                _ => bail!(\n                    \"invalid output in {whence}: `{line}`\\n\\\n                    Expected a line with `{syntax}KEY=VALUE` with an `=` character, \\\n                    but none was found.\\n\\\n                    {DOCS_LINK_SUGGESTION}\",\n                    syntax = if old_syntax {\n                        \"cargo:\"\n                    } else {\n                        \"cargo::metadata=\"\n                    },\n                ),\n            }\n        }\n\n        for line in input.split(|b| *b == b'\\n') {\n            let line = match str::from_utf8(line) {\n                Ok(line) => line.trim(),\n                Err(..) => continue,\n            };\n            let mut old_syntax = false;\n            let (key, value) = if let Some(data) = line.strip_prefix(\"cargo::\") {\n                check_minimum_supported_rust_version_for_new_syntax(pkg_descr, msrv, data)?;\n                // For instance, `cargo::rustc-flags=foo` or `cargo::metadata=foo=bar`.\n                parse_directive(whence.as_str(), line, data, old_syntax)?\n            } else if let Some(data) = line.strip_prefix(\"cargo:\") {\n                old_syntax = true;\n                // For instance, `cargo:rustc-flags=foo`.\n                if has_reserved_prefix(data) {\n                    parse_directive(whence.as_str(), line, data, old_syntax)?\n                } else {\n                    // For instance, `cargo:foo=bar`.\n                    (\"metadata\", data)\n                }\n            } else {\n                // Skip this line since it doesn't start with \"cargo:\" or \"cargo::\".\n                continue;\n            };\n            // This will rewrite paths if the target directory has been moved.\n            let value = value.replace(\n                script_out_dir_when_generated.to_str().unwrap(),\n                script_out_dir.to_str().unwrap(),\n            );\n\n            let syntax_prefix = if old_syntax { \"cargo:\" } else { \"cargo::\" };\n            macro_rules! check_and_add_target {\n                ($target_kind: expr, $is_target_kind: expr, $link_type: expr) => {\n                    if !targets.iter().any(|target| $is_target_kind(target)) {\n                        bail!(\n                            \"invalid instruction `{}{}` from {}\\n\\\n                                The package {} does not have a {} target.\",\n                            syntax_prefix,\n                            key,\n                            whence,\n                            pkg_descr,\n                            $target_kind\n                        );\n                    }\n                    linker_args.push(($link_type, value));\n                };\n            }\n\n            // Keep in sync with TargetConfig::parse_links_overrides.\n            match key {\n                \"rustc-flags\" => {\n                    let (paths, links) = BuildOutput::parse_rustc_flags(&value, &whence)?;\n                    library_links.extend(links.into_iter());\n                    library_paths.extend(\n                        paths\n                            .into_iter()\n                            .map(|p| LibraryPath::new(p, script_out_dir)),\n                    );\n                }\n                \"rustc-link-lib\" => library_links.push(value.to_string()),\n                \"rustc-link-search\" => {\n                    library_paths.push(LibraryPath::new(PathBuf::from(value), script_out_dir))\n                }\n                \"rustc-link-arg-cdylib\" | \"rustc-cdylib-link-arg\" => {\n                    if !targets.iter().any(|target| target.is_cdylib()) {\n                        log_messages.push((\n                            Severity::Warning,\n                            format!(\n                                \"{}{} was specified in the build script of {}, \\\n                             but that package does not contain a cdylib target\\n\\\n                             \\n\\\n                             Allowing this was an unintended change in the 1.50 \\\n                             release, and may become an error in the future. \\\n                             For more information, see \\\n                             <https://github.com/rust-lang/cargo/issues/9562>.\",\n                                syntax_prefix, key, pkg_descr\n                            ),\n                        ));\n                    }\n                    linker_args.push((LinkArgTarget::Cdylib, value))\n                }\n                \"rustc-link-arg-bins\" => {\n                    check_and_add_target!(\"bin\", Target::is_bin, LinkArgTarget::Bin);\n                }\n                \"rustc-link-arg-bin\" => {\n                    let (bin_name, arg) = value.split_once('=').ok_or_else(|| {\n                        anyhow::format_err!(\n                            \"invalid instruction `{}{}={}` from {}\\n\\\n                                The instruction should have the form {}{}=BIN=ARG\",\n                            syntax_prefix,\n                            key,\n                            value,\n                            whence,\n                            syntax_prefix,\n                            key\n                        )\n                    })?;\n                    if !targets\n                        .iter()\n                        .any(|target| target.is_bin() && target.name() == bin_name)\n                    {\n                        bail!(\n                            \"invalid instruction `{}{}` from {}\\n\\\n                                The package {} does not have a bin target with the name `{}`.\",\n                            syntax_prefix,\n                            key,\n                            whence,\n                            pkg_descr,\n                            bin_name\n                        );\n                    }\n                    linker_args.push((\n                        LinkArgTarget::SingleBin(bin_name.to_owned()),\n                        arg.to_string(),\n                    ));\n                }\n                \"rustc-link-arg-tests\" => {\n                    check_and_add_target!(\"test\", Target::is_test, LinkArgTarget::Test);\n                }\n                \"rustc-link-arg-benches\" => {\n                    check_and_add_target!(\"benchmark\", Target::is_bench, LinkArgTarget::Bench);\n                }\n                \"rustc-link-arg-examples\" => {\n                    check_and_add_target!(\"example\", Target::is_example, LinkArgTarget::Example);\n                }\n                \"rustc-link-arg\" => {\n                    linker_args.push((LinkArgTarget::All, value));\n                }\n                \"rustc-cfg\" => cfgs.push(value.to_string()),\n                \"rustc-check-cfg\" => check_cfgs.push(value.to_string()),\n                \"rustc-env\" => {\n                    let (key, val) = BuildOutput::parse_rustc_env(&value, &whence)?;\n                    // Build scripts aren't allowed to set RUSTC_BOOTSTRAP.\n                    // See https://github.com/rust-lang/cargo/issues/7088.\n                    if key == \"RUSTC_BOOTSTRAP\" {\n                        // If RUSTC_BOOTSTRAP is already set, the user of Cargo knows about\n                        // bootstrap and still wants to override the channel. Give them a way to do\n                        // so, but still emit a warning that the current crate shouldn't be trying\n                        // to set RUSTC_BOOTSTRAP.\n                        // If this is a nightly build, setting RUSTC_BOOTSTRAP wouldn't affect the\n                        // behavior, so still only give a warning.\n                        // NOTE: cargo only allows nightly features on RUSTC_BOOTSTRAP=1, but we\n                        // want setting any value of RUSTC_BOOTSTRAP to downgrade this to a warning\n                        // (so that `RUSTC_BOOTSTRAP=library_name` will work)\n                        let rustc_bootstrap_allows = |name: Option<&str>| {\n                            let name = match name {\n                                // as of 2021, no binaries on crates.io use RUSTC_BOOTSTRAP, so\n                                // fine-grained opt-outs aren't needed. end-users can always use\n                                // RUSTC_BOOTSTRAP=1 from the top-level if it's really a problem.\n                                None => return false,\n                                Some(n) => n,\n                            };\n                            #[expect(\n                                clippy::disallowed_methods,\n                                reason = \"consistency with rustc, not specified behavior\"\n                            )]\n                            std::env::var(\"RUSTC_BOOTSTRAP\")\n                                .map_or(false, |var| var.split(',').any(|s| s == name))\n                        };\n                        if nightly_features_allowed\n                            || rustc_bootstrap_allows(library_name.as_deref())\n                        {\n                            log_messages.push((Severity::Warning, format!(\"cannot set `RUSTC_BOOTSTRAP={}` from {}.\\n\\\n                                note: crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.\",\n                                val, whence\n                            )));\n                        } else {\n                            // Setting RUSTC_BOOTSTRAP would change the behavior of the crate.\n                            // Abort with an error.\n                            bail!(\n                                \"cannot set `RUSTC_BOOTSTRAP={}` from {}.\\n\\\n                                note: crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.\\n\\\n                                help: If you're sure you want to do this in your project, set the environment variable `RUSTC_BOOTSTRAP={}` before running cargo instead.\",\n                                val,\n                                whence,\n                                library_name.as_deref().unwrap_or(\"1\"),\n                            );\n                        }\n                    } else {\n                        env.push((key, val));\n                    }\n                }\n                \"error\" => log_messages.push((Severity::Error, value.to_string())),\n                \"warning\" => log_messages.push((Severity::Warning, value.to_string())),\n                \"rerun-if-changed\" => rerun_if_changed.push(PathBuf::from(value)),\n                \"rerun-if-env-changed\" => rerun_if_env_changed.push(value.to_string()),\n                \"metadata\" => {\n                    let (key, value) = parse_metadata(whence.as_str(), line, &value, old_syntax)?;\n                    metadata.push((key.to_owned(), value.to_owned()));\n                }\n                _ => bail!(\n                    \"invalid output in {whence}: `{line}`\\n\\\n                    Unknown key: `{key}`.\\n\\\n                    {DOCS_LINK_SUGGESTION}\",\n                ),\n            }\n        }\n\n        Ok(BuildOutput {\n            library_paths,\n            library_links,\n            linker_args,\n            cfgs,\n            check_cfgs,\n            env,\n            metadata,\n            rerun_if_changed,\n            rerun_if_env_changed,\n            log_messages,\n        })\n    }\n\n    /// Parses [`cargo::rustc-flags`] instruction.\n    ///\n    /// [`cargo::rustc-flags`]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargorustc-flagsflags\n    pub fn parse_rustc_flags(\n        value: &str,\n        whence: &str,\n    ) -> CargoResult<(Vec<PathBuf>, Vec<String>)> {\n        let value = value.trim();\n        let mut flags_iter = value\n            .split(|c: char| c.is_whitespace())\n            .filter(|w| w.chars().any(|c| !c.is_whitespace()));\n        let (mut library_paths, mut library_links) = (Vec::new(), Vec::new());\n\n        while let Some(flag) = flags_iter.next() {\n            if flag.starts_with(\"-l\") || flag.starts_with(\"-L\") {\n                // Check if this flag has no space before the value as is\n                // common with tools like pkg-config\n                // e.g. -L/some/dir/local/lib or -licui18n\n                let (flag, mut value) = flag.split_at(2);\n                if value.is_empty() {\n                    value = match flags_iter.next() {\n                        Some(v) => v,\n                        None => bail! {\n                            \"flag in rustc-flags has no value in {}: {}\",\n                            whence,\n                            value\n                        },\n                    }\n                }\n\n                match flag {\n                    \"-l\" => library_links.push(value.to_string()),\n                    \"-L\" => library_paths.push(PathBuf::from(value)),\n\n                    // This was already checked above\n                    _ => unreachable!(),\n                };\n            } else {\n                bail!(\n                    \"only `-l` and `-L` flags are allowed in {}: `{}`\",\n                    whence,\n                    value\n                )\n            }\n        }\n        Ok((library_paths, library_links))\n    }\n\n    /// Parses [`cargo::rustc-env`] instruction.\n    ///\n    /// [`cargo::rustc-env`]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-env\n    pub fn parse_rustc_env(value: &str, whence: &str) -> CargoResult<(String, String)> {\n        match value.split_once('=') {\n            Some((n, v)) => Ok((n.to_owned(), v.to_owned())),\n            _ => bail!(\"Variable rustc-env has no value in {whence}: {value}\"),\n        }\n    }\n}\n\n/// Prepares the Rust script for the unstable feature [metabuild].\n///\n/// [metabuild]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#metabuild\nfn prepare_metabuild(\n    build_runner: &BuildRunner<'_, '_>,\n    unit: &Unit,\n    deps: &[String],\n) -> CargoResult<()> {\n    let mut output = Vec::new();\n    let available_deps = build_runner.unit_deps(unit);\n    // Filter out optional dependencies, and look up the actual lib name.\n    let meta_deps: Vec<_> = deps\n        .iter()\n        .filter_map(|name| {\n            available_deps\n                .iter()\n                .find(|d| d.unit.pkg.name().as_str() == name.as_str())\n                .map(|d| d.unit.target.crate_name())\n        })\n        .collect();\n    output.push(\"fn main() {\\n\".to_string());\n    for dep in &meta_deps {\n        output.push(format!(\"    {}::metabuild();\\n\", dep));\n    }\n    output.push(\"}\\n\".to_string());\n    let output = output.join(\"\");\n    let path = unit\n        .pkg\n        .manifest()\n        .metabuild_path(build_runner.bcx.ws.build_dir());\n    paths::create_dir_all(path.parent().unwrap())?;\n    paths::write_if_changed(path, &output)?;\n    Ok(())\n}\n\nimpl BuildDeps {\n    /// Creates a build script dependency information from a previous\n    /// build script output path and the content.\n    pub fn new(output_file: &Path, output: Option<&BuildOutput>) -> BuildDeps {\n        BuildDeps {\n            build_script_output: output_file.to_path_buf(),\n            rerun_if_changed: output\n                .map(|p| &p.rerun_if_changed)\n                .cloned()\n                .unwrap_or_default(),\n            rerun_if_env_changed: output\n                .map(|p| &p.rerun_if_env_changed)\n                .cloned()\n                .unwrap_or_default(),\n        }\n    }\n}\n\n/// Computes several maps in [`BuildRunner`].\n///\n/// - [`build_scripts`]: A map that tracks which build scripts each package\n///   depends on.\n/// - [`build_explicit_deps`]: Dependency statements emitted by build scripts\n///   from a previous run.\n/// - [`build_script_outputs`]: Pre-populates this with any overridden build\n///   scripts.\n///\n/// The important one here is [`build_scripts`], which for each `(package,\n/// metadata)` stores a [`BuildScripts`] object which contains a list of\n/// dependencies with build scripts that the unit should consider when linking.\n/// For example this lists all dependencies' `-L` flags which need to be\n/// propagated transitively.\n///\n/// The given set of units to this function is the initial set of\n/// targets/profiles which are being built.\n///\n/// [`build_scripts`]: BuildRunner::build_scripts\n/// [`build_explicit_deps`]: BuildRunner::build_explicit_deps\n/// [`build_script_outputs`]: BuildRunner::build_script_outputs\npub fn build_map(build_runner: &mut BuildRunner<'_, '_>) -> CargoResult<()> {\n    let mut ret = HashMap::new();\n    for unit in &build_runner.bcx.roots {\n        build(&mut ret, build_runner, unit)?;\n    }\n    build_runner\n        .build_scripts\n        .extend(ret.into_iter().map(|(k, v)| (k, Arc::new(v))));\n    return Ok(());\n\n    // Recursive function to build up the map we're constructing. This function\n    // memoizes all of its return values as it goes along.\n    fn build<'a>(\n        out: &'a mut HashMap<Unit, BuildScripts>,\n        build_runner: &mut BuildRunner<'_, '_>,\n        unit: &Unit,\n    ) -> CargoResult<&'a BuildScripts> {\n        // Do a quick pre-flight check to see if we've already calculated the\n        // set of dependencies.\n        if out.contains_key(unit) {\n            return Ok(&out[unit]);\n        }\n\n        // If there is a build script override, pre-fill the build output.\n        if unit.mode.is_run_custom_build() {\n            if let Some(links) = unit.pkg.manifest().links() {\n                if let Some(output) = unit.links_overrides.get(links) {\n                    let metadata = build_runner.get_run_build_script_metadata(unit);\n                    build_runner.build_script_outputs.lock().unwrap().insert(\n                        unit.pkg.package_id(),\n                        metadata,\n                        output.clone(),\n                    );\n                }\n            }\n        }\n\n        let mut ret = BuildScripts::default();\n\n        // If a package has a build script, add itself as something to inspect for linking.\n        if !unit.target.is_custom_build() && unit.pkg.has_custom_build() {\n            let script_metas = build_runner\n                .find_build_script_metadatas(unit)\n                .expect(\"has_custom_build should have RunCustomBuild\");\n            for script_meta in script_metas {\n                add_to_link(&mut ret, unit.pkg.package_id(), script_meta);\n            }\n        }\n\n        if unit.mode.is_run_custom_build() {\n            parse_previous_explicit_deps(build_runner, unit);\n        }\n\n        // We want to invoke the compiler deterministically to be cache-friendly\n        // to rustc invocation caching schemes, so be sure to generate the same\n        // set of build script dependency orderings via sorting the targets that\n        // come out of the `Context`.\n        let mut dependencies: Vec<Unit> = build_runner\n            .unit_deps(unit)\n            .iter()\n            .map(|d| d.unit.clone())\n            .collect();\n        dependencies.sort_by_key(|u| u.pkg.package_id());\n\n        for dep_unit in dependencies.iter() {\n            let dep_scripts = build(out, build_runner, dep_unit)?;\n\n            if dep_unit.target.for_host() {\n                ret.plugins.extend(dep_scripts.to_link.iter().cloned());\n            } else if dep_unit.target.is_linkable() {\n                for &(pkg, metadata) in dep_scripts.to_link.iter() {\n                    add_to_link(&mut ret, pkg, metadata);\n                }\n            }\n        }\n\n        match out.entry(unit.clone()) {\n            Entry::Vacant(entry) => Ok(entry.insert(ret)),\n            Entry::Occupied(_) => panic!(\"cyclic dependencies in `build_map`\"),\n        }\n    }\n\n    // When adding an entry to 'to_link' we only actually push it on if the\n    // script hasn't seen it yet (e.g., we don't push on duplicates).\n    fn add_to_link(scripts: &mut BuildScripts, pkg: PackageId, metadata: UnitHash) {\n        if scripts.seen_to_link.insert((pkg, metadata)) {\n            scripts.to_link.push((pkg, metadata));\n        }\n    }\n\n    /// Load any dependency declarations from a previous build script run.\n    fn parse_previous_explicit_deps(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) {\n        let run_files = BuildScriptRunFiles::for_unit(build_runner, unit);\n        let (prev_output, _) = prev_build_output(build_runner, unit);\n        let deps = BuildDeps::new(&run_files.stdout, prev_output.as_ref());\n        build_runner.build_explicit_deps.insert(unit.clone(), deps);\n    }\n}\n\n/// Returns the previous parsed `BuildOutput`, if any, from a previous\n/// execution.\n///\n/// Also returns the directory containing the output, typically used later in\n/// processing.\nfn prev_build_output(\n    build_runner: &mut BuildRunner<'_, '_>,\n    unit: &Unit,\n) -> (Option<BuildOutput>, PathBuf) {\n    let script_out_dir = if build_runner.bcx.gctx.cli_unstable().build_dir_new_layout {\n        build_runner.files().out_dir_new_layout(unit)\n    } else {\n        build_runner.files().build_script_out_dir(unit)\n    };\n    let run_files = BuildScriptRunFiles::for_unit(build_runner, unit);\n\n    let prev_script_out_dir = paths::read_bytes(&run_files.root_output)\n        .and_then(|bytes| paths::bytes2path(&bytes))\n        .unwrap_or_else(|_| script_out_dir.clone());\n\n    (\n        BuildOutput::parse_file(\n            &run_files.stdout,\n            unit.pkg.library().map(|t| t.crate_name()),\n            &unit.pkg.to_string(),\n            &prev_script_out_dir,\n            &script_out_dir,\n            build_runner.bcx.gctx.nightly_features_allowed,\n            unit.pkg.targets(),\n            &unit.pkg.rust_version().cloned(),\n        )\n        .ok(),\n        prev_script_out_dir,\n    )\n}\n\nimpl BuildScriptOutputs {\n    /// Inserts a new entry into the map.\n    fn insert(&mut self, pkg_id: PackageId, metadata: UnitHash, parsed_output: BuildOutput) {\n        match self.outputs.entry(metadata) {\n            Entry::Vacant(entry) => {\n                entry.insert(parsed_output);\n            }\n            Entry::Occupied(entry) => panic!(\n                \"build script output collision for {}/{}\\n\\\n                old={:?}\\nnew={:?}\",\n                pkg_id,\n                metadata,\n                entry.get(),\n                parsed_output\n            ),\n        }\n    }\n\n    /// Returns `true` if the given key already exists.\n    fn contains_key(&self, metadata: UnitHash) -> bool {\n        self.outputs.contains_key(&metadata)\n    }\n\n    /// Gets the build output for the given key.\n    pub fn get(&self, meta: UnitHash) -> Option<&BuildOutput> {\n        self.outputs.get(&meta)\n    }\n\n    /// Returns an iterator over all entries.\n    pub fn iter(&self) -> impl Iterator<Item = (&UnitHash, &BuildOutput)> {\n        self.outputs.iter()\n    }\n}\n\n/// Files with information about a running build script.\nstruct BuildScriptRunFiles {\n    /// The directory containing files related to running a build script.\n    root: PathBuf,\n    /// The stdout produced by the build script\n    stdout: PathBuf,\n    /// The stderr produced by the build script\n    stderr: PathBuf,\n    /// A file that contains the path to the `out` dir of the build script.\n    /// This is used for detect if the directory was moved since the previous run.\n    root_output: PathBuf,\n}\n\nimpl BuildScriptRunFiles {\n    pub fn for_unit(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> Self {\n        let root = build_runner.files().build_script_run_dir(unit);\n        let stdout = if build_runner.bcx.gctx.cli_unstable().build_dir_new_layout {\n            root.join(\"stdout\")\n        } else {\n            root.join(\"output\")\n        };\n        let stderr = root.join(\"stderr\");\n        let root_output = root.join(\"root-output\");\n        Self {\n            root,\n            stdout,\n            stderr,\n            root_output,\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/fingerprint/dep_info.rs",
    "content": "//! Types and functions managing dep-info files.\n//! For more, see [the documentation] in the `fingerprint` module.\n//!\n//! [the documentation]: crate::core::compiler::fingerprint#dep-info-files\n\nuse std::collections::HashMap;\nuse std::ffi::OsString;\nuse std::fmt;\nuse std::io;\nuse std::io::Read;\nuse std::path::Path;\nuse std::path::PathBuf;\nuse std::str;\nuse std::str::FromStr;\nuse std::sync::Arc;\n\nuse anyhow::bail;\nuse cargo_util::ProcessBuilder;\nuse cargo_util::Sha256;\nuse cargo_util::paths;\nuse serde::Serialize;\n\nuse crate::CARGO_ENV;\nuse crate::CargoResult;\nuse crate::core::manifest::ManifestMetadata;\n\n/// The current format version of [`EncodedDepInfo`].\nconst CURRENT_ENCODED_DEP_INFO_VERSION: u8 = 1;\n\n/// The representation of the `.d` dep-info file generated by rustc\n#[derive(Default)]\npub struct RustcDepInfo {\n    /// The list of files that the main target in the dep-info file depends on.\n    ///\n    /// The optional checksums are parsed from the special `# checksum:...` comments.\n    pub files: HashMap<PathBuf, Option<(u64, Checksum)>>,\n    /// The list of environment variables we found that the rustc compilation\n    /// depends on.\n    ///\n    /// The first element of the pair is the name of the env var and the second\n    /// item is the value. `Some` means that the env var was set, and `None`\n    /// means that the env var wasn't actually set and the compilation depends\n    /// on it not being set.\n    ///\n    /// These are from the special `# env-var:...` comments.\n    pub env: Vec<(String, Option<String>)>,\n}\n\n/// Tells the associated path in [`EncodedDepInfo::files`] is relative to package root,\n/// target root, or absolute.\n#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]\npub enum DepInfoPathType {\n    /// src/, e.g. src/lib.rs\n    PackageRootRelative,\n    /// {build-dir}/debug/deps/lib...\n    /// or an absolute path /.../sysroot/...\n    BuildRootRelative,\n}\n\n/// Same as [`RustcDepInfo`] except avoids absolute paths as much as possible to\n/// allow moving around the target directory.\n///\n/// This is also stored in an optimized format to make parsing it fast because\n/// Cargo will read it for crates on all future compilations.\n///\n/// Currently the format looks like:\n///\n/// ```text\n/// +--------+---------+------------+------------+---------------+---------------+\n/// | marker | version | # of files | file paths | # of env vars | env var pairs |\n/// +--------+---------+------------+------------+---------------+---------------+\n/// ```\n///\n/// Each field represents\n///\n/// * _Marker_ --- A magic marker to ensure that older Cargoes, which only\n///   recognize format v0 (prior to checksum support in [`f4ca7390`]), do not\n///   proceed with parsing newer formats. Since [`EncodedDepInfo`] is merely\n///   an optimization, and to avoid adding complexity, Cargo recognizes only\n///   one version of [`CURRENT_ENCODED_DEP_INFO_VERSION`].\n///   The current layout looks like this\n///   ```text\n///   +----------------------------+\n///   | [0x01 0x00 0x00 0x00 0xff] |\n///   +----------------------------+\n///   ```\n///   These bytes will be interpreted as \"one file tracked and an invalid\n///   [`DepInfoPathType`] variant with 255\" by older Cargoes, causing them to\n///   stop parsing. This could prevent problematic parsing as noted in\n///   rust-lang/cargo#14712.\n/// * _Version_ --- The current format version.\n/// * _Number of files/envs_ --- A `u32` representing the number of things.\n/// * _File paths_ --- Zero or more paths of files the dep-info file depends on.\n///   Each path is encoded as the following:\n///\n///   ```text\n///   +-----------+-------------+------------+---------------+-----------+-------+\n///   | path type | len of path | path bytes | cksum exists? | file size | cksum |\n///   +-----------+-------------+------------+---------------+-----------+-------+\n///   ```\n/// * _Env var pairs_ --- Zero or more env vars the dep-info file depends on.\n///   Each env key-value pair is encoded as the following:\n///   ```text\n///   +------------+-----------+---------------+--------------+-------------+\n///   | len of key | key bytes | value exists? | len of value | value bytes |\n///   +------------+-----------+---------------+--------------+-------------+\n///   ```\n///\n/// [`f4ca7390`]: https://github.com/rust-lang/cargo/commit/f4ca739073185ea5e1148ff100bb4a06d3bf721d\n#[derive(Default, Debug, PartialEq, Eq)]\npub struct EncodedDepInfo {\n    pub files: Vec<(DepInfoPathType, PathBuf, Option<(u64, String)>)>,\n    pub env: Vec<(String, Option<String>)>,\n}\n\nimpl EncodedDepInfo {\n    pub fn parse(mut bytes: &[u8]) -> Option<EncodedDepInfo> {\n        let bytes = &mut bytes;\n        read_magic_marker(bytes)?;\n        let version = read_u8(bytes)?;\n        if version != CURRENT_ENCODED_DEP_INFO_VERSION {\n            return None;\n        }\n\n        let nfiles = read_usize(bytes)?;\n        let mut files = Vec::with_capacity(nfiles);\n        for _ in 0..nfiles {\n            let ty = match read_u8(bytes)? {\n                0 => DepInfoPathType::PackageRootRelative,\n                1 => DepInfoPathType::BuildRootRelative,\n                _ => return None,\n            };\n            let path_bytes = read_bytes(bytes)?;\n            let path = paths::bytes2path(path_bytes).ok()?;\n            let has_checksum = read_bool(bytes)?;\n            let checksum_info = has_checksum\n                .then(|| {\n                    let file_len = read_u64(bytes);\n                    let checksum_string = read_bytes(bytes)\n                        .map(Vec::from)\n                        .and_then(|v| String::from_utf8(v).ok());\n                    file_len.zip(checksum_string)\n                })\n                .flatten();\n            files.push((ty, path, checksum_info));\n        }\n\n        let nenv = read_usize(bytes)?;\n        let mut env = Vec::with_capacity(nenv);\n        for _ in 0..nenv {\n            let key = str::from_utf8(read_bytes(bytes)?).ok()?.to_string();\n            let val = match read_u8(bytes)? {\n                0 => None,\n                1 => Some(str::from_utf8(read_bytes(bytes)?).ok()?.to_string()),\n                _ => return None,\n            };\n            env.push((key, val));\n        }\n        return Some(EncodedDepInfo { files, env });\n\n        /// See [`EncodedDepInfo`] for why a magic marker exists.\n        fn read_magic_marker(bytes: &mut &[u8]) -> Option<()> {\n            let _size = read_usize(bytes)?;\n            let path_type = read_u8(bytes)?;\n            if path_type != u8::MAX {\n                // Old depinfo. Give up parsing it.\n                None\n            } else {\n                Some(())\n            }\n        }\n\n        fn read_usize(bytes: &mut &[u8]) -> Option<usize> {\n            let ret = bytes.get(..4)?;\n            *bytes = &bytes[4..];\n            Some(u32::from_le_bytes(ret.try_into().unwrap()) as usize)\n        }\n\n        fn read_u64(bytes: &mut &[u8]) -> Option<u64> {\n            let ret = bytes.get(..8)?;\n            *bytes = &bytes[8..];\n            Some(u64::from_le_bytes(ret.try_into().unwrap()))\n        }\n\n        fn read_bool(bytes: &mut &[u8]) -> Option<bool> {\n            read_u8(bytes).map(|b| b != 0)\n        }\n\n        fn read_u8(bytes: &mut &[u8]) -> Option<u8> {\n            let ret = *bytes.get(0)?;\n            *bytes = &bytes[1..];\n            Some(ret)\n        }\n\n        fn read_bytes<'a>(bytes: &mut &'a [u8]) -> Option<&'a [u8]> {\n            let n = read_usize(bytes)? as usize;\n            let ret = bytes.get(..n)?;\n            *bytes = &bytes[n..];\n            Some(ret)\n        }\n    }\n\n    pub fn serialize(&self) -> CargoResult<Vec<u8>> {\n        let mut ret = Vec::new();\n        let dst = &mut ret;\n\n        write_magic_marker(dst);\n        dst.push(CURRENT_ENCODED_DEP_INFO_VERSION);\n\n        write_usize(dst, self.files.len());\n        for (ty, file, checksum_info) in self.files.iter() {\n            match ty {\n                DepInfoPathType::PackageRootRelative => dst.push(0),\n                DepInfoPathType::BuildRootRelative => dst.push(1),\n            }\n            write_bytes(dst, paths::path2bytes(file)?);\n            write_bool(dst, checksum_info.is_some());\n            if let Some((len, checksum)) = checksum_info {\n                write_u64(dst, *len);\n                write_bytes(dst, checksum);\n            }\n        }\n\n        write_usize(dst, self.env.len());\n        for (key, val) in self.env.iter() {\n            write_bytes(dst, key);\n            match val {\n                None => dst.push(0),\n                Some(val) => {\n                    dst.push(1);\n                    write_bytes(dst, val);\n                }\n            }\n        }\n        return Ok(ret);\n\n        /// See [`EncodedDepInfo`] for why a magic marker exists.\n        ///\n        /// There is an assumption that there is always at least a file.\n        fn write_magic_marker(dst: &mut Vec<u8>) {\n            write_usize(dst, 1);\n            dst.push(u8::MAX);\n        }\n\n        fn write_bytes(dst: &mut Vec<u8>, val: impl AsRef<[u8]>) {\n            let val = val.as_ref();\n            write_usize(dst, val.len());\n            dst.extend_from_slice(val);\n        }\n\n        fn write_usize(dst: &mut Vec<u8>, val: usize) {\n            dst.extend(&u32::to_le_bytes(val as u32));\n        }\n\n        fn write_u64(dst: &mut Vec<u8>, val: u64) {\n            dst.extend(&u64::to_le_bytes(val));\n        }\n\n        fn write_bool(dst: &mut Vec<u8>, val: bool) {\n            dst.push(u8::from(val));\n        }\n    }\n}\n\n/// Parses the dep-info file coming out of rustc into a Cargo-specific format.\n///\n/// This function will parse `rustc_dep_info` as a makefile-style dep info to\n/// learn about the all files which a crate depends on. This is then\n/// re-serialized into the `cargo_dep_info` path in a Cargo-specific format.\n///\n/// The `pkg_root` argument here is the absolute path to the directory\n/// containing `Cargo.toml` for this crate that was compiled. The paths listed\n/// in the rustc dep-info file may or may not be absolute but we'll want to\n/// consider all of them relative to the `root` specified.\n///\n/// The `rustc_cwd` argument is the absolute path to the cwd of the compiler\n/// when it was invoked.\n///\n/// If the `allow_package` argument is true, then package-relative paths are\n/// included. If it is false, then package-relative paths are skipped and\n/// ignored (typically used for registry or git dependencies where we assume\n/// the source never changes, and we don't want the cost of running `stat` on\n/// all those files). See the module-level docs for the note about\n/// `-Zbinary-dep-depinfo` for more details on why this is done.\n///\n/// The serialized Cargo format will contain a list of files, all of which are\n/// relative if they're under `root`. or absolute if they're elsewhere.\n///\n/// The `env_config` argument is a set of environment variables that are\n/// defined in `[env]` table of the `config.toml`.\npub fn translate_dep_info(\n    rustc_dep_info: &Path,\n    cargo_dep_info: &Path,\n    rustc_cwd: &Path,\n    pkg_root: &Path,\n    build_root: &Path,\n    rustc_cmd: &ProcessBuilder,\n    allow_package: bool,\n    env_config: &Arc<HashMap<String, OsString>>,\n) -> CargoResult<()> {\n    let depinfo = parse_rustc_dep_info(rustc_dep_info)?;\n\n    let build_root = crate::util::try_canonicalize(build_root)?;\n    let pkg_root = crate::util::try_canonicalize(pkg_root)?;\n    let mut on_disk_info = EncodedDepInfo::default();\n    on_disk_info.env = depinfo.env;\n\n    // This is a bit of a tricky statement, but here we're *removing* the\n    // dependency on environment variables that were defined specifically for\n    // the command itself. Environment variables returned by `get_envs` includes\n    // environment variables like:\n    //\n    // * `OUT_DIR` if applicable\n    // * env vars added by a build script, if any\n    //\n    // The general idea here is that the dep info file tells us what, when\n    // changed, should cause us to rebuild the crate. These environment\n    // variables are synthesized by Cargo and/or the build script, and the\n    // intention is that their values are tracked elsewhere for whether the\n    // crate needs to be rebuilt.\n    //\n    // For example a build script says when it needs to be rerun and otherwise\n    // it's assumed to produce the same output, so we're guaranteed that env\n    // vars defined by the build script will always be the same unless the build\n    // script itself reruns, in which case the crate will rerun anyway.\n    //\n    // For things like `OUT_DIR` it's a bit sketchy for now. Most of the time\n    // that's used for code generation but this is technically buggy where if\n    // you write a binary that does `println!(\"{}\", env!(\"OUT_DIR\"))` we won't\n    // recompile that if you move the target directory. Hopefully that's not too\n    // bad of an issue for now...\n    //\n    // This also includes `CARGO` since if the code is explicitly wanting to\n    // know that path, it should be rebuilt if it changes. The CARGO path is\n    // not tracked elsewhere in the fingerprint.\n    //\n    // For cargo#13280, We trace env vars that are defined in the `[env]` config table.\n    on_disk_info.env.retain(|(key, _)| {\n        ManifestMetadata::should_track(key)\n            || env_config.contains_key(key)\n            || !rustc_cmd.get_envs().contains_key(key)\n            || key == CARGO_ENV\n    });\n\n    let serialize_path = |file| {\n        // The path may be absolute or relative, canonical or not. Make sure\n        // it is canonicalized so we are comparing the same kinds of paths.\n        let abs_file = rustc_cwd.join(file);\n        // If canonicalization fails, just use the abs path. There is currently\n        // a bug where --remap-path-prefix is affecting .d files, causing them\n        // to point to non-existent paths.\n        let canon_file =\n            crate::util::try_canonicalize(&abs_file).unwrap_or_else(|_| abs_file.clone());\n\n        let (ty, path) = if let Ok(stripped) = canon_file.strip_prefix(&build_root) {\n            (DepInfoPathType::BuildRootRelative, stripped)\n        } else if let Ok(stripped) = canon_file.strip_prefix(&pkg_root) {\n            if !allow_package {\n                return None;\n            }\n            (DepInfoPathType::PackageRootRelative, stripped)\n        } else {\n            // It's definitely not target root relative, but this is an absolute path (since it was\n            // joined to rustc_cwd) and as such re-joining it later to the target root will have no\n            // effect.\n            (DepInfoPathType::BuildRootRelative, &*abs_file)\n        };\n        Some((ty, path.to_owned()))\n    };\n\n    for (file, checksum_info) in depinfo.files {\n        let Some((path_type, path)) = serialize_path(file) else {\n            continue;\n        };\n        on_disk_info.files.push((\n            path_type,\n            path,\n            checksum_info.map(|(len, checksum)| (len, checksum.to_string())),\n        ));\n    }\n    paths::write(cargo_dep_info, on_disk_info.serialize()?)?;\n    Ok(())\n}\n\n/// Parse the `.d` dep-info file generated by rustc.\npub fn parse_rustc_dep_info(rustc_dep_info: &Path) -> CargoResult<RustcDepInfo> {\n    let contents = paths::read(rustc_dep_info)?;\n    let mut ret = RustcDepInfo::default();\n    let mut found_deps = false;\n\n    for line in contents.lines() {\n        if let Some(rest) = line.strip_prefix(\"# env-dep:\") {\n            let mut parts = rest.splitn(2, '=');\n            let Some(env_var) = parts.next() else {\n                continue;\n            };\n            let env_val = match parts.next() {\n                Some(s) => Some(unescape_env(s)?),\n                None => None,\n            };\n            ret.env.push((unescape_env(env_var)?, env_val));\n        } else if let Some(pos) = line.find(\": \") {\n            if found_deps {\n                continue;\n            }\n            found_deps = true;\n            let mut deps = line[pos + 2..].split_whitespace();\n\n            while let Some(s) = deps.next() {\n                let mut file = s.to_string();\n                while file.ends_with('\\\\') {\n                    file.pop();\n                    file.push(' ');\n                    file.push_str(deps.next().ok_or_else(|| {\n                        crate::util::internal(\"malformed dep-info format, trailing \\\\\")\n                    })?);\n                }\n                ret.files.entry(file.into()).or_default();\n            }\n        } else if let Some(rest) = line.strip_prefix(\"# checksum:\") {\n            let mut parts = rest.splitn(3, ' ');\n            let Some(checksum) = parts.next().map(Checksum::from_str).transpose()? else {\n                continue;\n            };\n            let Some(Ok(file_len)) = parts\n                .next()\n                .and_then(|s| s.strip_prefix(\"file_len:\").map(|s| s.parse::<u64>()))\n            else {\n                continue;\n            };\n            let Some(path) = parts.next().map(PathBuf::from) else {\n                continue;\n            };\n\n            ret.files.insert(path, Some((file_len, checksum)));\n        }\n    }\n    return Ok(ret);\n\n    // rustc tries to fit env var names and values all on a single line, which\n    // means it needs to escape `\\r` and `\\n`. The escape syntax used is \"\\n\"\n    // which means that `\\` also needs to be escaped.\n    fn unescape_env(s: &str) -> CargoResult<String> {\n        let mut ret = String::with_capacity(s.len());\n        let mut chars = s.chars();\n        while let Some(c) = chars.next() {\n            if c != '\\\\' {\n                ret.push(c);\n                continue;\n            }\n            match chars.next() {\n                Some('\\\\') => ret.push('\\\\'),\n                Some('n') => ret.push('\\n'),\n                Some('r') => ret.push('\\r'),\n                Some(c) => bail!(\"unknown escape character `{}`\", c),\n                None => bail!(\"unterminated escape character\"),\n            }\n        }\n        Ok(ret)\n    }\n}\n\n/// Parses Cargo's internal [`EncodedDepInfo`] structure that was previously\n/// serialized to disk.\n///\n/// Note that this is not rustc's `*.d` files.\n///\n/// Also note that rustc's `*.d` files are translated to Cargo-specific\n/// `EncodedDepInfo` files after compilations have finished in\n/// [`translate_dep_info`].\n///\n/// Returns `None` if the file is corrupt or couldn't be read from disk. This\n/// indicates that the crate should likely be rebuilt.\npub fn parse_dep_info(\n    pkg_root: &Path,\n    build_root: &Path,\n    dep_info: &Path,\n) -> CargoResult<Option<RustcDepInfo>> {\n    let Ok(data) = paths::read_bytes(dep_info) else {\n        return Ok(None);\n    };\n    let Some(info) = EncodedDepInfo::parse(&data) else {\n        tracing::warn!(\"failed to parse cargo's dep-info at {:?}\", dep_info);\n        return Ok(None);\n    };\n    let mut ret = RustcDepInfo::default();\n    ret.env = info.env;\n    ret.files\n        .extend(info.files.into_iter().map(|(ty, path, checksum_info)| {\n            (\n                make_absolute_path(ty, pkg_root, build_root, path),\n                checksum_info.and_then(|(file_len, checksum)| {\n                    Checksum::from_str(&checksum).ok().map(|c| (file_len, c))\n                }),\n            )\n        }));\n    Ok(Some(ret))\n}\n\nfn make_absolute_path(\n    ty: DepInfoPathType,\n    pkg_root: &Path,\n    build_root: &Path,\n    path: PathBuf,\n) -> PathBuf {\n    let relative_to = match ty {\n        DepInfoPathType::PackageRootRelative => pkg_root,\n        // N.B. path might be absolute here in which case the join below will have no effect\n        DepInfoPathType::BuildRootRelative => build_root,\n    };\n\n    if path.as_os_str().is_empty() {\n        // Joining with an empty path causes Rust to add a trailing path separator. On Windows, this\n        // would add an invalid trailing backslash to the .d file.\n        return relative_to.to_path_buf();\n    }\n\n    relative_to.join(path)\n}\n\n/// Some algorithms are here to ensure compatibility with possible rustc outputs.\n/// The presence of an algorithm here is not a suggestion that it's fit for use.\n#[derive(Copy, Clone, Debug, Eq, PartialEq)]\npub enum ChecksumAlgo {\n    Sha256,\n    Blake3,\n}\n\nimpl ChecksumAlgo {\n    fn hash_len(&self) -> usize {\n        match self {\n            ChecksumAlgo::Sha256 | ChecksumAlgo::Blake3 => 32,\n        }\n    }\n}\n\nimpl FromStr for ChecksumAlgo {\n    type Err = InvalidChecksum;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        match s {\n            \"sha256\" => Ok(Self::Sha256),\n            \"blake3\" => Ok(Self::Blake3),\n            _ => Err(InvalidChecksum::InvalidChecksumAlgo),\n        }\n    }\n}\n\nimpl fmt::Display for ChecksumAlgo {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(match self {\n            ChecksumAlgo::Sha256 => \"sha256\",\n            ChecksumAlgo::Blake3 => \"blake3\",\n        })\n    }\n}\n\n#[derive(Copy, Clone, Debug, Eq, PartialEq)]\npub struct Checksum {\n    algo: ChecksumAlgo,\n    /// If the algorithm uses fewer than 32 bytes, then the remaining bytes will be zero.\n    value: [u8; 32],\n}\n\nimpl Checksum {\n    pub fn new(algo: ChecksumAlgo, value: [u8; 32]) -> Self {\n        Self { algo, value }\n    }\n\n    pub fn compute(algo: ChecksumAlgo, contents: impl Read) -> Result<Self, io::Error> {\n        // Buffer size is the recommended amount to fully leverage SIMD instructions on AVX-512 as per\n        // blake3 documentation.\n        let mut buf = vec![0; 16 * 1024];\n        let mut ret = Self {\n            algo,\n            value: [0; 32],\n        };\n        let len = algo.hash_len();\n        let value = &mut ret.value[..len];\n\n        fn digest<T>(\n            mut hasher: T,\n            mut update: impl FnMut(&mut T, &[u8]),\n            finish: impl FnOnce(T, &mut [u8]),\n            mut contents: impl Read,\n            buf: &mut [u8],\n            value: &mut [u8],\n        ) -> Result<(), io::Error> {\n            loop {\n                let bytes_read = contents.read(buf)?;\n                if bytes_read == 0 {\n                    break;\n                }\n                update(&mut hasher, &buf[0..bytes_read]);\n            }\n            finish(hasher, value);\n            Ok(())\n        }\n\n        match algo {\n            ChecksumAlgo::Sha256 => {\n                digest(\n                    Sha256::new(),\n                    |h, b| {\n                        h.update(b);\n                    },\n                    |mut h, out| out.copy_from_slice(&h.finish()),\n                    contents,\n                    &mut buf,\n                    value,\n                )?;\n            }\n            ChecksumAlgo::Blake3 => {\n                digest(\n                    blake3::Hasher::new(),\n                    |h, b| {\n                        h.update(b);\n                    },\n                    |h, out| out.copy_from_slice(h.finalize().as_bytes()),\n                    contents,\n                    &mut buf,\n                    value,\n                )?;\n            }\n        }\n        Ok(ret)\n    }\n\n    pub fn algo(&self) -> ChecksumAlgo {\n        self.algo\n    }\n\n    pub fn value(&self) -> &[u8; 32] {\n        &self.value\n    }\n}\n\nimpl FromStr for Checksum {\n    type Err = InvalidChecksum;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        let mut parts = s.split('=');\n        let Some(algo) = parts.next().map(ChecksumAlgo::from_str).transpose()? else {\n            return Err(InvalidChecksum::InvalidFormat);\n        };\n        let Some(checksum) = parts.next() else {\n            return Err(InvalidChecksum::InvalidFormat);\n        };\n        let mut value = [0; 32];\n        if hex::decode_to_slice(checksum, &mut value[0..algo.hash_len()]).is_err() {\n            return Err(InvalidChecksum::InvalidChecksum(algo));\n        }\n        Ok(Self { algo, value })\n    }\n}\n\nimpl fmt::Display for Checksum {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let mut checksum = [0; 64];\n        let hash_len = self.algo.hash_len();\n        hex::encode_to_slice(&self.value[0..hash_len], &mut checksum[0..(hash_len * 2)])\n            .map_err(|_| fmt::Error)?;\n        write!(\n            f,\n            \"{}={}\",\n            self.algo,\n            str::from_utf8(&checksum[0..(hash_len * 2)]).unwrap_or_default()\n        )\n    }\n}\n\nimpl Serialize for Checksum {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: serde::Serializer,\n    {\n        serializer.serialize_str(&self.to_string())\n    }\n}\n\nimpl<'de> serde::Deserialize<'de> for Checksum {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        let s = String::deserialize(deserializer)?;\n        s.parse().map_err(serde::de::Error::custom)\n    }\n}\n\n#[derive(Debug, thiserror::Error)]\npub enum InvalidChecksum {\n    #[error(\"algorithm portion incorrect, expected `sha256`, or `blake3`\")]\n    InvalidChecksumAlgo,\n    #[error(\"expected {} hexadecimal digits in checksum portion\", .0.hash_len() * 2)]\n    InvalidChecksum(ChecksumAlgo),\n    #[error(\"expected a string with format \\\"algorithm=hex_checksum\\\"\")]\n    InvalidFormat,\n}\n\n#[cfg(test)]\nmod encoded_dep_info {\n    use super::*;\n\n    #[track_caller]\n    fn gen_test(checksum: bool) {\n        let checksum = checksum.then_some((768, \"c01efc669f09508b55eced32d3c88702578a7c3e\".into()));\n        let lib_rs = (\n            DepInfoPathType::BuildRootRelative,\n            PathBuf::from(\"src/lib.rs\"),\n            checksum.clone(),\n        );\n\n        let depinfo = EncodedDepInfo {\n            files: vec![lib_rs.clone()],\n            env: Vec::new(),\n        };\n        let data = depinfo.serialize().unwrap();\n        assert_eq!(EncodedDepInfo::parse(&data).unwrap(), depinfo);\n\n        let mod_rs = (\n            DepInfoPathType::BuildRootRelative,\n            PathBuf::from(\"src/mod.rs\"),\n            checksum.clone(),\n        );\n        let depinfo = EncodedDepInfo {\n            files: vec![lib_rs.clone(), mod_rs.clone()],\n            env: Vec::new(),\n        };\n        let data = depinfo.serialize().unwrap();\n        assert_eq!(EncodedDepInfo::parse(&data).unwrap(), depinfo);\n\n        let depinfo = EncodedDepInfo {\n            files: vec![lib_rs, mod_rs],\n            env: vec![\n                (\"Gimli\".into(), Some(\"Legolas\".into())),\n                (\"Beren\".into(), Some(\"Lúthien\".into())),\n            ],\n        };\n        let data = depinfo.serialize().unwrap();\n        assert_eq!(EncodedDepInfo::parse(&data).unwrap(), depinfo);\n    }\n\n    #[test]\n    fn round_trip() {\n        gen_test(false);\n    }\n\n    #[test]\n    fn round_trip_with_checksums() {\n        gen_test(true);\n    }\n\n    #[test]\n    fn path_type_is_u8_max() {\n        #[rustfmt::skip]\n        let data = [\n            0x01, 0x00, 0x00, 0x00, 0xff,       // magic marker\n            CURRENT_ENCODED_DEP_INFO_VERSION,   // version\n            0x01, 0x00, 0x00, 0x00,             // # of files\n            0x00,                               // path type\n            0x04, 0x00, 0x00, 0x00,             // len of path\n            0x72, 0x75, 0x73, 0x74,             // path bytes (\"rust\")\n            0x00,                               // cksum exists?\n            0x00, 0x00, 0x00, 0x00,             // # of env vars\n        ];\n        // The current cargo doesn't recognize the magic marker.\n        assert_eq!(\n            EncodedDepInfo::parse(&data).unwrap(),\n            EncodedDepInfo {\n                files: vec![(DepInfoPathType::PackageRootRelative, \"rust\".into(), None)],\n                env: Vec::new(),\n            }\n        );\n    }\n\n    #[test]\n    fn parse_v0_fingerprint_dep_info() {\n        #[rustfmt::skip]\n        let data = [\n            0x01, 0x00, 0x00, 0x00, // # of files\n            0x00,                   // path type\n            0x04, 0x00, 0x00, 0x00, // len of path\n            0x72, 0x75, 0x73, 0x74, // path bytes: \"rust\"\n            0x00, 0x00, 0x00, 0x00, // # of env vars\n        ];\n        // Cargo can't recognize v0 after `-Zchecksum-freshness` added.\n        assert!(EncodedDepInfo::parse(&data).is_none());\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/fingerprint/dirty_reason.rs",
    "content": "use std::collections::HashMap;\nuse std::fmt;\nuse std::fmt::Debug;\n\nuse serde::Serialize;\n\nuse super::*;\nuse crate::core::Shell;\nuse crate::core::compiler::UnitIndex;\n\n/// Tells a better story of why a build is considered \"dirty\" that leads\n/// to a recompile. Usually constructed via [`Fingerprint::compare`].\n///\n/// [`Fingerprint::compare`]: super::Fingerprint::compare\n#[derive(Clone, Debug, Serialize, Deserialize)]\n#[serde(tag = \"dirty_reason\", rename_all = \"kebab-case\")]\npub enum DirtyReason {\n    RustcChanged,\n    FeaturesChanged {\n        old: String,\n        new: String,\n    },\n    DeclaredFeaturesChanged {\n        old: String,\n        new: String,\n    },\n    TargetConfigurationChanged,\n    PathToSourceChanged,\n    ProfileConfigurationChanged,\n    RustflagsChanged {\n        old: Vec<String>,\n        new: Vec<String>,\n    },\n    ConfigSettingsChanged,\n    CompileKindChanged,\n    LocalLengthsChanged,\n    PrecalculatedComponentsChanged {\n        old: String,\n        new: String,\n    },\n    ChecksumUseChanged {\n        old: bool,\n    },\n    DepInfoOutputChanged {\n        old: PathBuf,\n        new: PathBuf,\n    },\n    RerunIfChangedOutputFileChanged {\n        old: PathBuf,\n        new: PathBuf,\n    },\n    RerunIfChangedOutputPathsChanged {\n        old: Vec<PathBuf>,\n        new: Vec<PathBuf>,\n    },\n    EnvVarsChanged {\n        old: String,\n        new: String,\n    },\n    EnvVarChanged {\n        name: String,\n        old_value: Option<String>,\n        new_value: Option<String>,\n    },\n    LocalFingerprintTypeChanged {\n        old: String,\n        new: String,\n    },\n    NumberOfDependenciesChanged {\n        old: usize,\n        new: usize,\n    },\n    UnitDependencyNameChanged {\n        old: InternedString,\n        new: InternedString,\n    },\n    UnitDependencyInfoChanged {\n        unit: UnitIndex,\n    },\n    FsStatusOutdated(FsStatus),\n    NothingObvious,\n    Forced,\n    /// First time to build something.\n    FreshBuild,\n}\n\ntrait ShellExt {\n    fn dirty_because(&mut self, unit: &Unit, s: impl fmt::Display) -> CargoResult<()>;\n}\n\nimpl ShellExt for Shell {\n    fn dirty_because(&mut self, unit: &Unit, s: impl fmt::Display) -> CargoResult<()> {\n        self.status(\"Dirty\", format_args!(\"{}: {s}\", &unit.pkg))\n    }\n}\n\nstruct FileTimeDiff {\n    old_time: FileTime,\n    new_time: FileTime,\n}\n\nimpl fmt::Display for FileTimeDiff {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let s_diff = self.new_time.seconds() - self.old_time.seconds();\n        if s_diff >= 1 {\n            write!(f, \"{:#}\", jiff::SignedDuration::from_secs(s_diff))\n        } else {\n            // format nanoseconds as it is, jiff would display ms, us and ns\n            let ns_diff = self.new_time.nanoseconds() - self.old_time.nanoseconds();\n            write!(f, \"{ns_diff}ns\")\n        }\n    }\n}\n\n#[derive(Copy, Clone)]\nstruct After {\n    old_time: FileTime,\n    new_time: FileTime,\n    what: &'static str,\n}\n\nimpl fmt::Display for After {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let Self {\n            old_time,\n            new_time,\n            what,\n        } = *self;\n        let diff = FileTimeDiff { old_time, new_time };\n\n        write!(f, \"{new_time}, {diff} after {what} at {old_time}\")\n    }\n}\n\nimpl DirtyReason {\n    /// Whether a build is dirty because it is a fresh build being kicked off.\n    pub fn is_fresh_build(&self) -> bool {\n        matches!(self, DirtyReason::FreshBuild)\n    }\n\n    fn after(old_time: FileTime, new_time: FileTime, what: &'static str) -> After {\n        After {\n            old_time,\n            new_time,\n            what,\n        }\n    }\n\n    pub fn present_to(\n        &self,\n        s: &mut Shell,\n        unit: &Unit,\n        root: &Path,\n        index_to_unit: &HashMap<UnitIndex, Unit>,\n    ) -> CargoResult<()> {\n        match self {\n            DirtyReason::RustcChanged => s.dirty_because(unit, \"the toolchain changed\"),\n            DirtyReason::FeaturesChanged { .. } => {\n                s.dirty_because(unit, \"the list of features changed\")\n            }\n            DirtyReason::DeclaredFeaturesChanged { .. } => {\n                s.dirty_because(unit, \"the list of declared features changed\")\n            }\n            DirtyReason::TargetConfigurationChanged => {\n                s.dirty_because(unit, \"the target configuration changed\")\n            }\n            DirtyReason::PathToSourceChanged => {\n                s.dirty_because(unit, \"the path to the source changed\")\n            }\n            DirtyReason::ProfileConfigurationChanged => {\n                s.dirty_because(unit, \"the profile configuration changed\")\n            }\n            DirtyReason::RustflagsChanged { .. } => s.dirty_because(unit, \"the rustflags changed\"),\n            DirtyReason::ConfigSettingsChanged => {\n                s.dirty_because(unit, \"the config settings changed\")\n            }\n            DirtyReason::CompileKindChanged => {\n                s.dirty_because(unit, \"the rustc compile kind changed\")\n            }\n            DirtyReason::LocalLengthsChanged => {\n                s.dirty_because(unit, \"the local lengths changed\")?;\n                s.note(\n                    \"this could happen because of added/removed `cargo::rerun-if` instructions in the build script\",\n                )?;\n\n                Ok(())\n            }\n            DirtyReason::PrecalculatedComponentsChanged { .. } => {\n                s.dirty_because(unit, \"the precalculated components changed\")\n            }\n            DirtyReason::ChecksumUseChanged { old } => {\n                if *old {\n                    s.dirty_because(\n                        unit,\n                        \"the prior compilation used checksum freshness and this one does not\",\n                    )\n                } else {\n                    s.dirty_because(unit, \"checksum freshness requested, prior compilation did not use checksum freshness\")\n                }\n            }\n            DirtyReason::DepInfoOutputChanged { .. } => {\n                s.dirty_because(unit, \"the dependency info output changed\")\n            }\n            DirtyReason::RerunIfChangedOutputFileChanged { .. } => {\n                s.dirty_because(unit, \"rerun-if-changed output file path changed\")\n            }\n            DirtyReason::RerunIfChangedOutputPathsChanged { .. } => {\n                s.dirty_because(unit, \"the rerun-if-changed instructions changed\")\n            }\n            DirtyReason::EnvVarsChanged { .. } => {\n                s.dirty_because(unit, \"the environment variables changed\")\n            }\n            DirtyReason::EnvVarChanged { name, .. } => {\n                s.dirty_because(unit, format_args!(\"the env variable {name} changed\"))\n            }\n            DirtyReason::LocalFingerprintTypeChanged { .. } => {\n                s.dirty_because(unit, \"the local fingerprint type changed\")\n            }\n            DirtyReason::NumberOfDependenciesChanged { old, new } => s.dirty_because(\n                unit,\n                format_args!(\"number of dependencies changed ({old} => {new})\",),\n            ),\n            DirtyReason::UnitDependencyNameChanged { old, new } => s.dirty_because(\n                unit,\n                format_args!(\"name of dependency changed ({old} => {new})\"),\n            ),\n            DirtyReason::UnitDependencyInfoChanged { unit: dep_unit } => {\n                let dep_name = index_to_unit.get(dep_unit).map(|u| u.pkg.name()).unwrap();\n                s.dirty_because(\n                    unit,\n                    format_args!(\"info of dependency `{dep_name}` changed\"),\n                )\n            }\n            DirtyReason::FsStatusOutdated(status) => match status {\n                FsStatus::Stale => s.dirty_because(unit, \"stale, unknown reason\"),\n                FsStatus::StaleItem(item) => match item {\n                    StaleItem::MissingFile { path } => {\n                        let file = path.strip_prefix(root).unwrap_or(&path);\n                        s.dirty_because(\n                            unit,\n                            format_args!(\"the file `{}` is missing\", file.display()),\n                        )\n                    }\n                    StaleItem::UnableToReadFile { path } => {\n                        let file = path.strip_prefix(root).unwrap_or(&path);\n                        s.dirty_because(\n                            unit,\n                            format_args!(\"the file `{}` could not be read\", file.display()),\n                        )\n                    }\n                    StaleItem::FailedToReadMetadata { path } => {\n                        let file = path.strip_prefix(root).unwrap_or(&path);\n                        s.dirty_because(\n                            unit,\n                            format_args!(\"couldn't read metadata for file `{}`\", file.display()),\n                        )\n                    }\n                    StaleItem::ChangedFile {\n                        stale,\n                        stale_mtime,\n                        reference_mtime,\n                        ..\n                    } => {\n                        let file = stale.strip_prefix(root).unwrap_or(&stale);\n                        let after = Self::after(*reference_mtime, *stale_mtime, \"last build\");\n                        s.dirty_because(\n                            unit,\n                            format_args!(\"the file `{}` has changed ({after})\", file.display()),\n                        )\n                    }\n                    StaleItem::ChangedChecksum {\n                        source,\n                        stored_checksum,\n                        new_checksum,\n                    } => {\n                        let file = source.strip_prefix(root).unwrap_or(&source);\n                        s.dirty_because(\n                            unit,\n                            format_args!(\n                                \"the file `{}` has changed (checksum didn't match, {stored_checksum} != {new_checksum})\",\n                                file.display(),\n                            ),\n                        )\n                    }\n                    StaleItem::FileSizeChanged {\n                        path,\n                        old_size,\n                        new_size,\n                    } => {\n                        let file = path.strip_prefix(root).unwrap_or(&path);\n                        s.dirty_because(\n                            unit,\n                            format_args!(\n                                \"file size changed ({old_size} != {new_size}) for `{}`\",\n                                file.display()\n                            ),\n                        )\n                    }\n                    StaleItem::MissingChecksum { path } => {\n                        let file = path.strip_prefix(root).unwrap_or(&path);\n                        s.dirty_because(\n                            unit,\n                            format_args!(\"the checksum for file `{}` is missing\", file.display()),\n                        )\n                    }\n                    StaleItem::ChangedEnv { var, .. } => s.dirty_because(\n                        unit,\n                        format_args!(\"the environment variable {var} changed\"),\n                    ),\n                },\n                FsStatus::StaleDependency {\n                    unit: dep_unit,\n                    dep_mtime,\n                    max_mtime,\n                } => {\n                    let dep_name = index_to_unit.get(dep_unit).map(|u| u.pkg.name()).unwrap();\n                    let after = Self::after(*max_mtime, *dep_mtime, \"last build\");\n                    s.dirty_because(\n                        unit,\n                        format_args!(\"the dependency `{dep_name}` was rebuilt ({after})\"),\n                    )\n                }\n                FsStatus::StaleDepFingerprint { unit: dep_unit } => {\n                    let dep_name = index_to_unit.get(dep_unit).map(|u| u.pkg.name()).unwrap();\n                    s.dirty_because(\n                        unit,\n                        format_args!(\"the dependency `{dep_name}` was rebuilt\"),\n                    )\n                }\n                FsStatus::UpToDate { .. } => {\n                    unreachable!()\n                }\n            },\n            DirtyReason::NothingObvious => {\n                // See comment in fingerprint compare method.\n                s.dirty_because(unit, \"the fingerprint comparison turned up nothing obvious\")\n            }\n            DirtyReason::Forced => s.dirty_because(unit, \"forced\"),\n            DirtyReason::FreshBuild => s.dirty_because(unit, \"fresh build\"),\n        }\n    }\n}\n\n// These test the actual JSON structure that will be logged.\n// In the future we might decouple this from the actual log message schema.\n#[cfg(test)]\nmod json_schema {\n    use super::*;\n    use snapbox::IntoData;\n    use snapbox::assert_data_eq;\n    use snapbox::str;\n\n    fn to_json<T: Serialize>(value: &T) -> String {\n        serde_json::to_string_pretty(value).unwrap()\n    }\n\n    #[test]\n    fn rustc_changed() {\n        let reason = DirtyReason::RustcChanged;\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"rustc-changed\"\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn fresh_build() {\n        let reason = DirtyReason::FreshBuild;\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"fresh-build\"\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn forced() {\n        let reason = DirtyReason::Forced;\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"forced\"\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn nothing_obvious() {\n        let reason = DirtyReason::NothingObvious;\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"nothing-obvious\"\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn features_changed() {\n        let reason = DirtyReason::FeaturesChanged {\n            old: \"f1\".to_string(),\n            new: \"f1,f2\".to_string(),\n        };\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"features-changed\",\n  \"new\": \"f1,f2\",\n  \"old\": \"f1\"\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn rustflags_changed() {\n        let reason = DirtyReason::RustflagsChanged {\n            old: vec![\"-C\".into(), \"opt-level=2\".into()],\n            new: vec![\"--cfg\".into(), \"tokio_unstable\".into()],\n        };\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"rustflags-changed\",\n  \"old\": [\n    \"-C\",\n    \"opt-level=2\"\n  ],\n  \"new\": [\n    \"--cfg\",\n    \"tokio_unstable\"\n  ]\n}\n\"#]]\n        );\n    }\n\n    #[test]\n    fn env_var_changed_both_some() {\n        let reason = DirtyReason::EnvVarChanged {\n            name: \"VAR\".into(),\n            old_value: Some(\"old\".into()),\n            new_value: Some(\"new\".into()),\n        };\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"env-var-changed\",\n  \"name\": \"VAR\",\n  \"new_value\": \"new\",\n  \"old_value\": \"old\"\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn env_var_changed_old_none() {\n        let reason = DirtyReason::EnvVarChanged {\n            name: \"VAR\".into(),\n            old_value: None,\n            new_value: Some(\"new\".into()),\n        };\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"env-var-changed\",\n  \"name\": \"VAR\",\n  \"new_value\": \"new\",\n  \"old_value\": null\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn dep_info_output_changed() {\n        let reason = DirtyReason::DepInfoOutputChanged {\n            old: \"target/debug/old.d\".into(),\n            new: \"target/debug/new.d\".into(),\n        };\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"dep-info-output-changed\",\n  \"old\": \"target/debug/old.d\",\n  \"new\": \"target/debug/new.d\"\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn number_of_dependencies_changed() {\n        let reason = DirtyReason::NumberOfDependenciesChanged { old: 5, new: 7 };\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"number-of-dependencies-changed\",\n  \"old\": 5,\n  \"new\": 7\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn unit_dependency_name_changed() {\n        let reason = DirtyReason::UnitDependencyNameChanged {\n            old: \"old_dep\".into(),\n            new: \"new_dep\".into(),\n        };\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"unit-dependency-name-changed\",\n  \"new\": \"new_dep\",\n  \"old\": \"old_dep\"\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn unit_dependency_info_changed() {\n        let reason = DirtyReason::UnitDependencyInfoChanged {\n            unit: UnitIndex(15),\n        };\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"unit-dependency-info-changed\",\n  \"unit\": 15\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn fs_status_stale() {\n        let reason = DirtyReason::FsStatusOutdated(FsStatus::Stale);\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"fs-status-outdated\",\n  \"fs_status\": \"stale\"\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn fs_status_missing_file() {\n        let reason = DirtyReason::FsStatusOutdated(FsStatus::StaleItem(StaleItem::MissingFile {\n            path: \"src/lib.rs\".into(),\n        }));\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"fs-status-outdated\",\n  \"fs_status\": \"stale-item\",\n  \"path\": \"src/lib.rs\",\n  \"stale_item\": \"missing-file\"\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn fs_status_changed_file() {\n        let reason = DirtyReason::FsStatusOutdated(FsStatus::StaleItem(StaleItem::ChangedFile {\n            reference: \"target/debug/deps/libfoo-abc123.rmeta\".into(),\n            reference_mtime: FileTime::from_unix_time(1730567890, 123000000),\n            stale: \"src/lib.rs\".into(),\n            stale_mtime: FileTime::from_unix_time(1730567891, 456000000),\n        }));\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"fs-status-outdated\",\n  \"fs_status\": \"stale-item\",\n  \"reference\": \"target/debug/deps/libfoo-abc123.rmeta\",\n  \"reference_mtime\": 1730567890123.0,\n  \"stale\": \"src/lib.rs\",\n  \"stale_item\": \"changed-file\",\n  \"stale_mtime\": 1730567891456.0\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn fs_status_changed_checksum() {\n        use super::dep_info::ChecksumAlgo;\n        let reason =\n            DirtyReason::FsStatusOutdated(FsStatus::StaleItem(StaleItem::ChangedChecksum {\n                source: \"src/main.rs\".into(),\n                stored_checksum: Checksum::new(ChecksumAlgo::Sha256, [0xaa; 32]),\n                new_checksum: Checksum::new(ChecksumAlgo::Sha256, [0xbb; 32]),\n            }));\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"fs-status-outdated\",\n  \"fs_status\": \"stale-item\",\n  \"new_checksum\": \"sha256=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\",\n  \"source\": \"src/main.rs\",\n  \"stale_item\": \"changed-checksum\",\n  \"stored_checksum\": \"sha256=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn fs_status_stale_dependency() {\n        let reason = DirtyReason::FsStatusOutdated(FsStatus::StaleDependency {\n            unit: UnitIndex(42),\n            dep_mtime: FileTime::from_unix_time(1730567892, 789000000),\n            max_mtime: FileTime::from_unix_time(1730567890, 123000000),\n        });\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dep_mtime\": 1730567892789.0,\n  \"dirty_reason\": \"fs-status-outdated\",\n  \"fs_status\": \"stale-dependency\",\n  \"max_mtime\": 1730567890123.0,\n  \"unit\": 42\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn fs_status_stale_dep_fingerprint() {\n        let reason = DirtyReason::FsStatusOutdated(FsStatus::StaleDepFingerprint {\n            unit: UnitIndex(42),\n        });\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"fs-status-outdated\",\n  \"fs_status\": \"stale-dep-fingerprint\",\n  \"unit\": 42\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn fs_status_unable_to_read_file() {\n        let reason =\n            DirtyReason::FsStatusOutdated(FsStatus::StaleItem(StaleItem::UnableToReadFile {\n                path: \"src/lib.rs\".into(),\n            }));\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"fs-status-outdated\",\n  \"fs_status\": \"stale-item\",\n  \"stale_item\": \"unable-to-read-file\",\n  \"path\": \"src/lib.rs\"\n}\n\"#]]\n        );\n    }\n\n    #[test]\n    fn fs_status_failed_to_read_metadata() {\n        let reason =\n            DirtyReason::FsStatusOutdated(FsStatus::StaleItem(StaleItem::FailedToReadMetadata {\n                path: \"src/lib.rs\".into(),\n            }));\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"fs-status-outdated\",\n  \"fs_status\": \"stale-item\",\n  \"stale_item\": \"failed-to-read-metadata\",\n  \"path\": \"src/lib.rs\"\n}\n\"#]]\n        );\n    }\n\n    #[test]\n    fn fs_status_file_size_changed() {\n        let reason =\n            DirtyReason::FsStatusOutdated(FsStatus::StaleItem(StaleItem::FileSizeChanged {\n                path: \"src/lib.rs\".into(),\n                old_size: 1024,\n                new_size: 2048,\n            }));\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"fs-status-outdated\",\n  \"fs_status\": \"stale-item\",\n  \"stale_item\": \"file-size-changed\",\n  \"path\": \"src/lib.rs\",\n  \"old_size\": 1024,\n  \"new_size\": 2048\n}\n\"#]]\n        );\n    }\n\n    #[test]\n    fn fs_status_missing_checksum() {\n        let reason =\n            DirtyReason::FsStatusOutdated(FsStatus::StaleItem(StaleItem::MissingChecksum {\n                path: \"src/lib.rs\".into(),\n            }));\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"fs-status-outdated\",\n  \"fs_status\": \"stale-item\",\n  \"stale_item\": \"missing-checksum\",\n  \"path\": \"src/lib.rs\"\n}\n\"#]]\n        );\n    }\n\n    #[test]\n    fn fs_status_changed_env() {\n        let reason = DirtyReason::FsStatusOutdated(FsStatus::StaleItem(StaleItem::ChangedEnv {\n            var: \"VAR\".into(),\n            previous: Some(\"old\".into()),\n            current: Some(\"new\".into()),\n        }));\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"fs-status-outdated\",\n  \"fs_status\": \"stale-item\",\n  \"stale_item\": \"changed-env\",\n  \"var\": \"VAR\",\n  \"previous\": \"old\",\n  \"current\": \"new\"\n}\n\"#]]\n        );\n    }\n\n    #[test]\n    fn checksum_use_changed() {\n        let reason = DirtyReason::ChecksumUseChanged { old: false };\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"checksum-use-changed\",\n  \"old\": false\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn rerun_if_changed_output_paths_changed() {\n        let reason = DirtyReason::RerunIfChangedOutputPathsChanged {\n            old: vec![\"file1.txt\".into(), \"file2.txt\".into()],\n            new: vec![\"file1.txt\".into(), \"file2.txt\".into(), \"file3.txt\".into()],\n        };\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"rerun-if-changed-output-paths-changed\",\n  \"old\": [\n    \"file1.txt\",\n    \"file2.txt\"\n  ],\n  \"new\": [\n    \"file1.txt\",\n    \"file2.txt\",\n    \"file3.txt\"\n  ]\n}\n\"#]]\n            .is_json()\n        );\n    }\n\n    #[test]\n    fn local_fingerprint_type_changed() {\n        let reason = DirtyReason::LocalFingerprintTypeChanged {\n            old: \"precalculated\".to_owned(),\n            new: \"rerun-if-changed\".to_owned(),\n        };\n        assert_data_eq!(\n            to_json(&reason),\n            str![[r#\"\n{\n  \"dirty_reason\": \"local-fingerprint-type-changed\",\n  \"new\": \"rerun-if-changed\",\n  \"old\": \"precalculated\"\n}\n\"#]]\n            .is_json()\n        );\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/fingerprint/mod.rs",
    "content": "//! Tracks changes to determine if something needs to be recompiled.\n//!\n//! This module implements change-tracking so that Cargo can know whether or\n//! not something needs to be recompiled. A Cargo [`Unit`] can be either \"dirty\"\n//! (needs to be recompiled) or \"fresh\" (it does not need to be recompiled).\n//!\n//! ## Mechanisms affecting freshness\n//!\n//! There are several mechanisms that influence a Unit's freshness:\n//!\n//! - The [`Fingerprint`] is a hash, saved to the filesystem in the\n//!   `.fingerprint` directory, that tracks information about the Unit. If the\n//!   fingerprint is missing (such as the first time the unit is being\n//!   compiled), then the unit is dirty. If any of the fingerprint fields\n//!   change (like the name of the source file), then the Unit is considered\n//!   dirty.\n//!\n//!   The `Fingerprint` also tracks the fingerprints of all its dependencies,\n//!   so a change in a dependency will propagate the \"dirty\" status up.\n//!\n//! - Filesystem mtime tracking is also used to check if a unit is dirty.\n//!   See the section below on \"Mtime comparison\" for more details. There\n//!   are essentially two parts to mtime tracking:\n//!\n//!   1. The mtime of a Unit's output files is compared to the mtime of all\n//!      its dependencies' output file mtimes (see\n//!      [`check_filesystem`]). If any output is missing, or is\n//!      older than a dependency's output, then the unit is dirty.\n//!   2. The mtime of a Unit's source files is compared to the mtime of its\n//!      dep-info file in the fingerprint directory (see [`find_stale_file`]).\n//!      The dep-info file is used as an anchor to know when the last build of\n//!      the unit was done. See the \"dep-info files\" section below for more\n//!      details. If any input files are missing, or are newer than the\n//!      dep-info, then the unit is dirty.\n//!\n//!  - Alternatively if you're using the unstable feature `checksum-freshness`\n//!    mtimes are ignored entirely in favor of comparing first the file size, and\n//!    then the checksum with a known prior value emitted by rustc. Only nightly\n//!    rustc will emit the needed metadata at the time of writing. This is dependent\n//!    on the unstable feature `-Z checksum-hash-algorithm`.\n//!\n//! Note: Fingerprinting is not a perfect solution. Filesystem mtime tracking\n//! is notoriously imprecise and problematic. Only a small part of the\n//! environment is captured. This is a balance of performance, simplicity, and\n//! completeness. Sandboxing, hashing file contents, tracking every file\n//! access, environment variable, and network operation would ensure more\n//! reliable and reproducible builds at the cost of being complex, slow, and\n//! platform-dependent.\n//!\n//! ## Fingerprints and [`UnitHash`]s\n//!\n//! [`Metadata`] tracks several [`UnitHash`]s, including\n//! [`Metadata::unit_id`], [`Metadata::c_metadata`], and [`Metadata::c_extra_filename`].\n//! See its documentation for more details.\n//!\n//! NOTE: Not all output files are isolated via filename hashes (like dylibs).\n//! The fingerprint directory uses a hash, but sometimes units share the same\n//! fingerprint directory (when they don't have Metadata) so care should be\n//! taken to handle this!\n//!\n//! Fingerprints and [`UnitHash`]s are similar, and track some of the same things.\n//! [`UnitHash`]s contains information that is required to keep Units separate.\n//! The Fingerprint includes additional information that should cause a\n//! recompile, but it is desired to reuse the same filenames. A comparison\n//! of what is tracked:\n//!\n//! Value                                      | Fingerprint | `Metadata::unit_id` [^8] | `Metadata::c_metadata`\n//! -------------------------------------------|-------------|--------------------------|-----------------------\n//! rustc                                      | ✓           | ✓                        | ✓\n//! [`Profile`]                                | ✓           | ✓                        | ✓\n//! `cargo rustc` extra args                   | ✓           | ✓[^7]                    |\n//! [`CompileMode`]                            | ✓           | ✓                        | ✓\n//! Target Name                                | ✓           | ✓                        | ✓\n//! `TargetKind` (bin/lib/etc.)                | ✓           | ✓                        | ✓\n//! Enabled Features                           | ✓           | ✓                        | ✓\n//! Declared Features                          | ✓           |                          |\n//! Immediate dependency’s hashes              | ✓[^1]       | ✓                        | ✓\n//! [`CompileKind`] (host/target)              | ✓           | ✓                        | ✓\n//! `__CARGO_DEFAULT_LIB_METADATA`[^4]         |             | ✓                        | ✓\n//! `package_id`                               |             | ✓                        | ✓\n//! Target src path relative to ws             | ✓           |                          |\n//! Target flags (test/bench/for_host/edition) | ✓           |                          |\n//! -C incremental=… flag                      | ✓           |                          |\n//! mtime of sources                           | ✓[^3]       |                          |\n//! RUSTFLAGS/RUSTDOCFLAGS                     | ✓           | ✓[^7]                    |\n//! [`Lto`] flags                              | ✓           | ✓                        | ✓\n//! config settings[^5]                        | ✓           |                          |\n//! `is_std`                                   |             | ✓                        | ✓\n//! `[lints]` table[^6]                        | ✓           |                          |\n//! `[lints.rust.unexpected_cfgs.check-cfg]`   | ✓           |                          |\n//!\n//! [^1]: Bin dependencies are not included.\n//!\n//! [^3]: See below for details on mtime tracking.\n//!\n//! [^4]: `__CARGO_DEFAULT_LIB_METADATA` is set by rustbuild to embed the\n//!        release channel (bootstrap/stable/beta/nightly) in libstd.\n//!\n//! [^5]: Config settings that are not otherwise captured anywhere else.\n//!       Currently, this is only `doc.extern-map`.\n//!\n//! [^6]: Via [`Manifest::lint_rustflags`][crate::core::Manifest::lint_rustflags]\n//!\n//! [^7]: extra-flags and RUSTFLAGS are conditionally excluded when `--remap-path-prefix` is\n//!       present to avoid breaking build reproducibility while we wait for trim-paths\n//!\n//! [^8]: including `-Cextra-filename`\n//!\n//! When deciding what should go in the Metadata vs the Fingerprint, consider\n//! that some files (like dylibs) do not have a hash in their filename. Thus,\n//! if a value changes, only the fingerprint will detect the change (consider,\n//! for example, swapping between different features). Fields that are only in\n//! Metadata generally aren't relevant to the fingerprint because they\n//! fundamentally change the output (like target vs host changes the directory\n//! where it is emitted).\n//!\n//! ## Fingerprint files\n//!\n//! Fingerprint information is stored in the\n//! `target/{debug,release}/.fingerprint/` directory. Each Unit is stored in a\n//! separate directory. Each Unit directory contains:\n//!\n//! - A file with a 16 hex-digit hash. This is the Fingerprint hash, used for\n//!   quick loading and comparison.\n//! - A `.json` file that contains details about the Fingerprint. This is only\n//!   used to log details about *why* a fingerprint is considered dirty.\n//!   `CARGO_LOG=cargo::core::compiler::fingerprint=trace cargo build` can be\n//!   used to display this log information.\n//! - A \"dep-info\" file which is a translation of rustc's `*.d` dep-info files\n//!   to a Cargo-specific format that tweaks file names and is optimized for\n//!   reading quickly.\n//! - An `invoked.timestamp` file whose filesystem mtime is updated every time\n//!   the Unit is built. This is used for capturing the time when the build\n//!   starts, to detect if files are changed in the middle of the build. See\n//!   below for more details.\n//!\n//! Note that some units are a little different. A Unit for *running* a build\n//! script or for `rustdoc` does not have a dep-info file (it's not\n//! applicable). Build script `invoked.timestamp` files are in the build\n//! output directory.\n//!\n//! ## Fingerprint calculation\n//!\n//! After the list of Units has been calculated, the Units are added to the\n//! [`JobQueue`]. As each one is added, the fingerprint is calculated, and the\n//! dirty/fresh status is recorded. A closure is used to update the fingerprint\n//! on-disk when the Unit successfully finishes. The closure will recompute the\n//! Fingerprint based on the updated information. If the Unit fails to compile,\n//! the fingerprint is not updated.\n//!\n//! Fingerprints are cached in the [`BuildRunner`]. This makes computing\n//! Fingerprints faster, but also is necessary for properly updating\n//! dependency information. Since a Fingerprint includes the Fingerprints of\n//! all dependencies, when it is updated, by using `Arc` clones, it\n//! automatically picks up the updates to its dependencies.\n//!\n//! ### dep-info files\n//!\n//! Cargo has several kinds of \"dep info\" files:\n//!\n//! * dep-info files generated by `rustc`.\n//! * Fingerprint dep-info files translated from the first one.\n//! * dep-info for external build system integration.\n//! * Unstable `-Zbinary-dep-depinfo`.\n//!\n//! #### `rustc` dep-info files\n//!\n//! Cargo passes the `--emit=dep-info` flag to `rustc` so that `rustc` will\n//! generate a \"dep info\" file (with the `.d` extension). This is a\n//! Makefile-like syntax that includes all of the source files used to build\n//! the crate. This file is used by Cargo to know which files to check to see\n//! if the crate will need to be rebuilt. Example:\n//!\n//! ```makefile\n//! /path/to/target/debug/deps/cargo-b6219d178925203d: src/bin/main.rs src/bin/cargo/cli.rs # … etc.\n//! ```\n//!\n//! #### Fingerprint dep-info files\n//!\n//! After `rustc` exits successfully, Cargo will read the first kind of dep\n//! info file and translate it into a binary format that is stored in the\n//! fingerprint directory ([`translate_dep_info`]).\n//!\n//! These are used to quickly scan for any changed files. The mtime of the\n//! fingerprint dep-info file itself is used as the reference for comparing the\n//! source files to determine if any of the source files have been modified\n//! (see [below](#mtime-comparison) for more detail).\n//!\n//! Note that Cargo parses the special `# env-var:...` comments in dep-info\n//! files to learn about environment variables that the rustc compile depends on.\n//! Cargo then later uses this to trigger a recompile if a referenced env var\n//! changes (even if the source didn't change).\n//! This also includes env vars generated from Cargo metadata like `CARGO_PKG_DESCRIPTION`.\n//! (See [`crate::core::manifest::ManifestMetadata`]\n//!\n//! #### dep-info files for build system integration.\n//!\n//! There is also a third dep-info file. Cargo will extend the file created by\n//! rustc with some additional information and saves this into the output\n//! directory. This is intended for build system integration. See the\n//! [`output_depinfo`] function for more detail.\n//!\n//! #### -Zbinary-dep-depinfo\n//!\n//! `rustc` has an experimental flag `-Zbinary-dep-depinfo`. This causes\n//! `rustc` to include binary files (like rlibs) in the dep-info file. This is\n//! primarily to support rustc development, so that Cargo can check the\n//! implicit dependency to the standard library (which lives in the sysroot).\n//! We want Cargo to recompile whenever the standard library rlib/dylibs\n//! change, and this is a generic mechanism to make that work.\n//!\n//! ### Mtime comparison\n//!\n//! The use of modification timestamps is the most common way a unit will be\n//! determined to be dirty or fresh between builds. There are many subtle\n//! issues and edge cases with mtime comparisons. This gives a high-level\n//! overview, but you'll need to read the code for the gritty details. Mtime\n//! handling is different for different unit kinds. The different styles are\n//! driven by the [`Fingerprint::local`] field, which is set based on the unit\n//! kind.\n//!\n//! The status of whether or not the mtime is \"stale\" or \"up-to-date\" is\n//! stored in [`Fingerprint::fs_status`].\n//!\n//! All units will compare the mtime of its newest output file with the mtimes\n//! of the outputs of all its dependencies. If any output file is missing,\n//! then the unit is stale. If any dependency is newer, the unit is stale.\n//!\n//! #### Normal package mtime handling\n//!\n//! [`LocalFingerprint::CheckDepInfo`] is used for checking the mtime of\n//! packages. It compares the mtime of the input files (the source files) to\n//! the mtime of the dep-info file (which is written last after a build is\n//! finished). If the dep-info is missing, the unit is stale (it has never\n//! been built). The list of input files comes from the dep-info file. See the\n//! section above for details on dep-info files.\n//!\n//! Also note that although registry and git packages use [`CheckDepInfo`], none\n//! of their source files are included in the dep-info (see\n//! [`translate_dep_info`]), so for those kinds no mtime checking is done\n//! (unless `-Zbinary-dep-depinfo` is used). Repository and git packages are\n//! static, so there is no need to check anything.\n//!\n//! When a build is complete, the mtime of the dep-info file in the\n//! fingerprint directory is modified to rewind it to the time when the build\n//! started. This is done by creating an `invoked.timestamp` file when the\n//! build starts to capture the start time. The mtime is rewound to the start\n//! to handle the case where the user modifies a source file while a build is\n//! running. Cargo can't know whether or not the file was included in the\n//! build, so it takes a conservative approach of assuming the file was *not*\n//! included, and it should be rebuilt during the next build.\n//!\n//! #### Rustdoc mtime handling\n//!\n//! Rustdoc does not emit a dep-info file, so Cargo currently has a relatively\n//! simple system for detecting rebuilds. [`LocalFingerprint::Precalculated`] is\n//! used for rustdoc units. For registry packages, this is the package\n//! version. For git packages, it is the git hash. For path packages, it is\n//! a string of the mtime of the newest file in the package.\n//!\n//! There are some known bugs with how this works, so it should be improved at\n//! some point.\n//!\n//! #### Build script mtime handling\n//!\n//! Build script mtime handling runs in different modes. There is the \"old\n//! style\" where the build script does not emit any `rerun-if` directives. In\n//! this mode, Cargo will use [`LocalFingerprint::Precalculated`]. See the\n//! \"rustdoc\" section above how it works.\n//!\n//! In the new-style, each `rerun-if` directive is translated to the\n//! corresponding [`LocalFingerprint`] variant. The [`RerunIfChanged`] variant\n//! compares the mtime of the given filenames against the mtime of the\n//! \"output\" file.\n//!\n//! Similar to normal units, the build script \"output\" file mtime is rewound\n//! to the time just before the build script is executed to handle mid-build\n//! modifications.\n//!\n//! ## Considerations for inclusion in a fingerprint\n//!\n//! Over time we've realized a few items which historically were included in\n//! fingerprint hashings should not actually be included. Examples are:\n//!\n//! * Modification time values. We strive to never include a modification time\n//!   inside a `Fingerprint` to get hashed into an actual value. While\n//!   theoretically fine to do, in practice this causes issues with common\n//!   applications like Docker. Docker, after a layer is built, will zero out\n//!   the nanosecond part of all filesystem modification times. This means that\n//!   the actual modification time is different for all build artifacts, which\n//!   if we tracked the actual values of modification times would cause\n//!   unnecessary recompiles. To fix this we instead only track paths which are\n//!   relevant. These paths are checked dynamically to see if they're up to\n//!   date, and the modification time doesn't make its way into the fingerprint\n//!   hash.\n//!\n//! * Absolute path names. We strive to maintain a property where if you rename\n//!   a project directory Cargo will continue to preserve all build artifacts\n//!   and reuse the cache. This means that we can't ever hash an absolute path\n//!   name. Instead we always hash relative path names and the \"root\" is passed\n//!   in at runtime dynamically. Some of this is best effort, but the general\n//!   idea is that we assume all accesses within a crate stay within that\n//!   crate.\n//!\n//! These are pretty tricky to test for unfortunately, but we should have a good\n//! test suite nowadays and lord knows Cargo gets enough testing in the wild!\n//!\n//! ## Build scripts\n//!\n//! The *running* of a build script ([`CompileMode::RunCustomBuild`]) is treated\n//! significantly different than all other Unit kinds. It has its own function\n//! for calculating the Fingerprint ([`calculate_run_custom_build`]) and has some\n//! unique considerations. It does not track the same information as a normal\n//! Unit. The information tracked depends on the `rerun-if-changed` and\n//! `rerun-if-env-changed` statements produced by the build script. If the\n//! script does not emit either of these statements, the Fingerprint runs in\n//! \"old style\" mode where an mtime change of *any* file in the package will\n//! cause the build script to be re-run. Otherwise, the fingerprint *only*\n//! tracks the individual \"rerun-if\" items listed by the build script.\n//!\n//! The \"rerun-if\" statements from a *previous* build are stored in the build\n//! output directory in a file called `output`. Cargo parses this file when\n//! the Unit for that build script is prepared for the [`JobQueue`]. The\n//! Fingerprint code can then use that information to compute the Fingerprint\n//! and compare against the old fingerprint hash.\n//!\n//! Care must be taken with build script Fingerprints because the\n//! [`Fingerprint::local`] value may be changed after the build script runs\n//! (such as if the build script adds or removes \"rerun-if\" items).\n//!\n//! Another complication is if a build script is overridden. In that case, the\n//! fingerprint is the hash of the output of the override.\n//!\n//! ## Special considerations\n//!\n//! Registry dependencies do not track the mtime of files. This is because\n//! registry dependencies are not expected to change (if a new version is\n//! used, the Package ID will change, causing a rebuild). Cargo currently\n//! partially works with Docker caching. When a Docker image is built, it has\n//! normal mtime information. However, when a step is cached, the nanosecond\n//! portions of all files is zeroed out. Currently this works, but care must\n//! be taken for situations like these.\n//!\n//! HFS on macOS only supports 1 second timestamps. This causes a significant\n//! number of problems, particularly with Cargo's testsuite which does rapid\n//! builds in succession. Other filesystems have various degrees of\n//! resolution.\n//!\n//! Various weird filesystems (such as network filesystems) also can cause\n//! complications. Network filesystems may track the time on the server\n//! (except when the time is set manually such as with\n//! `filetime::set_file_times`). Not all filesystems support modifying the\n//! mtime.\n//!\n//! See the [`A-rebuild-detection`] label on the issue tracker for more.\n//!\n//! [`check_filesystem`]: Fingerprint::check_filesystem\n//! [`Metadata`]: crate::core::compiler::Metadata\n//! [`Metadata::unit_id`]: crate::core::compiler::Metadata::unit_id\n//! [`Metadata::c_metadata`]: crate::core::compiler::Metadata::c_metadata\n//! [`Metadata::c_extra_filename`]: crate::core::compiler::Metadata::c_extra_filename\n//! [`UnitHash`]: crate::core::compiler::UnitHash\n//! [`Profile`]: crate::core::profiles::Profile\n//! [`CompileMode`]: crate::core::compiler::CompileMode\n//! [`Lto`]: crate::core::compiler::Lto\n//! [`CompileKind`]: crate::core::compiler::CompileKind\n//! [`JobQueue`]: super::job_queue::JobQueue\n//! [`output_depinfo`]: super::output_depinfo()\n//! [`CheckDepInfo`]: LocalFingerprint::CheckDepInfo\n//! [`RerunIfChanged`]: LocalFingerprint::RerunIfChanged\n//! [`CompileMode::RunCustomBuild`]: crate::core::compiler::CompileMode::RunCustomBuild\n//! [`A-rebuild-detection`]: https://github.com/rust-lang/cargo/issues?q=is%3Aissue+is%3Aopen+label%3AA-rebuild-detection\n\nmod dep_info;\nmod dirty_reason;\nmod rustdoc;\n\nuse std::collections::hash_map::{Entry, HashMap};\nuse std::env;\nuse std::ffi::OsString;\nuse std::fs;\nuse std::fs::File;\nuse std::hash::{self, Hash, Hasher};\nuse std::io::{self};\nuse std::path::{Path, PathBuf};\nuse std::sync::{Arc, Mutex};\nuse std::time::SystemTime;\n\nuse anyhow::Context as _;\nuse anyhow::format_err;\nuse cargo_util::paths;\nuse filetime::FileTime;\nuse serde::de;\nuse serde::ser;\nuse serde::{Deserialize, Serialize};\nuse tracing::{debug, info};\n\nuse crate::core::Package;\nuse crate::core::compiler::unit_graph::UnitDep;\nuse crate::util;\nuse crate::util::errors::CargoResult;\nuse crate::util::interning::InternedString;\nuse crate::util::log_message::LogMessage;\nuse crate::util::{StableHasher, internal, path_args};\nuse crate::{CARGO_ENV, GlobalContext};\n\nuse super::BuildContext;\nuse super::BuildRunner;\nuse super::FileFlavor;\nuse super::Job;\nuse super::Unit;\nuse super::UnitIndex;\nuse super::Work;\nuse super::custom_build::BuildDeps;\n\npub use self::dep_info::Checksum;\npub use self::dep_info::parse_dep_info;\npub use self::dep_info::parse_rustc_dep_info;\npub use self::dep_info::translate_dep_info;\npub use self::dirty_reason::DirtyReason;\npub use self::rustdoc::RustdocFingerprint;\n\n/// Result of comparing fingerprints between the current and previous builds.\nenum FingerprintComparison {\n    /// The unit does not need rebuilding.\n    Fresh,\n    /// The unit needs rebuilding.\n    Dirty {\n        /// The reason why the unit is dirty.\n        reason: DirtyReason,\n    },\n}\n\n/// Determines if a [`Unit`] is up-to-date, and if not prepares necessary work to\n/// update the persisted fingerprint.\n///\n/// This function will inspect `Unit`, calculate a fingerprint for it, and then\n/// return an appropriate [`Job`] to run. The returned `Job` will be a noop if\n/// `unit` is considered \"fresh\", or if it was previously built and cached.\n/// Otherwise the `Job` returned will write out the true fingerprint to the\n/// filesystem, to be executed after the unit's work has completed.\n///\n/// The `force` flag is a way to force the `Job` to be \"dirty\", or always\n/// update the fingerprint. **Beware using this flag** because it does not\n/// transitively propagate throughout the dependency graph, it only forces this\n/// one unit which is very unlikely to be what you want unless you're\n/// exclusively talking about top-level units.\n#[tracing::instrument(\n    skip(build_runner, unit),\n    fields(package_id = %unit.pkg.package_id(), target = unit.target.name())\n)]\npub fn prepare_target(\n    build_runner: &mut BuildRunner<'_, '_>,\n    unit: &Unit,\n    force: bool,\n) -> CargoResult<Job> {\n    let bcx = build_runner.bcx;\n    let loc = build_runner.files().fingerprint_file_path(unit, \"\");\n\n    debug!(\"fingerprint at: {}\", loc.display());\n\n    // Figure out if this unit is up to date. After calculating the fingerprint\n    // compare it to an old version, if any, and attempt to print diagnostic\n    // information about failed comparisons to aid in debugging.\n    let fingerprint = calculate(build_runner, unit)?;\n    let mtime_on_use = build_runner.bcx.gctx.cli_unstable().mtime_on_use;\n    let dirty_reason = match compare_old_fingerprint(unit, &loc, &*fingerprint, mtime_on_use, force)\n    {\n        FingerprintComparison::Fresh => None,\n        FingerprintComparison::Dirty { reason } => Some(reason),\n    };\n\n    if let Some(logger) = bcx.logger {\n        let index = bcx.unit_to_index[unit];\n        let mut cause = None;\n        let status = match dirty_reason.as_ref() {\n            Some(reason) if reason.is_fresh_build() => util::log_message::FingerprintStatus::New,\n            Some(reason) => {\n                cause = Some(reason.clone());\n                util::log_message::FingerprintStatus::Dirty\n            }\n            None => util::log_message::FingerprintStatus::Fresh,\n        };\n        logger.log(LogMessage::UnitFingerprint {\n            index,\n            status,\n            cause,\n        });\n    }\n\n    let Some(dirty_reason) = dirty_reason else {\n        return Ok(Job::new_fresh());\n    };\n\n    // We're going to rebuild, so ensure the source of the crate passes all\n    // verification checks before we build it.\n    //\n    // The `Source::verify` method is intended to allow sources to execute\n    // pre-build checks to ensure that the relevant source code is all\n    // up-to-date and as expected. This is currently used primarily for\n    // directory sources which will use this hook to perform an integrity check\n    // on all files in the source to ensure they haven't changed. If they have\n    // changed then an error is issued.\n    let source_id = unit.pkg.package_id().source_id();\n    let sources = bcx.packages.sources();\n    let source = sources\n        .get(source_id)\n        .ok_or_else(|| internal(\"missing package source\"))?;\n    source.verify(unit.pkg.package_id())?;\n\n    // Clear out the old fingerprint file if it exists. This protects when\n    // compilation is interrupted leaving a corrupt file. For example, a\n    // project with a lib.rs and integration test (two units):\n    //\n    // 1. Build the library and integration test.\n    // 2. Make a change to lib.rs (NOT the integration test).\n    // 3. Build the integration test, hit Ctrl-C while linking. With gcc, this\n    //    will leave behind an incomplete executable (zero size, or partially\n    //    written). NOTE: The library builds successfully, it is the linking\n    //    of the integration test that we are interrupting.\n    // 4. Build the integration test again.\n    //\n    // Without the following line, then step 3 will leave a valid fingerprint\n    // on the disk. Then step 4 will think the integration test is \"fresh\"\n    // because:\n    //\n    // - There is a valid fingerprint hash on disk (written in step 1).\n    // - The mtime of the output file (the corrupt integration executable\n    //   written in step 3) is newer than all of its dependencies.\n    // - The mtime of the integration test fingerprint dep-info file (written\n    //   in step 1) is newer than the integration test's source files, because\n    //   we haven't modified any of its source files.\n    //\n    // But the executable is corrupt and needs to be rebuilt. Clearing the\n    // fingerprint at step 3 ensures that Cargo never mistakes a partially\n    // written output as up-to-date.\n    if loc.exists() {\n        // Truncate instead of delete so that compare_old_fingerprint will\n        // still log the reason for the fingerprint failure instead of just\n        // reporting \"failed to read fingerprint\" during the next build if\n        // this build fails.\n        paths::write(&loc, b\"\")?;\n    }\n\n    let write_fingerprint = if unit.mode.is_run_custom_build() {\n        // For build scripts the `local` field of the fingerprint may change\n        // while we're executing it. For example it could be in the legacy\n        // \"consider everything a dependency mode\" and then we switch to \"deps\n        // are explicitly specified\" mode.\n        //\n        // To handle this movement we need to regenerate the `local` field of a\n        // build script's fingerprint after it's executed. We do this by\n        // using the `build_script_local_fingerprints` function which returns a\n        // thunk we can invoke on a foreign thread to calculate this.\n        let build_script_outputs = Arc::clone(&build_runner.build_script_outputs);\n        let metadata = build_runner.get_run_build_script_metadata(unit);\n        let (gen_local, _overridden) = build_script_local_fingerprints(build_runner, unit)?;\n        let output_path = build_runner.build_explicit_deps[unit]\n            .build_script_output\n            .clone();\n        Work::new(move |_| {\n            let outputs = build_script_outputs.lock().unwrap();\n            let output = outputs\n                .get(metadata)\n                .expect(\"output must exist after running\");\n            let deps = BuildDeps::new(&output_path, Some(output));\n\n            // FIXME: it's basically buggy that we pass `None` to `call_box`\n            // here. See documentation on `build_script_local_fingerprints`\n            // below for more information. Despite this just try to proceed and\n            // hobble along if it happens to return `Some`.\n            if let Some(new_local) = (gen_local)(&deps, None)? {\n                *fingerprint.local.lock().unwrap() = new_local;\n            }\n\n            write_fingerprint(&loc, &fingerprint)\n        })\n    } else {\n        Work::new(move |_| write_fingerprint(&loc, &fingerprint))\n    };\n\n    Ok(Job::new_dirty(write_fingerprint, dirty_reason))\n}\n\n/// Dependency edge information for fingerprints. This is generated for each\n/// dependency and is stored in a [`Fingerprint`].\n#[derive(Clone)]\nstruct DepFingerprint {\n    /// The hash of the package id that this dependency points to\n    pkg_id: u64,\n    /// The crate name we're using for this dependency, which if we change we'll\n    /// need to recompile!\n    name: InternedString,\n    /// Whether or not this dependency is flagged as a public dependency or not.\n    public: bool,\n    /// Whether or not this dependency is an rmeta dependency or a \"full\"\n    /// dependency. In the case of an rmeta dependency our dependency edge only\n    /// actually requires the rmeta from what we depend on, so when checking\n    /// mtime information all files other than the rmeta can be ignored.\n    only_requires_rmeta: bool,\n    /// The dependency's fingerprint we recursively point to, containing all the\n    /// other hash information we'd otherwise need.\n    fingerprint: Arc<Fingerprint>,\n}\n\n/// A fingerprint can be considered to be a \"short string\" representing the\n/// state of a world for a package.\n///\n/// If a fingerprint ever changes, then the package itself needs to be\n/// recompiled. Inputs to the fingerprint include source code modifications,\n/// compiler flags, compiler version, etc. This structure is not simply a\n/// `String` due to the fact that some fingerprints cannot be calculated lazily.\n///\n/// Path sources, for example, use the mtime of the corresponding dep-info file\n/// as a fingerprint (all source files must be modified *before* this mtime).\n/// This dep-info file is not generated, however, until after the crate is\n/// compiled. As a result, this structure can be thought of as a fingerprint\n/// to-be. The actual value can be calculated via [`hash_u64()`], but the operation\n/// may fail as some files may not have been generated.\n///\n/// Note that dependencies are taken into account for fingerprints because rustc\n/// requires that whenever an upstream crate is recompiled that all downstream\n/// dependents are also recompiled. This is typically tracked through\n/// [`DependencyQueue`], but it also needs to be retained here because Cargo can\n/// be interrupted while executing, losing the state of the [`DependencyQueue`]\n/// graph.\n///\n/// [`hash_u64()`]: crate::core::compiler::fingerprint::Fingerprint::hash_u64\n/// [`DependencyQueue`]: crate::util::DependencyQueue\n#[derive(Serialize, Deserialize)]\npub struct Fingerprint {\n    /// Hash of the version of `rustc` used.\n    rustc: u64,\n    /// Sorted list of cfg features enabled.\n    features: String,\n    /// Sorted list of all the declared cfg features.\n    declared_features: String,\n    /// Hash of the `Target` struct, including the target name,\n    /// package-relative source path, edition, etc.\n    target: u64,\n    /// Hash of the [`Profile`], [`CompileMode`], and any extra flags passed via\n    /// `cargo rustc` or `cargo rustdoc`.\n    ///\n    /// [`Profile`]: crate::core::profiles::Profile\n    /// [`CompileMode`]: crate::core::compiler::CompileMode\n    profile: u64,\n    /// Hash of the path to the base source file. This is relative to the\n    /// workspace root for path members, or absolute for other sources.\n    path: u64,\n    /// Fingerprints of dependencies.\n    deps: Vec<DepFingerprint>,\n    /// Information about the inputs that affect this Unit (such as source\n    /// file mtimes or build script environment variables).\n    local: Mutex<Vec<LocalFingerprint>>,\n    /// Cached hash of the [`Fingerprint`] struct. Used to improve performance\n    /// for hashing.\n    #[serde(skip)]\n    memoized_hash: Mutex<Option<u64>>,\n    /// RUSTFLAGS/RUSTDOCFLAGS environment variable value (or config value).\n    rustflags: Vec<String>,\n    /// Hash of various config settings that change how things are compiled.\n    config: u64,\n    /// The rustc target. This is only relevant for `.json` files, otherwise\n    /// the metadata hash segregates the units.\n    compile_kind: u64,\n    /// Unit index for this fingerprint, used for tracing cascading rebuilds.\n    /// Not persisted to disk as indices can change between builds.\n    #[serde(skip)]\n    index: UnitIndex,\n    /// Description of whether the filesystem status for this unit is up to date\n    /// or should be considered stale.\n    #[serde(skip)]\n    fs_status: FsStatus,\n    /// Files, relative to `target_root`, that are produced by the step that\n    /// this `Fingerprint` represents. This is used to detect when the whole\n    /// fingerprint is out of date if this is missing, or if previous\n    /// fingerprints output files are regenerated and look newer than this one.\n    #[serde(skip)]\n    outputs: Vec<PathBuf>,\n}\n\n/// Indication of the status on the filesystem for a particular unit.\n#[derive(Clone, Default, Debug, Serialize, Deserialize)]\n#[serde(tag = \"fs_status\", rename_all = \"kebab-case\")]\npub enum FsStatus {\n    /// This unit is to be considered stale, even if hash information all\n    /// matches.\n    #[default]\n    Stale,\n\n    /// File system inputs have changed (or are missing), or there were\n    /// changes to the environment variables that affect this unit. See\n    /// the variants of [`StaleItem`] for more information.\n    StaleItem(StaleItem),\n\n    /// A dependency was stale.\n    StaleDependency {\n        unit: UnitIndex,\n        #[serde(with = \"serde_file_time\")]\n        dep_mtime: FileTime,\n        #[serde(with = \"serde_file_time\")]\n        max_mtime: FileTime,\n    },\n\n    /// A dependency's fingerprint was stale.\n    StaleDepFingerprint { unit: UnitIndex },\n\n    /// This unit is up-to-date. All outputs and their corresponding mtime are\n    /// listed in the payload here for other dependencies to compare against.\n    #[serde(skip)]\n    UpToDate { mtimes: HashMap<PathBuf, FileTime> },\n}\n\nimpl FsStatus {\n    fn up_to_date(&self) -> bool {\n        match self {\n            FsStatus::UpToDate { .. } => true,\n            FsStatus::Stale\n            | FsStatus::StaleItem(_)\n            | FsStatus::StaleDependency { .. }\n            | FsStatus::StaleDepFingerprint { .. } => false,\n        }\n    }\n}\n\nmod serde_file_time {\n    use filetime::FileTime;\n    use serde::Deserialize;\n    use serde::Serialize;\n\n    /// Serialize FileTime as milliseconds with nano.\n    pub(super) fn serialize<S>(ft: &FileTime, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: serde::Serializer,\n    {\n        let secs_as_millis = ft.unix_seconds() as f64 * 1000.0;\n        let nanos_as_millis = ft.nanoseconds() as f64 / 1_000_000.0;\n        (secs_as_millis + nanos_as_millis).serialize(s)\n    }\n\n    /// Deserialize FileTime from milliseconds with nano.\n    pub(super) fn deserialize<'de, D>(d: D) -> Result<FileTime, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        let millis = f64::deserialize(d)?;\n        let secs = (millis / 1000.0) as i64;\n        let nanos = ((millis % 1000.0) * 1_000_000.0) as u32;\n        Ok(FileTime::from_unix_time(secs, nanos))\n    }\n}\n\nimpl Serialize for DepFingerprint {\n    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        (\n            &self.pkg_id,\n            &self.name,\n            &self.public,\n            &self.fingerprint.hash_u64(),\n        )\n            .serialize(ser)\n    }\n}\n\nimpl<'de> Deserialize<'de> for DepFingerprint {\n    fn deserialize<D>(d: D) -> Result<DepFingerprint, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        let (pkg_id, name, public, hash) = <(u64, String, bool, u64)>::deserialize(d)?;\n        Ok(DepFingerprint {\n            pkg_id,\n            name: name.into(),\n            public,\n            fingerprint: Arc::new(Fingerprint {\n                memoized_hash: Mutex::new(Some(hash)),\n                ..Fingerprint::new()\n            }),\n            // This field is never read since it's only used in\n            // `check_filesystem` which isn't used by fingerprints loaded from\n            // disk.\n            only_requires_rmeta: false,\n        })\n    }\n}\n\n/// A `LocalFingerprint` represents something that we use to detect direct\n/// changes to a `Fingerprint`.\n///\n/// This is where we track file information, env vars, etc. This\n/// `LocalFingerprint` struct is hashed and if the hash changes will force a\n/// recompile of any fingerprint it's included into. Note that the \"local\"\n/// terminology comes from the fact that it only has to do with one crate, and\n/// `Fingerprint` tracks the transitive propagation of fingerprint changes.\n///\n/// Note that because this is hashed its contents are carefully managed. Like\n/// mentioned in the above module docs, we don't want to hash absolute paths or\n/// mtime information.\n///\n/// Also note that a `LocalFingerprint` is used in `check_filesystem` to detect\n/// when the filesystem contains stale information (based on mtime currently).\n/// The paths here don't change much between compilations but they're used as\n/// inputs when we probe the filesystem looking at information.\n#[derive(Debug, Serialize, Deserialize, Hash)]\nenum LocalFingerprint {\n    /// This is a precalculated fingerprint which has an opaque string we just\n    /// hash as usual. This variant is primarily used for rustdoc where we\n    /// don't have a dep-info file to compare against.\n    ///\n    /// This is also used for build scripts with no `rerun-if-*` statements, but\n    /// that's overall a mistake and causes bugs in Cargo. We shouldn't use this\n    /// for build scripts.\n    Precalculated(String),\n\n    /// This is used for crate compilations. The `dep_info` file is a relative\n    /// path anchored at `target_root(...)` to the dep-info file that Cargo\n    /// generates (which is a custom serialization after parsing rustc's own\n    /// `dep-info` output).\n    ///\n    /// The `dep_info` file, when present, also lists a number of other files\n    /// for us to look at. If any of those files are newer than this file then\n    /// we need to recompile.\n    ///\n    /// If the `checksum` bool is true then the `dep_info` file is expected to\n    /// contain file checksums instead of file mtimes.\n    CheckDepInfo { dep_info: PathBuf, checksum: bool },\n\n    /// This represents a nonempty set of `rerun-if-changed` annotations printed\n    /// out by a build script. The `output` file is a relative file anchored at\n    /// `target_root(...)` which is the actual output of the build script. That\n    /// output has already been parsed and the paths printed out via\n    /// `rerun-if-changed` are listed in `paths`. The `paths` field is relative\n    /// to `pkg.root()`\n    ///\n    /// This is considered up-to-date if all of the `paths` are older than\n    /// `output`, otherwise we need to recompile.\n    RerunIfChanged {\n        output: PathBuf,\n        paths: Vec<PathBuf>,\n    },\n\n    /// This represents a single `rerun-if-env-changed` annotation printed by a\n    /// build script. The exact env var and value are hashed here. There's no\n    /// filesystem dependence here, and if the values are changed the hash will\n    /// change forcing a recompile.\n    RerunIfEnvChanged { var: String, val: Option<String> },\n}\n\n/// See [`FsStatus::StaleItem`].\n#[derive(Clone, Debug, Serialize, Deserialize)]\n#[serde(tag = \"stale_item\", rename_all = \"kebab-case\")]\npub enum StaleItem {\n    MissingFile {\n        path: PathBuf,\n    },\n    UnableToReadFile {\n        path: PathBuf,\n    },\n    FailedToReadMetadata {\n        path: PathBuf,\n    },\n    FileSizeChanged {\n        path: PathBuf,\n        old_size: u64,\n        new_size: u64,\n    },\n    ChangedFile {\n        reference: PathBuf,\n        #[serde(with = \"serde_file_time\")]\n        reference_mtime: FileTime,\n        stale: PathBuf,\n        #[serde(with = \"serde_file_time\")]\n        stale_mtime: FileTime,\n    },\n    ChangedChecksum {\n        source: PathBuf,\n        stored_checksum: Checksum,\n        new_checksum: Checksum,\n    },\n    MissingChecksum {\n        path: PathBuf,\n    },\n    ChangedEnv {\n        var: String,\n        previous: Option<String>,\n        current: Option<String>,\n    },\n}\n\nimpl LocalFingerprint {\n    /// Read the environment variable of the given env `key`, and creates a new\n    /// [`LocalFingerprint::RerunIfEnvChanged`] for it. The `env_config` is used firstly\n    /// to check if the env var is set in the config system as some envs need to be overridden.\n    /// If not, it will fallback to `std::env::var`.\n    ///\n    // TODO: `std::env::var` is allowed at this moment. Should figure out\n    // if it makes sense if permitting to read env from the env snapshot.\n    #[allow(clippy::disallowed_methods)]\n    fn from_env<K: AsRef<str>>(\n        key: K,\n        env_config: &Arc<HashMap<String, OsString>>,\n    ) -> LocalFingerprint {\n        let key = key.as_ref();\n        let var = key.to_owned();\n        let val = if let Some(val) = env_config.get(key) {\n            val.to_str().map(ToOwned::to_owned)\n        } else {\n            env::var(key).ok()\n        };\n        LocalFingerprint::RerunIfEnvChanged { var, val }\n    }\n\n    /// Checks dynamically at runtime if this `LocalFingerprint` has a stale\n    /// item inside of it.\n    ///\n    /// The main purpose of this function is to handle two different ways\n    /// fingerprints can be invalidated:\n    ///\n    /// * One is a dependency listed in rustc's dep-info files is invalid. Note\n    ///   that these could either be env vars or files. We check both here.\n    ///\n    /// * Another is the `rerun-if-changed` directive from build scripts. This\n    ///   is where we'll find whether files have actually changed\n    fn find_stale_item(\n        &self,\n        mtime_cache: &mut HashMap<PathBuf, FileTime>,\n        checksum_cache: &mut HashMap<PathBuf, Checksum>,\n        pkg: &Package,\n        build_root: &Path,\n        cargo_exe: &Path,\n        gctx: &GlobalContext,\n    ) -> CargoResult<Option<StaleItem>> {\n        let pkg_root = pkg.root();\n        match self {\n            // We need to parse `dep_info`, learn about the crate's dependencies.\n            //\n            // For each env var we see if our current process's env var still\n            // matches, and for each file we see if any of them are newer than\n            // the `dep_info` file itself whose mtime represents the start of\n            // rustc.\n            LocalFingerprint::CheckDepInfo { dep_info, checksum } => {\n                let dep_info = build_root.join(dep_info);\n                let Some(info) = parse_dep_info(pkg_root, build_root, &dep_info)? else {\n                    return Ok(Some(StaleItem::MissingFile { path: dep_info }));\n                };\n                for (key, previous) in info.env.iter() {\n                    if let Some(value) = pkg.manifest().metadata().env_var(key.as_str()) {\n                        if Some(value.as_ref()) == previous.as_deref() {\n                            continue;\n                        }\n                    }\n\n                    let current = if key == CARGO_ENV {\n                        Some(cargo_exe.to_str().ok_or_else(|| {\n                            format_err!(\n                                \"cargo exe path {} must be valid UTF-8\",\n                                cargo_exe.display()\n                            )\n                        })?)\n                    } else {\n                        if let Some(value) = gctx.env_config()?.get(key) {\n                            value.to_str()\n                        } else {\n                            gctx.get_env(key).ok()\n                        }\n                    };\n                    if current == previous.as_deref() {\n                        continue;\n                    }\n                    return Ok(Some(StaleItem::ChangedEnv {\n                        var: key.clone(),\n                        previous: previous.clone(),\n                        current: current.map(Into::into),\n                    }));\n                }\n                if *checksum {\n                    Ok(find_stale_file(\n                        mtime_cache,\n                        checksum_cache,\n                        &dep_info,\n                        info.files.iter().map(|(file, checksum)| (file, *checksum)),\n                        *checksum,\n                    ))\n                } else {\n                    Ok(find_stale_file(\n                        mtime_cache,\n                        checksum_cache,\n                        &dep_info,\n                        info.files.into_keys().map(|p| (p, None)),\n                        *checksum,\n                    ))\n                }\n            }\n\n            // We need to verify that no paths listed in `paths` are newer than\n            // the `output` path itself, or the last time the build script ran.\n            LocalFingerprint::RerunIfChanged { output, paths } => Ok(find_stale_file(\n                mtime_cache,\n                checksum_cache,\n                &build_root.join(output),\n                paths.iter().map(|p| (pkg_root.join(p), None)),\n                false,\n            )),\n\n            // These have no dependencies on the filesystem, and their values\n            // are included natively in the `Fingerprint` hash so nothing\n            // tocheck for here.\n            LocalFingerprint::RerunIfEnvChanged { .. } => Ok(None),\n            LocalFingerprint::Precalculated(..) => Ok(None),\n        }\n    }\n\n    fn kind(&self) -> &'static str {\n        match self {\n            LocalFingerprint::Precalculated(..) => \"precalculated\",\n            LocalFingerprint::CheckDepInfo { .. } => \"dep-info\",\n            LocalFingerprint::RerunIfChanged { .. } => \"rerun-if-changed\",\n            LocalFingerprint::RerunIfEnvChanged { .. } => \"rerun-if-env-changed\",\n        }\n    }\n}\n\nimpl Fingerprint {\n    fn new() -> Fingerprint {\n        Fingerprint {\n            rustc: 0,\n            target: 0,\n            profile: 0,\n            path: 0,\n            features: String::new(),\n            declared_features: String::new(),\n            deps: Vec::new(),\n            local: Mutex::new(Vec::new()),\n            memoized_hash: Mutex::new(None),\n            rustflags: Vec::new(),\n            config: 0,\n            compile_kind: 0,\n            index: UnitIndex::default(),\n            fs_status: FsStatus::Stale,\n            outputs: Vec::new(),\n        }\n    }\n\n    /// For performance reasons fingerprints will memoize their own hash, but\n    /// there's also internal mutability with its `local` field which can\n    /// change, for example with build scripts, during a build.\n    ///\n    /// This method can be used to bust all memoized hashes just before a build\n    /// to ensure that after a build completes everything is up-to-date.\n    pub fn clear_memoized(&self) {\n        *self.memoized_hash.lock().unwrap() = None;\n    }\n\n    fn hash_u64(&self) -> u64 {\n        if let Some(s) = *self.memoized_hash.lock().unwrap() {\n            return s;\n        }\n        let ret = util::hash_u64(self);\n        *self.memoized_hash.lock().unwrap() = Some(ret);\n        ret\n    }\n\n    /// Compares this fingerprint with an old version which was previously\n    /// serialized to filesystem.\n    ///\n    /// The purpose of this is exclusively to produce a diagnostic message\n    /// [`DirtyReason`], indicating why we're recompiling something.\n    fn compare(&self, old: &Fingerprint) -> DirtyReason {\n        if self.rustc != old.rustc {\n            return DirtyReason::RustcChanged;\n        }\n        if self.features != old.features {\n            return DirtyReason::FeaturesChanged {\n                old: old.features.clone(),\n                new: self.features.clone(),\n            };\n        }\n        if self.declared_features != old.declared_features {\n            return DirtyReason::DeclaredFeaturesChanged {\n                old: old.declared_features.clone(),\n                new: self.declared_features.clone(),\n            };\n        }\n        if self.target != old.target {\n            return DirtyReason::TargetConfigurationChanged;\n        }\n        if self.path != old.path {\n            return DirtyReason::PathToSourceChanged;\n        }\n        if self.profile != old.profile {\n            return DirtyReason::ProfileConfigurationChanged;\n        }\n        if self.rustflags != old.rustflags {\n            return DirtyReason::RustflagsChanged {\n                old: old.rustflags.clone(),\n                new: self.rustflags.clone(),\n            };\n        }\n        if self.config != old.config {\n            return DirtyReason::ConfigSettingsChanged;\n        }\n        if self.compile_kind != old.compile_kind {\n            return DirtyReason::CompileKindChanged;\n        }\n        let my_local = self.local.lock().unwrap();\n        let old_local = old.local.lock().unwrap();\n        if my_local.len() != old_local.len() {\n            return DirtyReason::LocalLengthsChanged;\n        }\n        for (new, old) in my_local.iter().zip(old_local.iter()) {\n            match (new, old) {\n                (LocalFingerprint::Precalculated(a), LocalFingerprint::Precalculated(b)) => {\n                    if a != b {\n                        return DirtyReason::PrecalculatedComponentsChanged {\n                            old: b.to_string(),\n                            new: a.to_string(),\n                        };\n                    }\n                }\n                (\n                    LocalFingerprint::CheckDepInfo {\n                        dep_info: a_dep,\n                        checksum: checksum_a,\n                    },\n                    LocalFingerprint::CheckDepInfo {\n                        dep_info: b_dep,\n                        checksum: checksum_b,\n                    },\n                ) => {\n                    if a_dep != b_dep {\n                        return DirtyReason::DepInfoOutputChanged {\n                            old: b_dep.clone(),\n                            new: a_dep.clone(),\n                        };\n                    }\n                    if checksum_a != checksum_b {\n                        return DirtyReason::ChecksumUseChanged { old: *checksum_b };\n                    }\n                }\n                (\n                    LocalFingerprint::RerunIfChanged {\n                        output: a_out,\n                        paths: a_paths,\n                    },\n                    LocalFingerprint::RerunIfChanged {\n                        output: b_out,\n                        paths: b_paths,\n                    },\n                ) => {\n                    if a_out != b_out {\n                        return DirtyReason::RerunIfChangedOutputFileChanged {\n                            old: b_out.clone(),\n                            new: a_out.clone(),\n                        };\n                    }\n                    if a_paths != b_paths {\n                        return DirtyReason::RerunIfChangedOutputPathsChanged {\n                            old: b_paths.clone(),\n                            new: a_paths.clone(),\n                        };\n                    }\n                }\n                (\n                    LocalFingerprint::RerunIfEnvChanged {\n                        var: a_key,\n                        val: a_value,\n                    },\n                    LocalFingerprint::RerunIfEnvChanged {\n                        var: b_key,\n                        val: b_value,\n                    },\n                ) => {\n                    if *a_key != *b_key {\n                        return DirtyReason::EnvVarsChanged {\n                            old: b_key.clone(),\n                            new: a_key.clone(),\n                        };\n                    }\n                    if *a_value != *b_value {\n                        return DirtyReason::EnvVarChanged {\n                            name: a_key.clone(),\n                            old_value: b_value.clone(),\n                            new_value: a_value.clone(),\n                        };\n                    }\n                }\n                (a, b) => {\n                    return DirtyReason::LocalFingerprintTypeChanged {\n                        old: b.kind().to_owned(),\n                        new: a.kind().to_owned(),\n                    };\n                }\n            }\n        }\n\n        if self.deps.len() != old.deps.len() {\n            return DirtyReason::NumberOfDependenciesChanged {\n                old: old.deps.len(),\n                new: self.deps.len(),\n            };\n        }\n        for (a, b) in self.deps.iter().zip(old.deps.iter()) {\n            if a.name != b.name {\n                return DirtyReason::UnitDependencyNameChanged {\n                    old: b.name,\n                    new: a.name,\n                };\n            }\n\n            if a.fingerprint.hash_u64() != b.fingerprint.hash_u64() {\n                return DirtyReason::UnitDependencyInfoChanged {\n                    unit: a.fingerprint.index,\n                };\n            }\n        }\n\n        if !self.fs_status.up_to_date() {\n            return DirtyReason::FsStatusOutdated(self.fs_status.clone());\n        }\n\n        // This typically means some filesystem modifications happened or\n        // something transitive was odd. In general we should strive to provide\n        // a better error message than this, so if you see this message a lot it\n        // likely means this method needs to be updated!\n        DirtyReason::NothingObvious\n    }\n\n    /// Dynamically inspect the local filesystem to update the `fs_status` field\n    /// of this `Fingerprint`.\n    ///\n    /// This function is used just after a `Fingerprint` is constructed to check\n    /// the local state of the filesystem and propagate any dirtiness from\n    /// dependencies up to this unit as well. This function assumes that the\n    /// unit starts out as [`FsStatus::Stale`] and then it will optionally switch\n    /// it to `UpToDate` if it can.\n    fn check_filesystem(\n        &mut self,\n        mtime_cache: &mut HashMap<PathBuf, FileTime>,\n        checksum_cache: &mut HashMap<PathBuf, Checksum>,\n        pkg: &Package,\n        build_root: &Path,\n        cargo_exe: &Path,\n        gctx: &GlobalContext,\n    ) -> CargoResult<()> {\n        assert!(!self.fs_status.up_to_date());\n\n        let pkg_root = pkg.root();\n        let mut mtimes = HashMap::new();\n\n        // Get the `mtime` of all outputs. Optionally update their mtime\n        // afterwards based on the `mtime_on_use` flag. Afterwards we want the\n        // minimum mtime as it's the one we'll be comparing to inputs and\n        // dependencies.\n        for output in self.outputs.iter() {\n            let Ok(mtime) = paths::mtime(output) else {\n                // This path failed to report its `mtime`. It probably doesn't\n                // exists, so leave ourselves as stale and bail out.\n                let item = StaleItem::FailedToReadMetadata {\n                    path: output.clone(),\n                };\n                self.fs_status = FsStatus::StaleItem(item);\n                return Ok(());\n            };\n            assert!(mtimes.insert(output.clone(), mtime).is_none());\n        }\n\n        let opt_max = mtimes.iter().max_by_key(|kv| kv.1);\n        let Some((max_path, max_mtime)) = opt_max else {\n            // We had no output files. This means we're an overridden build\n            // script and we're just always up to date because we aren't\n            // watching the filesystem.\n            self.fs_status = FsStatus::UpToDate { mtimes };\n            return Ok(());\n        };\n        debug!(\n            \"max output mtime for {:?} is {:?} {}\",\n            pkg_root, max_path, max_mtime\n        );\n\n        for dep in self.deps.iter() {\n            let dep_mtimes = match &dep.fingerprint.fs_status {\n                FsStatus::UpToDate { mtimes } => mtimes,\n                // If our dependency is stale, so are we, so bail out.\n                FsStatus::Stale\n                | FsStatus::StaleItem(_)\n                | FsStatus::StaleDependency { .. }\n                | FsStatus::StaleDepFingerprint { .. } => {\n                    self.fs_status = FsStatus::StaleDepFingerprint {\n                        unit: dep.fingerprint.index,\n                    };\n                    return Ok(());\n                }\n            };\n\n            // If our dependency edge only requires the rmeta file to be present\n            // then we only need to look at that one output file, otherwise we\n            // need to consider all output files to see if we're out of date.\n            let (dep_path, dep_mtime) = if dep.only_requires_rmeta {\n                dep_mtimes\n                    .iter()\n                    .find(|(path, _mtime)| {\n                        path.extension().and_then(|s| s.to_str()) == Some(\"rmeta\")\n                    })\n                    .expect(\"failed to find rmeta\")\n            } else {\n                match dep_mtimes.iter().max_by_key(|kv| kv.1) {\n                    Some(dep_mtime) => dep_mtime,\n                    // If our dependencies is up to date and has no filesystem\n                    // interactions, then we can move on to the next dependency.\n                    None => continue,\n                }\n            };\n            debug!(\n                \"max dep mtime for {:?} is {:?} {}\",\n                pkg_root, dep_path, dep_mtime\n            );\n\n            // If the dependency is newer than our own output then it was\n            // recompiled previously. We transitively become stale ourselves in\n            // that case, so bail out.\n            //\n            // Note that this comparison should probably be `>=`, not `>`, but\n            // for a discussion of why it's `>` see the discussion about #5918\n            // below in `find_stale`.\n            if dep_mtime > max_mtime {\n                info!(\n                    \"dependency on `{}` is newer than we are {} > {} {:?}\",\n                    dep.name, dep_mtime, max_mtime, pkg_root\n                );\n\n                self.fs_status = FsStatus::StaleDependency {\n                    unit: dep.fingerprint.index,\n                    dep_mtime: *dep_mtime,\n                    max_mtime: *max_mtime,\n                };\n\n                return Ok(());\n            }\n        }\n\n        // If we reached this far then all dependencies are up to date. Check\n        // all our `LocalFingerprint` information to see if we have any stale\n        // files for this package itself. If we do find something log a helpful\n        // message and bail out so we stay stale.\n        for local in self.local.get_mut().unwrap().iter() {\n            if let Some(item) = local.find_stale_item(\n                mtime_cache,\n                checksum_cache,\n                pkg,\n                build_root,\n                cargo_exe,\n                gctx,\n            )? {\n                item.log();\n                self.fs_status = FsStatus::StaleItem(item);\n                return Ok(());\n            }\n        }\n\n        // Everything was up to date! Record such.\n        self.fs_status = FsStatus::UpToDate { mtimes };\n        debug!(\"filesystem up-to-date {:?}\", pkg_root);\n\n        Ok(())\n    }\n}\n\nimpl hash::Hash for Fingerprint {\n    fn hash<H: Hasher>(&self, h: &mut H) {\n        let Fingerprint {\n            rustc,\n            ref features,\n            ref declared_features,\n            target,\n            path,\n            profile,\n            ref deps,\n            ref local,\n            config,\n            compile_kind,\n            ref rustflags,\n            ..\n        } = *self;\n        let local = local.lock().unwrap();\n        (\n            rustc,\n            features,\n            declared_features,\n            target,\n            path,\n            profile,\n            &*local,\n            config,\n            compile_kind,\n            rustflags,\n        )\n            .hash(h);\n\n        h.write_usize(deps.len());\n        for DepFingerprint {\n            pkg_id,\n            name,\n            public,\n            fingerprint,\n            only_requires_rmeta: _, // static property, no need to hash\n        } in deps\n        {\n            pkg_id.hash(h);\n            name.hash(h);\n            public.hash(h);\n            // use memoized dep hashes to avoid exponential blowup\n            h.write_u64(fingerprint.hash_u64());\n        }\n    }\n}\n\nimpl DepFingerprint {\n    fn new(\n        build_runner: &mut BuildRunner<'_, '_>,\n        parent: &Unit,\n        dep: &UnitDep,\n    ) -> CargoResult<DepFingerprint> {\n        let fingerprint = calculate(build_runner, &dep.unit)?;\n        // We need to be careful about what we hash here. We have a goal of\n        // supporting renaming a project directory and not rebuilding\n        // everything. To do that, however, we need to make sure that the cwd\n        // doesn't make its way into any hashes, and one source of that is the\n        // `SourceId` for `path` packages.\n        //\n        // We already have a requirement that `path` packages all have unique\n        // names (sort of for this same reason), so if the package source is a\n        // `path` then we just hash the name, but otherwise we hash the full\n        // id as it won't change when the directory is renamed.\n        let pkg_id = if dep.unit.pkg.package_id().source_id().is_path() {\n            util::hash_u64(dep.unit.pkg.package_id().name())\n        } else {\n            util::hash_u64(dep.unit.pkg.package_id())\n        };\n\n        Ok(DepFingerprint {\n            pkg_id,\n            name: dep.extern_crate_name,\n            public: dep.public,\n            fingerprint,\n            only_requires_rmeta: build_runner.only_requires_rmeta(parent, &dep.unit),\n        })\n    }\n}\n\nimpl StaleItem {\n    /// Use the `log` crate to log a hopefully helpful message in diagnosing\n    /// what file is considered stale and why. This is intended to be used in\n    /// conjunction with `CARGO_LOG` to determine why Cargo is recompiling\n    /// something. Currently there's no user-facing usage of this other than\n    /// that.\n    fn log(&self) {\n        match self {\n            StaleItem::MissingFile { path } => {\n                info!(\"stale: missing {:?}\", path);\n            }\n            StaleItem::UnableToReadFile { path } => {\n                info!(\"stale: unable to read {:?}\", path);\n            }\n            StaleItem::FailedToReadMetadata { path } => {\n                info!(\"stale: couldn't read metadata {:?}\", path);\n            }\n            StaleItem::ChangedFile {\n                reference,\n                reference_mtime,\n                stale,\n                stale_mtime,\n            } => {\n                info!(\"stale: changed {:?}\", stale);\n                info!(\"          (vs) {:?}\", reference);\n                info!(\"               {:?} < {:?}\", reference_mtime, stale_mtime);\n            }\n            StaleItem::FileSizeChanged {\n                path,\n                new_size,\n                old_size,\n            } => {\n                info!(\"stale: changed {:?}\", path);\n                info!(\"prior file size {old_size}\");\n                info!(\"  new file size {new_size}\");\n            }\n            StaleItem::ChangedChecksum {\n                source,\n                stored_checksum,\n                new_checksum,\n            } => {\n                info!(\"stale: changed {:?}\", source);\n                info!(\"prior checksum {stored_checksum}\");\n                info!(\"  new checksum {new_checksum}\");\n            }\n            StaleItem::MissingChecksum { path } => {\n                info!(\"stale: no prior checksum {:?}\", path);\n            }\n            StaleItem::ChangedEnv {\n                var,\n                previous,\n                current,\n            } => {\n                info!(\"stale: changed env {:?}\", var);\n                info!(\"       {:?} != {:?}\", previous, current);\n            }\n        }\n    }\n}\n\n/// Calculates the fingerprint for a [`Unit`].\n///\n/// This fingerprint is used by Cargo to learn about when information such as:\n///\n/// * A non-path package changes (changes version, changes revision, etc).\n/// * Any dependency changes\n/// * The compiler changes\n/// * The set of features a package is built with changes\n/// * The profile a target is compiled with changes (e.g., opt-level changes)\n/// * Any other compiler flags change that will affect the result\n///\n/// Information like file modification time is only calculated for path\n/// dependencies.\nfn calculate(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<Arc<Fingerprint>> {\n    // This function is slammed quite a lot, so the result is memoized.\n    if let Some(s) = build_runner.fingerprints.get(unit) {\n        return Ok(Arc::clone(s));\n    }\n    let mut fingerprint = if unit.mode.is_run_custom_build() {\n        calculate_run_custom_build(build_runner, unit)?\n    } else if unit.mode.is_doc_test() {\n        panic!(\"doc tests do not fingerprint\");\n    } else {\n        calculate_normal(build_runner, unit)?\n    };\n\n    // After we built the initial `Fingerprint` be sure to update the\n    // `fs_status` field of it.\n    let build_root = build_root(build_runner);\n    let cargo_exe = build_runner.bcx.gctx.cargo_exe()?;\n    fingerprint.check_filesystem(\n        &mut build_runner.mtime_cache,\n        &mut build_runner.checksum_cache,\n        &unit.pkg,\n        &build_root,\n        cargo_exe,\n        build_runner.bcx.gctx,\n    )?;\n\n    let fingerprint = Arc::new(fingerprint);\n    build_runner\n        .fingerprints\n        .insert(unit.clone(), Arc::clone(&fingerprint));\n    Ok(fingerprint)\n}\n\n/// Calculate a fingerprint for a \"normal\" unit, or anything that's not a build\n/// script. This is an internal helper of [`calculate`], don't call directly.\nfn calculate_normal(\n    build_runner: &mut BuildRunner<'_, '_>,\n    unit: &Unit,\n) -> CargoResult<Fingerprint> {\n    let deps = {\n        // Recursively calculate the fingerprint for all of our dependencies.\n        //\n        // Skip fingerprints of binaries because they don't actually induce a\n        // recompile, they're just dependencies in the sense that they need to be\n        // built. The only exception here are artifact dependencies,\n        // which is an actual dependency that needs a recompile.\n        //\n        // Create Vec since mutable build_runner is needed in closure.\n        let deps = Vec::from(build_runner.unit_deps(unit));\n        let mut deps = deps\n            .into_iter()\n            .filter(|dep| !dep.unit.target.is_bin() || dep.unit.artifact.is_true())\n            .map(|dep| DepFingerprint::new(build_runner, unit, &dep))\n            .collect::<CargoResult<Vec<_>>>()?;\n        deps.sort_by(|a, b| a.pkg_id.cmp(&b.pkg_id));\n        deps\n    };\n\n    // Afterwards calculate our own fingerprint information.\n    let build_root = build_root(build_runner);\n    let is_any_doc_gen = unit.mode.is_doc() || unit.mode.is_doc_scrape();\n    let rustdoc_depinfo_enabled = build_runner.bcx.gctx.cli_unstable().rustdoc_depinfo;\n    let local = if is_any_doc_gen && !rustdoc_depinfo_enabled {\n        // rustdoc does not have dep-info files.\n        let fingerprint = pkg_fingerprint(build_runner.bcx, &unit.pkg).with_context(|| {\n            format!(\n                \"failed to determine package fingerprint for documenting {}\",\n                unit.pkg\n            )\n        })?;\n        vec![LocalFingerprint::Precalculated(fingerprint)]\n    } else {\n        let dep_info = dep_info_loc(build_runner, unit);\n        let dep_info = dep_info.strip_prefix(&build_root).unwrap().to_path_buf();\n        vec![LocalFingerprint::CheckDepInfo {\n            dep_info,\n            checksum: build_runner.bcx.gctx.cli_unstable().checksum_freshness,\n        }]\n    };\n\n    // Figure out what the outputs of our unit is, and we'll be storing them\n    // into the fingerprint as well.\n    let outputs = build_runner\n        .outputs(unit)?\n        .iter()\n        .filter(|output| {\n            !matches!(\n                output.flavor,\n                FileFlavor::DebugInfo | FileFlavor::Auxiliary | FileFlavor::Sbom\n            )\n        })\n        .map(|output| output.path.clone())\n        .collect();\n\n    // Fill out a bunch more information that we'll be tracking typically\n    // hashed to take up less space on disk as we just need to know when things\n    // change.\n    let extra_flags = if unit.mode.is_doc() || unit.mode.is_doc_scrape() {\n        &unit.rustdocflags\n    } else {\n        &unit.rustflags\n    }\n    .to_vec();\n\n    let profile_hash = util::hash_u64((\n        &unit.profile,\n        unit.mode,\n        build_runner.bcx.extra_args_for(unit),\n        build_runner.lto[unit],\n        unit.pkg.manifest().lint_rustflags(),\n    ));\n    let mut config = StableHasher::new();\n    let linker = if unit.target.for_host() && !build_runner.bcx.gctx.target_applies_to_host()? {\n        build_runner.compilation.host_linker()\n    } else {\n        build_runner.compilation.target_linker(unit.kind)\n    };\n    if let Some(linker) = linker {\n        linker.hash(&mut config);\n    }\n    if unit.mode.is_doc() && build_runner.bcx.gctx.cli_unstable().rustdoc_map {\n        if let Ok(map) = build_runner.bcx.gctx.doc_extern_map() {\n            map.hash(&mut config);\n        }\n    }\n    if let Some(allow_features) = &build_runner.bcx.gctx.cli_unstable().allow_features {\n        allow_features.hash(&mut config);\n    }\n    // -Zno-embed-metadata changes how all units are compiled, and it also changes how we tell\n    // rustc to link to deps using `--extern`. If it changes, we should rebuild everything.\n    build_runner\n        .bcx\n        .gctx\n        .cli_unstable()\n        .no_embed_metadata\n        .hash(&mut config);\n\n    let compile_kind = unit.kind.fingerprint_hash();\n    let mut declared_features = unit.pkg.summary().features().keys().collect::<Vec<_>>();\n    declared_features.sort(); // to avoid useless rebuild if the user orders it's features\n    // differently\n    Ok(Fingerprint {\n        rustc: util::hash_u64(&build_runner.bcx.rustc().verbose_version),\n        target: util::hash_u64(&unit.target),\n        profile: profile_hash,\n        // Note that .0 is hashed here, not .1 which is the cwd. That doesn't\n        // actually affect the output artifact so there's no need to hash it.\n        path: util::hash_u64(path_args(build_runner.bcx.ws, unit).0),\n        features: format!(\"{:?}\", unit.features),\n        declared_features: format!(\"{declared_features:?}\"),\n        deps,\n        local: Mutex::new(local),\n        memoized_hash: Mutex::new(None),\n        config: Hasher::finish(&config),\n        compile_kind,\n        index: build_runner.bcx.unit_to_index[unit],\n        rustflags: extra_flags,\n        fs_status: FsStatus::Stale,\n        outputs,\n    })\n}\n\n/// Calculate a fingerprint for an \"execute a build script\" unit.  This is an\n/// internal helper of [`calculate`], don't call directly.\nfn calculate_run_custom_build(\n    build_runner: &mut BuildRunner<'_, '_>,\n    unit: &Unit,\n) -> CargoResult<Fingerprint> {\n    assert!(unit.mode.is_run_custom_build());\n    // Using the `BuildDeps` information we'll have previously parsed and\n    // inserted into `build_explicit_deps` built an initial snapshot of the\n    // `LocalFingerprint` list for this build script. If we previously executed\n    // the build script this means we'll be watching files and env vars.\n    // Otherwise if we haven't previously executed it we'll just start watching\n    // the whole crate.\n    let (gen_local, overridden) = build_script_local_fingerprints(build_runner, unit)?;\n    let deps = &build_runner.build_explicit_deps[unit];\n    let local = (gen_local)(\n        deps,\n        Some(&|| {\n            const IO_ERR_MESSAGE: &str = \"\\\nAn I/O error happened. Please make sure you can access the file.\n\nBy default, if your project contains a build script, cargo scans all files in\nit to determine whether a rebuild is needed. If you don't expect to access the\nfile, specify `rerun-if-changed` in your build script.\nSee https://doc.rust-lang.org/cargo/reference/build-scripts.html#rerun-if-changed for more information.\";\n            pkg_fingerprint(build_runner.bcx, &unit.pkg).map_err(|err| {\n                let mut message = format!(\"failed to determine package fingerprint for build script for {}\", unit.pkg);\n                if err.root_cause().is::<io::Error>() {\n                    message = format!(\"{}\\n{}\", message, IO_ERR_MESSAGE)\n                }\n                err.context(message)\n            })\n        }),\n    )?\n    .unwrap();\n    let output = deps.build_script_output.clone();\n\n    // Include any dependencies of our execution, which is typically just the\n    // compilation of the build script itself. (if the build script changes we\n    // should be rerun!). Note though that if we're an overridden build script\n    // we have no dependencies so no need to recurse in that case.\n    let deps = if overridden {\n        // Overridden build scripts don't need to track deps.\n        vec![]\n    } else {\n        // Create Vec since mutable build_runner is needed in closure.\n        let deps = Vec::from(build_runner.unit_deps(unit));\n        deps.into_iter()\n            .map(|dep| DepFingerprint::new(build_runner, unit, &dep))\n            .collect::<CargoResult<Vec<_>>>()?\n    };\n\n    let rustflags = unit.rustflags.to_vec();\n\n    Ok(Fingerprint {\n        local: Mutex::new(local),\n        rustc: util::hash_u64(&build_runner.bcx.rustc().verbose_version),\n        deps,\n        outputs: if overridden { Vec::new() } else { vec![output] },\n        rustflags,\n        index: build_runner.bcx.unit_to_index[unit],\n\n        // Most of the other info is blank here as we don't really include it\n        // in the execution of the build script, but... this may be a latent\n        // bug in Cargo.\n        ..Fingerprint::new()\n    })\n}\n\n/// Get ready to compute the [`LocalFingerprint`] values\n/// for a [`RunCustomBuild`] unit.\n///\n/// This function has, what's on the surface, a seriously wonky interface.\n/// You'll call this function and it'll return a closure and a boolean. The\n/// boolean is pretty simple in that it indicates whether the `unit` has been\n/// overridden via `.cargo/config.toml`. The closure is much more complicated.\n///\n/// This closure is intended to capture any local state necessary to compute\n/// the `LocalFingerprint` values for this unit. It is `Send` and `'static` to\n/// be sent to other threads as well (such as when we're executing build\n/// scripts). That deduplication is the rationale for the closure at least.\n///\n/// The arguments to the closure are a bit weirder, though, and I'll apologize\n/// in advance for the weirdness too. The first argument to the closure is a\n/// `&BuildDeps`. This is the parsed version of a build script, and when Cargo\n/// starts up this is cached from previous runs of a build script.  After a\n/// build script executes the output file is reparsed and passed in here.\n///\n/// The second argument is the weirdest, it's *optionally* a closure to\n/// call [`pkg_fingerprint`]. The `pkg_fingerprint` requires access to\n/// \"source map\" located in `Context`. That's very non-`'static` and\n/// non-`Send`, so it can't be used on other threads, such as when we invoke\n/// this after a build script has finished. The `Option` allows us to for sure\n/// calculate it on the main thread at the beginning, and then swallow the bug\n/// for now where a worker thread after a build script has finished doesn't\n/// have access. Ideally there would be no second argument or it would be more\n/// \"first class\" and not an `Option` but something that can be sent between\n/// threads. In any case, it's a bug for now.\n///\n/// This isn't the greatest of interfaces, and if there's suggestions to\n/// improve please do so!\n///\n/// FIXME(#6779) - see all the words above\n///\n/// [`RunCustomBuild`]: crate::core::compiler::CompileMode::RunCustomBuild\nfn build_script_local_fingerprints(\n    build_runner: &mut BuildRunner<'_, '_>,\n    unit: &Unit,\n) -> CargoResult<(\n    Box<\n        dyn FnOnce(\n                &BuildDeps,\n                Option<&dyn Fn() -> CargoResult<String>>,\n            ) -> CargoResult<Option<Vec<LocalFingerprint>>>\n            + Send,\n    >,\n    bool,\n)> {\n    assert!(unit.mode.is_run_custom_build());\n    // First up, if this build script is entirely overridden, then we just\n    // return the hash of what we overrode it with. This is the easy case!\n    if let Some(fingerprint) = build_script_override_fingerprint(build_runner, unit) {\n        debug!(\"override local fingerprints deps {}\", unit.pkg);\n        return Ok((\n            Box::new(\n                move |_: &BuildDeps, _: Option<&dyn Fn() -> CargoResult<String>>| {\n                    Ok(Some(vec![fingerprint]))\n                },\n            ),\n            true, // this is an overridden build script\n        ));\n    }\n\n    // ... Otherwise this is a \"real\" build script and we need to return a real\n    // closure. Our returned closure classifies the build script based on\n    // whether it prints `rerun-if-*`. If it *doesn't* print this it's where the\n    // magical second argument comes into play, which fingerprints a whole\n    // package. Remember that the fact that this is an `Option` is a bug, but a\n    // longstanding bug, in Cargo. Recent refactorings just made it painfully\n    // obvious.\n    let pkg_root = unit.pkg.root().to_path_buf();\n    let build_dir = build_root(build_runner);\n    let env_config = Arc::clone(build_runner.bcx.gctx.env_config()?);\n    let calculate =\n        move |deps: &BuildDeps, pkg_fingerprint: Option<&dyn Fn() -> CargoResult<String>>| {\n            if deps.rerun_if_changed.is_empty() && deps.rerun_if_env_changed.is_empty() {\n                match pkg_fingerprint {\n                    // FIXME: this is somewhat buggy with respect to docker and\n                    // weird filesystems. The `Precalculated` variant\n                    // constructed below will, for `path` dependencies, contain\n                    // a stringified version of the mtime for the local crate.\n                    // This violates one of the things we describe in this\n                    // module's doc comment, never hashing mtimes. We should\n                    // figure out a better scheme where a package fingerprint\n                    // may be a string (like for a registry) or a list of files\n                    // (like for a path dependency). Those list of files would\n                    // be stored here rather than the mtime of them.\n                    Some(f) => {\n                        let s = f()?;\n                        debug!(\n                            \"old local fingerprints deps {:?} precalculated={:?}\",\n                            pkg_root, s\n                        );\n                        return Ok(Some(vec![LocalFingerprint::Precalculated(s)]));\n                    }\n                    None => return Ok(None),\n                }\n            }\n\n            // Ok so now we're in \"new mode\" where we can have files listed as\n            // dependencies as well as env vars listed as dependencies. Process\n            // them all here.\n            Ok(Some(local_fingerprints_deps(\n                deps,\n                &build_dir,\n                &pkg_root,\n                &env_config,\n            )))\n        };\n\n    // Note that `false` == \"not overridden\"\n    Ok((Box::new(calculate), false))\n}\n\n/// Create a [`LocalFingerprint`] for an overridden build script.\n/// Returns None if it is not overridden.\nfn build_script_override_fingerprint(\n    build_runner: &mut BuildRunner<'_, '_>,\n    unit: &Unit,\n) -> Option<LocalFingerprint> {\n    // Build script output is only populated at this stage when it is\n    // overridden.\n    let build_script_outputs = build_runner.build_script_outputs.lock().unwrap();\n    let metadata = build_runner.get_run_build_script_metadata(unit);\n    // Returns None if it is not overridden.\n    let output = build_script_outputs.get(metadata)?;\n    let s = format!(\n        \"overridden build state with hash: {}\",\n        util::hash_u64(output)\n    );\n    Some(LocalFingerprint::Precalculated(s))\n}\n\n/// Compute the [`LocalFingerprint`] values for a [`RunCustomBuild`] unit for\n/// non-overridden new-style build scripts only. This is only used when `deps`\n/// is already known to have a nonempty `rerun-if-*` somewhere.\n///\n/// [`RunCustomBuild`]: crate::core::compiler::CompileMode::RunCustomBuild\nfn local_fingerprints_deps(\n    deps: &BuildDeps,\n    build_root: &Path,\n    pkg_root: &Path,\n    env_config: &Arc<HashMap<String, OsString>>,\n) -> Vec<LocalFingerprint> {\n    debug!(\"new local fingerprints deps {:?}\", pkg_root);\n    let mut local = Vec::new();\n\n    if !deps.rerun_if_changed.is_empty() {\n        // Note that like the module comment above says we are careful to never\n        // store an absolute path in `LocalFingerprint`, so ensure that we strip\n        // absolute prefixes from them.\n        let output = deps\n            .build_script_output\n            .strip_prefix(build_root)\n            .unwrap()\n            .to_path_buf();\n        let paths = deps\n            .rerun_if_changed\n            .iter()\n            .map(|p| p.strip_prefix(pkg_root).unwrap_or(p).to_path_buf())\n            .collect();\n        local.push(LocalFingerprint::RerunIfChanged { output, paths });\n    }\n\n    local.extend(\n        deps.rerun_if_env_changed\n            .iter()\n            .map(|s| LocalFingerprint::from_env(s, env_config)),\n    );\n\n    local\n}\n\n/// Writes the short fingerprint hash value to `<loc>`\n/// and logs detailed JSON information to `<loc>.json`.\nfn write_fingerprint(loc: &Path, fingerprint: &Fingerprint) -> CargoResult<()> {\n    debug_assert_ne!(fingerprint.rustc, 0);\n    // fingerprint::new().rustc == 0, make sure it doesn't make it to the file system.\n    // This is mostly so outside tools can reliably find out what rust version this file is for,\n    // as we can use the full hash.\n    let hash = fingerprint.hash_u64();\n    debug!(\"write fingerprint ({:x}) : {}\", hash, loc.display());\n    paths::write(loc, util::to_hex(hash).as_bytes())?;\n\n    let json = serde_json::to_string(fingerprint).unwrap();\n    if cfg!(debug_assertions) {\n        let f: Fingerprint = serde_json::from_str(&json).unwrap();\n        assert_eq!(f.hash_u64(), hash);\n    }\n    paths::write(&loc.with_extension(\"json\"), json.as_bytes())?;\n    Ok(())\n}\n\n/// Prepare for work when a package starts to build\npub fn prepare_init(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<()> {\n    let new1 = build_runner.files().fingerprint_dir(unit);\n\n    // Doc tests have no output, thus no fingerprint.\n    if !new1.exists() && !unit.mode.is_doc_test() {\n        paths::create_dir_all(&new1)?;\n    }\n\n    Ok(())\n}\n\n/// Returns the location that the dep-info file will show up at\n/// for the [`Unit`] specified.\npub fn dep_info_loc(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> PathBuf {\n    build_runner.files().fingerprint_file_path(unit, \"dep-\")\n}\n\n/// Returns an absolute path that build directory.\n/// All paths are rewritten to be relative to this.\nfn build_root(build_runner: &BuildRunner<'_, '_>) -> PathBuf {\n    build_runner.bcx.ws.build_dir().into_path_unlocked()\n}\n\n/// Reads the value from the old fingerprint hash file and compare.\n///\n/// If dirty, it then restores the detailed information\n/// from the fingerprint JSON file, and provides an rich dirty reason.\nfn compare_old_fingerprint(\n    unit: &Unit,\n    old_hash_path: &Path,\n    new_fingerprint: &Fingerprint,\n    mtime_on_use: bool,\n    forced: bool,\n) -> FingerprintComparison {\n    if mtime_on_use {\n        // update the mtime so other cleaners know we used it\n        let t = FileTime::from_system_time(SystemTime::now());\n        debug!(\"mtime-on-use forcing {:?} to {}\", old_hash_path, t);\n        paths::set_file_time_no_err(old_hash_path, t);\n    }\n\n    let compare = _compare_old_fingerprint(old_hash_path, new_fingerprint);\n\n    match compare.as_ref() {\n        Ok(FingerprintComparison::Fresh) => {}\n        Ok(FingerprintComparison::Dirty { reason }) => {\n            info!(\n                \"fingerprint dirty for {}/{:?}/{:?}\",\n                unit.pkg, unit.mode, unit.target,\n            );\n            info!(\"    dirty: {reason:?}\");\n        }\n        Err(e) => {\n            info!(\n                \"fingerprint error for {}/{:?}/{:?}\",\n                unit.pkg, unit.mode, unit.target,\n            );\n            info!(\"    err: {e:?}\");\n        }\n    }\n\n    match compare {\n        Ok(FingerprintComparison::Fresh) if forced => FingerprintComparison::Dirty {\n            reason: DirtyReason::Forced,\n        },\n        Ok(cmp) => cmp,\n        Err(_) => FingerprintComparison::Dirty {\n            reason: DirtyReason::FreshBuild,\n        },\n    }\n}\n\nfn _compare_old_fingerprint(\n    old_hash_path: &Path,\n    new_fingerprint: &Fingerprint,\n) -> CargoResult<FingerprintComparison> {\n    let old_fingerprint_short = paths::read(old_hash_path)?;\n\n    let new_hash = new_fingerprint.hash_u64();\n\n    if util::to_hex(new_hash) == old_fingerprint_short && new_fingerprint.fs_status.up_to_date() {\n        return Ok(FingerprintComparison::Fresh);\n    }\n\n    let old_fingerprint_json = paths::read(&old_hash_path.with_extension(\"json\"))?;\n    let old_fingerprint: Fingerprint = serde_json::from_str(&old_fingerprint_json)\n        .with_context(|| internal(\"failed to deserialize json\"))?;\n    // Fingerprint can be empty after a failed rebuild (see comment in prepare_target).\n    if !old_fingerprint_short.is_empty() {\n        debug_assert_eq!(\n            util::to_hex(old_fingerprint.hash_u64()),\n            old_fingerprint_short\n        );\n    }\n\n    let reason = new_fingerprint.compare(&old_fingerprint);\n    Ok(FingerprintComparison::Dirty { reason })\n}\n\n/// Calculates the fingerprint of a unit thats contains no dep-info files.\nfn pkg_fingerprint(bcx: &BuildContext<'_, '_>, pkg: &Package) -> CargoResult<String> {\n    let source_id = pkg.package_id().source_id();\n    let sources = bcx.packages.sources();\n\n    let source = sources\n        .get(source_id)\n        .ok_or_else(|| internal(\"missing package source\"))?;\n    source.fingerprint(pkg)\n}\n\n/// The `reference` file is considered as \"stale\" if any file from `paths` has a newer mtime.\nfn find_stale_file<I, P>(\n    mtime_cache: &mut HashMap<PathBuf, FileTime>,\n    checksum_cache: &mut HashMap<PathBuf, Checksum>,\n    reference: &Path,\n    paths: I,\n    use_checksums: bool,\n) -> Option<StaleItem>\nwhere\n    I: IntoIterator<Item = (P, Option<(u64, Checksum)>)>,\n    P: AsRef<Path>,\n{\n    let reference_mtime = match paths::mtime(reference) {\n        Ok(mtime) => mtime,\n        Err(..) => {\n            return Some(StaleItem::MissingFile {\n                path: reference.to_path_buf(),\n            });\n        }\n    };\n\n    let skippable_dirs = if let Ok(cargo_home) = home::cargo_home() {\n        let skippable_dirs: Vec<_> = [\"git\", \"registry\"]\n            .into_iter()\n            .map(|subfolder| cargo_home.join(subfolder))\n            .collect();\n        Some(skippable_dirs)\n    } else {\n        None\n    };\n    for (path, prior_checksum) in paths {\n        let path = path.as_ref();\n\n        // Assuming anything in cargo_home/{git, registry} is immutable\n        // (see also #9455 about marking the src directory readonly) which avoids rebuilds when CI\n        // caches $CARGO_HOME/registry/{index, cache} and $CARGO_HOME/git/db across runs, keeping\n        // the content the same but changing the mtime.\n        if let Some(ref skippable_dirs) = skippable_dirs {\n            if skippable_dirs.iter().any(|dir| path.starts_with(dir)) {\n                continue;\n            }\n        }\n        if use_checksums {\n            let Some((file_len, prior_checksum)) = prior_checksum else {\n                return Some(StaleItem::MissingChecksum {\n                    path: path.to_path_buf(),\n                });\n            };\n            let path_buf = path.to_path_buf();\n\n            let path_checksum = match checksum_cache.entry(path_buf) {\n                Entry::Occupied(o) => *o.get(),\n                Entry::Vacant(v) => {\n                    let Ok(current_file_len) = fs::metadata(&path).map(|m| m.len()) else {\n                        return Some(StaleItem::FailedToReadMetadata {\n                            path: path.to_path_buf(),\n                        });\n                    };\n                    if current_file_len != file_len {\n                        return Some(StaleItem::FileSizeChanged {\n                            path: path.to_path_buf(),\n                            new_size: current_file_len,\n                            old_size: file_len,\n                        });\n                    }\n                    let Ok(file) = File::open(path) else {\n                        return Some(StaleItem::MissingFile {\n                            path: path.to_path_buf(),\n                        });\n                    };\n                    let Ok(checksum) = Checksum::compute(prior_checksum.algo(), file) else {\n                        return Some(StaleItem::UnableToReadFile {\n                            path: path.to_path_buf(),\n                        });\n                    };\n                    *v.insert(checksum)\n                }\n            };\n            if path_checksum == prior_checksum {\n                continue;\n            }\n            return Some(StaleItem::ChangedChecksum {\n                source: path.to_path_buf(),\n                stored_checksum: prior_checksum,\n                new_checksum: path_checksum,\n            });\n        } else {\n            let path_mtime = match mtime_cache.entry(path.to_path_buf()) {\n                Entry::Occupied(o) => *o.get(),\n                Entry::Vacant(v) => {\n                    let Ok(mtime) = paths::mtime_recursive(path) else {\n                        return Some(StaleItem::MissingFile {\n                            path: path.to_path_buf(),\n                        });\n                    };\n                    *v.insert(mtime)\n                }\n            };\n\n            // TODO: fix #5918.\n            // Note that equal mtimes should be considered \"stale\". For filesystems with\n            // not much timestamp precision like 1s this is would be a conservative approximation\n            // to handle the case where a file is modified within the same second after\n            // a build starts. We want to make sure that incremental rebuilds pick that up!\n            //\n            // For filesystems with nanosecond precision it's been seen in the wild that\n            // its \"nanosecond precision\" isn't really nanosecond-accurate. It turns out that\n            // kernels may cache the current time so files created at different times actually\n            // list the same nanosecond precision. Some digging on #5919 picked up that the\n            // kernel caches the current time between timer ticks, which could mean that if\n            // a file is updated at most 10ms after a build starts then Cargo may not\n            // pick up the build changes.\n            //\n            // All in all, an equality check here would be a conservative assumption that,\n            // if equal, files were changed just after a previous build finished.\n            // Unfortunately this became problematic when (in #6484) cargo switch to more accurately\n            // measuring the start time of builds.\n            if path_mtime <= reference_mtime {\n                continue;\n            }\n\n            return Some(StaleItem::ChangedFile {\n                reference: reference.to_path_buf(),\n                reference_mtime,\n                stale: path.to_path_buf(),\n                stale_mtime: path_mtime,\n            });\n        }\n    }\n\n    debug!(\n        \"all paths up-to-date relative to {:?} mtime={}\",\n        reference, reference_mtime\n    );\n    None\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/fingerprint/rustdoc.rs",
    "content": "use std::collections::HashMap;\nuse std::path::Path;\nuse std::path::PathBuf;\n\nuse anyhow::Context as _;\nuse cargo_util::paths;\nuse serde::Deserialize;\nuse serde::Serialize;\n\nuse crate::CargoResult;\nuse crate::core::compiler::BuildRunner;\nuse crate::core::compiler::CompileKind;\n\n/// JSON Schema of the [`RustdocFingerprint`] file.\n#[derive(Debug, Serialize, Deserialize)]\nstruct RustdocFingerprintJson {\n    /// `rustc -vV` verbose version output.\n    pub rustc_vv: String,\n\n    /// Relative paths to cross crate info JSON files from previous `cargo doc` invocations.\n    #[serde(default, skip_serializing_if = \"Vec::is_empty\")]\n    pub doc_parts: Vec<PathBuf>,\n}\n\n/// Structure used to deal with Rustdoc fingerprinting\n///\n/// This is important because the `.js`/`.html` & `.css` files\n/// that are generated by Rustc don't have any versioning yet\n/// (see <https://github.com/rust-lang/cargo/issues/8461>).\n/// Therefore, we can end up with weird bugs and behaviours\n/// if we mix different versions of these files.\n///\n/// We need to make sure that if there were any previous docs already compiled,\n/// they were compiled with the same Rustc version that we're currently using.\n/// Otherwise we must remove the `doc/` folder and compile again forcing a rebuild.\n#[derive(Debug)]\npub struct RustdocFingerprint {\n    /// Path to the fingerprint file.\n    path: PathBuf,\n    /// `rustc -vV` verbose version output for the current session.\n    rustc_vv: String,\n    /// Absolute paths to new cross crate info JSON files generated in the current session.\n    doc_parts: Vec<PathBuf>,\n    /// The fingerprint file on disk.\n    on_disk: Option<RustdocFingerprintJson>,\n}\n\nimpl RustdocFingerprint {\n    /// Checks whether the latest version of rustc used to compile this workspace's docs\n    /// was the same as the one is currently being used in this `cargo doc` call.\n    ///\n    /// In case it's not,\n    /// it takes care of removing the `<build-dir>/doc/` folder\n    /// as well as overwriting the rustdoc fingerprint info.\n    /// This is to guarantee that we won't end up with mixed versions of the `js/html/css` files\n    /// which `rustdoc` autogenerates without any versioning.\n    ///\n    /// Each requested target platform maintains its own fingerprint file.\n    /// That is, if you run `cargo doc` and then `cargo doc --target wasm32-wasip1`,\n    /// you will have two separate fingerprint files:\n    ///\n    /// * `<build-dir>/.rustdoc_fingerprint.json` for host\n    /// * `<build-dir>/wasm32-wasip1/.rustdoc_fingerprint.json`\n    pub fn check_rustdoc_fingerprint(build_runner: &BuildRunner<'_, '_>) -> CargoResult<()> {\n        if build_runner\n            .bcx\n            .gctx\n            .cli_unstable()\n            .skip_rustdoc_fingerprint\n        {\n            return Ok(());\n        }\n        let new_fingerprint = RustdocFingerprintJson {\n            rustc_vv: build_runner.bcx.rustc().verbose_version.clone(),\n            doc_parts: Vec::new(),\n        };\n\n        for kind in &build_runner.bcx.build_config.requested_kinds {\n            check_fingerprint(build_runner, &new_fingerprint, *kind)?;\n        }\n\n        Ok(())\n    }\n\n    /// Creates a new fingerprint with given doc parts paths.\n    pub fn new(\n        build_runner: &BuildRunner<'_, '_>,\n        kind: CompileKind,\n        doc_parts: Vec<PathBuf>,\n    ) -> Self {\n        let path = fingerprint_path(build_runner, kind);\n        let rustc_vv = build_runner.bcx.rustc().verbose_version.clone();\n        let on_disk = load_on_disk(&path);\n        Self {\n            path,\n            rustc_vv,\n            doc_parts,\n            on_disk,\n        }\n    }\n\n    /// Persists the fingerprint.\n    ///\n    /// The closure will run before persisting the fingerprint,\n    /// and will be given a list of doc parts directories for passing to\n    /// `rustdoc --include-parts-dir`.\n    pub fn persist<F>(&self, exec: F) -> CargoResult<()>\n    where\n        // 1. paths for `--include-parts-dir`\n        F: Fn(&[&Path]) -> CargoResult<()>,\n    {\n        // Dedupe crate with the same name by file stem (which is effectively crate name),\n        // since rustdoc doesn't distinguish different crate versions.\n        //\n        // Rules applied here:\n        //\n        // * If name collides, favor the one selected via CLI over cached ones\n        //   (done by the insertion order)\n        let base = self.path.parent().unwrap();\n        let on_disk_doc_parts: Vec<_> = self\n            .on_disk\n            .iter()\n            .flat_map(|on_disk| {\n                on_disk\n                    .doc_parts\n                    .iter()\n                    // Make absolute so that we can pass to rustdoc\n                    .map(|p| base.join(p))\n                    // Doc parts may be selectively cleaned by `cargo clean -p <doc>`.\n                    // We should stop caching those no-exist.\n                    .filter(|p| p.exists())\n            })\n            .collect();\n        let dedup_map = on_disk_doc_parts\n            .iter()\n            .chain(self.doc_parts.iter())\n            .map(|p| (p.file_stem(), p))\n            .collect::<HashMap<_, _>>();\n        let mut doc_parts: Vec<_> = dedup_map.into_values().collect();\n        doc_parts.sort_unstable();\n\n        // Prepare args for `rustdoc --include-parts-dir`\n        let doc_parts_dirs: Vec<_> = doc_parts.iter().map(|p| p.parent().unwrap()).collect();\n        exec(&doc_parts_dirs)?;\n\n        // Persist with relative paths to the directory where fingerprint file is at.\n        let json = RustdocFingerprintJson {\n            rustc_vv: self.rustc_vv.clone(),\n            doc_parts: doc_parts\n                .iter()\n                .map(|p| p.strip_prefix(base).unwrap_or(p).to_owned())\n                .collect(),\n        };\n        paths::write(&self.path, serde_json::to_string(&json)?)?;\n\n        Ok(())\n    }\n\n    /// Checks if the fingerprint is outdated comparing against given doc parts file paths.\n    pub fn is_dirty(&self) -> bool {\n        let Some(on_disk) = self.on_disk.as_ref() else {\n            return true;\n        };\n\n        let Some(fingerprint_mtime) = paths::mtime(&self.path).ok() else {\n            return true;\n        };\n\n        if self.rustc_vv != on_disk.rustc_vv {\n            return true;\n        }\n\n        for path in &self.doc_parts {\n            let parts_mtime = match paths::mtime(&path) {\n                Ok(mtime) => mtime,\n                Err(e) => {\n                    tracing::debug!(\"failed to read mtime of {}: {e}\", path.display());\n                    return true;\n                }\n            };\n\n            if parts_mtime > fingerprint_mtime {\n                return true;\n            }\n        }\n\n        false\n    }\n}\n\n/// Returns the path to rustdoc fingerprint file for a given [`CompileKind`].\nfn fingerprint_path(build_runner: &BuildRunner<'_, '_>, kind: CompileKind) -> PathBuf {\n    build_runner\n        .files()\n        .layout(kind)\n        .build_dir()\n        .root()\n        .join(\".rustdoc_fingerprint.json\")\n}\n\n/// Checks rustdoc fingerprint file for a given [`CompileKind`].\nfn check_fingerprint(\n    build_runner: &BuildRunner<'_, '_>,\n    new_fingerprint: &RustdocFingerprintJson,\n    kind: CompileKind,\n) -> CargoResult<()> {\n    let fingerprint_path = fingerprint_path(build_runner, kind);\n\n    let write_fingerprint = || -> CargoResult<()> {\n        paths::write(&fingerprint_path, serde_json::to_string(new_fingerprint)?)\n    };\n\n    let Ok(rustdoc_data) = paths::read(&fingerprint_path) else {\n        // If the fingerprint does not exist, do not clear out the doc\n        // directories. Otherwise this ran into problems where projects\n        // like bootstrap were creating the doc directory before running\n        // `cargo doc` in a way that deleting it would break it.\n        return write_fingerprint();\n    };\n\n    match serde_json::from_str::<RustdocFingerprintJson>(&rustdoc_data) {\n        Ok(on_disk_fingerprint) => {\n            if on_disk_fingerprint.rustc_vv == new_fingerprint.rustc_vv {\n                return Ok(());\n            } else {\n                tracing::debug!(\n                    \"doc fingerprint changed:\\noriginal:\\n{}\\nnew:\\n{}\",\n                    on_disk_fingerprint.rustc_vv,\n                    new_fingerprint.rustc_vv\n                );\n            }\n        }\n        Err(e) => {\n            tracing::debug!(\"could not deserialize {:?}: {}\", fingerprint_path, e);\n        }\n    };\n    // Fingerprint does not match, delete the doc directories and write a new fingerprint.\n    tracing::debug!(\n        \"fingerprint {:?} mismatch, clearing doc directories\",\n        fingerprint_path\n    );\n    let doc_dir = build_runner\n        .files()\n        .layout(kind)\n        .artifact_dir()\n        .expect(\"artifact-dir was not locked\")\n        .doc();\n    if doc_dir.exists() {\n        clean_doc(doc_dir)?;\n    }\n\n    write_fingerprint()?;\n\n    Ok(())\n}\n\n/// Loads an on-disk fingerprint JSON file.\nfn load_on_disk(path: &Path) -> Option<RustdocFingerprintJson> {\n    let on_disk = match paths::read(path) {\n        Ok(data) => data,\n        Err(e) => {\n            tracing::debug!(\"failed to read rustdoc fingerprint at {path:?}: {e}\");\n            return None;\n        }\n    };\n\n    match serde_json::from_str::<RustdocFingerprintJson>(&on_disk) {\n        Ok(on_disk) => Some(on_disk),\n        Err(e) => {\n            tracing::debug!(\"could not deserialize {path:?}: {e}\");\n            None\n        }\n    }\n}\n\nfn clean_doc(path: &Path) -> CargoResult<()> {\n    let entries = path\n        .read_dir()\n        .with_context(|| format!(\"failed to read directory `{}`\", path.display()))?;\n    for entry in entries {\n        let entry = entry?;\n        // Don't remove hidden files. Rustdoc does not create them,\n        // but the user might have.\n        if entry\n            .file_name()\n            .to_str()\n            .map_or(false, |name| name.starts_with('.'))\n        {\n            continue;\n        }\n        let path = entry.path();\n        if entry.file_type()?.is_dir() {\n            paths::remove_dir_all(path)?;\n        } else {\n            paths::remove_file(path)?;\n        }\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/future_incompat.rs",
    "content": "//! Support for [future-incompatible warning reporting][1].\n//!\n//! Here is an overview of how Cargo handles future-incompatible reports.\n//!\n//! ## Receive reports from the compiler\n//!\n//! When receiving a compiler message during a build, if it is effectively\n//! a [`FutureIncompatReport`], Cargo gathers and forwards it as a\n//! `Message::FutureIncompatReport` to the main thread.\n//!\n//! To have the correct layout of structures for deserializing a report\n//! emitted by the compiler, most of structure definitions, for example\n//! [`FutureIncompatReport`], are copied either partially or entirely from\n//! [compiler/rustc_errors/src/json.rs][2] in rust-lang/rust repository.\n//!\n//! ## Persist reports on disk\n//!\n//! When a build comes to an end, by calling [`save_and_display_report`]\n//! Cargo saves the report on disk, and displays it directly if requested\n//! via command line or configuration. The information of the on-disk file can\n//! be found in [`FUTURE_INCOMPAT_FILE`].\n//!\n//! During the persistent process, Cargo will attempt to query the source of\n//! each package emitting the report, for the sake of providing an upgrade\n//! information as a solution to fix the incompatibility.\n//!\n//! ## Display reports to users\n//!\n//! Users can run `cargo report future-incompat` to retrieve a report. This is\n//! done by [`OnDiskReports::load`]. Cargo simply prints reports to the\n//! standard output.\n//!\n//! [1]: https://doc.rust-lang.org/nightly/cargo/reference/future-incompat-report.html\n//! [2]: https://github.com/rust-lang/rust/blob/9bb6e60d1f1360234aae90c97964c0fa5524f141/compiler/rustc_errors/src/json.rs#L312-L315\n\nuse crate::core::compiler::BuildContext;\nuse crate::core::{Dependency, PackageId, Workspace};\nuse crate::sources::SourceConfigMap;\nuse crate::sources::source::QueryKind;\nuse crate::util::CargoResult;\nuse crate::util::cache_lock::CacheLockMode;\nuse anyhow::{Context, bail, format_err};\nuse serde::{Deserialize, Serialize};\nuse std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};\nuse std::fmt::Write as _;\nuse std::io::{Read, Write};\nuse std::task::Poll;\n\npub const REPORT_PREAMBLE: &str = \"\\\nThe following warnings were discovered during the build. These warnings are an\nindication that the packages contain code that will become an error in a\nfuture release of Rust. These warnings typically cover changes to close\nsoundness problems, unintended or undocumented behavior, or critical problems\nthat cannot be fixed in a backwards-compatible fashion, and are not expected\nto be in wide use.\n\nEach warning should contain a link for more information on what the warning\nmeans and how to resolve it.\n\";\n\n/// Current version of the on-disk format.\nconst ON_DISK_VERSION: u32 = 0;\n\n/// The future incompatibility report, emitted by the compiler as a JSON message.\n#[derive(serde::Deserialize)]\npub struct FutureIncompatReport {\n    pub future_incompat_report: Vec<FutureBreakageItem>,\n}\n\n/// Structure used for collecting reports in-memory.\npub struct FutureIncompatReportPackage {\n    pub package_id: PackageId,\n    /// Whether or not this is a local package, or a remote dependency.\n    pub is_local: bool,\n    pub items: Vec<FutureBreakageItem>,\n}\n\n/// A single future-incompatible warning emitted by rustc.\n#[derive(Serialize, Deserialize)]\npub struct FutureBreakageItem {\n    /// The date at which this lint will become an error.\n    /// Currently unused\n    pub future_breakage_date: Option<String>,\n    /// The original diagnostic emitted by the compiler\n    pub diagnostic: Diagnostic,\n}\n\n/// A diagnostic emitted by the compiler as a JSON message.\n/// We only care about the 'rendered' field\n#[derive(Serialize, Deserialize)]\npub struct Diagnostic {\n    pub rendered: String,\n    pub level: String,\n}\n\n/// The filename in the top-level `build-dir` directory where we store\n/// the report\nconst FUTURE_INCOMPAT_FILE: &str = \".future-incompat-report.json\";\n/// Max number of reports to save on disk.\nconst MAX_REPORTS: usize = 5;\n\n/// The structure saved to disk containing the reports.\n#[derive(Serialize, Deserialize)]\npub struct OnDiskReports {\n    /// A schema version number, to handle older cargo's from trying to read\n    /// something that they don't understand.\n    version: u32,\n    /// The report ID to use for the next report to save.\n    next_id: u32,\n    /// Available reports.\n    reports: Vec<OnDiskReport>,\n}\n\n/// A single report for a given compilation session.\n#[derive(Serialize, Deserialize)]\nstruct OnDiskReport {\n    /// Unique reference to the report for the `--id` CLI flag.\n    id: u32,\n    /// A message describing suggestions for fixing the\n    /// reported issues\n    suggestion_message: String,\n    /// Report, suitable for printing to the console.\n    /// Maps package names to the corresponding report\n    /// We use a `BTreeMap` so that the iteration order\n    /// is stable across multiple runs of `cargo`\n    per_package: BTreeMap<String, String>,\n}\n\nimpl Default for OnDiskReports {\n    fn default() -> OnDiskReports {\n        OnDiskReports {\n            version: ON_DISK_VERSION,\n            next_id: 1,\n            reports: Vec::new(),\n        }\n    }\n}\n\nimpl OnDiskReports {\n    /// Saves a new report returning its id\n    pub fn save_report(\n        mut self,\n        ws: &Workspace<'_>,\n        suggestion_message: String,\n        per_package: BTreeMap<String, String>,\n    ) -> u32 {\n        if let Some(existing_id) = self.has_report(&per_package) {\n            return existing_id;\n        }\n\n        let report = OnDiskReport {\n            id: self.next_id,\n            suggestion_message,\n            per_package,\n        };\n\n        let saved_id = report.id;\n        self.next_id += 1;\n        self.reports.push(report);\n        if self.reports.len() > MAX_REPORTS {\n            self.reports.remove(0);\n        }\n        let on_disk = serde_json::to_vec(&self).unwrap();\n        if let Err(e) = ws\n            .build_dir()\n            .open_rw_exclusive_create(\n                FUTURE_INCOMPAT_FILE,\n                ws.gctx(),\n                \"Future incompatibility report\",\n            )\n            .and_then(|file| {\n                let mut file = file.file();\n                file.set_len(0)?;\n                file.write_all(&on_disk)?;\n                Ok(())\n            })\n        {\n            crate::display_warning_with_error(\n                \"failed to write on-disk future incompatible report\",\n                &e,\n                &mut ws.gctx().shell(),\n            );\n        }\n\n        saved_id\n    }\n\n    /// Returns the ID of a report if it is already on disk.\n    fn has_report(&self, rendered_per_package: &BTreeMap<String, String>) -> Option<u32> {\n        self.reports\n            .iter()\n            .find(|existing| &existing.per_package == rendered_per_package)\n            .map(|report| report.id)\n    }\n\n    /// Loads the on-disk reports.\n    pub fn load(ws: &Workspace<'_>) -> CargoResult<OnDiskReports> {\n        let report_file = match ws.build_dir().open_ro_shared(\n            FUTURE_INCOMPAT_FILE,\n            ws.gctx(),\n            \"Future incompatible report\",\n        ) {\n            Ok(r) => r,\n            Err(e) => {\n                if let Some(io_err) = e.downcast_ref::<std::io::Error>() {\n                    if io_err.kind() == std::io::ErrorKind::NotFound {\n                        bail!(\"no reports are currently available\");\n                    }\n                }\n                return Err(e);\n            }\n        };\n\n        let mut file_contents = String::new();\n        report_file\n            .file()\n            .read_to_string(&mut file_contents)\n            .context(\"failed to read report\")?;\n        let on_disk_reports: OnDiskReports =\n            serde_json::from_str(&file_contents).context(\"failed to load report\")?;\n        if on_disk_reports.version != ON_DISK_VERSION {\n            bail!(\"unable to read reports; reports were saved from a future version of Cargo\");\n        }\n        Ok(on_disk_reports)\n    }\n\n    /// Returns the most recent report ID.\n    pub fn last_id(&self) -> u32 {\n        self.reports.last().map(|r| r.id).unwrap()\n    }\n\n    /// Returns an ANSI-styled report\n    pub fn get_report(&self, id: u32, package: Option<&str>) -> CargoResult<String> {\n        let report = self.reports.iter().find(|r| r.id == id).ok_or_else(|| {\n            let available = itertools::join(self.reports.iter().map(|r| r.id), \", \");\n            format_err!(\n                \"could not find report with ID {}\\n\\\n                 Available IDs are: {}\",\n                id,\n                available\n            )\n        })?;\n\n        let mut to_display = report.suggestion_message.clone();\n        to_display += \"\\n\";\n\n        let package_report = if let Some(package) = package {\n            report\n                .per_package\n                .get(package)\n                .ok_or_else(|| {\n                    format_err!(\n                        \"could not find package with ID `{}`\\n\n                Available packages are: {}\\n\n                Omit the `--package` flag to display a report for all packages\",\n                        package,\n                        itertools::join(report.per_package.keys(), \", \")\n                    )\n                })?\n                .to_string()\n        } else {\n            report\n                .per_package\n                .values()\n                .cloned()\n                .collect::<Vec<_>>()\n                .join(\"\\n\")\n        };\n        to_display += &package_report;\n\n        Ok(to_display)\n    }\n}\n\nfn render_report(per_package_reports: &[FutureIncompatReportPackage]) -> BTreeMap<String, String> {\n    let mut report: BTreeMap<String, String> = BTreeMap::new();\n    for per_package in per_package_reports {\n        let package_spec = format!(\n            \"{}@{}\",\n            per_package.package_id.name(),\n            per_package.package_id.version()\n        );\n        let rendered = report.entry(package_spec).or_default();\n        rendered.push_str(&format!(\n            \"The package `{}` currently triggers the following future incompatibility lints:\\n\",\n            per_package.package_id\n        ));\n        for item in &per_package.items {\n            rendered.extend(\n                item.diagnostic\n                    .rendered\n                    .lines()\n                    .map(|l| format!(\"> {}\\n\", l)),\n            );\n        }\n    }\n    report\n}\n\n/// Returns a user-readable message explaining which of\n/// the packages in `package_ids` have updates available.\n/// This is best-effort - if an error occurs, `None` will be returned.\nfn get_updates(ws: &Workspace<'_>, package_ids: &BTreeSet<PackageId>) -> Option<String> {\n    // This in general ignores all errors since this is opportunistic.\n    let _lock = ws\n        .gctx()\n        .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)\n        .ok()?;\n    // Create a set of updated registry sources.\n    let map = SourceConfigMap::new(ws.gctx()).ok()?;\n    let mut package_ids: BTreeSet<_> = package_ids\n        .iter()\n        .filter(|pkg_id| pkg_id.source_id().is_registry())\n        .collect();\n    let source_ids: HashSet<_> = package_ids\n        .iter()\n        .map(|pkg_id| pkg_id.source_id())\n        .collect();\n    let mut sources: HashMap<_, _> = source_ids\n        .into_iter()\n        .filter_map(|sid| {\n            let source = map.load(sid, &HashSet::new()).ok()?;\n            Some((sid, source))\n        })\n        .collect();\n\n    // Query the sources for new versions, mapping `package_ids` into `summaries`.\n    let mut summaries = Vec::new();\n    while !package_ids.is_empty() {\n        package_ids.retain(|&pkg_id| {\n            let Some(source) = sources.get_mut(&pkg_id.source_id()) else {\n                return false;\n            };\n            let Ok(dep) = Dependency::parse(pkg_id.name(), None, pkg_id.source_id()) else {\n                return false;\n            };\n            match source.query_vec(&dep, QueryKind::Exact) {\n                Poll::Ready(Ok(sum)) => {\n                    summaries.push((pkg_id, sum));\n                    false\n                }\n                Poll::Ready(Err(_)) => false,\n                Poll::Pending => true,\n            }\n        });\n        for (_, source) in sources.iter_mut() {\n            source.block_until_ready().ok()?;\n        }\n    }\n\n    let mut updates = String::new();\n    for (pkg_id, summaries) in summaries {\n        let mut updated_versions: Vec<_> = summaries\n            .iter()\n            .map(|summary| summary.as_summary().version())\n            .filter(|version| *version > pkg_id.version())\n            .collect();\n        updated_versions.sort();\n\n        if !updated_versions.is_empty() {\n            let updated_versions = itertools::join(updated_versions, \", \");\n            write!(\n                updates,\n                \"\n  - {} has the following newer versions available: {}\",\n                pkg_id, updated_versions\n            )\n            .unwrap();\n        }\n    }\n    Some(updates)\n}\n\n/// Writes a future-incompat report to disk, using the per-package\n/// reports gathered during the build. If requested by the user,\n/// a message is also displayed in the build output.\npub fn save_and_display_report(\n    bcx: &BuildContext<'_, '_>,\n    per_package_future_incompat_reports: &[FutureIncompatReportPackage],\n) {\n    let should_display_message = match bcx.gctx.future_incompat_config() {\n        Ok(config) => config.should_display_message(),\n        Err(e) => {\n            crate::display_warning_with_error(\n                \"failed to read future-incompat config from disk\",\n                &e,\n                &mut bcx.gctx.shell(),\n            );\n            true\n        }\n    };\n\n    if per_package_future_incompat_reports.is_empty() {\n        // Explicitly passing a command-line flag overrides\n        // `should_display_message` from the config file\n        if bcx.build_config.future_incompat_report {\n            drop(\n                bcx.gctx\n                    .shell()\n                    .note(\"0 dependencies had future-incompatible warnings\"),\n            );\n        }\n        return;\n    }\n\n    let current_reports = match OnDiskReports::load(bcx.ws) {\n        Ok(r) => r,\n        Err(e) => {\n            tracing::debug!(\n                \"saving future-incompatible reports failed to load current reports: {:?}\",\n                e\n            );\n            OnDiskReports::default()\n        }\n    };\n\n    let rendered_report = render_report(per_package_future_incompat_reports);\n\n    // If the report is already on disk, then it will reuse the same ID,\n    // otherwise prepare for the next ID.\n    let report_id = current_reports\n        .has_report(&rendered_report)\n        .unwrap_or(current_reports.next_id);\n\n    // Get a list of unique and sorted package name/versions.\n    let package_ids: BTreeSet<_> = per_package_future_incompat_reports\n        .iter()\n        .map(|r| r.package_id)\n        .collect();\n    let package_vers: Vec<_> = package_ids.iter().map(|pid| pid.to_string()).collect();\n\n    let updated_versions = get_updates(bcx.ws, &package_ids).unwrap_or(String::new());\n\n    let update_message = if !updated_versions.is_empty() {\n        format!(\n            \"\\\nupdate to a newer version to see if the issue has been fixed{updated_versions}\",\n            updated_versions = updated_versions\n        )\n    } else {\n        String::new()\n    };\n\n    let upstream_info = package_ids\n        .iter()\n        .map(|package_id| {\n            let manifest = bcx.packages.get_one(*package_id).unwrap().manifest();\n            format!(\n                \"  - {package_spec}\n  - repository: {url}\n  - detailed warning command: `cargo report future-incompatibilities --id {id} --package {package_spec}`\",\n                package_spec = format!(\"{}@{}\", package_id.name(), package_id.version()),\n                url = manifest\n                    .metadata()\n                    .repository\n                    .as_deref()\n                    .unwrap_or(\"<not found>\"),\n                id = report_id,\n            )\n        })\n        .collect::<Vec<_>>()\n        .join(\"\\n\\n\");\n\n    let all_is_local = per_package_future_incompat_reports\n        .iter()\n        .all(|report| report.is_local);\n\n    let suggestion_header = \"to solve this problem, you can try the following approaches:\";\n    let mut suggestions = Vec::new();\n    if !all_is_local {\n        if !update_message.is_empty() {\n            suggestions.push(update_message);\n        }\n        suggestions.push(format!(\n            \"\\\nensure the maintainers know of this problem (e.g. creating a bug report if needed)\nor even helping with a fix (e.g. by creating a pull request)\n{upstream_info}\"\n        ));\n        suggestions.push(\n            \"\\\nuse your own version of the dependency with the `[patch]` section in `Cargo.toml`\nFor more information, see:\nhttps://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section\"\n                .to_owned(),\n        );\n    }\n\n    let suggestion_message = if suggestions.is_empty() {\n        String::new()\n    } else {\n        let mut suggestion_message = String::new();\n        writeln!(&mut suggestion_message, \"{suggestion_header}\").unwrap();\n        for suggestion in &suggestions {\n            writeln!(\n                &mut suggestion_message,\n                \"\n- {suggestion}\"\n            )\n            .unwrap();\n        }\n        suggestion_message\n    };\n    let saved_report_id =\n        current_reports.save_report(bcx.ws, suggestion_message.clone(), rendered_report);\n\n    if should_display_message || bcx.build_config.future_incompat_report {\n        use annotate_snippets::*;\n        let mut report = vec![Group::with_title(Level::WARNING.secondary_title(format!(\n            \"the following packages contain code that will be rejected by a future \\\n             version of Rust: {}\",\n            package_vers.join(\", \")\n        )))];\n        if bcx.build_config.future_incompat_report {\n            for suggestion in &suggestions {\n                report.push(Group::with_title(Level::HELP.secondary_title(suggestion)));\n            }\n            report.push(Group::with_title(Level::NOTE.secondary_title(format!(\n                \"this report can be shown with `cargo report \\\n             future-incompatibilities --id {}`\",\n                saved_report_id\n            ))));\n        } else if should_display_message {\n            report.push(Group::with_title(Level::NOTE.secondary_title(format!(\n                \"to see what the problems were, use the option \\\n             `--future-incompat-report`, or run `cargo report \\\n             future-incompatibilities --id {}`\",\n                saved_report_id\n            ))));\n        }\n        drop(bcx.gctx.shell().print_report(&report, false))\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/job_queue/job.rs",
    "content": "//! See [`Job`] and [`Work`].\n\nuse std::fmt;\nuse std::mem;\n\nuse super::JobState;\nuse crate::core::compiler::fingerprint::DirtyReason;\nuse crate::util::CargoResult;\n\n/// Represents a unit of [`Work`] with a [`Freshness`] for caller\n/// to determine whether to re-execute or not.\npub struct Job {\n    work: Work,\n    fresh: Freshness,\n}\n\n/// The basic unit of work.\n///\n/// Each proc should send its description before starting.\n/// It should send either once or close immediately.\npub struct Work {\n    inner: Box<dyn FnOnce(&JobState<'_, '_>) -> CargoResult<()> + Send>,\n}\n\nimpl Work {\n    /// Creates a unit of work.\n    pub fn new<F>(f: F) -> Work\n    where\n        F: FnOnce(&JobState<'_, '_>) -> CargoResult<()> + Send + 'static,\n    {\n        Work { inner: Box::new(f) }\n    }\n\n    /// Creates a unit of work that does nothing.\n    pub fn noop() -> Work {\n        Work::new(|_| Ok(()))\n    }\n\n    /// Consumes this work by running it.\n    pub fn call(self, tx: &JobState<'_, '_>) -> CargoResult<()> {\n        (self.inner)(tx)\n    }\n\n    /// Creates a new unit of work that chains `next` after ourself.\n    pub fn then(self, next: Work) -> Work {\n        Work::new(move |state| {\n            self.call(state)?;\n            next.call(state)\n        })\n    }\n}\n\nimpl Job {\n    /// Creates a new job that does nothing.\n    pub fn new_fresh() -> Job {\n        Job {\n            work: Work::noop(),\n            fresh: Freshness::Fresh,\n        }\n    }\n\n    /// Creates a new job representing a unit of work.\n    pub fn new_dirty(work: Work, dirty_reason: DirtyReason) -> Job {\n        Job {\n            work,\n            fresh: Freshness::Dirty(dirty_reason),\n        }\n    }\n\n    /// Consumes this job by running it, returning the result of the\n    /// computation.\n    pub fn run(self, state: &JobState<'_, '_>) -> CargoResult<()> {\n        self.work.call(state)\n    }\n\n    /// Returns whether this job was fresh/dirty, where \"fresh\" means we're\n    /// likely to perform just some small bookkeeping where \"dirty\" means we'll\n    /// probably do something slow like invoke rustc.\n    pub fn freshness(&self) -> &Freshness {\n        &self.fresh\n    }\n\n    /// Chains the given work by putting it in front of our own unit of work.\n    pub fn before(&mut self, next: Work) {\n        let prev = mem::replace(&mut self.work, Work::noop());\n        self.work = next.then(prev);\n    }\n\n    /// Chains the given work by putting it after of our own unit of work.\n    pub fn after(&mut self, next: Work) {\n        let prev = mem::replace(&mut self.work, Work::noop());\n        self.work = prev.then(next);\n    }\n}\n\nimpl fmt::Debug for Job {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"Job {{ ... }}\")\n    }\n}\n\n/// Indication of the freshness of a package.\n///\n/// A fresh package does not necessarily need to be rebuilt (unless a dependency\n/// was also rebuilt), and a dirty package must always be rebuilt.\n#[derive(Debug, Clone)]\npub enum Freshness {\n    Fresh,\n    Dirty(DirtyReason),\n}\n\nimpl Freshness {\n    pub fn is_dirty(&self) -> bool {\n        matches!(self, Freshness::Dirty(_))\n    }\n\n    pub fn is_fresh(&self) -> bool {\n        matches!(self, Freshness::Fresh)\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/job_queue/job_state.rs",
    "content": "//! See [`JobState`].\n\nuse std::{cell::Cell, marker, sync::Arc};\n\nuse cargo_util::ProcessBuilder;\n\nuse crate::core::compiler::future_incompat::FutureBreakageItem;\nuse crate::core::compiler::locking::LockKey;\nuse crate::core::compiler::timings::SectionTiming;\nuse crate::util::Queue;\nuse crate::{CargoResult, core::compiler::locking::LockManager};\n\nuse super::{Artifact, DiagDedupe, Job, JobId, Message};\n\n/// A `JobState` is constructed by `JobQueue::run` and passed to `Job::run`. It includes everything\n/// necessary to communicate between the main thread and the execution of the job.\n///\n/// The job may execute on either a dedicated thread or the main thread. If the job executes on the\n/// main thread, the `output` field must be set to prevent a deadlock.\npub struct JobState<'a, 'gctx> {\n    /// Channel back to the main thread to coordinate messages and such.\n    ///\n    /// When the `output` field is `Some`, care must be taken to avoid calling `push_bounded` on\n    /// the message queue to prevent a deadlock.\n    messages: Arc<Queue<Message>>,\n\n    /// Normally output is sent to the job queue with backpressure. When the job is fresh\n    /// however we need to immediately display the output to prevent a deadlock as the\n    /// output messages are processed on the same thread as they are sent from. `output`\n    /// defines where to output in this case.\n    ///\n    /// Currently the [`Shell`] inside [`GlobalContext`] is wrapped in a `RefCell` and thus can't\n    /// be passed between threads. This means that it isn't possible for multiple output messages\n    /// to be interleaved. In the future, it may be wrapped in a `Mutex` instead. In this case\n    /// interleaving is still prevented as the lock would be held for the whole printing of an\n    /// output message.\n    ///\n    /// [`Shell`]: crate::core::Shell\n    /// [`GlobalContext`]: crate::GlobalContext\n    output: Option<&'a DiagDedupe<'gctx>>,\n\n    /// The job id that this state is associated with, used when sending\n    /// messages back to the main thread.\n    id: JobId,\n\n    /// Whether or not we're expected to have a call to `rmeta_produced`. Once\n    /// that method is called this is dynamically set to `false` to prevent\n    /// sending a double message later on.\n    rmeta_required: Cell<bool>,\n\n    /// Manages locks for build units when fine grain locking is enabled.\n    lock_manager: Arc<LockManager>,\n\n    // Historical versions of Cargo made use of the `'a` argument here, so to\n    // leave the door open to future refactorings keep it here.\n    _marker: marker::PhantomData<&'a ()>,\n}\n\nimpl<'a, 'gctx> JobState<'a, 'gctx> {\n    pub(super) fn new(\n        id: JobId,\n        messages: Arc<Queue<Message>>,\n        output: Option<&'a DiagDedupe<'gctx>>,\n        rmeta_required: bool,\n        lock_manager: Arc<LockManager>,\n    ) -> Self {\n        Self {\n            id,\n            messages,\n            output,\n            rmeta_required: Cell::new(rmeta_required),\n            lock_manager,\n            _marker: marker::PhantomData,\n        }\n    }\n\n    pub fn running(&self, cmd: &ProcessBuilder) {\n        self.messages.push(Message::Run(self.id, cmd.to_string()));\n    }\n\n    pub fn stdout(&self, stdout: String) -> CargoResult<()> {\n        if let Some(dedupe) = self.output {\n            writeln!(dedupe.gctx.shell().out(), \"{}\", stdout)?;\n        } else {\n            self.messages.push_bounded(Message::Stdout(stdout));\n        }\n        Ok(())\n    }\n\n    pub fn stderr(&self, stderr: String) -> CargoResult<()> {\n        if let Some(dedupe) = self.output {\n            let mut shell = dedupe.gctx.shell();\n            shell.print_ansi_stderr(stderr.as_bytes())?;\n            shell.err().write_all(b\"\\n\")?;\n        } else {\n            self.messages.push_bounded(Message::Stderr(stderr));\n        }\n        Ok(())\n    }\n\n    /// See [`Message::Diagnostic`] and [`Message::WarningCount`].\n    pub fn emit_diag(\n        &self,\n        level: &str,\n        diag: String,\n        lint: bool,\n        fixable: bool,\n    ) -> CargoResult<()> {\n        if let Some(dedupe) = self.output {\n            let emitted = dedupe.emit_diag(&diag)?;\n            if level == \"warning\" {\n                self.messages.push(Message::WarningCount {\n                    id: self.id,\n                    lint,\n                    emitted,\n                    fixable,\n                });\n            }\n        } else {\n            self.messages.push_bounded(Message::Diagnostic {\n                id: self.id,\n                level: level.to_string(),\n                diag,\n                lint,\n                fixable,\n            });\n        }\n        Ok(())\n    }\n\n    /// See [`Message::Warning`].\n    pub fn warning(&self, warning: String) {\n        self.messages.push_bounded(Message::Warning {\n            id: self.id,\n            warning,\n        });\n    }\n\n    /// A method used to signal to the coordinator thread that the rmeta file\n    /// for an rlib has been produced. This is only called for some rmeta\n    /// builds when required, and can be called at any time before a job ends.\n    /// This should only be called once because a metadata file can only be\n    /// produced once!\n    pub fn rmeta_produced(&self) {\n        self.rmeta_required.set(false);\n        self.messages\n            .push(Message::Finish(self.id, Artifact::Metadata, Ok(())));\n    }\n\n    pub fn lock_exclusive(&self, lock: &LockKey) -> CargoResult<()> {\n        self.lock_manager.lock(lock)\n    }\n\n    pub fn downgrade_to_shared(&self, lock: &LockKey) -> CargoResult<()> {\n        self.lock_manager.downgrade_to_shared(lock)\n    }\n\n    pub fn on_section_timing_emitted(&self, section: SectionTiming) {\n        self.messages.push(Message::SectionTiming(self.id, section));\n    }\n\n    /// Drives a [`Job`] to finish. This ensures that a [`Message::Finish`] is\n    /// sent even if our job panics.\n    pub(super) fn run_to_finish(self, job: Job) {\n        let mut sender = FinishOnDrop {\n            messages: &self.messages,\n            id: self.id,\n            result: None,\n        };\n        sender.result = Some(job.run(&self));\n\n        // If the `rmeta_required` wasn't consumed but it was set\n        // previously, then we either have:\n        //\n        // 1. The `job` didn't do anything because it was \"fresh\".\n        // 2. The `job` returned an error and didn't reach the point where\n        //    it called `rmeta_produced`.\n        // 3. We forgot to call `rmeta_produced` and there's a bug in Cargo.\n        //\n        // Ruling out the third, the other two are pretty common for 2\n        // we'll just naturally abort the compilation operation but for 1\n        // we need to make sure that the metadata is flagged as produced so\n        // send a synthetic message here.\n        if self.rmeta_required.get() && sender.result.as_ref().unwrap().is_ok() {\n            self.messages\n                .push(Message::Finish(self.id, Artifact::Metadata, Ok(())));\n        }\n\n        // Use a helper struct with a `Drop` implementation to guarantee\n        // that a `Finish` message is sent even if our job panics. We\n        // shouldn't panic unless there's a bug in Cargo, so we just need\n        // to make sure nothing hangs by accident.\n        struct FinishOnDrop<'a> {\n            messages: &'a Queue<Message>,\n            id: JobId,\n            result: Option<CargoResult<()>>,\n        }\n\n        impl Drop for FinishOnDrop<'_> {\n            fn drop(&mut self) {\n                let result = self\n                    .result\n                    .take()\n                    .unwrap_or_else(|| Err(anyhow::format_err!(\"worker panicked\")));\n                self.messages\n                    .push(Message::Finish(self.id, Artifact::All, result));\n            }\n        }\n    }\n\n    pub fn future_incompat_report(&self, report: Vec<FutureBreakageItem>) {\n        self.messages\n            .push(Message::FutureIncompatReport(self.id, report));\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/job_queue/mod.rs",
    "content": "//! Management of the interaction between the main `cargo` and all spawned jobs.\n//!\n//! ## Overview\n//!\n//! This module implements a job queue. A job here represents a unit of work,\n//! which is roughly a rustc invocation, a build script run, or just a no-op.\n//! The job queue primarily handles the following things:\n//!\n//! * Spawns concurrent jobs. Depending on its [`Freshness`], a job could be\n//!     either executed on a spawned thread or ran on the same thread to avoid\n//!     the threading overhead.\n//! * Controls the number of concurrency. It allocates and manages [`jobserver`]\n//!     tokens to each spawned off rustc and build scripts.\n//! * Manages the communication between the main `cargo` process and its\n//!     spawned jobs. Those [`Message`]s are sent over a [`Queue`] shared\n//!     across threads.\n//! * Schedules the execution order of each [`Job`]. Priorities are determined\n//!     when calling [`JobQueue::enqueue`] to enqueue a job. The scheduling is\n//!     relatively rudimentary and could likely be improved.\n//!\n//! A rough outline of building a queue and executing jobs is:\n//!\n//! 1. [`JobQueue::new`] to simply create one queue.\n//! 2. [`JobQueue::enqueue`] to add new jobs onto the queue.\n//! 3. Consumes the queue and executes all jobs via [`JobQueue::execute`].\n//!\n//! The primary loop happens insides [`JobQueue::execute`], which is effectively\n//! [`DrainState::drain_the_queue`]. [`DrainState`] is, as its name tells,\n//! the running state of the job queue getting drained.\n//!\n//! ## Jobserver\n//!\n//! As of Feb. 2023, Cargo and rustc have a relatively simple jobserver\n//! relationship with each other. They share a single jobserver amongst what\n//! is potentially hundreds of threads of work on many-cored systems.\n//! The jobserver could come from either the environment (e.g., from a `make`\n//! invocation), or from Cargo creating its own jobserver server if there is no\n//! jobserver to inherit from.\n//!\n//! Cargo wants to complete the build as quickly as possible, fully saturating\n//! all cores (as constrained by the `-j=N`) parameter. Cargo also must not spawn\n//! more than N threads of work: the total amount of tokens we have floating\n//! around must always be limited to N.\n//!\n//! It is not really possible to optimally choose which crate should build\n//! first or last; nor is it possible to decide whether to give an additional\n//! token to rustc first or rather spawn a new crate of work. The algorithm in\n//! Cargo prioritizes spawning as many crates (i.e., rustc processes) as\n//! possible. In short, the jobserver relationship among Cargo and rustc\n//! processes is **1 `cargo` to N `rustc`**. Cargo knows nothing beyond rustc\n//! processes in terms of parallelism[^parallel-rustc].\n//!\n//! We integrate with the [jobserver] crate, originating from GNU make\n//! [POSIX jobserver], to make sure that build scripts which use make to\n//! build C code can cooperate with us on the number of used tokens and\n//! avoid overfilling the system we're on.\n//!\n//! ## Scheduling\n//!\n//! The current scheduling algorithm is not really polished. It is simply based\n//! on a dependency graph [`DependencyQueue`]. We continue adding nodes onto\n//! the graph until we finalize it. When the graph gets finalized, it finds the\n//! sum of the cost of each dependencies of each node, including transitively.\n//! The sum of dependency cost turns out to be the cost of each given node.\n//!\n//! At the time being, the cost is just passed as a fixed placeholder in\n//! [`JobQueue::enqueue`]. In the future, we could explore more possibilities\n//! around it. For instance, we start persisting timing information for each\n//! build somewhere. For a subsequent build, we can look into the historical\n//! data and perform a PGO-like optimization to prioritize jobs, making a build\n//! fully pipelined.\n//!\n//! ## Message queue\n//!\n//! Each spawned thread running a process uses the message queue [`Queue`] to\n//! send messages back to the main thread (the one running `cargo`).\n//! The main thread coordinates everything, and handles printing output.\n//!\n//! It is important to be careful which messages use [`push`] vs [`push_bounded`].\n//! `push` is for priority messages (like tokens, or \"finished\") where the\n//! sender shouldn't block. We want to handle those so real work can proceed\n//! ASAP.\n//!\n//! `push_bounded` is only for messages being printed to stdout/stderr. Being\n//! bounded prevents a flood of messages causing a large amount of memory\n//! being used.\n//!\n//! `push` also avoids blocking which helps avoid deadlocks. For example, when\n//! the diagnostic server thread is dropped, it waits for the thread to exit.\n//! But if the thread is blocked on a full queue, and there is a critical\n//! error, the drop will deadlock. This should be fixed at some point in the\n//! future. The jobserver thread has a similar problem, though it will time\n//! out after 1 second.\n//!\n//! To access the message queue, each running `Job` is given its own [`JobState`],\n//! containing everything it needs to communicate with the main thread.\n//!\n//! See [`Message`] for all available message kinds.\n//!\n//! [^parallel-rustc]: In fact, `jobserver` that Cargo uses also manages the\n//!     allocation of tokens to rustc beyond the implicit token each rustc owns\n//!     (i.e., the ones used for parallel LLVM work and parallel rustc threads).\n//!     See also [\"Rust Compiler Development Guide: Parallel Compilation\"]\n//!     and [this comment][rustc-codegen] in rust-lang/rust.\n//!\n//! [\"Rust Compiler Development Guide: Parallel Compilation\"]: https://rustc-dev-guide.rust-lang.org/parallel-rustc.html\n//! [rustc-codegen]: https://github.com/rust-lang/rust/blob/5423745db8b434fcde54888b35f518f00cce00e4/compiler/rustc_codegen_ssa/src/back/write.rs#L1204-L1217\n//! [jobserver]: https://docs.rs/jobserver\n//! [POSIX jobserver]: https://www.gnu.org/software/make/manual/html_node/POSIX-Jobserver.html\n//! [`push`]: Queue::push\n//! [`push_bounded`]: Queue::push_bounded\n\nmod job;\nmod job_state;\n\nuse std::cell::RefCell;\nuse std::collections::{HashMap, HashSet};\nuse std::fmt::Write as _;\nuse std::path::{Path, PathBuf};\nuse std::sync::Arc;\nuse std::thread::{self, Scope};\nuse std::time::Duration;\nuse std::{env, io};\n\nuse anyhow::{Context as _, format_err};\nuse jobserver::{Acquired, HelperThread};\nuse semver::Version;\nuse tracing::{debug, trace};\n\npub use self::job::Freshness::{self, Dirty, Fresh};\npub use self::job::{Job, Work};\npub use self::job_state::JobState;\nuse super::BuildContext;\nuse super::BuildRunner;\nuse super::CompileMode;\nuse super::Unit;\nuse super::UnitIndex;\nuse super::custom_build::Severity;\nuse super::timings::SectionTiming;\nuse super::timings::Timings;\nuse crate::core::compiler::descriptive_pkg_name;\nuse crate::core::compiler::future_incompat::{\n    self, FutureBreakageItem, FutureIncompatReportPackage,\n};\nuse crate::core::resolver::ResolveBehavior;\nuse crate::core::{PackageId, Shell, TargetKind};\nuse crate::util::CargoResult;\nuse crate::util::context::WarningHandling;\nuse crate::util::diagnostic_server::{self, DiagnosticPrinter};\nuse crate::util::errors::AlreadyPrintedError;\nuse crate::util::machine_message::{self, Message as _};\nuse crate::util::{self, internal};\nuse crate::util::{DependencyQueue, GlobalContext, Progress, ProgressStyle, Queue};\n\n/// This structure is backed by the `DependencyQueue` type and manages the\n/// queueing of compilation steps for each package. Packages enqueue units of\n/// work and then later on the entire graph is converted to `DrainState` and\n/// executed.\npub struct JobQueue<'gctx> {\n    queue: DependencyQueue<Unit, Artifact, Job>,\n    counts: HashMap<PackageId, usize>,\n    timings: Timings<'gctx>,\n}\n\n/// This structure is backed by the `DependencyQueue` type and manages the\n/// actual compilation step of each package. Packages enqueue units of work and\n/// then later on the entire graph is processed and compiled.\n///\n/// It is created from `JobQueue` when we have fully assembled the crate graph\n/// (i.e., all package dependencies are known).\nstruct DrainState<'gctx> {\n    // This is the length of the DependencyQueue when starting out\n    total_units: usize,\n\n    queue: DependencyQueue<Unit, Artifact, Job>,\n    messages: Arc<Queue<Message>>,\n    /// Diagnostic deduplication support.\n    diag_dedupe: DiagDedupe<'gctx>,\n    /// Count of warnings, used to print a summary after the job succeeds\n    warning_count: HashMap<JobId, WarningCount>,\n    active: HashMap<JobId, Unit>,\n    compiled: HashSet<PackageId>,\n    documented: HashSet<PackageId>,\n    scraped: HashSet<PackageId>,\n    counts: HashMap<PackageId, usize>,\n    progress: Progress<'gctx>,\n    next_id: u32,\n    timings: Timings<'gctx>,\n\n    /// Map from unit index to unit, for looking up dependency information.\n    index_to_unit: HashMap<UnitIndex, Unit>,\n\n    /// Tokens that are currently owned by this Cargo, and may be \"associated\"\n    /// with a rustc process. They may also be unused, though if so will be\n    /// dropped on the next loop iteration.\n    ///\n    /// Note that the length of this may be zero, but we will still spawn work,\n    /// as we share the implicit token given to this Cargo process with a\n    /// single rustc process.\n    tokens: Vec<Acquired>,\n\n    /// The list of jobs that we have not yet started executing, but have\n    /// retrieved from the `queue`. We eagerly pull jobs off the main queue to\n    /// allow us to request jobserver tokens pretty early.\n    pending_queue: Vec<(Unit, Job, usize)>,\n    print: DiagnosticPrinter<'gctx>,\n\n    /// How many jobs we've finished\n    finished: usize,\n    per_package_future_incompat_reports: Vec<FutureIncompatReportPackage>,\n}\n\n/// Count of warnings, used to print a summary after the job succeeds\n#[derive(Default, Clone)]\npub struct WarningCount {\n    /// total number of warnings\n    pub total: usize,\n    /// number of lint warnings\n    pub lints: usize,\n    /// number of warnings that were suppressed because they\n    /// were duplicates of a previous warning\n    pub duplicates: usize,\n    /// number of fixable warnings set to `NotAllowed`\n    /// if any errors have been seen for the current\n    /// target\n    pub fixable: FixableWarnings,\n}\n\nimpl WarningCount {\n    /// If an error is seen this should be called\n    /// to set `fixable` to `NotAllowed`\n    fn disallow_fixable(&mut self) {\n        self.fixable = FixableWarnings::NotAllowed;\n    }\n\n    /// Checks fixable if warnings are allowed\n    /// fixable warnings are allowed if no\n    /// errors have been seen for the current\n    /// target. If an error was seen `fixable`\n    /// will be `NotAllowed`.\n    fn fixable_allowed(&self) -> bool {\n        match &self.fixable {\n            FixableWarnings::NotAllowed => false,\n            _ => true,\n        }\n    }\n}\n\n/// Used to keep track of how many fixable warnings there are\n/// and if fixable warnings are allowed\n#[derive(Default, Copy, Clone)]\npub enum FixableWarnings {\n    NotAllowed,\n    #[default]\n    Zero,\n    Positive(usize),\n}\n\npub struct ErrorsDuringDrain {\n    pub count: usize,\n}\n\nstruct ErrorToHandle {\n    error: anyhow::Error,\n\n    /// This field is true for \"interesting\" errors and false for \"mundane\"\n    /// errors. If false, we print the above error only if it's the first one\n    /// encountered so far while draining the job queue.\n    ///\n    /// At most places that an error is propagated, we set this to false to\n    /// avoid scenarios where Cargo might end up spewing tons of redundant error\n    /// messages. For example if an i/o stream got closed somewhere, we don't\n    /// care about individually reporting every thread that it broke; just the\n    /// first is enough.\n    ///\n    /// The exception where `print_always` is true is that we do report every\n    /// instance of a rustc invocation that failed with diagnostics. This\n    /// corresponds to errors from `Message::Finish`.\n    print_always: bool,\n}\n\nimpl<E> From<E> for ErrorToHandle\nwhere\n    anyhow::Error: From<E>,\n{\n    fn from(error: E) -> Self {\n        ErrorToHandle {\n            error: anyhow::Error::from(error),\n            print_always: false,\n        }\n    }\n}\n\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]\npub struct JobId(pub u32);\n\nimpl std::fmt::Display for JobId {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}\", self.0)\n    }\n}\n\n/// Handler for deduplicating diagnostics.\nstruct DiagDedupe<'gctx> {\n    seen: RefCell<HashSet<u64>>,\n    gctx: &'gctx GlobalContext,\n}\n\nimpl<'gctx> DiagDedupe<'gctx> {\n    fn new(gctx: &'gctx GlobalContext) -> Self {\n        DiagDedupe {\n            seen: RefCell::new(HashSet::new()),\n            gctx,\n        }\n    }\n\n    /// Emits a diagnostic message.\n    ///\n    /// Returns `true` if the message was emitted, or `false` if it was\n    /// suppressed for being a duplicate.\n    fn emit_diag(&self, diag: &str) -> CargoResult<bool> {\n        let h = util::hash_u64(diag);\n        if !self.seen.borrow_mut().insert(h) {\n            return Ok(false);\n        }\n        let mut shell = self.gctx.shell();\n        shell.print_ansi_stderr(diag.as_bytes())?;\n        shell.err().write_all(b\"\\n\")?;\n        Ok(true)\n    }\n}\n\n/// Possible artifacts that can be produced by compilations, used as edge values\n/// in the dependency graph.\n///\n/// As edge values we can have multiple kinds of edges depending on one node,\n/// for example some units may only depend on the metadata for an rlib while\n/// others depend on the full rlib. This `Artifact` enum is used to distinguish\n/// this case and track the progress of compilations as they proceed.\n#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]\nenum Artifact {\n    /// A generic placeholder for \"depends on everything run by a step\" and\n    /// means that we can't start the next compilation until the previous has\n    /// finished entirely.\n    All,\n\n    /// A node indicating that we only depend on the metadata of a compilation,\n    /// but the compilation is typically also producing an rlib. We can start\n    /// our step, however, before the full rlib is available.\n    Metadata,\n}\n\nenum Message {\n    Run(JobId, String),\n    Stdout(String),\n    Stderr(String),\n\n    // This is for general stderr output from subprocesses\n    Diagnostic {\n        id: JobId,\n        level: String,\n        diag: String,\n        lint: bool,\n        fixable: bool,\n    },\n    // This handles duplicate output that is suppressed, for showing\n    // only a count of duplicate messages instead\n    WarningCount {\n        id: JobId,\n        lint: bool,\n        emitted: bool,\n        fixable: bool,\n    },\n    // This is for warnings generated by Cargo's interpretation of the\n    // subprocess output, e.g. scrape-examples prints a warning if a\n    // unit fails to be scraped\n    Warning {\n        id: JobId,\n        warning: String,\n    },\n\n    FixDiagnostic(diagnostic_server::Message),\n    Token(io::Result<Acquired>),\n    Finish(JobId, Artifact, CargoResult<()>),\n    FutureIncompatReport(JobId, Vec<FutureBreakageItem>),\n    SectionTiming(JobId, SectionTiming),\n}\n\nimpl<'gctx> JobQueue<'gctx> {\n    pub fn new(bcx: &BuildContext<'_, 'gctx>) -> JobQueue<'gctx> {\n        JobQueue {\n            queue: DependencyQueue::new(),\n            counts: HashMap::new(),\n            timings: Timings::new(bcx),\n        }\n    }\n\n    pub fn enqueue(\n        &mut self,\n        build_runner: &BuildRunner<'_, 'gctx>,\n        unit: &Unit,\n        job: Job,\n    ) -> CargoResult<()> {\n        let dependencies = build_runner.unit_deps(unit);\n        let mut queue_deps = dependencies\n            .iter()\n            .filter(|dep| {\n                // Binaries aren't actually needed to *compile* tests, just to run\n                // them, so we don't include this dependency edge in the job graph.\n                // But we shouldn't filter out dependencies being scraped for Rustdoc.\n                (!dep.unit.target.is_test() && !dep.unit.target.is_bin())\n                    || dep.unit.artifact.is_true()\n                    || dep.unit.mode.is_doc_scrape()\n            })\n            .map(|dep| {\n                // Handle the case here where our `unit -> dep` dependency may\n                // only require the metadata, not the full compilation to\n                // finish. Use the tables in `build_runner` to figure out what\n                // kind of artifact is associated with this dependency.\n                let artifact = if build_runner.only_requires_rmeta(unit, &dep.unit) {\n                    Artifact::Metadata\n                } else {\n                    Artifact::All\n                };\n                (dep.unit.clone(), artifact)\n            })\n            .collect::<HashMap<_, _>>();\n\n        // This is somewhat tricky, but we may need to synthesize some\n        // dependencies for this target if it requires full upstream\n        // compilations to have completed. Because of pipelining, some\n        // dependency edges may be `Metadata` due to the above clause (as\n        // opposed to everything being `All`). For example consider:\n        //\n        //    a (binary)\n        //    └ b (lib)\n        //        └ c (lib)\n        //\n        // Here the dependency edge from B to C will be `Metadata`, and the\n        // dependency edge from A to B will be `All`. For A to be compiled,\n        // however, it currently actually needs the full rlib of C. This means\n        // that we need to synthesize a dependency edge for the dependency graph\n        // from A to C. That's done here.\n        //\n        // This will walk all dependencies of the current target, and if any of\n        // *their* dependencies are `Metadata` then we depend on the `All` of\n        // the target as well. This should ensure that edges changed to\n        // `Metadata` propagate upwards `All` dependencies to anything that\n        // transitively contains the `Metadata` edge.\n        if unit.requires_upstream_objects() {\n            for dep in dependencies {\n                depend_on_deps_of_deps(build_runner, &mut queue_deps, dep.unit.clone());\n            }\n\n            fn depend_on_deps_of_deps(\n                build_runner: &BuildRunner<'_, '_>,\n                deps: &mut HashMap<Unit, Artifact>,\n                unit: Unit,\n            ) {\n                for dep in build_runner.unit_deps(&unit) {\n                    if deps.insert(dep.unit.clone(), Artifact::All).is_none() {\n                        depend_on_deps_of_deps(build_runner, deps, dep.unit.clone());\n                    }\n                }\n            }\n        }\n\n        // For now we use a fixed placeholder value for the cost of each unit, but\n        // in the future this could be used to allow users to provide hints about\n        // relative expected costs of units, or this could be automatically set in\n        // a smarter way using timing data from a previous compilation.\n        self.queue.queue(unit.clone(), job, queue_deps, 100);\n        *self.counts.entry(unit.pkg.package_id()).or_insert(0) += 1;\n        Ok(())\n    }\n\n    /// Executes all jobs necessary to build the dependency graph.\n    ///\n    /// This function will spawn off `config.jobs()` workers to build all of the\n    /// necessary dependencies, in order. Freshness is propagated as far as\n    /// possible along each dependency chain.\n    #[tracing::instrument(skip_all)]\n    pub fn execute(mut self, build_runner: &mut BuildRunner<'_, '_>) -> CargoResult<()> {\n        self.queue.queue_finished();\n\n        let progress =\n            Progress::with_style(\"Building\", ProgressStyle::Ratio, build_runner.bcx.gctx);\n        let state = DrainState {\n            total_units: self.queue.len(),\n            queue: self.queue,\n            // 100 here is somewhat arbitrary. It is a few screenfulls of\n            // output, and hopefully at most a few megabytes of memory for\n            // typical messages. If you change this, please update the test\n            // caching_large_output, too.\n            messages: Arc::new(Queue::new(100)),\n            diag_dedupe: DiagDedupe::new(build_runner.bcx.gctx),\n            warning_count: HashMap::new(),\n            active: HashMap::new(),\n            compiled: HashSet::new(),\n            documented: HashSet::new(),\n            scraped: HashSet::new(),\n            counts: self.counts,\n            progress,\n            next_id: 0,\n            timings: self.timings,\n            index_to_unit: build_runner\n                .bcx\n                .unit_to_index\n                .iter()\n                .map(|(unit, &index)| (index, unit.clone()))\n                .collect(),\n            tokens: Vec::new(),\n            pending_queue: Vec::new(),\n            print: DiagnosticPrinter::new(\n                build_runner.bcx.gctx,\n                &build_runner.bcx.rustc().workspace_wrapper,\n            ),\n            finished: 0,\n            per_package_future_incompat_reports: Vec::new(),\n        };\n\n        // Create a helper thread for acquiring jobserver tokens\n        let messages = state.messages.clone();\n        let helper = build_runner\n            .jobserver\n            .clone()\n            .into_helper_thread(move |token| {\n                messages.push(Message::Token(token));\n            })\n            .context(\"failed to create helper thread for jobserver management\")?;\n\n        // Create a helper thread to manage the diagnostics for rustfix if\n        // necessary.\n        let messages = state.messages.clone();\n        // It is important that this uses `push` instead of `push_bounded` for\n        // now. If someone wants to fix this to be bounded, the `drop`\n        // implementation needs to be changed to avoid possible deadlocks.\n        let _diagnostic_server = build_runner\n            .bcx\n            .build_config\n            .rustfix_diagnostic_server\n            .borrow_mut()\n            .take()\n            .map(move |srv| srv.start(move |msg| messages.push(Message::FixDiagnostic(msg))));\n\n        thread::scope(\n            move |scope| match state.drain_the_queue(build_runner, scope, &helper) {\n                Some(err) => Err(err),\n                None => Ok(()),\n            },\n        )\n    }\n}\n\nimpl<'gctx> DrainState<'gctx> {\n    fn spawn_work_if_possible<'s>(\n        &mut self,\n        build_runner: &mut BuildRunner<'_, '_>,\n        jobserver_helper: &HelperThread,\n        scope: &'s Scope<'s, '_>,\n    ) -> CargoResult<()> {\n        // Dequeue as much work as we can, learning about everything\n        // possible that can run. Note that this is also the point where we\n        // start requesting job tokens. Each job after the first needs to\n        // request a token.\n        while let Some((unit, job, priority)) = self.queue.dequeue() {\n            // We want to keep the pieces of work in the `pending_queue` sorted\n            // by their priorities, and insert the current job at its correctly\n            // sorted position: following the lower priority jobs, and the ones\n            // with the same priority (since they were dequeued before the\n            // current one, we also keep that relation).\n            let idx = self\n                .pending_queue\n                .partition_point(|&(_, _, p)| p <= priority);\n            self.pending_queue.insert(idx, (unit, job, priority));\n            if self.active.len() + self.pending_queue.len() > 1 {\n                jobserver_helper.request_token();\n            }\n        }\n\n        // Now that we've learned of all possible work that we can execute\n        // try to spawn it so long as we've got a jobserver token which says\n        // we're able to perform some parallel work.\n        // The `pending_queue` is sorted in ascending priority order, and we\n        // remove items from its end to schedule the highest priority items\n        // sooner.\n        while self.has_extra_tokens() && !self.pending_queue.is_empty() {\n            let (unit, job, _) = self.pending_queue.pop().unwrap();\n            *self.counts.get_mut(&unit.pkg.package_id()).unwrap() -= 1;\n            // Print out some nice progress information.\n            // NOTE: An error here will drop the job without starting it.\n            // That should be OK, since we want to exit as soon as\n            // possible during an error.\n            self.note_working_on(\n                build_runner.bcx.gctx,\n                build_runner.bcx.ws.root(),\n                &unit,\n                job.freshness(),\n            )?;\n            self.run(&unit, job, build_runner, scope);\n        }\n\n        Ok(())\n    }\n\n    fn has_extra_tokens(&self) -> bool {\n        self.active.len() < self.tokens.len() + 1\n    }\n\n    fn handle_event(\n        &mut self,\n        build_runner: &mut BuildRunner<'_, '_>,\n        event: Message,\n    ) -> Result<(), ErrorToHandle> {\n        let warning_handling = build_runner.bcx.gctx.warning_handling()?;\n        match event {\n            Message::Run(id, cmd) => {\n                build_runner\n                    .bcx\n                    .gctx\n                    .shell()\n                    .verbose(|c| c.status(\"Running\", &cmd))?;\n                self.timings\n                    .unit_start(build_runner, id, self.active[&id].clone());\n            }\n            Message::Stdout(out) => {\n                writeln!(build_runner.bcx.gctx.shell().out(), \"{}\", out)?;\n            }\n            Message::Stderr(err) => {\n                let mut shell = build_runner.bcx.gctx.shell();\n                shell.print_ansi_stderr(err.as_bytes())?;\n                shell.err().write_all(b\"\\n\")?;\n            }\n            Message::Diagnostic {\n                id,\n                level,\n                diag,\n                lint,\n                fixable,\n            } => {\n                let emitted = self.diag_dedupe.emit_diag(&diag)?;\n                if level == \"warning\" {\n                    self.bump_warning_count(id, lint, emitted, fixable);\n                }\n                if level == \"error\" {\n                    let count = self.warning_count.entry(id).or_default();\n                    // If there is an error, the `cargo fix` message should not show\n                    count.disallow_fixable();\n                }\n            }\n            Message::Warning { id, warning } => {\n                if warning_handling != WarningHandling::Allow {\n                    build_runner.bcx.gctx.shell().warn(warning)?;\n                }\n                let lint = false;\n                let emitted = true;\n                let fixable = false;\n                self.bump_warning_count(id, lint, emitted, fixable);\n            }\n            Message::WarningCount {\n                id,\n                lint,\n                emitted,\n                fixable,\n            } => {\n                self.bump_warning_count(id, lint, emitted, fixable);\n            }\n            Message::FixDiagnostic(msg) => {\n                self.print.print(&msg)?;\n            }\n            Message::Finish(id, artifact, mut result) => {\n                let unit = match artifact {\n                    // If `id` has completely finished we remove it\n                    // from the `active` map ...\n                    Artifact::All => {\n                        trace!(\"end: {:?}\", id);\n                        self.finished += 1;\n                        let unit = self.active.remove(&id).unwrap();\n                        // An error could add an entry for a `Unit`\n                        // with 0 warnings but having fixable\n                        // warnings be disallowed\n                        let count = self\n                            .warning_count\n                            .get(&id)\n                            .filter(|count| 0 < count.total)\n                            .cloned();\n                        if let Some(count) = count {\n                            self.report_warning_count(\n                                build_runner,\n                                &unit,\n                                &count,\n                                &build_runner.bcx.rustc().workspace_wrapper,\n                                warning_handling,\n                            );\n                            let stop_on_warnings = warning_handling == WarningHandling::Deny\n                                && 0 < count.lints\n                                && !build_runner.bcx.build_config.keep_going;\n                            if stop_on_warnings {\n                                result = Err(anyhow::format_err!(\n                                    \"warnings are denied by `build.warnings` configuration\"\n                                ))\n                            }\n                        }\n                        unit\n                    }\n                    // ... otherwise if it hasn't finished we leave it\n                    // in there as we'll get another `Finish` later on.\n                    Artifact::Metadata => {\n                        trace!(\"end (meta): {:?}\", id);\n                        self.active[&id].clone()\n                    }\n                };\n                debug!(\"end ({:?}): {:?}\", unit, result);\n                match result {\n                    Ok(()) => self.finish(id, &unit, artifact, build_runner)?,\n                    Err(_) if build_runner.bcx.unit_can_fail_for_docscraping(&unit) => {\n                        build_runner\n                            .failed_scrape_units\n                            .lock()\n                            .unwrap()\n                            .insert(build_runner.files().metadata(&unit).unit_id());\n                        self.queue.finish(&unit, &artifact);\n                    }\n                    Err(error) => {\n                        let show_warnings = true;\n                        self.emit_log_messages(&unit, build_runner, show_warnings)?;\n                        self.back_compat_notice(build_runner, &unit)?;\n                        return Err(ErrorToHandle {\n                            error,\n                            print_always: true,\n                        });\n                    }\n                }\n            }\n            Message::FutureIncompatReport(id, items) => {\n                let unit = &self.active[&id];\n                let package_id = unit.pkg.package_id();\n                let is_local = unit.is_local();\n                self.per_package_future_incompat_reports\n                    .push(FutureIncompatReportPackage {\n                        package_id,\n                        is_local,\n                        items,\n                    });\n            }\n            Message::Token(acquired_token) => {\n                let token = acquired_token.context(\"failed to acquire jobserver token\")?;\n                self.tokens.push(token);\n            }\n            Message::SectionTiming(id, section) => {\n                self.timings.unit_section_timing(build_runner, id, &section);\n            }\n        }\n\n        Ok(())\n    }\n\n    // This will also tick the progress bar as appropriate\n    fn wait_for_events(&mut self) -> Vec<Message> {\n        // Drain all events at once to avoid displaying the progress bar\n        // unnecessarily. If there's no events we actually block waiting for\n        // an event, but we keep a \"heartbeat\" going to allow `record_cpu`\n        // to run above to calculate CPU usage over time. To do this we\n        // listen for a message with a timeout, and on timeout we run the\n        // previous parts of the loop again.\n        let mut events = self.messages.try_pop_all();\n        if events.is_empty() {\n            loop {\n                self.tick_progress();\n                self.tokens.truncate(self.active.len() - 1);\n                match self.messages.pop(Duration::from_millis(500)) {\n                    Some(message) => {\n                        events.push(message);\n                        break;\n                    }\n                    None => continue,\n                }\n            }\n        }\n        events\n    }\n\n    /// This is the \"main\" loop, where Cargo does all work to run the\n    /// compiler.\n    ///\n    /// This returns an Option to prevent the use of `?` on `Result` types\n    /// because it is important for the loop to carefully handle errors.\n    fn drain_the_queue<'s>(\n        mut self,\n        build_runner: &mut BuildRunner<'_, '_>,\n        scope: &'s Scope<'s, '_>,\n        jobserver_helper: &HelperThread,\n    ) -> Option<anyhow::Error> {\n        trace!(\"queue: {:#?}\", self.queue);\n\n        // Iteratively execute the entire dependency graph. Each turn of the\n        // loop starts out by scheduling as much work as possible (up to the\n        // maximum number of parallel jobs we have tokens for). A local queue\n        // is maintained separately from the main dependency queue as one\n        // dequeue may actually dequeue quite a bit of work (e.g., 10 binaries\n        // in one package).\n        //\n        // After a job has finished we update our internal state if it was\n        // successful and otherwise wait for pending work to finish if it failed\n        // and then immediately return (or keep going, if requested by the build\n        // config).\n        let mut errors = ErrorsDuringDrain { count: 0 };\n        // CAUTION! Do not use `?` or break out of the loop early. Every error\n        // must be handled in such a way that the loop is still allowed to\n        // drain event messages.\n        loop {\n            if errors.count == 0 || build_runner.bcx.build_config.keep_going {\n                if let Err(e) = self.spawn_work_if_possible(build_runner, jobserver_helper, scope) {\n                    self.handle_error(&mut build_runner.bcx.gctx.shell(), &mut errors, e);\n                }\n            }\n\n            // If after all that we're not actually running anything then we're\n            // done!\n            if self.active.is_empty() {\n                break;\n            }\n\n            // And finally, before we block waiting for the next event, drop any\n            // excess tokens we may have accidentally acquired. Due to how our\n            // jobserver interface is architected we may acquire a token that we\n            // don't actually use, and if this happens just relinquish it back\n            // to the jobserver itself.\n            for event in self.wait_for_events() {\n                if let Err(event_err) = self.handle_event(build_runner, event) {\n                    self.handle_error(&mut build_runner.bcx.gctx.shell(), &mut errors, event_err);\n                }\n            }\n        }\n        self.progress.clear();\n\n        let profile_name = build_runner.bcx.build_config.requested_profile;\n        // NOTE: this may be a bit inaccurate, since this may not display the\n        // profile for what was actually built. Profile overrides can change\n        // these settings, and in some cases different targets are built with\n        // different profiles. To be accurate, it would need to collect a\n        // list of Units built, and maybe display a list of the different\n        // profiles used. However, to keep it simple and compatible with old\n        // behavior, we just display what the base profile is.\n        let profile = build_runner.bcx.profiles.base_profile();\n        let mut opt_type = String::from(if profile.opt_level.as_str() == \"0\" {\n            \"unoptimized\"\n        } else {\n            \"optimized\"\n        });\n        if profile.debuginfo.is_turned_on() {\n            opt_type += \" + debuginfo\";\n        }\n\n        let time_elapsed = util::elapsed(build_runner.bcx.gctx.creation_time().elapsed());\n        if let Err(e) = self\n            .timings\n            .finished(build_runner, &errors.to_error())\n            .context(\"failed to render timing report\")\n        {\n            self.handle_error(&mut build_runner.bcx.gctx.shell(), &mut errors, e);\n        }\n        if build_runner.bcx.build_config.emit_json() {\n            let mut shell = build_runner.bcx.gctx.shell();\n            let msg = machine_message::BuildFinished {\n                success: errors.count == 0,\n            }\n            .to_json_string();\n            if let Err(e) = writeln!(shell.out(), \"{}\", msg) {\n                self.handle_error(&mut shell, &mut errors, e);\n            }\n        }\n\n        if let Some(error) = errors.to_error() {\n            // Any errors up to this point have already been printed via the\n            // `display_error` inside `handle_error`.\n            Some(anyhow::Error::new(AlreadyPrintedError::new(error)))\n        } else if self.queue.is_empty() && self.pending_queue.is_empty() {\n            let profile_link = build_runner.bcx.gctx.shell().err_hyperlink(\n                \"https://doc.rust-lang.org/cargo/reference/profiles.html#default-profiles\",\n            );\n            let message = format!(\n                \"{profile_link}`{profile_name}` profile [{opt_type}]{profile_link:#} target(s) in {time_elapsed}\",\n            );\n            // It doesn't really matter if this fails.\n            let _ = build_runner.bcx.gctx.shell().status(\"Finished\", message);\n            future_incompat::save_and_display_report(\n                build_runner.bcx,\n                &self.per_package_future_incompat_reports,\n            );\n\n            None\n        } else {\n            debug!(\"queue: {:#?}\", self.queue);\n            Some(internal(\"finished with jobs still left in the queue\"))\n        }\n    }\n\n    fn handle_error(\n        &mut self,\n        shell: &mut Shell,\n        err_state: &mut ErrorsDuringDrain,\n        new_err: impl Into<ErrorToHandle>,\n    ) {\n        let new_err = new_err.into();\n        if new_err.print_always || err_state.count == 0 {\n            crate::display_error(&new_err.error, shell);\n            if err_state.count == 0 && !self.active.is_empty() {\n                self.progress.indicate_error();\n                let _ = shell.warn(\"build failed, waiting for other jobs to finish...\");\n            }\n            err_state.count += 1;\n        } else {\n            tracing::warn!(\"{:?}\", new_err.error);\n        }\n    }\n\n    // This also records CPU usage and marks concurrency; we roughly want to do\n    // this as often as we spin on the events receiver (at least every 500ms or\n    // so).\n    fn tick_progress(&mut self) {\n        // Record some timing information if `--timings` is enabled, and\n        // this'll end up being a noop if we're not recording this\n        // information.\n        self.timings.record_cpu();\n\n        let active_names = self\n            .active\n            .values()\n            .map(|u| self.name_for_progress(u))\n            .collect::<Vec<_>>();\n        let _ = self.progress.tick_now(\n            self.finished,\n            self.total_units,\n            &format!(\": {}\", active_names.join(\", \")),\n        );\n    }\n\n    fn name_for_progress(&self, unit: &Unit) -> String {\n        let pkg_name = unit.pkg.name();\n        let target_name = unit.target.name();\n        match unit.mode {\n            CompileMode::Doc { .. } => format!(\"{}(doc)\", pkg_name),\n            CompileMode::RunCustomBuild => format!(\"{}(build)\", pkg_name),\n            CompileMode::Test | CompileMode::Check { test: true } => match unit.target.kind() {\n                TargetKind::Lib(_) => format!(\"{}(test)\", target_name),\n                TargetKind::CustomBuild => panic!(\"cannot test build script\"),\n                TargetKind::Bin => format!(\"{}(bin test)\", target_name),\n                TargetKind::Test => format!(\"{}(test)\", target_name),\n                TargetKind::Bench => format!(\"{}(bench)\", target_name),\n                TargetKind::ExampleBin | TargetKind::ExampleLib(_) => {\n                    format!(\"{}(example test)\", target_name)\n                }\n            },\n            _ => match unit.target.kind() {\n                TargetKind::Lib(_) => pkg_name.to_string(),\n                TargetKind::CustomBuild => format!(\"{}(build.rs)\", pkg_name),\n                TargetKind::Bin => format!(\"{}(bin)\", target_name),\n                TargetKind::Test => format!(\"{}(test)\", target_name),\n                TargetKind::Bench => format!(\"{}(bench)\", target_name),\n                TargetKind::ExampleBin | TargetKind::ExampleLib(_) => {\n                    format!(\"{}(example)\", target_name)\n                }\n            },\n        }\n    }\n\n    /// Executes a job.\n    ///\n    /// Fresh jobs block until finished (which should be very fast!), Dirty\n    /// jobs will spawn a thread in the background and return immediately.\n    fn run<'s>(\n        &mut self,\n        unit: &Unit,\n        job: Job,\n        build_runner: &BuildRunner<'_, '_>,\n        scope: &'s Scope<'s, '_>,\n    ) {\n        let id = JobId(self.next_id);\n        self.next_id = self.next_id.checked_add(1).unwrap();\n\n        debug!(\"start {}: {:?}\", id, unit);\n\n        assert!(self.active.insert(id, unit.clone()).is_none());\n\n        let messages = self.messages.clone();\n        let is_fresh = job.freshness().is_fresh();\n        let rmeta_required = build_runner.rmeta_required(unit);\n        let lock_manager = build_runner.lock_manager.clone();\n\n        let doit = move |diag_dedupe| {\n            let state = JobState::new(id, messages, diag_dedupe, rmeta_required, lock_manager);\n            state.run_to_finish(job);\n        };\n\n        match is_fresh {\n            true => {\n                // Running a fresh job on the same thread is often much faster than spawning a new\n                // thread to run the job.\n                doit(Some(&self.diag_dedupe));\n            }\n            false => {\n                scope.spawn(move || doit(None));\n            }\n        }\n    }\n\n    fn emit_log_messages(\n        &self,\n        unit: &Unit,\n        build_runner: &mut BuildRunner<'_, '_>,\n        show_warnings: bool,\n    ) -> CargoResult<()> {\n        let outputs = build_runner.build_script_outputs.lock().unwrap();\n        let Some(metadata_vec) = build_runner.find_build_script_metadatas(unit) else {\n            return Ok(());\n        };\n        let bcx = &mut build_runner.bcx;\n        for metadata in metadata_vec {\n            if let Some(output) = outputs.get(metadata) {\n                if !output.log_messages.is_empty()\n                    && (show_warnings\n                        || output\n                            .log_messages\n                            .iter()\n                            .any(|(severity, _)| *severity == Severity::Error))\n                {\n                    let msg_with_package =\n                        |msg: &str| format!(\"{}@{}: {}\", unit.pkg.name(), unit.pkg.version(), msg);\n\n                    for (severity, message) in output.log_messages.iter() {\n                        match severity {\n                            Severity::Error => {\n                                bcx.gctx.shell().error(msg_with_package(message))?;\n                            }\n                            Severity::Warning => {\n                                bcx.gctx.shell().warn(msg_with_package(message))?;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        Ok(())\n    }\n\n    fn bump_warning_count(&mut self, id: JobId, lint: bool, emitted: bool, fixable: bool) {\n        let count = self.warning_count.entry(id).or_default();\n        count.total += 1;\n        if lint {\n            let unit = self.active.get(&id).unwrap();\n            // If this is an upstream dep but we *do* want warnings, make sure that they\n            // don't fail compilation.\n            if unit.is_local() {\n                count.lints += 1;\n            }\n        }\n        if !emitted {\n            count.duplicates += 1;\n        // Don't add to fixable if it's already been emitted\n        } else if fixable {\n            // Do not add anything to the fixable warning count if\n            // is `NotAllowed` since that indicates there was an\n            // error while building this `Unit`\n            if count.fixable_allowed() {\n                count.fixable = match count.fixable {\n                    FixableWarnings::NotAllowed => FixableWarnings::NotAllowed,\n                    FixableWarnings::Zero => FixableWarnings::Positive(1),\n                    FixableWarnings::Positive(fixable) => FixableWarnings::Positive(fixable + 1),\n                };\n            }\n        }\n    }\n\n    /// Displays a final report of the warnings emitted by a particular job.\n    fn report_warning_count(\n        &mut self,\n        runner: &mut BuildRunner<'_, '_>,\n        unit: &Unit,\n        count: &WarningCount,\n        rustc_workspace_wrapper: &Option<PathBuf>,\n        warning_handling: WarningHandling,\n    ) {\n        let gctx = runner.bcx.gctx;\n        runner.compilation.lint_warning_count += count.lints;\n        let mut message = descriptive_pkg_name(&unit.pkg.name(), &unit.target, &unit.mode);\n        message.push_str(\" generated \");\n        match count.total {\n            1 => message.push_str(\"1 warning\"),\n            n => {\n                let _ = write!(message, \"{} warnings\", n);\n            }\n        };\n        match count.duplicates {\n            0 => {}\n            1 => message.push_str(\" (1 duplicate)\"),\n            n => {\n                let _ = write!(message, \" ({} duplicates)\", n);\n            }\n        }\n        // Only show the `cargo fix` message if its a local `Unit`\n        if unit.is_local() {\n            // Do not show this if there are any errors or no fixable warnings\n            if let FixableWarnings::Positive(fixable) = count.fixable {\n                // `cargo fix` doesn't have an option for custom builds\n                if !unit.target.is_custom_build() {\n                    // To make sure the correct command is shown for `clippy` we\n                    // check if `RUSTC_WORKSPACE_WRAPPER` is set and pointing towards\n                    // `clippy-driver`.\n                    let clippy = std::ffi::OsStr::new(\"clippy-driver\");\n                    let is_clippy = rustc_workspace_wrapper.as_ref().and_then(|x| x.file_stem())\n                        == Some(clippy);\n\n                    let command = if is_clippy {\n                        \"cargo clippy --fix\"\n                    } else {\n                        \"cargo fix\"\n                    };\n\n                    let mut args =\n                        format!(\"{} -p {}\", unit.target.description_named(), unit.pkg.name());\n                    if unit.mode.is_rustc_test()\n                        && !(unit.target.is_test() || unit.target.is_bench())\n                    {\n                        args.push_str(\" --tests\");\n                    }\n                    let mut suggestions = format!(\"{} suggestion\", fixable);\n                    if fixable > 1 {\n                        suggestions.push_str(\"s\")\n                    }\n\n                    #[expect(clippy::disallowed_methods, reason = \"consistency with clippy\")]\n                    let _ = write!(\n                        message,\n                        \" (run `{command} --{args}{}` to apply {suggestions})\",\n                        if let Some(cli_lints_os) = env::var_os(\"CLIPPY_ARGS\")\n                            && let Ok(cli_lints) = cli_lints_os.into_string()\n                            && is_clippy\n                        {\n                            // Clippy can take lints through the CLI, each lint flag is separated by \"__CLIPPY_HACKERY__\".\n                            let cli_lints = cli_lints.replace(\"__CLIPPY_HACKERY__\", \" \");\n                            let cli_lints = cli_lints.trim_ascii_end(); // Remove that last space left by __CLIPPY_HACKERY__\n                            format!(\" -- {cli_lints}\")\n                        } else {\n                            \"\".to_owned()\n                        }\n                    );\n                }\n            }\n        }\n        // Errors are ignored here because it is tricky to handle them\n        // correctly, and they aren't important.\n        let _ = if warning_handling == WarningHandling::Deny && 0 < count.lints {\n            gctx.shell().error(message)\n        } else {\n            gctx.shell().warn(message)\n        };\n    }\n\n    fn finish(\n        &mut self,\n        id: JobId,\n        unit: &Unit,\n        artifact: Artifact,\n        build_runner: &mut BuildRunner<'_, '_>,\n    ) -> CargoResult<()> {\n        if unit.mode.is_run_custom_build() {\n            self.emit_log_messages(\n                unit,\n                build_runner,\n                unit.show_warnings(build_runner.bcx.gctx),\n            )?;\n        }\n        let unblocked = self.queue.finish(unit, &artifact);\n        match artifact {\n            Artifact::All => self.timings.unit_finished(build_runner, id, unblocked),\n            Artifact::Metadata => self\n                .timings\n                .unit_rmeta_finished(build_runner, id, unblocked),\n        }\n        Ok(())\n    }\n\n    // This isn't super trivial because we don't want to print loads and\n    // loads of information to the console, but we also want to produce a\n    // faithful representation of what's happening. This is somewhat nuanced\n    // as a package can start compiling *very* early on because of custom\n    // build commands and such.\n    //\n    // In general, we try to print \"Compiling\" for the first nontrivial task\n    // run for a package, regardless of when that is. We then don't print\n    // out any more information for a package after we've printed it once.\n    fn note_working_on(\n        &mut self,\n        gctx: &GlobalContext,\n        ws_root: &Path,\n        unit: &Unit,\n        fresh: &Freshness,\n    ) -> CargoResult<()> {\n        if (self.compiled.contains(&unit.pkg.package_id())\n            && !unit.mode.is_doc()\n            && !unit.mode.is_doc_scrape())\n            || (self.documented.contains(&unit.pkg.package_id()) && unit.mode.is_doc())\n            || (self.scraped.contains(&unit.pkg.package_id()) && unit.mode.is_doc_scrape())\n        {\n            return Ok(());\n        }\n\n        match fresh {\n            // Any dirty stage which runs at least one command gets printed as\n            // being a compiled package.\n            Dirty(dirty_reason) => {\n                if !dirty_reason.is_fresh_build() {\n                    gctx.shell().verbose(|shell| {\n                        dirty_reason.present_to(shell, unit, ws_root, &self.index_to_unit)\n                    })?;\n                }\n\n                if unit.mode.is_doc() {\n                    self.documented.insert(unit.pkg.package_id());\n                    gctx.shell().status(\"Documenting\", &unit.pkg)?;\n                } else if unit.mode.is_doc_test() {\n                    // Skip doc test.\n                } else if unit.mode.is_doc_scrape() {\n                    self.scraped.insert(unit.pkg.package_id());\n                    gctx.shell().status(\"Scraping\", &unit.pkg)?;\n                } else {\n                    self.compiled.insert(unit.pkg.package_id());\n                    if unit.mode.is_check() {\n                        gctx.shell().status(\"Checking\", &unit.pkg)?;\n                    } else {\n                        gctx.shell().status(\"Compiling\", &unit.pkg)?;\n                    }\n                }\n            }\n            Fresh => {\n                // If doc test are last, only print \"Fresh\" if nothing has been printed.\n                if self.counts[&unit.pkg.package_id()] == 0\n                    && !(unit.mode.is_doc_test() && self.compiled.contains(&unit.pkg.package_id()))\n                {\n                    self.compiled.insert(unit.pkg.package_id());\n                    gctx.shell().verbose(|c| c.status(\"Fresh\", &unit.pkg))?;\n                }\n            }\n        }\n        Ok(())\n    }\n\n    fn back_compat_notice(\n        &self,\n        build_runner: &BuildRunner<'_, '_>,\n        unit: &Unit,\n    ) -> CargoResult<()> {\n        if unit.pkg.name() != \"diesel\"\n            || unit.pkg.version() >= &Version::new(1, 4, 8)\n            || build_runner.bcx.ws.resolve_behavior() == ResolveBehavior::V1\n            || !unit.pkg.package_id().source_id().is_registry()\n            || !unit.features.is_empty()\n        {\n            return Ok(());\n        }\n        if !build_runner\n            .bcx\n            .unit_graph\n            .keys()\n            .any(|unit| unit.pkg.name() == \"diesel\" && !unit.features.is_empty())\n        {\n            return Ok(());\n        }\n        build_runner.bcx.gctx.shell().note(\n            \"\\\nThis error may be due to an interaction between diesel and Cargo's new\nfeature resolver. Try updating to diesel 1.4.8 to fix this error.\n\",\n        )?;\n        Ok(())\n    }\n}\n\nimpl ErrorsDuringDrain {\n    fn to_error(&self) -> Option<anyhow::Error> {\n        match self.count {\n            0 => None,\n            1 => Some(format_err!(\"1 job failed\")),\n            n => Some(format_err!(\"{} jobs failed\", n)),\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/layout.rs",
    "content": "//! Management of the directory layout of a build\n//!\n//! The directory layout is a little tricky at times, hence a separate file to\n//! house this logic. Cargo stores build artifacts in two directories: `artifact-dir` and\n//! `build-dir`\n//!\n//! ## `artifact-dir` layout\n//!\n//! `artifact-dir` is where final artifacts like binaries are stored.\n//! The `artifact-dir` layout is consider part of the public API and\n//! cannot be easily changed.\n//!\n//! ```text\n//! <artifact-dir>/\n//!\n//!     # Compilation files are grouped by build target and profile.\n//!     # The target is omitted if not explicitly specified.\n//!     [<target>]/<profile>/ # e.g. `debug` / `release`\n//!\n//!         # File used to lock the directory to prevent multiple cargo processes\n//!         # from using it at the same time.\n//!         .cargo-lock\n//!\n//!         # Root directory for all compiled examples.\n//!         examples/\n//!\n//!     # Output from rustdoc\n//!     doc/\n//!\n//!     # Output from `cargo package` to build a `.crate` file.\n//!     package/\n//! ```\n//!\n//! ## `build-dir` layout\n//!\n//! `build-dir` is where intermediate build artifacts are stored.\n//! The `build-dir` layout is considered an internal implementation detail of Cargo\n//! meaning that we can change this if needed. However, in reality many tools rely on\n//! implementation details of Cargo so breaking changes need to be done carefully.\n//!\n//! ```text\n//! <build-dir>/\n//!\n//!     # Cache of `rustc -Vv` output for performance.\n//!     .rustc-info.json\n//!\n//!     # Compilation files are grouped by build target and profile.\n//!     # The target is omitted if not explicitly specified.\n//!     [<target>]/<profile>/ # e.g. `debug` / `release`\n//!\n//!         # File used to lock the directory to prevent multiple cargo processes\n//!         # from using it at the same time.\n//!         .cargo-lock\n//!\n//!         # Hidden directory that holds all of the fingerprint files for all\n//!         # packages\n//!         .fingerprint/\n//!             # Each package is in a separate directory.\n//!             # Note that different target kinds have different filename prefixes.\n//!             $pkgname-$META/\n//!                 # Set of source filenames for this package.\n//!                 dep-lib-$targetname\n//!                 # Timestamp when this package was last built.\n//!                 invoked.timestamp\n//!                 # The fingerprint hash.\n//!                 lib-$targetname\n//!                 # Detailed information used for logging the reason why\n//!                 # something is being recompiled.\n//!                 lib-$targetname.json\n//!                 # The console output from the compiler. This is cached\n//!                 # so that warnings can be redisplayed for \"fresh\" units.\n//!                 output-lib-$targetname\n//!\n//!         # This is the root directory for all rustc artifacts except build\n//!         # scripts, examples, and test and bench executables. Almost every\n//!         # artifact should have a metadata hash added to its filename to\n//!         # prevent collisions. One notable exception is dynamic libraries.\n//!         deps/\n//!\n//!             # Each artifact dependency gets in its own directory.\n//!             /artifact/$pkgname-$META/$kind\n//!\n//!         # Root directory for all compiled examples.\n//!         examples/\n//!\n//!         # Directory used to store incremental data for the compiler (when\n//!         # incremental is enabled.\n//!         incremental/\n//!\n//!         # This is the location at which the output of all custom build\n//!         # commands are rooted.\n//!         build/\n//!\n//!             # Each package gets its own directory where its build script and\n//!             # script output are placed\n//!             $pkgname-$META/    # For the build script itself.\n//!                 # The build script executable (name may be changed by user).\n//!                 build-script-build-$META\n//!                 # Hard link to build-script-build-$META.\n//!                 build-script-build\n//!                 # Dependency information generated by rustc.\n//!                 build-script-build-$META.d\n//!                 # Debug information, depending on platform and profile\n//!                 # settings.\n//!                 <debug symbols>\n//!\n//!             # The package shows up twice with two different metadata hashes.\n//!             $pkgname-$META/  # For the output of the build script.\n//!                 # Timestamp when the build script was last executed.\n//!                 invoked.timestamp\n//!                 # Directory where script can output files ($OUT_DIR).\n//!                 out/\n//!                 # Output from the build script.\n//!                 output\n//!                 # Path to `out`, used to help when the target directory is\n//!                 # moved.\n//!                 root-output\n//!                 # Stderr output from the build script.\n//!                 stderr\n//!\n//!     # Used by `cargo package` and `cargo publish` to build a `.crate` file.\n//!     package/\n//!\n//!     # Experimental feature for generated build scripts.\n//!     .metabuild/\n//! ```\n//!\n//! ### New `build-dir` layout\n//!\n//! `build-dir` supports a new \"build unit\" based layout that is unstable.\n//! It can be enabled via `-Zbuild-dir-new-layout`.\n//! For more info about the layout transition see: [#15010](https://github.com/rust-lang/cargo/issues/15010)\n//!\n//! ```text\n//! <build-dir>/\n//!\n//!     # Cache of `rustc -Vv` output for performance.\n//!     .rustc-info.json\n//!\n//!     # Compilation files are grouped by build target and profile.\n//!     # The target is omitted if not explicitly specified.\n//!     [<target>]/<profile>/ # e.g. `debug` / `release`\n//!\n//!         # File used to lock the directory to prevent multiple cargo processes\n//!         # from using it at the same time.\n//!         .cargo-lock\n//!\n//!         # Directory used to store incremental data for the compiler (when\n//!         # incremental is enabled.\n//!         incremental/\n//!\n//!         # Main directory for storing build unit related files.\n//!         # Files are organized by Cargo build unit (`$pkgname/$META`) so that\n//!         # related files are stored in a single directory.\n//!         build/\n//!\n//!             # This is the location at which the output of all files related to\n//!             # a given build unit. These files are organized together so that we can\n//!             # treat this directly like a single unit for locking and caching.\n//!             $pkgname/\n//!                 $META/\n//!                     # The general purpose output directory for build units.\n//!                     # For compilation units, the rustc artifact will be located here.\n//!                     # For build script run units, this is the $OUT_DIR\n//!                     out/\n//!\n//!                         # For artifact dependency units, the output is nested by the kind\n//!                         artifact/$kind\n//!\n//!                     # Directory that holds all of the fingerprint files for the build unit.\n//!                     fingerprint/\n//!                         # Set of source filenames for this package.\n//!                         dep-lib-$targetname\n//!                         # Timestamp when this package was last built.\n//!                         invoked.timestamp\n//!                         # The fingerprint hash.\n//!                         lib-$targetname\n//!                         # Detailed information used for logging the reason why\n//!                         # something is being recompiled.\n//!                         lib-$targetname.json\n//!                         # The console output from the compiler. This is cached\n//!                         # so that warnings can be redisplayed for \"fresh\" units.\n//!                         output-lib-$targetname\n//!\n//!                     # Directory for \"execution\" units that spawn a process (excluding compilation with\n//!                     # rustc). Contains the process execution details.\n//!                     # Currently the only execution unit Cargo supports is running build script\n//!                     # binaries.\n//!                     run/\n//!                         # Timestamp of last execution.\n//!                         invoked.timestamp\n//!                         # Stdout output from the process.\n//!                         stdout\n//!                         # Stderr output from the process.\n//!                         stderr\n//!                         # Path to `out`, used to help when the target directory is\n//!                         # moved. (build scripts)\n//!                         root-output\n//!\n//!     # Used by `cargo package` and `cargo publish` to build a `.crate` file.\n//!     package/\n//!\n//!     # Experimental feature for generated build scripts.\n//!     .metabuild/\n//! ```\n//!\n//! When cross-compiling, the layout is the same, except it appears in\n//! `target/$TRIPLE`.\n\nuse crate::core::Workspace;\nuse crate::core::compiler::CompileTarget;\nuse crate::util::flock::is_on_nfs_mount;\nuse crate::util::{CargoResult, FileLock};\nuse cargo_util::paths;\nuse std::path::{Path, PathBuf};\n\n/// Contains the paths of all target output locations.\n///\n/// See module docs for more information.\npub struct Layout {\n    artifact_dir: Option<ArtifactDirLayout>,\n    build_dir: BuildDirLayout,\n}\n\nimpl Layout {\n    /// Calculate the paths for build output, lock the build directory, and return as a Layout.\n    ///\n    /// This function will block if the directory is already locked.\n    ///\n    /// `dest` should be the final artifact directory name. Currently either\n    /// \"debug\" or \"release\".\n    pub fn new(\n        ws: &Workspace<'_>,\n        target: Option<CompileTarget>,\n        dest: &str,\n        must_take_artifact_dir_lock: bool,\n        must_take_build_dir_lock_exclusively: bool,\n    ) -> CargoResult<Layout> {\n        let is_new_layout = ws.gctx().cli_unstable().build_dir_new_layout;\n        let mut root = ws.target_dir();\n        let mut build_root = ws.build_dir();\n        if let Some(target) = target {\n            root.push(target.short_name());\n            build_root.push(target.short_name());\n        }\n        let build_dest = build_root.join(dest);\n        let dest = root.join(dest);\n        // If the root directory doesn't already exist go ahead and create it\n        // here. Use this opportunity to exclude it from backups as well if the\n        // system supports it since this is a freshly created folder.\n        //\n        paths::create_dir_all_excluded_from_backups_atomic(root.as_path_unlocked())?;\n        if root != build_root {\n            paths::create_dir_all_excluded_from_backups_atomic(build_root.as_path_unlocked())?;\n        }\n\n        // Now that the excluded from backups target root is created we can create the\n        // actual destination (sub)subdirectory.\n        paths::create_dir_all(dest.as_path_unlocked())?;\n\n        let build_dir_lock = if is_on_nfs_mount(build_root.as_path_unlocked()) {\n            None\n        } else {\n            if ws.gctx().cli_unstable().fine_grain_locking && !must_take_build_dir_lock_exclusively\n            {\n                Some(build_dest.open_ro_shared_create(\n                    \".cargo-build-lock\",\n                    ws.gctx(),\n                    \"build directory\",\n                )?)\n            } else {\n                Some(build_dest.open_rw_exclusive_create(\n                    \".cargo-build-lock\",\n                    ws.gctx(),\n                    \"build directory\",\n                )?)\n            }\n        };\n        let build_root = build_root.into_path_unlocked();\n        let build_dest = build_dest.as_path_unlocked();\n        let deps = build_dest.join(\"deps\");\n        let artifact = deps.join(\"artifact\");\n\n        let artifact_dir = if must_take_artifact_dir_lock {\n            // For now we don't do any more finer-grained locking on the artifact\n            // directory, so just lock the entire thing for the duration of this\n            // compile.\n            let artifact_dir_lock = if is_on_nfs_mount(root.as_path_unlocked()) {\n                None\n            } else {\n                Some(dest.open_rw_exclusive_create(\n                    \".cargo-lock\",\n                    ws.gctx(),\n                    \"artifact directory\",\n                )?)\n            };\n            let root = root.into_path_unlocked();\n            let dest = dest.into_path_unlocked();\n            Some(ArtifactDirLayout {\n                dest: dest.clone(),\n                examples: dest.join(\"examples\"),\n                doc: root.join(\"doc\"),\n                timings: root.join(\"cargo-timings\"),\n                _lock: artifact_dir_lock,\n            })\n        } else {\n            None\n        };\n        Ok(Layout {\n            artifact_dir,\n            build_dir: BuildDirLayout {\n                root: build_root.clone(),\n                deps,\n                build: build_dest.join(\"build\"),\n                artifact,\n                incremental: build_dest.join(\"incremental\"),\n                fingerprint: build_dest.join(\".fingerprint\"),\n                examples: build_dest.join(\"examples\"),\n                tmp: build_root.join(\"tmp\"),\n                _lock: build_dir_lock,\n                is_new_layout,\n            },\n        })\n    }\n\n    /// Makes sure all directories stored in the Layout exist on the filesystem.\n    pub fn prepare(&mut self) -> CargoResult<()> {\n        if let Some(ref mut artifact_dir) = self.artifact_dir {\n            artifact_dir.prepare()?;\n        }\n        self.build_dir.prepare()?;\n\n        Ok(())\n    }\n\n    pub fn artifact_dir(&self) -> Option<&ArtifactDirLayout> {\n        self.artifact_dir.as_ref()\n    }\n\n    pub fn build_dir(&self) -> &BuildDirLayout {\n        &self.build_dir\n    }\n}\n\npub struct ArtifactDirLayout {\n    /// The final artifact destination: `<artifact-dir>/debug` (or `release`).\n    dest: PathBuf,\n    /// The directory for examples\n    examples: PathBuf,\n    /// The directory for rustdoc output\n    doc: PathBuf,\n    /// The directory for --timings output\n    timings: PathBuf,\n    /// The lockfile for a build (`.cargo-lock`). Will be unlocked when this\n    /// struct is `drop`ped.\n    _lock: Option<FileLock>,\n}\n\nimpl ArtifactDirLayout {\n    /// Makes sure all directories stored in the Layout exist on the filesystem.\n    pub fn prepare(&mut self) -> CargoResult<()> {\n        paths::create_dir_all(&self.examples)?;\n\n        Ok(())\n    }\n    /// Fetch the destination path for final artifacts  (`/…/target/debug`).\n    pub fn dest(&self) -> &Path {\n        &self.dest\n    }\n    /// Fetch the examples path.\n    pub fn examples(&self) -> &Path {\n        &self.examples\n    }\n    /// Fetch the doc path.\n    pub fn doc(&self) -> &Path {\n        &self.doc\n    }\n    /// Fetch the cargo-timings path.\n    pub fn timings(&self) -> &Path {\n        &self.timings\n    }\n}\n\npub struct BuildDirLayout {\n    /// The root directory: `/path/to/build-dir`.\n    /// If cross compiling: `/path/to/build-dir/$TRIPLE`.\n    root: PathBuf,\n    /// The directory with rustc artifacts\n    deps: PathBuf,\n    /// The primary directory for build files\n    build: PathBuf,\n    /// The directory for artifacts, i.e. binaries, cdylibs, staticlibs\n    artifact: PathBuf,\n    /// The directory for incremental files\n    incremental: PathBuf,\n    /// The directory for fingerprints\n    fingerprint: PathBuf,\n    /// The directory for pre-uplifted examples: `build-dir/debug/examples`\n    examples: PathBuf,\n    /// The directory for temporary data of integration tests and benches\n    tmp: PathBuf,\n    /// The lockfile for a build (`.cargo-lock`). Will be unlocked when this\n    /// struct is `drop`ped.\n    ///\n    /// Will be `None` when the build-dir and target-dir are the same path as we cannot\n    /// lock the same path twice.\n    _lock: Option<FileLock>,\n    is_new_layout: bool,\n}\n\nimpl BuildDirLayout {\n    /// Makes sure all directories stored in the Layout exist on the filesystem.\n    pub fn prepare(&mut self) -> CargoResult<()> {\n        if !self.is_new_layout {\n            paths::create_dir_all(&self.deps)?;\n            paths::create_dir_all(&self.fingerprint)?;\n            paths::create_dir_all(&self.examples)?;\n        }\n        paths::create_dir_all(&self.incremental)?;\n        paths::create_dir_all(&self.build)?;\n\n        Ok(())\n    }\n    /// Fetch the deps path.\n    pub fn deps(&self, pkg_dir: &str) -> PathBuf {\n        if self.is_new_layout {\n            self.out_force_new_layout(pkg_dir)\n        } else {\n            self.legacy_deps().to_path_buf()\n        }\n    }\n    /// Fetch the output path for build units. (new layout only)\n    ///\n    /// New features should consider using this so we can avoid their migrations.\n    pub fn out_force_new_layout(&self, pkg_dir: &str) -> PathBuf {\n        self.build_unit(pkg_dir).join(\"out\")\n    }\n    /// Fetch the deps path. (old layout)\n    pub fn legacy_deps(&self) -> &Path {\n        &self.deps\n    }\n    pub fn root(&self) -> &Path {\n        &self.root\n    }\n    /// Fetch the build examples path.\n    pub fn examples(&self) -> &Path {\n        &self.examples\n    }\n    /// Fetch the incremental path.\n    pub fn incremental(&self) -> &Path {\n        &self.incremental\n    }\n    /// Fetch the fingerprint path.\n    pub fn fingerprint(&self, pkg_dir: &str) -> PathBuf {\n        if self.is_new_layout {\n            self.build_unit(pkg_dir).join(\"fingerprint\")\n        } else {\n            self.legacy_fingerprint().to_path_buf().join(pkg_dir)\n        }\n    }\n    /// Fetch the fingerprint path. (old layout)\n    pub fn legacy_fingerprint(&self) -> &Path {\n        &self.fingerprint\n    }\n    /// Fetch the build path.\n    pub fn build(&self) -> &Path {\n        &self.build\n    }\n    /// Fetch the build script path.\n    pub fn build_script(&self, pkg_dir: &str) -> PathBuf {\n        if self.is_new_layout {\n            self.deps(pkg_dir)\n        } else {\n            self.build().join(pkg_dir)\n        }\n    }\n    /// Fetch the build script execution path.\n    pub fn build_script_execution(&self, pkg_dir: &str) -> PathBuf {\n        if self.is_new_layout {\n            self.build_unit(pkg_dir).join(\"run\")\n        } else {\n            self.build().join(pkg_dir)\n        }\n    }\n    /// Fetch the artifact path.\n    pub fn artifact(&self, pkg_dir: &str, kind: &str) -> PathBuf {\n        if self.is_new_layout {\n            self.build_unit(pkg_dir).join(\"artifact\").join(kind)\n        } else {\n            self.artifact.join(pkg_dir).join(kind)\n        }\n    }\n    /// Fetch the build unit path\n    pub fn build_unit(&self, pkg_dir: &str) -> PathBuf {\n        self.build().join(pkg_dir)\n    }\n    /// Create and return the tmp path.\n    pub fn prepare_tmp(&self) -> CargoResult<&Path> {\n        paths::create_dir_all(&self.tmp)?;\n        Ok(&self.tmp)\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/links.rs",
    "content": "use super::unit_graph::UnitGraph;\nuse crate::core::resolver::errors::describe_path;\nuse crate::core::{PackageId, Resolve};\nuse crate::util::errors::CargoResult;\nuse std::collections::{HashMap, HashSet};\n\n/// Validates [`package.links`] field in the manifest file does not conflict\n/// between packages.\n///\n/// NOTE: This is the *old* links validator. Links are usually validated in the\n/// resolver. However, the `links` field was added to the index in early 2018\n/// (see [rust-lang/cargo#4978]). However, `links` has been around since 2014,\n/// so there are still many crates in the index that don't have `links`\n/// properly set in the index (over 600 at the time of this writing in 2019).\n/// This can probably be removed at some point in the future, though it might\n/// be worth considering fixing the index.\n///\n/// [rust-lang/cargo#4978]: https://github.com/rust-lang/cargo/pull/4978\n/// [`package.links`]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#the-links-manifest-key\npub fn validate_links(resolve: &Resolve, unit_graph: &UnitGraph) -> CargoResult<()> {\n    let mut validated: HashSet<PackageId> = HashSet::new();\n    let mut links: HashMap<String, PackageId> = HashMap::new();\n    let mut units: Vec<_> = unit_graph.keys().collect();\n    // Sort primarily to make testing easier.\n    units.sort_unstable();\n    for unit in units {\n        if !validated.insert(unit.pkg.package_id()) {\n            continue;\n        }\n        let Some(lib) = unit.pkg.manifest().links() else {\n            continue;\n        };\n        if let Some(&prev) = links.get(lib) {\n            let prev_path = resolve\n                .path_to_top(&prev)\n                .into_iter()\n                .map(|(p, d)| (p, d.and_then(|d| d.iter().next())));\n            let pkg = unit.pkg.package_id();\n            let path = resolve\n                .path_to_top(&pkg)\n                .into_iter()\n                .map(|(p, d)| (p, d.and_then(|d| d.iter().next())));\n            anyhow::bail!(\n                \"multiple packages link to native library `{}`, \\\n                 but a native library can be linked only once\\n\\\n                 \\n\\\n                 {}\\nlinks to native library `{}`\\n\\\n                 \\n\\\n                 {}\\nalso links to native library `{}`\",\n                lib,\n                describe_path(prev_path),\n                lib,\n                describe_path(path),\n                lib\n            )\n        }\n        links.insert(lib.to_string(), unit.pkg.package_id());\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/locking.rs",
    "content": "//! This module handles the locking logic during compilation.\n\nuse crate::{\n    CargoResult,\n    core::compiler::{BuildRunner, Unit},\n    util::{FileLock, Filesystem},\n};\nuse anyhow::bail;\nuse std::{\n    collections::HashMap,\n    fmt::{Display, Formatter},\n    path::PathBuf,\n    sync::RwLock,\n};\nuse tracing::instrument;\n\n/// A struct to store the lock handles for build units during compilation.\npub struct LockManager {\n    locks: RwLock<HashMap<LockKey, FileLock>>,\n}\n\nimpl LockManager {\n    pub fn new() -> Self {\n        Self {\n            locks: RwLock::new(HashMap::new()),\n        }\n    }\n\n    /// Takes a shared lock on a given [`Unit`]\n    /// This prevents other Cargo instances from compiling (writing) to\n    /// this build unit.\n    ///\n    /// This function returns a [`LockKey`] which can be used to\n    /// upgrade/unlock the lock.\n    #[instrument(skip_all, fields(key))]\n    pub fn lock_shared(\n        &self,\n        build_runner: &BuildRunner<'_, '_>,\n        unit: &Unit,\n    ) -> CargoResult<LockKey> {\n        let key = LockKey::from_unit(build_runner, unit);\n        tracing::Span::current().record(\"key\", key.0.to_str());\n\n        let mut locks = self.locks.write().unwrap();\n        if let Some(lock) = locks.get_mut(&key) {\n            lock.file().lock_shared()?;\n        } else {\n            let fs = Filesystem::new(key.0.clone());\n            let lock_msg = format!(\n                \"{} ({})\",\n                unit.pkg.name(),\n                build_runner.files().unit_hash(unit)\n            );\n            let lock = fs.open_ro_shared_create(&key.0, build_runner.bcx.gctx, &lock_msg)?;\n            locks.insert(key.clone(), lock);\n        }\n\n        Ok(key)\n    }\n\n    #[instrument(skip(self))]\n    pub fn lock(&self, key: &LockKey) -> CargoResult<()> {\n        let locks = self.locks.read().unwrap();\n        if let Some(lock) = locks.get(&key) {\n            lock.file().lock()?;\n        } else {\n            bail!(\"lock was not found in lock manager: {key}\");\n        }\n\n        Ok(())\n    }\n\n    /// Upgrades an existing exclusive lock into a shared lock.\n    #[instrument(skip(self))]\n    pub fn downgrade_to_shared(&self, key: &LockKey) -> CargoResult<()> {\n        let locks = self.locks.read().unwrap();\n        let Some(lock) = locks.get(key) else {\n            bail!(\"lock was not found in lock manager: {key}\");\n        };\n        lock.file().lock_shared()?;\n        Ok(())\n    }\n\n    #[instrument(skip(self))]\n    pub fn unlock(&self, key: &LockKey) -> CargoResult<()> {\n        let locks = self.locks.read().unwrap();\n        if let Some(lock) = locks.get(key) {\n            lock.file().unlock()?;\n        };\n\n        Ok(())\n    }\n}\n\n#[derive(Debug, Clone, Hash, Eq, PartialEq)]\npub struct LockKey(PathBuf);\n\nimpl LockKey {\n    fn from_unit(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> Self {\n        Self(build_runner.files().build_unit_lock(unit))\n    }\n}\n\nimpl Display for LockKey {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}\", self.0.display())\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/lto.rs",
    "content": "use crate::core::compiler::{BuildContext, CompileMode, CrateType, Unit};\nuse crate::core::profiles;\nuse crate::util::interning::InternedString;\n\nuse crate::util::errors::CargoResult;\nuse std::collections::hash_map::{Entry, HashMap};\n\n/// Possible ways to run rustc and request various parts of [LTO].\n///\n/// Variant            | Flag                   | Object Code | Bitcode\n/// -------------------|------------------------|-------------|--------\n/// `Run`              | `-C lto=foo`           | n/a         | n/a\n/// `Off`              | `-C lto=off`           | n/a         | n/a\n/// `OnlyBitcode`      | `-C linker-plugin-lto` |             | ✓\n/// `ObjectAndBitcode` |                        | ✓           | ✓\n/// `OnlyObject`       | `-C embed-bitcode=no`  | ✓           |\n///\n/// [LTO]: https://doc.rust-lang.org/nightly/cargo/reference/profiles.html#lto\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]\npub enum Lto {\n    /// LTO is run for this rustc, and it's `-Clto=foo`. If the given value is\n    /// None, that corresponds to `-Clto` with no argument, which means do\n    /// \"fat\" LTO.\n    Run(Option<InternedString>),\n\n    /// LTO has been explicitly listed as \"off\". This means no thin-local-LTO,\n    /// no LTO anywhere, I really mean it!\n    Off,\n\n    /// This rustc invocation only needs to produce bitcode (it is *only* used\n    /// for LTO), there's no need to produce object files, so we can pass\n    /// `-Clinker-plugin-lto`\n    OnlyBitcode,\n\n    /// This rustc invocation needs to embed bitcode in object files. This means\n    /// that object files may be used for a normal link, and the crate may be\n    /// loaded for LTO later, so both are required.\n    ObjectAndBitcode,\n\n    /// This should not include bitcode. This is primarily to reduce disk\n    /// space usage.\n    OnlyObject,\n}\n\npub fn generate(bcx: &BuildContext<'_, '_>) -> CargoResult<HashMap<Unit, Lto>> {\n    let mut map = HashMap::new();\n    for unit in bcx.roots.iter() {\n        let root_lto = match unit.profile.lto {\n            // LTO not requested, no need for bitcode.\n            profiles::Lto::Bool(false) => Lto::OnlyObject,\n            profiles::Lto::Off => Lto::Off,\n            _ => {\n                let crate_types = unit.target.rustc_crate_types();\n                if unit.target.for_host() {\n                    Lto::OnlyObject\n                } else if needs_object(&crate_types) {\n                    lto_when_needs_object(&crate_types)\n                } else {\n                    // This may or may not participate in LTO, let's start\n                    // with the minimum requirements. This may be expanded in\n                    // `calculate` below if necessary.\n                    Lto::OnlyBitcode\n                }\n            }\n        };\n        calculate(bcx, &mut map, unit, root_lto)?;\n    }\n    Ok(map)\n}\n\n/// Whether or not any of these crate types need object code.\nfn needs_object(crate_types: &[CrateType]) -> bool {\n    crate_types.iter().any(|k| k.can_lto() || k.is_dynamic())\n}\n\n/// Lto setting to use when this unit needs object code.\nfn lto_when_needs_object(crate_types: &[CrateType]) -> Lto {\n    if crate_types.iter().all(|ct| *ct == CrateType::Dylib) {\n        // A dylib whose parent is running LTO. rustc currently\n        // doesn't support LTO with dylibs, so bitcode is not\n        // needed.\n        Lto::OnlyObject\n    } else {\n        // Mixed rlib with a dylib or cdylib whose parent is running LTO. This\n        // needs both: bitcode for the rlib (for LTO) and object code for the\n        // dylib.\n        Lto::ObjectAndBitcode\n    }\n}\n\nfn calculate(\n    bcx: &BuildContext<'_, '_>,\n    map: &mut HashMap<Unit, Lto>,\n    unit: &Unit,\n    parent_lto: Lto,\n) -> CargoResult<()> {\n    let crate_types = match unit.mode {\n        // Note: Doctest ignores LTO, but for now we'll compute it as-if it is\n        // a Bin, in case it is ever supported in the future.\n        CompileMode::Test | CompileMode::Doctest => vec![CrateType::Bin],\n        // Notes on other modes:\n        // - Check: Treat as the underlying type, it doesn't really matter.\n        // - Doc: LTO is N/A for the Doc unit itself since rustdoc does not\n        //   support codegen flags. We still compute the dependencies, which\n        //   are mostly `Check`.\n        // - RunCustomBuild is ignored because it is always \"for_host\".\n        _ => unit.target.rustc_crate_types(),\n    };\n    // LTO can only be performed if *all* of the crate types support it.\n    // For example, a cdylib/rlib combination won't allow LTO.\n    let all_lto_types = crate_types.iter().all(CrateType::can_lto);\n    // Compute the LTO based on the profile, and what our parent requires.\n    let lto = if unit.target.for_host() {\n        // Disable LTO for host builds since we only really want to perform LTO\n        // for the final binary, and LTO on plugins/build scripts/proc macros is\n        // largely not desired.\n        Lto::OnlyObject\n    } else if all_lto_types {\n        // Note that this ignores the `parent_lto` because this isn't a\n        // linkable crate type; this unit is not being embedded in the parent.\n        match unit.profile.lto {\n            profiles::Lto::Named(s) => Lto::Run(Some(s)),\n            profiles::Lto::Off => Lto::Off,\n            profiles::Lto::Bool(true) => Lto::Run(None),\n            profiles::Lto::Bool(false) => Lto::OnlyObject,\n        }\n    } else {\n        match (parent_lto, needs_object(&crate_types)) {\n            // An rlib whose parent is running LTO, we only need bitcode.\n            (Lto::Run(_), false) => Lto::OnlyBitcode,\n            // LTO when something needs object code.\n            (Lto::Run(_), true) | (Lto::OnlyBitcode, true) => lto_when_needs_object(&crate_types),\n            // LTO is disabled, continue to disable it.\n            (Lto::Off, _) => Lto::Off,\n            // If this doesn't have any requirements, or the requirements are\n            // already satisfied, then stay with our parent.\n            (_, false) | (Lto::OnlyObject, true) | (Lto::ObjectAndBitcode, true) => parent_lto,\n        }\n    };\n\n    // Merge the computed LTO. If this unit appears multiple times in the\n    // graph, the merge may expand the requirements.\n    let merged_lto = match map.entry(unit.clone()) {\n        // If we haven't seen this unit before then insert our value and keep\n        // going.\n        Entry::Vacant(v) => *v.insert(lto),\n\n        Entry::Occupied(mut v) => {\n            let result = match (lto, v.get()) {\n                // No change in requirements.\n                (Lto::OnlyBitcode, Lto::OnlyBitcode) => Lto::OnlyBitcode,\n                (Lto::OnlyObject, Lto::OnlyObject) => Lto::OnlyObject,\n\n                // Once we're running LTO we keep running LTO. We should always\n                // calculate the same thing here each iteration because if we\n                // see this twice then it means, for example, two unit tests\n                // depend on a binary, which is normal.\n                (Lto::Run(s), _) | (_, &Lto::Run(s)) => Lto::Run(s),\n\n                // Off means off! This has the same reasoning as `Lto::Run`.\n                (Lto::Off, _) | (_, Lto::Off) => Lto::Off,\n\n                // Once a target has requested both, that's the maximal amount\n                // of work that can be done, so we just keep doing that work.\n                (Lto::ObjectAndBitcode, _) | (_, Lto::ObjectAndBitcode) => Lto::ObjectAndBitcode,\n\n                // Upgrade so that both requirements can be met.\n                //\n                // This is where the trickiness happens. This unit needs\n                // bitcode and the previously calculated value for this unit\n                // says it didn't need bitcode (or vice versa). This means that\n                // we're a shared dependency between some targets which require\n                // LTO and some which don't. This means that instead of being\n                // either only-objects or only-bitcode we have to embed both in\n                // rlibs (used for different compilations), so we switch to\n                // including both.\n                (Lto::OnlyObject, Lto::OnlyBitcode) | (Lto::OnlyBitcode, Lto::OnlyObject) => {\n                    Lto::ObjectAndBitcode\n                }\n            };\n            // No need to recurse if we calculated the same value as before.\n            if result == *v.get() {\n                return Ok(());\n            }\n            v.insert(result);\n            result\n        }\n    };\n\n    for dep in &bcx.unit_graph[unit] {\n        calculate(bcx, map, &dep.unit, merged_lto)?;\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/mod.rs",
    "content": "//! # Interact with the compiler\n//!\n//! If you consider [`ops::cargo_compile::compile`] as a `rustc` driver but on\n//! Cargo side, this module is kinda the `rustc_interface` for that merits.\n//! It contains all the interaction between Cargo and the rustc compiler,\n//! from preparing the context for the entire build process, to scheduling\n//! and executing each unit of work (e.g. running `rustc`), to managing and\n//! caching the output artifact of a build.\n//!\n//! However, it hasn't yet exposed a clear definition of each phase or session,\n//! like what rustc has done. Also, no one knows if Cargo really needs that.\n//! To be pragmatic, here we list a handful of items you may want to learn:\n//!\n//! * [`BuildContext`] is a static context containing all information you need\n//!   before a build gets started.\n//! * [`BuildRunner`] is the center of the world, coordinating a running build and\n//!   collecting information from it.\n//! * [`custom_build`] is the home of build script executions and output parsing.\n//! * [`fingerprint`] not only defines but also executes a set of rules to\n//!   determine if a re-compile is needed.\n//! * [`job_queue`] is where the parallelism, job scheduling, and communication\n//!   machinery happen between Cargo and the compiler.\n//! * [`layout`] defines and manages output artifacts of a build in the filesystem.\n//! * [`unit_dependencies`] is for building a dependency graph for compilation\n//!   from a result of dependency resolution.\n//! * [`Unit`] contains sufficient information to build something, usually\n//!   turning into a compiler invocation in a later phase.\n//!\n//! [`ops::cargo_compile::compile`]: crate::ops::compile\n\npub mod artifact;\nmod build_config;\npub(crate) mod build_context;\npub(crate) mod build_runner;\nmod compilation;\nmod compile_kind;\nmod crate_type;\nmod custom_build;\npub(crate) mod fingerprint;\npub mod future_incompat;\npub(crate) mod job_queue;\npub(crate) mod layout;\nmod links;\nmod locking;\nmod lto;\nmod output_depinfo;\nmod output_sbom;\npub mod rustdoc;\npub mod standard_lib;\npub mod timings;\nmod unit;\npub mod unit_dependencies;\npub mod unit_graph;\n\nuse std::borrow::Cow;\nuse std::cell::OnceCell;\nuse std::collections::{BTreeMap, HashMap, HashSet};\nuse std::env;\nuse std::ffi::{OsStr, OsString};\nuse std::fmt::Display;\nuse std::fs::{self, File};\nuse std::io::{BufRead, BufWriter, Write};\nuse std::ops::Range;\nuse std::path::{Path, PathBuf};\nuse std::sync::{Arc, LazyLock};\n\nuse annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet};\nuse anyhow::{Context as _, Error};\nuse cargo_platform::{Cfg, Platform};\nuse itertools::Itertools;\nuse regex::Regex;\nuse tracing::{debug, instrument, trace};\n\npub use self::build_config::UserIntent;\npub use self::build_config::{BuildConfig, CompileMode, MessageFormat};\npub use self::build_context::BuildContext;\npub use self::build_context::FileFlavor;\npub use self::build_context::FileType;\npub use self::build_context::RustcTargetData;\npub use self::build_context::TargetInfo;\npub use self::build_runner::{BuildRunner, Metadata, UnitHash};\npub use self::compilation::{Compilation, Doctest, UnitOutput};\npub use self::compile_kind::{CompileKind, CompileKindFallback, CompileTarget};\npub use self::crate_type::CrateType;\npub use self::custom_build::LinkArgTarget;\npub use self::custom_build::{BuildOutput, BuildScriptOutputs, BuildScripts, LibraryPath};\npub(crate) use self::fingerprint::DirtyReason;\npub use self::fingerprint::RustdocFingerprint;\npub use self::job_queue::Freshness;\nuse self::job_queue::{Job, JobQueue, JobState, Work};\npub(crate) use self::layout::Layout;\npub use self::lto::Lto;\nuse self::output_depinfo::output_depinfo;\nuse self::output_sbom::build_sbom;\nuse self::unit_graph::UnitDep;\n\nuse crate::core::compiler::future_incompat::FutureIncompatReport;\nuse crate::core::compiler::locking::LockKey;\nuse crate::core::compiler::timings::SectionTiming;\npub use crate::core::compiler::unit::Unit;\npub use crate::core::compiler::unit::UnitIndex;\npub use crate::core::compiler::unit::UnitInterner;\nuse crate::core::manifest::TargetSourcePath;\nuse crate::core::profiles::{PanicStrategy, Profile, StripInner};\nuse crate::core::{Feature, PackageId, Target, Verbosity};\nuse crate::lints::get_key_value;\nuse crate::util::OnceExt;\nuse crate::util::context::WarningHandling;\nuse crate::util::errors::{CargoResult, VerboseError};\nuse crate::util::interning::InternedString;\nuse crate::util::machine_message::{self, Message};\nuse crate::util::{add_path_args, internal, path_args};\n\nuse cargo_util::{ProcessBuilder, ProcessError, paths};\nuse cargo_util_schemas::manifest::TomlDebugInfo;\nuse cargo_util_schemas::manifest::TomlTrimPaths;\nuse cargo_util_schemas::manifest::TomlTrimPathsValue;\nuse rustfix::diagnostics::Applicability;\n\nconst RUSTDOC_CRATE_VERSION_FLAG: &str = \"--crate-version\";\n\n/// A glorified callback for executing calls to rustc. Rather than calling rustc\n/// directly, we'll use an `Executor`, giving clients an opportunity to intercept\n/// the build calls.\npub trait Executor: Send + Sync + 'static {\n    /// Called after a rustc process invocation is prepared up-front for a given\n    /// unit of work (may still be modified for runtime-known dependencies, when\n    /// the work is actually executed).\n    fn init(&self, _build_runner: &BuildRunner<'_, '_>, _unit: &Unit) {}\n\n    /// In case of an `Err`, Cargo will not continue with the build process for\n    /// this package.\n    fn exec(\n        &self,\n        cmd: &ProcessBuilder,\n        id: PackageId,\n        target: &Target,\n        mode: CompileMode,\n        on_stdout_line: &mut dyn FnMut(&str) -> CargoResult<()>,\n        on_stderr_line: &mut dyn FnMut(&str) -> CargoResult<()>,\n    ) -> CargoResult<()>;\n\n    /// Queried when queuing each unit of work. If it returns true, then the\n    /// unit will always be rebuilt, independent of whether it needs to be.\n    fn force_rebuild(&self, _unit: &Unit) -> bool {\n        false\n    }\n}\n\n/// A `DefaultExecutor` calls rustc without doing anything else. It is Cargo's\n/// default behaviour.\n#[derive(Copy, Clone)]\npub struct DefaultExecutor;\n\nimpl Executor for DefaultExecutor {\n    #[instrument(name = \"rustc\", skip_all, fields(package = id.name().as_str(), process = cmd.to_string()))]\n    fn exec(\n        &self,\n        cmd: &ProcessBuilder,\n        id: PackageId,\n        _target: &Target,\n        _mode: CompileMode,\n        on_stdout_line: &mut dyn FnMut(&str) -> CargoResult<()>,\n        on_stderr_line: &mut dyn FnMut(&str) -> CargoResult<()>,\n    ) -> CargoResult<()> {\n        cmd.exec_with_streaming(on_stdout_line, on_stderr_line, false)\n            .map(drop)\n    }\n}\n\n/// Builds up and enqueue a list of pending jobs onto the `job` queue.\n///\n/// Starting from the `unit`, this function recursively calls itself to build\n/// all jobs for dependencies of the `unit`. Each of these jobs represents\n/// compiling a particular package.\n///\n/// Note that **no actual work is executed as part of this**, that's all done\n/// next as part of [`JobQueue::execute`] function which will run everything\n/// in order with proper parallelism.\n#[tracing::instrument(skip(build_runner, jobs, exec))]\nfn compile<'gctx>(\n    build_runner: &mut BuildRunner<'_, 'gctx>,\n    jobs: &mut JobQueue<'gctx>,\n    unit: &Unit,\n    exec: &Arc<dyn Executor>,\n    force_rebuild: bool,\n) -> CargoResult<()> {\n    let bcx = build_runner.bcx;\n    if !build_runner.compiled.insert(unit.clone()) {\n        return Ok(());\n    }\n\n    let lock = if build_runner.bcx.gctx.cli_unstable().fine_grain_locking {\n        Some(build_runner.lock_manager.lock_shared(build_runner, unit)?)\n    } else {\n        None\n    };\n\n    // If we are in `--compile-time-deps` and the given unit is not a compile time\n    // dependency, skip compiling the unit and jumps to dependencies, which still\n    // have chances to be compile time dependencies\n    if !unit.skip_non_compile_time_dep {\n        // Build up the work to be done to compile this unit, enqueuing it once\n        // we've got everything constructed.\n        fingerprint::prepare_init(build_runner, unit)?;\n\n        let job = if unit.mode.is_run_custom_build() {\n            custom_build::prepare(build_runner, unit)?\n        } else if unit.mode.is_doc_test() {\n            // We run these targets later, so this is just a no-op for now.\n            Job::new_fresh()\n        } else {\n            let force = exec.force_rebuild(unit) || force_rebuild;\n            let mut job = fingerprint::prepare_target(build_runner, unit, force)?;\n            job.before(if job.freshness().is_dirty() {\n                let work = if unit.mode.is_doc() || unit.mode.is_doc_scrape() {\n                    rustdoc(build_runner, unit)?\n                } else {\n                    rustc(build_runner, unit, exec)?\n                };\n                work.then(link_targets(build_runner, unit, false)?)\n            } else {\n                // We always replay the output cache,\n                // since it might contain future-incompat-report messages\n                let show_diagnostics = unit.show_warnings(bcx.gctx)\n                    && build_runner.bcx.gctx.warning_handling()? != WarningHandling::Allow;\n                let manifest = ManifestErrorContext::new(build_runner, unit);\n                let work = replay_output_cache(\n                    unit.pkg.package_id(),\n                    manifest,\n                    &unit.target,\n                    build_runner.files().message_cache_path(unit),\n                    build_runner.bcx.build_config.message_format,\n                    show_diagnostics,\n                );\n                // Need to link targets on both the dirty and fresh.\n                work.then(link_targets(build_runner, unit, true)?)\n            });\n\n            // If -Zfine-grain-locking is enabled, we wrap the job with an upgrade to exclusive\n            // lock before starting, then downgrade to a shared lock after the job is finished.\n            if build_runner.bcx.gctx.cli_unstable().fine_grain_locking && job.freshness().is_dirty()\n            {\n                if let Some(lock) = lock {\n                    // Here we unlock the current shared lock to avoid deadlocking with other cargo\n                    // processes. Then we configure our compile job to take an exclusive lock\n                    // before starting. Once we are done compiling (including both rmeta and rlib)\n                    // we downgrade to a shared lock to allow other cargo's to read the build unit.\n                    // We will hold this shared lock for the remainder of compilation to prevent\n                    // other cargo from re-compiling while we are still using the unit.\n                    build_runner.lock_manager.unlock(&lock)?;\n                    job.before(prebuild_lock_exclusive(lock.clone()));\n                    job.after(downgrade_lock_to_shared(lock));\n                }\n            }\n\n            job\n        };\n        jobs.enqueue(build_runner, unit, job)?;\n    }\n\n    // Be sure to compile all dependencies of this target as well.\n    let deps = Vec::from(build_runner.unit_deps(unit)); // Create vec due to mutable borrow.\n    for dep in deps {\n        compile(build_runner, jobs, &dep.unit, exec, false)?;\n    }\n\n    Ok(())\n}\n\n/// Generates the warning message used when fallible doc-scrape units fail,\n/// either for rustdoc or rustc.\nfn make_failed_scrape_diagnostic(\n    build_runner: &BuildRunner<'_, '_>,\n    unit: &Unit,\n    top_line: impl Display,\n) -> String {\n    let manifest_path = unit.pkg.manifest_path();\n    let relative_manifest_path = manifest_path\n        .strip_prefix(build_runner.bcx.ws.root())\n        .unwrap_or(&manifest_path);\n\n    format!(\n        \"\\\n{top_line}\n    Try running with `--verbose` to see the error message.\n    If an example should not be scanned, then consider adding `doc-scrape-examples = false` to its `[[example]]` definition in {}\",\n        relative_manifest_path.display()\n    )\n}\n\n/// Creates a unit of work invoking `rustc` for building the `unit`.\nfn rustc(\n    build_runner: &mut BuildRunner<'_, '_>,\n    unit: &Unit,\n    exec: &Arc<dyn Executor>,\n) -> CargoResult<Work> {\n    let mut rustc = prepare_rustc(build_runner, unit)?;\n\n    let name = unit.pkg.name();\n\n    let outputs = build_runner.outputs(unit)?;\n    let root = build_runner.files().output_dir(unit);\n\n    // Prepare the native lib state (extra `-L` and `-l` flags).\n    let build_script_outputs = Arc::clone(&build_runner.build_script_outputs);\n    let current_id = unit.pkg.package_id();\n    let manifest = ManifestErrorContext::new(build_runner, unit);\n    let build_scripts = build_runner.build_scripts.get(unit).cloned();\n\n    // If we are a binary and the package also contains a library, then we\n    // don't pass the `-l` flags.\n    let pass_l_flag = unit.target.is_lib() || !unit.pkg.targets().iter().any(|t| t.is_lib());\n\n    let dep_info_name =\n        if let Some(c_extra_filename) = build_runner.files().metadata(unit).c_extra_filename() {\n            format!(\"{}-{}.d\", unit.target.crate_name(), c_extra_filename)\n        } else {\n            format!(\"{}.d\", unit.target.crate_name())\n        };\n    let rustc_dep_info_loc = root.join(dep_info_name);\n    let dep_info_loc = fingerprint::dep_info_loc(build_runner, unit);\n\n    let mut output_options = OutputOptions::new(build_runner, unit);\n    let package_id = unit.pkg.package_id();\n    let target = Target::clone(&unit.target);\n    let mode = unit.mode;\n\n    exec.init(build_runner, unit);\n    let exec = exec.clone();\n\n    let root_output = build_runner.files().host_dest().map(|v| v.to_path_buf());\n    let build_dir = build_runner.bcx.ws.build_dir().into_path_unlocked();\n    let pkg_root = unit.pkg.root().to_path_buf();\n    let cwd = rustc\n        .get_cwd()\n        .unwrap_or_else(|| build_runner.bcx.gctx.cwd())\n        .to_path_buf();\n    let fingerprint_dir = build_runner.files().fingerprint_dir(unit);\n    let script_metadatas = build_runner.find_build_script_metadatas(unit);\n    let is_local = unit.is_local();\n    let artifact = unit.artifact;\n    let sbom_files = build_runner.sbom_output_files(unit)?;\n    let sbom = build_sbom(build_runner, unit)?;\n\n    let hide_diagnostics_for_scrape_unit = build_runner.bcx.unit_can_fail_for_docscraping(unit)\n        && !matches!(\n            build_runner.bcx.gctx.shell().verbosity(),\n            Verbosity::Verbose\n        );\n    let failed_scrape_diagnostic = hide_diagnostics_for_scrape_unit.then(|| {\n        // If this unit is needed for doc-scraping, then we generate a diagnostic that\n        // describes the set of reverse-dependencies that cause the unit to be needed.\n        let target_desc = unit.target.description_named();\n        let mut for_scrape_units = build_runner\n            .bcx\n            .scrape_units_have_dep_on(unit)\n            .into_iter()\n            .map(|unit| unit.target.description_named())\n            .collect::<Vec<_>>();\n        for_scrape_units.sort();\n        let for_scrape_units = for_scrape_units.join(\", \");\n        make_failed_scrape_diagnostic(build_runner, unit, format_args!(\"failed to check {target_desc} in package `{name}` as a prerequisite for scraping examples from: {for_scrape_units}\"))\n    });\n    if hide_diagnostics_for_scrape_unit {\n        output_options.show_diagnostics = false;\n    }\n    let env_config = Arc::clone(build_runner.bcx.gctx.env_config()?);\n    return Ok(Work::new(move |state| {\n        // Artifacts are in a different location than typical units,\n        // hence we must assure the crate- and target-dependent\n        // directory is present.\n        if artifact.is_true() {\n            paths::create_dir_all(&root)?;\n        }\n\n        // Only at runtime have we discovered what the extra -L and -l\n        // arguments are for native libraries, so we process those here. We\n        // also need to be sure to add any -L paths for our plugins to the\n        // dynamic library load path as a plugin's dynamic library may be\n        // located somewhere in there.\n        // Finally, if custom environment variables have been produced by\n        // previous build scripts, we include them in the rustc invocation.\n        if let Some(build_scripts) = build_scripts {\n            let script_outputs = build_script_outputs.lock().unwrap();\n            add_native_deps(\n                &mut rustc,\n                &script_outputs,\n                &build_scripts,\n                pass_l_flag,\n                &target,\n                current_id,\n                mode,\n            )?;\n            if let Some(ref root_output) = root_output {\n                add_plugin_deps(&mut rustc, &script_outputs, &build_scripts, root_output)?;\n            }\n            add_custom_flags(&mut rustc, &script_outputs, script_metadatas)?;\n        }\n\n        for output in outputs.iter() {\n            // If there is both an rmeta and rlib, rustc will prefer to use the\n            // rlib, even if it is older. Therefore, we must delete the rlib to\n            // force using the new rmeta.\n            if output.path.extension() == Some(OsStr::new(\"rmeta\")) {\n                let dst = root.join(&output.path).with_extension(\"rlib\");\n                if dst.exists() {\n                    paths::remove_file(&dst)?;\n                }\n            }\n\n            // Some linkers do not remove the executable, but truncate and modify it.\n            // That results in the old hard-link being modified even after renamed.\n            // We delete the old artifact here to prevent this behavior from confusing users.\n            // See rust-lang/cargo#8348.\n            if output.hardlink.is_some() && output.path.exists() {\n                _ = paths::remove_file(&output.path).map_err(|e| {\n                    tracing::debug!(\n                        \"failed to delete previous output file `{:?}`: {e:?}\",\n                        output.path\n                    );\n                });\n            }\n        }\n\n        state.running(&rustc);\n        let timestamp = paths::set_invocation_time(&fingerprint_dir)?;\n        for file in sbom_files {\n            tracing::debug!(\"writing sbom to {}\", file.display());\n            let outfile = BufWriter::new(paths::create(&file)?);\n            serde_json::to_writer(outfile, &sbom)?;\n        }\n\n        let result = exec\n            .exec(\n                &rustc,\n                package_id,\n                &target,\n                mode,\n                &mut |line| on_stdout_line(state, line, package_id, &target),\n                &mut |line| {\n                    on_stderr_line(\n                        state,\n                        line,\n                        package_id,\n                        &manifest,\n                        &target,\n                        &mut output_options,\n                    )\n                },\n            )\n            .map_err(|e| {\n                if output_options.errors_seen == 0 {\n                    // If we didn't expect an error, do not require --verbose to fail.\n                    // This is intended to debug\n                    // https://github.com/rust-lang/crater/issues/733, where we are seeing\n                    // Cargo exit unsuccessfully while seeming to not show any errors.\n                    e\n                } else {\n                    verbose_if_simple_exit_code(e)\n                }\n            })\n            .with_context(|| {\n                // adapted from rustc_errors/src/lib.rs\n                let warnings = match output_options.warnings_seen {\n                    0 => String::new(),\n                    1 => \"; 1 warning emitted\".to_string(),\n                    count => format!(\"; {} warnings emitted\", count),\n                };\n                let errors = match output_options.errors_seen {\n                    0 => String::new(),\n                    1 => \" due to 1 previous error\".to_string(),\n                    count => format!(\" due to {} previous errors\", count),\n                };\n                let name = descriptive_pkg_name(&name, &target, &mode);\n                format!(\"could not compile {name}{errors}{warnings}\")\n            });\n\n        if let Err(e) = result {\n            if let Some(diagnostic) = failed_scrape_diagnostic {\n                state.warning(diagnostic);\n            }\n\n            return Err(e);\n        }\n\n        // Exec should never return with success *and* generate an error.\n        debug_assert_eq!(output_options.errors_seen, 0);\n\n        if rustc_dep_info_loc.exists() {\n            fingerprint::translate_dep_info(\n                &rustc_dep_info_loc,\n                &dep_info_loc,\n                &cwd,\n                &pkg_root,\n                &build_dir,\n                &rustc,\n                // Do not track source files in the fingerprint for registry dependencies.\n                is_local,\n                &env_config,\n            )\n            .with_context(|| {\n                internal(format!(\n                    \"could not parse/generate dep info at: {}\",\n                    rustc_dep_info_loc.display()\n                ))\n            })?;\n            // This mtime shift allows Cargo to detect if a source file was\n            // modified in the middle of the build.\n            paths::set_file_time_no_err(dep_info_loc, timestamp);\n        }\n\n        // This mtime shift for .rmeta is a workaround as rustc incremental build\n        // since rust-lang/rust#114669 (1.90.0) skips unnecessary rmeta generation.\n        //\n        // The situation is like this:\n        //\n        // 1. When build script execution's external dependendies\n        //    (rerun-if-changed, rerun-if-env-changed) got updated,\n        //    the execution unit reran and got a newer mtime.\n        // 2. rustc type-checked the associated crate, though with incremental\n        //    compilation, no rmeta regeneration. Its `.rmeta` stays old.\n        // 3. Run `cargo check` again. Cargo found build script execution had\n        //    a new mtime than existing crate rmeta, so re-checking the crate.\n        //    However the check is a no-op (input has no change), so stuck.\n        if mode.is_check() {\n            for output in outputs.iter() {\n                paths::set_file_time_no_err(&output.path, timestamp);\n            }\n        }\n\n        Ok(())\n    }));\n\n    // Add all relevant `-L` and `-l` flags from dependencies (now calculated and\n    // present in `state`) to the command provided.\n    fn add_native_deps(\n        rustc: &mut ProcessBuilder,\n        build_script_outputs: &BuildScriptOutputs,\n        build_scripts: &BuildScripts,\n        pass_l_flag: bool,\n        target: &Target,\n        current_id: PackageId,\n        mode: CompileMode,\n    ) -> CargoResult<()> {\n        let mut library_paths = vec![];\n\n        for key in build_scripts.to_link.iter() {\n            let output = build_script_outputs.get(key.1).ok_or_else(|| {\n                internal(format!(\n                    \"couldn't find build script output for {}/{}\",\n                    key.0, key.1\n                ))\n            })?;\n            library_paths.extend(output.library_paths.iter());\n        }\n\n        // NOTE: This very intentionally does not use the derived ord from LibraryPath because we need to\n        // retain relative ordering within the same type (i.e. not lexicographic). The use of a stable sort\n        // is also important here because it ensures that paths of the same type retain the same relative\n        // ordering (for an unstable sort to work here, the list would need to retain the idx of each element\n        // and then sort by that idx when the type is equivalent.\n        library_paths.sort_by_key(|p| match p {\n            LibraryPath::CargoArtifact(_) => 0,\n            LibraryPath::External(_) => 1,\n        });\n\n        for path in library_paths.iter() {\n            rustc.arg(\"-L\").arg(path.as_ref());\n        }\n\n        for key in build_scripts.to_link.iter() {\n            let output = build_script_outputs.get(key.1).ok_or_else(|| {\n                internal(format!(\n                    \"couldn't find build script output for {}/{}\",\n                    key.0, key.1\n                ))\n            })?;\n\n            if key.0 == current_id {\n                if pass_l_flag {\n                    for name in output.library_links.iter() {\n                        rustc.arg(\"-l\").arg(name);\n                    }\n                }\n            }\n\n            for (lt, arg) in &output.linker_args {\n                // There was an unintentional change where cdylibs were\n                // allowed to be passed via transitive dependencies. This\n                // clause should have been kept in the `if` block above. For\n                // now, continue allowing it for cdylib only.\n                // See https://github.com/rust-lang/cargo/issues/9562\n                if lt.applies_to(target, mode)\n                    && (key.0 == current_id || *lt == LinkArgTarget::Cdylib)\n                {\n                    rustc.arg(\"-C\").arg(format!(\"link-arg={}\", arg));\n                }\n            }\n        }\n        Ok(())\n    }\n}\n\nfn verbose_if_simple_exit_code(err: Error) -> Error {\n    // If a signal on unix (`code == None`) or an abnormal termination\n    // on Windows (codes like `0xC0000409`), don't hide the error details.\n    match err\n        .downcast_ref::<ProcessError>()\n        .as_ref()\n        .and_then(|perr| perr.code)\n    {\n        Some(n) if cargo_util::is_simple_exit_code(n) => VerboseError::new(err).into(),\n        _ => err,\n    }\n}\n\nfn prebuild_lock_exclusive(lock: LockKey) -> Work {\n    Work::new(move |state| {\n        state.lock_exclusive(&lock)?;\n        Ok(())\n    })\n}\n\nfn downgrade_lock_to_shared(lock: LockKey) -> Work {\n    Work::new(move |state| {\n        state.downgrade_to_shared(&lock)?;\n        Ok(())\n    })\n}\n\n/// Link the compiled target (often of form `foo-{metadata_hash}`) to the\n/// final target. This must happen during both \"Fresh\" and \"Compile\".\nfn link_targets(\n    build_runner: &mut BuildRunner<'_, '_>,\n    unit: &Unit,\n    fresh: bool,\n) -> CargoResult<Work> {\n    let bcx = build_runner.bcx;\n    let outputs = build_runner.outputs(unit)?;\n    let export_dir = build_runner.files().export_dir();\n    let package_id = unit.pkg.package_id();\n    let manifest_path = PathBuf::from(unit.pkg.manifest_path());\n    let profile = unit.profile.clone();\n    let unit_mode = unit.mode;\n    let features = unit.features.iter().map(|s| s.to_string()).collect();\n    let json_messages = bcx.build_config.emit_json();\n    let executable = build_runner.get_executable(unit)?;\n    let mut target = Target::clone(&unit.target);\n    if let TargetSourcePath::Metabuild = target.src_path() {\n        // Give it something to serialize.\n        let path = unit\n            .pkg\n            .manifest()\n            .metabuild_path(build_runner.bcx.ws.build_dir());\n        target.set_src_path(TargetSourcePath::Path(path));\n    }\n\n    Ok(Work::new(move |state| {\n        // If we're a \"root crate\", e.g., the target of this compilation, then we\n        // hard link our outputs out of the `deps` directory into the directory\n        // above. This means that `cargo build` will produce binaries in\n        // `target/debug` which one probably expects.\n        let mut destinations = vec![];\n        for output in outputs.iter() {\n            let src = &output.path;\n            // This may have been a `cargo rustc` command which changes the\n            // output, so the source may not actually exist.\n            if !src.exists() {\n                continue;\n            }\n            let Some(dst) = output.hardlink.as_ref() else {\n                destinations.push(src.clone());\n                continue;\n            };\n            destinations.push(dst.clone());\n            paths::link_or_copy(src, dst)?;\n            if let Some(ref path) = output.export_path {\n                let export_dir = export_dir.as_ref().unwrap();\n                paths::create_dir_all(export_dir)?;\n\n                paths::link_or_copy(src, path)?;\n            }\n        }\n\n        if json_messages {\n            let debuginfo = match profile.debuginfo.into_inner() {\n                TomlDebugInfo::None => machine_message::ArtifactDebuginfo::Int(0),\n                TomlDebugInfo::Limited => machine_message::ArtifactDebuginfo::Int(1),\n                TomlDebugInfo::Full => machine_message::ArtifactDebuginfo::Int(2),\n                TomlDebugInfo::LineDirectivesOnly => {\n                    machine_message::ArtifactDebuginfo::Named(\"line-directives-only\")\n                }\n                TomlDebugInfo::LineTablesOnly => {\n                    machine_message::ArtifactDebuginfo::Named(\"line-tables-only\")\n                }\n            };\n            let art_profile = machine_message::ArtifactProfile {\n                opt_level: profile.opt_level.as_str(),\n                debuginfo: Some(debuginfo),\n                debug_assertions: profile.debug_assertions,\n                overflow_checks: profile.overflow_checks,\n                test: unit_mode.is_any_test(),\n            };\n\n            let msg = machine_message::Artifact {\n                package_id: package_id.to_spec(),\n                manifest_path,\n                target: &target,\n                profile: art_profile,\n                features,\n                filenames: destinations,\n                executable,\n                fresh,\n            }\n            .to_json_string();\n            state.stdout(msg)?;\n        }\n        Ok(())\n    }))\n}\n\n// For all plugin dependencies, add their -L paths (now calculated and present\n// in `build_script_outputs`) to the dynamic library load path for the command\n// to execute.\nfn add_plugin_deps(\n    rustc: &mut ProcessBuilder,\n    build_script_outputs: &BuildScriptOutputs,\n    build_scripts: &BuildScripts,\n    root_output: &Path,\n) -> CargoResult<()> {\n    let var = paths::dylib_path_envvar();\n    let search_path = rustc.get_env(var).unwrap_or_default();\n    let mut search_path = env::split_paths(&search_path).collect::<Vec<_>>();\n    for (pkg_id, metadata) in &build_scripts.plugins {\n        let output = build_script_outputs\n            .get(*metadata)\n            .ok_or_else(|| internal(format!(\"couldn't find libs for plugin dep {}\", pkg_id)))?;\n        search_path.append(&mut filter_dynamic_search_path(\n            output.library_paths.iter().map(AsRef::as_ref),\n            root_output,\n        ));\n    }\n    let search_path = paths::join_paths(&search_path, var)?;\n    rustc.env(var, &search_path);\n    Ok(())\n}\n\nfn get_dynamic_search_path(path: &Path) -> &Path {\n    match path.to_str().and_then(|s| s.split_once(\"=\")) {\n        Some((\"native\" | \"crate\" | \"dependency\" | \"framework\" | \"all\", path)) => Path::new(path),\n        _ => path,\n    }\n}\n\n// Determine paths to add to the dynamic search path from -L entries\n//\n// Strip off prefixes like \"native=\" or \"framework=\" and filter out directories\n// **not** inside our output directory since they are likely spurious and can cause\n// clashes with system shared libraries (issue #3366).\nfn filter_dynamic_search_path<'a, I>(paths: I, root_output: &Path) -> Vec<PathBuf>\nwhere\n    I: Iterator<Item = &'a PathBuf>,\n{\n    let mut search_path = vec![];\n    for dir in paths {\n        let dir = get_dynamic_search_path(dir);\n        if dir.starts_with(&root_output) {\n            search_path.push(dir.to_path_buf());\n        } else {\n            debug!(\n                \"Not including path {} in runtime library search path because it is \\\n                 outside target root {}\",\n                dir.display(),\n                root_output.display()\n            );\n        }\n    }\n    search_path\n}\n\n/// Prepares flags and environments we can compute for a `rustc` invocation\n/// before the job queue starts compiling any unit.\n///\n/// This builds a static view of the invocation. Flags depending on the\n/// completion of other units will be added later in runtime, such as flags\n/// from build scripts.\nfn prepare_rustc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<ProcessBuilder> {\n    let gctx = build_runner.bcx.gctx;\n    let is_primary = build_runner.is_primary_package(unit);\n    let is_workspace = build_runner.bcx.ws.is_member(&unit.pkg);\n\n    let mut base = build_runner\n        .compilation\n        .rustc_process(unit, is_primary, is_workspace)?;\n    build_base_args(build_runner, &mut base, unit)?;\n    if unit.pkg.manifest().is_embedded() {\n        if !gctx.cli_unstable().script {\n            anyhow::bail!(\n                \"parsing `{}` requires `-Zscript`\",\n                unit.pkg.manifest_path().display()\n            );\n        }\n        base.arg(\"-Z\").arg(\"crate-attr=feature(frontmatter)\");\n        base.arg(\"-Z\").arg(\"crate-attr=allow(unused_features)\");\n    }\n\n    base.inherit_jobserver(&build_runner.jobserver);\n    build_deps_args(&mut base, build_runner, unit)?;\n    add_cap_lints(build_runner.bcx, unit, &mut base);\n    if let Some(args) = build_runner.bcx.extra_args_for(unit) {\n        base.args(args);\n    }\n    base.args(&unit.rustflags);\n    if gctx.cli_unstable().binary_dep_depinfo {\n        base.arg(\"-Z\").arg(\"binary-dep-depinfo\");\n    }\n    if build_runner.bcx.gctx.cli_unstable().checksum_freshness {\n        base.arg(\"-Z\").arg(\"checksum-hash-algorithm=blake3\");\n    }\n\n    if is_primary {\n        base.env(\"CARGO_PRIMARY_PACKAGE\", \"1\");\n        let file_list = build_runner.sbom_output_files(unit)?;\n        if !file_list.is_empty() {\n            let file_list = std::env::join_paths(file_list)?;\n            base.env(\"CARGO_SBOM_PATH\", file_list);\n        }\n    }\n\n    if unit.target.is_test() || unit.target.is_bench() {\n        let tmp = build_runner\n            .files()\n            .layout(unit.kind)\n            .build_dir()\n            .prepare_tmp()?;\n        base.env(\"CARGO_TARGET_TMPDIR\", tmp.display().to_string());\n    }\n\n    Ok(base)\n}\n\n/// Prepares flags and environments we can compute for a `rustdoc` invocation\n/// before the job queue starts compiling any unit.\n///\n/// This builds a static view of the invocation. Flags depending on the\n/// completion of other units will be added later in runtime, such as flags\n/// from build scripts.\nfn prepare_rustdoc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<ProcessBuilder> {\n    let bcx = build_runner.bcx;\n    // script_metadata is not needed here, it is only for tests.\n    let mut rustdoc = build_runner.compilation.rustdoc_process(unit, None)?;\n    if unit.pkg.manifest().is_embedded() {\n        if !bcx.gctx.cli_unstable().script {\n            anyhow::bail!(\n                \"parsing `{}` requires `-Zscript`\",\n                unit.pkg.manifest_path().display()\n            );\n        }\n        rustdoc.arg(\"-Z\").arg(\"crate-attr=feature(frontmatter)\");\n        rustdoc.arg(\"-Z\").arg(\"crate-attr=allow(unused_features)\");\n    }\n    rustdoc.inherit_jobserver(&build_runner.jobserver);\n    let crate_name = unit.target.crate_name();\n    rustdoc.arg(\"--crate-name\").arg(&crate_name);\n    add_path_args(bcx.ws, unit, &mut rustdoc);\n    add_cap_lints(bcx, unit, &mut rustdoc);\n\n    unit.kind.add_target_arg(&mut rustdoc);\n    let doc_dir = build_runner.files().output_dir(unit);\n    rustdoc.arg(\"-o\").arg(&doc_dir);\n    rustdoc.args(&features_args(unit));\n    rustdoc.args(&check_cfg_args(unit));\n\n    add_error_format_and_color(build_runner, &mut rustdoc);\n    add_allow_features(build_runner, &mut rustdoc);\n\n    if build_runner.bcx.gctx.cli_unstable().rustdoc_depinfo {\n        // html-static-files is required for keeping the shared styling resources\n        // html-non-static-files is required for keeping the original rustdoc emission\n        let mut arg = if build_runner.bcx.gctx.cli_unstable().rustdoc_mergeable_info {\n            // toolchain resources are written at the end, at the same time as merging\n            OsString::from(\"--emit=html-non-static-files,dep-info=\")\n        } else {\n            // if not using mergeable CCI, everything is written every time\n            OsString::from(\"--emit=html-static-files,html-non-static-files,dep-info=\")\n        };\n        arg.push(rustdoc_dep_info_loc(build_runner, unit));\n        rustdoc.arg(arg);\n\n        if build_runner.bcx.gctx.cli_unstable().checksum_freshness {\n            rustdoc.arg(\"-Z\").arg(\"checksum-hash-algorithm=blake3\");\n        }\n\n        rustdoc.arg(\"-Zunstable-options\");\n    } else if build_runner.bcx.gctx.cli_unstable().rustdoc_mergeable_info {\n        // toolchain resources are written at the end, at the same time as merging\n        rustdoc.arg(\"--emit=html-non-static-files\");\n        rustdoc.arg(\"-Zunstable-options\");\n    }\n\n    if build_runner.bcx.gctx.cli_unstable().rustdoc_mergeable_info {\n        // write out mergeable data to be imported\n        rustdoc.arg(\"--merge=none\");\n        let mut arg = OsString::from(\"--parts-out-dir=\");\n        // `-Zrustdoc-mergeable-info` always uses the new layout.\n        arg.push(build_runner.files().out_dir_new_layout(unit));\n        rustdoc.arg(arg);\n    }\n\n    if let Some(trim_paths) = unit.profile.trim_paths.as_ref() {\n        trim_paths_args_rustdoc(&mut rustdoc, build_runner, unit, trim_paths)?;\n    }\n\n    rustdoc.args(unit.pkg.manifest().lint_rustflags());\n\n    let metadata = build_runner.metadata_for_doc_units[unit];\n    rustdoc\n        .arg(\"-C\")\n        .arg(format!(\"metadata={}\", metadata.c_metadata()));\n\n    if unit.mode.is_doc_scrape() {\n        debug_assert!(build_runner.bcx.scrape_units.contains(unit));\n\n        if unit.target.is_test() {\n            rustdoc.arg(\"--scrape-tests\");\n        }\n\n        rustdoc.arg(\"-Zunstable-options\");\n\n        rustdoc\n            .arg(\"--scrape-examples-output-path\")\n            .arg(scrape_output_path(build_runner, unit)?);\n\n        // Only scrape example for items from crates in the workspace, to reduce generated file size\n        for pkg in build_runner.bcx.packages.packages() {\n            let names = pkg\n                .targets()\n                .iter()\n                .map(|target| target.crate_name())\n                .collect::<HashSet<_>>();\n            for name in names {\n                rustdoc.arg(\"--scrape-examples-target-crate\").arg(name);\n            }\n        }\n    }\n\n    if should_include_scrape_units(build_runner.bcx, unit) {\n        rustdoc.arg(\"-Zunstable-options\");\n    }\n\n    build_deps_args(&mut rustdoc, build_runner, unit)?;\n    rustdoc::add_root_urls(build_runner, unit, &mut rustdoc)?;\n\n    rustdoc::add_output_format(build_runner, &mut rustdoc)?;\n\n    if let Some(args) = build_runner.bcx.extra_args_for(unit) {\n        rustdoc.args(args);\n    }\n    rustdoc.args(&unit.rustdocflags);\n\n    if !crate_version_flag_already_present(&rustdoc) {\n        append_crate_version_flag(unit, &mut rustdoc);\n    }\n\n    Ok(rustdoc)\n}\n\n/// Creates a unit of work invoking `rustdoc` for documenting the `unit`.\nfn rustdoc(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<Work> {\n    let mut rustdoc = prepare_rustdoc(build_runner, unit)?;\n\n    let crate_name = unit.target.crate_name();\n    let doc_dir = build_runner.files().output_dir(unit);\n    // Create the documentation directory ahead of time as rustdoc currently has\n    // a bug where concurrent invocations will race to create this directory if\n    // it doesn't already exist.\n    paths::create_dir_all(&doc_dir)?;\n\n    let target_desc = unit.target.description_named();\n    let name = unit.pkg.name();\n    let build_script_outputs = Arc::clone(&build_runner.build_script_outputs);\n    let package_id = unit.pkg.package_id();\n    let target = Target::clone(&unit.target);\n    let manifest = ManifestErrorContext::new(build_runner, unit);\n\n    let rustdoc_dep_info_loc = rustdoc_dep_info_loc(build_runner, unit);\n    let dep_info_loc = fingerprint::dep_info_loc(build_runner, unit);\n    let build_dir = build_runner.bcx.ws.build_dir().into_path_unlocked();\n    let pkg_root = unit.pkg.root().to_path_buf();\n    let cwd = rustdoc\n        .get_cwd()\n        .unwrap_or_else(|| build_runner.bcx.gctx.cwd())\n        .to_path_buf();\n    let fingerprint_dir = build_runner.files().fingerprint_dir(unit);\n    let is_local = unit.is_local();\n    let env_config = Arc::clone(build_runner.bcx.gctx.env_config()?);\n    let rustdoc_depinfo_enabled = build_runner.bcx.gctx.cli_unstable().rustdoc_depinfo;\n\n    let mut output_options = OutputOptions::new(build_runner, unit);\n    let script_metadatas = build_runner.find_build_script_metadatas(unit);\n    let scrape_outputs = if should_include_scrape_units(build_runner.bcx, unit) {\n        Some(\n            build_runner\n                .bcx\n                .scrape_units\n                .iter()\n                .map(|unit| {\n                    Ok((\n                        build_runner.files().metadata(unit).unit_id(),\n                        scrape_output_path(build_runner, unit)?,\n                    ))\n                })\n                .collect::<CargoResult<HashMap<_, _>>>()?,\n        )\n    } else {\n        None\n    };\n\n    let failed_scrape_units = Arc::clone(&build_runner.failed_scrape_units);\n    let hide_diagnostics_for_scrape_unit = build_runner.bcx.unit_can_fail_for_docscraping(unit)\n        && !matches!(\n            build_runner.bcx.gctx.shell().verbosity(),\n            Verbosity::Verbose\n        );\n    let failed_scrape_diagnostic = hide_diagnostics_for_scrape_unit.then(|| {\n        make_failed_scrape_diagnostic(\n            build_runner,\n            unit,\n            format_args!(\"failed to scan {target_desc} in package `{name}` for example code usage\"),\n        )\n    });\n    if hide_diagnostics_for_scrape_unit {\n        output_options.show_diagnostics = false;\n    }\n\n    Ok(Work::new(move |state| {\n        add_custom_flags(\n            &mut rustdoc,\n            &build_script_outputs.lock().unwrap(),\n            script_metadatas,\n        )?;\n\n        // Add the output of scraped examples to the rustdoc command.\n        // This action must happen after the unit's dependencies have finished,\n        // because some of those deps may be Docscrape units which have failed.\n        // So we dynamically determine which `--with-examples` flags to pass here.\n        if let Some(scrape_outputs) = scrape_outputs {\n            let failed_scrape_units = failed_scrape_units.lock().unwrap();\n            for (metadata, output_path) in &scrape_outputs {\n                if !failed_scrape_units.contains(metadata) {\n                    rustdoc.arg(\"--with-examples\").arg(output_path);\n                }\n            }\n        }\n\n        let crate_dir = doc_dir.join(&crate_name);\n        if crate_dir.exists() {\n            // Remove output from a previous build. This ensures that stale\n            // files for removed items are removed.\n            debug!(\"removing pre-existing doc directory {:?}\", crate_dir);\n            paths::remove_dir_all(crate_dir)?;\n        }\n        state.running(&rustdoc);\n        let timestamp = paths::set_invocation_time(&fingerprint_dir)?;\n\n        let result = rustdoc\n            .exec_with_streaming(\n                &mut |line| on_stdout_line(state, line, package_id, &target),\n                &mut |line| {\n                    on_stderr_line(\n                        state,\n                        line,\n                        package_id,\n                        &manifest,\n                        &target,\n                        &mut output_options,\n                    )\n                },\n                false,\n            )\n            .map_err(verbose_if_simple_exit_code)\n            .with_context(|| format!(\"could not document `{}`\", name));\n\n        if let Err(e) = result {\n            if let Some(diagnostic) = failed_scrape_diagnostic {\n                state.warning(diagnostic);\n            }\n\n            return Err(e);\n        }\n\n        if rustdoc_depinfo_enabled && rustdoc_dep_info_loc.exists() {\n            fingerprint::translate_dep_info(\n                &rustdoc_dep_info_loc,\n                &dep_info_loc,\n                &cwd,\n                &pkg_root,\n                &build_dir,\n                &rustdoc,\n                // Should we track source file for doc gen?\n                is_local,\n                &env_config,\n            )\n            .with_context(|| {\n                internal(format_args!(\n                    \"could not parse/generate dep info at: {}\",\n                    rustdoc_dep_info_loc.display()\n                ))\n            })?;\n            // This mtime shift allows Cargo to detect if a source file was\n            // modified in the middle of the build.\n            paths::set_file_time_no_err(dep_info_loc, timestamp);\n        }\n\n        Ok(())\n    }))\n}\n\n// The --crate-version flag could have already been passed in RUSTDOCFLAGS\n// or as an extra compiler argument for rustdoc\nfn crate_version_flag_already_present(rustdoc: &ProcessBuilder) -> bool {\n    rustdoc.get_args().any(|flag| {\n        flag.to_str()\n            .map_or(false, |flag| flag.starts_with(RUSTDOC_CRATE_VERSION_FLAG))\n    })\n}\n\nfn append_crate_version_flag(unit: &Unit, rustdoc: &mut ProcessBuilder) {\n    rustdoc\n        .arg(RUSTDOC_CRATE_VERSION_FLAG)\n        .arg(unit.pkg.version().to_string());\n}\n\n/// Adds [`--cap-lints`] to the command to execute.\n///\n/// [`--cap-lints`]: https://doc.rust-lang.org/nightly/rustc/lints/levels.html#capping-lints\nfn add_cap_lints(bcx: &BuildContext<'_, '_>, unit: &Unit, cmd: &mut ProcessBuilder) {\n    // If this is an upstream dep we don't want warnings from, turn off all\n    // lints.\n    if !unit.show_warnings(bcx.gctx) {\n        cmd.arg(\"--cap-lints\").arg(\"allow\");\n\n    // If this is an upstream dep but we *do* want warnings, make sure that they\n    // don't fail compilation.\n    } else if !unit.is_local() {\n        cmd.arg(\"--cap-lints\").arg(\"warn\");\n    }\n}\n\n/// Forwards [`-Zallow-features`] if it is set for cargo.\n///\n/// [`-Zallow-features`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#allow-features\nfn add_allow_features(build_runner: &BuildRunner<'_, '_>, cmd: &mut ProcessBuilder) {\n    if let Some(allow) = &build_runner.bcx.gctx.cli_unstable().allow_features {\n        use std::fmt::Write;\n        let mut arg = String::from(\"-Zallow-features=\");\n        for f in allow {\n            let _ = write!(&mut arg, \"{f},\");\n        }\n        cmd.arg(arg.trim_end_matches(','));\n    }\n}\n\n/// Adds [`--error-format`] to the command to execute.\n///\n/// Cargo always uses JSON output. This has several benefits, such as being\n/// easier to parse, handles changing formats (for replaying cached messages),\n/// ensures atomic output (so messages aren't interleaved), allows for\n/// intercepting messages like rmeta artifacts, etc. rustc includes a\n/// \"rendered\" field in the JSON message with the message properly formatted,\n/// which Cargo will extract and display to the user.\n///\n/// [`--error-format`]: https://doc.rust-lang.org/nightly/rustc/command-line-arguments.html#--error-format-control-how-errors-are-produced\nfn add_error_format_and_color(build_runner: &BuildRunner<'_, '_>, cmd: &mut ProcessBuilder) {\n    let enable_timings =\n        build_runner.bcx.gctx.cli_unstable().section_timings && build_runner.bcx.logger.is_some();\n    if enable_timings {\n        cmd.arg(\"-Zunstable-options\");\n    }\n\n    cmd.arg(\"--error-format=json\");\n    let mut json = String::from(\"--json=diagnostic-rendered-ansi,artifacts,future-incompat\");\n\n    if let MessageFormat::Short | MessageFormat::Json { short: true, .. } =\n        build_runner.bcx.build_config.message_format\n    {\n        json.push_str(\",diagnostic-short\");\n    } else if build_runner.bcx.gctx.shell().err_unicode()\n        && build_runner.bcx.gctx.cli_unstable().rustc_unicode\n    {\n        json.push_str(\",diagnostic-unicode\");\n    }\n\n    if enable_timings {\n        json.push_str(\",timings\");\n    }\n\n    cmd.arg(json);\n\n    let gctx = build_runner.bcx.gctx;\n    if let Some(width) = gctx.shell().err_width().diagnostic_terminal_width() {\n        cmd.arg(format!(\"--diagnostic-width={width}\"));\n    }\n}\n\n/// Adds essential rustc flags and environment variables to the command to execute.\nfn build_base_args(\n    build_runner: &BuildRunner<'_, '_>,\n    cmd: &mut ProcessBuilder,\n    unit: &Unit,\n) -> CargoResult<()> {\n    assert!(!unit.mode.is_run_custom_build());\n\n    let bcx = build_runner.bcx;\n    let Profile {\n        ref opt_level,\n        codegen_backend,\n        codegen_units,\n        debuginfo,\n        debug_assertions,\n        split_debuginfo,\n        overflow_checks,\n        rpath,\n        ref panic,\n        incremental,\n        strip,\n        rustflags: profile_rustflags,\n        trim_paths,\n        hint_mostly_unused: profile_hint_mostly_unused,\n        ..\n    } = unit.profile.clone();\n    let hints = unit.pkg.hints().cloned().unwrap_or_default();\n    let test = unit.mode.is_any_test();\n\n    let warn = |msg: &str| {\n        bcx.gctx.shell().warn(format!(\n            \"{}@{}: {msg}\",\n            unit.pkg.package_id().name(),\n            unit.pkg.package_id().version()\n        ))\n    };\n    let unit_capped_warn = |msg: &str| {\n        if unit.show_warnings(bcx.gctx) {\n            warn(msg)\n        } else {\n            Ok(())\n        }\n    };\n\n    cmd.arg(\"--crate-name\").arg(&unit.target.crate_name());\n\n    let edition = unit.target.edition();\n    edition.cmd_edition_arg(cmd);\n\n    add_path_args(bcx.ws, unit, cmd);\n    add_error_format_and_color(build_runner, cmd);\n    add_allow_features(build_runner, cmd);\n\n    let mut contains_dy_lib = false;\n    if !test {\n        for crate_type in &unit.target.rustc_crate_types() {\n            cmd.arg(\"--crate-type\").arg(crate_type.as_str());\n            contains_dy_lib |= crate_type == &CrateType::Dylib;\n        }\n    }\n\n    if unit.mode.is_check() {\n        cmd.arg(\"--emit=dep-info,metadata\");\n    } else if build_runner.bcx.gctx.cli_unstable().no_embed_metadata {\n        // Nightly rustc supports the -Zembed-metadata=no flag, which tells it to avoid including\n        // full metadata in rlib/dylib artifacts, to save space on disk. In this case, metadata\n        // will only be stored in .rmeta files.\n        // When we use this flag, we should also pass --emit=metadata to all artifacts that\n        // contain useful metadata (rlib/dylib/proc macros), so that a .rmeta file is actually\n        // generated. If we didn't do this, the full metadata would not get written anywhere.\n        // However, we do not want to pass --emit=metadata to artifacts that never produce useful\n        // metadata, such as binaries, because that would just unnecessarily create empty .rmeta\n        // files on disk.\n        if unit.benefits_from_no_embed_metadata() {\n            cmd.arg(\"--emit=dep-info,metadata,link\");\n            cmd.args(&[\"-Z\", \"embed-metadata=no\"]);\n        } else {\n            cmd.arg(\"--emit=dep-info,link\");\n        }\n    } else {\n        // If we don't use -Zembed-metadata=no, we emit .rmeta files only for rlib outputs.\n        // This metadata may be used in this session for a pipelined compilation, or it may\n        // be used in a future Cargo session as part of a pipelined compile.\n        if !unit.requires_upstream_objects() {\n            cmd.arg(\"--emit=dep-info,metadata,link\");\n        } else {\n            cmd.arg(\"--emit=dep-info,link\");\n        }\n    }\n\n    let prefer_dynamic = (unit.target.for_host() && !unit.target.is_custom_build())\n        || (contains_dy_lib && !build_runner.is_primary_package(unit));\n    if prefer_dynamic {\n        cmd.arg(\"-C\").arg(\"prefer-dynamic\");\n    }\n\n    if opt_level.as_str() != \"0\" {\n        cmd.arg(\"-C\").arg(&format!(\"opt-level={}\", opt_level));\n    }\n\n    if *panic != PanicStrategy::Unwind {\n        cmd.arg(\"-C\").arg(format!(\"panic={}\", panic));\n    }\n    if *panic == PanicStrategy::ImmediateAbort {\n        cmd.arg(\"-Z\").arg(\"unstable-options\");\n    }\n\n    cmd.args(&lto_args(build_runner, unit));\n\n    if let Some(backend) = codegen_backend {\n        cmd.arg(\"-Z\").arg(&format!(\"codegen-backend={}\", backend));\n    }\n\n    if let Some(n) = codegen_units {\n        cmd.arg(\"-C\").arg(&format!(\"codegen-units={}\", n));\n    }\n\n    let debuginfo = debuginfo.into_inner();\n    // Shorten the number of arguments if possible.\n    if debuginfo != TomlDebugInfo::None {\n        cmd.arg(\"-C\").arg(format!(\"debuginfo={debuginfo}\"));\n        // This is generally just an optimization on build time so if we don't\n        // pass it then it's ok. The values for the flag (off, packed, unpacked)\n        // may be supported or not depending on the platform, so availability is\n        // checked per-value. For example, at the time of writing this code, on\n        // Windows the only stable valid value for split-debuginfo is \"packed\",\n        // while on Linux \"unpacked\" is also stable.\n        if let Some(split) = split_debuginfo {\n            if build_runner\n                .bcx\n                .target_data\n                .info(unit.kind)\n                .supports_debuginfo_split(split)\n            {\n                cmd.arg(\"-C\").arg(format!(\"split-debuginfo={split}\"));\n            }\n        }\n    }\n\n    if let Some(trim_paths) = trim_paths {\n        trim_paths_args(cmd, build_runner, unit, &trim_paths)?;\n    }\n\n    cmd.args(unit.pkg.manifest().lint_rustflags());\n    cmd.args(&profile_rustflags);\n\n    // `-C overflow-checks` is implied by the setting of `-C debug-assertions`,\n    // so we only need to provide `-C overflow-checks` if it differs from\n    // the value of `-C debug-assertions` we would provide.\n    if opt_level.as_str() != \"0\" {\n        if debug_assertions {\n            cmd.args(&[\"-C\", \"debug-assertions=on\"]);\n            if !overflow_checks {\n                cmd.args(&[\"-C\", \"overflow-checks=off\"]);\n            }\n        } else if overflow_checks {\n            cmd.args(&[\"-C\", \"overflow-checks=on\"]);\n        }\n    } else if !debug_assertions {\n        cmd.args(&[\"-C\", \"debug-assertions=off\"]);\n        if overflow_checks {\n            cmd.args(&[\"-C\", \"overflow-checks=on\"]);\n        }\n    } else if !overflow_checks {\n        cmd.args(&[\"-C\", \"overflow-checks=off\"]);\n    }\n\n    if test && unit.target.harness() {\n        cmd.arg(\"--test\");\n\n        // Cargo has historically never compiled `--test` binaries with\n        // `panic=abort` because the `test` crate itself didn't support it.\n        // Support is now upstream, however, but requires an unstable flag to be\n        // passed when compiling the test. We require, in Cargo, an unstable\n        // flag to pass to rustc, so register that here. Eventually this flag\n        // will simply not be needed when the behavior is stabilized in the Rust\n        // compiler itself.\n        if *panic == PanicStrategy::Abort || *panic == PanicStrategy::ImmediateAbort {\n            cmd.arg(\"-Z\").arg(\"panic-abort-tests\");\n        }\n    } else if test {\n        cmd.arg(\"--cfg\").arg(\"test\");\n    }\n\n    cmd.args(&features_args(unit));\n    cmd.args(&check_cfg_args(unit));\n\n    let meta = build_runner.files().metadata(unit);\n    cmd.arg(\"-C\")\n        .arg(&format!(\"metadata={}\", meta.c_metadata()));\n    if let Some(c_extra_filename) = meta.c_extra_filename() {\n        cmd.arg(\"-C\")\n            .arg(&format!(\"extra-filename=-{c_extra_filename}\"));\n    }\n\n    if rpath {\n        cmd.arg(\"-C\").arg(\"rpath\");\n    }\n\n    cmd.arg(\"--out-dir\")\n        .arg(&build_runner.files().output_dir(unit));\n\n    unit.kind.add_target_arg(cmd);\n\n    add_codegen_linker(cmd, build_runner, unit, bcx.gctx.target_applies_to_host()?);\n\n    if incremental {\n        add_codegen_incremental(cmd, build_runner, unit)\n    }\n\n    let pkg_hint_mostly_unused = match hints.mostly_unused {\n        None => None,\n        Some(toml::Value::Boolean(b)) => Some(b),\n        Some(v) => {\n            unit_capped_warn(&format!(\n                \"ignoring unsupported value type ({}) for 'hints.mostly-unused', which expects a boolean\",\n                v.type_str()\n            ))?;\n            None\n        }\n    };\n    if profile_hint_mostly_unused\n        .or(pkg_hint_mostly_unused)\n        .unwrap_or(false)\n    {\n        if bcx.gctx.cli_unstable().profile_hint_mostly_unused {\n            cmd.arg(\"-Zhint-mostly-unused\");\n        } else {\n            if profile_hint_mostly_unused.is_some() {\n                // Profiles come from the top-level unit, so we don't use `unit_capped_warn` here.\n                warn(\n                    \"ignoring 'hint-mostly-unused' profile option, pass `-Zprofile-hint-mostly-unused` to enable it\",\n                )?;\n            } else if pkg_hint_mostly_unused.is_some() {\n                unit_capped_warn(\n                    \"ignoring 'hints.mostly-unused', pass `-Zprofile-hint-mostly-unused` to enable it\",\n                )?;\n            }\n        }\n    }\n\n    let strip = strip.into_inner();\n    if strip != StripInner::None {\n        cmd.arg(\"-C\").arg(format!(\"strip={}\", strip));\n    }\n\n    if unit.is_std {\n        // -Zforce-unstable-if-unmarked prevents the accidental use of\n        // unstable crates within the sysroot (such as \"extern crate libc\" or\n        // any non-public crate in the sysroot).\n        //\n        // RUSTC_BOOTSTRAP allows unstable features on stable.\n        cmd.arg(\"-Z\")\n            .arg(\"force-unstable-if-unmarked\")\n            .env(\"RUSTC_BOOTSTRAP\", \"1\");\n    }\n\n    Ok(())\n}\n\n/// All active features for the unit passed as `--cfg features=<feature-name>`.\nfn features_args(unit: &Unit) -> Vec<OsString> {\n    let mut args = Vec::with_capacity(unit.features.len() * 2);\n\n    for feat in &unit.features {\n        args.push(OsString::from(\"--cfg\"));\n        args.push(OsString::from(format!(\"feature=\\\"{}\\\"\", feat)));\n    }\n\n    args\n}\n\n/// Like [`trim_paths_args`] but for rustdoc invocations.\nfn trim_paths_args_rustdoc(\n    cmd: &mut ProcessBuilder,\n    build_runner: &BuildRunner<'_, '_>,\n    unit: &Unit,\n    trim_paths: &TomlTrimPaths,\n) -> CargoResult<()> {\n    match trim_paths {\n        // rustdoc supports diagnostics trimming only.\n        TomlTrimPaths::Values(values) if !values.contains(&TomlTrimPathsValue::Diagnostics) => {\n            return Ok(());\n        }\n        _ => {}\n    }\n\n    // feature gate was checked during manifest/config parsing.\n    cmd.arg(\"-Zunstable-options\");\n\n    // Order of `--remap-path-prefix` flags is important for `-Zbuild-std`.\n    // We want to show `/rustc/<hash>/library/std` instead of `std-0.0.0`.\n    cmd.arg(package_remap(build_runner, unit));\n    cmd.arg(build_dir_remap(build_runner));\n    cmd.arg(sysroot_remap(build_runner, unit));\n\n    Ok(())\n}\n\n/// Generates the `--remap-path-scope` and `--remap-path-prefix` for [RFC 3127].\n/// See also unstable feature [`-Ztrim-paths`].\n///\n/// [RFC 3127]: https://rust-lang.github.io/rfcs/3127-trim-paths.html\n/// [`-Ztrim-paths`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-trim-paths-option\nfn trim_paths_args(\n    cmd: &mut ProcessBuilder,\n    build_runner: &BuildRunner<'_, '_>,\n    unit: &Unit,\n    trim_paths: &TomlTrimPaths,\n) -> CargoResult<()> {\n    if trim_paths.is_none() {\n        return Ok(());\n    }\n\n    // feature gate was checked during manifest/config parsing.\n    cmd.arg(format!(\"--remap-path-scope={trim_paths}\"));\n\n    // Order of `--remap-path-prefix` flags is important for `-Zbuild-std`.\n    // We want to show `/rustc/<hash>/library/std` instead of `std-0.0.0`.\n    cmd.arg(package_remap(build_runner, unit));\n    cmd.arg(build_dir_remap(build_runner));\n    cmd.arg(sysroot_remap(build_runner, unit));\n\n    Ok(())\n}\n\n/// Path prefix remap rules for sysroot.\n///\n/// This remap logic aligns with rustc:\n/// <https://github.com/rust-lang/rust/blob/c2ef3516/src/bootstrap/src/lib.rs#L1113-L1116>\nfn sysroot_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> OsString {\n    let mut remap = OsString::from(\"--remap-path-prefix=\");\n    remap.push({\n        // See also `detect_sysroot_src_path()`.\n        let mut sysroot = build_runner.bcx.target_data.info(unit.kind).sysroot.clone();\n        sysroot.push(\"lib\");\n        sysroot.push(\"rustlib\");\n        sysroot.push(\"src\");\n        sysroot.push(\"rust\");\n        sysroot\n    });\n    remap.push(\"=\");\n    remap.push(\"/rustc/\");\n    if let Some(commit_hash) = build_runner.bcx.rustc().commit_hash.as_ref() {\n        remap.push(commit_hash);\n    } else {\n        remap.push(build_runner.bcx.rustc().version.to_string());\n    }\n    remap\n}\n\n/// Path prefix remap rules for dependencies.\n///\n/// * Git dependencies: remove `~/.cargo/git/checkouts` prefix.\n/// * Registry dependencies: remove `~/.cargo/registry/src` prefix.\n/// * Others (e.g. path dependencies):\n///     * relative paths to workspace root if inside the workspace directory.\n///     * otherwise remapped to `<pkg>-<version>`.\nfn package_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> OsString {\n    let pkg_root = unit.pkg.root();\n    let ws_root = build_runner.bcx.ws.root();\n    let mut remap = OsString::from(\"--remap-path-prefix=\");\n    let source_id = unit.pkg.package_id().source_id();\n    if source_id.is_git() {\n        remap.push(\n            build_runner\n                .bcx\n                .gctx\n                .git_checkouts_path()\n                .as_path_unlocked(),\n        );\n        remap.push(\"=\");\n    } else if source_id.is_registry() {\n        remap.push(\n            build_runner\n                .bcx\n                .gctx\n                .registry_source_path()\n                .as_path_unlocked(),\n        );\n        remap.push(\"=\");\n    } else if pkg_root.strip_prefix(ws_root).is_ok() {\n        remap.push(ws_root);\n        remap.push(\"=.\"); // remap to relative rustc work dir explicitly\n    } else {\n        remap.push(pkg_root);\n        remap.push(\"=\");\n        remap.push(unit.pkg.name());\n        remap.push(\"-\");\n        remap.push(unit.pkg.version().to_string());\n    }\n    remap\n}\n\n/// Remap all paths pointing to `build.build-dir`,\n/// i.e., `[BUILD_DIR]/debug/deps/foo-[HASH].dwo` would be remapped to\n/// `/cargo/build-dir/debug/deps/foo-[HASH].dwo`\n/// (note the `/cargo/build-dir` prefix).\n///\n/// This covers scenarios like:\n///\n/// * Build script generated code. For example, a build script may call `file!`\n///   macros, and the associated crate uses [`include!`] to include the expanded\n///   [`file!`] macro in-place via the `OUT_DIR` environment.\n/// * On Linux, `DW_AT_GNU_dwo_name` that contains paths to split debuginfo\n///   files (dwp and dwo).\nfn build_dir_remap(build_runner: &BuildRunner<'_, '_>) -> OsString {\n    let build_dir = build_runner.bcx.ws.build_dir();\n    let mut remap = OsString::from(\"--remap-path-prefix=\");\n    remap.push(build_dir.as_path_unlocked());\n    remap.push(\"=/cargo/build-dir\");\n    remap\n}\n\n/// Generates the `--check-cfg` arguments for the `unit`.\nfn check_cfg_args(unit: &Unit) -> Vec<OsString> {\n    // The routine below generates the --check-cfg arguments. Our goals here are to\n    // enable the checking of conditionals and pass the list of declared features.\n    //\n    // In the simplified case, it would resemble something like this:\n    //\n    //   --check-cfg=cfg() --check-cfg=cfg(feature, values(...))\n    //\n    // but having `cfg()` is redundant with the second argument (as well-known names\n    // and values are implicitly enabled when one or more `--check-cfg` argument is\n    // passed) so we don't emit it and just pass:\n    //\n    //   --check-cfg=cfg(feature, values(...))\n    //\n    // This way, even if there are no declared features, the config `feature` will\n    // still be expected, meaning users would get \"unexpected value\" instead of name.\n    // This wasn't always the case, see rust-lang#119930 for some details.\n\n    let gross_cap_estimation = unit.pkg.summary().features().len() * 7 + 25;\n    let mut arg_feature = OsString::with_capacity(gross_cap_estimation);\n\n    arg_feature.push(\"cfg(feature, values(\");\n    for (i, feature) in unit.pkg.summary().features().keys().enumerate() {\n        if i != 0 {\n            arg_feature.push(\", \");\n        }\n        arg_feature.push(\"\\\"\");\n        arg_feature.push(feature);\n        arg_feature.push(\"\\\"\");\n    }\n    arg_feature.push(\"))\");\n\n    // In addition to the package features, we also include the `test` cfg (since\n    // compiler-team#785, as to be able to someday apply it conditionally), as well\n    // the `docsrs` cfg from the docs.rs service.\n    //\n    // We include `docsrs` here (in Cargo) instead of rustc, since there is a much closer\n    // relationship between Cargo and docs.rs than rustc and docs.rs. In particular, all\n    // users of docs.rs use Cargo, but not all users of rustc (like Rust-for-Linux) use docs.rs.\n\n    vec![\n        OsString::from(\"--check-cfg\"),\n        OsString::from(\"cfg(docsrs,test)\"),\n        OsString::from(\"--check-cfg\"),\n        arg_feature,\n    ]\n}\n\n/// Adds LTO related codegen flags.\nfn lto_args(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> Vec<OsString> {\n    let mut result = Vec::new();\n    let mut push = |arg: &str| {\n        result.push(OsString::from(\"-C\"));\n        result.push(OsString::from(arg));\n    };\n    match build_runner.lto[unit] {\n        lto::Lto::Run(None) => push(\"lto\"),\n        lto::Lto::Run(Some(s)) => push(&format!(\"lto={}\", s)),\n        lto::Lto::Off => {\n            push(\"lto=off\");\n            push(\"embed-bitcode=no\");\n        }\n        lto::Lto::ObjectAndBitcode => {} // this is rustc's default\n        lto::Lto::OnlyBitcode => push(\"linker-plugin-lto\"),\n        lto::Lto::OnlyObject => push(\"embed-bitcode=no\"),\n    }\n    result\n}\n\n/// Adds dependency-relevant rustc flags and environment variables\n/// to the command to execute, such as [`-L`] and [`--extern`].\n///\n/// [`-L`]: https://doc.rust-lang.org/nightly/rustc/command-line-arguments.html#-l-add-a-directory-to-the-library-search-path\n/// [`--extern`]: https://doc.rust-lang.org/nightly/rustc/command-line-arguments.html#--extern-specify-where-an-external-library-is-located\nfn build_deps_args(\n    cmd: &mut ProcessBuilder,\n    build_runner: &BuildRunner<'_, '_>,\n    unit: &Unit,\n) -> CargoResult<()> {\n    let bcx = build_runner.bcx;\n\n    for arg in lib_search_paths(build_runner, unit)? {\n        cmd.arg(arg);\n    }\n\n    let deps = build_runner.unit_deps(unit);\n\n    // If there is not one linkable target but should, rustc fails later\n    // on if there is an `extern crate` for it. This may turn into a hard\n    // error in the future (see PR #4797).\n    if !deps\n        .iter()\n        .any(|dep| !dep.unit.mode.is_doc() && dep.unit.target.is_linkable())\n    {\n        if let Some(dep) = deps.iter().find(|dep| {\n            !dep.unit.mode.is_doc() && dep.unit.target.is_lib() && !dep.unit.artifact.is_true()\n        }) {\n            let dep_name = dep.unit.target.crate_name();\n            let name = unit.target.crate_name();\n            bcx.gctx.shell().print_report(&[\n                Level::WARNING.secondary_title(format!(\"the package `{dep_name}` provides no linkable target\"))\n                    .elements([\n                        Level::NOTE.message(format!(\"this might cause `{name}` to fail compilation\")),\n                        Level::NOTE.message(\"this warning might turn into a hard error in the future\"),\n                        Level::HELP.message(format!(\"consider adding 'dylib' or 'rlib' to key 'crate-type' in `{dep_name}`'s Cargo.toml\"))\n                    ])\n            ], false)?;\n        }\n    }\n\n    let mut unstable_opts = false;\n\n    // Add `OUT_DIR` environment variables for build scripts\n    let first_custom_build_dep = deps.iter().find(|dep| dep.unit.mode.is_run_custom_build());\n    if let Some(dep) = first_custom_build_dep {\n        let out_dir = if bcx.gctx.cli_unstable().build_dir_new_layout {\n            build_runner.files().out_dir_new_layout(&dep.unit)\n        } else {\n            build_runner.files().build_script_out_dir(&dep.unit)\n        };\n        cmd.env(\"OUT_DIR\", &out_dir);\n    }\n\n    // Adding output directory for each build script\n    let is_multiple_build_scripts_enabled = unit\n        .pkg\n        .manifest()\n        .unstable_features()\n        .require(Feature::multiple_build_scripts())\n        .is_ok();\n\n    if is_multiple_build_scripts_enabled {\n        for dep in deps {\n            if dep.unit.mode.is_run_custom_build() {\n                let out_dir = if bcx.gctx.cli_unstable().build_dir_new_layout {\n                    build_runner.files().out_dir_new_layout(&dep.unit)\n                } else {\n                    build_runner.files().build_script_out_dir(&dep.unit)\n                };\n                let target_name = dep.unit.target.name();\n                let out_dir_prefix = target_name\n                    .strip_prefix(\"build-script-\")\n                    .unwrap_or(target_name);\n                let out_dir_name = format!(\"{out_dir_prefix}_OUT_DIR\");\n                cmd.env(&out_dir_name, &out_dir);\n            }\n        }\n    }\n    for arg in extern_args(build_runner, unit, &mut unstable_opts)? {\n        cmd.arg(arg);\n    }\n\n    for (var, env) in artifact::get_env(build_runner, unit, deps)? {\n        cmd.env(&var, env);\n    }\n\n    // This will only be set if we're already using a feature\n    // requiring nightly rust\n    if unstable_opts {\n        cmd.arg(\"-Z\").arg(\"unstable-options\");\n    }\n\n    Ok(())\n}\n\nfn add_dep_arg<'a, 'b: 'a>(\n    map: &mut BTreeMap<&'a Unit, PathBuf>,\n    build_runner: &'b BuildRunner<'b, '_>,\n    unit: &'a Unit,\n) {\n    if map.contains_key(&unit) {\n        return;\n    }\n    map.insert(&unit, build_runner.files().deps_dir(&unit));\n\n    for dep in build_runner.unit_deps(unit) {\n        add_dep_arg(map, build_runner, &dep.unit);\n    }\n}\n\n/// Adds extra rustc flags and environment variables collected from the output\n/// of a build-script to the command to execute, include custom environment\n/// variables and `cfg`.\nfn add_custom_flags(\n    cmd: &mut ProcessBuilder,\n    build_script_outputs: &BuildScriptOutputs,\n    metadata_vec: Option<Vec<UnitHash>>,\n) -> CargoResult<()> {\n    if let Some(metadata_vec) = metadata_vec {\n        for metadata in metadata_vec {\n            if let Some(output) = build_script_outputs.get(metadata) {\n                for cfg in output.cfgs.iter() {\n                    cmd.arg(\"--cfg\").arg(cfg);\n                }\n                for check_cfg in &output.check_cfgs {\n                    cmd.arg(\"--check-cfg\").arg(check_cfg);\n                }\n                for (name, value) in output.env.iter() {\n                    cmd.env(name, value);\n                }\n            }\n        }\n    }\n\n    Ok(())\n}\n\n/// Generate a list of `-L` arguments\npub fn lib_search_paths(\n    build_runner: &BuildRunner<'_, '_>,\n    unit: &Unit,\n) -> CargoResult<Vec<OsString>> {\n    let mut lib_search_paths = Vec::new();\n    if build_runner.bcx.gctx.cli_unstable().build_dir_new_layout {\n        let mut map = BTreeMap::new();\n\n        // Recursively add all dependency args to rustc process\n        add_dep_arg(&mut map, build_runner, unit);\n\n        let paths = map.into_iter().map(|(_, path)| path).sorted_unstable();\n\n        for path in paths {\n            let mut deps = OsString::from(\"dependency=\");\n            deps.push(path);\n            lib_search_paths.extend([\"-L\".into(), deps]);\n        }\n    } else {\n        let mut deps = OsString::from(\"dependency=\");\n        deps.push(build_runner.files().deps_dir(unit));\n        lib_search_paths.extend([\"-L\".into(), deps]);\n    }\n\n    // Be sure that the host path is also listed. This'll ensure that proc macro\n    // dependencies are correctly found (for reexported macros).\n    if !unit.kind.is_host() {\n        let mut deps = OsString::from(\"dependency=\");\n        deps.push(build_runner.files().host_deps(unit));\n        lib_search_paths.extend([\"-L\".into(), deps]);\n    }\n\n    Ok(lib_search_paths)\n}\n\n/// Generates a list of `--extern` arguments.\npub fn extern_args(\n    build_runner: &BuildRunner<'_, '_>,\n    unit: &Unit,\n    unstable_opts: &mut bool,\n) -> CargoResult<Vec<OsString>> {\n    let mut result = Vec::new();\n    let deps = build_runner.unit_deps(unit);\n\n    let no_embed_metadata = build_runner.bcx.gctx.cli_unstable().no_embed_metadata;\n\n    // Closure to add one dependency to `result`.\n    let mut link_to = |dep: &UnitDep,\n                       extern_crate_name: InternedString,\n                       noprelude: bool,\n                       nounused: bool|\n     -> CargoResult<()> {\n        let mut value = OsString::new();\n        let mut opts = Vec::new();\n        let is_public_dependency_enabled = unit\n            .pkg\n            .manifest()\n            .unstable_features()\n            .require(Feature::public_dependency())\n            .is_ok()\n            || build_runner.bcx.gctx.cli_unstable().public_dependency;\n        if !dep.public && unit.target.is_lib() && is_public_dependency_enabled {\n            opts.push(\"priv\");\n            *unstable_opts = true;\n        }\n        if noprelude {\n            opts.push(\"noprelude\");\n            *unstable_opts = true;\n        }\n        if nounused {\n            opts.push(\"nounused\");\n            *unstable_opts = true;\n        }\n        if !opts.is_empty() {\n            value.push(opts.join(\",\"));\n            value.push(\":\");\n        }\n        value.push(extern_crate_name.as_str());\n        value.push(\"=\");\n\n        let mut pass = |file| {\n            let mut value = value.clone();\n            value.push(file);\n            result.push(OsString::from(\"--extern\"));\n            result.push(value);\n        };\n\n        let outputs = build_runner.outputs(&dep.unit)?;\n\n        if build_runner.only_requires_rmeta(unit, &dep.unit) || dep.unit.mode.is_check() {\n            // Example: rlib dependency for an rlib, rmeta is all that is required.\n            let output = outputs\n                .iter()\n                .find(|output| output.flavor == FileFlavor::Rmeta)\n                .expect(\"failed to find rmeta dep for pipelined dep\");\n            pass(&output.path);\n        } else {\n            // Example: a bin needs `rlib` for dependencies, it cannot use rmeta.\n            for output in outputs.iter() {\n                if output.flavor == FileFlavor::Linkable {\n                    pass(&output.path);\n                }\n                // If we use -Zembed-metadata=no, we also need to pass the path to the\n                // corresponding .rmeta file to the linkable artifact, because the\n                // normal dependency (rlib) doesn't contain the full metadata.\n                else if no_embed_metadata && output.flavor == FileFlavor::Rmeta {\n                    pass(&output.path);\n                }\n            }\n        }\n        Ok(())\n    };\n\n    for dep in deps {\n        if dep.unit.target.is_linkable() && !dep.unit.mode.is_doc() {\n            link_to(dep, dep.extern_crate_name, dep.noprelude, dep.nounused)?;\n        }\n    }\n    if unit.target.proc_macro() {\n        // Automatically import `proc_macro`.\n        result.push(OsString::from(\"--extern\"));\n        result.push(OsString::from(\"proc_macro\"));\n    }\n\n    Ok(result)\n}\n\n/// Adds `-C linker=<path>` if specified.\nfn add_codegen_linker(\n    cmd: &mut ProcessBuilder,\n    build_runner: &BuildRunner<'_, '_>,\n    unit: &Unit,\n    target_applies_to_host: bool,\n) {\n    let linker = if unit.target.for_host() && !target_applies_to_host {\n        build_runner\n            .compilation\n            .host_linker()\n            .map(|s| s.as_os_str())\n    } else {\n        build_runner\n            .compilation\n            .target_linker(unit.kind)\n            .map(|s| s.as_os_str())\n    };\n\n    if let Some(linker) = linker {\n        let mut arg = OsString::from(\"linker=\");\n        arg.push(linker);\n        cmd.arg(\"-C\").arg(arg);\n    }\n}\n\n/// Adds `-C incremental=<path>`.\nfn add_codegen_incremental(\n    cmd: &mut ProcessBuilder,\n    build_runner: &BuildRunner<'_, '_>,\n    unit: &Unit,\n) {\n    let dir = build_runner.files().incremental_dir(&unit);\n    let mut arg = OsString::from(\"incremental=\");\n    arg.push(dir.as_os_str());\n    cmd.arg(\"-C\").arg(arg);\n}\n\nfn envify(s: &str) -> String {\n    s.chars()\n        .flat_map(|c| c.to_uppercase())\n        .map(|c| if c == '-' { '_' } else { c })\n        .collect()\n}\n\n/// Configuration of the display of messages emitted by the compiler,\n/// e.g. diagnostics, warnings, errors, and message caching.\nstruct OutputOptions {\n    /// What format we're emitting from Cargo itself.\n    format: MessageFormat,\n    /// Where to write the JSON messages to support playback later if the unit\n    /// is fresh. The file is created lazily so that in the normal case, lots\n    /// of empty files are not created. If this is None, the output will not\n    /// be cached (such as when replaying cached messages).\n    cache_cell: Option<(PathBuf, OnceCell<File>)>,\n    /// If `true`, display any diagnostics.\n    /// Other types of JSON messages are processed regardless\n    /// of the value of this flag.\n    ///\n    /// This is used primarily for cache replay. If you build with `-vv`, the\n    /// cache will be filled with diagnostics from dependencies. When the\n    /// cache is replayed without `-vv`, we don't want to show them.\n    show_diagnostics: bool,\n    /// Tracks the number of warnings we've seen so far.\n    warnings_seen: usize,\n    /// Tracks the number of errors we've seen so far.\n    errors_seen: usize,\n}\n\nimpl OutputOptions {\n    fn new(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> OutputOptions {\n        let path = build_runner.files().message_cache_path(unit);\n        // Remove old cache, ignore ENOENT, which is the common case.\n        drop(fs::remove_file(&path));\n        let cache_cell = Some((path, OnceCell::new()));\n        let show_diagnostics =\n            build_runner.bcx.gctx.warning_handling().unwrap_or_default() != WarningHandling::Allow;\n        OutputOptions {\n            format: build_runner.bcx.build_config.message_format,\n            cache_cell,\n            show_diagnostics,\n            warnings_seen: 0,\n            errors_seen: 0,\n        }\n    }\n}\n\n/// Cloned and sendable context about the manifest file.\n///\n/// Sometimes we enrich rustc's errors with some locations in the manifest file; this\n/// contains a `Send`-able copy of the manifest information that we need for the\n/// enriched errors.\nstruct ManifestErrorContext {\n    /// The path to the manifest.\n    path: PathBuf,\n    /// The locations of various spans within the manifest.\n    spans: Option<toml::Spanned<toml::de::DeTable<'static>>>,\n    /// The raw manifest contents.\n    contents: Option<String>,\n    /// A lookup for all the unambiguous renamings, mapping from the original package\n    /// name to the renamed one.\n    rename_table: HashMap<InternedString, InternedString>,\n    /// A list of targets we're compiling for, to determine which of the `[target.<something>.dependencies]`\n    /// tables might be of interest.\n    requested_kinds: Vec<CompileKind>,\n    /// A list of all the collections of cfg values, one collection for each target, to determine\n    /// which of the `[target.'cfg(...)'.dependencies]` tables might be of interest.\n    cfgs: Vec<Vec<Cfg>>,\n    host_name: InternedString,\n    /// Cargo's working directory (for printing out a more friendly manifest path).\n    cwd: PathBuf,\n    /// Terminal width for formatting diagnostics.\n    term_width: usize,\n}\n\nfn on_stdout_line(\n    state: &JobState<'_, '_>,\n    line: &str,\n    _package_id: PackageId,\n    _target: &Target,\n) -> CargoResult<()> {\n    state.stdout(line.to_string())?;\n    Ok(())\n}\n\nfn on_stderr_line(\n    state: &JobState<'_, '_>,\n    line: &str,\n    package_id: PackageId,\n    manifest: &ManifestErrorContext,\n    target: &Target,\n    options: &mut OutputOptions,\n) -> CargoResult<()> {\n    if on_stderr_line_inner(state, line, package_id, manifest, target, options)? {\n        // Check if caching is enabled.\n        if let Some((path, cell)) = &mut options.cache_cell {\n            // Cache the output, which will be replayed later when Fresh.\n            let f = cell.try_borrow_mut_with(|| paths::create(path))?;\n            debug_assert!(!line.contains('\\n'));\n            f.write_all(line.as_bytes())?;\n            f.write_all(&[b'\\n'])?;\n        }\n    }\n    Ok(())\n}\n\n/// Returns true if the line should be cached.\nfn on_stderr_line_inner(\n    state: &JobState<'_, '_>,\n    line: &str,\n    package_id: PackageId,\n    manifest: &ManifestErrorContext,\n    target: &Target,\n    options: &mut OutputOptions,\n) -> CargoResult<bool> {\n    // We primarily want to use this function to process JSON messages from\n    // rustc. The compiler should always print one JSON message per line, and\n    // otherwise it may have other output intermingled (think RUST_LOG or\n    // something like that), so skip over everything that doesn't look like a\n    // JSON message.\n    if !line.starts_with('{') {\n        state.stderr(line.to_string())?;\n        return Ok(true);\n    }\n\n    let mut compiler_message: Box<serde_json::value::RawValue> = match serde_json::from_str(line) {\n        Ok(msg) => msg,\n\n        // If the compiler produced a line that started with `{` but it wasn't\n        // valid JSON, maybe it wasn't JSON in the first place! Forward it along\n        // to stderr.\n        Err(e) => {\n            debug!(\"failed to parse json: {:?}\", e);\n            state.stderr(line.to_string())?;\n            return Ok(true);\n        }\n    };\n\n    let count_diagnostic = |level, options: &mut OutputOptions| {\n        if level == \"warning\" {\n            options.warnings_seen += 1;\n        } else if level == \"error\" {\n            options.errors_seen += 1;\n        }\n    };\n\n    if let Ok(report) = serde_json::from_str::<FutureIncompatReport>(compiler_message.get()) {\n        for item in &report.future_incompat_report {\n            count_diagnostic(&*item.diagnostic.level, options);\n        }\n        state.future_incompat_report(report.future_incompat_report);\n        return Ok(true);\n    }\n\n    let res = serde_json::from_str::<SectionTiming>(compiler_message.get());\n    if let Ok(timing_record) = res {\n        state.on_section_timing_emitted(timing_record);\n        return Ok(false);\n    }\n\n    // Returns `true` if the diagnostic was modified.\n    let add_pub_in_priv_diagnostic = |diag: &mut String| -> bool {\n        // We are parsing the compiler diagnostic here, as this information isn't\n        // currently exposed elsewhere.\n        // At the time of writing this comment, rustc emits two different\n        // \"exported_private_dependencies\" errors:\n        //  - type `FromPriv` from private dependency 'priv_dep' in public interface\n        //  - struct `FromPriv` from private dependency 'priv_dep' is re-exported\n        // This regex matches them both. To see if it needs to be updated, grep the rust\n        // source for \"EXPORTED_PRIVATE_DEPENDENCIES\".\n        static PRIV_DEP_REGEX: LazyLock<Regex> =\n            LazyLock::new(|| Regex::new(\"from private dependency '([A-Za-z0-9-_]+)'\").unwrap());\n        if let Some(crate_name) = PRIV_DEP_REGEX.captures(diag).and_then(|m| m.get(1))\n            && let Some(ref contents) = manifest.contents\n            && let Some(span) = manifest.find_crate_span(crate_name.as_str())\n        {\n            let rel_path = pathdiff::diff_paths(&manifest.path, &manifest.cwd)\n                .unwrap_or_else(|| manifest.path.clone())\n                .display()\n                .to_string();\n            let report = [Group::with_title(Level::NOTE.secondary_title(format!(\n                \"dependency `{}` declared here\",\n                crate_name.as_str()\n            )))\n            .element(\n                Snippet::source(contents)\n                    .path(rel_path)\n                    .annotation(AnnotationKind::Context.span(span)),\n            )];\n\n            let rendered = Renderer::styled()\n                .term_width(manifest.term_width)\n                .render(&report);\n            diag.push_str(&rendered);\n            diag.push('\\n');\n            return true;\n        }\n        false\n    };\n\n    // Depending on what we're emitting from Cargo itself, we figure out what to\n    // do with this JSON message.\n    match options.format {\n        // In the \"human\" output formats (human/short) or if diagnostic messages\n        // from rustc aren't being included in the output of Cargo's JSON\n        // messages then we extract the diagnostic (if present) here and handle\n        // it ourselves.\n        MessageFormat::Human\n        | MessageFormat::Short\n        | MessageFormat::Json {\n            render_diagnostics: true,\n            ..\n        } => {\n            #[derive(serde::Deserialize)]\n            struct CompilerMessage<'a> {\n                // `rendered` contains escape sequences, which can't be\n                // zero-copy deserialized by serde_json.\n                // See https://github.com/serde-rs/json/issues/742\n                rendered: String,\n                #[serde(borrow)]\n                message: Cow<'a, str>,\n                #[serde(borrow)]\n                level: Cow<'a, str>,\n                children: Vec<PartialDiagnostic>,\n                code: Option<DiagnosticCode>,\n            }\n\n            // A partial rustfix::diagnostics::Diagnostic. We deserialize only a\n            // subset of the fields because rustc's output can be extremely\n            // deeply nested JSON in pathological cases involving macro\n            // expansion. Rustfix's Diagnostic struct is recursive containing a\n            // field `children: Vec<Self>`, and it can cause deserialization to\n            // hit serde_json's default recursion limit, or overflow the stack\n            // if we turn that off. Cargo only cares about the 1 field listed\n            // here.\n            #[derive(serde::Deserialize)]\n            struct PartialDiagnostic {\n                spans: Vec<PartialDiagnosticSpan>,\n            }\n\n            // A partial rustfix::diagnostics::DiagnosticSpan.\n            #[derive(serde::Deserialize)]\n            struct PartialDiagnosticSpan {\n                suggestion_applicability: Option<Applicability>,\n            }\n\n            #[derive(serde::Deserialize)]\n            struct DiagnosticCode {\n                code: String,\n            }\n\n            if let Ok(mut msg) = serde_json::from_str::<CompilerMessage<'_>>(compiler_message.get())\n            {\n                if msg.message.starts_with(\"aborting due to\")\n                    || msg.message.ends_with(\"warning emitted\")\n                    || msg.message.ends_with(\"warnings emitted\")\n                {\n                    // Skip this line; we'll print our own summary at the end.\n                    return Ok(true);\n                }\n                // state.stderr will add a newline\n                if msg.rendered.ends_with('\\n') {\n                    msg.rendered.pop();\n                }\n                let mut rendered = msg.rendered;\n                if options.show_diagnostics {\n                    let machine_applicable: bool = msg\n                        .children\n                        .iter()\n                        .map(|child| {\n                            child\n                                .spans\n                                .iter()\n                                .filter_map(|span| span.suggestion_applicability)\n                                .any(|app| app == Applicability::MachineApplicable)\n                        })\n                        .any(|b| b);\n                    count_diagnostic(&msg.level, options);\n                    if msg\n                        .code\n                        .as_ref()\n                        .is_some_and(|c| c.code == \"exported_private_dependencies\")\n                        && options.format != MessageFormat::Short\n                    {\n                        add_pub_in_priv_diagnostic(&mut rendered);\n                    }\n                    let lint = msg.code.is_some();\n                    state.emit_diag(&msg.level, rendered, lint, machine_applicable)?;\n                }\n                return Ok(true);\n            }\n        }\n\n        MessageFormat::Json { ansi, .. } => {\n            #[derive(serde::Deserialize, serde::Serialize)]\n            struct CompilerMessage<'a> {\n                rendered: String,\n                #[serde(flatten, borrow)]\n                other: std::collections::BTreeMap<Cow<'a, str>, serde_json::Value>,\n                code: Option<DiagnosticCode<'a>>,\n            }\n\n            #[derive(serde::Deserialize, serde::Serialize)]\n            struct DiagnosticCode<'a> {\n                code: String,\n                #[serde(flatten, borrow)]\n                other: std::collections::BTreeMap<Cow<'a, str>, serde_json::Value>,\n            }\n\n            if let Ok(mut error) =\n                serde_json::from_str::<CompilerMessage<'_>>(compiler_message.get())\n            {\n                let modified_diag = if error\n                    .code\n                    .as_ref()\n                    .is_some_and(|c| c.code == \"exported_private_dependencies\")\n                {\n                    add_pub_in_priv_diagnostic(&mut error.rendered)\n                } else {\n                    false\n                };\n\n                // Remove color information from the rendered string if color is not\n                // enabled. Cargo always asks for ANSI colors from rustc. This allows\n                // cached replay to enable/disable colors without re-invoking rustc.\n                if !ansi {\n                    error.rendered = anstream::adapter::strip_str(&error.rendered).to_string();\n                }\n                if !ansi || modified_diag {\n                    let new_line = serde_json::to_string(&error)?;\n                    compiler_message = serde_json::value::RawValue::from_string(new_line)?;\n                }\n            }\n        }\n    }\n\n    // We always tell rustc to emit messages about artifacts being produced.\n    // These messages feed into pipelined compilation, as well as timing\n    // information.\n    //\n    // Look for a matching directive and inform Cargo internally that a\n    // metadata file has been produced.\n    #[derive(serde::Deserialize)]\n    struct ArtifactNotification<'a> {\n        #[serde(borrow)]\n        artifact: Cow<'a, str>,\n    }\n\n    if let Ok(artifact) = serde_json::from_str::<ArtifactNotification<'_>>(compiler_message.get()) {\n        trace!(\"found directive from rustc: `{}`\", artifact.artifact);\n        if artifact.artifact.ends_with(\".rmeta\") {\n            debug!(\"looks like metadata finished early!\");\n            state.rmeta_produced();\n        }\n        return Ok(false);\n    }\n\n    // And failing all that above we should have a legitimate JSON diagnostic\n    // from the compiler, so wrap it in an external Cargo JSON message\n    // indicating which package it came from and then emit it.\n\n    if !options.show_diagnostics {\n        return Ok(true);\n    }\n\n    #[derive(serde::Deserialize)]\n    struct CompilerMessage<'a> {\n        #[serde(borrow)]\n        message: Cow<'a, str>,\n        #[serde(borrow)]\n        level: Cow<'a, str>,\n    }\n\n    if let Ok(msg) = serde_json::from_str::<CompilerMessage<'_>>(compiler_message.get()) {\n        if msg.message.starts_with(\"aborting due to\")\n            || msg.message.ends_with(\"warning emitted\")\n            || msg.message.ends_with(\"warnings emitted\")\n        {\n            // Skip this line; we'll print our own summary at the end.\n            return Ok(true);\n        }\n        count_diagnostic(&msg.level, options);\n    }\n\n    let msg = machine_message::FromCompiler {\n        package_id: package_id.to_spec(),\n        manifest_path: &manifest.path,\n        target,\n        message: compiler_message,\n    }\n    .to_json_string();\n\n    // Switch json lines from rustc/rustdoc that appear on stderr to stdout\n    // instead. We want the stdout of Cargo to always be machine parseable as\n    // stderr has our colorized human-readable messages.\n    state.stdout(msg)?;\n    Ok(true)\n}\n\nimpl ManifestErrorContext {\n    fn new(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> ManifestErrorContext {\n        let mut duplicates = HashSet::new();\n        let mut rename_table = HashMap::new();\n\n        for dep in build_runner.unit_deps(unit) {\n            let unrenamed_id = dep.unit.pkg.package_id().name();\n            if duplicates.contains(&unrenamed_id) {\n                continue;\n            }\n            match rename_table.entry(unrenamed_id) {\n                std::collections::hash_map::Entry::Occupied(occ) => {\n                    occ.remove_entry();\n                    duplicates.insert(unrenamed_id);\n                }\n                std::collections::hash_map::Entry::Vacant(vac) => {\n                    vac.insert(dep.extern_crate_name);\n                }\n            }\n        }\n\n        let bcx = build_runner.bcx;\n        ManifestErrorContext {\n            path: unit.pkg.manifest_path().to_owned(),\n            spans: unit.pkg.manifest().document().cloned(),\n            contents: unit.pkg.manifest().contents().map(String::from),\n            requested_kinds: bcx.target_data.requested_kinds().to_owned(),\n            host_name: bcx.rustc().host,\n            rename_table,\n            cwd: path_args(build_runner.bcx.ws, unit).1,\n            cfgs: bcx\n                .target_data\n                .requested_kinds()\n                .iter()\n                .map(|k| bcx.target_data.cfg(*k).to_owned())\n                .collect(),\n            term_width: bcx\n                .gctx\n                .shell()\n                .err_width()\n                .diagnostic_terminal_width()\n                .unwrap_or(annotate_snippets::renderer::DEFAULT_TERM_WIDTH),\n        }\n    }\n\n    fn requested_target_names(&self) -> impl Iterator<Item = &str> {\n        self.requested_kinds.iter().map(|kind| match kind {\n            CompileKind::Host => &self.host_name,\n            CompileKind::Target(target) => target.short_name(),\n        })\n    }\n\n    /// Find a span for the dependency that specifies this unrenamed crate, if it's unique.\n    ///\n    /// rustc diagnostics (at least for public-in-private) mention the un-renamed\n    /// crate: if you have `foo = { package = \"bar\" }`, the rustc diagnostic will\n    /// say \"bar\".\n    ///\n    /// This function does its best to find a span for \"bar\", but it could fail if\n    /// there are multiple candidates:\n    ///\n    /// ```toml\n    /// foo = { package = \"bar\" }\n    /// baz = { path = \"../bar\", package = \"bar\" }\n    /// ```\n    fn find_crate_span(&self, unrenamed: &str) -> Option<Range<usize>> {\n        let Some(ref spans) = self.spans else {\n            return None;\n        };\n\n        let orig_name = self.rename_table.get(unrenamed)?.as_str();\n\n        if let Some((k, v)) = get_key_value(&spans, &[\"dependencies\", orig_name]) {\n            // We make some effort to find the unrenamed text: in\n            //\n            // ```\n            // foo = { package = \"bar\" }\n            // ```\n            //\n            // we try to find the \"bar\", but fall back to \"foo\" if we can't (which might\n            // happen if the renaming took place in the workspace, for example).\n            if let Some(package) = v.get_ref().as_table().and_then(|t| t.get(\"package\")) {\n                return Some(package.span());\n            } else {\n                return Some(k.span());\n            }\n        }\n\n        // The dependency could also be in a target-specific table, like\n        // [target.x86_64-unknown-linux-gnu.dependencies] or\n        // [target.'cfg(something)'.dependencies]. We filter out target tables\n        // that don't match a requested target or a requested cfg.\n        if let Some(target) = spans\n            .as_ref()\n            .get(\"target\")\n            .and_then(|t| t.as_ref().as_table())\n        {\n            for (platform, platform_table) in target.iter() {\n                match platform.as_ref().parse::<Platform>() {\n                    Ok(Platform::Name(name)) => {\n                        if !self.requested_target_names().any(|n| n == name) {\n                            continue;\n                        }\n                    }\n                    Ok(Platform::Cfg(cfg_expr)) => {\n                        if !self.cfgs.iter().any(|cfgs| cfg_expr.matches(cfgs)) {\n                            continue;\n                        }\n                    }\n                    Err(_) => continue,\n                }\n\n                let Some(platform_table) = platform_table.as_ref().as_table() else {\n                    continue;\n                };\n\n                if let Some(deps) = platform_table\n                    .get(\"dependencies\")\n                    .and_then(|d| d.as_ref().as_table())\n                {\n                    if let Some((k, v)) = deps.get_key_value(orig_name) {\n                        if let Some(package) = v.get_ref().as_table().and_then(|t| t.get(\"package\"))\n                        {\n                            return Some(package.span());\n                        } else {\n                            return Some(k.span());\n                        }\n                    }\n                }\n            }\n        }\n        None\n    }\n}\n\n/// Creates a unit of work that replays the cached compiler message.\n///\n/// Usually used when a job is fresh and doesn't need to recompile.\nfn replay_output_cache(\n    package_id: PackageId,\n    manifest: ManifestErrorContext,\n    target: &Target,\n    path: PathBuf,\n    format: MessageFormat,\n    show_diagnostics: bool,\n) -> Work {\n    let target = target.clone();\n    let mut options = OutputOptions {\n        format,\n        cache_cell: None,\n        show_diagnostics,\n        warnings_seen: 0,\n        errors_seen: 0,\n    };\n    Work::new(move |state| {\n        if !path.exists() {\n            // No cached output, probably didn't emit anything.\n            return Ok(());\n        }\n        // We sometimes have gigabytes of output from the compiler, so avoid\n        // loading it all into memory at once, as that can cause OOM where\n        // otherwise there would be none.\n        let file = paths::open(&path)?;\n        let mut reader = std::io::BufReader::new(file);\n        let mut line = String::new();\n        loop {\n            let length = reader.read_line(&mut line)?;\n            if length == 0 {\n                break;\n            }\n            let trimmed = line.trim_end_matches(&['\\n', '\\r'][..]);\n            on_stderr_line(state, trimmed, package_id, &manifest, &target, &mut options)?;\n            line.clear();\n        }\n        Ok(())\n    })\n}\n\n/// Provides a package name with descriptive target information,\n/// e.g., '`foo` (bin \"bar\" test)', '`foo` (lib doctest)'.\nfn descriptive_pkg_name(name: &str, target: &Target, mode: &CompileMode) -> String {\n    let desc_name = target.description_named();\n    let mode = if mode.is_rustc_test() && !(target.is_test() || target.is_bench()) {\n        \" test\"\n    } else if mode.is_doc_test() {\n        \" doctest\"\n    } else if mode.is_doc() {\n        \" doc\"\n    } else {\n        \"\"\n    };\n    format!(\"`{name}` ({desc_name}{mode})\")\n}\n\n/// Applies environment variables from config `[env]` to [`ProcessBuilder`].\npub(crate) fn apply_env_config(\n    gctx: &crate::GlobalContext,\n    cmd: &mut ProcessBuilder,\n) -> CargoResult<()> {\n    for (key, value) in gctx.env_config()?.iter() {\n        // never override a value that has already been set by cargo\n        if cmd.get_envs().contains_key(key) {\n            continue;\n        }\n        cmd.env(key, value);\n    }\n    Ok(())\n}\n\n/// Checks if there are some scrape units waiting to be processed.\nfn should_include_scrape_units(bcx: &BuildContext<'_, '_>, unit: &Unit) -> bool {\n    unit.mode.is_doc() && bcx.scrape_units.len() > 0 && bcx.ws.unit_needs_doc_scrape(unit)\n}\n\n/// Gets the file path of function call information output from `rustdoc`.\nfn scrape_output_path(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<PathBuf> {\n    assert!(unit.mode.is_doc() || unit.mode.is_doc_scrape());\n    build_runner\n        .outputs(unit)\n        .map(|outputs| outputs[0].path.clone())\n}\n\n/// Gets the dep-info file emitted by rustdoc.\nfn rustdoc_dep_info_loc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> PathBuf {\n    let mut loc = build_runner.files().fingerprint_file_path(unit, \"\");\n    loc.set_extension(\"d\");\n    loc\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/output_depinfo.rs",
    "content": "//! dep-info files for external build system integration.\n//! See [`output_depinfo`] for more.\n\nuse cargo_util::paths::normalize_path;\nuse std::collections::{BTreeSet, HashSet};\nuse std::io::{BufWriter, Write};\nuse std::path::{Path, PathBuf};\n\nuse super::{BuildRunner, FileFlavor, Unit, fingerprint};\nuse crate::util::{CargoResult, internal};\nuse cargo_util::paths;\nuse tracing::debug;\n\n/// Basically just normalizes a given path and converts it to a string.\nfn render_filename<P: AsRef<Path>>(path: P, basedir: Option<&str>) -> CargoResult<String> {\n    fn wrap_path(path: &Path) -> CargoResult<String> {\n        path.to_str()\n            .ok_or_else(|| internal(format!(\"path `{:?}` not utf-8\", path)))\n            .map(|f| f.replace(\" \", \"\\\\ \"))\n    }\n\n    let path = path.as_ref();\n    if let Some(basedir) = basedir {\n        let norm_path = normalize_path(path);\n        let norm_basedir = normalize_path(basedir.as_ref());\n        match norm_path.strip_prefix(norm_basedir) {\n            Ok(relpath) => wrap_path(relpath),\n            _ => wrap_path(path),\n        }\n    } else {\n        wrap_path(path)\n    }\n}\n\n/// Collects all dependencies of the `unit` for the output dep info file.\n///\n/// Dependencies will be stored in `deps`, including:\n///\n/// * dependencies from [fingerprint dep-info]\n/// * paths from `rerun-if-changed` build script instruction\n/// * ...and traverse transitive dependencies recursively\n///\n/// [fingerprint dep-info]: super::fingerprint#fingerprint-dep-info-files\nfn add_deps_for_unit(\n    deps: &mut BTreeSet<PathBuf>,\n    build_runner: &mut BuildRunner<'_, '_>,\n    unit: &Unit,\n    visited: &mut HashSet<Unit>,\n) -> CargoResult<()> {\n    if !visited.insert(unit.clone()) {\n        return Ok(());\n    }\n\n    // units representing the execution of a build script don't actually\n    // generate a dep info file, so we just keep on going below\n    if !unit.mode.is_run_custom_build() {\n        // Add dependencies from rustc dep-info output (stored in fingerprint directory)\n        let dep_info_loc = fingerprint::dep_info_loc(build_runner, unit);\n        if let Some(paths) = fingerprint::parse_dep_info(\n            unit.pkg.root(),\n            build_runner.files().host_build_root(),\n            &dep_info_loc,\n        )? {\n            for path in paths.files.into_keys() {\n                deps.insert(path);\n            }\n        } else {\n            debug!(\n                \"can't find dep_info for {:?} {}\",\n                unit.pkg.package_id(),\n                unit.target\n            );\n            return Err(internal(\"dep_info missing\"));\n        }\n    }\n\n    // Add rerun-if-changed dependencies\n    if let Some(metadata_vec) = build_runner.find_build_script_metadatas(unit) {\n        for metadata in metadata_vec {\n            if let Some(output) = build_runner\n                .build_script_outputs\n                .lock()\n                .unwrap()\n                .get(metadata)\n            {\n                for path in &output.rerun_if_changed {\n                    let package_root = unit.pkg.root();\n\n                    let path = if path.as_os_str().is_empty() {\n                        // Joining with an empty path causes Rust to add a trailing path separator.\n                        // On Windows, this would add an invalid trailing backslash to the .d file.\n                        package_root.to_path_buf()\n                    } else {\n                        // The paths we have saved from the unit are of arbitrary relativeness and\n                        // may be relative to the crate root of the dependency.\n                        package_root.join(path)\n                    };\n\n                    deps.insert(path);\n                }\n            }\n        }\n    }\n\n    // Recursively traverse all transitive dependencies\n    let unit_deps = Vec::from(build_runner.unit_deps(unit)); // Create vec due to mutable borrow.\n    for dep in unit_deps {\n        if dep.unit.is_local() {\n            add_deps_for_unit(deps, build_runner, &dep.unit, visited)?;\n        }\n    }\n    Ok(())\n}\n\n/// Save a `.d` dep-info file for the given unit. This is the third kind of\n/// dep-info mentioned in [`fingerprint`] module.\n///\n/// Argument `unit` is expected to be the root unit, which will be uplifted.\n///\n/// Cargo emits its own dep-info files in the output directory. This is\n/// only done for every \"uplifted\" artifact. These are intended to be used\n/// with external build systems so that they can detect if Cargo needs to be\n/// re-executed.\n///\n/// It includes all the entries from the `rustc` dep-info file, and extends it\n/// with any `rerun-if-changed` entries from build scripts. It also includes\n/// sources from any path dependencies. Registry dependencies are not included\n/// under the assumption that changes to them can be detected via changes to\n/// `Cargo.lock`.\n///\n/// [`fingerprint`]: super::fingerprint#dep-info-files\npub fn output_depinfo(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<()> {\n    let bcx = build_runner.bcx;\n    let mut deps = BTreeSet::new();\n    let mut visited = HashSet::new();\n    let success = add_deps_for_unit(&mut deps, build_runner, unit, &mut visited).is_ok();\n    let basedir_string;\n    let basedir = match bcx.gctx.build_config()?.dep_info_basedir.clone() {\n        Some(value) => {\n            basedir_string = value\n                .resolve_path(bcx.gctx)\n                .as_os_str()\n                .to_str()\n                .ok_or_else(|| anyhow::format_err!(\"build.dep-info-basedir path not utf-8\"))?\n                .to_string();\n            Some(basedir_string.as_str())\n        }\n        None => None,\n    };\n    let deps = deps\n        .iter()\n        .map(|f| render_filename(f, basedir))\n        .collect::<CargoResult<Vec<_>>>()?;\n\n    for output in build_runner.outputs(unit)?.iter().filter(|o| {\n        !matches!(\n            o.flavor,\n            FileFlavor::DebugInfo | FileFlavor::Auxiliary | FileFlavor::Sbom\n        )\n    }) {\n        if let Some(ref link_dst) = output.hardlink {\n            let output_path = link_dst.with_extension(\"d\");\n            if success {\n                let target_fn = render_filename(link_dst, basedir)?;\n\n                // If nothing changed don't recreate the file which could alter\n                // its mtime\n                if let Ok(previous) = fingerprint::parse_rustc_dep_info(&output_path) {\n                    if previous\n                        .files\n                        .iter()\n                        .map(|(path, _checksum)| path)\n                        .eq(deps.iter().map(Path::new))\n                    {\n                        continue;\n                    }\n                }\n\n                // Otherwise write it all out\n                let mut outfile = BufWriter::new(paths::create(output_path)?);\n                write!(outfile, \"{}:\", target_fn)?;\n                for dep in &deps {\n                    write!(outfile, \" {}\", dep)?;\n                }\n                writeln!(outfile)?;\n\n            // dep-info generation failed, so delete output file. This will\n            // usually cause the build system to always rerun the build\n            // rule, which is correct if inefficient.\n            } else if output_path.exists() {\n                paths::remove_file(output_path)?;\n            }\n        }\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/output_sbom.rs",
    "content": "//! cargo-sbom precursor files for external tools to create SBOM files from.\n//! See [`build_sbom_graph`] for more.\n\nuse std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};\nuse std::path::PathBuf;\n\nuse cargo_util_schemas::core::PackageIdSpec;\nuse itertools::Itertools;\nuse serde::Serialize;\n\nuse crate::CargoResult;\nuse crate::core::TargetKind;\nuse crate::util::Rustc;\nuse crate::util::interning::InternedString;\n\nuse super::{BuildRunner, CompileMode, Unit};\n\n/// Typed version of a SBOM format version number.\n#[derive(Serialize, Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]\npub struct SbomFormatVersion(u32);\n\n#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize)]\n#[serde(rename_all = \"snake_case\")]\nenum SbomDependencyType {\n    /// A dependency linked to the artifact produced by this unit.\n    Normal,\n    /// A dependency needed to run the build for this unit (e.g. a build script or proc-macro).\n    /// The dependency is not linked to the artifact produced by this unit.\n    Build,\n}\n\n#[derive(Serialize, Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]\nstruct SbomIndex(usize);\n\n#[derive(Serialize, Clone, Debug)]\n#[serde(rename_all = \"snake_case\")]\nstruct SbomDependency {\n    index: SbomIndex,\n    kind: SbomDependencyType,\n}\n\n#[derive(Serialize, Clone, Debug)]\n#[serde(rename_all = \"snake_case\")]\nstruct SbomCrate {\n    id: PackageIdSpec,\n    features: Vec<String>,\n    dependencies: Vec<SbomDependency>,\n    kind: TargetKind,\n}\n\nimpl SbomCrate {\n    pub fn new(unit: &Unit) -> Self {\n        let package_id = unit.pkg.package_id().to_spec();\n        let features = unit.features.iter().map(|f| f.to_string()).collect_vec();\n        Self {\n            id: package_id,\n            features,\n            dependencies: Vec::new(),\n            kind: unit.target.kind().clone(),\n        }\n    }\n}\n\n#[derive(Serialize, Clone)]\n#[serde(rename_all = \"snake_case\")]\nstruct SbomRustc {\n    version: String,\n    wrapper: Option<PathBuf>,\n    workspace_wrapper: Option<PathBuf>,\n    commit_hash: Option<String>,\n    host: String,\n    verbose_version: String,\n}\n\nimpl From<&Rustc> for SbomRustc {\n    fn from(rustc: &Rustc) -> Self {\n        Self {\n            version: rustc.version.to_string(),\n            wrapper: rustc.wrapper.clone(),\n            workspace_wrapper: rustc.workspace_wrapper.clone(),\n            commit_hash: rustc.commit_hash.clone(),\n            host: rustc.host.to_string(),\n            verbose_version: rustc.verbose_version.clone(),\n        }\n    }\n}\n\n#[derive(Serialize)]\n#[serde(rename_all = \"snake_case\")]\npub struct Sbom {\n    version: SbomFormatVersion,\n    root: SbomIndex,\n    crates: Vec<SbomCrate>,\n    rustc: SbomRustc,\n    target: InternedString,\n}\n\n/// Build an [`Sbom`] for the given [`Unit`].\npub fn build_sbom(build_runner: &BuildRunner<'_, '_>, root: &Unit) -> CargoResult<Sbom> {\n    let bcx = build_runner.bcx;\n    let rustc: SbomRustc = bcx.rustc().into();\n\n    let mut crates = Vec::new();\n    let sbom_graph = build_sbom_graph(build_runner, root);\n\n    // Build set of indices for each node in the graph for fast lookup.\n    let indices: HashMap<&Unit, SbomIndex> = sbom_graph\n        .keys()\n        .enumerate()\n        .map(|(i, dep)| (*dep, SbomIndex(i)))\n        .collect();\n\n    // Add a item to the crates list for each node in the graph.\n    for (unit, edges) in sbom_graph {\n        let mut krate = SbomCrate::new(unit);\n        for (dep, kind) in edges {\n            krate.dependencies.push(SbomDependency {\n                index: indices[dep],\n                kind: kind,\n            });\n        }\n        crates.push(krate);\n    }\n    let target = match root.kind {\n        super::CompileKind::Host => build_runner.bcx.host_triple(),\n        super::CompileKind::Target(target) => target.rustc_target(),\n    };\n    Ok(Sbom {\n        version: SbomFormatVersion(1),\n        crates,\n        root: indices[root],\n        rustc,\n        target,\n    })\n}\n\n/// List all dependencies, including transitive ones. A dependency can also appear multiple times\n/// if it's using different settings, e.g. profile, features or crate versions.\n///\n/// Returns a graph of dependencies.\nfn build_sbom_graph<'a>(\n    build_runner: &'a BuildRunner<'_, '_>,\n    root: &'a Unit,\n) -> BTreeMap<&'a Unit, BTreeSet<(&'a Unit, SbomDependencyType)>> {\n    tracing::trace!(\"building sbom graph for {}\", root.pkg.package_id());\n\n    let mut queue = Vec::new();\n    let mut sbom_graph: BTreeMap<&Unit, BTreeSet<(&Unit, SbomDependencyType)>> = BTreeMap::new();\n    let mut visited = HashSet::new();\n\n    // Search to collect all dependencies of the root unit.\n    queue.push((root, root, false));\n    while let Some((node, parent, is_build_dep)) = queue.pop() {\n        let dependencies = sbom_graph.entry(parent).or_default();\n        for dep in build_runner.unit_deps(node) {\n            let dep = &dep.unit;\n            let (next_parent, next_is_build_dep) = if dep.mode == CompileMode::RunCustomBuild {\n                // Nodes in the SBOM graph for building/running build scripts are moved on to their parent as build dependencies.\n                (parent, true)\n            } else {\n                // Proc-macros and build scripts are marked as build dependencies.\n                let dep_type = match is_build_dep || dep.target.proc_macro() {\n                    false => SbomDependencyType::Normal,\n                    true => SbomDependencyType::Build,\n                };\n                dependencies.insert((dep, dep_type));\n                tracing::trace!(\n                    \"adding sbom edge {} -> {} ({:?})\",\n                    parent.pkg.package_id(),\n                    dep.pkg.package_id(),\n                    dep_type,\n                );\n                (dep, false)\n            };\n            if visited.insert(dep) {\n                queue.push((dep, next_parent, next_is_build_dep));\n            }\n        }\n    }\n    sbom_graph\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/rustdoc.rs",
    "content": "//! Utilities for building with rustdoc.\n\nuse crate::core::compiler::build_runner::BuildRunner;\nuse crate::core::compiler::unit::Unit;\nuse crate::core::compiler::{BuildContext, CompileKind};\nuse crate::sources::CRATES_IO_REGISTRY;\nuse crate::util::errors::{CargoResult, internal};\nuse cargo_util::ProcessBuilder;\nuse std::collections::HashMap;\nuse std::collections::HashSet;\nuse std::fmt;\nuse std::hash;\nuse url::Url;\n\nconst DOCS_RS_URL: &'static str = \"https://docs.rs/\";\n\n/// Mode used for `std`. This is for unstable feature [`-Zrustdoc-map`][1].\n///\n/// [1]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#rustdoc-map\n#[derive(Debug, Hash)]\npub enum RustdocExternMode {\n    /// Use a local `file://` URL.\n    Local,\n    /// Use a remote URL to <https://doc.rust-lang.org/> (default).\n    Remote,\n    /// An arbitrary URL.\n    Url(String),\n}\n\nimpl From<String> for RustdocExternMode {\n    fn from(s: String) -> RustdocExternMode {\n        match s.as_ref() {\n            \"local\" => RustdocExternMode::Local,\n            \"remote\" => RustdocExternMode::Remote,\n            _ => RustdocExternMode::Url(s),\n        }\n    }\n}\n\nimpl fmt::Display for RustdocExternMode {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            RustdocExternMode::Local => \"local\".fmt(f),\n            RustdocExternMode::Remote => \"remote\".fmt(f),\n            RustdocExternMode::Url(s) => s.fmt(f),\n        }\n    }\n}\n\nimpl<'de> serde::de::Deserialize<'de> for RustdocExternMode {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::de::Deserializer<'de>,\n    {\n        let s = String::deserialize(deserializer)?;\n        Ok(s.into())\n    }\n}\n\n/// A map of registry names to URLs where documentations are hosted.\n/// This is for unstable feature [`-Zrustdoc-map`][1].\n///\n/// [1]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#rustdoc-map\n#[derive(serde::Deserialize, Debug)]\n#[serde(default)]\npub struct RustdocExternMap {\n    #[serde(deserialize_with = \"default_crates_io_to_docs_rs\")]\n    /// * Key is the registry name in the configuration `[registries.<name>]`.\n    /// * Value is the URL where the documentation is hosted.\n    registries: HashMap<String, String>,\n    std: Option<RustdocExternMode>,\n}\n\nimpl Default for RustdocExternMap {\n    fn default() -> Self {\n        Self {\n            registries: HashMap::from([(CRATES_IO_REGISTRY.into(), DOCS_RS_URL.into())]),\n            std: None,\n        }\n    }\n}\n\nfn default_crates_io_to_docs_rs<'de, D: serde::Deserializer<'de>>(\n    de: D,\n) -> Result<HashMap<String, String>, D::Error> {\n    use serde::Deserialize;\n    let mut registries = HashMap::deserialize(de)?;\n    if !registries.contains_key(CRATES_IO_REGISTRY) {\n        registries.insert(CRATES_IO_REGISTRY.into(), DOCS_RS_URL.into());\n    }\n    Ok(registries)\n}\n\nimpl hash::Hash for RustdocExternMap {\n    fn hash<H: hash::Hasher>(&self, into: &mut H) {\n        self.std.hash(into);\n        for (key, value) in &self.registries {\n            key.hash(into);\n            value.hash(into);\n        }\n    }\n}\n\n/// Recursively generate html root url for all units and their children.\n///\n/// This is needed because in case there is a reexport of foreign reexport, you\n/// need to have information about grand-children deps level (deps of your deps).\nfn build_all_urls(\n    build_runner: &BuildRunner<'_, '_>,\n    rustdoc: &mut ProcessBuilder,\n    unit: &Unit,\n    name2url: &HashMap<&String, Url>,\n    map: &RustdocExternMap,\n    unstable_opts: &mut bool,\n    seen: &mut HashSet<Unit>,\n) {\n    for dep in build_runner.unit_deps(unit) {\n        if !seen.insert(dep.unit.clone()) {\n            continue;\n        }\n        if !dep.unit.target.is_linkable() || dep.unit.mode.is_doc() {\n            continue;\n        }\n        for (registry, location) in &map.registries {\n            let sid = dep.unit.pkg.package_id().source_id();\n            let matches_registry = || -> bool {\n                if !sid.is_registry() {\n                    return false;\n                }\n                if sid.is_crates_io() {\n                    return registry == CRATES_IO_REGISTRY;\n                }\n                if let Some(index_url) = name2url.get(registry) {\n                    return index_url == sid.url();\n                }\n                false\n            };\n            if matches_registry() {\n                let mut url = location.clone();\n                if !url.contains(\"{pkg_name}\") && !url.contains(\"{version}\") {\n                    if !url.ends_with('/') {\n                        url.push('/');\n                    }\n                    url.push_str(\"{pkg_name}/{version}/\");\n                }\n                let url = url\n                    .replace(\"{pkg_name}\", &dep.unit.pkg.name())\n                    .replace(\"{version}\", &dep.unit.pkg.version().to_string());\n                rustdoc.arg(\"--extern-html-root-url\");\n                rustdoc.arg(format!(\"{}={}\", dep.unit.target.crate_name(), url));\n                *unstable_opts = true;\n            }\n        }\n        build_all_urls(\n            build_runner,\n            rustdoc,\n            &dep.unit,\n            name2url,\n            map,\n            unstable_opts,\n            seen,\n        );\n    }\n}\n\n/// Adds unstable flag [`--extern-html-root-url`][1] to the given `rustdoc`\n/// invocation. This is for unstable feature [`-Zrustdoc-map`][2].\n///\n/// [1]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#--extern-html-root-url-control-how-rustdoc-links-to-non-local-crates\n/// [2]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#rustdoc-map\npub fn add_root_urls(\n    build_runner: &BuildRunner<'_, '_>,\n    unit: &Unit,\n    rustdoc: &mut ProcessBuilder,\n) -> CargoResult<()> {\n    let gctx = build_runner.bcx.gctx;\n    if !gctx.cli_unstable().rustdoc_map {\n        tracing::debug!(\"`doc.extern-map` ignored, requires -Zrustdoc-map flag\");\n        return Ok(());\n    }\n    let map = gctx.doc_extern_map()?;\n    let mut unstable_opts = false;\n    // Collect mapping of registry name -> index url.\n    let name2url: HashMap<&String, Url> = map\n        .registries\n        .keys()\n        .filter_map(|name| {\n            if let Ok(index_url) = gctx.get_registry_index(name) {\n                Some((name, index_url))\n            } else {\n                tracing::warn!(\n                    \"`doc.extern-map.{}` specifies a registry that is not defined\",\n                    name\n                );\n                None\n            }\n        })\n        .collect();\n    build_all_urls(\n        build_runner,\n        rustdoc,\n        unit,\n        &name2url,\n        map,\n        &mut unstable_opts,\n        &mut HashSet::new(),\n    );\n    let std_url = match &map.std {\n        None | Some(RustdocExternMode::Remote) => None,\n        Some(RustdocExternMode::Local) => {\n            let sysroot = &build_runner.bcx.target_data.info(CompileKind::Host).sysroot;\n            let html_root = sysroot.join(\"share\").join(\"doc\").join(\"rust\").join(\"html\");\n            if html_root.exists() {\n                let url = Url::from_file_path(&html_root).map_err(|()| {\n                    internal(format!(\n                        \"`{}` failed to convert to URL\",\n                        html_root.display()\n                    ))\n                })?;\n                Some(url.to_string())\n            } else {\n                tracing::warn!(\n                    \"`doc.extern-map.std` is \\\"local\\\", but local docs don't appear to exist at {}\",\n                    html_root.display()\n                );\n                None\n            }\n        }\n        Some(RustdocExternMode::Url(s)) => Some(s.to_string()),\n    };\n    if let Some(url) = std_url {\n        for name in &[\"std\", \"core\", \"alloc\", \"proc_macro\"] {\n            rustdoc.arg(\"--extern-html-root-url\");\n            rustdoc.arg(format!(\"{}={}\", name, url));\n            unstable_opts = true;\n        }\n    }\n\n    if unstable_opts {\n        rustdoc.arg(\"-Zunstable-options\");\n    }\n    Ok(())\n}\n\n/// Adds unstable flag [`--output-format`][1] to the given `rustdoc`\n/// invocation. This is for unstable feature `-Zunstable-features`.\n///\n/// [1]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html?highlight=output-format#-w--output-format-output-format\npub fn add_output_format(\n    build_runner: &BuildRunner<'_, '_>,\n    rustdoc: &mut ProcessBuilder,\n) -> CargoResult<()> {\n    let gctx = build_runner.bcx.gctx;\n    if !gctx.cli_unstable().unstable_options {\n        tracing::debug!(\"`unstable-options` is ignored, required -Zunstable-options flag\");\n        return Ok(());\n    }\n\n    if build_runner.bcx.build_config.intent.wants_doc_json_output() {\n        rustdoc.arg(\"-Zunstable-options\");\n        rustdoc.arg(\"--output-format=json\");\n    }\n\n    Ok(())\n}\n\n/// Indicates whether a target should have examples scraped from it by rustdoc.\n/// Configured within Cargo.toml and only for unstable feature\n/// [`-Zrustdoc-scrape-examples`][1].\n///\n/// [1]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#scrape-examples\n#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Copy)]\npub enum RustdocScrapeExamples {\n    Enabled,\n    Disabled,\n    Unset,\n}\n\nimpl RustdocScrapeExamples {\n    pub fn is_enabled(&self) -> bool {\n        matches!(self, RustdocScrapeExamples::Enabled)\n    }\n\n    pub fn is_unset(&self) -> bool {\n        matches!(self, RustdocScrapeExamples::Unset)\n    }\n}\n\nimpl BuildContext<'_, '_> {\n    /// Returns the set of [`Docscrape`] units that have a direct dependency on `unit`.\n    ///\n    /// [`RunCustomBuild`] units are excluded because we allow failures\n    /// from type checks but not build script executions.\n    /// A plain old `cargo doc` would just die if a build script execution fails,\n    /// there is no reason for `-Zrustdoc-scrape-examples` to keep going.\n    ///\n    /// [`Docscrape`]: crate::core::compiler::CompileMode::Docscrape\n    /// [`RunCustomBuild`]: crate::core::compiler::CompileMode::Docscrape\n    pub fn scrape_units_have_dep_on<'a>(&'a self, unit: &'a Unit) -> Vec<&'a Unit> {\n        self.scrape_units\n            .iter()\n            .filter(|scrape_unit| {\n                self.unit_graph[scrape_unit]\n                    .iter()\n                    .any(|dep| &dep.unit == unit && !dep.unit.mode.is_run_custom_build())\n            })\n            .collect()\n    }\n\n    /// Returns true if this unit is needed for doing doc-scraping and is also\n    /// allowed to fail without killing the build.\n    pub fn unit_can_fail_for_docscraping(&self, unit: &Unit) -> bool {\n        // If the unit is not a Docscrape unit, e.g. a Lib target that is\n        // checked to scrape an Example target, then we need to get the doc-scrape-examples\n        // configuration for the reverse-dependent Example target.\n        let for_scrape_units = if unit.mode.is_doc_scrape() {\n            vec![unit]\n        } else {\n            self.scrape_units_have_dep_on(unit)\n        };\n\n        if for_scrape_units.is_empty() {\n            false\n        } else {\n            // All Docscrape units must have doc-scrape-examples unset. If any are true,\n            // then the unit is not allowed to fail.\n            for_scrape_units\n                .iter()\n                .all(|unit| unit.target.doc_scrape_examples().is_unset())\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/standard_lib.rs",
    "content": "//! Code for building the standard library.\n\nuse crate::core::compiler::UnitInterner;\nuse crate::core::compiler::unit_dependencies::IsArtifact;\nuse crate::core::compiler::{CompileKind, CompileMode, RustcTargetData, Unit};\nuse crate::core::profiles::{Profiles, UnitFor};\nuse crate::core::resolver::HasDevUnits;\nuse crate::core::resolver::features::{CliFeatures, FeaturesFor, ResolvedFeatures};\nuse crate::core::{PackageId, PackageSet, Resolve, Workspace};\nuse crate::ops::{self, Packages};\nuse crate::util::errors::CargoResult;\n\nuse std::collections::{HashMap, HashSet};\nuse std::path::PathBuf;\n\nuse super::BuildConfig;\n\nfn std_crates<'a>(crates: &'a [String], default: &'static str, units: &[Unit]) -> HashSet<&'a str> {\n    let mut crates = HashSet::from_iter(crates.iter().map(|s| s.as_str()));\n    // This is a temporary hack until there is a more principled way to\n    // declare dependencies in Cargo.toml.\n    if crates.is_empty() {\n        crates.insert(default);\n    }\n    if crates.contains(\"std\") {\n        crates.insert(\"core\");\n        crates.insert(\"alloc\");\n        crates.insert(\"proc_macro\");\n        crates.insert(\"panic_unwind\");\n        crates.insert(\"compiler_builtins\");\n        // Only build libtest if it looks like it is needed (libtest depends on libstd)\n        // If we know what units we're building, we can filter for libtest depending on the jobs.\n        if units\n            .iter()\n            .any(|unit| unit.mode.is_rustc_test() && unit.target.harness())\n        {\n            crates.insert(\"test\");\n        }\n    } else if crates.contains(\"core\") {\n        crates.insert(\"compiler_builtins\");\n    }\n\n    crates\n}\n\n/// Resolve the standard library dependencies.\n///\n/// * `crates` is the arg value from `-Zbuild-std`.\npub fn resolve_std<'gctx>(\n    ws: &Workspace<'gctx>,\n    target_data: &mut RustcTargetData<'gctx>,\n    build_config: &BuildConfig,\n    crates: &[String],\n    kinds: &[CompileKind],\n) -> CargoResult<(PackageSet<'gctx>, Resolve, ResolvedFeatures)> {\n    let src_path = detect_sysroot_src_path(target_data)?;\n    let std_ws_manifest_path = src_path.join(\"Cargo.toml\");\n    let gctx = ws.gctx();\n    // TODO: Consider doing something to enforce --locked? Or to prevent the\n    // lock file from being written, such as setting ephemeral.\n    let mut std_ws = Workspace::new(&std_ws_manifest_path, gctx)?;\n    // Don't require optional dependencies in this workspace, aka std's own\n    // `[dev-dependencies]`. No need for us to generate a `Resolve` which has\n    // those included because we'll never use them anyway.\n    std_ws.set_require_optional_deps(false);\n    let specs = {\n        // If there is anything looks like needing std, resolve with it.\n        // If not, we assume only `core` maye be needed, as `core the most fundamental crate.\n        //\n        // This may need a UI overhaul if `build-std` wants to fully support multi-targets.\n        let maybe_std = kinds\n            .iter()\n            .any(|kind| target_data.info(*kind).maybe_support_std());\n        let mut crates = std_crates(crates, if maybe_std { \"std\" } else { \"core\" }, &[]);\n        // `sysroot` is not in the default set because it is optional, but it needs\n        // to be part of the resolve in case we do need it or `libtest`.\n        crates.insert(\"sysroot\");\n        let specs = Packages::Packages(crates.into_iter().map(Into::into).collect());\n        specs.to_package_id_specs(&std_ws)?\n    };\n    let features = match &gctx.cli_unstable().build_std_features {\n        Some(list) => list.clone(),\n        None => vec![\n            \"panic-unwind\".to_string(),\n            \"backtrace\".to_string(),\n            \"default\".to_string(),\n        ],\n    };\n    let cli_features = CliFeatures::from_command_line(\n        &features, /*all_features*/ false, /*uses_default_features*/ false,\n    )?;\n    let dry_run = false;\n    let mut resolve = ops::resolve_ws_with_opts(\n        &std_ws,\n        target_data,\n        &build_config.requested_kinds,\n        &cli_features,\n        &specs,\n        HasDevUnits::No,\n        crate::core::resolver::features::ForceAllTargets::No,\n        dry_run,\n    )?;\n    debug_assert_eq!(resolve.specs_and_features.len(), 1);\n    Ok((\n        resolve.pkg_set,\n        resolve.targeted_resolve,\n        resolve\n            .specs_and_features\n            .pop()\n            .expect(\"resolve should have a single spec with resolved features\")\n            .resolved_features,\n    ))\n}\n\n/// Generates a map of root units for the standard library for each kind requested.\n///\n/// * `crates` is the arg value from `-Zbuild-std`.\n/// * `units` is the root units of the build.\npub fn generate_std_roots(\n    crates: &[String],\n    units: &[Unit],\n    std_resolve: &Resolve,\n    std_features: &ResolvedFeatures,\n    kinds: &[CompileKind],\n    package_set: &PackageSet<'_>,\n    interner: &UnitInterner,\n    profiles: &Profiles,\n    target_data: &RustcTargetData<'_>,\n) -> CargoResult<HashMap<CompileKind, Vec<Unit>>> {\n    // Generate a map of Units for each kind requested.\n    let mut ret = HashMap::new();\n    let (maybe_std, maybe_core): (Vec<&CompileKind>, Vec<_>) = kinds\n        .iter()\n        .partition(|kind| target_data.info(**kind).maybe_support_std());\n    for (default_crate, kinds) in [(\"core\", maybe_core), (\"std\", maybe_std)] {\n        if kinds.is_empty() {\n            continue;\n        }\n        generate_roots(\n            &mut ret,\n            default_crate,\n            crates,\n            units,\n            std_resolve,\n            std_features,\n            &kinds,\n            package_set,\n            interner,\n            profiles,\n            target_data,\n        )?;\n    }\n\n    Ok(ret)\n}\n\nfn generate_roots(\n    ret: &mut HashMap<CompileKind, Vec<Unit>>,\n    default: &'static str,\n    crates: &[String],\n    units: &[Unit],\n    std_resolve: &Resolve,\n    std_features: &ResolvedFeatures,\n    kinds: &[&CompileKind],\n    package_set: &PackageSet<'_>,\n    interner: &UnitInterner,\n    profiles: &Profiles,\n    target_data: &RustcTargetData<'_>,\n) -> CargoResult<()> {\n    let std_ids = std_crates(crates, default, units)\n        .iter()\n        .map(|crate_name| std_resolve.query(crate_name))\n        .collect::<CargoResult<Vec<PackageId>>>()?;\n    let std_pkgs = package_set.get_many(std_ids)?;\n\n    for pkg in std_pkgs {\n        let lib = pkg\n            .targets()\n            .iter()\n            .find(|t| t.is_lib())\n            .expect(\"std has a lib\");\n        // I don't think we need to bother with Check here, the difference\n        // in time is minimal, and the difference in caching is\n        // significant.\n        let mode = CompileMode::Build;\n        let features = std_features.activated_features(pkg.package_id(), FeaturesFor::NormalOrDev);\n        for kind in kinds {\n            let kind = **kind;\n            let list = ret.entry(kind).or_insert_with(Vec::new);\n            let unit_for = UnitFor::new_normal(kind);\n            let profile = profiles.get_profile(\n                pkg.package_id(),\n                /*is_member*/ false,\n                /*is_local*/ false,\n                unit_for,\n                kind,\n            );\n            list.push(interner.intern(\n                pkg,\n                lib,\n                profile,\n                kind,\n                mode,\n                features.clone(),\n                target_data.info(kind).rustflags.clone(),\n                target_data.info(kind).rustdocflags.clone(),\n                target_data.target_config(kind).links_overrides.clone(),\n                /*is_std*/ true,\n                /*dep_hash*/ 0,\n                IsArtifact::No,\n                None,\n                false,\n            ));\n        }\n    }\n    Ok(())\n}\n\nfn detect_sysroot_src_path(target_data: &RustcTargetData<'_>) -> CargoResult<PathBuf> {\n    if let Some(s) = target_data.gctx.get_env_os(\"__CARGO_TESTS_ONLY_SRC_ROOT\") {\n        return Ok(s.into());\n    }\n\n    // NOTE: This is temporary until we figure out how to acquire the source.\n    let src_path = target_data\n        .info(CompileKind::Host)\n        .sysroot\n        .join(\"lib\")\n        .join(\"rustlib\")\n        .join(\"src\")\n        .join(\"rust\")\n        .join(\"library\");\n    let lock = src_path.join(\"Cargo.lock\");\n    if !lock.exists() {\n        let msg = format!(\n            \"{:?} does not exist, unable to build with the standard \\\n             library, try:\\n        rustup component add rust-src\",\n            lock\n        );\n        match target_data.gctx.get_env(\"RUSTUP_TOOLCHAIN\") {\n            Ok(rustup_toolchain) => {\n                anyhow::bail!(\"{} --toolchain {}\", msg, rustup_toolchain);\n            }\n            Err(_) => {\n                anyhow::bail!(msg);\n            }\n        }\n    }\n    Ok(src_path)\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/timings/mod.rs",
    "content": "//! Timing tracking.\n//!\n//! This module implements some simple tracking information for timing of how\n//! long it takes for different units to compile.\n\npub mod report;\n\nuse super::CompileMode;\nuse super::Unit;\nuse super::UnitIndex;\nuse crate::core::compiler::BuildContext;\nuse crate::core::compiler::BuildRunner;\nuse crate::core::compiler::job_queue::JobId;\nuse crate::ops::cargo_report::timings::prepare_context;\nuse crate::util::cpu::State;\nuse crate::util::log_message::LogMessage;\nuse crate::util::style;\nuse crate::util::{CargoResult, GlobalContext};\n\nuse cargo_util::paths;\nuse std::collections::HashMap;\nuse std::io::BufWriter;\nuse std::time::{Duration, Instant};\n\n/// Tracking information for the entire build.\n///\n/// Methods on this structure are generally called from the main thread of a\n/// running [`JobQueue`] instance (`DrainState` in specific) when the queue\n/// receives messages from spawned off threads.\n///\n/// [`JobQueue`]: super::JobQueue\npub struct Timings<'gctx> {\n    gctx: &'gctx GlobalContext,\n    /// Whether or not timings should be captured.\n    enabled: bool,\n    /// When Cargo started.\n    start: Instant,\n    /// A summary of the root units.\n    ///\n    /// A map from unit to index.\n    unit_to_index: HashMap<Unit, UnitIndex>,\n    /// Units that are in the process of being built.\n    /// When they finished, they are moved to `unit_times`.\n    active: HashMap<JobId, Unit>,\n    /// Last recorded state of the system's CPUs and when it happened\n    last_cpu_state: Option<State>,\n    last_cpu_recording: Instant,\n    /// Recorded CPU states, stored as tuples. First element is when the\n    /// recording was taken and second element is percentage usage of the\n    /// system.\n    cpu_usage: Vec<(f64, f64)>,\n}\n\n/// Section of compilation (e.g. frontend, backend, linking).\n#[derive(Copy, Clone, serde::Serialize)]\npub struct CompilationSection {\n    /// Start of the section, as an offset in seconds from `UnitTime::start`.\n    pub start: f64,\n    /// End of the section, as an offset in seconds from `UnitTime::start`.\n    pub end: Option<f64>,\n}\n\n/// Data for a single compilation unit, prepared for serialization to JSON.\n///\n/// This is used by the HTML report's JavaScript to render the pipeline graph.\n#[derive(serde::Serialize)]\npub struct UnitData {\n    pub i: UnitIndex,\n    pub name: String,\n    pub version: String,\n    pub mode: String,\n    pub target: String,\n    pub features: Vec<String>,\n    pub start: f64,\n    pub duration: f64,\n    pub unblocked_units: Vec<UnitIndex>,\n    pub unblocked_rmeta_units: Vec<UnitIndex>,\n    pub sections: Option<Vec<(report::SectionName, report::SectionData)>>,\n}\n\nimpl<'gctx> Timings<'gctx> {\n    pub fn new(bcx: &BuildContext<'_, 'gctx>) -> Timings<'gctx> {\n        let start = bcx.gctx.creation_time();\n        let enabled = bcx.logger.is_some();\n\n        if !enabled {\n            return Timings {\n                gctx: bcx.gctx,\n                enabled,\n                start,\n                unit_to_index: HashMap::new(),\n                active: HashMap::new(),\n                last_cpu_state: None,\n                last_cpu_recording: Instant::now(),\n                cpu_usage: Vec::new(),\n            };\n        }\n\n        let last_cpu_state = match State::current() {\n            Ok(state) => Some(state),\n            Err(e) => {\n                tracing::info!(\"failed to get CPU state, CPU tracking disabled: {:?}\", e);\n                None\n            }\n        };\n\n        Timings {\n            gctx: bcx.gctx,\n            enabled,\n            start,\n            unit_to_index: bcx.unit_to_index.clone(),\n            active: HashMap::new(),\n            last_cpu_state,\n            last_cpu_recording: Instant::now(),\n            cpu_usage: Vec::new(),\n        }\n    }\n\n    /// Mark that a unit has started running.\n    pub fn unit_start(&mut self, build_runner: &BuildRunner<'_, '_>, id: JobId, unit: Unit) {\n        let Some(logger) = build_runner.bcx.logger else {\n            return;\n        };\n        let mut target = if unit.target.is_lib()\n            && matches!(unit.mode, CompileMode::Build | CompileMode::Check { .. })\n        {\n            // Special case for brevity, since most dependencies hit this path.\n            \"\".to_string()\n        } else {\n            format!(\" {}\", unit.target.description_named())\n        };\n        match unit.mode {\n            CompileMode::Test => target.push_str(\" (test)\"),\n            CompileMode::Build => {}\n            CompileMode::Check { test: true } => target.push_str(\" (check-test)\"),\n            CompileMode::Check { test: false } => target.push_str(\" (check)\"),\n            CompileMode::Doc { .. } => target.push_str(\" (doc)\"),\n            CompileMode::Doctest => target.push_str(\" (doc test)\"),\n            CompileMode::Docscrape => target.push_str(\" (doc scrape)\"),\n            CompileMode::RunCustomBuild => target.push_str(\" (run)\"),\n        }\n        let start = self.start.elapsed().as_secs_f64();\n        logger.log(LogMessage::UnitStarted {\n            index: self.unit_to_index[&unit],\n            elapsed: start,\n        });\n\n        assert!(self.active.insert(id, unit).is_none());\n    }\n\n    /// Mark that the `.rmeta` file as generated.\n    pub fn unit_rmeta_finished(\n        &mut self,\n        build_runner: &BuildRunner<'_, '_>,\n        id: JobId,\n        unblocked: Vec<&Unit>,\n    ) {\n        let Some(logger) = build_runner.bcx.logger else {\n            return;\n        };\n        // `id` may not always be active. \"fresh\" units unconditionally\n        // generate `Message::Finish`, but this active map only tracks dirty\n        // units.\n        let Some(unit) = self.active.get(&id) else {\n            return;\n        };\n        let elapsed = self.start.elapsed().as_secs_f64();\n\n        let unblocked = unblocked.iter().map(|u| self.unit_to_index[u]).collect();\n        logger.log(LogMessage::UnitRmetaFinished {\n            index: self.unit_to_index[unit],\n            elapsed,\n            unblocked,\n        });\n    }\n\n    /// Mark that a unit has finished running.\n    pub fn unit_finished(\n        &mut self,\n        build_runner: &BuildRunner<'_, '_>,\n        id: JobId,\n        unblocked: Vec<&Unit>,\n    ) {\n        let Some(logger) = build_runner.bcx.logger else {\n            return;\n        };\n        // See note above in `unit_rmeta_finished`, this may not always be active.\n        let Some(unit) = self.active.remove(&id) else {\n            return;\n        };\n        let elapsed = self.start.elapsed().as_secs_f64();\n\n        let unblocked = unblocked.iter().map(|u| self.unit_to_index[u]).collect();\n        logger.log(LogMessage::UnitFinished {\n            index: self.unit_to_index[&unit],\n            elapsed,\n            unblocked,\n        });\n    }\n\n    /// Handle the start/end of a compilation section.\n    pub fn unit_section_timing(\n        &mut self,\n        build_runner: &BuildRunner<'_, '_>,\n        id: JobId,\n        section_timing: &SectionTiming,\n    ) {\n        let Some(logger) = build_runner.bcx.logger else {\n            return;\n        };\n        let Some(unit) = self.active.get(&id) else {\n            return;\n        };\n        let elapsed = self.start.elapsed().as_secs_f64();\n\n        let index = self.unit_to_index[&unit];\n        let section = section_timing.name.clone();\n        logger.log(match section_timing.event {\n            SectionTimingEvent::Start => LogMessage::UnitSectionStarted {\n                index,\n                elapsed,\n                section,\n            },\n            SectionTimingEvent::End => LogMessage::UnitSectionFinished {\n                index,\n                elapsed,\n                section,\n            },\n        })\n    }\n\n    /// Take a sample of CPU usage\n    pub fn record_cpu(&mut self) {\n        if !self.enabled {\n            return;\n        }\n        let Some(prev) = &mut self.last_cpu_state else {\n            return;\n        };\n        // Don't take samples too frequently, even if requested.\n        let now = Instant::now();\n        if self.last_cpu_recording.elapsed() < Duration::from_millis(100) {\n            return;\n        }\n        let current = match State::current() {\n            Ok(s) => s,\n            Err(e) => {\n                tracing::info!(\"failed to get CPU state: {:?}\", e);\n                return;\n            }\n        };\n        let pct_idle = current.idle_since(prev);\n        *prev = current;\n        self.last_cpu_recording = now;\n        let dur = now.duration_since(self.start).as_secs_f64();\n        self.cpu_usage.push((dur, 100.0 - pct_idle));\n    }\n\n    /// Call this when all units are finished.\n    pub fn finished(\n        &mut self,\n        build_runner: &BuildRunner<'_, '_>,\n        error: &Option<anyhow::Error>,\n    ) -> CargoResult<()> {\n        if let Some(logger) = build_runner.bcx.logger\n            && let Some(logs) = logger.get_logs()\n        {\n            let timings_path = build_runner\n                .files()\n                .timings_dir()\n                .expect(\"artifact-dir was not locked\");\n            paths::create_dir_all(&timings_path)?;\n            let run_id = logger.run_id();\n            let filename = timings_path.join(format!(\"cargo-timing-{run_id}.html\"));\n            let mut f = BufWriter::new(paths::create(&filename)?);\n\n            let mut ctx = prepare_context(logs.into_iter(), run_id)?;\n            ctx.error = error;\n            ctx.cpu_usage = &self.cpu_usage;\n            report::write_html(ctx, &mut f)?;\n\n            let unstamped_filename = timings_path.join(\"cargo-timing.html\");\n            paths::link_or_copy(&filename, &unstamped_filename)?;\n\n            let mut shell = self.gctx.shell();\n            let timing_path = std::env::current_dir().unwrap_or_default().join(&filename);\n            let link = shell.err_file_hyperlink(&timing_path);\n            let msg = format!(\"report saved to {link}{}{link:#}\", timing_path.display(),);\n            shell.status_with_color(\"Timing\", msg, &style::NOTE)?;\n        }\n        Ok(())\n    }\n}\n\n/// Start or end of a section timing.\n#[derive(serde::Deserialize, Debug)]\n#[serde(rename_all = \"kebab-case\")]\npub enum SectionTimingEvent {\n    Start,\n    End,\n}\n\n/// Represents a certain section (phase) of rustc compilation.\n/// It is emitted by rustc when the `--json=timings` flag is used.\n#[derive(serde::Deserialize, Debug)]\npub struct SectionTiming {\n    pub name: String,\n    pub event: SectionTimingEvent,\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/timings/report.rs",
    "content": "//! Render HTML report from timing tracking data.\n\nuse std::borrow::Cow;\nuse std::collections::HashMap;\nuse std::collections::HashSet;\nuse std::io::Write;\n\nuse indexmap::IndexMap;\nuse itertools::Itertools as _;\n\nuse crate::CargoResult;\nuse crate::core::compiler::UnitIndex;\n\nuse super::CompilationSection;\nuse super::UnitData;\n\n/// Name of an individual compilation section.\n#[derive(Clone, Hash, Eq, PartialEq)]\npub enum SectionName {\n    Frontend,\n    Codegen,\n    Named(String),\n    Other,\n}\n\nimpl SectionName {\n    /// Lower case name.\n    fn name(&self) -> Cow<'static, str> {\n        match self {\n            SectionName::Frontend => \"frontend\".into(),\n            SectionName::Codegen => \"codegen\".into(),\n            SectionName::Named(n) => n.to_lowercase().into(),\n            SectionName::Other => \"other\".into(),\n        }\n    }\n\n    fn capitalized_name(&self) -> String {\n        // Make the first \"letter\" uppercase. We could probably just assume ASCII here, but this\n        // should be Unicode compatible.\n        fn capitalize(s: &str) -> String {\n            let first_char = s\n                .chars()\n                .next()\n                .map(|c| c.to_uppercase().to_string())\n                .unwrap_or_default();\n            format!(\"{first_char}{}\", s.chars().skip(1).collect::<String>())\n        }\n        capitalize(&self.name())\n    }\n}\n\nimpl serde::ser::Serialize for SectionName {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: serde::Serializer,\n    {\n        self.name().serialize(serializer)\n    }\n}\n\n/// Postprocessed section data that has both start and an end.\n#[derive(Copy, Clone, serde::Serialize)]\npub struct SectionData {\n    /// Start (relative to the start of the unit)\n    pub start: f64,\n    /// End (relative to the start of the unit)\n    pub end: f64,\n}\n\nimpl SectionData {\n    fn duration(&self) -> f64 {\n        (self.end - self.start).max(0.0)\n    }\n}\n\n/// Concurrency tracking information.\n#[derive(serde::Serialize)]\npub struct Concurrency {\n    /// Time as an offset in seconds from `Timings::start`.\n    t: f64,\n    /// Number of units currently running.\n    active: usize,\n    /// Number of units that could run, but are waiting for a jobserver token.\n    waiting: usize,\n    /// Number of units that are not yet ready, because they are waiting for\n    /// dependencies to finish.\n    inactive: usize,\n}\n\npub struct RenderContext<'a> {\n    /// A rendered string of when compilation started.\n    pub start_str: String,\n    /// A summary of the root units.\n    ///\n    /// Tuples of `(package_description, target_descriptions)`.\n    pub root_units: Vec<(String, Vec<String>)>,\n    /// The build profile.\n    pub profile: String,\n    /// Total number of fresh units.\n    pub total_fresh: u32,\n    /// Total number of dirty units.\n    pub total_dirty: u32,\n    /// Time tracking for each individual unit.\n    pub unit_data: Vec<UnitData>,\n    /// Concurrency-tracking information. This is periodically updated while\n    /// compilation progresses.\n    pub concurrency: Vec<Concurrency>,\n    /// Recorded CPU states, stored as tuples. First element is when the\n    /// recording was taken and second element is percentage usage of the\n    /// system.\n    pub cpu_usage: &'a [(f64, f64)],\n    /// Compiler version info, i.e., `rustc 1.92.0-beta.2 (0a411606e 2025-10-31)`.\n    pub rustc_version: String,\n    /// The host triple (arch-platform-OS).\n    pub host: String,\n    /// The requested target platforms of compilation for this build.\n    pub requested_targets: Vec<String>,\n    /// The number of jobs specified for this build.\n    pub jobs: u32,\n    /// Available parallelism of the compilation environment.\n    pub num_cpus: Option<u64>,\n    /// Fatal error during the build.\n    pub error: &'a Option<anyhow::Error>,\n}\n\n/// Writes an HTML report.\npub fn write_html(ctx: RenderContext<'_>, f: &mut impl Write) -> CargoResult<()> {\n    // The last concurrency record should equal to the last unit finished time.\n    let duration = ctx.concurrency.last().map(|c| c.t).unwrap_or(0.0);\n    let roots: Vec<&str> = ctx\n        .root_units\n        .iter()\n        .map(|(name, _targets)| name.as_str())\n        .collect();\n    f.write_all(HTML_TMPL.replace(\"{ROOTS}\", &roots.join(\", \")).as_bytes())?;\n    write_summary_table(&ctx, f, duration)?;\n    f.write_all(HTML_CANVAS.as_bytes())?;\n    write_unit_table(&ctx, f)?;\n    // It helps with pixel alignment to use whole numbers.\n    writeln!(\n        f,\n        \"<script>\\n\\\n         DURATION = {};\",\n        f64::ceil(duration) as u32\n    )?;\n    write_js_data(&ctx, f)?;\n    write!(\n        f,\n        \"{}\\n\\\n         </script>\\n\\\n         </body>\\n\\\n         </html>\\n\\\n         \",\n        include_str!(\"timings.js\")\n    )?;\n\n    Ok(())\n}\n\n/// Render the summary table.\nfn write_summary_table(\n    ctx: &RenderContext<'_>,\n    f: &mut impl Write,\n    duration: f64,\n) -> CargoResult<()> {\n    let targets = ctx\n        .root_units\n        .iter()\n        .map(|(name, targets)| format!(\"{} ({})\", name, targets.join(\", \")))\n        .collect::<Vec<_>>()\n        .join(\"<br>\");\n\n    let total_units = ctx.total_fresh + ctx.total_dirty;\n\n    let time_human = if duration > 60.0 {\n        format!(\" ({}m {:.1}s)\", duration as u32 / 60, duration % 60.0)\n    } else {\n        \"\".to_string()\n    };\n    let total_time = format!(\"{:.1}s{}\", duration, time_human);\n\n    let max_concurrency = ctx.concurrency.iter().map(|c| c.active).max().unwrap_or(0);\n    let num_cpus = ctx\n        .num_cpus\n        .map(|x| x.to_string())\n        .unwrap_or_else(|| \"n/a\".into());\n\n    let requested_targets = ctx.requested_targets.join(\", \");\n\n    let error_msg = match ctx.error {\n        Some(e) => format!(r#\"<tr><td class=\"error-text\">Error:</td><td>{e}</td></tr>\"#),\n        None => \"\".to_string(),\n    };\n\n    let RenderContext {\n        start_str,\n        profile,\n        total_fresh,\n        total_dirty,\n        rustc_version,\n        host,\n        jobs,\n        ..\n    } = &ctx;\n\n    write!(\n        f,\n        r#\"\n<table class=\"my-table summary-table\">\n<tr>\n<td>Targets:</td><td>{targets}</td>\n</tr>\n<tr>\n<td>Profile:</td><td>{profile}</td>\n</tr>\n<tr>\n<td>Fresh units:</td><td>{total_fresh}</td>\n</tr>\n<tr>\n<td>Dirty units:</td><td>{total_dirty}</td>\n</tr>\n<tr>\n<td>Total units:</td><td>{total_units}</td>\n</tr>\n<tr>\n<td>Max concurrency:</td><td>{max_concurrency} (jobs={jobs} ncpu={num_cpus})</td>\n</tr>\n<tr>\n<td>Build start:</td><td>{start_str}</td>\n</tr>\n<tr>\n<td>Total time:</td><td>{total_time}</td>\n</tr>\n<tr>\n<td>rustc:</td><td>{rustc_version}<br>Host: {host}<br>Target: {requested_targets}</td>\n</tr>\n{error_msg}\n</table>\n\"#,\n    )?;\n    Ok(())\n}\n\n/// Write timing data in JavaScript. Primarily for `timings.js` to put data\n/// in a `<script>` HTML element to draw graphs.\nfn write_js_data(ctx: &RenderContext<'_>, f: &mut impl Write) -> CargoResult<()> {\n    writeln!(\n        f,\n        \"const UNIT_DATA = {};\",\n        serde_json::to_string_pretty(&ctx.unit_data)?\n    )?;\n    writeln!(\n        f,\n        \"const CONCURRENCY_DATA = {};\",\n        serde_json::to_string_pretty(&ctx.concurrency)?\n    )?;\n    writeln!(\n        f,\n        \"const CPU_USAGE = {};\",\n        serde_json::to_string_pretty(&ctx.cpu_usage)?\n    )?;\n    Ok(())\n}\n\n/// Render the table of all units.\nfn write_unit_table(ctx: &RenderContext<'_>, f: &mut impl Write) -> CargoResult<()> {\n    let mut units: Vec<_> = ctx.unit_data.iter().collect();\n    units.sort_unstable_by(|a, b| b.duration.partial_cmp(&a.duration).unwrap());\n\n    let aggregated: Vec<Option<_>> = units.iter().map(|u| u.sections.as_ref()).collect();\n\n    let headers: Vec<_> = aggregated\n        .iter()\n        .find_map(|s| s.as_ref())\n        .map(|sections| {\n            sections\n                .iter()\n                // We don't want to show the \"Other\" section in the table,\n                // as it is usually a tiny portion out of the entire unit.\n                .filter(|(name, _)| !matches!(name, SectionName::Other))\n                .map(|s| s.0.clone())\n                .collect()\n        })\n        .unwrap_or_default();\n\n    write!(\n        f,\n        r#\"\n<table class=\"my-table\">\n<thead>\n<tr>\n  <th></th>\n  <th>Unit</th>\n  <th>Total</th>\n  {headers}\n  <th>Features</th>\n</tr>\n</thead>\n<tbody>\n\"#,\n        headers = headers\n            .iter()\n            .map(|h| format!(\"<th>{}</th>\", h.capitalized_name()))\n            .join(\"\\n\")\n    )?;\n\n    for (i, (unit, aggregated_sections)) in units.iter().zip(aggregated).enumerate() {\n        let format_duration = |section: Option<&SectionData>| match section {\n            Some(section) => {\n                let duration = section.duration();\n                let pct = (duration / unit.duration) * 100.0;\n                format!(\"{duration:.1}s ({:.0}%)\", pct)\n            }\n            None => \"\".to_string(),\n        };\n\n        // This is a bit complex, as we assume the most general option - we can have an\n        // arbitrary set of headers, and an arbitrary set of sections per unit, so we always\n        // initiate the cells to be empty, and then try to find a corresponding column for which\n        // we might have data.\n        let mut cells: HashMap<_, _> = aggregated_sections\n            .iter()\n            .flat_map(|sections| sections.into_iter().map(|s| (&s.0, &s.1)))\n            .collect();\n\n        let cells = headers\n            .iter()\n            .map(|header| format!(\"<td>{}</td>\", format_duration(cells.remove(header))))\n            .join(\"\\n\");\n\n        let features = unit.features.join(\", \");\n        write!(\n            f,\n            r#\"\n<tr>\n<td>{}.</td>\n<td>{}{}</td>\n<td>{:.1}s</td>\n{cells}\n<td>{features}</td>\n</tr>\n\"#,\n            i + 1,\n            format_args!(\"{} v{}\", unit.name, unit.version),\n            unit.target,\n            unit.duration,\n        )?;\n    }\n    write!(f, \"</tbody>\\n</table>\\n\")?;\n    Ok(())\n}\n\n/// Derives concurrency information from unit timing data.\npub fn compute_concurrency(unit_data: &[UnitData]) -> Vec<Concurrency> {\n    if unit_data.is_empty() {\n        return Vec::new();\n    }\n\n    let unit_by_index: HashMap<_, _> = unit_data.iter().map(|u| (u.i, u)).collect();\n\n    enum UnblockedBy {\n        Rmeta(UnitIndex),\n        Full(UnitIndex),\n    }\n\n    // unit_id -> unit that unblocks it.\n    let mut unblocked_by: HashMap<_, _> = HashMap::new();\n    for unit in unit_data {\n        for id in unit.unblocked_rmeta_units.iter() {\n            assert!(\n                unblocked_by\n                    .insert(*id, UnblockedBy::Rmeta(unit.i))\n                    .is_none()\n            );\n        }\n\n        for id in unit.unblocked_units.iter() {\n            assert!(\n                unblocked_by\n                    .insert(*id, UnblockedBy::Full(unit.i))\n                    .is_none()\n            );\n        }\n    }\n\n    let ready_time = |unit: &UnitData| -> Option<f64> {\n        let dep = unblocked_by.get(&unit.i)?;\n        match dep {\n            UnblockedBy::Rmeta(id) => {\n                let dep = unit_by_index.get(id)?;\n                let duration = dep.sections.iter().flatten().find_map(|(name, section)| {\n                    matches!(name, SectionName::Frontend).then_some(section.end)\n                });\n\n                Some(dep.start + duration.unwrap_or(dep.duration))\n            }\n            UnblockedBy::Full(id) => {\n                let dep = unit_by_index.get(id)?;\n                Some(dep.start + dep.duration)\n            }\n        }\n    };\n\n    #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]\n    enum State {\n        Ready,\n        Start,\n        End,\n    }\n\n    let mut events: Vec<_> = unit_data\n        .iter()\n        .flat_map(|unit| {\n            // Adding rounded numbers may cause ready > start,\n            // so cap with unit.start here to be defensive.\n            let ready = ready_time(unit).unwrap_or(unit.start).min(unit.start);\n\n            [\n                (ready, State::Ready, unit.i),\n                (unit.start, State::Start, unit.i),\n                (unit.start + unit.duration, State::End, unit.i),\n            ]\n        })\n        .collect();\n\n    events.sort_by(|a, b| {\n        a.0.partial_cmp(&b.0)\n            .unwrap()\n            .then_with(|| a.1.cmp(&b.1))\n            .then_with(|| a.2.cmp(&b.2))\n    });\n\n    let mut concurrency: Vec<Concurrency> = Vec::new();\n    let mut inactive: HashSet<UnitIndex> = unit_data.iter().map(|unit| unit.i).collect();\n    let mut waiting: HashSet<UnitIndex> = HashSet::new();\n    let mut active: HashSet<UnitIndex> = HashSet::new();\n\n    for (t, state, unit_id) in events {\n        match state {\n            State::Ready => {\n                inactive.remove(&unit_id);\n                waiting.insert(unit_id);\n                active.remove(&unit_id);\n            }\n            State::Start => {\n                inactive.remove(&unit_id);\n                waiting.remove(&unit_id);\n                active.insert(unit_id);\n            }\n            State::End => {\n                inactive.remove(&unit_id);\n                waiting.remove(&unit_id);\n                active.remove(&unit_id);\n            }\n        }\n\n        let record = Concurrency {\n            t,\n            active: active.len(),\n            waiting: waiting.len(),\n            inactive: inactive.len(),\n        };\n\n        if let Some(last) = concurrency.last_mut()\n            && last.t == t\n        {\n            // We don't want to draw long vertical lines at the same timestamp,\n            // so we keep only the latest state.\n            *last = record;\n        } else {\n            concurrency.push(record);\n        }\n    }\n\n    concurrency\n}\n\n/// Aggregates section timing information from individual compilation sections.\n///\n/// We can have a bunch of situations here.\n///\n/// - `-Zsection-timings` is enabled, and we received some custom sections,\n///   in which case we use them to determine the headers.\n/// - We have at least one rmeta time, so we hard-code Frontend and Codegen headers.\n/// - We only have total durations, so we don't add any additional headers.\npub fn aggregate_sections(\n    sections: IndexMap<String, CompilationSection>,\n    end: f64,\n    rmeta_time: Option<f64>,\n) -> Option<Vec<(SectionName, SectionData)>> {\n    if !sections.is_empty() {\n        // We have some detailed compilation section timings, so we postprocess them\n        // Since it is possible that we do not have an end timestamp for a given compilation\n        // section, we need to iterate them and if an end is missing, we assign the end of\n        // the section to the start of the following section.\n        let mut sections = sections.into_iter().fold(\n            // The frontend section is currently implicit in rustc.\n            // It is assumed to start at compilation start and end when codegen starts,\n            // So we hard-code it here.\n            vec![(\n                SectionName::Frontend,\n                SectionData {\n                    start: 0.0,\n                    end: round_to_centisecond(end),\n                },\n            )],\n            |mut sections, (name, section)| {\n                let previous = sections.last_mut().unwrap();\n                // Setting the end of previous to the start of the current.\n                previous.1.end = section.start;\n\n                sections.push((\n                    SectionName::Named(name),\n                    SectionData {\n                        start: round_to_centisecond(section.start),\n                        end: round_to_centisecond(section.end.unwrap_or(end)),\n                    },\n                ));\n\n                sections\n            },\n        );\n\n        // We draw the sections in the pipeline graph in a way where the frontend\n        // section has the \"default\" build color, and then additional sections\n        // (codegen, link) are overlaid on top with a different color.\n        // However, there might be some time after the final (usually link) section,\n        // which definitely shouldn't be classified as \"Frontend\". We thus try to\n        // detect this situation and add a final \"Other\" section.\n        if let Some((_, section)) = sections.last()\n            && section.end < end\n        {\n            sections.push((\n                SectionName::Other,\n                SectionData {\n                    start: round_to_centisecond(section.end),\n                    end: round_to_centisecond(end),\n                },\n            ));\n        }\n        Some(sections)\n    } else if let Some(rmeta) = rmeta_time {\n        // We only know when the rmeta time was generated\n        Some(vec![\n            (\n                SectionName::Frontend,\n                SectionData {\n                    start: 0.0,\n                    end: round_to_centisecond(rmeta),\n                },\n            ),\n            (\n                SectionName::Codegen,\n                SectionData {\n                    start: round_to_centisecond(rmeta),\n                    end: round_to_centisecond(end),\n                },\n            ),\n        ])\n    } else {\n        // No section data provided. We only know the total duration.\n        None\n    }\n}\n\n/// Rounds seconds to 0.01s precision.\npub fn round_to_centisecond(x: f64) -> f64 {\n    (x * 100.0).round() / 100.0\n}\n\nstatic HTML_TMPL: &str = r#\"\n<html>\n<head>\n  <title>Cargo Build Timings — {ROOTS}</title>\n  <meta charset=\"utf-8\">\n<style type=\"text/css\">\n:root {\n  --error-text: #e80000;\n  --text: #000;\n  --background: #fff;\n  --h1-border-bottom: #c0c0c0;\n  --table-box-shadow: rgba(0, 0, 0, 0.1);\n  --table-th: #d5dde5;\n  --table-th-background: #1b1e24;\n  --table-th-border-bottom: #9ea7af;\n  --table-th-border-right: #343a45;\n  --table-tr-border-top: #c1c3d1;\n  --table-tr-border-bottom: #c1c3d1;\n  --table-tr-odd-background: #ebebeb;\n  --table-td-background: #ffffff;\n  --table-td-border-right: #C1C3D1;\n  --canvas-background: #f7f7f7;\n  --canvas-axes: #303030;\n  --canvas-grid: #e6e6e6;\n  --canvas-codegen: #aa95e8;\n  --canvas-link: #95e8aa;\n  --canvas-other: #e895aa;\n  --canvas-custom-build: #f0b165;\n  --canvas-not-custom-build: #95cce8;\n  --canvas-dep-line: #ddd;\n  --canvas-dep-line-highlighted: #000;\n  --canvas-cpu: rgba(250, 119, 0, 0.2);\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --error-text: #e80000;\n    --text: #fff;\n    --background: #121212;\n    --h1-border-bottom: #444;\n    --table-box-shadow: rgba(255, 255, 255, 0.1);\n    --table-th: #a0a0a0;\n    --table-th-background: #2c2c2c;\n    --table-th-border-bottom: #555;\n    --table-th-border-right: #444;\n    --table-tr-border-top: #333;\n    --table-tr-border-bottom: #333;\n    --table-tr-odd-background: #1e1e1e;\n    --table-td-background: #262626;\n    --table-td-border-right: #333;\n    --canvas-background: #1a1a1a;\n    --canvas-axes: #b0b0b0;\n    --canvas-grid: #333;\n    --canvas-block: #aa95e8;\n    --canvas-custom-build: #f0b165;\n    --canvas-not-custom-build: #95cce8;\n    --canvas-dep-line: #444;\n    --canvas-dep-line-highlighted: #fff;\n    --canvas-cpu: rgba(250, 119, 0, 0.2);\n  }\n}\n\nhtml {\n  font-family: sans-serif;\n  color: var(--text);\n  background: var(--background);\n}\n\n.canvas-container {\n  position: relative;\n  margin-top: 5px;\n  margin-bottom: 5px;\n}\n\n.canvas-container.hidden {\n  display: none;\n}\n\nh1 {\n  border-bottom: 1px solid var(--h1-border-bottom);\n}\n\n.graph {\n  display: block;\n}\n\n.my-table {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  border-collapse: collapse;\n  box-shadow: 0 5px 10px var(--table-box-shadow);\n}\n\n.my-table th {\n  color: var(--table-th);\n  background: var(--table-th-background);\n  border-bottom: 4px solid var(--table-th-border-bottom);\n  border-right: 1px solid var(--table-th-border-right);\n  font-size: 18px;\n  font-weight: 100;\n  padding: 12px;\n  text-align: left;\n  vertical-align: middle;\n}\n\n.my-table th:first-child {\n  border-top-left-radius: 3px;\n}\n\n.my-table th:last-child {\n  border-top-right-radius: 3px;\n  border-right:none;\n}\n\n.my-table tr {\n  border-top: 1px solid var(--table-tr-border-top);\n  border-bottom: 1px solid var(--table-tr-border-bottom);\n  font-size: 16px;\n  font-weight: normal;\n}\n\n.my-table tr:first-child {\n  border-top:none;\n}\n\n.my-table tr:last-child {\n  border-bottom:none;\n}\n\n.my-table tr:nth-child(odd) td {\n  background: var(--table-tr-odd-background);\n}\n\n.my-table tr:last-child td:first-child {\n  border-bottom-left-radius:3px;\n}\n\n.my-table tr:last-child td:last-child {\n  border-bottom-right-radius:3px;\n}\n\n.my-table td {\n  background: var(--table-td-background);\n  padding: 10px;\n  text-align: left;\n  vertical-align: middle;\n  font-weight: 300;\n  font-size: 14px;\n  border-right: 1px solid var(--table-td-border-right);\n}\n\n.my-table td:last-child {\n  border-right: 0px;\n}\n\n.summary-table td:first-child {\n  vertical-align: top;\n  text-align: right;\n}\n\n.input-table td {\n  text-align: center;\n}\n\n.error-text {\n  color: var(--error-text);\n}\n\n</style>\n</head>\n<body>\n\n<h1>Cargo Build Timings</h1>\nSee <a href=\"https://doc.rust-lang.org/nightly/cargo/reference/timings.html\">Documentation</a>\n\"#;\n\nstatic HTML_CANVAS: &str = r#\"\n<table class=\"input-table\">\n  <tr>\n    <td><label for=\"min-unit-time\">Min unit time:</label></td>\n    <td title=\"Scale corresponds to a number of pixels per second. It is automatically initialized based on your viewport width.\">\n      <label for=\"scale\">Scale:</label>\n    </td>\n  </tr>\n  <tr>\n    <td><input type=\"range\" min=\"0\" max=\"30\" step=\"0.1\" value=\"0\" id=\"min-unit-time\"></td>\n    <!--\n        The scale corresponds to some number of \"pixels per second\".\n        Its min, max, and initial values are automatically set by JavaScript on page load,\n        based on the client viewport.\n    -->\n    <td><input type=\"range\" min=\"1\" max=\"100\" value=\"50\" id=\"scale\"></td>\n  </tr>\n  <tr>\n    <td><output for=\"min-unit-time\" id=\"min-unit-time-output\"></output></td>\n    <td><output for=\"scale\" id=\"scale-output\"></output></td>\n    <td></td>\n  </tr>\n</table>\n\n<div id=\"pipeline-container\" class=\"canvas-container\"></div>\n<div id=\"timing-container\" class=\"canvas-container\"></div>\n\"#;\n"
  },
  {
    "path": "src/cargo/core/compiler/timings/timings.js",
    "content": "// Position of the vertical axis.\nconst X_LINE = 50;\n// General-use margin size.\nconst MARGIN = 5;\n// Position of the horizontal axis, relative to the bottom.\nconst Y_LINE = 35;\n// Minimum distance between time tick labels.\nconst MIN_TICK_DIST = 50;\n// Radius for rounded rectangle corners.\nconst RADIUS = 3;\n// Height of unit boxes.\nconst BOX_HEIGHT = 25;\n// Distance between Y tick marks on the unit graph.\nconst Y_TICK_DIST = BOX_HEIGHT + 2;\n// Rects used for mouseover detection.\n// Objects of {x, y, x2, y2, i} where `i` is the index into UNIT_DATA.\nlet HIT_BOXES = [];\n// Index into UNIT_DATA of the last unit hovered over by mouse.\nlet LAST_HOVER = null;\n// Key is unit index, value is {x, y, width, sections} of the box.\nlet UNIT_COORDS = {};\n// Map of unit index to the index it was unlocked by.\nlet REVERSE_UNIT_DEPS = {};\nlet REVERSE_UNIT_RMETA_DEPS = {};\nlet UNIT_BY_INDEX = {};\n\nconst MIN_GRAPH_WIDTH = 200;\nconst MAX_GRAPH_WIDTH = 4096;\n\n// How many pixels per second is added by each scale value\nconst SCALE_PIXELS_PER_SEC = 8;\n\nfunction scale_to_graph_width(scale) {\n  // The scale corresponds to `SCALE_PIXELS_PER_SEC` pixels per seconds.\n  // We thus multiply it by that, and the total duration, to get the graph width.\n  const width = scale * SCALE_PIXELS_PER_SEC * DURATION;\n\n  // We then cap the size of the graph. It is hard to view if it is too large, and\n  // browsers may not render a large graph because it takes too much memory.\n  // 4096 is still ridiculously large, and probably won't render on mobile\n  // browsers, but should be ok for many desktop environments.\n  // Also use a minimum width of 200.\n  return Math.max(MIN_GRAPH_WIDTH, Math.min(MAX_GRAPH_WIDTH, width));\n}\n\n// This function performs the reverse of `scale_to_graph_width`.\nfunction width_to_graph_scale(width) {\n  const maxWidth = Math.min(MAX_GRAPH_WIDTH, width);\n  const minWidth = Math.max(MIN_GRAPH_WIDTH, width);\n\n  const trimmedWidth = Math.max(minWidth, Math.min(maxWidth, width));\n\n  const scale = Math.round(trimmedWidth / (DURATION * SCALE_PIXELS_PER_SEC));\n  return Math.max(1, scale);\n}\n\n// Init scale value and limits based on the client's window width and min/max graph width.\nconst scaleElement = document.getElementById('scale');\nscaleElement.min = width_to_graph_scale(MIN_GRAPH_WIDTH);\nscaleElement.max = width_to_graph_scale(MAX_GRAPH_WIDTH);\nscaleElement.value = width_to_graph_scale(window.innerWidth * 0.75);\n\n// Colors from css\nconst getCssColor = name => getComputedStyle(document.body).getPropertyValue(name);\nconst TEXT_COLOR = getCssColor('--text');\nconst BG_COLOR = getCssColor('--background');\nconst CANVAS_BG = getCssColor('--canvas-background');\nconst AXES_COLOR = getCssColor('--canvas-axes');\nconst GRID_COLOR = getCssColor('--canvas-grid');\nconst CODEGEN_COLOR = getCssColor('--canvas-codegen');\nconst LINK_COLOR = getCssColor('--canvas-link');\n// Final leftover section after link\nconst OTHER_COLOR = getCssColor('--canvas-other');\nconst CUSTOM_BUILD_COLOR = getCssColor('--canvas-custom-build');\nconst NOT_CUSTOM_BUILD_COLOR = getCssColor('--canvas-not-custom-build');\nconst DEP_LINE_COLOR = getCssColor('--canvas-dep-line');\nconst DEP_LINE_HIGHLIGHTED_COLOR = getCssColor('--canvas-dep-line-highlighted');\nconst CPU_COLOR = getCssColor('--canvas-cpu');\n\nfor (const unit of UNIT_DATA) {\n  UNIT_BY_INDEX[unit.i] = unit;\n  for (let unblocked of unit.unblocked_units) {\n    REVERSE_UNIT_DEPS[unblocked] = unit.i;\n  }\n  for (let unblocked of unit.unblocked_rmeta_units) {\n    REVERSE_UNIT_RMETA_DEPS[unblocked] = unit.i;\n  }\n}\n\n// Compute x,y coordinate of each block.\n// We also populate a map with the count of each unit name to disambiguate if necessary\nfunction compute_unit_coords(units, px_per_sec) {\n  const unitCount = new Map();\n  UNIT_COORDS = {};\n  for (i = 0; i < units.length; i++) {\n    let unit = units[i];\n    let y = i * Y_TICK_DIST + 1;\n    let x = px_per_sec * unit.start;\n\n    const sections = [];\n    if (unit.sections !== null) {\n      // We have access to compilation sections\n      for (const section of unit.sections) {\n        const [name, { start, end }] = section;\n        sections.push({\n          name,\n          start: x + px_per_sec * start,\n          width: (end - start) * px_per_sec\n        });\n      }\n    }\n\n    let width = Math.max(px_per_sec * unit.duration, 1.0);\n    UNIT_COORDS[unit.i] = { x, y, width, sections };\n\n    const count = unitCount.get(unit.name) || 0;\n    unitCount.set(unit.name, count + 1);\n  }\n\n  return { UNIT_COORDS, unitCount }\n}\n\nclass SvgRenderer {\n  constructor() {}\n\n  render_pipeline_graph() {\n    if (UNIT_DATA.length == 0) {\n      return;\n    }\n    HIT_BOXES.length = 0;\n    const min_time = document.getElementById('min-unit-time').valueAsNumber;\n\n    const units = UNIT_DATA.filter(unit => unit.duration >= min_time);\n\n    const graph_height = Y_TICK_DIST * units.length;\n    let { canvas_height, canvas_width, graph_width, px_per_sec } = graph_dimension(graph_height);\n    const axes = this._draw_graph_axes({ canvas_height, graph_height, graph_width, px_per_sec });\n\n    // Draw Y tick marks.\n    let y_ticks = '';\n    if (units.length != 0) {\n      const path_commands = Array(units.length - 1)\n        .fill(0)\n        .map((_, idx) => {\n          const n = idx + 1;\n          const y = MARGIN + Y_TICK_DIST * n;\n          return `M${X_LINE} ${y} h-5`;\n        });\n      y_ticks = `<path class=\"axis axis-y\" d=\"${path_commands.join(\" \")}\"></path>`;\n    }\n\n    // Draw Y labels.\n    const y_labels = Array(units.length)\n      .fill(0)\n      .map((_, n) => {\n          let y = MARGIN + Y_TICK_DIST * n + Y_TICK_DIST / 2;\n          return `<text class=\"axis axis-y\" x=\"${X_LINE - 4}\" y=\"${y}\">${n + 1}</text>`;\n      })\n      .join(\"\");\n\n    // Draw the graph.\n    const { UNIT_COORDS, unitCount } = compute_unit_coords(units, px_per_sec);\n    const presentSections = new Set();\n\n    // Draw the blocks.\n    let blocks = Array(units.length)\n      .fill(0)\n      .map((_, i) => {\n        let unit = units[i];\n        let { x, y, width, sections } = UNIT_COORDS[unit.i];\n\n        const boxes = [this._roundedRect(\"\", x, y, width, unit)].concat(\n          sections.map((section) => {\n            presentSections.add(section.name);\n            return this._roundedRect(\n              section.name,\n              section.start,\n              y,\n              section.width,\n              unit,\n            );\n          }),\n        );\n\n        const labelName = (unitCount.get(unit.name) || 0) > 1 ? `${unit.name} (v${unit.version})${unit.target}` : `${unit.name}${unit.target}`;\n        const label = `${labelName}: ${unit.duration}s`;\n\n        const text_info_width = measure_text_width(label);\n        const label_x = Math.min(x + 5.0, canvas_width - text_info_width - X_LINE);\n        const box_label = `<text class=\"box\" x=\"${label_x}\" y=\"${y + BOX_HEIGHT / 2}\">${label}</text>`;\n\n        const dep_lines = this._draw_dep_lines(unit.i);\n        return boxes.concat(box_label).concat(dep_lines);\n      })\n      .flat()\n      .join(\"\");\n\n    blocks = `\n<g id=\"boxes\" transform=\"translate(${X_LINE} ${MARGIN})\">${blocks}</g>\n<g id=\"hl-dep-lines\" transform=\"translate(${X_LINE} ${MARGIN})\"></g>`;\n\n    // Draw a legend.\n    const legend = `\n<g class=\"legend\" transform=\"translate(${canvas_width-200},${MARGIN})\">\n  ${this._draw_legend(160, get_legend_entries(presentSections))}\n</g>`;\n\n    const svg_container = document.getElementById(\"pipeline-container\");\n    if (svg_container) {\n      const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n      svg.setAttribute(\"width\", canvas_width);\n      svg.setAttribute(\"height\", canvas_height);\n      Object.assign(svg.style, {\n        background: CANVAS_BG,\n        color: TEXT_COLOR,\n        fontFamily: 'sans-serif',\n        fontSize: '16px'\n      });\n      svg.innerHTML = `\n<style type=\"text/css\">\n  path.axis {\n    fill: none;\n    stroke: ${AXES_COLOR};\n    stroke-width: 2;\n  }\n  text.axis {\n    fill: ${AXES_COLOR};\n    font-size: 16px;\n    stroke: none;\n    text-anchor: middle;\n  }\n  text.axis-y {\n    dominant-baseline: middle;\n    text-anchor: end;\n  }\n  .grid {\n    stroke: ${GRID_COLOR};\n    stroke-dasharray: 2 4;\n    stroke-width: 2;\n  }\n  rect.box {\n    fill: ${NOT_CUSTOM_BUILD_COLOR};\n    height: ${BOX_HEIGHT}px;\n    rx: ${RADIUS}px;\n    ry: ${RADIUS}px;\n  }\n  rect.box.run-custom-build {\n    fill: ${CUSTOM_BUILD_COLOR};\n  }\n  rect.box.codegen {\n    fill: ${CODEGEN_COLOR};\n  }\n  rect.box.link {\n    fill: ${LINK_COLOR};\n  }\n  rect.box.other {\n    fill: ${OTHER_COLOR}\n  }\n  text.box {\n    dominant-baseline: middle;\n    fill: ${TEXT_COLOR};\n    font-size: 14px;\n    text-anchor: start\n  }\n  .dep-line {\n    fill: none;\n    stroke: ${DEP_LINE_COLOR};\n    stroke-dasharray: 2;\n    stroke-width: 2;\n  }\n  #hl-dep-lines .dep-line{\n    stroke: ${DEP_LINE_HIGHLIGHTED_COLOR};\n  }\n  path.legend__cell {\n    stroke-width: 2;\n  }\n  .legend__desc {\n    fill: ${TEXT_COLOR};\n    dominant-baseline: middle;\n  }\n</style>\n${axes}\n${y_ticks}\n${y_labels}\n${blocks}\n${legend}`;\n      svg_container.innerHTML = svg.outerHTML;\n    }\n  }\n\n  // Draw a legend at the current position of the ctx.\n  // entries should be an array of objects with the following scheme:\n  // {\n  //   \"name\": <name of the legend entry> [string],\n  //   \"color\": <color of the legend entry> [string],\n  //   \"line\": <should the entry be a thin line or a rectangle> [bool]\n  // }\n  _draw_legend(width, entries) {\n    const entry_height = 20;\n\n    // Add a bit of margin to the bottom and top\n    const height = entries.length * entry_height + 4;\n\n    // Draw background\n    let legend = [];\n    legend.push(`<rect stroke=\"${TEXT_COLOR}\" stroke-width=\"1\" fill=\"${BG_COLOR}\" width=\"${width}\" height=\"${height}\"></rect>`);\n\n    // Dimension of a block\n    const block_height = 15;\n    const block_width = 30;\n\n    // Margin from the left edge\n    const x_start = 5;\n    // Width of the \"mark\" section (line/block)\n    const mark_width = 45;\n\n    // Draw legend entries\n    let y = 12;\n    for (const entry of entries) {\n      const cell = entry.line ?\n        `<path class=\"legend__cell\" stroke=\"${entry.color}\" d=\"M${x_start} ${y} h ${mark_width}\"></path>` :\n        `\n<rect class=\"legend__cell\" fill=\"${entry.color}\" width=\"${block_width}\" height=\"${block_height}\"\n  x=\"${x_start + (mark_width - block_width) / 2}\" y=\"${y - (block_height / 2)}\"\n></rect>`;\n      legend.push(cell);\n      legend.push(`<text class=\"legend__desc\" x=\"${x_start + mark_width + 4}\" y=\"${y + 1}\">${entry.name}</text>`)\n      y += entry_height;\n    }\n    return legend.join(\"\")\n  }\n\n  // Draws lines from the given unit to the units it unlocks.\n  _draw_dep_lines(unit_idx) {\n    const unit = UNIT_BY_INDEX[unit_idx];\n    const { x, y, sections } = UNIT_COORDS[unit_idx];\n    return unit.unblocked_units\n      .map((unblocked) => this._draw_one_dep_line(x, y, unblocked, unit_idx))\n      .concat(\n        unit.unblocked_rmeta_units.map((unblocked) => {\n          const codegen_x = get_codegen_section_x(sections);\n          return this._draw_one_dep_line(codegen_x, y, unblocked, unit_idx);\n        }),\n      )\n      .join(\"\");\n  }\n\n  _draw_one_dep_line(from_x, from_y, to_unit, from_unit) {\n    if (to_unit in UNIT_COORDS) {\n      let { x: u_x, y: u_y } = UNIT_COORDS[to_unit];\n      // Use multiple path instead to avoid potential rendering issue while scrolling in Firefox.\n      return `\n<path class=\"dep-line\" data-unblocked=\"${to_unit}\" data-unblocked-by=\"${from_unit}\" d=\"M ${from_x} ${from_y + BOX_HEIGHT / 2} h -5\"></path>\n<path class=\"dep-line\" data-unblocked=\"${to_unit}\" data-unblocked-by=\"${from_unit}\" d=\"M ${from_x - 5} ${from_y + BOX_HEIGHT / 2} V ${u_y + BOX_HEIGHT / 2}\"></path>\n<path class=\"dep-line\" data-unblocked=\"${to_unit}\" data-unblocked-by=\"${from_unit}\" d=\"M ${from_x - 5} ${u_y + BOX_HEIGHT / 2} H${u_x}\"></path>\n`;\n    }\n  }\n\n  render_timing_graph() {\n    if (CONCURRENCY_DATA.length == 0) {\n      return;\n    }\n    const HEIGHT = 400;\n    const AXIS_HEIGHT = HEIGHT - MARGIN - Y_LINE;\n    const TOP_MARGIN = 10;\n    const GRAPH_HEIGHT = AXIS_HEIGHT - TOP_MARGIN;\n\n    let { canvas_height, canvas_width, graph_height, graph_width, px_per_sec } = graph_dimension(AXIS_HEIGHT);\n    const axis_bottom = this._draw_graph_axes({ canvas_height, graph_height, graph_width, px_per_sec });\n\n    // Draw Y tick marks and labels.\n    let max_v = 0;\n    for (let c of CONCURRENCY_DATA) {\n      max_v = Math.max(max_v, c.active, c.waiting, c.inactive);\n    }\n    const px_per_v = GRAPH_HEIGHT / max_v;\n    const { step, tick_dist, num_ticks } = split_ticks(max_v, px_per_v, GRAPH_HEIGHT);\n\n    const labels = [];\n    const ticks_path_commands = Array(num_ticks)\n      .fill(0)\n      .map((_, n) => {\n        const y = HEIGHT - Y_LINE - ((n + 1) * tick_dist);\n        labels.push( `<text class=\"axis axis-y\" x=\"${X_LINE - 10}\" y=\"${y}\">${(n + 1) * step}</text>`);\n        return `M${X_LINE} ${y} h-5`;\n      })\n      .join(\" \");\n    const ticks = `<path class=\"axis axis-y\" d=\"${ticks_path_commands}\"></path>`;\n    const ticks_labels = labels.join(\"\");\n\n    // Label the Y axis.\n    let label_y = (HEIGHT - Y_LINE) / 2;\n\n    const y_axis_label = `<text class=\"axis axis-label\" transform=\"translate(15, ${label_y}) rotate(270)\"># Units</text>`\n    const axis_left = `${y_axis_label}${ticks}${ticks_labels}`;\n\n    // Draw the graph.\n\n    function coord(t, v) {\n      return {\n        x: graph_width * (t / DURATION),\n        y: TOP_MARGIN + GRAPH_HEIGHT * (1.0 - (v / max_v))\n      };\n    }\n\n    const cpuFillStyle = CPU_COLOR;\n    let cpu = \"\";\n    if (CPU_USAGE.length > 1) {\n      const bottomLeft = coord(CPU_USAGE[0][0], 0);\n      const bottomRight = coord(CPU_USAGE[CPU_USAGE.length - 1][0], 0);\n      const path_commands = [`M${bottomLeft.x} ${bottomLeft.y}`]\n      .concat(\n        Array(CPU_USAGE.length)\n          .fill(0)\n          .map((_, i) => {\n            let [time, usage] = CPU_USAGE[i];\n            let { x, y } = coord(time, (usage / 100.0) * max_v);\n            return `L${x} ${y}`;\n          }),\n      )\n      .concat(`L${bottomRight.x} ${bottomRight.y}`);\n      cpu = `<path stroke-width=\"0\" fill=\"${cpuFillStyle}\" d=\"${path_commands.join(\"\")}\"></path>`;\n    }\n\n    function draw_line(style, key) {\n      let first = CONCURRENCY_DATA[0];\n      let last = coord(first.t, key(first));\n      const path_commands = [];\n      path_commands.push(`M${last.x} ${last.y}`)\n      for (let i = 1; i < CONCURRENCY_DATA.length; i++) {\n        let c = CONCURRENCY_DATA[i];\n        let { x, y } = coord(c.t, key(c));\n        path_commands.push(`L${x} ${last.y} V${y}`);\n        last = { x, y };\n      }\n      return `<path class=\"status-line\" stroke=\"${style}\" d=\"${path_commands.join(\"\")}\"></path>`\n    }\n\n    const lines = [];\n    lines.push(draw_line('blue', function(c) { return c.inactive; }));\n    lines.push(draw_line('red', function(c) { return c.waiting; }));\n    lines.push(draw_line('green', function(c) { return c.active; }));\n\n    const timings = `<g class=\"graph-content\" transform=\"translate(${X_LINE} ${MARGIN})\">${cpu}${lines}</g>`;\n\n    // Draw a legend.\n    const legend = `\n<g class=\"legend\" transform=\"translate(${canvas_width-200},${MARGIN})\">\n${this._draw_legend(150, [{\n    name: \"Waiting\",\n    color: \"red\",\n    line: true\n  }, {\n    name: \"Inactive\",\n    color: \"blue\",\n    line: true\n  }, {\n    name: \"Active\",\n    color: \"green\",\n    line: true\n  }, {\n    name: \"CPU Usage\",\n    color: cpuFillStyle,\n    line: false\n}])}\n</g>`;\n\n    const svg_container = document.getElementById(\"timing-container\");\n    if (svg_container) {\n      const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n      svg.setAttribute(\"width\", canvas_width);\n      svg.setAttribute(\"height\", canvas_height);\n      Object.assign(svg.style, {\n        background: CANVAS_BG,\n        color: TEXT_COLOR,\n        fontFamily: 'sans-serif',\n        fontSize: '16px'\n      });\n      svg.innerHTML = `\n<style type=\"text/css\">\n  path.axis {\n    fill: none;\n    stroke: ${AXES_COLOR};\n    stroke-width: 2;\n  }\n  text.axis {\n    fill: ${AXES_COLOR};\n    font-size: 16px;\n    stroke: none;\n    text-anchor: middle;\n  }\n  text.axis-y {\n    dominant-baseline: middle;\n    text-anchor: end;\n  }\n  .grid {\n    stroke: ${GRID_COLOR};\n    stroke-dasharray: 2 4;\n    stroke-width: 2;\n  }\n  .status-line {\n    fill: none;\n    stroke-width: 2;\n  }\n  path.legend__cell {\n    stroke-width: 2;\n  }\n  .legend__desc {\n    fill: ${TEXT_COLOR};\n    dominant-baseline: middle;\n  }\n</style>\n${axis_bottom}\n${axis_left}\n${timings}\n${legend}\n`;\n      svg_container.innerHTML = svg.outerHTML;\n    }\n  }\n\n  _draw_graph_axes({ canvas_height, graph_height, graph_width, px_per_sec }) {\n    // Draw main axes.\n    const main_axes = `\n<path class=\"axis\" d=\"\n  M${X_LINE} ${MARGIN}\n  V${graph_height + MARGIN}\n  H${X_LINE + graph_width + 20}\"\n></path>`;\n\n    // Draw X tick marks.\n    const { step, tick_dist, num_ticks } = split_ticks(DURATION, px_per_sec, graph_width);\n    const TICK_LENGTH = 5;\n    const grid_height = canvas_height - Y_LINE;\n    const labels = [];\n    const ticks_path_commands = Array(num_ticks)\n        .fill(0)\n        .map((_, n) => {\n          const x = X_LINE + ((n + 1) * tick_dist);\n          const label = `\n  <text class=\"axis\" x=\"${x}\" y=\"${grid_height + 20}\">\n    ${(n + 1) * step}s\n  </text>`;\n          labels.push(label);\n          return `M${x} ${grid_height} v${TICK_LENGTH}`;\n        })\n        .join(\" \");\n\n    const ticks = `<path class=\"axis\"  d=\"${ticks_path_commands}\"></path>`;\n    const ticks_labels = labels.join(\"\")\n\n    // Draw vertical lines.\n    const vertical_lines = Array(num_ticks)\n      .fill(0)\n      .map((_, n) => {\n        const x = X_LINE + ((n + 1) * tick_dist);\n        return `<path class=\"grid\" d=\"M${x} ${grid_height - 1} V${MARGIN}\"></path>`;\n      })\n      .join(\"\");\n    return `${main_axes}${ticks}${vertical_lines}${ticks_labels}`;\n  }\n\n  _roundedRect(section_name, x, y, width, unit) {\n    return `\n<rect class=\"box ${unit.mode} ${section_name}\" data-i=\"${unit.i}\" x=\"${x}\" y=\"${y}\" width=\"${width}\"\n  onmousemove=\"hl(${unit.i})\"\n>\n</rect>`\n  }\n}\n\n// Determine the width of text for svg.\nfunction measure_text_width(text) {\n  let ctx;\n  let canvas = measure_text_width.canvas;\n  if (!canvas) {\n    canvas = (measure_text_width.canvas = document.createElement(\"canvas\"));\n  }\n  ctx = canvas.getContext(\"2d\");\n  ctx.font = '14px sans-serif';\n  const text_info = ctx.measureText(text);\n  return text_info.width;\n}\n\n// Gets the x-coordinate of the codegen section of a unit.\n//\n// This is for drawing rmeta dependency lines.\nfunction get_codegen_section_x(sections) {\n    const codegen_section = sections.find(s => s.name === \"codegen\")\n    if (!codegen_section) {\n        // This happens only when type-checking (e.g., `cargo check`)\n        return null;\n    }\n    return codegen_section.start;\n}\n\nfunction get_legend_entries(presentSections) {\n    let frontend_name = \"Frontend/rest\";\n    if (presentSections.has(\"other\")) {\n      frontend_name = \"Frontend\";\n    }\n\n    const legend_entries = [{\n      name: frontend_name,\n      color: NOT_CUSTOM_BUILD_COLOR,\n      line: false\n    }];\n    if (presentSections.has(\"codegen\")) {\n      legend_entries.push({\n        name: \"Codegen\",\n        color: CODEGEN_COLOR,\n        line: false\n      });\n    }\n    if (presentSections.has(\"link\")) {\n      legend_entries.push({\n        name: \"Linking\",\n        color: LINK_COLOR,\n        line: false\n      });\n    }\n    if (presentSections.has(\"other\")) {\n      legend_entries.push({\n        name: \"Other\",\n        color: OTHER_COLOR,\n        line: false\n      });\n    }\n  return legend_entries\n}\n\nfunction graph_dimension(graph_height) {\n  const scale = document.getElementById('scale').valueAsNumber;\n  const graph_width = scale_to_graph_width(scale);\n  const px_per_sec = graph_width / DURATION;\n  const canvas_width = Math.max(graph_width + X_LINE + 30, X_LINE + 250);\n  const canvas_height = graph_height + MARGIN + Y_LINE;\n  return { canvas_height, canvas_width, graph_height, graph_width, px_per_sec, scale }\n}\n\n// Determine the spacing and number of ticks along an axis.\nfunction split_ticks(max_value, px_per_v, max_px) {\n  const max_ticks = Math.floor(max_px / MIN_TICK_DIST);\n  if (max_ticks <= 1) {\n    // Graph is too small for even 1 tick.\n    return {step: max_value, tick_dist: max_px, num_ticks: 1};\n  }\n  let step;\n  if (max_value <= max_ticks) {\n    step = 1;\n  } else if (max_value <= max_ticks * 2) {\n    step = 2;\n  } else if (max_value <= max_ticks * 4) {\n    step = 4;\n  } else if (max_value <= max_ticks * 5) {\n    step = 5;\n  } else {\n    step = 10;\n    let count = 0;\n    while (true) {\n      if (count > 100) {\n        throw Error(\"tick loop too long\");\n      }\n      count += 1;\n      if (max_value <= max_ticks * step) {\n        break;\n      }\n      step += 10;\n    }\n  }\n  const tick_dist = px_per_v * step;\n  const num_ticks = Math.floor(max_value / step);\n  return {step, tick_dist, num_ticks};\n}\n\nfunction hl(i) {\n  // Highlight dependency lines on mouse hover.\n  if (i === undefined || i == LAST_HOVER) {\n    return\n  }\n  LAST_HOVER = i;\n  let g = document.getElementById(\"hl-dep-lines\");\n\n  if (g) {\n    const selector = '#boxes .dep-line[data-unblocked=\"'+i+'\"],#boxes .dep-line[data-unblocked-by=\"' + i + '\"]';\n    const lines = Array.from(document.querySelectorAll(selector)).map(el => el.outerHTML);\n    g.innerHTML = lines.join(\"\");\n  }\n}\n\nlet renderer = new SvgRenderer();\ntry {\n  renderer.render_pipeline_graph();\n  renderer.render_timing_graph();\n} catch (err) {\n  console.error(err);\n}\n\n// Set up and handle controls.\n{\n  const range = document.getElementById('min-unit-time');\n  const time_output = document.getElementById('min-unit-time-output');\n  time_output.innerHTML = `${range.value}s`;\n  range.oninput = event => {\n    time_output.innerHTML = `${range.value}s`;\n    try {\n      renderer.render_pipeline_graph();\n    } catch (err) {\n      console.error(err);\n    }\n  };\n\n  const scale = document.getElementById('scale');\n  const scale_output = document.getElementById('scale-output');\n  scale_output.innerHTML = `${scale.value}`;\n  scale.oninput = event => {\n    scale_output.innerHTML = `${scale.value}`;\n    try {\n      renderer.render_pipeline_graph();\n      renderer.render_timing_graph();\n    } catch (err) {\n      console.error(err);\n    }\n  };\n\n  Array.from(document.querySelectorAll(\"input[name='renderer']\")).forEach(function(el) {\n    el.addEventListener(\"change\", function(event) {\n      renderer = setupRenderer(event.target.value);\n      try {\n        renderer.render_pipeline_graph();\n        renderer.render_timing_graph();\n      } catch (err) {\n        console.error(err);\n      }\n    });\n  });\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/unit.rs",
    "content": "//! Types and impls for [`Unit`].\n\nuse serde::Deserialize;\nuse serde::Serialize;\n\nuse crate::core::Package;\nuse crate::core::compiler::unit_dependencies::IsArtifact;\nuse crate::core::compiler::{CompileKind, CompileMode, CompileTarget, CrateType};\nuse crate::core::manifest::{Target, TargetKind};\nuse crate::core::profiles::Profile;\nuse crate::util::GlobalContext;\nuse crate::util::interning::InternedString;\nuse std::cell::RefCell;\nuse std::collections::{BTreeMap, HashSet};\nuse std::fmt;\nuse std::hash::{Hash, Hasher};\nuse std::ops::Deref;\nuse std::rc::Rc;\n\nuse super::BuildOutput;\n\n/// Stable identifier for referencing a [`Unit`].\n///\n/// This is an index into the unit graph, assigned when units are registered.\n/// It provides a compact way to reference units.\n#[derive(\n    Serialize, Deserialize, Debug, Default, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,\n)]\n#[serde(transparent)]\npub struct UnitIndex(pub u64);\n\nimpl fmt::Display for UnitIndex {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{}\", self.0)\n    }\n}\n\n/// All information needed to define a unit.\n///\n/// A unit is an object that has enough information so that cargo knows how to build it.\n/// For example, if your package has dependencies, then every dependency will be built as a library\n/// unit. If your package is a library, then it will be built as a library unit as well, or if it\n/// is a binary with `main.rs`, then a binary will be output. There are also separate unit types\n/// for `test`ing and `check`ing, amongst others.\n///\n/// The unit also holds information about all possible metadata about the package in `pkg`.\n///\n/// A unit needs to know extra information in addition to the type and root source file. For\n/// example, it needs to know the target architecture (OS, chip arch etc.) and it needs to know\n/// whether you want a debug or release build. There is enough information in this struct to figure\n/// all that out.\n#[derive(Clone, PartialOrd, Ord)]\npub struct Unit {\n    inner: Rc<UnitInner>,\n}\n\n/// Internal fields of `Unit` which `Unit` will dereference to.\n#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]\npub struct UnitInner {\n    /// Information about available targets, which files to include/exclude, etc. Basically stuff in\n    /// `Cargo.toml`.\n    pub pkg: Package,\n    /// Information about the specific target to build, out of the possible targets in `pkg`. Not\n    /// to be confused with *target-triple* (or *target architecture* ...), the target arch for a\n    /// build.\n    pub target: Target,\n    /// The profile contains information about *how* the build should be run, including debug\n    /// level, etc.\n    pub profile: Profile,\n    /// Whether this compilation unit is for the host or target architecture.\n    ///\n    /// For example, when\n    /// cross compiling and using a custom build script, the build script needs to be compiled for\n    /// the host architecture so the host rustc can use it (when compiling to the target\n    /// architecture).\n    pub kind: CompileKind,\n    /// The \"mode\" this unit is being compiled for. See [`CompileMode`] for more details.\n    pub mode: CompileMode,\n    /// The `cfg` features to enable for this unit.\n    /// This must be sorted.\n    pub features: Vec<InternedString>,\n    /// Extra compiler flags to pass to `rustc` for a given unit.\n    ///\n    /// Although it depends on the caller, in the current Cargo implementation,\n    /// these flags take precedence over those from [`BuildContext::extra_args_for`].\n    ///\n    /// As of now, these flags come from environment variables and configurations.\n    /// See [`TargetInfo.rustflags`] for more on how Cargo collects them.\n    ///\n    /// [`BuildContext::extra_args_for`]: crate::core::compiler::build_context::BuildContext::extra_args_for\n    /// [`TargetInfo.rustflags`]: crate::core::compiler::build_context::TargetInfo::rustflags\n    pub rustflags: Rc<[String]>,\n    /// Extra compiler flags to pass to `rustdoc` for a given unit.\n    ///\n    /// Although it depends on the caller, in the current Cargo implementation,\n    /// these flags take precedence over those from [`BuildContext::extra_args_for`].\n    ///\n    /// As of now, these flags come from environment variables and configurations.\n    /// See [`TargetInfo.rustdocflags`] for more on how Cargo collects them.\n    ///\n    /// [`BuildContext::extra_args_for`]: crate::core::compiler::build_context::BuildContext::extra_args_for\n    /// [`TargetInfo.rustdocflags`]: crate::core::compiler::build_context::TargetInfo::rustdocflags\n    pub rustdocflags: Rc<[String]>,\n    /// Build script override for the given library name.\n    ///\n    /// Any package with a `links` value for the given library name will skip\n    /// running its build script and instead use the given output from the\n    /// config file.\n    pub links_overrides: Rc<BTreeMap<String, BuildOutput>>,\n    // if `true`, the dependency is an artifact dependency, requiring special handling when\n    // calculating output directories, linkage and environment variables provided to builds.\n    pub artifact: IsArtifact,\n    /// Whether this is a standard library unit.\n    pub is_std: bool,\n    /// A hash of all dependencies of this unit.\n    ///\n    /// This is used to keep the `Unit` unique in the situation where two\n    /// otherwise identical units need to link to different dependencies. This\n    /// can happen, for example, when there are shared dependencies that need\n    /// to be built with different features between normal and build\n    /// dependencies. See `rebuild_unit_graph_shared` for more on why this is\n    /// done.\n    ///\n    /// This value initially starts as 0, and then is filled in via a\n    /// second-pass after all the unit dependencies have been computed.\n    pub dep_hash: u64,\n\n    /// This is used for target-dependent feature resolution and is copied from\n    /// [`FeaturesFor::ArtifactDep`], if the enum matches the variant.\n    ///\n    /// [`FeaturesFor::ArtifactDep`]: crate::core::resolver::features::FeaturesFor::ArtifactDep\n    pub artifact_target_for_features: Option<CompileTarget>,\n\n    /// Skip compiling this unit because `--compile-time-deps` flag is set and\n    /// this is not a compile time dependency.\n    ///\n    /// Since dependencies of this unit might be compile time dependencies, we\n    /// set this field instead of completely dropping out this unit from unit graph.\n    pub skip_non_compile_time_dep: bool,\n}\n\nimpl UnitInner {\n    /// Returns whether compilation of this unit requires all upstream artifacts\n    /// to be available.\n    ///\n    /// This effectively means that this unit is a synchronization point (if the\n    /// return value is `true`) that all previously pipelined units need to\n    /// finish in their entirety before this one is started.\n    pub fn requires_upstream_objects(&self) -> bool {\n        self.mode.is_any_test() || self.target.kind().requires_upstream_objects()\n    }\n\n    /// Returns whether compilation of this unit could benefit from splitting metadata\n    /// into a .rmeta file.\n    pub fn benefits_from_no_embed_metadata(&self) -> bool {\n        matches!(self.mode, CompileMode::Build)\n            && self.target.kind().benefits_from_no_embed_metadata()\n    }\n\n    /// Returns whether or not this is a \"local\" package.\n    ///\n    /// A \"local\" package is one that the user can likely edit, or otherwise\n    /// wants warnings, etc.\n    pub fn is_local(&self) -> bool {\n        self.pkg.package_id().source_id().is_path() && !self.is_std\n    }\n\n    /// Returns whether or not warnings should be displayed for this unit.\n    pub fn show_warnings(&self, gctx: &GlobalContext) -> bool {\n        self.is_local() || gctx.extra_verbose()\n    }\n}\n\n// Just hash the pointer for fast hashing\nimpl Hash for Unit {\n    fn hash<H: Hasher>(&self, hasher: &mut H) {\n        std::ptr::hash(&*self.inner, hasher)\n    }\n}\n\n// Just equate the pointer since these are interned\nimpl PartialEq for Unit {\n    fn eq(&self, other: &Unit) -> bool {\n        std::ptr::eq(&*self.inner, &*other.inner)\n    }\n}\n\nimpl Eq for Unit {}\n\nimpl Deref for Unit {\n    type Target = UnitInner;\n\n    fn deref(&self) -> &UnitInner {\n        &*self.inner\n    }\n}\n\nimpl fmt::Debug for Unit {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Unit\")\n            .field(\"pkg\", &self.pkg)\n            .field(\"target\", &self.target)\n            .field(\"profile\", &self.profile)\n            .field(\"kind\", &self.kind)\n            .field(\"mode\", &self.mode)\n            .field(\"features\", &self.features)\n            .field(\"rustflags\", &self.rustflags)\n            .field(\"rustdocflags\", &self.rustdocflags)\n            .field(\"links_overrides\", &self.links_overrides)\n            .field(\"artifact\", &self.artifact.is_true())\n            .field(\n                \"artifact_target_for_features\",\n                &self.artifact_target_for_features,\n            )\n            .field(\"is_std\", &self.is_std)\n            .field(\"dep_hash\", &self.dep_hash)\n            .finish()\n    }\n}\n\n/// A small structure used to \"intern\" `Unit` values.\n///\n/// A `Unit` is just a thin pointer to an internal `UnitInner`. This is done to\n/// ensure that `Unit` itself is quite small as well as enabling a very\n/// efficient hash/equality implementation for `Unit`. All units are\n/// manufactured through an interner which guarantees that each equivalent value\n/// is only produced once.\npub struct UnitInterner {\n    state: RefCell<InternerState>,\n}\n\nstruct InternerState {\n    cache: HashSet<Rc<UnitInner>>,\n}\n\nimpl UnitInterner {\n    /// Creates a new blank interner\n    pub fn new() -> UnitInterner {\n        UnitInterner {\n            state: RefCell::new(InternerState {\n                cache: HashSet::new(),\n            }),\n        }\n    }\n\n    /// Creates a new `unit` from its components. The returned `Unit`'s fields\n    /// will all be equivalent to the provided arguments, although they may not\n    /// be the exact same instance.\n    pub fn intern(\n        &self,\n        pkg: &Package,\n        target: &Target,\n        profile: Profile,\n        kind: CompileKind,\n        mode: CompileMode,\n        features: Vec<InternedString>,\n        rustflags: Rc<[String]>,\n        rustdocflags: Rc<[String]>,\n        links_overrides: Rc<BTreeMap<String, BuildOutput>>,\n        is_std: bool,\n        dep_hash: u64,\n        artifact: IsArtifact,\n        artifact_target_for_features: Option<CompileTarget>,\n        skip_non_compile_time_dep: bool,\n    ) -> Unit {\n        let target = match (is_std, target.kind()) {\n            // This is a horrible hack to support build-std. `libstd` declares\n            // itself with both rlib and dylib. We don't want the dylib for a\n            // few reasons:\n            //\n            // - dylibs don't have a hash in the filename. If you do something\n            //   (like switch rustc versions), it will stomp on the dylib\n            //   file, invalidating the entire cache (because std is a dep of\n            //   everything).\n            // - We don't want to publicize the presence of dylib for the\n            //   standard library.\n            //\n            // At some point in the future, it would be nice to have a\n            // first-class way of overriding or specifying crate-types.\n            (true, TargetKind::Lib(crate_types)) if crate_types.contains(&CrateType::Dylib) => {\n                let mut new_target = Target::clone(target);\n                new_target.set_kind(TargetKind::Lib(vec![CrateType::Rlib]));\n                new_target\n            }\n            _ => target.clone(),\n        };\n        let inner = self.intern_inner(&UnitInner {\n            pkg: pkg.clone(),\n            target,\n            profile,\n            kind,\n            mode,\n            features,\n            rustflags,\n            rustdocflags,\n            links_overrides,\n            is_std,\n            dep_hash,\n            artifact,\n            artifact_target_for_features,\n            skip_non_compile_time_dep,\n        });\n        Unit { inner }\n    }\n\n    fn intern_inner(&self, item: &UnitInner) -> Rc<UnitInner> {\n        let mut me = self.state.borrow_mut();\n        if let Some(item) = me.cache.get(item) {\n            return item.clone();\n        }\n        let item = Rc::new(item.clone());\n        me.cache.insert(item.clone());\n        item\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/unit_dependencies.rs",
    "content": "//! Constructs the dependency graph for compilation.\n//!\n//! Rust code is typically organized as a set of Cargo packages. The\n//! dependencies between the packages themselves are stored in the\n//! [`Resolve`] struct. However, we can't use that information as is for\n//! compilation! A package typically contains several targets, or crates,\n//! and these targets has inter-dependencies. For example, you need to\n//! compile the `lib` target before the `bin` one, and you need to compile\n//! `build.rs` before either of those.\n//!\n//! So, we need to lower the `Resolve`, which specifies dependencies between\n//! *packages*, to a graph of dependencies between their *targets*, and this\n//! is exactly what this module is doing! Well, almost exactly: another\n//! complication is that we might want to compile the same target several times\n//! (for example, with and without tests), so we actually build a dependency\n//! graph of [`Unit`]s, which capture these properties.\n\nuse std::collections::{HashMap, HashSet};\n\nuse tracing::trace;\n\nuse crate::CargoResult;\nuse crate::core::compiler::UserIntent;\nuse crate::core::compiler::artifact::match_artifacts_kind_with_targets;\nuse crate::core::compiler::unit_graph::{UnitDep, UnitGraph};\nuse crate::core::compiler::{\n    CompileKind, CompileMode, CrateType, RustcTargetData, Unit, UnitInterner,\n};\nuse crate::core::dependency::{Artifact, ArtifactKind, ArtifactTarget, DepKind};\nuse crate::core::profiles::{Profile, Profiles, UnitFor};\nuse crate::core::resolver::features::{FeaturesFor, ResolvedFeatures};\nuse crate::core::resolver::{ForceAllTargets, HasDevUnits, Resolve};\nuse crate::core::{\n    Dependency, Feature, Package, PackageId, PackageSet, Target, TargetKind, Workspace,\n};\nuse crate::ops::resolve_all_features;\nuse crate::util::GlobalContext;\nuse crate::util::interning::InternedString;\n\nconst IS_NO_ARTIFACT_DEP: Option<&'static Artifact> = None;\n\n/// Collection of stuff used while creating the [`UnitGraph`].\nstruct State<'a, 'gctx> {\n    ws: &'a Workspace<'gctx>,\n    gctx: &'gctx GlobalContext,\n    /// Stores the result of building the [`UnitGraph`].\n    unit_dependencies: UnitGraph,\n    package_set: &'a PackageSet<'gctx>,\n    usr_resolve: &'a Resolve,\n    usr_features: &'a ResolvedFeatures,\n    /// Like `usr_resolve` but for building standard library (`-Zbuild-std`).\n    std_resolve: Option<&'a Resolve>,\n    /// Like `usr_features` but for building standard library (`-Zbuild-std`).\n    std_features: Option<&'a ResolvedFeatures>,\n    /// `true` while generating the dependencies for the standard library.\n    is_std: bool,\n    /// The high-level operation requested by the user.\n    /// Used for preventing from building lib thrice.\n    intent: UserIntent,\n    target_data: &'a RustcTargetData<'gctx>,\n    profiles: &'a Profiles,\n    interner: &'a UnitInterner,\n    // Units for `-Zrustdoc-scrape-examples`.\n    scrape_units: &'a [Unit],\n\n    /// A set of edges in `unit_dependencies` where (a, b) means that the\n    /// dependency from a to b was added purely because it was a dev-dependency.\n    /// This is used during `connect_run_custom_build_deps`.\n    dev_dependency_edges: HashSet<(Unit, Unit)>,\n}\n\n/// A boolean-like to indicate if a `Unit` is an artifact or not.\n#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]\npub enum IsArtifact {\n    Yes,\n    No,\n}\n\nimpl IsArtifact {\n    pub fn is_true(&self) -> bool {\n        matches!(self, IsArtifact::Yes)\n    }\n}\n\n/// Then entry point for building a dependency graph of compilation units.\n///\n/// You can find some information for arguments from doc of [`State`].\n#[tracing::instrument(skip_all)]\npub fn build_unit_dependencies<'a, 'gctx>(\n    ws: &'a Workspace<'gctx>,\n    package_set: &'a PackageSet<'gctx>,\n    resolve: &'a Resolve,\n    features: &'a ResolvedFeatures,\n    std_resolve: Option<&'a (Resolve, ResolvedFeatures)>,\n    roots: &[Unit],\n    scrape_units: &[Unit],\n    std_roots: &HashMap<CompileKind, Vec<Unit>>,\n    intent: UserIntent,\n    target_data: &'a RustcTargetData<'gctx>,\n    profiles: &'a Profiles,\n    interner: &'a UnitInterner,\n) -> CargoResult<UnitGraph> {\n    if roots.is_empty() {\n        // If -Zbuild-std, don't attach units if there is nothing to build.\n        // Otherwise, other parts of the code may be confused by seeing units\n        // in the dep graph without a root.\n        return Ok(HashMap::new());\n    }\n    let (std_resolve, std_features) = match std_resolve {\n        Some((r, f)) => (Some(r), Some(f)),\n        None => (None, None),\n    };\n    let mut state = State {\n        ws,\n        gctx: ws.gctx(),\n        unit_dependencies: HashMap::new(),\n        package_set,\n        usr_resolve: resolve,\n        usr_features: features,\n        std_resolve,\n        std_features,\n        is_std: false,\n        intent,\n        target_data,\n        profiles,\n        interner,\n        scrape_units,\n        dev_dependency_edges: HashSet::new(),\n    };\n\n    let std_unit_deps = calc_deps_of_std(&mut state, std_roots)?;\n\n    deps_of_roots(roots, &mut state)?;\n    super::links::validate_links(state.resolve(), &state.unit_dependencies)?;\n    // Hopefully there aren't any links conflicts with the standard library?\n\n    if let Some(std_unit_deps) = std_unit_deps {\n        attach_std_deps(&mut state, std_roots, std_unit_deps);\n    }\n\n    connect_run_custom_build_deps(&mut state);\n\n    // Dependencies are used in tons of places throughout the backend, many of\n    // which affect the determinism of the build itself. As a result be sure\n    // that dependency lists are always sorted to ensure we've always got a\n    // deterministic output.\n    for (unit, list) in &mut state.unit_dependencies {\n        let is_multiple_build_scripts_enabled = unit\n            .pkg\n            .manifest()\n            .unstable_features()\n            .require(Feature::multiple_build_scripts())\n            .is_ok();\n\n        if is_multiple_build_scripts_enabled {\n            list.sort_by_key(|unit_dep| {\n                if unit_dep.unit.target.is_custom_build() {\n                    // We do not sort build scripts to preserve the user-defined order.\n                    // In terms of determinism, we are assuming nothing interferes with order from when the user set it in `Cargo.toml` to here\n                    (0, None)\n                } else {\n                    (1, Some(unit_dep.clone()))\n                }\n            });\n        } else {\n            list.sort();\n        }\n    }\n    trace!(\"ALL UNIT DEPENDENCIES {:#?}\", state.unit_dependencies);\n\n    Ok(state.unit_dependencies)\n}\n\n/// Compute all the dependencies for the standard library.\nfn calc_deps_of_std(\n    state: &mut State<'_, '_>,\n    std_roots: &HashMap<CompileKind, Vec<Unit>>,\n) -> CargoResult<Option<UnitGraph>> {\n    if std_roots.is_empty() {\n        return Ok(None);\n    }\n    // Compute dependencies for the standard library.\n    state.is_std = true;\n    for roots in std_roots.values() {\n        deps_of_roots(roots, state)?;\n    }\n    state.is_std = false;\n    Ok(Some(std::mem::take(&mut state.unit_dependencies)))\n}\n\n/// Add the standard library units to the `unit_dependencies`.\nfn attach_std_deps(\n    state: &mut State<'_, '_>,\n    std_roots: &HashMap<CompileKind, Vec<Unit>>,\n    std_unit_deps: UnitGraph,\n) {\n    // Attach the standard library as a dependency of every target unit.\n    let mut found = false;\n    for (unit, deps) in state.unit_dependencies.iter_mut() {\n        if !unit.kind.is_host() && !unit.mode.is_run_custom_build() {\n            deps.extend(std_roots[&unit.kind].iter().map(|unit| UnitDep {\n                unit: unit.clone(),\n                unit_for: UnitFor::new_normal(unit.kind),\n                extern_crate_name: unit.pkg.name(),\n                dep_name: None,\n                // TODO: Does this `public` make sense?\n                public: true,\n                noprelude: true,\n                nounused: true,\n            }));\n            found = true;\n        }\n    }\n    // And also include the dependencies of the standard library itself. Don't\n    // include these if no units actually needed the standard library.\n    if found {\n        for (unit, deps) in std_unit_deps.into_iter() {\n            if let Some(other_unit) = state.unit_dependencies.insert(unit, deps) {\n                panic!(\"std unit collision with existing unit: {:?}\", other_unit);\n            }\n        }\n    }\n}\n\n/// Compute all the dependencies of the given root units.\n/// The result is stored in `state.unit_dependencies`.\nfn deps_of_roots(roots: &[Unit], state: &mut State<'_, '_>) -> CargoResult<()> {\n    for unit in roots.iter() {\n        // Dependencies of tests/benches should not have `panic` set.\n        // We check the user intent to see if we are running in `cargo test` in\n        // which case we ensure all dependencies have `panic` cleared, and\n        // avoid building the lib thrice (once with `panic`, once without, once\n        // for `--test`). In particular, the lib included for Doc tests and\n        // examples are `Build` mode here.\n        let root_compile_kind = unit.kind;\n        let unit_for = if unit.mode.is_any_test() || state.intent.is_rustc_test() {\n            if unit.target.proc_macro() {\n                // Special-case for proc-macros, which are forced to for-host\n                // since they need to link with the proc_macro crate.\n                UnitFor::new_host_test(state.gctx, root_compile_kind)\n            } else {\n                UnitFor::new_test(state.gctx, root_compile_kind)\n            }\n        } else if unit.target.is_custom_build() {\n            // This normally doesn't happen, except `clean` aggressively\n            // generates all units.\n            UnitFor::new_host(false, root_compile_kind)\n        } else if unit.target.proc_macro() {\n            UnitFor::new_host(true, root_compile_kind)\n        } else if unit.target.for_host() {\n            // Plugin should never have panic set.\n            UnitFor::new_compiler(root_compile_kind)\n        } else {\n            UnitFor::new_normal(root_compile_kind)\n        };\n        deps_of(unit, state, unit_for)?;\n    }\n\n    Ok(())\n}\n\n/// Compute the dependencies of a single unit, recursively computing all\n/// transitive dependencies.\n///\n/// The result is stored in `state.unit_dependencies`.\nfn deps_of(unit: &Unit, state: &mut State<'_, '_>, unit_for: UnitFor) -> CargoResult<()> {\n    // Currently the `unit_dependencies` map does not include `unit_for`. This should\n    // be safe for now. `TestDependency` only exists to clear the `panic`\n    // flag, and you'll never ask for a `unit` with `panic` set as a\n    // `TestDependency`. `CustomBuild` should also be fine since if the\n    // requested unit's settings are the same as `Any`, `CustomBuild` can't\n    // affect anything else in the hierarchy.\n    if !state.unit_dependencies.contains_key(unit) {\n        let unit_deps = compute_deps(unit, state, unit_for)?;\n        state\n            .unit_dependencies\n            .insert(unit.clone(), unit_deps.clone());\n        for unit_dep in unit_deps {\n            deps_of(&unit_dep.unit, state, unit_dep.unit_for)?;\n        }\n    }\n    Ok(())\n}\n\n/// Returns the direct unit dependencies for the given `Unit`.\nfn compute_deps(\n    unit: &Unit,\n    state: &mut State<'_, '_>,\n    unit_for: UnitFor,\n) -> CargoResult<Vec<UnitDep>> {\n    if unit.mode.is_run_custom_build() {\n        return compute_deps_custom_build(unit, unit_for, state);\n    } else if unit.mode.is_doc() {\n        // Note: this does not include doc test.\n        return compute_deps_doc(unit, state, unit_for);\n    }\n\n    let mut ret = Vec::new();\n    let mut dev_deps = Vec::new();\n    for (dep_pkg_id, deps) in state.deps(unit, unit_for) {\n        let Some(dep_lib) = calc_artifact_deps(unit, unit_for, dep_pkg_id, &deps, state, &mut ret)?\n        else {\n            continue;\n        };\n        let dep_pkg = state.get(dep_pkg_id);\n        let mode = check_or_build_mode(unit.mode, dep_lib);\n        let dep_unit_for = unit_for.with_dependency(unit, dep_lib, unit_for.root_compile_kind());\n\n        let start = ret.len();\n        if state.gctx.cli_unstable().dual_proc_macros\n            && dep_lib.proc_macro()\n            && !unit.kind.is_host()\n        {\n            let unit_dep = new_unit_dep(\n                state,\n                unit,\n                dep_pkg,\n                dep_lib,\n                dep_unit_for,\n                unit.kind,\n                mode,\n                IS_NO_ARTIFACT_DEP,\n            )?;\n            ret.push(unit_dep);\n            let unit_dep = new_unit_dep(\n                state,\n                unit,\n                dep_pkg,\n                dep_lib,\n                dep_unit_for,\n                CompileKind::Host,\n                mode,\n                IS_NO_ARTIFACT_DEP,\n            )?;\n            ret.push(unit_dep);\n        } else {\n            let unit_dep = new_unit_dep(\n                state,\n                unit,\n                dep_pkg,\n                dep_lib,\n                dep_unit_for,\n                unit.kind.for_target(dep_lib),\n                mode,\n                IS_NO_ARTIFACT_DEP,\n            )?;\n            ret.push(unit_dep);\n        }\n\n        // If the unit added was a dev-dependency unit, then record that in the\n        // dev-dependencies array. We'll add this to\n        // `state.dev_dependency_edges` at the end and process it later in\n        // `connect_run_custom_build_deps`.\n        if deps.iter().all(|d| !d.is_transitive()) {\n            for dep in ret[start..].iter() {\n                dev_deps.push((unit.clone(), dep.unit.clone()));\n            }\n        }\n    }\n    state.dev_dependency_edges.extend(dev_deps);\n\n    // If this target is a build script, then what we've collected so far is\n    // all we need. If this isn't a build script, then it depends on the\n    // build script if there is one.\n    if unit.target.is_custom_build() {\n        return Ok(ret);\n    }\n    ret.extend(\n        dep_build_script(unit, unit_for, state)?\n            .into_iter()\n            .flatten(),\n    );\n\n    // If this target is a binary, test, example, etc, then it depends on\n    // the library of the same package. The call to `resolve.deps` above\n    // didn't include `pkg` in the return values, so we need to special case\n    // it here and see if we need to push `(pkg, pkg_lib_target)`.\n    if unit.target.is_lib() && unit.mode != CompileMode::Doctest {\n        return Ok(ret);\n    }\n    ret.extend(maybe_lib(unit, state, unit_for)?);\n\n    // If any integration tests/benches are being run, make sure that\n    // binaries are built as well.\n    if !unit.mode.is_check()\n        && unit.mode.is_any_test()\n        && (unit.target.is_test() || unit.target.is_bench())\n    {\n        let id = unit.pkg.package_id();\n        ret.extend(\n            unit.pkg\n                .targets()\n                .iter()\n                .filter(|t| {\n                    // Skip binaries with required features that have not been selected.\n                    match t.required_features() {\n                        Some(rf) if t.is_bin() => {\n                            let features = resolve_all_features(\n                                state.resolve(),\n                                state.features(),\n                                state.package_set,\n                                id,\n                                HasDevUnits::No,\n                                &[unit.kind],\n                                state.target_data,\n                                ForceAllTargets::No,\n                            );\n                            rf.iter().all(|f| features.contains(f))\n                        }\n                        None if t.is_bin() => true,\n                        _ => false,\n                    }\n                })\n                .map(|t| {\n                    new_unit_dep(\n                        state,\n                        unit,\n                        &unit.pkg,\n                        t,\n                        UnitFor::new_normal(unit_for.root_compile_kind()),\n                        unit.kind.for_target(t),\n                        CompileMode::Build,\n                        IS_NO_ARTIFACT_DEP,\n                    )\n                })\n                .collect::<CargoResult<Vec<UnitDep>>>()?,\n        );\n    }\n\n    Ok(ret)\n}\n\n/// Find artifacts for all `deps` of `unit` and add units that build these artifacts\n/// to `ret`.\nfn calc_artifact_deps<'a>(\n    unit: &Unit,\n    unit_for: UnitFor,\n    dep_id: PackageId,\n    deps: &[&Dependency],\n    state: &State<'a, '_>,\n    ret: &mut Vec<UnitDep>,\n) -> CargoResult<Option<&'a Target>> {\n    let mut has_artifact_lib = false;\n    let mut maybe_non_artifact_lib = false;\n    let artifact_pkg = state.get(dep_id);\n    for dep in deps {\n        let Some(artifact) = dep.artifact() else {\n            maybe_non_artifact_lib = true;\n            continue;\n        };\n        has_artifact_lib |= artifact.is_lib();\n        // Custom build scripts (build/compile) never get artifact dependencies,\n        // but the run-build-script step does (where it is handled).\n        if !unit.target.is_custom_build() {\n            debug_assert!(\n                !unit.mode.is_run_custom_build(),\n                \"BUG: This should be handled in a separate branch\"\n            );\n            ret.extend(artifact_targets_to_unit_deps(\n                unit,\n                unit_for.with_artifact_features(artifact),\n                state,\n                artifact\n                    .target()\n                    .and_then(|t| match t {\n                        ArtifactTarget::BuildDependencyAssumeTarget => None,\n                        ArtifactTarget::Force(kind) => Some(CompileKind::Target(kind)),\n                    })\n                    .unwrap_or(unit.kind),\n                artifact_pkg,\n                dep,\n            )?);\n        }\n    }\n    if has_artifact_lib || maybe_non_artifact_lib {\n        Ok(artifact_pkg.targets().iter().find(|t| t.is_lib()))\n    } else {\n        Ok(None)\n    }\n}\n\n/// Returns the dependencies needed to run a build script.\n///\n/// The `unit` provided must represent an execution of a build script, and\n/// the returned set of units must all be run before `unit` is run.\nfn compute_deps_custom_build(\n    unit: &Unit,\n    unit_for: UnitFor,\n    state: &State<'_, '_>,\n) -> CargoResult<Vec<UnitDep>> {\n    if let Some(links) = unit.pkg.manifest().links() {\n        if unit.links_overrides.get(links).is_some() {\n            // Overridden build scripts don't have any dependencies.\n            return Ok(Vec::new());\n        }\n    }\n    // All dependencies of this unit should use profiles for custom builds.\n    // If this is a build script of a proc macro, make sure it uses host\n    // features.\n    let script_unit_for = unit_for.for_custom_build();\n    // When not overridden, then the dependencies to run a build script are:\n    //\n    // 1. Compiling the build script itself.\n    // 2. For each immediate dependency of our package which has a `links`\n    //    key, the execution of that build script.\n    //\n    // We don't have a great way of handling (2) here right now so this is\n    // deferred until after the graph of all unit dependencies has been\n    // constructed.\n    let compile_script_unit = new_unit_dep(\n        state,\n        unit,\n        &unit.pkg,\n        &unit.target,\n        script_unit_for,\n        // Build scripts always compiled for the host.\n        CompileKind::Host,\n        CompileMode::Build,\n        IS_NO_ARTIFACT_DEP,\n    )?;\n\n    let mut result = vec![compile_script_unit];\n\n    // Include any artifact dependencies.\n    //\n    // This is essentially the same as `calc_artifact_deps`, but there are some\n    // subtle differences that require this to be implemented differently.\n    //\n    // Produce units that build all required artifact kinds (like binaries,\n    // static libraries, etc) with the correct compile target.\n    //\n    // Computing the compile target for artifact units is more involved as it has to handle\n    // various target configurations specific to artifacts, like `target = \"target\"` and\n    // `target = \"<triple>\"`, which makes knowing the root units compile target\n    // `root_unit_compile_target` necessary.\n    let root_unit_compile_target = unit_for.root_compile_kind();\n    let unit_for = UnitFor::new_host(/*host_features*/ true, root_unit_compile_target);\n    for (dep_pkg_id, deps) in state.deps(unit, script_unit_for) {\n        for dep in deps {\n            if dep.kind() != DepKind::Build || dep.artifact().is_none() {\n                continue;\n            }\n            let artifact_pkg = state.get(dep_pkg_id);\n            let artifact = dep.artifact().expect(\"artifact dep\");\n            let resolved_artifact_compile_kind = artifact\n                .target()\n                .map(|target| target.to_resolved_compile_kind(root_unit_compile_target));\n\n            result.extend(artifact_targets_to_unit_deps(\n                unit,\n                unit_for.with_artifact_features_from_resolved_compile_kind(\n                    resolved_artifact_compile_kind,\n                ),\n                state,\n                resolved_artifact_compile_kind.unwrap_or(CompileKind::Host),\n                artifact_pkg,\n                dep,\n            )?);\n        }\n    }\n\n    Ok(result)\n}\n\n/// Given a `parent` unit containing a dependency `dep` whose package is `artifact_pkg`,\n/// find all targets in `artifact_pkg` which refer to the `dep`s artifact declaration\n/// and turn them into units.\n/// Due to the nature of artifact dependencies, a single dependency in a manifest can\n/// cause one or more targets to be build, for instance with\n/// `artifact = [\"bin:a\", \"bin:b\", \"staticlib\"]`, which is very different from normal\n/// dependencies which cause only a single unit to be created.\n///\n/// `compile_kind` is the computed kind for the future artifact unit\n/// dependency, only the caller can pick the correct one.\nfn artifact_targets_to_unit_deps(\n    parent: &Unit,\n    parent_unit_for: UnitFor,\n    state: &State<'_, '_>,\n    compile_kind: CompileKind,\n    artifact_pkg: &Package,\n    dep: &Dependency,\n) -> CargoResult<Vec<UnitDep>> {\n    let ret =\n        match_artifacts_kind_with_targets(dep, artifact_pkg.targets(), parent.pkg.name().as_str())?\n            .into_iter()\n            .flat_map(|(artifact_kind, target)| {\n                // We split target libraries into individual units, even though rustc is able\n                // to produce multiple kinds in a single invocation for the sole reason that\n                // each artifact kind has its own output directory, something we can't easily\n                // teach rustc for now.\n                match target.kind() {\n                    TargetKind::Lib(kinds) => Box::new(\n                        kinds\n                            .iter()\n                            .filter(move |tk| match (tk, artifact_kind) {\n                                (CrateType::Cdylib, ArtifactKind::Cdylib) => true,\n                                (CrateType::Staticlib, ArtifactKind::Staticlib) => true,\n                                _ => false,\n                            })\n                            .map(|target_kind| {\n                                new_unit_dep(\n                                    state,\n                                    parent,\n                                    artifact_pkg,\n                                    target\n                                        .clone()\n                                        .set_kind(TargetKind::Lib(vec![target_kind.clone()])),\n                                    parent_unit_for,\n                                    compile_kind,\n                                    CompileMode::Build,\n                                    dep.artifact(),\n                                )\n                            }),\n                    ) as Box<dyn Iterator<Item = _>>,\n                    _ => Box::new(std::iter::once(new_unit_dep(\n                        state,\n                        parent,\n                        artifact_pkg,\n                        target,\n                        parent_unit_for,\n                        compile_kind,\n                        CompileMode::Build,\n                        dep.artifact(),\n                    ))),\n                }\n            })\n            .collect::<Result<Vec<_>, _>>()?;\n    Ok(ret)\n}\n\n/// Returns the dependencies necessary to document a package.\nfn compute_deps_doc(\n    unit: &Unit,\n    state: &mut State<'_, '_>,\n    unit_for: UnitFor,\n) -> CargoResult<Vec<UnitDep>> {\n    // To document a library, we depend on dependencies actually being\n    // built. If we're documenting *all* libraries, then we also depend on\n    // the documentation of the library being built.\n    let mut ret = Vec::new();\n    for (id, deps) in state.deps(unit, unit_for) {\n        let Some(dep_lib) = calc_artifact_deps(unit, unit_for, id, &deps, state, &mut ret)? else {\n            continue;\n        };\n        let dep_pkg = state.get(id);\n        // Rustdoc only needs rmeta files for regular dependencies.\n        // However, for plugins/proc macros, deps should be built like normal.\n        let mode = check_or_build_mode(unit.mode, dep_lib);\n        let dep_unit_for = unit_for.with_dependency(unit, dep_lib, unit_for.root_compile_kind());\n        let lib_unit_dep = new_unit_dep(\n            state,\n            unit,\n            dep_pkg,\n            dep_lib,\n            dep_unit_for,\n            unit.kind.for_target(dep_lib),\n            mode,\n            IS_NO_ARTIFACT_DEP,\n        )?;\n        ret.push(lib_unit_dep);\n        if dep_lib.documented() && state.intent.wants_deps_docs() {\n            // Document this lib as well.\n            let doc_unit_dep = new_unit_dep(\n                state,\n                unit,\n                dep_pkg,\n                dep_lib,\n                dep_unit_for,\n                unit.kind.for_target(dep_lib),\n                unit.mode,\n                IS_NO_ARTIFACT_DEP,\n            )?;\n            ret.push(doc_unit_dep);\n        }\n    }\n\n    // Be sure to build/run the build script for documented libraries.\n    ret.extend(\n        dep_build_script(unit, unit_for, state)?\n            .into_iter()\n            .flatten(),\n    );\n\n    // If we document a binary/example, we need the library available.\n    if unit.target.is_bin() || unit.target.is_example() {\n        // build the lib\n        ret.extend(maybe_lib(unit, state, unit_for)?);\n        // and also the lib docs for intra-doc links\n        if let Some(lib) = unit\n            .pkg\n            .targets()\n            .iter()\n            .find(|t| t.is_linkable() && t.documented())\n        {\n            let dep_unit_for = unit_for.with_dependency(unit, lib, unit_for.root_compile_kind());\n            let lib_doc_unit = new_unit_dep(\n                state,\n                unit,\n                &unit.pkg,\n                lib,\n                dep_unit_for,\n                unit.kind.for_target(lib),\n                unit.mode,\n                IS_NO_ARTIFACT_DEP,\n            )?;\n            ret.push(lib_doc_unit);\n        }\n    }\n\n    // Add all units being scraped for examples as a dependency of top-level Doc units.\n    if state.ws.unit_needs_doc_scrape(unit) {\n        for scrape_unit in state.scrape_units.iter() {\n            let scrape_unit_for = UnitFor::new_normal(scrape_unit.kind);\n            deps_of(scrape_unit, state, scrape_unit_for)?;\n            ret.push(new_unit_dep(\n                state,\n                scrape_unit,\n                &scrape_unit.pkg,\n                &scrape_unit.target,\n                scrape_unit_for,\n                scrape_unit.kind,\n                scrape_unit.mode,\n                IS_NO_ARTIFACT_DEP,\n            )?);\n        }\n    }\n\n    Ok(ret)\n}\n\nfn maybe_lib(\n    unit: &Unit,\n    state: &mut State<'_, '_>,\n    unit_for: UnitFor,\n) -> CargoResult<Option<UnitDep>> {\n    unit.pkg\n        .targets()\n        .iter()\n        .find(|t| t.is_linkable())\n        .map(|t| {\n            let mode = check_or_build_mode(unit.mode, t);\n            let dep_unit_for = unit_for.with_dependency(unit, t, unit_for.root_compile_kind());\n            new_unit_dep(\n                state,\n                unit,\n                &unit.pkg,\n                t,\n                dep_unit_for,\n                unit.kind.for_target(t),\n                mode,\n                IS_NO_ARTIFACT_DEP,\n            )\n        })\n        .transpose()\n}\n\n/// If a build script is scheduled to be run for the package specified by\n/// `unit`, this function will return the unit to run that build script.\n///\n/// Overriding a build script simply means that the running of the build\n/// script itself doesn't have any dependencies, so even in that case a unit\n/// of work is still returned. `None` is only returned if the package has no\n/// build script.\nfn dep_build_script(\n    unit: &Unit,\n    unit_for: UnitFor,\n    state: &State<'_, '_>,\n) -> CargoResult<Option<Vec<UnitDep>>> {\n    Some(\n        unit.pkg\n            .targets()\n            .iter()\n            .filter(|t| t.is_custom_build())\n            .map(|t| {\n                // The profile stored in the Unit is the profile for the thing\n                // the custom build script is running for.\n                let profile = state.profiles.get_profile_run_custom_build(&unit.profile);\n                // UnitFor::for_custom_build is used because we want the `host` flag set\n                // for all of our build dependencies (so they all get\n                // build-override profiles), including compiling the build.rs\n                // script itself.\n                //\n                // If `is_for_host_features` here is `false`, that means we are a\n                // build.rs script for a normal dependency and we want to set the\n                // CARGO_FEATURE_* environment variables to the features as a\n                // normal dep.\n                //\n                // If `is_for_host_features` here is `true`, that means that this\n                // package is being used as a build dependency or proc-macro, and\n                // so we only want to set CARGO_FEATURE_* variables for the host\n                // side of the graph.\n                //\n                // Keep in mind that the RunCustomBuild unit and the Compile\n                // build.rs unit use the same features. This is because some\n                // people use `cfg!` and `#[cfg]` expressions to check for enabled\n                // features instead of just checking `CARGO_FEATURE_*` at runtime.\n                // In the case with the new feature resolver (decoupled host\n                // deps), and a shared dependency has different features enabled\n                // for normal vs. build, then the build.rs script will get\n                // compiled twice. I believe it is not feasible to only build it\n                // once because it would break a large number of scripts (they\n                // would think they have the wrong set of features enabled).\n                let script_unit_for = unit_for.for_custom_build();\n                new_unit_dep_with_profile(\n                    state,\n                    unit,\n                    &unit.pkg,\n                    t,\n                    script_unit_for,\n                    unit.kind,\n                    CompileMode::RunCustomBuild,\n                    profile,\n                    IS_NO_ARTIFACT_DEP,\n                )\n            })\n            .collect(),\n    )\n    .transpose()\n}\n\n/// Choose the correct mode for dependencies.\nfn check_or_build_mode(mode: CompileMode, target: &Target) -> CompileMode {\n    match mode {\n        CompileMode::Check { .. } | CompileMode::Doc { .. } | CompileMode::Docscrape => {\n            if target.for_host() {\n                // Plugin and proc macro targets should be compiled like\n                // normal.\n                CompileMode::Build\n            } else {\n                // Regular dependencies should not be checked with --test.\n                // Regular dependencies of doc targets should emit rmeta only.\n                CompileMode::Check { test: false }\n            }\n        }\n        _ => CompileMode::Build,\n    }\n}\n\n/// Create a new Unit for a dependency from `parent` to `pkg` and `target`.\nfn new_unit_dep(\n    state: &State<'_, '_>,\n    parent: &Unit,\n    pkg: &Package,\n    target: &Target,\n    unit_for: UnitFor,\n    kind: CompileKind,\n    mode: CompileMode,\n    artifact: Option<&Artifact>,\n) -> CargoResult<UnitDep> {\n    let is_local = pkg.package_id().source_id().is_path() && !state.is_std;\n    let profile = state.profiles.get_profile(\n        pkg.package_id(),\n        state.ws.is_member(pkg),\n        is_local,\n        unit_for,\n        kind,\n    );\n    new_unit_dep_with_profile(\n        state, parent, pkg, target, unit_for, kind, mode, profile, artifact,\n    )\n}\n\nfn new_unit_dep_with_profile(\n    state: &State<'_, '_>,\n    parent: &Unit,\n    pkg: &Package,\n    target: &Target,\n    unit_for: UnitFor,\n    kind: CompileKind,\n    mode: CompileMode,\n    profile: Profile,\n    artifact: Option<&Artifact>,\n) -> CargoResult<UnitDep> {\n    let (extern_crate_name, dep_name) = state.resolve().extern_crate_name_and_dep_name(\n        parent.pkg.package_id(),\n        pkg.package_id(),\n        target,\n    )?;\n    let public = state\n        .resolve()\n        .is_public_dep(parent.pkg.package_id(), pkg.package_id());\n    let features_for = unit_for.map_to_features_for(artifact);\n    let artifact_target = match features_for {\n        FeaturesFor::ArtifactDep(target) => Some(target),\n        _ => None,\n    };\n    let features = state.activated_features(pkg.package_id(), features_for);\n    let unit = state.interner.intern(\n        pkg,\n        target,\n        profile,\n        kind,\n        mode,\n        features,\n        state.target_data.info(kind).rustflags.clone(),\n        state.target_data.info(kind).rustdocflags.clone(),\n        state\n            .target_data\n            .target_config(kind)\n            .links_overrides\n            .clone(),\n        state.is_std,\n        /*dep_hash*/ 0,\n        artifact.map_or(IsArtifact::No, |_| IsArtifact::Yes),\n        artifact_target,\n        false,\n    );\n    Ok(UnitDep {\n        unit,\n        unit_for,\n        extern_crate_name,\n        dep_name,\n        public,\n        noprelude: false,\n        nounused: false,\n    })\n}\n\n/// Fill in missing dependencies for units of the `RunCustomBuild`\n///\n/// As mentioned above in `compute_deps_custom_build` each build script\n/// execution has two dependencies. The first is compiling the build script\n/// itself (already added) and the second is that all crates the package of the\n/// build script depends on with `links` keys, their build script execution. (a\n/// bit confusing eh?)\n///\n/// Here we take the entire `deps` map and add more dependencies from execution\n/// of one build script to execution of another build script.\nfn connect_run_custom_build_deps(state: &mut State<'_, '_>) {\n    let mut new_deps = Vec::new();\n\n    {\n        let state = &*state;\n        // First up build a reverse dependency map. This is a mapping of all\n        // `RunCustomBuild` known steps to the unit which depends on them. For\n        // example a library might depend on a build script, so this map will\n        // have the build script as the key and the library would be in the\n        // value's set.\n        let mut reverse_deps_map = HashMap::new();\n        for (unit, deps) in state.unit_dependencies.iter() {\n            for dep in deps {\n                if dep.unit.mode == CompileMode::RunCustomBuild {\n                    reverse_deps_map\n                        .entry(dep.unit.clone())\n                        .or_insert_with(HashSet::new)\n                        .insert(unit);\n                }\n            }\n        }\n\n        // Next, we take a look at all build scripts executions listed in the\n        // dependency map. Our job here is to take everything that depends on\n        // this build script (from our reverse map above) and look at the other\n        // package dependencies of these parents.\n        //\n        // If we depend on a linkable target and the build script mentions\n        // `links`, then we depend on that package's build script! Here we use\n        // `dep_build_script` to manufacture an appropriate build script unit to\n        // depend on.\n        for unit in state\n            .unit_dependencies\n            .keys()\n            .filter(|k| k.mode == CompileMode::RunCustomBuild)\n        {\n            // This list of dependencies all depend on `unit`, an execution of\n            // the build script.\n            let Some(reverse_deps) = reverse_deps_map.get(unit) else {\n                continue;\n            };\n\n            let to_add = reverse_deps\n                .iter()\n                // Get all sibling dependencies of `unit`\n                .flat_map(|reverse_dep| {\n                    state.unit_dependencies[reverse_dep]\n                        .iter()\n                        .map(move |a| (reverse_dep, a))\n                })\n                // Exclude ourself\n                .filter(|(_parent, other)| other.unit.pkg != unit.pkg)\n                // Only deps with `links`.\n                .filter(|(_parent, other)| {\n                    state.gctx.cli_unstable().any_build_script_metadata\n                        || (other.unit.target.is_linkable()\n                            && other.unit.pkg.manifest().links().is_some())\n                })\n                // Avoid cycles when using the doc --scrape-examples feature:\n                // Say a workspace has crates A and B where A has a build-dependency on B.\n                // The Doc units for A and B will have a dependency on the Docscrape for both A and B.\n                // So this would add a dependency from B-build to A-build, causing a cycle:\n                //   B (build) -> A (build) -> B(build)\n                // See the test scrape_examples_avoid_build_script_cycle for a concrete example.\n                // To avoid this cycle, we filter out the B -> A (docscrape) dependency.\n                .filter(|(_parent, other)| !other.unit.mode.is_doc_scrape())\n                // Skip dependencies induced via dev-dependencies since\n                // connections between `links` and build scripts only happens\n                // via normal dependencies. Otherwise since dev-dependencies can\n                // be cyclic we could have cyclic build-script executions.\n                .filter_map(move |(parent, other)| {\n                    if state\n                        .dev_dependency_edges\n                        .contains(&((*parent).clone(), other.unit.clone()))\n                    {\n                        None\n                    } else {\n                        Some(other)\n                    }\n                })\n                // Get the RunCustomBuild for other lib.\n                .filter_map(|other| {\n                    state.unit_dependencies[&other.unit]\n                        .iter()\n                        .find(|other_dep| other_dep.unit.mode == CompileMode::RunCustomBuild)\n                        .map(|other_dep| {\n                            let mut dep = other_dep.clone();\n                            let dep_name = other.dep_name.unwrap_or(other.unit.pkg.name());\n                            // Propagate the manifest dep name from the sibling edge.\n                            // The RunCustomBuild-RustCustomBuild edge is synthetic\n                            // and doesn't carry a usable dep name, but build script\n                            // metadata needs one for `CARGO_DEP_<dep_name>_*` env var\n                            dep.dep_name = Some(dep_name);\n                            dep\n                        })\n                })\n                .collect::<HashSet<_>>();\n\n            if !to_add.is_empty() {\n                // (RunCustomBuild, set(other RunCustomBuild))\n                new_deps.push((unit.clone(), to_add));\n            }\n        }\n    }\n\n    // And finally, add in all the missing dependencies!\n    for (unit, new_deps) in new_deps {\n        state\n            .unit_dependencies\n            .get_mut(&unit)\n            .unwrap()\n            .extend(new_deps);\n    }\n}\n\nimpl<'a, 'gctx> State<'a, 'gctx> {\n    /// Gets `std_resolve` during building std, otherwise `usr_resolve`.\n    fn resolve(&self) -> &'a Resolve {\n        if self.is_std {\n            self.std_resolve.unwrap()\n        } else {\n            self.usr_resolve\n        }\n    }\n\n    /// Gets `std_features` during building std, otherwise `usr_features`.\n    fn features(&self) -> &'a ResolvedFeatures {\n        if self.is_std {\n            self.std_features.unwrap()\n        } else {\n            self.usr_features\n        }\n    }\n\n    fn activated_features(\n        &self,\n        pkg_id: PackageId,\n        features_for: FeaturesFor,\n    ) -> Vec<InternedString> {\n        let features = self.features();\n        features.activated_features(pkg_id, features_for)\n    }\n\n    fn is_dep_activated(\n        &self,\n        pkg_id: PackageId,\n        features_for: FeaturesFor,\n        dep_name: InternedString,\n    ) -> bool {\n        self.features()\n            .is_dep_activated(pkg_id, features_for, dep_name)\n    }\n\n    fn get(&self, id: PackageId) -> &'a Package {\n        self.package_set\n            .get_one(id)\n            .unwrap_or_else(|_| panic!(\"expected {} to be downloaded\", id))\n    }\n\n    /// Returns a filtered set of dependencies for the given unit.\n    fn deps(&self, unit: &Unit, unit_for: UnitFor) -> Vec<(PackageId, Vec<&Dependency>)> {\n        let pkg_id = unit.pkg.package_id();\n        let kind = unit.kind;\n        self.resolve()\n            .deps(pkg_id)\n            .filter_map(|(id, deps)| {\n                assert!(!deps.is_empty());\n                let deps: Vec<_> = deps\n                    .iter()\n                    .filter(|dep| {\n                        // If this target is a build command, then we only want build\n                        // dependencies, otherwise we want everything *other than* build\n                        // dependencies.\n                        if unit.target.is_custom_build() != dep.is_build() {\n                            return false;\n                        }\n\n                        // If this dependency is **not** a transitive dependency, then it\n                        // only applies to test/example targets.\n                        if !dep.is_transitive()\n                            && !unit.target.is_test()\n                            && !unit.target.is_example()\n                            && !unit.mode.is_any_test()\n                        {\n                            return false;\n                        }\n\n                        // If this dependency is only available for certain platforms,\n                        // make sure we're only enabling it for that platform.\n                        if !self.target_data.dep_platform_activated(dep, kind) {\n                            return false;\n                        }\n\n                        // If this is an optional dependency, and the new feature resolver\n                        // did not enable it, don't include it.\n                        if dep.is_optional() {\n                            // This `unit_for` is from parent dep and *SHOULD* contains its own\n                            // artifact dep information inside `artifact_target_for_features`.\n                            // So, no need to map any artifact info from an incorrect `dep.artifact()`.\n                            let features_for = unit_for.map_to_features_for(IS_NO_ARTIFACT_DEP);\n                            if !self.is_dep_activated(pkg_id, features_for, dep.name_in_toml()) {\n                                return false;\n                            }\n                        }\n\n                        // If we've gotten past all that, then this dependency is\n                        // actually used!\n                        true\n                    })\n                    .collect();\n                if deps.is_empty() {\n                    None\n                } else {\n                    Some((id, deps))\n                }\n            })\n            .collect()\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/compiler/unit_graph.rs",
    "content": "//! Serialization of [`UnitGraph`] for unstable option [`--unit-graph`].\n//!\n//! [`--unit-graph`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#unit-graph\n\nuse cargo_util_schemas::core::PackageIdSpec;\n\nuse crate::GlobalContext;\nuse crate::core::Target;\nuse crate::core::compiler::Unit;\nuse crate::core::compiler::{CompileKind, CompileMode};\nuse crate::core::profiles::{Profile, UnitFor};\nuse crate::util::CargoResult;\nuse crate::util::interning::InternedString;\nuse std::collections::HashMap;\n\n/// The dependency graph of Units.\npub type UnitGraph = HashMap<Unit, Vec<UnitDep>>;\n\n/// A unit dependency.\n#[derive(Debug, Clone, Hash, Eq, PartialEq, PartialOrd, Ord)]\npub struct UnitDep {\n    /// The dependency unit.\n    pub unit: Unit,\n    /// The purpose of this dependency (a dependency for a test, or a build\n    /// script, etc.). Do not use this after the unit graph has been built.\n    pub unit_for: UnitFor,\n    /// The name the parent uses to refer to this dependency.\n    pub extern_crate_name: InternedString,\n    /// The dependency name as written in the manifest (including a rename).\n    ///\n    /// `None` means this edge does not carry a manifest dep name. For example,\n    /// std edges in build-std or synthetic edges for build script executions.\n    /// When `None`, the package name is typically used by callers as a fallback.\n    ///\n    /// This is mainly for Cargo-synthesized outputs\n    /// (artifact env vars and `CARGO_DEP_*` metadata env)\n    /// and is distinct from `extern_crate_name`.\n    pub dep_name: Option<InternedString>,\n    /// Whether or not this is a public dependency.\n    pub public: bool,\n    /// If `true`, the dependency should not be added to Rust's prelude.\n    pub noprelude: bool,\n    /// If `true`, the dependency will not trigger Rust lint.\n    pub nounused: bool,\n}\n\nconst VERSION: u32 = 1;\n\n#[derive(serde::Serialize)]\nstruct SerializedUnitGraph<'a> {\n    version: u32,\n    units: Vec<SerializedUnit<'a>>,\n    roots: Vec<usize>,\n}\n\n#[derive(serde::Serialize)]\nstruct SerializedUnit<'a> {\n    pkg_id: PackageIdSpec,\n    target: &'a Target,\n    profile: &'a Profile,\n    platform: CompileKind,\n    mode: CompileMode,\n    features: &'a Vec<InternedString>,\n    #[serde(skip_serializing_if = \"std::ops::Not::not\")] // hide for unstable build-std\n    is_std: bool,\n    dependencies: Vec<SerializedUnitDep>,\n}\n\n#[derive(serde::Serialize)]\nstruct SerializedUnitDep {\n    index: usize,\n    extern_crate_name: InternedString,\n    // This is only set on nightly since it is unstable.\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    public: Option<bool>,\n    // This is only set on nightly since it is unstable.\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    noprelude: Option<bool>,\n    // This is only set on nightly since it is unstable.\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    nounused: Option<bool>,\n    // Intentionally not including `unit_for` because it is a low-level\n    // internal detail that is mostly used for building the graph.\n}\n\n/// Outputs a JSON serialization of [`UnitGraph`] for given `root_units`\n/// to the standard output.\npub fn emit_serialized_unit_graph(\n    root_units: &[Unit],\n    unit_graph: &UnitGraph,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let mut units: Vec<(&Unit, &Vec<UnitDep>)> = unit_graph.iter().collect();\n    units.sort_unstable();\n    // Create a map for quick lookup for dependencies.\n    let indices: HashMap<&Unit, usize> = units\n        .iter()\n        .enumerate()\n        .map(|(i, val)| (val.0, i))\n        .collect();\n    let roots = root_units.iter().map(|root| indices[root]).collect();\n    let ser_units = units\n        .iter()\n        .map(|(unit, unit_deps)| {\n            let dependencies = unit_deps\n                .iter()\n                .map(|unit_dep| {\n                    // https://github.com/rust-lang/rust/issues/64260 when stabilized.\n                    let (public, noprelude, nounused) = if gctx.nightly_features_allowed {\n                        (\n                            Some(unit_dep.public),\n                            Some(unit_dep.noprelude),\n                            Some(unit_dep.nounused),\n                        )\n                    } else {\n                        (None, None, None)\n                    };\n                    SerializedUnitDep {\n                        index: indices[&unit_dep.unit],\n                        extern_crate_name: unit_dep.extern_crate_name,\n                        public,\n                        noprelude,\n                        nounused,\n                    }\n                })\n                .collect();\n            SerializedUnit {\n                pkg_id: unit.pkg.package_id().to_spec(),\n                target: &unit.target,\n                profile: &unit.profile,\n                platform: unit.kind,\n                mode: unit.mode,\n                features: &unit.features,\n                is_std: unit.is_std,\n                dependencies,\n            }\n        })\n        .collect();\n\n    gctx.shell().print_json(&SerializedUnitGraph {\n        version: VERSION,\n        units: ser_units,\n        roots,\n    })\n}\n"
  },
  {
    "path": "src/cargo/core/dependency.rs",
    "content": "use cargo_platform::Platform;\nuse semver::VersionReq;\nuse serde::Serialize;\nuse serde::ser;\nuse std::borrow::Cow;\nuse std::fmt;\nuse std::fmt::{Display, Formatter};\nuse std::path::{Path, PathBuf};\nuse std::sync::Arc;\nuse tracing::trace;\n\nuse crate::core::compiler::{CompileKind, CompileTarget};\nuse crate::core::{CliUnstable, Feature, Features, PackageId, SourceId, Summary};\nuse crate::util::OptVersionReq;\nuse crate::util::context::Definition;\nuse crate::util::errors::CargoResult;\nuse crate::util::interning::InternedString;\n\n/// Information about a dependency requested by a Cargo manifest.\n/// Cheap to copy.\n#[derive(PartialEq, Eq, Hash, Clone, Debug)]\npub struct Dependency {\n    inner: Arc<Inner>,\n}\n\n/// The data underlying a `Dependency`.\n#[derive(PartialEq, Eq, Hash, Clone, Debug)]\nstruct Inner {\n    name: InternedString,\n    source_id: SourceId,\n    /// Source ID for the registry as specified in the manifest.\n    ///\n    /// This will be None if it is not specified (crates.io dependency).\n    /// This is different from `source_id` for example when both a `path` and\n    /// `registry` is specified. Or in the case of a crates.io dependency,\n    /// `source_id` will be crates.io and this will be None.\n    registry_id: Option<SourceId>,\n    req: OptVersionReq,\n    specified_req: bool,\n    kind: DepKind,\n    only_match_name: bool,\n    explicit_name_in_toml: Option<InternedString>,\n\n    optional: bool,\n    public: bool,\n    default_features: bool,\n    features: Vec<InternedString>,\n    // The presence of this information turns a dependency into an artifact dependency.\n    artifact: Option<Artifact>,\n\n    // This dependency should be used only for this platform.\n    // `None` means *all platforms*.\n    platform: Option<Platform>,\n}\n\n#[derive(Serialize)]\npub struct SerializedDependency {\n    name: InternedString,\n    source: SourceId,\n    req: String,\n    kind: DepKind,\n    rename: Option<InternedString>,\n\n    optional: bool,\n    uses_default_features: bool,\n    features: Vec<InternedString>,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    artifact: Option<Artifact>,\n    target: Option<Platform>,\n    /// The registry URL this dependency is from.\n    /// If None, then it comes from the default registry (crates.io).\n    registry: Option<String>,\n\n    /// The file system path for a local path dependency.\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    path: Option<PathBuf>,\n\n    /// `public` flag is unset if `-Zpublic-dependency` is not enabled\n    ///\n    /// Once that feature is stabilized, `public` will not need to be `Option`\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    public: Option<bool>,\n}\n\n#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug, Copy)]\npub enum DepKind {\n    Normal,\n    Development,\n    Build,\n}\n\nimpl DepKind {\n    pub fn kind_table(&self) -> &'static str {\n        match self {\n            DepKind::Normal => \"dependencies\",\n            DepKind::Development => \"dev-dependencies\",\n            DepKind::Build => \"build-dependencies\",\n        }\n    }\n}\n\nimpl ser::Serialize for DepKind {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        match *self {\n            DepKind::Normal => None,\n            DepKind::Development => Some(\"dev\"),\n            DepKind::Build => Some(\"build\"),\n        }\n        .serialize(s)\n    }\n}\n\nimpl Dependency {\n    /// Attempt to create a `Dependency` from an entry in the manifest.\n    pub fn parse(\n        name: impl Into<InternedString>,\n        version: Option<&str>,\n        source_id: SourceId,\n    ) -> CargoResult<Dependency> {\n        let name = name.into();\n        let (specified_req, version_req) = match version {\n            Some(v) => match VersionReq::parse(v) {\n                Ok(req) => (true, OptVersionReq::Req(req)),\n                Err(err) => {\n                    return Err(anyhow::Error::new(err).context(format!(\n                        \"failed to parse the version requirement `{}` for dependency `{}`\",\n                        v, name,\n                    )));\n                }\n            },\n            None => (false, OptVersionReq::Any),\n        };\n\n        let mut ret = Dependency::new_override(name, source_id);\n        {\n            let ptr = Arc::make_mut(&mut ret.inner);\n            ptr.only_match_name = false;\n            ptr.req = version_req;\n            ptr.specified_req = specified_req;\n        }\n        Ok(ret)\n    }\n\n    pub fn new_override(name: InternedString, source_id: SourceId) -> Dependency {\n        assert!(!name.is_empty());\n        Dependency {\n            inner: Arc::new(Inner {\n                name,\n                source_id,\n                registry_id: None,\n                req: OptVersionReq::Any,\n                kind: DepKind::Normal,\n                only_match_name: true,\n                optional: false,\n                public: false,\n                features: Vec::new(),\n                default_features: true,\n                specified_req: false,\n                platform: None,\n                explicit_name_in_toml: None,\n                artifact: None,\n            }),\n        }\n    }\n\n    pub fn serialized(\n        &self,\n        unstable_flags: &CliUnstable,\n        features: &Features,\n    ) -> SerializedDependency {\n        SerializedDependency {\n            name: self.package_name(),\n            source: self.source_id(),\n            req: self.version_req().to_string(),\n            kind: self.kind(),\n            optional: self.is_optional(),\n            uses_default_features: self.uses_default_features(),\n            features: self.features().to_vec(),\n            target: self.inner.platform.clone(),\n            rename: self.explicit_name_in_toml(),\n            registry: self.registry_id().as_ref().map(|sid| sid.url().to_string()),\n            path: self.source_id().local_path(),\n            artifact: self.inner.artifact.clone(),\n            public: if unstable_flags.public_dependency\n                || features.is_enabled(Feature::public_dependency())\n            {\n                Some(self.inner.public)\n            } else {\n                None\n            },\n        }\n    }\n\n    pub fn version_req(&self) -> &OptVersionReq {\n        &self.inner.req\n    }\n\n    /// This is the name of this `Dependency` as listed in `Cargo.toml`.\n    ///\n    /// Or in other words, this is what shows up in the `[dependencies]` section\n    /// on the left hand side. This is *not* the name of the package that's\n    /// being depended on as the dependency can be renamed. For that use\n    /// `package_name` below.\n    ///\n    /// Both of the dependencies below return `foo` for `name_in_toml`:\n    ///\n    /// ```toml\n    /// [dependencies]\n    /// foo = \"0.1\"\n    /// ```\n    ///\n    /// and ...\n    ///\n    /// ```toml\n    /// [dependencies]\n    /// foo = { version = \"0.1\", package = 'bar' }\n    /// ```\n    pub fn name_in_toml(&self) -> InternedString {\n        self.explicit_name_in_toml().unwrap_or(self.inner.name)\n    }\n\n    /// The name of the package that this `Dependency` depends on.\n    ///\n    /// Usually this is what's written on the left hand side of a dependencies\n    /// section, but it can also be renamed via the `package` key.\n    ///\n    /// Both of the dependencies below return `foo` for `package_name`:\n    ///\n    /// ```toml\n    /// [dependencies]\n    /// foo = \"0.1\"\n    /// ```\n    ///\n    /// and ...\n    ///\n    /// ```toml\n    /// [dependencies]\n    /// bar = { version = \"0.1\", package = 'foo' }\n    /// ```\n    pub fn package_name(&self) -> InternedString {\n        self.inner.name\n    }\n\n    pub fn source_id(&self) -> SourceId {\n        self.inner.source_id\n    }\n\n    pub fn registry_id(&self) -> Option<SourceId> {\n        self.inner.registry_id\n    }\n\n    pub fn set_registry_id(&mut self, registry_id: SourceId) -> &mut Dependency {\n        Arc::make_mut(&mut self.inner).registry_id = Some(registry_id);\n        self\n    }\n\n    pub fn kind(&self) -> DepKind {\n        self.inner.kind\n    }\n\n    pub fn is_public(&self) -> bool {\n        self.inner.public\n    }\n\n    /// Sets whether the dependency is public.\n    pub fn set_public(&mut self, public: bool) -> &mut Dependency {\n        if public {\n            // Setting 'public' only makes sense for normal dependencies\n            assert_eq!(self.kind(), DepKind::Normal);\n        }\n        Arc::make_mut(&mut self.inner).public = public;\n        self\n    }\n\n    pub fn specified_req(&self) -> bool {\n        self.inner.specified_req\n    }\n\n    /// If none, this dependencies must be built for all platforms.\n    /// If some, it must only be built for the specified platform.\n    pub fn platform(&self) -> Option<&Platform> {\n        self.inner.platform.as_ref()\n    }\n\n    /// The renamed name of this dependency, if any.\n    ///\n    /// If the `package` key is used in `Cargo.toml` then this returns the same\n    /// value as `name_in_toml`.\n    pub fn explicit_name_in_toml(&self) -> Option<InternedString> {\n        self.inner.explicit_name_in_toml\n    }\n\n    pub fn set_kind(&mut self, kind: DepKind) -> &mut Dependency {\n        if self.is_public() {\n            // Setting 'public' only makes sense for normal dependencies\n            assert_eq!(kind, DepKind::Normal);\n        }\n        Arc::make_mut(&mut self.inner).kind = kind;\n        self\n    }\n\n    /// Sets the list of features requested for the package.\n    pub fn set_features(\n        &mut self,\n        features: impl IntoIterator<Item = impl Into<InternedString>>,\n    ) -> &mut Dependency {\n        Arc::make_mut(&mut self.inner).features = features.into_iter().map(|s| s.into()).collect();\n        self\n    }\n\n    /// Sets whether the dependency requests default features of the package.\n    pub fn set_default_features(&mut self, default_features: bool) -> &mut Dependency {\n        Arc::make_mut(&mut self.inner).default_features = default_features;\n        self\n    }\n\n    /// Sets whether the dependency is optional.\n    pub fn set_optional(&mut self, optional: bool) -> &mut Dependency {\n        Arc::make_mut(&mut self.inner).optional = optional;\n        self\n    }\n\n    /// Sets the source ID for this dependency.\n    pub fn set_source_id(&mut self, id: SourceId) -> &mut Dependency {\n        Arc::make_mut(&mut self.inner).source_id = id;\n        self\n    }\n\n    /// Sets the version requirement for this dependency.\n    pub fn set_version_req(&mut self, req: OptVersionReq) -> &mut Dependency {\n        Arc::make_mut(&mut self.inner).req = req;\n        self\n    }\n\n    pub fn set_platform(&mut self, platform: Option<Platform>) -> &mut Dependency {\n        Arc::make_mut(&mut self.inner).platform = platform;\n        self\n    }\n\n    pub fn set_explicit_name_in_toml(\n        &mut self,\n        name: impl Into<InternedString>,\n    ) -> &mut Dependency {\n        Arc::make_mut(&mut self.inner).explicit_name_in_toml = Some(name.into());\n        self\n    }\n\n    /// Locks this dependency to depending on the specified package ID.\n    pub fn lock_to(&mut self, id: PackageId) -> &mut Dependency {\n        assert_eq!(self.inner.source_id, id.source_id());\n        trace!(\n            \"locking dep from `{}` with `{}` at {} to {}\",\n            self.package_name(),\n            self.version_req(),\n            self.source_id(),\n            id\n        );\n        let me = Arc::make_mut(&mut self.inner);\n        me.req.lock_to(id.version());\n\n        // Only update the `precise` of this source to preserve other\n        // information about dependency's source which may not otherwise be\n        // tested during equality/hashing.\n        me.source_id = me.source_id.with_precise_from(id.source_id());\n        self\n    }\n\n    /// Locks this dependency to a specified version.\n    ///\n    /// Mainly used in dependency patching like `[patch]` or `[replace]`, which\n    /// doesn't need to lock the entire dependency to a specific [`PackageId`].\n    pub fn lock_version(&mut self, version: &semver::Version) -> &mut Dependency {\n        let me = Arc::make_mut(&mut self.inner);\n        me.req.lock_to(version);\n        self\n    }\n\n    /// Returns `true` if this is a \"locked\" dependency. Basically a locked\n    /// dependency has an exact version req, but not vice versa.\n    pub fn is_locked(&self) -> bool {\n        self.inner.req.is_locked()\n    }\n\n    /// Returns `false` if the dependency is only used to build the local package.\n    pub fn is_transitive(&self) -> bool {\n        match self.inner.kind {\n            DepKind::Normal | DepKind::Build => true,\n            DepKind::Development => false,\n        }\n    }\n\n    pub fn is_build(&self) -> bool {\n        matches!(self.inner.kind, DepKind::Build)\n    }\n\n    pub fn is_optional(&self) -> bool {\n        self.inner.optional\n    }\n\n    /// Returns `true` if the default features of the dependency are requested.\n    pub fn uses_default_features(&self) -> bool {\n        self.inner.default_features\n    }\n    /// Returns the list of features that are requested by the dependency.\n    pub fn features(&self) -> &[InternedString] {\n        &self.inner.features\n    }\n\n    /// Returns `true` if the package (`sum`) can fulfill this dependency request.\n    pub fn matches(&self, sum: &Summary) -> bool {\n        self.matches_id(sum.package_id())\n    }\n\n    pub fn matches_prerelease(&self, sum: &Summary) -> bool {\n        let id = sum.package_id();\n        self.inner.name == id.name()\n            && (self.inner.only_match_name\n                || (self.inner.req.matches_prerelease(id.version())\n                    && self.inner.source_id == id.source_id()))\n    }\n\n    /// Returns `true` if the package (`id`) can fulfill this dependency request.\n    pub fn matches_ignoring_source(&self, id: PackageId) -> bool {\n        self.package_name() == id.name() && self.version_req().matches(id.version())\n    }\n\n    /// Returns `true` if the package (`id`) can fulfill this dependency request.\n    pub fn matches_id(&self, id: PackageId) -> bool {\n        self.inner.name == id.name()\n            && (self.inner.only_match_name\n                || (self.inner.req.matches(id.version()) && self.inner.source_id == id.source_id()))\n    }\n\n    pub fn map_source(mut self, to_replace: SourceId, replace_with: SourceId) -> Dependency {\n        if self.source_id() == to_replace {\n            self.set_source_id(replace_with);\n        }\n        self\n    }\n\n    pub(crate) fn set_artifact(&mut self, artifact: Artifact) {\n        Arc::make_mut(&mut self.inner).artifact = Some(artifact);\n    }\n\n    pub fn artifact(&self) -> Option<&Artifact> {\n        self.inner.artifact.as_ref()\n    }\n\n    /// Dependencies are potential rust libs if they are not artifacts or they are an\n    /// artifact which allows to be seen as library.\n    /// Previously, every dependency was potentially seen as library.\n    pub(crate) fn maybe_lib(&self) -> bool {\n        self.artifact().map(|a| a.is_lib).unwrap_or(true)\n    }\n}\n\n/// The presence of an artifact turns an ordinary dependency into an Artifact dependency.\n/// As such, it will build one or more different artifacts of possibly various kinds\n/// for making them available at build time for rustc invocations or runtime\n/// for build scripts.\n///\n/// This information represents a requirement in the package this dependency refers to.\n#[derive(PartialEq, Eq, Hash, Clone, Debug)]\npub struct Artifact {\n    inner: Arc<Vec<ArtifactKind>>,\n    is_lib: bool,\n    target: Option<ArtifactTarget>,\n}\n\n#[derive(Serialize)]\npub struct SerializedArtifact<'a> {\n    kinds: &'a [ArtifactKind],\n    lib: bool,\n    target: Option<&'a str>,\n}\n\nimpl ser::Serialize for Artifact {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        SerializedArtifact {\n            kinds: self.kinds(),\n            lib: self.is_lib,\n            target: self.target.as_ref().map(ArtifactTarget::as_str),\n        }\n        .serialize(s)\n    }\n}\n\nimpl Artifact {\n    pub(crate) fn parse(\n        artifacts: &[impl AsRef<str>],\n        is_lib: bool,\n        target: Option<&str>,\n        unstable_json: bool,\n    ) -> CargoResult<Self> {\n        let kinds = ArtifactKind::validate(\n            artifacts\n                .iter()\n                .map(|s| ArtifactKind::parse(s.as_ref()))\n                .collect::<Result<Vec<_>, _>>()?,\n        )?;\n        Ok(Artifact {\n            inner: Arc::new(kinds),\n            is_lib,\n            target: target\n                .map(|name| ArtifactTarget::parse(name, unstable_json))\n                .transpose()?,\n        })\n    }\n\n    pub fn kinds(&self) -> &[ArtifactKind] {\n        &self.inner\n    }\n\n    pub fn is_lib(&self) -> bool {\n        self.is_lib\n    }\n\n    pub fn target(&self) -> Option<ArtifactTarget> {\n        self.target\n    }\n}\n\n#[derive(PartialEq, Eq, Hash, Copy, Clone, Ord, PartialOrd, Debug)]\npub enum ArtifactTarget {\n    /// Only applicable to build-dependencies, causing them to be built\n    /// for the given target (i.e. via `--target <triple>`) instead of for the host.\n    /// Has no effect on non-build dependencies.\n    BuildDependencyAssumeTarget,\n    /// The name of the platform triple, like `x86_64-apple-darwin`, that this\n    /// artifact will always be built for, no matter if it is a build,\n    /// normal or dev dependency.\n    Force(CompileTarget),\n}\n\nimpl ArtifactTarget {\n    pub fn parse(target: &str, unstable_json: bool) -> CargoResult<ArtifactTarget> {\n        Ok(match target {\n            \"target\" => ArtifactTarget::BuildDependencyAssumeTarget,\n            name => ArtifactTarget::Force(CompileTarget::new(name, unstable_json)?),\n        })\n    }\n\n    pub fn as_str(&self) -> &str {\n        match self {\n            ArtifactTarget::BuildDependencyAssumeTarget => \"target\",\n            ArtifactTarget::Force(target) => target.rustc_target().as_str(),\n        }\n    }\n\n    pub fn to_compile_kind(&self) -> Option<CompileKind> {\n        self.to_compile_target().map(CompileKind::Target)\n    }\n\n    pub fn to_compile_target(&self) -> Option<CompileTarget> {\n        match self {\n            ArtifactTarget::BuildDependencyAssumeTarget => None,\n            ArtifactTarget::Force(target) => Some(*target),\n        }\n    }\n\n    pub(crate) fn to_resolved_compile_kind(\n        &self,\n        root_unit_compile_kind: CompileKind,\n    ) -> CompileKind {\n        match self {\n            ArtifactTarget::Force(target) => CompileKind::Target(*target),\n            ArtifactTarget::BuildDependencyAssumeTarget => root_unit_compile_kind,\n        }\n    }\n\n    pub(crate) fn to_resolved_compile_target(\n        &self,\n        root_unit_compile_kind: CompileKind,\n    ) -> Option<CompileTarget> {\n        match self.to_resolved_compile_kind(root_unit_compile_kind) {\n            CompileKind::Host => None,\n            CompileKind::Target(target) => Some(target),\n        }\n    }\n}\n\n#[derive(PartialEq, Eq, Hash, Copy, Clone, Ord, PartialOrd, Debug)]\npub enum ArtifactKind {\n    /// We represent all binaries in this dependency\n    AllBinaries,\n    /// We represent a single binary\n    SelectedBinary(InternedString),\n    Cdylib,\n    Staticlib,\n}\n\nimpl ser::Serialize for ArtifactKind {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        self.as_str().serialize(s)\n    }\n}\n\nimpl fmt::Display for ArtifactKind {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(&self.as_str())\n    }\n}\n\nimpl ArtifactKind {\n    /// Returns a string of crate type of the artifact being built.\n    ///\n    /// Note that the name of `SelectedBinary` would be dropped and displayed as `bin`.\n    pub fn crate_type(&self) -> &'static str {\n        match self {\n            ArtifactKind::AllBinaries | ArtifactKind::SelectedBinary(_) => \"bin\",\n            ArtifactKind::Cdylib => \"cdylib\",\n            ArtifactKind::Staticlib => \"staticlib\",\n        }\n    }\n\n    pub fn as_str(&self) -> Cow<'static, str> {\n        match *self {\n            ArtifactKind::SelectedBinary(name) => format!(\"bin:{}\", name.as_str()).into(),\n            _ => self.crate_type().into(),\n        }\n    }\n\n    pub fn parse(kind: &str) -> CargoResult<Self> {\n        Ok(match kind {\n            \"bin\" => ArtifactKind::AllBinaries,\n            \"cdylib\" => ArtifactKind::Cdylib,\n            \"staticlib\" => ArtifactKind::Staticlib,\n            _ => {\n                return kind\n                    .strip_prefix(\"bin:\")\n                    .map(|bin_name| ArtifactKind::SelectedBinary(bin_name.into()))\n                    .ok_or_else(|| {\n                        anyhow::anyhow!(\"'{}' is not a valid artifact specifier\", kind)\n                    });\n            }\n        })\n    }\n\n    fn validate(kinds: Vec<ArtifactKind>) -> CargoResult<Vec<ArtifactKind>> {\n        if kinds.iter().any(|k| matches!(k, ArtifactKind::AllBinaries))\n            && kinds\n                .iter()\n                .any(|k| matches!(k, ArtifactKind::SelectedBinary(_)))\n        {\n            anyhow::bail!(\n                \"Cannot specify both 'bin' and 'bin:<name>' binary artifacts, as 'bin' selects all available binaries.\"\n            );\n        }\n        let mut kinds_without_dupes = kinds.clone();\n        kinds_without_dupes.sort();\n        kinds_without_dupes.dedup();\n        let num_dupes = kinds.len() - kinds_without_dupes.len();\n        if num_dupes != 0 {\n            anyhow::bail!(\n                \"Found {} duplicate binary artifact{}\",\n                num_dupes,\n                (num_dupes > 1).then(|| \"s\").unwrap_or(\"\")\n            );\n        }\n        Ok(kinds)\n    }\n}\n\n/// Patch is a dependency override that knows where it has been defined.\n/// See [`PatchLocation`] for possible locations.\n#[derive(Clone, Debug)]\npub struct Patch {\n    pub dep: Dependency,\n    pub loc: PatchLocation,\n}\n\n/// Place where a [`Patch`] has been defined.\n#[derive(Clone, Debug)]\npub enum PatchLocation {\n    /// Defined in a manifest.\n    Manifest(PathBuf),\n    /// Defined in cargo configuration.\n    Config(Definition),\n}\n\nimpl Display for PatchLocation {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        match self {\n            PatchLocation::Manifest(p) => Path::display(p).fmt(f),\n            PatchLocation::Config(def) => def.fmt(f),\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/features.rs",
    "content": "//! Support for nightly features in Cargo itself.\n//!\n//! This file is the version of `feature_gate.rs` in upstream Rust for Cargo\n//! itself and is intended to be the avenue for which new features in Cargo are\n//! gated by default and then eventually stabilized. All known stable and\n//! unstable features are tracked in this file.\n//!\n//! If you're reading this then you're likely interested in adding a feature to\n//! Cargo, and the good news is that it shouldn't be too hard! First determine\n//! how the feature should be gated:\n//!\n//! * Error when the feature is used without the gate\n//!   * Required if ignoring the feature violates the users intent in non-superficial ways\n//!   * A low-effort / safe way to protect the user from being broken if the format of the feature changes in\n//!     incompatible was (can be worked around)\n//!   * Good for: CLI (gate: `-Zunstable-options` or `-Z` if combined with other changes), `Cargo.toml` (gate: `cargo-features`)\n//! * Warn that the feature is ignored due to lack of the gate\n//!   * For if you could opt-in to the unimplemented feature on Cargo today and Cargo would\n//!     operate just fine\n//!   * If gate is not enabled, prefer to warn if the format of the feature is incompatible\n//!     (instead of error or ignore)\n//!   * Good for: `Cargo.toml`, `.cargo/config.toml`, `config.json` index file (gate: `-Z`)\n//! * Ignore the feature that is used without a gate\n//!   * For when ignoring the feature has so little impact that annoying the user is not worth it\n//!     (e.g. a config field that changes Cargo's terminal output)\n//!   * For behavior changes without an interface (e.g. the resolver)\n//!   * Good for: `.cargo/config.toml`, `config.json` index file (gate: `-Z`)\n//!\n//! For features that touch multiple parts of Cargo, multiple feature gating strategies (error,\n//! warn, ignore) and mechanisms (`-Z`, `cargo-features`) may be used.\n//!\n//! When adding new tests for your feature, usually the tests should go into a\n//! new module of the testsuite named after the feature. See\n//! <https://doc.crates.io/contrib/tests/writing.html> for more information on\n//! writing tests. Particularly, check out the \"Testing Nightly Features\"\n//! section for testing unstable features. Be sure to test the feature gate itself.\n//!\n//! After you have added your feature, be sure to update the unstable\n//! documentation at `src/doc/src/reference/unstable.md` to include a short\n//! description of how to use your new feature.\n//!\n//! And hopefully that's it!\n//!\n//! ## `cargo-features`\n//!\n//! The steps for adding new Cargo.toml syntax are:\n//!\n//! 1. Add the cargo-features unstable gate. Search the code below for \"look here\" to\n//!    find the [`features!`] macro invocation and add your feature to the list.\n//!\n//! 2. Update the Cargo.toml parsing code to handle your new feature.\n//!\n//! 3. Wherever you added the new parsing code, call\n//!    `features.require(Feature::my_feature_name())?` if the new syntax is\n//!    used. This will return an error if the user hasn't listed the feature\n//!    in `cargo-features` or this is not the nightly channel.\n//!\n//! ## `-Z unstable-options`\n//!\n//! `-Z unstable-options` is intended to force the user to opt-in to new CLI\n//! flags, options, and new subcommands.\n//!\n//! The steps to add a new command-line option are:\n//!\n//! 1. Add the option to the CLI parsing code. In the help text, be sure to\n//!    include `(unstable)` to note that this is an unstable option.\n//! 2. Where the CLI option is loaded, be sure to call\n//!    [`CliUnstable::fail_if_stable_opt`]. This will return an error if `-Z\n//!    unstable options` was not passed.\n//!\n//! ## `-Z` options\n//!\n//! New `-Z` options cover all other functionality that isn't covered with\n//! `cargo-features` or `-Z unstable-options`.\n//!\n//! The steps to add a new `-Z` option are:\n//!\n//! 1. Add the option to the [`CliUnstable`] struct in the macro invocation of\n//!    [`unstable_cli_options!`]. Flags can take an optional value if you want.\n//! 2. Update the [`CliUnstable::add`] function to parse the flag.\n//! 3. Wherever the new functionality is implemented, call\n//!    [`GlobalContext::cli_unstable`] to get an instance of [`CliUnstable`]\n//!    and check if the option has been enabled on the [`CliUnstable`] instance.\n//!    Nightly gating is already handled, so no need to worry about that.\n//!    If warning when feature is used without the gate, be sure to gracefully degrade (with a\n//!    warning) when the `Cargo.toml` / `.cargo/config.toml` field usage doesn't match the\n//!    schema.\n//! 4. For any `Cargo.toml` fields, strip them in [`prepare_for_publish`] if the gate isn't set\n//!\n//! ## Stabilization\n//!\n//! For the stabilization process, see\n//! <https://doc.crates.io/contrib/process/unstable.html#stabilization>.\n//!\n//! The steps for stabilizing are roughly:\n//!\n//! 1. Update the feature to be stable, based on the kind of feature:\n//!   1. `cargo-features`: Change the feature to `stable` in the [`features!`]\n//!      macro invocation below, and include the version and a URL for the\n//!      documentation.\n//!   2. `-Z unstable-options`: Find the call to [`fail_if_stable_opt`] and\n//!      remove it. Be sure to update the man pages if necessary.\n//!   3. `-Z` flag: Change the parsing code in [`CliUnstable::add`] to call\n//!      `stabilized_warn` or `stabilized_err` and remove the field from\n//!      [`CliUnstable`]. Remove the `(unstable)` note in the clap help text if\n//!      necessary.\n//! 2. Remove `masquerade_as_nightly_cargo` from any tests, and remove\n//!    `cargo-features` from `Cargo.toml` test files if any. You can\n//!     quickly find what needs to be removed by searching for the name\n//!     of the feature, e.g. `print_im_a_teapot`\n//! 3. Update the docs in unstable.md to move the section to the bottom\n//!    and summarize it similar to the other entries. Update the rest of the\n//!    documentation to add the new feature.\n//!\n//! [`GlobalContext::cli_unstable`]: crate::util::context::GlobalContext::cli_unstable\n//! [`fail_if_stable_opt`]: CliUnstable::fail_if_stable_opt\n//! [`features!`]: macro.features.html\n//! [`unstable_cli_options!`]: macro.unstable_cli_options.html\n//! [`prepare_for_publish`]: crate::util::toml::prepare_for_publish\n\nuse std::collections::BTreeSet;\nuse std::env;\nuse std::fmt::{self, Write};\nuse std::path::PathBuf;\nuse std::str::FromStr;\n\nuse anyhow::{Error, bail};\nuse cargo_util::ProcessBuilder;\nuse serde::{Deserialize, Serialize};\nuse tracing::debug;\n\nuse crate::GlobalContext;\nuse crate::core::resolver::ResolveBehavior;\nuse crate::util::errors::CargoResult;\nuse crate::util::indented_lines;\n\npub const SEE_CHANNELS: &str = \"See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information \\\n     about Rust release channels.\";\n\n/// Value of [`allow-features`](CliUnstable::allow_features)\npub type AllowFeatures = BTreeSet<String>;\n\n/// The edition of the compiler ([RFC 2052])\n///\n/// The following sections will guide you how to add and stabilize an edition.\n///\n/// ## Adding a new edition\n///\n/// - Add the next edition to the enum.\n/// - Update every match expression that now fails to compile.\n/// - Update the [`FromStr`] impl.\n/// - Update [`CLI_VALUES`] to include the new edition.\n/// - Set [`LATEST_UNSTABLE`] to Some with the new edition.\n/// - Update the shell completion files.\n/// - Update any failing tests (hopefully there are very few).\n///\n/// ## Stabilization instructions\n///\n/// - Set [`LATEST_UNSTABLE`] to None.\n/// - Set [`LATEST_STABLE`] to the new version.\n/// - Update [`is_stable`] to `true`.\n/// - Set [`first_version`] to the version it will be released.\n/// - Update any tests that are affected.\n/// - Update the man page for the `--edition` flag.\n/// - Update the documentation:\n///   - Update any features impacted by the edition.\n///   - Update manifest.md#the-edition-field.\n///   - Update the `--edition` flag (options-new.md).\n///   - Rebuild man pages.\n///\n/// [RFC 2052]: https://rust-lang.github.io/rfcs/2052-epochs.html\n/// [`FromStr`]: Edition::from_str\n/// [`CLI_VALUES`]: Edition::CLI_VALUES\n/// [`LATEST_UNSTABLE`]: Edition::LATEST_UNSTABLE\n/// [`LATEST_STABLE`]: Edition::LATEST_STABLE\n/// [`first_version`]: Edition::first_version\n/// [`is_stable`]: Edition::is_stable\n/// [`toml`]: crate::util::toml\n/// [`features!`]: macro.features.html\n#[derive(\n    Default, Clone, Copy, Debug, Hash, PartialOrd, Ord, Eq, PartialEq, Serialize, Deserialize,\n)]\npub enum Edition {\n    /// The 2015 edition\n    #[default]\n    Edition2015,\n    /// The 2018 edition\n    Edition2018,\n    /// The 2021 edition\n    Edition2021,\n    /// The 2024 edition\n    Edition2024,\n    /// The future edition (permanently unstable)\n    EditionFuture,\n}\n\nimpl Edition {\n    /// The latest edition that is unstable.\n    ///\n    /// This is `None` if there is no next unstable edition.\n    ///\n    /// Note that this does *not* include \"future\" since this is primarily\n    /// used for tests that need to step between stable and unstable.\n    pub const LATEST_UNSTABLE: Option<Edition> = None;\n    /// The latest stable edition.\n    pub const LATEST_STABLE: Edition = Edition::Edition2024;\n    pub const ALL: &'static [Edition] = &[\n        Self::Edition2015,\n        Self::Edition2018,\n        Self::Edition2021,\n        Self::Edition2024,\n        Self::EditionFuture,\n    ];\n    /// Possible values allowed for the `--edition` CLI flag.\n    ///\n    /// This requires a static value due to the way clap works, otherwise I\n    /// would have built this dynamically.\n    ///\n    /// This does not include `future` since we don't need to create new\n    /// packages with it.\n    pub const CLI_VALUES: [&'static str; 4] = [\"2015\", \"2018\", \"2021\", \"2024\"];\n\n    /// Returns the first version that a particular edition was released on\n    /// stable.\n    pub(crate) fn first_version(&self) -> Option<semver::Version> {\n        use Edition::*;\n        match self {\n            Edition2015 => None,\n            Edition2018 => Some(semver::Version::new(1, 31, 0)),\n            Edition2021 => Some(semver::Version::new(1, 56, 0)),\n            Edition2024 => Some(semver::Version::new(1, 85, 0)),\n            EditionFuture => None,\n        }\n    }\n\n    /// Returns `true` if this edition is stable in this release.\n    pub fn is_stable(&self) -> bool {\n        use Edition::*;\n        match self {\n            Edition2015 => true,\n            Edition2018 => true,\n            Edition2021 => true,\n            Edition2024 => true,\n            EditionFuture => false,\n        }\n    }\n\n    /// Returns the previous edition from this edition.\n    ///\n    /// Returns `None` for 2015.\n    pub fn previous(&self) -> Option<Edition> {\n        use Edition::*;\n        match self {\n            Edition2015 => None,\n            Edition2018 => Some(Edition2015),\n            Edition2021 => Some(Edition2018),\n            Edition2024 => Some(Edition2021),\n            EditionFuture => panic!(\"future does not have a previous edition\"),\n        }\n    }\n\n    /// Returns the next edition from this edition, returning the last edition\n    /// if this is already the last one.\n    pub fn saturating_next(&self) -> Edition {\n        use Edition::*;\n        // Nothing should treat \"future\" as being next.\n        match self {\n            Edition2015 => Edition2018,\n            Edition2018 => Edition2021,\n            Edition2021 => Edition2024,\n            Edition2024 => Edition2024,\n            EditionFuture => EditionFuture,\n        }\n    }\n\n    /// Updates the given [`ProcessBuilder`] to include the appropriate flags\n    /// for setting the edition.\n    pub(crate) fn cmd_edition_arg(&self, cmd: &mut ProcessBuilder) {\n        cmd.arg(format!(\"--edition={}\", self));\n        if !self.is_stable() {\n            cmd.arg(\"-Z\").arg(\"unstable-options\");\n        }\n    }\n\n    /// Adds the appropriate argument to generate warnings for this edition.\n    pub(crate) fn force_warn_arg(&self, cmd: &mut ProcessBuilder) {\n        use Edition::*;\n        match self {\n            Edition2015 => {}\n            EditionFuture => {\n                cmd.arg(\"--force-warn=edition_future_compatibility\");\n            }\n            e => {\n                // Note that cargo always passes this even if the\n                // compatibility lint group does not exist. When a new edition\n                // is introduced, but there are no migration lints, rustc does\n                // not create the lint group. That's OK because rustc will\n                // just generate a warning about an unknown lint which will be\n                // suppressed due to cap-lints.\n                cmd.arg(format!(\"--force-warn=rust-{e}-compatibility\"));\n            }\n        }\n    }\n\n    /// Whether or not this edition supports the `rust_*_idioms` lint.\n    ///\n    /// Ideally this would not be necessary...\n    pub(crate) fn supports_idiom_lint(&self) -> bool {\n        use Edition::*;\n        match self {\n            Edition2015 => false,\n            Edition2018 => true,\n            Edition2021 => false,\n            Edition2024 => false,\n            EditionFuture => false,\n        }\n    }\n\n    pub(crate) fn default_resolve_behavior(&self) -> ResolveBehavior {\n        if *self >= Edition::Edition2024 {\n            ResolveBehavior::V3\n        } else if *self >= Edition::Edition2021 {\n            ResolveBehavior::V2\n        } else {\n            ResolveBehavior::V1\n        }\n    }\n}\n\nimpl fmt::Display for Edition {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match *self {\n            Edition::Edition2015 => f.write_str(\"2015\"),\n            Edition::Edition2018 => f.write_str(\"2018\"),\n            Edition::Edition2021 => f.write_str(\"2021\"),\n            Edition::Edition2024 => f.write_str(\"2024\"),\n            Edition::EditionFuture => f.write_str(\"future\"),\n        }\n    }\n}\n\nimpl FromStr for Edition {\n    type Err = Error;\n    fn from_str(s: &str) -> Result<Self, Error> {\n        match s {\n            \"2015\" => Ok(Edition::Edition2015),\n            \"2018\" => Ok(Edition::Edition2018),\n            \"2021\" => Ok(Edition::Edition2021),\n            \"2024\" => Ok(Edition::Edition2024),\n            \"future\" => Ok(Edition::EditionFuture),\n            s if s.parse().map_or(false, |y: u16| y > 2024 && y < 2050) => bail!(\n                \"this version of Cargo is older than the `{}` edition, \\\n                 and only supports `2015`, `2018`, `2021`, and `2024` editions.\",\n                s\n            ),\n            s => bail!(\n                \"supported edition values are `2015`, `2018`, `2021`, or `2024`, \\\n                 but `{}` is unknown\",\n                s\n            ),\n        }\n    }\n}\n\n/// The value for `-Zfix-edition`.\n#[derive(Debug, Deserialize)]\npub enum FixEdition {\n    /// `-Zfix-edition=start=$INITIAL`\n    ///\n    /// This mode for `cargo fix` will just run `cargo check` if the current\n    /// edition is equal to this edition. If it is a different edition, then\n    /// it just exits with success. This is used for crater integration which\n    /// needs to set a baseline for the \"before\" toolchain.\n    Start(Edition),\n    /// `-Zfix-edition=end=$INITIAL,$NEXT`\n    ///\n    /// This mode for `cargo fix` will migrate to the `next` edition if the\n    /// current edition is `initial`. After migration, it will update\n    /// `Cargo.toml` and verify that that it works on the new edition. If the\n    /// current edition is not `initial`, then it immediately exits with\n    /// success since we just want to ignore those packages.\n    End { initial: Edition, next: Edition },\n}\n\nimpl FromStr for FixEdition {\n    type Err = anyhow::Error;\n    fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {\n        if let Some(start) = s.strip_prefix(\"start=\") {\n            Ok(FixEdition::Start(start.parse()?))\n        } else if let Some(end) = s.strip_prefix(\"end=\") {\n            let (initial, next) = end\n                .split_once(',')\n                .ok_or_else(|| anyhow::format_err!(\"expected `initial,next`\"))?;\n            Ok(FixEdition::End {\n                initial: initial.parse()?,\n                next: next.parse()?,\n            })\n        } else {\n            bail!(\"invalid `-Zfix-edition, expected start= or end=, got `{s}`\");\n        }\n    }\n}\n\n#[derive(Debug, PartialEq)]\nenum Status {\n    Stable,\n    Unstable,\n    Removed,\n}\n\n/// A listing of stable and unstable new syntax in Cargo.toml.\n///\n/// This generates definitions and impls for [`Features`] and [`Feature`]\n/// for each new syntax.\n///\n/// Note that all feature names in the macro invocation are valid Rust\n/// identifiers, but the `_` character is translated to `-` when specified in\n/// the `cargo-features` manifest entry in `Cargo.toml`.\n///\n/// See the [module-level documentation](self#new-cargotoml-syntax)\n/// for the process of adding a new syntax.\nmacro_rules! features {\n    (\n        $(\n            $(#[$attr:meta])*\n            ($stab:ident, $feature:ident, $version:expr, $docs:expr),\n        )*\n    ) => (\n        /// Unstable feature context for querying if a new Cargo.toml syntax\n        /// is allowed to use.\n        ///\n        /// See the [module-level documentation](self#new-cargotoml-syntax) for the usage.\n        #[derive(Default, Clone, Debug)]\n        pub struct Features {\n            $($feature: bool,)*\n            /// The current activated features.\n            activated: Vec<String>,\n            /// Whether is allowed to use any unstable features.\n            nightly_features_allowed: bool,\n            /// Whether the source manifest is from a local package.\n            is_local: bool,\n        }\n\n        impl Feature {\n            $(\n                $(#[$attr])*\n                #[doc = concat!(\"\\n\\n\\nSee <https://doc.rust-lang.org/nightly/cargo/\", $docs, \">.\")]\n                pub const fn $feature() -> &'static Feature {\n                    fn get(features: &Features) -> bool {\n                        stab!($stab) == Status::Stable || features.$feature\n                    }\n                    const FEAT: Feature = Feature {\n                        name: stringify!($feature),\n                        stability: stab!($stab),\n                        version: $version,\n                        docs: $docs,\n                        get,\n                    };\n                    &FEAT\n                }\n            )*\n\n            /// Whether this feature is allowed to use in the given [`Features`] context.\n            fn is_enabled(&self, features: &Features) -> bool {\n                (self.get)(features)\n            }\n\n            pub(crate) fn name(&self) -> &str {\n                self.name\n            }\n        }\n\n        impl Features {\n            fn status(&mut self, feature: &str) -> Option<(&mut bool, &'static Feature)> {\n                if feature.contains(\"_\") {\n                    return None;\n                }\n                let feature = feature.replace(\"-\", \"_\");\n                $(\n                    if feature == stringify!($feature) {\n                        return Some((&mut self.$feature, Feature::$feature()));\n                    }\n                )*\n                None\n            }\n        }\n    )\n}\n\nmacro_rules! stab {\n    (stable) => {\n        Status::Stable\n    };\n    (unstable) => {\n        Status::Unstable\n    };\n    (removed) => {\n        Status::Removed\n    };\n}\n\n// \"look here\"\nfeatures! {\n    /// A dummy feature that doesn't actually gate anything, but it's used in\n    /// testing to ensure that we can enable stable features.\n    (stable, test_dummy_stable, \"1.0\", \"\"),\n\n    /// A dummy feature that gates the usage of the `im-a-teapot` manifest\n    /// entry. This is basically just intended for tests.\n    (unstable, test_dummy_unstable, \"\", \"reference/unstable.html\"),\n\n    /// Downloading packages from alternative registry indexes.\n    (stable, alternative_registries, \"1.34\", \"reference/registries.html\"),\n\n    /// Using editions\n    (stable, edition, \"1.31\", \"reference/manifest.html#the-edition-field\"),\n\n    /// Renaming a package in the manifest via the `package` key.\n    (stable, rename_dependency, \"1.31\", \"reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml\"),\n\n    /// Whether a lock file is published with this crate.\n    (removed, publish_lockfile, \"1.37\", \"reference/unstable.html#publish-lockfile\"),\n\n    /// Overriding profiles for dependencies.\n    (stable, profile_overrides, \"1.41\", \"reference/profiles.html#overrides\"),\n\n    /// \"default-run\" manifest option.\n    (stable, default_run, \"1.37\", \"reference/manifest.html#the-default-run-field\"),\n\n    /// Declarative build scripts.\n    (unstable, metabuild, \"\", \"reference/unstable.html#metabuild\"),\n\n    /// Specifying the 'public' attribute on dependencies.\n    (unstable, public_dependency, \"\", \"reference/unstable.html#public-dependency\"),\n\n    /// Allow to specify profiles other than 'dev', 'release', 'test', etc.\n    (stable, named_profiles, \"1.57\", \"reference/profiles.html#custom-profiles\"),\n\n    /// Opt-in new-resolver behavior.\n    (stable, resolver, \"1.51\", \"reference/resolver.html#resolver-versions\"),\n\n    /// Allow to specify whether binaries should be stripped.\n    (stable, strip, \"1.58\", \"reference/profiles.html#strip-option\"),\n\n    /// Specifying a minimal 'rust-version' attribute for crates.\n    (stable, rust_version, \"1.56\", \"reference/manifest.html#the-rust-version-field\"),\n\n    /// Support for 2021 edition.\n    (stable, edition2021, \"1.56\", \"reference/manifest.html#the-edition-field\"),\n\n    /// Allow to specify per-package targets (compile kinds).\n    (unstable, per_package_target, \"\", \"reference/unstable.html#per-package-target\"),\n\n    /// Allow to specify which codegen backend should be used.\n    (unstable, codegen_backend, \"\", \"reference/unstable.html#codegen-backend\"),\n\n    /// Allow specifying different binary name apart from the crate name.\n    (unstable, different_binary_name, \"\", \"reference/unstable.html#different-binary-name\"),\n\n    /// Allow specifying rustflags directly in a profile.\n    (unstable, profile_rustflags, \"\", \"reference/unstable.html#profile-rustflags-option\"),\n\n    /// Allow workspace members to inherit fields and dependencies from a workspace.\n    (stable, workspace_inheritance, \"1.64\", \"reference/unstable.html#workspace-inheritance\"),\n\n    /// Support for 2024 edition.\n    (stable, edition2024, \"1.85\", \"reference/manifest.html#the-edition-field\"),\n\n    /// Allow setting trim-paths in a profile to control the sanitisation of file paths in build outputs.\n    (unstable, trim_paths, \"\", \"reference/unstable.html#profile-trim-paths-option\"),\n\n    /// Allow multiple packages to participate in the same API namespace\n    (unstable, open_namespaces, \"\", \"reference/unstable.html#open-namespaces\"),\n\n    /// Allow paths that resolve relatively to a base specified in the config.\n    (unstable, path_bases, \"\", \"reference/unstable.html#path-bases\"),\n\n    /// Allows use of editions that are not yet stable.\n    (unstable, unstable_editions, \"\", \"reference/unstable.html#unstable-editions\"),\n\n    /// Allows use of multiple build scripts.\n    (unstable, multiple_build_scripts, \"\", \"reference/unstable.html#multiple-build-scripts\"),\n\n    /// Allows use of panic=\"immediate-abort\".\n    (unstable, panic_immediate_abort, \"\", \"reference/unstable.html#panic-immediate-abort\"),\n}\n\n/// Status and metadata for a single unstable feature.\n#[derive(Debug)]\npub struct Feature {\n    /// Feature name. This is valid Rust identifier so no dash only underscore.\n    name: &'static str,\n    stability: Status,\n    /// Version that this feature was stabilized or removed.\n    version: &'static str,\n    /// Link to the unstable documentation.\n    docs: &'static str,\n    get: fn(&Features) -> bool,\n}\n\nimpl Features {\n    /// Creates a new unstable features context.\n    pub fn new(\n        features: &[String],\n        gctx: &GlobalContext,\n        warnings: &mut Vec<String>,\n        is_local: bool,\n    ) -> CargoResult<Features> {\n        let mut ret = Features::default();\n        ret.nightly_features_allowed = gctx.nightly_features_allowed;\n        ret.is_local = is_local;\n        for feature in features {\n            ret.add(feature, gctx, warnings)?;\n            ret.activated.push(feature.to_string());\n        }\n        Ok(ret)\n    }\n\n    fn add(\n        &mut self,\n        feature_name: &str,\n        gctx: &GlobalContext,\n        warnings: &mut Vec<String>,\n    ) -> CargoResult<()> {\n        let nightly_features_allowed = self.nightly_features_allowed;\n        let Some((slot, feature)) = self.status(feature_name) else {\n            let mut msg = format!(\"unknown Cargo.toml feature `{feature_name}`\\n\\n\");\n            let mut append_see_docs = true;\n\n            if feature_name.contains('_') {\n                let _ = writeln!(msg, \"Feature names must use '-' instead of '_'.\");\n                append_see_docs = false;\n            } else {\n                let underscore_name = feature_name.replace('-', \"_\");\n                if CliUnstable::help()\n                    .iter()\n                    .any(|(option, _)| *option == underscore_name)\n                {\n                    let _ = writeln!(\n                        msg,\n                        \"This feature can be enabled via -Z{feature_name} or the `[unstable]` section in config.toml.\"\n                    );\n                }\n            }\n\n            if append_see_docs {\n                let _ = writeln!(\n                    msg,\n                    \"See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information.\"\n                );\n            }\n            bail!(msg)\n        };\n\n        if *slot {\n            bail!(\n                \"the cargo feature `{}` has already been activated\",\n                feature_name\n            );\n        }\n\n        let see_docs = || {\n            format!(\n                \"See {} for more information about using this feature.\",\n                cargo_docs_link(feature.docs)\n            )\n        };\n\n        match feature.stability {\n            Status::Stable => {\n                let warning = format!(\n                    \"the cargo feature `{}` has been stabilized in the {} \\\n                         release and is no longer necessary to be listed in the \\\n                         manifest\\n  {}\",\n                    feature_name,\n                    feature.version,\n                    see_docs()\n                );\n                warnings.push(warning);\n            }\n            Status::Unstable if !nightly_features_allowed => bail!(\n                \"the cargo feature `{}` requires a nightly version of \\\n                 Cargo, but this is the `{}` channel\\n\\\n                 {}\\n{}\",\n                feature_name,\n                channel(),\n                SEE_CHANNELS,\n                see_docs()\n            ),\n            Status::Unstable => {\n                if let Some(allow) = &gctx.cli_unstable().allow_features {\n                    if !allow.contains(feature_name) {\n                        bail!(\n                            \"the feature `{}` is not in the list of allowed features: [{}]\",\n                            feature_name,\n                            itertools::join(allow, \", \"),\n                        );\n                    }\n                }\n            }\n            Status::Removed => {\n                let mut msg = format!(\n                    \"the cargo feature `{}` has been removed in the {} release\\n\\n\",\n                    feature_name, feature.version\n                );\n                if self.is_local {\n                    let _ = writeln!(\n                        msg,\n                        \"Remove the feature from Cargo.toml to remove this error.\"\n                    );\n                } else {\n                    let _ = writeln!(\n                        msg,\n                        \"This package cannot be used with this version of Cargo, \\\n                         as the unstable feature `{}` is no longer supported.\",\n                        feature_name\n                    );\n                }\n                let _ = writeln!(msg, \"{}\", see_docs());\n                bail!(msg);\n            }\n        }\n\n        *slot = true;\n\n        Ok(())\n    }\n\n    /// Gets the current activated features.\n    pub fn activated(&self) -> &[String] {\n        &self.activated\n    }\n\n    /// Checks if the given feature is enabled.\n    pub fn require(&self, feature: &Feature) -> CargoResult<()> {\n        self.require_with_hint(feature, None)\n    }\n\n    /// Like [`require`][Self::require], but appends an optional help message\n    /// to the error, placed just before the documentation link.\n    ///\n    /// Use this when the call site has additional context (e.g. the package's\n    /// `rust-version`) that can make the error more actionable.\n    pub(crate) fn require_with_hint(\n        &self,\n        feature: &Feature,\n        hint: Option<&str>,\n    ) -> CargoResult<()> {\n        if feature.is_enabled(self) {\n            return Ok(());\n        }\n        let feature_name = feature.name.replace(\"_\", \"-\");\n        let mut msg = format!(\n            \"feature `{}` is required\\n\\\n             \\n\\\n             The package requires the Cargo feature called `{}`, but \\\n             that feature is not stabilized in this version of Cargo ({}).\\n\\\n            \",\n            feature_name,\n            feature_name,\n            crate::version(),\n        );\n\n        if self.nightly_features_allowed {\n            if self.is_local {\n                let _ = writeln!(\n                    msg,\n                    \"Consider adding `cargo-features = [\\\"{}\\\"]` \\\n                     to the top of Cargo.toml (above the [package] table) \\\n                     to tell Cargo you are opting in to use this unstable feature.\",\n                    feature_name\n                );\n            } else {\n                let _ = writeln!(msg, \"Consider trying a more recent nightly release.\");\n            }\n        } else {\n            let _ = writeln!(\n                msg,\n                \"Consider trying a newer version of Cargo \\\n                 (this may require the nightly release).\"\n            );\n        }\n        let _ = writeln!(\n            msg,\n            \"See https://doc.rust-lang.org/nightly/cargo/{} for more information \\\n             about the status of this feature.\",\n            feature.docs\n        );\n        if let Some(hint) = hint {\n            let _ = writeln!(msg, \"{hint}\");\n        }\n\n        bail!(\"{}\", msg);\n    }\n\n    /// Whether the given feature is allowed to use in this context.\n    pub fn is_enabled(&self, feature: &Feature) -> bool {\n        feature.is_enabled(self)\n    }\n}\n\n/// Generates `-Z` flags as fields of [`CliUnstable`].\n///\n/// See the [module-level documentation](self#-z-options) for details.\nmacro_rules! unstable_cli_options {\n    (\n        $(\n            $(#[$meta:meta])?\n            $element: ident: $ty: ty$( = ($help:literal))?,\n        )*\n    ) => {\n        /// A parsed representation of all unstable flags that Cargo accepts.\n        ///\n        /// Cargo, like `rustc`, accepts a suite of `-Z` flags which are intended for\n        /// gating unstable functionality to Cargo. These flags are only available on\n        /// the nightly channel of Cargo.\n        #[derive(Default, Debug, Deserialize)]\n        #[serde(default, rename_all = \"kebab-case\")]\n        pub struct CliUnstable {\n            $(\n                $(#[doc = $help])?\n                $(#[$meta])?\n                pub $element: $ty\n            ),*\n        }\n        impl CliUnstable {\n            /// Returns a list of `(<option-name>, <help-text>)`.\n            pub fn help() -> Vec<(&'static str, Option<&'static str>)> {\n                let fields = vec![$((stringify!($element), None$(.or(Some($help)))?)),*];\n                fields\n            }\n        }\n\n        #[cfg(test)]\n        mod test {\n            #[test]\n            fn ensure_sorted() {\n                // This will be printed out if the fields are not sorted.\n                let location = std::panic::Location::caller();\n                println!(\n                    \"\\nTo fix this test, sort the features inside the macro at {}:{}\\n\",\n                    location.file(),\n                    location.line()\n                );\n                let mut expected = vec![$(stringify!($element)),*];\n                expected[2..].sort();\n                let expected = format!(\"{:#?}\", expected);\n                let actual = format!(\"{:#?}\", vec![$(stringify!($element)),*]);\n                snapbox::assert_data_eq!(actual, expected);\n            }\n        }\n    }\n}\n\nunstable_cli_options!(\n    // Permanently unstable features:\n    allow_features: Option<AllowFeatures> = (\"Allow *only* the listed unstable features\"),\n    print_im_a_teapot: bool,\n\n    // All other unstable features.\n    // Please keep this list lexicographically ordered.\n    advanced_env: bool,\n    any_build_script_metadata: bool = (\"Allow any build script to specify env vars via cargo::metadata=key=value\"),\n    asymmetric_token: bool = (\"Allows authenticating with asymmetric tokens\"),\n    avoid_dev_deps: bool = (\"Avoid installing dev-dependencies if possible\"),\n    binary_dep_depinfo: bool = (\"Track changes to dependency artifacts\"),\n    bindeps: bool = (\"Allow Cargo packages to depend on bin, cdylib, and staticlib crates, and use the artifacts built by those crates\"),\n    build_analysis: bool = (\"Record and persist build metrics across runs, with commands to query past builds.\"),\n    build_dir_new_layout: bool = (\"Use the new build-dir filesystem layout\"),\n    #[serde(deserialize_with = \"deserialize_comma_separated_list\")]\n    build_std: Option<Vec<String>>  = (\"Enable Cargo to compile the standard library itself as part of a crate graph compilation\"),\n    #[serde(deserialize_with = \"deserialize_comma_separated_list\")]\n    build_std_features: Option<Vec<String>>  = (\"Configure features enabled for the standard library itself when building the standard library\"),\n    cargo_lints: bool = (\"Enable the `[lints.cargo]` table\"),\n    checksum_freshness: bool = (\"Use a checksum to determine if output is fresh rather than filesystem mtime\"),\n    codegen_backend: bool = (\"Enable the `codegen-backend` option in profiles in .cargo/config.toml file\"),\n    direct_minimal_versions: bool = (\"Resolve minimal dependency versions instead of maximum (direct dependencies only)\"),\n    dual_proc_macros: bool = (\"Build proc-macros for both the host and the target\"),\n    feature_unification: bool = (\"Enable new feature unification modes in workspaces\"),\n    features: Option<Vec<String>>,\n    fine_grain_locking: bool = (\"Use fine grain locking instead of locking the entire build cache\"),\n    fix_edition: Option<FixEdition> = (\"Permanently unstable edition migration helper\"),\n    gc: bool = (\"Track cache usage and \\\"garbage collect\\\" unused files\"),\n    #[serde(deserialize_with = \"deserialize_git_features\")]\n    git: Option<GitFeatures> = (\"Enable support for shallow git fetch operations\"),\n    #[serde(deserialize_with = \"deserialize_gitoxide_features\")]\n    gitoxide: Option<GitoxideFeatures> = (\"Use gitoxide for the given git interactions, or all of them if no argument is given\"),\n    host_config: bool = (\"Enable the `[host]` section in the .cargo/config.toml file\"),\n    json_target_spec: bool = (\"Enable `.json` target spec files\"),\n    lockfile_path: bool = (\"Enable the `resolver.lockfile-path` config option\"),\n    minimal_versions: bool = (\"Resolve minimal dependency versions instead of maximum\"),\n    msrv_policy: bool = (\"Enable rust-version aware policy within cargo\"),\n    mtime_on_use: bool = (\"Configure Cargo to update the mtime of used files\"),\n    next_lockfile_bump: bool,\n    no_embed_metadata: bool = (\"Avoid embedding metadata in library artifacts\"),\n    no_index_update: bool = (\"Do not update the registry index even if the cache is outdated\"),\n    panic_abort_tests: bool = (\"Enable support to run tests with -Cpanic=abort\"),\n    panic_immediate_abort: bool = (\"Enable setting `panic = \\\"immediate-abort\\\"` in profiles\"),\n    profile_hint_mostly_unused: bool = (\"Enable the `hint-mostly-unused` setting in profiles to mark a crate as mostly unused.\"),\n    profile_rustflags: bool = (\"Enable the `rustflags` option in profiles in .cargo/config.toml file\"),\n    public_dependency: bool = (\"Respect a dependency's `public` field in Cargo.toml to control public/private dependencies\"),\n    publish_timeout: bool = (\"Enable the `publish.timeout` key in .cargo/config.toml file\"),\n    root_dir: Option<PathBuf> = (\"Set the root directory relative to which paths are printed (defaults to workspace root)\"),\n    rustc_unicode: bool = (\"Enable `rustc`'s unicode error format in Cargo's error messages\"),\n    rustdoc_depinfo: bool = (\"Use dep-info files in rustdoc rebuild detection\"),\n    rustdoc_map: bool = (\"Allow passing external documentation mappings to rustdoc\"),\n    rustdoc_mergeable_info: bool = (\"Use rustdoc mergeable cross-crate-info files\"),\n    rustdoc_scrape_examples: bool = (\"Allows Rustdoc to scrape code examples from reverse-dependencies\"),\n    sbom: bool = (\"Enable the `sbom` option in build config in .cargo/config.toml file\"),\n    script: bool = (\"Enable support for single-file, `.rs` packages\"),\n    section_timings: bool = (\"Enable support for extended compilation sections in --timings output\"),\n    separate_nightlies: bool,\n    skip_rustdoc_fingerprint: bool,\n    target_applies_to_host: bool = (\"Enable the `target-applies-to-host` key in the .cargo/config.toml file\"),\n    trim_paths: bool = (\"Enable the `trim-paths` option in profiles\"),\n    unstable_options: bool = (\"Allow the usage of unstable options\"),\n    warnings: bool = (\"Allow use of the build.warnings config key\"),\n);\n\nconst STABILIZED_COMPILE_PROGRESS: &str = \"The progress bar is now always \\\n    enabled when used on an interactive console.\\n\\\n    See https://doc.rust-lang.org/cargo/reference/config.html#termprogresswhen \\\n    for information on controlling the progress bar.\";\n\nconst STABILIZED_OFFLINE: &str = \"Offline mode is now available via the \\\n    --offline CLI option\";\n\nconst STABILIZED_CACHE_MESSAGES: &str = \"Message caching is now always enabled.\";\n\nconst STABILIZED_INSTALL_UPGRADE: &str = \"Packages are now always upgraded if \\\n    they appear out of date.\\n\\\n    See https://doc.rust-lang.org/cargo/commands/cargo-install.html for more \\\n    information on how upgrading works.\";\n\nconst STABILIZED_CONFIG_PROFILE: &str = \"See \\\n    https://doc.rust-lang.org/cargo/reference/config.html#profile for more \\\n    information about specifying profiles in config.\";\n\nconst STABILIZED_CRATE_VERSIONS: &str = \"The crate version is now \\\n    automatically added to the documentation.\";\n\nconst STABILIZED_PACKAGE_FEATURES: &str = \"Enhanced feature flag behavior is now \\\n    available in virtual workspaces, and `member/feature-name` syntax is also \\\n    always available. Other extensions require setting `resolver = \\\"2\\\"` in \\\n    Cargo.toml.\\n\\\n    See https://doc.rust-lang.org/nightly/cargo/reference/features.html#resolver-version-2-command-line-flags \\\n    for more information.\";\n\nconst STABILIZED_FEATURES: &str = \"The new feature resolver is now available \\\n    by specifying `resolver = \\\"2\\\"` in Cargo.toml.\\n\\\n    See https://doc.rust-lang.org/nightly/cargo/reference/features.html#feature-resolver-version-2 \\\n    for more information.\";\n\nconst STABILIZED_EXTRA_LINK_ARG: &str = \"Additional linker arguments are now \\\n    supported without passing this flag.\";\n\nconst STABILIZED_CONFIGURABLE_ENV: &str = \"The [env] section is now always enabled.\";\n\nconst STABILIZED_PATCH_IN_CONFIG: &str = \"The patch-in-config feature is now always enabled.\";\n\nconst STABILIZED_NAMED_PROFILES: &str = \"The named-profiles feature is now always enabled.\\n\\\n    See https://doc.rust-lang.org/nightly/cargo/reference/profiles.html#custom-profiles \\\n    for more information\";\n\nconst STABILIZED_DOCTEST_IN_WORKSPACE: &str =\n    \"The doctest-in-workspace feature is now always enabled.\";\n\nconst STABILIZED_FUTURE_INCOMPAT_REPORT: &str =\n    \"The future-incompat-report feature is now always enabled.\";\n\nconst STABILIZED_WEAK_DEP_FEATURES: &str = \"Weak dependency features are now always available.\";\n\nconst STABILISED_NAMESPACED_FEATURES: &str = \"Namespaced features are now always available.\";\n\nconst STABILIZED_TIMINGS: &str = \"The -Ztimings option has been stabilized as --timings.\";\n\nconst STABILISED_MULTITARGET: &str = \"Multiple `--target` options are now always available.\";\n\nconst STABILIZED_TERMINAL_WIDTH: &str =\n    \"The -Zterminal-width option is now always enabled for terminal output.\";\n\nconst STABILISED_SPARSE_REGISTRY: &str = \"The sparse protocol is now the default for crates.io\";\n\nconst STABILIZED_CREDENTIAL_PROCESS: &str =\n    \"Authentication with a credential provider is always available.\";\n\nconst STABILIZED_REGISTRY_AUTH: &str =\n    \"Authenticated registries are available if a credential provider is configured.\";\n\nconst STABILIZED_LINTS: &str = \"The `[lints]` table is now always available.\";\n\nconst STABILIZED_CHECK_CFG: &str =\n    \"Compile-time checking of conditional (a.k.a. `-Zcheck-cfg`) is now always enabled.\";\n\nconst STABILIZED_DOCTEST_XCOMPILE: &str = \"Doctest cross-compiling is now always enabled.\";\n\nconst STABILIZED_PACKAGE_WORKSPACE: &str =\n    \"Workspace packaging and publishing (a.k.a. `-Zpackage-workspace`) is now always enabled.\";\n\nconst STABILIZED_BUILD_DIR: &str = \"build.build-dir is now always enabled.\";\n\nconst STABILIZED_CONFIG_INCLUDE: &str = \"The `include` config key is now always available\";\n\nfn deserialize_comma_separated_list<'de, D>(\n    deserializer: D,\n) -> Result<Option<Vec<String>>, D::Error>\nwhere\n    D: serde::Deserializer<'de>,\n{\n    let Some(list) = <Option<Vec<String>>>::deserialize(deserializer)? else {\n        return Ok(None);\n    };\n    let v = list\n        .iter()\n        .flat_map(|s| s.split(','))\n        .filter(|s| !s.is_empty())\n        .map(String::from)\n        .collect();\n    Ok(Some(v))\n}\n\n#[derive(Debug, Copy, Clone, Default, Deserialize, Ord, PartialOrd, Eq, PartialEq)]\n#[serde(default)]\npub struct GitFeatures {\n    /// When cloning the index, perform a shallow clone. Maintain shallowness upon subsequent fetches.\n    pub shallow_index: bool,\n    /// When cloning git dependencies, perform a shallow clone and maintain shallowness on subsequent fetches.\n    pub shallow_deps: bool,\n}\n\nimpl GitFeatures {\n    pub fn all() -> Self {\n        GitFeatures {\n            shallow_index: true,\n            shallow_deps: true,\n        }\n    }\n\n    fn expecting() -> String {\n        let fields = [\"`shallow-index`\", \"`shallow-deps`\"];\n        format!(\n            \"unstable 'git' only takes {} as valid inputs\",\n            fields.join(\" and \")\n        )\n    }\n}\n\nfn deserialize_git_features<'de, D>(deserializer: D) -> Result<Option<GitFeatures>, D::Error>\nwhere\n    D: serde::de::Deserializer<'de>,\n{\n    struct GitFeaturesVisitor;\n\n    impl<'de> serde::de::Visitor<'de> for GitFeaturesVisitor {\n        type Value = Option<GitFeatures>;\n\n        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n            formatter.write_str(&GitFeatures::expecting())\n        }\n\n        fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>\n        where\n            E: serde::de::Error,\n        {\n            if v {\n                Ok(Some(GitFeatures::all()))\n            } else {\n                Ok(None)\n            }\n        }\n\n        fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>\n        where\n            E: serde::de::Error,\n        {\n            Ok(parse_git(s.split(\",\")).map_err(serde::de::Error::custom)?)\n        }\n\n        fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>\n        where\n            D: serde::de::Deserializer<'de>,\n        {\n            let git = GitFeatures::deserialize(deserializer)?;\n            Ok(Some(git))\n        }\n\n        fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>\n        where\n            V: serde::de::MapAccess<'de>,\n        {\n            let mvd = serde::de::value::MapAccessDeserializer::new(map);\n            Ok(Some(GitFeatures::deserialize(mvd)?))\n        }\n    }\n\n    deserializer.deserialize_any(GitFeaturesVisitor)\n}\n\nfn parse_git(it: impl Iterator<Item = impl AsRef<str>>) -> CargoResult<Option<GitFeatures>> {\n    let mut out = GitFeatures::default();\n    let GitFeatures {\n        shallow_index,\n        shallow_deps,\n    } = &mut out;\n\n    for e in it {\n        match e.as_ref() {\n            \"shallow-index\" => *shallow_index = true,\n            \"shallow-deps\" => *shallow_deps = true,\n            _ => {\n                bail!(GitFeatures::expecting())\n            }\n        }\n    }\n    Ok(Some(out))\n}\n\n#[derive(Debug, Copy, Clone, Default, Deserialize, Ord, PartialOrd, Eq, PartialEq)]\n#[serde(default)]\npub struct GitoxideFeatures {\n    /// All fetches are done with `gitoxide`, which includes git dependencies as well as the crates index.\n    pub fetch: bool,\n    /// Checkout git dependencies using `gitoxide` (submodules are still handled by git2 ATM, and filters\n    /// like linefeed conversions are unsupported).\n    pub checkout: bool,\n    /// A feature flag which doesn't have any meaning except for preventing\n    /// `__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2=1` builds to enable all safe `gitoxide` features.\n    /// That way, `gitoxide` isn't actually used even though it's enabled.\n    pub internal_use_git2: bool,\n}\n\nimpl GitoxideFeatures {\n    pub fn all() -> Self {\n        GitoxideFeatures {\n            fetch: true,\n            checkout: true,\n            internal_use_git2: false,\n        }\n    }\n\n    /// Features we deem safe for everyday use - typically true when all tests pass with them\n    /// AND they are backwards compatible.\n    fn safe() -> Self {\n        GitoxideFeatures {\n            fetch: true,\n            checkout: true,\n            internal_use_git2: false,\n        }\n    }\n\n    fn expecting() -> String {\n        let fields = [\"`fetch`\", \"`checkout`\", \"`internal-use-git2`\"];\n        format!(\n            \"unstable 'gitoxide' only takes {} as valid inputs, for shallow fetches see `-Zgit=shallow-index,shallow-deps`\",\n            fields.join(\" and \")\n        )\n    }\n}\n\nfn deserialize_gitoxide_features<'de, D>(\n    deserializer: D,\n) -> Result<Option<GitoxideFeatures>, D::Error>\nwhere\n    D: serde::de::Deserializer<'de>,\n{\n    struct GitoxideFeaturesVisitor;\n\n    impl<'de> serde::de::Visitor<'de> for GitoxideFeaturesVisitor {\n        type Value = Option<GitoxideFeatures>;\n\n        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n            formatter.write_str(&GitoxideFeatures::expecting())\n        }\n\n        fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>\n        where\n            E: serde::de::Error,\n        {\n            Ok(parse_gitoxide(s.split(\",\")).map_err(serde::de::Error::custom)?)\n        }\n\n        fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>\n        where\n            E: serde::de::Error,\n        {\n            if v {\n                Ok(Some(GitoxideFeatures::all()))\n            } else {\n                Ok(None)\n            }\n        }\n\n        fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>\n        where\n            D: serde::de::Deserializer<'de>,\n        {\n            let gitoxide = GitoxideFeatures::deserialize(deserializer)?;\n            Ok(Some(gitoxide))\n        }\n\n        fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>\n        where\n            V: serde::de::MapAccess<'de>,\n        {\n            let mvd = serde::de::value::MapAccessDeserializer::new(map);\n            Ok(Some(GitoxideFeatures::deserialize(mvd)?))\n        }\n    }\n\n    deserializer.deserialize_any(GitoxideFeaturesVisitor)\n}\n\nfn parse_gitoxide(\n    it: impl Iterator<Item = impl AsRef<str>>,\n) -> CargoResult<Option<GitoxideFeatures>> {\n    let mut out = GitoxideFeatures::default();\n    let GitoxideFeatures {\n        fetch,\n        checkout,\n        internal_use_git2,\n    } = &mut out;\n\n    for e in it {\n        match e.as_ref() {\n            \"fetch\" => *fetch = true,\n            \"checkout\" => *checkout = true,\n            \"internal-use-git2\" => *internal_use_git2 = true,\n            _ => {\n                bail!(GitoxideFeatures::expecting())\n            }\n        }\n    }\n    Ok(Some(out))\n}\n\nimpl CliUnstable {\n    /// Parses `-Z` flags from the command line, and returns messages that warn\n    /// if any flag has already been stabilized.\n    pub fn parse(\n        &mut self,\n        flags: &[String],\n        nightly_features_allowed: bool,\n    ) -> CargoResult<Vec<String>> {\n        if !flags.is_empty() && !nightly_features_allowed {\n            bail!(\n                \"the `-Z` flag is only accepted on the nightly channel of Cargo, \\\n                 but this is the `{}` channel\\n\\\n                 {}\",\n                channel(),\n                SEE_CHANNELS\n            );\n        }\n        let mut warnings = Vec::new();\n        // We read flags twice, first to get allowed-features (if specified),\n        // and then to read the remaining unstable flags.\n        for flag in flags {\n            if flag.starts_with(\"allow-features=\") {\n                self.add(flag, &mut warnings)?;\n            }\n        }\n        for flag in flags {\n            self.add(flag, &mut warnings)?;\n        }\n\n        if self.gitoxide.is_none() && cargo_use_gitoxide_instead_of_git2() {\n            self.gitoxide = GitoxideFeatures::safe().into();\n        }\n\n        self.implicitly_enable_features_if_needed();\n\n        Ok(warnings)\n    }\n\n    fn add(&mut self, flag: &str, warnings: &mut Vec<String>) -> CargoResult<()> {\n        let mut parts = flag.splitn(2, '=');\n        let k = parts.next().unwrap();\n        let v = parts.next();\n\n        fn parse_bool(key: &str, value: Option<&str>) -> CargoResult<bool> {\n            match value {\n                None | Some(\"yes\") => Ok(true),\n                Some(\"no\") => Ok(false),\n                Some(s) => bail!(\"flag -Z{} expected `no` or `yes`, found: `{}`\", key, s),\n            }\n        }\n\n        /// Parse a comma-separated list\n        fn parse_list(value: Option<&str>) -> Vec<String> {\n            match value {\n                None => Vec::new(),\n                Some(\"\") => Vec::new(),\n                Some(v) => v.split(',').map(|s| s.to_string()).collect(),\n            }\n        }\n\n        // Asserts that there is no argument to the flag.\n        fn parse_empty(key: &str, value: Option<&str>) -> CargoResult<bool> {\n            if let Some(v) = value {\n                bail!(\"flag -Z{} does not take a value, found: `{}`\", key, v);\n            }\n            Ok(true)\n        }\n\n        let mut stabilized_warn = |key: &str, version: &str, message: &str| {\n            warnings.push(format!(\n                \"flag `-Z {}` has been stabilized in the {} release, \\\n                 and is no longer necessary\\n{}\",\n                key,\n                version,\n                indented_lines(message)\n            ));\n        };\n\n        // Use this if the behavior now requires another mechanism to enable.\n        let stabilized_err = |key: &str, version: &str, message: &str| {\n            Err(anyhow::format_err!(\n                \"flag `-Z {}` has been stabilized in the {} release\\n{}\",\n                key,\n                version,\n                indented_lines(message)\n            ))\n        };\n\n        if let Some(allowed) = &self.allow_features {\n            if k != \"allow-features\" && !allowed.contains(k) {\n                bail!(\n                    \"the feature `{}` is not in the list of allowed features: [{}]\",\n                    k,\n                    itertools::join(allowed, \", \")\n                );\n            }\n        }\n\n        match k {\n            // Permanently unstable features\n            // Sorted alphabetically:\n            \"allow-features\" => self.allow_features = Some(parse_list(v).into_iter().collect()),\n            \"print-im-a-teapot\" => self.print_im_a_teapot = parse_bool(k, v)?,\n\n            // Stabilized features\n            // Sorted by version, then alphabetically:\n            \"compile-progress\" => stabilized_warn(k, \"1.30\", STABILIZED_COMPILE_PROGRESS),\n            \"offline\" => stabilized_err(k, \"1.36\", STABILIZED_OFFLINE)?,\n            \"cache-messages\" => stabilized_warn(k, \"1.40\", STABILIZED_CACHE_MESSAGES),\n            \"install-upgrade\" => stabilized_warn(k, \"1.41\", STABILIZED_INSTALL_UPGRADE),\n            \"config-profile\" => stabilized_warn(k, \"1.43\", STABILIZED_CONFIG_PROFILE),\n            \"crate-versions\" => stabilized_warn(k, \"1.47\", STABILIZED_CRATE_VERSIONS),\n            \"features\" => {\n                // `-Z features` has been stabilized since 1.51,\n                // but `-Z features=compare` is still allowed for convenience\n                // to validate that the feature resolver resolves features\n                // in the same way as the dependency resolver,\n                // until we feel confident to remove entirely.\n                //\n                // See rust-lang/cargo#11168\n                let feats = parse_list(v);\n                let stab_is_not_empty = feats.iter().any(|feat| {\n                    matches!(\n                        feat.as_str(),\n                        \"build_dep\" | \"host_dep\" | \"dev_dep\" | \"itarget\" | \"all\"\n                    )\n                });\n                if stab_is_not_empty || feats.is_empty() {\n                    // Make this stabilized_err once -Zfeature support is removed.\n                    stabilized_warn(k, \"1.51\", STABILIZED_FEATURES);\n                }\n                self.features = Some(feats);\n            }\n            \"package-features\" => stabilized_warn(k, \"1.51\", STABILIZED_PACKAGE_FEATURES),\n            \"configurable-env\" => stabilized_warn(k, \"1.56\", STABILIZED_CONFIGURABLE_ENV),\n            \"extra-link-arg\" => stabilized_warn(k, \"1.56\", STABILIZED_EXTRA_LINK_ARG),\n            \"patch-in-config\" => stabilized_warn(k, \"1.56\", STABILIZED_PATCH_IN_CONFIG),\n            \"named-profiles\" => stabilized_warn(k, \"1.57\", STABILIZED_NAMED_PROFILES),\n            \"future-incompat-report\" => {\n                stabilized_warn(k, \"1.59.0\", STABILIZED_FUTURE_INCOMPAT_REPORT)\n            }\n            \"namespaced-features\" => stabilized_warn(k, \"1.60\", STABILISED_NAMESPACED_FEATURES),\n            \"timings\" => stabilized_warn(k, \"1.60\", STABILIZED_TIMINGS),\n            \"weak-dep-features\" => stabilized_warn(k, \"1.60\", STABILIZED_WEAK_DEP_FEATURES),\n            \"multitarget\" => stabilized_warn(k, \"1.64\", STABILISED_MULTITARGET),\n            \"sparse-registry\" => stabilized_warn(k, \"1.68\", STABILISED_SPARSE_REGISTRY),\n            \"terminal-width\" => stabilized_warn(k, \"1.68\", STABILIZED_TERMINAL_WIDTH),\n            \"doctest-in-workspace\" => stabilized_warn(k, \"1.72\", STABILIZED_DOCTEST_IN_WORKSPACE),\n            \"credential-process\" => stabilized_warn(k, \"1.74\", STABILIZED_CREDENTIAL_PROCESS),\n            \"lints\" => stabilized_warn(k, \"1.74\", STABILIZED_LINTS),\n            \"registry-auth\" => stabilized_warn(k, \"1.74\", STABILIZED_REGISTRY_AUTH),\n            \"check-cfg\" => stabilized_warn(k, \"1.80\", STABILIZED_CHECK_CFG),\n            \"doctest-xcompile\" => stabilized_warn(k, \"1.89\", STABILIZED_DOCTEST_XCOMPILE),\n            \"package-workspace\" => stabilized_warn(k, \"1.89\", STABILIZED_PACKAGE_WORKSPACE),\n            \"build-dir\" => stabilized_warn(k, \"1.91\", STABILIZED_BUILD_DIR),\n            \"config-include\" => stabilized_warn(k, \"1.93\", STABILIZED_CONFIG_INCLUDE),\n\n            // Unstable features\n            // Sorted alphabetically:\n            \"advanced-env\" => self.advanced_env = parse_empty(k, v)?,\n            \"any-build-script-metadata\" => self.any_build_script_metadata = parse_empty(k, v)?,\n            \"asymmetric-token\" => self.asymmetric_token = parse_empty(k, v)?,\n            \"avoid-dev-deps\" => self.avoid_dev_deps = parse_empty(k, v)?,\n            \"binary-dep-depinfo\" => self.binary_dep_depinfo = parse_empty(k, v)?,\n            \"bindeps\" => self.bindeps = parse_empty(k, v)?,\n            \"build-analysis\" => self.build_analysis = parse_empty(k, v)?,\n            \"build-dir-new-layout\" => self.build_dir_new_layout = parse_empty(k, v)?,\n            \"build-std\" => self.build_std = Some(parse_list(v)),\n            \"build-std-features\" => self.build_std_features = Some(parse_list(v)),\n            \"cargo-lints\" => self.cargo_lints = parse_empty(k, v)?,\n            \"codegen-backend\" => self.codegen_backend = parse_empty(k, v)?,\n            \"direct-minimal-versions\" => self.direct_minimal_versions = parse_empty(k, v)?,\n            \"dual-proc-macros\" => self.dual_proc_macros = parse_empty(k, v)?,\n            \"feature-unification\" => self.feature_unification = parse_empty(k, v)?,\n            \"fine-grain-locking\" => self.fine_grain_locking = parse_empty(k, v)?,\n            \"fix-edition\" => {\n                let fe = v\n                    .ok_or_else(|| anyhow::anyhow!(\"-Zfix-edition expected a value\"))?\n                    .parse()?;\n                self.fix_edition = Some(fe);\n            }\n            \"gc\" => self.gc = parse_empty(k, v)?,\n            \"git\" => {\n                self.git =\n                    v.map_or_else(|| Ok(Some(GitFeatures::all())), |v| parse_git(v.split(',')))?\n            }\n            \"gitoxide\" => {\n                self.gitoxide = v.map_or_else(\n                    || Ok(Some(GitoxideFeatures::all())),\n                    |v| parse_gitoxide(v.split(',')),\n                )?\n            }\n            \"host-config\" => self.host_config = parse_empty(k, v)?,\n            \"json-target-spec\" => self.json_target_spec = parse_empty(k, v)?,\n            \"lockfile-path\" => self.lockfile_path = parse_empty(k, v)?,\n            \"next-lockfile-bump\" => self.next_lockfile_bump = parse_empty(k, v)?,\n            \"minimal-versions\" => self.minimal_versions = parse_empty(k, v)?,\n            \"msrv-policy\" => self.msrv_policy = parse_empty(k, v)?,\n            // can also be set in .cargo/config or with and ENV\n            \"mtime-on-use\" => self.mtime_on_use = parse_empty(k, v)?,\n            \"no-embed-metadata\" => self.no_embed_metadata = parse_empty(k, v)?,\n            \"no-index-update\" => self.no_index_update = parse_empty(k, v)?,\n            \"panic-abort-tests\" => self.panic_abort_tests = parse_empty(k, v)?,\n            \"public-dependency\" => self.public_dependency = parse_empty(k, v)?,\n            \"profile-hint-mostly-unused\" => self.profile_hint_mostly_unused = parse_empty(k, v)?,\n            \"profile-rustflags\" => self.profile_rustflags = parse_empty(k, v)?,\n            \"trim-paths\" => self.trim_paths = parse_empty(k, v)?,\n            \"publish-timeout\" => self.publish_timeout = parse_empty(k, v)?,\n            \"root-dir\" => self.root_dir = v.map(|v| v.into()),\n            \"rustc-unicode\" => self.rustc_unicode = parse_empty(k, v)?,\n            \"rustdoc-depinfo\" => self.rustdoc_depinfo = parse_empty(k, v)?,\n            \"rustdoc-map\" => self.rustdoc_map = parse_empty(k, v)?,\n            \"rustdoc-mergeable-info\" => self.rustdoc_mergeable_info = parse_empty(k, v)?,\n            \"rustdoc-scrape-examples\" => self.rustdoc_scrape_examples = parse_empty(k, v)?,\n            \"sbom\" => self.sbom = parse_empty(k, v)?,\n            \"section-timings\" => self.section_timings = parse_empty(k, v)?,\n            \"separate-nightlies\" => self.separate_nightlies = parse_empty(k, v)?,\n            \"checksum-freshness\" => self.checksum_freshness = parse_empty(k, v)?,\n            \"skip-rustdoc-fingerprint\" => self.skip_rustdoc_fingerprint = parse_empty(k, v)?,\n            \"script\" => self.script = parse_empty(k, v)?,\n            \"target-applies-to-host\" => self.target_applies_to_host = parse_empty(k, v)?,\n            \"panic-immediate-abort\" => self.panic_immediate_abort = parse_empty(k, v)?,\n            \"unstable-options\" => self.unstable_options = parse_empty(k, v)?,\n            \"warnings\" => self.warnings = parse_empty(k, v)?,\n            _ => bail!(\n                \"\\\n            unknown `-Z` flag specified: {k}\\n\\n\\\n            For available unstable features, see \\\n            https://doc.rust-lang.org/nightly/cargo/reference/unstable.html\\n\\\n            If you intended to use an unstable rustc feature, try setting `RUSTFLAGS=\\\"-Z{k}\\\"`\"\n            ),\n        }\n\n        Ok(())\n    }\n\n    /// Generates an error if `-Z unstable-options` was not used for a new,\n    /// unstable command-line flag.\n    pub fn fail_if_stable_opt(&self, flag: &str, issue: u32) -> CargoResult<()> {\n        self.fail_if_stable_opt_custom_z(flag, issue, \"unstable-options\", self.unstable_options)\n    }\n\n    pub fn fail_if_stable_opt_custom_z(\n        &self,\n        flag: &str,\n        issue: u32,\n        z_name: &str,\n        enabled: bool,\n    ) -> CargoResult<()> {\n        if !enabled {\n            let see = format!(\n                \"See https://github.com/rust-lang/cargo/issues/{issue} for more \\\n                 information about the `{flag}` flag.\"\n            );\n            // NOTE: a `config` isn't available here, check the channel directly\n            let channel = channel();\n            if channel == \"nightly\" || channel == \"dev\" {\n                bail!(\n                    \"the `{flag}` flag is unstable, pass `-Z {z_name}` to enable it\\n\\\n                     {see}\"\n                );\n            } else {\n                bail!(\n                    \"the `{flag}` flag is unstable, and only available on the nightly channel \\\n                     of Cargo, but this is the `{channel}` channel\\n\\\n                     {SEE_CHANNELS}\\n\\\n                     {see}\"\n                );\n            }\n        }\n        Ok(())\n    }\n\n    /// Generates an error if `-Z unstable-options` was not used for a new,\n    /// unstable subcommand.\n    pub fn fail_if_stable_command(\n        &self,\n        gctx: &GlobalContext,\n        command: &str,\n        issue: u32,\n        z_name: &str,\n        enabled: bool,\n    ) -> CargoResult<()> {\n        if enabled {\n            return Ok(());\n        }\n        let see = format!(\n            \"See https://github.com/rust-lang/cargo/issues/{} for more \\\n            information about the `cargo {}` command.\",\n            issue, command\n        );\n        if gctx.nightly_features_allowed {\n            bail!(\n                \"the `cargo {command}` command is unstable, pass `-Z {z_name}` \\\n                 to enable it\\n\\\n                 {see}\",\n            );\n        } else {\n            bail!(\n                \"the `cargo {}` command is unstable, and only available on the \\\n                 nightly channel of Cargo, but this is the `{}` channel\\n\\\n                 {}\\n\\\n                 {}\",\n                command,\n                channel(),\n                SEE_CHANNELS,\n                see\n            );\n        }\n    }\n\n    fn implicitly_enable_features_if_needed(&mut self) {\n        if self.fine_grain_locking && !self.build_dir_new_layout {\n            debug!(\"-Zbuild-dir-new-layout implicitly enabled by -Zfine-grain-locking\");\n            self.build_dir_new_layout = true;\n        }\n    }\n}\n\n/// Returns the current release channel (\"stable\", \"beta\", \"nightly\", \"dev\").\npub fn channel() -> String {\n    #[expect(\n        clippy::disallowed_methods,\n        reason = \"testing only, no reason for config support\"\n    )]\n    if let Ok(override_channel) = env::var(\"__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS\") {\n        return override_channel;\n    }\n    #[expect(\n        clippy::disallowed_methods,\n        reason = \"consistency with rustc, not specified behavior\"\n    )]\n    if let Ok(staging) = env::var(\"RUSTC_BOOTSTRAP\") {\n        if staging == \"1\" {\n            return \"dev\".to_string();\n        }\n    }\n    crate::version()\n        .release_channel\n        .unwrap_or_else(|| String::from(\"dev\"))\n}\n\n/// Only for testing and developing. See [\"Running with gitoxide as default git backend in tests\"][1].\n///\n/// [1]: https://doc.crates.io/contrib/tests/running.html#running-with-gitoxide-as-default-git-backend-in-tests\n#[expect(\n    clippy::disallowed_methods,\n    reason = \"testing only, no reason for config support\"\n)]\nfn cargo_use_gitoxide_instead_of_git2() -> bool {\n    std::env::var_os(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\").map_or(false, |value| value == \"1\")\n}\n\n/// Generate a link to Cargo documentation for the current release channel\n/// `path` is the URL component after `https://doc.rust-lang.org/{channel}/cargo/`\npub fn cargo_docs_link(path: &str) -> String {\n    let url_channel = match channel().as_str() {\n        \"dev\" | \"nightly\" => \"nightly/\",\n        \"beta\" => \"beta/\",\n        _ => \"\",\n    };\n    format!(\"https://doc.rust-lang.org/{url_channel}cargo/{path}\")\n}\n"
  },
  {
    "path": "src/cargo/core/gc.rs",
    "content": "//! Support for garbage collecting unused files from downloaded files or\n//! artifacts from the target directory.\n//!\n//! The [`Gc`] type provides the high-level interface for the\n//! garbage-collection system.\n//!\n//! Garbage collection can be done \"automatically\" by cargo, which it does by\n//! default once a day when running any command that does a lot of work (like\n//! `cargo build`). The entry point for this is the [`auto_gc`] function,\n//! which handles some basic setup, creating the [`Gc`], and calling\n//! [`Gc::auto`].\n//!\n//! Garbage collection can also be done manually via the `cargo clean` command\n//! by passing any option that requests deleting unused files. That is\n//! implemented by calling the [`Gc::gc`] method.\n//!\n//! Garbage collection for the global cache is guided by the last-use tracking\n//! implemented in the [`crate::core::global_cache_tracker`] module. See that\n//! module documentation for an in-depth explanation of how global cache\n//! tracking works.\n\nuse crate::core::global_cache_tracker::{self, GlobalCacheTracker};\nuse crate::ops::CleanContext;\nuse crate::util::cache_lock::{CacheLock, CacheLockMode};\nuse crate::{CargoResult, GlobalContext};\nuse anyhow::{Context as _, format_err};\nuse serde::Deserialize;\nuse std::time::Duration;\n\n/// Default max age to auto-clean extracted sources, which can be recovered\n/// without downloading anything.\nconst DEFAULT_MAX_AGE_EXTRACTED: &str = \"1 month\";\n/// Default max ago to auto-clean cache data, which must be downloaded to\n/// recover.\nconst DEFAULT_MAX_AGE_DOWNLOADED: &str = \"3 months\";\n/// How often auto-gc will run by default unless overridden in the config.\nconst DEFAULT_AUTO_FREQUENCY: &str = \"1 day\";\n\n/// Performs automatic garbage collection.\n///\n/// This is called in various places in Cargo where garbage collection should\n/// be performed automatically based on the config settings. The default\n/// behavior is to only clean once a day.\n///\n/// This should only be called in code paths for commands that are already\n/// doing a lot of work. It should only be called *after* crates are\n/// downloaded so that the last-use data is updated first.\n///\n/// It should be cheap to call this multiple times (subsequent calls are\n/// ignored), but try not to abuse that.\npub fn auto_gc(gctx: &GlobalContext) {\n    if !gctx.network_allowed() {\n        // As a conservative choice, auto-gc is disabled when offline. If the\n        // user is indefinitely offline, we don't want to delete things they\n        // may later depend on.\n        tracing::trace!(target: \"gc\", \"running offline, auto gc disabled\");\n        return;\n    }\n\n    if let Err(e) = auto_gc_inner(gctx) {\n        if global_cache_tracker::is_silent_error(&e) && !gctx.extra_verbose() {\n            tracing::warn!(target: \"gc\", \"failed to auto-clean cache data: {e:?}\");\n        } else {\n            crate::display_warning_with_error(\n                \"failed to auto-clean cache data\",\n                &e,\n                &mut gctx.shell(),\n            );\n        }\n    }\n}\n\nfn auto_gc_inner(gctx: &GlobalContext) -> CargoResult<()> {\n    let _lock = match gctx.try_acquire_package_cache_lock(CacheLockMode::MutateExclusive)? {\n        Some(lock) => lock,\n        None => {\n            tracing::debug!(target: \"gc\", \"unable to acquire mutate lock, auto gc disabled\");\n            return Ok(());\n        }\n    };\n    // This should not be called when there are pending deferred entries, so check that.\n    let deferred = gctx.deferred_global_last_use()?;\n    debug_assert!(deferred.is_empty());\n    let mut global_cache_tracker = gctx.global_cache_tracker()?;\n    let mut gc = Gc::new(gctx, &mut global_cache_tracker)?;\n    let mut clean_ctx = CleanContext::new(gctx);\n    gc.auto(&mut clean_ctx)?;\n    Ok(())\n}\n\n/// Cache cleaning settings from the `cache.global-clean` config table.\n///\n/// NOTE: Not all of these options may get stabilized. Some of them are very\n/// low-level details, and may not be something typical users need.\n///\n/// If any of these options are `None`, the built-in default is used.\n#[derive(Deserialize, Default)]\n#[serde(rename_all = \"kebab-case\")]\nstruct GlobalCleanConfig {\n    /// Anything older than this duration will be deleted in the source cache.\n    max_src_age: Option<String>,\n    /// Anything older than this duration will be deleted in the compressed crate cache.\n    max_crate_age: Option<String>,\n    /// Any index older than this duration will be deleted from the index cache.\n    max_index_age: Option<String>,\n    /// Any git checkout older than this duration will be deleted from the checkout cache.\n    max_git_co_age: Option<String>,\n    /// Any git clone older than this duration will be deleted from the git cache.\n    max_git_db_age: Option<String>,\n}\n\n/// Options to use for garbage collection.\n#[derive(Clone, Debug, Default)]\npub struct GcOpts {\n    /// The `--max-src-age` CLI option.\n    pub max_src_age: Option<Duration>,\n    // The `--max-crate-age` CLI option.\n    pub max_crate_age: Option<Duration>,\n    /// The `--max-index-age` CLI option.\n    pub max_index_age: Option<Duration>,\n    /// The `--max-git-co-age` CLI option.\n    pub max_git_co_age: Option<Duration>,\n    /// The `--max-git-db-age` CLI option.\n    pub max_git_db_age: Option<Duration>,\n    /// The `--max-src-size` CLI option.\n    pub max_src_size: Option<u64>,\n    /// The `--max-crate-size` CLI option.\n    pub max_crate_size: Option<u64>,\n    /// The `--max-git-size` CLI option.\n    pub max_git_size: Option<u64>,\n    /// The `--max-download-size` CLI option.\n    pub max_download_size: Option<u64>,\n}\n\nimpl GcOpts {\n    /// Returns whether any download cache cleaning options are set.\n    pub fn is_download_cache_opt_set(&self) -> bool {\n        self.max_src_age.is_some()\n            || self.max_crate_age.is_some()\n            || self.max_index_age.is_some()\n            || self.max_git_co_age.is_some()\n            || self.max_git_db_age.is_some()\n            || self.max_src_size.is_some()\n            || self.max_crate_size.is_some()\n            || self.max_git_size.is_some()\n            || self.max_download_size.is_some()\n    }\n\n    /// Returns whether any download cache cleaning options based on size are set.\n    pub fn is_download_cache_size_set(&self) -> bool {\n        self.max_src_size.is_some()\n            || self.max_crate_size.is_some()\n            || self.max_git_size.is_some()\n            || self.max_download_size.is_some()\n    }\n\n    /// Updates the `GcOpts` to incorporate the specified max download age.\n    ///\n    /// \"Download\" means any cached data that can be re-downloaded.\n    pub fn set_max_download_age(&mut self, max_download_age: Duration) {\n        self.max_src_age = Some(maybe_newer_span(max_download_age, self.max_src_age));\n        self.max_crate_age = Some(maybe_newer_span(max_download_age, self.max_crate_age));\n        self.max_index_age = Some(maybe_newer_span(max_download_age, self.max_index_age));\n        self.max_git_co_age = Some(maybe_newer_span(max_download_age, self.max_git_co_age));\n        self.max_git_db_age = Some(maybe_newer_span(max_download_age, self.max_git_db_age));\n    }\n\n    /// Updates the configuration of this [`GcOpts`] to incorporate the\n    /// settings from config.\n    pub fn update_for_auto_gc(&mut self, gctx: &GlobalContext) -> CargoResult<()> {\n        let config = gctx\n            .get::<Option<GlobalCleanConfig>>(\"cache.global-clean\")?\n            .unwrap_or_default();\n        self.update_for_auto_gc_config(&config, gctx.cli_unstable().gc)\n    }\n\n    fn update_for_auto_gc_config(\n        &mut self,\n        config: &GlobalCleanConfig,\n        unstable_allowed: bool,\n    ) -> CargoResult<()> {\n        macro_rules! config_default {\n            ($config:expr, $field:ident, $default:expr, $unstable_allowed:expr) => {\n                if !unstable_allowed {\n                    // These config options require -Zgc\n                    $default\n                } else {\n                    $config.$field.as_deref().unwrap_or($default)\n                }\n            };\n        }\n\n        self.max_src_age = newer_time_span_for_config(\n            self.max_src_age,\n            \"gc.auto.max-src-age\",\n            config_default!(\n                config,\n                max_src_age,\n                DEFAULT_MAX_AGE_EXTRACTED,\n                unstable_allowed\n            ),\n        )?;\n        self.max_crate_age = newer_time_span_for_config(\n            self.max_crate_age,\n            \"gc.auto.max-crate-age\",\n            config_default!(\n                config,\n                max_crate_age,\n                DEFAULT_MAX_AGE_DOWNLOADED,\n                unstable_allowed\n            ),\n        )?;\n        self.max_index_age = newer_time_span_for_config(\n            self.max_index_age,\n            \"gc.auto.max-index-age\",\n            config_default!(\n                config,\n                max_index_age,\n                DEFAULT_MAX_AGE_DOWNLOADED,\n                unstable_allowed\n            ),\n        )?;\n        self.max_git_co_age = newer_time_span_for_config(\n            self.max_git_co_age,\n            \"gc.auto.max-git-co-age\",\n            config_default!(\n                config,\n                max_git_co_age,\n                DEFAULT_MAX_AGE_EXTRACTED,\n                unstable_allowed\n            ),\n        )?;\n        self.max_git_db_age = newer_time_span_for_config(\n            self.max_git_db_age,\n            \"gc.auto.max-git-db-age\",\n            config_default!(\n                config,\n                max_git_db_age,\n                DEFAULT_MAX_AGE_DOWNLOADED,\n                unstable_allowed\n            ),\n        )?;\n        Ok(())\n    }\n}\n\n/// Garbage collector.\n///\n/// See the module docs at [`crate::core::gc`] for more information on GC.\npub struct Gc<'a, 'gctx> {\n    gctx: &'gctx GlobalContext,\n    global_cache_tracker: &'a mut GlobalCacheTracker,\n    /// A lock on the package cache.\n    ///\n    /// This is important to be held, since we don't want multiple cargos to\n    /// be allowed to write to the cache at the same time, or for others to\n    /// read while we are modifying the cache.\n    #[expect(dead_code, reason = \"held for `drop`\")]\n    lock: CacheLock<'gctx>,\n}\n\nimpl<'a, 'gctx> Gc<'a, 'gctx> {\n    pub fn new(\n        gctx: &'gctx GlobalContext,\n        global_cache_tracker: &'a mut GlobalCacheTracker,\n    ) -> CargoResult<Gc<'a, 'gctx>> {\n        let lock = gctx.acquire_package_cache_lock(CacheLockMode::MutateExclusive)?;\n        Ok(Gc {\n            gctx,\n            global_cache_tracker,\n            lock,\n        })\n    }\n\n    /// Performs automatic garbage cleaning.\n    ///\n    /// This returns immediately without doing work if garbage collection has\n    /// been performed recently (since `cache.auto-clean-frequency`).\n    fn auto(&mut self, clean_ctx: &mut CleanContext<'gctx>) -> CargoResult<()> {\n        let freq = self\n            .gctx\n            .get::<Option<String>>(\"cache.auto-clean-frequency\")?;\n        let Some(freq) = parse_frequency(freq.as_deref().unwrap_or(DEFAULT_AUTO_FREQUENCY))? else {\n            tracing::trace!(target: \"gc\", \"auto gc disabled\");\n            return Ok(());\n        };\n        if !self.global_cache_tracker.should_run_auto_gc(freq)? {\n            return Ok(());\n        }\n        let config = self\n            .gctx\n            .get::<Option<GlobalCleanConfig>>(\"cache.global-clean\")?\n            .unwrap_or_default();\n\n        let mut gc_opts = GcOpts::default();\n        gc_opts.update_for_auto_gc_config(&config, self.gctx.cli_unstable().gc)?;\n        self.gc(clean_ctx, &gc_opts)?;\n        if !clean_ctx.dry_run {\n            self.global_cache_tracker.set_last_auto_gc()?;\n        }\n        Ok(())\n    }\n\n    /// Performs garbage collection based on the given options.\n    pub fn gc(&mut self, clean_ctx: &mut CleanContext<'gctx>, gc_opts: &GcOpts) -> CargoResult<()> {\n        self.global_cache_tracker.clean(clean_ctx, gc_opts)?;\n        // In the future, other gc operations go here, such as target cleaning.\n        Ok(())\n    }\n}\n\n/// Returns the shorter duration from `cur_span` versus `config_span`.\n///\n/// This is used because the user may specify multiple options which overlap,\n/// and this will pick whichever one is shorter.\n///\n/// * `cur_span` is the span we are comparing against (the value from the CLI\n///   option). If None, just returns the config duration.\n/// * `config_name` is the name of the config option the span is loaded from.\n/// * `config_span` is the span value loaded from config.\nfn newer_time_span_for_config(\n    cur_span: Option<Duration>,\n    config_name: &str,\n    config_span: &str,\n) -> CargoResult<Option<Duration>> {\n    let config_span = parse_time_span_for_config(config_name, config_span)?;\n    Ok(Some(maybe_newer_span(config_span, cur_span)))\n}\n\n/// Returns whichever [`Duration`] is shorter.\nfn maybe_newer_span(a: Duration, b: Option<Duration>) -> Duration {\n    match b {\n        Some(b) => {\n            if b < a {\n                b\n            } else {\n                a\n            }\n        }\n        None => a,\n    }\n}\n\n/// Parses a frequency string.\n///\n/// Returns `Ok(None)` if the frequency is \"never\".\nfn parse_frequency(frequency: &str) -> CargoResult<Option<Duration>> {\n    if frequency == \"always\" {\n        return Ok(Some(Duration::new(0, 0)));\n    } else if frequency == \"never\" {\n        return Ok(None);\n    }\n    let duration = maybe_parse_time_span(frequency).ok_or_else(|| {\n        format_err!(\n            \"config option `cache.auto-clean-frequency` expected a value of \\\"always\\\", \\\"never\\\", \\\n             or \\\"N seconds/minutes/days/weeks/months\\\", got: {frequency:?}\"\n        )\n    })?;\n    Ok(Some(duration))\n}\n\n/// Parses a time span value fetched from config.\n///\n/// This is here to provide better error messages specific to reading from\n/// config.\nfn parse_time_span_for_config(config_name: &str, span: &str) -> CargoResult<Duration> {\n    maybe_parse_time_span(span).ok_or_else(|| {\n        format_err!(\n            \"config option `{config_name}` expected a value of the form \\\n             \\\"N seconds/minutes/days/weeks/months\\\", got: {span:?}\"\n        )\n    })\n}\n\n/// Parses a time span string.\n///\n/// Returns None if the value is not valid. See [`parse_time_span`] if you\n/// need a variant that generates an error message.\nfn maybe_parse_time_span(span: &str) -> Option<Duration> {\n    let Some(right_i) = span.find(|c: char| !c.is_ascii_digit()) else {\n        return None;\n    };\n    let (left, mut right) = span.split_at(right_i);\n    if right.starts_with(' ') {\n        right = &right[1..];\n    }\n    let count: u64 = left.parse().ok()?;\n    let factor = match right {\n        \"second\" | \"seconds\" => 1,\n        \"minute\" | \"minutes\" => 60,\n        \"hour\" | \"hours\" => 60 * 60,\n        \"day\" | \"days\" => 24 * 60 * 60,\n        \"week\" | \"weeks\" => 7 * 24 * 60 * 60,\n        \"month\" | \"months\" => 2_629_746, // average is 30.436875 days\n        _ => return None,\n    };\n    Some(Duration::from_secs(factor * count))\n}\n\n/// Parses a time span string.\npub fn parse_time_span(span: &str) -> CargoResult<Duration> {\n    maybe_parse_time_span(span).ok_or_else(|| {\n        format_err!(\n            \"expected a value of the form \\\n             \\\"N seconds/minutes/days/weeks/months\\\", got: {span:?}\"\n        )\n    })\n}\n\n/// Parses a file size using metric or IEC units.\npub fn parse_human_size(input: &str) -> CargoResult<u64> {\n    let re = regex::Regex::new(r\"(?i)^([0-9]+(\\.[0-9])?) ?(b|kb|mb|gb|kib|mib|gib)?$\").unwrap();\n    let cap = re.captures(input).ok_or_else(|| {\n        format_err!(\n            \"invalid size `{input}`, \\\n             expected a number with an optional B, kB, MB, GB, kiB, MiB, or GiB suffix\"\n        )\n    })?;\n    let factor = match cap.get(3) {\n        Some(suffix) => match suffix.as_str().to_lowercase().as_str() {\n            \"b\" => 1.0,\n            \"kb\" => 1_000.0,\n            \"mb\" => 1_000_000.0,\n            \"gb\" => 1_000_000_000.0,\n            \"kib\" => 1024.0,\n            \"mib\" => 1024.0 * 1024.0,\n            \"gib\" => 1024.0 * 1024.0 * 1024.0,\n            s => unreachable!(\"suffix `{s}` out of sync with regex\"),\n        },\n        None => {\n            return cap[1]\n                .parse()\n                .with_context(|| format!(\"expected an integer size, got `{}`\", &cap[1]));\n        }\n    };\n    let num = cap[1]\n        .parse::<f64>()\n        .with_context(|| format!(\"expected an integer or float, found `{}`\", &cap[1]))?;\n    Ok((num * factor) as u64)\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    #[test]\n    fn time_spans() {\n        let d = |x| Some(Duration::from_secs(x));\n        assert_eq!(maybe_parse_time_span(\"0 seconds\"), d(0));\n        assert_eq!(maybe_parse_time_span(\"1second\"), d(1));\n        assert_eq!(maybe_parse_time_span(\"23 seconds\"), d(23));\n        assert_eq!(maybe_parse_time_span(\"5 minutes\"), d(60 * 5));\n        assert_eq!(maybe_parse_time_span(\"2 hours\"), d(60 * 60 * 2));\n        assert_eq!(maybe_parse_time_span(\"1 day\"), d(60 * 60 * 24));\n        assert_eq!(maybe_parse_time_span(\"2 weeks\"), d(60 * 60 * 24 * 14));\n        assert_eq!(maybe_parse_time_span(\"6 months\"), d(2_629_746 * 6));\n\n        assert_eq!(parse_frequency(\"5 seconds\").unwrap(), d(5));\n        assert_eq!(parse_frequency(\"always\").unwrap(), d(0));\n        assert_eq!(parse_frequency(\"never\").unwrap(), None);\n    }\n\n    #[test]\n    fn time_span_errors() {\n        assert_eq!(maybe_parse_time_span(\"\"), None);\n        assert_eq!(maybe_parse_time_span(\"1\"), None);\n        assert_eq!(maybe_parse_time_span(\"second\"), None);\n        assert_eq!(maybe_parse_time_span(\"+2 seconds\"), None);\n        assert_eq!(maybe_parse_time_span(\"day\"), None);\n        assert_eq!(maybe_parse_time_span(\"-1 days\"), None);\n        assert_eq!(maybe_parse_time_span(\"1.5 days\"), None);\n        assert_eq!(maybe_parse_time_span(\"1 dayz\"), None);\n        assert_eq!(maybe_parse_time_span(\"always\"), None);\n        assert_eq!(maybe_parse_time_span(\"never\"), None);\n        assert_eq!(maybe_parse_time_span(\"1 day \"), None);\n        assert_eq!(maybe_parse_time_span(\" 1 day\"), None);\n        assert_eq!(maybe_parse_time_span(\"1  second\"), None);\n\n        let e =\n            parse_time_span_for_config(\"cache.global-clean.max-src-age\", \"-1 days\").unwrap_err();\n        assert_eq!(\n            e.to_string(),\n            \"config option `cache.global-clean.max-src-age` \\\n             expected a value of the form \\\"N seconds/minutes/days/weeks/months\\\", \\\n             got: \\\"-1 days\\\"\"\n        );\n        let e = parse_frequency(\"abc\").unwrap_err();\n        assert_eq!(\n            e.to_string(),\n            \"config option `cache.auto-clean-frequency` \\\n             expected a value of \\\"always\\\", \\\"never\\\", or \\\"N seconds/minutes/days/weeks/months\\\", \\\n             got: \\\"abc\\\"\"\n        );\n    }\n\n    #[test]\n    fn human_sizes() {\n        assert_eq!(parse_human_size(\"0\").unwrap(), 0);\n        assert_eq!(parse_human_size(\"123\").unwrap(), 123);\n        assert_eq!(parse_human_size(\"123b\").unwrap(), 123);\n        assert_eq!(parse_human_size(\"123B\").unwrap(), 123);\n        assert_eq!(parse_human_size(\"123 b\").unwrap(), 123);\n        assert_eq!(parse_human_size(\"123 B\").unwrap(), 123);\n        assert_eq!(parse_human_size(\"1kb\").unwrap(), 1_000);\n        assert_eq!(parse_human_size(\"5kb\").unwrap(), 5_000);\n        assert_eq!(parse_human_size(\"1mb\").unwrap(), 1_000_000);\n        assert_eq!(parse_human_size(\"1gb\").unwrap(), 1_000_000_000);\n        assert_eq!(parse_human_size(\"1kib\").unwrap(), 1_024);\n        assert_eq!(parse_human_size(\"1mib\").unwrap(), 1_048_576);\n        assert_eq!(parse_human_size(\"1gib\").unwrap(), 1_073_741_824);\n        assert_eq!(parse_human_size(\"1.5kb\").unwrap(), 1_500);\n        assert_eq!(parse_human_size(\"1.7b\").unwrap(), 1);\n\n        assert!(parse_human_size(\"\").is_err());\n        assert!(parse_human_size(\"x\").is_err());\n        assert!(parse_human_size(\"1x\").is_err());\n        assert!(parse_human_size(\"1 2\").is_err());\n        assert!(parse_human_size(\"1.5\").is_err());\n        assert!(parse_human_size(\"+1\").is_err());\n        assert!(parse_human_size(\"123  b\").is_err());\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/global_cache_tracker.rs",
    "content": "//! Support for tracking the last time files were used to assist with cleaning\n//! up those files if they haven't been used in a while.\n//!\n//! Tracking of cache files is stored in a sqlite database which contains a\n//! timestamp of the last time the file was used, as well as the size of the\n//! file.\n//!\n//! While cargo is running, when it detects a use of a cache file, it adds a\n//! timestamp to [`DeferredGlobalLastUse`]. This batches up a set of changes\n//! that are then flushed to the database all at once (via\n//! [`DeferredGlobalLastUse::save`]). Ideally saving would only be done once\n//! for performance reasons, but that is not really possible due to the way\n//! cargo works, since there are different ways cargo can be used (like `cargo\n//! generate-lockfile`, `cargo fetch`, and `cargo build` are all very\n//! different ways the code is used).\n//!\n//! All of the database interaction is done through the [`GlobalCacheTracker`]\n//! type.\n//!\n//! There is a single global [`GlobalCacheTracker`] and\n//! [`DeferredGlobalLastUse`] stored in [`GlobalContext`].\n//!\n//! The high-level interface for performing garbage collection is defined in\n//! the [`crate::core::gc`] module. The functions there are responsible for\n//! interacting with the [`GlobalCacheTracker`] to handle cleaning of global\n//! cache data.\n//!\n//! ## Automatic gc\n//!\n//! Some commands (primarily the build commands) will trigger an automatic\n//! deletion of files that haven't been used in a while. The high-level\n//! interface for this is the [`crate::core::gc::auto_gc`] function.\n//!\n//! The [`GlobalCacheTracker`] database tracks the last time an automatic gc\n//! was performed so that it is only done once per day for performance\n//! reasons.\n//!\n//! ## Manual gc\n//!\n//! The user can perform a manual garbage collection with the `cargo clean`\n//! command. That command has a variety of options to specify what to delete.\n//! Manual gc supports deleting based on age or size or both. From a\n//! high-level, this is done by the [`crate::core::gc::Gc::gc`] method, which\n//! calls into [`GlobalCacheTracker`] to handle all the cleaning.\n//!\n//! ## Locking\n//!\n//! Usage of the database requires that the package cache is locked to prevent\n//! concurrent access. Although sqlite has built-in locking support, we want\n//! to use cargo's locking so that the \"Blocking\" message gets displayed, and\n//! so that locks can block indefinitely for long-running build commands.\n//! [`rusqlite`] has a default timeout of 5 seconds, though that is\n//! configurable.\n//!\n//! When garbage collection is being performed, the package cache lock must be\n//! in [`CacheLockMode::MutateExclusive`] to ensure no other cargo process is\n//! running. See [`crate::util::cache_lock`] for more detail on locking.\n//!\n//! When performing automatic gc, [`crate::core::gc::auto_gc`] will skip the\n//! GC if the package cache lock is already held by anything else. Automatic\n//! GC is intended to be opportunistic, and should impose as little disruption\n//! to the user as possible.\n//!\n//! ## Compatibility\n//!\n//! The database must retain both forwards and backwards compatibility between\n//! different versions of cargo. For the most part, this shouldn't be too\n//! difficult to maintain. Generally sqlite doesn't change on-disk formats\n//! between versions (the introduction of WAL is one of the few examples where\n//! version 3 had a format change, but we wouldn't use it anyway since it has\n//! shared-memory requirements cargo can't depend on due to things like\n//! network mounts).\n//!\n//! Schema changes must be managed through [`migrations`] by adding new\n//! entries that make a change to the database. Changes must not break older\n//! versions of cargo. Generally, adding columns should be fine (either with a\n//! default value, or NULL). Adding tables should also be fine. Just don't do\n//! destructive things like removing a column, or changing the semantics of an\n//! existing column.\n//!\n//! Since users may run older versions of cargo that do not do cache tracking,\n//! the [`GlobalCacheTracker::sync_db_with_files`] method helps dealing with\n//! keeping the database in sync in the presence of older versions of cargo\n//! touching the cache directories.\n//!\n//! ## Performance\n//!\n//! A lot of focus on the design of this system is to minimize the performance\n//! impact. Every build command needs to save updates which we try to avoid\n//! having a noticeable impact on build times. Systems like Windows,\n//! particularly with a magnetic hard disk, can experience a fairly large\n//! impact of cargo's overhead. Cargo's benchsuite has some benchmarks to help\n//! compare different environments, or changes to the code here. Please try to\n//! keep performance in mind if making any major changes.\n//!\n//! Performance of `cargo clean` is not quite as important since it is not\n//! expected to be run often. However, it is still courteous to the user to\n//! try to not impact it too much. One part that has a performance concern is\n//! that the clean command will synchronize the database with whatever is on\n//! disk if needed (in case files were added by older versions of cargo that\n//! don't do cache tracking, or if the user manually deleted some files). This\n//! can potentially be very slow, especially if the two are very out of sync.\n//!\n//! ## Filesystems\n//!\n//! Everything here is sensitive to the kind of filesystem it is running on.\n//! People tend to run cargo in all sorts of strange environments that have\n//! limited capabilities, or on things like read-only mounts. The code here\n//! needs to gracefully handle as many situations as possible.\n//!\n//! See also the information in the [Performance](#performance) and\n//! [Locking](#locking) sections when considering different filesystems and\n//! their impact on performance and locking.\n//!\n//! There are checks for read-only filesystems, which is generally ignored.\n\nuse crate::core::Verbosity;\nuse crate::core::gc::GcOpts;\nuse crate::ops::CleanContext;\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::interning::InternedString;\nuse crate::util::sqlite::{self, Migration, basic_migration};\nuse crate::util::{Filesystem, Progress, ProgressStyle};\nuse crate::{CargoResult, GlobalContext};\nuse anyhow::{Context as _, bail};\nuse cargo_util::paths;\nuse rusqlite::{Connection, ErrorCode, params};\nuse std::collections::{HashMap, hash_map};\nuse std::path::{Path, PathBuf};\nuse std::time::{Duration, SystemTime};\nuse tracing::{debug, trace};\n\n/// The filename of the database.\nconst GLOBAL_CACHE_FILENAME: &str = \".global-cache\";\n\nconst REGISTRY_INDEX_TABLE: &str = \"registry_index\";\nconst REGISTRY_CRATE_TABLE: &str = \"registry_crate\";\nconst REGISTRY_SRC_TABLE: &str = \"registry_src\";\nconst GIT_DB_TABLE: &str = \"git_db\";\nconst GIT_CO_TABLE: &str = \"git_checkout\";\n\n/// How often timestamps will be updated.\n///\n/// As an optimization timestamps are not updated unless they are older than\n/// the given number of seconds. This helps reduce the amount of disk I/O when\n/// running cargo multiple times within a short window.\nconst UPDATE_RESOLUTION: u64 = 60 * 5;\n\n/// Type for timestamps as stored in the database.\n///\n/// These are seconds since the Unix epoch.\ntype Timestamp = u64;\n\n/// The key for a registry index entry stored in the database.\n#[derive(Clone, Debug, Hash, Eq, PartialEq)]\npub struct RegistryIndex {\n    /// A unique name of the registry source.\n    pub encoded_registry_name: InternedString,\n}\n\n/// The key for a registry `.crate` entry stored in the database.\n#[derive(Clone, Debug, Hash, Eq, PartialEq)]\npub struct RegistryCrate {\n    /// A unique name of the registry source.\n    pub encoded_registry_name: InternedString,\n    /// The filename of the compressed crate, like `foo-1.2.3.crate`.\n    pub crate_filename: InternedString,\n    /// The size of the `.crate` file.\n    pub size: u64,\n}\n\n/// The key for a registry src directory entry stored in the database.\n#[derive(Clone, Debug, Hash, Eq, PartialEq)]\npub struct RegistrySrc {\n    /// A unique name of the registry source.\n    pub encoded_registry_name: InternedString,\n    /// The directory name of the extracted source, like `foo-1.2.3`.\n    pub package_dir: InternedString,\n    /// Total size of the src directory in bytes.\n    ///\n    /// This can be None when the size is unknown. For example, when the src\n    /// directory already exists on disk, and we just want to update the\n    /// last-use timestamp. We don't want to take the expense of computing disk\n    /// usage unless necessary. [`GlobalCacheTracker::populate_untracked`]\n    /// will handle any actual NULL values in the database, which can happen\n    /// when the src directory is created by an older version of cargo that\n    /// did not track sizes.\n    pub size: Option<u64>,\n}\n\n/// The key for a git db entry stored in the database.\n#[derive(Clone, Debug, Hash, Eq, PartialEq)]\npub struct GitDb {\n    /// A unique name of the git database.\n    pub encoded_git_name: InternedString,\n}\n\n/// The key for a git checkout entry stored in the database.\n#[derive(Clone, Debug, Hash, Eq, PartialEq)]\npub struct GitCheckout {\n    /// A unique name of the git database.\n    pub encoded_git_name: InternedString,\n    /// A unique name of the checkout without the database.\n    pub short_name: InternedString,\n    /// Total size of the checkout directory.\n    ///\n    /// This can be None when the size is unknown. See [`RegistrySrc::size`]\n    /// for an explanation.\n    pub size: Option<u64>,\n}\n\n/// Filesystem paths in the global cache.\n///\n/// Accessing these assumes a lock has already been acquired.\nstruct BasePaths {\n    /// Root path to the index caches.\n    index: PathBuf,\n    /// Root path to the git DBs.\n    git_db: PathBuf,\n    /// Root path to the git checkouts.\n    git_co: PathBuf,\n    /// Root path to the `.crate` files.\n    crate_dir: PathBuf,\n    /// Root path to the `src` directories.\n    src: PathBuf,\n}\n\n/// Migrations which initialize the database, and can be used to evolve it over time.\n///\n/// See [`Migration`] for more detail.\n///\n/// **Be sure to not change the order or entries here!**\nfn migrations() -> Vec<Migration> {\n    vec![\n        // registry_index tracks the overall usage of an index cache, and tracks a\n        // numeric ID to refer to that index that is used in other tables.\n        basic_migration(\n            \"CREATE TABLE registry_index (\n                id INTEGER PRIMARY KEY AUTOINCREMENT,\n                name TEXT UNIQUE NOT NULL,\n                timestamp INTEGER NOT NULL\n            )\",\n        ),\n        // .crate files\n        basic_migration(\n            \"CREATE TABLE registry_crate (\n                registry_id INTEGER NOT NULL,\n                name TEXT NOT NULL,\n                size INTEGER NOT NULL,\n                timestamp INTEGER NOT NULL,\n                PRIMARY KEY (registry_id, name),\n                FOREIGN KEY (registry_id) REFERENCES registry_index (id) ON DELETE CASCADE\n             )\",\n        ),\n        // Extracted src directories\n        //\n        // Note that `size` can be NULL. This will happen when marking a src\n        // directory as used that was created by an older version of cargo\n        // that didn't do size tracking.\n        basic_migration(\n            \"CREATE TABLE registry_src (\n                registry_id INTEGER NOT NULL,\n                name TEXT NOT NULL,\n                size INTEGER,\n                timestamp INTEGER NOT NULL,\n                PRIMARY KEY (registry_id, name),\n                FOREIGN KEY (registry_id) REFERENCES registry_index (id) ON DELETE CASCADE\n             )\",\n        ),\n        // Git db directories\n        basic_migration(\n            \"CREATE TABLE git_db (\n                id INTEGER PRIMARY KEY AUTOINCREMENT,\n                name TEXT UNIQUE NOT NULL,\n                timestamp INTEGER NOT NULL\n             )\",\n        ),\n        // Git checkout directories\n        basic_migration(\n            \"CREATE TABLE git_checkout (\n                git_id INTEGER NOT NULL,\n                name TEXT UNIQUE NOT NULL,\n                size INTEGER,\n                timestamp INTEGER NOT NULL,\n                PRIMARY KEY (git_id, name),\n                FOREIGN KEY (git_id) REFERENCES git_db (id) ON DELETE CASCADE\n             )\",\n        ),\n        // This is a general-purpose single-row table that can store arbitrary\n        // data. Feel free to add columns (with ALTER TABLE) if necessary.\n        basic_migration(\n            \"CREATE TABLE global_data (\n                last_auto_gc INTEGER NOT NULL\n            )\",\n        ),\n        // last_auto_gc tracks the last time auto-gc was run (so that it only\n        // runs roughly once a day for performance reasons). Prime it with the\n        // current time to establish a baseline.\n        Box::new(|conn| {\n            conn.execute(\n                \"INSERT INTO global_data (last_auto_gc) VALUES (?1)\",\n                [now()],\n            )?;\n            Ok(())\n        }),\n    ]\n}\n\n/// Type for SQL columns that refer to the primary key of their parent table.\n///\n/// For example, `registry_crate.registry_id` refers to its parent `registry_index.id`.\n#[derive(Copy, Clone, Debug, PartialEq)]\nstruct ParentId(i64);\n\nimpl rusqlite::types::FromSql for ParentId {\n    fn column_result(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {\n        let i = i64::column_result(value)?;\n        Ok(ParentId(i))\n    }\n}\n\nimpl rusqlite::types::ToSql for ParentId {\n    fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {\n        Ok(rusqlite::types::ToSqlOutput::from(self.0))\n    }\n}\n\n/// Tracking for the global shared cache (registry files, etc.).\n///\n/// This is the interface to the global cache database, used for tracking and\n/// cleaning. See the [`crate::core::global_cache_tracker`] module docs for\n/// details.\n#[derive(Debug)]\npub struct GlobalCacheTracker {\n    /// Connection to the SQLite database.\n    conn: Connection,\n    /// This is an optimization used to make sure cargo only checks if gc\n    /// needs to run once per session. This starts as `false`, and then the\n    /// first time it checks if automatic gc needs to run, it will be set to\n    /// `true`.\n    auto_gc_checked_this_session: bool,\n}\n\nimpl GlobalCacheTracker {\n    /// Creates a new [`GlobalCacheTracker`].\n    ///\n    /// The caller is responsible for locking the package cache with\n    /// [`CacheLockMode::DownloadExclusive`] before calling this.\n    pub fn new(gctx: &GlobalContext) -> CargoResult<GlobalCacheTracker> {\n        let db_path = Self::db_path(gctx);\n        // A package cache lock is required to ensure only one cargo is\n        // accessing at the same time. If there is concurrent access, we\n        // want to rely on cargo's own \"Blocking\" system (which can\n        // provide user feedback) rather than blocking inside sqlite\n        // (which by default has a short timeout).\n        let db_path = gctx.assert_package_cache_locked(CacheLockMode::DownloadExclusive, &db_path);\n        let mut conn = Connection::open(db_path)?;\n        conn.pragma_update(None, \"foreign_keys\", true)?;\n        sqlite::migrate(&mut conn, &migrations())?;\n        Ok(GlobalCacheTracker {\n            conn,\n            auto_gc_checked_this_session: false,\n        })\n    }\n\n    /// The path to the database.\n    pub fn db_path(gctx: &GlobalContext) -> Filesystem {\n        gctx.home().join(GLOBAL_CACHE_FILENAME)\n    }\n\n    /// Given an encoded registry name, returns its ID.\n    ///\n    /// Returns None if the given name isn't in the database.\n    fn id_from_name(\n        conn: &Connection,\n        table_name: &str,\n        encoded_name: &str,\n    ) -> CargoResult<Option<ParentId>> {\n        let mut stmt =\n            conn.prepare_cached(&format!(\"SELECT id FROM {table_name} WHERE name = ?\"))?;\n        match stmt.query_row([encoded_name], |row| row.get(0)) {\n            Ok(id) => Ok(Some(id)),\n            Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),\n            Err(e) => Err(e.into()),\n        }\n    }\n\n    /// Returns a map of ID to path for the given ids in the given table.\n    ///\n    /// For example, given `registry_index` IDs, it returns filenames of the\n    /// form \"index.crates.io-6f17d22bba15001f\".\n    fn get_id_map(\n        conn: &Connection,\n        table_name: &str,\n        ids: &[i64],\n    ) -> CargoResult<HashMap<i64, PathBuf>> {\n        let mut stmt =\n            conn.prepare_cached(&format!(\"SELECT name FROM {table_name} WHERE id = ?1\"))?;\n        ids.iter()\n            .map(|id| {\n                let name = stmt.query_row(params![id], |row| {\n                    Ok(PathBuf::from(row.get::<_, String>(0)?))\n                })?;\n                Ok((*id, name))\n            })\n            .collect()\n    }\n\n    /// Returns all index cache timestamps.\n    pub fn registry_index_all(&self) -> CargoResult<Vec<(RegistryIndex, Timestamp)>> {\n        let mut stmt = self\n            .conn\n            .prepare_cached(\"SELECT name, timestamp FROM registry_index\")?;\n        let rows = stmt\n            .query_map([], |row| {\n                let encoded_registry_name = row.get_unwrap(0);\n                let timestamp = row.get_unwrap(1);\n                let kind = RegistryIndex {\n                    encoded_registry_name,\n                };\n                Ok((kind, timestamp))\n            })?\n            .collect::<Result<Vec<_>, _>>()?;\n        Ok(rows)\n    }\n\n    /// Returns all registry crate cache timestamps.\n    pub fn registry_crate_all(&self) -> CargoResult<Vec<(RegistryCrate, Timestamp)>> {\n        let mut stmt = self.conn.prepare_cached(\n            \"SELECT registry_index.name, registry_crate.name, registry_crate.size, registry_crate.timestamp\n             FROM registry_index, registry_crate\n             WHERE registry_crate.registry_id = registry_index.id\",\n        )?;\n        let rows = stmt\n            .query_map([], |row| {\n                let encoded_registry_name = row.get_unwrap(0);\n                let crate_filename = row.get_unwrap(1);\n                let size = row.get_unwrap(2);\n                let timestamp = row.get_unwrap(3);\n                let kind = RegistryCrate {\n                    encoded_registry_name,\n                    crate_filename,\n                    size,\n                };\n                Ok((kind, timestamp))\n            })?\n            .collect::<Result<Vec<_>, _>>()?;\n        Ok(rows)\n    }\n\n    /// Returns all registry source cache timestamps.\n    pub fn registry_src_all(&self) -> CargoResult<Vec<(RegistrySrc, Timestamp)>> {\n        let mut stmt = self.conn.prepare_cached(\n            \"SELECT registry_index.name, registry_src.name, registry_src.size, registry_src.timestamp\n             FROM registry_index, registry_src\n             WHERE registry_src.registry_id = registry_index.id\",\n        )?;\n        let rows = stmt\n            .query_map([], |row| {\n                let encoded_registry_name = row.get_unwrap(0);\n                let package_dir = row.get_unwrap(1);\n                let size = row.get_unwrap(2);\n                let timestamp = row.get_unwrap(3);\n                let kind = RegistrySrc {\n                    encoded_registry_name,\n                    package_dir,\n                    size,\n                };\n                Ok((kind, timestamp))\n            })?\n            .collect::<Result<Vec<_>, _>>()?;\n        Ok(rows)\n    }\n\n    /// Returns all git db timestamps.\n    pub fn git_db_all(&self) -> CargoResult<Vec<(GitDb, Timestamp)>> {\n        let mut stmt = self\n            .conn\n            .prepare_cached(\"SELECT name, timestamp FROM git_db\")?;\n        let rows = stmt\n            .query_map([], |row| {\n                let encoded_git_name = row.get_unwrap(0);\n                let timestamp = row.get_unwrap(1);\n                let kind = GitDb { encoded_git_name };\n                Ok((kind, timestamp))\n            })?\n            .collect::<Result<Vec<_>, _>>()?;\n        Ok(rows)\n    }\n\n    /// Returns all git checkout timestamps.\n    pub fn git_checkout_all(&self) -> CargoResult<Vec<(GitCheckout, Timestamp)>> {\n        let mut stmt = self.conn.prepare_cached(\n            \"SELECT git_db.name, git_checkout.name, git_checkout.size, git_checkout.timestamp\n             FROM git_db, git_checkout\n             WHERE git_checkout.git_id = git_db.id\",\n        )?;\n        let rows = stmt\n            .query_map([], |row| {\n                let encoded_git_name = row.get_unwrap(0);\n                let short_name = row.get_unwrap(1);\n                let size = row.get_unwrap(2);\n                let timestamp = row.get_unwrap(3);\n                let kind = GitCheckout {\n                    encoded_git_name,\n                    short_name,\n                    size,\n                };\n                Ok((kind, timestamp))\n            })?\n            .collect::<Result<Vec<_>, _>>()?;\n        Ok(rows)\n    }\n\n    /// Returns whether or not an auto GC should be performed, compared to the\n    /// last time it was recorded in the database.\n    pub fn should_run_auto_gc(&mut self, frequency: Duration) -> CargoResult<bool> {\n        trace!(target: \"gc\", \"should_run_auto_gc\");\n        if self.auto_gc_checked_this_session {\n            return Ok(false);\n        }\n        let last_auto_gc: Timestamp =\n            self.conn\n                .query_row(\"SELECT last_auto_gc FROM global_data\", [], |row| row.get(0))?;\n        let should_run = last_auto_gc + frequency.as_secs() < now();\n        trace!(target: \"gc\",\n            \"last auto gc was {}, {}\",\n            last_auto_gc,\n            if should_run { \"running\" } else { \"skipping\" }\n        );\n        self.auto_gc_checked_this_session = true;\n        Ok(should_run)\n    }\n\n    /// Writes to the database to indicate that an automatic GC has just been\n    /// completed.\n    pub fn set_last_auto_gc(&self) -> CargoResult<()> {\n        self.conn\n            .execute(\"UPDATE global_data SET last_auto_gc = ?1\", [now()])?;\n        Ok(())\n    }\n\n    /// Deletes files from the global cache based on the given options.\n    pub fn clean(&mut self, clean_ctx: &mut CleanContext<'_>, gc_opts: &GcOpts) -> CargoResult<()> {\n        self.clean_inner(clean_ctx, gc_opts)\n            .context(\"failed to clean entries from the global cache\")\n    }\n\n    #[tracing::instrument(skip_all)]\n    fn clean_inner(\n        &mut self,\n        clean_ctx: &mut CleanContext<'_>,\n        gc_opts: &GcOpts,\n    ) -> CargoResult<()> {\n        let gctx = clean_ctx.gctx;\n        let base = BasePaths {\n            index: gctx.registry_index_path().into_path_unlocked(),\n            git_db: gctx.git_db_path().into_path_unlocked(),\n            git_co: gctx.git_checkouts_path().into_path_unlocked(),\n            crate_dir: gctx.registry_cache_path().into_path_unlocked(),\n            src: gctx.registry_source_path().into_path_unlocked(),\n        };\n        let now = now();\n        trace!(target: \"gc\", \"cleaning {gc_opts:?}\");\n        let tx = self.conn.transaction()?;\n        let mut delete_paths = Vec::new();\n        // This can be an expensive operation, so only perform it if necessary.\n        if gc_opts.is_download_cache_opt_set() {\n            // TODO: Investigate how slow this might be.\n            Self::sync_db_with_files(\n                &tx,\n                now,\n                gctx,\n                &base,\n                gc_opts.is_download_cache_size_set(),\n                &mut delete_paths,\n            )\n            .context(\"failed to sync tracking database\")?\n        }\n        if let Some(max_age) = gc_opts.max_index_age {\n            let max_age = now - max_age.as_secs();\n            Self::get_registry_index_to_clean(&tx, max_age, &base, &mut delete_paths)?;\n        }\n        if let Some(max_age) = gc_opts.max_src_age {\n            let max_age = now - max_age.as_secs();\n            Self::get_registry_items_to_clean_age(\n                &tx,\n                max_age,\n                REGISTRY_SRC_TABLE,\n                &base.src,\n                &mut delete_paths,\n            )?;\n        }\n        if let Some(max_age) = gc_opts.max_crate_age {\n            let max_age = now - max_age.as_secs();\n            Self::get_registry_items_to_clean_age(\n                &tx,\n                max_age,\n                REGISTRY_CRATE_TABLE,\n                &base.crate_dir,\n                &mut delete_paths,\n            )?;\n        }\n        if let Some(max_age) = gc_opts.max_git_db_age {\n            let max_age = now - max_age.as_secs();\n            Self::get_git_db_items_to_clean(&tx, max_age, &base, &mut delete_paths)?;\n        }\n        if let Some(max_age) = gc_opts.max_git_co_age {\n            let max_age = now - max_age.as_secs();\n            Self::get_git_co_items_to_clean(&tx, max_age, &base.git_co, &mut delete_paths)?;\n        }\n        // Size collection must happen after date collection so that dates\n        // have precedence, since size constraints are a more blunt\n        // instrument.\n        //\n        // These are also complicated by the `--max-download-size` option\n        // overlapping with `--max-crate-size` and `--max-src-size`, which\n        // requires some coordination between those options which isn't\n        // necessary with the age-based options. An item's age is either older\n        // or it isn't, but contrast that with size which is based on the sum\n        // of all tracked items. Also, `--max-download-size` is summed against\n        // both the crate and src tracking, which requires combining them to\n        // compute the size, and then separating them to calculate the correct\n        // paths.\n        if let Some(max_size) = gc_opts.max_crate_size {\n            Self::get_registry_items_to_clean_size(\n                &tx,\n                max_size,\n                REGISTRY_CRATE_TABLE,\n                &base.crate_dir,\n                &mut delete_paths,\n            )?;\n        }\n        if let Some(max_size) = gc_opts.max_src_size {\n            Self::get_registry_items_to_clean_size(\n                &tx,\n                max_size,\n                REGISTRY_SRC_TABLE,\n                &base.src,\n                &mut delete_paths,\n            )?;\n        }\n        if let Some(max_size) = gc_opts.max_git_size {\n            Self::get_git_items_to_clean_size(&tx, max_size, &base, &mut delete_paths)?;\n        }\n        if let Some(max_size) = gc_opts.max_download_size {\n            Self::get_registry_items_to_clean_size_both(&tx, max_size, &base, &mut delete_paths)?;\n        }\n\n        clean_ctx.remove_paths(&delete_paths)?;\n\n        if clean_ctx.dry_run {\n            tx.rollback()?;\n        } else {\n            tx.commit()?;\n        }\n        Ok(())\n    }\n\n    /// Returns a list of directory entries in the given path that are\n    /// themselves directories.\n    fn list_dir_names(path: &Path) -> CargoResult<Vec<String>> {\n        Self::read_dir_with_filter(path, &|entry| {\n            entry.file_type().map_or(false, |ty| ty.is_dir())\n        })\n    }\n\n    /// Returns a list of names in a directory, filtered by the given callback.\n    fn read_dir_with_filter(\n        path: &Path,\n        filter: &dyn Fn(&std::fs::DirEntry) -> bool,\n    ) -> CargoResult<Vec<String>> {\n        let entries = match path.read_dir() {\n            Ok(e) => e,\n            Err(e) => {\n                if e.kind() == std::io::ErrorKind::NotFound {\n                    return Ok(Vec::new());\n                } else {\n                    return Err(\n                        anyhow::Error::new(e).context(format!(\"failed to read path `{path:?}`\"))\n                    );\n                }\n            }\n        };\n        let names = entries\n            .filter_map(|entry| entry.ok())\n            .filter(|entry| filter(entry))\n            .filter_map(|entry| entry.file_name().into_string().ok())\n            .collect();\n        Ok(names)\n    }\n\n    /// Synchronizes the database to match the files on disk.\n    ///\n    /// This performs the following cleanups:\n    ///\n    /// 1. Remove entries from the database that are missing on disk.\n    /// 2. Adds missing entries to the database that are on disk (such as when\n    ///    files are added by older versions of cargo).\n    /// 3. Fills in the `size` column where it is NULL (such as when something\n    ///    is added to disk by an older version of cargo, and one of the mark\n    ///    functions marked it without knowing the size).\n    ///\n    ///    Size computations are only done if `sync_size` is set since it can\n    ///    be a very expensive operation. This should only be set if the user\n    ///    requested to clean based on the cache size.\n    /// 4. Checks for orphaned files. For example, if there are `.crate` files\n    ///    associated with an index that does not exist.\n    ///\n    ///    These orphaned files will be added to `delete_paths` so that the\n    ///    caller can delete them.\n    #[tracing::instrument(skip(conn, gctx, base, delete_paths))]\n    fn sync_db_with_files(\n        conn: &Connection,\n        now: Timestamp,\n        gctx: &GlobalContext,\n        base: &BasePaths,\n        sync_size: bool,\n        delete_paths: &mut Vec<PathBuf>,\n    ) -> CargoResult<()> {\n        debug!(target: \"gc\", \"starting db sync\");\n        // For registry_index and git_db, add anything that is missing in the db.\n        Self::update_parent_for_missing_from_db(conn, now, REGISTRY_INDEX_TABLE, &base.index)?;\n        Self::update_parent_for_missing_from_db(conn, now, GIT_DB_TABLE, &base.git_db)?;\n\n        // For registry_crate, registry_src, and git_checkout, remove anything\n        // from the db that isn't on disk.\n        Self::update_db_for_removed(\n            conn,\n            REGISTRY_INDEX_TABLE,\n            \"registry_id\",\n            REGISTRY_CRATE_TABLE,\n            &base.crate_dir,\n        )?;\n        Self::update_db_for_removed(\n            conn,\n            REGISTRY_INDEX_TABLE,\n            \"registry_id\",\n            REGISTRY_SRC_TABLE,\n            &base.src,\n        )?;\n        Self::update_db_for_removed(conn, GIT_DB_TABLE, \"git_id\", GIT_CO_TABLE, &base.git_co)?;\n\n        // For registry_index and git_db, remove anything from the db that\n        // isn't on disk.\n        //\n        // This also collects paths for any child files that don't have their\n        // respective parent on disk.\n        Self::update_db_parent_for_removed_from_disk(\n            conn,\n            REGISTRY_INDEX_TABLE,\n            &base.index,\n            &[&base.crate_dir, &base.src],\n            delete_paths,\n        )?;\n        Self::update_db_parent_for_removed_from_disk(\n            conn,\n            GIT_DB_TABLE,\n            &base.git_db,\n            &[&base.git_co],\n            delete_paths,\n        )?;\n\n        // For registry_crate, registry_src, and git_checkout, add anything\n        // that is missing in the db.\n        Self::populate_untracked_crate(conn, now, &base.crate_dir)?;\n        Self::populate_untracked(\n            conn,\n            now,\n            gctx,\n            REGISTRY_INDEX_TABLE,\n            \"registry_id\",\n            REGISTRY_SRC_TABLE,\n            &base.src,\n            sync_size,\n        )?;\n        Self::populate_untracked(\n            conn,\n            now,\n            gctx,\n            GIT_DB_TABLE,\n            \"git_id\",\n            GIT_CO_TABLE,\n            &base.git_co,\n            sync_size,\n        )?;\n\n        // Update any NULL sizes if needed.\n        if sync_size {\n            Self::update_null_sizes(\n                conn,\n                gctx,\n                REGISTRY_INDEX_TABLE,\n                \"registry_id\",\n                REGISTRY_SRC_TABLE,\n                &base.src,\n            )?;\n            Self::update_null_sizes(\n                conn,\n                gctx,\n                GIT_DB_TABLE,\n                \"git_id\",\n                GIT_CO_TABLE,\n                &base.git_co,\n            )?;\n        }\n        Ok(())\n    }\n\n    /// For parent tables, add any entries that are on disk but aren't tracked in the db.\n    #[tracing::instrument(skip(conn, now, base_path))]\n    fn update_parent_for_missing_from_db(\n        conn: &Connection,\n        now: Timestamp,\n        parent_table_name: &str,\n        base_path: &Path,\n    ) -> CargoResult<()> {\n        trace!(target: \"gc\", \"checking for untracked parent to add to {parent_table_name}\");\n        let names = Self::list_dir_names(base_path)?;\n\n        let mut stmt = conn.prepare_cached(&format!(\n            \"INSERT INTO {parent_table_name} (name, timestamp)\n                VALUES (?1, ?2)\n                ON CONFLICT DO NOTHING\",\n        ))?;\n        for name in names {\n            stmt.execute(params![name, now])?;\n        }\n        Ok(())\n    }\n\n    /// Removes database entries for any files that are not on disk for the child tables.\n    ///\n    /// This could happen for example if the user manually deleted the file or\n    /// any such scenario where the filesystem and db are out of sync.\n    #[tracing::instrument(skip(conn, base_path))]\n    fn update_db_for_removed(\n        conn: &Connection,\n        parent_table_name: &str,\n        id_column_name: &str,\n        table_name: &str,\n        base_path: &Path,\n    ) -> CargoResult<()> {\n        trace!(target: \"gc\", \"checking for db entries to remove from {table_name}\");\n        let mut select_stmt = conn.prepare_cached(&format!(\n            \"SELECT {table_name}.rowid, {parent_table_name}.name, {table_name}.name\n             FROM {parent_table_name}, {table_name}\n             WHERE {table_name}.{id_column_name} = {parent_table_name}.id\",\n        ))?;\n        let mut delete_stmt =\n            conn.prepare_cached(&format!(\"DELETE FROM {table_name} WHERE rowid = ?1\"))?;\n        let mut rows = select_stmt.query([])?;\n        while let Some(row) = rows.next()? {\n            let rowid: i64 = row.get_unwrap(0);\n            let id_name: String = row.get_unwrap(1);\n            let name: String = row.get_unwrap(2);\n            if !base_path.join(id_name).join(name).exists() {\n                delete_stmt.execute([rowid])?;\n            }\n        }\n        Ok(())\n    }\n\n    /// Removes database entries for any files that are not on disk for the parent tables.\n    #[tracing::instrument(skip(conn, base_path, child_base_paths, delete_paths))]\n    fn update_db_parent_for_removed_from_disk(\n        conn: &Connection,\n        parent_table_name: &str,\n        base_path: &Path,\n        child_base_paths: &[&Path],\n        delete_paths: &mut Vec<PathBuf>,\n    ) -> CargoResult<()> {\n        trace!(target: \"gc\", \"checking for db entries to remove from {parent_table_name}\");\n        let mut select_stmt =\n            conn.prepare_cached(&format!(\"SELECT rowid, name FROM {parent_table_name}\"))?;\n        let mut delete_stmt =\n            conn.prepare_cached(&format!(\"DELETE FROM {parent_table_name} WHERE rowid = ?1\"))?;\n        let mut rows = select_stmt.query([])?;\n        while let Some(row) = rows.next()? {\n            let rowid: i64 = row.get_unwrap(0);\n            let id_name: String = row.get_unwrap(1);\n            if !base_path.join(&id_name).exists() {\n                delete_stmt.execute([rowid])?;\n                // Make sure any child data is also cleaned up.\n                for child_base in child_base_paths {\n                    let child_path = child_base.join(&id_name);\n                    if child_path.exists() {\n                        debug!(target: \"gc\", \"removing orphaned path {child_path:?}\");\n                        delete_paths.push(child_path);\n                    }\n                }\n            }\n        }\n        Ok(())\n    }\n\n    /// Updates the database to add any `.crate` files that are currently\n    /// not tracked (such as when they are downloaded by an older version of\n    /// cargo).\n    #[tracing::instrument(skip(conn, now, base_path))]\n    fn populate_untracked_crate(\n        conn: &Connection,\n        now: Timestamp,\n        base_path: &Path,\n    ) -> CargoResult<()> {\n        trace!(target: \"gc\", \"populating untracked crate files\");\n        let mut insert_stmt = conn.prepare_cached(\n            \"INSERT INTO registry_crate (registry_id, name, size, timestamp)\n             VALUES (?1, ?2, ?3, ?4)\n             ON CONFLICT DO NOTHING\",\n        )?;\n        let index_names = Self::list_dir_names(&base_path)?;\n        for index_name in index_names {\n            let Some(id) = Self::id_from_name(conn, REGISTRY_INDEX_TABLE, &index_name)? else {\n                // The id is missing from the database. This should be resolved\n                // via update_db_parent_for_removed_from_disk.\n                continue;\n            };\n            let index_path = base_path.join(index_name);\n            let crates = Self::read_dir_with_filter(&index_path, &|entry| {\n                entry.file_type().map_or(false, |ty| ty.is_file())\n                    && entry\n                        .file_name()\n                        .to_str()\n                        .map_or(false, |name| name.ends_with(\".crate\"))\n            })?;\n            for crate_name in crates {\n                // Missing files should have already been taken care of by\n                // update_db_for_removed.\n                let size = paths::metadata(index_path.join(&crate_name))?.len();\n                insert_stmt.execute(params![id, crate_name, size, now])?;\n            }\n        }\n        Ok(())\n    }\n\n    /// Updates the database to add any files that are currently not tracked\n    /// (such as when they are downloaded by an older version of cargo).\n    #[tracing::instrument(skip(conn, now, gctx, base_path, populate_size))]\n    fn populate_untracked(\n        conn: &Connection,\n        now: Timestamp,\n        gctx: &GlobalContext,\n        id_table_name: &str,\n        id_column_name: &str,\n        table_name: &str,\n        base_path: &Path,\n        populate_size: bool,\n    ) -> CargoResult<()> {\n        trace!(target: \"gc\", \"populating untracked files for {table_name}\");\n        // Gather names (and make sure they are in the database).\n        let id_names = Self::list_dir_names(&base_path)?;\n\n        // This SELECT is used to determine if the directory is already\n        // tracked. We don't want to do the expensive size computation unless\n        // necessary.\n        let mut select_stmt = conn.prepare_cached(&format!(\n            \"SELECT 1 FROM {table_name}\n             WHERE {id_column_name} = ?1 AND name = ?2\",\n        ))?;\n        let mut insert_stmt = conn.prepare_cached(&format!(\n            \"INSERT INTO {table_name} ({id_column_name}, name, size, timestamp)\n             VALUES (?1, ?2, ?3, ?4)\n             ON CONFLICT DO NOTHING\",\n        ))?;\n        let mut progress = Progress::with_style(\"Scanning\", ProgressStyle::Ratio, gctx);\n        // Compute the size of any directory not in the database.\n        for id_name in id_names {\n            let Some(id) = Self::id_from_name(conn, id_table_name, &id_name)? else {\n                // The id is missing from the database. This should be resolved\n                // via update_db_parent_for_removed_from_disk.\n                continue;\n            };\n            let index_path = base_path.join(id_name);\n            let names = Self::list_dir_names(&index_path)?;\n            let max = names.len();\n            for (i, name) in names.iter().enumerate() {\n                if select_stmt.exists(params![id, name])? {\n                    continue;\n                }\n                let dir_path = index_path.join(name);\n                if !dir_path.is_dir() {\n                    continue;\n                }\n                progress.tick(i, max, \"\")?;\n                let size = if populate_size {\n                    Some(du(&dir_path, table_name)?)\n                } else {\n                    None\n                };\n                insert_stmt.execute(params![id, name, size, now])?;\n            }\n        }\n        Ok(())\n    }\n\n    /// Fills in the `size` column where it is NULL.\n    ///\n    /// This can happen when something is added to disk by an older version of\n    /// cargo, and one of the mark functions marked it without knowing the\n    /// size.\n    ///\n    /// `update_db_for_removed` should be called before this is called.\n    #[tracing::instrument(skip(conn, gctx, base_path))]\n    fn update_null_sizes(\n        conn: &Connection,\n        gctx: &GlobalContext,\n        parent_table_name: &str,\n        id_column_name: &str,\n        table_name: &str,\n        base_path: &Path,\n    ) -> CargoResult<()> {\n        trace!(target: \"gc\", \"updating NULL size information in {table_name}\");\n        let mut null_stmt = conn.prepare_cached(&format!(\n            \"SELECT {table_name}.rowid, {table_name}.name, {parent_table_name}.name\n             FROM {table_name}, {parent_table_name}\n             WHERE {table_name}.size IS NULL AND {table_name}.{id_column_name} = {parent_table_name}.id\",\n        ))?;\n        let mut update_stmt = conn.prepare_cached(&format!(\n            \"UPDATE {table_name} SET size = ?1 WHERE rowid = ?2\"\n        ))?;\n        let mut progress = Progress::with_style(\"Scanning\", ProgressStyle::Ratio, gctx);\n        let rows: Vec<_> = null_stmt\n            .query_map([], |row| {\n                Ok((row.get_unwrap(0), row.get_unwrap(1), row.get_unwrap(2)))\n            })?\n            .collect();\n        let max = rows.len();\n        for (i, row) in rows.into_iter().enumerate() {\n            let (rowid, name, id_name): (i64, String, String) = row?;\n            let path = base_path.join(id_name).join(name);\n            progress.tick(i, max, \"\")?;\n            // Missing files should have already been taken care of by\n            // update_db_for_removed.\n            let size = du(&path, table_name)?;\n            update_stmt.execute(params![size, rowid])?;\n        }\n        Ok(())\n    }\n\n    /// Adds paths to delete from either `registry_crate` or `registry_src` whose\n    /// last use is older than the given timestamp.\n    fn get_registry_items_to_clean_age(\n        conn: &Connection,\n        max_age: Timestamp,\n        table_name: &str,\n        base_path: &Path,\n        delete_paths: &mut Vec<PathBuf>,\n    ) -> CargoResult<()> {\n        debug!(target: \"gc\", \"cleaning {table_name} since {max_age:?}\");\n        let mut stmt = conn.prepare_cached(&format!(\n            \"DELETE FROM {table_name} WHERE timestamp < ?1\n                RETURNING registry_id, name\"\n        ))?;\n        let rows = stmt\n            .query_map(params![max_age], |row| {\n                let registry_id = row.get_unwrap(0);\n                let name: String = row.get_unwrap(1);\n                Ok((registry_id, name))\n            })?\n            .collect::<Result<Vec<_>, _>>()?;\n        let ids: Vec<_> = rows.iter().map(|r| r.0).collect();\n        let id_map = Self::get_id_map(conn, REGISTRY_INDEX_TABLE, &ids)?;\n        for (id, name) in rows {\n            let encoded_registry_name = &id_map[&id];\n            delete_paths.push(base_path.join(encoded_registry_name).join(name));\n        }\n        Ok(())\n    }\n\n    /// Adds paths to delete from either `registry_crate` or `registry_src` in\n    /// order to keep the total size under the given max size.\n    fn get_registry_items_to_clean_size(\n        conn: &Connection,\n        max_size: u64,\n        table_name: &str,\n        base_path: &Path,\n        delete_paths: &mut Vec<PathBuf>,\n    ) -> CargoResult<()> {\n        debug!(target: \"gc\", \"cleaning {table_name} till under {max_size:?}\");\n        let total_size: u64 = conn.query_row(\n            &format!(\"SELECT coalesce(SUM(size), 0) FROM {table_name}\"),\n            [],\n            |row| row.get(0),\n        )?;\n        if total_size <= max_size {\n            return Ok(());\n        }\n        // This SQL statement selects all of the rows ordered by timestamp,\n        // and then uses a window function to keep a running total of the\n        // size. It selects all rows until the running total exceeds the\n        // threshold of the total number of bytes that we want to delete.\n        //\n        // The window function essentially computes an aggregate over all\n        // previous rows as it goes along. As long as the running size is\n        // below the total amount that we need to delete, it keeps picking\n        // more rows.\n        //\n        // The ORDER BY includes `name` mainly for test purposes so that\n        // entries with the same timestamp have deterministic behavior.\n        //\n        // The coalesce helps convert NULL to 0.\n        let mut stmt = conn.prepare(&format!(\n            \"DELETE FROM {table_name} WHERE rowid IN \\\n                (SELECT x.rowid FROM \\\n                    (SELECT rowid, size, SUM(size) OVER \\\n                        (ORDER BY timestamp, name ROWS UNBOUNDED PRECEDING) AS running_amount \\\n                        FROM {table_name}) x \\\n                    WHERE coalesce(x.running_amount, 0) - x.size < ?1) \\\n                RETURNING registry_id, name;\"\n        ))?;\n        let rows = stmt\n            .query_map(params![total_size - max_size], |row| {\n                let id = row.get_unwrap(0);\n                let name: String = row.get_unwrap(1);\n                Ok((id, name))\n            })?\n            .collect::<Result<Vec<_>, _>>()?;\n        // Convert registry_id to the encoded registry name, and join those.\n        let ids: Vec<_> = rows.iter().map(|r| r.0).collect();\n        let id_map = Self::get_id_map(conn, REGISTRY_INDEX_TABLE, &ids)?;\n        for (id, name) in rows {\n            let encoded_name = &id_map[&id];\n            delete_paths.push(base_path.join(encoded_name).join(name));\n        }\n        Ok(())\n    }\n\n    /// Adds paths to delete from both `registry_crate` and `registry_src` in\n    /// order to keep the total size under the given max size.\n    fn get_registry_items_to_clean_size_both(\n        conn: &Connection,\n        max_size: u64,\n        base: &BasePaths,\n        delete_paths: &mut Vec<PathBuf>,\n    ) -> CargoResult<()> {\n        debug!(target: \"gc\", \"cleaning download till under {max_size:?}\");\n\n        // This SQL statement selects from both registry_src and\n        // registry_crate so that sorting of timestamps incorporates both of\n        // them at the same time. It uses a const value of 1 or 2 as the first\n        // column so that the code below can determine which table the value\n        // came from.\n        let mut stmt = conn.prepare_cached(\n            \"SELECT 1, registry_src.rowid, registry_src.name AS name, registry_index.name,\n                    registry_src.size, registry_src.timestamp AS timestamp\n             FROM registry_src, registry_index\n             WHERE registry_src.registry_id = registry_index.id AND registry_src.size NOT NULL\n\n             UNION\n\n             SELECT 2, registry_crate.rowid, registry_crate.name AS name, registry_index.name,\n                    registry_crate.size, registry_crate.timestamp AS timestamp\n             FROM registry_crate, registry_index\n             WHERE registry_crate.registry_id = registry_index.id\n\n             ORDER BY timestamp, name\",\n        )?;\n        let mut delete_src_stmt =\n            conn.prepare_cached(\"DELETE FROM registry_src WHERE rowid = ?1\")?;\n        let mut delete_crate_stmt =\n            conn.prepare_cached(\"DELETE FROM registry_crate WHERE rowid = ?1\")?;\n        let rows = stmt\n            .query_map([], |row| {\n                Ok((\n                    row.get_unwrap(0),\n                    row.get_unwrap(1),\n                    row.get_unwrap(2),\n                    row.get_unwrap(3),\n                    row.get_unwrap(4),\n                ))\n            })?\n            .collect::<Result<Vec<(i64, i64, String, String, u64)>, _>>()?;\n        let mut total_size: u64 = rows.iter().map(|r| r.4).sum();\n        debug!(target: \"gc\", \"total download cache size appears to be {total_size}\");\n        for (table, rowid, name, index_name, size) in rows {\n            if total_size <= max_size {\n                break;\n            }\n            if table == 1 {\n                delete_paths.push(base.src.join(index_name).join(name));\n                delete_src_stmt.execute([rowid])?;\n            } else {\n                delete_paths.push(base.crate_dir.join(index_name).join(name));\n                delete_crate_stmt.execute([rowid])?;\n            }\n            // TODO: If delete crate, ensure src is also deleted.\n            total_size -= size;\n        }\n        Ok(())\n    }\n\n    /// Adds paths to delete from the git cache, keeping the total size under\n    /// the give value.\n    ///\n    /// Paths are relative to the `git` directory in the cache directory.\n    fn get_git_items_to_clean_size(\n        conn: &Connection,\n        max_size: u64,\n        base: &BasePaths,\n        delete_paths: &mut Vec<PathBuf>,\n    ) -> CargoResult<()> {\n        debug!(target: \"gc\", \"cleaning git till under {max_size:?}\");\n\n        // Collect all the sizes from git_db and git_checkouts, and then sort them by timestamp.\n        let mut stmt = conn.prepare_cached(\"SELECT rowid, name, timestamp FROM git_db\")?;\n        let mut git_info = stmt\n            .query_map([], |row| {\n                let rowid: i64 = row.get_unwrap(0);\n                let name: String = row.get_unwrap(1);\n                let timestamp: Timestamp = row.get_unwrap(2);\n                // Size is added below so that the error doesn't need to be\n                // converted to a rusqlite error.\n                Ok((timestamp, rowid, None, name, 0))\n            })?\n            .collect::<Result<Vec<_>, _>>()?;\n        for info in &mut git_info {\n            let size = cargo_util::du(&base.git_db.join(&info.3), &[])?;\n            info.4 = size;\n        }\n\n        let mut stmt = conn.prepare_cached(\n            \"SELECT git_checkout.rowid, git_db.name, git_checkout.name,\n                git_checkout.size, git_checkout.timestamp\n                FROM git_checkout, git_db\n                WHERE git_checkout.git_id = git_db.id AND git_checkout.size NOT NULL\",\n        )?;\n        let git_co_rows = stmt\n            .query_map([], |row| {\n                let rowid = row.get_unwrap(0);\n                let db_name: String = row.get_unwrap(1);\n                let name = row.get_unwrap(2);\n                let size = row.get_unwrap(3);\n                let timestamp = row.get_unwrap(4);\n                Ok((timestamp, rowid, Some(db_name), name, size))\n            })?\n            .collect::<Result<Vec<_>, _>>()?;\n        git_info.extend(git_co_rows);\n\n        // Sort by timestamp, and name. The name is included mostly for test\n        // purposes so that entries with the same timestamp have deterministic\n        // behavior.\n        git_info.sort_by(|a, b| (b.0, &b.3).cmp(&(a.0, &a.3)));\n\n        // Collect paths to delete.\n        let mut delete_db_stmt = conn.prepare_cached(\"DELETE FROM git_db WHERE rowid = ?1\")?;\n        let mut delete_co_stmt =\n            conn.prepare_cached(\"DELETE FROM git_checkout WHERE rowid = ?1\")?;\n        let mut total_size: u64 = git_info.iter().map(|r| r.4).sum();\n        debug!(target: \"gc\", \"total git cache size appears to be {total_size}\");\n        while let Some((_timestamp, rowid, db_name, name, size)) = git_info.pop() {\n            if total_size <= max_size {\n                break;\n            }\n            if let Some(db_name) = db_name {\n                delete_paths.push(base.git_co.join(db_name).join(name));\n                delete_co_stmt.execute([rowid])?;\n                total_size -= size;\n            } else {\n                total_size -= size;\n                delete_paths.push(base.git_db.join(&name));\n                delete_db_stmt.execute([rowid])?;\n                // If the db is deleted, then all the checkouts must be deleted.\n                let mut i = 0;\n                while i < git_info.len() {\n                    if git_info[i].2.as_deref() == Some(name.as_ref()) {\n                        let (_, rowid, db_name, name, size) = git_info.remove(i);\n                        delete_paths.push(base.git_co.join(db_name.unwrap()).join(name));\n                        delete_co_stmt.execute([rowid])?;\n                        total_size -= size;\n                    } else {\n                        i += 1;\n                    }\n                }\n            }\n        }\n        Ok(())\n    }\n\n    /// Adds paths to delete from `registry_index` whose last use is older\n    /// than the given timestamp.\n    fn get_registry_index_to_clean(\n        conn: &Connection,\n        max_age: Timestamp,\n        base: &BasePaths,\n        delete_paths: &mut Vec<PathBuf>,\n    ) -> CargoResult<()> {\n        debug!(target: \"gc\", \"cleaning index since {max_age:?}\");\n        let mut stmt = conn.prepare_cached(\n            \"DELETE FROM registry_index WHERE timestamp < ?1\n                RETURNING name\",\n        )?;\n        let mut rows = stmt.query([max_age])?;\n        while let Some(row) = rows.next()? {\n            let name: String = row.get_unwrap(0);\n            delete_paths.push(base.index.join(&name));\n            // Also delete .crate and src directories, since by definition\n            // they cannot be used without their index.\n            delete_paths.push(base.src.join(&name));\n            delete_paths.push(base.crate_dir.join(&name));\n        }\n        Ok(())\n    }\n\n    /// Adds paths to delete from `git_checkout` whose last use is\n    /// older than the given timestamp.\n    fn get_git_co_items_to_clean(\n        conn: &Connection,\n        max_age: Timestamp,\n        base_path: &Path,\n        delete_paths: &mut Vec<PathBuf>,\n    ) -> CargoResult<()> {\n        debug!(target: \"gc\", \"cleaning git co since {max_age:?}\");\n        let mut stmt = conn.prepare_cached(\n            \"DELETE FROM git_checkout WHERE timestamp < ?1\n                RETURNING git_id, name\",\n        )?;\n        let rows = stmt\n            .query_map(params![max_age], |row| {\n                let git_id = row.get_unwrap(0);\n                let name: String = row.get_unwrap(1);\n                Ok((git_id, name))\n            })?\n            .collect::<Result<Vec<_>, _>>()?;\n        let ids: Vec<_> = rows.iter().map(|r| r.0).collect();\n        let id_map = Self::get_id_map(conn, GIT_DB_TABLE, &ids)?;\n        for (id, name) in rows {\n            let encoded_git_name = &id_map[&id];\n            delete_paths.push(base_path.join(encoded_git_name).join(name));\n        }\n        Ok(())\n    }\n\n    /// Adds paths to delete from `git_db` in order to keep the total size\n    /// under the given max size.\n    fn get_git_db_items_to_clean(\n        conn: &Connection,\n        max_age: Timestamp,\n        base: &BasePaths,\n        delete_paths: &mut Vec<PathBuf>,\n    ) -> CargoResult<()> {\n        debug!(target: \"gc\", \"cleaning git db since {max_age:?}\");\n        let mut stmt = conn.prepare_cached(\n            \"DELETE FROM git_db WHERE timestamp < ?1\n                RETURNING name\",\n        )?;\n        let mut rows = stmt.query([max_age])?;\n        while let Some(row) = rows.next()? {\n            let name: String = row.get_unwrap(0);\n            delete_paths.push(base.git_db.join(&name));\n            // Also delete checkout directories, since by definition they\n            // cannot be used without their db.\n            delete_paths.push(base.git_co.join(&name));\n        }\n        Ok(())\n    }\n}\n\n/// Helper to generate the upsert for the parent tables.\n///\n/// This handles checking if the row already exists, and only updates the\n/// timestamp it if it hasn't been updated recently. This also handles keeping\n/// a cached map of the `id` value.\n///\n/// Unfortunately it is a bit tricky to share this code without a macro.\nmacro_rules! insert_or_update_parent {\n    ($self:expr, $conn:expr, $table_name:expr, $timestamps_field:ident, $keys_field:ident, $encoded_name:ident) => {\n        let mut select_stmt = $conn.prepare_cached(concat!(\n            \"SELECT id, timestamp FROM \",\n            $table_name,\n            \" WHERE name = ?1\"\n        ))?;\n        let mut insert_stmt = $conn.prepare_cached(concat!(\n            \"INSERT INTO \",\n            $table_name,\n            \" (name, timestamp)\n                VALUES (?1, ?2)\n                ON CONFLICT DO UPDATE SET timestamp=excluded.timestamp\n                RETURNING id\",\n        ))?;\n        let mut update_stmt = $conn.prepare_cached(concat!(\n            \"UPDATE \",\n            $table_name,\n            \" SET timestamp = ?1 WHERE id = ?2\"\n        ))?;\n        for (parent, new_timestamp) in std::mem::take(&mut $self.$timestamps_field) {\n            trace!(target: \"gc\",\n                concat!(\"insert \", $table_name, \" {:?} {}\"),\n                parent,\n                new_timestamp\n            );\n            let mut rows = select_stmt.query([parent.$encoded_name])?;\n            let id = if let Some(row) = rows.next()? {\n                let id: ParentId = row.get_unwrap(0);\n                let timestamp: Timestamp = row.get_unwrap(1);\n                if timestamp < new_timestamp - UPDATE_RESOLUTION {\n                    update_stmt.execute(params![new_timestamp, id])?;\n                }\n                id\n            } else {\n                insert_stmt.query_row(params![parent.$encoded_name, new_timestamp], |row| {\n                    row.get(0)\n                })?\n            };\n            match $self.$keys_field.entry(parent.$encoded_name) {\n                hash_map::Entry::Occupied(o) => {\n                    assert_eq!(*o.get(), id);\n                }\n                hash_map::Entry::Vacant(v) => {\n                    v.insert(id);\n                }\n            }\n        }\n        return Ok(());\n    };\n}\n\n/// This is a cache of modifications that will be saved to disk all at once\n/// via the [`DeferredGlobalLastUse::save`] method.\n///\n/// This is here to improve performance.\n#[derive(Debug)]\npub struct DeferredGlobalLastUse {\n    /// Cache of registry keys, used for faster fetching.\n    ///\n    /// The key is the registry name (which is its directory name) and the\n    /// value is the `id` in the `registry_index` table.\n    registry_keys: HashMap<InternedString, ParentId>,\n    /// Cache of git keys, used for faster fetching.\n    ///\n    /// The key is the git db name (which is its directory name) and the value\n    /// is the `id` in the `git_db` table.\n    git_keys: HashMap<InternedString, ParentId>,\n\n    /// New registry index entries to insert.\n    registry_index_timestamps: HashMap<RegistryIndex, Timestamp>,\n    /// New registry `.crate` entries to insert.\n    registry_crate_timestamps: HashMap<RegistryCrate, Timestamp>,\n    /// New registry src directory entries to insert.\n    registry_src_timestamps: HashMap<RegistrySrc, Timestamp>,\n    /// New git db entries to insert.\n    git_db_timestamps: HashMap<GitDb, Timestamp>,\n    /// New git checkout entries to insert.\n    git_checkout_timestamps: HashMap<GitCheckout, Timestamp>,\n    /// This is used so that a warning about failing to update the database is\n    /// only displayed once.\n    save_err_has_warned: bool,\n    /// The current time, used to improve performance to avoid accessing the\n    /// clock hundreds of times.\n    now: Timestamp,\n}\n\nimpl DeferredGlobalLastUse {\n    pub fn new() -> DeferredGlobalLastUse {\n        DeferredGlobalLastUse {\n            registry_keys: HashMap::new(),\n            git_keys: HashMap::new(),\n            registry_index_timestamps: HashMap::new(),\n            registry_crate_timestamps: HashMap::new(),\n            registry_src_timestamps: HashMap::new(),\n            git_db_timestamps: HashMap::new(),\n            git_checkout_timestamps: HashMap::new(),\n            save_err_has_warned: false,\n            now: now(),\n        }\n    }\n\n    pub fn is_empty(&self) -> bool {\n        self.registry_index_timestamps.is_empty()\n            && self.registry_crate_timestamps.is_empty()\n            && self.registry_src_timestamps.is_empty()\n            && self.git_db_timestamps.is_empty()\n            && self.git_checkout_timestamps.is_empty()\n    }\n\n    fn clear(&mut self) {\n        self.registry_index_timestamps.clear();\n        self.registry_crate_timestamps.clear();\n        self.registry_src_timestamps.clear();\n        self.git_db_timestamps.clear();\n        self.git_checkout_timestamps.clear();\n    }\n\n    /// Indicates the given [`RegistryIndex`] has been used right now.\n    pub fn mark_registry_index_used(&mut self, registry_index: RegistryIndex) {\n        self.mark_registry_index_used_stamp(registry_index, None);\n    }\n\n    /// Indicates the given [`RegistryCrate`] has been used right now.\n    ///\n    /// Also implicitly marks the index used, too.\n    pub fn mark_registry_crate_used(&mut self, registry_crate: RegistryCrate) {\n        self.mark_registry_crate_used_stamp(registry_crate, None);\n    }\n\n    /// Indicates the given [`RegistrySrc`] has been used right now.\n    ///\n    /// Also implicitly marks the index used, too.\n    pub fn mark_registry_src_used(&mut self, registry_src: RegistrySrc) {\n        self.mark_registry_src_used_stamp(registry_src, None);\n    }\n\n    /// Indicates the given [`GitCheckout`] has been used right now.\n    ///\n    /// Also implicitly marks the git db used, too.\n    pub fn mark_git_checkout_used(&mut self, git_checkout: GitCheckout) {\n        self.mark_git_checkout_used_stamp(git_checkout, None);\n    }\n\n    /// Indicates the given [`RegistryIndex`] has been used with the given\n    /// time (or \"now\" if `None`).\n    pub fn mark_registry_index_used_stamp(\n        &mut self,\n        registry_index: RegistryIndex,\n        timestamp: Option<&SystemTime>,\n    ) {\n        let timestamp = timestamp.map_or(self.now, to_timestamp);\n        self.registry_index_timestamps\n            .insert(registry_index, timestamp);\n    }\n\n    /// Indicates the given [`RegistryCrate`] has been used with the given\n    /// time (or \"now\" if `None`).\n    ///\n    /// Also implicitly marks the index used, too.\n    pub fn mark_registry_crate_used_stamp(\n        &mut self,\n        registry_crate: RegistryCrate,\n        timestamp: Option<&SystemTime>,\n    ) {\n        let timestamp = timestamp.map_or(self.now, to_timestamp);\n        let index = RegistryIndex {\n            encoded_registry_name: registry_crate.encoded_registry_name,\n        };\n        self.registry_index_timestamps.insert(index, timestamp);\n        self.registry_crate_timestamps\n            .insert(registry_crate, timestamp);\n    }\n\n    /// Indicates the given [`RegistrySrc`] has been used with the given\n    /// time (or \"now\" if `None`).\n    ///\n    /// Also implicitly marks the index used, too.\n    pub fn mark_registry_src_used_stamp(\n        &mut self,\n        registry_src: RegistrySrc,\n        timestamp: Option<&SystemTime>,\n    ) {\n        let timestamp = timestamp.map_or(self.now, to_timestamp);\n        let index = RegistryIndex {\n            encoded_registry_name: registry_src.encoded_registry_name,\n        };\n        self.registry_index_timestamps.insert(index, timestamp);\n        self.registry_src_timestamps.insert(registry_src, timestamp);\n    }\n\n    /// Indicates the given [`GitCheckout`] has been used with the given\n    /// time (or \"now\" if `None`).\n    ///\n    /// Also implicitly marks the git db used, too.\n    pub fn mark_git_checkout_used_stamp(\n        &mut self,\n        git_checkout: GitCheckout,\n        timestamp: Option<&SystemTime>,\n    ) {\n        let timestamp = timestamp.map_or(self.now, to_timestamp);\n        let db = GitDb {\n            encoded_git_name: git_checkout.encoded_git_name,\n        };\n        self.git_db_timestamps.insert(db, timestamp);\n        self.git_checkout_timestamps.insert(git_checkout, timestamp);\n    }\n\n    /// Saves all of the deferred information to the database.\n    ///\n    /// This will also clear the state of `self`.\n    #[tracing::instrument(skip_all)]\n    pub fn save(&mut self, tracker: &mut GlobalCacheTracker) -> CargoResult<()> {\n        trace!(target: \"gc\", \"saving last-use data\");\n        if self.is_empty() {\n            return Ok(());\n        }\n        let tx = tracker.conn.transaction()?;\n        // These must run before the ones that refer to their IDs.\n        self.insert_registry_index_from_cache(&tx)?;\n        self.insert_git_db_from_cache(&tx)?;\n        self.insert_registry_crate_from_cache(&tx)?;\n        self.insert_registry_src_from_cache(&tx)?;\n        self.insert_git_checkout_from_cache(&tx)?;\n        tx.commit()?;\n        trace!(target: \"gc\", \"last-use save complete\");\n        Ok(())\n    }\n\n    /// Variant of [`DeferredGlobalLastUse::save`] that does not return an\n    /// error.\n    ///\n    /// This will log or display a warning to the user.\n    pub fn save_no_error(&mut self, gctx: &GlobalContext) {\n        if let Err(e) = self.save_with_gctx(gctx) {\n            // Because there is an assertion in auto-gc that checks if this is\n            // empty, be sure to clear it so that assertion doesn't fail.\n            self.clear();\n            if !self.save_err_has_warned {\n                if is_silent_error(&e) && gctx.shell().verbosity() != Verbosity::Verbose {\n                    tracing::warn!(\"failed to save last-use data: {e:?}\");\n                } else {\n                    crate::display_warning_with_error(\n                        \"failed to save last-use data\\n\\\n                        This may prevent cargo from accurately tracking what is being \\\n                        used in its global cache. This information is used for \\\n                        automatically removing unused data in the cache.\",\n                        &e,\n                        &mut gctx.shell(),\n                    );\n                    self.save_err_has_warned = true;\n                }\n            }\n        }\n    }\n\n    fn save_with_gctx(&mut self, gctx: &GlobalContext) -> CargoResult<()> {\n        let mut tracker = gctx.global_cache_tracker()?;\n        self.save(&mut tracker)\n    }\n\n    /// Flushes all of the `registry_index_timestamps` to the database,\n    /// clearing `registry_index_timestamps`.\n    fn insert_registry_index_from_cache(&mut self, conn: &Connection) -> CargoResult<()> {\n        insert_or_update_parent!(\n            self,\n            conn,\n            \"registry_index\",\n            registry_index_timestamps,\n            registry_keys,\n            encoded_registry_name\n        );\n    }\n\n    /// Flushes all of the `git_db_timestamps` to the database,\n    /// clearing `registry_index_timestamps`.\n    fn insert_git_db_from_cache(&mut self, conn: &Connection) -> CargoResult<()> {\n        insert_or_update_parent!(\n            self,\n            conn,\n            \"git_db\",\n            git_db_timestamps,\n            git_keys,\n            encoded_git_name\n        );\n    }\n\n    /// Flushes all of the `registry_crate_timestamps` to the database,\n    /// clearing `registry_index_timestamps`.\n    fn insert_registry_crate_from_cache(&mut self, conn: &Connection) -> CargoResult<()> {\n        let registry_crate_timestamps = std::mem::take(&mut self.registry_crate_timestamps);\n        for (registry_crate, timestamp) in registry_crate_timestamps {\n            trace!(target: \"gc\", \"insert registry crate {registry_crate:?} {timestamp}\");\n            let registry_id = self.registry_id(conn, registry_crate.encoded_registry_name)?;\n            let mut stmt = conn.prepare_cached(\n                \"INSERT INTO registry_crate (registry_id, name, size, timestamp)\n                 VALUES (?1, ?2, ?3, ?4)\n                 ON CONFLICT DO UPDATE SET timestamp=excluded.timestamp\n                    WHERE timestamp < ?5\n                 \",\n            )?;\n            stmt.execute(params![\n                registry_id,\n                registry_crate.crate_filename,\n                registry_crate.size,\n                timestamp,\n                timestamp - UPDATE_RESOLUTION\n            ])?;\n        }\n        Ok(())\n    }\n\n    /// Flushes all of the `registry_src_timestamps` to the database,\n    /// clearing `registry_index_timestamps`.\n    fn insert_registry_src_from_cache(&mut self, conn: &Connection) -> CargoResult<()> {\n        let registry_src_timestamps = std::mem::take(&mut self.registry_src_timestamps);\n        for (registry_src, timestamp) in registry_src_timestamps {\n            trace!(target: \"gc\", \"insert registry src {registry_src:?} {timestamp}\");\n            let registry_id = self.registry_id(conn, registry_src.encoded_registry_name)?;\n            let mut stmt = conn.prepare_cached(\n                \"INSERT INTO registry_src (registry_id, name, size, timestamp)\n                 VALUES (?1, ?2, ?3, ?4)\n                 ON CONFLICT DO UPDATE SET timestamp=excluded.timestamp\n                    WHERE timestamp < ?5\n                 \",\n            )?;\n            stmt.execute(params![\n                registry_id,\n                registry_src.package_dir,\n                registry_src.size,\n                timestamp,\n                timestamp - UPDATE_RESOLUTION\n            ])?;\n        }\n\n        Ok(())\n    }\n\n    /// Flushes all of the `git_checkout_timestamps` to the database,\n    /// clearing `registry_index_timestamps`.\n    fn insert_git_checkout_from_cache(&mut self, conn: &Connection) -> CargoResult<()> {\n        let git_checkout_timestamps = std::mem::take(&mut self.git_checkout_timestamps);\n        for (git_checkout, timestamp) in git_checkout_timestamps {\n            let git_id = self.git_id(conn, git_checkout.encoded_git_name)?;\n            let mut stmt = conn.prepare_cached(\n                \"INSERT INTO git_checkout (git_id, name, size, timestamp)\n                 VALUES (?1, ?2, ?3, ?4)\n                 ON CONFLICT DO UPDATE SET timestamp=excluded.timestamp\n                    WHERE timestamp < ?5\",\n            )?;\n            stmt.execute(params![\n                git_id,\n                git_checkout.short_name,\n                git_checkout.size,\n                timestamp,\n                timestamp - UPDATE_RESOLUTION\n            ])?;\n        }\n\n        Ok(())\n    }\n\n    /// Returns the numeric ID of the registry, either fetching from the local\n    /// cache, or getting it from the database.\n    ///\n    /// It is an error if the registry does not exist.\n    fn registry_id(\n        &mut self,\n        conn: &Connection,\n        encoded_registry_name: InternedString,\n    ) -> CargoResult<ParentId> {\n        match self.registry_keys.get(&encoded_registry_name) {\n            Some(i) => Ok(*i),\n            None => {\n                let Some(id) = GlobalCacheTracker::id_from_name(\n                    conn,\n                    REGISTRY_INDEX_TABLE,\n                    &encoded_registry_name,\n                )?\n                else {\n                    bail!(\n                        \"expected registry_index {encoded_registry_name} to exist, but wasn't found\"\n                    );\n                };\n                self.registry_keys.insert(encoded_registry_name, id);\n                Ok(id)\n            }\n        }\n    }\n\n    /// Returns the numeric ID of the git db, either fetching from the local\n    /// cache, or getting it from the database.\n    ///\n    /// It is an error if the git db does not exist.\n    fn git_id(\n        &mut self,\n        conn: &Connection,\n        encoded_git_name: InternedString,\n    ) -> CargoResult<ParentId> {\n        match self.git_keys.get(&encoded_git_name) {\n            Some(i) => Ok(*i),\n            None => {\n                let Some(id) =\n                    GlobalCacheTracker::id_from_name(conn, GIT_DB_TABLE, &encoded_git_name)?\n                else {\n                    bail!(\"expected git_db {encoded_git_name} to exist, but wasn't found\")\n                };\n                self.git_keys.insert(encoded_git_name, id);\n                Ok(id)\n            }\n        }\n    }\n}\n\n/// Converts a [`SystemTime`] to a [`Timestamp`] which can be stored in the database.\nfn to_timestamp(t: &SystemTime) -> Timestamp {\n    t.duration_since(SystemTime::UNIX_EPOCH)\n        .expect(\"invalid clock\")\n        .as_secs()\n}\n\n/// Returns the current time.\n///\n/// This supports pretending that the time is different for testing using an\n/// environment variable.\n///\n/// If possible, try to avoid calling this too often since accessing clocks\n/// can be a little slow on some systems.\n#[expect(\n    clippy::disallowed_methods,\n    reason = \"testing only, no reason for config support\"\n)]\nfn now() -> Timestamp {\n    match std::env::var(\"__CARGO_TEST_LAST_USE_NOW\") {\n        Ok(now) => now.parse().unwrap(),\n        Err(_) => to_timestamp(&SystemTime::now()),\n    }\n}\n\n/// Returns whether or not the given error should cause a warning to be\n/// displayed to the user.\n///\n/// In some situations, like a read-only global cache, we don't want to spam\n/// the user with a warning. I think once cargo has controllable lints, I\n/// think we should consider changing this to always warn, but give the user\n/// an option to silence the warning.\npub fn is_silent_error(e: &anyhow::Error) -> bool {\n    if let Some(e) = e.downcast_ref::<rusqlite::Error>() {\n        if matches!(\n            e.sqlite_error_code(),\n            Some(ErrorCode::CannotOpen | ErrorCode::ReadOnly)\n        ) {\n            return true;\n        }\n    }\n    false\n}\n\n/// Returns the disk usage for a git checkout directory.\n#[tracing::instrument]\nfn du_git_checkout(path: &Path) -> CargoResult<u64> {\n    // !.git is used because clones typically use hardlinks for the git\n    // contents. TODO: Verify behavior on Windows.\n    // TODO: Or even better, switch to worktrees, and remove this.\n    cargo_util::du(&path, &[\"!.git\"])\n}\n\nfn du(path: &Path, table_name: &str) -> CargoResult<u64> {\n    if table_name == GIT_CO_TABLE {\n        du_git_checkout(path)\n    } else {\n        cargo_util::du(&path, &[])\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/manifest.rs",
    "content": "use std::borrow::Cow;\nuse std::collections::{BTreeMap, HashMap};\nuse std::fmt;\nuse std::hash::{Hash, Hasher};\nuse std::path::{Path, PathBuf};\nuse std::rc::Rc;\nuse std::sync::Arc;\n\nuse anyhow::Context as _;\nuse cargo_util_schemas::manifest::RustVersion;\nuse cargo_util_schemas::manifest::{Hints, TomlManifest, TomlProfiles};\nuse semver::Version;\nuse serde::Serialize;\nuse serde::ser;\nuse url::Url;\n\nuse crate::core::compiler::rustdoc::RustdocScrapeExamples;\nuse crate::core::compiler::{CompileKind, CrateType};\nuse crate::core::resolver::ResolveBehavior;\nuse crate::core::{Dependency, PackageId, PackageIdSpec, Patch, SourceId, Summary};\nuse crate::core::{Edition, Feature, Features, WorkspaceConfig};\nuse crate::util::errors::*;\nuse crate::util::interning::InternedString;\nuse crate::util::{Filesystem, GlobalContext, short_hash};\n\npub const MANIFEST_PREAMBLE: &str = \"\\\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \\\"normalize\\\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\";\n\npub enum EitherManifest {\n    Real(Manifest),\n    Virtual(VirtualManifest),\n}\n\nimpl EitherManifest {\n    pub fn warnings_mut(&mut self) -> &mut Warnings {\n        match self {\n            EitherManifest::Real(r) => r.warnings_mut(),\n            EitherManifest::Virtual(v) => v.warnings_mut(),\n        }\n    }\n    pub(crate) fn workspace_config(&self) -> &WorkspaceConfig {\n        match *self {\n            EitherManifest::Real(ref r) => r.workspace_config(),\n            EitherManifest::Virtual(ref v) => v.workspace_config(),\n        }\n    }\n}\n\n/// Contains all the information about a package, as loaded from a `Cargo.toml`.\n///\n/// This is deserialized using the [`TomlManifest`] type.\n#[derive(Clone, Debug)]\npub struct Manifest {\n    // alternate forms of manifests:\n    contents: Option<Rc<String>>,\n    document: Option<Rc<toml::Spanned<toml::de::DeTable<'static>>>>,\n    original_toml: Option<Rc<TomlManifest>>,\n    normalized_toml: Rc<TomlManifest>,\n    summary: Summary,\n\n    // this form of manifest:\n    targets: Vec<Target>,\n    default_kind: Option<CompileKind>,\n    forced_kind: Option<CompileKind>,\n    links: Option<String>,\n    warnings: Warnings,\n    exclude: Vec<String>,\n    include: Vec<String>,\n    metadata: ManifestMetadata,\n    custom_metadata: Option<toml::Value>,\n    publish: Option<Vec<String>>,\n    replace: Vec<(PackageIdSpec, Dependency)>,\n    patch: HashMap<Url, Vec<Patch>>,\n    workspace: WorkspaceConfig,\n    unstable_features: Features,\n    edition: Edition,\n    rust_version: Option<RustVersion>,\n    im_a_teapot: Option<bool>,\n    default_run: Option<String>,\n    metabuild: Option<Vec<String>>,\n    resolve_behavior: Option<ResolveBehavior>,\n    lint_rustflags: Vec<String>,\n    hints: Option<Hints>,\n    embedded: bool,\n}\n\n/// When parsing `Cargo.toml`, some warnings should silenced\n/// if the manifest comes from a dependency. `ManifestWarning`\n/// allows this delayed emission of warnings.\n#[derive(Clone, Debug)]\npub struct DelayedWarning {\n    pub message: String,\n    pub is_critical: bool,\n}\n\n#[derive(Clone, Debug)]\npub struct Warnings(Vec<DelayedWarning>);\n\n#[derive(Clone, Debug)]\npub struct VirtualManifest {\n    // alternate forms of manifests:\n    contents: Option<Rc<String>>,\n    document: Option<Rc<toml::Spanned<toml::de::DeTable<'static>>>>,\n    original_toml: Option<Rc<TomlManifest>>,\n    normalized_toml: Rc<TomlManifest>,\n\n    // this form of manifest:\n    replace: Vec<(PackageIdSpec, Dependency)>,\n    patch: HashMap<Url, Vec<Patch>>,\n    workspace: WorkspaceConfig,\n    warnings: Warnings,\n    features: Features,\n    resolve_behavior: Option<ResolveBehavior>,\n}\n\n/// General metadata about a package which is just blindly uploaded to the\n/// registry.\n///\n/// Note that many of these fields can contain invalid values such as the\n/// homepage, repository, documentation, or license. These fields are not\n/// validated by cargo itself, but rather it is up to the registry when uploaded\n/// to validate these fields. Cargo will itself accept any valid TOML\n/// specification for these values.\n#[derive(PartialEq, Clone, Debug)]\npub struct ManifestMetadata {\n    pub authors: Vec<String>,\n    pub keywords: Vec<String>,\n    pub categories: Vec<String>,\n    pub license: Option<String>,\n    pub license_file: Option<String>,\n    pub description: Option<String>,   // Not in Markdown\n    pub readme: Option<String>,        // File, not contents\n    pub homepage: Option<String>,      // URL\n    pub repository: Option<String>,    // URL\n    pub documentation: Option<String>, // URL\n    pub badges: BTreeMap<String, BTreeMap<String, String>>,\n    pub links: Option<String>,\n    pub rust_version: Option<RustVersion>,\n}\n\nimpl ManifestMetadata {\n    /// Whether the given env var should be tracked by Cargo's dep-info.\n    pub fn should_track(env_key: &str) -> bool {\n        let keys = MetadataEnvs::keys();\n        keys.contains(&env_key)\n    }\n\n    pub fn env_var<'a>(&'a self, env_key: &str) -> Option<Cow<'a, str>> {\n        MetadataEnvs::var(self, env_key)\n    }\n\n    pub fn env_vars(&self) -> impl Iterator<Item = (&'static str, Cow<'_, str>)> {\n        MetadataEnvs::keys()\n            .iter()\n            .map(|k| (*k, MetadataEnvs::var(self, k).unwrap()))\n    }\n}\n\nmacro_rules! get_metadata_env {\n    ($meta:ident, $field:ident) => {\n        $meta.$field.as_deref().unwrap_or_default().into()\n    };\n    ($meta:ident, $field:ident, $to_var:expr) => {\n        $to_var($meta).into()\n    };\n}\n\nstruct MetadataEnvs;\n\nmacro_rules! metadata_envs {\n    (\n        $(\n            ($field:ident, $key:literal$(, $to_var:expr)?),\n        )*\n    ) => {\n        impl MetadataEnvs {\n            fn keys() -> &'static [&'static str] {\n                &[$($key),*]\n            }\n\n            fn var<'a>(meta: &'a ManifestMetadata, key: &str) -> Option<Cow<'a, str>> {\n                match key {\n                    $($key => Some(get_metadata_env!(meta, $field$(, $to_var)?)),)*\n                    _ => None,\n                }\n            }\n        }\n    }\n}\n\n// Metadata environmental variables that are emitted to rustc. Usable by `env!()`\n// If these change we need to trigger a rebuild.\n// NOTE: The env var name will be prefixed with `CARGO_PKG_`\nmetadata_envs! {\n    (description, \"CARGO_PKG_DESCRIPTION\"),\n    (homepage, \"CARGO_PKG_HOMEPAGE\"),\n    (repository, \"CARGO_PKG_REPOSITORY\"),\n    (license, \"CARGO_PKG_LICENSE\"),\n    (license_file, \"CARGO_PKG_LICENSE_FILE\"),\n    (authors, \"CARGO_PKG_AUTHORS\", |m: &ManifestMetadata| m.authors.join(\":\")),\n    (rust_version, \"CARGO_PKG_RUST_VERSION\", |m: &ManifestMetadata| m.rust_version.as_ref().map(ToString::to_string).unwrap_or_default()),\n    (readme, \"CARGO_PKG_README\"),\n}\n\n#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]\npub enum TargetKind {\n    Lib(Vec<CrateType>),\n    Bin,\n    Test,\n    Bench,\n    ExampleLib(Vec<CrateType>),\n    ExampleBin,\n    CustomBuild,\n}\n\nimpl ser::Serialize for TargetKind {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        use self::TargetKind::*;\n        match self {\n            Lib(kinds) => s.collect_seq(kinds.iter().map(|t| t.to_string())),\n            Bin => [\"bin\"].serialize(s),\n            ExampleBin | ExampleLib(_) => [\"example\"].serialize(s),\n            Test => [\"test\"].serialize(s),\n            CustomBuild => [\"custom-build\"].serialize(s),\n            Bench => [\"bench\"].serialize(s),\n        }\n    }\n}\n\nimpl fmt::Debug for TargetKind {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        use self::TargetKind::*;\n        match *self {\n            Lib(ref kinds) => kinds.fmt(f),\n            Bin => \"bin\".fmt(f),\n            ExampleBin | ExampleLib(_) => \"example\".fmt(f),\n            Test => \"test\".fmt(f),\n            CustomBuild => \"custom-build\".fmt(f),\n            Bench => \"bench\".fmt(f),\n        }\n    }\n}\n\nimpl TargetKind {\n    pub fn description(&self) -> &'static str {\n        match self {\n            TargetKind::Lib(..) => \"lib\",\n            TargetKind::Bin => \"bin\",\n            TargetKind::Test => \"integration-test\",\n            TargetKind::ExampleBin | TargetKind::ExampleLib(..) => \"example\",\n            TargetKind::Bench => \"bench\",\n            TargetKind::CustomBuild => \"build-script\",\n        }\n    }\n\n    /// Returns whether production of this artifact requires the object files\n    /// from dependencies to be available.\n    ///\n    /// This only returns `false` when all we're producing is an rlib, otherwise\n    /// it will return `true`.\n    pub fn requires_upstream_objects(&self) -> bool {\n        match self {\n            TargetKind::Lib(kinds) | TargetKind::ExampleLib(kinds) => {\n                kinds.iter().any(|k| k.requires_upstream_objects())\n            }\n            _ => true,\n        }\n    }\n\n    /// Returns whether production of this artifact could benefit from splitting metadata\n    /// into a .rmeta file.\n    pub fn benefits_from_no_embed_metadata(&self) -> bool {\n        match self {\n            TargetKind::Lib(kinds) | TargetKind::ExampleLib(kinds) => {\n                kinds.iter().any(|k| k.benefits_from_no_embed_metadata())\n            }\n            _ => false,\n        }\n    }\n\n    /// Returns the arguments suitable for `--crate-type` to pass to rustc.\n    pub fn rustc_crate_types(&self) -> Vec<CrateType> {\n        match self {\n            TargetKind::Lib(kinds) | TargetKind::ExampleLib(kinds) => kinds.clone(),\n            TargetKind::CustomBuild\n            | TargetKind::Bench\n            | TargetKind::Test\n            | TargetKind::ExampleBin\n            | TargetKind::Bin => vec![CrateType::Bin],\n        }\n    }\n}\n\n/// Information about a binary, a library, an example, etc. that is part of the\n/// package.\n#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]\npub struct Target {\n    inner: Arc<TargetInner>,\n}\n\n#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]\nstruct TargetInner {\n    kind: TargetKind,\n    name: String,\n    // Whether the name was inferred by Cargo, or explicitly given.\n    name_inferred: bool,\n    // Note that `bin_name` is used for the cargo-feature `different_binary_name`\n    bin_name: Option<String>,\n    // Note that the `src_path` here is excluded from the `Hash` implementation\n    // as it's absolute currently and is otherwise a little too brittle for\n    // causing rebuilds. Instead the hash for the path that we send to the\n    // compiler is handled elsewhere.\n    src_path: TargetSourcePath,\n    required_features: Option<Vec<String>>,\n    tested: bool,\n    benched: bool,\n    doc: bool,\n    doctest: bool,\n    harness: bool, // whether to use the test harness (--test)\n    for_host: bool,\n    proc_macro: bool,\n    edition: Edition,\n    doc_scrape_examples: RustdocScrapeExamples,\n}\n\n#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]\npub enum TargetSourcePath {\n    Path(PathBuf),\n    Metabuild,\n}\n\nimpl TargetSourcePath {\n    pub fn path(&self) -> Option<&Path> {\n        match self {\n            TargetSourcePath::Path(path) => Some(path.as_ref()),\n            TargetSourcePath::Metabuild => None,\n        }\n    }\n\n    pub fn is_path(&self) -> bool {\n        matches!(self, TargetSourcePath::Path(_))\n    }\n}\n\nimpl Hash for TargetSourcePath {\n    fn hash<H: Hasher>(&self, _: &mut H) {\n        // ...\n    }\n}\n\nimpl fmt::Debug for TargetSourcePath {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            TargetSourcePath::Path(path) => path.fmt(f),\n            TargetSourcePath::Metabuild => \"metabuild\".fmt(f),\n        }\n    }\n}\n\nimpl From<PathBuf> for TargetSourcePath {\n    fn from(path: PathBuf) -> Self {\n        assert!(path.is_absolute(), \"`{}` is not absolute\", path.display());\n        TargetSourcePath::Path(path)\n    }\n}\n\n#[derive(Serialize)]\nstruct SerializedTarget<'a> {\n    /// Is this a `--bin bin`, `--lib`, `--example ex`?\n    /// Serialized as a list of strings for historical reasons.\n    kind: &'a TargetKind,\n    /// Corresponds to `--crate-type` compiler attribute.\n    /// See <https://doc.rust-lang.org/reference/linkage.html>\n    crate_types: Vec<CrateType>,\n    name: &'a str,\n    src_path: Option<&'a PathBuf>,\n    edition: &'a str,\n    #[serde(rename = \"required-features\", skip_serializing_if = \"Option::is_none\")]\n    required_features: Option<Vec<&'a str>>,\n    /// Whether docs should be built for the target via `cargo doc`\n    /// See <https://doc.rust-lang.org/cargo/commands/cargo-doc.html#target-selection>\n    doc: bool,\n    doctest: bool,\n    /// Whether tests should be run for the target (`test` field in `Cargo.toml`)\n    test: bool,\n}\n\nimpl ser::Serialize for Target {\n    fn serialize<S: ser::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {\n        let src_path = match self.src_path() {\n            TargetSourcePath::Path(p) => Some(p),\n            // Unfortunately getting the correct path would require access to\n            // target_dir, which is not available here.\n            TargetSourcePath::Metabuild => None,\n        };\n        SerializedTarget {\n            kind: self.kind(),\n            crate_types: self.rustc_crate_types(),\n            name: self.name(),\n            src_path,\n            edition: &self.edition().to_string(),\n            required_features: self\n                .required_features()\n                .map(|rf| rf.iter().map(|s| s.as_str()).collect()),\n            doc: self.documented(),\n            doctest: self.doctested() && self.doctestable(),\n            test: self.tested(),\n        }\n        .serialize(s)\n    }\n}\n\nimpl fmt::Debug for Target {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.inner.fmt(f)\n    }\n}\n\ncompact_debug! {\n    impl fmt::Debug for TargetInner {\n        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n            let (default, default_name) = {\n                match &self.kind {\n                    TargetKind::Lib(kinds) => {\n                        (\n                            Target::lib_target(\n                                &self.name,\n                                kinds.clone(),\n                                self.src_path.path().unwrap().to_path_buf(),\n                                self.edition,\n                            ).inner,\n                            format!(\"lib_target({:?}, {:?}, {:?}, {:?})\",\n                                    self.name, kinds, self.src_path, self.edition),\n                        )\n                    }\n                    TargetKind::CustomBuild => {\n                        match self.src_path {\n                            TargetSourcePath::Path(ref path) => {\n                                (\n                                    Target::custom_build_target(\n                                        &self.name,\n                                        path.to_path_buf(),\n                                        self.edition,\n                                    ).inner,\n                                    format!(\"custom_build_target({:?}, {:?}, {:?})\",\n                                            self.name, path, self.edition),\n                                )\n                            }\n                            TargetSourcePath::Metabuild => {\n                                (\n                                    Target::metabuild_target(&self.name).inner,\n                                    format!(\"metabuild_target({:?})\", self.name),\n                                )\n                            }\n                        }\n                    }\n                    _ => (\n                        Target::new(self.src_path.clone(), self.edition).inner,\n                        format!(\"with_path({:?}, {:?})\", self.src_path, self.edition),\n                    ),\n                }\n            };\n            [debug_the_fields(\n                kind\n                name\n                name_inferred\n                bin_name\n                src_path\n                required_features\n                tested\n                benched\n                doc\n                doctest\n                harness\n                for_host\n                proc_macro\n                edition\n                doc_scrape_examples\n            )]\n        }\n    }\n}\n\nimpl Manifest {\n    pub fn new(\n        contents: Option<Rc<String>>,\n        document: Option<Rc<toml::Spanned<toml::de::DeTable<'static>>>>,\n        original_toml: Option<Rc<TomlManifest>>,\n        normalized_toml: Rc<TomlManifest>,\n        summary: Summary,\n\n        default_kind: Option<CompileKind>,\n        forced_kind: Option<CompileKind>,\n        targets: Vec<Target>,\n        exclude: Vec<String>,\n        include: Vec<String>,\n        links: Option<String>,\n        metadata: ManifestMetadata,\n        custom_metadata: Option<toml::Value>,\n        publish: Option<Vec<String>>,\n        replace: Vec<(PackageIdSpec, Dependency)>,\n        patch: HashMap<Url, Vec<Patch>>,\n        workspace: WorkspaceConfig,\n        unstable_features: Features,\n        edition: Edition,\n        rust_version: Option<RustVersion>,\n        im_a_teapot: Option<bool>,\n        default_run: Option<String>,\n        metabuild: Option<Vec<String>>,\n        resolve_behavior: Option<ResolveBehavior>,\n        lint_rustflags: Vec<String>,\n        hints: Option<Hints>,\n        embedded: bool,\n    ) -> Manifest {\n        Manifest {\n            contents,\n            document,\n            original_toml,\n            normalized_toml,\n            summary,\n\n            default_kind,\n            forced_kind,\n            targets,\n            warnings: Warnings::new(),\n            exclude,\n            include,\n            links,\n            metadata,\n            custom_metadata,\n            publish,\n            replace,\n            patch,\n            workspace,\n            unstable_features,\n            edition,\n            rust_version,\n            im_a_teapot,\n            default_run,\n            metabuild,\n            resolve_behavior,\n            lint_rustflags,\n            hints,\n            embedded,\n        }\n    }\n\n    /// The raw contents of the original TOML\n    pub fn contents(&self) -> Option<&str> {\n        self.contents.as_deref().map(|c| c.as_str())\n    }\n    /// See [`Manifest::normalized_toml`] for what \"normalized\" means\n    pub fn to_normalized_contents(&self) -> CargoResult<String> {\n        let toml = toml::to_string_pretty(self.normalized_toml())?;\n        Ok(format!(\"{}\\n{}\", MANIFEST_PREAMBLE, toml))\n    }\n    /// Collection of spans for the original TOML\n    pub fn document(&self) -> Option<&toml::Spanned<toml::de::DeTable<'static>>> {\n        self.document.as_deref()\n    }\n    /// The [`TomlManifest`] as parsed from [`Manifest::document`]\n    pub fn original_toml(&self) -> Option<&TomlManifest> {\n        self.original_toml.as_deref()\n    }\n    /// The [`TomlManifest`] with all fields expanded\n    ///\n    /// This is the intersection of what fields need resolving for cargo-publish that also are\n    /// useful for the operation of cargo, including\n    /// - workspace inheritance\n    /// - target discovery\n    pub fn normalized_toml(&self) -> &TomlManifest {\n        &self.normalized_toml\n    }\n    pub fn summary(&self) -> &Summary {\n        &self.summary\n    }\n    pub fn summary_mut(&mut self) -> &mut Summary {\n        &mut self.summary\n    }\n\n    pub fn dependencies(&self) -> &[Dependency] {\n        self.summary.dependencies()\n    }\n    pub fn default_kind(&self) -> Option<CompileKind> {\n        self.default_kind\n    }\n    pub fn forced_kind(&self) -> Option<CompileKind> {\n        self.forced_kind\n    }\n    pub fn exclude(&self) -> &[String] {\n        &self.exclude\n    }\n    pub fn include(&self) -> &[String] {\n        &self.include\n    }\n    pub fn metadata(&self) -> &ManifestMetadata {\n        &self.metadata\n    }\n    pub fn name(&self) -> InternedString {\n        self.package_id().name()\n    }\n    pub fn package_id(&self) -> PackageId {\n        self.summary.package_id()\n    }\n    pub fn targets(&self) -> &[Target] {\n        &self.targets\n    }\n    // It is used by cargo-c, please do not remove it\n    pub fn targets_mut(&mut self) -> &mut [Target] {\n        &mut self.targets\n    }\n    pub fn version(&self) -> &Version {\n        self.package_id().version()\n    }\n    pub fn warnings_mut(&mut self) -> &mut Warnings {\n        &mut self.warnings\n    }\n    pub fn warnings(&self) -> &Warnings {\n        &self.warnings\n    }\n    pub fn profiles(&self) -> Option<&TomlProfiles> {\n        self.normalized_toml.profile.as_ref()\n    }\n    pub fn publish(&self) -> &Option<Vec<String>> {\n        &self.publish\n    }\n    pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] {\n        &self.replace\n    }\n    pub fn patch(&self) -> &HashMap<Url, Vec<Patch>> {\n        &self.patch\n    }\n    pub fn links(&self) -> Option<&str> {\n        self.links.as_deref()\n    }\n    pub fn is_embedded(&self) -> bool {\n        self.embedded\n    }\n\n    pub fn workspace_config(&self) -> &WorkspaceConfig {\n        &self.workspace\n    }\n\n    /// Unstable, nightly features that are enabled in this manifest.\n    pub fn unstable_features(&self) -> &Features {\n        &self.unstable_features\n    }\n\n    /// The style of resolver behavior to use, declared with the `resolver` field.\n    ///\n    /// Returns `None` if it is not specified.\n    pub fn resolve_behavior(&self) -> Option<ResolveBehavior> {\n        self.resolve_behavior\n    }\n\n    /// `RUSTFLAGS` from the `[lints]` table\n    pub fn lint_rustflags(&self) -> &[String] {\n        self.lint_rustflags.as_slice()\n    }\n\n    pub fn hints(&self) -> Option<&Hints> {\n        self.hints.as_ref()\n    }\n\n    pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Manifest {\n        Manifest {\n            summary: self.summary.map_source(to_replace, replace_with),\n            ..self\n        }\n    }\n\n    pub fn feature_gate(&self) -> CargoResult<()> {\n        if self.im_a_teapot.is_some() {\n            self.unstable_features\n                .require(Feature::test_dummy_unstable())\n                .with_context(|| {\n                    \"the `im-a-teapot` manifest key is unstable and may \\\n                     not work properly in England\"\n                })?;\n        }\n\n        if self.default_kind.is_some() || self.forced_kind.is_some() {\n            self.unstable_features\n                .require(Feature::per_package_target())\n                .with_context(|| {\n                    \"the `package.default-target` and `package.forced-target` \\\n                     manifest keys are unstable and may not work properly\"\n                })?;\n        }\n\n        Ok(())\n    }\n\n    // Just a helper function to test out `-Z` flags on Cargo\n    pub fn print_teapot(&self, gctx: &GlobalContext) {\n        if let Some(teapot) = self.im_a_teapot {\n            if gctx.cli_unstable().print_im_a_teapot {\n                crate::drop_println!(gctx, \"im-a-teapot = {}\", teapot);\n            }\n        }\n    }\n\n    pub fn edition(&self) -> Edition {\n        self.edition\n    }\n\n    pub fn rust_version(&self) -> Option<&RustVersion> {\n        self.rust_version.as_ref()\n    }\n\n    pub fn custom_metadata(&self) -> Option<&toml::Value> {\n        self.custom_metadata.as_ref()\n    }\n\n    pub fn default_run(&self) -> Option<&str> {\n        self.default_run.as_deref()\n    }\n\n    pub fn metabuild(&self) -> Option<&Vec<String>> {\n        self.metabuild.as_ref()\n    }\n\n    pub fn metabuild_path(&self, target_dir: Filesystem) -> PathBuf {\n        let hash = short_hash(&self.package_id());\n        target_dir\n            .into_path_unlocked()\n            .join(\".metabuild\")\n            .join(format!(\"metabuild-{}-{}.rs\", self.name(), hash))\n    }\n}\n\nimpl VirtualManifest {\n    pub fn new(\n        contents: Option<Rc<String>>,\n        document: Option<Rc<toml::Spanned<toml::de::DeTable<'static>>>>,\n        original_toml: Option<Rc<TomlManifest>>,\n        normalized_toml: Rc<TomlManifest>,\n        replace: Vec<(PackageIdSpec, Dependency)>,\n        patch: HashMap<Url, Vec<Patch>>,\n        workspace: WorkspaceConfig,\n        features: Features,\n        resolve_behavior: Option<ResolveBehavior>,\n    ) -> VirtualManifest {\n        VirtualManifest {\n            contents,\n            document,\n            original_toml,\n            normalized_toml,\n            replace,\n            patch,\n            workspace,\n            warnings: Warnings::new(),\n            features,\n            resolve_behavior,\n        }\n    }\n\n    /// The raw contents of the original TOML\n    pub fn contents(&self) -> Option<&str> {\n        self.contents.as_deref().map(|c| c.as_str())\n    }\n    /// Collection of spans for the original TOML\n    pub fn document(&self) -> Option<&toml::Spanned<toml::de::DeTable<'static>>> {\n        self.document.as_deref()\n    }\n    /// The [`TomlManifest`] as parsed from [`VirtualManifest::document`]\n    pub fn original_toml(&self) -> Option<&TomlManifest> {\n        self.original_toml.as_deref()\n    }\n    /// The [`TomlManifest`] with all fields expanded\n    pub fn normalized_toml(&self) -> &TomlManifest {\n        &self.normalized_toml\n    }\n\n    pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] {\n        &self.replace\n    }\n\n    pub fn patch(&self) -> &HashMap<Url, Vec<Patch>> {\n        &self.patch\n    }\n\n    pub fn workspace_config(&self) -> &WorkspaceConfig {\n        &self.workspace\n    }\n\n    pub fn profiles(&self) -> Option<&TomlProfiles> {\n        self.normalized_toml.profile.as_ref()\n    }\n\n    pub fn warnings_mut(&mut self) -> &mut Warnings {\n        &mut self.warnings\n    }\n\n    pub fn warnings(&self) -> &Warnings {\n        &self.warnings\n    }\n\n    pub fn unstable_features(&self) -> &Features {\n        &self.features\n    }\n\n    /// The style of resolver behavior to use, declared with the `resolver` field.\n    ///\n    /// Returns `None` if it is not specified.\n    pub fn resolve_behavior(&self) -> Option<ResolveBehavior> {\n        self.resolve_behavior\n    }\n}\n\nimpl Target {\n    fn new(src_path: TargetSourcePath, edition: Edition) -> Target {\n        Target {\n            inner: Arc::new(TargetInner {\n                kind: TargetKind::Bin,\n                name: String::new(),\n                name_inferred: false,\n                bin_name: None,\n                src_path,\n                required_features: None,\n                doc: false,\n                doctest: false,\n                harness: true,\n                for_host: false,\n                proc_macro: false,\n                doc_scrape_examples: RustdocScrapeExamples::Unset,\n                edition,\n                tested: true,\n                benched: true,\n            }),\n        }\n    }\n\n    fn with_path(src_path: PathBuf, edition: Edition) -> Target {\n        Target::new(TargetSourcePath::from(src_path), edition)\n    }\n\n    pub fn lib_target(\n        name: &str,\n        crate_targets: Vec<CrateType>,\n        src_path: PathBuf,\n        edition: Edition,\n    ) -> Target {\n        let mut target = Target::with_path(src_path, edition);\n        target\n            .set_kind(TargetKind::Lib(crate_targets))\n            .set_name(name)\n            .set_doctest(true)\n            .set_doc(true);\n        target\n    }\n\n    pub fn bin_target(\n        name: &str,\n        bin_name: Option<String>,\n        src_path: PathBuf,\n        required_features: Option<Vec<String>>,\n        edition: Edition,\n    ) -> Target {\n        let mut target = Target::with_path(src_path, edition);\n        target\n            .set_kind(TargetKind::Bin)\n            .set_name(name)\n            .set_binary_name(bin_name)\n            .set_required_features(required_features)\n            .set_doc(true);\n        target\n    }\n\n    /// Builds a `Target` corresponding to the `build = \"build.rs\"` entry.\n    pub fn custom_build_target(name: &str, src_path: PathBuf, edition: Edition) -> Target {\n        let mut target = Target::with_path(src_path, edition);\n        target\n            .set_kind(TargetKind::CustomBuild)\n            .set_name(name)\n            .set_for_host(true)\n            .set_benched(false)\n            .set_tested(false)\n            .set_doc_scrape_examples(RustdocScrapeExamples::Disabled);\n        target\n    }\n\n    pub fn metabuild_target(name: &str) -> Target {\n        let mut target = Target::new(TargetSourcePath::Metabuild, Edition::Edition2018);\n        target\n            .set_kind(TargetKind::CustomBuild)\n            .set_name(name)\n            .set_for_host(true)\n            .set_benched(false)\n            .set_tested(false)\n            .set_doc_scrape_examples(RustdocScrapeExamples::Disabled);\n        target\n    }\n\n    pub fn example_target(\n        name: &str,\n        crate_targets: Vec<CrateType>,\n        src_path: PathBuf,\n        required_features: Option<Vec<String>>,\n        edition: Edition,\n    ) -> Target {\n        let kind = if crate_targets.is_empty() || crate_targets.iter().all(|t| *t == CrateType::Bin)\n        {\n            TargetKind::ExampleBin\n        } else {\n            TargetKind::ExampleLib(crate_targets)\n        };\n        let mut target = Target::with_path(src_path, edition);\n        target\n            .set_kind(kind)\n            .set_name(name)\n            .set_required_features(required_features)\n            .set_tested(false)\n            .set_benched(false);\n        target\n    }\n\n    pub fn test_target(\n        name: &str,\n        src_path: PathBuf,\n        required_features: Option<Vec<String>>,\n        edition: Edition,\n    ) -> Target {\n        let mut target = Target::with_path(src_path, edition);\n        target\n            .set_kind(TargetKind::Test)\n            .set_name(name)\n            .set_required_features(required_features)\n            .set_benched(false);\n        target\n    }\n\n    pub fn bench_target(\n        name: &str,\n        src_path: PathBuf,\n        required_features: Option<Vec<String>>,\n        edition: Edition,\n    ) -> Target {\n        let mut target = Target::with_path(src_path, edition);\n        target\n            .set_kind(TargetKind::Bench)\n            .set_name(name)\n            .set_required_features(required_features)\n            .set_tested(false);\n        target\n    }\n\n    pub fn name(&self) -> &str {\n        &self.inner.name\n    }\n    pub fn name_inferred(&self) -> bool {\n        self.inner.name_inferred\n    }\n    pub fn crate_name(&self) -> String {\n        self.name().replace(\"-\", \"_\")\n    }\n    pub fn src_path(&self) -> &TargetSourcePath {\n        &self.inner.src_path\n    }\n    pub fn set_src_path(&mut self, src_path: TargetSourcePath) {\n        Arc::make_mut(&mut self.inner).src_path = src_path;\n    }\n    pub fn required_features(&self) -> Option<&Vec<String>> {\n        self.inner.required_features.as_ref()\n    }\n    pub fn kind(&self) -> &TargetKind {\n        &self.inner.kind\n    }\n    pub fn tested(&self) -> bool {\n        self.inner.tested\n    }\n    pub fn harness(&self) -> bool {\n        self.inner.harness\n    }\n    pub fn documented(&self) -> bool {\n        self.inner.doc\n    }\n    // A proc-macro or build-script.\n    pub fn for_host(&self) -> bool {\n        self.inner.for_host\n    }\n    pub fn proc_macro(&self) -> bool {\n        self.inner.proc_macro\n    }\n    pub fn edition(&self) -> Edition {\n        self.inner.edition\n    }\n    pub fn doc_scrape_examples(&self) -> RustdocScrapeExamples {\n        self.inner.doc_scrape_examples\n    }\n    pub fn benched(&self) -> bool {\n        self.inner.benched\n    }\n    pub fn doctested(&self) -> bool {\n        self.inner.doctest\n    }\n\n    pub fn doctestable(&self) -> bool {\n        match self.kind() {\n            TargetKind::Lib(kinds) => kinds.iter().any(|k| {\n                *k == CrateType::Rlib || *k == CrateType::Lib || *k == CrateType::ProcMacro\n            }),\n            _ => false,\n        }\n    }\n\n    pub fn is_lib(&self) -> bool {\n        matches!(self.kind(), TargetKind::Lib(_))\n    }\n\n    pub fn is_dylib(&self) -> bool {\n        match self.kind() {\n            TargetKind::Lib(libs) => libs.contains(&CrateType::Dylib),\n            _ => false,\n        }\n    }\n\n    pub fn is_cdylib(&self) -> bool {\n        match self.kind() {\n            TargetKind::Lib(libs) => libs.contains(&CrateType::Cdylib),\n            _ => false,\n        }\n    }\n\n    pub fn is_staticlib(&self) -> bool {\n        match self.kind() {\n            TargetKind::Lib(libs) => libs.contains(&CrateType::Staticlib),\n            _ => false,\n        }\n    }\n\n    /// Returns whether this target produces an artifact which can be linked\n    /// into a Rust crate.\n    ///\n    /// This only returns true for certain kinds of libraries.\n    pub fn is_linkable(&self) -> bool {\n        match self.kind() {\n            TargetKind::Lib(kinds) => kinds.iter().any(|k| k.is_linkable()),\n            _ => false,\n        }\n    }\n\n    pub fn is_bin(&self) -> bool {\n        *self.kind() == TargetKind::Bin\n    }\n\n    pub fn is_example(&self) -> bool {\n        matches!(\n            self.kind(),\n            TargetKind::ExampleBin | TargetKind::ExampleLib(..)\n        )\n    }\n\n    /// Returns `true` if it is a binary or executable example.\n    /// NOTE: Tests are `false`!\n    pub fn is_executable(&self) -> bool {\n        self.is_bin() || self.is_exe_example()\n    }\n\n    /// Returns `true` if it is an executable example.\n    pub fn is_exe_example(&self) -> bool {\n        // Needed for --all-examples in contexts where only runnable examples make sense\n        matches!(self.kind(), TargetKind::ExampleBin)\n    }\n\n    pub fn is_test(&self) -> bool {\n        *self.kind() == TargetKind::Test\n    }\n    pub fn is_bench(&self) -> bool {\n        *self.kind() == TargetKind::Bench\n    }\n    pub fn is_custom_build(&self) -> bool {\n        *self.kind() == TargetKind::CustomBuild\n    }\n\n    /// Returns `true` if it is a compile time dependencies, e.g., build script or proc macro\n    pub fn is_compile_time_dependency(&self) -> bool {\n        self.is_custom_build() || self.proc_macro()\n    }\n\n    /// Returns the arguments suitable for `--crate-type` to pass to rustc.\n    pub fn rustc_crate_types(&self) -> Vec<CrateType> {\n        self.kind().rustc_crate_types()\n    }\n\n    pub fn set_tested(&mut self, tested: bool) -> &mut Target {\n        Arc::make_mut(&mut self.inner).tested = tested;\n        self\n    }\n    pub fn set_benched(&mut self, benched: bool) -> &mut Target {\n        Arc::make_mut(&mut self.inner).benched = benched;\n        self\n    }\n    pub fn set_doctest(&mut self, doctest: bool) -> &mut Target {\n        Arc::make_mut(&mut self.inner).doctest = doctest;\n        self\n    }\n    pub fn set_for_host(&mut self, for_host: bool) -> &mut Target {\n        Arc::make_mut(&mut self.inner).for_host = for_host;\n        self\n    }\n    pub fn set_proc_macro(&mut self, proc_macro: bool) -> &mut Target {\n        Arc::make_mut(&mut self.inner).proc_macro = proc_macro;\n        self\n    }\n    pub fn set_edition(&mut self, edition: Edition) -> &mut Target {\n        Arc::make_mut(&mut self.inner).edition = edition;\n        self\n    }\n    pub fn set_doc_scrape_examples(\n        &mut self,\n        doc_scrape_examples: RustdocScrapeExamples,\n    ) -> &mut Target {\n        Arc::make_mut(&mut self.inner).doc_scrape_examples = doc_scrape_examples;\n        self\n    }\n    pub fn set_harness(&mut self, harness: bool) -> &mut Target {\n        Arc::make_mut(&mut self.inner).harness = harness;\n        self\n    }\n    pub fn set_doc(&mut self, doc: bool) -> &mut Target {\n        Arc::make_mut(&mut self.inner).doc = doc;\n        self\n    }\n    pub fn set_kind(&mut self, kind: TargetKind) -> &mut Target {\n        Arc::make_mut(&mut self.inner).kind = kind;\n        self\n    }\n    pub fn set_name(&mut self, name: &str) -> &mut Target {\n        Arc::make_mut(&mut self.inner).name = name.to_string();\n        self\n    }\n    pub fn set_name_inferred(&mut self, inferred: bool) -> &mut Target {\n        Arc::make_mut(&mut self.inner).name_inferred = inferred;\n        self\n    }\n    pub fn set_binary_name(&mut self, bin_name: Option<String>) -> &mut Target {\n        Arc::make_mut(&mut self.inner).bin_name = bin_name;\n        self\n    }\n    pub fn set_required_features(&mut self, required_features: Option<Vec<String>>) -> &mut Target {\n        Arc::make_mut(&mut self.inner).required_features = required_features;\n        self\n    }\n    pub fn binary_filename(&self) -> Option<String> {\n        self.inner.bin_name.clone()\n    }\n    pub fn description_named(&self) -> String {\n        match self.kind() {\n            TargetKind::Lib(..) => \"lib\".to_string(),\n            TargetKind::Bin => format!(\"bin \\\"{}\\\"\", self.name()),\n            TargetKind::Test => format!(\"test \\\"{}\\\"\", self.name()),\n            TargetKind::Bench => format!(\"bench \\\"{}\\\"\", self.name()),\n            TargetKind::ExampleLib(..) | TargetKind::ExampleBin => {\n                format!(\"example \\\"{}\\\"\", self.name())\n            }\n            TargetKind::CustomBuild => \"build script\".to_string(),\n        }\n    }\n}\n\nimpl fmt::Display for Target {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self.kind() {\n            TargetKind::Lib(..) => write!(f, \"Target(lib)\"),\n            TargetKind::Bin => write!(f, \"Target(bin: {})\", self.name()),\n            TargetKind::Test => write!(f, \"Target(test: {})\", self.name()),\n            TargetKind::Bench => write!(f, \"Target(bench: {})\", self.name()),\n            TargetKind::ExampleBin | TargetKind::ExampleLib(..) => {\n                write!(f, \"Target(example: {})\", self.name())\n            }\n            TargetKind::CustomBuild => write!(f, \"Target(script)\"),\n        }\n    }\n}\n\nimpl Warnings {\n    fn new() -> Warnings {\n        Warnings(Vec::new())\n    }\n\n    pub fn add_warning(&mut self, s: String) {\n        self.0.push(DelayedWarning {\n            message: s,\n            is_critical: false,\n        })\n    }\n\n    pub fn add_critical_warning(&mut self, s: String) {\n        self.0.push(DelayedWarning {\n            message: s,\n            is_critical: true,\n        })\n    }\n\n    pub fn warnings(&self) -> &[DelayedWarning] {\n        &self.0\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/mod.rs",
    "content": "pub use self::dependency::{Dependency, Patch, PatchLocation, SerializedDependency};\npub use self::features::{CliUnstable, Edition, Feature, Features};\npub use self::manifest::{EitherManifest, VirtualManifest};\npub use self::manifest::{Manifest, Target, TargetKind};\npub use self::package::{Package, PackageSet};\npub use self::package_id::PackageId;\npub use self::package_id_spec::PackageIdSpecQuery;\npub use self::registry::Registry;\npub use self::resolver::{Resolve, ResolveVersion};\npub use self::shell::{Shell, Verbosity};\npub use self::source_id::SourceId;\npub use self::summary::{FeatureMap, FeatureValue, Summary};\npub use self::workspace::{\n    MaybePackage, Workspace, WorkspaceConfig, WorkspaceRootConfig, find_workspace_root,\n    find_workspace_root_with_membership_check, resolve_relative_path,\n};\npub use cargo_util_schemas::core::{GitReference, PackageIdSpec, SourceKind};\n\npub mod compiler;\npub mod dependency;\npub mod features;\npub mod gc;\npub mod global_cache_tracker;\npub mod manifest;\npub mod package;\npub mod package_id;\nmod package_id_spec;\npub mod profiles;\npub mod registry;\npub mod resolver;\npub mod shell;\nmod source_id;\npub mod summary;\nmod workspace;\n"
  },
  {
    "path": "src/cargo/core/package.rs",
    "content": "use std::cell::OnceCell;\nuse std::cell::{Cell, Ref, RefCell, RefMut};\nuse std::cmp::Ordering;\nuse std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};\nuse std::fmt;\nuse std::hash;\nuse std::mem;\nuse std::path::{Path, PathBuf};\nuse std::rc::Rc;\nuse std::time::{Duration, Instant};\n\nuse anyhow::Context as _;\nuse cargo_util_schemas::manifest::{Hints, RustVersion};\nuse curl::easy::Easy;\nuse curl::multi::{EasyHandle, Multi};\nuse semver::Version;\nuse serde::Serialize;\nuse tracing::debug;\n\nuse crate::core::compiler::{CompileKind, RustcTargetData};\nuse crate::core::dependency::DepKind;\nuse crate::core::resolver::features::ForceAllTargets;\nuse crate::core::resolver::{HasDevUnits, Resolve};\nuse crate::core::{\n    CliUnstable, Dependency, Features, Manifest, PackageId, PackageIdSpec, SerializedDependency,\n    SourceId, Target,\n};\nuse crate::core::{Summary, Workspace};\nuse crate::sources::source::{MaybePackage, SourceMap};\nuse crate::util::HumanBytes;\nuse crate::util::cache_lock::{CacheLock, CacheLockMode};\nuse crate::util::errors::{CargoResult, HttpNotSuccessful};\nuse crate::util::interning::InternedString;\nuse crate::util::network::http::HttpTimeout;\nuse crate::util::network::http::http_handle_and_timeout;\nuse crate::util::network::retry::{Retry, RetryResult};\nuse crate::util::network::sleep::SleepTracker;\nuse crate::util::{self, GlobalContext, Progress, ProgressStyle, internal};\n\n/// Information about a package that is available somewhere in the file system.\n///\n/// A package is a `Cargo.toml` file plus all the files that are part of it.\n#[derive(Clone)]\npub struct Package {\n    inner: Rc<PackageInner>,\n}\n\n#[derive(Clone)]\n// TODO: is `manifest_path` a relic?\nstruct PackageInner {\n    /// The package's manifest.\n    manifest: Manifest,\n    /// The root of the package.\n    manifest_path: PathBuf,\n}\n\nimpl Ord for Package {\n    fn cmp(&self, other: &Package) -> Ordering {\n        self.package_id().cmp(&other.package_id())\n    }\n}\n\nimpl PartialOrd for Package {\n    fn partial_cmp(&self, other: &Package) -> Option<Ordering> {\n        Some(self.cmp(other))\n    }\n}\n\n/// A Package in a form where `Serialize` can be derived.\n#[derive(Serialize)]\npub struct SerializedPackage {\n    name: InternedString,\n    version: Version,\n    id: PackageIdSpec,\n    license: Option<String>,\n    license_file: Option<String>,\n    description: Option<String>,\n    source: SourceId,\n    dependencies: Vec<SerializedDependency>,\n    targets: Vec<Target>,\n    features: BTreeMap<InternedString, Vec<InternedString>>,\n    manifest_path: PathBuf,\n    metadata: Option<toml::Value>,\n    publish: Option<Vec<String>>,\n    authors: Vec<String>,\n    categories: Vec<String>,\n    keywords: Vec<String>,\n    readme: Option<String>,\n    repository: Option<String>,\n    homepage: Option<String>,\n    documentation: Option<String>,\n    edition: String,\n    links: Option<String>,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    metabuild: Option<Vec<String>>,\n    default_run: Option<String>,\n    rust_version: Option<RustVersion>,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    hints: Option<Hints>,\n}\n\nimpl Package {\n    /// Creates a package from a manifest and its location.\n    pub fn new(manifest: Manifest, manifest_path: &Path) -> Package {\n        Package {\n            inner: Rc::new(PackageInner {\n                manifest,\n                manifest_path: manifest_path.to_path_buf(),\n            }),\n        }\n    }\n\n    /// Gets the manifest dependencies.\n    pub fn dependencies(&self) -> &[Dependency] {\n        self.manifest().dependencies()\n    }\n    /// Gets the manifest.\n    pub fn manifest(&self) -> &Manifest {\n        &self.inner.manifest\n    }\n    /// Gets the manifest.\n    pub fn manifest_mut(&mut self) -> &mut Manifest {\n        &mut Rc::make_mut(&mut self.inner).manifest\n    }\n    /// Gets the path to the manifest.\n    pub fn manifest_path(&self) -> &Path {\n        &self.inner.manifest_path\n    }\n    /// Gets the name of the package.\n    pub fn name(&self) -> InternedString {\n        self.package_id().name()\n    }\n    /// Gets the `PackageId` object for the package (fully defines a package).\n    pub fn package_id(&self) -> PackageId {\n        self.manifest().package_id()\n    }\n    /// Gets the root folder of the package.\n    pub fn root(&self) -> &Path {\n        self.manifest_path().parent().unwrap()\n    }\n    /// Gets the summary for the package.\n    pub fn summary(&self) -> &Summary {\n        self.manifest().summary()\n    }\n    /// Gets the targets specified in the manifest.\n    pub fn targets(&self) -> &[Target] {\n        self.manifest().targets()\n    }\n    /// Gets the library crate for this package, if it exists.\n    pub fn library(&self) -> Option<&Target> {\n        self.targets().iter().find(|t| t.is_lib())\n    }\n    /// Gets the current package version.\n    pub fn version(&self) -> &Version {\n        self.package_id().version()\n    }\n    /// Gets the package authors.\n    pub fn authors(&self) -> &Vec<String> {\n        &self.manifest().metadata().authors\n    }\n\n    /// Returns `None` if the package is set to publish.\n    /// Returns `Some(allowed_registries)` if publishing is limited to specified\n    /// registries or if package is set to not publish.\n    pub fn publish(&self) -> &Option<Vec<String>> {\n        self.manifest().publish()\n    }\n    /// Returns `true` if this package is a proc-macro.\n    pub fn proc_macro(&self) -> bool {\n        self.targets().iter().any(|target| target.proc_macro())\n    }\n    /// Gets the package's minimum Rust version.\n    pub fn rust_version(&self) -> Option<&RustVersion> {\n        self.manifest().rust_version()\n    }\n\n    /// Gets the package's hints.\n    pub fn hints(&self) -> Option<&Hints> {\n        self.manifest().hints()\n    }\n\n    /// Returns `true` if the package uses a custom build script for any target.\n    pub fn has_custom_build(&self) -> bool {\n        self.targets().iter().any(|t| t.is_custom_build())\n    }\n\n    pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Package {\n        Package {\n            inner: Rc::new(PackageInner {\n                manifest: self.manifest().clone().map_source(to_replace, replace_with),\n                manifest_path: self.manifest_path().to_owned(),\n            }),\n        }\n    }\n\n    pub fn serialized(\n        &self,\n        unstable_flags: &CliUnstable,\n        cargo_features: &Features,\n    ) -> SerializedPackage {\n        let summary = self.manifest().summary();\n        let package_id = summary.package_id();\n        let manmeta = self.manifest().metadata();\n        // Filter out metabuild targets. They are an internal implementation\n        // detail that is probably not relevant externally. There's also not a\n        // real path to show in `src_path`, and this avoids changing the format.\n        let targets: Vec<Target> = self\n            .manifest()\n            .targets()\n            .iter()\n            .filter(|t| t.src_path().is_path())\n            .cloned()\n            .collect();\n        // Convert Vec<FeatureValue> to Vec<InternedString>\n        let crate_features = summary\n            .features()\n            .iter()\n            .map(|(k, v)| (*k, v.iter().map(|fv| fv.to_string().into()).collect()))\n            .collect();\n\n        SerializedPackage {\n            name: package_id.name(),\n            version: package_id.version().clone(),\n            id: package_id.to_spec(),\n            license: manmeta.license.clone(),\n            license_file: manmeta.license_file.clone(),\n            description: manmeta.description.clone(),\n            source: summary.source_id(),\n            dependencies: summary\n                .dependencies()\n                .iter()\n                .map(|dep| dep.serialized(unstable_flags, cargo_features))\n                .collect(),\n            targets,\n            features: crate_features,\n            manifest_path: self.manifest_path().to_path_buf(),\n            metadata: self.manifest().custom_metadata().cloned(),\n            authors: manmeta.authors.clone(),\n            categories: manmeta.categories.clone(),\n            keywords: manmeta.keywords.clone(),\n            readme: manmeta.readme.clone(),\n            repository: manmeta.repository.clone(),\n            homepage: manmeta.homepage.clone(),\n            documentation: manmeta.documentation.clone(),\n            edition: self.manifest().edition().to_string(),\n            links: self.manifest().links().map(|s| s.to_owned()),\n            metabuild: self.manifest().metabuild().cloned(),\n            publish: self.publish().as_ref().cloned(),\n            default_run: self.manifest().default_run().map(|s| s.to_owned()),\n            rust_version: self.rust_version().cloned(),\n            hints: self.hints().cloned(),\n        }\n    }\n}\n\nimpl fmt::Display for Package {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{}\", self.summary().package_id())\n    }\n}\n\nimpl fmt::Debug for Package {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Package\")\n            .field(\"id\", &self.summary().package_id())\n            .field(\"..\", &\"..\")\n            .finish()\n    }\n}\n\nimpl PartialEq for Package {\n    fn eq(&self, other: &Package) -> bool {\n        self.package_id() == other.package_id()\n    }\n}\n\nimpl Eq for Package {}\n\nimpl hash::Hash for Package {\n    fn hash<H: hash::Hasher>(&self, into: &mut H) {\n        self.package_id().hash(into)\n    }\n}\n\n/// A set of packages, with the intent to download.\n///\n/// This is primarily used to convert a set of `PackageId`s to `Package`s. It\n/// will download as needed, or used the cached download if available.\npub struct PackageSet<'gctx> {\n    packages: HashMap<PackageId, OnceCell<Package>>,\n    sources: RefCell<SourceMap<'gctx>>,\n    gctx: &'gctx GlobalContext,\n    multi: Multi,\n    /// Used to prevent reusing the `PackageSet` to download twice.\n    downloading: Cell<bool>,\n    /// Whether or not to use curl HTTP/2 multiplexing.\n    multiplexing: bool,\n}\n\n/// Helper for downloading crates.\npub struct Downloads<'a, 'gctx> {\n    set: &'a PackageSet<'gctx>,\n    /// When a download is started, it is added to this map. The key is a\n    /// \"token\" (see `Download::token`). It is removed once the download is\n    /// finished.\n    pending: HashMap<usize, (Download<'gctx>, EasyHandle)>,\n    /// Set of packages currently being downloaded. This should stay in sync\n    /// with `pending`.\n    pending_ids: HashSet<PackageId>,\n    /// Downloads that have failed and are waiting to retry again later.\n    sleeping: SleepTracker<(Download<'gctx>, Easy)>,\n    /// The final result of each download. A pair `(token, result)`. This is a\n    /// temporary holding area, needed because curl can report multiple\n    /// downloads at once, but the main loop (`wait`) is written to only\n    /// handle one at a time.\n    results: Vec<(usize, Result<(), curl::Error>)>,\n    /// The next ID to use for creating a token (see `Download::token`).\n    next: usize,\n    /// Progress bar.\n    progress: RefCell<Option<Progress<'gctx>>>,\n    /// Number of downloads that have successfully finished.\n    downloads_finished: usize,\n    /// Total bytes for all successfully downloaded packages.\n    downloaded_bytes: u64,\n    /// Size (in bytes) and package name of the largest downloaded package.\n    largest: (u64, InternedString),\n    /// Time when downloading started.\n    start: Instant,\n    /// Indicates *all* downloads were successful.\n    success: bool,\n\n    /// Timeout management, both of timeout thresholds as well as whether or not\n    /// our connection has timed out (and accompanying message if it has).\n    ///\n    /// Note that timeout management is done manually here instead of in libcurl\n    /// because we want to apply timeouts to an entire batch of operations, not\n    /// any one particular single operation.\n    timeout: HttpTimeout,\n    /// Last time bytes were received.\n    updated_at: Cell<Instant>,\n    /// This is a slow-speed check. It is reset to `now + timeout_duration`\n    /// every time at least `threshold` bytes are received. If the current\n    /// time ever exceeds `next_speed_check`, then give up and report a\n    /// timeout error.\n    next_speed_check: Cell<Instant>,\n    /// This is the slow-speed threshold byte count. It starts at the\n    /// configured threshold value (default 10), and is decremented by the\n    /// number of bytes received in each chunk. If it is <= zero, the\n    /// threshold has been met and data is being received fast enough not to\n    /// trigger a timeout; reset `next_speed_check` and set this back to the\n    /// configured threshold.\n    next_speed_check_bytes_threshold: Cell<u64>,\n    /// Global filesystem lock to ensure only one Cargo is downloading at a\n    /// time.\n    _lock: CacheLock<'gctx>,\n}\n\nstruct Download<'gctx> {\n    /// The token for this download, used as the key of the `Downloads::pending` map\n    /// and stored in `EasyHandle` as well.\n    token: usize,\n\n    /// The package that we're downloading.\n    id: PackageId,\n\n    /// Actual downloaded data, updated throughout the lifetime of this download.\n    data: RefCell<Vec<u8>>,\n\n    /// HTTP headers for debugging.\n    headers: RefCell<Vec<String>>,\n\n    /// The URL that we're downloading from, cached here for error messages and\n    /// reenqueuing.\n    url: String,\n\n    /// A descriptive string to print when we've finished downloading this crate.\n    descriptor: String,\n\n    /// Statistics updated from the progress callback in libcurl.\n    total: Cell<u64>,\n    current: Cell<u64>,\n\n    /// The moment we started this transfer at.\n    start: Instant,\n    timed_out: Cell<Option<String>>,\n\n    /// Logic used to track retrying this download if it's a spurious failure.\n    retry: Retry<'gctx>,\n}\n\nimpl<'gctx> PackageSet<'gctx> {\n    pub fn new(\n        package_ids: &[PackageId],\n        sources: SourceMap<'gctx>,\n        gctx: &'gctx GlobalContext,\n    ) -> CargoResult<PackageSet<'gctx>> {\n        // We've enabled the `http2` feature of `curl` in Cargo, so treat\n        // failures here as fatal as it would indicate a build-time problem.\n        let mut multi = Multi::new();\n        let multiplexing = gctx.http_config()?.multiplexing.unwrap_or(true);\n        multi\n            .pipelining(false, multiplexing)\n            .context(\"failed to enable multiplexing/pipelining in curl\")?;\n\n        // let's not flood crates.io with connections\n        multi.set_max_host_connections(2)?;\n\n        Ok(PackageSet {\n            packages: package_ids\n                .iter()\n                .map(|&id| (id, OnceCell::new()))\n                .collect(),\n            sources: RefCell::new(sources),\n            gctx,\n            multi,\n            downloading: Cell::new(false),\n            multiplexing,\n        })\n    }\n\n    pub fn package_ids(&self) -> impl Iterator<Item = PackageId> + '_ {\n        self.packages.keys().cloned()\n    }\n\n    pub fn packages(&self) -> impl Iterator<Item = &Package> {\n        self.packages.values().filter_map(|p| p.get())\n    }\n\n    pub fn enable_download<'a>(&'a self) -> CargoResult<Downloads<'a, 'gctx>> {\n        assert!(!self.downloading.replace(true));\n        let timeout = HttpTimeout::new(self.gctx)?;\n        Ok(Downloads {\n            start: Instant::now(),\n            set: self,\n            next: 0,\n            pending: HashMap::new(),\n            pending_ids: HashSet::new(),\n            sleeping: SleepTracker::new(),\n            results: Vec::new(),\n            progress: RefCell::new(Some(Progress::with_style(\n                \"Downloading\",\n                ProgressStyle::Ratio,\n                self.gctx,\n            ))),\n            downloads_finished: 0,\n            downloaded_bytes: 0,\n            largest: (0, \"\".into()),\n            success: false,\n            updated_at: Cell::new(Instant::now()),\n            timeout,\n            next_speed_check: Cell::new(Instant::now()),\n            next_speed_check_bytes_threshold: Cell::new(0),\n            _lock: self\n                .gctx\n                .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?,\n        })\n    }\n\n    pub fn get_one(&self, id: PackageId) -> CargoResult<&Package> {\n        if let Some(pkg) = self.packages.get(&id).and_then(|slot| slot.get()) {\n            return Ok(pkg);\n        }\n        Ok(self.get_many(Some(id))?.remove(0))\n    }\n\n    pub fn get_many(&self, ids: impl IntoIterator<Item = PackageId>) -> CargoResult<Vec<&Package>> {\n        let mut pkgs = Vec::new();\n        let _lock = self\n            .gctx\n            .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n        let mut downloads = self.enable_download()?;\n        for id in ids {\n            pkgs.extend(downloads.start(id)?);\n        }\n        while downloads.remaining() > 0 {\n            pkgs.push(downloads.wait()?);\n        }\n        downloads.success = true;\n        drop(downloads);\n\n        let mut deferred = self.gctx.deferred_global_last_use()?;\n        deferred.save_no_error(self.gctx);\n        Ok(pkgs)\n    }\n\n    /// Downloads any packages accessible from the give root ids.\n    #[tracing::instrument(skip_all)]\n    pub fn download_accessible(\n        &self,\n        resolve: &Resolve,\n        root_ids: &[PackageId],\n        has_dev_units: HasDevUnits,\n        requested_kinds: &[CompileKind],\n        target_data: &RustcTargetData<'gctx>,\n        force_all_targets: ForceAllTargets,\n    ) -> CargoResult<()> {\n        fn collect_used_deps(\n            used: &mut BTreeSet<(PackageId, CompileKind)>,\n            resolve: &Resolve,\n            pkg_id: PackageId,\n            has_dev_units: HasDevUnits,\n            requested_kind: CompileKind,\n            target_data: &RustcTargetData<'_>,\n            force_all_targets: ForceAllTargets,\n        ) -> CargoResult<()> {\n            if !used.insert((pkg_id, requested_kind)) {\n                return Ok(());\n            }\n            let requested_kinds = &[requested_kind];\n            let filtered_deps = PackageSet::filter_deps(\n                pkg_id,\n                resolve,\n                has_dev_units,\n                requested_kinds,\n                target_data,\n                force_all_targets,\n            );\n            for (pkg_id, deps) in filtered_deps {\n                collect_used_deps(\n                    used,\n                    resolve,\n                    pkg_id,\n                    has_dev_units,\n                    requested_kind,\n                    target_data,\n                    force_all_targets,\n                )?;\n                let artifact_kinds = deps.iter().filter_map(|dep| {\n                    Some(\n                        dep.artifact()?\n                            .target()?\n                            .to_resolved_compile_kind(*requested_kinds.iter().next().unwrap()),\n                    )\n                });\n                for artifact_kind in artifact_kinds {\n                    collect_used_deps(\n                        used,\n                        resolve,\n                        pkg_id,\n                        has_dev_units,\n                        artifact_kind,\n                        target_data,\n                        force_all_targets,\n                    )?;\n                }\n            }\n            Ok(())\n        }\n\n        // This is sorted by PackageId to get consistent behavior and error\n        // messages for Cargo's testsuite. Perhaps there is a better ordering\n        // that optimizes download time?\n        let mut to_download = BTreeSet::new();\n\n        for id in root_ids {\n            for requested_kind in requested_kinds {\n                collect_used_deps(\n                    &mut to_download,\n                    resolve,\n                    *id,\n                    has_dev_units,\n                    *requested_kind,\n                    target_data,\n                    force_all_targets,\n                )?;\n            }\n        }\n        let to_download = to_download\n            .into_iter()\n            .map(|(p, _)| p)\n            .collect::<BTreeSet<_>>();\n        self.get_many(to_download.into_iter())?;\n        Ok(())\n    }\n\n    /// Check if there are any dependency packages that violate artifact constraints\n    /// to instantly abort, or that do not have any libs which results in warnings.\n    pub(crate) fn warn_no_lib_packages_and_artifact_libs_overlapping_deps(\n        &self,\n        ws: &Workspace<'gctx>,\n        resolve: &Resolve,\n        root_ids: &[PackageId],\n        has_dev_units: HasDevUnits,\n        requested_kinds: &[CompileKind],\n        target_data: &RustcTargetData<'_>,\n        force_all_targets: ForceAllTargets,\n    ) -> CargoResult<()> {\n        let no_lib_pkgs: BTreeMap<PackageId, Vec<(&Package, &HashSet<Dependency>)>> = root_ids\n            .iter()\n            .map(|&root_id| {\n                let dep_pkgs_to_deps: Vec<_> = PackageSet::filter_deps(\n                    root_id,\n                    resolve,\n                    has_dev_units,\n                    requested_kinds,\n                    target_data,\n                    force_all_targets,\n                )\n                .collect();\n\n                let dep_pkgs_and_deps = dep_pkgs_to_deps\n                    .into_iter()\n                    .filter(|(_id, deps)| deps.iter().any(|dep| dep.maybe_lib()))\n                    .filter_map(|(dep_package_id, deps)| {\n                        self.get_one(dep_package_id).ok().and_then(|dep_pkg| {\n                            (!dep_pkg.targets().iter().any(|t| t.is_lib())).then(|| (dep_pkg, deps))\n                        })\n                    })\n                    .collect();\n                (root_id, dep_pkgs_and_deps)\n            })\n            .collect();\n\n        for (pkg_id, dep_pkgs) in no_lib_pkgs {\n            for (_dep_pkg_without_lib_target, deps) in dep_pkgs {\n                for dep in deps.iter().filter(|dep| {\n                    dep.artifact()\n                        .map(|artifact| artifact.is_lib())\n                        .unwrap_or(true)\n                }) {\n                    ws.gctx().shell().warn(&format!(\n                        \"{} ignoring invalid dependency `{}` which is missing a lib target\",\n                        pkg_id,\n                        dep.name_in_toml(),\n                    ))?;\n                }\n            }\n        }\n        Ok(())\n    }\n\n    pub fn filter_deps<'a>(\n        pkg_id: PackageId,\n        resolve: &'a Resolve,\n        has_dev_units: HasDevUnits,\n        requested_kinds: &'a [CompileKind],\n        target_data: &'a RustcTargetData<'_>,\n        force_all_targets: ForceAllTargets,\n    ) -> impl Iterator<Item = (PackageId, &'a HashSet<Dependency>)> + 'a {\n        resolve\n            .deps(pkg_id)\n            .filter(move |&(_id, deps)| {\n                deps.iter().any(|dep| {\n                    if dep.kind() == DepKind::Development && has_dev_units == HasDevUnits::No {\n                        return false;\n                    }\n                    if force_all_targets == ForceAllTargets::No {\n                        let activated = requested_kinds\n                            .iter()\n                            .chain(Some(&CompileKind::Host))\n                            .any(|kind| target_data.dep_platform_activated(dep, *kind));\n                        if !activated {\n                            return false;\n                        }\n                    }\n                    true\n                })\n            })\n            .into_iter()\n    }\n\n    pub fn sources(&self) -> Ref<'_, SourceMap<'gctx>> {\n        self.sources.borrow()\n    }\n\n    pub fn sources_mut(&self) -> RefMut<'_, SourceMap<'gctx>> {\n        self.sources.borrow_mut()\n    }\n\n    /// Merge the given set into self.\n    pub fn add_set(&mut self, set: PackageSet<'gctx>) {\n        assert!(!self.downloading.get());\n        assert!(!set.downloading.get());\n        for (pkg_id, p_cell) in set.packages {\n            self.packages.entry(pkg_id).or_insert(p_cell);\n        }\n        let mut sources = self.sources.borrow_mut();\n        let other_sources = set.sources.into_inner();\n        sources.add_source_map(other_sources);\n    }\n}\n\nimpl<'a, 'gctx> Downloads<'a, 'gctx> {\n    /// Starts to download the package for the `id` specified.\n    ///\n    /// Returns `None` if the package is queued up for download and will\n    /// eventually be returned from `wait_for_download`. Returns `Some(pkg)` if\n    /// the package is ready and doesn't need to be downloaded.\n    #[tracing::instrument(skip_all)]\n    pub fn start(&mut self, id: PackageId) -> CargoResult<Option<&'a Package>> {\n        self.start_inner(id)\n            .with_context(|| format!(\"failed to download `{}`\", id))\n    }\n\n    fn start_inner(&mut self, id: PackageId) -> CargoResult<Option<&'a Package>> {\n        // First up see if we've already cached this package, in which case\n        // there's nothing to do.\n        let slot = self\n            .set\n            .packages\n            .get(&id)\n            .ok_or_else(|| internal(format!(\"couldn't find `{}` in package set\", id)))?;\n        if let Some(pkg) = slot.get() {\n            return Ok(Some(pkg));\n        }\n\n        // Ask the original source for this `PackageId` for the corresponding\n        // package. That may immediately come back and tell us that the package\n        // is ready, or it could tell us that it needs to be downloaded.\n        let mut sources = self.set.sources.borrow_mut();\n        let source = sources\n            .get_mut(id.source_id())\n            .ok_or_else(|| internal(format!(\"couldn't find source for `{}`\", id)))?;\n        let pkg = source\n            .download(id)\n            .context(\"unable to get packages from source\")?;\n        let (url, descriptor, authorization) = match pkg {\n            MaybePackage::Ready(pkg) => {\n                debug!(\"{} doesn't need a download\", id);\n                assert!(slot.set(pkg).is_ok());\n                return Ok(Some(slot.get().unwrap()));\n            }\n            MaybePackage::Download {\n                url,\n                descriptor,\n                authorization,\n            } => (url, descriptor, authorization),\n        };\n\n        // Ok we're going to download this crate, so let's set up all our\n        // internal state and hand off an `Easy` handle to our libcurl `Multi`\n        // handle. This won't actually start the transfer, but later it'll\n        // happen during `wait_for_download`\n        let token = self.next;\n        self.next += 1;\n        debug!(target: \"network\", \"downloading {} as {}\", id, token);\n        assert!(self.pending_ids.insert(id));\n\n        let (mut handle, _timeout) = http_handle_and_timeout(self.set.gctx)?;\n        handle.get(true)?;\n        handle.url(&url)?;\n        handle.follow_location(true)?; // follow redirects\n\n        // Add authorization header.\n        if let Some(authorization) = authorization {\n            let mut headers = curl::easy::List::new();\n            headers.append(&format!(\"Authorization: {}\", authorization))?;\n            handle.http_headers(headers)?;\n        }\n\n        // Enable HTTP/2 if possible.\n        crate::try_old_curl_http2_pipewait!(self.set.multiplexing, handle);\n\n        handle.write_function(move |buf| {\n            debug!(target: \"network\", \"{} - {} bytes of data\", token, buf.len());\n            tls::with(|downloads| {\n                if let Some(downloads) = downloads {\n                    downloads.pending[&token]\n                        .0\n                        .data\n                        .borrow_mut()\n                        .extend_from_slice(buf);\n                }\n            });\n            Ok(buf.len())\n        })?;\n        handle.header_function(move |data| {\n            tls::with(|downloads| {\n                if let Some(downloads) = downloads {\n                    // Headers contain trailing \\r\\n, trim them to make it easier\n                    // to work with.\n                    let h = String::from_utf8_lossy(data).trim().to_string();\n                    downloads.pending[&token].0.headers.borrow_mut().push(h);\n                }\n            });\n            true\n        })?;\n\n        handle.progress(true)?;\n        handle.progress_function(move |dl_total, dl_cur, _, _| {\n            tls::with(|downloads| match downloads {\n                Some(d) => d.progress(token, dl_total as u64, dl_cur as u64),\n                None => false,\n            })\n        })?;\n\n        // If the progress bar isn't enabled then it may be awhile before the\n        // first crate finishes downloading so we inform immediately that we're\n        // downloading crates here.\n        if self.downloads_finished == 0\n            && self.pending.is_empty()\n            && !self.progress.borrow().as_ref().unwrap().is_enabled()\n        {\n            self.set.gctx.shell().status(\"Downloading\", \"crates ...\")?;\n        }\n\n        let dl = Download {\n            token,\n            data: RefCell::new(Vec::new()),\n            headers: RefCell::new(Vec::new()),\n            id,\n            url,\n            descriptor,\n            total: Cell::new(0),\n            current: Cell::new(0),\n            start: Instant::now(),\n            timed_out: Cell::new(None),\n            retry: Retry::new(self.set.gctx)?,\n        };\n        self.enqueue(dl, handle)?;\n        self.tick(WhyTick::DownloadStarted)?;\n\n        Ok(None)\n    }\n\n    /// Returns the number of crates that are still downloading.\n    pub fn remaining(&self) -> usize {\n        self.pending.len() + self.sleeping.len()\n    }\n\n    /// Blocks the current thread waiting for a package to finish downloading.\n    ///\n    /// This method will wait for a previously enqueued package to finish\n    /// downloading and return a reference to it after it's done downloading.\n    ///\n    /// # Panics\n    ///\n    /// This function will panic if there are no remaining downloads.\n    #[tracing::instrument(skip_all)]\n    pub fn wait(&mut self) -> CargoResult<&'a Package> {\n        let (dl, data) = loop {\n            assert_eq!(self.pending.len(), self.pending_ids.len());\n            let (token, result) = self.wait_for_curl()?;\n            debug!(target: \"network\", \"{} finished with {:?}\", token, result);\n\n            let (mut dl, handle) = self\n                .pending\n                .remove(&token)\n                .expect(\"got a token for a non-in-progress transfer\");\n            let data = mem::take(&mut *dl.data.borrow_mut());\n            let headers = mem::take(&mut *dl.headers.borrow_mut());\n            let mut handle = self.set.multi.remove(handle)?;\n            self.pending_ids.remove(&dl.id);\n\n            // Check if this was a spurious error. If it was a spurious error\n            // then we want to re-enqueue our request for another attempt and\n            // then we wait for another request to finish.\n            let ret = {\n                let timed_out = &dl.timed_out;\n                let url = &dl.url;\n                dl.retry.r#try(|| {\n                    if let Err(e) = result {\n                        // If this error is \"aborted by callback\" then that's\n                        // probably because our progress callback aborted due to\n                        // a timeout. We'll find out by looking at the\n                        // `timed_out` field, looking for a descriptive message.\n                        // If one is found we switch the error code (to ensure\n                        // it's flagged as spurious) and then attach our extra\n                        // information to the error.\n                        if !e.is_aborted_by_callback() {\n                            return Err(e.into());\n                        }\n\n                        return Err(match timed_out.replace(None) {\n                            Some(msg) => {\n                                let code = curl_sys::CURLE_OPERATION_TIMEDOUT;\n                                let mut err = curl::Error::new(code);\n                                err.set_extra(msg);\n                                err\n                            }\n                            None => e,\n                        }\n                        .into());\n                    }\n\n                    let code = handle.response_code()?;\n                    if code != 200 && code != 0 {\n                        return Err(HttpNotSuccessful::new_from_handle(\n                            &mut handle,\n                            &url,\n                            data,\n                            headers,\n                        )\n                        .into());\n                    }\n                    Ok(data)\n                })\n            };\n            match ret {\n                RetryResult::Success(data) => break (dl, data),\n                RetryResult::Err(e) => {\n                    return Err(e.context(format!(\"failed to download from `{}`\", dl.url)));\n                }\n                RetryResult::Retry(sleep) => {\n                    debug!(target: \"network\", \"download retry {} for {sleep}ms\", dl.url);\n                    self.sleeping.push(sleep, (dl, handle));\n                }\n            }\n        };\n\n        // If the progress bar isn't enabled then we still want to provide some\n        // semblance of progress of how we're downloading crates, and if the\n        // progress bar is enabled this provides a good log of what's happening.\n        self.progress.borrow_mut().as_mut().unwrap().clear();\n        self.set.gctx.shell().status(\"Downloaded\", &dl.descriptor)?;\n\n        self.downloads_finished += 1;\n        self.downloaded_bytes += dl.total.get();\n        if dl.total.get() > self.largest.0 {\n            self.largest = (dl.total.get(), dl.id.name());\n        }\n\n        // We're about to synchronously extract the crate below. While we're\n        // doing that our download progress won't actually be updated, nor do we\n        // have a great view into the progress of the extraction. Let's prepare\n        // the user for this CPU-heavy step if it looks like it'll take some\n        // time to do so.\n        let kib_400 = 1024 * 400;\n        if dl.total.get() < kib_400 {\n            self.tick(WhyTick::DownloadFinished)?;\n        } else {\n            self.tick(WhyTick::Extracting(&dl.id.name()))?;\n        }\n\n        // Inform the original source that the download is finished which\n        // should allow us to actually get the package and fill it in now.\n        let mut sources = self.set.sources.borrow_mut();\n        let source = sources\n            .get_mut(dl.id.source_id())\n            .ok_or_else(|| internal(format!(\"couldn't find source for `{}`\", dl.id)))?;\n        let start = Instant::now();\n        let pkg = source.finish_download(dl.id, data)?;\n\n        // Assume that no time has passed while we were calling\n        // `finish_download`, update all speed checks and timeout limits of all\n        // active downloads to make sure they don't fire because of a slowly\n        // extracted tarball.\n        let finish_dur = start.elapsed();\n        self.updated_at.set(self.updated_at.get() + finish_dur);\n        self.next_speed_check\n            .set(self.next_speed_check.get() + finish_dur);\n\n        let slot = &self.set.packages[&dl.id];\n        assert!(slot.set(pkg).is_ok());\n        Ok(slot.get().unwrap())\n    }\n\n    fn enqueue(&mut self, dl: Download<'gctx>, handle: Easy) -> CargoResult<()> {\n        let mut handle = self.set.multi.add(handle)?;\n        let now = Instant::now();\n        handle.set_token(dl.token)?;\n        self.updated_at.set(now);\n        self.next_speed_check.set(now + self.timeout.dur);\n        self.next_speed_check_bytes_threshold\n            .set(u64::from(self.timeout.low_speed_limit));\n        dl.timed_out.set(None);\n        dl.current.set(0);\n        dl.total.set(0);\n        self.pending.insert(dl.token, (dl, handle));\n        Ok(())\n    }\n\n    /// Block, waiting for curl. Returns a token and a `Result` for that token\n    /// (`Ok` means the download successfully finished).\n    fn wait_for_curl(&mut self) -> CargoResult<(usize, Result<(), curl::Error>)> {\n        // This is the main workhorse loop. We use libcurl's portable `wait`\n        // method to actually perform blocking. This isn't necessarily too\n        // efficient in terms of fd management, but we should only be juggling\n        // a few anyway.\n        //\n        // Here we start off by asking the `multi` handle to do some work via\n        // the `perform` method. This will actually do I/O work (non-blocking)\n        // and attempt to make progress. Afterwards we ask about the `messages`\n        // contained in the handle which will inform us if anything has finished\n        // transferring.\n        //\n        // If we've got a finished transfer after all that work we break out\n        // and process the finished transfer at the end. Otherwise we need to\n        // actually block waiting for I/O to happen, which we achieve with the\n        // `wait` method on `multi`.\n        loop {\n            self.add_sleepers()?;\n            let n = tls::set(self, || {\n                self.set\n                    .multi\n                    .perform()\n                    .context(\"failed to perform http requests\")\n            })?;\n            debug!(target: \"network\", \"handles remaining: {}\", n);\n            let results = &mut self.results;\n            let pending = &self.pending;\n            self.set.multi.messages(|msg| {\n                let token = msg.token().expect(\"failed to read token\");\n                let handle = &pending[&token].1;\n                if let Some(result) = msg.result_for(handle) {\n                    results.push((token, result));\n                } else {\n                    debug!(target: \"network\", \"message without a result (?)\");\n                }\n            });\n\n            if let Some(pair) = results.pop() {\n                break Ok(pair);\n            }\n            assert_ne!(self.remaining(), 0);\n            if self.pending.is_empty() {\n                let delay = self.sleeping.time_to_next().unwrap();\n                debug!(target: \"network\", \"sleeping main thread for {delay:?}\");\n                std::thread::sleep(delay);\n            } else {\n                let min_timeout = Duration::new(1, 0);\n                let timeout = self.set.multi.get_timeout()?.unwrap_or(min_timeout);\n                let timeout = timeout.min(min_timeout);\n                self.set\n                    .multi\n                    .wait(&mut [], timeout)\n                    .context(\"failed to wait on curl `Multi`\")?;\n            }\n        }\n    }\n\n    fn add_sleepers(&mut self) -> CargoResult<()> {\n        for (dl, handle) in self.sleeping.to_retry() {\n            self.pending_ids.insert(dl.id);\n            self.enqueue(dl, handle)?;\n        }\n        Ok(())\n    }\n\n    fn progress(&self, token: usize, total: u64, cur: u64) -> bool {\n        let dl = &self.pending[&token].0;\n        dl.total.set(total);\n        let now = Instant::now();\n        if cur > dl.current.get() {\n            let delta = cur - dl.current.get();\n            let threshold = self.next_speed_check_bytes_threshold.get();\n\n            dl.current.set(cur);\n            self.updated_at.set(now);\n\n            if delta >= threshold {\n                self.next_speed_check.set(now + self.timeout.dur);\n                self.next_speed_check_bytes_threshold\n                    .set(u64::from(self.timeout.low_speed_limit));\n            } else {\n                self.next_speed_check_bytes_threshold.set(threshold - delta);\n            }\n        }\n        if self.tick(WhyTick::DownloadUpdate).is_err() {\n            return false;\n        }\n\n        // If we've spent too long not actually receiving any data we time out.\n        if now > self.updated_at.get() + self.timeout.dur {\n            self.updated_at.set(now);\n            let msg = format!(\n                \"failed to download any data for `{}` within {}s\",\n                dl.id,\n                self.timeout.dur.as_secs()\n            );\n            dl.timed_out.set(Some(msg));\n            return false;\n        }\n\n        // If we reached the point in time that we need to check our speed\n        // limit, see if we've transferred enough data during this threshold. If\n        // it fails this check then we fail because the download is going too\n        // slowly.\n        if now >= self.next_speed_check.get() {\n            self.next_speed_check.set(now + self.timeout.dur);\n            assert!(self.next_speed_check_bytes_threshold.get() > 0);\n            let msg = format!(\n                \"download of `{}` failed to transfer more \\\n                 than {} bytes in {}s\",\n                dl.id,\n                self.timeout.low_speed_limit,\n                self.timeout.dur.as_secs()\n            );\n            dl.timed_out.set(Some(msg));\n            return false;\n        }\n\n        true\n    }\n\n    fn tick(&self, why: WhyTick<'_>) -> CargoResult<()> {\n        let mut progress = self.progress.borrow_mut();\n        let progress = progress.as_mut().unwrap();\n\n        if let WhyTick::DownloadUpdate = why {\n            if !progress.update_allowed() {\n                return Ok(());\n            }\n        }\n        let pending = self.remaining();\n        let mut msg = if pending == 1 {\n            format!(\"{} crate\", pending)\n        } else {\n            format!(\"{} crates\", pending)\n        };\n        match why {\n            WhyTick::Extracting(krate) => {\n                msg.push_str(&format!(\", extracting {} ...\", krate));\n            }\n            _ => {\n                let mut dur = Duration::new(0, 0);\n                let mut remaining = 0;\n                for (dl, _) in self.pending.values() {\n                    dur += dl.start.elapsed();\n                    // If the total/current look weird just throw out the data\n                    // point, sounds like curl has more to learn before we have\n                    // the true information.\n                    if dl.total.get() >= dl.current.get() {\n                        remaining += dl.total.get() - dl.current.get();\n                    }\n                }\n                if remaining > 0 && dur > Duration::from_millis(500) {\n                    msg.push_str(&format!(\", remaining bytes: {:.1}\", HumanBytes(remaining)));\n                }\n            }\n        }\n        progress.print_now(&msg)\n    }\n}\n\n#[derive(Copy, Clone)]\nenum WhyTick<'a> {\n    DownloadStarted,\n    DownloadUpdate,\n    DownloadFinished,\n    Extracting(&'a str),\n}\n\nimpl<'a, 'gctx> Drop for Downloads<'a, 'gctx> {\n    fn drop(&mut self) {\n        self.set.downloading.set(false);\n        let progress = self.progress.get_mut().take().unwrap();\n        // Don't print a download summary if we're not using a progress bar,\n        // we've already printed lots of `Downloading...` items.\n        if !progress.is_enabled() {\n            return;\n        }\n        // If we didn't download anything, no need for a summary.\n        if self.downloads_finished == 0 {\n            return;\n        }\n        // If an error happened, let's not clutter up the output.\n        if !self.success {\n            return;\n        }\n        // pick the correct plural of crate(s)\n        let crate_string = if self.downloads_finished == 1 {\n            \"crate\"\n        } else {\n            \"crates\"\n        };\n        let mut status = format!(\n            \"{} {} ({:.1}) in {}\",\n            self.downloads_finished,\n            crate_string,\n            HumanBytes(self.downloaded_bytes),\n            util::elapsed(self.start.elapsed())\n        );\n        // print the size of largest crate if it was >1mb\n        // however don't print if only a single crate was downloaded\n        // because it is obvious that it will be the largest then\n        let mib_1 = 1024 * 1024;\n        if self.largest.0 > mib_1 && self.downloads_finished > 1 {\n            status.push_str(&format!(\n                \" (largest was `{}` at {:.1})\",\n                self.largest.1,\n                HumanBytes(self.largest.0),\n            ));\n        }\n        // Clear progress before displaying final summary.\n        drop(progress);\n        drop(self.set.gctx.shell().status(\"Downloaded\", status));\n    }\n}\n\nmod tls {\n    use std::cell::Cell;\n\n    use super::Downloads;\n\n    thread_local!(static PTR: Cell<usize> = const { Cell::new(0) });\n\n    pub(crate) fn with<R>(f: impl FnOnce(Option<&Downloads<'_, '_>>) -> R) -> R {\n        let ptr = PTR.with(|p| p.get());\n        if ptr == 0 {\n            f(None)\n        } else {\n            unsafe { f(Some(&*(ptr as *const Downloads<'_, '_>))) }\n        }\n    }\n\n    pub(crate) fn set<R>(dl: &Downloads<'_, '_>, f: impl FnOnce() -> R) -> R {\n        struct Reset<'a, T: Copy>(&'a Cell<T>, T);\n\n        impl<'a, T: Copy> Drop for Reset<'a, T> {\n            fn drop(&mut self) {\n                self.0.set(self.1);\n            }\n        }\n\n        PTR.with(|p| {\n            let _reset = Reset(p, p.get());\n            p.set(dl as *const Downloads<'_, '_> as usize);\n            f()\n        })\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/package_id.rs",
    "content": "use std::collections::HashSet;\nuse std::fmt::{self, Formatter};\nuse std::hash;\nuse std::hash::Hash;\nuse std::path::Path;\nuse std::ptr;\nuse std::sync::Mutex;\nuse std::sync::OnceLock;\n\nuse serde::de;\nuse serde::ser;\n\nuse crate::core::PackageIdSpec;\nuse crate::core::SourceId;\nuse crate::util::CargoResult;\nuse crate::util::interning::InternedString;\n\nstatic PACKAGE_ID_CACHE: OnceLock<Mutex<HashSet<&'static PackageIdInner>>> = OnceLock::new();\n\n/// Identifier for a specific version of a package in a specific source.\n#[derive(Clone, Copy, Eq, PartialOrd, Ord)]\npub struct PackageId {\n    inner: &'static PackageIdInner,\n}\n\n#[derive(PartialOrd, Eq, Ord)]\nstruct PackageIdInner {\n    name: InternedString,\n    version: semver::Version,\n    source_id: SourceId,\n}\n\n// Custom equality that uses full equality of SourceId, rather than its custom equality.\n//\n// The `build` part of the version is usually ignored (like a \"comment\").\n// However, there are some cases where it is important. The download path from\n// a registry includes the build metadata, and Cargo uses PackageIds for\n// creating download paths. Including it here prevents the PackageId interner\n// from getting poisoned with PackageIds where that build metadata is missing.\nimpl PartialEq for PackageIdInner {\n    fn eq(&self, other: &Self) -> bool {\n        self.name == other.name\n            && self.version == other.version\n            && self.source_id.full_eq(other.source_id)\n    }\n}\n\n// Custom hash that is coherent with the custom equality above.\nimpl Hash for PackageIdInner {\n    fn hash<S: hash::Hasher>(&self, into: &mut S) {\n        self.name.hash(into);\n        self.version.hash(into);\n        self.source_id.full_hash(into);\n    }\n}\n\nimpl ser::Serialize for PackageId {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        s.collect_str(&format_args!(\n            \"{} {} ({})\",\n            self.inner.name,\n            self.inner.version,\n            self.inner.source_id.as_url()\n        ))\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for PackageId {\n    fn deserialize<D>(d: D) -> Result<PackageId, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        let string = String::deserialize(d)?;\n\n        let (field, rest) = string\n            .split_once(' ')\n            .ok_or_else(|| de::Error::custom(\"invalid serialized PackageId\"))?;\n        let name = field.into();\n\n        let (field, rest) = rest\n            .split_once(' ')\n            .ok_or_else(|| de::Error::custom(\"invalid serialized PackageId\"))?;\n        let version = field.parse().map_err(de::Error::custom)?;\n\n        let url =\n            strip_parens(rest).ok_or_else(|| de::Error::custom(\"invalid serialized PackageId\"))?;\n        let source_id = SourceId::from_url(url).map_err(de::Error::custom)?;\n\n        Ok(PackageId::new(name, version, source_id))\n    }\n}\n\nfn strip_parens(value: &str) -> Option<&str> {\n    let value = value.strip_prefix('(')?;\n    let value = value.strip_suffix(')')?;\n    Some(value)\n}\n\nimpl PartialEq for PackageId {\n    fn eq(&self, other: &PackageId) -> bool {\n        if ptr::eq(self.inner, other.inner) {\n            return true;\n        }\n        // This is here so that PackageId uses SourceId's and Version's idea\n        // of equality. PackageIdInner uses a more exact notion of equality.\n        self.inner.name == other.inner.name\n            && self.inner.version == other.inner.version\n            && self.inner.source_id == other.inner.source_id\n    }\n}\n\nimpl Hash for PackageId {\n    fn hash<S: hash::Hasher>(&self, state: &mut S) {\n        // This is here (instead of derived) so that PackageId uses SourceId's\n        // and Version's idea of equality. PackageIdInner uses a more exact\n        // notion of hashing.\n        self.inner.name.hash(state);\n        self.inner.version.hash(state);\n        self.inner.source_id.hash(state);\n    }\n}\n\nimpl PackageId {\n    pub fn try_new(\n        name: impl Into<InternedString>,\n        version: &str,\n        sid: SourceId,\n    ) -> CargoResult<PackageId> {\n        let v = version.parse()?;\n        Ok(PackageId::new(name.into(), v, sid))\n    }\n\n    pub fn new(name: InternedString, version: semver::Version, source_id: SourceId) -> PackageId {\n        let inner = PackageIdInner {\n            name,\n            version,\n            source_id,\n        };\n        let mut cache = PACKAGE_ID_CACHE\n            .get_or_init(|| Default::default())\n            .lock()\n            .unwrap();\n        let inner = cache.get(&inner).cloned().unwrap_or_else(|| {\n            let inner = Box::leak(Box::new(inner));\n            cache.insert(inner);\n            inner\n        });\n        PackageId { inner }\n    }\n\n    pub fn name(self) -> InternedString {\n        self.inner.name\n    }\n    pub fn version(self) -> &'static semver::Version {\n        &self.inner.version\n    }\n    pub fn source_id(self) -> SourceId {\n        self.inner.source_id\n    }\n\n    pub fn with_source_id(self, source: SourceId) -> PackageId {\n        PackageId::new(self.inner.name, self.inner.version.clone(), source)\n    }\n\n    pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Self {\n        if self.source_id() == to_replace {\n            self.with_source_id(replace_with)\n        } else {\n            self\n        }\n    }\n\n    /// Returns a value that implements a \"stable\" hashable value.\n    ///\n    /// Stable hashing removes the path prefix of the workspace from path\n    /// packages. This helps with reproducible builds, since this hash is part\n    /// of the symbol metadata, and we don't want the absolute path where the\n    /// build is performed to affect the binary output.\n    pub fn stable_hash(self, workspace: &Path) -> PackageIdStableHash<'_> {\n        PackageIdStableHash(self, workspace)\n    }\n\n    /// Filename of the `.crate` tarball, e.g., `once_cell-1.18.0.crate`.\n    pub fn tarball_name(&self) -> String {\n        format!(\"{}-{}.crate\", self.name(), self.version())\n    }\n\n    /// Convert a `PackageId` to a `PackageIdSpec`, which will have both the `PartialVersion` and `Url`\n    /// fields filled in.\n    pub fn to_spec(&self) -> PackageIdSpec {\n        PackageIdSpec::new(String::from(self.name().as_str()))\n            .with_version(self.version().clone().into())\n            .with_url(self.source_id().url().clone())\n            .with_kind(self.source_id().kind().clone())\n    }\n}\n\npub struct PackageIdStableHash<'a>(PackageId, &'a Path);\n\nimpl<'a> Hash for PackageIdStableHash<'a> {\n    fn hash<S: hash::Hasher>(&self, state: &mut S) {\n        self.0.inner.name.hash(state);\n        self.0.inner.version.hash(state);\n        self.0.inner.source_id.stable_hash(self.1, state);\n    }\n}\n\nimpl fmt::Display for PackageId {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        write!(f, \"{} v{}\", self.inner.name, self.inner.version)?;\n\n        if !self.inner.source_id.is_crates_io() {\n            write!(f, \" ({})\", self.inner.source_id)?;\n        }\n\n        Ok(())\n    }\n}\n\nimpl fmt::Debug for PackageId {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"PackageId\")\n            .field(\"name\", &self.inner.name)\n            .field(\"version\", &self.inner.version.to_string())\n            .field(\"source\", &self.inner.source_id.to_string())\n            .finish()\n    }\n}\n\nimpl fmt::Debug for PackageIdInner {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"PackageIdInner\")\n            .field(\"name\", &self.name)\n            .field(\"version\", &self.version.to_string())\n            .field(\"source\", &self.source_id.to_string())\n            .finish()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::PackageId;\n    use crate::core::SourceId;\n    use crate::sources::CRATES_IO_INDEX;\n    use crate::util::IntoUrl;\n\n    #[test]\n    fn invalid_version_handled_nicely() {\n        let loc = CRATES_IO_INDEX.into_url().unwrap();\n        let repo = SourceId::for_registry(&loc).unwrap();\n\n        assert!(PackageId::try_new(\"foo\", \"1.0\", repo).is_err());\n        assert!(PackageId::try_new(\"foo\", \"1\", repo).is_err());\n        assert!(PackageId::try_new(\"foo\", \"bar\", repo).is_err());\n        assert!(PackageId::try_new(\"foo\", \"\", repo).is_err());\n    }\n\n    #[test]\n    fn display() {\n        let loc = CRATES_IO_INDEX.into_url().unwrap();\n        let pkg_id =\n            PackageId::try_new(\"foo\", \"1.0.0\", SourceId::for_registry(&loc).unwrap()).unwrap();\n        assert_eq!(\"foo v1.0.0\", pkg_id.to_string());\n    }\n\n    #[test]\n    fn unequal_build_metadata() {\n        let loc = CRATES_IO_INDEX.into_url().unwrap();\n        let repo = SourceId::for_registry(&loc).unwrap();\n        let first = PackageId::try_new(\"foo\", \"0.0.1+first\", repo).unwrap();\n        let second = PackageId::try_new(\"foo\", \"0.0.1+second\", repo).unwrap();\n        assert_ne!(first, second);\n        assert_ne!(first.inner, second.inner);\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/package_id_spec.rs",
    "content": "use std::collections::HashMap;\n\nuse anyhow::{Context as _, bail};\n\nuse crate::core::PackageId;\nuse crate::core::PackageIdSpec;\nuse crate::util::edit_distance;\nuse crate::util::errors::CargoResult;\n\npub trait PackageIdSpecQuery {\n    /// Roughly equivalent to `PackageIdSpec::parse(spec)?.query(i)`\n    fn query_str<I>(spec: &str, i: I) -> CargoResult<PackageId>\n    where\n        I: IntoIterator<Item = PackageId>;\n\n    /// Checks whether the given `PackageId` matches the `PackageIdSpec`.\n    fn matches(&self, package_id: PackageId) -> bool;\n\n    /// Checks a list of `PackageId`s to find 1 that matches this `PackageIdSpec`. If 0, 2, or\n    /// more are found, then this returns an error.\n    fn query<I>(&self, i: I) -> CargoResult<PackageId>\n    where\n        I: IntoIterator<Item = PackageId>;\n}\n\nimpl PackageIdSpecQuery for PackageIdSpec {\n    fn query_str<I>(spec: &str, i: I) -> CargoResult<PackageId>\n    where\n        I: IntoIterator<Item = PackageId>,\n    {\n        let i: Vec<_> = i.into_iter().collect();\n        let spec = PackageIdSpec::parse(spec).with_context(|| {\n            let suggestion =\n                edit_distance::closest_msg(spec, i.iter(), |id| id.name().as_str(), \"package\");\n            format!(\"invalid package ID specification: `{}`{}\", spec, suggestion)\n        })?;\n        spec.query(i)\n    }\n\n    fn matches(&self, package_id: PackageId) -> bool {\n        if self.name() != package_id.name().as_str() {\n            return false;\n        }\n\n        if let Some(ref v) = self.partial_version() {\n            if !v.matches(package_id.version()) {\n                return false;\n            }\n        }\n\n        if let Some(u) = &self.url() {\n            if *u != package_id.source_id().url() {\n                return false;\n            }\n        }\n\n        if let Some(k) = &self.kind() {\n            if *k != package_id.source_id().kind() {\n                return false;\n            }\n        }\n\n        true\n    }\n\n    fn query<I>(&self, i: I) -> CargoResult<PackageId>\n    where\n        I: IntoIterator<Item = PackageId>,\n    {\n        let all_ids: Vec<_> = i.into_iter().collect();\n        let mut ids = all_ids.iter().copied().filter(|&id| self.matches(id));\n        let Some(ret) = ids.next() else {\n            let mut suggestion = String::new();\n            let try_spec = |spec: PackageIdSpec, suggestion: &mut String| {\n                let try_matches: Vec<_> = all_ids\n                    .iter()\n                    .copied()\n                    .filter(|&id| spec.matches(id))\n                    .collect();\n                if !try_matches.is_empty() {\n                    suggestion.push_str(\"\\nhelp: there are similar package ID specifications:\\n\");\n                    minimize(suggestion, &try_matches, self);\n                }\n            };\n            if self.url().is_some() {\n                let spec = PackageIdSpec::new(self.name().to_owned());\n                let spec = if let Some(version) = self.partial_version().cloned() {\n                    spec.with_version(version)\n                } else {\n                    spec\n                };\n                try_spec(spec, &mut suggestion);\n            }\n            if suggestion.is_empty() && self.version().is_some() {\n                try_spec(PackageIdSpec::new(self.name().to_owned()), &mut suggestion);\n            }\n            if suggestion.is_empty() {\n                suggestion.push_str(&edit_distance::closest_msg(\n                    self.name(),\n                    all_ids.iter(),\n                    |id| id.name().as_str(),\n                    \"package\",\n                ));\n            }\n\n            bail!(\n                \"package ID specification `{}` did not match any packages{}\",\n                self,\n                suggestion\n            );\n        };\n        return match ids.next() {\n            Some(other) => {\n                let mut msg = format!(\n                    \"specification `{self}` is ambiguous\nhelp: re-run this command with one of the following specifications\",\n                );\n                let mut vec = vec![ret, other];\n                vec.extend(ids);\n                minimize(&mut msg, &vec, self);\n                Err(anyhow::format_err!(\"{}\", msg))\n            }\n            None => Ok(ret),\n        };\n\n        fn minimize(msg: &mut String, ids: &[PackageId], spec: &PackageIdSpec) {\n            let mut version_cnt = HashMap::new();\n            for id in ids {\n                *version_cnt.entry(id.version()).or_insert(0) += 1;\n            }\n            for id in ids {\n                if version_cnt[id.version()] == 1 {\n                    msg.push_str(&format!(\"\\n  {}@{}\", spec.name(), id.version()));\n                } else {\n                    msg.push_str(&format!(\"\\n  {}\", id.to_spec()));\n                }\n            }\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::PackageIdSpec;\n    use super::PackageIdSpecQuery;\n    use crate::core::{PackageId, SourceId};\n    use url::Url;\n\n    #[test]\n    fn matching() {\n        let url = Url::parse(\"https://example.com\").unwrap();\n        let sid = SourceId::for_registry(&url).unwrap();\n\n        let foo = PackageId::try_new(\"foo\", \"1.2.3\", sid).unwrap();\n        assert!(PackageIdSpec::parse(\"foo\").unwrap().matches(foo));\n        assert!(!PackageIdSpec::parse(\"bar\").unwrap().matches(foo));\n        assert!(PackageIdSpec::parse(\"foo:1.2.3\").unwrap().matches(foo));\n        assert!(!PackageIdSpec::parse(\"foo:1.2.2\").unwrap().matches(foo));\n        assert!(PackageIdSpec::parse(\"foo@1.2.3\").unwrap().matches(foo));\n        assert!(!PackageIdSpec::parse(\"foo@1.2.2\").unwrap().matches(foo));\n        assert!(PackageIdSpec::parse(\"foo@1.2\").unwrap().matches(foo));\n        assert!(\n            PackageIdSpec::parse(\"https://example.com#foo@1.2\")\n                .unwrap()\n                .matches(foo)\n        );\n        assert!(\n            !PackageIdSpec::parse(\"https://bob.com#foo@1.2\")\n                .unwrap()\n                .matches(foo)\n        );\n        assert!(\n            PackageIdSpec::parse(\"registry+https://example.com#foo@1.2\")\n                .unwrap()\n                .matches(foo)\n        );\n        assert!(\n            !PackageIdSpec::parse(\"git+https://example.com#foo@1.2\")\n                .unwrap()\n                .matches(foo)\n        );\n\n        let meta = PackageId::try_new(\"meta\", \"1.2.3+hello\", sid).unwrap();\n        assert!(PackageIdSpec::parse(\"meta\").unwrap().matches(meta));\n        assert!(PackageIdSpec::parse(\"meta@1\").unwrap().matches(meta));\n        assert!(PackageIdSpec::parse(\"meta@1.2\").unwrap().matches(meta));\n        assert!(PackageIdSpec::parse(\"meta@1.2.3\").unwrap().matches(meta));\n        assert!(\n            !PackageIdSpec::parse(\"meta@1.2.3-alpha.0\")\n                .unwrap()\n                .matches(meta)\n        );\n        assert!(\n            PackageIdSpec::parse(\"meta@1.2.3+hello\")\n                .unwrap()\n                .matches(meta)\n        );\n        assert!(\n            !PackageIdSpec::parse(\"meta@1.2.3+bye\")\n                .unwrap()\n                .matches(meta)\n        );\n\n        let pre = PackageId::try_new(\"pre\", \"1.2.3-alpha.0\", sid).unwrap();\n        assert!(PackageIdSpec::parse(\"pre\").unwrap().matches(pre));\n        assert!(!PackageIdSpec::parse(\"pre@1\").unwrap().matches(pre));\n        assert!(!PackageIdSpec::parse(\"pre@1.2\").unwrap().matches(pre));\n        assert!(!PackageIdSpec::parse(\"pre@1.2.3\").unwrap().matches(pre));\n        assert!(\n            PackageIdSpec::parse(\"pre@1.2.3-alpha.0\")\n                .unwrap()\n                .matches(pre)\n        );\n        assert!(\n            !PackageIdSpec::parse(\"pre@1.2.3-alpha.1\")\n                .unwrap()\n                .matches(pre)\n        );\n        assert!(\n            !PackageIdSpec::parse(\"pre@1.2.3-beta.0\")\n                .unwrap()\n                .matches(pre)\n        );\n        assert!(\n            !PackageIdSpec::parse(\"pre@1.2.3+hello\")\n                .unwrap()\n                .matches(pre)\n        );\n        assert!(\n            !PackageIdSpec::parse(\"pre@1.2.3-alpha.0+hello\")\n                .unwrap()\n                .matches(pre)\n        );\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/profiles.rs",
    "content": "//! Handles built-in and customizable compiler flag presets.\n//!\n//! [`Profiles`] is a collections of built-in profiles, and profiles defined\n//! in the root manifest and configurations.\n//!\n//! To start using a profile, most of the time you start from [`Profiles::new`],\n//! which does the followings:\n//!\n//! - Create a `Profiles` by merging profiles from configs onto the profile\n//!   from root manifest (see [`merge_config_profiles`]).\n//! - Add built-in profiles onto it (see [`Profiles::add_root_profiles`]).\n//! - Process profile inheritance for each profiles. (see [`Profiles::add_maker`]).\n//!\n//! Then you can query a [`Profile`] via [`Profiles::get_profile`], which respects\n//! the profile overridden hierarchy described in below. The [`Profile`] you get\n//! is basically an immutable struct containing the compiler flag presets.\n//!\n//! ## Profile overridden hierarchy\n//!\n//! Profile settings can be overridden for specific packages and build-time crates.\n//! The precedence is explained in [`ProfileMaker`].\n//! The algorithm happens within [`ProfileMaker::get_profile`].\n\nuse crate::core::Feature;\nuse crate::core::compiler::{CompileKind, CompileTarget, Unit};\nuse crate::core::dependency::Artifact;\nuse crate::core::resolver::features::FeaturesFor;\nuse crate::core::{\n    PackageId, PackageIdSpec, PackageIdSpecQuery, Resolve, Shell, Target, Workspace,\n};\nuse crate::util::interning::InternedString;\nuse crate::util::toml::validate_profile;\nuse crate::util::{CargoResult, GlobalContext, closest_msg, context};\nuse anyhow::{Context as _, bail};\nuse cargo_util_schemas::manifest::TomlTrimPaths;\nuse cargo_util_schemas::manifest::TomlTrimPathsValue;\nuse cargo_util_schemas::manifest::{\n    ProfilePackageSpec, StringOrBool, TomlDebugInfo, TomlProfile, TomlProfiles,\n};\nuse std::collections::{BTreeMap, HashMap, HashSet};\nuse std::hash::Hash;\nuse std::{cmp, fmt, hash};\n\n/// Collection of all profiles.\n///\n/// To get a specific [`Profile`], you usually create this and call [`get_profile`] then.\n///\n/// [`get_profile`]: Profiles::get_profile\n#[derive(Clone, Debug)]\npub struct Profiles {\n    /// Incremental compilation can be overridden globally via:\n    /// - `CARGO_INCREMENTAL` environment variable.\n    /// - `build.incremental` config value.\n    incremental: Option<bool>,\n    /// Map of profile name to directory name for that profile.\n    dir_names: HashMap<InternedString, InternedString>,\n    /// The profile makers. Key is the profile name.\n    by_name: HashMap<InternedString, ProfileMaker>,\n    /// The original profiles written by the user in the manifest and config.\n    ///\n    /// This is here to assist with error reporting, as the `ProfileMaker`\n    /// values have the inherits chains all merged together.\n    original_profiles: BTreeMap<InternedString, TomlProfile>,\n    /// The profile the user requested to use.\n    requested_profile: InternedString,\n    /// The host target for rustc being used by this `Profiles`.\n    rustc_host: InternedString,\n}\n\nimpl Profiles {\n    pub fn new(ws: &Workspace<'_>, requested_profile: InternedString) -> CargoResult<Profiles> {\n        let gctx = ws.gctx();\n        let incremental = match gctx.get_env_os(\"CARGO_INCREMENTAL\") {\n            Some(v) => Some(v == \"1\"),\n            None => gctx.build_config()?.incremental,\n        };\n        let mut profiles = merge_config_profiles(ws, requested_profile)?;\n        let rustc_host = ws.gctx().load_global_rustc(Some(ws))?.host;\n\n        let mut profile_makers = Profiles {\n            incremental,\n            dir_names: Self::predefined_dir_names(),\n            by_name: HashMap::new(),\n            original_profiles: profiles.clone(),\n            requested_profile,\n            rustc_host,\n        };\n\n        let trim_paths_enabled = ws.unstable_features().is_enabled(Feature::trim_paths())\n            || gctx.cli_unstable().trim_paths;\n        Self::add_root_profiles(&mut profile_makers, &profiles, trim_paths_enabled);\n\n        // Merge with predefined profiles.\n        use std::collections::btree_map::Entry;\n        for (predef_name, mut predef_prof) in Self::predefined_profiles().into_iter() {\n            match profiles.entry(predef_name.into()) {\n                Entry::Vacant(vac) => {\n                    vac.insert(predef_prof);\n                }\n                Entry::Occupied(mut oc) => {\n                    // Override predefined with the user-provided Toml.\n                    let r = oc.get_mut();\n                    predef_prof.merge(r);\n                    *r = predef_prof;\n                }\n            }\n        }\n\n        for (name, profile) in &profiles {\n            profile_makers.add_maker(*name, profile, &profiles)?;\n        }\n        // Verify that the requested profile is defined *somewhere*.\n        // This simplifies the API (no need for CargoResult), and enforces\n        // assumptions about how config profiles are loaded.\n        profile_makers.get_profile_maker(&requested_profile)?;\n        Ok(profile_makers)\n    }\n\n    /// Returns the hard-coded directory names for built-in profiles.\n    fn predefined_dir_names() -> HashMap<InternedString, InternedString> {\n        [\n            (\"dev\".into(), \"debug\".into()),\n            (\"test\".into(), \"debug\".into()),\n            (\"bench\".into(), \"release\".into()),\n        ]\n        .into()\n    }\n\n    /// Initialize `by_name` with the two \"root\" profiles, `dev`, and\n    /// `release` given the user's definition.\n    fn add_root_profiles(\n        profile_makers: &mut Profiles,\n        profiles: &BTreeMap<InternedString, TomlProfile>,\n        trim_paths_enabled: bool,\n    ) {\n        profile_makers.by_name.insert(\n            \"dev\".into(),\n            ProfileMaker::new(Profile::default_dev(), profiles.get(\"dev\").cloned()),\n        );\n\n        profile_makers.by_name.insert(\n            \"release\".into(),\n            ProfileMaker::new(\n                Profile::default_release(trim_paths_enabled),\n                profiles.get(\"release\").cloned(),\n            ),\n        );\n    }\n\n    /// Returns the built-in profiles (not including dev/release, which are\n    /// \"root\" profiles).\n    fn predefined_profiles() -> Vec<(&'static str, TomlProfile)> {\n        vec![\n            (\n                \"bench\",\n                TomlProfile {\n                    inherits: Some(String::from(\"release\")),\n                    ..TomlProfile::default()\n                },\n            ),\n            (\n                \"test\",\n                TomlProfile {\n                    inherits: Some(String::from(\"dev\")),\n                    ..TomlProfile::default()\n                },\n            ),\n            (\n                \"doc\",\n                TomlProfile {\n                    inherits: Some(String::from(\"dev\")),\n                    ..TomlProfile::default()\n                },\n            ),\n        ]\n    }\n\n    /// Creates a `ProfileMaker`, and inserts it into `self.by_name`.\n    fn add_maker(\n        &mut self,\n        name: InternedString,\n        profile: &TomlProfile,\n        profiles: &BTreeMap<InternedString, TomlProfile>,\n    ) -> CargoResult<()> {\n        match &profile.dir_name {\n            None => {}\n            Some(dir_name) => {\n                self.dir_names.insert(name, dir_name.into());\n            }\n        }\n\n        // dev/release are \"roots\" and don't inherit.\n        if name == \"dev\" || name == \"release\" {\n            if profile.inherits.is_some() {\n                bail!(\n                    \"`inherits` must not be specified in root profile `{}`\",\n                    name\n                );\n            }\n            // Already inserted from `add_root_profiles`, no need to do anything.\n            return Ok(());\n        }\n\n        // Keep track for inherits cycles.\n        let mut set = HashSet::new();\n        set.insert(name);\n        let maker = self.process_chain(name, profile, &mut set, profiles)?;\n        self.by_name.insert(name, maker);\n        Ok(())\n    }\n\n    /// Build a `ProfileMaker` by recursively following the `inherits` setting.\n    ///\n    /// * `name`: The name of the profile being processed.\n    /// * `profile`: The TOML profile being processed.\n    /// * `set`: Set of profiles that have been visited, used to detect cycles.\n    /// * `profiles`: Map of all TOML profiles.\n    ///\n    /// Returns a `ProfileMaker` to be used for the given named profile.\n    fn process_chain(\n        &mut self,\n        name: InternedString,\n        profile: &TomlProfile,\n        set: &mut HashSet<InternedString>,\n        profiles: &BTreeMap<InternedString, TomlProfile>,\n    ) -> CargoResult<ProfileMaker> {\n        let mut maker = match &profile.inherits {\n            Some(inherits_name) if inherits_name == \"dev\" || inherits_name == \"release\" => {\n                // These are the root profiles added in `add_root_profiles`.\n                self.get_profile_maker(&inherits_name).unwrap().clone()\n            }\n            Some(inherits_name) => {\n                let inherits_name = inherits_name.into();\n                if !set.insert(inherits_name) {\n                    bail!(\n                        \"profile inheritance loop detected with profile `{}` inheriting `{}`\",\n                        name,\n                        inherits_name\n                    );\n                }\n\n                match profiles.get(&inherits_name) {\n                    None => {\n                        bail!(\n                            \"profile `{}` inherits from `{}`, but that profile is not defined\",\n                            name,\n                            inherits_name\n                        );\n                    }\n                    Some(parent) => self.process_chain(inherits_name, parent, set, profiles)?,\n                }\n            }\n            None => {\n                bail!(\n                    \"profile `{}` is missing an `inherits` directive \\\n                     (`inherits` is required for all profiles except `dev` or `release`)\",\n                    name\n                );\n            }\n        };\n        match &mut maker.toml {\n            Some(toml) => toml.merge(profile),\n            None => maker.toml = Some(profile.clone()),\n        };\n        Ok(maker)\n    }\n\n    /// Retrieves the profile for a target.\n    /// `is_member` is whether or not this package is a member of the\n    /// workspace.\n    pub fn get_profile(\n        &self,\n        pkg_id: PackageId,\n        is_member: bool,\n        is_local: bool,\n        unit_for: UnitFor,\n        kind: CompileKind,\n    ) -> Profile {\n        let maker = self.get_profile_maker(&self.requested_profile).unwrap();\n        let mut profile = maker.get_profile(Some(pkg_id), is_member, unit_for.is_for_host());\n\n        // Dealing with `panic=abort` and `panic=unwind` requires some special\n        // treatment. Be sure to process all the various options here.\n        match unit_for.panic_setting() {\n            PanicSetting::AlwaysUnwind => profile.panic = PanicStrategy::Unwind,\n            PanicSetting::ReadProfile => {}\n        }\n\n        // Default macOS debug information to being stored in the \"unpacked\"\n        // split-debuginfo format. At the time of this writing that's the only\n        // platform which has a stable `-Csplit-debuginfo` option for rustc,\n        // and it's typically much faster than running `dsymutil` on all builds\n        // in incremental cases.\n        if profile.debuginfo.is_turned_on() && profile.split_debuginfo.is_none() {\n            let target = match &kind {\n                CompileKind::Host => self.rustc_host.as_str(),\n                CompileKind::Target(target) => target.short_name(),\n            };\n            if target.contains(\"-apple-\") {\n                profile.split_debuginfo = Some(\"unpacked\".into());\n            }\n        }\n\n        // Incremental can be globally overridden.\n        if let Some(v) = self.incremental {\n            profile.incremental = v;\n        }\n\n        // Only enable incremental compilation for sources the user can\n        // modify (aka path sources). For things that change infrequently,\n        // non-incremental builds yield better performance in the compiler\n        // itself (aka crates.io / git dependencies)\n        //\n        // (see also https://github.com/rust-lang/cargo/issues/3972)\n        if !is_local {\n            profile.incremental = false;\n        }\n        profile.name = self.requested_profile;\n        profile\n    }\n\n    /// The profile for *running* a `build.rs` script is only used for setting\n    /// a few environment variables. To ensure proper de-duplication of the\n    /// running `Unit`, this uses a stripped-down profile (so that unrelated\n    /// profile flags don't cause `build.rs` to needlessly run multiple\n    /// times).\n    pub fn get_profile_run_custom_build(&self, for_unit_profile: &Profile) -> Profile {\n        let mut result = Profile::default();\n        result.name = for_unit_profile.name;\n        result.root = for_unit_profile.root;\n        result.debuginfo = for_unit_profile.debuginfo;\n        result.opt_level = for_unit_profile.opt_level;\n        result.debug_assertions = for_unit_profile.debug_assertions;\n        result.trim_paths = for_unit_profile.trim_paths.clone();\n        result\n    }\n\n    /// This returns the base profile. This is currently used for the\n    /// `[Finished]` line. It is not entirely accurate, since it doesn't\n    /// select for the package that was actually built.\n    pub fn base_profile(&self) -> Profile {\n        let profile_name = self.requested_profile;\n        let maker = self.get_profile_maker(&profile_name).unwrap();\n        maker.get_profile(None, /*is_member*/ true, /*is_for_host*/ false)\n    }\n\n    /// Gets the directory name for a profile, like `debug` or `release`.\n    pub fn get_dir_name(&self) -> InternedString {\n        *self\n            .dir_names\n            .get(&self.requested_profile)\n            .unwrap_or(&self.requested_profile)\n    }\n\n    /// Used to check for overrides for non-existing packages.\n    pub fn validate_packages(\n        &self,\n        profiles: Option<&TomlProfiles>,\n        shell: &mut Shell,\n        resolve: &Resolve,\n    ) -> CargoResult<()> {\n        for (name, profile) in &self.by_name {\n            // If the user did not specify an override, skip this. This is here\n            // to avoid generating errors for inherited profiles which don't\n            // specify package overrides. The `by_name` profile has had the inherits\n            // chain merged, so we need to look at the original source to check\n            // if an override was specified.\n            if self\n                .original_profiles\n                .get(name)\n                .and_then(|orig| orig.package.as_ref())\n                .is_none()\n            {\n                continue;\n            }\n            let found = validate_packages_unique(resolve, name, &profile.toml)?;\n            // We intentionally do not validate unmatched packages for config\n            // profiles, in case they are defined in a central location. This\n            // iterates over the manifest profiles only.\n            if let Some(profiles) = profiles {\n                if let Some(toml_profile) = profiles.get(name) {\n                    validate_packages_unmatched(shell, resolve, name, toml_profile, &found)?;\n                }\n            }\n        }\n        Ok(())\n    }\n\n    /// Returns the profile maker for the given profile name.\n    fn get_profile_maker(&self, name: &str) -> CargoResult<&ProfileMaker> {\n        self.by_name\n            .get(name)\n            .ok_or_else(|| anyhow::format_err!(\"profile `{}` is not defined\", name))\n    }\n\n    /// Returns an iterator over all profile names known to Cargo.\n    pub fn profile_names(&self) -> impl Iterator<Item = InternedString> + '_ {\n        self.by_name.keys().copied()\n    }\n}\n\n/// An object used for handling the profile hierarchy.\n///\n/// The precedence of profiles are (first one wins):\n///\n/// - Profiles in `.cargo/config` files (using same order as below).\n/// - `[profile.dev.package.name]` -- a named package.\n/// - `[profile.dev.package.\"*\"]` -- this cannot apply to workspace members.\n/// - `[profile.dev.build-override]` -- this can only apply to `build.rs` scripts\n///   and their dependencies.\n/// - `[profile.dev]`\n/// - Default (hard-coded) values.\n#[derive(Debug, Clone)]\nstruct ProfileMaker {\n    /// The starting, hard-coded defaults for the profile.\n    default: Profile,\n    /// The TOML profile defined in `Cargo.toml` or config.\n    ///\n    /// This is None if the user did not specify one, in which case the\n    /// `default` is used. Note that the built-in defaults for test/bench/doc\n    /// always set this since they need to declare the `inherits` value.\n    toml: Option<TomlProfile>,\n}\n\nimpl ProfileMaker {\n    /// Creates a new `ProfileMaker`.\n    ///\n    /// Note that this does not process `inherits`, the caller is responsible for that.\n    fn new(default: Profile, toml: Option<TomlProfile>) -> ProfileMaker {\n        ProfileMaker { default, toml }\n    }\n\n    /// Generates a new `Profile`.\n    fn get_profile(\n        &self,\n        pkg_id: Option<PackageId>,\n        is_member: bool,\n        is_for_host: bool,\n    ) -> Profile {\n        let mut profile = self.default.clone();\n\n        // First apply profile-specific settings, things like\n        // `[profile.release]`\n        if let Some(toml) = &self.toml {\n            merge_profile(&mut profile, toml);\n        }\n\n        // Next start overriding those settings. First comes build dependencies\n        // which default to opt-level 0...\n        if is_for_host {\n            // For-host units are things like procedural macros, build scripts, and\n            // their dependencies. For these units most projects simply want them\n            // to compile quickly and the runtime doesn't matter too much since\n            // they tend to process very little data. For this reason we default\n            // them to a \"compile as quickly as possible\" mode which for now means\n            // basically turning down the optimization level and avoid limiting\n            // codegen units. This ensures that we spend little time optimizing as\n            // well as enabling parallelism by not constraining codegen units.\n            profile.opt_level = \"0\".into();\n            profile.codegen_units = None;\n\n            // For build dependencies, we usually don't need debuginfo, and\n            // removing it will compile faster. However, that can conflict with\n            // a unit graph optimization, reusing units that are shared between\n            // build dependencies and runtime dependencies: when the runtime\n            // target is the same as the build host, we only need to build a\n            // dependency once and reuse the results, instead of building twice.\n            // We defer the choice of the debuginfo level until we can check if\n            // a unit is shared. If that's the case, we'll use the deferred value\n            // below so the unit can be reused, otherwise we can avoid emitting\n            // the unit's debuginfo.\n            profile.debuginfo = DebugInfo::Deferred(profile.debuginfo.into_inner());\n        }\n        // ... and next comes any other sorts of overrides specified in\n        // profiles, such as `[profile.release.build-override]` or\n        // `[profile.release.package.foo]`\n        if let Some(toml) = &self.toml {\n            merge_toml_overrides(pkg_id, is_member, is_for_host, &mut profile, toml);\n        }\n        profile\n    }\n}\n\n/// Merge package and build overrides from the given TOML profile into the given `Profile`.\nfn merge_toml_overrides(\n    pkg_id: Option<PackageId>,\n    is_member: bool,\n    is_for_host: bool,\n    profile: &mut Profile,\n    toml: &TomlProfile,\n) {\n    if is_for_host {\n        if let Some(build_override) = &toml.build_override {\n            merge_profile(profile, build_override);\n        }\n    }\n    if let Some(overrides) = toml.package.as_ref() {\n        if !is_member {\n            if let Some(all) = overrides.get(&ProfilePackageSpec::All) {\n                merge_profile(profile, all);\n            }\n        }\n        if let Some(pkg_id) = pkg_id {\n            let mut matches = overrides\n                .iter()\n                .filter_map(|(key, spec_profile)| match *key {\n                    ProfilePackageSpec::All => None,\n                    ProfilePackageSpec::Spec(ref s) => {\n                        if s.matches(pkg_id) {\n                            Some(spec_profile)\n                        } else {\n                            None\n                        }\n                    }\n                });\n            if let Some(spec_profile) = matches.next() {\n                merge_profile(profile, spec_profile);\n                // `validate_packages` should ensure that there are\n                // no additional matches.\n                assert!(\n                    matches.next().is_none(),\n                    \"package `{}` matched multiple package profile overrides\",\n                    pkg_id\n                );\n            }\n        }\n    }\n}\n\n/// Merge the given TOML profile into the given `Profile`.\n///\n/// Does not merge overrides (see `merge_toml_overrides`).\nfn merge_profile(profile: &mut Profile, toml: &TomlProfile) {\n    if let Some(ref opt_level) = toml.opt_level {\n        profile.opt_level = opt_level.0.as_str().into();\n    }\n    match toml.lto {\n        Some(StringOrBool::Bool(b)) => profile.lto = Lto::Bool(b),\n        Some(StringOrBool::String(ref n)) if is_off(n.as_str()) => profile.lto = Lto::Off,\n        Some(StringOrBool::String(ref n)) => profile.lto = Lto::Named(n.into()),\n        None => {}\n    }\n    if toml.codegen_backend.is_some() {\n        profile.codegen_backend = toml.codegen_backend.as_ref().map(InternedString::from);\n    }\n    if toml.codegen_units.is_some() {\n        profile.codegen_units = toml.codegen_units;\n    }\n    if let Some(debuginfo) = toml.debug {\n        profile.debuginfo = DebugInfo::Resolved(debuginfo);\n    }\n    if let Some(debug_assertions) = toml.debug_assertions {\n        profile.debug_assertions = debug_assertions;\n    }\n    if let Some(split_debuginfo) = &toml.split_debuginfo {\n        profile.split_debuginfo = Some(split_debuginfo.into());\n    }\n    if let Some(rpath) = toml.rpath {\n        profile.rpath = rpath;\n    }\n    if let Some(panic) = &toml.panic {\n        profile.panic = match panic.as_str() {\n            \"unwind\" => PanicStrategy::Unwind,\n            \"abort\" => PanicStrategy::Abort,\n            \"immediate-abort\" => PanicStrategy::ImmediateAbort,\n            // This should be validated in TomlProfile::validate\n            _ => panic!(\"Unexpected panic setting `{}`\", panic),\n        };\n    }\n    if let Some(overflow_checks) = toml.overflow_checks {\n        profile.overflow_checks = overflow_checks;\n    }\n    if let Some(incremental) = toml.incremental {\n        profile.incremental = incremental;\n    }\n    if let Some(flags) = &toml.rustflags {\n        profile.rustflags = flags.iter().map(InternedString::from).collect();\n    }\n    if let Some(trim_paths) = &toml.trim_paths {\n        profile.trim_paths = Some(trim_paths.clone());\n    }\n    if let Some(hint_mostly_unused) = toml.hint_mostly_unused {\n        profile.hint_mostly_unused = Some(hint_mostly_unused);\n    }\n    profile.strip = match toml.strip {\n        Some(StringOrBool::Bool(true)) => Strip::Resolved(StripInner::Named(\"symbols\".into())),\n        Some(StringOrBool::Bool(false)) => Strip::Resolved(StripInner::None),\n        Some(StringOrBool::String(ref n)) if n.as_str() == \"none\" => {\n            Strip::Resolved(StripInner::None)\n        }\n        Some(StringOrBool::String(ref n)) => Strip::Resolved(StripInner::Named(n.into())),\n        None => Strip::Deferred(StripInner::None),\n    };\n}\n\n/// The root profile (dev/release).\n///\n/// This is currently only used for the `PROFILE` env var for build scripts\n/// for backwards compatibility. We should probably deprecate `PROFILE` and\n/// encourage using things like `DEBUG` and `OPT_LEVEL` instead.\n#[derive(Clone, Copy, Eq, PartialOrd, Ord, PartialEq, Debug)]\npub enum ProfileRoot {\n    Release,\n    Debug,\n}\n\n/// Profile settings used to determine which compiler flags to use for a\n/// target.\n#[derive(Clone, Eq, PartialOrd, Ord, serde::Serialize)]\npub struct Profile {\n    pub name: InternedString,\n    pub opt_level: InternedString,\n    #[serde(skip)] // named profiles are unstable\n    pub root: ProfileRoot,\n    pub lto: Lto,\n    // `None` means use rustc default.\n    pub codegen_backend: Option<InternedString>,\n    // `None` means use rustc default.\n    pub codegen_units: Option<u32>,\n    pub debuginfo: DebugInfo,\n    pub split_debuginfo: Option<InternedString>,\n    pub debug_assertions: bool,\n    pub overflow_checks: bool,\n    pub rpath: bool,\n    pub incremental: bool,\n    pub panic: PanicStrategy,\n    pub strip: Strip,\n    #[serde(skip_serializing_if = \"Vec::is_empty\")] // remove when `rustflags` is stabilized\n    // Note that `rustflags` is used for the cargo-feature `profile_rustflags`\n    pub rustflags: Vec<InternedString>,\n    // remove when `-Ztrim-paths` is stabilized\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    pub trim_paths: Option<TomlTrimPaths>,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    pub hint_mostly_unused: Option<bool>,\n}\n\nimpl Default for Profile {\n    fn default() -> Profile {\n        Profile {\n            name: \"\".into(),\n            opt_level: \"0\".into(),\n            root: ProfileRoot::Debug,\n            lto: Lto::Bool(false),\n            codegen_backend: None,\n            codegen_units: None,\n            debuginfo: DebugInfo::Resolved(TomlDebugInfo::None),\n            debug_assertions: false,\n            split_debuginfo: None,\n            overflow_checks: false,\n            rpath: false,\n            incremental: false,\n            panic: PanicStrategy::Unwind,\n            strip: Strip::Deferred(StripInner::None),\n            rustflags: vec![],\n            trim_paths: None,\n            hint_mostly_unused: None,\n        }\n    }\n}\n\ncompact_debug! {\n    impl fmt::Debug for Profile {\n        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n            let (default, default_name) = match self.name.as_str() {\n                \"dev\" => (Profile::default_dev(), \"default_dev()\"),\n                \"release\" => (Profile::default_release(false), \"default_release()\"),\n                _ => (Profile::default(), \"default()\"),\n            };\n            [debug_the_fields(\n                name\n                opt_level\n                lto\n                root\n                codegen_backend\n                codegen_units\n                debuginfo\n                split_debuginfo\n                debug_assertions\n                overflow_checks\n                rpath\n                incremental\n                panic\n                strip\n                rustflags\n                trim_paths\n                hint_mostly_unused\n            )]\n        }\n    }\n}\n\nimpl fmt::Display for Profile {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"Profile({})\", self.name)\n    }\n}\n\nimpl hash::Hash for Profile {\n    fn hash<H>(&self, state: &mut H)\n    where\n        H: hash::Hasher,\n    {\n        self.comparable().hash(state);\n    }\n}\n\nimpl cmp::PartialEq for Profile {\n    fn eq(&self, other: &Self) -> bool {\n        self.comparable() == other.comparable()\n    }\n}\n\nimpl Profile {\n    /// Returns a built-in `dev` profile.\n    fn default_dev() -> Profile {\n        Profile {\n            name: \"dev\".into(),\n            root: ProfileRoot::Debug,\n            debuginfo: DebugInfo::Resolved(TomlDebugInfo::Full),\n            debug_assertions: true,\n            overflow_checks: true,\n            incremental: true,\n            ..Profile::default()\n        }\n    }\n\n    /// Returns a built-in `release` profile.\n    fn default_release(trim_paths_enabled: bool) -> Profile {\n        let trim_paths = trim_paths_enabled.then(|| TomlTrimPathsValue::Object.into());\n        Profile {\n            name: \"release\".into(),\n            root: ProfileRoot::Release,\n            opt_level: \"3\".into(),\n            trim_paths,\n            ..Profile::default()\n        }\n    }\n\n    /// Compares all fields except `name`, which doesn't affect compilation.\n    /// This is necessary for `Unit` deduplication for things like \"test\" and\n    /// \"dev\" which are essentially the same.\n    fn comparable(&self) -> impl Hash + Eq + '_ {\n        (\n            self.opt_level,\n            self.lto,\n            self.codegen_backend,\n            self.codegen_units,\n            self.debuginfo,\n            self.split_debuginfo,\n            self.debug_assertions,\n            self.overflow_checks,\n            self.rpath,\n            (self.incremental, self.panic, self.strip),\n            &self.rustflags,\n            &self.trim_paths,\n        )\n    }\n}\n\n/// The debuginfo level setting.\n///\n/// This is semantically a [`TomlDebugInfo`], and should be used as so via the\n/// [`DebugInfo::into_inner`] method for all intents and purposes.\n///\n/// Internally, it's used to model a debuginfo level whose value can be deferred\n/// for optimization purposes: host dependencies usually don't need the same\n/// level as target dependencies. For dependencies that are shared between the\n/// two however, that value also affects reuse: different debuginfo levels would\n/// cause to build a unit twice. By deferring the choice until we know\n/// whether to choose the optimized value or the default value, we can make sure\n/// the unit is only built once and the unit graph is still optimized.\n#[derive(Debug, Copy, Clone, serde::Serialize)]\n#[serde(untagged)]\npub enum DebugInfo {\n    /// A debuginfo level that is fixed and will not change.\n    ///\n    /// This can be set by a profile, user, or default value.\n    Resolved(TomlDebugInfo),\n    /// For internal purposes: a deferred debuginfo level that can be optimized\n    /// away, but has this value otherwise.\n    ///\n    /// Behaves like `Resolved` in all situations except for the default build\n    /// dependencies profile: whenever a build dependency is not shared with\n    /// runtime dependencies, this level is weakened to a lower level that is\n    /// faster to build (see [`DebugInfo::weaken`]).\n    ///\n    /// In all other situations, this level value will be the one to use.\n    Deferred(TomlDebugInfo),\n}\n\nimpl DebugInfo {\n    /// The main way to interact with this debuginfo level, turning it into a [`TomlDebugInfo`].\n    pub fn into_inner(self) -> TomlDebugInfo {\n        match self {\n            DebugInfo::Resolved(v) | DebugInfo::Deferred(v) => v,\n        }\n    }\n\n    /// Returns true if any debuginfo will be generated. Helper\n    /// for a common operation on the usual `Option` representation.\n    pub(crate) fn is_turned_on(&self) -> bool {\n        !matches!(self.into_inner(), TomlDebugInfo::None)\n    }\n\n    pub(crate) fn is_deferred(&self) -> bool {\n        matches!(self, DebugInfo::Deferred(_))\n    }\n\n    /// Force the deferred, preferred, debuginfo level to a finalized explicit value.\n    pub(crate) fn finalize(self) -> Self {\n        match self {\n            DebugInfo::Deferred(v) => DebugInfo::Resolved(v),\n            _ => self,\n        }\n    }\n\n    /// Reset to the lowest level: no debuginfo.\n    pub(crate) fn weaken(self) -> Self {\n        DebugInfo::Resolved(TomlDebugInfo::None)\n    }\n}\n\nimpl PartialEq for DebugInfo {\n    fn eq(&self, other: &DebugInfo) -> bool {\n        self.into_inner().eq(&other.into_inner())\n    }\n}\n\nimpl Eq for DebugInfo {}\n\nimpl Hash for DebugInfo {\n    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n        self.into_inner().hash(state);\n    }\n}\n\nimpl PartialOrd for DebugInfo {\n    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {\n        self.into_inner().partial_cmp(&other.into_inner())\n    }\n}\n\nimpl Ord for DebugInfo {\n    fn cmp(&self, other: &Self) -> std::cmp::Ordering {\n        self.into_inner().cmp(&other.into_inner())\n    }\n}\n\n/// The link-time-optimization setting.\n#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)]\npub enum Lto {\n    /// Explicitly no LTO, disables thin-LTO.\n    Off,\n    /// True = \"Fat\" LTO\n    /// False = rustc default (no args), currently \"thin LTO\"\n    Bool(bool),\n    /// Named LTO settings like \"thin\".\n    Named(InternedString),\n}\n\nimpl serde::ser::Serialize for Lto {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: serde::ser::Serializer,\n    {\n        match self {\n            Lto::Off => \"off\".serialize(s),\n            Lto::Bool(b) => b.to_string().serialize(s),\n            Lto::Named(n) => n.serialize(s),\n        }\n    }\n}\n\n/// The `panic` setting.\n#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord, serde::Serialize)]\n#[serde(rename_all = \"kebab-case\")]\npub enum PanicStrategy {\n    Unwind,\n    Abort,\n    ImmediateAbort,\n}\n\nimpl fmt::Display for PanicStrategy {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match *self {\n            PanicStrategy::Unwind => \"unwind\",\n            PanicStrategy::Abort => \"abort\",\n            PanicStrategy::ImmediateAbort => \"immediate-abort\",\n        }\n        .fmt(f)\n    }\n}\n\n#[derive(\n    Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize,\n)]\npub enum StripInner {\n    /// Don't remove any symbols\n    None,\n    /// Named Strip settings\n    Named(InternedString),\n}\n\nimpl fmt::Display for StripInner {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match *self {\n            StripInner::None => \"none\",\n            StripInner::Named(s) => s.as_str(),\n        }\n        .fmt(f)\n    }\n}\n\n/// The setting for choosing which symbols to strip.\n///\n/// This is semantically a [`StripInner`], and should be used as so via the\n/// [`Strip::into_inner`] method for all intents and purposes.\n///\n/// Internally, it's used to model a strip option whose value can be deferred\n/// for optimization purposes: when no package being compiled requires debuginfo,\n/// then we can strip debuginfo to remove pre-existing debug symbols from the\n/// standard library.\n#[derive(Clone, Copy, Debug, Eq, serde::Serialize, serde::Deserialize)]\n#[serde(rename_all = \"lowercase\")]\npub enum Strip {\n    /// A strip option that is fixed and will not change.\n    Resolved(StripInner),\n    /// A strip option that might be overridden by Cargo for optimization\n    /// purposes.\n    Deferred(StripInner),\n}\n\nimpl Strip {\n    /// The main way to interact with this strip option, turning it into a [`StripInner`].\n    pub fn into_inner(self) -> StripInner {\n        match self {\n            Strip::Resolved(v) | Strip::Deferred(v) => v,\n        }\n    }\n\n    pub(crate) fn is_deferred(&self) -> bool {\n        matches!(self, Strip::Deferred(_))\n    }\n\n    /// Reset to stripping debuginfo.\n    pub(crate) fn strip_debuginfo(self) -> Self {\n        Strip::Resolved(StripInner::Named(\"debuginfo\".into()))\n    }\n}\n\nimpl PartialEq for Strip {\n    fn eq(&self, other: &Self) -> bool {\n        self.into_inner().eq(&other.into_inner())\n    }\n}\n\nimpl Hash for Strip {\n    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n        self.into_inner().hash(state);\n    }\n}\n\nimpl PartialOrd for Strip {\n    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {\n        self.into_inner().partial_cmp(&other.into_inner())\n    }\n}\n\nimpl Ord for Strip {\n    fn cmp(&self, other: &Self) -> std::cmp::Ordering {\n        self.into_inner().cmp(&other.into_inner())\n    }\n}\n\n/// Flags used in creating `Unit`s to indicate the purpose for the target, and\n/// to ensure the target's dependencies have the correct settings.\n///\n/// This means these are passed down from the root of the dependency tree to apply\n/// to most child dependencies.\n#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]\npub struct UnitFor {\n    /// A target for `build.rs` or any of its dependencies, or a proc-macro or\n    /// any of its dependencies. This enables `build-override` profiles for\n    /// these targets.\n    ///\n    /// An invariant is that if `host_features` is true, `host` must be true.\n    ///\n    /// Note that this is `true` for `RunCustomBuild` units, even though that\n    /// unit should *not* use build-override profiles. This is a bit of a\n    /// special case. When computing the `RunCustomBuild` unit, it manually\n    /// uses the `get_profile_run_custom_build` method to get the correct\n    /// profile information for the unit. `host` needs to be true so that all\n    /// of the dependencies of that `RunCustomBuild` unit have this flag be\n    /// sticky (and forced to `true` for all further dependencies) — which is\n    /// the whole point of `UnitFor`.\n    host: bool,\n    /// A target for a build dependency or proc-macro (or any of its\n    /// dependencies). This is used for computing features of build\n    /// dependencies and proc-macros independently of other dependency kinds.\n    ///\n    /// The subtle difference between this and `host` is that the build script\n    /// for a non-host package sets this to `false` because it wants the\n    /// features of the non-host package (whereas `host` is true because the\n    /// build script is being built for the host). `host_features` becomes\n    /// `true` for build-dependencies or proc-macros, or any of their\n    /// dependencies. For example, with this dependency tree:\n    ///\n    /// ```text\n    /// foo\n    /// ├── foo build.rs\n    /// │   └── shared_dep (BUILD dependency)\n    /// │       └── shared_dep build.rs\n    /// └── shared_dep (Normal dependency)\n    ///     └── shared_dep build.rs\n    /// ```\n    ///\n    /// In this example, `foo build.rs` is `HOST=true`, `HOST_FEATURES=false`.\n    /// This is so that `foo build.rs` gets the profile settings for build\n    /// scripts (`HOST=true`) and features of foo (`HOST_FEATURES=false`) because\n    /// build scripts need to know which features their package is being built\n    /// with.\n    ///\n    /// But in the case of `shared_dep`, when built as a build dependency,\n    /// both flags are true (it only wants the build-dependency features).\n    /// When `shared_dep` is built as a normal dependency, then `shared_dep\n    /// build.rs` is `HOST=true`, `HOST_FEATURES=false` for the same reasons that\n    /// foo's build script is set that way.\n    host_features: bool,\n    /// How Cargo processes the `panic` setting or profiles.\n    panic_setting: PanicSetting,\n\n    /// The compile kind of the root unit for which artifact dependencies are built.\n    /// This is required particularly for the `target = \"target\"` setting of artifact\n    /// dependencies which mean to inherit the `--target` specified on the command-line.\n    /// However, that is a multi-value argument and root units are already created to\n    /// reflect one unit per --target. Thus we have to build one artifact with the\n    /// correct target for each of these trees.\n    /// Note that this will always be set as we don't initially know if there are\n    /// artifacts that make use of it.\n    root_compile_kind: CompileKind,\n\n    /// This is only set for artifact dependencies which have their\n    /// `<target-triple>|target` set.\n    /// If so, this information is used as part of the key for resolving their features,\n    /// allowing for target-dependent feature resolution within the entire dependency tree.\n    /// Note that this target corresponds to the target used to build the units in that\n    /// dependency tree, too, but this copy of it is specifically used for feature lookup.\n    artifact_target_for_features: Option<CompileTarget>,\n}\n\n/// How Cargo processes the `panic` setting or profiles.\n///\n/// This is done to handle test/benches inheriting from dev/release,\n/// as well as forcing `for_host` units to always unwind.\n/// It also interacts with [`-Z panic-abort-tests`].\n///\n/// [`-Z panic-abort-tests`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#panic-abort-tests\n#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]\nenum PanicSetting {\n    /// Used to force a unit to always be compiled with the `panic=unwind`\n    /// strategy, notably for build scripts, proc macros, etc.\n    AlwaysUnwind,\n\n    /// Indicates that this unit will read its `profile` setting and use\n    /// whatever is configured there.\n    ReadProfile,\n}\n\nimpl UnitFor {\n    /// A unit for a normal target/dependency (i.e., not custom build,\n    /// proc macro/plugin, or test/bench).\n    pub fn new_normal(root_compile_kind: CompileKind) -> UnitFor {\n        UnitFor {\n            host: false,\n            host_features: false,\n            panic_setting: PanicSetting::ReadProfile,\n            root_compile_kind,\n            artifact_target_for_features: None,\n        }\n    }\n\n    /// A unit for a custom build script or proc-macro or its dependencies.\n    ///\n    /// The `host_features` parameter is whether or not this is for a build\n    /// dependency or proc-macro (something that requires being built \"on the\n    /// host\"). Build scripts for non-host units should use `false` because\n    /// they want to use the features of the package they are running for.\n    pub fn new_host(host_features: bool, root_compile_kind: CompileKind) -> UnitFor {\n        UnitFor {\n            host: true,\n            host_features,\n            // Force build scripts to always use `panic=unwind` for now to\n            // maximally share dependencies with procedural macros.\n            panic_setting: PanicSetting::AlwaysUnwind,\n            root_compile_kind,\n            artifact_target_for_features: None,\n        }\n    }\n\n    /// A unit for a compiler plugin or their dependencies.\n    pub fn new_compiler(root_compile_kind: CompileKind) -> UnitFor {\n        UnitFor {\n            host: false,\n            // The feature resolver doesn't know which dependencies are\n            // plugins, so for now plugins don't split features. Since plugins\n            // are mostly deprecated, just leave this as false.\n            host_features: false,\n            // Force plugins to use `panic=abort` so panics in the compiler do\n            // not abort the process but instead end with a reasonable error\n            // message that involves catching the panic in the compiler.\n            panic_setting: PanicSetting::AlwaysUnwind,\n            root_compile_kind,\n            artifact_target_for_features: None,\n        }\n    }\n\n    /// A unit for a test/bench target or their dependencies.\n    ///\n    /// Note that `config` is taken here for unstable CLI features to detect\n    /// whether `panic=abort` is supported for tests. Historical versions of\n    /// rustc did not support this, but newer versions do with an unstable\n    /// compiler flag.\n    pub fn new_test(gctx: &GlobalContext, root_compile_kind: CompileKind) -> UnitFor {\n        UnitFor {\n            host: false,\n            host_features: false,\n            // We're testing out an unstable feature (`-Zpanic-abort-tests`)\n            // which inherits the panic setting from the dev/release profile\n            // (basically avoid recompiles) but historical defaults required\n            // that we always unwound.\n            panic_setting: if gctx.cli_unstable().panic_abort_tests {\n                PanicSetting::ReadProfile\n            } else {\n                PanicSetting::AlwaysUnwind\n            },\n            root_compile_kind,\n            artifact_target_for_features: None,\n        }\n    }\n\n    /// This is a special case for unit tests of a proc-macro.\n    ///\n    /// Proc-macro unit tests are forced to be run on the host.\n    pub fn new_host_test(gctx: &GlobalContext, root_compile_kind: CompileKind) -> UnitFor {\n        let mut unit_for = UnitFor::new_test(gctx, root_compile_kind);\n        unit_for.host = true;\n        unit_for.host_features = true;\n        unit_for\n    }\n\n    /// Returns a new copy updated based on the target dependency.\n    ///\n    /// This is where the magic happens that the `host`/`host_features` settings\n    /// transition in a sticky fashion. As the dependency graph is being\n    /// built, once those flags are set, they stay set for the duration of\n    /// that portion of tree.\n    pub fn with_dependency(\n        self,\n        parent: &Unit,\n        dep_target: &Target,\n        root_compile_kind: CompileKind,\n    ) -> UnitFor {\n        // A build script or proc-macro transitions this to being built for the host.\n        let dep_for_host = dep_target.for_host();\n        // This is where feature decoupling of host versus target happens.\n        //\n        // Once host features are desired, they are always desired.\n        //\n        // A proc-macro should always use host features.\n        //\n        // Dependencies of a build script should use host features (subtle\n        // point: the build script itself does *not* use host features, that's\n        // why the parent is checked here, and not the dependency).\n        let host_features =\n            self.host_features || parent.target.is_custom_build() || dep_target.proc_macro();\n        // Build scripts and proc macros, and all of their dependencies are\n        // AlwaysUnwind.\n        let panic_setting = if dep_for_host {\n            PanicSetting::AlwaysUnwind\n        } else {\n            self.panic_setting\n        };\n        let artifact_target_for_features =\n            // build.rs and proc-macros are always for host.\n            if dep_target.proc_macro() || parent.target.is_custom_build() {\n                None\n            } else {\n                self.artifact_target_for_features\n            };\n        UnitFor {\n            host: self.host || dep_for_host,\n            host_features,\n            panic_setting,\n            root_compile_kind,\n            artifact_target_for_features,\n        }\n    }\n\n    pub fn for_custom_build(self) -> UnitFor {\n        UnitFor {\n            host: true,\n            host_features: self.host_features,\n            // Force build scripts to always use `panic=unwind` for now to\n            // maximally share dependencies with procedural macros.\n            panic_setting: PanicSetting::AlwaysUnwind,\n            root_compile_kind: self.root_compile_kind,\n            artifact_target_for_features: self.artifact_target_for_features,\n        }\n    }\n\n    /// Set the artifact compile target for use in features using the given `artifact`.\n    pub(crate) fn with_artifact_features(mut self, artifact: &Artifact) -> UnitFor {\n        self.artifact_target_for_features = artifact.target().and_then(|t| t.to_compile_target());\n        self\n    }\n\n    /// Set the artifact compile target as determined by a resolved compile target. This is used if `target = \"target\"`.\n    pub(crate) fn with_artifact_features_from_resolved_compile_kind(\n        mut self,\n        kind: Option<CompileKind>,\n    ) -> UnitFor {\n        self.artifact_target_for_features = kind.and_then(|kind| match kind {\n            CompileKind::Host => None,\n            CompileKind::Target(triple) => Some(triple),\n        });\n        self\n    }\n\n    /// Returns `true` if this unit is for a build script or any of its\n    /// dependencies, or a proc macro or any of its dependencies.\n    pub fn is_for_host(&self) -> bool {\n        self.host\n    }\n\n    pub fn is_for_host_features(&self) -> bool {\n        self.host_features\n    }\n\n    /// Returns how `panic` settings should be handled for this profile\n    fn panic_setting(&self) -> PanicSetting {\n        self.panic_setting\n    }\n\n    /// We might contain a parent artifact compile kind for features already, but will\n    /// gladly accept the one of this dependency as an override as it defines how\n    /// the artifact is built.\n    /// If we are an artifact but don't specify a `target`, we assume the default\n    /// compile kind that is suitable in this situation.\n    pub(crate) fn map_to_features_for(&self, dep_artifact: Option<&Artifact>) -> FeaturesFor {\n        FeaturesFor::from_for_host_or_artifact_target(\n            self.is_for_host_features(),\n            match dep_artifact {\n                Some(artifact) => artifact\n                    .target()\n                    .and_then(|t| t.to_resolved_compile_target(self.root_compile_kind)),\n                None => self.artifact_target_for_features,\n            },\n        )\n    }\n\n    pub(crate) fn root_compile_kind(&self) -> CompileKind {\n        self.root_compile_kind\n    }\n}\n\n/// Takes the manifest profiles, and overlays the config profiles on-top.\n///\n/// Returns a new copy of the profile map with all the mergers complete.\nfn merge_config_profiles(\n    ws: &Workspace<'_>,\n    requested_profile: InternedString,\n) -> CargoResult<BTreeMap<InternedString, TomlProfile>> {\n    let mut profiles = match ws.profiles() {\n        Some(profiles) => profiles\n            .get_all()\n            .iter()\n            .map(|(k, v)| (InternedString::new(k), v.clone()))\n            .collect(),\n        None => BTreeMap::new(),\n    };\n    // Set of profile names to check if defined in config only.\n    let mut check_to_add = HashSet::new();\n    check_to_add.insert(requested_profile);\n    // Merge config onto manifest profiles.\n    for (name, profile) in &mut profiles {\n        if let Some(config_profile) = get_config_profile(ws, name)? {\n            profile.merge(&config_profile);\n        }\n        if let Some(inherits) = &profile.inherits {\n            check_to_add.insert(inherits.into());\n        }\n    }\n    // Add the built-in profiles. This is important for things like `cargo\n    // test` which implicitly use the \"dev\" profile for dependencies.\n    for name in [\"dev\", \"release\", \"test\", \"bench\"] {\n        check_to_add.insert(name.into());\n    }\n    // Add config-only profiles.\n    // Need to iterate repeatedly to get all the inherits values.\n    let mut current = HashSet::new();\n    while !check_to_add.is_empty() {\n        std::mem::swap(&mut current, &mut check_to_add);\n        for name in current.drain() {\n            if !profiles.contains_key(name.as_str()) {\n                if let Some(config_profile) = get_config_profile(ws, &name)? {\n                    if let Some(inherits) = &config_profile.inherits {\n                        check_to_add.insert(inherits.into());\n                    }\n                    profiles.insert(name, config_profile);\n                }\n            }\n        }\n    }\n    Ok(profiles)\n}\n\n/// Helper for fetching a profile from config.\nfn get_config_profile(ws: &Workspace<'_>, name: &str) -> CargoResult<Option<TomlProfile>> {\n    let profile: Option<context::Value<TomlProfile>> =\n        ws.gctx().get(&format!(\"profile.{}\", name))?;\n    let Some(profile) = profile else {\n        return Ok(None);\n    };\n    let mut warnings = Vec::new();\n    validate_profile(\n        &profile.val,\n        name,\n        ws.gctx().cli_unstable(),\n        ws.unstable_features(),\n        &mut warnings,\n    )\n    .with_context(|| {\n        format!(\n            \"config profile `{}` is not valid (defined in `{}`)\",\n            name, profile.definition\n        )\n    })?;\n    for warning in warnings {\n        ws.gctx().shell().warn(warning)?;\n    }\n    Ok(Some(profile.val))\n}\n\n/// Validate that a package does not match multiple package override specs.\n///\n/// For example `[profile.dev.package.bar]` and `[profile.dev.package.\"bar:0.5.0\"]`\n/// would both match `bar:0.5.0` which would be ambiguous.\nfn validate_packages_unique(\n    resolve: &Resolve,\n    name: &str,\n    toml: &Option<TomlProfile>,\n) -> CargoResult<HashSet<PackageIdSpec>> {\n    let Some(toml) = toml else {\n        return Ok(HashSet::new());\n    };\n    let Some(overrides) = toml.package.as_ref() else {\n        return Ok(HashSet::new());\n    };\n    // Verify that a package doesn't match multiple spec overrides.\n    let mut found = HashSet::new();\n    for pkg_id in resolve.iter() {\n        let matches: Vec<&PackageIdSpec> = overrides\n            .keys()\n            .filter_map(|key| match *key {\n                ProfilePackageSpec::All => None,\n                ProfilePackageSpec::Spec(ref spec) => {\n                    if spec.matches(pkg_id) {\n                        Some(spec)\n                    } else {\n                        None\n                    }\n                }\n            })\n            .collect();\n        match matches.len() {\n            0 => {}\n            1 => {\n                found.insert(matches[0].clone());\n            }\n            _ => {\n                let specs = matches\n                    .iter()\n                    .map(|spec| spec.to_string())\n                    .collect::<Vec<_>>()\n                    .join(\", \");\n                bail!(\n                    \"multiple package overrides in profile `{}` match package `{}`\\n\\\n                     found package specs: {}\",\n                    name,\n                    pkg_id,\n                    specs\n                );\n            }\n        }\n    }\n    Ok(found)\n}\n\n/// Check for any profile override specs that do not match any known packages.\n///\n/// This helps check for typos and mistakes.\nfn validate_packages_unmatched(\n    shell: &mut Shell,\n    resolve: &Resolve,\n    name: &str,\n    toml: &TomlProfile,\n    found: &HashSet<PackageIdSpec>,\n) -> CargoResult<()> {\n    let Some(overrides) = toml.package.as_ref() else {\n        return Ok(());\n    };\n\n    // Verify every override matches at least one package.\n    let missing_specs = overrides.keys().filter_map(|key| {\n        if let ProfilePackageSpec::Spec(ref spec) = *key {\n            if !found.contains(spec) {\n                return Some(spec);\n            }\n        }\n        None\n    });\n    for spec in missing_specs {\n        // See if there is an exact name match.\n        let name_matches: Vec<String> = resolve\n            .iter()\n            .filter_map(|pkg_id| {\n                if pkg_id.name() == spec.name() {\n                    Some(pkg_id.to_string())\n                } else {\n                    None\n                }\n            })\n            .collect();\n        if name_matches.is_empty() {\n            let suggestion = closest_msg(\n                &spec.name(),\n                resolve.iter(),\n                |p| p.name().as_str(),\n                \"package\",\n            );\n            shell.warn(format!(\n                \"profile package spec `{}` in profile `{}` did not match any packages{}\",\n                spec, name, suggestion\n            ))?;\n        } else {\n            shell.warn(format!(\n                \"profile package spec `{}` in profile `{}` \\\n                 has a version or URL that does not match any of the packages: {}\",\n                spec,\n                name,\n                name_matches.join(\", \")\n            ))?;\n        }\n    }\n    Ok(())\n}\n\n/// Returns `true` if a string is a toggle that turns an option off.\nfn is_off(s: &str) -> bool {\n    matches!(s, \"off\" | \"n\" | \"no\" | \"none\")\n}\n"
  },
  {
    "path": "src/cargo/core/registry.rs",
    "content": "//! Types that hold source information for a group of packages.\n//!\n//! The primary type you're looking for is [`PackageRegistry`]. It is an\n//! abstraction over multiple [`Source`]s. [`PackageRegistry`] also implements\n//! the [`Registry`] trait, allowing a dependency resolver to query necessary\n//! package metadata (i.e., [Summary]) from it.\n//!\n//! Not to be confused with [`crate::sources::registry`] and [`crate::ops::registry`].\n//! The former is just one kind of source,\n//! while the latter involves operations on the registry Web API.\n\nuse std::collections::{HashMap, HashSet};\nuse std::task::{Poll, ready};\n\nuse crate::core::{Dependency, PackageId, PackageSet, Patch, SourceId, Summary};\nuse crate::sources::IndexSummary;\nuse crate::sources::config::SourceConfigMap;\nuse crate::sources::source::QueryKind;\nuse crate::sources::source::Source;\nuse crate::sources::source::SourceMap;\nuse crate::util::errors::CargoResult;\nuse crate::util::interning::InternedString;\nuse crate::util::{CanonicalUrl, GlobalContext};\nuse annotate_snippets::Level;\nuse anyhow::Context as _;\nuse itertools::Itertools;\nuse tracing::{debug, trace};\nuse url::Url;\n\n/// An abstraction provides a set of methods for querying source information\n/// about a group of packages, without leaking too much implementation details\n/// of the actual registry.\n///\n/// As of 2024-04, only [`PackageRegistry`] and `MyRegistry` in resolver-tests\n/// are found implementing this.\n///\n/// See also the [`Source`] trait, as many of the methods here mirror and\n/// abstract over its functionalities.\npub trait Registry {\n    /// Attempt to find the packages that match a dependency request.\n    fn query(\n        &mut self,\n        dep: &Dependency,\n        kind: QueryKind,\n        f: &mut dyn FnMut(IndexSummary),\n    ) -> Poll<CargoResult<()>>;\n\n    /// Gathers the result from [`Registry::query`] as a list of [`IndexSummary`] items\n    /// when they become available.\n    fn query_vec(\n        &mut self,\n        dep: &Dependency,\n        kind: QueryKind,\n    ) -> Poll<CargoResult<Vec<IndexSummary>>> {\n        let mut ret = Vec::new();\n        self.query(dep, kind, &mut |s| ret.push(s)).map_ok(|()| ret)\n    }\n\n    /// Gets the description of a source, to provide useful messages.\n    fn describe_source(&self, source: SourceId) -> String;\n\n    /// Checks if a source is replaced with some other source.\n    fn is_replaced(&self, source: SourceId) -> bool;\n\n    /// Block until all outstanding [`Poll::Pending`] requests are [`Poll::Ready`].\n    fn block_until_ready(&mut self) -> CargoResult<()>;\n}\n\n/// This structure represents a registry of known packages. It internally\n/// contains a number of [`Source`] instances which are used to load a\n/// [`Package`] from.\n///\n/// The resolution phase of Cargo uses this to drive knowledge about new\n/// packages as well as querying for lists of new packages.\n/// It is here that sources are updated (e.g., network operations) and\n/// overrides/patches are handled.\n///\n/// The general idea behind this registry is that it is centered around the\n/// [`SourceMap`] structure, contained within which is a mapping of a [`SourceId`]\n/// to a [`Source`]. Each [`Source`] in the map has been updated (using network\n/// operations if necessary) and is ready to be queried for packages.\n///\n/// [`Package`]: crate::core::Package\npub struct PackageRegistry<'gctx> {\n    gctx: &'gctx GlobalContext,\n    sources: SourceMap<'gctx>,\n\n    /// A list of sources which are considered \"path-overrides\" which take\n    /// precedent when querying for packages.\n    overrides: Vec<SourceId>,\n\n    /// Use for tracking sources that are already loaded into the registry.\n    // Note that each SourceId does not take into account its `precise` field\n    // when hashing or testing for equality. When adding a new `SourceId`, we\n    // want to avoid duplicates in the `SourceMap` (to prevent re-updating the\n    // same git repo twice for example), but we also want to ensure that the\n    // loaded source is always updated.\n    //\n    // Sources with a `precise` field normally don't need to be updated because\n    // their contents are already on disk, but sources without a `precise` field\n    // almost always need to be updated. If we have a cached `Source` for a\n    // precise `SourceId`, then when we add a new `SourceId` that is not precise\n    // we want to ensure that the underlying source is updated.\n    //\n    // This is basically a long-winded way of saying that we want to know\n    // precisely what the keys of `sources` are, so this is a mapping of key to\n    // what exactly the key is.\n    source_ids: HashMap<SourceId, (SourceId, Kind)>,\n\n    /// This is constructed via [`PackageRegistry::register_lock`].\n    /// See also [`LockedMap`].\n    locked: LockedMap,\n    /// Packages allowed to be used, even if they are yanked.\n    yanked_whitelist: HashSet<PackageId>,\n    source_config: SourceConfigMap<'gctx>,\n\n    /// Patches registered during calls to [`PackageRegistry::patch`].\n    ///\n    /// These are available for `query` after calling [`PackageRegistry::lock_patches`],\n    /// which `lock`s them all to specific versions.\n    patches: HashMap<CanonicalUrl, Vec<Summary>>,\n    /// Whether patches are locked. That is, they are available to resolution.\n    ///\n    /// See [`PackageRegistry::lock_patches`] and [`PackageRegistry::patch`] for more.\n    patches_locked: bool,\n    /// Patches available for each source.\n    ///\n    /// This is for determining whether a dependency entry from a lockfile\n    /// happened through `[patch]`, during calls to [`lock`] to rewrite\n    /// summaries to point directly at these patched entries.\n    ///\n    /// This is constructed during calls to [`PackageRegistry::patch`],\n    /// along with the `patches` field, thoough these entries never get locked.\n    patches_available: HashMap<CanonicalUrl, Vec<PackageId>>,\n}\n\n/// A map of all \"locked packages\" which is filled in when parsing a lock file\n/// and is used to guide dependency resolution by altering summaries as they're\n/// queried from this source.\n///\n/// This map can be thought of as a glorified `Vec<MySummary>` where `MySummary`\n/// has a `PackageId` for which package it represents as well as a list of\n/// `PackageId` for the resolved dependencies. The hash map is otherwise\n/// structured though for easy access throughout this registry.\ntype LockedMap = HashMap<\n    // The first level of key-ing done in this hash map is the source that\n    // dependencies come from, identified by a `SourceId`.\n    // The next level is keyed by the name of the package...\n    (SourceId, InternedString),\n    // ... and the value here is a list of tuples. The first element of each\n    // tuple is a package which has the source/name used to get to this\n    // point. The second element of each tuple is the list of locked\n    // dependencies that the first element has.\n    Vec<(PackageId, Vec<PackageId>)>,\n>;\n\n/// Kinds of sources a [`PackageRegistry`] has loaded.\n#[derive(PartialEq, Eq, Clone, Copy)]\nenum Kind {\n    /// A source from a [path override].\n    ///\n    /// [path overrides]: https://doc.rust-lang.org/nightly/cargo/reference/overriding-dependencies.html#paths-overrides\n    Override,\n    /// A source that is locked and not going to change.\n    ///\n    /// For example, sources of workspace members are loaded during the\n    /// workspace initialization, so not allowed to change.\n    Locked,\n    /// A source that is not locked nor a path-override.\n    Normal,\n}\n\n/// This tuple is an argument to [`PackageRegistry::patch`].\n///\n/// * The first element is the patch definition straight from the manifest.\n/// * The second element is an optional variant where the patch has been locked.\n///   It is the patch locked to a specific version found in Cargo.lock.\n///   This will be `None` if `Cargo.lock` doesn't exist,\n///   or the patch did not match any existing entries in `Cargo.lock`.\npub type PatchDependency<'a> = (&'a Patch, Option<LockedPatchDependency>);\n\n/// Argument to [`PackageRegistry::patch`] which is information about a `[patch]`\n/// directive that we found in a lockfile, if present.\npub struct LockedPatchDependency {\n    /// The original `Dependency` directive, except \"locked\" so it's version\n    /// requirement is Locked to `foo` and its `SourceId` has a \"precise\" listed.\n    pub dependency: Dependency,\n    /// The `PackageId` that was previously found in a lock file which\n    /// `dependency` matches.\n    pub package_id: PackageId,\n    /// Something only used for backwards compatibility with the v2 lock file\n    /// format where `branch=master` is considered the same as `DefaultBranch`.\n    /// For more comments on this see the code in `ops/resolve.rs`.\n    pub alt_package_id: Option<PackageId>,\n}\n\nimpl<'gctx> PackageRegistry<'gctx> {\n    pub fn new_with_source_config(\n        gctx: &'gctx GlobalContext,\n        source_config: SourceConfigMap<'gctx>,\n    ) -> CargoResult<PackageRegistry<'gctx>> {\n        Ok(PackageRegistry {\n            gctx,\n            sources: SourceMap::new(),\n            source_ids: HashMap::new(),\n            overrides: Vec::new(),\n            source_config,\n            locked: HashMap::new(),\n            yanked_whitelist: HashSet::new(),\n            patches: HashMap::new(),\n            patches_locked: false,\n            patches_available: HashMap::new(),\n        })\n    }\n\n    pub fn get(self, package_ids: &[PackageId]) -> CargoResult<PackageSet<'gctx>> {\n        trace!(\"getting packages; sources={}\", self.sources.len());\n        PackageSet::new(package_ids, self.sources, self.gctx)\n    }\n\n    /// Ensures the [`Source`] of the given [`SourceId`] is loaded.\n    /// If not, this will block until the source is ready.\n    fn ensure_loaded(&mut self, namespace: SourceId, kind: Kind) -> CargoResult<()> {\n        match self.source_ids.get(&namespace) {\n            // We've previously loaded this source, and we've already locked it,\n            // so we're not allowed to change it even if `namespace` has a\n            // slightly different precise version listed.\n            Some((_, Kind::Locked)) => {\n                debug!(\"load/locked   {}\", namespace);\n                return Ok(());\n            }\n\n            // If the previous source was not a precise source, then we can be\n            // sure that it's already been updated if we've already loaded it.\n            Some((previous, _)) if !previous.has_precise() => {\n                debug!(\"load/precise  {}\", namespace);\n                return Ok(());\n            }\n\n            // If the previous source has the same precise version as we do,\n            // then we're done, otherwise we need to move forward\n            // updating this source.\n            Some((previous, _)) => {\n                if previous.has_same_precise_as(namespace) {\n                    debug!(\"load/match    {}\", namespace);\n                    return Ok(());\n                }\n                debug!(\"load/mismatch {}\", namespace);\n            }\n            None => {\n                debug!(\"load/missing  {}\", namespace);\n            }\n        }\n\n        self.load(namespace, kind)?;\n\n        // This isn't strictly necessary since it will be called later.\n        // However it improves error messages for sources that issue errors\n        // in `block_until_ready` because the callers here have context about\n        // which deps are being resolved.\n        self.block_until_ready()?;\n        Ok(())\n    }\n\n    pub fn add_sources(&mut self, ids: impl IntoIterator<Item = SourceId>) -> CargoResult<()> {\n        for id in ids {\n            self.ensure_loaded(id, Kind::Locked)?;\n        }\n        Ok(())\n    }\n\n    /// Adds a source which will be locked.\n    /// Useful for path sources such as the source of a workspace member.\n    pub fn add_preloaded(&mut self, source: Box<dyn Source + 'gctx>) {\n        self.add_source(source, Kind::Locked);\n    }\n\n    /// Adds a source to the registry.\n    fn add_source(&mut self, source: Box<dyn Source + 'gctx>, kind: Kind) {\n        let id = source.source_id();\n        self.sources.insert(source);\n        self.source_ids.insert(id, (id, kind));\n    }\n\n    /// Adds a source from a [path override].\n    ///\n    /// [path override]: https://doc.rust-lang.org/nightly/cargo/reference/overriding-dependencies.html#paths-overrides\n    pub fn add_override(&mut self, source: Box<dyn Source + 'gctx>) {\n        self.overrides.push(source.source_id());\n        self.add_source(source, Kind::Override);\n    }\n\n    /// Allows a group of package to be available to query even if they are yanked.\n    pub fn add_to_yanked_whitelist(&mut self, iter: impl Iterator<Item = PackageId>) {\n        let pkgs = iter.collect::<Vec<_>>();\n        for (_, source) in self.sources.sources_mut() {\n            source.add_to_yanked_whitelist(&pkgs);\n        }\n        self.yanked_whitelist.extend(pkgs);\n    }\n\n    /// remove all residual state from previous lock files.\n    pub fn clear_lock(&mut self) {\n        trace!(\"clear_lock\");\n        self.locked = HashMap::new();\n    }\n\n    /// Registers one \"locked package\" to the registry, for guiding the\n    /// dependency resolution. See [`LockedMap`] for more.\n    pub fn register_lock(&mut self, id: PackageId, deps: Vec<PackageId>) {\n        trace!(\"register_lock: {}\", id);\n        for dep in deps.iter() {\n            trace!(\"\\t-> {}\", dep);\n        }\n        let sub_vec = self\n            .locked\n            .entry((id.source_id(), id.name()))\n            .or_insert_with(Vec::new);\n        sub_vec.push((id, deps));\n    }\n\n    /// Insert a `[patch]` section into this registry.\n    ///\n    /// This method will insert a `[patch]` section for the `url` specified,\n    /// with the given list of dependencies. The `url` specified is the URL of\n    /// the source to patch (for example this is `crates-io` in the manifest).\n    /// The `deps` is an array of all the entries in the `[patch]` section of\n    /// the manifest.\n    ///\n    /// Here the `patch_deps` will be resolved to a precise version and stored\n    /// internally for future calls to `query` below.\n    ///\n    /// Note that the patch list specified here *will not* be available to\n    /// [`Registry::query`] until [`PackageRegistry::lock_patches`] is called\n    /// below, which should be called once all patches have been added.\n    ///\n    /// The return value is a `Vec` of patches that should *not* be locked.\n    /// This happens when the patch is locked, but the patch has been updated\n    /// so the locked value is no longer correct.\n    #[tracing::instrument(skip(self, patch_deps))]\n    pub fn patch(\n        &mut self,\n        url: &Url,\n        patch_deps: &[PatchDependency<'_>],\n    ) -> CargoResult<Vec<(Patch, PackageId)>> {\n        // NOTE: None of this code is aware of required features. If a patch\n        // is missing a required feature, you end up with an \"unused patch\"\n        // warning, which is very hard to understand. Ideally the warning\n        // would be tailored to indicate *why* it is unused.\n        let canonical = CanonicalUrl::new(url)?;\n\n        // Return value of patches that shouldn't be locked.\n        let mut unlock_patches = Vec::new();\n\n        // First up we need to actually resolve each `patch_deps` specification\n        // to precisely one summary. We're not using the `query` method below\n        // as it internally uses maps we're building up as part of this method\n        // (`patches_available` and `patches`). Instead we're going straight to\n        // the source to load information from it.\n        //\n        // Remember that each dependency listed in `[patch]` has to resolve to\n        // precisely one package, so that's why we're just creating a flat list\n        // of summaries which should be the same length as `deps` above.\n\n        let mut patch_deps_remaining: Vec<_> = patch_deps.iter().collect();\n        let mut unlocked_summaries = Vec::new();\n        while !patch_deps_remaining.is_empty() {\n            let mut patch_deps_pending = Vec::new();\n            for patch_dep_remaining in patch_deps_remaining {\n                let (orig_patch, locked) = patch_dep_remaining;\n\n                // Use the locked patch if it exists, otherwise use the original.\n                let dep = match locked {\n                    Some(lock) => &lock.dependency,\n                    None => &orig_patch.dep,\n                };\n                debug!(\n                    \"registering a patch for `{}` with `{}`\",\n                    url,\n                    dep.package_name()\n                );\n\n                let mut unused_fields = Vec::new();\n                if dep.features().len() != 0 {\n                    unused_fields.push(\"`features`\");\n                }\n                if !dep.uses_default_features() {\n                    unused_fields.push(\"`default-features`\")\n                }\n                if !unused_fields.is_empty() {\n                    self.source_config.gctx().shell().print_report(\n                        &[Level::WARNING\n                            .secondary_title(format!(\n                                \"unused field in patch for `{}`: {}\",\n                                dep.package_name(),\n                                unused_fields.join(\", \")\n                            ))\n                            .element(Level::HELP.message(format!(\n                                \"configure {} in the `dependencies` entry\",\n                                unused_fields.join(\", \")\n                            )))],\n                        false,\n                    )?;\n                }\n\n                // Go straight to the source for resolving `dep`. Load it as we\n                // normally would and then ask it directly for the list of summaries\n                // corresponding to this `dep`.\n                self.ensure_loaded(dep.source_id(), Kind::Normal)\n                    .with_context(|| {\n                        format!(\n                            \"failed to load source for dependency `{}`\",\n                            dep.package_name()\n                        )\n                    })?;\n\n                let source = self\n                    .sources\n                    .get_mut(dep.source_id())\n                    .expect(\"loaded source not present\");\n\n                let summaries = match source.query_vec(dep, QueryKind::Exact)? {\n                    Poll::Ready(deps) => deps,\n                    Poll::Pending => {\n                        patch_deps_pending.push(patch_dep_remaining);\n                        continue;\n                    }\n                };\n\n                let summaries = summaries.into_iter().map(|s| s.into_summary()).collect();\n\n                let (summary, should_unlock) =\n                    match summary_for_patch(&orig_patch, url, &locked, summaries, source) {\n                        Poll::Ready(x) => x,\n                        Poll::Pending => {\n                            patch_deps_pending.push(patch_dep_remaining);\n                            continue;\n                        }\n                    }?;\n\n                debug!(\n                    \"patch summary is {:?} should_unlock={:?}\",\n                    summary, should_unlock\n                );\n                if let Some(unlock_id) = should_unlock {\n                    unlock_patches.push(((*orig_patch).clone(), unlock_id));\n                }\n\n                if *summary.package_id().source_id().canonical_url() == canonical {\n                    return Err(anyhow::anyhow!(\n                        \"patch for `{}` points to the same source, but patches must point to different sources\\n\\\n                        help: check `{}` patch definition for `{}` in `{}`\",\n                        dep.package_name(),\n                        dep.package_name(),\n                        url,\n                        orig_patch.loc\n                    ));\n                }\n                unlocked_summaries.push(summary);\n            }\n\n            patch_deps_remaining = patch_deps_pending;\n            self.block_until_ready()?;\n        }\n\n        let mut name_and_version = HashSet::new();\n        for summary in unlocked_summaries.iter() {\n            let name = summary.package_id().name();\n            let version = summary.package_id().version();\n            if !name_and_version.insert((name, version)) {\n                let duplicate_locations = patch_deps\n                    .iter()\n                    .filter(|&p| p.0.dep.package_name() == name)\n                    .map(|p| format!(\"`{}`\", p.0.loc))\n                    .unique()\n                    .join(\", \");\n                return Err(anyhow::anyhow!(\n                    \"several `[patch]` entries resolving to same version `{} v{}`\\n\\\n                    help: check `{}` patch definitions for `{}` in {}\",\n                    name,\n                    version,\n                    name,\n                    url,\n                    duplicate_locations\n                ));\n            }\n        }\n\n        // Calculate a list of all patches available for this source.\n        let mut ids = Vec::new();\n        for (summary, (_, lock)) in unlocked_summaries.iter().zip(patch_deps) {\n            ids.push(summary.package_id());\n            // This is subtle where the list of `ids` for a canonical URL is\n            // extend with possibly two ids per summary. This is done to handle\n            // the transition from the v2->v3 lock file format where in v2\n            // DefaultBranch was either DefaultBranch or Branch(\"master\") for\n            // git dependencies. In this case if `summary.package_id()` is\n            // Branch(\"master\") then alt_package_id will be DefaultBranch. This\n            // signifies that there's a patch available for either of those\n            // dependency directives if we see them in the dependency graph.\n            if let Some(lock) = lock {\n                ids.extend(lock.alt_package_id);\n            }\n        }\n        self.patches_available.insert(canonical.clone(), ids);\n\n        // Note that we do not use `lock` here to lock summaries! That step\n        // happens later once `lock_patches` is invoked. In the meantime though\n        // we want to fill in the `patches_available` map (later used in the\n        // `lock` method) and otherwise store the unlocked summaries in\n        // `patches` to get locked in a future call to `lock_patches`.\n        self.patches.insert(canonical, unlocked_summaries);\n\n        Ok(unlock_patches)\n    }\n\n    /// Lock all patch summaries added via [`patch`](Self::patch),\n    /// making them available to resolution via [`Registry::query`].\n    pub fn lock_patches(&mut self) {\n        assert!(!self.patches_locked);\n        for summaries in self.patches.values_mut() {\n            for summary in summaries {\n                debug!(\"locking patch {:?}\", summary);\n                *summary = lock(&self.locked, &self.patches_available, summary.clone());\n            }\n        }\n        self.patches_locked = true;\n    }\n\n    /// Gets all patches grouped by the source URLs they are going to patch.\n    ///\n    /// These patches are mainly collected from [`patch`](Self::patch).\n    /// They might not be the same as patches actually used during dependency resolving.\n    pub fn patches(&self) -> &HashMap<CanonicalUrl, Vec<Summary>> {\n        &self.patches\n    }\n\n    /// Loads the [`Source`] for a given [`SourceId`] to this registry, making\n    /// them available to resolution.\n    fn load(&mut self, source_id: SourceId, kind: Kind) -> CargoResult<()> {\n        debug!(\"loading source {}\", source_id);\n        let source = self\n            .source_config\n            .load(source_id, &self.yanked_whitelist)\n            .with_context(|| format!(\"unable to update {}\", source_id))?;\n        assert_eq!(source.source_id(), source_id);\n\n        if kind == Kind::Override {\n            self.overrides.push(source_id);\n        }\n        self.add_source(source, kind);\n\n        // If we have an imprecise version then we don't know what we're going\n        // to look for, so we always attempt to perform an update here.\n        //\n        // If we have a precise version, then we'll update lazily during the\n        // querying phase. Note that precise in this case is only\n        // `\"locked\"` as other values indicate a `cargo update\n        // --precise` request\n        if !source_id.has_locked_precise() {\n            self.sources.get_mut(source_id).unwrap().invalidate_cache();\n        } else {\n            debug!(\"skipping update due to locked registry\");\n        }\n        Ok(())\n    }\n\n    /// Queries path overrides from this registry.\n    fn query_overrides(&mut self, dep: &Dependency) -> Poll<CargoResult<Option<IndexSummary>>> {\n        for &s in self.overrides.iter() {\n            let src = self.sources.get_mut(s).unwrap();\n            let dep = Dependency::new_override(dep.package_name(), s);\n\n            let mut results = None;\n            ready!(src.query(&dep, QueryKind::Exact, &mut |s| results = Some(s)))?;\n            if results.is_some() {\n                return Poll::Ready(Ok(results));\n            }\n        }\n        Poll::Ready(Ok(None))\n    }\n\n    /// This function is used to transform a summary to another locked summary\n    /// if possible. This is where the concept of a lock file comes into play.\n    ///\n    /// If a summary points at a package ID which was previously locked, then we\n    /// override the summary's ID itself, as well as all dependencies, to be\n    /// rewritten to the locked versions. This will transform the summary's\n    /// source to a precise source (listed in the locked version) as well as\n    /// transforming all of the dependencies from range requirements on\n    /// imprecise sources to exact requirements on precise sources.\n    ///\n    /// If a summary does not point at a package ID which was previously locked,\n    /// or if any dependencies were added and don't have a previously listed\n    /// version, we still want to avoid updating as many dependencies as\n    /// possible to keep the graph stable. In this case we map all of the\n    /// summary's dependencies to be rewritten to a locked version wherever\n    /// possible. If we're unable to map a dependency though, we just pass it on\n    /// through.\n    pub fn lock(&self, summary: Summary) -> Summary {\n        assert!(self.patches_locked);\n        lock(&self.locked, &self.patches_available, summary)\n    }\n\n    fn warn_bad_override(\n        &self,\n        override_summary: &Summary,\n        real_summary: &Summary,\n    ) -> CargoResult<()> {\n        let mut real_deps = real_summary.dependencies().iter().collect::<Vec<_>>();\n\n        let boilerplate = \"\\\nThis is currently allowed but is known to produce buggy behavior with spurious\nrecompiles and changes to the crate graph. Path overrides unfortunately were\nnever intended to support this feature, so for now this message is just a\nwarning. In the future, however, this message will become a hard error.\n\nTo change the dependency graph via an override it's recommended to use the\n`[patch]` feature of Cargo instead of the path override feature. This is\ndocumented online at the url below for more information.\n\nhttps://doc.rust-lang.org/cargo/reference/overriding-dependencies.html\n\";\n\n        for dep in override_summary.dependencies() {\n            if let Some(i) = real_deps.iter().position(|d| dep == *d) {\n                real_deps.remove(i);\n                continue;\n            }\n            let msg = format!(\n                \"path override for crate `{}` has altered the original list of\\n\\\n                 dependencies; the dependency on `{}` was either added or\\n\\\n                 modified to not match the previously resolved version\\n\\n\\\n                 {}\",\n                override_summary.package_id().name(),\n                dep.package_name(),\n                boilerplate\n            );\n            self.source_config.gctx().shell().warn(&msg)?;\n            return Ok(());\n        }\n\n        if let Some(dep) = real_deps.get(0) {\n            let msg = format!(\n                \"path override for crate `{}` has altered the original list of\\n\\\n                 dependencies; the dependency on `{}` was removed\\n\\n\\\n                 {}\",\n                override_summary.package_id().name(),\n                dep.package_name(),\n                boilerplate\n            );\n            self.source_config.gctx().shell().warn(&msg)?;\n            return Ok(());\n        }\n\n        Ok(())\n    }\n}\n\nimpl<'gctx> Registry for PackageRegistry<'gctx> {\n    fn query(\n        &mut self,\n        dep: &Dependency,\n        kind: QueryKind,\n        f: &mut dyn FnMut(IndexSummary),\n    ) -> Poll<CargoResult<()>> {\n        assert!(self.patches_locked);\n        // Look for an override and get ready to query the real source.\n        let override_summary = ready!(self.query_overrides(dep))?;\n\n        // Next up on our list of candidates is to check the `[patch]` section\n        // of the manifest. Here we look through all patches relevant to the\n        // source that `dep` points to, and then we match name/version. Note\n        // that we don't use `dep.matches(..)` because the patches, by definition,\n        // come from a different source. This means that `dep.matches(..)` will\n        // always return false, when what we really care about is the name/version match.\n        let mut patches = Vec::<Summary>::new();\n        if let Some(extra) = self.patches.get(dep.source_id().canonical_url()) {\n            patches.extend(\n                extra\n                    .iter()\n                    .filter(|s| dep.matches_ignoring_source(s.package_id()))\n                    .cloned(),\n            );\n        }\n\n        // A crucial feature of the `[patch]` feature is that we don't query the\n        // actual registry if we have a \"locked\" dependency. A locked dep basically\n        // just means a version constraint of `=a.b.c`, and because patches take\n        // priority over the actual source then if we have a candidate we're done.\n        if patches.len() == 1 && dep.is_locked() {\n            let patch = patches.remove(0);\n            match override_summary {\n                Some(override_summary) => {\n                    self.warn_bad_override(override_summary.as_summary(), &patch)?;\n                    let override_summary =\n                        override_summary.map_summary(|summary| self.lock(summary));\n                    f(override_summary);\n                }\n                None => f(IndexSummary::Candidate(patch)),\n            }\n\n            return Poll::Ready(Ok(()));\n        }\n\n        if !patches.is_empty() {\n            debug!(\n                \"found {} patches with an unlocked dep on `{}` at {} \\\n                     with `{}`, \\\n                     looking at sources\",\n                patches.len(),\n                dep.package_name(),\n                dep.source_id(),\n                dep.version_req()\n            );\n        }\n\n        // Ensure the requested source_id is loaded\n        self.ensure_loaded(dep.source_id(), Kind::Normal)\n            .with_context(|| {\n                format!(\n                    \"failed to load source for dependency `{}`\",\n                    dep.package_name()\n                )\n            })?;\n\n        let source = self.sources.get_mut(dep.source_id());\n        match (override_summary, source) {\n            (Some(_), None) => {\n                return Poll::Ready(Err(anyhow::anyhow!(\"override found but no real ones\")));\n            }\n            (None, None) => return Poll::Ready(Ok(())),\n\n            // If we don't have an override then we just ship everything upstairs after locking the summary\n            (None, Some(source)) => {\n                for patch in patches.iter() {\n                    f(IndexSummary::Candidate(patch.clone()));\n                }\n\n                // Our sources shouldn't ever come back to us with two summaries\n                // that have the same version. We could, however, have an `[patch]`\n                // section which is in use to override a version in the registry.\n                // This means that if our `summary` in this loop has the same\n                // version as something in `patches` that we've already selected,\n                // then we skip this `summary`.\n                let locked = &self.locked;\n                let all_patches = &self.patches_available;\n                let callback = &mut |summary: IndexSummary| {\n                    for patch in patches.iter() {\n                        let patch = patch.package_id().version();\n                        if summary.package_id().version() == patch {\n                            return;\n                        }\n                    }\n                    let summary = summary.map_summary(|summary| lock(locked, all_patches, summary));\n                    f(summary)\n                };\n                return source.query(dep, kind, callback);\n            }\n\n            // If we have an override summary then we query the source to sanity check its results.\n            // We don't actually use any of the summaries it gives us though.\n            (Some(override_summary), Some(source)) => {\n                if !patches.is_empty() {\n                    return Poll::Ready(Err(anyhow::anyhow!(\"found patches and a path override\")));\n                }\n                let mut n = 0;\n                let mut to_warn = None;\n                let callback = &mut |summary| {\n                    n += 1;\n                    to_warn = Some(summary);\n                };\n                let pend = source.query(dep, kind, callback);\n                if pend.is_pending() {\n                    return Poll::Pending;\n                }\n                if n > 1 {\n                    return Poll::Ready(Err(anyhow::anyhow!(\n                        \"found an override with a non-locked list\"\n                    )));\n                }\n                if let Some(to_warn) = to_warn {\n                    self.warn_bad_override(override_summary.as_summary(), to_warn.as_summary())?;\n                }\n                let override_summary = override_summary.map_summary(|summary| self.lock(summary));\n                f(override_summary);\n            }\n        }\n\n        Poll::Ready(Ok(()))\n    }\n\n    fn describe_source(&self, id: SourceId) -> String {\n        match self.sources.get(id) {\n            Some(src) => src.describe(),\n            None => id.to_string(),\n        }\n    }\n\n    fn is_replaced(&self, id: SourceId) -> bool {\n        match self.sources.get(id) {\n            Some(src) => src.is_replaced(),\n            None => false,\n        }\n    }\n\n    #[tracing::instrument(skip_all)]\n    fn block_until_ready(&mut self) -> CargoResult<()> {\n        // Ensure `shell` is not already in use,\n        // regardless of which source is used and how it happens to behave this time\n        self.gctx.debug_assert_shell_not_borrowed();\n        for (source_id, source) in self.sources.sources_mut() {\n            source\n                .block_until_ready()\n                .with_context(|| format!(\"unable to update {}\", source_id))?;\n        }\n        Ok(())\n    }\n}\n\n/// See [`PackageRegistry::lock`].\nfn lock(\n    locked: &LockedMap,\n    patches: &HashMap<CanonicalUrl, Vec<PackageId>>,\n    summary: Summary,\n) -> Summary {\n    let pair = locked\n        .get(&(summary.source_id(), summary.name()))\n        .and_then(|vec| vec.iter().find(|&&(id, _)| id == summary.package_id()));\n\n    trace!(\"locking summary of {}\", summary.package_id());\n\n    // Lock the summary's ID if possible\n    let summary = match pair {\n        Some((precise, _)) => summary.override_id(*precise),\n        None => summary,\n    };\n    summary.map_dependencies(|dep| {\n        trace!(\n            \"\\t{}/{}/{}\",\n            dep.package_name(),\n            dep.version_req(),\n            dep.source_id()\n        );\n\n        // If we've got a known set of overrides for this summary, then\n        // one of a few cases can arise:\n        //\n        // 1. We have a lock entry for this dependency from the same\n        //    source as it's listed as coming from. In this case we make\n        //    sure to lock to precisely the given package ID.\n        //\n        // 2. We have a lock entry for this dependency, but it's from a\n        //    different source than what's listed, or the version\n        //    requirement has changed. In this case we must discard the\n        //    locked version because the dependency needs to be\n        //    re-resolved.\n        //\n        // 3. We have a lock entry for this dependency, but it's from a\n        //    different source than what's listed. This lock though happens\n        //    through `[patch]`, so we want to preserve it.\n        //\n        // 4. We don't have a lock entry for this dependency, in which\n        //    case it was likely an optional dependency which wasn't\n        //    included previously so we just pass it through anyway.\n        //\n        // Cases 1/2 are handled by `matches_id`, case 3 is handled specially,\n        // and case 4 is handled by falling through to the logic below.\n        if let Some((_, locked_deps)) = pair {\n            let locked = locked_deps.iter().find(|&&id| {\n                // If the dependency matches the package id exactly then we've\n                // found a match, this is the id the dependency was previously\n                // locked to.\n                if dep.matches_id(id) {\n                    return true;\n                }\n\n                // If the name/version doesn't match, then we definitely don't\n                // have a match whatsoever. Otherwise we need to check\n                // `[patch]`...\n                if !dep.matches_ignoring_source(id) {\n                    return false;\n                }\n\n                // ... so here we look up the dependency url in the patches\n                // map, and we see if `id` is contained in the list of patches\n                // for that url. If it is then this lock is still valid,\n                // otherwise the lock is no longer valid.\n                match patches.get(dep.source_id().canonical_url()) {\n                    Some(list) => list.contains(&id),\n                    None => false,\n                }\n            });\n\n            if let Some(&locked) = locked {\n                trace!(\"\\tfirst hit on {}\", locked);\n                let mut dep = dep;\n\n                // If we found a locked version where the sources match, then\n                // we can `lock_to` to get an exact lock on this dependency.\n                // Otherwise we got a lock via `[patch]` so we only lock the\n                // version requirement, not the source.\n                if locked.source_id() == dep.source_id() {\n                    dep.lock_to(locked);\n                } else {\n                    dep.lock_version(locked.version());\n                }\n                return dep;\n            }\n        }\n\n        // If this dependency did not have a locked version, then we query\n        // all known locked packages to see if they match this dependency.\n        // If anything does then we lock it to that and move on.\n        let v = locked\n            .get(&(dep.source_id(), dep.package_name()))\n            .and_then(|vec| vec.iter().find(|&&(id, _)| dep.matches_id(id)));\n        if let Some(&(id, _)) = v {\n            trace!(\"\\tsecond hit on {}\", id);\n            let mut dep = dep;\n            dep.lock_to(id);\n            return dep;\n        }\n\n        trace!(\"\\tnope, unlocked\");\n        dep\n    })\n}\n\n/// A helper for selecting the summary, or generating a helpful error message.\n///\n/// Returns a tuple that the first element is the summary selected. The second\n/// is a package ID indicating that the patch entry should be unlocked. This\n/// happens when a match cannot be found with the `locked` one, but found one\n/// via the original patch, so we need to inform the resolver to \"unlock\" it.\nfn summary_for_patch(\n    original_patch: &Patch,\n    orig_patch_url: &Url,\n    locked: &Option<LockedPatchDependency>,\n    mut summaries: Vec<Summary>,\n    source: &mut dyn Source,\n) -> Poll<CargoResult<(Summary, Option<PackageId>)>> {\n    if summaries.len() == 1 {\n        return Poll::Ready(Ok((summaries.pop().unwrap(), None)));\n    }\n    if summaries.len() > 1 {\n        // TODO: In the future, it might be nice to add all of these\n        // candidates so that version selection would just pick the\n        // appropriate one. However, as this is currently structured, if we\n        // added these all as patches, the unselected versions would end up in\n        // the \"unused patch\" listing, and trigger a warning. It might take a\n        // fair bit of restructuring to make that work cleanly, and there\n        // isn't any demand at this time to support that.\n        let mut vers: Vec<_> = summaries.iter().map(|summary| summary.version()).collect();\n        vers.sort();\n        let versions: Vec<_> = vers.into_iter().map(|v| v.to_string()).collect();\n        return Poll::Ready(Err(anyhow::anyhow!(\n            \"patch for `{}` in `{}` resolved to more than one candidate\\n\\\n            note: found versions: {}\\n\\\n            help: check `{}` patch definition for `{}` in `{}`\\n\\\n            help: select only one package using `version = \\\"={}\\\"`\",\n            &original_patch.dep.package_name(),\n            &original_patch.dep.source_id(),\n            versions.join(\", \"),\n            &original_patch.dep.package_name(),\n            orig_patch_url,\n            original_patch.loc,\n            versions.last().unwrap()\n        )));\n    }\n    assert!(summaries.is_empty());\n    // No summaries found, try to help the user figure out what is wrong.\n    if let Some(locked) = locked {\n        // Since the locked patch did not match anything, try the unlocked one.\n        let orig_matches = ready!(source.query_vec(&original_patch.dep, QueryKind::Exact))\n            .unwrap_or_else(|e| {\n                tracing::warn!(\n                    \"could not determine unlocked summaries for dep {:?}: {:?}\",\n                    &original_patch.dep,\n                    e\n                );\n                Vec::new()\n            });\n\n        let orig_matches = orig_matches.into_iter().map(|s| s.into_summary()).collect();\n\n        let summary = ready!(summary_for_patch(\n            original_patch,\n            orig_patch_url,\n            &None,\n            orig_matches,\n            source\n        ))?;\n        return Poll::Ready(Ok((summary.0, Some(locked.package_id))));\n    }\n    // Try checking if there are *any* packages that match this by name.\n    let name_only_dep = Dependency::new_override(\n        original_patch.dep.package_name(),\n        original_patch.dep.source_id(),\n    );\n\n    let name_summaries =\n        ready!(source.query_vec(&name_only_dep, QueryKind::Exact)).unwrap_or_else(|e| {\n            tracing::warn!(\n                \"failed to do name-only summary query for {:?}: {:?}\",\n                name_only_dep,\n                e\n            );\n            Vec::new()\n        });\n    let mut vers = name_summaries\n        .iter()\n        .map(|summary| summary.as_summary().version())\n        .collect::<Vec<_>>();\n    let found = match vers.len() {\n        0 => \"\".to_string(),\n        1 => format!(\"version `{}`\", vers[0]),\n        _ => {\n            vers.sort();\n            let strs: Vec<_> = vers.into_iter().map(|v| v.to_string()).collect();\n            format!(\"versions `{}`\", strs.join(\", \"))\n        }\n    };\n    Poll::Ready(Err(if found.is_empty() {\n        anyhow::anyhow!(\n            \"patch location `{}` does not contain packages matching `{}`\\n\\\n            help: check `{}` patch definition for `{}` in `{}`\",\n            &original_patch.dep.source_id(),\n            &original_patch.dep.package_name(),\n            &original_patch.dep.package_name(),\n            orig_patch_url,\n            original_patch.loc\n        )\n    } else {\n        anyhow::anyhow!(\n            \"patch `{}` version mismatch\\n\\\n            note: patch location contains {}, but patch definition requires `{}`\\n\\\n            help: check patch location `{}`\\n\\\n            help: check `{}` patch definition for `{}` in `{}`\",\n            &original_patch.dep.package_name(),\n            found,\n            &original_patch.dep.version_req(),\n            &original_patch.dep.source_id(),\n            &original_patch.dep.package_name(),\n            orig_patch_url,\n            original_patch.loc\n        )\n    }))\n}\n"
  },
  {
    "path": "src/cargo/core/resolver/conflict_cache.rs",
    "content": "use std::collections::{BTreeMap, HashMap};\n\nuse rustc_hash::{FxHashMap, FxHashSet};\nuse tracing::trace;\n\nuse super::types::ConflictMap;\nuse crate::core::resolver::ResolverContext;\nuse crate::core::{Dependency, PackageId};\n\n/// This is a trie for storing a large number of sets designed to\n/// efficiently see if any of the stored sets are a subset of a search set.\nenum ConflictStoreTrie {\n    /// One of the stored sets.\n    Leaf(ConflictMap),\n    /// A map from an element to a subtrie where\n    /// all the sets in the subtrie contains that element.\n    Node(BTreeMap<PackageId, ConflictStoreTrie>),\n}\n\nimpl ConflictStoreTrie {\n    /// Finds any known set of conflicts, if any,\n    /// where all elements return some from `is_active` and contain `PackageId` specified.\n    /// If more than one are activated, then it will return\n    /// one that will allow for the most jump-back.\n    fn find(\n        &self,\n        is_active: &impl Fn(PackageId) -> Option<usize>,\n        must_contain: Option<PackageId>,\n        mut max_age: usize,\n    ) -> Option<(&ConflictMap, usize)> {\n        match self {\n            ConflictStoreTrie::Leaf(c) => {\n                if must_contain.is_none() {\n                    Some((c, 0))\n                } else {\n                    // We did not find `must_contain`, so we need to keep looking.\n                    None\n                }\n            }\n            ConflictStoreTrie::Node(m) => {\n                let mut out = None;\n                for (&pid, store) in must_contain\n                    .map(|f| m.range(..=f))\n                    .unwrap_or_else(|| m.range(..))\n                {\n                    // If the key is active, then we need to check all of the corresponding subtrie.\n                    if let Some(age_this) = is_active(pid) {\n                        if age_this >= max_age && must_contain != Some(pid) {\n                            // not worth looking at, it is to old.\n                            continue;\n                        }\n                        if let Some((o, age_o)) =\n                            store.find(is_active, must_contain.filter(|&f| f != pid), max_age)\n                        {\n                            let age = if must_contain == Some(pid) {\n                                // all the results will include `must_contain`\n                                // so the age of must_contain is not relevant to find the best result.\n                                age_o\n                            } else {\n                                std::cmp::max(age_this, age_o)\n                            };\n                            if max_age > age {\n                                // we found one that can jump-back further so replace the out.\n                                out = Some((o, age));\n                                // and don't look at anything older\n                                max_age = age\n                            }\n                        }\n                    }\n                    // Else, if it is not active then there is no way any of the corresponding\n                    // subtrie will be conflicting.\n                }\n                out\n            }\n        }\n    }\n\n    fn insert(&mut self, mut iter: impl Iterator<Item = PackageId>, con: ConflictMap) {\n        if let Some(pid) = iter.next() {\n            if let ConflictStoreTrie::Node(p) = self {\n                p.entry(pid)\n                    .or_insert_with(|| ConflictStoreTrie::Node(BTreeMap::new()))\n                    .insert(iter, con);\n            }\n        // Else, we already have a subset of this in the `ConflictStore`.\n        } else {\n            // We are at the end of the set we are adding, there are three cases for what to do\n            // next:\n            // 1. `self` is an empty dummy Node inserted by `or_insert_with`\n            //      in witch case we should replace it with `Leaf(con)`.\n            // 2. `self` is a `Node` because we previously inserted a superset of\n            //      the thing we are working on (I don't know if this happens in practice)\n            //      but the subset that we are working on will\n            //      always match any time the larger set would have\n            //      in witch case we can replace it with `Leaf(con)`.\n            // 3. `self` is a `Leaf` that is in the same spot in the structure as\n            //      the thing we are working on. So it is equivalent.\n            //      We can replace it with `Leaf(con)`.\n            if cfg!(debug_assertions) {\n                if let ConflictStoreTrie::Leaf(c) = self {\n                    let a: Vec<_> = con.keys().collect();\n                    let b: Vec<_> = c.keys().collect();\n                    assert_eq!(a, b);\n                }\n            }\n            *self = ConflictStoreTrie::Leaf(con)\n        }\n    }\n}\n\npub(super) struct ConflictCache {\n    // `con_from_dep` is a cache of the reasons for each time we\n    // backtrack. For example after several backtracks we may have:\n    //\n    //  con_from_dep[`foo = \"^1.0.2\"`] = map!{\n    //      `foo=1.0.1`: map!{`foo=1.0.1`: Semver},\n    //      `foo=1.0.0`: map!{`foo=1.0.0`: Semver},\n    //  };\n    //\n    // This can be read as \"we cannot find a candidate for dep `foo = \"^1.0.2\"`\n    // if either `foo=1.0.1` OR `foo=1.0.0` are activated\".\n    //\n    // Another example after several backtracks we may have:\n    //\n    //  con_from_dep[`foo = \">=0.8.2, <=0.9.3\"`] = map!{\n    //      `foo=0.8.1`: map!{\n    //          `foo=0.9.4`: map!{`foo=0.8.1`: Semver, `foo=0.9.4`: Semver},\n    //      }\n    //  };\n    //\n    // This can be read as \"we cannot find a candidate for dep `foo = \">=0.8.2,\n    // <=0.9.3\"` if both `foo=0.8.1` AND `foo=0.9.4` are activated\".\n    //\n    // This is used to make sure we don't queue work we know will fail. See the\n    // discussion in https://github.com/rust-lang/cargo/pull/5168 for why this\n    // is so important. The nested HashMaps act as a kind of btree, that lets us\n    // look up which entries are still active without\n    // linearly scanning through the full list.\n    //\n    // Also, as a final note, this map is **not** ever removed from. This remains\n    // as a global cache which we never delete from. Any entry in this map is\n    // unconditionally true regardless of our resolution history of how we got\n    // here.\n    con_from_dep: FxHashMap<Dependency, ConflictStoreTrie>,\n    // `dep_from_pid` is an inverse-index of `con_from_dep`.\n    // For every `PackageId` this lists the `Dependency`s that mention it in `dep_from_pid`.\n    dep_from_pid: FxHashMap<PackageId, FxHashSet<Dependency>>,\n}\n\nimpl ConflictCache {\n    pub fn new() -> ConflictCache {\n        ConflictCache {\n            con_from_dep: HashMap::default(),\n            dep_from_pid: HashMap::default(),\n        }\n    }\n    pub fn find(\n        &self,\n        dep: &Dependency,\n        is_active: &impl Fn(PackageId) -> Option<usize>,\n        must_contain: Option<PackageId>,\n        max_age: usize,\n    ) -> Option<&ConflictMap> {\n        self.con_from_dep\n            .get(dep)?\n            .find(is_active, must_contain, max_age)\n            .map(|(c, _)| c)\n    }\n    /// Finds any known set of conflicts, if any,\n    /// which are activated in `cx` and contain `PackageId` specified.\n    /// If more than one are activated, then it will return\n    /// one that will allow for the most jump-back.\n    pub fn find_conflicting(\n        &self,\n        cx: &ResolverContext,\n        dep: &Dependency,\n        must_contain: Option<PackageId>,\n    ) -> Option<&ConflictMap> {\n        let out = self.find(dep, &|id| cx.is_active(id), must_contain, usize::MAX);\n        if cfg!(debug_assertions) {\n            if let Some(c) = &out {\n                assert!(cx.is_conflicting(None, c).is_some());\n                if let Some(f) = must_contain {\n                    assert!(c.contains_key(&f));\n                }\n            }\n        }\n        out\n    }\n    pub fn conflicting(&self, cx: &ResolverContext, dep: &Dependency) -> Option<&ConflictMap> {\n        self.find_conflicting(cx, dep, None)\n    }\n\n    /// Adds to the cache a conflict of the form:\n    /// `dep` is known to be unresolvable if\n    /// all the `PackageId` entries are activated.\n    pub fn insert(&mut self, dep: &Dependency, con: &ConflictMap) {\n        self.con_from_dep\n            .entry(dep.clone())\n            .or_insert_with(|| ConflictStoreTrie::Node(BTreeMap::new()))\n            .insert(con.keys().cloned(), con.clone());\n\n        trace!(\n            \"{} = \\\"{}\\\" adding a skip {:?}\",\n            dep.package_name(),\n            dep.version_req(),\n            con\n        );\n\n        for c in con.keys() {\n            self.dep_from_pid.entry(*c).or_default().insert(dep.clone());\n        }\n    }\n\n    pub fn dependencies_conflicting_with(&self, pid: PackageId) -> Option<&FxHashSet<Dependency>> {\n        self.dep_from_pid.get(&pid)\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/resolver/context.rs",
    "content": "use super::RequestedFeatures;\nuse super::dep_cache::RegistryQueryer;\nuse super::errors::ActivateResult;\nuse super::types::{ActivationsKey, ConflictMap, ConflictReason, FeaturesSet, ResolveOpts};\nuse crate::core::{Dependency, PackageId, Registry, Summary};\nuse crate::util::Graph;\nuse crate::util::interning::{INTERNED_DEFAULT, InternedString};\nuse anyhow::format_err;\nuse std::collections::{BTreeSet, HashMap};\nuse tracing::debug;\n\n// A `Context` is basically a bunch of local resolution information which is\n// kept around for all `BacktrackFrame` instances. As a result, this runs the\n// risk of being cloned *a lot* so we want to make this as cheap to clone as\n// possible.\n#[derive(Clone)]\npub struct ResolverContext {\n    pub age: ContextAge,\n    pub activations: Activations,\n    /// list the features that are activated for each package\n    pub resolve_features: im_rc::HashMap<PackageId, FeaturesSet, rustc_hash::FxBuildHasher>,\n    /// get the package that will be linking to a native library by its links attribute\n    pub links: im_rc::HashMap<InternedString, PackageId, rustc_hash::FxBuildHasher>,\n\n    /// a way to look up for a package in activations what packages required it\n    /// and all of the exact deps that it fulfilled.\n    pub parents: Graph<PackageId, im_rc::HashSet<Dependency, rustc_hash::FxBuildHasher>>,\n}\n\n/// When backtracking it can be useful to know how far back to go.\n/// The `ContextAge` of a `Context` is a monotonically increasing counter of the number\n/// of decisions made to get to this state.\n/// Several structures store the `ContextAge` when it was added,\n/// to be used in `find_candidate` for backtracking.\npub type ContextAge = usize;\n\n/// Find the activated version of a crate based on the name, source, and semver compatibility.\n/// By storing this in a hash map we ensure that there is only one\n/// semver compatible version of each crate.\n/// This all so stores the `ContextAge`.\npub type Activations =\n    im_rc::HashMap<ActivationsKey, (Summary, ContextAge), rustc_hash::FxBuildHasher>;\n\nimpl ResolverContext {\n    pub fn new() -> ResolverContext {\n        ResolverContext {\n            age: 0,\n            resolve_features: im_rc::HashMap::default(),\n            links: im_rc::HashMap::default(),\n            parents: Graph::new(),\n            activations: im_rc::HashMap::default(),\n        }\n    }\n\n    /// Activate this summary by inserting it into our list of known activations.\n    ///\n    /// The `parent` passed in here is the parent summary/dependency edge which\n    /// cased `summary` to get activated. This may not be present for the root\n    /// crate, for example.\n    ///\n    /// Returns `true` if this summary with the given features is already activated.\n    pub fn flag_activated(\n        &mut self,\n        summary: &Summary,\n        opts: &ResolveOpts,\n        parent: Option<(&Summary, &Dependency)>,\n    ) -> ActivateResult<bool> {\n        let id = summary.package_id();\n        let age: ContextAge = self.age;\n        match self.activations.entry(id.as_activations_key()) {\n            im_rc::hashmap::Entry::Occupied(o) => {\n                debug_assert_eq!(\n                    &o.get().0,\n                    summary,\n                    \"cargo does not allow two semver compatible versions\"\n                );\n            }\n            im_rc::hashmap::Entry::Vacant(v) => {\n                if let Some(link) = summary.links() {\n                    if self.links.insert(link, id).is_some() {\n                        return Err(format_err!(\n                            \"Attempting to resolve a dependency with more than \\\n                             one crate with links={}.\\nThis will not build as \\\n                             is. Consider rebuilding the .lock file.\",\n                            &*link\n                        )\n                        .into());\n                    }\n                }\n                v.insert((summary.clone(), age));\n\n                // If we've got a parent dependency which activated us, *and*\n                // the dependency has a different source id listed than the\n                // `summary` itself, then things get interesting. This basically\n                // means that a `[patch]` was used to augment `dep.source_id()`\n                // with `summary`.\n                //\n                // In this scenario we want to consider the activation key, as\n                // viewed from the perspective of `dep.source_id()`, as being\n                // fulfilled. This means that we need to add a second entry in\n                // the activations map for the source that was patched, in\n                // addition to the source of the actual `summary` itself.\n                //\n                // Without this it would be possible to have both 1.0.0 and\n                // 1.1.0 \"from crates.io\" in a dependency graph if one of those\n                // versions came from a `[patch]` source.\n                if let Some((_, dep)) = parent {\n                    if dep.source_id() != id.source_id() {\n                        let key =\n                            ActivationsKey::new(id.name(), id.version().into(), dep.source_id());\n                        let prev = self.activations.insert(key, (summary.clone(), age));\n                        if let Some((previous_summary, _)) = prev {\n                            return Err(\n                                (previous_summary.package_id(), ConflictReason::Semver).into()\n                            );\n                        }\n                    }\n                }\n\n                return Ok(false);\n            }\n        }\n        debug!(\"checking if {} is already activated\", summary.package_id());\n        let empty_features = BTreeSet::new();\n        match &opts.features {\n            // This returns `false` for CliFeatures just for simplicity. It\n            // would take a bit of work to compare since they are not in the\n            // same format as DepFeatures (and that may be expensive\n            // performance-wise). Also, it should only occur once for a root\n            // package. The only drawback is that it may re-activate a root\n            // package again, which should only affect performance, but that\n            // should be rare. Cycles should still be detected since those\n            // will have `DepFeatures` edges.\n            RequestedFeatures::CliFeatures(_) => Ok(false),\n            RequestedFeatures::DepFeatures {\n                features,\n                uses_default_features,\n            } => {\n                let has_default_feature = summary.features().contains_key(&INTERNED_DEFAULT);\n                let prev = self\n                    .resolve_features\n                    .get(&id)\n                    .map(|f| &**f)\n                    .unwrap_or(&empty_features);\n                Ok(features.is_subset(prev)\n                    && (!uses_default_features\n                        || prev.contains(&INTERNED_DEFAULT)\n                        || !has_default_feature))\n            }\n        }\n    }\n\n    /// If the package is active returns the `ContextAge` when it was added\n    pub fn is_active(&self, id: PackageId) -> Option<ContextAge> {\n        self.activations\n            .get(&id.as_activations_key())\n            .and_then(|(s, l)| if s.package_id() == id { Some(*l) } else { None })\n    }\n\n    /// Checks whether all of `parent` and the keys of `conflicting activations`\n    /// are still active.\n    /// If so returns the `ContextAge` when the newest one was added.\n    pub fn is_conflicting(\n        &self,\n        parent: Option<PackageId>,\n        conflicting_activations: &ConflictMap,\n    ) -> Option<usize> {\n        let mut max = 0;\n        if let Some(parent) = parent {\n            max = std::cmp::max(max, self.is_active(parent)?);\n        }\n\n        for id in conflicting_activations.keys() {\n            max = std::cmp::max(max, self.is_active(*id)?);\n        }\n        Some(max)\n    }\n\n    pub fn resolve_replacements(\n        &self,\n        registry: &RegistryQueryer<'_, impl Registry>,\n    ) -> HashMap<PackageId, PackageId> {\n        self.activations\n            .values()\n            .filter_map(|(s, _)| registry.used_replacement_for(s.package_id()))\n            .collect()\n    }\n\n    pub fn graph(&self) -> Graph<PackageId, std::collections::HashSet<Dependency>> {\n        let mut graph: Graph<PackageId, std::collections::HashSet<Dependency>> = Graph::new();\n        self.activations\n            .values()\n            .for_each(|(r, _)| graph.add(r.package_id()));\n        for i in self.parents.iter() {\n            graph.add(*i);\n            for (o, e) in self.parents.edges(i) {\n                let old_link = graph.link(*o, *i);\n                assert!(old_link.is_empty());\n                *old_link = e.iter().cloned().collect();\n            }\n        }\n        graph\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/resolver/dep_cache.rs",
    "content": "//! There are 2 sources of facts for the resolver:\n//!\n//! - The `Registry` tells us for a `Dependency` what versions are available to fulfil it.\n//! - The `Summary` tells us for a version (and features) what dependencies need to be fulfilled for it to be activated.\n//!\n//! These constitute immutable facts, the soled ground truth that all other inference depends on.\n//! Theoretically this could all be enumerated ahead of time, but we want to be lazy and only\n//! look up things we need to. The compromise is to cache the results as they are computed.\n//!\n//! This module impl that cache in all the gory details\n\nuse crate::core::resolver::context::ResolverContext;\nuse crate::core::resolver::errors::describe_path_in_context;\nuse crate::core::resolver::types::{ConflictReason, DepInfo, FeaturesSet};\nuse crate::core::resolver::{\n    ActivateError, ActivateResult, CliFeatures, RequestedFeatures, ResolveOpts, VersionOrdering,\n    VersionPreferences,\n};\nuse crate::core::{\n    Dependency, FeatureValue, PackageId, PackageIdSpec, PackageIdSpecQuery, Registry, Summary,\n};\nuse crate::sources::source::QueryKind;\nuse crate::util::closest_msg;\nuse crate::util::errors::CargoResult;\nuse crate::util::interning::{INTERNED_DEFAULT, InternedString};\n\nuse anyhow::Context as _;\nuse std::collections::{BTreeSet, HashMap, HashSet};\nuse std::fmt::Write;\nuse std::rc::Rc;\nuse std::task::Poll;\nuse tracing::debug;\n\npub struct RegistryQueryer<'a, T: Registry> {\n    pub registry: &'a mut T,\n    replacements: &'a [(PackageIdSpec, Dependency)],\n    version_prefs: &'a VersionPreferences,\n    /// a cache of `Candidate`s that fulfil a `Dependency` (and whether `first_version`)\n    registry_cache: HashMap<(Dependency, Option<VersionOrdering>), Poll<Rc<Vec<Summary>>>>,\n    /// a cache of `Dependency`s that are required for a `Summary`\n    ///\n    /// HACK: `first_version` is not kept in the cache key is it is 1:1 with\n    /// `parent.is_none()` (the first element of the cache key) as it doesn't change through\n    /// execution.\n    summary_cache: HashMap<\n        (Option<PackageId>, Summary, ResolveOpts),\n        (Rc<(HashSet<InternedString>, Rc<Vec<DepInfo>>)>, bool),\n    >,\n    /// all the cases we ended up using a supplied replacement\n    used_replacements: HashMap<PackageId, Summary>,\n}\n\nimpl<'a, T: Registry> RegistryQueryer<'a, T> {\n    pub fn new(\n        registry: &'a mut T,\n        replacements: &'a [(PackageIdSpec, Dependency)],\n        version_prefs: &'a VersionPreferences,\n    ) -> Self {\n        RegistryQueryer {\n            registry,\n            replacements,\n            version_prefs,\n            registry_cache: HashMap::new(),\n            summary_cache: HashMap::new(),\n            used_replacements: HashMap::new(),\n        }\n    }\n\n    pub fn reset_pending(&mut self) -> bool {\n        let mut all_ready = true;\n        self.registry_cache.retain(|_, r| {\n            if !r.is_ready() {\n                all_ready = false;\n            }\n            r.is_ready()\n        });\n        self.summary_cache.retain(|_, (_, r)| {\n            if !*r {\n                all_ready = false;\n            }\n            *r\n        });\n        all_ready\n    }\n\n    pub fn used_replacement_for(&self, p: PackageId) -> Option<(PackageId, PackageId)> {\n        self.used_replacements.get(&p).map(|r| (p, r.package_id()))\n    }\n\n    pub fn replacement_summary(&self, p: PackageId) -> Option<&Summary> {\n        self.used_replacements.get(&p)\n    }\n\n    /// Queries the `registry` to return a list of candidates for `dep`.\n    ///\n    /// This method is the location where overrides are taken into account. If\n    /// any candidates are returned which match an override then the override is\n    /// applied by performing a second query for what the override should\n    /// return.\n    pub fn query(\n        &mut self,\n        dep: &Dependency,\n        first_version: Option<VersionOrdering>,\n    ) -> Poll<CargoResult<Rc<Vec<Summary>>>> {\n        let registry_cache_key = (dep.clone(), first_version);\n        if let Some(out) = self.registry_cache.get(&registry_cache_key).cloned() {\n            return out.map(Result::Ok);\n        }\n\n        let mut ret = Vec::new();\n        let ready = self.registry.query(dep, QueryKind::Exact, &mut |s| {\n            ret.push(s.into_summary());\n        })?;\n        if ready.is_pending() {\n            self.registry_cache\n                .insert((dep.clone(), first_version), Poll::Pending);\n            return Poll::Pending;\n        }\n        for summary in ret.iter() {\n            let mut potential_matches = self\n                .replacements\n                .iter()\n                .filter(|(spec, _)| spec.matches(summary.package_id()));\n\n            let Some((spec, dep)) = potential_matches.next() else {\n                continue;\n            };\n            debug!(\n                \"found an override for {} {}\",\n                dep.package_name(),\n                dep.version_req()\n            );\n\n            let mut summaries = match self.registry.query_vec(dep, QueryKind::Exact)? {\n                Poll::Ready(s) => s.into_iter(),\n                Poll::Pending => {\n                    self.registry_cache\n                        .insert((dep.clone(), first_version), Poll::Pending);\n                    return Poll::Pending;\n                }\n            };\n            let s = summaries\n                .next()\n                .ok_or_else(|| {\n                    anyhow::format_err!(\n                        \"no matching package for override `{}` found\\n\\\n                     location searched: {}\\n\\\n                     version required: {}\",\n                        spec,\n                        dep.source_id(),\n                        dep.version_req()\n                    )\n                })?\n                .into_summary();\n            let summaries = summaries.collect::<Vec<_>>();\n            if !summaries.is_empty() {\n                let bullets = summaries\n                    .iter()\n                    .map(|s| format!(\"  * {}\", s.package_id()))\n                    .collect::<Vec<_>>();\n                return Poll::Ready(Err(anyhow::anyhow!(\n                    \"the replacement specification `{}` matched \\\n                     multiple packages:\\n  * {}\\n{}\",\n                    spec,\n                    s.package_id(),\n                    bullets.join(\"\\n\")\n                )));\n            }\n\n            assert_eq!(\n                s.name(),\n                summary.name(),\n                \"dependency should be hard coded to have the same name\"\n            );\n            if s.version() != summary.version() {\n                return Poll::Ready(Err(anyhow::anyhow!(\n                    \"replacement specification `{}` matched {} and tried to override it with {}\\n\\\n                     avoid matching unrelated packages by being more specific\",\n                    spec,\n                    summary.version(),\n                    s.version(),\n                )));\n            }\n\n            let replace = if s.source_id() == summary.source_id() {\n                debug!(\"Preventing\\n{:?}\\nfrom replacing\\n{:?}\", summary, s);\n                None\n            } else {\n                Some(s)\n            };\n            let matched_spec = spec.clone();\n\n            // Make sure no duplicates\n            if let Some((spec, _)) = potential_matches.next() {\n                return Poll::Ready(Err(anyhow::anyhow!(\n                    \"overlapping replacement specifications found:\\n\\n  \\\n                     * {}\\n  * {}\\n\\nboth specifications match: {}\",\n                    matched_spec,\n                    spec,\n                    summary.package_id()\n                )));\n            }\n\n            for dep in summary.dependencies() {\n                debug!(\"\\t{} => {}\", dep.package_name(), dep.version_req());\n            }\n            if let Some(r) = replace {\n                self.used_replacements.insert(summary.package_id(), r);\n            }\n        }\n\n        self.version_prefs.sort_summaries(&mut ret, first_version);\n\n        let out = Poll::Ready(Rc::new(ret));\n\n        self.registry_cache.insert(registry_cache_key, out.clone());\n\n        out.map(Result::Ok)\n    }\n\n    /// Find out what dependencies will be added by activating `candidate`,\n    /// with features described in `opts`. Then look up in the `registry`\n    /// the candidates that will fulfil each of these dependencies, as it is the\n    /// next obvious question.\n    pub fn build_deps(\n        &mut self,\n        cx: &ResolverContext,\n        parent: Option<PackageId>,\n        candidate: &Summary,\n        opts: &ResolveOpts,\n        first_version: Option<VersionOrdering>,\n    ) -> ActivateResult<Rc<(HashSet<InternedString>, Rc<Vec<DepInfo>>)>> {\n        // if we have calculated a result before, then we can just return it,\n        // as it is a \"pure\" query of its arguments.\n        if let Some(out) = self\n            .summary_cache\n            .get(&(parent, candidate.clone(), opts.clone()))\n        {\n            return Ok(out.0.clone());\n        }\n        // First, figure out our set of dependencies based on the requested set\n        // of features. This also calculates what features we're going to enable\n        // for our own dependencies.\n        let (used_features, deps) = resolve_features(parent, candidate, opts)?;\n\n        // Next, transform all dependencies into a list of possible candidates\n        // which can satisfy that dependency.\n        let mut all_ready = true;\n        let mut deps = deps\n            .into_iter()\n            .filter_map(|(dep, features)| match self.query(&dep, first_version) {\n                Poll::Ready(Ok(candidates)) => Some(Ok((dep, candidates, features))),\n                Poll::Pending => {\n                    all_ready = false;\n                    // we can ignore Pending deps, resolve will be repeatedly called\n                    // until there are none to ignore\n                    None\n                }\n                Poll::Ready(Err(e)) => Some(Err(e).with_context(|| {\n                    format!(\n                        \"failed to get `{}` as a dependency of {}\",\n                        dep.package_name(),\n                        describe_path_in_context(cx, &candidate.package_id()),\n                    )\n                })),\n            })\n            .collect::<CargoResult<Vec<DepInfo>>>()?;\n\n        // Attempt to resolve dependencies with fewer candidates before trying\n        // dependencies with more candidates. This way if the dependency with\n        // only one candidate can't be resolved we don't have to do a bunch of\n        // work before we figure that out.\n        deps.sort_by_key(|(_, a, _)| a.len());\n\n        let out = Rc::new((used_features, Rc::new(deps)));\n\n        // If we succeed we add the result to the cache so we can use it again next time.\n        // We don't cache the failure cases as they don't impl Clone.\n        self.summary_cache.insert(\n            (parent, candidate.clone(), opts.clone()),\n            (out.clone(), all_ready),\n        );\n\n        Ok(out)\n    }\n}\n\n/// Returns the features we ended up using and\n/// all dependencies and the features we want from each of them.\npub fn resolve_features<'b>(\n    parent: Option<PackageId>,\n    s: &'b Summary,\n    opts: &'b ResolveOpts,\n) -> ActivateResult<(HashSet<InternedString>, Vec<(Dependency, FeaturesSet)>)> {\n    // First, filter by dev-dependencies.\n    let deps = s.dependencies();\n    let deps = deps.iter().filter(|d| d.is_transitive() || opts.dev_deps);\n\n    let reqs = build_requirements(parent, s, opts)?;\n    let mut ret = Vec::new();\n    let default_dep = BTreeSet::new();\n    let mut valid_dep_names = HashSet::new();\n\n    // Next, collect all actually enabled dependencies and their features.\n    for dep in deps {\n        // Skip optional dependencies, but not those enabled through a\n        // feature\n        if dep.is_optional() && !reqs.deps.contains_key(&dep.name_in_toml()) {\n            continue;\n        }\n        valid_dep_names.insert(dep.name_in_toml());\n        // So we want this dependency. Move the features we want from\n        // `feature_deps` to `ret` and register ourselves as using this\n        // name.\n        let mut base = reqs\n            .deps\n            .get(&dep.name_in_toml())\n            .unwrap_or(&default_dep)\n            .clone();\n        base.extend(dep.features().iter());\n        ret.push((dep.clone(), Rc::new(base)));\n    }\n\n    // This is a special case for command-line `--features\n    // dep_name/feat_name` where `dep_name` does not exist. All other\n    // validation is done either in `build_requirements` or\n    // `build_feature_map`.\n    if parent.is_none() {\n        for dep_name in reqs.deps.keys() {\n            if !valid_dep_names.contains(dep_name) {\n                let e = RequirementError::MissingDependency(*dep_name);\n                return Err(e.into_activate_error(parent, s));\n            }\n        }\n    }\n\n    Ok((reqs.into_features(), ret))\n}\n\n/// Takes requested features for a single package from the input `ResolveOpts` and\n/// recurses to find all requested features, dependencies and requested\n/// dependency features in a `Requirements` object, returning it to the resolver.\nfn build_requirements<'a, 'b: 'a>(\n    parent: Option<PackageId>,\n    s: &'a Summary,\n    opts: &'b ResolveOpts,\n) -> ActivateResult<Requirements<'a>> {\n    let mut reqs = Requirements::new(s);\n\n    let handle_default = |uses_default_features, reqs: &mut Requirements<'_>| {\n        if uses_default_features && s.features().contains_key(\"default\") {\n            if let Err(e) = reqs.require_feature(INTERNED_DEFAULT) {\n                return Err(e.into_activate_error(parent, s));\n            }\n        }\n        Ok(())\n    };\n\n    match &opts.features {\n        RequestedFeatures::CliFeatures(CliFeatures {\n            features,\n            all_features,\n            uses_default_features,\n        }) => {\n            if *all_features {\n                for key in s.features().keys() {\n                    if let Err(e) = reqs.require_feature(*key) {\n                        return Err(e.into_activate_error(parent, s));\n                    }\n                }\n            }\n\n            for fv in features.iter() {\n                if let Err(e) = reqs.require_value(fv) {\n                    return Err(e.into_activate_error(parent, s));\n                }\n            }\n            handle_default(*uses_default_features, &mut reqs)?;\n        }\n        RequestedFeatures::DepFeatures {\n            features,\n            uses_default_features,\n        } => {\n            for feature in features.iter() {\n                if let Err(e) = reqs.require_feature(*feature) {\n                    return Err(e.into_activate_error(parent, s));\n                }\n            }\n            handle_default(*uses_default_features, &mut reqs)?;\n        }\n    }\n\n    Ok(reqs)\n}\n\n/// Set of feature and dependency requirements for a package.\n#[derive(Debug)]\nstruct Requirements<'a> {\n    summary: &'a Summary,\n    /// The deps map is a mapping of dependency name to list of features enabled.\n    ///\n    /// The resolver will activate all of these dependencies, with the given\n    /// features enabled.\n    deps: HashMap<InternedString, BTreeSet<InternedString>>,\n    /// The set of features enabled on this package which is later used when\n    /// compiling to instruct the code what features were enabled.\n    features: HashSet<InternedString>,\n}\n\n/// An error for a requirement.\n///\n/// This will later be converted to an `ActivateError` depending on whether or\n/// not this is a dependency or a root package.\nenum RequirementError {\n    /// The package does not have the requested feature.\n    MissingFeature(InternedString),\n    /// The package does not have the requested dependency.\n    MissingDependency(InternedString),\n    /// A feature has a direct cycle to itself.\n    ///\n    /// Note that cycles through multiple features are allowed (but perhaps\n    /// they shouldn't be?).\n    Cycle(InternedString),\n}\n\nimpl Requirements<'_> {\n    fn new(summary: &Summary) -> Requirements<'_> {\n        Requirements {\n            summary,\n            deps: HashMap::new(),\n            features: HashSet::new(),\n        }\n    }\n\n    fn into_features(self) -> HashSet<InternedString> {\n        self.features\n    }\n\n    fn require_dep_feature(\n        &mut self,\n        package: InternedString,\n        feat: InternedString,\n        weak: bool,\n    ) -> Result<(), RequirementError> {\n        // If `package` is indeed an optional dependency then we activate the\n        // feature named `package`, but otherwise if `package` is a required\n        // dependency then there's no feature associated with it.\n        if !weak\n            && self\n                .summary\n                .dependencies()\n                .iter()\n                .any(|dep| dep.name_in_toml() == package && dep.is_optional())\n        {\n            // This optional dependency may not have an implicit feature of\n            // the same name if the `dep:` syntax is used to avoid creating\n            // that implicit feature.\n            if self.summary.features().contains_key(&package) {\n                self.require_feature(package)?;\n            }\n        }\n        self.deps.entry(package).or_default().insert(feat);\n        Ok(())\n    }\n\n    fn require_dependency(&mut self, pkg: InternedString) {\n        self.deps.entry(pkg).or_default();\n    }\n\n    fn require_feature(&mut self, feat: InternedString) -> Result<(), RequirementError> {\n        if !self.features.insert(feat) {\n            // Already seen this feature.\n            return Ok(());\n        }\n\n        let Some(fvs) = self.summary.features().get(&feat) else {\n            return Err(RequirementError::MissingFeature(feat));\n        };\n\n        for fv in fvs {\n            if let FeatureValue::Feature(dep_feat) = fv {\n                if *dep_feat == feat {\n                    return Err(RequirementError::Cycle(feat));\n                }\n            }\n            self.require_value(fv)?;\n        }\n        Ok(())\n    }\n\n    fn require_value(&mut self, fv: &FeatureValue) -> Result<(), RequirementError> {\n        match fv {\n            FeatureValue::Feature(feat) => self.require_feature(*feat)?,\n            FeatureValue::Dep { dep_name } => self.require_dependency(*dep_name),\n            FeatureValue::DepFeature {\n                dep_name,\n                dep_feature,\n                // Weak features are always activated in the dependency\n                // resolver. They will be narrowed inside the new feature\n                // resolver.\n                weak,\n            } => self.require_dep_feature(*dep_name, *dep_feature, *weak)?,\n        };\n        Ok(())\n    }\n}\n\nimpl RequirementError {\n    fn into_activate_error(self, parent: Option<PackageId>, summary: &Summary) -> ActivateError {\n        match self {\n            RequirementError::MissingFeature(feat) => {\n                let deps: Vec<_> = summary\n                    .dependencies()\n                    .iter()\n                    .filter(|dep| dep.name_in_toml() == feat)\n                    .collect();\n                if deps.is_empty() {\n                    return match parent {\n                        None => {\n                            let closest = closest_msg(\n                                &feat.as_str(),\n                                summary.features().keys(),\n                                |key| &key,\n                                \"feature\",\n                            );\n                            ActivateError::Fatal(anyhow::format_err!(\n                                \"package `{}` does not have the feature `{}`{}\",\n                                summary.package_id(),\n                                feat,\n                                closest\n                            ))\n                        }\n                        Some(p) => ActivateError::Conflict(p, ConflictReason::MissingFeature(feat)),\n                    };\n                }\n                if deps.iter().any(|dep| dep.is_optional()) {\n                    match parent {\n                        None => {\n                            let mut features =\n                                features_enabling_dependency_sorted(summary, feat).peekable();\n                            let mut suggestion = String::new();\n                            if features.peek().is_some() {\n                                suggestion = format!(\n                                    \"\\nDependency `{}` would be enabled by these features:\",\n                                    feat\n                                );\n                                for feature in (&mut features).take(3) {\n                                    let _ = write!(&mut suggestion, \"\\n\\t- `{}`\", feature);\n                                }\n                                if features.peek().is_some() {\n                                    suggestion.push_str(\"\\n\\t  ...\");\n                                }\n                            }\n                            ActivateError::Fatal(anyhow::format_err!(\n                                \"\\\npackage `{}` does not have feature `{}`\n\nhelp: an optional dependency \\\nwith that name exists, but the `features` table includes it with the \\\"dep:\\\" \\\nsyntax so it does not have an implicit feature with that name{}\",\n                                summary.package_id(),\n                                feat,\n                                suggestion\n                            ))\n                        }\n                        Some(p) => ActivateError::Conflict(\n                            p,\n                            ConflictReason::NonImplicitDependencyAsFeature(feat),\n                        ),\n                    }\n                } else {\n                    match parent {\n                        None => ActivateError::Fatal(anyhow::format_err!(\n                            \"package `{}` does not have feature `{}`\n\nhelp: a dependency with that name exists but it is required dependency and only optional dependencies can be used as features.\",\n                            summary.package_id(),\n                            feat,\n                        )),\n                        Some(p) => ActivateError::Conflict(\n                            p,\n                            ConflictReason::RequiredDependencyAsFeature(feat),\n                        ),\n                    }\n                }\n            }\n            RequirementError::MissingDependency(dep_name) => {\n                match parent {\n                    None => ActivateError::Fatal(anyhow::format_err!(\n                        \"package `{}` does not have a dependency named `{}`\",\n                        summary.package_id(),\n                        dep_name\n                    )),\n                    // This code path currently isn't used, since `foo/bar`\n                    // and `dep:` syntax is not allowed in a dependency.\n                    Some(p) => ActivateError::Conflict(p, ConflictReason::MissingFeature(dep_name)),\n                }\n            }\n            RequirementError::Cycle(feat) => ActivateError::Fatal(anyhow::format_err!(\n                \"cyclic feature dependency: feature `{}` depends on itself\",\n                feat\n            )),\n        }\n    }\n}\n\n/// Collect any features which enable the optional dependency \"target_dep\".\n///\n/// The returned value will be sorted.\nfn features_enabling_dependency_sorted(\n    summary: &Summary,\n    target_dep: InternedString,\n) -> impl Iterator<Item = InternedString> + '_ {\n    let iter = summary\n        .features()\n        .iter()\n        .filter(move |(_, values)| {\n            for value in *values {\n                match value {\n                    FeatureValue::Dep { dep_name }\n                    | FeatureValue::DepFeature {\n                        dep_name,\n                        weak: false,\n                        ..\n                    } if dep_name == &target_dep => return true,\n                    _ => (),\n                }\n            }\n            false\n        })\n        .map(|(name, _)| *name);\n    // iter is already sorted because it was constructed from a BTreeMap.\n    iter\n}\n"
  },
  {
    "path": "src/cargo/core/resolver/encode.rs",
    "content": "//! Definition of how to encode a `Resolve` into a TOML `Cargo.lock` file\n//!\n//! This module contains all machinery necessary to parse a `Resolve` from a\n//! `Cargo.lock` as well as serialize a `Resolve` to a `Cargo.lock`.\n//!\n//! ## Changing `Cargo.lock`\n//!\n//! In general Cargo is quite conservative about changing the format of\n//! `Cargo.lock`. Usage of new features in Cargo can change `Cargo.lock` at any\n//! time, but otherwise changing the serialization of `Cargo.lock` is a\n//! difficult operation to do that we typically avoid.\n//!\n//! The main problem with changing the format of `Cargo.lock` is that it can\n//! cause quite a bad experience for end users who use different versions of\n//! Cargo. If every PR to a project oscillates between the stable channel's\n//! encoding of Cargo.lock and the nightly channel's encoding then that's a\n//! pretty bad experience.\n//!\n//! We do, however, want to change `Cargo.lock` over time. (and we have!). To do\n//! this the rules that we currently have are:\n//!\n//! * Add support for the new format to Cargo. This involves code changes in\n//!   Cargo itself, likely by adding a new variant of `ResolveVersion` and\n//!   branching on that where necessary. This is accompanied with tests in the\n//!   `lockfile_compat` module.\n//!\n//!   * Do not update `ResolveVersion::default()`. The new lockfile format will\n//!     not be used yet.\n//!\n//!   * Preserve the new format if found. This means that if Cargo finds the new\n//!     version it'll keep using it, but otherwise it continues to use whatever\n//!     format it previously found.\n//!\n//! * Wait a \"long time\". This is at least until the changes here hit stable\n//!   Rust. Often though we wait a little longer to let the changes percolate\n//!   into one or two older stable releases.\n//!\n//! * Change the return value of `ResolveVersion::default()` to the new format.\n//!   This will cause new lock files to use the latest encoding as well as\n//!   causing any operation which updates the lock file to update to the new\n//!   format.\n//!\n//! This migration scheme in general means that Cargo we'll get *support* for a\n//! new format into Cargo ASAP, but it won't be exercised yet (except in Cargo's\n//! own tests). Eventually when stable/beta/nightly all have support for the new\n//! format (and maybe a few previous stable versions) we flip the switch.\n//! Projects on nightly will quickly start seeing changes, but\n//! stable/beta/nightly will all understand this new format and will preserve\n//! it.\n//!\n//! While this does mean that projects' `Cargo.lock` changes over time, it's\n//! typically a pretty minimal effort change that's just \"check in what's\n//! there\".\n//!\n//! ## Historical changes to `Cargo.lock`\n//!\n//! Listed from most recent to oldest, these are some of the changes we've made\n//! to `Cargo.lock`'s serialization format:\n//!\n//! * A `version` marker is now at the top of the lock file which is a way for\n//!   super-old Cargos (at least since this was implemented) to give a formal\n//!   error if they see a lock file from a super-future Cargo. Additionally as\n//!   part of this change the encoding of `git` dependencies in lock files\n//!   changed where `branch = \"master\"` is now encoded with `branch=master`\n//!   instead of with nothing at all.\n//!\n//! * The entries in `dependencies` arrays have been shortened and the\n//!   `checksum` field now shows up directly in `[[package]]` instead of always\n//!   at the end of the file. The goal of this change was to ideally reduce\n//!   merge conflicts being generated on `Cargo.lock`. Updating a version of a\n//!   package now only updates two lines in the file, the checksum and the\n//!   version number, most of the time. Dependency edges are specified in a\n//!   compact form where possible where just the name is listed. The\n//!   version/source on dependency edges are only listed if necessary to\n//!   disambiguate which version or which source is in use.\n//!\n//! * A comment at the top of the file indicates that the file is a generated\n//!   file and contains the special symbol `@generated` to indicate to common\n//!   review tools that it's a generated file.\n//!\n//! * A `[root]` entry for the \"root crate\" has been removed and instead now\n//!   included in `[[package]]` like everything else.\n//!\n//! * All packages from registries contain a `checksum` which is a sha256\n//!   checksum of the tarball the package is associated with. This is all stored\n//!   in the `[metadata]` table of `Cargo.lock` which all versions of Cargo\n//!   since 1.0 have preserved. The goal of this was to start recording\n//!   checksums so mirror sources can be verified.\n//!\n//! ## Other oddities about `Cargo.lock`\n//!\n//! There's a few other miscellaneous weird things about `Cargo.lock` that you\n//! may want to be aware of when reading this file:\n//!\n//! * All packages have a `source` listed to indicate where they come from. For\n//!   `path` dependencies, however, no `source` is listed. There's no way we\n//!   could emit a filesystem path name and have that be portable across\n//!   systems, so all packages from a `path` are not listed with a `source`.\n//!   Note that this also means that all packages with `path` sources must have\n//!   unique names.\n//!\n//! * The `[metadata]` table in `Cargo.lock` is intended to be a generic mapping\n//!   of strings to strings that's simply preserved by Cargo. This was a very\n//!   early effort to be forward compatible against changes to `Cargo.lock`'s\n//!   format. This is nowadays sort of deemed a bad idea though and we don't\n//!   really use it that much except for `checksum`s historically. It's not\n//!   really recommended to use this.\n//!\n//! * The actual literal on-disk serialization is found in\n//!   `src/cargo/ops/lockfile.rs` which basically renders a `toml::Value` in a\n//!   special fashion to make sure we have strict control over the on-disk\n//!   format.\n\nuse super::{Resolve, ResolveVersion};\nuse crate::core::{Dependency, GitReference, Package, PackageId, Patch, SourceId, Workspace};\nuse crate::util::errors::CargoResult;\nuse crate::util::interning::InternedString;\nuse crate::util::{Graph, internal};\nuse anyhow::{Context as _, bail};\nuse cargo_util_schemas::lockfile::{\n    TomlLockfile, TomlLockfileDependency, TomlLockfilePackageId, TomlLockfilePatch,\n    TomlLockfileSourceId,\n};\nuse serde::ser;\nuse std::collections::{HashMap, HashSet};\nuse tracing::debug;\n\n/// Convert a `Cargo.lock` to a Resolve.\n///\n/// Note that this `Resolve` is not \"complete\". For example, the\n/// dependencies do not know the difference between regular/dev/build\n/// dependencies, so they are not filled in. It also does not include\n/// `features`. Care should be taken when using this Resolve. One of the\n/// primary uses is to be used with `resolve_with_previous` to guide the\n/// resolver to create a complete Resolve.\npub fn into_resolve(\n    resolve: TomlLockfile,\n    original: &str,\n    ws: &Workspace<'_>,\n) -> CargoResult<Resolve> {\n    let path_deps: HashMap<String, HashMap<semver::Version, SourceId>> = build_path_deps(ws)?;\n    let mut checksums = HashMap::new();\n\n    let mut version = match resolve.version {\n        Some(n @ 5) if ws.gctx().nightly_features_allowed => {\n            if ws.gctx().cli_unstable().next_lockfile_bump {\n                ResolveVersion::V5\n            } else {\n                anyhow::bail!(\"lock file version `{n}` requires `-Znext-lockfile-bump`\");\n            }\n        }\n        Some(4) => ResolveVersion::V4,\n        Some(3) => ResolveVersion::V3,\n        Some(n) => bail!(\n            \"lock file version `{}` was found, but this version of Cargo \\\n             does not understand this lock file, perhaps Cargo needs \\\n             to be updated?\",\n            n,\n        ),\n        // Historically Cargo did not have a version indicator in lock\n        // files, so this could either be the V1 or V2 encoding. We assume\n        // an older format is being parsed until we see so otherwise.\n        None => ResolveVersion::V1,\n    };\n\n    let packages = {\n        let mut packages = resolve.package.unwrap_or_default();\n        if let Some(root) = resolve.root {\n            packages.insert(0, root);\n        }\n        packages\n    };\n\n    // `PackageId`s in the lock file don't include the `source` part\n    // for workspace members, so we reconstruct proper IDs.\n    let live_pkgs = {\n        let mut live_pkgs = HashMap::new();\n        let mut all_pkgs = HashSet::new();\n        for pkg in packages.iter() {\n            let enc_id = TomlLockfilePackageId {\n                name: pkg.name.clone(),\n                version: Some(pkg.version.clone()),\n                source: pkg.source.clone(),\n            };\n\n            if !all_pkgs.insert(enc_id.clone()) {\n                anyhow::bail!(\"package `{}` is specified twice in the lockfile\", pkg.name);\n            }\n            let id = match pkg\n                .source\n                .as_ref()\n                .map(|source| SourceId::from_url(&source.source_str()))\n                .transpose()?\n                .or_else(|| get_source_id(&path_deps, &pkg).copied())\n            {\n                // We failed to find a local package in the workspace.\n                // It must have been removed and should be ignored.\n                None => {\n                    debug!(\"path dependency now missing {} v{}\", pkg.name, pkg.version);\n                    continue;\n                }\n                Some(source) => PackageId::try_new(&pkg.name, &pkg.version, source)?,\n            };\n\n            // If a package has a checksum listed directly on it then record\n            // that here, and we also bump our version up to 2 since V1\n            // didn't ever encode this field.\n            if let Some(cksum) = &pkg.checksum {\n                version = version.max(ResolveVersion::V2);\n                checksums.insert(id, Some(cksum.clone()));\n            }\n\n            assert!(live_pkgs.insert(enc_id, (id, pkg)).is_none())\n        }\n        live_pkgs\n    };\n\n    // When decoding a V2 version the edges in `dependencies` aren't\n    // guaranteed to have either version or source information. This `map`\n    // is used to find package ids even if dependencies have missing\n    // information. This map is from name to version to source to actual\n    // package ID. (various levels to drill down step by step)\n    let mut map = HashMap::new();\n    for (id, _) in live_pkgs.values() {\n        map.entry(id.name().as_str())\n            .or_insert_with(HashMap::new)\n            .entry(id.version().to_string())\n            .or_insert_with(HashMap::new)\n            .insert(id.source_id(), *id);\n    }\n\n    let mut lookup_id = |enc_id: &TomlLockfilePackageId| -> Option<PackageId> {\n        // The name of this package should always be in the larger list of\n        // all packages.\n        let by_version = map.get(enc_id.name.as_str())?;\n\n        // If the version is provided, look that up. Otherwise if the\n        // version isn't provided this is a V2 manifest and we should only\n        // have one version for this name. If we have more than one version\n        // for the name then it's ambiguous which one we'd use. That\n        // shouldn't ever actually happen but in theory bad git merges could\n        // produce invalid lock files, so silently ignore these cases.\n        let by_source = match &enc_id.version {\n            Some(version) => by_version.get(version)?,\n            None => {\n                version = version.max(ResolveVersion::V2);\n                if by_version.len() == 1 {\n                    by_version.values().next().unwrap()\n                } else {\n                    return None;\n                }\n            }\n        };\n\n        // This is basically the same as above. Note though that `source` is\n        // always missing for path dependencies regardless of serialization\n        // format. That means we have to handle the `None` case a bit more\n        // carefully.\n        match &enc_id.source {\n            Some(source) => by_source\n                .get(&SourceId::from_url(&source.source_str()).unwrap())\n                .cloned(),\n            None => {\n                // Look through all possible packages ids for this\n                // name/version. If there's only one `path` dependency then\n                // we are hardcoded to use that since `path` dependencies\n                // can't have a source listed.\n                let mut path_packages = by_source.values().filter(|p| p.source_id().is_path());\n                if let Some(path) = path_packages.next() {\n                    if path_packages.next().is_some() {\n                        return None;\n                    }\n                    Some(*path)\n\n                // ... otherwise if there's only one then we must be\n                // implicitly using that one due to a V2 serialization of\n                // the lock file\n                } else if by_source.len() == 1 {\n                    let id = by_source.values().next().unwrap();\n                    version = version.max(ResolveVersion::V2);\n                    Some(*id)\n\n                // ... and failing that we probably had a bad git merge of\n                // `Cargo.lock` or something like that, so just ignore this.\n                } else {\n                    None\n                }\n            }\n        }\n    };\n\n    let mut g = Graph::new();\n\n    for (id, _) in live_pkgs.values() {\n        g.add(*id);\n    }\n\n    for &(ref id, pkg) in live_pkgs.values() {\n        let Some(ref deps) = pkg.dependencies else {\n            continue;\n        };\n\n        for edge in deps.iter() {\n            if let Some(to_depend_on) = lookup_id(edge) {\n                g.link(*id, to_depend_on);\n            }\n        }\n    }\n\n    let replacements = {\n        let mut replacements = HashMap::new();\n        for &(ref id, pkg) in live_pkgs.values() {\n            if let Some(ref replace) = pkg.replace {\n                assert!(pkg.dependencies.is_none());\n                if let Some(replace_id) = lookup_id(replace) {\n                    replacements.insert(*id, replace_id);\n                }\n            }\n        }\n        replacements\n    };\n\n    let mut metadata = resolve.metadata.unwrap_or_default();\n\n    // In the V1 serialization formats all checksums were listed in the lock\n    // file in the `[metadata]` section, so if we're still V1 then look for\n    // that here.\n    let prefix = \"checksum \";\n    let mut to_remove = Vec::new();\n    for (k, v) in metadata.iter().filter(|p| p.0.starts_with(prefix)) {\n        to_remove.push(k.to_string());\n        let k = k.strip_prefix(prefix).unwrap();\n        let enc_id: TomlLockfilePackageId = k\n            .parse()\n            .with_context(|| internal(\"invalid encoding of checksum in lockfile\"))?;\n        let Some(id) = lookup_id(&enc_id) else {\n            continue;\n        };\n\n        let v = if v == \"<none>\" {\n            None\n        } else {\n            Some(v.to_string())\n        };\n        checksums.insert(id, v);\n    }\n    // If `checksum` was listed in `[metadata]` but we were previously\n    // listed as `V2` then assume some sort of bad git merge happened, so\n    // discard all checksums and let's regenerate them later.\n    if !to_remove.is_empty() && version >= ResolveVersion::V2 {\n        checksums.drain();\n    }\n    for k in to_remove {\n        metadata.remove(&k);\n    }\n\n    let mut unused_patches = Vec::new();\n    for pkg in resolve.patch.unused {\n        let id = match pkg\n            .source\n            .as_ref()\n            .map(|source| SourceId::from_url(&source.source_str()))\n            .transpose()?\n            .or_else(|| get_source_id(&path_deps, &pkg).copied())\n        {\n            Some(src) => PackageId::try_new(&pkg.name, &pkg.version, src)?,\n            None => continue,\n        };\n        unused_patches.push(id);\n    }\n\n    // We have a curious issue where in the \"v1 format\" we buggily had a\n    // trailing blank line at the end of lock files under some specific\n    // conditions.\n    //\n    // Cargo is trying to write new lockfies in the \"v2 format\" but if you\n    // have no dependencies, for example, then the lockfile encoded won't\n    // really have any indicator that it's in the new format (no\n    // dependencies or checksums listed). This means that if you type `cargo\n    // new` followed by `cargo build` it will generate a \"v2 format\" lock\n    // file since none previously existed. When reading this on the next\n    // `cargo build`, however, it generates a new lock file because when\n    // reading in that lockfile we think it's the v1 format.\n    //\n    // To help fix this issue we special case here. If our lockfile only has\n    // one trailing newline, not two, *and* it only has one package, then\n    // this is actually the v2 format.\n    if original.ends_with('\\n')\n        && !original.ends_with(\"\\n\\n\")\n        && version == ResolveVersion::V1\n        && g.iter().count() == 1\n    {\n        version = ResolveVersion::V2;\n    }\n\n    return Ok(Resolve::new(\n        g,\n        replacements,\n        HashMap::new(),\n        checksums,\n        metadata,\n        unused_patches,\n        version,\n        HashMap::new(),\n    ));\n\n    fn get_source_id<'a>(\n        path_deps: &'a HashMap<String, HashMap<semver::Version, SourceId>>,\n        pkg: &'a TomlLockfileDependency,\n    ) -> Option<&'a SourceId> {\n        path_deps.iter().find_map(|(name, version_source)| {\n            if name != &pkg.name || version_source.len() == 0 {\n                return None;\n            }\n            if version_source.len() == 1 {\n                return Some(version_source.values().next().unwrap());\n            }\n            // If there are multiple candidates for the same name, it needs to be determined by combining versions (See #13405).\n            if let Ok(pkg_version) = pkg.version.parse::<semver::Version>() {\n                if let Some(source_id) = version_source.get(&pkg_version) {\n                    return Some(source_id);\n                }\n            }\n\n            None\n        })\n    }\n}\n\nfn build_path_deps(\n    ws: &Workspace<'_>,\n) -> CargoResult<HashMap<String, HashMap<semver::Version, SourceId>>> {\n    // If a crate is **not** a path source, then we're probably in a situation\n    // such as `cargo install` with a lock file from a remote dependency. In\n    // that case we don't need to fixup any path dependencies (as they're not\n    // actually path dependencies any more), so we ignore them.\n    let members = ws\n        .members()\n        .filter(|p| p.package_id().source_id().is_path())\n        .collect::<Vec<_>>();\n\n    let mut ret: HashMap<String, HashMap<semver::Version, SourceId>> = HashMap::new();\n    let mut visited = HashSet::new();\n    for member in members.iter() {\n        ret.entry(member.package_id().name().to_string())\n            .or_insert_with(HashMap::new)\n            .insert(\n                member.package_id().version().clone(),\n                member.package_id().source_id(),\n            );\n        visited.insert(member.package_id().source_id());\n    }\n    for member in members.iter() {\n        build_pkg(member, ws, &mut ret, &mut visited);\n    }\n    for deps in ws.root_patch()?.values() {\n        for Patch { dep, loc: _ } in deps {\n            build_dep(dep, ws, &mut ret, &mut visited);\n        }\n    }\n    for (_, dep) in ws.root_replace() {\n        build_dep(dep, ws, &mut ret, &mut visited);\n    }\n\n    return Ok(ret);\n\n    fn build_pkg(\n        pkg: &Package,\n        ws: &Workspace<'_>,\n        ret: &mut HashMap<String, HashMap<semver::Version, SourceId>>,\n        visited: &mut HashSet<SourceId>,\n    ) {\n        for dep in pkg.dependencies() {\n            build_dep(dep, ws, ret, visited);\n        }\n    }\n\n    fn build_dep(\n        dep: &Dependency,\n        ws: &Workspace<'_>,\n        ret: &mut HashMap<String, HashMap<semver::Version, SourceId>>,\n        visited: &mut HashSet<SourceId>,\n    ) {\n        let id = dep.source_id();\n        if visited.contains(&id) || !id.is_path() {\n            return;\n        }\n        let path = match id.url().to_file_path() {\n            Ok(p) => p.join(\"Cargo.toml\"),\n            Err(_) => return,\n        };\n        let Ok(pkg) = ws.load(&path) else { return };\n        ret.entry(pkg.package_id().name().to_string())\n            .or_insert_with(HashMap::new)\n            .insert(\n                pkg.package_id().version().clone(),\n                pkg.package_id().source_id(),\n            );\n        visited.insert(pkg.package_id().source_id());\n        build_pkg(&pkg, ws, ret, visited);\n    }\n}\n\nimpl ser::Serialize for Resolve {\n    #[tracing::instrument(skip_all)]\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        let mut ids: Vec<_> = self.iter().collect();\n        ids.sort();\n\n        let state = EncodeState::new(self);\n\n        let encodable = ids\n            .iter()\n            .map(|&id| encodable_resolve_node(id, self, &state))\n            .collect::<Vec<_>>();\n\n        let mut metadata = self.metadata().clone();\n\n        if self.version() == ResolveVersion::V1 {\n            for &id in ids.iter().filter(|id| !id.source_id().is_path()) {\n                let checksum = match self.checksums()[&id] {\n                    Some(ref s) => &s[..],\n                    None => \"<none>\",\n                };\n                let id = encodable_package_id(id, &state, self.version());\n                metadata.insert(format!(\"checksum {}\", id), checksum.to_string());\n            }\n        }\n\n        let metadata = if metadata.is_empty() {\n            None\n        } else {\n            Some(metadata)\n        };\n\n        let patch = TomlLockfilePatch {\n            unused: self\n                .unused_patches()\n                .iter()\n                .map(|id| TomlLockfileDependency {\n                    name: id.name().to_string(),\n                    version: id.version().to_string(),\n                    source: encodable_source_id(id.source_id(), self.version()),\n                    dependencies: None,\n                    replace: None,\n                    checksum: if self.version() >= ResolveVersion::V2 {\n                        self.checksums().get(id).and_then(|x| x.clone())\n                    } else {\n                        None\n                    },\n                })\n                .collect(),\n        };\n        TomlLockfile {\n            package: Some(encodable),\n            root: None,\n            metadata,\n            patch,\n            version: match self.version() {\n                ResolveVersion::V5 => Some(5),\n                ResolveVersion::V4 => Some(4),\n                ResolveVersion::V3 => Some(3),\n                ResolveVersion::V2 | ResolveVersion::V1 => None,\n            },\n        }\n        .serialize(s)\n    }\n}\n\npub struct EncodeState<'a> {\n    counts: Option<HashMap<InternedString, HashMap<&'a semver::Version, usize>>>,\n}\n\nimpl<'a> EncodeState<'a> {\n    pub fn new(resolve: &'a Resolve) -> EncodeState<'a> {\n        let counts = if resolve.version() >= ResolveVersion::V2 {\n            let mut map = HashMap::new();\n            for id in resolve.iter() {\n                let slot = map\n                    .entry(id.name())\n                    .or_insert_with(HashMap::new)\n                    .entry(id.version())\n                    .or_insert(0);\n                *slot += 1;\n            }\n            Some(map)\n        } else {\n            None\n        };\n        EncodeState { counts }\n    }\n}\n\nfn encodable_resolve_node(\n    id: PackageId,\n    resolve: &Resolve,\n    state: &EncodeState<'_>,\n) -> TomlLockfileDependency {\n    let (replace, deps) = match resolve.replacement(id) {\n        Some(id) => (\n            Some(encodable_package_id(id, state, resolve.version())),\n            None,\n        ),\n        None => {\n            let mut deps = resolve\n                .deps_not_replaced(id)\n                .map(|(id, _)| encodable_package_id(id, state, resolve.version()))\n                .collect::<Vec<_>>();\n            deps.sort();\n            (None, Some(deps))\n        }\n    };\n\n    TomlLockfileDependency {\n        name: id.name().to_string(),\n        version: id.version().to_string(),\n        source: encodable_source_id(id.source_id(), resolve.version()),\n        dependencies: deps,\n        replace,\n        checksum: if resolve.version() >= ResolveVersion::V2 {\n            resolve.checksums().get(&id).and_then(|s| s.clone())\n        } else {\n            None\n        },\n    }\n}\n\npub fn encodable_package_id(\n    id: PackageId,\n    state: &EncodeState<'_>,\n    resolve_version: ResolveVersion,\n) -> TomlLockfilePackageId {\n    let mut version = Some(id.version().to_string());\n    let mut id_to_encode = id.source_id();\n    if resolve_version <= ResolveVersion::V2 {\n        if let Some(GitReference::Branch(b)) = id_to_encode.git_reference() {\n            if b == \"master\" {\n                id_to_encode =\n                    SourceId::for_git(id_to_encode.url(), GitReference::DefaultBranch).unwrap();\n            }\n        }\n    }\n    let mut source = encodable_source_id(id_to_encode.without_precise(), resolve_version);\n    if let Some(counts) = &state.counts {\n        let version_counts = &counts[&id.name()];\n        if version_counts[&id.version()] == 1 {\n            source = None;\n            if version_counts.len() == 1 {\n                version = None;\n            }\n        }\n    }\n    TomlLockfilePackageId {\n        name: id.name().to_string(),\n        version,\n        source,\n    }\n}\n\nfn encodable_source_id(id: SourceId, version: ResolveVersion) -> Option<TomlLockfileSourceId> {\n    if id.is_path() {\n        None\n    } else {\n        Some(\n            if version >= ResolveVersion::V4 {\n                TomlLockfileSourceId::new(id.as_encoded_url().to_string())\n            } else {\n                TomlLockfileSourceId::new(id.as_url().to_string())\n            }\n            .expect(\"source ID should have valid URLs\"),\n        )\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/resolver/errors.rs",
    "content": "use std::fmt;\nuse std::fmt::Write as _;\nuse std::task::Poll;\n\nuse crate::core::{Dependency, PackageId, Registry, Summary};\nuse crate::sources::IndexSummary;\nuse crate::sources::source::QueryKind;\nuse crate::util::edit_distance::{closest, edit_distance};\nuse crate::util::errors::CargoResult;\nuse crate::util::{GlobalContext, OptVersionReq, VersionExt};\nuse anyhow::Error;\n\nuse super::context::ResolverContext;\nuse super::types::{ConflictMap, ConflictReason};\n\n/// Error during resolution providing a path of `PackageId`s.\npub struct ResolveError {\n    cause: Error,\n    package_path: Vec<PackageId>,\n}\n\nimpl ResolveError {\n    pub fn new<E: Into<Error>>(cause: E, package_path: Vec<PackageId>) -> Self {\n        Self {\n            cause: cause.into(),\n            package_path,\n        }\n    }\n\n    /// Returns a path of packages from the package whose requirements could not be resolved up to\n    /// the root.\n    pub fn package_path(&self) -> &[PackageId] {\n        &self.package_path\n    }\n}\n\nimpl std::error::Error for ResolveError {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        self.cause.source()\n    }\n}\n\nimpl fmt::Debug for ResolveError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.cause.fmt(f)\n    }\n}\n\nimpl fmt::Display for ResolveError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.cause.fmt(f)\n    }\n}\n\npub type ActivateResult<T> = Result<T, ActivateError>;\n\n#[derive(Debug)]\npub enum ActivateError {\n    Fatal(anyhow::Error),\n    Conflict(PackageId, ConflictReason),\n}\n\nimpl From<::anyhow::Error> for ActivateError {\n    fn from(t: ::anyhow::Error) -> Self {\n        ActivateError::Fatal(t)\n    }\n}\n\nimpl From<(PackageId, ConflictReason)> for ActivateError {\n    fn from(t: (PackageId, ConflictReason)) -> Self {\n        ActivateError::Conflict(t.0, t.1)\n    }\n}\n\npub(super) fn activation_error(\n    resolver_ctx: &ResolverContext,\n    registry: &mut impl Registry,\n    parent: &Summary,\n    dep: &Dependency,\n    conflicting_activations: &ConflictMap,\n    candidates: &[Summary],\n    gctx: Option<&GlobalContext>,\n) -> ResolveError {\n    let to_resolve_err = |err| {\n        ResolveError::new(\n            err,\n            resolver_ctx\n                .parents\n                .path_to_bottom(&parent.package_id())\n                .into_iter()\n                .map(|(node, _)| node)\n                .cloned()\n                .collect(),\n        )\n    };\n\n    if !candidates.is_empty() {\n        let mut msg = format!(\"failed to select a version for `{}`.\", dep.package_name());\n        msg.push_str(\"\\n    ... required by \");\n        msg.push_str(&describe_path_in_context(\n            resolver_ctx,\n            &parent.package_id(),\n        ));\n\n        msg.push_str(\"\\nversions that meet the requirements `\");\n        msg.push_str(&dep.version_req().to_string());\n        msg.push_str(\"` \");\n\n        if let Some(v) = dep.version_req().locked_version() {\n            msg.push_str(\"(locked to \");\n            msg.push_str(&v.to_string());\n            msg.push_str(\") \");\n        }\n\n        msg.push_str(\"are: \");\n        msg.push_str(\n            &candidates\n                .iter()\n                .map(|v| v.version())\n                .map(|v| v.to_string())\n                .collect::<Vec<_>>()\n                .join(\", \"),\n        );\n\n        let mut conflicting_activations: Vec<_> = conflicting_activations.iter().collect();\n        conflicting_activations.sort_unstable();\n        // This is reversed to show the newest versions first. I don't know if there is\n        // a strong reason to do this, but that is how the code previously worked\n        // (see https://github.com/rust-lang/cargo/pull/5037) and I don't feel like changing it.\n        conflicting_activations.reverse();\n        // Flag used for grouping all semver errors together.\n        let mut has_semver = false;\n\n        for (p, r) in &conflicting_activations {\n            match r {\n                ConflictReason::Semver => {\n                    has_semver = true;\n                }\n                ConflictReason::Links(link) => {\n                    msg.push_str(\"\\n\\npackage `\");\n                    msg.push_str(&*dep.package_name());\n                    msg.push_str(\"` links to the native library `\");\n                    msg.push_str(link);\n                    msg.push_str(\"`, but it conflicts with a previous package which links to `\");\n                    msg.push_str(link);\n                    msg.push_str(\"` as well:\\n\");\n                    msg.push_str(&describe_path_in_context(resolver_ctx, p));\n                    msg.push_str(\"\\nOnly one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. \");\n                    msg.push_str(\"Try to adjust your dependencies so that only one package uses the `links = \\\"\");\n                    msg.push_str(link);\n                    msg.push_str(\"\\\"` value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.\");\n                }\n                ConflictReason::MissingFeature(feature) => {\n                    msg.push_str(\"\\n\\npackage `\");\n                    msg.push_str(&*p.name());\n                    msg.push_str(\"` depends on `\");\n                    msg.push_str(&*dep.package_name());\n                    msg.push_str(\"` with feature `\");\n                    msg.push_str(feature);\n                    msg.push_str(\"` but `\");\n                    msg.push_str(&*dep.package_name());\n                    msg.push_str(\"` does not have that feature.\\n\");\n                    let latest = candidates.last().expect(\"in the non-empty branch\");\n                    if let Some(closest) = closest(feature, latest.features().keys(), |k| k) {\n                        msg.push_str(\" package `\");\n                        msg.push_str(&*dep.package_name());\n                        msg.push_str(\"` does have feature `\");\n                        msg.push_str(closest);\n                        msg.push_str(\"`\\n\");\n                    } else if !latest.features().is_empty() {\n                        let mut features: Vec<_> =\n                            latest.features().keys().map(|f| f.as_str()).collect();\n                        features.sort();\n                        msg.push_str(\" available features: \");\n                        msg.push_str(&features.join(\", \"));\n                        msg.push_str(\"\\n\");\n                    }\n                    // p == parent so the full path is redundant.\n                }\n                ConflictReason::RequiredDependencyAsFeature(feature) => {\n                    msg.push_str(\"\\n\\npackage `\");\n                    msg.push_str(&*p.name());\n                    msg.push_str(\"` depends on `\");\n                    msg.push_str(&*dep.package_name());\n                    msg.push_str(\"` with feature `\");\n                    msg.push_str(feature);\n                    msg.push_str(\"` but `\");\n                    msg.push_str(&*dep.package_name());\n                    msg.push_str(\"` does not have that feature.\\n\");\n                    msg.push_str(\n                        \" A required dependency with that name exists, \\\n                         but only optional dependencies can be used as features.\\n\",\n                    );\n                    // p == parent so the full path is redundant.\n                }\n                ConflictReason::NonImplicitDependencyAsFeature(feature) => {\n                    msg.push_str(\"\\n\\npackage `\");\n                    msg.push_str(&*p.name());\n                    msg.push_str(\"` depends on `\");\n                    msg.push_str(&*dep.package_name());\n                    msg.push_str(\"` with feature `\");\n                    msg.push_str(feature);\n                    msg.push_str(\"` but `\");\n                    msg.push_str(&*dep.package_name());\n                    msg.push_str(\"` does not have that feature.\\n\");\n                    msg.push_str(\n                        \" An optional dependency with that name exists, \\\n                         but that dependency uses the \\\"dep:\\\" \\\n                         syntax in the features table, so it does not have an \\\n                         implicit feature with that name.\\n\",\n                    );\n                    // p == parent so the full path is redundant.\n                }\n            }\n        }\n\n        if has_semver {\n            // Group these errors together.\n            msg.push_str(\"\\n\\nall possible versions conflict with previously selected packages.\");\n            for (p, r) in &conflicting_activations {\n                if let ConflictReason::Semver = r {\n                    msg.push_str(\"\\n\\n  previously selected \");\n                    msg.push_str(&describe_path_in_context(resolver_ctx, p));\n                }\n            }\n        }\n\n        msg.push_str(\"\\n\\nfailed to select a version for `\");\n        msg.push_str(&*dep.package_name());\n        msg.push_str(\"` which could resolve this conflict\");\n\n        return to_resolve_err(anyhow::format_err!(\"{}\", msg));\n    }\n\n    // We didn't actually find any candidates, so we need to\n    // give an error message that nothing was found.\n    let mut msg = String::new();\n    let mut hints = String::new();\n    if let Some(version_candidates) = rejected_versions(registry, dep) {\n        let version_candidates = match version_candidates {\n            Ok(c) => c,\n            Err(e) => return to_resolve_err(e),\n        };\n\n        let locked_version = dep\n            .version_req()\n            .locked_version()\n            .map(|v| format!(\" (locked to {})\", v))\n            .unwrap_or_default();\n        let _ = writeln!(\n            &mut msg,\n            \"failed to select a version for the requirement `{} = \\\"{}\\\"`{}\",\n            dep.package_name(),\n            dep.version_req(),\n            locked_version\n        );\n        for candidate in version_candidates {\n            match candidate {\n                IndexSummary::Candidate(summary) => {\n                    // HACK: If this was a real candidate, we wouldn't hit this case.\n                    // so it must be a patch which get normalized to being a candidate\n                    let _ = writeln!(&mut msg, \"  version {} is unavailable\", summary.version());\n                }\n                IndexSummary::Yanked(summary) => {\n                    let _ = writeln!(&mut msg, \"  version {} is yanked\", summary.version());\n                }\n                IndexSummary::Offline(summary) => {\n                    let _ = writeln!(&mut msg, \"  version {} is not cached\", summary.version());\n                }\n                IndexSummary::Unsupported(summary, schema_version) => {\n                    if let Some(rust_version) = summary.rust_version() {\n                        // HACK: technically its unsupported and we shouldn't make assumptions\n                        // about the entry but this is limited and for diagnostics purposes\n                        let _ = writeln!(\n                            &mut msg,\n                            \"  version {} requires cargo {}\",\n                            summary.version(),\n                            rust_version\n                        );\n                    } else {\n                        let _ = writeln!(\n                            &mut msg,\n                            \"  version {} requires a Cargo version that supports index version {}\",\n                            summary.version(),\n                            schema_version\n                        );\n                    }\n                }\n                IndexSummary::Invalid(summary) => {\n                    let _ = writeln!(\n                        &mut msg,\n                        \"  version {}'s index entry is invalid\",\n                        summary.version()\n                    );\n                }\n            }\n        }\n    } else if let Some(candidates) = alt_versions(registry, dep) {\n        let candidates = match candidates {\n            Ok(c) => c,\n            Err(e) => return to_resolve_err(e),\n        };\n        let versions = {\n            let mut versions = candidates\n                .iter()\n                .take(3)\n                .map(|cand| cand.version().to_string())\n                .collect::<Vec<_>>();\n\n            if candidates.len() > 3 {\n                versions.push(\"...\".into());\n            }\n\n            versions.join(\", \")\n        };\n\n        let locked_version = dep\n            .version_req()\n            .locked_version()\n            .map(|v| format!(\" (locked to {})\", v))\n            .unwrap_or_default();\n\n        let _ = writeln!(\n            &mut msg,\n            \"failed to select a version for the requirement `{} = \\\"{}\\\"`{}\",\n            dep.package_name(),\n            dep.version_req(),\n            locked_version,\n        );\n        let _ = writeln!(\n            &mut msg,\n            \"candidate versions found which didn't match: {versions}\",\n        );\n\n        // If we have a pre-release candidate, then that may be what our user is looking for\n        if let Some(pre) = candidates.iter().find(|c| c.version().is_prerelease()) {\n            let _ = write!(\n                &mut hints,\n                \"\\nif you are looking for the prerelease package it needs to be specified explicitly\"\n            );\n            let _ = write!(\n                &mut hints,\n                \"\\n    {} = {{ version = \\\"{}\\\" }}\",\n                pre.name(),\n                pre.version()\n            );\n        }\n\n        // If we have a path dependency with a locked version, then this may\n        // indicate that we updated a sub-package and forgot to run `cargo\n        // update`. In this case try to print a helpful error!\n        if dep.source_id().is_path() && dep.version_req().is_locked() {\n            let _ = write!(\n                &mut hints,\n                \"\\nconsider running `cargo update` to update \\\n                          a path dependency's locked version\",\n            );\n        }\n\n        if registry.is_replaced(dep.source_id()) {\n            let _ = write!(\n                &mut hints,\n                \"\\nperhaps a crate was updated and forgotten to be re-vendored?\"\n            );\n        }\n    } else if let Some(name_candidates) = alt_names(registry, dep) {\n        let name_candidates = match name_candidates {\n            Ok(c) => c,\n            Err(e) => return to_resolve_err(e),\n        };\n        let _ = writeln!(&mut msg, \"no matching package found\",);\n        let _ = writeln!(&mut msg, \"searched package name: `{}`\", dep.package_name());\n        let mut names = name_candidates\n            .iter()\n            .take(3)\n            .map(|c| c.1.name().as_str())\n            .collect::<Vec<_>>();\n\n        if name_candidates.len() > 3 {\n            names.push(\"...\");\n        }\n        // Vertically align first suggestion with missing crate name\n        // so a typo jumps out at you.\n        let suggestions =\n            names\n                .iter()\n                .enumerate()\n                .fold(String::default(), |acc, (i, el)| match i {\n                    0 => acc + el,\n                    i if names.len() - 1 == i && name_candidates.len() <= 3 => acc + \" or \" + el,\n                    _ => acc + \", \" + el,\n                });\n        let _ = writeln!(&mut msg, \"perhaps you meant:      {suggestions}\");\n    } else {\n        let _ = writeln!(\n            &mut msg,\n            \"no matching package named `{}` found\",\n            dep.package_name()\n        );\n    }\n\n    let mut location_searched_msg = registry.describe_source(dep.source_id());\n    if location_searched_msg.is_empty() {\n        location_searched_msg = format!(\"{}\", dep.source_id());\n    }\n    let _ = writeln!(&mut msg, \"location searched: {}\", location_searched_msg);\n    let _ = write!(\n        &mut msg,\n        \"required by {}\",\n        describe_path_in_context(resolver_ctx, &parent.package_id()),\n    );\n\n    if let Some(gctx) = gctx {\n        if let Some(offline_flag) = gctx.offline_flag() {\n            let _ = write!(\n                &mut hints,\n                \"\\nAs a reminder, you're using offline mode ({offline_flag}) \\\n                 which can sometimes cause surprising resolution failures, \\\n                 if this error is too confusing you may wish to retry \\\n                 without `{offline_flag}`.\",\n            );\n        }\n    }\n\n    to_resolve_err(anyhow::format_err!(\"{msg}{hints}\"))\n}\n\n// Maybe the user mistyped the ver_req? Like `dep=\"2\"` when `dep=\"0.2\"`\n// was meant. So we re-query the registry with `dep=\"*\"` so we can\n// list a few versions that were actually found.\nfn alt_versions(\n    registry: &mut impl Registry,\n    dep: &Dependency,\n) -> Option<CargoResult<Vec<Summary>>> {\n    let mut wild_dep = dep.clone();\n    wild_dep.set_version_req(OptVersionReq::Any);\n\n    let candidates = loop {\n        match registry.query_vec(&wild_dep, QueryKind::Exact) {\n            Poll::Ready(Ok(candidates)) => break candidates,\n            Poll::Ready(Err(e)) => return Some(Err(e)),\n            Poll::Pending => match registry.block_until_ready() {\n                Ok(()) => continue,\n                Err(e) => return Some(Err(e)),\n            },\n        }\n    };\n    let mut candidates: Vec<_> = candidates.into_iter().map(|s| s.into_summary()).collect();\n    candidates.sort_unstable_by(|a, b| b.version().cmp(a.version()));\n    if candidates.is_empty() {\n        None\n    } else {\n        Some(Ok(candidates))\n    }\n}\n\n/// Maybe something is wrong with the available versions\nfn rejected_versions(\n    registry: &mut impl Registry,\n    dep: &Dependency,\n) -> Option<CargoResult<Vec<IndexSummary>>> {\n    let mut version_candidates = loop {\n        match registry.query_vec(&dep, QueryKind::RejectedVersions) {\n            Poll::Ready(Ok(candidates)) => break candidates,\n            Poll::Ready(Err(e)) => return Some(Err(e)),\n            Poll::Pending => match registry.block_until_ready() {\n                Ok(()) => continue,\n                Err(e) => return Some(Err(e)),\n            },\n        }\n    };\n    version_candidates.sort_unstable_by_key(|a| a.as_summary().version().clone());\n    if version_candidates.is_empty() {\n        None\n    } else {\n        Some(Ok(version_candidates))\n    }\n}\n\n/// Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing`\n/// was meant. So we try asking the registry for a `fuzzy` search for suggestions.\nfn alt_names(\n    registry: &mut impl Registry,\n    dep: &Dependency,\n) -> Option<CargoResult<Vec<(usize, Summary)>>> {\n    let mut wild_dep = dep.clone();\n    wild_dep.set_version_req(OptVersionReq::Any);\n\n    let name_candidates = loop {\n        match registry.query_vec(&wild_dep, QueryKind::AlternativeNames) {\n            Poll::Ready(Ok(candidates)) => break candidates,\n            Poll::Ready(Err(e)) => return Some(Err(e)),\n            Poll::Pending => match registry.block_until_ready() {\n                Ok(()) => continue,\n                Err(e) => return Some(Err(e)),\n            },\n        }\n    };\n    let mut name_candidates: Vec<_> = name_candidates\n        .into_iter()\n        .map(|s| s.into_summary())\n        .collect();\n    name_candidates.sort_unstable_by_key(|a| a.name());\n    name_candidates.dedup_by(|a, b| a.name() == b.name());\n    let mut name_candidates: Vec<_> = name_candidates\n        .into_iter()\n        .filter_map(|n| Some((edit_distance(&*wild_dep.package_name(), &*n.name(), 3)?, n)))\n        .collect();\n    name_candidates.sort_by_key(|o| o.0);\n\n    if name_candidates.is_empty() {\n        None\n    } else {\n        Some(Ok(name_candidates))\n    }\n}\n\n/// Returns String representation of dependency chain for a particular `pkgid`\n/// within given context.\npub(super) fn describe_path_in_context(cx: &ResolverContext, id: &PackageId) -> String {\n    let iter = cx\n        .parents\n        .path_to_bottom(id)\n        .into_iter()\n        .map(|(p, d)| (p, d.and_then(|d| d.iter().next())));\n    describe_path(iter)\n}\n\n/// Returns String representation of dependency chain for a particular `pkgid`.\n///\n/// Note that all elements of `path` iterator should have `Some` dependency\n/// except the first one. It would look like:\n///\n/// (pkg0, None)\n/// -> (pkg1, dep from pkg1 satisfied by pkg0)\n/// -> (pkg2, dep from pkg2 satisfied by pkg1)\n/// -> ...\npub(crate) fn describe_path<'a>(\n    mut path: impl Iterator<Item = (&'a PackageId, Option<&'a Dependency>)>,\n) -> String {\n    use std::fmt::Write;\n\n    if let Some(p) = path.next() {\n        let mut dep_path_desc = format!(\"package `{}`\", p.0);\n        for (pkg, dep) in path {\n            let dep = dep.unwrap();\n            let source_kind = if dep.source_id().is_path() {\n                \"path \"\n            } else if dep.source_id().is_git() {\n                \"git \"\n            } else {\n                \"\"\n            };\n            let requirement = if source_kind.is_empty() {\n                format!(\"{} = \\\"{}\\\"\", dep.name_in_toml(), dep.version_req())\n            } else {\n                dep.name_in_toml().to_string()\n            };\n            let locked_version = dep\n                .version_req()\n                .locked_version()\n                .map(|v| format!(\"(locked to {}) \", v))\n                .unwrap_or_default();\n\n            write!(\n                dep_path_desc,\n                \"\\n    ... which satisfies {}dependency `{}` {}of package `{}`\",\n                source_kind, requirement, locked_version, pkg\n            )\n            .unwrap();\n        }\n\n        return dep_path_desc;\n    }\n\n    String::new()\n}\n"
  },
  {
    "path": "src/cargo/core/resolver/features.rs",
    "content": "//! Resolves conditional compilation for [`features` section] in the manifest.\n//!\n//! This is a [new feature resolver] that runs independently of the main\n//! dependency resolver. It has several options which can enable new feature\n//! resolution behavior.\n//!\n//! One of its key characteristics is that it can avoid unifying features for\n//! shared dependencies in some situations. See [`FeatureOpts`] for the\n//! different behaviors that can be enabled. If no extra options are enabled,\n//! then it should behave exactly the same as the dependency resolver's\n//! feature resolution.\n//!\n//! The preferred way to engage this new resolver is via [`resolve_ws_with_opts`].\n//!\n//! This does not *replace* feature resolution in the dependency resolver, but\n//! instead acts as a second pass which can *narrow* the features selected in\n//! the dependency resolver. The dependency resolver still needs to do its own\n//! feature resolution in order to avoid selecting optional dependencies that\n//! are never enabled. The dependency resolver could, in theory, just assume\n//! all optional dependencies on all packages are enabled (and remove all\n//! knowledge of features), but that could introduce new requirements that\n//! might change old behavior or cause conflicts. Maybe some day in the future\n//! we could experiment with that, but it seems unlikely to work or be all\n//! that helpful.\n//!\n//! ## Assumptions\n//!\n//! There are many assumptions made about the dependency resolver:\n//!\n//! * Assumes feature validation has already been done during the construction\n//!   of feature maps, so the feature resolver doesn't do that validation at all.\n//! * Assumes `dev-dependencies` within a dependency have been removed\n//!   in the given [`Resolve`].\n//!\n//! There are probably other assumptions that I am forgetting.\n//!\n//! [`features` section]: https://doc.rust-lang.org/nightly/cargo/reference/features.html\n//! [new feature resolver]: https://doc.rust-lang.org/nightly/cargo/reference/resolver.html#feature-resolver-version-2\n//! [`resolve_ws_with_opts`]: crate::ops::resolve_ws_with_opts\n\nuse crate::core::compiler::{CompileKind, CompileTarget, RustcTargetData};\nuse crate::core::dependency::{ArtifactTarget, DepKind, Dependency};\nuse crate::core::resolver::types::FeaturesSet;\nuse crate::core::resolver::{Resolve, ResolveBehavior};\nuse crate::core::{FeatureValue, PackageId, PackageIdSpec, PackageSet, Workspace};\nuse crate::util::CargoResult;\nuse crate::util::interning::{INTERNED_DEFAULT, InternedString};\nuse anyhow::{Context, bail};\nuse itertools::Itertools;\nuse std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};\nuse std::rc::Rc;\n\n/// The key used in various places to store features for a particular dependency.\n/// The actual discrimination happens with the [`FeaturesFor`] type.\npub type PackageFeaturesKey = (PackageId, FeaturesFor);\n/// Map of activated features.\npub type ActivateMap = HashMap<PackageFeaturesKey, BTreeSet<InternedString>>;\n\n/// Set of all activated features for all packages in the resolve graph.\npub struct ResolvedFeatures {\n    pub activated_features: ActivateMap,\n    /// Optional dependencies that should be built.\n    ///\n    /// The value is the `name_in_toml` of the dependencies.\n    pub activated_dependencies: ActivateMap,\n    pub opts: FeatureOpts,\n}\n\n/// Options for how the feature resolver works.\n#[derive(Default)]\npub struct FeatureOpts {\n    /// Build deps and proc-macros will not share features with other dep kinds,\n    /// and so won't artifact targets.\n    /// In other terms, if true, features associated with certain kinds of dependencies\n    /// will only be unified together.\n    /// If false, there is only one namespace for features, unifying all features across\n    /// all dependencies, no matter what kind.\n    decouple_host_deps: bool,\n    /// Dev dep features will not be activated unless needed.\n    decouple_dev_deps: bool,\n    /// Targets that are not in use will not activate features.\n    ignore_inactive_targets: bool,\n    /// If enabled, compare against old resolver (for testing).\n    compare: bool,\n}\n\n/// Flag to indicate if Cargo is building *any* dev units (tests, examples, etc.).\n///\n/// This disables decoupling of dev dependencies. It may be possible to relax\n/// this in the future, but it will require significant changes to how unit\n/// dependencies are computed, and can result in longer build times with\n/// `cargo test` because the lib may need to be built 3 times instead of\n/// twice.\n#[derive(Copy, Clone, PartialEq)]\npub enum HasDevUnits {\n    Yes,\n    No,\n}\n\n/// Flag to indicate that target-specific filtering should be disabled.\n#[derive(Copy, Clone, PartialEq)]\npub enum ForceAllTargets {\n    Yes,\n    No,\n}\n\n/// Flag to indicate if features are requested for a certain type of dependency.\n///\n/// This is primarily used for constructing a [`PackageFeaturesKey`] to decouple\n/// activated features of the same package with different types of dependency.\n#[derive(Default, Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]\npub enum FeaturesFor {\n    /// Normal or dev dependency.\n    #[default]\n    NormalOrDev,\n    /// Build dependency or proc-macro.\n    HostDep,\n    /// Any dependency with both artifact and target specified.\n    ///\n    /// That is, `dep = { …, artifact = <crate-type>, target = <triple> }`\n    ArtifactDep(CompileTarget),\n}\n\nimpl std::fmt::Display for FeaturesFor {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            FeaturesFor::HostDep => f.write_str(\"host\"),\n            FeaturesFor::ArtifactDep(target) => f.write_str(&target.rustc_target()),\n            FeaturesFor::NormalOrDev => Ok(()),\n        }\n    }\n}\n\nimpl FeaturesFor {\n    pub fn from_for_host(for_host: bool) -> FeaturesFor {\n        if for_host {\n            FeaturesFor::HostDep\n        } else {\n            FeaturesFor::NormalOrDev\n        }\n    }\n\n    pub fn from_for_host_or_artifact_target(\n        for_host: bool,\n        artifact_target: Option<CompileTarget>,\n    ) -> FeaturesFor {\n        match artifact_target {\n            Some(target) => FeaturesFor::ArtifactDep(target),\n            None => {\n                if for_host {\n                    FeaturesFor::HostDep\n                } else {\n                    FeaturesFor::NormalOrDev\n                }\n            }\n        }\n    }\n\n    fn apply_opts(self, opts: &FeatureOpts) -> Self {\n        if opts.decouple_host_deps {\n            self\n        } else {\n            FeaturesFor::default()\n        }\n    }\n}\n\nimpl FeatureOpts {\n    pub fn new(\n        ws: &Workspace<'_>,\n        has_dev_units: HasDevUnits,\n        force_all_targets: ForceAllTargets,\n    ) -> CargoResult<FeatureOpts> {\n        let mut opts = FeatureOpts::default();\n        let unstable_flags = ws.gctx().cli_unstable();\n        let mut enable = |feat_opts: &Vec<String>| {\n            for opt in feat_opts {\n                match opt.as_ref() {\n                    \"build_dep\" | \"host_dep\" => opts.decouple_host_deps = true,\n                    \"dev_dep\" => opts.decouple_dev_deps = true,\n                    \"itarget\" => opts.ignore_inactive_targets = true,\n                    \"all\" => {\n                        opts.decouple_host_deps = true;\n                        opts.decouple_dev_deps = true;\n                        opts.ignore_inactive_targets = true;\n                    }\n                    \"compare\" => opts.compare = true,\n                    \"ws\" => unimplemented!(),\n                    s => bail!(\"-Zfeatures flag `{}` is not supported\", s),\n                }\n            }\n            Ok(())\n        };\n        if let Some(feat_opts) = unstable_flags.features.as_ref() {\n            enable(feat_opts)?;\n        }\n        match ws.resolve_behavior() {\n            ResolveBehavior::V1 => {}\n            ResolveBehavior::V2 | ResolveBehavior::V3 => {\n                enable(&vec![\"all\".to_string()]).unwrap();\n            }\n        }\n        if let HasDevUnits::Yes = has_dev_units {\n            // Dev deps cannot be decoupled when they are in use.\n            opts.decouple_dev_deps = false;\n        }\n        if let ForceAllTargets::Yes = force_all_targets {\n            opts.ignore_inactive_targets = false;\n        }\n        Ok(opts)\n    }\n\n    /// Creates a new `FeatureOpts` for the given behavior.\n    pub fn new_behavior(behavior: ResolveBehavior, has_dev_units: HasDevUnits) -> FeatureOpts {\n        match behavior {\n            ResolveBehavior::V1 => FeatureOpts::default(),\n            ResolveBehavior::V2 | ResolveBehavior::V3 => FeatureOpts {\n                decouple_host_deps: true,\n                decouple_dev_deps: has_dev_units == HasDevUnits::No,\n                ignore_inactive_targets: true,\n                compare: false,\n            },\n        }\n    }\n}\n\n/// Features flags requested for a package.\n///\n/// This should be cheap and fast to clone, it is used in the resolver for\n/// various caches.\n///\n/// This is split into enum variants because the resolver needs to handle\n/// features coming from different places (command-line and dependency\n/// declarations), but those different places have different constraints on\n/// which syntax is allowed. This helps ensure that every place dealing with\n/// features is properly handling those syntax restrictions.\n#[derive(Debug, Clone, Eq, PartialEq, Hash)]\npub enum RequestedFeatures {\n    /// Features requested on the command-line with flags.\n    CliFeatures(CliFeatures),\n    /// Features specified in a dependency declaration.\n    DepFeatures {\n        /// The `features` dependency field.\n        features: FeaturesSet,\n        /// The `default-features` dependency field.\n        uses_default_features: bool,\n    },\n}\n\n/// Features specified on the command-line.\n#[derive(Debug, Clone, Eq, PartialEq, Hash)]\npub struct CliFeatures {\n    /// Features from the `--features` flag.\n    pub features: Rc<BTreeSet<FeatureValue>>,\n    /// The `--all-features` flag.\n    pub all_features: bool,\n    /// Inverse of `--no-default-features` flag.\n    pub uses_default_features: bool,\n}\n\nimpl CliFeatures {\n    /// Creates a new `CliFeatures` from the given command-line flags.\n    pub fn from_command_line(\n        features: &[String],\n        all_features: bool,\n        uses_default_features: bool,\n    ) -> CargoResult<CliFeatures> {\n        let features = Rc::new(CliFeatures::split_features(features));\n        // Some early validation to ensure correct syntax.\n        for feature in features.iter() {\n            match feature {\n                // Maybe call validate_feature_name here once it is an error?\n                FeatureValue::Feature(_) => {}\n                FeatureValue::Dep { .. } => {\n                    bail!(\n                        \"feature `{}` is not allowed to use explicit `dep:` syntax\",\n                        feature\n                    );\n                }\n                FeatureValue::DepFeature { dep_feature, .. } => {\n                    if dep_feature.contains('/') {\n                        bail!(\"multiple slashes in feature `{}` is not allowed\", feature);\n                    }\n                }\n            }\n        }\n        Ok(CliFeatures {\n            features,\n            all_features,\n            uses_default_features,\n        })\n    }\n\n    /// Creates a new `CliFeatures` with the given `all_features` setting.\n    pub fn new_all(all_features: bool) -> CliFeatures {\n        CliFeatures {\n            features: Rc::new(BTreeSet::new()),\n            all_features,\n            uses_default_features: true,\n        }\n    }\n\n    fn split_features(features: &[String]) -> BTreeSet<FeatureValue> {\n        features\n            .iter()\n            .flat_map(|s| s.split_whitespace())\n            .flat_map(|s| s.split(','))\n            .filter(|s| !s.is_empty())\n            .map(|s| s.into())\n            .map(FeatureValue::new)\n            .collect()\n    }\n}\n\nimpl ResolvedFeatures {\n    /// Returns the list of features that are enabled for the given package.\n    pub fn activated_features(\n        &self,\n        pkg_id: PackageId,\n        features_for: FeaturesFor,\n    ) -> Vec<InternedString> {\n        if let Some(res) = self.activated_features_unverified(pkg_id, features_for) {\n            res\n        } else {\n            panic!(\n                \"did not find features for ({pkg_id:?}, {features_for:?}) within activated_features:\\n{:#?}\",\n                self.activated_features.keys()\n            )\n        }\n    }\n\n    /// Variant of `activated_features` that returns `None` if this is\n    /// not a valid `pkg_id/is_build` combination. Used in places which do\n    /// not know which packages are activated (like `cargo clean`).\n    pub fn activated_features_unverified(\n        &self,\n        pkg_id: PackageId,\n        features_for: FeaturesFor,\n    ) -> Option<Vec<InternedString>> {\n        let fk = features_for.apply_opts(&self.opts);\n        if let Some(fs) = self.activated_features.get(&(pkg_id, fk)) {\n            Some(fs.iter().cloned().collect())\n        } else {\n            None\n        }\n    }\n\n    /// Returns if the given dependency should be included.\n    ///\n    /// This handles dependencies disabled via `cfg` expressions and optional\n    /// dependencies which are not enabled.\n    pub fn is_dep_activated(\n        &self,\n        pkg_id: PackageId,\n        features_for: FeaturesFor,\n        dep_name: InternedString,\n    ) -> bool {\n        let key = features_for.apply_opts(&self.opts);\n        self.activated_dependencies\n            .get(&(pkg_id, key))\n            .map(|deps| deps.contains(&dep_name))\n            .unwrap_or(false)\n    }\n\n    /// Compares the result against the original resolver behavior.\n    ///\n    /// Used by `cargo fix --edition` to display any differences.\n    pub fn compare_legacy(&self, legacy: &ResolvedFeatures) -> DiffMap {\n        self.activated_features\n            .iter()\n            .filter_map(|((pkg_id, for_host), new_features)| {\n                let old_features = legacy\n                    .activated_features\n                    .get(&(*pkg_id, *for_host))\n                    // The new features may have for_host entries where the old one does not.\n                    .or_else(|| {\n                        legacy\n                            .activated_features\n                            .get(&(*pkg_id, FeaturesFor::default()))\n                    })\n                    .map(|feats| feats.iter().cloned().collect())\n                    .unwrap_or_else(|| BTreeSet::new());\n                // The new resolver should never add features.\n                assert_eq!(new_features.difference(&old_features).next(), None);\n                let removed_features: BTreeSet<_> =\n                    old_features.difference(new_features).cloned().collect();\n                if removed_features.is_empty() {\n                    None\n                } else {\n                    Some(((*pkg_id, *for_host), removed_features))\n                }\n            })\n            .collect()\n    }\n}\n\n/// Map of differences.\n///\n/// Key is `(pkg_id, for_host)`. Value is a set of features or dependencies removed.\npub type DiffMap = BTreeMap<PackageFeaturesKey, BTreeSet<InternedString>>;\n\n/// The new feature resolver that [`resolve`]s your project.\n///\n/// For more information, please see the [module-level documentation].\n///\n/// [`resolve`]: Self::resolve\n/// [module-level documentation]: crate::core::resolver::features\npub struct FeatureResolver<'a, 'gctx> {\n    ws: &'a Workspace<'gctx>,\n    target_data: &'a mut RustcTargetData<'gctx>,\n    /// The platforms to build for, requested by the user.\n    requested_targets: &'a [CompileKind],\n    resolve: &'a Resolve,\n    package_set: &'a PackageSet<'gctx>,\n    /// Options that change how the feature resolver operates.\n    opts: FeatureOpts,\n    /// Map of features activated for each package.\n    activated_features: ActivateMap,\n    /// Map of optional dependencies activated for each package.\n    activated_dependencies: ActivateMap,\n    /// Keeps track of which packages have had its dependencies processed.\n    /// Used to avoid cycles, and to speed up processing.\n    processed_deps: HashSet<PackageFeaturesKey>,\n    /// If this is `true`, then a non-default `feature_key` needs to be tracked while\n    /// traversing the graph.\n    ///\n    /// This is only here to avoid calling [`has_any_proc_macro`] when all feature\n    /// options are disabled (because [`has_any_proc_macro`] can trigger downloads).\n    /// This has to be separate from [`FeatureOpts::decouple_host_deps`] because\n    /// `for_host` tracking is also needed for `itarget` to work properly.\n    ///\n    /// [`has_any_proc_macro`]: FeatureResolver::has_any_proc_macro\n    track_for_host: bool,\n    /// `dep_name?/feat_name` features that will be activated if `dep_name` is\n    /// ever activated.\n    ///\n    /// The key is the `(package, for_host, dep_name)` of the package whose\n    /// dependency will trigger the addition of new features. The value is the\n    /// set of features to activate.\n    deferred_weak_dependencies:\n        HashMap<(PackageId, FeaturesFor, InternedString), HashSet<InternedString>>,\n}\n\nimpl<'a, 'gctx> FeatureResolver<'a, 'gctx> {\n    /// Runs the resolution algorithm and returns a new [`ResolvedFeatures`]\n    /// with the result.\n    #[tracing::instrument(skip_all)]\n    pub fn resolve(\n        ws: &Workspace<'gctx>,\n        target_data: &'a mut RustcTargetData<'gctx>,\n        resolve: &Resolve,\n        package_set: &'a PackageSet<'gctx>,\n        cli_features: &CliFeatures,\n        specs: &[PackageIdSpec],\n        requested_targets: &[CompileKind],\n        opts: FeatureOpts,\n    ) -> CargoResult<ResolvedFeatures> {\n        let track_for_host = opts.decouple_host_deps || opts.ignore_inactive_targets;\n        let mut r = FeatureResolver {\n            ws,\n            target_data,\n            requested_targets,\n            resolve,\n            package_set,\n            opts,\n            activated_features: HashMap::new(),\n            activated_dependencies: HashMap::new(),\n            processed_deps: HashSet::new(),\n            track_for_host,\n            deferred_weak_dependencies: HashMap::new(),\n        };\n        r.do_resolve(specs, cli_features)?;\n        tracing::debug!(\"features={:#?}\", r.activated_features);\n        if r.opts.compare {\n            r.compare();\n        }\n        Ok(ResolvedFeatures {\n            activated_features: r.activated_features,\n            activated_dependencies: r.activated_dependencies,\n            opts: r.opts,\n        })\n    }\n\n    /// Performs the process of resolving all features for the resolve graph.\n    fn do_resolve(\n        &mut self,\n        specs: &[PackageIdSpec],\n        cli_features: &CliFeatures,\n    ) -> CargoResult<()> {\n        let member_features = self.ws.members_with_features(specs, cli_features)?;\n        for (member, cli_features) in &member_features {\n            let fvs = self.fvs_from_requested(member.package_id(), cli_features);\n            let fk = if self.track_for_host && self.has_any_proc_macro(member.package_id()) {\n                // Also activate for normal dependencies. This is needed if the\n                // proc-macro includes other targets (like binaries or tests),\n                // or running in `cargo test`. Note that in a workspace, if\n                // the proc-macro is selected on the command like (like with\n                // `--workspace`), this forces feature unification with normal\n                // dependencies. This is part of the bigger problem where\n                // features depend on which packages are built.\n                self.activate_pkg(member.package_id(), FeaturesFor::default(), &fvs)?;\n                FeaturesFor::HostDep\n            } else {\n                FeaturesFor::default()\n            };\n            self.activate_pkg(member.package_id(), fk, &fvs)?;\n        }\n        Ok(())\n    }\n\n    /// Activates [`FeatureValue`]s on the given package.\n    ///\n    /// This is the main entrance into the recursion of feature activation\n    /// for a package.\n    fn activate_pkg(\n        &mut self,\n        pkg_id: PackageId,\n        fk: FeaturesFor,\n        fvs: &[FeatureValue],\n    ) -> CargoResult<()> {\n        tracing::trace!(\"activate_pkg {} {}\", pkg_id.name(), fk);\n        // Add an empty entry to ensure everything is covered. This is intended for\n        // finding bugs where the resolver missed something it should have visited.\n        // Remove this in the future if `activated_features` uses an empty default.\n        self.activated_features\n            .entry((pkg_id, fk.apply_opts(&self.opts)))\n            .or_insert_with(BTreeSet::new);\n        for fv in fvs {\n            self.activate_fv(pkg_id, fk, fv)?;\n        }\n        if !self.processed_deps.insert((pkg_id, fk)) {\n            // Already processed dependencies. There's no need to process them\n            // again. This is primarily to avoid cycles, but also helps speed\n            // things up.\n            //\n            // This is safe because if another package comes along and adds a\n            // feature on this package, it will immediately add it (in\n            // `activate_fv`), and recurse as necessary right then and there.\n            // For example, consider we've already processed our dependencies,\n            // and another package comes along and enables one of our optional\n            // dependencies, it will do so immediately in the\n            // `FeatureValue::DepFeature` branch, and then immediately\n            // recurse into that optional dependency. This also holds true for\n            // features that enable other features.\n            return Ok(());\n        }\n        for (dep_pkg_id, deps) in self.deps(pkg_id, fk)? {\n            for (dep, dep_fk) in deps {\n                if dep.is_optional() {\n                    // Optional dependencies are enabled in `activate_fv` when\n                    // a feature enables it.\n                    continue;\n                }\n                // Recurse into the dependency.\n                let fvs = self.fvs_from_dependency(dep_pkg_id, dep);\n                self.activate_pkg(dep_pkg_id, dep_fk, &fvs)?;\n            }\n        }\n        Ok(())\n    }\n\n    /// Activate a single `FeatureValue` for a package.\n    fn activate_fv(\n        &mut self,\n        pkg_id: PackageId,\n        fk: FeaturesFor,\n        fv: &FeatureValue,\n    ) -> CargoResult<()> {\n        tracing::trace!(\"activate_fv {} {} {}\", pkg_id.name(), fk, fv);\n        match fv {\n            FeatureValue::Feature(f) => {\n                self.activate_rec(pkg_id, fk, *f)?;\n            }\n            FeatureValue::Dep { dep_name } => {\n                self.activate_dependency(pkg_id, fk, *dep_name)?;\n            }\n            FeatureValue::DepFeature {\n                dep_name,\n                dep_feature,\n                weak,\n            } => {\n                self.activate_dep_feature(pkg_id, fk, *dep_name, *dep_feature, *weak)?;\n            }\n        }\n        Ok(())\n    }\n\n    /// Activate the given feature for the given package, and then recursively\n    /// activate any other features that feature enables.\n    fn activate_rec(\n        &mut self,\n        pkg_id: PackageId,\n        fk: FeaturesFor,\n        feature_to_enable: InternedString,\n    ) -> CargoResult<()> {\n        tracing::trace!(\n            \"activate_rec {} {} feat={}\",\n            pkg_id.name(),\n            fk,\n            feature_to_enable\n        );\n        let enabled = self\n            .activated_features\n            .entry((pkg_id, fk.apply_opts(&self.opts)))\n            .or_insert_with(BTreeSet::new);\n        if !enabled.insert(feature_to_enable) {\n            // Already enabled.\n            return Ok(());\n        }\n        let summary = self.resolve.summary(pkg_id);\n        let feature_map = summary.features();\n        let Some(fvs) = feature_map.get(&feature_to_enable) else {\n            // TODO: this should only happen for optional dependencies.\n            // Other cases should be validated by Summary's `build_feature_map`.\n            // Figure out some way to validate this assumption.\n            tracing::debug!(\n                \"pkg {:?} does not define feature {}\",\n                pkg_id,\n                feature_to_enable\n            );\n            return Ok(());\n        };\n        for fv in fvs {\n            self.activate_fv(pkg_id, fk, fv)?;\n        }\n        Ok(())\n    }\n\n    /// Activate a dependency (`dep:dep_name` syntax).\n    fn activate_dependency(\n        &mut self,\n        pkg_id: PackageId,\n        fk: FeaturesFor,\n        dep_name: InternedString,\n    ) -> CargoResult<()> {\n        // Mark this dependency as activated.\n        let save_decoupled = fk.apply_opts(&self.opts);\n        self.activated_dependencies\n            .entry((pkg_id, save_decoupled))\n            .or_default()\n            .insert(dep_name);\n        // Check for any deferred features.\n        let to_enable = self\n            .deferred_weak_dependencies\n            .remove(&(pkg_id, fk, dep_name));\n        // Activate the optional dep.\n        for (dep_pkg_id, deps) in self.deps(pkg_id, fk)? {\n            for (dep, dep_fk) in deps {\n                if dep.name_in_toml() != dep_name {\n                    continue;\n                }\n                if let Some(to_enable) = &to_enable {\n                    for dep_feature in to_enable {\n                        tracing::trace!(\n                            \"activate deferred {} {} -> {}/{}\",\n                            pkg_id.name(),\n                            fk,\n                            dep_name,\n                            dep_feature\n                        );\n                        let fv = FeatureValue::new(*dep_feature);\n                        self.activate_fv(dep_pkg_id, dep_fk, &fv)?;\n                    }\n                }\n                let fvs = self.fvs_from_dependency(dep_pkg_id, dep);\n                self.activate_pkg(dep_pkg_id, dep_fk, &fvs)?;\n            }\n        }\n        Ok(())\n    }\n\n    /// Activate a feature within a dependency (`dep_name/feat_name` syntax).\n    fn activate_dep_feature(\n        &mut self,\n        pkg_id: PackageId,\n        fk: FeaturesFor,\n        dep_name: InternedString,\n        dep_feature: InternedString,\n        weak: bool,\n    ) -> CargoResult<()> {\n        for (dep_pkg_id, deps) in self.deps(pkg_id, fk)? {\n            for (dep, dep_fk) in deps {\n                if dep.name_in_toml() != dep_name {\n                    continue;\n                }\n                if dep.is_optional() {\n                    let save_for_host = fk.apply_opts(&self.opts);\n                    if weak\n                        && !self\n                            .activated_dependencies\n                            .get(&(pkg_id, save_for_host))\n                            .map(|deps| deps.contains(&dep_name))\n                            .unwrap_or(false)\n                    {\n                        // This is weak, but not yet activated. Defer in case\n                        // something comes along later and enables it.\n                        tracing::trace!(\n                            \"deferring feature {} {} -> {}/{}\",\n                            pkg_id.name(),\n                            fk,\n                            dep_name,\n                            dep_feature\n                        );\n                        self.deferred_weak_dependencies\n                            .entry((pkg_id, fk, dep_name))\n                            .or_default()\n                            .insert(dep_feature);\n                        continue;\n                    }\n\n                    // Activate the dependency on self.\n                    let fv = FeatureValue::Dep { dep_name };\n                    self.activate_fv(pkg_id, fk, &fv)?;\n                    if !weak {\n                        // The old behavior before weak dependencies were\n                        // added is to also enables a feature of the same\n                        // name.\n                        //\n                        // Don't enable if the implicit optional dependency\n                        // feature wasn't created due to `dep:` hiding.\n                        // See rust-lang/cargo#10788 and rust-lang/cargo#12130\n                        let summary = self.resolve.summary(pkg_id);\n                        let feature_map = summary.features();\n                        if feature_map.contains_key(&dep_name) {\n                            self.activate_rec(pkg_id, fk, dep_name)?;\n                        }\n                    }\n                }\n                // Activate the feature on the dependency.\n                let fv = FeatureValue::new(dep_feature);\n                self.activate_fv(dep_pkg_id, dep_fk, &fv)?;\n            }\n        }\n        Ok(())\n    }\n\n    /// Returns Vec of `FeatureValues` from a Dependency definition.\n    fn fvs_from_dependency(&self, dep_id: PackageId, dep: &Dependency) -> Vec<FeatureValue> {\n        let summary = self.resolve.summary(dep_id);\n        let feature_map = summary.features();\n        let mut result: Vec<FeatureValue> = dep\n            .features()\n            .iter()\n            .map(|f| FeatureValue::new(*f))\n            .collect();\n        if dep.uses_default_features() && feature_map.contains_key(&INTERNED_DEFAULT) {\n            result.push(FeatureValue::Feature(INTERNED_DEFAULT));\n        }\n        result\n    }\n\n    /// Returns Vec of `FeatureValues` from a set of command-line features.\n    fn fvs_from_requested(\n        &self,\n        pkg_id: PackageId,\n        cli_features: &CliFeatures,\n    ) -> Vec<FeatureValue> {\n        let summary = self.resolve.summary(pkg_id);\n        let feature_map = summary.features();\n\n        let mut result: Vec<FeatureValue> = cli_features.features.iter().cloned().collect();\n        if cli_features.uses_default_features && feature_map.contains_key(&INTERNED_DEFAULT) {\n            result.push(FeatureValue::Feature(INTERNED_DEFAULT));\n        }\n\n        if cli_features.all_features {\n            result.extend(feature_map.keys().map(|k| FeatureValue::Feature(*k)))\n        }\n\n        result\n    }\n\n    /// Returns the dependencies for a package, filtering out inactive targets.\n    fn deps(\n        &mut self,\n        pkg_id: PackageId,\n        fk: FeaturesFor,\n    ) -> CargoResult<Vec<(PackageId, Vec<(&'a Dependency, FeaturesFor)>)>> {\n        // Helper for determining if a platform is activated.\n        fn platform_activated(\n            dep: &Dependency,\n            fk: FeaturesFor,\n            target_data: &RustcTargetData<'_>,\n            requested_targets: &[CompileKind],\n        ) -> bool {\n            // We always count platforms as activated if the target stems from an artifact\n            // dependency's target specification. This triggers in conjunction with\n            // `[target.'cfg(…)'.dependencies]` manifest sections.\n            match (dep.is_build(), fk) {\n                (true, _) | (_, FeaturesFor::HostDep) => {\n                    // We always care about build-dependencies, and they are always\n                    // Host. If we are computing dependencies \"for a build script\",\n                    // even normal dependencies are host-only.\n                    target_data.dep_platform_activated(dep, CompileKind::Host)\n                }\n                (_, FeaturesFor::NormalOrDev) => requested_targets\n                    .iter()\n                    .any(|kind| target_data.dep_platform_activated(dep, *kind)),\n                (_, FeaturesFor::ArtifactDep(target)) => {\n                    target_data.dep_platform_activated(dep, CompileKind::Target(target))\n                }\n            }\n        }\n\n        /// Returns the `FeaturesFor` needed for this dependency.\n        ///\n        /// This includes the `FeaturesFor` for artifact dependencies, which\n        /// might specify multiple targets.\n        fn artifact_features_for(\n            this: &mut FeatureResolver<'_, '_>,\n            pkg_id: PackageId,\n            dep: &Dependency,\n            lib_fk: FeaturesFor,\n            unstable_json_spec: bool,\n        ) -> CargoResult<Vec<FeaturesFor>> {\n            let Some(artifact) = dep.artifact() else {\n                return Ok(vec![lib_fk]);\n            };\n            let mut result = Vec::new();\n            let host_triple = this.target_data.rustc.host;\n            // Not all targets may be queried before resolution since artifact\n            // dependencies and per-pkg-targets are not immediately known.\n            let mut activate_target = |target| {\n                let name = dep.name_in_toml();\n                this.target_data\n                    .merge_compile_kind(CompileKind::Target(target))\n                    .with_context(|| {\n                        format!(\n                            \"failed to determine target information for target `{target}`.\\n  \\\n                             Artifact dependency `{name}` in package `{pkg_id}` requires building \\\n                             for `{target}`\",\n                            target = target.rustc_target()\n                        )\n                    })\n            };\n\n            if let Some(target) = artifact.target() {\n                match target {\n                    ArtifactTarget::Force(target) => {\n                        activate_target(target)?;\n                        result.push(FeaturesFor::ArtifactDep(target))\n                    }\n                    // FIXME: this needs to interact with the `default-target`\n                    // and `forced-target` values of the dependency\n                    ArtifactTarget::BuildDependencyAssumeTarget => {\n                        for kind in this.requested_targets {\n                            let target = match kind {\n                                CompileKind::Host => {\n                                    CompileTarget::new(&host_triple, unstable_json_spec).unwrap()\n                                }\n                                CompileKind::Target(target) => *target,\n                            };\n                            activate_target(target)?;\n                            result.push(FeaturesFor::ArtifactDep(target));\n                        }\n                    }\n                }\n            }\n            if artifact.is_lib() || artifact.target().is_none() {\n                result.push(lib_fk);\n            }\n            Ok(result)\n        }\n\n        let unstable_json_spec = self.ws.gctx().cli_unstable().json_target_spec;\n        self.resolve\n            .deps(pkg_id)\n            .map(|(dep_id, deps)| {\n                let deps = deps\n                    .iter()\n                    .filter(|dep| {\n                        if dep.platform().is_some()\n                            && self.opts.ignore_inactive_targets\n                            && !platform_activated(\n                                dep,\n                                fk,\n                                self.target_data,\n                                self.requested_targets,\n                            )\n                        {\n                            return false;\n                        }\n                        if self.opts.decouple_dev_deps && dep.kind() == DepKind::Development {\n                            return false;\n                        }\n                        true\n                    })\n                    .collect_vec() // collect because the next closure mutably borrows `self.target_data`\n                    .into_iter()\n                    .map(|dep| {\n                        // Each `dep`endency can be built for multiple targets. For one, it\n                        // may be a library target which is built as initially configured\n                        // by `fk`. If it appears as build dependency, it must be built\n                        // for the host.\n                        //\n                        // It may also be an artifact dependency,\n                        // which could be built either\n                        //\n                        //  - for a specified (aka 'forced') target, specified by\n                        //    `dep = { …, target = <triple>` }`\n                        //  - as an artifact for use in build dependencies that should\n                        //    build for whichever `--target`s are specified\n                        //  - like a library would be built\n                        //\n                        // Generally, the logic for choosing a target for dependencies is\n                        // unaltered and used to determine how to build non-artifacts,\n                        // artifacts without target specification and no library,\n                        // or an artifacts library.\n                        //\n                        // All this may result in a dependency being built multiple times\n                        // for various targets which are either specified in the manifest\n                        // or on the cargo command-line.\n                        let lib_fk = if fk != FeaturesFor::HostDep\n                            && self.track_for_host\n                            && (dep.is_build() || self.has_proc_macro_lib(dep_id))\n                        {\n                            FeaturesFor::HostDep\n                        } else {\n                            fk\n                        };\n\n                        let dep_fks =\n                            artifact_features_for(self, pkg_id, dep, lib_fk, unstable_json_spec)?;\n                        Ok(dep_fks.into_iter().map(move |dep_fk| (dep, dep_fk)))\n                    })\n                    .flatten_ok()\n                    .collect::<CargoResult<Vec<_>>>()?;\n                Ok((dep_id, deps))\n            })\n            .filter(|res| res.as_ref().map_or(true, |(_id, deps)| !deps.is_empty()))\n            .collect()\n    }\n\n    /// Compare the activated features to the resolver. Used for testing.\n    fn compare(&self) {\n        let mut found = false;\n        for ((pkg_id, dep_kind), features) in &self.activated_features {\n            let r_features = self.resolve.features(*pkg_id);\n            if !r_features.iter().eq(features.iter()) {\n                crate::drop_eprintln!(\n                    self.ws.gctx(),\n                    \"{}/{:?} features mismatch\\nresolve: {:?}\\nnew: {:?}\\n\",\n                    pkg_id,\n                    dep_kind,\n                    r_features,\n                    features\n                );\n                found = true;\n            }\n        }\n        if found {\n            panic!(\"feature mismatch\");\n        }\n    }\n\n    /// Whether the given package has any proc macro target, including proc-macro examples.\n    fn has_any_proc_macro(&self, package_id: PackageId) -> bool {\n        self.package_set\n            .get_one(package_id)\n            .expect(\"packages downloaded\")\n            .proc_macro()\n    }\n\n    /// Whether the given package is a proc macro lib target.\n    ///\n    /// This is useful for checking if a dependency is a proc macro,\n    /// as it is not possible to depend on a non-lib target as a proc-macro.\n    fn has_proc_macro_lib(&self, package_id: PackageId) -> bool {\n        self.package_set\n            .get_one(package_id)\n            .expect(\"packages downloaded\")\n            .library()\n            .map(|lib| lib.proc_macro())\n            .unwrap_or_default()\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/resolver/mod.rs",
    "content": "//! Resolution of the entire dependency graph for a crate.\n//!\n//! This module implements the core logic in taking the world of crates and\n//! constraints and creating a resolved graph with locked versions for all\n//! crates and their dependencies. This is separate from the registry module\n//! which is more worried about discovering crates from various sources, this\n//! module just uses the Registry trait as a source to learn about crates from.\n//!\n//! Actually solving a constraint graph is an NP-hard problem. This algorithm\n//! is basically a nice heuristic to make sure we get roughly the best answer\n//! most of the time. The constraints that we're working with are:\n//!\n//! 1. Each crate can have any number of dependencies. Each dependency can\n//!    declare a version range that it is compatible with.\n//! 2. Crates can be activated with multiple version (e.g., show up in the\n//!    dependency graph twice) so long as each pairwise instance have\n//!    semver-incompatible versions.\n//!\n//! The algorithm employed here is fairly simple, we simply do a DFS, activating\n//! the \"newest crate\" (highest version) first and then going to the next\n//! option. The heuristics we employ are:\n//!\n//! * Never try to activate a crate version which is incompatible. This means we\n//!   only try crates which will actually satisfy a dependency and we won't ever\n//!   try to activate a crate that's semver compatible with something else\n//!   activated (as we're only allowed to have one) nor try to activate a crate\n//!   that has the same links attribute as something else\n//!   activated.\n//! * Always try to activate the highest version crate first. The default\n//!   dependency in Cargo (e.g., when you write `foo = \"0.1.2\"`) is\n//!   semver-compatible, so selecting the highest version possible will allow us\n//!   to hopefully satisfy as many dependencies at once.\n//!\n//! Beyond that, what's implemented below is just a naive backtracking version\n//! which should in theory try all possible combinations of dependencies and\n//! versions to see if one works. The first resolution that works causes\n//! everything to bail out immediately and return success, and only if *nothing*\n//! works do we actually return an error up the stack.\n//!\n//! Resolution is currently performed twice\n//! 1. With all features enabled (this is what gets saved to `Cargo.lock`)\n//! 2. With only the specific features the user selected on the command-line. Ideally this\n//!    run will get removed in the future when transitioning to the new feature resolver.\n//!\n//! A new feature-specific resolver was added in 2020 which adds more sophisticated feature\n//! resolution. It is located in the [`features`] module. The original dependency resolver still\n//! performs feature unification, as it can help reduce the dependencies it has to consider during\n//! resolution (rather than assuming every optional dependency of every package is enabled).\n//! Checking if a feature is enabled must go through the new feature resolver.\n//!\n//! ## Performance\n//!\n//! Note that this is a relatively performance-critical portion of Cargo. The\n//! data that we're processing is proportional to the size of the dependency\n//! graph, which can often be quite large (e.g., take a look at Servo). To make\n//! matters worse the DFS algorithm we're implemented is inherently quite\n//! inefficient. When we add the requirement of backtracking on top it means\n//! that we're implementing something that probably shouldn't be allocating all\n//! over the place.\n\nuse std::collections::{BTreeMap, HashMap, HashSet};\nuse std::rc::Rc;\nuse std::time::{Duration, Instant};\n\nuse tracing::{debug, trace};\n\nuse crate::core::PackageIdSpec;\nuse crate::core::{Dependency, PackageId, Registry, Summary};\nuse crate::util::context::GlobalContext;\nuse crate::util::errors::CargoResult;\nuse crate::util::network::PollExt;\n\nuse self::context::ResolverContext;\nuse self::dep_cache::RegistryQueryer;\nuse self::features::RequestedFeatures;\nuse self::types::{ConflictMap, ConflictReason, DepsFrame};\nuse self::types::{FeaturesSet, RcVecIter, RemainingDeps, ResolverProgress};\n\npub use self::errors::{ActivateError, ActivateResult, ResolveError};\npub use self::features::{CliFeatures, ForceAllTargets, HasDevUnits};\npub use self::resolve::{Resolve, ResolveVersion};\npub use self::types::{ResolveBehavior, ResolveOpts};\npub use self::version_prefs::{VersionOrdering, VersionPreferences};\n\nmod conflict_cache;\nmod context;\nmod dep_cache;\npub(crate) mod encode;\npub(crate) mod errors;\npub mod features;\nmod resolve;\nmod types;\nmod version_prefs;\n\n/// Builds the list of all packages required to build the first argument.\n///\n/// * `summaries` - the list of package summaries along with how to resolve\n///   their features. This is a list of all top-level packages that are intended\n///   to be part of the lock file (resolve output). These typically are a list\n///   of all workspace members.\n///\n/// * `replacements` - this is a list of `[replace]` directives found in the\n///   root of the workspace. The list here is a `PackageIdSpec` of what to\n///   replace and a `Dependency` to replace that with. In general it's not\n///   recommended to use `[replace]` any more and use `[patch]` instead, which\n///   is supported elsewhere.\n///\n/// * `registry` - this is the source from which all package summaries are\n///   loaded. It's expected that this is extensively configured ahead of time\n///   and is idempotent with our requests to it (aka returns the same results\n///   for the same query every time). Typically this is an instance of a\n///   `PackageRegistry`.\n///\n/// * `version_prefs` - this represents a preference for some versions over others,\n///   based on the lock file or other reasons such as `[patch]`es.\n///\n/// * `resolve_version` - this controls how the lockfile will be serialized.\n///\n/// * `config` - a location to print warnings and such, or `None` if no warnings\n///   should be printed\n#[tracing::instrument(skip_all)]\npub fn resolve(\n    summaries: &[(Summary, ResolveOpts)],\n    replacements: &[(PackageIdSpec, Dependency)],\n    registry: &mut impl Registry,\n    version_prefs: &VersionPreferences,\n    resolve_version: ResolveVersion,\n    gctx: Option<&GlobalContext>,\n) -> CargoResult<Resolve> {\n    let first_version = match gctx {\n        Some(config) if config.cli_unstable().direct_minimal_versions => {\n            Some(VersionOrdering::MinimumVersionsFirst)\n        }\n        _ => None,\n    };\n    let mut registry = RegistryQueryer::new(registry, replacements, version_prefs);\n\n    // Global cache of the reasons for each time we backtrack.\n    let mut past_conflicting_activations = conflict_cache::ConflictCache::new();\n\n    let resolver_ctx = loop {\n        let resolver_ctx = activate_deps_loop(\n            &mut registry,\n            summaries,\n            first_version,\n            gctx,\n            &mut past_conflicting_activations,\n        )?;\n        if registry.reset_pending() {\n            break resolver_ctx;\n        } else {\n            registry.registry.block_until_ready()?;\n        }\n    };\n\n    let mut cksums = HashMap::new();\n    for (summary, _) in resolver_ctx.activations.values() {\n        let cksum = summary.checksum().map(|s| s.to_string());\n        cksums.insert(summary.package_id(), cksum);\n    }\n    let graph = resolver_ctx.graph();\n    let replacements = resolver_ctx.resolve_replacements(&registry);\n    let features = resolver_ctx\n        .resolve_features\n        .iter()\n        .map(|(k, v)| (*k, v.iter().cloned().collect()))\n        .collect();\n    let summaries = resolver_ctx\n        .activations\n        .into_iter()\n        .map(|(_key, (summary, _age))| (summary.package_id(), summary))\n        .collect();\n    let resolve = Resolve::new(\n        graph,\n        replacements,\n        features,\n        cksums,\n        BTreeMap::new(),\n        Vec::new(),\n        resolve_version,\n        summaries,\n    );\n\n    check_cycles(&resolve)?;\n    check_duplicate_pkgs_in_lockfile(&resolve)?;\n    trace!(\"resolved: {:?}\", resolve);\n\n    Ok(resolve)\n}\n\n/// Recursively activates the dependencies for `summaries`, in depth-first order,\n/// backtracking across possible candidates for each dependency as necessary.\n///\n/// If all dependencies can be activated and resolved to a version in the\n/// dependency graph, `cx` is returned.\nfn activate_deps_loop(\n    registry: &mut RegistryQueryer<'_, impl Registry>,\n    summaries: &[(Summary, ResolveOpts)],\n    first_version: Option<VersionOrdering>,\n    gctx: Option<&GlobalContext>,\n    past_conflicting_activations: &mut conflict_cache::ConflictCache,\n) -> CargoResult<ResolverContext> {\n    let mut resolver_ctx = ResolverContext::new();\n    let mut backtrack_stack = Vec::new();\n    let mut remaining_deps = RemainingDeps::new();\n\n    // Activate all the initial summaries to kick off some work.\n    for (summary, opts) in summaries {\n        debug!(\"initial activation: {}\", summary.package_id());\n        let res = activate(\n            &mut resolver_ctx,\n            registry,\n            None,\n            summary.clone(),\n            first_version,\n            opts,\n        );\n        match res {\n            Ok(Some((frame, _))) => remaining_deps.push(frame),\n            Ok(None) => (),\n            Err(ActivateError::Fatal(e)) => return Err(e),\n            Err(ActivateError::Conflict(_, _)) => panic!(\"bad error from activate\"),\n        }\n    }\n\n    let mut printed = ResolverProgress::new();\n\n    // Main resolution loop, this is the workhorse of the resolution algorithm.\n    //\n    // You'll note that a few stacks are maintained on the side, which might\n    // seem odd when this algorithm looks like it could be implemented\n    // recursively. While correct, this is implemented iteratively to avoid\n    // blowing the stack (the recursion depth is proportional to the size of the\n    // input).\n    //\n    // The general sketch of this loop is to run until there are no dependencies\n    // left to activate, and for each dependency to attempt to activate all of\n    // its own dependencies in turn. The `backtrack_stack` is a side table of\n    // backtracking states where if we hit an error we can return to in order to\n    // attempt to continue resolving.\n    while let Some((just_here_for_the_error_messages, frame)) =\n        remaining_deps.pop_most_constrained()\n    {\n        let (mut parent, (mut dep, candidates, mut features)) = frame;\n\n        // If we spend a lot of time here (we shouldn't in most cases) then give\n        // a bit of a visual indicator as to what we're doing.\n        printed.shell_status(gctx)?;\n\n        trace!(\n            \"{}[{}]>{} {} candidates\",\n            parent.name(),\n            resolver_ctx.age,\n            dep.package_name(),\n            candidates.len()\n        );\n\n        let just_here_for_the_error_messages = just_here_for_the_error_messages\n            && past_conflicting_activations\n                .conflicting(&resolver_ctx, &dep)\n                .is_some();\n\n        let mut remaining_candidates = RemainingCandidates::new(&candidates);\n\n        // `conflicting_activations` stores all the reasons we were unable to\n        // activate candidates. One of these reasons will have to go away for\n        // backtracking to find a place to restart. It is also the list of\n        // things to explain in the error message if we fail to resolve.\n        //\n        // This is a map of package ID to a reason why that packaged caused a\n        // conflict for us.\n        let mut conflicting_activations = ConflictMap::new();\n\n        // When backtracking we don't fully update `conflicting_activations`\n        // especially for the cases that we didn't make a backtrack frame in the\n        // first place. This `backtracked` var stores whether we are continuing\n        // from a restored backtrack frame so that we can skip caching\n        // `conflicting_activations` in `past_conflicting_activations`\n        let mut backtracked = false;\n\n        loop {\n            let next = remaining_candidates.next(&mut conflicting_activations, &resolver_ctx);\n\n            let (candidate, has_another) = next.ok_or(()).or_else(|_| {\n                // If we get here then our `remaining_candidates` was just\n                // exhausted, so `dep` failed to activate.\n                //\n                // It's our job here to backtrack, if possible, and find a\n                // different candidate to activate. If we can't find any\n                // candidates whatsoever then it's time to bail entirely.\n                trace!(\n                    \"{}[{}]>{} -- no candidates\",\n                    parent.name(),\n                    resolver_ctx.age,\n                    dep.package_name()\n                );\n\n                // Use our list of `conflicting_activations` to add to our\n                // global list of past conflicting activations, effectively\n                // globally poisoning `dep` if `conflicting_activations` ever\n                // shows up again. We'll use the `past_conflicting_activations`\n                // below to determine if a dependency is poisoned and skip as\n                // much work as possible.\n                //\n                // If we're only here for the error messages then there's no\n                // need to try this as this dependency is already known to be\n                // bad.\n                //\n                // As we mentioned above with the `backtracked` variable if this\n                // local is set to `true` then our `conflicting_activations` may\n                // not be right, so we can't push into our global cache.\n                let mut generalize_conflicting_activations = None;\n                if !just_here_for_the_error_messages && !backtracked {\n                    past_conflicting_activations.insert(&dep, &conflicting_activations);\n                    if let Some(c) = generalize_conflicting(\n                        &resolver_ctx,\n                        registry,\n                        past_conflicting_activations,\n                        &parent,\n                        &dep,\n                        &conflicting_activations,\n                    ) {\n                        generalize_conflicting_activations = Some(c);\n                    }\n                }\n\n                match find_candidate(\n                    &resolver_ctx,\n                    &mut backtrack_stack,\n                    &parent,\n                    backtracked,\n                    generalize_conflicting_activations\n                        .as_ref()\n                        .unwrap_or(&conflicting_activations),\n                ) {\n                    Some((candidate, has_another, frame)) => {\n                        // Reset all of our local variables used with the\n                        // contents of `frame` to complete our backtrack.\n                        resolver_ctx = frame.context;\n                        remaining_deps = frame.remaining_deps;\n                        remaining_candidates = frame.remaining_candidates;\n                        parent = frame.parent;\n                        dep = frame.dep;\n                        features = frame.features;\n                        conflicting_activations = frame.conflicting_activations;\n                        backtracked = true;\n                        Ok((candidate, has_another))\n                    }\n                    None => {\n                        debug!(\"no candidates found\");\n                        Err(errors::activation_error(\n                            &resolver_ctx,\n                            registry.registry,\n                            &parent,\n                            &dep,\n                            &conflicting_activations,\n                            &candidates,\n                            gctx,\n                        ))\n                    }\n                }\n            })?;\n\n            // If we're only here for the error messages then we know that this\n            // activation will fail one way or another. To that end if we've got\n            // more candidates we want to fast-forward to the last one as\n            // otherwise we'll just backtrack here anyway (helping us to skip\n            // some work).\n            if just_here_for_the_error_messages && !backtracked && has_another {\n                continue;\n            }\n\n            // We have a `candidate`. Create a `BacktrackFrame` so we can add it\n            // to the `backtrack_stack` later if activation succeeds.\n            //\n            // Note that if we don't actually have another candidate then there\n            // will be nothing to backtrack to so we skip construction of the\n            // frame. This is a relatively important optimization as a number of\n            // the `clone` calls below can be quite expensive, so we avoid them\n            // if we can.\n            let backtrack = if has_another {\n                Some(BacktrackFrame {\n                    context: ResolverContext::clone(&resolver_ctx),\n                    remaining_deps: remaining_deps.clone(),\n                    remaining_candidates: remaining_candidates.clone(),\n                    parent: Summary::clone(&parent),\n                    dep: Dependency::clone(&dep),\n                    features: Rc::clone(&features),\n                    conflicting_activations: conflicting_activations.clone(),\n                })\n            } else {\n                None\n            };\n\n            let pid = candidate.package_id();\n            let opts = ResolveOpts {\n                dev_deps: false,\n                features: RequestedFeatures::DepFeatures {\n                    features: Rc::clone(&features),\n                    uses_default_features: dep.uses_default_features(),\n                },\n            };\n            trace!(\n                \"{}[{}]>{} trying {}\",\n                parent.name(),\n                resolver_ctx.age,\n                dep.package_name(),\n                candidate.version()\n            );\n            let first_version = None; // this is an indirect dependency\n            let res = activate(\n                &mut resolver_ctx,\n                registry,\n                Some((&parent, &dep)),\n                candidate,\n                first_version,\n                &opts,\n            );\n\n            let successfully_activated = match res {\n                // Success! We've now activated our `candidate` in our context\n                // and we're almost ready to move on. We may want to scrap this\n                // frame in the end if it looks like it's not going to end well,\n                // so figure that out here.\n                Ok(Some((mut frame, dur))) => {\n                    printed.elapsed(dur);\n\n                    // Our `frame` here is a new package with its own list of\n                    // dependencies. Do a sanity check here of all those\n                    // dependencies by cross-referencing our global\n                    // `past_conflicting_activations`. Recall that map is a\n                    // global cache which lists sets of packages where, when\n                    // activated, the dependency is unresolvable.\n                    //\n                    // If any our frame's dependencies fit in that bucket,\n                    // aka known unresolvable, then we extend our own set of\n                    // conflicting activations with theirs. We can do this\n                    // because the set of conflicts we found implies the\n                    // dependency can't be activated which implies that we\n                    // ourselves can't be activated, so we know that they\n                    // conflict with us.\n                    let mut has_past_conflicting_dep = just_here_for_the_error_messages;\n                    if !has_past_conflicting_dep {\n                        if let Some(conflicting) =\n                            frame\n                                .remaining_siblings\n                                .remaining()\n                                .find_map(|(new_dep, _, _)| {\n                                    past_conflicting_activations.conflicting(&resolver_ctx, new_dep)\n                                })\n                        {\n                            // If one of our deps is known unresolvable\n                            // then we will not succeed.\n                            // How ever if we are part of the reason that\n                            // one of our deps conflicts then\n                            // we can make a stronger statement\n                            // because we will definitely be activated when\n                            // we try our dep.\n                            conflicting_activations.extend(\n                                conflicting\n                                    .iter()\n                                    .filter(|&(p, _)| p != &pid)\n                                    .map(|(&p, r)| (p, r.clone())),\n                            );\n\n                            has_past_conflicting_dep = true;\n                        }\n                    }\n                    // If any of `remaining_deps` are known unresolvable with\n                    // us activated, then we extend our own set of\n                    // conflicting activations with theirs and its parent. We can do this\n                    // because the set of conflicts we found implies the\n                    // dependency can't be activated which implies that we\n                    // ourselves are incompatible with that dep, so we know that deps\n                    // parent conflict with us.\n                    if !has_past_conflicting_dep {\n                        if let Some(known_related_bad_deps) =\n                            past_conflicting_activations.dependencies_conflicting_with(pid)\n                        {\n                            if let Some((other_parent, conflict)) = remaining_deps\n                                .iter()\n                                // for deps related to us\n                                .filter(|(_, other_dep)| known_related_bad_deps.contains(other_dep))\n                                .filter_map(|(other_parent, other_dep)| {\n                                    past_conflicting_activations\n                                        .find_conflicting(&resolver_ctx, &other_dep, Some(pid))\n                                        .map(|con| (other_parent, con))\n                                })\n                                .next()\n                            {\n                                let rel = conflict.get(&pid).unwrap().clone();\n\n                                // The conflict we found is\n                                // \"other dep will not succeed if we are activated.\"\n                                // We want to add\n                                // \"our dep will not succeed if other dep is in remaining_deps\"\n                                // but that is not how the cache is set up.\n                                // So we add the less general but much faster,\n                                // \"our dep will not succeed if other dep's parent is activated\".\n                                conflicting_activations.extend(\n                                    conflict\n                                        .iter()\n                                        .filter(|&(p, _)| p != &pid)\n                                        .map(|(&p, r)| (p, r.clone())),\n                                );\n                                conflicting_activations.insert(other_parent, rel);\n                                has_past_conflicting_dep = true;\n                            }\n                        }\n                    }\n\n                    // Ok if we're in a \"known failure\" state for this frame we\n                    // may want to skip it altogether though. We don't want to\n                    // skip it though in the case that we're displaying error\n                    // messages to the user!\n                    //\n                    // Here we need to figure out if the user will see if we\n                    // skipped this candidate (if it's known to fail, aka has a\n                    // conflicting dep and we're the last candidate). If we're\n                    // here for the error messages, we can't skip it (but we can\n                    // prune extra work). If we don't have any candidates in our\n                    // backtrack stack then we're the last line of defense, so\n                    // we'll want to present an error message for sure.\n                    let activate_for_error_message = has_past_conflicting_dep && !has_another && {\n                        just_here_for_the_error_messages || {\n                            find_candidate(\n                                &resolver_ctx,\n                                &mut backtrack_stack.clone(),\n                                &parent,\n                                backtracked,\n                                &conflicting_activations,\n                            )\n                            .is_none()\n                        }\n                    };\n\n                    // If we're only here for the error messages then we know\n                    // one of our candidate deps will fail, meaning we will\n                    // fail and that none of the backtrack frames will find a\n                    // candidate that will help. Consequently let's clean up the\n                    // no longer needed backtrack frames.\n                    if activate_for_error_message {\n                        backtrack_stack.clear();\n                    }\n\n                    // If we don't know for a fact that we'll fail or if we're\n                    // just here for the error message then we push this frame\n                    // onto our list of to-be-resolve, which will generate more\n                    // work for us later on.\n                    //\n                    // Otherwise we're guaranteed to fail and were not here for\n                    // error messages, so we skip work and don't push anything\n                    // onto our stack.\n                    frame.just_for_error_messages = has_past_conflicting_dep;\n                    if !has_past_conflicting_dep || activate_for_error_message {\n                        remaining_deps.push(frame);\n                        true\n                    } else {\n                        trace!(\n                            \"{}[{}]>{} skipping {} \",\n                            parent.name(),\n                            resolver_ctx.age,\n                            dep.package_name(),\n                            pid.version()\n                        );\n                        false\n                    }\n                }\n\n                // This candidate's already activated, so there's no extra work\n                // for us to do. Let's keep going.\n                Ok(None) => true,\n\n                // We failed with a super fatal error (like a network error), so\n                // bail out as quickly as possible as we can't reliably\n                // backtrack from errors like these\n                Err(ActivateError::Fatal(e)) => return Err(e),\n\n                // We failed due to a bland conflict, bah! Record this in our\n                // frame's list of conflicting activations as to why this\n                // candidate failed, and then move on.\n                Err(ActivateError::Conflict(id, reason)) => {\n                    conflicting_activations.insert(id, reason);\n                    false\n                }\n            };\n\n            // If we've successfully activated then save off the backtrack frame\n            // if one was created, and otherwise break out of the inner\n            // activation loop as we're ready to move to the next dependency\n            if successfully_activated {\n                backtrack_stack.extend(backtrack);\n                break;\n            }\n\n            // We've failed to activate this dependency, oh dear! Our call to\n            // `activate` above may have altered our `cx` local variable, so\n            // restore it back if we've got a backtrack frame.\n            //\n            // If we don't have a backtrack frame then we're just using the `cx`\n            // for error messages anyway so we can live with a little\n            // imprecision.\n            if let Some(b) = backtrack {\n                resolver_ctx = b.context;\n            }\n        }\n\n        // Ok phew, that loop was a big one! If we've broken out then we've\n        // successfully activated a candidate. Our stacks are all in place that\n        // we're ready to move on to the next dependency that needs activation,\n        // so loop back to the top of the function here.\n    }\n\n    Ok(resolver_ctx)\n}\n\n/// Attempts to activate the summary `candidate` in the context `cx`.\n///\n/// This function will pull dependency summaries from the registry provided, and\n/// the dependencies of the package will be determined by the `opts` provided.\n/// If `candidate` was activated, this function returns the dependency frame to\n/// iterate through next.\nfn activate(\n    cx: &mut ResolverContext,\n    registry: &mut RegistryQueryer<'_, impl Registry>,\n    parent: Option<(&Summary, &Dependency)>,\n    candidate: Summary,\n    first_version: Option<VersionOrdering>,\n    opts: &ResolveOpts,\n) -> ActivateResult<Option<(DepsFrame, Duration)>> {\n    let candidate_pid = candidate.package_id();\n    cx.age += 1;\n    if let Some((parent, dep)) = parent {\n        let parent_pid = parent.package_id();\n        // add an edge from candidate to parent in the parents graph\n        cx.parents\n            .link(candidate_pid, parent_pid)\n            // and associate dep with that edge\n            .insert(dep.clone());\n    }\n\n    let activated = cx.flag_activated(&candidate, opts, parent)?;\n\n    let candidate = match registry.replacement_summary(candidate_pid) {\n        Some(replace) => {\n            // Note the `None` for parent here since `[replace]` is a bit wonky\n            // and doesn't activate the same things that `[patch]` typically\n            // does. TBH it basically cause panics in the test suite if\n            // `parent` is passed through here and `[replace]` is otherwise\n            // on life support so it's not critical to fix bugs anyway per se.\n            if cx.flag_activated(replace, opts, None)? && activated {\n                return Ok(None);\n            }\n            trace!(\n                \"activating {} (replacing {})\",\n                replace.package_id(),\n                candidate_pid\n            );\n            replace.clone()\n        }\n        None => {\n            if activated {\n                return Ok(None);\n            }\n            trace!(\"activating {}\", candidate_pid);\n            candidate\n        }\n    };\n\n    let now = Instant::now();\n    let (used_features, deps) = &*registry.build_deps(\n        cx,\n        parent.map(|p| p.0.package_id()),\n        &candidate,\n        opts,\n        first_version,\n    )?;\n\n    // Record what list of features is active for this package.\n    if !used_features.is_empty() {\n        Rc::make_mut(\n            cx.resolve_features\n                .entry(candidate.package_id())\n                .or_default(),\n        )\n        .extend(used_features);\n    }\n\n    let frame = DepsFrame {\n        parent: candidate,\n        just_for_error_messages: false,\n        remaining_siblings: RcVecIter::new(Rc::clone(deps)),\n    };\n    Ok(Some((frame, now.elapsed())))\n}\n\n#[derive(Clone)]\nstruct BacktrackFrame {\n    context: ResolverContext,\n    remaining_deps: RemainingDeps,\n    remaining_candidates: RemainingCandidates,\n    parent: Summary,\n    dep: Dependency,\n    features: FeaturesSet,\n    conflicting_activations: ConflictMap,\n}\n\n/// A helper \"iterator\" used to extract candidates within a current `Context` of\n/// a dependency graph.\n///\n/// This struct doesn't literally implement the `Iterator` trait (requires a few\n/// more inputs) but in general acts like one. Each `RemainingCandidates` is\n/// created with a list of candidates to choose from. When attempting to iterate\n/// over the list of candidates only *valid* candidates are returned. Validity\n/// is defined within a `Context`.\n///\n/// Candidates passed to `new` may not be returned from `next` as they could be\n/// filtered out, and as they are filtered the causes will be added to `conflicting_prev_active`.\n#[derive(Clone)]\nstruct RemainingCandidates {\n    remaining: RcVecIter<Summary>,\n    // This is an inlined peekable generator\n    has_another: Option<Summary>,\n}\n\nimpl RemainingCandidates {\n    fn new(candidates: &Rc<Vec<Summary>>) -> RemainingCandidates {\n        RemainingCandidates {\n            remaining: RcVecIter::new(Rc::clone(candidates)),\n            has_another: None,\n        }\n    }\n\n    /// Attempts to find another candidate to check from this list.\n    ///\n    /// This method will attempt to move this iterator forward, returning a\n    /// candidate that's possible to activate. The `cx` argument is the current\n    /// context which determines validity for candidates returned, and the `dep`\n    /// is the dependency listing that we're activating for.\n    ///\n    /// If successful a `(Candidate, bool)` pair will be returned. The\n    /// `Candidate` is the candidate to attempt to activate, and the `bool` is\n    /// an indicator of whether there are remaining candidates to try of if\n    /// we've reached the end of iteration.\n    ///\n    /// If we've reached the end of the iterator here then `Err` will be\n    /// returned. The error will contain a map of package ID to conflict reason,\n    /// where each package ID caused a candidate to be filtered out from the\n    /// original list for the reason listed.\n    fn next(\n        &mut self,\n        conflicting_prev_active: &mut ConflictMap,\n        cx: &ResolverContext,\n    ) -> Option<(Summary, bool)> {\n        for b in self.remaining.iter() {\n            let b_id = b.package_id();\n\n            // The condition for being a valid candidate relies on\n            // semver. Cargo dictates that you can't duplicate multiple\n            // semver-compatible versions of a crate. For example we can't\n            // simultaneously activate `foo 1.0.2` and `foo 1.2.0`. We can,\n            // however, activate `1.0.2` and `2.0.0`.\n            //\n            // Here we throw out our candidate if it's *compatible*, yet not\n            // equal, to all previously activated versions.\n            if let Some((a, _)) = cx.activations.get(&b_id.as_activations_key()) {\n                if a != b {\n                    conflicting_prev_active\n                        .entry(a.package_id())\n                        .or_insert(ConflictReason::Semver);\n                    continue;\n                }\n            }\n\n            // Otherwise the `links` key in the manifest dictates that there's only one\n            // package in a dependency graph, globally, with that particular\n            // `links` key. If this candidate links to something that's already\n            // linked to by a different package then we've gotta skip this.\n            if let Some(link) = b.links() {\n                if let Some(&a) = cx.links.get(&link) {\n                    if a != b_id {\n                        conflicting_prev_active\n                            .entry(a)\n                            .or_insert_with(|| ConflictReason::Links(link));\n                        continue;\n                    }\n                }\n            }\n\n            // Well if we made it this far then we've got a valid dependency. We\n            // want this iterator to be inherently \"peekable\" so we don't\n            // necessarily return the item just yet. Instead we stash it away to\n            // get returned later, and if we replaced something then that was\n            // actually the candidate to try first so we return that.\n            if let Some(r) = self.has_another.replace(b.clone()) {\n                return Some((r, true));\n            }\n        }\n\n        // Alright we've entirely exhausted our list of candidates. If we've got\n        // something stashed away return that here (also indicating that there's\n        // nothing else).\n        self.has_another.take().map(|r| (r, false))\n    }\n}\n\n/// Attempts to find a new conflict that allows a `find_candidate` better then the input one.\n/// It will add the new conflict to the cache if one is found.\nfn generalize_conflicting(\n    cx: &ResolverContext,\n    registry: &mut RegistryQueryer<'_, impl Registry>,\n    past_conflicting_activations: &mut conflict_cache::ConflictCache,\n    parent: &Summary,\n    dep: &Dependency,\n    conflicting_activations: &ConflictMap,\n) -> Option<ConflictMap> {\n    // We need to determine the `ContextAge` that this `conflicting_activations` will jump to, and why.\n    let (backtrack_critical_age, backtrack_critical_id) = shortcircuit_max(\n        conflicting_activations\n            .keys()\n            .map(|&c| cx.is_active(c).map(|a| (a, c))),\n    )?;\n    let backtrack_critical_reason: ConflictReason =\n        conflicting_activations[&backtrack_critical_id].clone();\n\n    if cx\n        .parents\n        .is_path_from_to(&parent.package_id(), &backtrack_critical_id)\n    {\n        // We are a descendant of the trigger of the problem.\n        // The best generalization of this is to let things bubble up\n        // and let `backtrack_critical_id` figure this out.\n        return None;\n    }\n    // What parents does that critical activation have\n    for (critical_parent, critical_parents_deps) in\n        cx.parents.edges(&backtrack_critical_id).filter(|(p, _)| {\n            // it will only help backjump further if it is older then the critical_age\n            cx.is_active(**p).expect(\"parent not currently active!?\") < backtrack_critical_age\n        })\n    {\n        for critical_parents_dep in critical_parents_deps.iter() {\n            // We only want `first_version.is_some()` for direct dependencies of workspace\n            // members which isn't the case here as this has a `parent`\n            let first_version = None;\n            // A dep is equivalent to one of the things it can resolve to.\n            // Thus, if all the things it can resolve to have already ben determined\n            // to be conflicting, then we can just say that we conflict with the parent.\n            if let Some(others) = registry\n                .query(critical_parents_dep, first_version)\n                .expect(\"an already used dep now pending!?\")\n                .expect(\"an already used dep now error!?\")\n                .iter()\n                .rev() // the last one to be tried is the least likely to be in the cache, so start with that.\n                .map(|other| {\n                    past_conflicting_activations\n                        .find(\n                            dep,\n                            &|id| {\n                                if id == other.package_id() {\n                                    // we are imagining that we used other instead\n                                    Some(backtrack_critical_age)\n                                } else {\n                                    cx.is_active(id)\n                                }\n                            },\n                            Some(other.package_id()),\n                            // we only care about things that are newer then critical_age\n                            backtrack_critical_age,\n                        )\n                        .map(|con| (other.package_id(), con))\n                })\n                .collect::<Option<Vec<(PackageId, &ConflictMap)>>>()\n            {\n                let mut con = conflicting_activations.clone();\n                // It is always valid to combine previously inserted conflicts.\n                // A, B are both known bad states each that can never be activated.\n                // A + B is redundant but can't be activated, as if\n                // A + B is active then A is active and we know that is not ok.\n                for (_, other) in &others {\n                    con.extend(other.iter().map(|(&id, re)| (id, re.clone())));\n                }\n                // Now that we have this combined conflict, we can do a substitution:\n                // A dep is equivalent to one of the things it can resolve to.\n                // So we can remove all the things that it resolves to and replace with the parent.\n                for (other_id, _) in &others {\n                    con.remove(other_id);\n                }\n                con.insert(*critical_parent, backtrack_critical_reason);\n\n                if cfg!(debug_assertions) {\n                    // the entire point is to find an older conflict, so let's make sure we did\n                    let new_age = con\n                        .keys()\n                        .map(|&c| cx.is_active(c).expect(\"not currently active!?\"))\n                        .max()\n                        .unwrap();\n                    assert!(\n                        new_age < backtrack_critical_age,\n                        \"new_age {} < backtrack_critical_age {}\",\n                        new_age,\n                        backtrack_critical_age\n                    );\n                }\n                past_conflicting_activations.insert(dep, &con);\n                return Some(con);\n            }\n        }\n    }\n    None\n}\n\n/// Returns Some of the largest item in the iterator.\n/// Returns None if any of the items are None or the iterator is empty.\nfn shortcircuit_max<I: Ord>(iter: impl Iterator<Item = Option<I>>) -> Option<I> {\n    let mut out = None;\n    for i in iter {\n        if i.is_none() {\n            return None;\n        }\n        out = std::cmp::max(out, i);\n    }\n    out\n}\n\n/// Looks through the states in `backtrack_stack` for dependencies with\n/// remaining candidates. For each one, also checks if rolling back\n/// could change the outcome of the failed resolution that caused backtracking\n/// in the first place. Namely, if we've backtracked past the parent of the\n/// failed dep, or any of the packages flagged as giving us trouble in\n/// `conflicting_activations`.\n///\n/// Read <https://github.com/rust-lang/cargo/pull/4834>\n/// For several more detailed explanations of the logic here.\nfn find_candidate(\n    cx: &ResolverContext,\n    backtrack_stack: &mut Vec<BacktrackFrame>,\n    parent: &Summary,\n    backtracked: bool,\n    conflicting_activations: &ConflictMap,\n) -> Option<(Summary, bool, BacktrackFrame)> {\n    // When we're calling this method we know that `parent` failed to\n    // activate. That means that some dependency failed to get resolved for\n    // whatever reason. Normally, that means that all of those reasons\n    // (plus maybe some extras) are listed in `conflicting_activations`.\n    //\n    // The abnormal situations are things that do not put all of the reasons in `conflicting_activations`:\n    // If we backtracked we do not know how our `conflicting_activations` related to\n    // the cause of that backtrack, so we do not update it.\n    let age = if !backtracked {\n        // we don't have abnormal situations. So we can ask `cx` for how far back we need to go.\n        // If the `conflicting_activations` does not apply to `cx`,\n        // we will just fall back to laboriously trying all possibilities witch\n        // will give us the correct answer.\n        cx.is_conflicting(Some(parent.package_id()), conflicting_activations)\n    } else {\n        None\n    };\n    let mut new_frame = None;\n    if let Some(age) = age {\n        while let Some(frame) = backtrack_stack.pop() {\n            // If all members of `conflicting_activations` are still\n            // active in this back up we know that we're guaranteed to not actually\n            // make any progress. As a result if we hit this condition we can\n            // completely skip this backtrack frame and move on to the next.\n\n            // Above we use `cx` to determine if this is going to be conflicting.\n            // But lets just double check if the `pop`ed frame agrees.\n            let frame_too_new = frame.context.age >= age;\n            debug_assert!(\n                frame\n                    .context\n                    .is_conflicting(Some(parent.package_id()), conflicting_activations)\n                    == frame_too_new.then_some(age)\n            );\n\n            if !frame_too_new {\n                new_frame = Some(frame);\n                break;\n            }\n            trace!(\n                \"{} = \\\"{}\\\" skip as not solving {}: {:?}\",\n                frame.dep.package_name(),\n                frame.dep.version_req(),\n                parent.package_id(),\n                conflicting_activations\n            );\n        }\n    } else {\n        // If we're here then we are in abnormal situations and need to just go one frame at a time.\n        new_frame = backtrack_stack.pop();\n    }\n\n    new_frame.map(|mut frame| {\n        let (candidate, has_another) = frame\n            .remaining_candidates\n            .next(&mut frame.conflicting_activations, &frame.context)\n            .expect(\"why did we save a frame that has no next?\");\n        (candidate, has_another, frame)\n    })\n}\n\nfn check_cycles(resolve: &Resolve) -> CargoResult<()> {\n    // Perform a simple cycle check by visiting all nodes.\n    // We visit each node at most once and we keep\n    // track of the path through the graph as we walk it. If we walk onto the\n    // same node twice that's a cycle.\n    let mut checked = HashSet::with_capacity(resolve.len());\n    let mut path = Vec::with_capacity(4);\n    let mut visited = HashSet::with_capacity(4);\n    for pkg in resolve.iter() {\n        if !checked.contains(&pkg) {\n            visit(&resolve, pkg, &mut visited, &mut path, &mut checked)?\n        }\n    }\n    return Ok(());\n\n    fn visit(\n        resolve: &Resolve,\n        id: PackageId,\n        visited: &mut HashSet<PackageId>,\n        path: &mut Vec<PackageId>,\n        checked: &mut HashSet<PackageId>,\n    ) -> CargoResult<()> {\n        if !visited.insert(id) {\n            // We found a cycle and need to construct an error. Performance is no longer top priority.\n            let iter = path.iter().rev().scan(id, |child, parent| {\n                let dep = resolve.transitive_deps_not_replaced(*parent).find_map(\n                    |(dep_id, transitive_dep)| {\n                        (*child == dep_id || Some(*child) == resolve.replacement(dep_id))\n                            .then_some(transitive_dep)\n                    },\n                );\n                *child = *parent;\n                Some((parent, dep))\n            });\n            let iter = std::iter::once((&id, None)).chain(iter);\n            let describe_path = errors::describe_path(iter);\n            anyhow::bail!(\n                \"cyclic package dependency: package `{id}` depends on itself. Cycle:\\n{describe_path}\"\n            );\n        }\n\n        if checked.insert(id) {\n            path.push(id);\n            for (dep_id, _transitive_dep) in resolve.transitive_deps_not_replaced(id) {\n                visit(resolve, dep_id, visited, path, checked)?;\n                if let Some(replace_id) = resolve.replacement(dep_id) {\n                    visit(resolve, replace_id, visited, path, checked)?;\n                }\n            }\n            path.pop();\n        }\n\n        visited.remove(&id);\n        Ok(())\n    }\n}\n\n/// Checks that packages are unique when written to lock file.\n///\n/// When writing package ID's to lock file, we apply lossy encoding. In\n/// particular, we don't store paths of path dependencies. That means that\n/// *different* packages may collide in the lock file, hence this check.\nfn check_duplicate_pkgs_in_lockfile(resolve: &Resolve) -> CargoResult<()> {\n    let mut unique_pkg_ids = HashMap::new();\n    let state = encode::EncodeState::new(resolve);\n    for pkg_id in resolve.iter() {\n        let encodable_pkd_id = encode::encodable_package_id(pkg_id, &state, resolve.version());\n        if let Some(prev_pkg_id) = unique_pkg_ids.insert(encodable_pkd_id, pkg_id) {\n            anyhow::bail!(\n                \"package collision in the lockfile: packages {} and {} are different, \\\n                 but only one can be written to lockfile unambiguously\",\n                prev_pkg_id,\n                pkg_id\n            )\n        }\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/core/resolver/resolve.rs",
    "content": "use cargo_util_schemas::core::PartialVersion;\nuse cargo_util_schemas::manifest::RustVersion;\n\nuse crate::core::dependency::DepKind;\nuse crate::core::{Dependency, PackageId, PackageIdSpec, PackageIdSpecQuery, Summary, Target};\nuse crate::util::Graph;\nuse crate::util::errors::CargoResult;\nuse crate::util::interning::InternedString;\nuse cargo_util_schemas::lockfile::TomlLockfileMetadata;\nuse std::borrow::Borrow;\nuse std::collections::{HashMap, HashSet};\nuse std::fmt;\n\n/// Represents a fully-resolved package dependency graph. Each node in the graph\n/// is a package and edges represent dependencies between packages.\n///\n/// Each instance of `Resolve` also understands the full set of features used\n/// for each package.\npub struct Resolve {\n    /// A graph, whose vertices are packages and edges are dependency specifications\n    /// from `Cargo.toml`. We need a `HashSet` here because the same package\n    /// might be present in both `[dependencies]` and `[build-dependencies]`.\n    graph: Graph<PackageId, HashSet<Dependency>>,\n    /// Replacements from the `[replace]` table.\n    replacements: HashMap<PackageId, PackageId>,\n    /// Inverted version of `replacements`.\n    reverse_replacements: HashMap<PackageId, PackageId>,\n    /// Features enabled for a given package.\n    features: HashMap<PackageId, Vec<InternedString>>,\n    /// Checksum for each package. A SHA256 hash of the `.crate` file used to\n    /// validate the correct crate file is used. This is `None` for sources\n    /// that do not use `.crate` files, like path or git dependencies.\n    checksums: HashMap<PackageId, Option<String>>,\n    /// \"Unknown\" metadata. This is a collection of extra, unrecognized data\n    /// found in the `[metadata]` section of `Cargo.lock`, preserved for\n    /// forwards compatibility.\n    metadata: TomlLockfileMetadata,\n    /// `[patch]` entries that did not match anything, preserved in\n    /// `Cargo.lock` as the `[[patch.unused]]` table array. Tracking unused\n    /// patches helps prevent Cargo from being forced to re-update the\n    /// registry every time it runs, and keeps the resolve in a locked state\n    /// so it doesn't re-resolve the unused entries.\n    unused_patches: Vec<PackageId>,\n    /// A map from packages to a set of their public dependencies\n    public_dependencies: HashMap<PackageId, HashSet<PackageId>>,\n    /// Version of the `Cargo.lock` format, see\n    /// `cargo::core::resolver::encode` for more.\n    version: ResolveVersion,\n    summaries: HashMap<PackageId, Summary>,\n}\n\n/// A version to indicate how a `Cargo.lock` should be serialized.\n///\n/// When creating a new lockfile, the version in [`ResolveVersion::default`] is used.\n/// If an old version of lockfile already exists, it will stay as-is.\n///\n/// It's important that if a new version is added that this is not updated\n/// until *at least* the support for the version is in the stable release of Rust.\n///\n/// This resolve version will be used for all new lock files, for example\n/// those generated by `cargo update` (update everything) or building after\n/// a `cargo new` (where no lock file previously existed). This is also used\n/// for *updated* lock files such as when a dependency is added or when a\n/// version requirement changes. In this situation Cargo's updating the lock\n/// file anyway so it takes the opportunity to bump the lock file version\n/// forward.\n///\n/// It's theorized that we can add more here over time to track larger changes\n/// to the `Cargo.lock` format, but we've yet to see how that strategy pans out.\n#[derive(PartialEq, Eq, Clone, Copy, Debug, PartialOrd, Ord)]\npub enum ResolveVersion {\n    /// Historical baseline for when this abstraction was added.\n    V1,\n    /// A more compact format, more amenable to avoiding source-control merge\n    /// conflicts. The `dependencies` arrays are compressed and checksums are\n    /// listed inline.\n    ///\n    /// * Introduced in 2019 in version 1.38.\n    /// * New lockfiles use V2 by default from 1.41 to 1.52.\n    V2,\n    /// A format that explicitly lists a `version` at the top of the file as\n    /// well as changing how git dependencies are encoded. Dependencies with\n    /// `branch = \"master\"` are no longer encoded the same way as those without\n    /// branch specifiers.\n    ///\n    /// * Introduced in 2020 in version 1.47.\n    /// * New lockfiles use V3 by default from in 1.53 to 1.82.\n    V3,\n    /// `SourceId` URL serialization is aware of URL encoding. For example,\n    /// `?branch=foo bar` is now encoded as `?branch=foo+bar` and can be decoded\n    /// back and forth correctly.\n    ///\n    /// * Introduced in 2024 in version 1.78.\n    /// * New lockfiles use V4 by default starting in 1.83.\n    V4,\n    /// Unstable. Will collect a certain amount of changes and then go.\n    ///\n    /// Changes made:\n    V5,\n}\n\nimpl ResolveVersion {\n    /// Gets the default lockfile version.\n    ///\n    /// This is intended to be private.\n    /// You shall use [`ResolveVersion::with_rust_version`] always.\n    ///\n    /// Update this and the description of enum variants of [`ResolveVersion`]\n    /// when we're changing the default lockfile version.\n    fn default() -> ResolveVersion {\n        ResolveVersion::V4\n    }\n\n    /// The maximum version of lockfile made into the stable channel.\n    ///\n    /// Any version larger than this needs `-Znext-lockfile-bump` to enable.\n    ///\n    /// Update this when you're going to stabilize a new lockfile format.\n    pub fn max_stable() -> ResolveVersion {\n        ResolveVersion::V4\n    }\n\n    /// Gets the default lockfile version for the given Rust version.\n    pub fn with_rust_version(rust_version: Option<&RustVersion>) -> Self {\n        let Some(rust_version) = rust_version else {\n            return ResolveVersion::default();\n        };\n\n        let rust = |major, minor| -> RustVersion {\n            PartialVersion {\n                major,\n                minor: Some(minor),\n                patch: None,\n                pre: None,\n                build: None,\n            }\n            .try_into()\n            .unwrap()\n        };\n\n        if rust_version >= &rust(1, 83) {\n            ResolveVersion::V4\n        } else if rust_version >= &rust(1, 53) {\n            ResolveVersion::V3\n        } else if rust_version >= &rust(1, 41) {\n            ResolveVersion::V2\n        } else {\n            ResolveVersion::V1\n        }\n    }\n}\n\nimpl Resolve {\n    pub fn new(\n        graph: Graph<PackageId, HashSet<Dependency>>,\n        replacements: HashMap<PackageId, PackageId>,\n        features: HashMap<PackageId, Vec<InternedString>>,\n        checksums: HashMap<PackageId, Option<String>>,\n        metadata: TomlLockfileMetadata,\n        unused_patches: Vec<PackageId>,\n        version: ResolveVersion,\n        summaries: HashMap<PackageId, Summary>,\n    ) -> Resolve {\n        let reverse_replacements = replacements.iter().map(|(&p, &r)| (r, p)).collect();\n        let public_dependencies = graph\n            .iter()\n            .map(|p| {\n                let public_deps = graph\n                    .edges(p)\n                    .filter(|(_, deps)| {\n                        deps.iter()\n                            .any(|d| d.kind() == DepKind::Normal && d.is_public())\n                    })\n                    .map(|(dep_package, _)| *dep_package)\n                    .collect::<HashSet<PackageId>>();\n\n                (*p, public_deps)\n            })\n            .collect();\n\n        Resolve {\n            graph,\n            replacements,\n            features,\n            checksums,\n            metadata,\n            unused_patches,\n            reverse_replacements,\n            public_dependencies,\n            version,\n            summaries,\n        }\n    }\n\n    /// Resolves one of the paths from the given dependent package up to\n    /// the root.\n    pub fn path_to_top<'a>(\n        &'a self,\n        pkg: &'a PackageId,\n    ) -> Vec<(&'a PackageId, Option<&'a HashSet<Dependency>>)> {\n        self.graph.path_to_top(pkg)\n    }\n\n    pub fn register_used_patches<'a>(&mut self, patches: impl Iterator<Item = &'a Summary>) {\n        for summary in patches {\n            if !self.graph.contains(&summary.package_id()) {\n                self.unused_patches.push(summary.package_id())\n            };\n        }\n    }\n\n    pub fn merge_from(&mut self, previous: &Resolve) -> CargoResult<()> {\n        // Given a previous instance of resolve, it should be forbidden to ever\n        // have a checksums which *differ*. If the same package ID has differing\n        // checksums, then something has gone wrong such as:\n        //\n        // * Something got seriously corrupted\n        // * A \"mirror\" isn't actually a mirror as some changes were made\n        // * A replacement source wasn't actually a replacement, some changes\n        //   were made\n        //\n        // In all of these cases, we want to report an error to indicate that\n        // something is awry. Normal execution (esp just using crates.io) should\n        // never run into this.\n        for (id, cksum) in previous.checksums.iter() {\n            if let Some(mine) = self.checksums.get(id) {\n                if mine == cksum {\n                    continue;\n                }\n\n                // If the previous checksum wasn't calculated, the current\n                // checksum is `Some`. This may indicate that a source was\n                // erroneously replaced or was replaced with something that\n                // desires stronger checksum guarantees than can be afforded\n                // elsewhere.\n                if cksum.is_none() {\n                    anyhow::bail!(\n                        \"\\\nchecksum for `{}` was not previously calculated, but a checksum could now \\\nbe calculated\n\nthis could be indicative of a few possible situations:\n\n    * the source `{}` did not previously support checksums,\n      but was replaced with one that does\n    * newer Cargo implementations know how to checksum this source, but this\n      older implementation does not\n    * the lock file is corrupt\n\",\n                        id,\n                        id.source_id()\n                    )\n\n                // If our checksum hasn't been calculated, then it could mean\n                // that future Cargo figured out how to checksum something or\n                // more realistically we were overridden with a source that does\n                // not have checksums.\n                } else if mine.is_none() {\n                    anyhow::bail!(\n                        \"\\\nchecksum for `{}` could not be calculated, but a checksum is listed in \\\nthe existing lock file\n\nthis could be indicative of a few possible situations:\n\n    * the source `{}` supports checksums,\n      but was replaced with one that doesn't\n    * the lock file is corrupt\n\nunable to verify that `{0}` is the same as when the lockfile was generated\n\",\n                        id,\n                        id.source_id()\n                    )\n\n                // If the checksums aren't equal, and neither is None, then they\n                // must both be Some, in which case the checksum now differs.\n                // That's quite bad!\n                } else {\n                    anyhow::bail!(\n                        \"\\\nchecksum for `{}` changed between lock files\n\nthis could be indicative of a few possible errors:\n\n    * the lock file is corrupt\n    * a replacement source in use (e.g., a mirror) returned a different checksum\n    * the source itself may be corrupt in one way or another\n\nunable to verify that `{0}` is the same as when the lockfile was generated\n\",\n                        id\n                    );\n                }\n            }\n        }\n\n        // Be sure to just copy over any unknown metadata.\n        self.metadata = previous.metadata.clone();\n\n        // Preserve the lockfile encoding where possible to avoid lockfile churn\n        self.version = previous.version;\n\n        Ok(())\n    }\n\n    pub fn contains<Q: ?Sized>(&self, k: &Q) -> bool\n    where\n        PackageId: Borrow<Q>,\n        Q: Ord + Eq,\n    {\n        self.graph.contains(k)\n    }\n\n    pub fn sort(&self) -> Vec<PackageId> {\n        self.graph.sort()\n    }\n\n    pub fn iter(&self) -> impl Iterator<Item = PackageId> + '_ {\n        self.graph.iter().cloned()\n    }\n\n    pub fn len(&self) -> usize {\n        self.graph.len()\n    }\n\n    pub fn deps(&self, pkg: PackageId) -> impl Iterator<Item = (PackageId, &HashSet<Dependency>)> {\n        self.deps_not_replaced(pkg)\n            .map(move |(id, deps)| (self.replacement(id).unwrap_or(id), deps))\n    }\n\n    pub fn deps_not_replaced(\n        &self,\n        pkg: PackageId,\n    ) -> impl Iterator<Item = (PackageId, &HashSet<Dependency>)> {\n        self.graph.edges(&pkg).map(|(id, deps)| (*id, deps))\n    }\n\n    // Only edges that are transitive, filtering out edges between a crate and its dev-dependency\n    // since that doesn't count for cycles.\n    pub fn transitive_deps_not_replaced(\n        &self,\n        pkg: PackageId,\n    ) -> impl Iterator<Item = (PackageId, &Dependency)> {\n        self.graph.edges(&pkg).filter_map(|(id, deps)| {\n            deps.iter()\n                .find(|d| d.is_transitive())\n                .map(|transitive_dep| (*id, transitive_dep))\n        })\n    }\n\n    pub fn replacement(&self, pkg: PackageId) -> Option<PackageId> {\n        self.replacements.get(&pkg).cloned()\n    }\n\n    pub fn replacements(&self) -> &HashMap<PackageId, PackageId> {\n        &self.replacements\n    }\n\n    pub fn features(&self, pkg: PackageId) -> &[InternedString] {\n        self.features.get(&pkg).map(|v| &**v).unwrap_or(&[])\n    }\n\n    /// This is only here for legacy support, it will be removed when\n    /// switching to the new feature resolver.\n    pub fn features_clone(&self) -> HashMap<PackageId, Vec<InternedString>> {\n        self.features.clone()\n    }\n\n    pub fn is_public_dep(&self, pkg: PackageId, dep: PackageId) -> bool {\n        self.public_dependencies\n            .get(&pkg)\n            .map(|public_deps| public_deps.contains(&dep))\n            .unwrap_or_else(|| panic!(\"Unknown dependency {:?} for package {:?}\", dep, pkg))\n    }\n\n    pub fn query(&self, spec: &str) -> CargoResult<PackageId> {\n        PackageIdSpec::query_str(spec, self.iter())\n    }\n\n    pub fn specs_to_ids(&self, specs: &[PackageIdSpec]) -> CargoResult<Vec<PackageId>> {\n        specs.iter().map(|s| s.query(self.iter())).collect()\n    }\n\n    pub fn unused_patches(&self) -> &[PackageId] {\n        &self.unused_patches\n    }\n\n    pub fn checksums(&self) -> &HashMap<PackageId, Option<String>> {\n        &self.checksums\n    }\n\n    pub fn set_checksum(&mut self, pkg_id: PackageId, checksum: String) {\n        self.checksums.insert(pkg_id, Some(checksum));\n    }\n\n    pub fn metadata(&self) -> &TomlLockfileMetadata {\n        &self.metadata\n    }\n\n    pub fn extern_crate_name_and_dep_name(\n        &self,\n        from: PackageId,\n        to: PackageId,\n        to_target: &Target,\n    ) -> CargoResult<(InternedString, Option<InternedString>)> {\n        let empty_set: HashSet<Dependency> = HashSet::new();\n        let deps = if from == to {\n            &empty_set\n        } else {\n            self.dependencies_listed(from, to)\n        };\n\n        let target_crate_name = || (to_target.crate_name(), None);\n        let mut name_pairs = deps.iter().map(|d| {\n            d.explicit_name_in_toml()\n                .map(|s| (s.as_str().replace(\"-\", \"_\"), Some(s)))\n                .unwrap_or_else(target_crate_name)\n        });\n        let (extern_crate_name, dep_name) = name_pairs.next().unwrap_or_else(target_crate_name);\n        for (n, _) in name_pairs {\n            anyhow::ensure!(\n                n == extern_crate_name,\n                \"the crate `{}` depends on crate `{}` multiple times with different names\",\n                from,\n                to,\n            );\n        }\n        Ok((extern_crate_name.into(), dep_name))\n    }\n\n    fn dependencies_listed(&self, from: PackageId, to: PackageId) -> &HashSet<Dependency> {\n        // We've got a dependency on `from` to `to`, but this dependency edge\n        // may be affected by [replace]. If the `to` package is listed as the\n        // target of a replacement (aka the key of a reverse replacement map)\n        // then we try to find our dependency edge through that. If that fails\n        // then we go down below assuming it's not replaced.\n        //\n        // Note that we don't treat `from` as if it's been replaced because\n        // that's where the dependency originates from, and we only replace\n        // targets of dependencies not the originator.\n        if let Some(replace) = self.reverse_replacements.get(&to) {\n            if let Some(deps) = self.graph.edge(&from, replace) {\n                return deps;\n            }\n        }\n        match self.graph.edge(&from, &to) {\n            Some(ret) => ret,\n            None => panic!(\"no Dependency listed for `{}` => `{}`\", from, to),\n        }\n    }\n\n    /// Returns the version of the encoding that's being used for this lock\n    /// file.\n    pub fn version(&self) -> ResolveVersion {\n        self.version\n    }\n\n    pub fn set_version(&mut self, version: ResolveVersion) {\n        self.version = version;\n    }\n\n    pub fn summary(&self, pkg_id: PackageId) -> &Summary {\n        &self.summaries[&pkg_id]\n    }\n}\n\nimpl PartialEq for Resolve {\n    fn eq(&self, other: &Resolve) -> bool {\n        macro_rules! compare {\n            ($($fields:ident)* | $($ignored:ident)*) => {\n                let Resolve { $($fields,)* $($ignored: _,)* } = self;\n                $($fields == &other.$fields)&&*\n            }\n        }\n        compare! {\n            // fields to compare\n            graph replacements reverse_replacements features\n            checksums metadata unused_patches public_dependencies summaries\n            |\n            // fields to ignore\n            version\n        }\n    }\n}\n\nimpl fmt::Debug for Resolve {\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        writeln!(fmt, \"graph: {:?}\", self.graph)?;\n        writeln!(fmt, \"\\nfeatures: {{\")?;\n        for (pkg, features) in &self.features {\n            writeln!(fmt, \"  {}: {:?}\", pkg, features)?;\n        }\n        write!(fmt, \"}}\")\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/resolver/types.rs",
    "content": "use super::features::{CliFeatures, RequestedFeatures};\nuse crate::core::{Dependency, PackageId, SourceId, Summary};\nuse crate::util::GlobalContext;\nuse crate::util::errors::CargoResult;\nuse crate::util::interning::InternedString;\nuse std::cmp::Ordering;\nuse std::collections::{BTreeMap, BTreeSet};\nuse std::num::NonZeroU64;\nuse std::rc::Rc;\nuse std::time::{Duration, Instant};\n\npub struct ResolverProgress {\n    ticks: u16,\n    start: Instant,\n    time_to_print: Duration,\n    printed: bool,\n    deps_time: Duration,\n    /// Provides an escape hatch for machine with slow CPU for debugging and\n    /// testing Cargo itself.\n    /// See [rust-lang/cargo#6596](https://github.com/rust-lang/cargo/pull/6596) for more.\n    #[cfg(debug_assertions)]\n    slow_cpu_multiplier: u64,\n}\n\nimpl ResolverProgress {\n    pub fn new() -> ResolverProgress {\n        ResolverProgress {\n            ticks: 0,\n            start: Instant::now(),\n            time_to_print: Duration::from_millis(500),\n            printed: false,\n            deps_time: Duration::new(0, 0),\n            // Some CI setups are much slower then the equipment used by Cargo itself.\n            // Architectures that do not have a modern processor, hardware emulation, etc.\n            // In the test code we have `slow_cpu_multiplier`, but that is not accessible here.\n            #[cfg(debug_assertions)]\n            // ALLOWED: For testing cargo itself only. However, it was communicated as an public\n            // interface to other developers, so keep it as-is, shouldn't add `__CARGO` prefix.\n            #[allow(clippy::disallowed_methods)]\n            slow_cpu_multiplier: std::env::var(\"CARGO_TEST_SLOW_CPU_MULTIPLIER\")\n                .ok()\n                .and_then(|m| m.parse().ok())\n                .unwrap_or(1),\n        }\n    }\n    pub fn shell_status(&mut self, gctx: Option<&GlobalContext>) -> CargoResult<()> {\n        // If we spend a lot of time here (we shouldn't in most cases) then give\n        // a bit of a visual indicator as to what we're doing. Only enable this\n        // when stderr is a tty (a human is likely to be watching) to ensure we\n        // get deterministic output otherwise when observed by tools.\n        //\n        // Also note that we hit this loop a lot, so it's fairly performance\n        // sensitive. As a result try to defer a possibly expensive operation\n        // like `Instant::now` by only checking every N iterations of this loop\n        // to amortize the cost of the current time lookup.\n        self.ticks += 1;\n        if let Some(config) = gctx {\n            if config.shell().is_err_tty()\n                && !self.printed\n                && self.ticks % 1000 == 0\n                && self.start.elapsed() - self.deps_time > self.time_to_print\n            {\n                self.printed = true;\n                config.shell().status(\"Resolving\", \"dependency graph...\")?;\n            }\n        }\n        #[cfg(debug_assertions)]\n        {\n            // The largest test in our suite takes less then 5000 ticks\n            // with all the algorithm improvements.\n            // If any of them are removed then it takes more than I am willing to measure.\n            // So lets fail the test fast if we have been running for too long.\n            assert!(\n                self.ticks < 50_000,\n                \"got to 50_000 ticks in {:?}\",\n                self.start.elapsed()\n            );\n            // The largest test in our suite takes less then 30 sec\n            // with all the improvements to how fast a tick can go.\n            // If any of them are removed then it takes more than I am willing to measure.\n            // So lets fail the test fast if we have been running for too long.\n            if self.ticks % 1000 == 0 {\n                assert!(\n                    self.start.elapsed() - self.deps_time\n                        < Duration::from_secs(self.slow_cpu_multiplier * 90)\n                );\n            }\n        }\n        Ok(())\n    }\n    pub fn elapsed(&mut self, dur: Duration) {\n        self.deps_time += dur;\n    }\n}\n\n/// The preferred way to store the set of activated features for a package.\n/// This is sorted so that it impls Hash, and owns its contents,\n/// needed so it can be part of the key for caching in the `DepsCache`.\n/// It is also cloned often as part of `Context`, hence the `RC`.\n/// `im-rs::OrdSet` was slower of small sets like this,\n/// but this can change with improvements to std, im, or llvm.\n/// Using a consistent type for this allows us to use the highly\n/// optimized comparison operators like `is_subset` at the interfaces.\npub type FeaturesSet = Rc<BTreeSet<InternedString>>;\n\n/// Resolver behavior, used to opt-in to new behavior that is\n/// backwards-incompatible via the `resolver` field in the manifest.\n#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]\npub enum ResolveBehavior {\n    /// V1 is the original resolver behavior.\n    V1,\n    /// V2 adds the new feature resolver.\n    V2,\n    /// V3 changes version preferences\n    V3,\n}\n\nimpl ResolveBehavior {\n    pub fn from_manifest(resolver: &str) -> CargoResult<ResolveBehavior> {\n        match resolver {\n            \"1\" => Ok(ResolveBehavior::V1),\n            \"2\" => Ok(ResolveBehavior::V2),\n            \"3\" => Ok(ResolveBehavior::V3),\n            s => anyhow::bail!(\n                \"`resolver` setting `{}` is not valid, valid options are \\\"1\\\", \\\"2\\\" or \\\"3\\\"\",\n                s\n            ),\n        }\n    }\n\n    pub fn to_manifest(&self) -> String {\n        match self {\n            ResolveBehavior::V1 => \"1\",\n            ResolveBehavior::V2 => \"2\",\n            ResolveBehavior::V3 => \"3\",\n        }\n        .to_owned()\n    }\n}\n\n/// Options for how the resolve should work.\n#[derive(Clone, Debug, Eq, PartialEq, Hash)]\npub struct ResolveOpts {\n    /// Whether or not dev-dependencies should be included.\n    ///\n    /// This may be set to `false` by things like `cargo install` or `-Z avoid-dev-deps`.\n    /// It also gets set to `false` when activating dependencies in the resolver.\n    pub dev_deps: bool,\n    /// Set of features requested on the command-line.\n    pub features: RequestedFeatures,\n}\n\nimpl ResolveOpts {\n    /// Creates a `ResolveOpts` that resolves everything.\n    pub fn everything() -> ResolveOpts {\n        ResolveOpts {\n            dev_deps: true,\n            features: RequestedFeatures::CliFeatures(CliFeatures::new_all(true)),\n        }\n    }\n\n    pub fn new(dev_deps: bool, features: RequestedFeatures) -> ResolveOpts {\n        ResolveOpts { dev_deps, features }\n    }\n}\n\n/// A key that when stord in a hash map ensures that there is only one\n/// semver compatible version of each crate.\n/// Find the activated version of a crate based on the name, source, and semver compatibility.\n#[derive(Clone, PartialEq, Eq, Debug, Ord, PartialOrd)]\npub struct ActivationsKey(InternedString, SemverCompatibility, SourceId);\n\nimpl ActivationsKey {\n    pub fn new(\n        name: InternedString,\n        ver: SemverCompatibility,\n        source_id: SourceId,\n    ) -> ActivationsKey {\n        ActivationsKey(name, ver, source_id)\n    }\n}\n\nimpl std::hash::Hash for ActivationsKey {\n    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n        self.0.hash(state);\n        self.1.hash(state);\n        // self.2.hash(state); // Packages that only differ by SourceId are rare enough to not be worth hashing\n    }\n}\n\n/// A type that represents when cargo treats two Versions as compatible.\n/// Versions `a` and `b` are compatible if their left-most nonzero digit is the\n/// same.\n#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug, PartialOrd, Ord)]\npub enum SemverCompatibility {\n    Major(NonZeroU64),\n    Minor(NonZeroU64),\n    Patch(u64),\n}\n\nimpl From<&semver::Version> for SemverCompatibility {\n    fn from(ver: &semver::Version) -> Self {\n        if let Some(m) = NonZeroU64::new(ver.major) {\n            return SemverCompatibility::Major(m);\n        }\n        if let Some(m) = NonZeroU64::new(ver.minor) {\n            return SemverCompatibility::Minor(m);\n        }\n        SemverCompatibility::Patch(ver.patch)\n    }\n}\n\nimpl PackageId {\n    pub fn as_activations_key(self) -> ActivationsKey {\n        ActivationsKey(self.name(), self.version().into(), self.source_id())\n    }\n}\n\n#[derive(Clone)]\npub struct DepsFrame {\n    pub parent: Summary,\n    pub just_for_error_messages: bool,\n    pub remaining_siblings: RcVecIter<DepInfo>,\n}\n\nimpl DepsFrame {\n    /// Returns the least number of candidates that any of this frame's siblings\n    /// has.\n    ///\n    /// The `remaining_siblings` array is already sorted with the smallest\n    /// number of candidates at the front, so we just return the number of\n    /// candidates in that entry.\n    fn min_candidates(&self) -> usize {\n        self.remaining_siblings\n            .peek()\n            .map(|(_, candidates, _)| candidates.len())\n            .unwrap_or(0)\n    }\n\n    pub fn flatten(&self) -> impl Iterator<Item = (PackageId, &Dependency)> + '_ {\n        self.remaining_siblings\n            .remaining()\n            .map(move |(d, _, _)| (self.parent.package_id(), d))\n    }\n}\n\nimpl PartialEq for DepsFrame {\n    fn eq(&self, other: &DepsFrame) -> bool {\n        self.just_for_error_messages == other.just_for_error_messages\n            && self.min_candidates() == other.min_candidates()\n    }\n}\n\nimpl Eq for DepsFrame {}\n\nimpl PartialOrd for DepsFrame {\n    fn partial_cmp(&self, other: &DepsFrame) -> Option<Ordering> {\n        Some(self.cmp(other))\n    }\n}\n\nimpl Ord for DepsFrame {\n    fn cmp(&self, other: &DepsFrame) -> Ordering {\n        self.just_for_error_messages\n            .cmp(&other.just_for_error_messages)\n            .reverse()\n            .then_with(|| self.min_candidates().cmp(&other.min_candidates()))\n    }\n}\n\n/// Note that an `OrdSet` is used for the remaining dependencies that need\n/// activation. This set is sorted by how many candidates each dependency has.\n///\n/// This helps us get through super constrained portions of the dependency\n/// graph quickly and hopefully lock down what later larger dependencies can\n/// use (those with more candidates).\n#[derive(Clone)]\npub struct RemainingDeps {\n    /// a monotonic counter, increased for each new insertion.\n    time: u32,\n    /// the data is augmented by the insertion time.\n    /// This insures that no two items will cmp eq.\n    /// Forcing the `OrdSet` into a multi set.\n    data: im_rc::OrdSet<(DepsFrame, u32)>,\n}\n\nimpl RemainingDeps {\n    pub fn new() -> RemainingDeps {\n        RemainingDeps {\n            time: 0,\n            data: im_rc::OrdSet::new(),\n        }\n    }\n    pub fn push(&mut self, x: DepsFrame) {\n        let insertion_time = self.time;\n        self.data.insert((x, insertion_time));\n        self.time += 1;\n    }\n    pub fn pop_most_constrained(&mut self) -> Option<(bool, (Summary, DepInfo))> {\n        while let Some((mut deps_frame, insertion_time)) = self.data.remove_min() {\n            let just_here_for_the_error_messages = deps_frame.just_for_error_messages;\n\n            // Figure out what our next dependency to activate is, and if nothing is\n            // listed then we're entirely done with this frame (yay!) and we can\n            // move on to the next frame.\n            let sibling = deps_frame.remaining_siblings.iter().next().cloned();\n            if let Some(sibling) = sibling {\n                let parent = Summary::clone(&deps_frame.parent);\n                self.data.insert((deps_frame, insertion_time));\n                return Some((just_here_for_the_error_messages, (parent, sibling)));\n            }\n        }\n        None\n    }\n    pub fn iter(&mut self) -> impl Iterator<Item = (PackageId, &Dependency)> + '_ {\n        self.data.iter().flat_map(|(other, _)| other.flatten())\n    }\n}\n\n/// Information about the dependencies for a crate, a tuple of:\n///\n/// (dependency info, candidates, features activated)\npub type DepInfo = (Dependency, Rc<Vec<Summary>>, FeaturesSet);\n\n/// All possible reasons that a package might fail to activate.\n///\n/// We maintain a list of conflicts for error reporting as well as backtracking\n/// purposes. Each reason here is why candidates may be rejected or why we may\n/// fail to resolve a dependency.\n#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]\npub enum ConflictReason {\n    /// There was a semver conflict, for example we tried to activate a package\n    /// 1.0.2 but 1.1.0 was already activated (aka a compatible semver version\n    /// is already activated)\n    Semver,\n\n    /// The `links` key is being violated. For example one crate in the\n    /// dependency graph has `links = \"foo\"` but this crate also had that, and\n    /// we're only allowed one per dependency graph.\n    Links(InternedString),\n\n    /// A dependency listed a feature that wasn't actually available on the\n    /// candidate. For example we tried to activate feature `foo` but the\n    /// candidate we're activating didn't actually have the feature `foo`.\n    MissingFeature(InternedString),\n\n    /// A dependency listed a feature that ended up being a required dependency.\n    /// For example we tried to activate feature `foo` but the\n    /// candidate we're activating didn't actually have the feature `foo`\n    /// it had a dependency `foo` instead.\n    RequiredDependencyAsFeature(InternedString),\n\n    /// A dependency listed a feature for an optional dependency, but that\n    /// optional dependency is \"hidden\" using namespaced `dep:` syntax.\n    NonImplicitDependencyAsFeature(InternedString),\n}\n\nimpl ConflictReason {\n    pub fn is_links(&self) -> bool {\n        matches!(self, ConflictReason::Links(_))\n    }\n\n    pub fn is_missing_feature(&self) -> bool {\n        matches!(self, ConflictReason::MissingFeature(_))\n    }\n\n    pub fn is_required_dependency_as_features(&self) -> bool {\n        matches!(self, ConflictReason::RequiredDependencyAsFeature(_))\n    }\n}\n\n/// A list of packages that have gotten in the way of resolving a dependency.\n/// If resolving a dependency fails then this represents an incompatibility,\n/// that dependency will never be resolve while all of these packages are active.\n/// This is useless if the packages can't be simultaneously activated for other reasons.\npub type ConflictMap = BTreeMap<PackageId, ConflictReason>;\n\npub struct RcVecIter<T> {\n    vec: Rc<Vec<T>>,\n    offset: usize,\n}\n\nimpl<T> RcVecIter<T> {\n    pub fn new(vec: Rc<Vec<T>>) -> RcVecIter<T> {\n        RcVecIter { vec, offset: 0 }\n    }\n\n    pub fn peek(&self) -> Option<&T> {\n        self.vec.get(self.offset)\n    }\n\n    pub fn remaining(&self) -> impl Iterator<Item = &T> + '_ {\n        self.vec.get(self.offset..).into_iter().flatten()\n    }\n\n    pub fn iter(&mut self) -> impl Iterator<Item = &T> + '_ {\n        let iter = self.vec.get(self.offset..).into_iter().flatten();\n        // This call to `ìnspect()` is used to increment `self.offset` when iterating the inner `Vec`,\n        // while keeping the `ExactSizeIterator` property.\n        iter.inspect(|_| self.offset += 1)\n    }\n}\n\n// Not derived to avoid `T: Clone`\nimpl<T> Clone for RcVecIter<T> {\n    fn clone(&self) -> RcVecIter<T> {\n        RcVecIter {\n            vec: self.vec.clone(),\n            offset: self.offset,\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/resolver/version_prefs.rs",
    "content": "//! This module implements support for preferring some versions of a package\n//! over other versions.\n\nuse std::cmp::Ordering;\nuse std::collections::{HashMap, HashSet};\n\nuse cargo_util_schemas::core::PartialVersion;\n\nuse crate::core::{Dependency, PackageId, Summary};\nuse crate::util::interning::InternedString;\n\n/// A collection of preferences for particular package versions.\n///\n/// This is built up with [`Self::prefer_package_id`] and [`Self::prefer_dependency`], then used to sort the set of\n/// summaries for a package during resolution via [`Self::sort_summaries`].\n///\n/// As written, a version is either \"preferred\" or \"not preferred\".  Later extensions may\n/// introduce more granular preferences.\n#[derive(Default)]\npub struct VersionPreferences {\n    try_to_use: HashSet<PackageId>,\n    prefer_patch_deps: HashMap<InternedString, HashSet<Dependency>>,\n    version_ordering: VersionOrdering,\n    rust_versions: Vec<PartialVersion>,\n    publish_time: Option<jiff::Timestamp>,\n}\n\n#[derive(Copy, Clone, Default, PartialEq, Eq, Hash, Debug)]\npub enum VersionOrdering {\n    #[default]\n    MaximumVersionsFirst,\n    MinimumVersionsFirst,\n}\n\nimpl VersionPreferences {\n    /// Indicate that the given package (specified as a [`PackageId`]) should be preferred.\n    pub fn prefer_package_id(&mut self, pkg_id: PackageId) {\n        self.try_to_use.insert(pkg_id);\n    }\n\n    /// Indicate that the given package (specified as a [`Dependency`])  should be preferred.\n    pub fn prefer_dependency(&mut self, dep: Dependency) {\n        self.prefer_patch_deps\n            .entry(dep.package_name())\n            .or_insert_with(HashSet::new)\n            .insert(dep);\n    }\n\n    pub fn version_ordering(&mut self, ordering: VersionOrdering) {\n        self.version_ordering = ordering;\n    }\n\n    pub fn rust_versions(&mut self, vers: Vec<PartialVersion>) {\n        self.rust_versions = vers;\n    }\n\n    pub fn publish_time(&mut self, publish_time: jiff::Timestamp) {\n        self.publish_time = Some(publish_time);\n    }\n\n    /// Sort (and filter) the given vector of summaries in-place\n    ///\n    /// Note: all summaries presumed to be for the same package.\n    ///\n    /// Sort order:\n    /// 1. Preferred packages\n    /// 2. Most compatible [`VersionPreferences::rust_versions`]\n    /// 3. `first_version`, falling back to [`VersionPreferences::version_ordering`] when `None`\n    ///\n    /// Filtering:\n    /// - `publish_time`\n    /// - `first_version`\n    pub fn sort_summaries(\n        &self,\n        summaries: &mut Vec<Summary>,\n        first_version: Option<VersionOrdering>,\n    ) {\n        let should_prefer = |pkg_id: &PackageId| {\n            self.try_to_use.contains(pkg_id)\n                || self\n                    .prefer_patch_deps\n                    .get(&pkg_id.name())\n                    .map(|deps| deps.iter().any(|d| d.matches_id(*pkg_id)))\n                    .unwrap_or(false)\n        };\n        if let Some(max_publish_time) = self.publish_time {\n            summaries.retain(|s| {\n                if let Some(summary_publish_time) = s.pubtime() {\n                    summary_publish_time <= max_publish_time\n                } else {\n                    true\n                }\n            });\n        }\n        summaries.sort_unstable_by(|a, b| {\n            let prefer_a = should_prefer(&a.package_id());\n            let prefer_b = should_prefer(&b.package_id());\n            let previous_cmp = prefer_a.cmp(&prefer_b).reverse();\n            if previous_cmp != Ordering::Equal {\n                return previous_cmp;\n            }\n\n            if !self.rust_versions.is_empty() {\n                let a_compat_count = self.msrv_compat_count(a);\n                let b_compat_count = self.msrv_compat_count(b);\n                if b_compat_count != a_compat_count {\n                    return b_compat_count.cmp(&a_compat_count);\n                }\n            }\n\n            let cmp = a.version().cmp(b.version());\n            match first_version.unwrap_or(self.version_ordering) {\n                VersionOrdering::MaximumVersionsFirst => cmp.reverse(),\n                VersionOrdering::MinimumVersionsFirst => cmp,\n            }\n        });\n        if first_version.is_some() && !summaries.is_empty() {\n            let _ = summaries.split_off(1);\n        }\n    }\n\n    fn msrv_compat_count(&self, summary: &Summary) -> usize {\n        let Some(rust_version) = summary.rust_version() else {\n            return self.rust_versions.len();\n        };\n\n        self.rust_versions\n            .iter()\n            .filter(|max| rust_version.is_compatible_with(max))\n            .count()\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use crate::core::SourceId;\n    use std::collections::BTreeMap;\n\n    fn pkgid(name: &str, version: &str) -> PackageId {\n        let src_id =\n            SourceId::from_url(\"registry+https://github.com/rust-lang/crates.io-index\").unwrap();\n        PackageId::try_new(name, version, src_id).unwrap()\n    }\n\n    fn dep(name: &str, version: &str) -> Dependency {\n        let src_id =\n            SourceId::from_url(\"registry+https://github.com/rust-lang/crates.io-index\").unwrap();\n        Dependency::parse(name, Some(version), src_id).unwrap()\n    }\n\n    fn summ(name: &str, version: &str, msrv: Option<&str>) -> Summary {\n        let pkg_id = pkgid(name, version);\n        let features = BTreeMap::new();\n        Summary::new(\n            pkg_id,\n            Vec::new(),\n            &features,\n            None::<&String>,\n            msrv.map(|m| m.parse().unwrap()),\n        )\n        .unwrap()\n    }\n\n    fn describe(summaries: &Vec<Summary>) -> String {\n        let strs: Vec<String> = summaries\n            .iter()\n            .map(|summary| format!(\"{}/{}\", summary.name(), summary.version()))\n            .collect();\n        strs.join(\", \")\n    }\n\n    #[test]\n    fn test_prefer_package_id() {\n        let mut vp = VersionPreferences::default();\n        vp.prefer_package_id(pkgid(\"foo\", \"1.2.3\"));\n\n        let mut summaries = vec![\n            summ(\"foo\", \"1.2.4\", None),\n            summ(\"foo\", \"1.2.3\", None),\n            summ(\"foo\", \"1.1.0\", None),\n            summ(\"foo\", \"1.0.9\", None),\n        ];\n\n        vp.version_ordering(VersionOrdering::MaximumVersionsFirst);\n        vp.sort_summaries(&mut summaries, None);\n        assert_eq!(\n            describe(&summaries),\n            \"foo/1.2.3, foo/1.2.4, foo/1.1.0, foo/1.0.9\".to_string()\n        );\n\n        vp.version_ordering(VersionOrdering::MinimumVersionsFirst);\n        vp.sort_summaries(&mut summaries, None);\n        assert_eq!(\n            describe(&summaries),\n            \"foo/1.2.3, foo/1.0.9, foo/1.1.0, foo/1.2.4\".to_string()\n        );\n    }\n\n    #[test]\n    fn test_prefer_dependency() {\n        let mut vp = VersionPreferences::default();\n        vp.prefer_dependency(dep(\"foo\", \"=1.2.3\"));\n\n        let mut summaries = vec![\n            summ(\"foo\", \"1.2.4\", None),\n            summ(\"foo\", \"1.2.3\", None),\n            summ(\"foo\", \"1.1.0\", None),\n            summ(\"foo\", \"1.0.9\", None),\n        ];\n\n        vp.version_ordering(VersionOrdering::MaximumVersionsFirst);\n        vp.sort_summaries(&mut summaries, None);\n        assert_eq!(\n            describe(&summaries),\n            \"foo/1.2.3, foo/1.2.4, foo/1.1.0, foo/1.0.9\".to_string()\n        );\n\n        vp.version_ordering(VersionOrdering::MinimumVersionsFirst);\n        vp.sort_summaries(&mut summaries, None);\n        assert_eq!(\n            describe(&summaries),\n            \"foo/1.2.3, foo/1.0.9, foo/1.1.0, foo/1.2.4\".to_string()\n        );\n    }\n\n    #[test]\n    fn test_prefer_both() {\n        let mut vp = VersionPreferences::default();\n        vp.prefer_package_id(pkgid(\"foo\", \"1.2.3\"));\n        vp.prefer_dependency(dep(\"foo\", \"=1.1.0\"));\n\n        let mut summaries = vec![\n            summ(\"foo\", \"1.2.4\", None),\n            summ(\"foo\", \"1.2.3\", None),\n            summ(\"foo\", \"1.1.0\", None),\n            summ(\"foo\", \"1.0.9\", None),\n        ];\n\n        vp.version_ordering(VersionOrdering::MaximumVersionsFirst);\n        vp.sort_summaries(&mut summaries, None);\n        assert_eq!(\n            describe(&summaries),\n            \"foo/1.2.3, foo/1.1.0, foo/1.2.4, foo/1.0.9\".to_string()\n        );\n\n        vp.version_ordering(VersionOrdering::MinimumVersionsFirst);\n        vp.sort_summaries(&mut summaries, None);\n        assert_eq!(\n            describe(&summaries),\n            \"foo/1.1.0, foo/1.2.3, foo/1.0.9, foo/1.2.4\".to_string()\n        );\n    }\n\n    #[test]\n    fn test_single_rust_version() {\n        let mut vp = VersionPreferences::default();\n        vp.rust_versions(vec![\"1.50\".parse().unwrap()]);\n\n        let mut summaries = vec![\n            summ(\"foo\", \"1.2.4\", None),\n            summ(\"foo\", \"1.2.3\", Some(\"1.60\")),\n            summ(\"foo\", \"1.2.2\", None),\n            summ(\"foo\", \"1.2.1\", Some(\"1.50\")),\n            summ(\"foo\", \"1.2.0\", None),\n            summ(\"foo\", \"1.1.0\", Some(\"1.40\")),\n            summ(\"foo\", \"1.0.9\", None),\n        ];\n\n        vp.version_ordering(VersionOrdering::MaximumVersionsFirst);\n        vp.sort_summaries(&mut summaries, None);\n        assert_eq!(\n            describe(&summaries),\n            \"foo/1.2.4, foo/1.2.2, foo/1.2.1, foo/1.2.0, foo/1.1.0, foo/1.0.9, foo/1.2.3\"\n                .to_string()\n        );\n\n        vp.version_ordering(VersionOrdering::MinimumVersionsFirst);\n        vp.sort_summaries(&mut summaries, None);\n        assert_eq!(\n            describe(&summaries),\n            \"foo/1.0.9, foo/1.1.0, foo/1.2.0, foo/1.2.1, foo/1.2.2, foo/1.2.4, foo/1.2.3\"\n                .to_string()\n        );\n    }\n\n    #[test]\n    fn test_multiple_rust_versions() {\n        let mut vp = VersionPreferences::default();\n        vp.rust_versions(vec![\"1.45\".parse().unwrap(), \"1.55\".parse().unwrap()]);\n\n        let mut summaries = vec![\n            summ(\"foo\", \"1.2.4\", None),\n            summ(\"foo\", \"1.2.3\", Some(\"1.60\")),\n            summ(\"foo\", \"1.2.2\", None),\n            summ(\"foo\", \"1.2.1\", Some(\"1.50\")),\n            summ(\"foo\", \"1.2.0\", None),\n            summ(\"foo\", \"1.1.0\", Some(\"1.40\")),\n            summ(\"foo\", \"1.0.9\", None),\n        ];\n\n        vp.version_ordering(VersionOrdering::MaximumVersionsFirst);\n        vp.sort_summaries(&mut summaries, None);\n        assert_eq!(\n            describe(&summaries),\n            \"foo/1.2.4, foo/1.2.2, foo/1.2.0, foo/1.1.0, foo/1.0.9, foo/1.2.1, foo/1.2.3\"\n                .to_string()\n        );\n\n        vp.version_ordering(VersionOrdering::MinimumVersionsFirst);\n        vp.sort_summaries(&mut summaries, None);\n        assert_eq!(\n            describe(&summaries),\n            \"foo/1.0.9, foo/1.1.0, foo/1.2.0, foo/1.2.2, foo/1.2.4, foo/1.2.1, foo/1.2.3\"\n                .to_string()\n        );\n    }\n\n    #[test]\n    fn test_empty_summaries() {\n        let vp = VersionPreferences::default();\n        let mut summaries = vec![];\n\n        vp.sort_summaries(&mut summaries, Some(VersionOrdering::MaximumVersionsFirst));\n        assert_eq!(summaries, vec![]);\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/shell.rs",
    "content": "use std::fmt;\nuse std::io::IsTerminal;\nuse std::io::prelude::*;\n\nuse annotate_snippets::renderer::DecorStyle;\nuse annotate_snippets::{Renderer, Report};\nuse anstream::AutoStream;\nuse anstyle::Style;\n\nuse crate::util::errors::CargoResult;\nuse crate::util::style::*;\n\npub use anstyle_hyperlink::Hyperlink;\n\n/// An abstraction around console output that remembers preferences for output\n/// verbosity and color.\npub struct Shell {\n    /// Wrapper around stdout/stderr. This helps with supporting sending\n    /// output to a memory buffer which is useful for tests.\n    output: ShellOut,\n    /// How verbose messages should be.\n    verbosity: Verbosity,\n    /// Flag that indicates the current line needs to be cleared before\n    /// printing. Used when a progress bar is currently displayed.\n    needs_clear: bool,\n}\n\nimpl fmt::Debug for Shell {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self.output {\n            ShellOut::Write(_) => f\n                .debug_struct(\"Shell\")\n                .field(\"verbosity\", &self.verbosity)\n                .finish(),\n            ShellOut::Stream { color_choice, .. } => f\n                .debug_struct(\"Shell\")\n                .field(\"verbosity\", &self.verbosity)\n                .field(\"color_choice\", &color_choice)\n                .finish(),\n        }\n    }\n}\n\nimpl Shell {\n    /// Creates a new shell (color choice and verbosity), defaulting to 'auto' color and verbose\n    /// output.\n    pub fn new() -> Shell {\n        let auto_clr = ColorChoice::CargoAuto;\n        let stdout_choice = auto_clr.to_anstream_color_choice();\n        let stderr_choice = auto_clr.to_anstream_color_choice();\n        Shell {\n            output: ShellOut::Stream {\n                stdout: AutoStream::new(std::io::stdout(), stdout_choice),\n                stderr: AutoStream::new(std::io::stderr(), stderr_choice),\n                color_choice: auto_clr,\n                hyperlinks: supports_hyperlinks(),\n                stderr_tty: std::io::stderr().is_terminal(),\n                stdout_unicode: supports_unicode(&std::io::stdout()),\n                stderr_unicode: supports_unicode(&std::io::stderr()),\n                stderr_term_integration: supports_term_integration(&std::io::stderr()),\n                unstable_flags_rustc_unicode: false,\n            },\n            verbosity: Verbosity::Verbose,\n            needs_clear: false,\n        }\n    }\n\n    /// Creates a shell from a plain writable object, with no color, and max verbosity.\n    pub fn from_write(out: Box<dyn Write + Send + Sync>) -> Shell {\n        Shell {\n            output: ShellOut::Write(AutoStream::never(out)), // strip all formatting on write\n            verbosity: Verbosity::Verbose,\n            needs_clear: false,\n        }\n    }\n\n    /// Prints a message, where the status will have `color` color, and can be justified. The\n    /// messages follows without color.\n    fn print(\n        &mut self,\n        status: &dyn fmt::Display,\n        message: Option<&dyn fmt::Display>,\n        color: &Style,\n        justified: bool,\n    ) -> CargoResult<()> {\n        match self.verbosity {\n            Verbosity::Quiet => Ok(()),\n            _ => {\n                if self.needs_clear {\n                    self.err_erase_line();\n                }\n                self.output\n                    .message_stderr(status, message, color, justified)\n            }\n        }\n    }\n\n    /// Sets whether the next print should clear the current line.\n    pub fn set_needs_clear(&mut self, needs_clear: bool) {\n        self.needs_clear = needs_clear;\n    }\n\n    /// Returns `true` if the `needs_clear` flag is unset.\n    pub fn is_cleared(&self) -> bool {\n        !self.needs_clear\n    }\n\n    /// Returns the width of the terminal in spaces, if any.\n    pub fn err_width(&self) -> TtyWidth {\n        match self.output {\n            ShellOut::Stream {\n                stderr_tty: true, ..\n            } => imp::stderr_width(),\n            _ => TtyWidth::NoTty,\n        }\n    }\n\n    /// Returns `true` if stderr is a tty.\n    pub fn is_err_tty(&self) -> bool {\n        match self.output {\n            ShellOut::Stream { stderr_tty, .. } => stderr_tty,\n            _ => false,\n        }\n    }\n\n    pub fn is_err_term_integration_available(&self) -> bool {\n        if let ShellOut::Stream {\n            stderr_term_integration,\n            ..\n        } = self.output\n        {\n            stderr_term_integration\n        } else {\n            false\n        }\n    }\n\n    /// Gets a reference to the underlying stdout writer.\n    pub fn out(&mut self) -> &mut dyn Write {\n        if self.needs_clear {\n            self.err_erase_line();\n        }\n        self.output.stdout()\n    }\n\n    /// Gets a reference to the underlying stderr writer.\n    pub fn err(&mut self) -> &mut dyn Write {\n        if self.needs_clear {\n            self.err_erase_line();\n        }\n        self.output.stderr()\n    }\n\n    /// Erase from cursor to end of line.\n    pub fn err_erase_line(&mut self) {\n        if self.err_supports_color() {\n            imp::err_erase_line(self);\n            self.needs_clear = false;\n        }\n    }\n\n    /// Shortcut to right-align and color green a status message.\n    pub fn status<T, U>(&mut self, status: T, message: U) -> CargoResult<()>\n    where\n        T: fmt::Display,\n        U: fmt::Display,\n    {\n        self.print(&status, Some(&message), &HEADER, true)\n    }\n\n    pub fn transient_status<T>(&mut self, status: T) -> CargoResult<()>\n    where\n        T: fmt::Display,\n    {\n        self.print(&status, None, &TRANSIENT, true)\n    }\n\n    /// Shortcut to right-align a status message.\n    pub fn status_with_color<T, U>(\n        &mut self,\n        status: T,\n        message: U,\n        color: &Style,\n    ) -> CargoResult<()>\n    where\n        T: fmt::Display,\n        U: fmt::Display,\n    {\n        self.print(&status, Some(&message), color, true)\n    }\n\n    /// Runs the callback only if we are in verbose mode.\n    pub fn verbose<F>(&mut self, mut callback: F) -> CargoResult<()>\n    where\n        F: FnMut(&mut Shell) -> CargoResult<()>,\n    {\n        match self.verbosity {\n            Verbosity::Verbose => callback(self),\n            _ => Ok(()),\n        }\n    }\n\n    /// Runs the callback if we are not in verbose mode.\n    pub fn concise<F>(&mut self, mut callback: F) -> CargoResult<()>\n    where\n        F: FnMut(&mut Shell) -> CargoResult<()>,\n    {\n        match self.verbosity {\n            Verbosity::Verbose => Ok(()),\n            _ => callback(self),\n        }\n    }\n\n    /// Prints a red 'error' message.\n    pub fn error<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {\n        if self.needs_clear {\n            self.err_erase_line();\n        }\n        self.output\n            .message_stderr(&\"error\", Some(&message), &ERROR, false)\n    }\n\n    /// Prints an amber 'warning' message.\n    pub fn warn<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {\n        self.print(&\"warning\", Some(&message), &WARN, false)\n    }\n\n    /// Prints a cyan 'note' message.\n    pub fn note<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {\n        let report = &[annotate_snippets::Group::with_title(\n            annotate_snippets::Level::NOTE.secondary_title(message.to_string()),\n        )];\n        self.print_report(report, false)\n    }\n\n    /// Updates the verbosity of the shell.\n    pub fn set_verbosity(&mut self, verbosity: Verbosity) {\n        self.verbosity = verbosity;\n    }\n\n    /// Gets the verbosity of the shell.\n    pub fn verbosity(&self) -> Verbosity {\n        self.verbosity\n    }\n\n    /// Updates the color choice (always, never, or auto) from a string..\n    pub fn set_color_choice(&mut self, color: Option<&str>) -> CargoResult<()> {\n        if let ShellOut::Stream {\n            stdout,\n            stderr,\n            color_choice,\n            ..\n        } = &mut self.output\n        {\n            let cfg = color\n                .map(|c| c.parse())\n                .transpose()?\n                .unwrap_or(ColorChoice::CargoAuto);\n            *color_choice = cfg;\n            let stdout_choice = cfg.to_anstream_color_choice();\n            let stderr_choice = cfg.to_anstream_color_choice();\n            *stdout = AutoStream::new(std::io::stdout(), stdout_choice);\n            *stderr = AutoStream::new(std::io::stderr(), stderr_choice);\n        }\n        Ok(())\n    }\n\n    pub fn set_unicode(&mut self, yes: bool) -> CargoResult<()> {\n        if let ShellOut::Stream {\n            stdout_unicode,\n            stderr_unicode,\n            ..\n        } = &mut self.output\n        {\n            *stdout_unicode = yes;\n            *stderr_unicode = yes;\n        }\n        Ok(())\n    }\n\n    pub fn set_hyperlinks(&mut self, yes: bool) -> CargoResult<()> {\n        if let ShellOut::Stream { hyperlinks, .. } = &mut self.output {\n            *hyperlinks = yes;\n        }\n        Ok(())\n    }\n\n    pub fn out_unicode(&self) -> bool {\n        match &self.output {\n            ShellOut::Write(_) => true,\n            ShellOut::Stream { stdout_unicode, .. } => *stdout_unicode,\n        }\n    }\n\n    pub fn err_unicode(&self) -> bool {\n        match &self.output {\n            ShellOut::Write(_) => true,\n            ShellOut::Stream { stderr_unicode, .. } => *stderr_unicode,\n        }\n    }\n\n    /// Gets the current color choice.\n    ///\n    /// If we are not using a color stream, this will always return `Never`, even if the color\n    /// choice has been set to something else.\n    pub fn color_choice(&self) -> ColorChoice {\n        match self.output {\n            ShellOut::Stream { color_choice, .. } => color_choice,\n            ShellOut::Write(_) => ColorChoice::Never,\n        }\n    }\n\n    /// Whether the shell supports color.\n    pub fn err_supports_color(&self) -> bool {\n        match &self.output {\n            ShellOut::Write(_) => false,\n            ShellOut::Stream { stderr, .. } => supports_color(stderr.current_choice()),\n        }\n    }\n\n    pub fn out_supports_color(&self) -> bool {\n        match &self.output {\n            ShellOut::Write(_) => false,\n            ShellOut::Stream { stdout, .. } => supports_color(stdout.current_choice()),\n        }\n    }\n\n    pub fn out_hyperlink<D: fmt::Display>(&self, url: D) -> Hyperlink<D> {\n        let supports_hyperlinks = match &self.output {\n            ShellOut::Write(_) => false,\n            ShellOut::Stream {\n                stdout, hyperlinks, ..\n            } => stdout.current_choice() == anstream::ColorChoice::AlwaysAnsi && *hyperlinks,\n        };\n        if supports_hyperlinks {\n            Hyperlink::with_url(url)\n        } else {\n            Hyperlink::default()\n        }\n    }\n\n    pub fn err_hyperlink<D: fmt::Display>(&self, url: D) -> Hyperlink<D> {\n        let supports_hyperlinks = match &self.output {\n            ShellOut::Write(_) => false,\n            ShellOut::Stream {\n                stderr, hyperlinks, ..\n            } => stderr.current_choice() == anstream::ColorChoice::AlwaysAnsi && *hyperlinks,\n        };\n        if supports_hyperlinks {\n            Hyperlink::with_url(url)\n        } else {\n            Hyperlink::default()\n        }\n    }\n\n    pub fn out_file_hyperlink(&mut self, path: &std::path::Path) -> Hyperlink<String> {\n        let url = anstyle_hyperlink::path_to_url(path);\n        url.map(|u| self.out_hyperlink(u)).unwrap_or_default()\n    }\n\n    pub fn err_file_hyperlink(&mut self, path: &std::path::Path) -> Hyperlink<String> {\n        let url = anstyle_hyperlink::path_to_url(path);\n        url.map(|u| self.err_hyperlink(u)).unwrap_or_default()\n    }\n\n    fn unstable_flags_rustc_unicode(&self) -> bool {\n        match &self.output {\n            ShellOut::Write(_) => false,\n            ShellOut::Stream {\n                unstable_flags_rustc_unicode,\n                ..\n            } => *unstable_flags_rustc_unicode,\n        }\n    }\n\n    pub(crate) fn set_unstable_flags_rustc_unicode(&mut self, yes: bool) -> CargoResult<()> {\n        if let ShellOut::Stream {\n            unstable_flags_rustc_unicode,\n            ..\n        } = &mut self.output\n        {\n            *unstable_flags_rustc_unicode = yes;\n        }\n        Ok(())\n    }\n\n    /// Prints a message to stderr and translates ANSI escape code into console colors.\n    pub fn print_ansi_stderr(&mut self, message: &[u8]) -> CargoResult<()> {\n        if self.needs_clear {\n            self.err_erase_line();\n        }\n        self.err().write_all(message)?;\n        Ok(())\n    }\n\n    /// Prints a message to stdout and translates ANSI escape code into console colors.\n    pub fn print_ansi_stdout(&mut self, message: &[u8]) -> CargoResult<()> {\n        if self.needs_clear {\n            self.err_erase_line();\n        }\n        self.out().write_all(message)?;\n        Ok(())\n    }\n\n    pub fn print_json<T: serde::ser::Serialize>(&mut self, obj: &T) -> CargoResult<()> {\n        // Path may fail to serialize to JSON ...\n        let encoded = serde_json::to_string(obj)?;\n        // ... but don't fail due to a closed pipe.\n        drop(writeln!(self.out(), \"{}\", encoded));\n        Ok(())\n    }\n\n    /// Prints the passed in [`Report`] to stderr\n    pub fn print_report(&mut self, report: Report<'_>, force: bool) -> CargoResult<()> {\n        if !force && matches!(self.verbosity, Verbosity::Quiet) {\n            return Ok(());\n        }\n\n        if self.needs_clear {\n            self.err_erase_line();\n        }\n        let term_width = self\n            .err_width()\n            .diagnostic_terminal_width()\n            .unwrap_or(annotate_snippets::renderer::DEFAULT_TERM_WIDTH);\n        let decor_style = if self.err_unicode() && self.unstable_flags_rustc_unicode() {\n            DecorStyle::Unicode\n        } else {\n            DecorStyle::Ascii\n        };\n        let rendered = Renderer::styled()\n            .term_width(term_width)\n            .decor_style(decor_style)\n            .render(report);\n        self.err().write_all(rendered.as_bytes())?;\n        self.err().write_all(b\"\\n\")?;\n        Ok(())\n    }\n}\n\nimpl Default for Shell {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\n/// A `Write`able object, either with or without color support\nenum ShellOut {\n    /// A plain write object without color support\n    Write(AutoStream<Box<dyn Write + Send + Sync>>),\n    /// Color-enabled stdio, with information on whether color should be used\n    Stream {\n        stdout: AutoStream<std::io::Stdout>,\n        stderr: AutoStream<std::io::Stderr>,\n        stderr_tty: bool,\n        color_choice: ColorChoice,\n        hyperlinks: bool,\n        stdout_unicode: bool,\n        stderr_unicode: bool,\n        stderr_term_integration: bool,\n        unstable_flags_rustc_unicode: bool,\n    },\n}\n\nimpl ShellOut {\n    /// Prints out a message with a status. The status comes first, and is bold plus the given\n    /// color. The status can be justified, in which case the max width that will right align is\n    /// 12 chars.\n    fn message_stderr(\n        &mut self,\n        status: &dyn fmt::Display,\n        message: Option<&dyn fmt::Display>,\n        style: &Style,\n        justified: bool,\n    ) -> CargoResult<()> {\n        let mut buffer = Vec::new();\n        if justified {\n            write!(&mut buffer, \"{style}{status:>12}{style:#}\")?;\n        } else {\n            write!(&mut buffer, \"{style}{status}{style:#}:\")?;\n        }\n        match message {\n            Some(message) => writeln!(buffer, \" {message}\")?,\n            None => write!(buffer, \" \")?,\n        }\n        self.stderr().write_all(&buffer)?;\n        Ok(())\n    }\n\n    /// Gets stdout as a `io::Write`.\n    fn stdout(&mut self) -> &mut dyn Write {\n        match self {\n            ShellOut::Stream { stdout, .. } => stdout,\n            ShellOut::Write(w) => w,\n        }\n    }\n\n    /// Gets stderr as a `io::Write`.\n    fn stderr(&mut self) -> &mut dyn Write {\n        match self {\n            ShellOut::Stream { stderr, .. } => stderr,\n            ShellOut::Write(w) => w,\n        }\n    }\n}\n\npub enum TtyWidth {\n    NoTty,\n    Known(usize),\n    Guess(usize),\n}\n\nimpl TtyWidth {\n    /// Returns the width of the terminal to use for diagnostics (which is\n    /// relayed to rustc via `--diagnostic-width`).\n    pub fn diagnostic_terminal_width(&self) -> Option<usize> {\n        #[expect(\n            clippy::disallowed_methods,\n            reason = \"testing only, no reason for config support\"\n        )]\n        if let Ok(width) = std::env::var(\"__CARGO_TEST_TTY_WIDTH_DO_NOT_USE_THIS\") {\n            return Some(width.parse().unwrap());\n        }\n        match *self {\n            TtyWidth::NoTty | TtyWidth::Guess(_) => None,\n            TtyWidth::Known(width) => Some(width),\n        }\n    }\n\n    /// Returns the width used by progress bars for the tty.\n    pub fn progress_max_width(&self) -> Option<usize> {\n        match *self {\n            TtyWidth::NoTty => None,\n            TtyWidth::Known(width) | TtyWidth::Guess(width) => Some(width),\n        }\n    }\n}\n\n/// The requested verbosity of output.\n#[derive(Debug, Clone, Copy, PartialEq)]\npub enum Verbosity {\n    Verbose,\n    Normal,\n    Quiet,\n}\n\n/// Whether messages should use color output\n#[derive(Debug, PartialEq, Clone, Copy)]\npub enum ColorChoice {\n    /// Force color output\n    Always,\n    /// Force disable color output\n    Never,\n    /// Intelligently guess whether to use color output\n    CargoAuto,\n}\n\nimpl ColorChoice {\n    /// Converts our color choice to anstream's version.\n    fn to_anstream_color_choice(self) -> anstream::ColorChoice {\n        match self {\n            ColorChoice::Always => anstream::ColorChoice::Always,\n            ColorChoice::Never => anstream::ColorChoice::Never,\n            ColorChoice::CargoAuto => anstream::ColorChoice::Auto,\n        }\n    }\n}\n\nimpl std::str::FromStr for ColorChoice {\n    type Err = anyhow::Error;\n    fn from_str(color: &str) -> Result<Self, Self::Err> {\n        let cfg = match color {\n            \"always\" => ColorChoice::Always,\n            \"never\" => ColorChoice::Never,\n\n            \"auto\" => ColorChoice::CargoAuto,\n\n            arg => anyhow::bail!(\n                \"argument for --color must be auto, always, or \\\n                     never, but found `{}`\",\n                arg\n            ),\n        };\n        Ok(cfg)\n    }\n}\n\nfn supports_color(choice: anstream::ColorChoice) -> bool {\n    match choice {\n        anstream::ColorChoice::Always\n        | anstream::ColorChoice::AlwaysAnsi\n        | anstream::ColorChoice::Auto => true,\n        anstream::ColorChoice::Never => false,\n    }\n}\n\nfn supports_unicode(stream: &dyn IsTerminal) -> bool {\n    !stream.is_terminal() || supports_unicode::supports_unicode()\n}\n\nfn supports_hyperlinks() -> bool {\n    #[expect(\n        clippy::disallowed_methods,\n        reason = \"reading the state of the system, not config\"\n    )]\n    if std::env::var_os(\"TERM_PROGRAM\").as_deref() == Some(std::ffi::OsStr::new(\"iTerm.app\")) {\n        // Override `supports_hyperlinks` as we have an unknown incompatibility with iTerm2\n        return false;\n    }\n\n    supports_hyperlinks::supports_hyperlinks()\n}\n\n/// Determines whether the terminal supports ANSI OSC 9;4.\nfn supports_term_integration(stream: &dyn IsTerminal) -> bool {\n    anstyle_progress::supports_term_progress(stream.is_terminal())\n}\n\n#[cfg(unix)]\nmod imp {\n    use super::{Shell, TtyWidth};\n    use std::mem;\n\n    pub fn stderr_width() -> TtyWidth {\n        unsafe {\n            let mut winsize: libc::winsize = mem::zeroed();\n            // The .into() here is needed for FreeBSD which defines TIOCGWINSZ\n            // as c_uint but ioctl wants c_ulong.\n            if libc::ioctl(libc::STDERR_FILENO, libc::TIOCGWINSZ.into(), &mut winsize) < 0 {\n                return TtyWidth::NoTty;\n            }\n            if winsize.ws_col > 0 {\n                TtyWidth::Known(winsize.ws_col as usize)\n            } else {\n                TtyWidth::NoTty\n            }\n        }\n    }\n\n    pub fn err_erase_line(shell: &mut Shell) {\n        // This is the \"EL - Erase in Line\" sequence. It clears from the cursor\n        // to the end of line.\n        // https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences\n        let _ = shell.output.stderr().write_all(b\"\\x1B[K\");\n    }\n}\n\n#[cfg(windows)]\nmod imp {\n    use std::{cmp, mem, ptr};\n\n    use windows_sys::Win32::Foundation::CloseHandle;\n    use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;\n    use windows_sys::Win32::Foundation::{GENERIC_READ, GENERIC_WRITE};\n    use windows_sys::Win32::Storage::FileSystem::{\n        CreateFileA, FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING,\n    };\n    use windows_sys::Win32::System::Console::{\n        CONSOLE_SCREEN_BUFFER_INFO, GetConsoleScreenBufferInfo, GetStdHandle, STD_ERROR_HANDLE,\n    };\n    use windows_sys::core::PCSTR;\n\n    pub(super) use super::{TtyWidth, default_err_erase_line as err_erase_line};\n\n    pub fn stderr_width() -> TtyWidth {\n        unsafe {\n            let stdout = GetStdHandle(STD_ERROR_HANDLE);\n            let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();\n            if GetConsoleScreenBufferInfo(stdout, &mut csbi) != 0 {\n                return TtyWidth::Known((csbi.srWindow.Right - csbi.srWindow.Left) as usize);\n            }\n\n            // On mintty/msys/cygwin based terminals, the above fails with\n            // INVALID_HANDLE_VALUE. Use an alternate method which works\n            // in that case as well.\n            let h = CreateFileA(\n                \"CONOUT$\\0\".as_ptr() as PCSTR,\n                GENERIC_READ | GENERIC_WRITE,\n                FILE_SHARE_READ | FILE_SHARE_WRITE,\n                ptr::null_mut(),\n                OPEN_EXISTING,\n                0,\n                std::ptr::null_mut(),\n            );\n            if h == INVALID_HANDLE_VALUE {\n                return TtyWidth::NoTty;\n            }\n\n            let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();\n            let rc = GetConsoleScreenBufferInfo(h, &mut csbi);\n            CloseHandle(h);\n            if rc != 0 {\n                let width = (csbi.srWindow.Right - csbi.srWindow.Left) as usize;\n                // Unfortunately cygwin/mintty does not set the size of the\n                // backing console to match the actual window size. This\n                // always reports a size of 80 or 120 (not sure what\n                // determines that). Use a conservative max of 60 which should\n                // work in most circumstances. ConEmu does some magic to\n                // resize the console correctly, but there's no reasonable way\n                // to detect which kind of terminal we are running in, or if\n                // GetConsoleScreenBufferInfo returns accurate information.\n                return TtyWidth::Guess(cmp::min(60, width));\n            }\n\n            TtyWidth::NoTty\n        }\n    }\n}\n\n#[cfg(windows)]\nfn default_err_erase_line(shell: &mut Shell) {\n    match imp::stderr_width() {\n        TtyWidth::Known(max_width) | TtyWidth::Guess(max_width) => {\n            let blank = \" \".repeat(max_width);\n            drop(write!(shell.output.stderr(), \"{}\\r\", blank));\n        }\n        _ => (),\n    }\n}\n"
  },
  {
    "path": "src/cargo/core/source_id.rs",
    "content": "use crate::core::GitReference;\nuse crate::core::PackageId;\nuse crate::core::SourceKind;\nuse crate::sources::registry::CRATES_IO_HTTP_INDEX;\nuse crate::sources::source::Source;\nuse crate::sources::{CRATES_IO_DOMAIN, CRATES_IO_INDEX, CRATES_IO_REGISTRY, DirectorySource};\nuse crate::sources::{GitSource, PathSource, RegistrySource};\nuse crate::util::interning::InternedString;\nuse crate::util::{CanonicalUrl, CargoResult, GlobalContext, IntoUrl, context};\nuse anyhow::Context as _;\nuse serde::de;\nuse serde::ser;\nuse std::cmp::{self, Ordering};\nuse std::collections::HashSet;\nuse std::fmt::{self, Formatter};\nuse std::hash::{self, Hash};\nuse std::path::{Path, PathBuf};\nuse std::ptr;\nuse std::sync::Mutex;\nuse std::sync::OnceLock;\nuse tracing::trace;\nuse url::Url;\n\nstatic SOURCE_ID_CACHE: OnceLock<Mutex<HashSet<&'static SourceIdInner>>> = OnceLock::new();\n\n/// Unique identifier for a source of packages.\n///\n/// Cargo uniquely identifies packages using [`PackageId`], a combination of the\n/// package name, version, and the code source. `SourceId` exactly represents\n/// the \"code source\" in `PackageId`. See [`SourceId::hash`] to learn what are\n/// taken into account for the uniqueness of a source.\n///\n/// `SourceId` is usually associated with an instance of [`Source`], which is\n/// supposed to provide a `SourceId` via [`Source::source_id`] method.\n///\n/// [`Source`]: crate::sources::source::Source\n/// [`Source::source_id`]: crate::sources::source::Source::source_id\n/// [`PackageId`]: super::PackageId\n#[derive(Clone, Copy, Eq, Debug)]\npub struct SourceId {\n    inner: &'static SourceIdInner,\n}\n\n/// The interned version of [`SourceId`] to avoid excessive clones and borrows.\n/// Values are cached in `SOURCE_ID_CACHE` once created.\n#[derive(Eq, Clone, Debug)]\nstruct SourceIdInner {\n    /// The source URL.\n    url: Url,\n    /// The canonical version of the above url. See [`CanonicalUrl`] to learn\n    /// why it is needed and how it normalizes a URL.\n    canonical_url: CanonicalUrl,\n    /// The source kind.\n    kind: SourceKind,\n    /// For example, the exact Git revision of the specified branch for a Git Source.\n    precise: Option<Precise>,\n    /// Name of the remote registry.\n    ///\n    /// WARNING: this is not always set when the name is not known,\n    /// e.g. registry coming from `--index` or Cargo.lock\n    registry_key: Option<KeyOf>,\n}\n\n#[derive(Eq, PartialEq, Clone, Debug, Hash)]\nenum Precise {\n    Locked,\n    Updated {\n        name: InternedString,\n        from: semver::Version,\n        to: semver::Version,\n    },\n    GitUrlFragment(String),\n}\n\nimpl fmt::Display for Precise {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        match self {\n            Precise::Locked => \"locked\".fmt(f),\n            Precise::Updated { name, from, to } => {\n                write!(f, \"{name}={from}->{to}\")\n            }\n            Precise::GitUrlFragment(s) => s.fmt(f),\n        }\n    }\n}\n\n/// Where the remote source key is defined.\n///\n/// The purpose of this is to provide better diagnostics for different sources of keys.\n#[derive(Debug, Clone, PartialEq, Eq)]\nenum KeyOf {\n    /// Defined in the `[registries]` table or the built-in `crates-io` key.\n    Registry(String),\n    /// Defined in the `[source]` replacement table.\n    Source(String),\n}\n\nimpl SourceId {\n    /// Creates a `SourceId` object from the kind and URL.\n    ///\n    /// The canonical url will be calculated, but the precise field will not\n    fn new(kind: SourceKind, url: Url, key: Option<KeyOf>) -> CargoResult<SourceId> {\n        if kind == SourceKind::SparseRegistry {\n            // Sparse URLs are different because they store the kind prefix (sparse+)\n            // in the URL. This is because the prefix is necessary to differentiate\n            // from regular registries (git-based). The sparse+ prefix is included\n            // everywhere, including user-facing locations such as the `config.toml`\n            // file that defines the registry, or whenever Cargo displays it to the user.\n            assert!(url.as_str().starts_with(\"sparse+\"));\n        }\n        let source_id = SourceId::wrap(SourceIdInner {\n            kind,\n            canonical_url: CanonicalUrl::new(&url)?,\n            url,\n            precise: None,\n            registry_key: key,\n        });\n        Ok(source_id)\n    }\n\n    /// Interns the value and returns the wrapped type.\n    fn wrap(inner: SourceIdInner) -> SourceId {\n        let mut cache = SOURCE_ID_CACHE\n            .get_or_init(|| Default::default())\n            .lock()\n            .unwrap();\n        let inner = cache.get(&inner).cloned().unwrap_or_else(|| {\n            let inner = Box::leak(Box::new(inner));\n            cache.insert(inner);\n            inner\n        });\n        SourceId { inner }\n    }\n\n    fn remote_source_kind(url: &Url) -> SourceKind {\n        if url.as_str().starts_with(\"sparse+\") {\n            SourceKind::SparseRegistry\n        } else {\n            SourceKind::Registry\n        }\n    }\n\n    /// Parses a source URL and returns the corresponding ID.\n    ///\n    /// ## Example\n    ///\n    /// ```\n    /// use cargo::core::SourceId;\n    /// SourceId::from_url(\"git+https://github.com/alexcrichton/\\\n    ///                     libssh2-static-sys#80e71a3021618eb05\\\n    ///                     656c58fb7c5ef5f12bc747f\");\n    /// ```\n    pub fn from_url(string: &str) -> CargoResult<SourceId> {\n        let (kind, url) = string\n            .split_once('+')\n            .ok_or_else(|| anyhow::format_err!(\"invalid source `{}`\", string))?;\n\n        match kind {\n            \"git\" => {\n                let mut url = url.into_url()?;\n                let reference = GitReference::from_query(url.query_pairs());\n                let precise = url.fragment().map(|s| s.to_owned());\n                url.set_fragment(None);\n                url.set_query(None);\n                Ok(SourceId::for_git(&url, reference)?.with_git_precise(precise))\n            }\n            \"registry\" => {\n                let url = url.into_url()?;\n                Ok(SourceId::new(SourceKind::Registry, url, None)?.with_locked_precise())\n            }\n            \"sparse\" => {\n                let url = string.into_url()?;\n                Ok(SourceId::new(SourceKind::SparseRegistry, url, None)?.with_locked_precise())\n            }\n            \"path\" => {\n                let url = url.into_url()?;\n                SourceId::new(SourceKind::Path, url, None)\n            }\n            kind => Err(anyhow::format_err!(\"unsupported source protocol: {}\", kind)),\n        }\n    }\n\n    /// A view of the [`SourceId`] that can be `Display`ed as a URL.\n    pub fn as_url(&self) -> SourceIdAsUrl<'_> {\n        SourceIdAsUrl {\n            inner: &*self.inner,\n            encoded: false,\n        }\n    }\n\n    /// Like [`Self::as_url`] but with URL parameters encoded.\n    pub fn as_encoded_url(&self) -> SourceIdAsUrl<'_> {\n        SourceIdAsUrl {\n            inner: &*self.inner,\n            encoded: true,\n        }\n    }\n\n    /// Creates a `SourceId` from a filesystem path.\n    ///\n    /// `path`: an absolute path.\n    pub fn for_path(path: &Path) -> CargoResult<SourceId> {\n        let url = path.into_url()?;\n        SourceId::new(SourceKind::Path, url, None)\n    }\n\n    /// Creates a `SourceId` from a filesystem path.\n    ///\n    /// `path`: an absolute path.\n    pub fn for_manifest_path(manifest_path: &Path) -> CargoResult<SourceId> {\n        if crate::util::toml::is_embedded(manifest_path) && manifest_path.is_file() {\n            Self::for_path(manifest_path)\n        } else {\n            Self::for_path(manifest_path.parent().unwrap())\n        }\n    }\n\n    /// Creates a `SourceId` from a Git reference.\n    pub fn for_git(url: &Url, reference: GitReference) -> CargoResult<SourceId> {\n        SourceId::new(SourceKind::Git(reference), url.clone(), None)\n    }\n\n    /// Creates a `SourceId` from a remote registry URL when the registry name\n    /// cannot be determined, e.g. a user passes `--index` directly from CLI.\n    ///\n    /// Use [`SourceId::for_alt_registry`] if a name can provided, which\n    /// generates better messages for cargo.\n    pub fn for_registry(url: &Url) -> CargoResult<SourceId> {\n        let kind = Self::remote_source_kind(url);\n        SourceId::new(kind, url.to_owned(), None)\n    }\n\n    /// Creates a `SourceId` for a remote registry from the `[registries]` table or crates.io.\n    pub fn for_alt_registry(url: &Url, key: &str) -> CargoResult<SourceId> {\n        let kind = Self::remote_source_kind(url);\n        let key = KeyOf::Registry(key.into());\n        SourceId::new(kind, url.to_owned(), Some(key))\n    }\n\n    /// Creates a `SourceId` for a remote registry from the `[source]` replacement table.\n    pub fn for_source_replacement_registry(url: &Url, key: &str) -> CargoResult<SourceId> {\n        let kind = Self::remote_source_kind(url);\n        let key = KeyOf::Source(key.into());\n        SourceId::new(kind, url.to_owned(), Some(key))\n    }\n\n    /// Creates a `SourceId` from a local registry path.\n    pub fn for_local_registry(path: &Path) -> CargoResult<SourceId> {\n        let url = path.into_url()?;\n        SourceId::new(SourceKind::LocalRegistry, url, None)\n    }\n\n    /// Creates a `SourceId` from a directory path.\n    pub fn for_directory(path: &Path) -> CargoResult<SourceId> {\n        let url = path.into_url()?;\n        SourceId::new(SourceKind::Directory, url, None)\n    }\n\n    /// Returns the `SourceId` corresponding to the main repository.\n    ///\n    /// This is the main cargo registry by default, but it can be overridden in\n    /// a `.cargo/config.toml`.\n    pub fn crates_io(gctx: &GlobalContext) -> CargoResult<SourceId> {\n        gctx.crates_io_source_id()\n    }\n\n    /// Returns the `SourceId` corresponding to the main repository, using the\n    /// sparse HTTP index if allowed.\n    pub fn crates_io_maybe_sparse_http(gctx: &GlobalContext) -> CargoResult<SourceId> {\n        if Self::crates_io_is_sparse(gctx)? {\n            gctx.check_registry_index_not_set()?;\n            let url = CRATES_IO_HTTP_INDEX.into_url().unwrap();\n            let key = KeyOf::Registry(CRATES_IO_REGISTRY.into());\n            SourceId::new(SourceKind::SparseRegistry, url, Some(key))\n        } else {\n            Self::crates_io(gctx)\n        }\n    }\n\n    /// Returns whether to access crates.io over the sparse protocol.\n    pub fn crates_io_is_sparse(gctx: &GlobalContext) -> CargoResult<bool> {\n        let proto: Option<context::Value<String>> = gctx.get(\"registries.crates-io.protocol\")?;\n        let is_sparse = match proto.as_ref().map(|v| v.val.as_str()) {\n            Some(\"sparse\") => true,\n            Some(\"git\") => false,\n            Some(unknown) => anyhow::bail!(\n                \"unsupported registry protocol `{unknown}` (defined in {})\",\n                proto.as_ref().unwrap().definition\n            ),\n            None => true,\n        };\n        Ok(is_sparse)\n    }\n\n    /// Gets the `SourceId` associated with given name of the remote registry.\n    pub fn alt_registry(gctx: &GlobalContext, key: &str) -> CargoResult<SourceId> {\n        if key == CRATES_IO_REGISTRY {\n            return Self::crates_io(gctx);\n        }\n        let url = gctx.get_registry_index(key)?;\n        Self::for_alt_registry(&url, key)\n    }\n\n    /// Gets this source URL.\n    pub fn url(&self) -> &Url {\n        &self.inner.url\n    }\n\n    /// Gets the canonical URL of this source, used for internal comparison\n    /// purposes.\n    pub fn canonical_url(&self) -> &CanonicalUrl {\n        &self.inner.canonical_url\n    }\n\n    /// Displays the text \"crates.io index\" for Cargo shell status output.\n    pub fn display_index(self) -> String {\n        if self.is_crates_io() {\n            format!(\"{} index\", CRATES_IO_DOMAIN)\n        } else {\n            format!(\"`{}` index\", self.display_registry_name())\n        }\n    }\n\n    /// Displays the name of a registry if it has one. Otherwise just the URL.\n    pub fn display_registry_name(self) -> String {\n        if let Some(key) = self.inner.registry_key.as_ref().map(|k| k.key()) {\n            key.into()\n        } else if self.has_precise() {\n            // We remove `precise` here to retrieve an permissive version of\n            // `SourceIdInner`, which may contain the registry name.\n            self.without_precise().display_registry_name()\n        } else {\n            url_display(self.url())\n        }\n    }\n\n    /// Gets the name of the remote registry as defined in the `[registries]` table,\n    /// or the built-in `crates-io` key.\n    pub fn alt_registry_key(&self) -> Option<&str> {\n        self.inner.registry_key.as_ref()?.alternative_registry()\n    }\n\n    /// Returns `true` if this source is from a filesystem path.\n    pub fn is_path(self) -> bool {\n        self.inner.kind == SourceKind::Path\n    }\n\n    /// Returns the local path if this is a path dependency.\n    pub fn local_path(self) -> Option<PathBuf> {\n        if self.inner.kind != SourceKind::Path {\n            return None;\n        }\n\n        Some(self.inner.url.to_file_path().unwrap())\n    }\n\n    pub fn kind(&self) -> &SourceKind {\n        &self.inner.kind\n    }\n\n    /// Returns `true` if this source is from a registry (either local or not).\n    pub fn is_registry(self) -> bool {\n        matches!(\n            self.inner.kind,\n            SourceKind::Registry | SourceKind::SparseRegistry | SourceKind::LocalRegistry\n        )\n    }\n\n    /// Returns `true` if this source is from a sparse registry.\n    pub fn is_sparse(self) -> bool {\n        matches!(self.inner.kind, SourceKind::SparseRegistry)\n    }\n\n    /// Returns `true` if this source is a \"remote\" registry.\n    ///\n    /// \"remote\" may also mean a file URL to a git index, so it is not\n    /// necessarily \"remote\". This just means it is not `local-registry`.\n    pub fn is_remote_registry(self) -> bool {\n        matches!(\n            self.inner.kind,\n            SourceKind::Registry | SourceKind::SparseRegistry\n        )\n    }\n\n    /// Returns `true` if this source from a Git repository.\n    pub fn is_git(self) -> bool {\n        matches!(self.inner.kind, SourceKind::Git(_))\n    }\n\n    /// Creates an implementation of `Source` corresponding to this ID.\n    ///\n    /// * `yanked_whitelist` --- Packages allowed to be used, even if they are yanked.\n    pub fn load<'a>(\n        self,\n        gctx: &'a GlobalContext,\n        yanked_whitelist: &HashSet<PackageId>,\n    ) -> CargoResult<Box<dyn Source + 'a>> {\n        trace!(\"loading SourceId; {}\", self);\n        match self.inner.kind {\n            SourceKind::Git(..) => Ok(Box::new(GitSource::new(self, gctx)?)),\n            SourceKind::Path => {\n                let path = self\n                    .inner\n                    .url\n                    .to_file_path()\n                    .expect(\"path sources cannot be remote\");\n                if crate::util::toml::is_embedded(&path) && path.is_file() {\n                    anyhow::bail!(\"single file packages cannot be used as dependencies\")\n                }\n                Ok(Box::new(PathSource::new(&path, self, gctx)))\n            }\n            SourceKind::Registry | SourceKind::SparseRegistry => Ok(Box::new(\n                RegistrySource::remote(self, yanked_whitelist, gctx)?,\n            )),\n            SourceKind::LocalRegistry => {\n                let path = self\n                    .inner\n                    .url\n                    .to_file_path()\n                    .expect(\"path sources cannot be remote\");\n                Ok(Box::new(RegistrySource::local(\n                    self,\n                    &path,\n                    yanked_whitelist,\n                    gctx,\n                )))\n            }\n            SourceKind::Directory => {\n                let path = self\n                    .inner\n                    .url\n                    .to_file_path()\n                    .expect(\"path sources cannot be remote\");\n                Ok(Box::new(DirectorySource::new(&path, self, gctx)))\n            }\n        }\n    }\n\n    /// Gets the Git reference if this is a git source, otherwise `None`.\n    pub fn git_reference(self) -> Option<&'static GitReference> {\n        match self.inner.kind {\n            SourceKind::Git(ref s) => Some(s),\n            _ => None,\n        }\n    }\n\n    /// Check if the precise data field has bean set\n    pub fn has_precise(self) -> bool {\n        self.inner.precise.is_some()\n    }\n\n    /// Check if the precise data field has bean set to \"locked\"\n    pub fn has_locked_precise(self) -> bool {\n        self.inner.precise == Some(Precise::Locked)\n    }\n\n    /// Check if two sources have the same precise data field\n    pub fn has_same_precise_as(self, other: Self) -> bool {\n        self.inner.precise == other.inner.precise\n    }\n\n    /// Check if the precise data field stores information for this `name`\n    /// from a call to [`SourceId::with_precise_registry_version`].\n    ///\n    /// If so return the version currently in the lock file and the version to be updated to.\n    pub fn precise_registry_version(\n        self,\n        pkg: &str,\n    ) -> Option<(&semver::Version, &semver::Version)> {\n        match &self.inner.precise {\n            Some(Precise::Updated { name, from, to }) if name == pkg => Some((from, to)),\n            _ => None,\n        }\n    }\n\n    pub fn precise_git_fragment(self) -> Option<&'static str> {\n        match &self.inner.precise {\n            Some(Precise::GitUrlFragment(s)) => Some(&s),\n            _ => None,\n        }\n    }\n\n    /// Creates a new `SourceId` from this source with the given `precise`.\n    pub fn with_git_precise(self, fragment: Option<String>) -> SourceId {\n        self.with_precise(&fragment.map(|f| Precise::GitUrlFragment(f)))\n    }\n\n    /// Creates a new `SourceId` from this source without a `precise`.\n    pub fn without_precise(self) -> SourceId {\n        self.with_precise(&None)\n    }\n\n    /// Creates a new `SourceId` from this source without a `precise`.\n    pub fn with_locked_precise(self) -> SourceId {\n        self.with_precise(&Some(Precise::Locked))\n    }\n\n    /// Creates a new `SourceId` from this source with the `precise` from some other `SourceId`.\n    pub fn with_precise_from(self, v: Self) -> SourceId {\n        self.with_precise(&v.inner.precise)\n    }\n\n    fn with_precise(self, precise: &Option<Precise>) -> SourceId {\n        if &self.inner.precise == precise {\n            self\n        } else {\n            SourceId::wrap(SourceIdInner {\n                precise: precise.clone(),\n                ..(*self.inner).clone()\n            })\n        }\n    }\n\n    /// When updating a lock file on a version using `cargo update --precise`\n    /// the requested version is stored in the precise field.\n    /// On a registry dependency we also need to keep track of the package that\n    /// should be updated and even which of the versions should be updated.\n    /// All of this gets encoded in the precise field using this method.\n    /// The data can be read with [`SourceId::precise_registry_version`]\n    pub fn with_precise_registry_version(\n        self,\n        name: InternedString,\n        version: semver::Version,\n        precise: &str,\n    ) -> CargoResult<SourceId> {\n        let precise = semver::Version::parse(precise).with_context(|| {\n            if let Some(stripped) = precise.strip_prefix(\"v\") {\n                return format!(\n                    \"the version provided, `{precise}` is not a \\\n                    valid SemVer version\\n\\n\\\n                    help: try changing the version to `{stripped}`\",\n                );\n            }\n            format!(\"invalid version format for precise version `{precise}`\")\n        })?;\n\n        Ok(SourceId::wrap(SourceIdInner {\n            precise: Some(Precise::Updated {\n                name,\n                from: version,\n                to: precise,\n            }),\n            ..(*self.inner).clone()\n        }))\n    }\n\n    /// Returns `true` if the remote registry is the standard <https://crates.io>.\n    pub fn is_crates_io(self) -> bool {\n        match self.inner.kind {\n            SourceKind::Registry | SourceKind::SparseRegistry => {}\n            _ => return false,\n        }\n        let url = self.inner.url.as_str();\n        url == CRATES_IO_INDEX || url == CRATES_IO_HTTP_INDEX || is_overridden_crates_io_url(url)\n    }\n\n    /// Hashes `self` to be used in the name of some Cargo folders, so shouldn't vary.\n    ///\n    /// For git and url, `as_str` gives the serialisation of a url (which has a spec) and so\n    /// insulates against possible changes in how the url crate does hashing.\n    ///\n    /// For paths, remove the workspace prefix so the same source will give the\n    /// same hash in different locations, helping reproducible builds.\n    pub fn stable_hash<S: hash::Hasher>(self, workspace: &Path, into: &mut S) {\n        if self.is_path() {\n            if let Ok(p) = self\n                .inner\n                .url\n                .to_file_path()\n                .unwrap()\n                .strip_prefix(workspace)\n            {\n                self.inner.kind.hash(into);\n                p.to_str().unwrap().hash(into);\n                return;\n            }\n        }\n        self.inner.kind.hash(into);\n        match self.inner.kind {\n            SourceKind::Git(_) => (&self).inner.canonical_url.hash(into),\n            _ => (&self).inner.url.as_str().hash(into),\n        }\n    }\n\n    pub fn full_eq(self, other: SourceId) -> bool {\n        ptr::eq(self.inner, other.inner)\n    }\n\n    pub fn full_hash<S: hash::Hasher>(self, into: &mut S) {\n        ptr::NonNull::from(self.inner).hash(into)\n    }\n}\n\nimpl PartialEq for SourceId {\n    fn eq(&self, other: &SourceId) -> bool {\n        self.cmp(other) == Ordering::Equal\n    }\n}\n\nimpl PartialOrd for SourceId {\n    fn partial_cmp(&self, other: &SourceId) -> Option<Ordering> {\n        Some(self.cmp(other))\n    }\n}\n\n// Custom comparison defined as source kind and canonical URL equality,\n// ignoring the `precise` and `name` fields.\nimpl Ord for SourceId {\n    fn cmp(&self, other: &SourceId) -> Ordering {\n        // If our interior pointers are to the exact same `SourceIdInner` then\n        // we're guaranteed to be equal.\n        if ptr::eq(self.inner, other.inner) {\n            return Ordering::Equal;\n        }\n\n        // Sort first based on `kind`, deferring to the URL comparison if\n        // the kinds are equal.\n        let ord_kind = self.inner.kind.cmp(&other.inner.kind);\n        ord_kind.then_with(|| self.inner.canonical_url.cmp(&other.inner.canonical_url))\n    }\n}\n\nimpl ser::Serialize for SourceId {\n    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>\n    where\n        S: ser::Serializer,\n    {\n        if self.is_path() {\n            None::<String>.serialize(s)\n        } else {\n            s.collect_str(&self.as_url())\n        }\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for SourceId {\n    fn deserialize<D>(d: D) -> Result<SourceId, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        let string = String::deserialize(d)?;\n        SourceId::from_url(&string).map_err(de::Error::custom)\n    }\n}\n\nfn url_display(url: &Url) -> String {\n    if url.scheme() == \"file\" {\n        if let Ok(path) = url.to_file_path() {\n            if let Some(path_str) = path.to_str() {\n                return path_str.to_string();\n            }\n        }\n    }\n\n    url.as_str().to_string()\n}\n\nimpl fmt::Display for SourceId {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        match self.inner.kind {\n            SourceKind::Git(ref reference) => {\n                // Don't replace the URL display for git references,\n                // because those are kind of expected to be URLs.\n                write!(f, \"{}\", self.inner.url)?;\n                if let Some(pretty) = reference.pretty_ref(true) {\n                    write!(f, \"?{}\", pretty)?;\n                }\n\n                if let Some(s) = &self.inner.precise {\n                    let s = s.to_string();\n                    let len = cmp::min(s.len(), 8);\n                    write!(f, \"#{}\", &s[..len])?;\n                }\n                Ok(())\n            }\n            SourceKind::Path => write!(f, \"{}\", url_display(&self.inner.url)),\n            SourceKind::Registry | SourceKind::SparseRegistry => {\n                write!(f, \"registry `{}`\", self.display_registry_name())\n            }\n            SourceKind::LocalRegistry => write!(f, \"registry `{}`\", url_display(&self.inner.url)),\n            SourceKind::Directory => write!(f, \"dir {}\", url_display(&self.inner.url)),\n        }\n    }\n}\n\nimpl Hash for SourceId {\n    fn hash<S: hash::Hasher>(&self, into: &mut S) {\n        self.inner.kind.hash(into);\n        self.inner.canonical_url.hash(into);\n    }\n}\n\n/// The hash of `SourceIdInner` is used to retrieve its interned value from\n/// `SOURCE_ID_CACHE`. We only care about fields that make `SourceIdInner`\n/// unique. Optional fields not affecting the uniqueness must be excluded,\n/// such as [`registry_key`]. That's why this is not derived.\n///\n/// [`registry_key`]: SourceIdInner::registry_key\nimpl Hash for SourceIdInner {\n    fn hash<S: hash::Hasher>(&self, into: &mut S) {\n        self.kind.hash(into);\n        self.precise.hash(into);\n        self.canonical_url.hash(into);\n    }\n}\n\n/// This implementation must be synced with [`SourceIdInner::hash`].\nimpl PartialEq for SourceIdInner {\n    fn eq(&self, other: &Self) -> bool {\n        self.kind == other.kind\n            && self.precise == other.precise\n            && self.canonical_url == other.canonical_url\n    }\n}\n\n/// A `Display`able view into a `SourceId` that will write it as a url\npub struct SourceIdAsUrl<'a> {\n    inner: &'a SourceIdInner,\n    encoded: bool,\n}\n\nimpl<'a> fmt::Display for SourceIdAsUrl<'a> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        if let Some(protocol) = self.inner.kind.protocol() {\n            write!(f, \"{protocol}+\")?;\n        }\n        write!(f, \"{}\", self.inner.url)?;\n        if let SourceIdInner {\n            kind: SourceKind::Git(ref reference),\n            ref precise,\n            ..\n        } = *self.inner\n        {\n            if let Some(pretty) = reference.pretty_ref(self.encoded) {\n                write!(f, \"?{}\", pretty)?;\n            }\n            if let Some(precise) = precise.as_ref() {\n                write!(f, \"#{}\", precise)?;\n            }\n        }\n        Ok(())\n    }\n}\n\nimpl KeyOf {\n    /// Gets the underlying key.\n    fn key(&self) -> &str {\n        match self {\n            KeyOf::Registry(k) | KeyOf::Source(k) => k,\n        }\n    }\n\n    /// Gets the key if it's from an alternative registry.\n    fn alternative_registry(&self) -> Option<&str> {\n        match self {\n            KeyOf::Registry(k) => Some(k),\n            _ => None,\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::{GitReference, SourceId, SourceKind};\n    use crate::util::{GlobalContext, IntoUrl};\n\n    #[test]\n    fn github_sources_equal() {\n        let loc = \"https://github.com/foo/bar\".into_url().unwrap();\n        let default = SourceKind::Git(GitReference::DefaultBranch);\n        let s1 = SourceId::new(default.clone(), loc, None).unwrap();\n\n        let loc = \"git://github.com/foo/bar\".into_url().unwrap();\n        let s2 = SourceId::new(default, loc.clone(), None).unwrap();\n\n        assert_eq!(s1, s2);\n\n        let foo = SourceKind::Git(GitReference::Branch(\"foo\".to_string()));\n        let s3 = SourceId::new(foo, loc, None).unwrap();\n        assert_ne!(s1, s3);\n    }\n\n    // This is a test that the hash of the `SourceId` for crates.io is a well-known\n    // value.\n    //\n    // Note that the hash value matches what the crates.io source id has hashed\n    // since Rust 1.84.0. We strive to keep this value the same across\n    // versions of Cargo because changing it means that users will need to\n    // redownload the index and all crates they use when using a new Cargo version.\n    //\n    // This isn't to say that this hash can *never* change, only that when changing\n    // this it should be explicitly done. If this hash changes accidentally and\n    // you're able to restore the hash to its original value, please do so!\n    // Otherwise please just leave a comment in your PR as to why the hash value is\n    // changing and why the old value can't be easily preserved.\n    // If it takes an ugly hack to restore it,\n    // then leave a link here so we can remove the hack next time we change the hash.\n    //\n    // Hacks to remove next time the hash changes:\n    // - (fill in your code here)\n    //\n    // The hash value should be stable across platforms, and doesn't depend on\n    // endianness and bit-width. One caveat is that absolute paths on Windows\n    // are inherently different than on Unix-like platforms. Unless we omit or\n    // strip the prefix components (e.g. `C:`), there is not way to have a true\n    // cross-platform stable hash for absolute paths.\n    #[test]\n    fn test_stable_hash() {\n        use std::hash::Hasher;\n        use std::path::Path;\n\n        use snapbox::IntoData as _;\n        use snapbox::assert_data_eq;\n        use snapbox::str;\n\n        use crate::util::StableHasher;\n        use crate::util::hex::short_hash;\n\n        #[cfg(not(windows))]\n        let ws_root = Path::new(\"/tmp/ws\");\n        #[cfg(windows)]\n        let ws_root = Path::new(r\"C:\\\\tmp\\ws\");\n\n        let gen_hash = |source_id: SourceId| {\n            let mut hasher = StableHasher::new();\n            source_id.stable_hash(ws_root, &mut hasher);\n            Hasher::finish(&hasher).to_string()\n        };\n\n        let source_id = SourceId::crates_io(&GlobalContext::default().unwrap()).unwrap();\n        assert_data_eq!(gen_hash(source_id), str![\"7062945687441624357\"].raw());\n        assert_data_eq!(short_hash(&source_id), str![\"25cdd57fae9f0462\"].raw());\n\n        let url = \"https://my-crates.io\".into_url().unwrap();\n        let source_id = SourceId::for_registry(&url).unwrap();\n        assert_data_eq!(gen_hash(source_id), str![\"8310250053664888498\"].raw());\n        assert_data_eq!(short_hash(&source_id), str![\"b2d65deb64f05373\"].raw());\n\n        let url = \"https://your-crates.io\".into_url().unwrap();\n        let source_id = SourceId::for_alt_registry(&url, \"alt\").unwrap();\n        assert_data_eq!(gen_hash(source_id), str![\"14149534903000258933\"].raw());\n        assert_data_eq!(short_hash(&source_id), str![\"755952de063f5dc4\"].raw());\n\n        let url = \"sparse+https://my-crates.io\".into_url().unwrap();\n        let source_id = SourceId::for_registry(&url).unwrap();\n        assert_data_eq!(gen_hash(source_id), str![\"16249512552851930162\"].raw());\n        assert_data_eq!(short_hash(&source_id), str![\"327cfdbd92dd81e1\"].raw());\n\n        let url = \"sparse+https://your-crates.io\".into_url().unwrap();\n        let source_id = SourceId::for_alt_registry(&url, \"alt\").unwrap();\n        assert_data_eq!(gen_hash(source_id), str![\"6156697384053352292\"].raw());\n        assert_data_eq!(short_hash(&source_id), str![\"64a713b6a6fb7055\"].raw());\n\n        let url = \"file:///tmp/ws/crate\".into_url().unwrap();\n        let source_id = SourceId::for_git(&url, GitReference::DefaultBranch).unwrap();\n        assert_data_eq!(gen_hash(source_id), str![\"473480029881867801\"].raw());\n        assert_data_eq!(short_hash(&source_id), str![\"199e591d94239206\"].raw());\n\n        let path = &ws_root.join(\"crate\");\n        let source_id = SourceId::for_local_registry(path).unwrap();\n        #[cfg(not(windows))]\n        {\n            assert_data_eq!(gen_hash(source_id), str![\"11515846423845066584\"].raw());\n            assert_data_eq!(short_hash(&source_id), str![\"58d73c154f81d09f\"].raw());\n        }\n        #[cfg(windows)]\n        {\n            assert_data_eq!(gen_hash(source_id), str![\"6146331155906064276\"].raw());\n            assert_data_eq!(short_hash(&source_id), str![\"946fb2239f274c55\"].raw());\n        }\n\n        let source_id = SourceId::for_path(path).unwrap();\n        assert_data_eq!(gen_hash(source_id), str![\"215644081443634269\"].raw());\n        #[cfg(not(windows))]\n        assert_data_eq!(short_hash(&source_id), str![\"64bace89c92b101f\"].raw());\n        #[cfg(windows)]\n        assert_data_eq!(short_hash(&source_id), str![\"01e1e6c391813fb6\"].raw());\n\n        let source_id = SourceId::for_directory(path).unwrap();\n        #[cfg(not(windows))]\n        {\n            assert_data_eq!(gen_hash(source_id), str![\"6127590343904940368\"].raw());\n            assert_data_eq!(short_hash(&source_id), str![\"505191d1f3920955\"].raw());\n        }\n        #[cfg(windows)]\n        {\n            assert_data_eq!(gen_hash(source_id), str![\"10423446877655960172\"].raw());\n            assert_data_eq!(short_hash(&source_id), str![\"6c8ad69db585a790\"].raw());\n        }\n    }\n\n    #[test]\n    fn serde_roundtrip() {\n        let url = \"sparse+https://my-crates.io/\".into_url().unwrap();\n        let source_id = SourceId::for_registry(&url).unwrap();\n        let formatted = format!(\"{}\", source_id.as_url());\n        let deserialized = SourceId::from_url(&formatted).unwrap();\n        assert_eq!(formatted, \"sparse+https://my-crates.io/\");\n        assert_eq!(source_id, deserialized);\n    }\n\n    #[test]\n    fn gitrefs_roundtrip() {\n        let base = \"https://host/path\".into_url().unwrap();\n        let branch = GitReference::Branch(\"*-._+20%30 Z/z#foo=bar&zap[]?to\\\\()'\\\"\".to_string());\n        let s1 = SourceId::for_git(&base, branch).unwrap();\n        let ser1 = format!(\"{}\", s1.as_encoded_url());\n        let s2 = SourceId::from_url(&ser1).expect(\"Failed to deserialize\");\n        let ser2 = format!(\"{}\", s2.as_encoded_url());\n        // Serializing twice should yield the same result\n        assert_eq!(ser1, ser2, \"Serialized forms don't match\");\n        // SourceId serializing the same should have the same semantics\n        // This used to not be the case (# was ambiguous)\n        assert_eq!(s1, s2, \"SourceId doesn't round-trip\");\n        // Freeze the format to match an x-www-form-urlencoded query string\n        // https://url.spec.whatwg.org/#application/x-www-form-urlencoded\n        assert_eq!(\n            ser1,\n            \"git+https://host/path?branch=*-._%2B20%2530+Z%2Fz%23foo%3Dbar%26zap%5B%5D%3Fto%5C%28%29%27%22\"\n        );\n    }\n}\n\n/// Check if `url` equals to the overridden crates.io URL.\n#[expect(\n    clippy::disallowed_methods,\n    reason = \"testing only, no reason for config support\"\n)]\nfn is_overridden_crates_io_url(url: &str) -> bool {\n    std::env::var(\"__CARGO_TEST_CRATES_IO_URL_DO_NOT_USE_THIS\").map_or(false, |v| v == url)\n}\n"
  },
  {
    "path": "src/cargo/core/summary.rs",
    "content": "use crate::core::{Dependency, PackageId, SourceId};\nuse crate::util::CargoResult;\nuse crate::util::closest_msg;\nuse crate::util::interning::InternedString;\nuse anyhow::bail;\nuse cargo_util_schemas::manifest::FeatureName;\nuse cargo_util_schemas::manifest::RustVersion;\nuse semver::Version;\nuse std::collections::{BTreeMap, HashMap, HashSet};\nuse std::fmt;\nuse std::hash::{Hash, Hasher};\nuse std::mem;\nuse std::sync::Arc;\n\n/// Subset of a `Manifest`. Contains only the most important information about\n/// a package.\n///\n/// Summaries are cloned, and should not be mutated after creation\n#[derive(Debug, Clone)]\npub struct Summary {\n    inner: Arc<Inner>,\n}\n\n#[derive(Debug, Clone)]\nstruct Inner {\n    package_id: PackageId,\n    dependencies: Vec<Dependency>,\n    features: Arc<FeatureMap>,\n    checksum: Option<String>,\n    links: Option<InternedString>,\n    rust_version: Option<RustVersion>,\n    pubtime: Option<jiff::Timestamp>,\n}\n\n/// Indicates the dependency inferred from the `dep` syntax that should exist,\n/// but missing on the resolved dependencies tables.\n#[derive(Debug)]\npub struct MissingDependencyError {\n    pub dep_name: InternedString,\n    pub feature: InternedString,\n    pub feature_value: FeatureValue,\n    /// Indicates the dependency inferred from the `dep?` syntax that is weak optional\n    pub weak_optional: bool,\n}\n\nimpl std::error::Error for MissingDependencyError {}\n\nimpl fmt::Display for MissingDependencyError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let Self {\n            dep_name,\n            feature,\n            feature_value: fv,\n            ..\n        } = self;\n\n        write!(\n            f,\n            \"feature `{feature}` includes `{fv}`, but `{dep_name}` is not a dependency\",\n        )\n    }\n}\n\nimpl Summary {\n    #[tracing::instrument(skip_all)]\n    pub fn new(\n        pkg_id: PackageId,\n        dependencies: Vec<Dependency>,\n        features: &BTreeMap<InternedString, Vec<InternedString>>,\n        links: Option<impl Into<InternedString>>,\n        rust_version: Option<RustVersion>,\n    ) -> CargoResult<Summary> {\n        // ****CAUTION**** If you change anything here that may raise a new\n        // error, be sure to coordinate that change with either the index\n        // schema field or the SummariesCache version.\n        for dep in dependencies.iter() {\n            let dep_name = dep.name_in_toml();\n            if dep.is_optional() && !dep.is_transitive() {\n                bail!(\n                    \"dev-dependencies are not allowed to be optional: `{}`\",\n                    dep_name\n                )\n            }\n        }\n        let feature_map = build_feature_map(features, &dependencies)?;\n        Ok(Summary {\n            inner: Arc::new(Inner {\n                package_id: pkg_id,\n                dependencies,\n                features: Arc::new(feature_map),\n                checksum: None,\n                links: links.map(|l| l.into()),\n                rust_version,\n                pubtime: None,\n            }),\n        })\n    }\n\n    pub fn package_id(&self) -> PackageId {\n        self.inner.package_id\n    }\n    pub fn name(&self) -> InternedString {\n        self.package_id().name()\n    }\n    pub fn version(&self) -> &Version {\n        self.package_id().version()\n    }\n    pub fn source_id(&self) -> SourceId {\n        self.package_id().source_id()\n    }\n    pub fn dependencies(&self) -> &[Dependency] {\n        &self.inner.dependencies\n    }\n    pub fn features(&self) -> &FeatureMap {\n        &self.inner.features\n    }\n\n    pub fn checksum(&self) -> Option<&str> {\n        self.inner.checksum.as_deref()\n    }\n    pub fn links(&self) -> Option<InternedString> {\n        self.inner.links\n    }\n\n    pub fn rust_version(&self) -> Option<&RustVersion> {\n        self.inner.rust_version.as_ref()\n    }\n\n    pub fn pubtime(&self) -> Option<jiff::Timestamp> {\n        self.inner.pubtime\n    }\n\n    pub fn override_id(mut self, id: PackageId) -> Summary {\n        Arc::make_mut(&mut self.inner).package_id = id;\n        self\n    }\n\n    pub fn set_checksum(&mut self, cksum: String) {\n        Arc::make_mut(&mut self.inner).checksum = Some(cksum);\n    }\n\n    pub fn set_pubtime(&mut self, pubtime: jiff::Timestamp) {\n        Arc::make_mut(&mut self.inner).pubtime = Some(pubtime);\n    }\n\n    pub fn map_dependencies<F>(self, mut f: F) -> Summary\n    where\n        F: FnMut(Dependency) -> Dependency,\n    {\n        self.try_map_dependencies(|dep| Ok(f(dep))).unwrap()\n    }\n\n    pub fn try_map_dependencies<F>(mut self, f: F) -> CargoResult<Summary>\n    where\n        F: FnMut(Dependency) -> CargoResult<Dependency>,\n    {\n        {\n            let slot = &mut Arc::make_mut(&mut self.inner).dependencies;\n            *slot = mem::take(slot)\n                .into_iter()\n                .map(f)\n                .collect::<CargoResult<_>>()?;\n        }\n        Ok(self)\n    }\n\n    pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Summary {\n        let me = if self.package_id().source_id() == to_replace {\n            let new_id = self.package_id().with_source_id(replace_with);\n            self.override_id(new_id)\n        } else {\n            self\n        };\n        me.map_dependencies(|dep| dep.map_source(to_replace, replace_with))\n    }\n}\n\nimpl PartialEq for Summary {\n    fn eq(&self, other: &Summary) -> bool {\n        self.inner.package_id == other.inner.package_id\n    }\n}\n\nimpl Eq for Summary {}\n\nimpl Hash for Summary {\n    fn hash<H: Hasher>(&self, state: &mut H) {\n        self.inner.package_id.hash(state);\n    }\n}\n\n// A check that only compiles if Summary is Sync\nconst _: fn() = || {\n    fn is_sync<T: Sync>() {}\n    is_sync::<Summary>();\n};\n\n/// Checks features for errors, bailing out a CargoResult:Err if invalid,\n/// and creates `FeatureValues` for each feature.\nfn build_feature_map(\n    features: &BTreeMap<InternedString, Vec<InternedString>>,\n    dependencies: &[Dependency],\n) -> CargoResult<FeatureMap> {\n    use self::FeatureValue::*;\n    // A map of dependency names to whether there are any that are optional.\n    let mut dep_map: HashMap<InternedString, bool> = HashMap::new();\n    for dep in dependencies.iter() {\n        *dep_map.entry(dep.name_in_toml()).or_insert(false) |= dep.is_optional();\n    }\n    let dep_map = dep_map; // We are done mutating this variable\n\n    let mut map: FeatureMap = features\n        .iter()\n        .map(|(feature, list)| {\n            let fvs: Vec<_> = list\n                .iter()\n                .map(|feat_value| FeatureValue::new(*feat_value))\n                .collect();\n            (*feature, fvs)\n        })\n        .collect();\n\n    // Add implicit features for optional dependencies if they weren't\n    // explicitly listed anywhere.\n    let explicitly_listed: HashSet<_> = map\n        .values()\n        .flatten()\n        .filter_map(|fv| fv.explicit_dep_name())\n        .collect();\n\n    for dep in dependencies {\n        if !dep.is_optional() {\n            continue;\n        }\n        let dep_name = dep.name_in_toml();\n        if features.contains_key(&dep_name) || explicitly_listed.contains(&dep_name) {\n            continue;\n        }\n        map.insert(dep_name, vec![Dep { dep_name }]);\n    }\n    let map = map; // We are done mutating this variable\n\n    // Validate features are listed properly.\n    for (feature, fvs) in &map {\n        FeatureName::new(feature)?;\n        for fv in fvs {\n            // Find data for the referenced dependency...\n            let dep_data = dep_map.get(&fv.feature_or_dep_name());\n            let is_any_dep = dep_data.is_some();\n            let is_optional_dep = dep_data.is_some_and(|&o| o);\n            match fv {\n                Feature(f) => {\n                    if !features.contains_key(f) {\n                        if !is_any_dep {\n                            let closest = closest_msg(f, features.keys(), |k| k, \"feature\");\n                            bail!(\n                                \"feature `{feature}` includes `{fv}` which is neither a dependency \\\n                                 nor another feature{closest}\"\n                            );\n                        }\n                        if is_optional_dep {\n                            if !map.contains_key(f) {\n                                bail!(\n                                    \"feature `{feature}` includes `{fv}`, but `{f}` is an \\\n                                     optional dependency without an implicit feature\\n\\\n                                     Use `dep:{f}` to enable the dependency.\"\n                                );\n                            }\n                        } else {\n                            bail!(\n                                \"feature `{feature}` includes `{fv}`, but `{f}` is not an optional dependency\\n\\\n                                A non-optional dependency of the same name is defined; \\\n                                consider adding `optional = true` to its definition.\"\n                            );\n                        }\n                    }\n                }\n                Dep { dep_name } => {\n                    if !is_any_dep {\n                        bail!(\n                            \"feature `{feature}` includes `{fv}`, but `{dep_name}` is not listed as a dependency\"\n                        );\n                    }\n                    if !is_optional_dep {\n                        bail!(\n                            \"feature `{feature}` includes `{fv}`, but `{dep_name}` is not an optional dependency\\n\\\n                             A non-optional dependency of the same name is defined; \\\n                             consider adding `optional = true` to its definition.\"\n                        );\n                    }\n                }\n                DepFeature {\n                    dep_name,\n                    dep_feature,\n                    weak,\n                } => {\n                    // Early check for some unlikely syntax.\n                    if dep_feature.contains('/') {\n                        bail!(\n                            \"multiple slashes in feature `{fv}` (included by feature `{feature}`) are not allowed\"\n                        );\n                    }\n\n                    // dep: cannot be combined with /\n                    if let Some(stripped_dep) = dep_name.strip_prefix(\"dep:\") {\n                        let has_other_dep = explicitly_listed.contains(stripped_dep);\n                        let is_optional = dep_map.get(stripped_dep).is_some_and(|&o| o);\n                        let extra_help = if *weak || has_other_dep || !is_optional {\n                            // In this case, the user should just remove dep:.\n                            // Note that \"hiding\" an optional dependency\n                            // wouldn't work with just a single `dep:foo?/bar`\n                            // because there would not be any way to enable\n                            // `foo`.\n                            String::new()\n                        } else {\n                            format!(\n                                \"\\nIf the intent is to avoid creating an implicit feature \\\n                                 `{stripped_dep}` for an optional dependency, \\\n                                 then consider replacing this with two values:\\n    \\\n                                 \\\"dep:{stripped_dep}\\\", \\\"{stripped_dep}/{dep_feature}\\\"\"\n                            )\n                        };\n                        bail!(\n                            \"feature `{feature}` includes `{fv}` with both `dep:` and `/`\\n\\\n                            To fix this, remove the `dep:` prefix.{extra_help}\"\n                        )\n                    }\n\n                    // Validation of the feature name will be performed in the resolver.\n                    if !is_any_dep {\n                        bail!(MissingDependencyError {\n                            feature: *feature,\n                            feature_value: (*fv).clone(),\n                            dep_name: *dep_name,\n                            weak_optional: *weak,\n                        })\n                    }\n                    if *weak && !is_optional_dep {\n                        bail!(\n                            \"feature `{feature}` includes `{fv}` with a `?`, but `{dep_name}` is not an optional dependency\\n\\\n                            A non-optional dependency of the same name is defined; \\\n                            consider removing the `?` or changing the dependency to be optional\"\n                        );\n                    }\n                }\n            }\n        }\n    }\n\n    // Make sure every optional dep is mentioned at least once.\n    let used: HashSet<_> = map\n        .values()\n        .flatten()\n        .filter_map(|fv| match fv {\n            Dep { dep_name } | DepFeature { dep_name, .. } => Some(dep_name),\n            _ => None,\n        })\n        .collect();\n    if let Some((dep, _)) = dep_map\n        .iter()\n        .find(|&(dep, &is_optional)| is_optional && !used.contains(dep))\n    {\n        bail!(\n            \"optional dependency `{dep}` is not included in any feature\\n\\\n            Make sure that `dep:{dep}` is included in one of features in the [features] table.\"\n        );\n    }\n\n    Ok(map)\n}\n\n/// `FeatureValue` represents the types of dependencies a feature can have.\n#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]\npub enum FeatureValue {\n    /// A feature enabling another feature.\n    Feature(InternedString),\n    /// A feature enabling a dependency with `dep:dep_name` syntax.\n    Dep { dep_name: InternedString },\n    /// A feature enabling a feature on a dependency with `crate_name/feat_name` syntax.\n    DepFeature {\n        dep_name: InternedString,\n        dep_feature: InternedString,\n        /// If `true`, indicates the `?` syntax is used, which means this will\n        /// not automatically enable the dependency unless the dependency is\n        /// activated through some other means.\n        weak: bool,\n    },\n}\n\nimpl FeatureValue {\n    pub fn new(feature: InternedString) -> FeatureValue {\n        match feature.split_once('/') {\n            Some((dep, dep_feat)) => {\n                let dep_name = dep.strip_suffix('?');\n                FeatureValue::DepFeature {\n                    dep_name: dep_name.unwrap_or(dep).into(),\n                    dep_feature: dep_feat.into(),\n                    weak: dep_name.is_some(),\n                }\n            }\n            None => {\n                if let Some(dep_name) = feature.strip_prefix(\"dep:\") {\n                    FeatureValue::Dep {\n                        dep_name: dep_name.into(),\n                    }\n                } else {\n                    FeatureValue::Feature(feature)\n                }\n            }\n        }\n    }\n\n    /// Returns the name of the dependency if and only if it was explicitly named with the `dep:` syntax.\n    fn explicit_dep_name(&self) -> Option<InternedString> {\n        match self {\n            FeatureValue::Dep { dep_name, .. } => Some(*dep_name),\n            _ => None,\n        }\n    }\n\n    fn feature_or_dep_name(&self) -> InternedString {\n        match self {\n            FeatureValue::Feature(dep_name)\n            | FeatureValue::Dep { dep_name, .. }\n            | FeatureValue::DepFeature { dep_name, .. } => *dep_name,\n        }\n    }\n}\n\nimpl fmt::Display for FeatureValue {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        use self::FeatureValue::*;\n        match self {\n            Feature(feat) => write!(f, \"{feat}\"),\n            Dep { dep_name } => write!(f, \"dep:{dep_name}\"),\n            DepFeature {\n                dep_name,\n                dep_feature,\n                weak,\n            } => {\n                let weak = if *weak { \"?\" } else { \"\" };\n                write!(f, \"{dep_name}{weak}/{dep_feature}\")\n            }\n        }\n    }\n}\n\npub type FeatureMap = BTreeMap<InternedString, Vec<FeatureValue>>;\n"
  },
  {
    "path": "src/cargo/core/workspace.rs",
    "content": "use std::cell::RefCell;\nuse std::collections::hash_map::{Entry, HashMap};\nuse std::collections::{BTreeMap, BTreeSet, HashSet};\nuse std::path::{Path, PathBuf};\nuse std::rc::Rc;\n\nuse annotate_snippets::Level;\nuse anyhow::{Context as _, anyhow, bail};\nuse glob::glob;\nuse itertools::Itertools;\nuse tracing::debug;\nuse url::Url;\n\nuse crate::core::compiler::Unit;\nuse crate::core::features::Features;\nuse crate::core::registry::PackageRegistry;\nuse crate::core::resolver::ResolveBehavior;\nuse crate::core::resolver::features::CliFeatures;\nuse crate::core::{\n    Dependency, Edition, FeatureValue, PackageId, PackageIdSpec, PackageIdSpecQuery, Patch,\n    PatchLocation,\n};\nuse crate::core::{EitherManifest, Package, SourceId, VirtualManifest};\nuse crate::lints::analyze_cargo_lints_table;\nuse crate::lints::rules::blanket_hint_mostly_unused;\nuse crate::lints::rules::check_im_a_teapot;\nuse crate::lints::rules::implicit_minimum_version_req_pkg;\nuse crate::lints::rules::implicit_minimum_version_req_ws;\nuse crate::lints::rules::missing_lints_inheritance;\nuse crate::lints::rules::non_kebab_case_bins;\nuse crate::lints::rules::non_kebab_case_features;\nuse crate::lints::rules::non_kebab_case_packages;\nuse crate::lints::rules::non_snake_case_features;\nuse crate::lints::rules::non_snake_case_packages;\nuse crate::lints::rules::redundant_homepage;\nuse crate::lints::rules::redundant_readme;\nuse crate::lints::rules::unused_workspace_dependencies;\nuse crate::lints::rules::unused_workspace_package_fields;\nuse crate::ops;\nuse crate::ops::lockfile::LOCKFILE_NAME;\nuse crate::sources::{CRATES_IO_INDEX, CRATES_IO_REGISTRY, PathSource, SourceConfigMap};\nuse crate::util::context;\nuse crate::util::context::{FeatureUnification, Value};\nuse crate::util::edit_distance;\nuse crate::util::errors::{CargoResult, ManifestError};\nuse crate::util::interning::InternedString;\nuse crate::util::toml::{InheritableFields, read_manifest};\nuse crate::util::{\n    Filesystem, GlobalContext, IntoUrl, context::CargoResolverConfig, context::ConfigRelativePath,\n    context::IncompatibleRustVersions,\n};\n\nuse cargo_util::paths;\nuse cargo_util::paths::normalize_path;\nuse cargo_util_schemas::manifest;\nuse cargo_util_schemas::manifest::RustVersion;\nuse cargo_util_schemas::manifest::{TomlDependency, TomlManifest, TomlProfiles};\nuse pathdiff::diff_paths;\n\n/// The core abstraction in Cargo for working with a workspace of crates.\n///\n/// A workspace is often created very early on and then threaded through all\n/// other functions. It's typically through this object that the current\n/// package is loaded and/or learned about.\n#[derive(Debug)]\npub struct Workspace<'gctx> {\n    /// Cargo configuration information. See [`GlobalContext`].\n    gctx: &'gctx GlobalContext,\n\n    /// This path is a path to where the current cargo subcommand was invoked\n    /// from. That is the `--manifest-path` argument to Cargo, and\n    /// points to the \"main crate\" that we're going to worry about.\n    current_manifest: PathBuf,\n\n    /// A list of packages found in this workspace. Always includes at least the\n    /// package mentioned by `current_manifest`.\n    packages: Packages<'gctx>,\n\n    /// If this workspace includes more than one crate, this points to the root\n    /// of the workspace. This is `None` in the case that `[workspace]` is\n    /// missing, `package.workspace` is missing, and no `Cargo.toml` above\n    /// `current_manifest` was found on the filesystem with `[workspace]`.\n    root_manifest: Option<PathBuf>,\n\n    /// Shared target directory for all the packages of this workspace.\n    /// `None` if the default path of `root/target` should be used.\n    target_dir: Option<Filesystem>,\n\n    /// Shared build directory for intermediate build artifacts.\n    /// This directory may be shared between multiple workspaces.\n    build_dir: Option<Filesystem>,\n\n    /// List of members in this workspace with a listing of all their manifest\n    /// paths. The packages themselves can be looked up through the `packages`\n    /// set above.\n    members: Vec<PathBuf>,\n    /// Set of ids of workspace members\n    member_ids: HashSet<PackageId>,\n\n    /// The subset of `members` that are used by the\n    /// `build`, `check`, `test`, and `bench` subcommands\n    /// when no package is selected with `--package` / `-p` and `--workspace`\n    /// is not used.\n    ///\n    /// This is set by the `default-members` config\n    /// in the `[workspace]` section.\n    /// When unset, this is the same as `members` for virtual workspaces\n    /// (`--workspace` is implied)\n    /// or only the root package for non-virtual workspaces.\n    default_members: Vec<PathBuf>,\n\n    /// `true` if this is a temporary workspace created for the purposes of the\n    /// `cargo install` or `cargo package` commands.\n    is_ephemeral: bool,\n\n    /// `true` if this workspace should enforce optional dependencies even when\n    /// not needed; false if this workspace should only enforce dependencies\n    /// needed by the current configuration (such as in cargo install). In some\n    /// cases `false` also results in the non-enforcement of dev-dependencies.\n    require_optional_deps: bool,\n\n    /// A cache of loaded packages for particular paths which is disjoint from\n    /// `packages` up above, used in the `load` method down below.\n    loaded_packages: RefCell<HashMap<PathBuf, Package>>,\n\n    /// If `true`, then the resolver will ignore any existing `Cargo.lock`\n    /// file. This is set for `cargo install` without `--locked`.\n    ignore_lock: bool,\n\n    /// Requested path of the lockfile (i.e. passed as the cli flag)\n    requested_lockfile_path: Option<PathBuf>,\n\n    /// The resolver behavior specified with the `resolver` field.\n    resolve_behavior: ResolveBehavior,\n    /// If `true`, then workspace `rust_version` would be used in `cargo resolve`\n    /// and other places that use rust version.\n    /// This is set based on the resolver version, config settings, and CLI flags.\n    resolve_honors_rust_version: bool,\n    /// The feature unification mode used when building packages.\n    resolve_feature_unification: FeatureUnification,\n    /// Latest publish time allowed for packages\n    resolve_publish_time: Option<jiff::Timestamp>,\n    /// Workspace-level custom metadata\n    custom_metadata: Option<toml::Value>,\n\n    /// Local overlay configuration. See [`crate::sources::overlay`].\n    local_overlays: HashMap<SourceId, PathBuf>,\n}\n\n// Separate structure for tracking loaded packages (to avoid loading anything\n// twice), and this is separate to help appease the borrow checker.\n#[derive(Debug)]\nstruct Packages<'gctx> {\n    gctx: &'gctx GlobalContext,\n    packages: HashMap<PathBuf, MaybePackage>,\n}\n\n#[derive(Debug)]\npub enum MaybePackage {\n    Package(Package),\n    Virtual(VirtualManifest),\n}\n\n/// Configuration of a workspace in a manifest.\n#[derive(Debug, Clone)]\npub enum WorkspaceConfig {\n    /// Indicates that `[workspace]` was present and the members were\n    /// optionally specified as well.\n    Root(WorkspaceRootConfig),\n\n    /// Indicates that `[workspace]` was present and the `root` field is the\n    /// optional value of `package.workspace`, if present.\n    Member { root: Option<String> },\n}\n\nimpl WorkspaceConfig {\n    pub fn inheritable(&self) -> Option<&InheritableFields> {\n        match self {\n            WorkspaceConfig::Root(root) => Some(&root.inheritable_fields),\n            WorkspaceConfig::Member { .. } => None,\n        }\n    }\n\n    /// Returns the path of the workspace root based on this `[workspace]` configuration.\n    ///\n    /// Returns `None` if the root is not explicitly known.\n    ///\n    /// * `self_path` is the path of the manifest this `WorkspaceConfig` is located.\n    /// * `look_from` is the path where discovery started (usually the current\n    ///   working directory), used for `workspace.exclude` checking.\n    fn get_ws_root(&self, self_path: &Path, look_from: &Path) -> Option<PathBuf> {\n        match self {\n            WorkspaceConfig::Root(ances_root_config) => {\n                debug!(\"find_root - found a root checking exclusion\");\n                if !ances_root_config.is_excluded(look_from) {\n                    debug!(\"find_root - found!\");\n                    Some(self_path.to_owned())\n                } else {\n                    None\n                }\n            }\n            WorkspaceConfig::Member {\n                root: Some(path_to_root),\n            } => {\n                debug!(\"find_root - found pointer\");\n                Some(read_root_pointer(self_path, path_to_root))\n            }\n            WorkspaceConfig::Member { .. } => None,\n        }\n    }\n}\n\n/// Intermediate configuration of a workspace root in a manifest.\n///\n/// Knows the Workspace Root path, as well as `members` and `exclude` lists of path patterns, which\n/// together tell if some path is recognized as a member by this root or not.\n#[derive(Debug, Clone)]\npub struct WorkspaceRootConfig {\n    root_dir: PathBuf,\n    members: Option<Vec<String>>,\n    default_members: Option<Vec<String>>,\n    exclude: Vec<String>,\n    inheritable_fields: InheritableFields,\n    custom_metadata: Option<toml::Value>,\n}\n\nimpl<'gctx> Workspace<'gctx> {\n    /// Creates a new workspace given the target manifest pointed to by\n    /// `manifest_path`.\n    ///\n    /// This function will construct the entire workspace by determining the\n    /// root and all member packages. It will then validate the workspace\n    /// before returning it, so `Ok` is only returned for valid workspaces.\n    pub fn new(manifest_path: &Path, gctx: &'gctx GlobalContext) -> CargoResult<Workspace<'gctx>> {\n        let mut ws = Workspace::new_default(manifest_path.to_path_buf(), gctx);\n\n        if manifest_path.is_relative() {\n            bail!(\n                \"manifest_path:{:?} is not an absolute path. Please provide an absolute path.\",\n                manifest_path\n            )\n        } else {\n            ws.root_manifest = ws.find_root(manifest_path)?;\n        }\n\n        ws.target_dir = gctx.target_dir()?;\n        ws.build_dir = gctx.build_dir(ws.root_manifest())?;\n\n        ws.custom_metadata = ws\n            .load_workspace_config()?\n            .and_then(|cfg| cfg.custom_metadata);\n        ws.find_members()?;\n        ws.set_resolve_behavior()?;\n        ws.validate()?;\n        Ok(ws)\n    }\n\n    fn new_default(current_manifest: PathBuf, gctx: &'gctx GlobalContext) -> Workspace<'gctx> {\n        Workspace {\n            gctx,\n            current_manifest,\n            packages: Packages {\n                gctx,\n                packages: HashMap::new(),\n            },\n            root_manifest: None,\n            target_dir: None,\n            build_dir: None,\n            members: Vec::new(),\n            member_ids: HashSet::new(),\n            default_members: Vec::new(),\n            is_ephemeral: false,\n            require_optional_deps: true,\n            loaded_packages: RefCell::new(HashMap::new()),\n            ignore_lock: false,\n            requested_lockfile_path: None,\n            resolve_behavior: ResolveBehavior::V1,\n            resolve_honors_rust_version: false,\n            resolve_feature_unification: FeatureUnification::Selected,\n            resolve_publish_time: None,\n            custom_metadata: None,\n            local_overlays: HashMap::new(),\n        }\n    }\n\n    /// Creates a \"temporary workspace\" from one package which only contains\n    /// that package.\n    ///\n    /// This constructor will not touch the filesystem and only creates an\n    /// in-memory workspace. That is, all configuration is ignored, it's just\n    /// intended for that one package.\n    ///\n    /// This is currently only used in niche situations like `cargo install` or\n    /// `cargo package`.\n    pub fn ephemeral(\n        package: Package,\n        gctx: &'gctx GlobalContext,\n        target_dir: Option<Filesystem>,\n        require_optional_deps: bool,\n    ) -> CargoResult<Workspace<'gctx>> {\n        let mut ws = Workspace::new_default(package.manifest_path().to_path_buf(), gctx);\n        ws.is_ephemeral = true;\n        ws.require_optional_deps = require_optional_deps;\n        let id = package.package_id();\n        let package = MaybePackage::Package(package);\n        ws.packages\n            .packages\n            .insert(ws.current_manifest.clone(), package);\n        ws.target_dir = if let Some(dir) = target_dir {\n            Some(dir)\n        } else {\n            ws.gctx.target_dir()?\n        };\n        ws.build_dir = ws.target_dir.clone();\n        ws.members.push(ws.current_manifest.clone());\n        ws.member_ids.insert(id);\n        ws.default_members.push(ws.current_manifest.clone());\n        ws.set_resolve_behavior()?;\n        Ok(ws)\n    }\n\n    /// Reloads the workspace.\n    ///\n    /// This is useful if the workspace has been updated, such as with `cargo\n    /// fix` modifying the `Cargo.toml` file.\n    pub fn reload(&self, gctx: &'gctx GlobalContext) -> CargoResult<Workspace<'gctx>> {\n        let mut ws = Workspace::new(&self.current_manifest, gctx)?;\n        ws.set_resolve_honors_rust_version(Some(self.resolve_honors_rust_version));\n        ws.set_resolve_feature_unification(self.resolve_feature_unification);\n        ws.set_requested_lockfile_path(self.requested_lockfile_path.clone());\n        Ok(ws)\n    }\n\n    fn set_resolve_behavior(&mut self) -> CargoResult<()> {\n        // - If resolver is specified in the workspace definition, use that.\n        // - If the root package specifies the resolver, use that.\n        // - If the root package specifies edition 2021, use v2.\n        // - Otherwise, use the default v1.\n        self.resolve_behavior = match self.root_maybe() {\n            MaybePackage::Package(p) => p\n                .manifest()\n                .resolve_behavior()\n                .unwrap_or_else(|| p.manifest().edition().default_resolve_behavior()),\n            MaybePackage::Virtual(vm) => vm.resolve_behavior().unwrap_or(ResolveBehavior::V1),\n        };\n\n        match self.resolve_behavior() {\n            ResolveBehavior::V1 | ResolveBehavior::V2 => {}\n            ResolveBehavior::V3 => {\n                if self.resolve_behavior == ResolveBehavior::V3 {\n                    self.resolve_honors_rust_version = true;\n                }\n            }\n        }\n        let config = self.gctx().get::<CargoResolverConfig>(\"resolver\")?;\n        if let Some(incompatible_rust_versions) = config.incompatible_rust_versions {\n            self.resolve_honors_rust_version =\n                incompatible_rust_versions == IncompatibleRustVersions::Fallback;\n        }\n        if self.gctx().cli_unstable().feature_unification {\n            self.resolve_feature_unification = config\n                .feature_unification\n                .unwrap_or(FeatureUnification::Selected);\n        } else if config.feature_unification.is_some() {\n            self.gctx()\n                .shell()\n                .warn(\"ignoring `resolver.feature-unification` without `-Zfeature-unification`\")?;\n        };\n\n        if let Some(lockfile_path) = config.lockfile_path {\n            if self.gctx().cli_unstable().lockfile_path {\n                // Reserve the ability to add templates in the future.\n                let replacements: [(&str, &str); 0] = [];\n                let path = lockfile_path\n                    .resolve_templated_path(self.gctx(), replacements)\n                    .map_err(|e| match e {\n                        context::ResolveTemplateError::UnexpectedVariable {\n                            variable,\n                            raw_template,\n                        } => {\n                            anyhow!(\n                                \"unexpected variable `{variable}` in resolver.lockfile-path `{raw_template}`\"\n                            )\n                        }\n                        context::ResolveTemplateError::UnexpectedBracket { bracket_type, raw_template } => {\n                            let (btype, literal) = match bracket_type {\n                                context::BracketType::Opening => (\"opening\", \"{\"),\n                                context::BracketType::Closing => (\"closing\", \"}\"),\n                            };\n\n                            anyhow!(\n                                \"unexpected {btype} bracket `{literal}` in build.build-dir path `{raw_template}`\"\n                            )\n                        }\n                    })?;\n                if !path.ends_with(LOCKFILE_NAME) {\n                    bail!(\"the `resolver.lockfile-path` must be a path to a {LOCKFILE_NAME} file\");\n                }\n                if path.is_dir() {\n                    bail!(\n                        \"`resolver.lockfile-path` `{}` is a directory but expected a file\",\n                        path.display()\n                    );\n                }\n                self.requested_lockfile_path = Some(path);\n            } else {\n                self.gctx().shell().warn(\n                    \"ignoring `resolver.lockfile-path`, pass `-Zlockfile-path` to enable it\",\n                )?;\n            }\n        }\n\n        Ok(())\n    }\n\n    /// Returns the current package of this workspace.\n    ///\n    /// Note that this can return an error if it the current manifest is\n    /// actually a \"virtual Cargo.toml\", in which case an error is returned\n    /// indicating that something else should be passed.\n    pub fn current(&self) -> CargoResult<&Package> {\n        let pkg = self.current_opt().ok_or_else(|| {\n            anyhow::format_err!(\n                \"manifest path `{}` is a virtual manifest, but this \\\n                 command requires running against an actual package in \\\n                 this workspace\",\n                self.current_manifest.display()\n            )\n        })?;\n        Ok(pkg)\n    }\n\n    pub fn current_mut(&mut self) -> CargoResult<&mut Package> {\n        let cm = self.current_manifest.clone();\n        let pkg = self.current_opt_mut().ok_or_else(|| {\n            anyhow::format_err!(\n                \"manifest path `{}` is a virtual manifest, but this \\\n                 command requires running against an actual package in \\\n                 this workspace\",\n                cm.display()\n            )\n        })?;\n        Ok(pkg)\n    }\n\n    pub fn current_opt(&self) -> Option<&Package> {\n        match *self.packages.get(&self.current_manifest) {\n            MaybePackage::Package(ref p) => Some(p),\n            MaybePackage::Virtual(..) => None,\n        }\n    }\n\n    pub fn current_opt_mut(&mut self) -> Option<&mut Package> {\n        match *self.packages.get_mut(&self.current_manifest) {\n            MaybePackage::Package(ref mut p) => Some(p),\n            MaybePackage::Virtual(..) => None,\n        }\n    }\n\n    pub fn is_virtual(&self) -> bool {\n        match *self.packages.get(&self.current_manifest) {\n            MaybePackage::Package(..) => false,\n            MaybePackage::Virtual(..) => true,\n        }\n    }\n\n    /// Returns the `GlobalContext` this workspace is associated with.\n    pub fn gctx(&self) -> &'gctx GlobalContext {\n        self.gctx\n    }\n\n    pub fn profiles(&self) -> Option<&TomlProfiles> {\n        self.root_maybe().profiles()\n    }\n\n    /// Returns the root path of this workspace.\n    ///\n    /// That is, this returns the path of the directory containing the\n    /// `Cargo.toml` which is the root of this workspace.\n    pub fn root(&self) -> &Path {\n        self.root_manifest().parent().unwrap()\n    }\n\n    /// Returns the path of the `Cargo.toml` which is the root of this\n    /// workspace.\n    pub fn root_manifest(&self) -> &Path {\n        self.root_manifest\n            .as_ref()\n            .unwrap_or(&self.current_manifest)\n    }\n\n    /// Returns the root Package or `VirtualManifest`.\n    pub fn root_maybe(&self) -> &MaybePackage {\n        self.packages.get(self.root_manifest())\n    }\n\n    pub fn target_dir(&self) -> Filesystem {\n        self.target_dir\n            .clone()\n            .unwrap_or_else(|| self.default_target_dir())\n    }\n\n    pub fn build_dir(&self) -> Filesystem {\n        self.build_dir\n            .clone()\n            .or_else(|| self.target_dir.clone())\n            .unwrap_or_else(|| self.default_build_dir())\n    }\n\n    fn default_target_dir(&self) -> Filesystem {\n        if self.root_maybe().is_embedded() {\n            self.build_dir().join(\"target\")\n        } else {\n            Filesystem::new(self.root().join(\"target\"))\n        }\n    }\n\n    fn default_build_dir(&self) -> Filesystem {\n        if self.root_maybe().is_embedded() {\n            let default = ConfigRelativePath::new(\n                \"{cargo-cache-home}/build/{workspace-path-hash}\"\n                    .to_owned()\n                    .into(),\n            );\n            self.gctx()\n                .custom_build_dir(&default, self.root_manifest())\n                .expect(\"template is correct\")\n        } else {\n            self.default_target_dir()\n        }\n    }\n\n    /// Returns the root `[replace]` section of this workspace.\n    ///\n    /// This may be from a virtual crate or an actual crate.\n    pub fn root_replace(&self) -> &[(PackageIdSpec, Dependency)] {\n        match self.root_maybe() {\n            MaybePackage::Package(p) => p.manifest().replace(),\n            MaybePackage::Virtual(vm) => vm.replace(),\n        }\n    }\n\n    fn config_patch(&self) -> CargoResult<HashMap<Url, Vec<Patch>>> {\n        let config_patch: Option<\n            BTreeMap<String, BTreeMap<String, Value<TomlDependency<ConfigRelativePath>>>>,\n        > = self.gctx.get(\"patch\")?;\n\n        let source = SourceId::for_manifest_path(self.root_manifest())?;\n\n        let mut warnings = Vec::new();\n\n        let mut patch = HashMap::new();\n        for (url, deps) in config_patch.into_iter().flatten() {\n            let url = match &url[..] {\n                CRATES_IO_REGISTRY => CRATES_IO_INDEX.parse().unwrap(),\n                url => self\n                    .gctx\n                    .get_registry_index(url)\n                    .or_else(|_| url.into_url())\n                    .with_context(|| {\n                        format!(\"[patch] entry `{}` should be a URL or registry name\", url)\n                    })?,\n            };\n            patch.insert(\n                url,\n                deps.iter()\n                    .map(|(name, dependency_cv)| {\n                        crate::util::toml::config_patch_to_dependency(\n                            &dependency_cv.val,\n                            name,\n                            source,\n                            self.gctx,\n                            &mut warnings,\n                        )\n                        .map(|dep| Patch {\n                            dep,\n                            loc: PatchLocation::Config(dependency_cv.definition.clone()),\n                        })\n                    })\n                    .collect::<CargoResult<Vec<_>>>()?,\n            );\n        }\n\n        for message in warnings {\n            self.gctx\n                .shell()\n                .warn(format!(\"[patch] in cargo config: {}\", message))?\n        }\n\n        Ok(patch)\n    }\n\n    /// Returns the root `[patch]` section of this workspace.\n    ///\n    /// This may be from a virtual crate or an actual crate.\n    pub fn root_patch(&self) -> CargoResult<HashMap<Url, Vec<Patch>>> {\n        let from_manifest = match self.root_maybe() {\n            MaybePackage::Package(p) => p.manifest().patch(),\n            MaybePackage::Virtual(vm) => vm.patch(),\n        };\n\n        let from_config = self.config_patch()?;\n        if from_config.is_empty() {\n            return Ok(from_manifest.clone());\n        }\n        if from_manifest.is_empty() {\n            return Ok(from_config);\n        }\n\n        // We could just chain from_manifest and from_config,\n        // but that's not quite right as it won't deal with overlaps.\n        let mut combined = from_config;\n        for (url, deps_from_manifest) in from_manifest {\n            if let Some(deps_from_config) = combined.get_mut(url) {\n                // We want from_config to take precedence for each patched name.\n                // NOTE: This is inefficient if the number of patches is large!\n                let mut from_manifest_pruned = deps_from_manifest.clone();\n                for dep_from_config in &mut *deps_from_config {\n                    if let Some(i) = from_manifest_pruned.iter().position(|dep_from_manifest| {\n                        // XXX: should this also take into account version numbers?\n                        dep_from_config.dep.name_in_toml() == dep_from_manifest.dep.name_in_toml()\n                    }) {\n                        from_manifest_pruned.swap_remove(i);\n                    }\n                }\n                // Whatever is left does not exist in manifest dependencies.\n                deps_from_config.extend(from_manifest_pruned);\n            } else {\n                combined.insert(url.clone(), deps_from_manifest.clone());\n            }\n        }\n        Ok(combined)\n    }\n\n    /// Returns an iterator over all packages in this workspace\n    pub fn members(&self) -> impl Iterator<Item = &Package> {\n        let packages = &self.packages;\n        self.members\n            .iter()\n            .filter_map(move |path| match packages.get(path) {\n                MaybePackage::Package(p) => Some(p),\n                _ => None,\n            })\n    }\n\n    /// Returns a mutable iterator over all packages in this workspace\n    pub fn members_mut(&mut self) -> impl Iterator<Item = &mut Package> {\n        let packages = &mut self.packages.packages;\n        let members: HashSet<_> = self.members.iter().map(|path| path).collect();\n\n        packages.iter_mut().filter_map(move |(path, package)| {\n            if members.contains(path) {\n                if let MaybePackage::Package(p) = package {\n                    return Some(p);\n                }\n            }\n\n            None\n        })\n    }\n\n    /// Returns an iterator over default packages in this workspace\n    pub fn default_members<'a>(&'a self) -> impl Iterator<Item = &'a Package> {\n        let packages = &self.packages;\n        self.default_members\n            .iter()\n            .filter_map(move |path| match packages.get(path) {\n                MaybePackage::Package(p) => Some(p),\n                _ => None,\n            })\n    }\n\n    /// Returns an iterator over default packages in this workspace\n    pub fn default_members_mut(&mut self) -> impl Iterator<Item = &mut Package> {\n        let packages = &mut self.packages.packages;\n        let members: HashSet<_> = self\n            .default_members\n            .iter()\n            .map(|path| path.parent().unwrap().to_owned())\n            .collect();\n\n        packages.iter_mut().filter_map(move |(path, package)| {\n            if members.contains(path) {\n                if let MaybePackage::Package(p) = package {\n                    return Some(p);\n                }\n            }\n\n            None\n        })\n    }\n\n    /// Returns true if the package is a member of the workspace.\n    pub fn is_member(&self, pkg: &Package) -> bool {\n        self.member_ids.contains(&pkg.package_id())\n    }\n\n    /// Returns true if the given package_id is a member of the workspace.\n    pub fn is_member_id(&self, package_id: PackageId) -> bool {\n        self.member_ids.contains(&package_id)\n    }\n\n    pub fn is_ephemeral(&self) -> bool {\n        self.is_ephemeral\n    }\n\n    pub fn require_optional_deps(&self) -> bool {\n        self.require_optional_deps\n    }\n\n    pub fn set_require_optional_deps(\n        &mut self,\n        require_optional_deps: bool,\n    ) -> &mut Workspace<'gctx> {\n        self.require_optional_deps = require_optional_deps;\n        self\n    }\n\n    pub fn ignore_lock(&self) -> bool {\n        self.ignore_lock\n    }\n\n    pub fn set_ignore_lock(&mut self, ignore_lock: bool) -> &mut Workspace<'gctx> {\n        self.ignore_lock = ignore_lock;\n        self\n    }\n\n    /// Returns the directory where the lockfile is in.\n    pub fn lock_root(&self) -> Filesystem {\n        if let Some(requested) = self.requested_lockfile_path.as_ref() {\n            return Filesystem::new(\n                requested\n                    .parent()\n                    .expect(\"Lockfile path can't be root\")\n                    .to_owned(),\n            );\n        }\n        self.default_lock_root()\n    }\n\n    fn default_lock_root(&self) -> Filesystem {\n        if self.root_maybe().is_embedded() {\n            // Include a workspace hash in case the user requests a shared build-dir so that\n            // scripts don't fight over the `Cargo.lock` content\n            let workspace_manifest_path = self.root_manifest();\n            let real_path = std::fs::canonicalize(workspace_manifest_path)\n                .unwrap_or_else(|_err| workspace_manifest_path.to_owned());\n            let hash = crate::util::hex::short_hash(&real_path);\n            self.build_dir().join(hash)\n        } else {\n            Filesystem::new(self.root().to_owned())\n        }\n    }\n\n    // NOTE: may be removed once the deprecated `--lockfile-path` CLI flag is removed\n    pub fn set_requested_lockfile_path(&mut self, path: Option<PathBuf>) {\n        self.requested_lockfile_path = path;\n    }\n\n    pub fn requested_lockfile_path(&self) -> Option<&Path> {\n        self.requested_lockfile_path.as_deref()\n    }\n\n    /// Get the lowest-common denominator `package.rust-version` within the workspace, if specified\n    /// anywhere\n    pub fn lowest_rust_version(&self) -> Option<&RustVersion> {\n        self.members().filter_map(|pkg| pkg.rust_version()).min()\n    }\n\n    pub fn set_resolve_honors_rust_version(&mut self, honor_rust_version: Option<bool>) {\n        if let Some(honor_rust_version) = honor_rust_version {\n            self.resolve_honors_rust_version = honor_rust_version;\n        }\n    }\n\n    pub fn resolve_honors_rust_version(&self) -> bool {\n        self.resolve_honors_rust_version\n    }\n\n    pub fn set_resolve_feature_unification(&mut self, feature_unification: FeatureUnification) {\n        self.resolve_feature_unification = feature_unification;\n    }\n\n    pub fn resolve_feature_unification(&self) -> FeatureUnification {\n        self.resolve_feature_unification\n    }\n\n    pub fn set_resolve_publish_time(&mut self, publish_time: jiff::Timestamp) {\n        self.resolve_publish_time = Some(publish_time);\n    }\n\n    pub fn resolve_publish_time(&self) -> Option<jiff::Timestamp> {\n        self.resolve_publish_time\n    }\n\n    pub fn custom_metadata(&self) -> Option<&toml::Value> {\n        self.custom_metadata.as_ref()\n    }\n\n    pub fn load_workspace_config(&mut self) -> CargoResult<Option<WorkspaceRootConfig>> {\n        // If we didn't find a root, it must mean there is no [workspace] section, and thus no\n        // metadata.\n        if let Some(root_path) = &self.root_manifest {\n            let root_package = self.packages.load(root_path)?;\n            match root_package.workspace_config() {\n                WorkspaceConfig::Root(root_config) => {\n                    return Ok(Some(root_config.clone()));\n                }\n\n                _ => bail!(\n                    \"root of a workspace inferred but wasn't a root: {}\",\n                    root_path.display()\n                ),\n            }\n        }\n\n        Ok(None)\n    }\n\n    /// Finds the root of a workspace for the crate whose manifest is located\n    /// at `manifest_path`.\n    ///\n    /// This will parse the `Cargo.toml` at `manifest_path` and then interpret\n    /// the workspace configuration, optionally walking up the filesystem\n    /// looking for other workspace roots.\n    ///\n    /// Returns an error if `manifest_path` isn't actually a valid manifest or\n    /// if some other transient error happens.\n    fn find_root(&mut self, manifest_path: &Path) -> CargoResult<Option<PathBuf>> {\n        let current = self.packages.load(manifest_path)?;\n        match current\n            .workspace_config()\n            .get_ws_root(manifest_path, manifest_path)\n        {\n            Some(root_path) => {\n                debug!(\"find_root - is root {}\", manifest_path.display());\n                Ok(Some(root_path))\n            }\n            None => find_workspace_root_with_loader(manifest_path, self.gctx, |self_path| {\n                Ok(self\n                    .packages\n                    .load(self_path)?\n                    .workspace_config()\n                    .get_ws_root(self_path, manifest_path))\n            }),\n        }\n    }\n\n    /// After the root of a workspace has been located, probes for all members\n    /// of a workspace.\n    ///\n    /// If the `workspace.members` configuration is present, then this just\n    /// verifies that those are all valid packages to point to. Otherwise, this\n    /// will transitively follow all `path` dependencies looking for members of\n    /// the workspace.\n    #[tracing::instrument(skip_all)]\n    fn find_members(&mut self) -> CargoResult<()> {\n        let Some(workspace_config) = self.load_workspace_config()? else {\n            debug!(\"find_members - only me as a member\");\n            self.members.push(self.current_manifest.clone());\n            self.default_members.push(self.current_manifest.clone());\n            if let Ok(pkg) = self.current() {\n                let id = pkg.package_id();\n                self.member_ids.insert(id);\n            }\n            return Ok(());\n        };\n\n        // self.root_manifest must be Some to have retrieved workspace_config\n        let root_manifest_path = self.root_manifest.clone().unwrap();\n\n        let members_paths = workspace_config\n            .members_paths(workspace_config.members.as_deref().unwrap_or_default())?;\n        let default_members_paths = if root_manifest_path == self.current_manifest {\n            if let Some(ref default) = workspace_config.default_members {\n                Some(workspace_config.members_paths(default)?)\n            } else {\n                None\n            }\n        } else {\n            None\n        };\n\n        for (path, glob) in &members_paths {\n            self.find_path_deps(&path.join(\"Cargo.toml\"), &root_manifest_path, false)\n                .with_context(|| {\n                    format!(\n                        \"failed to load manifest for workspace member `{}`\\n\\\n                        referenced{} by workspace at `{}`\",\n                        path.display(),\n                        glob.map(|g| format!(\" via `{g}`\")).unwrap_or_default(),\n                        root_manifest_path.display(),\n                    )\n                })?;\n        }\n\n        self.find_path_deps(&root_manifest_path, &root_manifest_path, false)?;\n\n        if let Some(default) = default_members_paths {\n            for (path, default_member_glob) in default {\n                let normalized_path = paths::normalize_path(&path);\n                let manifest_path = normalized_path.join(\"Cargo.toml\");\n                if !self.members.contains(&manifest_path) {\n                    // default-members are allowed to be excluded, but they\n                    // still must be referred to by the original (unfiltered)\n                    // members list. Note that we aren't testing against the\n                    // manifest path, both because `members_paths` doesn't\n                    // include `/Cargo.toml`, and because excluded paths may not\n                    // be crates.\n                    let exclude = members_paths.iter().any(|(m, _)| *m == normalized_path)\n                        && workspace_config.is_excluded(&normalized_path);\n                    if exclude {\n                        continue;\n                    }\n                    bail!(\n                        \"package `{}` is listed in default-members{} but is not a member\\n\\\n                        for workspace at `{}`.\",\n                        path.display(),\n                        default_member_glob\n                            .map(|g| format!(\" via `{g}`\"))\n                            .unwrap_or_default(),\n                        root_manifest_path.display(),\n                    )\n                }\n                self.default_members.push(manifest_path)\n            }\n        } else if self.is_virtual() {\n            self.default_members = self.members.clone()\n        } else {\n            self.default_members.push(self.current_manifest.clone())\n        }\n\n        Ok(())\n    }\n\n    fn find_path_deps(\n        &mut self,\n        manifest_path: &Path,\n        root_manifest: &Path,\n        is_path_dep: bool,\n    ) -> CargoResult<()> {\n        let manifest_path = paths::normalize_path(manifest_path);\n        if self.members.contains(&manifest_path) {\n            return Ok(());\n        }\n        if is_path_dep && self.root_maybe().is_embedded() {\n            // Embedded manifests cannot have workspace members\n            return Ok(());\n        }\n        if is_path_dep\n            && !manifest_path.parent().unwrap().starts_with(self.root())\n            && self.find_root(&manifest_path)? != self.root_manifest\n        {\n            // If `manifest_path` is a path dependency outside of the workspace,\n            // don't add it, or any of its dependencies, as a members.\n            return Ok(());\n        }\n\n        if let WorkspaceConfig::Root(ref root_config) =\n            *self.packages.load(root_manifest)?.workspace_config()\n        {\n            if root_config.is_excluded(&manifest_path) {\n                return Ok(());\n            }\n        }\n\n        debug!(\"find_path_deps - {}\", manifest_path.display());\n        self.members.push(manifest_path.clone());\n\n        let candidates = {\n            let pkg = match *self.packages.load(&manifest_path)? {\n                MaybePackage::Package(ref p) => p,\n                MaybePackage::Virtual(_) => return Ok(()),\n            };\n            self.member_ids.insert(pkg.package_id());\n            pkg.dependencies()\n                .iter()\n                .map(|d| (d.source_id(), d.package_name()))\n                .filter(|(s, _)| s.is_path())\n                .filter_map(|(s, n)| s.url().to_file_path().ok().map(|p| (p, n)))\n                .map(|(p, n)| (p.join(\"Cargo.toml\"), n))\n                .collect::<Vec<_>>()\n        };\n        for (path, name) in candidates {\n            self.find_path_deps(&path, root_manifest, true)\n                .with_context(|| format!(\"failed to load manifest for dependency `{}`\", name))\n                .map_err(|err| ManifestError::new(err, manifest_path.clone()))?;\n        }\n        Ok(())\n    }\n\n    /// Returns the unstable nightly-only features enabled via `cargo-features` in the manifest.\n    pub fn unstable_features(&self) -> &Features {\n        self.root_maybe().unstable_features()\n    }\n\n    pub fn resolve_behavior(&self) -> ResolveBehavior {\n        self.resolve_behavior\n    }\n\n    /// Returns `true` if this workspace uses the new CLI features behavior.\n    ///\n    /// The old behavior only allowed choosing the features from the package\n    /// in the current directory, regardless of which packages were chosen\n    /// with the -p flags. The new behavior allows selecting features from the\n    /// packages chosen on the command line (with -p or --workspace flags),\n    /// ignoring whatever is in the current directory.\n    pub fn allows_new_cli_feature_behavior(&self) -> bool {\n        self.is_virtual()\n            || match self.resolve_behavior() {\n                ResolveBehavior::V1 => false,\n                ResolveBehavior::V2 | ResolveBehavior::V3 => true,\n            }\n    }\n\n    /// Validates a workspace, ensuring that a number of invariants are upheld:\n    ///\n    /// 1. A workspace only has one root.\n    /// 2. All workspace members agree on this one root as the root.\n    /// 3. The current crate is a member of this workspace.\n    #[tracing::instrument(skip_all)]\n    fn validate(&mut self) -> CargoResult<()> {\n        // The rest of the checks require a VirtualManifest or multiple members.\n        if self.root_manifest.is_none() {\n            return Ok(());\n        }\n\n        self.validate_unique_names()?;\n        self.validate_workspace_roots()?;\n        self.validate_members()?;\n        self.error_if_manifest_not_in_members()?;\n        self.validate_manifest()\n    }\n\n    fn validate_unique_names(&self) -> CargoResult<()> {\n        let mut names = BTreeMap::new();\n        for member in self.members.iter() {\n            let package = self.packages.get(member);\n            let name = match *package {\n                MaybePackage::Package(ref p) => p.name(),\n                MaybePackage::Virtual(_) => continue,\n            };\n            if let Some(prev) = names.insert(name, member) {\n                bail!(\n                    \"two packages named `{}` in this workspace:\\n\\\n                         - {}\\n\\\n                         - {}\",\n                    name,\n                    prev.display(),\n                    member.display()\n                );\n            }\n        }\n        Ok(())\n    }\n\n    fn validate_workspace_roots(&self) -> CargoResult<()> {\n        let roots: Vec<PathBuf> = self\n            .members\n            .iter()\n            .filter(|&member| {\n                let config = self.packages.get(member).workspace_config();\n                matches!(config, WorkspaceConfig::Root(_))\n            })\n            .map(|member| member.parent().unwrap().to_path_buf())\n            .collect();\n        match roots.len() {\n            1 => Ok(()),\n            0 => bail!(\n                \"`package.workspace` configuration points to a crate \\\n                 which is not configured with [workspace]: \\n\\\n                 configuration at: {}\\n\\\n                 points to: {}\",\n                self.current_manifest.display(),\n                self.root_manifest.as_ref().unwrap().display()\n            ),\n            _ => {\n                bail!(\n                    \"multiple workspace roots found in the same workspace:\\n{}\",\n                    roots\n                        .iter()\n                        .map(|r| format!(\"  {}\", r.display()))\n                        .collect::<Vec<_>>()\n                        .join(\"\\n\")\n                );\n            }\n        }\n    }\n\n    #[tracing::instrument(skip_all)]\n    fn validate_members(&mut self) -> CargoResult<()> {\n        for member in self.members.clone() {\n            let root = self.find_root(&member)?;\n            if root == self.root_manifest {\n                continue;\n            }\n\n            match root {\n                Some(root) => {\n                    bail!(\n                        \"package `{}` is a member of the wrong workspace\\n\\\n                         expected: {}\\n\\\n                         actual:   {}\",\n                        member.display(),\n                        self.root_manifest.as_ref().unwrap().display(),\n                        root.display()\n                    );\n                }\n                None => {\n                    bail!(\n                        \"workspace member `{}` is not hierarchically below \\\n                         the workspace root `{}`\",\n                        member.display(),\n                        self.root_manifest.as_ref().unwrap().display()\n                    );\n                }\n            }\n        }\n        Ok(())\n    }\n\n    fn error_if_manifest_not_in_members(&mut self) -> CargoResult<()> {\n        if self.members.contains(&self.current_manifest) {\n            return Ok(());\n        }\n\n        let root = self.root_manifest.as_ref().unwrap();\n        let root_dir = root.parent().unwrap();\n        let current_dir = self.current_manifest.parent().unwrap();\n        let root_pkg = self.packages.get(root);\n\n        // Use pathdiff to handle finding the relative path between the current package\n        // and the workspace root. This usually does a good job of handling `..` and\n        // other weird things.\n        // Normalize paths first to ensure `../` components are resolved if possible,\n        // which helps `diff_paths` find the most direct relative path.\n        let current_dir = paths::normalize_path(current_dir);\n        let root_dir = paths::normalize_path(root_dir);\n        let members_msg = match pathdiff::diff_paths(&current_dir, &root_dir) {\n            Some(rel) => format!(\n                \"this may be fixable by adding `{}` to the \\\n                     `workspace.members` array of the manifest \\\n                     located at: {}\",\n                rel.display(),\n                root.display()\n            ),\n            None => format!(\n                \"this may be fixable by adding a member to \\\n                     the `workspace.members` array of the \\\n                     manifest located at: {}\",\n                root.display()\n            ),\n        };\n        let extra = match *root_pkg {\n            MaybePackage::Virtual(_) => members_msg,\n            MaybePackage::Package(ref p) => {\n                let has_members_list = match *p.manifest().workspace_config() {\n                    WorkspaceConfig::Root(ref root_config) => root_config.has_members_list(),\n                    WorkspaceConfig::Member { .. } => unreachable!(),\n                };\n                if !has_members_list {\n                    format!(\n                        \"this may be fixable by ensuring that this \\\n                             crate is depended on by the workspace \\\n                             root: {}\",\n                        root.display()\n                    )\n                } else {\n                    members_msg\n                }\n            }\n        };\n        bail!(\n            \"current package believes it's in a workspace when it's not:\\n\\\n                 current:   {}\\n\\\n                 workspace: {}\\n\\n{}\\n\\\n                 Alternatively, to keep it out of the workspace, add the package \\\n                 to the `workspace.exclude` array, or add an empty `[workspace]` \\\n                 table to the package's manifest.\",\n            self.current_manifest.display(),\n            root.display(),\n            extra\n        );\n    }\n\n    fn validate_manifest(&mut self) -> CargoResult<()> {\n        if let Some(ref root_manifest) = self.root_manifest {\n            for pkg in self\n                .members()\n                .filter(|p| p.manifest_path() != root_manifest)\n            {\n                let manifest = pkg.manifest();\n                let emit_warning = |what| -> CargoResult<()> {\n                    let msg = format!(\n                        \"{} for the non root package will be ignored, \\\n                         specify {} at the workspace root:\\n\\\n                         package:   {}\\n\\\n                         workspace: {}\",\n                        what,\n                        what,\n                        pkg.manifest_path().display(),\n                        root_manifest.display(),\n                    );\n                    self.gctx.shell().warn(&msg)\n                };\n                if manifest.normalized_toml().has_profiles() {\n                    emit_warning(\"profiles\")?;\n                }\n                if !manifest.replace().is_empty() {\n                    emit_warning(\"replace\")?;\n                }\n                if !manifest.patch().is_empty() {\n                    emit_warning(\"patch\")?;\n                }\n                if let Some(behavior) = manifest.resolve_behavior() {\n                    if behavior != self.resolve_behavior {\n                        // Only warn if they don't match.\n                        emit_warning(\"resolver\")?;\n                    }\n                }\n            }\n            if let MaybePackage::Virtual(vm) = self.root_maybe() {\n                if vm.resolve_behavior().is_none() {\n                    if let Some(edition) = self\n                        .members()\n                        .filter(|p| p.manifest_path() != root_manifest)\n                        .map(|p| p.manifest().edition())\n                        .filter(|&e| e >= Edition::Edition2021)\n                        .max()\n                    {\n                        let resolver = edition.default_resolve_behavior().to_manifest();\n                        let report = &[Level::WARNING\n                            .primary_title(format!(\n                                \"virtual workspace defaulting to `resolver = \\\"1\\\"` despite one or more workspace members being on edition {edition} which implies `resolver = \\\"{resolver}\\\"`\"\n                            ))\n                            .elements([\n                                Level::NOTE.message(\"to keep the current resolver, specify `workspace.resolver = \\\"1\\\"` in the workspace root's manifest\"),\n                                Level::NOTE.message(\n                                    format!(\"to use the edition {edition} resolver, specify `workspace.resolver = \\\"{resolver}\\\"` in the workspace root's manifest\"),\n                                ),\n                                Level::NOTE.message(\"for more details see https://doc.rust-lang.org/cargo/reference/resolver.html#resolver-versions\"),\n                            ])];\n                        self.gctx.shell().print_report(report, false)?;\n                    }\n                }\n            }\n        }\n        Ok(())\n    }\n\n    pub fn load(&self, manifest_path: &Path) -> CargoResult<Package> {\n        match self.packages.maybe_get(manifest_path) {\n            Some(MaybePackage::Package(p)) => return Ok(p.clone()),\n            Some(&MaybePackage::Virtual(_)) => bail!(\"cannot load workspace root\"),\n            None => {}\n        }\n\n        let mut loaded = self.loaded_packages.borrow_mut();\n        if let Some(p) = loaded.get(manifest_path).cloned() {\n            return Ok(p);\n        }\n        let source_id = SourceId::for_manifest_path(manifest_path)?;\n        let package = ops::read_package(manifest_path, source_id, self.gctx)?;\n        loaded.insert(manifest_path.to_path_buf(), package.clone());\n        Ok(package)\n    }\n\n    /// Preload the provided registry with already loaded packages.\n    ///\n    /// A workspace may load packages during construction/parsing/early phases\n    /// for various operations, and this preload step avoids doubly-loading and\n    /// parsing crates on the filesystem by inserting them all into the registry\n    /// with their in-memory formats.\n    pub fn preload(&self, registry: &mut PackageRegistry<'gctx>) {\n        // These can get weird as this generally represents a workspace during\n        // `cargo install`. Things like git repositories will actually have a\n        // `PathSource` with multiple entries in it, so the logic below is\n        // mostly just an optimization for normal `cargo build` in workspaces\n        // during development.\n        if self.is_ephemeral {\n            return;\n        }\n\n        for pkg in self.packages.packages.values() {\n            let pkg = match *pkg {\n                MaybePackage::Package(ref p) => p.clone(),\n                MaybePackage::Virtual(_) => continue,\n            };\n            let src = PathSource::preload_with(pkg, self.gctx);\n            registry.add_preloaded(Box::new(src));\n        }\n    }\n\n    pub fn emit_warnings(&self) -> CargoResult<()> {\n        let mut first_emitted_error = None;\n\n        if let Err(e) = self.emit_ws_lints() {\n            first_emitted_error = Some(e);\n        }\n\n        for (path, maybe_pkg) in &self.packages.packages {\n            if let MaybePackage::Package(pkg) = maybe_pkg {\n                if let Err(e) = self.emit_pkg_lints(pkg, &path)\n                    && first_emitted_error.is_none()\n                {\n                    first_emitted_error = Some(e);\n                }\n            }\n            let warnings = match maybe_pkg {\n                MaybePackage::Package(pkg) => pkg.manifest().warnings().warnings(),\n                MaybePackage::Virtual(vm) => vm.warnings().warnings(),\n            };\n            for warning in warnings {\n                if warning.is_critical {\n                    let err = anyhow::format_err!(\"{}\", warning.message);\n                    let cx =\n                        anyhow::format_err!(\"failed to parse manifest at `{}`\", path.display());\n                    if first_emitted_error.is_none() {\n                        first_emitted_error = Some(err.context(cx));\n                    }\n                } else {\n                    let msg = if self.root_manifest.is_none() {\n                        warning.message.to_string()\n                    } else {\n                        // In a workspace, it can be confusing where a warning\n                        // originated, so include the path.\n                        format!(\"{}: {}\", path.display(), warning.message)\n                    };\n                    self.gctx.shell().warn(msg)?\n                }\n            }\n        }\n\n        if let Some(error) = first_emitted_error {\n            Err(error)\n        } else {\n            Ok(())\n        }\n    }\n\n    pub fn emit_pkg_lints(&self, pkg: &Package, path: &Path) -> CargoResult<()> {\n        let toml_lints = pkg\n            .manifest()\n            .normalized_toml()\n            .lints\n            .clone()\n            .map(|lints| lints.lints)\n            .unwrap_or(manifest::TomlLints::default());\n        let cargo_lints = toml_lints\n            .get(\"cargo\")\n            .cloned()\n            .unwrap_or(manifest::TomlToolLints::default());\n\n        if self.gctx.cli_unstable().cargo_lints {\n            let mut verify_error_count = 0;\n\n            analyze_cargo_lints_table(\n                pkg.into(),\n                &path,\n                &cargo_lints,\n                &mut verify_error_count,\n                self.gctx,\n            )?;\n\n            if verify_error_count > 0 {\n                let plural = if verify_error_count == 1 { \"\" } else { \"s\" };\n                bail!(\"encountered {verify_error_count} error{plural} while verifying lints\")\n            }\n\n            let mut run_error_count = 0;\n\n            check_im_a_teapot(pkg, &path, &cargo_lints, &mut run_error_count, self.gctx)?;\n            implicit_minimum_version_req_pkg(\n                pkg,\n                &path,\n                &cargo_lints,\n                &mut run_error_count,\n                self.gctx,\n            )?;\n            non_kebab_case_packages(pkg, &path, &cargo_lints, &mut run_error_count, self.gctx)?;\n            non_snake_case_packages(pkg, &path, &cargo_lints, &mut run_error_count, self.gctx)?;\n            non_kebab_case_bins(\n                self,\n                pkg,\n                &path,\n                &cargo_lints,\n                &mut run_error_count,\n                self.gctx,\n            )?;\n            non_kebab_case_features(pkg, &path, &cargo_lints, &mut run_error_count, self.gctx)?;\n            non_snake_case_features(pkg, &path, &cargo_lints, &mut run_error_count, self.gctx)?;\n            redundant_readme(pkg, &path, &cargo_lints, &mut run_error_count, self.gctx)?;\n            redundant_homepage(pkg, &path, &cargo_lints, &mut run_error_count, self.gctx)?;\n            missing_lints_inheritance(\n                self,\n                pkg,\n                &path,\n                &cargo_lints,\n                &mut run_error_count,\n                self.gctx,\n            )?;\n\n            if run_error_count > 0 {\n                let plural = if run_error_count == 1 { \"\" } else { \"s\" };\n                bail!(\"encountered {run_error_count} error{plural} while running lints\")\n            }\n        }\n\n        Ok(())\n    }\n\n    pub fn emit_ws_lints(&self) -> CargoResult<()> {\n        let mut run_error_count = 0;\n\n        let cargo_lints = match self.root_maybe() {\n            MaybePackage::Package(pkg) => {\n                let toml = pkg.manifest().normalized_toml();\n                if let Some(ws) = &toml.workspace {\n                    ws.lints.as_ref()\n                } else {\n                    toml.lints.as_ref().map(|l| &l.lints)\n                }\n            }\n            MaybePackage::Virtual(vm) => vm\n                .normalized_toml()\n                .workspace\n                .as_ref()\n                .unwrap()\n                .lints\n                .as_ref(),\n        }\n        .and_then(|t| t.get(\"cargo\"))\n        .cloned()\n        .unwrap_or(manifest::TomlToolLints::default());\n\n        if self.gctx.cli_unstable().cargo_lints {\n            let mut verify_error_count = 0;\n\n            analyze_cargo_lints_table(\n                (self, self.root_maybe()).into(),\n                self.root_manifest(),\n                &cargo_lints,\n                &mut verify_error_count,\n                self.gctx,\n            )?;\n\n            if verify_error_count > 0 {\n                let plural = if verify_error_count == 1 { \"\" } else { \"s\" };\n                bail!(\"encountered {verify_error_count} error{plural} while verifying lints\")\n            }\n\n            unused_workspace_package_fields(\n                self,\n                self.root_maybe(),\n                self.root_manifest(),\n                &cargo_lints,\n                &mut run_error_count,\n                self.gctx,\n            )?;\n            unused_workspace_dependencies(\n                self,\n                self.root_maybe(),\n                self.root_manifest(),\n                &cargo_lints,\n                &mut run_error_count,\n                self.gctx,\n            )?;\n            implicit_minimum_version_req_ws(\n                self,\n                self.root_maybe(),\n                self.root_manifest(),\n                &cargo_lints,\n                &mut run_error_count,\n                self.gctx,\n            )?;\n        }\n\n        // This is a short term hack to allow `blanket_hint_mostly_unused`\n        // to run without requiring `-Zcargo-lints`, which should hopefully\n        // improve the testing experience while we are collecting feedback\n        if self.gctx.cli_unstable().profile_hint_mostly_unused {\n            blanket_hint_mostly_unused(\n                self,\n                self.root_maybe(),\n                self.root_manifest(),\n                &cargo_lints,\n                &mut run_error_count,\n                self.gctx,\n            )?;\n        }\n\n        if run_error_count > 0 {\n            let plural = if run_error_count == 1 { \"\" } else { \"s\" };\n            bail!(\"encountered {run_error_count} error{plural} while running lints\")\n        } else {\n            Ok(())\n        }\n    }\n\n    pub fn set_target_dir(&mut self, target_dir: Filesystem) {\n        self.target_dir = Some(target_dir);\n    }\n\n    /// Returns a Vec of `(&Package, CliFeatures)` tuples that\n    /// represent the workspace members that were requested on the command-line.\n    ///\n    /// `specs` may be empty, which indicates it should return all workspace\n    /// members. In this case, `requested_features.all_features` must be\n    /// `true`. This is used for generating `Cargo.lock`, which must include\n    /// all members with all features enabled.\n    pub fn members_with_features(\n        &self,\n        specs: &[PackageIdSpec],\n        cli_features: &CliFeatures,\n    ) -> CargoResult<Vec<(&Package, CliFeatures)>> {\n        assert!(\n            !specs.is_empty() || cli_features.all_features,\n            \"no specs requires all_features\"\n        );\n        if specs.is_empty() {\n            // When resolving the entire workspace, resolve each member with\n            // all features enabled.\n            return Ok(self\n                .members()\n                .map(|m| (m, CliFeatures::new_all(true)))\n                .collect());\n        }\n        if self.allows_new_cli_feature_behavior() {\n            self.members_with_features_new(specs, cli_features)\n        } else {\n            Ok(self.members_with_features_old(specs, cli_features))\n        }\n    }\n\n    /// Returns the requested features for the given member.\n    /// This filters out any named features that the member does not have.\n    fn collect_matching_features(\n        member: &Package,\n        cli_features: &CliFeatures,\n        found_features: &mut BTreeSet<FeatureValue>,\n    ) -> CliFeatures {\n        if cli_features.features.is_empty() {\n            return cli_features.clone();\n        }\n\n        // Only include features this member defines.\n        let summary = member.summary();\n\n        // Features defined in the manifest\n        let summary_features = summary.features();\n\n        // Dependency name -> dependency\n        let dependencies: BTreeMap<InternedString, &Dependency> = summary\n            .dependencies()\n            .iter()\n            .map(|dep| (dep.name_in_toml(), dep))\n            .collect();\n\n        // Features that enable optional dependencies\n        let optional_dependency_names: BTreeSet<_> = dependencies\n            .iter()\n            .filter(|(_, dep)| dep.is_optional())\n            .map(|(name, _)| name)\n            .copied()\n            .collect();\n\n        let mut features = BTreeSet::new();\n\n        // Checks if a member contains the given feature.\n        let summary_or_opt_dependency_feature = |feature: &InternedString| -> bool {\n            summary_features.contains_key(feature) || optional_dependency_names.contains(feature)\n        };\n\n        for feature in cli_features.features.iter() {\n            match feature {\n                FeatureValue::Feature(f) => {\n                    if summary_or_opt_dependency_feature(f) {\n                        // feature exists in this member.\n                        features.insert(feature.clone());\n                        found_features.insert(feature.clone());\n                    }\n                }\n                // This should be enforced by CliFeatures.\n                FeatureValue::Dep { .. } => panic!(\"unexpected dep: syntax {}\", feature),\n                FeatureValue::DepFeature {\n                    dep_name,\n                    dep_feature,\n                    weak: _,\n                } => {\n                    if dependencies.contains_key(dep_name) {\n                        // pkg/feat for a dependency.\n                        // Will rely on the dependency resolver to validate `dep_feature`.\n                        features.insert(feature.clone());\n                        found_features.insert(feature.clone());\n                    } else if *dep_name == member.name()\n                        && summary_or_opt_dependency_feature(dep_feature)\n                    {\n                        // member/feat where \"feat\" is a feature in member.\n                        //\n                        // `weak` can be ignored here, because the member\n                        // either is or isn't being built.\n                        features.insert(FeatureValue::Feature(*dep_feature));\n                        found_features.insert(feature.clone());\n                    }\n                }\n            }\n        }\n        CliFeatures {\n            features: Rc::new(features),\n            all_features: cli_features.all_features,\n            uses_default_features: cli_features.uses_default_features,\n        }\n    }\n\n    fn missing_feature_spelling_suggestions(\n        &self,\n        selected_members: &[&Package],\n        cli_features: &CliFeatures,\n        found_features: &BTreeSet<FeatureValue>,\n    ) -> Vec<String> {\n        // Keeps track of which features were contained in summary of `member` to suggest similar features in errors\n        let mut summary_features: Vec<InternedString> = Default::default();\n\n        // Keeps track of `member` dependencies (`dep/feature`) and their features names to suggest similar features in error\n        let mut dependencies_features: BTreeMap<InternedString, &[InternedString]> =\n            Default::default();\n\n        // Keeps track of `member` optional dependencies names (which can be enabled with feature) to suggest similar features in error\n        let mut optional_dependency_names: Vec<InternedString> = Default::default();\n\n        // Keeps track of which features were contained in summary of `member` to suggest similar features in errors\n        let mut summary_features_per_member: BTreeMap<&Package, BTreeSet<InternedString>> =\n            Default::default();\n\n        // Keeps track of `member` optional dependencies (which can be enabled with feature) to suggest similar features in error\n        let mut optional_dependency_names_per_member: BTreeMap<&Package, BTreeSet<InternedString>> =\n            Default::default();\n\n        for &member in selected_members {\n            // Only include features this member defines.\n            let summary = member.summary();\n\n            // Features defined in the manifest\n            summary_features.extend(summary.features().keys());\n            summary_features_per_member\n                .insert(member, summary.features().keys().copied().collect());\n\n            // Dependency name -> dependency\n            let dependencies: BTreeMap<InternedString, &Dependency> = summary\n                .dependencies()\n                .iter()\n                .map(|dep| (dep.name_in_toml(), dep))\n                .collect();\n\n            dependencies_features.extend(\n                dependencies\n                    .iter()\n                    .map(|(name, dep)| (*name, dep.features())),\n            );\n\n            // Features that enable optional dependencies\n            let optional_dependency_names_raw: BTreeSet<_> = dependencies\n                .iter()\n                .filter(|(_, dep)| dep.is_optional())\n                .map(|(name, _)| name)\n                .copied()\n                .collect();\n\n            optional_dependency_names.extend(optional_dependency_names_raw.iter());\n            optional_dependency_names_per_member.insert(member, optional_dependency_names_raw);\n        }\n\n        let edit_distance_test = |a: InternedString, b: InternedString| {\n            edit_distance(a.as_str(), b.as_str(), 3).is_some()\n        };\n\n        cli_features\n            .features\n            .difference(found_features)\n            .map(|feature| match feature {\n                // Simple feature, check if any of the optional dependency features or member features are close enough\n                FeatureValue::Feature(typo) => {\n                    // Finds member features which are similar to the requested feature.\n                    let summary_features = summary_features\n                        .iter()\n                        .filter(move |feature| edit_distance_test(**feature, *typo));\n\n                    // Finds optional dependencies which name is similar to the feature\n                    let optional_dependency_features = optional_dependency_names\n                        .iter()\n                        .filter(move |feature| edit_distance_test(**feature, *typo));\n\n                    summary_features\n                        .chain(optional_dependency_features)\n                        .map(|s| s.to_string())\n                        .collect::<Vec<_>>()\n                }\n                FeatureValue::Dep { .. } => panic!(\"unexpected dep: syntax {}\", feature),\n                FeatureValue::DepFeature {\n                    dep_name,\n                    dep_feature,\n                    weak: _,\n                } => {\n                    // Finds set of `pkg/feat` that are very similar to current `pkg/feat`.\n                    let pkg_feat_similar = dependencies_features\n                        .iter()\n                        .filter(|(name, _)| edit_distance_test(**name, *dep_name))\n                        .map(|(name, features)| {\n                            (\n                                name,\n                                features\n                                    .iter()\n                                    .filter(|feature| edit_distance_test(**feature, *dep_feature))\n                                    .collect::<Vec<_>>(),\n                            )\n                        })\n                        .map(|(name, features)| {\n                            features\n                                .into_iter()\n                                .map(move |feature| format!(\"{}/{}\", name, feature))\n                        })\n                        .flatten();\n\n                    // Finds set of `member/optional_dep` features which name is similar to current `pkg/feat`.\n                    let optional_dependency_features = optional_dependency_names_per_member\n                        .iter()\n                        .filter(|(package, _)| edit_distance_test(package.name(), *dep_name))\n                        .map(|(package, optional_dependencies)| {\n                            optional_dependencies\n                                .into_iter()\n                                .filter(|optional_dependency| {\n                                    edit_distance_test(**optional_dependency, *dep_name)\n                                })\n                                .map(move |optional_dependency| {\n                                    format!(\"{}/{}\", package.name(), optional_dependency)\n                                })\n                        })\n                        .flatten();\n\n                    // Finds set of `member/feat` features which name is similar to current `pkg/feat`.\n                    let summary_features = summary_features_per_member\n                        .iter()\n                        .filter(|(package, _)| edit_distance_test(package.name(), *dep_name))\n                        .map(|(package, summary_features)| {\n                            summary_features\n                                .into_iter()\n                                .filter(|summary_feature| {\n                                    edit_distance_test(**summary_feature, *dep_feature)\n                                })\n                                .map(move |summary_feature| {\n                                    format!(\"{}/{}\", package.name(), summary_feature)\n                                })\n                        })\n                        .flatten();\n\n                    pkg_feat_similar\n                        .chain(optional_dependency_features)\n                        .chain(summary_features)\n                        .collect::<Vec<_>>()\n                }\n            })\n            .map(|v| v.into_iter())\n            .flatten()\n            .unique()\n            .filter(|element| {\n                let feature = FeatureValue::new(element.into());\n                !cli_features.features.contains(&feature) && !found_features.contains(&feature)\n            })\n            .sorted()\n            .take(5)\n            .collect()\n    }\n\n    fn report_unknown_features_error(\n        &self,\n        specs: &[PackageIdSpec],\n        cli_features: &CliFeatures,\n        found_features: &BTreeSet<FeatureValue>,\n    ) -> CargoResult<()> {\n        let unknown: Vec<_> = cli_features\n            .features\n            .difference(found_features)\n            .map(|feature| feature.to_string())\n            .sorted()\n            .collect();\n\n        let (selected_members, unselected_members): (Vec<_>, Vec<_>) = self\n            .members()\n            .partition(|member| specs.iter().any(|spec| spec.matches(member.package_id())));\n\n        let missing_packages_with_the_features = unselected_members\n            .into_iter()\n            .filter(|member| {\n                unknown\n                    .iter()\n                    .any(|feature| member.summary().features().contains_key(&**feature))\n            })\n            .map(|m| m.name())\n            .collect_vec();\n\n        let these_features = if unknown.len() == 1 {\n            \"this feature\"\n        } else {\n            \"these features\"\n        };\n        let mut msg = if let [singular] = &selected_members[..] {\n            format!(\n                \"the package '{}' does not contain {these_features}: {}\",\n                singular.name(),\n                unknown.join(\", \")\n            )\n        } else {\n            let names = selected_members.iter().map(|m| m.name()).join(\", \");\n            format!(\n                \"none of the selected packages contains {these_features}: {}\\nselected packages: {names}\",\n                unknown.join(\", \")\n            )\n        };\n\n        use std::fmt::Write;\n        if !missing_packages_with_the_features.is_empty() {\n            write!(\n                &mut msg,\n                \"\\nhelp: package{} with the missing feature{}: {}\",\n                if missing_packages_with_the_features.len() != 1 {\n                    \"s\"\n                } else {\n                    \"\"\n                },\n                if unknown.len() != 1 { \"s\" } else { \"\" },\n                missing_packages_with_the_features.join(\", \")\n            )?;\n        } else {\n            let suggestions = self.missing_feature_spelling_suggestions(\n                &selected_members,\n                cli_features,\n                found_features,\n            );\n            if !suggestions.is_empty() {\n                write!(\n                    &mut msg,\n                    \"\\nhelp: there {}: {}\",\n                    if suggestions.len() == 1 {\n                        \"is a similarly named feature\"\n                    } else {\n                        \"are similarly named features\"\n                    },\n                    suggestions.join(\", \")\n                )?;\n            }\n        }\n\n        bail!(\"{msg}\")\n    }\n\n    /// New command-line feature selection behavior with resolver = \"2\" or the\n    /// root of a virtual workspace. See `allows_new_cli_feature_behavior`.\n    fn members_with_features_new(\n        &self,\n        specs: &[PackageIdSpec],\n        cli_features: &CliFeatures,\n    ) -> CargoResult<Vec<(&Package, CliFeatures)>> {\n        // Keeps track of which features matched `member` to produce an error\n        // if any of them did not match anywhere.\n        let mut found_features = Default::default();\n\n        let members: Vec<(&Package, CliFeatures)> = self\n            .members()\n            .filter(|m| specs.iter().any(|spec| spec.matches(m.package_id())))\n            .map(|m| {\n                (\n                    m,\n                    Workspace::collect_matching_features(m, cli_features, &mut found_features),\n                )\n            })\n            .collect();\n\n        if members.is_empty() {\n            // `cargo build -p foo`, where `foo` is not a member.\n            // Do not allow any command-line flags (defaults only).\n            if !(cli_features.features.is_empty()\n                && !cli_features.all_features\n                && cli_features.uses_default_features)\n            {\n                bail!(\"cannot specify features for packages outside of workspace\");\n            }\n            // Add all members from the workspace so we can ensure `-p nonmember`\n            // is in the resolve graph.\n            return Ok(self\n                .members()\n                .map(|m| (m, CliFeatures::new_all(false)))\n                .collect());\n        }\n        if *cli_features.features != found_features {\n            self.report_unknown_features_error(specs, cli_features, &found_features)?;\n        }\n        Ok(members)\n    }\n\n    /// This is the \"old\" behavior for command-line feature selection.\n    /// See `allows_new_cli_feature_behavior`.\n    fn members_with_features_old(\n        &self,\n        specs: &[PackageIdSpec],\n        cli_features: &CliFeatures,\n    ) -> Vec<(&Package, CliFeatures)> {\n        // Split off any features with the syntax `member-name/feature-name` into a map\n        // so that those features can be applied directly to those workspace-members.\n        let mut member_specific_features: HashMap<InternedString, BTreeSet<FeatureValue>> =\n            HashMap::new();\n        // Features for the member in the current directory.\n        let mut cwd_features = BTreeSet::new();\n        for feature in cli_features.features.iter() {\n            match feature {\n                FeatureValue::Feature(_) => {\n                    cwd_features.insert(feature.clone());\n                }\n                // This should be enforced by CliFeatures.\n                FeatureValue::Dep { .. } => panic!(\"unexpected dep: syntax {}\", feature),\n                FeatureValue::DepFeature {\n                    dep_name,\n                    dep_feature,\n                    weak: _,\n                } => {\n                    // I think weak can be ignored here.\n                    // * With `--features member?/feat -p member`, the ? doesn't\n                    //   really mean anything (either the member is built or it isn't).\n                    // * With `--features nonmember?/feat`, cwd_features will\n                    //   handle processing it correctly.\n                    let is_member = self.members().any(|member| {\n                        // Check if `dep_name` is member of the workspace, but isn't associated with current package.\n                        self.current_opt() != Some(member) && member.name() == *dep_name\n                    });\n                    if is_member && specs.iter().any(|spec| spec.name() == dep_name.as_str()) {\n                        member_specific_features\n                            .entry(*dep_name)\n                            .or_default()\n                            .insert(FeatureValue::Feature(*dep_feature));\n                    } else {\n                        cwd_features.insert(feature.clone());\n                    }\n                }\n            }\n        }\n\n        let ms: Vec<_> = self\n            .members()\n            .filter_map(|member| {\n                let member_id = member.package_id();\n                match self.current_opt() {\n                    // The features passed on the command-line only apply to\n                    // the \"current\" package (determined by the cwd).\n                    Some(current) if member_id == current.package_id() => {\n                        let feats = CliFeatures {\n                            features: Rc::new(cwd_features.clone()),\n                            all_features: cli_features.all_features,\n                            uses_default_features: cli_features.uses_default_features,\n                        };\n                        Some((member, feats))\n                    }\n                    _ => {\n                        // Ignore members that are not enabled on the command-line.\n                        if specs.iter().any(|spec| spec.matches(member_id)) {\n                            // -p for a workspace member that is not the \"current\"\n                            // one.\n                            //\n                            // The odd behavior here is due to backwards\n                            // compatibility. `--features` and\n                            // `--no-default-features` used to only apply to the\n                            // \"current\" package. As an extension, this allows\n                            // member-name/feature-name to set member-specific\n                            // features, which should be backwards-compatible.\n                            let feats = CliFeatures {\n                                features: Rc::new(\n                                    member_specific_features\n                                        .remove(member.name().as_str())\n                                        .unwrap_or_default(),\n                                ),\n                                uses_default_features: true,\n                                all_features: cli_features.all_features,\n                            };\n                            Some((member, feats))\n                        } else {\n                            // This member was not requested on the command-line, skip.\n                            None\n                        }\n                    }\n                }\n            })\n            .collect();\n\n        // If any member specific features were not removed while iterating over members\n        // some features will be ignored.\n        assert!(member_specific_features.is_empty());\n\n        ms\n    }\n\n    /// Returns true if `unit` should depend on the output of Docscrape units.\n    pub fn unit_needs_doc_scrape(&self, unit: &Unit) -> bool {\n        // We do not add scraped units for Host units, as they're either build scripts\n        // (not documented) or proc macros (have no scrape-able exports). Additionally,\n        // naively passing a proc macro's unit_for to new_unit_dep will currently cause\n        // Cargo to panic, see issue #10545.\n        self.is_member(&unit.pkg) && !(unit.target.for_host() || unit.pkg.proc_macro())\n    }\n\n    /// Adds a local package registry overlaying a `SourceId`.\n    ///\n    /// See [`crate::sources::overlay::DependencyConfusionThreatOverlaySource`] for why you shouldn't use this.\n    pub fn add_local_overlay(&mut self, id: SourceId, registry_path: PathBuf) {\n        self.local_overlays.insert(id, registry_path);\n    }\n\n    /// Builds a package registry that reflects this workspace configuration.\n    pub fn package_registry(&self) -> CargoResult<PackageRegistry<'gctx>> {\n        let source_config =\n            SourceConfigMap::new_with_overlays(self.gctx(), self.local_overlays()?)?;\n        PackageRegistry::new_with_source_config(self.gctx(), source_config)\n    }\n\n    /// Returns all the configured local overlays, including the ones from our secret environment variable.\n    fn local_overlays(&self) -> CargoResult<impl Iterator<Item = (SourceId, SourceId)>> {\n        let mut ret = self\n            .local_overlays\n            .iter()\n            .map(|(id, path)| Ok((*id, SourceId::for_local_registry(path)?)))\n            .collect::<CargoResult<Vec<_>>>()?;\n\n        if let Ok(overlay) = self\n            .gctx\n            .get_env(\"__CARGO_TEST_DEPENDENCY_CONFUSION_VULNERABILITY_DO_NOT_USE_THIS\")\n        {\n            let (url, path) = overlay.split_once('=').ok_or(anyhow::anyhow!(\n                \"invalid overlay format. I won't tell you why; you shouldn't be using it anyway\"\n            ))?;\n            ret.push((\n                SourceId::from_url(url)?,\n                SourceId::for_local_registry(path.as_ref())?,\n            ));\n        }\n\n        Ok(ret.into_iter())\n    }\n}\n\nimpl<'gctx> Packages<'gctx> {\n    fn get(&self, manifest_path: &Path) -> &MaybePackage {\n        self.maybe_get(manifest_path).unwrap()\n    }\n\n    fn get_mut(&mut self, manifest_path: &Path) -> &mut MaybePackage {\n        self.maybe_get_mut(manifest_path).unwrap()\n    }\n\n    fn maybe_get(&self, manifest_path: &Path) -> Option<&MaybePackage> {\n        self.packages.get(manifest_path)\n    }\n\n    fn maybe_get_mut(&mut self, manifest_path: &Path) -> Option<&mut MaybePackage> {\n        self.packages.get_mut(manifest_path)\n    }\n\n    fn load(&mut self, manifest_path: &Path) -> CargoResult<&MaybePackage> {\n        match self.packages.entry(manifest_path.to_path_buf()) {\n            Entry::Occupied(e) => Ok(e.into_mut()),\n            Entry::Vacant(v) => {\n                let source_id = SourceId::for_manifest_path(manifest_path)?;\n                let manifest = read_manifest(manifest_path, source_id, self.gctx)?;\n                Ok(v.insert(match manifest {\n                    EitherManifest::Real(manifest) => {\n                        MaybePackage::Package(Package::new(manifest, manifest_path))\n                    }\n                    EitherManifest::Virtual(vm) => MaybePackage::Virtual(vm),\n                }))\n            }\n        }\n    }\n}\n\nimpl MaybePackage {\n    fn workspace_config(&self) -> &WorkspaceConfig {\n        match *self {\n            MaybePackage::Package(ref p) => p.manifest().workspace_config(),\n            MaybePackage::Virtual(ref vm) => vm.workspace_config(),\n        }\n    }\n\n    /// Has an embedded manifest (single-file package)\n    pub fn is_embedded(&self) -> bool {\n        match self {\n            MaybePackage::Package(p) => p.manifest().is_embedded(),\n            MaybePackage::Virtual(_) => false,\n        }\n    }\n\n    pub fn contents(&self) -> Option<&str> {\n        match self {\n            MaybePackage::Package(p) => p.manifest().contents(),\n            MaybePackage::Virtual(v) => v.contents(),\n        }\n    }\n\n    pub fn document(&self) -> Option<&toml::Spanned<toml::de::DeTable<'static>>> {\n        match self {\n            MaybePackage::Package(p) => p.manifest().document(),\n            MaybePackage::Virtual(v) => v.document(),\n        }\n    }\n\n    pub fn original_toml(&self) -> Option<&TomlManifest> {\n        match self {\n            MaybePackage::Package(p) => p.manifest().original_toml(),\n            MaybePackage::Virtual(v) => v.original_toml(),\n        }\n    }\n\n    pub fn normalized_toml(&self) -> &TomlManifest {\n        match self {\n            MaybePackage::Package(p) => p.manifest().normalized_toml(),\n            MaybePackage::Virtual(v) => v.normalized_toml(),\n        }\n    }\n\n    pub fn edition(&self) -> Edition {\n        match self {\n            MaybePackage::Package(p) => p.manifest().edition(),\n            MaybePackage::Virtual(_) => Edition::default(),\n        }\n    }\n\n    pub fn profiles(&self) -> Option<&TomlProfiles> {\n        match self {\n            MaybePackage::Package(p) => p.manifest().profiles(),\n            MaybePackage::Virtual(v) => v.profiles(),\n        }\n    }\n\n    pub fn unstable_features(&self) -> &Features {\n        match self {\n            MaybePackage::Package(p) => p.manifest().unstable_features(),\n            MaybePackage::Virtual(vm) => vm.unstable_features(),\n        }\n    }\n}\n\nimpl WorkspaceRootConfig {\n    /// Creates a new Intermediate Workspace Root configuration.\n    pub fn new(\n        root_dir: &Path,\n        members: &Option<Vec<String>>,\n        default_members: &Option<Vec<String>>,\n        exclude: &Option<Vec<String>>,\n        inheritable: &Option<InheritableFields>,\n        custom_metadata: &Option<toml::Value>,\n    ) -> WorkspaceRootConfig {\n        WorkspaceRootConfig {\n            root_dir: root_dir.to_path_buf(),\n            members: members.clone(),\n            default_members: default_members.clone(),\n            exclude: exclude.clone().unwrap_or_default(),\n            inheritable_fields: inheritable.clone().unwrap_or_default(),\n            custom_metadata: custom_metadata.clone(),\n        }\n    }\n    /// Checks the path against the `excluded` list.\n    ///\n    /// This method does **not** consider the `members` list.\n    fn is_excluded(&self, manifest_path: &Path) -> bool {\n        let excluded = self\n            .exclude\n            .iter()\n            .any(|ex| manifest_path.starts_with(self.root_dir.join(ex)));\n\n        let explicit_member = match self.members {\n            Some(ref members) => members\n                .iter()\n                .any(|mem| manifest_path.starts_with(self.root_dir.join(mem))),\n            None => false,\n        };\n\n        !explicit_member && excluded\n    }\n\n    /// Checks if the path is explicitly listed as a workspace member.\n    ///\n    /// Returns `true` ONLY if:\n    /// - The path is the workspace root manifest itself, or\n    /// - The path matches one of the explicit `members` patterns\n    ///\n    /// NOTE: This does NOT check for implicit path dependency membership.\n    /// A `false` return does NOT mean the package is definitely not a member -\n    /// it could still be a member via path dependencies. Callers should fallback\n    /// to full workspace loading when this returns `false`.\n    fn is_explicitly_listed_member(&self, manifest_path: &Path) -> bool {\n        let root_manifest = self.root_dir.join(\"Cargo.toml\");\n        if manifest_path == root_manifest {\n            return true;\n        }\n        match self.members {\n            Some(ref members) => {\n                // Use members_paths to properly expand glob patterns\n                let Ok(expanded_members) = self.members_paths(members) else {\n                    return false;\n                };\n                // Normalize the manifest path for comparison\n                let normalized_manifest = paths::normalize_path(manifest_path);\n                expanded_members.iter().any(|(member_path, _)| {\n                    // Normalize the member path as glob expansion may leave \"..\" components\n                    let normalized_member = paths::normalize_path(member_path);\n                    // Compare the manifest's parent directory with the member path exactly\n                    // instead of using starts_with to avoid matching nested directories\n                    normalized_manifest.parent() == Some(normalized_member.as_path())\n                })\n            }\n            None => false,\n        }\n    }\n\n    fn has_members_list(&self) -> bool {\n        self.members.is_some()\n    }\n\n    /// Returns true if this workspace config has default-members defined.\n    fn has_default_members(&self) -> bool {\n        self.default_members.is_some()\n    }\n\n    /// Returns expanded paths along with the glob that they were expanded from.\n    /// The glob is `None` if the path matched exactly.\n    #[tracing::instrument(skip_all)]\n    fn members_paths<'g>(\n        &self,\n        globs: &'g [String],\n    ) -> CargoResult<Vec<(PathBuf, Option<&'g str>)>> {\n        let mut expanded_list = Vec::new();\n\n        for glob in globs {\n            let pathbuf = self.root_dir.join(glob);\n            let expanded_paths = Self::expand_member_path(&pathbuf)?;\n\n            // If glob does not find any valid paths, then put the original\n            // path in the expanded list to maintain backwards compatibility.\n            if expanded_paths.is_empty() {\n                expanded_list.push((pathbuf, None));\n            } else {\n                let used_glob_pattern = expanded_paths.len() > 1 || expanded_paths[0] != pathbuf;\n                let glob = used_glob_pattern.then_some(glob.as_str());\n\n                // Some OS can create system support files anywhere.\n                // (e.g. macOS creates `.DS_Store` file if you visit a directory using Finder.)\n                // Such files can be reported as a member path unexpectedly.\n                // Check and filter out non-directory paths to prevent pushing such accidental unwanted path\n                // as a member.\n                for expanded_path in expanded_paths {\n                    if expanded_path.is_dir() {\n                        expanded_list.push((expanded_path, glob));\n                    }\n                }\n            }\n        }\n\n        Ok(expanded_list)\n    }\n\n    fn expand_member_path(path: &Path) -> CargoResult<Vec<PathBuf>> {\n        let Some(path) = path.to_str() else {\n            return Ok(Vec::new());\n        };\n        let res = glob(path).with_context(|| format!(\"could not parse pattern `{}`\", &path))?;\n        let res = res\n            .map(|p| p.with_context(|| format!(\"unable to match path to pattern `{}`\", &path)))\n            .collect::<Result<Vec<_>, _>>()?;\n        Ok(res)\n    }\n\n    pub fn inheritable(&self) -> &InheritableFields {\n        &self.inheritable_fields\n    }\n}\n\npub fn resolve_relative_path(\n    label: &str,\n    old_root: &Path,\n    new_root: &Path,\n    rel_path: &str,\n) -> CargoResult<String> {\n    let joined_path = normalize_path(&old_root.join(rel_path));\n    match diff_paths(joined_path, new_root) {\n        None => Err(anyhow!(\n            \"`{}` was defined in {} but could not be resolved with {}\",\n            label,\n            old_root.display(),\n            new_root.display()\n        )),\n        Some(path) => Ok(path\n            .to_str()\n            .ok_or_else(|| {\n                anyhow!(\n                    \"`{}` resolved to non-UTF value (`{}`)\",\n                    label,\n                    path.display()\n                )\n            })?\n            .to_owned()),\n    }\n}\n\n/// Finds the path of the root of the workspace.\npub fn find_workspace_root(\n    manifest_path: &Path,\n    gctx: &GlobalContext,\n) -> CargoResult<Option<PathBuf>> {\n    find_workspace_root_with_loader(manifest_path, gctx, |self_path| {\n        let source_id = SourceId::for_manifest_path(self_path)?;\n        let manifest = read_manifest(self_path, source_id, gctx)?;\n        Ok(manifest\n            .workspace_config()\n            .get_ws_root(self_path, manifest_path))\n    })\n}\n\n/// Finds the workspace root for a manifest, with minimal verification.\n///\n/// This is similar to `find_workspace_root`, but additionally verifies that the\n/// package and workspace agree on each other:\n/// - If the package has an explicit `package.workspace` pointer, it is trusted\n/// - Otherwise, the workspace must include the package in its `members` list\npub fn find_workspace_root_with_membership_check(\n    manifest_path: &Path,\n    gctx: &GlobalContext,\n) -> CargoResult<Option<PathBuf>> {\n    let source_id = SourceId::for_manifest_path(manifest_path)?;\n    let current_manifest = read_manifest(manifest_path, source_id, gctx)?;\n\n    match current_manifest.workspace_config() {\n        WorkspaceConfig::Root(root_config) => {\n            // This manifest is a workspace root itself\n            // If default-members are defined, fall back to full loading for proper validation\n            if root_config.has_default_members() {\n                Ok(None)\n            } else {\n                Ok(Some(manifest_path.to_path_buf()))\n            }\n        }\n        WorkspaceConfig::Member {\n            root: Some(path_to_root),\n        } => {\n            // Has explicit `package.workspace` pointer - verify the workspace agrees\n            let ws_manifest_path = read_root_pointer(manifest_path, path_to_root);\n            let ws_source_id = SourceId::for_manifest_path(&ws_manifest_path)?;\n            let ws_manifest = read_manifest(&ws_manifest_path, ws_source_id, gctx)?;\n\n            // Verify the workspace includes this package in its members\n            if let WorkspaceConfig::Root(ref root_config) = *ws_manifest.workspace_config() {\n                if root_config.is_explicitly_listed_member(manifest_path)\n                    && !root_config.is_excluded(manifest_path)\n                {\n                    return Ok(Some(ws_manifest_path));\n                }\n            }\n            // Workspace doesn't agree with the pointer - not a valid workspace root\n            Ok(None)\n        }\n        WorkspaceConfig::Member { root: None } => {\n            // No explicit pointer, walk up with membership validation\n            find_workspace_root_with_loader(manifest_path, gctx, |candidate_manifest_path| {\n                let source_id = SourceId::for_manifest_path(candidate_manifest_path)?;\n                let manifest = read_manifest(candidate_manifest_path, source_id, gctx)?;\n                if let WorkspaceConfig::Root(ref root_config) = *manifest.workspace_config() {\n                    if root_config.is_explicitly_listed_member(manifest_path)\n                        && !root_config.is_excluded(manifest_path)\n                    {\n                        return Ok(Some(candidate_manifest_path.to_path_buf()));\n                    }\n                }\n                Ok(None)\n            })\n        }\n    }\n}\n\n/// Finds the path of the root of the workspace.\n///\n/// This uses a callback to determine if the given path tells us what the\n/// workspace root is.\nfn find_workspace_root_with_loader(\n    manifest_path: &Path,\n    gctx: &GlobalContext,\n    mut loader: impl FnMut(&Path) -> CargoResult<Option<PathBuf>>,\n) -> CargoResult<Option<PathBuf>> {\n    // Check if there are any workspace roots that have already been found that would work\n    {\n        let roots = gctx.ws_roots();\n        // Iterate through the manifests parent directories until we find a workspace\n        // root. Note we skip the first item since that is just the path itself\n        for current in manifest_path.ancestors().skip(1) {\n            if let Some(ws_config) = roots.get(current) {\n                if !ws_config.is_excluded(manifest_path) {\n                    // Add `Cargo.toml` since ws_root is the root and not the file\n                    return Ok(Some(current.join(\"Cargo.toml\")));\n                }\n            }\n        }\n    }\n\n    for ances_manifest_path in find_root_iter(manifest_path, gctx) {\n        debug!(\"find_root - trying {}\", ances_manifest_path.display());\n        let ws_root_path = loader(&ances_manifest_path).with_context(|| {\n            format!(\n                \"failed searching for potential workspace\\n\\\n                 package manifest: `{}`\\n\\\n                 invalid potential workspace manifest: `{}`\\n\\\n                 \\n\\\n                 help: to avoid searching for a non-existent workspace, add \\\n                 `[workspace]` to the package manifest\",\n                manifest_path.display(),\n                ances_manifest_path.display(),\n            )\n        })?;\n        if let Some(ws_root_path) = ws_root_path {\n            return Ok(Some(ws_root_path));\n        }\n    }\n    Ok(None)\n}\n\nfn read_root_pointer(member_manifest: &Path, root_link: &str) -> PathBuf {\n    let path = member_manifest\n        .parent()\n        .unwrap()\n        .join(root_link)\n        .join(\"Cargo.toml\");\n    debug!(\"find_root - pointer {}\", path.display());\n    paths::normalize_path(&path)\n}\n\nfn find_root_iter<'a>(\n    manifest_path: &'a Path,\n    gctx: &'a GlobalContext,\n) -> impl Iterator<Item = PathBuf> + 'a {\n    LookBehind::new(paths::ancestors(manifest_path, None).skip(2))\n        .take_while(|path| !path.curr.ends_with(\"target/package\"))\n        // Don't walk across `CARGO_HOME` when we're looking for the\n        // workspace root. Sometimes a package will be organized with\n        // `CARGO_HOME` pointing inside of the workspace root or in the\n        // current package, but we don't want to mistakenly try to put\n        // crates.io crates into the workspace by accident.\n        .take_while(|path| {\n            if let Some(last) = path.last {\n                gctx.home() != last\n            } else {\n                true\n            }\n        })\n        .map(|path| path.curr.join(\"Cargo.toml\"))\n        .filter(|ances_manifest_path| ances_manifest_path.exists())\n}\n\nstruct LookBehindWindow<'a, T: ?Sized> {\n    curr: &'a T,\n    last: Option<&'a T>,\n}\n\nstruct LookBehind<'a, T: ?Sized, K: Iterator<Item = &'a T>> {\n    iter: K,\n    last: Option<&'a T>,\n}\n\nimpl<'a, T: ?Sized, K: Iterator<Item = &'a T>> LookBehind<'a, T, K> {\n    fn new(items: K) -> Self {\n        Self {\n            iter: items,\n            last: None,\n        }\n    }\n}\n\nimpl<'a, T: ?Sized, K: Iterator<Item = &'a T>> Iterator for LookBehind<'a, T, K> {\n    type Item = LookBehindWindow<'a, T>;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        match self.iter.next() {\n            None => None,\n            Some(next) => {\n                let last = self.last;\n                self.last = Some(next);\n                Some(LookBehindWindow { curr: next, last })\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/lib.rs",
    "content": "//! # Cargo as a library\n//!\n//! There are two places you can find API documentation of cargo-the-library,\n//!\n//! - <https://docs.rs/cargo>: targeted at external tool developers using cargo-the-library\n//!   - Released with every rustc release\n//! - <https://doc.rust-lang.org/nightly/nightly-rustc/cargo>: targeted at cargo contributors\n//!   - Updated on each update of the `cargo` submodule in `rust-lang/rust`\n//!\n//! > This library is maintained by the Cargo team, primarily for use by Cargo\n//! > and not intended for external use (except as a transitive dependency). This\n//! > crate may make major changes to its APIs. See [The Cargo Book:\n//! > External tools] for more on this topic.\n//!\n//! ## Overview\n//!\n//! Major components of cargo include:\n//!\n//! - [`ops`]:\n//!   Every major operation is implemented here. Each command is a thin wrapper around ops.\n//!   - [`ops::cargo_compile`]:\n//!     This is the entry point for all the compilation commands. This is a\n//!     good place to start if you want to follow how compilation starts and\n//!     flows to completion.\n//! - [`ops::resolve`]:\n//!   Top-level API for dependency and feature resolver (e.g. [`ops::resolve_ws`])\n//!   - [`core::resolver`]: The core algorithm\n//! - [`core::compiler`]:\n//!   This is the code responsible for running `rustc` and `rustdoc`.\n//!   - [`core::compiler::build_context`]:\n//!     The [`BuildContext`][core::compiler::BuildContext] is the result of the \"front end\" of the\n//!     build process. This contains the graph of work to perform and any settings necessary for\n//!     `rustc`. After this is built, the next stage of building is handled in\n//!     [`BuildRunner`][core::compiler::BuildRunner].\n//!   - [`core::compiler::build_runner`]:\n//!     The `Context` is the mutable state used during the build process. This\n//!     is the core of the build process, and everything is coordinated through\n//!     this.\n//!   - [`core::compiler::fingerprint`]:\n//!     The `fingerprint` module contains all the code that handles detecting\n//!     if a crate needs to be recompiled.\n//! - [`sources::source`]:\n//!   The [`sources::source::Source`] trait is an abstraction over different sources of packages.\n//!   Sources are uniquely identified by a [`core::SourceId`]. Sources are implemented in the [`sources`]\n//!   directory.\n//! - [`util`]:\n//!   This directory contains generally-useful utility modules.\n//! - [`util::context`]:\n//!   This directory contains the global application context.\n//!   This includes the config parser which makes heavy use of\n//!   [serde](https://serde.rs/) to merge and translate config values.\n//!   The [`util::GlobalContext`] is usually accessed from the\n//!   [`core::Workspace`]\n//!   though references to it are scattered around for more convenient access.\n//! - [`util::toml`]:\n//!   This directory contains the code for parsing `Cargo.toml` files.\n//!   - [`ops::lockfile`]:\n//!     This is where `Cargo.lock` files are loaded and saved.\n//!\n//! Related crates:\n//! - [`cargo-platform`](https://crates.io/crates/cargo-platform)\n//!   ([nightly docs](https://doc.rust-lang.org/nightly/nightly-rustc/cargo_platform)):\n//!   This library handles parsing `cfg` expressions.\n//! - [`cargo-util`](https://crates.io/crates/cargo-util)\n//!   ([nightly docs](https://doc.rust-lang.org/nightly/nightly-rustc/cargo_util)):\n//!   This contains general utility code that is shared between cargo and the testsuite\n//! - [`cargo-util-schemas`](https://crates.io/crates/cargo-util-schemas)\n//!   ([nightly docs](https://doc.rust-lang.org/nightly/nightly-rustc/cargo_util_schemas)):\n//!   This contains the serde schemas for cargo\n//! - [`crates-io`](https://crates.io/crates/crates-io)\n//!   ([nightly docs](https://doc.rust-lang.org/nightly/nightly-rustc/crates_io)):\n//!   This contains code for accessing the crates.io API.\n//! - [`home`](https://crates.io/crates/home):\n//!   This library is shared between cargo and rustup and is used for finding their home directories.\n//!   This is not directly depended upon with a `path` dependency; cargo uses the version from crates.io.\n//!   It is intended to be versioned and published independently of Rust's release system.\n//!   Whenever a change needs to be made, bump the version in Cargo.toml and `cargo publish` it manually, and then update cargo's `Cargo.toml` to depend on the new version.\n//! - [`rustfix`](https://crates.io/crates/rustfix)\n//!   ([nightly docs](https://doc.rust-lang.org/nightly/nightly-rustc/rustfix)):\n//!   This defines structures that represent fix suggestions from rustc,\n//!   as well as generates \"fixed\" code from suggestions.\n//!   Operations in `rustfix` are all in memory and won't write to disks.\n//! - [`cargo-test-support`](https://github.com/rust-lang/cargo/tree/master/crates/cargo-test-support)\n//!   ([nightly docs](https://doc.rust-lang.org/nightly/nightly-rustc/cargo_test_support/index.html)):\n//!   This contains a variety of code to support writing tests\n//! - [`cargo-test-macro`](https://github.com/rust-lang/cargo/tree/master/crates/cargo-test-macro)\n//!   ([nightly docs](https://doc.rust-lang.org/nightly/nightly-rustc/cargo_test_macro/index.html)):\n//!   This is the `#[cargo_test]` proc-macro used by the test suite to define tests.\n//! - [`credential`](https://github.com/rust-lang/cargo/tree/master/credential)\n//!   This subdirectory contains several packages for implementing the\n//!   [credential providers](https://doc.rust-lang.org/nightly/cargo/reference/registry-authentication.html).\n//! - [`mdman`](https://github.com/rust-lang/cargo/tree/master/crates/mdman)\n//!   ([nightly docs](https://doc.rust-lang.org/nightly/nightly-rustc/mdman/index.html)):\n//!   This is a utility for generating cargo's man pages. See [Building the man\n//!   pages](https://github.com/rust-lang/cargo/tree/master/src/doc#building-the-man-pages)\n//!   for more information.\n//! - [`resolver-tests`](https://github.com/rust-lang/cargo/tree/master/crates/resolver-tests)\n//!   This is a dedicated package that defines tests for the [dependency\n//!   resolver][core::resolver].\n//!\n//! ### File Overview\n//!\n//! Files that interact with cargo include\n//!\n//! - Package\n//!   - `Cargo.toml`: User-written project manifest, loaded with [`util::toml::read_manifest`] and then\n//!     translated to [`core::manifest::Manifest`] which maybe stored in a [`core::Package`].\n//!     - This is editable with [`util::toml_mut::manifest::LocalManifest`]\n//!   - `Cargo.lock`: Generally loaded with [`ops::resolve_ws`] or a variant of it into a [`core::resolver::Resolve`]\n//!     - At the lowest level, [`ops::load_pkg_lockfile`] and [`ops::write_pkg_lockfile`] are used\n//!     - See [`core::resolver::encode`] for versioning of `Cargo.lock`\n//!   - `target/`: Used for build artifacts and abstracted with [`core::compiler::layout`]. `Layout` handles locking the target directory and providing paths to parts inside. There is a separate `Layout` for each build `target`.\n//!     - `target/debug/.fingerprint`: Tracker whether nor not a crate needs to be rebuilt.  See [`core::compiler::fingerprint`]\n//! - `$CARGO_HOME/`:\n//!   - `registry/`: Package registry cache which is managed in [`sources::registry`].  Be careful\n//!     as the lock [`util::GlobalContext::acquire_package_cache_lock`] must be manually acquired.\n//!     - `index`/: Fast-to-access crate metadata (no need to download / extract `*.crate` files)\n//!     - `cache/*/*.crate`: Local cache of published crates\n//!     - `src/*/*`: Extracted from `*.crate` by [`sources::registry::RegistrySource`]\n//!   - `git/`: Git source cache.  See [`sources::git`].\n//! - `**/.cargo/config.toml`: Environment dependent (env variables, files) configuration.  See\n//!   [`util::context`]\n//!\n//! ## Contribute to Cargo documentations\n//!\n//! The Cargo team always continues improving all external and internal documentations.\n//! If you spot anything could be better, don't hesitate to discuss with the team on\n//! Zulip [`t-cargo` stream], or [submit an issue] right on GitHub.\n//! There is also an issue label [`A-documenting-cargo-itself`],\n//! which is generally for documenting user-facing [The Cargo Book],\n//! but the Cargo team is welcome any form of enhancement for the [Cargo Contributor Guide]\n//! and this API documentation as well.\n//!\n//! [The Cargo Book: External tools]: https://doc.rust-lang.org/stable/cargo/reference/external-tools.html\n//! [Cargo Architecture Overview]: https://doc.crates.io/contrib/architecture\n//! [`t-cargo` stream]: https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo\n//! [submit an issue]: https://github.com/rust-lang/cargo/issues/new/choose\n//! [`A-documenting-cargo-itself`]: https://github.com/rust-lang/cargo/labels/A-documenting-cargo-itself\n//! [The Cargo Book]: https://doc.rust-lang.org/cargo/\n//! [Cargo Contributor Guide]: https://doc.crates.io/contrib/\n\nuse crate::core::Shell;\nuse crate::core::shell::Verbosity;\nuse crate::core::shell::Verbosity::Verbose;\nuse anyhow::Error;\nuse tracing::debug;\n\npub use crate::util::errors::{AlreadyPrintedError, InternalError, VerboseError};\npub use crate::util::{CargoResult, CliError, CliResult, GlobalContext, indented_lines};\npub use crate::version::version;\n\npub const CARGO_ENV: &str = \"CARGO\";\n\n#[macro_use]\nmod macros;\n\npub mod core;\npub mod lints;\npub mod ops;\npub mod sources;\npub mod util;\nmod version;\n\npub fn exit_with_error(err: CliError, shell: &mut Shell) -> ! {\n    debug!(\"exit_with_error; err={:?}\", err);\n\n    if let Some(ref err) = err.error {\n        if let Some(clap_err) = err.downcast_ref::<clap::Error>() {\n            let exit_code = if clap_err.use_stderr() { 1 } else { 0 };\n            let _ = clap_err.print();\n            std::process::exit(exit_code)\n        }\n    }\n\n    let CliError { error, exit_code } = err;\n    if let Some(error) = error {\n        display_error(&error, shell);\n    }\n\n    std::process::exit(exit_code)\n}\n\n/// Displays an error, and all its causes, to stderr.\npub fn display_error(err: &Error, shell: &mut Shell) {\n    debug!(\"display_error; err={:?}\", err);\n    _display_error(err, shell, true);\n    if err\n        .chain()\n        .any(|e| e.downcast_ref::<InternalError>().is_some())\n    {\n        drop(shell.note(\"this is an unexpected cargo internal error\"));\n        drop(\n            shell.note(\n                \"we would appreciate a bug report: https://github.com/rust-lang/cargo/issues/\",\n            ),\n        );\n        drop(shell.note(format!(\"cargo {}\", version())));\n        // Once backtraces are stabilized, this should print out a backtrace\n        // if it is available.\n    }\n}\n\n/// Displays a warning, with an error object providing detailed information\n/// and context.\npub fn display_warning_with_error(warning: &str, err: &Error, shell: &mut Shell) {\n    drop(shell.warn(warning));\n    drop(writeln!(shell.err()));\n    _display_error(err, shell, false);\n}\n\nfn error_chain(err: &Error, verbosity: Verbosity) -> impl Iterator<Item = &dyn std::fmt::Display> {\n    err.chain()\n        .take_while(move |err| {\n            // If we're not in verbose mode then only print cause chain until one\n            // marked as `VerboseError` appears.\n            //\n            // Generally the top error shouldn't be verbose, but check it anyways.\n            verbosity == Verbose || !err.is::<VerboseError>()\n        })\n        .take_while(|err| !err.is::<AlreadyPrintedError>())\n        .map(|err| err as &dyn std::fmt::Display)\n}\n\nfn _display_error(err: &Error, shell: &mut Shell, as_err: bool) {\n    for (i, err) in error_chain(err, shell.verbosity()).enumerate() {\n        if i == 0 {\n            if as_err {\n                drop(shell.error(&err));\n            } else {\n                drop(writeln!(shell.err(), \"{}\", err));\n            }\n        } else {\n            drop(writeln!(shell.err(), \"\\nCaused by:\"));\n            drop(write!(shell.err(), \"{}\", indented_lines(&err.to_string())));\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/lints/mod.rs",
    "content": "use std::borrow::Cow;\nuse std::cmp::{Reverse, max_by_key};\nuse std::fmt::Display;\nuse std::ops::Range;\nuse std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::RustVersion;\nuse cargo_util_schemas::manifest::TomlLintLevel;\nuse cargo_util_schemas::manifest::TomlToolLints;\nuse pathdiff::diff_paths;\n\nuse crate::core::Workspace;\nuse crate::core::{Edition, Feature, Features, MaybePackage, Package};\nuse crate::{CargoResult, GlobalContext};\n\npub mod rules;\npub use rules::LINTS;\n\npub static LINT_GROUPS: &[LintGroup] = &[\n    COMPLEXITY,\n    CORRECTNESS,\n    NURSERY,\n    PEDANTIC,\n    PERF,\n    RESTRICTION,\n    STYLE,\n    SUSPICIOUS,\n    TEST_DUMMY_UNSTABLE,\n];\n\n/// Scope at which a lint runs: package-level or workspace-level.\npub enum ManifestFor<'a> {\n    /// Lint runs for a specific package.\n    Package(&'a Package),\n    /// Lint runs for workspace-level config.\n    Workspace {\n        ws: &'a Workspace<'a>,\n        maybe_pkg: &'a MaybePackage,\n    },\n}\n\nimpl ManifestFor<'_> {\n    fn lint_level(&self, pkg_lints: &TomlToolLints, lint: &Lint) -> (LintLevel, LintLevelReason) {\n        lint.level(pkg_lints, self.rust_version(), self.unstable_features())\n    }\n\n    pub fn rust_version(&self) -> Option<&RustVersion> {\n        match self {\n            ManifestFor::Package(p) => p.rust_version(),\n            ManifestFor::Workspace { ws, maybe_pkg: _ } => ws.lowest_rust_version(),\n        }\n    }\n\n    pub fn contents(&self) -> Option<&str> {\n        match self {\n            ManifestFor::Package(p) => p.manifest().contents(),\n            ManifestFor::Workspace { ws: _, maybe_pkg } => maybe_pkg.contents(),\n        }\n    }\n\n    pub fn document(&self) -> Option<&toml::Spanned<toml::de::DeTable<'static>>> {\n        match self {\n            ManifestFor::Package(p) => p.manifest().document(),\n            ManifestFor::Workspace { ws: _, maybe_pkg } => maybe_pkg.document(),\n        }\n    }\n\n    pub fn edition(&self) -> Edition {\n        match self {\n            ManifestFor::Package(p) => p.manifest().edition(),\n            ManifestFor::Workspace { ws: _, maybe_pkg } => maybe_pkg.edition(),\n        }\n    }\n\n    pub fn unstable_features(&self) -> &Features {\n        match self {\n            ManifestFor::Package(p) => p.manifest().unstable_features(),\n            ManifestFor::Workspace { ws: _, maybe_pkg } => maybe_pkg.unstable_features(),\n        }\n    }\n}\n\nimpl<'a> From<&'a Package> for ManifestFor<'a> {\n    fn from(value: &'a Package) -> ManifestFor<'a> {\n        ManifestFor::Package(value)\n    }\n}\n\nimpl<'a> From<(&'a Workspace<'a>, &'a MaybePackage)> for ManifestFor<'a> {\n    fn from((ws, maybe_pkg): (&'a Workspace<'a>, &'a MaybePackage)) -> ManifestFor<'a> {\n        ManifestFor::Workspace { ws, maybe_pkg }\n    }\n}\n\npub fn analyze_cargo_lints_table(\n    manifest: ManifestFor<'_>,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n    let mut unknown_lints = Vec::new();\n    for lint_name in cargo_lints.keys().map(|name| name) {\n        let Some((name, default_level, feature_gate)) = find_lint_or_group(lint_name) else {\n            unknown_lints.push(lint_name);\n            continue;\n        };\n\n        let (_, reason, _) = level_priority(name, *default_level, cargo_lints);\n\n        // Only run analysis on user-specified lints\n        if !reason.is_user_specified() {\n            continue;\n        }\n\n        // Only run this on lints that are gated by a feature\n        if let Some(feature_gate) = feature_gate\n            && !manifest.unstable_features().is_enabled(feature_gate)\n        {\n            report_feature_not_enabled(\n                name,\n                feature_gate,\n                &manifest,\n                &manifest_path,\n                error_count,\n                gctx,\n            )?;\n        }\n    }\n\n    rules::output_unknown_lints(\n        unknown_lints,\n        &manifest,\n        &manifest_path,\n        cargo_lints,\n        error_count,\n        gctx,\n    )?;\n\n    Ok(())\n}\n\nfn find_lint_or_group<'a>(\n    name: &str,\n) -> Option<(&'static str, &LintLevel, &Option<&'static Feature>)> {\n    if let Some(lint) = LINTS.iter().find(|l| l.name == name) {\n        Some((\n            lint.name,\n            &lint.primary_group.default_level,\n            &lint.feature_gate,\n        ))\n    } else if let Some(group) = LINT_GROUPS.iter().find(|g| g.name == name) {\n        Some((group.name, &group.default_level, &group.feature_gate))\n    } else {\n        None\n    }\n}\n\nfn report_feature_not_enabled(\n    lint_name: &str,\n    feature_gate: &Feature,\n    manifest: &ManifestFor<'_>,\n    manifest_path: &str,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let dash_feature_name = feature_gate.name().replace(\"_\", \"-\");\n    let title = format!(\"use of unstable lint `{}`\", lint_name);\n    let label = format!(\n        \"this is behind `{}`, which is not enabled\",\n        dash_feature_name\n    );\n    let help = format!(\n        \"consider adding `cargo-features = [\\\"{}\\\"]` to the top of the manifest\",\n        dash_feature_name\n    );\n\n    let key_path = match manifest {\n        ManifestFor::Package(_) => &[\"lints\", \"cargo\", lint_name][..],\n        ManifestFor::Workspace { .. } => &[\"workspace\", \"lints\", \"cargo\", lint_name][..],\n    };\n\n    let mut error = Group::with_title(Level::ERROR.primary_title(title));\n\n    if let Some(document) = manifest.document()\n        && let Some(contents) = manifest.contents()\n    {\n        let Some(span) = get_key_value_span(document, key_path) else {\n            // This lint is handled by either package or workspace lint.\n            return Ok(());\n        };\n\n        error = error.element(\n            Snippet::source(contents)\n                .path(manifest_path)\n                .annotation(AnnotationKind::Primary.span(span.key).label(label)),\n        )\n    }\n\n    let report = [error.element(Level::HELP.message(help))];\n\n    *error_count += 1;\n    gctx.shell().print_report(&report, true)?;\n\n    Ok(())\n}\n\n#[derive(Clone)]\npub struct TomlSpan {\n    pub key: Range<usize>,\n    pub value: Range<usize>,\n}\n\n#[derive(Copy, Clone)]\npub enum TomlIndex<'i> {\n    Key(&'i str),\n    Offset(usize),\n}\n\nimpl<'i> TomlIndex<'i> {\n    fn as_key(&self) -> Option<&'i str> {\n        match self {\n            TomlIndex::Key(key) => Some(key),\n            TomlIndex::Offset(_) => None,\n        }\n    }\n}\n\npub trait AsIndex {\n    fn as_index<'i>(&'i self) -> TomlIndex<'i>;\n}\n\nimpl AsIndex for TomlIndex<'_> {\n    fn as_index<'i>(&'i self) -> TomlIndex<'i> {\n        match self {\n            TomlIndex::Key(key) => TomlIndex::Key(key),\n            TomlIndex::Offset(offset) => TomlIndex::Offset(*offset),\n        }\n    }\n}\n\nimpl AsIndex for &str {\n    fn as_index<'i>(&'i self) -> TomlIndex<'i> {\n        TomlIndex::Key(self)\n    }\n}\n\nimpl AsIndex for usize {\n    fn as_index<'i>(&'i self) -> TomlIndex<'i> {\n        TomlIndex::Offset(*self)\n    }\n}\n\npub fn get_key_value<'doc, 'i>(\n    document: &'doc toml::Spanned<toml::de::DeTable<'static>>,\n    path: &[impl AsIndex],\n) -> Option<(\n    &'doc toml::Spanned<Cow<'doc, str>>,\n    &'doc toml::Spanned<toml::de::DeValue<'static>>,\n)> {\n    let table = document.get_ref();\n    let mut iter = path.into_iter();\n    let index0 = iter.next()?.as_index();\n    let key0 = index0.as_key()?;\n    let (mut current_key, mut current_item) = table.get_key_value(key0)?;\n\n    while let Some(index) = iter.next() {\n        match index.as_index() {\n            TomlIndex::Key(key) => {\n                if let Some(table) = current_item.get_ref().as_table() {\n                    (current_key, current_item) = table.get_key_value(key)?;\n                } else if let Some(array) = current_item.get_ref().as_array() {\n                    current_item = array.iter().find(|item| match item.get_ref() {\n                        toml::de::DeValue::String(s) => s == key,\n                        _ => false,\n                    })?;\n                } else {\n                    return None;\n                }\n            }\n            TomlIndex::Offset(offset) => {\n                let array = current_item.get_ref().as_array()?;\n                current_item = array.get(offset)?;\n            }\n        }\n    }\n    Some((current_key, current_item))\n}\n\npub fn get_key_value_span<'i>(\n    document: &toml::Spanned<toml::de::DeTable<'static>>,\n    path: &[impl AsIndex],\n) -> Option<TomlSpan> {\n    get_key_value(document, path).map(|(k, v)| TomlSpan {\n        key: k.span(),\n        value: v.span(),\n    })\n}\n\n/// Gets the relative path to a manifest from the current working directory, or\n/// the absolute path of the manifest if a relative path cannot be constructed\npub fn rel_cwd_manifest_path(path: &Path, gctx: &GlobalContext) -> String {\n    diff_paths(path, gctx.cwd())\n        .unwrap_or_else(|| path.to_path_buf())\n        .display()\n        .to_string()\n}\n\n#[derive(Clone, Debug)]\npub struct LintGroup {\n    pub name: &'static str,\n    pub default_level: LintLevel,\n    pub desc: &'static str,\n    pub feature_gate: Option<&'static Feature>,\n    pub hidden: bool,\n}\n\nconst COMPLEXITY: LintGroup = LintGroup {\n    name: \"complexity\",\n    desc: \"code that does something simple but in a complex way\",\n    default_level: LintLevel::Warn,\n    feature_gate: None,\n    hidden: false,\n};\n\nconst CORRECTNESS: LintGroup = LintGroup {\n    name: \"correctness\",\n    desc: \"code that is outright wrong or useless\",\n    default_level: LintLevel::Deny,\n    feature_gate: None,\n    hidden: false,\n};\n\nconst NURSERY: LintGroup = LintGroup {\n    name: \"nursery\",\n    desc: \"new lints that are still under development\",\n    default_level: LintLevel::Allow,\n    feature_gate: None,\n    hidden: false,\n};\n\nconst PEDANTIC: LintGroup = LintGroup {\n    name: \"pedantic\",\n    desc: \"lints which are rather strict or have occasional false positives\",\n    default_level: LintLevel::Allow,\n    feature_gate: None,\n    hidden: false,\n};\n\nconst PERF: LintGroup = LintGroup {\n    name: \"perf\",\n    desc: \"code that can be written to run faster\",\n    default_level: LintLevel::Warn,\n    feature_gate: None,\n    hidden: false,\n};\n\nconst RESTRICTION: LintGroup = LintGroup {\n    name: \"restriction\",\n    desc: \"lints which prevent the use of Cargo features\",\n    default_level: LintLevel::Allow,\n    feature_gate: None,\n    hidden: false,\n};\n\nconst STYLE: LintGroup = LintGroup {\n    name: \"style\",\n    desc: \"code that should be written in a more idiomatic way\",\n    default_level: LintLevel::Warn,\n    feature_gate: None,\n    hidden: false,\n};\n\nconst SUSPICIOUS: LintGroup = LintGroup {\n    name: \"suspicious\",\n    desc: \"code that is most likely wrong or useless\",\n    default_level: LintLevel::Warn,\n    feature_gate: None,\n    hidden: false,\n};\n\n/// This lint group is only to be used for testing purposes\nconst TEST_DUMMY_UNSTABLE: LintGroup = LintGroup {\n    name: \"test_dummy_unstable\",\n    desc: \"test_dummy_unstable is meant to only be used in tests\",\n    default_level: LintLevel::Allow,\n    feature_gate: Some(Feature::test_dummy_unstable()),\n    hidden: true,\n};\n\n#[derive(Clone, Debug)]\npub struct Lint {\n    pub name: &'static str,\n    pub desc: &'static str,\n    pub primary_group: &'static LintGroup,\n    /// The minimum supported Rust version for applying this lint\n    ///\n    /// Note: If the lint is on by default and did not qualify as a hard-warning before the\n    /// linting system, then at earliest an MSRV of 1.78 is required as `[lints.cargo]` was a hard\n    /// error before then.\n    pub msrv: Option<RustVersion>,\n    pub feature_gate: Option<&'static Feature>,\n    /// This is a markdown formatted string that will be used when generating\n    /// the lint documentation. If docs is `None`, the lint will not be\n    /// documented.\n    pub docs: Option<&'static str>,\n}\n\nimpl Lint {\n    pub fn level(\n        &self,\n        pkg_lints: &TomlToolLints,\n        pkg_rust_version: Option<&RustVersion>,\n        unstable_features: &Features,\n    ) -> (LintLevel, LintLevelReason) {\n        // We should return `Allow` if a lint is behind a feature, but it is\n        // not enabled, that way the lint does not run.\n        if self\n            .feature_gate\n            .is_some_and(|f| !unstable_features.is_enabled(f))\n        {\n            return (LintLevel::Allow, LintLevelReason::Default);\n        }\n\n        if let (Some(msrv), Some(pkg_rust_version)) = (&self.msrv, pkg_rust_version) {\n            let pkg_rust_version = pkg_rust_version.to_partial();\n            if !msrv.is_compatible_with(&pkg_rust_version) {\n                return (LintLevel::Allow, LintLevelReason::Default);\n            }\n        }\n\n        let lint_level_priority =\n            level_priority(self.name, self.primary_group.default_level, pkg_lints);\n\n        let group_level_priority = level_priority(\n            self.primary_group.name,\n            self.primary_group.default_level,\n            pkg_lints,\n        );\n\n        let (_, (l, r, _)) = max_by_key(\n            (self.name, lint_level_priority),\n            (self.primary_group.name, group_level_priority),\n            |(n, (l, _, p))| (l == &LintLevel::Forbid, *p, Reverse(*n)),\n        );\n        (l, r)\n    }\n\n    fn emitted_source(&self, lint_level: LintLevel, reason: LintLevelReason) -> String {\n        format!(\"`cargo::{}` is set to `{lint_level}` {reason}\", self.name,)\n    }\n}\n\n#[derive(Copy, Clone, Debug, PartialEq)]\npub enum LintLevel {\n    Allow,\n    Warn,\n    Deny,\n    Forbid,\n}\n\nimpl Display for LintLevel {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            LintLevel::Allow => write!(f, \"allow\"),\n            LintLevel::Warn => write!(f, \"warn\"),\n            LintLevel::Deny => write!(f, \"deny\"),\n            LintLevel::Forbid => write!(f, \"forbid\"),\n        }\n    }\n}\n\nimpl LintLevel {\n    pub fn is_error(&self) -> bool {\n        self == &LintLevel::Forbid || self == &LintLevel::Deny\n    }\n\n    pub fn to_diagnostic_level(self) -> Level<'static> {\n        match self {\n            LintLevel::Allow => unreachable!(\"allow does not map to a diagnostic level\"),\n            LintLevel::Warn => Level::WARNING,\n            LintLevel::Deny => Level::ERROR,\n            LintLevel::Forbid => Level::ERROR,\n        }\n    }\n\n    fn force(self) -> bool {\n        match self {\n            Self::Allow => false,\n            Self::Warn => true,\n            Self::Deny => true,\n            Self::Forbid => true,\n        }\n    }\n}\n\nimpl From<TomlLintLevel> for LintLevel {\n    fn from(toml_lint_level: TomlLintLevel) -> LintLevel {\n        match toml_lint_level {\n            TomlLintLevel::Allow => LintLevel::Allow,\n            TomlLintLevel::Warn => LintLevel::Warn,\n            TomlLintLevel::Deny => LintLevel::Deny,\n            TomlLintLevel::Forbid => LintLevel::Forbid,\n        }\n    }\n}\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq)]\npub enum LintLevelReason {\n    Default,\n    Package,\n}\n\nimpl Display for LintLevelReason {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            LintLevelReason::Default => write!(f, \"by default\"),\n            LintLevelReason::Package => write!(f, \"in `[lints]`\"),\n        }\n    }\n}\n\nimpl LintLevelReason {\n    fn is_user_specified(&self) -> bool {\n        match self {\n            LintLevelReason::Default => false,\n            LintLevelReason::Package => true,\n        }\n    }\n}\n\nfn level_priority(\n    name: &str,\n    default_level: LintLevel,\n    pkg_lints: &TomlToolLints,\n) -> (LintLevel, LintLevelReason, i8) {\n    if let Some(defined_level) = pkg_lints.get(name) {\n        (\n            defined_level.level().into(),\n            LintLevelReason::Package,\n            defined_level.priority(),\n        )\n    } else {\n        (default_level, LintLevelReason::Default, 0)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use itertools::Itertools;\n    use snapbox::ToDebug;\n    use std::collections::HashSet;\n\n    #[test]\n    fn ensure_lint_groups_do_not_default_to_forbid() {\n        let forbid_groups = super::LINT_GROUPS\n            .iter()\n            .filter(|g| matches!(g.default_level, super::LintLevel::Forbid))\n            .collect::<Vec<_>>();\n\n        assert!(\n            forbid_groups.is_empty(),\n            \"\\n`LintGroup`s should never default to `forbid`, but the following do:\\n\\\n            {}\\n\",\n            forbid_groups.iter().map(|g| g.name).join(\"\\n\")\n        );\n    }\n\n    #[test]\n    fn ensure_sorted_lints() {\n        // This will be printed out if the fields are not sorted.\n        let location = std::panic::Location::caller();\n        println!(\"\\nTo fix this test, sort `LINTS` in {}\\n\", location.file(),);\n\n        let actual = super::LINTS\n            .iter()\n            .map(|l| l.name.to_uppercase())\n            .collect::<Vec<_>>();\n\n        let mut expected = actual.clone();\n        expected.sort();\n        snapbox::assert_data_eq!(actual.to_debug(), expected.to_debug());\n    }\n\n    #[test]\n    fn ensure_sorted_lint_groups() {\n        // This will be printed out if the fields are not sorted.\n        let location = std::panic::Location::caller();\n        println!(\n            \"\\nTo fix this test, sort `LINT_GROUPS` in {}\\n\",\n            location.file(),\n        );\n        let actual = super::LINT_GROUPS\n            .iter()\n            .map(|l| l.name.to_uppercase())\n            .collect::<Vec<_>>();\n\n        let mut expected = actual.clone();\n        expected.sort();\n        snapbox::assert_data_eq!(actual.to_debug(), expected.to_debug());\n    }\n\n    #[test]\n    fn ensure_updated_lints() {\n        let dir = snapbox::utils::current_dir!().join(\"rules\");\n        let mut expected = HashSet::new();\n        for entry in std::fs::read_dir(&dir).unwrap() {\n            let entry = entry.unwrap();\n            let path = entry.path();\n            if path.ends_with(\"mod.rs\") {\n                continue;\n            }\n            let lint_name = path.file_stem().unwrap().to_string_lossy();\n            assert!(expected.insert(lint_name.into()), \"duplicate lint found\");\n        }\n\n        let actual = super::LINTS\n            .iter()\n            .map(|l| l.name.to_string())\n            .collect::<HashSet<_>>();\n        let diff = expected.difference(&actual).sorted().collect::<Vec<_>>();\n\n        let mut need_added = String::new();\n        for name in &diff {\n            need_added.push_str(&format!(\"{name}\\n\"));\n        }\n        assert!(\n            diff.is_empty(),\n            \"\\n`LINTS` did not contain all `Lint`s found in {}\\n\\\n            Please add the following to `LINTS`:\\n\\\n            {need_added}\",\n            dir.display(),\n        );\n    }\n\n    #[test]\n    fn ensure_updated_lint_groups() {\n        let path = snapbox::utils::current_rs!();\n        let expected = std::fs::read_to_string(&path).unwrap();\n        let expected = expected\n            .lines()\n            .filter_map(|l| {\n                if l.ends_with(\": LintGroup = LintGroup {\") {\n                    Some(\n                        l.chars()\n                            .skip(6)\n                            .take_while(|c| *c != ':')\n                            .collect::<String>(),\n                    )\n                } else {\n                    None\n                }\n            })\n            .collect::<HashSet<_>>();\n        let actual = super::LINT_GROUPS\n            .iter()\n            .map(|l| l.name.to_uppercase())\n            .collect::<HashSet<_>>();\n        let diff = expected.difference(&actual).sorted().collect::<Vec<_>>();\n\n        let mut need_added = String::new();\n        for name in &diff {\n            need_added.push_str(&format!(\"{}\\n\", name));\n        }\n        assert!(\n            diff.is_empty(),\n            \"\\n`LINT_GROUPS` did not contain all `LintGroup`s found in {}\\n\\\n            Please add the following to `LINT_GROUPS`:\\n\\\n            {}\",\n            path.display(),\n            need_added\n        );\n    }\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/blanket_hint_mostly_unused.rs",
    "content": "use std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Patch;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::ProfilePackageSpec;\nuse cargo_util_schemas::manifest::TomlToolLints;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::MaybePackage;\nuse crate::core::Workspace;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::SUSPICIOUS;\nuse crate::lints::get_key_value_span;\nuse crate::lints::rel_cwd_manifest_path;\n\npub static LINT: &Lint = &Lint {\n    name: \"blanket_hint_mostly_unused\",\n    desc: \"blanket_hint_mostly_unused lint\",\n    primary_group: &SUSPICIOUS,\n    msrv: Some(super::CARGO_LINTS_MSRV),\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\nChecks if `hint-mostly-unused` being applied to all dependencies.\n\n### Why it is bad\n`hint-mostly-unused` indicates that most of a crate's API surface will go\nunused by anything depending on it; this hint can speed up the build by\nattempting to minimize compilation time for items that aren't used at all.\nMisapplication to crates that don't fit that criteria will slow down the build\nrather than speeding it up. It should be selectively applied to dependencies\nthat meet these criteria. Applying it globally is always a misapplication and\nwill likely slow down the build.\n\n### Example\n```toml\n[profile.dev.package.\"*\"]\nhint-mostly-unused = true\n```\n\nShould instead be:\n```toml\n[profile.dev.package.huge-mostly-unused-dependency]\nhint-mostly-unused = true\n```\n\"#,\n    ),\n};\n\npub fn blanket_hint_mostly_unused(\n    ws: &Workspace<'_>,\n    maybe_pkg: &MaybePackage,\n    path: &Path,\n    pkg_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        pkg_lints,\n        ws.lowest_rust_version(),\n        maybe_pkg.unstable_features(),\n    );\n\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let level = lint_level.to_diagnostic_level();\n    let manifest_path = rel_cwd_manifest_path(path, gctx);\n    let mut paths = Vec::new();\n\n    if let Some(profiles) = maybe_pkg.profiles() {\n        for (profile_name, top_level_profile) in &profiles.0 {\n            if let Some(true) = top_level_profile.hint_mostly_unused {\n                paths.push((\n                    vec![\"profile\", profile_name.as_str(), \"hint-mostly-unused\"],\n                    true,\n                ));\n            }\n\n            if let Some(build_override) = &top_level_profile.build_override\n                && let Some(true) = build_override.hint_mostly_unused\n            {\n                paths.push((\n                    vec![\n                        \"profile\",\n                        profile_name.as_str(),\n                        \"build-override\",\n                        \"hint-mostly-unused\",\n                    ],\n                    false,\n                ));\n            }\n\n            if let Some(packages) = &top_level_profile.package\n                && let Some(profile) = packages.get(&ProfilePackageSpec::All)\n                && let Some(true) = profile.hint_mostly_unused\n            {\n                paths.push((\n                    vec![\n                        \"profile\",\n                        profile_name.as_str(),\n                        \"package\",\n                        \"*\",\n                        \"hint-mostly-unused\",\n                    ],\n                    false,\n                ));\n            }\n        }\n    }\n\n    for (i, (path, show_per_pkg_suggestion)) in paths.iter().enumerate() {\n        if lint_level.is_error() {\n            *error_count += 1;\n        }\n        let title = \"`hint-mostly-unused` is being blanket applied to all dependencies\";\n        let help_txt =\n            \"scope `hint-mostly-unused` to specific packages with a lot of unused object code\";\n\n        let mut report = Vec::new();\n        let mut primary_group = Group::with_title(level.clone().primary_title(title));\n\n        if let Some(contents) = maybe_pkg.contents()\n            && let Some(document) = maybe_pkg.document()\n            && let Some(span) = get_key_value_span(document, &path)\n            && let Some(table_span) = get_key_value_span(document, &path[..path.len() - 1])\n        {\n            primary_group = primary_group.element(\n                Snippet::source(contents)\n                    .path(&manifest_path)\n                    .annotation(\n                        AnnotationKind::Primary.span(table_span.key.start..table_span.key.end),\n                    )\n                    .annotation(AnnotationKind::Context.span(span.key.start..span.value.end)),\n            );\n        } else {\n            primary_group = primary_group.element(Origin::path(&manifest_path))\n        }\n\n        if *show_per_pkg_suggestion {\n            let help_group = Group::with_title(Level::HELP.secondary_title(help_txt));\n\n            report.push(\n                if let Some(contents) = maybe_pkg.contents()\n                    && let Some(document) = maybe_pkg.document()\n                    && let Some(table_span) = get_key_value_span(document, &path[..path.len() - 1])\n                {\n                    help_group.element(Snippet::source(contents).path(&manifest_path).patch(\n                        Patch::new(\n                            table_span.key.end..table_span.key.end,\n                            \".package.<pkg_name>\",\n                        ),\n                    ))\n                } else {\n                    help_group.element(Origin::path(&manifest_path))\n                },\n            );\n        } else {\n            primary_group = primary_group.element(Level::HELP.message(help_txt));\n        }\n\n        if i == 0 {\n            primary_group =\n                primary_group.element(Level::NOTE.message(LINT.emitted_source(lint_level, reason)));\n        }\n\n        // The primary group should always be first\n        report.insert(0, primary_group);\n\n        gctx.shell().print_report(&report, lint_level.force())?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/im_a_teapot.rs",
    "content": "use std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::TomlToolLints;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Feature;\nuse crate::core::Package;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::TEST_DUMMY_UNSTABLE;\nuse crate::lints::get_key_value_span;\nuse crate::lints::rel_cwd_manifest_path;\n\n/// This lint is only to be used for testing purposes\npub static LINT: &Lint = &Lint {\n    name: \"im_a_teapot\",\n    desc: \"`im_a_teapot` is specified\",\n    primary_group: &TEST_DUMMY_UNSTABLE,\n    msrv: None,\n    feature_gate: Some(Feature::test_dummy_unstable()),\n    docs: None,\n};\n\npub fn check_im_a_teapot(\n    pkg: &Package,\n    path: &Path,\n    pkg_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let manifest = pkg.manifest();\n    let (lint_level, reason) =\n        LINT.level(pkg_lints, pkg.rust_version(), manifest.unstable_features());\n\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    if manifest\n        .normalized_toml()\n        .package()\n        .is_some_and(|p| p.im_a_teapot.is_some())\n    {\n        if lint_level.is_error() {\n            *error_count += 1;\n        }\n        let level = lint_level.to_diagnostic_level();\n        let manifest_path = rel_cwd_manifest_path(path, gctx);\n        let emitted_reason = LINT.emitted_source(lint_level, reason);\n\n        let mut desc = Group::with_title(level.primary_title(LINT.desc));\n\n        if let Some(document) = manifest.document()\n            && let Some(contents) = manifest.contents()\n        {\n            let span = get_key_value_span(document, &[\"package\", \"im-a-teapot\"]).unwrap();\n\n            desc = desc.element(\n                Snippet::source(contents)\n                    .path(&manifest_path)\n                    .annotation(AnnotationKind::Primary.span(span.key.start..span.value.end)),\n            );\n        } else {\n            desc = desc.element(Origin::path(&manifest_path));\n        }\n\n        let report = &[desc.element(Level::NOTE.message(&emitted_reason))];\n\n        gctx.shell().print_report(report, lint_level.force())?;\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/implicit_minimum_version_req.rs",
    "content": "use std::collections::HashMap;\nuse std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Patch;\nuse annotate_snippets::Snippet;\nuse cargo_platform::Platform;\nuse cargo_util_schemas::manifest::TomlDependency;\nuse cargo_util_schemas::manifest::TomlToolLints;\nuse toml::de::DeValue;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Manifest;\nuse crate::core::MaybePackage;\nuse crate::core::Package;\nuse crate::core::Workspace;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::LintLevelReason;\nuse crate::lints::PEDANTIC;\nuse crate::lints::get_key_value;\nuse crate::lints::rel_cwd_manifest_path;\nuse crate::util::OptVersionReq;\n\npub static LINT: &Lint = &Lint {\n    name: \"implicit_minimum_version_req\",\n    desc: \"dependency version requirement without an explicit minimum version\",\n    primary_group: &PEDANTIC,\n    msrv: None,\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\n\nChecks for dependency version requirements\nthat do not explicitly specify a full `major.minor.patch` version requirement,\nsuch as `serde = \"1\"` or `serde = \"1.0\"`.\n\nThis lint currently only applies to caret requirements\n(the [default requirements](specifying-dependencies.md#default-requirements)).\n\n### Why it is bad\n\nVersion requirements without an explicit full version\ncan be misleading about the actual minimum supported version.\nFor example,\n`serde = \"1\"` has an implicit minimum bound of `1.0.0`.\nIf your code actually requires features from `1.0.219`,\nthe implicit minimum bound of `1.0.0` gives a false impression about compatibility.\n\nSpecifying the full version helps with:\n\n- Accurate minimum version documentation\n- Better compatibility with `-Z minimal-versions`\n- Clearer dependency constraints for consumers\n\n### Drawbacks\n\nEven with a fully specified version,\nthe minimum bound might still be incorrect if untested.\nThis lint helps make the minimum version requirement explicit\nbut doesn't guarantee correctness.\n\n### Example\n\n```toml\n[dependencies]\nserde = \"1\"\n```\n\nShould be written as a full specific version:\n\n```toml\n[dependencies]\nserde = \"1.0.219\"\n```\n\"#,\n    ),\n};\n\npub fn implicit_minimum_version_req_pkg(\n    pkg: &Package,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        cargo_lints,\n        pkg.rust_version(),\n        pkg.manifest().unstable_features(),\n    );\n\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n\n    let manifest = pkg.manifest();\n\n    let document = manifest.document();\n    let contents = manifest.contents();\n    let target_key_for_platform = target_key_for_platform(&manifest);\n\n    let mut emit_source = true;\n    for dep in manifest.dependencies().iter() {\n        let version_req = dep.version_req();\n        let Some(suggested_req) = get_suggested_version_req(&version_req) else {\n            continue;\n        };\n\n        let name_in_toml = dep.name_in_toml().as_str();\n        let key_path =\n            if let Some(cfg) = dep.platform().and_then(|p| target_key_for_platform.get(p)) {\n                &[\"target\", &cfg, dep.kind().kind_table(), name_in_toml][..]\n            } else {\n                &[dep.kind().kind_table(), name_in_toml][..]\n            };\n\n        let Some(report) = report(\n            lint_level,\n            reason,\n            contents,\n            document,\n            key_path,\n            &manifest_path,\n            &suggested_req,\n            emit_source,\n        ) else {\n            continue;\n        };\n\n        if emit_source {\n            emit_source = false;\n        }\n\n        if lint_level.is_error() {\n            *error_count += 1;\n        }\n        gctx.shell().print_report(&report, lint_level.force())?;\n    }\n\n    Ok(())\n}\n\npub fn implicit_minimum_version_req_ws(\n    ws: &Workspace<'_>,\n    maybe_pkg: &MaybePackage,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        cargo_lints,\n        ws.lowest_rust_version(),\n        maybe_pkg.unstable_features(),\n    );\n\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n\n    let document = maybe_pkg.document();\n    let contents = maybe_pkg.contents();\n    let toml = match maybe_pkg {\n        MaybePackage::Package(p) => p.manifest().normalized_toml(),\n        MaybePackage::Virtual(vm) => vm.normalized_toml(),\n    };\n    let dep_iter = toml\n        .workspace\n        .as_ref()\n        .and_then(|ws| ws.dependencies.as_ref())\n        .into_iter()\n        .flat_map(|deps| deps.iter())\n        .map(|(name, dep)| {\n            let name = name.as_str();\n            let ver = match dep {\n                TomlDependency::Simple(ver) => ver,\n                TomlDependency::Detailed(detailed) => {\n                    let Some(ver) = detailed.version.as_ref() else {\n                        return (name, OptVersionReq::Any);\n                    };\n                    ver\n                }\n            };\n            let req = semver::VersionReq::parse(ver)\n                .map(Into::into)\n                .unwrap_or(OptVersionReq::Any);\n            (name, req)\n        });\n\n    let mut emit_source = true;\n    for (name_in_toml, version_req) in dep_iter {\n        let Some(suggested_req) = get_suggested_version_req(&version_req) else {\n            continue;\n        };\n\n        let key_path = [\"workspace\", \"dependencies\", name_in_toml];\n\n        let Some(report) = report(\n            lint_level,\n            reason,\n            contents,\n            document,\n            &key_path,\n            &manifest_path,\n            &suggested_req,\n            emit_source,\n        ) else {\n            continue;\n        };\n\n        if emit_source {\n            emit_source = false;\n        }\n\n        if lint_level.is_error() {\n            *error_count += 1;\n        }\n        gctx.shell().print_report(&report, lint_level.force())?;\n    }\n\n    Ok(())\n}\n\npub fn span_of_version_req<'doc>(\n    document: &'doc toml::Spanned<toml::de::DeTable<'static>>,\n    path: &[&str],\n) -> Option<std::ops::Range<usize>> {\n    let (_key, value) = get_key_value(document, path)?;\n\n    match value.as_ref() {\n        DeValue::String(_) => Some(value.span()),\n        DeValue::Table(map) if map.get(\"workspace\").is_some() => {\n            // We only lint non-workspace-inherited dependencies\n            None\n        }\n        DeValue::Table(map) => {\n            let Some(v) = map.get(\"version\") else {\n                panic!(\"version must be specified or workspace-inherited\");\n            };\n            Some(v.span())\n        }\n        _ => unreachable!(\"dependency must be string or table\"),\n    }\n}\n\nfn report<'a>(\n    lint_level: LintLevel,\n    reason: LintLevelReason,\n    contents: Option<&'a str>,\n    document: Option<&toml::Spanned<toml::de::DeTable<'static>>>,\n    key_path: &[&str],\n    manifest_path: &str,\n    suggested_req: &str,\n    emit_source: bool,\n) -> Option<[Group<'a>; 2]> {\n    let level = lint_level.to_diagnostic_level();\n    let emitted_source = LINT.emitted_source(lint_level, reason);\n    let replacement = format!(r#\"\"{suggested_req}\"\"#);\n    let label = \"missing full version components\";\n    let secondary_title = \"consider specifying full `major.minor.patch` version components\";\n\n    let mut desc = Group::with_title(level.primary_title(LINT.desc));\n    let mut help = Group::with_title(Level::HELP.secondary_title(secondary_title));\n\n    if let Some(document) = document\n        && let Some(contents) = contents\n    {\n        let Some(span) = span_of_version_req(document, key_path) else {\n            return None;\n        };\n        desc = desc.element(\n            Snippet::source(contents)\n                .path(manifest_path.to_owned())\n                .annotation(AnnotationKind::Primary.span(span.clone()).label(label)),\n        );\n\n        help = help.element(Snippet::source(contents).patch(Patch::new(span.clone(), replacement)));\n    } else {\n        desc = desc.element(Origin::path(manifest_path.to_owned()));\n    }\n\n    if emit_source {\n        desc = desc.element(Level::NOTE.message(emitted_source));\n    }\n\n    Some([desc, help])\n}\n\nfn get_suggested_version_req(req: &OptVersionReq) -> Option<String> {\n    use semver::Op;\n    let OptVersionReq::Req(req) = req else {\n        return None;\n    };\n    let mut has_suggestions = false;\n    let mut comparators = Vec::new();\n\n    for mut cmp in req.comparators.iter().cloned() {\n        match cmp.op {\n            Op::Caret | Op::GreaterEq => {\n                // Only focus on comparator that has only `major` or `major.minor`\n                if cmp.minor.is_some() && cmp.patch.is_some() {\n                    comparators.push(cmp);\n                    continue;\n                } else {\n                    has_suggestions = true;\n                    cmp.minor.get_or_insert(0);\n                    cmp.patch.get_or_insert(0);\n                    comparators.push(cmp);\n                }\n            }\n            Op::Exact | Op::Tilde | Op::Wildcard | Op::Greater | Op::Less | Op::LessEq => {\n                comparators.push(cmp);\n                continue;\n            }\n            _ => panic!(\"unknown comparator in `{cmp}`\"),\n        }\n    }\n\n    if !has_suggestions {\n        return None;\n    }\n\n    // This is a lossy suggestion that\n    //\n    // * extra spaces are removed\n    // * caret operator `^` is stripped\n    let mut suggestion = String::new();\n\n    for cmp in &comparators {\n        if !suggestion.is_empty() {\n            suggestion.push_str(\", \");\n        }\n        let s = cmp.to_string();\n\n        if cmp.op == Op::Caret {\n            suggestion.push_str(s.strip_prefix('^').unwrap_or(&s));\n        } else {\n            suggestion.push_str(&s);\n        }\n    }\n\n    Some(suggestion)\n}\n\n/// A map from parsed `Platform` to their original TOML key strings.\n/// This is needed for constructing TOML key paths in diagnostics.\n///\n/// This is only relevant for package dependencies.\nfn target_key_for_platform(manifest: &Manifest) -> HashMap<Platform, String> {\n    manifest\n        .normalized_toml()\n        .target\n        .as_ref()\n        .map(|map| {\n            map.keys()\n                .map(|k| (k.parse().expect(\"already parsed\"), k.clone()))\n                .collect()\n        })\n        .unwrap_or_default()\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/missing_lints_inheritance.rs",
    "content": "use std::path::Path;\n\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Patch;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::TomlToolLints;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Package;\nuse crate::core::Workspace;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::SUSPICIOUS;\nuse crate::lints::rel_cwd_manifest_path;\n\npub static LINT: &Lint = &Lint {\n    name: \"missing_lints_inheritance\",\n    desc: \"missing `[lints]` to inherit `[workspace.lints]`\",\n    primary_group: &SUSPICIOUS,\n    msrv: Some(super::CARGO_LINTS_MSRV),\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\n\nChecks for packages without a `lints` table while `workspace.lints` is present.\n\n### Why it is bad\n\nMany people mistakenly think that `workspace.lints` is implicitly inherited when it is not.\n\n### Drawbacks\n\n### Example\n\n```toml\n[workspace.lints.cargo]\n```\n\nShould be written as:\n\n```toml\n[workspace.lints.cargo]\n\n[lints]\nworkspace = true\n```\n\"#,\n    ),\n};\n\npub fn missing_lints_inheritance(\n    ws: &Workspace<'_>,\n    pkg: &Package,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        cargo_lints,\n        pkg.rust_version(),\n        pkg.manifest().unstable_features(),\n    );\n\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let root = ws.root_maybe();\n    // `normalized_toml` normally isn't guaranteed to include inheritance information except\n    // `workspace.lints` is used outside of inheritance for workspace-level lints.\n    let ws_lints = root\n        .normalized_toml()\n        .workspace\n        .as_ref()\n        .map(|ws| ws.lints.is_some())\n        .unwrap_or(false);\n    if !ws_lints {\n        return Ok(());\n    }\n    if pkg.manifest().normalized_toml().lints.is_some() {\n        return Ok(());\n    }\n\n    let manifest = pkg.manifest();\n    let contents = manifest.contents();\n    let level = lint_level.to_diagnostic_level();\n    let emitted_source = LINT.emitted_source(lint_level, reason);\n    let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n\n    let mut primary = Group::with_title(level.primary_title(LINT.desc));\n    primary = primary.element(Origin::path(&manifest_path));\n    primary = primary.element(Level::NOTE.message(emitted_source));\n    let mut report = vec![primary];\n    if let Some(contents) = contents {\n        let span = contents.len()..contents.len();\n        let mut help =\n            Group::with_title(Level::HELP.secondary_title(\"to inherit `workspace.lints, add:\"));\n        help = help.element(\n            Snippet::source(contents)\n                .path(&manifest_path)\n                .patch(Patch::new(span.clone(), \"\\n[lints]\\nworkspace = true\")),\n        );\n        report.push(help);\n        let mut help = Group::with_title(\n            Level::HELP.secondary_title(\"to clarify your intent to not inherit, add:\"),\n        );\n        help = help.element(\n            Snippet::source(contents)\n                .path(&manifest_path)\n                .patch(Patch::new(span, \"\\n[lints]\")),\n        );\n        report.push(help);\n    }\n\n    if lint_level.is_error() {\n        *error_count += 1;\n    }\n    gctx.shell().print_report(&report, lint_level.force())?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/mod.rs",
    "content": "mod blanket_hint_mostly_unused;\nmod im_a_teapot;\nmod implicit_minimum_version_req;\nmod missing_lints_inheritance;\nmod non_kebab_case_bins;\nmod non_kebab_case_features;\nmod non_kebab_case_packages;\nmod non_snake_case_features;\nmod non_snake_case_packages;\nmod redundant_homepage;\nmod redundant_readme;\nmod unknown_lints;\nmod unused_workspace_dependencies;\nmod unused_workspace_package_fields;\n\npub use blanket_hint_mostly_unused::blanket_hint_mostly_unused;\npub use im_a_teapot::check_im_a_teapot;\npub use implicit_minimum_version_req::implicit_minimum_version_req_pkg;\npub use implicit_minimum_version_req::implicit_minimum_version_req_ws;\npub use missing_lints_inheritance::missing_lints_inheritance;\npub use non_kebab_case_bins::non_kebab_case_bins;\npub use non_kebab_case_features::non_kebab_case_features;\npub use non_kebab_case_packages::non_kebab_case_packages;\npub use non_snake_case_features::non_snake_case_features;\npub use non_snake_case_packages::non_snake_case_packages;\npub use redundant_homepage::redundant_homepage;\npub use redundant_readme::redundant_readme;\npub use unknown_lints::output_unknown_lints;\npub use unused_workspace_dependencies::unused_workspace_dependencies;\npub use unused_workspace_package_fields::unused_workspace_package_fields;\n\npub static LINTS: &[&crate::lints::Lint] = &[\n    blanket_hint_mostly_unused::LINT,\n    implicit_minimum_version_req::LINT,\n    im_a_teapot::LINT,\n    missing_lints_inheritance::LINT,\n    non_kebab_case_bins::LINT,\n    non_kebab_case_features::LINT,\n    non_kebab_case_packages::LINT,\n    non_snake_case_features::LINT,\n    non_snake_case_packages::LINT,\n    redundant_homepage::LINT,\n    redundant_readme::LINT,\n    unknown_lints::LINT,\n    unused_workspace_dependencies::LINT,\n    unused_workspace_package_fields::LINT,\n];\n\n/// Version required for specifying `[lints.cargo]`\n///\n/// Before this, it was an error.  No on-by-default lint should fire before this time without\n/// another way of disabling it.\nstatic CARGO_LINTS_MSRV: cargo_util_schemas::manifest::RustVersion =\n    cargo_util_schemas::manifest::RustVersion::new(1, 79, 0);\n"
  },
  {
    "path": "src/cargo/lints/rules/non_kebab_case_bins.rs",
    "content": "use std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Patch;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::TomlToolLints;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Package;\nuse crate::core::Workspace;\nuse crate::lints::AsIndex;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::LintLevelReason;\nuse crate::lints::STYLE;\nuse crate::lints::get_key_value_span;\nuse crate::lints::rel_cwd_manifest_path;\n\npub static LINT: &Lint = &Lint {\n    name: \"non_kebab_case_bins\",\n    desc: \"binaries should have a kebab-case name\",\n    primary_group: &STYLE,\n    msrv: Some(super::CARGO_LINTS_MSRV),\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\n\nDetect binary names, explicit and implicit, that are not kebab-case\n\n### Why it is bad\n\nKebab-case binary names is a common convention among command line tools.\n\n### Drawbacks\n\nIt would be disruptive to existing users to change the binary name.\n\nA binary may need to conform to externally controlled conventions which can include a different naming convention.\n\nGUI applications may wish to choose a more user focused naming convention, like \"Title Case\" or \"Sentence case\".\n\n### Example\n\n```toml\n[[bin]]\nname = \"foo_bar\"\n```\n\nShould be written as:\n\n```toml\n[[bin]]\nname = \"foo-bar\"\n```\n\"#,\n    ),\n};\n\npub fn non_kebab_case_bins(\n    ws: &Workspace<'_>,\n    pkg: &Package,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        cargo_lints,\n        pkg.rust_version(),\n        pkg.manifest().unstable_features(),\n    );\n\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n\n    lint_package(\n        ws,\n        pkg,\n        &manifest_path,\n        lint_level,\n        reason,\n        error_count,\n        gctx,\n    )\n}\n\npub fn lint_package(\n    ws: &Workspace<'_>,\n    pkg: &Package,\n    manifest_path: &str,\n    lint_level: LintLevel,\n    reason: LintLevelReason,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let manifest = pkg.manifest();\n\n    for (i, bin) in manifest.normalized_toml().bin.iter().flatten().enumerate() {\n        let Some(original_name) = bin.name.as_deref() else {\n            continue;\n        };\n        let kebab_case = heck::ToKebabCase::to_kebab_case(original_name);\n        if kebab_case == original_name {\n            continue;\n        }\n\n        let document = manifest.document();\n        let contents = manifest.contents();\n        let level = lint_level.to_diagnostic_level();\n        let emitted_source = LINT.emitted_source(lint_level, reason);\n\n        let mut primary_source = ws.target_dir().as_path_unlocked().to_owned();\n        // Elide profile/platform as we don't have that context\n        primary_source.push(\"...\");\n        primary_source.push(\"\");\n        let mut primary_source = primary_source.display().to_string();\n        let primary_span_start = primary_source.len();\n        let primary_span_end = primary_span_start + original_name.len();\n        primary_source.push_str(original_name);\n        primary_source.push_str(std::env::consts::EXE_SUFFIX);\n        let mut primary_group =\n            level\n                .primary_title(LINT.desc)\n                .element(Snippet::source(&primary_source).annotation(\n                    AnnotationKind::Primary.span(primary_span_start..primary_span_end),\n                ));\n        if i == 0 {\n            primary_group = primary_group.element(Level::NOTE.message(emitted_source));\n        }\n        let mut report = vec![primary_group];\n\n        if let Some((i, _target)) = manifest\n            .original_toml()\n            .iter()\n            .flat_map(|m| m.bin.iter().flatten())\n            .enumerate()\n            .find(|(_i, t)| t.name.as_deref() == Some(original_name))\n        {\n            let mut help = Group::with_title(\n                Level::HELP\n                    .secondary_title(\"to change the binary name to kebab case, convert `bin.name`\"),\n            );\n            if let Some(document) = document\n                && let Some(contents) = contents\n                && let Some(span) = get_key_value_span(\n                    document,\n                    &[\"bin\".as_index(), i.as_index(), \"name\".as_index()],\n                )\n            {\n                help = help.element(\n                    Snippet::source(contents)\n                        .path(manifest_path)\n                        .patch(Patch::new(span.value, format!(\"\\\"{kebab_case}\\\"\"))),\n                );\n            } else {\n                help = help.element(Origin::path(manifest_path));\n            }\n            report.push(help);\n        } else if is_default_main(bin.path.as_ref())\n            && manifest\n                .original_toml()\n                .iter()\n                .flat_map(|m| m.bin.iter().flatten())\n                .all(|t| t.path != bin.path)\n            && manifest\n                .original_toml()\n                .and_then(|t| t.package.as_ref())\n                .map(|p| p.name.is_some())\n                .unwrap_or(false)\n        {\n            // Showing package in case this is done before first publish to fix the problem at the\n            // root\n            let help_package_name =\n                \"to change the binary name to kebab case, convert `package.name`\";\n            // Including `[[bin]]` in case it is already published.\n            // Preferring it over moving the file to avoid having to get into moving the\n            // files it `mod`s\n            let help_bin_table = \"to change the binary name to kebab case, specify `bin.name`\";\n            if let Some(document) = document\n                && let Some(contents) = contents\n                && let Some(span) = get_key_value_span(document, &[\"package\", \"name\"])\n            {\n                report.push(\n                    Level::HELP.secondary_title(help_package_name).element(\n                        Snippet::source(contents)\n                            .path(manifest_path)\n                            .patch(Patch::new(span.value, format!(\"\\\"{kebab_case}\\\"\"))),\n                    ),\n                );\n                report.push(\n                    Level::HELP.secondary_title(help_bin_table).element(\n                        Snippet::source(contents)\n                            .path(manifest_path)\n                            .patch(Patch::new(\n                                contents.len()..contents.len(),\n                                format!(\n                                    r#\"\n[[bin]]\nname = \"{kebab_case}\"\npath = \"src/main.rs\"\"#\n                                ),\n                            )),\n                    ),\n                );\n            } else {\n                report.push(\n                    Level::HELP\n                        .secondary_title(help_package_name)\n                        .element(Origin::path(manifest_path)),\n                );\n                report.push(\n                    Level::HELP\n                        .secondary_title(help_bin_table)\n                        .element(Origin::path(manifest_path)),\n                );\n            }\n        } else {\n            let path = bin\n                .path\n                .as_ref()\n                .expect(\"normalized have a path\")\n                .0\n                .as_path();\n            let display_path = path.as_os_str().to_string_lossy();\n            let end = display_path.len() - if display_path.ends_with(\".rs\") { 3 } else { 0 };\n            let start = path\n                .parent()\n                .map(|p| {\n                    let p = p.as_os_str().to_string_lossy();\n                    // Account for trailing slash that was removed\n                    p.len() + if p.is_empty() { 0 } else { 1 }\n                })\n                .unwrap_or(0);\n            let help = Level::HELP\n                .secondary_title(\"to change the binary name to kebab case, convert the file stem\")\n                .element(Snippet::source(display_path).patch(Patch::new(start..end, kebab_case)));\n            report.push(help);\n        }\n\n        if lint_level.is_error() {\n            *error_count += 1;\n        }\n        gctx.shell().print_report(&report, lint_level.force())?;\n    }\n\n    Ok(())\n}\n\nfn is_default_main(path: Option<&cargo_util_schemas::manifest::PathValue>) -> bool {\n    let Some(path) = path else {\n        return false;\n    };\n    path.0 == std::path::Path::new(\"src/main.rs\")\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/non_kebab_case_features.rs",
    "content": "use std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Patch;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::TomlToolLints;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Package;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::LintLevelReason;\nuse crate::lints::RESTRICTION;\nuse crate::lints::get_key_value_span;\nuse crate::lints::rel_cwd_manifest_path;\n\npub static LINT: &Lint = &Lint {\n    name: \"non_kebab_case_features\",\n    desc: \"features should have a kebab-case name\",\n    primary_group: &RESTRICTION,\n    msrv: None,\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\n\nDetect feature names that are not kebab-case.\n\n### Why it is bad\n\nHaving multiple naming styles within a workspace can be confusing.\n\n### Drawbacks\n\nUsers would expect that a feature tightly coupled to a dependency would match the dependency's name.\n\n### Example\n\n```toml\n[features]\nfoo_bar = []\n```\n\nShould be written as:\n\n```toml\n[features]\nfoo-bar = []\n```\n\"#,\n    ),\n};\n\npub fn non_kebab_case_features(\n    pkg: &Package,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        cargo_lints,\n        pkg.rust_version(),\n        pkg.manifest().unstable_features(),\n    );\n\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n\n    lint_package(pkg, &manifest_path, lint_level, reason, error_count, gctx)\n}\n\npub fn lint_package(\n    pkg: &Package,\n    manifest_path: &str,\n    lint_level: LintLevel,\n    reason: LintLevelReason,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    for original_name in pkg.summary().features().keys() {\n        let original_name = &**original_name;\n        let kebab_case = heck::ToKebabCase::to_kebab_case(original_name);\n        if kebab_case == original_name {\n            continue;\n        }\n\n        let manifest = pkg.manifest();\n        let document = manifest.document();\n        let contents = manifest.contents();\n        let level = lint_level.to_diagnostic_level();\n        let emitted_source = LINT.emitted_source(lint_level, reason);\n\n        let mut primary = Group::with_title(level.primary_title(LINT.desc));\n        if let Some(document) = document\n            && let Some(contents) = contents\n            && let Some(span) = get_key_value_span(document, &[\"features\", original_name])\n        {\n            primary = primary.element(\n                Snippet::source(contents)\n                    .path(manifest_path)\n                    .annotation(AnnotationKind::Primary.span(span.key)),\n            );\n        } else if let Some(document) = document\n            && let Some(contents) = contents\n            && let Some(dep_span) = get_key_value_span(document, &[\"dependencies\", original_name])\n            && let Some(optional_span) =\n                get_key_value_span(document, &[\"dependencies\", original_name, \"optional\"])\n        {\n            primary = primary.element(\n                Snippet::source(contents)\n                    .path(manifest_path)\n                    .annotation(AnnotationKind::Primary.span(dep_span.key).label(\"source of feature name\"))\n                    .annotation(\n                        AnnotationKind::Context\n                            .span(optional_span.key.start..optional_span.value.end)\n                            .label(\"cause of feature\"),\n                    ),\n            ).element(Level::NOTE.message(\"see also <https://doc.rust-lang.org/cargo/reference/features.html#optional-dependencies>\"));\n        } else {\n            primary = primary.element(Origin::path(manifest_path));\n        }\n        primary = primary.element(Level::NOTE.message(emitted_source));\n        let mut report = vec![primary];\n        if let Some(document) = document\n            && let Some(contents) = contents\n            && let Some(span) = get_key_value_span(document, &[\"features\", original_name])\n        {\n            let mut help = Group::with_title(Level::HELP.secondary_title(\n                \"to change the feature name to kebab case, convert the `features` key\",\n            ));\n            help = help.element(\n                Snippet::source(contents)\n                    .path(manifest_path)\n                    .patch(Patch::new(span.key, kebab_case.as_str())),\n            );\n            report.push(help);\n        }\n\n        if lint_level.is_error() {\n            *error_count += 1;\n        }\n        gctx.shell().print_report(&report, lint_level.force())?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/non_kebab_case_packages.rs",
    "content": "use std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Patch;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::TomlToolLints;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Package;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::LintLevelReason;\nuse crate::lints::RESTRICTION;\nuse crate::lints::get_key_value_span;\nuse crate::lints::rel_cwd_manifest_path;\n\npub static LINT: &Lint = &Lint {\n    name: \"non_kebab_case_packages\",\n    desc: \"packages should have a kebab-case name\",\n    primary_group: &RESTRICTION,\n    msrv: None,\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\n\nDetect package names that are not kebab-case.\n\n### Why it is bad\n\nHaving multiple naming styles within a workspace can be confusing.\n\n### Drawbacks\n\nUsers have to mentally translate package names to namespaces in Rust.\n\n### Example\n\n```toml\n[package]\nname = \"foo_bar\"\n```\n\nShould be written as:\n\n```toml\n[package]\nname = \"foo-bar\"\n```\n\"#,\n    ),\n};\n\npub fn non_kebab_case_packages(\n    pkg: &Package,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        cargo_lints,\n        pkg.rust_version(),\n        pkg.manifest().unstable_features(),\n    );\n\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n\n    lint_package(pkg, &manifest_path, lint_level, reason, error_count, gctx)\n}\n\npub fn lint_package(\n    pkg: &Package,\n    manifest_path: &str,\n    lint_level: LintLevel,\n    reason: LintLevelReason,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let manifest = pkg.manifest();\n\n    let original_name = &*manifest.name();\n    let kebab_case = heck::ToKebabCase::to_kebab_case(original_name);\n    if kebab_case == original_name {\n        return Ok(());\n    }\n\n    let document = manifest.document();\n    let contents = manifest.contents();\n    let level = lint_level.to_diagnostic_level();\n    let emitted_source = LINT.emitted_source(lint_level, reason);\n\n    let mut primary = Group::with_title(level.primary_title(LINT.desc));\n    if let Some(document) = document\n        && let Some(contents) = contents\n        && let Some(span) = get_key_value_span(document, &[\"package\", \"name\"])\n    {\n        primary = primary.element(\n            Snippet::source(contents)\n                .path(manifest_path)\n                .annotation(AnnotationKind::Primary.span(span.value)),\n        );\n    } else {\n        primary = primary.element(Origin::path(manifest_path));\n    }\n    primary = primary.element(Level::NOTE.message(emitted_source));\n    let mut report = vec![primary];\n    if let Some(document) = document\n        && let Some(contents) = contents\n        && let Some(span) = get_key_value_span(document, &[\"package\", \"name\"])\n    {\n        let mut help =\n            Group::with_title(Level::HELP.secondary_title(\n                \"to change the package name to kebab case, convert `package.name`\",\n            ));\n        help = help.element(\n            Snippet::source(contents)\n                .path(manifest_path)\n                .patch(Patch::new(span.value, format!(\"\\\"{kebab_case}\\\"\"))),\n        );\n        report.push(help);\n    } else {\n        let path = pkg.manifest_path();\n        let display_path = path.as_os_str().to_string_lossy();\n        let end = display_path.len() - if display_path.ends_with(\".rs\") { 3 } else { 0 };\n        let start = path\n            .parent()\n            .map(|p| {\n                let p = p.as_os_str().to_string_lossy();\n                // Account for trailing slash that was removed\n                p.len() + if p.is_empty() { 0 } else { 1 }\n            })\n            .unwrap_or(0);\n        let help = Level::HELP\n            .secondary_title(\"to change the package name to kebab case, convert the file stem\")\n            .element(Snippet::source(display_path).patch(Patch::new(start..end, kebab_case)));\n        report.push(help);\n    }\n\n    if lint_level.is_error() {\n        *error_count += 1;\n    }\n    gctx.shell().print_report(&report, lint_level.force())?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/non_snake_case_features.rs",
    "content": "use std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Patch;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::TomlToolLints;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Package;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::LintLevelReason;\nuse crate::lints::RESTRICTION;\nuse crate::lints::get_key_value_span;\nuse crate::lints::rel_cwd_manifest_path;\n\npub static LINT: &Lint = &Lint {\n    name: \"non_snake_case_features\",\n    desc: \"features should have a snake-case name\",\n    primary_group: &RESTRICTION,\n    msrv: None,\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\n\nDetect feature names that are not snake-case.\n\n### Why it is bad\n\nHaving multiple naming styles within a workspace can be confusing.\n\n### Drawbacks\n\nUsers would expect that a feature tightly coupled to a dependency would match the dependency's name.\n\n### Example\n\n```toml\n[features]\nfoo-bar = []\n```\n\nShould be written as:\n\n```toml\n[features]\nfoo_bar = []\n```\n\"#,\n    ),\n};\n\npub fn non_snake_case_features(\n    pkg: &Package,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        cargo_lints,\n        pkg.rust_version(),\n        pkg.manifest().unstable_features(),\n    );\n\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n\n    lint_package(pkg, &manifest_path, lint_level, reason, error_count, gctx)\n}\n\npub fn lint_package(\n    pkg: &Package,\n    manifest_path: &str,\n    lint_level: LintLevel,\n    reason: LintLevelReason,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    for original_name in pkg.summary().features().keys() {\n        let original_name = &**original_name;\n        let snake_case = heck::ToSnakeCase::to_snake_case(original_name);\n        if snake_case == original_name {\n            continue;\n        }\n\n        let manifest = pkg.manifest();\n        let document = manifest.document();\n        let contents = manifest.contents();\n        let level = lint_level.to_diagnostic_level();\n        let emitted_source = LINT.emitted_source(lint_level, reason);\n\n        let mut primary = Group::with_title(level.primary_title(LINT.desc));\n        if let Some(document) = document\n            && let Some(contents) = contents\n            && let Some(span) = get_key_value_span(document, &[\"features\", original_name])\n        {\n            primary = primary.element(\n                Snippet::source(contents)\n                    .path(manifest_path)\n                    .annotation(AnnotationKind::Primary.span(span.key)),\n            );\n        } else if let Some(document) = document\n            && let Some(contents) = contents\n            && let Some(dep_span) = get_key_value_span(document, &[\"dependencies\", original_name])\n            && let Some(optional_span) =\n                get_key_value_span(document, &[\"dependencies\", original_name, \"optional\"])\n        {\n            primary = primary.element(\n                Snippet::source(contents)\n                    .path(manifest_path)\n                    .annotation(AnnotationKind::Primary.span(dep_span.key).label(\"source of feature name\"))\n                    .annotation(\n                        AnnotationKind::Context\n                            .span(optional_span.key.start..optional_span.value.end)\n                            .label(\"cause of feature\"),\n                    ),\n            ).element(Level::NOTE.message(\"see also <https://doc.rust-lang.org/cargo/reference/features.html#optional-dependencies>\"));\n        } else {\n            primary = primary.element(Origin::path(manifest_path));\n        }\n        primary = primary.element(Level::NOTE.message(emitted_source));\n        let mut report = vec![primary];\n        if let Some(document) = document\n            && let Some(contents) = contents\n            && let Some(span) = get_key_value_span(document, &[\"features\", original_name])\n        {\n            let mut help = Group::with_title(Level::HELP.secondary_title(\n                \"to change the feature name to snake case, convert the `features` key\",\n            ));\n            help = help.element(\n                Snippet::source(contents)\n                    .path(manifest_path)\n                    .patch(Patch::new(span.key, snake_case.as_str())),\n            );\n            report.push(help);\n        }\n\n        if lint_level.is_error() {\n            *error_count += 1;\n        }\n        gctx.shell().print_report(&report, lint_level.force())?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/non_snake_case_packages.rs",
    "content": "use std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Patch;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::TomlToolLints;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Package;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::LintLevelReason;\nuse crate::lints::RESTRICTION;\nuse crate::lints::get_key_value_span;\nuse crate::lints::rel_cwd_manifest_path;\n\npub static LINT: &Lint = &Lint {\n    name: \"non_snake_case_packages\",\n    desc: \"packages should have a snake-case name\",\n    primary_group: &RESTRICTION,\n    msrv: None,\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\n\nDetect package names that are not snake-case.\n\n### Why it is bad\n\nHaving multiple naming styles within a workspace can be confusing.\n\n### Drawbacks\n\nUsers have to mentally translate package names to namespaces in Rust.\n\n### Example\n\n```toml\n[package]\nname = \"foo_bar\"\n```\n\nShould be written as:\n\n```toml\n[package]\nname = \"foo-bar\"\n```\n\"#,\n    ),\n};\n\npub fn non_snake_case_packages(\n    pkg: &Package,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        cargo_lints,\n        pkg.rust_version(),\n        pkg.manifest().unstable_features(),\n    );\n\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n\n    lint_package(pkg, &manifest_path, lint_level, reason, error_count, gctx)\n}\n\npub fn lint_package(\n    pkg: &Package,\n    manifest_path: &str,\n    lint_level: LintLevel,\n    reason: LintLevelReason,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let manifest = pkg.manifest();\n\n    let original_name = &*manifest.name();\n    let snake_case = heck::ToSnakeCase::to_snake_case(original_name);\n    if snake_case == original_name {\n        return Ok(());\n    }\n\n    let document = manifest.document();\n    let contents = manifest.contents();\n    let level = lint_level.to_diagnostic_level();\n    let emitted_source = LINT.emitted_source(lint_level, reason);\n\n    let mut primary = Group::with_title(level.primary_title(LINT.desc));\n    if let Some(document) = document\n        && let Some(contents) = contents\n        && let Some(span) = get_key_value_span(document, &[\"package\", \"name\"])\n    {\n        primary = primary.element(\n            Snippet::source(contents)\n                .path(manifest_path)\n                .annotation(AnnotationKind::Primary.span(span.value)),\n        );\n    } else {\n        primary = primary.element(Origin::path(manifest_path));\n    }\n    primary = primary.element(Level::NOTE.message(emitted_source));\n    let mut report = vec![primary];\n    if let Some(document) = document\n        && let Some(contents) = contents\n        && let Some(span) = get_key_value_span(document, &[\"package\", \"name\"])\n    {\n        let mut help =\n            Group::with_title(Level::HELP.secondary_title(\n                \"to change the package name to snake case, convert `package.name`\",\n            ));\n        help = help.element(\n            Snippet::source(contents)\n                .path(manifest_path)\n                .patch(Patch::new(span.value, format!(\"\\\"{snake_case}\\\"\"))),\n        );\n        report.push(help);\n    } else {\n        let path = pkg.manifest_path();\n        let display_path = path.as_os_str().to_string_lossy();\n        let end = display_path.len() - if display_path.ends_with(\".rs\") { 3 } else { 0 };\n        let start = path\n            .parent()\n            .map(|p| {\n                let p = p.as_os_str().to_string_lossy();\n                // Account for trailing slash that was removed\n                p.len() + if p.is_empty() { 0 } else { 1 }\n            })\n            .unwrap_or(0);\n        let help = Level::HELP\n            .secondary_title(\"to change the package name to snake case, convert the file stem\")\n            .element(Snippet::source(display_path).patch(Patch::new(start..end, snake_case)));\n        report.push(help);\n    }\n\n    if lint_level.is_error() {\n        *error_count += 1;\n    }\n    gctx.shell().print_report(&report, lint_level.force())?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/redundant_homepage.rs",
    "content": "use std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Patch;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::InheritableField;\nuse cargo_util_schemas::manifest::TomlToolLints;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Package;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::LintLevelReason;\nuse crate::lints::STYLE;\nuse crate::lints::get_key_value_span;\nuse crate::lints::rel_cwd_manifest_path;\n\npub static LINT: &Lint = &Lint {\n    name: \"redundant_homepage\",\n    desc: \"`package.homepage` is redundant with another manifest field\",\n    primary_group: &STYLE,\n    msrv: Some(super::CARGO_LINTS_MSRV),\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\n\nChecks if the value of `package.homepage` is already covered by another field.\n\nSee also [`package.homepage` reference documentation](manifest.md#the-homepage-field).\n\n### Why it is bad\n\nWhen package browsers render each link, a redundant link adds visual noise.\n\n### Drawbacks\n\n### Example\n\n```toml\n[package]\nname = \"foo\"\nhomepage = \"https://github.com/rust-lang/cargo/\"\nrepository = \"https://github.com/rust-lang/cargo/\"\n```\n\nShould be written as:\n\n```toml\n[package]\nname = \"foo\"\nrepository = \"https://github.com/rust-lang/cargo/\"\n```\n\"#,\n    ),\n};\n\npub fn redundant_homepage(\n    pkg: &Package,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        cargo_lints,\n        pkg.rust_version(),\n        pkg.manifest().unstable_features(),\n    );\n\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n\n    lint_package(pkg, &manifest_path, lint_level, reason, error_count, gctx)\n}\n\npub fn lint_package(\n    pkg: &Package,\n    manifest_path: &str,\n    lint_level: LintLevel,\n    reason: LintLevelReason,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let manifest = pkg.manifest();\n\n    let Some(normalized_pkg) = &manifest.normalized_toml().package else {\n        return Ok(());\n    };\n    let Some(InheritableField::Value(homepage)) = &normalized_pkg.homepage else {\n        return Ok(());\n    };\n\n    let other_field = if let Some(InheritableField::Value(repository)) = &normalized_pkg.repository\n        && repository == homepage\n    {\n        \"repository\"\n    } else if let Some(InheritableField::Value(documentation)) = &normalized_pkg.documentation\n        && documentation == homepage\n    {\n        \"documentation\"\n    } else {\n        return Ok(());\n    };\n\n    let document = manifest.document();\n    let contents = manifest.contents();\n    let level = lint_level.to_diagnostic_level();\n    let emitted_source = LINT.emitted_source(lint_level, reason);\n\n    let mut primary = Group::with_title(level.primary_title(LINT.desc));\n    if let Some(document) = document\n        && let Some(contents) = contents\n        && let Some(span) = get_key_value_span(document, &[\"package\", \"homepage\"])\n    {\n        let mut snippet = Snippet::source(contents)\n            .path(manifest_path)\n            .annotation(AnnotationKind::Primary.span(span.value));\n        if let Some(span) = get_key_value_span(document, &[\"package\", other_field]) {\n            snippet = snippet.annotation(AnnotationKind::Context.span(span.value));\n        }\n        primary = primary.element(snippet);\n    } else {\n        primary = primary.element(Origin::path(manifest_path));\n    }\n    primary = primary.element(Level::NOTE.message(emitted_source));\n    let mut report = vec![primary];\n    if let Some(document) = document\n        && let Some(contents) = contents\n        && let Some(span) = get_key_value_span(document, &[\"package\", \"homepage\"])\n    {\n        let span = if let Some(workspace_span) =\n            get_key_value_span(document, &[\"package\", \"homepage\", \"workspace\"])\n        {\n            span.key.start..workspace_span.value.end\n        } else {\n            span.key.start..span.value.end\n        };\n        let mut help =\n            Group::with_title(Level::HELP.secondary_title(\"consider removing `package.homepage`\"));\n        help = help.element(\n            Snippet::source(contents)\n                .path(manifest_path)\n                .patch(Patch::new(span, \"\")),\n        );\n        report.push(help);\n    }\n\n    if lint_level.is_error() {\n        *error_count += 1;\n    }\n    gctx.shell().print_report(&report, lint_level.force())?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/redundant_readme.rs",
    "content": "use std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Patch;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::InheritableField;\nuse cargo_util_schemas::manifest::StringOrBool;\nuse cargo_util_schemas::manifest::TomlToolLints;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Package;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::LintLevelReason;\nuse crate::lints::STYLE;\nuse crate::lints::get_key_value_span;\nuse crate::lints::rel_cwd_manifest_path;\nuse crate::util::toml::DEFAULT_README_FILES;\n\npub static LINT: &Lint = &Lint {\n    name: \"redundant_readme\",\n    desc: \"explicit `package.readme` can be inferred\",\n    primary_group: &STYLE,\n    msrv: Some(super::CARGO_LINTS_MSRV),\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\n\nChecks for `package.readme` fields that can be inferred.\n\nSee also [`package.readme` reference documentation](manifest.md#the-readme-field).\n\n### Why it is bad\n\nAdds boilerplate.\n\n### Drawbacks\n\nIt might not be obvious if they named their file correctly.\n\n### Example\n\n```toml\n[package]\nname = \"foo\"\nreadme = \"README.md\"\n```\n\nShould be written as:\n\n```toml\n[package]\nname = \"foo\"\n```\n\"#,\n    ),\n};\n\npub fn redundant_readme(\n    pkg: &Package,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        cargo_lints,\n        pkg.rust_version(),\n        pkg.manifest().unstable_features(),\n    );\n\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n\n    lint_package(pkg, &manifest_path, lint_level, reason, error_count, gctx)\n}\n\npub fn lint_package(\n    pkg: &Package,\n    manifest_path: &str,\n    lint_level: LintLevel,\n    reason: LintLevelReason,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let manifest = pkg.manifest();\n\n    // Must check `original_toml`, before any inferring happened\n    let Some(original_toml) = manifest.original_toml() else {\n        return Ok(());\n    };\n    let Some(original_pkg) = &original_toml.package else {\n        return Ok(());\n    };\n    let Some(readme) = &original_pkg.readme else {\n        return Ok(());\n    };\n\n    let InheritableField::Value(StringOrBool::String(readme)) = readme else {\n        // Not checking inheritance because at most one package can be identified from the lint and\n        // consistency of inheritance is likely best.\n        return Ok(());\n    };\n\n    if !DEFAULT_README_FILES.contains(&readme.as_str()) {\n        return Ok(());\n    }\n\n    let document = manifest.document();\n    let contents = manifest.contents();\n    let level = lint_level.to_diagnostic_level();\n    let emitted_source = LINT.emitted_source(lint_level, reason);\n\n    let mut primary = Group::with_title(level.primary_title(LINT.desc));\n    if let Some(document) = document\n        && let Some(contents) = contents\n        && let Some(span) = get_key_value_span(document, &[\"package\", \"readme\"])\n    {\n        let span = span.key.start..span.value.end;\n        primary = primary.element(\n            Snippet::source(contents)\n                .path(manifest_path)\n                .annotation(AnnotationKind::Primary.span(span)),\n        );\n    } else {\n        primary = primary.element(Origin::path(manifest_path));\n    }\n    primary = primary.element(Level::NOTE.message(emitted_source));\n    let mut report = vec![primary];\n    if let Some(document) = document\n        && let Some(contents) = contents\n        && let Some(span) = get_key_value_span(document, &[\"package\", \"readme\"])\n    {\n        let span = if let Some(workspace_span) =\n            get_key_value_span(document, &[\"package\", \"readme\", \"workspace\"])\n        {\n            span.key.start..workspace_span.value.end\n        } else {\n            span.key.start..span.value.end\n        };\n        let mut help =\n            Group::with_title(Level::HELP.secondary_title(\"consider removing `package.readme`\"));\n        help = help.element(\n            Snippet::source(contents)\n                .path(manifest_path)\n                .patch(Patch::new(span, \"\")),\n        );\n        report.push(help);\n    }\n\n    if lint_level.is_error() {\n        *error_count += 1;\n    }\n    gctx.shell().print_report(&report, lint_level.force())?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/unknown_lints.rs",
    "content": "use annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::TomlToolLints;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::lints::LINT_GROUPS;\nuse crate::lints::LINTS;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::ManifestFor;\nuse crate::lints::SUSPICIOUS;\nuse crate::lints::get_key_value_span;\n\npub static LINT: &Lint = &Lint {\n    name: \"unknown_lints\",\n    desc: \"unknown lint\",\n    primary_group: &SUSPICIOUS,\n    msrv: Some(super::CARGO_LINTS_MSRV),\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\nChecks for unknown lints in the `[lints.cargo]` table\n\n### Why it is bad\n- The lint name could be misspelled, leading to confusion as to why it is\n  not working as expected\n- The unknown lint could end up causing an error if `cargo` decides to make\n  a lint with the same name in the future\n\n### Example\n```toml\n[lints.cargo]\nthis-lint-does-not-exist = \"warn\"\n```\n\"#,\n    ),\n};\n\npub fn output_unknown_lints(\n    unknown_lints: Vec<&String>,\n    manifest: &ManifestFor<'_>,\n    manifest_path: &str,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = manifest.lint_level(cargo_lints, LINT);\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let level = lint_level.to_diagnostic_level();\n    let mut emitted_source = None;\n    for lint_name in unknown_lints {\n        if lint_level.is_error() {\n            *error_count += 1;\n        }\n        let title = format!(\"{}: `{lint_name}`\", LINT.desc);\n        let underscore_lint_name = lint_name.replace(\"-\", \"_\");\n        let matching = if let Some(lint) = LINTS.iter().find(|l| l.name == underscore_lint_name) {\n            Some((lint.name, \"lint\"))\n        } else if let Some(group) = LINT_GROUPS.iter().find(|g| g.name == underscore_lint_name) {\n            Some((group.name, \"group\"))\n        } else {\n            None\n        };\n        let help =\n            matching.map(|(name, kind)| format!(\"there is a {kind} with a similar name: `{name}`\"));\n\n        let key_path = match manifest {\n            ManifestFor::Package(_) => &[\"lints\", \"cargo\", lint_name][..],\n            ManifestFor::Workspace { .. } => &[\"workspace\", \"lints\", \"cargo\", lint_name][..],\n        };\n\n        let mut report = Vec::new();\n        let mut group = Group::with_title(level.clone().primary_title(title));\n\n        if let Some(document) = manifest.document()\n            && let Some(contents) = manifest.contents()\n        {\n            let Some(span) = get_key_value_span(document, key_path) else {\n                // This lint is handled by either package or workspace lint.\n                return Ok(());\n            };\n            group = group.element(\n                Snippet::source(contents)\n                    .path(manifest_path)\n                    .annotation(AnnotationKind::Primary.span(span.key)),\n            );\n        } else {\n            group = group.element(Origin::path(manifest_path));\n        }\n\n        if emitted_source.is_none() {\n            emitted_source = Some(LINT.emitted_source(lint_level, reason));\n            group = group.element(Level::NOTE.message(emitted_source.as_ref().unwrap()));\n        }\n        if let Some(help) = help.as_ref() {\n            group = group.element(Level::HELP.message(help));\n        }\n        report.push(group);\n\n        gctx.shell().print_report(&report, lint_level.force())?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/unused_workspace_dependencies.rs",
    "content": "use std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Patch;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::InheritableDependency;\nuse cargo_util_schemas::manifest::TomlToolLints;\nuse indexmap::IndexSet;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::MaybePackage;\nuse crate::core::Workspace;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::SUSPICIOUS;\nuse crate::lints::get_key_value_span;\nuse crate::lints::rel_cwd_manifest_path;\n\npub static LINT: &Lint = &Lint {\n    name: \"unused_workspace_dependencies\",\n    desc: \"unused workspace dependency\",\n    primary_group: &SUSPICIOUS,\n    msrv: Some(super::CARGO_LINTS_MSRV),\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\nChecks for any entry in `[workspace.dependencies]` that has not been inherited\n\n### Why it is bad\nThey can give the false impression that these dependencies are used\n\n### Example\n```toml\n[workspace.dependencies]\nregex = \"1\"\n\n[dependencies]\n```\n\"#,\n    ),\n};\n\npub fn unused_workspace_dependencies(\n    ws: &Workspace<'_>,\n    maybe_pkg: &MaybePackage,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        cargo_lints,\n        ws.lowest_rust_version(),\n        maybe_pkg.unstable_features(),\n    );\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let workspace_deps: IndexSet<_> = maybe_pkg\n        .original_toml()\n        .and_then(|t| t.workspace.as_ref())\n        .and_then(|w| w.dependencies.as_ref())\n        .iter()\n        .flat_map(|d| d.keys())\n        .collect();\n\n    let mut inherited_deps = IndexSet::new();\n    for member in ws.members() {\n        let Some(original_toml) = member.manifest().original_toml() else {\n            return Ok(());\n        };\n        inherited_deps.extend(\n            original_toml\n                .build_dependencies()\n                .into_iter()\n                .flatten()\n                .filter(|(_, d)| is_inherited(d))\n                .map(|(name, _)| name),\n        );\n        inherited_deps.extend(\n            original_toml\n                .dependencies\n                .iter()\n                .flatten()\n                .filter(|(_, d)| is_inherited(d))\n                .map(|(name, _)| name),\n        );\n        inherited_deps.extend(\n            original_toml\n                .dev_dependencies()\n                .into_iter()\n                .flatten()\n                .filter(|(_, d)| is_inherited(d))\n                .map(|(name, _)| name),\n        );\n        for target in original_toml.target.iter().flat_map(|t| t.values()) {\n            inherited_deps.extend(\n                target\n                    .build_dependencies()\n                    .into_iter()\n                    .flatten()\n                    .filter(|(_, d)| is_inherited(d))\n                    .map(|(name, _)| name),\n            );\n            inherited_deps.extend(\n                target\n                    .dependencies\n                    .iter()\n                    .flatten()\n                    .filter(|(_, d)| is_inherited(d))\n                    .map(|(name, _)| name),\n            );\n            inherited_deps.extend(\n                target\n                    .dev_dependencies()\n                    .into_iter()\n                    .flatten()\n                    .filter(|(_, d)| is_inherited(d))\n                    .map(|(name, _)| name),\n            );\n        }\n    }\n\n    for (i, unused) in workspace_deps.difference(&inherited_deps).enumerate() {\n        let document = maybe_pkg.document();\n        let contents = maybe_pkg.contents();\n        let level = lint_level.to_diagnostic_level();\n        let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n        let emitted_source = LINT.emitted_source(lint_level, reason);\n\n        let mut primary = Group::with_title(level.primary_title(LINT.desc));\n        if let Some(document) = document\n            && let Some(contents) = contents\n        {\n            let mut snippet = Snippet::source(contents).path(&manifest_path);\n            if let Some(span) =\n                get_key_value_span(document, &[\"workspace\", \"dependencies\", unused.as_str()])\n            {\n                snippet = snippet.annotation(AnnotationKind::Primary.span(span.key));\n            }\n            primary = primary.element(snippet);\n        } else {\n            primary = primary.element(Origin::path(&manifest_path));\n        }\n        if i == 0 {\n            primary = primary.element(Level::NOTE.message(emitted_source));\n        }\n        let mut report = vec![primary];\n        if let Some(document) = document\n            && let Some(contents) = contents\n        {\n            let mut help = Group::with_title(\n                Level::HELP.secondary_title(\"consider removing the unused dependency\"),\n            );\n            let mut snippet = Snippet::source(contents).path(&manifest_path);\n            if let Some(span) =\n                get_key_value_span(document, &[\"workspace\", \"dependencies\", unused.as_str()])\n            {\n                snippet = snippet.patch(Patch::new(span.key.start..span.value.end, \"\"));\n            }\n            help = help.element(snippet);\n            report.push(help);\n        }\n\n        if lint_level.is_error() {\n            *error_count += 1;\n        }\n        gctx.shell().print_report(&report, lint_level.force())?;\n    }\n\n    Ok(())\n}\n\nfn is_inherited(dep: &InheritableDependency) -> bool {\n    matches!(dep, InheritableDependency::Inherit(_))\n}\n"
  },
  {
    "path": "src/cargo/lints/rules/unused_workspace_package_fields.rs",
    "content": "use std::path::Path;\n\nuse annotate_snippets::AnnotationKind;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse annotate_snippets::Patch;\nuse annotate_snippets::Snippet;\nuse cargo_util_schemas::manifest::TomlToolLints;\nuse indexmap::IndexSet;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::MaybePackage;\nuse crate::core::Workspace;\nuse crate::lints::Lint;\nuse crate::lints::LintLevel;\nuse crate::lints::SUSPICIOUS;\nuse crate::lints::get_key_value_span;\nuse crate::lints::rel_cwd_manifest_path;\n\npub static LINT: &Lint = &Lint {\n    name: \"unused_workspace_package_fields\",\n    desc: \"unused field in `workspace.package`\",\n    primary_group: &SUSPICIOUS,\n    msrv: Some(super::CARGO_LINTS_MSRV),\n    feature_gate: None,\n    docs: Some(\n        r#\"\n### What it does\nChecks for any fields in `[workspace.package]` that has not been inherited\n\n### Why it is bad\nThey can give the false impression that these fields are used\n\n### Example\n```toml\n[workspace.package]\nedition = \"2024\"\n\n[package]\nname = \"foo\"\n```\n\"#,\n    ),\n};\n\npub fn unused_workspace_package_fields(\n    ws: &Workspace<'_>,\n    maybe_pkg: &MaybePackage,\n    manifest_path: &Path,\n    cargo_lints: &TomlToolLints,\n    error_count: &mut usize,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let (lint_level, reason) = LINT.level(\n        cargo_lints,\n        ws.lowest_rust_version(),\n        maybe_pkg.unstable_features(),\n    );\n    if lint_level == LintLevel::Allow {\n        return Ok(());\n    }\n\n    let workspace_package_fields: IndexSet<_> = maybe_pkg\n        .document()\n        .and_then(|d| d.get_ref().get(\"workspace\"))\n        .and_then(|w| w.get_ref().get(\"package\"))\n        .and_then(|p| p.get_ref().as_table())\n        .iter()\n        .flat_map(|d| d.keys())\n        .collect();\n\n    let mut inherited_fields = IndexSet::new();\n    for member in ws.members() {\n        inherited_fields.extend(\n            member\n                .manifest()\n                .document()\n                .and_then(|w| w.get_ref().get(\"package\"))\n                .and_then(|p| p.get_ref().as_table())\n                .iter()\n                .flat_map(|d| {\n                    d.iter()\n                        .filter(|(_, v)| {\n                            v.get_ref()\n                                .get(\"workspace\")\n                                .and_then(|w| w.get_ref().as_bool())\n                                == Some(true)\n                        })\n                        .map(|(k, _)| k)\n                }),\n        );\n    }\n\n    for (i, unused) in workspace_package_fields\n        .difference(&inherited_fields)\n        .enumerate()\n    {\n        let document = maybe_pkg.document();\n        let contents = maybe_pkg.contents();\n        let level = lint_level.to_diagnostic_level();\n        let manifest_path = rel_cwd_manifest_path(manifest_path, gctx);\n        let emitted_source = LINT.emitted_source(lint_level, reason);\n\n        let mut primary = Group::with_title(level.primary_title(LINT.desc));\n        if let Some(document) = document\n            && let Some(contents) = contents\n        {\n            let mut snippet = Snippet::source(contents).path(&manifest_path);\n            if let Some(span) =\n                get_key_value_span(document, &[\"workspace\", \"package\", unused.as_ref()])\n            {\n                snippet = snippet.annotation(AnnotationKind::Primary.span(span.key));\n            }\n            primary = primary.element(snippet);\n        } else {\n            primary = primary.element(Origin::path(&manifest_path));\n        }\n        if i == 0 {\n            primary = primary.element(Level::NOTE.message(emitted_source));\n        }\n        let mut report = vec![primary];\n        if let Some(document) = document\n            && let Some(contents) = contents\n        {\n            let mut help = Group::with_title(\n                Level::HELP.secondary_title(\"consider removing the unused field\"),\n            );\n            let mut snippet = Snippet::source(contents).path(&manifest_path);\n            if let Some(span) =\n                get_key_value_span(document, &[\"workspace\", \"package\", unused.as_ref()])\n            {\n                snippet = snippet.patch(Patch::new(span.key.start..span.value.end, \"\"));\n            }\n            help = help.element(snippet);\n            report.push(help);\n        }\n\n        if lint_level.is_error() {\n            *error_count += 1;\n        }\n        gctx.shell().print_report(&report, lint_level.force())?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/macros.rs",
    "content": "use std::fmt;\n\nmacro_rules! compact_debug {\n    (\n        impl fmt::Debug for $ty:ident {\n            fn fmt(&$this:ident, f: &mut fmt::Formatter) -> fmt::Result {\n                let (default, default_name) = $e:expr;\n                [debug_the_fields($($field:ident)*)]\n            }\n        }\n    ) => (\n\n        impl fmt::Debug for $ty {\n            fn fmt(&$this, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n                // Try printing a pretty version where we collapse as many fields as\n                // possible, indicating that they're equivalent to a function call\n                // that's hopefully enough to indicate what each value is without\n                // actually dumping everything so verbosely.\n                let mut s = f.debug_struct(stringify!($ty));\n                let (default, default_name) = $e;\n                let mut any_default = false;\n\n                // Exhaustively match so when fields are added we get a compile\n                // failure\n                let $ty { $($field),* } = $this;\n                $(\n                    if *$field == default.$field {\n                        any_default = true;\n                    } else {\n                        s.field(stringify!($field), $field);\n                    }\n                )*\n\n                if any_default {\n                    s.field(\"..\", &crate::macros::DisplayAsDebug(default_name));\n                }\n                s.finish()\n            }\n        }\n    )\n}\n\npub struct DisplayAsDebug<T>(pub T);\n\nimpl<T: fmt::Display> fmt::Debug for DisplayAsDebug<T> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt::Display::fmt(&self.0, f)\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_add/crate_spec.rs",
    "content": "//! Crate name parsing.\n\nuse anyhow::Context as _;\n\nuse super::Dependency;\nuse crate::CargoResult;\nuse crate::util::toml_mut::dependency::RegistrySource;\nuse cargo_util_schemas::manifest::PackageName;\n\n/// User-specified crate\n///\n/// This can be a\n/// - Name (e.g. `docopt`)\n/// - Name and a version req (e.g. `docopt@^0.8`)\n#[derive(Debug)]\npub struct CrateSpec {\n    /// Crate name\n    name: String,\n    /// Optional version requirement\n    version_req: Option<String>,\n}\n\nimpl CrateSpec {\n    /// Convert a string to a `Crate`\n    pub fn resolve(pkg_id: &str) -> CargoResult<Self> {\n        let (name, version) = pkg_id\n            .split_once('@')\n            .map(|(n, v)| (n, Some(v)))\n            .unwrap_or((pkg_id, None));\n\n        let package_name = PackageName::new(name);\n        if !pkg_id.contains(\"@\") && package_name.is_err() {\n            for (idx, ch) in pkg_id.char_indices() {\n                if !(unicode_ident::is_xid_continue(ch) || ch == '-') {\n                    let mut suggested_pkg_id = pkg_id.to_string();\n                    suggested_pkg_id.insert_str(idx, \"@\");\n                    if let Ok(_) = CrateSpec::resolve(&suggested_pkg_id.as_str()) {\n                        let err = package_name.unwrap_err();\n                        return Err(\n                            anyhow::format_err!(\"{err}\\n\\n\\\n                                help: if this is meant to be a package name followed by a version, insert an `@` like `{suggested_pkg_id}`\").into());\n                    }\n                }\n            }\n        }\n\n        package_name?;\n\n        if let Some(version) = version {\n            semver::VersionReq::parse(version).with_context(|| {\n                if let Some(stripped) = version.strip_prefix(\"v\") {\n                    return format!(\n                        \"the version provided, `{version}` is not a \\\n                         valid SemVer requirement\\n\\n\\\n                         help: changing the package to `{name}@{stripped}`\",\n                    );\n                }\n                format!(\"invalid version requirement `{version}`\")\n            })?;\n        }\n\n        let id = Self {\n            name: name.to_owned(),\n            version_req: version.map(|s| s.to_owned()),\n        };\n\n        Ok(id)\n    }\n\n    /// Generate a dependency entry for this crate specifier\n    pub fn to_dependency(&self) -> CargoResult<Dependency> {\n        let mut dep = Dependency::new(self.name());\n        if let Some(version_req) = self.version_req() {\n            dep = dep.set_source(RegistrySource::new(version_req));\n        }\n        Ok(dep)\n    }\n\n    pub fn name(&self) -> &str {\n        &self.name\n    }\n\n    pub fn version_req(&self) -> Option<&str> {\n        self.version_req.as_deref()\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_add/mod.rs",
    "content": "//! Core of cargo-add command\n\nmod crate_spec;\n\nuse std::collections::BTreeMap;\nuse std::collections::BTreeSet;\nuse std::collections::VecDeque;\nuse std::fmt::Write;\nuse std::path::Path;\n\nuse anyhow::Context as _;\nuse cargo_util::paths;\nuse cargo_util_schemas::core::PartialVersion;\nuse cargo_util_schemas::manifest::PathBaseName;\nuse cargo_util_schemas::manifest::RustVersion;\nuse indexmap::IndexSet;\nuse itertools::Itertools;\nuse toml_edit::Item as TomlItem;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Feature;\nuse crate::core::FeatureValue;\nuse crate::core::Features;\nuse crate::core::Package;\nuse crate::core::PackageId;\nuse crate::core::Registry;\nuse crate::core::Shell;\nuse crate::core::Summary;\nuse crate::core::Workspace;\nuse crate::core::dependency::DepKind;\nuse crate::core::registry::PackageRegistry;\nuse crate::ops::resolve_ws;\nuse crate::sources::source::QueryKind;\nuse crate::util::OptVersionReq;\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::edit_distance;\nuse crate::util::style;\nuse crate::util::toml::lookup_path_base;\nuse crate::util::toml_mut::dependency::Dependency;\nuse crate::util::toml_mut::dependency::GitSource;\nuse crate::util::toml_mut::dependency::MaybeWorkspace;\nuse crate::util::toml_mut::dependency::PathSource;\nuse crate::util::toml_mut::dependency::RegistrySource;\nuse crate::util::toml_mut::dependency::Source;\nuse crate::util::toml_mut::dependency::WorkspaceSource;\nuse crate::util::toml_mut::manifest::DepTable;\nuse crate::util::toml_mut::manifest::LocalManifest;\nuse crate_spec::CrateSpec;\n\nconst MAX_FEATURE_PRINTS: usize = 30;\n\n/// Information on what dependencies should be added\n#[derive(Clone, Debug)]\npub struct AddOptions<'a> {\n    /// Configuration information for cargo operations\n    pub gctx: &'a GlobalContext,\n    /// Package to add dependencies to\n    pub spec: &'a Package,\n    /// Dependencies to add or modify\n    pub dependencies: Vec<DepOp>,\n    /// Which dependency section to add these to\n    pub section: DepTable,\n    /// Act as if dependencies will be added\n    pub dry_run: bool,\n    /// Whether the minimum supported Rust version should be considered during resolution\n    pub honor_rust_version: Option<bool>,\n}\n\n/// Add dependencies to a manifest\npub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<()> {\n    let dep_table = options\n        .section\n        .to_table()\n        .into_iter()\n        .map(String::from)\n        .collect::<Vec<_>>();\n\n    let manifest_path = options.spec.manifest_path().to_path_buf();\n    let mut manifest = LocalManifest::try_new(&manifest_path)?;\n    let original_raw_manifest = manifest.to_string();\n    let legacy = manifest.get_legacy_sections();\n    if !legacy.is_empty() {\n        anyhow::bail!(\n            \"Deprecated dependency sections are unsupported: {}\",\n            legacy.join(\", \")\n        );\n    }\n\n    let mut registry = workspace.package_registry()?;\n\n    let deps = {\n        let _lock = options\n            .gctx\n            .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n        registry.lock_patches();\n        options\n            .dependencies\n            .iter()\n            .map(|raw| {\n                resolve_dependency(\n                    &manifest,\n                    raw,\n                    workspace,\n                    &options.spec,\n                    &options.section,\n                    options.honor_rust_version,\n                    options.gctx,\n                    &mut registry,\n                )\n            })\n            .collect::<CargoResult<Vec<_>>>()?\n    };\n\n    let was_sorted = manifest\n        .get_table(&dep_table)\n        .map(TomlItem::as_table)\n        .map_or(true, |table_option| {\n            table_option.map_or(true, |table| {\n                table\n                    .get_values()\n                    .iter_mut()\n                    .map(|(key, _)| {\n                        // get_values key paths always have at least one key.\n                        key.remove(0)\n                    })\n                    .is_sorted()\n            })\n        });\n    for dep in deps {\n        print_action_msg(&mut options.gctx.shell(), &dep, &dep_table)?;\n        if let Some(Source::Path(src)) = dep.source() {\n            if src.path == manifest.path.parent().unwrap_or_else(|| Path::new(\"\")) {\n                anyhow::bail!(\n                    \"cannot add `{}` as a dependency to itself\",\n                    manifest.package_name()?\n                )\n            }\n        }\n\n        let available_features = dep\n            .available_features\n            .keys()\n            .map(|s| s.as_ref())\n            .collect::<BTreeSet<&str>>();\n        let mut unknown_features: Vec<&str> = Vec::new();\n        if let Some(req_feats) = dep.features.as_ref() {\n            let req_feats: BTreeSet<_> = req_feats.iter().map(|s| s.as_str()).collect();\n            unknown_features.extend(req_feats.difference(&available_features).copied());\n        }\n        if let Some(inherited_features) = dep.inherited_features.as_ref() {\n            let inherited_features: BTreeSet<_> =\n                inherited_features.iter().map(|s| s.as_str()).collect();\n            unknown_features.extend(inherited_features.difference(&available_features).copied());\n        }\n\n        unknown_features.sort();\n\n        if !unknown_features.is_empty() {\n            let (mut activated, mut deactivated) = dep.features();\n            // Since the unknown features have been added to the DependencyUI we need to remove\n            // them to present the \"correct\" features that can be specified for the crate.\n            deactivated.retain(|f| !unknown_features.contains(f));\n            activated.retain(|f| !unknown_features.contains(f));\n\n            let mut message = format!(\n                \"unrecognized feature{} for crate {}: {}\",\n                if unknown_features.len() == 1 { \"\" } else { \"s\" },\n                dep.name,\n                unknown_features.iter().format(\", \"),\n            );\n            if activated.is_empty() && deactivated.is_empty() {\n                write!(message, \"\\n\\nno features available for crate {}\", dep.name)?;\n            } else {\n                let mut suggested = false;\n                for unknown_feature in &unknown_features {\n                    let suggestion = edit_distance::closest_msg(\n                        unknown_feature,\n                        deactivated.iter().chain(activated.iter()),\n                        |dep| *dep,\n                        \"feature\",\n                    );\n                    if !suggestion.is_empty() {\n                        write!(message, \"{suggestion}\")?;\n                        suggested = true;\n                    }\n                }\n                if !deactivated.is_empty() && !suggested {\n                    if deactivated.len() <= MAX_FEATURE_PRINTS {\n                        write!(\n                            message,\n                            \"\\n\\ndisabled features:\\n    {}\",\n                            deactivated\n                                .iter()\n                                .map(|s| s.to_string())\n                                .coalesce(|x, y| if x.len() + y.len() < 78 {\n                                    Ok(format!(\"{x}, {y}\"))\n                                } else {\n                                    Err((x, y))\n                                })\n                                .into_iter()\n                                .format(\"\\n    \")\n                        )?;\n                    } else {\n                        write!(\n                            message,\n                            \"\\n\\n{} disabled features available\",\n                            deactivated.len()\n                        )?;\n                    }\n                }\n                if !activated.is_empty() && !suggested {\n                    if deactivated.len() + activated.len() <= MAX_FEATURE_PRINTS {\n                        writeln!(\n                            message,\n                            \"\\n\\nenabled features:\\n    {}\",\n                            activated\n                                .iter()\n                                .map(|s| s.to_string())\n                                .coalesce(|x, y| if x.len() + y.len() < 78 {\n                                    Ok(format!(\"{x}, {y}\"))\n                                } else {\n                                    Err((x, y))\n                                })\n                                .into_iter()\n                                .format(\"\\n    \")\n                        )?;\n                    } else {\n                        writeln!(\n                            message,\n                            \"\\n\\n{} enabled features available\",\n                            activated.len()\n                        )?;\n                    }\n                }\n            }\n            anyhow::bail!(message.trim().to_owned());\n        }\n\n        print_dep_table_msg(&mut options.gctx.shell(), &dep)?;\n\n        manifest.insert_into_table(\n            &dep_table,\n            &dep,\n            workspace.gctx(),\n            workspace.root(),\n            options.spec.manifest().unstable_features(),\n        )?;\n        if dep.optional == Some(true) {\n            let is_namespaced_features_supported =\n                check_rust_version_for_optional_dependency(options.spec.rust_version())?;\n            if is_namespaced_features_supported {\n                let dep_key = dep.toml_key();\n                if !manifest.is_explicit_dep_activation(dep_key) {\n                    let table = manifest\n                        .get_table_mut(&[String::from(\"features\")])\n                        .expect(\"manifest validated\");\n                    let dep_name = dep.rename.as_deref().unwrap_or(&dep.name);\n                    let new_feature: toml_edit::Value =\n                        [format!(\"dep:{dep_name}\")].iter().collect();\n                    table[dep_key] = toml_edit::value(new_feature);\n                    options\n                        .gctx\n                        .shell()\n                        .status(\"Adding\", format!(\"feature `{dep_key}`\"))?;\n                }\n            }\n        }\n        manifest.gc_dep(dep.toml_key());\n    }\n\n    if was_sorted {\n        if let Some(table) = manifest\n            .get_table_mut(&dep_table)\n            .and_then(TomlItem::as_table_like_mut)\n        {\n            table.sort_values();\n        }\n    }\n\n    if let Some(locked_flag) = options.gctx.locked_flag() {\n        let new_raw_manifest = manifest.to_string();\n        if original_raw_manifest != new_raw_manifest {\n            anyhow::bail!(\n                \"the manifest file {} needs to be updated but {locked_flag} was passed to prevent this\",\n                manifest.path.display()\n            );\n        }\n    }\n\n    if options.dry_run {\n        options.gctx.shell().warn(\"aborting add due to dry run\")?;\n    } else {\n        manifest.write()?;\n    }\n\n    Ok(())\n}\n\n/// Dependency entry operation\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct DepOp {\n    /// Describes the crate\n    pub crate_spec: Option<String>,\n    /// Dependency key, overriding the package name in `crate_spec`\n    pub rename: Option<String>,\n\n    /// Feature flags to activate\n    pub features: Option<IndexSet<String>>,\n    /// Whether the default feature should be activated\n    pub default_features: Option<bool>,\n\n    /// Whether dependency is optional\n    pub optional: Option<bool>,\n\n    /// Whether dependency is public\n    pub public: Option<bool>,\n\n    /// Registry for looking up dependency version\n    pub registry: Option<String>,\n\n    /// File system path for dependency\n    pub path: Option<String>,\n    /// Specify a named base for a path dependency\n    pub base: Option<String>,\n\n    /// Git repo for dependency\n    pub git: Option<String>,\n    /// Specify an alternative git branch\n    pub branch: Option<String>,\n    /// Specify a specific git rev\n    pub rev: Option<String>,\n    /// Specify a specific git tag\n    pub tag: Option<String>,\n}\n\nfn resolve_dependency(\n    manifest: &LocalManifest,\n    arg: &DepOp,\n    ws: &Workspace<'_>,\n    spec: &Package,\n    section: &DepTable,\n    honor_rust_version: Option<bool>,\n    gctx: &GlobalContext,\n    registry: &mut PackageRegistry<'_>,\n) -> CargoResult<DependencyUI> {\n    let crate_spec = arg\n        .crate_spec\n        .as_deref()\n        .map(CrateSpec::resolve)\n        .transpose()?;\n    let mut selected_dep = if let Some(url) = &arg.git {\n        let mut src = GitSource::new(url);\n        if let Some(branch) = &arg.branch {\n            src = src.set_branch(branch);\n        }\n        if let Some(tag) = &arg.tag {\n            src = src.set_tag(tag);\n        }\n        if let Some(rev) = &arg.rev {\n            src = src.set_rev(rev);\n        }\n\n        let selected = if let Some(crate_spec) = &crate_spec {\n            if let Some(v) = crate_spec.version_req() {\n                // crate specifier includes a version (e.g. `docopt@0.8`)\n                anyhow::bail!(\"cannot specify a git URL (`{url}`) with a version (`{v}`).\");\n            }\n            let dependency = crate_spec.to_dependency()?.set_source(src);\n            let selected = select_package(&dependency, gctx, registry)?;\n            if dependency.name != selected.name {\n                gctx.shell().warn(format!(\n                    \"translating `{}` to `{}`\",\n                    dependency.name, selected.name,\n                ))?;\n            }\n            selected\n        } else {\n            let mut source = crate::sources::GitSource::new(src.source_id()?, gctx)?;\n            let packages = source.read_packages()?;\n            let package = infer_package_for_git_source(packages, &src)?;\n            Dependency::from(package.summary())\n        };\n        selected\n    } else if let Some(raw_path) = &arg.path {\n        let path = paths::normalize_path(&std::env::current_dir()?.join(raw_path));\n        let mut src = PathSource::new(path);\n        src.base = arg.base.clone();\n\n        if let Some(base) = &arg.base {\n            // Validate that the base is valid.\n            let workspace_root = || Ok(ws.root_manifest().parent().unwrap());\n            lookup_path_base(\n                &PathBaseName::new(base.clone())?,\n                &gctx,\n                &workspace_root,\n                spec.manifest().unstable_features(),\n            )?;\n        }\n\n        let selected = if let Some(crate_spec) = &crate_spec {\n            if let Some(v) = crate_spec.version_req() {\n                // crate specifier includes a version (e.g. `docopt@0.8`)\n                anyhow::bail!(\"cannot specify a path (`{raw_path}`) with a version (`{v}`).\");\n            }\n            let dependency = crate_spec.to_dependency()?.set_source(src);\n            let selected = select_package(&dependency, gctx, registry)?;\n            if dependency.name != selected.name {\n                gctx.shell().warn(format!(\n                    \"translating `{}` to `{}`\",\n                    dependency.name, selected.name,\n                ))?;\n            }\n            selected\n        } else {\n            let mut source = crate::sources::PathSource::new(&src.path, src.source_id()?, gctx);\n            let package = source.root_package()?;\n            let mut selected = Dependency::from(package.summary());\n            if let Some(Source::Path(selected_src)) = &mut selected.source {\n                selected_src.base = src.base;\n            }\n            selected\n        };\n        selected\n    } else if let Some(crate_spec) = &crate_spec {\n        crate_spec.to_dependency()?\n    } else {\n        anyhow::bail!(\"dependency name is required\");\n    };\n    selected_dep = populate_dependency(selected_dep, arg);\n\n    let lookup = |dep_key: &_| {\n        get_existing_dependency(\n            ws,\n            spec.manifest().unstable_features(),\n            manifest,\n            dep_key,\n            section,\n        )\n    };\n    let old_dep = fuzzy_lookup(&mut selected_dep, lookup, gctx)?;\n    let mut dependency = if let Some(mut old_dep) = old_dep.clone() {\n        if old_dep.name != selected_dep.name {\n            // Assuming most existing keys are not relevant when the package changes\n            if selected_dep.optional.is_none() {\n                selected_dep.optional = old_dep.optional;\n            }\n            selected_dep\n        } else {\n            if selected_dep.source().is_some() {\n                // Overwrite with `crate_spec`\n                old_dep.source = selected_dep.source;\n            }\n            populate_dependency(old_dep, arg)\n        }\n    } else {\n        selected_dep\n    };\n\n    if dependency.source().is_none() {\n        // Checking for a workspace dependency happens first since a member could be specified\n        // in the workspace dependencies table as a dependency\n        let lookup = |toml_key: &_| {\n            Ok(find_workspace_dep(toml_key, ws, ws.root_manifest(), ws.unstable_features()).ok())\n        };\n        if let Some(_dep) = fuzzy_lookup(&mut dependency, lookup, gctx)? {\n            dependency = dependency.set_source(WorkspaceSource::new());\n        } else if let Some(package) = ws.members().find(|p| p.name().as_str() == dependency.name) {\n            // Only special-case workspaces when the user doesn't provide any extra\n            // information, otherwise, trust the user.\n            let mut src = PathSource::new(package.root());\n            // dev-dependencies do not need the version populated\n            if section.kind() != DepKind::Development {\n                let op = \"\";\n                let v = format!(\"{op}{version}\", version = package.version());\n                src = src.set_version(v);\n            }\n            dependency = dependency.set_source(src);\n        } else if let Some((registry, public_source)) =\n            get_public_dependency(spec, manifest, ws, section, gctx, &dependency)?\n        {\n            if let Some(registry) = registry {\n                dependency = dependency.set_registry(registry);\n            }\n            dependency = dependency.set_source(public_source);\n        } else {\n            let latest =\n                get_latest_dependency(spec, &dependency, honor_rust_version, gctx, registry)?;\n\n            if dependency.name != latest.name {\n                gctx.shell().warn(format!(\n                    \"translating `{}` to `{}`\",\n                    dependency.name, latest.name,\n                ))?;\n                dependency.name = latest.name; // Normalize the name\n            }\n            dependency = dependency.set_source(latest.source.expect(\"latest always has a source\"));\n        }\n    }\n\n    if let Some(Source::Workspace(_)) = dependency.source() {\n        check_invalid_ws_keys(dependency.toml_key(), arg)?;\n    }\n\n    let version_required = dependency.source().and_then(|s| s.as_registry()).is_some();\n    let version_optional_in_section = section.kind() == DepKind::Development;\n    let preserve_existing_version = old_dep\n        .as_ref()\n        .map(|d| d.version().is_some())\n        .unwrap_or(false);\n    if !version_required && !preserve_existing_version && version_optional_in_section {\n        // dev-dependencies do not need the version populated\n        dependency = dependency.clear_version();\n    }\n\n    let query = query_dependency(ws, gctx, &mut dependency)?;\n    let dependency = populate_available_features(dependency, &query, registry)?;\n\n    Ok(dependency)\n}\n\nfn get_public_dependency(\n    spec: &Package,\n    manifest: &LocalManifest,\n    ws: &Workspace<'_>,\n    section: &DepTable,\n    gctx: &GlobalContext,\n    dependency: &Dependency,\n) -> CargoResult<Option<(Option<String>, Source)>> {\n    if spec\n        .manifest()\n        .unstable_features()\n        .require(Feature::public_dependency())\n        .is_err()\n    {\n        return Ok(None);\n    }\n\n    let (package_set, resolve) = resolve_ws(ws, true)?;\n\n    let mut latest: Option<(PackageId, OptVersionReq)> = None;\n\n    for (_, path, dep) in manifest.get_dependencies(ws, ws.unstable_features()) {\n        if path != *section {\n            continue;\n        }\n\n        let Some(mut dep) = dep.ok() else {\n            continue;\n        };\n\n        let dep = query_dependency(ws, gctx, &mut dep)?;\n        let Some(dep_pkgid) = package_set\n            .package_ids()\n            .filter(|package_id| {\n                package_id.name() == dep.package_name()\n                    && dep.version_req().matches(package_id.version())\n            })\n            .max_by_key(|x| x.version())\n        else {\n            continue;\n        };\n\n        let mut pkg_ids_and_reqs = Vec::new();\n        let mut pkg_id_queue = VecDeque::new();\n        let mut examined = BTreeSet::new();\n        pkg_id_queue.push_back(dep_pkgid);\n\n        while let Some(dep_pkgid) = pkg_id_queue.pop_front() {\n            let got_deps = resolve.deps(dep_pkgid).filter_map(|(id, deps)| {\n                deps.iter()\n                    .find(|dep| dep.is_public() && dep.kind() == DepKind::Normal)\n                    .map(|dep| (id, dep))\n            });\n\n            for (pkg_id, got_dep) in got_deps {\n                if got_dep.package_name() == dependency.name.as_str() {\n                    pkg_ids_and_reqs.push((pkg_id, got_dep.version_req().clone()));\n                }\n\n                if examined.insert(pkg_id.clone()) {\n                    pkg_id_queue.push_back(pkg_id)\n                }\n            }\n        }\n\n        for (pkg_id, req) in pkg_ids_and_reqs {\n            if let Some((old_pkg_id, _)) = &latest\n                && old_pkg_id.version() >= pkg_id.version()\n            {\n                continue;\n            }\n            latest = Some((pkg_id, req))\n        }\n    }\n\n    let Some((pkg_id, version_req)) = latest else {\n        return Ok(None);\n    };\n\n    let source = pkg_id.source_id();\n    if source.is_git() {\n        Ok(Some((\n            Option::<String>::None,\n            Source::Git(GitSource::new(source.as_encoded_url().to_string())),\n        )))\n    } else if let Some(path) = source.local_path() {\n        Ok(Some((None, Source::Path(PathSource::new(path)))))\n    } else {\n        let toml_source = match version_req {\n            crate::util::OptVersionReq::Any => {\n                Source::Registry(RegistrySource::new(pkg_id.version().to_string()))\n            }\n            crate::util::OptVersionReq::Req(version_req)\n            | crate::util::OptVersionReq::Locked(_, version_req)\n            | crate::util::OptVersionReq::Precise(_, version_req) => {\n                Source::Registry(RegistrySource::new(version_req.to_string()))\n            }\n        };\n        Ok(Some((\n            source\n                .alt_registry_key()\n                .map(|x| x.to_owned())\n                .filter(|_| !source.is_crates_io()),\n            toml_source,\n        )))\n    }\n}\n\nfn query_dependency(\n    ws: &Workspace<'_>,\n    gctx: &GlobalContext,\n    dependency: &mut Dependency,\n) -> CargoResult<crate::core::Dependency> {\n    let query = dependency.query(gctx)?;\n    let query = match query {\n        MaybeWorkspace::Workspace(_workspace) => {\n            let dep = find_workspace_dep(\n                dependency.toml_key(),\n                ws,\n                ws.root_manifest(),\n                ws.unstable_features(),\n            )?;\n            if let Some(features) = dep.features.clone() {\n                *dependency = dependency.clone().set_inherited_features(features);\n            }\n            let query = dep.query(gctx)?;\n            match query {\n                MaybeWorkspace::Workspace(_) => {\n                    anyhow::bail!(\n                        \"dependency ({}) specified without \\\n                        providing a local path, Git repository, or version\",\n                        dependency.toml_key()\n                    );\n                }\n                MaybeWorkspace::Other(query) => query,\n            }\n        }\n        MaybeWorkspace::Other(query) => query,\n    };\n    Ok(query)\n}\n\nfn fuzzy_lookup(\n    dependency: &mut Dependency,\n    lookup: impl Fn(&str) -> CargoResult<Option<Dependency>>,\n    gctx: &GlobalContext,\n) -> CargoResult<Option<Dependency>> {\n    if let Some(rename) = dependency.rename() {\n        // Manually implement `toml_key` to restrict fuzzy lookups to only package names to mirror `PackageRegistry::query()`\n        return lookup(rename);\n    }\n\n    for name_permutation in [\n        dependency.name.clone(),\n        dependency.name.replace('-', \"_\"),\n        dependency.name.replace('_', \"-\"),\n    ] {\n        let Some(dep) = lookup(&name_permutation)? else {\n            continue;\n        };\n\n        if dependency.name != name_permutation {\n            // Mirror the fuzzy matching policy of `PackageRegistry::query()`\n            if !matches!(dep.source, Some(Source::Registry(_))) {\n                continue;\n            }\n            gctx.shell().warn(format!(\n                \"translating `{}` to `{}`\",\n                dependency.name, &name_permutation,\n            ))?;\n            dependency.name = name_permutation;\n        }\n        return Ok(Some(dep));\n    }\n\n    Ok(None)\n}\n\n/// When { workspace = true } you cannot define other keys that configure\n/// the source of the dependency such as `version`, `registry`, `registry-index`,\n/// `path`, `git`, `branch`, `tag`, `rev`, or `package`. You can also not define\n/// `default-features`.\n///\n/// Only `default-features`, `registry` and `rename` need to be checked\n///  for currently. This is because `git` and its associated keys, `path`, and\n/// `version`  should all bee checked before this is called. `rename` is checked\n/// for as it turns into `package`\nfn check_invalid_ws_keys(toml_key: &str, arg: &DepOp) -> CargoResult<()> {\n    fn err_msg(toml_key: &str, flag: &str, field: &str) -> String {\n        format!(\n            \"cannot override workspace dependency with `{flag}`, \\\n            either change `workspace.dependencies.{toml_key}.{field}` \\\n            or define the dependency exclusively in the package's manifest\"\n        )\n    }\n\n    if arg.default_features.is_some() {\n        anyhow::bail!(\n            \"{}\",\n            err_msg(toml_key, \"--default-features\", \"default-features\")\n        )\n    }\n    if arg.registry.is_some() {\n        anyhow::bail!(\"{}\", err_msg(toml_key, \"--registry\", \"registry\"))\n    }\n    // rename is `package`\n    if arg.rename.is_some() {\n        anyhow::bail!(\"{}\", err_msg(toml_key, \"--rename\", \"package\"))\n    }\n    Ok(())\n}\n\n/// When the `--optional` option is added using `cargo add`, we need to\n/// check the current rust-version. As the `dep:` syntax is only available\n/// starting with Rust 1.60.0\n///\n/// `true` means that the rust-version is None or the rust-version is higher\n/// than the version needed.\n///\n/// Note: Previous versions can only use the implicit feature name.\nfn check_rust_version_for_optional_dependency(\n    rust_version: Option<&RustVersion>,\n) -> CargoResult<bool> {\n    match rust_version {\n        Some(version) => {\n            let syntax_support_version = RustVersion::new(1, 60, 0);\n            Ok(&syntax_support_version <= version)\n        }\n        None => Ok(true),\n    }\n}\n\n/// Provide the existing dependency for the target table\n///\n/// If it doesn't exist but exists in another table, let's use that as most likely users\n/// want to use the same version across all tables unless they are renaming.\nfn get_existing_dependency(\n    ws: &Workspace<'_>,\n    unstable_features: &Features,\n    manifest: &LocalManifest,\n    dep_key: &str,\n    section: &DepTable,\n) -> CargoResult<Option<Dependency>> {\n    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]\n    enum Key {\n        Error,\n        Dev,\n        Build,\n        Normal,\n        Existing,\n    }\n\n    let mut possible: Vec<_> = manifest\n        .get_dependencies(ws, unstable_features)\n        .filter_map(|(key, path, dep)| {\n            if key.as_str() != dep_key {\n                return None;\n            }\n            let key = if path == *section {\n                (Key::Existing, true)\n            } else if dep.is_err() {\n                (Key::Error, path.target().is_some())\n            } else {\n                let key = match path.kind() {\n                    DepKind::Normal => Key::Normal,\n                    DepKind::Build => Key::Build,\n                    DepKind::Development => Key::Dev,\n                };\n                (key, path.target().is_some())\n            };\n            Some((key, dep))\n        })\n        .collect();\n    possible.sort_by_key(|(key, _)| *key);\n    let Some((key, dep)) = possible.pop() else {\n        return Ok(None);\n    };\n    let mut dep = dep?;\n\n    if key.0 != Key::Existing {\n        // When the dep comes from a different section, we only care about the source and not any\n        // of the other fields, like `features`\n        let unrelated = dep;\n        dep = Dependency::new(&unrelated.name);\n        dep.source = unrelated.source.clone();\n        dep.registry = unrelated.registry.clone();\n\n        // dev-dependencies do not need the version populated when path is set though we\n        // should preserve it if the user chose to populate it.\n        let version_required = unrelated.source().and_then(|s| s.as_registry()).is_some();\n        let version_optional_in_section = section.kind() == DepKind::Development;\n        if !version_required && version_optional_in_section {\n            dep = dep.clear_version();\n        }\n    }\n\n    Ok(Some(dep))\n}\n\nfn get_latest_dependency(\n    spec: &Package,\n    dependency: &Dependency,\n    honor_rust_version: Option<bool>,\n    gctx: &GlobalContext,\n    registry: &mut PackageRegistry<'_>,\n) -> CargoResult<Dependency> {\n    let query = dependency.query(gctx)?;\n    match query {\n        MaybeWorkspace::Workspace(_) => {\n            unreachable!(\"registry dependencies required, found a workspace dependency\");\n        }\n        MaybeWorkspace::Other(query) => {\n            let possibilities = loop {\n                match registry.query_vec(&query, QueryKind::Normalized) {\n                    std::task::Poll::Ready(res) => {\n                        break res?;\n                    }\n                    std::task::Poll::Pending => registry.block_until_ready()?,\n                }\n            };\n\n            let mut possibilities: Vec<_> = possibilities\n                .into_iter()\n                .map(|s| s.into_summary())\n                .collect();\n\n            possibilities.sort_by_key(|s| {\n                // Fallback to a pre-release if no official release is available by sorting them as\n                // less.\n                let stable = s.version().pre.is_empty();\n                (stable, s.version().clone())\n            });\n\n            let mut latest = possibilities.last().ok_or_else(|| {\n                anyhow::format_err!(\n                    \"the crate `{dependency}` could not be found in registry index.\"\n                )\n            })?;\n\n            if honor_rust_version.unwrap_or(true) {\n                let (req_msrv, is_msrv) = spec\n                    .rust_version()\n                    .cloned()\n                    .map(|msrv| CargoResult::Ok((msrv.to_partial(), true)))\n                    .unwrap_or_else(|| {\n                        let rustc = gctx.load_global_rustc(None)?;\n\n                        // Remove any pre-release identifiers for easier comparison\n                        let rustc_version = rustc.version.clone().into();\n                        Ok((rustc_version, false))\n                    })?;\n\n                let msrvs = possibilities\n                    .iter()\n                    .map(|s| (s, s.rust_version()))\n                    .collect::<Vec<_>>();\n\n                // Find the latest version of the dep which has a compatible rust-version. To\n                // determine whether or not one rust-version is compatible with another, we\n                // compare the lowest possible versions they could represent, and treat\n                // candidates without a rust-version as compatible by default.\n                let latest_msrv = latest_compatible(&msrvs, &req_msrv).ok_or_else(|| {\n                        let name = spec.name();\n                        let dep_name = &dependency.name;\n                        let latest_version = latest.version();\n                        let latest_msrv = latest\n                            .rust_version()\n                            .expect(\"as `None` are compatible, we can't be here\");\n                        if is_msrv {\n                            anyhow::format_err!(\n                                \"\\\nno version of crate `{dep_name}` can maintain {name}'s rust-version of {req_msrv}\nhelp: pass `--ignore-rust-version` to select {dep_name}@{latest_version} which requires rustc {latest_msrv}\"\n                            )\n                        } else {\n                            anyhow::format_err!(\n                                \"\\\nno version of crate `{dep_name}` is compatible with rustc {req_msrv}\nhelp: pass `--ignore-rust-version` to select {dep_name}@{latest_version} which requires rustc {latest_msrv}\"\n                            )\n                        }\n                    })?;\n\n                if latest_msrv.version() < latest.version() {\n                    let latest_version = latest.version();\n                    let latest_rust_version = latest.rust_version().unwrap();\n                    let name = spec.name();\n                    if is_msrv {\n                        gctx.shell().warn(format_args!(\n                            \"\\\nignoring {dependency}@{latest_version} (which requires rustc {latest_rust_version}) to maintain {name}'s rust-version of {req_msrv}\",\n                        ))?;\n                    } else {\n                        gctx.shell().warn(format_args!(\n                            \"\\\nignoring {dependency}@{latest_version} (which requires rustc {latest_rust_version}) as it is incompatible with rustc {req_msrv}\",\n                        ))?;\n                    }\n\n                    latest = latest_msrv;\n                }\n            }\n\n            let mut dep = Dependency::from(latest);\n            if let Some(reg_name) = dependency.registry.as_deref() {\n                dep = dep.set_registry(reg_name);\n            }\n            Ok(dep)\n        }\n    }\n}\n\n/// Of MSRV-compatible summaries, find the highest version\n///\n/// Assumptions:\n/// - `msrvs` is sorted by version\nfn latest_compatible<'s>(\n    msrvs: &[(&'s Summary, Option<&RustVersion>)],\n    pkg_msrv: &PartialVersion,\n) -> Option<&'s Summary> {\n    msrvs\n        .iter()\n        .filter(|(_, dep_msrv)| {\n            dep_msrv\n                .as_ref()\n                .map(|dep_msrv| dep_msrv.is_compatible_with(pkg_msrv))\n                .unwrap_or(true)\n        })\n        .map(|(s, _)| s)\n        .next_back()\n        .copied()\n}\n\nfn select_package(\n    dependency: &Dependency,\n    gctx: &GlobalContext,\n    registry: &mut PackageRegistry<'_>,\n) -> CargoResult<Dependency> {\n    let query = dependency.query(gctx)?;\n    match query {\n        MaybeWorkspace::Workspace(_) => {\n            unreachable!(\"path or git dependency expected, found workspace dependency\");\n        }\n        MaybeWorkspace::Other(query) => {\n            let possibilities = loop {\n                // Exact to avoid returning all for path/git\n                match registry.query_vec(&query, QueryKind::Normalized) {\n                    std::task::Poll::Ready(res) => {\n                        break res?;\n                    }\n                    std::task::Poll::Pending => registry.block_until_ready()?,\n                }\n            };\n\n            let possibilities: Vec<_> = possibilities\n                .into_iter()\n                .map(|s| s.into_summary())\n                .collect();\n\n            match possibilities.len() {\n                0 => {\n                    let source = dependency\n                        .source()\n                        .expect(\"source should be resolved before here\");\n                    anyhow::bail!(\"the crate `{dependency}` could not be found at `{source}`\")\n                }\n                1 => {\n                    let mut dep = Dependency::from(&possibilities[0]);\n                    if let Some(reg_name) = dependency.registry.as_deref() {\n                        dep = dep.set_registry(reg_name);\n                    }\n                    if let Some(Source::Path(PathSource { base, .. })) = dependency.source() {\n                        if let Some(Source::Path(dep_src)) = &mut dep.source {\n                            dep_src.base = base.clone();\n                        }\n                    }\n                    Ok(dep)\n                }\n                _ => {\n                    let source = dependency\n                        .source()\n                        .expect(\"source should be resolved before here\");\n                    anyhow::bail!(\n                        \"unexpectedly found multiple copies of crate `{dependency}` at `{source}`\"\n                    )\n                }\n            }\n        }\n    }\n}\n\nfn infer_package_for_git_source(\n    mut packages: Vec<Package>,\n    src: &dyn std::fmt::Display,\n) -> CargoResult<Package> {\n    let package = match packages.len() {\n        0 => unreachable!(\n            \"this function should only be called with packages from `GitSource::read_packages` \\\n            and that call should error for us when there are no packages\"\n        ),\n        1 => packages.pop().expect(\"match ensured element is present\"),\n        _ => {\n            let mut names: Vec<_> = packages\n                .iter()\n                .map(|p| p.name().as_str().to_owned())\n                .collect();\n            names.sort_unstable();\n            anyhow::bail!(\n                \"multiple packages found at `{src}`:\\n    {}\\nTo disambiguate, run `cargo add --git {src} <package>`\",\n                names\n                    .iter()\n                    .map(|s| s.to_string())\n                    .coalesce(|x, y| if x.len() + y.len() < 78 {\n                        Ok(format!(\"{x}, {y}\"))\n                    } else {\n                        Err((x, y))\n                    })\n                    .into_iter()\n                    .format(\"\\n    \"),\n            );\n        }\n    };\n    Ok(package)\n}\n\nfn populate_dependency(mut dependency: Dependency, arg: &DepOp) -> Dependency {\n    if let Some(registry) = &arg.registry {\n        if registry.is_empty() {\n            dependency.registry = None;\n        } else {\n            dependency.registry = Some(registry.to_owned());\n        }\n    }\n    if let Some(value) = arg.optional {\n        if value {\n            dependency.optional = Some(true);\n        } else {\n            dependency.optional = None;\n        }\n    }\n    if let Some(value) = arg.public {\n        if value {\n            dependency.public = Some(true);\n        } else {\n            dependency.public = None;\n        }\n    }\n    if let Some(value) = arg.default_features {\n        if value {\n            dependency.default_features = None;\n        } else {\n            dependency.default_features = Some(false);\n        }\n    }\n    if let Some(value) = arg.features.as_ref() {\n        dependency = dependency.extend_features(value.iter().cloned());\n    }\n\n    if let Some(rename) = &arg.rename {\n        dependency = dependency.set_rename(rename);\n    }\n\n    dependency\n}\n\n/// Track presentation-layer information with the editable representation of a `[dependencies]`\n/// entry (Dependency)\npub struct DependencyUI {\n    /// Editable representation of a `[dependencies]` entry\n    dep: Dependency,\n    /// The version of the crate that we pulled `available_features` from\n    available_version: Option<semver::Version>,\n    /// The widest set of features compatible with `Dependency`s version requirement\n    available_features: BTreeMap<String, Vec<String>>,\n}\n\nimpl DependencyUI {\n    fn new(dep: Dependency) -> Self {\n        Self {\n            dep,\n            available_version: None,\n            available_features: Default::default(),\n        }\n    }\n\n    fn apply_summary(&mut self, summary: &Summary) {\n        self.available_version = Some(summary.version().clone());\n        self.available_features = summary\n            .features()\n            .iter()\n            .map(|(k, v)| {\n                (\n                    k.as_str().to_owned(),\n                    v.iter()\n                        .filter_map(|v| match v {\n                            FeatureValue::Feature(f) => Some(f.as_str().to_owned()),\n                            FeatureValue::Dep { .. } | FeatureValue::DepFeature { .. } => None,\n                        })\n                        .collect::<Vec<_>>(),\n                )\n            })\n            .collect();\n    }\n\n    fn features(&self) -> (IndexSet<&str>, IndexSet<&str>) {\n        let mut activated: IndexSet<_> =\n            self.features.iter().flatten().map(|s| s.as_str()).collect();\n        if self.default_features().unwrap_or(true) {\n            activated.insert(\"default\");\n        }\n        activated.extend(self.inherited_features.iter().flatten().map(|s| s.as_str()));\n        let mut walk: VecDeque<_> = activated.iter().cloned().collect();\n        while let Some(next) = walk.pop_front() {\n            walk.extend(\n                self.available_features\n                    .get(next)\n                    .into_iter()\n                    .flatten()\n                    .map(|s| s.as_str())\n                    .filter(|s| !activated.contains(s)),\n            );\n            activated.extend(\n                self.available_features\n                    .get(next)\n                    .into_iter()\n                    .flatten()\n                    .map(|s| s.as_str()),\n            );\n        }\n        activated.swap_remove(\"default\");\n        activated.sort();\n        let mut deactivated = self\n            .available_features\n            .keys()\n            .filter(|f| !activated.contains(f.as_str()) && *f != \"default\")\n            .map(|f| f.as_str())\n            .collect::<IndexSet<_>>();\n        deactivated.sort();\n        (activated, deactivated)\n    }\n}\n\nimpl<'s> From<&'s Summary> for DependencyUI {\n    fn from(other: &'s Summary) -> Self {\n        let dep = Dependency::from(other);\n        let mut dep = Self::new(dep);\n        dep.apply_summary(other);\n        dep\n    }\n}\n\nimpl std::fmt::Display for DependencyUI {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.dep.fmt(f)\n    }\n}\n\nimpl std::ops::Deref for DependencyUI {\n    type Target = Dependency;\n\n    fn deref(&self) -> &Self::Target {\n        &self.dep\n    }\n}\n\n/// Lookup available features\nfn populate_available_features(\n    dependency: Dependency,\n    query: &crate::core::dependency::Dependency,\n    registry: &mut PackageRegistry<'_>,\n) -> CargoResult<DependencyUI> {\n    let mut dependency = DependencyUI::new(dependency);\n\n    if !dependency.available_features.is_empty() {\n        return Ok(dependency);\n    }\n\n    let possibilities = loop {\n        match registry.query_vec(&query, QueryKind::Normalized) {\n            std::task::Poll::Ready(res) => {\n                break res?;\n            }\n            std::task::Poll::Pending => registry.block_until_ready()?,\n        }\n    };\n    // Ensure widest feature flag compatibility by picking the earliest version that could show up\n    // in the lock file for a given version requirement.\n    let lowest_common_denominator = possibilities\n        .iter()\n        .map(|s| s.as_summary())\n        .min_by_key(|s| {\n            // Fallback to a pre-release if no official release is available by sorting them as\n            // more.\n            let is_pre = !s.version().pre.is_empty();\n            (is_pre, s.version())\n        })\n        .ok_or_else(|| {\n            anyhow::format_err!(\"the crate `{dependency}` could not be found in registry index.\")\n        })?;\n    dependency.apply_summary(&lowest_common_denominator);\n\n    Ok(dependency)\n}\n\nfn print_action_msg(shell: &mut Shell, dep: &DependencyUI, section: &[String]) -> CargoResult<()> {\n    if matches!(shell.verbosity(), crate::core::shell::Verbosity::Quiet) {\n        return Ok(());\n    }\n\n    let mut message = String::new();\n    write!(message, \"{}\", dep.name)?;\n    match dep.source() {\n        Some(Source::Registry(src)) => {\n            if src.version.chars().next().unwrap_or('0').is_ascii_digit() {\n                write!(message, \" v{}\", src.version)?;\n            } else {\n                write!(message, \" {}\", src.version)?;\n            }\n        }\n        Some(Source::Path(_)) => {\n            write!(message, \" (local)\")?;\n        }\n        Some(Source::Git(_)) => {\n            write!(message, \" (git)\")?;\n        }\n        Some(Source::Workspace(_)) => {\n            write!(message, \" (workspace)\")?;\n        }\n        None => {}\n    }\n    write!(message, \" to\")?;\n    if dep.optional().unwrap_or(false) {\n        write!(message, \" optional\")?;\n    }\n    if dep.public().unwrap_or(false) {\n        write!(message, \" public\")?;\n    }\n    let section = if section.len() == 1 {\n        section[0].clone()\n    } else {\n        format!(\"{} for target `{}`\", &section[2], &section[1])\n    };\n    write!(message, \" {section}\")?;\n    shell.status(\"Adding\", message)\n}\n\nfn print_dep_table_msg(shell: &mut Shell, dep: &DependencyUI) -> CargoResult<()> {\n    if matches!(shell.verbosity(), crate::core::shell::Verbosity::Quiet) {\n        return Ok(());\n    }\n\n    let stderr = shell.err();\n    let good = style::GOOD;\n    let error = style::ERROR;\n\n    let (activated, deactivated) = dep.features();\n    if !activated.is_empty() || !deactivated.is_empty() {\n        let prefix = format!(\"{:>13}\", \" \");\n        let suffix = format_features_version_suffix(&dep);\n\n        writeln!(stderr, \"{prefix}Features{suffix}:\")?;\n\n        let total_activated = activated.len();\n        let total_deactivated = deactivated.len();\n\n        if total_activated <= MAX_FEATURE_PRINTS {\n            for feat in activated {\n                writeln!(stderr, \"{prefix}{good}+{good:#} {feat}\")?;\n            }\n        } else {\n            writeln!(stderr, \"{prefix}{total_activated} activated features\")?;\n        }\n\n        if total_activated + total_deactivated <= MAX_FEATURE_PRINTS {\n            for feat in deactivated {\n                writeln!(stderr, \"{prefix}{error}-{error:#} {feat}\")?;\n            }\n        } else {\n            writeln!(stderr, \"{prefix}{total_deactivated} deactivated features\")?;\n        }\n    }\n\n    Ok(())\n}\n\nfn format_features_version_suffix(dep: &DependencyUI) -> String {\n    if let Some(version) = &dep.available_version {\n        let mut version = version.clone();\n        version.build = Default::default();\n        let version = version.to_string();\n        // Avoid displaying the version if it will visually look like the version req that we\n        // showed earlier\n        let version_req = dep\n            .version()\n            .and_then(|v| semver::VersionReq::parse(v).ok())\n            .and_then(|v| precise_version(&v));\n        if version_req.as_deref() != Some(version.as_str()) {\n            format!(\" as of v{version}\")\n        } else {\n            \"\".to_owned()\n        }\n    } else {\n        \"\".to_owned()\n    }\n}\n\nfn find_workspace_dep(\n    toml_key: &str,\n    ws: &Workspace<'_>,\n    root_manifest: &Path,\n    unstable_features: &Features,\n) -> CargoResult<Dependency> {\n    let manifest = LocalManifest::try_new(root_manifest)?;\n    let manifest = manifest\n        .data\n        .as_item()\n        .as_table_like()\n        .context(\"could not make `manifest.data` into a table\")?;\n    let workspace = manifest\n        .get(\"workspace\")\n        .context(\"could not find `workspace`\")?\n        .as_table_like()\n        .context(\"could not make `manifest.data.workspace` into a table\")?;\n    let dependencies = workspace\n        .get(\"dependencies\")\n        .context(\"could not find `dependencies` table in `workspace`\")?\n        .as_table_like()\n        .context(\"could not make `dependencies` into a table\")?;\n    let dep_item = dependencies\n        .get(toml_key)\n        .with_context(|| format!(\"could not find {toml_key} in `workspace.dependencies`\"))?;\n    Dependency::from_toml(\n        ws.gctx(),\n        ws.root(),\n        root_manifest.parent().unwrap(),\n        unstable_features,\n        toml_key,\n        dep_item,\n    )\n}\n\n/// Convert a `semver::VersionReq` into a rendered `semver::Version` if all fields are fully\n/// specified.\nfn precise_version(version_req: &semver::VersionReq) -> Option<String> {\n    version_req\n        .comparators\n        .iter()\n        .filter(|c| {\n            matches!(\n                c.op,\n                // Only ops we can determine a precise version from\n                semver::Op::Exact\n                    | semver::Op::GreaterEq\n                    | semver::Op::LessEq\n                    | semver::Op::Tilde\n                    | semver::Op::Caret\n                    | semver::Op::Wildcard\n            )\n        })\n        .filter_map(|c| {\n            // Only do it when full precision is specified\n            c.minor.and_then(|minor| {\n                c.patch.map(|patch| semver::Version {\n                    major: c.major,\n                    minor,\n                    patch,\n                    pre: c.pre.clone(),\n                    build: Default::default(),\n                })\n            })\n        })\n        .max()\n        .map(|v| v.to_string())\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_clean.rs",
    "content": "use crate::core::compiler::{CompileKind, CompileMode, Layout, RustcTargetData};\nuse crate::core::profiles::Profiles;\nuse crate::core::{PackageIdSpec, PackageIdSpecQuery, TargetKind, Workspace};\nuse crate::ops;\nuse crate::util::HumanBytes;\nuse crate::util::edit_distance;\nuse crate::util::errors::CargoResult;\nuse crate::util::interning::InternedString;\nuse crate::util::{GlobalContext, Progress, ProgressStyle};\nuse anyhow::bail;\nuse cargo_util::paths;\nuse indexmap::{IndexMap, IndexSet};\n\nuse std::ffi::OsString;\nuse std::fs;\nuse std::path::{Path, PathBuf};\nuse std::rc::Rc;\n\npub struct CleanOptions<'gctx> {\n    pub gctx: &'gctx GlobalContext,\n    /// A list of packages to clean. If empty, everything is cleaned.\n    pub spec: IndexSet<String>,\n    /// The target arch triple to clean, or None for the host arch\n    pub targets: Vec<String>,\n    /// Whether to clean the release directory\n    pub profile_specified: bool,\n    /// Whether to clean the directory of a certain build profile\n    pub requested_profile: InternedString,\n    /// Whether to just clean the doc directory\n    pub doc: bool,\n    /// If set, doesn't delete anything.\n    pub dry_run: bool,\n}\n\npub struct CleanContext<'gctx> {\n    pub gctx: &'gctx GlobalContext,\n    progress: Box<dyn CleaningProgressBar + 'gctx>,\n    pub dry_run: bool,\n    num_files_removed: u64,\n    num_dirs_removed: u64,\n    total_bytes_removed: u64,\n}\n\n/// Cleans various caches.\npub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {\n    let mut target_dir = ws.target_dir();\n    let mut build_dir = ws.build_dir();\n    let gctx = opts.gctx;\n    let mut clean_ctx = CleanContext::new(gctx);\n    clean_ctx.dry_run = opts.dry_run;\n\n    if opts.doc {\n        if !opts.spec.is_empty() {\n            // FIXME: https://github.com/rust-lang/cargo/issues/8790\n            // This should support the ability to clean specific packages\n            // within the doc directory. It's a little tricky since it\n            // needs to find all documentable targets, but also consider\n            // the fact that target names might overlap with dependency\n            // names and such.\n            bail!(\"--doc cannot be used with -p\");\n        }\n        // If the doc option is set, we just want to delete the doc directory.\n        target_dir = target_dir.join(\"doc\");\n        clean_ctx.remove_paths(&[target_dir.into_path_unlocked()])?;\n    } else {\n        let profiles = Profiles::new(&ws, opts.requested_profile)?;\n\n        if opts.profile_specified {\n            // After parsing profiles we know the dir-name of the profile, if a profile\n            // was passed from the command line. If so, delete only the directory of\n            // that profile.\n            let dir_name = profiles.get_dir_name();\n            target_dir = target_dir.join(dir_name);\n            build_dir = build_dir.join(dir_name);\n        }\n\n        // If we have a spec, then we need to delete some packages, otherwise, just\n        // remove the whole target directory and be done with it!\n        //\n        // Note that we don't bother grabbing a lock here as we're just going to\n        // blow it all away anyway.\n        if opts.spec.is_empty() {\n            let paths: &[PathBuf] = if build_dir != target_dir {\n                &[\n                    target_dir.into_path_unlocked(),\n                    build_dir.into_path_unlocked(),\n                ]\n            } else {\n                &[target_dir.into_path_unlocked()]\n            };\n            clean_ctx.remove_paths(paths)?;\n        } else {\n            clean_specs(\n                &mut clean_ctx,\n                &ws,\n                &profiles,\n                &opts.targets,\n                &opts.spec,\n                opts.dry_run,\n            )?;\n        }\n    }\n\n    clean_ctx.display_summary()?;\n    Ok(())\n}\n\nfn clean_specs(\n    clean_ctx: &mut CleanContext<'_>,\n    ws: &Workspace<'_>,\n    profiles: &Profiles,\n    targets: &[String],\n    spec: &IndexSet<String>,\n    dry_run: bool,\n) -> CargoResult<()> {\n    // Clean specific packages.\n    let requested_kinds = CompileKind::from_requested_targets(clean_ctx.gctx, targets)?;\n    let target_data = RustcTargetData::new(ws, &requested_kinds)?;\n    let (pkg_set, resolve) = ops::resolve_ws(ws, dry_run)?;\n    let prof_dir_name = profiles.get_dir_name();\n    let host_layout = Layout::new(ws, None, &prof_dir_name, true, true)?;\n    // Convert requested kinds to a Vec of layouts.\n    let target_layouts: Vec<(CompileKind, Layout)> = requested_kinds\n        .into_iter()\n        .filter_map(|kind| match kind {\n            CompileKind::Target(target) => {\n                match Layout::new(ws, Some(target), &prof_dir_name, true, true) {\n                    Ok(layout) => Some(Ok((kind, layout))),\n                    Err(e) => Some(Err(e)),\n                }\n            }\n            CompileKind::Host => None,\n        })\n        .collect::<CargoResult<_>>()?;\n    // A Vec of layouts. This is a little convoluted because there can only be\n    // one host_layout.\n    let layouts = if targets.is_empty() {\n        vec![(CompileKind::Host, &host_layout)]\n    } else {\n        target_layouts\n            .iter()\n            .map(|(kind, layout)| (*kind, layout))\n            .collect()\n    };\n    // Create a Vec that also includes the host for things that need to clean both.\n    let layouts_with_host: Vec<(CompileKind, &Layout)> =\n        std::iter::once((CompileKind::Host, &host_layout))\n            .chain(layouts.iter().map(|(k, l)| (*k, *l)))\n            .collect();\n\n    // Cleaning individual rustdoc crates is currently not supported.\n    // For example, the search index would need to be rebuilt to fully\n    // remove it (otherwise you're left with lots of broken links).\n    // Doc tests produce no output.\n\n    // Get Packages for the specified specs.\n    let mut pkg_ids = Vec::new();\n    for spec_str in spec.iter() {\n        // Translate the spec to a Package.\n        let spec = PackageIdSpec::parse(spec_str)?;\n        if spec.partial_version().is_some() {\n            clean_ctx.gctx.shell().warn(&format!(\n                \"version qualifier in `-p {}` is ignored, \\\n                cleaning all versions of `{}` found\",\n                spec_str,\n                spec.name()\n            ))?;\n        }\n        if spec.url().is_some() {\n            clean_ctx.gctx.shell().warn(&format!(\n                \"url qualifier in `-p {}` ignored, \\\n                cleaning all versions of `{}` found\",\n                spec_str,\n                spec.name()\n            ))?;\n        }\n        let matches: Vec<_> = resolve.iter().filter(|id| spec.matches(*id)).collect();\n        if matches.is_empty() {\n            let mut suggestion = String::new();\n            suggestion.push_str(&edit_distance::closest_msg(\n                &spec.name(),\n                resolve.iter(),\n                |id| id.name().as_str(),\n                \"package\",\n            ));\n            anyhow::bail!(\n                \"package ID specification `{}` did not match any packages{}\",\n                spec,\n                suggestion\n            );\n        }\n        pkg_ids.extend(matches);\n    }\n    let packages = pkg_set.get_many(pkg_ids)?;\n\n    clean_ctx.progress = Box::new(CleaningPackagesBar::new(clean_ctx.gctx, packages.len()));\n    let mut dirs_to_clean = DirectoriesToClean::default();\n\n    if clean_ctx.gctx.cli_unstable().build_dir_new_layout {\n        for pkg in packages {\n            clean_ctx.progress.on_cleaning_package(&pkg.name())?;\n\n            // Remove intermediate artifacts\n            for (_compile_kind, layout) in &layouts_with_host {\n                let dir = layout.build_dir().build_unit(&pkg.name());\n                clean_ctx.rm_rf(&dir)?;\n            }\n\n            // Remove the uplifted copy.\n            for target in pkg.targets() {\n                if target.is_custom_build() {\n                    continue;\n                }\n                let crate_name: Rc<str> = target.crate_name().into();\n                for &mode in &[\n                    CompileMode::Build,\n                    CompileMode::Test,\n                    CompileMode::Check { test: false },\n                ] {\n                    for (compile_kind, layout) in &layouts {\n                        let triple = target_data.short_name(compile_kind);\n                        let (file_types, _unsupported) = target_data\n                            .info(*compile_kind)\n                            .rustc_outputs(mode, target.kind(), triple, clean_ctx.gctx)?;\n                        let artifact_dir = layout\n                            .artifact_dir()\n                            .expect(\"artifact-dir was not locked during clean\");\n                        let uplift_dir = match target.kind() {\n                            TargetKind::ExampleBin | TargetKind::ExampleLib(..) => {\n                                Some(artifact_dir.examples())\n                            }\n                            // Tests/benchmarks are never uplifted.\n                            TargetKind::Test | TargetKind::Bench => None,\n                            _ => Some(artifact_dir.dest()),\n                        };\n                        if let Some(uplift_dir) = uplift_dir {\n                            for file_type in file_types {\n                                let uplifted_filename = file_type.uplift_filename(target);\n\n                                // Dep-info generated by Cargo itself.\n                                let dep_info = Path::new(&uplifted_filename)\n                                    .with_extension(\"d\")\n                                    .to_string_lossy()\n                                    .into_owned();\n\n                                dirs_to_clean.mark_utf(uplift_dir, |filename| {\n                                    filename == uplifted_filename || filename == dep_info\n                                });\n                            }\n                        }\n                        let path_dash = format!(\"{}-\", crate_name);\n\n                        dirs_to_clean.mark_utf(layout.build_dir().incremental(), |filename| {\n                            filename.starts_with(&path_dash)\n                        });\n                    }\n                }\n            }\n        }\n    } else {\n        for pkg in packages {\n            clean_ctx.progress.on_cleaning_package(&pkg.name())?;\n\n            // Clean fingerprints.\n            for (_, layout) in &layouts_with_host {\n                dirs_to_clean.mark_utf(layout.build_dir().legacy_fingerprint(), |filename| {\n                    let Some((pkg_name, _)) = filename.rsplit_once('-') else {\n                        return false;\n                    };\n\n                    pkg_name == pkg.name().as_str()\n                });\n            }\n\n            for target in pkg.targets() {\n                if target.is_custom_build() {\n                    // Get both the build_script_build and the output directory.\n                    for (_, layout) in &layouts_with_host {\n                        dirs_to_clean.mark_utf(layout.build_dir().build(), |filename| {\n                            let Some((current_name, _)) = filename.rsplit_once('-') else {\n                                return false;\n                            };\n\n                            current_name == pkg.name().as_str()\n                        });\n                    }\n                    continue;\n                }\n                let crate_name: Rc<str> = target.crate_name().into();\n                let path_dot: &str = &format!(\"{crate_name}.\");\n                let path_dash: &str = &format!(\"{crate_name}-\");\n                for &mode in &[\n                    CompileMode::Build,\n                    CompileMode::Test,\n                    CompileMode::Check { test: false },\n                ] {\n                    for (compile_kind, layout) in &layouts {\n                        let triple = target_data.short_name(compile_kind);\n                        let (file_types, _unsupported) = target_data\n                            .info(*compile_kind)\n                            .rustc_outputs(mode, target.kind(), triple, clean_ctx.gctx)?;\n                        let artifact_dir = layout\n                            .artifact_dir()\n                            .expect(\"artifact-dir was not locked during clean\");\n                        let (dir, uplift_dir) = match target.kind() {\n                            TargetKind::ExampleBin | TargetKind::ExampleLib(..) => {\n                                (layout.build_dir().examples(), Some(artifact_dir.examples()))\n                            }\n                            // Tests/benchmarks are never uplifted.\n                            TargetKind::Test | TargetKind::Bench => {\n                                (layout.build_dir().legacy_deps(), None)\n                            }\n                            _ => (layout.build_dir().legacy_deps(), Some(artifact_dir.dest())),\n                        };\n\n                        for file_type in file_types {\n                            // Some files include a hash in the filename, some don't.\n                            let (prefix, suffix) = file_type.output_prefix_suffix(target);\n                            let unhashed_name = file_type.output_filename(target, None);\n                            dirs_to_clean.mark_utf(&dir, |filename| {\n                                (filename.starts_with(&prefix) && filename.ends_with(&suffix))\n                                    || unhashed_name == filename\n                            });\n\n                            // Remove the uplifted copy.\n                            if let Some(uplift_dir) = uplift_dir {\n                                let uplifted_path =\n                                    uplift_dir.join(file_type.uplift_filename(target));\n                                clean_ctx.rm_rf(&uplifted_path)?;\n                                // Dep-info generated by Cargo itself.\n                                let dep_info = uplifted_path.with_extension(\"d\");\n                                clean_ctx.rm_rf(&dep_info)?;\n                            }\n                        }\n                        let unhashed_dep_info = format!(\"{}.d\", crate_name);\n                        dirs_to_clean.mark_utf(dir, |filename| filename == unhashed_dep_info);\n\n                        dirs_to_clean.mark_utf(dir, |filename| {\n                            if filename.starts_with(&path_dash) {\n                                // Remove dep-info file generated by rustc. It is not tracked in\n                                // file_types. It does not have a prefix.\n                                filename.ends_with(\".d\")\n                            } else if filename.starts_with(&path_dot) {\n                                // Remove split-debuginfo files generated by rustc.\n                                [\".o\", \".dwo\", \".dwp\"]\n                                    .iter()\n                                    .any(|suffix| filename.ends_with(suffix))\n                            } else {\n                                false\n                            }\n                        });\n\n                        // TODO: what to do about build_script_build?\n                        dirs_to_clean.mark_utf(layout.build_dir().incremental(), |filename| {\n                            filename.starts_with(path_dash)\n                        });\n                    }\n                }\n            }\n        }\n    }\n    clean_ctx.rm_rf_all(dirs_to_clean)?;\n\n    Ok(())\n}\n\n#[derive(Default)]\nstruct DirectoriesToClean {\n    dir_contents: IndexMap<PathBuf, IndexSet<OsString>>,\n    to_remove: IndexSet<PathBuf>,\n}\n\nimpl DirectoriesToClean {\n    fn mark(&mut self, directory: &Path, mut should_remove_entry: impl FnMut(&OsString) -> bool) {\n        let entry = match self.dir_contents.entry(directory.to_owned()) {\n            indexmap::map::Entry::Occupied(occupied_entry) => occupied_entry.into_mut(),\n            indexmap::map::Entry::Vacant(vacant_entry) => {\n                let Ok(dir_entries) = std::fs::read_dir(directory.to_owned()) else {\n                    return;\n                };\n                vacant_entry.insert(\n                    dir_entries\n                        .into_iter()\n                        .flatten()\n                        .map(|entry| entry.file_name())\n                        .collect::<IndexSet<_>>(),\n                )\n            }\n        };\n\n        entry.retain(|path| {\n            let should_remove = should_remove_entry(path);\n            if should_remove {\n                self.to_remove.insert(directory.join(path));\n            }\n            !should_remove\n        });\n    }\n\n    fn mark_utf(&mut self, directory: &Path, mut should_remove_entry: impl FnMut(&str) -> bool) {\n        self.mark(directory, move |filename| {\n            let Some(as_utf) = filename.to_str() else {\n                return false;\n            };\n            should_remove_entry(as_utf)\n        });\n    }\n}\n\nimpl<'gctx> CleanContext<'gctx> {\n    pub fn new(gctx: &'gctx GlobalContext) -> Self {\n        // This progress bar will get replaced, this is just here to avoid needing\n        // an Option until the actual bar is created.\n        let progress = CleaningFolderBar::new(gctx, 0);\n        CleanContext {\n            gctx,\n            progress: Box::new(progress),\n            dry_run: false,\n            num_files_removed: 0,\n            num_dirs_removed: 0,\n            total_bytes_removed: 0,\n        }\n    }\n\n    fn rm_rf_all(&mut self, dirs: DirectoriesToClean) -> CargoResult<()> {\n        for path in dirs.to_remove {\n            self.rm_rf(&path)?;\n        }\n        Ok(())\n    }\n\n    pub fn rm_rf(&mut self, path: &Path) -> CargoResult<()> {\n        let meta = match fs::symlink_metadata(path) {\n            Ok(meta) => meta,\n            Err(e) => {\n                if e.kind() != std::io::ErrorKind::NotFound {\n                    self.gctx\n                        .shell()\n                        .warn(&format!(\"cannot access {}: {e}\", path.display()))?;\n                }\n                return Ok(());\n            }\n        };\n\n        // dry-run displays paths while walking, so don't print here.\n        if !self.dry_run {\n            self.gctx\n                .shell()\n                .verbose(|shell| shell.status(\"Removing\", path.display()))?;\n        }\n        self.progress.display_now()?;\n\n        let mut rm_file = |path: &Path, meta: Result<std::fs::Metadata, _>| {\n            if let Ok(meta) = meta {\n                // Note: This can over-count bytes removed for hard-linked\n                // files. It also under-counts since it only counts the exact\n                // byte sizes and not the block sizes.\n                self.total_bytes_removed += meta.len();\n            }\n            self.num_files_removed += 1;\n            if !self.dry_run {\n                paths::remove_file(path)?;\n            }\n            Ok(())\n        };\n\n        if !meta.is_dir() {\n            return rm_file(path, Ok(meta));\n        }\n\n        for entry in walkdir::WalkDir::new(path).contents_first(true) {\n            let entry = entry?;\n            self.progress.on_clean()?;\n            if self.dry_run {\n                // This prints the path without the \"Removing\" status since I feel\n                // like it can be surprising or even frightening if cargo says it\n                // is removing something without actually removing it. And I can't\n                // come up with a different verb to use as the status.\n                self.gctx\n                    .shell()\n                    .verbose(|shell| Ok(writeln!(shell.out(), \"{}\", entry.path().display())?))?;\n            }\n            if entry.file_type().is_dir() {\n                self.num_dirs_removed += 1;\n                // The contents should have been removed by now, but sometimes a race condition is hit\n                // where other files have been added by the OS. `paths::remove_dir_all` also falls back\n                // to `std::fs::remove_dir_all`, which may be more reliable than a simple walk in\n                // platform-specific edge cases.\n                if !self.dry_run {\n                    paths::remove_dir_all(entry.path())?;\n                }\n            } else {\n                rm_file(entry.path(), entry.metadata())?;\n            }\n        }\n\n        Ok(())\n    }\n\n    pub fn display_summary(&self) -> CargoResult<()> {\n        let status = if self.dry_run { \"Summary\" } else { \"Removed\" };\n        let byte_count = if self.total_bytes_removed == 0 {\n            String::new()\n        } else {\n            let bytes = HumanBytes(self.total_bytes_removed);\n            format!(\", {bytes:.1} total\")\n        };\n        // I think displaying the number of directories removed isn't\n        // particularly interesting to the user. However, if there are 0\n        // files, and a nonzero number of directories, cargo should indicate\n        // that it did *something*, so directory counts are only shown in that\n        // case.\n        let file_count = match (self.num_files_removed, self.num_dirs_removed) {\n            (0, 0) => format!(\"0 files\"),\n            (0, 1) => format!(\"1 directory\"),\n            (0, 2..) => format!(\"{} directories\", self.num_dirs_removed),\n            (1, _) => format!(\"1 file\"),\n            (2.., _) => format!(\"{} files\", self.num_files_removed),\n        };\n        self.gctx\n            .shell()\n            .status(status, format!(\"{file_count}{byte_count}\"))?;\n        if self.dry_run {\n            self.gctx\n                .shell()\n                .warn(\"no files deleted due to --dry-run\")?;\n        }\n        Ok(())\n    }\n\n    /// Deletes all of the given paths, showing a progress bar as it proceeds.\n    ///\n    /// If any path does not exist, or is not accessible, this will not\n    /// generate an error. This only generates an error for other issues, like\n    /// not being able to write to the console.\n    pub fn remove_paths(&mut self, paths: &[PathBuf]) -> CargoResult<()> {\n        let num_paths = paths\n            .iter()\n            .map(|path| walkdir::WalkDir::new(path).into_iter().count())\n            .sum();\n        self.progress = Box::new(CleaningFolderBar::new(self.gctx, num_paths));\n        for path in paths {\n            self.rm_rf(path)?;\n        }\n        Ok(())\n    }\n}\n\ntrait CleaningProgressBar {\n    fn display_now(&mut self) -> CargoResult<()>;\n    fn on_clean(&mut self) -> CargoResult<()>;\n    fn on_cleaning_package(&mut self, _package: &str) -> CargoResult<()> {\n        Ok(())\n    }\n}\n\nstruct CleaningFolderBar<'gctx> {\n    bar: Progress<'gctx>,\n    max: usize,\n    cur: usize,\n}\n\nimpl<'gctx> CleaningFolderBar<'gctx> {\n    fn new(gctx: &'gctx GlobalContext, max: usize) -> Self {\n        Self {\n            bar: Progress::with_style(\"Cleaning\", ProgressStyle::Percentage, gctx),\n            max,\n            cur: 0,\n        }\n    }\n\n    fn cur_progress(&self) -> usize {\n        std::cmp::min(self.cur, self.max)\n    }\n}\n\nimpl<'gctx> CleaningProgressBar for CleaningFolderBar<'gctx> {\n    fn display_now(&mut self) -> CargoResult<()> {\n        self.bar.tick_now(self.cur_progress(), self.max, \"\")\n    }\n\n    fn on_clean(&mut self) -> CargoResult<()> {\n        self.cur += 1;\n        self.bar.tick(self.cur_progress(), self.max, \"\")\n    }\n}\n\nstruct CleaningPackagesBar<'gctx> {\n    bar: Progress<'gctx>,\n    max: usize,\n    cur: usize,\n    num_files_folders_cleaned: usize,\n    package_being_cleaned: String,\n}\n\nimpl<'gctx> CleaningPackagesBar<'gctx> {\n    fn new(gctx: &'gctx GlobalContext, max: usize) -> Self {\n        Self {\n            bar: Progress::with_style(\"Cleaning\", ProgressStyle::Ratio, gctx),\n            max,\n            cur: 0,\n            num_files_folders_cleaned: 0,\n            package_being_cleaned: String::new(),\n        }\n    }\n\n    fn cur_progress(&self) -> usize {\n        std::cmp::min(self.cur, self.max)\n    }\n\n    fn format_message(&self) -> String {\n        format!(\n            \": {}, {} files/folders cleaned\",\n            self.package_being_cleaned, self.num_files_folders_cleaned\n        )\n    }\n}\n\nimpl<'gctx> CleaningProgressBar for CleaningPackagesBar<'gctx> {\n    fn display_now(&mut self) -> CargoResult<()> {\n        self.bar\n            .tick_now(self.cur_progress(), self.max, &self.format_message())\n    }\n\n    fn on_clean(&mut self) -> CargoResult<()> {\n        self.bar\n            .tick(self.cur_progress(), self.max, &self.format_message())?;\n        self.num_files_folders_cleaned += 1;\n        Ok(())\n    }\n\n    fn on_cleaning_package(&mut self, package: &str) -> CargoResult<()> {\n        self.cur += 1;\n        self.package_being_cleaned = String::from(package);\n        self.bar\n            .tick(self.cur_progress(), self.max, &self.format_message())\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_compile/compile_filter.rs",
    "content": "//! Filters and their rules to select which Cargo targets will be built.\n\nuse crate::core::compiler::UserIntent;\nuse crate::core::{Target, TargetKind};\nuse crate::util::restricted_names::is_glob_pattern;\n\n#[derive(Debug, PartialEq, Eq, Clone)]\n/// Indicates whether or not the library target gets included.\npub enum LibRule {\n    /// Include the library, fail if not present\n    True,\n    /// Include the library if present\n    Default,\n    /// Exclude the library\n    False,\n}\n\n#[derive(Debug, Clone)]\n/// Indicates which Cargo targets will be selected to be built.\npub enum FilterRule {\n    /// All included.\n    All,\n    /// Just a subset of Cargo targets based on names given.\n    Just(Vec<String>),\n}\n\n/// Filter to apply to the root package to select which Cargo targets will be built.\n/// (examples, bins, benches, tests, ...)\n///\n/// The actual filter process happens inside [`generate_root_units`].\n///\n/// Not to be confused with [`Packages`], which opts in packages to be built.\n///\n/// [`generate_root_units`]: super::UnitGenerator::generate_root_units\n/// [`Packages`]: crate::ops::Packages\n#[derive(Debug, Clone)]\npub enum CompileFilter {\n    /// The default set of Cargo targets.\n    Default {\n        /// Flag whether targets can be safely skipped when required-features are not satisfied.\n        required_features_filterable: bool,\n    },\n    /// Only includes a subset of all Cargo targets.\n    Only {\n        /// Include all Cargo targets.\n        all_targets: bool,\n        lib: LibRule,\n        bins: FilterRule,\n        examples: FilterRule,\n        tests: FilterRule,\n        benches: FilterRule,\n    },\n}\n\nimpl FilterRule {\n    pub fn new(targets: Vec<String>, all: bool) -> FilterRule {\n        if all {\n            FilterRule::All\n        } else {\n            FilterRule::Just(targets)\n        }\n    }\n\n    /// Creates a filter with no rule.\n    ///\n    /// In the current Cargo implementation, filter without a rule implies\n    /// Cargo will follows the default behaviour to filter targets.\n    pub fn none() -> FilterRule {\n        FilterRule::Just(Vec::new())\n    }\n\n    /// Checks if a target definition matches this filter rule.\n    fn matches(&self, target: &Target) -> bool {\n        match *self {\n            FilterRule::All => true,\n            FilterRule::Just(ref targets) => targets.iter().any(|x| *x == target.name()),\n        }\n    }\n\n    /// Check if a filter is specific.\n    ///\n    /// Only filters without rules are considered as not specific.\n    fn is_specific(&self) -> bool {\n        match *self {\n            FilterRule::All => true,\n            FilterRule::Just(ref targets) => !targets.is_empty(),\n        }\n    }\n\n    /// Checks if any specified target name contains glob patterns.\n    pub(crate) fn contains_glob_patterns(&self) -> bool {\n        match self {\n            FilterRule::All => false,\n            FilterRule::Just(targets) => targets.iter().any(is_glob_pattern),\n        }\n    }\n}\n\nimpl CompileFilter {\n    /// Constructs a filter from raw command line arguments.\n    pub fn from_raw_arguments(\n        lib_only: bool,\n        bins: Vec<String>,\n        all_bins: bool,\n        tests: Vec<String>,\n        all_tests: bool,\n        examples: Vec<String>,\n        all_examples: bool,\n        benches: Vec<String>,\n        all_benches: bool,\n        all_targets: bool,\n    ) -> CompileFilter {\n        if all_targets {\n            return CompileFilter::new_all_targets();\n        }\n        let rule_lib = if lib_only {\n            LibRule::True\n        } else {\n            LibRule::False\n        };\n        let rule_bins = FilterRule::new(bins, all_bins);\n        let rule_tests = FilterRule::new(tests, all_tests);\n        let rule_examples = FilterRule::new(examples, all_examples);\n        let rule_benches = FilterRule::new(benches, all_benches);\n\n        CompileFilter::new(rule_lib, rule_bins, rule_tests, rule_examples, rule_benches)\n    }\n\n    /// Constructs a filter from underlying primitives.\n    pub fn new(\n        rule_lib: LibRule,\n        rule_bins: FilterRule,\n        rule_tests: FilterRule,\n        rule_examples: FilterRule,\n        rule_benches: FilterRule,\n    ) -> CompileFilter {\n        if rule_lib == LibRule::True\n            || rule_bins.is_specific()\n            || rule_tests.is_specific()\n            || rule_examples.is_specific()\n            || rule_benches.is_specific()\n        {\n            CompileFilter::Only {\n                all_targets: false,\n                lib: rule_lib,\n                bins: rule_bins,\n                examples: rule_examples,\n                benches: rule_benches,\n                tests: rule_tests,\n            }\n        } else {\n            CompileFilter::Default {\n                required_features_filterable: true,\n            }\n        }\n    }\n\n    /// Constructs a filter that includes all targets.\n    pub fn new_all_targets() -> CompileFilter {\n        CompileFilter::Only {\n            all_targets: true,\n            lib: LibRule::Default,\n            bins: FilterRule::All,\n            examples: FilterRule::All,\n            benches: FilterRule::All,\n            tests: FilterRule::All,\n        }\n    }\n\n    /// Constructs a filter that includes all test targets.\n    ///\n    /// Being different from the behavior of [`CompileFilter::Default`], this\n    /// function only recognizes test targets, which means cargo might compile\n    /// all targets with `tested` flag on, whereas [`CompileFilter::Default`]\n    /// may include additional example targets to ensure they can be compiled.\n    ///\n    /// Note that the actual behavior is subject to [`filter_default_targets`]\n    /// and [`generate_root_units`] though.\n    ///\n    /// [`generate_root_units`]: super::UnitGenerator::generate_root_units\n    /// [`filter_default_targets`]: super::UnitGenerator::filter_default_targets\n    pub fn all_test_targets() -> Self {\n        Self::Only {\n            all_targets: false,\n            lib: LibRule::Default,\n            bins: FilterRule::none(),\n            examples: FilterRule::none(),\n            tests: FilterRule::All,\n            benches: FilterRule::none(),\n        }\n    }\n\n    /// Constructs a filter that includes lib target only.\n    pub fn lib_only() -> Self {\n        Self::Only {\n            all_targets: false,\n            lib: LibRule::True,\n            bins: FilterRule::none(),\n            examples: FilterRule::none(),\n            tests: FilterRule::none(),\n            benches: FilterRule::none(),\n        }\n    }\n\n    /// Constructs a filter that includes the given binary. No more. No less.\n    pub fn single_bin(bin: String) -> Self {\n        Self::Only {\n            all_targets: false,\n            lib: LibRule::False,\n            bins: FilterRule::new(vec![bin], false),\n            examples: FilterRule::none(),\n            tests: FilterRule::none(),\n            benches: FilterRule::none(),\n        }\n    }\n\n    /// Indicates if Cargo needs to build any dev dependency.\n    pub fn need_dev_deps(&self, intent: UserIntent) -> bool {\n        match intent {\n            UserIntent::Test | UserIntent::Doctest | UserIntent::Bench => true,\n            UserIntent::Check { test: true } => true,\n            UserIntent::Build | UserIntent::Doc { .. } | UserIntent::Check { test: false } => {\n                match *self {\n                    CompileFilter::Default { .. } => false,\n                    CompileFilter::Only {\n                        ref examples,\n                        ref tests,\n                        ref benches,\n                        ..\n                    } => examples.is_specific() || tests.is_specific() || benches.is_specific(),\n                }\n            }\n        }\n    }\n\n    /// Selects targets for \"cargo run\". for logic to select targets for other\n    /// subcommands, see [`generate_root_units`] and [`filter_default_targets`].\n    ///\n    /// [`generate_root_units`]: super::UnitGenerator::generate_root_units\n    /// [`filter_default_targets`]: super::UnitGenerator::filter_default_targets\n    pub fn target_run(&self, target: &Target) -> bool {\n        match *self {\n            CompileFilter::Default { .. } => true,\n            CompileFilter::Only {\n                ref lib,\n                ref bins,\n                ref examples,\n                ref tests,\n                ref benches,\n                ..\n            } => {\n                let rule = match *target.kind() {\n                    TargetKind::Bin => bins,\n                    TargetKind::Test => tests,\n                    TargetKind::Bench => benches,\n                    TargetKind::ExampleBin | TargetKind::ExampleLib(..) => examples,\n                    TargetKind::Lib(..) => {\n                        return match *lib {\n                            LibRule::True => true,\n                            LibRule::Default => true,\n                            LibRule::False => false,\n                        };\n                    }\n                    TargetKind::CustomBuild => return false,\n                };\n                rule.matches(target)\n            }\n        }\n    }\n\n    pub fn is_specific(&self) -> bool {\n        match *self {\n            CompileFilter::Default { .. } => false,\n            CompileFilter::Only { .. } => true,\n        }\n    }\n\n    pub fn is_all_targets(&self) -> bool {\n        matches!(\n            *self,\n            CompileFilter::Only {\n                all_targets: true,\n                ..\n            }\n        )\n    }\n\n    /// Checks if any specified target name contains glob patterns.\n    pub(crate) fn contains_glob_patterns(&self) -> bool {\n        match self {\n            CompileFilter::Default { .. } => false,\n            CompileFilter::Only {\n                bins,\n                examples,\n                tests,\n                benches,\n                ..\n            } => {\n                bins.contains_glob_patterns()\n                    || examples.contains_glob_patterns()\n                    || tests.contains_glob_patterns()\n                    || benches.contains_glob_patterns()\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_compile/mod.rs",
    "content": "//! The entry point for starting the compilation process for commands like\n//! `build`, `test`, `doc`, `rustc`, etc.\n//!\n//! The [`compile`] function will do all the work to compile a workspace. A\n//! rough outline is:\n//!\n//! 1. Resolve the dependency graph (see [`ops::resolve`]).\n//! 2. Download any packages needed (see [`PackageSet`]).\n//! 3. Generate a list of top-level \"units\" of work for the targets the user\n//!   requested on the command-line. Each [`Unit`] corresponds to a compiler\n//!   invocation. This is done in this module ([`UnitGenerator::generate_root_units`]).\n//! 4. Starting from the root [`Unit`]s, generate the [`UnitGraph`] by walking the dependency graph\n//!   from the resolver.  See also [`unit_dependencies`].\n//! 5. Construct the [`BuildContext`] with all of the information collected so\n//!   far. This is the end of the \"front end\" of compilation.\n//! 6. Create a [`BuildRunner`] which coordinates the compilation process\n//!   and will perform the following steps:\n//!     1. Prepare the `target` directory (see [`Layout`]).\n//!     2. Create a [`JobQueue`]. The queue checks the\n//!       fingerprint of each `Unit` to determine if it should run or be\n//!       skipped.\n//!     3. Execute the queue via [`drain_the_queue`]. Each leaf in the queue's dependency graph is\n//!        executed, and then removed from the graph when finished. This repeats until the queue is\n//!        empty.  Note that this is the only point in cargo that currently uses threads.\n//! 7. The result of the compilation is stored in the [`Compilation`] struct. This can be used for\n//!    various things, such as running tests after the compilation  has finished.\n//!\n//! **Note**: \"target\" inside this module generally refers to [\"Cargo Target\"],\n//! which corresponds to artifact that will be built in a package. Not to be\n//! confused with target-triple or target architecture.\n//!\n//! [`unit_dependencies`]: crate::core::compiler::unit_dependencies\n//! [`Layout`]: crate::core::compiler::Layout\n//! [`JobQueue`]: crate::core::compiler::job_queue\n//! [`drain_the_queue`]: crate::core::compiler::job_queue\n//! [\"Cargo Target\"]: https://doc.rust-lang.org/nightly/cargo/reference/cargo-targets.html\n\nuse std::collections::{HashMap, HashSet};\nuse std::hash::{Hash, Hasher};\nuse std::sync::Arc;\n\nuse crate::core::compiler::UnitIndex;\nuse crate::core::compiler::UserIntent;\nuse crate::core::compiler::unit_dependencies::build_unit_dependencies;\nuse crate::core::compiler::unit_graph::{self, UnitDep, UnitGraph};\nuse crate::core::compiler::{BuildConfig, BuildContext, BuildRunner, Compilation};\nuse crate::core::compiler::{CompileKind, CompileTarget, RustcTargetData, Unit};\nuse crate::core::compiler::{CrateType, TargetInfo, apply_env_config, standard_lib};\nuse crate::core::compiler::{DefaultExecutor, Executor, UnitInterner};\nuse crate::core::profiles::Profiles;\nuse crate::core::resolver::features::{self, CliFeatures, FeaturesFor};\nuse crate::core::resolver::{ForceAllTargets, HasDevUnits, Resolve};\nuse crate::core::{PackageId, PackageSet, SourceId, TargetKind, Workspace};\nuse crate::drop_println;\nuse crate::ops;\nuse crate::ops::resolve::{SpecsAndResolvedFeatures, WorkspaceResolve};\nuse crate::util::BuildLogger;\nuse crate::util::context::{GlobalContext, WarningHandling};\nuse crate::util::interning::InternedString;\nuse crate::util::log_message::LogMessage;\nuse crate::util::{CargoResult, StableHasher};\n\nmod compile_filter;\nuse annotate_snippets::{Group, Level, Origin};\npub use compile_filter::{CompileFilter, FilterRule, LibRule};\n\npub(super) mod unit_generator;\nuse itertools::Itertools as _;\nuse unit_generator::UnitGenerator;\n\nmod packages;\n\npub use packages::Packages;\n\n/// Contains information about how a package should be compiled.\n///\n/// Note on distinction between `CompileOptions` and [`BuildConfig`]:\n/// `BuildConfig` contains values that need to be retained after\n/// [`BuildContext`] is created. The other fields are no longer necessary. Think\n/// of it as `CompileOptions` are high-level settings requested on the\n/// command-line, and `BuildConfig` are low-level settings for actually\n/// driving `rustc`.\n#[derive(Debug, Clone)]\npub struct CompileOptions {\n    /// Configuration information for a rustc build\n    pub build_config: BuildConfig,\n    /// Feature flags requested by the user.\n    pub cli_features: CliFeatures,\n    /// A set of packages to build.\n    pub spec: Packages,\n    /// Filter to apply to the root package to select which targets will be\n    /// built.\n    pub filter: CompileFilter,\n    /// Extra arguments to be passed to rustdoc (single target only)\n    pub target_rustdoc_args: Option<Vec<String>>,\n    /// The specified target will be compiled with all the available arguments,\n    /// note that this only accounts for the *final* invocation of rustc\n    pub target_rustc_args: Option<Vec<String>>,\n    /// Crate types to be passed to rustc (single target only)\n    pub target_rustc_crate_types: Option<Vec<String>>,\n    /// Whether the `--document-private-items` flags was specified and should\n    /// be forwarded to `rustdoc`.\n    pub rustdoc_document_private_items: bool,\n    /// Whether the build process should check the minimum Rust version\n    /// defined in the cargo metadata for a crate.\n    pub honor_rust_version: Option<bool>,\n}\n\nimpl CompileOptions {\n    pub fn new(gctx: &GlobalContext, intent: UserIntent) -> CargoResult<CompileOptions> {\n        let jobs = None;\n        let keep_going = false;\n        Ok(CompileOptions {\n            build_config: BuildConfig::new(gctx, jobs, keep_going, &[], intent)?,\n            cli_features: CliFeatures::new_all(false),\n            spec: ops::Packages::Packages(Vec::new()),\n            filter: CompileFilter::Default {\n                required_features_filterable: false,\n            },\n            target_rustdoc_args: None,\n            target_rustc_args: None,\n            target_rustc_crate_types: None,\n            rustdoc_document_private_items: false,\n            honor_rust_version: None,\n        })\n    }\n}\n\n/// Compiles!\n///\n/// This uses the [`DefaultExecutor`]. To use a custom [`Executor`], see [`compile_with_exec`].\npub fn compile<'a>(ws: &Workspace<'a>, options: &CompileOptions) -> CargoResult<Compilation<'a>> {\n    let exec: Arc<dyn Executor> = Arc::new(DefaultExecutor);\n    compile_with_exec(ws, options, &exec)\n}\n\n/// Like [`compile`] but allows specifying a custom [`Executor`]\n/// that will be able to intercept build calls and add custom logic.\n///\n/// [`compile`] uses [`DefaultExecutor`] which just passes calls through.\npub fn compile_with_exec<'a>(\n    ws: &Workspace<'a>,\n    options: &CompileOptions,\n    exec: &Arc<dyn Executor>,\n) -> CargoResult<Compilation<'a>> {\n    ws.emit_warnings()?;\n    let compilation = compile_ws(ws, options, exec)?;\n    if ws.gctx().warning_handling()? == WarningHandling::Deny && compilation.lint_warning_count > 0\n    {\n        anyhow::bail!(\"warnings are denied by `build.warnings` configuration\")\n    }\n    Ok(compilation)\n}\n\n/// Like [`compile_with_exec`] but without warnings from manifest parsing.\n#[tracing::instrument(skip_all)]\npub fn compile_ws<'a>(\n    ws: &Workspace<'a>,\n    options: &CompileOptions,\n    exec: &Arc<dyn Executor>,\n) -> CargoResult<Compilation<'a>> {\n    let interner = UnitInterner::new();\n    let logger = BuildLogger::maybe_new(ws, &options.build_config)?;\n\n    if let Some(ref logger) = logger {\n        let rustc = ws.gctx().load_global_rustc(Some(ws))?;\n        let num_cpus = std::thread::available_parallelism()\n            .ok()\n            .map(|x| x.get() as u64);\n        logger.log(LogMessage::BuildStarted {\n            command: std::env::args_os()\n                .map(|arg| arg.to_string_lossy().into_owned())\n                .collect(),\n            cwd: ws.gctx().cwd().to_path_buf(),\n            host: rustc.host.to_string(),\n            jobs: options.build_config.jobs,\n            num_cpus,\n            profile: options.build_config.requested_profile.to_string(),\n            rustc_version: rustc.version.to_string(),\n            rustc_version_verbose: rustc.verbose_version.clone(),\n            target_dir: ws.target_dir().as_path_unlocked().to_path_buf(),\n            workspace_root: ws.root().to_path_buf(),\n        });\n    }\n\n    let bcx = create_bcx(ws, options, &interner, logger.as_ref())?;\n\n    if options.build_config.unit_graph {\n        unit_graph::emit_serialized_unit_graph(&bcx.roots, &bcx.unit_graph, ws.gctx())?;\n        return Compilation::new(&bcx);\n    }\n    crate::core::gc::auto_gc(bcx.gctx);\n    let build_runner = BuildRunner::new(&bcx)?;\n    if options.build_config.dry_run {\n        build_runner.dry_run()\n    } else {\n        build_runner.compile(exec)\n    }\n}\n\n/// Executes `rustc --print <VALUE>`.\n///\n/// * `print_opt_value` is the VALUE passed through.\npub fn print<'a>(\n    ws: &Workspace<'a>,\n    options: &CompileOptions,\n    print_opt_value: &str,\n) -> CargoResult<()> {\n    let CompileOptions {\n        ref build_config,\n        ref target_rustc_args,\n        ..\n    } = *options;\n    let gctx = ws.gctx();\n    let rustc = gctx.load_global_rustc(Some(ws))?;\n    for (index, kind) in build_config.requested_kinds.iter().enumerate() {\n        if index != 0 {\n            drop_println!(gctx);\n        }\n        let target_info = TargetInfo::new(gctx, &build_config.requested_kinds, &rustc, *kind)?;\n        let mut process = rustc.process();\n        apply_env_config(gctx, &mut process)?;\n        process.args(&target_info.rustflags);\n        if let Some(args) = target_rustc_args {\n            process.args(args);\n        }\n        kind.add_target_arg(&mut process);\n        process.arg(\"--print\").arg(print_opt_value);\n        process.exec()?;\n    }\n    Ok(())\n}\n\n/// Prepares all required information for the actual compilation.\n///\n/// For how it works and what data it collects,\n/// please see the [module-level documentation](self).\n#[tracing::instrument(skip_all)]\npub fn create_bcx<'a, 'gctx>(\n    ws: &'a Workspace<'gctx>,\n    options: &'a CompileOptions,\n    interner: &'a UnitInterner,\n    logger: Option<&'a BuildLogger>,\n) -> CargoResult<BuildContext<'a, 'gctx>> {\n    let CompileOptions {\n        ref build_config,\n        ref spec,\n        ref cli_features,\n        ref filter,\n        ref target_rustdoc_args,\n        ref target_rustc_args,\n        ref target_rustc_crate_types,\n        rustdoc_document_private_items,\n        honor_rust_version,\n    } = *options;\n    let gctx = ws.gctx();\n\n    // Perform some pre-flight validation.\n    match build_config.intent {\n        UserIntent::Test | UserIntent::Build | UserIntent::Check { .. } | UserIntent::Bench => {\n            if ws.gctx().get_env(\"RUST_FLAGS\").is_ok() {\n                gctx.shell().print_report(\n                    &[Level::WARNING\n                        .secondary_title(\"ignoring environment variable `RUST_FLAGS`\")\n                        .element(Level::HELP.message(\"rust flags are passed via `RUSTFLAGS`\"))],\n                    false,\n                )?;\n            }\n        }\n        UserIntent::Doc { .. } | UserIntent::Doctest => {\n            if ws.gctx().get_env(\"RUSTDOC_FLAGS\").is_ok() {\n                gctx.shell().print_report(\n                    &[Level::WARNING\n                        .secondary_title(\"ignoring environment variable `RUSTDOC_FLAGS`\")\n                        .element(\n                            Level::HELP.message(\"rustdoc flags are passed via `RUSTDOCFLAGS`\"),\n                        )],\n                    false,\n                )?;\n            }\n        }\n    }\n    gctx.validate_term_config()?;\n\n    let mut target_data = RustcTargetData::new(ws, &build_config.requested_kinds)?;\n\n    let specs = spec.to_package_id_specs(ws)?;\n    let has_dev_units = {\n        // Rustdoc itself doesn't need dev-dependencies. But to scrape examples from packages in the\n        // workspace, if any of those packages need dev-dependencies, then we need include dev-dependencies\n        // to scrape those packages.\n        let any_pkg_has_scrape_enabled = ws\n            .members_with_features(&specs, cli_features)?\n            .iter()\n            .any(|(pkg, _)| {\n                pkg.targets()\n                    .iter()\n                    .any(|target| target.is_example() && target.doc_scrape_examples().is_enabled())\n            });\n\n        if filter.need_dev_deps(build_config.intent)\n            || (build_config.intent.is_doc() && any_pkg_has_scrape_enabled)\n        {\n            HasDevUnits::Yes\n        } else {\n            HasDevUnits::No\n        }\n    };\n    let dry_run = false;\n\n    if let Some(logger) = logger {\n        let elapsed = ws.gctx().creation_time().elapsed().as_secs_f64();\n        logger.log(LogMessage::ResolutionStarted { elapsed });\n    }\n\n    let resolve = ops::resolve_ws_with_opts(\n        ws,\n        &mut target_data,\n        &build_config.requested_kinds,\n        cli_features,\n        &specs,\n        has_dev_units,\n        ForceAllTargets::No,\n        dry_run,\n    )?;\n    let WorkspaceResolve {\n        mut pkg_set,\n        workspace_resolve,\n        targeted_resolve: resolve,\n        specs_and_features,\n    } = resolve;\n\n    if let Some(logger) = logger {\n        let elapsed = ws.gctx().creation_time().elapsed().as_secs_f64();\n        logger.log(LogMessage::ResolutionFinished { elapsed });\n    }\n\n    let std_resolve_features = if let Some(crates) = &gctx.cli_unstable().build_std {\n        let (std_package_set, std_resolve, std_features) = standard_lib::resolve_std(\n            ws,\n            &mut target_data,\n            &build_config,\n            crates,\n            &build_config.requested_kinds,\n        )?;\n        pkg_set.add_set(std_package_set);\n        Some((std_resolve, std_features))\n    } else {\n        None\n    };\n\n    // Find the packages in the resolver that the user wants to build (those\n    // passed in with `-p` or the defaults from the workspace), and convert\n    // Vec<PackageIdSpec> to a Vec<PackageId>.\n    let to_build_ids = resolve.specs_to_ids(&specs)?;\n    // Now get the `Package` for each `PackageId`. This may trigger a download\n    // if the user specified `-p` for a dependency that is not downloaded.\n    // Dependencies will be downloaded during build_unit_dependencies.\n    let mut to_builds = pkg_set.get_many(to_build_ids)?;\n\n    // The ordering here affects some error messages coming out of cargo, so\n    // let's be test and CLI friendly by always printing in the same order if\n    // there's an error.\n    to_builds.sort_by_key(|p| p.package_id());\n\n    for pkg in to_builds.iter() {\n        pkg.manifest().print_teapot(gctx);\n\n        if build_config.intent.is_any_test()\n            && !ws.is_member(pkg)\n            && pkg.dependencies().iter().any(|dep| !dep.is_transitive())\n        {\n            anyhow::bail!(\n                \"package `{}` cannot be tested because it requires dev-dependencies \\\n                 and is not a member of the workspace\",\n                pkg.name()\n            );\n        }\n    }\n\n    let (extra_args, extra_args_name) = match (target_rustc_args, target_rustdoc_args) {\n        (Some(args), _) => (Some(args.clone()), \"rustc\"),\n        (_, Some(args)) => (Some(args.clone()), \"rustdoc\"),\n        _ => (None, \"\"),\n    };\n\n    if extra_args.is_some() && to_builds.len() != 1 {\n        panic!(\n            \"`{}` should not accept multiple `-p` flags\",\n            extra_args_name\n        );\n    }\n\n    let profiles = Profiles::new(ws, build_config.requested_profile)?;\n    profiles.validate_packages(\n        ws.profiles(),\n        &mut gctx.shell(),\n        workspace_resolve.as_ref().unwrap_or(&resolve),\n    )?;\n\n    // If `--target` has not been specified, then the unit graph is built\n    // assuming `--target $HOST` was specified. See\n    // `rebuild_unit_graph_shared` for more on why this is done.\n    let explicit_host_kind = CompileKind::Target(CompileTarget::new(\n        &target_data.rustc.host,\n        gctx.cli_unstable().json_target_spec,\n    )?);\n    let explicit_host_kinds: Vec<_> = build_config\n        .requested_kinds\n        .iter()\n        .map(|kind| match kind {\n            CompileKind::Host => explicit_host_kind,\n            CompileKind::Target(t) => CompileKind::Target(*t),\n        })\n        .collect();\n\n    let mut root_units = Vec::new();\n    let mut unit_graph = HashMap::new();\n    let mut scrape_units = Vec::new();\n\n    if let Some(logger) = logger {\n        let elapsed = ws.gctx().creation_time().elapsed().as_secs_f64();\n        logger.log(LogMessage::UnitGraphStarted { elapsed });\n    }\n\n    for SpecsAndResolvedFeatures {\n        specs,\n        resolved_features,\n    } in &specs_and_features\n    {\n        // Passing `build_config.requested_kinds` instead of\n        // `explicit_host_kinds` here so that `generate_root_units` can do\n        // its own special handling of `CompileKind::Host`. It will\n        // internally replace the host kind by the `explicit_host_kind`\n        // before setting as a unit.\n        let spec_names = specs.iter().map(|spec| spec.name()).collect::<Vec<_>>();\n        let packages = to_builds\n            .iter()\n            .filter(|package| spec_names.contains(&package.name().as_str()))\n            .cloned()\n            .collect::<Vec<_>>();\n        let generator = UnitGenerator {\n            ws,\n            packages: &packages,\n            spec,\n            target_data: &target_data,\n            filter,\n            requested_kinds: &build_config.requested_kinds,\n            explicit_host_kind,\n            intent: build_config.intent,\n            resolve: &resolve,\n            workspace_resolve: &workspace_resolve,\n            resolved_features: &resolved_features,\n            package_set: &pkg_set,\n            profiles: &profiles,\n            interner,\n            has_dev_units,\n        };\n        let mut targeted_root_units = generator.generate_root_units()?;\n\n        if let Some(args) = target_rustc_crate_types {\n            override_rustc_crate_types(&mut targeted_root_units, args, interner)?;\n        }\n\n        let should_scrape =\n            build_config.intent.is_doc() && gctx.cli_unstable().rustdoc_scrape_examples;\n        let targeted_scrape_units = if should_scrape {\n            generator.generate_scrape_units(&targeted_root_units)?\n        } else {\n            Vec::new()\n        };\n\n        let std_roots = if let Some(crates) = gctx.cli_unstable().build_std.as_ref() {\n            let (std_resolve, std_features) = std_resolve_features.as_ref().unwrap();\n            standard_lib::generate_std_roots(\n                &crates,\n                &targeted_root_units,\n                std_resolve,\n                std_features,\n                &explicit_host_kinds,\n                &pkg_set,\n                interner,\n                &profiles,\n                &target_data,\n            )?\n        } else {\n            Default::default()\n        };\n\n        unit_graph.extend(build_unit_dependencies(\n            ws,\n            &pkg_set,\n            &resolve,\n            &resolved_features,\n            std_resolve_features.as_ref(),\n            &targeted_root_units,\n            &targeted_scrape_units,\n            &std_roots,\n            build_config.intent,\n            &target_data,\n            &profiles,\n            interner,\n        )?);\n        root_units.extend(targeted_root_units);\n        scrape_units.extend(targeted_scrape_units);\n    }\n\n    // TODO: In theory, Cargo should also dedupe the roots, but I'm uncertain\n    // what heuristics to use in that case.\n    if build_config.intent.wants_deps_docs() {\n        remove_duplicate_doc(build_config, &root_units, &mut unit_graph);\n    }\n\n    let host_kind_requested = build_config\n        .requested_kinds\n        .iter()\n        .any(CompileKind::is_host);\n    // Rebuild the unit graph, replacing the explicit host targets with\n    // CompileKind::Host, removing `artifact_target_for_features` and merging any dependencies\n    // shared with build and artifact dependencies.\n    //\n    // NOTE: after this point, all units and the unit graph must be immutable.\n    let (root_units, scrape_units, unit_graph) = rebuild_unit_graph_shared(\n        interner,\n        unit_graph,\n        &root_units,\n        &scrape_units,\n        host_kind_requested.then_some(explicit_host_kind),\n        build_config.compile_time_deps_only,\n    );\n\n    let units: Vec<_> = unit_graph.keys().sorted().collect();\n    let unit_to_index: HashMap<_, _> = units\n        .iter()\n        .enumerate()\n        .map(|(i, &unit)| (unit.clone(), UnitIndex(i as u64)))\n        .collect();\n\n    if let Some(logger) = logger {\n        let root_unit_indexes: HashSet<_> =\n            root_units.iter().map(|unit| unit_to_index[&unit]).collect();\n\n        for (index, unit) in units.into_iter().enumerate() {\n            let index = UnitIndex(index as u64);\n            let dependencies = unit_graph\n                .get(unit)\n                .map(|deps| {\n                    deps.iter()\n                        .filter_map(|dep| unit_to_index.get(&dep.unit).copied())\n                        .collect()\n                })\n                .unwrap_or_default();\n            logger.log(LogMessage::UnitRegistered {\n                package_id: unit.pkg.package_id().to_spec(),\n                target: (&unit.target).into(),\n                mode: unit.mode,\n                platform: target_data.short_name(&unit.kind).to_owned(),\n                index,\n                features: unit\n                    .features\n                    .iter()\n                    .map(|s| s.as_str().to_owned())\n                    .collect(),\n                requested: root_unit_indexes.contains(&index),\n                dependencies,\n            });\n        }\n        let elapsed = ws.gctx().creation_time().elapsed().as_secs_f64();\n        logger.log(LogMessage::UnitGraphFinished { elapsed });\n    }\n\n    let mut extra_compiler_args = HashMap::new();\n    if let Some(args) = extra_args {\n        if root_units.len() != 1 {\n            anyhow::bail!(\n                \"extra arguments to `{}` can only be passed to one \\\n                 target, consider filtering\\nthe package by passing, \\\n                 e.g., `--lib` or `--bin NAME` to specify a single target\",\n                extra_args_name\n            );\n        }\n        extra_compiler_args.insert(root_units[0].clone(), args);\n    }\n\n    for unit in root_units\n        .iter()\n        .filter(|unit| unit.mode.is_doc() || unit.mode.is_doc_test())\n        .filter(|unit| rustdoc_document_private_items || unit.target.is_bin())\n    {\n        // Add `--document-private-items` rustdoc flag if requested or if\n        // the target is a binary. Binary crates get their private items\n        // documented by default.\n        let mut args = vec![\"--document-private-items\".into()];\n        if unit.target.is_bin() {\n            // This warning only makes sense if it's possible to document private items\n            // sometimes and ignore them at other times. But cargo consistently passes\n            // `--document-private-items`, so the warning isn't useful.\n            args.push(\"-Arustdoc::private-intra-doc-links\".into());\n        }\n        extra_compiler_args\n            .entry(unit.clone())\n            .or_default()\n            .extend(args);\n    }\n\n    // Validate target src path for each root unit\n    let mut error_count: usize = 0;\n    for unit in &root_units {\n        if let Some(target_src_path) = unit.target.src_path().path() {\n            validate_target_path_as_source_file(\n                gctx,\n                target_src_path,\n                unit.target.name(),\n                unit.target.kind(),\n                unit.pkg.manifest_path(),\n                &mut error_count,\n            )?\n        }\n    }\n    if error_count > 0 {\n        let plural: &str = if error_count > 1 { \"s\" } else { \"\" };\n        anyhow::bail!(\n            \"could not compile due to {error_count} previous target resolution error{plural}\"\n        );\n    }\n\n    if honor_rust_version.unwrap_or(true) {\n        let rustc_version = target_data.rustc.version.clone().into();\n\n        let mut incompatible = Vec::new();\n        let mut local_incompatible = false;\n        for unit in unit_graph.keys() {\n            let Some(pkg_msrv) = unit.pkg.rust_version() else {\n                continue;\n            };\n\n            if pkg_msrv.is_compatible_with(&rustc_version) {\n                continue;\n            }\n\n            local_incompatible |= unit.is_local();\n            incompatible.push((unit, pkg_msrv));\n        }\n        if !incompatible.is_empty() {\n            use std::fmt::Write as _;\n\n            let plural = if incompatible.len() == 1 { \"\" } else { \"s\" };\n            let mut message = format!(\n                \"rustc {rustc_version} is not supported by the following package{plural}:\\n\"\n            );\n            incompatible.sort_by_key(|(unit, _)| (unit.pkg.name(), unit.pkg.version()));\n            for (unit, msrv) in incompatible {\n                let name = &unit.pkg.name();\n                let version = &unit.pkg.version();\n                writeln!(&mut message, \"  {name}@{version} requires rustc {msrv}\").unwrap();\n            }\n            if ws.is_ephemeral() {\n                if ws.ignore_lock() {\n                    writeln!(\n                        &mut message,\n                        \"Try re-running `cargo install` with `--locked`\"\n                    )\n                    .unwrap();\n                }\n            } else if !local_incompatible {\n                writeln!(\n                    &mut message,\n                    \"Either upgrade rustc or select compatible dependency versions with\n`cargo update <name>@<current-ver> --precise <compatible-ver>`\nwhere `<compatible-ver>` is the latest version supporting rustc {rustc_version}\",\n                )\n                .unwrap();\n            }\n            return Err(anyhow::Error::msg(message));\n        }\n    }\n\n    let bcx = BuildContext::new(\n        ws,\n        logger,\n        pkg_set,\n        build_config,\n        profiles,\n        extra_compiler_args,\n        target_data,\n        root_units,\n        unit_graph,\n        unit_to_index,\n        scrape_units,\n    )?;\n\n    Ok(bcx)\n}\n\n// Checks if a target path exists and is a source file, not a directory\nfn validate_target_path_as_source_file(\n    gctx: &GlobalContext,\n    target_path: &std::path::Path,\n    target_name: &str,\n    target_kind: &TargetKind,\n    unit_manifest_path: &std::path::Path,\n    error_count: &mut usize,\n) -> CargoResult<()> {\n    if !target_path.exists() {\n        *error_count += 1;\n\n        let err_msg = format!(\n            \"can't find {} `{}` at path `{}`\",\n            target_kind.description(),\n            target_name,\n            target_path.display()\n        );\n\n        let group = Group::with_title(Level::ERROR.primary_title(err_msg)).element(Origin::path(\n            unit_manifest_path.to_str().unwrap_or_default(),\n        ));\n\n        gctx.shell().print_report(&[group], true)?;\n    } else if target_path.is_dir() {\n        *error_count += 1;\n\n        // suggest setting the path to a likely entrypoint\n        let main_rs = target_path.join(\"main.rs\");\n        let lib_rs = target_path.join(\"lib.rs\");\n\n        let suggested_files_opt = match target_kind {\n            TargetKind::Lib(_) => {\n                if lib_rs.exists() {\n                    Some(format!(\"`{}`\", lib_rs.display()))\n                } else {\n                    None\n                }\n            }\n            TargetKind::Bin => {\n                if main_rs.exists() {\n                    Some(format!(\"`{}`\", main_rs.display()))\n                } else {\n                    None\n                }\n            }\n            TargetKind::Test => {\n                if main_rs.exists() {\n                    Some(format!(\"`{}`\", main_rs.display()))\n                } else {\n                    None\n                }\n            }\n            TargetKind::ExampleBin => {\n                if main_rs.exists() {\n                    Some(format!(\"`{}`\", main_rs.display()))\n                } else {\n                    None\n                }\n            }\n            TargetKind::Bench => {\n                if main_rs.exists() {\n                    Some(format!(\"`{}`\", main_rs.display()))\n                } else {\n                    None\n                }\n            }\n            TargetKind::ExampleLib(_) => {\n                if lib_rs.exists() {\n                    Some(format!(\"`{}`\", lib_rs.display()))\n                } else {\n                    None\n                }\n            }\n            TargetKind::CustomBuild => None,\n        };\n\n        let err_msg = format!(\n            \"path `{}` for {} `{}` is a directory, but a source file was expected.\",\n            target_path.display(),\n            target_kind.description(),\n            target_name,\n        );\n        let mut group = Group::with_title(Level::ERROR.primary_title(err_msg)).element(\n            Origin::path(unit_manifest_path.to_str().unwrap_or_default()),\n        );\n\n        if let Some(suggested_files) = suggested_files_opt {\n            group = group.element(\n                Level::HELP.message(format!(\"an entry point exists at {}\", suggested_files)),\n            );\n        }\n\n        gctx.shell().print_report(&[group], true)?;\n    }\n\n    Ok(())\n}\n\n/// This is used to rebuild the unit graph, sharing host dependencies if possible,\n/// and applying other unit adjustments based on the whole graph.\n///\n/// This will translate any unit's `CompileKind::Target(host)` to\n/// `CompileKind::Host` if `to_host` is not `None` and the kind is equal to `to_host`.\n/// This also handles generating the unit `dep_hash`, and merging shared units if possible.\n///\n/// This is necessary because if normal dependencies used `CompileKind::Host`,\n/// there would be no way to distinguish those units from build-dependency\n/// units or artifact dependency units.\n/// This can cause a problem if a shared normal/build/artifact dependency needs\n/// to link to another dependency whose features differ based on whether or\n/// not it is a normal, build or artifact dependency. If all units used\n/// `CompileKind::Host`, then they would end up being identical, causing a\n/// collision in the `UnitGraph`, and Cargo would end up randomly choosing one\n/// value or the other.\n///\n/// The solution is to keep normal, build and artifact dependencies separate when\n/// building the unit graph, and then run this second pass which will try to\n/// combine shared dependencies safely. By adding a hash of the dependencies\n/// to the `Unit`, this allows the `CompileKind` to be changed back to `Host`\n/// and `artifact_target_for_features` to be removed without fear of an unwanted\n/// collision for build or artifact dependencies.\n///\n/// This is also responsible for adjusting the `strip` profile option to\n/// opportunistically strip if debug is 0 for all dependencies. This helps\n/// remove debuginfo added by the standard library.\n///\n/// This is also responsible for adjusting the `debug` setting for host\n/// dependencies, turning off debug if the user has not explicitly enabled it,\n/// and the unit is not shared with a target unit.\n///\n/// This is also responsible for adjusting whether each unit should be compiled\n/// or not regarding `--compile-time-deps` flag.\nfn rebuild_unit_graph_shared(\n    interner: &UnitInterner,\n    unit_graph: UnitGraph,\n    roots: &[Unit],\n    scrape_units: &[Unit],\n    to_host: Option<CompileKind>,\n    compile_time_deps_only: bool,\n) -> (Vec<Unit>, Vec<Unit>, UnitGraph) {\n    let mut result = UnitGraph::new();\n    // Map of the old unit to the new unit, used to avoid recursing into units\n    // that have already been computed to improve performance.\n    let mut memo = HashMap::new();\n    let new_roots = roots\n        .iter()\n        .map(|root| {\n            traverse_and_share(\n                interner,\n                &mut memo,\n                &mut result,\n                &unit_graph,\n                root,\n                true,\n                false,\n                to_host,\n                compile_time_deps_only,\n            )\n        })\n        .collect();\n    // If no unit in the unit graph ended up having scrape units attached as dependencies,\n    // then they won't have been discovered in traverse_and_share and hence won't be in\n    // memo. So we filter out missing scrape units.\n    let new_scrape_units = scrape_units\n        .iter()\n        .map(|unit| memo.get(unit).unwrap().clone())\n        .collect();\n    (new_roots, new_scrape_units, result)\n}\n\n/// Recursive function for rebuilding the graph.\n///\n/// This walks `unit_graph`, starting at the given `unit`. It inserts the new\n/// units into `new_graph`, and returns a new updated version of the given\n/// unit (`dep_hash` is filled in, and `kind` switched if necessary).\nfn traverse_and_share(\n    interner: &UnitInterner,\n    memo: &mut HashMap<Unit, Unit>,\n    new_graph: &mut UnitGraph,\n    unit_graph: &UnitGraph,\n    unit: &Unit,\n    unit_is_root: bool,\n    unit_is_for_host: bool,\n    to_host: Option<CompileKind>,\n    compile_time_deps_only: bool,\n) -> Unit {\n    if let Some(new_unit) = memo.get(unit) {\n        // Already computed, no need to recompute.\n        return new_unit.clone();\n    }\n    let mut dep_hash = StableHasher::new();\n    let skip_non_compile_time_deps = compile_time_deps_only\n        && (!unit.target.is_compile_time_dependency() ||\n            // Root unit is not a dependency unless other units are dependant\n            // to it.\n            unit_is_root);\n    let new_deps: Vec<_> = unit_graph[unit]\n        .iter()\n        .map(|dep| {\n            let new_dep_unit = traverse_and_share(\n                interner,\n                memo,\n                new_graph,\n                unit_graph,\n                &dep.unit,\n                false,\n                dep.unit_for.is_for_host(),\n                to_host,\n                // If we should compile the current unit, we should also compile\n                // its dependencies. And if not, we should compile compile time\n                // dependencies only.\n                skip_non_compile_time_deps,\n            );\n            new_dep_unit.hash(&mut dep_hash);\n            UnitDep {\n                unit: new_dep_unit,\n                ..dep.clone()\n            }\n        })\n        .collect();\n    // Here, we have recursively traversed this unit's dependencies, and hashed them: we can\n    // finalize the dep hash.\n    let new_dep_hash = Hasher::finish(&dep_hash);\n\n    // This is the key part of the sharing process: if the unit is a runtime dependency, whose\n    // target is the same as the host, we canonicalize the compile kind to `CompileKind::Host`.\n    // A possible host dependency counterpart to this unit would have that kind, and if such a unit\n    // exists in the current `unit_graph`, they will unify in the new unit graph map `new_graph`.\n    // The resulting unit graph will be optimized with less units, thanks to sharing these host\n    // dependencies.\n    let canonical_kind = match to_host {\n        Some(to_host) if to_host == unit.kind => CompileKind::Host,\n        _ => unit.kind,\n    };\n\n    let mut profile = unit.profile.clone();\n    if profile.strip.is_deferred() {\n        // If strip was not manually set, and all dependencies of this unit together\n        // with this unit have debuginfo turned off, we enable debuginfo stripping.\n        // This will remove pre-existing debug symbols coming from the standard library.\n        if !profile.debuginfo.is_turned_on()\n            && new_deps\n                .iter()\n                .all(|dep| !dep.unit.profile.debuginfo.is_turned_on())\n        {\n            profile.strip = profile.strip.strip_debuginfo();\n        }\n    }\n\n    // If this is a build dependency, and it's not shared with runtime dependencies, we can weaken\n    // its debuginfo level to optimize build times. We do nothing if it's an artifact dependency,\n    // as it and its debuginfo may end up embedded in the main program.\n    if unit_is_for_host\n        && to_host.is_some()\n        && profile.debuginfo.is_deferred()\n        && !unit.artifact.is_true()\n    {\n        // We create a \"probe\" test to see if a unit with the same explicit debuginfo level exists\n        // in the graph. This is the level we'd expect if it was set manually or the default value\n        // set by a profile for a runtime dependency: its canonical value.\n        let canonical_debuginfo = profile.debuginfo.finalize();\n        let mut canonical_profile = profile.clone();\n        canonical_profile.debuginfo = canonical_debuginfo;\n        let unit_probe = interner.intern(\n            &unit.pkg,\n            &unit.target,\n            canonical_profile,\n            to_host.unwrap(),\n            unit.mode,\n            unit.features.clone(),\n            unit.rustflags.clone(),\n            unit.rustdocflags.clone(),\n            unit.links_overrides.clone(),\n            unit.is_std,\n            unit.dep_hash,\n            unit.artifact,\n            unit.artifact_target_for_features,\n            unit.skip_non_compile_time_dep,\n        );\n\n        // We can now turn the deferred value into its actual final value.\n        profile.debuginfo = if unit_graph.contains_key(&unit_probe) {\n            // The unit is present in both build time and runtime subgraphs: we canonicalize its\n            // level to the other unit's, thus ensuring reuse between the two to optimize build times.\n            canonical_debuginfo\n        } else {\n            // The unit is only present in the build time subgraph, we can weaken its debuginfo\n            // level to optimize build times.\n            canonical_debuginfo.weaken()\n        }\n    }\n\n    let new_unit = interner.intern(\n        &unit.pkg,\n        &unit.target,\n        profile,\n        canonical_kind,\n        unit.mode,\n        unit.features.clone(),\n        unit.rustflags.clone(),\n        unit.rustdocflags.clone(),\n        unit.links_overrides.clone(),\n        unit.is_std,\n        new_dep_hash,\n        unit.artifact,\n        // Since `dep_hash` is now filled in, there's no need to specify the artifact target\n        // for target-dependent feature resolution\n        None,\n        skip_non_compile_time_deps,\n    );\n    if !unit_is_root || !compile_time_deps_only {\n        assert!(memo.insert(unit.clone(), new_unit.clone()).is_none());\n    }\n    new_graph.entry(new_unit.clone()).or_insert(new_deps);\n    new_unit\n}\n\n/// Removes duplicate `CompileMode::Doc` units that would cause problems with\n/// filename collisions.\n///\n/// Rustdoc only separates units by crate name in the file directory\n/// structure. If any two units with the same crate name exist, this would\n/// cause a filename collision, causing different rustdoc invocations to stomp\n/// on one another's files.\n///\n/// Unfortunately this does not remove all duplicates, as some of them are\n/// either user error, or difficult to remove. Cases that I can think of:\n///\n/// - Same target name in different packages. See the `collision_doc` test.\n/// - Different sources. See `collision_doc_sources` test.\n///\n/// Ideally this would not be necessary.\nfn remove_duplicate_doc(\n    build_config: &BuildConfig,\n    root_units: &[Unit],\n    unit_graph: &mut UnitGraph,\n) {\n    // First, create a mapping of crate_name -> Unit so we can see where the\n    // duplicates are.\n    let mut all_docs: HashMap<String, Vec<Unit>> = HashMap::new();\n    for unit in unit_graph.keys() {\n        if unit.mode.is_doc() {\n            all_docs\n                .entry(unit.target.crate_name())\n                .or_default()\n                .push(unit.clone());\n        }\n    }\n    // Keep track of units to remove so that they can be efficiently removed\n    // from the unit_deps.\n    let mut removed_units: HashSet<Unit> = HashSet::new();\n    let mut remove = |units: Vec<Unit>, reason: &str, cb: &dyn Fn(&Unit) -> bool| -> Vec<Unit> {\n        let (to_remove, remaining_units): (Vec<Unit>, Vec<Unit>) = units\n            .into_iter()\n            .partition(|unit| cb(unit) && !root_units.contains(unit));\n        for unit in to_remove {\n            tracing::debug!(\n                \"removing duplicate doc due to {} for package {} target `{}`\",\n                reason,\n                unit.pkg,\n                unit.target.name()\n            );\n            unit_graph.remove(&unit);\n            removed_units.insert(unit);\n        }\n        remaining_units\n    };\n    // Iterate over the duplicates and try to remove them from unit_graph.\n    for (_crate_name, mut units) in all_docs {\n        if units.len() == 1 {\n            continue;\n        }\n        // Prefer target over host if --target was not specified.\n        if build_config\n            .requested_kinds\n            .iter()\n            .all(CompileKind::is_host)\n        {\n            // Note these duplicates may not be real duplicates, since they\n            // might get merged in rebuild_unit_graph_shared. Either way, it\n            // shouldn't hurt to remove them early (although the report in the\n            // log might be confusing).\n            units = remove(units, \"host/target merger\", &|unit| unit.kind.is_host());\n            if units.len() == 1 {\n                continue;\n            }\n        }\n        // Prefer newer versions over older.\n        let mut source_map: HashMap<(InternedString, SourceId, CompileKind), Vec<Unit>> =\n            HashMap::new();\n        for unit in units {\n            let pkg_id = unit.pkg.package_id();\n            // Note, this does not detect duplicates from different sources.\n            source_map\n                .entry((pkg_id.name(), pkg_id.source_id(), unit.kind))\n                .or_default()\n                .push(unit);\n        }\n        let mut remaining_units = Vec::new();\n        for (_key, mut units) in source_map {\n            if units.len() > 1 {\n                units.sort_by(|a, b| a.pkg.version().partial_cmp(b.pkg.version()).unwrap());\n                // Remove any entries with version < newest.\n                let newest_version = units.last().unwrap().pkg.version().clone();\n                let keep_units = remove(units, \"older version\", &|unit| {\n                    unit.pkg.version() < &newest_version\n                });\n                remaining_units.extend(keep_units);\n            } else {\n                remaining_units.extend(units);\n            }\n        }\n        if remaining_units.len() == 1 {\n            continue;\n        }\n        // Are there other heuristics to remove duplicates that would make\n        // sense? Maybe prefer path sources over all others?\n    }\n    // Also remove units from the unit_deps so there aren't any dangling edges.\n    for unit_deps in unit_graph.values_mut() {\n        unit_deps.retain(|unit_dep| !removed_units.contains(&unit_dep.unit));\n    }\n    // Remove any orphan units that were detached from the graph.\n    let mut visited = HashSet::new();\n    fn visit(unit: &Unit, graph: &UnitGraph, visited: &mut HashSet<Unit>) {\n        if !visited.insert(unit.clone()) {\n            return;\n        }\n        for dep in &graph[unit] {\n            visit(&dep.unit, graph, visited);\n        }\n    }\n    for unit in root_units {\n        visit(unit, unit_graph, &mut visited);\n    }\n    unit_graph.retain(|unit, _| visited.contains(unit));\n}\n\n/// Override crate types for given units.\n///\n/// This is primarily used by `cargo rustc --crate-type`.\nfn override_rustc_crate_types(\n    units: &mut [Unit],\n    args: &[String],\n    interner: &UnitInterner,\n) -> CargoResult<()> {\n    if units.len() != 1 {\n        anyhow::bail!(\n            \"crate types to rustc can only be passed to one \\\n            target, consider filtering\\nthe package by passing, \\\n            e.g., `--lib` or `--example` to specify a single target\"\n        );\n    }\n\n    let unit = &units[0];\n    let override_unit = |f: fn(Vec<CrateType>) -> TargetKind| {\n        let crate_types = args.iter().map(|s| s.into()).collect();\n        let mut target = unit.target.clone();\n        target.set_kind(f(crate_types));\n        interner.intern(\n            &unit.pkg,\n            &target,\n            unit.profile.clone(),\n            unit.kind,\n            unit.mode,\n            unit.features.clone(),\n            unit.rustflags.clone(),\n            unit.rustdocflags.clone(),\n            unit.links_overrides.clone(),\n            unit.is_std,\n            unit.dep_hash,\n            unit.artifact,\n            unit.artifact_target_for_features,\n            unit.skip_non_compile_time_dep,\n        )\n    };\n    units[0] = match unit.target.kind() {\n        TargetKind::Lib(_) => override_unit(TargetKind::Lib),\n        TargetKind::ExampleLib(_) => override_unit(TargetKind::ExampleLib),\n        _ => {\n            anyhow::bail!(\n                \"crate types can only be specified for libraries and example libraries.\\n\\\n                Binaries, tests, and benchmarks are always the `bin` crate type\"\n            );\n        }\n    };\n\n    Ok(())\n}\n\n/// Gets all of the features enabled for a package, plus its dependencies'\n/// features.\n///\n/// Dependencies are added as `dep_name/feat_name` because `required-features`\n/// wants to support that syntax.\npub fn resolve_all_features(\n    resolve_with_overrides: &Resolve,\n    resolved_features: &features::ResolvedFeatures,\n    package_set: &PackageSet<'_>,\n    package_id: PackageId,\n    has_dev_units: HasDevUnits,\n    requested_kinds: &[CompileKind],\n    target_data: &RustcTargetData<'_>,\n    force_all_targets: ForceAllTargets,\n) -> HashSet<String> {\n    let mut features: HashSet<String> = resolved_features\n        .activated_features(package_id, FeaturesFor::NormalOrDev)\n        .iter()\n        .map(|s| s.to_string())\n        .collect();\n\n    // Include features enabled for use by dependencies so targets can also use them with the\n    // required-features field when deciding whether to be built or skipped.\n    let filtered_deps = PackageSet::filter_deps(\n        package_id,\n        resolve_with_overrides,\n        has_dev_units,\n        requested_kinds,\n        target_data,\n        force_all_targets,\n    );\n    for (dep_id, deps) in filtered_deps {\n        let is_proc_macro = package_set\n            .get_one(dep_id)\n            .expect(\"packages downloaded\")\n            .proc_macro();\n        for dep in deps {\n            let features_for = FeaturesFor::from_for_host(is_proc_macro || dep.is_build());\n            for feature in resolved_features\n                .activated_features_unverified(dep_id, features_for)\n                .unwrap_or_default()\n            {\n                features.insert(format!(\"{}/{}\", dep.name_in_toml(), feature));\n            }\n        }\n    }\n\n    features\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_compile/packages.rs",
    "content": "//! See [`Packages`].\n\nuse std::collections::BTreeSet;\n\nuse crate::core::{Package, PackageIdSpecQuery};\nuse crate::core::{PackageIdSpec, Workspace};\nuse crate::util::CargoResult;\nuse crate::util::restricted_names::is_glob_pattern;\n\nuse anyhow::{Context as _, bail};\n\n/// Represents the selected packages that will be built.\n///\n/// Generally, it represents the combination of all `-p` flag. When working within\n/// a workspace, `--exclude` and `--workspace` flags also contribute to it.\n#[derive(PartialEq, Eq, Debug, Clone)]\npub enum Packages {\n    /// Packages selected by default. Usually means no flag provided.\n    Default,\n    /// Opt in all packages.\n    ///\n    /// As of the time of this writing, it only works on opting in all workspace members.\n    /// Keeps the packages passed in to verify that they exist in the workspace.\n    All(Vec<String>),\n    /// Opt out of packages passed in.\n    ///\n    /// As of the time of this writing, it only works on opting out workspace members.\n    OptOut(Vec<String>),\n    /// A sequence of hand-picked packages that will be built. Normally done by `-p` flag.\n    Packages(Vec<String>),\n}\n\nimpl Packages {\n    /// Creates a `Packages` from flags which are generally equivalent to command line flags.\n    pub fn from_flags(all: bool, exclude: Vec<String>, package: Vec<String>) -> CargoResult<Self> {\n        Ok(match (all, exclude.len(), package.len()) {\n            (false, 0, 0) => Packages::Default,\n            (false, 0, _) => Packages::Packages(package),\n            (false, _, _) => anyhow::bail!(\"--exclude can only be used together with --workspace\"),\n            (true, 0, _) => Packages::All(package),\n            (true, _, _) => Packages::OptOut(exclude),\n        })\n    }\n\n    /// Converts selected packages to [`PackageIdSpec`]s.\n    pub fn to_package_id_specs(&self, ws: &Workspace<'_>) -> CargoResult<Vec<PackageIdSpec>> {\n        let specs = match self {\n            Packages::All(packages) => {\n                emit_packages_not_found_within_workspace(ws, packages)?;\n                ws.members()\n                    .map(Package::package_id)\n                    .map(|id| id.to_spec())\n                    .collect()\n            }\n            Packages::OptOut(opt_out) => {\n                let (mut patterns, mut ids) = opt_patterns_and_ids(opt_out)?;\n                let specs = ws\n                    .members()\n                    .filter(|pkg| {\n                        let id = ids.iter().find(|id| id.matches(pkg.package_id())).cloned();\n                        if let Some(id) = &id {\n                            ids.remove(id);\n                        }\n                        !id.is_some() && !match_patterns(pkg, &mut patterns)\n                    })\n                    .map(Package::package_id)\n                    .map(|id| id.to_spec())\n                    .collect();\n                let warn = |e| ws.gctx().shell().warn(e);\n                let names = ids\n                    .into_iter()\n                    .map(|id| id.to_string())\n                    .collect::<BTreeSet<_>>();\n                emit_package_not_found(ws, names, true).or_else(warn)?;\n                emit_pattern_not_found(ws, patterns, true).or_else(warn)?;\n                specs\n            }\n            Packages::Packages(packages) if packages.is_empty() => {\n                vec![ws.current()?.package_id().to_spec()]\n            }\n            Packages::Packages(opt_in) => {\n                let (mut patterns, mut specs) = opt_patterns_and_ids(opt_in)?;\n                if !patterns.is_empty() {\n                    let matched_pkgs = ws\n                        .members()\n                        .filter(|pkg| match_patterns(pkg, &mut patterns))\n                        .map(Package::package_id)\n                        .map(|id| id.to_spec());\n                    specs.extend(matched_pkgs);\n                }\n                emit_pattern_not_found(ws, patterns, false)?;\n                specs.into_iter().collect()\n            }\n            Packages::Default => ws\n                .default_members()\n                .map(Package::package_id)\n                .map(|id| id.to_spec())\n                .collect(),\n        };\n        if specs.is_empty() {\n            if ws.is_virtual() {\n                bail!(\n                    \"manifest path `{}` contains no package: The manifest is virtual, \\\n                     and the workspace has no members.\",\n                    ws.root().display()\n                )\n            }\n            bail!(\"no packages to compile\")\n        }\n        Ok(specs)\n    }\n\n    /// Gets a list of selected [`Package`]s.\n    pub fn get_packages<'ws>(&self, ws: &'ws Workspace<'_>) -> CargoResult<Vec<&'ws Package>> {\n        let packages: Vec<_> = match self {\n            Packages::Default => ws.default_members().collect(),\n            Packages::All(packages) => {\n                emit_packages_not_found_within_workspace(ws, packages)?;\n                ws.members().collect()\n            }\n            Packages::OptOut(opt_out) => {\n                let (mut patterns, mut ids) = opt_patterns_and_ids(opt_out)?;\n                let packages = ws\n                    .members()\n                    .filter(|pkg| {\n                        let id = ids.iter().find(|id| id.matches(pkg.package_id())).cloned();\n                        if let Some(id) = &id {\n                            ids.remove(id);\n                        }\n                        !id.is_some() && !match_patterns(pkg, &mut patterns)\n                    })\n                    .collect();\n                let names = ids\n                    .into_iter()\n                    .map(|id| id.to_string())\n                    .collect::<BTreeSet<_>>();\n                emit_package_not_found(ws, names, true)?;\n                emit_pattern_not_found(ws, patterns, true)?;\n                packages\n            }\n            Packages::Packages(opt_in) => {\n                let (mut patterns, mut ids) = opt_patterns_and_ids(opt_in)?;\n                let packages = ws\n                    .members()\n                    .filter(|pkg| {\n                        let id = ids.iter().find(|id| id.matches(pkg.package_id())).cloned();\n                        if let Some(id) = &id {\n                            ids.remove(id);\n                        }\n                        id.is_some() || match_patterns(pkg, &mut patterns)\n                    })\n                    .collect();\n                let names = ids\n                    .into_iter()\n                    .map(|id| id.to_string())\n                    .collect::<BTreeSet<_>>();\n                emit_package_not_found(ws, names, false)?;\n                emit_pattern_not_found(ws, patterns, false)?;\n                packages\n            }\n        };\n        Ok(packages)\n    }\n\n    /// Returns whether or not the user needs to pass a `-p` flag to target a\n    /// specific package in the workspace.\n    pub fn needs_spec_flag(&self, ws: &Workspace<'_>) -> bool {\n        match self {\n            Packages::Default => ws.default_members().count() > 1,\n            Packages::All(_) => ws.members().count() > 1,\n            Packages::Packages(_) => true,\n            Packages::OptOut(_) => true,\n        }\n    }\n}\n\n/// Emits \"package not found\" error.\nfn emit_package_not_found(\n    ws: &Workspace<'_>,\n    opt_names: BTreeSet<String>,\n    opt_out: bool,\n) -> CargoResult<()> {\n    if !opt_names.is_empty() {\n        anyhow::bail!(\n            \"{}package(s) `{}` not found in workspace `{}`\",\n            if opt_out { \"excluded \" } else { \"\" },\n            opt_names.into_iter().collect::<Vec<_>>().join(\", \"),\n            ws.root().display(),\n        )\n    }\n    Ok(())\n}\n\n/// Emits \"glob pattern not found\" error.\nfn emit_pattern_not_found(\n    ws: &Workspace<'_>,\n    opt_patterns: Vec<(glob::Pattern, bool)>,\n    opt_out: bool,\n) -> CargoResult<()> {\n    let not_matched = opt_patterns\n        .iter()\n        .filter(|(_, matched)| !*matched)\n        .map(|(pat, _)| pat.as_str())\n        .collect::<Vec<_>>();\n    if !not_matched.is_empty() {\n        anyhow::bail!(\n            \"{}package pattern(s) `{}` not found in workspace `{}`\",\n            if opt_out { \"excluded \" } else { \"\" },\n            not_matched.join(\", \"),\n            ws.root().display(),\n        )\n    }\n    Ok(())\n}\n\nfn emit_packages_not_found_within_workspace(\n    ws: &Workspace<'_>,\n    packages: &[String],\n) -> CargoResult<()> {\n    let (mut patterns, mut ids) = opt_patterns_and_ids(packages)?;\n    let _: Vec<_> = ws\n        .members()\n        .filter(|pkg| {\n            let id = ids.iter().find(|id| id.matches(pkg.package_id())).cloned();\n            if let Some(id) = &id {\n                ids.remove(id);\n            }\n            !id.is_some() && !match_patterns(pkg, &mut patterns)\n        })\n        .map(Package::package_id)\n        .map(|id| id.to_spec())\n        .collect();\n    let names = ids\n        .into_iter()\n        .map(|id| id.to_string())\n        .collect::<BTreeSet<_>>();\n    emit_package_not_found(ws, names, false)?;\n    emit_pattern_not_found(ws, patterns, false)?;\n    Ok(())\n}\n\n/// Given a list opt-in or opt-out package selection strings, generates two\n/// collections that represent glob patterns and package id specs respectively.\nfn opt_patterns_and_ids(\n    opt: &[String],\n) -> CargoResult<(Vec<(glob::Pattern, bool)>, BTreeSet<PackageIdSpec>)> {\n    let mut opt_patterns = Vec::new();\n    let mut opt_ids = BTreeSet::new();\n    for x in opt.iter() {\n        match PackageIdSpec::parse(x) {\n            Ok(spec) => {\n                opt_ids.insert(spec);\n            }\n            Err(_) if is_glob_pattern(x) => opt_patterns.push((build_glob(x)?, false)),\n            Err(e) => return Err(e.into()),\n        }\n    }\n    Ok((opt_patterns, opt_ids))\n}\n\n/// Checks whether a package matches any of a list of glob patterns generated\n/// from `opt_patterns_and_names`.\nfn match_patterns(pkg: &Package, patterns: &mut Vec<(glob::Pattern, bool)>) -> bool {\n    patterns.iter_mut().any(|(m, matched)| {\n        let is_matched = m.matches(pkg.name().as_str());\n        *matched |= is_matched;\n        is_matched\n    })\n}\n\n/// Build [`glob::Pattern`] with informative context.\npub fn build_glob(pat: &str) -> CargoResult<glob::Pattern> {\n    glob::Pattern::new(pat).with_context(|| format!(\"cannot build glob pattern from `{}`\", pat))\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_compile/unit_generator.rs",
    "content": "use std::cell::RefCell;\nuse std::collections::{HashMap, HashSet};\nuse std::fmt::Write;\n\nuse crate::core::Workspace;\nuse crate::core::compiler::UserIntent;\nuse crate::core::compiler::rustdoc::RustdocScrapeExamples;\nuse crate::core::compiler::unit_dependencies::IsArtifact;\nuse crate::core::compiler::{CompileKind, CompileMode, Unit};\nuse crate::core::compiler::{RustcTargetData, UnitInterner};\nuse crate::core::dependency::DepKind;\nuse crate::core::profiles::{Profiles, UnitFor};\nuse crate::core::resolver::features::{self, FeaturesFor};\nuse crate::core::resolver::{ForceAllTargets, HasDevUnits, Resolve};\nuse crate::core::{FeatureValue, Package, PackageSet, Summary, Target};\nuse crate::util::restricted_names::is_glob_pattern;\nuse crate::util::{CargoResult, closest_msg};\n\nuse super::Packages;\nuse super::compile_filter::{CompileFilter, FilterRule, LibRule};\nuse super::packages::build_glob;\n\n/// A proposed target.\n///\n/// Proposed targets are later filtered into actual `Unit`s based on whether or\n/// not the target requires its features to be present.\n#[derive(Debug)]\nstruct Proposal<'a> {\n    pkg: &'a Package,\n    target: &'a Target,\n    /// Indicates whether or not all required features *must* be present. If\n    /// false, and the features are not available, then it will be silently\n    /// skipped. Generally, targets specified by name (`--bin foo`) are\n    /// required, all others can be silently skipped if features are missing.\n    requires_features: bool,\n    mode: CompileMode,\n}\n\n/// The context needed for generating root units,\n/// which are packages the user has requested to compile.\n///\n/// To generate a full [`UnitGraph`],\n/// generally you need to call [`generate_root_units`] first,\n/// and then provide the output to [`build_unit_dependencies`].\n///\n/// [`generate_root_units`]: UnitGenerator::generate_root_units\n/// [`build_unit_dependencies`]: crate::core::compiler::unit_dependencies::build_unit_dependencies\n/// [`UnitGraph`]: crate::core::compiler::unit_graph::UnitGraph\npub struct UnitGenerator<'a, 'gctx> {\n    pub ws: &'a Workspace<'gctx>,\n    pub packages: &'a [&'a Package],\n    pub spec: &'a Packages,\n    pub target_data: &'a RustcTargetData<'gctx>,\n    pub filter: &'a CompileFilter,\n    pub requested_kinds: &'a [CompileKind],\n    pub explicit_host_kind: CompileKind,\n    pub intent: UserIntent,\n    pub resolve: &'a Resolve,\n    pub workspace_resolve: &'a Option<Resolve>,\n    pub resolved_features: &'a features::ResolvedFeatures,\n    pub package_set: &'a PackageSet<'gctx>,\n    pub profiles: &'a Profiles,\n    pub interner: &'a UnitInterner,\n    pub has_dev_units: HasDevUnits,\n}\n\nimpl<'a> UnitGenerator<'a, '_> {\n    /// Helper for creating a list of `Unit` structures\n    fn new_units(\n        &self,\n        pkg: &Package,\n        target: &Target,\n        initial_target_mode: CompileMode,\n    ) -> Vec<Unit> {\n        // Custom build units are added in `build_unit_dependencies`.\n        assert!(!target.is_custom_build());\n        let target_mode = match initial_target_mode {\n            CompileMode::Test => {\n                if target.is_example() && !self.filter.is_specific() && !target.tested() {\n                    // Examples are included as regular binaries to verify\n                    // that they compile.\n                    CompileMode::Build\n                } else {\n                    CompileMode::Test\n                }\n            }\n            _ => initial_target_mode,\n        };\n\n        let is_local = pkg.package_id().source_id().is_path();\n\n        // No need to worry about build-dependencies, roots are never build dependencies.\n        let features_for = FeaturesFor::from_for_host(target.proc_macro());\n        let features = self\n            .resolved_features\n            .activated_features(pkg.package_id(), features_for);\n\n        // If `--target` has not been specified, then the unit\n        // graph is built almost like if `--target $HOST` was\n        // specified. See `rebuild_unit_graph_shared` for more on\n        // why this is done. However, if the package has its own\n        // `package.target` key, then this gets used instead of\n        // `$HOST`\n        let explicit_kinds = if let Some(k) = pkg.manifest().forced_kind() {\n            vec![k]\n        } else {\n            self.requested_kinds\n                .iter()\n                .map(|kind| match kind {\n                    CompileKind::Host => pkg\n                        .manifest()\n                        .default_kind()\n                        .unwrap_or(self.explicit_host_kind),\n                    CompileKind::Target(t) => CompileKind::Target(*t),\n                })\n                .collect()\n        };\n\n        explicit_kinds\n            .into_iter()\n            .map(move |kind| {\n                let unit_for = if initial_target_mode.is_any_test() {\n                    // NOTE: the `UnitFor` here is subtle. If you have a profile\n                    // with `panic` set, the `panic` flag is cleared for\n                    // tests/benchmarks and their dependencies. If this\n                    // was `normal`, then the lib would get compiled three\n                    // times (once with panic, once without, and once with\n                    // `--test`).\n                    //\n                    // This would cause a problem for doc tests, which would fail\n                    // because `rustdoc` would attempt to link with both libraries\n                    // at the same time. Also, it's probably not important (or\n                    // even desirable?) for rustdoc to link with a lib with\n                    // `panic` set.\n                    //\n                    // As a consequence, Examples and Binaries get compiled\n                    // without `panic` set. This probably isn't a bad deal.\n                    //\n                    // Forcing the lib to be compiled three times during `cargo\n                    // test` is probably also not desirable.\n                    UnitFor::new_test(self.ws.gctx(), kind)\n                } else if target.for_host() {\n                    // Proc macro / plugin should not have `panic` set.\n                    UnitFor::new_compiler(kind)\n                } else {\n                    UnitFor::new_normal(kind)\n                };\n                let profile = self.profiles.get_profile(\n                    pkg.package_id(),\n                    self.ws.is_member(pkg),\n                    is_local,\n                    unit_for,\n                    kind,\n                );\n                let kind = kind.for_target(target);\n                self.interner.intern(\n                    pkg,\n                    target,\n                    profile,\n                    kind,\n                    target_mode,\n                    features.clone(),\n                    self.target_data.info(kind).rustflags.clone(),\n                    self.target_data.info(kind).rustdocflags.clone(),\n                    self.target_data.target_config(kind).links_overrides.clone(),\n                    /*is_std*/ false,\n                    /*dep_hash*/ 0,\n                    IsArtifact::No,\n                    None,\n                    false,\n                )\n            })\n            .collect()\n    }\n\n    /// Given a list of all targets for a package, filters out only the targets\n    /// that are automatically included when the user doesn't specify any targets.\n    fn filter_default_targets<'b>(&self, targets: &'b [Target]) -> Vec<&'b Target> {\n        match self.intent {\n            UserIntent::Bench => targets.iter().filter(|t| t.benched()).collect(),\n            UserIntent::Test => targets\n                .iter()\n                .filter(|t| t.tested() || t.is_example())\n                .collect(),\n            UserIntent::Build | UserIntent::Check { .. } => targets\n                .iter()\n                .filter(|t| t.is_bin() || t.is_lib())\n                .collect(),\n            UserIntent::Doc { .. } => {\n                // `doc` does lib and bins (bin with same name as lib is skipped).\n                targets\n                    .iter()\n                    .filter(|t| {\n                        t.documented()\n                            && (!t.is_bin()\n                                || !targets\n                                    .iter()\n                                    .any(|l| l.is_lib() && l.crate_name() == t.crate_name()))\n                    })\n                    .collect()\n            }\n            UserIntent::Doctest => {\n                panic!(\"Invalid intent {:?}\", self.intent)\n            }\n        }\n    }\n\n    /// Filters the set of all possible targets based on the provided predicate.\n    fn filter_targets(\n        &self,\n        predicate: impl Fn(&Target) -> bool,\n        requires_features: bool,\n        mode: CompileMode,\n    ) -> Vec<Proposal<'a>> {\n        self.packages\n            .iter()\n            .flat_map(|pkg| {\n                pkg.targets()\n                    .iter()\n                    .filter(|t| predicate(t))\n                    .map(|target| Proposal {\n                        pkg,\n                        target,\n                        requires_features,\n                        mode,\n                    })\n            })\n            .collect()\n    }\n\n    /// Finds the targets for a specifically named target.\n    fn find_named_targets(\n        &self,\n        target_name: &str,\n        target_desc: &'static str,\n        is_expected_kind: fn(&Target) -> bool,\n        mode: CompileMode,\n    ) -> CargoResult<Vec<Proposal<'a>>> {\n        let is_glob = is_glob_pattern(target_name);\n        let pattern = build_glob(target_name)?;\n        let filter = |t: &Target| {\n            if is_glob {\n                is_expected_kind(t) && pattern.matches(t.name())\n            } else {\n                is_expected_kind(t) && t.name() == target_name\n            }\n        };\n        let proposals = self.filter_targets(filter, true, mode);\n        if proposals.is_empty() {\n            let mut targets = std::collections::BTreeMap::new();\n            for (pkg, target) in self.packages.iter().flat_map(|pkg| {\n                pkg.targets()\n                    .iter()\n                    .filter(|target| is_expected_kind(target))\n                    .map(move |t| (pkg, t))\n            }) {\n                targets\n                    .entry(target.name())\n                    .or_insert_with(Vec::new)\n                    .push((pkg, target));\n            }\n\n            let suggestion = closest_msg(target_name, targets.keys(), |t| t, \"target\");\n            let targets_elsewhere = self.get_targets_from_other_packages(filter)?;\n            let append_targets_elsewhere = |msg: &mut String| {\n                let mut available_msg = Vec::new();\n                for (package, targets) in &targets_elsewhere {\n                    if !targets.is_empty() {\n                        available_msg.push(format!(\n                            \"help: available {target_desc} in `{package}` package:\"\n                        ));\n                        for target in targets {\n                            available_msg.push(format!(\"    {target}\"));\n                        }\n                    }\n                }\n                if !available_msg.is_empty() {\n                    write!(msg, \"\\n{}\", available_msg.join(\"\\n\"))?;\n                }\n                CargoResult::Ok(())\n            };\n\n            let unmatched_packages = match self.spec {\n                Packages::Default | Packages::OptOut(_) | Packages::All(_) => {\n                    \" in default-run packages\".to_owned()\n                }\n                Packages::Packages(packages) => match packages.len() {\n                    0 => String::new(),\n                    1 => format!(\" in `{}` package\", packages[0]),\n                    _ => format!(\" in `{}`, ... packages\", packages[0]),\n                },\n            };\n\n            let named = if is_glob { \"matches pattern\" } else { \"named\" };\n\n            let mut msg = String::new();\n            write!(\n                msg,\n                \"no {target_desc} target {named} `{target_name}`{unmatched_packages}{suggestion}\",\n            )?;\n            if !targets_elsewhere.is_empty() {\n                append_targets_elsewhere(&mut msg)?;\n            } else if suggestion.is_empty() && !targets.is_empty() {\n                write!(msg, \"\\nhelp: available {} targets:\", target_desc)?;\n                for (target_name, pkgs) in targets {\n                    if pkgs.len() == 1 {\n                        write!(msg, \"\\n    {target_name}\")?;\n                    } else {\n                        for (pkg, _) in pkgs {\n                            let pkg_name = pkg.name();\n                            write!(msg, \"\\n    {target_name} in package {pkg_name}\")?;\n                        }\n                    }\n                }\n            }\n            anyhow::bail!(msg);\n        }\n        Ok(proposals)\n    }\n\n    fn get_targets_from_other_packages(\n        &self,\n        filter_fn: impl Fn(&Target) -> bool,\n    ) -> CargoResult<Vec<(&str, Vec<&str>)>> {\n        let packages = Packages::All(Vec::new()).get_packages(self.ws)?;\n        let targets = packages\n            .into_iter()\n            .filter_map(|pkg| {\n                let mut targets: Vec<_> = pkg\n                    .manifest()\n                    .targets()\n                    .iter()\n                    .filter_map(|target| filter_fn(target).then(|| target.name()))\n                    .collect();\n                if targets.is_empty() {\n                    None\n                } else {\n                    targets.sort();\n                    Some((pkg.name().as_str(), targets))\n                }\n            })\n            .collect();\n\n        Ok(targets)\n    }\n\n    /// Returns a list of proposed targets based on command-line target selection flags.\n    fn list_rule_targets(\n        &self,\n        rule: &FilterRule,\n        target_desc: &'static str,\n        is_expected_kind: fn(&Target) -> bool,\n        mode: CompileMode,\n    ) -> CargoResult<Vec<Proposal<'a>>> {\n        let mut proposals = Vec::new();\n        match rule {\n            FilterRule::All => proposals.extend(self.filter_targets(is_expected_kind, false, mode)),\n            FilterRule::Just(names) => {\n                for name in names {\n                    proposals.extend(self.find_named_targets(\n                        name,\n                        target_desc,\n                        is_expected_kind,\n                        mode,\n                    )?);\n                }\n            }\n        }\n        Ok(proposals)\n    }\n\n    /// Create a list of proposed targets given the context in `UnitGenerator`\n    fn create_proposals(&self) -> CargoResult<Vec<Proposal<'_>>> {\n        let mut proposals: Vec<Proposal<'_>> = Vec::new();\n\n        match *self.filter {\n            CompileFilter::Default {\n                required_features_filterable,\n            } => {\n                for pkg in self.packages {\n                    let default = self.filter_default_targets(pkg.targets());\n                    proposals.extend(default.into_iter().map(|target| Proposal {\n                        pkg,\n                        target,\n                        requires_features: !required_features_filterable,\n                        mode: to_compile_mode(self.intent),\n                    }));\n                    if matches!(self.intent, UserIntent::Test) {\n                        if let Some(t) = pkg\n                            .targets()\n                            .iter()\n                            .find(|t| t.is_lib() && t.doctested() && t.doctestable())\n                        {\n                            proposals.push(Proposal {\n                                pkg,\n                                target: t,\n                                requires_features: false,\n                                mode: CompileMode::Doctest,\n                            });\n                        }\n                    }\n                }\n            }\n            CompileFilter::Only {\n                all_targets,\n                ref lib,\n                ref bins,\n                ref examples,\n                ref tests,\n                ref benches,\n            } => {\n                if *lib != LibRule::False {\n                    let mut libs = Vec::new();\n                    let compile_mode = to_compile_mode(self.intent);\n                    for proposal in self.filter_targets(Target::is_lib, false, compile_mode) {\n                        let Proposal { target, pkg, .. } = proposal;\n                        if matches!(self.intent, UserIntent::Doctest) && !target.doctestable() {\n                            let types = target.rustc_crate_types();\n                            let types_str: Vec<&str> = types.iter().map(|t| t.as_str()).collect();\n                            self.ws.gctx().shell().warn(format!(\n                      \"doc tests are not supported for crate type(s) `{}` in package `{}`\",\n                      types_str.join(\", \"),\n                      pkg.name()\n                  ))?;\n                        } else {\n                            libs.push(proposal)\n                        }\n                    }\n                    if !all_targets && libs.is_empty() && *lib == LibRule::True {\n                        let names = self\n                            .packages\n                            .iter()\n                            .map(|pkg| pkg.name())\n                            .collect::<Vec<_>>();\n                        if names.len() == 1 {\n                            anyhow::bail!(\"no library targets found in package `{}`\", names[0]);\n                        } else {\n                            anyhow::bail!(\n                                \"no library targets found in packages: {}\",\n                                names.join(\", \")\n                            );\n                        }\n                    }\n                    proposals.extend(libs);\n                }\n\n                let default_mode = to_compile_mode(self.intent);\n\n                // If `--tests` was specified, add all targets that would be\n                // generated by `cargo test`.\n                let test_filter = match tests {\n                    FilterRule::All => Target::tested,\n                    FilterRule::Just(_) => Target::is_test,\n                };\n                let test_mode = match self.intent {\n                    UserIntent::Build => CompileMode::Test,\n                    UserIntent::Check { .. } => CompileMode::Check { test: true },\n                    _ => default_mode,\n                };\n                // If `--benches` was specified, add all targets that would be\n                // generated by `cargo bench`.\n                let bench_filter = match benches {\n                    FilterRule::All => Target::benched,\n                    FilterRule::Just(_) => Target::is_bench,\n                };\n\n                proposals.extend(self.list_rule_targets(\n                    bins,\n                    \"bin\",\n                    Target::is_bin,\n                    default_mode,\n                )?);\n                proposals.extend(self.list_rule_targets(\n                    examples,\n                    \"example\",\n                    Target::is_example,\n                    default_mode,\n                )?);\n                proposals.extend(self.list_rule_targets(tests, \"test\", test_filter, test_mode)?);\n                proposals.extend(self.list_rule_targets(\n                    benches,\n                    \"bench\",\n                    bench_filter,\n                    test_mode,\n                )?);\n            }\n        }\n\n        Ok(proposals)\n    }\n\n    /// Proposes targets from which to scrape examples for documentation\n    fn create_docscrape_proposals(&self, doc_units: &[Unit]) -> CargoResult<Vec<Proposal<'a>>> {\n        // In general, the goal is to scrape examples from (a) whatever targets\n        // the user is documenting, and (b) Example targets. However, if the user\n        // is documenting a library with dev-dependencies, those dev-deps are not\n        // needed for the library, while dev-deps are needed for the examples.\n        //\n        // If scrape-examples caused `cargo doc` to start requiring dev-deps, this\n        // would be a breaking change to crates whose dev-deps don't compile.\n        // Therefore we ONLY want to scrape Example targets if either:\n        //    (1) No package has dev-dependencies, so this is a moot issue, OR\n        //    (2) The provided CompileFilter requires dev-dependencies anyway.\n        //\n        // The next two variables represent these two conditions.\n        let no_pkg_has_dev_deps = self.packages.iter().all(|pkg| {\n            pkg.summary()\n                .dependencies()\n                .iter()\n                .all(|dep| !matches!(dep.kind(), DepKind::Development))\n        });\n        let reqs_dev_deps = matches!(self.has_dev_units, HasDevUnits::Yes);\n        let safe_to_scrape_example_targets = no_pkg_has_dev_deps || reqs_dev_deps;\n\n        let pkgs_to_scrape = doc_units\n            .iter()\n            .filter(|unit| self.ws.unit_needs_doc_scrape(unit))\n            .map(|u| &u.pkg)\n            .collect::<HashSet<_>>();\n\n        let skipped_examples = RefCell::new(Vec::new());\n        let can_scrape = |target: &Target| {\n            match (target.doc_scrape_examples(), target.is_example()) {\n                // Targets configured by the user to not be scraped should never be scraped\n                (RustdocScrapeExamples::Disabled, _) => false,\n                // Targets configured by the user to be scraped should always be scraped\n                (RustdocScrapeExamples::Enabled, _) => true,\n                // Example targets with no configuration should be conditionally scraped if\n                // it's guaranteed not to break the build\n                (RustdocScrapeExamples::Unset, true) => {\n                    if !safe_to_scrape_example_targets {\n                        skipped_examples\n                            .borrow_mut()\n                            .push(target.name().to_string());\n                    }\n                    safe_to_scrape_example_targets\n                }\n                // All other targets are ignored for now. This may change in the future!\n                (RustdocScrapeExamples::Unset, false) => false,\n            }\n        };\n\n        let mut scrape_proposals = self.filter_targets(can_scrape, false, CompileMode::Docscrape);\n        scrape_proposals.retain(|proposal| pkgs_to_scrape.contains(proposal.pkg));\n\n        let skipped_examples = skipped_examples.into_inner();\n        if !skipped_examples.is_empty() {\n            let mut shell = self.ws.gctx().shell();\n            let example_str = skipped_examples.join(\", \");\n            shell.warn(format!(\n                \"\\\nRustdoc did not scrape the following examples because they require dev-dependencies: {example_str}\n    If you want Rustdoc to scrape these examples, then add `doc-scrape-examples = true`\n    to the [[example]] target configuration of at least one example.\"\n            ))?;\n        }\n\n        Ok(scrape_proposals)\n    }\n\n    /// Checks if the unit list is empty and the user has passed any combination of\n    /// --tests, --examples, --benches or --bins, and we didn't match on any targets.\n    /// We want to emit a warning to make sure the user knows that this run is a no-op,\n    /// and their code remains unchecked despite cargo not returning any errors\n    fn unmatched_target_filters(&self, units: &[Unit]) -> CargoResult<()> {\n        let mut shell = self.ws.gctx().shell();\n        if let CompileFilter::Only {\n            all_targets,\n            lib: _,\n            ref bins,\n            ref examples,\n            ref tests,\n            ref benches,\n        } = *self.filter\n        {\n            if units.is_empty() {\n                let mut filters = String::new();\n                let mut miss_count = 0;\n\n                let mut append = |t: &FilterRule, s| {\n                    if let FilterRule::All = *t {\n                        miss_count += 1;\n                        filters.push_str(s);\n                    }\n                };\n\n                if all_targets {\n                    filters.push_str(\" `all-targets`\");\n                } else {\n                    append(bins, \" `bins`,\");\n                    append(tests, \" `tests`,\");\n                    append(examples, \" `examples`,\");\n                    append(benches, \" `benches`,\");\n                    filters.pop();\n                }\n\n                return shell.warn(format!(\n                    \"target {}{} specified, but no targets matched; this is a no-op\",\n                    if miss_count > 1 { \"filters\" } else { \"filter\" },\n                    filters,\n                ));\n            }\n        }\n\n        Ok(())\n    }\n\n    /// Warns if a target's required-features references a feature that doesn't exist.\n    ///\n    /// This is a warning because historically this was not validated, and it\n    /// would cause too much breakage to make it an error.\n    fn validate_required_features(\n        &self,\n        target_name: &str,\n        required_features: &[String],\n        summary: &Summary,\n    ) -> CargoResult<()> {\n        let resolve = match self.workspace_resolve {\n            None => return Ok(()),\n            Some(resolve) => resolve,\n        };\n\n        let mut shell = self.ws.gctx().shell();\n        for feature in required_features {\n            let fv = FeatureValue::new(feature.into());\n            match &fv {\n                FeatureValue::Feature(f) => {\n                    if !summary.features().contains_key(f) {\n                        shell.warn(format!(\n                            \"invalid feature `{}` in required-features of target `{}`: \\\n                      `{}` is not present in [features] section\",\n                            fv, target_name, fv\n                        ))?;\n                    }\n                }\n                FeatureValue::Dep { .. } => {\n                    anyhow::bail!(\n                        \"invalid feature `{}` in required-features of target `{}`: \\\n                  `dep:` prefixed feature values are not allowed in required-features\",\n                        fv,\n                        target_name\n                    );\n                }\n                FeatureValue::DepFeature { weak: true, .. } => {\n                    anyhow::bail!(\n                        \"invalid feature `{}` in required-features of target `{}`: \\\n                  optional dependency with `?` is not allowed in required-features\",\n                        fv,\n                        target_name\n                    );\n                }\n                // Handling of dependent_crate/dependent_crate_feature syntax\n                FeatureValue::DepFeature {\n                    dep_name,\n                    dep_feature,\n                    weak: false,\n                } => {\n                    match resolve.deps(summary.package_id()).find(|(_dep_id, deps)| {\n                        deps.iter().any(|dep| dep.name_in_toml() == *dep_name)\n                    }) {\n                        Some((dep_id, _deps)) => {\n                            let dep_summary = resolve.summary(dep_id);\n                            if !dep_summary.features().contains_key(dep_feature)\n                                && !dep_summary.dependencies().iter().any(|dep| {\n                                    dep.name_in_toml() == *dep_feature && dep.is_optional()\n                                })\n                            {\n                                shell.warn(format!(\n                                    \"invalid feature `{}` in required-features of target `{}`: \\\n                              feature `{}` does not exist in package `{}`\",\n                                    fv, target_name, dep_feature, dep_id\n                                ))?;\n                            }\n                        }\n                        None => {\n                            shell.warn(format!(\n                                \"invalid feature `{}` in required-features of target `{}`: \\\n                          dependency `{}` does not exist\",\n                                fv, target_name, dep_name\n                            ))?;\n                        }\n                    }\n                }\n            }\n        }\n        Ok(())\n    }\n\n    /// Converts proposals to units based on each target's required features.\n    fn proposals_to_units(&self, proposals: Vec<Proposal<'_>>) -> CargoResult<Vec<Unit>> {\n        // Only include targets that are libraries or have all required\n        // features available.\n        //\n        // `features_map` is a map of &Package -> enabled_features\n        // It is computed by the set of enabled features for the package plus\n        // every enabled feature of every enabled dependency.\n        let mut features_map = HashMap::new();\n        // This needs to be a set to de-duplicate units. Due to the way the\n        // targets are filtered, it is possible to have duplicate proposals for\n        // the same thing.\n        let mut units = HashSet::new();\n        for Proposal {\n            pkg,\n            target,\n            requires_features,\n            mode,\n        } in proposals\n        {\n            let unavailable_features = match target.required_features() {\n                Some(rf) => {\n                    self.validate_required_features(target.name(), rf, pkg.summary())?;\n\n                    let features = features_map.entry(pkg).or_insert_with(|| {\n                        super::resolve_all_features(\n                            self.resolve,\n                            self.resolved_features,\n                            self.package_set,\n                            pkg.package_id(),\n                            self.has_dev_units,\n                            self.requested_kinds,\n                            self.target_data,\n                            ForceAllTargets::No,\n                        )\n                    });\n                    rf.iter().filter(|f| !features.contains(*f)).collect()\n                }\n                None => Vec::new(),\n            };\n            if target.is_lib() || unavailable_features.is_empty() {\n                units.extend(self.new_units(pkg, target, mode));\n            } else if requires_features {\n                let required_features = target.required_features().unwrap();\n                let quoted_required_features: Vec<String> = required_features\n                    .iter()\n                    .map(|s| format!(\"`{}`\", s))\n                    .collect();\n                anyhow::bail!(\n                    \"target `{}` in package `{}` requires the features: {}\\n\\\n               Consider enabling them by passing, e.g., `--features=\\\"{}\\\"`\",\n                    target.name(),\n                    pkg.name(),\n                    quoted_required_features.join(\", \"),\n                    required_features.join(\" \")\n                );\n            }\n            // else, silently skip target.\n        }\n        let mut units: Vec<_> = units.into_iter().collect();\n        self.unmatched_target_filters(&units)?;\n\n        // Keep the roots in a consistent order, which helps with checking test output.\n        units.sort_unstable();\n        Ok(units)\n    }\n\n    /// Generates all the base units for the packages the user has requested to\n    /// compile. Dependencies for these units are computed later in [`unit_dependencies`].\n    ///\n    /// [`unit_dependencies`]: crate::core::compiler::unit_dependencies\n    pub fn generate_root_units(&self) -> CargoResult<Vec<Unit>> {\n        let proposals = self.create_proposals()?;\n        self.proposals_to_units(proposals)\n    }\n\n    /// Generates units specifically for doc-scraping.\n    ///\n    /// This requires a separate entrypoint from [`generate_root_units`] because it\n    /// takes the documented units as input.\n    ///\n    /// [`generate_root_units`]: Self::generate_root_units\n    pub fn generate_scrape_units(&self, doc_units: &[Unit]) -> CargoResult<Vec<Unit>> {\n        let scrape_proposals = self.create_docscrape_proposals(&doc_units)?;\n        let scrape_units = self.proposals_to_units(scrape_proposals)?;\n        Ok(scrape_units)\n    }\n}\n\n/// Converts [`UserIntent`] to [`CompileMode`] for root units.\nfn to_compile_mode(intent: UserIntent) -> CompileMode {\n    match intent {\n        UserIntent::Test | UserIntent::Bench => CompileMode::Test,\n        UserIntent::Build => CompileMode::Build,\n        UserIntent::Check { test } => CompileMode::Check { test },\n        UserIntent::Doc { .. } => CompileMode::Doc,\n        UserIntent::Doctest => CompileMode::Doctest,\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_config.rs",
    "content": "//! Implementation of `cargo config` subcommand.\n\nuse crate::util::context::{ConfigKey, ConfigValue as CV, Definition, GlobalContext};\nuse crate::util::errors::CargoResult;\nuse crate::{drop_eprintln, drop_println};\nuse anyhow::{Error, bail, format_err};\nuse serde_json::json;\nuse std::borrow::Cow;\nuse std::fmt;\nuse std::str::FromStr;\n\npub enum ConfigFormat {\n    Toml,\n    Json,\n    JsonValue,\n}\n\nimpl ConfigFormat {\n    /// For clap.\n    pub const POSSIBLE_VALUES: [&'static str; 3] = [\"toml\", \"json\", \"json-value\"];\n}\n\nimpl FromStr for ConfigFormat {\n    type Err = Error;\n    fn from_str(s: &str) -> CargoResult<Self> {\n        match s {\n            \"toml\" => Ok(ConfigFormat::Toml),\n            \"json\" => Ok(ConfigFormat::Json),\n            \"json-value\" => Ok(ConfigFormat::JsonValue),\n            f => bail!(\"unknown config format `{}`\", f),\n        }\n    }\n}\n\nimpl fmt::Display for ConfigFormat {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match *self {\n            ConfigFormat::Toml => write!(f, \"toml\"),\n            ConfigFormat::Json => write!(f, \"json\"),\n            ConfigFormat::JsonValue => write!(f, \"json-value\"),\n        }\n    }\n}\n\n/// Options for `cargo config get`.\npub struct GetOptions<'a> {\n    pub key: Option<&'a str>,\n    pub format: ConfigFormat,\n    pub show_origin: bool,\n    pub merged: bool,\n}\n\npub fn get(gctx: &GlobalContext, opts: &GetOptions<'_>) -> CargoResult<()> {\n    if opts.show_origin && !matches!(opts.format, ConfigFormat::Toml) {\n        bail!(\n            \"the `{}` format does not support --show-origin, try the `toml` format instead\",\n            opts.format\n        );\n    }\n    let key = match opts.key {\n        Some(key) => ConfigKey::from_str(key),\n        None => ConfigKey::new(),\n    };\n    if opts.merged {\n        let cv = gctx\n            .get_cv_with_env(&key)?\n            .ok_or_else(|| format_err!(\"config value `{}` is not set\", key))?;\n        match opts.format {\n            ConfigFormat::Toml => print_toml(gctx, opts, &key, &cv),\n            ConfigFormat::Json => print_json(gctx, &key, &cv, true),\n            ConfigFormat::JsonValue => print_json(gctx, &key, &cv, false),\n        }\n        if let Some(env) = maybe_env(gctx, &key, &cv) {\n            match opts.format {\n                ConfigFormat::Toml => print_toml_env(gctx, &env),\n                ConfigFormat::Json | ConfigFormat::JsonValue => print_json_env(gctx, &env),\n            }\n        }\n    } else {\n        match &opts.format {\n            ConfigFormat::Toml => print_toml_unmerged(gctx, opts, &key)?,\n            format => bail!(\n                \"the `{}` format does not support --merged=no, try the `toml` format instead\",\n                format\n            ),\n        }\n    }\n    Ok(())\n}\n\n/// Checks for environment variables that might be used.\nfn maybe_env<'gctx>(\n    gctx: &'gctx GlobalContext,\n    key: &ConfigKey,\n    cv: &CV,\n) -> Option<Vec<(&'gctx str, &'gctx str)>> {\n    // Only fetching a table is unable to load env values. Leaf entries should\n    // work properly.\n    match cv {\n        CV::Table(_map, _def) => {}\n        _ => return None,\n    }\n    let mut env: Vec<_> = gctx\n        .env()\n        .filter(|(env_key, _val)| env_key.starts_with(&format!(\"{}_\", key.as_env_key())))\n        .collect();\n    env.sort_by_key(|x| x.0);\n    if env.is_empty() { None } else { Some(env) }\n}\n\nfn print_toml(gctx: &GlobalContext, opts: &GetOptions<'_>, key: &ConfigKey, cv: &CV) {\n    let origin = |def: &Definition| -> String {\n        if !opts.show_origin {\n            return \"\".to_string();\n        }\n        format!(\" # {}\", def)\n    };\n\n    fn cv_to_toml(cv: &CV) -> toml_edit::Value {\n        match cv {\n            CV::String(s, _) => toml_edit::Value::from(s.as_str()),\n            CV::Integer(i, _) => toml_edit::Value::from(*i),\n            CV::Boolean(b, _) => toml_edit::Value::from(*b),\n            CV::List(l, _) => toml_edit::Value::from_iter(l.iter().map(cv_to_toml)),\n            CV::Table(t, _) => toml_edit::Value::from_iter({\n                let mut t: Vec<_> = t.iter().collect();\n                t.sort_by_key(|t| t.0);\n                t.into_iter().map(|(k, v)| (k, cv_to_toml(v)))\n            }),\n        }\n    }\n\n    match cv {\n        CV::Boolean(val, def) => drop_println!(gctx, \"{} = {}{}\", key, val, origin(def)),\n        CV::Integer(val, def) => drop_println!(gctx, \"{} = {}{}\", key, val, origin(def)),\n        CV::String(val, def) => drop_println!(\n            gctx,\n            \"{} = {}{}\",\n            key,\n            toml_edit::Value::from(val),\n            origin(def)\n        ),\n        CV::List(vals, _def) => {\n            if opts.show_origin {\n                drop_println!(gctx, \"{} = [\", key);\n                for cv in vals {\n                    let val = cv_to_toml(cv);\n                    let def = cv.definition();\n                    drop_println!(gctx, \"    {val}, # {def}\");\n                }\n                drop_println!(gctx, \"]\");\n            } else {\n                let vals: toml_edit::Array = vals.iter().map(cv_to_toml).collect();\n                drop_println!(gctx, \"{} = {}\", key, vals);\n            }\n        }\n        CV::Table(table, _def) => {\n            let mut key_vals: Vec<_> = table.iter().collect();\n            key_vals.sort_by(|a, b| a.0.cmp(b.0));\n            for (table_key, val) in key_vals {\n                let mut subkey = key.clone();\n                // push or push_sensitive shouldn't matter here, since this is\n                // not dealing with environment variables.\n                subkey.push(table_key);\n                print_toml(gctx, opts, &subkey, val);\n            }\n        }\n    }\n}\n\nfn print_toml_env(gctx: &GlobalContext, env: &[(&str, &str)]) {\n    drop_println!(\n        gctx,\n        \"# The following environment variables may affect the loaded values.\"\n    );\n    for (env_key, env_value) in env {\n        let val = shell_escape::escape(Cow::Borrowed(env_value));\n        drop_println!(gctx, \"# {}={}\", env_key, val);\n    }\n}\n\nfn print_json_env(gctx: &GlobalContext, env: &[(&str, &str)]) {\n    drop_eprintln!(\n        gctx,\n        \"note: The following environment variables may affect the loaded values.\"\n    );\n    for (env_key, env_value) in env {\n        let val = shell_escape::escape(Cow::Borrowed(env_value));\n        drop_eprintln!(gctx, \"{}={}\", env_key, val);\n    }\n}\n\nfn print_json(gctx: &GlobalContext, key: &ConfigKey, cv: &CV, include_key: bool) {\n    let json_value = if key.is_root() || !include_key {\n        cv_to_json(cv)\n    } else {\n        let mut parts: Vec<_> = key.parts().collect();\n        let last_part = parts.pop().unwrap();\n        let mut root_table = json!({});\n        // Create a JSON object with nested keys up to the value being displayed.\n        let mut table = &mut root_table;\n        for part in parts {\n            table[part] = json!({});\n            table = table.get_mut(part).unwrap();\n        }\n        table[last_part] = cv_to_json(cv);\n        root_table\n    };\n    drop_println!(gctx, \"{}\", serde_json::to_string(&json_value).unwrap());\n\n    // Helper for recursively converting a CV to JSON.\n    fn cv_to_json(cv: &CV) -> serde_json::Value {\n        match cv {\n            CV::Boolean(val, _def) => json!(val),\n            CV::Integer(val, _def) => json!(val),\n            CV::String(val, _def) => json!(val),\n            CV::List(vals, _def) => {\n                let jvals: Vec<_> = vals.iter().map(cv_to_json).collect();\n                json!(jvals)\n            }\n            CV::Table(map, _def) => {\n                let mut table = json!({});\n                for (key, val) in map {\n                    table[key] = cv_to_json(val);\n                }\n                table\n            }\n        }\n    }\n}\n\nfn print_toml_unmerged(\n    gctx: &GlobalContext,\n    opts: &GetOptions<'_>,\n    key: &ConfigKey,\n) -> CargoResult<()> {\n    let print_table = |cv: &CV| {\n        drop_println!(gctx, \"# {}\", cv.definition());\n        print_toml(gctx, opts, &ConfigKey::new(), cv);\n        drop_println!(gctx, \"\");\n    };\n    // This removes entries from the given CV so that all that remains is the\n    // given key. Returns false if no entries were found.\n    fn trim_cv(mut cv: &mut CV, key: &ConfigKey) -> CargoResult<bool> {\n        for (i, part) in key.parts().enumerate() {\n            match cv {\n                CV::Table(map, _def) => {\n                    map.retain(|key, _value| key == part);\n                    match map.get_mut(part) {\n                        Some(val) => cv = val,\n                        None => return Ok(false),\n                    }\n                }\n                _ => {\n                    let mut key_so_far = ConfigKey::new();\n                    for part in key.parts().take(i) {\n                        key_so_far.push(part);\n                    }\n                    bail!(\n                        \"expected table for configuration key `{}`, \\\n                         but found {} in {}\",\n                        key_so_far,\n                        cv.desc(),\n                        cv.definition()\n                    )\n                }\n            }\n        }\n        Ok(match cv {\n            CV::Table(map, _def) => !map.is_empty(),\n            _ => true,\n        })\n    }\n\n    let mut cli_args = gctx.cli_args_as_table()?;\n    if trim_cv(&mut cli_args, key)? {\n        print_table(&cli_args);\n    }\n\n    // This slurps up some extra env vars that aren't technically part of the\n    // \"config\" (or are special-cased). I'm personally fine with just keeping\n    // them here, though it might be confusing. The vars I'm aware of:\n    //\n    // * CARGO\n    // * CARGO_HOME\n    // * CARGO_NAME\n    // * CARGO_EMAIL\n    // * CARGO_INCREMENTAL\n    // * CARGO_TARGET_DIR\n    // * CARGO_CACHE_RUSTC_INFO\n    //\n    // All of these except CARGO, CARGO_HOME, and CARGO_CACHE_RUSTC_INFO are\n    // actually part of the config, but they are special-cased in the code.\n    //\n    // TODO: It might be a good idea to teach the Config loader to support\n    // environment variable aliases so that these special cases are less\n    // special, and will just naturally get loaded as part of the config.\n    let mut env: Vec<_> = gctx\n        .env()\n        .filter(|(env_key, _val)| env_key.starts_with(key.as_env_key()))\n        .collect();\n    if !env.is_empty() {\n        env.sort_by_key(|x| x.0);\n        drop_println!(gctx, \"# Environment variables\");\n        for (key, value) in env {\n            // Displaying this in \"shell\" syntax instead of TOML, since that\n            // somehow makes more sense to me.\n            let val = shell_escape::escape(Cow::Borrowed(value));\n            drop_println!(gctx, \"# {}={}\", key, val);\n        }\n        drop_println!(gctx, \"\");\n    }\n\n    let unmerged = gctx.load_values_unmerged()?;\n    for mut cv in unmerged {\n        if trim_cv(&mut cv, key)? {\n            print_table(&cv);\n        }\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_doc.rs",
    "content": "use crate::core::Workspace;\nuse crate::core::compiler::{Compilation, CompileKind};\nuse crate::core::shell::Verbosity;\nuse crate::ops;\nuse crate::util;\nuse crate::util::CargoResult;\n\nuse anyhow::{Error, bail};\nuse cargo_util::ProcessBuilder;\n\nuse std::ffi::OsString;\nuse std::path::PathBuf;\nuse std::str::FromStr;\n\n/// Format of rustdoc [`--output-format`][1].\n///\n/// [1]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#-w--output-format-output-format\n#[derive(Debug, Default, Clone)]\npub enum OutputFormat {\n    #[default]\n    Html,\n    Json,\n}\n\nimpl OutputFormat {\n    pub const POSSIBLE_VALUES: [&'static str; 2] = [\"html\", \"json\"];\n}\n\nimpl FromStr for OutputFormat {\n    // bail! error instead of string error like impl FromStr for Edition {\n    type Err = Error;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        match s {\n            \"json\" => Ok(OutputFormat::Json),\n            \"html\" => Ok(OutputFormat::Html),\n            _ => bail!(\n                \"supported values for --output-format are `json` and `html`, \\\n\t\t\t\t\t\t but `{}` is unknown\",\n                s\n            ),\n        }\n    }\n}\n\n/// Strongly typed options for the `cargo doc` command.\n#[derive(Debug)]\npub struct DocOptions {\n    /// Whether to attempt to open the browser after compiling the docs\n    pub open_result: bool,\n    /// Same as `rustdoc --output-format`\n    pub output_format: OutputFormat,\n    /// Options to pass through to the compiler\n    pub compile_opts: ops::CompileOptions,\n}\n\n/// Main method for `cargo doc`.\npub fn doc(ws: &Workspace<'_>, options: &DocOptions) -> CargoResult<()> {\n    let compilation = ops::compile(ws, &options.compile_opts)?;\n\n    if ws.gctx().cli_unstable().rustdoc_mergeable_info {\n        merge_cross_crate_info(ws, &compilation)?;\n    }\n\n    if options.open_result {\n        let name = &compilation.root_crate_names.get(0).ok_or_else(|| {\n            anyhow::anyhow!(\n                \"cannot open specified crate's documentation: no documentation generated\"\n            )\n        })?;\n        let kind = options.compile_opts.build_config.single_requested_kind()?;\n\n        let path = path_by_output_format(&compilation, &kind, &name, &options.output_format);\n\n        if path.exists() {\n            util::open::open(&path, ws.gctx())?;\n        }\n    } else if ws.gctx().shell().verbosity() == Verbosity::Verbose {\n        for name in &compilation.root_crate_names {\n            for kind in &options.compile_opts.build_config.requested_kinds {\n                let path =\n                    path_by_output_format(&compilation, &kind, &name, &options.output_format);\n                if path.exists() {\n                    let mut shell = ws.gctx().shell();\n                    let link = shell.err_file_hyperlink(&path);\n                    shell.status(\"Generated\", format!(\"{link}{}{link:#}\", path.display()))?;\n                }\n            }\n        }\n    } else {\n        let mut output = compilation.root_crate_names.iter().flat_map(|name| {\n            options\n                .compile_opts\n                .build_config\n                .requested_kinds\n                .iter()\n                .map(|kind| path_by_output_format(&compilation, kind, name, &options.output_format))\n                .filter(|path| path.exists())\n        });\n        if let Some(first_path) = output.next() {\n            let remaining = output.count();\n            let remaining = match remaining {\n                0 => \"\".to_owned(),\n                1 => \" and 1 other file\".to_owned(),\n                n => format!(\" and {n} other files\"),\n            };\n\n            let mut shell = ws.gctx().shell();\n            let link = shell.err_file_hyperlink(&first_path);\n            shell.status(\n                \"Generated\",\n                format!(\"{link}{}{link:#}{remaining}\", first_path.display(),),\n            )?;\n        }\n    }\n\n    Ok(())\n}\n\nfn merge_cross_crate_info(ws: &Workspace<'_>, compilation: &Compilation<'_>) -> CargoResult<()> {\n    let Some(fingerprints) = compilation.rustdoc_fingerprints.as_ref() else {\n        return Ok(());\n    };\n\n    let now = std::time::Instant::now();\n    for (kind, fingerprint) in fingerprints.iter() {\n        let (target_name, build_dir, artifact_dir) = match kind {\n            CompileKind::Host => (\"host\", ws.build_dir(), ws.target_dir()),\n            CompileKind::Target(t) => {\n                let name = t.short_name();\n                let build_dir = ws.build_dir().join(name);\n                let artifact_dir = ws.target_dir().join(name);\n                (name, build_dir, artifact_dir)\n            }\n        };\n\n        // rustdoc needs to read doc parts files from build dir\n        build_dir.open_ro_shared_create(\".cargo-lock\", ws.gctx(), \"build directory\")?;\n        // rustdoc will write to `<artifact-dir>/doc/`\n        artifact_dir.open_rw_exclusive_create(\".cargo-lock\", ws.gctx(), \"artifact directory\")?;\n        // We're leaking the layout implementation detail here.\n        // This detail should be hidden when doc merge becomes a Unit of work inside the build.\n        let rustdoc_artifact_dir = artifact_dir.join(\"doc\");\n\n        if !fingerprint.is_dirty() {\n            ws.gctx().shell().verbose(|shell| {\n                shell.status(\"Fresh\", format_args!(\"doc-merge for {target_name}\"))\n            })?;\n            continue;\n        }\n\n        fingerprint.persist(|doc_parts_dirs| {\n            let mut cmd = ProcessBuilder::new(ws.gctx().rustdoc()?);\n            if ws.gctx().extra_verbose() {\n                cmd.display_env_vars();\n            }\n            cmd.retry_with_argfile(true);\n            cmd.arg(\"-o\")\n                .arg(rustdoc_artifact_dir.as_path_unlocked())\n                .arg(\"-Zunstable-options\")\n                .arg(\"--merge=finalize\");\n            for parts_dir in doc_parts_dirs {\n                let mut include_arg = OsString::from(\"--include-parts-dir=\");\n                include_arg.push(parts_dir);\n                cmd.arg(include_arg);\n            }\n\n            let num_crates = doc_parts_dirs.len();\n            let plural = if num_crates == 1 { \"\" } else { \"s\" };\n\n            ws.gctx().shell().status(\n                \"Merging\",\n                format_args!(\"{num_crates} doc{plural} for {target_name}\"),\n            )?;\n            ws.gctx()\n                .shell()\n                .verbose(|shell| shell.status(\"Running\", cmd.to_string()))?;\n            cmd.exec()?;\n\n            Ok(())\n        })?;\n    }\n\n    let time_elapsed = util::elapsed(now.elapsed());\n    ws.gctx().shell().status(\n        \"Finished\",\n        format_args!(\"documentation merge in {time_elapsed}\"),\n    )?;\n\n    Ok(())\n}\n\nfn path_by_output_format(\n    compilation: &Compilation<'_>,\n    kind: &CompileKind,\n    name: &str,\n    output_format: &OutputFormat,\n) -> PathBuf {\n    if matches!(output_format, OutputFormat::Json) {\n        compilation.root_output[kind]\n            .with_file_name(\"doc\")\n            .join(format!(\"{}.json\", name))\n    } else {\n        compilation.root_output[kind]\n            .with_file_name(\"doc\")\n            .join(name)\n            .join(\"index.html\")\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_fetch.rs",
    "content": "use crate::core::compiler::BuildConfig;\nuse crate::core::compiler::RustcTargetData;\nuse crate::core::compiler::UserIntent;\nuse crate::core::compiler::standard_lib;\nuse crate::core::{PackageSet, Resolve, Workspace};\nuse crate::ops;\nuse crate::util::CargoResult;\nuse crate::util::GlobalContext;\nuse crate::util::context::JobsConfig;\nuse std::collections::HashSet;\n\npub struct FetchOptions<'a> {\n    pub gctx: &'a GlobalContext,\n    /// The target arch triple to fetch dependencies for\n    pub targets: Vec<String>,\n}\n\n/// Executes `cargo fetch`.\npub fn fetch<'a>(\n    ws: &Workspace<'a>,\n    options: &FetchOptions<'a>,\n) -> CargoResult<(Resolve, PackageSet<'a>)> {\n    ws.emit_warnings()?;\n    let dry_run = false;\n    let (mut packages, resolve) = ops::resolve_ws(ws, dry_run)?;\n\n    let jobs = Some(JobsConfig::Integer(1));\n    let keep_going = false;\n    let gctx = ws.gctx();\n    let build_config =\n        BuildConfig::new(gctx, jobs, keep_going, &options.targets, UserIntent::Build)?;\n    let mut data = RustcTargetData::new(ws, &build_config.requested_kinds)?;\n    let mut fetched_packages = HashSet::new();\n    let mut deps_to_fetch = ws.members().map(|p| p.package_id()).collect::<Vec<_>>();\n    let mut to_download = Vec::new();\n\n    while let Some(id) = deps_to_fetch.pop() {\n        if !fetched_packages.insert(id) {\n            continue;\n        }\n\n        to_download.push(id);\n        let deps = resolve\n            .deps(id)\n            .filter(|&(_id, deps)| {\n                deps.iter().any(|d| {\n                    // If no target was specified then all dependencies are\n                    // fetched.\n                    if options.targets.is_empty() {\n                        return true;\n                    }\n\n                    // Otherwise we only download this dependency if any of the\n                    // requested platforms would match this dependency. Note\n                    // that this is a bit lossy because not all dependencies are\n                    // always compiled for all platforms, but it should be\n                    // \"close enough\" for now.\n                    build_config\n                        .requested_kinds\n                        .iter()\n                        .any(|kind| data.dep_platform_activated(d, *kind))\n                })\n            })\n            .map(|(id, _deps)| id);\n        deps_to_fetch.extend(deps);\n    }\n\n    // If -Zbuild-std was passed, download dependencies for the standard library.\n    if let Some(crates) = &gctx.cli_unstable().build_std {\n        let (std_package_set, _, _) = standard_lib::resolve_std(\n            ws,\n            &mut data,\n            &build_config,\n            crates,\n            &build_config.requested_kinds,\n        )?;\n        packages.add_set(std_package_set);\n    }\n\n    packages.get_many(to_download)?;\n    crate::core::gc::auto_gc(gctx);\n\n    Ok((resolve, packages))\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_install.rs",
    "content": "use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};\nuse std::path::{Path, PathBuf};\nuse std::sync::Arc;\nuse std::{env, fs};\n\nuse crate::core::compiler::{CompileKind, DefaultExecutor, Executor, UnitOutput};\nuse crate::core::{Dependency, Edition, Package, PackageId, SourceId, Target, Workspace};\nuse crate::ops::{CompileFilter, Packages};\nuse crate::ops::{FilterRule, common_for_install_and_uninstall::*};\nuse crate::sources::source::Source;\nuse crate::sources::{GitSource, PathSource, SourceConfigMap};\nuse crate::util::context::FeatureUnification;\nuse crate::util::errors::CargoResult;\nuse crate::util::{Filesystem, GlobalContext, Rustc};\nuse crate::{drop_println, ops};\n\nuse anyhow::{Context as _, bail};\nuse cargo_util::paths;\nuse cargo_util_schemas::core::PartialVersion;\nuse itertools::Itertools;\nuse semver::VersionReq;\nuse tempfile::Builder as TempFileBuilder;\n\nstruct Transaction {\n    bins: Vec<PathBuf>,\n}\n\nimpl Transaction {\n    fn success(mut self) {\n        self.bins.clear();\n    }\n}\n\nimpl Drop for Transaction {\n    fn drop(&mut self) {\n        for bin in self.bins.iter() {\n            let _ = paths::remove_file(bin);\n        }\n    }\n}\n\nstruct InstallablePackage<'gctx> {\n    gctx: &'gctx GlobalContext,\n    opts: ops::CompileOptions,\n    root: Filesystem,\n    source_id: SourceId,\n    vers: Option<VersionReq>,\n    force: bool,\n    no_track: bool,\n    pkg: Package,\n    ws: Workspace<'gctx>,\n    rustc: Rustc,\n    target: String,\n}\n\nimpl<'gctx> InstallablePackage<'gctx> {\n    // Returns pkg to install. None if pkg is already installed\n    pub fn new(\n        gctx: &'gctx GlobalContext,\n        root: Filesystem,\n        map: SourceConfigMap<'_>,\n        krate: Option<&str>,\n        source_id: SourceId,\n        from_cwd: bool,\n        vers: Option<&VersionReq>,\n        original_opts: &ops::CompileOptions,\n        force: bool,\n        no_track: bool,\n        needs_update_if_source_is_index: bool,\n        current_rust_version: Option<&PartialVersion>,\n    ) -> CargoResult<Option<Self>> {\n        if let Some(name) = krate {\n            if name == \".\" {\n                bail!(\n                    \"to install the binaries for the package in current working \\\n                     directory use `cargo install --path .`. \\n\\\n                     use `cargo build` if you want to simply build the package.\"\n                )\n            }\n        }\n\n        let dst = root.join(\"bin\").into_path_unlocked();\n        let pkg = {\n            let dep = {\n                if let Some(krate) = krate {\n                    let vers = if let Some(vers) = vers {\n                        Some(vers.to_string())\n                    } else if source_id.is_registry() {\n                        // Avoid pre-release versions from crate.io\n                        // unless explicitly asked for\n                        Some(String::from(\"*\"))\n                    } else {\n                        None\n                    };\n                    Some(Dependency::parse(krate, vers.as_deref(), source_id)?)\n                } else {\n                    None\n                }\n            };\n\n            if source_id.is_git() {\n                let mut source = GitSource::new(source_id, gctx)?;\n                select_pkg(\n                    &mut source,\n                    dep,\n                    |git: &mut GitSource<'_>| git.read_packages(),\n                    gctx,\n                    current_rust_version,\n                )?\n            } else if source_id.is_path() {\n                let mut src = path_source(source_id, gctx)?;\n                if !src.path().is_dir() {\n                    bail!(\n                        \"`{}` is not a directory. \\\n                     --path must point to a directory containing a Cargo.toml file.\",\n                        src.path().display()\n                    )\n                }\n                if !src.path().join(\"Cargo.toml\").exists() {\n                    if from_cwd {\n                        bail!(\n                            \"`{}` is not a crate root; specify a crate to \\\n                         install from crates.io, or use --path or --git to \\\n                         specify an alternate source\",\n                            src.path().display()\n                        );\n                    } else if src.path().join(\"cargo.toml\").exists() {\n                        bail!(\n                            \"`{}` does not contain a Cargo.toml file, but found cargo.toml please try to rename it to Cargo.toml. \\\n                     --path must point to a directory containing a Cargo.toml file.\",\n                            src.path().display()\n                        )\n                    } else {\n                        bail!(\n                            \"`{}` does not contain a Cargo.toml file. \\\n                     --path must point to a directory containing a Cargo.toml file.\",\n                            src.path().display()\n                        )\n                    }\n                }\n                select_pkg(\n                    &mut src,\n                    dep,\n                    |path: &mut PathSource<'_>| path.root_package().map(|p| vec![p]),\n                    gctx,\n                    current_rust_version,\n                )?\n            } else if let Some(dep) = dep {\n                let mut source = map.load(source_id, &HashSet::new())?;\n                if let Ok(Some(pkg)) = installed_exact_package(\n                    dep.clone(),\n                    &mut *source,\n                    gctx,\n                    original_opts,\n                    &root,\n                    &dst,\n                    force,\n                ) {\n                    let msg = format!(\n                        \"package `{}` is already installed, use --force to override\",\n                        pkg\n                    );\n                    gctx.shell().status(\"Ignored\", &msg)?;\n                    return Ok(None);\n                }\n                select_dep_pkg(\n                    &mut *source,\n                    dep,\n                    gctx,\n                    needs_update_if_source_is_index,\n                    current_rust_version,\n                )?\n            } else {\n                bail!(\n                    \"must specify a crate to install from \\\n                         crates.io, or use --path or --git to \\\n                         specify alternate source\"\n                )\n            }\n        };\n\n        let (ws, rustc, target) =\n            make_ws_rustc_target(gctx, &original_opts, &source_id, pkg.clone())?;\n\n        if !gctx.lock_update_allowed() {\n            // When --lockfile-path is set, check that passed lock file exists\n            // (unlike the usual flag behavior, lockfile won't be created as we imply --locked)\n            if let Some(requested_lockfile_path) = ws.requested_lockfile_path() {\n                if !requested_lockfile_path.is_file() {\n                    bail!(\n                        \"no Cargo.lock file found in the requested path {}\",\n                        requested_lockfile_path.display()\n                    );\n                }\n            // If we're installing in --locked mode and there's no `Cargo.lock` published\n            // ie. the bin was published before https://github.com/rust-lang/cargo/pull/7026\n            } else if !ws.root().join(\"Cargo.lock\").exists() {\n                gctx.shell()\n                    .warn(format!(\"no Cargo.lock file published in {}\", pkg))?;\n            }\n        }\n        let pkg = if source_id.is_git() {\n            // Don't use ws.current() in order to keep the package source as a git source so that\n            // install tracking uses the correct source.\n            pkg\n        } else {\n            ws.current()?.clone()\n        };\n\n        // When we build this package, we want to build the *specified* package only,\n        // and avoid building e.g. workspace default-members instead. Do so by constructing\n        // specialized compile options specific to the identified package.\n        // See test `path_install_workspace_root_despite_default_members`.\n        let mut opts = original_opts.clone();\n        // For cargo install tracking, we retain the source git url in `pkg`, but for the build spec\n        // we need to unconditionally use `ws.current()` to correctly address the path where we\n        // locally cloned that repo.\n        let pkgidspec = ws.current()?.package_id().to_spec();\n        opts.spec = Packages::Packages(vec![pkgidspec.to_string()]);\n\n        if from_cwd {\n            if pkg.manifest().edition() == Edition::Edition2015 {\n                gctx.shell().warn(\n                    \"using `cargo install` to install the binaries from the \\\n                     package in current working directory is deprecated, \\\n                     use `cargo install --path .` instead. \\\n                     note: use `cargo build` if you want to simply build the package.\",\n                )?\n            } else {\n                bail!(\n                    \"using `cargo install` to install the binaries from the \\\n                     package in current working directory is no longer supported, \\\n                     use `cargo install --path .` instead. \\\n                     note: use `cargo build` if you want to simply build the package.\"\n                )\n            }\n        };\n\n        // For bare `cargo install` (no `--bin` or `--example`), check if there is\n        // *something* to install. Explicit `--bin` or `--example` flags will be\n        // checked at the start of `compile_ws`.\n        if !opts.filter.is_specific() && !pkg.targets().iter().any(|t| t.is_bin()) {\n            bail!(\n                \"there is nothing to install in `{}`, because it has no binaries\\n\\\n                 `cargo install` is only for installing programs, and can't be used with libraries.\\n\\\n                 To use a library crate, add it as a dependency to a Cargo project with `cargo add`.\",\n                pkg,\n            );\n        }\n\n        let ip = InstallablePackage {\n            gctx,\n            opts,\n            root,\n            source_id,\n            vers: vers.cloned(),\n            force,\n            no_track,\n            pkg,\n            ws,\n            rustc,\n            target,\n        };\n\n        // WARNING: no_track does not perform locking, so there is no protection\n        // of concurrent installs.\n        if no_track {\n            // Check for conflicts.\n            ip.no_track_duplicates(&dst)?;\n        } else if is_installed(\n            &ip.pkg, gctx, &ip.opts, &ip.rustc, &ip.target, &ip.root, &dst, force,\n        )? {\n            let msg = format!(\n                \"package `{}` is already installed, use --force to override\",\n                ip.pkg\n            );\n            gctx.shell().status(\"Ignored\", &msg)?;\n            return Ok(None);\n        }\n\n        Ok(Some(ip))\n    }\n\n    fn no_track_duplicates(&self, dst: &Path) -> CargoResult<BTreeMap<String, Option<PackageId>>> {\n        // Helper for --no-track flag to make sure it doesn't overwrite anything.\n        let duplicates: BTreeMap<String, Option<PackageId>> =\n            exe_names(&self.pkg, &self.opts.filter)\n                .into_iter()\n                .filter(|name| dst.join(name).exists())\n                .map(|name| (name, None))\n                .collect();\n        if !self.force && !duplicates.is_empty() {\n            let mut msg: Vec<String> = duplicates\n                .iter()\n                .map(|(name, _)| {\n                    format!(\n                        \"binary `{}` already exists in destination `{}`\",\n                        name,\n                        dst.join(name).to_string_lossy()\n                    )\n                })\n                .collect();\n            msg.push(\"Add --force to overwrite\".to_string());\n            bail!(\"{}\", msg.join(\"\\n\"));\n        }\n        Ok(duplicates)\n    }\n\n    fn install_one(mut self, dry_run: bool) -> CargoResult<bool> {\n        self.gctx.shell().status(\"Installing\", &self.pkg)?;\n\n        // Normalize to absolute path for consistency throughout.\n        // See: https://github.com/rust-lang/cargo/issues/16023\n        let dst = self.root.join(\"bin\").into_path_unlocked();\n        let cwd = self.gctx.cwd();\n        let dst = if dst.is_absolute() {\n            paths::normalize_path(dst.as_path())\n        } else {\n            paths::normalize_path(&cwd.join(&dst))\n        };\n\n        let mut td_opt = None;\n        let mut needs_cleanup = false;\n        if !self.source_id.is_path() {\n            let target_dir = if let Some(dir) = self.gctx.target_dir()? {\n                dir\n            } else if let Ok(td) = TempFileBuilder::new().prefix(\"cargo-install\").tempdir() {\n                let p = td.path().to_owned();\n                td_opt = Some(td);\n                Filesystem::new(p)\n            } else {\n                needs_cleanup = true;\n                Filesystem::new(self.gctx.cwd().join(\"target-install\"))\n            };\n            self.ws.set_target_dir(target_dir);\n        }\n\n        self.check_yanked_install()?;\n\n        let exec: Arc<dyn Executor> = Arc::new(DefaultExecutor);\n        self.opts.build_config.dry_run = dry_run;\n        let compile = ops::compile_ws(&self.ws, &self.opts, &exec).with_context(|| {\n            if let Some(td) = td_opt.take() {\n                // preserve the temporary directory, so the user can inspect it\n                drop(td.keep());\n            }\n\n            format!(\n                \"failed to compile `{}`, intermediate artifacts can be \\\n                 found at `{}`.\\nTo reuse those artifacts with a future \\\n                 compilation, set the environment variable \\\n                 `CARGO_BUILD_BUILD_DIR` to that path.\",\n                self.pkg,\n                self.ws.build_dir().display()\n            )\n        })?;\n        let mut binaries: Vec<(&str, &Path)> = compile\n            .binaries\n            .iter()\n            .map(|UnitOutput { path, .. }| {\n                let name = path.file_name().unwrap();\n                if let Some(s) = name.to_str() {\n                    Ok((s, path.as_ref()))\n                } else {\n                    bail!(\"Binary `{:?}` name can't be serialized into string\", name)\n                }\n            })\n            .collect::<CargoResult<_>>()?;\n        if binaries.is_empty() {\n            // Cargo already warns the user if they use a target specifier that matches nothing,\n            // but we want to error if the user asked for a _particular_ binary to be installed,\n            // and we didn't end up installing it.\n            //\n            // NOTE: This _should_ be impossible to hit since --bin=does_not_exist will fail on\n            // target selection, and --bin=requires_a without --features=a will fail with \"target\n            // .. requires the features ..\". But rather than assume that's the case, we define the\n            // behavior for this fallback case as well.\n            if let CompileFilter::Only { bins, examples, .. } = &self.opts.filter {\n                let mut any_specific = false;\n                if let FilterRule::Just(v) = bins {\n                    if !v.is_empty() {\n                        any_specific = true;\n                    }\n                }\n                if let FilterRule::Just(v) = examples {\n                    if !v.is_empty() {\n                        any_specific = true;\n                    }\n                }\n                if any_specific {\n                    bail!(\"no binaries are available for install using the selected features\");\n                }\n            }\n\n            // If there _are_ binaries available, but none were selected given the current set of\n            // features, let the user know.\n            //\n            // Note that we know at this point that _if_ bins or examples is set to `::Just`,\n            // they're `::Just([])`, which is `FilterRule::none()`.\n            let binaries: Vec<_> = self\n                .pkg\n                .targets()\n                .iter()\n                .filter(|t| t.is_executable())\n                .collect();\n            if !binaries.is_empty() {\n                self.gctx\n                    .shell()\n                    .warn(make_warning_about_missing_features(&binaries))?;\n            }\n\n            return Ok(false);\n        }\n        // This is primarily to make testing easier.\n        binaries.sort_unstable();\n\n        let (tracker, duplicates) = if self.no_track {\n            (None, self.no_track_duplicates(&dst)?)\n        } else {\n            let tracker = InstallTracker::load(self.gctx, &self.root)?;\n            let (_freshness, duplicates) = tracker.check_upgrade(\n                &dst,\n                &self.pkg,\n                self.force,\n                &self.opts,\n                &self.target,\n                &self.rustc.verbose_version,\n            )?;\n            (Some(tracker), duplicates)\n        };\n\n        paths::create_dir_all(&dst)?;\n\n        // Copy all binaries to a temporary directory under `dst` first, catching\n        // some failure modes (e.g., out of space) before touching the existing\n        // binaries. This directory will get cleaned up via RAII.\n        let staging_dir = TempFileBuilder::new()\n            .prefix(\"cargo-install\")\n            .tempdir_in(&dst)?;\n        if !dry_run {\n            for &(bin, src) in binaries.iter() {\n                let dst = staging_dir.path().join(bin);\n                // Try to move if `target_dir` is transient.\n                if !self.source_id.is_path() && fs::rename(src, &dst).is_ok() {\n                    continue;\n                }\n                paths::copy(src, &dst)?;\n            }\n        }\n\n        let (to_replace, to_install): (Vec<&str>, Vec<&str>) = binaries\n            .iter()\n            .map(|&(bin, _)| bin)\n            .partition(|&bin| duplicates.contains_key(bin));\n\n        let mut installed = Transaction { bins: Vec::new() };\n        let mut successful_bins = BTreeSet::new();\n\n        // Move the temporary copies into `dst` starting with new binaries.\n        for bin in to_install.iter() {\n            let src = staging_dir.path().join(bin);\n            let dst = dst.join(bin);\n            self.gctx.shell().status(\"Installing\", dst.display())?;\n            if !dry_run {\n                fs::rename(&src, &dst).with_context(|| {\n                    format!(\"failed to move `{}` to `{}`\", src.display(), dst.display())\n                })?;\n                installed.bins.push(dst);\n                successful_bins.insert(bin.to_string());\n            }\n        }\n\n        // Repeat for binaries which replace existing ones but don't pop the error\n        // up until after updating metadata.\n        let replace_result = {\n            let mut try_install = || -> CargoResult<()> {\n                for &bin in to_replace.iter() {\n                    let src = staging_dir.path().join(bin);\n                    let dst = dst.join(bin);\n                    self.gctx.shell().status(\"Replacing\", dst.display())?;\n                    if !dry_run {\n                        fs::rename(&src, &dst).with_context(|| {\n                            format!(\"failed to move `{}` to `{}`\", src.display(), dst.display())\n                        })?;\n                        successful_bins.insert(bin.to_string());\n                    }\n                }\n                Ok(())\n            };\n            try_install()\n        };\n\n        if let Some(mut tracker) = tracker {\n            tracker.mark_installed(\n                &self.pkg,\n                &successful_bins,\n                self.vers.map(|s| s.to_string()),\n                &self.opts,\n                &self.target,\n                &self.rustc.verbose_version,\n            );\n\n            if let Err(e) = remove_orphaned_bins(\n                &self.ws,\n                &mut tracker,\n                &duplicates,\n                &self.pkg,\n                &dst,\n                dry_run,\n            ) {\n                // Don't hard error on remove.\n                self.gctx\n                    .shell()\n                    .warn(format!(\"failed to remove orphan: {:?}\", e))?;\n            }\n\n            match tracker.save() {\n                Err(err) => replace_result.with_context(|| err)?,\n                Ok(_) => replace_result?,\n            }\n        }\n\n        // Reaching here means all actions have succeeded. Clean up.\n        installed.success();\n        if needs_cleanup {\n            // Don't bother grabbing a lock as we're going to blow it all away\n            // anyway.\n            let target_dir = self.ws.target_dir().into_path_unlocked();\n            paths::remove_dir_all(&target_dir)?;\n        }\n\n        // Helper for creating status messages.\n        fn executables<T: AsRef<str>>(mut names: impl Iterator<Item = T> + Clone) -> String {\n            if names.clone().count() == 1 {\n                format!(\"(executable `{}`)\", names.next().unwrap().as_ref())\n            } else {\n                format!(\n                    \"(executables {})\",\n                    names\n                        .map(|b| format!(\"`{}`\", b.as_ref()))\n                        .collect::<Vec<_>>()\n                        .join(\", \")\n                )\n            }\n        }\n\n        if dry_run {\n            self.gctx.shell().warn(\"aborting install due to dry run\")?;\n            Ok(true)\n        } else if duplicates.is_empty() {\n            self.gctx.shell().status(\n                \"Installed\",\n                format!(\n                    \"package `{}` {}\",\n                    self.pkg,\n                    executables(successful_bins.iter())\n                ),\n            )?;\n            Ok(true)\n        } else {\n            if !to_install.is_empty() {\n                self.gctx.shell().status(\n                    \"Installed\",\n                    format!(\"package `{}` {}\", self.pkg, executables(to_install.iter())),\n                )?;\n            }\n            // Invert the duplicate map.\n            let mut pkg_map = BTreeMap::new();\n            for (bin_name, opt_pkg_id) in &duplicates {\n                let key =\n                    opt_pkg_id.map_or_else(|| \"unknown\".to_string(), |pkg_id| pkg_id.to_string());\n                pkg_map.entry(key).or_insert_with(Vec::new).push(bin_name);\n            }\n            for (pkg_descr, bin_names) in &pkg_map {\n                self.gctx.shell().status(\n                    \"Replaced\",\n                    format!(\n                        \"package `{}` with `{}` {}\",\n                        pkg_descr,\n                        self.pkg,\n                        executables(bin_names.iter())\n                    ),\n                )?;\n            }\n            Ok(true)\n        }\n    }\n\n    fn check_yanked_install(&self) -> CargoResult<()> {\n        if self.ws.ignore_lock() || !self.ws.root().join(\"Cargo.lock\").exists() {\n            return Ok(());\n        }\n        // It would be best if `source` could be passed in here to avoid a\n        // duplicate \"Updating\", but since `source` is taken by value, then it\n        // wouldn't be available for `compile_ws`.\n        let dry_run = false;\n        let (pkg_set, resolve) = ops::resolve_ws(&self.ws, dry_run)?;\n        ops::check_yanked(\n            self.ws.gctx(),\n            &pkg_set,\n            &resolve,\n            \"consider running without --locked\",\n        )\n    }\n}\n\nfn make_warning_about_missing_features(binaries: &[&Target]) -> String {\n    let max_targets_listed = 7;\n    let target_features_message = binaries\n        .iter()\n        .take(max_targets_listed)\n        .map(|b| {\n            let name = b.description_named();\n            let features = b\n                .required_features()\n                .unwrap_or(&Vec::new())\n                .iter()\n                .map(|f| format!(\"`{f}`\"))\n                .join(\", \");\n            format!(\"  {name} requires the features: {features}\")\n        })\n        .join(\"\\n\");\n\n    let additional_bins_message = if binaries.len() > max_targets_listed {\n        format!(\n            \"\\n{} more targets also requires features not enabled. See them in the Cargo.toml file.\",\n            binaries.len() - max_targets_listed\n        )\n    } else {\n        \"\".into()\n    };\n\n    let example_features = binaries[0]\n        .required_features()\n        .map(|f| f.join(\" \"))\n        .unwrap_or_default();\n\n    format!(\n        \"\\\nnone of the package's binaries are available for install using the selected features\n{target_features_message}{additional_bins_message}\nConsider enabling some of the needed features by passing, e.g., `--features=\\\"{example_features}\\\"`\"\n    )\n}\n\npub fn install(\n    gctx: &GlobalContext,\n    root: Option<&str>,\n    krates: Vec<(String, Option<VersionReq>)>,\n    source_id: SourceId,\n    from_cwd: bool,\n    opts: &ops::CompileOptions,\n    force: bool,\n    no_track: bool,\n    dry_run: bool,\n) -> CargoResult<()> {\n    let root = resolve_root(root, gctx)?;\n    // Normalize to absolute path for consistency throughout.\n    // See: https://github.com/rust-lang/cargo/issues/16023\n    let dst = root.join(\"bin\").into_path_unlocked();\n    let cwd = gctx.cwd();\n    let dst = if dst.is_absolute() {\n        paths::normalize_path(dst.as_path())\n    } else {\n        paths::normalize_path(&cwd.join(&dst))\n    };\n    let map = SourceConfigMap::new(gctx)?;\n\n    let current_rust_version = if opts.honor_rust_version.unwrap_or(true) {\n        let rustc = gctx.load_global_rustc(None)?;\n        Some(rustc.version.clone().into())\n    } else {\n        None\n    };\n\n    let (installed_anything, scheduled_error) = if krates.len() <= 1 {\n        let (krate, vers) = krates\n            .iter()\n            .next()\n            .map(|(k, v)| (Some(k.as_str()), v.as_ref()))\n            .unwrap_or((None, None));\n        let installable_pkg = InstallablePackage::new(\n            gctx,\n            root,\n            map,\n            krate,\n            source_id,\n            from_cwd,\n            vers,\n            opts,\n            force,\n            no_track,\n            true,\n            current_rust_version.as_ref(),\n        )?;\n        let mut installed_anything = true;\n        if let Some(installable_pkg) = installable_pkg {\n            installed_anything = installable_pkg.install_one(dry_run)?;\n        }\n        (installed_anything, false)\n    } else {\n        let mut succeeded = vec![];\n        let mut failed = vec![];\n        // \"Tracks whether or not the source (such as a registry or git repo) has been updated.\n        // This is used to avoid updating it multiple times when installing multiple crates.\n        let mut did_update = false;\n\n        let pkgs_to_install: Vec<_> = krates\n            .iter()\n            .filter_map(|(krate, vers)| {\n                let root = root.clone();\n                let map = map.clone();\n                match InstallablePackage::new(\n                    gctx,\n                    root,\n                    map,\n                    Some(krate.as_str()),\n                    source_id,\n                    from_cwd,\n                    vers.as_ref(),\n                    opts,\n                    force,\n                    no_track,\n                    !did_update,\n                    current_rust_version.as_ref(),\n                ) {\n                    Ok(Some(installable_pkg)) => {\n                        did_update = true;\n                        Some((krate, installable_pkg))\n                    }\n                    Ok(None) => {\n                        // Already installed\n                        succeeded.push(krate.as_str());\n                        None\n                    }\n                    Err(e) => {\n                        crate::display_error(&e, &mut gctx.shell());\n                        failed.push(krate.as_str());\n                        // We assume an update was performed if we got an error.\n                        did_update = true;\n                        None\n                    }\n                }\n            })\n            .collect();\n\n        let install_results: Vec<_> = pkgs_to_install\n            .into_iter()\n            .map(|(krate, installable_pkg)| (krate, installable_pkg.install_one(dry_run)))\n            .collect();\n\n        for (krate, result) in install_results {\n            match result {\n                Ok(installed) => {\n                    if installed {\n                        succeeded.push(krate);\n                    }\n                }\n                Err(e) => {\n                    crate::display_error(&e, &mut gctx.shell());\n                    failed.push(krate);\n                }\n            }\n        }\n\n        let mut summary = vec![];\n        if !succeeded.is_empty() {\n            summary.push(format!(\"Successfully installed {}!\", succeeded.join(\", \")));\n        }\n        if !failed.is_empty() {\n            summary.push(format!(\n                \"Failed to install {} (see error(s) above).\",\n                failed.join(\", \")\n            ));\n        }\n        if !succeeded.is_empty() || !failed.is_empty() {\n            gctx.shell().status(\"Summary\", summary.join(\" \"))?;\n        }\n\n        (!succeeded.is_empty(), !failed.is_empty())\n    };\n\n    if installed_anything {\n        // Print a warning that if this directory isn't in PATH that they won't be\n        // able to run these commands.\n        let path = gctx.get_env_os(\"PATH\").unwrap_or_default();\n        let dst_in_path = env::split_paths(&path).any(|path| path == dst);\n\n        if !dst_in_path {\n            gctx.shell().warn(&format!(\n                \"be sure to add `{}` to your PATH to be \\\n             able to run the installed binaries\",\n                dst.display()\n            ))?;\n        }\n    }\n\n    if scheduled_error {\n        bail!(\"some crates failed to install\");\n    }\n\n    Ok(())\n}\n\nfn is_installed(\n    pkg: &Package,\n    gctx: &GlobalContext,\n    opts: &ops::CompileOptions,\n    rustc: &Rustc,\n    target: &str,\n    root: &Filesystem,\n    dst: &Path,\n    force: bool,\n) -> CargoResult<bool> {\n    let tracker = InstallTracker::load(gctx, root)?;\n    let (freshness, _duplicates) =\n        tracker.check_upgrade(dst, pkg, force, opts, target, &rustc.verbose_version)?;\n    Ok(freshness.is_fresh())\n}\n\n/// Checks if vers can only be satisfied by exactly one version of a package in a registry, and it's\n/// already installed. If this is the case, we can skip interacting with a registry to check if\n/// newer versions may be installable, as no newer version can exist.\nfn installed_exact_package(\n    dep: Dependency,\n    source: &mut dyn Source,\n    gctx: &GlobalContext,\n    opts: &ops::CompileOptions,\n    root: &Filesystem,\n    dst: &Path,\n    force: bool,\n) -> CargoResult<Option<Package>> {\n    if !dep.version_req().is_exact() {\n        // If the version isn't exact, we may need to update the registry and look for a newer\n        // version - we can't know if the package is installed without doing so.\n        return Ok(None);\n    }\n    // Try getting the package from the registry  without updating it, to avoid a potentially\n    // expensive network call in the case that the package is already installed.\n    // If this fails, the caller will possibly do an index update and try again, this is just a\n    // best-effort check to see if we can avoid hitting the network.\n    if let Ok(pkg) = select_dep_pkg(source, dep, gctx, false, None) {\n        let (_ws, rustc, target) =\n            make_ws_rustc_target(gctx, opts, &source.source_id(), pkg.clone())?;\n        if let Ok(true) = is_installed(&pkg, gctx, opts, &rustc, &target, root, dst, force) {\n            return Ok(Some(pkg));\n        }\n    }\n    Ok(None)\n}\n\nfn make_ws_rustc_target<'gctx>(\n    gctx: &'gctx GlobalContext,\n    opts: &ops::CompileOptions,\n    source_id: &SourceId,\n    pkg: Package,\n) -> CargoResult<(Workspace<'gctx>, Rustc, String)> {\n    let mut ws = if source_id.is_git() || source_id.is_path() {\n        Workspace::new(pkg.manifest_path(), gctx)?\n    } else {\n        let mut ws = Workspace::ephemeral(pkg, gctx, None, false)?;\n        ws.set_resolve_honors_rust_version(Some(false));\n        ws\n    };\n    ws.set_resolve_feature_unification(FeatureUnification::Selected);\n    ws.set_ignore_lock(gctx.lock_update_allowed());\n    ws.set_require_optional_deps(false);\n\n    let rustc = gctx.load_global_rustc(Some(&ws))?;\n    let target = match &opts.build_config.single_requested_kind()? {\n        CompileKind::Host => rustc.host.as_str().to_owned(),\n        CompileKind::Target(target) => target.short_name().to_owned(),\n    };\n\n    Ok((ws, rustc, target))\n}\n\n/// Display a list of installed binaries.\npub fn install_list(dst: Option<&str>, gctx: &GlobalContext) -> CargoResult<()> {\n    let root = resolve_root(dst, gctx)?;\n    let tracker = InstallTracker::load(gctx, &root)?;\n    for (k, v) in tracker.all_installed_bins() {\n        drop_println!(gctx, \"{}:\", k);\n        for bin in v {\n            drop_println!(gctx, \"    {}\", bin);\n        }\n    }\n    Ok(())\n}\n\n/// Removes executables that are no longer part of a package that was\n/// previously installed.\nfn remove_orphaned_bins(\n    ws: &Workspace<'_>,\n    tracker: &mut InstallTracker,\n    duplicates: &BTreeMap<String, Option<PackageId>>,\n    pkg: &Package,\n    dst: &Path,\n    dry_run: bool,\n) -> CargoResult<()> {\n    let filter = ops::CompileFilter::new_all_targets();\n    let all_self_names = exe_names(pkg, &filter);\n    let mut to_remove: HashMap<PackageId, BTreeSet<String>> = HashMap::new();\n    // For each package that we stomped on.\n    for other_pkg in duplicates.values().flatten() {\n        // Only for packages with the same name.\n        if other_pkg.name() == pkg.name() {\n            // Check what the old package had installed.\n            if let Some(installed) = tracker.installed_bins(*other_pkg) {\n                // If the old install has any names that no longer exist,\n                // add them to the list to remove.\n                for installed_name in installed {\n                    if !all_self_names.contains(installed_name.as_str()) {\n                        to_remove\n                            .entry(*other_pkg)\n                            .or_default()\n                            .insert(installed_name.clone());\n                    }\n                }\n            }\n        }\n    }\n\n    for (old_pkg, bins) in to_remove {\n        tracker.remove(old_pkg, &bins);\n        for bin in bins {\n            let full_path = dst.join(bin);\n            if full_path.exists() {\n                ws.gctx().shell().status(\n                    \"Removing\",\n                    format!(\n                        \"executable `{}` from previous version {}\",\n                        full_path.display(),\n                        old_pkg\n                    ),\n                )?;\n                if !dry_run {\n                    paths::remove_file(&full_path)\n                        .with_context(|| format!(\"failed to remove {:?}\", full_path))?;\n                }\n            }\n        }\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_new.rs",
    "content": "use crate::core::{Edition, Shell, Workspace};\nuse crate::util::errors::CargoResult;\nuse crate::util::important_paths::find_root_manifest_for_wd;\nuse crate::util::{FossilRepo, GitRepo, HgRepo, PijulRepo, existing_vcs_repo};\nuse crate::util::{GlobalContext, restricted_names};\nuse anyhow::{Context as _, anyhow};\nuse cargo_util::paths::{self, write_atomic};\nuse cargo_util_schemas::manifest::PackageName;\nuse home::home_dir;\nuse serde::Deserialize;\nuse serde::de;\nuse std::collections::BTreeMap;\nuse std::ffi::OsStr;\nuse std::io::{BufRead, BufReader, ErrorKind};\nuse std::path::{Path, PathBuf};\nuse std::str::FromStr;\nuse std::{fmt, slice};\nuse toml_edit::{Array, Value};\n\n#[derive(Clone, Copy, Debug, PartialEq)]\npub enum VersionControl {\n    Git,\n    Hg,\n    Pijul,\n    Fossil,\n    NoVcs,\n}\n\nimpl FromStr for VersionControl {\n    type Err = anyhow::Error;\n\n    fn from_str(s: &str) -> Result<Self, anyhow::Error> {\n        match s {\n            \"git\" => Ok(VersionControl::Git),\n            \"hg\" => Ok(VersionControl::Hg),\n            \"pijul\" => Ok(VersionControl::Pijul),\n            \"fossil\" => Ok(VersionControl::Fossil),\n            \"none\" => Ok(VersionControl::NoVcs),\n            other => anyhow::bail!(\"unknown vcs specification: `{}`\", other),\n        }\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for VersionControl {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        let s = String::deserialize(deserializer)?;\n        FromStr::from_str(&s).map_err(de::Error::custom)\n    }\n}\n\n#[derive(Debug)]\npub struct NewOptions {\n    pub version_control: Option<VersionControl>,\n    pub kind: NewProjectKind,\n    pub auto_detect_kind: bool,\n    /// Absolute path to the directory for the new package\n    pub path: PathBuf,\n    pub name: Option<String>,\n    pub edition: Option<String>,\n    pub registry: Option<String>,\n}\n\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npub enum NewProjectKind {\n    Bin,\n    Lib,\n}\n\nimpl NewProjectKind {\n    fn is_bin(self) -> bool {\n        self == NewProjectKind::Bin\n    }\n}\n\nimpl fmt::Display for NewProjectKind {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match *self {\n            NewProjectKind::Bin => \"binary (application)\",\n            NewProjectKind::Lib => \"library\",\n        }\n        .fmt(f)\n    }\n}\n\nstruct SourceFileInformation {\n    relative_path: String,\n    bin: bool,\n}\n\nstruct MkOptions<'a> {\n    version_control: Option<VersionControl>,\n    path: &'a Path,\n    name: &'a str,\n    source_files: Vec<SourceFileInformation>,\n    edition: Option<&'a str>,\n    registry: Option<&'a str>,\n}\n\nimpl NewOptions {\n    pub fn new(\n        version_control: Option<VersionControl>,\n        bin: bool,\n        lib: bool,\n        path: PathBuf,\n        name: Option<String>,\n        edition: Option<String>,\n        registry: Option<String>,\n    ) -> CargoResult<NewOptions> {\n        let auto_detect_kind = !bin && !lib;\n\n        let kind = match (bin, lib) {\n            (true, true) => anyhow::bail!(\"can't specify both lib and binary outputs\"),\n            (false, true) => NewProjectKind::Lib,\n            (_, false) => NewProjectKind::Bin,\n        };\n\n        let opts = NewOptions {\n            version_control,\n            kind,\n            auto_detect_kind,\n            path,\n            name,\n            edition,\n            registry,\n        };\n        Ok(opts)\n    }\n}\n\n#[derive(Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\nstruct CargoNewConfig {\n    #[deprecated = \"cargo-new no longer supports adding the authors field\"]\n    #[expect(dead_code, reason = \"deprecated\")]\n    name: Option<String>,\n\n    #[deprecated = \"cargo-new no longer supports adding the authors field\"]\n    #[expect(dead_code, reason = \"deprecated\")]\n    email: Option<String>,\n\n    #[serde(rename = \"vcs\")]\n    version_control: Option<VersionControl>,\n}\n\nfn get_name<'a>(path: &'a Path, opts: &'a NewOptions) -> CargoResult<&'a str> {\n    if let Some(ref name) = opts.name {\n        return Ok(name);\n    }\n\n    let file_name = path.file_name().ok_or_else(|| {\n        anyhow::format_err!(\n            \"cannot auto-detect package name from path {:?} ; use --name to override\",\n            path.as_os_str()\n        )\n    })?;\n\n    file_name.to_str().ok_or_else(|| {\n        anyhow::format_err!(\n            \"cannot create package with a non-unicode name: {:?}\",\n            file_name\n        )\n    })\n}\n\n/// See also `util::toml::embedded::sanitize_name`\nfn check_name(\n    name: &str,\n    show_name_help: bool,\n    has_bin: bool,\n    shell: &mut Shell,\n) -> CargoResult<()> {\n    // If --name is already used to override, no point in suggesting it\n    // again as a fix.\n    let name_help = if show_name_help {\n        \"\\nnote: the directory name is used as the package name\\\n        \\nhelp: to override the package name, pass `--name <pkgname>`\"\n    } else {\n        \"\"\n    };\n    let bin_help = || {\n        let mut help = String::from(name_help);\n        // Only suggest `bin.name` for valid crate names because it is used for `--crate`\n        if has_bin && validate_crate_name(name) {\n            help.push_str(&format!(\n                \"\\n\\\n                help: to name the binary \\\"{name}\\\", use a valid package \\\n                name, and set the binary name to be different from the package. \\\n                This can be done by setting the binary filename to `src/bin/{name}.rs` \\\n                or change the name in Cargo.toml with:\\n\\\n                \\n    \\\n                [[bin]]\\n    \\\n                name = \\\"{name}\\\"\\n    \\\n                path = \\\"src/main.rs\\\"\\n\\\n            \",\n                name = name\n            ));\n        }\n        help\n    };\n    PackageName::new(name).map_err(|err| {\n        let help = bin_help();\n        anyhow::anyhow!(\"{err}{help}\")\n    })?;\n\n    if restricted_names::is_keyword(name) {\n        anyhow::bail!(\n            \"invalid package name `{}`: it is a Rust keyword{}\",\n            name,\n            bin_help()\n        );\n    }\n    if restricted_names::is_conflicting_artifact_name(name) {\n        if has_bin {\n            anyhow::bail!(\n                \"invalid package name `{}`: \\\n                it conflicts with cargo's build directory names{}\",\n                name,\n                name_help\n            );\n        } else {\n            shell.warn(format!(\n                \"package `{}` will not support binary \\\n                executables with that name, \\\n                it conflicts with cargo's build directory names\",\n                name\n            ))?;\n        }\n    }\n    if name == \"test\" {\n        anyhow::bail!(\n            \"invalid package name `test`: \\\n            it conflicts with Rust's built-in test library{}\",\n            bin_help()\n        );\n    }\n    if [\"core\", \"std\", \"alloc\", \"proc_macro\", \"proc-macro\"].contains(&name) {\n        shell.warn(format!(\n            \"package name `{}` may be confused with the package with that name in Rust's standard library\\n\\\n            It is recommended to use a different name to avoid problems.{}\",\n            name,\n            bin_help()\n        ))?;\n    }\n    if restricted_names::is_windows_reserved(name) {\n        if cfg!(windows) {\n            anyhow::bail!(\n                \"invalid package name `{}`: it is a reserved Windows filename{}\",\n                name,\n                name_help\n            );\n        } else {\n            shell.warn(format!(\n                \"package name `{}` is a reserved Windows filename\\n\\\n                This package will not work on Windows platforms.\",\n                name\n            ))?;\n        }\n    }\n    if restricted_names::is_non_ascii_name(name) {\n        shell.warn(format!(\n            \"invalid package name `{}`: contains non-ASCII characters\\n\\\n            Non-ASCII crate names are not supported by Rust.\",\n            name\n        ))?;\n    }\n    let name_in_lowercase = name.to_lowercase();\n    if name != name_in_lowercase {\n        shell.warn(format!(\n            \"package name `{name}` is not snake_case or kebab-case which is recommended for package names, consider `{name_in_lowercase}`\"\n        ))?;\n    }\n\n    Ok(())\n}\n\n// Taken from <https://github.com/rust-lang/rust/blob/693f365667a97b24cb40173bc2801eb66ea53020/compiler/rustc_session/src/output.rs#L49-L79>\nfn validate_crate_name(name: &str) -> bool {\n    if name.is_empty() {\n        return false;\n    }\n\n    for c in name.chars() {\n        if c.is_alphanumeric() || c == '-' || c == '_' {\n            continue;\n        } else {\n            return false;\n        }\n    }\n\n    true\n}\n\n/// Checks if the path contains any invalid PATH env characters.\nfn check_path(path: &Path, shell: &mut Shell) -> CargoResult<()> {\n    // warn if the path contains characters that will break `env::join_paths`\n    if let Err(_) = paths::join_paths(slice::from_ref(&OsStr::new(path)), \"\") {\n        let path = path.to_string_lossy();\n        shell.warn(format!(\n            \"the path `{path}` contains invalid PATH characters (usually `:`, `;`, or `\\\"`)\\n\\\n            It is recommended to use a different name to avoid problems.\"\n        ))?;\n    }\n    Ok(())\n}\n\nfn detect_source_paths_and_types(\n    package_path: &Path,\n    package_name: &str,\n    detected_files: &mut Vec<SourceFileInformation>,\n) -> CargoResult<()> {\n    let path = package_path;\n    let name = package_name;\n\n    enum H {\n        Bin,\n        Lib,\n        Detect,\n    }\n\n    struct Test {\n        proposed_path: String,\n        handling: H,\n    }\n\n    let tests = vec![\n        Test {\n            proposed_path: \"src/main.rs\".to_string(),\n            handling: H::Bin,\n        },\n        Test {\n            proposed_path: \"main.rs\".to_string(),\n            handling: H::Bin,\n        },\n        Test {\n            proposed_path: format!(\"src/{}.rs\", name),\n            handling: H::Detect,\n        },\n        Test {\n            proposed_path: format!(\"{}.rs\", name),\n            handling: H::Detect,\n        },\n        Test {\n            proposed_path: \"src/lib.rs\".to_string(),\n            handling: H::Lib,\n        },\n        Test {\n            proposed_path: \"lib.rs\".to_string(),\n            handling: H::Lib,\n        },\n    ];\n\n    for i in tests {\n        let pp = i.proposed_path;\n\n        // path/pp does not exist or is not a file\n        if !path.join(&pp).is_file() {\n            continue;\n        }\n\n        let sfi = match i.handling {\n            H::Bin => SourceFileInformation {\n                relative_path: pp,\n                bin: true,\n            },\n            H::Lib => SourceFileInformation {\n                relative_path: pp,\n                bin: false,\n            },\n            H::Detect => {\n                let content = paths::read(&path.join(pp.clone()))?;\n                let isbin = content.contains(\"fn main\");\n                SourceFileInformation {\n                    relative_path: pp,\n                    bin: isbin,\n                }\n            }\n        };\n        detected_files.push(sfi);\n    }\n\n    // Check for duplicate lib attempt\n\n    let mut previous_lib_relpath: Option<&str> = None;\n    let mut duplicates_checker: BTreeMap<&str, &SourceFileInformation> = BTreeMap::new();\n\n    for i in detected_files {\n        if i.bin {\n            if let Some(x) = BTreeMap::get::<str>(&duplicates_checker, &name) {\n                anyhow::bail!(\n                    \"\\\nmultiple possible binary sources found:\n  {}\n  {}\ncannot automatically generate Cargo.toml as the main target would be ambiguous\",\n                    &x.relative_path,\n                    &i.relative_path\n                );\n            }\n            duplicates_checker.insert(name, i);\n        } else {\n            if let Some(plp) = previous_lib_relpath {\n                anyhow::bail!(\n                    \"cannot have a package with \\\n                     multiple libraries, \\\n                     found both `{}` and `{}`\",\n                    plp,\n                    i.relative_path\n                )\n            }\n            previous_lib_relpath = Some(&i.relative_path);\n        }\n    }\n\n    Ok(())\n}\n\nfn plan_new_source_file(bin: bool) -> SourceFileInformation {\n    if bin {\n        SourceFileInformation {\n            relative_path: \"src/main.rs\".to_string(),\n            bin: true,\n        }\n    } else {\n        SourceFileInformation {\n            relative_path: \"src/lib.rs\".to_string(),\n            bin: false,\n        }\n    }\n}\n\nfn calculate_new_project_kind(\n    requested_kind: NewProjectKind,\n    auto_detect_kind: bool,\n    found_files: &Vec<SourceFileInformation>,\n) -> NewProjectKind {\n    let bin_file = found_files.iter().find(|x| x.bin);\n\n    let kind_from_files = if !found_files.is_empty() && bin_file.is_none() {\n        NewProjectKind::Lib\n    } else {\n        NewProjectKind::Bin\n    };\n\n    if auto_detect_kind {\n        return kind_from_files;\n    }\n\n    requested_kind\n}\n\npub fn new(opts: &NewOptions, gctx: &GlobalContext) -> CargoResult<()> {\n    let path = &opts.path;\n    let name = get_name(path, opts)?;\n    gctx.shell()\n        .status(\"Creating\", format!(\"{} `{}` package\", opts.kind, name))?;\n\n    if path.exists() {\n        anyhow::bail!(\n            \"destination `{}` already exists\\n\\n\\\n             Use `cargo init` to initialize the directory\",\n            path.display()\n        )\n    }\n    check_path(path, &mut gctx.shell())?;\n\n    let is_bin = opts.kind.is_bin();\n\n    check_name(name, opts.name.is_none(), is_bin, &mut gctx.shell())?;\n\n    let mkopts = MkOptions {\n        version_control: opts.version_control,\n        path,\n        name,\n        source_files: vec![plan_new_source_file(opts.kind.is_bin())],\n        edition: opts.edition.as_deref(),\n        registry: opts.registry.as_deref(),\n    };\n\n    mk(gctx, &mkopts).with_context(|| {\n        format!(\n            \"failed to create package `{}` at `{}`\",\n            name,\n            path.display()\n        )\n    })?;\n    Ok(())\n}\n\npub fn init(opts: &NewOptions, gctx: &GlobalContext) -> CargoResult<NewProjectKind> {\n    // This is here just as a random location to exercise the internal error handling.\n    if gctx.get_env_os(\"__CARGO_TEST_INTERNAL_ERROR\").is_some() {\n        return Err(crate::util::internal(\"internal error test\"));\n    }\n\n    let path = &opts.path;\n\n    if let Some(home) = home_dir() {\n        if path == &home {\n            anyhow::bail!(\n                \"cannot create package in the home directory\\n\\n\\\n                 help: use `cargo init <path>` to create a package in a different directory\"\n            )\n        }\n    }\n    let name = get_name(path, opts)?;\n    let mut src_paths_types = vec![];\n    detect_source_paths_and_types(path, name, &mut src_paths_types)?;\n    let kind = calculate_new_project_kind(opts.kind, opts.auto_detect_kind, &src_paths_types);\n    gctx.shell()\n        .status(\"Creating\", format!(\"{} package\", opts.kind))?;\n\n    if path.join(\"Cargo.toml\").exists() {\n        anyhow::bail!(\n            \"`cargo init` cannot be run on existing Cargo packages\\n\\\n             help: use `cargo new` to create a package in a new subdirectory\"\n        )\n    }\n    check_path(path, &mut gctx.shell())?;\n\n    let has_bin = kind.is_bin();\n\n    if src_paths_types.is_empty() {\n        src_paths_types.push(plan_new_source_file(has_bin));\n    } else if src_paths_types.len() == 1 && !src_paths_types.iter().any(|x| x.bin == has_bin) {\n        // we've found the only file and it's not the type user wants. Change the type and warn\n        let file_type = if src_paths_types[0].bin {\n            NewProjectKind::Bin\n        } else {\n            NewProjectKind::Lib\n        };\n        gctx.shell().warn(format!(\n            \"file `{}` seems to be a {} file\",\n            src_paths_types[0].relative_path, file_type\n        ))?;\n        src_paths_types[0].bin = has_bin\n    } else if src_paths_types.len() > 1 && !has_bin {\n        // We have found both lib and bin files and the user would like us to treat both as libs\n        anyhow::bail!(\n            \"cannot have a package with \\\n             multiple libraries, \\\n             found both `{}` and `{}`\",\n            src_paths_types[0].relative_path,\n            src_paths_types[1].relative_path\n        )\n    }\n\n    check_name(name, opts.name.is_none(), has_bin, &mut gctx.shell())?;\n\n    let mut version_control = opts.version_control;\n\n    if version_control == None {\n        let mut num_detected_vcses = 0;\n\n        if path.join(\".git\").exists() {\n            version_control = Some(VersionControl::Git);\n            num_detected_vcses += 1;\n        }\n\n        if path.join(\".hg\").exists() {\n            version_control = Some(VersionControl::Hg);\n            num_detected_vcses += 1;\n        }\n\n        if path.join(\".pijul\").exists() {\n            version_control = Some(VersionControl::Pijul);\n            num_detected_vcses += 1;\n        }\n\n        if path.join(\".fossil\").exists() {\n            version_control = Some(VersionControl::Fossil);\n            num_detected_vcses += 1;\n        }\n\n        // if none exists, maybe create git, like in `cargo new`\n\n        if num_detected_vcses > 1 {\n            anyhow::bail!(\n                \"more than one of .hg, .git, .pijul, .fossil configurations \\\n                 found and the ignore file can't be filled in as \\\n                 a result. specify --vcs to override detection\"\n            );\n        }\n    }\n\n    let mkopts = MkOptions {\n        version_control,\n        path,\n        name,\n        source_files: src_paths_types,\n        edition: opts.edition.as_deref(),\n        registry: opts.registry.as_deref(),\n    };\n\n    mk(gctx, &mkopts).with_context(|| {\n        format!(\n            \"failed to create package `{}` at `{}`\",\n            name,\n            path.display()\n        )\n    })?;\n    Ok(kind)\n}\n\n/// `IgnoreList`\nstruct IgnoreList {\n    /// git like formatted entries\n    ignore: Vec<String>,\n    /// mercurial formatted entries\n    hg_ignore: Vec<String>,\n    /// Fossil-formatted entries.\n    fossil_ignore: Vec<String>,\n}\n\nimpl IgnoreList {\n    /// constructor to build a new ignore file\n    fn new() -> IgnoreList {\n        IgnoreList {\n            ignore: Vec::new(),\n            hg_ignore: Vec::new(),\n            fossil_ignore: Vec::new(),\n        }\n    }\n\n    /// Add a new entry to the ignore list. Requires three arguments with the\n    /// entry in possibly three different formats. One for \"git style\" entries,\n    /// one for \"mercurial style\" entries and one for \"fossil style\" entries.\n    fn push(&mut self, ignore: &str, hg_ignore: &str, fossil_ignore: &str) {\n        self.ignore.push(ignore.to_string());\n        self.hg_ignore.push(hg_ignore.to_string());\n        self.fossil_ignore.push(fossil_ignore.to_string());\n    }\n\n    /// Return the correctly formatted content of the ignore file for the given\n    /// version control system as `String`.\n    fn format_new(&self, vcs: VersionControl) -> String {\n        let ignore_items = match vcs {\n            VersionControl::Hg => &self.hg_ignore,\n            VersionControl::Fossil => &self.fossil_ignore,\n            _ => &self.ignore,\n        };\n\n        ignore_items.join(\"\\n\") + \"\\n\"\n    }\n\n    /// `format_existing` is used to format the `IgnoreList` when the ignore file\n    /// already exists. It reads the contents of the given `BufRead` and\n    /// checks if the contents of the ignore list are already existing in the\n    /// file.\n    fn format_existing<T: BufRead>(&self, existing: T, vcs: VersionControl) -> CargoResult<String> {\n        let mut existing_items = Vec::new();\n        for (i, item) in existing.lines().enumerate() {\n            match item {\n                Ok(s) => existing_items.push(s),\n                Err(err) => match err.kind() {\n                    ErrorKind::InvalidData => {\n                        return Err(anyhow!(\n                            \"Character at line {} is invalid. Cargo only supports UTF-8.\",\n                            i\n                        ));\n                    }\n                    _ => return Err(anyhow!(err)),\n                },\n            }\n        }\n\n        let ignore_items = match vcs {\n            VersionControl::Hg => &self.hg_ignore,\n            VersionControl::Fossil => &self.fossil_ignore,\n            _ => &self.ignore,\n        };\n\n        let mut out = String::new();\n\n        // Fossil does not support `#` comments.\n        if vcs != VersionControl::Fossil {\n            out.push_str(\"\\n\\n# Added by cargo\\n\");\n            if ignore_items\n                .iter()\n                .any(|item| existing_items.contains(item))\n            {\n                out.push_str(\"#\\n# already existing elements were commented out\\n\");\n            }\n            out.push('\\n');\n        }\n\n        for item in ignore_items {\n            if existing_items.contains(item) {\n                if vcs == VersionControl::Fossil {\n                    // Just merge for Fossil.\n                    continue;\n                }\n                out.push('#');\n            }\n            out.push_str(item);\n            out.push('\\n');\n        }\n\n        Ok(out)\n    }\n}\n\n/// Writes the ignore file to the given directory. If the ignore file for the\n/// given vcs system already exists, its content is read and duplicate ignore\n/// file entries are filtered out.\nfn write_ignore_file(base_path: &Path, list: &IgnoreList, vcs: VersionControl) -> CargoResult<()> {\n    // Fossil only supports project-level settings in a dedicated subdirectory.\n    if vcs == VersionControl::Fossil {\n        paths::create_dir_all(base_path.join(\".fossil-settings\"))?;\n    }\n\n    for fp_ignore in match vcs {\n        VersionControl::Git => vec![base_path.join(\".gitignore\")],\n        VersionControl::Hg => vec![base_path.join(\".hgignore\")],\n        VersionControl::Pijul => vec![base_path.join(\".ignore\")],\n        // Fossil has a cleaning functionality configured in a separate file.\n        VersionControl::Fossil => vec![\n            base_path.join(\".fossil-settings/ignore-glob\"),\n            base_path.join(\".fossil-settings/clean-glob\"),\n        ],\n        VersionControl::NoVcs => return Ok(()),\n    } {\n        let ignore: String = match paths::open(&fp_ignore) {\n            Err(err) => match err.downcast_ref::<std::io::Error>() {\n                Some(io_err) if io_err.kind() == ErrorKind::NotFound => list.format_new(vcs),\n                _ => return Err(err),\n            },\n            Ok(file) => list.format_existing(BufReader::new(file), vcs)?,\n        };\n\n        paths::append(&fp_ignore, ignore.as_bytes())?;\n    }\n\n    Ok(())\n}\n\n/// Initializes the correct VCS system based on the provided config.\nfn init_vcs(path: &Path, vcs: VersionControl, gctx: &GlobalContext) -> CargoResult<()> {\n    match vcs {\n        VersionControl::Git => {\n            if !path.join(\".git\").exists() {\n                // Temporary fix to work around bug in libgit2 when creating a\n                // directory in the root of a posix filesystem.\n                // See: https://github.com/libgit2/libgit2/issues/5130\n                paths::create_dir_all(path)?;\n                GitRepo::init(path, gctx.cwd())?;\n            }\n        }\n        VersionControl::Hg => {\n            if !path.join(\".hg\").exists() {\n                HgRepo::init(path, gctx.cwd())?;\n            }\n        }\n        VersionControl::Pijul => {\n            if !path.join(\".pijul\").exists() {\n                PijulRepo::init(path, gctx.cwd())?;\n            }\n        }\n        VersionControl::Fossil => {\n            if !path.join(\".fossil\").exists() {\n                FossilRepo::init(path, gctx.cwd())?;\n            }\n        }\n        VersionControl::NoVcs => {\n            paths::create_dir_all(path)?;\n        }\n    };\n\n    Ok(())\n}\n\nfn mk(gctx: &GlobalContext, opts: &MkOptions<'_>) -> CargoResult<()> {\n    let path = opts.path;\n    let name = opts.name;\n    let cfg = gctx.get::<CargoNewConfig>(\"cargo-new\")?;\n\n    // Using the push method with multiple arguments ensures that the entries\n    // for all mutually-incompatible VCS in terms of syntax are in sync.\n    let mut ignore = IgnoreList::new();\n    ignore.push(\"/target\", \"^target$\", \"target\");\n\n    let vcs = opts.version_control.unwrap_or_else(|| {\n        let in_existing_vcs = existing_vcs_repo(path.parent().unwrap_or(path), gctx.cwd());\n        match (cfg.version_control, in_existing_vcs) {\n            (None, false) => VersionControl::Git,\n            (Some(opt), false) => opt,\n            (_, true) => VersionControl::NoVcs,\n        }\n    });\n\n    init_vcs(path, vcs, gctx)?;\n    write_ignore_file(path, &ignore, vcs)?;\n\n    // Create `Cargo.toml` file with necessary `[lib]` and `[[bin]]` sections, if needed.\n    let mut manifest = toml_edit::DocumentMut::new();\n    manifest[\"package\"] = toml_edit::Item::Table(toml_edit::Table::new());\n    manifest[\"package\"][\"name\"] = toml_edit::value(name);\n    manifest[\"package\"][\"version\"] = toml_edit::value(\"0.1.0\");\n    let edition = match opts.edition {\n        Some(edition) => edition.to_string(),\n        None => Edition::LATEST_STABLE.to_string(),\n    };\n    manifest[\"package\"][\"edition\"] = toml_edit::value(edition);\n    if let Some(registry) = opts.registry {\n        let mut array = toml_edit::Array::default();\n        array.push(registry);\n        manifest[\"package\"][\"publish\"] = toml_edit::value(array);\n    }\n    let dep_table = toml_edit::Table::default();\n    manifest[\"dependencies\"] = toml_edit::Item::Table(dep_table);\n\n    // Calculate what `[lib]` and `[[bin]]`s we need to append to `Cargo.toml`.\n    for i in &opts.source_files {\n        if i.bin {\n            if i.relative_path != \"src/main.rs\" {\n                let mut bin = toml_edit::Table::new();\n                bin[\"name\"] = toml_edit::value(name);\n                bin[\"path\"] = toml_edit::value(i.relative_path.clone());\n                manifest[\"bin\"]\n                    .or_insert(toml_edit::Item::ArrayOfTables(\n                        toml_edit::ArrayOfTables::new(),\n                    ))\n                    .as_array_of_tables_mut()\n                    .expect(\"bin is an array of tables\")\n                    .push(bin);\n            }\n        } else if i.relative_path != \"src/lib.rs\" {\n            let mut lib = toml_edit::Table::new();\n            lib[\"path\"] = toml_edit::value(i.relative_path.clone());\n            manifest[\"lib\"] = toml_edit::Item::Table(lib);\n        }\n    }\n\n    let manifest_path = paths::normalize_path(&path.join(\"Cargo.toml\"));\n    if let Ok(root_manifest_path) = find_root_manifest_for_wd(&manifest_path) {\n        let root_manifest = paths::read(&root_manifest_path)?;\n        // Sometimes the root manifest is not a valid manifest, so we only try to parse it if it is.\n        // This should not block the creation of the new project. It is only a best effort to\n        // inherit the workspace package keys.\n        if let Ok(mut workspace_document) = root_manifest.parse::<toml_edit::DocumentMut>() {\n            let display_path = get_display_path(&root_manifest_path, &path)?;\n            let can_be_a_member = can_be_workspace_member(&display_path, &workspace_document)?;\n            // Only try to inherit the workspace stuff if the new package can be a member of the workspace.\n            if can_be_a_member {\n                if let Some(workspace_package_keys) = workspace_document\n                    .get(\"workspace\")\n                    .and_then(|workspace| workspace.get(\"package\"))\n                    .and_then(|package| package.as_table())\n                {\n                    update_manifest_with_inherited_workspace_package_keys(\n                        opts,\n                        &mut manifest,\n                        workspace_package_keys,\n                    )\n                }\n                // Try to inherit the workspace lints key if it exists.\n                if workspace_document\n                    .get(\"workspace\")\n                    .and_then(|workspace| workspace.get(\"lints\"))\n                    .is_some()\n                {\n                    let mut table = toml_edit::Table::new();\n                    table[\"workspace\"] = toml_edit::value(true);\n                    manifest[\"lints\"] = toml_edit::Item::Table(table);\n                }\n\n                // Try to add the new package to the workspace members.\n                if update_manifest_with_new_member(\n                    &root_manifest_path,\n                    &mut workspace_document,\n                    &display_path,\n                )? {\n                    gctx.shell().status(\n                        \"Adding\",\n                        format!(\n                            \"`{}` as member of workspace at `{}`\",\n                            PathBuf::from(&display_path)\n                                .file_name()\n                                .unwrap()\n                                .to_str()\n                                .unwrap(),\n                            root_manifest_path.parent().unwrap().display()\n                        ),\n                    )?\n                }\n            }\n        }\n    }\n\n    paths::write(&manifest_path, manifest.to_string())?;\n\n    // Create all specified source files (with respective parent directories) if they don't exist.\n    for i in &opts.source_files {\n        let path_of_source_file = path.join(i.relative_path.clone());\n\n        if let Some(src_dir) = path_of_source_file.parent() {\n            paths::create_dir_all(src_dir)?;\n        }\n\n        let default_file_content: &[u8] = if i.bin {\n            b\"\\\nfn main() {\n    println!(\\\"Hello, world!\\\");\n}\n\"\n        } else {\n            b\"\\\npub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n\"\n        };\n\n        if !path_of_source_file.is_file() {\n            paths::write(&path_of_source_file, default_file_content)?;\n\n            // Format the newly created source file\n            if let Err(e) = cargo_util::ProcessBuilder::new(\"rustfmt\")\n                .arg(&path_of_source_file)\n                .exec_with_output()\n            {\n                tracing::warn!(\"failed to call rustfmt: {:#}\", e);\n            }\n        }\n    }\n\n    if let Err(e) = Workspace::new(&manifest_path, gctx) {\n        crate::display_warning_with_error(\n            \"compiling this new package may not work due to invalid \\\n             workspace configuration\",\n            &e,\n            &mut gctx.shell(),\n        );\n    }\n\n    gctx.shell().note(\n        \"see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\",\n    )?;\n\n    Ok(())\n}\n\n// Update the manifest with the inherited workspace package keys.\n// If the option is not set, the key is removed from the manifest.\n// If the option is set, keep the value from the manifest.\nfn update_manifest_with_inherited_workspace_package_keys(\n    opts: &MkOptions<'_>,\n    manifest: &mut toml_edit::DocumentMut,\n    workspace_package_keys: &toml_edit::Table,\n) {\n    if workspace_package_keys.is_empty() {\n        return;\n    }\n\n    let try_remove_and_inherit_package_key = |key: &str, manifest: &mut toml_edit::DocumentMut| {\n        let package = manifest[\"package\"]\n            .as_table_mut()\n            .expect(\"package is a table\");\n        package.remove(key);\n        let mut table = toml_edit::Table::new();\n        table.set_dotted(true);\n        table[\"workspace\"] = toml_edit::value(true);\n        package.insert(key, toml_edit::Item::Table(table));\n    };\n\n    // Inherit keys from the workspace.\n    // Only keep the value from the manifest if the option is set.\n    for (key, _) in workspace_package_keys {\n        if key == \"edition\" && opts.edition.is_some() {\n            continue;\n        }\n        if key == \"publish\" && opts.registry.is_some() {\n            continue;\n        }\n\n        try_remove_and_inherit_package_key(key, manifest);\n    }\n}\n\n/// Adds the new package member to the [workspace.members] array.\n/// - It first checks if the name matches any element in [workspace.exclude],\n///  and it ignores the name if there is a match.\n/// - Then it check if the name matches any element already in [workspace.members],\n/// and it ignores the name if there is a match.\n/// - If [workspace.members] doesn't exist in the manifest, it will add a new section\n/// with the new package in it.\nfn update_manifest_with_new_member(\n    root_manifest_path: &Path,\n    workspace_document: &mut toml_edit::DocumentMut,\n    display_path: &str,\n) -> CargoResult<bool> {\n    let Some(workspace) = workspace_document.get_mut(\"workspace\") else {\n        return Ok(false);\n    };\n\n    // If the members element already exist, check if one of the patterns\n    // in the array already includes the new package's relative path.\n    // - Add the relative path if the members don't match the new package's path.\n    // - Create a new members array if there are no members element in the workspace yet.\n    if let Some(members) = workspace\n        .get_mut(\"members\")\n        .and_then(|members| members.as_array_mut())\n    {\n        for member in members.iter() {\n            let pat = member\n                .as_str()\n                .with_context(|| format!(\"invalid non-string member `{}`\", member))?;\n            let pattern = glob::Pattern::new(pat)\n                .with_context(|| format!(\"cannot build glob pattern from `{}`\", pat))?;\n\n            if pattern.matches(&display_path) {\n                return Ok(false);\n            }\n        }\n\n        let was_sorted = members.iter().map(Value::as_str).is_sorted();\n        members.push(display_path);\n        if was_sorted {\n            members.sort_by(|lhs, rhs| lhs.as_str().cmp(&rhs.as_str()));\n        }\n    } else {\n        let mut array = Array::new();\n        array.push(display_path);\n\n        workspace[\"members\"] = toml_edit::value(array);\n    }\n\n    write_atomic(\n        &root_manifest_path,\n        workspace_document.to_string().to_string().as_bytes(),\n    )?;\n    Ok(true)\n}\n\nfn get_display_path(root_manifest_path: &Path, package_path: &Path) -> CargoResult<String> {\n    // Find the relative path for the package from the workspace root directory.\n    let workspace_root = root_manifest_path.parent().with_context(|| {\n        format!(\n            \"workspace root manifest doesn't have a parent directory `{}`\",\n            root_manifest_path.display()\n        )\n    })?;\n    let relpath = pathdiff::diff_paths(package_path, workspace_root).with_context(|| {\n        format!(\n            \"path comparison requires two absolute paths; package_path: `{}`, workspace_path: `{}`\",\n            package_path.display(),\n            workspace_root.display()\n        )\n    })?;\n\n    let mut components = Vec::new();\n    for comp in relpath.iter() {\n        let comp = comp.to_str().with_context(|| {\n            format!(\"invalid unicode component in path `{}`\", relpath.display())\n        })?;\n        components.push(comp);\n    }\n    let display_path = components.join(\"/\");\n    Ok(display_path)\n}\n\n// Check if the package can be a member of the workspace.\nfn can_be_workspace_member(\n    display_path: &str,\n    workspace_document: &toml_edit::DocumentMut,\n) -> CargoResult<bool> {\n    if let Some(exclude) = workspace_document\n        .get(\"workspace\")\n        .and_then(|workspace| workspace.get(\"exclude\"))\n        .and_then(|exclude| exclude.as_array())\n    {\n        for member in exclude {\n            let pat = member\n                .as_str()\n                .with_context(|| format!(\"invalid non-string exclude path `{}`\", member))?;\n            if pat == display_path {\n                return Ok(false);\n            }\n        }\n    }\n    Ok(true)\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_output_metadata.rs",
    "content": "use crate::core::compiler::artifact::match_artifacts_kind_with_targets;\nuse crate::core::compiler::{CompileKind, CompileKindFallback, RustcTargetData};\nuse crate::core::dependency::DepKind;\nuse crate::core::package::SerializedPackage;\nuse crate::core::resolver::{HasDevUnits, Resolve, features::CliFeatures};\nuse crate::core::{Package, PackageId, PackageIdSpec, Workspace};\nuse crate::ops::{self, Packages};\nuse crate::util::CargoResult;\nuse crate::util::interning::InternedString;\nuse cargo_platform::Platform;\nuse serde::Serialize;\nuse std::collections::BTreeMap;\nuse std::path::PathBuf;\n\nconst VERSION: u32 = 1;\n\npub struct OutputMetadataOptions {\n    pub cli_features: CliFeatures,\n    pub no_deps: bool,\n    pub version: u32,\n    pub filter_platforms: Vec<String>,\n}\n\n/// Loads the manifest, resolves the dependencies of the package to the concrete\n/// used versions - considering overrides - and writes all dependencies in a JSON\n/// format to stdout.\npub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> CargoResult<ExportInfo> {\n    if opt.version != VERSION {\n        anyhow::bail!(\n            \"metadata version {} not supported, only {} is currently supported\",\n            opt.version,\n            VERSION\n        );\n    }\n    let (packages, resolve) = if opt.no_deps {\n        let packages = ws\n            .members()\n            .map(|pkg| pkg.serialized(ws.gctx().cli_unstable(), ws.unstable_features()))\n            .collect();\n        (packages, None)\n    } else {\n        let (packages, resolve) = build_resolve_graph(ws, opt)?;\n        (packages, Some(resolve))\n    };\n\n    Ok(ExportInfo {\n        packages,\n        workspace_members: ws.members().map(|pkg| pkg.package_id().to_spec()).collect(),\n        workspace_default_members: ws\n            .default_members()\n            .map(|pkg| pkg.package_id().to_spec())\n            .collect(),\n        resolve,\n        target_directory: ws.target_dir().into_path_unlocked(),\n        build_directory: ws.build_dir().into_path_unlocked(),\n        version: VERSION,\n        workspace_root: ws.root().to_path_buf(),\n        metadata: ws.custom_metadata().cloned(),\n    })\n}\n\n/// This is the structure that is serialized and displayed to the user.\n///\n/// See cargo-metadata.adoc for detailed documentation of the format.\n#[derive(Serialize)]\npub struct ExportInfo {\n    packages: Vec<SerializedPackage>,\n    workspace_members: Vec<PackageIdSpec>,\n    workspace_default_members: Vec<PackageIdSpec>,\n    resolve: Option<MetadataResolve>,\n    target_directory: PathBuf,\n    build_directory: PathBuf,\n    version: u32,\n    workspace_root: PathBuf,\n    metadata: Option<toml::Value>,\n}\n\n#[derive(Serialize)]\nstruct MetadataResolve {\n    nodes: Vec<MetadataResolveNode>,\n    root: Option<PackageIdSpec>,\n}\n\n#[derive(Serialize)]\nstruct MetadataResolveNode {\n    id: PackageIdSpec,\n    dependencies: Vec<PackageIdSpec>,\n    deps: Vec<Dep>,\n    features: Vec<InternedString>,\n}\n\n#[derive(Serialize)]\nstruct Dep {\n    // TODO(bindeps): after -Zbindeps gets stabilized,\n    // mark this field as deprecated in the help manual of cargo-metadata\n    name: InternedString,\n    pkg: PackageIdSpec,\n    #[serde(skip)]\n    pkg_id: PackageId,\n    dep_kinds: Vec<DepKindInfo>,\n}\n\n#[derive(Serialize, PartialEq, Eq, PartialOrd, Ord)]\nstruct DepKindInfo {\n    kind: DepKind,\n    target: Option<Platform>,\n\n    // vvvvv The fields below are introduced for `-Z bindeps`.\n    /// What the manifest calls the crate.\n    ///\n    /// A renamed dependency will show the rename instead of original name.\n    // TODO(bindeps): Remove `Option` after -Zbindeps get stabilized.\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    extern_name: Option<InternedString>,\n    /// Artifact's crate type, e.g. staticlib, cdylib, bin...\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    artifact: Option<&'static str>,\n    /// Equivalent to `{ target = \"…\" }` in an artifact dependency requirement.\n    ///\n    /// * If the target points to a custom target JSON file, the path will be absolute.\n    /// * If the target is a build assumed target `{ target = \"target\" }`, it will show as `<target>`.\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    compile_target: Option<InternedString>,\n    /// Executable name for an artifact binary dependency.\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    bin_name: Option<String>,\n    // ^^^^^ The fields above are introduced for `-Z bindeps`.\n}\n\n/// Builds the resolve graph as it will be displayed to the user.\nfn build_resolve_graph(\n    ws: &Workspace<'_>,\n    metadata_opts: &OutputMetadataOptions,\n) -> CargoResult<(Vec<SerializedPackage>, MetadataResolve)> {\n    // TODO: Without --filter-platform, features are being resolved for `host` only.\n    // How should this work?\n    //\n    // Otherwise note that \"just host\" is used as the fallback here if\n    // `filter_platforms` is empty to intentionally avoid reading\n    // `$CARGO_BUILD_TARGET` (or `build.target`) which makes sense for other\n    // subcommands like `cargo build` but does not fit with this command.\n    let requested_kinds = CompileKind::from_requested_targets_with_fallback(\n        ws.gctx(),\n        &metadata_opts.filter_platforms,\n        CompileKindFallback::JustHost,\n    )?;\n    let mut target_data = RustcTargetData::new(ws, &requested_kinds)?;\n    // Resolve entire workspace.\n    let specs = Packages::All(Vec::new()).to_package_id_specs(ws)?;\n    let force_all = if metadata_opts.filter_platforms.is_empty() {\n        crate::core::resolver::features::ForceAllTargets::Yes\n    } else {\n        crate::core::resolver::features::ForceAllTargets::No\n    };\n\n    // Note that even with --filter-platform we end up downloading host dependencies as well,\n    // as that is the behavior of download_accessible.\n    let dry_run = false;\n    let ws_resolve = ops::resolve_ws_with_opts(\n        ws,\n        &mut target_data,\n        &requested_kinds,\n        &metadata_opts.cli_features,\n        &specs,\n        HasDevUnits::Yes,\n        force_all,\n        dry_run,\n    )?;\n\n    let package_map: BTreeMap<PackageId, Package> = ws_resolve\n        .pkg_set\n        .packages()\n        // This is a little lazy, but serde doesn't handle Rc fields very well.\n        .map(|pkg| (pkg.package_id(), Package::clone(pkg)))\n        .collect();\n\n    // Start from the workspace roots, and recurse through filling out the\n    // map, filtering targets as necessary.\n    let mut node_map = BTreeMap::new();\n    for member_pkg in ws.members() {\n        build_resolve_graph_r(\n            &mut node_map,\n            member_pkg.package_id(),\n            &ws_resolve.targeted_resolve,\n            &package_map,\n            &target_data,\n            &requested_kinds,\n        )?;\n    }\n    // Get a Vec of Packages.\n    let actual_packages = package_map\n        .into_iter()\n        .filter_map(|(pkg_id, pkg)| node_map.get(&pkg_id).map(|_| pkg))\n        .map(|pkg| pkg.serialized(ws.gctx().cli_unstable(), ws.unstable_features()))\n        .collect();\n\n    let mr = MetadataResolve {\n        nodes: node_map.into_iter().map(|(_pkg_id, node)| node).collect(),\n        root: ws.current_opt().map(|pkg| pkg.package_id().to_spec()),\n    };\n    Ok((actual_packages, mr))\n}\n\nfn build_resolve_graph_r(\n    node_map: &mut BTreeMap<PackageId, MetadataResolveNode>,\n    pkg_id: PackageId,\n    resolve: &Resolve,\n    package_map: &BTreeMap<PackageId, Package>,\n    target_data: &RustcTargetData<'_>,\n    requested_kinds: &[CompileKind],\n) -> CargoResult<()> {\n    if node_map.contains_key(&pkg_id) {\n        return Ok(());\n    }\n    // This normalizes the IDs so that they are consistent between the\n    // `packages` array and the `resolve` map. This is a bit of a hack to\n    // compensate for the fact that\n    // SourceKind::Git(GitReference::Branch(\"master\")) is the same as\n    // SourceKind::Git(GitReference::DefaultBranch). We want IDs in the JSON\n    // to be opaque, and compare with basic string equality, so this will\n    // always prefer the style of ID in the Package instead of the resolver.\n    // Cargo generally only exposes PackageIds from the Package struct, and\n    // AFAIK this is the only place where the resolver variant is exposed.\n    //\n    // This diverges because the SourceIds created for Packages are built\n    // based on the Dependency declaration, but the SourceIds in the resolver\n    // are deserialized from Cargo.lock. Cargo.lock may have been generated by\n    // an older (or newer!) version of Cargo which uses a different style.\n    let normalize_id = |id| -> PackageId { *package_map.get_key_value(&id).unwrap().0 };\n    let features = resolve.features(pkg_id).to_vec();\n\n    let deps = {\n        let mut dep_metadatas = Vec::new();\n        let iter = resolve.deps(pkg_id).filter(|(_dep_id, deps)| {\n            if requested_kinds == [CompileKind::Host] {\n                true\n            } else {\n                requested_kinds.iter().any(|kind| {\n                    deps.iter()\n                        .any(|dep| target_data.dep_platform_activated(dep, *kind))\n                })\n            }\n        });\n        for (dep_id, deps) in iter {\n            let mut dep_kinds = Vec::new();\n\n            let targets = package_map[&dep_id].targets();\n\n            // Try to get the extern name for lib, or crate name for bins.\n            let extern_name = |target| {\n                resolve\n                    .extern_crate_name_and_dep_name(pkg_id, dep_id, target)\n                    .map(|(ext_crate_name, _)| ext_crate_name)\n            };\n\n            let lib_target = targets.iter().find(|t| t.is_lib());\n\n            for dep in deps.iter() {\n                if let Some(target) = lib_target {\n                    // When we do have a library target, include them in deps if...\n                    let included = match dep.artifact() {\n                        // it is not an artifact dep at all\n                        None => true,\n                        // it is also an artifact dep with `{ …, lib = true }`\n                        Some(a) if a.is_lib() => true,\n                        _ => false,\n                    };\n                    // TODO(bindeps): Cargo shouldn't have `extern_name` field\n                    // if the user is not using -Zbindeps.\n                    // Remove this condition ` after -Zbindeps gets stabilized.\n                    let extern_name = if dep.artifact().is_some() {\n                        Some(extern_name(target)?)\n                    } else {\n                        None\n                    };\n                    if included {\n                        dep_kinds.push(DepKindInfo {\n                            kind: dep.kind(),\n                            target: dep.platform().cloned(),\n                            extern_name,\n                            artifact: None,\n                            compile_target: None,\n                            bin_name: None,\n                        });\n                    }\n                }\n\n                // No need to proceed if there is no artifact dependency.\n                let Some(artifact_requirements) = dep.artifact() else {\n                    continue;\n                };\n\n                let compile_target = match artifact_requirements.target() {\n                    Some(t) => t\n                        .to_compile_target()\n                        .map(|t| t.rustc_target())\n                        // Given that Cargo doesn't know which target it should resolve to,\n                        // when an artifact dep is specified with { target = \"target\" },\n                        // keep it with a special \"<target>\" string,\n                        .or_else(|| Some(\"<target>\".into())),\n                    None => None,\n                };\n\n                let target_set =\n                    match_artifacts_kind_with_targets(dep, targets, pkg_id.name().as_str())?;\n                dep_kinds.reserve(target_set.len());\n                for (kind, target) in target_set.into_iter() {\n                    dep_kinds.push(DepKindInfo {\n                        kind: dep.kind(),\n                        target: dep.platform().cloned(),\n                        extern_name: extern_name(target).ok(),\n                        artifact: Some(kind.crate_type()),\n                        compile_target,\n                        bin_name: target.is_bin().then(|| target.name().to_string()),\n                    })\n                }\n            }\n\n            dep_kinds.sort();\n\n            let pkg_id = normalize_id(dep_id);\n\n            let dep = match (lib_target, dep_kinds.len()) {\n                (Some(target), _) => Dep {\n                    name: extern_name(target)?,\n                    pkg: pkg_id.to_spec(),\n                    pkg_id,\n                    dep_kinds,\n                },\n                // No lib target exists but contains artifact deps.\n                (None, 1..) => Dep {\n                    name: \"\".into(),\n                    pkg: pkg_id.to_spec(),\n                    pkg_id,\n                    dep_kinds,\n                },\n                // No lib or artifact dep exists.\n                // Usually this mean parent depending on non-lib bin crate.\n                (None, _) => continue,\n            };\n\n            dep_metadatas.push(dep)\n        }\n        dep_metadatas\n    };\n\n    let to_visit: Vec<PackageId> = deps.iter().map(|dep| dep.pkg_id).collect();\n    let node = MetadataResolveNode {\n        id: normalize_id(pkg_id).to_spec(),\n        dependencies: to_visit.iter().map(|id| id.to_spec()).collect(),\n        deps,\n        features,\n    };\n    node_map.insert(pkg_id, node);\n    for dep_id in to_visit {\n        build_resolve_graph_r(\n            node_map,\n            dep_id,\n            resolve,\n            package_map,\n            target_data,\n            requested_kinds,\n        )?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_package/mod.rs",
    "content": "use std::collections::BTreeMap;\nuse std::collections::BTreeSet;\nuse std::collections::HashMap;\nuse std::fs::File;\nuse std::io::SeekFrom;\nuse std::io::prelude::*;\nuse std::path::{Path, PathBuf};\nuse std::task::Poll;\n\nuse crate::core::PackageIdSpecQuery;\nuse crate::core::Shell;\nuse crate::core::Verbosity;\nuse crate::core::Workspace;\nuse crate::core::dependency::DepKind;\nuse crate::core::manifest::Target;\nuse crate::core::resolver::CliFeatures;\nuse crate::core::resolver::HasDevUnits;\nuse crate::core::{Package, PackageId, PackageSet, Resolve, SourceId};\nuse crate::ops::lockfile::LOCKFILE_NAME;\nuse crate::ops::registry::{RegistryOrIndex, infer_registry};\nuse crate::sources::path::PathEntry;\nuse crate::sources::{CRATES_IO_REGISTRY, PathSource};\nuse crate::util::FileLock;\nuse crate::util::Filesystem;\nuse crate::util::GlobalContext;\nuse crate::util::Graph;\nuse crate::util::HumanBytes;\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::context::JobsConfig;\nuse crate::util::errors::CargoResult;\nuse crate::util::errors::ManifestError;\nuse crate::util::restricted_names;\nuse crate::util::toml::prepare_for_publish;\nuse crate::{drop_println, ops};\nuse annotate_snippets::Level;\nuse anyhow::{Context as _, bail};\nuse cargo_util::paths;\nuse cargo_util_schemas::index::{IndexPackage, RegistryDependency};\nuse cargo_util_schemas::messages;\nuse flate2::{Compression, GzBuilder};\nuse tar::{Builder, EntryType, Header, HeaderMode};\nuse tracing::debug;\nuse unicase::Ascii as UncasedAscii;\n\nmod vcs;\nmod verify;\n\n/// Message format for `cargo package`.\n///\n/// Currently only affect the output of the `--list` flag.\n#[derive(Debug, Clone)]\npub enum PackageMessageFormat {\n    Human,\n    Json,\n}\n\nimpl PackageMessageFormat {\n    pub const POSSIBLE_VALUES: [&str; 2] = [\"human\", \"json\"];\n\n    pub const DEFAULT: &str = \"human\";\n}\n\nimpl std::str::FromStr for PackageMessageFormat {\n    type Err = anyhow::Error;\n\n    fn from_str(s: &str) -> Result<PackageMessageFormat, anyhow::Error> {\n        match s {\n            \"human\" => Ok(PackageMessageFormat::Human),\n            \"json\" => Ok(PackageMessageFormat::Json),\n            f => bail!(\"unknown message format `{f}`\"),\n        }\n    }\n}\n\n#[derive(Clone)]\npub struct PackageOpts<'gctx> {\n    pub gctx: &'gctx GlobalContext,\n    pub list: bool,\n    pub fmt: PackageMessageFormat,\n    pub check_metadata: bool,\n    pub allow_dirty: bool,\n    pub include_lockfile: bool,\n    pub verify: bool,\n    pub jobs: Option<JobsConfig>,\n    pub keep_going: bool,\n    pub to_package: ops::Packages,\n    pub targets: Vec<String>,\n    pub cli_features: CliFeatures,\n    pub reg_or_index: Option<ops::RegistryOrIndex>,\n    /// Whether this packaging job is meant for a publishing dry-run.\n    ///\n    /// Packaging on its own has no side effects, so a dry-run doesn't\n    /// make sense from that point of view. But dry-run publishing needs\n    /// special packaging behavior, which this flag turns on.\n    ///\n    /// Specifically, we want dry-run packaging to work even if versions\n    /// have not yet been bumped. But then if you dry-run packaging in\n    /// a workspace with some declared versions that are already published,\n    /// the package verification step can fail with checksum mismatches.\n    /// So when dry-run is true, the verification step does some extra\n    /// checksum fudging in the lock file.\n    pub dry_run: bool,\n}\n\nconst ORIGINAL_MANIFEST_FILE: &str = \"Cargo.toml.orig\";\nconst VCS_INFO_FILE: &str = \".cargo_vcs_info.json\";\n\nstruct ArchiveFile {\n    /// The relative path in the archive (not including the top-level package\n    /// name directory).\n    rel_path: PathBuf,\n    /// String variant of `rel_path`, for convenience.\n    rel_str: String,\n    /// The contents to add to the archive.\n    contents: FileContents,\n}\n\nenum FileContents {\n    /// Absolute path to the file on disk to add to the archive.\n    OnDisk(PathBuf),\n    /// Generates a file.\n    Generated(GeneratedFile),\n}\n\nenum GeneratedFile {\n    /// Generates `Cargo.toml` by rewriting the original.\n    ///\n    /// Associated path is the original manifest path.\n    Manifest(PathBuf),\n    /// Generates `Cargo.lock`.\n    ///\n    /// Associated path is the path to the original lock file, if existing.\n    Lockfile(Option<PathBuf>),\n    /// Adds a `.cargo_vcs_info.json` file if in a git repo.\n    VcsInfo(vcs::VcsInfo),\n}\n\n// Builds a tarball and places it in the output directory.\n#[tracing::instrument(skip_all)]\nfn create_package(\n    ws: &Workspace<'_>,\n    opts: &PackageOpts<'_>,\n    pkg: &Package,\n    ar_files: Vec<ArchiveFile>,\n    local_reg: Option<&TmpRegistry<'_>>,\n) -> CargoResult<FileLock> {\n    let gctx = ws.gctx();\n    let filecount = ar_files.len();\n\n    // Check that the package dependencies are safe to deploy.\n    for dep in pkg.dependencies() {\n        super::check_dep_has_version(dep, false).map_err(|err| {\n            ManifestError::new(\n                err.context(format!(\n                    \"failed to verify manifest at `{}`\",\n                    pkg.manifest_path().display()\n                )),\n                pkg.manifest_path().into(),\n            )\n        })?;\n    }\n\n    let filename = pkg.package_id().tarball_name();\n    let build_dir = ws.build_dir();\n    paths::create_dir_all_excluded_from_backups_atomic(build_dir.as_path_unlocked())?;\n    let dir = build_dir.join(\"package\").join(\"tmp-crate\");\n    let dst = dir.open_rw_exclusive_create(&filename, gctx, \"package scratch space\")?;\n\n    // Package up and test a temporary tarball and only move it to the final\n    // location if it actually passes all our tests. Any previously existing\n    // tarball can be assumed as corrupt or invalid, so we just blow it away if\n    // it exists.\n    gctx.shell()\n        .status(\"Packaging\", pkg.package_id().to_string())?;\n    dst.file().set_len(0)?;\n    let uncompressed_size = tar(ws, opts, pkg, local_reg, ar_files, dst.file(), &filename)\n        .context(\"failed to prepare local package for uploading\")?;\n\n    let dst_metadata = dst\n        .file()\n        .metadata()\n        .with_context(|| format!(\"could not learn metadata for: `{}`\", dst.path().display()))?;\n    let compressed_size = dst_metadata.len();\n\n    let uncompressed = HumanBytes(uncompressed_size);\n    let compressed = HumanBytes(compressed_size);\n\n    let message = format!(\"{filecount} files, {uncompressed:.1} ({compressed:.1} compressed)\");\n    // It doesn't really matter if this fails.\n    drop(gctx.shell().status(\"Packaged\", message));\n\n    return Ok(dst);\n}\n\n/// Packages an entire workspace.\n///\n/// Returns the generated package files. If `opts.list` is true, skips\n/// generating package files and returns an empty list.\npub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<FileLock>> {\n    let specs = &opts.to_package.to_package_id_specs(ws)?;\n    // If -p is used, we should check spec is matched with the members (See #13719)\n    if let ops::Packages::Packages(_) = opts.to_package {\n        for spec in specs.iter() {\n            let member_ids = ws.members().map(|p| p.package_id());\n            spec.query(member_ids)?;\n        }\n    }\n    let mut pkgs = ws.members_with_features(specs, &opts.cli_features)?;\n\n    // In `members_with_features_old`, it will add \"current\" package (determined by the cwd)\n    // So we need filter\n    pkgs.retain(|(pkg, _feats)| specs.iter().any(|spec| spec.matches(pkg.package_id())));\n\n    let packaged = do_package(ws, opts, pkgs)?;\n\n    // Uplifting artifacts\n    let mut result = Vec::new();\n    let target_dir = ws.target_dir();\n    paths::create_dir_all_excluded_from_backups_atomic(target_dir.as_path_unlocked())?;\n    let artifact_dir = target_dir.join(\"package\");\n    for (pkg, _, src) in packaged {\n        let filename = pkg.package_id().tarball_name();\n        let dst = artifact_dir.open_rw_exclusive_create(filename, ws.gctx(), \"uplifted package\")?;\n        dst.file().set_len(0)?;\n        src.file().seek(SeekFrom::Start(0))?;\n        std::io::copy(&mut src.file(), &mut dst.file())?;\n        result.push(dst);\n    }\n\n    Ok(result)\n}\n\n/// Packages an entire workspace.\n///\n/// Returns the generated package files and the dependencies between them. If\n/// `opts.list` is true, skips generating package files and returns an empty\n/// list.\npub(crate) fn package_with_dep_graph(\n    ws: &Workspace<'_>,\n    opts: &PackageOpts<'_>,\n    pkgs: Vec<(&Package, CliFeatures)>,\n) -> CargoResult<LocalDependencies<(CliFeatures, FileLock)>> {\n    let output = do_package(ws, opts, pkgs)?;\n\n    Ok(local_deps(output.into_iter().map(\n        |(pkg, opts, tarball)| (pkg, (opts.cli_features, tarball)),\n    )))\n}\n\nfn do_package<'a>(\n    ws: &Workspace<'_>,\n    opts: &PackageOpts<'a>,\n    pkgs: Vec<(&Package, CliFeatures)>,\n) -> CargoResult<Vec<(Package, PackageOpts<'a>, FileLock)>> {\n    if ws\n        .lock_root()\n        .as_path_unlocked()\n        .join(LOCKFILE_NAME)\n        .exists()\n        && opts.include_lockfile\n    {\n        // Make sure the Cargo.lock is up-to-date and valid.\n        let dry_run = false;\n        let _ = ops::resolve_ws(ws, dry_run)?;\n        // If Cargo.lock does not exist, it will be generated by `build_lock`\n        // below, and will be validated during the verification step.\n    }\n\n    let deps = local_deps(pkgs.iter().map(|(p, f)| ((*p).clone(), f.clone())));\n    let just_pkgs: Vec<_> = pkgs.iter().map(|p| p.0).collect();\n\n    // The publish registry doesn't matter unless there are local dependencies that will be\n    // resolved,\n    // so only try to get one if we need it.\n    //\n    // If they explicitly passed a registry on the CLI, we check it no matter what to verify\n    // `package.publish`.\n    let needs_local_reg = deps.has_dependencies() && (opts.include_lockfile || opts.verify);\n    let verify_registry_allow_list = opts.reg_or_index.is_some();\n    let mut local_reg = if !opts.list && (needs_local_reg || verify_registry_allow_list) {\n        let sid = get_registry(ws.gctx(), &just_pkgs, opts.reg_or_index.clone())?;\n        debug!(\"packaging for registry {}\", sid);\n        let reg_dir = ws.build_dir().join(\"package\").join(\"tmp-registry\");\n        let local_reg = TmpRegistry::new(ws.gctx(), reg_dir, sid)?;\n        Some(local_reg)\n    } else {\n        None\n    };\n\n    // Packages need to be created in dependency order, because dependencies must\n    // be added to our local overlay before we can create lockfiles that depend on them.\n    let sorted_pkgs = deps.sort();\n    let mut outputs: Vec<(Package, PackageOpts<'_>, FileLock)> = Vec::new();\n    for (pkg, cli_features) in sorted_pkgs {\n        let opts = PackageOpts {\n            cli_features: cli_features.clone(),\n            to_package: ops::Packages::Default,\n            ..opts.clone()\n        };\n        let ar_files = prepare_archive(ws, &pkg, &opts)?;\n\n        if opts.list {\n            match opts.fmt {\n                PackageMessageFormat::Human => {\n                    // While this form is called \"human\",\n                    // it keeps the old file-per-line format for compatibility.\n                    for ar_file in &ar_files {\n                        drop_println!(ws.gctx(), \"{}\", ar_file.rel_str);\n                    }\n                }\n                PackageMessageFormat::Json => {\n                    let message = messages::PackageList {\n                        id: pkg.package_id().to_spec(),\n                        files: BTreeMap::from_iter(ar_files.into_iter().map(|f| {\n                            let file = match f.contents {\n                                FileContents::OnDisk(path) => messages::PackageFile::Copy { path },\n                                FileContents::Generated(\n                                    GeneratedFile::Manifest(path)\n                                    | GeneratedFile::Lockfile(Some(path)),\n                                ) => messages::PackageFile::Generate { path: Some(path) },\n                                FileContents::Generated(\n                                    GeneratedFile::VcsInfo(_) | GeneratedFile::Lockfile(None),\n                                ) => messages::PackageFile::Generate { path: None },\n                            };\n                            (f.rel_path, file)\n                        })),\n                    };\n                    let _ = ws.gctx().shell().print_json(&message);\n                }\n            }\n        } else {\n            let tarball = create_package(ws, &opts, &pkg, ar_files, local_reg.as_ref())?;\n            if let Some(local_reg) = local_reg.as_mut() {\n                if pkg.publish() != &Some(Vec::new()) {\n                    local_reg.add_package(ws, &pkg, &tarball)?;\n                }\n            }\n            outputs.push((pkg, opts, tarball));\n        }\n    }\n\n    // Verify all packages in the workspace. This can be done in any order, since the dependencies\n    // are already all in the local registry overlay.\n    if opts.verify {\n        for (pkg, opts, tarball) in &outputs {\n            verify::run_verify(ws, pkg, tarball, local_reg.as_ref(), opts)\n                .context(\"failed to verify package tarball\")?\n        }\n    }\n\n    Ok(outputs)\n}\n\n/// Determine which registry the packages are for.\n///\n/// The registry only affects the built packages if there are dependencies within the\n/// packages that we're packaging: if we're packaging foo-bin and foo-lib, and foo-bin\n/// depends on foo-lib, then the foo-lib entry in foo-bin's lockfile will depend on the\n/// registry that we're building packages for.\nfn get_registry(\n    gctx: &GlobalContext,\n    pkgs: &[&Package],\n    reg_or_index: Option<RegistryOrIndex>,\n) -> CargoResult<SourceId> {\n    let reg_or_index = match reg_or_index.clone() {\n        Some(r) => Some(r),\n        None => infer_registry(pkgs)?,\n    };\n\n    // Validate the registry against the packages' allow-lists.\n    let reg = reg_or_index\n        .clone()\n        .unwrap_or_else(|| RegistryOrIndex::Registry(CRATES_IO_REGISTRY.to_owned()));\n    if let RegistryOrIndex::Registry(reg_name) = reg {\n        for pkg in pkgs {\n            if let Some(allowed) = pkg.publish().as_ref() {\n                // If allowed is empty (i.e. package.publish is false), we let it slide.\n                // This allows packaging unpublishable packages (although packaging might\n                // fail later if the unpublishable package is a dependency of something else).\n                if !allowed.is_empty() && !allowed.iter().any(|a| a == &reg_name) {\n                    bail!(\n                        \"`{}` cannot be packaged.\\n\\\n                         The registry `{}` is not listed in the `package.publish` value in Cargo.toml.\",\n                        pkg.name(),\n                        reg_name\n                    );\n                }\n            }\n        }\n    }\n    Ok(ops::registry::get_source_id(gctx, reg_or_index.as_ref())?.replacement)\n}\n\n/// Just the part of the dependency graph that's between the packages we're packaging.\n#[derive(Clone, Debug, Default)]\npub(crate) struct LocalDependencies<T> {\n    pub packages: HashMap<PackageId, (Package, T)>,\n    pub graph: Graph<PackageId, ()>,\n}\n\nimpl<T: Clone> LocalDependencies<T> {\n    pub fn sort(&self) -> Vec<(Package, T)> {\n        self.graph\n            .sort()\n            .into_iter()\n            .map(|name| self.packages[&name].clone())\n            .collect()\n    }\n\n    pub fn has_dependencies(&self) -> bool {\n        self.graph\n            .iter()\n            .any(|node| self.graph.edges(node).next().is_some())\n    }\n}\n\n/// Build just the part of the dependency graph that's between the given packages,\n/// ignoring dev dependencies.\n///\n/// We assume that the packages all belong to this workspace.\nfn local_deps<T>(packages: impl Iterator<Item = (Package, T)>) -> LocalDependencies<T> {\n    let packages: HashMap<PackageId, (Package, T)> = packages\n        .map(|(pkg, payload)| (pkg.package_id(), (pkg, payload)))\n        .collect();\n\n    // Dependencies have source ids but not package ids. We draw an edge\n    // whenever a dependency's source id matches one of our packages. This is\n    // wrong in general because it doesn't require (e.g.) versions to match. But\n    // since we're working only with path dependencies here, it should be fine.\n    let source_to_pkg: HashMap<_, _> = packages\n        .keys()\n        .map(|pkg_id| (pkg_id.source_id(), *pkg_id))\n        .collect();\n\n    let mut graph = Graph::new();\n    for (pkg, _payload) in packages.values() {\n        graph.add(pkg.package_id());\n        for dep in pkg.dependencies() {\n            // We're only interested in local (i.e. living in this workspace) dependencies.\n            if !dep.source_id().is_path() {\n                continue;\n            }\n\n            // If local dev-dependencies don't have a version specified, they get stripped\n            // on publish so we should ignore them.\n            if dep.kind() == DepKind::Development && !dep.specified_req() {\n                continue;\n            };\n\n            // We don't care about cycles\n            if dep.source_id() == pkg.package_id().source_id() {\n                continue;\n            }\n\n            if let Some(dep_pkg) = source_to_pkg.get(&dep.source_id()) {\n                graph.link(pkg.package_id(), *dep_pkg);\n            }\n        }\n    }\n\n    LocalDependencies { packages, graph }\n}\n\n/// Performs pre-archiving checks and builds a list of files to archive.\n#[tracing::instrument(skip_all)]\nfn prepare_archive(\n    ws: &Workspace<'_>,\n    pkg: &Package,\n    opts: &PackageOpts<'_>,\n) -> CargoResult<Vec<ArchiveFile>> {\n    let gctx = ws.gctx();\n    let mut src = PathSource::new(pkg.root(), pkg.package_id().source_id(), gctx);\n    src.load()?;\n\n    if opts.check_metadata {\n        check_metadata(pkg, opts.reg_or_index.as_ref(), gctx)?;\n    }\n\n    if !pkg.manifest().exclude().is_empty() && !pkg.manifest().include().is_empty() {\n        gctx.shell().warn(\n            \"both package.include and package.exclude are specified; \\\n             the exclude list will be ignored\",\n        )?;\n    }\n    let src_files = src.list_files(pkg)?;\n\n    // Check (git) repository state, getting the current commit hash.\n    let vcs_info = vcs::check_repo_state(pkg, &src_files, ws, &opts)?;\n    build_ar_list(ws, pkg, src_files, vcs_info, opts.include_lockfile)\n}\n\n/// Builds list of files to archive.\n#[tracing::instrument(skip_all)]\nfn build_ar_list(\n    ws: &Workspace<'_>,\n    pkg: &Package,\n    src_files: Vec<PathEntry>,\n    vcs_info: Option<vcs::VcsInfo>,\n    include_lockfile: bool,\n) -> CargoResult<Vec<ArchiveFile>> {\n    let mut result = HashMap::new();\n    let root = pkg.root();\n    for src_file in &src_files {\n        let rel_path = src_file.strip_prefix(&root)?;\n        check_filename(rel_path, &mut ws.gctx().shell())?;\n        let rel_str = rel_path.to_str().ok_or_else(|| {\n            anyhow::format_err!(\"non-utf8 path in source directory: {}\", rel_path.display())\n        })?;\n        match rel_str {\n            \"Cargo.lock\" => continue,\n            VCS_INFO_FILE | ORIGINAL_MANIFEST_FILE => anyhow::bail!(\n                \"invalid inclusion of reserved file name {} in package source\",\n                rel_str\n            ),\n            _ => {\n                result\n                    .entry(UncasedAscii::new(rel_str))\n                    .or_insert_with(Vec::new)\n                    .push(ArchiveFile {\n                        rel_path: rel_path.to_owned(),\n                        rel_str: rel_str.to_owned(),\n                        contents: FileContents::OnDisk(src_file.to_path_buf()),\n                    });\n            }\n        }\n    }\n\n    // Ensure we normalize for case insensitive filesystems (like on Windows) by removing the\n    // existing entry, regardless of case, and adding in with the correct case\n    if result.remove(&UncasedAscii::new(\"Cargo.toml\")).is_some() {\n        result\n            .entry(UncasedAscii::new(ORIGINAL_MANIFEST_FILE))\n            .or_insert_with(Vec::new)\n            .push(ArchiveFile {\n                rel_path: PathBuf::from(ORIGINAL_MANIFEST_FILE),\n                rel_str: ORIGINAL_MANIFEST_FILE.to_string(),\n                contents: FileContents::OnDisk(pkg.manifest_path().to_owned()),\n            });\n        result\n            .entry(UncasedAscii::new(\"Cargo.toml\"))\n            .or_insert_with(Vec::new)\n            .push(ArchiveFile {\n                rel_path: PathBuf::from(\"Cargo.toml\"),\n                rel_str: \"Cargo.toml\".to_string(),\n                contents: FileContents::Generated(GeneratedFile::Manifest(\n                    pkg.manifest_path().to_owned(),\n                )),\n            });\n    } else {\n        ws.gctx().shell().warn(&format!(\n            \"no `Cargo.toml` file found when packaging `{}` (note the case of the file name).\",\n            pkg.name()\n        ))?;\n    }\n\n    if include_lockfile {\n        let lockfile_path = ws.lock_root().as_path_unlocked().join(LOCKFILE_NAME);\n        let lockfile_path = lockfile_path.exists().then_some(lockfile_path);\n        let rel_str = \"Cargo.lock\";\n        result\n            .entry(UncasedAscii::new(rel_str))\n            .or_insert_with(Vec::new)\n            .push(ArchiveFile {\n                rel_path: PathBuf::from(rel_str),\n                rel_str: rel_str.to_string(),\n                contents: FileContents::Generated(GeneratedFile::Lockfile(lockfile_path)),\n            });\n    }\n\n    if let Some(vcs_info) = vcs_info {\n        let rel_str = VCS_INFO_FILE;\n        result\n            .entry(UncasedAscii::new(rel_str))\n            .or_insert_with(Vec::new)\n            .push(ArchiveFile {\n                rel_path: PathBuf::from(rel_str),\n                rel_str: rel_str.to_string(),\n                contents: FileContents::Generated(GeneratedFile::VcsInfo(vcs_info)),\n            });\n    }\n\n    let mut invalid_manifest_field: Vec<String> = vec![];\n\n    let mut result = result.into_values().flatten().collect();\n    if let Some(license_file) = &pkg.manifest().metadata().license_file {\n        let license_path = Path::new(license_file);\n        let abs_file_path = paths::normalize_path(&pkg.root().join(license_path));\n        if abs_file_path.is_file() {\n            check_for_file_and_add(\n                \"license-file\",\n                license_path,\n                abs_file_path,\n                pkg,\n                &mut result,\n                ws,\n            )?;\n        } else {\n            error_on_nonexistent_file(\n                &pkg,\n                &license_path,\n                \"license-file\",\n                &mut invalid_manifest_field,\n            );\n        }\n    }\n    if let Some(readme) = &pkg.manifest().metadata().readme {\n        let readme_path = Path::new(readme);\n        let abs_file_path = paths::normalize_path(&pkg.root().join(readme_path));\n        if abs_file_path.is_file() {\n            check_for_file_and_add(\"readme\", readme_path, abs_file_path, pkg, &mut result, ws)?;\n        } else {\n            error_on_nonexistent_file(&pkg, &readme_path, \"readme\", &mut invalid_manifest_field);\n        }\n    }\n\n    if !invalid_manifest_field.is_empty() {\n        return Err(anyhow::anyhow!(invalid_manifest_field.join(\"\\n\")));\n    }\n\n    for t in pkg\n        .manifest()\n        .targets()\n        .iter()\n        .filter(|t| t.is_custom_build())\n    {\n        if let Some(custom_build_path) = t.src_path().path() {\n            let abs_custom_build_path = paths::normalize_path(&pkg.root().join(custom_build_path));\n            if !abs_custom_build_path.is_file() || !abs_custom_build_path.starts_with(pkg.root()) {\n                error_custom_build_file_not_in_package(pkg, &abs_custom_build_path, t)?;\n            }\n        }\n    }\n\n    result.sort_unstable_by(|a, b| a.rel_path.cmp(&b.rel_path));\n\n    Ok(result)\n}\n\nfn check_for_file_and_add(\n    label: &str,\n    file_path: &Path,\n    abs_file_path: PathBuf,\n    pkg: &Package,\n    result: &mut Vec<ArchiveFile>,\n    ws: &Workspace<'_>,\n) -> CargoResult<()> {\n    match abs_file_path.strip_prefix(&pkg.root()) {\n        Ok(rel_file_path) => {\n            if !result.iter().any(|ar| ar.rel_path == rel_file_path) {\n                result.push(ArchiveFile {\n                    rel_path: rel_file_path.to_path_buf(),\n                    rel_str: rel_file_path\n                        .to_str()\n                        .expect(\"everything was utf8\")\n                        .to_string(),\n                    contents: FileContents::OnDisk(abs_file_path),\n                })\n            }\n        }\n        Err(_) => {\n            // The file exists somewhere outside of the package.\n            let file_name = file_path.file_name().unwrap();\n            if result.iter().any(|ar| ar.rel_path == file_name) {\n                ws.gctx().shell().warn(&format!(\n                    \"{} `{}` appears to be a path outside of the package, \\\n                            but there is already a file named `{}` in the root of the package. \\\n                            The archived crate will contain the copy in the root of the package. \\\n                            Update the {} to point to the path relative \\\n                            to the root of the package to remove this warning.\",\n                    label,\n                    file_path.display(),\n                    file_name.to_str().unwrap(),\n                    label,\n                ))?;\n            } else {\n                result.push(ArchiveFile {\n                    rel_path: PathBuf::from(file_name),\n                    rel_str: file_name.to_str().unwrap().to_string(),\n                    contents: FileContents::OnDisk(abs_file_path),\n                })\n            }\n        }\n    }\n    Ok(())\n}\n\nfn error_on_nonexistent_file(\n    pkg: &Package,\n    path: &Path,\n    manifest_key_name: &'static str,\n    invalid: &mut Vec<String>,\n) {\n    let rel_msg = if path.is_absolute() {\n        \"\".to_string()\n    } else {\n        format!(\" (relative to `{}`)\", pkg.root().display())\n    };\n\n    let msg = format!(\n        \"{manifest_key_name} `{}` does not appear to exist{}.\\n\\\n                Please update the {manifest_key_name} setting in the manifest at `{}`.\",\n        path.display(),\n        rel_msg,\n        pkg.manifest_path().display()\n    );\n\n    invalid.push(msg);\n}\n\nfn error_custom_build_file_not_in_package(\n    pkg: &Package,\n    path: &Path,\n    target: &Target,\n) -> CargoResult<Vec<ArchiveFile>> {\n    let tip = {\n        let description_name = target.description_named();\n        if path.is_file() {\n            format!(\n                \"the source file of {description_name} doesn't appear to be a path inside of the package.\\n\\\n            It is at `{}`, whereas the root the package is `{}`.\\n\",\n                path.display(),\n                pkg.root().display()\n            )\n        } else {\n            format!(\"the source file of {description_name} doesn't appear to exist.\\n\",)\n        }\n    };\n    let msg = format!(\n        \"{}\\\n        This may cause issue during packaging, as modules resolution and resources included via macros are often relative to the path of source files.\\n\\\n        Please update the `build` setting in the manifest at `{}` and point to a path inside the root of the package.\",\n        tip,\n        pkg.manifest_path().display()\n    );\n    anyhow::bail!(msg)\n}\n\n/// Construct `Cargo.lock` for the package to be published.\nfn build_lock(\n    ws: &Workspace<'_>,\n    opts: &PackageOpts<'_>,\n    publish_pkg: &Package,\n    local_reg: Option<&TmpRegistry<'_>>,\n) -> CargoResult<String> {\n    let gctx = ws.gctx();\n    let mut orig_resolve = ops::load_pkg_lockfile(ws)?;\n\n    let mut tmp_ws = Workspace::ephemeral(publish_pkg.clone(), ws.gctx(), None, true)?;\n\n    // The local registry is an overlay used for simulating workspace packages\n    // that are supposed to be in the published registry, but that aren't there\n    // yet.\n    if let Some(local_reg) = local_reg {\n        tmp_ws.add_local_overlay(\n            local_reg.upstream,\n            local_reg.root.as_path_unlocked().to_owned(),\n        );\n        if opts.dry_run {\n            if let Some(orig_resolve) = orig_resolve.as_mut() {\n                let upstream_in_lock = if local_reg.upstream.is_crates_io() {\n                    SourceId::crates_io(gctx)?\n                } else {\n                    local_reg.upstream\n                };\n                for (p, s) in local_reg.checksums() {\n                    orig_resolve.set_checksum(p.with_source_id(upstream_in_lock), s.to_owned());\n                }\n            }\n        }\n    }\n    let mut tmp_reg = tmp_ws.package_registry()?;\n\n    let mut new_resolve = ops::resolve_with_previous(\n        &mut tmp_reg,\n        &tmp_ws,\n        &CliFeatures::new_all(true),\n        HasDevUnits::Yes,\n        orig_resolve.as_ref(),\n        None,\n        &[],\n        true,\n    )?;\n\n    let pkg_set = ops::get_resolved_packages(&new_resolve, tmp_reg)?;\n\n    if let Some(orig_resolve) = orig_resolve {\n        compare_resolve(gctx, tmp_ws.current()?, &orig_resolve, &new_resolve)?;\n    }\n    check_yanked(\n        gctx,\n        &pkg_set,\n        &new_resolve,\n        \"consider updating to a version that is not yanked\",\n    )?;\n\n    ops::resolve_to_string(&tmp_ws, &mut new_resolve)\n}\n\n// Checks that the package has some piece of metadata that a human can\n// use to tell what the package is about.\nfn check_metadata(\n    pkg: &Package,\n    reg_or_index: Option<&RegistryOrIndex>,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let md = pkg.manifest().metadata();\n\n    let mut missing = vec![];\n\n    macro_rules! lacking {\n        ($( $($field: ident)||* ),*) => {{\n            $(\n                if $(md.$field.as_ref().map_or(true, |s| s.is_empty()))&&* {\n                    $(missing.push(stringify!($field).replace(\"_\", \"-\"));)*\n                }\n            )*\n        }}\n    }\n    lacking!(\n        description,\n        license || license_file,\n        documentation || homepage || repository\n    );\n\n    if !missing.is_empty() {\n        // Only warn if publishing to crates.io based on resolved registry\n        let should_warn = match reg_or_index {\n            Some(RegistryOrIndex::Registry(reg_name)) => reg_name == CRATES_IO_REGISTRY,\n            None => true,                             // Default is crates.io\n            Some(RegistryOrIndex::Index(_)) => false, // Custom index, not crates.io\n        };\n\n        if should_warn {\n            let mut things = missing[..missing.len() - 1].join(\", \");\n            // `things` will be empty if and only if its length is 1 (i.e., the only case\n            // to have no `or`).\n            if !things.is_empty() {\n                things.push_str(\" or \");\n            }\n            things.push_str(missing.last().unwrap());\n\n            gctx.shell().print_report(&[\n                Level::WARNING.secondary_title(format!(\"manifest has no {things}\"))\n                    .element(Level::NOTE.message(\"see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\"))\n             ],\n                 false\n            )?\n        }\n    }\n\n    Ok(())\n}\n\n/// Compresses and packages a list of [`ArchiveFile`]s and writes into the given file.\n///\n/// Returns the uncompressed size of the contents of the new archive file.\nfn tar(\n    ws: &Workspace<'_>,\n    opts: &PackageOpts<'_>,\n    pkg: &Package,\n    local_reg: Option<&TmpRegistry<'_>>,\n    ar_files: Vec<ArchiveFile>,\n    dst: &File,\n    filename: &str,\n) -> CargoResult<u64> {\n    // Prepare the encoder and its header.\n    let filename = Path::new(filename);\n    let encoder = GzBuilder::new()\n        .filename(paths::path2bytes(filename)?)\n        .write(dst, Compression::best());\n\n    // Put all package files into a compressed archive.\n    let mut ar = Builder::new(encoder);\n    ar.sparse(false);\n    let gctx = ws.gctx();\n\n    let base_name = format!(\"{}-{}\", pkg.name(), pkg.version());\n    let base_path = Path::new(&base_name);\n    let included = ar_files\n        .iter()\n        .map(|ar_file| ar_file.rel_path.clone())\n        .collect::<Vec<_>>();\n    let publish_pkg = prepare_for_publish(pkg, ws, Some(&included))?;\n\n    let mut uncompressed_size = 0;\n    for ar_file in ar_files {\n        let ArchiveFile {\n            rel_path,\n            rel_str,\n            contents,\n        } = ar_file;\n        let ar_path = base_path.join(&rel_path);\n        gctx.shell()\n            .verbose(|shell| shell.status(\"Archiving\", &rel_str))?;\n        let mut header = Header::new_gnu();\n        match contents {\n            FileContents::OnDisk(disk_path) => {\n                let mut file = File::open(&disk_path).with_context(|| {\n                    format!(\"failed to open for archiving: `{}`\", disk_path.display())\n                })?;\n                let metadata = file.metadata().with_context(|| {\n                    format!(\"could not learn metadata for: `{}`\", disk_path.display())\n                })?;\n                header.set_metadata_in_mode(&metadata, HeaderMode::Deterministic);\n                header.set_cksum();\n                ar.append_data(&mut header, &ar_path, &mut file)\n                    .with_context(|| {\n                        format!(\"could not archive source file `{}`\", disk_path.display())\n                    })?;\n                uncompressed_size += metadata.len() as u64;\n            }\n            FileContents::Generated(generated_kind) => {\n                let contents = match generated_kind {\n                    GeneratedFile::Manifest(_) => {\n                        publish_pkg.manifest().to_normalized_contents()?\n                    }\n                    GeneratedFile::Lockfile(_) => build_lock(ws, opts, &publish_pkg, local_reg)?,\n                    GeneratedFile::VcsInfo(ref s) => serde_json::to_string_pretty(s)?,\n                };\n                header.set_entry_type(EntryType::file());\n                header.set_mode(0o644);\n                header.set_size(contents.len() as u64);\n                // We need to have the same DETERMINISTIC_TIMESTAMP for generated files\n                // https://github.com/alexcrichton/tar-rs/blob/d0261f1f6cc959ba0758e7236b3fd81e90dd1dc6/src/header.rs#L18-L24\n                // Unfortunately tar-rs doesn't expose that so we hardcode the timestamp here.\n                // Hardcoded value be removed once alexcrichton/tar-rs#420 is merged and released.\n                // See also rust-lang/cargo#16237\n                header.set_mtime(1153704088);\n                header.set_cksum();\n                ar.append_data(&mut header, &ar_path, contents.as_bytes())\n                    .with_context(|| format!(\"could not archive source file `{}`\", rel_str))?;\n                uncompressed_size += contents.len() as u64;\n            }\n        }\n    }\n\n    let encoder = ar.into_inner()?;\n    encoder.finish()?;\n    Ok(uncompressed_size)\n}\n\n/// Generate warnings when packaging Cargo.lock, and the resolve have changed.\nfn compare_resolve(\n    gctx: &GlobalContext,\n    current_pkg: &Package,\n    orig_resolve: &Resolve,\n    new_resolve: &Resolve,\n) -> CargoResult<()> {\n    if gctx.shell().verbosity() != Verbosity::Verbose {\n        return Ok(());\n    }\n    let new_set: BTreeSet<PackageId> = new_resolve.iter().collect();\n    let orig_set: BTreeSet<PackageId> = orig_resolve.iter().collect();\n    let added = new_set.difference(&orig_set);\n    // Removed entries are ignored, this is used to quickly find hints for why\n    // an entry changed.\n    let removed: Vec<&PackageId> = orig_set.difference(&new_set).collect();\n    for pkg_id in added {\n        if pkg_id.name() == current_pkg.name() && pkg_id.version() == current_pkg.version() {\n            // Skip the package that is being created, since its SourceId\n            // (directory) changes.\n            continue;\n        }\n        // Check for candidates where the source has changed (such as [patch]\n        // or a dependency with multiple sources like path/version).\n        let removed_candidates: Vec<&PackageId> = removed\n            .iter()\n            .filter(|orig_pkg_id| {\n                orig_pkg_id.name() == pkg_id.name() && orig_pkg_id.version() == pkg_id.version()\n            })\n            .cloned()\n            .collect();\n        let extra = match removed_candidates.len() {\n            0 => {\n                // This can happen if the original was out of date.\n                let previous_versions: Vec<&PackageId> = removed\n                    .iter()\n                    .filter(|orig_pkg_id| orig_pkg_id.name() == pkg_id.name())\n                    .cloned()\n                    .collect();\n                match previous_versions.len() {\n                    0 => String::new(),\n                    1 => format!(\n                        \", previous version was `{}`\",\n                        previous_versions[0].version()\n                    ),\n                    _ => format!(\n                        \", previous versions were: {}\",\n                        previous_versions\n                            .iter()\n                            .map(|pkg_id| format!(\"`{}`\", pkg_id.version()))\n                            .collect::<Vec<_>>()\n                            .join(\", \")\n                    ),\n                }\n            }\n            1 => {\n                // This can happen for multi-sourced dependencies like\n                // `{path=\"...\", version=\"...\"}` or `[patch]` replacement.\n                // `[replace]` is not captured in Cargo.lock.\n                format!(\n                    \", was originally sourced from `{}`\",\n                    removed_candidates[0].source_id()\n                )\n            }\n            _ => {\n                // I don't know if there is a way to actually trigger this,\n                // but handle it just in case.\n                let comma_list = removed_candidates\n                    .iter()\n                    .map(|pkg_id| format!(\"`{}`\", pkg_id.source_id()))\n                    .collect::<Vec<_>>()\n                    .join(\", \");\n                format!(\n                    \", was originally sourced from one of these sources: {}\",\n                    comma_list\n                )\n            }\n        };\n        let msg = format!(\n            \"package `{}` added to the packaged Cargo.lock file{}\",\n            pkg_id, extra\n        );\n        gctx.shell().note(msg)?;\n    }\n    Ok(())\n}\n\npub fn check_yanked(\n    gctx: &GlobalContext,\n    pkg_set: &PackageSet<'_>,\n    resolve: &Resolve,\n    hint: &str,\n) -> CargoResult<()> {\n    // Checking the yanked status involves taking a look at the registry and\n    // maybe updating files, so be sure to lock it here.\n    let _lock = gctx.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n\n    let mut sources = pkg_set.sources_mut();\n    let mut pending: Vec<PackageId> = resolve.iter().collect();\n    let mut results = Vec::new();\n    for (_id, source) in sources.sources_mut() {\n        source.invalidate_cache();\n    }\n    while !pending.is_empty() {\n        pending.retain(|pkg_id| {\n            if let Some(source) = sources.get_mut(pkg_id.source_id()) {\n                match source.is_yanked(*pkg_id) {\n                    Poll::Ready(result) => results.push((*pkg_id, result)),\n                    Poll::Pending => return true,\n                }\n            }\n            false\n        });\n        for (_id, source) in sources.sources_mut() {\n            source.block_until_ready()?;\n        }\n    }\n\n    for (pkg_id, is_yanked) in results {\n        if is_yanked? {\n            gctx.shell().warn(format!(\n                \"package `{}` in Cargo.lock is yanked in registry `{}`, {}\",\n                pkg_id,\n                pkg_id.source_id().display_registry_name(),\n                hint\n            ))?;\n        }\n    }\n    Ok(())\n}\n\n// It can often be the case that files of a particular name on one platform\n// can't actually be created on another platform. For example files with colons\n// in the name are allowed on Unix but not on Windows.\n//\n// To help out in situations like this, issue about weird filenames when\n// packaging as a \"heads up\" that something may not work on other platforms.\nfn check_filename(file: &Path, shell: &mut Shell) -> CargoResult<()> {\n    let Some(name) = file.file_name() else {\n        return Ok(());\n    };\n    let Some(name) = name.to_str() else {\n        anyhow::bail!(\n            \"path does not have a unicode filename which may not unpack \\\n             on all platforms: {}\",\n            file.display()\n        )\n    };\n    let bad_chars = ['/', '\\\\', '<', '>', ':', '\"', '|', '?', '*'];\n    if let Some(c) = bad_chars.iter().find(|c| name.contains(**c)) {\n        anyhow::bail!(\n            \"cannot package a filename with a special character `{}`: {}\",\n            c,\n            file.display()\n        )\n    }\n    if restricted_names::is_windows_reserved_path(file) {\n        shell.warn(format!(\n            \"file {} is a reserved Windows filename, \\\n                it will not work on Windows platforms\",\n            file.display()\n        ))?;\n    }\n    Ok(())\n}\n\n/// Manages a temporary local registry that we use to overlay our new packages on the\n/// upstream registry. This way we can build lockfiles that depend on the new packages even\n/// before they're published.\nstruct TmpRegistry<'a> {\n    gctx: &'a GlobalContext,\n    upstream: SourceId,\n    root: Filesystem,\n    checksums: HashMap<PackageId, String>,\n    _lock: FileLock,\n}\n\nimpl<'a> TmpRegistry<'a> {\n    fn new(gctx: &'a GlobalContext, root: Filesystem, upstream: SourceId) -> CargoResult<Self> {\n        root.create_dir()?;\n        let _lock = root.open_rw_exclusive_create(\".cargo-lock\", gctx, \"temporary registry\")?;\n        let slf = Self {\n            gctx,\n            root,\n            upstream,\n            checksums: HashMap::new(),\n            _lock,\n        };\n        // If there's an old temporary registry, delete it.\n        let index_path = slf.index_path().into_path_unlocked();\n        if index_path.exists() {\n            paths::remove_dir_all(index_path)?;\n        }\n        slf.index_path().create_dir()?;\n        Ok(slf)\n    }\n\n    fn index_path(&self) -> Filesystem {\n        self.root.join(\"index\")\n    }\n\n    fn add_package(\n        &mut self,\n        ws: &Workspace<'_>,\n        package: &Package,\n        tar: &FileLock,\n    ) -> CargoResult<()> {\n        debug!(\n            \"adding package {}@{} to local overlay at {}\",\n            package.name(),\n            package.version(),\n            self.root.as_path_unlocked().display()\n        );\n        {\n            let mut tar_copy = self.root.open_rw_exclusive_create(\n                package.package_id().tarball_name(),\n                self.gctx,\n                \"temporary package registry\",\n            )?;\n            tar_copy.file().set_len(0)?;\n            tar.file().seek(SeekFrom::Start(0))?;\n            std::io::copy(&mut tar.file(), &mut tar_copy)?;\n            tar_copy.flush()?;\n        }\n\n        let new_crate = super::registry::prepare_transmit(self.gctx, ws, package, self.upstream)?;\n\n        tar.file().seek(SeekFrom::Start(0))?;\n        let cksum = cargo_util::Sha256::new()\n            .update_file(tar.file())?\n            .finish_hex();\n\n        self.checksums.insert(package.package_id(), cksum.clone());\n\n        let deps: Vec<_> = new_crate\n            .deps\n            .into_iter()\n            .map(|dep| {\n                let name = dep\n                    .explicit_name_in_toml\n                    .clone()\n                    .unwrap_or_else(|| dep.name.clone())\n                    .into();\n                let package = dep\n                    .explicit_name_in_toml\n                    .as_ref()\n                    .map(|_| dep.name.clone().into());\n                RegistryDependency {\n                    name: name,\n                    req: dep.version_req.into(),\n                    features: dep.features.into_iter().map(|x| x.into()).collect(),\n                    optional: dep.optional,\n                    default_features: dep.default_features,\n                    target: dep.target.map(|x| x.into()),\n                    kind: Some(dep.kind.into()),\n                    registry: dep.registry.map(|x| x.into()),\n                    package: package,\n                    public: None,\n                    artifact: dep\n                        .artifact\n                        .map(|xs| xs.into_iter().map(|x| x.into()).collect()),\n                    bindep_target: dep.bindep_target.map(|x| x.into()),\n                    lib: dep.lib,\n                }\n            })\n            .collect();\n\n        let index_line = serde_json::to_string(&IndexPackage {\n            name: new_crate.name.into(),\n            vers: package.version().clone(),\n            deps,\n            features: new_crate\n                .features\n                .into_iter()\n                .map(|(k, v)| (k.into(), v.into_iter().map(|x| x.into()).collect()))\n                .collect(),\n            features2: None,\n            cksum,\n            yanked: None,\n            links: new_crate.links.map(|x| x.into()),\n            rust_version: None,\n            pubtime: None,\n            v: Some(2),\n        })?;\n\n        let file =\n            cargo_util::registry::make_dep_path(&package.name().as_str().to_lowercase(), false);\n        let mut dst = self.index_path().open_rw_exclusive_create(\n            file,\n            self.gctx,\n            \"temporary package registry\",\n        )?;\n        dst.file().set_len(0)?;\n        dst.write_all(index_line.as_bytes())?;\n        Ok(())\n    }\n\n    fn checksums(&self) -> impl Iterator<Item = (PackageId, &str)> {\n        self.checksums.iter().map(|(p, s)| (*p, s.as_str()))\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_package/vcs.rs",
    "content": "//! Helpers to gather the VCS information for `cargo package`.\n\nuse crate::core::{Package, Workspace};\nuse crate::ops::PackageOpts;\nuse crate::sources::PathEntry;\nuse crate::{CargoResult, GlobalContext};\n\nuse annotate_snippets::Level;\nuse anyhow::Context;\nuse cargo_util::paths;\nuse gix::bstr::BString;\nuse gix::bstr::ByteSlice;\nuse gix::bstr::ByteVec;\nuse gix::dir::walk::EmissionMode;\nuse gix::dirwalk::Options;\nuse gix::index::entry::Mode;\nuse gix::status::tree_index::TrackRenames;\nuse gix::worktree::stack::state::ignore::Source;\nuse serde::Serialize;\nuse std::path::{Path, PathBuf};\nuse tracing::debug;\n\n/// Represents the VCS information when packaging.\n#[derive(Serialize)]\npub struct VcsInfo {\n    git: GitVcsInfo,\n    /// Path to the package within repo (empty string if root).\n    path_in_vcs: String,\n}\n\n/// Represents the Git VCS information when packaging.\n#[derive(Serialize)]\npub struct GitVcsInfo {\n    sha1: String,\n    /// Indicate whether the Git worktree is dirty.\n    #[serde(skip_serializing_if = \"std::ops::Not::not\")]\n    dirty: bool,\n}\n\n/// Checks if the package source is in a *git* DVCS repository.\n///\n/// If *git*, and the source is *dirty* (e.g., has uncommitted changes),\n/// and `--allow-dirty` has not been passed,\n/// then `bail!` with an informative message.\n/// Otherwise, return the sha1 hash of the current *HEAD* commit,\n/// or `None` if no repo is found.\n#[tracing::instrument(skip_all)]\npub fn check_repo_state(\n    p: &Package,\n    src_files: &[PathEntry],\n    ws: &Workspace<'_>,\n    opts: &PackageOpts<'_>,\n) -> CargoResult<Option<VcsInfo>> {\n    let gctx = ws.gctx();\n    let Ok(mut repo) = gix::discover(p.root()) else {\n        gctx.shell().verbose(|shell| {\n            shell.warn(format_args!(\n                \"no (git) VCS found for `{}`\",\n                p.root().display()\n            ))\n        })?;\n        // No Git repo found. Have to assume it is clean.\n        return Ok(None);\n    };\n\n    let Some(workdir) = repo.workdir() else {\n        debug!(\n            \"no (git) workdir found for repo at `{}`\",\n            repo.path().display()\n        );\n        // No git workdir. Have to assume it is clean.\n        return Ok(None);\n    };\n\n    debug!(\"found a git repo at `{}`\", workdir.display());\n    let path = p.manifest_path();\n\n    let manifest_exists = path.exists();\n    let path = paths::strip_prefix_canonical(path, workdir).unwrap_or_else(|_| path.to_path_buf());\n    let rela_path =\n        gix::path::to_unix_separators_on_windows(gix::path::os_str_into_bstr(path.as_os_str())?);\n    if !manifest_exists {\n        gctx.shell().verbose(|shell| {\n            shell.warn(format_args!(\n                \"Cargo.toml not found at `{}` in workdir `{}`\",\n                path.display(),\n                workdir.display()\n            ))\n        })?;\n        // No `Cargo.toml` found. This package may be irrelevant.\n        // Have to assume it is clean.\n        return Ok(None);\n    };\n\n    let manifest_is_ignored = {\n        let index = repo.index_or_empty()?;\n        let mut excludes =\n            repo.excludes(&index, None, Source::WorktreeThenIdMappingIfNotSkipped)?;\n        excludes\n            .at_entry(rela_path.as_bstr(), Some(Mode::FILE))?\n            .is_excluded()\n    };\n    if manifest_is_ignored {\n        gctx.shell().verbose(|shell| {\n            shell.warn(format_args!(\n                \"found (git) Cargo.toml ignored at `{}` in workdir `{}`\",\n                path.display(),\n                workdir.display()\n            ))\n        })?;\n        // An ignored `Cargo.toml` found. This package may be irrelevant.\n        // Have to assume it is clean.\n        return Ok(None);\n    }\n\n    warn_symlink_checked_out_as_plain_text_file(gctx, src_files, &repo)?;\n\n    debug!(\n        \"found (git) Cargo.toml at `{}` in workdir `{}`\",\n        path.display(),\n        workdir.display(),\n    );\n    let Some(git) = git(ws, p, src_files, &mut repo, &opts)? else {\n        // If the git repo lacks essential field like `sha1`, and since this field exists from the beginning,\n        // then don't generate the corresponding file in order to maintain consistency with past behavior.\n        return Ok(None);\n    };\n\n    let path_in_vcs = path\n        .parent()\n        .and_then(|p| p.to_str())\n        .unwrap_or(\"\")\n        .replace(\"\\\\\", \"/\");\n\n    Ok(Some(VcsInfo { git, path_in_vcs }))\n}\n\n/// Warns if any symlinks were checked out as plain text files.\n///\n/// Git config [`core.symlinks`] defaults to true when unset.\n/// In git-for-windows (and git as well),\n/// the config should be set to false explicitly when the repo was created,\n/// if symlink support wasn't detected [^1].\n///\n/// We assume the config was always set at creation time and never changed.\n/// So, if it is true, we don't bother users with any warning.\n///\n/// [^1]: <https://github.com/git-for-windows/git/blob/f1241afcc7956918d5da33ef74abd9cbba369247/setup.c#L2394-L2403>\n///\n/// [`core.symlinks`]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-coresymlinks\nfn warn_symlink_checked_out_as_plain_text_file(\n    gctx: &GlobalContext,\n    src_files: &[PathEntry],\n    repo: &gix::Repository,\n) -> CargoResult<()> {\n    if repo\n        .config_snapshot()\n        .boolean(&gix::config::tree::Core::SYMLINKS)\n        .unwrap_or(true)\n    {\n        return Ok(());\n    }\n\n    if src_files.iter().any(|f| f.maybe_plain_text_symlink()) {\n        let msg = format!(\n            \"found symbolic links that may be checked out as regular files for git repo at `{}/`\",\n            repo.workdir().unwrap().display()\n        );\n        let mut notes = vec![\n            Level::NOTE.message(\n                \"this might cause the `.crate` file to include incorrect or incomplete files\",\n            ),\n            Level::HELP.message(\"to avoid this, set the Git config `core.symlinks` to `true`\"),\n        ];\n        if cfg!(windows) {\n            notes.push(\n                Level::HELP.message(\"on Windows, enable the Developer Mode to support symlinks\"),\n            );\n        };\n        gctx.shell().print_report(\n            &[Level::WARNING\n                .secondary_title(msg)\n                .elements(notes.into_iter())],\n            false,\n        )?;\n    }\n\n    Ok(())\n}\n\n/// The real git status check starts from here.\nfn git(\n    ws: &Workspace<'_>,\n    pkg: &Package,\n    src_files: &[PathEntry],\n    repo: &mut gix::Repository,\n    opts: &PackageOpts<'_>,\n) -> CargoResult<Option<GitVcsInfo>> {\n    {\n        let mut config = repo.config_snapshot_mut();\n        // This currently is only a very minor speedup for the biggest repositories,\n        // but might trigger creating many threads.\n        config.set_value(&gix::config::tree::Index::THREADS, \"false\")?;\n    }\n    // This is a collection of any dirty or untracked files. This covers:\n    // - new/modified/deleted/renamed/type change (index or worktree)\n    // - untracked files (which are \"new\" worktree files)\n    // - ignored (in case the user has an `include` directive that\n    //   conflicts with .gitignore).\n    let mut dirty_files = Vec::new();\n    let workdir = repo.workdir().unwrap();\n    collect_statuses(\n        repo,\n        workdir,\n        relative_package_root(repo, pkg.root()).as_deref(),\n        &mut dirty_files,\n    )?;\n\n    // Include each submodule so that the error message can provide\n    // specifically *which* files in a submodule are modified.\n    status_submodules(repo, &mut dirty_files)?;\n\n    // Find the intersection of dirty in git, and the src_files that would\n    // be packaged. This is a lazy n^2 check, but seems fine with\n    // thousands of files.\n    let cwd = ws.gctx().cwd();\n    let mut dirty_src_files: Vec<_> = src_files\n        .iter()\n        .filter(|src_file| {\n            if let Some(canon_src_file) = src_file.is_symlink_or_under_symlink().then(|| {\n                gix::path::realpath_opts(\n                    &src_file,\n                    ws.gctx().cwd(),\n                    gix::path::realpath::MAX_SYMLINKS,\n                )\n                .unwrap_or_else(|_| src_file.to_path_buf())\n            }) {\n                dirty_files\n                    .iter()\n                    .any(|path| canon_src_file.starts_with(path))\n            } else {\n                dirty_files.iter().any(|path| src_file.starts_with(path))\n            }\n        })\n        .map(|p| p.as_ref())\n        .chain(dirty_files_outside_pkg_root(ws, pkg, repo, src_files)?.iter())\n        .map(|path| {\n            pathdiff::diff_paths(path, cwd)\n                .as_ref()\n                .unwrap_or(path)\n                .display()\n                .to_string()\n        })\n        .collect();\n    let dirty = !dirty_src_files.is_empty();\n    if !dirty || opts.allow_dirty {\n        let maybe_head_id = repo.head()?.try_peel_to_id()?;\n        Ok(maybe_head_id.map(|id| GitVcsInfo {\n            sha1: id.to_string(),\n            dirty,\n        }))\n    } else {\n        dirty_src_files.sort_unstable();\n        anyhow::bail!(\n            \"{} files in the working directory contain changes that were \\\n             not yet committed into git:\\n\\n{}\\n\\n\\\n             to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\",\n            dirty_src_files.len(),\n            dirty_src_files.join(\"\\n\")\n        )\n    }\n}\n\n/// Helper to collect dirty statuses for a single repo.\n/// `relative_package_root` is `Some` if the root is a sub-directory of the workdir.\n/// Writes dirty files outside `relative_package_root` into `dirty_files_outside_package_root`,\n/// and all *everything else* into `dirty_files`.\n#[must_use]\nfn collect_statuses(\n    repo: &gix::Repository,\n    workdir: &Path,\n    relative_package_root: Option<&Path>,\n    dirty_files: &mut Vec<PathBuf>,\n) -> CargoResult<()> {\n    let statuses = repo\n        .status(gix::progress::Discard)?\n        .dirwalk_options(configure_dirwalk)\n        .tree_index_track_renames(TrackRenames::Disabled)\n        .index_worktree_submodules(None)\n        .into_iter(\n            relative_package_root.map(|rela_pkg_root| {\n                // Use `:(top)` magic signature to make the pathspec relative to\n                // the repo root, not the current working directory.\n                let mut pathspec = BString::from(\":(top)\");\n                let prefix =\n                    gix::path::to_unix_separators_on_windows(gix::path::into_bstr(rela_pkg_root));\n                pathspec.push_str(prefix.as_ref());\n                pathspec\n            }), /* pathspec patterns */\n        )\n        .with_context(|| {\n            format!(\n                \"failed to begin git status for repo {}\",\n                repo.path().display()\n            )\n        })?;\n\n    for status in statuses {\n        let status = status.with_context(|| {\n            format!(\n                \"failed to retrieve git status from repo {}\",\n                repo.path().display()\n            )\n        })?;\n\n        let rel_path = gix::path::from_bstr(status.location());\n        let path = workdir.join(&rel_path);\n        // It is OK to include Cargo.lock even if it is ignored.\n        if path.ends_with(\"Cargo.lock\")\n            && matches!(\n                &status,\n                gix::status::Item::IndexWorktree(\n                    gix::status::index_worktree::Item::DirectoryContents { entry, .. }\n                ) if matches!(entry.status, gix::dir::entry::Status::Ignored(_))\n            )\n        {\n            continue;\n        }\n\n        dirty_files.push(path);\n    }\n    Ok(())\n}\n\n/// Helper to collect dirty statuses while recursing into submodules.\nfn status_submodules(repo: &gix::Repository, dirty_files: &mut Vec<PathBuf>) -> CargoResult<()> {\n    let Some(submodules) = repo.submodules()? else {\n        return Ok(());\n    };\n    for submodule in submodules {\n        // Ignore submodules that don't open, they are probably not initialized.\n        // If its files are required, then the verification step should fail.\n        if let Some(sub_repo) = submodule.open()? {\n            let Some(workdir) = sub_repo.workdir() else {\n                continue;\n            };\n            status_submodules(&sub_repo, dirty_files)?;\n            collect_statuses(&sub_repo, workdir, None, dirty_files)?;\n        }\n    }\n    Ok(())\n}\n\n/// Make `pkg_root` relative to the `repo` workdir.\nfn relative_package_root(repo: &gix::Repository, pkg_root: &Path) -> Option<PathBuf> {\n    let workdir = repo.workdir().unwrap();\n    let rela_root = pkg_root.strip_prefix(workdir).unwrap_or(Path::new(\"\"));\n    if rela_root.as_os_str().is_empty() {\n        None\n    } else {\n        rela_root.to_owned().into()\n    }\n}\n\n/// Checks whether \"included\" source files outside package root have been modified.\n///\n/// This currently looks at\n///\n/// * `package.readme` and `package.license-file` pointing to paths outside package root\n/// * symlinks targets residing outside package root\n/// * Any change in the root workspace manifest, regardless of what has changed.\n///\n/// This is required because those paths may link to a file outside the\n/// current package root, but still under the git workdir, affecting the\n/// final packaged `.crate` file.\nfn dirty_files_outside_pkg_root(\n    ws: &Workspace<'_>,\n    pkg: &Package,\n    repo: &gix::Repository,\n    src_files: &[PathEntry],\n) -> CargoResult<Vec<PathBuf>> {\n    let pkg_root = pkg.root();\n    let workdir = repo.workdir().unwrap();\n\n    let meta = pkg.manifest().metadata();\n    let metadata_paths: Vec<_> = [&meta.license_file, &meta.readme]\n        .into_iter()\n        .filter_map(|p| p.as_deref())\n        .map(|path| paths::normalize_path(&pkg_root.join(path)))\n        .collect();\n\n    let linked_files_outside_package_root: Vec<_> = src_files\n        .iter()\n        .filter(|p| p.is_symlink_or_under_symlink())\n        .map(|p| p.as_ref().as_path())\n        .chain(metadata_paths.iter().map(AsRef::as_ref))\n        .chain([ws.root_manifest()])\n        // If inside package root. Don't bother checking git status.\n        .filter(|p| paths::strip_prefix_canonical(p, pkg_root).is_err())\n        // Handle files outside package root but under git workdir,\n        .filter_map(|p| paths::strip_prefix_canonical(p, workdir).ok())\n        .collect();\n\n    if linked_files_outside_package_root.is_empty() {\n        return Ok(Vec::new());\n    }\n\n    let statuses = repo\n        .status(gix::progress::Discard)?\n        .dirwalk_options(configure_dirwalk)\n        // Limit the amount of threads for used for the worktree status, as the pathspec will\n        // prevent most paths from being visited anyway there is not much work.\n        .index_worktree_options_mut(|opts| opts.thread_limit = Some(1))\n        .tree_index_track_renames(TrackRenames::Disabled)\n        .index_worktree_submodules(None)\n        .into_iter(\n            linked_files_outside_package_root\n                .into_iter()\n                .map(|p| gix::path::into_bstr(p).into_owned()),\n        )\n        .with_context(|| {\n            format!(\n                \"failed to begin git status for outfor repo {}\",\n                repo.path().display()\n            )\n        })?;\n\n    let mut dirty_files = Vec::new();\n    for status in statuses {\n        let status = status.with_context(|| {\n            format!(\n                \"failed to retrieve git status from repo {}\",\n                repo.path().display()\n            )\n        })?;\n\n        let rel_path = gix::path::from_bstr(status.location());\n        let path = workdir.join(&rel_path);\n        dirty_files.push(path);\n    }\n    Ok(dirty_files)\n}\n\nfn configure_dirwalk(opts: Options) -> Options {\n    opts.emit_untracked(gix::dir::walk::EmissionMode::Matching)\n        // Also pick up ignored files or whole directories\n        // to specifically catch overzealously ignored source files.\n        // Later we will match these dirs by prefix, which is why collapsing\n        // them is desirable here.\n        .emit_ignored(Some(EmissionMode::CollapseDirectory))\n        .emit_tracked(false)\n        .recurse_repositories(false)\n        .symlinks_to_directories_are_ignored_like_directories(true)\n        .emit_empty_directories(false)\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_package/verify.rs",
    "content": "//! Helpers to verify a packaged `.crate` file.\n\nuse std::collections::HashMap;\nuse std::fs;\nuse std::fs::File;\nuse std::io::SeekFrom;\nuse std::io::prelude::*;\nuse std::path::Path;\nuse std::path::PathBuf;\nuse std::sync::Arc;\n\nuse anyhow::Context as _;\nuse cargo_util::paths;\nuse flate2::read::GzDecoder;\nuse tar::Archive;\n\nuse crate::CargoResult;\nuse crate::core::Feature;\nuse crate::core::Package;\nuse crate::core::SourceId;\nuse crate::core::Workspace;\nuse crate::core::compiler::BuildConfig;\nuse crate::core::compiler::DefaultExecutor;\nuse crate::core::compiler::Executor;\nuse crate::core::compiler::UserIntent;\nuse crate::ops;\nuse crate::sources::PathSource;\nuse crate::util;\nuse crate::util::FileLock;\n\nuse super::PackageOpts;\nuse super::TmpRegistry;\n\n/// Verifies whether a `.crate` file is able to compile.\npub fn run_verify(\n    ws: &Workspace<'_>,\n    pkg: &Package,\n    tar: &FileLock,\n    local_reg: Option<&TmpRegistry<'_>>,\n    opts: &PackageOpts<'_>,\n) -> CargoResult<()> {\n    let gctx = ws.gctx();\n\n    gctx.shell().status(\"Verifying\", pkg)?;\n\n    tar.file().seek(SeekFrom::Start(0))?;\n    let f = GzDecoder::new(tar.file());\n    let dst = ws.build_dir().as_path_unlocked().join(&format!(\n        \"package/{}-{}\",\n        pkg.name(),\n        pkg.version()\n    ));\n    if dst.exists() {\n        paths::remove_dir_all(&dst)?;\n    }\n    let mut archive = Archive::new(f);\n    // We don't need to set the Modified Time, as it's not relevant to verification\n    // and it errors on filesystems that don't support setting a modified timestamp\n    archive.set_preserve_mtime(false);\n    archive.unpack(dst.parent().unwrap())?;\n\n    // Manufacture an ephemeral workspace to ensure that even if the top-level\n    // package has a workspace we can still build our new crate.\n    let id = SourceId::for_path(&dst)?;\n    let mut src = PathSource::new(&dst, id, ws.gctx());\n    let new_pkg = src.root_package()?;\n    let pkg_fingerprint = hash_all(&dst)?;\n\n    // When packaging we use an ephemeral workspace but reuse the build cache to reduce\n    // verification time if the user has already compiled the dependencies and the fingerprint\n    // is unchanged.\n    let mut ws = Workspace::ephemeral(new_pkg, gctx, Some(ws.build_dir()), true)?;\n    if let Some(local_reg) = local_reg {\n        ws.add_local_overlay(\n            local_reg.upstream,\n            local_reg.root.as_path_unlocked().to_owned(),\n        );\n    }\n\n    let rustc_args = if pkg\n        .manifest()\n        .unstable_features()\n        .require(Feature::public_dependency())\n        .is_ok()\n        || ws.gctx().cli_unstable().public_dependency\n    {\n        // FIXME: Turn this on at some point in the future\n        //Some(vec![\"-D exported_private_dependencies\".to_string()])\n        Some(vec![])\n    } else {\n        None\n    };\n\n    let exec: Arc<dyn Executor> = Arc::new(DefaultExecutor);\n    ops::compile_with_exec(\n        &ws,\n        &ops::CompileOptions {\n            build_config: BuildConfig::new(\n                gctx,\n                opts.jobs.clone(),\n                opts.keep_going,\n                &opts.targets,\n                UserIntent::Build,\n            )?,\n            cli_features: opts.cli_features.clone(),\n            spec: ops::Packages::Packages(Vec::new()),\n            filter: ops::CompileFilter::Default {\n                required_features_filterable: true,\n            },\n            target_rustdoc_args: None,\n            target_rustc_args: rustc_args,\n            target_rustc_crate_types: None,\n            rustdoc_document_private_items: false,\n            honor_rust_version: None,\n        },\n        &exec,\n    )?;\n\n    // Check that `build.rs` didn't modify any files in the `src` directory.\n    let ws_fingerprint = hash_all(&dst)?;\n    if pkg_fingerprint != ws_fingerprint {\n        let changes = report_hash_difference(&pkg_fingerprint, &ws_fingerprint);\n        anyhow::bail!(\n            \"Source directory was modified by build.rs during cargo publish. \\\n             Build scripts should not modify anything outside of OUT_DIR.\\n\\\n             {}\\n\\n\\\n             To proceed despite this, pass the `--no-verify` flag.\",\n            changes\n        )\n    }\n\n    Ok(())\n}\n\n/// Hashes everything under a given directory.\n///\n/// This is for checking if any source file inside a `.crate` file has changed\n/// durint the compilation. It is usually caused by bad build scripts or proc\n/// macros trying to modify source files. Cargo disallows that.\nfn hash_all(path: &Path) -> CargoResult<HashMap<PathBuf, u64>> {\n    fn wrap(path: &Path) -> CargoResult<HashMap<PathBuf, u64>> {\n        let mut result = HashMap::new();\n        let walker = walkdir::WalkDir::new(path).into_iter();\n        for entry in walker.filter_entry(|e| !(e.depth() == 1 && e.file_name() == \"target\")) {\n            let entry = entry?;\n            let file_type = entry.file_type();\n            if file_type.is_file() {\n                let file = File::open(entry.path())?;\n                let hash = util::hex::hash_u64_file(&file)?;\n                result.insert(entry.path().to_path_buf(), hash);\n            } else if file_type.is_symlink() {\n                let hash = util::hex::hash_u64(&fs::read_link(entry.path())?);\n                result.insert(entry.path().to_path_buf(), hash);\n            } else if file_type.is_dir() {\n                let hash = util::hex::hash_u64(&());\n                result.insert(entry.path().to_path_buf(), hash);\n            }\n        }\n        Ok(result)\n    }\n    let result = wrap(path).with_context(|| format!(\"failed to verify output at {:?}\", path))?;\n    Ok(result)\n}\n\n/// Reports the hash difference before and after the compilation computed by  [`hash_all`].\nfn report_hash_difference(orig: &HashMap<PathBuf, u64>, after: &HashMap<PathBuf, u64>) -> String {\n    let mut changed = Vec::new();\n    let mut removed = Vec::new();\n    for (key, value) in orig {\n        match after.get(key) {\n            Some(after_value) => {\n                if value != after_value {\n                    changed.push(key.to_string_lossy());\n                }\n            }\n            None => removed.push(key.to_string_lossy()),\n        }\n    }\n    let mut added: Vec<_> = after\n        .keys()\n        .filter(|key| !orig.contains_key(*key))\n        .map(|key| key.to_string_lossy())\n        .collect();\n    let mut result = Vec::new();\n    if !changed.is_empty() {\n        changed.sort_unstable();\n        result.push(format!(\"Changed: {}\", changed.join(\"\\n\\t\")));\n    }\n    if !added.is_empty() {\n        added.sort_unstable();\n        result.push(format!(\"Added: {}\", added.join(\"\\n\\t\")));\n    }\n    if !removed.is_empty() {\n        removed.sort_unstable();\n        result.push(format!(\"Removed: {}\", removed.join(\"\\n\\t\")));\n    }\n    assert!(!result.is_empty(), \"unexpected empty change detection\");\n    result.join(\"\\n\")\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_pkgid.rs",
    "content": "use crate::core::{PackageIdSpec, PackageIdSpecQuery, Workspace};\nuse crate::ops;\nuse crate::util::CargoResult;\n\npub fn pkgid(ws: &Workspace<'_>, spec: Option<&str>) -> CargoResult<PackageIdSpec> {\n    let Some(resolve) = ops::load_pkg_lockfile(ws)? else {\n        anyhow::bail!(\"a Cargo.lock must exist for this command\")\n    };\n\n    let pkgid = match spec {\n        Some(spec) => PackageIdSpec::query_str(spec, resolve.iter())?,\n        None => ws.current()?.package_id(),\n    };\n    Ok(pkgid.to_spec())\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_read_manifest.rs",
    "content": "use std::path::Path;\n\nuse crate::core::{EitherManifest, Package, SourceId};\nuse crate::util::GlobalContext;\nuse crate::util::errors::CargoResult;\nuse crate::util::toml::read_manifest;\nuse tracing::trace;\n\npub fn read_package(\n    path: &Path,\n    source_id: SourceId,\n    gctx: &GlobalContext,\n) -> CargoResult<Package> {\n    trace!(\n        \"read_package; path={}; source-id={}\",\n        path.display(),\n        source_id\n    );\n    let manifest = read_manifest(path, source_id, gctx)?;\n    let manifest = match manifest {\n        EitherManifest::Real(manifest) => manifest,\n        EitherManifest::Virtual(..) => anyhow::bail!(\n            \"found a virtual manifest at `{}` instead of a package \\\n             manifest\",\n            path.display()\n        ),\n    };\n\n    Ok(Package::new(manifest, path))\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_remove.rs",
    "content": "//! Core of cargo-remove command\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Package;\nuse crate::util::toml_mut::manifest::DepTable;\nuse crate::util::toml_mut::manifest::LocalManifest;\nuse crate::util::toml_mut::manifest::MissingDependencyError;\n\n/// Remove a dependency from a Cargo.toml manifest file.\n#[derive(Debug)]\npub struct RemoveOptions<'a> {\n    /// Configuration information for Cargo operations\n    pub gctx: &'a GlobalContext,\n    /// Package to remove dependencies from\n    pub spec: &'a Package,\n    /// Dependencies to remove\n    pub dependencies: Vec<String>,\n    /// Which dependency section to remove these from\n    pub section: DepTable,\n    /// Whether or not to actually write the manifest\n    pub dry_run: bool,\n}\n\n/// Remove dependencies from a manifest\npub fn remove(options: &RemoveOptions<'_>) -> CargoResult<()> {\n    let dep_table = options\n        .section\n        .to_table()\n        .into_iter()\n        .map(String::from)\n        .collect::<Vec<_>>();\n\n    let manifest_path = options.spec.manifest_path().to_path_buf();\n    let mut manifest = LocalManifest::try_new(&manifest_path)?;\n\n    for dep in &options.dependencies {\n        let section = if dep_table.len() >= 3 {\n            format!(\"{} for target `{}`\", &dep_table[2], &dep_table[1])\n        } else {\n            dep_table[0].clone()\n        };\n        options\n            .gctx\n            .shell()\n            .status(\"Removing\", format!(\"{dep} from {section}\"))?;\n\n        manifest.remove_from_table(&dep_table, dep).map_err(\n            |MissingDependencyError {\n                 expected_name,\n                 expected_path,\n                 alt_name,\n                 alt_path,\n             }| {\n                use std::fmt::Write as _;\n\n                let mut error = String::new();\n                let path = expected_path.join(\".\");\n                let _ = write!(\n                    &mut error,\n                    \"the dependency `{expected_name}` could not be found in `{path}`\"\n                );\n                if let Some(alt_path) = alt_path {\n                    let mut flags = Vec::new();\n                    match (\n                        expected_path.last().unwrap().as_str(),\n                        alt_path.last().unwrap().as_str(),\n                    ) {\n                        (\"build-dependencies\", \"build-dependencies\") => {}\n                        (\"dev-dependencies\", \"dev-dependencies\") => {}\n                        (\"dependencies\", \"dependencies\") => {}\n                        (_, \"build-dependencies\") => flags.push(\"--build\"),\n                        (_, \"dev-dependencies\") => flags.push(\"--dev\"),\n                        (_, _) => {}\n                    }\n                    if expected_path[0] != \"target\" && alt_path[0] == \"target\" {\n                        flags.push(&\"--target\");\n                        flags.push(&alt_path[1]);\n                    }\n                    let alt_path = alt_path.join(\".\");\n                    if !flags.is_empty() {\n                        let flags = flags.join(\" \");\n                        let _ = write!(\n                            &mut error,\n                            \"\\n\\nhelp: pass `{flags}` to remove `{expected_name}` from `{alt_path}`\"\n                        );\n                    } else {\n                        let _ = write!(\n                            &mut error,\n                            \"\\n\\nhelp: a dependency with the same name exists in `{alt_path}`\"\n                        );\n                    }\n                } else if let Some(alt_name) = alt_name {\n                    let _ = write!(\n                        &mut error,\n                        \"\\n\\nhelp: a dependency with a similar name exists: `{alt_name}`\"\n                    );\n                }\n                anyhow::format_err!(\"{error}\")\n            },\n        )?;\n\n        // Now that we have removed the crate, if that was the last reference to that\n        // crate, then we need to drop any explicitly activated features on\n        // that crate.\n        manifest.gc_dep(dep);\n    }\n\n    if options.dry_run {\n        options\n            .gctx\n            .shell()\n            .warn(\"aborting remove due to dry run\")?;\n    } else {\n        manifest.write()?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_report/mod.rs",
    "content": "pub mod rebuilds;\npub mod sessions;\npub mod timings;\npub mod util;\n"
  },
  {
    "path": "src/cargo/ops/cargo_report/rebuilds.rs",
    "content": "//! The `cargo report rebuilds` command.\n\nuse std::collections::{HashMap, HashSet};\nuse std::fs::File;\nuse std::io::BufReader;\nuse std::path::Path;\n\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse anyhow::Context as _;\nuse cargo_util_schemas::core::PackageIdSpec;\nuse itertools::Itertools as _;\n\nuse crate::AlreadyPrintedError;\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Workspace;\nuse crate::core::compiler::CompileMode;\nuse crate::core::compiler::UnitIndex;\nuse crate::core::compiler::fingerprint::DirtyReason;\nuse crate::core::compiler::fingerprint::FsStatus;\nuse crate::core::compiler::fingerprint::StaleItem;\nuse crate::ops::cargo_report::util::find_log_file;\nuse crate::ops::cargo_report::util::unit_target_description;\nuse crate::util::log_message::FingerprintStatus;\nuse crate::util::log_message::LogMessage;\nuse crate::util::log_message::Target;\nuse crate::util::logger::RunId;\nuse crate::util::style;\n\nconst DEFAULT_DISPLAY_LIMIT: usize = 5;\n\npub struct ReportRebuildsOptions {\n    pub id: Option<RunId>,\n}\n\npub fn report_rebuilds(\n    gctx: &GlobalContext,\n    ws: Option<&Workspace<'_>>,\n    opts: ReportRebuildsOptions,\n) -> CargoResult<()> {\n    let Some((log, run_id)) = find_log_file(gctx, ws, opts.id.as_ref())? else {\n        let context = if let Some(ws) = ws {\n            format!(\" for workspace at `{}`\", ws.root().display())\n        } else {\n            String::new()\n        };\n        let (title, note) = if let Some(id) = &opts.id {\n            (\n                format!(\"session `{id}` not found{context}\"),\n                \"run `cargo report sessions` to list available sessions\",\n            )\n        } else {\n            (\n                format!(\"no sessions found{context}\"),\n                \"run command with `-Z build-analysis` to generate log files\",\n            )\n        };\n        let report = [Level::ERROR\n            .primary_title(title)\n            .element(Level::NOTE.message(note))];\n        gctx.shell().print_report(&report, false)?;\n        return Err(AlreadyPrintedError::new(anyhow::anyhow!(\"\")).into());\n    };\n\n    let ctx = prepare_context(&log)\n        .with_context(|| format!(\"failed to analyze log at `{}`\", log.display()))?;\n    let ws_root = ws.map(|ws| ws.root()).unwrap_or(gctx.cwd());\n\n    display_report(gctx, ctx, &run_id, ws_root)?;\n\n    Ok(())\n}\n\nstruct Context {\n    root_rebuilds: Vec<RootRebuild>,\n    units: HashMap<UnitIndex, UnitInfo>,\n    total_cached: usize,\n    total_new: usize,\n    total_rebuilt: usize,\n}\n\nstruct UnitInfo {\n    package_id: PackageIdSpec,\n    target: Target,\n    mode: CompileMode,\n}\n\nstruct RootRebuild {\n    unit_index: UnitIndex,\n    reason: DirtyReason,\n    affected_units: Vec<UnitIndex>,\n}\n\nfn prepare_context(log: &Path) -> CargoResult<Context> {\n    let reader = BufReader::new(File::open(log)?);\n\n    let mut units: HashMap<UnitIndex, UnitInfo> = HashMap::new();\n    let mut dependencies: HashMap<UnitIndex, Vec<UnitIndex>> = HashMap::new();\n    let mut dirty_reasons: HashMap<UnitIndex, DirtyReason> = HashMap::new();\n    let mut total_cached = 0;\n    let mut total_new = 0;\n    let mut total_rebuilt = 0;\n\n    for (log_index, result) in serde_json::Deserializer::from_reader(reader)\n        .into_iter::<LogMessage>()\n        .enumerate()\n    {\n        let msg = match result {\n            Ok(msg) => msg,\n            Err(e) => {\n                tracing::warn!(\"failed to parse log message at index {log_index}: {e}\");\n                continue;\n            }\n        };\n\n        match msg {\n            LogMessage::UnitRegistered {\n                package_id,\n                target,\n                mode,\n                index,\n                dependencies: deps,\n                ..\n            } => {\n                units.insert(\n                    index,\n                    UnitInfo {\n                        package_id,\n                        target,\n                        mode,\n                    },\n                );\n                dependencies.insert(index, deps);\n            }\n            LogMessage::UnitFingerprint {\n                index,\n                status,\n                cause,\n                ..\n            } => {\n                if let Some(reason) = cause {\n                    dirty_reasons.insert(index, reason);\n                }\n                match status {\n                    FingerprintStatus::Fresh => {\n                        total_cached += 1;\n                    }\n                    FingerprintStatus::Dirty => {\n                        total_rebuilt += 1;\n                    }\n                    FingerprintStatus::New => {\n                        total_new += 1;\n                        dirty_reasons.insert(index, DirtyReason::FreshBuild);\n                    }\n                }\n            }\n            _ => {}\n        }\n    }\n\n    // reverse dependency graph (dependents of each unit)\n    let mut reverse_deps: HashMap<UnitIndex, Vec<UnitIndex>> = HashMap::new();\n    for (unit_id, deps) in &dependencies {\n        for dep_id in deps {\n            reverse_deps.entry(*dep_id).or_default().push(*unit_id);\n        }\n    }\n\n    let rebuilt_units: HashSet<UnitIndex> = dirty_reasons.keys().copied().collect();\n\n    // Root rebuilds: units that rebuilt but none of their dependencies rebuilt\n    let root_rebuilds: Vec<_> = dirty_reasons\n        .iter()\n        .filter(|(unit_index, _)| {\n            let has_rebuilt_deps = dependencies\n                .get(unit_index)\n                .map(|deps| deps.iter().any(|dep| rebuilt_units.contains(dep)))\n                .unwrap_or_default();\n            !has_rebuilt_deps\n        })\n        .map(|(&unit_index, reason)| {\n            let affected_units = find_cascading_rebuilds(unit_index, &reverse_deps, &rebuilt_units);\n            RootRebuild {\n                unit_index,\n                reason: reason.clone(),\n                affected_units,\n            }\n        })\n        .sorted_by(|a, b| {\n            b.affected_units\n                .len()\n                .cmp(&a.affected_units.len())\n                .then_with(|| {\n                    let a_name = units.get(&a.unit_index).map(|u| u.package_id.name());\n                    let b_name = units.get(&b.unit_index).map(|u| u.package_id.name());\n                    a_name.cmp(&b_name)\n                })\n        })\n        .collect();\n\n    Ok(Context {\n        root_rebuilds,\n        units,\n        total_cached,\n        total_new,\n        total_rebuilt,\n    })\n}\n\n/// Finds all units that were rebuilt as a cascading effect of the given root rebuild.\nfn find_cascading_rebuilds(\n    root_rebuild: UnitIndex,\n    dependents: &HashMap<UnitIndex, Vec<UnitIndex>>,\n    rebuilt_units: &HashSet<UnitIndex>,\n) -> Vec<UnitIndex> {\n    let mut affected = Vec::new();\n    let mut visited = HashSet::new();\n    let mut queue = vec![root_rebuild];\n    visited.insert(root_rebuild);\n\n    while let Some(unit) = queue.pop() {\n        if let Some(deps) = dependents.get(&unit) {\n            for &dep in deps {\n                if !visited.contains(&dep) && rebuilt_units.contains(&dep) {\n                    visited.insert(dep);\n                    affected.push(dep);\n                    queue.push(dep);\n                }\n            }\n        }\n    }\n\n    affected.sort_unstable();\n    affected\n}\n\nfn display_report(\n    gctx: &GlobalContext,\n    ctx: Context,\n    run_id: &RunId,\n    ws_root: &Path,\n) -> CargoResult<()> {\n    let verbose = gctx.shell().verbosity() == crate::core::shell::Verbosity::Verbose;\n    let extra_verbose = gctx.extra_verbose();\n\n    let Context {\n        root_rebuilds,\n        units,\n        total_cached,\n        total_new,\n        total_rebuilt,\n    } = ctx;\n\n    let header = style::HEADER;\n    let subheader = style::LITERAL;\n    let mut shell = gctx.shell();\n    let stderr = shell.err();\n\n    writeln!(stderr, \"{header}Session:{header:#} {run_id}\")?;\n\n    // Render summary\n    let rebuilt_plural = plural(total_rebuilt);\n\n    writeln!(\n        stderr,\n        \"{header}Status:{header:#} {total_rebuilt} unit{rebuilt_plural} rebuilt, {total_cached} cached, {total_new} new\"\n    )?;\n    writeln!(stderr)?;\n\n    if total_rebuilt == 0 && total_new == 0 {\n        // Don't show detailed report if all units are cached.\n        return Ok(());\n    }\n\n    if total_rebuilt == 0 && total_cached == 0 {\n        // Don't show detailed report if all units are new build.\n        return Ok(());\n    }\n\n    // Render root rebuilds and cascading count\n    let root_rebuild_count = root_rebuilds.len();\n    let cascading_count: usize = root_rebuilds.iter().map(|r| r.affected_units.len()).sum();\n\n    let root_plural = plural(root_rebuild_count);\n    let cascading_plural = plural(cascading_count);\n\n    writeln!(stderr, \"{header}Rebuild impact:{header:#}\",)?;\n    writeln!(\n        stderr,\n        \"  root rebuilds: {root_rebuild_count} unit{root_plural}\"\n    )?;\n    writeln!(\n        stderr,\n        \"  cascading:     {cascading_count} unit{cascading_plural}\"\n    )?;\n    writeln!(stderr)?;\n\n    // Render each root rebuilds\n    let display_limit = if verbose {\n        root_rebuilds.len()\n    } else {\n        DEFAULT_DISPLAY_LIMIT.min(root_rebuilds.len())\n    };\n    let truncated_count = root_rebuilds.len().saturating_sub(display_limit);\n\n    if truncated_count > 0 {\n        let count = root_rebuilds.len();\n        writeln!(\n            stderr,\n            \"{header}Root rebuilds:{header:#} (top {display_limit} of {count} by impact)\",\n        )?;\n    } else {\n        writeln!(stderr, \"{header}Root rebuilds:{header:#}\",)?;\n    }\n\n    for (idx, root_rebuild) in root_rebuilds.iter().take(display_limit).enumerate() {\n        let unit_desc = units\n            .get(&root_rebuild.unit_index)\n            .map(unit_description)\n            .expect(\"must have the unit\");\n\n        let reason_str = format_dirty_reason(&root_rebuild.reason, &units, ws_root);\n\n        writeln!(\n            stderr,\n            \"  {subheader}{idx}. {unit_desc}:{subheader:#} {reason_str}\",\n        )?;\n\n        if root_rebuild.affected_units.is_empty() {\n            writeln!(stderr, \"     impact: no cascading rebuilds\")?;\n        } else {\n            let count = root_rebuild.affected_units.len();\n            let plural = plural(count);\n            writeln!(\n                stderr,\n                \"     impact: {count} dependent unit{plural} rebuilt\"\n            )?;\n\n            if extra_verbose {\n                for affected in &root_rebuild.affected_units {\n                    if let Some(affected) = units.get(affected) {\n                        let desc = unit_description(affected);\n                        writeln!(stderr, \"       - {desc}\")?;\n                    }\n                }\n            }\n        }\n    }\n\n    // Render --verbose notes\n    drop(shell);\n    let has_cascading_rebuilds = root_rebuilds.iter().any(|rr| !rr.affected_units.is_empty());\n\n    if !verbose && truncated_count > 0 {\n        writeln!(gctx.shell().err())?;\n        let note = \"pass `--verbose` to show all root rebuilds\";\n        gctx.shell().print_report(\n            &[Group::with_title(Level::NOTE.secondary_title(note))],\n            false,\n        )?;\n    } else if !extra_verbose && has_cascading_rebuilds {\n        writeln!(gctx.shell().err())?;\n        let note = \"pass `-vv` to show all affected rebuilt unit lists\";\n        gctx.shell().print_report(\n            &[Group::with_title(Level::NOTE.secondary_title(note))],\n            false,\n        )?;\n    }\n\n    Ok(())\n}\n\nfn unit_description(unit: &UnitInfo) -> String {\n    let name = unit.package_id.name();\n    let version = unit\n        .package_id\n        .version()\n        .map(|v| v.to_string())\n        .unwrap_or_else(|| \"<n/a>\".into());\n    let target = unit_target_description(&unit.target, unit.mode);\n\n    let literal = style::LITERAL;\n    let nop = style::NOP;\n\n    format!(\"{literal}{name}@{version}{literal:#}{nop}{target}{nop:#}\")\n}\n\nfn plural(len: usize) -> &'static str {\n    if len == 1 { \"\" } else { \"s\" }\n}\n\nfn format_dirty_reason(\n    reason: &DirtyReason,\n    units: &HashMap<UnitIndex, UnitInfo>,\n    ws_root: &Path,\n) -> String {\n    match reason {\n        DirtyReason::RustcChanged => \"toolchain changed\".to_string(),\n        DirtyReason::FeaturesChanged { old, new } => {\n            format!(\"activated features changed: {old} -> {new}\")\n        }\n        DirtyReason::DeclaredFeaturesChanged { old, new } => {\n            format!(\"declared features changed: {old} -> {new}\")\n        }\n        DirtyReason::TargetConfigurationChanged => \"target configuration changed\".to_string(),\n        DirtyReason::PathToSourceChanged => \"path to source changed\".to_string(),\n        DirtyReason::ProfileConfigurationChanged => \"profile configuration changed\".to_string(),\n        DirtyReason::RustflagsChanged { old, new } => {\n            let old = old.join(\", \");\n            let new = new.join(\", \");\n            format!(\"rustflags changed: {old} -> {new}\")\n        }\n        DirtyReason::ConfigSettingsChanged => \"config settings changed\".to_string(),\n        DirtyReason::CompileKindChanged => \"compile target changed\".to_string(),\n        DirtyReason::FsStatusOutdated(status) => match status {\n            FsStatus::Stale => \"filesystem status stale\".to_string(),\n            FsStatus::StaleItem(item) => match item {\n                StaleItem::MissingFile { path } => {\n                    let path = path.strip_prefix(ws_root).unwrap_or(path).display();\n                    format!(\"file missing: {path}\")\n                }\n                StaleItem::UnableToReadFile { path } => {\n                    let path = path.strip_prefix(ws_root).unwrap_or(path).display();\n                    format!(\"unable to read file: {path}\")\n                }\n                StaleItem::FailedToReadMetadata { path } => {\n                    let path = path.strip_prefix(ws_root).unwrap_or(path).display();\n                    format!(\"failed to read file metadata: {path}\")\n                }\n                StaleItem::FileSizeChanged {\n                    path,\n                    old_size: old,\n                    new_size: new,\n                } => {\n                    let path = path.strip_prefix(ws_root).unwrap_or(path).display();\n                    format!(\"file size changed: {path} ({old} -> {new} bytes)\")\n                }\n                StaleItem::ChangedFile { stale, .. } => {\n                    let path = stale.strip_prefix(ws_root).unwrap_or(stale).display();\n                    format!(\"file modified: {path}\")\n                }\n                StaleItem::ChangedChecksum {\n                    source,\n                    stored_checksum: old,\n                    new_checksum: new,\n                } => {\n                    let path = source.strip_prefix(ws_root).unwrap_or(source).display();\n                    format!(\"file checksum changed: {path} ({old} -> {new})\")\n                }\n                StaleItem::MissingChecksum { path } => {\n                    let path = path.strip_prefix(ws_root).unwrap_or(path).display();\n                    format!(\"checksum missing: {path}\")\n                }\n                StaleItem::ChangedEnv {\n                    var,\n                    previous,\n                    current,\n                } => {\n                    let old = previous.as_deref().unwrap_or(\"<unset>\");\n                    let new = current.as_deref().unwrap_or(\"<unset>\");\n                    format!(\"environment variable changed ({var}): {old} -> {new}\")\n                }\n            },\n            FsStatus::StaleDepFingerprint { unit } => units\n                .get(unit)\n                .map(|u| format!(\"dependency rebuilt: {}\", unit_description(u)))\n                .unwrap_or_else(|| format!(\"dependency rebuilt: unit {unit}\")),\n            FsStatus::StaleDependency { unit, .. } => units\n                .get(unit)\n                .map(|u| format!(\"dependency rebuilt: {}\", unit_description(u)))\n                .unwrap_or_else(|| format!(\"dependency rebuilt: unit {unit}\")),\n            FsStatus::UpToDate { .. } => \"up to date\".to_string(),\n        },\n        DirtyReason::EnvVarChanged {\n            name,\n            old_value,\n            new_value,\n        } => {\n            let old = old_value.as_deref().unwrap_or(\"<unset>\");\n            let new = new_value.as_deref().unwrap_or(\"<unset>\");\n            format!(\"environment variable changed ({name}): {old} -> {new}\")\n        }\n        DirtyReason::EnvVarsChanged { old, new } => {\n            format!(\"environment variables changed: {old} -> {new}\")\n        }\n        DirtyReason::LocalFingerprintTypeChanged { old, new } => {\n            format!(\"local fingerprint type changed: {old} -> {new}\")\n        }\n        DirtyReason::NumberOfDependenciesChanged { old, new } => {\n            format!(\"number of dependencies changed: {old} -> {new}\")\n        }\n        DirtyReason::UnitDependencyNameChanged { old, new } => {\n            format!(\"dependency name changed: {old} -> {new}\")\n        }\n        DirtyReason::UnitDependencyInfoChanged { unit } => units\n            .get(unit)\n            .map(|u| format!(\"dependency info changed: {}\", unit_description(u)))\n            .unwrap_or_else(|| \"dependency info changed\".to_string()),\n        DirtyReason::LocalLengthsChanged => \"local lengths changed\".to_string(),\n        DirtyReason::PrecalculatedComponentsChanged { old, new } => {\n            format!(\"precalculated components changed: {old} -> {new}\")\n        }\n        DirtyReason::ChecksumUseChanged { old } => {\n            if *old {\n                \"checksum use changed: enabled -> disabled\".to_string()\n            } else {\n                \"checksum use changed: disabled -> enabled\".to_string()\n            }\n        }\n        DirtyReason::DepInfoOutputChanged { old, new } => {\n            let old = old.strip_prefix(ws_root).unwrap_or(old).display();\n            let new = new.strip_prefix(ws_root).unwrap_or(new).display();\n            format!(\"dependency info output changed: {old} -> {new}\")\n        }\n        DirtyReason::RerunIfChangedOutputFileChanged { old, new } => {\n            let old = old.strip_prefix(ws_root).unwrap_or(old).display();\n            let new = new.strip_prefix(ws_root).unwrap_or(new).display();\n            format!(\"rerun-if-changed output file changed: {old} -> {new}\")\n        }\n        DirtyReason::RerunIfChangedOutputPathsChanged { old, new } => {\n            let old = old.len();\n            let new = new.len();\n            format!(\"rerun-if-changed paths changed: {old} path(s) -> {new} path(s)\",)\n        }\n        DirtyReason::NothingObvious => \"nothing obvious\".to_string(),\n        DirtyReason::Forced => \"forced rebuild\".to_string(),\n        DirtyReason::FreshBuild => \"fresh build\".to_string(),\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_report/sessions.rs",
    "content": "//! The `cargo report sessions` command.\n\nuse annotate_snippets::Level;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Workspace;\nuse crate::ops::cargo_report::util::list_log_files;\nuse crate::util::BuildLogger;\n\npub struct ReportSessionsOptions {\n    pub limit: usize,\n}\n\npub fn report_sessions(\n    gctx: &GlobalContext,\n    ws: Option<&Workspace<'_>>,\n    opts: ReportSessionsOptions,\n) -> CargoResult<()> {\n    let ws_run_id = ws.map(BuildLogger::generate_run_id);\n\n    // Take limit + 1 to detect if there are more sessions\n    let sessions: Vec<_> = list_log_files(gctx, None)?\n        .filter(|(_, id)| {\n            ws_run_id\n                .as_ref()\n                .map(|ws_run_id| ws_run_id.same_workspace(id))\n                .unwrap_or(true)\n        })\n        .take(opts.limit + 1)\n        .collect();\n\n    if sessions.is_empty() {\n        let context = if let Some(ws) = ws {\n            format!(\" for workspace at `{}`\", ws.root().display())\n        } else {\n            String::new()\n        };\n        let title = format!(\"no sessions found{context}\");\n        let note = \"run build commands with `-Z build-analysis` to generate log files\";\n\n        let report = [Level::ERROR\n            .primary_title(title)\n            .element(Level::NOTE.message(note))];\n        gctx.shell().print_report(&report, false)?;\n        return Err(crate::AlreadyPrintedError::new(anyhow::anyhow!(\"\")).into());\n    }\n\n    let truncated = sessions.len() > opts.limit;\n    let display_count = opts.limit.min(sessions.len());\n\n    let mut shell = gctx.shell();\n    let stderr = shell.err();\n\n    if let Some(ws) = ws {\n        writeln!(\n            stderr,\n            \"Session IDs for `{}` (most recent first):\",\n            ws.root().display(),\n        )?;\n    } else {\n        writeln!(stderr, \"Session IDs (most recent first):\",)?\n    };\n    writeln!(stderr)?;\n\n    for (_path, run_id) in sessions.iter().take(display_count) {\n        writeln!(stderr, \" - {run_id}\")?;\n    }\n\n    if truncated {\n        writeln!(stderr)?;\n        writeln!(stderr, \"... and more (use --limit N to see more)\")?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_report/timings.rs",
    "content": "//! The `cargo report timings` command.\n\nuse std::collections::HashSet;\nuse std::fs::File;\nuse std::io::BufReader;\nuse std::path::PathBuf;\n\nuse annotate_snippets::Level;\nuse anyhow::Context as _;\nuse cargo_util::paths;\nuse indexmap::IndexMap;\nuse indexmap::map::Entry;\nuse itertools::Itertools as _;\nuse tempfile::TempDir;\n\nuse crate::AlreadyPrintedError;\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Workspace;\nuse crate::core::compiler::UnitIndex;\nuse crate::core::compiler::timings::CompilationSection;\nuse crate::core::compiler::timings::UnitData;\nuse crate::core::compiler::timings::report::RenderContext;\nuse crate::core::compiler::timings::report::aggregate_sections;\nuse crate::core::compiler::timings::report::compute_concurrency;\nuse crate::core::compiler::timings::report::round_to_centisecond;\nuse crate::core::compiler::timings::report::write_html;\nuse crate::ops::cargo_report::util::find_log_file;\nuse crate::ops::cargo_report::util::unit_target_description;\nuse crate::util::log_message::FingerprintStatus;\nuse crate::util::log_message::LogMessage;\nuse crate::util::log_message::Target;\nuse crate::util::logger::RunId;\nuse crate::util::style;\n\npub struct ReportTimingsOptions<'gctx> {\n    /// Whether to attempt to open the browser after the report is generated\n    pub open_result: bool,\n    pub gctx: &'gctx GlobalContext,\n    pub id: Option<RunId>,\n}\n\n/// Collects sections data for later post-processing through [`aggregate_sections`].\nstruct UnitEntry {\n    target: Target,\n    data: UnitData,\n    sections: IndexMap<String, CompilationSection>,\n    rmeta_time: Option<f64>,\n}\n\npub fn report_timings(\n    gctx: &GlobalContext,\n    ws: Option<&Workspace<'_>>,\n    opts: ReportTimingsOptions<'_>,\n) -> CargoResult<()> {\n    let Some((log, run_id)) = find_log_file(gctx, ws, opts.id.as_ref())? else {\n        let context = if let Some(ws) = ws {\n            format!(\" for workspace at `{}`\", ws.root().display())\n        } else {\n            String::new()\n        };\n        let (title, note) = if let Some(id) = &opts.id {\n            (\n                format!(\"session `{id}` not found{context}\"),\n                \"run `cargo report sessions` to list available sessions\",\n            )\n        } else {\n            (\n                format!(\"no sessions found{context}\"),\n                \"run command with `-Z build-analysis` to generate log files\",\n            )\n        };\n        let report = [Level::ERROR\n            .primary_title(title)\n            .element(Level::NOTE.message(note))];\n        gctx.shell().print_report(&report, false)?;\n        return Err(AlreadyPrintedError::new(anyhow::anyhow!(\"\")).into());\n    };\n\n    let reader = BufReader::new(File::open(&log)?);\n    let iter = serde_json::Deserializer::from_reader(reader)\n        .into_iter::<LogMessage>()\n        .enumerate()\n        .filter_map(|(idx, msg)| match msg {\n            Ok(msg) => Some(msg),\n            Err(e) => {\n                tracing::warn!(\"failed to parse log message at index {idx}: {e}\");\n                None\n            }\n        });\n    let ctx = prepare_context(iter, &run_id)\n        .with_context(|| format!(\"failed to analyze log at `{}`\", log.display()))?;\n\n    // If we are in a workspace,\n    // put timing reports in <target-dir>/cargo-timings/` as usual for easy access.\n    // Otherwise in a temporary directory\n    let reports_dir = if let Some(ws) = ws {\n        let target_dir = ws.target_dir();\n        let target_dir = target_dir.as_path_unlocked();\n        paths::create_dir_all_excluded_from_backups_atomic(target_dir)?;\n        let timings_dir = target_dir.join(\"cargo-timings\");\n        paths::create_dir_all(&timings_dir)?;\n        timings_dir\n    } else if let Ok(path) = gctx.get_env(\"__CARGO_TEST_REPORT_TIMINGS_TEMPDIR\") {\n        PathBuf::from(path.to_owned())\n    } else {\n        TempDir::with_prefix(\"cargo-timings-\")?.keep()\n    };\n\n    let timing_path = reports_dir.join(format!(\"cargo-timing-{run_id}.html\"));\n\n    let mut out_file = std::fs::OpenOptions::new()\n        .write(true)\n        .create(true)\n        .truncate(true)\n        .open(&timing_path)\n        .with_context(|| format!(\"failed to open `{}`\", timing_path.display()))?;\n\n    write_html(ctx, &mut out_file)?;\n\n    let link = gctx.shell().err_file_hyperlink(&timing_path);\n    let msg = format!(\"report saved to {link}{}{link:#}\", timing_path.display());\n    gctx.shell()\n        .status_with_color(\"Timing\", msg, &style::NOTE)?;\n\n    if opts.open_result {\n        crate::util::open::open(&timing_path, gctx)?;\n    }\n\n    Ok(())\n}\n\npub(crate) fn prepare_context<I>(log: I, run_id: &RunId) -> CargoResult<RenderContext<'_>>\nwhere\n    I: Iterator<Item = LogMessage>,\n{\n    let mut ctx = RenderContext {\n        start_str: run_id.timestamp().to_string(),\n        root_units: Default::default(),\n        profile: Default::default(),\n        total_fresh: Default::default(),\n        total_dirty: Default::default(),\n        unit_data: Default::default(),\n        concurrency: Default::default(),\n        cpu_usage: Default::default(),\n        rustc_version: Default::default(),\n        host: Default::default(),\n        requested_targets: Default::default(),\n        jobs: 0,\n        num_cpus: None,\n        error: &None,\n    };\n    let mut units: IndexMap<_, UnitEntry> = IndexMap::new();\n\n    let mut platform_targets = HashSet::new();\n\n    let mut requested_units: HashSet<UnitIndex> = HashSet::new();\n\n    for msg in log {\n        match msg {\n            LogMessage::BuildStarted {\n                command: _,\n                cwd: _,\n                host,\n                jobs,\n                num_cpus,\n                profile,\n                rustc_version,\n                rustc_version_verbose,\n                target_dir: _,\n                workspace_root: _,\n            } => {\n                let rustc_version = rustc_version_verbose\n                    .lines()\n                    .next()\n                    .map(ToOwned::to_owned)\n                    .unwrap_or(rustc_version);\n                ctx.host = host;\n                ctx.jobs = jobs;\n                ctx.num_cpus = num_cpus;\n                ctx.profile = profile;\n                ctx.rustc_version = rustc_version;\n            }\n            LogMessage::UnitRegistered {\n                package_id,\n                target,\n                mode,\n                platform,\n                index,\n                features,\n                requested,\n                dependencies: _,\n            } => {\n                if requested {\n                    requested_units.insert(index);\n                }\n                platform_targets.insert(platform);\n\n                let version = package_id\n                    .version()\n                    .map(|v| v.to_string())\n                    .unwrap_or_else(|| \"N/A\".into());\n\n                let target_str = unit_target_description(&target, mode);\n\n                let mode_str = if mode.is_run_custom_build() {\n                    \"run-custom-build\"\n                } else {\n                    \"todo\"\n                };\n\n                let data = UnitData {\n                    i: index,\n                    name: package_id.name().to_string(),\n                    version,\n                    mode: mode_str.to_owned(),\n                    target: target_str,\n                    features,\n                    start: 0.0,\n                    duration: 0.0,\n                    unblocked_units: Vec::new(),\n                    unblocked_rmeta_units: Vec::new(),\n                    sections: None,\n                };\n\n                units.insert(\n                    index,\n                    UnitEntry {\n                        target,\n                        data,\n                        sections: IndexMap::new(),\n                        rmeta_time: None,\n                    },\n                );\n            }\n            LogMessage::UnitFingerprint { status, .. } => match status {\n                FingerprintStatus::New => ctx.total_dirty += 1,\n                FingerprintStatus::Dirty => ctx.total_dirty += 1,\n                FingerprintStatus::Fresh => ctx.total_fresh += 1,\n            },\n            LogMessage::UnitStarted { index, elapsed } => {\n                units\n                    .entry(index)\n                    .and_modify(|unit| unit.data.start = elapsed)\n                    .or_insert_with(|| {\n                        unreachable!(\"unit {index} must have been registered first\")\n                    });\n            }\n            LogMessage::UnitRmetaFinished {\n                index,\n                elapsed,\n                unblocked,\n            } => match units.entry(index) {\n                Entry::Occupied(mut e) => {\n                    let elapsed = f64::max(elapsed - e.get().data.start, 0.0);\n                    e.get_mut().data.unblocked_rmeta_units = unblocked;\n                    e.get_mut().data.duration = elapsed;\n                    e.get_mut().rmeta_time = Some(elapsed);\n                }\n                Entry::Vacant(_) => {\n                    tracing::warn!(\n                        \"section `frontend` ended, but unit {index} has no start recorded\"\n                    )\n                }\n            },\n            LogMessage::UnitSectionStarted {\n                index,\n                elapsed,\n                section,\n            } => match units.entry(index) {\n                Entry::Occupied(mut e) => {\n                    let elapsed = f64::max(elapsed - e.get().data.start, 0.0);\n                    if e.get_mut()\n                        .sections\n                        .insert(\n                            section.clone(),\n                            CompilationSection {\n                                start: elapsed,\n                                end: None,\n                            },\n                        )\n                        .is_some()\n                    {\n                        tracing::warn!(\n                            \"section `{section}` for unit {index} started more than once\",\n                        );\n                    }\n                }\n                Entry::Vacant(_) => {\n                    tracing::warn!(\n                        \"section `{section}` started, but unit {index} has no start recorded\"\n                    )\n                }\n            },\n            LogMessage::UnitSectionFinished {\n                index,\n                elapsed,\n                section,\n            } => match units.entry(index) {\n                Entry::Occupied(mut e) => {\n                    let elapsed = f64::max(elapsed - e.get().data.start, 0.0);\n                    if let Some(section) = e.get_mut().sections.get_mut(&section) {\n                        section.end = Some(elapsed);\n                    } else {\n                        tracing::warn!(\n                            \"section `{section}` for unit {index} ended, but section `{section}` has no start recorded\"\n                        );\n                    }\n                }\n                Entry::Vacant(_) => {\n                    tracing::warn!(\n                        \"section `{section}` ended, but unit {index} has no start recorded\"\n                    )\n                }\n            },\n            LogMessage::UnitFinished {\n                index,\n                elapsed,\n                unblocked,\n            } => match units.entry(index) {\n                Entry::Occupied(mut e) => {\n                    let elapsed = f64::max(elapsed - e.get().data.start, 0.0);\n                    e.get_mut().data.duration = elapsed;\n                    e.get_mut().data.unblocked_units = unblocked;\n                }\n                Entry::Vacant(_) => {\n                    tracing::warn!(\"unit {index} ended, but it has no start recorded\");\n                }\n            },\n            _ => {} // skip non-timing logs\n        }\n    }\n\n    ctx.root_units = {\n        let mut root_map: IndexMap<_, Vec<_>> = IndexMap::new();\n        for index in requested_units {\n            let unit = &units[&index];\n            // Pretty much like `core::Target::description_named`\n            let target_desc = if unit.target.kind == \"lib\" {\n                \"lib\".to_owned()\n            } else if unit.target.kind == \"build-script\" {\n                \"build script\".to_owned()\n            } else {\n                format!(r#\" {} \"{}\"\"#, unit.target.name, unit.target.kind)\n            };\n            root_map.entry(index).or_default().push(target_desc);\n        }\n        root_map\n            .into_iter()\n            .sorted_by_key(|(i, _)| *i)\n            .map(|(index, targets)| {\n                let unit = &units[&index];\n                let pkg_desc = format!(\"{} {}\", unit.data.name, unit.data.version);\n                (pkg_desc, targets)\n            })\n            .collect()\n    };\n\n    let unit_data: Vec<_> = units\n        .into_values()\n        .map(\n            |UnitEntry {\n                 target: _,\n                 mut data,\n                 sections,\n                 rmeta_time,\n             }| {\n                // Post-processing for compilation sections we've collected so far.\n                data.sections = aggregate_sections(sections, data.duration, rmeta_time);\n                data.start = round_to_centisecond(data.start);\n                data.duration = round_to_centisecond(data.duration);\n                data\n            },\n        )\n        .sorted_unstable_by(|a, b| a.start.partial_cmp(&b.start).unwrap())\n        .collect();\n\n    if unit_data.is_empty() {\n        anyhow::bail!(\"no timing data found in log\");\n    }\n\n    ctx.unit_data = unit_data;\n    ctx.concurrency = compute_concurrency(&ctx.unit_data);\n    ctx.requested_targets = platform_targets.into_iter().sorted_unstable().collect();\n\n    Ok(ctx)\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_report/util.rs",
    "content": "//! Common utilities for `cargo report` commands.\n\nuse std::ffi::OsStr;\nuse std::path::PathBuf;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Workspace;\nuse crate::core::compiler::CompileMode;\nuse crate::util::BuildLogger;\nuse crate::util::log_message::Target;\nuse crate::util::logger::RunId;\n\n/// Lists log files by calling a callback for each valid log file.\n///\n/// * Yield log files from new to old\n/// * If in a workspace, select only the log files associated with the workspace\npub fn list_log_files(\n    gctx: &GlobalContext,\n    ws: Option<&Workspace<'_>>,\n) -> CargoResult<Box<dyn Iterator<Item = (PathBuf, RunId)>>> {\n    let log_dir = gctx.home().join(\"log\");\n    let log_dir = log_dir.as_path_unlocked();\n\n    if !log_dir.exists() {\n        return Ok(Box::new(std::iter::empty()));\n    }\n\n    let walk = walkdir::WalkDir::new(log_dir)\n        .follow_links(true)\n        .sort_by(|a, b| a.file_name().cmp(b.file_name()).reverse())\n        .min_depth(1)\n        .max_depth(1)\n        .into_iter()\n        .filter_map(|entry| {\n            let entry = entry.ok()?;\n            let path = entry.path();\n\n            // We only accept JSONL/NDJSON files.\n            if !entry.file_type().is_file() {\n                return None;\n            }\n            if entry.path().extension() != Some(OsStr::new(\"jsonl\")) {\n                return None;\n            }\n\n            // ...and the file name must follow RunId format\n            let run_id = path.file_stem()?.to_str()?.parse::<RunId>().ok()?;\n            Some((path.to_path_buf(), run_id))\n        });\n\n    let ws_run_id = ws.map(BuildLogger::generate_run_id);\n\n    let walk = walk.filter(move |(_, id)| {\n        ws_run_id\n            .as_ref()\n            .map_or(true, |ws_id| id.same_workspace(ws_id))\n    });\n\n    Ok(Box::new(walk))\n}\n\npub fn find_log_file(\n    gctx: &GlobalContext,\n    ws: Option<&Workspace<'_>>,\n    id: Option<&RunId>,\n) -> CargoResult<Option<(std::path::PathBuf, RunId)>> {\n    match id {\n        Some(requested_id) => {\n            for (path, run_id) in list_log_files(gctx, ws)? {\n                if run_id.to_string() == requested_id.to_string() {\n                    return Ok(Some((path, run_id)));\n                }\n            }\n            Ok(None)\n        }\n        None => Ok(list_log_files(gctx, ws)?.next()),\n    }\n}\n\npub fn unit_target_description(target: &Target, mode: CompileMode) -> String {\n    // This is pretty similar to how the current `core::compiler::timings`\n    // renders `core::manifest::Target`. However, our target is\n    // a simplified type so we cannot reuse the same logic here.\n    let mut target_str =\n        if target.kind == \"lib\" && matches!(mode, CompileMode::Build | CompileMode::Check { .. }) {\n            // Special case for brevity, since most dependencies hit this path.\n            \"\".to_string()\n        } else if target.kind == \"build-script\" {\n            \" build-script\".to_string()\n        } else {\n            format!(r#\" {} \"{}\"\"#, target.name, target.kind)\n        };\n\n    match mode {\n        CompileMode::Test => target_str.push_str(\" (test)\"),\n        CompileMode::Build => {}\n        CompileMode::Check { test: true } => target_str.push_str(\" (check-test)\"),\n        CompileMode::Check { test: false } => target_str.push_str(\" (check)\"),\n        CompileMode::Doc { .. } => target_str.push_str(\" (doc)\"),\n        CompileMode::Doctest => target_str.push_str(\" (doc test)\"),\n        CompileMode::Docscrape => target_str.push_str(\" (doc scrape)\"),\n        CompileMode::RunCustomBuild => target_str.push_str(\" (run)\"),\n    }\n\n    target_str\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_run.rs",
    "content": "use std::ffi::OsString;\nuse std::fmt::Write as _;\nuse std::iter;\nuse std::path::Path;\n\nuse crate::core::MaybePackage;\nuse crate::core::compiler::UnitOutput;\nuse crate::core::{TargetKind, Workspace};\nuse crate::ops;\nuse crate::util::CargoResult;\n\npub fn run(\n    ws: &Workspace<'_>,\n    options: &ops::CompileOptions,\n    args: &[OsString],\n) -> CargoResult<()> {\n    let gctx = ws.gctx();\n\n    if options.filter.contains_glob_patterns() {\n        anyhow::bail!(\"`cargo run` does not support glob patterns on target selection\")\n    }\n\n    // We compute the `bins` here *just for diagnosis*. The actual set of\n    // packages to be run is determined by the `ops::compile` call below.\n    let packages = options.spec.get_packages(ws)?;\n    let bins: Vec<_> = packages\n        .into_iter()\n        .flat_map(|pkg| {\n            iter::repeat(pkg).zip(pkg.manifest().targets().iter().filter(|target| {\n                !target.is_lib()\n                    && !target.is_custom_build()\n                    && if !options.filter.is_specific() {\n                        target.is_bin()\n                    } else {\n                        options.filter.target_run(target)\n                    }\n            }))\n        })\n        .collect();\n\n    if bins.is_empty() {\n        if !options.filter.is_specific() {\n            anyhow::bail!(\"a bin target must be available for `cargo run`\")\n        } else {\n            // This will be verified in `cargo_compile`.\n        }\n    }\n\n    if bins.len() == 1 {\n        let target = bins[0].1;\n        if let TargetKind::ExampleLib(..) = target.kind() {\n            anyhow::bail!(\n                \"example target `{}` is a library and cannot be executed\",\n                target.name()\n            )\n        }\n    }\n\n    if bins.len() > 1 {\n        if !options.filter.is_specific() {\n            let mut names: Vec<&str> = bins\n                .into_iter()\n                .map(|(_pkg, target)| target.name())\n                .collect();\n            names.sort();\n            anyhow::bail!(\n                \"`cargo run` could not determine which binary to run. \\\n                 Use the `--bin` option to specify a binary, \\\n                 or the `default-run` manifest key.\\n\\\n                 available binaries: {}\",\n                names.join(\", \")\n            )\n        } else {\n            let mut message = \"`cargo run` can run at most one executable, but \\\n                 multiple were specified\"\n                .to_owned();\n            write!(&mut message, \"\\nhelp: available targets:\")?;\n            for (pkg, bin) in &bins {\n                write!(\n                    &mut message,\n                    \"\\n    {} `{}` in package `{}`\",\n                    bin.kind().description(),\n                    bin.name(),\n                    pkg.name()\n                )?;\n            }\n            anyhow::bail!(message)\n        }\n    }\n\n    // `cargo run` is only compatible with one `--target` flag at most\n    options.build_config.single_requested_kind()?;\n\n    let compile = ops::compile(ws, options)?;\n    assert_eq!(compile.binaries.len(), 1);\n    let UnitOutput {\n        unit,\n        path,\n        script_metas,\n        env: _env,\n    } = &compile.binaries[0];\n    let exe = match path.strip_prefix(gctx.cwd()) {\n        Ok(path) if path.file_name() == Some(path.as_os_str()) => Path::new(\".\").join(path),\n        Ok(path) => path.to_path_buf(),\n        Err(_) => path.to_path_buf(),\n    };\n    let pkg = bins[0].0;\n    let mut process = compile.target_process(exe, unit.kind, pkg, script_metas.as_ref())?;\n\n    if let MaybePackage::Package(pkg) = ws.root_maybe()\n        && pkg.manifest().is_embedded()\n    {\n        process.arg0(pkg.manifest_path());\n    }\n\n    // Sets the working directory of the child process to the current working\n    // directory of the parent process.\n    // Overrides the default working directory of the `ProcessBuilder` returned\n    // by `compile.target_process` (the package's root directory)\n    process.args(args).cwd(gctx.cwd());\n\n    if gctx.extra_verbose() {\n        process.display_env_vars();\n    }\n\n    gctx.shell().status(\"Running\", process.to_string())?;\n\n    process.exec_replace()\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_test.rs",
    "content": "use crate::core::compiler::{Compilation, Doctest, Unit, UnitHash, UnitOutput};\nuse crate::core::profiles::PanicStrategy;\nuse crate::core::shell::ColorChoice;\nuse crate::core::shell::Verbosity;\nuse crate::core::{TargetKind, Workspace};\nuse crate::ops;\nuse crate::util::errors::CargoResult;\nuse crate::util::{CliError, CliResult, GlobalContext, add_path_args};\nuse anyhow::format_err;\nuse cargo_util::{ProcessBuilder, ProcessError};\nuse std::collections::HashMap;\nuse std::ffi::OsString;\nuse std::fmt::Write;\nuse std::path::{Path, PathBuf};\n\npub struct TestOptions {\n    pub compile_opts: ops::CompileOptions,\n    pub no_run: bool,\n    pub no_fail_fast: bool,\n}\n\n/// The kind of test.\n///\n/// This is needed because `Unit` does not track whether or not something is a\n/// benchmark.\n#[derive(Copy, Clone)]\nenum TestKind {\n    Test,\n    Bench,\n    Doctest,\n}\n\n/// A unit that failed to run.\nstruct UnitTestError {\n    unit: Unit,\n    kind: TestKind,\n}\n\nimpl UnitTestError {\n    /// Returns the CLI args needed to target this unit.\n    fn cli_args(&self, ws: &Workspace<'_>, opts: &ops::CompileOptions) -> String {\n        let mut args = if opts.spec.needs_spec_flag(ws) {\n            format!(\"-p {} \", self.unit.pkg.name())\n        } else {\n            String::new()\n        };\n        let mut add = |which| write!(args, \"--{which} {}\", self.unit.target.name()).unwrap();\n\n        match self.kind {\n            TestKind::Test | TestKind::Bench => match self.unit.target.kind() {\n                TargetKind::Lib(_) => args.push_str(\"--lib\"),\n                TargetKind::Bin => add(\"bin\"),\n                TargetKind::Test => add(\"test\"),\n                TargetKind::Bench => add(\"bench\"),\n                TargetKind::ExampleLib(_) | TargetKind::ExampleBin => add(\"example\"),\n                TargetKind::CustomBuild => panic!(\"unexpected CustomBuild kind\"),\n            },\n            TestKind::Doctest => args.push_str(\"--doc\"),\n        }\n        args\n    }\n}\n\n/// Compiles and runs tests.\n///\n/// On error, the returned [`CliError`] will have the appropriate process exit\n/// code that Cargo should use.\npub fn run_tests(ws: &Workspace<'_>, options: &TestOptions, test_args: &[&str]) -> CliResult {\n    let compilation = compile_tests(ws, options)?;\n\n    if options.no_run {\n        if !options.compile_opts.build_config.emit_json() {\n            display_no_run_information(ws, test_args, &compilation, \"unittests\")?;\n        }\n        return Ok(());\n    }\n    let mut errors = run_unit_tests(ws, options, test_args, &compilation, TestKind::Test)?;\n\n    let doctest_errors = run_doc_tests(ws, options, test_args, &compilation)?;\n    errors.extend(doctest_errors);\n    no_fail_fast_err(ws, &options.compile_opts, &errors)\n}\n\n/// Compiles and runs benchmarks.\n///\n/// On error, the returned [`CliError`] will have the appropriate process exit\n/// code that Cargo should use.\npub fn run_benches(ws: &Workspace<'_>, options: &TestOptions, args: &[&str]) -> CliResult {\n    let compilation = compile_tests(ws, options)?;\n\n    if options.no_run {\n        if !options.compile_opts.build_config.emit_json() {\n            display_no_run_information(ws, args, &compilation, \"benches\")?;\n        }\n        return Ok(());\n    }\n\n    let mut args = args.to_vec();\n    args.push(\"--bench\");\n\n    let errors = run_unit_tests(ws, options, &args, &compilation, TestKind::Bench)?;\n    no_fail_fast_err(ws, &options.compile_opts, &errors)\n}\n\nfn compile_tests<'a>(ws: &Workspace<'a>, options: &TestOptions) -> CargoResult<Compilation<'a>> {\n    let mut compilation = ops::compile(ws, &options.compile_opts)?;\n    compilation.tests.sort_by_key(|u| u.unit.clone());\n    Ok(compilation)\n}\n\n/// Runs the unit and integration tests of a package.\n///\n/// Returns a `Vec` of tests that failed when `--no-fail-fast` is used.\n/// If `--no-fail-fast` is *not* used, then this returns an `Err`.\nfn run_unit_tests(\n    ws: &Workspace<'_>,\n    options: &TestOptions,\n    test_args: &[&str],\n    compilation: &Compilation<'_>,\n    test_kind: TestKind,\n) -> Result<Vec<UnitTestError>, CliError> {\n    let gctx = ws.gctx();\n    let cwd = gctx.cwd();\n    let mut errors = Vec::new();\n\n    for UnitOutput {\n        unit,\n        path,\n        script_metas,\n        env,\n    } in compilation.tests.iter()\n    {\n        let (exe_display, mut cmd) = cmd_builds(\n            gctx,\n            cwd,\n            unit,\n            path,\n            script_metas.as_ref(),\n            env,\n            test_args,\n            compilation,\n            \"unittests\",\n        )?;\n\n        if gctx.extra_verbose() {\n            cmd.display_env_vars();\n        }\n\n        gctx.shell()\n            .concise(|shell| shell.status(\"Running\", &exe_display))?;\n        gctx.shell()\n            .verbose(|shell| shell.status(\"Running\", &cmd))?;\n\n        if let Err(e) = cmd.exec() {\n            let code = fail_fast_code(&e);\n            let unit_err = UnitTestError {\n                unit: unit.clone(),\n                kind: test_kind,\n            };\n            report_test_error(ws, test_args, &options.compile_opts, &unit_err, e);\n            errors.push(unit_err);\n            if !options.no_fail_fast {\n                return Err(CliError::code(code));\n            }\n        }\n    }\n    Ok(errors)\n}\n\n/// Runs doc tests.\n///\n/// Returns a `Vec` of tests that failed when `--no-fail-fast` is used.\n/// If `--no-fail-fast` is *not* used, then this returns an `Err`.\nfn run_doc_tests(\n    ws: &Workspace<'_>,\n    options: &TestOptions,\n    test_args: &[&str],\n    compilation: &Compilation<'_>,\n) -> Result<Vec<UnitTestError>, CliError> {\n    let gctx = ws.gctx();\n    let mut errors = Vec::new();\n    let color = gctx.shell().color_choice();\n\n    for doctest_info in &compilation.to_doc_test {\n        let Doctest {\n            args,\n            unstable_opts,\n            unit,\n            linker,\n            script_metas,\n            env,\n        } = doctest_info;\n\n        gctx.shell().status(\"Doc-tests\", unit.target.name())?;\n        let mut p = compilation.rustdoc_process(unit, script_metas.as_ref())?;\n\n        for (var, value) in env {\n            p.env(var, value);\n        }\n\n        let color_arg = match color {\n            ColorChoice::Always => \"always\",\n            ColorChoice::Never => \"never\",\n            ColorChoice::CargoAuto => \"auto\",\n        };\n        p.arg(\"--color\").arg(color_arg);\n\n        p.arg(\"--crate-name\").arg(&unit.target.crate_name());\n        p.arg(\"--test\");\n\n        add_path_args(ws, unit, &mut p);\n        p.arg(\"--test-run-directory\").arg(unit.pkg.root());\n\n        unit.kind.add_target_arg(&mut p);\n\n        if let Some((runtool, runtool_args)) = compilation.target_runner(unit.kind) {\n            p.arg(\"--test-runtool\").arg(runtool);\n            for arg in runtool_args {\n                p.arg(\"--test-runtool-arg\").arg(arg);\n            }\n        }\n        if let Some(linker) = linker {\n            let mut joined = OsString::from(\"linker=\");\n            joined.push(linker);\n            p.arg(\"-C\").arg(joined);\n        }\n\n        if unit.profile.panic != PanicStrategy::Unwind {\n            p.arg(\"-C\").arg(format!(\"panic={}\", unit.profile.panic));\n        }\n\n        for native_dep in compilation.native_dirs.iter() {\n            p.arg(\"-L\").arg(native_dep);\n        }\n\n        for arg in test_args {\n            p.arg(\"--test-args\").arg(arg);\n        }\n\n        if gctx.shell().verbosity() == Verbosity::Quiet {\n            p.arg(\"--test-args\").arg(\"--quiet\");\n        }\n\n        p.args(unit.pkg.manifest().lint_rustflags());\n\n        p.args(args);\n\n        if *unstable_opts {\n            p.arg(\"-Zunstable-options\");\n        }\n\n        if gctx.extra_verbose() {\n            p.display_env_vars();\n        }\n\n        gctx.shell()\n            .verbose(|shell| shell.status(\"Running\", p.to_string()))?;\n\n        if let Err(e) = p.exec() {\n            let code = fail_fast_code(&e);\n            let unit_err = UnitTestError {\n                unit: unit.clone(),\n                kind: TestKind::Doctest,\n            };\n            report_test_error(ws, test_args, &options.compile_opts, &unit_err, e);\n            errors.push(unit_err);\n            if !options.no_fail_fast {\n                return Err(CliError::code(code));\n            }\n        }\n    }\n    Ok(errors)\n}\n\n/// Displays human-readable descriptions of the test executables.\n///\n/// This is used when `cargo test --no-run` is used.\nfn display_no_run_information(\n    ws: &Workspace<'_>,\n    test_args: &[&str],\n    compilation: &Compilation<'_>,\n    exec_type: &str,\n) -> CargoResult<()> {\n    let gctx = ws.gctx();\n    let cwd = gctx.cwd();\n    for UnitOutput {\n        unit,\n        path,\n        script_metas,\n        env,\n    } in compilation.tests.iter()\n    {\n        let (exe_display, cmd) = cmd_builds(\n            gctx,\n            cwd,\n            unit,\n            path,\n            script_metas.as_ref(),\n            env,\n            test_args,\n            compilation,\n            exec_type,\n        )?;\n        gctx.shell()\n            .concise(|shell| shell.status(\"Executable\", &exe_display))?;\n        gctx.shell()\n            .verbose(|shell| shell.status(\"Executable\", &cmd))?;\n    }\n\n    return Ok(());\n}\n\n/// Creates a [`ProcessBuilder`] for executing a single test.\n///\n/// Returns a tuple `(exe_display, process)` where `exe_display` is a string\n/// to display that describes the executable path in a human-readable form.\n/// `process` is the `ProcessBuilder` to use for executing the test.\nfn cmd_builds(\n    gctx: &GlobalContext,\n    cwd: &Path,\n    unit: &Unit,\n    path: &PathBuf,\n    script_metas: Option<&Vec<UnitHash>>,\n    env: &HashMap<String, OsString>,\n    test_args: &[&str],\n    compilation: &Compilation<'_>,\n    exec_type: &str,\n) -> CargoResult<(String, ProcessBuilder)> {\n    let test_path = unit.target.src_path().path().unwrap();\n    let short_test_path = test_path\n        .strip_prefix(unit.pkg.root())\n        .unwrap_or(test_path)\n        .display();\n\n    let exe_display = match unit.target.kind() {\n        TargetKind::Test | TargetKind::Bench => format!(\n            \"{} ({})\",\n            short_test_path,\n            path.strip_prefix(cwd).unwrap_or(path).display()\n        ),\n        _ => format!(\n            \"{} {} ({})\",\n            exec_type,\n            short_test_path,\n            path.strip_prefix(cwd).unwrap_or(path).display()\n        ),\n    };\n\n    let mut cmd = compilation.target_process(path, unit.kind, &unit.pkg, script_metas)?;\n    cmd.args(test_args);\n    if unit.target.harness() && gctx.shell().verbosity() == Verbosity::Quiet {\n        cmd.arg(\"--quiet\");\n    }\n    for (key, val) in env.iter() {\n        cmd.env(key, val);\n    }\n\n    Ok((exe_display, cmd))\n}\n\n/// Returns the error code to use when *not* using `--no-fail-fast`.\n///\n/// Cargo will return the error code from the test process itself. If some\n/// other error happened (like a failure to launch the process), then it will\n/// return a standard 101 error code.\n///\n/// When using `--no-fail-fast`, Cargo always uses the 101 exit code (since\n/// there may not be just one process to report).\nfn fail_fast_code(error: &anyhow::Error) -> i32 {\n    if let Some(proc_err) = error.downcast_ref::<ProcessError>() {\n        if let Some(code) = proc_err.code {\n            return code;\n        }\n    }\n    101\n}\n\n/// Returns the `CliError` when using `--no-fail-fast` and there is at least\n/// one error.\nfn no_fail_fast_err(\n    ws: &Workspace<'_>,\n    opts: &ops::CompileOptions,\n    errors: &[UnitTestError],\n) -> CliResult {\n    // TODO: This could be improved by combining the flags on a single line when feasible.\n    let args: Vec<_> = errors\n        .iter()\n        .map(|unit_err| format!(\"    `{}`\", unit_err.cli_args(ws, opts)))\n        .collect();\n    let message = match errors.len() {\n        0 => return Ok(()),\n        1 => format!(\"1 target failed:\\n{}\", args.join(\"\\n\")),\n        n => format!(\"{n} targets failed:\\n{}\", args.join(\"\\n\")),\n    };\n    Err(anyhow::Error::msg(message).into())\n}\n\n/// Displays an error on the console about a test failure.\nfn report_test_error(\n    ws: &Workspace<'_>,\n    test_args: &[&str],\n    opts: &ops::CompileOptions,\n    unit_err: &UnitTestError,\n    test_error: anyhow::Error,\n) {\n    let which = match unit_err.kind {\n        TestKind::Test => \"test failed\",\n        TestKind::Bench => \"bench failed\",\n        TestKind::Doctest => \"doctest failed\",\n    };\n\n    let mut err = format_err!(\"{}, to rerun pass `{}`\", which, unit_err.cli_args(ws, opts));\n    // Don't show \"process didn't exit successfully\" for simple errors.\n    // libtest exits with 101 for normal errors.\n    let (is_simple, executed) = test_error\n        .downcast_ref::<ProcessError>()\n        .and_then(|proc_err| proc_err.code)\n        .map_or((false, false), |code| (code == 101, true));\n\n    if !is_simple {\n        err = test_error.context(err);\n    }\n\n    crate::display_error(&err, &mut ws.gctx().shell());\n\n    let harness: bool = unit_err.unit.target.harness();\n    let nocapture: bool = test_args.contains(&\"--nocapture\") || test_args.contains(&\"--no-capture\");\n\n    if !is_simple && executed && harness && !nocapture {\n        drop(ws.gctx().shell().note(\n            \"test exited abnormally; to see the full output pass --no-capture to the harness.\",\n        ));\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_uninstall.rs",
    "content": "use crate::core::PackageId;\nuse crate::core::{PackageIdSpec, PackageIdSpecQuery, SourceId};\nuse crate::ops::common_for_install_and_uninstall::*;\nuse crate::sources::PathSource;\nuse crate::util::Filesystem;\nuse crate::util::GlobalContext;\nuse crate::util::errors::CargoResult;\nuse anyhow::bail;\nuse std::collections::BTreeSet;\nuse std::env;\n\npub fn uninstall(\n    root: Option<&str>,\n    specs: Vec<&str>,\n    bins: &[String],\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    if specs.len() > 1 && !bins.is_empty() {\n        bail!(\n            \"A binary can only be associated with a single installed package, specifying multiple specs with --bin is redundant.\"\n        );\n    }\n\n    let root = resolve_root(root, gctx)?;\n    let scheduled_error = if specs.len() == 1 {\n        uninstall_one(&root, specs[0], bins, gctx)?;\n        false\n    } else if specs.is_empty() {\n        uninstall_cwd(&root, bins, gctx)?;\n        false\n    } else {\n        let mut succeeded = vec![];\n        let mut failed = vec![];\n        for spec in specs {\n            let root = root.clone();\n            match uninstall_one(&root, spec, bins, gctx) {\n                Ok(()) => succeeded.push(spec),\n                Err(e) => {\n                    crate::display_error(&e, &mut gctx.shell());\n                    failed.push(spec)\n                }\n            }\n        }\n\n        let mut summary = vec![];\n        if !succeeded.is_empty() {\n            summary.push(format!(\n                \"Successfully uninstalled {}!\",\n                succeeded.join(\", \")\n            ));\n        }\n        if !failed.is_empty() {\n            summary.push(format!(\n                \"Failed to uninstall {} (see error(s) above).\",\n                failed.join(\", \")\n            ));\n        }\n\n        if !succeeded.is_empty() || !failed.is_empty() {\n            gctx.shell().status(\"Summary\", summary.join(\" \"))?;\n        }\n\n        !failed.is_empty()\n    };\n\n    if scheduled_error {\n        bail!(\"some packages failed to uninstall\");\n    }\n\n    Ok(())\n}\n\npub fn uninstall_one(\n    root: &Filesystem,\n    spec: &str,\n    bins: &[String],\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let tracker = InstallTracker::load(gctx, root)?;\n    let all_pkgs = tracker.all_installed_bins().map(|(pkg_id, _set)| *pkg_id);\n    let pkgid = PackageIdSpec::query_str(spec, all_pkgs)?;\n    uninstall_pkgid(root, tracker, pkgid, bins, gctx)\n}\n\nfn uninstall_cwd(root: &Filesystem, bins: &[String], gctx: &GlobalContext) -> CargoResult<()> {\n    let tracker = InstallTracker::load(gctx, root)?;\n    let source_id = SourceId::for_path(gctx.cwd())?;\n    let mut src = path_source(source_id, gctx)?;\n    let pkg = select_pkg(\n        &mut src,\n        None,\n        |path: &mut PathSource<'_>| path.root_package().map(|p| vec![p]),\n        gctx,\n        None,\n    )?;\n    let pkgid = pkg.package_id();\n    uninstall_pkgid(root, tracker, pkgid, bins, gctx)\n}\n\nfn uninstall_pkgid(\n    root: &Filesystem,\n    mut tracker: InstallTracker,\n    pkgid: PackageId,\n    bins: &[String],\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let installed = match tracker.installed_bins(pkgid) {\n        Some(bins) => bins.clone(),\n        None => bail!(\"package `{}` is not installed\", pkgid),\n    };\n\n    let dst = root.join(\"bin\").into_path_unlocked();\n    for bin in &installed {\n        let bin = dst.join(bin);\n        if !bin.exists() {\n            bail!(\n                \"corrupt metadata, `{}` does not exist when it should\",\n                bin.display()\n            )\n        }\n    }\n\n    let bins = bins\n        .iter()\n        .map(|s| {\n            if s.ends_with(env::consts::EXE_SUFFIX) {\n                s.to_string()\n            } else {\n                format!(\"{}{}\", s, env::consts::EXE_SUFFIX)\n            }\n        })\n        .collect::<BTreeSet<_>>();\n\n    for bin in bins.iter() {\n        if !installed.contains(bin) {\n            bail!(\"binary `{}` not installed as part of `{}`\", bin, pkgid)\n        }\n    }\n\n    let to_remove = { if bins.is_empty() { installed } else { bins } };\n\n    for bin in to_remove {\n        let bin_path = dst.join(&bin);\n        gctx.shell().status(\"Removing\", bin_path.display())?;\n        tracker.remove_bin_then_save(pkgid, &bin, &bin_path)?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/ops/cargo_update.rs",
    "content": "use crate::core::Registry as _;\nuse crate::core::dependency::Dependency;\nuse crate::core::registry::PackageRegistry;\nuse crate::core::resolver::features::{CliFeatures, HasDevUnits};\nuse crate::core::shell::Verbosity;\nuse crate::core::{PackageId, PackageIdSpec, PackageIdSpecQuery};\nuse crate::core::{Resolve, SourceId, Workspace};\nuse crate::ops;\nuse crate::sources::IndexSummary;\nuse crate::sources::source::QueryKind;\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::context::GlobalContext;\nuse crate::util::toml_mut::dependency::{MaybeWorkspace, Source};\nuse crate::util::toml_mut::manifest::LocalManifest;\nuse crate::util::toml_mut::upgrade::upgrade_requirement;\nuse crate::util::{CargoResult, VersionExt};\nuse crate::util::{OptVersionReq, style};\nuse anyhow::Context as _;\nuse cargo_util_schemas::core::PartialVersion;\nuse indexmap::{IndexMap, IndexSet};\nuse itertools::Itertools;\nuse semver::{Op, Version, VersionReq};\nuse std::cmp::Ordering;\nuse std::collections::{BTreeMap, HashMap, HashSet};\nuse tracing::{debug, trace};\n\npub type UpgradeMap = HashMap<(String, SourceId), Version>;\n\npub struct UpdateOptions<'a> {\n    pub gctx: &'a GlobalContext,\n    pub to_update: Vec<String>,\n    pub precise: Option<&'a str>,\n    pub recursive: bool,\n    pub dry_run: bool,\n    pub workspace: bool,\n}\n\npub fn generate_lockfile(ws: &Workspace<'_>) -> CargoResult<()> {\n    let mut registry = ws.package_registry()?;\n    let previous_resolve = None;\n    let mut resolve = ops::resolve_with_previous(\n        &mut registry,\n        ws,\n        &CliFeatures::new_all(true),\n        HasDevUnits::Yes,\n        previous_resolve,\n        None,\n        &[],\n        true,\n    )?;\n    ops::write_pkg_lockfile(ws, &mut resolve)?;\n    print_lockfile_changes(ws, previous_resolve, &resolve, &mut registry)?;\n    Ok(())\n}\n\npub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoResult<()> {\n    if opts.recursive && opts.precise.is_some() {\n        anyhow::bail!(\"cannot specify both recursive and precise simultaneously\")\n    }\n\n    if ws.members().count() == 0 {\n        anyhow::bail!(\"you can't generate a lockfile for an empty workspace.\")\n    }\n\n    // Updates often require a lot of modifications to the registry, so ensure\n    // that we're synchronized against other Cargos.\n    let _lock = ws\n        .gctx()\n        .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n\n    let previous_resolve = match ops::load_pkg_lockfile(ws)? {\n        Some(resolve) => resolve,\n        None => {\n            match opts.precise {\n                None => return generate_lockfile(ws),\n\n                // Precise option specified, so calculate a previous_resolve required\n                // by precise package update later.\n                Some(_) => {\n                    let mut registry = ws.package_registry()?;\n                    ops::resolve_with_previous(\n                        &mut registry,\n                        ws,\n                        &CliFeatures::new_all(true),\n                        HasDevUnits::Yes,\n                        None,\n                        None,\n                        &[],\n                        true,\n                    )?\n                }\n            }\n        }\n    };\n    let mut registry = ws.package_registry()?;\n    let mut to_avoid = HashSet::new();\n\n    if opts.to_update.is_empty() {\n        if !opts.workspace {\n            to_avoid.extend(previous_resolve.iter());\n            to_avoid.extend(previous_resolve.unused_patches());\n        }\n    } else {\n        let mut sources = Vec::new();\n        for name in opts.to_update.iter() {\n            let pid = previous_resolve.query(name)?;\n            if opts.recursive {\n                fill_with_deps(&previous_resolve, pid, &mut to_avoid, &mut HashSet::new());\n            } else {\n                to_avoid.insert(pid);\n                sources.push(match opts.precise {\n                    Some(precise) => {\n                        // TODO: see comment in `resolve.rs` as well, but this\n                        //       seems like a pretty hokey reason to single out\n                        //       the registry as well.\n                        if pid.source_id().is_registry() {\n                            pid.source_id().with_precise_registry_version(\n                                pid.name(),\n                                pid.version().clone(),\n                                precise,\n                            )?\n                        } else {\n                            pid.source_id().with_git_precise(Some(precise.to_string()))\n                        }\n                    }\n                    None => pid.source_id().without_precise(),\n                });\n            }\n            if let Ok(unused_id) =\n                PackageIdSpec::query_str(name, previous_resolve.unused_patches().iter().cloned())\n            {\n                to_avoid.insert(unused_id);\n            }\n        }\n\n        // Mirror `--workspace` and never avoid workspace members.\n        // Filtering them out here so the above processes them normally\n        // so their dependencies can be updated as requested\n        to_avoid.retain(|id| {\n            for package in ws.members() {\n                let member_id = package.package_id();\n                // Skip checking the `version` because `previous_resolve` might have a stale\n                // value.\n                // When dealing with workspace members, the other fields should be a\n                // sufficiently unique match.\n                if id.name() == member_id.name() && id.source_id() == member_id.source_id() {\n                    return false;\n                }\n            }\n            true\n        });\n\n        registry.add_sources(sources)?;\n    }\n\n    // Here we place an artificial limitation that all non-registry sources\n    // cannot be locked at more than one revision. This means that if a Git\n    // repository provides more than one package, they must all be updated in\n    // step when any of them are updated.\n    //\n    // TODO: this seems like a hokey reason to single out the registry as being\n    // different.\n    let to_avoid_sources: HashSet<_> = to_avoid\n        .iter()\n        .map(|p| p.source_id())\n        .filter(|s| !s.is_registry())\n        .collect();\n\n    let keep = |p: &PackageId| !to_avoid_sources.contains(&p.source_id()) && !to_avoid.contains(p);\n\n    let mut resolve = ops::resolve_with_previous(\n        &mut registry,\n        ws,\n        &CliFeatures::new_all(true),\n        HasDevUnits::Yes,\n        Some(&previous_resolve),\n        Some(&keep),\n        &[],\n        true,\n    )?;\n\n    print_lockfile_updates(\n        ws,\n        &previous_resolve,\n        &resolve,\n        opts.precise.is_some(),\n        &mut registry,\n    )?;\n    if opts.dry_run {\n        opts.gctx\n            .shell()\n            .warn(\"not updating lockfile due to dry run\")?;\n    } else {\n        ops::write_pkg_lockfile(ws, &mut resolve)?;\n    }\n    Ok(())\n}\n\n/// Prints lockfile change statuses.\n///\n/// This would acquire the package-cache lock, as it may update the index to\n/// show users latest available versions.\npub fn print_lockfile_changes(\n    ws: &Workspace<'_>,\n    previous_resolve: Option<&Resolve>,\n    resolve: &Resolve,\n    registry: &mut PackageRegistry<'_>,\n) -> CargoResult<()> {\n    let _lock = ws\n        .gctx()\n        .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n    if let Some(previous_resolve) = previous_resolve {\n        print_lockfile_sync(ws, previous_resolve, resolve, registry)\n    } else {\n        print_lockfile_generation(ws, resolve, registry)\n    }\n}\npub fn upgrade_manifests(\n    ws: &mut Workspace<'_>,\n    to_update: &Vec<String>,\n) -> CargoResult<UpgradeMap> {\n    let gctx = ws.gctx();\n    let mut upgrades = HashMap::new();\n    let mut upgrade_messages = HashSet::new();\n\n    let to_update = to_update\n        .iter()\n        .map(|spec| {\n            PackageIdSpec::parse(spec)\n                .with_context(|| format!(\"invalid package ID specification: `{spec}`\"))\n        })\n        .collect::<Result<Vec<_>, _>>()?;\n\n    // Updates often require a lot of modifications to the registry, so ensure\n    // that we're synchronized against other Cargos.\n    let _lock = gctx.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n\n    let mut registry = ws.package_registry()?;\n    registry.lock_patches();\n\n    let mut remaining_specs: IndexSet<_> = to_update.iter().cloned().collect();\n\n    for member in ws.members_mut().sorted() {\n        debug!(\"upgrading manifest for `{}`\", member.name());\n\n        *member.manifest_mut().summary_mut() = member\n            .manifest()\n            .summary()\n            .clone()\n            .try_map_dependencies(|d| {\n                upgrade_dependency(\n                    &gctx,\n                    &to_update,\n                    &mut registry,\n                    &mut upgrades,\n                    &mut upgrade_messages,\n                    &mut remaining_specs,\n                    d,\n                )\n            })?;\n    }\n\n    if !remaining_specs.is_empty() {\n        let previous_resolve = ops::load_pkg_lockfile(ws)?;\n        let plural = if remaining_specs.len() == 1 { \"\" } else { \"s\" };\n\n        let mut error_msg = format!(\n            \"package ID specification{plural} did not match any direct dependencies that could be upgraded\"\n        );\n\n        let mut transitive_specs = Vec::new();\n        for spec in &remaining_specs {\n            error_msg.push_str(&format!(\"\\n  {spec}\"));\n\n            // Check if spec is in the lockfile (could be transitive)\n            let in_lockfile = if let Some(ref resolve) = previous_resolve {\n                spec.query(resolve.iter()).is_ok()\n            } else {\n                false\n            };\n\n            // Check if spec matches any direct dependency in the workspace\n            let matches_direct_dep = ws.members().any(|member| {\n                member.dependencies().iter().any(|dep| {\n                    spec.name() == dep.package_name().as_str()\n                        && dep.source_id().is_registry()\n                        && spec.url().map_or(true, |url| url == dep.source_id().url())\n                        && spec\n                            .version()\n                            .map_or(true, |v| dep.version_req().matches(&v))\n                })\n            });\n\n            // Track transitive specs for notes at the end\n            if in_lockfile && !matches_direct_dep {\n                transitive_specs.push(spec);\n            }\n        }\n\n        for spec in transitive_specs {\n            error_msg.push_str(&format!(\n                \"\\nnote: `{spec}` exists as a transitive dependency but those are not available for upgrading through `--breaking`\"\n            ));\n        }\n\n        anyhow::bail!(\"{error_msg}\");\n    }\n\n    Ok(upgrades)\n}\n\nfn upgrade_dependency(\n    gctx: &GlobalContext,\n    to_update: &Vec<PackageIdSpec>,\n    registry: &mut PackageRegistry<'_>,\n    upgrades: &mut UpgradeMap,\n    upgrade_messages: &mut HashSet<String>,\n    remaining_specs: &mut IndexSet<PackageIdSpec>,\n    dependency: Dependency,\n) -> CargoResult<Dependency> {\n    let name = dependency.package_name();\n    let renamed_to = dependency.name_in_toml();\n\n    if name != renamed_to {\n        trace!(\"skipping dependency renamed from `{name}` to `{renamed_to}`\");\n        return Ok(dependency);\n    }\n\n    if !to_update.is_empty()\n        && !to_update.iter().any(|spec| {\n            spec.name() == name.as_str()\n                && dependency.source_id().is_registry()\n                && spec\n                    .url()\n                    .map_or(true, |url| url == dependency.source_id().url())\n                && spec\n                    .version()\n                    .map_or(true, |v| dependency.version_req().matches(&v))\n        })\n    {\n        trace!(\"skipping dependency `{name}` not selected for upgrading\");\n        return Ok(dependency);\n    }\n\n    if !dependency.source_id().is_registry() {\n        trace!(\"skipping non-registry dependency: {name}\");\n        return Ok(dependency);\n    }\n\n    let version_req = dependency.version_req();\n\n    let OptVersionReq::Req(current) = version_req else {\n        trace!(\"skipping dependency `{name}` without a simple version requirement: {version_req}\");\n        return Ok(dependency);\n    };\n\n    let [comparator] = &current.comparators[..] else {\n        trace!(\n            \"skipping dependency `{name}` with multiple version comparators: {:?}\",\n            &current.comparators\n        );\n        return Ok(dependency);\n    };\n\n    if comparator.op != Op::Caret {\n        trace!(\"skipping non-caret dependency `{name}`: {comparator}\");\n        return Ok(dependency);\n    }\n\n    let query =\n        crate::core::dependency::Dependency::parse(name, None, dependency.source_id().clone())?;\n\n    let possibilities = {\n        loop {\n            match registry.query_vec(&query, QueryKind::Exact) {\n                std::task::Poll::Ready(res) => {\n                    break res?;\n                }\n                std::task::Poll::Pending => registry.block_until_ready()?,\n            }\n        }\n    };\n\n    let latest = if !possibilities.is_empty() {\n        possibilities\n            .iter()\n            .map(|s| s.as_summary())\n            .map(|s| s.version())\n            .filter(|v| !v.is_prerelease())\n            .max()\n    } else {\n        None\n    };\n\n    let Some(latest) = latest else {\n        trace!(\"skipping dependency `{name}` without any published versions\");\n        return Ok(dependency);\n    };\n\n    if current.matches(&latest) {\n        trace!(\"skipping dependency `{name}` without a breaking update available\");\n        return Ok(dependency);\n    }\n\n    let Some((new_req_string, _)) = upgrade_requirement(&current.to_string(), latest)? else {\n        trace!(\"skipping dependency `{name}` because the version requirement didn't change\");\n        return Ok(dependency);\n    };\n\n    let upgrade_message = format!(\"{name} {current} -> {new_req_string}\");\n    trace!(upgrade_message);\n\n    if upgrade_messages.insert(upgrade_message.clone()) {\n        gctx.shell()\n            .status_with_color(\"Upgrading\", &upgrade_message, &style::GOOD)?;\n    }\n\n    upgrades.insert((name.to_string(), dependency.source_id()), latest.clone());\n\n    // Remove this spec from remaining_specs since we successfully upgraded it\n    remaining_specs\n        .retain(|spec| !(spec.name() == name.as_str() && dependency.source_id().is_registry()));\n\n    let req = OptVersionReq::Req(VersionReq::parse(&latest.to_string())?);\n    let mut dep = dependency.clone();\n    dep.set_version_req(req);\n    Ok(dep)\n}\n\n/// Update manifests with upgraded versions, and write to disk. Based on\n/// cargo-edit. Returns true if any file has changed.\n///\n/// Some of the checks here are duplicating checks already done in\n/// `upgrade_manifests/upgrade_dependency`. Why? Let's say `upgrade_dependency` has\n/// found that dependency foo was eligible for an upgrade. But foo can occur in\n/// multiple manifest files, and even multiple times in the same manifest file,\n/// and may be pinned, renamed, etc. in some of the instances. So we still need\n/// to check here which dependencies to actually modify. So why not drop the\n/// upgrade map and redo all checks here? Because then we'd have to query the\n/// registries again to find the latest versions.\npub fn write_manifest_upgrades(\n    ws: &Workspace<'_>,\n    upgrades: &UpgradeMap,\n    dry_run: bool,\n) -> CargoResult<bool> {\n    if upgrades.is_empty() {\n        return Ok(false);\n    }\n\n    let mut any_file_has_changed = false;\n\n    let items = std::iter::once((ws.root_manifest(), ws.unstable_features()))\n        .chain(ws.members().map(|member| {\n            (\n                member.manifest_path(),\n                member.manifest().unstable_features(),\n            )\n        }))\n        .collect::<Vec<_>>();\n\n    for (manifest_path, unstable_features) in items {\n        trace!(\"updating TOML manifest at `{manifest_path:?}` with upgraded dependencies\");\n\n        let crate_root = manifest_path\n            .parent()\n            .expect(\"manifest path is absolute\")\n            .to_owned();\n\n        let mut local_manifest = LocalManifest::try_new(&manifest_path)?;\n        let mut manifest_has_changed = false;\n\n        for dep_table in local_manifest.get_dependency_tables_mut() {\n            for (mut dep_key, dep_item) in dep_table.iter_mut() {\n                let dep_key_str = dep_key.get();\n                let dependency = crate::util::toml_mut::dependency::Dependency::from_toml(\n                    ws.gctx(),\n                    ws.root(),\n                    &manifest_path,\n                    unstable_features,\n                    dep_key_str,\n                    dep_item,\n                )?;\n                let name = &dependency.name;\n\n                if let Some(renamed_to) = dependency.rename {\n                    trace!(\"skipping dependency renamed from `{name}` to `{renamed_to}`\");\n                    continue;\n                }\n\n                let Some(current) = dependency.version() else {\n                    trace!(\"skipping dependency without a version: {name}\");\n                    continue;\n                };\n\n                let (MaybeWorkspace::Other(source_id), Some(Source::Registry(source))) =\n                    (dependency.source_id(ws.gctx())?, dependency.source())\n                else {\n                    trace!(\"skipping non-registry dependency: {name}\");\n                    continue;\n                };\n\n                let Some(latest) = upgrades.get(&(name.to_owned(), source_id)) else {\n                    trace!(\"skipping dependency without an upgrade: {name}\");\n                    continue;\n                };\n\n                let Some((new_req_string, new_req)) = upgrade_requirement(current, latest)? else {\n                    trace!(\n                        \"skipping dependency `{name}` because the version requirement didn't change\"\n                    );\n                    continue;\n                };\n\n                let [comparator] = &new_req.comparators[..] else {\n                    trace!(\n                        \"skipping dependency `{}` with multiple version comparators: {:?}\",\n                        name, new_req.comparators\n                    );\n                    continue;\n                };\n\n                if comparator.op != Op::Caret {\n                    trace!(\"skipping non-caret dependency `{}`: {}\", name, comparator);\n                    continue;\n                }\n\n                let mut dep = dependency.clone();\n                let mut source = source.clone();\n                source.version = new_req_string;\n                dep.source = Some(Source::Registry(source));\n\n                trace!(\"upgrading dependency {name}\");\n                dep.update_toml(\n                    ws.gctx(),\n                    ws.root(),\n                    &crate_root,\n                    unstable_features,\n                    &mut dep_key,\n                    dep_item,\n                )?;\n                manifest_has_changed = true;\n                any_file_has_changed = true;\n            }\n        }\n\n        if manifest_has_changed && !dry_run {\n            debug!(\"writing upgraded manifest to {}\", manifest_path.display());\n            local_manifest.write()?;\n        }\n    }\n\n    Ok(any_file_has_changed)\n}\n\nfn print_lockfile_generation(\n    ws: &Workspace<'_>,\n    resolve: &Resolve,\n    registry: &mut PackageRegistry<'_>,\n) -> CargoResult<()> {\n    let mut changes = PackageChange::new(ws, resolve);\n    let num_pkgs: usize = changes\n        .values()\n        .filter(|change| change.kind.is_new() && !change.is_member.unwrap_or(false))\n        .count();\n    if num_pkgs == 0 {\n        // nothing worth reporting\n        return Ok(());\n    }\n    annotate_required_rust_version(ws, resolve, &mut changes);\n\n    status_locking(ws, num_pkgs)?;\n    for change in changes.values() {\n        if change.is_member.unwrap_or(false) {\n            continue;\n        };\n        match change.kind {\n            PackageChangeKind::Added => {\n                let possibilities = if let Some(query) = change.alternatives_query() {\n                    loop {\n                        match registry.query_vec(&query, QueryKind::Exact) {\n                            std::task::Poll::Ready(res) => {\n                                break res?;\n                            }\n                            std::task::Poll::Pending => registry.block_until_ready()?,\n                        }\n                    }\n                } else {\n                    vec![]\n                };\n\n                let required_rust_version = report_required_rust_version(resolve, change);\n                let latest = report_latest(&possibilities, change);\n                let note = required_rust_version.or(latest);\n\n                if let Some(note) = note {\n                    ws.gctx().shell().status_with_color(\n                        change.kind.status(),\n                        format!(\"{change}{note}\"),\n                        &change.kind.style(),\n                    )?;\n                }\n            }\n            PackageChangeKind::Upgraded\n            | PackageChangeKind::Downgraded\n            | PackageChangeKind::Removed\n            | PackageChangeKind::Unchanged => {\n                unreachable!(\"without a previous resolve, everything should be added\")\n            }\n        }\n    }\n\n    Ok(())\n}\n\nfn print_lockfile_sync(\n    ws: &Workspace<'_>,\n    previous_resolve: &Resolve,\n    resolve: &Resolve,\n    registry: &mut PackageRegistry<'_>,\n) -> CargoResult<()> {\n    let mut changes = PackageChange::diff(ws, previous_resolve, resolve);\n    let num_pkgs: usize = changes\n        .values()\n        .filter(|change| change.kind.is_new() && !change.is_member.unwrap_or(false))\n        .count();\n    if num_pkgs == 0 {\n        // nothing worth reporting\n        return Ok(());\n    }\n    annotate_required_rust_version(ws, resolve, &mut changes);\n\n    status_locking(ws, num_pkgs)?;\n    for change in changes.values() {\n        if change.is_member.unwrap_or(false) {\n            continue;\n        };\n        match change.kind {\n            PackageChangeKind::Added\n            | PackageChangeKind::Upgraded\n            | PackageChangeKind::Downgraded => {\n                let possibilities = if let Some(query) = change.alternatives_query() {\n                    loop {\n                        match registry.query_vec(&query, QueryKind::Exact) {\n                            std::task::Poll::Ready(res) => {\n                                break res?;\n                            }\n                            std::task::Poll::Pending => registry.block_until_ready()?,\n                        }\n                    }\n                } else {\n                    vec![]\n                };\n\n                let required_rust_version = report_required_rust_version(resolve, change);\n                let latest = report_latest(&possibilities, change);\n                let note = required_rust_version.or(latest).unwrap_or_default();\n\n                ws.gctx().shell().status_with_color(\n                    change.kind.status(),\n                    format!(\"{change}{note}\"),\n                    &change.kind.style(),\n                )?;\n            }\n            PackageChangeKind::Removed | PackageChangeKind::Unchanged => {}\n        }\n    }\n\n    Ok(())\n}\n\nfn print_lockfile_updates(\n    ws: &Workspace<'_>,\n    previous_resolve: &Resolve,\n    resolve: &Resolve,\n    precise: bool,\n    registry: &mut PackageRegistry<'_>,\n) -> CargoResult<()> {\n    let mut changes = PackageChange::diff(ws, previous_resolve, resolve);\n    let num_pkgs: usize = changes\n        .values()\n        .filter(|change| change.kind.is_new())\n        .count();\n    annotate_required_rust_version(ws, resolve, &mut changes);\n\n    if !precise {\n        status_locking(ws, num_pkgs)?;\n    }\n    let mut unchanged_behind = 0;\n    for change in changes.values() {\n        let possibilities = if let Some(query) = change.alternatives_query() {\n            loop {\n                match registry.query_vec(&query, QueryKind::Exact) {\n                    std::task::Poll::Ready(res) => {\n                        break res?;\n                    }\n                    std::task::Poll::Pending => registry.block_until_ready()?,\n                }\n            }\n        } else {\n            vec![]\n        };\n\n        match change.kind {\n            PackageChangeKind::Added\n            | PackageChangeKind::Upgraded\n            | PackageChangeKind::Downgraded => {\n                let required_rust_version = report_required_rust_version(resolve, change);\n                let latest = report_latest(&possibilities, change);\n                let note = required_rust_version.or(latest).unwrap_or_default();\n\n                ws.gctx().shell().status_with_color(\n                    change.kind.status(),\n                    format!(\"{change}{note}\"),\n                    &change.kind.style(),\n                )?;\n            }\n            PackageChangeKind::Removed => {\n                ws.gctx().shell().status_with_color(\n                    change.kind.status(),\n                    format!(\"{change}\"),\n                    &change.kind.style(),\n                )?;\n            }\n            PackageChangeKind::Unchanged => {\n                let required_rust_version = report_required_rust_version(resolve, change);\n                let latest = report_latest(&possibilities, change);\n                let note = required_rust_version.as_deref().or(latest.as_deref());\n\n                if let Some(note) = note {\n                    if latest.is_some() {\n                        unchanged_behind += 1;\n                    }\n                    if ws.gctx().shell().verbosity() == Verbosity::Verbose {\n                        ws.gctx().shell().status_with_color(\n                            change.kind.status(),\n                            format!(\"{change}{note}\"),\n                            &change.kind.style(),\n                        )?;\n                    }\n                }\n            }\n        }\n    }\n\n    if ws.gctx().shell().verbosity() == Verbosity::Verbose {\n        ws.gctx()\n            .shell()\n            .note(\"to see how you depend on a package, run `cargo tree --invert <dep>@<ver>`\")?;\n    } else {\n        if 0 < unchanged_behind {\n            ws.gctx().shell().note(format!(\n                \"pass `--verbose` to see {unchanged_behind} unchanged dependencies behind latest\"\n            ))?;\n        }\n    }\n\n    Ok(())\n}\n\nfn status_locking(ws: &Workspace<'_>, num_pkgs: usize) -> CargoResult<()> {\n    use std::fmt::Write as _;\n\n    let plural = if num_pkgs == 1 { \"\" } else { \"s\" };\n\n    let mut cfg = String::new();\n    // Don't have a good way to describe `direct_minimal_versions` atm\n    if !ws.gctx().cli_unstable().direct_minimal_versions {\n        write!(&mut cfg, \" to\")?;\n        if ws.gctx().cli_unstable().minimal_versions {\n            write!(&mut cfg, \" earliest\")?;\n        } else {\n            write!(&mut cfg, \" latest\")?;\n        }\n\n        if let Some(rust_version) = required_rust_version(ws) {\n            write!(&mut cfg, \" Rust {rust_version}\")?;\n        }\n        write!(&mut cfg, \" compatible version{plural}\")?;\n        if let Some(publish_time) = ws.resolve_publish_time() {\n            write!(&mut cfg, \" as of {publish_time}\")?;\n        }\n    }\n\n    ws.gctx()\n        .shell()\n        .status(\"Locking\", format!(\"{num_pkgs} package{plural}{cfg}\"))?;\n    Ok(())\n}\n\nfn required_rust_version(ws: &Workspace<'_>) -> Option<PartialVersion> {\n    if !ws.resolve_honors_rust_version() {\n        return None;\n    }\n\n    if let Some(ver) = ws.lowest_rust_version() {\n        Some(ver.to_partial())\n    } else {\n        let rustc = ws.gctx().load_global_rustc(Some(ws)).ok()?;\n        let rustc_version = rustc.version.clone().into();\n        Some(rustc_version)\n    }\n}\n\nfn report_required_rust_version(resolve: &Resolve, change: &PackageChange) -> Option<String> {\n    if change.package_id.source_id().is_path() {\n        return None;\n    }\n    let summary = resolve.summary(change.package_id);\n    let package_rust_version = summary.rust_version()?;\n    let required_rust_version = change.required_rust_version.as_ref()?;\n    if package_rust_version.is_compatible_with(required_rust_version) {\n        return None;\n    }\n\n    let error = style::ERROR;\n    Some(format!(\n        \" {error}(requires Rust {package_rust_version}){error:#}\"\n    ))\n}\n\nfn report_latest(possibilities: &[IndexSummary], change: &PackageChange) -> Option<String> {\n    let package_id = change.package_id;\n    if !package_id.source_id().is_registry() {\n        return None;\n    }\n\n    let version_req = package_id.version().to_caret_req();\n    let required_rust_version = change.required_rust_version.as_ref();\n\n    let compat_ver_compat_msrv_summary = possibilities\n        .iter()\n        .map(|s| s.as_summary())\n        .filter(|s| {\n            if let (Some(summary_rust_version), Some(required_rust_version)) =\n                (s.rust_version(), required_rust_version)\n            {\n                summary_rust_version.is_compatible_with(required_rust_version)\n            } else {\n                true\n            }\n        })\n        .filter(|s| package_id.version() != s.version() && version_req.matches(s.version()))\n        .max_by_key(|s| s.version());\n    if let Some(summary) = compat_ver_compat_msrv_summary {\n        let warn = style::WARN;\n        let version = summary.version();\n        let report = format!(\" {warn}(available: v{version}){warn:#}\");\n        return Some(report);\n    }\n\n    if !change.is_transitive.unwrap_or(true) {\n        let incompat_ver_compat_msrv_summary = possibilities\n            .iter()\n            .map(|s| s.as_summary())\n            .filter(|s| {\n                if let (Some(summary_rust_version), Some(required_rust_version)) =\n                    (s.rust_version(), required_rust_version)\n                {\n                    summary_rust_version.is_compatible_with(required_rust_version)\n                } else {\n                    true\n                }\n            })\n            .filter(|s| is_latest(s.version(), package_id.version()))\n            .max_by_key(|s| s.version());\n        if let Some(summary) = incompat_ver_compat_msrv_summary {\n            let warn = style::WARN;\n            let version = summary.version();\n            let report = format!(\" {warn}(available: v{version}){warn:#}\");\n            return Some(report);\n        }\n    }\n\n    let compat_ver_summary = possibilities\n        .iter()\n        .map(|s| s.as_summary())\n        .filter(|s| package_id.version() != s.version() && version_req.matches(s.version()))\n        .max_by_key(|s| s.version());\n    if let Some(summary) = compat_ver_summary {\n        let msrv_note = summary\n            .rust_version()\n            .map(|rv| format!(\", requires Rust {rv}\"))\n            .unwrap_or_default();\n        let warn = style::NOP;\n        let version = summary.version();\n        let report = format!(\" {warn}(available: v{version}{msrv_note}){warn:#}\");\n        return Some(report);\n    }\n\n    if !change.is_transitive.unwrap_or(true) {\n        let incompat_ver_summary = possibilities\n            .iter()\n            .map(|s| s.as_summary())\n            .filter(|s| is_latest(s.version(), package_id.version()))\n            .max_by_key(|s| s.version());\n        if let Some(summary) = incompat_ver_summary {\n            let msrv_note = summary\n                .rust_version()\n                .map(|rv| format!(\", requires Rust {rv}\"))\n                .unwrap_or_default();\n            let warn = style::NOP;\n            let version = summary.version();\n            let report = format!(\" {warn}(available: v{version}{msrv_note}){warn:#}\");\n            return Some(report);\n        }\n    }\n\n    None\n}\n\nfn is_latest(candidate: &semver::Version, current: &semver::Version) -> bool {\n    current < candidate\n                // Only match pre-release if major.minor.patch are the same\n                && (candidate.pre.is_empty()\n                    || (candidate.major == current.major\n                        && candidate.minor == current.minor\n                        && candidate.patch == current.patch))\n}\n\nfn fill_with_deps<'a>(\n    resolve: &'a Resolve,\n    dep: PackageId,\n    set: &mut HashSet<PackageId>,\n    visited: &mut HashSet<PackageId>,\n) {\n    if !visited.insert(dep) {\n        return;\n    }\n    set.insert(dep);\n    for (dep, _) in resolve.deps_not_replaced(dep) {\n        fill_with_deps(resolve, dep, set, visited);\n    }\n}\n\n#[derive(Clone, Debug)]\nstruct PackageChange {\n    package_id: PackageId,\n    previous_id: Option<PackageId>,\n    kind: PackageChangeKind,\n    is_member: Option<bool>,\n    is_transitive: Option<bool>,\n    required_rust_version: Option<PartialVersion>,\n}\n\nimpl PackageChange {\n    pub fn new(ws: &Workspace<'_>, resolve: &Resolve) -> IndexMap<PackageId, Self> {\n        let diff = PackageDiff::new(resolve);\n        Self::with_diff(diff, ws, resolve)\n    }\n\n    pub fn diff(\n        ws: &Workspace<'_>,\n        previous_resolve: &Resolve,\n        resolve: &Resolve,\n    ) -> IndexMap<PackageId, Self> {\n        let diff = PackageDiff::diff(previous_resolve, resolve);\n        Self::with_diff(diff, ws, resolve)\n    }\n\n    fn with_diff(\n        diff: impl Iterator<Item = PackageDiff>,\n        ws: &Workspace<'_>,\n        resolve: &Resolve,\n    ) -> IndexMap<PackageId, Self> {\n        let member_ids: HashSet<_> = ws.members().map(|p| p.package_id()).collect();\n\n        let mut changes = IndexMap::new();\n        for diff in diff {\n            if let Some((previous_id, package_id)) = diff.change() {\n                // If versions differ only in build metadata, we call it an \"update\"\n                // regardless of whether the build metadata has gone up or down.\n                // This metadata is often stuff like git commit hashes, which are\n                // not meaningfully ordered.\n                let kind = if previous_id.version().cmp_precedence(package_id.version())\n                    == Ordering::Greater\n                {\n                    PackageChangeKind::Downgraded\n                } else {\n                    PackageChangeKind::Upgraded\n                };\n                let is_member = Some(member_ids.contains(&package_id));\n                let is_transitive = Some(true);\n                let change = Self {\n                    package_id,\n                    previous_id: Some(previous_id),\n                    kind,\n                    is_member,\n                    is_transitive,\n                    required_rust_version: None,\n                };\n                changes.insert(change.package_id, change);\n            } else {\n                for package_id in diff.removed {\n                    let kind = PackageChangeKind::Removed;\n                    let is_member = None;\n                    let is_transitive = None;\n                    let change = Self {\n                        package_id,\n                        previous_id: None,\n                        kind,\n                        is_member,\n                        is_transitive,\n                        required_rust_version: None,\n                    };\n                    changes.insert(change.package_id, change);\n                }\n                for package_id in diff.added {\n                    let kind = PackageChangeKind::Added;\n                    let is_member = Some(member_ids.contains(&package_id));\n                    let is_transitive = Some(true);\n                    let change = Self {\n                        package_id,\n                        previous_id: None,\n                        kind,\n                        is_member,\n                        is_transitive,\n                        required_rust_version: None,\n                    };\n                    changes.insert(change.package_id, change);\n                }\n            }\n            for package_id in diff.unchanged {\n                let kind = PackageChangeKind::Unchanged;\n                let is_member = Some(member_ids.contains(&package_id));\n                let is_transitive = Some(true);\n                let change = Self {\n                    package_id,\n                    previous_id: None,\n                    kind,\n                    is_member,\n                    is_transitive,\n                    required_rust_version: None,\n                };\n                changes.insert(change.package_id, change);\n            }\n        }\n\n        for member_id in &member_ids {\n            let Some(change) = changes.get_mut(member_id) else {\n                continue;\n            };\n            change.is_transitive = Some(false);\n            for (direct_dep_id, _) in resolve.deps(*member_id) {\n                let Some(change) = changes.get_mut(&direct_dep_id) else {\n                    continue;\n                };\n                change.is_transitive = Some(false);\n            }\n        }\n\n        changes\n    }\n\n    /// For querying [`PackageRegistry`] for alternative versions to report to the user\n    fn alternatives_query(&self) -> Option<crate::core::dependency::Dependency> {\n        if !self.package_id.source_id().is_registry() {\n            return None;\n        }\n\n        let query = crate::core::dependency::Dependency::parse(\n            self.package_id.name(),\n            None,\n            self.package_id.source_id(),\n        )\n        .expect(\"already a valid dependency\");\n        Some(query)\n    }\n}\n\nimpl std::fmt::Display for PackageChange {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let package_id = self.package_id;\n        if let Some(previous_id) = self.previous_id {\n            if package_id.source_id().is_git() {\n                write!(\n                    f,\n                    \"{previous_id} -> #{}\",\n                    &package_id.source_id().precise_git_fragment().unwrap()[..8],\n                )\n            } else {\n                write!(f, \"{previous_id} -> v{}\", package_id.version())\n            }\n        } else {\n            write!(f, \"{package_id}\")\n        }\n    }\n}\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]\nenum PackageChangeKind {\n    Added,\n    Removed,\n    Upgraded,\n    Downgraded,\n    Unchanged,\n}\n\nimpl PackageChangeKind {\n    pub fn is_new(&self) -> bool {\n        match self {\n            Self::Added | Self::Upgraded | Self::Downgraded => true,\n            Self::Removed | Self::Unchanged => false,\n        }\n    }\n\n    pub fn status(&self) -> &'static str {\n        match self {\n            Self::Added => \"Adding\",\n            Self::Removed => \"Removing\",\n            Self::Upgraded => \"Updating\",\n            Self::Downgraded => \"Downgrading\",\n            Self::Unchanged => \"Unchanged\",\n        }\n    }\n\n    pub fn style(&self) -> anstyle::Style {\n        match self {\n            Self::Added => style::UPDATE_ADDED,\n            Self::Removed => style::UPDATE_REMOVED,\n            Self::Upgraded => style::UPDATE_UPGRADED,\n            Self::Downgraded => style::UPDATE_DOWNGRADED,\n            Self::Unchanged => style::UPDATE_UNCHANGED,\n        }\n    }\n}\n\n/// All resolved versions of a package name within a [`SourceId`]\n#[derive(Default, Clone, Debug)]\npub struct PackageDiff {\n    removed: Vec<PackageId>,\n    added: Vec<PackageId>,\n    unchanged: Vec<PackageId>,\n}\n\nimpl PackageDiff {\n    pub fn new(resolve: &Resolve) -> impl Iterator<Item = Self> {\n        let mut changes = BTreeMap::new();\n        let empty = Self::default();\n        for dep in resolve.iter() {\n            changes\n                .entry(Self::key(dep))\n                .or_insert_with(|| empty.clone())\n                .added\n                .push(dep);\n        }\n\n        changes.into_iter().map(|(_, v)| v)\n    }\n\n    pub fn diff(previous_resolve: &Resolve, resolve: &Resolve) -> impl Iterator<Item = Self> {\n        fn vec_subset(a: &[PackageId], b: &[PackageId]) -> Vec<PackageId> {\n            a.iter().filter(|a| !contains_id(b, a)).cloned().collect()\n        }\n\n        fn vec_intersection(a: &[PackageId], b: &[PackageId]) -> Vec<PackageId> {\n            a.iter().filter(|a| contains_id(b, a)).cloned().collect()\n        }\n\n        // Check if a PackageId is present `b` from `a`.\n        //\n        // Note that this is somewhat more complicated because the equality for source IDs does not\n        // take precise versions into account (e.g., git shas), but we want to take that into\n        // account here.\n        fn contains_id(haystack: &[PackageId], needle: &PackageId) -> bool {\n            let Ok(i) = haystack.binary_search(needle) else {\n                return false;\n            };\n\n            // If we've found `a` in `b`, then we iterate over all instances\n            // (we know `b` is sorted) and see if they all have different\n            // precise versions. If so, then `a` isn't actually in `b` so\n            // we'll let it through.\n            //\n            // Note that we only check this for non-registry sources,\n            // however, as registries contain enough version information in\n            // the package ID to disambiguate.\n            if needle.source_id().is_registry() {\n                return true;\n            }\n            haystack[i..]\n                .iter()\n                .take_while(|b| &needle == b)\n                .any(|b| needle.source_id().has_same_precise_as(b.source_id()))\n        }\n\n        // Map `(package name, package source)` to `(removed versions, added versions)`.\n        let mut changes = BTreeMap::new();\n        let empty = Self::default();\n        for dep in previous_resolve.iter() {\n            changes\n                .entry(Self::key(dep))\n                .or_insert_with(|| empty.clone())\n                .removed\n                .push(dep);\n        }\n        for dep in resolve.iter() {\n            changes\n                .entry(Self::key(dep))\n                .or_insert_with(|| empty.clone())\n                .added\n                .push(dep);\n        }\n\n        for v in changes.values_mut() {\n            let Self {\n                removed: ref mut old,\n                added: ref mut new,\n                unchanged: ref mut other,\n            } = *v;\n            old.sort();\n            new.sort();\n            let removed = vec_subset(old, new);\n            let added = vec_subset(new, old);\n            let unchanged = vec_intersection(new, old);\n            *old = removed;\n            *new = added;\n            *other = unchanged;\n        }\n        debug!(\"{:#?}\", changes);\n\n        changes.into_iter().map(|(_, v)| v)\n    }\n\n    fn key(dep: PackageId) -> (&'static str, SourceId) {\n        (dep.name().as_str(), dep.source_id())\n    }\n\n    /// Guess if a package upgraded/downgraded\n    ///\n    /// All `PackageDiff` knows is that entries were added/removed within [`Resolve`].\n    /// A package could be added or removed because of dependencies from other packages\n    /// which makes it hard to definitively say \"X was upgrade to N\".\n    pub fn change(&self) -> Option<(PackageId, PackageId)> {\n        if self.removed.len() == 1 && self.added.len() == 1 {\n            Some((self.removed[0], self.added[0]))\n        } else {\n            None\n        }\n    }\n}\n\nfn annotate_required_rust_version(\n    ws: &Workspace<'_>,\n    resolve: &Resolve,\n    changes: &mut IndexMap<PackageId, PackageChange>,\n) {\n    let rustc = ws.gctx().load_global_rustc(Some(ws)).ok();\n    let rustc_version: Option<PartialVersion> =\n        rustc.as_ref().map(|rustc| rustc.version.clone().into());\n\n    if ws.resolve_honors_rust_version() {\n        let mut queue: std::collections::VecDeque<_> = ws\n            .members()\n            .map(|p| {\n                (\n                    p.rust_version()\n                        .map(|r| r.to_partial())\n                        .or_else(|| rustc_version.clone()),\n                    p.package_id(),\n                )\n            })\n            .collect();\n        while let Some((required_rust_version, current_id)) = queue.pop_front() {\n            let Some(required_rust_version) = required_rust_version else {\n                continue;\n            };\n            if let Some(change) = changes.get_mut(&current_id) {\n                if let Some(existing) = change.required_rust_version.as_ref() {\n                    if *existing <= required_rust_version {\n                        // Stop early; we already walked down this path with a better match\n                        continue;\n                    }\n                }\n                change.required_rust_version = Some(required_rust_version.clone());\n            }\n            queue.extend(\n                resolve\n                    .deps(current_id)\n                    .map(|(dep, _)| (Some(required_rust_version.clone()), dep)),\n            );\n        }\n    } else {\n        for change in changes.values_mut() {\n            change.required_rust_version = rustc_version.clone();\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/common_for_install_and_uninstall.rs",
    "content": "use std::collections::{BTreeMap, BTreeSet, btree_map};\nuse std::env;\nuse std::io::SeekFrom;\nuse std::io::prelude::*;\nuse std::path::{Path, PathBuf};\nuse std::rc::Rc;\nuse std::task::Poll;\n\nuse annotate_snippets::Level;\nuse anyhow::{Context as _, bail, format_err};\nuse cargo_util::paths;\nuse cargo_util_schemas::core::PartialVersion;\nuse ops::FilterRule;\nuse serde::{Deserialize, Serialize};\n\nuse crate::core::compiler::{DirtyReason, Freshness};\nuse crate::core::{Dependency, FeatureValue, Package, PackageId, SourceId};\nuse crate::core::{PackageSet, Target};\nuse crate::ops::{self, CompileFilter, CompileOptions};\nuse crate::sources::PathSource;\nuse crate::sources::source::Source;\nuse crate::sources::source::{QueryKind, SourceMap};\nuse crate::util::GlobalContext;\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::context::{ConfigRelativePath, Definition};\nuse crate::util::errors::CargoResult;\nuse crate::util::{FileLock, Filesystem};\n\n/// On-disk tracking for which package installed which binary.\n///\n/// v1 is an older style, v2 is a new style that tracks more information, and\n/// is both backwards and forwards compatible. Cargo keeps both files in sync,\n/// updating both v1 and v2 at the same time. Additionally, if it detects\n/// changes in v1 that are not in v2 (such as when an older version of Cargo\n/// is used), it will automatically propagate those changes to v2.\n///\n/// This maintains a filesystem lock, preventing other instances of Cargo from\n/// modifying at the same time. Drop the value to unlock.\n///\n/// It is intended that v1 should be retained for a while during a longish\n/// transition period, and then v1 can be removed.\npub struct InstallTracker {\n    v1: CrateListingV1,\n    v2: CrateListingV2,\n    v1_lock: FileLock,\n    v2_lock: FileLock,\n}\n\n/// Tracking information for the set of installed packages.\n#[derive(Default, Deserialize, Serialize)]\nstruct CrateListingV2 {\n    /// Map of every installed package.\n    installs: BTreeMap<PackageId, InstallInfo>,\n    /// Forwards compatibility. Unknown keys from future versions of Cargo\n    /// will be stored here and retained when the file is saved.\n    #[serde(flatten)]\n    other: BTreeMap<String, serde_json::Value>,\n}\n\n/// Tracking information for the installation of a single package.\n///\n/// This tracks the settings that were used when the package was installed.\n/// Future attempts to install the same package will check these settings to\n/// determine if it needs to be rebuilt/reinstalled. If nothing has changed,\n/// then Cargo will inform the user that it is \"up to date\".\n///\n/// This is only used for the v2 format.\n#[derive(Debug, Deserialize, Serialize)]\nstruct InstallInfo {\n    /// Version requested via `--version`.\n    /// None if `--version` not specified. Currently not used, possibly may be\n    /// used in the future.\n    version_req: Option<String>,\n    /// Set of binary names installed.\n    bins: BTreeSet<String>,\n    /// Set of features explicitly enabled.\n    features: BTreeSet<String>,\n    all_features: bool,\n    no_default_features: bool,\n    /// Either \"debug\" or \"release\".\n    profile: String,\n    /// The installation target.\n    /// Either the host or the value specified in `--target`.\n    /// None if unknown (when loading from v1).\n    target: Option<String>,\n    /// Output of `rustc -V`.\n    /// None if unknown (when loading from v1).\n    /// Currently not used, possibly may be used in the future.\n    rustc: Option<String>,\n    /// Forwards compatibility.\n    #[serde(flatten)]\n    other: BTreeMap<String, serde_json::Value>,\n}\n\n/// Tracking information for the set of installed packages.\n#[derive(Default, Deserialize, Serialize)]\npub struct CrateListingV1 {\n    /// Map of installed package id to the set of binary names for that package.\n    v1: BTreeMap<PackageId, BTreeSet<String>>,\n}\n\nimpl InstallTracker {\n    /// Create an `InstallTracker` from information on disk.\n    pub fn load(gctx: &GlobalContext, root: &Filesystem) -> CargoResult<InstallTracker> {\n        let v1_lock =\n            root.open_rw_exclusive_create(Path::new(\".crates.toml\"), gctx, \"crate metadata\")?;\n        let v2_lock =\n            root.open_rw_exclusive_create(Path::new(\".crates2.json\"), gctx, \"crate metadata\")?;\n\n        let v1 = (|| -> CargoResult<_> {\n            let mut contents = String::new();\n            v1_lock.file().read_to_string(&mut contents)?;\n            if contents.is_empty() {\n                Ok(CrateListingV1::default())\n            } else {\n                Ok(toml::from_str(&contents).context(\"invalid TOML found for metadata\")?)\n            }\n        })()\n        .with_context(|| {\n            format!(\n                \"failed to parse crate metadata at `{}`\",\n                v1_lock.path().to_string_lossy()\n            )\n        })?;\n\n        let v2 = (|| -> CargoResult<_> {\n            let mut contents = String::new();\n            v2_lock.file().read_to_string(&mut contents)?;\n            let mut v2 = if contents.is_empty() {\n                CrateListingV2::default()\n            } else {\n                serde_json::from_str(&contents).context(\"invalid JSON found for metadata\")?\n            };\n            v2.sync_v1(&v1);\n            Ok(v2)\n        })()\n        .with_context(|| {\n            format!(\n                \"failed to parse crate metadata at `{}`\",\n                v2_lock.path().to_string_lossy()\n            )\n        })?;\n\n        Ok(InstallTracker {\n            v1,\n            v2,\n            v1_lock,\n            v2_lock,\n        })\n    }\n\n    /// Checks if the given package should be built, and checks if executables\n    /// already exist in the destination directory.\n    ///\n    /// Returns a tuple `(freshness, map)`. `freshness` indicates if the\n    /// package should be built (`Dirty`) or if it is already up-to-date\n    /// (`Fresh`) and should be skipped. The map maps binary names to the\n    /// `PackageId` that installed it (which is `None` if not known).\n    ///\n    /// If there are no duplicates, then it will be considered `Dirty` (i.e.,\n    /// it is OK to build/install).\n    ///\n    /// `force=true` will always be considered `Dirty` (i.e., it will always\n    /// be rebuilt/reinstalled).\n    ///\n    /// Returns an error if there is a duplicate and `--force` is not used.\n    pub fn check_upgrade(\n        &self,\n        dst: &Path,\n        pkg: &Package,\n        force: bool,\n        opts: &CompileOptions,\n        target: &str,\n        _rustc: &str,\n    ) -> CargoResult<(Freshness, BTreeMap<String, Option<PackageId>>)> {\n        let exes = exe_names(pkg, &opts.filter);\n        // Check if any tracked exe's are already installed.\n        let duplicates = self.find_duplicates(dst, &exes);\n        if force || duplicates.is_empty() {\n            return Ok((Freshness::Dirty(DirtyReason::Forced), duplicates));\n        }\n        // Check if all duplicates come from packages of the same name. If\n        // there are duplicates from other packages, then --force will be\n        // required.\n        //\n        // There may be multiple matching duplicates if different versions of\n        // the same package installed different binaries.\n        //\n        // This does not check the source_id in order to allow the user to\n        // switch between different sources. For example, installing from git,\n        // and then switching to the official crates.io release or vice-versa.\n        // If the source_id were included, then the user would get possibly\n        // confusing errors like \"package `foo 1.0.0` is already installed\"\n        // and the change of source may not be obvious why it fails.\n        let matching_duplicates: Vec<PackageId> = duplicates\n            .values()\n            .filter_map(|v| match v {\n                Some(dupe_pkg_id) if dupe_pkg_id.name() == pkg.name() => Some(*dupe_pkg_id),\n                _ => None,\n            })\n            .collect();\n\n        // If both sets are the same length, that means all duplicates come\n        // from packages with the same name.\n        if matching_duplicates.len() == duplicates.len() {\n            // Determine if it is dirty or fresh.\n            let source_id = pkg.package_id().source_id();\n            if source_id.is_path() {\n                // `cargo install --path ...` is always rebuilt.\n                return Ok((Freshness::Dirty(DirtyReason::Forced), duplicates));\n            }\n            let is_up_to_date = |dupe_pkg_id| {\n                let info = self\n                    .v2\n                    .installs\n                    .get(dupe_pkg_id)\n                    .expect(\"dupes must be in sync\");\n                let precise_equal = if source_id.is_git() {\n                    // Git sources must have the exact same hash to be\n                    // considered \"fresh\".\n                    dupe_pkg_id.source_id().has_same_precise_as(source_id)\n                } else {\n                    true\n                };\n\n                dupe_pkg_id.version() == pkg.version()\n                    && dupe_pkg_id.source_id() == source_id\n                    && precise_equal\n                    && info.is_up_to_date(opts, target, &exes)\n            };\n            if matching_duplicates.iter().all(is_up_to_date) {\n                Ok((Freshness::Fresh, duplicates))\n            } else {\n                Ok((Freshness::Dirty(DirtyReason::Forced), duplicates))\n            }\n        } else {\n            // Format the error message.\n            let mut msg = String::new();\n            for (bin, p) in duplicates.iter() {\n                msg.push_str(&format!(\"binary `{}` already exists in destination\", bin));\n                if let Some(p) = p.as_ref() {\n                    msg.push_str(&format!(\" as part of `{}`\\n\", p));\n                } else {\n                    msg.push('\\n');\n                }\n            }\n            msg.push_str(\"Add --force to overwrite\");\n            bail!(\"{}\", msg);\n        }\n    }\n\n    /// Check if any executables are already installed.\n    ///\n    /// Returns a map of duplicates, the key is the executable name and the\n    /// value is the `PackageId` that is already installed. The `PackageId` is\n    /// None if it is an untracked executable.\n    fn find_duplicates(\n        &self,\n        dst: &Path,\n        exes: &BTreeSet<String>,\n    ) -> BTreeMap<String, Option<PackageId>> {\n        exes.iter()\n            .filter_map(|name| {\n                if !dst.join(&name).exists() {\n                    None\n                } else {\n                    let p = self.v2.package_for_bin(name);\n                    Some((name.clone(), p))\n                }\n            })\n            .collect()\n    }\n\n    /// Mark that a package was installed.\n    pub fn mark_installed(\n        &mut self,\n        package: &Package,\n        bins: &BTreeSet<String>,\n        version_req: Option<String>,\n        opts: &CompileOptions,\n        target: &str,\n        rustc: &str,\n    ) {\n        self.v2\n            .mark_installed(package, bins, version_req, opts, target, rustc);\n        self.v1.mark_installed(package, bins);\n    }\n\n    /// Save tracking information to disk.\n    pub fn save(&self) -> CargoResult<()> {\n        self.v1.save(&self.v1_lock).with_context(|| {\n            format!(\n                \"failed to write crate metadata at `{}`\",\n                self.v1_lock.path().to_string_lossy()\n            )\n        })?;\n\n        self.v2.save(&self.v2_lock).with_context(|| {\n            format!(\n                \"failed to write crate metadata at `{}`\",\n                self.v2_lock.path().to_string_lossy()\n            )\n        })?;\n        Ok(())\n    }\n\n    /// Iterator of all installed binaries.\n    /// Items are `(pkg_id, bins)` where `bins` is the set of binaries that\n    /// package installed.\n    pub fn all_installed_bins(&self) -> impl Iterator<Item = (&PackageId, &BTreeSet<String>)> {\n        self.v1.v1.iter()\n    }\n\n    /// Set of binaries installed by a particular package.\n    /// Returns None if the package is not installed.\n    pub fn installed_bins(&self, pkg_id: PackageId) -> Option<&BTreeSet<String>> {\n        self.v1.v1.get(&pkg_id)\n    }\n\n    /// Remove a package from the tracker.\n    pub fn remove(&mut self, pkg_id: PackageId, bins: &BTreeSet<String>) {\n        self.v1.remove(pkg_id, bins);\n        self.v2.remove(pkg_id, bins);\n    }\n\n    /// Remove a bin after it successfully had been removed in disk and then save the tracker at last.\n    pub fn remove_bin_then_save(\n        &mut self,\n        pkg_id: PackageId,\n        bin: &str,\n        bin_path: &PathBuf,\n    ) -> CargoResult<()> {\n        paths::remove_file(bin_path)?;\n        self.v1.remove_bin(pkg_id, bin);\n        self.v2.remove_bin(pkg_id, bin);\n        self.save()?;\n        Ok(())\n    }\n}\n\nimpl CrateListingV1 {\n    fn mark_installed(&mut self, pkg: &Package, bins: &BTreeSet<String>) {\n        // Remove bins from any other packages.\n        for other_bins in self.v1.values_mut() {\n            for bin in bins {\n                other_bins.remove(bin);\n            }\n        }\n        // Remove entries where `bins` is empty.\n        let to_remove = self\n            .v1\n            .iter()\n            .filter_map(|(&p, set)| if set.is_empty() { Some(p) } else { None })\n            .collect::<Vec<_>>();\n        for p in to_remove.iter() {\n            self.v1.remove(p);\n        }\n        // Add these bins.\n        self.v1\n            .entry(pkg.package_id())\n            .or_insert_with(BTreeSet::new)\n            .append(&mut bins.clone());\n    }\n\n    fn remove(&mut self, pkg_id: PackageId, bins: &BTreeSet<String>) {\n        let mut installed = match self.v1.entry(pkg_id) {\n            btree_map::Entry::Occupied(e) => e,\n            btree_map::Entry::Vacant(..) => panic!(\"v1 unexpected missing `{}`\", pkg_id),\n        };\n\n        for bin in bins {\n            installed.get_mut().remove(bin);\n        }\n        if installed.get().is_empty() {\n            installed.remove();\n        }\n    }\n\n    fn remove_bin(&mut self, pkg_id: PackageId, bin: &str) {\n        let mut installed = match self.v1.entry(pkg_id) {\n            btree_map::Entry::Occupied(e) => e,\n            btree_map::Entry::Vacant(..) => panic!(\"v1 unexpected missing `{}`\", pkg_id),\n        };\n        installed.get_mut().remove(bin);\n        if installed.get().is_empty() {\n            installed.remove();\n        }\n    }\n\n    fn save(&self, lock: &FileLock) -> CargoResult<()> {\n        let mut file = lock.file();\n        file.seek(SeekFrom::Start(0))?;\n        file.set_len(0)?;\n        let data = toml::to_string_pretty(self)?;\n        file.write_all(data.as_bytes())?;\n        Ok(())\n    }\n}\n\nimpl CrateListingV2 {\n    /// Incorporate any changes from v1 into self.\n    /// This handles the initial upgrade to v2, *and* handles the case\n    /// where v2 is in use, and a v1 update is made, then v2 is used again.\n    /// i.e., `cargo +new install foo ; cargo +old install bar ; cargo +new install bar`\n    /// For now, v1 is the source of truth, so its values are trusted over v2.\n    fn sync_v1(&mut self, v1: &CrateListingV1) {\n        // Make the `bins` entries the same.\n        for (pkg_id, bins) in &v1.v1 {\n            self.installs\n                .entry(*pkg_id)\n                .and_modify(|info| info.bins = bins.clone())\n                .or_insert_with(|| InstallInfo::from_v1(bins));\n        }\n        // Remove any packages that aren't present in v1.\n        let to_remove: Vec<_> = self\n            .installs\n            .keys()\n            .filter(|pkg_id| !v1.v1.contains_key(pkg_id))\n            .cloned()\n            .collect();\n        for pkg_id in to_remove {\n            self.installs.remove(&pkg_id);\n        }\n    }\n\n    fn package_for_bin(&self, bin_name: &str) -> Option<PackageId> {\n        self.installs\n            .iter()\n            .find(|(_, info)| info.bins.contains(bin_name))\n            .map(|(pkg_id, _)| *pkg_id)\n    }\n\n    fn mark_installed(\n        &mut self,\n        pkg: &Package,\n        bins: &BTreeSet<String>,\n        version_req: Option<String>,\n        opts: &CompileOptions,\n        target: &str,\n        rustc: &str,\n    ) {\n        // Remove bins from any other packages.\n        for info in &mut self.installs.values_mut() {\n            for bin in bins {\n                info.bins.remove(bin);\n            }\n        }\n        // Remove entries where `bins` is empty.\n        let to_remove = self\n            .installs\n            .iter()\n            .filter_map(|(&p, info)| if info.bins.is_empty() { Some(p) } else { None })\n            .collect::<Vec<_>>();\n        for p in to_remove.iter() {\n            self.installs.remove(p);\n        }\n        // Add these bins.\n        if let Some(info) = self.installs.get_mut(&pkg.package_id()) {\n            info.bins.append(&mut bins.clone());\n            info.version_req = version_req;\n            info.features = feature_set(&opts.cli_features.features);\n            info.all_features = opts.cli_features.all_features;\n            info.no_default_features = !opts.cli_features.uses_default_features;\n            info.profile = opts.build_config.requested_profile.to_string();\n            info.target = Some(target.to_string());\n            info.rustc = Some(rustc.to_string());\n        } else {\n            self.installs.insert(\n                pkg.package_id(),\n                InstallInfo {\n                    version_req,\n                    bins: bins.clone(),\n                    features: feature_set(&opts.cli_features.features),\n                    all_features: opts.cli_features.all_features,\n                    no_default_features: !opts.cli_features.uses_default_features,\n                    profile: opts.build_config.requested_profile.to_string(),\n                    target: Some(target.to_string()),\n                    rustc: Some(rustc.to_string()),\n                    other: BTreeMap::new(),\n                },\n            );\n        }\n    }\n\n    fn remove(&mut self, pkg_id: PackageId, bins: &BTreeSet<String>) {\n        let mut info_entry = match self.installs.entry(pkg_id) {\n            btree_map::Entry::Occupied(e) => e,\n            btree_map::Entry::Vacant(..) => panic!(\"v2 unexpected missing `{}`\", pkg_id),\n        };\n\n        for bin in bins {\n            info_entry.get_mut().bins.remove(bin);\n        }\n        if info_entry.get().bins.is_empty() {\n            info_entry.remove();\n        }\n    }\n\n    fn remove_bin(&mut self, pkg_id: PackageId, bin: &str) {\n        let mut info_entry = match self.installs.entry(pkg_id) {\n            btree_map::Entry::Occupied(e) => e,\n            btree_map::Entry::Vacant(..) => panic!(\"v1 unexpected missing `{}`\", pkg_id),\n        };\n        info_entry.get_mut().bins.remove(bin);\n        if info_entry.get().bins.is_empty() {\n            info_entry.remove();\n        }\n    }\n\n    fn save(&self, lock: &FileLock) -> CargoResult<()> {\n        let mut file = lock.file();\n        file.seek(SeekFrom::Start(0))?;\n        file.set_len(0)?;\n        let data = serde_json::to_string(self)?;\n        file.write_all(data.as_bytes())?;\n        Ok(())\n    }\n}\n\nimpl InstallInfo {\n    fn from_v1(set: &BTreeSet<String>) -> InstallInfo {\n        InstallInfo {\n            version_req: None,\n            bins: set.clone(),\n            features: BTreeSet::new(),\n            all_features: false,\n            no_default_features: false,\n            profile: \"release\".to_string(),\n            target: None,\n            rustc: None,\n            other: BTreeMap::new(),\n        }\n    }\n\n    /// Determine if this installation is \"up to date\", or if it needs to be reinstalled.\n    ///\n    /// This does not do Package/Source/Version checking.\n    fn is_up_to_date(&self, opts: &CompileOptions, target: &str, exes: &BTreeSet<String>) -> bool {\n        self.features == feature_set(&opts.cli_features.features)\n            && self.all_features == opts.cli_features.all_features\n            && self.no_default_features != opts.cli_features.uses_default_features\n            && self.profile.as_str() == opts.build_config.requested_profile.as_str()\n            && (self.target.is_none() || self.target.as_deref() == Some(target))\n            && &self.bins == exes\n    }\n}\n\n/// Determines the root directory where installation is done.\npub fn resolve_root(flag: Option<&str>, gctx: &GlobalContext) -> CargoResult<Filesystem> {\n    let config_root = match gctx.get::<Option<ConfigRelativePath>>(\"install.root\")? {\n        Some(p) => {\n            let resolved = p.resolve_program(gctx);\n            if resolved.is_relative() {\n                let definition = p.value().definition.clone();\n                if matches!(definition, Definition::Path(_)) {\n                    let suggested = format!(\"{}/\", resolved.display());\n                    let notes = [\n                        Level::NOTE.message(\"a future version of Cargo will treat it as relative to the configuration directory\"),\n                        Level::HELP.message(format!(\"add a trailing slash (`{}`) to adopt the correct behavior and silence this warning\", suggested)),\n                        Level::NOTE.message(\"see more at https://doc.rust-lang.org/cargo/reference/config.html#config-relative-paths\"),\n                    ];\n                    gctx.shell().print_report(\n                        &[Level::WARNING\n                            .secondary_title(format!(\n                                \"the `install.root` value `{}` defined in {} without a trailing slash is deprecated\",\n                                resolved.display(),\n                                definition\n                            ))\n                            .elements(notes)],\n                        false,\n                    )?;\n                }\n            }\n            Some(resolved)\n        }\n        None => None,\n    };\n\n    Ok(flag\n        .map(PathBuf::from)\n        .or_else(|| gctx.get_env_os(\"CARGO_INSTALL_ROOT\").map(PathBuf::from))\n        .or_else(|| config_root)\n        .map(Filesystem::new)\n        .unwrap_or_else(|| gctx.home().clone()))\n}\n\n/// Determines the `PathSource` from a `SourceId`.\npub fn path_source(source_id: SourceId, gctx: &GlobalContext) -> CargoResult<PathSource<'_>> {\n    let path = source_id\n        .url()\n        .to_file_path()\n        .map_err(|()| format_err!(\"path sources must have a valid path\"))?;\n    Ok(PathSource::new(&path, source_id, gctx))\n}\n\n/// Gets a Package based on command-line requirements.\npub fn select_dep_pkg(\n    source: &mut dyn Source,\n    dep: Dependency,\n    gctx: &GlobalContext,\n    needs_update: bool,\n    current_rust_version: Option<&PartialVersion>,\n) -> CargoResult<Package> {\n    // This operation may involve updating some sources or making a few queries\n    // which may involve frobbing caches, as a result make sure we synchronize\n    // with other global Cargos\n    let _lock = gctx.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n\n    if needs_update {\n        source.invalidate_cache();\n    }\n\n    let deps = loop {\n        match source.query_vec(&dep, QueryKind::Exact)? {\n            Poll::Ready(deps) => break deps,\n            Poll::Pending => source.block_until_ready()?,\n        }\n    };\n    match deps\n        .iter()\n        .map(|s| s.as_summary())\n        .max_by_key(|p| p.package_id())\n    {\n        Some(summary) => {\n            if let (Some(current), Some(msrv)) = (current_rust_version, summary.rust_version()) {\n                if !msrv.is_compatible_with(current) {\n                    let name = summary.name();\n                    let ver = summary.version();\n                    let extra = if dep.source_id().is_registry() {\n                        // Match any version, not just the selected\n                        let msrv_dep =\n                            Dependency::parse(dep.package_name(), None, dep.source_id())?;\n                        let msrv_deps = loop {\n                            match source.query_vec(&msrv_dep, QueryKind::Exact)? {\n                                Poll::Ready(deps) => break deps,\n                                Poll::Pending => source.block_until_ready()?,\n                            }\n                        };\n                        if let Some(alt) = msrv_deps\n                            .iter()\n                            .map(|s| s.as_summary())\n                            .filter(|summary| {\n                                summary\n                                    .rust_version()\n                                    .map(|msrv| msrv.is_compatible_with(current))\n                                    .unwrap_or(true)\n                            })\n                            .max_by_key(|s| s.package_id())\n                        {\n                            if let Some(rust_version) = alt.rust_version() {\n                                format!(\n                                    \"\\n`{name} {}` supports rustc {rust_version}\",\n                                    alt.version()\n                                )\n                            } else {\n                                format!(\n                                    \"\\n`{name} {}` has an unspecified minimum rustc version\",\n                                    alt.version()\n                                )\n                            }\n                        } else {\n                            String::new()\n                        }\n                    } else {\n                        String::new()\n                    };\n                    bail!(\n                        \"\\\ncannot install package `{name} {ver}`, it requires rustc {msrv} or newer, while the currently active rustc version is {current}{extra}\"\n                    )\n                }\n            }\n            // Download the package immediately.\n            let mut sources = SourceMap::new();\n            sources.insert(Box::new(source));\n            let pkg_set = PackageSet::new(&[summary.package_id()], sources, gctx)?;\n            Ok(pkg_set.get_one(summary.package_id())?.clone())\n        }\n        None => {\n            let is_yanked: bool = if dep.version_req().is_exact() {\n                let version: String = dep.version_req().to_string();\n                if let Ok(pkg_id) =\n                    PackageId::try_new(dep.package_name(), &version[1..], source.source_id())\n                {\n                    source.invalidate_cache();\n                    loop {\n                        match source.is_yanked(pkg_id) {\n                            Poll::Ready(Ok(is_yanked)) => break is_yanked,\n                            Poll::Ready(Err(_)) => break false,\n                            Poll::Pending => source.block_until_ready()?,\n                        }\n                    }\n                } else {\n                    false\n                }\n            } else {\n                false\n            };\n            if is_yanked {\n                bail!(\n                    \"cannot install package `{}`, it has been yanked from {}\",\n                    dep.package_name(),\n                    source.source_id()\n                )\n            } else {\n                bail!(\n                    \"could not find `{}` in {} with version `{}`\",\n                    dep.package_name(),\n                    source.source_id(),\n                    dep.version_req(),\n                )\n            }\n        }\n    }\n}\n\npub fn select_pkg<T, F>(\n    source: &mut T,\n    dep: Option<Dependency>,\n    mut list_all: F,\n    gctx: &GlobalContext,\n    current_rust_version: Option<&PartialVersion>,\n) -> CargoResult<Package>\nwhere\n    T: Source,\n    F: FnMut(&mut T) -> CargoResult<Vec<Package>>,\n{\n    // This operation may involve updating some sources or making a few queries\n    // which may involve frobbing caches, as a result make sure we synchronize\n    // with other global Cargos\n    let _lock = gctx.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n\n    source.invalidate_cache();\n\n    return if let Some(dep) = dep {\n        select_dep_pkg(source, dep, gctx, false, current_rust_version)\n    } else {\n        let candidates = list_all(source)?;\n        let binaries = candidates\n            .iter()\n            .filter(|cand| cand.targets().iter().filter(|t| t.is_bin()).count() > 0);\n        let examples = candidates\n            .iter()\n            .filter(|cand| cand.targets().iter().filter(|t| t.is_example()).count() > 0);\n        let git_url = source.source_id().url().to_string();\n        let pkg = match one(binaries, |v| multi_err(\"binaries\", &git_url, v))? {\n            Some(p) => p,\n            None => match one(examples, |v| multi_err(\"examples\", &git_url, v))? {\n                Some(p) => p,\n                None => bail!(\n                    \"no packages found with binaries or \\\n                         examples\"\n                ),\n            },\n        };\n        Ok(pkg.clone())\n    };\n\n    fn multi_err(kind: &str, git_url: &str, mut pkgs: Vec<&Package>) -> String {\n        pkgs.sort_unstable_by_key(|a| a.name());\n        let first_pkg = pkgs[0];\n        format!(\n            \"multiple packages with {} found: {}. When installing a git repository, \\\n            cargo will always search the entire repo for any Cargo.toml.\\n\\\n            Please specify a package, e.g. `cargo install --git {} {}`.\",\n            kind,\n            pkgs.iter()\n                .map(|p| p.name().as_str())\n                .collect::<Vec<_>>()\n                .join(\", \"),\n            git_url,\n            first_pkg.name()\n        )\n    }\n}\n\n/// Get one element from the iterator.\n/// Returns None if none left.\n/// Returns error if there is more than one item in the iterator.\nfn one<I, F>(mut i: I, f: F) -> CargoResult<Option<I::Item>>\nwhere\n    I: Iterator,\n    F: FnOnce(Vec<I::Item>) -> String,\n{\n    match (i.next(), i.next()) {\n        (Some(i1), Some(i2)) => {\n            let mut v = vec![i1, i2];\n            v.extend(i);\n            Err(format_err!(\"{}\", f(v)))\n        }\n        (Some(i), None) => Ok(Some(i)),\n        (None, _) => Ok(None),\n    }\n}\n\n/// Helper to convert features to a `BTreeSet`.\nfn feature_set(features: &Rc<BTreeSet<FeatureValue>>) -> BTreeSet<String> {\n    features.iter().map(|s| s.to_string()).collect()\n}\n\n/// Helper to get the executable names from a filter.\npub fn exe_names(pkg: &Package, filter: &ops::CompileFilter) -> BTreeSet<String> {\n    let to_exe = |name| format!(\"{}{}\", name, env::consts::EXE_SUFFIX);\n    match filter {\n        CompileFilter::Default { .. } => pkg\n            .targets()\n            .iter()\n            .filter(|t| t.is_bin())\n            .map(|t| to_exe(t.name()))\n            .collect(),\n        CompileFilter::Only {\n            all_targets: true, ..\n        } => pkg\n            .targets()\n            .iter()\n            .filter(|target| target.is_executable())\n            .map(|target| to_exe(target.name()))\n            .collect(),\n        CompileFilter::Only { bins, examples, .. } => {\n            let collect = |rule: &_, f: fn(&Target) -> _| match rule {\n                FilterRule::All => pkg\n                    .targets()\n                    .iter()\n                    .filter(|t| f(t))\n                    .map(|t| t.name().into())\n                    .collect(),\n                FilterRule::Just(targets) => targets.clone(),\n            };\n            let all_bins = collect(bins, Target::is_bin);\n            let all_examples = collect(examples, Target::is_exe_example);\n\n            all_bins\n                .iter()\n                .chain(all_examples.iter())\n                .map(|name| to_exe(name))\n                .collect()\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/fix/fix_edition.rs",
    "content": "//! Support for the permanently unstable `-Zfix-edition` flag.\n\nuse super::{EditionFixMode, FixOptions};\nuse crate::core::features::{Edition, FixEdition};\nuse crate::core::{Package, Workspace};\nuse crate::ops;\nuse crate::util::toml_mut::manifest::LocalManifest;\nuse crate::{CargoResult, GlobalContext};\nuse toml_edit::{Formatted, Item, Value};\n\n/// Performs the actions for the `-Zfix-edition` flag.\npub fn fix_edition(\n    gctx: &GlobalContext,\n    original_ws: &Workspace<'_>,\n    opts: &mut FixOptions,\n    fix_edition: &FixEdition,\n) -> CargoResult<()> {\n    let packages = opts.compile_opts.spec.get_packages(original_ws)?;\n    let skip_if_not_edition = |edition| -> CargoResult<bool> {\n        if !packages.iter().all(|p| p.manifest().edition() == edition) {\n            gctx.shell().status(\n                \"Skipping\",\n                &format!(\"not all packages are at edition {edition}\"),\n            )?;\n            Ok(true)\n        } else {\n            Ok(false)\n        }\n    };\n\n    match fix_edition {\n        FixEdition::Start(edition) => {\n            // The start point just runs `cargo check` if the edition is the\n            // starting edition. This is so that crater can set a baseline of\n            // whether or not the package builds at all. For other editions,\n            // we skip entirely since they are not of interest since we can't\n            // migrate them.\n            if skip_if_not_edition(*edition)? {\n                return Ok(());\n            }\n            ops::compile(&original_ws, &opts.compile_opts)?;\n        }\n        FixEdition::End { initial, next } => {\n            // Skip packages that are not the starting edition, since we can\n            // only migrate from one edition to the next.\n            if skip_if_not_edition(*initial)? {\n                return Ok(());\n            }\n            // Do the edition fix.\n            opts.edition = Some(EditionFixMode::OverrideSpecific(*next));\n            opts.allow_dirty = true;\n            opts.allow_no_vcs = true;\n            opts.allow_staged = true;\n            ops::fix(gctx, original_ws, opts)?;\n            // Do `cargo check` with the new edition so that we can verify\n            // that it also works on the next edition.\n            replace_edition(&packages, *next)?;\n            gctx.shell()\n                .status(\"Updated\", &format!(\"edition to {next}\"))?;\n            let ws = original_ws.reload(gctx)?;\n            // Unset these since we just want to do a normal `cargo check`.\n            *opts\n                .compile_opts\n                .build_config\n                .rustfix_diagnostic_server\n                .borrow_mut() = None;\n            opts.compile_opts.build_config.primary_unit_rustc = None;\n\n            ops::compile(&ws, &opts.compile_opts)?;\n        }\n    }\n    Ok(())\n}\n\n/// Modifies the `edition` value of the given packages to the new edition.\nfn replace_edition(packages: &[&Package], to_edition: Edition) -> CargoResult<()> {\n    for package in packages {\n        let mut manifest_mut = LocalManifest::try_new(package.manifest_path())?;\n        let document = &mut manifest_mut.data;\n        let root = document.as_table_mut();\n        // Update edition to the new value.\n        if let Some(package) = root.get_mut(\"package\").and_then(|t| t.as_table_like_mut()) {\n            package.insert(\n                \"edition\",\n                Item::Value(Value::String(Formatted::new(to_edition.to_string()))),\n            );\n        }\n        // If the edition is unstable, add it to cargo-features.\n        if !to_edition.is_stable() {\n            let feature = \"unstable-editions\";\n\n            if let Some(features) = root\n                .entry(\"cargo-features\")\n                .or_insert_with(|| Item::Value(Value::Array(toml_edit::Array::new())))\n                .as_array_mut()\n            {\n                if !features\n                    .iter()\n                    .any(|f| f.as_str().map_or(false, |f| f == feature))\n                {\n                    features.push(feature);\n                }\n            }\n        }\n        manifest_mut.write()?;\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/ops/fix/mod.rs",
    "content": "//! High-level overview of how `fix` works:\n//!\n//! The main goal is to run `cargo check` to get rustc to emit JSON\n//! diagnostics with suggested fixes that can be applied to the files on the\n//! filesystem, and validate that those changes didn't break anything.\n//!\n//! Cargo begins by launching a [`LockServer`] thread in the background to\n//! listen for network connections to coordinate locking when multiple targets\n//! are built simultaneously. It ensures each package has only one fix running\n//! at once.\n//!\n//! The [`RustfixDiagnosticServer`] is launched in a background thread (in\n//! `JobQueue`) to listen for network connections to coordinate displaying\n//! messages to the user on the console (so that multiple processes don't try\n//! to print at the same time).\n//!\n//! Cargo begins a normal `cargo check` operation with itself set as a proxy\n//! for rustc by setting `BuildConfig::primary_unit_rustc` in the build config. When\n//! cargo launches rustc to check a crate, it is actually launching itself.\n//! The `FIX_ENV_INTERNAL` environment variable is set to the value of the [`LockServer`]'s\n//! address so that cargo knows it is in fix-proxy-mode.\n//!\n//! Each proxied cargo-as-rustc detects it is in fix-proxy-mode (via `FIX_ENV_INTERNAL`\n//! environment variable in `main`) and does the following:\n//!\n//! - Acquire a lock from the [`LockServer`] from the master cargo process.\n//! - Launches the real rustc ([`rustfix_and_fix`]), looking at the JSON output\n//!   for suggested fixes.\n//! - Uses the `rustfix` crate to apply the suggestions to the files on the\n//!   file system.\n//! - If rustfix fails to apply any suggestions (for example, they are\n//!   overlapping), but at least some suggestions succeeded, it will try the\n//!   previous two steps up to 4 times as long as some suggestions succeed.\n//! - Assuming there's at least one suggestion applied, and the suggestions\n//!   applied cleanly, rustc is run again to verify the suggestions didn't\n//!   break anything. The change will be backed out if it fails (unless\n//!   `--broken-code` is used).\n\nuse std::collections::{BTreeSet, HashMap, HashSet};\nuse std::ffi::OsString;\nuse std::io::Write;\nuse std::path::{Path, PathBuf};\nuse std::process::{self, ExitStatus, Output};\nuse std::{env, fs, str};\n\nuse anyhow::{Context as _, bail};\nuse cargo_util::{ProcessBuilder, exit_status_to_string, is_simple_exit_code, paths};\nuse cargo_util_schemas::manifest::TomlManifest;\nuse rustfix::CodeFix;\nuse rustfix::diagnostics::Diagnostic;\nuse semver::Version;\nuse tracing::{debug, trace, warn};\n\npub use self::fix_edition::fix_edition;\nuse crate::core::PackageIdSpecQuery as _;\nuse crate::core::compiler::CompileKind;\nuse crate::core::compiler::RustcTargetData;\nuse crate::core::resolver::features::{DiffMap, FeatureOpts, FeatureResolver, FeaturesFor};\nuse crate::core::resolver::{HasDevUnits, Resolve, ResolveBehavior};\nuse crate::core::{Edition, MaybePackage, Package, PackageId, Workspace};\nuse crate::ops::resolve::WorkspaceResolve;\nuse crate::ops::{self, CompileOptions};\nuse crate::util::GlobalContext;\nuse crate::util::diagnostic_server::{Message, RustfixDiagnosticServer};\nuse crate::util::errors::CargoResult;\nuse crate::util::toml_mut::manifest::LocalManifest;\nuse crate::util::{LockServer, LockServerClient, existing_vcs_repo};\nuse crate::{drop_eprint, drop_eprintln};\n\nmod fix_edition;\n\n/// **Internal only.**\n/// Indicates Cargo is in fix-proxy-mode if presents.\n/// The value of it is the socket address of the [`LockServer`] being used.\n/// See the [module-level documentation](mod@super::fix) for more.\nconst FIX_ENV_INTERNAL: &str = \"__CARGO_FIX_PLZ\";\n/// **Internal only.**\n/// For passing [`FixOptions::broken_code`] through to cargo running in proxy mode.\nconst BROKEN_CODE_ENV_INTERNAL: &str = \"__CARGO_FIX_BROKEN_CODE\";\n/// **Internal only.**\n/// For passing [`FixOptions::edition`] through to cargo running in proxy mode.\nconst EDITION_ENV_INTERNAL: &str = \"__CARGO_FIX_EDITION\";\n/// **Internal only.**\n/// For passing [`FixOptions::idioms`] through to cargo running in proxy mode.\nconst IDIOMS_ENV_INTERNAL: &str = \"__CARGO_FIX_IDIOMS\";\n/// **Internal only.**\n/// The sysroot path.\n///\n/// This is for preventing `cargo fix` from fixing rust std/core libs. See\n///\n/// * <https://github.com/rust-lang/cargo/issues/9857>\n/// * <https://github.com/rust-lang/rust/issues/88514#issuecomment-2043469384>\nconst SYSROOT_INTERNAL: &str = \"__CARGO_FIX_RUST_SRC\";\n\npub struct FixOptions {\n    pub edition: Option<EditionFixMode>,\n    pub idioms: bool,\n    pub compile_opts: CompileOptions,\n    pub allow_dirty: bool,\n    pub allow_no_vcs: bool,\n    pub allow_staged: bool,\n    pub broken_code: bool,\n}\n\n/// The behavior of `--edition` migration.\n#[derive(Clone, Copy)]\npub enum EditionFixMode {\n    /// Migrates the package from the current edition to the next.\n    ///\n    /// This is the normal (stable) behavior of `--edition`.\n    NextRelative,\n    /// Migrates to a specific edition.\n    ///\n    /// This is used by `-Zfix-edition` to force a specific edition like\n    /// `future`, which does not have a relative value.\n    OverrideSpecific(Edition),\n}\n\nimpl EditionFixMode {\n    /// Returns the edition to use for the given current edition.\n    pub fn next_edition(&self, current_edition: Edition) -> Edition {\n        match self {\n            EditionFixMode::NextRelative => current_edition.saturating_next(),\n            EditionFixMode::OverrideSpecific(edition) => *edition,\n        }\n    }\n\n    /// Serializes to a string.\n    fn to_string(&self) -> String {\n        match self {\n            EditionFixMode::NextRelative => \"1\".to_string(),\n            EditionFixMode::OverrideSpecific(edition) => edition.to_string(),\n        }\n    }\n\n    /// Deserializes from the given string.\n    fn from_str(s: &str) -> EditionFixMode {\n        match s {\n            \"1\" => EditionFixMode::NextRelative,\n            edition => EditionFixMode::OverrideSpecific(edition.parse().unwrap()),\n        }\n    }\n}\n\npub fn fix(\n    gctx: &GlobalContext,\n    original_ws: &Workspace<'_>,\n    opts: &mut FixOptions,\n) -> CargoResult<()> {\n    check_version_control(gctx, opts)?;\n\n    let mut target_data =\n        RustcTargetData::new(original_ws, &opts.compile_opts.build_config.requested_kinds)?;\n\n    let specs = opts.compile_opts.spec.to_package_id_specs(&original_ws)?;\n    let members: Vec<&Package> = original_ws\n        .members()\n        .filter(|m| specs.iter().any(|spec| spec.matches(m.package_id())))\n        .collect();\n    if let Some(edition_mode) = opts.edition {\n        migrate_manifests(original_ws, &members, edition_mode)?;\n\n        check_resolver_change(&original_ws, &mut target_data, opts)?;\n    }\n    fix_manifests(original_ws, &members)?;\n    let ws = original_ws.reload(gctx)?;\n\n    // Spin up our lock server, which our subprocesses will use to synchronize fixes.\n    let lock_server = LockServer::new()?;\n    let mut wrapper = ProcessBuilder::new(env::current_exe()?);\n    wrapper.env(FIX_ENV_INTERNAL, lock_server.addr().to_string());\n    let _started = lock_server.start()?;\n\n    opts.compile_opts.build_config.force_rebuild = true;\n\n    if opts.broken_code {\n        wrapper.env(BROKEN_CODE_ENV_INTERNAL, \"1\");\n    }\n\n    if let Some(mode) = &opts.edition {\n        wrapper.env(EDITION_ENV_INTERNAL, mode.to_string());\n    }\n    if opts.idioms {\n        wrapper.env(IDIOMS_ENV_INTERNAL, \"1\");\n    }\n\n    let sysroot = &target_data.info(CompileKind::Host).sysroot;\n    if sysroot.is_dir() {\n        wrapper.env(SYSROOT_INTERNAL, sysroot);\n    }\n\n    *opts\n        .compile_opts\n        .build_config\n        .rustfix_diagnostic_server\n        .borrow_mut() = Some(RustfixDiagnosticServer::new()?);\n\n    if let Some(server) = opts\n        .compile_opts\n        .build_config\n        .rustfix_diagnostic_server\n        .borrow()\n        .as_ref()\n    {\n        server.configure(&mut wrapper);\n    }\n\n    let rustc = ws.gctx().load_global_rustc(Some(&ws))?;\n    wrapper.arg(&rustc.path);\n    // This is calling rustc in cargo fix-proxy-mode, so it also need to retry.\n    // The argfile handling are located at `FixArgs::from_args`.\n    wrapper.retry_with_argfile(true);\n\n    // primary crates are compiled using a cargo subprocess to do extra work of applying fixes and\n    // repeating build until there are no more changes to be applied\n    opts.compile_opts.build_config.primary_unit_rustc = Some(wrapper);\n\n    ops::compile(&ws, &opts.compile_opts)?;\n    Ok(())\n}\n\nfn check_version_control(gctx: &GlobalContext, opts: &FixOptions) -> CargoResult<()> {\n    if opts.allow_no_vcs {\n        return Ok(());\n    }\n    if !existing_vcs_repo(gctx.cwd(), gctx.cwd()) {\n        bail!(\n            \"no VCS found for this package and `cargo fix` can potentially \\\n             perform destructive changes; if you'd like to suppress this \\\n             error pass `--allow-no-vcs`\"\n        )\n    }\n\n    if opts.allow_dirty && opts.allow_staged {\n        return Ok(());\n    }\n\n    let mut dirty_files = Vec::new();\n    let mut staged_files = Vec::new();\n    if let Ok(repo) = git2::Repository::discover(gctx.cwd()) {\n        let mut repo_opts = git2::StatusOptions::new();\n        repo_opts.include_ignored(false);\n        repo_opts.include_untracked(true);\n        for status in repo.statuses(Some(&mut repo_opts))?.iter() {\n            if let Some(path) = status.path() {\n                match status.status() {\n                    git2::Status::CURRENT => (),\n                    git2::Status::INDEX_NEW\n                    | git2::Status::INDEX_MODIFIED\n                    | git2::Status::INDEX_DELETED\n                    | git2::Status::INDEX_RENAMED\n                    | git2::Status::INDEX_TYPECHANGE => {\n                        if !opts.allow_staged {\n                            staged_files.push(path.to_string())\n                        }\n                    }\n                    _ => {\n                        if !opts.allow_dirty {\n                            dirty_files.push(path.to_string())\n                        }\n                    }\n                };\n            }\n        }\n    }\n\n    if dirty_files.is_empty() && staged_files.is_empty() {\n        return Ok(());\n    }\n\n    let mut files_list = String::new();\n    for file in dirty_files {\n        files_list.push_str(\"  * \");\n        files_list.push_str(&file);\n        files_list.push_str(\" (dirty)\\n\");\n    }\n    for file in staged_files {\n        files_list.push_str(\"  * \");\n        files_list.push_str(&file);\n        files_list.push_str(\" (staged)\\n\");\n    }\n\n    bail!(\n        \"the working directory of this package has uncommitted changes, and \\\n         `cargo fix` can potentially perform destructive changes; if you'd \\\n         like to suppress this error pass `--allow-dirty`, \\\n         or commit the changes to these files:\\n\\\n         \\n\\\n         {}\\n\\\n         \",\n        files_list\n    );\n}\n\nfn fix_manifests(ws: &Workspace<'_>, pkgs: &[&Package]) -> CargoResult<()> {\n    for pkg in pkgs {\n        if !pkg.manifest().is_embedded()\n            || pkg\n                .manifest()\n                .original_toml()\n                .and_then(|m| m.package())\n                .map(|pkg| pkg.edition.is_some())\n                .unwrap_or(false)\n        {\n            continue;\n        }\n        let file = pkg.manifest_path();\n        let file = file.strip_prefix(ws.root()).unwrap_or(file);\n        let file = file.display();\n\n        let mut manifest_mut = LocalManifest::try_new(pkg.manifest_path())?;\n        let document = &mut manifest_mut.data;\n        let mut fixes = 0;\n\n        let root = document.as_table_mut();\n\n        fixes += 1;\n        root.entry(\"package\").or_insert_with(|| {\n            let mut t = toml_edit::Table::new();\n            t.set_position(Some(-1));\n            t.into()\n        });\n        root[\"package\"][\"edition\"] = crate::core::features::Edition::LATEST_STABLE\n            .to_string()\n            .into();\n\n        if 0 < fixes {\n            let verb = if fixes == 1 { \"fix\" } else { \"fixes\" };\n            let msg = format!(\"{file} ({fixes} {verb})\");\n            ws.gctx().shell().status(\"Fixed\", msg)?;\n\n            manifest_mut.write()?;\n        }\n    }\n\n    Ok(())\n}\n\nfn migrate_manifests(\n    ws: &Workspace<'_>,\n    pkgs: &[&Package],\n    edition_mode: EditionFixMode,\n) -> CargoResult<()> {\n    // HACK: Duplicate workspace migration logic between virtual manifests and real manifests to\n    // reduce multiple Migrating messages being reported for the same file to the user\n    if matches!(ws.root_maybe(), MaybePackage::Virtual(_)) {\n        // Warning: workspaces do not have an edition so this should only include changes needed by\n        // packages that preserve the behavior of the workspace on all editions\n        let highest_edition = pkgs\n            .iter()\n            .map(|p| p.manifest().edition())\n            .max()\n            .unwrap_or_default();\n        let prepare_for_edition = edition_mode.next_edition(highest_edition);\n        if highest_edition == prepare_for_edition\n            || (!prepare_for_edition.is_stable() && !ws.gctx().nightly_features_allowed)\n        {\n            //\n        } else {\n            let mut manifest_mut = LocalManifest::try_new(ws.root_manifest())?;\n            let document = &mut manifest_mut.data;\n            let mut fixes = 0;\n\n            if Edition::Edition2024 <= prepare_for_edition {\n                let root = document.as_table_mut();\n\n                if let Some(workspace) = root\n                    .get_mut(\"workspace\")\n                    .and_then(|t| t.as_table_like_mut())\n                {\n                    // strictly speaking, the edition doesn't apply to this table but it should be safe\n                    // enough\n                    fixes += rename_dep_fields_2024(workspace, \"dependencies\");\n                }\n            }\n\n            if 0 < fixes {\n                // HACK: As workspace migration is a special case, only report it if something\n                // happened\n                let file = ws.root_manifest();\n                let file = file.strip_prefix(ws.root()).unwrap_or(file);\n                let file = file.display();\n                ws.gctx().shell().status(\n                    \"Migrating\",\n                    format!(\"{file} from {highest_edition} edition to {prepare_for_edition}\"),\n                )?;\n\n                let verb = if fixes == 1 { \"fix\" } else { \"fixes\" };\n                let msg = format!(\"{file} ({fixes} {verb})\");\n                ws.gctx().shell().status(\"Fixed\", msg)?;\n\n                manifest_mut.write()?;\n            }\n        }\n    }\n\n    for pkg in pkgs {\n        let existing_edition = pkg.manifest().edition();\n        let prepare_for_edition = edition_mode.next_edition(existing_edition);\n        if existing_edition == prepare_for_edition\n            || (!prepare_for_edition.is_stable() && !ws.gctx().nightly_features_allowed)\n        {\n            continue;\n        }\n        let file = pkg.manifest_path();\n        let file = file.strip_prefix(ws.root()).unwrap_or(file);\n        let file = file.display();\n        ws.gctx().shell().status(\n            \"Migrating\",\n            format!(\"{file} from {existing_edition} edition to {prepare_for_edition}\"),\n        )?;\n\n        let mut manifest_mut = LocalManifest::try_new(pkg.manifest_path())?;\n        let document = &mut manifest_mut.data;\n        let mut fixes = 0;\n\n        let ws_original_toml = match ws.root_maybe() {\n            MaybePackage::Package(package) => package.manifest().original_toml(),\n            MaybePackage::Virtual(manifest) => manifest.original_toml(),\n        };\n\n        if Edition::Edition2024 <= prepare_for_edition {\n            let root = document.as_table_mut();\n\n            if let Some(workspace) = root\n                .get_mut(\"workspace\")\n                .and_then(|t| t.as_table_like_mut())\n            {\n                // strictly speaking, the edition doesn't apply to this table but it should be safe\n                // enough\n                fixes += rename_dep_fields_2024(workspace, \"dependencies\");\n            }\n\n            fixes += rename_table(root, \"project\", \"package\");\n            if let Some(target) = root.get_mut(\"lib\").and_then(|t| t.as_table_like_mut()) {\n                fixes += rename_target_fields_2024(target);\n            }\n            fixes += rename_array_of_target_fields_2024(root, \"bin\");\n            fixes += rename_array_of_target_fields_2024(root, \"example\");\n            fixes += rename_array_of_target_fields_2024(root, \"test\");\n            fixes += rename_array_of_target_fields_2024(root, \"bench\");\n            fixes += rename_dep_fields_2024(root, \"dependencies\");\n            fixes += remove_ignored_default_features_2024(root, \"dependencies\", ws_original_toml);\n            fixes += rename_table(root, \"dev_dependencies\", \"dev-dependencies\");\n            fixes += rename_dep_fields_2024(root, \"dev-dependencies\");\n            fixes +=\n                remove_ignored_default_features_2024(root, \"dev-dependencies\", ws_original_toml);\n            fixes += rename_table(root, \"build_dependencies\", \"build-dependencies\");\n            fixes += rename_dep_fields_2024(root, \"build-dependencies\");\n            fixes +=\n                remove_ignored_default_features_2024(root, \"build-dependencies\", ws_original_toml);\n            for target in root\n                .get_mut(\"target\")\n                .and_then(|t| t.as_table_like_mut())\n                .iter_mut()\n                .flat_map(|t| t.iter_mut())\n                .filter_map(|(_k, t)| t.as_table_like_mut())\n            {\n                fixes += rename_dep_fields_2024(target, \"dependencies\");\n                fixes +=\n                    remove_ignored_default_features_2024(target, \"dependencies\", ws_original_toml);\n                fixes += rename_table(target, \"dev_dependencies\", \"dev-dependencies\");\n                fixes += rename_dep_fields_2024(target, \"dev-dependencies\");\n                fixes += remove_ignored_default_features_2024(\n                    target,\n                    \"dev-dependencies\",\n                    ws_original_toml,\n                );\n                fixes += rename_table(target, \"build_dependencies\", \"build-dependencies\");\n                fixes += rename_dep_fields_2024(target, \"build-dependencies\");\n                fixes += remove_ignored_default_features_2024(\n                    target,\n                    \"build-dependencies\",\n                    ws_original_toml,\n                );\n            }\n        }\n\n        if 0 < fixes {\n            let verb = if fixes == 1 { \"fix\" } else { \"fixes\" };\n            let msg = format!(\"{file} ({fixes} {verb})\");\n            ws.gctx().shell().status(\"Fixed\", msg)?;\n\n            manifest_mut.write()?;\n        }\n    }\n\n    Ok(())\n}\n\nfn rename_dep_fields_2024(parent: &mut dyn toml_edit::TableLike, dep_kind: &str) -> usize {\n    let mut fixes = 0;\n    for target in parent\n        .get_mut(dep_kind)\n        .and_then(|t| t.as_table_like_mut())\n        .iter_mut()\n        .flat_map(|t| t.iter_mut())\n        .filter_map(|(_k, t)| t.as_table_like_mut())\n    {\n        fixes += rename_table(target, \"default_features\", \"default-features\");\n    }\n    fixes\n}\n\nfn remove_ignored_default_features_2024(\n    parent: &mut dyn toml_edit::TableLike,\n    dep_kind: &str,\n    ws_original_toml: Option<&TomlManifest>,\n) -> usize {\n    let Some(ws_original_toml) = ws_original_toml else {\n        return 0;\n    };\n\n    let mut fixes = 0;\n    for (name_in_toml, target) in parent\n        .get_mut(dep_kind)\n        .and_then(|t| t.as_table_like_mut())\n        .iter_mut()\n        .flat_map(|t| t.iter_mut())\n        .filter_map(|(k, t)| t.as_table_like_mut().map(|t| (k, t)))\n    {\n        let name_in_toml: &str = &name_in_toml;\n        let ws_deps = ws_original_toml\n            .workspace\n            .as_ref()\n            .and_then(|ws| ws.dependencies.as_ref());\n        if let Some(ws_dep) = ws_deps.and_then(|ws_deps| ws_deps.get(name_in_toml)) {\n            if ws_dep.default_features() == Some(false) {\n                continue;\n            }\n        }\n        if target\n            .get(\"workspace\")\n            .and_then(|i| i.as_value())\n            .and_then(|i| i.as_bool())\n            == Some(true)\n            && target\n                .get(\"default-features\")\n                .and_then(|i| i.as_value())\n                .and_then(|i| i.as_bool())\n                == Some(false)\n        {\n            target.remove(\"default-features\");\n            fixes += 1;\n        }\n    }\n    fixes\n}\n\nfn rename_array_of_target_fields_2024(root: &mut dyn toml_edit::TableLike, kind: &str) -> usize {\n    let mut fixes = 0;\n    for target in root\n        .get_mut(kind)\n        .and_then(|t| t.as_array_of_tables_mut())\n        .iter_mut()\n        .flat_map(|t| t.iter_mut())\n    {\n        fixes += rename_target_fields_2024(target);\n    }\n    fixes\n}\n\nfn rename_target_fields_2024(target: &mut dyn toml_edit::TableLike) -> usize {\n    let mut fixes = 0;\n    fixes += rename_table(target, \"crate_type\", \"crate-type\");\n    fixes += rename_table(target, \"proc_macro\", \"proc-macro\");\n    fixes\n}\n\nfn rename_table(parent: &mut dyn toml_edit::TableLike, old: &str, new: &str) -> usize {\n    let Some(old_key) = parent.key(old).cloned() else {\n        return 0;\n    };\n\n    let project = parent.remove(old).expect(\"returned early\");\n    if !parent.contains_key(new) {\n        parent.insert(new, project);\n        let mut new_key = parent.key_mut(new).expect(\"just inserted\");\n        *new_key.dotted_decor_mut() = old_key.dotted_decor().clone();\n        *new_key.leaf_decor_mut() = old_key.leaf_decor().clone();\n    }\n    1\n}\n\nfn check_resolver_change<'gctx>(\n    ws: &Workspace<'gctx>,\n    target_data: &mut RustcTargetData<'gctx>,\n    opts: &FixOptions,\n) -> CargoResult<()> {\n    let root = ws.root_maybe();\n    match root {\n        MaybePackage::Package(root_pkg) => {\n            if root_pkg.manifest().resolve_behavior().is_some() {\n                // If explicitly specified by the user, no need to check.\n                return Ok(());\n            }\n            // Only trigger if updating the root package from 2018.\n            let pkgs = opts.compile_opts.spec.get_packages(ws)?;\n            if !pkgs.contains(&root_pkg) {\n                // The root is not being migrated.\n                return Ok(());\n            }\n            if root_pkg.manifest().edition() != Edition::Edition2018 {\n                // V1 to V2 only happens on 2018 to 2021.\n                return Ok(());\n            }\n        }\n        MaybePackage::Virtual(_vm) => {\n            // Virtual workspaces don't have a global edition to set (yet).\n            return Ok(());\n        }\n    }\n    // 2018 without `resolver` set must be V1\n    assert_eq!(ws.resolve_behavior(), ResolveBehavior::V1);\n    let specs = opts.compile_opts.spec.to_package_id_specs(ws)?;\n    let mut resolve_differences = |has_dev_units| -> CargoResult<(WorkspaceResolve<'_>, DiffMap)> {\n        let dry_run = false;\n        let ws_resolve = ops::resolve_ws_with_opts(\n            ws,\n            target_data,\n            &opts.compile_opts.build_config.requested_kinds,\n            &opts.compile_opts.cli_features,\n            &specs,\n            has_dev_units,\n            crate::core::resolver::features::ForceAllTargets::No,\n            dry_run,\n        )?;\n\n        let feature_opts = FeatureOpts::new_behavior(ResolveBehavior::V2, has_dev_units);\n        let v2_features = FeatureResolver::resolve(\n            ws,\n            target_data,\n            &ws_resolve.targeted_resolve,\n            &ws_resolve.pkg_set,\n            &opts.compile_opts.cli_features,\n            &specs,\n            &opts.compile_opts.build_config.requested_kinds,\n            feature_opts,\n        )?;\n\n        if ws_resolve.specs_and_features.len() != 1 {\n            bail!(r#\"cannot fix edition when using `feature-unification = \"package\"`.\"#);\n        }\n        let resolved_features = &ws_resolve\n            .specs_and_features\n            .first()\n            .expect(\"We've already checked that there is exactly one.\")\n            .resolved_features;\n        let diffs = v2_features.compare_legacy(resolved_features);\n        Ok((ws_resolve, diffs))\n    };\n    let (_, without_dev_diffs) = resolve_differences(HasDevUnits::No)?;\n    let (ws_resolve, mut with_dev_diffs) = resolve_differences(HasDevUnits::Yes)?;\n    if without_dev_diffs.is_empty() && with_dev_diffs.is_empty() {\n        // Nothing is different, nothing to report.\n        return Ok(());\n    }\n    // Only display unique changes with dev-dependencies.\n    with_dev_diffs.retain(|k, vals| without_dev_diffs.get(k) != Some(vals));\n    let gctx = ws.gctx();\n    gctx.shell().note(\n        \"Switching to Edition 2021 will enable the use of the version 2 feature resolver in Cargo.\",\n    )?;\n    drop_eprintln!(\n        gctx,\n        \"This may cause some dependencies to be built with fewer features enabled than previously.\"\n    );\n    drop_eprintln!(\n        gctx,\n        \"More information about the resolver changes may be found \\\n         at https://doc.rust-lang.org/nightly/edition-guide/rust-2021/default-cargo-resolver.html\"\n    );\n    drop_eprintln!(\n        gctx,\n        \"When building the following dependencies, \\\n         the given features will no longer be used:\\n\"\n    );\n    let show_diffs = |differences: DiffMap| {\n        for ((pkg_id, features_for), removed) in differences {\n            drop_eprint!(gctx, \"  {}\", pkg_id);\n            if let FeaturesFor::HostDep = features_for {\n                drop_eprint!(gctx, \" (as host dependency)\");\n            }\n            drop_eprint!(gctx, \" removed features: \");\n            let joined: Vec<_> = removed.iter().map(|s| s.as_str()).collect();\n            drop_eprintln!(gctx, \"{}\", joined.join(\", \"));\n        }\n        drop_eprint!(gctx, \"\\n\");\n    };\n    if !without_dev_diffs.is_empty() {\n        show_diffs(without_dev_diffs);\n    }\n    if !with_dev_diffs.is_empty() {\n        drop_eprintln!(\n            gctx,\n            \"The following differences only apply when building with dev-dependencies:\\n\"\n        );\n        show_diffs(with_dev_diffs);\n    }\n    report_maybe_diesel(gctx, &ws_resolve.targeted_resolve)?;\n    Ok(())\n}\n\nfn report_maybe_diesel(gctx: &GlobalContext, resolve: &Resolve) -> CargoResult<()> {\n    fn is_broken_diesel(pid: PackageId) -> bool {\n        pid.name() == \"diesel\" && pid.version() < &Version::new(1, 4, 8)\n    }\n\n    fn is_broken_diesel_migration(pid: PackageId) -> bool {\n        pid.name() == \"diesel_migrations\" && pid.version().major <= 1\n    }\n\n    if resolve.iter().any(is_broken_diesel) && resolve.iter().any(is_broken_diesel_migration) {\n        gctx.shell().note(\n            \"\\\nThis project appears to use both diesel and diesel_migrations. These packages have\na known issue where the build may fail due to the version 2 resolver preventing\nfeature unification between those two packages. Please update to at least diesel 1.4.8\nto prevent this issue from happening.\n\",\n        )?;\n    }\n    Ok(())\n}\n\n/// Provide the lock address when running in proxy mode\n///\n/// Returns `None` if `fix` is not being run (not in proxy mode). Returns\n/// `Some(...)` if in `fix` proxy mode\npub fn fix_get_proxy_lock_addr() -> Option<String> {\n    #[expect(\n        clippy::disallowed_methods,\n        reason = \"internal only, no reason for config support\"\n    )]\n    env::var(FIX_ENV_INTERNAL).ok()\n}\n\n/// Entry point for `cargo` running as a proxy for `rustc`.\n///\n/// This is called every time `cargo` is run to check if it is in proxy mode.\n///\n/// If there are warnings or errors, this does not return,\n/// and the process exits with the corresponding `rustc` exit code.\n///\n/// See [`fix_get_proxy_lock_addr`]\npub fn fix_exec_rustc(gctx: &GlobalContext, lock_addr: &str) -> CargoResult<()> {\n    let args = FixArgs::get()?;\n    trace!(\"cargo-fix as rustc got file {:?}\", args.file);\n\n    let workspace_rustc = gctx\n        .get_env(\"RUSTC_WORKSPACE_WRAPPER\")\n        .map(PathBuf::from)\n        .ok();\n    let mut rustc = ProcessBuilder::new(&args.rustc).wrapped(workspace_rustc.as_ref());\n    rustc.retry_with_argfile(true);\n    rustc.env_remove(FIX_ENV_INTERNAL);\n    args.apply(&mut rustc);\n    // Removes `FD_CLOEXEC` set by `jobserver::Client` to ensure that the\n    // compiler can access the jobserver.\n    if let Some(client) = gctx.jobserver_from_env() {\n        rustc.inherit_jobserver(client);\n    }\n\n    trace!(\"start rustfixing {:?}\", args.file);\n    let fixes = rustfix_crate(&lock_addr, &rustc, &args.file, &args, gctx)?;\n\n    if fixes.last_output.status.success() {\n        for (path, file) in fixes.files.iter() {\n            Message::Fixed {\n                file: path.clone(),\n                fixes: file.fixes_applied,\n            }\n            .post(gctx)?;\n        }\n        // Display any remaining diagnostics.\n        emit_output(&fixes.last_output)?;\n        return Ok(());\n    }\n\n    let allow_broken_code = gctx.get_env_os(BROKEN_CODE_ENV_INTERNAL).is_some();\n\n    // There was an error running rustc during the last run.\n    //\n    // Back out all of the changes unless --broken-code was used.\n    if !allow_broken_code {\n        for (path, file) in fixes.files.iter() {\n            debug!(\"reverting {:?} due to errors\", path);\n            paths::write(path, &file.original_code)?;\n        }\n    }\n\n    // If there were any fixes, let the user know that there was a failure\n    // attempting to apply them, and to ask for a bug report.\n    //\n    // FIXME: The error message here is not correct with --broken-code.\n    //        https://github.com/rust-lang/cargo/issues/10955\n    if fixes.files.is_empty() {\n        // No fixes were available. Display whatever errors happened.\n        emit_output(&fixes.last_output)?;\n        exit_with(fixes.last_output.status);\n    } else {\n        let krate = {\n            let mut iter = rustc.get_args();\n            let mut krate = None;\n            while let Some(arg) = iter.next() {\n                if arg == \"--crate-name\" {\n                    krate = iter.next().and_then(|s| s.to_owned().into_string().ok());\n                }\n            }\n            krate\n        };\n        log_failed_fix(\n            gctx,\n            krate,\n            &fixes.last_output.stderr,\n            fixes.last_output.status,\n        )?;\n        // Display the diagnostics that appeared at the start, before the\n        // fixes failed. This can help with diagnosing which suggestions\n        // caused the failure.\n        emit_output(&fixes.first_output)?;\n        // Exit with whatever exit code we initially started with. `cargo fix`\n        // treats this as a warning, and shouldn't return a failure code\n        // unless the code didn't compile in the first place.\n        exit_with(fixes.first_output.status);\n    }\n}\n\nfn emit_output(output: &Output) -> CargoResult<()> {\n    // Unfortunately if there is output on stdout, this does not preserve the\n    // order of output relative to stderr. In practice, rustc should never\n    // print to stdout unless some proc-macro does it.\n    std::io::stderr().write_all(&output.stderr)?;\n    std::io::stdout().write_all(&output.stdout)?;\n    Ok(())\n}\n\nstruct FixedCrate {\n    /// Map of file path to some information about modifications made to that file.\n    files: HashMap<String, FixedFile>,\n    /// The output from rustc from the first time it was called.\n    ///\n    /// This is needed when fixes fail to apply, so that it can display the\n    /// original diagnostics to the user which can help with diagnosing which\n    /// suggestions caused the failure.\n    first_output: Output,\n    /// The output from rustc from the last time it was called.\n    ///\n    /// This will be displayed to the user to show any remaining diagnostics\n    /// or errors.\n    last_output: Output,\n}\n\n#[derive(Debug)]\nstruct FixedFile {\n    errors_applying_fixes: Vec<String>,\n    fixes_applied: u32,\n    original_code: String,\n}\n\n/// Attempts to apply fixes to a single crate.\n///\n/// This runs `rustc` (possibly multiple times) to gather suggestions from the\n/// compiler and applies them to the files on disk.\nfn rustfix_crate(\n    lock_addr: &str,\n    rustc: &ProcessBuilder,\n    filename: &Path,\n    args: &FixArgs,\n    gctx: &GlobalContext,\n) -> CargoResult<FixedCrate> {\n    // First up, we want to make sure that each crate is only checked by one\n    // process at a time. If two invocations concurrently check a crate then\n    // it's likely to corrupt it.\n    //\n    // Historically this used per-source-file locking, then per-package\n    // locking. It now uses a single, global lock as some users do things like\n    // #[path] or include!() of shared files between packages. Serializing\n    // makes it slower, but is the only safe way to prevent concurrent\n    // modification.\n    let _lock = LockServerClient::lock(&lock_addr.parse()?, \"global\")?;\n\n    // Map of files that have been modified.\n    let mut files = HashMap::new();\n\n    if !args.can_run_rustfix(gctx)? {\n        // This fix should not be run. Skipping...\n        // We still need to run rustc at least once to make sure any potential\n        // rmeta gets generated, and diagnostics get displayed.\n        debug!(\"can't fix {filename:?}, running rustc: {rustc}\");\n        let last_output = rustc.output()?;\n        let fixes = FixedCrate {\n            files,\n            first_output: last_output.clone(),\n            last_output,\n        };\n        return Ok(fixes);\n    }\n\n    // Next up, this is a bit suspicious, but we *iteratively* execute rustc and\n    // collect suggestions to feed to rustfix. Once we hit our limit of times to\n    // execute rustc or we appear to be reaching a fixed point we stop running\n    // rustc.\n    //\n    // This is currently done to handle code like:\n    //\n    //      ::foo::<::Bar>();\n    //\n    // where there are two fixes to happen here: `crate::foo::<crate::Bar>()`.\n    // The spans for these two suggestions are overlapping and its difficult in\n    // the compiler to **not** have overlapping spans here. As a result, a naive\n    // implementation would feed the two compiler suggestions for the above fix\n    // into `rustfix`, but one would be rejected because it overlaps with the\n    // other.\n    //\n    // In this case though, both suggestions are valid and can be automatically\n    // applied! To handle this case we execute rustc multiple times, collecting\n    // fixes each time we do so. Along the way we discard any suggestions that\n    // failed to apply, assuming that they can be fixed the next time we run\n    // rustc.\n    //\n    // Naturally, we want a few protections in place here though to avoid looping\n    // forever or otherwise losing data. To that end we have a few termination\n    // conditions:\n    //\n    // * Do this whole process a fixed number of times. In theory we probably\n    //   need an infinite number of times to apply fixes, but we're not gonna\n    //   sit around waiting for that.\n    // * If it looks like a fix genuinely can't be applied we need to bail out.\n    //   Detect this when a fix fails to get applied *and* no suggestions\n    //   successfully applied to the same file. In that case looks like we\n    //   definitely can't make progress, so bail out.\n    let max_iterations = gctx\n        .get_env(\"CARGO_FIX_MAX_RETRIES\")\n        .ok()\n        .and_then(|n| n.parse().ok())\n        .unwrap_or(4);\n    let mut last_output;\n    let mut last_made_changes;\n    let mut first_output = None;\n    let mut current_iteration = 0;\n    loop {\n        for file in files.values_mut() {\n            // We'll generate new errors below.\n            file.errors_applying_fixes.clear();\n        }\n        (last_output, last_made_changes) =\n            rustfix_and_fix(&mut files, rustc, filename, args, gctx)?;\n        if current_iteration == 0 {\n            first_output = Some(last_output.clone());\n        }\n        let mut progress_yet_to_be_made = false;\n        for (path, file) in files.iter_mut() {\n            if file.errors_applying_fixes.is_empty() {\n                continue;\n            }\n            debug!(\"had rustfix apply errors in {path:?} {file:?}\");\n            // If anything was successfully fixed *and* there's at least one\n            // error, then assume the error was spurious and we'll try again on\n            // the next iteration.\n            if last_made_changes {\n                progress_yet_to_be_made = true;\n            }\n        }\n        if !progress_yet_to_be_made {\n            break;\n        }\n        current_iteration += 1;\n        if current_iteration >= max_iterations {\n            break;\n        }\n    }\n    if last_made_changes {\n        debug!(\"calling rustc one last time for final results: {rustc}\");\n        last_output = rustc.output()?;\n    }\n\n    // Any errors still remaining at this point need to be reported as probably\n    // bugs in Cargo and/or rustfix.\n    for (path, file) in files.iter_mut() {\n        for error in file.errors_applying_fixes.drain(..) {\n            Message::ReplaceFailed {\n                file: path.clone(),\n                message: error,\n            }\n            .post(gctx)?;\n        }\n    }\n\n    Ok(FixedCrate {\n        files,\n        first_output: first_output.expect(\"at least one iteration\"),\n        last_output,\n    })\n}\n\n/// Executes `rustc` to apply one round of suggestions to the crate in question.\n///\n/// This will fill in the `fixes` map with original code, suggestions applied,\n/// and any errors encountered while fixing files.\nfn rustfix_and_fix(\n    files: &mut HashMap<String, FixedFile>,\n    rustc: &ProcessBuilder,\n    filename: &Path,\n    args: &FixArgs,\n    gctx: &GlobalContext,\n) -> CargoResult<(Output, bool)> {\n    // If not empty, filter by these lints.\n    // TODO: implement a way to specify this.\n    let only = HashSet::new();\n\n    debug!(\"calling rustc to collect suggestions and validate previous fixes: {rustc}\");\n    let output = rustc.output()?;\n\n    // If rustc didn't succeed for whatever reasons then we're very likely to be\n    // looking at otherwise broken code. Let's not make things accidentally\n    // worse by applying fixes where a bug could cause *more* broken code.\n    // Instead, punt upwards which will reexec rustc over the original code,\n    // displaying pretty versions of the diagnostics we just read out.\n    if !output.status.success() && gctx.get_env_os(BROKEN_CODE_ENV_INTERNAL).is_none() {\n        debug!(\n            \"rustfixing `{:?}` failed, rustc exited with {:?}\",\n            filename,\n            output.status.code()\n        );\n        return Ok((output, false));\n    }\n\n    let fix_mode = gctx\n        .get_env_os(\"__CARGO_FIX_YOLO\")\n        .map(|_| rustfix::Filter::Everything)\n        .unwrap_or(rustfix::Filter::MachineApplicableOnly);\n\n    // Sift through the output of the compiler to look for JSON messages.\n    // indicating fixes that we can apply.\n    let stderr = str::from_utf8(&output.stderr).context(\"failed to parse rustc stderr as UTF-8\")?;\n\n    let suggestions = stderr\n        .lines()\n        .filter(|x| !x.is_empty())\n        .inspect(|y| trace!(\"line: {}\", y))\n        // Parse each line of stderr, ignoring errors, as they may not all be JSON.\n        .filter_map(|line| serde_json::from_str::<Diagnostic>(line).ok())\n        // From each diagnostic, try to extract suggestions from rustc.\n        .filter_map(|diag| rustfix::collect_suggestions(&diag, &only, fix_mode));\n\n    // Collect suggestions by file so we can apply them one at a time later.\n    let mut file_map = HashMap::new();\n    let mut num_suggestion = 0;\n    // It's safe since we won't read any content under home dir.\n    let home_path = gctx.home().as_path_unlocked();\n    for suggestion in suggestions {\n        trace!(\"suggestion\");\n        // Make sure we've got a file associated with this suggestion and all\n        // snippets point to the same file. Right now it's not clear what\n        // we would do with multiple files.\n        let file_names = suggestion\n            .solutions\n            .iter()\n            .flat_map(|s| s.replacements.iter())\n            .map(|r| &r.snippet.file_name);\n\n        let file_name = if let Some(file_name) = file_names.clone().next() {\n            file_name.clone()\n        } else {\n            trace!(\"rejecting as it has no solutions {:?}\", suggestion);\n            continue;\n        };\n\n        let file_path = Path::new(&file_name);\n        // Do not write into registry cache. See rust-lang/cargo#9857.\n        if file_path.starts_with(home_path) {\n            continue;\n        }\n        // Do not write into standard library source. See rust-lang/cargo#9857.\n        if let Some(sysroot) = args.sysroot.as_deref() {\n            if file_path.starts_with(sysroot) {\n                continue;\n            }\n        }\n\n        if !file_names.clone().all(|f| f == &file_name) {\n            trace!(\"rejecting as it changes multiple files: {:?}\", suggestion);\n            continue;\n        }\n\n        trace!(\"adding suggestion for {:?}: {:?}\", file_name, suggestion);\n        file_map\n            .entry(file_name)\n            .or_insert_with(Vec::new)\n            .push(suggestion);\n        num_suggestion += 1;\n    }\n\n    debug!(\n        \"collected {} suggestions for `{}`\",\n        num_suggestion,\n        filename.display(),\n    );\n\n    let mut made_changes = false;\n    for (file, suggestions) in file_map {\n        // Attempt to read the source code for this file. If this fails then\n        // that'd be pretty surprising, so log a message and otherwise keep\n        // going.\n        let code = match paths::read(file.as_ref()) {\n            Ok(s) => s,\n            Err(e) => {\n                warn!(\"failed to read `{}`: {}\", file, e);\n                continue;\n            }\n        };\n        let num_suggestions = suggestions.len();\n        debug!(\"applying {} fixes to {}\", num_suggestions, file);\n\n        // If this file doesn't already exist then we just read the original\n        // code, so save it. If the file already exists then the original code\n        // doesn't need to be updated as we've just read an interim state with\n        // some fixes but perhaps not all.\n        let fixed_file = files.entry(file.clone()).or_insert_with(|| FixedFile {\n            errors_applying_fixes: Vec::new(),\n            fixes_applied: 0,\n            original_code: code.clone(),\n        });\n        let mut fixed = CodeFix::new(&code);\n\n        for suggestion in suggestions.iter().rev() {\n            // As mentioned above in `rustfix_crate`,\n            // we don't immediately warn about suggestions that fail to apply here,\n            // and instead we save them off for later processing.\n            //\n            // However, we don't bother reporting conflicts that exactly match prior replacements.\n            // This is currently done to reduce noise for things like rust-lang/rust#51211,\n            // although it may be removed if that's fixed deeper in the compiler.\n            match fixed.apply(suggestion) {\n                Ok(()) => fixed_file.fixes_applied += 1,\n                Err(rustfix::Error::AlreadyReplaced {\n                    is_identical: true, ..\n                }) => continue,\n                Err(e) => fixed_file.errors_applying_fixes.push(e.to_string()),\n            }\n        }\n        if fixed.modified() {\n            made_changes = true;\n            let new_code = fixed.finish()?;\n            paths::write(&file, new_code)?;\n        }\n    }\n\n    Ok((output, made_changes))\n}\n\nfn exit_with(status: ExitStatus) -> ! {\n    #[cfg(unix)]\n    {\n        use std::os::unix::prelude::*;\n        if let Some(signal) = status.signal() {\n            drop(writeln!(\n                std::io::stderr().lock(),\n                \"child failed with signal `{}`\",\n                signal\n            ));\n            process::exit(2);\n        }\n    }\n    process::exit(status.code().unwrap_or(3));\n}\n\nfn log_failed_fix(\n    gctx: &GlobalContext,\n    krate: Option<String>,\n    stderr: &[u8],\n    status: ExitStatus,\n) -> CargoResult<()> {\n    let stderr = str::from_utf8(stderr).context(\"failed to parse rustc stderr as utf-8\")?;\n\n    let diagnostics = stderr\n        .lines()\n        .filter(|x| !x.is_empty())\n        .filter_map(|line| serde_json::from_str::<Diagnostic>(line).ok());\n    let mut files = BTreeSet::new();\n    let mut errors = Vec::new();\n    for diagnostic in diagnostics {\n        errors.push(diagnostic.rendered.unwrap_or(diagnostic.message));\n        for span in diagnostic.spans.into_iter() {\n            files.insert(span.file_name);\n        }\n    }\n    // Include any abnormal messages (like an ICE or whatever).\n    errors.extend(\n        stderr\n            .lines()\n            .filter(|x| !x.starts_with('{'))\n            .map(|x| x.to_string()),\n    );\n\n    let files = files.into_iter().collect();\n    let abnormal_exit = if status.code().map_or(false, is_simple_exit_code) {\n        None\n    } else {\n        Some(exit_status_to_string(status))\n    };\n    Message::FixFailed {\n        files,\n        krate,\n        errors,\n        abnormal_exit,\n    }\n    .post(gctx)?;\n\n    Ok(())\n}\n\n/// Various command-line options and settings used when `cargo` is running as\n/// a proxy for `rustc` during the fix operation.\nstruct FixArgs {\n    /// This is the `.rs` file that is being fixed.\n    file: PathBuf,\n    /// If `--edition` is used to migrate to the next edition, this is the\n    /// edition we are migrating towards.\n    prepare_for_edition: Option<Edition>,\n    /// `true` if `--edition-idioms` is enabled.\n    idioms: bool,\n    /// The current edition.\n    ///\n    /// `None` if on 2015.\n    enabled_edition: Option<Edition>,\n    /// Other command-line arguments not reflected by other fields in\n    /// `FixArgs`.\n    other: Vec<OsString>,\n    /// Path to the `rustc` executable.\n    rustc: PathBuf,\n    /// Path to host sysroot.\n    sysroot: Option<PathBuf>,\n}\n\nimpl FixArgs {\n    fn get() -> CargoResult<FixArgs> {\n        Self::from_args(env::args_os())\n    }\n\n    // This is a separate function so that we can use it in tests.\n    fn from_args(argv: impl IntoIterator<Item = OsString>) -> CargoResult<Self> {\n        let mut argv = argv.into_iter();\n        let mut rustc = argv\n            .nth(1)\n            .map(PathBuf::from)\n            .ok_or_else(|| anyhow::anyhow!(\"expected rustc or `@path` as first argument\"))?;\n        let mut file = None;\n        let mut enabled_edition = None;\n        let mut other = Vec::new();\n\n        let mut handle_arg = |arg: OsString| -> CargoResult<()> {\n            let path = PathBuf::from(arg);\n            if path.extension().and_then(|s| s.to_str()) == Some(\"rs\") && path.exists() {\n                file = Some(path);\n                return Ok(());\n            }\n            if let Some(s) = path.to_str() {\n                if let Some(edition) = s.strip_prefix(\"--edition=\") {\n                    enabled_edition = Some(edition.parse()?);\n                    return Ok(());\n                }\n            }\n            other.push(path.into());\n            Ok(())\n        };\n\n        if let Some(argfile_path) = rustc.to_str().unwrap_or_default().strip_prefix(\"@\") {\n            // Because cargo in fix-proxy-mode might hit the command line size limit,\n            // cargo fix need handle `@path` argfile for this special case.\n            if argv.next().is_some() {\n                bail!(\"argfile `@path` cannot be combined with other arguments\");\n            }\n            let contents = fs::read_to_string(argfile_path)\n                .with_context(|| format!(\"failed to read argfile at `{argfile_path}`\"))?;\n            let mut iter = contents.lines().map(OsString::from);\n            rustc = iter\n                .next()\n                .map(PathBuf::from)\n                .ok_or_else(|| anyhow::anyhow!(\"expected rustc as first argument\"))?;\n            for arg in iter {\n                handle_arg(arg)?;\n            }\n        } else {\n            for arg in argv {\n                handle_arg(arg)?;\n            }\n        }\n\n        let file = file.ok_or_else(|| anyhow::anyhow!(\"could not find .rs file in rustc args\"))?;\n        #[expect(\n            clippy::disallowed_methods,\n            reason = \"internal only, no reason for config support\"\n        )]\n        let idioms = env::var(IDIOMS_ENV_INTERNAL).is_ok();\n\n        #[expect(\n            clippy::disallowed_methods,\n            reason = \"internal only, no reason for config support\"\n        )]\n        let prepare_for_edition = env::var(EDITION_ENV_INTERNAL).ok().map(|v| {\n            let enabled_edition = enabled_edition.unwrap_or(Edition::Edition2015);\n            let mode = EditionFixMode::from_str(&v);\n            mode.next_edition(enabled_edition)\n        });\n\n        #[expect(\n            clippy::disallowed_methods,\n            reason = \"internal only, no reason for config support\"\n        )]\n        let sysroot = env::var_os(SYSROOT_INTERNAL).map(PathBuf::from);\n\n        Ok(FixArgs {\n            file,\n            prepare_for_edition,\n            idioms,\n            enabled_edition,\n            other,\n            rustc,\n            sysroot,\n        })\n    }\n\n    fn apply(&self, cmd: &mut ProcessBuilder) {\n        cmd.arg(&self.file);\n        cmd.args(&self.other);\n        if self.prepare_for_edition.is_some() {\n            // When migrating an edition, we don't want to fix other lints as\n            // they can sometimes add suggestions that fail to apply, causing\n            // the entire migration to fail. But those lints aren't needed to\n            // migrate.\n            cmd.arg(\"--cap-lints=allow\");\n        } else {\n            // This allows `cargo fix` to work even if the crate has #[deny(warnings)].\n            cmd.arg(\"--cap-lints=warn\");\n        }\n        if let Some(edition) = self.enabled_edition {\n            cmd.arg(\"--edition\").arg(edition.to_string());\n            if self.idioms && edition.supports_idiom_lint() {\n                cmd.arg(format!(\"-Wrust-{}-idioms\", edition));\n            }\n        }\n\n        if let Some(edition) = self.prepare_for_edition {\n            edition.force_warn_arg(cmd);\n        }\n    }\n\n    /// Validates the edition, and sends a message indicating what is being\n    /// done. Returns a flag indicating whether this fix should be run.\n    fn can_run_rustfix(&self, gctx: &GlobalContext) -> CargoResult<bool> {\n        let Some(to_edition) = self.prepare_for_edition else {\n            return Message::Fixing {\n                file: self.file.display().to_string(),\n            }\n            .post(gctx)\n            .and(Ok(true));\n        };\n        // Unfortunately determining which cargo targets are being built\n        // isn't easy, and each target can be a different edition. The\n        // cargo-as-rustc fix wrapper doesn't know anything about the\n        // workspace, so it can't check for the `cargo-features` unstable\n        // opt-in. As a compromise, this just restricts to the nightly\n        // toolchain.\n        //\n        // Unfortunately this results in a pretty poor error message when\n        // multiple jobs run in parallel (the error appears multiple\n        // times). Hopefully this doesn't happen often in practice.\n        if !to_edition.is_stable() && !gctx.nightly_features_allowed {\n            let message = format!(\n                \"`{file}` is on the latest edition, but trying to \\\n                 migrate to edition {to_edition}.\\n\\\n                 Edition {to_edition} is unstable and not allowed in \\\n                 this release, consider trying the nightly release channel.\",\n                file = self.file.display(),\n                to_edition = to_edition\n            );\n            return Message::EditionAlreadyEnabled {\n                message,\n                edition: to_edition.previous().unwrap(),\n            }\n            .post(gctx)\n            .and(Ok(false)); // Do not run rustfix for this the edition.\n        }\n        let from_edition = self.enabled_edition.unwrap_or(Edition::Edition2015);\n        if from_edition == to_edition {\n            let message = format!(\n                \"`{}` is already on the latest edition ({}), \\\n                 unable to migrate further\",\n                self.file.display(),\n                to_edition\n            );\n            Message::EditionAlreadyEnabled {\n                message,\n                edition: to_edition,\n            }\n            .post(gctx)\n        } else {\n            Message::Migrating {\n                file: self.file.display().to_string(),\n                from_edition,\n                to_edition,\n            }\n            .post(gctx)\n        }\n        .and(Ok(true))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::FixArgs;\n    use std::ffi::OsString;\n    use std::io::Write as _;\n    use std::path::PathBuf;\n\n    #[test]\n    fn get_fix_args_from_argfile() {\n        let mut temp = tempfile::Builder::new().tempfile().unwrap();\n        let main_rs = tempfile::Builder::new().suffix(\".rs\").tempfile().unwrap();\n\n        let content = format!(\"/path/to/rustc\\n{}\\nfoobar\\n\", main_rs.path().display());\n        temp.write_all(content.as_bytes()).unwrap();\n\n        let argfile = format!(\"@{}\", temp.path().display());\n        let args = [\"cargo\", &argfile];\n        let fix_args = FixArgs::from_args(args.map(|x| x.into())).unwrap();\n        assert_eq!(fix_args.rustc, PathBuf::from(\"/path/to/rustc\"));\n        assert_eq!(fix_args.file, main_rs.path());\n        assert_eq!(fix_args.other, vec![OsString::from(\"foobar\")]);\n    }\n\n    #[test]\n    fn get_fix_args_from_argfile_with_extra_arg() {\n        let mut temp = tempfile::Builder::new().tempfile().unwrap();\n        let main_rs = tempfile::Builder::new().suffix(\".rs\").tempfile().unwrap();\n\n        let content = format!(\"/path/to/rustc\\n{}\\nfoobar\\n\", main_rs.path().display());\n        temp.write_all(content.as_bytes()).unwrap();\n\n        let argfile = format!(\"@{}\", temp.path().display());\n        let args = [\"cargo\", &argfile, \"boo!\"];\n        match FixArgs::from_args(args.map(|x| x.into())) {\n            Err(e) => assert_eq!(\n                e.to_string(),\n                \"argfile `@path` cannot be combined with other arguments\"\n            ),\n            Ok(_) => panic!(\"should fail\"),\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/lockfile.rs",
    "content": "use std::io::prelude::*;\n\nuse crate::core::resolver::encode::into_resolve;\nuse crate::core::{Resolve, ResolveVersion, Workspace};\nuse crate::util::Filesystem;\nuse crate::util::errors::CargoResult;\n\nuse anyhow::Context as _;\nuse cargo_util_schemas::lockfile::TomlLockfile;\n\npub const LOCKFILE_NAME: &str = \"Cargo.lock\";\n\n#[tracing::instrument(skip_all)]\npub fn load_pkg_lockfile(ws: &Workspace<'_>) -> CargoResult<Option<Resolve>> {\n    let lock_root = ws.lock_root();\n    if !lock_root.as_path_unlocked().join(LOCKFILE_NAME).exists() {\n        return Ok(None);\n    }\n\n    let mut f = lock_root.open_ro_shared(LOCKFILE_NAME, ws.gctx(), \"Cargo.lock file\")?;\n\n    let mut s = String::new();\n    f.read_to_string(&mut s)\n        .with_context(|| format!(\"failed to read file: {}\", f.path().display()))?;\n\n    let resolve = (|| -> CargoResult<Option<Resolve>> {\n        let v: TomlLockfile = toml::from_str(&s)?;\n        Ok(Some(into_resolve(v, &s, ws)?))\n    })()\n    .with_context(|| format!(\"failed to parse lock file at: {}\", f.path().display()))?;\n    Ok(resolve)\n}\n\n/// Generate a toml String of Cargo.lock from a Resolve.\npub fn resolve_to_string(ws: &Workspace<'_>, resolve: &Resolve) -> CargoResult<String> {\n    let (_orig, out, _lock_root) = resolve_to_string_orig(ws, resolve);\n    Ok(out)\n}\n\n/// Ensure the resolve result is written to fisk\n///\n/// Returns `true` if the lockfile changed\n#[tracing::instrument(skip_all)]\npub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoResult<bool> {\n    let (orig, mut out, lock_root) = resolve_to_string_orig(ws, resolve);\n\n    // If the lock file contents haven't changed so don't rewrite it. This is\n    // helpful on read-only filesystems.\n    if let Some(orig) = &orig {\n        if are_equal_lockfiles(orig, &out, ws) {\n            return Ok(false);\n        }\n    }\n\n    if let Some(locked_flag) = ws.gctx().locked_flag() {\n        let lockfile_path = lock_root.as_path_unlocked().join(LOCKFILE_NAME);\n        let action = if lockfile_path.exists() {\n            \"update\"\n        } else {\n            \"create\"\n        };\n        let lockfile_path = lockfile_path.display();\n        anyhow::bail!(\n            \"cannot {action} the lock file {lockfile_path} because {locked_flag} was passed to prevent this\\n\\\n             help: to generate the lock file without accessing the network, \\\n             remove the {locked_flag} flag and use --offline instead.\"\n        );\n    }\n\n    // While we're updating the lock file anyway go ahead and update its\n    // encoding to whatever the latest default is. That way we can slowly roll\n    // out lock file updates as they're otherwise already updated, and changes\n    // which don't touch dependencies won't seemingly spuriously update the lock\n    // file.\n    let default_version = ResolveVersion::with_rust_version(ws.lowest_rust_version());\n    let current_version = resolve.version();\n    let next_lockfile_bump = ws.gctx().cli_unstable().next_lockfile_bump;\n    tracing::debug!(\"lockfile - current: {current_version:?}, default: {default_version:?}\");\n\n    if current_version < default_version {\n        resolve.set_version(default_version);\n        out = serialize_resolve(resolve, orig.as_deref());\n    } else if current_version > ResolveVersion::max_stable() && !next_lockfile_bump {\n        // The next version hasn't yet stabilized.\n        anyhow::bail!(\"lock file version `{current_version:?}` requires `-Znext-lockfile-bump`\")\n    }\n\n    if !lock_root.as_path_unlocked().exists() {\n        lock_root.create_dir()?;\n    }\n\n    // Ok, if that didn't work just write it out\n    lock_root\n        .open_rw_exclusive_create(LOCKFILE_NAME, ws.gctx(), \"Cargo.lock file\")\n        .and_then(|mut f| {\n            f.file().set_len(0)?;\n            f.write_all(out.as_bytes())?;\n            Ok(())\n        })\n        .with_context(|| {\n            format!(\n                \"failed to write {}\",\n                lock_root.as_path_unlocked().join(LOCKFILE_NAME).display()\n            )\n        })?;\n    Ok(true)\n}\n\nfn resolve_to_string_orig(\n    ws: &Workspace<'_>,\n    resolve: &Resolve,\n) -> (Option<String>, String, Filesystem) {\n    // Load the original lock file if it exists.\n    let lock_root = ws.lock_root();\n    let orig = lock_root.open_ro_shared(LOCKFILE_NAME, ws.gctx(), \"Cargo.lock file\");\n    let orig = orig.and_then(|mut f| {\n        let mut s = String::new();\n        f.read_to_string(&mut s)?;\n        Ok(s)\n    });\n    let out = serialize_resolve(resolve, orig.as_deref().ok());\n    (orig.ok(), out, lock_root)\n}\n\n#[tracing::instrument(skip_all)]\nfn serialize_resolve(resolve: &Resolve, orig: Option<&str>) -> String {\n    let toml = toml::Table::try_from(resolve).unwrap();\n\n    let mut out = String::new();\n\n    // At the start of the file we notify the reader that the file is generated.\n    // Specifically Phabricator ignores files containing \"@generated\", so we use that.\n    let marker_line = \"# This file is automatically @generated by Cargo.\";\n    let extra_line = \"# It is not intended for manual editing.\";\n    out.push_str(marker_line);\n    out.push('\\n');\n    out.push_str(extra_line);\n    out.push('\\n');\n    // and preserve any other top comments\n    if let Some(orig) = orig {\n        let mut comments = orig.lines().take_while(|line| line.starts_with('#'));\n        if let Some(first) = comments.next() {\n            if first != marker_line {\n                out.push_str(first);\n                out.push('\\n');\n            }\n            if let Some(second) = comments.next() {\n                if second != extra_line {\n                    out.push_str(second);\n                    out.push('\\n');\n                }\n                for line in comments {\n                    out.push_str(line);\n                    out.push('\\n');\n                }\n            }\n        }\n    }\n\n    if let Some(version) = toml.get(\"version\") {\n        out.push_str(&format!(\"version = {}\\n\\n\", version));\n    }\n\n    let deps = toml[\"package\"].as_array().unwrap();\n    for dep in deps {\n        let dep = dep.as_table().unwrap();\n\n        out.push_str(\"[[package]]\\n\");\n        emit_package(dep, &mut out);\n    }\n\n    if let Some(patch) = toml.get(\"patch\") {\n        let list = patch[\"unused\"].as_array().unwrap();\n        for entry in list {\n            out.push_str(\"[[patch.unused]]\\n\");\n            emit_package(entry.as_table().unwrap(), &mut out);\n            out.push('\\n');\n        }\n    }\n\n    if let Some(meta) = toml.get(\"metadata\") {\n        // 1. We need to ensure we print the entire tree, not just the direct members of `metadata`\n        //    (which `toml_edit::Table::to_string` only shows)\n        // 2. We need to ensure all children tables have `metadata.` prefix\n        let meta_table = meta\n            .as_table()\n            .expect(\"validation ensures this is a table\")\n            .clone();\n        let mut meta_doc = toml::Table::new();\n        meta_doc.insert(\"metadata\".to_owned(), toml::Value::Table(meta_table));\n\n        out.push_str(&meta_doc.to_string());\n    }\n\n    // Historical versions of Cargo in the old format accidentally left trailing\n    // blank newlines at the end of files, so we just leave that as-is. For all\n    // encodings going forward, though, we want to be sure that our encoded lock\n    // file doesn't contain any trailing newlines so trim out the extra if\n    // necessary.\n    if resolve.version() >= ResolveVersion::V2 {\n        while out.ends_with(\"\\n\\n\") {\n            out.pop();\n        }\n    }\n    out\n}\n\n#[tracing::instrument(skip_all)]\nfn are_equal_lockfiles(orig: &str, current: &str, ws: &Workspace<'_>) -> bool {\n    // If we want to try and avoid updating the lock file, parse both and\n    // compare them; since this is somewhat expensive, don't do it in the\n    // common case where we can update lock files.\n    if !ws.gctx().lock_update_allowed() {\n        let res: CargoResult<bool> = (|| {\n            let old: TomlLockfile = toml::from_str(orig)?;\n            let new: TomlLockfile = toml::from_str(current)?;\n            Ok(into_resolve(old, orig, ws)? == into_resolve(new, current, ws)?)\n        })();\n        if let Ok(true) = res {\n            return true;\n        }\n    }\n\n    orig.lines().eq(current.lines())\n}\n\nfn emit_package(dep: &toml::Table, out: &mut String) {\n    out.push_str(&format!(\"name = {}\\n\", &dep[\"name\"]));\n    out.push_str(&format!(\"version = {}\\n\", &dep[\"version\"]));\n\n    if dep.contains_key(\"source\") {\n        out.push_str(&format!(\"source = {}\\n\", &dep[\"source\"]));\n    }\n    if dep.contains_key(\"checksum\") {\n        out.push_str(&format!(\"checksum = {}\\n\", &dep[\"checksum\"]));\n    }\n\n    if let Some(s) = dep.get(\"dependencies\") {\n        let slice = s.as_array().unwrap();\n\n        if !slice.is_empty() {\n            out.push_str(\"dependencies = [\\n\");\n\n            for child in slice.iter() {\n                out.push_str(&format!(\" {},\\n\", child));\n            }\n\n            out.push_str(\"]\\n\");\n        }\n        out.push('\\n');\n    } else if dep.contains_key(\"replace\") {\n        out.push_str(&format!(\"replace = {}\\n\\n\", &dep[\"replace\"]));\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/mod.rs",
    "content": "use crate::sources::CRATES_IO_DOMAIN;\n\npub use self::cargo_clean::{CleanContext, CleanOptions, clean};\npub use self::cargo_compile::unit_generator::UnitGenerator;\npub use self::cargo_compile::{CompileFilter, FilterRule, LibRule, Packages};\npub use self::cargo_compile::{\n    CompileOptions, compile, compile_with_exec, compile_ws, create_bcx, print, resolve_all_features,\n};\npub use self::cargo_doc::{DocOptions, OutputFormat, doc};\npub use self::cargo_fetch::{FetchOptions, fetch};\npub use self::cargo_install::{install, install_list};\npub use self::cargo_new::{NewOptions, NewProjectKind, VersionControl, init, new};\npub use self::cargo_output_metadata::{ExportInfo, OutputMetadataOptions, output_metadata};\npub use self::cargo_package::PackageMessageFormat;\npub use self::cargo_package::PackageOpts;\npub use self::cargo_package::check_yanked;\npub use self::cargo_package::package;\npub use self::cargo_pkgid::pkgid;\npub use self::cargo_read_manifest::read_package;\npub use self::cargo_report::rebuilds::ReportRebuildsOptions;\npub use self::cargo_report::rebuilds::report_rebuilds;\npub use self::cargo_report::sessions::ReportSessionsOptions;\npub use self::cargo_report::sessions::report_sessions;\npub use self::cargo_report::timings::ReportTimingsOptions;\npub use self::cargo_report::timings::report_timings;\npub use self::cargo_run::run;\npub use self::cargo_test::{TestOptions, run_benches, run_tests};\npub use self::cargo_uninstall::uninstall;\npub use self::cargo_update::UpdateOptions;\npub use self::cargo_update::generate_lockfile;\npub use self::cargo_update::print_lockfile_changes;\npub use self::cargo_update::update_lockfile;\npub use self::cargo_update::upgrade_manifests;\npub use self::cargo_update::write_manifest_upgrades;\npub use self::common_for_install_and_uninstall::{InstallTracker, resolve_root};\npub use self::fix::{\n    EditionFixMode, FixOptions, fix, fix_edition, fix_exec_rustc, fix_get_proxy_lock_addr,\n};\npub use self::lockfile::{load_pkg_lockfile, resolve_to_string, write_pkg_lockfile};\npub use self::registry::OwnersOptions;\npub use self::registry::PublishOpts;\npub use self::registry::RegistryCredentialConfig;\npub use self::registry::RegistryOrIndex;\npub use self::registry::info;\npub use self::registry::modify_owners;\npub use self::registry::publish;\npub use self::registry::registry_login;\npub use self::registry::registry_logout;\npub use self::registry::search;\npub use self::registry::yank;\npub use self::resolve::{\n    WorkspaceResolve, add_overrides, get_resolved_packages, resolve_with_previous, resolve_ws,\n    resolve_ws_with_opts,\n};\npub use self::vendor::{VendorOptions, vendor};\n\npub mod cargo_add;\nmod cargo_clean;\npub(crate) mod cargo_compile;\npub mod cargo_config;\nmod cargo_doc;\nmod cargo_fetch;\nmod cargo_install;\nmod cargo_new;\nmod cargo_output_metadata;\nmod cargo_package;\nmod cargo_pkgid;\nmod cargo_read_manifest;\npub mod cargo_remove;\npub(crate) mod cargo_report;\nmod cargo_run;\nmod cargo_test;\nmod cargo_uninstall;\nmod cargo_update;\nmod common_for_install_and_uninstall;\nmod fix;\npub(crate) mod lockfile;\npub(crate) mod registry;\npub(crate) mod resolve;\npub mod tree;\nmod vendor;\n\n/// Returns true if the dependency is either git or path, false otherwise\n/// Error if a git/path dep is transitive, but has no version (registry source).\n/// This check is performed on dependencies before publishing or packaging\nfn check_dep_has_version(dep: &crate::core::Dependency, publish: bool) -> crate::CargoResult<bool> {\n    let which = if dep.source_id().is_path() {\n        \"path\"\n    } else if dep.source_id().is_git() {\n        \"git\"\n    } else {\n        return Ok(false);\n    };\n\n    if !dep.specified_req() && dep.is_transitive() {\n        let dep_version_source = dep.registry_id().map_or_else(\n            || CRATES_IO_DOMAIN.to_string(),\n            |registry_id| registry_id.display_registry_name(),\n        );\n        anyhow::bail!(\n            \"all dependencies must have a version requirement specified when {}.\\n\\\n             dependency `{}` does not specify a version\\n\\\n             Note: The {} dependency will use the version from {},\\n\\\n             the `{}` specification will be removed from the dependency declaration.\",\n            if publish { \"publishing\" } else { \"packaging\" },\n            dep.package_name(),\n            if publish { \"published\" } else { \"packaged\" },\n            dep_version_source,\n            which,\n        )\n    }\n    Ok(true)\n}\n"
  },
  {
    "path": "src/cargo/ops/registry/info/mod.rs",
    "content": "//! Implementation of `cargo info`.\n\nuse anyhow::bail;\nuse cargo_util_schemas::core::{PackageIdSpec, PartialVersion};\n\nuse crate::core::registry::PackageRegistry;\nuse crate::core::{Dependency, Package, PackageId, PackageIdSpecQuery, Registry, Workspace};\nuse crate::ops::registry::info::view::pretty_view;\nuse crate::ops::registry::{RegistryOrIndex, RegistrySourceIds, get_source_id_with_package_id};\nuse crate::ops::resolve_ws;\nuse crate::sources::source::QueryKind;\nuse crate::sources::{IndexSummary, SourceConfigMap};\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::command_prelude::root_manifest;\nuse crate::{CargoResult, GlobalContext};\n\nmod view;\n\npub fn info(\n    spec: &PackageIdSpec,\n    gctx: &GlobalContext,\n    reg_or_index: Option<RegistryOrIndex>,\n    explicit_registry: bool,\n) -> CargoResult<()> {\n    let source_config = SourceConfigMap::new(gctx)?;\n    let mut registry = PackageRegistry::new_with_source_config(gctx, source_config)?;\n    // Make sure we get the lock before we download anything.\n    let _lock = gctx.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n    registry.lock_patches();\n\n    // If we can find it in workspace, use it as a specific version.\n    let nearest_manifest_path = root_manifest(None, gctx).ok();\n    let ws = nearest_manifest_path\n        .as_ref()\n        .and_then(|root| Workspace::new(root, gctx).ok());\n    validate_locked_and_frozen_options(ws.is_some(), gctx)?;\n    let nearest_package = ws.as_ref().and_then(|ws| {\n        nearest_manifest_path\n            .as_ref()\n            .and_then(|path| ws.members().find(|p| p.manifest_path() == path))\n    });\n    let (mut package_id, is_member) = find_pkgid_in_ws(nearest_package, ws.as_ref(), spec);\n\n    // If a local package exists and no explicit registry/index was provided,\n    // prefer the local package over the default registry\n    let reg_or_index_to_use = if package_id.is_some() && !explicit_registry {\n        None\n    } else {\n        reg_or_index.as_ref()\n    };\n\n    let (use_package_source_id, source_ids) =\n        get_source_id_with_package_id(gctx, package_id, reg_or_index_to_use)?;\n    // If we don't use the package's source, we need to query the package ID from the specified registry.\n    if !use_package_source_id {\n        package_id = None;\n    }\n\n    let msrv_from_nearest_manifest_path_or_ws =\n        try_get_msrv_from_nearest_manifest_or_ws(nearest_package, ws.as_ref());\n    // If the workspace does not have a specific Rust version,\n    // or if the command is not called within the workspace, then fallback to the global Rust version.\n    let rustc_version = match msrv_from_nearest_manifest_path_or_ws {\n        Some(msrv) => msrv,\n        None => {\n            let current_rustc = gctx.load_global_rustc(ws.as_ref())?.version;\n            // Remove any pre-release identifiers for easier comparison.\n            // Otherwise, the MSRV check will fail if the current Rust version is a nightly or beta version.\n            semver::Version::new(\n                current_rustc.major,\n                current_rustc.minor,\n                current_rustc.patch,\n            )\n            .into()\n        }\n    };\n    // Only suggest cargo tree command when the package is not a workspace member.\n    // For workspace members, `cargo tree --package <SPEC> --invert` is useless. It only prints itself.\n    let suggest_cargo_tree_command = package_id.is_some() && !is_member;\n\n    let (summaries, normalized_name) = query_summaries(spec, &mut registry, &source_ids)?;\n    let normalized_spec = match normalized_name {\n        Some(name) if name != spec.name() => {\n            let mut normalized_spec = PackageIdSpec::new(name);\n\n            if let Some(version) = spec.partial_version().cloned() {\n                normalized_spec = normalized_spec.with_version(version);\n            }\n\n            if let Some(url) = spec.url().cloned() {\n                normalized_spec = normalized_spec.with_url(url);\n            }\n\n            if let Some(kind) = spec.kind().cloned() {\n                normalized_spec = normalized_spec.with_kind(kind);\n            }\n\n            normalized_spec\n        }\n        _ => spec.clone(),\n    };\n    let package_id = match package_id {\n        Some(id) => id,\n        None => find_pkgid_in_summaries(&summaries, &normalized_spec, &rustc_version, &source_ids)?,\n    };\n\n    if package_id.name() != spec.name() {\n        gctx.shell().warn(format!(\n            \"translating `{}` to `{}`\",\n            spec.name(),\n            package_id.name(),\n        ))?;\n    }\n\n    let package = registry.get(&[package_id])?;\n    let package = package.get_one(package_id)?;\n    pretty_view(package, &summaries, suggest_cargo_tree_command, gctx)?;\n\n    Ok(())\n}\n\nfn find_pkgid_in_ws(\n    nearest_package: Option<&Package>,\n    ws: Option<&Workspace<'_>>,\n    spec: &PackageIdSpec,\n) -> (Option<PackageId>, bool) {\n    let Some(ws) = ws else {\n        return (None, false);\n    };\n\n    if let Some(member) = ws.members().find(|p| spec.matches(p.package_id())) {\n        return (Some(member.package_id()), true);\n    }\n\n    let Ok((_, resolve)) = resolve_ws(ws, false) else {\n        return (None, false);\n    };\n\n    if let Some(package_id) = nearest_package\n        .map(|p| p.package_id())\n        .into_iter()\n        .flat_map(|p| resolve.deps(p))\n        .map(|(p, _)| p)\n        .filter(|&p| spec.matches(p))\n        .max_by_key(|&p| p.version())\n    {\n        return (Some(package_id), false);\n    }\n\n    if let Some(package_id) = ws\n        .members()\n        .map(|p| p.package_id())\n        .flat_map(|p| resolve.deps(p))\n        .map(|(p, _)| p)\n        .filter(|&p| spec.matches(p))\n        .max_by_key(|&p| p.version())\n    {\n        return (Some(package_id), false);\n    }\n\n    if let Some(package_id) = resolve\n        .iter()\n        .filter(|&p| spec.matches(p))\n        .max_by_key(|&p| p.version())\n    {\n        return (Some(package_id), false);\n    }\n\n    (None, false)\n}\n\nfn find_pkgid_in_summaries(\n    summaries: &[IndexSummary],\n    normalized_spec: &PackageIdSpec,\n    rustc_version: &PartialVersion,\n    source_ids: &RegistrySourceIds,\n) -> CargoResult<PackageId> {\n    let summary = summaries\n        .iter()\n        .filter(|s| normalized_spec.matches(s.package_id()))\n        .max_by(|s1, s2| {\n            // Check the MSRV compatibility.\n            let s1_matches = s1\n                .as_summary()\n                .rust_version()\n                .map(|v| v.is_compatible_with(rustc_version))\n                .unwrap_or_else(|| false);\n            let s2_matches = s2\n                .as_summary()\n                .rust_version()\n                .map(|v| v.is_compatible_with(rustc_version))\n                .unwrap_or_else(|| false);\n            // MSRV compatible version is preferred.\n            match (s1_matches, s2_matches) {\n                (true, false) => std::cmp::Ordering::Greater,\n                (false, true) => std::cmp::Ordering::Less,\n                // If both summaries match the current Rust version or neither do, try to\n                // pick the latest version.\n                _ => s1.package_id().version().cmp(s2.package_id().version()),\n            }\n        });\n\n    match summary {\n        Some(summary) => Ok(summary.package_id()),\n        None => {\n            anyhow::bail!(\n                \"could not find `{}` in registry `{}`\",\n                normalized_spec,\n                source_ids.original.url()\n            )\n        }\n    }\n}\n\nfn query_summaries(\n    spec: &PackageIdSpec,\n    registry: &mut PackageRegistry<'_>,\n    source_ids: &RegistrySourceIds,\n) -> CargoResult<(Vec<IndexSummary>, Option<String>)> {\n    // Query without version requirement to get all index summaries.\n    let dep = Dependency::parse(spec.name(), None, source_ids.original)?;\n    let results = loop {\n        // Use normalized crate name lookup for user-provided package names.\n        match registry.query_vec(&dep, QueryKind::Normalized) {\n            std::task::Poll::Ready(res) => {\n                break res?;\n            }\n            std::task::Poll::Pending => registry.block_until_ready()?,\n        }\n    };\n\n    let normalized_name = results.first().map(|s| s.package_id().name().to_string());\n\n    Ok((results, normalized_name))\n}\n\nfn validate_locked_and_frozen_options(\n    in_workspace: bool,\n    gctx: &GlobalContext,\n) -> Result<(), anyhow::Error> {\n    // Only in workspace, we can use --frozen or --locked.\n    if !in_workspace {\n        if let Some(locked_flag) = gctx.locked_flag() {\n            bail!(\"the option `{locked_flag}` can only be used within a workspace\");\n        }\n    }\n    Ok(())\n}\n\nfn try_get_msrv_from_nearest_manifest_or_ws(\n    nearest_package: Option<&Package>,\n    ws: Option<&Workspace<'_>>,\n) -> Option<PartialVersion> {\n    // Try to get the MSRV from the nearest manifest.\n    let rust_version = nearest_package.and_then(|p| p.rust_version().map(|v| v.to_partial()));\n    // If the nearest manifest does not have a specific Rust version, try to get it from the workspace.\n    rust_version.or_else(|| ws.and_then(|ws| ws.lowest_rust_version().map(|v| v.to_partial())))\n}\n"
  },
  {
    "path": "src/cargo/ops/registry/info/view.rs",
    "content": "use std::collections::HashMap;\nuse std::io::Write;\n\nuse crate::core::Shell;\nuse crate::util::style::{CONTEXT, ERROR, HEADER, LITERAL, NOP, WARN};\nuse crate::{\n    CargoResult, GlobalContext,\n    core::{\n        Dependency, FeatureMap, Package, PackageId, SourceId, dependency::DepKind, shell::Verbosity,\n    },\n    sources::IndexSummary,\n    util::interning::InternedString,\n};\n\n// Pretty print the package information.\npub(super) fn pretty_view(\n    package: &Package,\n    summaries: &[IndexSummary],\n    suggest_cargo_tree_command: bool,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let summary = package.manifest().summary();\n    let package_id = summary.package_id();\n    let metadata = package.manifest().metadata();\n    let is_package_from_crates_io = summary.source_id().is_crates_io();\n    let header = HEADER;\n    let error = ERROR;\n    let warn = WARN;\n    let context = CONTEXT;\n\n    let mut shell = gctx.shell();\n    let verbosity = shell.verbosity();\n    write!(shell.out(), \"{header}{}{header:#}\", package_id.name())?;\n    if !metadata.keywords.is_empty() {\n        let message = if is_package_from_crates_io {\n            metadata\n                .keywords\n                .iter()\n                .map(|keyword| {\n                    let link = shell.out_hyperlink(format!(\"https://crates.io/keywords/{keyword}\"));\n                    format!(\"{link}#{keyword}{link:#}\")\n                })\n                .collect::<Vec<_>>()\n                .join(\" \")\n        } else {\n            format!(\"#{}\", metadata.keywords.join(\" #\"))\n        };\n        write!(shell.out(), \" {context}{message}{context:#}\")?;\n    }\n\n    let stdout = shell.out();\n    writeln!(stdout)?;\n    if let Some(ref description) = metadata.description {\n        writeln!(stdout, \"{}\", description.trim_end())?;\n    }\n    write!(\n        stdout,\n        \"{header}version:{header:#} {}\",\n        package_id.version()\n    )?;\n    // Add a warning message to stdout if the following conditions are met:\n    // 1. The package version is not the latest available version.\n    // 2. The package source is not crates.io.\n    match (\n        summaries.iter().max_by_key(|s| s.as_summary().version()),\n        is_package_from_crates_io,\n    ) {\n        (Some(latest), false) if latest.as_summary().version() != package_id.version() => {\n            write!(\n                stdout,\n                \" {warn}(latest {} {warn:#}{context}from {}{context:#}{warn}){warn:#}\",\n                latest.as_summary().version(),\n                pretty_source(summary.source_id(), gctx)\n            )?;\n        }\n        (Some(latest), true) if latest.as_summary().version() != package_id.version() => {\n            write!(\n                stdout,\n                \" {warn}(latest {}){warn:#}\",\n                latest.as_summary().version(),\n            )?;\n        }\n        (_, false) => {\n            write!(\n                stdout,\n                \" {context}(from {}){context:#}\",\n                pretty_source(summary.source_id(), gctx)\n            )?;\n        }\n        (_, true) => {}\n    }\n    writeln!(stdout)?;\n    writeln!(\n        stdout,\n        \"{header}license:{header:#} {}\",\n        metadata\n            .license\n            .clone()\n            .unwrap_or_else(|| format!(\"{error}unknown{error:#}\"))\n    )?;\n    // TODO: color MSRV as a warning if newer than either the \"workspace\" MSRV or `rustc --version`\n    writeln!(\n        stdout,\n        \"{header}rust-version:{header:#} {}\",\n        metadata\n            .rust_version\n            .as_ref()\n            .map(|v| v.to_string())\n            .unwrap_or_else(|| format!(\"{warn}unknown{warn:#}\"))\n    )?;\n    if let Some(ref link) = metadata.documentation.clone().or_else(|| {\n        is_package_from_crates_io.then(|| {\n            format!(\n                \"https://docs.rs/{name}/{version}\",\n                name = package_id.name(),\n                version = package_id.version()\n            )\n        })\n    }) {\n        writeln!(stdout, \"{header}documentation:{header:#} {link}\")?;\n    }\n    if let Some(ref link) = metadata.homepage {\n        writeln!(stdout, \"{header}homepage:{header:#} {link}\")?;\n    }\n    if let Some(ref link) = metadata.repository {\n        writeln!(stdout, \"{header}repository:{header:#} {link}\")?;\n    }\n    // Only print the crates.io link if the package is from crates.io.\n    if is_package_from_crates_io {\n        writeln!(\n            stdout,\n            \"{header}crates.io:{header:#} https://crates.io/crates/{}/{}\",\n            package_id.name(),\n            package_id.version()\n        )?;\n    }\n\n    let activated = &[\"default\".into()];\n    let resolved_features = resolve_features(activated, summary.features());\n    pretty_features(\n        resolved_features.clone(),\n        summary.features(),\n        verbosity,\n        stdout,\n    )?;\n\n    pretty_deps(\n        package,\n        &resolved_features,\n        summary.features(),\n        verbosity,\n        stdout,\n        gctx,\n    )?;\n\n    if suggest_cargo_tree_command {\n        suggest_cargo_tree(package_id, &mut shell)?;\n    }\n\n    Ok(())\n}\n\nfn pretty_source(source: SourceId, ctx: &GlobalContext) -> String {\n    if let Some(relpath) = source\n        .local_path()\n        .and_then(|path| pathdiff::diff_paths(path, ctx.cwd()))\n    {\n        let path = std::path::Path::new(\".\").join(relpath);\n        path.display().to_string()\n    } else {\n        source.to_string()\n    }\n}\n\nfn pretty_deps(\n    package: &Package,\n    resolved_features: &[(InternedString, FeatureStatus)],\n    features: &FeatureMap,\n    verbosity: Verbosity,\n    stdout: &mut dyn Write,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    match verbosity {\n        Verbosity::Quiet | Verbosity::Normal => {\n            return Ok(());\n        }\n        Verbosity::Verbose => {}\n    }\n\n    let header = HEADER;\n\n    let dependencies = package\n        .dependencies()\n        .iter()\n        .filter(|d| d.kind() == DepKind::Normal)\n        .collect::<Vec<_>>();\n    if !dependencies.is_empty() {\n        writeln!(stdout, \"{header}dependencies:{header:#}\")?;\n        print_deps(dependencies, resolved_features, features, stdout, gctx)?;\n    }\n\n    let build_dependencies = package\n        .dependencies()\n        .iter()\n        .filter(|d| d.kind() == DepKind::Build)\n        .collect::<Vec<_>>();\n    if !build_dependencies.is_empty() {\n        writeln!(stdout, \"{header}build-dependencies:{header:#}\")?;\n        print_deps(\n            build_dependencies,\n            resolved_features,\n            features,\n            stdout,\n            gctx,\n        )?;\n    }\n\n    Ok(())\n}\n\nfn print_deps(\n    dependencies: Vec<&Dependency>,\n    resolved_features: &[(InternedString, FeatureStatus)],\n    features: &FeatureMap,\n    stdout: &mut dyn Write,\n    gctx: &GlobalContext,\n) -> Result<(), anyhow::Error> {\n    let enabled_by_user = HEADER;\n    let enabled = NOP;\n    let disabled = anstyle::Style::new() | anstyle::Effects::DIMMED;\n\n    let mut dependencies = dependencies\n        .into_iter()\n        .map(|dependency| {\n            let status = if !dependency.is_optional() {\n                FeatureStatus::EnabledByUser\n            } else if resolved_features\n                .iter()\n                .filter(|(_, s)| !s.is_disabled())\n                .filter_map(|(n, _)| features.get(n))\n                .flatten()\n                .filter_map(|f| match f {\n                    crate::core::FeatureValue::Feature(_) => None,\n                    crate::core::FeatureValue::Dep { dep_name } => Some(dep_name),\n                    crate::core::FeatureValue::DepFeature { dep_name, weak, .. } if *weak => {\n                        Some(dep_name)\n                    }\n                    crate::core::FeatureValue::DepFeature { .. } => None,\n                })\n                .any(|dep_name| *dep_name == dependency.name_in_toml())\n            {\n                FeatureStatus::Enabled\n            } else {\n                FeatureStatus::Disabled\n            };\n            (dependency, status)\n        })\n        .collect::<Vec<_>>();\n    dependencies.sort_by_key(|(d, s)| (*s, d.package_name()));\n    for (dependency, status) in dependencies {\n        // 1. Only print the version requirement if it is a registry dependency.\n        // 2. Only print the source if it is not a registry dependency.\n        // For example: `bar (./crates/bar)` or `bar@=1.2.3`.\n        let (req, source) = if dependency.source_id().is_registry() {\n            (\n                format!(\"@{}\", pretty_req(dependency.version_req())),\n                String::new(),\n            )\n        } else {\n            (\n                String::new(),\n                format!(\" ({})\", pretty_source(dependency.source_id(), gctx)),\n            )\n        };\n\n        if status == FeatureStatus::EnabledByUser {\n            write!(stdout, \" {enabled_by_user}+{enabled_by_user:#}\")?;\n        } else {\n            write!(stdout, \"  \")?;\n        }\n        let style = match status {\n            FeatureStatus::EnabledByUser | FeatureStatus::Enabled => enabled,\n            FeatureStatus::Disabled => disabled,\n        };\n        writeln!(\n            stdout,\n            \"{style}{}{}{}{style:#}\",\n            dependency.package_name(),\n            req,\n            source\n        )?;\n    }\n    Ok(())\n}\n\nfn pretty_req(req: &crate::util::OptVersionReq) -> String {\n    let mut rendered = req.to_string();\n    let strip_prefix = match req {\n        crate::util::OptVersionReq::Any => false,\n        crate::util::OptVersionReq::Req(req)\n        | crate::util::OptVersionReq::Locked(_, req)\n        | crate::util::OptVersionReq::Precise(_, req) => {\n            req.comparators.len() == 1 && rendered.starts_with('^')\n        }\n    };\n    if strip_prefix {\n        rendered.remove(0);\n        rendered\n    } else {\n        rendered\n    }\n}\n\nfn pretty_features(\n    resolved_features: Vec<(InternedString, FeatureStatus)>,\n    features: &FeatureMap,\n    verbosity: Verbosity,\n    stdout: &mut dyn Write,\n) -> CargoResult<()> {\n    let header = HEADER;\n    let enabled_by_user = HEADER;\n    let enabled = NOP;\n    let disabled = anstyle::Style::new() | anstyle::Effects::DIMMED;\n    let summary = anstyle::Style::new() | anstyle::Effects::ITALIC;\n\n    // If there are no features, return early.\n    let margin = features\n        .iter()\n        .map(|(name, _)| name.len())\n        .max()\n        .unwrap_or_default();\n    if margin == 0 {\n        return Ok(());\n    }\n\n    writeln!(stdout, \"{header}features:{header:#}\")?;\n\n    const MAX_FEATURE_PRINTS: usize = 30;\n    let total_activated = resolved_features\n        .iter()\n        .filter(|(_, s)| !s.is_disabled())\n        .count();\n    let total_deactivated = resolved_features\n        .iter()\n        .filter(|(_, s)| s.is_disabled())\n        .count();\n    let show_all = match verbosity {\n        Verbosity::Quiet | Verbosity::Normal => false,\n        Verbosity::Verbose => true,\n    };\n    let show_activated = total_activated <= MAX_FEATURE_PRINTS || show_all;\n    let show_deactivated = (total_activated + total_deactivated) <= MAX_FEATURE_PRINTS || show_all;\n    for (current, status, current_activated) in resolved_features\n        .iter()\n        .map(|(n, s)| (n, s, features.get(n).unwrap()))\n    {\n        if !status.is_disabled() && !show_activated {\n            continue;\n        }\n        if status.is_disabled() && !show_deactivated {\n            continue;\n        }\n        if *status == FeatureStatus::EnabledByUser {\n            write!(stdout, \" {enabled_by_user}+{enabled_by_user:#}\")?;\n        } else {\n            write!(stdout, \"  \")?;\n        }\n        let style = match status {\n            FeatureStatus::EnabledByUser | FeatureStatus::Enabled => enabled,\n            FeatureStatus::Disabled => disabled,\n        };\n        writeln!(\n            stdout,\n            \"{style}{current: <margin$}{style:#} = [{features}]\",\n            features = current_activated\n                .iter()\n                .map(|s| format!(\"{style}{s}{style:#}\"))\n                .collect::<Vec<String>>()\n                .join(\", \")\n        )?;\n    }\n    if !show_activated {\n        writeln!(\n            stdout,\n            \"  {summary}{total_activated} activated features{summary:#}\",\n        )?;\n    }\n    if !show_deactivated {\n        writeln!(\n            stdout,\n            \"  {summary}{total_deactivated} deactivated features{summary:#}\",\n        )?;\n    }\n\n    Ok(())\n}\n\n// Suggest the cargo tree command to view the dependency tree.\nfn suggest_cargo_tree(package_id: PackageId, shell: &mut Shell) -> CargoResult<()> {\n    let literal = LITERAL;\n\n    shell.note(format_args!(\n        \"to see how you depend on {name}, run `{literal}cargo tree --invert {name}@{version}{literal:#}`\",\n        name = package_id.name(),\n        version = package_id.version(),\n    ))\n}\n\n#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]\nenum FeatureStatus {\n    EnabledByUser,\n    Enabled,\n    Disabled,\n}\n\nimpl FeatureStatus {\n    fn is_disabled(&self) -> bool {\n        *self == FeatureStatus::Disabled\n    }\n}\n\nfn resolve_features(\n    explicit: &[InternedString],\n    features: &FeatureMap,\n) -> Vec<(InternedString, FeatureStatus)> {\n    let mut resolved = features\n        .keys()\n        .cloned()\n        .map(|n| {\n            if explicit.contains(&n) {\n                (n, FeatureStatus::EnabledByUser)\n            } else {\n                (n, FeatureStatus::Disabled)\n            }\n        })\n        .collect::<HashMap<_, _>>();\n\n    let mut activated_queue = explicit.to_vec();\n\n    while let Some(current) = activated_queue.pop() {\n        let Some(current_activated) = features.get(&current) else {\n            // `default` isn't always present\n            continue;\n        };\n        for activated in current_activated.iter().rev().filter_map(|f| match f {\n            crate::core::FeatureValue::Feature(name) => Some(name),\n            crate::core::FeatureValue::Dep { .. }\n            | crate::core::FeatureValue::DepFeature { .. } => None,\n        }) {\n            let Some(status) = resolved.get_mut(activated) else {\n                continue;\n            };\n            if status.is_disabled() {\n                *status = FeatureStatus::Enabled;\n                activated_queue.push(*activated);\n            }\n        }\n    }\n\n    let mut resolved: Vec<_> = resolved.into_iter().collect();\n    resolved.sort_by_key(|(name, status)| (*status, *name));\n    resolved\n}\n"
  },
  {
    "path": "src/cargo/ops/registry/login.rs",
    "content": "//! Interacts with the registry [login API][1].\n//!\n//! This doesn't really call any web API at this moment. Instead, it's just an\n//! operation for `cargo login`.\n//!\n//! [1]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#login\n\nuse std::io::IsTerminal;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::util::auth;\nuse crate::util::auth::AuthorizationError;\nuse cargo_credential::LoginOptions;\nuse cargo_credential::Secret;\n\nuse super::RegistryOrIndex;\nuse super::get_source_id;\nuse super::registry;\n\npub fn registry_login(\n    gctx: &GlobalContext,\n    token_from_cmdline: Option<Secret<&str>>,\n    reg_or_index: Option<&RegistryOrIndex>,\n    args: &[&str],\n) -> CargoResult<()> {\n    let source_ids = get_source_id(gctx, reg_or_index)?;\n\n    let login_url = match registry(\n        gctx,\n        &source_ids,\n        token_from_cmdline.clone(),\n        reg_or_index,\n        false,\n        None,\n    ) {\n        Ok((registry, _)) => Some(format!(\"{}/me\", registry.host())),\n        Err(e) if e.is::<AuthorizationError>() => e\n            .downcast::<AuthorizationError>()\n            .unwrap()\n            .login_url\n            .map(|u| u.to_string()),\n        Err(e) => return Err(e),\n    };\n\n    let mut token_from_stdin = None;\n    let token = token_from_cmdline.or_else(|| {\n        if !std::io::stdin().is_terminal() {\n            let token = cargo_credential::read_line().unwrap_or_default();\n            if !token.is_empty() {\n                token_from_stdin = Some(token);\n            }\n        }\n        token_from_stdin.as_deref().map(Secret::from)\n    });\n\n    let options = LoginOptions {\n        token,\n        login_url: login_url.as_deref(),\n    };\n\n    auth::login(gctx, &source_ids.original, options, args)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/ops/registry/logout.rs",
    "content": "//! Interacts with the registry logout.\n//!\n//! There is no web API for logout at this moment. Instead, it's just an\n//! operation for `cargo logout`.\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::util::auth;\n\nuse super::RegistryOrIndex;\nuse super::get_source_id;\n\npub fn registry_logout(\n    gctx: &GlobalContext,\n    reg_or_index: Option<RegistryOrIndex>,\n) -> CargoResult<()> {\n    let source_ids = get_source_id(gctx, reg_or_index.as_ref())?;\n    auth::logout(gctx, &source_ids.original)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/ops/registry/mod.rs",
    "content": "//! Operations that interact with the [registry web API][1].\n//!\n//! [1]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html\n\nmod info;\nmod login;\nmod logout;\nmod owner;\nmod publish;\nmod search;\nmod yank;\n\nuse std::collections::HashSet;\nuse std::str;\nuse std::task::Poll;\n\nuse anyhow::{Context as _, bail, format_err};\nuse cargo_credential::{Operation, Secret};\nuse crates_io::Registry;\nuse url::Url;\n\nuse crate::core::{Package, PackageId, SourceId};\nuse crate::sources::source::Source;\nuse crate::sources::{RegistrySource, SourceConfigMap};\nuse crate::util::auth;\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::context::{GlobalContext, PathAndArgs};\nuse crate::util::errors::CargoResult;\nuse crate::util::network::http::http_handle;\n\npub use self::info::info;\npub use self::login::registry_login;\npub use self::logout::registry_logout;\npub use self::owner::OwnersOptions;\npub use self::owner::modify_owners;\npub use self::publish::PublishOpts;\npub use self::publish::publish;\npub use self::search::search;\npub use self::yank::yank;\n\npub(crate) use self::publish::prepare_transmit;\n\n/// Represents either `--registry` or `--index` argument, which is mutually exclusive.\n#[derive(Debug, Clone)]\npub enum RegistryOrIndex {\n    Registry(String),\n    Index(Url),\n}\n\nimpl RegistryOrIndex {\n    fn is_index(&self) -> bool {\n        matches!(self, RegistryOrIndex::Index(..))\n    }\n}\n\n/// Registry settings loaded from config files.\n///\n/// This is loaded based on the `--registry` flag and the config settings.\n#[derive(Debug, PartialEq)]\npub enum RegistryCredentialConfig {\n    None,\n    /// The authentication token.\n    Token(Secret<String>),\n    /// Process used for fetching a token.\n    Process(Vec<PathAndArgs>),\n    /// Secret Key and subject for Asymmetric tokens.\n    AsymmetricKey((Secret<String>, Option<String>)),\n}\n\nimpl RegistryCredentialConfig {\n    /// Returns `true` if the credential is [`None`].\n    ///\n    /// [`None`]: Self::None\n    pub fn is_none(&self) -> bool {\n        matches!(self, Self::None)\n    }\n    /// Returns `true` if the credential is [`Token`].\n    ///\n    /// [`Token`]: Self::Token\n    pub fn is_token(&self) -> bool {\n        matches!(self, Self::Token(..))\n    }\n    /// Returns `true` if the credential is [`AsymmetricKey`].\n    ///\n    /// [`AsymmetricKey`]: RegistryCredentialConfig::AsymmetricKey\n    pub fn is_asymmetric_key(&self) -> bool {\n        matches!(self, Self::AsymmetricKey(..))\n    }\n    pub fn as_token(&self) -> Option<Secret<&str>> {\n        if let Self::Token(v) = self {\n            Some(v.as_deref())\n        } else {\n            None\n        }\n    }\n    pub fn as_process(&self) -> Option<&Vec<PathAndArgs>> {\n        if let Self::Process(v) = self {\n            Some(v)\n        } else {\n            None\n        }\n    }\n    pub fn as_asymmetric_key(&self) -> Option<&(Secret<String>, Option<String>)> {\n        if let Self::AsymmetricKey(v) = self {\n            Some(v)\n        } else {\n            None\n        }\n    }\n}\n\n/// Returns the `Registry` and `Source` based on command-line and config settings.\n///\n/// * `source_ids`: The source IDs for the registry. It contains the original source ID and\n///   the replacement source ID.\n/// * `token_from_cmdline`: The token from the command-line. If not set, uses the token\n///   from the config.\n/// * `index`: The index URL from the command-line.\n/// * `registry`: The registry name from the command-line. If neither\n///   `registry`, or `index` are set, then uses `crates-io`.\n/// * `force_update`: If `true`, forces the index to be updated.\n/// * `token_required`: If `true`, the token will be set.\nfn registry<'gctx>(\n    gctx: &'gctx GlobalContext,\n    source_ids: &RegistrySourceIds,\n    token_from_cmdline: Option<Secret<&str>>,\n    reg_or_index: Option<&RegistryOrIndex>,\n    force_update: bool,\n    token_required: Option<Operation<'_>>,\n) -> CargoResult<(Registry, RegistrySource<'gctx>)> {\n    let is_index = reg_or_index.map(|v| v.is_index()).unwrap_or_default();\n    if is_index && token_required.is_some() && token_from_cmdline.is_none() {\n        bail!(\"command-line argument --index requires --token to be specified\");\n    }\n    if let Some(token) = token_from_cmdline {\n        auth::cache_token_from_commandline(gctx, &source_ids.original, token);\n    }\n\n    let mut src = RegistrySource::remote(source_ids.replacement, &HashSet::new(), gctx)?;\n    let cfg = {\n        let _lock = gctx.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n        // Only update the index if `force_update` is set.\n        if force_update {\n            src.invalidate_cache()\n        }\n        let cfg = loop {\n            match src.config()? {\n                Poll::Pending => src\n                    .block_until_ready()\n                    .with_context(|| format!(\"failed to update {}\", source_ids.replacement))?,\n                Poll::Ready(cfg) => break cfg,\n            }\n        };\n        cfg.expect(\"remote registries must have config\")\n    };\n    let api_host = cfg\n        .api\n        .ok_or_else(|| format_err!(\"{} does not support API commands\", source_ids.replacement))?;\n    let token = if token_required.is_some() || cfg.auth_required {\n        let operation = token_required.unwrap_or(Operation::Read);\n        Some(auth::auth_token(\n            gctx,\n            &source_ids.original,\n            None,\n            operation,\n            vec![],\n            false,\n        )?)\n    } else {\n        None\n    };\n    let handle = http_handle(gctx)?;\n    Ok((\n        Registry::new_handle(api_host, token, handle, cfg.auth_required),\n        src,\n    ))\n}\n\n/// Gets the `SourceId` for an index or registry setting.\n///\n/// The `index` and `reg` values are from the command-line or config settings.\n/// If both are None, and no source-replacement is configured, returns the source for crates.io.\n/// If both are None, and source replacement is configured, returns an error.\n///\n/// The source for crates.io may be GitHub, index.crates.io, or a test-only registry depending\n/// on configuration.\n///\n/// If `reg` is set, source replacement is not followed.\n///\n/// The return value is a pair of `SourceId`s: The first may be a built-in replacement of\n/// crates.io (such as index.crates.io), while the second is always the original source.\npub(crate) fn get_source_id(\n    gctx: &GlobalContext,\n    reg_or_index: Option<&RegistryOrIndex>,\n) -> CargoResult<RegistrySourceIds> {\n    let sid = get_initial_source_id(gctx, reg_or_index)?;\n    let (builtin_replacement_sid, replacement_sid) = get_replacement_source_ids(gctx, sid)?;\n\n    if reg_or_index.is_none() && replacement_sid != builtin_replacement_sid {\n        bail!(gen_replacement_error(replacement_sid));\n    } else {\n        Ok(RegistrySourceIds {\n            original: sid,\n            replacement: builtin_replacement_sid,\n        })\n    }\n}\n\n/// Very similar to [`get_source_id`], but is used when the `package_id` is known.\nfn get_source_id_with_package_id(\n    gctx: &GlobalContext,\n    package_id: Option<PackageId>,\n    reg_or_index: Option<&RegistryOrIndex>,\n) -> CargoResult<(bool, RegistrySourceIds)> {\n    let (use_package_source_id, sid) = match (&reg_or_index, package_id) {\n        (None, Some(package_id)) => (true, package_id.source_id()),\n        (None, None) => (false, SourceId::crates_io(gctx)?),\n        (Some(RegistryOrIndex::Index(url)), None) => (false, SourceId::for_registry(url)?),\n        (Some(RegistryOrIndex::Registry(r)), None) => (false, SourceId::alt_registry(gctx, r)?),\n        (Some(reg_or_index), Some(package_id)) => {\n            let sid = get_initial_source_id_from_registry_or_index(gctx, reg_or_index)?;\n            let package_source_id = package_id.source_id();\n            // 1. Same registry, use the package's source.\n            // 2. Use the package's source if the specified registry is a replacement for the package's source.\n            if sid == package_source_id\n                || is_replacement_for_package_source(gctx, sid, package_source_id)?\n            {\n                (true, package_source_id)\n            } else {\n                (false, sid)\n            }\n        }\n    };\n\n    let (builtin_replacement_sid, replacement_sid) = get_replacement_source_ids(gctx, sid)?;\n\n    if reg_or_index.is_none() && replacement_sid != builtin_replacement_sid {\n        bail!(gen_replacement_error(replacement_sid));\n    } else {\n        Ok((\n            use_package_source_id,\n            RegistrySourceIds {\n                original: sid,\n                replacement: builtin_replacement_sid,\n            },\n        ))\n    }\n}\n\nfn get_initial_source_id(\n    gctx: &GlobalContext,\n    reg_or_index: Option<&RegistryOrIndex>,\n) -> CargoResult<SourceId> {\n    match reg_or_index {\n        None => SourceId::crates_io(gctx),\n        Some(reg_or_index) => get_initial_source_id_from_registry_or_index(gctx, reg_or_index),\n    }\n}\n\nfn get_initial_source_id_from_registry_or_index(\n    gctx: &GlobalContext,\n    reg_or_index: &RegistryOrIndex,\n) -> CargoResult<SourceId> {\n    match reg_or_index {\n        RegistryOrIndex::Index(url) => SourceId::for_registry(url),\n        RegistryOrIndex::Registry(r) => SourceId::alt_registry(gctx, r),\n    }\n}\n\nfn get_replacement_source_ids(\n    gctx: &GlobalContext,\n    sid: SourceId,\n) -> CargoResult<(SourceId, SourceId)> {\n    let builtin_replacement_sid = SourceConfigMap::empty(gctx)?\n        .load(sid, &HashSet::new())?\n        .replaced_source_id();\n    let replacement_sid = SourceConfigMap::new(gctx)?\n        .load(sid, &HashSet::new())?\n        .replaced_source_id();\n    Ok((builtin_replacement_sid, replacement_sid))\n}\n\nfn is_replacement_for_package_source(\n    gctx: &GlobalContext,\n    sid: SourceId,\n    package_source_id: SourceId,\n) -> CargoResult<bool> {\n    let pkg_source_replacement_sid = SourceConfigMap::new(gctx)?\n        .load(package_source_id, &HashSet::new())?\n        .replaced_source_id();\n    Ok(pkg_source_replacement_sid == sid)\n}\n\nfn gen_replacement_error(replacement_sid: SourceId) -> String {\n    // Neither --registry nor --index was passed and the user has configured source-replacement.\n    let error_message = if let Some(replacement_name) = replacement_sid.alt_registry_key() {\n        format!(\n            \"crates-io is replaced with remote registry {};\\ninclude `--registry {}` or `--registry crates-io`\",\n            replacement_name, replacement_name\n        )\n    } else {\n        format!(\n            \"crates-io is replaced with non-remote-registry source {};\\ninclude `--registry crates-io` to use crates.io\",\n            replacement_sid\n        )\n    };\n\n    error_message\n}\n\npub(crate) struct RegistrySourceIds {\n    /// Use when looking up the auth token, or writing out `Cargo.lock`\n    pub(crate) original: SourceId,\n    /// Use when interacting with the source (querying / publishing , etc)\n    ///\n    /// The source for crates.io may be replaced by a built-in source for accessing crates.io with\n    /// the sparse protocol, or a source for the testing framework (when the `replace_crates_io`\n    /// function is used)\n    ///\n    /// User-defined source replacement is not applied.\n    pub(crate) replacement: SourceId,\n}\n\n/// If this set of packages has an unambiguous publish registry, find it.\npub(crate) fn infer_registry(pkgs: &[&Package]) -> CargoResult<Option<RegistryOrIndex>> {\n    // Ignore \"publish = false\" packages while inferring the registry.\n    let publishable_pkgs: Vec<_> = pkgs\n        .iter()\n        .filter(|p| p.publish() != &Some(Vec::new()))\n        .collect();\n\n    let Some((first, rest)) = publishable_pkgs.split_first() else {\n        return Ok(None);\n    };\n\n    // If all packages have the same publish settings, we take that as the default.\n    if rest.iter().all(|p| p.publish() == first.publish()) {\n        match publishable_pkgs[0].publish().as_deref() {\n            Some([unique_pkg_reg]) => {\n                Ok(Some(RegistryOrIndex::Registry(unique_pkg_reg.to_owned())))\n            }\n            None | Some([]) => Ok(None),\n            Some(regs) => {\n                let mut regs: Vec<_> = regs.iter().map(|s| format!(\"\\\"{}\\\"\", s)).collect();\n                regs.sort();\n                regs.dedup();\n                // unwrap: the match block ensures that there's more than one reg.\n                let (last_reg, regs) = regs.split_last().unwrap();\n                bail!(\n                    \"--registry is required to disambiguate between {} or {} registries\",\n                    regs.join(\", \"),\n                    last_reg\n                )\n            }\n        }\n    } else {\n        let common_regs = publishable_pkgs\n            .iter()\n            // `None` means \"all registries\", so drop them instead of including them\n            // in the intersection.\n            .filter_map(|p| p.publish().as_deref())\n            .map(|p| p.iter().collect::<HashSet<_>>())\n            .reduce(|xs, ys| xs.intersection(&ys).cloned().collect())\n            .unwrap_or_default();\n        if common_regs.is_empty() {\n            bail!(\"conflicts between `package.publish` fields in the selected packages\");\n        } else {\n            bail!(\"--registry is required because not all `package.publish` settings agree\",);\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/registry/owner.rs",
    "content": "//! Interacts with the registry [owners API][1].\n//!\n//! [1]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#owners\n\nuse anyhow::Context as _;\nuse cargo_credential::Operation;\nuse cargo_credential::Secret;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Workspace;\nuse crate::drop_print;\nuse crate::drop_println;\nuse crate::util::important_paths::find_root_manifest_for_wd;\n\nuse super::RegistryOrIndex;\n\npub struct OwnersOptions {\n    pub krate: Option<String>,\n    pub token: Option<Secret<String>>,\n    pub reg_or_index: Option<RegistryOrIndex>,\n    pub to_add: Option<Vec<String>>,\n    pub to_remove: Option<Vec<String>>,\n    pub list: bool,\n}\n\npub fn modify_owners(gctx: &GlobalContext, opts: &OwnersOptions) -> CargoResult<()> {\n    let name = match opts.krate {\n        Some(ref name) => name.clone(),\n        None => {\n            let manifest_path = find_root_manifest_for_wd(gctx.cwd())?;\n            let ws = Workspace::new(&manifest_path, gctx)?;\n            ws.current()?.package_id().name().to_string()\n        }\n    };\n\n    let operation = Operation::Owners { name: &name };\n    let source_ids = super::get_source_id(gctx, opts.reg_or_index.as_ref())?;\n    let (mut registry, _) = super::registry(\n        gctx,\n        &source_ids,\n        opts.token.as_ref().map(Secret::as_deref),\n        opts.reg_or_index.as_ref(),\n        true,\n        Some(operation),\n    )?;\n\n    if let Some(ref v) = opts.to_add {\n        let v = v.iter().map(|s| &s[..]).collect::<Vec<_>>();\n        let msg = registry.add_owners(&name, &v).with_context(|| {\n            format!(\n                \"failed to invite owners to crate `{}` on registry at {}\",\n                name,\n                registry.host()\n            )\n        })?;\n\n        gctx.shell().status(\"Owner\", msg)?;\n    }\n\n    if let Some(ref v) = opts.to_remove {\n        let v = v.iter().map(|s| &s[..]).collect::<Vec<_>>();\n        gctx.shell()\n            .status(\"Owner\", format!(\"removing {:?} from crate {}\", v, name))?;\n        registry.remove_owners(&name, &v).with_context(|| {\n            format!(\n                \"failed to remove owners from crate `{}` on registry at {}\",\n                name,\n                registry.host()\n            )\n        })?;\n    }\n\n    if opts.list {\n        let owners = registry.list_owners(&name).with_context(|| {\n            format!(\n                \"failed to list owners of crate `{}` on registry at {}\",\n                name,\n                registry.host()\n            )\n        })?;\n        for owner in owners.iter() {\n            drop_print!(gctx, \"{}\", owner.login);\n            match (owner.name.as_ref(), owner.email.as_ref()) {\n                (Some(name), Some(email)) => drop_println!(gctx, \" ({} <{}>)\", name, email),\n                (Some(s), None) | (None, Some(s)) => drop_println!(gctx, \" ({})\", s),\n                (None, None) => drop_println!(gctx),\n            }\n        }\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/ops/registry/publish.rs",
    "content": "//! Interacts with the registry [publish API][1].\n//!\n//! [1]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#publish\n\nuse std::collections::BTreeMap;\nuse std::collections::BTreeSet;\nuse std::collections::HashMap;\nuse std::collections::HashSet;\nuse std::fs::File;\nuse std::io::Seek;\nuse std::io::SeekFrom;\nuse std::time::Duration;\n\nuse annotate_snippets::Level;\nuse anyhow::Context as _;\nuse anyhow::bail;\nuse cargo_credential::Operation;\nuse cargo_credential::Secret;\nuse cargo_util::paths;\nuse crates_io::NewCrate;\nuse crates_io::NewCrateDependency;\nuse crates_io::Registry;\nuse itertools::Itertools;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::Dependency;\nuse crate::core::Package;\nuse crate::core::PackageId;\nuse crate::core::PackageIdSpecQuery;\nuse crate::core::SourceId;\nuse crate::core::Workspace;\nuse crate::core::dependency::DepKind;\nuse crate::core::manifest::ManifestMetadata;\nuse crate::core::resolver::CliFeatures;\nuse crate::ops;\nuse crate::ops::PackageOpts;\nuse crate::ops::Packages;\nuse crate::ops::RegistryOrIndex;\nuse crate::ops::registry::RegistrySourceIds;\nuse crate::sources::CRATES_IO_REGISTRY;\nuse crate::sources::RegistrySource;\nuse crate::sources::SourceConfigMap;\nuse crate::sources::source::QueryKind;\nuse crate::sources::source::Source;\nuse crate::util::Graph;\nuse crate::util::Progress;\nuse crate::util::ProgressStyle;\nuse crate::util::VersionExt as _;\nuse crate::util::auth;\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::context::JobsConfig;\nuse crate::util::errors::ManifestError;\nuse crate::util::toml::prepare_for_publish;\n\nuse super::super::check_dep_has_version;\n\npub struct PublishOpts<'gctx> {\n    pub gctx: &'gctx GlobalContext,\n    pub token: Option<Secret<String>>,\n    pub reg_or_index: Option<RegistryOrIndex>,\n    pub verify: bool,\n    pub allow_dirty: bool,\n    pub jobs: Option<JobsConfig>,\n    pub keep_going: bool,\n    pub to_publish: ops::Packages,\n    pub targets: Vec<String>,\n    pub dry_run: bool,\n    pub cli_features: CliFeatures,\n}\n\npub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {\n    let specs = opts.to_publish.to_package_id_specs(ws)?;\n\n    let member_ids: Vec<_> = ws.members().map(|p| p.package_id()).collect();\n    // Check that the specs match members.\n    for spec in &specs {\n        spec.query(member_ids.clone())?;\n    }\n    let mut pkgs = ws.members_with_features(&specs, &opts.cli_features)?;\n    // In `members_with_features_old`, it will add \"current\" package (determined by the cwd)\n    // So we need filter\n    pkgs.retain(|(m, _)| specs.iter().any(|spec| spec.matches(m.package_id())));\n\n    let (unpublishable, pkgs): (Vec<_>, Vec<_>) = pkgs\n        .into_iter()\n        .partition(|(pkg, _)| pkg.publish() == &Some(vec![]));\n    // If `--workspace` is passed,\n    // the intent is more like \"publish all publisable packages in this workspace\",\n    // so skip `publish=false` packages.\n    let allow_unpublishable = match &opts.to_publish {\n        Packages::Default => ws.is_virtual(),\n        Packages::All(_) => true,\n        Packages::OptOut(_) => true,\n        Packages::Packages(_) => false,\n    };\n    if !unpublishable.is_empty() && !allow_unpublishable {\n        bail!(\n            \"{} cannot be published.\\n\\\n            `package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish.\",\n            unpublishable\n                .iter()\n                .map(|(pkg, _)| format!(\"`{}`\", pkg.name()))\n                .join(\", \"),\n        );\n    }\n\n    if pkgs.is_empty() {\n        if allow_unpublishable {\n            let n = unpublishable.len();\n            let plural = if n == 1 { \"\" } else { \"s\" };\n            ws.gctx().shell().print_report(\n                &[Level::WARNING\n                    .secondary_title(format!(\n                        \"nothing to publish, but found {n} unpublishable package{plural}\"\n                    ))\n                    .element(Level::HELP.message(\n                        \"to publish packages, set `package.publish` to `true` or a non-empty list\",\n                    ))],\n                false,\n            )?;\n            return Ok(());\n        } else {\n            unreachable!(\"must have at least one publishable package\");\n        }\n    }\n\n    let just_pkgs: Vec<_> = pkgs.iter().map(|p| p.0).collect();\n    let reg_or_index = resolve_registry_or_index(opts, &just_pkgs)?;\n\n    // This is only used to confirm that we can create a token before we build the package.\n    // This causes the credential provider to be called an extra time, but keeps the same order of errors.\n    let source_ids = super::get_source_id(opts.gctx, reg_or_index.as_ref())?;\n    let (mut registry, mut source) = super::registry(\n        opts.gctx,\n        &source_ids,\n        opts.token.as_ref().map(Secret::as_deref),\n        reg_or_index.as_ref(),\n        true,\n        Some(Operation::Read).filter(|_| !opts.dry_run),\n    )?;\n\n    {\n        let _lock = opts\n            .gctx\n            .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n\n        for (pkg, _) in &pkgs {\n            verify_unpublished(pkg, &mut source, &source_ids, opts.dry_run, opts.gctx)?;\n            verify_dependencies(pkg, &registry, source_ids.original).map_err(|err| {\n                ManifestError::new(\n                    err.context(format!(\n                        \"failed to verify manifest at `{}`\",\n                        pkg.manifest_path().display()\n                    )),\n                    pkg.manifest_path().into(),\n                )\n            })?;\n        }\n    }\n\n    let pkg_dep_graph = ops::cargo_package::package_with_dep_graph(\n        ws,\n        &PackageOpts {\n            gctx: opts.gctx,\n            verify: opts.verify,\n            list: false,\n            fmt: ops::PackageMessageFormat::Human,\n            check_metadata: true,\n            allow_dirty: opts.allow_dirty,\n            include_lockfile: true,\n            // `package_with_dep_graph` ignores this field in favor of\n            // the already-resolved list of packages\n            to_package: ops::Packages::Default,\n            targets: opts.targets.clone(),\n            jobs: opts.jobs.clone(),\n            keep_going: opts.keep_going,\n            cli_features: opts.cli_features.clone(),\n            reg_or_index: reg_or_index.clone(),\n            dry_run: opts.dry_run,\n        },\n        pkgs,\n    )?;\n\n    let mut plan = PublishPlan::new(&pkg_dep_graph.graph);\n    // May contains packages from previous rounds as `wait_for_any_publish_confirmation` returns\n    // after it confirms any packages, not all packages, requiring us to handle the rest in the next\n    // iteration.\n    //\n    // As a side effect, any given package's \"effective\" timeout may be much larger.\n    let mut to_confirm = BTreeSet::new();\n\n    // Check for circular dependencies before publishing.\n    if plan.has_cycles() {\n        bail!(\n            \"circular dependency detected while publishing {}\\n\\\n             help: to break a cycle between dev-dependencies \\\n             and other dependencies, remove the version field \\\n             on the dev-dependency so it will be implicitly \\\n             stripped on publish\",\n            package_list(plan.cycle_members(), \"and\")\n        );\n    }\n\n    while !plan.is_empty() {\n        // There might not be any ready package, if the previous confirmations\n        // didn't unlock a new one. For example, if `c` depends on `a` and\n        // `b`, and we uploaded `a` and `b` but only confirmed `a`, then on\n        // the following pass through the outer loop nothing will be ready for\n        // upload.\n        let mut ready = plan.take_ready();\n\n        if ready.is_empty() {\n            // Circular dependencies are caught above, so this indicates a failure\n            // to progress, potentially due to a timeout while waiting for confirmations.\n            return Err(crate::util::internal(format!(\n                \"no packages ready to publish but {} packages remain in plan with {} awaiting confirmation: {}\",\n                plan.len(),\n                to_confirm.len(),\n                package_list(plan.iter(), \"and\")\n            )));\n        }\n\n        while let Some(pkg_id) = ready.pop_first() {\n            let (pkg, (_features, tarball)) = &pkg_dep_graph.packages[&pkg_id];\n            opts.gctx.shell().status(\"Uploading\", pkg.package_id())?;\n\n            if !opts.dry_run {\n                let ver = pkg.version().to_string();\n\n                tarball.file().seek(SeekFrom::Start(0))?;\n                let hash = cargo_util::Sha256::new()\n                    .update_file(tarball.file())?\n                    .finish_hex();\n                let operation = Operation::Publish {\n                    name: pkg.name().as_str(),\n                    vers: &ver,\n                    cksum: &hash,\n                };\n                registry.set_token(Some(auth::auth_token(\n                    &opts.gctx,\n                    &source_ids.original,\n                    None,\n                    operation,\n                    vec![],\n                    false,\n                )?));\n            }\n\n            let workspace_context = || {\n                let mut remaining = ready.clone();\n                remaining.extend(plan.iter());\n                if !remaining.is_empty() {\n                    format!(\n                        \"\\n\\nnote: the following crates have not been published yet:\\n  {}\",\n                        remaining.into_iter().join(\"\\n  \")\n                    )\n                } else {\n                    String::new()\n                }\n            };\n\n            transmit(\n                opts.gctx,\n                ws,\n                pkg,\n                tarball.file(),\n                &mut registry,\n                source_ids.original,\n                opts.dry_run,\n                workspace_context,\n            )?;\n            to_confirm.insert(pkg_id);\n\n            if !opts.dry_run {\n                // Short does not include the registry name.\n                let short_pkg_description = format!(\"{} v{}\", pkg.name(), pkg.version());\n                let source_description = source_ids.original.to_string();\n                ws.gctx().shell().status(\n                    \"Uploaded\",\n                    format!(\"{short_pkg_description} to {source_description}\"),\n                )?;\n            }\n        }\n\n        let confirmed = if opts.dry_run {\n            to_confirm.clone()\n        } else {\n            const DEFAULT_TIMEOUT: u64 = 60;\n            let timeout = if opts.gctx.cli_unstable().publish_timeout {\n                let timeout: Option<u64> = opts.gctx.get(\"publish.timeout\")?;\n                timeout.unwrap_or(DEFAULT_TIMEOUT)\n            } else {\n                DEFAULT_TIMEOUT\n            };\n            if 0 < timeout {\n                let source_description = source.source_id().to_string();\n                let short_pkg_descriptions = package_list(to_confirm.iter().copied(), \"or\");\n                if plan.is_empty() {\n                    let report = &[\n                        annotate_snippets::Group::with_title(\n                        annotate_snippets::Level::NOTE\n                            .secondary_title(format!(\n                                \"waiting for {short_pkg_descriptions} to be available at {source_description}\"\n                            ))),\n                            annotate_snippets::Group::with_title(annotate_snippets::Level::HELP.secondary_title(format!(\n                                \"you may press ctrl-c to skip waiting; the {crate} should be available shortly\",\n                                crate = if to_confirm.len() == 1 { \"crate\" } else {\"crates\"}\n                            ))),\n                    ];\n                    opts.gctx.shell().print_report(report, false)?;\n                } else {\n                    opts.gctx.shell().note(format!(\n                    \"waiting for {short_pkg_descriptions} to be available at {source_description}.\\n\\\n                    {count} remaining {crate} to be published\",\n                    count = plan.len(),\n                    crate = if plan.len() == 1 { \"crate\" } else {\"crates\"}\n                ))?;\n                }\n\n                let timeout = Duration::from_secs(timeout);\n                let confirmed = wait_for_any_publish_confirmation(\n                    opts.gctx,\n                    source_ids.original,\n                    &to_confirm,\n                    timeout,\n                )?;\n                if !confirmed.is_empty() {\n                    let short_pkg_description = package_list(confirmed.iter().copied(), \"and\");\n                    opts.gctx.shell().status(\n                        \"Published\",\n                        format!(\"{short_pkg_description} at {source_description}\"),\n                    )?;\n                } else {\n                    let short_pkg_descriptions = package_list(to_confirm.iter().copied(), \"or\");\n                    let krate = if to_confirm.len() == 1 {\n                        \"crate\"\n                    } else {\n                        \"crates\"\n                    };\n                    opts.gctx.shell().print_report(\n                        &[Level::WARNING\n                            .secondary_title(format!(\n                                \"timed out waiting for {short_pkg_descriptions} \\\n                                    to be available in {source_description}\",\n                            ))\n                            .element(Level::NOTE.message(format!(\n                                \"the registry may have a backlog that is delaying making the \\\n                                {krate} available. The {krate} should be available soon.\",\n                            )))],\n                        false,\n                    )?;\n                }\n                confirmed\n            } else {\n                BTreeSet::new()\n            }\n        };\n        if confirmed.is_empty() {\n            // If nothing finished, it means we timed out while waiting for confirmation.\n            // We're going to exit, but first we need to check: have we uploaded everything?\n            if plan.is_empty() {\n                // It's ok that we timed out, because nothing was waiting on dependencies to\n                // be confirmed.\n                break;\n            } else {\n                let failed_list = package_list(plan.iter(), \"and\");\n                bail!(\n                    \"unable to publish {failed_list} due to a timeout while waiting for published dependencies to be available.\"\n                );\n            }\n        }\n        for id in &confirmed {\n            to_confirm.remove(id);\n        }\n        plan.mark_confirmed(confirmed);\n    }\n\n    Ok(())\n}\n\n/// Poll the registry for any packages that are ready for use.\n///\n/// Returns the subset of `pkgs` that are ready for use.\n/// This will be an empty set if we timed out before confirming anything.\nfn wait_for_any_publish_confirmation(\n    gctx: &GlobalContext,\n    registry_src: SourceId,\n    pkgs: &BTreeSet<PackageId>,\n    timeout: Duration,\n) -> CargoResult<BTreeSet<PackageId>> {\n    let mut source = SourceConfigMap::empty(gctx)?.load(registry_src, &HashSet::new())?;\n    // Disable the source's built-in progress bars. Repeatedly showing a bunch\n    // of independent progress bars can be a little confusing. There is an\n    // overall progress bar managed here.\n    source.set_quiet(true);\n\n    let now = std::time::Instant::now();\n    let sleep_time = Duration::from_secs(1);\n    let max = timeout.as_secs() as usize;\n    let mut progress = Progress::with_style(\"Waiting\", ProgressStyle::Ratio, gctx);\n    progress.tick_now(0, max, \"\")?;\n    let available = loop {\n        {\n            let _lock = gctx.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n            // Force re-fetching the source\n            //\n            // As pulling from a git source is expensive, we track when we've done it within the\n            // process to only do it once, but we are one of the rare cases that needs to do it\n            // multiple times\n            gctx.updated_sources().remove(&source.replaced_source_id());\n            source.invalidate_cache();\n            let mut available = BTreeSet::new();\n            for pkg in pkgs {\n                if poll_one_package(registry_src, pkg, &mut *source)? {\n                    available.insert(*pkg);\n                }\n            }\n\n            // As soon as any package is available, break this loop so we can see if another\n            // one can be uploaded.\n            if !available.is_empty() {\n                break available;\n            }\n        }\n\n        let elapsed = now.elapsed();\n        if timeout < elapsed {\n            break BTreeSet::new();\n        }\n\n        progress.tick_now(elapsed.as_secs() as usize, max, \"\")?;\n        std::thread::sleep(sleep_time);\n    };\n\n    Ok(available)\n}\n\nfn poll_one_package(\n    registry_src: SourceId,\n    pkg_id: &PackageId,\n    source: &mut dyn Source,\n) -> CargoResult<bool> {\n    let version_req = format!(\"={}\", pkg_id.version());\n    let query = Dependency::parse(pkg_id.name(), Some(&version_req), registry_src)?;\n    let summaries = loop {\n        // Exact to avoid returning all for path/git\n        match source.query_vec(&query, QueryKind::Exact) {\n            std::task::Poll::Ready(res) => {\n                break res?;\n            }\n            std::task::Poll::Pending => source.block_until_ready()?,\n        }\n    };\n    Ok(!summaries.is_empty())\n}\n\nfn verify_unpublished(\n    pkg: &Package,\n    source: &mut RegistrySource<'_>,\n    source_ids: &RegistrySourceIds,\n    dry_run: bool,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let query = Dependency::parse(\n        pkg.name(),\n        Some(&pkg.version().to_exact_req().to_string()),\n        source_ids.replacement,\n    )?;\n    let duplicate_query = loop {\n        match source.query_vec(&query, QueryKind::Exact) {\n            std::task::Poll::Ready(res) => {\n                break res?;\n            }\n            std::task::Poll::Pending => source.block_until_ready()?,\n        }\n    };\n    if !duplicate_query.is_empty() {\n        // Move the registry error earlier in the publish process.\n        // Since dry-run wouldn't talk to the registry to get the error, we downgrade it to a\n        // warning.\n        if dry_run {\n            gctx.shell().warn(format!(\n                \"crate {}@{} already exists on {}\",\n                pkg.name(),\n                pkg.version(),\n                source.describe()\n            ))?;\n        } else {\n            bail!(\n                \"crate {}@{} already exists on {}\",\n                pkg.name(),\n                pkg.version(),\n                source.describe()\n            );\n        }\n    }\n\n    Ok(())\n}\n\nfn verify_dependencies(\n    pkg: &Package,\n    registry: &Registry,\n    registry_src: SourceId,\n) -> CargoResult<()> {\n    for dep in pkg.dependencies().iter() {\n        if check_dep_has_version(dep, true)? {\n            continue;\n        }\n        // TomlManifest::prepare_for_publish will rewrite the dependency\n        // to be just the `version` field.\n        if dep.source_id() != registry_src {\n            if !dep.source_id().is_registry() {\n                // Consider making SourceId::kind a public type that we can\n                // exhaustively match on. Using match can help ensure that\n                // every kind is properly handled.\n                panic!(\"unexpected source kind for dependency {:?}\", dep);\n            }\n            // Block requests to send to crates.io with alt-registry deps.\n            // This extra hostname check is mostly to assist with testing,\n            // but also prevents someone using `--index` to specify\n            // something that points to crates.io.\n            if registry_src.is_crates_io() || registry.host_is_crates_io() {\n                bail!(\n                    \"crates cannot be published to crates.io with dependencies sourced from other\\n\\\n                       registries. `{}` needs to be published to crates.io before publishing this crate.\\n\\\n                       (crate `{}` is pulled from {})\",\n                    dep.package_name(),\n                    dep.package_name(),\n                    dep.source_id()\n                );\n            }\n        }\n    }\n    Ok(())\n}\n\npub(crate) fn prepare_transmit(\n    gctx: &GlobalContext,\n    ws: &Workspace<'_>,\n    local_pkg: &Package,\n    registry_id: SourceId,\n) -> CargoResult<NewCrate> {\n    let included = None; // don't filter build-targets\n    let publish_pkg = prepare_for_publish(local_pkg, ws, included)?;\n\n    let deps = publish_pkg\n        .dependencies()\n        .iter()\n        .map(|dep| {\n            // If the dependency is from a different registry, then include the\n            // registry in the dependency.\n            let dep_registry_id = match dep.registry_id() {\n                Some(id) => id,\n                None => SourceId::crates_io(gctx)?,\n            };\n            // In the index and Web API, None means \"from the same registry\"\n            // whereas in Cargo.toml, it means \"from crates.io\".\n            let dep_registry = if dep_registry_id != registry_id {\n                Some(dep_registry_id.url().to_string())\n            } else {\n                None\n            };\n\n            Ok(NewCrateDependency {\n                optional: dep.is_optional(),\n                default_features: dep.uses_default_features(),\n                name: dep.package_name().to_string(),\n                features: dep.features().iter().map(|s| s.to_string()).collect(),\n                version_req: dep.version_req().to_string(),\n                target: dep.platform().map(|s| s.to_string()),\n                kind: match dep.kind() {\n                    DepKind::Normal => \"normal\",\n                    DepKind::Build => \"build\",\n                    DepKind::Development => \"dev\",\n                }\n                .to_string(),\n                registry: dep_registry,\n                explicit_name_in_toml: dep.explicit_name_in_toml().map(|s| s.to_string()),\n                artifact: dep.artifact().map(|artifact| {\n                    artifact\n                        .kinds()\n                        .iter()\n                        .map(|x| x.as_str().into_owned())\n                        .collect()\n                }),\n                bindep_target: dep.artifact().and_then(|artifact| {\n                    artifact.target().map(|target| target.as_str().to_owned())\n                }),\n                lib: dep.artifact().map_or(false, |artifact| artifact.is_lib()),\n            })\n        })\n        .collect::<CargoResult<Vec<NewCrateDependency>>>()?;\n    let manifest = publish_pkg.manifest();\n    let ManifestMetadata {\n        ref authors,\n        ref description,\n        ref homepage,\n        ref documentation,\n        ref keywords,\n        ref readme,\n        ref repository,\n        ref license,\n        ref license_file,\n        ref categories,\n        ref badges,\n        ref links,\n        ref rust_version,\n    } = *manifest.metadata();\n    let rust_version = rust_version.as_ref().map(ToString::to_string);\n    let readme_content = local_pkg\n        .manifest()\n        .metadata()\n        .readme\n        .as_ref()\n        .map(|readme| {\n            paths::read(&local_pkg.root().join(readme)).with_context(|| {\n                format!(\"failed to read `readme` file for package `{}`\", local_pkg)\n            })\n        })\n        .transpose()?;\n    if let Some(ref file) = local_pkg.manifest().metadata().license_file {\n        if !local_pkg.root().join(file).exists() {\n            bail!(\"the license file `{}` does not exist\", file)\n        }\n    }\n\n    let string_features = match manifest.normalized_toml().features() {\n        Some(features) => features\n            .iter()\n            .map(|(feat, values)| {\n                (\n                    feat.to_string(),\n                    values.iter().map(|fv| fv.to_string()).collect(),\n                )\n            })\n            .collect::<BTreeMap<String, Vec<String>>>(),\n        None => BTreeMap::new(),\n    };\n\n    Ok(NewCrate {\n        name: publish_pkg.name().to_string(),\n        vers: publish_pkg.version().to_string(),\n        deps,\n        features: string_features,\n        authors: authors.clone(),\n        description: description.clone(),\n        homepage: homepage.clone(),\n        documentation: documentation.clone(),\n        keywords: keywords.clone(),\n        categories: categories.clone(),\n        readme: readme_content,\n        readme_file: readme.clone(),\n        repository: repository.clone(),\n        license: license.clone(),\n        license_file: license_file.clone(),\n        badges: badges.clone(),\n        links: links.clone(),\n        rust_version,\n    })\n}\n\nfn transmit(\n    gctx: &GlobalContext,\n    ws: &Workspace<'_>,\n    pkg: &Package,\n    tarball: &File,\n    registry: &mut Registry,\n    registry_id: SourceId,\n    dry_run: bool,\n    workspace_context: impl Fn() -> String,\n) -> CargoResult<()> {\n    let new_crate = prepare_transmit(gctx, ws, pkg, registry_id)?;\n\n    // Do not upload if performing a dry run\n    if dry_run {\n        gctx.shell().warn(\"aborting upload due to dry run\")?;\n        return Ok(());\n    }\n\n    let warnings = registry.publish(&new_crate, tarball).with_context(|| {\n        format!(\n            \"failed to publish {} v{} to registry at {}{}\",\n            pkg.name(),\n            pkg.version(),\n            registry.host(),\n            workspace_context()\n        )\n    })?;\n\n    if !warnings.invalid_categories.is_empty() {\n        let msg = format!(\n            \"the following are not valid category slugs and were ignored: {}\",\n            warnings.invalid_categories.join(\", \")\n        );\n        gctx.shell().print_report(\n            &[Level::WARNING\n                .secondary_title(msg)\n                .element(Level::HELP.message(\n                \"please see <https://crates.io/category_slugs> for the list of all category slugs\",\n            ))],\n            false,\n        )?;\n    }\n\n    if !warnings.invalid_badges.is_empty() {\n        let msg = format!(\n            \"the following are not valid badges and were ignored: {}\",\n            warnings.invalid_badges.join(\", \")\n        );\n        gctx.shell().print_report(\n            &[Level::WARNING.secondary_title(msg).elements([\n                Level::NOTE.message(\n                    \"either the badge type specified is unknown or a required \\\n                    attribute is missing\",\n                ),\n                Level::HELP.message(\n                    \"please see \\\n                    <https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata> \\\n                    for valid badge types and their required attributes\",\n                ),\n            ])],\n            false,\n        )?;\n    }\n\n    if !warnings.other.is_empty() {\n        for msg in warnings.other {\n            gctx.shell().warn(&msg)?;\n        }\n    }\n\n    Ok(())\n}\n\n/// State for tracking dependencies during upload.\nstruct PublishPlan {\n    /// Graph of publishable packages where the edges are `(dependency -> dependent)`\n    dependents: Graph<PackageId, ()>,\n    /// The original graph of publishable packages where the edges are `(dependent -> dependency)`\n    graph: Graph<PackageId, ()>,\n    /// The weight of a package is the number of unpublished dependencies it has.\n    dependencies_count: HashMap<PackageId, usize>,\n}\n\nimpl PublishPlan {\n    /// Given a package dependency graph, creates a `PublishPlan` for tracking state.\n    fn new(graph: &Graph<PackageId, ()>) -> Self {\n        let dependents = graph.reversed();\n\n        let dependencies_count: HashMap<_, _> = dependents\n            .iter()\n            .map(|id| (*id, graph.edges(id).count()))\n            .collect();\n        Self {\n            dependents,\n            graph: graph.clone(),\n            dependencies_count,\n        }\n    }\n\n    fn iter(&self) -> impl Iterator<Item = PackageId> + '_ {\n        self.dependencies_count.iter().map(|(id, _)| *id)\n    }\n\n    fn is_empty(&self) -> bool {\n        self.dependencies_count.is_empty()\n    }\n\n    fn len(&self) -> usize {\n        self.dependencies_count.len()\n    }\n\n    /// Determines whether the dependency graph contains any circular dependencies.\n    fn has_cycles(&self) -> bool {\n        !self.cycle_members().is_empty()\n    }\n\n    /// Identifies and returns the packages involved in a circular dependency.\n    fn cycle_members(&self) -> Vec<PackageId> {\n        let mut remaining: BTreeSet<_> = self.dependencies_count.keys().copied().collect();\n        loop {\n            let to_remove: Vec<_> = remaining\n                .iter()\n                .filter(|&id| {\n                    self.graph\n                        .edges(id)\n                        .all(|(child, _)| !remaining.contains(child))\n                })\n                .copied()\n                .collect();\n            if to_remove.is_empty() {\n                break;\n            }\n            for id in to_remove {\n                remaining.remove(&id);\n            }\n        }\n        remaining.into_iter().collect()\n    }\n\n    /// Returns the set of packages that are ready for publishing (i.e. have no outstanding dependencies).\n    ///\n    /// These will not be returned in future calls.\n    fn take_ready(&mut self) -> BTreeSet<PackageId> {\n        let ready: BTreeSet<_> = self\n            .dependencies_count\n            .iter()\n            .filter_map(|(id, weight)| (*weight == 0).then_some(*id))\n            .collect();\n        for pkg in &ready {\n            self.dependencies_count.remove(pkg);\n        }\n        ready\n    }\n\n    /// Packages confirmed to be available in the registry, potentially allowing additional\n    /// packages to be \"ready\".\n    fn mark_confirmed(&mut self, published: impl IntoIterator<Item = PackageId>) {\n        for id in published {\n            for (dependent_id, _) in self.dependents.edges(&id) {\n                if let Some(weight) = self.dependencies_count.get_mut(dependent_id) {\n                    *weight = weight.saturating_sub(1);\n                }\n            }\n        }\n    }\n}\n\n/// Format a collection of packages as a list\n///\n/// e.g. \"foo v0.1.0, bar v0.2.0, and baz v0.3.0\".\n///\n/// Note: the final separator (e.g. \"and\" in the previous example) can be chosen.\nfn package_list(pkgs: impl IntoIterator<Item = PackageId>, final_sep: &str) -> String {\n    let mut names: Vec<_> = pkgs\n        .into_iter()\n        .map(|pkg| format!(\"{} v{}\", pkg.name(), pkg.version()))\n        .collect();\n    names.sort();\n\n    match &names[..] {\n        [] => String::new(),\n        [a] => a.clone(),\n        [a, b] => format!(\"{a} {final_sep} {b}\"),\n        [names @ .., last] => {\n            format!(\"{}, {final_sep} {last}\", names.join(\", \"))\n        }\n    }\n}\n\nfn resolve_registry_or_index(\n    opts: &PublishOpts<'_>,\n    just_pkgs: &[&Package],\n) -> CargoResult<Option<RegistryOrIndex>> {\n    let opt_index_or_registry = opts.reg_or_index.clone();\n\n    let res = match opt_index_or_registry {\n        ref r @ Some(ref registry_or_index) => {\n            validate_registry(just_pkgs, r.as_ref())?;\n\n            let registry_is_specified_by_any_package = just_pkgs\n                .iter()\n                .any(|pkg| pkg.publish().as_ref().map(|v| v.len()).unwrap_or(0) > 0);\n\n            if registry_is_specified_by_any_package && registry_or_index.is_index() {\n                opts.gctx.shell().warn(r#\"`--index` will ignore registries set by `package.publish` in Cargo.toml, and may cause unexpected push to prohibited registry\nhelp: use `--registry` instead or set `publish = true` in Cargo.toml to suppress this warning\"#)?;\n            }\n\n            r.clone()\n        }\n        None => {\n            let reg = super::infer_registry(&just_pkgs)?;\n            validate_registry(&just_pkgs, reg.as_ref())?;\n            if let Some(RegistryOrIndex::Registry(registry)) = &reg {\n                if registry != CRATES_IO_REGISTRY {\n                    // Don't warn for crates.io.\n                    opts.gctx.shell().note(&format!(\n                        \"found `{}` as only allowed registry. Publishing to it automatically.\",\n                        registry\n                    ))?;\n                }\n            }\n            reg\n        }\n    };\n\n    Ok(res)\n}\n\nfn validate_registry(pkgs: &[&Package], reg_or_index: Option<&RegistryOrIndex>) -> CargoResult<()> {\n    let reg_name = match reg_or_index {\n        Some(RegistryOrIndex::Registry(r)) => Some(r.as_str()),\n        None => Some(CRATES_IO_REGISTRY),\n        Some(RegistryOrIndex::Index(_)) => None,\n    };\n    if let Some(reg_name) = reg_name {\n        for pkg in pkgs {\n            if let Some(allowed) = pkg.publish().as_ref() {\n                if !allowed.iter().any(|a| a == reg_name) {\n                    bail!(\n                        \"`{}` cannot be published.\\n\\\n                         The registry `{}` is not listed in the `package.publish` value in Cargo.toml.\",\n                        pkg.name(),\n                        reg_name\n                    );\n                }\n            }\n        }\n    }\n\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::{\n        core::{PackageId, SourceId},\n        sources::CRATES_IO_INDEX,\n        util::{Graph, IntoUrl},\n    };\n\n    use super::PublishPlan;\n\n    fn pkg_id(name: &str) -> PackageId {\n        let loc = CRATES_IO_INDEX.into_url().unwrap();\n        PackageId::try_new(name, \"1.0.0\", SourceId::for_registry(&loc).unwrap()).unwrap()\n    }\n\n    #[test]\n    fn parallel_schedule() {\n        let mut graph: Graph<PackageId, ()> = Graph::new();\n        let a = pkg_id(\"a\");\n        let b = pkg_id(\"b\");\n        let c = pkg_id(\"c\");\n        let d = pkg_id(\"d\");\n        let e = pkg_id(\"e\");\n\n        graph.add(a);\n        graph.add(b);\n        graph.add(c);\n        graph.add(d);\n        graph.add(e);\n        graph.link(a, c);\n        graph.link(b, c);\n        graph.link(c, d);\n        graph.link(c, e);\n\n        let mut order = PublishPlan::new(&graph);\n        let ready: Vec<_> = order.take_ready().into_iter().collect();\n        assert_eq!(ready, vec![d, e]);\n\n        order.mark_confirmed(vec![d]);\n        let ready: Vec<_> = order.take_ready().into_iter().collect();\n        assert!(ready.is_empty());\n\n        order.mark_confirmed(vec![e]);\n        let ready: Vec<_> = order.take_ready().into_iter().collect();\n        assert_eq!(ready, vec![c]);\n\n        order.mark_confirmed(vec![c]);\n        let ready: Vec<_> = order.take_ready().into_iter().collect();\n        assert_eq!(ready, vec![a, b]);\n\n        order.mark_confirmed(vec![a, b]);\n        let ready: Vec<_> = order.take_ready().into_iter().collect();\n        assert!(ready.is_empty());\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/registry/search.rs",
    "content": "//! Interacts with the registry [search API][1].\n//!\n//! [1]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#search\n\nuse std::cmp;\n\nuse anyhow::Context as _;\nuse url::Url;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::util::style;\nuse crate::util::style::LITERAL;\nuse crate::util::truncate_with_ellipsis;\n\nuse super::RegistryOrIndex;\n\npub fn search(\n    query: &str,\n    gctx: &GlobalContext,\n    reg_or_index: Option<RegistryOrIndex>,\n    limit: u32,\n) -> CargoResult<()> {\n    let source_ids = super::get_source_id(gctx, reg_or_index.as_ref())?;\n    let (mut registry, _) =\n        super::registry(gctx, &source_ids, None, reg_or_index.as_ref(), false, None)?;\n    let (crates, total_crates) = registry.search(query, limit).with_context(|| {\n        format!(\n            \"failed to retrieve search results from the registry at {}\",\n            registry.host()\n        )\n    })?;\n\n    let names = crates\n        .iter()\n        .map(|krate| format!(\"{} = \\\"{}\\\"\", krate.name, krate.max_version))\n        .collect::<Vec<String>>();\n\n    let description_margin = names.iter().map(|s| s.len()).max().unwrap_or_default() + 4;\n\n    let description_length = cmp::max(80, 128 - description_margin);\n\n    let descriptions = crates.iter().map(|krate| {\n        krate\n            .description\n            .as_ref()\n            .map(|desc| truncate_with_ellipsis(&desc.replace(\"\\n\", \" \"), description_length))\n    });\n\n    let mut shell = gctx.shell();\n    let stdout = shell.out();\n    let good = style::GOOD;\n\n    for (name, description) in names.into_iter().zip(descriptions) {\n        let line = match description {\n            Some(desc) => format!(\"{name: <description_margin$}# {desc}\"),\n            None => name,\n        };\n        let mut fragments = line.split(query).peekable();\n        while let Some(fragment) = fragments.next() {\n            let _ = write!(stdout, \"{fragment}\");\n            if fragments.peek().is_some() {\n                let _ = write!(stdout, \"{good}{query}{good:#}\");\n            }\n        }\n        let _ = writeln!(stdout);\n    }\n\n    let search_max_limit = 100;\n    if total_crates > limit && limit < search_max_limit {\n        let _ = writeln!(\n            stdout,\n            \"... and {} crates more (use --limit N to see more)\",\n            total_crates - limit\n        );\n    } else if total_crates > limit && limit >= search_max_limit {\n        let extra = if source_ids.original.is_crates_io() {\n            let url = Url::parse_with_params(\"https://crates.io/search\", &[(\"q\", query)])?;\n            format!(\" (go to {url} to see more)\")\n        } else {\n            String::new()\n        };\n        let _ = writeln!(\n            stdout,\n            \"... and {} crates more{}\",\n            total_crates - limit,\n            extra\n        );\n    }\n\n    if total_crates > 0 {\n        let literal = LITERAL;\n        shell.note(format_args!(\n            \"to learn more about a package, run `{literal}cargo info <name>{literal:#}`\",\n        ))?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/ops/registry/yank.rs",
    "content": "//! Interacts with the registry [yank] and [unyank] API.\n//!\n//! [yank]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#yank\n//! [unyank]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#unyank\n\nuse anyhow::Context as _;\nuse anyhow::bail;\nuse cargo_credential::Operation;\nuse cargo_credential::Secret;\n\nuse crate::core::Workspace;\nuse crate::util::context::GlobalContext;\nuse crate::util::errors::CargoResult;\nuse crate::util::important_paths::find_root_manifest_for_wd;\n\nuse super::RegistryOrIndex;\n\npub fn yank(\n    gctx: &GlobalContext,\n    krate: Option<String>,\n    version: Option<String>,\n    token: Option<Secret<String>>,\n    reg_or_index: Option<RegistryOrIndex>,\n    undo: bool,\n) -> CargoResult<()> {\n    let name = match krate {\n        Some(name) => name,\n        None => {\n            let manifest_path = find_root_manifest_for_wd(gctx.cwd())?;\n            let ws = Workspace::new(&manifest_path, gctx)?;\n            ws.current()?.package_id().name().to_string()\n        }\n    };\n    let Some(version) = version else {\n        bail!(\"a version must be specified to yank\")\n    };\n\n    let message = if undo {\n        Operation::Unyank {\n            name: &name,\n            vers: &version,\n        }\n    } else {\n        Operation::Yank {\n            name: &name,\n            vers: &version,\n        }\n    };\n    let source_ids = super::get_source_id(gctx, reg_or_index.as_ref())?;\n    let (mut registry, _) = super::registry(\n        gctx,\n        &source_ids,\n        token.as_ref().map(Secret::as_deref),\n        reg_or_index.as_ref(),\n        true,\n        Some(message),\n    )?;\n\n    let package_spec = format!(\"{}@{}\", name, version);\n    if undo {\n        gctx.shell().status(\"Unyank\", package_spec)?;\n        registry.unyank(&name, &version).with_context(|| {\n            format!(\n                \"failed to undo a yank from the registry at {}\",\n                registry.host()\n            )\n        })?;\n    } else {\n        gctx.shell().status(\"Yank\", package_spec)?;\n        registry\n            .yank(&name, &version)\n            .with_context(|| format!(\"failed to yank from the registry at {}\", registry.host()))?;\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/ops/resolve.rs",
    "content": "//! High-level APIs for executing the resolver.\n//!\n//! This module provides functions for running the resolver given a workspace, including loading\n//! the `Cargo.lock` file and checking if it needs updating.\n//!\n//! There are roughly 3 main functions:\n//!\n//! - [`resolve_ws`]: A simple, high-level function with no options.\n//! - [`resolve_ws_with_opts`]: A medium-level function with options like\n//!   user-provided features. This is the most appropriate function to use in\n//!   most cases.\n//! - [`resolve_with_previous`]: A low-level function for running the resolver,\n//!   providing the most power and flexibility.\n//!\n//! ### Data Structures\n//!\n//! - [`Workspace`]:\n//!   Usually created by [`crate::util::command_prelude::ArgMatchesExt::workspace`] which discovers the root of the\n//!   workspace, and loads all the workspace members as a [`Package`] object\n//!   - [`Package`]\n//!     Corresponds with `Cargo.toml` manifest (deserialized as [`Manifest`]) and its associated files.\n//!     - [`Target`]s are crates such as the library, binaries, integration test, or examples.\n//!       They are what is actually compiled by `rustc`.\n//!       Each `Target` defines a crate root, like `src/lib.rs` or `examples/foo.rs`.\n//!     - [`PackageId`] --- A unique identifier for a package.\n//! - [`PackageRegistry`]:\n//!   The primary interface for how the dependency\n//!   resolver finds packages. It contains the `SourceMap`, and handles things\n//!   like the `[patch]` table. The dependency resolver\n//!   sends a query to the `PackageRegistry` to \"get me all packages that match\n//!   this dependency declaration\". The `Registry` trait provides a generic interface\n//!   to the `PackageRegistry`, but this is only used for providing an alternate\n//!   implementation of the `PackageRegistry` for testing.\n//! - [`SourceMap`]: Map of all available sources.\n//!   - [`Source`]: An abstraction for something that can fetch packages (a remote\n//!     registry, a git repo, the local filesystem, etc.). Check out the [source\n//!     implementations] for all the details about registries, indexes, git\n//!     dependencies, etc.\n//!       * [`SourceId`]: A unique identifier for a source.\n//!   - [`Summary`]: A of a [`Manifest`], and is essentially\n//!     the information that can be found in a registry index. Queries against the\n//!     `PackageRegistry` yields a `Summary`. The resolver uses the summary\n//!     information to build the dependency graph.\n//! - [`PackageSet`] --- Contains all the `Package` objects. This works with the\n//!   [`Downloads`] struct to coordinate downloading packages. It has a reference\n//!   to the `SourceMap` to get the `Source` objects which tell the `Downloads`\n//!   struct which URLs to fetch.\n//!\n//! [`Package`]: crate::core::package\n//! [`Target`]: crate::core::Target\n//! [`Manifest`]: crate::core::Manifest\n//! [`Source`]: crate::sources::source::Source\n//! [`SourceMap`]: crate::sources::source::SourceMap\n//! [`PackageRegistry`]: crate::core::registry::PackageRegistry\n//! [source implementations]: crate::sources\n//! [`Downloads`]: crate::core::package::Downloads\n\nuse crate::core::Dependency;\nuse crate::core::GitReference;\nuse crate::core::PackageId;\nuse crate::core::PackageIdSpec;\nuse crate::core::PackageIdSpecQuery;\nuse crate::core::PackageSet;\nuse crate::core::SourceId;\nuse crate::core::Workspace;\nuse crate::core::compiler::{CompileKind, RustcTargetData};\nuse crate::core::registry::{LockedPatchDependency, PackageRegistry};\nuse crate::core::resolver::features::{\n    CliFeatures, FeatureOpts, FeatureResolver, ForceAllTargets, RequestedFeatures, ResolvedFeatures,\n};\nuse crate::core::resolver::{\n    self, HasDevUnits, Resolve, ResolveOpts, ResolveVersion, VersionOrdering, VersionPreferences,\n};\nuse crate::core::summary::Summary;\nuse crate::ops;\nuse crate::sources::RecursivePathSource;\nuse crate::util::CanonicalUrl;\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::context::FeatureUnification;\nuse crate::util::errors::CargoResult;\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse anyhow::Context as _;\nuse cargo_util::paths;\nuse cargo_util_schemas::core::PartialVersion;\nuse std::borrow::Cow;\nuse std::collections::{HashMap, HashSet};\nuse std::rc::Rc;\nuse tracing::{debug, trace};\n\n/// Filter for keep using Package ID from previous lockfile.\ntype Keep<'a> = &'a dyn Fn(&PackageId) -> bool;\n\n/// Result for `resolve_ws_with_opts`.\npub struct WorkspaceResolve<'gctx> {\n    /// Packages to be downloaded.\n    pub pkg_set: PackageSet<'gctx>,\n    /// The resolve for the entire workspace.\n    ///\n    /// This may be `None` for things like `cargo install` and `-Zavoid-dev-deps`.\n    /// This does not include `paths` overrides.\n    pub workspace_resolve: Option<Resolve>,\n    /// The narrowed resolve, with the specific features enabled.\n    pub targeted_resolve: Resolve,\n    /// Package specs requested for compilation along with specific features enabled. This usually\n    /// has the length of one but there may be more specs with different features when using the\n    /// `package` feature resolver.\n    pub specs_and_features: Vec<SpecsAndResolvedFeatures>,\n}\n\n/// Pair of package specs requested for compilation along with enabled features.\npub struct SpecsAndResolvedFeatures {\n    /// Packages that are supposed to be built.\n    pub specs: Vec<PackageIdSpec>,\n    /// The features activated per package.\n    pub resolved_features: ResolvedFeatures,\n}\n\nconst UNUSED_PATCH_WARNING: &str = \"\\\nCheck that the patched package version and available features are compatible\nwith the dependency requirements. If the patch has a different version from\nwhat is locked in the Cargo.lock file, run `cargo update` to use the new\nversion. This may also occur with an optional dependency that is not enabled.\";\n\n/// Resolves all dependencies for the workspace using the previous\n/// lock file as a guide if present.\n///\n/// This function will also write the result of resolution as a new lock file\n/// (unless it is an ephemeral workspace such as `cargo install` or `cargo\n/// package`).\n///\n/// This is a simple interface used by commands like `clean`, `fetch`, and\n/// `package`, which don't specify any options or features.\npub fn resolve_ws<'a>(ws: &Workspace<'a>, dry_run: bool) -> CargoResult<(PackageSet<'a>, Resolve)> {\n    let mut registry = ws.package_registry()?;\n    let resolve = resolve_with_registry(ws, &mut registry, dry_run)?;\n    let packages = get_resolved_packages(&resolve, registry)?;\n    Ok((packages, resolve))\n}\n\n/// Resolves dependencies for some packages of the workspace,\n/// taking into account `paths` overrides and activated features.\n///\n/// This function will also write the result of resolution as a new lock file\n/// (unless `Workspace::require_optional_deps` is false, such as `cargo\n/// install` or `-Z avoid-dev-deps`), or it is an ephemeral workspace (`cargo\n/// install` or `cargo package`).\n///\n/// `specs` may be empty, which indicates it should resolve all workspace\n/// members. In this case, `opts.all_features` must be `true`.\npub fn resolve_ws_with_opts<'gctx>(\n    ws: &Workspace<'gctx>,\n    target_data: &mut RustcTargetData<'gctx>,\n    requested_targets: &[CompileKind],\n    cli_features: &CliFeatures,\n    specs: &[PackageIdSpec],\n    has_dev_units: HasDevUnits,\n    force_all_targets: ForceAllTargets,\n    dry_run: bool,\n) -> CargoResult<WorkspaceResolve<'gctx>> {\n    let feature_unification = ws.resolve_feature_unification();\n    let individual_specs = match feature_unification {\n        FeatureUnification::Selected => vec![specs.to_owned()],\n        FeatureUnification::Workspace => {\n            vec![ops::Packages::All(Vec::new()).to_package_id_specs(ws)?]\n        }\n        FeatureUnification::Package => specs.iter().map(|spec| vec![spec.clone()]).collect(),\n    };\n    let specs: Vec<_> = individual_specs\n        .iter()\n        .map(|specs| specs.iter())\n        .flatten()\n        .cloned()\n        .collect();\n    let specs = &specs[..];\n    let mut registry = ws.package_registry()?;\n    let (resolve, resolved_with_overrides) = if ws.ignore_lock() {\n        let add_patches = true;\n        let resolve = None;\n        let resolved_with_overrides = resolve_with_previous(\n            &mut registry,\n            ws,\n            cli_features,\n            has_dev_units,\n            resolve.as_ref(),\n            None,\n            specs,\n            add_patches,\n        )?;\n        ops::print_lockfile_changes(ws, None, &resolved_with_overrides, &mut registry)?;\n        (resolve, resolved_with_overrides)\n    } else if ws.require_optional_deps() {\n        // First, resolve the root_package's *listed* dependencies, as well as\n        // downloading and updating all remotes and such.\n        let resolve = resolve_with_registry(ws, &mut registry, dry_run)?;\n        // No need to add patches again, `resolve_with_registry` has done it.\n        let add_patches = false;\n\n        // Second, resolve with precisely what we're doing. Filter out\n        // transitive dependencies if necessary, specify features, handle\n        // overrides, etc.\n        add_overrides(&mut registry, ws)?;\n\n        for (replace_spec, dep) in ws.root_replace() {\n            if !resolve\n                .iter()\n                .any(|r| replace_spec.matches(r) && !dep.matches_id(r))\n            {\n                ws.gctx()\n                    .shell()\n                    .warn(format!(\"package replacement is not used: {}\", replace_spec))?\n            }\n\n            let mut unused_fields = Vec::new();\n            if dep.features().len() != 0 {\n                unused_fields.push(\"`features`\");\n            }\n            if !dep.uses_default_features() {\n                unused_fields.push(\"`default-features`\")\n            }\n            if !unused_fields.is_empty() {\n                ws.gctx().shell().print_report(\n                    &[Level::WARNING\n                        .secondary_title(format!(\n                            \"unused field in replacement for `{}`: {}\",\n                            dep.package_name(),\n                            unused_fields.join(\", \")\n                        ))\n                        .element(Level::NOTE.message(format!(\n                            \"configure {} in the `dependencies` entry\",\n                            unused_fields.join(\", \")\n                        )))],\n                    false,\n                )?;\n            }\n        }\n\n        let resolved_with_overrides = resolve_with_previous(\n            &mut registry,\n            ws,\n            cli_features,\n            has_dev_units,\n            Some(&resolve),\n            None,\n            specs,\n            add_patches,\n        )?;\n        (Some(resolve), resolved_with_overrides)\n    } else {\n        let add_patches = true;\n        let resolve = ops::load_pkg_lockfile(ws)?;\n        let resolved_with_overrides = resolve_with_previous(\n            &mut registry,\n            ws,\n            cli_features,\n            has_dev_units,\n            resolve.as_ref(),\n            None,\n            specs,\n            add_patches,\n        )?;\n        // Skipping `print_lockfile_changes` as there are cases where this prints irrelevant\n        // information\n        (resolve, resolved_with_overrides)\n    };\n\n    let pkg_set = get_resolved_packages(&resolved_with_overrides, registry)?;\n\n    let members_with_features = ws.members_with_features(specs, cli_features)?;\n    let member_ids = members_with_features\n        .iter()\n        .map(|(p, _fts)| p.package_id())\n        .collect::<Vec<_>>();\n    pkg_set.download_accessible(\n        &resolved_with_overrides,\n        &member_ids,\n        has_dev_units,\n        requested_targets,\n        target_data,\n        force_all_targets,\n    )?;\n\n    let mut specs_and_features = Vec::new();\n\n    for specs in individual_specs {\n        let feature_opts = FeatureOpts::new(ws, has_dev_units, force_all_targets)?;\n\n        // We want to narrow the features to the current specs so that stuff like `cargo check -p a\n        // -p b -F a/a,b/b` works and the resolver does not contain that `a` does not have feature\n        // `b` and vice-versa. However, resolver v1 needs to see even features of unselected\n        // packages turned on if it was because of working directory being inside the unselected\n        // package, because they might turn on a feature of a selected package.\n        let narrowed_features = match feature_unification {\n            FeatureUnification::Package => {\n                let mut narrowed_features = cli_features.clone();\n                let enabled_features = members_with_features\n                    .iter()\n                    .filter_map(|(package, cli_features)| {\n                        specs\n                            .iter()\n                            .any(|spec| spec.matches(package.package_id()))\n                            .then_some(cli_features.features.iter())\n                    })\n                    .flatten()\n                    .cloned()\n                    .collect();\n                narrowed_features.features = Rc::new(enabled_features);\n                Cow::Owned(narrowed_features)\n            }\n            FeatureUnification::Selected | FeatureUnification::Workspace => {\n                Cow::Borrowed(cli_features)\n            }\n        };\n\n        let resolved_features = FeatureResolver::resolve(\n            ws,\n            target_data,\n            &resolved_with_overrides,\n            &pkg_set,\n            &*narrowed_features,\n            &specs,\n            requested_targets,\n            feature_opts,\n        )?;\n\n        pkg_set.warn_no_lib_packages_and_artifact_libs_overlapping_deps(\n            ws,\n            &resolved_with_overrides,\n            &member_ids,\n            has_dev_units,\n            requested_targets,\n            target_data,\n            force_all_targets,\n        )?;\n\n        specs_and_features.push(SpecsAndResolvedFeatures {\n            specs,\n            resolved_features,\n        });\n    }\n\n    Ok(WorkspaceResolve {\n        pkg_set,\n        workspace_resolve: resolve,\n        targeted_resolve: resolved_with_overrides,\n        specs_and_features,\n    })\n}\n\n#[tracing::instrument(skip_all)]\nfn resolve_with_registry<'gctx>(\n    ws: &Workspace<'gctx>,\n    registry: &mut PackageRegistry<'gctx>,\n    dry_run: bool,\n) -> CargoResult<Resolve> {\n    let prev = ops::load_pkg_lockfile(ws)?;\n    let mut resolve = resolve_with_previous(\n        registry,\n        ws,\n        &CliFeatures::new_all(true),\n        HasDevUnits::Yes,\n        prev.as_ref(),\n        None,\n        &[],\n        true,\n    )?;\n\n    let print = if !ws.is_ephemeral() && ws.require_optional_deps() {\n        if !dry_run {\n            ops::write_pkg_lockfile(ws, &mut resolve)?\n        } else {\n            true\n        }\n    } else {\n        // This mostly represents\n        // - `cargo install --locked` and the only change is the package is no longer local but\n        //   from the registry which is noise\n        // - publish of libraries\n        false\n    };\n    if print {\n        ops::print_lockfile_changes(ws, prev.as_ref(), &resolve, registry)?;\n    }\n    Ok(resolve)\n}\n\n/// Resolves all dependencies for a package using an optional previous instance\n/// of resolve to guide the resolution process.\n///\n/// This also takes an optional filter `keep_previous`, which informs the `registry`\n/// which package ID should be locked to the previous instance of resolve\n/// (often used in pairings with updates). See comments in [`register_previous_locks`]\n/// for scenarios that might override this.\n///\n/// The previous resolve normally comes from a lock file. This function does not\n/// read or write lock files from the filesystem.\n///\n/// `specs` may be empty, which indicates it should resolve all workspace\n/// members. In this case, `opts.all_features` must be `true`.\n///\n/// If `register_patches` is true, then entries from the `[patch]` table in\n/// the manifest will be added to the given `PackageRegistry`.\n#[tracing::instrument(skip_all)]\npub fn resolve_with_previous<'gctx>(\n    registry: &mut PackageRegistry<'gctx>,\n    ws: &Workspace<'gctx>,\n    cli_features: &CliFeatures,\n    has_dev_units: HasDevUnits,\n    previous: Option<&Resolve>,\n    keep_previous: Option<Keep<'_>>,\n    specs: &[PackageIdSpec],\n    register_patches: bool,\n) -> CargoResult<Resolve> {\n    // We only want one Cargo at a time resolving a crate graph since this can\n    // involve a lot of frobbing of the global caches.\n    let _lock = ws\n        .gctx()\n        .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n\n    // Some packages are already loaded when setting up a workspace. This\n    // makes it so anything that was already loaded will not be loaded again.\n    // Without this there were cases where members would be parsed multiple times\n    ws.preload(registry);\n\n    // In case any members were not already loaded or the Workspace is_ephemeral.\n    for member in ws.members() {\n        registry.add_sources(Some(member.package_id().source_id()))?;\n    }\n\n    // Try to keep all from previous resolve if no instruction given.\n    let keep_previous = keep_previous.unwrap_or(&|_| true);\n\n    // While registering patches, we will record preferences for particular versions\n    // of various packages.\n    let mut version_prefs = VersionPreferences::default();\n    if ws.gctx().cli_unstable().minimal_versions {\n        version_prefs.version_ordering(VersionOrdering::MinimumVersionsFirst)\n    }\n    if ws.resolve_honors_rust_version() {\n        let mut rust_versions: Vec<_> = ws\n            .members()\n            .filter_map(|p| p.rust_version().map(|rv| rv.to_partial()))\n            .collect();\n        if rust_versions.is_empty() {\n            let rustc = ws.gctx().load_global_rustc(Some(ws))?;\n            let rust_version: PartialVersion = rustc.version.clone().into();\n            rust_versions.push(rust_version);\n        }\n        version_prefs.rust_versions(rust_versions);\n    }\n    if let Some(publish_time) = ws.resolve_publish_time() {\n        version_prefs.publish_time(publish_time);\n    }\n\n    let avoid_patch_ids = if register_patches {\n        register_patch_entries(registry, ws, previous, &mut version_prefs, keep_previous)?\n    } else {\n        HashSet::new()\n    };\n\n    // Refine `keep` with patches that should avoid locking.\n    let keep = |p: &PackageId| keep_previous(p) && !avoid_patch_ids.contains(p);\n\n    let dev_deps = ws.require_optional_deps() || has_dev_units == HasDevUnits::Yes;\n\n    if let Some(r) = previous {\n        trace!(\"previous: {:?}\", r);\n\n        // In the case where a previous instance of resolve is available, we\n        // want to lock as many packages as possible to the previous version\n        // without disturbing the graph structure.\n        register_previous_locks(ws, registry, r, &keep, dev_deps);\n\n        // Prefer to use anything in the previous lock file, aka we want to have conservative updates.\n        let _span = tracing::span!(tracing::Level::TRACE, \"prefer_package_id\").entered();\n        for id in r.iter().filter(keep) {\n            debug!(\"attempting to prefer {}\", id);\n            version_prefs.prefer_package_id(id);\n        }\n    }\n\n    if register_patches {\n        registry.lock_patches();\n    }\n\n    let summaries: Vec<(Summary, ResolveOpts)> = {\n        let _span = tracing::span!(tracing::Level::TRACE, \"registry.lock\").entered();\n        ws.members_with_features(specs, cli_features)?\n            .into_iter()\n            .map(|(member, features)| {\n                let summary = registry.lock(member.summary().clone());\n                (\n                    summary,\n                    ResolveOpts {\n                        dev_deps,\n                        features: RequestedFeatures::CliFeatures(features),\n                    },\n                )\n            })\n            .collect()\n    };\n\n    let replace = lock_replacements(ws, previous, &keep);\n\n    let mut resolved = resolver::resolve(\n        &summaries,\n        &replace,\n        registry,\n        &version_prefs,\n        ResolveVersion::with_rust_version(ws.lowest_rust_version()),\n        Some(ws.gctx()),\n    )?;\n\n    let patches = registry.patches().values().flat_map(|v| v.iter());\n    resolved.register_used_patches(patches);\n\n    if register_patches && !resolved.unused_patches().is_empty() {\n        emit_warnings_of_unused_patches(ws, &resolved, registry)?;\n    }\n\n    if let Some(previous) = previous {\n        resolved.merge_from(previous)?;\n    }\n    let gctx = ws.gctx();\n    let mut deferred = gctx.deferred_global_last_use()?;\n    deferred.save_no_error(gctx);\n    Ok(resolved)\n}\n\n/// Read the `paths` configuration variable to discover all path overrides that\n/// have been configured.\n#[tracing::instrument(skip_all)]\npub fn add_overrides<'a>(\n    registry: &mut PackageRegistry<'a>,\n    ws: &Workspace<'a>,\n) -> CargoResult<()> {\n    let gctx = ws.gctx();\n    let Some(paths) = gctx.paths_overrides()? else {\n        return Ok(());\n    };\n\n    let paths = paths.val.iter().map(|(s, def)| {\n        // The path listed next to the string is the config file in which the\n        // key was located, so we want to pop off the `.cargo/config` component\n        // to get the directory containing the `.cargo` folder.\n        (paths::normalize_path(&def.root(gctx.cwd()).join(s)), def)\n    });\n\n    for (path, definition) in paths {\n        let id = SourceId::for_path(&path)?;\n        let mut source = RecursivePathSource::new(&path, id, ws.gctx());\n        source.load().with_context(|| {\n            format!(\n                \"failed to update path override `{}` \\\n                 (defined in `{}`)\",\n                path.display(),\n                definition\n            )\n        })?;\n        registry.add_override(Box::new(source));\n    }\n    Ok(())\n}\n\npub fn get_resolved_packages<'gctx>(\n    resolve: &Resolve,\n    registry: PackageRegistry<'gctx>,\n) -> CargoResult<PackageSet<'gctx>> {\n    let ids: Vec<PackageId> = resolve.iter().collect();\n    registry.get(&ids)\n}\n\n/// In this function we're responsible for informing the `registry` of all\n/// locked dependencies from the previous lock file we had, `resolve`.\n///\n/// This gets particularly tricky for a couple of reasons. The first is that we\n/// want all updates to be conservative, so we actually want to take the\n/// `resolve` into account (and avoid unnecessary registry updates and such).\n/// the second, however, is that we want to be resilient to updates of\n/// manifests. For example if a dependency is added or a version is changed we\n/// want to make sure that we properly re-resolve (conservatively) instead of\n/// providing an opaque error.\n///\n/// The logic here is somewhat subtle, but there should be more comments below to\n/// clarify things.\n///\n/// Note that this function, at the time of this writing, is basically the\n/// entire fix for issue #4127.\n#[tracing::instrument(skip_all)]\nfn register_previous_locks(\n    ws: &Workspace<'_>,\n    registry: &mut PackageRegistry<'_>,\n    resolve: &Resolve,\n    keep: Keep<'_>,\n    dev_deps: bool,\n) {\n    let path_pkg = |id: SourceId| {\n        if !id.is_path() {\n            return None;\n        }\n        if let Ok(path) = id.url().to_file_path() {\n            if let Ok(pkg) = ws.load(&path.join(\"Cargo.toml\")) {\n                return Some(pkg);\n            }\n        }\n        None\n    };\n\n    // Ok so we've been passed in a `keep` function which basically says \"if I\n    // return `true` then this package wasn't listed for an update on the command\n    // line\". That is, if we run `cargo update foo` then `keep(bar)` will return\n    // `true`, whereas `keep(foo)` will return `false` (roughly speaking).\n    //\n    // This isn't actually quite what we want, however. Instead we want to\n    // further refine this `keep` function with *all transitive dependencies* of\n    // the packages we're not keeping. For example, consider a case like this:\n    //\n    // * There's a crate `log`.\n    // * There's a crate `serde` which depends on `log`.\n    //\n    // Let's say we then run `cargo update serde`. This may *also* want to\n    // update the `log` dependency as our newer version of `serde` may have a\n    // new minimum version required for `log`. Now this isn't always guaranteed\n    // to work. What'll happen here is we *won't* lock the `log` dependency nor\n    // the `log` crate itself, but we will inform the registry \"please prefer\n    // this version of `log`\". That way if our newer version of serde works with\n    // the older version of `log`, we conservatively won't update `log`. If,\n    // however, nothing else in the dependency graph depends on `log` and the\n    // newer version of `serde` requires a new version of `log` it'll get pulled\n    // in (as we didn't accidentally lock it to an old version).\n    let mut avoid_locking = HashSet::new();\n    registry.add_to_yanked_whitelist(resolve.iter().filter(keep));\n    for node in resolve.iter() {\n        if !keep(&node) {\n            add_deps(resolve, node, &mut avoid_locking);\n        }\n    }\n\n    // Ok, but the above loop isn't the entire story! Updates to the dependency\n    // graph can come from two locations, the `cargo update` command or\n    // manifests themselves. For example a manifest on the filesystem may\n    // have been updated to have an updated version requirement on `serde`. In\n    // this case both `keep(serde)` and `keep(log)` return `true` (the `keep`\n    // that's an argument to this function). We, however, don't want to keep\n    // either of those! Otherwise we'll get obscure resolve errors about locked\n    // versions.\n    //\n    // To solve this problem we iterate over all packages with path sources\n    // (aka ones with manifests that are changing) and take a look at all of\n    // their dependencies. If any dependency does not match something in the\n    // previous lock file, then we're guaranteed that the main resolver will\n    // update the source of this dependency no matter what. Knowing this we\n    // poison all packages from the same source, forcing them all to get\n    // updated.\n    //\n    // This may seem like a heavy hammer, and it is! It means that if you change\n    // anything from crates.io then all of crates.io becomes unlocked. Note,\n    // however, that we still want conservative updates. This currently happens\n    // because the first candidate the resolver picks is the previously locked\n    // version, and only if that fails to activate to we move on and try\n    // a different version. (giving the guise of conservative updates)\n    //\n    // For example let's say we had `serde = \"0.1\"` written in our lock file.\n    // When we later edit this to `serde = \"0.1.3\"` we don't want to lock serde\n    // at its old version, 0.1.1. Instead we want to allow it to update to\n    // `0.1.3` and update its own dependencies (like above). To do this *all\n    // crates from crates.io* are not locked (aka added to `avoid_locking`).\n    // For dependencies like `log` their previous version in the lock file will\n    // come up first before newer version, if newer version are available.\n    {\n        let _span = tracing::span!(tracing::Level::TRACE, \"poison\").entered();\n        let mut path_deps = ws.members().cloned().collect::<Vec<_>>();\n        let mut visited = HashSet::new();\n        while let Some(member) = path_deps.pop() {\n            if !visited.insert(member.package_id()) {\n                continue;\n            }\n            let is_ws_member = ws.is_member(&member);\n            for dep in member.dependencies() {\n                // If this dependency didn't match anything special then we may want\n                // to poison the source as it may have been added. If this path\n                // dependencies is **not** a workspace member, however, and it's an\n                // optional/non-transitive dependency then it won't be necessarily\n                // be in our lock file. If this shows up then we avoid poisoning\n                // this source as otherwise we'd repeatedly update the registry.\n                //\n                // TODO: this breaks adding an optional dependency in a\n                // non-workspace member and then simultaneously editing the\n                // dependency on that crate to enable the feature. For now,\n                // this bug is better than the always-updating registry though.\n                if !is_ws_member && (dep.is_optional() || !dep.is_transitive()) {\n                    continue;\n                }\n\n                // If dev-dependencies aren't being resolved, skip them.\n                if !dep.is_transitive() && !dev_deps {\n                    continue;\n                }\n\n                // If this is a path dependency, then try to push it onto our\n                // worklist.\n                if let Some(pkg) = path_pkg(dep.source_id()) {\n                    path_deps.push(pkg);\n                    continue;\n                }\n\n                // If we match *anything* in the dependency graph then we consider\n                // ourselves all ok, and assume that we'll resolve to that.\n                if resolve.iter().any(|id| dep.matches_ignoring_source(id)) {\n                    continue;\n                }\n\n                // Ok if nothing matches, then we poison the source of these\n                // dependencies and the previous lock file.\n                debug!(\n                    \"poisoning {} because {} looks like it changed {}\",\n                    dep.source_id(),\n                    member.package_id(),\n                    dep.package_name()\n                );\n                for id in resolve\n                    .iter()\n                    .filter(|id| id.source_id() == dep.source_id())\n                {\n                    add_deps(resolve, id, &mut avoid_locking);\n                }\n            }\n        }\n    }\n\n    // Additionally, here we process all path dependencies listed in the previous\n    // resolve. They can not only have their dependencies change but also\n    // the versions of the package change as well. If this ends up happening\n    // then we want to make sure we don't lock a package ID node that doesn't\n    // actually exist. Note that we don't do transitive visits of all the\n    // package's dependencies here as that'll be covered below to poison those\n    // if they changed.\n    //\n    // This must come after all other `add_deps` calls to ensure it recursively walks the tree when\n    // called.\n    for node in resolve.iter() {\n        if let Some(pkg) = path_pkg(node.source_id()) {\n            if pkg.package_id() != node {\n                avoid_locking.insert(node);\n            }\n        }\n    }\n\n    // Alright now that we've got our new, fresh, shiny, and refined `keep`\n    // function let's put it to action. Take a look at the previous lock file,\n    // filter everything by this callback, and then shove everything else into\n    // the registry as a locked dependency.\n    let keep = |id: &PackageId| keep(id) && !avoid_locking.contains(id);\n\n    registry.clear_lock();\n    {\n        let _span = tracing::span!(tracing::Level::TRACE, \"register_lock\").entered();\n        for node in resolve.iter().filter(keep) {\n            let deps = resolve\n                .deps_not_replaced(node)\n                .map(|p| p.0)\n                .filter(keep)\n                .collect::<Vec<_>>();\n\n            // In the v2 lockfile format and prior the `branch=master` dependency\n            // directive was serialized the same way as the no-branch-listed\n            // directive. Nowadays in Cargo, however, these two directives are\n            // considered distinct and are no longer represented the same way. To\n            // maintain compatibility with older lock files we register locked nodes\n            // for *both* the master branch and the default branch.\n            //\n            // Note that this is only applicable for loading older resolves now at\n            // this point. All new lock files are encoded as v3-or-later, so this is\n            // just compat for loading an old lock file successfully.\n            if let Some(node) = master_branch_git_source(node, resolve) {\n                registry.register_lock(node, deps.clone());\n            }\n\n            registry.register_lock(node, deps);\n        }\n    }\n\n    /// Recursively add `node` and all its transitive dependencies to `set`.\n    fn add_deps(resolve: &Resolve, node: PackageId, set: &mut HashSet<PackageId>) {\n        if !set.insert(node) {\n            return;\n        }\n        debug!(\"ignoring any lock pointing directly at {}\", node);\n        for (dep, _) in resolve.deps_not_replaced(node) {\n            add_deps(resolve, dep, set);\n        }\n    }\n}\n\nfn master_branch_git_source(id: PackageId, resolve: &Resolve) -> Option<PackageId> {\n    if resolve.version() <= ResolveVersion::V2 {\n        let source = id.source_id();\n        if let Some(GitReference::DefaultBranch) = source.git_reference() {\n            let new_source =\n                SourceId::for_git(source.url(), GitReference::Branch(\"master\".to_string()))\n                    .unwrap()\n                    .with_precise_from(source);\n            return Some(id.with_source_id(new_source));\n        }\n    }\n    None\n}\n\n/// Emits warnings of unused patches case by case.\n///\n/// This function does its best to provide more targeted and helpful\n/// (such as showing close candidates that failed to match). However, that's\n/// not terribly easy to do, so just show a general help message if we cannot.\nfn emit_warnings_of_unused_patches(\n    ws: &Workspace<'_>,\n    resolve: &Resolve,\n    registry: &PackageRegistry<'_>,\n) -> CargoResult<()> {\n    const MESSAGE: &str = \"was not used in the crate graph\";\n\n    // Patch package with the source URLs being patch\n    let mut patch_pkgid_to_urls = HashMap::new();\n    for (url, summaries) in registry.patches().iter() {\n        for summary in summaries.iter() {\n            patch_pkgid_to_urls\n                .entry(summary.package_id())\n                .or_insert_with(HashSet::new)\n                .insert(url);\n        }\n    }\n\n    // pkg name -> all source IDs of under the same pkg name\n    let mut source_ids_grouped_by_pkg_name = HashMap::new();\n    for pkgid in resolve.iter() {\n        source_ids_grouped_by_pkg_name\n            .entry(pkgid.name())\n            .or_insert_with(HashSet::new)\n            .insert(pkgid.source_id());\n    }\n\n    let mut unemitted_unused_patches = Vec::new();\n    for unused in resolve.unused_patches().iter() {\n        // Show alternative source URLs if the source URLs being patched\n        // cannot be found in the crate graph.\n        match (\n            source_ids_grouped_by_pkg_name.get(&unused.name()),\n            patch_pkgid_to_urls.get(unused),\n        ) {\n            (Some(ids), Some(patched_urls))\n                if ids\n                    .iter()\n                    .all(|id| !patched_urls.contains(id.canonical_url())) =>\n            {\n                let mut help = \"perhaps you meant one of the following:\".to_owned();\n                for id in ids {\n                    help.push_str(\"\\n\\t\");\n                    help.push_str(&id.display_registry_name());\n                }\n                ws.gctx().shell().print_report(\n                    &[Level::WARNING\n                        .secondary_title(format!(\"patch `{unused}` {MESSAGE}\"))\n                        .element(Level::HELP.message(help))],\n                    false,\n                )?;\n            }\n            _ => unemitted_unused_patches.push(unused),\n        }\n    }\n\n    // Show general help message.\n    if !unemitted_unused_patches.is_empty() {\n        let mut warnings: Vec<_> = unemitted_unused_patches\n            .iter()\n            .map(|pkgid| {\n                Group::with_title(\n                    Level::WARNING.secondary_title(format!(\"patch `{pkgid}` {MESSAGE}\")),\n                )\n            })\n            .collect();\n        warnings.push(Group::with_title(\n            Level::HELP.secondary_title(UNUSED_PATCH_WARNING),\n        ));\n        ws.gctx().shell().print_report(&warnings, false)?;\n    }\n\n    return Ok(());\n}\n\n/// Informs `registry` and `version_pref` that `[patch]` entries are available\n/// and preferable for the dependency resolution.\n///\n/// This returns a set of PackageIds of `[patch]` entries, and some related\n/// locked PackageIds, for which locking should be avoided (but which will be\n/// preferred when searching dependencies, via [`VersionPreferences::prefer_patch_deps`]).\n#[tracing::instrument(level = \"debug\", skip_all, ret)]\nfn register_patch_entries(\n    registry: &mut PackageRegistry<'_>,\n    ws: &Workspace<'_>,\n    previous: Option<&Resolve>,\n    version_prefs: &mut VersionPreferences,\n    keep_previous: Keep<'_>,\n) -> CargoResult<HashSet<PackageId>> {\n    let mut avoid_patch_ids = HashSet::new();\n    for (url, patches) in ws.root_patch()?.iter() {\n        for patch in patches {\n            version_prefs.prefer_dependency(patch.dep.clone());\n        }\n        let Some(previous) = previous else {\n            let patches: Vec<_> = patches.iter().map(|p| (p, None)).collect();\n            let unlock_ids = registry.patch(url, &patches)?;\n            // Since nothing is locked, this shouldn't possibly return anything.\n            assert!(unlock_ids.is_empty());\n            continue;\n        };\n\n        // This is a list of pairs where the first element of the pair is\n        // the raw `Dependency` which matches what's listed in `Cargo.toml`.\n        // The second element is, if present, the \"locked\" version of\n        // the `Dependency` as well as the `PackageId` that it previously\n        // resolved to. This second element is calculated by looking at the\n        // previous resolve graph, which is primarily what's done here to\n        // build the `registrations` list.\n        let mut registrations = Vec::new();\n        for patch in patches {\n            let dep = &patch.dep;\n            let candidates = || {\n                previous\n                    .iter()\n                    .chain(previous.unused_patches().iter().cloned())\n                    .filter(&keep_previous)\n            };\n\n            let lock = match candidates().find(|id| dep.matches_id(*id)) {\n                // If we found an exactly matching candidate in our list of\n                // candidates, then that's the one to use.\n                Some(package_id) => {\n                    let mut locked_dep = dep.clone();\n                    locked_dep.lock_to(package_id);\n                    Some(LockedPatchDependency {\n                        dependency: locked_dep,\n                        package_id,\n                        alt_package_id: None,\n                    })\n                }\n                None => {\n                    // If the candidate does not have a matching source id\n                    // then we may still have a lock candidate. If we're\n                    // loading a v2-encoded resolve graph and `dep` is a\n                    // git dep with `branch = 'master'`, then this should\n                    // also match candidates without `branch = 'master'`\n                    // (which is now treated separately in Cargo).\n                    //\n                    // In this scenario we try to convert candidates located\n                    // in the resolve graph to explicitly having the\n                    // `master` branch (if they otherwise point to\n                    // `DefaultBranch`). If this works and our `dep`\n                    // matches that then this is something we'll lock to.\n                    match candidates().find(|&id| match master_branch_git_source(id, previous) {\n                        Some(id) => dep.matches_id(id),\n                        None => false,\n                    }) {\n                        Some(id_using_default) => {\n                            let id_using_master = id_using_default.with_source_id(\n                                dep.source_id()\n                                    .with_precise_from(id_using_default.source_id()),\n                            );\n\n                            let mut locked_dep = dep.clone();\n                            locked_dep.lock_to(id_using_master);\n                            Some(LockedPatchDependency {\n                                dependency: locked_dep,\n                                package_id: id_using_master,\n                                // Note that this is where the magic\n                                // happens, where the resolve graph\n                                // probably has locks pointing to\n                                // DefaultBranch sources, and by including\n                                // this here those will get transparently\n                                // rewritten to Branch(\"master\") which we\n                                // have a lock entry for.\n                                alt_package_id: Some(id_using_default),\n                            })\n                        }\n\n                        // No locked candidate was found\n                        None => None,\n                    }\n                }\n            };\n\n            registrations.push((patch, lock));\n        }\n\n        let canonical = CanonicalUrl::new(url)?;\n        for (orig_patch, unlock_id) in registry.patch(url, &registrations)? {\n            // Avoid the locked patch ID.\n            avoid_patch_ids.insert(unlock_id);\n            // Also avoid the thing it is patching.\n            avoid_patch_ids.extend(previous.iter().filter(|id| {\n                orig_patch.dep.matches_ignoring_source(*id)\n                    && *id.source_id().canonical_url() == canonical\n            }));\n        }\n    }\n\n    Ok(avoid_patch_ids)\n}\n\n/// Locks each `[replace]` entry to a specific Package ID\n/// if the lockfile contains any corresponding previous replacement.\nfn lock_replacements(\n    ws: &Workspace<'_>,\n    previous: Option<&Resolve>,\n    keep: Keep<'_>,\n) -> Vec<(PackageIdSpec, Dependency)> {\n    let root_replace = ws.root_replace();\n    let replace = match previous {\n        Some(r) => root_replace\n            .iter()\n            .map(|(spec, dep)| {\n                for (&key, &val) in r.replacements().iter() {\n                    if spec.matches(key) && dep.matches_id(val) && keep(&val) {\n                        let mut dep = dep.clone();\n                        dep.lock_to(val);\n                        return (spec.clone(), dep);\n                    }\n                }\n                (spec.clone(), dep.clone())\n            })\n            .collect::<Vec<_>>(),\n        None => root_replace.to_vec(),\n    };\n    replace\n}\n"
  },
  {
    "path": "src/cargo/ops/tree/format/mod.rs",
    "content": "use std::fmt;\n\nuse anyhow::{Error, bail};\n\nuse self::parse::{Parser, RawChunk};\nuse super::{Graph, Node, NodeId};\n\nmod parse;\n\nenum Chunk {\n    Raw(String),\n    Package,\n    License,\n    Repository,\n    Features,\n    LibName,\n}\n\npub struct Pattern(Vec<Chunk>);\n\nimpl Pattern {\n    pub fn new(format: &str) -> Result<Pattern, Error> {\n        let mut chunks = vec![];\n\n        for raw in Parser::new(format) {\n            let chunk = match raw {\n                RawChunk::Text(text) => Chunk::Raw(text.to_owned()),\n                RawChunk::Argument(\"package\") | RawChunk::Argument(\"p\") => Chunk::Package,\n                RawChunk::Argument(\"license\") | RawChunk::Argument(\"l\") => Chunk::License,\n                RawChunk::Argument(\"repository\") | RawChunk::Argument(\"r\") => Chunk::Repository,\n                RawChunk::Argument(\"features\") | RawChunk::Argument(\"f\") => Chunk::Features,\n                RawChunk::Argument(\"lib\") => Chunk::LibName,\n                RawChunk::Argument(a) => {\n                    bail!(\"unsupported pattern `{}`\", a);\n                }\n                RawChunk::Error(err) => bail!(\"{}\", err),\n            };\n            chunks.push(chunk);\n        }\n\n        Ok(Pattern(chunks))\n    }\n\n    pub fn display<'a>(&'a self, graph: &'a Graph<'a>, node_index: NodeId) -> Display<'a> {\n        Display {\n            pattern: self,\n            graph,\n            node_index,\n        }\n    }\n}\n\npub struct Display<'a> {\n    pattern: &'a Pattern,\n    graph: &'a Graph<'a>,\n    node_index: NodeId,\n}\n\nimpl<'a> fmt::Display for Display<'a> {\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let node = self.graph.node(self.node_index);\n        match node {\n            Node::Package {\n                package_id,\n                features,\n                ..\n            } => {\n                let package = self.graph.package_for_id(*package_id);\n                for chunk in &self.pattern.0 {\n                    match chunk {\n                        Chunk::Raw(s) => fmt.write_str(s)?,\n                        Chunk::Package => {\n                            let proc_macro_suffix = if package.proc_macro() {\n                                \" (proc-macro)\"\n                            } else {\n                                \"\"\n                            };\n                            write!(\n                                fmt,\n                                \"{} v{}{}\",\n                                package.name(),\n                                package.version(),\n                                proc_macro_suffix\n                            )?;\n\n                            let source_id = package.package_id().source_id();\n                            if !source_id.is_crates_io() {\n                                write!(fmt, \" ({})\", source_id)?;\n                            }\n                        }\n                        Chunk::License => {\n                            if let Some(license) = &package.manifest().metadata().license {\n                                write!(fmt, \"{}\", license)?;\n                            }\n                        }\n                        Chunk::Repository => {\n                            if let Some(repository) = &package.manifest().metadata().repository {\n                                write!(fmt, \"{}\", repository)?;\n                            }\n                        }\n                        Chunk::Features => {\n                            write!(fmt, \"{}\", features.join(\",\"))?;\n                        }\n                        Chunk::LibName => {\n                            if let Some(target) = package\n                                .manifest()\n                                .targets()\n                                .iter()\n                                .find(|target| target.is_lib())\n                            {\n                                write!(fmt, \"{}\", target.crate_name())?;\n                            }\n                        }\n                    }\n                }\n            }\n            Node::Feature { name, node_index } => {\n                let for_node = self.graph.node(*node_index);\n                match for_node {\n                    Node::Package { package_id, .. } => {\n                        write!(fmt, \"{} feature \\\"{}\\\"\", package_id.name(), name)?;\n                        if self.graph.is_cli_feature(self.node_index) {\n                            write!(fmt, \" (command-line)\")?;\n                        }\n                    }\n                    // The node_index in Node::Feature must point to a package\n                    // node, see `add_feature`.\n                    _ => panic!(\"unexpected feature node {:?}\", for_node),\n                }\n            }\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/tree/format/parse.rs",
    "content": "//! Parser for the `--format` string for `cargo tree`.\n\nuse std::iter;\nuse std::str;\n\npub enum RawChunk<'a> {\n    /// Raw text to include in the output.\n    Text(&'a str),\n    /// A substitution to place in the output. For example, the argument \"p\"\n    /// emits the package name.\n    Argument(&'a str),\n    /// Indicates an error in the format string. The given string is a\n    /// human-readable message explaining the error.\n    Error(&'static str),\n}\n\n/// `cargo tree` format parser.\n///\n/// The format string indicates how each package should be displayed. It\n/// includes simple markers surrounded in curly braces that will be\n/// substituted with their corresponding values. For example, the text\n/// \"{p} license:{l}\" will substitute the `{p}` with the package name/version\n/// (and optionally source), and the `{l}` will be the license from\n/// `Cargo.toml`.\n///\n/// Substitutions are alphabetic characters between curly braces, like `{p}`\n/// or `{foo}`. The actual interpretation of these are done in the `Pattern`\n/// struct.\n///\n/// Bare curly braces can be included in the output with double braces like\n/// `{{` will include a single `{`, similar to Rust's format strings.\npub struct Parser<'a> {\n    s: &'a str,\n    it: iter::Peekable<str::CharIndices<'a>>,\n}\n\nimpl<'a> Parser<'a> {\n    pub fn new(s: &'a str) -> Parser<'a> {\n        Parser {\n            s,\n            it: s.char_indices().peekable(),\n        }\n    }\n\n    fn consume(&mut self, ch: char) -> bool {\n        match self.it.peek() {\n            Some(&(_, c)) if c == ch => {\n                self.it.next();\n                true\n            }\n            _ => false,\n        }\n    }\n\n    fn argument(&mut self) -> RawChunk<'a> {\n        RawChunk::Argument(self.name())\n    }\n\n    fn name(&mut self) -> &'a str {\n        let start = match self.it.peek() {\n            Some(&(pos, ch)) if ch.is_alphabetic() => {\n                self.it.next();\n                pos\n            }\n            _ => return \"\",\n        };\n\n        loop {\n            match self.it.peek() {\n                Some(&(_, ch)) if ch.is_alphanumeric() => {\n                    self.it.next();\n                }\n                Some(&(end, _)) => return &self.s[start..end],\n                None => return &self.s[start..],\n            }\n        }\n    }\n\n    fn text(&mut self, start: usize) -> RawChunk<'a> {\n        while let Some(&(pos, ch)) = self.it.peek() {\n            match ch {\n                '{' | '}' => return RawChunk::Text(&self.s[start..pos]),\n                _ => {\n                    self.it.next();\n                }\n            }\n        }\n        RawChunk::Text(&self.s[start..])\n    }\n}\n\nimpl<'a> Iterator for Parser<'a> {\n    type Item = RawChunk<'a>;\n\n    fn next(&mut self) -> Option<RawChunk<'a>> {\n        match self.it.peek() {\n            Some(&(_, '{')) => {\n                self.it.next();\n                if self.consume('{') {\n                    Some(RawChunk::Text(\"{\"))\n                } else {\n                    let chunk = self.argument();\n                    if self.consume('}') {\n                        Some(chunk)\n                    } else {\n                        for _ in &mut self.it {}\n                        Some(RawChunk::Error(\"expected '}'\"))\n                    }\n                }\n            }\n            Some(&(_, '}')) => {\n                self.it.next();\n                if self.consume('}') {\n                    Some(RawChunk::Text(\"}\"))\n                } else {\n                    Some(RawChunk::Error(\"unexpected '}'\"))\n                }\n            }\n            Some(&(i, _)) => Some(self.text(i)),\n            None => None,\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/tree/graph.rs",
    "content": "//! Code for building the graph used by `cargo tree`.\n\nuse super::TreeOptions;\nuse crate::core::compiler::{CompileKind, RustcTargetData};\nuse crate::core::dependency::DepKind;\nuse crate::core::resolver::Resolve;\nuse crate::core::resolver::features::{CliFeatures, FeaturesFor, ResolvedFeatures};\nuse crate::core::{FeatureMap, FeatureValue, Package, PackageId, PackageIdSpec, Workspace};\nuse crate::util::CargoResult;\nuse crate::util::interning::{INTERNED_DEFAULT, InternedString};\nuse std::collections::{HashMap, HashSet};\n\n#[derive(Debug, Copy, Clone)]\npub struct NodeId {\n    index: usize,\n    #[expect(dead_code, reason = \"intended for `derive(Debug)`\")]\n    debug: InternedString,\n}\n\nimpl NodeId {\n    fn new(index: usize, debug: InternedString) -> Self {\n        Self { index, debug }\n    }\n}\n\nimpl PartialEq for NodeId {\n    fn eq(&self, other: &Self) -> bool {\n        self.index == other.index\n    }\n}\n\nimpl Eq for NodeId {}\n\nimpl PartialOrd for NodeId {\n    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {\n        Some(self.cmp(other))\n    }\n}\n\nimpl Ord for NodeId {\n    fn cmp(&self, other: &Self) -> std::cmp::Ordering {\n        self.index.cmp(&other.index)\n    }\n}\n\nimpl std::hash::Hash for NodeId {\n    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n        self.index.hash(state)\n    }\n}\n\n#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]\npub enum Node {\n    Package {\n        package_id: PackageId,\n        /// Features that are enabled on this package.\n        features: Vec<InternedString>,\n        kind: CompileKind,\n    },\n    Feature {\n        /// Index of the package node this feature is for.\n        node_index: NodeId,\n        /// Name of the feature.\n        name: InternedString,\n    },\n}\n\nimpl Node {\n    fn name(&self) -> InternedString {\n        match self {\n            Self::Package { package_id, .. } => package_id.name(),\n            Self::Feature { name, .. } => *name,\n        }\n    }\n}\n\n#[derive(Debug, Copy, Hash, Eq, Clone, PartialEq)]\npub struct Edge {\n    kind: EdgeKind,\n    node: NodeId,\n    public: bool,\n}\n\nimpl Edge {\n    pub fn kind(&self) -> EdgeKind {\n        self.kind\n    }\n\n    pub fn node(&self) -> NodeId {\n        self.node\n    }\n\n    pub fn public(&self) -> bool {\n        self.public\n    }\n}\n\n/// The kind of edge, for separating dependencies into different sections.\n#[derive(Debug, Copy, Hash, Eq, Clone, PartialEq)]\npub enum EdgeKind {\n    Dep(DepKind),\n    Feature,\n}\n\n/// Set of outgoing edges for a single node.\n///\n/// Edges are separated by the edge kind (`DepKind` or `Feature`). This is\n/// primarily done so that the output can easily display separate sections\n/// like `[build-dependencies]`.\n///\n/// The value is a `Vec` because each edge kind can have multiple outgoing\n/// edges. For example, package \"foo\" can have multiple normal dependencies.\n#[derive(Clone, Debug)]\nstruct Edges(HashMap<EdgeKind, Vec<Edge>>);\n\nimpl Edges {\n    fn new() -> Edges {\n        Edges(HashMap::new())\n    }\n\n    /// Adds an edge pointing to the given node.\n    fn add_edge(&mut self, edge: Edge) {\n        let indexes = self.0.entry(edge.kind()).or_default();\n        if !indexes.contains(&edge) {\n            indexes.push(edge)\n        }\n    }\n\n    fn all(&self) -> impl Iterator<Item = &Edge> + '_ {\n        self.0.values().flatten()\n    }\n\n    fn of_kind(&self, kind: &EdgeKind) -> &[Edge] {\n        self.0.get(kind).map(Vec::as_slice).unwrap_or_default()\n    }\n\n    fn is_empty(&self) -> bool {\n        self.0.is_empty()\n    }\n}\n\n/// A graph of dependencies.\n#[derive(Debug)]\npub struct Graph<'a> {\n    nodes: Vec<Node>,\n    /// The indexes of `edges` correspond to the `nodes`. That is, `edges[0]`\n    /// is the set of outgoing edges for `nodes[0]`. They should always be in\n    /// sync.\n    edges: Vec<Edges>,\n    /// Index maps a node to an index, for fast lookup.\n    index: HashMap<Node, NodeId>,\n    /// Map for looking up packages.\n    package_map: HashMap<PackageId, &'a Package>,\n    /// Set of indexes of feature nodes that were added via the command-line.\n    ///\n    /// For example `--features foo` will mark the \"foo\" node here.\n    cli_features: HashSet<NodeId>,\n    /// Map of dependency names, used for building internal feature map for\n    /// `dep_name/feat_name` syntax.\n    ///\n    /// Key is the index of a package node, value is a map of `dep_name` to a\n    /// set of `(pkg_node_index, is_optional)`.\n    dep_name_map: HashMap<NodeId, HashMap<InternedString, HashSet<(NodeId, bool)>>>,\n}\n\nimpl<'a> Graph<'a> {\n    fn new(package_map: HashMap<PackageId, &'a Package>) -> Graph<'a> {\n        Graph {\n            nodes: Vec::new(),\n            edges: Vec::new(),\n            index: HashMap::new(),\n            package_map,\n            cli_features: HashSet::new(),\n            dep_name_map: HashMap::new(),\n        }\n    }\n\n    /// Adds a new node to the graph, returning its new index.\n    fn add_node(&mut self, node: Node) -> NodeId {\n        let from_index = NodeId::new(self.nodes.len(), node.name());\n        self.nodes.push(node);\n        self.edges.push(Edges::new());\n        self.index.insert(self.node(from_index).clone(), from_index);\n        from_index\n    }\n\n    /// Returns a list of nodes the given node index points to for the given kind.\n    pub fn edges_of_kind(&self, from: NodeId, kind: &EdgeKind) -> Vec<Edge> {\n        let edges = self.edges(from).of_kind(kind);\n        // Created a sorted list for consistent output.\n        let mut edges = edges.to_owned();\n        edges.sort_unstable_by(|a, b| self.node(a.node()).cmp(&self.node(b.node())));\n        edges\n    }\n\n    fn edges(&self, from: NodeId) -> &Edges {\n        &self.edges[from.index]\n    }\n\n    fn edges_mut(&mut self, from: NodeId) -> &mut Edges {\n        &mut self.edges[from.index]\n    }\n\n    /// Returns `true` if the given node has any outgoing edges.\n    pub fn has_outgoing_edges(&self, index: NodeId) -> bool {\n        !self.edges(index).is_empty()\n    }\n\n    /// Gets a node by index.\n    pub fn node(&self, index: NodeId) -> &Node {\n        &self.nodes[index.index]\n    }\n\n    /// Given a slice of `PackageIds`, returns the indexes of all nodes that match.\n    pub fn indexes_from_ids(&self, package_ids: &[PackageId]) -> Vec<NodeId> {\n        let mut result: Vec<(&Node, NodeId)> = self\n            .nodes\n            .iter()\n            .enumerate()\n            .filter(|(_i, node)| match node {\n                Node::Package { package_id, .. } => package_ids.contains(package_id),\n                _ => false,\n            })\n            .map(|(i, node)| (node, NodeId::new(i, node.name())))\n            .collect();\n        // Sort for consistent output (the same command should always return\n        // the same output). \"unstable\" since nodes should always be unique.\n        result.sort_unstable();\n        result.into_iter().map(|(_node, i)| i).collect()\n    }\n\n    pub fn package_for_id(&self, id: PackageId) -> &Package {\n        self.package_map[&id]\n    }\n\n    fn package_id_for_index(&self, index: NodeId) -> PackageId {\n        match self.node(index) {\n            Node::Package { package_id, .. } => *package_id,\n            Node::Feature { .. } => panic!(\"unexpected feature node\"),\n        }\n    }\n\n    /// Returns `true` if the given feature node index is a feature enabled\n    /// via the command-line.\n    pub fn is_cli_feature(&self, index: NodeId) -> bool {\n        self.cli_features.contains(&index)\n    }\n\n    /// Returns a new graph by removing all nodes not reachable from the\n    /// given nodes.\n    pub fn from_reachable(&self, roots: &[NodeId]) -> Graph<'a> {\n        // Graph built with features does not (yet) support --duplicates.\n        assert!(self.dep_name_map.is_empty());\n        let mut new_graph = Graph::new(self.package_map.clone());\n        // Maps old index to new index. None if not yet visited.\n        let mut remap: Vec<Option<NodeId>> = vec![None; self.nodes.len()];\n\n        fn visit(\n            graph: &Graph<'_>,\n            new_graph: &mut Graph<'_>,\n            remap: &mut Vec<Option<NodeId>>,\n            index: NodeId,\n        ) -> NodeId {\n            if let Some(new_index) = remap[index.index] {\n                // Already visited.\n                return new_index;\n            }\n            let node = graph.node(index).clone();\n            let new_from = new_graph.add_node(node);\n            remap[index.index] = Some(new_from);\n            // Visit dependencies.\n            for edge in graph.edges(index).all() {\n                let new_to_index = visit(graph, new_graph, remap, edge.node());\n                let new_edge = Edge {\n                    kind: edge.kind(),\n                    node: new_to_index,\n                    public: edge.public(),\n                };\n                new_graph.edges_mut(new_from).add_edge(new_edge);\n            }\n            new_from\n        }\n\n        // Walk the roots, generating a new graph as it goes along.\n        for root in roots {\n            visit(self, &mut new_graph, &mut remap, *root);\n        }\n\n        new_graph\n    }\n\n    /// Inverts the direction of all edges.\n    pub fn invert(&mut self) {\n        let mut new_edges = vec![Edges::new(); self.edges.len()];\n        for (from_idx, node_edges) in self.edges.iter().enumerate() {\n            for edge in node_edges.all() {\n                let new_edge = Edge {\n                    kind: edge.kind(),\n                    node: NodeId::new(from_idx, self.nodes[from_idx].name()),\n                    public: edge.public(),\n                };\n                new_edges[edge.node().index].add_edge(new_edge);\n            }\n        }\n        self.edges = new_edges;\n    }\n\n    /// Returns a list of nodes that are considered \"duplicates\" (same package\n    /// name, with different versions/features/source/etc.).\n    pub fn find_duplicates(&self) -> Vec<NodeId> {\n        // Graph built with features does not (yet) support --duplicates.\n        assert!(self.dep_name_map.is_empty());\n\n        // Collect a map of package name to Vec<(&Node, NodeId)>.\n        let mut packages = HashMap::new();\n        for (i, node) in self.nodes.iter().enumerate() {\n            if let Node::Package { package_id, .. } = node {\n                packages\n                    .entry(package_id.name())\n                    .or_insert_with(Vec::new)\n                    .push((node, NodeId::new(i, node.name())));\n            }\n        }\n\n        let mut dupes: Vec<(&Node, NodeId)> = packages\n            .into_iter()\n            .filter(|(_name, indexes)| {\n                indexes\n                    .into_iter()\n                    .map(|(node, _)| {\n                        match node {\n                            Node::Package {\n                                package_id,\n                                features,\n                                ..\n                            } => {\n                                // Do not treat duplicates on the host or target as duplicates.\n                                Node::Package {\n                                    package_id: package_id.clone(),\n                                    features: features.clone(),\n                                    kind: CompileKind::Host,\n                                }\n                            }\n                            _ => unreachable!(),\n                        }\n                    })\n                    .collect::<HashSet<_>>()\n                    .len()\n                    > 1\n            })\n            .flat_map(|(_name, indexes)| indexes)\n            .collect();\n\n        // For consistent output.\n        dupes.sort_unstable();\n        dupes.into_iter().map(|(_node, i)| i).collect()\n    }\n}\n\n/// Builds the graph.\npub fn build<'a>(\n    ws: &Workspace<'_>,\n    resolve: &Resolve,\n    resolved_features: &ResolvedFeatures,\n    specs: &[PackageIdSpec],\n    cli_features: &CliFeatures,\n    target_data: &RustcTargetData<'_>,\n    requested_kinds: &[CompileKind],\n    package_map: HashMap<PackageId, &'a Package>,\n    opts: &TreeOptions,\n) -> CargoResult<Graph<'a>> {\n    let mut graph = Graph::new(package_map);\n    let mut members_with_features = ws.members_with_features(specs, cli_features)?;\n    members_with_features.sort_unstable_by_key(|(member, _)| member.package_id());\n    for (member, cli_features) in members_with_features {\n        let member_id = member.package_id();\n        let features_for = FeaturesFor::from_for_host(member.proc_macro());\n        for kind in requested_kinds {\n            let member_index = add_pkg(\n                &mut graph,\n                resolve,\n                resolved_features,\n                member_id,\n                features_for,\n                target_data,\n                *kind,\n                opts,\n            );\n            if opts.graph_features {\n                let fmap = resolve.summary(member_id).features();\n                add_cli_features(&mut graph, member_index, &cli_features, fmap);\n            }\n        }\n    }\n    if opts.graph_features {\n        add_internal_features(&mut graph, resolve);\n    }\n    Ok(graph)\n}\n\n/// Adds a single package node (if it does not already exist).\n///\n/// This will also recursively add all of its dependencies.\n///\n/// Returns the index to the package node.\nfn add_pkg(\n    graph: &mut Graph<'_>,\n    resolve: &Resolve,\n    resolved_features: &ResolvedFeatures,\n    package_id: PackageId,\n    features_for: FeaturesFor,\n    target_data: &RustcTargetData<'_>,\n    requested_kind: CompileKind,\n    opts: &TreeOptions,\n) -> NodeId {\n    let node_features = resolved_features.activated_features(package_id, features_for);\n    let node_kind = match features_for {\n        FeaturesFor::HostDep => CompileKind::Host,\n        FeaturesFor::ArtifactDep(target) => CompileKind::Target(target),\n        FeaturesFor::NormalOrDev => requested_kind,\n    };\n    let node = Node::Package {\n        package_id,\n        features: node_features,\n        kind: node_kind,\n    };\n    if let Some(idx) = graph.index.get(&node) {\n        return *idx;\n    }\n    let from_index = graph.add_node(node);\n    // Compute the dep name map which is later used for foo/bar feature lookups.\n    let mut dep_name_map: HashMap<InternedString, HashSet<(NodeId, bool)>> = HashMap::new();\n    let mut deps: Vec<_> = resolve.deps(package_id).collect();\n    deps.sort_unstable_by_key(|(dep_id, _)| *dep_id);\n    let show_all_targets = opts.target == super::Target::All;\n    for (dep_id, deps) in deps {\n        let mut deps: Vec<_> = deps\n            .iter()\n            // This filter is *similar* to the one found in `unit_dependencies::compute_deps`.\n            // Try to keep them in sync!\n            .filter(|dep| {\n                let kind = match (node_kind, dep.kind()) {\n                    (CompileKind::Host, _) => CompileKind::Host,\n                    (_, DepKind::Build) => CompileKind::Host,\n                    (_, DepKind::Normal) => node_kind,\n                    (_, DepKind::Development) => node_kind,\n                };\n                // Filter out inactivated targets.\n                if !show_all_targets && !target_data.dep_platform_activated(dep, kind) {\n                    return false;\n                }\n                // Filter out dev-dependencies if requested.\n                if !opts.edge_kinds.contains(&EdgeKind::Dep(dep.kind())) {\n                    return false;\n                }\n                // Filter out proc-macros if requested.\n                if opts.no_proc_macro && graph.package_for_id(dep_id).proc_macro() {\n                    return false;\n                }\n                // Filter out private dependencies if requested.\n                if opts.public && !dep.is_public() {\n                    return false;\n                }\n                if dep.is_optional() {\n                    // If the new feature resolver does not enable this\n                    // optional dep, then don't use it.\n                    if !resolved_features.is_dep_activated(\n                        package_id,\n                        features_for,\n                        dep.name_in_toml(),\n                    ) {\n                        return false;\n                    }\n                }\n                true\n            })\n            .collect();\n\n        // This dependency is eliminated from the dependency tree under\n        // the current target and feature set.\n        if deps.is_empty() {\n            continue;\n        }\n\n        deps.sort_unstable_by_key(|dep| (dep.kind(), dep.name_in_toml()));\n        let dep_pkg = graph.package_map[&dep_id];\n\n        for dep in deps {\n            let dep_features_for = match dep\n                .artifact()\n                .and_then(|artifact| artifact.target())\n                .and_then(|target| target.to_resolved_compile_target(requested_kind))\n            {\n                // Dependency has a `{ …, target = <triple> }`\n                Some(target) => FeaturesFor::ArtifactDep(target),\n                // Get the information of the dependent crate from `features_for`.\n                // If a dependent crate is\n                //\n                // * specified as an artifact dep with a `target`, or\n                // * a host dep,\n                //\n                // its transitive deps, including build-deps, need to be built on that target.\n                None if features_for != FeaturesFor::default() => features_for,\n                // Dependent crate is a normal dep, then back to old rules:\n                //\n                // * normal deps, dev-deps -> inherited target\n                // * build-deps -> host\n                None => {\n                    if dep.is_build() || dep_pkg.proc_macro() {\n                        FeaturesFor::HostDep\n                    } else {\n                        features_for\n                    }\n                }\n            };\n            let dep_index = add_pkg(\n                graph,\n                resolve,\n                resolved_features,\n                dep_id,\n                dep_features_for,\n                target_data,\n                requested_kind,\n                opts,\n            );\n            let new_edge = Edge {\n                kind: EdgeKind::Dep(dep.kind()),\n                node: dep_index,\n                public: dep.is_public(),\n            };\n            if opts.graph_features {\n                // Add the dependency node with feature nodes in-between.\n                dep_name_map\n                    .entry(dep.name_in_toml())\n                    .or_default()\n                    .insert((dep_index, dep.is_optional()));\n                if dep.uses_default_features() {\n                    add_feature(graph, INTERNED_DEFAULT, Some(from_index), new_edge);\n                }\n                for feature in dep.features().iter() {\n                    add_feature(graph, *feature, Some(from_index), new_edge);\n                }\n                if !dep.uses_default_features() && dep.features().is_empty() {\n                    // No features, use a direct connection.\n                    graph.edges_mut(from_index).add_edge(new_edge);\n                }\n            } else {\n                graph.edges_mut(from_index).add_edge(new_edge);\n            }\n        }\n    }\n    if opts.graph_features {\n        assert!(\n            graph\n                .dep_name_map\n                .insert(from_index, dep_name_map)\n                .is_none()\n        );\n    }\n\n    from_index\n}\n\n/// Adds a feature node between two nodes.\n///\n/// That is, it adds the following:\n///\n/// ```text\n/// from -Edge-> featname -Edge::Feature-> to\n/// ```\n///\n/// Returns a tuple `(missing, index)`.\n/// `missing` is true if this feature edge was already added.\n/// `index` is the index of the index in the graph of the `Feature` node.\nfn add_feature(\n    graph: &mut Graph<'_>,\n    name: InternedString,\n    from: Option<NodeId>,\n    to: Edge,\n) -> (bool, NodeId) {\n    // `to` *must* point to a package node.\n    assert!(matches! {graph.node(to.node()), Node::Package{..}});\n    let node = Node::Feature {\n        node_index: to.node(),\n        name,\n    };\n    let (missing, node_index) = match graph.index.get(&node) {\n        Some(idx) => (false, *idx),\n        None => (true, graph.add_node(node)),\n    };\n    if let Some(from) = from {\n        let from_edge = Edge {\n            kind: to.kind(),\n            node: node_index,\n            public: to.public(),\n        };\n        graph.edges_mut(from).add_edge(from_edge);\n    }\n    let to_edge = Edge {\n        kind: EdgeKind::Feature,\n        node: to.node(),\n        public: true,\n    };\n    graph.edges_mut(node_index).add_edge(to_edge);\n    (missing, node_index)\n}\n\n/// Adds nodes for features requested on the command-line for the given member.\n///\n/// Feature nodes are added as \"roots\" (i.e., they have no \"from\" index),\n/// because they come from the outside world. They usually only appear with\n/// `--invert`.\nfn add_cli_features(\n    graph: &mut Graph<'_>,\n    package_index: NodeId,\n    cli_features: &CliFeatures,\n    feature_map: &FeatureMap,\n) {\n    // NOTE: Recursive enabling of features will be handled by\n    // add_internal_features.\n\n    // Create a set of feature names requested on the command-line.\n    let mut to_add: HashSet<FeatureValue> = HashSet::new();\n    if cli_features.all_features {\n        to_add.extend(feature_map.keys().map(|feat| FeatureValue::Feature(*feat)));\n    }\n\n    if cli_features.uses_default_features {\n        to_add.insert(FeatureValue::Feature(INTERNED_DEFAULT));\n    }\n    to_add.extend(cli_features.features.iter().cloned());\n\n    // Add each feature as a node, and mark as \"from command-line\" in graph.cli_features.\n    for fv in to_add {\n        match fv {\n            FeatureValue::Feature(feature) => {\n                let feature_edge = Edge {\n                    kind: EdgeKind::Feature,\n                    node: package_index,\n                    public: true,\n                };\n                let index = add_feature(graph, feature, None, feature_edge).1;\n                graph.cli_features.insert(index);\n            }\n            // This is enforced by CliFeatures.\n            FeatureValue::Dep { .. } => panic!(\"unexpected cli dep feature {}\", fv),\n            FeatureValue::DepFeature {\n                dep_name,\n                dep_feature,\n                weak,\n            } => {\n                let dep_connections = match graph.dep_name_map[&package_index].get(&dep_name) {\n                    // Clone to deal with immutable borrow of `graph`. :(\n                    Some(dep_connections) => dep_connections.clone(),\n                    None => {\n                        // --features bar?/feat where `bar` is not activated should be ignored.\n                        // If this wasn't weak, then this is a bug.\n                        if weak {\n                            continue;\n                        }\n                        panic!(\n                            \"missing dep graph connection for CLI feature `{}` for member {:?}\\n\\\n                             Please file a bug report at https://github.com/rust-lang/cargo/issues\",\n                            fv,\n                            graph.nodes.get(package_index.index)\n                        );\n                    }\n                };\n                for (dep_index, is_optional) in dep_connections {\n                    if is_optional {\n                        // Activate the optional dep on self.\n                        let feature_edge = Edge {\n                            kind: EdgeKind::Feature,\n                            node: package_index,\n                            public: true,\n                        };\n                        let index = add_feature(graph, dep_name, None, feature_edge).1;\n                        graph.cli_features.insert(index);\n                    }\n                    let dep_edge = Edge {\n                        kind: EdgeKind::Feature,\n                        node: dep_index,\n                        public: true,\n                    };\n                    let index = add_feature(graph, dep_feature, None, dep_edge).1;\n                    graph.cli_features.insert(index);\n                }\n            }\n        }\n    }\n}\n\n/// Recursively adds connections between features in the `[features]` table\n/// for every package.\nfn add_internal_features(graph: &mut Graph<'_>, resolve: &Resolve) {\n    // Collect features already activated by dependencies or command-line.\n    let feature_nodes: Vec<(PackageId, NodeId, NodeId, InternedString)> = graph\n        .nodes\n        .iter()\n        .enumerate()\n        .filter_map(|(i, node)| match node {\n            Node::Package { .. } => None,\n            Node::Feature { node_index, name } => {\n                let package_id = graph.package_id_for_index(*node_index);\n                Some((package_id, *node_index, NodeId::new(i, *name), *name))\n            }\n        })\n        .collect();\n\n    for (package_id, package_index, feature_index, feature_name) in feature_nodes {\n        add_feature_rec(\n            graph,\n            resolve,\n            feature_name,\n            package_id,\n            feature_index,\n            package_index,\n        );\n    }\n}\n\n/// Recursively add feature nodes for all features enabled by the given feature.\n///\n/// `from` is the index of the node that enables this feature.\n/// `package_index` is the index of the package node for the feature.\nfn add_feature_rec(\n    graph: &mut Graph<'_>,\n    resolve: &Resolve,\n    feature_name: InternedString,\n    package_id: PackageId,\n    from: NodeId,\n    package_index: NodeId,\n) {\n    let feature_map = resolve.summary(package_id).features();\n    let Some(fvs) = feature_map.get(&feature_name) else {\n        return;\n    };\n    for fv in fvs {\n        match fv {\n            FeatureValue::Feature(dep_name) => {\n                let feature_edge = Edge {\n                    kind: EdgeKind::Feature,\n                    node: package_index,\n                    public: true,\n                };\n                let (missing, feat_index) = add_feature(graph, *dep_name, Some(from), feature_edge);\n                // Don't recursive if the edge already exists to deal with cycles.\n                if missing {\n                    add_feature_rec(\n                        graph,\n                        resolve,\n                        *dep_name,\n                        package_id,\n                        feat_index,\n                        package_index,\n                    );\n                }\n            }\n            // Dependencies are already shown in the graph as dep edges. I'm\n            // uncertain whether or not this might be confusing in some cases\n            // (like feature `\"somefeat\" = [\"dep:somedep\"]`), so maybe in the\n            // future consider explicitly showing this?\n            FeatureValue::Dep { .. } => {}\n            FeatureValue::DepFeature {\n                dep_name,\n                dep_feature,\n                // Note: `weak` is mostly handled when the graph is built in\n                // `is_dep_activated` which is responsible for skipping\n                // unactivated weak dependencies. Here it is only used to\n                // determine if the feature of the dependency name is\n                // activated on self.\n                weak,\n            } => {\n                let dep_indexes = match graph.dep_name_map[&package_index].get(dep_name) {\n                    Some(indexes) => indexes.clone(),\n                    None => {\n                        tracing::debug!(\n                            \"enabling feature {} on {}, found {}/{}, \\\n                             dep appears to not be enabled\",\n                            feature_name,\n                            package_id,\n                            dep_name,\n                            dep_feature\n                        );\n                        continue;\n                    }\n                };\n                for (dep_index, is_optional) in dep_indexes {\n                    let dep_pkg_id = graph.package_id_for_index(dep_index);\n                    if is_optional && !weak {\n                        // Activate the optional dep on self.\n                        let feature_edge = Edge {\n                            kind: EdgeKind::Feature,\n                            node: package_index,\n                            public: true,\n                        };\n                        add_feature(graph, *dep_name, Some(from), feature_edge);\n                    }\n                    let dep_edge = Edge {\n                        kind: EdgeKind::Feature,\n                        node: dep_index,\n                        public: true,\n                    };\n                    let (missing, feat_index) =\n                        add_feature(graph, *dep_feature, Some(from), dep_edge);\n                    if missing {\n                        add_feature_rec(\n                            graph,\n                            resolve,\n                            *dep_feature,\n                            dep_pkg_id,\n                            feat_index,\n                            dep_index,\n                        );\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/tree/mod.rs",
    "content": "//! Implementation of `cargo tree`.\n\nuse self::format::Pattern;\nuse crate::core::compiler::{CompileKind, RustcTargetData};\nuse crate::core::dependency::DepKind;\nuse crate::core::resolver::{ForceAllTargets, HasDevUnits, features::CliFeatures};\nuse crate::core::{Package, PackageId, PackageIdSpec, PackageIdSpecQuery, Workspace};\nuse crate::ops::resolve::SpecsAndResolvedFeatures;\nuse crate::ops::{self, Packages};\nuse crate::util::CargoResult;\nuse crate::util::style;\nuse crate::{drop_print, drop_println};\nuse anyhow::Context as _;\nuse graph::Graph;\nuse std::collections::{HashMap, HashSet};\nuse std::str::FromStr;\n\nmod format;\nmod graph;\n\npub use {graph::EdgeKind, graph::Node, graph::NodeId};\n\npub struct TreeOptions {\n    pub cli_features: CliFeatures,\n    /// The packages to display the tree for.\n    pub packages: Packages,\n    /// The platform to filter for.\n    pub target: Target,\n    /// The dependency kinds to display.\n    pub edge_kinds: HashSet<EdgeKind>,\n    pub invert: Vec<String>,\n    /// The packages to prune from the display of the dependency tree.\n    pub pkgs_to_prune: Vec<String>,\n    /// The style of prefix for each line.\n    pub prefix: Prefix,\n    /// If `true`, duplicates will be repeated.\n    /// If `false`, duplicates will be marked with `*`, and their dependencies\n    /// won't be shown.\n    pub no_dedupe: bool,\n    /// If `true`, run in a special mode where it will scan for packages that\n    /// appear with different versions, and report if any where found. Implies\n    /// `invert`.\n    pub duplicates: bool,\n    /// A format string indicating how each package should be displayed.\n    pub format: String,\n    /// Includes features in the tree as separate nodes.\n    pub graph_features: bool,\n    /// Display depth of the dependency tree.\n    /// If non-negative integer, display dependencies with that amount of max depth.\n    /// If `workspace`, display dependencies from current workspace only.\n    pub display_depth: DisplayDepth,\n    /// Excludes proc-macro dependencies.\n    pub no_proc_macro: bool,\n    /// Include only public dependencies.\n    pub public: bool,\n}\n\n#[derive(PartialEq)]\npub enum Target {\n    Host,\n    Specific(Vec<String>),\n    All,\n}\n\nimpl Target {\n    pub fn from_cli(targets: Vec<String>) -> Target {\n        match targets.len() {\n            0 => Target::Host,\n            1 if targets[0] == \"all\" => Target::All,\n            _ => Target::Specific(targets),\n        }\n    }\n}\n\n#[derive(Clone, Copy)]\npub enum Prefix {\n    None,\n    Indent,\n    Depth,\n}\n\nimpl FromStr for Prefix {\n    type Err = &'static str;\n\n    fn from_str(s: &str) -> Result<Prefix, &'static str> {\n        match s {\n            \"none\" => Ok(Prefix::None),\n            \"indent\" => Ok(Prefix::Indent),\n            \"depth\" => Ok(Prefix::Depth),\n            _ => Err(\"invalid prefix\"),\n        }\n    }\n}\n\n#[derive(Clone, Copy)]\npub enum DisplayDepth {\n    MaxDisplayDepth(u32),\n    Workspace,\n}\n\nimpl FromStr for DisplayDepth {\n    type Err = clap::Error;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        match s {\n            \"workspace\" => Ok(Self::Workspace),\n            s => s.parse().map(Self::MaxDisplayDepth).map_err(|_| {\n                clap::Error::raw(\n                    clap::error::ErrorKind::ValueValidation,\n                    format!(\n                        \"supported values for --depth are non-negative integers and `workspace`, \\\n                                but `{}` is unknown\",\n                        s\n                    ),\n                )\n            }),\n        }\n    }\n}\n\nstruct Symbols {\n    down: &'static str,\n    tee: &'static str,\n    ell: &'static str,\n    right: &'static str,\n}\n\nstatic UTF8_SYMBOLS: Symbols = Symbols {\n    down: \"│\",\n    tee: \"├\",\n    ell: \"└\",\n    right: \"─\",\n};\n\nstatic ASCII_SYMBOLS: Symbols = Symbols {\n    down: \"|\",\n    tee: \"|\",\n    ell: \"`\",\n    right: \"-\",\n};\n\n/// Entry point for the `cargo tree` command.\npub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()> {\n    let requested_targets = match &opts.target {\n        Target::All | Target::Host => Vec::new(),\n        Target::Specific(t) => t.clone(),\n    };\n    // TODO: Target::All is broken with -Zfeatures=itarget. To handle that properly,\n    // `FeatureResolver` will need to be taught what \"all\" means.\n    let requested_kinds = CompileKind::from_requested_targets(ws.gctx(), &requested_targets)?;\n    let mut target_data = RustcTargetData::new(ws, &requested_kinds)?;\n    let specs = opts.packages.to_package_id_specs(ws)?;\n    let has_dev = if opts\n        .edge_kinds\n        .contains(&EdgeKind::Dep(DepKind::Development))\n    {\n        HasDevUnits::Yes\n    } else {\n        HasDevUnits::No\n    };\n    let force_all = if opts.target == Target::All {\n        ForceAllTargets::Yes\n    } else {\n        ForceAllTargets::No\n    };\n    let dry_run = false;\n    let ws_resolve = ops::resolve_ws_with_opts(\n        ws,\n        &mut target_data,\n        &requested_kinds,\n        &opts.cli_features,\n        &specs,\n        has_dev,\n        force_all,\n        dry_run,\n    )?;\n\n    let package_map: HashMap<PackageId, &Package> = ws_resolve\n        .pkg_set\n        .packages()\n        .map(|pkg| (pkg.package_id(), pkg))\n        .collect();\n\n    for SpecsAndResolvedFeatures {\n        specs,\n        resolved_features,\n    } in ws_resolve.specs_and_features\n    {\n        let mut graph = graph::build(\n            ws,\n            &ws_resolve.targeted_resolve,\n            &resolved_features,\n            &specs,\n            &opts.cli_features,\n            &target_data,\n            &requested_kinds,\n            package_map.clone(),\n            opts,\n        )?;\n\n        let root_specs = if opts.invert.is_empty() {\n            specs\n        } else {\n            opts.invert\n                .iter()\n                .map(|p| PackageIdSpec::parse(p))\n                .collect::<Result<Vec<PackageIdSpec>, _>>()?\n        };\n        let root_ids = ws_resolve.targeted_resolve.specs_to_ids(&root_specs)?;\n        let root_indexes = graph.indexes_from_ids(&root_ids);\n\n        let root_indexes = if opts.duplicates {\n            // `-d -p foo` will only show duplicates within foo's subtree\n            graph = graph.from_reachable(root_indexes.as_slice());\n            graph.find_duplicates()\n        } else {\n            root_indexes\n        };\n\n        if !opts.invert.is_empty() || opts.duplicates {\n            graph.invert();\n        }\n\n        // Packages to prune.\n        let pkgs_to_prune = opts\n            .pkgs_to_prune\n            .iter()\n            .map(|p| PackageIdSpec::parse(p).map_err(Into::into))\n            .map(|r| {\n                // Provide an error message if pkgid is not within the resolved\n                // dependencies graph.\n                r.and_then(|spec| spec.query(ws_resolve.targeted_resolve.iter()).and(Ok(spec)))\n            })\n            .collect::<CargoResult<Vec<PackageIdSpec>>>()?;\n\n        if root_indexes.len() == 0 {\n            ws.gctx().shell().warn(\n                \"nothing to print.\\n\\n\\\n            To find dependencies that require specific target platforms, \\\n            try to use option `--target all` first, and then narrow your search scope accordingly.\",\n            )?;\n        } else {\n            print(ws, opts, root_indexes, &pkgs_to_prune, &graph)?;\n        }\n    }\n    Ok(())\n}\n\n/// Prints a tree for each given root.\nfn print(\n    ws: &Workspace<'_>,\n    opts: &TreeOptions,\n    roots: Vec<NodeId>,\n    pkgs_to_prune: &[PackageIdSpec],\n    graph: &Graph<'_>,\n) -> CargoResult<()> {\n    let format = Pattern::new(&opts.format)\n        .with_context(|| format!(\"tree format `{}` not valid\", opts.format))?;\n\n    let symbols = if ws.gctx().shell().out_unicode() {\n        &UTF8_SYMBOLS\n    } else {\n        &ASCII_SYMBOLS\n    };\n\n    // The visited deps is used to display a (*) whenever a dep has\n    // already been printed (ignored with --no-dedupe).\n    let mut visited_deps = HashSet::new();\n\n    for (i, root_index) in roots.into_iter().enumerate() {\n        if i != 0 {\n            drop_println!(ws.gctx());\n        }\n\n        // A stack of bools used to determine where | symbols should appear\n        // when printing a line.\n        let mut levels_continue = vec![];\n        // The print stack is used to detect dependency cycles when\n        // --no-dedupe is used. It contains a Node for each level.\n        let mut print_stack = vec![];\n\n        print_node(\n            ws,\n            graph,\n            root_index,\n            &format,\n            symbols,\n            pkgs_to_prune,\n            opts.prefix,\n            opts.no_dedupe,\n            opts.display_depth,\n            &mut visited_deps,\n            &mut levels_continue,\n            &mut print_stack,\n        )?;\n    }\n\n    Ok(())\n}\n\n/// Prints a package and all of its dependencies.\nfn print_node<'a>(\n    ws: &Workspace<'_>,\n    graph: &'a Graph<'_>,\n    node_index: NodeId,\n    format: &Pattern,\n    symbols: &Symbols,\n    pkgs_to_prune: &[PackageIdSpec],\n    prefix: Prefix,\n    no_dedupe: bool,\n    display_depth: DisplayDepth,\n    visited_deps: &mut HashSet<NodeId>,\n    levels_continue: &mut Vec<(anstyle::Style, bool)>,\n    print_stack: &mut Vec<NodeId>,\n) -> CargoResult<()> {\n    let new = no_dedupe || visited_deps.insert(node_index);\n\n    match prefix {\n        Prefix::Depth => drop_print!(ws.gctx(), \"{}\", levels_continue.len()),\n        Prefix::Indent => {\n            if let Some(((last_style, last_continues), rest)) = levels_continue.split_last() {\n                for (style, continues) in rest {\n                    let c = if *continues { symbols.down } else { \" \" };\n                    drop_print!(ws.gctx(), \"{style}{c}{style:#}   \");\n                }\n\n                let c = if *last_continues {\n                    symbols.tee\n                } else {\n                    symbols.ell\n                };\n                drop_print!(\n                    ws.gctx(),\n                    \"{last_style}{0}{1}{1}{last_style:#} \",\n                    c,\n                    symbols.right\n                );\n            }\n        }\n        Prefix::None => {}\n    }\n\n    let in_cycle = print_stack.contains(&node_index);\n    // If this node does not have any outgoing edges, don't include the (*)\n    // since there isn't really anything \"deduplicated\", and it generally just\n    // adds noise.\n    let has_deps = graph.has_outgoing_edges(node_index);\n    let star = if (new && !in_cycle) || !has_deps {\n        \"\"\n    } else {\n        color_print::cstr!(\" <yellow,dim>(*)</>\")\n    };\n    drop_println!(ws.gctx(), \"{}{}\", format.display(graph, node_index), star);\n\n    if !new || in_cycle {\n        return Ok(());\n    }\n    print_stack.push(node_index);\n\n    for kind in &[\n        EdgeKind::Dep(DepKind::Normal),\n        EdgeKind::Dep(DepKind::Build),\n        EdgeKind::Dep(DepKind::Development),\n        EdgeKind::Feature,\n    ] {\n        print_dependencies(\n            ws,\n            graph,\n            node_index,\n            format,\n            symbols,\n            pkgs_to_prune,\n            prefix,\n            no_dedupe,\n            display_depth,\n            visited_deps,\n            levels_continue,\n            print_stack,\n            kind,\n        )?;\n    }\n    print_stack.pop();\n\n    Ok(())\n}\n\n/// Prints all the dependencies of a package for the given dependency kind.\nfn print_dependencies<'a>(\n    ws: &Workspace<'_>,\n    graph: &'a Graph<'_>,\n    node_index: NodeId,\n    format: &Pattern,\n    symbols: &Symbols,\n    pkgs_to_prune: &[PackageIdSpec],\n    prefix: Prefix,\n    no_dedupe: bool,\n    display_depth: DisplayDepth,\n    visited_deps: &mut HashSet<NodeId>,\n    levels_continue: &mut Vec<(anstyle::Style, bool)>,\n    print_stack: &mut Vec<NodeId>,\n    kind: &EdgeKind,\n) -> CargoResult<()> {\n    let deps = graph.edges_of_kind(node_index, kind);\n    if deps.is_empty() {\n        return Ok(());\n    }\n\n    let name = match kind {\n        EdgeKind::Dep(DepKind::Normal) => None,\n        EdgeKind::Dep(DepKind::Build) => Some(color_print::cstr!(\n            \"<bright-blue,bold>[build-dependencies]</>\"\n        )),\n        EdgeKind::Dep(DepKind::Development) => Some(color_print::cstr!(\n            \"<bright-cyan,bold>[dev-dependencies]</>\"\n        )),\n        EdgeKind::Feature => None,\n    };\n\n    if let Prefix::Indent = prefix {\n        if let Some(name) = name {\n            for (style, continues) in &**levels_continue {\n                let c = if *continues { symbols.down } else { \" \" };\n                drop_print!(ws.gctx(), \"{style}{c}{style:#}   \");\n            }\n\n            drop_println!(ws.gctx(), \"{name}\");\n        }\n    }\n\n    let (max_display_depth, filter_non_workspace_member) = match display_depth {\n        DisplayDepth::MaxDisplayDepth(max) => (max, false),\n        DisplayDepth::Workspace => (u32::MAX, true),\n    };\n\n    // Current level exceeds maximum display depth. Skip.\n    if levels_continue.len() + 1 > max_display_depth as usize {\n        return Ok(());\n    }\n\n    let mut it = deps\n        .iter()\n        .filter(|dep| {\n            // Filter out packages to prune.\n            match graph.node(dep.node()) {\n                Node::Package { package_id, .. } => {\n                    if filter_non_workspace_member && !ws.is_member_id(*package_id) {\n                        return false;\n                    }\n                    !pkgs_to_prune.iter().any(|spec| spec.matches(*package_id))\n                }\n                Node::Feature { .. } => true,\n            }\n        })\n        .peekable();\n\n    while let Some(dependency) = it.next() {\n        let style = edge_line_color(dependency.kind());\n        levels_continue.push((style, it.peek().is_some()));\n        print_node(\n            ws,\n            graph,\n            dependency.node(),\n            format,\n            symbols,\n            pkgs_to_prune,\n            prefix,\n            no_dedupe,\n            display_depth,\n            visited_deps,\n            levels_continue,\n            print_stack,\n        )?;\n        levels_continue.pop();\n    }\n\n    Ok(())\n}\n\nfn edge_line_color(kind: EdgeKind) -> anstyle::Style {\n    match kind {\n        EdgeKind::Dep(DepKind::Normal) => style::DEP_NORMAL,\n        EdgeKind::Dep(DepKind::Build) => style::DEP_BUILD,\n        EdgeKind::Dep(DepKind::Development) => style::DEP_DEV,\n        EdgeKind::Feature => style::DEP_FEATURE,\n    }\n}\n"
  },
  {
    "path": "src/cargo/ops/vendor.rs",
    "content": "use crate::core::SourceId;\nuse crate::core::shell::Verbosity;\nuse crate::core::{GitReference, Package, Workspace};\nuse crate::ops;\nuse crate::sources::CRATES_IO_REGISTRY;\nuse crate::sources::RegistrySource;\nuse crate::sources::SourceConfigMap;\nuse crate::sources::path::PathSource;\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::{CargoResult, GlobalContext, try_canonicalize};\n\nuse anyhow::{Context as _, bail};\nuse cargo_util::{Sha256, paths};\nuse cargo_util_schemas::core::SourceKind;\nuse cargo_util_schemas::manifest::TomlPackageBuild;\nuse serde::Serialize;\nuse walkdir::WalkDir;\n\nuse std::collections::HashSet;\nuse std::collections::{BTreeMap, BTreeSet, HashMap};\nuse std::ffi::OsStr;\nuse std::fs::{self, File, OpenOptions};\nuse std::io::{self, Read, Write};\nuse std::path::{Path, PathBuf};\n\npub struct VendorOptions<'a> {\n    pub no_delete: bool,\n    pub versioned_dirs: bool,\n    pub destination: &'a Path,\n    pub extra: Vec<PathBuf>,\n    pub respect_source_config: bool,\n}\n\npub fn vendor(ws: &Workspace<'_>, opts: &VendorOptions<'_>) -> CargoResult<()> {\n    let gctx = ws.gctx();\n    let mut extra_workspaces = Vec::new();\n    for extra in opts.extra.iter() {\n        let extra = gctx.cwd().join(extra);\n        let ws = Workspace::new(&extra, gctx)?;\n        extra_workspaces.push(ws);\n    }\n    let workspaces = extra_workspaces.iter().chain(Some(ws)).collect::<Vec<_>>();\n    let _lock = gctx.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n    let vendor_config = sync(gctx, &workspaces, opts).context(\"failed to sync\")?;\n\n    if gctx.shell().verbosity() != Verbosity::Quiet {\n        if vendor_config.source.is_empty() {\n            crate::drop_eprintln!(gctx, \"There is no dependency to vendor in this project.\");\n        } else {\n            crate::drop_eprint!(\n                gctx,\n                \"To use vendored sources, add this to your .cargo/config.toml for this project:\\n\\n\"\n            );\n            crate::drop_print!(gctx, \"{}\", &toml::to_string_pretty(&vendor_config).unwrap());\n        }\n    }\n\n    Ok(())\n}\n\n#[derive(Serialize)]\nstruct VendorConfig {\n    source: BTreeMap<String, VendorSource>,\n}\n\n#[derive(Serialize)]\n#[serde(rename_all = \"lowercase\", untagged)]\nenum VendorSource {\n    Directory {\n        directory: String,\n    },\n    Registry {\n        registry: Option<String>,\n        #[serde(rename = \"replace-with\")]\n        replace_with: String,\n    },\n    Git {\n        git: String,\n        branch: Option<String>,\n        tag: Option<String>,\n        rev: Option<String>,\n        #[serde(rename = \"replace-with\")]\n        replace_with: String,\n    },\n}\n\n/// Cache for mapping replaced sources to replacements.\nstruct SourceReplacementCache<'gctx> {\n    map: SourceConfigMap<'gctx>,\n    cache: HashMap<SourceId, SourceId>,\n}\n\nimpl SourceReplacementCache<'_> {\n    fn new(\n        gctx: &GlobalContext,\n        respect_source_config: bool,\n    ) -> CargoResult<SourceReplacementCache<'_>> {\n        Ok(SourceReplacementCache {\n            map: if respect_source_config {\n                SourceConfigMap::new(gctx)\n            } else {\n                SourceConfigMap::empty(gctx)\n            }?,\n            cache: Default::default(),\n        })\n    }\n\n    fn get(&mut self, id: SourceId) -> CargoResult<SourceId> {\n        use std::collections::hash_map::Entry;\n        match self.cache.entry(id) {\n            Entry::Occupied(e) => Ok(e.get().clone()),\n            Entry::Vacant(e) => {\n                let replaced = self.map.load(id, &HashSet::new())?.replaced_source_id();\n                Ok(e.insert(replaced).clone())\n            }\n        }\n    }\n}\n\nfn sync(\n    gctx: &GlobalContext,\n    workspaces: &[&Workspace<'_>],\n    opts: &VendorOptions<'_>,\n) -> CargoResult<VendorConfig> {\n    let dry_run = false;\n    let vendor_dir = try_canonicalize(opts.destination);\n    let vendor_dir = vendor_dir.as_deref().unwrap_or(opts.destination);\n    let vendor_dir_already_exists = vendor_dir.exists();\n\n    paths::create_dir_all(&vendor_dir)?;\n    let mut to_remove = HashSet::new();\n    if !opts.no_delete {\n        for entry in vendor_dir.read_dir()? {\n            let entry = entry?;\n            if !entry\n                .file_name()\n                .to_str()\n                .map_or(false, |s| s.starts_with('.'))\n            {\n                to_remove.insert(entry.path());\n            }\n        }\n    }\n\n    let mut source_replacement_cache =\n        SourceReplacementCache::new(gctx, opts.respect_source_config)?;\n\n    let mut checksums = HashMap::new();\n    let mut ids = BTreeMap::new();\n\n    // Let's download all crates and start storing internal tables about them.\n    for ws in workspaces {\n        let (packages, resolve) = ops::resolve_ws(ws, dry_run)\n            .with_context(|| format!(\"failed to load lockfile for {}\", ws.root().display()))?;\n\n        packages\n            .get_many(resolve.iter())\n            .with_context(|| format!(\"failed to download packages for {}\", ws.root().display()))?;\n\n        for pkg in resolve.iter() {\n            let sid = source_replacement_cache.get(pkg.source_id())?;\n\n            // Don't vendor path crates since they're already in the repository\n            if sid.is_path() {\n                // And don't delete actual source code!\n                if let Ok(path) = sid.url().to_file_path() {\n                    if let Ok(path) = try_canonicalize(path) {\n                        to_remove.remove(&path);\n                    }\n                }\n                continue;\n            }\n\n            ids.insert(\n                pkg,\n                packages\n                    .get_one(pkg)\n                    .context(\"failed to fetch package\")?\n                    .clone(),\n            );\n\n            checksums.insert(pkg, resolve.checksums().get(&pkg).cloned());\n        }\n    }\n\n    let mut versions = HashMap::new();\n    for id in ids.keys() {\n        let map = versions.entry(id.name()).or_insert_with(BTreeMap::default);\n        if let Some(prev) = map.get(&id.version()) {\n            bail!(\n                \"found duplicate version of package `{} v{}` \\\n                 vendored from two sources:\\n\\\n                 \\n\\\n                 \\tsource 1: {}\\n\\\n                 \\tsource 2: {}\",\n                id.name(),\n                id.version(),\n                prev,\n                id.source_id()\n            );\n        }\n        map.insert(id.version(), id.source_id());\n    }\n\n    let mut sources = BTreeSet::new();\n    let mut tmp_buf = [0; 64 * 1024];\n    for (id, pkg) in ids.iter() {\n        // Next up, copy it to the vendor directory\n        let src = pkg.root();\n        let max_version = *versions[&id.name()].iter().rev().next().unwrap().0;\n        let dir_has_version_suffix = opts.versioned_dirs || id.version() != max_version;\n        let dst_name = if dir_has_version_suffix {\n            // Eg vendor/futures-0.1.13\n            format!(\"{}-{}\", id.name(), id.version())\n        } else {\n            // Eg vendor/futures\n            id.name().to_string()\n        };\n\n        sources.insert(id.source_id());\n        let dst = vendor_dir.join(&dst_name);\n        to_remove.remove(&dst);\n        let cksum = dst.join(\".cargo-checksum.json\");\n        // Registries are the only immutable sources,\n        // path and git dependencies' versions cannot be trusted to mean \"no change\"\n        if dir_has_version_suffix && id.source_id().is_registry() && cksum.exists() {\n            // Don't re-copy directory with version suffix in case it comes from a registry\n            continue;\n        }\n\n        gctx.shell().status(\n            \"Vendoring\",\n            &format!(\"{} ({}) to {}\", id, src.to_string_lossy(), dst.display()),\n        )?;\n\n        let _ = fs::remove_dir_all(&dst);\n\n        let mut file_cksums = BTreeMap::new();\n\n        // Need this mapping anyway because we will directly consult registry sources,\n        // otherwise builtin source replacement (sparse registry) won't be respected.\n        let sid = source_replacement_cache.get(id.source_id())?;\n\n        if sid.is_registry() {\n            // To keep the unpacked source from registry in a pristine state,\n            // we'll do a direct extraction into the vendor directory.\n            let registry = match sid.kind() {\n                SourceKind::Registry | SourceKind::SparseRegistry => {\n                    RegistrySource::remote(sid, &Default::default(), gctx)?\n                }\n                SourceKind::LocalRegistry => {\n                    let path = sid.url().to_file_path().expect(\"local path\");\n                    RegistrySource::local(sid, &path, &Default::default(), gctx)\n                }\n                _ => unreachable!(\"not registry source: {sid}\"),\n            };\n\n            let walkdir = |root| {\n                WalkDir::new(root)\n                    .into_iter()\n                    // It is safe to skip errors,\n                    // since we'll hit them during copying/reading later anyway.\n                    .filter_map(|e| e.ok())\n                    // There should be no symlink in tarballs on crates.io,\n                    // but might be wrong for local registries.\n                    // Hence here be conservative and include symlinks.\n                    .filter(|e| e.file_type().is_file() || e.file_type().is_symlink())\n            };\n            let mut compute_file_cksums = |root| {\n                for e in walkdir(root) {\n                    let path = e.path();\n                    let relative = path.strip_prefix(&dst).unwrap();\n                    let cksum = Sha256::new()\n                        .update_path(path)\n                        .map(Sha256::finish_hex)\n                        .with_context(|| format!(\"failed to checksum `{}`\", path.display()))?;\n                    file_cksums.insert(relative.to_str().unwrap().replace(\"\\\\\", \"/\"), cksum);\n                }\n                Ok::<_, anyhow::Error>(())\n            };\n            if dir_has_version_suffix {\n                registry.unpack_package_in(id, &vendor_dir, &vendor_this)?;\n                compute_file_cksums(&dst)?;\n            } else {\n                // Due to the extra sanity check in registry unpack\n                // (ensure it contain only one top-level directory with name `pkg-version`),\n                // we can only unpack a directory with version suffix,\n                // and move it to the no suffix directory.\n                let staging_dir = tempfile::Builder::new()\n                    .prefix(\".vendor-staging\")\n                    .tempdir_in(vendor_dir)?;\n                let unpacked_src =\n                    registry.unpack_package_in(id, staging_dir.path(), &vendor_this)?;\n\n                let rename_result = if gctx\n                    .get_env_os(\"__CARGO_TEST_VENDOR_FALLBACK_CP_SOURCES\")\n                    .is_some()\n                {\n                    Err(io::Error::new(\n                        io::ErrorKind::Other,\n                        \"simulated rename error for testing\",\n                    ))\n                } else {\n                    fs::rename(&unpacked_src, &dst)\n                };\n\n                if let Err(e) = rename_result {\n                    // This fallback is worked for sometimes `fs::rename` failed in a specific situation, such as:\n                    // - In Windows 10 versions earlier than 1607, the destination of `fs::rename` can't be a directory in older versions.\n                    // - `from` and `to` are on separate filesystems.\n                    // - AntiVirus or our system indexer are doing stuf simultaneously.\n                    // - Any other reasons documented in std::fs::rename.\n                    tracing::warn!(\"failed to `mv {unpacked_src:?} {dst:?}`: {e}\");\n                    let paths: Vec<_> = walkdir(&unpacked_src).map(|e| e.into_path()).collect();\n                    cp_sources(\n                        pkg,\n                        &unpacked_src,\n                        &paths,\n                        &dst,\n                        &mut file_cksums,\n                        &mut tmp_buf,\n                        gctx,\n                    )\n                    .with_context(|| format!(\"failed to copy vendored sources for {id}\"))?;\n                } else {\n                    compute_file_cksums(&dst)?;\n                }\n            }\n        } else {\n            let paths = PathSource::new(src, sid, gctx)\n                .list_files(pkg)?\n                .into_iter()\n                .map(|p| p.into_path_buf())\n                .collect::<Vec<_>>();\n            cp_sources(pkg, src, &paths, &dst, &mut file_cksums, &mut tmp_buf, gctx)\n                .with_context(|| format!(\"failed to copy vendored sources for {id}\"))?;\n        }\n\n        // Finally, emit the metadata about this package\n        let json = serde_json::json!({\n            \"package\": checksums.get(id),\n            \"files\": file_cksums,\n        });\n\n        paths::write(&cksum, json.to_string())?;\n    }\n\n    for path in to_remove {\n        if path.is_dir() {\n            paths::remove_dir_all(&path)?;\n        } else {\n            paths::remove_file(&path)?;\n        }\n    }\n\n    // add our vendored source\n    let mut config = BTreeMap::new();\n\n    let merged_source_name = \"vendored-sources\";\n\n    // replace original sources with vendor\n    for source_id in sources {\n        let name = if source_id.is_crates_io() {\n            CRATES_IO_REGISTRY.to_string()\n        } else {\n            // Remove `precise` since that makes the source name very long,\n            // and isn't needed to disambiguate multiple sources.\n            source_id.without_precise().as_url().to_string()\n        };\n\n        let source = if source_id.is_crates_io() {\n            VendorSource::Registry {\n                registry: None,\n                replace_with: merged_source_name.to_string(),\n            }\n        } else if source_id.is_remote_registry() {\n            let registry = source_id.url().to_string();\n            VendorSource::Registry {\n                registry: Some(registry),\n                replace_with: merged_source_name.to_string(),\n            }\n        } else if source_id.is_git() {\n            let mut branch = None;\n            let mut tag = None;\n            let mut rev = None;\n            if let Some(reference) = source_id.git_reference() {\n                match *reference {\n                    GitReference::Branch(ref b) => branch = Some(b.clone()),\n                    GitReference::Tag(ref t) => tag = Some(t.clone()),\n                    GitReference::Rev(ref r) => rev = Some(r.clone()),\n                    GitReference::DefaultBranch => {}\n                }\n            }\n            VendorSource::Git {\n                git: source_id.url().to_string(),\n                branch,\n                tag,\n                rev,\n                replace_with: merged_source_name.to_string(),\n            }\n        } else {\n            panic!(\"Invalid source ID: {}\", source_id)\n        };\n        config.insert(name, source);\n    }\n\n    if !config.is_empty() {\n        config.insert(\n            merged_source_name.to_string(),\n            VendorSource::Directory {\n                // Windows-flavour paths are valid here on Windows but Unix.\n                // This backslash normalization is for making output paths more\n                // cross-platform compatible.\n                directory: opts.destination.to_string_lossy().replace(\"\\\\\", \"/\"),\n            },\n        );\n    } else if !vendor_dir_already_exists {\n        // Nothing to vendor. Remove the destination dir we've just created.\n        paths::remove_dir(vendor_dir)?;\n    }\n\n    Ok(VendorConfig { source: config })\n}\n\nfn cp_sources(\n    pkg: &Package,\n    src: &Path,\n    paths: &[PathBuf],\n    dst: &Path,\n    cksums: &mut BTreeMap<String, String>,\n    tmp_buf: &mut [u8],\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    for p in paths {\n        let relative = p.strip_prefix(&src).unwrap();\n\n        if !vendor_this(relative) {\n            continue;\n        }\n\n        // Join pathname components individually to make sure that the joined\n        // path uses the correct directory separators everywhere, since\n        // `relative` may use Unix-style and `dst` may require Windows-style\n        // backslashes.\n        let dst = relative\n            .iter()\n            .fold(dst.to_owned(), |acc, component| acc.join(&component));\n\n        paths::create_dir_all(dst.parent().unwrap())?;\n        let mut dst_opts = OpenOptions::new();\n        dst_opts.write(true).create(true).truncate(true);\n        // When vendoring git dependencies, the manifest has not been normalized like it would be\n        // when published. This causes issue when the manifest is using workspace inheritance.\n        // To get around this issue we use the \"original\" manifest after `{}.workspace = true`\n        // has been resolved for git dependencies.\n        let cksum = if dst.file_name() == Some(OsStr::new(\"Cargo.toml\"))\n            && pkg.package_id().source_id().is_git()\n        {\n            let packaged_files = paths\n                .iter()\n                .map(|p| p.strip_prefix(src).unwrap().to_owned())\n                .collect::<Vec<_>>();\n            let vendored_pkg = prepare_for_vendor(pkg, &packaged_files, gctx)?;\n            let contents = vendored_pkg.manifest().to_normalized_contents()?;\n            copy_and_checksum(\n                &dst,\n                &mut dst_opts,\n                &mut contents.as_bytes(),\n                Path::new(\"Generated Cargo.toml\"),\n                tmp_buf,\n            )?\n        } else {\n            let mut src = File::open(&p).with_context(|| format!(\"failed to open {:?}\", &p))?;\n            #[cfg(unix)]\n            {\n                use std::os::unix::fs::{MetadataExt, OpenOptionsExt};\n                let src_metadata = src\n                    .metadata()\n                    .with_context(|| format!(\"failed to stat {:?}\", p))?;\n                dst_opts.mode(src_metadata.mode());\n            }\n            copy_and_checksum(&dst, &mut dst_opts, &mut src, &p, tmp_buf)?\n        };\n\n        cksums.insert(relative.to_str().unwrap().replace(\"\\\\\", \"/\"), cksum);\n    }\n    Ok(())\n}\n\n/// HACK: Perform the bare minimum of `prepare_for_publish` needed for #14348.\n///\n/// There are parts of `prepare_for_publish` that could be directly useful (e.g. stripping\n/// `[workspace]`) while other parts that require other filesystem operations (moving the README\n/// file) and ideally we'd reuse `cargo package` code to take care of all of this for us.\nfn prepare_for_vendor(\n    me: &Package,\n    packaged_files: &[PathBuf],\n    gctx: &GlobalContext,\n) -> CargoResult<Package> {\n    let contents = me.manifest().contents();\n    let document = me.manifest().document();\n    let original_toml = prepare_toml_for_vendor(\n        me.manifest().normalized_toml().clone(),\n        packaged_files,\n        gctx,\n    )?;\n    let normalized_toml = original_toml.clone();\n    let features = me.manifest().unstable_features().clone();\n    let workspace_config = me.manifest().workspace_config().clone();\n    let source_id = me.package_id().source_id();\n    let mut warnings = Default::default();\n    let mut errors = Default::default();\n    let manifest = crate::util::toml::to_real_manifest(\n        contents.map(|c| c.to_owned()),\n        document.cloned(),\n        original_toml,\n        normalized_toml,\n        features,\n        workspace_config,\n        source_id,\n        me.manifest_path(),\n        me.manifest().is_embedded(),\n        gctx,\n        &mut warnings,\n        &mut errors,\n    )?;\n    let new_pkg = Package::new(manifest, me.manifest_path());\n    Ok(new_pkg)\n}\n\nfn prepare_toml_for_vendor(\n    mut me: cargo_util_schemas::manifest::TomlManifest,\n    packaged_files: &[PathBuf],\n    gctx: &GlobalContext,\n) -> CargoResult<cargo_util_schemas::manifest::TomlManifest> {\n    let package = me\n        .package\n        .as_mut()\n        .expect(\"venedored manifests must have packages\");\n    // Validates if build script file is included in package. If not, warn and ignore.\n    if let Some(custom_build_scripts) = package.normalized_build().expect(\"previously normalized\") {\n        let mut included_scripts = Vec::new();\n        for script in custom_build_scripts {\n            let path = paths::normalize_path(Path::new(script));\n            let included = packaged_files.contains(&path);\n            if included {\n                let path = path\n                    .into_os_string()\n                    .into_string()\n                    .map_err(|_err| anyhow::format_err!(\"non-UTF8 `package.build`\"))?;\n                let path = crate::util::toml::normalize_path_string_sep(path);\n                included_scripts.push(path);\n            } else {\n                gctx.shell().warn(format!(\n                    \"ignoring `package.build` entry `{}` as it is not included in the published package\",\n                    path.display()\n                ))?;\n            }\n        }\n        package.build = Some(match included_scripts.len() {\n            0 => TomlPackageBuild::Auto(false),\n            1 => TomlPackageBuild::SingleScript(included_scripts[0].clone()),\n            _ => TomlPackageBuild::MultipleScript(included_scripts),\n        });\n    }\n\n    let lib = if let Some(target) = &me.lib {\n        crate::util::toml::prepare_target_for_publish(\n            target,\n            Some(packaged_files),\n            \"library\",\n            gctx,\n        )?\n    } else {\n        None\n    };\n    let bin = crate::util::toml::prepare_targets_for_publish(\n        me.bin.as_ref(),\n        Some(packaged_files),\n        \"binary\",\n        gctx,\n    )?;\n    let example = crate::util::toml::prepare_targets_for_publish(\n        me.example.as_ref(),\n        Some(packaged_files),\n        \"example\",\n        gctx,\n    )?;\n    let test = crate::util::toml::prepare_targets_for_publish(\n        me.test.as_ref(),\n        Some(packaged_files),\n        \"test\",\n        gctx,\n    )?;\n    let bench = crate::util::toml::prepare_targets_for_publish(\n        me.bench.as_ref(),\n        Some(packaged_files),\n        \"benchmark\",\n        gctx,\n    )?;\n\n    me.lib = lib;\n    me.bin = bin;\n    me.example = example;\n    me.test = test;\n    me.bench = bench;\n\n    Ok(me)\n}\n\nfn copy_and_checksum<T: Read>(\n    dst_path: &Path,\n    dst_opts: &mut OpenOptions,\n    contents: &mut T,\n    contents_path: &Path,\n    buf: &mut [u8],\n) -> CargoResult<String> {\n    let mut dst = dst_opts\n        .open(dst_path)\n        .with_context(|| format!(\"failed to create {:?}\", dst_path))?;\n    // Not going to bother setting mode on pre-existing files, since there\n    // shouldn't be any under normal conditions.\n    let mut cksum = Sha256::new();\n    loop {\n        let n = contents\n            .read(buf)\n            .with_context(|| format!(\"failed to read from {:?}\", contents_path))?;\n        if n == 0 {\n            break Ok(cksum.finish_hex());\n        }\n        let data = &buf[..n];\n        cksum.update(data);\n        dst.write_all(data)\n            .with_context(|| format!(\"failed to write to {:?}\", dst_path))?;\n    }\n}\n\n/// Filters files we want to vendor.\n///\n/// `relative` is a path relative to the package root.\n\nfn vendor_this(relative: &Path) -> bool {\n    // Skip git config files as they're not relevant to builds most of\n    // the time and if we respect them (e.g. in git) then it'll\n    // probably mess with the checksums when a vendor dir is checked\n    // into someone else's source control\n    for component in relative.components() {\n        if let Some(name) = component.as_os_str().to_str() {\n            if name == \".git\" {\n                return false;\n            }\n        }\n    }\n\n    if let Some(file_name) = relative.file_name().and_then(|s| s.to_str()) {\n        if matches!(file_name, \".gitattributes\" | \".gitignore\") {\n            return false;\n        }\n    }\n\n    // Temporary Cargo files\n    match relative.to_str() {\n        Some(\".cargo-ok\") => false,\n        _ => true,\n    }\n}\n"
  },
  {
    "path": "src/cargo/sources/config.rs",
    "content": "//! Implementation of configuration for various sources.\n//!\n//! This module will parse the various `source.*` TOML configuration keys into a\n//! structure usable by Cargo itself. Currently, this is primarily used to map\n//! sources to one another via the `replace-with` key in `.cargo/config`.\n\nuse crate::core::{GitReference, PackageId, SourceId};\nuse crate::sources::overlay::DependencyConfusionThreatOverlaySource;\nuse crate::sources::source::Source;\nuse crate::sources::{CRATES_IO_REGISTRY, ReplacedSource};\nuse crate::util::context::{self, ConfigRelativePath, OptValue};\nuse crate::util::errors::CargoResult;\nuse crate::util::{GlobalContext, IntoUrl};\nuse anyhow::{Context as _, bail};\nuse std::collections::{HashMap, HashSet};\nuse tracing::debug;\nuse url::Url;\n\n/// Represents the entire [`[source]` replacement table][1] in Cargo configuration.\n///\n/// [1]: https://doc.rust-lang.org/nightly/cargo/reference/config.html#source\n#[derive(Clone)]\npub struct SourceConfigMap<'gctx> {\n    /// Mapping of source name to the toml configuration.\n    cfgs: HashMap<String, SourceConfig>,\n    /// Mapping of [`SourceId`] to the source name.\n    id2name: HashMap<SourceId, String>,\n    /// Mapping of sources to local registries that will be overlaid on them.\n    overlays: HashMap<SourceId, SourceId>,\n    gctx: &'gctx GlobalContext,\n}\n\n/// Definition of a source in a config file.\n#[derive(Debug, serde::Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\nstruct SourceConfigDef {\n    /// Indicates this source should be replaced with another of the given name.\n    replace_with: OptValue<String>,\n    /// A directory source.\n    directory: Option<ConfigRelativePath>,\n    /// A registry source. Value is a URL.\n    registry: OptValue<String>,\n    /// A local registry source.\n    local_registry: Option<ConfigRelativePath>,\n    /// A git source. Value is a URL.\n    git: OptValue<String>,\n    /// The git branch.\n    branch: OptValue<String>,\n    /// The git tag.\n    tag: OptValue<String>,\n    /// The git revision.\n    rev: OptValue<String>,\n}\n\n/// Configuration for a particular source, found in TOML looking like:\n///\n/// ```toml\n/// [source.crates-io]\n/// registry = 'https://github.com/rust-lang/crates.io-index'\n/// replace-with = 'foo'    # optional\n/// ```\n#[derive(Clone)]\nstruct SourceConfig {\n    /// `SourceId` this source corresponds to, inferred from the various\n    /// defined keys in the configuration.\n    id: SourceId,\n\n    /// Whether or not this source is replaced with another.\n    ///\n    /// This field is a tuple of `(name, location)` where `location` is where\n    /// this configuration key was defined (such as the `.cargo/config` path\n    /// or the environment variable name).\n    replace_with: Option<(String, String)>,\n}\n\nimpl<'gctx> SourceConfigMap<'gctx> {\n    /// Like [`SourceConfigMap::empty`] but includes sources from source\n    /// replacement configurations.\n    pub fn new(gctx: &'gctx GlobalContext) -> CargoResult<SourceConfigMap<'gctx>> {\n        let mut base = SourceConfigMap::empty(gctx)?;\n        let sources: Option<HashMap<String, SourceConfigDef>> = gctx.get(\"source\")?;\n        if let Some(sources) = sources {\n            for (key, value) in sources.into_iter() {\n                base.add_config(key, value)?;\n            }\n        }\n\n        Ok(base)\n    }\n\n    /// Like [`SourceConfigMap::new`] but includes sources from source\n    /// replacement configurations.\n    pub fn new_with_overlays(\n        gctx: &'gctx GlobalContext,\n        overlays: impl IntoIterator<Item = (SourceId, SourceId)>,\n    ) -> CargoResult<SourceConfigMap<'gctx>> {\n        let mut base = SourceConfigMap::new(gctx)?;\n        base.overlays = overlays.into_iter().collect();\n        Ok(base)\n    }\n\n    /// Creates the default set of sources that doesn't take `[source]`\n    /// replacement into account.\n    pub fn empty(gctx: &'gctx GlobalContext) -> CargoResult<SourceConfigMap<'gctx>> {\n        let mut base = SourceConfigMap {\n            cfgs: HashMap::new(),\n            id2name: HashMap::new(),\n            overlays: HashMap::new(),\n            gctx,\n        };\n        base.add(\n            CRATES_IO_REGISTRY,\n            SourceConfig {\n                id: SourceId::crates_io(gctx)?,\n                replace_with: None,\n            },\n        )?;\n        if SourceId::crates_io_is_sparse(gctx)? {\n            base.add(\n                CRATES_IO_REGISTRY,\n                SourceConfig {\n                    id: SourceId::crates_io_maybe_sparse_http(gctx)?,\n                    replace_with: None,\n                },\n            )?;\n        }\n        if let Ok(url) = gctx.get_env(\"__CARGO_TEST_CRATES_IO_URL_DO_NOT_USE_THIS\") {\n            base.add(\n                CRATES_IO_REGISTRY,\n                SourceConfig {\n                    id: SourceId::for_alt_registry(&url.parse()?, CRATES_IO_REGISTRY)?,\n                    replace_with: None,\n                },\n            )?;\n        }\n        Ok(base)\n    }\n\n    /// Returns the [`GlobalContext`] this source config map is associated with.\n    pub fn gctx(&self) -> &'gctx GlobalContext {\n        self.gctx\n    }\n\n    /// Gets the [`Source`] for a given [`SourceId`].\n    ///\n    /// * `yanked_whitelist` --- Packages allowed to be used, even if they are yanked.\n    pub fn load(\n        &self,\n        id: SourceId,\n        yanked_whitelist: &HashSet<PackageId>,\n    ) -> CargoResult<Box<dyn Source + 'gctx>> {\n        debug!(\"loading: {}\", id);\n\n        let Some(mut name) = self.id2name.get(&id) else {\n            return self.load_overlaid(id, yanked_whitelist);\n        };\n        let mut cfg_loc = \"\";\n        let orig_name = name;\n        let new_id = loop {\n            let Some(cfg) = self.cfgs.get(name) else {\n                // Attempt to interpret the source name as an alt registry name\n                if let Ok(alt_id) = SourceId::alt_registry(self.gctx, name) {\n                    debug!(\"following pointer to registry {}\", name);\n                    break alt_id.with_precise_from(id);\n                }\n                bail!(\n                    \"could not find a configured source with the \\\n                     name `{}` when attempting to lookup `{}` \\\n                     (configuration in `{}`)\",\n                    name,\n                    orig_name,\n                    cfg_loc\n                );\n            };\n            match &cfg.replace_with {\n                Some((s, c)) => {\n                    name = s;\n                    cfg_loc = c;\n                }\n                None if id == cfg.id => return self.load_overlaid(id, yanked_whitelist),\n                None => {\n                    break cfg.id.with_precise_from(id);\n                }\n            }\n            debug!(\"following pointer to {}\", name);\n            if name == orig_name {\n                bail!(\n                    \"detected a cycle of `replace-with` sources, the source \\\n                     `{}` is eventually replaced with itself \\\n                     (configuration in `{}`)\",\n                    name,\n                    cfg_loc\n                )\n            }\n        };\n\n        let new_src = self.load_overlaid(\n            new_id,\n            &yanked_whitelist\n                .iter()\n                .map(|p| p.map_source(id, new_id))\n                .collect(),\n        )?;\n        let old_src = id.load(self.gctx, yanked_whitelist)?;\n        if !new_src.supports_checksums() && old_src.supports_checksums() {\n            bail!(\n                \"\\\ncannot replace `{orig}` with `{name}`, the source `{orig}` supports \\\nchecksums, but `{name}` does not\n\na lock file compatible with `{orig}` cannot be generated in this situation\n\",\n                orig = orig_name,\n                name = name\n            );\n        }\n\n        if old_src.requires_precise() && !id.has_precise() {\n            bail!(\n                \"\\\nthe source {orig} requires a lock file to be present first before it can be\nused against vendored source code\n\nremove the source replacement configuration, generate a lock file, and then\nrestore the source replacement configuration to continue the build\n\",\n                orig = orig_name\n            );\n        }\n\n        Ok(Box::new(ReplacedSource::new(id, new_id, new_src)))\n    }\n\n    /// Gets the [`Source`] for a given [`SourceId`] without performing any source replacement.\n    fn load_overlaid(\n        &self,\n        id: SourceId,\n        yanked_whitelist: &HashSet<PackageId>,\n    ) -> CargoResult<Box<dyn Source + 'gctx>> {\n        let src = id.load(self.gctx, yanked_whitelist)?;\n        if let Some(overlay_id) = self.overlays.get(&id) {\n            let overlay = overlay_id.load(self.gctx(), yanked_whitelist)?;\n            Ok(Box::new(DependencyConfusionThreatOverlaySource::new(\n                overlay, src,\n            )))\n        } else {\n            Ok(src)\n        }\n    }\n\n    /// Adds a source config with an associated name.\n    fn add(&mut self, name: &str, cfg: SourceConfig) -> CargoResult<()> {\n        if let Some(old_name) = self.id2name.insert(cfg.id, name.to_string()) {\n            // The user is allowed to redefine the built-in crates-io\n            // definition from `empty()`.\n            if name != CRATES_IO_REGISTRY {\n                bail!(\n                    \"source `{}` defines source {}, but that source is already defined by `{}`\\n\\\n                     note: Sources are not allowed to be defined multiple times.\",\n                    name,\n                    cfg.id,\n                    old_name\n                );\n            }\n        }\n        self.cfgs.insert(name.to_string(), cfg);\n        Ok(())\n    }\n\n    /// Adds a source config from TOML definition.\n    fn add_config(&mut self, name: String, def: SourceConfigDef) -> CargoResult<()> {\n        let mut srcs = Vec::new();\n        if let Some(registry) = def.registry {\n            let url = url(&registry, &format!(\"source.{}.registry\", name))?;\n            srcs.push(SourceId::for_source_replacement_registry(&url, &name)?);\n        }\n        if let Some(local_registry) = def.local_registry {\n            let path = local_registry.resolve_path(self.gctx);\n            srcs.push(SourceId::for_local_registry(&path)?);\n        }\n        if let Some(directory) = def.directory {\n            let path = directory.resolve_path(self.gctx);\n            srcs.push(SourceId::for_directory(&path)?);\n        }\n        if let Some(git) = def.git {\n            let url = url(&git, &format!(\"source.{}.git\", name))?;\n            let reference = match def.branch {\n                Some(b) => GitReference::Branch(b.val),\n                None => match def.tag {\n                    Some(b) => GitReference::Tag(b.val),\n                    None => match def.rev {\n                        Some(b) => GitReference::Rev(b.val),\n                        None => GitReference::DefaultBranch,\n                    },\n                },\n            };\n            srcs.push(SourceId::for_git(&url, reference)?);\n        } else {\n            let check_not_set = |key, v: OptValue<String>| {\n                if let Some(val) = v {\n                    bail!(\n                        \"source definition `source.{}` specifies `{}`, \\\n                         but that requires a `git` key to be specified (in {})\",\n                        name,\n                        key,\n                        val.definition\n                    );\n                }\n                Ok(())\n            };\n            check_not_set(\"branch\", def.branch)?;\n            check_not_set(\"tag\", def.tag)?;\n            check_not_set(\"rev\", def.rev)?;\n        }\n        if name == CRATES_IO_REGISTRY && srcs.is_empty() {\n            srcs.push(SourceId::crates_io_maybe_sparse_http(self.gctx)?);\n        }\n\n        match srcs.len() {\n            0 => bail!(\n                \"no source location specified for `source.{}`, need \\\n                 `registry`, `local-registry`, `directory`, or `git` defined\",\n                name\n            ),\n            1 => {}\n            _ => bail!(\n                \"more than one source location specified for `source.{}`\",\n                name\n            ),\n        }\n        let src = srcs[0];\n\n        let replace_with = def\n            .replace_with\n            .map(|val| (val.val, val.definition.to_string()));\n\n        self.add(\n            &name,\n            SourceConfig {\n                id: src,\n                replace_with,\n            },\n        )?;\n\n        return Ok(());\n\n        fn url(val: &context::Value<String>, key: &str) -> CargoResult<Url> {\n            let url = val.val.into_url().with_context(|| {\n                format!(\n                    \"configuration key `{}` specified an invalid \\\n                     URL (in {})\",\n                    key, val.definition\n                )\n            })?;\n\n            Ok(url)\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/sources/directory.rs",
    "content": "use std::collections::HashMap;\nuse std::fmt::{self, Debug, Formatter};\nuse std::path::{Path, PathBuf};\nuse std::task::Poll;\n\nuse crate::core::{Dependency, Package, PackageId, SourceId};\nuse crate::sources::IndexSummary;\nuse crate::sources::PathSource;\nuse crate::sources::source::MaybePackage;\nuse crate::sources::source::QueryKind;\nuse crate::sources::source::Source;\nuse crate::util::GlobalContext;\nuse crate::util::errors::CargoResult;\n\nuse anyhow::Context as _;\nuse cargo_util::{Sha256, paths};\nuse serde::Deserialize;\n\n/// `DirectorySource` contains a number of crates on the file system. It was\n/// designed for representing vendored dependencies for `cargo vendor`.\n///\n/// `DirectorySource` at this moment is just a root directory containing other\n/// directories, which contain the source files of packages. Assumptions would\n/// be made to determine if a directory should be included as a package of a\n/// directory source's:\n///\n/// * Ignore directories starting with dot `.` (tend to be hidden).\n/// * Only when a `Cargo.toml` exists in a directory will it be included as\n///   a package. `DirectorySource` at this time only looks at one level of\n///   directories and never went deeper.\n/// * There must be a [`Checksum`] file `.cargo-checksum.json` file at the same\n///   level of `Cargo.toml` to ensure the integrity when a directory source was\n///   created (usually by `cargo vendor`). A failure to find or parse a single\n///   checksum results in a denial of loading any package in this source.\n/// * Otherwise, there is no other restriction of the name of directories. At\n///   this moment, it is `cargo vendor` that defines the layout and the name of\n///   each directory.\n///\n/// The file tree of a directory source may look like:\n///\n/// ```text\n/// [source root]\n/// ├── a-valid-crate/\n/// │  ├── src/\n/// │  ├── .cargo-checksum.json\n/// │  └── Cargo.toml\n/// ├── .ignored-a-dot-crate/\n/// │  ├── src/\n/// │  ├── .cargo-checksum.json\n/// │  └── Cargo.toml\n/// ├── skipped-no-manifest/\n/// │  ├── src/\n/// │  └── .cargo-checksum.json\n/// └── no-checksum-so-fails-the-entire-source-reading/\n///    └── Cargo.toml\n/// ```\npub struct DirectorySource<'gctx> {\n    /// The unique identifier of this source.\n    source_id: SourceId,\n    /// The root path of this source.\n    root: PathBuf,\n    /// Packages that this sources has discovered.\n    packages: HashMap<PackageId, (Package, Checksum)>,\n    gctx: &'gctx GlobalContext,\n    updated: bool,\n}\n\n/// The checksum file to ensure the integrity of a package in a directory source.\n///\n/// The file name is simply `.cargo-checksum.json`. The checksum algorithm as\n/// of now is SHA256.\n#[derive(Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\nstruct Checksum {\n    /// Checksum of the package. Normally it is computed from the `.crate` file.\n    package: Option<String>,\n    /// Checksums of each source file.\n    files: HashMap<String, String>,\n}\n\nimpl<'gctx> DirectorySource<'gctx> {\n    pub fn new(path: &Path, id: SourceId, gctx: &'gctx GlobalContext) -> DirectorySource<'gctx> {\n        DirectorySource {\n            source_id: id,\n            root: path.to_path_buf(),\n            gctx,\n            packages: HashMap::new(),\n            updated: false,\n        }\n    }\n}\n\nimpl<'gctx> Debug for DirectorySource<'gctx> {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        write!(f, \"DirectorySource {{ root: {:?} }}\", self.root)\n    }\n}\n\nimpl<'gctx> Source for DirectorySource<'gctx> {\n    fn query(\n        &mut self,\n        dep: &Dependency,\n        kind: QueryKind,\n        f: &mut dyn FnMut(IndexSummary),\n    ) -> Poll<CargoResult<()>> {\n        if !self.updated {\n            return Poll::Pending;\n        }\n        let packages = self.packages.values().map(|p| &p.0);\n        let matches = packages.filter(|pkg| match kind {\n            QueryKind::Exact | QueryKind::RejectedVersions => dep.matches(pkg.summary()),\n            QueryKind::AlternativeNames => true,\n            QueryKind::Normalized => dep.matches(pkg.summary()),\n        });\n        for summary in matches.map(|pkg| pkg.summary().clone()) {\n            f(IndexSummary::Candidate(summary));\n        }\n        Poll::Ready(Ok(()))\n    }\n\n    fn supports_checksums(&self) -> bool {\n        true\n    }\n\n    fn requires_precise(&self) -> bool {\n        true\n    }\n\n    fn source_id(&self) -> SourceId {\n        self.source_id\n    }\n\n    fn block_until_ready(&mut self) -> CargoResult<()> {\n        if self.updated {\n            return Ok(());\n        }\n        self.packages.clear();\n        let entries = self.root.read_dir().with_context(|| {\n            format!(\n                \"failed to read root of directory source: {}\",\n                self.root.display()\n            )\n        })?;\n\n        for entry in entries {\n            let entry = entry?;\n            let path = entry.path();\n\n            // Ignore hidden/dot directories as they typically don't contain\n            // crates and otherwise may conflict with a VCS\n            // (rust-lang/cargo#3414).\n            if let Some(s) = path.file_name().and_then(|s| s.to_str()) {\n                if s.starts_with('.') {\n                    continue;\n                }\n            }\n\n            // Vendor directories are often checked into a VCS, but throughout\n            // the lifetime of a vendor dir crates are often added and deleted.\n            // Some VCS implementations don't always fully delete the directory\n            // when a dir is removed from a different checkout. Sometimes a\n            // mostly-empty dir is left behind.\n            //\n            // Additionally vendor directories are sometimes accompanied with\n            // readme files and other auxiliary information not too interesting\n            // to Cargo.\n            //\n            // To help handle all this we only try processing folders with a\n            // `Cargo.toml` in them. This has the upside of being pretty\n            // flexible with the contents of vendor directories but has the\n            // downside of accidentally misconfigured vendor directories\n            // silently returning less crates.\n            if !path.join(\"Cargo.toml\").exists() {\n                continue;\n            }\n\n            let mut src = PathSource::new(&path, self.source_id, self.gctx);\n            src.load()?;\n            let mut pkg = src.root_package()?;\n\n            let cksum_file = path.join(\".cargo-checksum.json\");\n            let cksum = paths::read(&path.join(cksum_file)).with_context(|| {\n                format!(\n                    \"failed to load checksum `.cargo-checksum.json` \\\n                     of {} v{}\",\n                    pkg.package_id().name(),\n                    pkg.package_id().version()\n                )\n            })?;\n            let cksum: Checksum = serde_json::from_str(&cksum).with_context(|| {\n                format!(\n                    \"failed to decode `.cargo-checksum.json` of \\\n                     {} v{}\",\n                    pkg.package_id().name(),\n                    pkg.package_id().version()\n                )\n            })?;\n\n            if let Some(package) = &cksum.package {\n                pkg.manifest_mut()\n                    .summary_mut()\n                    .set_checksum(package.clone());\n            }\n            self.packages.insert(pkg.package_id(), (pkg, cksum));\n        }\n\n        self.updated = true;\n        Ok(())\n    }\n\n    fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {\n        self.packages\n            .get(&id)\n            .map(|p| &p.0)\n            .cloned()\n            .map(MaybePackage::Ready)\n            .ok_or_else(|| anyhow::format_err!(\"failed to find package with id: {}\", id))\n    }\n\n    fn finish_download(&mut self, _id: PackageId, _data: Vec<u8>) -> CargoResult<Package> {\n        panic!(\"no downloads to do\")\n    }\n\n    fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {\n        Ok(pkg.package_id().version().to_string())\n    }\n\n    fn verify(&self, id: PackageId) -> CargoResult<()> {\n        let Some((pkg, cksum)) = self.packages.get(&id) else {\n            anyhow::bail!(\"failed to find entry for `{}` in directory source\", id);\n        };\n\n        for (file, cksum) in cksum.files.iter() {\n            let file = pkg.root().join(file);\n            let actual = Sha256::new()\n                .update_path(&file)\n                .with_context(|| format!(\"failed to calculate checksum of: {}\", file.display()))?\n                .finish_hex();\n            if &*actual != cksum {\n                anyhow::bail!(\n                    \"the listed checksum of `{}` has changed:\\n\\\n                     expected: {}\\n\\\n                     actual:   {}\\n\\\n                     \\n\\\n                     directory sources are not intended to be edited, if \\\n                     modifications are required then it is recommended \\\n                     that `[patch]` is used with a forked copy of the \\\n                     source\\\n                     \",\n                    file.display(),\n                    cksum,\n                    actual\n                );\n            }\n        }\n\n        Ok(())\n    }\n\n    fn describe(&self) -> String {\n        format!(\"directory source `{}`\", self.root.display())\n    }\n\n    fn add_to_yanked_whitelist(&mut self, _pkgs: &[PackageId]) {}\n\n    fn is_yanked(&mut self, _pkg: PackageId) -> Poll<CargoResult<bool>> {\n        Poll::Ready(Ok(false))\n    }\n\n    fn invalidate_cache(&mut self) {\n        // Directory source has no local cache.\n    }\n\n    fn set_quiet(&mut self, _quiet: bool) {\n        // Directory source does not display status\n    }\n}\n"
  },
  {
    "path": "src/cargo/sources/git/known_hosts.rs",
    "content": "//! SSH host key validation support.\n//!\n//! The only public item in this module is [`certificate_check`],\n//! which provides a callback to [`git2::RemoteCallbacks::certificate_check`].\n//!\n//! A primary goal with this implementation is to provide user-friendly error\n//! messages, guiding them to understand the issue and how to resolve it.\n//!\n//! Note that there are a lot of limitations here. This reads OpenSSH\n//! `known_hosts` files from well-known locations, but it does not read OpenSSH\n//! config files. The config file can change the behavior of how OpenSSH\n//! handles `known_hosts` files. For example, some things we don't handle:\n//!\n//! - `GlobalKnownHostsFile` — Changes the location of the global host file.\n//! - `UserKnownHostsFile` — Changes the location of the user's host file.\n//! - `KnownHostsCommand` — A command to fetch known hosts.\n//! - `CheckHostIP` — DNS spoofing checks.\n//! - `VisualHostKey` — Shows a visual ascii-art key.\n//! - `VerifyHostKeyDNS` — Uses SSHFP DNS records to fetch a host key.\n//!\n//! There's also a number of things that aren't supported but could be easily\n//! added (it just adds a little complexity). For example, hostname patterns,\n//! and revoked markers. See \"FIXME\" comments littered in this file.\n\nuse crate::CargoResult;\nuse crate::util::context::{Definition, GlobalContext, Value};\nuse crate::util::restricted_names::is_glob_pattern;\nuse base64::Engine as _;\nuse base64::engine::general_purpose::STANDARD;\nuse base64::engine::general_purpose::STANDARD_NO_PAD;\nuse git2::CertificateCheckStatus;\nuse git2::cert::{Cert, SshHostKeyType};\nuse hmac::Mac;\nuse std::collections::HashSet;\nuse std::fmt::{Display, Write};\nuse std::path::{Path, PathBuf};\n\n/// These are host keys that are hard-coded in cargo to provide convenience.\n///\n/// If GitHub ever publishes new keys, the user can add them to their own\n/// configuration file to use those instead.\n///\n/// The GitHub keys are sourced from <https://api.github.com/meta> or\n/// <https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints>.\n///\n/// These will be ignored if the user adds their own entries for `github.com`,\n/// which can be useful if GitHub ever revokes their old keys.\nstatic BUNDLED_KEYS: &[(&str, &str, &str)] = &[\n    (\n        \"github.com\",\n        \"ssh-ed25519\",\n        \"AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl\",\n    ),\n    (\n        \"github.com\",\n        \"ecdsa-sha2-nistp256\",\n        \"AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=\",\n    ),\n    (\n        \"github.com\",\n        \"ssh-rsa\",\n        \"AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=\",\n    ),\n];\n\n/// List of keys that public hosts have rotated away from.\n///\n/// We explicitly distrust these keys as users with the old key in their\n/// local configuration will otherwise be vulnerable to MITM attacks if the\n/// attacker has access to the old key. As there is no other way to distribute\n/// revocations of ssh host keys, we need to bundle them with the client.\n///\n/// Unlike [`BUNDLED_KEYS`], these revocations will not be ignored if the user\n/// has their own entries: we *know* that these keys are bad.\nstatic BUNDLED_REVOCATIONS: &[(&str, &str, &str)] = &[\n    // Used until March 24, 2023: https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/\n    (\n        \"github.com\",\n        \"ssh-rsa\",\n        \"AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==\",\n    ),\n];\n\nenum KnownHostError {\n    /// Some general error happened while validating the known hosts.\n    CheckError(anyhow::Error),\n    /// The host key was not found.\n    HostKeyNotFound {\n        hostname: String,\n        key_type: SshHostKeyType,\n        remote_host_key: String,\n        remote_fingerprint: String,\n        other_hosts: Vec<KnownHost>,\n    },\n    /// The host key was found, but does not match the remote's key.\n    HostKeyHasChanged {\n        hostname: String,\n        key_type: SshHostKeyType,\n        old_known_host: KnownHost,\n        remote_host_key: String,\n        remote_fingerprint: String,\n    },\n    /// The host key was found with a @revoked marker, it must not be accepted.\n    HostKeyRevoked {\n        hostname: String,\n        key_type: SshHostKeyType,\n        remote_host_key: String,\n        location: KnownHostLocation,\n    },\n    /// The host key was not found, but there was a matching known host with a\n    /// @cert-authority marker (which Cargo doesn't yet support).\n    HostHasOnlyCertAuthority {\n        hostname: String,\n        location: KnownHostLocation,\n    },\n}\n\nimpl From<anyhow::Error> for KnownHostError {\n    fn from(err: anyhow::Error) -> KnownHostError {\n        KnownHostError::CheckError(err)\n    }\n}\n\n/// The location where a host key was located.\n#[derive(Clone)]\nenum KnownHostLocation {\n    /// Loaded from a file from disk.\n    File { path: PathBuf, lineno: u32 },\n    /// Loaded from cargo's config system.\n    Config { definition: Definition },\n    /// Part of the hard-coded bundled keys in Cargo.\n    Bundled,\n}\n\nimpl Display for KnownHostLocation {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let loc = match self {\n            KnownHostLocation::File { path, lineno } => {\n                format!(\"{} line {lineno}\", path.display())\n            }\n            KnownHostLocation::Config { definition } => {\n                format!(\"config value from {definition}\")\n            }\n            KnownHostLocation::Bundled => format!(\"bundled with cargo\"),\n        };\n        f.write_str(&loc)\n    }\n}\n\n/// The git2 callback used to validate a certificate (only ssh known hosts are validated).\npub fn certificate_check(\n    gctx: &GlobalContext,\n    cert: &Cert<'_>,\n    host: &str,\n    port: Option<u16>,\n    config_known_hosts: Option<&Vec<Value<String>>>,\n    diagnostic_home_config: &str,\n) -> CargoResult<CertificateCheckStatus> {\n    let Some(host_key) = cert.as_hostkey() else {\n        // Return passthrough for TLS X509 certificates to use whatever validation\n        // was done in git2.\n        return Ok(CertificateCheckStatus::CertificatePassthrough);\n    };\n    // If a nonstandard port is in use, check for that first.\n    // The fallback to check without a port is handled in the HostKeyNotFound handler.\n    let host_maybe_port = match port {\n        Some(port) if port != 22 => format!(\"[{host}]:{port}\"),\n        _ => host.to_string(),\n    };\n    // The error message must be constructed as a string to pass through the libgit2 C API.\n    match check_ssh_known_hosts(gctx, host_key, &host_maybe_port, config_known_hosts) {\n        Ok(()) => {\n            return Ok(CertificateCheckStatus::CertificateOk);\n        }\n        Err(KnownHostError::CheckError(e)) => {\n            anyhow::bail!(\"error: failed to validate host key:\\n{:#}\", e)\n        }\n        Err(KnownHostError::HostKeyNotFound {\n            hostname,\n            key_type,\n            remote_host_key,\n            remote_fingerprint,\n            other_hosts,\n        }) => {\n            // Try checking without the port.\n            if port.is_some()\n                && !matches!(port, Some(22))\n                && check_ssh_known_hosts(gctx, host_key, host, config_known_hosts).is_ok()\n            {\n                return Ok(CertificateCheckStatus::CertificateOk);\n            }\n            let key_type_short_name = key_type.short_name();\n            let key_type_name = key_type.name();\n            let known_hosts_location = user_known_host_location_to_add(diagnostic_home_config);\n            let other_hosts_message = if other_hosts.is_empty() {\n                String::new()\n            } else {\n                let mut msg = String::from(\n                    \"Note: This host key was found, \\\n                    but is associated with a different host:\\n\",\n                );\n                for known_host in other_hosts {\n                    write!(\n                        msg,\n                        \"    {loc}: {patterns}\\n\",\n                        loc = known_host.location,\n                        patterns = known_host.patterns\n                    )\n                    .unwrap();\n                }\n                msg\n            };\n            anyhow::bail!(\n                \"error: unknown SSH host key\\n\\\n                The SSH host key for `{hostname}` is not known and cannot be validated.\\n\\\n                \\n\\\n                To resolve this issue, add the host key to {known_hosts_location}\\n\\\n                \\n\\\n                The key to add is:\\n\\\n                \\n\\\n                {hostname} {key_type_name} {remote_host_key}\\n\\\n                \\n\\\n                The {key_type_short_name} key fingerprint is: SHA256:{remote_fingerprint}\\n\\\n                This fingerprint should be validated with the server administrator that it is correct.\\n\\\n                {other_hosts_message}\\n\\\n                See https://doc.rust-lang.org/stable/cargo/appendix/git-authentication.html#ssh-known-hosts \\\n                for more information.\\n\\\n                \"\n            )\n        }\n        Err(KnownHostError::HostKeyHasChanged {\n            hostname,\n            key_type,\n            old_known_host,\n            remote_host_key,\n            remote_fingerprint,\n        }) => {\n            let key_type_short_name = key_type.short_name();\n            let key_type_name = key_type.name();\n            let known_hosts_location = user_known_host_location_to_add(diagnostic_home_config);\n            let old_key_resolution = match old_known_host.location {\n                KnownHostLocation::File { path, lineno } => {\n                    let old_key_location = path.display();\n                    format!(\n                        \"removing the old {key_type_name} key for `{hostname}` \\\n                        located at {old_key_location} line {lineno}, \\\n                        and adding the new key to {known_hosts_location}\",\n                    )\n                }\n                KnownHostLocation::Config { definition } => {\n                    format!(\n                        \"removing the old {key_type_name} key for `{hostname}` \\\n                        loaded from Cargo's config at {definition}, \\\n                        and adding the new key to {known_hosts_location}\"\n                    )\n                }\n                KnownHostLocation::Bundled => {\n                    format!(\n                        \"adding the new key to {known_hosts_location}\\n\\\n                        The current host key is bundled as part of Cargo.\"\n                    )\n                }\n            };\n            anyhow::bail!(\n                \"error: SSH host key has changed for `{hostname}`\\n\\\n                *********************************\\n\\\n                * WARNING: HOST KEY HAS CHANGED *\\n\\\n                *********************************\\n\\\n                This may be caused by a man-in-the-middle attack, or the \\\n                server may have changed its host key.\\n\\\n                \\n\\\n                The {key_type_short_name} fingerprint for the key from the remote host is:\\n\\\n                    SHA256:{remote_fingerprint}\\n\\\n                \\n\\\n                You are strongly encouraged to contact the server \\\n                administrator for `{hostname}` to verify that this new key is \\\n                correct.\\n\\\n                \\n\\\n                If you can verify that the server has a new key, you can \\\n                resolve this error by {old_key_resolution}\\n\\\n                \\n\\\n                The key provided by the remote host is:\\n\\\n                \\n\\\n                {hostname} {key_type_name} {remote_host_key}\\n\\\n                \\n\\\n                See https://doc.rust-lang.org/stable/cargo/appendix/git-authentication.html#ssh-known-hosts \\\n                for more information.\\n\\\n                \"\n            )\n        }\n        Err(KnownHostError::HostKeyRevoked {\n            hostname,\n            key_type,\n            remote_host_key,\n            location,\n        }) => {\n            let key_type_short_name = key_type.short_name();\n            anyhow::bail!(\n                \"error: Key has been revoked for `{hostname}`\\n\\\n                **************************************\\n\\\n                * WARNING: REVOKED HOST KEY DETECTED *\\n\\\n                **************************************\\n\\\n                This may indicate that the key provided by this host has been\\n\\\n                compromised and should not be accepted.\n                \\n\\\n                The host key {key_type_short_name} {remote_host_key} is revoked\\n\\\n                in {location} and has been rejected.\\n\\\n                \"\n            )\n        }\n        Err(KnownHostError::HostHasOnlyCertAuthority { hostname, location }) => {\n            anyhow::bail!(\"error: Found a `@cert-authority` marker for `{hostname}`\\n\\\n                \\n\\\n                Cargo doesn't support certificate authorities for host key verification. It is\\n\\\n                recommended that the command line Git client is used instead. This can be achieved\\n\\\n                by setting `net.git-fetch-with-cli` to `true` in the Cargo config.\\n\\\n                \\n\n                The `@cert-authority` line was found in {location}.\\n\\\n                \\n\\\n                See https://doc.rust-lang.org/stable/cargo/appendix/git-authentication.html#ssh-known-hosts \\\n                for more information.\\n\\\n                \")\n        }\n    }\n}\n\n/// Checks if the given host/host key pair is known.\nfn check_ssh_known_hosts(\n    gctx: &GlobalContext,\n    cert_host_key: &git2::cert::CertHostkey<'_>,\n    host: &str,\n    config_known_hosts: Option<&Vec<Value<String>>>,\n) -> Result<(), KnownHostError> {\n    let Some(remote_host_key) = cert_host_key.hostkey() else {\n        return Err(anyhow::format_err!(\"remote host key is not available\").into());\n    };\n    let remote_key_type = cert_host_key.hostkey_type().unwrap();\n\n    // Collect all the known host entries from disk.\n    let mut known_hosts = Vec::new();\n    for path in known_host_files(gctx) {\n        if !path.exists() {\n            continue;\n        }\n        let hosts = load_hostfile(&path)?;\n        known_hosts.extend(hosts);\n    }\n    if let Some(config_known_hosts) = config_known_hosts {\n        // Format errors aren't an error in case the format needs to change in\n        // the future, to retain forwards compatibility.\n        for line_value in config_known_hosts {\n            let location = KnownHostLocation::Config {\n                definition: line_value.definition.clone(),\n            };\n            match parse_known_hosts_line(&line_value.val, location) {\n                Some(known_host) => known_hosts.push(known_host),\n                None => tracing::warn!(\n                    \"failed to parse known host {} from {}\",\n                    line_value.val,\n                    line_value.definition\n                ),\n            }\n        }\n    }\n    // Load the bundled keys. Don't add keys for hosts that the user has\n    // configured, which gives them the option to override them. This could be\n    // useful if the keys are ever revoked.\n    let configured_hosts: HashSet<_> = known_hosts\n        .iter()\n        .flat_map(|known_host| {\n            known_host\n                .patterns\n                .split(',')\n                .map(|pattern| pattern.to_lowercase())\n        })\n        .collect();\n    for (patterns, key_type, key) in BUNDLED_KEYS {\n        if !configured_hosts.contains(*patterns) {\n            let key = STANDARD.decode(key).unwrap();\n            known_hosts.push(KnownHost {\n                location: KnownHostLocation::Bundled,\n                patterns: patterns.to_string(),\n                key_type: key_type.to_string(),\n                key,\n                line_type: KnownHostLineType::Key,\n            });\n        }\n    }\n    for (patterns, key_type, key) in BUNDLED_REVOCATIONS {\n        let key = STANDARD.decode(key).unwrap();\n        known_hosts.push(KnownHost {\n            location: KnownHostLocation::Bundled,\n            patterns: patterns.to_string(),\n            key_type: key_type.to_string(),\n            key,\n            line_type: KnownHostLineType::Revoked,\n        });\n    }\n    check_ssh_known_hosts_loaded(&known_hosts, host, remote_key_type, remote_host_key)\n}\n\n/// Checks a host key against a loaded set of known hosts.\nfn check_ssh_known_hosts_loaded(\n    known_hosts: &[KnownHost],\n    host: &str,\n    remote_key_type: SshHostKeyType,\n    remote_host_key: &[u8],\n) -> Result<(), KnownHostError> {\n    // `latent_error` keeps track of a potential error that will be returned\n    // in case a matching host key isn't found.\n    let mut latent_errors: Vec<KnownHostError> = Vec::new();\n\n    // `other_hosts` keeps track of any entries that have an identical key,\n    // but a different hostname.\n    let mut other_hosts = Vec::new();\n\n    // `accepted_known_host_found` keeps track of whether we've found a matching\n    // line in the `known_hosts` file that we would accept. We can't return that\n    // immediately, because there may be a subsequent @revoked key.\n    let mut accepted_known_host_found = false;\n\n    // Older versions of OpenSSH (before 6.8, March 2015) showed MD5\n    // fingerprints (see FingerprintHash ssh config option). Here we only\n    // support SHA256.\n    let mut remote_fingerprint = cargo_util::Sha256::new();\n    remote_fingerprint.update(remote_host_key);\n    let remote_fingerprint = STANDARD_NO_PAD.encode(remote_fingerprint.finish());\n    let remote_host_key_encoded = STANDARD.encode(remote_host_key);\n\n    for known_host in known_hosts {\n        // The key type from libgit2 needs to match the key type from the host file.\n        if known_host.key_type != remote_key_type.name() {\n            continue;\n        }\n        let key_matches = known_host.key == remote_host_key;\n        if !known_host.host_matches(host) {\n            if key_matches {\n                other_hosts.push(known_host.clone());\n            }\n            continue;\n        }\n        match known_host.line_type {\n            KnownHostLineType::Key => {\n                if key_matches {\n                    accepted_known_host_found = true;\n                } else {\n                    // The host and key type matched, but the key itself did not.\n                    // This indicates the key has changed.\n                    // This is only reported as an error if no subsequent lines have a\n                    // correct key.\n                    latent_errors.push(KnownHostError::HostKeyHasChanged {\n                        hostname: host.to_string(),\n                        key_type: remote_key_type,\n                        old_known_host: known_host.clone(),\n                        remote_host_key: remote_host_key_encoded.clone(),\n                        remote_fingerprint: remote_fingerprint.clone(),\n                    });\n                }\n            }\n            KnownHostLineType::Revoked => {\n                if key_matches {\n                    return Err(KnownHostError::HostKeyRevoked {\n                        hostname: host.to_string(),\n                        key_type: remote_key_type,\n                        remote_host_key: remote_host_key_encoded,\n                        location: known_host.location.clone(),\n                    });\n                }\n            }\n            KnownHostLineType::CertAuthority => {\n                // The host matches a @cert-authority line, which is unsupported.\n                latent_errors.push(KnownHostError::HostHasOnlyCertAuthority {\n                    hostname: host.to_string(),\n                    location: known_host.location.clone(),\n                });\n            }\n        }\n    }\n\n    // We have an accepted host key and it hasn't been revoked.\n    if accepted_known_host_found {\n        return Ok(());\n    }\n\n    if latent_errors.is_empty() {\n        // FIXME: Ideally the error message should include the IP address of the\n        // remote host (to help the user validate that they are connecting to the\n        // host they were expecting to). However, I don't see a way to obtain that\n        // information from libgit2.\n        Err(KnownHostError::HostKeyNotFound {\n            hostname: host.to_string(),\n            key_type: remote_key_type,\n            remote_host_key: remote_host_key_encoded,\n            remote_fingerprint,\n            other_hosts,\n        })\n    } else {\n        // We're going to take the first HostKeyHasChanged error if\n        // we find one, otherwise we'll take the first error (which\n        // we expect to be a CertAuthority error).\n        if let Some(index) = latent_errors\n            .iter()\n            .position(|e| matches!(e, KnownHostError::HostKeyHasChanged { .. }))\n        {\n            return Err(latent_errors.remove(index));\n        } else {\n            // Otherwise, we take the first error (which we expect to be\n            // a CertAuthority error).\n            Err(latent_errors.pop().unwrap())\n        }\n    }\n}\n\n/// Returns a list of files to try loading OpenSSH-formatted known hosts.\nfn known_host_files(gctx: &GlobalContext) -> Vec<PathBuf> {\n    let mut result = Vec::new();\n    if gctx\n        .get_env_os(\"__CARGO_TEST_DISABLE_GLOBAL_KNOWN_HOST\")\n        .is_some()\n    {\n    } else if cfg!(unix) {\n        result.push(PathBuf::from(\"/etc/ssh/ssh_known_hosts\"));\n    } else if cfg!(windows) {\n        // The msys/cygwin version of OpenSSH uses `/etc` from the posix root\n        // filesystem there (such as `C:\\msys64\\etc\\ssh\\ssh_known_hosts`).\n        // However, I do not know of a way to obtain that location from\n        // Windows-land. The ProgramData version here is what the PowerShell\n        // port of OpenSSH does.\n        if let Some(progdata) = gctx.get_env_os(\"ProgramData\") {\n            let mut progdata = PathBuf::from(progdata);\n            progdata.push(\"ssh\");\n            progdata.push(\"ssh_known_hosts\");\n            result.push(progdata)\n        }\n    }\n    result.extend(user_known_host_location());\n    result\n}\n\n/// The location of the user's `known_hosts` file.\nfn user_known_host_location() -> Option<PathBuf> {\n    // NOTE: This is a potentially inaccurate prediction of what the user\n    // actually wants. The actual location depends on several factors:\n    //\n    // - Windows OpenSSH Powershell version: I believe this looks up the home\n    //   directory via ProfileImagePath in the registry, falling back to\n    //   `GetWindowsDirectoryW` if that fails.\n    // - OpenSSH Portable (under msys): This is very complicated. I got lost\n    //   after following it through some ldap/active directory stuff.\n    // - OpenSSH (most unix platforms): Uses `pw->pw_dir` from `getpwuid()`.\n    //\n    // This doesn't do anything close to that. home_dir's behavior is:\n    // - Windows: $USERPROFILE, or SHGetKnownFolderPath()\n    // - Unix: $HOME, or getpwuid_r()\n    //\n    // Since there is a mismatch here, the location returned here might be\n    // different than what the user's `ssh` CLI command uses. We may want to\n    // consider trying to align it better.\n    home::home_dir().map(|mut home| {\n        home.push(\".ssh\");\n        home.push(\"known_hosts\");\n        home\n    })\n}\n\n/// The location to display in an error message instructing the user where to\n/// add the new key.\nfn user_known_host_location_to_add(diagnostic_home_config: &str) -> String {\n    // Note that we don't bother with the legacy known_hosts2 files.\n    let user = user_known_host_location();\n    let openssh_loc = match &user {\n        Some(path) => path.to_str().expect(\"utf-8 home\"),\n        None => \"~/.ssh/known_hosts\",\n    };\n    format!(\n        \"the `net.ssh.known-hosts` array in your Cargo configuration \\\n        (such as {diagnostic_home_config}) \\\n        or in your OpenSSH known_hosts file at {openssh_loc}\"\n    )\n}\n\nconst HASH_HOSTNAME_PREFIX: &str = \"|1|\";\n\n#[derive(Clone)]\nenum KnownHostLineType {\n    Key,\n    CertAuthority,\n    Revoked,\n}\n\n/// A single known host entry.\n#[derive(Clone)]\nstruct KnownHost {\n    location: KnownHostLocation,\n    /// The hostname. May be comma separated to match multiple hosts.\n    patterns: String,\n    key_type: String,\n    key: Vec<u8>,\n    line_type: KnownHostLineType,\n}\n\nimpl KnownHost {\n    /// Returns whether or not the given host matches this known host entry.\n    fn host_matches(&self, host: &str) -> bool {\n        let mut match_found = false;\n        let host = host.to_lowercase();\n        if let Some(hashed) = self.patterns.strip_prefix(HASH_HOSTNAME_PREFIX) {\n            return hashed_hostname_matches(&host, hashed);\n        }\n        for pattern in self.patterns.split(',') {\n            let pattern = pattern.to_lowercase();\n\n            let (negated, pattern) = match pattern.strip_prefix('!') {\n                Some(rest) => (true, rest.to_string()),\n                None => (false, pattern),\n            };\n\n            let matches = if is_glob_pattern(&pattern) && !is_bracketed_with_port(&pattern) {\n                match glob::Pattern::new(&pattern) {\n                    Ok(glob) => glob.matches(&host),\n                    Err(e) => {\n                        tracing::warn!(\n                            \"failed to interpret hostname `{pattern}` as glob pattern: {e}\"\n                        );\n                        false\n                    }\n                }\n            } else {\n                pattern == host\n            };\n\n            // if the host is a negation and the rest matches then preemtively return false\n            if negated && matches {\n                return false;\n            }\n\n            // note that if a negation does not match then it does not mean that we found a match\n            match_found |= !negated && matches;\n        }\n        match_found\n    }\n}\n\nfn is_bracketed_with_port(pattern: &str) -> bool {\n    pattern.starts_with('[') && pattern.contains(\"]:\")\n}\n\nfn hashed_hostname_matches(host: &str, hashed: &str) -> bool {\n    let Some((b64_salt, b64_host)) = hashed.split_once('|') else {\n        return false;\n    };\n    let Ok(salt) = STANDARD.decode(b64_salt) else {\n        return false;\n    };\n    let Ok(hashed_host) = STANDARD.decode(b64_host) else {\n        return false;\n    };\n    let Ok(mut mac) = hmac::Hmac::<sha1::Sha1>::new_from_slice(&salt) else {\n        return false;\n    };\n    mac.update(host.as_bytes());\n    let result = mac.finalize().into_bytes();\n    hashed_host == &result[..]\n}\n\n/// Loads an OpenSSH `known_hosts` file.\nfn load_hostfile(path: &Path) -> Result<Vec<KnownHost>, anyhow::Error> {\n    let contents = cargo_util::paths::read(path)?;\n    Ok(load_hostfile_contents(path, &contents))\n}\n\nfn load_hostfile_contents(path: &Path, contents: &str) -> Vec<KnownHost> {\n    let entries = contents\n        .lines()\n        .enumerate()\n        .filter_map(|(lineno, line)| {\n            let location = KnownHostLocation::File {\n                path: path.to_path_buf(),\n                lineno: lineno as u32 + 1,\n            };\n            parse_known_hosts_line(line, location)\n        })\n        .collect();\n    entries\n}\n\nfn parse_known_hosts_line(line: &str, location: KnownHostLocation) -> Option<KnownHost> {\n    let line = line.trim();\n    if line.is_empty() || line.starts_with('#') {\n        return None;\n    }\n    let mut parts = line.split([' ', '\\t']).filter(|s| !s.is_empty());\n\n    let line_type = if line.starts_with(\"@\") {\n        let line_type = parts.next()?;\n\n        if line_type == \"@cert-authority\" {\n            KnownHostLineType::CertAuthority\n        } else if line_type == \"@revoked\" {\n            KnownHostLineType::Revoked\n        } else {\n            // No other markers are defined\n            return None;\n        }\n    } else {\n        KnownHostLineType::Key\n    };\n\n    let patterns = parts.next()?;\n    let key_type = parts.next()?;\n    let key = parts.next().map(|p| STANDARD.decode(p))?.ok()?;\n    Some(KnownHost {\n        line_type,\n        location,\n        patterns: patterns.to_string(),\n        key_type: key_type.to_string(),\n        key,\n    })\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    static COMMON_CONTENTS: &str = r#\"\n        # Comments allowed at start of line\n\n        example.com,rust-lang.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC5MzWIpZwpkpDjyCNiTIEVFhSA9OUUQvjFo7CgZBGCAj/cqeUIgiLsgtfmtBsfWIkAECQpM7ePP7NLZFGJcHvoyg5jXJiIX5s0eKo9IlcuTLLrMkW5MkHXE7bNklVbW1WdCfF2+y7Ao25B4L8FFRokMh0yp/H6+8xZ7PdVwL3FRPEg8ftZ5R0kuups6xiMHPRX+f/07vfJzA47YDPmXfhkn+JK8kL0JYw8iy8BtNBfRQL99d9iXJzWXnNce5NHMuKD5rOonD3aQHLDlwK+KhrFRrdaxQEM8ZWxNti0ux8yT4Dl5jJY0CrIu3Xl6+qroVgTqJGNkTbhs5DGWdFh6BLPTTH15rN4buisg7uMyLyHqx06ckborqD33gWu+Jig7O+PV6KJmL5mp1O1HXvZqkpBdTiT6GiDKG3oECCIXkUk0BSU9VG9VQcrMxxvgiHlyoXUAfYQoXv/lnxkTnm+Sr36kutsVOs7n5B43ZKAeuaxyQ11huJZpxamc0RA1HM641s= eric@host\n        Example.net ssh-dss AAAAB3NzaC1kc3MAAACBAK2Ek3jVxisXmz5UcZ7W65BAj/nDJCCVvSe0Aytndn4PH6k7sVesut5OoY6PdksZ9tEfuFjjS9HR5SJb8j1GW0GxtaSHHbf+rNc36PeU75bffzyIWwpA8uZFONt5swUAXJXcsHOoapNbUFuhHsRhB2hXxz9QGNiiwIwRJeSHixKRAAAAFQChKfxO1z9H2/757697xP5nJ/Z5dwAAAIEAoc+HIWas+4WowtB/KtAp6XE0B9oHI+55wKtdcGwwb7zHKK9scWNXwxIcMhSvyB3Oe2I7dQQlvyIWxsdZlzOkX0wdsTHjIAnBAP68MyvMv4kq3+I5GAVcFsqoLZfZvh0dlcgUq1/YNYZwKlt89tnzk8Fp4KLWmuw8Bd8IShYVa78AAACAL3qd8kNTY7CthgsQ8iWdjbkGSF/1KCeFyt8UjurInp9wvPDjqagwakbyLOzN7y3/ItTPCaGuX+RjFP0zZTf8i9bsAVyjFJiJ7vzRXcWytuFWANrpzLTn1qzPfh63iK92Aw8AVBYvEA/4bxo+XReAvhNBB/m78G6OedTeu6ZoTsI= eric@host\n        [example.net]:2222 ssh-dss AAAAB3NzaC1kc3MAAACBAJJN5kLZEpOJpXWyMT4KwYvLAj+b9ErNtglxOi86C6Kw7oZeYdDMCfD3lc3PJyX64udQcWGfO4abSESMiYdY43yFAZH279QGH5Q/B5CklVvTqYpfAUR+1r9TQxy3OVQHk7FB2wOi4xNQ3myO0vaYlBOB9il+P223aERbXx4JTWdvAAAAFQCTHWTcXxLK5Z6ZVPmfdSDyHzkF2wAAAIEAhp41/mTnM0Y0EWSyCXuETMW1QSpKGF8sqoZKp6wdzyhLXu0i32gLdXj4p24em/jObYh93hr+MwgxqWq+FHgD+D80Qg5f6vj4yEl4Uu5hqtTpCBFWUQoyEckbUkPf8uZ4/XzAne+tUSjZm09xATCmK9U2IGqZE+D+90eBkf1Svc8AAACAeKhi4EtfwenFYqKz60ZoEEhIsE1yI2jH73akHnfHpcW84w+fk3YlwjcfDfyYso+D0jZBdJeK5qIdkbUWhAX8wDjJVO0WL6r/YPr4yu/CgEyW1H59tAbujGJ4NR0JDqioulzYqNHnxpiw1RJukZnPBfSFKzRElvPOCq/NkQM/Mwk= eric@host\n        nistp256.example.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJ4iYGCcJrUIfrHfzlsv8e8kaF36qpcUpe3VNAKVCZX/BDptIdlEe8u8vKNRTPgUO9jqS0+tjTcPiQd8/8I9qng= eric@host\n        nistp384.example.org ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBNuGT3TqMz2rcwOt2ZqkiNqq7dvWPE66W2qPCoZsh0pQhVU3BnhKIc6nEr6+Wts0Z3jdF3QWwxbbTjbVTVhdr8fMCFhDCWiQFm9xLerYPKnu9qHvx9K87/fjc5+0pu4hLA== eric@host\n        nistp521.example.org ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAD35HH6OsK4DN75BrKipVj/GvZaUzjPNa1F8wMjUdPB1JlVcUfgzJjWSxrhmaNN3u0soiZw8WNRFINsGPCw5E7DywF1689WcIj2Ye2rcy99je15FknScTzBBD04JgIyOI50mCUaPCBoF14vFlN6BmO00cFo+yzy5N8GuQ2sx9kr21xmFQ== eric@host\n        # Revoked is supported, but without Cert-Authority support, it will only negate some other fixed key.\n        @revoked revoked.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKtQsi+KPYispwm2rkMidQf30fG1Niy8XNkvASfePoca eric@host\n        # Cert-Authority is not supported (below key should not be valid anyway)\n        @cert-authority ca.example.com ssh-rsa AABBB5Wm\n        example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAWkjI6XT2SZh3xNk5NhisA3o3sGzWR+VAKMSqHtI0aY eric@host\n        192.168.42.12 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKVYJpa0yUGaNk0NXQTPWa0tHjqRpx+7hl2diReH6DtR eric@host\n        |1|QxzZoTXIWLhUsuHAXjuDMIV3FjQ=|M6NCOIkjiWdCWqkh5+Q+/uFLGjs= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIHgN3O21U4LWtP5OzjTzPnUnSDmCNDvyvlaj6Hi65JC eric@host\n        # Negation isn't terribly useful without globs.\n        neg.example.com,!neg.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOXfUnaAHTlo1Qi//rNk26OcmHikmkns1Z6WW/UuuS3K eric@host\n        # Glob patterns\n        *.asterisk.glob.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO6/wm8Z5aVL2cDyALY6zE7KVW0s64utWTUmbAvvSKlI eric@host\n        test?.question.glob.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKceiey2vuK/WB/kLsiGa85xw897JzvGGaHmkAZbVHf3 eric@host\n    \"#;\n\n    #[test]\n    fn known_hosts_parse() {\n        let kh_path = Path::new(\"/home/abc/.known_hosts\");\n        let khs = load_hostfile_contents(kh_path, COMMON_CONTENTS);\n        assert_eq!(khs.len(), 14);\n        match &khs[0].location {\n            KnownHostLocation::File { path, lineno } => {\n                assert_eq!(path, kh_path);\n                assert_eq!(*lineno, 4);\n            }\n            _ => panic!(\"unexpected\"),\n        }\n        assert_eq!(khs[0].patterns, \"example.com,rust-lang.org\");\n        assert_eq!(khs[0].key_type, \"ssh-rsa\");\n        assert_eq!(khs[0].key.len(), 407);\n        assert_eq!(&khs[0].key[..30], b\"\\x00\\x00\\x00\\x07ssh-rsa\\x00\\x00\\x00\\x03\\x01\\x00\\x01\\x00\\x00\\x01\\x81\\x00\\xb935\\x88\\xa5\\x9c)\");\n        match &khs[1].location {\n            KnownHostLocation::File { path, lineno } => {\n                assert_eq!(path, kh_path);\n                assert_eq!(*lineno, 5);\n            }\n            _ => panic!(\"unexpected\"),\n        }\n        assert_eq!(khs[2].patterns, \"[example.net]:2222\");\n        assert_eq!(khs[3].patterns, \"nistp256.example.org\");\n        assert_eq!(khs[9].patterns, \"192.168.42.12\");\n    }\n\n    #[test]\n    fn host_matches() {\n        let kh_path = Path::new(\"/home/abc/.known_hosts\");\n        let khs = load_hostfile_contents(kh_path, COMMON_CONTENTS);\n        assert!(khs[0].host_matches(\"example.com\"));\n        assert!(khs[0].host_matches(\"rust-lang.org\"));\n        assert!(khs[0].host_matches(\"EXAMPLE.COM\"));\n        assert!(khs[1].host_matches(\"example.net\"));\n        assert!(!khs[0].host_matches(\"example.net\"));\n        assert!(khs[2].host_matches(\"[example.net]:2222\"));\n        assert!(!khs[2].host_matches(\"example.net\"));\n        assert!(khs[10].host_matches(\"hashed.example.com\"));\n        assert!(!khs[10].host_matches(\"example.com\"));\n        assert!(!khs[11].host_matches(\"neg.example.com\"));\n\n        // Glob patterns\n        assert!(khs[12].host_matches(\"matches.asterisk.glob.example.com\"));\n        assert!(!khs[12].host_matches(\"matches.not.glob.example.com\"));\n        assert!(khs[13].host_matches(\"test3.question.glob.example.com\"));\n        assert!(!khs[13].host_matches(\"test120.question.glob.example.com\"));\n    }\n\n    #[test]\n    fn check_match() {\n        let kh_path = Path::new(\"/home/abc/.known_hosts\");\n        let khs = load_hostfile_contents(kh_path, COMMON_CONTENTS);\n\n        assert!(\n            check_ssh_known_hosts_loaded(&khs, \"example.com\", SshHostKeyType::Rsa, &khs[0].key)\n                .is_ok()\n        );\n\n        match check_ssh_known_hosts_loaded(&khs, \"example.com\", SshHostKeyType::Dss, &khs[0].key) {\n            Err(KnownHostError::HostKeyNotFound {\n                hostname,\n                remote_fingerprint,\n                other_hosts,\n                ..\n            }) => {\n                assert_eq!(\n                    remote_fingerprint,\n                    \"yn+pONDn0EcgdOCVptgB4RZd/wqmsVKrPnQMLtrvhw8\"\n                );\n                assert_eq!(hostname, \"example.com\");\n                assert_eq!(other_hosts.len(), 0);\n            }\n            _ => panic!(\"unexpected\"),\n        }\n\n        match check_ssh_known_hosts_loaded(\n            &khs,\n            \"foo.example.com\",\n            SshHostKeyType::Rsa,\n            &khs[0].key,\n        ) {\n            Err(KnownHostError::HostKeyNotFound { other_hosts, .. }) => {\n                assert_eq!(other_hosts.len(), 1);\n                assert_eq!(other_hosts[0].patterns, \"example.com,rust-lang.org\");\n            }\n            _ => panic!(\"unexpected\"),\n        }\n\n        let mut modified_key = khs[0].key.clone();\n        modified_key[0] = 1;\n        match check_ssh_known_hosts_loaded(&khs, \"example.com\", SshHostKeyType::Rsa, &modified_key)\n        {\n            Err(KnownHostError::HostKeyHasChanged { old_known_host, .. }) => {\n                assert!(matches!(\n                    old_known_host.location,\n                    KnownHostLocation::File { lineno: 4, .. }\n                ));\n            }\n            _ => panic!(\"unexpected\"),\n        }\n    }\n\n    #[test]\n    fn revoked() {\n        let kh_path = Path::new(\"/home/abc/.known_hosts\");\n        let khs = load_hostfile_contents(kh_path, COMMON_CONTENTS);\n\n        match check_ssh_known_hosts_loaded(\n            &khs,\n            \"revoked.example.com\",\n            SshHostKeyType::Ed255219,\n            &khs[6].key,\n        ) {\n            Err(KnownHostError::HostKeyRevoked {\n                hostname, location, ..\n            }) => {\n                assert_eq!(\"revoked.example.com\", hostname);\n                assert!(matches!(\n                    location,\n                    KnownHostLocation::File { lineno: 11, .. }\n                ));\n            }\n            _ => panic!(\"Expected key to be revoked for revoked.example.com.\"),\n        }\n    }\n\n    #[test]\n    fn cert_authority() {\n        let kh_path = Path::new(\"/home/abc/.known_hosts\");\n        let khs = load_hostfile_contents(kh_path, COMMON_CONTENTS);\n\n        match check_ssh_known_hosts_loaded(\n            &khs,\n            \"ca.example.com\",\n            SshHostKeyType::Rsa,\n            &khs[0].key, // The key should not matter\n        ) {\n            Err(KnownHostError::HostHasOnlyCertAuthority {\n                hostname, location, ..\n            }) => {\n                assert_eq!(\"ca.example.com\", hostname);\n                assert!(matches!(\n                    location,\n                    KnownHostLocation::File { lineno: 13, .. }\n                ));\n            }\n            Err(KnownHostError::HostKeyNotFound { hostname, .. }) => {\n                panic!(\"host key not found... {}\", hostname);\n            }\n            _ => panic!(\"Expected host to only have @cert-authority line (which is unsupported).\"),\n        }\n    }\n\n    #[test]\n    fn multiple_errors() {\n        let contents = r#\"\n        not-used.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAWkjI6XT2SZh3xNk5NhisA3o3sGzWR+VAKMSqHtI0aY eric@host\n        # Cert-authority and changed key for the same host - changed key error should prevail\n        @cert-authority example.com ssh-ed25519 AABBB5Wm\n        example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKVYJpa0yUGaNk0NXQTPWa0tHjqRpx+7hl2diReH6DtR eric@host\n        \"#;\n\n        let kh_path = Path::new(\"/home/abc/.known_hosts\");\n        let khs = load_hostfile_contents(kh_path, contents);\n\n        match check_ssh_known_hosts_loaded(\n            &khs,\n            \"example.com\",\n            SshHostKeyType::Ed255219,\n            &khs[0].key,\n        ) {\n            Err(KnownHostError::HostKeyHasChanged {\n                hostname,\n                old_known_host,\n                remote_host_key,\n                ..\n            }) => {\n                assert_eq!(\"example.com\", hostname);\n                assert_eq!(\n                    \"AAAAC3NzaC1lZDI1NTE5AAAAIAWkjI6XT2SZh3xNk5NhisA3o3sGzWR+VAKMSqHtI0aY\",\n                    remote_host_key\n                );\n                assert!(matches!(\n                    old_known_host.location,\n                    KnownHostLocation::File { lineno: 5, .. }\n                ));\n            }\n            _ => panic!(\"Expected error to be of type HostKeyHasChanged.\"),\n        }\n    }\n\n    #[test]\n    fn known_host_and_revoked() {\n        let contents = r#\"\n        example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKVYJpa0yUGaNk0NXQTPWa0tHjqRpx+7hl2diReH6DtR eric@host\n        # Later in the file the same host key is revoked\n        @revoked example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKVYJpa0yUGaNk0NXQTPWa0tHjqRpx+7hl2diReH6DtR eric@host\n        \"#;\n\n        let kh_path = Path::new(\"/home/abc/.known_hosts\");\n        let khs = load_hostfile_contents(kh_path, contents);\n\n        match check_ssh_known_hosts_loaded(\n            &khs,\n            \"example.com\",\n            SshHostKeyType::Ed255219,\n            &khs[0].key,\n        ) {\n            Err(KnownHostError::HostKeyRevoked {\n                hostname,\n                remote_host_key,\n                location,\n                ..\n            }) => {\n                assert_eq!(\"example.com\", hostname);\n                assert_eq!(\n                    \"AAAAC3NzaC1lZDI1NTE5AAAAIKVYJpa0yUGaNk0NXQTPWa0tHjqRpx+7hl2diReH6DtR\",\n                    remote_host_key\n                );\n                assert!(matches!(\n                    location,\n                    KnownHostLocation::File { lineno: 4, .. }\n                ));\n            }\n            _ => panic!(\"Expected host key to be reject with error HostKeyRevoked.\"),\n        }\n    }\n\n    #[test]\n    fn negated_glob_rejects_match() {\n        let contents = r#\"\n            *example.com,!*h.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKVYJpa0yUGaNk0NXQTPWa0tHjqRpx+7hl2diReH6DtR\n            \"#;\n        let kh_path = Path::new(\"/home/abc/.known_hosts\");\n        let khs = load_hostfile_contents(kh_path, contents);\n\n        assert!(khs[0].host_matches(\"web.example.com\"));\n        assert!(\n            !khs[0].host_matches(\"ssh.example.com\"),\n            \"negated glob !*.example.com should reject ssh.example.com\"\n        );\n    }\n\n    #[test]\n    fn validate_bracketed_host_with_port() {\n        let contents = r#\"\n            [example.com]:2222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKVYJpa0yUGaNk0NXQTPWa0tHjqRpx+7hl2diReH6DtR\n            \"#;\n        let kh_path = Path::new(\"/home/abc/.known_hosts\");\n        let khs = load_hostfile_contents(kh_path, contents);\n\n        assert!(\n            !khs[0].host_matches(\"e:2222\"),\n            \"Bracketed host with port should not be glob matched\"\n        );\n        assert!(\n            !khs[0].host_matches(\"[example.com]:443\"),\n            \"Bracketed host with different port should not match\"\n        );\n        assert!(\n            khs[0].host_matches(\"[example.com]:2222\"),\n            \"Bracketed host with port should match\"\n        );\n    }\n}\n"
  },
  {
    "path": "src/cargo/sources/git/mod.rs",
    "content": "//! Home of the [`GitSource`].\n//!\n//! Apparently, the most important type in this module is [`GitSource`].\n//! [`utils`] provides libgit2 utilities like fetch and checkout, whereas\n//! [`oxide`] is the counterpart for gitoxide integration. [`known_hosts`]\n//! is the mitigation of [CVE-2022-46176].\n//!\n//! [CVE-2022-46176]: https://blog.rust-lang.org/2023/01/10/cve-2022-46176.html\n\npub use self::source::GitSource;\npub use self::utils::{GitCheckout, GitDatabase, GitRemote, fetch, resolve_ref};\nmod known_hosts;\nmod oxide;\nmod source;\nmod utils;\n\n/// For `-Zgitoxide` integration.\npub mod fetch {\n    use crate::GlobalContext;\n    use crate::core::features::GitFeatures;\n\n    /// The kind remote repository to fetch.\n    #[derive(Debug, Copy, Clone)]\n    pub enum RemoteKind {\n        /// A repository belongs to a git dependency.\n        GitDependency,\n        /// A repository belongs to a Cargo registry.\n        Registry,\n    }\n\n    impl RemoteKind {\n        /// Obtain the kind of history we would want for a fetch from our remote knowing if the target repo is already shallow\n        /// via `repo_is_shallow` along with gitoxide-specific feature configuration via `config`.\n        /// `rev_and_ref` is additional information that affects whether or not we may be shallow.\n        pub(crate) fn to_shallow_setting(\n            &self,\n            repo_is_shallow: bool,\n            gctx: &GlobalContext,\n        ) -> gix::remote::fetch::Shallow {\n            let has_feature = |cb: &dyn Fn(GitFeatures) -> bool| {\n                gctx.cli_unstable()\n                    .git\n                    .map_or(false, |features| cb(features))\n            };\n\n            // maintain shallow-ness and keep downloading single commits, or see if we can do shallow clones\n            if !repo_is_shallow {\n                match self {\n                    RemoteKind::GitDependency if has_feature(&|features| features.shallow_deps) => {\n                    }\n                    RemoteKind::Registry if has_feature(&|features| features.shallow_index) => {}\n                    _ => return gix::remote::fetch::Shallow::NoChange,\n                }\n            };\n\n            gix::remote::fetch::Shallow::DepthAtRemote(1.try_into().expect(\"non-zero\"))\n        }\n    }\n\n    pub type Error = gix::env::collate::fetch::Error<gix::refspec::parse::Error>;\n}\n"
  },
  {
    "path": "src/cargo/sources/git/oxide.rs",
    "content": "//! This module contains all code sporting `gitoxide` for operations on `git` repositories and it mirrors\n//! `utils` closely for now. One day it can be renamed into `utils` once `git2` isn't required anymore.\n\nuse crate::util::HumanBytes;\nuse crate::util::network::http::HttpTimeout;\nuse crate::util::{MetricsCounter, Progress, network};\nuse crate::{CargoResult, GlobalContext};\nuse cargo_util::paths;\nuse gix::bstr::{BString, ByteSlice};\nuse std::cell::RefCell;\nuse std::path::Path;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::sync::{Arc, Weak};\nuse std::time::{Duration, Instant};\nuse tracing::debug;\n\n/// For the time being, `repo_path` makes it easy to instantiate a gitoxide repo just for fetching.\n/// In future this may change to be the gitoxide repository itself.\npub fn with_retry_and_progress(\n    repo_path: &std::path::Path,\n    gctx: &GlobalContext,\n    repo_remote_url: &str,\n    cb: &(\n         dyn Fn(\n        &std::path::Path,\n        &AtomicBool,\n        &mut gix::progress::tree::Item,\n        &mut dyn FnMut(&gix::bstr::BStr),\n    ) -> Result<(), crate::sources::git::fetch::Error>\n             + Send\n             + Sync\n     ),\n) -> CargoResult<()> {\n    std::thread::scope(|s| {\n        let mut progress_bar = Progress::new(\"Fetch\", gctx);\n        let is_shallow = gctx.cli_unstable().git.map_or(false, |features| {\n            features.shallow_deps || features.shallow_index\n        });\n        network::retry::with_retry(gctx, || {\n            let progress_root: Arc<gix::progress::tree::Root> =\n                gix::progress::tree::root::Options {\n                    initial_capacity: 10,\n                    message_buffer_capacity: 10,\n                }\n                .into();\n            let root = Arc::downgrade(&progress_root);\n            let thread = s.spawn(move || {\n                let mut progress = progress_root.add_child(\"operation\");\n                let mut urls = RefCell::new(Default::default());\n                let res = cb(\n                    &repo_path,\n                    &AtomicBool::default(),\n                    &mut progress,\n                    &mut |url| {\n                        *urls.borrow_mut() = Some(url.to_owned());\n                    },\n                );\n                amend_authentication_hints(res, repo_remote_url, urls.get_mut().take())\n            });\n            translate_progress_to_bar(&mut progress_bar, root, is_shallow)?;\n            thread.join().expect(\"no panic in scoped thread\")\n        })\n    })\n}\n\nfn translate_progress_to_bar(\n    progress_bar: &mut Progress<'_>,\n    root: Weak<gix::progress::tree::Root>,\n    is_shallow: bool,\n) -> CargoResult<()> {\n    let remote_progress: gix::progress::Id = gix::remote::fetch::ProgressId::RemoteProgress.into();\n    let read_pack_bytes: gix::progress::Id =\n        gix::odb::pack::bundle::write::ProgressId::ReadPackBytes.into();\n    let delta_index_objects: gix::progress::Id =\n        gix::odb::pack::index::write::ProgressId::IndexObjects.into();\n    let resolve_objects: gix::progress::Id =\n        gix::odb::pack::index::write::ProgressId::ResolveObjects.into();\n\n    // We choose `N=10` here to make a `300ms * 10slots ~= 3000ms`\n    // sliding window for tracking the data transfer rate (in bytes/s).\n    let mut last_percentage_update = Instant::now();\n    let mut last_fast_update = Instant::now();\n    let mut counter = MetricsCounter::<10>::new(0, last_percentage_update);\n\n    let mut tasks = Vec::with_capacity(10);\n    let slow_check_interval = std::time::Duration::from_millis(300);\n    let fast_check_interval = Duration::from_millis(50);\n    let sleep_interval = Duration::from_millis(10);\n    debug_assert_eq!(\n        slow_check_interval.as_millis() % fast_check_interval.as_millis(),\n        0,\n        \"progress should be smoother by keeping these as multiples of each other\"\n    );\n    debug_assert_eq!(\n        fast_check_interval.as_millis() % sleep_interval.as_millis(),\n        0,\n        \"progress should be smoother by keeping these as multiples of each other\"\n    );\n\n    let num_phases = if is_shallow { 3 } else { 2 }; // indexing + delta-resolution, both with same amount of objects to handle\n    while let Some(root) = root.upgrade() {\n        std::thread::sleep(sleep_interval);\n        let needs_update = last_fast_update.elapsed() >= fast_check_interval;\n        if !needs_update {\n            continue;\n        }\n        let now = Instant::now();\n        last_fast_update = now;\n\n        root.sorted_snapshot(&mut tasks);\n\n        fn progress_by_id(\n            id: gix::progress::Id,\n            task: &gix::progress::Task,\n        ) -> Option<(&str, &gix::progress::Value)> {\n            (task.id == id)\n                .then(|| task.progress.as_ref())\n                .flatten()\n                .map(|value| (task.name.as_str(), value))\n        }\n        fn find_in<K>(\n            tasks: &[(K, gix::progress::Task)],\n            cb: impl Fn(&gix::progress::Task) -> Option<(&str, &gix::progress::Value)>,\n        ) -> Option<(&str, &gix::progress::Value)> {\n            tasks.iter().find_map(|(_, t)| cb(t))\n        }\n\n        if let Some((_, objs)) = find_in(&tasks, |t| progress_by_id(resolve_objects, t)) {\n            // Phase 3: Resolving deltas.\n            let objects = objs.step.load(Ordering::Relaxed);\n            let total_objects = objs.done_at.expect(\"known amount of objects\");\n            let msg = format!(\", ({objects}/{total_objects}) resolving deltas\");\n\n            progress_bar.tick(\n                (total_objects * (num_phases - 1)) + objects,\n                total_objects * num_phases,\n                &msg,\n            )?;\n        } else if let Some((objs, read_pack)) =\n            find_in(&tasks, |t| progress_by_id(read_pack_bytes, t)).and_then(|read| {\n                find_in(&tasks, |t| progress_by_id(delta_index_objects, t))\n                    .map(|delta| (delta.1, read.1))\n            })\n        {\n            // Phase 2: Receiving objects.\n            let objects = objs.step.load(Ordering::Relaxed);\n            let total_objects = objs.done_at.expect(\"known amount of objects\");\n            let received_bytes = read_pack.step.load(Ordering::Relaxed);\n\n            let needs_percentage_update = last_percentage_update.elapsed() >= slow_check_interval;\n            if needs_percentage_update {\n                counter.add(received_bytes, now);\n                last_percentage_update = now;\n            }\n            let rate = HumanBytes(counter.rate() as u64);\n            let msg = format!(\", {rate:.2}/s\");\n\n            progress_bar.tick(\n                (total_objects * (num_phases - 2)) + objects,\n                total_objects * num_phases,\n                &msg,\n            )?;\n        } else if let Some((action, remote)) =\n            find_in(&tasks, |t| progress_by_id(remote_progress, t))\n        {\n            if !is_shallow {\n                continue;\n            }\n            // phase 1: work on the remote side\n\n            // Resolving deltas.\n            let objects = remote.step.load(Ordering::Relaxed);\n            if let Some(total_objects) = remote.done_at {\n                let msg = format!(\", ({objects}/{total_objects}) {action}\");\n                progress_bar.tick(objects, total_objects * num_phases, &msg)?;\n            }\n        }\n    }\n    Ok(())\n}\n\nfn amend_authentication_hints(\n    res: Result<(), crate::sources::git::fetch::Error>,\n    remote_url: &str,\n    last_url_for_authentication: Option<gix::bstr::BString>,\n) -> CargoResult<()> {\n    let Err(err) = res else { return Ok(()) };\n    let e = match &err {\n        crate::sources::git::fetch::Error::PrepareFetch(\n            gix::remote::fetch::prepare::Error::RefMap(gix::remote::ref_map::Error::Handshake(err)),\n        ) => Some(err),\n        _ => None,\n    };\n\n    if let Some(e) = e {\n        let auth_message = match e {\n            gix::protocol::handshake::Error::Credentials(_) => {\n                \"\\n* attempted to find username/password via \\\n                     git's `credential.helper` support, but failed\"\n                    .into()\n            }\n            gix::protocol::handshake::Error::InvalidCredentials { .. } => {\n                \"\\n* attempted to find username/password via \\\n                     `credential.helper`, but maybe the found \\\n                     credentials were incorrect\"\n                    .into()\n            }\n            gix::protocol::handshake::Error::Transport(_) => {\n                let msg = format!(\n                    concat!(\n                        \"network failure seems to have happened\\n\",\n                        \"if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\\n\",\n                        \"https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\",\n                        \"{}\"\n                    ),\n                    super::utils::note_github_pull_request(remote_url).unwrap_or_default()\n                );\n                return Err(anyhow::Error::from(err).context(msg));\n            }\n            _ => None,\n        };\n        if let Some(auth_message) = auth_message {\n            let mut msg = \"failed to authenticate when downloading \\\n                       repository\"\n                .to_string();\n            if let Some(url) = last_url_for_authentication {\n                msg.push_str(\": \");\n                msg.push_str(url.to_str_lossy().as_ref());\n            }\n            msg.push('\\n');\n            msg.push_str(auth_message);\n            msg.push_str(\"\\n\\n\");\n            msg.push_str(\"if the git CLI succeeds then `net.git-fetch-with-cli` may help here\\n\");\n            msg.push_str(\n                \"https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\",\n            );\n            return Err(anyhow::Error::from(err).context(msg));\n        }\n    }\n    Err(err.into())\n}\n\n/// The reason we are opening a git repository.\n///\n/// This can affect the way we open it and the cost associated with it.\npub enum OpenMode {\n    /// We need `git_binary` configuration as well for being able to see credential helpers\n    /// that are configured with the `git` installation itself.\n    /// However, this is slow on windows (~150ms) and most people won't need it as they use the\n    /// standard index which won't ever need authentication, so we only enable this when needed.\n    ForFetch,\n}\n\nimpl OpenMode {\n    /// Sometimes we don't need to pay for figuring out the system's git installation, and this tells\n    /// us if that is the case.\n    pub fn needs_git_binary_config(&self) -> bool {\n        match self {\n            OpenMode::ForFetch => true,\n        }\n    }\n}\n\n/// Produce a repository with everything pre-configured according to `config`. Most notably this includes\n/// transport configuration. Knowing its `purpose` helps to optimize the way we open the repository.\n/// Use `config_overrides` to configure the new repository.\npub fn open_repo(\n    repo_path: &std::path::Path,\n    config_overrides: Vec<BString>,\n    purpose: OpenMode,\n) -> Result<gix::Repository, gix::open::Error> {\n    gix::open_opts(repo_path, {\n        let mut opts = gix::open::Options::default();\n        opts.permissions.config = gix::open::permissions::Config::all();\n        opts.permissions.config.git_binary = purpose.needs_git_binary_config();\n        opts.with(gix::sec::Trust::Full)\n            .config_overrides(config_overrides)\n    })\n}\n\n/// Convert `git` related cargo configuration into the respective `git` configuration which can be\n/// used when opening new repositories.\npub fn cargo_config_to_gitoxide_overrides(gctx: &GlobalContext) -> CargoResult<Vec<BString>> {\n    use gix::config::tree::{Core, Http, Key, gitoxide};\n    let timeout = HttpTimeout::new(gctx)?;\n    let http = gctx.http_config()?;\n\n    let mut values = vec![\n        gitoxide::Http::CONNECT_TIMEOUT.validated_assignment_fmt(&timeout.dur.as_millis())?,\n        Http::LOW_SPEED_LIMIT.validated_assignment_fmt(&timeout.low_speed_limit)?,\n        Http::LOW_SPEED_TIME.validated_assignment_fmt(&timeout.dur.as_secs())?,\n        // Assure we are not depending on committer information when updating refs after cloning.\n        Core::LOG_ALL_REF_UPDATES.validated_assignment_fmt(&false)?,\n    ];\n    if let Some(proxy) = &http.proxy {\n        values.push(Http::PROXY.validated_assignment_fmt(proxy)?);\n    }\n    if let Some(check_revoke) = http.check_revoke {\n        values.push(Http::SCHANNEL_CHECK_REVOKE.validated_assignment_fmt(&check_revoke)?);\n    }\n    if let Some(cainfo) = &http.cainfo {\n        values.push(\n            Http::SSL_CA_INFO.validated_assignment_fmt(&cainfo.resolve_path(gctx).display())?,\n        );\n    }\n\n    values.push(if let Some(user_agent) = &http.user_agent {\n        Http::USER_AGENT.validated_assignment_fmt(user_agent)\n    } else {\n        Http::USER_AGENT.validated_assignment_fmt(&format!(\"cargo {}\", crate::version()))\n    }?);\n    if let Some(ssl_version) = &http.ssl_version {\n        use crate::util::context::SslVersionConfig;\n        match ssl_version {\n            SslVersionConfig::Single(version) => {\n                values.push(Http::SSL_VERSION.validated_assignment_fmt(&version)?);\n            }\n            SslVersionConfig::Range(range) => {\n                values.push(\n                    gitoxide::Http::SSL_VERSION_MIN\n                        .validated_assignment_fmt(&range.min.as_deref().unwrap_or(\"default\"))?,\n                );\n                values.push(\n                    gitoxide::Http::SSL_VERSION_MAX\n                        .validated_assignment_fmt(&range.max.as_deref().unwrap_or(\"default\"))?,\n                );\n            }\n        }\n    } else if cfg!(windows) {\n        // This text is copied from https://github.com/rust-lang/cargo/blob/39c13e67a5962466cc7253d41bc1099bbcb224c3/src/cargo/ops/registry.rs#L658-L674 .\n        // This is a temporary workaround for some bugs with libcurl and\n        // schannel and TLS 1.3.\n        //\n        // Our libcurl on Windows is usually built with schannel.\n        // On Windows 11 (or Windows Server 2022), libcurl recently (late\n        // 2022) gained support for TLS 1.3 with schannel, and it now defaults\n        // to 1.3. Unfortunately there have been some bugs with this.\n        // https://github.com/curl/curl/issues/9431 is the most recent. Once\n        // that has been fixed, and some time has passed where we can be more\n        // confident that the 1.3 support won't cause issues, this can be\n        // removed.\n        //\n        // Windows 10 is unaffected. libcurl does not support TLS 1.3 on\n        // Windows 10. (Windows 10 sorta had support, but it required enabling\n        // an advanced option in the registry which was buggy, and libcurl\n        // does runtime checks to prevent it.)\n        values.push(gitoxide::Http::SSL_VERSION_MIN.validated_assignment_fmt(&\"default\")?);\n        values.push(gitoxide::Http::SSL_VERSION_MAX.validated_assignment_fmt(&\"tlsv1.2\")?);\n    }\n    if let Some(debug) = http.debug {\n        values.push(gitoxide::Http::VERBOSE.validated_assignment_fmt(&debug)?);\n    }\n    if let Some(multiplexing) = http.multiplexing {\n        let http_version = multiplexing.then(|| \"HTTP/2\").unwrap_or(\"HTTP/1.1\");\n        // Note that failing to set the HTTP version in `gix-transport` isn't fatal,\n        // which is why we don't have to try to figure out if HTTP V2 is supported in the\n        // currently linked version (see `try_old_curl!()`)\n        values.push(Http::VERSION.validated_assignment_fmt(&http_version)?);\n    }\n\n    Ok(values)\n}\n\n/// Reinitializes a given Git repository. This is useful when a Git repository\n/// seems corrupted, and we want to start over.\npub fn reinitialize(git_dir: &Path) -> CargoResult<()> {\n    fn init(path: &Path, bare: bool) -> CargoResult<()> {\n        let mut opts = git2::RepositoryInitOptions::new();\n        // Skip anything related to templates, they just call all sorts of issues as\n        // we really don't want to use them yet they insist on being used. See #6240\n        // for an example issue that comes up.\n        opts.external_template(false);\n        opts.bare(bare);\n        git2::Repository::init_opts(&path, &opts)?;\n        Ok(())\n    }\n    // Here we want to drop the current repository object pointed to by `repo`,\n    // so we initialize temporary repository in a sub-folder, blow away the\n    // existing git folder, and then recreate the git repo. Finally we blow away\n    // the `tmp` folder we allocated.\n    debug!(\"reinitializing git repo at {:?}\", git_dir);\n    let tmp = git_dir.join(\"tmp\");\n    let bare = !git_dir.ends_with(\".git\");\n    init(&tmp, false)?;\n    for entry in git_dir.read_dir()? {\n        let entry = entry?;\n        if entry.file_name().to_str() == Some(\"tmp\") {\n            continue;\n        }\n        let path = entry.path();\n        drop(paths::remove_file(&path).or_else(|_| paths::remove_dir_all(&path)));\n    }\n    init(git_dir, bare)?;\n    paths::remove_dir_all(&tmp)?;\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/sources/git/source.rs",
    "content": "//! See [`GitSource`].\n\nuse crate::core::GitReference;\nuse crate::core::SourceId;\nuse crate::core::global_cache_tracker;\nuse crate::core::{Dependency, Package, PackageId};\nuse crate::sources::IndexSummary;\nuse crate::sources::RecursivePathSource;\nuse crate::sources::git::utils::GitDatabase;\nuse crate::sources::git::utils::GitRemote;\nuse crate::sources::git::utils::rev_to_oid;\nuse crate::sources::source::MaybePackage;\nuse crate::sources::source::QueryKind;\nuse crate::sources::source::Source;\nuse crate::util::GlobalContext;\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::errors::CargoResult;\nuse crate::util::hex::short_hash;\nuse crate::util::interning::InternedString;\nuse anyhow::Context as _;\nuse cargo_util::paths::exclude_from_backups_and_indexing;\nuse std::fmt::{self, Debug, Formatter};\nuse std::task::Poll;\nuse tracing::trace;\nuse url::Url;\n\n/// `GitSource` contains one or more packages gathering from a Git repository.\n/// Under the hood it uses [`RecursivePathSource`] to discover packages inside the\n/// repository.\n///\n/// ## Filesystem layout\n///\n/// During a successful `GitSource` download, at least two Git repositories are\n/// created: one is the shared Git database of this remote, and the other is the\n/// Git checkout to a specific revision, which contains the actual files to be\n/// compiled. Multiple checkouts can be cloned from a single Git database.\n///\n/// Those repositories are located at Cargo's Git cache directory\n/// `$CARGO_HOME/git`. The file tree of the cache directory roughly looks like:\n///\n/// ```text\n/// $CARGO_HOME/git/\n/// ├── checkouts/\n/// │  ├── gimli-a0d193bd15a5ed96/\n/// │  │  ├── 8e73ef0/     # Git short ID for a certain revision\n/// │  │  ├── a2a4b78/\n/// │  │  └── e33d1ac/\n/// │  ├── log-c58e1db3de7c154d-shallow/\n/// │  │  └── 11eda98/\n/// └── db/\n///    ├── gimli-a0d193bd15a5ed96/\n///    └── log-c58e1db3de7c154d-shallow/\n/// ```\n///\n/// For more on Git cache directory, see [\"Cargo Home\"] in The Cargo Book.\n///\n/// For more on the directory format `<pkg>-<hash>[-shallow]`, see [`ident`]\n/// and [`ident_shallow`].\n///\n/// ## Locked to a revision\n///\n/// Once a `GitSource` is fetched, it will resolve to a specific commit revision.\n/// This is often mentioned as \"locked revision\" (`locked_rev`) throughout the\n/// codebase. The revision is written into `Cargo.lock`. This is essential since\n/// we want to ensure a package can compiles with the same set of files when\n/// a `Cargo.lock` is present. With the `locked_rev` provided, `GitSource` can\n/// precisely fetch the same revision from the Git repository.\n///\n/// [\"Cargo Home\"]: https://doc.rust-lang.org/nightly/cargo/guide/cargo-home.html#directories\npub struct GitSource<'gctx> {\n    /// The git remote which we're going to fetch from.\n    remote: GitRemote,\n    /// The revision which a git source is locked to.\n    ///\n    /// Expected to always be [`Revision::Locked`] after the Git repository is fetched.\n    locked_rev: Revision,\n    /// The unique identifier of this source.\n    source_id: SourceId,\n    /// The underlying path source to discover packages inside the Git repository.\n    ///\n    /// This gets set to `Some` after the git repo has been checked out\n    /// (automatically handled via [`GitSource::block_until_ready`]).\n    path_source: Option<RecursivePathSource<'gctx>>,\n    /// A short string that uniquely identifies the version of the checkout.\n    ///\n    /// This is typically a 7-character string of the OID hash, automatically\n    /// increasing in size if it is ambiguous.\n    ///\n    /// This is set to `Some` after the git repo has been checked out\n    /// (automatically handled via [`GitSource::block_until_ready`]).\n    short_id: Option<InternedString>,\n    /// The identifier of this source for Cargo's Git cache directory.\n    /// See [`ident`] for more.\n    ident: InternedString,\n    gctx: &'gctx GlobalContext,\n    /// Disables status messages.\n    quiet: bool,\n}\n\nimpl<'gctx> GitSource<'gctx> {\n    /// Creates a git source for the given [`SourceId`].\n    pub fn new(source_id: SourceId, gctx: &'gctx GlobalContext) -> CargoResult<GitSource<'gctx>> {\n        let remote = GitRemote::new(source_id.url());\n        Self::new_with_remote(source_id, remote, gctx)\n    }\n\n    /// Creates a git source for a submodule with an URL that may not be a valid WHATWG URL.\n    ///\n    /// This is needed because [`SourceId`] hasn't yet supported SCP-like URLs.\n    pub(super) fn new_for_submodule(\n        source_id: SourceId,\n        fetch_url: String,\n        gctx: &'gctx GlobalContext,\n    ) -> CargoResult<GitSource<'gctx>> {\n        let remote = GitRemote::new_from_str(fetch_url);\n        Self::new_with_remote(source_id, remote, gctx)\n    }\n\n    fn new_with_remote(\n        source_id: SourceId,\n        remote: GitRemote,\n        gctx: &'gctx GlobalContext,\n    ) -> CargoResult<GitSource<'gctx>> {\n        assert!(source_id.is_git(), \"id is not git, id={}\", source_id);\n\n        // Fallback to git ref from manifest if there is no locked revision.\n        let locked_rev = source_id\n            .precise_git_fragment()\n            .map(|s| Revision::new(s.into()))\n            .unwrap_or_else(|| source_id.git_reference().unwrap().clone().into());\n\n        let ident = ident_shallow(\n            &source_id,\n            gctx.cli_unstable()\n                .git\n                .map_or(false, |features| features.shallow_deps),\n        );\n\n        let source = GitSource {\n            remote,\n            locked_rev,\n            source_id,\n            path_source: None,\n            short_id: None,\n            ident: ident.into(),\n            gctx,\n            quiet: false,\n        };\n\n        Ok(source)\n    }\n\n    /// Gets the remote repository URL.\n    pub fn url(&self) -> &Url {\n        self.source_id.url()\n    }\n\n    /// Returns the packages discovered by this source. It may fetch the Git\n    /// repository as well as walk the filesystem if package information\n    /// haven't yet updated.\n    pub fn read_packages(&mut self) -> CargoResult<Vec<Package>> {\n        if self.path_source.is_none() {\n            self.invalidate_cache();\n            self.block_until_ready()?;\n        }\n        self.path_source.as_mut().unwrap().read_packages()\n    }\n\n    fn mark_used(&self) -> CargoResult<()> {\n        self.gctx\n            .deferred_global_last_use()?\n            .mark_git_checkout_used(global_cache_tracker::GitCheckout {\n                encoded_git_name: self.ident,\n                short_name: self.short_id.expect(\"update before download\"),\n                size: None,\n            });\n        Ok(())\n    }\n\n    /// Fetch and return a [`GitDatabase`] with the resolved revision\n    /// for this source,\n    ///\n    /// This won't fetch anything if the required revision is\n    /// already available locally.\n    pub(crate) fn fetch_db(&self, is_submodule: bool) -> CargoResult<(GitDatabase, git2::Oid)> {\n        let db_path = self.gctx.git_db_path().join(&self.ident);\n        let db_path = db_path.into_path_unlocked();\n\n        let db = self.remote.db_at(&db_path).ok();\n\n        let (db, actual_rev) = match (&self.locked_rev, db) {\n            // If we have a locked revision, and we have a preexisting database\n            // which has that revision, then no update needs to happen.\n            (Revision::Locked(oid), Some(db)) if db.contains(*oid) => (db, *oid),\n\n            // If we're in offline mode, we're not locked, and we have a\n            // database, then try to resolve our reference with the preexisting\n            // repository.\n            (Revision::Deferred(git_ref), Some(db)) if !self.gctx.network_allowed() => {\n                let offline_flag = self\n                    .gctx\n                    .offline_flag()\n                    .expect(\"always present when `!network_allowed`\");\n                let rev = db.resolve(&git_ref).with_context(|| {\n                    format!(\n                        \"failed to lookup reference in preexisting repository, and \\\n                         can't check for updates in offline mode ({offline_flag})\"\n                    )\n                })?;\n                (db, rev)\n            }\n\n            // ... otherwise we use this state to update the git database. Note\n            // that we still check for being offline here, for example in the\n            // situation that we have a locked revision but the database\n            // doesn't have it.\n            (locked_rev, db) => {\n                if let Some(offline_flag) = self.gctx.offline_flag() {\n                    anyhow::bail!(\n                        \"can't checkout from '{}': you are in the offline mode ({offline_flag})\",\n                        self.remote.url()\n                    );\n                }\n\n                if !self.quiet {\n                    let scope = if is_submodule {\n                        \"submodule\"\n                    } else {\n                        \"repository\"\n                    };\n                    self.gctx\n                        .shell()\n                        .status(\"Updating\", format!(\"git {scope} `{}`\", self.remote.url()))?;\n                }\n\n                trace!(\"updating git source `{:?}`\", self.remote);\n\n                let locked_rev = locked_rev.clone().into();\n                let manifest_reference = self.source_id.git_reference().unwrap();\n                self.remote\n                    .checkout(&db_path, db, manifest_reference, &locked_rev, self.gctx)?\n            }\n        };\n        Ok((db, actual_rev))\n    }\n}\n\n/// Indicates a [Git revision] that might be locked or deferred to be resolved.\n///\n/// [Git revision]: https://git-scm.com/docs/revisions\n#[derive(Clone, Debug)]\nenum Revision {\n    /// A [Git reference] that would trigger extra fetches when being resolved.\n    ///\n    /// [Git reference]: https://git-scm.com/book/en/v2/Git-Internals-Git-References\n    Deferred(GitReference),\n    /// A locked revision of the actual Git commit object ID.\n    Locked(git2::Oid),\n}\n\nimpl Revision {\n    fn new(rev: &str) -> Revision {\n        match rev_to_oid(rev) {\n            Some(oid) => Revision::Locked(oid),\n            None => Revision::Deferred(GitReference::Rev(rev.to_string())),\n        }\n    }\n}\n\nimpl From<GitReference> for Revision {\n    fn from(value: GitReference) -> Self {\n        Revision::Deferred(value)\n    }\n}\n\nimpl From<Revision> for GitReference {\n    fn from(value: Revision) -> Self {\n        match value {\n            Revision::Deferred(git_ref) => git_ref,\n            Revision::Locked(oid) => GitReference::Rev(oid.to_string()),\n        }\n    }\n}\n\n/// Create an identifier from a URL,\n/// essentially turning `proto://host/path/repo` into `repo-<hash-of-url>`.\nfn ident(id: &SourceId) -> String {\n    let ident = id\n        .canonical_url()\n        .raw_canonicalized_url()\n        .path_segments()\n        .and_then(|s| s.rev().next())\n        .unwrap_or(\"\");\n\n    let ident = if ident.is_empty() { \"_empty\" } else { ident };\n\n    format!(\"{}-{}\", ident, short_hash(id.canonical_url()))\n}\n\n/// Like [`ident()`], but appends `-shallow` to it, turning\n/// `proto://host/path/repo` into `repo-<hash-of-url>-shallow`.\n///\n/// It's important to separate shallow from non-shallow clones for reasons of\n/// backwards compatibility --- older cargo's aren't necessarily handling\n/// shallow clones correctly.\nfn ident_shallow(id: &SourceId, is_shallow: bool) -> String {\n    let mut ident = ident(id);\n    if is_shallow {\n        ident.push_str(\"-shallow\");\n    }\n    ident\n}\n\nimpl<'gctx> Debug for GitSource<'gctx> {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        write!(f, \"git repo at {}\", self.source_id.url())?;\n        match &self.locked_rev {\n            Revision::Deferred(git_ref) => match git_ref.pretty_ref(true) {\n                Some(s) => write!(f, \" ({})\", s),\n                None => Ok(()),\n            },\n            Revision::Locked(oid) => write!(f, \" ({oid})\"),\n        }\n    }\n}\n\nimpl<'gctx> Source for GitSource<'gctx> {\n    fn query(\n        &mut self,\n        dep: &Dependency,\n        kind: QueryKind,\n        f: &mut dyn FnMut(IndexSummary),\n    ) -> Poll<CargoResult<()>> {\n        if let Some(src) = self.path_source.as_mut() {\n            src.query(dep, kind, f)\n        } else {\n            Poll::Pending\n        }\n    }\n\n    fn supports_checksums(&self) -> bool {\n        false\n    }\n\n    fn requires_precise(&self) -> bool {\n        true\n    }\n\n    fn source_id(&self) -> SourceId {\n        self.source_id\n    }\n\n    fn block_until_ready(&mut self) -> CargoResult<()> {\n        if self.path_source.is_some() {\n            self.mark_used()?;\n            return Ok(());\n        }\n\n        let git_fs = self.gctx.git_path();\n        // Ignore errors creating it, in case this is a read-only filesystem:\n        // perhaps the later operations can succeed anyhow.\n        let _ = git_fs.create_dir();\n        let git_path = self\n            .gctx\n            .assert_package_cache_locked(CacheLockMode::DownloadExclusive, &git_fs);\n\n        // Before getting a checkout, make sure that `<cargo_home>/git` is\n        // marked as excluded from indexing and backups. Older versions of Cargo\n        // didn't do this, so we do it here regardless of whether `<cargo_home>`\n        // exists.\n        //\n        // This does not use `create_dir_all_excluded_from_backups_atomic` for\n        // the same reason: we want to exclude it even if the directory already\n        // exists.\n        exclude_from_backups_and_indexing(&git_path);\n\n        let (db, actual_rev) = self.fetch_db(false)?;\n\n        // Don’t use the full hash, in order to contribute less to reaching the\n        // path length limit on Windows. See\n        // <https://github.com/servo/servo/pull/14397>.\n        let short_id = db.to_short_id(actual_rev)?;\n\n        // Check out `actual_rev` from the database to a scoped location on the\n        // filesystem. This will use hard links and such to ideally make the\n        // checkout operation here pretty fast.\n        let checkout_path = self\n            .gctx\n            .git_checkouts_path()\n            .join(&self.ident)\n            .join(short_id.as_str());\n        let checkout_path = checkout_path.into_path_unlocked();\n        db.copy_to(actual_rev, &checkout_path, self.gctx, self.quiet)?;\n\n        let source_id = self\n            .source_id\n            .with_git_precise(Some(actual_rev.to_string()));\n        let path_source = RecursivePathSource::new(&checkout_path, source_id, self.gctx);\n\n        self.path_source = Some(path_source);\n        self.short_id = Some(short_id.as_str().into());\n        self.locked_rev = Revision::Locked(actual_rev);\n        self.path_source.as_mut().unwrap().load()?;\n\n        self.mark_used()?;\n        Ok(())\n    }\n\n    fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {\n        trace!(\n            \"getting packages for package ID `{}` from `{:?}`\",\n            id, self.remote\n        );\n        self.mark_used()?;\n        self.path_source\n            .as_mut()\n            .expect(\"BUG: `update()` must be called before `get()`\")\n            .download(id)\n    }\n\n    fn finish_download(&mut self, _id: PackageId, _data: Vec<u8>) -> CargoResult<Package> {\n        panic!(\"no download should have started\")\n    }\n\n    fn fingerprint(&self, _pkg: &Package) -> CargoResult<String> {\n        match &self.locked_rev {\n            Revision::Locked(oid) => Ok(oid.to_string()),\n            _ => unreachable!(\"locked_rev must be resolved when computing fingerprint\"),\n        }\n    }\n\n    fn describe(&self) -> String {\n        format!(\"Git repository {}\", self.source_id)\n    }\n\n    fn add_to_yanked_whitelist(&mut self, _pkgs: &[PackageId]) {}\n\n    fn is_yanked(&mut self, _pkg: PackageId) -> Poll<CargoResult<bool>> {\n        Poll::Ready(Ok(false))\n    }\n\n    fn invalidate_cache(&mut self) {}\n\n    fn set_quiet(&mut self, quiet: bool) {\n        self.quiet = quiet;\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::ident;\n    use crate::core::{GitReference, SourceId};\n    use crate::util::IntoUrl;\n\n    #[test]\n    pub fn test_url_to_path_ident_with_path() {\n        let ident = ident(&src(\"https://github.com/carlhuda/cargo\"));\n        assert!(ident.starts_with(\"cargo-\"));\n    }\n\n    #[test]\n    pub fn test_url_to_path_ident_without_path() {\n        let ident = ident(&src(\"https://github.com\"));\n        assert!(ident.starts_with(\"_empty-\"));\n    }\n\n    #[test]\n    fn test_canonicalize_idents_by_stripping_trailing_url_slash() {\n        let ident1 = ident(&src(\"https://github.com/PistonDevelopers/piston/\"));\n        let ident2 = ident(&src(\"https://github.com/PistonDevelopers/piston\"));\n        assert_eq!(ident1, ident2);\n    }\n\n    #[test]\n    fn test_canonicalize_idents_by_lowercasing_github_urls() {\n        let ident1 = ident(&src(\"https://github.com/PistonDevelopers/piston\"));\n        let ident2 = ident(&src(\"https://github.com/pistondevelopers/piston\"));\n        assert_eq!(ident1, ident2);\n    }\n\n    #[test]\n    fn test_canonicalize_idents_by_stripping_dot_git() {\n        let ident1 = ident(&src(\"https://github.com/PistonDevelopers/piston\"));\n        let ident2 = ident(&src(\"https://github.com/PistonDevelopers/piston.git\"));\n        assert_eq!(ident1, ident2);\n    }\n\n    #[test]\n    fn test_canonicalize_idents_different_protocols() {\n        let ident1 = ident(&src(\"https://github.com/PistonDevelopers/piston\"));\n        let ident2 = ident(&src(\"git://github.com/PistonDevelopers/piston\"));\n        assert_eq!(ident1, ident2);\n    }\n\n    fn src(s: &str) -> SourceId {\n        SourceId::for_git(&s.into_url().unwrap(), GitReference::DefaultBranch).unwrap()\n    }\n}\n"
  },
  {
    "path": "src/cargo/sources/git/utils.rs",
    "content": "//! Utilities for handling git repositories, mainly around\n//! authentication/cloning.\n\nuse crate::core::{GitReference, SourceId, Verbosity};\nuse crate::sources::git::fetch::RemoteKind;\nuse crate::sources::git::oxide;\nuse crate::sources::git::oxide::cargo_config_to_gitoxide_overrides;\nuse crate::sources::git::source::GitSource;\nuse crate::sources::source::Source as _;\nuse crate::util::HumanBytes;\nuse crate::util::errors::{CargoResult, GitCliError};\nuse crate::util::{GlobalContext, IntoUrl, MetricsCounter, Progress, network};\n\nuse anyhow::{Context as _, anyhow};\nuse cargo_util::{ProcessBuilder, paths};\nuse curl::easy::List;\nuse git2::{ErrorClass, ObjectType, Oid};\nuse tracing::{debug, info};\nuse url::Url;\n\nuse std::borrow::Cow;\nuse std::path::{Path, PathBuf};\nuse std::process::Command;\nuse std::str;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::time::{Duration, Instant};\n\n/// A file indicates that if present, `git reset` has been done and a repo\n/// checkout is ready to go. See [`GitCheckout::reset`] for why we need this.\nconst CHECKOUT_READY_LOCK: &str = \".cargo-ok\";\n\n/// A short abbreviated OID.\n///\n/// Exists for avoiding extra allocations in [`GitDatabase::to_short_id`].\npub struct GitShortID(git2::Buf);\n\nimpl GitShortID {\n    /// Views the short ID as a `str`.\n    pub fn as_str(&self) -> &str {\n        self.0.as_str().unwrap()\n    }\n}\n\n/// A remote repository. It gets cloned into a local [`GitDatabase`].\n#[derive(PartialEq, Clone, Debug)]\npub struct GitRemote {\n    /// URL to a remote repository.\n    ///\n    /// This may differ from the [`SourceId`] URL when the original URL\n    /// can't be represented as a WHATWG [`Url`], for example SCP-like URLs.\n    /// See <https://github.com/rust-lang/cargo/issues/16740>.\n    url: String,\n}\n\n/// A local clone of a remote repository's database. Multiple [`GitCheckout`]s\n/// can be cloned from a single [`GitDatabase`].\npub struct GitDatabase {\n    /// The remote repository where this database is fetched from.\n    remote: GitRemote,\n    /// Path to the root of the underlying Git repository on the local filesystem.\n    path: PathBuf,\n    /// Underlying Git repository instance for this database.\n    repo: git2::Repository,\n}\n\n/// A local checkout of a particular revision from a [`GitDatabase`].\npub struct GitCheckout<'a> {\n    /// The git database where this checkout is cloned from.\n    database: &'a GitDatabase,\n    /// Path to the root of the underlying Git repository on the local filesystem.\n    path: PathBuf,\n    /// The git revision this checkout is for.\n    revision: git2::Oid,\n    /// Underlying Git repository instance for this checkout.\n    repo: git2::Repository,\n}\n\nimpl GitRemote {\n    /// Creates an instance for a remote repository URL.\n    pub fn new(url: &Url) -> GitRemote {\n        GitRemote {\n            url: url.as_str().to_owned(),\n        }\n    }\n\n    /// Creates an instance with an URL that may not be a valid WHATWG URL.\n    ///\n    /// This is needed because [`SourceId`] hasn't yet supported SCP-like URLs.\n    pub(super) fn new_from_str(url: String) -> GitRemote {\n        GitRemote { url }\n    }\n\n    /// Gets the remote repository URL.\n    pub fn url(&self) -> &str {\n        &self.url\n    }\n\n    /// Fetches and checkouts to a reference or a revision from this remote\n    /// into a local path.\n    ///\n    /// This ensures that it gets the up-to-date commit when a named reference\n    /// is given (tag, branch, refs/*). Thus, network connection is involved.\n    ///\n    /// If we have a previous instance of [`GitDatabase`] then fetch into that\n    /// if we can. If that can successfully load our revision then we've\n    /// populated the database with the latest version of `reference`, so\n    /// return that database and the rev we resolve to.\n    pub fn checkout(\n        &self,\n        into: &Path,\n        db: Option<GitDatabase>,\n        manifest_reference: &GitReference,\n        reference: &GitReference,\n        gctx: &GlobalContext,\n    ) -> CargoResult<(GitDatabase, git2::Oid)> {\n        if let Some(mut db) = db {\n            fetch(\n                &mut db.repo,\n                self.url(),\n                manifest_reference,\n                reference,\n                gctx,\n                RemoteKind::GitDependency,\n            )\n            .with_context(|| format!(\"failed to fetch into: {}\", into.display()))?;\n\n            if let Some(rev) = resolve_ref(reference, &db.repo).ok() {\n                return Ok((db, rev));\n            }\n        }\n\n        // Otherwise start from scratch to handle corrupt git repositories.\n        // After our fetch (which is interpreted as a clone now) we do the same\n        // resolution to figure out what we cloned.\n        if into.exists() {\n            paths::remove_dir_all(into)?;\n        }\n        paths::create_dir_all(into)?;\n        let mut repo = init(into, true)?;\n        fetch(\n            &mut repo,\n            self.url(),\n            manifest_reference,\n            reference,\n            gctx,\n            RemoteKind::GitDependency,\n        )\n        .with_context(|| format!(\"failed to clone into: {}\", into.display()))?;\n        let rev = resolve_ref(reference, &repo)?;\n\n        Ok((\n            GitDatabase {\n                remote: self.clone(),\n                path: into.to_path_buf(),\n                repo,\n            },\n            rev,\n        ))\n    }\n\n    /// Creates a [`GitDatabase`] of this remote at `db_path`.\n    pub fn db_at(&self, db_path: &Path) -> CargoResult<GitDatabase> {\n        let repo = git2::Repository::open(db_path)?;\n        Ok(GitDatabase {\n            remote: self.clone(),\n            path: db_path.to_path_buf(),\n            repo,\n        })\n    }\n}\n\nimpl GitDatabase {\n    /// Checkouts to a revision at `dest`ination from this database.\n    #[tracing::instrument(skip(self, gctx))]\n    pub fn copy_to(\n        &self,\n        rev: git2::Oid,\n        dest: &Path,\n        gctx: &GlobalContext,\n        quiet: bool,\n    ) -> CargoResult<GitCheckout<'_>> {\n        // If the existing checkout exists, and it is fresh, use it.\n        // A non-fresh checkout can happen if the checkout operation was\n        // interrupted. In that case, the checkout gets deleted and a new\n        // clone is created.\n        let checkout = match git2::Repository::open(dest)\n            .ok()\n            .map(|repo| GitCheckout::new(self, rev, repo))\n            .filter(|co| co.is_fresh())\n        {\n            Some(co) => co,\n            None => {\n                let (checkout, guard) = GitCheckout::clone_into(dest, self, rev, gctx)?;\n                checkout.update_submodules(gctx, quiet)?;\n                guard.mark_ok()?;\n                checkout\n            }\n        };\n\n        Ok(checkout)\n    }\n\n    /// Get a short OID for a `revision`, usually 7 chars or more if ambiguous.\n    pub fn to_short_id(&self, revision: git2::Oid) -> CargoResult<GitShortID> {\n        let obj = self.repo.find_object(revision, None)?;\n        Ok(GitShortID(obj.short_id()?))\n    }\n\n    /// Checks if the database contains the object of this `oid`..\n    pub fn contains(&self, oid: git2::Oid) -> bool {\n        self.repo.revparse_single(&oid.to_string()).is_ok()\n    }\n\n    /// [`resolve_ref`]s this reference with this database.\n    pub fn resolve(&self, r: &GitReference) -> CargoResult<git2::Oid> {\n        resolve_ref(r, &self.repo)\n    }\n}\n\n/// Resolves [`GitReference`] to an object ID with objects the `repo` currently has.\npub fn resolve_ref(gitref: &GitReference, repo: &git2::Repository) -> CargoResult<git2::Oid> {\n    let id = match gitref {\n        // Note that we resolve the named tag here in sync with where it's\n        // fetched into via `fetch` below.\n        GitReference::Tag(s) => (|| -> CargoResult<git2::Oid> {\n            let refname = format!(\"refs/remotes/origin/tags/{}\", s);\n            let id = repo.refname_to_id(&refname)?;\n            let obj = repo.find_object(id, None)?;\n            let obj = obj.peel(ObjectType::Commit)?;\n            Ok(obj.id())\n        })()\n        .with_context(|| format!(\"failed to find tag `{}`\", s))?,\n\n        // Resolve the remote name since that's all we're configuring in\n        // `fetch` below.\n        GitReference::Branch(s) => {\n            let name = format!(\"origin/{}\", s);\n            let b = repo\n                .find_branch(&name, git2::BranchType::Remote)\n                .with_context(|| format!(\"failed to find branch `{}`\", s))?;\n            b.get()\n                .target()\n                .ok_or_else(|| anyhow::format_err!(\"branch `{}` did not have a target\", s))?\n        }\n\n        // We'll be using the HEAD commit\n        GitReference::DefaultBranch => {\n            let head_id = repo.refname_to_id(\"refs/remotes/origin/HEAD\")?;\n            let head = repo.find_object(head_id, None)?;\n            head.peel(ObjectType::Commit)?.id()\n        }\n\n        GitReference::Rev(s) => {\n            let obj = repo.revparse_single(s)?;\n            match obj.as_tag() {\n                Some(tag) => tag.target_id(),\n                None => obj.id(),\n            }\n        }\n    };\n    Ok(id)\n}\n\nimpl<'a> GitCheckout<'a> {\n    /// Creates an instance of [`GitCheckout`]. This doesn't imply the checkout\n    /// is done. Use [`GitCheckout::is_fresh`] to check.\n    ///\n    /// * The `database` is where this checkout is from.\n    /// * The `repo` will be the checked out Git repository.\n    fn new(\n        database: &'a GitDatabase,\n        revision: git2::Oid,\n        repo: git2::Repository,\n    ) -> GitCheckout<'a> {\n        let path = repo.workdir().unwrap_or_else(|| repo.path());\n        GitCheckout {\n            path: path.to_path_buf(),\n            database,\n            revision,\n            repo,\n        }\n    }\n\n    /// Gets the remote repository URL.\n    fn remote_url(&self) -> &str {\n        self.database.remote.url()\n    }\n\n    /// Clone a repo for a `revision` into a local path from a `database`.\n    /// This is a filesystem-to-filesystem clone.\n    fn clone_into(\n        into: &Path,\n        database: &'a GitDatabase,\n        revision: git2::Oid,\n        gctx: &GlobalContext,\n    ) -> CargoResult<(GitCheckout<'a>, CheckoutGuard)> {\n        let dirname = into.parent().unwrap();\n        paths::create_dir_all(&dirname)?;\n        if into.exists() {\n            paths::remove_dir_all(into)?;\n        }\n\n        // we're doing a local filesystem-to-filesystem clone so there should\n        // be no need to respect global configuration options, so pass in\n        // an empty instance of `git2::Config` below.\n        let git_config = git2::Config::new()?;\n\n        // Clone the repository, but make sure we use the \"local\" option in\n        // libgit2 which will attempt to use hardlinks to set up the database.\n        // This should speed up the clone operation quite a bit if it works.\n        //\n        // Note that we still use the same fetch options because while we don't\n        // need authentication information we may want progress bars and such.\n        let url = database.path.into_url()?;\n        let mut repo = None;\n        with_fetch_options(&git_config, url.as_str(), gctx, &mut |fopts| {\n            let mut checkout = git2::build::CheckoutBuilder::new();\n            checkout.dry_run(); // we'll do this below during a `reset`\n\n            let r = git2::build::RepoBuilder::new()\n                // use hard links and/or copy the database, we're doing a\n                // filesystem clone so this'll speed things up quite a bit.\n                .clone_local(git2::build::CloneLocal::Local)\n                .with_checkout(checkout)\n                .fetch_options(fopts)\n                .clone(url.as_str(), into)?;\n            // `git2` doesn't seem to handle shallow repos correctly when doing\n            // a local clone. Fortunately all that's needed is the copy of the\n            // one file that defines the shallow boundary, the commits which\n            // have their parents omitted as part of the shallow clone.\n            //\n            // TODO(git2): remove this when git2 supports shallow clone correctly\n            if database.repo.is_shallow() {\n                std::fs::copy(\n                    database.repo.path().join(\"shallow\"),\n                    r.path().join(\"shallow\"),\n                )?;\n            }\n            repo = Some(r);\n            Ok(())\n        })?;\n        let repo = repo.unwrap();\n\n        let checkout = GitCheckout::new(database, revision, repo);\n        let guard = checkout.reset(gctx)?;\n        Ok((checkout, guard))\n    }\n\n    /// Checks if the `HEAD` of this checkout points to the expected revision.\n    fn is_fresh(&self) -> bool {\n        match self.repo.revparse_single(\"HEAD\") {\n            Ok(ref head) if head.id() == self.revision => {\n                // See comments in reset() for why we check this\n                self.path.join(CHECKOUT_READY_LOCK).exists()\n            }\n            _ => false,\n        }\n    }\n\n    /// Similar to [`reset()`]. This roughly performs `git reset --hard` to the\n    /// revision of this checkout, with additional interrupt protection by a\n    /// dummy file [`CHECKOUT_READY_LOCK`].\n    ///\n    /// If we're interrupted while performing a `git reset` (e.g., we die\n    /// because of a signal) Cargo needs to be sure to try to check out this\n    /// repo again on the next go-round.\n    ///\n    /// To enable this we have a dummy file in our checkout, [`.cargo-ok`],\n    /// which if present means that the repo has been successfully reset and is\n    /// ready to go. Hence if we start to do a reset, we make sure this file\n    /// *doesn't* exist. The caller of [`reset`] has an option to perform additional operations\n    /// (e.g. submodule update) before marking the check-out as ready.\n    ///\n    /// [`.cargo-ok`]: CHECKOUT_READY_LOCK\n    fn reset(&self, gctx: &GlobalContext) -> CargoResult<CheckoutGuard> {\n        let guard = CheckoutGuard::guard(&self.path);\n        info!(\"reset {} to {}\", self.repo.path().display(), self.revision);\n\n        // Ensure libgit2 won't mess with newlines when we vendor.\n        if let Ok(mut git_config) = self.repo.config() {\n            git_config.set_bool(\"core.autocrlf\", false)?;\n        }\n\n        let object = self.repo.find_object(self.revision, None)?;\n        reset(&self.repo, &object, gctx)?;\n\n        Ok(guard)\n    }\n\n    /// Like `git submodule update --recursive` but for this git checkout.\n    ///\n    /// This function respects `submodule.<name>.update = none`[^1] git config.\n    /// Submodules set to `none` won't be fetched.\n    ///\n    /// [^1]: <https://git-scm.com/docs/git-submodule#Documentation/git-submodule.txt-none>\n    fn update_submodules(&self, gctx: &GlobalContext, quiet: bool) -> CargoResult<()> {\n        return update_submodules(&self.repo, gctx, quiet, self.remote_url());\n\n        /// Recursive helper for [`GitCheckout::update_submodules`].\n        fn update_submodules(\n            repo: &git2::Repository,\n            gctx: &GlobalContext,\n            quiet: bool,\n            parent_remote_url: &str,\n        ) -> CargoResult<()> {\n            debug!(\"update submodules for: {:?}\", repo.workdir().unwrap());\n\n            for mut child in repo.submodules()? {\n                update_submodule(repo, &mut child, gctx, quiet, parent_remote_url).with_context(\n                    || {\n                        format!(\n                            \"failed to update submodule `{}`\",\n                            child.name().unwrap_or(\"\")\n                        )\n                    },\n                )?;\n            }\n            Ok(())\n        }\n\n        /// Update a single Git submodule, and recurse into its submodules.\n        fn update_submodule(\n            parent: &git2::Repository,\n            child: &mut git2::Submodule<'_>,\n            gctx: &GlobalContext,\n            quiet: bool,\n            parent_remote_url: &str,\n        ) -> CargoResult<()> {\n            child.init(false)?;\n\n            let child_url_str = child.url().ok_or_else(|| {\n                anyhow::format_err!(\"non-utf8 url for submodule {:?}?\", child.path())\n            })?;\n\n            // Skip the submodule if the config says not to update it.\n            if child.update_strategy() == git2::SubmoduleUpdate::None {\n                gctx.shell().status(\n                    \"Skipping\",\n                    format!(\n                        \"git submodule `{}` due to update strategy in .gitmodules\",\n                        child_url_str\n                    ),\n                )?;\n                return Ok(());\n            }\n\n            let child_remote_url = absolute_submodule_url(parent_remote_url, child_url_str)?;\n\n            // A submodule which is listed in .gitmodules but not actually\n            // checked out will not have a head id, so we should ignore it.\n            let Some(head) = child.head_id() else {\n                return Ok(());\n            };\n\n            // If the submodule hasn't been checked out yet, we need to\n            // clone it. If it has been checked out and the head is the same\n            // as the submodule's head, then we can skip an update and keep\n            // recursing.\n            let head_and_repo = child.open().and_then(|repo| {\n                let target = repo.head()?.target();\n                Ok((target, repo))\n            });\n            let repo = match head_and_repo {\n                Ok((head, repo)) => {\n                    if child.head_id() == head {\n                        return update_submodules(&repo, gctx, quiet, &child_remote_url);\n                    }\n                    repo\n                }\n                Err(..) => {\n                    let path = parent.workdir().unwrap().join(child.path());\n                    let _ = paths::remove_dir_all(&path);\n                    init(&path, false)?\n                }\n            };\n            // Fetch submodule database and checkout to target revision\n            let reference = GitReference::Rev(head.to_string());\n\n            // SCP-like URL is not a WHATWG Standard URL.\n            // `url` crate can't parse SCP-like URLs.\n            // We convert to `ssh://` for SourceId,\n            // but preserve the original URL for fetch to maintain correct semantics\n            // See <https://github.com/rust-lang/cargo/issues/16740>\n            let (source_url, fetch_url) = match child_remote_url.as_ref().into_url() {\n                Ok(url) => (url, None),\n                Err(_) => {\n                    let ssh_url = scp_to_ssh(&child_remote_url)\n                        .ok_or_else(|| anyhow::format_err!(\"invalid url `{child_remote_url}`\"))?\n                        .as_str()\n                        .into_url()?;\n                    (ssh_url, Some(child_remote_url.into_owned()))\n                }\n            };\n\n            // GitSource created from SourceId without git precise will result to\n            // locked_rev being Deferred and fetch_db always try to fetch if online\n            let source_id =\n                SourceId::for_git(&source_url, reference)?.with_git_precise(Some(head.to_string()));\n\n            let mut source = match &fetch_url {\n                Some(url) => GitSource::new_for_submodule(source_id, url.to_owned(), gctx)?,\n                None => GitSource::new(source_id, gctx)?,\n            };\n            source.set_quiet(quiet);\n\n            let (db, actual_rev) = source.fetch_db(true).with_context(|| {\n                let name = child.name().unwrap_or(\"\");\n                let url = fetch_url.unwrap_or_else(|| source_url.to_string());\n                format!(\"failed to fetch submodule `{name}` from {url}\")\n            })?;\n            db.copy_to(actual_rev, repo.path(), gctx, quiet)?;\n            Ok(())\n        }\n    }\n}\n\n/// See [`GitCheckout::reset`] for rationale on this type.\n#[must_use]\nstruct CheckoutGuard {\n    ok_file: PathBuf,\n}\n\nimpl CheckoutGuard {\n    fn guard(path: &Path) -> Self {\n        let ok_file = path.join(CHECKOUT_READY_LOCK);\n        let _ = paths::remove_file(&ok_file);\n        Self { ok_file }\n    }\n\n    fn mark_ok(self) -> CargoResult<()> {\n        let _ = paths::create(self.ok_file)?;\n        Ok(())\n    }\n}\n\n/// Constructs an absolute URL for a child submodule URL with its parent base URL.\n///\n/// Git only assumes a submodule URL is a relative path if it starts with `./`\n/// or `../` [^1]. To fetch the correct repo, we need to construct an absolute\n/// submodule URL.\n///\n/// At this moment it comes with some limitations:\n///\n/// * GitHub doesn't accept non-normalized URLs with relative paths.\n///   (`ssh://git@github.com/rust-lang/cargo.git/relative/..` is invalid)\n/// * `url` crate cannot parse SCP-like URLs.\n///   (`git@github.com:rust-lang/cargo.git` is not a valid WHATWG URL)\n///\n/// To overcome these, this patch always tries [`Url::parse`] first to normalize\n/// the path. If it couldn't, append the relative path and/or convert SCP-like URLs\n/// to ssh:// format as the last resorts and pray the remote git service supports\n/// non-normalized URLs.\n///\n/// See also rust-lang/cargo#12404 and rust-lang/cargo#12295.\n///\n/// [^1]: <https://git-scm.com/docs/git-submodule>\nfn absolute_submodule_url<'s>(base_url: &str, submodule_url: &'s str) -> CargoResult<Cow<'s, str>> {\n    let absolute_url = if [\"./\", \"../\"].iter().any(|p| submodule_url.starts_with(p)) {\n        match Url::parse(base_url) {\n            Ok(mut base_url) => {\n                let path = base_url.path();\n                if !path.ends_with('/') {\n                    base_url.set_path(&format!(\"{path}/\"));\n                }\n                let absolute_url = base_url.join(submodule_url).with_context(|| {\n                    format!(\n                        \"failed to parse relative child submodule url `{submodule_url}` \\\n                        using parent base url `{base_url}`\"\n                    )\n                })?;\n                Cow::from(absolute_url.to_string())\n            }\n            Err(_) => {\n                let mut absolute_url = base_url.to_string();\n                if !absolute_url.ends_with('/') {\n                    absolute_url.push('/');\n                }\n                absolute_url.push_str(submodule_url);\n                Cow::from(absolute_url)\n            }\n        }\n    } else {\n        Cow::from(submodule_url)\n    };\n\n    Ok(absolute_url)\n}\n\n/// Converts an SCP-like URL to `ssh://` format.\nfn scp_to_ssh(url: &str) -> Option<String> {\n    let mut gix_url = gix::url::parse(gix::bstr::BStr::new(url.as_bytes())).ok()?;\n    if gix_url.serialize_alternative_form && gix_url.scheme == gix::url::Scheme::Ssh {\n        gix_url.serialize_alternative_form = false;\n        Some(gix_url.to_bstring().to_string())\n    } else {\n        None\n    }\n}\n\n/// Prepare the authentication callbacks for cloning a git repository.\n///\n/// The main purpose of this function is to construct the \"authentication\n/// callback\" which is used to clone a repository. This callback will attempt to\n/// find the right authentication on the system (without user input) and will\n/// guide libgit2 in doing so.\n///\n/// The callback is provided `allowed` types of credentials, and we try to do as\n/// much as possible based on that:\n///\n/// * Prioritize SSH keys from the local ssh agent as they're likely the most\n///   reliable. The username here is prioritized from the credential\n///   callback, then from whatever is configured in git itself, and finally\n///   we fall back to the generic user of `git`.\n///\n/// * If a username/password is allowed, then we fallback to git2-rs's\n///   implementation of the credential helper. This is what is configured\n///   with `credential.helper` in git, and is the interface for the macOS\n///   keychain, for example.\n///\n/// * After the above two have failed, we just kinda grapple attempting to\n///   return *something*.\n///\n/// If any form of authentication fails, libgit2 will repeatedly ask us for\n/// credentials until we give it a reason to not do so. To ensure we don't\n/// just sit here looping forever we keep track of authentications we've\n/// attempted and we don't try the same ones again.\nfn with_authentication<T, F>(\n    gctx: &GlobalContext,\n    url: &str,\n    cfg: &git2::Config,\n    mut f: F,\n) -> CargoResult<T>\nwhere\n    F: FnMut(&mut git2::Credentials<'_>) -> CargoResult<T>,\n{\n    let mut cred_helper = git2::CredentialHelper::new(url);\n    cred_helper.config(cfg);\n\n    let mut ssh_username_requested = false;\n    let mut cred_helper_bad = None;\n    let mut ssh_agent_attempts = Vec::new();\n    let mut any_attempts = false;\n    let mut tried_sshkey = false;\n    let mut url_attempt = None;\n\n    let orig_url = url;\n    let mut res = f(&mut |url, username, allowed| {\n        any_attempts = true;\n        if url != orig_url {\n            url_attempt = Some(url.to_string());\n        }\n        // libgit2's \"USERNAME\" authentication actually means that it's just\n        // asking us for a username to keep going. This is currently only really\n        // used for SSH authentication and isn't really an authentication type.\n        // The logic currently looks like:\n        //\n        //      let user = ...;\n        //      if (user.is_null())\n        //          user = callback(USERNAME, null, ...);\n        //\n        //      callback(SSH_KEY, user, ...)\n        //\n        // So if we're being called here then we know that (a) we're using ssh\n        // authentication and (b) no username was specified in the URL that\n        // we're trying to clone. We need to guess an appropriate username here,\n        // but that may involve a few attempts. Unfortunately we can't switch\n        // usernames during one authentication session with libgit2, so to\n        // handle this we bail out of this authentication session after setting\n        // the flag `ssh_username_requested`, and then we handle this below.\n        if allowed.contains(git2::CredentialType::USERNAME) {\n            debug_assert!(username.is_none());\n            ssh_username_requested = true;\n            return Err(git2::Error::from_str(\"gonna try usernames later\"));\n        }\n\n        // An \"SSH_KEY\" authentication indicates that we need some sort of SSH\n        // authentication. This can currently either come from the ssh-agent\n        // process or from a raw in-memory SSH key. Cargo only supports using\n        // ssh-agent currently.\n        //\n        // If we get called with this then the only way that should be possible\n        // is if a username is specified in the URL itself (e.g., `username` is\n        // Some), hence the unwrap() here. We try custom usernames down below.\n        if allowed.contains(git2::CredentialType::SSH_KEY) && !tried_sshkey {\n            // If ssh-agent authentication fails, libgit2 will keep\n            // calling this callback asking for other authentication\n            // methods to try. Make sure we only try ssh-agent once,\n            // to avoid looping forever.\n            tried_sshkey = true;\n            let username = username.unwrap();\n            debug_assert!(!ssh_username_requested);\n            ssh_agent_attempts.push(username.to_string());\n            return git2::Cred::ssh_key_from_agent(username);\n        }\n\n        // Sometimes libgit2 will ask for a username/password in plaintext. This\n        // is where Cargo would have an interactive prompt if we supported it,\n        // but we currently don't! Right now the only way we support fetching a\n        // plaintext password is through the `credential.helper` support, so\n        // fetch that here.\n        //\n        // If ssh-agent authentication fails, libgit2 will keep calling this\n        // callback asking for other authentication methods to try. Check\n        // cred_helper_bad to make sure we only try the git credential helper\n        // once, to avoid looping forever.\n        if allowed.contains(git2::CredentialType::USER_PASS_PLAINTEXT) && cred_helper_bad.is_none()\n        {\n            let r = git2::Cred::credential_helper(cfg, url, username);\n            cred_helper_bad = Some(r.is_err());\n            return r;\n        }\n\n        // I'm... not sure what the DEFAULT kind of authentication is, but seems\n        // easy to support?\n        if allowed.contains(git2::CredentialType::DEFAULT) {\n            return git2::Cred::default();\n        }\n\n        // Whelp, we tried our best\n        Err(git2::Error::from_str(\"no authentication methods succeeded\"))\n    });\n\n    // Ok, so if it looks like we're going to be doing ssh authentication, we\n    // want to try a few different usernames as one wasn't specified in the URL\n    // for us to use. In order, we'll try:\n    //\n    // * A credential helper's username for this URL, if available.\n    // * This account's username.\n    // * \"git\"\n    //\n    // We have to restart the authentication session each time (due to\n    // constraints in libssh2 I guess? maybe this is inherent to ssh?), so we\n    // call our callback, `f`, in a loop here.\n    if ssh_username_requested {\n        debug_assert!(res.is_err());\n        let mut attempts = vec![String::from(\"git\")];\n        if let Ok(s) = gctx.get_env(\"USER\").or_else(|_| gctx.get_env(\"USERNAME\")) {\n            attempts.push(s.to_string());\n        }\n        if let Some(ref s) = cred_helper.username {\n            attempts.push(s.clone());\n        }\n\n        while let Some(s) = attempts.pop() {\n            // We should get `USERNAME` first, where we just return our attempt,\n            // and then after that we should get `SSH_KEY`. If the first attempt\n            // fails we'll get called again, but we don't have another option so\n            // we bail out.\n            let mut attempts = 0;\n            res = f(&mut |_url, username, allowed| {\n                if allowed.contains(git2::CredentialType::USERNAME) {\n                    return git2::Cred::username(&s);\n                }\n                if allowed.contains(git2::CredentialType::SSH_KEY) {\n                    debug_assert_eq!(Some(&s[..]), username);\n                    attempts += 1;\n                    if attempts == 1 {\n                        ssh_agent_attempts.push(s.to_string());\n                        return git2::Cred::ssh_key_from_agent(&s);\n                    }\n                }\n                Err(git2::Error::from_str(\"no authentication methods succeeded\"))\n            });\n\n            // If we made two attempts then that means:\n            //\n            // 1. A username was requested, we returned `s`.\n            // 2. An ssh key was requested, we returned to look up `s` in the\n            //    ssh agent.\n            // 3. For whatever reason that lookup failed, so we were asked again\n            //    for another mode of authentication.\n            //\n            // Essentially, if `attempts == 2` then in theory the only error was\n            // that this username failed to authenticate (e.g., no other network\n            // errors happened). Otherwise something else is funny so we bail\n            // out.\n            if attempts != 2 {\n                break;\n            }\n        }\n    }\n    let mut err = match res {\n        Ok(e) => return Ok(e),\n        Err(e) => e,\n    };\n\n    // In the case of an authentication failure (where we tried something) then\n    // we try to give a more helpful error message about precisely what we\n    // tried.\n    if any_attempts {\n        let mut msg = \"failed to authenticate when downloading \\\n                       repository\"\n            .to_string();\n\n        if let Some(attempt) = &url_attempt {\n            if url != attempt {\n                msg.push_str(\": \");\n                msg.push_str(attempt);\n            }\n        }\n        msg.push('\\n');\n        if !ssh_agent_attempts.is_empty() {\n            let names = ssh_agent_attempts\n                .iter()\n                .map(|s| format!(\"`{}`\", s))\n                .collect::<Vec<_>>()\n                .join(\", \");\n            msg.push_str(&format!(\n                \"\\n* attempted ssh-agent authentication, but \\\n                 no usernames succeeded: {}\",\n                names\n            ));\n        }\n        if let Some(failed_cred_helper) = cred_helper_bad {\n            if failed_cred_helper {\n                msg.push_str(\n                    \"\\n* attempted to find username/password via \\\n                     git's `credential.helper` support, but failed\",\n                );\n            } else {\n                msg.push_str(\n                    \"\\n* attempted to find username/password via \\\n                     `credential.helper`, but maybe the found \\\n                     credentials were incorrect\",\n                );\n            }\n        }\n        msg.push_str(\"\\n\\n\");\n        msg.push_str(\"if the git CLI succeeds then `net.git-fetch-with-cli` may help here\\n\");\n        msg.push_str(\"https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\");\n        err = err.context(msg);\n\n        // Otherwise if we didn't even get to the authentication phase them we may\n        // have failed to set up a connection, in these cases hint on the\n        // `net.git-fetch-with-cli` configuration option.\n    } else if let Some(e) = err.downcast_ref::<git2::Error>() {\n        match e.class() {\n            ErrorClass::Net\n            | ErrorClass::Ssl\n            | ErrorClass::Submodule\n            | ErrorClass::FetchHead\n            | ErrorClass::Ssh\n            | ErrorClass::Http => {\n                let msg = format!(\n                    concat!(\n                        \"network failure seems to have happened\\n\",\n                        \"if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\\n\",\n                        \"https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\",\n                        \"{}\"\n                    ),\n                    note_github_pull_request(url).unwrap_or_default()\n                );\n                err = err.context(msg);\n            }\n            ErrorClass::Callback => {\n                // This unwraps the git2 error. We're using the callback error\n                // specifically to convey errors from Rust land through the C\n                // callback interface. We don't need the `; class=Callback\n                // (26)` that gets tacked on to the git2 error message.\n                err = anyhow::format_err!(\"{}\", e.message());\n            }\n            _ => {}\n        }\n    }\n\n    Err(err)\n}\n\n/// `git reset --hard` to the given `obj` for the `repo`.\n///\n/// The `obj` is a commit-ish to which the head should be moved.\nfn reset(repo: &git2::Repository, obj: &git2::Object<'_>, gctx: &GlobalContext) -> CargoResult<()> {\n    let mut pb = Progress::new(\"Checkout\", gctx);\n    let mut opts = git2::build::CheckoutBuilder::new();\n    opts.progress(|_, cur, max| {\n        drop(pb.tick(cur, max, \"\"));\n    });\n    debug!(\"doing reset\");\n    repo.reset(obj, git2::ResetType::Hard, Some(&mut opts))?;\n    debug!(\"reset done\");\n    Ok(())\n}\n\n/// Prepares the callbacks for fetching a git repository.\n///\n/// The main purpose of this function is to construct everything before a fetch.\n/// This will attempt to setup a progress bar, the authentication for git,\n/// ssh known hosts check, and the network retry mechanism.\n///\n/// The callback is provided a fetch options, which can be used by the actual\n/// git fetch.\npub fn with_fetch_options(\n    git_config: &git2::Config,\n    url: &str,\n    gctx: &GlobalContext,\n    cb: &mut dyn FnMut(git2::FetchOptions<'_>) -> CargoResult<()>,\n) -> CargoResult<()> {\n    let mut progress = Progress::new(\"Fetch\", gctx);\n    let ssh_config = gctx.net_config()?.ssh.as_ref();\n    let config_known_hosts = ssh_config.and_then(|ssh| ssh.known_hosts.as_ref());\n    let diagnostic_home_config = gctx.diagnostic_home_config();\n    network::retry::with_retry(gctx, || {\n        // Hack: libgit2 disallows overriding the error from check_cb since v1.8.0,\n        // so we store the error additionally and unwrap it later\n        let mut check_cb_result = Ok(());\n        let auth_result = with_authentication(gctx, url, git_config, |f| {\n            let port = Url::parse(url).ok().and_then(|url| url.port());\n            let mut last_update = Instant::now();\n            let mut rcb = git2::RemoteCallbacks::new();\n            // We choose `N=10` here to make a `300ms * 10slots ~= 3000ms`\n            // sliding window for tracking the data transfer rate (in bytes/s).\n            let mut counter = MetricsCounter::<10>::new(0, last_update);\n            rcb.credentials(f);\n            rcb.certificate_check(|cert, host| {\n                match super::known_hosts::certificate_check(\n                    gctx,\n                    cert,\n                    host,\n                    port,\n                    config_known_hosts,\n                    &diagnostic_home_config,\n                ) {\n                    Ok(status) => Ok(status),\n                    Err(e) => {\n                        check_cb_result = Err(e);\n                        // This is not really used because it'll be overridden by libgit2\n                        // See https://github.com/libgit2/libgit2/commit/9a9f220119d9647a352867b24b0556195cb26548\n                        Err(git2::Error::from_str(\n                            \"invalid or unknown remote ssh hostkey\",\n                        ))\n                    }\n                }\n            });\n            rcb.transfer_progress(|stats| {\n                let indexed_deltas = stats.indexed_deltas();\n                let msg = if indexed_deltas > 0 {\n                    // Resolving deltas.\n                    format!(\n                        \", ({}/{}) resolving deltas\",\n                        indexed_deltas,\n                        stats.total_deltas()\n                    )\n                } else {\n                    // Receiving objects.\n                    //\n                    // # Caveat\n                    //\n                    // Progress bar relies on git2 calling `transfer_progress`\n                    // to update its transfer rate, but we cannot guarantee a\n                    // periodic call of that callback. Thus if we don't receive\n                    // any data for, say, 10 seconds, the rate will get stuck\n                    // and never go down to 0B/s.\n                    // In the future, we need to find away to update the rate\n                    // even when the callback is not called.\n                    let now = Instant::now();\n                    // Scrape a `received_bytes` to the counter every 300ms.\n                    if now - last_update > Duration::from_millis(300) {\n                        counter.add(stats.received_bytes(), now);\n                        last_update = now;\n                    }\n                    let rate = HumanBytes(counter.rate() as u64);\n                    format!(\", {rate:.2}/s\")\n                };\n                progress\n                    .tick(stats.indexed_objects(), stats.total_objects(), &msg)\n                    .is_ok()\n            });\n\n            // Create a local anonymous remote in the repository to fetch the\n            // url\n            let mut opts = git2::FetchOptions::new();\n            opts.remote_callbacks(rcb);\n            cb(opts)\n        });\n        if auth_result.is_err() {\n            check_cb_result?;\n        }\n        auth_result?;\n        Ok(())\n    })\n}\n\n/// Attempts to fetch the given git `reference` for a Git repository.\n///\n/// This is the main entry for git clone/fetch. It does the followings:\n///\n/// * Turns [`GitReference`] into refspecs accordingly.\n/// * Dispatches `git fetch` using libgit2, gitoxide, or git CLI.\n///\n/// The `remote_url` argument is the git remote URL where we want to fetch from.\n///\n/// The `remote_kind` argument is a thing for [`-Zgitoxide`] shallow clones\n/// at this time. It could be extended when libgit2 supports shallow clones.\n///\n/// [`-Zgitoxide`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#gitoxide\npub fn fetch(\n    repo: &mut git2::Repository,\n    remote_url: &str,\n    manifest_reference: &GitReference,\n    locked_reference: &GitReference,\n    gctx: &GlobalContext,\n    remote_kind: RemoteKind,\n) -> CargoResult<()> {\n    if let Some(offline_flag) = gctx.offline_flag() {\n        anyhow::bail!(\n            \"attempting to update a git repository, but {offline_flag} \\\n             was specified\"\n        )\n    }\n\n    let shallow = remote_kind.to_shallow_setting(repo.is_shallow(), gctx);\n\n    // Flag to keep track if the rev is a full commit hash\n    let mut fast_path_rev: bool = false;\n\n    let oid_to_fetch = match github_fast_path(repo, remote_url, locked_reference, gctx) {\n        Ok(FastPathRev::UpToDate) => return Ok(()),\n        Ok(FastPathRev::NeedsFetch(rev)) => Some(rev),\n        Ok(FastPathRev::Indeterminate) => None,\n        Err(e) => {\n            debug!(\"failed to check github {:?}\", e);\n            None\n        }\n    };\n\n    maybe_gc_repo(repo, gctx)?;\n\n    clean_repo_temp_files(repo);\n\n    // Translate the reference desired here into an actual list of refspecs\n    // which need to get fetched. Additionally record if we're fetching tags.\n    let mut refspecs = Vec::new();\n    let mut tags = false;\n    // The `+` symbol on the refspec means to allow a forced (fast-forward)\n    // update which is needed if there is ever a force push that requires a\n    // fast-forward.\n    match locked_reference {\n        // For branches and tags we can fetch simply one reference and copy it\n        // locally, no need to fetch other branches/tags.\n        GitReference::Branch(b) => {\n            refspecs.push(format!(\"+refs/heads/{0}:refs/remotes/origin/{0}\", b));\n        }\n\n        GitReference::Tag(t) => {\n            refspecs.push(format!(\"+refs/tags/{0}:refs/remotes/origin/tags/{0}\", t));\n        }\n\n        GitReference::DefaultBranch => {\n            refspecs.push(String::from(\"+HEAD:refs/remotes/origin/HEAD\"));\n        }\n\n        GitReference::Rev(rev) => {\n            if rev.starts_with(\"refs/\") {\n                refspecs.push(format!(\"+{0}:{0}\", rev));\n            } else if let Some(oid_to_fetch) = oid_to_fetch {\n                fast_path_rev = true;\n                refspecs.push(format!(\"+{0}:refs/commit/{0}\", oid_to_fetch));\n            } else if !matches!(shallow, gix::remote::fetch::Shallow::NoChange)\n                && rev_to_oid(rev).is_some()\n            {\n                // There is a specific commit to fetch and we will do so in shallow-mode only\n                // to not disturb the previous logic.\n                // Note that with typical settings for shallowing, we will just fetch a single `rev`\n                // as single commit.\n                // The reason we write to `refs/remotes/origin/HEAD` is that it's of special significance\n                // when during `GitReference::resolve()`, but otherwise it shouldn't matter.\n                refspecs.push(format!(\"+{0}:refs/remotes/origin/HEAD\", rev));\n            } else if let GitReference::Rev(rev) = manifest_reference\n                && rev.starts_with(\"refs/\")\n            {\n                // If the lockfile has a commit. we can't directly fetch it (unless we're talking\n                // to GitHub), so we fetch the ref associated with it from the manifest.\n                refspecs.push(format!(\"+{0}:{0}\", rev));\n            } else {\n                // We don't know what the rev will point to. To handle this\n                // situation we fetch all branches and tags, and then we pray\n                // it's somewhere in there.\n                refspecs.push(String::from(\"+refs/heads/*:refs/remotes/origin/*\"));\n                refspecs.push(String::from(\"+HEAD:refs/remotes/origin/HEAD\"));\n                tags = true;\n            }\n        }\n    }\n\n    debug!(\"doing a fetch for {remote_url}\");\n    let result = if let Some(true) = gctx.net_config()?.git_fetch_with_cli {\n        fetch_with_cli(repo, remote_url, &refspecs, tags, shallow, gctx)\n    } else if gctx.cli_unstable().gitoxide.map_or(false, |git| git.fetch) {\n        fetch_with_gitoxide(repo, remote_url, refspecs, tags, shallow, gctx)\n    } else {\n        fetch_with_libgit2(repo, remote_url, refspecs, tags, shallow, gctx)\n    };\n\n    if fast_path_rev {\n        if let Some(oid) = oid_to_fetch {\n            return result.with_context(|| format!(\"revision {} not found\", oid));\n        }\n    }\n    result\n}\n\n/// `gitoxide` uses shallow locks to assure consistency when fetching to and to avoid races, and to write\n/// files atomically.\n/// Cargo has its own lock files and doesn't need that mechanism for race protection, so a stray lock means\n/// a signal interrupted a previous shallow fetch and doesn't mean a race is happening.\nfn has_shallow_lock_file(err: &crate::sources::git::fetch::Error) -> bool {\n    matches!(\n        err,\n        gix::env::collate::fetch::Error::Fetch(gix::remote::fetch::Error::Fetch(\n            gix::protocol::fetch::Error::LockShallowFile(_)\n        ))\n    )\n}\n\n/// Attempts to use `git` CLI installed on the system to fetch a repository,\n/// when the config value [`net.git-fetch-with-cli`][1] is set.\n///\n/// Unfortunately `libgit2` is notably lacking in the realm of authentication\n/// when compared to the `git` command line. As a result, allow an escape\n/// hatch for users that would prefer to use `git`-the-CLI for fetching\n/// repositories instead of `libgit2`-the-library. This should make more\n/// flavors of authentication possible while also still giving us all the\n/// speed and portability of using `libgit2`.\n///\n/// [1]: https://doc.rust-lang.org/nightly/cargo/reference/config.html#netgit-fetch-with-cli\nfn fetch_with_cli(\n    repo: &mut git2::Repository,\n    url: &str,\n    refspecs: &[String],\n    tags: bool,\n    shallow: gix::remote::fetch::Shallow,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    debug!(target: \"git-fetch\", backend = \"git-cli\");\n\n    let mut cmd = ProcessBuilder::new(\"git\");\n    cmd.arg(\"fetch\");\n    if tags {\n        cmd.arg(\"--tags\");\n    } else {\n        cmd.arg(\"--no-tags\");\n    }\n    if let gix::remote::fetch::Shallow::DepthAtRemote(depth) = shallow {\n        let depth = 0i32.saturating_add_unsigned(depth.get());\n        cmd.arg(format!(\"--depth={depth}\"));\n    }\n    match gctx.shell().verbosity() {\n        Verbosity::Normal => {}\n        Verbosity::Verbose => {\n            cmd.arg(\"--verbose\");\n        }\n        Verbosity::Quiet => {\n            cmd.arg(\"--quiet\");\n        }\n    }\n    cmd.arg(\"--force\") // handle force pushes\n        .arg(\"--update-head-ok\") // see discussion in #2078\n        .arg(url)\n        .args(refspecs)\n        // If cargo is run by git (for example, the `exec` command in `git\n        // rebase`), the GIT_DIR is set by git and will point to the wrong\n        // location. This makes sure GIT_DIR is always the repository path.\n        .env(\"GIT_DIR\", repo.path())\n        // The reset of these may not be necessary, but I'm including them\n        // just to be extra paranoid and avoid any issues.\n        .env_remove(\"GIT_WORK_TREE\")\n        .env_remove(\"GIT_INDEX_FILE\")\n        .env_remove(\"GIT_OBJECT_DIRECTORY\")\n        .env_remove(\"GIT_ALTERNATE_OBJECT_DIRECTORIES\")\n        .cwd(repo.path());\n    gctx.shell()\n        .verbose(|s| s.status(\"Running\", &cmd.to_string()))?;\n    network::retry::with_retry(gctx, || {\n        cmd.exec()\n            .map_err(|error| GitCliError::new(error, true).into())\n    })?;\n\n    Ok(())\n}\n\nfn fetch_with_gitoxide(\n    repo: &mut git2::Repository,\n    remote_url: &str,\n    refspecs: Vec<String>,\n    tags: bool,\n    shallow: gix::remote::fetch::Shallow,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    debug!(target: \"git-fetch\", backend = \"gitoxide\");\n\n    let git2_repo = repo;\n    let config_overrides = cargo_config_to_gitoxide_overrides(gctx)?;\n    let repo_reinitialized = AtomicBool::default();\n    let res = oxide::with_retry_and_progress(\n        git2_repo.path(),\n        gctx,\n        remote_url,\n        &|repo_path,\n          should_interrupt,\n          mut progress,\n          url_for_authentication: &mut dyn FnMut(&gix::bstr::BStr)| {\n            // The `fetch` operation here may fail spuriously due to a corrupt\n            // repository. It could also fail, however, for a whole slew of other\n            // reasons (aka network related reasons). We want Cargo to automatically\n            // recover from corrupt repositories, but we don't want Cargo to stomp\n            // over other legitimate errors.\n            //\n            // Consequently we save off the error of the `fetch` operation and if it\n            // looks like a \"corrupt repo\" error then we blow away the repo and try\n            // again. If it looks like any other kind of error, or if we've already\n            // blown away the repository, then we want to return the error as-is.\n            loop {\n                let res = oxide::open_repo(\n                    repo_path,\n                    config_overrides.clone(),\n                    oxide::OpenMode::ForFetch,\n                )\n                .map_err(crate::sources::git::fetch::Error::from)\n                .and_then(|repo| {\n                    debug!(\"initiating fetch of {refspecs:?} from {remote_url}\");\n                    let url_for_authentication = &mut *url_for_authentication;\n                    let remote = repo\n                        .remote_at(remote_url)?\n                        .with_fetch_tags(if tags {\n                            gix::remote::fetch::Tags::All\n                        } else {\n                            gix::remote::fetch::Tags::Included\n                        })\n                        .with_refspecs(\n                            refspecs.iter().map(|s| s.as_str()),\n                            gix::remote::Direction::Fetch,\n                        )\n                        .map_err(crate::sources::git::fetch::Error::Other)?;\n                    let url = remote\n                        .url(gix::remote::Direction::Fetch)\n                        .expect(\"set at init\")\n                        .to_owned();\n                    let connection = remote.connect(gix::remote::Direction::Fetch)?;\n                    let mut authenticate = connection.configured_credentials(url)?;\n                    let connection = connection.with_credentials(\n                        move |action: gix::protocol::credentials::helper::Action| {\n                            if let Some(url) = action\n                                .context()\n                                .and_then(|gctx| gctx.url.as_ref().filter(|url| *url != remote_url))\n                            {\n                                url_for_authentication(url.as_ref());\n                            }\n                            authenticate(action)\n                        },\n                    );\n                    let outcome = connection\n                        .prepare_fetch(&mut progress, gix::remote::ref_map::Options::default())?\n                        .with_shallow(shallow.clone())\n                        .receive(&mut progress, should_interrupt)?;\n                    Ok(outcome)\n                });\n                let err = match res {\n                    Ok(_) => break,\n                    Err(e) => e,\n                };\n                debug!(\"fetch failed: {}\", err);\n\n                if !repo_reinitialized.load(Ordering::Relaxed)\n                        // We check for errors that could occur if the configuration, refs or odb files are corrupted.\n                        // We don't check for errors related to writing as `gitoxide` is expected to create missing leading\n                        // folder before writing files into it, or else not even open a directory as git repository (which is\n                        // also handled here).\n                        && err.is_corrupted()\n                    || has_shallow_lock_file(&err)\n                {\n                    repo_reinitialized.store(true, Ordering::Relaxed);\n                    debug!(\n                        \"looks like this is a corrupt repository, reinitializing \\\n                     and trying again\"\n                    );\n                    if oxide::reinitialize(repo_path).is_ok() {\n                        continue;\n                    }\n                }\n\n                return Err(err.into());\n            }\n            Ok(())\n        },\n    );\n    if repo_reinitialized.load(Ordering::Relaxed) {\n        *git2_repo = git2::Repository::open(git2_repo.path())?;\n    }\n    res\n}\n\nfn fetch_with_libgit2(\n    repo: &mut git2::Repository,\n    remote_url: &str,\n    refspecs: Vec<String>,\n    tags: bool,\n    shallow: gix::remote::fetch::Shallow,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    debug!(target: \"git-fetch\", backend = \"libgit2\");\n\n    let git_config = git2::Config::open_default()?;\n    with_fetch_options(&git_config, remote_url, gctx, &mut |mut opts| {\n        if tags {\n            opts.download_tags(git2::AutotagOption::All);\n        }\n        if let gix::remote::fetch::Shallow::DepthAtRemote(depth) = shallow {\n            opts.depth(0i32.saturating_add_unsigned(depth.get()));\n        }\n        // The `fetch` operation here may fail spuriously due to a corrupt\n        // repository. It could also fail, however, for a whole slew of other\n        // reasons (aka network related reasons). We want Cargo to automatically\n        // recover from corrupt repositories, but we don't want Cargo to stomp\n        // over other legitimate errors.\n        //\n        // Consequently we save off the error of the `fetch` operation and if it\n        // looks like a \"corrupt repo\" error then we blow away the repo and try\n        // again. If it looks like any other kind of error, or if we've already\n        // blown away the repository, then we want to return the error as-is.\n        let mut repo_reinitialized = false;\n        loop {\n            debug!(\"initiating fetch of {refspecs:?} from {remote_url}\");\n            let res = repo\n                .remote_anonymous(remote_url)?\n                .fetch(&refspecs, Some(&mut opts), None);\n            let err = match res {\n                Ok(()) => break,\n                Err(e) => e,\n            };\n            debug!(\"fetch failed: {}\", err);\n\n            if !repo_reinitialized && matches!(err.class(), ErrorClass::Reference | ErrorClass::Odb)\n            {\n                repo_reinitialized = true;\n                debug!(\n                    \"looks like this is a corrupt repository, reinitializing \\\n                     and trying again\"\n                );\n                if reinitialize(repo).is_ok() {\n                    continue;\n                }\n            }\n\n            return Err(err.into());\n        }\n        Ok(())\n    })\n}\n\n/// Attempts to `git gc` a repository.\n///\n/// Cargo has a bunch of long-lived git repositories in its global cache and\n/// some, like the index, are updated very frequently. Right now each update\n/// creates a new \"pack file\" inside the git database, and over time this can\n/// cause bad performance and bad current behavior in libgit2.\n///\n/// One pathological use case today is where libgit2 opens hundreds of file\n/// descriptors, getting us dangerously close to blowing out the OS limits of\n/// how many fds we can have open. This is detailed in [#4403].\n///\n/// Instead of trying to be clever about when gc is needed, we just run\n/// `git gc --auto` and let git figure it out. It checks its own thresholds\n/// (gc.auto, gc.autoPackLimit) and either does the work or exits quickly.\n/// If git isn't installed, no worries - we skip it.\n///\n/// [#4403]: https://github.com/rust-lang/cargo/issues/4403\nfn maybe_gc_repo(repo: &mut git2::Repository, gctx: &GlobalContext) -> CargoResult<()> {\n    // Let git decide whether gc is actually needed based on its own thresholds\n    // (gc.auto, gc.autoPackLimit). This avoids duplicating git's internal logic\n    // for deciding when housekeeping is needed.\n    //\n    // For testing purposes, __CARGO_PACKFILE_LIMIT can be set to override\n    // gc.autoPackLimit, which has the same meaning. This lets tests force gc\n    // to run by setting a low threshold without depending on git's defaults.\n    let mut cmd = Command::new(\"git\");\n    if let Ok(limit) = gctx.get_env(\"__CARGO_PACKFILE_LIMIT\") {\n        cmd.arg(format!(\"-c gc.autoPackLimit={}\", limit));\n    }\n    cmd.arg(\"gc\").arg(\"--auto\").current_dir(repo.path());\n\n    match cmd.output() {\n        Ok(out) => {\n            debug!(\n                \"git-gc --auto status: {}\\n\\nstdout ---\\n{}\\nstderr ---\\n{}\",\n                out.status,\n                String::from_utf8_lossy(&out.stdout),\n                String::from_utf8_lossy(&out.stderr)\n            );\n            if out.status.success() {\n                let new = git2::Repository::open(repo.path())?;\n                *repo = new;\n                return Ok(());\n            }\n        }\n        Err(e) => debug!(\"git-gc --auto failed to spawn: {}\", e),\n    }\n\n    // Alright all else failed, let's start over.\n    reinitialize(repo)\n}\n\n/// Removes temporary files left from previous activity.\n///\n/// If libgit2 is interrupted while indexing pack files, it will leave behind\n/// some temporary files that it doesn't clean up. These can be quite large in\n/// size, so this tries to clean things up.\n///\n/// This intentionally ignores errors. This is only an opportunistic cleaning,\n/// and we don't really care if there are issues (there's unlikely anything\n/// that can be done).\n///\n/// The git CLI has similar behavior (its temp files look like\n/// `objects/pack/tmp_pack_9kUSA8`). Those files are normally deleted via `git\n/// prune` which is run by `git gc`. However, it doesn't know about libgit2's\n/// filenames, so they never get cleaned up.\nfn clean_repo_temp_files(repo: &git2::Repository) {\n    let path = repo.path().join(\"objects/pack/pack_git2_*\");\n    let Some(pattern) = path.to_str() else {\n        tracing::warn!(\"cannot convert {path:?} to a string\");\n        return;\n    };\n    let Ok(paths) = glob::glob(pattern) else {\n        return;\n    };\n    for path in paths {\n        if let Ok(path) = path {\n            match paths::remove_file(&path) {\n                Ok(_) => tracing::debug!(\"removed stale temp git file {path:?}\"),\n                Err(e) => {\n                    tracing::warn!(\"failed to remove {path:?} while cleaning temp files: {e}\")\n                }\n            }\n        }\n    }\n}\n\n/// Reinitializes a given Git repository. This is useful when a Git repository\n/// seems corrupted and we want to start over.\nfn reinitialize(repo: &mut git2::Repository) -> CargoResult<()> {\n    // Here we want to drop the current repository object pointed to by `repo`,\n    // so we initialize temporary repository in a sub-folder, blow away the\n    // existing git folder, and then recreate the git repo. Finally we blow away\n    // the `tmp` folder we allocated.\n    let path = repo.path().to_path_buf();\n    debug!(\"reinitializing git repo at {:?}\", path);\n    let tmp = path.join(\"tmp\");\n    let bare = !repo.path().ends_with(\".git\");\n    *repo = init(&tmp, false)?;\n    for entry in path.read_dir()? {\n        let entry = entry?;\n        if entry.file_name().to_str() == Some(\"tmp\") {\n            continue;\n        }\n        let path = entry.path();\n        drop(paths::remove_file(&path).or_else(|_| paths::remove_dir_all(&path)));\n    }\n    *repo = init(&path, bare)?;\n    paths::remove_dir_all(&tmp)?;\n    Ok(())\n}\n\n/// Initializes a Git repository at `path`.\nfn init(path: &Path, bare: bool) -> CargoResult<git2::Repository> {\n    let mut opts = git2::RepositoryInitOptions::new();\n    // Skip anything related to templates, they just call all sorts of issues as\n    // we really don't want to use them yet they insist on being used. See #6240\n    // for an example issue that comes up.\n    opts.external_template(false);\n    opts.bare(bare);\n    Ok(git2::Repository::init_opts(&path, &opts)?)\n}\n\n/// The result of GitHub fast path check. See [`github_fast_path`] for more.\nenum FastPathRev {\n    /// The local rev (determined by `reference.resolve(repo)`) is already up to\n    /// date with what this rev resolves to on GitHub's server.\n    UpToDate,\n    /// The following SHA must be fetched in order for the local rev to become\n    /// up to date.\n    NeedsFetch(Oid),\n    /// Don't know whether local rev is up to date. We'll fetch _all_ branches\n    /// and tags from the server and see what happens.\n    Indeterminate,\n}\n\n/// Attempts GitHub's special fast path for testing if we've already got an\n/// up-to-date copy of the repository.\n///\n/// Updating the index is done pretty regularly so we want it to be as fast as\n/// possible. For registries hosted on GitHub (like the crates.io index) there's\n/// a fast path available to use[^1] to tell us that there's no updates to be\n/// made.\n///\n/// Note that this function should never cause an actual failure because it's\n/// just a fast path. As a result, a caller should ignore `Err` returned from\n/// this function and move forward on the normal path.\n///\n/// [^1]: <https://developer.github.com/v3/repos/commits/#get-the-sha-1-of-a-commit-reference>\nfn github_fast_path(\n    repo: &mut git2::Repository,\n    url: &str,\n    reference: &GitReference,\n    gctx: &GlobalContext,\n) -> CargoResult<FastPathRev> {\n    let url = Url::parse(url)?;\n    if !is_github(&url) {\n        return Ok(FastPathRev::Indeterminate);\n    }\n\n    let local_object = resolve_ref(reference, repo).ok();\n\n    let github_branch_name = match reference {\n        GitReference::Branch(branch) => branch,\n        GitReference::Tag(tag) => tag,\n        GitReference::DefaultBranch => \"HEAD\",\n        GitReference::Rev(rev) => {\n            if rev.starts_with(\"refs/\") {\n                rev\n            } else if looks_like_commit_hash(rev) {\n                // `revparse_single` (used by `resolve`) is the only way to turn\n                // short hash -> long hash, but it also parses other things,\n                // like branch and tag names, which might coincidentally be\n                // valid hex.\n                //\n                // We only return early if `rev` is a prefix of the object found\n                // by `revparse_single`. Don't bother talking to GitHub in that\n                // case, since commit hashes are permanent. If a commit with the\n                // requested hash is already present in the local clone, its\n                // contents must be the same as what is on the server for that\n                // hash.\n                //\n                // If `rev` is not found locally by `revparse_single`, we'll\n                // need GitHub to resolve it and get a hash. If `rev` is found\n                // but is not a short hash of the found object, it's probably a\n                // branch and we also need to get a hash from GitHub, in case\n                // the branch has moved.\n                if let Some(local_object) = local_object {\n                    if is_short_hash_of(rev, local_object) {\n                        debug!(\"github fast path already has {local_object}\");\n                        return Ok(FastPathRev::UpToDate);\n                    }\n                }\n                // If `rev` is a full commit hash, the only thing it can resolve\n                // to is itself. Don't bother talking to GitHub in that case\n                // either. (This ensures that we always attempt to fetch the\n                // commit directly even if we can't reach the GitHub API.)\n                if let Some(oid) = rev_to_oid(rev) {\n                    debug!(\"github fast path is already a full commit hash {rev}\");\n                    return Ok(FastPathRev::NeedsFetch(oid));\n                }\n                rev\n            } else {\n                debug!(\"can't use github fast path with `rev = \\\"{}\\\"`\", rev);\n                return Ok(FastPathRev::Indeterminate);\n            }\n        }\n    };\n\n    // This expects GitHub urls in the form `github.com/user/repo` and nothing\n    // else\n    let mut pieces = url\n        .path_segments()\n        .ok_or_else(|| anyhow!(\"no path segments on url\"))?;\n    let username = pieces\n        .next()\n        .ok_or_else(|| anyhow!(\"couldn't find username\"))?;\n    let repository = pieces\n        .next()\n        .ok_or_else(|| anyhow!(\"couldn't find repository name\"))?;\n    if pieces.next().is_some() {\n        anyhow::bail!(\"too many segments on URL\");\n    }\n\n    // Trim off the `.git` from the repository, if present, since that's\n    // optional for GitHub and won't work when we try to use the API as well.\n    let repository = repository.strip_suffix(\".git\").unwrap_or(repository);\n\n    let url = format!(\n        \"https://api.github.com/repos/{}/{}/commits/{}\",\n        username, repository, github_branch_name,\n    );\n    let mut handle = gctx.http()?.lock().unwrap();\n    debug!(\"attempting GitHub fast path for {}\", url);\n    handle.get(true)?;\n    handle.url(&url)?;\n    handle.useragent(\"cargo\")?;\n    handle.follow_location(true)?; // follow redirects\n    handle.http_headers({\n        let mut headers = List::new();\n        headers.append(\"Accept: application/vnd.github.3.sha\")?;\n        if let Some(local_object) = local_object {\n            headers.append(&format!(\"If-None-Match: \\\"{}\\\"\", local_object))?;\n        }\n        headers\n    })?;\n\n    let mut response_body = Vec::new();\n    let mut transfer = handle.transfer();\n    transfer.write_function(|data| {\n        response_body.extend_from_slice(data);\n        Ok(data.len())\n    })?;\n    transfer.perform()?;\n    drop(transfer); // end borrow of handle so that response_code can be called\n\n    let response_code = handle.response_code()?;\n    if response_code == 304 {\n        debug!(\"github fast path up-to-date\");\n        Ok(FastPathRev::UpToDate)\n    } else if response_code == 200\n        && let Some(oid_to_fetch) = rev_to_oid(str::from_utf8(&response_body)?)\n    {\n        // response expected to be a full hash hexstring (40 or 64 chars)\n        debug!(\"github fast path fetch {oid_to_fetch}\");\n        Ok(FastPathRev::NeedsFetch(oid_to_fetch))\n    } else {\n        // Usually response_code == 404 if the repository does not exist, and\n        // response_code == 422 if exists but GitHub is unable to resolve the\n        // requested rev.\n        debug!(\"github fast path bad response code {response_code}\");\n        Ok(FastPathRev::Indeterminate)\n    }\n}\n\n/// Whether a `url` is one from GitHub.\nfn is_github(url: &Url) -> bool {\n    url.host_str() == Some(\"github.com\")\n}\n\n// Give some messages on GitHub PR URL given as is\npub(crate) fn note_github_pull_request(url: &str) -> Option<String> {\n    if let Ok(url) = url.parse::<Url>()\n        && is_github(&url)\n    {\n        let path_segments = url\n            .path_segments()\n            .map(|p| p.into_iter().collect::<Vec<_>>())\n            .unwrap_or_default();\n        if let [owner, repo, \"pull\", pr_number, ..] = path_segments[..] {\n            let repo_url = format!(\"https://github.com/{owner}/{repo}.git\");\n            let rev = format!(\"refs/pull/{pr_number}/head\");\n            return Some(format!(\n                concat!(\n                    \"\\n\\nnote: GitHub url {} is not a repository. \\n\",\n                    \"help: Replace the dependency with \\n\",\n                    \"       `git = \\\"{}\\\" rev = \\\"{}\\\"` \\n\",\n                    \"   to specify pull requests as dependencies' revision.\"\n                ),\n                url, repo_url, rev\n            ));\n        }\n    }\n\n    None\n}\n\n/// Whether a `rev` looks like a commit hash (ASCII hex digits).\nfn looks_like_commit_hash(rev: &str) -> bool {\n    rev.len() >= 7 && rev.chars().all(|ch| ch.is_ascii_hexdigit())\n}\n\n/// Whether `rev` is a shorter hash of `oid`.\nfn is_short_hash_of(rev: &str, oid: Oid) -> bool {\n    let long_hash = oid.to_string();\n    match long_hash.get(..rev.len()) {\n        Some(truncated_long_hash) => truncated_long_hash.eq_ignore_ascii_case(rev),\n        None => false,\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::absolute_submodule_url;\n\n    #[test]\n    fn test_absolute_submodule_url() {\n        let cases = [\n            (\n                \"ssh://git@gitub.com/rust-lang/cargo\",\n                \"git@github.com:rust-lang/cargo.git\",\n                \"git@github.com:rust-lang/cargo.git\",\n            ),\n            (\n                \"ssh://git@gitub.com/rust-lang/cargo\",\n                \"./\",\n                \"ssh://git@gitub.com/rust-lang/cargo/\",\n            ),\n            (\n                \"ssh://git@gitub.com/rust-lang/cargo\",\n                \"../\",\n                \"ssh://git@gitub.com/rust-lang/\",\n            ),\n            (\n                \"ssh://git@gitub.com/rust-lang/cargo\",\n                \"./foo\",\n                \"ssh://git@gitub.com/rust-lang/cargo/foo\",\n            ),\n            (\n                \"ssh://git@gitub.com/rust-lang/cargo/\",\n                \"./foo\",\n                \"ssh://git@gitub.com/rust-lang/cargo/foo\",\n            ),\n            (\n                \"ssh://git@gitub.com/rust-lang/cargo/\",\n                \"../foo\",\n                \"ssh://git@gitub.com/rust-lang/foo\",\n            ),\n            (\n                \"ssh://git@gitub.com/rust-lang/cargo\",\n                \"../foo\",\n                \"ssh://git@gitub.com/rust-lang/foo\",\n            ),\n            (\n                \"ssh://git@gitub.com/rust-lang/cargo\",\n                \"../foo/bar/../baz\",\n                \"ssh://git@gitub.com/rust-lang/foo/baz\",\n            ),\n            (\n                \"git@github.com:rust-lang/cargo.git\",\n                \"ssh://git@gitub.com/rust-lang/cargo\",\n                \"ssh://git@gitub.com/rust-lang/cargo\",\n            ),\n            (\n                \"git@github.com:rust-lang/cargo.git\",\n                \"./\",\n                \"git@github.com:rust-lang/cargo.git/./\",\n            ),\n            (\n                \"git@github.com:rust-lang/cargo.git\",\n                \"../\",\n                \"git@github.com:rust-lang/cargo.git/../\",\n            ),\n            (\n                \"git@github.com:rust-lang/cargo.git\",\n                \"./foo\",\n                \"git@github.com:rust-lang/cargo.git/./foo\",\n            ),\n            (\n                \"git@github.com:rust-lang/cargo.git/\",\n                \"./foo\",\n                \"git@github.com:rust-lang/cargo.git/./foo\",\n            ),\n            (\n                \"git@github.com:rust-lang/cargo.git\",\n                \"../foo\",\n                \"git@github.com:rust-lang/cargo.git/../foo\",\n            ),\n            (\n                \"git@github.com:rust-lang/cargo.git/\",\n                \"../foo\",\n                \"git@github.com:rust-lang/cargo.git/../foo\",\n            ),\n            (\n                \"git@github.com:rust-lang/cargo.git\",\n                \"../foo/bar/../baz\",\n                \"git@github.com:rust-lang/cargo.git/../foo/bar/../baz\",\n            ),\n        ];\n\n        for (base_url, submodule_url, expected) in cases {\n            let url = absolute_submodule_url(base_url, submodule_url).unwrap();\n            assert_eq!(\n                expected, url,\n                \"base `{base_url}`; submodule `{submodule_url}`\"\n            );\n        }\n    }\n}\n\n/// Turns a full commit hash revision into an oid.\n///\n/// Git object ID is supposed to be a hex string of 20 (SHA1) or 32 (SHA256) bytes.\n/// Its length must be double to the underlying bytes (40 or 64),\n/// otherwise libgit2 would happily zero-pad the returned oid.\n///\n/// See:\n///\n/// * <https://github.com/rust-lang/cargo/issues/13188>\n/// * <https://github.com/rust-lang/cargo/issues/13968>\npub(super) fn rev_to_oid(rev: &str) -> Option<Oid> {\n    Oid::from_str(rev)\n        .ok()\n        .filter(|oid| oid.as_bytes().len() * 2 == rev.len())\n}\n"
  },
  {
    "path": "src/cargo/sources/mod.rs",
    "content": "//! The trait for sources of Cargo packages and its built-in implementations.\n//!\n//! A source is a provider that contains source files and metadata of packages.\n//! It provides a number of methods to fetch those package information, for\n//! example, querying metadata or downloading files for a package. These\n//! information then can be used as dependencies for other Cargo packages.\n//!\n//! This module provides [`Source`][source::Source] trait as an abstraction of different sources,\n//! as well as [`SourceMap`][source::SourceMap] struct as a map of all available sources.\n//!\n//! Several built-in implementations of `Source` trait are provided. Namely,\n//!\n//! * [`RegistrySource`] --- A source that provides an index for people to query\n//!   a crate's metadata, and fetch files for a certain crate. crates.io falls\n//!   into this category. So do local registry and sparse registry.\n//! * [`DirectorySource`] --- Files are downloaded ahead of time. Primarily\n//!   designed for crates generated from `cargo vendor`.\n//! * [`GitSource`] --- This gets crate information from a git repository.\n//! * [`PathSource`] --- This gets crate information from a local path on the\n//!   filesystem.\n//! * [`ReplacedSource`] --- This manages the [source replacement] feature,\n//!   redirecting operations on the original source to the replacement.\n//!\n//! This module also contains [`SourceConfigMap`], which is effectively the\n//! representation of the `[source.*]` value in Cargo configuration.\n//!\n//! [source replacement]: https://doc.rust-lang.org/nightly/cargo/reference/source-replacement.html\n\npub use self::config::SourceConfigMap;\npub use self::directory::DirectorySource;\npub use self::git::GitSource;\npub use self::path::PathEntry;\npub use self::path::PathSource;\npub use self::path::RecursivePathSource;\npub use self::registry::{\n    CRATES_IO_DOMAIN, CRATES_IO_INDEX, CRATES_IO_REGISTRY, IndexSummary, RegistrySource,\n};\npub use self::replaced::ReplacedSource;\n\npub mod config;\npub mod directory;\npub mod git;\npub mod overlay;\npub mod path;\npub mod registry;\npub mod replaced;\npub mod source;\n"
  },
  {
    "path": "src/cargo/sources/overlay.rs",
    "content": "use std::task::ready;\n\nuse tracing::debug;\n\nuse crate::sources::IndexSummary;\n\nuse super::source::{MaybePackage, Source};\n\n/// A `Source` that overlays one source over another, pretending that the packages\n/// available in the overlay are actually available in the other one.\n///\n/// This is a massive footgun and a terrible idea, so we do not (and never will)\n/// expose this publicly. However, it is useful for some very specific private\n/// things, like locally verifying a bunch of packages at a time before any of\n/// them have been published.\npub struct DependencyConfusionThreatOverlaySource<'gctx> {\n    // The overlay source. The naming here comes from the main application of this,\n    // where there is a remote registry that we overlay some local packages on.\n    local: Box<dyn Source + 'gctx>,\n    // The source we're impersonating.\n    remote: Box<dyn Source + 'gctx>,\n}\n\nimpl<'gctx> DependencyConfusionThreatOverlaySource<'gctx> {\n    pub fn new(local: Box<dyn Source + 'gctx>, remote: Box<dyn Source + 'gctx>) -> Self {\n        debug!(\n            \"overlaying {} on {}\",\n            local.source_id().as_url(),\n            remote.source_id().as_url()\n        );\n        Self { local, remote }\n    }\n}\n\nimpl<'gctx> Source for DependencyConfusionThreatOverlaySource<'gctx> {\n    fn source_id(&self) -> crate::core::SourceId {\n        self.remote.source_id()\n    }\n\n    fn supports_checksums(&self) -> bool {\n        self.local.supports_checksums() && self.remote.supports_checksums()\n    }\n\n    fn requires_precise(&self) -> bool {\n        self.local.requires_precise() || self.remote.requires_precise()\n    }\n\n    fn query(\n        &mut self,\n        dep: &crate::core::Dependency,\n        kind: super::source::QueryKind,\n        f: &mut dyn FnMut(super::IndexSummary),\n    ) -> std::task::Poll<crate::CargoResult<()>> {\n        let local_source = self.local.source_id();\n        let remote_source = self.remote.source_id();\n\n        let local_dep = dep.clone().map_source(remote_source, local_source);\n        let mut local_packages = std::collections::HashSet::new();\n        let mut local_callback = |index: IndexSummary| {\n            let index = index.map_summary(|s| s.map_source(local_source, remote_source));\n            local_packages.insert(index.as_summary().clone());\n            f(index)\n        };\n        ready!(self.local.query(&local_dep, kind, &mut local_callback))?;\n\n        let mut remote_callback = |index: IndexSummary| {\n            if local_packages.contains(index.as_summary()) {\n                tracing::debug!(?local_source, ?remote_source, ?index, \"package collision\");\n            } else {\n                f(index)\n            }\n        };\n        ready!(self.remote.query(dep, kind, &mut remote_callback))?;\n\n        std::task::Poll::Ready(Ok(()))\n    }\n\n    fn invalidate_cache(&mut self) {\n        self.local.invalidate_cache();\n        self.remote.invalidate_cache();\n    }\n\n    fn set_quiet(&mut self, quiet: bool) {\n        self.local.set_quiet(quiet);\n        self.remote.set_quiet(quiet);\n    }\n\n    fn download(\n        &mut self,\n        package: crate::core::PackageId,\n    ) -> crate::CargoResult<super::source::MaybePackage> {\n        let local_source = self.local.source_id();\n        let remote_source = self.remote.source_id();\n\n        self.local\n            .download(package.map_source(remote_source, local_source))\n            .map(|maybe_pkg| match maybe_pkg {\n                MaybePackage::Ready(pkg) => {\n                    MaybePackage::Ready(pkg.map_source(local_source, remote_source))\n                }\n                x => x,\n            })\n            .or_else(|_| self.remote.download(package))\n    }\n\n    fn finish_download(\n        &mut self,\n        pkg_id: crate::core::PackageId,\n        contents: Vec<u8>,\n    ) -> crate::CargoResult<crate::core::Package> {\n        // The local registry should never return MaybePackage::Download from `download`, so any\n        // downloads that need to be finished come from the remote registry.\n        self.remote.finish_download(pkg_id, contents)\n    }\n\n    fn fingerprint(&self, pkg: &crate::core::Package) -> crate::CargoResult<String> {\n        Ok(pkg.package_id().version().to_string())\n    }\n\n    fn describe(&self) -> String {\n        self.remote.describe()\n    }\n\n    fn add_to_yanked_whitelist(&mut self, pkgs: &[crate::core::PackageId]) {\n        self.local.add_to_yanked_whitelist(pkgs);\n        self.remote.add_to_yanked_whitelist(pkgs);\n    }\n\n    fn is_yanked(\n        &mut self,\n        pkg: crate::core::PackageId,\n    ) -> std::task::Poll<crate::CargoResult<bool>> {\n        self.remote.is_yanked(pkg)\n    }\n\n    fn block_until_ready(&mut self) -> crate::CargoResult<()> {\n        self.local.block_until_ready()?;\n        self.remote.block_until_ready()\n    }\n}\n"
  },
  {
    "path": "src/cargo/sources/path.rs",
    "content": "use std::collections::{HashMap, HashSet};\nuse std::fmt::{self, Debug, Formatter};\nuse std::fs;\nuse std::io;\nuse std::path::{Path, PathBuf};\nuse std::task::Poll;\n\nuse crate::core::{Dependency, EitherManifest, Manifest, Package, PackageId, SourceId};\nuse crate::ops;\nuse crate::sources::IndexSummary;\nuse crate::sources::source::MaybePackage;\nuse crate::sources::source::QueryKind;\nuse crate::sources::source::Source;\nuse crate::util::GlobalContext;\nuse crate::util::errors::CargoResult;\nuse crate::util::important_paths::find_project_manifest_exact;\nuse crate::util::internal;\nuse crate::util::toml::read_manifest;\nuse anyhow::Context as _;\nuse cargo_util::paths;\nuse filetime::FileTime;\nuse gix::bstr::{BString, ByteVec};\nuse gix::dir::entry::Status;\nuse gix::index::entry::Stage;\nuse ignore::gitignore::GitignoreBuilder;\nuse tracing::{debug, info, trace, warn};\nuse walkdir::WalkDir;\n\n/// A source that represents a package gathered at the root\n/// path on the filesystem.\n///\n/// It also provides convenient methods like [`PathSource::list_files`] to\n/// list all files in a package, given its ability to walk the filesystem.\npub struct PathSource<'gctx> {\n    /// The unique identifier of this source.\n    source_id: SourceId,\n    /// The root path of this source.\n    path: PathBuf,\n    /// Packages that this sources has discovered.\n    package: Option<Package>,\n    gctx: &'gctx GlobalContext,\n}\n\nimpl<'gctx> PathSource<'gctx> {\n    /// Invoked with an absolute path to a directory that contains a `Cargo.toml`.\n    ///\n    /// This source will only return the package at precisely the `path`\n    /// specified, and it will be an error if there's not a package at `path`.\n    pub fn new(path: &Path, source_id: SourceId, gctx: &'gctx GlobalContext) -> Self {\n        Self {\n            source_id,\n            path: path.to_path_buf(),\n            package: None,\n            gctx,\n        }\n    }\n\n    /// Preloads a package for this source. The source is assumed that it has\n    /// yet loaded any other packages.\n    pub fn preload_with(pkg: Package, gctx: &'gctx GlobalContext) -> Self {\n        let source_id = pkg.package_id().source_id();\n        let path = pkg.root().to_owned();\n        Self {\n            source_id,\n            path,\n            package: Some(pkg),\n            gctx,\n        }\n    }\n\n    /// Gets the package on the root path.\n    pub fn root_package(&mut self) -> CargoResult<Package> {\n        trace!(\"root_package; source={:?}\", self);\n\n        self.load()?;\n\n        match &self.package {\n            Some(pkg) => Ok(pkg.clone()),\n            None => Err(internal(format!(\n                \"no package found in source {:?}\",\n                self.path\n            ))),\n        }\n    }\n\n    /// List all files relevant to building this package inside this source.\n    ///\n    /// This function will use the appropriate methods to determine the\n    /// set of files underneath this source's directory which are relevant for\n    /// building `pkg`.\n    ///\n    /// The basic assumption of this method is that all files in the directory\n    /// are relevant for building this package, but it also contains logic to\n    /// use other methods like `.gitignore`, `package.include`, or\n    /// `package.exclude` to filter the list of files.\n    #[tracing::instrument(skip_all)]\n    pub fn list_files(&self, pkg: &Package) -> CargoResult<Vec<PathEntry>> {\n        list_files(pkg, self.gctx)\n    }\n\n    /// Gets the last modified file in a package.\n    fn last_modified_file(&self, pkg: &Package) -> CargoResult<(FileTime, PathBuf)> {\n        if self.package.is_none() {\n            return Err(internal(format!(\n                \"BUG: source `{:?}` was not loaded\",\n                self.path\n            )));\n        }\n        last_modified_file(&self.path, pkg, self.gctx)\n    }\n\n    /// Returns the root path of this source.\n    pub fn path(&self) -> &Path {\n        &self.path\n    }\n\n    /// Discovers packages inside this source if it hasn't yet done.\n    pub fn load(&mut self) -> CargoResult<()> {\n        if self.package.is_none() {\n            self.package = Some(self.read_package()?);\n        }\n\n        Ok(())\n    }\n\n    fn read_package(&self) -> CargoResult<Package> {\n        let path = self.path.join(\"Cargo.toml\");\n        let pkg = ops::read_package(&path, self.source_id, self.gctx)?;\n        Ok(pkg)\n    }\n}\n\nimpl<'gctx> Debug for PathSource<'gctx> {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        write!(f, \"the paths source\")\n    }\n}\n\nimpl<'gctx> Source for PathSource<'gctx> {\n    fn query(\n        &mut self,\n        dep: &Dependency,\n        kind: QueryKind,\n        f: &mut dyn FnMut(IndexSummary),\n    ) -> Poll<CargoResult<()>> {\n        self.load()?;\n        if let Some(s) = self.package.as_ref().map(|p| p.summary()) {\n            let matched = match kind {\n                QueryKind::Exact | QueryKind::RejectedVersions => dep.matches(s),\n                QueryKind::AlternativeNames => true,\n                QueryKind::Normalized => dep.matches(s),\n            };\n            if matched {\n                f(IndexSummary::Candidate(s.clone()))\n            }\n        }\n        Poll::Ready(Ok(()))\n    }\n\n    fn supports_checksums(&self) -> bool {\n        false\n    }\n\n    fn requires_precise(&self) -> bool {\n        false\n    }\n\n    fn source_id(&self) -> SourceId {\n        self.source_id\n    }\n\n    fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {\n        trace!(\"getting packages; id={}\", id);\n        self.load()?;\n        let pkg = self.package.iter().find(|pkg| pkg.package_id() == id);\n        pkg.cloned()\n            .map(MaybePackage::Ready)\n            .ok_or_else(|| internal(format!(\"failed to find {} in path source\", id)))\n    }\n\n    fn finish_download(&mut self, _id: PackageId, _data: Vec<u8>) -> CargoResult<Package> {\n        panic!(\"no download should have started\")\n    }\n\n    fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {\n        let (max, max_path) = self.last_modified_file(pkg)?;\n        // Note that we try to strip the prefix of this package to get a\n        // relative path to ensure that the fingerprint remains consistent\n        // across entire project directory renames.\n        let max_path = max_path.strip_prefix(&self.path).unwrap_or(&max_path);\n        Ok(format!(\"{} ({})\", max, max_path.display()))\n    }\n\n    fn describe(&self) -> String {\n        match self.source_id.url().to_file_path() {\n            Ok(path) => path.display().to_string(),\n            Err(_) => self.source_id.to_string(),\n        }\n    }\n\n    fn add_to_yanked_whitelist(&mut self, _pkgs: &[PackageId]) {}\n\n    fn is_yanked(&mut self, _pkg: PackageId) -> Poll<CargoResult<bool>> {\n        Poll::Ready(Ok(false))\n    }\n\n    fn block_until_ready(&mut self) -> CargoResult<()> {\n        self.load()\n    }\n\n    fn invalidate_cache(&mut self) {\n        // Path source has no local cache.\n    }\n\n    fn set_quiet(&mut self, _quiet: bool) {\n        // Path source does not display status\n    }\n}\n\n/// A source that represents one or multiple packages gathered from a given root\n/// path on the filesystem.\npub struct RecursivePathSource<'gctx> {\n    /// The unique identifier of this source.\n    source_id: SourceId,\n    /// The root path of this source.\n    path: PathBuf,\n    /// Whether this source has loaded all package information it may contain.\n    loaded: bool,\n    /// Packages that this sources has discovered.\n    ///\n    /// Tracking all packages for a given ID to warn on-demand for unused packages\n    packages: HashMap<PackageId, Vec<Package>>,\n    /// Avoid redundant unused package warnings\n    warned_duplicate: HashSet<PackageId>,\n    gctx: &'gctx GlobalContext,\n}\n\nimpl<'gctx> RecursivePathSource<'gctx> {\n    /// Creates a new source which is walked recursively to discover packages.\n    ///\n    /// This is similar to the [`PathSource::new`] method except that instead\n    /// of requiring a valid package to be present at `root` the folder is\n    /// walked entirely to crawl for packages.\n    ///\n    /// Note that this should be used with care and likely shouldn't be chosen\n    /// by default!\n    pub fn new(root: &Path, source_id: SourceId, gctx: &'gctx GlobalContext) -> Self {\n        Self {\n            source_id,\n            path: root.to_path_buf(),\n            loaded: false,\n            packages: Default::default(),\n            warned_duplicate: Default::default(),\n            gctx,\n        }\n    }\n\n    /// Returns the packages discovered by this source. It may walk the\n    /// filesystem if package information haven't yet loaded.\n    pub fn read_packages(&mut self) -> CargoResult<Vec<Package>> {\n        self.load()?;\n        Ok(self\n            .packages\n            .iter()\n            .map(|(pkg_id, v)| {\n                first_package(*pkg_id, v, &mut self.warned_duplicate, self.gctx).clone()\n            })\n            .collect())\n    }\n\n    /// List all files relevant to building this package inside this source.\n    ///\n    /// This function will use the appropriate methods to determine the\n    /// set of files underneath this source's directory which are relevant for\n    /// building `pkg`.\n    ///\n    /// The basic assumption of this method is that all files in the directory\n    /// are relevant for building this package, but it also contains logic to\n    /// use other methods like `.gitignore`, `package.include`, or\n    /// `package.exclude` to filter the list of files.\n    pub fn list_files(&self, pkg: &Package) -> CargoResult<Vec<PathEntry>> {\n        list_files(pkg, self.gctx)\n    }\n\n    /// Gets the last modified file in a package.\n    fn last_modified_file(&self, pkg: &Package) -> CargoResult<(FileTime, PathBuf)> {\n        if !self.loaded {\n            return Err(internal(format!(\n                \"BUG: source `{:?}` was not loaded\",\n                self.path\n            )));\n        }\n        last_modified_file(&self.path, pkg, self.gctx)\n    }\n\n    /// Returns the root path of this source.\n    pub fn path(&self) -> &Path {\n        &self.path\n    }\n\n    /// Discovers packages inside this source if it hasn't yet done.\n    pub fn load(&mut self) -> CargoResult<()> {\n        if !self.loaded {\n            self.packages = read_packages(&self.path, self.source_id, self.gctx)?;\n            self.loaded = true;\n        }\n\n        Ok(())\n    }\n}\n\nimpl<'gctx> Debug for RecursivePathSource<'gctx> {\n    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {\n        write!(f, \"the paths source\")\n    }\n}\n\nimpl<'gctx> Source for RecursivePathSource<'gctx> {\n    fn query(\n        &mut self,\n        dep: &Dependency,\n        kind: QueryKind,\n        f: &mut dyn FnMut(IndexSummary),\n    ) -> Poll<CargoResult<()>> {\n        self.load()?;\n        for s in self\n            .packages\n            .iter()\n            .filter(|(pkg_id, _)| pkg_id.name() == dep.package_name())\n            .map(|(pkg_id, pkgs)| {\n                first_package(*pkg_id, pkgs, &mut self.warned_duplicate, self.gctx)\n            })\n            .map(|p| p.summary())\n        {\n            let matched = match kind {\n                QueryKind::Exact | QueryKind::RejectedVersions => dep.matches(s),\n                QueryKind::AlternativeNames => true,\n                QueryKind::Normalized => dep.matches(s),\n            };\n            if matched {\n                f(IndexSummary::Candidate(s.clone()))\n            }\n        }\n        Poll::Ready(Ok(()))\n    }\n\n    fn supports_checksums(&self) -> bool {\n        false\n    }\n\n    fn requires_precise(&self) -> bool {\n        false\n    }\n\n    fn source_id(&self) -> SourceId {\n        self.source_id\n    }\n\n    fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {\n        trace!(\"getting packages; id={}\", id);\n        self.load()?;\n        let pkg = self.packages.get(&id);\n        pkg.map(|pkgs| first_package(id, pkgs, &mut self.warned_duplicate, self.gctx).clone())\n            .map(MaybePackage::Ready)\n            .ok_or_else(|| internal(format!(\"failed to find {} in path source\", id)))\n    }\n\n    fn finish_download(&mut self, _id: PackageId, _data: Vec<u8>) -> CargoResult<Package> {\n        panic!(\"no download should have started\")\n    }\n\n    fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {\n        let (max, max_path) = self.last_modified_file(pkg)?;\n        // Note that we try to strip the prefix of this package to get a\n        // relative path to ensure that the fingerprint remains consistent\n        // across entire project directory renames.\n        let max_path = max_path.strip_prefix(&self.path).unwrap_or(&max_path);\n        Ok(format!(\"{} ({})\", max, max_path.display()))\n    }\n\n    fn describe(&self) -> String {\n        match self.source_id.url().to_file_path() {\n            Ok(path) => path.display().to_string(),\n            Err(_) => self.source_id.to_string(),\n        }\n    }\n\n    fn add_to_yanked_whitelist(&mut self, _pkgs: &[PackageId]) {}\n\n    fn is_yanked(&mut self, _pkg: PackageId) -> Poll<CargoResult<bool>> {\n        Poll::Ready(Ok(false))\n    }\n\n    fn block_until_ready(&mut self) -> CargoResult<()> {\n        self.load()\n    }\n\n    fn invalidate_cache(&mut self) {\n        // Path source has no local cache.\n    }\n\n    fn set_quiet(&mut self, _quiet: bool) {\n        // Path source does not display status\n    }\n}\n\n/// Type that abstracts over [`gix::dir::entry::Kind`] and [`fs::FileType`].\n#[derive(Debug, Clone, Copy)]\nenum FileType {\n    File { maybe_symlink: bool },\n    Dir,\n    Symlink,\n    Other,\n}\n\nimpl From<fs::FileType> for FileType {\n    fn from(value: fs::FileType) -> Self {\n        if value.is_file() {\n            FileType::File {\n                maybe_symlink: false,\n            }\n        } else if value.is_dir() {\n            FileType::Dir\n        } else if value.is_symlink() {\n            FileType::Symlink\n        } else {\n            FileType::Other\n        }\n    }\n}\n\nimpl From<gix::dir::entry::Kind> for FileType {\n    fn from(value: gix::dir::entry::Kind) -> Self {\n        use gix::dir::entry::Kind;\n        match value {\n            Kind::Untrackable => FileType::Other,\n            Kind::File => FileType::File {\n                maybe_symlink: false,\n            },\n            Kind::Symlink => FileType::Symlink,\n            Kind::Directory | Kind::Repository => FileType::Dir,\n        }\n    }\n}\n\n/// [`PathBuf`] with extra metadata.\n#[derive(Clone, Debug)]\npub struct PathEntry {\n    path: PathBuf,\n    ty: FileType,\n    /// Whether this path was visited when traversing a symlink directory.\n    under_symlink_dir: bool,\n}\n\nimpl PathEntry {\n    pub fn into_path_buf(self) -> PathBuf {\n        self.path\n    }\n\n    /// Similar to [`std::path::Path::is_file`]\n    /// but doesn't follow the symbolic link nor make any system call\n    pub fn is_file(&self) -> bool {\n        matches!(self.ty, FileType::File { .. })\n    }\n\n    /// Similar to [`std::path::Path::is_dir`]\n    /// but doesn't follow the symbolic link nor make any system call\n    pub fn is_dir(&self) -> bool {\n        matches!(self.ty, FileType::Dir)\n    }\n\n    /// Similar to [`std::path::Path::is_symlink`]\n    /// but doesn't follow the symbolic link nor make any system call\n    ///\n    /// If the path is not a symlink but under a symlink parent directory,\n    /// this will return false.\n    /// See [`PathEntry::is_symlink_or_under_symlink`] for an alternative.\n    pub fn is_symlink(&self) -> bool {\n        matches!(self.ty, FileType::Symlink)\n    }\n\n    /// Whether a path is a symlink or a path under a symlink directory.\n    ///\n    /// Use [`PathEntry::is_symlink`] to get the exact file type of the path only.\n    pub fn is_symlink_or_under_symlink(&self) -> bool {\n        self.is_symlink() || self.under_symlink_dir\n    }\n\n    /// Whether this path might be a plain text symlink.\n    ///\n    /// Git may check out symlinks as plain text files that contain the link texts,\n    /// when either `core.symlinks` is `false`, or on Windows.\n    pub fn maybe_plain_text_symlink(&self) -> bool {\n        matches!(\n            self.ty,\n            FileType::File {\n                maybe_symlink: true\n            }\n        )\n    }\n}\n\nimpl std::ops::Deref for PathEntry {\n    type Target = Path;\n\n    fn deref(&self) -> &Self::Target {\n        self.path.as_path()\n    }\n}\n\nimpl AsRef<PathBuf> for PathEntry {\n    fn as_ref(&self) -> &PathBuf {\n        &self.path\n    }\n}\n\nfn first_package<'p>(\n    pkg_id: PackageId,\n    pkgs: &'p Vec<Package>,\n    warned_duplicate: &mut HashSet<PackageId>,\n    gctx: &GlobalContext,\n) -> &'p Package {\n    if pkgs.len() != 1 && warned_duplicate.insert(pkg_id) {\n        let ignored = pkgs[1..]\n            .iter()\n            // We can assume a package with publish = false isn't intended to be seen\n            // by users so we can hide the warning about those since the user is unlikely\n            // to care about those cases.\n            .filter(|pkg| pkg.publish().is_none())\n            .collect::<Vec<_>>();\n        if !ignored.is_empty() {\n            use std::fmt::Write as _;\n\n            let plural = if ignored.len() == 1 { \"\" } else { \"s\" };\n            let mut msg = String::new();\n            let _ = writeln!(&mut msg, \"skipping duplicate package{plural} `{pkg_id}`:\");\n            for ignored in ignored {\n                let manifest_path = ignored.manifest_path().display();\n                let _ = writeln!(&mut msg, \"  {manifest_path}\");\n            }\n            let manifest_path = pkgs[0].manifest_path().display();\n            let _ = writeln!(&mut msg, \"in favor of {manifest_path}\");\n            let _ = gctx.shell().warn(msg);\n        }\n    }\n    &pkgs[0]\n}\n\n/// List all files relevant to building this package inside this source.\n///\n/// This function will use the appropriate methods to determine the\n/// set of files underneath this source's directory which are relevant for\n/// building `pkg`.\n///\n/// The basic assumption of this method is that all files in the directory\n/// are relevant for building this package, but it also contains logic to\n/// use other methods like `.gitignore`, `package.include`, or\n/// `package.exclude` to filter the list of files.\npub fn list_files(pkg: &Package, gctx: &GlobalContext) -> CargoResult<Vec<PathEntry>> {\n    _list_files(pkg, gctx).with_context(|| {\n        format!(\n            \"failed to determine list of files in {}\",\n            pkg.root().display()\n        )\n    })\n}\n\n/// See [`PathSource::list_files`].\nfn _list_files(pkg: &Package, gctx: &GlobalContext) -> CargoResult<Vec<PathEntry>> {\n    let root = pkg.root();\n    let no_include_option = pkg.manifest().include().is_empty();\n    let git_repo = if no_include_option {\n        discover_gix_repo(root)?\n    } else {\n        None\n    };\n\n    let mut exclude_builder = GitignoreBuilder::new(root);\n    if no_include_option && git_repo.is_none() {\n        // no include option and not git repo discovered (see rust-lang/cargo#7183).\n        exclude_builder.add_line(None, \".*\")?;\n    }\n    for rule in pkg.manifest().exclude() {\n        exclude_builder.add_line(None, rule)?;\n    }\n    let ignore_exclude = exclude_builder.build()?;\n\n    let mut include_builder = GitignoreBuilder::new(root);\n    for rule in pkg.manifest().include() {\n        include_builder.add_line(None, rule)?;\n    }\n    let ignore_include = include_builder.build()?;\n\n    let ignore_should_package = |relative_path: &Path, is_dir: bool| {\n        // \"Include\" and \"exclude\" options are mutually exclusive.\n        if no_include_option {\n            !ignore_exclude\n                .matched_path_or_any_parents(relative_path, is_dir)\n                .is_ignore()\n        } else {\n            if is_dir {\n                // Generally, include directives don't list every\n                // directory (nor should they!). Just skip all directory\n                // checks, and only check files.\n                return true;\n            }\n            ignore_include\n                .matched_path_or_any_parents(relative_path, /* is_dir */ false)\n                .is_ignore()\n        }\n    };\n\n    let filter = |path: &Path, is_dir: bool| {\n        let Ok(relative_path) = path.strip_prefix(root) else {\n            return false;\n        };\n\n        let rel = relative_path.as_os_str();\n        if rel == \"Cargo.lock\" || rel == \"Cargo.toml\" {\n            return true;\n        }\n\n        ignore_should_package(relative_path, is_dir)\n    };\n\n    // Attempt Git-prepopulate only if no `include` (see rust-lang/cargo#4135).\n    if no_include_option {\n        if let Some(repo) = git_repo {\n            return list_files_gix(pkg, &repo, &filter, gctx);\n        }\n    }\n    let mut ret = Vec::new();\n    list_files_walk(pkg.root(), &mut ret, true, &filter, gctx)?;\n    Ok(ret)\n}\n\n/// Returns [`Some(gix::Repository)`](gix::Repository) if the discovered repository\n/// (searched upwards from `root`) contains a tracked `<root>/Cargo.toml`.\n/// Otherwise, the caller should fall back on full file list.\nfn discover_gix_repo(root: &Path) -> CargoResult<Option<gix::Repository>> {\n    let repo = match gix::ThreadSafeRepository::discover(root) {\n        Ok(repo) => repo.to_thread_local(),\n        Err(e) => {\n            tracing::debug!(\n                \"could not discover git repo at or above {}: {}\",\n                root.display(),\n                e\n            );\n            return Ok(None);\n        }\n    };\n    let index = repo\n        .index_or_empty()\n        .with_context(|| format!(\"failed to open git index at {}\", repo.path().display()))?;\n    let repo_root = repo.workdir().ok_or_else(|| {\n        anyhow::format_err!(\n            \"did not expect repo at {} to be bare\",\n            repo.path().display()\n        )\n    })?;\n    let repo_relative_path = match paths::strip_prefix_canonical(root, repo_root) {\n        Ok(p) => p,\n        Err(e) => {\n            warn!(\n                \"cannot determine if path `{:?}` is in git repo `{:?}`: {:?}\",\n                root, repo_root, e\n            );\n            return Ok(None);\n        }\n    };\n    let manifest_path = gix::path::join_bstr_unix_pathsep(\n        gix::path::to_unix_separators_on_windows(gix::path::into_bstr(repo_relative_path)),\n        \"Cargo.toml\",\n    );\n    if index.entry_index_by_path(&manifest_path).is_ok() {\n        return Ok(Some(repo));\n    }\n    // Package Cargo.toml is not in git, don't use git to guide our selection.\n    Ok(None)\n}\n\n/// Lists files relevant to building this package inside this source by\n/// traversing the git working tree, while avoiding ignored files.\n///\n/// This looks into Git sub-repositories as well, resolving them to individual files.\n/// Symlinks to directories will also be resolved, but walked as repositories if they\n/// point to one to avoid picking up `.git` directories.\nfn list_files_gix(\n    pkg: &Package,\n    repo: &gix::Repository,\n    filter: &dyn Fn(&Path, bool) -> bool,\n    gctx: &GlobalContext,\n) -> CargoResult<Vec<PathEntry>> {\n    debug!(\"list_files_gix {}\", pkg.package_id());\n    let options = repo\n        .dirwalk_options()?\n        .emit_untracked(gix::dir::walk::EmissionMode::Matching)\n        .emit_ignored(None)\n        .emit_tracked(true)\n        .recurse_repositories(false)\n        .symlinks_to_directories_are_ignored_like_directories(true)\n        .emit_empty_directories(false);\n    let index = repo.index_or_empty()?;\n    let root = repo\n        .workdir()\n        .ok_or_else(|| anyhow::format_err!(\"can't list files on a bare repository\"))?;\n    assert!(\n        root.is_absolute(),\n        \"BUG: paths used internally are absolute, and the repo inherits that\"\n    );\n\n    let pkg_path = pkg.root();\n    let repo_relative_pkg_path = pkg_path.strip_prefix(root).unwrap_or(Path::new(\"\"));\n    let target_prefix = gix::path::to_unix_separators_on_windows(gix::path::into_bstr(\n        repo_relative_pkg_path.join(\"target/\"),\n    ));\n    let package_prefix =\n        gix::path::to_unix_separators_on_windows(gix::path::into_bstr(repo_relative_pkg_path));\n\n    let pathspec = {\n        // Include the package root.\n        let mut include = BString::from(\":(top)\");\n        include.push_str(package_prefix.as_ref());\n\n        // Exclude the target directory.\n        let mut exclude = BString::from(\":!(exclude,top)\");\n        exclude.push_str(target_prefix.as_ref());\n\n        vec![include, exclude]\n    };\n\n    let mut files = Vec::<PathEntry>::new();\n    let mut subpackages_found = Vec::new();\n    for item in repo\n        .dirwalk_iter(index.clone(), pathspec, Default::default(), options)?\n        .filter(|res| {\n            // Don't include Cargo.lock if it is untracked. Packaging will\n            // generate a new one as needed.\n            // Also don't include untrackable directory entries, like FIFOs.\n            res.as_ref().map_or(true, |item| {\n                item.entry.disk_kind != Some(gix::dir::entry::Kind::Untrackable)\n                    && !(item.entry.status == Status::Untracked\n                        && item.entry.rela_path == \"Cargo.lock\")\n            })\n        })\n        .map(|res| {\n            res.map(|item| {\n                // Assumption: if a file tracked as a symlink in Git index, and\n                // the actual file type on disk is file, then it might be a\n                // plain text file symlink.\n                // There are exceptions like the file has changed from a symlink\n                // to a real text file, but hasn't been committed to Git index.\n                // Exceptions may be rare so we're okay with this now.\n                let maybe_plain_text_symlink = item.entry.index_kind\n                    == Some(gix::dir::entry::Kind::Symlink)\n                    && item.entry.disk_kind == Some(gix::dir::entry::Kind::File);\n                (\n                    item.entry.rela_path,\n                    item.entry.disk_kind,\n                    maybe_plain_text_symlink,\n                )\n            })\n        })\n        .chain(\n            // Append entries that might be tracked in `<pkg_root>/target/`.\n            index\n                .prefixed_entries(target_prefix.as_ref())\n                .unwrap_or_default()\n                .iter()\n                .filter(|entry| {\n                    // probably not needed as conflicts prevent this to run, but let's be explicit.\n                    entry.stage() == Stage::Unconflicted\n                })\n                .map(|entry| {\n                    (\n                        entry.path(&index).to_owned(),\n                        // Do not trust what's recorded in the index, enforce checking the disk.\n                        // This traversal is not part of a `status()`, and tracking things in `target/`\n                        // is rare.\n                        None,\n                        false,\n                    )\n                })\n                .map(Ok),\n        )\n    {\n        let (rela_path, kind, maybe_plain_text_symlink) = item?;\n        let file_path = root.join(gix::path::from_bstr(rela_path));\n        if file_path.file_name().and_then(|name| name.to_str()) == Some(\"Cargo.toml\") {\n            // Keep track of all sub-packages found and also strip out all\n            // matches we've found so far. Note, though, that if we find\n            // our own `Cargo.toml`, we keep going.\n            let path = file_path.parent().unwrap();\n            if path != pkg_path {\n                debug!(\"subpackage found: {}\", path.display());\n                files.retain(|p| !p.starts_with(path));\n                subpackages_found.push(path.to_path_buf());\n                continue;\n            }\n        }\n\n        // If this file is part of any other sub-package we've found so far,\n        // skip it.\n        if subpackages_found.iter().any(|p| file_path.starts_with(p)) {\n            continue;\n        }\n\n        let is_dir = kind.map_or(false, |kind| {\n            if kind == gix::dir::entry::Kind::Symlink {\n                // Symlinks must be checked to see if they point to a directory\n                // we should traverse.\n                file_path.is_dir()\n            } else {\n                kind.is_dir()\n            }\n        });\n        if is_dir {\n            // This could be a submodule, or a sub-repository. In any case, we prefer to walk\n            // it with git-support to leverage ignored files and to avoid pulling in entire\n            // .git repositories.\n            match gix::open(&file_path) {\n                Ok(sub_repo) => {\n                    files.extend(list_files_gix(pkg, &sub_repo, filter, gctx)?);\n                }\n                Err(_) => {\n                    list_files_walk(&file_path, &mut files, false, filter, gctx)?;\n                }\n            }\n        } else if (filter)(&file_path, is_dir) {\n            assert!(!is_dir);\n            trace!(\"  found {}\", file_path.display());\n            let ty = match kind.map(Into::into) {\n                Some(FileType::File { .. }) => FileType::File {\n                    maybe_symlink: maybe_plain_text_symlink,\n                },\n                Some(ty) => ty,\n                None => FileType::Other,\n            };\n            files.push(PathEntry {\n                path: file_path,\n                ty,\n                // Git index doesn't include files from symlink directory,\n                // symlink dirs are handled in `list_files_walk`.\n                under_symlink_dir: false,\n            });\n        }\n    }\n\n    return Ok(files);\n}\n\n/// Lists files relevant to building this package inside this source by\n/// walking the filesystem from the package root path.\n///\n/// This is a fallback for [`list_files_gix`] when the package\n/// is not tracked under a Git repository.\nfn list_files_walk(\n    path: &Path,\n    ret: &mut Vec<PathEntry>,\n    is_root: bool,\n    filter: &dyn Fn(&Path, bool) -> bool,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let walkdir = WalkDir::new(path)\n        .follow_links(true)\n        // While this is the default, set it explicitly.\n        // We need walkdir to visit the directory tree in depth-first order,\n        // so we can ensure a path visited later be under a certain directory.\n        .contents_first(false)\n        .into_iter()\n        .filter_entry(|entry| {\n            let path = entry.path();\n            let at_root = is_root && entry.depth() == 0;\n            let is_dir = entry.file_type().is_dir();\n\n            if !at_root && !filter(path, is_dir) {\n                return false;\n            }\n\n            if !is_dir {\n                return true;\n            }\n\n            // Don't recurse into any sub-packages that we have.\n            if !at_root && path.join(\"Cargo.toml\").exists() {\n                return false;\n            }\n\n            // Skip root Cargo artifacts.\n            if is_root\n                && entry.depth() == 1\n                && path.file_name().and_then(|s| s.to_str()) == Some(\"target\")\n            {\n                return false;\n            }\n\n            true\n        });\n\n    let mut current_symlink_dir = None;\n    for entry in walkdir {\n        match entry {\n            Ok(entry) => {\n                let file_type = entry.file_type();\n\n                match current_symlink_dir.as_ref() {\n                    Some(dir) if entry.path().starts_with(dir) => {\n                        // Still walk under the same parent symlink dir, so keep it\n                    }\n                    Some(_) | None => {\n                        // Not under any parent symlink dir, update the current one.\n                        current_symlink_dir = if file_type.is_dir() && entry.path_is_symlink() {\n                            Some(entry.path().to_path_buf())\n                        } else {\n                            None\n                        };\n                    }\n                }\n\n                if file_type.is_file() || file_type.is_symlink() {\n                    // We follow_links(true) here so check if entry was created from a symlink\n                    let ty = if entry.path_is_symlink() {\n                        FileType::Symlink\n                    } else {\n                        file_type.into()\n                    };\n                    ret.push(PathEntry {\n                        path: entry.into_path(),\n                        ty,\n                        // This rely on contents_first(false), which walks in depth-first order\n                        under_symlink_dir: current_symlink_dir.is_some(),\n                    });\n                }\n            }\n            Err(err) if err.loop_ancestor().is_some() => {\n                gctx.shell().warn(err)?;\n            }\n            Err(err) => match err.path() {\n                // If an error occurs with a path, filter it again.\n                // If it is excluded, Just ignore it in this case.\n                // See issue rust-lang/cargo#10917\n                Some(path) if !filter(path, path.is_dir()) => {}\n                // Otherwise, simply recover from it.\n                // Don't worry about error skipping here, the callers would\n                // still hit the IO error if they do access it thereafter.\n                Some(path) => ret.push(PathEntry {\n                    path: path.to_path_buf(),\n                    ty: FileType::Other,\n                    under_symlink_dir: false,\n                }),\n                None => return Err(err.into()),\n            },\n        }\n    }\n\n    Ok(())\n}\n\n/// Gets the last modified file in a package.\nfn last_modified_file(\n    path: &Path,\n    pkg: &Package,\n    gctx: &GlobalContext,\n) -> CargoResult<(FileTime, PathBuf)> {\n    let mut max = FileTime::zero();\n    let mut max_path = PathBuf::new();\n    for file in list_files(pkg, gctx).with_context(|| {\n        format!(\n            \"failed to determine the most recently modified file in {}\",\n            pkg.root().display()\n        )\n    })? {\n        // An `fs::stat` error here is either because path is a\n        // broken symlink, a permissions error, or a race\n        // condition where this path was `rm`-ed -- either way,\n        // we can ignore the error and treat the path's `mtime`\n        // as `0`.\n        let mtime = paths::mtime(&file).unwrap_or_else(|_| FileTime::zero());\n        if mtime > max {\n            max = mtime;\n            max_path = file.into_path_buf();\n        }\n    }\n    trace!(\"last modified file {}: {}\", path.display(), max);\n    Ok((max, max_path))\n}\n\nfn read_packages(\n    path: &Path,\n    source_id: SourceId,\n    gctx: &GlobalContext,\n) -> CargoResult<HashMap<PackageId, Vec<Package>>> {\n    let mut all_packages = HashMap::new();\n    let mut visited = HashSet::<PathBuf>::new();\n    let mut errors = Vec::<anyhow::Error>::new();\n\n    trace!(\n        \"looking for root package: {}, source_id={}\",\n        path.display(),\n        source_id\n    );\n\n    walk(path, &mut |dir| {\n        trace!(\"looking for child package: {}\", dir.display());\n\n        // Don't recurse into hidden/dot directories unless we're at the toplevel\n        if dir != path {\n            let name = dir.file_name().and_then(|s| s.to_str());\n            if name.map(|s| s.starts_with('.')) == Some(true) {\n                return Ok(false);\n            }\n\n            // Don't automatically discover packages across git submodules\n            if dir.join(\".git\").exists() {\n                return Ok(false);\n            }\n        }\n\n        // Don't ever look at target directories\n        if dir.file_name().and_then(|s| s.to_str()) == Some(\"target\")\n            && has_manifest(dir.parent().unwrap())\n        {\n            return Ok(false);\n        }\n\n        if has_manifest(dir) {\n            read_nested_packages(\n                dir,\n                &mut all_packages,\n                source_id,\n                gctx,\n                &mut visited,\n                &mut errors,\n            )?;\n        }\n        Ok(true)\n    })?;\n\n    if all_packages.is_empty() {\n        match errors.pop() {\n            Some(err) => Err(err),\n            None => {\n                if find_project_manifest_exact(path, \"cargo.toml\").is_ok() {\n                    Err(anyhow::format_err!(\n                        \"could not find `Cargo.toml` in `{}`\nhelp: found `cargo.toml`, consider renaming it to `Cargo.toml`\",\n                        path.display()\n                    ))\n                } else {\n                    Err(anyhow::format_err!(\n                        \"could not find `Cargo.toml` in `{}`\",\n                        path.display()\n                    ))\n                }\n            }\n        }\n    } else {\n        Ok(all_packages)\n    }\n}\n\nfn nested_paths(manifest: &Manifest) -> Vec<PathBuf> {\n    let mut nested_paths = Vec::new();\n    let normalized = manifest.normalized_toml();\n    let dependencies = normalized\n        .dependencies\n        .iter()\n        .chain(normalized.build_dependencies())\n        .chain(normalized.dev_dependencies())\n        .chain(\n            normalized\n                .target\n                .as_ref()\n                .into_iter()\n                .flat_map(|t| t.values())\n                .flat_map(|t| {\n                    t.dependencies\n                        .iter()\n                        .chain(t.build_dependencies())\n                        .chain(t.dev_dependencies())\n                }),\n        );\n    for dep_table in dependencies {\n        for dep in dep_table.values() {\n            let cargo_util_schemas::manifest::InheritableDependency::Value(dep) = dep else {\n                continue;\n            };\n            let cargo_util_schemas::manifest::TomlDependency::Detailed(dep) = dep else {\n                continue;\n            };\n            let Some(path) = dep.path.as_ref() else {\n                continue;\n            };\n            nested_paths.push(PathBuf::from(path.as_str()));\n        }\n    }\n    nested_paths\n}\n\nfn walk(path: &Path, callback: &mut dyn FnMut(&Path) -> CargoResult<bool>) -> CargoResult<()> {\n    if !callback(path)? {\n        trace!(\"not processing {}\", path.display());\n        return Ok(());\n    }\n\n    // Ignore any permission denied errors because temporary directories\n    // can often have some weird permissions on them.\n    let dirs = match fs::read_dir(path) {\n        Ok(dirs) => dirs,\n        Err(ref e) if e.kind() == io::ErrorKind::PermissionDenied => return Ok(()),\n        Err(e) => {\n            let cx = format!(\"failed to read directory `{}`\", path.display());\n            let e = anyhow::Error::from(e);\n            return Err(e.context(cx));\n        }\n    };\n    let mut dirs = dirs.collect::<Vec<_>>();\n    dirs.sort_unstable_by_key(|d| d.as_ref().ok().map(|d| d.file_name()));\n    for dir in dirs {\n        let dir = dir?;\n        if dir.file_type()?.is_dir() {\n            walk(&dir.path(), callback)?;\n        }\n    }\n    Ok(())\n}\n\nfn has_manifest(path: &Path) -> bool {\n    find_project_manifest_exact(path, \"Cargo.toml\").is_ok()\n}\n\nfn read_nested_packages(\n    path: &Path,\n    all_packages: &mut HashMap<PackageId, Vec<Package>>,\n    source_id: SourceId,\n    gctx: &GlobalContext,\n    visited: &mut HashSet<PathBuf>,\n    errors: &mut Vec<anyhow::Error>,\n) -> CargoResult<()> {\n    if !visited.insert(path.to_path_buf()) {\n        return Ok(());\n    }\n\n    let manifest_path = find_project_manifest_exact(path, \"Cargo.toml\")?;\n\n    let manifest = match read_manifest(&manifest_path, source_id, gctx) {\n        Err(err) => {\n            // Ignore malformed manifests found on git repositories\n            //\n            // git source try to find and read all manifests from the repository\n            // but since it's not possible to exclude folders from this search\n            // it's safer to ignore malformed manifests to avoid\n            //\n            // TODO: Add a way to exclude folders?\n            info!(\n                \"skipping malformed package found at `{}`\",\n                path.to_string_lossy()\n            );\n            errors.push(err.into());\n            return Ok(());\n        }\n        Ok(tuple) => tuple,\n    };\n\n    let manifest = match manifest {\n        EitherManifest::Real(manifest) => manifest,\n        EitherManifest::Virtual(..) => return Ok(()),\n    };\n    let nested = nested_paths(&manifest);\n    let pkg = Package::new(manifest, &manifest_path);\n\n    let pkg_id = pkg.package_id();\n    all_packages.entry(pkg_id).or_default().push(pkg);\n\n    // Registry sources are not allowed to have `path=` dependencies because\n    // they're all translated to actual registry dependencies.\n    //\n    // We normalize the path here ensure that we don't infinitely walk around\n    // looking for crates. By normalizing we ensure that we visit this crate at\n    // most once.\n    //\n    // TODO: filesystem/symlink implications?\n    if !source_id.is_registry() {\n        for p in nested.iter() {\n            let path = paths::normalize_path(&path.join(p));\n            let result =\n                read_nested_packages(&path, all_packages, source_id, gctx, visited, errors);\n            // Ignore broken manifests found on git repositories.\n            //\n            // A well formed manifest might still fail to load due to reasons\n            // like referring to a \"path\" that requires an extra build step.\n            //\n            // See https://github.com/rust-lang/cargo/issues/6822.\n            if let Err(err) = result {\n                if source_id.is_git() {\n                    info!(\n                        \"skipping nested package found at `{}`: {:?}\",\n                        path.display(),\n                        &err,\n                    );\n                    errors.push(err);\n                } else {\n                    return Err(err);\n                }\n            }\n        }\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/sources/registry/download.rs",
    "content": "//! Shared download logic between [`HttpRegistry`] and [`RemoteRegistry`].\n//!\n//! [`HttpRegistry`]: super::http_remote::HttpRegistry\n//! [`RemoteRegistry`]: super::remote::RemoteRegistry\n\nuse crate::util::interning::InternedString;\nuse anyhow::Context as _;\nuse cargo_credential::Operation;\nuse cargo_util::Sha256;\nuse cargo_util::registry::make_dep_path;\n\nuse crate::core::PackageId;\nuse crate::core::global_cache_tracker;\nuse crate::sources::registry::MaybeLock;\nuse crate::sources::registry::RegistryConfig;\nuse crate::util::auth;\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::errors::CargoResult;\nuse crate::util::{Filesystem, GlobalContext};\nuse std::fmt::Write as FmtWrite;\nuse std::fs::{self, File, OpenOptions};\nuse std::io::SeekFrom;\nuse std::io::prelude::*;\nuse std::str;\n\nconst CRATE_TEMPLATE: &str = \"{crate}\";\nconst VERSION_TEMPLATE: &str = \"{version}\";\nconst PREFIX_TEMPLATE: &str = \"{prefix}\";\nconst LOWER_PREFIX_TEMPLATE: &str = \"{lowerprefix}\";\nconst CHECKSUM_TEMPLATE: &str = \"{sha256-checksum}\";\n\n/// Checks if `pkg` is downloaded and ready under the directory at `cache_path`.\n/// If not, returns a URL to download it from.\n///\n/// This is primarily called by [`RegistryData::download`](super::RegistryData::download).\npub(super) fn download(\n    cache_path: &Filesystem,\n    gctx: &GlobalContext,\n    encoded_registry_name: InternedString,\n    pkg: PackageId,\n    checksum: &str,\n    registry_config: RegistryConfig,\n) -> CargoResult<MaybeLock> {\n    let path = cache_path.join(&pkg.tarball_name());\n    let path = gctx.assert_package_cache_locked(CacheLockMode::DownloadExclusive, &path);\n\n    // Attempt to open a read-only copy first to avoid an exclusive write\n    // lock and also work with read-only filesystems. Note that we check the\n    // length of the file like below to handle interrupted downloads.\n    //\n    // If this fails then we fall through to the exclusive path where we may\n    // have to redownload the file.\n    if let Ok(dst) = File::open(path) {\n        let meta = dst.metadata()?;\n        if meta.len() > 0 {\n            gctx.deferred_global_last_use()?.mark_registry_crate_used(\n                global_cache_tracker::RegistryCrate {\n                    encoded_registry_name,\n                    crate_filename: pkg.tarball_name().into(),\n                    size: meta.len(),\n                },\n            );\n            return Ok(MaybeLock::Ready(dst));\n        }\n    }\n\n    let mut url = registry_config.dl;\n    if !url.contains(CRATE_TEMPLATE)\n        && !url.contains(VERSION_TEMPLATE)\n        && !url.contains(PREFIX_TEMPLATE)\n        && !url.contains(LOWER_PREFIX_TEMPLATE)\n        && !url.contains(CHECKSUM_TEMPLATE)\n    {\n        // Original format before customizing the download URL was supported.\n        write!(url, \"/{}/{}/download\", pkg.name(), pkg.version()).unwrap();\n    } else {\n        let prefix = make_dep_path(&pkg.name(), true);\n        url = url\n            .replace(CRATE_TEMPLATE, &*pkg.name())\n            .replace(VERSION_TEMPLATE, &pkg.version().to_string())\n            .replace(PREFIX_TEMPLATE, &prefix)\n            .replace(LOWER_PREFIX_TEMPLATE, &prefix.to_lowercase())\n            .replace(CHECKSUM_TEMPLATE, checksum);\n    }\n\n    let authorization = if registry_config.auth_required {\n        Some(auth::auth_token(\n            gctx,\n            &pkg.source_id(),\n            None,\n            Operation::Read,\n            vec![],\n            true,\n        )?)\n    } else {\n        None\n    };\n\n    Ok(MaybeLock::Download {\n        url,\n        descriptor: pkg.to_string(),\n        authorization: authorization,\n    })\n}\n\n/// Verifies the integrity of `data` with `checksum` and persists it under the\n/// directory at `cache_path`.\n///\n/// This is primarily called by [`RegistryData::finish_download`](super::RegistryData::finish_download).\npub(super) fn finish_download(\n    cache_path: &Filesystem,\n    gctx: &GlobalContext,\n    encoded_registry_name: InternedString,\n    pkg: PackageId,\n    checksum: &str,\n    data: &[u8],\n) -> CargoResult<File> {\n    // Verify what we just downloaded\n    let actual = Sha256::new().update(data).finish_hex();\n    if actual != checksum {\n        anyhow::bail!(\"failed to verify the checksum of `{}`\", pkg)\n    }\n    gctx.deferred_global_last_use()?.mark_registry_crate_used(\n        global_cache_tracker::RegistryCrate {\n            encoded_registry_name,\n            crate_filename: pkg.tarball_name().into(),\n            size: data.len() as u64,\n        },\n    );\n\n    cache_path.create_dir()?;\n    let path = cache_path.join(&pkg.tarball_name());\n    let path = gctx.assert_package_cache_locked(CacheLockMode::DownloadExclusive, &path);\n    let mut dst = OpenOptions::new()\n        .create(true)\n        .read(true)\n        .write(true)\n        .open(&path)\n        .with_context(|| format!(\"failed to open `{}`\", path.display()))?;\n    let meta = dst.metadata()?;\n    if meta.len() > 0 {\n        return Ok(dst);\n    }\n\n    dst.write_all(data)?;\n    dst.seek(SeekFrom::Start(0))?;\n    Ok(dst)\n}\n\n/// Checks if a tarball of `pkg` has been already downloaded under the\n/// directory at `cache_path`.\n///\n/// This is primarily called by [`RegistryData::is_crate_downloaded`](super::RegistryData::is_crate_downloaded).\npub(super) fn is_crate_downloaded(\n    cache_path: &Filesystem,\n    gctx: &GlobalContext,\n    pkg: PackageId,\n) -> bool {\n    let path = cache_path.join(pkg.tarball_name());\n    let path = gctx.assert_package_cache_locked(CacheLockMode::DownloadExclusive, &path);\n    if let Ok(meta) = fs::metadata(path) {\n        return meta.len() > 0;\n    }\n    false\n}\n"
  },
  {
    "path": "src/cargo/sources/registry/http_remote.rs",
    "content": "//! Access to a HTTP-based crate registry. See [`HttpRegistry`] for details.\n\nuse crate::core::global_cache_tracker;\nuse crate::core::{PackageId, SourceId};\nuse crate::sources::registry::MaybeLock;\nuse crate::sources::registry::download;\nuse crate::sources::registry::{LoadResponse, RegistryConfig, RegistryData};\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::errors::{CargoResult, HttpNotSuccessful};\nuse crate::util::interning::InternedString;\nuse crate::util::network::http::http_handle;\nuse crate::util::network::retry::{Retry, RetryResult};\nuse crate::util::network::sleep::SleepTracker;\nuse crate::util::{Filesystem, GlobalContext, IntoUrl, Progress, ProgressStyle, auth};\nuse anyhow::Context as _;\nuse cargo_credential::Operation;\nuse cargo_util::paths;\nuse curl::easy::{Easy, List};\nuse curl::multi::{EasyHandle, Multi};\nuse std::cell::RefCell;\nuse std::collections::{HashMap, HashSet};\nuse std::fs::{self, File};\nuse std::io::ErrorKind;\nuse std::path::{Path, PathBuf};\nuse std::str;\nuse std::task::{Poll, ready};\nuse std::time::Duration;\nuse tracing::{debug, trace};\nuse url::Url;\n\n// HTTP headers\nconst ETAG: &'static str = \"etag\";\nconst LAST_MODIFIED: &'static str = \"last-modified\";\nconst WWW_AUTHENTICATE: &'static str = \"www-authenticate\";\nconst IF_NONE_MATCH: &'static str = \"if-none-match\";\nconst IF_MODIFIED_SINCE: &'static str = \"if-modified-since\";\n\nconst UNKNOWN: &'static str = \"Unknown\";\n\n/// A registry served by the HTTP-based registry API.\n///\n/// This type is primarily accessed through the [`RegistryData`] trait.\n///\n/// `HttpRegistry` implements the HTTP-based registry API outlined in [RFC 2789]. Read the RFC for\n/// the complete protocol, but _roughly_ the implementation loads each index file (e.g.,\n/// config.json or re/ge/regex) from an HTTP service rather than from a locally cloned git\n/// repository. The remote service can more or less be a static file server that simply serves the\n/// contents of the origin git repository.\n///\n/// Implemented naively, this leads to a significant amount of network traffic, as a lookup of any\n/// index file would need to check with the remote backend if the index file has changed. This\n/// cost is somewhat mitigated by the use of HTTP conditional fetches (`If-Modified-Since` and\n/// `If-None-Match` for `ETag`s) which can be efficiently handled by HTTP/2.\n///\n/// [RFC 2789]: https://github.com/rust-lang/rfcs/pull/2789\npub struct HttpRegistry<'gctx> {\n    /// The name of this source, a unique string (across all sources) used as\n    /// the directory name where its cached content is stored.\n    name: InternedString,\n    /// Path to the registry index (`$CARGO_HOME/registry/index/$REG-HASH`).\n    ///\n    /// To be fair, `HttpRegistry` doesn't store the registry index it\n    /// downloads on the file system, but other cached data like registry\n    /// configuration could be stored here.\n    index_path: Filesystem,\n    /// Path to the cache of `.crate` files (`$CARGO_HOME/registry/cache/$REG-HASH`).\n    cache_path: Filesystem,\n    /// The unique identifier of this registry source.\n    source_id: SourceId,\n    gctx: &'gctx GlobalContext,\n\n    /// Store the server URL without the protocol prefix (sparse+)\n    url: Url,\n\n    /// HTTP multi-handle for asynchronous/parallel requests.\n    multi: Multi,\n\n    /// Has the client requested a cache update?\n    ///\n    /// Only if they have do we double-check the freshness of each locally-stored index file.\n    requested_update: bool,\n\n    /// State for currently pending index downloads.\n    downloads: Downloads<'gctx>,\n\n    /// Does the config say that we can use HTTP multiplexing?\n    multiplexing: bool,\n\n    /// What paths have we already fetched since the last index update?\n    ///\n    /// We do not need to double-check any of these index files since we have already done so.\n    fresh: HashSet<PathBuf>,\n\n    /// Have we started to download any index files?\n    fetch_started: bool,\n\n    /// Cached registry configuration.\n    registry_config: Option<RegistryConfig>,\n\n    /// Should we include the authorization header?\n    auth_required: bool,\n\n    /// Url to get a token for the registry.\n    login_url: Option<Url>,\n\n    /// Headers received with an HTTP 401.\n    auth_error_headers: Vec<String>,\n\n    /// Disables status messages.\n    quiet: bool,\n}\n\n/// State for currently pending index file downloads.\nstruct Downloads<'gctx> {\n    /// When a download is started, it is added to this map. The key is a\n    /// \"token\" (see [`Download::token`]). It is removed once the download is\n    /// finished.\n    pending: HashMap<usize, (Download<'gctx>, EasyHandle)>,\n    /// Set of paths currently being downloaded.\n    /// This should stay in sync with the `pending` field.\n    pending_paths: HashSet<PathBuf>,\n    /// Downloads that have failed and are waiting to retry again later.\n    sleeping: SleepTracker<(Download<'gctx>, Easy)>,\n    /// The final result of each download.\n    results: HashMap<PathBuf, CargoResult<CompletedDownload>>,\n    /// The next ID to use for creating a token (see [`Download::token`]).\n    next: usize,\n    /// Progress bar.\n    progress: RefCell<Option<Progress<'gctx>>>,\n    /// Number of downloads that have successfully finished.\n    downloads_finished: usize,\n    /// Number of times the caller has requested blocking. This is used for\n    /// an estimate of progress.\n    blocking_calls: usize,\n}\n\n/// Represents a single index file download, including its progress and retry.\nstruct Download<'gctx> {\n    /// The token for this download, used as the key of the\n    /// [`Downloads::pending`] map and stored in [`EasyHandle`] as well.\n    token: usize,\n\n    /// The path of the package that we're downloading.\n    path: PathBuf,\n\n    /// Actual downloaded data, updated throughout the lifetime of this download.\n    data: RefCell<Vec<u8>>,\n\n    /// HTTP headers.\n    header_map: RefCell<Headers>,\n\n    /// Logic used to track retrying this download if it's a spurious failure.\n    retry: Retry<'gctx>,\n}\n\n/// HTTPS headers [`HttpRegistry`] cares about.\n#[derive(Default)]\nstruct Headers {\n    last_modified: Option<String>,\n    etag: Option<String>,\n    www_authenticate: Vec<String>,\n    /// All headers, including explicit headers above.\n    all: Vec<String>,\n}\n\n/// HTTP status code [`HttpRegistry`] cares about.\nenum StatusCode {\n    Success,\n    NotModified,\n    NotFound,\n    Unauthorized,\n}\n\n/// Represents a complete [`Download`] from an HTTP request.\n///\n/// Usually it is constructed in [`HttpRegistry::handle_completed_downloads`],\n/// and then returns to the caller of [`HttpRegistry::load()`].\nstruct CompletedDownload {\n    response_code: StatusCode,\n    data: Vec<u8>,\n    header_map: Headers,\n}\n\nimpl<'gctx> HttpRegistry<'gctx> {\n    /// Creates a HTTP-rebased remote registry for `source_id`.\n    ///\n    /// * `name` --- Name of a path segment where `.crate` tarballs and the\n    ///   registry index are stored. Expect to be unique.\n    pub fn new(\n        source_id: SourceId,\n        gctx: &'gctx GlobalContext,\n        name: &str,\n    ) -> CargoResult<HttpRegistry<'gctx>> {\n        let url = source_id.url().as_str();\n        // Ensure the url ends with a slash so we can concatenate paths.\n        if !url.ends_with('/') {\n            anyhow::bail!(\"sparse registry url must end in a slash `/`: {url}\")\n        }\n        assert!(source_id.is_sparse());\n        let url = url\n            .strip_prefix(\"sparse+\")\n            .expect(\"sparse registry needs sparse+ prefix\")\n            .into_url()\n            .expect(\"a url with the sparse+ stripped should still be valid\");\n\n        Ok(HttpRegistry {\n            name: name.into(),\n            index_path: gctx.registry_index_path().join(name),\n            cache_path: gctx.registry_cache_path().join(name),\n            source_id,\n            gctx,\n            url,\n            multi: Multi::new(),\n            multiplexing: false,\n            downloads: Downloads {\n                next: 0,\n                pending: HashMap::new(),\n                pending_paths: HashSet::new(),\n                sleeping: SleepTracker::new(),\n                results: HashMap::new(),\n                progress: RefCell::new(Some(Progress::with_style(\n                    \"Fetch\",\n                    ProgressStyle::Indeterminate,\n                    gctx,\n                ))),\n                downloads_finished: 0,\n                blocking_calls: 0,\n            },\n            fresh: HashSet::new(),\n            requested_update: false,\n            fetch_started: false,\n            registry_config: None,\n            auth_required: false,\n            login_url: None,\n            auth_error_headers: vec![],\n            quiet: false,\n        })\n    }\n\n    /// Splits HTTP `HEADER: VALUE` to a tuple.\n    fn handle_http_header(buf: &[u8]) -> Option<(&str, &str)> {\n        if buf.is_empty() {\n            return None;\n        }\n        let buf = std::str::from_utf8(buf).ok()?.trim_end();\n        // Don't let server sneak extra lines anywhere.\n        if buf.contains('\\n') {\n            return None;\n        }\n        let (tag, value) = buf.split_once(':')?;\n        let value = value.trim();\n        Some((tag, value))\n    }\n\n    /// Setup the necessary works before the first fetch gets started.\n    ///\n    /// This is a no-op if called more than one time.\n    fn start_fetch(&mut self) -> CargoResult<()> {\n        if self.fetch_started {\n            // We only need to run the setup code once.\n            return Ok(());\n        }\n        self.fetch_started = true;\n\n        // We've enabled the `http2` feature of `curl` in Cargo, so treat\n        // failures here as fatal as it would indicate a build-time problem.\n        self.multiplexing = self.gctx.http_config()?.multiplexing.unwrap_or(true);\n\n        self.multi\n            .pipelining(false, self.multiplexing)\n            .context(\"failed to enable multiplexing/pipelining in curl\")?;\n\n        // let's not flood the server with connections\n        self.multi.set_max_host_connections(2)?;\n\n        if !self.quiet {\n            self.gctx\n                .shell()\n                .status(\"Updating\", self.source_id.display_index())?;\n        }\n\n        Ok(())\n    }\n\n    /// Checks the results inside the [`HttpRegistry::multi`] handle, and\n    /// updates relevant state in [`HttpRegistry::downloads`] accordingly.\n    fn handle_completed_downloads(&mut self) -> CargoResult<()> {\n        assert_eq!(\n            self.downloads.pending.len(),\n            self.downloads.pending_paths.len()\n        );\n\n        // Collect the results from the Multi handle.\n        let results = {\n            let mut results = Vec::new();\n            let pending = &mut self.downloads.pending;\n            self.multi.messages(|msg| {\n                let token = msg.token().expect(\"failed to read token\");\n                let (_, handle) = &pending[&token];\n                if let Some(result) = msg.result_for(handle) {\n                    results.push((token, result));\n                };\n            });\n            results\n        };\n        for (token, result) in results {\n            let (mut download, handle) = self.downloads.pending.remove(&token).unwrap();\n            let was_present = self.downloads.pending_paths.remove(&download.path);\n            assert!(\n                was_present,\n                \"expected pending_paths to contain {:?}\",\n                download.path\n            );\n            let mut handle = self.multi.remove(handle)?;\n            let data = download.data.take();\n            let url = self.full_url(&download.path);\n            let result = match download.retry.r#try(|| {\n                result.with_context(|| format!(\"failed to download from `{}`\", url))?;\n                let code = handle.response_code()?;\n                // Keep this list of expected status codes in sync with the codes handled in `load`\n                let code = match code {\n                    200 => StatusCode::Success,\n                    304 => StatusCode::NotModified,\n                    401 => StatusCode::Unauthorized,\n                    404 | 410 | 451 => StatusCode::NotFound,\n                    _ => {\n                        return Err(HttpNotSuccessful::new_from_handle(\n                            &mut handle,\n                            &url,\n                            data,\n                            download.header_map.take().all,\n                        )\n                        .into());\n                    }\n                };\n                Ok((data, code))\n            }) {\n                RetryResult::Success((data, code)) => Ok(CompletedDownload {\n                    response_code: code,\n                    data,\n                    header_map: download.header_map.take(),\n                }),\n                RetryResult::Err(e) => Err(e),\n                RetryResult::Retry(sleep) => {\n                    debug!(target: \"network\", \"download retry {:?} for {sleep}ms\", download.path);\n                    self.downloads.sleeping.push(sleep, (download, handle));\n                    continue;\n                }\n            };\n\n            self.downloads.results.insert(download.path, result);\n            self.downloads.downloads_finished += 1;\n        }\n\n        self.downloads.tick()?;\n\n        Ok(())\n    }\n\n    /// Constructs the full URL to download a index file.\n    fn full_url(&self, path: &Path) -> String {\n        // self.url always ends with a slash.\n        format!(\"{}{}\", self.url, path.display())\n    }\n\n    /// Check if an index file of `path` is up-to-date.\n    ///\n    /// The `path` argument is the same as in [`RegistryData::load`].\n    fn is_fresh(&self, path: &Path) -> bool {\n        if !self.requested_update {\n            trace!(\n                \"using local {} as user did not request update\",\n                path.display()\n            );\n            true\n        } else if self.gctx.cli_unstable().no_index_update {\n            trace!(\"using local {} in no_index_update mode\", path.display());\n            true\n        } else if !self.gctx.network_allowed() {\n            trace!(\"using local {} in offline mode\", path.display());\n            true\n        } else if self.fresh.contains(path) {\n            trace!(\"using local {} as it was already fetched\", path.display());\n            true\n        } else {\n            debug!(\"checking freshness of {}\", path.display());\n            false\n        }\n    }\n\n    /// Get the cached registry configuration, if it exists.\n    fn config_cached(&mut self) -> CargoResult<Option<&RegistryConfig>> {\n        if self.registry_config.is_some() {\n            return Ok(self.registry_config.as_ref());\n        }\n        let config_json_path = self\n            .assert_index_locked(&self.index_path)\n            .join(RegistryConfig::NAME);\n        match fs::read(&config_json_path) {\n            Ok(raw_data) => match serde_json::from_slice(&raw_data) {\n                Ok(json) => {\n                    self.registry_config = Some(json);\n                }\n                Err(e) => tracing::debug!(\"failed to decode cached config.json: {}\", e),\n            },\n            Err(e) => {\n                if e.kind() != ErrorKind::NotFound {\n                    tracing::debug!(\"failed to read config.json cache: {}\", e)\n                }\n            }\n        }\n        Ok(self.registry_config.as_ref())\n    }\n\n    /// Get the registry configuration from either cache or remote.\n    fn config(&mut self) -> Poll<CargoResult<&RegistryConfig>> {\n        debug!(\"loading config\");\n        let index_path = self.assert_index_locked(&self.index_path);\n        let config_json_path = index_path.join(RegistryConfig::NAME);\n        if self.is_fresh(Path::new(RegistryConfig::NAME)) && self.config_cached()?.is_some() {\n            return Poll::Ready(Ok(self.registry_config.as_ref().unwrap()));\n        }\n\n        match ready!(self.load(Path::new(\"\"), Path::new(RegistryConfig::NAME), None)?) {\n            LoadResponse::Data {\n                raw_data,\n                index_version: _,\n            } => {\n                trace!(\"config loaded\");\n                self.registry_config = Some(serde_json::from_slice(&raw_data)?);\n                if paths::create_dir_all(&config_json_path.parent().unwrap()).is_ok() {\n                    if let Err(e) = fs::write(&config_json_path, &raw_data) {\n                        tracing::debug!(\"failed to write config.json cache: {}\", e);\n                    }\n                }\n                Poll::Ready(Ok(self.registry_config.as_ref().unwrap()))\n            }\n            LoadResponse::NotFound => {\n                Poll::Ready(Err(anyhow::anyhow!(\"config.json not found in registry\")))\n            }\n            LoadResponse::CacheValid => Poll::Ready(Err(crate::util::internal(\n                \"config.json is never stored in the index cache\",\n            ))),\n        }\n    }\n\n    /// Moves failed [`Download`]s that are ready to retry to the pending queue.\n    fn add_sleepers(&mut self) -> CargoResult<()> {\n        for (dl, handle) in self.downloads.sleeping.to_retry() {\n            let mut handle = self.multi.add(handle)?;\n            handle.set_token(dl.token)?;\n            let is_new = self.downloads.pending_paths.insert(dl.path.to_path_buf());\n            assert!(is_new, \"path queued for download more than once\");\n            let previous = self.downloads.pending.insert(dl.token, (dl, handle));\n            assert!(previous.is_none(), \"dl token queued more than once\");\n        }\n        Ok(())\n    }\n}\n\nimpl<'gctx> RegistryData for HttpRegistry<'gctx> {\n    fn prepare(&self) -> CargoResult<()> {\n        self.gctx\n            .deferred_global_last_use()?\n            .mark_registry_index_used(global_cache_tracker::RegistryIndex {\n                encoded_registry_name: self.name,\n            });\n        Ok(())\n    }\n\n    fn index_path(&self) -> &Filesystem {\n        &self.index_path\n    }\n\n    fn cache_path(&self) -> &Filesystem {\n        &self.cache_path\n    }\n\n    fn assert_index_locked<'a>(&self, path: &'a Filesystem) -> &'a Path {\n        self.gctx\n            .assert_package_cache_locked(CacheLockMode::DownloadExclusive, path)\n    }\n\n    fn is_updated(&self) -> bool {\n        self.requested_update\n    }\n\n    fn load(\n        &mut self,\n        _root: &Path,\n        path: &Path,\n        index_version: Option<&str>,\n    ) -> Poll<CargoResult<LoadResponse>> {\n        trace!(\"load: {}\", path.display());\n        if let Some(_token) = self.downloads.pending_paths.get(path) {\n            debug!(\"dependency is still pending: {}\", path.display());\n            return Poll::Pending;\n        }\n\n        if let Some(index_version) = index_version {\n            trace!(\n                \"local cache of {} is available at version `{}`\",\n                path.display(),\n                index_version\n            );\n            if self.is_fresh(path) {\n                return Poll::Ready(Ok(LoadResponse::CacheValid));\n            }\n        } else if self.fresh.contains(path) {\n            // We have no cached copy of this file, and we already downloaded it.\n            debug!(\n                \"cache did not contain previously downloaded file {}\",\n                path.display()\n            );\n            return Poll::Ready(Ok(LoadResponse::NotFound));\n        }\n\n        if !self.gctx.network_allowed() || self.gctx.cli_unstable().no_index_update {\n            // Return NotFound in offline mode when the file doesn't exist in the cache.\n            // If this results in resolution failure, the resolver will suggest\n            // removing the --offline flag.\n            return Poll::Ready(Ok(LoadResponse::NotFound));\n        }\n\n        if let Some(result) = self.downloads.results.remove(path) {\n            let result =\n                result.with_context(|| format!(\"download of {} failed\", path.display()))?;\n\n            let is_new = self.fresh.insert(path.to_path_buf());\n            assert!(\n                is_new,\n                \"downloaded the index file `{}` twice\",\n                path.display()\n            );\n\n            // The status handled here need to be kept in sync with the codes handled\n            // in `handle_completed_downloads`\n            match result.response_code {\n                StatusCode::Success => {\n                    let response_index_version = if let Some(etag) = result.header_map.etag {\n                        format!(\"{}: {}\", ETAG, etag)\n                    } else if let Some(lm) = result.header_map.last_modified {\n                        format!(\"{}: {}\", LAST_MODIFIED, lm)\n                    } else {\n                        UNKNOWN.to_string()\n                    };\n                    trace!(\"index file version: {}\", response_index_version);\n                    return Poll::Ready(Ok(LoadResponse::Data {\n                        raw_data: result.data,\n                        index_version: Some(response_index_version),\n                    }));\n                }\n                StatusCode::NotModified => {\n                    // Not Modified: the data in the cache is still the latest.\n                    if index_version.is_none() {\n                        return Poll::Ready(Err(anyhow::anyhow!(\n                            \"server said not modified (HTTP 304) when no local cache exists\"\n                        )));\n                    }\n                    return Poll::Ready(Ok(LoadResponse::CacheValid));\n                }\n                StatusCode::NotFound => {\n                    // The crate was not found or deleted from the registry.\n                    return Poll::Ready(Ok(LoadResponse::NotFound));\n                }\n                StatusCode::Unauthorized\n                    if !self.auth_required && path == Path::new(RegistryConfig::NAME) =>\n                {\n                    debug!(target: \"network\", \"re-attempting request for config.json with authorization included.\");\n                    self.fresh.remove(path);\n                    self.auth_required = true;\n\n                    // Look for a `www-authenticate` header with the `Cargo` scheme.\n                    for header in &result.header_map.www_authenticate {\n                        for challenge in http_auth::ChallengeParser::new(header) {\n                            match challenge {\n                                Ok(challenge) if challenge.scheme.eq_ignore_ascii_case(\"Cargo\") => {\n                                    // Look for the `login_url` parameter.\n                                    for (param, value) in challenge.params {\n                                        if param.eq_ignore_ascii_case(\"login_url\") {\n                                            self.login_url = Some(value.to_unescaped().into_url()?);\n                                        }\n                                    }\n                                }\n                                Ok(challenge) => {\n                                    debug!(target: \"network\", \"ignoring non-Cargo challenge: {}\", challenge.scheme)\n                                }\n                                Err(e) => {\n                                    debug!(target: \"network\", \"failed to parse challenge: {}\", e)\n                                }\n                            }\n                        }\n                    }\n                    self.auth_error_headers = result.header_map.all;\n                }\n                StatusCode::Unauthorized => {\n                    let err = Err(HttpNotSuccessful {\n                        code: 401,\n                        body: result.data,\n                        url: self.full_url(path),\n                        ip: None,\n                        headers: result.header_map.all,\n                    }\n                    .into());\n                    if self.auth_required {\n                        let auth_error = auth::AuthorizationError::new(\n                            self.gctx,\n                            self.source_id,\n                            self.login_url.clone(),\n                            auth::AuthorizationErrorReason::TokenRejected,\n                        )?;\n                        return Poll::Ready(err.context(auth_error));\n                    } else {\n                        return Poll::Ready(err);\n                    }\n                }\n            }\n        }\n\n        if path != Path::new(RegistryConfig::NAME) {\n            self.auth_required = ready!(self.config()?).auth_required;\n        } else if !self.auth_required {\n            // Check if there's a cached config that says auth is required.\n            // This allows avoiding the initial unauthenticated request to probe.\n            if let Some(config) = self.config_cached()? {\n                self.auth_required = config.auth_required;\n            }\n        }\n\n        // Looks like we're going to have to do a network request.\n        self.start_fetch()?;\n\n        let mut handle = http_handle(self.gctx)?;\n        let full_url = self.full_url(path);\n        debug!(target: \"network\", \"fetch {}\", full_url);\n        handle.get(true)?;\n        handle.url(&full_url)?;\n        handle.follow_location(true)?;\n\n        // Enable HTTP/2 if possible.\n        crate::try_old_curl_http2_pipewait!(self.multiplexing, handle);\n\n        let mut headers = List::new();\n        // Include a header to identify the protocol. This allows the server to\n        // know that Cargo is attempting to use the sparse protocol.\n        headers.append(\"cargo-protocol: version=1\")?;\n        headers.append(\"accept: text/plain\")?;\n\n        // If we have a cached copy of the file, include IF_NONE_MATCH or IF_MODIFIED_SINCE header.\n        if let Some(index_version) = index_version {\n            if let Some((key, value)) = index_version.split_once(':') {\n                match key {\n                    ETAG => headers.append(&format!(\"{}: {}\", IF_NONE_MATCH, value.trim()))?,\n                    LAST_MODIFIED => {\n                        headers.append(&format!(\"{}: {}\", IF_MODIFIED_SINCE, value.trim()))?\n                    }\n                    _ => debug!(\"unexpected index version: {}\", index_version),\n                }\n            }\n        }\n        if self.auth_required {\n            let authorization = auth::auth_token(\n                self.gctx,\n                &self.source_id,\n                self.login_url.as_ref(),\n                Operation::Read,\n                self.auth_error_headers.clone(),\n                true,\n            )?;\n            headers.append(&format!(\"Authorization: {}\", authorization))?;\n            trace!(target: \"network\", \"including authorization for {}\", full_url);\n        }\n        handle.http_headers(headers)?;\n\n        // We're going to have a bunch of downloads all happening \"at the same time\".\n        // So, we need some way to track what headers/data/responses are for which request.\n        // We do that through this token. Each request (and associated response) gets one.\n        let token = self.downloads.next;\n        self.downloads.next += 1;\n        debug!(target: \"network\", \"downloading {} as {}\", path.display(), token);\n        let is_new = self.downloads.pending_paths.insert(path.to_path_buf());\n        assert!(is_new, \"path queued for download more than once\");\n\n        // Each write should go to self.downloads.pending[&token].data.\n        // Since the write function must be 'static, we access downloads through a thread-local.\n        // That thread-local is set up in `block_until_ready` when it calls self.multi.perform,\n        // which is what ultimately calls this method.\n        handle.write_function(move |buf| {\n            trace!(target: \"network\", \"{} - {} bytes of data\", token, buf.len());\n            tls::with(|downloads| {\n                if let Some(downloads) = downloads {\n                    downloads.pending[&token]\n                        .0\n                        .data\n                        .borrow_mut()\n                        .extend_from_slice(buf);\n                }\n            });\n            Ok(buf.len())\n        })?;\n\n        // And ditto for the header function.\n        handle.header_function(move |buf| {\n            if let Some((tag, value)) = Self::handle_http_header(buf) {\n                tls::with(|downloads| {\n                    if let Some(downloads) = downloads {\n                        let mut header_map = downloads.pending[&token].0.header_map.borrow_mut();\n                        header_map.all.push(format!(\"{tag}: {value}\"));\n                        match tag.to_ascii_lowercase().as_str() {\n                            LAST_MODIFIED => header_map.last_modified = Some(value.to_string()),\n                            ETAG => header_map.etag = Some(value.to_string()),\n                            WWW_AUTHENTICATE => header_map.www_authenticate.push(value.to_string()),\n                            _ => {}\n                        }\n                    }\n                });\n            }\n\n            true\n        })?;\n\n        let dl = Download {\n            token,\n            path: path.to_path_buf(),\n            data: RefCell::new(Vec::new()),\n            header_map: Default::default(),\n            retry: Retry::new(self.gctx)?,\n        };\n\n        // Finally add the request we've lined up to the pool of requests that cURL manages.\n        let mut handle = self.multi.add(handle)?;\n        handle.set_token(token)?;\n        self.downloads.pending.insert(dl.token, (dl, handle));\n\n        Poll::Pending\n    }\n\n    fn config(&mut self) -> Poll<CargoResult<Option<RegistryConfig>>> {\n        let cfg = ready!(self.config()?).clone();\n        Poll::Ready(Ok(Some(cfg)))\n    }\n\n    fn invalidate_cache(&mut self) {\n        // Actually updating the index is more or less a no-op for this implementation.\n        // All it does is ensure that a subsequent load will double-check files with the\n        // server rather than rely on a locally cached copy of the index files.\n        debug!(\"invalidated index cache\");\n        self.fresh.clear();\n        self.requested_update = true;\n    }\n\n    fn set_quiet(&mut self, quiet: bool) {\n        self.quiet = quiet;\n        self.downloads.progress.replace(None);\n    }\n\n    fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult<MaybeLock> {\n        let registry_config = loop {\n            match self.config()? {\n                Poll::Pending => self.block_until_ready()?,\n                Poll::Ready(cfg) => break cfg.to_owned(),\n            }\n        };\n\n        download::download(\n            &self.cache_path,\n            &self.gctx,\n            self.name.clone(),\n            pkg,\n            checksum,\n            registry_config,\n        )\n    }\n\n    fn finish_download(\n        &mut self,\n        pkg: PackageId,\n        checksum: &str,\n        data: &[u8],\n    ) -> CargoResult<File> {\n        download::finish_download(\n            &self.cache_path,\n            &self.gctx,\n            self.name.clone(),\n            pkg,\n            checksum,\n            data,\n        )\n    }\n\n    fn is_crate_downloaded(&self, pkg: PackageId) -> bool {\n        download::is_crate_downloaded(&self.cache_path, &self.gctx, pkg)\n    }\n\n    fn block_until_ready(&mut self) -> CargoResult<()> {\n        trace!(target: \"network::HttpRegistry::block_until_ready\",\n            \"{} transfers pending\",\n            self.downloads.pending.len()\n        );\n        self.downloads.blocking_calls += 1;\n\n        loop {\n            let remaining_in_multi = tls::set(&self.downloads, || {\n                self.multi\n                    .perform()\n                    .context(\"failed to perform http requests\")\n            })?;\n            trace!(target: \"network\", \"{} transfers remaining\", remaining_in_multi);\n            // Handles transfers performed by `self.multi` above and adds to\n            // `self.downloads.results`. Failed transfers get added to\n            // `self.downloads.sleeping` for retry.\n            self.handle_completed_downloads()?;\n            if remaining_in_multi + self.downloads.sleeping.len() as u32 == 0 {\n                return Ok(());\n            }\n            // Handles failed transfers in `self.downloads.sleeping` and\n            // re-adds them to `self.multi`.\n            self.add_sleepers()?;\n\n            if self.downloads.pending.is_empty() {\n                let delay = self.downloads.sleeping.time_to_next().unwrap();\n                debug!(target: \"network\", \"sleeping main thread for {delay:?}\");\n                std::thread::sleep(delay);\n            } else {\n                // We have no more replies to provide the caller with,\n                // so we need to wait until cURL has something new for us.\n                let timeout = self\n                    .multi\n                    .get_timeout()?\n                    .unwrap_or_else(|| Duration::new(1, 0));\n                self.multi\n                    .wait(&mut [], timeout)\n                    .context(\"failed to wait on curl `Multi`\")?;\n            }\n        }\n    }\n}\n\nimpl<'gctx> Downloads<'gctx> {\n    /// Updates the state of the progress bar for downloads.\n    fn tick(&self) -> CargoResult<()> {\n        let mut progress = self.progress.borrow_mut();\n        let Some(progress) = progress.as_mut() else {\n            return Ok(());\n        };\n\n        // Since the sparse protocol discovers dependencies as it goes,\n        // it's not possible to get an accurate progress indication.\n        //\n        // As an approximation, we assume that the depth of the dependency graph\n        // is fixed, and base the progress on how many times the caller has asked\n        // for blocking. If there are actually additional dependencies, the progress\n        // bar will get stuck. If there are fewer dependencies, it will disappear\n        // early. It will never go backwards.\n        //\n        // The status text also contains the number of completed & pending requests, which\n        // gives an better indication of forward progress.\n        let approximate_tree_depth = 10;\n\n        progress.tick(\n            self.blocking_calls.min(approximate_tree_depth),\n            approximate_tree_depth + 1,\n            &format!(\n                \" {} complete; {} pending\",\n                self.downloads_finished,\n                self.pending.len() + self.sleeping.len()\n            ),\n        )\n    }\n}\n\nmod tls {\n    use super::Downloads;\n    use std::cell::Cell;\n\n    thread_local!(static PTR: Cell<usize> = const { Cell::new(0) });\n\n    pub(super) fn with<R>(f: impl FnOnce(Option<&Downloads<'_>>) -> R) -> R {\n        let ptr = PTR.with(|p| p.get());\n        if ptr == 0 {\n            f(None)\n        } else {\n            // Safety: * `ptr` is only set by `set` below which ensures the type is correct.\n            let ptr = unsafe { &*(ptr as *const Downloads<'_>) };\n            f(Some(ptr))\n        }\n    }\n\n    pub(super) fn set<R>(dl: &Downloads<'_>, f: impl FnOnce() -> R) -> R {\n        struct Reset<'a, T: Copy>(&'a Cell<T>, T);\n\n        impl<'a, T: Copy> Drop for Reset<'a, T> {\n            fn drop(&mut self) {\n                self.0.set(self.1);\n            }\n        }\n\n        PTR.with(|p| {\n            let _reset = Reset(p, p.get());\n            p.set(dl as *const Downloads<'_> as usize);\n            f()\n        })\n    }\n}\n"
  },
  {
    "path": "src/cargo/sources/registry/index/cache.rs",
    "content": "//! A layer of on-disk index cache for performance.\n//!\n//! One important aspect of the index is that we want to optimize the \"happy\n//! path\" as much as possible. Whenever you type `cargo build` Cargo will\n//! *always* reparse the registry and learn about dependency information. This\n//! is done because Cargo needs to learn about the upstream crates.io crates\n//! that you're using and ensure that the preexisting `Cargo.lock` still matches\n//! the current state of the world.\n//!\n//! Consequently, Cargo \"null builds\" (the index that Cargo adds to each build\n//! itself) need to be fast when accessing the index. The primary performance\n//! optimization here is to avoid parsing JSON blobs from the registry if we\n//! don't need them. Most secondary optimizations are centered around removing\n//! allocations and such, but avoiding parsing JSON is the #1 optimization.\n//!\n//! When we get queries from the resolver we're given a [`Dependency`]. This\n//! dependency in turn has a version requirement, and with lock files that\n//! already exist these version requirements are exact version requirements\n//! `=a.b.c`. This means that we in theory only need to parse one line of JSON\n//! per query in the registry, the one that matches version `a.b.c`.\n//!\n//! The crates.io index, however, is not amenable to this form of query. Instead\n//! the crates.io index simply is a file where each line is a JSON blob, aka\n//! [`IndexPackage`]. To learn about the versions in each JSON blob we would\n//! need to parse the JSON via [`IndexSummary::parse`], defeating the purpose\n//! of trying to parse as little as possible.\n//!\n//! > Note that as a small aside even *loading* the JSON from the registry is\n//! > actually pretty slow. For crates.io and [`RemoteRegistry`] we don't\n//! > actually check out the git index on disk because that takes quite some\n//! > time and is quite large. Instead we use `libgit2` to read the JSON from\n//! > the raw git objects. This in turn can be slow (aka show up high in\n//! > profiles) because libgit2 has to do deflate decompression and such.\n//!\n//! To solve all these issues a strategy is employed here where Cargo basically\n//! creates an index into the index. The first time a package is queried about\n//! (first time being for an entire computer) Cargo will load the contents\n//! (slowly via libgit2) from the registry. It will then (slowly) parse every\n//! single line to learn about its versions. Afterwards, however, Cargo will\n//! emit a new file (a cache, representing as [`SummariesCache`]) which is\n//! amenable for speedily parsing in future invocations.\n//!\n//! This cache file is currently organized by basically having the semver\n//! version extracted from each JSON blob. That way Cargo can quickly and\n//! easily parse all versions contained and which JSON blob they're associated\n//! with. The JSON blob then doesn't actually need to get parsed unless the\n//! version is parsed.\n//!\n//! Altogether the initial measurements of this shows a massive improvement for\n//! Cargo null build performance. It's expected that the improvements earned\n//! here will continue to grow over time in the sense that the previous\n//! implementation (parse all lines each time) actually continues to slow down\n//! over time as new versions of a crate are published. In any case when first\n//! implemented a null build of Cargo itself would parse 3700 JSON blobs from\n//! the registry and load 150 blobs from git. Afterwards it parses 150 JSON\n//! blobs and loads 0 files git. Removing 200ms or more from Cargo's startup\n//! time is certainly nothing to sneeze at!\n//!\n//! Note that this is just a high-level overview, there's of course lots of\n//! details like invalidating caches and whatnot which are handled below, but\n//! hopefully those are more obvious inline in the code itself.\n//!\n//! [`Dependency`]: crate::core::Dependency\n//! [`IndexPackage`]: super::IndexPackage\n//! [`IndexSummary::parse`]: super::IndexSummary::parse\n//! [`RemoteRegistry`]: crate::sources::registry::remote::RemoteRegistry\n\nuse std::cell::RefCell;\nuse std::fs;\nuse std::io;\nuse std::path::PathBuf;\nuse std::str;\n\nuse anyhow::bail;\nuse cargo_util::registry::make_dep_path;\nuse semver::Version;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::util::Filesystem;\nuse crate::util::cache_lock::CacheLockMode;\n\nuse super::INDEX_V_MAX;\nuse super::split;\n\n/// The current version of [`SummariesCache`].\nconst CURRENT_CACHE_VERSION: u8 = 3;\n\n/// A representation of the cache on disk that Cargo maintains of summaries.\n///\n/// Cargo will initially parse all summaries in the registry and will then\n/// serialize that into this form and place it in a new location on disk,\n/// ensuring that access in the future is much speedier.\n///\n/// For serialization and deserialization of this on-disk index cache of\n/// summaries, see [`SummariesCache::serialize`]  and [`SummariesCache::parse`].\n///\n/// # The format of the index cache\n///\n/// The idea of this format is that it's a very easy file for Cargo to parse in\n/// future invocations. The read from disk should be fast and then afterwards\n/// all we need to know is what versions correspond to which JSON blob.\n///\n/// Currently the format looks like:\n///\n/// ```text\n/// +---------------+----------------------+--------------------+---+\n/// | cache version | index schema version | index file version | 0 |\n/// +---------------+----------------------+--------------------+---+\n/// ```\n///\n/// followed by one or more (version + JSON blob) pairs...\n///\n/// ```text\n/// +----------------+---+-----------+---+\n/// | semver version | 0 | JSON blob | 0 | ...\n/// +----------------+---+-----------+---+\n/// ```\n///\n/// Each field represents:\n///\n/// * _cache version_ --- Intended to ensure that there's some level of\n///   future compatibility against changes to this cache format so if different\n///   versions of Cargo share the same cache they don't get too confused.\n/// * _index schema version_ --- The schema version of the raw index file.\n///   See [`IndexPackage::v`] for the detail.\n/// * _index file version_ --- Tracks when a cache needs to be regenerated.\n///   A cache regeneration is required whenever the index file itself updates.\n/// * _semver version_ --- The version for each JSON blob. Extracted from the\n///   blob for fast queries without parsing the entire blob.\n/// * _JSON blob_ --- The actual metadata for each version of the package. It\n///   has the same representation as [`IndexPackage`].\n///\n/// # Changes between each cache version\n///\n/// * `1`: The original version.\n/// * `2`: Added the \"index schema version\" field so that if the index schema\n///   changes, different versions of cargo won't get confused reading each\n///   other's caches.\n/// * `3`: Bumped the version to work around an issue where multiple versions of\n///   a package were published that differ only by semver metadata. For\n///   example, openssl-src 110.0.0 and 110.0.0+1.1.0f. Previously, the cache\n///   would be incorrectly populated with two entries, both 110.0.0. After\n///   this, the metadata will be correctly included. This isn't really a format\n///   change, just a version bump to clear the incorrect cache entries. Note:\n///   the index shouldn't allow these, but unfortunately crates.io doesn't\n///   check it.\n///\n/// See [`CURRENT_CACHE_VERSION`] for the current cache version.\n///\n/// [`IndexPackage::v`]: super::IndexPackage::v\n/// [`IndexPackage`]: super::IndexPackage\n#[derive(Default)]\npub struct SummariesCache<'a> {\n    /// JSON blobs of the summaries. Each JSON blob has a [`Version`] beside,\n    /// so that Cargo can query a version without full JSON parsing.\n    pub versions: Vec<(Version, &'a [u8])>,\n    /// For cache invalidation, we tracks the index file version to determine\n    /// when to regenerate the cache itself.\n    pub index_version: &'a str,\n}\n\nimpl<'a> SummariesCache<'a> {\n    /// Deserializes an on-disk cache.\n    pub fn parse(data: &'a [u8]) -> CargoResult<SummariesCache<'a>> {\n        // NB: keep this method in sync with `serialize` below\n        let (first_byte, rest) = data\n            .split_first()\n            .ok_or_else(|| anyhow::format_err!(\"malformed cache\"))?;\n        if *first_byte != CURRENT_CACHE_VERSION {\n            bail!(\"looks like a different Cargo's cache, bailing out\");\n        }\n        let index_v_bytes = rest\n            .get(..4)\n            .ok_or_else(|| anyhow::anyhow!(\"cache expected 4 bytes for index schema version\"))?;\n        let index_v = u32::from_le_bytes(index_v_bytes.try_into().unwrap());\n        if index_v != INDEX_V_MAX {\n            bail!(\n                \"index schema version {index_v} doesn't match the version I know ({INDEX_V_MAX})\",\n            );\n        }\n        let rest = &rest[4..];\n\n        let mut iter = split(rest, 0);\n        let last_index_update = if let Some(update) = iter.next() {\n            str::from_utf8(update)?\n        } else {\n            bail!(\"malformed file\");\n        };\n        let mut ret = SummariesCache::default();\n        ret.index_version = last_index_update;\n        while let Some(version) = iter.next() {\n            let version = str::from_utf8(version)?;\n            let version = Version::parse(version)?;\n            let summary = iter.next().unwrap();\n            ret.versions.push((version, summary));\n        }\n        Ok(ret)\n    }\n\n    /// Serializes itself with a given `index_version`.\n    pub fn serialize(&self, index_version: &str) -> Vec<u8> {\n        // NB: keep this method in sync with `parse` above\n        let size = self\n            .versions\n            .iter()\n            .map(|(_version, data)| 10 + data.len())\n            .sum();\n        let mut contents = Vec::with_capacity(size);\n        contents.push(CURRENT_CACHE_VERSION);\n        contents.extend(&u32::to_le_bytes(INDEX_V_MAX));\n        contents.extend_from_slice(index_version.as_bytes());\n        contents.push(0);\n        for (version, data) in self.versions.iter() {\n            contents.extend_from_slice(version.to_string().as_bytes());\n            contents.push(0);\n            contents.extend_from_slice(data);\n            contents.push(0);\n        }\n        contents\n    }\n}\n\n/// Manages the on-disk index caches.\npub struct CacheManager<'gctx> {\n    /// The root path where caches are located.\n    cache_root: Filesystem,\n    /// [`GlobalContext`] reference for convenience.\n    gctx: &'gctx GlobalContext,\n    /// Keeps track of if we have sent a warning message if there was an error updating the cache.\n    /// The motivation is to avoid warning spam if the cache is not writable.\n    has_warned: RefCell<bool>,\n}\n\nimpl<'gctx> CacheManager<'gctx> {\n    /// Creates a new instance of the on-disk index cache manager.\n    ///\n    /// `root` --- The root path where caches are located.\n    pub fn new(cache_root: Filesystem, gctx: &'gctx GlobalContext) -> CacheManager<'gctx> {\n        CacheManager {\n            cache_root,\n            gctx,\n            has_warned: Default::default(),\n        }\n    }\n\n    /// Gets the cache associated with the key.\n    pub fn get(&self, key: &str) -> Option<Vec<u8>> {\n        let cache_path = &self.cache_path(key);\n        match fs::read(cache_path) {\n            Ok(contents) => Some(contents),\n            Err(e) => {\n                tracing::debug!(?cache_path, \"cache missing: {e}\");\n                None\n            }\n        }\n    }\n\n    /// Associates the value with the key.\n    pub fn put(&self, key: &str, value: &[u8]) {\n        let cache_path = &self.cache_path(key);\n        if let Err(e) = self.put_inner(cache_path, value) {\n            tracing::info!(?cache_path, \"failed to write cache: {e}\");\n\n            if !*self.has_warned.borrow() {\n                let _ = self.gctx.shell().warn(format!(\n                    \"failed to write cache, path: {}, error: {e}\",\n                    cache_path.to_str().unwrap_or_default()\n                ));\n                *self.has_warned.borrow_mut() = true;\n            }\n        }\n    }\n\n    fn put_inner(&self, cache_path: &PathBuf, value: &[u8]) -> std::io::Result<()> {\n        fs::create_dir_all(cache_path.parent().unwrap())?;\n        let path = Filesystem::new(cache_path.clone());\n        self.gctx\n            .assert_package_cache_locked(CacheLockMode::DownloadExclusive, &path);\n        fs::write(cache_path, value)?;\n        Ok(())\n    }\n\n    /// Invalidates the cache associated with the key.\n    pub fn invalidate(&self, key: &str) {\n        let cache_path = &self.cache_path(key);\n        if let Err(e) = fs::remove_file(cache_path) {\n            if e.kind() != io::ErrorKind::NotFound {\n                tracing::debug!(?cache_path, \"failed to remove from cache: {e}\");\n            }\n        }\n    }\n\n    fn cache_path(&self, key: &str) -> PathBuf {\n        let relative = make_dep_path(key, false);\n        // This is the file we're loading from cache or the index data.\n        // See module comment in `registry/mod.rs` for why this is structured\n        // the way it is.\n        self.cache_root.join(relative).into_path_unlocked()\n    }\n}\n"
  },
  {
    "path": "src/cargo/sources/registry/index/mod.rs",
    "content": "//! Management of the index of a registry source.\n//!\n//! This module contains management of the index and various operations, such as\n//! actually parsing the index, looking for crates, etc. This is intended to be\n//! abstract over remote indices (downloaded via Git or HTTP) and local registry\n//! indices (which are all just present on the filesystem).\n//!\n//! ## How the index works\n//!\n//! Here is a simple flow when loading a [`Summary`] (metadata) from the index:\n//!\n//! 1. A query is fired via [`RegistryIndex::query_inner`].\n//! 2. Tries loading all summaries via [`RegistryIndex::load_summaries`], and\n//!    under the hood calling [`Summaries::parse`] to parse an index file.\n//!     1. If an on-disk index cache is present, loads it via\n//!        [`Summaries::parse_cache`].\n//!     2. Otherwise goes to the slower path [`RegistryData::load`] to get the\n//!        specific index file.\n//! 3. A [`Summary`] is now ready in callback `f` in [`RegistryIndex::query_inner`].\n//!\n//! To learn the rationale behind this multi-layer index metadata loading,\n//! see [the documentation of the on-disk index cache](cache).\nuse crate::core::dependency::{Artifact, DepKind};\nuse crate::core::{CliUnstable, Dependency};\nuse crate::core::{PackageId, SourceId, Summary};\nuse crate::sources::registry::{LoadResponse, RegistryData};\nuse crate::util::IntoUrl;\nuse crate::util::interning::InternedString;\nuse crate::util::{CargoResult, Filesystem, GlobalContext, OptVersionReq, internal};\nuse cargo_util::registry::make_dep_path;\nuse cargo_util_schemas::index::{IndexPackage, RegistryDependency};\nuse cargo_util_schemas::manifest::RustVersion;\nuse semver::Version;\nuse serde::{Deserialize, Serialize};\nuse std::borrow::Cow;\nuse std::collections::BTreeMap;\nuse std::collections::HashMap;\nuse std::path::Path;\nuse std::str;\nuse std::task::{Poll, ready};\nuse tracing::info;\n\nmod cache;\nuse self::cache::CacheManager;\nuse self::cache::SummariesCache;\n\n/// The maximum schema version of the `v` field in the index this version of\n/// cargo understands. See [`IndexPackage::v`] for the detail.\nconst INDEX_V_MAX: u32 = 2;\n\n/// Manager for handling the on-disk index.\n///\n/// Different kinds of registries store the index differently:\n///\n/// * [`LocalRegistry`] is a simple on-disk tree of files of the raw index.\n/// * [`RemoteRegistry`] is stored as a raw git repository.\n/// * [`HttpRegistry`] fills the on-disk index cache directly without keeping\n///   any raw index.\n///\n/// These means of access are handled via the [`RegistryData`] trait abstraction.\n/// This transparently handles caching of the index in a more efficient format.\n///\n/// [`LocalRegistry`]: super::local::LocalRegistry\n/// [`RemoteRegistry`]: super::remote::RemoteRegistry\n/// [`HttpRegistry`]: super::http_remote::HttpRegistry\npub struct RegistryIndex<'gctx> {\n    source_id: SourceId,\n    /// Root directory of the index for the registry.\n    path: Filesystem,\n    /// In-memory cache of summary data.\n    ///\n    /// This is keyed off the package name. The [`Summaries`] value handles\n    /// loading the summary data. It keeps an optimized on-disk representation\n    /// of the JSON files, which is created in an as-needed fashion. If it\n    /// hasn't been cached already, it uses [`RegistryData::load`] to access\n    /// to JSON files from the index, and the creates the optimized on-disk\n    /// summary cache.\n    summaries_cache: HashMap<InternedString, Summaries>,\n    /// [`GlobalContext`] reference for convenience.\n    gctx: &'gctx GlobalContext,\n    /// Manager of on-disk caches.\n    cache_manager: CacheManager<'gctx>,\n}\n\n/// An internal cache of summaries for a particular package.\n///\n/// A list of summaries are loaded from disk via one of two methods:\n///\n/// 1. From raw registry index --- Primarily Cargo will parse the corresponding\n///    file for a crate in the upstream crates.io registry. That's just a JSON\n///    blob per line which we can parse, extract the version, and then store here.\n///    See [`IndexPackage`] and [`IndexSummary::parse`].\n///\n/// 2. From on-disk index cache --- If Cargo has previously run, we'll have a\n///    cached index of dependencies for the upstream index. This is a file that\n///    Cargo maintains lazily on the local filesystem and is much faster to\n///    parse since it doesn't involve parsing all of the JSON.\n///    See [`SummariesCache`].\n///\n/// The outward-facing interface of this doesn't matter too much where it's\n/// loaded from, but it's important when reading the implementation to note that\n/// we try to parse as little as possible!\n#[derive(Default)]\nstruct Summaries {\n    /// A raw vector of uninterpreted bytes. This is what `Unparsed` start/end\n    /// fields are indexes into. If a `Summaries` is loaded from the crates.io\n    /// index then this field will be empty since nothing is `Unparsed`.\n    raw_data: Vec<u8>,\n\n    /// All known versions of a crate, keyed from their `Version` to the\n    /// possibly parsed or unparsed version of the full summary.\n    versions: HashMap<Version, MaybeIndexSummary>,\n}\n\n/// A lazily parsed [`IndexSummary`].\nenum MaybeIndexSummary {\n    /// A summary which has not been parsed, The `start` and `end` are pointers\n    /// into [`Summaries::raw_data`] which this is an entry of.\n    Unparsed { start: usize, end: usize },\n\n    /// An actually parsed summary.\n    Parsed(IndexSummary),\n}\n\n/// A parsed representation of a summary from the index. This is usually parsed\n/// from a line from a raw index file, or a JSON blob from on-disk index cache.\n///\n/// In addition to a full [`Summary`], we have information on whether it is `yanked`.\n#[derive(Clone, Debug)]\npub enum IndexSummary {\n    /// Available for consideration\n    Candidate(Summary),\n    /// Yanked within its registry\n    Yanked(Summary),\n    /// Not available as we are offline and create is not downloaded yet\n    Offline(Summary),\n    /// From a newer schema version and is likely incomplete or inaccurate\n    Unsupported(Summary, u32),\n    /// An error was encountered despite being a supported schema version\n    Invalid(Summary),\n}\n\nimpl IndexSummary {\n    /// Extract the summary from any variant\n    pub fn as_summary(&self) -> &Summary {\n        match self {\n            IndexSummary::Candidate(sum)\n            | IndexSummary::Yanked(sum)\n            | IndexSummary::Offline(sum)\n            | IndexSummary::Unsupported(sum, _)\n            | IndexSummary::Invalid(sum) => sum,\n        }\n    }\n\n    /// Extract the summary from any variant\n    pub fn into_summary(self) -> Summary {\n        match self {\n            IndexSummary::Candidate(sum)\n            | IndexSummary::Yanked(sum)\n            | IndexSummary::Offline(sum)\n            | IndexSummary::Unsupported(sum, _)\n            | IndexSummary::Invalid(sum) => sum,\n        }\n    }\n\n    pub fn map_summary(self, f: impl Fn(Summary) -> Summary) -> Self {\n        match self {\n            IndexSummary::Candidate(s) => IndexSummary::Candidate(f(s)),\n            IndexSummary::Yanked(s) => IndexSummary::Yanked(f(s)),\n            IndexSummary::Offline(s) => IndexSummary::Offline(f(s)),\n            IndexSummary::Unsupported(s, v) => IndexSummary::Unsupported(f(s), v.clone()),\n            IndexSummary::Invalid(s) => IndexSummary::Invalid(f(s)),\n        }\n    }\n\n    /// Extract the package id from any variant\n    pub fn package_id(&self) -> PackageId {\n        self.as_summary().package_id()\n    }\n\n    /// Returns `true` if the index summary is [`Yanked`].\n    ///\n    /// [`Yanked`]: IndexSummary::Yanked\n    #[must_use]\n    pub fn is_yanked(&self) -> bool {\n        matches!(self, Self::Yanked(..))\n    }\n\n    /// Returns `true` if the index summary is [`Offline`].\n    ///\n    /// [`Offline`]: IndexSummary::Offline\n    #[must_use]\n    pub fn is_offline(&self) -> bool {\n        matches!(self, Self::Offline(..))\n    }\n}\n\nfn index_package_to_summary(\n    pkg: &IndexPackage<'_>,\n    source_id: SourceId,\n    cli_unstable: &CliUnstable,\n) -> CargoResult<Summary> {\n    // ****CAUTION**** Please be extremely careful with returning errors, see\n    // `IndexSummary::parse` for details\n    let pkgid = PackageId::new(pkg.name.as_ref().into(), pkg.vers.clone(), source_id);\n    let deps = pkg\n        .deps\n        .iter()\n        .map(|dep| registry_dependency_into_dep(dep.clone(), source_id, cli_unstable))\n        .collect::<CargoResult<Vec<_>>>()?;\n    let mut features = pkg.features.clone();\n    if let Some(features2) = pkg.features2.clone() {\n        for (name, values) in features2 {\n            features.entry(name).or_default().extend(values);\n        }\n    }\n    let features = features\n        .into_iter()\n        .map(|(name, values)| (name.into(), values.into_iter().map(|v| v.into()).collect()))\n        .collect::<BTreeMap<_, _>>();\n    let links: Option<InternedString> = pkg.links.as_ref().map(|l| l.as_ref().into());\n    let mut summary = Summary::new(pkgid, deps, &features, links, pkg.rust_version.clone())?;\n    summary.set_checksum(pkg.cksum.clone());\n    if let Some(pubtime) = pkg.pubtime {\n        summary.set_pubtime(pubtime);\n    }\n    Ok(summary)\n}\n\n#[derive(Deserialize, Serialize)]\nstruct IndexPackageMinimum<'a> {\n    name: Cow<'a, str>,\n    vers: Version,\n}\n\n#[derive(Deserialize, Serialize, Default)]\nstruct IndexPackageRustVersion {\n    rust_version: Option<RustVersion>,\n}\n\n#[derive(Deserialize, Serialize, Default)]\nstruct IndexPackageV {\n    v: Option<u32>,\n}\n\nimpl<'gctx> RegistryIndex<'gctx> {\n    /// Creates an empty registry index at `path`.\n    pub fn new(\n        source_id: SourceId,\n        path: &Filesystem,\n        gctx: &'gctx GlobalContext,\n    ) -> RegistryIndex<'gctx> {\n        RegistryIndex {\n            source_id,\n            path: path.clone(),\n            summaries_cache: HashMap::new(),\n            gctx,\n            cache_manager: CacheManager::new(path.join(\".cache\"), gctx),\n        }\n    }\n\n    /// Returns the hash listed for a specified `PackageId`. Primarily for\n    /// checking the integrity of a downloaded package matching the checksum in\n    /// the index file, aka [`IndexSummary`].\n    pub fn hash(&mut self, pkg: PackageId, load: &mut dyn RegistryData) -> Poll<CargoResult<&str>> {\n        let req = OptVersionReq::lock_to_exact(pkg.version());\n        let summary = self.summaries(pkg.name(), &req, load)?;\n        let summary = ready!(summary).next();\n        Poll::Ready(Ok(summary\n            .ok_or_else(|| internal(format!(\"no hash listed for {}\", pkg)))?\n            .as_summary()\n            .checksum()\n            .ok_or_else(|| internal(format!(\"no hash listed for {}\", pkg)))?))\n    }\n\n    /// Load a list of summaries for `name` package in this registry which\n    /// match `req`.\n    ///\n    /// This function will semantically\n    ///\n    /// 1. parse the index file (either raw or cache),\n    /// 2. match all versions,\n    /// 3. and then return an iterator over all summaries which matched.\n    ///\n    /// Internally there's quite a few layer of caching to amortize this cost\n    /// though since this method is called quite a lot on null builds in Cargo.\n    fn summaries<'a, 'b>(\n        &'a mut self,\n        name: InternedString,\n        req: &'b OptVersionReq,\n        load: &mut dyn RegistryData,\n    ) -> Poll<CargoResult<impl Iterator<Item = &'a IndexSummary> + 'b>>\n    where\n        'a: 'b,\n    {\n        let cli_unstable = self.gctx.cli_unstable();\n\n        let source_id = self.source_id;\n\n        // First up parse what summaries we have available.\n        let summaries = ready!(self.load_summaries(name, load)?);\n\n        // Iterate over our summaries, extract all relevant ones which match our\n        // version requirement, and then parse all corresponding rows in the\n        // registry. As a reminder this `summaries` method is called for each\n        // entry in a lock file on every build, so we want to absolutely\n        // minimize the amount of work being done here and parse as little as\n        // necessary.\n        let raw_data = &summaries.raw_data;\n        Poll::Ready(Ok(summaries\n            .versions\n            .iter_mut()\n            .filter_map(move |(k, v)| if req.matches(k) { Some(v) } else { None })\n            .filter_map(move |maybe| {\n                match maybe.parse(raw_data, source_id, cli_unstable) {\n                    Ok(sum) => Some(sum),\n                    Err(e) => {\n                        info!(\"failed to parse `{}` registry package: {}\", name, e);\n                        None\n                    }\n                }\n            })))\n    }\n\n    /// Actually parses what summaries we have available.\n    ///\n    /// If Cargo has run previously, this tries in this order:\n    ///\n    /// 1. Returns from in-memory cache, aka [`RegistryIndex::summaries_cache`].\n    /// 2. If missing, hands over to [`Summaries::parse`] to parse an index file.\n    ///\n    ///    The actual kind index file being parsed depends on which kind of\n    ///    [`RegistryData`] the `load` argument is given. For example, a\n    ///    Git-based [`RemoteRegistry`] will first try a on-disk index cache\n    ///    file, and then try parsing registry raw index from Git repository.\n    ///\n    /// In effect, this is intended to be a quite cheap operation.\n    ///\n    /// [`RemoteRegistry`]: super::remote::RemoteRegistry\n    fn load_summaries(\n        &mut self,\n        name: InternedString,\n        load: &mut dyn RegistryData,\n    ) -> Poll<CargoResult<&mut Summaries>> {\n        // If we've previously loaded what versions are present for `name`, just\n        // return that since our in-memory cache should still be valid.\n        if self.summaries_cache.contains_key(&name) {\n            return Poll::Ready(Ok(self.summaries_cache.get_mut(&name).unwrap()));\n        }\n\n        // Prepare the `RegistryData` which will lazily initialize internal data\n        // structures.\n        load.prepare()?;\n\n        let root = load.assert_index_locked(&self.path);\n        let summaries = ready!(Summaries::parse(\n            root,\n            &name,\n            self.source_id,\n            load,\n            self.gctx.cli_unstable(),\n            &self.cache_manager,\n        ))?\n        .unwrap_or_default();\n        self.summaries_cache.insert(name, summaries);\n        Poll::Ready(Ok(self.summaries_cache.get_mut(&name).unwrap()))\n    }\n\n    /// Clears the in-memory summaries cache.\n    pub fn clear_summaries_cache(&mut self) {\n        self.summaries_cache.clear();\n    }\n\n    /// Attempts to find the packages that match a `name` and a version `req`.\n    ///\n    /// This is primarily used by [`Source::query`](super::Source).\n    pub fn query_inner(\n        &mut self,\n        name: InternedString,\n        req: &OptVersionReq,\n        load: &mut dyn RegistryData,\n        f: &mut dyn FnMut(IndexSummary),\n    ) -> Poll<CargoResult<()>> {\n        if !self.gctx.network_allowed() {\n            // This should only return `Poll::Ready(Ok(()))` if there is at least 1 match.\n            //\n            // If there are 0 matches it should fall through and try again with online.\n            // This is necessary for dependencies that are not used (such as\n            // target-cfg or optional), but are not downloaded. Normally the\n            // build should succeed if they are not downloaded and not used,\n            // but they still need to resolve. If they are actually needed\n            // then cargo will fail to download and an error message\n            // indicating that the required dependency is unavailable while\n            // offline will be displayed.\n            let mut called = false;\n            let callback = &mut |s: IndexSummary| {\n                if !s.is_offline() {\n                    called = true;\n                    f(s);\n                }\n            };\n            ready!(self.query_inner_with_online(name, req, load, callback, false)?);\n            if called {\n                return Poll::Ready(Ok(()));\n            }\n        }\n        self.query_inner_with_online(name, req, load, f, true)\n    }\n\n    /// Inner implementation of [`Self::query_inner`]. Returns the number of\n    /// summaries we've got.\n    ///\n    /// The `online` controls whether Cargo can access the network when needed.\n    fn query_inner_with_online(\n        &mut self,\n        name: InternedString,\n        req: &OptVersionReq,\n        load: &mut dyn RegistryData,\n        f: &mut dyn FnMut(IndexSummary),\n        online: bool,\n    ) -> Poll<CargoResult<()>> {\n        ready!(self.summaries(name, &req, load))?\n            // First filter summaries for `--offline`. If we're online then\n            // everything is a candidate, otherwise if we're offline we're only\n            // going to consider candidates which are actually present on disk.\n            //\n            // Note: This particular logic can cause problems with\n            // optional dependencies when offline. If at least 1 version\n            // of an optional dependency is downloaded, but that version\n            // does not satisfy the requirements, then resolution will\n            // fail. Unfortunately, whether or not something is optional\n            // is not known here.\n            .map(|s| {\n                if online || load.is_crate_downloaded(s.package_id()) {\n                    s.clone()\n                } else {\n                    IndexSummary::Offline(s.as_summary().clone())\n                }\n            })\n            .for_each(f);\n        Poll::Ready(Ok(()))\n    }\n\n    /// Looks into the summaries to check if a package has been yanked.\n    pub fn is_yanked(\n        &mut self,\n        pkg: PackageId,\n        load: &mut dyn RegistryData,\n    ) -> Poll<CargoResult<bool>> {\n        let req = OptVersionReq::lock_to_exact(pkg.version());\n        let found = ready!(self.summaries(pkg.name(), &req, load))?.any(|s| s.is_yanked());\n        Poll::Ready(Ok(found))\n    }\n}\n\nimpl Summaries {\n    /// Parse out a [`Summaries`] instances from on-disk state.\n    ///\n    /// This will do the followings in order:\n    ///\n    /// 1. Attempt to prefer parsing a previous index cache file that already\n    ///    exists from a previous invocation of Cargo (aka you're typing `cargo\n    ///    build` again after typing it previously).\n    /// 2. If parsing fails, or the cache isn't found or is invalid, we then\n    ///    take a slower path which loads the full descriptor for `relative`\n    ///    from the underlying index (aka libgit2 with crates.io, or from a\n    ///    remote HTTP index) and then parse everything in there.\n    ///\n    /// * `root` --- this is the root argument passed to `load`\n    /// * `name` --- the name of the package.\n    /// * `source_id` --- the registry's `SourceId` used when parsing JSON blobs\n    ///   to create summaries.\n    /// * `load` --- the actual index implementation which may be very slow to\n    ///   call. We avoid this if we can.\n    /// * `bindeps` --- whether the `-Zbindeps` unstable flag is enabled\n    pub fn parse(\n        root: &Path,\n        name: &str,\n        source_id: SourceId,\n        load: &mut dyn RegistryData,\n        cli_unstable: &CliUnstable,\n        cache_manager: &CacheManager<'_>,\n    ) -> Poll<CargoResult<Option<Summaries>>> {\n        // This is the file we're loading from cache or the index data.\n        // See module comment in `registry/mod.rs` for why this is structured the way it is.\n        let lowered_name = &name.to_lowercase();\n        let relative = make_dep_path(&lowered_name, false);\n\n        let mut cached_summaries = None;\n        let mut index_version = None;\n        if let Some(contents) = cache_manager.get(lowered_name) {\n            match Summaries::parse_cache(contents) {\n                Ok((s, v)) => {\n                    cached_summaries = Some(s);\n                    index_version = Some(v);\n                }\n                Err(e) => {\n                    tracing::debug!(\"failed to parse {lowered_name:?} cache: {e}\");\n                }\n            }\n        }\n\n        let response = ready!(load.load(root, relative.as_ref(), index_version.as_deref())?);\n\n        match response {\n            LoadResponse::CacheValid => {\n                tracing::debug!(\"fast path for registry cache of {:?}\", relative);\n                return Poll::Ready(Ok(cached_summaries));\n            }\n            LoadResponse::NotFound => {\n                cache_manager.invalidate(lowered_name);\n                return Poll::Ready(Ok(None));\n            }\n            LoadResponse::Data {\n                raw_data,\n                index_version,\n            } => {\n                // This is the fallback path where we actually talk to the registry backend to load\n                // information. Here we parse every single line in the index (as we need\n                // to find the versions)\n                tracing::debug!(\"slow path for {:?}\", relative);\n                let mut cache = SummariesCache::default();\n                let mut ret = Summaries::default();\n                ret.raw_data = raw_data;\n                for line in split(&ret.raw_data, b'\\n') {\n                    // Attempt forwards-compatibility on the index by ignoring\n                    // everything that we ourselves don't understand, that should\n                    // allow future cargo implementations to break the\n                    // interpretation of each line here and older cargo will simply\n                    // ignore the new lines.\n                    let summary = match IndexSummary::parse(line, source_id, cli_unstable) {\n                        Ok(summary) => summary,\n                        Err(e) => {\n                            // This should only happen when there is an index\n                            // entry from a future version of cargo that this\n                            // version doesn't understand. Hopefully, those future\n                            // versions of cargo correctly set INDEX_V_MAX and\n                            // CURRENT_CACHE_VERSION, otherwise this will skip\n                            // entries in the cache preventing those newer\n                            // versions from reading them (that is, until the\n                            // cache is rebuilt).\n                            tracing::info!(\n                                \"failed to parse {:?} registry package: {}\",\n                                relative,\n                                e\n                            );\n                            continue;\n                        }\n                    };\n                    let version = summary.package_id().version().clone();\n                    cache.versions.push((version.clone(), line));\n                    ret.versions.insert(version, summary.into());\n                }\n                if let Some(index_version) = index_version {\n                    tracing::trace!(\"caching index_version {}\", index_version);\n                    let cache_bytes = cache.serialize(index_version.as_str());\n                    // Once we have our `cache_bytes` which represents the `Summaries` we're\n                    // about to return, write that back out to disk so future Cargo\n                    // invocations can use it.\n                    cache_manager.put(lowered_name, &cache_bytes);\n\n                    // If we've got debug assertions enabled read back in the cached values\n                    // and assert they match the expected result.\n                    #[cfg(debug_assertions)]\n                    {\n                        let readback = SummariesCache::parse(&cache_bytes)\n                            .expect(\"failed to parse cache we just wrote\");\n                        assert_eq!(\n                            readback.index_version, index_version,\n                            \"index_version mismatch\"\n                        );\n                        assert_eq!(readback.versions, cache.versions, \"versions mismatch\");\n                    }\n                }\n                Poll::Ready(Ok(Some(ret)))\n            }\n        }\n    }\n\n    /// Parses the contents of an on-disk cache, aka [`SummariesCache`], which\n    /// represents information previously cached by Cargo.\n    pub fn parse_cache(contents: Vec<u8>) -> CargoResult<(Summaries, InternedString)> {\n        let cache = SummariesCache::parse(&contents)?;\n        let index_version = cache.index_version.into();\n        let mut ret = Summaries::default();\n        for (version, summary) in cache.versions {\n            let (start, end) = subslice_bounds(&contents, summary);\n            ret.versions\n                .insert(version, MaybeIndexSummary::Unparsed { start, end });\n        }\n        ret.raw_data = contents;\n        return Ok((ret, index_version));\n\n        // Returns the start/end offsets of `inner` with `outer`. Asserts that\n        // `inner` is a subslice of `outer`.\n        fn subslice_bounds(outer: &[u8], inner: &[u8]) -> (usize, usize) {\n            let outer_start = outer.as_ptr() as usize;\n            let outer_end = outer_start + outer.len();\n            let inner_start = inner.as_ptr() as usize;\n            let inner_end = inner_start + inner.len();\n            assert!(inner_start >= outer_start);\n            assert!(inner_end <= outer_end);\n            (inner_start - outer_start, inner_end - outer_start)\n        }\n    }\n}\n\nimpl MaybeIndexSummary {\n    /// Parses this \"maybe a summary\" into a `Parsed` for sure variant.\n    ///\n    /// Does nothing if this is already `Parsed`, and otherwise the `raw_data`\n    /// passed in is sliced with the bounds in `Unparsed` and then actually\n    /// parsed.\n    fn parse(\n        &mut self,\n        raw_data: &[u8],\n        source_id: SourceId,\n        cli_unstable: &CliUnstable,\n    ) -> CargoResult<&IndexSummary> {\n        let (start, end) = match self {\n            MaybeIndexSummary::Unparsed { start, end } => (*start, *end),\n            MaybeIndexSummary::Parsed(summary) => return Ok(summary),\n        };\n        let summary = IndexSummary::parse(&raw_data[start..end], source_id, cli_unstable)?;\n        *self = MaybeIndexSummary::Parsed(summary);\n        match self {\n            MaybeIndexSummary::Unparsed { .. } => unreachable!(),\n            MaybeIndexSummary::Parsed(summary) => Ok(summary),\n        }\n    }\n}\n\nimpl From<IndexSummary> for MaybeIndexSummary {\n    fn from(summary: IndexSummary) -> MaybeIndexSummary {\n        MaybeIndexSummary::Parsed(summary)\n    }\n}\n\nimpl IndexSummary {\n    /// Parses a line from the registry's index file into an [`IndexSummary`]\n    /// for a package.\n    ///\n    /// The `line` provided is expected to be valid JSON. It is supposed to be\n    /// a [`IndexPackage`].\n    fn parse(\n        line: &[u8],\n        source_id: SourceId,\n        cli_unstable: &CliUnstable,\n    ) -> CargoResult<IndexSummary> {\n        // ****CAUTION**** Please be extremely careful with returning errors\n        // from this function. Entries that error are not included in the\n        // index cache, and can cause cargo to get confused when switching\n        // between different versions that understand the index differently.\n        // Make sure to consider the INDEX_V_MAX and CURRENT_CACHE_VERSION\n        // values carefully when making changes here.\n        let index_summary = (|| {\n            let index = serde_json::from_slice::<IndexPackage<'_>>(line)?;\n            let summary = index_package_to_summary(&index, source_id, cli_unstable)?;\n            Ok((index, summary))\n        })();\n        let (index, summary, valid) = match index_summary {\n            Ok((index, summary)) => (index, summary, true),\n            Err(err) => {\n                let Ok(IndexPackageMinimum { name, vers }) =\n                    serde_json::from_slice::<IndexPackageMinimum<'_>>(line)\n                else {\n                    // If we can't recover, prefer the original error\n                    return Err(err);\n                };\n                tracing::info!(\n                    \"recoverying from failed parse of registry package {name}@{vers}: {err}\"\n                );\n                let IndexPackageRustVersion { rust_version } =\n                    serde_json::from_slice::<IndexPackageRustVersion>(line).unwrap_or_default();\n                let IndexPackageV { v } =\n                    serde_json::from_slice::<IndexPackageV>(line).unwrap_or_default();\n                let index = IndexPackage {\n                    name,\n                    vers,\n                    rust_version,\n                    v,\n                    deps: Default::default(),\n                    features: Default::default(),\n                    features2: Default::default(),\n                    cksum: Default::default(),\n                    yanked: Default::default(),\n                    links: Default::default(),\n                    pubtime: Default::default(),\n                };\n                let summary = index_package_to_summary(&index, source_id, cli_unstable)?;\n                (index, summary, false)\n            }\n        };\n        let v = index.v.unwrap_or(1);\n        tracing::trace!(\"json parsed registry {}/{}\", index.name, index.vers);\n\n        let v_max = if cli_unstable.bindeps {\n            INDEX_V_MAX + 1\n        } else {\n            INDEX_V_MAX\n        };\n\n        if v_max < v {\n            Ok(IndexSummary::Unsupported(summary, v))\n        } else if !valid {\n            Ok(IndexSummary::Invalid(summary))\n        } else if index.yanked.unwrap_or(false) {\n            Ok(IndexSummary::Yanked(summary))\n        } else {\n            Ok(IndexSummary::Candidate(summary))\n        }\n    }\n}\n\n/// Converts an encoded dependency in the registry to a cargo dependency\nfn registry_dependency_into_dep(\n    dep: RegistryDependency<'_>,\n    default: SourceId,\n    cli_unstable: &CliUnstable,\n) -> CargoResult<Dependency> {\n    let RegistryDependency {\n        name,\n        req,\n        mut features,\n        optional,\n        default_features,\n        target,\n        kind,\n        registry,\n        package,\n        public,\n        artifact,\n        bindep_target,\n        lib,\n    } = dep;\n\n    let id = if let Some(registry) = &registry {\n        SourceId::for_registry(&registry.into_url()?)?\n    } else {\n        default\n    };\n\n    let interned_name = InternedString::new(package.as_ref().unwrap_or(&name));\n    let mut dep = Dependency::parse(interned_name, Some(&req), id)?;\n    if package.is_some() {\n        dep.set_explicit_name_in_toml(name);\n    }\n    let kind = match kind.as_deref().unwrap_or(\"\") {\n        \"dev\" => DepKind::Development,\n        \"build\" => DepKind::Build,\n        _ => DepKind::Normal,\n    };\n\n    let platform = match target {\n        Some(target) => Some(target.parse()?),\n        None => None,\n    };\n\n    // All dependencies are private by default\n    let public = public.unwrap_or(false);\n\n    // Unfortunately older versions of cargo and/or the registry ended up\n    // publishing lots of entries where the features array contained the\n    // empty feature, \"\", inside. This confuses the resolution process much\n    // later on and these features aren't actually valid, so filter them all\n    // out here.\n    features.retain(|s| !s.is_empty());\n\n    // In index, \"registry\" is null if it is from the same index.\n    // In Cargo.toml, \"registry\" is None if it is from the default\n    if !id.is_crates_io() {\n        dep.set_registry_id(id);\n    }\n\n    if let Some(artifacts) = artifact {\n        let artifact = Artifact::parse(\n            &artifacts,\n            lib,\n            bindep_target.as_deref(),\n            cli_unstable.json_target_spec,\n        )?;\n        dep.set_artifact(artifact);\n    }\n\n    dep.set_optional(optional)\n        .set_default_features(default_features)\n        .set_features(features)\n        .set_platform(platform)\n        .set_kind(kind)\n        .set_public(public);\n\n    Ok(dep)\n}\n\n/// Like [`slice::split`] but is optimized by [`memchr`].\nfn split(haystack: &[u8], needle: u8) -> impl Iterator<Item = &[u8]> {\n    struct Split<'a> {\n        haystack: &'a [u8],\n        needle: u8,\n    }\n\n    impl<'a> Iterator for Split<'a> {\n        type Item = &'a [u8];\n\n        fn next(&mut self) -> Option<&'a [u8]> {\n            if self.haystack.is_empty() {\n                return None;\n            }\n            let (ret, remaining) = match memchr::memchr(self.needle, self.haystack) {\n                Some(pos) => (&self.haystack[..pos], &self.haystack[pos + 1..]),\n                None => (self.haystack, &[][..]),\n            };\n            self.haystack = remaining;\n            Some(ret)\n        }\n    }\n\n    Split { haystack, needle }\n}\n"
  },
  {
    "path": "src/cargo/sources/registry/local.rs",
    "content": "//! Access to a registry on the local filesystem. See [`LocalRegistry`] for more.\n\nuse crate::core::PackageId;\nuse crate::sources::registry::{LoadResponse, MaybeLock, RegistryConfig, RegistryData};\nuse crate::util::errors::CargoResult;\nuse crate::util::{Filesystem, GlobalContext};\nuse cargo_util::{Sha256, paths};\nuse std::fs::File;\nuse std::io::SeekFrom;\nuse std::io::{self, prelude::*};\nuse std::path::Path;\nuse std::task::Poll;\n\n/// A local registry is a registry that lives on the filesystem as a set of\n/// `.crate` files with an `index` directory in the [same format] as a remote\n/// registry.\n///\n/// This type is primarily accessed through the [`RegistryData`] trait.\n///\n/// When a local registry is requested for a package, it simply looks into what\n/// its index has under the `index` directory. When [`LocalRegistry::download`]\n/// is called, a local registry verifies the checksum of the requested `.crate`\n/// tarball and then unpacks it to `$CARGO_HOME/.registry/src`.\n///\n/// > Note that there is a third-party subcommand [`cargo-local-registry`],\n/// > which happened to be developed by a former Cargo team member when local\n/// > registry was introduced. The tool is to ease the burden of maintaining\n/// > local registries. However, in general the Cargo team avoids recommending\n/// > any specific third-party crate. Just FYI.\n///\n/// [same format]: super#the-format-of-the-index\n/// [`cargo-local-registry`]: https://crates.io/crates/cargo-local-registry\n///\n/// # Filesystem hierarchy\n///\n/// Here is an example layout of a local registry on a local filesystem:\n///\n/// ```text\n/// [registry root]/\n/// ├── index/                      # registry index\n/// │  ├── an/\n/// │  │  └── yh/\n/// │  │     └── anyhow\n/// │  ├── ru/\n/// │  │  └── st/\n/// │  │     ├── rustls\n/// │  │     └── rustls-ffi\n/// │  └── se/\n/// │     └── mv/\n/// │        └── semver\n/// ├── anyhow-1.0.71.crate         # pre-downloaded crate tarballs\n/// ├── rustls-0.20.8.crate\n/// ├── rustls-ffi-0.8.2.crate\n/// └── semver-1.0.17.crate\n/// ```\n///\n/// For general concepts of registries, see the [module-level documentation](crate::sources::registry).\npub struct LocalRegistry<'gctx> {\n    /// Path to the registry index.\n    index_path: Filesystem,\n    /// Root path of this local registry.\n    root: Filesystem,\n    /// Path where this local registry extract `.crate` tarballs to.\n    src_path: Filesystem,\n    gctx: &'gctx GlobalContext,\n    /// Whether this source has updated all package information it may contain.\n    updated: bool,\n    /// Disables status messages.\n    quiet: bool,\n}\n\nimpl<'gctx> LocalRegistry<'gctx> {\n    /// Creates a local registry at `root`.\n    ///\n    /// * `name` --- Name of a path segment where `.crate` tarballs are stored.\n    ///   Expect to be unique.\n    pub fn new(root: &Path, gctx: &'gctx GlobalContext, name: &str) -> LocalRegistry<'gctx> {\n        LocalRegistry {\n            src_path: gctx.registry_source_path().join(name),\n            index_path: Filesystem::new(root.join(\"index\")),\n            root: Filesystem::new(root.to_path_buf()),\n            gctx,\n            updated: false,\n            quiet: false,\n        }\n    }\n}\n\nimpl<'gctx> RegistryData for LocalRegistry<'gctx> {\n    fn prepare(&self) -> CargoResult<()> {\n        Ok(())\n    }\n\n    fn index_path(&self) -> &Filesystem {\n        &self.index_path\n    }\n\n    fn cache_path(&self) -> &Filesystem {\n        &self.root\n    }\n\n    fn assert_index_locked<'a>(&self, path: &'a Filesystem) -> &'a Path {\n        // Note that the `*_unlocked` variant is used here since we're not\n        // modifying the index and it's required to be externally synchronized.\n        path.as_path_unlocked()\n    }\n\n    fn load(\n        &mut self,\n        root: &Path,\n        path: &Path,\n        _index_version: Option<&str>,\n    ) -> Poll<CargoResult<LoadResponse>> {\n        if self.updated {\n            let raw_data = match paths::read_bytes(&root.join(path)) {\n                Err(e)\n                    if e.downcast_ref::<io::Error>()\n                        .map_or(false, |ioe| ioe.kind() == io::ErrorKind::NotFound) =>\n                {\n                    return Poll::Ready(Ok(LoadResponse::NotFound));\n                }\n                r => r,\n            }?;\n            Poll::Ready(Ok(LoadResponse::Data {\n                raw_data,\n                index_version: None,\n            }))\n        } else {\n            Poll::Pending\n        }\n    }\n\n    fn config(&mut self) -> Poll<CargoResult<Option<RegistryConfig>>> {\n        // Local registries don't have configuration for remote APIs or anything\n        // like that\n        Poll::Ready(Ok(None))\n    }\n\n    fn block_until_ready(&mut self) -> CargoResult<()> {\n        if self.updated {\n            return Ok(());\n        }\n        // Nothing to update, we just use what's on disk. Verify it actually\n        // exists though. We don't use any locks as we're just checking whether\n        // these directories exist.\n        let root = self.root.clone().into_path_unlocked();\n        if !root.is_dir() {\n            anyhow::bail!(\"local registry path is not a directory: {}\", root.display());\n        }\n        let index_path = self.index_path.clone().into_path_unlocked();\n        if !index_path.is_dir() {\n            anyhow::bail!(\n                \"local registry index path is not a directory: {}\",\n                index_path.display()\n            );\n        }\n        self.updated = true;\n        Ok(())\n    }\n\n    fn invalidate_cache(&mut self) {\n        // Local registry has no cache - just reads from disk.\n    }\n\n    fn set_quiet(&mut self, _quiet: bool) {\n        self.quiet = true;\n    }\n\n    fn is_updated(&self) -> bool {\n        self.updated\n    }\n\n    fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult<MaybeLock> {\n        // Note that the usage of `into_path_unlocked` here is because the local\n        // crate files here never change in that we're not the one writing them,\n        // so it's not our responsibility to synchronize access to them.\n        let path = self.root.join(&pkg.tarball_name()).into_path_unlocked();\n        let mut crate_file = paths::open(&path)?;\n\n        // If we've already got an unpacked version of this crate, then skip the\n        // checksum below as it is in theory already verified.\n        let dst = path.file_stem().unwrap();\n        if self.src_path.join(dst).into_path_unlocked().exists() {\n            return Ok(MaybeLock::Ready(crate_file));\n        }\n\n        if !self.quiet {\n            self.gctx.shell().status(\"Unpacking\", pkg)?;\n        }\n\n        // We don't actually need to download anything per-se, we just need to\n        // verify the checksum matches the .crate file itself.\n        let actual = Sha256::new().update_file(&crate_file)?.finish_hex();\n        if actual != checksum {\n            anyhow::bail!(\"failed to verify the checksum of `{}`\", pkg)\n        }\n\n        crate_file.seek(SeekFrom::Start(0))?;\n\n        Ok(MaybeLock::Ready(crate_file))\n    }\n\n    fn finish_download(\n        &mut self,\n        _pkg: PackageId,\n        _checksum: &str,\n        _data: &[u8],\n    ) -> CargoResult<File> {\n        panic!(\"this source doesn't download\")\n    }\n}\n"
  },
  {
    "path": "src/cargo/sources/registry/mod.rs",
    "content": "//! A `Source` for registry-based packages.\n//!\n//! # What's a Registry?\n//!\n//! [Registries] are central locations where packages can be uploaded to,\n//! discovered, and searched for. The purpose of a registry is to have a\n//! location that serves as permanent storage for versions of a crate over time.\n//!\n//! Compared to git sources (see [`GitSource`]), a registry provides many\n//! packages as well as many versions simultaneously. Git sources can also\n//! have commits deleted through rebasings where registries cannot have their\n//! versions deleted.\n//!\n//! In Cargo, [`RegistryData`] is an abstraction over each kind of actual\n//! registry, and [`RegistrySource`] connects those implementations to\n//! [`Source`] trait. Two prominent features these abstractions provide are\n//!\n//! * A way to query the metadata of a package from a registry. The metadata\n//!   comes from the index.\n//! * A way to download package contents (a.k.a source files) that are required\n//!   when building the package itself.\n//!\n//! We'll cover each functionality later.\n//!\n//! [Registries]: https://doc.rust-lang.org/nightly/cargo/reference/registries.html\n//! [`GitSource`]: super::GitSource\n//!\n//! # Different Kinds of Registries\n//!\n//! Cargo provides multiple kinds of registries. Each of them serves the index\n//! and package contents in a slightly different way. Namely,\n//!\n//! * [`LocalRegistry`] --- Serves the index and package contents entirely on\n//!   a local filesystem.\n//! * [`RemoteRegistry`] --- Serves the index ahead of time from a Git\n//!   repository, and package contents are downloaded as needed.\n//! * [`HttpRegistry`] --- Serves both the index and package contents on demand\n//!   over a HTTP-based registry API. This is the default starting from 1.70.0.\n//!\n//! Each registry has its own [`RegistryData`] implementation, and can be\n//! created from either [`RegistrySource::local`] or [`RegistrySource::remote`].\n//!\n//! [`LocalRegistry`]: local::LocalRegistry\n//! [`RemoteRegistry`]: remote::RemoteRegistry\n//! [`HttpRegistry`]: http_remote::HttpRegistry\n//!\n//! # The Index of a Registry\n//!\n//! One of the major difficulties with a registry is that hosting so many\n//! packages may quickly run into performance problems when dealing with\n//! dependency graphs. It's infeasible for cargo to download the entire contents\n//! of the registry just to resolve one package's dependencies, for example. As\n//! a result, cargo needs some efficient method of querying what packages are\n//! available on a registry, what versions are available, and what the\n//! dependencies for each version is.\n//!\n//! To solve the problem, a registry must provide an index of package metadata.\n//! The index of a registry is essentially an easily query-able version of the\n//! registry's database for a list of versions of a package as well as a list\n//! of dependencies for each version. The exact format of the index is\n//! described later.\n//!\n//! See the [`index`] module for topics about the management, parsing, caching,\n//! and versioning for the on-disk index.\n//!\n//! ## The Format of The Index\n//!\n//! The index is a store for the list of versions for all packages known, so its\n//! format on disk is optimized slightly to ensure that `ls registry` doesn't\n//! produce a list of all packages ever known. The index also wants to ensure\n//! that there's not a million files which may actually end up hitting\n//! filesystem limits at some point. To this end, a few decisions were made\n//! about the format of the registry:\n//!\n//! 1. Each crate will have one file corresponding to it. Each version for a\n//!    crate will just be a line in this file (see [`cargo_util_schemas::index::IndexPackage`] for its\n//!    representation).\n//! 2. There will be two tiers of directories for crate names, under which\n//!    crates corresponding to those tiers will be located.\n//!    (See [`cargo_util::registry::make_dep_path`] for the implementation of\n//!    this layout hierarchy.)\n//!\n//! As an example, this is an example hierarchy of an index:\n//!\n//! ```notrust\n//! .\n//! ├── 3\n//! │   └── u\n//! │       └── url\n//! ├── bz\n//! │   └── ip\n//! │       └── bzip2\n//! ├── config.json\n//! ├── en\n//! │   └── co\n//! │       └── encoding\n//! └── li\n//!     ├── bg\n//!     │   └── libgit2\n//!     └── nk\n//!         └── link-config\n//! ```\n//!\n//! The root of the index contains a `config.json` file with a few entries\n//! corresponding to the registry (see [`RegistryConfig`] below).\n//!\n//! Otherwise, there are three numbered directories (1, 2, 3) for crates with\n//! names 1, 2, and 3 characters in length. The 1/2 directories simply have the\n//! crate files underneath them, while the 3 directory is sharded by the first\n//! letter of the crate name.\n//!\n//! Otherwise the top-level directory contains many two-letter directory names,\n//! each of which has many sub-folders with two letters. At the end of all these\n//! are the actual crate files themselves.\n//!\n//! The purpose of this layout is to hopefully cut down on `ls` sizes as well as\n//! efficient lookup based on the crate name itself.\n//!\n//! See [The Cargo Book: Registry Index][registry-index] for the public\n//! interface on the index format.\n//!\n//! [registry-index]: https://doc.rust-lang.org/nightly/cargo/reference/registry-index.html\n//!\n//! ## The Index Files\n//!\n//! Each file in the index is the history of one crate over time. Each line in\n//! the file corresponds to one version of a crate, stored in JSON format (see\n//! the [`cargo_util_schemas::index::IndexPackage`] structure).\n//!\n//! As new versions are published, new lines are appended to this file. **The\n//! only modifications to this file that should happen over time are yanks of a\n//! particular version.**\n//!\n//! # Downloading Packages\n//!\n//! The purpose of the index was to provide an efficient method to resolve the\n//! dependency graph for a package. After resolution has been performed, we need\n//! to download the contents of packages so we can read the full manifest and\n//! build the source code.\n//!\n//! To accomplish this, [`RegistryData::download`] will \"make\" an HTTP request\n//! per-package requested to download tarballs into a local cache. These\n//! tarballs will then be unpacked into a destination folder.\n//!\n//! Note that because versions uploaded to the registry are frozen forever that\n//! the HTTP download and unpacking can all be skipped if the version has\n//! already been downloaded and unpacked. This caching allows us to only\n//! download a package when absolutely necessary.\n//!\n//! # Filesystem Hierarchy\n//!\n//! Overall, the `$HOME/.cargo` looks like this when talking about the registry\n//! (remote registries, specifically):\n//!\n//! ```notrust\n//! # A folder under which all registry metadata is hosted (similar to\n//! # $HOME/.cargo/git)\n//! $HOME/.cargo/registry/\n//!\n//!     # For each registry that cargo knows about (keyed by hostname + hash)\n//!     # there is a folder which is the checked out version of the index for\n//!     # the registry in this location. Note that this is done so cargo can\n//!     # support multiple registries simultaneously\n//!     index/\n//!         registry1-<hash>/\n//!         registry2-<hash>/\n//!         ...\n//!\n//!     # This folder is a cache for all downloaded tarballs (`.crate` file)\n//!     # from a registry. Once downloaded and verified, a tarball never changes.\n//!     cache/\n//!         registry1-<hash>/<pkg>-<version>.crate\n//!         ...\n//!\n//!     # Location in which all tarballs are unpacked. Each tarball is known to\n//!     # be frozen after downloading, so transitively this folder is also\n//!     # frozen once its unpacked (it's never unpacked again)\n//!     # CAVEAT: They are not read-only. See rust-lang/cargo#9455.\n//!     src/\n//!         registry1-<hash>/<pkg>-<version>/...\n//!         ...\n//! ```\n//!\n\nuse std::collections::HashSet;\nuse std::fs;\nuse std::fs::{File, OpenOptions};\nuse std::io;\nuse std::io::Read;\nuse std::io::Write;\nuse std::path::{Path, PathBuf};\nuse std::task::{Poll, ready};\n\nuse annotate_snippets::Level;\nuse anyhow::Context as _;\nuse cargo_util::paths::{self, exclude_from_backups_and_indexing};\nuse flate2::read::GzDecoder;\nuse serde::Deserialize;\nuse serde::Serialize;\nuse tar::Archive;\nuse tracing::debug;\n\nuse crate::core::dependency::Dependency;\nuse crate::core::global_cache_tracker;\nuse crate::core::{Package, PackageId, SourceId};\nuse crate::sources::PathSource;\nuse crate::sources::source::MaybePackage;\nuse crate::sources::source::QueryKind;\nuse crate::sources::source::Source;\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::interning::InternedString;\nuse crate::util::network::PollExt;\nuse crate::util::{CargoResult, Filesystem, GlobalContext, LimitErrorReader, restricted_names};\nuse crate::util::{VersionExt, hex};\n\n/// The `.cargo-ok` file is used to track if the source is already unpacked.\n/// See [`RegistrySource::unpack_package`] for more.\n///\n/// Not to be confused with `.cargo-ok` file in git sources.\nconst PACKAGE_SOURCE_LOCK: &str = \".cargo-ok\";\n\npub const CRATES_IO_INDEX: &str = \"https://github.com/rust-lang/crates.io-index\";\npub const CRATES_IO_HTTP_INDEX: &str = \"sparse+https://index.crates.io/\";\npub const CRATES_IO_REGISTRY: &str = \"crates-io\";\npub const CRATES_IO_DOMAIN: &str = \"crates.io\";\n\n/// The content inside `.cargo-ok`.\n/// See [`RegistrySource::unpack_package`] for more.\n#[derive(Deserialize, Serialize)]\n#[serde(rename_all = \"kebab-case\")]\nstruct LockMetadata {\n    /// The version of `.cargo-ok` file\n    v: u32,\n}\n\n/// A [`Source`] implementation for a local or a remote registry.\n///\n/// This contains common functionality that is shared between each registry\n/// kind, with the registry-specific logic implemented as part of the\n/// [`RegistryData`] trait referenced via the `ops` field.\n///\n/// For general concepts of registries, see the [module-level documentation](crate::sources::registry).\npub struct RegistrySource<'gctx> {\n    /// A unique name of the source (typically used as the directory name\n    /// where its cached content is stored).\n    name: InternedString,\n    /// The unique identifier of this source.\n    source_id: SourceId,\n    /// The path where crate files are extracted (`$CARGO_HOME/registry/src/$REG-HASH`).\n    src_path: Filesystem,\n    /// Local reference to [`GlobalContext`] for convenience.\n    gctx: &'gctx GlobalContext,\n    /// Abstraction for interfacing to the different registry kinds.\n    ops: Box<dyn RegistryData + 'gctx>,\n    /// Interface for managing the on-disk index.\n    index: index::RegistryIndex<'gctx>,\n    /// A set of packages that should be allowed to be used, even if they are\n    /// yanked.\n    ///\n    /// This is populated from the entries in `Cargo.lock` to ensure that\n    /// `cargo update somepkg` won't unlock yanked entries in `Cargo.lock`.\n    /// Otherwise, the resolver would think that those entries no longer\n    /// exist, and it would trigger updates to unrelated packages.\n    yanked_whitelist: HashSet<PackageId>,\n    /// Yanked versions that have already been selected during queries.\n    ///\n    /// As of this writing, this is for not emitting the `--precise <yanked>`\n    /// warning twice, with the assumption of (`dep.package_name()` + `--precise`\n    /// version) being sufficient to uniquely identify the same query result.\n    selected_precise_yanked: HashSet<(InternedString, semver::Version)>,\n}\n\n/// The [`config.json`] file stored in the index.\n///\n/// The config file may look like:\n///\n/// ```json\n/// {\n///     \"dl\": \"https://example.com/api/{crate}/{version}/download\",\n///     \"api\": \"https://example.com/api\",\n///     \"auth-required\": false             # unstable feature (RFC 3139)\n/// }\n/// ```\n///\n/// [`config.json`]: https://doc.rust-lang.org/nightly/cargo/reference/registry-index.html#index-configuration\n#[derive(Deserialize, Debug, Clone)]\n#[serde(rename_all = \"kebab-case\")]\npub struct RegistryConfig {\n    /// Download endpoint for all crates.\n    ///\n    /// The string is a template which will generate the download URL for the\n    /// tarball of a specific version of a crate. The substrings `{crate}` and\n    /// `{version}` will be replaced with the crate's name and version\n    /// respectively.  The substring `{prefix}` will be replaced with the\n    /// crate's prefix directory name, and the substring `{lowerprefix}` will\n    /// be replaced with the crate's prefix directory name converted to\n    /// lowercase. The substring `{sha256-checksum}` will be replaced with the\n    /// crate's sha256 checksum.\n    ///\n    /// For backwards compatibility, if the string does not contain any\n    /// markers (`{crate}`, `{version}`, `{prefix}`, or `{lowerprefix}`), it\n    /// will be extended with `/{crate}/{version}/download` to\n    /// support registries like crates.io which were created before the\n    /// templating setup was created.\n    ///\n    /// For more on the template of the download URL, see [Index Configuration](\n    /// https://doc.rust-lang.org/nightly/cargo/reference/registry-index.html#index-configuration).\n    pub dl: String,\n\n    /// API endpoint for the registry. This is what's actually hit to perform\n    /// operations like yanks, owner modifications, publish new crates, etc.\n    /// If this is None, the registry does not support API commands.\n    pub api: Option<String>,\n\n    /// Whether all operations require authentication. See [RFC 3139].\n    ///\n    /// [RFC 3139]: https://rust-lang.github.io/rfcs/3139-cargo-alternative-registry-auth.html\n    #[serde(default)]\n    pub auth_required: bool,\n}\n\n/// Result from loading data from a registry.\npub enum LoadResponse {\n    /// The cache is valid. The cached data should be used.\n    CacheValid,\n\n    /// The cache is out of date. Returned data should be used.\n    Data {\n        raw_data: Vec<u8>,\n        /// Version of this data to determine whether it is out of date.\n        index_version: Option<String>,\n    },\n\n    /// The requested crate was found.\n    NotFound,\n}\n\n/// An abstract interface to handle both a local and remote registry.\n///\n/// This allows [`RegistrySource`] to abstractly handle each registry kind.\n///\n/// For general concepts of registries, see the [module-level documentation](crate::sources::registry).\npub trait RegistryData {\n    /// Performs initialization for the registry.\n    ///\n    /// This should be safe to call multiple times, the implementation is\n    /// expected to not do any work if it is already prepared.\n    fn prepare(&self) -> CargoResult<()>;\n\n    /// Returns the path to the index.\n    ///\n    /// Note that different registries store the index in different formats\n    /// (remote = git, http & local = files).\n    fn index_path(&self) -> &Filesystem;\n\n    /// Returns the path of the directory that stores the cache of `.crate` files.\n    ///\n    /// The directory is currently expected to contain a flat list of all `.crate` files,\n    /// named `<package-name>-<version>.crate`.\n    fn cache_path(&self) -> &Filesystem;\n\n    /// Loads the JSON for a specific named package from the index.\n    ///\n    /// * `root` is the root path to the index.\n    /// * `path` is the relative path to the package to load (like `ca/rg/cargo`).\n    /// * `index_version` is the version of the requested crate data currently\n    ///    in cache. This is useful for checking if a local cache is outdated.\n    fn load(\n        &mut self,\n        root: &Path,\n        path: &Path,\n        index_version: Option<&str>,\n    ) -> Poll<CargoResult<LoadResponse>>;\n\n    /// Loads the `config.json` file and returns it.\n    ///\n    /// Local registries don't have a config, and return `None`.\n    fn config(&mut self) -> Poll<CargoResult<Option<RegistryConfig>>>;\n\n    /// Invalidates locally cached data.\n    fn invalidate_cache(&mut self);\n\n    /// If quiet, the source should not display any progress or status messages.\n    fn set_quiet(&mut self, quiet: bool);\n\n    /// Is the local cached data up-to-date?\n    fn is_updated(&self) -> bool;\n\n    /// Prepare to start downloading a `.crate` file.\n    ///\n    /// Despite the name, this doesn't actually download anything. If the\n    /// `.crate` is already downloaded, then it returns [`MaybeLock::Ready`].\n    /// If it hasn't been downloaded, then it returns [`MaybeLock::Download`]\n    /// which contains the URL to download. The [`crate::core::package::Downloads`]\n    /// system handles the actual download process. After downloading, it\n    /// calls [`Self::finish_download`] to save the downloaded file.\n    ///\n    /// `checksum` is currently only used by local registries to verify the\n    /// file contents (because local registries never actually download\n    /// anything). Remote registries will validate the checksum in\n    /// `finish_download`. For already downloaded `.crate` files, it does not\n    /// validate the checksum, assuming the filesystem does not suffer from\n    /// corruption or manipulation.\n    fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult<MaybeLock>;\n\n    /// Finish a download by saving a `.crate` file to disk.\n    ///\n    /// After [`crate::core::package::Downloads`] has finished a download,\n    /// it will call this to save the `.crate` file. This is only relevant\n    /// for remote registries. This should validate the checksum and save\n    /// the given data to the on-disk cache.\n    ///\n    /// Returns a [`File`] handle to the `.crate` file, positioned at the start.\n    fn finish_download(&mut self, pkg: PackageId, checksum: &str, data: &[u8])\n    -> CargoResult<File>;\n\n    /// Returns whether or not the `.crate` file is already downloaded.\n    fn is_crate_downloaded(&self, _pkg: PackageId) -> bool {\n        true\n    }\n\n    /// Validates that the global package cache lock is held.\n    ///\n    /// Given the [`Filesystem`], this will make sure that the package cache\n    /// lock is held. If not, it will panic. See\n    /// [`GlobalContext::acquire_package_cache_lock`] for acquiring the global lock.\n    ///\n    /// Returns the [`Path`] to the [`Filesystem`].\n    fn assert_index_locked<'a>(&self, path: &'a Filesystem) -> &'a Path;\n\n    /// Block until all outstanding `Poll::Pending` requests are `Poll::Ready`.\n    fn block_until_ready(&mut self) -> CargoResult<()>;\n}\n\n/// The status of [`RegistryData::download`] which indicates if a `.crate`\n/// file has already been downloaded, or if not then the URL to download.\npub enum MaybeLock {\n    /// The `.crate` file is already downloaded. [`File`] is a handle to the\n    /// opened `.crate` file on the filesystem.\n    Ready(File),\n    /// The `.crate` file is not downloaded, here's the URL to download it from.\n    ///\n    /// `descriptor` is just a text string to display to the user of what is\n    /// being downloaded.\n    Download {\n        url: String,\n        descriptor: String,\n        authorization: Option<String>,\n    },\n}\n\nmod download;\nmod http_remote;\npub(crate) mod index;\npub use index::IndexSummary;\nmod local;\nmod remote;\n\n/// Generates a unique name for [`SourceId`] to have a unique path to put their\n/// index files.\nfn short_name(id: SourceId, is_shallow: bool) -> String {\n    // CAUTION: This should not change between versions. If you change how\n    // this is computed, it will orphan previously cached data, forcing the\n    // cache to be rebuilt and potentially wasting significant disk space. If\n    // you change it, be cautious of the impact. See `test_cratesio_hash` for\n    // a similar discussion.\n    let hash = hex::short_hash(&id);\n    let ident = id.url().host_str().unwrap_or(\"\").to_string();\n    let mut name = format!(\"{}-{}\", ident, hash);\n    if is_shallow {\n        name.push_str(\"-shallow\");\n    }\n    name\n}\n\nimpl<'gctx> RegistrySource<'gctx> {\n    /// Creates a [`Source`] of a \"remote\" registry.\n    /// It could be either an HTTP-based [`http_remote::HttpRegistry`] or\n    /// a Git-based [`remote::RemoteRegistry`].\n    ///\n    /// * `yanked_whitelist` --- Packages allowed to be used, even if they are yanked.\n    pub fn remote(\n        source_id: SourceId,\n        yanked_whitelist: &HashSet<PackageId>,\n        gctx: &'gctx GlobalContext,\n    ) -> CargoResult<RegistrySource<'gctx>> {\n        assert!(source_id.is_remote_registry());\n        let name = short_name(\n            source_id,\n            gctx.cli_unstable()\n                .git\n                .map_or(false, |features| features.shallow_index)\n                && !source_id.is_sparse(),\n        );\n        let ops = if source_id.is_sparse() {\n            Box::new(http_remote::HttpRegistry::new(source_id, gctx, &name)?) as Box<_>\n        } else {\n            Box::new(remote::RemoteRegistry::new(source_id, gctx, &name)) as Box<_>\n        };\n\n        Ok(RegistrySource::new(\n            source_id,\n            gctx,\n            &name,\n            ops,\n            yanked_whitelist,\n        ))\n    }\n\n    /// Creates a [`Source`] of a local registry, with [`local::LocalRegistry`] under the hood.\n    ///\n    /// * `path` --- The root path of a local registry on the file system.\n    /// * `yanked_whitelist` --- Packages allowed to be used, even if they are yanked.\n    pub fn local(\n        source_id: SourceId,\n        path: &Path,\n        yanked_whitelist: &HashSet<PackageId>,\n        gctx: &'gctx GlobalContext,\n    ) -> RegistrySource<'gctx> {\n        let name = short_name(source_id, false);\n        let ops = local::LocalRegistry::new(path, gctx, &name);\n        RegistrySource::new(source_id, gctx, &name, Box::new(ops), yanked_whitelist)\n    }\n\n    /// Creates a source of a registry. This is a inner helper function.\n    ///\n    /// * `name` --- Name of a path segment which may affect where `.crate`\n    ///   tarballs, the registry index and cache are stored. Expect to be unique.\n    /// * `ops` --- The underlying [`RegistryData`] type.\n    /// * `yanked_whitelist` --- Packages allowed to be used, even if they are yanked.\n    fn new(\n        source_id: SourceId,\n        gctx: &'gctx GlobalContext,\n        name: &str,\n        ops: Box<dyn RegistryData + 'gctx>,\n        yanked_whitelist: &HashSet<PackageId>,\n    ) -> RegistrySource<'gctx> {\n        RegistrySource {\n            name: name.into(),\n            src_path: gctx.registry_source_path().join(name),\n            gctx,\n            source_id,\n            index: index::RegistryIndex::new(source_id, ops.index_path(), gctx),\n            yanked_whitelist: yanked_whitelist.clone(),\n            ops,\n            selected_precise_yanked: HashSet::new(),\n        }\n    }\n\n    /// Decode the [configuration](RegistryConfig) stored within the registry.\n    ///\n    /// This requires that the index has been at least checked out.\n    pub fn config(&mut self) -> Poll<CargoResult<Option<RegistryConfig>>> {\n        self.ops.config()\n    }\n\n    /// Unpacks a downloaded package into a location where it's ready to be\n    /// compiled.\n    ///\n    /// No action is taken if the source looks like it's already unpacked.\n    ///\n    /// # History of interruption detection with `.cargo-ok` file\n    ///\n    /// Cargo has always included a `.cargo-ok` file ([`PACKAGE_SOURCE_LOCK`])\n    /// to detect if extraction was interrupted, but it was originally empty.\n    ///\n    /// In 1.34, Cargo was changed to create the `.cargo-ok` file before it\n    /// started extraction to implement fine-grained locking. After it was\n    /// finished extracting, it wrote two bytes to indicate it was complete.\n    /// It would use the length check to detect if it was possibly interrupted.\n    ///\n    /// In 1.36, Cargo changed to not use fine-grained locking, and instead used\n    /// a global lock. The use of `.cargo-ok` was no longer needed for locking\n    /// purposes, but was kept to detect when extraction was interrupted.\n    ///\n    /// In 1.49, Cargo changed to not create the `.cargo-ok` file before it\n    /// started extraction to deal with `.crate` files that inexplicably had\n    /// a `.cargo-ok` file in them.\n    ///\n    /// In 1.64, Cargo changed to detect `.crate` files with `.cargo-ok` files\n    /// in them in response to [CVE-2022-36113], which dealt with malicious\n    /// `.crate` files making `.cargo-ok` a symlink causing cargo to write \"ok\"\n    /// to any arbitrary file on the filesystem it has permission to.\n    ///\n    /// In 1.71, `.cargo-ok` changed to contain a JSON `{ v: 1 }` to indicate\n    /// the version of it. A failure of parsing will result in a heavy-hammer\n    /// approach that unpacks the `.crate` file again. This is in response to a\n    /// security issue that the unpacking didn't respect umask on Unix systems.\n    ///\n    /// This is all a long-winded way of explaining the circumstances that might\n    /// cause a directory to contain a `.cargo-ok` file that is empty or\n    /// otherwise corrupted. Either this was extracted by a version of Rust\n    /// before 1.34, in which case everything should be fine. However, an empty\n    /// file created by versions 1.36 to 1.49 indicates that the extraction was\n    /// interrupted and that we need to start again.\n    ///\n    /// Another possibility is that the filesystem is simply corrupted, in\n    /// which case deleting the directory might be the safe thing to do. That\n    /// is probably unlikely, though.\n    ///\n    /// To be safe, we delete the directory and start over again if an empty\n    /// `.cargo-ok` file is found.\n    ///\n    /// [CVE-2022-36113]: https://blog.rust-lang.org/2022/09/14/cargo-cves.html#arbitrary-file-corruption-cve-2022-36113\n    fn unpack_package(&self, pkg: PackageId, tarball: &File) -> CargoResult<PathBuf> {\n        let package_dir = format!(\"{}-{}\", pkg.name(), pkg.version());\n        let dst = self.src_path.join(&package_dir);\n        let path = dst.join(PACKAGE_SOURCE_LOCK);\n        let path = self\n            .gctx\n            .assert_package_cache_locked(CacheLockMode::DownloadExclusive, &path);\n        let unpack_dir = path.parent().unwrap();\n        match fs::read_to_string(path) {\n            Ok(ok) => match serde_json::from_str::<LockMetadata>(&ok) {\n                Ok(lock_meta) if lock_meta.v == 1 => {\n                    self.gctx\n                        .deferred_global_last_use()?\n                        .mark_registry_src_used(global_cache_tracker::RegistrySrc {\n                            encoded_registry_name: self.name,\n                            package_dir: package_dir.into(),\n                            size: None,\n                        });\n                    return Ok(unpack_dir.to_path_buf());\n                }\n                _ => {\n                    if ok == \"ok\" {\n                        tracing::debug!(\"old `ok` content found, clearing cache\");\n                    } else {\n                        tracing::warn!(\"unrecognized .cargo-ok content, clearing cache: {ok}\");\n                    }\n                    // See comment of `unpack_package` about why removing all stuff.\n                    paths::remove_dir_all(dst.as_path_unlocked())?;\n                }\n            },\n            Err(e) if e.kind() == io::ErrorKind::NotFound => {}\n            Err(e) => anyhow::bail!(\"unable to read .cargo-ok file at {path:?}: {e}\"),\n        }\n        dst.create_dir()?;\n\n        let bytes_written = unpack(self.gctx, tarball, unpack_dir, &|_| true)?;\n        update_mtime_for_generated_files(unpack_dir);\n\n        // Now that we've finished unpacking, create and write to the lock file to indicate that\n        // unpacking was successful.\n        let mut ok = OpenOptions::new()\n            .create_new(true)\n            .read(true)\n            .write(true)\n            .open(&path)\n            .with_context(|| format!(\"failed to open `{}`\", path.display()))?;\n\n        let lock_meta = LockMetadata { v: 1 };\n        write!(ok, \"{}\", serde_json::to_string(&lock_meta).unwrap())?;\n\n        self.gctx\n            .deferred_global_last_use()?\n            .mark_registry_src_used(global_cache_tracker::RegistrySrc {\n                encoded_registry_name: self.name,\n                package_dir: package_dir.into(),\n                size: Some(bytes_written),\n            });\n\n        Ok(unpack_dir.to_path_buf())\n    }\n\n    /// Unpacks the `.crate` tarball of the package in a given directory.\n    ///\n    /// Returns the path to the crate tarball directory,\n    /// which is always `<unpack_dir>/<pkg>-<version>`.\n    ///\n    /// This holds some assumptions\n    ///\n    /// * The associated tarball already exists\n    /// * If this is a local registry,\n    ///   the package cache lock must be externally synchronized.\n    ///   Cargo does not take care of it being locked or not.\n    pub fn unpack_package_in(\n        &self,\n        pkg: &PackageId,\n        unpack_dir: &Path,\n        include: &dyn Fn(&Path) -> bool,\n    ) -> CargoResult<PathBuf> {\n        let path = self.ops.cache_path().join(pkg.tarball_name());\n        let path = self.ops.assert_index_locked(&path);\n        let dst = unpack_dir.join(format!(\"{}-{}\", pkg.name(), pkg.version()));\n        let tarball =\n            File::open(path).with_context(|| format!(\"failed to open {}\", path.display()))?;\n        unpack(self.gctx, &tarball, &dst, include)?;\n        update_mtime_for_generated_files(&dst);\n        Ok(dst)\n    }\n\n    /// Turns the downloaded `.crate` tarball file into a [`Package`].\n    ///\n    /// This unconditionally sets checksum for the returned package, so it\n    /// should only be called after doing integrity check. That is to say,\n    /// you need to call either [`RegistryData::download`] or\n    /// [`RegistryData::finish_download`] before calling this method.\n    fn get_pkg(&mut self, package: PackageId, path: &File) -> CargoResult<Package> {\n        let path = self\n            .unpack_package(package, path)\n            .with_context(|| format!(\"failed to unpack package `{}`\", package))?;\n        let mut src = PathSource::new(&path, self.source_id, self.gctx);\n        src.load()?;\n        let mut pkg = match src.download(package)? {\n            MaybePackage::Ready(pkg) => pkg,\n            MaybePackage::Download { .. } => unreachable!(),\n        };\n\n        // After we've loaded the package configure its summary's `checksum`\n        // field with the checksum we know for this `PackageId`.\n        let cksum = self\n            .index\n            .hash(package, &mut *self.ops)\n            .expect(\"a downloaded dep now pending!?\")\n            .expect(\"summary not found\");\n        pkg.manifest_mut()\n            .summary_mut()\n            .set_checksum(cksum.to_string());\n\n        Ok(pkg)\n    }\n}\n\nimpl<'gctx> Source for RegistrySource<'gctx> {\n    fn query(\n        &mut self,\n        dep: &Dependency,\n        kind: QueryKind,\n        f: &mut dyn FnMut(IndexSummary),\n    ) -> Poll<CargoResult<()>> {\n        let mut req = dep.version_req().clone();\n\n        // Handle `cargo update --precise` here.\n        if let Some((_, requested)) = self\n            .source_id\n            .precise_registry_version(dep.package_name().as_str())\n            .filter(|(c, to)| {\n                if to.is_prerelease() && self.gctx.cli_unstable().unstable_options {\n                    req.matches_prerelease(c)\n                } else {\n                    req.matches(c)\n                }\n            })\n        {\n            req.precise_to(&requested);\n        }\n\n        let mut called = false;\n        let callback = &mut |s| {\n            called = true;\n            f(s);\n        };\n\n        // If this is a locked dependency, then it came from a lock file and in\n        // theory the registry is known to contain this version. If, however, we\n        // come back with no summaries, then our registry may need to be\n        // updated, so we fall back to performing a lazy update.\n        if kind == QueryKind::Exact && req.is_locked() && !self.ops.is_updated() {\n            debug!(\"attempting query without update\");\n            ready!(\n                self.index\n                    .query_inner(dep.package_name(), &req, &mut *self.ops, &mut |s| {\n                        if matches!(s, IndexSummary::Candidate(_) | IndexSummary::Yanked(_))\n                            && dep.matches(s.as_summary())\n                        {\n                            // We are looking for a package from a lock file so we do not care about yank\n                            callback(s)\n                        }\n                    },)\n            )?;\n            if called {\n                Poll::Ready(Ok(()))\n            } else {\n                debug!(\"falling back to an update\");\n                self.invalidate_cache();\n                Poll::Pending\n            }\n        } else {\n            let mut precise_yanked_in_use = false;\n            ready!(\n                self.index\n                    .query_inner(dep.package_name(), &req, &mut *self.ops, &mut |s| {\n                        let matched = match kind {\n                            QueryKind::Exact | QueryKind::RejectedVersions => {\n                                if req.is_precise() && self.gctx.cli_unstable().unstable_options {\n                                    dep.matches_prerelease(s.as_summary())\n                                } else {\n                                    dep.matches(s.as_summary())\n                                }\n                            }\n                            QueryKind::AlternativeNames => true,\n                            QueryKind::Normalized => true,\n                        };\n                        if !matched {\n                            return;\n                        }\n                        // Next filter out all yanked packages. Some yanked packages may\n                        // leak through if they're in a whitelist (aka if they were\n                        // previously in `Cargo.lock`\n                        match s {\n                            s @ _ if kind == QueryKind::RejectedVersions => callback(s),\n                            s @ IndexSummary::Candidate(_) => callback(s),\n                            s @ IndexSummary::Yanked(_) => {\n                                if self.yanked_whitelist.contains(&s.package_id()) {\n                                    callback(s);\n                                } else if req.is_precise() {\n                                    precise_yanked_in_use = true;\n                                    callback(s);\n                                }\n                            }\n                            IndexSummary::Unsupported(summary, v) => {\n                                tracing::debug!(\n                                    \"unsupported schema version {} ({} {})\",\n                                    v,\n                                    summary.name(),\n                                    summary.version()\n                                );\n                            }\n                            IndexSummary::Invalid(summary) => {\n                                tracing::debug!(\n                                    \"invalid ({} {})\",\n                                    summary.name(),\n                                    summary.version()\n                                );\n                            }\n                            IndexSummary::Offline(summary) => {\n                                tracing::debug!(\n                                    \"offline ({} {})\",\n                                    summary.name(),\n                                    summary.version()\n                                );\n                            }\n                        }\n                    })\n            )?;\n            if precise_yanked_in_use {\n                let name = dep.package_name();\n                let version = req\n                    .precise_version()\n                    .expect(\"--precise <yanked-version> in use\");\n                if self.selected_precise_yanked.insert((name, version.clone())) {\n                    let mut shell = self.gctx.shell();\n                    shell.print_report(\n                        &[Level::WARNING\n                            .secondary_title(format!(\n                                \"selected package `{name}@{version}` was yanked by the author\"\n                            ))\n                            .element(\n                                Level::HELP\n                                    .message(\"if possible, try a compatible non-yanked version\"),\n                            )],\n                        false,\n                    )?;\n                }\n            }\n            if called {\n                return Poll::Ready(Ok(()));\n            }\n            let mut any_pending = false;\n            if kind == QueryKind::AlternativeNames || kind == QueryKind::Normalized {\n                // Attempt to handle misspellings by searching for a chain of related\n                // names to the original name. The resolver will later\n                // reject any candidates that have the wrong name, and with this it'll\n                // have enough information to offer \"a similar crate exists\" suggestions.\n                // For now we only try canonicalizing `-` to `_` and vice versa.\n                // More advanced fuzzy searching become in the future.\n                for name_permutation in [\n                    dep.package_name().replace('-', \"_\"),\n                    dep.package_name().replace('_', \"-\"),\n                ] {\n                    let name_permutation = name_permutation.into();\n                    if name_permutation == dep.package_name() {\n                        continue;\n                    }\n                    any_pending |= self\n                        .index\n                        .query_inner(name_permutation, &req, &mut *self.ops, &mut |s| {\n                            if !s.is_yanked() {\n                                f(s);\n                            } else if kind == QueryKind::AlternativeNames {\n                                f(s);\n                            }\n                        })?\n                        .is_pending();\n                }\n            }\n            if any_pending {\n                Poll::Pending\n            } else {\n                Poll::Ready(Ok(()))\n            }\n        }\n    }\n\n    fn supports_checksums(&self) -> bool {\n        true\n    }\n\n    fn requires_precise(&self) -> bool {\n        false\n    }\n\n    fn source_id(&self) -> SourceId {\n        self.source_id\n    }\n\n    fn invalidate_cache(&mut self) {\n        self.index.clear_summaries_cache();\n        self.ops.invalidate_cache();\n    }\n\n    fn set_quiet(&mut self, quiet: bool) {\n        self.ops.set_quiet(quiet);\n    }\n\n    fn download(&mut self, package: PackageId) -> CargoResult<MaybePackage> {\n        let hash = loop {\n            match self.index.hash(package, &mut *self.ops)? {\n                Poll::Pending => self.block_until_ready()?,\n                Poll::Ready(hash) => break hash,\n            }\n        };\n        match self.ops.download(package, hash)? {\n            MaybeLock::Ready(file) => self.get_pkg(package, &file).map(MaybePackage::Ready),\n            MaybeLock::Download {\n                url,\n                descriptor,\n                authorization,\n            } => Ok(MaybePackage::Download {\n                url,\n                descriptor,\n                authorization,\n            }),\n        }\n    }\n\n    fn finish_download(&mut self, package: PackageId, data: Vec<u8>) -> CargoResult<Package> {\n        let hash = loop {\n            match self.index.hash(package, &mut *self.ops)? {\n                Poll::Pending => self.block_until_ready()?,\n                Poll::Ready(hash) => break hash,\n            }\n        };\n        let file = self.ops.finish_download(package, hash, &data)?;\n        self.get_pkg(package, &file)\n    }\n\n    fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {\n        Ok(pkg.package_id().version().to_string())\n    }\n\n    fn describe(&self) -> String {\n        self.source_id.display_index()\n    }\n\n    fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]) {\n        self.yanked_whitelist.extend(pkgs);\n    }\n\n    fn is_yanked(&mut self, pkg: PackageId) -> Poll<CargoResult<bool>> {\n        self.index.is_yanked(pkg, &mut *self.ops)\n    }\n\n    fn block_until_ready(&mut self) -> CargoResult<()> {\n        // Before starting to work on the registry, make sure that\n        // `<cargo_home>/registry` is marked as excluded from indexing and\n        // backups. Older versions of Cargo didn't do this, so we do it here\n        // regardless of whether `<cargo_home>` exists.\n        //\n        // This does not use `create_dir_all_excluded_from_backups_atomic` for\n        // the same reason: we want to exclude it even if the directory already\n        // exists.\n        //\n        // IO errors in creating and marking it are ignored, e.g. in case we're on a\n        // read-only filesystem.\n        let registry_base = self.gctx.registry_base_path();\n        let _ = registry_base.create_dir();\n        exclude_from_backups_and_indexing(&registry_base.into_path_unlocked());\n\n        self.ops.block_until_ready()\n    }\n}\n\nimpl RegistryConfig {\n    /// File name of [`RegistryConfig`].\n    const NAME: &'static str = \"config.json\";\n}\n\n/// Get the maximum unpack size that Cargo permits\n/// based on a given `size` of your compressed file.\n///\n/// Returns the larger one between `size * max compression ratio`\n/// and a fixed max unpacked size.\n///\n/// In reality, the compression ratio usually falls in the range of 2:1 to 10:1.\n/// We choose 20:1 to cover almost all possible cases hopefully.\n/// Any ratio higher than this is considered as a zip bomb.\n///\n/// In the future we might want to introduce a configurable size.\n///\n/// Some of the real world data from common compression algorithms:\n///\n/// * <https://www.zlib.net/zlib_tech.html>\n/// * <https://cran.r-project.org/web/packages/brotli/vignettes/brotli-2015-09-22.pdf>\n/// * <https://blog.cloudflare.com/results-experimenting-brotli/>\n/// * <https://tukaani.org/lzma/benchmarks.html>\nfn max_unpack_size(gctx: &GlobalContext, size: u64) -> u64 {\n    const SIZE_VAR: &str = \"__CARGO_TEST_MAX_UNPACK_SIZE\";\n    const RATIO_VAR: &str = \"__CARGO_TEST_MAX_UNPACK_RATIO\";\n    const MAX_UNPACK_SIZE: u64 = 512 * 1024 * 1024; // 512 MiB\n    const MAX_COMPRESSION_RATIO: usize = 20; // 20:1\n\n    let max_unpack_size = if cfg!(debug_assertions) && gctx.get_env(SIZE_VAR).is_ok() {\n        // For integration test only.\n        gctx.get_env(SIZE_VAR)\n            .unwrap()\n            .parse()\n            .expect(\"a max unpack size in bytes\")\n    } else {\n        MAX_UNPACK_SIZE\n    };\n    let max_compression_ratio = if cfg!(debug_assertions) && gctx.get_env(RATIO_VAR).is_ok() {\n        // For integration test only.\n        gctx.get_env(RATIO_VAR)\n            .unwrap()\n            .parse()\n            .expect(\"a max compression ratio in bytes\")\n    } else {\n        MAX_COMPRESSION_RATIO\n    };\n\n    u64::max(max_unpack_size, size * max_compression_ratio as u64)\n}\n\n/// Set the current [`umask`] value for the given tarball. No-op on non-Unix\n/// platforms.\n///\n/// On Windows, tar only looks at user permissions and tries to set the \"read\n/// only\" attribute, so no-op as well.\n///\n/// [`umask`]: https://man7.org/linux/man-pages/man2/umask.2.html\n#[allow(unused_variables)]\nfn set_mask<R: Read>(tar: &mut Archive<R>) {\n    #[cfg(unix)]\n    tar.set_mask(crate::util::get_umask());\n}\n\n/// Unpack a tarball with zip bomb and overwrite protections.\nfn unpack(\n    gctx: &GlobalContext,\n    tarball: &File,\n    unpack_dir: &Path,\n    include: &dyn Fn(&Path) -> bool,\n) -> CargoResult<u64> {\n    let mut tar = {\n        let size_limit = max_unpack_size(gctx, tarball.metadata()?.len());\n        let gz = GzDecoder::new(tarball);\n        let gz = LimitErrorReader::new(gz, size_limit);\n        let mut tar = Archive::new(gz);\n        set_mask(&mut tar);\n        tar\n    };\n    let mut bytes_written = 0;\n    let prefix = unpack_dir.file_name().unwrap();\n    let parent = unpack_dir.parent().unwrap();\n    for entry in tar.entries()? {\n        let mut entry = entry.context(\"failed to iterate over archive\")?;\n        let entry_path = entry\n            .path()\n            .context(\"failed to read entry path\")?\n            .into_owned();\n\n        if let Ok(path) = entry_path.strip_prefix(prefix) {\n            if !include(path) {\n                continue;\n            }\n        } else {\n            // We're going to unpack this tarball into the global source\n            // directory, but we want to make sure that it doesn't accidentally\n            // (or maliciously) overwrite source code from other crates. Cargo\n            // itself should never generate a tarball that hits this error, and\n            // crates.io should also block uploads with these sorts of tarballs,\n            // but be extra sure by adding a check here as well.\n            anyhow::bail!(\n                \"invalid tarball downloaded, contains \\\n                     a file at {entry_path:?} which isn't under {prefix:?}\",\n            )\n        }\n\n        // Prevent unpacking the lockfile from the crate itself.\n        if entry_path\n            .file_name()\n            .map_or(false, |p| p == PACKAGE_SOURCE_LOCK)\n        {\n            continue;\n        }\n        // Unpacking failed\n        bytes_written += entry.size();\n        let mut result = entry.unpack_in(parent).map_err(anyhow::Error::from);\n        if cfg!(windows) && restricted_names::is_windows_reserved_path(&entry_path) {\n            result = result.with_context(|| {\n                format!(\n                    \"`{}` appears to contain a reserved Windows path, \\\n                        it cannot be extracted on Windows\",\n                    entry_path.display()\n                )\n            });\n        }\n        result.with_context(|| format!(\"failed to unpack entry at `{}`\", entry_path.display()))?;\n    }\n\n    Ok(bytes_written)\n}\n\n/// Workaround for rust-lang/cargo#16237\n///\n/// Generated files should have the same deterministic mtime as other files.\n/// However, since we forgot to set mtime for those files when uploading, they\n/// always have older mtime (1973-11-29) that prevents zip from packing (requiring >1980)\n///\n/// This workaround updates mtime after we unpack the tarball at the destination.\nfn update_mtime_for_generated_files(pkg_root: &Path) {\n    const GENERATED_FILES: &[&str] = &[\"Cargo.lock\", \"Cargo.toml\", \".cargo_vcs_info.json\"];\n    // Hardcoded value be removed once alexcrichton/tar-rs#420 is merged and released.\n    // See also rust-lang/cargo#16237\n    const DETERMINISTIC_TIMESTAMP: i64 = 1153704088;\n\n    for file in GENERATED_FILES {\n        let path = pkg_root.join(file);\n        let mtime = filetime::FileTime::from_unix_time(DETERMINISTIC_TIMESTAMP, 0);\n        if let Err(e) = filetime::set_file_mtime(&path, mtime) {\n            tracing::trace!(\"failed to set deterministic mtime for {path:?}: {e}\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/sources/registry/remote.rs",
    "content": "//! Access to a Git index based registry. See [`RemoteRegistry`] for details.\n\nuse crate::core::global_cache_tracker;\nuse crate::core::{GitReference, PackageId, SourceId};\nuse crate::sources::git;\nuse crate::sources::git::fetch::RemoteKind;\nuse crate::sources::git::resolve_ref;\nuse crate::sources::registry::MaybeLock;\nuse crate::sources::registry::download;\nuse crate::sources::registry::{LoadResponse, RegistryConfig, RegistryData};\nuse crate::util::cache_lock::CacheLockMode;\nuse crate::util::errors::CargoResult;\nuse crate::util::interning::InternedString;\nuse crate::util::{Filesystem, GlobalContext, OnceExt};\nuse anyhow::Context as _;\nuse cargo_util::paths;\nuse std::cell::OnceCell;\nuse std::cell::{Cell, Ref, RefCell};\nuse std::fs::File;\nuse std::mem;\nuse std::path::Path;\nuse std::str;\nuse std::task::{Poll, ready};\nuse tracing::{debug, trace};\n\n/// A remote registry is a registry that lives at a remote URL (such as\n/// crates.io). The git index is cloned locally, and `.crate` files are\n/// downloaded as needed and cached locally.\n///\n/// This type is primarily accessed through the [`RegistryData`] trait.\n///\n/// See the [module-level documentation](super) for the index format and layout.\n///\n/// ## History of Git-based index registry\n///\n/// Using Git to host this index used to be quite efficient. The full index can\n/// be stored efficiently locally on disk, and once it is downloaded, all\n/// queries of a registry can happen locally and needn't touch the network.\n/// Git-based index was a reasonable design choice at the time when HTTP/2\n/// was just introduced.\n///\n/// However, the full index keeps growing as crates.io grows. It becomes\n/// relatively big and slows down the first use of Cargo. Git (specifically\n/// libgit2) is not efficient at handling huge amounts of small files either.\n/// On the other hand, newer protocols like HTTP/2 are prevalent and capable to\n/// serve a bunch of tiny files. Today, it is encouraged to use [`HttpRegistry`],\n/// which is the default from 1.70.0. That being said, Cargo will continue\n/// supporting Git-based index for a pretty long while.\n///\n/// [`HttpRegistry`]: super::http_remote::HttpRegistry\npub struct RemoteRegistry<'gctx> {\n    /// The name of this source, a unique string (across all sources) used as\n    /// the directory name where its cached content is stored.\n    name: InternedString,\n    /// Path to the registry index (`$CARGO_HOME/registry/index/$REG-HASH`).\n    index_path: Filesystem,\n    /// Path to the cache of `.crate` files (`$CARGO_HOME/registry/cache/$REG-HASH`).\n    cache_path: Filesystem,\n    /// The unique identifier of this registry source.\n    source_id: SourceId,\n    /// This reference is stored so that when a registry needs update, it knows\n    /// where to fetch from.\n    index_git_ref: GitReference,\n    gctx: &'gctx GlobalContext,\n    /// A Git [tree object] to help this registry find crate metadata from the\n    /// underlying Git repository.\n    ///\n    /// This is stored here to prevent Git from repeatedly creating a tree object\n    /// during each call into `load()`.\n    ///\n    /// [tree object]: https://git-scm.com/book/en/v2/Git-Internals-Git-Objects#_tree_objects\n    tree: RefCell<Option<git2::Tree<'static>>>,\n    /// A Git repository that contains the actual index we want.\n    repo: OnceCell<git2::Repository>,\n    /// The current HEAD commit of the underlying Git repository.\n    head: Cell<Option<git2::Oid>>,\n    /// This stores sha value of the current HEAD commit for convenience.\n    current_sha: Cell<Option<InternedString>>,\n    /// Whether this registry needs to update package information.\n    ///\n    /// See [`RemoteRegistry::mark_updated`] on how to make sure a registry\n    /// index is updated only once per session.\n    needs_update: bool,\n    /// Disables status messages.\n    quiet: bool,\n}\n\nimpl<'gctx> RemoteRegistry<'gctx> {\n    /// Creates a Git-rebased remote registry for `source_id`.\n    ///\n    /// * `name` --- Name of a path segment where `.crate` tarballs and the\n    ///   registry index are stored. Expect to be unique.\n    pub fn new(\n        source_id: SourceId,\n        gctx: &'gctx GlobalContext,\n        name: &str,\n    ) -> RemoteRegistry<'gctx> {\n        RemoteRegistry {\n            name: name.into(),\n            index_path: gctx.registry_index_path().join(name),\n            cache_path: gctx.registry_cache_path().join(name),\n            source_id,\n            gctx,\n            index_git_ref: GitReference::DefaultBranch,\n            tree: RefCell::new(None),\n            repo: OnceCell::new(),\n            head: Cell::new(None),\n            current_sha: Cell::new(None),\n            needs_update: false,\n            quiet: false,\n        }\n    }\n\n    /// Creates intermediate dirs and initialize the repository.\n    fn repo(&self) -> CargoResult<&git2::Repository> {\n        self.repo.try_borrow_with(|| {\n            trace!(\"acquiring registry index lock\");\n            let path = self\n                .gctx\n                .assert_package_cache_locked(CacheLockMode::DownloadExclusive, &self.index_path);\n\n            match git2::Repository::open(&path) {\n                Ok(repo) => Ok(repo),\n                Err(_) => {\n                    drop(paths::remove_dir_all(&path));\n                    paths::create_dir_all(&path)?;\n\n                    // Note that we'd actually prefer to use a bare repository\n                    // here as we're not actually going to check anything out.\n                    // All versions of Cargo, though, share the same CARGO_HOME,\n                    // so for compatibility with older Cargo which *does* do\n                    // checkouts we make sure to initialize a new full\n                    // repository (not a bare one).\n                    //\n                    // We should change this to `init_bare` whenever we feel\n                    // like enough time has passed or if we change the directory\n                    // that the folder is located in, such as by changing the\n                    // hash at the end of the directory.\n                    //\n                    // Note that in the meantime we also skip `init.templatedir`\n                    // as it can be misconfigured sometimes or otherwise add\n                    // things that we don't want.\n                    let mut opts = git2::RepositoryInitOptions::new();\n                    opts.external_template(false);\n                    Ok(git2::Repository::init_opts(&path, &opts).with_context(|| {\n                        format!(\"failed to initialize index git repository (in {:?})\", path)\n                    })?)\n                }\n            }\n        })\n    }\n\n    /// Get the object ID of the HEAD commit from the underlying Git repository.\n    fn head(&self) -> CargoResult<git2::Oid> {\n        if self.head.get().is_none() {\n            let repo = self.repo()?;\n            let oid = resolve_ref(&self.index_git_ref, repo)?;\n            self.head.set(Some(oid));\n        }\n        Ok(self.head.get().unwrap())\n    }\n\n    /// Returns a [`git2::Tree`] object of the current HEAD commit of the\n    /// underlying Git repository.\n    fn tree(&self) -> CargoResult<Ref<'_, git2::Tree<'_>>> {\n        {\n            let tree = self.tree.borrow();\n            if tree.is_some() {\n                return Ok(Ref::map(tree, |s| s.as_ref().unwrap()));\n            }\n        }\n        let repo = self.repo()?;\n        let commit = repo.find_commit(self.head()?)?;\n        let tree = commit.tree()?;\n\n        // SAFETY:\n        // Unfortunately in libgit2 the tree objects look like they've got a\n        // reference to the repository object which means that a tree cannot\n        // outlive the repository that it came from. Here we want to cache this\n        // tree, though, so to accomplish this we transmute it to a static\n        // lifetime.\n        //\n        // Note that we don't actually hand out the static lifetime, instead we\n        // only return a scoped one from this function. Additionally the repo\n        // we loaded from (above) lives as long as this object\n        // (`RemoteRegistry`) so we then just need to ensure that the tree is\n        // destroyed first in the destructor, hence the destructor on\n        // `RemoteRegistry` below.\n        let tree = unsafe { mem::transmute::<git2::Tree<'_>, git2::Tree<'static>>(tree) };\n        *self.tree.borrow_mut() = Some(tree);\n        Ok(Ref::map(self.tree.borrow(), |s| s.as_ref().unwrap()))\n    }\n\n    /// Gets the current version of the registry index.\n    ///\n    /// It is usually sha of the HEAD commit from the underlying Git repository.\n    fn current_version(&self) -> Option<InternedString> {\n        if let Some(sha) = self.current_sha.get() {\n            return Some(sha);\n        }\n        let sha = self.head().ok()?.to_string().into();\n        self.current_sha.set(Some(sha));\n        Some(sha)\n    }\n\n    /// Whether the registry is up-to-date. See [`Self::mark_updated`] for more.\n    fn is_updated(&self) -> bool {\n        self.gctx.updated_sources().contains(&self.source_id)\n    }\n\n    /// Marks this registry as up-to-date.\n    ///\n    /// This makes sure the index is only updated once per session since it is\n    /// an expensive operation. This generally only happens when the resolver\n    /// is run multiple times, such as during `cargo publish`.\n    fn mark_updated(&self) {\n        self.gctx.updated_sources().insert(self.source_id);\n    }\n}\n\nimpl<'gctx> RegistryData for RemoteRegistry<'gctx> {\n    fn prepare(&self) -> CargoResult<()> {\n        self.repo()?;\n        self.gctx\n            .deferred_global_last_use()?\n            .mark_registry_index_used(global_cache_tracker::RegistryIndex {\n                encoded_registry_name: self.name,\n            });\n        Ok(())\n    }\n\n    fn index_path(&self) -> &Filesystem {\n        &self.index_path\n    }\n\n    fn cache_path(&self) -> &Filesystem {\n        &self.cache_path\n    }\n\n    fn assert_index_locked<'a>(&self, path: &'a Filesystem) -> &'a Path {\n        self.gctx\n            .assert_package_cache_locked(CacheLockMode::DownloadExclusive, path)\n    }\n\n    /// Read the general concept for `load()` on [`RegistryData::load`].\n    ///\n    /// `index_version` is a string representing the version of the file used\n    /// to construct the cached copy.\n    ///\n    /// Older versions of Cargo used the single value of the hash of the HEAD\n    /// commit as a `index_version`. This is technically correct but a little\n    /// too conservative. If a new commit is fetched all cached files need to\n    /// be regenerated even if a particular file was not changed.\n    ///\n    /// However if an old cargo has written such a file we still know how to\n    /// read it, as long as we check for that hash value.\n    ///\n    /// Cargo now uses a hash of the file's contents as provided by git.\n    fn load(\n        &mut self,\n        _root: &Path,\n        path: &Path,\n        index_version: Option<&str>,\n    ) -> Poll<CargoResult<LoadResponse>> {\n        if self.needs_update {\n            return Poll::Pending;\n        }\n        // Check if the cache is valid.\n        let git_commit_hash = self.current_version();\n        if index_version.is_some() && index_version == git_commit_hash.as_deref() {\n            // This file was written by an old version of cargo, but it is\n            // still up-to-date.\n            return Poll::Ready(Ok(LoadResponse::CacheValid));\n        }\n        // Note that the index calls this method and the filesystem is locked\n        // in the index, so we don't need to worry about an `update_index`\n        // happening in a different process.\n        fn load_helper(\n            registry: &RemoteRegistry<'_>,\n            path: &Path,\n            index_version: Option<&str>,\n        ) -> CargoResult<LoadResponse> {\n            let repo = registry.repo()?;\n            let tree = registry.tree()?;\n            let entry = tree.get_path(path);\n            let entry = entry?;\n            let git_file_hash = Some(entry.id().to_string());\n\n            // Check if the cache is valid.\n            if index_version.is_some() && index_version == git_file_hash.as_deref() {\n                return Ok(LoadResponse::CacheValid);\n            }\n\n            let object = entry.to_object(repo)?;\n            let Some(blob) = object.as_blob() else {\n                anyhow::bail!(\"path `{}` is not a blob in the git repo\", path.display())\n            };\n\n            Ok(LoadResponse::Data {\n                raw_data: blob.content().to_vec(),\n                index_version: git_file_hash,\n            })\n        }\n\n        match load_helper(&self, path, index_version) {\n            Ok(result) => Poll::Ready(Ok(result)),\n            Err(_) if !self.is_updated() => {\n                // If git returns an error and we haven't updated the repo,\n                // return pending to allow an update to try again.\n                self.needs_update = true;\n                Poll::Pending\n            }\n            Err(e)\n                if e.downcast_ref::<git2::Error>()\n                    .map(|e| e.code() == git2::ErrorCode::NotFound)\n                    .unwrap_or_default() =>\n            {\n                // The repo has been updated and the file does not exist.\n                Poll::Ready(Ok(LoadResponse::NotFound))\n            }\n            Err(e) => Poll::Ready(Err(e)),\n        }\n    }\n\n    fn config(&mut self) -> Poll<CargoResult<Option<RegistryConfig>>> {\n        debug!(\"loading config\");\n        self.prepare()?;\n        self.gctx\n            .assert_package_cache_locked(CacheLockMode::DownloadExclusive, &self.index_path);\n        match ready!(self.load(Path::new(\"\"), Path::new(RegistryConfig::NAME), None)?) {\n            LoadResponse::Data { raw_data, .. } => {\n                trace!(\"config loaded\");\n                let cfg: RegistryConfig = serde_json::from_slice(&raw_data)?;\n                Poll::Ready(Ok(Some(cfg)))\n            }\n            _ => Poll::Ready(Ok(None)),\n        }\n    }\n\n    fn block_until_ready(&mut self) -> CargoResult<()> {\n        if !self.needs_update {\n            return Ok(());\n        }\n\n        self.needs_update = false;\n\n        if self.is_updated() {\n            return Ok(());\n        }\n        self.mark_updated();\n\n        if !self.gctx.network_allowed() {\n            return Ok(());\n        }\n        if self.gctx.cli_unstable().no_index_update {\n            return Ok(());\n        }\n\n        debug!(\"updating the index\");\n\n        // Ensure that we'll actually be able to acquire an HTTP handle later on\n        // once we start trying to download crates. This will weed out any\n        // problems with `.cargo/config` configuration related to HTTP.\n        //\n        // This way if there's a problem the error gets printed before we even\n        // hit the index, which may not actually read this configuration.\n        self.gctx.http()?;\n\n        self.prepare()?;\n        self.head.set(None);\n        *self.tree.borrow_mut() = None;\n        self.current_sha.set(None);\n        let _path = self\n            .gctx\n            .assert_package_cache_locked(CacheLockMode::DownloadExclusive, &self.index_path);\n        if !self.quiet {\n            self.gctx\n                .shell()\n                .status(\"Updating\", self.source_id.display_index())?;\n        }\n\n        // Fetch the latest version of our `index_git_ref` into the index\n        // checkout.\n        let url = self.source_id.url();\n        let repo = self.repo.get_mut().unwrap();\n        git::fetch(\n            repo,\n            url.as_str(),\n            &self.index_git_ref,\n            &self.index_git_ref,\n            self.gctx,\n            RemoteKind::Registry,\n        )\n        .with_context(|| format!(\"failed to fetch `{}`\", url))?;\n\n        Ok(())\n    }\n\n    /// Read the general concept for `invalidate_cache()` on\n    /// [`RegistryData::invalidate_cache`].\n    ///\n    /// To fully invalidate, undo [`RemoteRegistry::mark_updated`]'s work.\n    fn invalidate_cache(&mut self) {\n        self.needs_update = true;\n    }\n\n    fn set_quiet(&mut self, quiet: bool) {\n        self.quiet = quiet;\n    }\n\n    fn is_updated(&self) -> bool {\n        self.is_updated()\n    }\n\n    fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult<MaybeLock> {\n        let registry_config = loop {\n            match self.config()? {\n                Poll::Pending => self.block_until_ready()?,\n                Poll::Ready(cfg) => break cfg.unwrap(),\n            }\n        };\n\n        download::download(\n            &self.cache_path,\n            &self.gctx,\n            self.name,\n            pkg,\n            checksum,\n            registry_config,\n        )\n    }\n\n    fn finish_download(\n        &mut self,\n        pkg: PackageId,\n        checksum: &str,\n        data: &[u8],\n    ) -> CargoResult<File> {\n        download::finish_download(\n            &self.cache_path,\n            &self.gctx,\n            self.name.clone(),\n            pkg,\n            checksum,\n            data,\n        )\n    }\n\n    fn is_crate_downloaded(&self, pkg: PackageId) -> bool {\n        download::is_crate_downloaded(&self.cache_path, &self.gctx, pkg)\n    }\n}\n\n/// Implemented to just be sure to drop `tree` field before our other fields.\n/// See SAFETY inside [`RemoteRegistry::tree()`] for more.\nimpl<'gctx> Drop for RemoteRegistry<'gctx> {\n    fn drop(&mut self) {\n        self.tree.borrow_mut().take();\n    }\n}\n"
  },
  {
    "path": "src/cargo/sources/replaced.rs",
    "content": "use crate::core::{Dependency, Package, PackageId, SourceId};\nuse crate::sources::IndexSummary;\nuse crate::sources::source::MaybePackage;\nuse crate::sources::source::QueryKind;\nuse crate::sources::source::Source;\nuse crate::util::errors::CargoResult;\nuse std::task::Poll;\n\n/// A source that replaces one source with the other. This manages the [source\n/// replacement] feature.\n///\n/// The implementation is merely redirecting from the original to the replacement.\n///\n/// [source replacement]: https://doc.rust-lang.org/nightly/cargo/reference/source-replacement.html\npub struct ReplacedSource<'gctx> {\n    /// The identifier of the original source.\n    to_replace: SourceId,\n    /// The identifier of the new replacement source.\n    replace_with: SourceId,\n    inner: Box<dyn Source + 'gctx>,\n}\n\nimpl<'gctx> ReplacedSource<'gctx> {\n    /// Creates a replaced source.\n    ///\n    /// The `src` argument is the new replacement source.\n    pub fn new(\n        to_replace: SourceId,\n        replace_with: SourceId,\n        src: Box<dyn Source + 'gctx>,\n    ) -> ReplacedSource<'gctx> {\n        ReplacedSource {\n            to_replace,\n            replace_with,\n            inner: src,\n        }\n    }\n\n    /// Is this source a built-in replacement of crates.io?\n    ///\n    /// Built-in source replacement of crates.io for sparse registry or tests\n    /// should not show messages indicating source replacement.\n    fn is_builtin_replacement(&self) -> bool {\n        self.replace_with.is_crates_io() && self.to_replace.is_crates_io()\n    }\n}\n\nimpl<'gctx> Source for ReplacedSource<'gctx> {\n    fn source_id(&self) -> SourceId {\n        self.to_replace\n    }\n\n    fn replaced_source_id(&self) -> SourceId {\n        self.replace_with\n    }\n\n    fn supports_checksums(&self) -> bool {\n        self.inner.supports_checksums()\n    }\n\n    fn requires_precise(&self) -> bool {\n        self.inner.requires_precise()\n    }\n\n    fn query(\n        &mut self,\n        dep: &Dependency,\n        kind: QueryKind,\n        f: &mut dyn FnMut(IndexSummary),\n    ) -> Poll<CargoResult<()>> {\n        let (replace_with, to_replace) = (self.replace_with, self.to_replace);\n        let dep = dep.clone().map_source(to_replace, replace_with);\n\n        self.inner\n            .query(&dep, kind, &mut |summary| {\n                f(summary.map_summary(|s| s.map_source(replace_with, to_replace)))\n            })\n            .map_err(|e| {\n                if self.is_builtin_replacement() {\n                    e\n                } else {\n                    e.context(format!(\n                        \"failed to query replaced source {}\",\n                        self.to_replace\n                    ))\n                }\n            })\n    }\n\n    fn invalidate_cache(&mut self) {\n        self.inner.invalidate_cache()\n    }\n\n    fn set_quiet(&mut self, quiet: bool) {\n        self.inner.set_quiet(quiet);\n    }\n\n    fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {\n        let id = id.with_source_id(self.replace_with);\n        let pkg = self.inner.download(id).map_err(|e| {\n            if self.is_builtin_replacement() {\n                e\n            } else {\n                e.context(format!(\n                    \"failed to download replaced source {}\",\n                    self.to_replace\n                ))\n            }\n        })?;\n        Ok(match pkg {\n            MaybePackage::Ready(pkg) => {\n                MaybePackage::Ready(pkg.map_source(self.replace_with, self.to_replace))\n            }\n            other @ MaybePackage::Download { .. } => other,\n        })\n    }\n\n    fn finish_download(&mut self, id: PackageId, data: Vec<u8>) -> CargoResult<Package> {\n        let id = id.with_source_id(self.replace_with);\n        let pkg = self.inner.finish_download(id, data).map_err(|e| {\n            if self.is_builtin_replacement() {\n                e\n            } else {\n                e.context(format!(\n                    \"failed to download replaced source {}\",\n                    self.to_replace\n                ))\n            }\n        })?;\n        Ok(pkg.map_source(self.replace_with, self.to_replace))\n    }\n\n    fn fingerprint(&self, id: &Package) -> CargoResult<String> {\n        self.inner.fingerprint(id)\n    }\n\n    fn verify(&self, id: PackageId) -> CargoResult<()> {\n        let id = id.with_source_id(self.replace_with);\n        self.inner.verify(id)\n    }\n\n    fn describe(&self) -> String {\n        if self.is_builtin_replacement() {\n            self.inner.describe()\n        } else {\n            format!(\n                \"{} (which is replacing {})\",\n                self.inner.describe(),\n                self.to_replace\n            )\n        }\n    }\n\n    fn is_replaced(&self) -> bool {\n        !self.is_builtin_replacement()\n    }\n\n    fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]) {\n        let pkgs = pkgs\n            .iter()\n            .map(|id| id.with_source_id(self.replace_with))\n            .collect::<Vec<_>>();\n        self.inner.add_to_yanked_whitelist(&pkgs);\n    }\n\n    fn is_yanked(&mut self, pkg: PackageId) -> Poll<CargoResult<bool>> {\n        self.inner.is_yanked(pkg)\n    }\n\n    fn block_until_ready(&mut self) -> CargoResult<()> {\n        self.inner.block_until_ready().map_err(|e| {\n            if self.is_builtin_replacement() {\n                e\n            } else {\n                e.context(format!(\n                    \"failed to update replaced source {}\",\n                    self.to_replace\n                ))\n            }\n        })\n    }\n}\n"
  },
  {
    "path": "src/cargo/sources/source.rs",
    "content": "//! [`Source`] trait for sources of Cargo packages.\n\nuse std::collections::hash_map::HashMap;\nuse std::fmt;\nuse std::task::Poll;\n\nuse crate::core::SourceId;\nuse crate::core::{Dependency, Package, PackageId};\nuse crate::sources::IndexSummary;\nuse crate::util::CargoResult;\n\n/// An abstraction of different sources of Cargo packages.\n///\n/// The [`Source`] trait generalizes the API to interact with these providers.\n/// For example,\n///\n/// * [`Source::query`] is for querying package metadata on a given\n///   [`Dependency`] requested by a Cargo manifest.\n/// * [`Source::download`] is for fetching the full package information on\n///   given names and versions.\n/// * [`Source::source_id`] is for defining an unique identifier of a source to\n///   distinguish one source from another, keeping Cargo safe from [dependency\n///   confusion attack].\n///\n/// Normally, developers don't need to implement their own [`Source`]s. Cargo\n/// provides several kinds of sources implementations that should cover almost\n/// all use cases. See [`crate::sources`] for implementations provided by Cargo.\n///\n/// [dependency confusion attack]: https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610\npub trait Source {\n    /// Returns the [`SourceId`] corresponding to this source.\n    fn source_id(&self) -> SourceId;\n\n    /// Returns the replaced [`SourceId`] corresponding to this source.\n    fn replaced_source_id(&self) -> SourceId {\n        self.source_id()\n    }\n\n    /// Returns whether or not this source will return [`IndexSummary`] items with\n    /// checksums listed.\n    fn supports_checksums(&self) -> bool;\n\n    /// Returns whether or not this source will return [`IndexSummary`] items with\n    /// the `precise` field in the [`SourceId`] listed.\n    fn requires_precise(&self) -> bool;\n\n    /// Attempts to find the packages that match a dependency request.\n    ///\n    /// Usually you should call [`Source::block_until_ready`] somewhere and\n    /// wait until package information become available. Otherwise any query\n    /// may return a [`Poll::Pending`].\n    ///\n    /// The `f` argument is expected to get called when any [`IndexSummary`] becomes available.\n    fn query(\n        &mut self,\n        dep: &Dependency,\n        kind: QueryKind,\n        f: &mut dyn FnMut(IndexSummary),\n    ) -> Poll<CargoResult<()>>;\n\n    /// Gathers the result from [`Source::query`] as a list of [`IndexSummary`] items\n    /// when they become available.\n    fn query_vec(\n        &mut self,\n        dep: &Dependency,\n        kind: QueryKind,\n    ) -> Poll<CargoResult<Vec<IndexSummary>>> {\n        let mut ret = Vec::new();\n        self.query(dep, kind, &mut |s| ret.push(s)).map_ok(|_| ret)\n    }\n\n    /// Ensure that the source is fully up-to-date for the current session on the next query.\n    fn invalidate_cache(&mut self);\n\n    /// If quiet, the source should not display any progress or status messages.\n    fn set_quiet(&mut self, quiet: bool);\n\n    /// Starts the process to fetch a [`Package`] for the given [`PackageId`].\n    ///\n    /// If the source already has the package available on disk, then it\n    /// should return immediately with [`MaybePackage::Ready`] with the\n    /// [`Package`]. Otherwise it should return a [`MaybePackage::Download`]\n    /// to indicate the URL to download the package (this is for remote\n    /// registry sources only).\n    ///\n    /// In the case where [`MaybePackage::Download`] is returned, then the\n    /// package downloader will call [`Source::finish_download`] after the\n    /// download has finished.\n    fn download(&mut self, package: PackageId) -> CargoResult<MaybePackage>;\n\n    /// Gives the source the downloaded `.crate` file.\n    ///\n    /// When a source has returned [`MaybePackage::Download`] in the\n    /// [`Source::download`] method, then this function will be called with\n    /// the results of the download of the given URL. The source is\n    /// responsible for saving to disk, and returning the appropriate\n    /// [`Package`].\n    fn finish_download(&mut self, pkg_id: PackageId, contents: Vec<u8>) -> CargoResult<Package>;\n\n    /// Generates a unique string which represents the fingerprint of the\n    /// current state of the source.\n    ///\n    /// This fingerprint is used to determine the \"freshness\" of the source\n    /// later on. It must be guaranteed that the fingerprint of a source is\n    /// constant if and only if the output product will remain constant.\n    ///\n    /// The `pkg` argument is the package which this fingerprint should only be\n    /// interested in for when this source may contain multiple packages.\n    fn fingerprint(&self, pkg: &Package) -> CargoResult<String>;\n\n    /// If this source supports it, verifies the source of the package\n    /// specified.\n    ///\n    /// Note that the source may also have performed other checksum-based\n    /// verification during the `download` step, but this is intended to be run\n    /// just before a crate is compiled so it may perform more expensive checks\n    /// which may not be cacheable.\n    fn verify(&self, _pkg: PackageId) -> CargoResult<()> {\n        Ok(())\n    }\n\n    /// Describes this source in a human readable fashion, used for display in\n    /// resolver error messages currently.\n    fn describe(&self) -> String;\n\n    /// Returns whether a source is being replaced by another here.\n    ///\n    /// Builtin replacement of `crates.io` doesn't count as replacement here.\n    fn is_replaced(&self) -> bool {\n        false\n    }\n\n    /// Add a number of crates that should be whitelisted for showing up during\n    /// queries, even if they are yanked. Currently only applies to registry\n    /// sources.\n    fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]);\n\n    /// Query if a package is yanked. Only registry sources can mark packages\n    /// as yanked. This ignores the yanked whitelist.\n    fn is_yanked(&mut self, _pkg: PackageId) -> Poll<CargoResult<bool>>;\n\n    /// Block until all outstanding [`Poll::Pending`] requests are [`Poll::Ready`].\n    ///\n    /// After calling this function, the source should return `Poll::Ready` for\n    /// any queries that previously returned `Poll::Pending`.\n    ///\n    /// If no queries previously returned `Poll::Pending`, and [`Source::invalidate_cache`]\n    /// was not called, this function should be a no-op.\n    fn block_until_ready(&mut self) -> CargoResult<()>;\n}\n\n/// Defines how a dependency query will be performed for a [`Source`].\n#[derive(Copy, Clone, PartialEq, Eq)]\npub enum QueryKind {\n    /// A query for packages exactly matching the given dependency requirement.\n    ///\n    /// Each source gets to define what `exact` means for it.\n    Exact,\n    /// A query for packages close to the given dependency requirement.\n    ///\n    /// Each source gets to define what `close` means for it.\n    ///\n    /// Path/Git sources may return all dependencies that are at that URI,\n    /// whereas an `Registry` source may return dependencies that are yanked or invalid.\n    RejectedVersions,\n    /// A query for packages close to the given dependency requirement.\n    ///\n    /// Each source gets to define what `close` means for it.\n    ///\n    /// Path/Git sources may return all dependencies that are at that URI,\n    /// whereas an `Registry` source may return dependencies that have the same\n    /// canonicalization.\n    AlternativeNames,\n    /// Match a dependency in all ways and will normalize the package name.\n    /// Each source defines what normalizing means.\n    Normalized,\n}\n\n/// A download status that represents if a [`Package`] has already been\n/// downloaded, or if not then a location to download.\npub enum MaybePackage {\n    /// The [`Package`] is already downloaded.\n    Ready(Package),\n    /// Not yet downloaded. Here is the URL to download the [`Package`] from.\n    Download {\n        /// URL to download the content.\n        url: String,\n        /// Text to display to the user of what is being downloaded.\n        descriptor: String,\n        /// Authorization data that may be required to attach when downloading.\n        authorization: Option<String>,\n    },\n}\n\n/// A blanket implementation forwards all methods to [`Source`].\nimpl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {\n    fn source_id(&self) -> SourceId {\n        (**self).source_id()\n    }\n\n    fn replaced_source_id(&self) -> SourceId {\n        (**self).replaced_source_id()\n    }\n\n    fn supports_checksums(&self) -> bool {\n        (**self).supports_checksums()\n    }\n\n    fn requires_precise(&self) -> bool {\n        (**self).requires_precise()\n    }\n\n    fn query(\n        &mut self,\n        dep: &Dependency,\n        kind: QueryKind,\n        f: &mut dyn FnMut(IndexSummary),\n    ) -> Poll<CargoResult<()>> {\n        (**self).query(dep, kind, f)\n    }\n\n    fn invalidate_cache(&mut self) {\n        (**self).invalidate_cache()\n    }\n\n    fn set_quiet(&mut self, quiet: bool) {\n        (**self).set_quiet(quiet)\n    }\n\n    fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {\n        (**self).download(id)\n    }\n\n    fn finish_download(&mut self, id: PackageId, data: Vec<u8>) -> CargoResult<Package> {\n        (**self).finish_download(id, data)\n    }\n\n    fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {\n        (**self).fingerprint(pkg)\n    }\n\n    fn verify(&self, pkg: PackageId) -> CargoResult<()> {\n        (**self).verify(pkg)\n    }\n\n    fn describe(&self) -> String {\n        (**self).describe()\n    }\n\n    fn is_replaced(&self) -> bool {\n        (**self).is_replaced()\n    }\n\n    fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]) {\n        (**self).add_to_yanked_whitelist(pkgs);\n    }\n\n    fn is_yanked(&mut self, pkg: PackageId) -> Poll<CargoResult<bool>> {\n        (**self).is_yanked(pkg)\n    }\n\n    fn block_until_ready(&mut self) -> CargoResult<()> {\n        (**self).block_until_ready()\n    }\n}\n\n/// A [`HashMap`] of [`SourceId`] to `Box<Source>`.\n#[derive(Default)]\npub struct SourceMap<'src> {\n    map: HashMap<SourceId, Box<dyn Source + 'src>>,\n}\n\n// `impl Debug` on source requires specialization, if even desirable at all.\nimpl<'src> fmt::Debug for SourceMap<'src> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"SourceMap \")?;\n        f.debug_set().entries(self.map.keys()).finish()\n    }\n}\n\nimpl<'src> SourceMap<'src> {\n    /// Creates an empty map.\n    pub fn new() -> SourceMap<'src> {\n        SourceMap {\n            map: HashMap::new(),\n        }\n    }\n\n    /// Like `HashMap::get`.\n    pub fn get(&self, id: SourceId) -> Option<&(dyn Source + 'src)> {\n        self.map.get(&id).map(|s| s.as_ref())\n    }\n\n    /// Like `HashMap::get_mut`.\n    pub fn get_mut(&mut self, id: SourceId) -> Option<&mut (dyn Source + 'src)> {\n        self.map.get_mut(&id).map(|s| s.as_mut())\n    }\n\n    /// Like `HashMap::insert`, but derives the [`SourceId`] key from the [`Source`].\n    pub fn insert(&mut self, source: Box<dyn Source + 'src>) {\n        let id = source.source_id();\n        self.map.insert(id, source);\n    }\n\n    /// Like `HashMap::len`.\n    pub fn len(&self) -> usize {\n        self.map.len()\n    }\n\n    /// Like `HashMap::iter_mut`.\n    pub fn sources_mut<'a>(\n        &'a mut self,\n    ) -> impl Iterator<Item = (&'a SourceId, &'a mut (dyn Source + 'src))> {\n        self.map.iter_mut().map(|(a, b)| (a, &mut **b))\n    }\n\n    /// Merge the given map into self.\n    pub fn add_source_map(&mut self, other: SourceMap<'src>) {\n        for (key, value) in other.map {\n            self.map.entry(key).or_insert(value);\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/auth/mod.rs",
    "content": "//! Registry authentication support.\n\nuse crate::{\n    core::features::cargo_docs_link,\n    util::{CanonicalUrl, CargoResult, GlobalContext, IntoUrl, context::ConfigKey},\n};\nuse anyhow::{Context as _, bail};\nuse cargo_credential::{\n    Action, CacheControl, Credential, CredentialResponse, LoginOptions, Operation, RegistryInfo,\n    Secret,\n};\n\nuse core::fmt;\nuse serde::Deserialize;\nuse std::error::Error;\nuse time::{Duration, OffsetDateTime};\nuse url::Url;\n\nuse crate::core::SourceId;\nuse crate::util::context::Value;\nuse crate::util::credential::adaptor::BasicProcessCredential;\nuse crate::util::credential::paseto::PasetoCredential;\n\nuse super::{\n    context::{CredentialCacheValue, OptValue, PathAndArgs},\n    credential::process::CredentialProcessCredential,\n    credential::token::TokenCredential,\n};\n\n/// `[registries.NAME]` tables.\n///\n/// The values here should be kept in sync with `RegistryConfigExtended`\n#[derive(Deserialize, Clone, Debug)]\n#[serde(rename_all = \"kebab-case\")]\npub struct RegistryConfig {\n    pub index: Option<String>,\n    pub token: OptValue<Secret<String>>,\n    pub credential_provider: Option<PathAndArgs>,\n    pub secret_key: OptValue<Secret<String>>,\n    pub secret_key_subject: Option<String>,\n    #[serde(rename = \"protocol\")]\n    _protocol: Option<String>,\n}\n\n/// The `[registry]` table, which has more keys than the `[registries.NAME]` tables.\n///\n/// Note: nesting `RegistryConfig` inside this struct and using `serde(flatten)` *should* work\n/// but fails with \"invalid type: sequence, expected a value\" when attempting to deserialize.\n#[derive(Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\npub struct RegistryConfigExtended {\n    pub index: Option<String>,\n    pub token: OptValue<Secret<String>>,\n    pub credential_provider: Option<PathAndArgs>,\n    pub secret_key: OptValue<Secret<String>>,\n    pub secret_key_subject: Option<String>,\n    #[serde(rename = \"default\")]\n    _default: Option<String>,\n    #[serde(rename = \"global-credential-providers\")]\n    _global_credential_providers: Option<Vec<String>>,\n}\n\nimpl RegistryConfigExtended {\n    pub fn to_registry_config(self) -> RegistryConfig {\n        RegistryConfig {\n            index: self.index,\n            token: self.token,\n            credential_provider: self.credential_provider,\n            secret_key: self.secret_key,\n            secret_key_subject: self.secret_key_subject,\n            _protocol: None,\n        }\n    }\n}\n\n/// Get the list of credential providers for a registry source.\nfn credential_provider(\n    gctx: &GlobalContext,\n    sid: &SourceId,\n    require_cred_provider_config: bool,\n    show_warnings: bool,\n) -> CargoResult<Vec<Vec<String>>> {\n    let warn = |message: String| {\n        if show_warnings {\n            gctx.shell().warn(message)\n        } else {\n            Ok(())\n        }\n    };\n\n    let cfg = registry_credential_config_raw(gctx, sid)?;\n    let mut global_provider_defined = true;\n    let default_providers = || {\n        global_provider_defined = false;\n        if gctx.cli_unstable().asymmetric_token {\n            // Enable the PASETO provider\n            vec![\n                vec![\"cargo:token\".to_string()],\n                vec![\"cargo:paseto\".to_string()],\n            ]\n        } else {\n            vec![vec![\"cargo:token\".to_string()]]\n        }\n    };\n    let global_providers = gctx\n        .get::<Option<Vec<Value<String>>>>(\"registry.global-credential-providers\")?\n        .filter(|p| !p.is_empty())\n        .map(|p| {\n            p.iter()\n                .rev()\n                .map(PathAndArgs::from_whitespace_separated_string)\n                .map(|p| resolve_credential_alias(gctx, p))\n                .collect()\n        })\n        .unwrap_or_else(default_providers);\n    tracing::debug!(?global_providers);\n\n    match cfg {\n        // If there's a specific provider configured for this registry, use it.\n        Some(RegistryConfig {\n            credential_provider: Some(provider),\n            token,\n            secret_key,\n            ..\n        }) => {\n            let provider = resolve_credential_alias(gctx, provider);\n            if let Some(token) = token {\n                if provider[0] != \"cargo:token\" {\n                    warn(format!(\n                        \"{sid} has a token configured in {} that will be ignored \\\n                        because this registry is configured to use credential-provider `{}`\",\n                        token.definition, provider[0],\n                    ))?;\n                }\n            }\n            if let Some(secret_key) = secret_key {\n                if provider[0] != \"cargo:paseto\" {\n                    warn(format!(\n                        \"{sid} has a secret-key configured in {} that will be ignored \\\n                        because this registry is configured to use credential-provider `{}`\",\n                        secret_key.definition, provider[0],\n                    ))?;\n                }\n            }\n            return Ok(vec![provider]);\n        }\n\n        // Warning for both `token` and `secret-key`, stating which will be ignored\n        Some(RegistryConfig {\n            token: Some(token),\n            secret_key: Some(secret_key),\n            ..\n        }) if gctx.cli_unstable().asymmetric_token => {\n            let token_pos = global_providers\n                .iter()\n                .position(|p| p.first().map(String::as_str) == Some(\"cargo:token\"));\n            let paseto_pos = global_providers\n                .iter()\n                .position(|p| p.first().map(String::as_str) == Some(\"cargo:paseto\"));\n            match (token_pos, paseto_pos) {\n                (Some(token_pos), Some(paseto_pos)) => {\n                    if token_pos < paseto_pos {\n                        warn(format!(\n                            \"{sid} has a `secret_key` configured in {} that will be ignored \\\n                        because a `token` is also configured, and the `cargo:token` provider is \\\n                        configured with higher precedence\",\n                            secret_key.definition\n                        ))?;\n                    } else {\n                        warn(format!(\n                            \"{sid} has a `token` configured in {} that will be ignored \\\n                        because a `secret_key` is also configured, and the `cargo:paseto` provider is \\\n                        configured with higher precedence\",\n                            token.definition\n                        ))?;\n                    }\n                }\n                (_, _) => {\n                    // One or both of the below individual warnings will trigger\n                }\n            }\n        }\n\n        // Check if a `token` is configured that will be ignored.\n        Some(RegistryConfig {\n            token: Some(token), ..\n        }) => {\n            if !global_providers\n                .iter()\n                .any(|p| p.first().map(String::as_str) == Some(\"cargo:token\"))\n            {\n                warn(format!(\n                    \"{sid} has a token configured in {} that will be ignored \\\n                    because the `cargo:token` credential provider is not listed in \\\n                    `registry.global-credential-providers`\",\n                    token.definition\n                ))?;\n            }\n        }\n\n        // Check if a asymmetric token is configured that will be ignored.\n        Some(RegistryConfig {\n            secret_key: Some(token),\n            ..\n        }) if gctx.cli_unstable().asymmetric_token => {\n            if !global_providers\n                .iter()\n                .any(|p| p.first().map(String::as_str) == Some(\"cargo:paseto\"))\n            {\n                warn(format!(\n                    \"{sid} has a secret-key configured in {} that will be ignored \\\n                    because the `cargo:paseto` credential provider is not listed in \\\n                    `registry.global-credential-providers`\",\n                    token.definition\n                ))?;\n            }\n        }\n\n        // If we couldn't find a registry-specific provider, use the fallback provider list.\n        None | Some(RegistryConfig { .. }) => {}\n    };\n    if !global_provider_defined && require_cred_provider_config {\n        bail!(\n            \"authenticated registries require a credential-provider to be configured\\n\\\n        see {} for details\",\n            cargo_docs_link(\"reference/registry-authentication.html\")\n        );\n    }\n    Ok(global_providers)\n}\n\n/// Get the credential configuration for a `SourceId`.\npub fn registry_credential_config_raw(\n    gctx: &GlobalContext,\n    sid: &SourceId,\n) -> CargoResult<Option<RegistryConfig>> {\n    let mut cache = gctx.registry_config();\n    if let Some(cfg) = cache.get(&sid) {\n        return Ok(cfg.clone());\n    }\n    let cfg = registry_credential_config_raw_uncached(gctx, sid)?;\n    cache.insert(*sid, cfg.clone());\n    return Ok(cfg);\n}\n\nfn registry_credential_config_raw_uncached(\n    gctx: &GlobalContext,\n    sid: &SourceId,\n) -> CargoResult<Option<RegistryConfig>> {\n    tracing::trace!(\"loading credential config for {}\", sid);\n    gctx.load_credentials()?;\n    if !sid.is_remote_registry() {\n        bail!(\n            \"{} does not support API commands.\\n\\\n             Check for a source-replacement in .cargo/config.\",\n            sid\n        );\n    }\n\n    // Handle crates.io specially, since it uses different configuration keys.\n    if sid.is_crates_io() {\n        gctx.check_registry_index_not_set()?;\n        return Ok(gctx\n            .get::<Option<RegistryConfigExtended>>(\"registry\")?\n            .map(|c| c.to_registry_config()));\n    }\n\n    // Find the SourceId's name by its index URL. If environment variables\n    // are available they will be preferred over configuration values.\n    //\n    // The fundamental problem is that we only know the index url of the registry\n    // for certain. For example, an unnamed registry source can come from the `--index`\n    // command line argument, or from a Cargo.lock file. For this reason, we always\n    // attempt to discover the name by looking it up by the index URL.\n    //\n    // This also allows the authorization token for a registry to be set\n    // without knowing the registry name by using the _INDEX and _TOKEN\n    // environment variables.\n\n    let name = {\n        // Discover names from environment variables.\n        let index = sid.canonical_url();\n        let mut names: Vec<_> = gctx\n            .env()\n            .filter_map(|(k, v)| {\n                Some((\n                    k.strip_prefix(\"CARGO_REGISTRIES_\")?\n                        .strip_suffix(\"_INDEX\")?,\n                    v,\n                ))\n            })\n            .filter_map(|(k, v)| Some((k, CanonicalUrl::new(&v.into_url().ok()?).ok()?)))\n            .filter(|(_, v)| v == index)\n            .map(|(k, _)| k.to_lowercase())\n            .collect();\n\n        // Discover names from the configuration only if none were found in the environment.\n        if names.len() == 0 {\n            if let Some(registries) = gctx.values()?.get(\"registries\") {\n                let (registries, _) = registries.table(\"registries\")?;\n                for (name, value) in registries {\n                    if let Some(v) = value.table(&format!(\"registries.{name}\"))?.0.get(\"index\") {\n                        let (v, _) = v.string(&format!(\"registries.{name}.index\"))?;\n                        if index == &CanonicalUrl::new(&v.into_url()?)? {\n                            names.push(name.clone());\n                        }\n                    }\n                }\n            }\n        }\n        names.sort();\n        match names.len() {\n            0 => None,\n            1 => Some(std::mem::take(&mut names[0])),\n            _ => anyhow::bail!(\n                \"multiple registries are configured with the same index url '{}': {}\",\n                &sid.as_url(),\n                names.join(\", \")\n            ),\n        }\n    };\n\n    // It's possible to have a registry configured in a Cargo config file,\n    // then override it with configuration from environment variables.\n    // If the name doesn't match, leave a note to help the user understand\n    // the potentially confusing situation.\n    if let Some(name) = name.as_deref() {\n        if Some(name) != sid.alt_registry_key() {\n            gctx.shell().note(format!(\n                \"name of alternative registry `{}` set to `{name}`\",\n                sid.url()\n            ))?\n        }\n    }\n\n    if let Some(name) = &name {\n        tracing::debug!(\"found alternative registry name `{name}` for {sid}\");\n        gctx.get::<Option<RegistryConfig>>(&format!(\"registries.{name}\"))\n    } else {\n        tracing::debug!(\"no registry name found for {sid}\");\n        Ok(None)\n    }\n}\n\n/// Use the `[credential-alias]` table to see if the provider name has been aliased.\nfn resolve_credential_alias(gctx: &GlobalContext, mut provider: PathAndArgs) -> Vec<String> {\n    if provider.args.is_empty() {\n        let name = provider.path.raw_value();\n        let key = format!(\"credential-alias.{name}\");\n        if let Ok(alias) = gctx.get::<Value<PathAndArgs>>(&key) {\n            tracing::debug!(\"resolving credential alias '{key}' -> '{alias:?}'\");\n            if BUILT_IN_PROVIDERS.contains(&name) {\n                let _ = gctx.shell().warn(format!(\n                    \"credential-alias `{name}` (defined in `{}`) will be \\\n                    ignored because it would shadow a built-in credential-provider\",\n                    alias.definition\n                ));\n            } else {\n                provider = alias.val;\n            }\n        }\n    }\n    provider.args.insert(\n        0,\n        provider\n            .path\n            .resolve_program(gctx)\n            .to_str()\n            .unwrap()\n            .to_string(),\n    );\n    provider.args\n}\n\n#[derive(Debug, PartialEq)]\npub enum AuthorizationErrorReason {\n    TokenMissing,\n    TokenRejected,\n}\n\nimpl fmt::Display for AuthorizationErrorReason {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            AuthorizationErrorReason::TokenMissing => write!(f, \"no token found\"),\n            AuthorizationErrorReason::TokenRejected => write!(f, \"token rejected\"),\n        }\n    }\n}\n\n/// An authorization error from accessing a registry.\n#[derive(Debug)]\npub struct AuthorizationError {\n    /// Url that was attempted\n    sid: SourceId,\n    /// The `registry.default` config value.\n    default_registry: Option<String>,\n    /// Url where the user could log in.\n    pub login_url: Option<Url>,\n    /// Specific reason indicating what failed\n    reason: AuthorizationErrorReason,\n    /// Should `cargo login` and the `_TOKEN` env var be included when displaying this error?\n    supports_cargo_token_credential_provider: bool,\n}\n\nimpl AuthorizationError {\n    pub fn new(\n        gctx: &GlobalContext,\n        sid: SourceId,\n        login_url: Option<Url>,\n        reason: AuthorizationErrorReason,\n    ) -> CargoResult<Self> {\n        // Only display the _TOKEN environment variable suggestion if the `cargo:token` credential\n        // provider is available for the source. Otherwise setting the environment variable will\n        // have no effect.\n        let supports_cargo_token_credential_provider =\n            credential_provider(gctx, &sid, false, false)?\n                .iter()\n                .any(|p| p.first().map(String::as_str) == Some(\"cargo:token\"));\n        Ok(AuthorizationError {\n            sid,\n            default_registry: gctx.default_registry()?,\n            login_url,\n            reason,\n            supports_cargo_token_credential_provider,\n        })\n    }\n}\n\nimpl Error for AuthorizationError {}\nimpl fmt::Display for AuthorizationError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        if self.sid.is_crates_io() {\n            let args = if self.default_registry.is_some() {\n                \" --registry crates-io\"\n            } else {\n                \"\"\n            };\n            write!(f, \"{}, please run `cargo login{args}`\", self.reason)?;\n            if self.supports_cargo_token_credential_provider {\n                write!(f, \"\\nor use environment variable CARGO_REGISTRY_TOKEN\")?;\n            }\n            Ok(())\n        } else if let Some(name) = self.sid.alt_registry_key() {\n            write!(\n                f,\n                \"{} for `{}`\",\n                self.reason,\n                self.sid.display_registry_name()\n            )?;\n            if self.supports_cargo_token_credential_provider {\n                let key = ConfigKey::from_str(&format!(\"registries.{name}.token\"));\n                write!(\n                    f,\n                    \", please run `cargo login --registry {name}`\\n\\\n                    or use environment variable {}\",\n                    key.as_env_key()\n                )?;\n            } else {\n                write!(\n                    f,\n                    \"\\nYou may need to log in using this registry's credential provider\"\n                )?;\n            }\n            Ok(())\n        } else if self.reason == AuthorizationErrorReason::TokenMissing {\n            write!(\n                f,\n                r#\"{} for `{}`\nconsider setting up an alternate registry in Cargo's configuration\nas described by https://doc.rust-lang.org/cargo/reference/registries.html\n\n[registries]\nmy-registry = {{ index = \"{}\" }}\n\"#,\n                self.reason,\n                self.sid.display_registry_name(),\n                self.sid.url()\n            )\n        } else {\n            write!(\n                f,\n                r#\"{} for `{}`\"#,\n                self.reason,\n                self.sid.display_registry_name(),\n            )\n        }\n    }\n}\n\n/// Store a token in the cache for future calls.\npub fn cache_token_from_commandline(gctx: &GlobalContext, sid: &SourceId, token: Secret<&str>) {\n    let url = sid.canonical_url();\n    gctx.credential_cache().insert(\n        url.clone(),\n        CredentialCacheValue {\n            token_value: token.to_owned(),\n            expiration: None,\n            operation_independent: true,\n        },\n    );\n}\n\n/// List of credential providers built-in to Cargo.\n/// Keep in sync with the `match` in `credential_action`.\nstatic BUILT_IN_PROVIDERS: &[&'static str] = &[\n    \"cargo:token\",\n    \"cargo:paseto\",\n    \"cargo:token-from-stdout\",\n    \"cargo:wincred\",\n    \"cargo:macos-keychain\",\n    \"cargo:libsecret\",\n];\n\n/// Retrieves a cached instance of `LibSecretCredential`.\n/// Must be cached to avoid repeated load/unload cycles, which are not supported by `glib`.\n#[cfg(target_os = \"linux\")]\nfn get_credential_libsecret()\n-> CargoResult<&'static cargo_credential_libsecret::LibSecretCredential> {\n    static CARGO_CREDENTIAL_LIBSECRET: std::sync::OnceLock<\n        cargo_credential_libsecret::LibSecretCredential,\n    > = std::sync::OnceLock::new();\n    // Unfortunately `get_or_try_init` is not yet stable. This workaround is not threadsafe but\n    // loading libsecret twice will only temporary increment the ref counter, which is decrement\n    // again when `drop` is called.\n    match CARGO_CREDENTIAL_LIBSECRET.get() {\n        Some(lib) => Ok(lib),\n        None => {\n            let _ = CARGO_CREDENTIAL_LIBSECRET\n                .set(cargo_credential_libsecret::LibSecretCredential::new()?);\n            Ok(CARGO_CREDENTIAL_LIBSECRET.get().unwrap())\n        }\n    }\n}\n\nfn credential_action(\n    gctx: &GlobalContext,\n    sid: &SourceId,\n    action: Action<'_>,\n    headers: Vec<String>,\n    args: &[&str],\n    require_cred_provider_config: bool,\n) -> CargoResult<CredentialResponse> {\n    let name = sid.alt_registry_key();\n    let registry = RegistryInfo {\n        index_url: sid.url().as_str(),\n        name,\n        headers,\n    };\n    let providers = credential_provider(gctx, sid, require_cred_provider_config, true)?;\n    let mut any_not_found = false;\n    for provider in providers {\n        let args: Vec<&str> = provider\n            .iter()\n            .map(String::as_str)\n            .chain(args.iter().copied())\n            .collect();\n        let process = args[0];\n        tracing::debug!(\"attempting credential provider: {args:?}\");\n        // If the available built-in providers are changed, update the `BUILT_IN_PROVIDERS` list.\n        let provider: Box<dyn Credential> = match process {\n            \"cargo:token\" => Box::new(TokenCredential::new(gctx)),\n            \"cargo:paseto\" if gctx.cli_unstable().asymmetric_token => {\n                Box::new(PasetoCredential::new(gctx))\n            }\n            \"cargo:paseto\" => bail!(\"cargo:paseto requires -Zasymmetric-token\"),\n            \"cargo:token-from-stdout\" => Box::new(BasicProcessCredential {}),\n            #[cfg(windows)]\n            \"cargo:wincred\" => Box::new(cargo_credential_wincred::WindowsCredential {}),\n            #[cfg(target_os = \"macos\")]\n            \"cargo:macos-keychain\" => Box::new(cargo_credential_macos_keychain::MacKeychain {}),\n            #[cfg(target_os = \"linux\")]\n            \"cargo:libsecret\" => Box::new(get_credential_libsecret()?),\n            name if BUILT_IN_PROVIDERS.contains(&name) => {\n                Box::new(cargo_credential::UnsupportedCredential {})\n            }\n            process => Box::new(CredentialProcessCredential::new(process)),\n        };\n        gctx.shell().verbose(|c| {\n            c.status(\n                \"Credential\",\n                format!(\n                    \"{} {action} {}\",\n                    args.join(\" \"),\n                    sid.display_registry_name()\n                ),\n            )\n        })?;\n        match provider.perform(&registry, &action, &args[1..]) {\n            Ok(response) => return Ok(response),\n            Err(cargo_credential::Error::UrlNotSupported) => {}\n            Err(cargo_credential::Error::NotFound) => any_not_found = true,\n            e => {\n                return e.with_context(|| {\n                    format!(\n                        \"credential provider `{}` failed action `{action}`\",\n                        args.join(\" \")\n                    )\n                });\n            }\n        }\n    }\n    if any_not_found {\n        Err(cargo_credential::Error::NotFound.into())\n    } else {\n        anyhow::bail!(\"no credential providers could handle the request\")\n    }\n}\n\n/// Returns the token to use for the given registry.\n/// If a `login_url` is provided and a token is not available, the\n/// `login_url` will be included in the returned error.\npub fn auth_token(\n    gctx: &GlobalContext,\n    sid: &SourceId,\n    login_url: Option<&Url>,\n    operation: Operation<'_>,\n    headers: Vec<String>,\n    require_cred_provider_config: bool,\n) -> CargoResult<String> {\n    match auth_token_optional(gctx, sid, operation, headers, require_cred_provider_config)? {\n        Some(token) => Ok(token.expose()),\n        None => Err(AuthorizationError::new(\n            gctx,\n            *sid,\n            login_url.cloned(),\n            AuthorizationErrorReason::TokenMissing,\n        )?\n        .into()),\n    }\n}\n\n/// Returns the token to use for the given registry.\nfn auth_token_optional(\n    gctx: &GlobalContext,\n    sid: &SourceId,\n    operation: Operation<'_>,\n    headers: Vec<String>,\n    require_cred_provider_config: bool,\n) -> CargoResult<Option<Secret<String>>> {\n    tracing::trace!(\"token requested for {}\", sid.display_registry_name());\n    let mut cache = gctx.credential_cache();\n    let url = sid.canonical_url();\n    if let Some(cached_token) = cache.get(url) {\n        if cached_token\n            .expiration\n            .map(|exp| OffsetDateTime::now_utc() + Duration::minutes(1) < exp)\n            .unwrap_or(true)\n        {\n            if cached_token.operation_independent || matches!(operation, Operation::Read) {\n                tracing::trace!(\"using token from in-memory cache\");\n                return Ok(Some(cached_token.token_value.clone()));\n            }\n        } else {\n            // Remove expired token from the cache\n            cache.remove(url);\n        }\n    }\n\n    let credential_response = credential_action(\n        gctx,\n        sid,\n        Action::Get(operation),\n        headers,\n        &[],\n        require_cred_provider_config,\n    );\n    if let Some(e) = credential_response.as_ref().err() {\n        if let Some(e) = e.downcast_ref::<cargo_credential::Error>() {\n            if matches!(e, cargo_credential::Error::NotFound) {\n                return Ok(None);\n            }\n        }\n    }\n    let credential_response = credential_response?;\n\n    let CredentialResponse::Get {\n        token,\n        cache: cache_control,\n        operation_independent,\n    } = credential_response\n    else {\n        bail!(\n            \"credential provider produced unexpected response for `get` request: {credential_response:?}\"\n        )\n    };\n    let token = Secret::from(token);\n    tracing::trace!(\"found token\");\n    let expiration = match cache_control {\n        CacheControl::Expires { expiration } => Some(expiration),\n        CacheControl::Session => None,\n        CacheControl::Never | _ => return Ok(Some(token)),\n    };\n\n    cache.insert(\n        url.clone(),\n        CredentialCacheValue {\n            token_value: token.clone(),\n            expiration,\n            operation_independent,\n        },\n    );\n    Ok(Some(token))\n}\n\n/// Log out from the given registry.\npub fn logout(gctx: &GlobalContext, sid: &SourceId) -> CargoResult<()> {\n    let credential_response = credential_action(gctx, sid, Action::Logout, vec![], &[], false);\n    if let Some(e) = credential_response.as_ref().err() {\n        if let Some(e) = e.downcast_ref::<cargo_credential::Error>() {\n            if matches!(e, cargo_credential::Error::NotFound) {\n                gctx.shell().status(\n                    \"Logout\",\n                    format!(\n                        \"not currently logged in to `{}`\",\n                        sid.display_registry_name()\n                    ),\n                )?;\n                return Ok(());\n            }\n        }\n    }\n    let credential_response = credential_response?;\n    let CredentialResponse::Logout = credential_response else {\n        bail!(\n            \"credential provider produced unexpected response for `logout` request: {credential_response:?}\"\n        )\n    };\n    Ok(())\n}\n\n/// Log in to the given registry.\npub fn login(\n    gctx: &GlobalContext,\n    sid: &SourceId,\n    options: LoginOptions<'_>,\n    args: &[&str],\n) -> CargoResult<()> {\n    let credential_response =\n        credential_action(gctx, sid, Action::Login(options), vec![], args, false)?;\n    let CredentialResponse::Login = credential_response else {\n        bail!(\n            \"credential provider produced unexpected response for `login` request: {credential_response:?}\"\n        )\n    };\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/util/cache_lock.rs",
    "content": "//! Support for locking the package and index caches.\n//!\n//! This implements locking on the package and index caches (source files,\n//! `.crate` files, and index caches) to coordinate when multiple cargos are\n//! running at the same time.\n//!\n//! ## Usage\n//!\n//! There is a global [`CacheLocker`] held inside cargo's venerable\n//! [`GlobalContext`]. The `CacheLocker` manages creating and tracking the locks\n//! being held. There are methods on [`GlobalContext`] for managing the locks:\n//!\n//! - [`GlobalContext::acquire_package_cache_lock`] --- Acquires a lock. May block if\n//!   another process holds a lock.\n//! - [`GlobalContext::try_acquire_package_cache_lock`] --- Acquires a lock, returning\n//!   immediately if it would block.\n//! - [`GlobalContext::assert_package_cache_locked`] --- This is used to ensure the\n//!   proper lock is being held.\n//!\n//! Lower-level code that accesses the package cache typically just use\n//! `assert_package_cache_locked` to ensure that the correct lock is being\n//! held. Higher-level code is responsible for acquiring the appropriate lock,\n//! and holding it during the duration that it is performing its operation.\n//!\n//! ## Types of locking\n//!\n//! There are three styles of locks:\n//!\n//! * [`CacheLockMode::DownloadExclusive`] -- This is an exclusive lock\n//!   acquired while downloading packages and doing resolution.\n//! * [`CacheLockMode::Shared`] -- This is a shared lock acquired while a\n//!   build is running. In other words, whenever cargo just needs to read from\n//!   the cache, it should hold this lock. This is here to ensure that no\n//!   cargos are trying to read the source caches when cache garbage\n//!   collection runs.\n//! * [`CacheLockMode::MutateExclusive`] -- This is an exclusive lock acquired\n//!   whenever needing to modify existing source files (for example, with\n//!   cache garbage collection). This is acquired to make sure that no other\n//!   cargo is reading from the cache.\n//!\n//! Importantly, a `DownloadExclusive` lock does *not* interfere with a\n//! `Shared` lock. The download process generally does not modify source files\n//! (it only adds new ones), so other cargos should be able to safely proceed\n//! in reading source files[^1].\n//!\n//! See the [`CacheLockMode`] enum docs for more details on when the different\n//! modes should be used.\n//!\n//! ## Locking implementation details\n//!\n//! This is implemented by two separate lock files, the \"download\" one and the\n//! \"mutate\" one. The `MutateExclusive` lock acquired both the \"mutate\" and\n//! \"download\" locks. The `Shared` lock acquires the \"mutate\" lock in share\n//! mode.\n//!\n//! An important rule is that `MutateExclusive` acquires the locks in the\n//! order \"mutate\" first and then the \"download\". That helps prevent\n//! deadlocks. It is not allowed for a cargo to first acquire a\n//! `DownloadExclusive` lock and then a `Shared` lock because that would open\n//! it up for deadlock.\n//!\n//! Another rule is that there should be only one [`CacheLocker`] per process\n//! to uphold the ordering rules. You could in theory have multiple if you\n//! could ensure that other threads would make progress and drop a lock, but\n//! cargo is not architected that way.\n//!\n//! It is safe to recursively acquire a lock as many times as you want.\n//!\n//! ## Interaction with older cargos\n//!\n//! Before version 1.74, cargo only acquired the `DownloadExclusive` lock when\n//! downloading and doing resolution. Newer cargos that acquire\n//! `MutateExclusive` should still correctly block when an old cargo is\n//! downloading (because it also acquires `DownloadExclusive`), but they do\n//! not properly coordinate when an old cargo is in the build phase (because\n//! it holds no locks). This isn't expected to be much of a problem because\n//! the intended use of mutating the cache is only to delete old contents\n//! which aren't currently being used. It is possible for there to be a\n//! conflict, particularly if the user manually deletes the entire cache, but\n//! it is not expected for this scenario to happen too often, and the only\n//! consequence is that one side or the other encounters an error and needs to\n//! retry.\n//!\n//! [^1]: A minor caveat is that downloads will delete an existing `src`\n//!   directory if it was extracted via an old cargo. See\n//!   [`crate::sources::registry::RegistrySource::unpack_package`]. This\n//!   should probably be fixed, but is unlikely to be a problem if the user is\n//!   only using versions of cargo with the same deletion logic.\n\nuse super::FileLock;\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse anyhow::Context as _;\nuse std::io;\nuse std::sync::Mutex;\n\n/// The style of lock to acquire.\n#[derive(Copy, Clone, Debug, PartialEq)]\npub enum CacheLockMode {\n    /// A `DownloadExclusive` lock ensures that only one cargo is doing\n    /// resolution and downloading new packages.\n    ///\n    /// You should use this when downloading new packages or doing resolution.\n    ///\n    /// If another cargo has a `MutateExclusive` lock, then an attempt to get\n    /// a `DownloadExclusive` lock will block.\n    ///\n    /// If another cargo has a `Shared` lock, then both can operate\n    /// concurrently.\n    DownloadExclusive,\n    /// A `Shared` lock allows multiple cargos to read from the source files.\n    ///\n    /// You should use this when cargo is reading source files from the\n    /// package cache. This is typically done during the build phase, since\n    /// cargo only needs to read files during that time. This allows multiple\n    /// cargo processes to build concurrently without interfering with one\n    /// another, while guarding against other cargos using `MutateExclusive`.\n    ///\n    /// If another cargo has a `MutateExclusive` lock, then an attempt to get\n    /// a `Shared` will block.\n    ///\n    /// If another cargo has a `DownloadExclusive` lock, then they both can\n    /// operate concurrently under the assumption that downloading does not\n    /// modify existing source files.\n    Shared,\n    /// A `MutateExclusive` lock ensures no other cargo is reading or writing\n    /// from the package caches.\n    ///\n    /// You should use this when modifying existing files in the package\n    /// cache. For example, things like garbage collection want to avoid\n    /// deleting files while other cargos are trying to read (`Shared`) or\n    /// resolve or download (`DownloadExclusive`).\n    ///\n    /// If another cargo has a `DownloadExclusive` or `Shared` lock, then this\n    /// will block until they all release their locks.\n    MutateExclusive,\n}\n\n/// Whether or not a lock attempt should block.\n#[derive(Copy, Clone)]\nenum BlockingMode {\n    Blocking,\n    NonBlocking,\n}\n\nuse BlockingMode::*;\n\n/// Whether or not a lock attempt blocked or succeeded.\n#[derive(PartialEq, Copy, Clone)]\n#[must_use]\nenum LockingResult {\n    LockAcquired,\n    WouldBlock,\n}\n\nuse LockingResult::*;\n\n/// A file lock, with a counter to assist with recursive locking.\n#[derive(Debug)]\nstruct RecursiveLock {\n    /// The file lock.\n    ///\n    /// An important note is that locks can be `None` even when they are held.\n    /// This can happen on things like old NFS mounts where locking isn't\n    /// supported. We otherwise pretend we have a lock via the lock count. See\n    /// [`FileLock`] for more detail on that.\n    lock: Option<FileLock>,\n    /// Number locks held, to support recursive locking.\n    count: u32,\n    /// If this is `true`, it is an exclusive lock, otherwise it is shared.\n    is_exclusive: bool,\n    /// The filename of the lock.\n    filename: &'static str,\n}\n\nimpl RecursiveLock {\n    fn new(filename: &'static str) -> RecursiveLock {\n        RecursiveLock {\n            lock: None,\n            count: 0,\n            is_exclusive: false,\n            filename,\n        }\n    }\n\n    /// Low-level lock count increment routine.\n    fn increment(&mut self) {\n        self.count = self.count.checked_add(1).unwrap();\n    }\n\n    /// Unlocks a previously acquired lock.\n    fn decrement(&mut self) {\n        let new_cnt = self.count.checked_sub(1).unwrap();\n        self.count = new_cnt;\n        if new_cnt == 0 {\n            // This will drop, releasing the lock.\n            self.lock = None;\n        }\n    }\n\n    /// Acquires a shared lock.\n    fn lock_shared(\n        &mut self,\n        gctx: &GlobalContext,\n        description: &'static str,\n        blocking: BlockingMode,\n    ) -> LockingResult {\n        match blocking {\n            Blocking => {\n                self.lock_shared_blocking(gctx, description);\n                LockAcquired\n            }\n            NonBlocking => self.lock_shared_nonblocking(gctx),\n        }\n    }\n\n    /// Acquires a shared lock, blocking if held by another locker.\n    fn lock_shared_blocking(&mut self, gctx: &GlobalContext, description: &'static str) {\n        if self.count == 0 {\n            self.is_exclusive = false;\n            self.lock = match gctx\n                .home()\n                .open_ro_shared_create(self.filename, gctx, description)\n            {\n                Ok(lock) => Some(lock),\n                Err(e) => {\n                    // There is no error here because locking is mostly a\n                    // best-effort attempt. If cargo home is read-only, we don't\n                    // want to fail just because we couldn't create the lock file.\n                    tracing::warn!(\"failed to acquire cache lock {}: {e:?}\", self.filename);\n                    None\n                }\n            };\n        }\n        self.increment();\n    }\n\n    /// Acquires a shared lock, returns [`WouldBlock`] if held by another locker.\n    fn lock_shared_nonblocking(&mut self, gctx: &GlobalContext) -> LockingResult {\n        if self.count == 0 {\n            self.is_exclusive = false;\n            self.lock = match gctx.home().try_open_ro_shared_create(self.filename) {\n                Ok(Some(lock)) => Some(lock),\n                Ok(None) => {\n                    return WouldBlock;\n                }\n                Err(e) => {\n                    // Pretend that the lock was acquired (see lock_shared_blocking).\n                    tracing::warn!(\"failed to acquire cache lock {}: {e:?}\", self.filename);\n                    None\n                }\n            };\n        }\n        self.increment();\n        LockAcquired\n    }\n\n    /// Acquires an exclusive lock.\n    fn lock_exclusive(\n        &mut self,\n        gctx: &GlobalContext,\n        description: &'static str,\n        blocking: BlockingMode,\n    ) -> CargoResult<LockingResult> {\n        if self.count > 0 && !self.is_exclusive {\n            // Lock upgrades are dicey. It might be possible to support\n            // this but would take a bit of work, and so far it isn't\n            // needed.\n            panic!(\"lock upgrade from shared to exclusive not supported\");\n        }\n        match blocking {\n            Blocking => {\n                self.lock_exclusive_blocking(gctx, description)?;\n                Ok(LockAcquired)\n            }\n            NonBlocking => self.lock_exclusive_nonblocking(gctx),\n        }\n    }\n\n    /// Acquires an exclusive lock, blocking if held by another locker.\n    fn lock_exclusive_blocking(\n        &mut self,\n        gctx: &GlobalContext,\n        description: &'static str,\n    ) -> CargoResult<()> {\n        if self.count == 0 {\n            self.is_exclusive = true;\n            match gctx\n                .home()\n                .open_rw_exclusive_create(self.filename, gctx, description)\n            {\n                Ok(lock) => self.lock = Some(lock),\n                Err(e) => {\n                    if maybe_readonly(&e) {\n                        // This is a best-effort attempt to at least try to\n                        // acquire some sort of lock. This can help in the\n                        // situation where this cargo only has read-only access,\n                        // but maybe some other cargo has read-write. This will at\n                        // least attempt to coordinate with it.\n                        //\n                        // We don't want to fail on a read-only mount because\n                        // cargo grabs an exclusive lock in situations where it\n                        // may only be reading from the package cache. In that\n                        // case, cargo isn't writing anything, and we don't want\n                        // to fail on that.\n                        self.lock_shared_blocking(gctx, description);\n                        // This has to pretend it is exclusive for recursive locks to work.\n                        self.is_exclusive = true;\n                        return Ok(());\n                    } else {\n                        return Err(e).context(\"failed to acquire package cache lock\");\n                    }\n                }\n            }\n        }\n        self.increment();\n        Ok(())\n    }\n\n    /// Acquires an exclusive lock, returns [`WouldBlock`] if held by another locker.\n    fn lock_exclusive_nonblocking(&mut self, gctx: &GlobalContext) -> CargoResult<LockingResult> {\n        if self.count == 0 {\n            self.is_exclusive = true;\n            match gctx.home().try_open_rw_exclusive_create(self.filename) {\n                Ok(Some(lock)) => self.lock = Some(lock),\n                Ok(None) => return Ok(WouldBlock),\n                Err(e) => {\n                    if maybe_readonly(&e) {\n                        let result = self.lock_shared_nonblocking(gctx);\n                        // This has to pretend it is exclusive for recursive locks to work.\n                        self.is_exclusive = true;\n                        return Ok(result);\n                    } else {\n                        return Err(e).context(\"failed to acquire package cache lock\");\n                    }\n                }\n            }\n        }\n        self.increment();\n        Ok(LockAcquired)\n    }\n}\n\n/// The state of the [`CacheLocker`].\n#[derive(Debug)]\nstruct CacheState {\n    /// The cache lock guards the package cache used for download and\n    /// resolution (append operations that should not interfere with reading\n    /// from existing src files).\n    cache_lock: RecursiveLock,\n    /// The mutate lock is used to either guard the entire package cache for\n    /// destructive modifications (in exclusive mode), or for reading the\n    /// package cache src files (in shared mode).\n    ///\n    /// Note that [`CacheLockMode::MutateExclusive`] holds both\n    /// [`CacheState::mutate_lock`] and [`CacheState::cache_lock`].\n    mutate_lock: RecursiveLock,\n}\n\nimpl CacheState {\n    fn lock(\n        &mut self,\n        gctx: &GlobalContext,\n        mode: CacheLockMode,\n        blocking: BlockingMode,\n    ) -> CargoResult<LockingResult> {\n        use CacheLockMode::*;\n        if mode == Shared && self.cache_lock.count > 0 && self.mutate_lock.count == 0 {\n            // Shared lock, when a DownloadExclusive is held.\n            //\n            // This isn't supported because it could cause a deadlock. If\n            // one cargo is attempting to acquire a MutateExclusive lock,\n            // and acquires the mutate lock, but is blocked on the\n            // download lock, and the cargo that holds the download lock\n            // attempts to get a shared lock, they would end up blocking\n            // each other.\n            panic!(\"shared lock while holding download lock is not allowed\");\n        }\n        match mode {\n            Shared => {\n                if self.mutate_lock.lock_shared(gctx, SHARED_DESCR, blocking) == WouldBlock {\n                    return Ok(WouldBlock);\n                }\n            }\n            DownloadExclusive => {\n                if self\n                    .cache_lock\n                    .lock_exclusive(gctx, DOWNLOAD_EXCLUSIVE_DESCR, blocking)?\n                    == WouldBlock\n                {\n                    return Ok(WouldBlock);\n                }\n            }\n            MutateExclusive => {\n                if self\n                    .mutate_lock\n                    .lock_exclusive(gctx, MUTATE_EXCLUSIVE_DESCR, blocking)?\n                    == WouldBlock\n                {\n                    return Ok(WouldBlock);\n                }\n\n                // Part of the contract of MutateExclusive is that it doesn't\n                // allow any processes to have a lock on the package cache, so\n                // this acquires both locks.\n                match self\n                    .cache_lock\n                    .lock_exclusive(gctx, DOWNLOAD_EXCLUSIVE_DESCR, blocking)\n                {\n                    Ok(LockAcquired) => {}\n                    Ok(WouldBlock) => {\n                        self.mutate_lock.decrement();\n                        return Ok(WouldBlock);\n                    }\n                    Err(e) => {\n                        self.mutate_lock.decrement();\n                        return Err(e);\n                    }\n                }\n            }\n        }\n        Ok(LockAcquired)\n    }\n}\n\n/// A held lock guard.\n///\n/// When this is dropped, the lock will be released.\n#[must_use]\npub struct CacheLock<'lock> {\n    mode: CacheLockMode,\n    locker: &'lock CacheLocker,\n}\n\nimpl Drop for CacheLock<'_> {\n    fn drop(&mut self) {\n        use CacheLockMode::*;\n        let mut state = match self.locker.state.lock() {\n            Ok(result) => result,\n            // we should release the cache even if a thread panicked while holding a lock\n            Err(poison) => poison.into_inner(),\n        };\n        match self.mode {\n            Shared => {\n                state.mutate_lock.decrement();\n            }\n            DownloadExclusive => {\n                state.cache_lock.decrement();\n            }\n            MutateExclusive => {\n                state.cache_lock.decrement();\n                state.mutate_lock.decrement();\n            }\n        }\n    }\n}\n\n/// The filename for the [`CacheLockMode::DownloadExclusive`] lock.\nconst CACHE_LOCK_NAME: &str = \".package-cache\";\n/// The filename for the [`CacheLockMode::MutateExclusive`] and\n/// [`CacheLockMode::Shared`] lock.\nconst MUTATE_NAME: &str = \".package-cache-mutate\";\n\n// Descriptions that are displayed in the \"Blocking\" message shown to the user.\nconst SHARED_DESCR: &str = \"shared package cache\";\nconst DOWNLOAD_EXCLUSIVE_DESCR: &str = \"package cache\";\nconst MUTATE_EXCLUSIVE_DESCR: &str = \"package cache mutation\";\n\n/// A locker that can be used to acquire locks.\n///\n/// See the [`crate::util::cache_lock`] module documentation for an overview\n/// of how cache locking works.\n#[derive(Debug)]\npub struct CacheLocker {\n    /// The state of the locker.\n    ///\n    /// [`CacheLocker`] uses interior mutability because it is stuffed inside\n    /// [`GlobalContext`], which does not allow mutation.\n    state: Mutex<CacheState>,\n}\n\nimpl CacheLocker {\n    /// Creates a new `CacheLocker`.\n    pub fn new() -> CacheLocker {\n        CacheLocker {\n            state: CacheState {\n                cache_lock: RecursiveLock::new(CACHE_LOCK_NAME),\n                mutate_lock: RecursiveLock::new(MUTATE_NAME),\n            }\n            .into(),\n        }\n    }\n\n    /// Acquires a lock with the given mode, possibly blocking if another\n    /// cargo is holding the lock.\n    pub fn lock(&self, gctx: &GlobalContext, mode: CacheLockMode) -> CargoResult<CacheLock<'_>> {\n        let mut state = self.state.lock().unwrap();\n        let _ = state.lock(gctx, mode, Blocking)?;\n        Ok(CacheLock { mode, locker: self })\n    }\n\n    /// Acquires a lock with the given mode, returning `None` if another cargo\n    /// is holding the lock.\n    pub fn try_lock(\n        &self,\n        gctx: &GlobalContext,\n        mode: CacheLockMode,\n    ) -> CargoResult<Option<CacheLock<'_>>> {\n        let mut state = self.state.lock().unwrap();\n        if state.lock(gctx, mode, NonBlocking)? == LockAcquired {\n            Ok(Some(CacheLock { mode, locker: self }))\n        } else {\n            Ok(None)\n        }\n    }\n\n    /// Returns whether or not a lock is held for the given mode in this locker.\n    ///\n    /// This does not tell you whether or not it is locked in some other\n    /// locker (such as in another process).\n    ///\n    /// Note that `Shared` will return true if a `MutateExclusive` lock is\n    /// held, since `MutateExclusive` is just an upgraded `Shared`. Likewise,\n    /// `DownloadExclusive` will return true if a `MutateExclusive` lock is\n    /// held since they overlap.\n    pub fn is_locked(&self, mode: CacheLockMode) -> bool {\n        let state = self.state.lock().unwrap();\n        match (\n            mode,\n            state.cache_lock.count,\n            state.mutate_lock.count,\n            state.mutate_lock.is_exclusive,\n        ) {\n            (CacheLockMode::Shared, _, 1.., _) => true,\n            (CacheLockMode::MutateExclusive, _, 1.., true) => true,\n            (CacheLockMode::DownloadExclusive, 1.., _, _) => true,\n            _ => false,\n        }\n    }\n}\n\n/// Returns whether or not the error appears to be from a read-only filesystem.\nfn maybe_readonly(err: &anyhow::Error) -> bool {\n    err.chain().any(|err| {\n        if let Some(io) = err.downcast_ref::<io::Error>() {\n            if io.kind() == io::ErrorKind::PermissionDenied {\n                return true;\n            }\n\n            #[cfg(unix)]\n            return io.raw_os_error() == Some(libc::EROFS);\n        }\n\n        false\n    })\n}\n"
  },
  {
    "path": "src/cargo/util/canonical_url.rs",
    "content": "use crate::util::errors::CargoResult;\nuse std::hash::{self, Hash};\nuse url::Url;\n\n/// A newtype wrapper around `Url` which represents a \"canonical\" version of an\n/// original URL.\n///\n/// A \"canonical\" url is only intended for internal comparison purposes in\n/// Cargo. It's to help paper over mistakes such as depending on\n/// `github.com/foo/bar` vs `github.com/foo/bar.git`. This is **only** for\n/// internal purposes within Cargo and provides no means to actually read the\n/// underlying string value of the `Url` it contains. This is intentional,\n/// because all fetching should still happen within the context of the original\n/// URL.\n#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]\npub struct CanonicalUrl(Url);\n\nimpl CanonicalUrl {\n    pub fn new(url: &Url) -> CargoResult<CanonicalUrl> {\n        let mut url = url.clone();\n\n        // cannot-be-a-base-urls (e.g., `github.com:rust-lang/rustfmt.git`)\n        // are not supported.\n        if url.cannot_be_a_base() {\n            anyhow::bail!(\n                \"invalid url `{}`: cannot-be-a-base-URLs are not supported\",\n                url\n            )\n        }\n\n        // Strip a trailing slash.\n        if url.path().ends_with('/') {\n            url.path_segments_mut().unwrap().pop_if_empty();\n        }\n\n        // For GitHub URLs specifically, just lower-case everything. GitHub\n        // treats both the same, but they hash differently, and we're gonna be\n        // hashing them. This wants a more general solution, and also we're\n        // almost certainly not using the same case conversion rules that GitHub\n        // does. (See issue #84)\n        if url.host_str() == Some(\"github.com\") {\n            url = format!(\"https{}\", &url[url::Position::AfterScheme..])\n                .parse()\n                .unwrap();\n            let path = url.path().to_lowercase();\n            url.set_path(&path);\n        }\n\n        // Repos can generally be accessed with or without `.git` extension.\n        let needs_chopping = url.path().ends_with(\".git\");\n        if needs_chopping {\n            let last = {\n                let last = url.path_segments().unwrap().next_back().unwrap();\n                last[..last.len() - 4].to_owned()\n            };\n            url.path_segments_mut().unwrap().pop().push(&last);\n        }\n\n        Ok(CanonicalUrl(url))\n    }\n\n    /// Returns the raw canonicalized URL, although beware that this should\n    /// never be used/displayed/etc, it should only be used for internal data\n    /// structures and hashes and such.\n    pub fn raw_canonicalized_url(&self) -> &Url {\n        &self.0\n    }\n}\n\n// See comment in `source_id.rs` for why we explicitly use `as_str()` here.\nimpl Hash for CanonicalUrl {\n    fn hash<S: hash::Hasher>(&self, into: &mut S) {\n        self.0.as_str().hash(into);\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/command_prelude.rs",
    "content": "use crate::CargoResult;\nuse crate::core::Dependency;\nuse crate::core::compiler::{BuildConfig, CompileKind, MessageFormat, RustcTargetData};\nuse crate::core::resolver::{CliFeatures, ForceAllTargets, HasDevUnits};\nuse crate::core::{Edition, Package, TargetKind, Workspace, profiles::Profiles, shell};\nuse crate::ops::registry::RegistryOrIndex;\nuse crate::ops::{self, CompileFilter, CompileOptions, NewOptions, Packages, VersionControl};\nuse crate::util::important_paths::find_root_manifest_for_wd;\nuse crate::util::interning::InternedString;\nuse crate::util::is_rustup;\nuse crate::util::restricted_names;\nuse crate::util::toml::is_embedded;\nuse crate::util::{\n    print_available_benches, print_available_binaries, print_available_examples,\n    print_available_packages, print_available_tests,\n};\nuse anyhow::bail;\nuse cargo_util::paths;\nuse cargo_util_schemas::manifest::ProfileName;\nuse cargo_util_schemas::manifest::RegistryName;\nuse cargo_util_schemas::manifest::StringOrVec;\nuse clap::builder::UnknownArgumentValueParser;\nuse clap_complete::ArgValueCandidates;\nuse home::cargo_home_with_cwd;\nuse indexmap::IndexSet;\nuse itertools::Itertools;\nuse semver::Version;\nuse std::collections::{BTreeMap, HashMap, HashSet};\nuse std::ffi::{OsStr, OsString};\nuse std::path::Path;\nuse std::path::PathBuf;\n\npub use crate::core::compiler::UserIntent;\npub use crate::{CliError, CliResult, GlobalContext};\npub use clap::{Arg, ArgAction, ArgMatches, value_parser};\n\npub use clap::Command;\n\nuse super::IntoUrl;\nuse super::context::JobsConfig;\n\npub mod heading {\n    pub const PACKAGE_SELECTION: &str = \"Package Selection\";\n    pub const TARGET_SELECTION: &str = \"Target Selection\";\n    pub const FEATURE_SELECTION: &str = \"Feature Selection\";\n    pub const COMPILATION_OPTIONS: &str = \"Compilation Options\";\n    pub const MANIFEST_OPTIONS: &str = \"Manifest Options\";\n}\n\npub trait CommandExt: Sized {\n    fn _arg(self, arg: Arg) -> Self;\n\n    /// Do not use this method, it is only for backwards compatibility.\n    /// Use `arg_package_spec_no_all` instead.\n    fn arg_package_spec(\n        self,\n        package: &'static str,\n        all: &'static str,\n        exclude: &'static str,\n    ) -> Self {\n        self.arg_package_spec_no_all(\n            package,\n            all,\n            exclude,\n            ArgValueCandidates::new(get_ws_member_candidates),\n        )\n        ._arg(\n            flag(\"all\", \"Alias for --workspace (deprecated)\")\n                .help_heading(heading::PACKAGE_SELECTION),\n        )\n    }\n\n    /// Variant of `arg_package_spec` that does not include the `--all` flag\n    /// (but does include `--workspace`). Used to avoid confusion with\n    /// historical uses of `--all`.\n    fn arg_package_spec_no_all(\n        self,\n        package: &'static str,\n        all: &'static str,\n        exclude: &'static str,\n        package_completion: ArgValueCandidates,\n    ) -> Self {\n        let unsupported_short_arg = {\n            let value_parser = UnknownArgumentValueParser::suggest_arg(\"--exclude\");\n            Arg::new(\"unsupported-short-exclude-flag\")\n                .help(\"\")\n                .short('x')\n                .value_parser(value_parser)\n                .action(ArgAction::SetTrue)\n                .hide(true)\n        };\n        self.arg_package_spec_simple(package, package_completion)\n            ._arg(flag(\"workspace\", all).help_heading(heading::PACKAGE_SELECTION))\n            ._arg(\n                multi_opt(\"exclude\", \"SPEC\", exclude)\n                    .help_heading(heading::PACKAGE_SELECTION)\n                    .add(clap_complete::ArgValueCandidates::new(\n                        get_ws_member_candidates,\n                    )),\n            )\n            ._arg(unsupported_short_arg)\n    }\n\n    fn arg_package_spec_simple(\n        self,\n        package: &'static str,\n        package_completion: ArgValueCandidates,\n    ) -> Self {\n        self._arg(\n            optional_multi_opt(\"package\", \"SPEC\", package)\n                .short('p')\n                .help_heading(heading::PACKAGE_SELECTION)\n                .add(package_completion),\n        )\n    }\n\n    fn arg_package(self, package: &'static str) -> Self {\n        self._arg(\n            optional_opt(\"package\", package)\n                .short('p')\n                .value_name(\"SPEC\")\n                .help_heading(heading::PACKAGE_SELECTION)\n                .add(clap_complete::ArgValueCandidates::new(|| {\n                    get_ws_member_candidates()\n                })),\n        )\n    }\n\n    fn arg_parallel(self) -> Self {\n        self.arg_jobs()._arg(\n            flag(\n                \"keep-going\",\n                \"Do not abort the build as soon as there is an error\",\n            )\n            .help_heading(heading::COMPILATION_OPTIONS),\n        )\n    }\n\n    fn arg_jobs(self) -> Self {\n        self._arg(\n            opt(\"jobs\", \"Number of parallel jobs, defaults to # of CPUs.\")\n                .short('j')\n                .value_name(\"N\")\n                .allow_hyphen_values(true)\n                .help_heading(heading::COMPILATION_OPTIONS),\n        )\n    }\n\n    fn arg_unsupported_keep_going(self) -> Self {\n        let msg = \"use `--no-fail-fast` to run as many tests as possible regardless of failure\";\n        let value_parser = UnknownArgumentValueParser::suggest(msg);\n        self._arg(flag(\"keep-going\", \"\").value_parser(value_parser).hide(true))\n    }\n\n    fn arg_redundant_default_mode(\n        self,\n        default_mode: &'static str,\n        command: &'static str,\n        supported_mode: &'static str,\n    ) -> Self {\n        let msg = format!(\n            \"`--{default_mode}` is the default for `cargo {command}`; instead `--{supported_mode}` is supported\"\n        );\n        let value_parser = UnknownArgumentValueParser::suggest(msg);\n        self._arg(\n            flag(default_mode, \"\")\n                .conflicts_with(\"profile\")\n                .value_parser(value_parser)\n                .hide(true),\n        )\n    }\n\n    fn arg_targets_all(\n        self,\n        lib: &'static str,\n        bin: &'static str,\n        bins: &'static str,\n        example: &'static str,\n        examples: &'static str,\n        test: &'static str,\n        tests: &'static str,\n        bench: &'static str,\n        benches: &'static str,\n        all: &'static str,\n    ) -> Self {\n        self.arg_targets_lib_bin_example(lib, bin, bins, example, examples)\n            ._arg(flag(\"tests\", tests).help_heading(heading::TARGET_SELECTION))\n            ._arg(\n                optional_multi_opt(\"test\", \"NAME\", test)\n                    .help_heading(heading::TARGET_SELECTION)\n                    .add(clap_complete::ArgValueCandidates::new(|| {\n                        get_crate_candidates(TargetKind::Test).unwrap_or_default()\n                    })),\n            )\n            ._arg(flag(\"benches\", benches).help_heading(heading::TARGET_SELECTION))\n            ._arg(\n                optional_multi_opt(\"bench\", \"NAME\", bench)\n                    .help_heading(heading::TARGET_SELECTION)\n                    .add(clap_complete::ArgValueCandidates::new(|| {\n                        get_crate_candidates(TargetKind::Bench).unwrap_or_default()\n                    })),\n            )\n            ._arg(flag(\"all-targets\", all).help_heading(heading::TARGET_SELECTION))\n    }\n\n    fn arg_targets_lib_bin_example(\n        self,\n        lib: &'static str,\n        bin: &'static str,\n        bins: &'static str,\n        example: &'static str,\n        examples: &'static str,\n    ) -> Self {\n        self._arg(flag(\"lib\", lib).help_heading(heading::TARGET_SELECTION))\n            ._arg(flag(\"bins\", bins).help_heading(heading::TARGET_SELECTION))\n            ._arg(\n                optional_multi_opt(\"bin\", \"NAME\", bin)\n                    .help_heading(heading::TARGET_SELECTION)\n                    .add(clap_complete::ArgValueCandidates::new(|| {\n                        get_crate_candidates(TargetKind::Bin).unwrap_or_default()\n                    })),\n            )\n            ._arg(flag(\"examples\", examples).help_heading(heading::TARGET_SELECTION))\n            ._arg(\n                optional_multi_opt(\"example\", \"NAME\", example)\n                    .help_heading(heading::TARGET_SELECTION)\n                    .add(clap_complete::ArgValueCandidates::new(|| {\n                        get_crate_candidates(TargetKind::ExampleBin).unwrap_or_default()\n                    })),\n            )\n    }\n\n    fn arg_targets_bins_examples(\n        self,\n        bin: &'static str,\n        bins: &'static str,\n        example: &'static str,\n        examples: &'static str,\n    ) -> Self {\n        self._arg(\n            optional_multi_opt(\"bin\", \"NAME\", bin)\n                .help_heading(heading::TARGET_SELECTION)\n                .add(clap_complete::ArgValueCandidates::new(|| {\n                    get_crate_candidates(TargetKind::Bin).unwrap_or_default()\n                })),\n        )\n        ._arg(flag(\"bins\", bins).help_heading(heading::TARGET_SELECTION))\n        ._arg(\n            optional_multi_opt(\"example\", \"NAME\", example)\n                .help_heading(heading::TARGET_SELECTION)\n                .add(clap_complete::ArgValueCandidates::new(|| {\n                    get_crate_candidates(TargetKind::ExampleBin).unwrap_or_default()\n                })),\n        )\n        ._arg(flag(\"examples\", examples).help_heading(heading::TARGET_SELECTION))\n    }\n\n    fn arg_targets_bin_example(self, bin: &'static str, example: &'static str) -> Self {\n        self._arg(\n            optional_multi_opt(\"bin\", \"NAME\", bin)\n                .help_heading(heading::TARGET_SELECTION)\n                .add(clap_complete::ArgValueCandidates::new(|| {\n                    get_crate_candidates(TargetKind::Bin).unwrap_or_default()\n                })),\n        )\n        ._arg(\n            optional_multi_opt(\"example\", \"NAME\", example)\n                .help_heading(heading::TARGET_SELECTION)\n                .add(clap_complete::ArgValueCandidates::new(|| {\n                    get_crate_candidates(TargetKind::ExampleBin).unwrap_or_default()\n                })),\n        )\n    }\n\n    fn arg_features(self) -> Self {\n        self._arg(\n            multi_opt(\n                \"features\",\n                \"FEATURES\",\n                \"Space or comma separated list of features to activate\",\n            )\n            .short('F')\n            .help_heading(heading::FEATURE_SELECTION)\n            .add(clap_complete::ArgValueCandidates::new(|| {\n                get_feature_candidates().unwrap_or_default()\n            })),\n        )\n        ._arg(\n            flag(\"all-features\", \"Activate all available features\")\n                .help_heading(heading::FEATURE_SELECTION),\n        )\n        ._arg(\n            flag(\n                \"no-default-features\",\n                \"Do not activate the `default` feature\",\n            )\n            .help_heading(heading::FEATURE_SELECTION),\n        )\n    }\n\n    fn arg_release(self, release: &'static str) -> Self {\n        self._arg(\n            flag(\"release\", release)\n                .short('r')\n                .conflicts_with(\"profile\")\n                .help_heading(heading::COMPILATION_OPTIONS),\n        )\n    }\n\n    fn arg_profile(self, profile: &'static str) -> Self {\n        self._arg(\n            opt(\"profile\", profile)\n                .value_name(\"PROFILE-NAME\")\n                .help_heading(heading::COMPILATION_OPTIONS)\n                .add(clap_complete::ArgValueCandidates::new(|| {\n                    let candidates = get_profile_candidates();\n                    candidates\n                })),\n        )\n    }\n\n    fn arg_doc(self, doc: &'static str) -> Self {\n        self._arg(flag(\"doc\", doc))\n    }\n\n    fn arg_target_triple(self, target: &'static str) -> Self {\n        self.arg_target_triple_with_candidates(target, ArgValueCandidates::new(get_target_triples))\n    }\n\n    fn arg_target_triple_with_candidates(\n        self,\n        target: &'static str,\n        target_completion: ArgValueCandidates,\n    ) -> Self {\n        let unsupported_short_arg = {\n            let value_parser = UnknownArgumentValueParser::suggest_arg(\"--target\");\n            Arg::new(\"unsupported-short-target-flag\")\n                .help(\"\")\n                .short('t')\n                .value_parser(value_parser)\n                .action(ArgAction::SetTrue)\n                .hide(true)\n        };\n        self._arg(\n            optional_multi_opt(\"target\", \"TRIPLE\", target)\n                .help_heading(heading::COMPILATION_OPTIONS)\n                .add(target_completion),\n        )\n        ._arg(unsupported_short_arg)\n    }\n\n    fn arg_target_dir(self) -> Self {\n        self._arg(\n            opt(\"target-dir\", \"Directory for all generated artifacts\")\n                .value_name(\"DIRECTORY\")\n                .help_heading(heading::COMPILATION_OPTIONS),\n        )\n    }\n\n    fn arg_manifest_path(self) -> Self {\n        // We use `--manifest-path` instead of `--path`.\n        let unsupported_path_arg = {\n            let value_parser = UnknownArgumentValueParser::suggest_arg(\"--manifest-path\");\n            flag(\"unsupported-path-flag\", \"\")\n                .long(\"path\")\n                .value_parser(value_parser)\n                .hide(true)\n        };\n        self.arg_manifest_path_without_unsupported_path_tip()\n            ._arg(unsupported_path_arg)\n    }\n\n    // `cargo add` has a `--path` flag to install a crate from a local path.\n    fn arg_manifest_path_without_unsupported_path_tip(self) -> Self {\n        self._arg(\n            opt(\"manifest-path\", \"Path to Cargo.toml\")\n                .value_name(\"PATH\")\n                .help_heading(heading::MANIFEST_OPTIONS)\n                .add(clap_complete::engine::ArgValueCompleter::new(\n                    clap_complete::engine::PathCompleter::any().filter(|path: &Path| {\n                        if path.file_name() == Some(OsStr::new(\"Cargo.toml\")) {\n                            return true;\n                        }\n                        if is_embedded(path) {\n                            return true;\n                        }\n                        false\n                    }),\n                )),\n        )\n    }\n\n    fn arg_message_format(self) -> Self {\n        self._arg(\n            multi_opt(\"message-format\", \"FMT\", \"Error format\")\n                .value_parser([\n                    \"human\",\n                    \"short\",\n                    \"json\",\n                    \"json-diagnostic-short\",\n                    \"json-diagnostic-rendered-ansi\",\n                    \"json-render-diagnostics\",\n                ])\n                .value_delimiter(',')\n                .ignore_case(true),\n        )\n    }\n\n    fn arg_unit_graph(self) -> Self {\n        self._arg(\n            flag(\"unit-graph\", \"Output build graph in JSON (unstable)\")\n                .help_heading(heading::COMPILATION_OPTIONS),\n        )\n    }\n\n    fn arg_new_opts(self) -> Self {\n        self._arg(\n            opt(\n                \"vcs\",\n                \"Initialize a new repository for the given version \\\n                 control system, overriding \\\n                 a global configuration.\",\n            )\n            .value_name(\"VCS\")\n            .value_parser([\"git\", \"hg\", \"pijul\", \"fossil\", \"none\"]),\n        )\n        ._arg(flag(\"bin\", \"Use a binary (application) template [default]\"))\n        ._arg(flag(\"lib\", \"Use a library template\"))\n        ._arg(\n            opt(\"edition\", \"Edition to set for the crate generated\")\n                .value_parser(Edition::CLI_VALUES)\n                .value_name(\"YEAR\"),\n        )\n        ._arg(\n            opt(\n                \"name\",\n                \"Set the resulting package name, defaults to the directory name\",\n            )\n            .value_name(\"NAME\"),\n        )\n    }\n\n    fn arg_registry(self, help: &'static str) -> Self {\n        self._arg(opt(\"registry\", help).value_name(\"REGISTRY\").add(\n            clap_complete::ArgValueCandidates::new(|| {\n                let candidates = get_registry_candidates();\n                candidates.unwrap_or_default()\n            }),\n        ))\n    }\n\n    fn arg_index(self, help: &'static str) -> Self {\n        // Always conflicts with `--registry`.\n        self._arg(\n            opt(\"index\", help)\n                .value_name(\"INDEX\")\n                .conflicts_with(\"registry\"),\n        )\n    }\n\n    fn arg_dry_run(self, dry_run: &'static str) -> Self {\n        self._arg(flag(\"dry-run\", dry_run).short('n'))\n    }\n\n    fn arg_ignore_rust_version(self) -> Self {\n        self.arg_ignore_rust_version_with_help(\"Ignore `rust-version` specification in packages\")\n    }\n\n    fn arg_ignore_rust_version_with_help(self, help: &'static str) -> Self {\n        self._arg(flag(\"ignore-rust-version\", help).help_heading(heading::MANIFEST_OPTIONS))\n    }\n\n    fn arg_future_incompat_report(self) -> Self {\n        self._arg(flag(\n            \"future-incompat-report\",\n            \"Outputs a future incompatibility report at the end of the build\",\n        ))\n    }\n\n    /// Adds a suggestion for the `--silent` or `-s` flags to use the\n    /// `--quiet` flag instead. This is to help with people familiar with\n    /// other tools that use `-s`.\n    ///\n    /// Every command should call this, unless it has its own `-s` short flag.\n    fn arg_silent_suggestion(self) -> Self {\n        let value_parser = UnknownArgumentValueParser::suggest_arg(\"--quiet\");\n        self._arg(\n            flag(\"silent\", \"\")\n                .short('s')\n                .value_parser(value_parser)\n                .hide(true),\n        )\n    }\n\n    fn arg_timings(self) -> Self {\n        self._arg(\n            flag(\n                \"timings\",\n                \"Output a build timing report at the end of the build\",\n            )\n            .help_heading(heading::COMPILATION_OPTIONS),\n        )\n    }\n\n    fn arg_artifact_dir(self) -> Self {\n        let unsupported_short_arg = {\n            let value_parser = UnknownArgumentValueParser::suggest_arg(\"--artifact-dir\");\n            Arg::new(\"unsupported-short-artifact-dir-flag\")\n                .help(\"\")\n                .short('O')\n                .value_parser(value_parser)\n                .action(ArgAction::SetTrue)\n                .hide(true)\n        };\n\n        self._arg(\n            opt(\n                \"artifact-dir\",\n                \"Copy final artifacts to this directory (unstable)\",\n            )\n            .value_name(\"PATH\")\n            .help_heading(heading::COMPILATION_OPTIONS),\n        )\n        ._arg(unsupported_short_arg)\n        ._arg({\n            let value_parser = UnknownArgumentValueParser::suggest_arg(\"--artifact-dir\");\n            Arg::new(\"unsupported-out-dir-flag\")\n                .help(\"\")\n                .long(\"out-dir\")\n                .value_name(\"PATH\")\n                .value_parser(value_parser)\n                .action(ArgAction::SetTrue)\n                .hide(true)\n        })\n    }\n\n    fn arg_compile_time_deps(self) -> Self {\n        self._arg(flag(\"compile-time-deps\", \"\").hide(true))\n    }\n}\n\nimpl CommandExt for Command {\n    fn _arg(self, arg: Arg) -> Self {\n        self.arg(arg)\n    }\n}\n\npub fn flag(name: &'static str, help: &'static str) -> Arg {\n    Arg::new(name)\n        .long(name)\n        .help(help)\n        .action(ArgAction::SetTrue)\n}\n\npub fn opt(name: &'static str, help: &'static str) -> Arg {\n    Arg::new(name).long(name).help(help).action(ArgAction::Set)\n}\n\npub fn optional_opt(name: &'static str, help: &'static str) -> Arg {\n    opt(name, help).num_args(0..=1)\n}\n\npub fn optional_multi_opt(name: &'static str, value_name: &'static str, help: &'static str) -> Arg {\n    opt(name, help)\n        .value_name(value_name)\n        .num_args(0..=1)\n        .action(ArgAction::Append)\n}\n\npub fn multi_opt(name: &'static str, value_name: &'static str, help: &'static str) -> Arg {\n    opt(name, help)\n        .value_name(value_name)\n        .action(ArgAction::Append)\n}\n\npub fn subcommand(name: &'static str) -> Command {\n    Command::new(name)\n}\n\n/// Determines whether or not to gate `--profile` as unstable when resolving it.\npub enum ProfileChecking {\n    /// `cargo rustc` historically has allowed \"test\", \"bench\", and \"check\". This\n    /// variant explicitly allows those.\n    LegacyRustc,\n    /// `cargo check` and `cargo fix` historically has allowed \"test\". This variant\n    /// explicitly allows that on stable.\n    LegacyTestOnly,\n    /// All other commands, which allow any valid custom named profile.\n    Custom,\n}\n\npub trait ArgMatchesExt {\n    fn value_of_u32(&self, name: &str) -> CargoResult<Option<u32>> {\n        let arg = match self._value_of(name) {\n            None => None,\n            Some(arg) => Some(arg.parse::<u32>().map_err(|_| {\n                clap::Error::raw(\n                    clap::error::ErrorKind::ValueValidation,\n                    format!(\"invalid value: could not parse `{}` as a number\", arg),\n                )\n            })?),\n        };\n        Ok(arg)\n    }\n\n    fn value_of_i32(&self, name: &str) -> CargoResult<Option<i32>> {\n        let arg = match self._value_of(name) {\n            None => None,\n            Some(arg) => Some(arg.parse::<i32>().map_err(|_| {\n                clap::Error::raw(\n                    clap::error::ErrorKind::ValueValidation,\n                    format!(\"invalid value: could not parse `{}` as a number\", arg),\n                )\n            })?),\n        };\n        Ok(arg)\n    }\n\n    /// Returns value of the `name` command-line argument as an absolute path\n    fn value_of_path(&self, name: &str, gctx: &GlobalContext) -> Option<PathBuf> {\n        self._value_of(name).map(|path| gctx.cwd().join(path))\n    }\n\n    fn root_manifest(&self, gctx: &GlobalContext) -> CargoResult<PathBuf> {\n        root_manifest(self._value_of(\"manifest-path\").map(Path::new), gctx)\n    }\n\n    #[tracing::instrument(skip_all)]\n    fn workspace<'a>(&self, gctx: &'a GlobalContext) -> CargoResult<Workspace<'a>> {\n        let root = self.root_manifest(gctx)?;\n        let mut ws = Workspace::new(&root, gctx)?;\n        ws.set_resolve_honors_rust_version(self.honor_rust_version());\n        if gctx.cli_unstable().avoid_dev_deps {\n            ws.set_require_optional_deps(false);\n        }\n        Ok(ws)\n    }\n\n    fn jobs(&self) -> CargoResult<Option<JobsConfig>> {\n        let arg = match self._value_of(\"jobs\") {\n            None => None,\n            Some(arg) => match arg.parse::<i32>() {\n                Ok(j) => Some(JobsConfig::Integer(j)),\n                Err(_) => Some(JobsConfig::String(arg.to_string())),\n            },\n        };\n\n        Ok(arg)\n    }\n\n    fn verbose(&self) -> u32 {\n        self._count(\"verbose\")\n    }\n\n    fn dry_run(&self) -> bool {\n        self.flag(\"dry-run\")\n    }\n\n    fn keep_going(&self) -> bool {\n        self.maybe_flag(\"keep-going\")\n    }\n\n    fn honor_rust_version(&self) -> Option<bool> {\n        self.flag(\"ignore-rust-version\").then_some(false)\n    }\n\n    fn targets(&self) -> CargoResult<Vec<String>> {\n        if self.is_present_with_zero_values(\"target\") {\n            let cmd = if is_rustup() {\n                \"rustup target list\"\n            } else {\n                \"rustc --print target-list\"\n            };\n            bail!(\n                \"\\\"--target\\\" takes a target architecture as an argument.\n\nRun `{cmd}` to see possible targets.\"\n            );\n        }\n        Ok(self._values_of(\"target\"))\n    }\n\n    fn get_profile_name(\n        &self,\n        default: &str,\n        profile_checking: ProfileChecking,\n    ) -> CargoResult<InternedString> {\n        let specified_profile = self._value_of(\"profile\");\n\n        // Check for allowed legacy names.\n        // This is an early exit, since it allows combination with `--release`.\n        match (specified_profile, profile_checking) {\n            // `cargo rustc` has legacy handling of these names\n            (Some(name @ (\"dev\" | \"test\" | \"bench\" | \"check\")), ProfileChecking::LegacyRustc)\n            // `cargo fix` and `cargo check` has legacy handling of this profile name\n            | (Some(name @ \"test\"), ProfileChecking::LegacyTestOnly) => {\n                return Ok(name.into());\n            }\n            _ => {}\n        }\n\n        let name = match (\n            self.maybe_flag(\"release\"),\n            self.maybe_flag(\"debug\"),\n            specified_profile,\n        ) {\n            (false, false, None) => default,\n            (true, _, None) => \"release\",\n            (_, true, None) => \"dev\",\n            // `doc` is separate from all the other reservations because\n            // [profile.doc] was historically allowed, but is deprecated and\n            // has no effect. To avoid potentially breaking projects, it is a\n            // warning in Cargo.toml, but since `--profile` is new, we can\n            // reject it completely here.\n            (_, _, Some(\"doc\")) => {\n                bail!(\"profile `doc` is reserved and not allowed to be explicitly specified\")\n            }\n            (_, _, Some(name)) => {\n                ProfileName::new(name)?;\n                name\n            }\n        };\n\n        Ok(name.into())\n    }\n\n    fn packages_from_flags(&self) -> CargoResult<Packages> {\n        Packages::from_flags(\n            // TODO Integrate into 'workspace'\n            self.flag(\"workspace\") || self.flag(\"all\"),\n            self._values_of(\"exclude\"),\n            self._values_of(\"package\"),\n        )\n    }\n\n    fn compile_options(\n        &self,\n        gctx: &GlobalContext,\n        intent: UserIntent,\n        workspace: Option<&Workspace<'_>>,\n        profile_checking: ProfileChecking,\n    ) -> CargoResult<CompileOptions> {\n        let spec = self.packages_from_flags()?;\n        let mut message_format = None;\n        let default_json = MessageFormat::Json {\n            short: false,\n            ansi: false,\n            render_diagnostics: false,\n        };\n        let two_kinds_of_msg_format_err = \"cannot specify two kinds of `message-format` arguments\";\n        for fmt in self._values_of(\"message-format\") {\n            for fmt in fmt.split(',') {\n                let fmt = fmt.to_ascii_lowercase();\n                match fmt.as_str() {\n                    \"json\" => {\n                        if message_format.is_some() {\n                            bail!(two_kinds_of_msg_format_err);\n                        }\n                        message_format = Some(default_json);\n                    }\n                    \"human\" => {\n                        if message_format.is_some() {\n                            bail!(two_kinds_of_msg_format_err);\n                        }\n                        message_format = Some(MessageFormat::Human);\n                    }\n                    \"short\" => {\n                        if message_format.is_some() {\n                            bail!(two_kinds_of_msg_format_err);\n                        }\n                        message_format = Some(MessageFormat::Short);\n                    }\n                    \"json-render-diagnostics\" => {\n                        if message_format.is_none() {\n                            message_format = Some(default_json);\n                        }\n                        match &mut message_format {\n                            Some(MessageFormat::Json {\n                                render_diagnostics, ..\n                            }) => *render_diagnostics = true,\n                            _ => bail!(two_kinds_of_msg_format_err),\n                        }\n                    }\n                    \"json-diagnostic-short\" => {\n                        if message_format.is_none() {\n                            message_format = Some(default_json);\n                        }\n                        match &mut message_format {\n                            Some(MessageFormat::Json { short, .. }) => *short = true,\n                            _ => bail!(two_kinds_of_msg_format_err),\n                        }\n                    }\n                    \"json-diagnostic-rendered-ansi\" => {\n                        if message_format.is_none() {\n                            message_format = Some(default_json);\n                        }\n                        match &mut message_format {\n                            Some(MessageFormat::Json { ansi, .. }) => *ansi = true,\n                            _ => bail!(two_kinds_of_msg_format_err),\n                        }\n                    }\n                    s => bail!(\"invalid message format specifier: `{}`\", s),\n                }\n            }\n        }\n\n        let mut build_config = BuildConfig::new(\n            gctx,\n            self.jobs()?,\n            self.keep_going(),\n            &self.targets()?,\n            intent,\n        )?;\n        build_config.message_format = message_format.unwrap_or(MessageFormat::Human);\n        build_config.requested_profile = self.get_profile_name(\"dev\", profile_checking)?;\n        build_config.unit_graph = self.flag(\"unit-graph\");\n        build_config.future_incompat_report = self.flag(\"future-incompat-report\");\n        build_config.compile_time_deps_only = self.flag(\"compile-time-deps\");\n        build_config.timing_report = self.flag(\"timings\");\n\n        if build_config.unit_graph {\n            gctx.cli_unstable()\n                .fail_if_stable_opt(\"--unit-graph\", 8002)?;\n        }\n        if build_config.compile_time_deps_only {\n            gctx.cli_unstable()\n                .fail_if_stable_opt(\"--compile-time-deps\", 14434)?;\n        }\n\n        let opts = CompileOptions {\n            build_config,\n            cli_features: self.cli_features()?,\n            spec,\n            filter: CompileFilter::from_raw_arguments(\n                self.flag(\"lib\"),\n                self._values_of(\"bin\"),\n                self.flag(\"bins\"),\n                self._values_of(\"test\"),\n                self.flag(\"tests\"),\n                self._values_of(\"example\"),\n                self.flag(\"examples\"),\n                self._values_of(\"bench\"),\n                self.flag(\"benches\"),\n                self.flag(\"all-targets\"),\n            ),\n            target_rustdoc_args: None,\n            target_rustc_args: None,\n            target_rustc_crate_types: None,\n            rustdoc_document_private_items: false,\n            honor_rust_version: self.honor_rust_version(),\n        };\n\n        if let Some(ws) = workspace {\n            self.check_optional_opts(ws, &opts)?;\n        } else if self.is_present_with_zero_values(\"package\") {\n            // As for cargo 0.50.0, this won't occur but if someone sneaks in\n            // we can still provide this informative message for them.\n            anyhow::bail!(\n                \"\\\"--package <SPEC>\\\" requires a SPEC format value, \\\n                which can be any package ID specifier in the dependency graph.\\n\\\n                Run `cargo help pkgid` for more information about SPEC format.\"\n            )\n        }\n\n        Ok(opts)\n    }\n\n    fn cli_features(&self) -> CargoResult<CliFeatures> {\n        CliFeatures::from_command_line(\n            &self._values_of(\"features\"),\n            self.flag(\"all-features\"),\n            !self.flag(\"no-default-features\"),\n        )\n    }\n\n    fn compile_options_for_single_package(\n        &self,\n        gctx: &GlobalContext,\n        intent: UserIntent,\n        workspace: Option<&Workspace<'_>>,\n        profile_checking: ProfileChecking,\n    ) -> CargoResult<CompileOptions> {\n        let mut compile_opts = self.compile_options(gctx, intent, workspace, profile_checking)?;\n        let spec = self._values_of(\"package\");\n        if spec.iter().any(restricted_names::is_glob_pattern) {\n            anyhow::bail!(\"glob patterns on package selection are not supported.\")\n        }\n        compile_opts.spec = Packages::Packages(spec);\n        Ok(compile_opts)\n    }\n\n    fn new_options(&self, gctx: &GlobalContext) -> CargoResult<NewOptions> {\n        let vcs = self._value_of(\"vcs\").map(|vcs| match vcs {\n            \"git\" => VersionControl::Git,\n            \"hg\" => VersionControl::Hg,\n            \"pijul\" => VersionControl::Pijul,\n            \"fossil\" => VersionControl::Fossil,\n            \"none\" => VersionControl::NoVcs,\n            vcs => panic!(\"Impossible vcs: {:?}\", vcs),\n        });\n        NewOptions::new(\n            vcs,\n            self.flag(\"bin\"),\n            self.flag(\"lib\"),\n            self.value_of_path(\"path\", gctx).unwrap(),\n            self._value_of(\"name\").map(|s| s.to_string()),\n            self._value_of(\"edition\").map(|s| s.to_string()),\n            self.registry(gctx)?,\n        )\n    }\n\n    fn registry_or_index(&self, gctx: &GlobalContext) -> CargoResult<Option<RegistryOrIndex>> {\n        let registry = self._value_of(\"registry\");\n        let index = self._value_of(\"index\");\n        let result = match (registry, index) {\n            (None, None) => gctx.default_registry()?.map(RegistryOrIndex::Registry),\n            (None, Some(i)) => Some(RegistryOrIndex::Index(i.into_url()?)),\n            (Some(r), None) => {\n                RegistryName::new(r)?;\n                Some(RegistryOrIndex::Registry(r.to_string()))\n            }\n            (Some(_), Some(_)) => {\n                // Should be guarded by clap\n                unreachable!(\"both `--index` and `--registry` should not be set at the same time\")\n            }\n        };\n        Ok(result)\n    }\n\n    fn registry(&self, gctx: &GlobalContext) -> CargoResult<Option<String>> {\n        match self._value_of(\"registry\").map(|s| s.to_string()) {\n            None => gctx.default_registry(),\n            Some(registry) => {\n                RegistryName::new(&registry)?;\n                Ok(Some(registry))\n            }\n        }\n    }\n\n    fn check_optional_opts(\n        &self,\n        workspace: &Workspace<'_>,\n        compile_opts: &CompileOptions,\n    ) -> CargoResult<()> {\n        if self.is_present_with_zero_values(\"package\") {\n            print_available_packages(workspace)?\n        }\n\n        if self.is_present_with_zero_values(\"example\") {\n            print_available_examples(workspace, compile_opts)?;\n        }\n\n        if self.is_present_with_zero_values(\"bin\") {\n            print_available_binaries(workspace, compile_opts)?;\n        }\n\n        if self.is_present_with_zero_values(\"bench\") {\n            print_available_benches(workspace, compile_opts)?;\n        }\n\n        if self.is_present_with_zero_values(\"test\") {\n            print_available_tests(workspace, compile_opts)?;\n        }\n\n        Ok(())\n    }\n\n    fn is_present_with_zero_values(&self, name: &str) -> bool {\n        self._contains(name) && self._value_of(name).is_none()\n    }\n\n    fn flag(&self, name: &str) -> bool;\n\n    fn maybe_flag(&self, name: &str) -> bool;\n\n    fn _value_of(&self, name: &str) -> Option<&str>;\n\n    fn _values_of(&self, name: &str) -> Vec<String>;\n\n    fn _value_of_os(&self, name: &str) -> Option<&OsStr>;\n\n    fn _values_of_os(&self, name: &str) -> Vec<OsString>;\n\n    fn _count(&self, name: &str) -> u32;\n\n    fn _contains(&self, name: &str) -> bool;\n}\n\nimpl<'a> ArgMatchesExt for ArgMatches {\n    fn flag(&self, name: &str) -> bool {\n        ignore_unknown(self.try_get_one::<bool>(name))\n            .copied()\n            .unwrap_or(false)\n    }\n\n    // This works around before an upstream fix in clap for `UnknownArgumentValueParser` accepting\n    // generics arguments. `flag()` cannot be used with `--keep-going` at this moment due to\n    // <https://github.com/clap-rs/clap/issues/5081>.\n    fn maybe_flag(&self, name: &str) -> bool {\n        self.try_get_one::<bool>(name)\n            .ok()\n            .flatten()\n            .copied()\n            .unwrap_or_default()\n    }\n\n    fn _value_of(&self, name: &str) -> Option<&str> {\n        ignore_unknown(self.try_get_one::<String>(name)).map(String::as_str)\n    }\n\n    fn _value_of_os(&self, name: &str) -> Option<&OsStr> {\n        ignore_unknown(self.try_get_one::<OsString>(name)).map(OsString::as_os_str)\n    }\n\n    fn _values_of(&self, name: &str) -> Vec<String> {\n        ignore_unknown(self.try_get_many::<String>(name))\n            .unwrap_or_default()\n            .cloned()\n            .collect()\n    }\n\n    fn _values_of_os(&self, name: &str) -> Vec<OsString> {\n        ignore_unknown(self.try_get_many::<OsString>(name))\n            .unwrap_or_default()\n            .cloned()\n            .collect()\n    }\n\n    fn _count(&self, name: &str) -> u32 {\n        *ignore_unknown(self.try_get_one::<u8>(name)).expect(\"defaulted by clap\") as u32\n    }\n\n    fn _contains(&self, name: &str) -> bool {\n        ignore_unknown(self.try_contains_id(name))\n    }\n}\n\npub fn values(args: &ArgMatches, name: &str) -> Vec<String> {\n    args._values_of(name)\n}\n\npub fn values_os(args: &ArgMatches, name: &str) -> Vec<OsString> {\n    args._values_of_os(name)\n}\n\npub fn root_manifest(manifest_path: Option<&Path>, gctx: &GlobalContext) -> CargoResult<PathBuf> {\n    if let Some(manifest_path) = manifest_path {\n        let path = gctx.cwd().join(manifest_path);\n        // In general, we try to avoid normalizing paths in Cargo,\n        // but in this particular case we need it to fix #3586.\n        let path = paths::normalize_path(&path);\n        if !path.exists() {\n            anyhow::bail!(\"manifest path `{}` does not exist\", manifest_path.display())\n        } else if path.is_dir() {\n            let child_path = path.join(\"Cargo.toml\");\n            let suggested_path = if child_path.exists() {\n                format!(\"\\nhelp: {} exists\", child_path.display())\n            } else {\n                \"\".to_string()\n            };\n            anyhow::bail!(\n                \"manifest path `{}` is a directory but expected a file{suggested_path}\",\n                manifest_path.display()\n            )\n        } else if !path.ends_with(\"Cargo.toml\") && !crate::util::toml::is_embedded(&path) {\n            if gctx.cli_unstable().script {\n                anyhow::bail!(\n                    \"the manifest-path must be a path to a Cargo.toml or script file: `{}`\",\n                    path.display()\n                )\n            } else {\n                anyhow::bail!(\n                    \"the manifest-path must be a path to a Cargo.toml file: `{}`\",\n                    path.display()\n                )\n            }\n        }\n        if crate::util::toml::is_embedded(&path) && !gctx.cli_unstable().script {\n            anyhow::bail!(\"embedded manifest `{}` requires `-Zscript`\", path.display())\n        }\n        Ok(path)\n    } else {\n        find_root_manifest_for_wd(gctx.cwd())\n    }\n}\n\npub fn get_registry_candidates() -> CargoResult<Vec<clap_complete::CompletionCandidate>> {\n    let gctx = new_gctx_for_completions()?;\n\n    if let Ok(Some(registries)) =\n        gctx.get::<Option<HashMap<String, HashMap<String, String>>>>(\"registries\")\n    {\n        Ok(registries\n            .keys()\n            .map(|name| clap_complete::CompletionCandidate::new(name.to_owned()))\n            .collect())\n    } else {\n        Ok(vec![])\n    }\n}\n\nfn get_profile_candidates() -> Vec<clap_complete::CompletionCandidate> {\n    match get_workspace_profile_candidates() {\n        Ok(candidates) if !candidates.is_empty() => candidates,\n        // fallback to default profile candidates\n        _ => default_profile_candidates(),\n    }\n}\n\nfn get_workspace_profile_candidates() -> CargoResult<Vec<clap_complete::CompletionCandidate>> {\n    let gctx = new_gctx_for_completions()?;\n    let ws = Workspace::new(&find_root_manifest_for_wd(gctx.cwd())?, &gctx)?;\n    let profiles = Profiles::new(&ws, \"dev\".into())?;\n\n    let mut candidates = Vec::new();\n    for name in profiles.profile_names() {\n        let Ok(profile_instance) = Profiles::new(&ws, name) else {\n            continue;\n        };\n        let base_profile = profile_instance.base_profile();\n\n        let mut description = String::from(if base_profile.opt_level.as_str() == \"0\" {\n            \"unoptimized\"\n        } else {\n            \"optimized\"\n        });\n\n        if base_profile.debuginfo.is_turned_on() {\n            description.push_str(\" + debuginfo\");\n        }\n\n        candidates\n            .push(clap_complete::CompletionCandidate::new(&name).help(Some(description.into())));\n    }\n\n    Ok(candidates)\n}\n\nfn default_profile_candidates() -> Vec<clap_complete::CompletionCandidate> {\n    vec![\n        clap_complete::CompletionCandidate::new(\"dev\").help(Some(\"unoptimized + debuginfo\".into())),\n        clap_complete::CompletionCandidate::new(\"release\").help(Some(\"optimized\".into())),\n        clap_complete::CompletionCandidate::new(\"test\")\n            .help(Some(\"unoptimized + debuginfo\".into())),\n        clap_complete::CompletionCandidate::new(\"bench\").help(Some(\"optimized\".into())),\n    ]\n}\n\nfn get_feature_candidates() -> CargoResult<Vec<clap_complete::CompletionCandidate>> {\n    let gctx = new_gctx_for_completions()?;\n\n    let ws = Workspace::new(&find_root_manifest_for_wd(gctx.cwd())?, &gctx)?;\n    let mut feature_candidates = Vec::new();\n\n    // Process all packages in the workspace\n    for package in ws.members() {\n        let package_name = package.name();\n\n        // Add direct features with package info\n        for feature_name in package.summary().features().keys() {\n            let order = if ws.current_opt().map(|p| p.name()) == Some(package_name) {\n                0\n            } else {\n                1\n            };\n            feature_candidates.push(\n                clap_complete::CompletionCandidate::new(feature_name)\n                    .display_order(Some(order))\n                    .help(Some(format!(\"from {}\", package_name).into())),\n            );\n        }\n    }\n\n    Ok(feature_candidates)\n}\n\nfn get_crate_candidates(kind: TargetKind) -> CargoResult<Vec<clap_complete::CompletionCandidate>> {\n    let gctx = new_gctx_for_completions()?;\n\n    let ws = Workspace::new(&find_root_manifest_for_wd(gctx.cwd())?, &gctx)?;\n\n    let targets = ws\n        .members()\n        .flat_map(|pkg| pkg.targets().into_iter().cloned().map(|t| (pkg.name(), t)))\n        .filter(|(_, target)| *target.kind() == kind)\n        .map(|(pkg_name, target)| {\n            let order = if ws.current_opt().map(|p| p.name()) == Some(pkg_name) {\n                0\n            } else {\n                1\n            };\n            clap_complete::CompletionCandidate::new(target.name())\n                .display_order(Some(order))\n                .help(Some(format!(\"from {}\", pkg_name).into()))\n        })\n        .collect::<Vec<_>>();\n\n    Ok(targets)\n}\n\nfn get_target_triples() -> Vec<clap_complete::CompletionCandidate> {\n    let mut candidates = Vec::new();\n\n    if let Ok(targets) = get_target_triples_from_rustup() {\n        candidates = targets;\n    }\n\n    if candidates.is_empty() {\n        if let Ok(targets) = get_target_triples_from_rustc() {\n            candidates = targets;\n        }\n    }\n\n    // Allow tab-completion for `host-tuple` as the desired target.\n    candidates.insert(\n        0,\n        clap_complete::CompletionCandidate::new(\"host-tuple\").help(Some(\n            concat!(\"alias for: \", env!(\"RUST_HOST_TARGET\")).into(),\n        )),\n    );\n\n    candidates\n}\n\npub fn get_target_triples_with_all() -> Vec<clap_complete::CompletionCandidate> {\n    let mut candidates = vec![\n        clap_complete::CompletionCandidate::new(\"all\").help(Some(\"Include all targets\".into())),\n    ];\n    candidates.extend(get_target_triples());\n    candidates\n}\n\nfn get_target_triples_from_rustup() -> CargoResult<Vec<clap_complete::CompletionCandidate>> {\n    let output = std::process::Command::new(\"rustup\")\n        .arg(\"target\")\n        .arg(\"list\")\n        .output()?;\n\n    if !output.status.success() {\n        return Ok(vec![]);\n    }\n\n    let stdout = String::from_utf8(output.stdout)?;\n\n    Ok(stdout\n        .lines()\n        .map(|line| {\n            let target = line.split_once(' ');\n            match target {\n                None => clap_complete::CompletionCandidate::new(line.to_owned()).hide(true),\n                Some((target, _installed)) => clap_complete::CompletionCandidate::new(target),\n            }\n        })\n        .collect())\n}\n\nfn get_target_triples_from_rustc() -> CargoResult<Vec<clap_complete::CompletionCandidate>> {\n    let gctx = new_gctx_for_completions()?;\n\n    let ws = Workspace::new(&find_root_manifest_for_wd(gctx.cwd())?, &gctx);\n\n    let rustc = gctx.load_global_rustc(ws.as_ref().ok())?;\n\n    let (stdout, _stderr) =\n        rustc.cached_output(rustc.process().arg(\"--print\").arg(\"target-list\"), 0)?;\n\n    Ok(stdout\n        .lines()\n        .map(|line| clap_complete::CompletionCandidate::new(line.to_owned()))\n        .collect())\n}\n\npub fn get_ws_member_candidates() -> Vec<clap_complete::CompletionCandidate> {\n    get_ws_member_packages()\n        .unwrap_or_default()\n        .into_iter()\n        .map(|pkg| {\n            clap_complete::CompletionCandidate::new(pkg.name().as_str()).help(\n                pkg.manifest()\n                    .metadata()\n                    .description\n                    .to_owned()\n                    .map(From::from),\n            )\n        })\n        .collect::<Vec<_>>()\n}\n\nfn get_ws_member_packages() -> CargoResult<Vec<Package>> {\n    let gctx = new_gctx_for_completions()?;\n    let ws = Workspace::new(&find_root_manifest_for_wd(gctx.cwd())?, &gctx)?;\n    let packages = ws.members().map(Clone::clone).collect::<Vec<_>>();\n    Ok(packages)\n}\n\npub fn get_pkg_id_spec_candidates() -> Vec<clap_complete::CompletionCandidate> {\n    let mut candidates = vec![];\n\n    let package_map = HashMap::<&str, Vec<Package>>::new();\n    let package_map =\n        get_packages()\n            .unwrap_or_default()\n            .into_iter()\n            .fold(package_map, |mut map, package| {\n                map.entry(package.name().as_str())\n                    .or_insert_with(Vec::new)\n                    .push(package);\n                map\n            });\n\n    let unique_name_candidates = package_map\n        .iter()\n        .filter(|(_name, packages)| packages.len() == 1)\n        .map(|(name, packages)| {\n            clap_complete::CompletionCandidate::new(name.to_string()).help(\n                packages[0]\n                    .manifest()\n                    .metadata()\n                    .description\n                    .to_owned()\n                    .map(From::from),\n            )\n        })\n        .collect::<Vec<_>>();\n\n    let duplicate_name_pairs = package_map\n        .iter()\n        .filter(|(_name, packages)| packages.len() > 1)\n        .collect::<Vec<_>>();\n\n    let mut duplicate_name_candidates = vec![];\n    for (name, packages) in duplicate_name_pairs {\n        let mut version_count: HashMap<&Version, usize> = HashMap::new();\n\n        for package in packages {\n            *version_count.entry(package.version()).or_insert(0) += 1;\n        }\n\n        for package in packages {\n            if let Some(&count) = version_count.get(package.version()) {\n                if count == 1 {\n                    duplicate_name_candidates.push(\n                        clap_complete::CompletionCandidate::new(format!(\n                            \"{}@{}\",\n                            name,\n                            package.version()\n                        ))\n                        .help(\n                            package\n                                .manifest()\n                                .metadata()\n                                .description\n                                .to_owned()\n                                .map(From::from),\n                        ),\n                    );\n                } else {\n                    duplicate_name_candidates.push(\n                        clap_complete::CompletionCandidate::new(format!(\n                            \"{}\",\n                            package.package_id().to_spec()\n                        ))\n                        .help(\n                            package\n                                .manifest()\n                                .metadata()\n                                .description\n                                .to_owned()\n                                .map(From::from),\n                        ),\n                    )\n                }\n            }\n        }\n    }\n\n    candidates.extend(unique_name_candidates);\n    candidates.extend(duplicate_name_candidates);\n\n    candidates\n}\n\npub fn get_pkg_name_candidates() -> Vec<clap_complete::CompletionCandidate> {\n    let packages: BTreeMap<_, _> = get_packages()\n        .unwrap_or_default()\n        .into_iter()\n        .map(|package| {\n            (\n                package.name(),\n                package.manifest().metadata().description.clone(),\n            )\n        })\n        .collect();\n\n    packages\n        .into_iter()\n        .map(|(name, description)| {\n            clap_complete::CompletionCandidate::new(name.as_str()).help(description.map(From::from))\n        })\n        .collect()\n}\n\nfn get_packages() -> CargoResult<Vec<Package>> {\n    let gctx = new_gctx_for_completions()?;\n\n    let ws = Workspace::new(&find_root_manifest_for_wd(gctx.cwd())?, &gctx)?;\n\n    let requested_kinds = CompileKind::from_requested_targets(ws.gctx(), &[])?;\n    let mut target_data = RustcTargetData::new(&ws, &requested_kinds)?;\n    // `cli_features.all_features` must be true in case that `specs` is empty.\n    let cli_features = CliFeatures::new_all(true);\n    let has_dev_units = HasDevUnits::Yes;\n    let force_all_targets = ForceAllTargets::No;\n    let dry_run = true;\n\n    let ws_resolve = ops::resolve_ws_with_opts(\n        &ws,\n        &mut target_data,\n        &requested_kinds,\n        &cli_features,\n        &[],\n        has_dev_units,\n        force_all_targets,\n        dry_run,\n    )?;\n\n    let packages = ws_resolve\n        .pkg_set\n        .packages()\n        .map(Clone::clone)\n        .collect::<Vec<_>>();\n\n    Ok(packages)\n}\n\npub fn get_direct_dependencies_pkg_name_candidates() -> Vec<clap_complete::CompletionCandidate> {\n    let (current_package_deps, all_package_deps) = match get_dependencies_from_metadata() {\n        Ok(v) => v,\n        Err(_) => return Vec::new(),\n    };\n\n    let current_package_deps_package_names = current_package_deps\n        .into_iter()\n        .map(|dep| dep.package_name().to_string())\n        .sorted();\n    let all_package_deps_package_names = all_package_deps\n        .into_iter()\n        .map(|dep| dep.package_name().to_string())\n        .sorted();\n\n    let mut package_names_set = IndexSet::new();\n    package_names_set.extend(current_package_deps_package_names);\n    package_names_set.extend(all_package_deps_package_names);\n\n    package_names_set\n        .into_iter()\n        .map(|name| name.into())\n        .collect_vec()\n}\n\nfn get_dependencies_from_metadata() -> CargoResult<(Vec<Dependency>, Vec<Dependency>)> {\n    let cwd = std::env::current_dir()?;\n    let gctx = GlobalContext::new(shell::Shell::new(), cwd.clone(), cargo_home_with_cwd(&cwd)?);\n    let ws = Workspace::new(&find_root_manifest_for_wd(&cwd)?, &gctx)?;\n    let current_package = ws.current().ok();\n\n    let current_package_dependencies = ws\n        .current()\n        .map(|current| current.dependencies())\n        .unwrap_or_default()\n        .to_vec();\n    let all_other_packages_dependencies = ws\n        .members()\n        .filter(|&member| Some(member) != current_package)\n        .flat_map(|pkg| pkg.dependencies().into_iter().cloned())\n        .collect::<HashSet<_>>()\n        .into_iter()\n        .collect::<Vec<_>>();\n\n    Ok((\n        current_package_dependencies,\n        all_other_packages_dependencies,\n    ))\n}\n\npub fn new_gctx_for_completions() -> CargoResult<GlobalContext> {\n    let cwd = std::env::current_dir()?;\n    let mut gctx = GlobalContext::new(shell::Shell::new(), cwd.clone(), cargo_home_with_cwd(&cwd)?);\n\n    let verbose = 0;\n    let quiet = true;\n    let color = None;\n    let frozen = false;\n    let locked = true;\n    let offline = false;\n    let target_dir = None;\n    let unstable_flags = &[];\n    let cli_config = &[];\n\n    gctx.configure(\n        verbose,\n        quiet,\n        color,\n        frozen,\n        locked,\n        offline,\n        &target_dir,\n        unstable_flags,\n        cli_config,\n    )?;\n\n    Ok(gctx)\n}\n\n#[track_caller]\npub fn ignore_unknown<T: Default>(r: Result<T, clap::parser::MatchesError>) -> T {\n    match r {\n        Ok(t) => t,\n        Err(clap::parser::MatchesError::UnknownArgument { .. }) => Default::default(),\n        Err(e) => {\n            panic!(\"Mismatch between definition and access: {}\", e);\n        }\n    }\n}\n\n#[derive(PartialEq, Eq, PartialOrd, Ord)]\npub enum CommandInfo {\n    BuiltIn { about: Option<String> },\n    External { path: PathBuf },\n    Alias { target: StringOrVec },\n}\n"
  },
  {
    "path": "src/cargo/util/context/config_value.rs",
    "content": "//! [`ConfigValue`] represents Cargo configuration values loaded from TOML.\n//!\n//! See [the module-level doc](crate::util::context)\n//! for how configuration is parsed and deserialized.\n\nuse std::collections::HashMap;\nuse std::collections::hash_map::Entry;\nuse std::fmt;\nuse std::mem;\n\nuse anyhow::Context as _;\nuse anyhow::anyhow;\nuse anyhow::bail;\n\nuse super::ConfigKey;\nuse super::Definition;\nuse super::key;\nuse super::key::KeyOrIdx;\nuse crate::CargoResult;\n\nuse self::ConfigValue as CV;\n\n/// List of which configuration lists cannot be merged.\n///\n/// Instead of merging,\n/// the higher priority list should replaces the lower priority list.\n///\n/// ## What kind of config is non-mergeable\n///\n/// The rule of thumb is that if a config is a path of a program,\n/// it should be added to this list.\nconst NON_MERGEABLE_LISTS: &[&str] = &[\n    \"credential-alias.*\",\n    \"doc.browser\",\n    \"host.runner\",\n    \"registries.*.credential-provider\",\n    \"registry.credential-provider\",\n    \"target.*.runner\",\n];\n\n/// Similar to [`toml::Value`] but includes the source location where it is defined.\n#[derive(Eq, PartialEq, Clone)]\npub enum ConfigValue {\n    Integer(i64, Definition),\n    String(String, Definition),\n    List(Vec<ConfigValue>, Definition),\n    Table(HashMap<String, ConfigValue>, Definition),\n    Boolean(bool, Definition),\n}\n\nimpl fmt::Debug for ConfigValue {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            CV::Integer(i, def) => write!(f, \"{} (from {})\", i, def),\n            CV::Boolean(b, def) => write!(f, \"{} (from {})\", b, def),\n            CV::String(s, def) => write!(f, \"{} (from {})\", s, def),\n            CV::List(list, def) => {\n                write!(f, \"[\")?;\n                for (i, item) in list.iter().enumerate() {\n                    if i > 0 {\n                        write!(f, \", \")?;\n                    }\n                    write!(f, \"{item:?}\")?;\n                }\n                write!(f, \"] (from {})\", def)\n            }\n            CV::Table(table, _) => write!(f, \"{:?}\", table),\n        }\n    }\n}\n\nimpl ConfigValue {\n    pub(super) fn from_toml(def: Definition, toml: toml::Value) -> CargoResult<ConfigValue> {\n        let mut error_path = Vec::new();\n        Self::from_toml_inner(def, toml, &mut error_path).with_context(|| {\n            let mut it = error_path.iter().rev().peekable();\n            let mut key_path = String::with_capacity(error_path.len() * 3);\n            while let Some(k) = it.next() {\n                match k {\n                    KeyOrIdx::Key(s) => key_path.push_str(&key::escape_key_part(&s)),\n                    KeyOrIdx::Idx(i) => key_path.push_str(&format!(\"[{i}]\")),\n                }\n                if matches!(it.peek(), Some(KeyOrIdx::Key(_))) {\n                    key_path.push('.');\n                }\n            }\n            format!(\"failed to parse config at `{key_path}`\")\n        })\n    }\n\n    fn from_toml_inner(\n        def: Definition,\n        toml: toml::Value,\n        path: &mut Vec<KeyOrIdx>,\n    ) -> CargoResult<ConfigValue> {\n        match toml {\n            toml::Value::String(val) => Ok(CV::String(val, def)),\n            toml::Value::Boolean(b) => Ok(CV::Boolean(b, def)),\n            toml::Value::Integer(i) => Ok(CV::Integer(i, def)),\n            toml::Value::Array(val) => Ok(CV::List(\n                val.into_iter()\n                    .enumerate()\n                    .map(|(i, toml)| {\n                        CV::from_toml_inner(def.clone(), toml, path)\n                            .inspect_err(|_| path.push(KeyOrIdx::Idx(i)))\n                    })\n                    .collect::<CargoResult<_>>()?,\n                def,\n            )),\n            toml::Value::Table(val) => Ok(CV::Table(\n                val.into_iter()\n                    .map(\n                        |(key, value)| match CV::from_toml_inner(def.clone(), value, path) {\n                            Ok(value) => Ok((key, value)),\n                            Err(e) => {\n                                path.push(KeyOrIdx::Key(key));\n                                Err(e)\n                            }\n                        },\n                    )\n                    .collect::<CargoResult<_>>()?,\n                def,\n            )),\n            v => bail!(\"unsupported TOML configuration type `{}`\", v.type_str()),\n        }\n    }\n\n    pub(super) fn into_toml(self) -> toml::Value {\n        match self {\n            CV::Boolean(s, _) => toml::Value::Boolean(s),\n            CV::String(s, _) => toml::Value::String(s),\n            CV::Integer(i, _) => toml::Value::Integer(i),\n            CV::List(l, _) => toml::Value::Array(l.into_iter().map(|cv| cv.into_toml()).collect()),\n            CV::Table(l, _) => {\n                toml::Value::Table(l.into_iter().map(|(k, v)| (k, v.into_toml())).collect())\n            }\n        }\n    }\n\n    /// Merge the given value into self.\n    ///\n    /// If `force` is true, primitive (non-container) types will override existing values\n    /// of equal priority. For arrays, incoming values of equal priority will be placed later.\n    ///\n    /// Container types (tables and arrays) are merged with existing values.\n    ///\n    /// Container and non-container types cannot be mixed.\n    pub(super) fn merge(&mut self, from: ConfigValue, force: bool) -> CargoResult<()> {\n        self.merge_helper(from, force, &mut ConfigKey::new())\n    }\n\n    fn merge_helper(\n        &mut self,\n        from: ConfigValue,\n        force: bool,\n        parts: &mut ConfigKey,\n    ) -> CargoResult<()> {\n        let is_higher_priority = from.definition().is_higher_priority(self.definition());\n        match (self, from) {\n            (&mut CV::List(ref mut old, _), CV::List(ref mut new, _)) => {\n                if is_nonmergeable_list(&parts) {\n                    // Use whichever list is higher priority.\n                    if force || is_higher_priority {\n                        mem::swap(new, old);\n                    }\n                } else {\n                    // Merge the lists together.\n                    if force {\n                        old.append(new);\n                    } else {\n                        new.append(old);\n                        mem::swap(new, old);\n                    }\n                }\n                old.sort_by(|a, b| a.definition().cmp(b.definition()));\n            }\n            (&mut CV::Table(ref mut old, _), CV::Table(ref mut new, _)) => {\n                for (key, value) in mem::take(new) {\n                    match old.entry(key.clone()) {\n                        Entry::Occupied(mut entry) => {\n                            let new_def = value.definition().clone();\n                            let entry = entry.get_mut();\n                            parts.push(&key);\n                            entry.merge_helper(value, force, parts).with_context(|| {\n                                format!(\n                                    \"failed to merge key `{}` between \\\n                                     {} and {}\",\n                                    key,\n                                    entry.definition(),\n                                    new_def,\n                                )\n                            })?;\n                        }\n                        Entry::Vacant(entry) => {\n                            entry.insert(value);\n                        }\n                    };\n                }\n            }\n            // Allow switching types except for tables or arrays.\n            (expected @ &mut CV::List(_, _), found)\n            | (expected @ &mut CV::Table(_, _), found)\n            | (expected, found @ CV::List(_, _))\n            | (expected, found @ CV::Table(_, _)) => {\n                return Err(anyhow!(\n                    \"failed to merge config value from `{}` into `{}`: expected {}, but found {}\",\n                    found.definition(),\n                    expected.definition(),\n                    expected.desc(),\n                    found.desc()\n                ));\n            }\n            (old, mut new) => {\n                if force || is_higher_priority {\n                    mem::swap(old, &mut new);\n                }\n            }\n        }\n\n        Ok(())\n    }\n\n    pub fn i64(&self, key: &str) -> CargoResult<(i64, &Definition)> {\n        match self {\n            CV::Integer(i, def) => Ok((*i, def)),\n            _ => self.expected(\"integer\", key),\n        }\n    }\n\n    pub fn string(&self, key: &str) -> CargoResult<(&str, &Definition)> {\n        match self {\n            CV::String(s, def) => Ok((s, def)),\n            _ => self.expected(\"string\", key),\n        }\n    }\n\n    pub fn table(&self, key: &str) -> CargoResult<(&HashMap<String, ConfigValue>, &Definition)> {\n        match self {\n            CV::Table(table, def) => Ok((table, def)),\n            _ => self.expected(\"table\", key),\n        }\n    }\n\n    pub fn table_mut(\n        &mut self,\n        key: &str,\n    ) -> CargoResult<(&mut HashMap<String, ConfigValue>, &mut Definition)> {\n        match self {\n            CV::Table(table, def) => Ok((table, def)),\n            _ => self.expected(\"table\", key),\n        }\n    }\n\n    pub fn is_table(&self) -> bool {\n        matches!(self, CV::Table(..))\n    }\n\n    pub fn string_list(&self, key: &str) -> CargoResult<Vec<(String, Definition)>> {\n        match self {\n            CV::List(list, _) => list\n                .iter()\n                .map(|cv| match cv {\n                    CV::String(s, def) => Ok((s.clone(), def.clone())),\n                    _ => self.expected(\"string\", key),\n                })\n                .collect::<CargoResult<_>>(),\n            _ => self.expected(\"list\", key),\n        }\n    }\n\n    pub fn boolean(&self, key: &str) -> CargoResult<(bool, &Definition)> {\n        match self {\n            CV::Boolean(b, def) => Ok((*b, def)),\n            _ => self.expected(\"bool\", key),\n        }\n    }\n\n    pub fn desc(&self) -> &'static str {\n        match *self {\n            CV::Table(..) => \"table\",\n            CV::List(..) => \"array\",\n            CV::String(..) => \"string\",\n            CV::Boolean(..) => \"boolean\",\n            CV::Integer(..) => \"integer\",\n        }\n    }\n\n    pub fn definition(&self) -> &Definition {\n        match self {\n            CV::Boolean(_, def)\n            | CV::Integer(_, def)\n            | CV::String(_, def)\n            | CV::List(_, def)\n            | CV::Table(_, def) => def,\n        }\n    }\n\n    pub(super) fn expected<T>(&self, wanted: &str, key: &str) -> CargoResult<T> {\n        bail!(\n            \"expected a {}, but found a {} for `{}` in {}\",\n            wanted,\n            self.desc(),\n            key,\n            self.definition()\n        )\n    }\n}\n\npub(super) fn is_nonmergeable_list(key: &ConfigKey) -> bool {\n    NON_MERGEABLE_LISTS.iter().any(|l| key.matches(l))\n}\n"
  },
  {
    "path": "src/cargo/util/context/de.rs",
    "content": "//! Deserialization for converting [`ConfigValue`] instances to target types.\n//!\n//! The [`Deserializer`] type is the main driver of deserialization.\n//! The workflow is roughly:\n//!\n//! 1. [`GlobalContext::get<T>()`] creates [`Deserializer`] and calls `T::deserialize()`\n//! 2. Then call type-specific deserialize methods as in normal serde deserialization.\n//!     - For primitives, `deserialize_*` methods look up [`ConfigValue`] instances\n//!       in [`GlobalContext`] and convert.\n//!     - Structs and maps are handled by [`ConfigMapAccess`].\n//!     - Sequences are handled by [`ConfigSeqAccess`],\n//!       which later uses [`ArrayItemDeserializer`] for each array item.\n//!     - [`Value<T>`] is delegated to [`ValueDeserializer`] in `deserialize_struct`.\n//!\n//! The purpose of this workflow is to:\n//!\n//! - Retrieve the correct config value based on source location precedence\n//! - Provide richer error context showing where a config is defined\n//! - Provide a richer internal API to map to concrete config types\n//!   without touching underlying [`ConfigValue`] directly\n//!\n//! [`ConfigValue`]: CV\n\nuse crate::util::context::key::ArrayItemKeyPath;\nuse crate::util::context::value;\nuse crate::util::context::{ConfigError, ConfigKey, GlobalContext};\nuse crate::util::context::{ConfigValue as CV, Definition, Value};\nuse serde::{de, de::IntoDeserializer};\nuse std::collections::HashSet;\nuse std::vec;\n\n/// Serde deserializer used to convert config values to a target type using\n/// [`GlobalContext::get`].\n#[derive(Clone)]\npub(super) struct Deserializer<'gctx> {\n    pub(super) gctx: &'gctx GlobalContext,\n    /// The current key being deserialized.\n    pub(super) key: ConfigKey,\n    /// Whether or not this key part is allowed to be an inner table. For\n    /// example, `profile.dev.build-override` needs to check if\n    /// `CARGO_PROFILE_DEV_BUILD_OVERRIDE_` prefixes exist. But\n    /// `CARGO_BUILD_TARGET` should not check for prefixes because it would\n    /// collide with `CARGO_BUILD_TARGET_DIR`. See `ConfigMapAccess` for\n    /// details.\n    pub(super) env_prefix_ok: bool,\n}\n\nmacro_rules! deserialize_method {\n    ($method:ident, $visit:ident, $getter:ident) => {\n        fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>\n        where\n            V: de::Visitor<'de>,\n        {\n            let v = self\n                .gctx\n                .$getter(&self.key)?\n                .ok_or_else(|| ConfigError::missing(&self.key))?;\n            let Value { val, definition } = v;\n            let res: Result<V::Value, ConfigError> = visitor.$visit(val);\n            res.map_err(|e| e.with_key_context(&self.key, Some(definition)))\n        }\n    };\n}\n\nimpl<'de, 'gctx> de::Deserializer<'de> for Deserializer<'gctx> {\n    type Error = ConfigError;\n\n    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>\n    where\n        V: de::Visitor<'de>,\n    {\n        let cv = self.gctx.get_cv_with_env(&self.key)?;\n        if let Some(cv) = cv {\n            let res: (Result<V::Value, ConfigError>, Definition) = match cv {\n                CV::Integer(i, def) => (visitor.visit_i64(i), def),\n                CV::String(s, def) => (visitor.visit_string(s), def),\n                CV::List(_, def) => (visitor.visit_seq(ConfigSeqAccess::new(self.clone())?), def),\n                CV::Table(_, def) => (\n                    visitor.visit_map(ConfigMapAccess::new_map(self.clone())?),\n                    def,\n                ),\n                CV::Boolean(b, def) => (visitor.visit_bool(b), def),\n            };\n            let (res, def) = res;\n            return res.map_err(|e| e.with_key_context(&self.key, Some(def)));\n        }\n\n        // The effect here is the same as in `deserialize_option`.\n        if self.gctx.has_key(&self.key, self.env_prefix_ok)? {\n            return visitor.visit_some(self);\n        }\n\n        Err(ConfigError::missing(&self.key))\n    }\n\n    deserialize_method!(deserialize_bool, visit_bool, get_bool);\n    deserialize_method!(deserialize_i8, visit_i64, get_integer);\n    deserialize_method!(deserialize_i16, visit_i64, get_integer);\n    deserialize_method!(deserialize_i32, visit_i64, get_integer);\n    deserialize_method!(deserialize_i64, visit_i64, get_integer);\n    deserialize_method!(deserialize_u8, visit_i64, get_integer);\n    deserialize_method!(deserialize_u16, visit_i64, get_integer);\n    deserialize_method!(deserialize_u32, visit_i64, get_integer);\n    deserialize_method!(deserialize_u64, visit_i64, get_integer);\n    deserialize_method!(deserialize_string, visit_string, get_string_priv);\n\n    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>\n    where\n        V: de::Visitor<'de>,\n    {\n        if self.gctx.has_key(&self.key, self.env_prefix_ok)? {\n            visitor.visit_some(self)\n        } else {\n            // Treat missing values as `None`.\n            visitor.visit_none()\n        }\n    }\n\n    fn deserialize_struct<V>(\n        self,\n        name: &'static str,\n        fields: &'static [&'static str],\n        visitor: V,\n    ) -> Result<V::Value, Self::Error>\n    where\n        V: de::Visitor<'de>,\n    {\n        // Match on the magical struct name/field names that are passed in to\n        // detect when we're deserializing `Value<T>`.\n        //\n        // See more comments in `value.rs` for the protocol used here.\n        if name == value::NAME && fields == value::FIELDS {\n            let source = ValueSource::with_deserializer(self)?;\n            return visitor.visit_map(ValueDeserializer::new(source));\n        }\n        visitor.visit_map(ConfigMapAccess::new_struct(self, fields)?)\n    }\n\n    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>\n    where\n        V: de::Visitor<'de>,\n    {\n        visitor.visit_map(ConfigMapAccess::new_map(self)?)\n    }\n\n    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>\n    where\n        V: de::Visitor<'de>,\n    {\n        visitor.visit_seq(ConfigSeqAccess::new(self)?)\n    }\n\n    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>\n    where\n        V: de::Visitor<'de>,\n    {\n        visitor.visit_seq(ConfigSeqAccess::new(self)?)\n    }\n\n    fn deserialize_tuple_struct<V>(\n        self,\n        _name: &'static str,\n        _len: usize,\n        visitor: V,\n    ) -> Result<V::Value, Self::Error>\n    where\n        V: de::Visitor<'de>,\n    {\n        visitor.visit_seq(ConfigSeqAccess::new(self)?)\n    }\n\n    fn deserialize_newtype_struct<V>(\n        self,\n        name: &'static str,\n        visitor: V,\n    ) -> Result<V::Value, Self::Error>\n    where\n        V: de::Visitor<'de>,\n    {\n        if name == \"StringList\" {\n            let mut res = Vec::new();\n\n            match self.gctx.get_cv(&self.key)? {\n                Some(CV::List(val, _def)) => res.extend(val),\n                Some(CV::String(val, def)) => {\n                    let split_vs = val\n                        .split_whitespace()\n                        .map(|s| CV::String(s.to_string(), def.clone()));\n                    res.extend(split_vs);\n                }\n                Some(val) => {\n                    self.gctx\n                        .expected(\"string or array of strings\", &self.key, &val)?;\n                }\n                None => {}\n            }\n\n            self.gctx.get_env_list(&self.key, &mut res)?;\n\n            let vals: Vec<String> = res\n                .into_iter()\n                .map(|val| match val {\n                    CV::String(s, _definition) => Ok(s),\n                    other => Err(ConfigError::expected(&self.key, \"string\", &other)),\n                })\n                .collect::<Result<_, _>>()?;\n            visitor.visit_newtype_struct(vals.into_deserializer())\n        } else {\n            visitor.visit_newtype_struct(self)\n        }\n    }\n\n    fn deserialize_enum<V>(\n        self,\n        _name: &'static str,\n        _variants: &'static [&'static str],\n        visitor: V,\n    ) -> Result<V::Value, Self::Error>\n    where\n        V: de::Visitor<'de>,\n    {\n        let value = self\n            .gctx\n            .get_string_priv(&self.key)?\n            .ok_or_else(|| ConfigError::missing(&self.key))?;\n\n        let Value { val, definition } = value;\n        visitor\n            .visit_enum(val.into_deserializer())\n            .map_err(|e: ConfigError| e.with_key_context(&self.key, Some(definition)))\n    }\n\n    // These aren't really supported, yet.\n    serde::forward_to_deserialize_any! {\n        f32 f64 char str bytes\n        byte_buf unit unit_struct\n        identifier ignored_any\n    }\n}\n\nstruct ConfigMapAccess<'gctx> {\n    de: Deserializer<'gctx>,\n    /// The fields that this map should deserialize.\n    fields: Vec<KeyKind>,\n    /// Current field being deserialized.\n    field_index: usize,\n}\n\n#[derive(Debug, PartialEq, Eq, Hash)]\nenum KeyKind {\n    Normal(String),\n    CaseSensitive(String),\n}\n\nimpl<'gctx> ConfigMapAccess<'gctx> {\n    fn new_map(de: Deserializer<'gctx>) -> Result<ConfigMapAccess<'gctx>, ConfigError> {\n        let mut fields = Vec::new();\n        if let Some(mut v) = de.gctx.get_table(&de.key)? {\n            // `v: Value<HashMap<String, CV>>`\n            for (key, _value) in v.val.drain() {\n                fields.push(KeyKind::CaseSensitive(key));\n            }\n        }\n        if de.gctx.cli_unstable().advanced_env {\n            // `CARGO_PROFILE_DEV_PACKAGE_`\n            let env_prefix = format!(\"{}_\", de.key.as_env_key());\n            for env_key in de.gctx.env_keys() {\n                // `CARGO_PROFILE_DEV_PACKAGE_bar_OPT_LEVEL = 3`\n                if let Some(rest) = env_key.strip_prefix(&env_prefix) {\n                    // `rest = bar_OPT_LEVEL`\n                    let part = rest.splitn(2, '_').next().unwrap();\n                    // `part = \"bar\"`\n                    fields.push(KeyKind::CaseSensitive(part.to_string()));\n                }\n            }\n        }\n        Ok(ConfigMapAccess {\n            de,\n            fields,\n            field_index: 0,\n        })\n    }\n\n    fn new_struct(\n        de: Deserializer<'gctx>,\n        given_fields: &'static [&'static str],\n    ) -> Result<ConfigMapAccess<'gctx>, ConfigError> {\n        let table = de.gctx.get_table(&de.key)?;\n\n        // Assume that if we're deserializing a struct it exhaustively lists all\n        // possible fields on this key that we're *supposed* to use, so take\n        // this opportunity to warn about any keys that aren't recognized as\n        // fields and warn about them.\n        if let Some(v) = table.as_ref() {\n            let unused_keys = v\n                .val\n                .iter()\n                .filter(|(k, _v)| !given_fields.iter().any(|gk| gk == k));\n            for (unused_key, unused_value) in unused_keys {\n                de.gctx.shell().warn(format!(\n                    \"unused config key `{}.{}` in `{}`\",\n                    de.key,\n                    unused_key,\n                    unused_value.definition()\n                ))?;\n            }\n        }\n\n        let mut fields = HashSet::new();\n\n        // If the caller is interested in a field which we can provide from\n        // the environment, get it from there.\n        for field in given_fields {\n            let mut field_key = de.key.clone();\n            field_key.push(field);\n            for env_key in de.gctx.env_keys() {\n                let Some(nested_field) = env_key.strip_prefix(field_key.as_env_key()) else {\n                    continue;\n                };\n                // This distinguishes fields that share the same prefix.\n                // For example, when env_key is UNSTABLE_GITOXIDE_FETCH\n                // and field_key is UNSTABLE_GIT, the field shouldn't be\n                // added because `unstable.gitoxide.fetch` doesn't\n                // belong to `unstable.git` struct.\n                if nested_field.is_empty() || nested_field.starts_with('_') {\n                    fields.insert(KeyKind::Normal(field.to_string()));\n                }\n            }\n        }\n\n        // Add everything from the config table we're interested in that we\n        // haven't already provided via an environment variable\n        if let Some(v) = table {\n            for key in v.val.keys() {\n                fields.insert(KeyKind::Normal(key.clone()));\n            }\n        }\n\n        Ok(ConfigMapAccess {\n            de,\n            fields: fields.into_iter().collect(),\n            field_index: 0,\n        })\n    }\n}\n\nimpl<'de, 'gctx> de::MapAccess<'de> for ConfigMapAccess<'gctx> {\n    type Error = ConfigError;\n\n    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>\n    where\n        K: de::DeserializeSeed<'de>,\n    {\n        if self.field_index >= self.fields.len() {\n            return Ok(None);\n        }\n        let field = match &self.fields[self.field_index] {\n            KeyKind::Normal(s) | KeyKind::CaseSensitive(s) => s.as_str(),\n        };\n        seed.deserialize(field.into_deserializer()).map(Some)\n    }\n\n    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>\n    where\n        V: de::DeserializeSeed<'de>,\n    {\n        let field = &self.fields[self.field_index];\n        self.field_index += 1;\n        // Set this as the current key in the deserializer.\n        let field = match field {\n            KeyKind::Normal(field) => {\n                self.de.key.push(field);\n                field\n            }\n            KeyKind::CaseSensitive(field) => {\n                self.de.key.push_sensitive(field);\n                field\n            }\n        };\n        // Env vars that are a prefix of another with a dash/underscore cannot\n        // be supported by our serde implementation, so check for them here.\n        // Example:\n        //     CARGO_BUILD_TARGET\n        //     CARGO_BUILD_TARGET_DIR\n        // or\n        //     CARGO_PROFILE_DEV_DEBUG\n        //     CARGO_PROFILE_DEV_DEBUG_ASSERTIONS\n        // The `deserialize_option` method does not know the type of the field.\n        // If the type is an Option<struct> (like\n        // `profile.dev.build-override`), then it needs to check for env vars\n        // starting with CARGO_FOO_BAR_. This is a problem for keys like\n        // CARGO_BUILD_TARGET because checking for a prefix would incorrectly\n        // match CARGO_BUILD_TARGET_DIR. `deserialize_option` would have no\n        // choice but to call `visit_some()` which would then fail if\n        // CARGO_BUILD_TARGET isn't set. So we check for these prefixes and\n        // disallow them here.\n        let env_prefix = format!(\"{}_\", field).replace('-', \"_\");\n        let env_prefix_ok = !self.fields.iter().any(|field| {\n            let field = match field {\n                KeyKind::Normal(s) | KeyKind::CaseSensitive(s) => s.as_str(),\n            };\n            field.replace('-', \"_\").starts_with(&env_prefix)\n        });\n\n        let result = seed\n            .deserialize(Deserializer {\n                gctx: self.de.gctx,\n                key: self.de.key.clone(),\n                env_prefix_ok,\n            })\n            .map_err(|e| {\n                if !e.is_missing_field() {\n                    return e;\n                }\n                e.with_key_context(\n                    &self.de.key,\n                    self.de\n                        .gctx\n                        .get_cv_with_env(&self.de.key)\n                        .ok()\n                        .and_then(|cv| cv.map(|cv| cv.definition().clone())),\n                )\n            });\n        self.de.key.pop();\n        result\n    }\n}\n\nstruct ConfigSeqAccess<'gctx> {\n    de: Deserializer<'gctx>,\n    list_iter: std::iter::Enumerate<vec::IntoIter<CV>>,\n}\n\nimpl ConfigSeqAccess<'_> {\n    fn new(de: Deserializer<'_>) -> Result<ConfigSeqAccess<'_>, ConfigError> {\n        let mut res = Vec::new();\n\n        match de.gctx.get_cv(&de.key)? {\n            Some(CV::List(val, _definition)) => {\n                res.extend(val);\n            }\n            Some(val) => {\n                de.gctx.expected(\"list\", &de.key, &val)?;\n            }\n            None => {}\n        }\n\n        de.gctx.get_env_list(&de.key, &mut res)?;\n\n        Ok(ConfigSeqAccess {\n            de,\n            list_iter: res.into_iter().enumerate(),\n        })\n    }\n}\n\nimpl<'de, 'gctx> de::SeqAccess<'de> for ConfigSeqAccess<'gctx> {\n    type Error = ConfigError;\n\n    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>\n    where\n        T: de::DeserializeSeed<'de>,\n    {\n        let Some((i, cv)) = self.list_iter.next() else {\n            return Ok(None);\n        };\n\n        let mut key_path = ArrayItemKeyPath::new(self.de.key.clone());\n        let definition = Some(cv.definition().clone());\n        let de = ArrayItemDeserializer {\n            cv,\n            key_path: &mut key_path,\n        };\n        seed.deserialize(de)\n            .map_err(|e| {\n                // This along with ArrayItemKeyPath provide a better error context of the\n                // ConfigValue definition + the key path within an array item that native\n                // TOML key path can't express. For example, `foo.bar[3].baz`.\n                key_path.push_index(i);\n                e.with_array_item_key_context(&key_path, definition)\n            })\n            .map(Some)\n    }\n}\n\n/// Source of data for [`ValueDeserializer`]\nenum ValueSource<'gctx, 'err> {\n    /// The deserializer used to actually deserialize a Value struct.\n    Deserializer {\n        de: Deserializer<'gctx>,\n        definition: Definition,\n    },\n    /// A [`ConfigValue`](CV).\n    ///\n    /// This is used for situations where you can't address type via a TOML key,\n    /// such as a value inside an array.\n    /// The [`ConfigSeqAccess`] doesn't know what type it should deserialize to\n    /// so [`ArrayItemDeserializer`] needs to be able to handle all of them.\n    ConfigValue {\n        cv: CV,\n        key_path: &'err mut ArrayItemKeyPath,\n    },\n}\n\nimpl<'gctx, 'err> ValueSource<'gctx, 'err> {\n    fn with_deserializer(de: Deserializer<'gctx>) -> Result<ValueSource<'gctx, 'err>, ConfigError> {\n        // Figure out where this key is defined.\n        let definition = {\n            let env = de.key.as_env_key();\n            let env_def = Definition::Environment(env.to_string());\n            match (de.gctx.env.contains_key(env), de.gctx.get_cv(&de.key)?) {\n                (true, Some(cv)) => {\n                    // Both, pick highest priority.\n                    if env_def.is_higher_priority(cv.definition()) {\n                        env_def\n                    } else {\n                        cv.definition().clone()\n                    }\n                }\n                (false, Some(cv)) => cv.definition().clone(),\n                // Assume it is an environment, even if the key is not set.\n                // This can happen for intermediate tables, like\n                // CARGO_FOO_BAR_* where `CARGO_FOO_BAR` is not set.\n                (_, None) => env_def,\n            }\n        };\n\n        Ok(Self::Deserializer { de, definition })\n    }\n\n    fn with_cv(cv: CV, key_path: &'err mut ArrayItemKeyPath) -> ValueSource<'gctx, 'err> {\n        ValueSource::ConfigValue { cv, key_path }\n    }\n}\n\n/// This is a deserializer that deserializes into a `Value<T>` for\n/// configuration.\n///\n/// This is a special deserializer because it deserializes one of its struct\n/// fields into the location that this configuration value was defined in.\n///\n/// See more comments in `value.rs` for the protocol used here.\nstruct ValueDeserializer<'gctx, 'err> {\n    hits: u32,\n    source: ValueSource<'gctx, 'err>,\n}\n\nimpl<'gctx, 'err> ValueDeserializer<'gctx, 'err> {\n    fn new(source: ValueSource<'gctx, 'err>) -> ValueDeserializer<'gctx, 'err> {\n        Self { hits: 0, source }\n    }\n\n    fn definition(&self) -> &Definition {\n        match &self.source {\n            ValueSource::Deserializer { definition, .. } => definition,\n            ValueSource::ConfigValue { cv, .. } => cv.definition(),\n        }\n    }\n}\n\nimpl<'de, 'gctx, 'err> de::MapAccess<'de> for ValueDeserializer<'gctx, 'err> {\n    type Error = ConfigError;\n\n    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>\n    where\n        K: de::DeserializeSeed<'de>,\n    {\n        self.hits += 1;\n        match self.hits {\n            1 => seed\n                .deserialize(value::VALUE_FIELD.into_deserializer())\n                .map(Some),\n            2 => seed\n                .deserialize(value::DEFINITION_FIELD.into_deserializer())\n                .map(Some),\n            _ => Ok(None),\n        }\n    }\n\n    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>\n    where\n        V: de::DeserializeSeed<'de>,\n    {\n        // If this is the first time around we deserialize the `value` field\n        // which is the actual deserializer\n        if self.hits == 1 {\n            return match &mut self.source {\n                ValueSource::Deserializer { de, definition } => seed\n                    .deserialize(de.clone())\n                    .map_err(|e| e.with_key_context(&de.key, Some(definition.clone()))),\n                ValueSource::ConfigValue { cv, key_path } => {\n                    let de = ArrayItemDeserializer {\n                        cv: cv.clone(),\n                        key_path,\n                    };\n                    seed.deserialize(de)\n                }\n            };\n        }\n\n        // ... otherwise we're deserializing the `definition` field, so we need\n        // to figure out where the field we just deserialized was defined at.\n        match self.definition() {\n            Definition::BuiltIn => seed.deserialize(0.into_deserializer()),\n            Definition::Path(path) => {\n                seed.deserialize(Tuple2Deserializer(1i32, path.to_string_lossy()))\n            }\n            Definition::Environment(env) => {\n                seed.deserialize(Tuple2Deserializer(2i32, env.as_str()))\n            }\n            Definition::Cli(path) => {\n                let s = path\n                    .as_ref()\n                    .map(|p| p.to_string_lossy())\n                    .unwrap_or_default();\n                seed.deserialize(Tuple2Deserializer(3i32, s))\n            }\n        }\n    }\n}\n\n/// A deserializer for individual [`ConfigValue`](CV) items in arrays\n///\n/// It is implemented to handle any types inside a sequence, like `Vec<String>`,\n/// `Vec<Value<i32>>`, or even `Vev<HashMap<String, Vec<bool>>>`.\nstruct ArrayItemDeserializer<'err> {\n    cv: CV,\n    key_path: &'err mut ArrayItemKeyPath,\n}\n\nimpl<'de, 'err> de::Deserializer<'de> for ArrayItemDeserializer<'err> {\n    type Error = ConfigError;\n\n    fn deserialize_struct<V>(\n        self,\n        name: &'static str,\n        fields: &'static [&'static str],\n        visitor: V,\n    ) -> Result<V::Value, Self::Error>\n    where\n        V: de::Visitor<'de>,\n    {\n        // Match on the magical struct name/field names that are passed in to\n        // detect when we're deserializing `Value<T>`.\n        //\n        // See more comments in `value.rs` for the protocol used here.\n        if name == value::NAME && fields == value::FIELDS {\n            let source = ValueSource::with_cv(self.cv, self.key_path);\n            return visitor.visit_map(ValueDeserializer::new(source));\n        }\n        visitor.visit_map(ArrayItemMapAccess::with_struct(\n            self.cv,\n            fields,\n            self.key_path,\n        ))\n    }\n\n    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>\n    where\n        V: de::Visitor<'de>,\n    {\n        match self.cv {\n            CV::String(s, _) => visitor.visit_string(s),\n            CV::Integer(i, _) => visitor.visit_i64(i),\n            CV::Boolean(b, _) => visitor.visit_bool(b),\n            l @ CV::List(_, _) => visitor.visit_seq(ArrayItemSeqAccess::new(l, self.key_path)),\n            t @ CV::Table(_, _) => visitor.visit_map(ArrayItemMapAccess::new(t, self.key_path)),\n        }\n    }\n\n    // Forward everything to deserialize_any\n    serde::forward_to_deserialize_any! {\n        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq\n        bytes byte_buf map option unit newtype_struct\n        ignored_any unit_struct tuple_struct tuple enum identifier\n    }\n}\n\n/// Sequence access for nested arrays within [`ArrayItemDeserializer`]\nstruct ArrayItemSeqAccess<'err> {\n    items: std::iter::Enumerate<vec::IntoIter<CV>>,\n    key_path: &'err mut ArrayItemKeyPath,\n}\n\nimpl<'err> ArrayItemSeqAccess<'err> {\n    fn new(cv: CV, key_path: &'err mut ArrayItemKeyPath) -> ArrayItemSeqAccess<'err> {\n        let items = match cv {\n            CV::List(list, _) => list.into_iter().enumerate(),\n            _ => unreachable!(\"must be a list\"),\n        };\n        Self { items, key_path }\n    }\n}\n\nimpl<'de, 'err> de::SeqAccess<'de> for ArrayItemSeqAccess<'err> {\n    type Error = ConfigError;\n\n    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>\n    where\n        T: de::DeserializeSeed<'de>,\n    {\n        match self.items.next() {\n            Some((i, cv)) => {\n                let de = ArrayItemDeserializer {\n                    cv,\n                    key_path: self.key_path,\n                };\n                seed.deserialize(de)\n                    .inspect_err(|_| self.key_path.push_index(i))\n                    .map(Some)\n            }\n            None => Ok(None),\n        }\n    }\n}\n\n/// Map access for nested tables within [`ArrayItemDeserializer`]\nstruct ArrayItemMapAccess<'err> {\n    cv: CV,\n    keys: vec::IntoIter<String>,\n    current_key: Option<String>,\n    key_path: &'err mut ArrayItemKeyPath,\n}\n\nimpl<'err> ArrayItemMapAccess<'err> {\n    fn new(cv: CV, key_path: &'err mut ArrayItemKeyPath) -> Self {\n        let keys = match &cv {\n            CV::Table(map, _) => map.keys().cloned().collect::<Vec<_>>().into_iter(),\n            _ => unreachable!(\"must be a map\"),\n        };\n        Self {\n            cv,\n            keys,\n            current_key: None,\n            key_path,\n        }\n    }\n\n    fn with_struct(cv: CV, given_fields: &[&str], key_path: &'err mut ArrayItemKeyPath) -> Self {\n        // TODO: We might want to warn unused fields,\n        // like what we did in ConfigMapAccess::new_struct\n        let keys = given_fields\n            .into_iter()\n            .map(|s| s.to_string())\n            .collect::<Vec<_>>()\n            .into_iter();\n        Self {\n            cv,\n            keys,\n            current_key: None,\n            key_path,\n        }\n    }\n}\n\nimpl<'de, 'err> de::MapAccess<'de> for ArrayItemMapAccess<'err> {\n    type Error = ConfigError;\n\n    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>\n    where\n        K: de::DeserializeSeed<'de>,\n    {\n        match self.keys.next() {\n            Some(key) => {\n                self.current_key = Some(key.clone());\n                seed.deserialize(key.into_deserializer()).map(Some)\n            }\n            None => Ok(None),\n        }\n    }\n\n    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>\n    where\n        V: de::DeserializeSeed<'de>,\n    {\n        let key = self.current_key.take().unwrap();\n        match &self.cv {\n            CV::Table(map, _) => {\n                if let Some(cv) = map.get(&key) {\n                    let de = ArrayItemDeserializer {\n                        cv: cv.clone(),\n                        key_path: self.key_path,\n                    };\n                    seed.deserialize(de)\n                        .inspect_err(|_| self.key_path.push_key(key))\n                } else {\n                    Err(ConfigError::new(\n                        format!(\"missing config key `{key}`\"),\n                        self.cv.definition().clone(),\n                    ))\n                }\n            }\n            _ => Err(ConfigError::new(\n                \"expected table\".to_string(),\n                self.cv.definition().clone(),\n            )),\n        }\n    }\n}\n\n/// A deserializer which takes two values and deserializes into a tuple of those\n/// two values. This is similar to types like `StrDeserializer` in upstream\n/// serde itself.\nstruct Tuple2Deserializer<T, U>(T, U);\n\nimpl<'de, T, U> de::Deserializer<'de> for Tuple2Deserializer<T, U>\nwhere\n    T: IntoDeserializer<'de, ConfigError>,\n    U: IntoDeserializer<'de, ConfigError>,\n{\n    type Error = ConfigError;\n\n    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, ConfigError>\n    where\n        V: de::Visitor<'de>,\n    {\n        struct SeqVisitor<T, U> {\n            first: Option<T>,\n            second: Option<U>,\n        }\n        impl<'de, T, U> de::SeqAccess<'de> for SeqVisitor<T, U>\n        where\n            T: IntoDeserializer<'de, ConfigError>,\n            U: IntoDeserializer<'de, ConfigError>,\n        {\n            type Error = ConfigError;\n            fn next_element_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>\n            where\n                K: de::DeserializeSeed<'de>,\n            {\n                if let Some(first) = self.first.take() {\n                    return seed.deserialize(first.into_deserializer()).map(Some);\n                }\n                if let Some(second) = self.second.take() {\n                    return seed.deserialize(second.into_deserializer()).map(Some);\n                }\n                Ok(None)\n            }\n        }\n\n        visitor.visit_seq(SeqVisitor {\n            first: Some(self.0),\n            second: Some(self.1),\n        })\n    }\n\n    serde::forward_to_deserialize_any! {\n        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq\n        bytes byte_buf map struct option unit newtype_struct\n        ignored_any unit_struct tuple_struct tuple enum identifier\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/context/environment.rs",
    "content": "//! Encapsulates snapshotting of environment variables.\n\nuse std::collections::HashMap;\nuse std::ffi::{OsStr, OsString};\n\nuse crate::util::errors::CargoResult;\nuse anyhow::{anyhow, bail};\n\n/// Generate `case_insensitive_env` and `normalized_env` from the `env`.\nfn make_case_insensitive_and_normalized_env(\n    env: &HashMap<OsString, OsString>,\n) -> (HashMap<String, String>, HashMap<String, String>) {\n    let case_insensitive_env: HashMap<_, _> = env\n        .keys()\n        .filter_map(|k| k.to_str())\n        .map(|k| (k.to_uppercase(), k.to_owned()))\n        .collect();\n\n    let normalized_env = env\n        .iter()\n        // Only keep entries where both the key and value are valid UTF-8,\n        // since the config env vars only support UTF-8 keys and values.\n        // Otherwise, the normalized map warning could incorrectly warn about entries that can't be\n        // read by the config system.\n        // Please see the docs for `Env` for more context.\n        .filter_map(|(k, v)| Some((k.to_str()?, v.to_str()?)))\n        .map(|(k, _)| (k.to_uppercase().replace(\"-\", \"_\"), k.to_owned()))\n        .collect();\n    (case_insensitive_env, normalized_env)\n}\n\n/// A snapshot of the environment variables available to [`GlobalContext`].\n///\n/// Currently, the [`GlobalContext`] supports lookup of environment variables\n/// through two different means:\n///\n/// - [`GlobalContext::get_env`](super::GlobalContext::get_env)\n///   and [`GlobalContext::get_env_os`](super::GlobalContext::get_env_os)\n///   for process environment variables (similar to [`std::env::var`] and [`std::env::var_os`]),\n/// - Typed Config Value API via [`GlobalContext::get`](super::GlobalContext::get).\n///   This is only available for `CARGO_` prefixed environment keys.\n///\n/// This type contains the env var snapshot and helper methods for both APIs.\n///\n/// [`GlobalContext`]: super::GlobalContext\n#[derive(Debug)]\npub struct Env {\n    /// A snapshot of the process's environment variables.\n    env: HashMap<OsString, OsString>,\n    /// Used in the typed Config value API for warning messages when config keys are\n    /// given in the wrong format.\n    ///\n    /// Maps from \"normalized\" (upper case and with \"-\" replaced by \"_\") env keys\n    /// to the actual keys in the environment.\n    /// The normalized format is the one expected by Cargo.\n    ///\n    /// This only holds env keys that are valid UTF-8, since [`super::ConfigKey`] only supports UTF-8 keys.\n    /// In addition, this only holds env keys whose value in the environment is also valid UTF-8,\n    /// since the typed Config value API only supports UTF-8 values.\n    normalized_env: HashMap<String, String>,\n    /// Used to implement `get_env` and `get_env_os` on Windows, where env keys are case-insensitive.\n    ///\n    /// Maps from uppercased env keys to the actual key in the environment.\n    /// For example, this might hold a pair `(\"PATH\", \"Path\")`.\n    /// Currently only supports UTF-8 keys and values.\n    case_insensitive_env: HashMap<String, String>,\n}\n\nimpl Env {\n    /// Create a new `Env` from process's environment variables.\n    pub fn new() -> Self {\n        #[expect(clippy::disallowed_methods, reason = \"seeds `GlobalContext::get_env`\")]\n        let env: HashMap<_, _> = std::env::vars_os().collect();\n        let (case_insensitive_env, normalized_env) = make_case_insensitive_and_normalized_env(&env);\n        Self {\n            env,\n            case_insensitive_env,\n            normalized_env,\n        }\n    }\n\n    /// Set the env directly from a `HashMap`.\n    /// This should be used for debugging purposes only.\n    pub(super) fn from_map(env: HashMap<String, String>) -> Self {\n        let env = env.into_iter().map(|(k, v)| (k.into(), v.into())).collect();\n        let (case_insensitive_env, normalized_env) = make_case_insensitive_and_normalized_env(&env);\n        Self {\n            env,\n            case_insensitive_env,\n            normalized_env,\n        }\n    }\n\n    /// Returns all environment variables as an iterator,\n    /// keeping only entries where both the key and value are valid UTF-8.\n    pub fn iter_str(&self) -> impl Iterator<Item = (&str, &str)> {\n        self.env\n            .iter()\n            .filter_map(|(k, v)| Some((k.to_str()?, v.to_str()?)))\n    }\n\n    /// Returns all environment variable keys, filtering out keys that are not valid UTF-8.\n    pub fn keys_str(&self) -> impl Iterator<Item = &str> {\n        self.env.keys().filter_map(|k| k.to_str())\n    }\n\n    /// Get the value of environment variable `key` through the snapshot in\n    /// [`GlobalContext`](super::GlobalContext).\n    ///\n    /// This can be used similarly to [`std::env::var_os`].\n    /// On Windows, we check for case mismatch since environment keys are case-insensitive.\n    pub fn get_env_os(&self, key: impl AsRef<OsStr>) -> Option<&OsStr> {\n        match self.env.get(key.as_ref()) {\n            Some(s) => Some(s),\n            None => {\n                if cfg!(windows) {\n                    self.get_env_case_insensitive(key)\n                } else {\n                    None\n                }\n            }\n        }\n    }\n\n    /// Get the value of environment variable `key` through the `self.env` snapshot.\n    ///\n    /// This can be used similarly to `std::env::var`.\n    /// On Windows, we check for case mismatch since environment keys are case-insensitive.\n    pub fn get_env(&self, key: impl AsRef<OsStr>) -> CargoResult<&str> {\n        let key = key.as_ref();\n        let s = self\n            .get_env_os(key)\n            .ok_or_else(|| anyhow!(\"{key:?} could not be found in the environment snapshot\"))?;\n\n        match s.to_str() {\n            Some(s) => Ok(s),\n            None => bail!(\"environment variable value is not valid unicode: {s:?}\"),\n        }\n    }\n\n    /// Performs a case-insensitive lookup of `key` in the environment.\n    ///\n    /// This is relevant on Windows, where environment variables are case-insensitive.\n    /// Note that this only works on keys that are valid UTF-8 and it uses Unicode uppercase,\n    /// which may differ from the OS's notion of uppercase.\n    fn get_env_case_insensitive(&self, key: impl AsRef<OsStr>) -> Option<&OsStr> {\n        let upper_case_key = key.as_ref().to_str()?.to_uppercase();\n        let env_key: &OsStr = self.case_insensitive_env.get(&upper_case_key)?.as_ref();\n        self.env.get(env_key).map(|v| v.as_ref())\n    }\n\n    /// Get the value of environment variable `key` as a `&str`.\n    /// Returns `None` if `key` is not in `self.env` or if the value is not valid UTF-8.\n    ///\n    /// This is intended for use in private methods of [`GlobalContext`](super::GlobalContext),\n    /// and does not check for env key case mismatch.\n    ///\n    /// This is case-sensitive on Windows (even though environment keys on Windows are usually\n    /// case-insensitive) due to an unintended regression in 1.28 (via #5552).\n    /// This should only affect keys used for cargo's config-system env variables (`CARGO_`\n    /// prefixed ones), which are currently all uppercase.\n    /// We may want to consider rectifying it if users report issues.\n    /// One thing that adds a wrinkle here is the unstable advanced-env option that *requires*\n    /// case-sensitive keys.\n    ///\n    /// Do not use this for any other purposes.\n    /// Use [`Env::get_env_os`] or [`Env::get_env`] instead, which properly handle case\n    /// insensitivity on Windows.\n    pub(super) fn get_str(&self, key: impl AsRef<OsStr>) -> Option<&str> {\n        self.env.get(key.as_ref()).and_then(|s| s.to_str())\n    }\n\n    /// Check if the environment contains `key`.\n    ///\n    /// This is intended for use in private methods of [`GlobalContext`](super::GlobalContext),\n    /// and does not check for env key case mismatch.\n    /// See the docstring of [`Env::get_str`] for more context.\n    pub(super) fn contains_key(&self, key: impl AsRef<OsStr>) -> bool {\n        self.env.contains_key(key.as_ref())\n    }\n\n    /// Looks up a normalized `key` in the `normalized_env`.\n    /// Returns the corresponding (non-normalized) env key if it exists, else `None`.\n    ///\n    /// This is used by [`super::GlobalContext::check_environment_key_case_mismatch`].\n    pub(super) fn get_normalized(&self, key: &str) -> Option<&str> {\n        self.normalized_env.get(key).map(|s| s.as_ref())\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/context/error.rs",
    "content": "use std::fmt;\n\nuse crate::util::ConfigValue;\nuse crate::util::context::ConfigKey;\nuse crate::util::context::Definition;\nuse crate::util::context::key::ArrayItemKeyPath;\n\n/// Internal error for serde errors.\n#[derive(Debug)]\npub struct ConfigError {\n    error: anyhow::Error,\n    definition: Option<Definition>,\n}\n\nimpl ConfigError {\n    pub(super) fn new(message: String, definition: Definition) -> ConfigError {\n        ConfigError {\n            error: anyhow::Error::msg(message),\n            definition: Some(definition),\n        }\n    }\n\n    pub(super) fn expected(key: &ConfigKey, expected: &str, found: &ConfigValue) -> ConfigError {\n        ConfigError {\n            error: anyhow::anyhow!(\n                \"`{}` expected {}, but found a {}\",\n                key,\n                expected,\n                found.desc()\n            ),\n            definition: Some(found.definition().clone()),\n        }\n    }\n\n    pub(super) fn is_missing_field(&self) -> bool {\n        self.error.downcast_ref::<MissingFieldError>().is_some()\n    }\n\n    pub(super) fn missing(key: &ConfigKey) -> ConfigError {\n        ConfigError {\n            error: anyhow::anyhow!(\"missing config key `{}`\", key),\n            definition: None,\n        }\n    }\n\n    pub(super) fn with_key_context(\n        self,\n        key: &ConfigKey,\n        definition: Option<Definition>,\n    ) -> ConfigError {\n        ConfigError {\n            error: anyhow::Error::from(self)\n                .context(format!(\"could not load config key `{}`\", key)),\n            definition: definition,\n        }\n    }\n\n    pub(super) fn with_array_item_key_context(\n        self,\n        key: &ArrayItemKeyPath,\n        definition: Option<Definition>,\n    ) -> ConfigError {\n        ConfigError {\n            error: anyhow::Error::from(self).context(format!(\"failed to parse config at `{key}`\")),\n            definition,\n        }\n    }\n}\n\nimpl std::error::Error for ConfigError {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        self.error.source()\n    }\n}\n\nimpl fmt::Display for ConfigError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        if let Some(definition) = &self.definition {\n            write!(f, \"error in {}: {}\", definition, self.error)\n        } else {\n            self.error.fmt(f)\n        }\n    }\n}\n\n#[derive(Debug)]\nstruct MissingFieldError(String);\n\nimpl fmt::Display for MissingFieldError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"missing field `{}`\", self.0)\n    }\n}\n\nimpl std::error::Error for MissingFieldError {}\n\nimpl serde::de::Error for ConfigError {\n    fn custom<T: fmt::Display>(msg: T) -> Self {\n        ConfigError {\n            error: anyhow::Error::msg(msg.to_string()),\n            definition: None,\n        }\n    }\n\n    fn missing_field(field: &'static str) -> Self {\n        ConfigError {\n            error: anyhow::Error::new(MissingFieldError(field.to_string())),\n            definition: None,\n        }\n    }\n}\n\nimpl From<anyhow::Error> for ConfigError {\n    fn from(error: anyhow::Error) -> Self {\n        ConfigError {\n            error,\n            definition: None,\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/context/key.rs",
    "content": "use std::borrow::Cow;\nuse std::fmt;\n\n/// Key for a configuration variable.\n///\n/// This type represents a configuration variable that we're looking up in\n/// Cargo's configuration. This structure simultaneously keeps track of a\n/// corresponding environment variable name as well as a TOML config name. The\n/// intention here is that this is built up and torn down over time efficiently,\n/// avoiding clones and such as possible.\n#[derive(Debug, Clone)]\npub struct ConfigKey {\n    // The current environment variable this configuration key maps to. This is\n    // updated with `push` methods and looks like `CARGO_FOO_BAR` for pushing\n    // `foo` and then `bar`.\n    env: String,\n    // This is used to keep track of how many sub-keys have been pushed on\n    // this `ConfigKey`. Each element of this vector is a new sub-key pushed\n    // onto this `ConfigKey`. Each element is a pair where the first item is\n    // the key part as a string, and the second item is an index into `env`.\n    // The `env` index is used on `pop` to truncate `env` to rewind back to\n    // the previous `ConfigKey` state before a `push`.\n    parts: Vec<(String, usize)>,\n}\n\nimpl ConfigKey {\n    /// Creates a new blank configuration key which is ready to get built up by\n    /// using `push` and `push_sensitive`.\n    pub fn new() -> ConfigKey {\n        ConfigKey {\n            env: \"CARGO\".to_string(),\n            parts: Vec::new(),\n        }\n    }\n\n    /// Creates a `ConfigKey` from the `key` specified.\n    ///\n    /// The `key` specified is expected to be a period-separated toml\n    /// configuration key.\n    pub fn from_str(key: &str) -> ConfigKey {\n        let mut cfg = ConfigKey::new();\n        for part in key.split('.') {\n            cfg.push(part);\n        }\n        cfg\n    }\n\n    /// Pushes a new sub-key on this `ConfigKey`. This sub-key should be\n    /// equivalent to accessing a sub-table in TOML.\n    ///\n    /// Note that this considers `name` to be case-insensitive, meaning that the\n    /// corresponding toml key is appended with this `name` as-is and the\n    /// corresponding env key is appended with `name` after transforming it to\n    /// uppercase characters.\n    pub fn push(&mut self, name: &str) {\n        let env = name.replace(\"-\", \"_\").to_uppercase();\n        self._push(&env, name);\n    }\n\n    /// Performs the same function as `push` except that the corresponding\n    /// environment variable does not get the uppercase letters of `name` but\n    /// instead `name` is pushed raw onto the corresponding environment\n    /// variable.\n    pub fn push_sensitive(&mut self, name: &str) {\n        self._push(name, name);\n    }\n\n    fn _push(&mut self, env: &str, config: &str) {\n        self.parts.push((config.to_string(), self.env.len()));\n        self.env.push('_');\n        self.env.push_str(env);\n    }\n\n    /// Rewinds this `ConfigKey` back to the state it was at before the last\n    /// `push` method being called.\n    pub fn pop(&mut self) {\n        let (_part, env) = self.parts.pop().unwrap();\n        self.env.truncate(env);\n    }\n\n    /// Returns the corresponding environment variable key for this\n    /// configuration value.\n    pub fn as_env_key(&self) -> &str {\n        &self.env\n    }\n\n    /// Returns an iterator of the key parts as strings.\n    pub(crate) fn parts(&self) -> impl Iterator<Item = &str> {\n        self.parts.iter().map(|p| p.0.as_ref())\n    }\n\n    /// Returns whether or not this is a key for the root table.\n    pub fn is_root(&self) -> bool {\n        self.parts.is_empty()\n    }\n\n    /// Returns whether or not the given key string matches this key.\n    /// Use * to match any key part.\n    pub fn matches(&self, pattern: &str) -> bool {\n        let mut parts = self.parts();\n        pattern\n            .split('.')\n            .all(|pat| parts.next() == Some(pat) || pat == \"*\")\n            && parts.next().is_none()\n    }\n}\n\nimpl fmt::Display for ConfigKey {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let parts: Vec<_> = self.parts().map(|part| escape_key_part(part)).collect();\n        parts.join(\".\").fmt(f)\n    }\n}\n\n#[derive(Debug, Clone)]\npub enum KeyOrIdx {\n    Key(String),\n    Idx(usize),\n}\n\n/// Tracks the key path to an item in an array for detailed error context.\n#[derive(Debug, Clone)]\npub struct ArrayItemKeyPath {\n    base: ConfigKey,\n    /// This is stored in reverse, and is pushed only when erroring out.\n    /// The first element is the innermost key.\n    path: Vec<KeyOrIdx>,\n}\n\nimpl ArrayItemKeyPath {\n    pub fn new(base: ConfigKey) -> Self {\n        Self {\n            base,\n            path: Vec::new(),\n        }\n    }\n\n    pub fn push_key(&mut self, k: String) {\n        self.path.push(KeyOrIdx::Key(k))\n    }\n\n    pub fn push_index(&mut self, i: usize) {\n        self.path.push(KeyOrIdx::Idx(i))\n    }\n}\n\nimpl fmt::Display for ArrayItemKeyPath {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{}\", self.base)?;\n        for k in self.path.iter().rev() {\n            match k {\n                KeyOrIdx::Key(s) => {\n                    f.write_str(\".\")?;\n                    f.write_str(&escape_key_part(&s))?;\n                }\n                KeyOrIdx::Idx(i) => {\n                    write!(f, \"[{i}]\")?;\n                }\n            }\n        }\n        Ok(())\n    }\n}\n\npub(super) fn escape_key_part<'a>(part: &'a str) -> Cow<'a, str> {\n    let ok = part.chars().all(|c| {\n        matches!(c,\n        'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_')\n    });\n    if ok {\n        Cow::Borrowed(part)\n    } else {\n        // This is a bit messy, but toml doesn't expose a function to do this.\n        Cow::Owned(toml::Value::from(part).to_string())\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use snapbox::assert_data_eq;\n    use snapbox::str;\n\n    use super::*;\n\n    #[test]\n    fn array_item_key_path_display() {\n        let base = ConfigKey::from_str(\"array\");\n        let mut key_path = ArrayItemKeyPath::new(base);\n        // These are pushed in reverse order.\n        key_path.push_index(1);\n        key_path.push_key(\"rustflags\".into());\n        key_path.push_key(\"thumbv8m.base-none-eabi\".into());\n        key_path.push_index(2);\n        key_path.push_index(3);\n\n        assert_data_eq!(\n            key_path.to_string(),\n            str![[r#\"array[3][2].\"thumbv8m.base-none-eabi\".rustflags[1]\"#]]\n        );\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/context/mod.rs",
    "content": "//! Cargo's config system.\n//!\n//! The [`GlobalContext`] object contains general information about the environment,\n//! and provides access to Cargo's configuration files.\n//!\n//! ## Config value API\n//!\n//! The primary API for fetching user-defined config values is the\n//! [`GlobalContext::get`] method. It uses `serde` to translate config values to a\n//! target type.\n//!\n//! There are a variety of helper types for deserializing some common formats:\n//!\n//! - [`value::Value`]: This type provides access to the location where the\n//!   config value was defined.\n//! - [`ConfigRelativePath`]: For a path that is relative to where it is\n//!   defined.\n//! - [`PathAndArgs`]: Similar to [`ConfigRelativePath`],\n//!   but also supports a list of arguments, useful for programs to execute.\n//! - [`StringList`]: Get a value that is either a list or a whitespace split\n//!   string.\n//!\n//! # Config schemas\n//!\n//! Configuration schemas are defined in the [`schema`] module.\n//!\n//! ## Config deserialization\n//!\n//! Cargo uses a two-layer deserialization approach:\n//!\n//! 1. **External sources → `ConfigValue`** ---\n//!    Configuration files, environment variables, and CLI `--config` arguments\n//!    are parsed into [`ConfigValue`] instances via [`ConfigValue::from_toml`].\n//!    These parsed results are stored in [`GlobalContext`].\n//!\n//! 2. **`ConfigValue` → Target types** ---\n//!    The [`GlobalContext::get`] method uses a [custom serde deserializer](Deserializer)\n//!    to convert [`ConfigValue`] instances to the caller's desired type.\n//!    Precedence between [`ConfigValue`] sources is resolved during retrieval\n//!    based on [`Definition`] priority.\n//!    See the top-level documentation of the [`de`] module for more.\n//!\n//! ## Map key recommendations\n//!\n//! Handling tables that have arbitrary keys can be tricky, particularly if it\n//! should support environment variables. In general, if possible, the caller\n//! should pass the full key path into the `get()` method so that the config\n//! deserializer can properly handle environment variables (which need to be\n//! uppercased, and dashes converted to underscores).\n//!\n//! A good example is the `[target]` table. The code will request\n//! `target.$TRIPLE` and the config system can then appropriately fetch\n//! environment variables like `CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER`.\n//! Conversely, it is not possible do the same thing for the `cfg()` target\n//! tables (because Cargo must fetch all of them), so those do not support\n//! environment variables.\n//!\n//! Try to avoid keys that are a prefix of another with a dash/underscore. For\n//! example `build.target` and `build.target-dir`. This is OK if these are not\n//! structs/maps, but if it is a struct or map, then it will not be able to\n//! read the environment variable due to ambiguity. (See `ConfigMapAccess` for\n//! more details.)\n\nuse std::borrow::Cow;\nuse std::collections::{HashMap, HashSet};\nuse std::env;\nuse std::ffi::{OsStr, OsString};\nuse std::fmt;\nuse std::fs::{self, File};\nuse std::io::SeekFrom;\nuse std::io::prelude::*;\nuse std::mem;\nuse std::path::{Path, PathBuf};\nuse std::str::FromStr;\nuse std::sync::{Arc, Mutex, MutexGuard, Once, OnceLock};\nuse std::time::Instant;\n\nuse self::ConfigValue as CV;\nuse crate::core::compiler::rustdoc::RustdocExternMap;\nuse crate::core::global_cache_tracker::{DeferredGlobalLastUse, GlobalCacheTracker};\nuse crate::core::shell::Verbosity;\nuse crate::core::{CliUnstable, Shell, SourceId, Workspace, WorkspaceRootConfig, features};\nuse crate::ops::RegistryCredentialConfig;\nuse crate::sources::CRATES_IO_INDEX;\nuse crate::sources::CRATES_IO_REGISTRY;\nuse crate::util::OnceExt as _;\nuse crate::util::cache_lock::{CacheLock, CacheLockMode, CacheLocker};\nuse crate::util::errors::CargoResult;\nuse crate::util::network::http::configure_http_handle;\nuse crate::util::network::http::http_handle;\nuse crate::util::restricted_names::is_glob_pattern;\nuse crate::util::{CanonicalUrl, closest_msg, internal};\nuse crate::util::{Filesystem, IntoUrl, IntoUrlWithBase, Rustc};\n\nuse annotate_snippets::Level;\nuse anyhow::{Context as _, anyhow, bail, format_err};\nuse cargo_credential::Secret;\nuse cargo_util::paths;\nuse cargo_util_schemas::manifest::RegistryName;\nuse curl::easy::Easy;\nuse itertools::Itertools;\nuse serde::Deserialize;\nuse serde::de::IntoDeserializer as _;\nuse time::OffsetDateTime;\nuse toml_edit::Item;\nuse url::Url;\n\nmod de;\nuse de::Deserializer;\n\nmod error;\npub use error::ConfigError;\n\nmod value;\npub use value::{Definition, OptValue, Value};\n\nmod key;\npub use key::ConfigKey;\n\nmod config_value;\npub use config_value::ConfigValue;\nuse config_value::is_nonmergeable_list;\n\nmod path;\npub use path::BracketType;\npub use path::ConfigRelativePath;\npub use path::PathAndArgs;\npub use path::ResolveTemplateError;\n\nmod target;\npub use target::{TargetCfgConfig, TargetConfig};\n\nmod environment;\nuse environment::Env;\n\nmod schema;\npub use schema::*;\n\nuse super::auth::RegistryConfig;\n\n/// Helper macro for creating typed access methods.\nmacro_rules! get_value_typed {\n    ($name:ident, $ty:ty, $variant:ident, $expected:expr) => {\n        /// Low-level private method for getting a config value as an [`OptValue`].\n        fn $name(&self, key: &ConfigKey) -> Result<OptValue<$ty>, ConfigError> {\n            let cv = self.get_cv(key)?;\n            let env = self.get_config_env::<$ty>(key)?;\n            match (cv, env) {\n                (Some(CV::$variant(val, definition)), Some(env)) => {\n                    if definition.is_higher_priority(&env.definition) {\n                        Ok(Some(Value { val, definition }))\n                    } else {\n                        Ok(Some(env))\n                    }\n                }\n                (Some(CV::$variant(val, definition)), None) => Ok(Some(Value { val, definition })),\n                (Some(cv), _) => Err(ConfigError::expected(key, $expected, &cv)),\n                (None, Some(env)) => Ok(Some(env)),\n                (None, None) => Ok(None),\n            }\n        }\n    };\n}\n\npub const TOP_LEVEL_CONFIG_KEYS: &[&str] = &[\n    \"paths\",\n    \"alias\",\n    \"build\",\n    \"credential-alias\",\n    \"doc\",\n    \"env\",\n    \"future-incompat-report\",\n    \"cache\",\n    \"cargo-new\",\n    \"http\",\n    \"install\",\n    \"net\",\n    \"patch\",\n    \"profile\",\n    \"resolver\",\n    \"registries\",\n    \"registry\",\n    \"source\",\n    \"target\",\n    \"term\",\n];\n\n/// Indicates why a config value is being loaded.\n#[derive(Clone, Copy, Debug)]\nenum WhyLoad {\n    /// Loaded due to a request from the global cli arg `--config`\n    ///\n    /// Indirect configs loaded via [`ConfigInclude`] are also seen as from cli args,\n    /// if the initial config is being loaded from cli.\n    Cli,\n    /// Loaded due to config file discovery.\n    FileDiscovery,\n}\n\n/// A previously generated authentication token and the data needed to determine if it can be reused.\n#[derive(Debug)]\npub struct CredentialCacheValue {\n    pub token_value: Secret<String>,\n    pub expiration: Option<OffsetDateTime>,\n    pub operation_independent: bool,\n}\n\n/// Configuration information for cargo. This is not specific to a build, it is information\n/// relating to cargo itself.\n#[derive(Debug)]\npub struct GlobalContext {\n    /// The location of the user's Cargo home directory. OS-dependent.\n    home_path: Filesystem,\n    /// Information about how to write messages to the shell\n    shell: Mutex<Shell>,\n    /// A collection of configuration options\n    values: OnceLock<HashMap<String, ConfigValue>>,\n    /// A collection of configuration options from the credentials file\n    credential_values: OnceLock<HashMap<String, ConfigValue>>,\n    /// CLI config values, passed in via `configure`.\n    cli_config: Option<Vec<String>>,\n    /// The current working directory of cargo\n    cwd: PathBuf,\n    /// Directory where config file searching should stop (inclusive).\n    search_stop_path: Option<PathBuf>,\n    /// The location of the cargo executable (path to current process)\n    cargo_exe: OnceLock<PathBuf>,\n    /// The location of the rustdoc executable\n    rustdoc: OnceLock<PathBuf>,\n    /// Whether we are printing extra verbose messages\n    extra_verbose: bool,\n    /// `frozen` is the same as `locked`, but additionally will not access the\n    /// network to determine if the lock file is out-of-date.\n    frozen: bool,\n    /// `locked` is set if we should not update lock files. If the lock file\n    /// is missing, or needs to be updated, an error is produced.\n    locked: bool,\n    /// `offline` is set if we should never access the network, but otherwise\n    /// continue operating if possible.\n    offline: bool,\n    /// A global static IPC control mechanism (used for managing parallel builds)\n    jobserver: Option<jobserver::Client>,\n    /// Cli flags of the form \"-Z something\" merged with config file values\n    unstable_flags: CliUnstable,\n    /// Cli flags of the form \"-Z something\"\n    unstable_flags_cli: Option<Vec<String>>,\n    /// A handle on curl easy mode for http calls\n    easy: OnceLock<Mutex<Easy>>,\n    /// Cache of the `SourceId` for crates.io\n    crates_io_source_id: OnceLock<SourceId>,\n    /// If false, don't cache `rustc --version --verbose` invocations\n    cache_rustc_info: bool,\n    /// Creation time of this config, used to output the total build time\n    creation_time: Instant,\n    /// Target Directory via resolved Cli parameter\n    target_dir: Option<Filesystem>,\n    /// Environment variable snapshot.\n    env: Env,\n    /// Tracks which sources have been updated to avoid multiple updates.\n    updated_sources: Mutex<HashSet<SourceId>>,\n    /// Cache of credentials from configuration or credential providers.\n    /// Maps from url to credential value.\n    credential_cache: Mutex<HashMap<CanonicalUrl, CredentialCacheValue>>,\n    /// Cache of registry config from the `[registries]` table.\n    registry_config: Mutex<HashMap<SourceId, Option<RegistryConfig>>>,\n    /// Locks on the package and index caches.\n    package_cache_lock: CacheLocker,\n    /// Cached configuration parsed by Cargo\n    http_config: OnceLock<CargoHttpConfig>,\n    future_incompat_config: OnceLock<CargoFutureIncompatConfig>,\n    net_config: OnceLock<CargoNetConfig>,\n    build_config: OnceLock<CargoBuildConfig>,\n    target_cfgs: OnceLock<Vec<(String, TargetCfgConfig)>>,\n    doc_extern_map: OnceLock<RustdocExternMap>,\n    progress_config: ProgressConfig,\n    env_config: OnceLock<Arc<HashMap<String, OsString>>>,\n    /// This should be false if:\n    /// - this is an artifact of the rustc distribution process for \"stable\" or for \"beta\"\n    /// - this is an `#[test]` that does not opt in with `enable_nightly_features`\n    /// - this is an integration test that uses `ProcessBuilder`\n    ///      that does not opt in with `masquerade_as_nightly_cargo`\n    /// This should be true if:\n    /// - this is an artifact of the rustc distribution process for \"nightly\"\n    /// - this is being used in the rustc distribution process internally\n    /// - this is a cargo executable that was built from source\n    /// - this is an `#[test]` that called `enable_nightly_features`\n    /// - this is an integration test that uses `ProcessBuilder`\n    ///       that called `masquerade_as_nightly_cargo`\n    /// It's public to allow tests use nightly features.\n    /// NOTE: this should be set before `configure()`. If calling this from an integration test,\n    /// consider using `ConfigBuilder::enable_nightly_features` instead.\n    pub nightly_features_allowed: bool,\n    /// `WorkspaceRootConfigs` that have been found\n    ws_roots: Mutex<HashMap<PathBuf, WorkspaceRootConfig>>,\n    /// The global cache tracker is a database used to track disk cache usage.\n    global_cache_tracker: OnceLock<Mutex<GlobalCacheTracker>>,\n    /// A cache of modifications to make to [`GlobalContext::global_cache_tracker`],\n    /// saved to disk in a batch to improve performance.\n    deferred_global_last_use: OnceLock<Mutex<DeferredGlobalLastUse>>,\n}\n\nimpl GlobalContext {\n    /// Creates a new config instance.\n    ///\n    /// This is typically used for tests or other special cases. `default` is\n    /// preferred otherwise.\n    ///\n    /// This does only minimal initialization. In particular, it does not load\n    /// any config files from disk. Those will be loaded lazily as-needed.\n    pub fn new(shell: Shell, cwd: PathBuf, homedir: PathBuf) -> GlobalContext {\n        static mut GLOBAL_JOBSERVER: *mut jobserver::Client = 0 as *mut _;\n        static INIT: Once = Once::new();\n\n        // This should be called early on in the process, so in theory the\n        // unsafety is ok here. (taken ownership of random fds)\n        INIT.call_once(|| unsafe {\n            if let Some(client) = jobserver::Client::from_env() {\n                GLOBAL_JOBSERVER = Box::into_raw(Box::new(client));\n            }\n        });\n\n        let env = Env::new();\n\n        let cache_key = \"CARGO_CACHE_RUSTC_INFO\";\n        let cache_rustc_info = match env.get_env_os(cache_key) {\n            Some(cache) => cache != \"0\",\n            _ => true,\n        };\n\n        GlobalContext {\n            home_path: Filesystem::new(homedir),\n            shell: Mutex::new(shell),\n            cwd,\n            search_stop_path: None,\n            values: Default::default(),\n            credential_values: Default::default(),\n            cli_config: None,\n            cargo_exe: Default::default(),\n            rustdoc: Default::default(),\n            extra_verbose: false,\n            frozen: false,\n            locked: false,\n            offline: false,\n            jobserver: unsafe {\n                if GLOBAL_JOBSERVER.is_null() {\n                    None\n                } else {\n                    Some((*GLOBAL_JOBSERVER).clone())\n                }\n            },\n            unstable_flags: CliUnstable::default(),\n            unstable_flags_cli: None,\n            easy: Default::default(),\n            crates_io_source_id: Default::default(),\n            cache_rustc_info,\n            creation_time: Instant::now(),\n            target_dir: None,\n            env,\n            updated_sources: Default::default(),\n            credential_cache: Default::default(),\n            registry_config: Default::default(),\n            package_cache_lock: CacheLocker::new(),\n            http_config: Default::default(),\n            future_incompat_config: Default::default(),\n            net_config: Default::default(),\n            build_config: Default::default(),\n            target_cfgs: Default::default(),\n            doc_extern_map: Default::default(),\n            progress_config: ProgressConfig::default(),\n            env_config: Default::default(),\n            nightly_features_allowed: matches!(&*features::channel(), \"nightly\" | \"dev\"),\n            ws_roots: Default::default(),\n            global_cache_tracker: Default::default(),\n            deferred_global_last_use: Default::default(),\n        }\n    }\n\n    /// Creates a new instance, with all default settings.\n    ///\n    /// This does only minimal initialization. In particular, it does not load\n    /// any config files from disk. Those will be loaded lazily as-needed.\n    pub fn default() -> CargoResult<GlobalContext> {\n        let shell = Shell::new();\n        let cwd =\n            env::current_dir().context(\"couldn't get the current directory of the process\")?;\n        let homedir = homedir(&cwd).ok_or_else(|| {\n            anyhow!(\n                \"Cargo couldn't find your home directory. \\\n                 This probably means that $HOME was not set.\"\n            )\n        })?;\n        Ok(GlobalContext::new(shell, cwd, homedir))\n    }\n\n    /// Gets the user's Cargo home directory (OS-dependent).\n    pub fn home(&self) -> &Filesystem {\n        &self.home_path\n    }\n\n    /// Returns a path to display to the user with the location of their home\n    /// config file (to only be used for displaying a diagnostics suggestion,\n    /// such as recommending where to add a config value).\n    pub fn diagnostic_home_config(&self) -> String {\n        let home = self.home_path.as_path_unlocked();\n        let path = match self.get_file_path(home, \"config\", false) {\n            Ok(Some(existing_path)) => existing_path,\n            _ => home.join(\"config.toml\"),\n        };\n        path.to_string_lossy().to_string()\n    }\n\n    /// Gets the Cargo Git directory (`<cargo_home>/git`).\n    pub fn git_path(&self) -> Filesystem {\n        self.home_path.join(\"git\")\n    }\n\n    /// Gets the directory of code sources Cargo checkouts from Git bare repos\n    /// (`<cargo_home>/git/checkouts`).\n    pub fn git_checkouts_path(&self) -> Filesystem {\n        self.git_path().join(\"checkouts\")\n    }\n\n    /// Gets the directory for all Git bare repos Cargo clones\n    /// (`<cargo_home>/git/db`).\n    pub fn git_db_path(&self) -> Filesystem {\n        self.git_path().join(\"db\")\n    }\n\n    /// Gets the Cargo base directory for all registry information (`<cargo_home>/registry`).\n    pub fn registry_base_path(&self) -> Filesystem {\n        self.home_path.join(\"registry\")\n    }\n\n    /// Gets the Cargo registry index directory (`<cargo_home>/registry/index`).\n    pub fn registry_index_path(&self) -> Filesystem {\n        self.registry_base_path().join(\"index\")\n    }\n\n    /// Gets the Cargo registry cache directory (`<cargo_home>/registry/cache`).\n    pub fn registry_cache_path(&self) -> Filesystem {\n        self.registry_base_path().join(\"cache\")\n    }\n\n    /// Gets the Cargo registry source directory (`<cargo_home>/registry/src`).\n    pub fn registry_source_path(&self) -> Filesystem {\n        self.registry_base_path().join(\"src\")\n    }\n\n    /// Gets the default Cargo registry.\n    pub fn default_registry(&self) -> CargoResult<Option<String>> {\n        Ok(self\n            .get_string(\"registry.default\")?\n            .map(|registry| registry.val))\n    }\n\n    /// Gets a reference to the shell, e.g., for writing error messages.\n    pub fn shell(&self) -> MutexGuard<'_, Shell> {\n        self.shell.lock().unwrap()\n    }\n\n    /// Assert [`Self::shell`] is not in use\n    ///\n    /// Testing might not identify bugs with two accesses to `shell` at once\n    /// due to conditional logic,\n    /// so place this outside of the conditions to catch these bugs in more situations.\n    pub fn debug_assert_shell_not_borrowed(&self) {\n        if cfg!(debug_assertions) {\n            match self.shell.try_lock() {\n                Ok(_) | Err(std::sync::TryLockError::Poisoned(_)) => (),\n                Err(std::sync::TryLockError::WouldBlock) => panic!(\"shell is borrowed!\"),\n            }\n        }\n    }\n\n    /// Gets the path to the `rustdoc` executable.\n    pub fn rustdoc(&self) -> CargoResult<&Path> {\n        self.rustdoc\n            .try_borrow_with(|| Ok(self.get_tool(Tool::Rustdoc, &self.build_config()?.rustdoc)))\n            .map(AsRef::as_ref)\n    }\n\n    /// Gets the path to the `rustc` executable.\n    pub fn load_global_rustc(&self, ws: Option<&Workspace<'_>>) -> CargoResult<Rustc> {\n        let cache_location =\n            ws.map(|ws| ws.build_dir().join(\".rustc_info.json\").into_path_unlocked());\n        let wrapper = self.maybe_get_tool(\"rustc_wrapper\", &self.build_config()?.rustc_wrapper);\n        let rustc_workspace_wrapper = self.maybe_get_tool(\n            \"rustc_workspace_wrapper\",\n            &self.build_config()?.rustc_workspace_wrapper,\n        );\n\n        Rustc::new(\n            self.get_tool(Tool::Rustc, &self.build_config()?.rustc),\n            wrapper,\n            rustc_workspace_wrapper,\n            &self\n                .home()\n                .join(\"bin\")\n                .join(\"rustc\")\n                .into_path_unlocked()\n                .with_extension(env::consts::EXE_EXTENSION),\n            if self.cache_rustc_info {\n                cache_location\n            } else {\n                None\n            },\n            self,\n        )\n    }\n\n    /// Gets the path to the `cargo` executable.\n    pub fn cargo_exe(&self) -> CargoResult<&Path> {\n        self.cargo_exe\n            .try_borrow_with(|| {\n                let from_env = || -> CargoResult<PathBuf> {\n                    // Try re-using the `cargo` set in the environment already. This allows\n                    // commands that use Cargo as a library to inherit (via `cargo <subcommand>`)\n                    // or set (by setting `$CARGO`) a correct path to `cargo` when the current exe\n                    // is not actually cargo (e.g., `cargo-*` binaries, Valgrind, `ld.so`, etc.).\n                    let exe = self\n                        .get_env_os(crate::CARGO_ENV)\n                        .map(PathBuf::from)\n                        .ok_or_else(|| anyhow!(\"$CARGO not set\"))?;\n                    Ok(exe)\n                };\n\n                fn from_current_exe() -> CargoResult<PathBuf> {\n                    // Try fetching the path to `cargo` using `env::current_exe()`.\n                    // The method varies per operating system and might fail; in particular,\n                    // it depends on `/proc` being mounted on Linux, and some environments\n                    // (like containers or chroots) may not have that available.\n                    let exe = env::current_exe()?;\n                    Ok(exe)\n                }\n\n                fn from_argv() -> CargoResult<PathBuf> {\n                    // Grab `argv[0]` and attempt to resolve it to an absolute path.\n                    // If `argv[0]` has one component, it must have come from a `PATH` lookup,\n                    // so probe `PATH` in that case.\n                    // Otherwise, it has multiple components and is either:\n                    // - a relative path (e.g., `./cargo`, `target/debug/cargo`), or\n                    // - an absolute path (e.g., `/usr/local/bin/cargo`).\n                    let argv0 = env::args_os()\n                        .map(PathBuf::from)\n                        .next()\n                        .ok_or_else(|| anyhow!(\"no argv[0]\"))?;\n                    paths::resolve_executable(&argv0)\n                }\n\n                // Determines whether `path` is a cargo binary.\n                // See: https://github.com/rust-lang/cargo/issues/15099#issuecomment-2666737150\n                fn is_cargo(path: &Path) -> bool {\n                    path.file_stem() == Some(OsStr::new(\"cargo\"))\n                }\n\n                let from_current_exe = from_current_exe();\n                if from_current_exe.as_deref().is_ok_and(is_cargo) {\n                    return from_current_exe;\n                }\n\n                let from_argv = from_argv();\n                if from_argv.as_deref().is_ok_and(is_cargo) {\n                    return from_argv;\n                }\n\n                let exe = from_env()\n                    .or(from_current_exe)\n                    .or(from_argv)\n                    .context(\"couldn't get the path to cargo executable\")?;\n                Ok(exe)\n            })\n            .map(AsRef::as_ref)\n    }\n\n    /// Which package sources have been updated, used to ensure it is only done once.\n    pub fn updated_sources(&self) -> MutexGuard<'_, HashSet<SourceId>> {\n        self.updated_sources.lock().unwrap()\n    }\n\n    /// Cached credentials from credential providers or configuration.\n    pub fn credential_cache(&self) -> MutexGuard<'_, HashMap<CanonicalUrl, CredentialCacheValue>> {\n        self.credential_cache.lock().unwrap()\n    }\n\n    /// Cache of already parsed registries from the `[registries]` table.\n    pub(crate) fn registry_config(\n        &self,\n    ) -> MutexGuard<'_, HashMap<SourceId, Option<RegistryConfig>>> {\n        self.registry_config.lock().unwrap()\n    }\n\n    /// Gets all config values from disk.\n    ///\n    /// This will lazy-load the values as necessary. Callers are responsible\n    /// for checking environment variables. Callers outside of the `config`\n    /// module should avoid using this.\n    pub fn values(&self) -> CargoResult<&HashMap<String, ConfigValue>> {\n        self.values.try_borrow_with(|| self.load_values())\n    }\n\n    /// Gets a mutable copy of the on-disk config values.\n    ///\n    /// This requires the config values to already have been loaded. This\n    /// currently only exists for `cargo vendor` to remove the `source`\n    /// entries. This doesn't respect environment variables. You should avoid\n    /// using this if possible.\n    pub fn values_mut(&mut self) -> CargoResult<&mut HashMap<String, ConfigValue>> {\n        let _ = self.values()?;\n        Ok(self.values.get_mut().expect(\"already loaded config values\"))\n    }\n\n    // Note: this is used by RLS, not Cargo.\n    pub fn set_values(&self, values: HashMap<String, ConfigValue>) -> CargoResult<()> {\n        if self.values.get().is_some() {\n            bail!(\"config values already found\")\n        }\n        match self.values.set(values.into()) {\n            Ok(()) => Ok(()),\n            Err(_) => bail!(\"could not fill values\"),\n        }\n    }\n\n    /// Sets the path where ancestor config file searching will stop. The\n    /// given path is included, but its ancestors are not.\n    pub fn set_search_stop_path<P: Into<PathBuf>>(&mut self, path: P) {\n        let path = path.into();\n        debug_assert!(self.cwd.starts_with(&path));\n        self.search_stop_path = Some(path);\n    }\n\n    /// Switches the working directory to [`std::env::current_dir`]\n    ///\n    /// There is not a need to also call [`Self::reload_rooted_at`].\n    pub fn reload_cwd(&mut self) -> CargoResult<()> {\n        let cwd =\n            env::current_dir().context(\"couldn't get the current directory of the process\")?;\n        let homedir = homedir(&cwd).ok_or_else(|| {\n            anyhow!(\n                \"Cargo couldn't find your home directory. \\\n                 This probably means that $HOME was not set.\"\n            )\n        })?;\n\n        self.cwd = cwd;\n        self.home_path = Filesystem::new(homedir);\n        self.reload_rooted_at(self.cwd.clone())?;\n        Ok(())\n    }\n\n    /// Reloads on-disk configuration values, starting at the given path and\n    /// walking up its ancestors.\n    pub fn reload_rooted_at<P: AsRef<Path>>(&mut self, path: P) -> CargoResult<()> {\n        let values = self.load_values_from(path.as_ref())?;\n        self.values.replace(values);\n        self.merge_cli_args()?;\n        self.load_unstable_flags_from_config()?;\n        Ok(())\n    }\n\n    /// The current working directory.\n    pub fn cwd(&self) -> &Path {\n        &self.cwd\n    }\n\n    /// The `target` output directory to use.\n    ///\n    /// Returns `None` if the user has not chosen an explicit directory.\n    ///\n    /// Callers should prefer [`Workspace::target_dir`] instead.\n    pub fn target_dir(&self) -> CargoResult<Option<Filesystem>> {\n        if let Some(dir) = &self.target_dir {\n            Ok(Some(dir.clone()))\n        } else if let Some(dir) = self.get_env_os(\"CARGO_TARGET_DIR\") {\n            // Check if the CARGO_TARGET_DIR environment variable is set to an empty string.\n            if dir.is_empty() {\n                bail!(\n                    \"the target directory is set to an empty string in the \\\n                     `CARGO_TARGET_DIR` environment variable\"\n                )\n            }\n\n            Ok(Some(Filesystem::new(self.cwd.join(dir))))\n        } else if let Some(val) = &self.build_config()?.target_dir {\n            let path = val.resolve_path(self);\n\n            // Check if the target directory is set to an empty string in the config.toml file.\n            if val.raw_value().is_empty() {\n                bail!(\n                    \"the target directory is set to an empty string in {}\",\n                    val.value().definition\n                )\n            }\n\n            Ok(Some(Filesystem::new(path)))\n        } else {\n            Ok(None)\n        }\n    }\n\n    /// The directory to use for intermediate build artifacts.\n    ///\n    /// Callers should prefer [`Workspace::build_dir`] instead.\n    pub fn build_dir(&self, workspace_manifest_path: &Path) -> CargoResult<Option<Filesystem>> {\n        let Some(val) = &self.build_config()?.build_dir else {\n            return Ok(None);\n        };\n        self.custom_build_dir(val, workspace_manifest_path)\n            .map(Some)\n    }\n\n    /// The directory to use for intermediate build artifacts.\n    ///\n    /// Callers should prefer [`Workspace::build_dir`] instead.\n    pub fn custom_build_dir(\n        &self,\n        val: &ConfigRelativePath,\n        workspace_manifest_path: &Path,\n    ) -> CargoResult<Filesystem> {\n        let replacements = [\n            (\n                \"{workspace-root}\",\n                workspace_manifest_path\n                    .parent()\n                    .unwrap()\n                    .to_str()\n                    .context(\"workspace root was not valid utf-8\")?\n                    .to_string(),\n            ),\n            (\n                \"{cargo-cache-home}\",\n                self.home()\n                    .as_path_unlocked()\n                    .to_str()\n                    .context(\"cargo home was not valid utf-8\")?\n                    .to_string(),\n            ),\n            (\"{workspace-path-hash}\", {\n                let real_path = std::fs::canonicalize(workspace_manifest_path)\n                    .unwrap_or_else(|_err| workspace_manifest_path.to_owned());\n                let hash = crate::util::hex::short_hash(&real_path);\n                format!(\"{}{}{}\", &hash[0..2], std::path::MAIN_SEPARATOR, &hash[2..])\n            }),\n        ];\n\n        let template_variables = replacements\n            .iter()\n            .map(|(key, _)| key[1..key.len() - 1].to_string())\n            .collect_vec();\n\n        let path = val\n                .resolve_templated_path(self, replacements)\n                .map_err(|e| match e {\n                    path::ResolveTemplateError::UnexpectedVariable {\n                        variable,\n                        raw_template,\n                    } => {\n                        let mut suggestion = closest_msg(&variable, template_variables.iter(), |key| key, \"template variable\");\n                        if suggestion == \"\" {\n                            let variables = template_variables.iter().map(|v| format!(\"`{{{v}}}`\")).join(\", \");\n                            suggestion = format!(\"\\n\\nhelp: available template variables are {variables}\");\n                        }\n                        anyhow!(\n                            \"unexpected variable `{variable}` in build.build-dir path `{raw_template}`{suggestion}\"\n                        )\n                    },\n                    path::ResolveTemplateError::UnexpectedBracket { bracket_type, raw_template } => {\n                        let (btype, literal) = match bracket_type {\n                            path::BracketType::Opening => (\"opening\", \"{\"),\n                            path::BracketType::Closing => (\"closing\", \"}\"),\n                        };\n\n                        anyhow!(\n                            \"unexpected {btype} bracket `{literal}` in build.build-dir path `{raw_template}`\"\n                        )\n                    }\n                })?;\n\n        // Check if the target directory is set to an empty string in the config.toml file.\n        if val.raw_value().is_empty() {\n            bail!(\n                \"the build directory is set to an empty string in {}\",\n                val.value().definition\n            )\n        }\n\n        Ok(Filesystem::new(path))\n    }\n\n    /// Get a configuration value by key.\n    ///\n    /// This does NOT look at environment variables. See `get_cv_with_env` for\n    /// a variant that supports environment variables.\n    fn get_cv(&self, key: &ConfigKey) -> CargoResult<Option<ConfigValue>> {\n        if let Some(vals) = self.credential_values.get() {\n            let val = self.get_cv_helper(key, vals)?;\n            if val.is_some() {\n                return Ok(val);\n            }\n        }\n        self.get_cv_helper(key, &*self.values()?)\n    }\n\n    fn get_cv_helper(\n        &self,\n        key: &ConfigKey,\n        vals: &HashMap<String, ConfigValue>,\n    ) -> CargoResult<Option<ConfigValue>> {\n        tracing::trace!(\"get cv {:?}\", key);\n        if key.is_root() {\n            // Returning the entire root table (for example `cargo config get`\n            // with no key). The definition here shouldn't matter.\n            return Ok(Some(CV::Table(\n                vals.clone(),\n                Definition::Path(PathBuf::new()),\n            )));\n        }\n        let mut parts = key.parts().enumerate();\n        let Some(mut val) = vals.get(parts.next().unwrap().1) else {\n            return Ok(None);\n        };\n        for (i, part) in parts {\n            match val {\n                CV::Table(map, _) => {\n                    val = match map.get(part) {\n                        Some(val) => val,\n                        None => return Ok(None),\n                    }\n                }\n                CV::Integer(_, def)\n                | CV::String(_, def)\n                | CV::List(_, def)\n                | CV::Boolean(_, def) => {\n                    let mut key_so_far = ConfigKey::new();\n                    for part in key.parts().take(i) {\n                        key_so_far.push(part);\n                    }\n                    bail!(\n                        \"expected table for configuration key `{}`, \\\n                         but found {} in {}\",\n                        key_so_far,\n                        val.desc(),\n                        def\n                    )\n                }\n            }\n        }\n        Ok(Some(val.clone()))\n    }\n\n    /// This is a helper for getting a CV from a file or env var.\n    pub(crate) fn get_cv_with_env(&self, key: &ConfigKey) -> CargoResult<Option<CV>> {\n        // Determine if value comes from env, cli, or file, and merge env if\n        // possible.\n        let cv = self.get_cv(key)?;\n        if key.is_root() {\n            // Root table can't have env value.\n            return Ok(cv);\n        }\n        let env = self.env.get_str(key.as_env_key());\n        let env_def = Definition::Environment(key.as_env_key().to_string());\n        let use_env = match (&cv, env) {\n            // Lists are always merged.\n            (Some(CV::List(..)), Some(_)) => true,\n            (Some(cv), Some(_)) => env_def.is_higher_priority(cv.definition()),\n            (None, Some(_)) => true,\n            _ => false,\n        };\n\n        if !use_env {\n            return Ok(cv);\n        }\n\n        // Future note: If you ever need to deserialize a non-self describing\n        // map type, this should implement a starts_with check (similar to how\n        // ConfigMapAccess does).\n        let env = env.unwrap();\n        if env == \"true\" {\n            Ok(Some(CV::Boolean(true, env_def)))\n        } else if env == \"false\" {\n            Ok(Some(CV::Boolean(false, env_def)))\n        } else if let Ok(i) = env.parse::<i64>() {\n            Ok(Some(CV::Integer(i, env_def)))\n        } else if self.cli_unstable().advanced_env && env.starts_with('[') && env.ends_with(']') {\n            match cv {\n                Some(CV::List(mut cv_list, cv_def)) => {\n                    // Merge with config file.\n                    self.get_env_list(key, &mut cv_list)?;\n                    Ok(Some(CV::List(cv_list, cv_def)))\n                }\n                Some(cv) => {\n                    // This can't assume StringList.\n                    // Return an error, which is the behavior of merging\n                    // multiple config.toml files with the same scenario.\n                    bail!(\n                        \"unable to merge array env for config `{}`\\n\\\n                        file: {:?}\\n\\\n                        env: {}\",\n                        key,\n                        cv,\n                        env\n                    );\n                }\n                None => {\n                    let mut cv_list = Vec::new();\n                    self.get_env_list(key, &mut cv_list)?;\n                    Ok(Some(CV::List(cv_list, env_def)))\n                }\n            }\n        } else {\n            // Try to merge if possible.\n            match cv {\n                Some(CV::List(mut cv_list, cv_def)) => {\n                    // Merge with config file.\n                    self.get_env_list(key, &mut cv_list)?;\n                    Ok(Some(CV::List(cv_list, cv_def)))\n                }\n                _ => {\n                    // Note: CV::Table merging is not implemented, as env\n                    // vars do not support table values. In the future, we\n                    // could check for `{}`, and interpret it as TOML if\n                    // that seems useful.\n                    Ok(Some(CV::String(env.to_string(), env_def)))\n                }\n            }\n        }\n    }\n\n    /// Helper primarily for testing.\n    pub fn set_env(&mut self, env: HashMap<String, String>) {\n        self.env = Env::from_map(env);\n    }\n\n    /// Returns all environment variables as an iterator,\n    /// keeping only entries where both the key and value are valid UTF-8.\n    pub(crate) fn env(&self) -> impl Iterator<Item = (&str, &str)> {\n        self.env.iter_str()\n    }\n\n    /// Returns all environment variable keys, filtering out keys that are not valid UTF-8.\n    fn env_keys(&self) -> impl Iterator<Item = &str> {\n        self.env.keys_str()\n    }\n\n    fn get_config_env<T>(&self, key: &ConfigKey) -> Result<OptValue<T>, ConfigError>\n    where\n        T: FromStr,\n        <T as FromStr>::Err: fmt::Display,\n    {\n        match self.env.get_str(key.as_env_key()) {\n            Some(value) => {\n                let definition = Definition::Environment(key.as_env_key().to_string());\n                Ok(Some(Value {\n                    val: value\n                        .parse()\n                        .map_err(|e| ConfigError::new(format!(\"{}\", e), definition.clone()))?,\n                    definition,\n                }))\n            }\n            None => {\n                self.check_environment_key_case_mismatch(key);\n                Ok(None)\n            }\n        }\n    }\n\n    /// Get the value of environment variable `key` through the snapshot in\n    /// [`GlobalContext`].\n    ///\n    /// This can be used similarly to [`std::env::var`].\n    pub fn get_env(&self, key: impl AsRef<OsStr>) -> CargoResult<&str> {\n        self.env.get_env(key)\n    }\n\n    /// Get the value of environment variable `key` through the snapshot in\n    /// [`GlobalContext`].\n    ///\n    /// This can be used similarly to [`std::env::var_os`].\n    pub fn get_env_os(&self, key: impl AsRef<OsStr>) -> Option<&OsStr> {\n        self.env.get_env_os(key)\n    }\n\n    /// Check if the [`GlobalContext`] contains a given [`ConfigKey`].\n    ///\n    /// See `ConfigMapAccess` for a description of `env_prefix_ok`.\n    fn has_key(&self, key: &ConfigKey, env_prefix_ok: bool) -> CargoResult<bool> {\n        if self.env.contains_key(key.as_env_key()) {\n            return Ok(true);\n        }\n        if env_prefix_ok {\n            let env_prefix = format!(\"{}_\", key.as_env_key());\n            if self.env_keys().any(|k| k.starts_with(&env_prefix)) {\n                return Ok(true);\n            }\n        }\n        if self.get_cv(key)?.is_some() {\n            return Ok(true);\n        }\n        self.check_environment_key_case_mismatch(key);\n\n        Ok(false)\n    }\n\n    fn check_environment_key_case_mismatch(&self, key: &ConfigKey) {\n        if let Some(env_key) = self.env.get_normalized(key.as_env_key()) {\n            let _ = self.shell().warn(format!(\n                \"environment variables are expected to use uppercase letters and underscores, \\\n                the variable `{}` will be ignored and have no effect\",\n                env_key\n            ));\n        }\n    }\n\n    /// Get a string config value.\n    ///\n    /// See `get` for more details.\n    pub fn get_string(&self, key: &str) -> CargoResult<OptValue<String>> {\n        self.get::<OptValue<String>>(key)\n    }\n\n    fn string_to_path(&self, value: &str, definition: &Definition) -> PathBuf {\n        let is_path = value.contains('/') || (cfg!(windows) && value.contains('\\\\'));\n        if is_path {\n            definition.root(self.cwd()).join(value)\n        } else {\n            // A pathless name.\n            PathBuf::from(value)\n        }\n    }\n\n    /// Internal method for getting an environment variable as a list.\n    /// If the key is a non-mergeable list and a value is found in the environment, existing values are cleared.\n    fn get_env_list(&self, key: &ConfigKey, output: &mut Vec<ConfigValue>) -> CargoResult<()> {\n        let Some(env_val) = self.env.get_str(key.as_env_key()) else {\n            self.check_environment_key_case_mismatch(key);\n            return Ok(());\n        };\n\n        let env_def = Definition::Environment(key.as_env_key().to_string());\n\n        if is_nonmergeable_list(&key) {\n            assert!(\n                output\n                    .windows(2)\n                    .all(|cvs| cvs[0].definition() == cvs[1].definition()),\n                \"non-mergeable list must have only one definition: {output:?}\",\n            );\n\n            // Keep existing config if higher priority than env (e.g., --config CLI),\n            // otherwise clear for env\n            if output\n                .first()\n                .map(|o| o.definition() > &env_def)\n                .unwrap_or_default()\n            {\n                return Ok(());\n            } else {\n                output.clear();\n            }\n        }\n\n        if self.cli_unstable().advanced_env && env_val.starts_with('[') && env_val.ends_with(']') {\n            // Parse an environment string as a TOML array.\n            let toml_v = env_val.parse::<toml::Value>().map_err(|e| {\n                ConfigError::new(format!(\"could not parse TOML list: {}\", e), env_def.clone())\n            })?;\n            let values = toml_v.as_array().expect(\"env var was not array\");\n            for value in values {\n                // Until we figure out how to deal with it through `-Zadvanced-env`,\n                // complex array types are unsupported.\n                let s = value.as_str().ok_or_else(|| {\n                    ConfigError::new(\n                        format!(\"expected string, found {}\", value.type_str()),\n                        env_def.clone(),\n                    )\n                })?;\n                output.push(CV::String(s.to_string(), env_def.clone()))\n            }\n        } else {\n            output.extend(\n                env_val\n                    .split_whitespace()\n                    .map(|s| CV::String(s.to_string(), env_def.clone())),\n            );\n        }\n        output.sort_by(|a, b| a.definition().cmp(b.definition()));\n        Ok(())\n    }\n\n    /// Low-level method for getting a config value as an `OptValue<HashMap<String, CV>>`.\n    ///\n    /// NOTE: This does not read from env. The caller is responsible for that.\n    fn get_table(&self, key: &ConfigKey) -> CargoResult<OptValue<HashMap<String, CV>>> {\n        match self.get_cv(key)? {\n            Some(CV::Table(val, definition)) => Ok(Some(Value { val, definition })),\n            Some(val) => self.expected(\"table\", key, &val),\n            None => Ok(None),\n        }\n    }\n\n    get_value_typed! {get_integer, i64, Integer, \"an integer\"}\n    get_value_typed! {get_bool, bool, Boolean, \"true/false\"}\n    get_value_typed! {get_string_priv, String, String, \"a string\"}\n\n    /// Generate an error when the given value is the wrong type.\n    fn expected<T>(&self, ty: &str, key: &ConfigKey, val: &CV) -> CargoResult<T> {\n        val.expected(ty, &key.to_string())\n            .map_err(|e| anyhow!(\"invalid configuration for key `{}`\\n{}\", key, e))\n    }\n\n    /// Update the instance based on settings typically passed in on\n    /// the command-line.\n    ///\n    /// This may also load the config from disk if it hasn't already been\n    /// loaded.\n    pub fn configure(\n        &mut self,\n        verbose: u32,\n        quiet: bool,\n        color: Option<&str>,\n        frozen: bool,\n        locked: bool,\n        offline: bool,\n        target_dir: &Option<PathBuf>,\n        unstable_flags: &[String],\n        cli_config: &[String],\n    ) -> CargoResult<()> {\n        for warning in self\n            .unstable_flags\n            .parse(unstable_flags, self.nightly_features_allowed)?\n        {\n            self.shell().warn(warning)?;\n        }\n        if !unstable_flags.is_empty() {\n            // store a copy of the cli flags separately for `load_unstable_flags_from_config`\n            // (we might also need it again for `reload_rooted_at`)\n            self.unstable_flags_cli = Some(unstable_flags.to_vec());\n        }\n        if !cli_config.is_empty() {\n            self.cli_config = Some(cli_config.iter().map(|s| s.to_string()).collect());\n            self.merge_cli_args()?;\n        }\n\n        self.load_unstable_flags_from_config()?;\n\n        // Ignore errors in the configuration files. We don't want basic\n        // commands like `cargo version` to error out due to config file\n        // problems.\n        let term = self.get::<TermConfig>(\"term\").unwrap_or_default();\n\n        // The command line takes precedence over configuration.\n        let extra_verbose = verbose >= 2;\n        let verbose = verbose != 0;\n        let verbosity = match (verbose, quiet) {\n            (true, true) => bail!(\"cannot set both --verbose and --quiet\"),\n            (true, false) => Verbosity::Verbose,\n            (false, true) => Verbosity::Quiet,\n            (false, false) => match (term.verbose, term.quiet) {\n                (Some(true), Some(true)) => {\n                    bail!(\"cannot set both `term.verbose` and `term.quiet`\")\n                }\n                (Some(true), _) => Verbosity::Verbose,\n                (_, Some(true)) => Verbosity::Quiet,\n                _ => Verbosity::Normal,\n            },\n        };\n        self.shell().set_verbosity(verbosity);\n        self.extra_verbose = extra_verbose;\n\n        let color = color.or_else(|| term.color.as_deref());\n        self.shell().set_color_choice(color)?;\n        if let Some(hyperlinks) = term.hyperlinks {\n            self.shell().set_hyperlinks(hyperlinks)?;\n        }\n        if let Some(unicode) = term.unicode {\n            self.shell().set_unicode(unicode)?;\n        }\n\n        self.progress_config = term.progress.unwrap_or_default();\n\n        self.frozen = frozen;\n        self.locked = locked;\n        self.offline = offline\n            || self\n                .net_config()\n                .ok()\n                .and_then(|n| n.offline)\n                .unwrap_or(false);\n        let cli_target_dir = target_dir.as_ref().map(|dir| Filesystem::new(dir.clone()));\n        self.target_dir = cli_target_dir;\n\n        self.shell()\n            .set_unstable_flags_rustc_unicode(self.unstable_flags.rustc_unicode)?;\n\n        Ok(())\n    }\n\n    fn load_unstable_flags_from_config(&mut self) -> CargoResult<()> {\n        // If nightly features are enabled, allow setting Z-flags from config\n        // using the `unstable` table. Ignore that block otherwise.\n        if self.nightly_features_allowed {\n            self.unstable_flags = self\n                .get::<Option<CliUnstable>>(\"unstable\")?\n                .unwrap_or_default();\n            if let Some(unstable_flags_cli) = &self.unstable_flags_cli {\n                // NB. It's not ideal to parse these twice, but doing it again here\n                //     allows the CLI to override config files for both enabling\n                //     and disabling, and doing it up top allows CLI Zflags to\n                //     control config parsing behavior.\n                self.unstable_flags.parse(unstable_flags_cli, true)?;\n            }\n        }\n\n        Ok(())\n    }\n\n    pub fn cli_unstable(&self) -> &CliUnstable {\n        &self.unstable_flags\n    }\n\n    pub fn extra_verbose(&self) -> bool {\n        self.extra_verbose\n    }\n\n    pub fn network_allowed(&self) -> bool {\n        !self.offline_flag().is_some()\n    }\n\n    pub fn offline_flag(&self) -> Option<&'static str> {\n        if self.frozen {\n            Some(\"--frozen\")\n        } else if self.offline {\n            Some(\"--offline\")\n        } else {\n            None\n        }\n    }\n\n    pub fn set_locked(&mut self, locked: bool) {\n        self.locked = locked;\n    }\n\n    pub fn lock_update_allowed(&self) -> bool {\n        !self.locked_flag().is_some()\n    }\n\n    pub fn locked_flag(&self) -> Option<&'static str> {\n        if self.frozen {\n            Some(\"--frozen\")\n        } else if self.locked {\n            Some(\"--locked\")\n        } else {\n            None\n        }\n    }\n\n    /// Loads configuration from the filesystem.\n    pub fn load_values(&self) -> CargoResult<HashMap<String, ConfigValue>> {\n        self.load_values_from(&self.cwd)\n    }\n\n    /// Like [`load_values`](GlobalContext::load_values) but without merging config values.\n    ///\n    /// This is primarily crafted for `cargo config` command.\n    pub(crate) fn load_values_unmerged(&self) -> CargoResult<Vec<ConfigValue>> {\n        let mut result = Vec::new();\n        let mut seen = HashSet::new();\n        let home = self.home_path.clone().into_path_unlocked();\n        self.walk_tree(&self.cwd, &home, |path| {\n            let mut cv = self._load_file(path, &mut seen, false, WhyLoad::FileDiscovery)?;\n            self.load_unmerged_include(&mut cv, &mut seen, &mut result)?;\n            result.push(cv);\n            Ok(())\n        })\n        .context(\"could not load Cargo configuration\")?;\n        Ok(result)\n    }\n\n    /// Like [`load_includes`](GlobalContext::load_includes) but without merging config values.\n    ///\n    /// This is primarily crafted for `cargo config` command.\n    fn load_unmerged_include(\n        &self,\n        cv: &mut CV,\n        seen: &mut HashSet<PathBuf>,\n        output: &mut Vec<CV>,\n    ) -> CargoResult<()> {\n        let includes = self.include_paths(cv, false)?;\n        for include in includes {\n            let Some(abs_path) = include.resolve_path(self) else {\n                continue;\n            };\n\n            let mut cv = self\n                ._load_file(&abs_path, seen, false, WhyLoad::FileDiscovery)\n                .with_context(|| {\n                    format!(\n                        \"failed to load config include `{}` from `{}`\",\n                        include.path.display(),\n                        include.def\n                    )\n                })?;\n            self.load_unmerged_include(&mut cv, seen, output)?;\n            output.push(cv);\n        }\n        Ok(())\n    }\n\n    /// Start a config file discovery from a path and merges all config values found.\n    fn load_values_from(&self, path: &Path) -> CargoResult<HashMap<String, ConfigValue>> {\n        // The root config value container isn't from any external source,\n        // so its definition should be built-in.\n        let mut cfg = CV::Table(HashMap::new(), Definition::BuiltIn);\n        let home = self.home_path.clone().into_path_unlocked();\n\n        self.walk_tree(path, &home, |path| {\n            let value = self.load_file(path)?;\n            cfg.merge(value, false).with_context(|| {\n                format!(\"failed to merge configuration at `{}`\", path.display())\n            })?;\n            Ok(())\n        })\n        .context(\"could not load Cargo configuration\")?;\n\n        match cfg {\n            CV::Table(map, _) => Ok(map),\n            _ => unreachable!(),\n        }\n    }\n\n    /// Loads a config value from a path.\n    ///\n    /// This is used during config file discovery.\n    fn load_file(&self, path: &Path) -> CargoResult<ConfigValue> {\n        self._load_file(path, &mut HashSet::new(), true, WhyLoad::FileDiscovery)\n    }\n\n    /// Loads a config value from a path with options.\n    ///\n    /// This is actual implementation of loading a config value from a path.\n    ///\n    /// * `includes` determines whether to load configs from [`ConfigInclude`].\n    /// * `seen` is used to check for cyclic includes.\n    /// * `why_load` tells why a config is being loaded.\n    fn _load_file(\n        &self,\n        path: &Path,\n        seen: &mut HashSet<PathBuf>,\n        includes: bool,\n        why_load: WhyLoad,\n    ) -> CargoResult<ConfigValue> {\n        if !seen.insert(path.to_path_buf()) {\n            bail!(\n                \"config `include` cycle detected with path `{}`\",\n                path.display()\n            );\n        }\n        tracing::debug!(?path, ?why_load, includes, \"load config from file\");\n\n        let contents = fs::read_to_string(path)\n            .with_context(|| format!(\"failed to read configuration file `{}`\", path.display()))?;\n        let toml = parse_document(&contents, path, self).with_context(|| {\n            format!(\"could not parse TOML configuration in `{}`\", path.display())\n        })?;\n        let def = match why_load {\n            WhyLoad::Cli => Definition::Cli(Some(path.into())),\n            WhyLoad::FileDiscovery => Definition::Path(path.into()),\n        };\n        let value = CV::from_toml(def, toml::Value::Table(toml)).with_context(|| {\n            format!(\n                \"failed to load TOML configuration from `{}`\",\n                path.display()\n            )\n        })?;\n        if includes {\n            self.load_includes(value, seen, why_load)\n        } else {\n            Ok(value)\n        }\n    }\n\n    /// Load any `include` files listed in the given `value`.\n    ///\n    /// Returns `value` with the given include files merged into it.\n    ///\n    /// * `seen` is used to check for cyclic includes.\n    /// * `why_load` tells why a config is being loaded.\n    fn load_includes(\n        &self,\n        mut value: CV,\n        seen: &mut HashSet<PathBuf>,\n        why_load: WhyLoad,\n    ) -> CargoResult<CV> {\n        // Get the list of files to load.\n        let includes = self.include_paths(&mut value, true)?;\n\n        // Accumulate all values here.\n        let mut root = CV::Table(HashMap::new(), value.definition().clone());\n        for include in includes {\n            let Some(abs_path) = include.resolve_path(self) else {\n                continue;\n            };\n\n            self._load_file(&abs_path, seen, true, why_load)\n                .and_then(|include| root.merge(include, true))\n                .with_context(|| {\n                    format!(\n                        \"failed to load config include `{}` from `{}`\",\n                        include.path.display(),\n                        include.def\n                    )\n                })?;\n        }\n        root.merge(value, true)?;\n        Ok(root)\n    }\n\n    /// Converts the `include` config value to a list of absolute paths.\n    fn include_paths(&self, cv: &mut CV, remove: bool) -> CargoResult<Vec<ConfigInclude>> {\n        let CV::Table(table, _def) = cv else {\n            unreachable!()\n        };\n        let include = if remove {\n            table.remove(\"include\").map(Cow::Owned)\n        } else {\n            table.get(\"include\").map(Cow::Borrowed)\n        };\n        let includes = match include.map(|c| c.into_owned()) {\n            Some(CV::List(list, _def)) => list\n                .into_iter()\n                .enumerate()\n                .map(|(idx, cv)| match cv {\n                    CV::String(s, def) => Ok(ConfigInclude::new(s, def)),\n                    CV::Table(mut table, def) => {\n                        // Extract `include.path`\n                        let s = match table.remove(\"path\") {\n                            Some(CV::String(s, _)) => s,\n                            Some(other) => bail!(\n                                \"expected a string, but found {} at `include[{idx}].path` in `{def}`\",\n                                other.desc()\n                            ),\n                            None => bail!(\"missing field `path` at `include[{idx}]` in `{def}`\"),\n                        };\n\n                        // Extract optional `include.optional` field\n                        let optional = match table.remove(\"optional\") {\n                            Some(CV::Boolean(b, _)) => b,\n                            Some(other) => bail!(\n                                \"expected a boolean, but found {} at `include[{idx}].optional` in `{def}`\",\n                                other.desc()\n                            ),\n                            None => false,\n                        };\n\n                        let mut include = ConfigInclude::new(s, def);\n                        include.optional = optional;\n                        Ok(include)\n                    }\n                    other => bail!(\n                        \"expected a string or table, but found {} at `include[{idx}]` in {}\",\n                        other.desc(),\n                        other.definition(),\n                    ),\n                })\n                .collect::<CargoResult<Vec<_>>>()?,\n            Some(other) => bail!(\n                \"expected a list of strings or a list of tables, but found {} at `include` in `{}\",\n                other.desc(),\n                other.definition()\n            ),\n            None => {\n                return Ok(Vec::new());\n            }\n        };\n\n        for include in &includes {\n            if include.path.extension() != Some(OsStr::new(\"toml\")) {\n                bail!(\n                    \"expected a config include path ending with `.toml`, \\\n                     but found `{}` from `{}`\",\n                    include.path.display(),\n                    include.def,\n                )\n            }\n\n            if let Some(path) = include.path.to_str() {\n                // Ignore non UTF-8 bytes as glob and template syntax are for textual config.\n                if is_glob_pattern(path) {\n                    bail!(\n                        \"expected a config include path without glob patterns, \\\n                         but found `{}` from `{}`\",\n                        include.path.display(),\n                        include.def,\n                    )\n                }\n                if path.contains(&['{', '}']) {\n                    bail!(\n                        \"expected a config include path without template braces, \\\n                         but found `{}` from `{}`\",\n                        include.path.display(),\n                        include.def,\n                    )\n                }\n            }\n        }\n\n        Ok(includes)\n    }\n\n    /// Parses the CLI config args and returns them as a table.\n    pub(crate) fn cli_args_as_table(&self) -> CargoResult<ConfigValue> {\n        let mut loaded_args = CV::Table(HashMap::new(), Definition::Cli(None));\n        let Some(cli_args) = &self.cli_config else {\n            return Ok(loaded_args);\n        };\n        let mut seen = HashSet::new();\n        for arg in cli_args {\n            let arg_as_path = self.cwd.join(arg);\n            let tmp_table = if !arg.is_empty() && arg_as_path.exists() {\n                // --config path_to_file\n                self._load_file(&arg_as_path, &mut seen, true, WhyLoad::Cli)\n                    .with_context(|| {\n                        format!(\"failed to load config from `{}`\", arg_as_path.display())\n                    })?\n            } else {\n                let doc = toml_dotted_keys(arg)?;\n                let doc: toml::Value = toml::Value::deserialize(doc.into_deserializer())\n                    .with_context(|| {\n                        format!(\"failed to parse value from --config argument `{arg}`\")\n                    })?;\n\n                if doc\n                    .get(\"registry\")\n                    .and_then(|v| v.as_table())\n                    .and_then(|t| t.get(\"token\"))\n                    .is_some()\n                {\n                    bail!(\"registry.token cannot be set through --config for security reasons\");\n                } else if let Some((k, _)) = doc\n                    .get(\"registries\")\n                    .and_then(|v| v.as_table())\n                    .and_then(|t| t.iter().find(|(_, v)| v.get(\"token\").is_some()))\n                {\n                    bail!(\n                        \"registries.{}.token cannot be set through --config for security reasons\",\n                        k\n                    );\n                }\n\n                if doc\n                    .get(\"registry\")\n                    .and_then(|v| v.as_table())\n                    .and_then(|t| t.get(\"secret-key\"))\n                    .is_some()\n                {\n                    bail!(\n                        \"registry.secret-key cannot be set through --config for security reasons\"\n                    );\n                } else if let Some((k, _)) = doc\n                    .get(\"registries\")\n                    .and_then(|v| v.as_table())\n                    .and_then(|t| t.iter().find(|(_, v)| v.get(\"secret-key\").is_some()))\n                {\n                    bail!(\n                        \"registries.{}.secret-key cannot be set through --config for security reasons\",\n                        k\n                    );\n                }\n\n                CV::from_toml(Definition::Cli(None), doc)\n                    .with_context(|| format!(\"failed to convert --config argument `{arg}`\"))?\n            };\n            let tmp_table = self\n                .load_includes(tmp_table, &mut HashSet::new(), WhyLoad::Cli)\n                .context(\"failed to load --config include\".to_string())?;\n            loaded_args\n                .merge(tmp_table, true)\n                .with_context(|| format!(\"failed to merge --config argument `{arg}`\"))?;\n        }\n        Ok(loaded_args)\n    }\n\n    /// Add config arguments passed on the command line.\n    fn merge_cli_args(&mut self) -> CargoResult<()> {\n        let cv_from_cli = self.cli_args_as_table()?;\n        assert!(cv_from_cli.is_table(), \"cv from CLI must be a table\");\n\n        let root_cv = mem::take(self.values_mut()?);\n        // The root config value container isn't from any external source,\n        // so its definition should be built-in.\n        let mut root_cv = CV::Table(root_cv, Definition::BuiltIn);\n        root_cv.merge(cv_from_cli, true)?;\n\n        // Put it back to gctx\n        mem::swap(self.values_mut()?, root_cv.table_mut(\"<root>\")?.0);\n\n        Ok(())\n    }\n\n    /// The purpose of this function is to aid in the transition to using\n    /// .toml extensions on Cargo's config files, which were historically not used.\n    /// Both 'config.toml' and 'credentials.toml' should be valid with or without extension.\n    /// When both exist, we want to prefer the one without an extension for\n    /// backwards compatibility, but warn the user appropriately.\n    fn get_file_path(\n        &self,\n        dir: &Path,\n        filename_without_extension: &str,\n        warn: bool,\n    ) -> CargoResult<Option<PathBuf>> {\n        let possible = dir.join(filename_without_extension);\n        let possible_with_extension = dir.join(format!(\"{}.toml\", filename_without_extension));\n\n        if let Ok(possible_handle) = same_file::Handle::from_path(&possible) {\n            if warn {\n                if let Ok(possible_with_extension_handle) =\n                    same_file::Handle::from_path(&possible_with_extension)\n                {\n                    // We don't want to print a warning if the version\n                    // without the extension is just a symlink to the version\n                    // WITH an extension, which people may want to do to\n                    // support multiple Cargo versions at once and not\n                    // get a warning.\n                    if possible_handle != possible_with_extension_handle {\n                        self.shell().warn(format!(\n                            \"both `{}` and `{}` exist. Using `{}`\",\n                            possible.display(),\n                            possible_with_extension.display(),\n                            possible.display()\n                        ))?;\n                    }\n                } else {\n                    self.shell().print_report(&[\n                        Level::WARNING.secondary_title(\n                        format!(\n                        \"`{}` is deprecated in favor of `{filename_without_extension}.toml`\",\n                        possible.display(),\n                    )).element(Level::HELP.message(\n                        format!(\"if you need to support cargo 1.38 or earlier, you can symlink `{filename_without_extension}` to `{filename_without_extension}.toml`\")))\n\n                    ], false)?;\n                }\n            }\n\n            Ok(Some(possible))\n        } else if possible_with_extension.exists() {\n            Ok(Some(possible_with_extension))\n        } else {\n            Ok(None)\n        }\n    }\n\n    fn walk_tree<F>(&self, pwd: &Path, home: &Path, mut walk: F) -> CargoResult<()>\n    where\n        F: FnMut(&Path) -> CargoResult<()>,\n    {\n        let mut seen_dir = HashSet::new();\n\n        for current in paths::ancestors(pwd, self.search_stop_path.as_deref()) {\n            let config_root = current.join(\".cargo\");\n            if let Some(path) = self.get_file_path(&config_root, \"config\", true)? {\n                walk(&path)?;\n            }\n\n            let canonical_root = config_root.canonicalize().unwrap_or(config_root);\n            seen_dir.insert(canonical_root);\n        }\n\n        let canonical_home = home.canonicalize().unwrap_or(home.to_path_buf());\n\n        // Once we're done, also be sure to walk the home directory even if it's not\n        // in our history to be sure we pick up that standard location for\n        // information.\n        if !seen_dir.contains(&canonical_home) && !seen_dir.contains(home) {\n            if let Some(path) = self.get_file_path(home, \"config\", true)? {\n                walk(&path)?;\n            }\n        }\n\n        Ok(())\n    }\n\n    /// Gets the index for a registry.\n    pub fn get_registry_index(&self, registry: &str) -> CargoResult<Url> {\n        RegistryName::new(registry)?;\n        if let Some(index) = self.get_string(&format!(\"registries.{}.index\", registry))? {\n            self.resolve_registry_index(&index).with_context(|| {\n                format!(\n                    \"invalid index URL for registry `{}` defined in {}\",\n                    registry, index.definition\n                )\n            })\n        } else {\n            bail!(\n                \"registry index was not found in any configuration: `{}`\",\n                registry\n            );\n        }\n    }\n\n    /// Returns an error if `registry.index` is set.\n    pub fn check_registry_index_not_set(&self) -> CargoResult<()> {\n        if self.get_string(\"registry.index\")?.is_some() {\n            bail!(\n                \"the `registry.index` config value is no longer supported\\n\\\n                Use `[source]` replacement to alter the default index for crates.io.\"\n            );\n        }\n        Ok(())\n    }\n\n    fn resolve_registry_index(&self, index: &Value<String>) -> CargoResult<Url> {\n        // This handles relative file: URLs, relative to the config definition.\n        let base = index\n            .definition\n            .root(self.cwd())\n            .join(\"truncated-by-url_with_base\");\n        // Parse val to check it is a URL, not a relative path without a protocol.\n        let _parsed = index.val.into_url()?;\n        let url = index.val.into_url_with_base(Some(&*base))?;\n        if url.password().is_some() {\n            bail!(\"registry URLs may not contain passwords\");\n        }\n        Ok(url)\n    }\n\n    /// Loads credentials config from the credentials file, if present.\n    ///\n    /// The credentials are loaded into a separate field to enable them\n    /// to be lazy-loaded after the main configuration has been loaded,\n    /// without requiring `mut` access to the [`GlobalContext`].\n    ///\n    /// If the credentials are already loaded, this function does nothing.\n    pub fn load_credentials(&self) -> CargoResult<()> {\n        if self.credential_values.filled() {\n            return Ok(());\n        }\n\n        let home_path = self.home_path.clone().into_path_unlocked();\n        let Some(credentials) = self.get_file_path(&home_path, \"credentials\", true)? else {\n            return Ok(());\n        };\n\n        let mut value = self.load_file(&credentials)?;\n        // Backwards compatibility for old `.cargo/credentials` layout.\n        {\n            let (value_map, def) = value.table_mut(\"<root>\")?;\n\n            if let Some(token) = value_map.remove(\"token\") {\n                value_map.entry(\"registry\".into()).or_insert_with(|| {\n                    let map = HashMap::from([(\"token\".into(), token)]);\n                    CV::Table(map, def.clone())\n                });\n            }\n        }\n\n        let mut credential_values = HashMap::new();\n        if let CV::Table(map, _) = value {\n            let base_map = self.values()?;\n            for (k, v) in map {\n                let entry = match base_map.get(&k) {\n                    Some(base_entry) => {\n                        let mut entry = base_entry.clone();\n                        entry.merge(v, true)?;\n                        entry\n                    }\n                    None => v,\n                };\n                credential_values.insert(k, entry);\n            }\n        }\n        self.credential_values\n            .set(credential_values)\n            .expect(\"was not filled at beginning of the function\");\n        Ok(())\n    }\n\n    /// Looks for a path for `tool` in an environment variable or the given config, and returns\n    /// `None` if it's not present.\n    fn maybe_get_tool(\n        &self,\n        tool: &str,\n        from_config: &Option<ConfigRelativePath>,\n    ) -> Option<PathBuf> {\n        let var = tool.to_uppercase();\n\n        match self.get_env_os(&var).as_ref().and_then(|s| s.to_str()) {\n            Some(tool_path) => {\n                let maybe_relative = tool_path.contains('/') || tool_path.contains('\\\\');\n                let path = if maybe_relative {\n                    self.cwd.join(tool_path)\n                } else {\n                    PathBuf::from(tool_path)\n                };\n                Some(path)\n            }\n\n            None => from_config.as_ref().map(|p| p.resolve_program(self)),\n        }\n    }\n\n    /// Returns the path for the given tool.\n    ///\n    /// This will look for the tool in the following order:\n    ///\n    /// 1. From an environment variable matching the tool name (such as `RUSTC`).\n    /// 2. From the given config value (which is usually something like `build.rustc`).\n    /// 3. Finds the tool in the PATH environment variable.\n    ///\n    /// This is intended for tools that are rustup proxies. If you need to get\n    /// a tool that is not a rustup proxy, use `maybe_get_tool` instead.\n    fn get_tool(&self, tool: Tool, from_config: &Option<ConfigRelativePath>) -> PathBuf {\n        let tool_str = tool.as_str();\n        self.maybe_get_tool(tool_str, from_config)\n            .or_else(|| {\n                // This is an optimization to circumvent the rustup proxies\n                // which can have a significant performance hit. The goal here\n                // is to determine if calling `rustc` from PATH would end up\n                // calling the proxies.\n                //\n                // This is somewhat cautious trying to determine if it is safe\n                // to circumvent rustup, because there are some situations\n                // where users may do things like modify PATH, call cargo\n                // directly, use a custom rustup toolchain link without a\n                // cargo executable, etc. However, there is still some risk\n                // this may make the wrong decision in unusual circumstances.\n                //\n                // First, we must be running under rustup in the first place.\n                let toolchain = self.get_env_os(\"RUSTUP_TOOLCHAIN\")?;\n                // This currently does not support toolchain paths.\n                // This also enforces UTF-8.\n                if toolchain.to_str()?.contains(&['/', '\\\\']) {\n                    return None;\n                }\n                // If the tool on PATH is the same as `rustup` on path, then\n                // there is pretty good evidence that it will be a proxy.\n                let tool_resolved = paths::resolve_executable(Path::new(tool_str)).ok()?;\n                let rustup_resolved = paths::resolve_executable(Path::new(\"rustup\")).ok()?;\n                let tool_meta = tool_resolved.metadata().ok()?;\n                let rustup_meta = rustup_resolved.metadata().ok()?;\n                // This works on the assumption that rustup and its proxies\n                // use hard links to a single binary. If rustup ever changes\n                // that setup, then I think the worst consequence is that this\n                // optimization will not work, and it will take the slow path.\n                if tool_meta.len() != rustup_meta.len() {\n                    return None;\n                }\n                // Try to find the tool in rustup's toolchain directory.\n                let tool_exe = Path::new(tool_str).with_extension(env::consts::EXE_EXTENSION);\n                let toolchain_exe = home::rustup_home()\n                    .ok()?\n                    .join(\"toolchains\")\n                    .join(&toolchain)\n                    .join(\"bin\")\n                    .join(&tool_exe);\n                toolchain_exe.exists().then_some(toolchain_exe)\n            })\n            .unwrap_or_else(|| PathBuf::from(tool_str))\n    }\n\n    /// Get the `paths` overrides config value.\n    pub fn paths_overrides(&self) -> CargoResult<OptValue<Vec<(String, Definition)>>> {\n        let key = ConfigKey::from_str(\"paths\");\n        // paths overrides cannot be set via env config, so use get_cv here.\n        match self.get_cv(&key)? {\n            Some(CV::List(val, definition)) => {\n                let val = val\n                    .into_iter()\n                    .map(|cv| match cv {\n                        CV::String(s, def) => Ok((s, def)),\n                        other => self.expected(\"string\", &key, &other),\n                    })\n                    .collect::<CargoResult<Vec<_>>>()?;\n                Ok(Some(Value { val, definition }))\n            }\n            Some(val) => self.expected(\"list\", &key, &val),\n            None => Ok(None),\n        }\n    }\n\n    pub fn jobserver_from_env(&self) -> Option<&jobserver::Client> {\n        self.jobserver.as_ref()\n    }\n\n    pub fn http(&self) -> CargoResult<&Mutex<Easy>> {\n        let http = self\n            .easy\n            .try_borrow_with(|| http_handle(self).map(Into::into))?;\n        {\n            let mut http = http.lock().unwrap();\n            http.reset();\n            let timeout = configure_http_handle(self, &mut http)?;\n            timeout.configure(&mut http)?;\n        }\n        Ok(http)\n    }\n\n    pub fn http_config(&self) -> CargoResult<&CargoHttpConfig> {\n        self.http_config.try_borrow_with(|| {\n            let mut http = self.get::<CargoHttpConfig>(\"http\")?;\n            let curl_v = curl::Version::get();\n            disables_multiplexing_for_bad_curl(curl_v.version(), &mut http, self);\n            Ok(http)\n        })\n    }\n\n    pub fn future_incompat_config(&self) -> CargoResult<&CargoFutureIncompatConfig> {\n        self.future_incompat_config\n            .try_borrow_with(|| self.get::<CargoFutureIncompatConfig>(\"future-incompat-report\"))\n    }\n\n    pub fn net_config(&self) -> CargoResult<&CargoNetConfig> {\n        self.net_config\n            .try_borrow_with(|| self.get::<CargoNetConfig>(\"net\"))\n    }\n\n    pub fn build_config(&self) -> CargoResult<&CargoBuildConfig> {\n        self.build_config\n            .try_borrow_with(|| self.get::<CargoBuildConfig>(\"build\"))\n    }\n\n    pub fn progress_config(&self) -> &ProgressConfig {\n        &self.progress_config\n    }\n\n    /// Get the env vars from the config `[env]` table which\n    /// are `force = true` or don't exist in the env snapshot [`GlobalContext::get_env`].\n    pub fn env_config(&self) -> CargoResult<&Arc<HashMap<String, OsString>>> {\n        let env_config = self.env_config.try_borrow_with(|| {\n            CargoResult::Ok(Arc::new({\n                let env_config = self.get::<EnvConfig>(\"env\")?;\n                // Reasons for disallowing these values:\n                //\n                // - CARGO_HOME: The initial call to cargo does not honor this value\n                //   from the [env] table. Recursive calls to cargo would use the new\n                //   value, possibly behaving differently from the outer cargo.\n                //\n                // - RUSTUP_HOME and RUSTUP_TOOLCHAIN: Under normal usage with rustup,\n                //   this will have no effect because the rustup proxy sets\n                //   RUSTUP_HOME and RUSTUP_TOOLCHAIN, and that would override the\n                //   [env] table. If the outer cargo is executed directly\n                //   circumventing the rustup proxy, then this would affect calls to\n                //   rustc (assuming that is a proxy), which could potentially cause\n                //   problems with cargo and rustc being from different toolchains. We\n                //   consider this to be not a use case we would like to support,\n                //   since it will likely cause problems or lead to confusion.\n                for disallowed in &[\"CARGO_HOME\", \"RUSTUP_HOME\", \"RUSTUP_TOOLCHAIN\"] {\n                    if env_config.contains_key(*disallowed) {\n                        bail!(\n                            \"setting the `{disallowed}` environment variable is not supported \\\n                            in the `[env]` configuration table\"\n                        );\n                    }\n                }\n                env_config\n                    .into_iter()\n                    .filter_map(|(k, v)| {\n                        if v.is_force() || self.get_env_os(&k).is_none() {\n                            Some((k, v.resolve(self.cwd()).to_os_string()))\n                        } else {\n                            None\n                        }\n                    })\n                    .collect()\n            }))\n        })?;\n\n        Ok(env_config)\n    }\n\n    /// This is used to validate the `term` table has valid syntax.\n    ///\n    /// This is necessary because loading the term settings happens very\n    /// early, and in some situations (like `cargo version`) we don't want to\n    /// fail if there are problems with the config file.\n    pub fn validate_term_config(&self) -> CargoResult<()> {\n        drop(self.get::<TermConfig>(\"term\")?);\n        Ok(())\n    }\n\n    /// Returns a list of `target.'cfg()'` tables.\n    ///\n    /// The list is sorted by the table name.\n    pub fn target_cfgs(&self) -> CargoResult<&Vec<(String, TargetCfgConfig)>> {\n        self.target_cfgs\n            .try_borrow_with(|| target::load_target_cfgs(self))\n    }\n\n    pub fn doc_extern_map(&self) -> CargoResult<&RustdocExternMap> {\n        // Note: This does not support environment variables. The `Unit`\n        // fundamentally does not have access to the registry name, so there is\n        // nothing to query. Plumbing the name into SourceId is quite challenging.\n        self.doc_extern_map\n            .try_borrow_with(|| self.get::<RustdocExternMap>(\"doc.extern-map\"))\n    }\n\n    /// Returns true if the `[target]` table should be applied to host targets.\n    pub fn target_applies_to_host(&self) -> CargoResult<bool> {\n        target::get_target_applies_to_host(self)\n    }\n\n    /// Returns the `[host]` table definition for the given target triple.\n    pub fn host_cfg_triple(&self, target: &str) -> CargoResult<TargetConfig> {\n        target::load_host_triple(self, target)\n    }\n\n    /// Returns the `[target]` table definition for the given target triple.\n    pub fn target_cfg_triple(&self, target: &str) -> CargoResult<TargetConfig> {\n        target::load_target_triple(self, target)\n    }\n\n    /// Returns the cached [`SourceId`] corresponding to the main repository.\n    ///\n    /// This is the main cargo registry by default, but it can be overridden in\n    /// a `.cargo/config.toml`.\n    pub fn crates_io_source_id(&self) -> CargoResult<SourceId> {\n        let source_id = self.crates_io_source_id.try_borrow_with(|| {\n            self.check_registry_index_not_set()?;\n            let url = CRATES_IO_INDEX.into_url().unwrap();\n            SourceId::for_alt_registry(&url, CRATES_IO_REGISTRY)\n        })?;\n        Ok(*source_id)\n    }\n\n    pub fn creation_time(&self) -> Instant {\n        self.creation_time\n    }\n\n    /// Retrieves a config variable.\n    ///\n    /// This supports most serde `Deserialize` types. Examples:\n    ///\n    /// ```rust,ignore\n    /// let v: Option<u32> = config.get(\"some.nested.key\")?;\n    /// let v: Option<MyStruct> = config.get(\"some.key\")?;\n    /// let v: Option<HashMap<String, MyStruct>> = config.get(\"foo\")?;\n    /// ```\n    ///\n    /// The key may be a dotted key, but this does NOT support TOML key\n    /// quoting. Avoid key components that may have dots. For example,\n    /// `foo.'a.b'.bar\" does not work if you try to fetch `foo.'a.b'\". You can\n    /// fetch `foo` if it is a map, though.\n    pub fn get<'de, T: serde::de::Deserialize<'de>>(&self, key: &str) -> CargoResult<T> {\n        let d = Deserializer {\n            gctx: self,\n            key: ConfigKey::from_str(key),\n            env_prefix_ok: true,\n        };\n        T::deserialize(d).map_err(|e| e.into())\n    }\n\n    /// Obtain a [`Path`] from a [`Filesystem`], verifying that the\n    /// appropriate lock is already currently held.\n    ///\n    /// Locks are usually acquired via [`GlobalContext::acquire_package_cache_lock`]\n    /// or [`GlobalContext::try_acquire_package_cache_lock`].\n    #[track_caller]\n    #[tracing::instrument(skip_all)]\n    pub fn assert_package_cache_locked<'a>(\n        &self,\n        mode: CacheLockMode,\n        f: &'a Filesystem,\n    ) -> &'a Path {\n        let ret = f.as_path_unlocked();\n        assert!(\n            self.package_cache_lock.is_locked(mode),\n            \"package cache lock is not currently held, Cargo forgot to call \\\n             `acquire_package_cache_lock` before we got to this stack frame\",\n        );\n        assert!(ret.starts_with(self.home_path.as_path_unlocked()));\n        ret\n    }\n\n    /// Acquires a lock on the global \"package cache\", blocking if another\n    /// cargo holds the lock.\n    ///\n    /// See [`crate::util::cache_lock`] for an in-depth discussion of locking\n    /// and lock modes.\n    #[tracing::instrument(skip_all)]\n    pub fn acquire_package_cache_lock(&self, mode: CacheLockMode) -> CargoResult<CacheLock<'_>> {\n        self.package_cache_lock.lock(self, mode)\n    }\n\n    /// Acquires a lock on the global \"package cache\", returning `None` if\n    /// another cargo holds the lock.\n    ///\n    /// See [`crate::util::cache_lock`] for an in-depth discussion of locking\n    /// and lock modes.\n    #[tracing::instrument(skip_all)]\n    pub fn try_acquire_package_cache_lock(\n        &self,\n        mode: CacheLockMode,\n    ) -> CargoResult<Option<CacheLock<'_>>> {\n        self.package_cache_lock.try_lock(self, mode)\n    }\n\n    /// Returns a reference to the shared [`GlobalCacheTracker`].\n    ///\n    /// The package cache lock must be held to call this function (and to use\n    /// it in general).\n    pub fn global_cache_tracker(&self) -> CargoResult<MutexGuard<'_, GlobalCacheTracker>> {\n        let tracker = self.global_cache_tracker.try_borrow_with(|| {\n            Ok::<_, anyhow::Error>(Mutex::new(GlobalCacheTracker::new(self)?))\n        })?;\n        Ok(tracker.lock().unwrap())\n    }\n\n    /// Returns a reference to the shared [`DeferredGlobalLastUse`].\n    pub fn deferred_global_last_use(&self) -> CargoResult<MutexGuard<'_, DeferredGlobalLastUse>> {\n        let deferred = self\n            .deferred_global_last_use\n            .try_borrow_with(|| Ok::<_, anyhow::Error>(Mutex::new(DeferredGlobalLastUse::new())))?;\n        Ok(deferred.lock().unwrap())\n    }\n\n    /// Get the global [`WarningHandling`] configuration.\n    pub fn warning_handling(&self) -> CargoResult<WarningHandling> {\n        if self.unstable_flags.warnings {\n            Ok(self.build_config()?.warnings.unwrap_or_default())\n        } else {\n            Ok(WarningHandling::default())\n        }\n    }\n\n    pub fn ws_roots(&self) -> MutexGuard<'_, HashMap<PathBuf, WorkspaceRootConfig>> {\n        self.ws_roots.lock().unwrap()\n    }\n}\n\npub fn homedir(cwd: &Path) -> Option<PathBuf> {\n    ::home::cargo_home_with_cwd(cwd).ok()\n}\n\npub fn save_credentials(\n    gctx: &GlobalContext,\n    token: Option<RegistryCredentialConfig>,\n    registry: &SourceId,\n) -> CargoResult<()> {\n    let registry = if registry.is_crates_io() {\n        None\n    } else {\n        let name = registry\n            .alt_registry_key()\n            .ok_or_else(|| internal(\"can't save credentials for anonymous registry\"))?;\n        Some(name)\n    };\n\n    // If 'credentials' exists, write to that for backward compatibility reasons.\n    // Otherwise write to 'credentials.toml'. There's no need to print the\n    // warning here, because it would already be printed at load time.\n    let home_path = gctx.home_path.clone().into_path_unlocked();\n    let filename = match gctx.get_file_path(&home_path, \"credentials\", false)? {\n        Some(path) => match path.file_name() {\n            Some(filename) => Path::new(filename).to_owned(),\n            None => Path::new(\"credentials.toml\").to_owned(),\n        },\n        None => Path::new(\"credentials.toml\").to_owned(),\n    };\n\n    let mut file = {\n        gctx.home_path.create_dir()?;\n        gctx.home_path\n            .open_rw_exclusive_create(filename, gctx, \"credentials' config file\")?\n    };\n\n    let mut contents = String::new();\n    file.read_to_string(&mut contents).with_context(|| {\n        format!(\n            \"failed to read configuration file `{}`\",\n            file.path().display()\n        )\n    })?;\n\n    let mut toml = parse_document(&contents, file.path(), gctx)?;\n\n    // Move the old token location to the new one.\n    if let Some(token) = toml.remove(\"token\") {\n        let map = HashMap::from([(\"token\".to_string(), token)]);\n        toml.insert(\"registry\".into(), map.into());\n    }\n\n    if let Some(token) = token {\n        // login\n\n        let path_def = Definition::Path(file.path().to_path_buf());\n        let (key, mut value) = match token {\n            RegistryCredentialConfig::Token(token) => {\n                // login with token\n\n                let key = \"token\".to_string();\n                let value = ConfigValue::String(token.expose(), path_def.clone());\n                let map = HashMap::from([(key, value)]);\n                let table = CV::Table(map, path_def.clone());\n\n                if let Some(registry) = registry {\n                    let map = HashMap::from([(registry.to_string(), table)]);\n                    (\"registries\".into(), CV::Table(map, path_def.clone()))\n                } else {\n                    (\"registry\".into(), table)\n                }\n            }\n            RegistryCredentialConfig::AsymmetricKey((secret_key, key_subject)) => {\n                // login with key\n\n                let key = \"secret-key\".to_string();\n                let value = ConfigValue::String(secret_key.expose(), path_def.clone());\n                let mut map = HashMap::from([(key, value)]);\n                if let Some(key_subject) = key_subject {\n                    let key = \"secret-key-subject\".to_string();\n                    let value = ConfigValue::String(key_subject, path_def.clone());\n                    map.insert(key, value);\n                }\n                let table = CV::Table(map, path_def.clone());\n\n                if let Some(registry) = registry {\n                    let map = HashMap::from([(registry.to_string(), table)]);\n                    (\"registries\".into(), CV::Table(map, path_def.clone()))\n                } else {\n                    (\"registry\".into(), table)\n                }\n            }\n            _ => unreachable!(),\n        };\n\n        if registry.is_some() {\n            if let Some(table) = toml.remove(\"registries\") {\n                let v = CV::from_toml(path_def, table)?;\n                value.merge(v, false)?;\n            }\n        }\n        toml.insert(key, value.into_toml());\n    } else {\n        // logout\n        if let Some(registry) = registry {\n            if let Some(registries) = toml.get_mut(\"registries\") {\n                if let Some(reg) = registries.get_mut(registry) {\n                    let rtable = reg.as_table_mut().ok_or_else(|| {\n                        format_err!(\"expected `[registries.{}]` to be a table\", registry)\n                    })?;\n                    rtable.remove(\"token\");\n                    rtable.remove(\"secret-key\");\n                    rtable.remove(\"secret-key-subject\");\n                }\n            }\n        } else if let Some(registry) = toml.get_mut(\"registry\") {\n            let reg_table = registry\n                .as_table_mut()\n                .ok_or_else(|| format_err!(\"expected `[registry]` to be a table\"))?;\n            reg_table.remove(\"token\");\n            reg_table.remove(\"secret-key\");\n            reg_table.remove(\"secret-key-subject\");\n        }\n    }\n\n    let contents = toml.to_string();\n    file.seek(SeekFrom::Start(0))?;\n    file.write_all(contents.as_bytes())\n        .with_context(|| format!(\"failed to write to `{}`\", file.path().display()))?;\n    file.file().set_len(contents.len() as u64)?;\n    set_permissions(file.file(), 0o600)\n        .with_context(|| format!(\"failed to set permissions of `{}`\", file.path().display()))?;\n\n    return Ok(());\n\n    #[cfg(unix)]\n    fn set_permissions(file: &File, mode: u32) -> CargoResult<()> {\n        use std::os::unix::fs::PermissionsExt;\n\n        let mut perms = file.metadata()?.permissions();\n        perms.set_mode(mode);\n        file.set_permissions(perms)?;\n        Ok(())\n    }\n\n    #[cfg(not(unix))]\n    fn set_permissions(_file: &File, _mode: u32) -> CargoResult<()> {\n        Ok(())\n    }\n}\n\n/// Represents a config-include value in the configuration.\n///\n/// This intentionally doesn't derive serde deserialization\n/// to avoid any misuse of `GlobalContext::get::<ConfigInclude>()`,\n/// which might lead to wrong config loading order.\nstruct ConfigInclude {\n    /// Path to a config-include configuration file.\n    /// Could be either relative or absolute.\n    path: PathBuf,\n    def: Definition,\n    /// Whether this include is optional (missing files are silently ignored)\n    optional: bool,\n}\n\nimpl ConfigInclude {\n    fn new(p: impl Into<PathBuf>, def: Definition) -> Self {\n        Self {\n            path: p.into(),\n            def,\n            optional: false,\n        }\n    }\n\n    /// Resolves the absolute path for this include.\n    ///\n    /// For file based include,\n    /// it is relative to parent directory of the config file includes it.\n    /// For example, if `.cargo/config.toml has a `include = \"foo.toml\"`,\n    /// Cargo will load `.cargo/foo.toml`.\n    ///\n    /// For CLI based include (e.g., `--config 'include = \"foo.toml\"'`),\n    /// it is relative to the current working directory.\n    ///\n    /// Returns `None` if this is an optional include and the file doesn't exist.\n    /// Otherwise returns `Some(PathBuf)` with the absolute path.\n    fn resolve_path(&self, gctx: &GlobalContext) -> Option<PathBuf> {\n        let abs_path = match &self.def {\n            Definition::Path(p) | Definition::Cli(Some(p)) => p.parent().unwrap(),\n            Definition::Environment(_) | Definition::Cli(None) | Definition::BuiltIn => gctx.cwd(),\n        }\n        .join(&self.path);\n\n        if self.optional && !abs_path.exists() {\n            tracing::info!(\n                \"skipping optional include `{}` in `{}`:  file not found at `{}`\",\n                self.path.display(),\n                self.def,\n                abs_path.display(),\n            );\n            None\n        } else {\n            Some(abs_path)\n        }\n    }\n}\n\nfn parse_document(toml: &str, _file: &Path, _gctx: &GlobalContext) -> CargoResult<toml::Table> {\n    // At the moment, no compatibility checks are needed.\n    toml.parse().map_err(Into::into)\n}\n\nfn toml_dotted_keys(arg: &str) -> CargoResult<toml_edit::DocumentMut> {\n    // We only want to allow \"dotted key\" (see https://toml.io/en/v1.0.0#keys)\n    // expressions followed by a value that's not an \"inline table\"\n    // (https://toml.io/en/v1.0.0#inline-table). Easiest way to check for that is to\n    // parse the value as a toml_edit::DocumentMut, and check that the (single)\n    // inner-most table is set via dotted keys.\n    let doc: toml_edit::DocumentMut = arg.parse().with_context(|| {\n        format!(\"failed to parse value from --config argument `{arg}` as a dotted key expression\")\n    })?;\n    fn non_empty(d: Option<&toml_edit::RawString>) -> bool {\n        d.map_or(false, |p| !p.as_str().unwrap_or_default().trim().is_empty())\n    }\n    fn non_empty_decor(d: &toml_edit::Decor) -> bool {\n        non_empty(d.prefix()) || non_empty(d.suffix())\n    }\n    fn non_empty_key_decor(k: &toml_edit::Key) -> bool {\n        non_empty_decor(k.leaf_decor()) || non_empty_decor(k.dotted_decor())\n    }\n    let ok = {\n        let mut got_to_value = false;\n        let mut table = doc.as_table();\n        let mut is_root = true;\n        while table.is_dotted() || is_root {\n            is_root = false;\n            if table.len() != 1 {\n                break;\n            }\n            let (k, n) = table.iter().next().expect(\"len() == 1 above\");\n            match n {\n                Item::Table(nt) => {\n                    if table.key(k).map_or(false, non_empty_key_decor)\n                        || non_empty_decor(nt.decor())\n                    {\n                        bail!(\n                            \"--config argument `{arg}` \\\n                                includes non-whitespace decoration\"\n                        )\n                    }\n                    table = nt;\n                }\n                Item::Value(v) if v.is_inline_table() => {\n                    bail!(\n                        \"--config argument `{arg}` \\\n                        sets a value to an inline table, which is not accepted\"\n                    );\n                }\n                Item::Value(v) => {\n                    if table\n                        .key(k)\n                        .map_or(false, |k| non_empty(k.leaf_decor().prefix()))\n                        || non_empty_decor(v.decor())\n                    {\n                        bail!(\n                            \"--config argument `{arg}` \\\n                                includes non-whitespace decoration\"\n                        )\n                    }\n                    got_to_value = true;\n                    break;\n                }\n                Item::ArrayOfTables(_) => {\n                    bail!(\n                        \"--config argument `{arg}` \\\n                        sets a value to an array of tables, which is not accepted\"\n                    );\n                }\n\n                Item::None => {\n                    bail!(\"--config argument `{arg}` doesn't provide a value\")\n                }\n            }\n        }\n        got_to_value\n    };\n    if !ok {\n        bail!(\n            \"--config argument `{arg}` was not a TOML dotted key expression (such as `build.jobs = 2`)\"\n        );\n    }\n    Ok(doc)\n}\n\n/// A type to deserialize a list of strings from a toml file.\n///\n/// Supports deserializing either a whitespace-separated list of arguments in a\n/// single string or a string list itself. For example these deserialize to\n/// equivalent values:\n///\n/// ```toml\n/// a = 'a b c'\n/// b = ['a', 'b', 'c']\n/// ```\n#[derive(Debug, Deserialize, Clone)]\npub struct StringList(Vec<String>);\n\nimpl StringList {\n    pub fn as_slice(&self) -> &[String] {\n        &self.0\n    }\n}\n\n#[macro_export]\nmacro_rules! __shell_print {\n    ($config:expr, $which:ident, $newline:literal, $($arg:tt)*) => ({\n        let mut shell = $config.shell();\n        let out = shell.$which();\n        drop(out.write_fmt(format_args!($($arg)*)));\n        if $newline {\n            drop(out.write_all(b\"\\n\"));\n        }\n    });\n}\n\n#[macro_export]\nmacro_rules! drop_println {\n    ($config:expr) => ( $crate::drop_print!($config, \"\\n\") );\n    ($config:expr, $($arg:tt)*) => (\n        $crate::__shell_print!($config, out, true, $($arg)*)\n    );\n}\n\n#[macro_export]\nmacro_rules! drop_eprintln {\n    ($config:expr) => ( $crate::drop_eprint!($config, \"\\n\") );\n    ($config:expr, $($arg:tt)*) => (\n        $crate::__shell_print!($config, err, true, $($arg)*)\n    );\n}\n\n#[macro_export]\nmacro_rules! drop_print {\n    ($config:expr, $($arg:tt)*) => (\n        $crate::__shell_print!($config, out, false, $($arg)*)\n    );\n}\n\n#[macro_export]\nmacro_rules! drop_eprint {\n    ($config:expr, $($arg:tt)*) => (\n        $crate::__shell_print!($config, err, false, $($arg)*)\n    );\n}\n\nenum Tool {\n    Rustc,\n    Rustdoc,\n}\n\nimpl Tool {\n    fn as_str(&self) -> &str {\n        match self {\n            Tool::Rustc => \"rustc\",\n            Tool::Rustdoc => \"rustdoc\",\n        }\n    }\n}\n\n/// Disable HTTP/2 multiplexing for some broken versions of libcurl.\n///\n/// In certain versions of libcurl when proxy is in use with HTTP/2\n/// multiplexing, connections will continue stacking up. This was\n/// fixed in libcurl 8.0.0 in curl/curl@821f6e2a89de8aec1c7da3c0f381b92b2b801efc\n///\n/// However, Cargo can still link against old system libcurl if it is from a\n/// custom built one or on macOS. For those cases, multiplexing needs to be\n/// disabled when those versions are detected.\nfn disables_multiplexing_for_bad_curl(\n    curl_version: &str,\n    http: &mut CargoHttpConfig,\n    gctx: &GlobalContext,\n) {\n    use crate::util::network;\n\n    if network::proxy::http_proxy_exists(http, gctx) && http.multiplexing.is_none() {\n        let bad_curl_versions = [\"7.87.0\", \"7.88.0\", \"7.88.1\"];\n        if bad_curl_versions\n            .iter()\n            .any(|v| curl_version.starts_with(v))\n        {\n            tracing::info!(\"disabling multiplexing with proxy, curl version is {curl_version}\");\n            http.multiplexing = Some(false);\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::CargoHttpConfig;\n    use super::GlobalContext;\n    use super::Shell;\n    use super::disables_multiplexing_for_bad_curl;\n\n    #[test]\n    fn disables_multiplexing() {\n        let mut gctx = GlobalContext::new(Shell::new(), \"\".into(), \"\".into());\n        gctx.set_search_stop_path(std::path::PathBuf::new());\n        gctx.set_env(Default::default());\n\n        let mut http = CargoHttpConfig::default();\n        http.proxy = Some(\"127.0.0.1:3128\".into());\n        disables_multiplexing_for_bad_curl(\"7.88.1\", &mut http, &gctx);\n        assert_eq!(http.multiplexing, Some(false));\n\n        let cases = [\n            (None, None, \"7.87.0\", None),\n            (None, None, \"7.88.0\", None),\n            (None, None, \"7.88.1\", None),\n            (None, None, \"8.0.0\", None),\n            (Some(\"\".into()), None, \"7.87.0\", Some(false)),\n            (Some(\"\".into()), None, \"7.88.0\", Some(false)),\n            (Some(\"\".into()), None, \"7.88.1\", Some(false)),\n            (Some(\"\".into()), None, \"8.0.0\", None),\n            (Some(\"\".into()), Some(false), \"7.87.0\", Some(false)),\n            (Some(\"\".into()), Some(false), \"7.88.0\", Some(false)),\n            (Some(\"\".into()), Some(false), \"7.88.1\", Some(false)),\n            (Some(\"\".into()), Some(false), \"8.0.0\", Some(false)),\n        ];\n\n        for (proxy, multiplexing, curl_v, result) in cases {\n            let mut http = CargoHttpConfig {\n                multiplexing,\n                proxy,\n                ..Default::default()\n            };\n            disables_multiplexing_for_bad_curl(curl_v, &mut http, &gctx);\n            assert_eq!(http.multiplexing, result);\n        }\n    }\n\n    #[test]\n    fn sync_context() {\n        fn assert_sync<S: Sync>() {}\n        assert_sync::<GlobalContext>();\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/context/path.rs",
    "content": "use super::{GlobalContext, StringList, Value};\nuse regex::Regex;\nuse serde::{Deserialize, de::Error};\nuse std::path::PathBuf;\n\n/// Use with the `get` API to fetch a string that will be converted to a\n/// `PathBuf`. Relative paths are converted to absolute paths based on the\n/// location of the config file.\n#[derive(Debug, Deserialize, PartialEq, Clone)]\n#[serde(transparent)]\npub struct ConfigRelativePath(Value<String>);\n\nimpl ConfigRelativePath {\n    pub fn new(path: Value<String>) -> ConfigRelativePath {\n        ConfigRelativePath(path)\n    }\n\n    /// Returns the underlying value.\n    pub fn value(&self) -> &Value<String> {\n        &self.0\n    }\n\n    /// Returns the raw underlying configuration value for this key.\n    pub fn raw_value(&self) -> &str {\n        &self.0.val\n    }\n\n    /// Resolves this configuration-relative path to an absolute path.\n    ///\n    /// This will always return an absolute path where it's relative to the\n    /// location for configuration for this value.\n    pub fn resolve_path(&self, gctx: &GlobalContext) -> PathBuf {\n        self.0.definition.root(gctx.cwd()).join(&self.0.val)\n    }\n\n    /// Same as [`Self::resolve_path`] but will make string replacements\n    /// before resolving the path.\n    ///\n    /// `replacements` should be an [`IntoIterator`] of tuples with the \"from\" and \"to\" for the\n    /// string replacement\n    pub fn resolve_templated_path(\n        &self,\n        gctx: &GlobalContext,\n        replacements: impl IntoIterator<Item = (impl AsRef<str>, impl AsRef<str>)>,\n    ) -> Result<PathBuf, ResolveTemplateError> {\n        let mut value = self.0.val.clone();\n\n        for (from, to) in replacements {\n            value = value.replace(from.as_ref(), to.as_ref());\n        }\n\n        // Check for expected variables\n        let re = Regex::new(r\"\\{(.*)\\}\").unwrap();\n        if let Some(caps) = re.captures(&value) {\n            return Err(ResolveTemplateError::UnexpectedVariable {\n                variable: caps[1].to_string(),\n                raw_template: self.0.val.clone(),\n            });\n        };\n\n        if value.contains(\"{\") {\n            return Err(ResolveTemplateError::UnexpectedBracket {\n                bracket_type: BracketType::Opening,\n                raw_template: self.0.val.clone(),\n            });\n        }\n\n        if value.contains(\"}\") {\n            return Err(ResolveTemplateError::UnexpectedBracket {\n                bracket_type: BracketType::Closing,\n                raw_template: self.0.val.clone(),\n            });\n        }\n\n        Ok(self.0.definition.root(gctx.cwd()).join(&value))\n    }\n\n    /// Resolves this configuration-relative path to either an absolute path or\n    /// something appropriate to execute from `PATH`.\n    ///\n    /// Values which don't look like a filesystem path (don't contain `/` or\n    /// `\\`) will be returned as-is, and everything else will fall through to an\n    /// absolute path.\n    pub fn resolve_program(&self, gctx: &GlobalContext) -> PathBuf {\n        gctx.string_to_path(&self.0.val, &self.0.definition)\n    }\n}\n\n/// A config type that is a program to run.\n///\n/// This supports a list of strings like `['/path/to/program', 'somearg']`\n/// or a space separated string like `'/path/to/program somearg'`.\n///\n/// This expects the first value to be the path to the program to run.\n/// Subsequent values are strings of arguments to pass to the program.\n///\n/// Typically you should use `ConfigRelativePath::resolve_program` on the path\n/// to get the actual program.\n///\n/// **Note**: Any usage of this type in config needs to be listed in\n/// the `NON_MERGEABLE_LISTS` check to prevent list merging\n/// from multiple config files.\n#[derive(Debug, Clone, PartialEq)]\npub struct PathAndArgs {\n    pub path: ConfigRelativePath,\n    pub args: Vec<String>,\n}\n\nimpl<'de> serde::Deserialize<'de> for PathAndArgs {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        let vsl = Value::<StringList>::deserialize(deserializer)?;\n        let mut strings = vsl.val.0;\n        if strings.is_empty() {\n            return Err(D::Error::invalid_length(0, &\"at least one element\"));\n        }\n        let first = strings.remove(0);\n        let crp = Value {\n            val: first,\n            definition: vsl.definition,\n        };\n        Ok(PathAndArgs {\n            path: ConfigRelativePath(crp),\n            args: strings,\n        })\n    }\n}\n\nimpl PathAndArgs {\n    /// Construct a `PathAndArgs` from a string. The string will be split on ascii whitespace,\n    /// with the first item being treated as a `ConfigRelativePath` to the executable, and subsequent\n    /// items as arguments.\n    pub fn from_whitespace_separated_string(p: &Value<String>) -> PathAndArgs {\n        let mut iter = p.val.split_ascii_whitespace().map(str::to_string);\n        let val = iter.next().unwrap_or_default();\n        let args = iter.collect();\n        let crp = Value {\n            val,\n            definition: p.definition.clone(),\n        };\n        PathAndArgs {\n            path: ConfigRelativePath(crp),\n            args,\n        }\n    }\n}\n\n#[derive(Debug)]\npub enum ResolveTemplateError {\n    UnexpectedVariable {\n        variable: String,\n        raw_template: String,\n    },\n    UnexpectedBracket {\n        bracket_type: BracketType,\n        raw_template: String,\n    },\n}\n\n#[derive(Debug)]\npub enum BracketType {\n    Opening,\n    Closing,\n}\n"
  },
  {
    "path": "src/cargo/util/context/schema.rs",
    "content": "//! Cargo configuration schemas.\n//!\n//! This module contains types that define the schema for various configuration\n//! sections found in Cargo configuration.\n//!\n//! These types are mostly used by [`GlobalContext::get`](super::GlobalContext::get)\n//! to deserialize configuration values from TOML files, environment variables,\n//! and CLI arguments.\n//!\n//! Schema types here should only contain data and simple accessor methods.\n//! Avoid depending on [`GlobalContext`](super::GlobalContext) directly.\n\nuse std::borrow::Cow;\nuse std::collections::HashMap;\nuse std::ffi::OsStr;\n\nuse serde::Deserialize;\nuse serde_untagged::UntaggedEnumVisitor;\n\nuse std::path::Path;\n\nuse crate::CargoResult;\n\nuse super::StringList;\nuse super::Value;\nuse super::path::ConfigRelativePath;\n\n/// The `[http]` table.\n///\n/// Example configuration:\n///\n/// ```toml\n/// [http]\n/// proxy = \"host:port\"\n/// timeout = 30\n/// cainfo = \"/path/to/ca-bundle.crt\"\n/// check-revoke = true\n/// multiplexing = true\n/// ssl-version = \"tlsv1.3\"\n/// ```\n#[derive(Debug, Default, Deserialize, PartialEq)]\n#[serde(rename_all = \"kebab-case\")]\npub struct CargoHttpConfig {\n    pub proxy: Option<String>,\n    pub low_speed_limit: Option<u32>,\n    pub timeout: Option<u64>,\n    pub cainfo: Option<ConfigRelativePath>,\n    pub proxy_cainfo: Option<ConfigRelativePath>,\n    pub check_revoke: Option<bool>,\n    pub user_agent: Option<String>,\n    pub debug: Option<bool>,\n    pub multiplexing: Option<bool>,\n    pub ssl_version: Option<SslVersionConfig>,\n}\n\n/// The `[future-incompat-report]` stable\n///\n/// Example configuration:\n///\n/// ```toml\n/// [future-incompat-report]\n/// frequency = \"always\"\n/// ```\n#[derive(Debug, Default, Deserialize, PartialEq)]\n#[serde(rename_all = \"kebab-case\")]\npub struct CargoFutureIncompatConfig {\n    frequency: Option<CargoFutureIncompatFrequencyConfig>,\n}\n\n#[derive(Debug, Default, Deserialize, PartialEq)]\n#[serde(rename_all = \"kebab-case\")]\npub enum CargoFutureIncompatFrequencyConfig {\n    #[default]\n    Always,\n    Never,\n}\n\nimpl CargoFutureIncompatConfig {\n    pub fn should_display_message(&self) -> bool {\n        use CargoFutureIncompatFrequencyConfig::*;\n\n        let frequency = self.frequency.as_ref().unwrap_or(&Always);\n        match frequency {\n            Always => true,\n            Never => false,\n        }\n    }\n}\n\n/// Configuration for `ssl-version` in `http` section\n/// There are two ways to configure:\n///\n/// ```text\n/// [http]\n/// ssl-version = \"tlsv1.3\"\n/// ```\n///\n/// ```text\n/// [http]\n/// ssl-version.min = \"tlsv1.2\"\n/// ssl-version.max = \"tlsv1.3\"\n/// ```\n#[derive(Clone, Debug, PartialEq)]\npub enum SslVersionConfig {\n    Single(String),\n    Range(SslVersionConfigRange),\n}\n\nimpl<'de> Deserialize<'de> for SslVersionConfig {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        UntaggedEnumVisitor::new()\n            .string(|single| Ok(SslVersionConfig::Single(single.to_owned())))\n            .map(|map| map.deserialize().map(SslVersionConfig::Range))\n            .deserialize(deserializer)\n    }\n}\n\n#[derive(Clone, Debug, Deserialize, PartialEq)]\n#[serde(rename_all = \"kebab-case\")]\npub struct SslVersionConfigRange {\n    pub min: Option<String>,\n    pub max: Option<String>,\n}\n\n/// The `[net]` table.\n///\n/// Example configuration:\n///\n/// ```toml\n/// [net]\n/// retry = 2\n/// offline = false\n/// git-fetch-with-cli = true\n/// ```\n#[derive(Debug, Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\npub struct CargoNetConfig {\n    pub retry: Option<u32>,\n    pub offline: Option<bool>,\n    pub git_fetch_with_cli: Option<bool>,\n    pub ssh: Option<CargoSshConfig>,\n}\n\n#[derive(Debug, Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\npub struct CargoSshConfig {\n    pub known_hosts: Option<Vec<Value<String>>>,\n}\n\n/// Configuration for `jobs` in `build` section. There are two\n/// ways to configure: An integer or a simple string expression.\n///\n/// ```toml\n/// [build]\n/// jobs = 1\n/// ```\n///\n/// ```toml\n/// [build]\n/// jobs = \"default\" # Currently only support \"default\".\n/// ```\n#[derive(Debug, Clone)]\npub enum JobsConfig {\n    Integer(i32),\n    String(String),\n}\n\nimpl<'de> Deserialize<'de> for JobsConfig {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        UntaggedEnumVisitor::new()\n            .i32(|int| Ok(JobsConfig::Integer(int)))\n            .string(|string| Ok(JobsConfig::String(string.to_owned())))\n            .deserialize(deserializer)\n    }\n}\n\n/// The `[build]` table.\n///\n/// Example configuration:\n///\n/// ```toml\n/// [build]\n/// jobs = 4\n/// target = \"x86_64-unknown-linux-gnu\"\n/// target-dir = \"target\"\n/// rustflags = [\"-C\", \"link-arg=-fuse-ld=lld\"]\n/// incremental = true\n/// ```\n#[derive(Debug, Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\npub struct CargoBuildConfig {\n    // deprecated, but preserved for compatibility\n    pub pipelining: Option<bool>,\n    pub dep_info_basedir: Option<ConfigRelativePath>,\n    pub target_dir: Option<ConfigRelativePath>,\n    pub build_dir: Option<ConfigRelativePath>,\n    pub incremental: Option<bool>,\n    pub target: Option<BuildTargetConfig>,\n    pub jobs: Option<JobsConfig>,\n    pub rustflags: Option<StringList>,\n    pub rustdocflags: Option<StringList>,\n    pub rustc_wrapper: Option<ConfigRelativePath>,\n    pub rustc_workspace_wrapper: Option<ConfigRelativePath>,\n    pub rustc: Option<ConfigRelativePath>,\n    pub rustdoc: Option<ConfigRelativePath>,\n    pub artifact_dir: Option<ConfigRelativePath>,\n    pub warnings: Option<WarningHandling>,\n    /// Unstable feature `-Zsbom`.\n    pub sbom: Option<bool>,\n    /// Unstable feature `-Zbuild-analysis`.\n    pub analysis: Option<CargoBuildAnalysis>,\n}\n\n/// Metrics collection for build analysis.\n#[derive(Debug, Deserialize, Default)]\n#[serde(rename_all = \"kebab-case\")]\npub struct CargoBuildAnalysis {\n    pub enabled: bool,\n}\n\n/// Whether warnings should warn, be allowed, or cause an error.\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Default)]\n#[serde(rename_all = \"kebab-case\")]\npub enum WarningHandling {\n    #[default]\n    /// Output warnings.\n    Warn,\n    /// Allow warnings (do not output them).\n    Allow,\n    /// Error if  warnings are emitted.\n    Deny,\n}\n\n/// Configuration for `build.target`.\n///\n/// Accepts in the following forms:\n///\n/// ```toml\n/// target = \"a\"\n/// target = [\"a\"]\n/// target = [\"a\", \"b\"]\n/// ```\n#[derive(Debug, Deserialize)]\n#[serde(transparent)]\npub struct BuildTargetConfig {\n    inner: Value<BuildTargetConfigInner>,\n}\n\n#[derive(Debug)]\nenum BuildTargetConfigInner {\n    One(String),\n    Many(Vec<String>),\n}\n\nimpl<'de> Deserialize<'de> for BuildTargetConfigInner {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        UntaggedEnumVisitor::new()\n            .string(|one| Ok(BuildTargetConfigInner::One(one.to_owned())))\n            .seq(|many| many.deserialize().map(BuildTargetConfigInner::Many))\n            .deserialize(deserializer)\n    }\n}\n\nimpl BuildTargetConfig {\n    /// Gets values of `build.target` as a list of strings.\n    pub fn values(&self, cwd: &Path) -> CargoResult<Vec<String>> {\n        let map = |s: &String| {\n            if s.ends_with(\".json\") {\n                // Path to a target specification file (in JSON).\n                // <https://doc.rust-lang.org/rustc/targets/custom.html>\n                self.inner\n                    .definition\n                    .root(cwd)\n                    .join(s)\n                    .to_str()\n                    .expect(\"must be utf-8 in toml\")\n                    .to_string()\n            } else {\n                // A string. Probably a target triple.\n                s.to_string()\n            }\n        };\n        let values = match &self.inner.val {\n            BuildTargetConfigInner::One(s) => vec![map(s)],\n            BuildTargetConfigInner::Many(v) => v.iter().map(map).collect(),\n        };\n        Ok(values)\n    }\n}\n\n/// The `[resolver]` table.\n///\n/// Example configuration:\n///\n/// ```toml\n/// [resolver]\n/// incompatible-rust-versions = \"fallback\"\n/// feature-unification = \"workspace\"\n/// lockfile-path = \"my/Cargo.lock\"\n/// ```\n#[derive(Debug, Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\npub struct CargoResolverConfig {\n    pub incompatible_rust_versions: Option<IncompatibleRustVersions>,\n    pub feature_unification: Option<FeatureUnification>,\n    pub lockfile_path: Option<ConfigRelativePath>,\n}\n\n#[derive(Debug, Deserialize, PartialEq, Eq)]\n#[serde(rename_all = \"kebab-case\")]\npub enum IncompatibleRustVersions {\n    Allow,\n    Fallback,\n}\n\n#[derive(Copy, Clone, Debug, Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\npub enum FeatureUnification {\n    Package,\n    Selected,\n    Workspace,\n}\n\n/// The `[term]` table.\n///\n/// Example configuration:\n///\n/// ```toml\n/// [term]\n/// verbose = false\n/// quiet = false\n/// color = \"auto\"\n/// progress.when = \"auto\"\n/// ```\n#[derive(Debug, Deserialize, Default)]\n#[serde(rename_all = \"kebab-case\")]\npub struct TermConfig {\n    pub verbose: Option<bool>,\n    pub quiet: Option<bool>,\n    pub color: Option<String>,\n    pub hyperlinks: Option<bool>,\n    pub unicode: Option<bool>,\n    pub progress: Option<ProgressConfig>,\n}\n\n/// The `term.progress` configuration.\n///\n/// Example configuration:\n///\n/// ```toml\n/// [term]\n/// progress.when = \"never\" # or \"auto\"\n/// ```\n///\n/// ```toml\n/// # `when = \"always\"` requires a `width` field\n/// [term]\n/// progress = { when = \"always\", width = 80 }\n/// ```\n#[derive(Debug, Default)]\npub struct ProgressConfig {\n    pub when: ProgressWhen,\n    pub width: Option<usize>,\n    /// Communicate progress status with a terminal\n    pub term_integration: Option<bool>,\n}\n\n#[derive(Debug, Default, Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\npub enum ProgressWhen {\n    #[default]\n    Auto,\n    Never,\n    Always,\n}\n\n// We need this custom deserialization for validadting the rule of\n// `when = \"always\"` requiring a `width` field.\nimpl<'de> Deserialize<'de> for ProgressConfig {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        #[derive(Deserialize)]\n        #[serde(rename_all = \"kebab-case\")]\n        struct ProgressConfigInner {\n            #[serde(default)]\n            when: ProgressWhen,\n            width: Option<usize>,\n            term_integration: Option<bool>,\n        }\n\n        let pc = ProgressConfigInner::deserialize(deserializer)?;\n        if let ProgressConfigInner {\n            when: ProgressWhen::Always,\n            width: None,\n            ..\n        } = pc\n        {\n            return Err(serde::de::Error::custom(\n                \"\\\"always\\\" progress requires a `width` key\",\n            ));\n        }\n        Ok(ProgressConfig {\n            when: pc.when,\n            width: pc.width,\n            term_integration: pc.term_integration,\n        })\n    }\n}\n\n#[derive(Debug)]\nenum EnvConfigValueInner {\n    Simple(String),\n    WithOptions {\n        value: String,\n        force: bool,\n        relative: bool,\n    },\n}\n\nimpl<'de> Deserialize<'de> for EnvConfigValueInner {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        #[derive(Deserialize)]\n        struct WithOptions {\n            value: String,\n            #[serde(default)]\n            force: bool,\n            #[serde(default)]\n            relative: bool,\n        }\n\n        UntaggedEnumVisitor::new()\n            .string(|simple| Ok(EnvConfigValueInner::Simple(simple.to_owned())))\n            .map(|map| {\n                let with_options: WithOptions = map.deserialize()?;\n                Ok(EnvConfigValueInner::WithOptions {\n                    value: with_options.value,\n                    force: with_options.force,\n                    relative: with_options.relative,\n                })\n            })\n            .deserialize(deserializer)\n    }\n}\n\n/// Configuration value for environment variables in `[env]` section.\n///\n/// Supports two formats: simple string and with options.\n///\n/// ```toml\n/// [env]\n/// FOO = \"value\"\n/// ```\n///\n/// ```toml\n/// [env]\n/// BAR = { value = \"relative/path\", relative = true }\n/// BAZ = { value = \"override\", force = true }\n/// ```\n#[derive(Debug, Deserialize)]\n#[serde(transparent)]\npub struct EnvConfigValue {\n    inner: Value<EnvConfigValueInner>,\n}\n\nimpl EnvConfigValue {\n    /// Whether this value should override existing environment variables.\n    pub fn is_force(&self) -> bool {\n        match self.inner.val {\n            EnvConfigValueInner::Simple(_) => false,\n            EnvConfigValueInner::WithOptions { force, .. } => force,\n        }\n    }\n\n    /// Resolves the environment variable value.\n    ///\n    /// If `relative = true`,\n    /// the value is interpreted as a [`ConfigRelativePath`]-like path.\n    pub fn resolve<'a>(&'a self, cwd: &Path) -> Cow<'a, OsStr> {\n        match self.inner.val {\n            EnvConfigValueInner::Simple(ref s) => Cow::Borrowed(OsStr::new(s.as_str())),\n            EnvConfigValueInner::WithOptions {\n                ref value,\n                relative,\n                ..\n            } => {\n                if relative {\n                    let p = self.inner.definition.root(cwd).join(&value);\n                    Cow::Owned(p.into_os_string())\n                } else {\n                    Cow::Borrowed(OsStr::new(value.as_str()))\n                }\n            }\n        }\n    }\n}\n\npub type EnvConfig = HashMap<String, EnvConfigValue>;\n"
  },
  {
    "path": "src/cargo/util/context/target.rs",
    "content": "use super::{CV, ConfigKey, ConfigRelativePath, GlobalContext, OptValue, PathAndArgs, StringList};\nuse crate::core::compiler::{BuildOutput, LibraryPath, LinkArgTarget};\nuse crate::util::CargoResult;\nuse serde::Deserialize;\nuse std::collections::{BTreeMap, HashMap};\nuse std::path::{Path, PathBuf};\nuse std::rc::Rc;\n\n/// Config definition of a `[target.'cfg(…)']` table.\n///\n/// This is a subset of `TargetConfig`.\n#[derive(Debug, Deserialize)]\npub struct TargetCfgConfig {\n    pub runner: OptValue<PathAndArgs>,\n    pub rustflags: OptValue<StringList>,\n    pub linker: OptValue<ConfigRelativePath>,\n    // This is here just to ignore fields from normal `TargetConfig` because\n    // all `[target]` tables are getting deserialized, whether they start with\n    // `cfg(` or not.\n    #[serde(flatten)]\n    pub other: BTreeMap<String, toml::Value>,\n}\n\n/// Config definition of a `[target]` table or `[host]`.\n#[derive(Debug, Clone, Default)]\npub struct TargetConfig {\n    /// Process to run as a wrapper for `cargo run`, `test`, and `bench` commands.\n    pub runner: OptValue<PathAndArgs>,\n    /// Additional rustc flags to pass.\n    pub rustflags: OptValue<StringList>,\n    /// Additional rustdoc flags to pass.\n    pub rustdocflags: OptValue<StringList>,\n    /// The path of the linker for this target.\n    pub linker: OptValue<ConfigRelativePath>,\n    /// Build script override for the given library name.\n    ///\n    /// Any package with a `links` value for the given library name will skip\n    /// running its build script and instead use the given output from the\n    /// config file.\n    pub links_overrides: Rc<BTreeMap<String, BuildOutput>>,\n}\n\n/// Loads all of the `target.'cfg()'` tables.\npub(super) fn load_target_cfgs(\n    gctx: &GlobalContext,\n) -> CargoResult<Vec<(String, TargetCfgConfig)>> {\n    // Load all [target] tables, filter out the cfg() entries.\n    let mut result = Vec::new();\n    // Use a BTreeMap so the keys are sorted. This is important for\n    // deterministic ordering of rustflags, which affects fingerprinting and\n    // rebuilds. We may perhaps one day wish to ensure a deterministic\n    // ordering via the order keys were defined in files perhaps.\n    let target: BTreeMap<String, TargetCfgConfig> = gctx.get(\"target\")?;\n    tracing::debug!(\"Got all targets {:#?}\", target);\n    for (key, cfg) in target {\n        if let Ok(platform) = key.parse::<cargo_platform::Platform>() {\n            let mut warnings = Vec::new();\n            platform.check_cfg_keywords(&mut warnings, &Path::new(\".cargo/config.toml\"));\n            for w in warnings {\n                gctx.shell().warn(w)?;\n            }\n        }\n        if key.starts_with(\"cfg(\") {\n            // Unfortunately this is not able to display the location of the\n            // unused key. Using config::Value<toml::Value> doesn't work. One\n            // solution might be to create a special \"Any\" type, but I think\n            // that will be quite difficult with the current design.\n            for other_key in cfg.other.keys() {\n                gctx.shell().warn(format!(\n                    \"unused key `{}` in [target] config table `{}`\",\n                    other_key, key\n                ))?;\n            }\n            result.push((key, cfg));\n        }\n    }\n    Ok(result)\n}\n\n/// Returns true if the `[target]` table should be applied to host targets.\npub(super) fn get_target_applies_to_host(gctx: &GlobalContext) -> CargoResult<bool> {\n    if gctx.cli_unstable().target_applies_to_host {\n        if let Ok(target_applies_to_host) = gctx.get::<bool>(\"target-applies-to-host\") {\n            Ok(target_applies_to_host)\n        } else {\n            Ok(!gctx.cli_unstable().host_config)\n        }\n    } else if gctx.cli_unstable().host_config {\n        anyhow::bail!(\n            \"the -Zhost-config flag requires the -Ztarget-applies-to-host flag to be set\"\n        );\n    } else {\n        Ok(true)\n    }\n}\n\n/// Loads a single `[host]` table for the given triple.\npub(super) fn load_host_triple(gctx: &GlobalContext, triple: &str) -> CargoResult<TargetConfig> {\n    if gctx.cli_unstable().host_config {\n        let host_triple_prefix = format!(\"host.{}\", triple);\n        let host_triple_key = ConfigKey::from_str(&host_triple_prefix);\n        let host_prefix = match gctx.get_cv(&host_triple_key)? {\n            Some(_) => host_triple_prefix,\n            None => \"host\".to_string(),\n        };\n        load_config_table(gctx, &host_prefix)\n    } else {\n        Ok(TargetConfig::default())\n    }\n}\n\n/// Loads a single `[target]` table for the given triple.\npub(super) fn load_target_triple(gctx: &GlobalContext, triple: &str) -> CargoResult<TargetConfig> {\n    load_config_table(gctx, &format!(\"target.{}\", triple))\n}\n\n/// Loads a single table for the given prefix.\nfn load_config_table(gctx: &GlobalContext, prefix: &str) -> CargoResult<TargetConfig> {\n    // This needs to get each field individually because it cannot fetch the\n    // struct all at once due to `links_overrides`. Can't use `serde(flatten)`\n    // because it causes serde to use `deserialize_map` which means the config\n    // deserializer does not know which keys to deserialize, which means\n    // environment variables would not work.\n    let runner: OptValue<PathAndArgs> = gctx.get(&format!(\"{prefix}.runner\"))?;\n    let rustflags: OptValue<StringList> = gctx.get(&format!(\"{prefix}.rustflags\"))?;\n    let rustdocflags: OptValue<StringList> = gctx.get(&format!(\"{prefix}.rustdocflags\"))?;\n    let linker: OptValue<ConfigRelativePath> = gctx.get(&format!(\"{prefix}.linker\"))?;\n    // Links do not support environment variables.\n    let target_key = ConfigKey::from_str(prefix);\n    let links_overrides = match gctx.get_table(&target_key)? {\n        Some(links) => parse_links_overrides(&target_key, links.val)?,\n        None => BTreeMap::new(),\n    };\n    Ok(TargetConfig {\n        runner,\n        rustflags,\n        rustdocflags,\n        linker,\n        links_overrides: Rc::new(links_overrides),\n    })\n}\n\nfn parse_links_overrides(\n    target_key: &ConfigKey,\n    links: HashMap<String, CV>,\n) -> CargoResult<BTreeMap<String, BuildOutput>> {\n    let mut links_overrides = BTreeMap::new();\n\n    for (lib_name, value) in links {\n        // Skip these keys, it shares the namespace with `TargetConfig`.\n        match lib_name.as_str() {\n            // `ar` is a historical thing.\n            \"ar\" | \"linker\" | \"runner\" | \"rustflags\" | \"rustdocflags\" => continue,\n            _ => {}\n        }\n        let mut output = BuildOutput::default();\n        let table = value.table(&format!(\"{}.{}\", target_key, lib_name))?.0;\n        // We require deterministic order of evaluation, so we must sort the pairs by key first.\n        let mut pairs = Vec::new();\n        for (k, value) in table {\n            pairs.push((k, value));\n        }\n        pairs.sort_by_key(|p| p.0);\n        for (key, value) in pairs {\n            match key.as_str() {\n                \"rustc-flags\" => {\n                    let flags = value.string(key)?;\n                    let whence = format!(\"target config `{}.{}` (in {})\", target_key, key, flags.1);\n                    let (paths, links) = BuildOutput::parse_rustc_flags(flags.0, &whence)?;\n                    output\n                        .library_paths\n                        .extend(paths.into_iter().map(LibraryPath::External));\n                    output.library_links.extend(links);\n                }\n                \"rustc-link-lib\" => {\n                    let list = value.string_list(key)?;\n                    output\n                        .library_links\n                        .extend(list.iter().map(|v| v.0.clone()));\n                }\n                \"rustc-link-search\" => {\n                    let list = value.string_list(key)?;\n                    output.library_paths.extend(\n                        list.iter()\n                            .map(|v| PathBuf::from(&v.0))\n                            .map(LibraryPath::External),\n                    );\n                }\n                \"rustc-link-arg-cdylib\" | \"rustc-cdylib-link-arg\" => {\n                    let args = extra_link_args(LinkArgTarget::Cdylib, key, value)?;\n                    output.linker_args.extend(args);\n                }\n                \"rustc-link-arg-bins\" => {\n                    let args = extra_link_args(LinkArgTarget::Bin, key, value)?;\n                    output.linker_args.extend(args);\n                }\n                \"rustc-link-arg\" => {\n                    let args = extra_link_args(LinkArgTarget::All, key, value)?;\n                    output.linker_args.extend(args);\n                }\n                \"rustc-link-arg-tests\" => {\n                    let args = extra_link_args(LinkArgTarget::Test, key, value)?;\n                    output.linker_args.extend(args);\n                }\n                \"rustc-link-arg-benches\" => {\n                    let args = extra_link_args(LinkArgTarget::Bench, key, value)?;\n                    output.linker_args.extend(args);\n                }\n                \"rustc-link-arg-examples\" => {\n                    let args = extra_link_args(LinkArgTarget::Example, key, value)?;\n                    output.linker_args.extend(args);\n                }\n                \"rustc-cfg\" => {\n                    let list = value.string_list(key)?;\n                    output.cfgs.extend(list.iter().map(|v| v.0.clone()));\n                }\n                \"rustc-check-cfg\" => {\n                    let list = value.string_list(key)?;\n                    output.check_cfgs.extend(list.iter().map(|v| v.0.clone()));\n                }\n                \"rustc-env\" => {\n                    for (name, val) in value.table(key)?.0 {\n                        let val = val.string(name)?.0;\n                        output.env.push((name.clone(), val.to_string()));\n                    }\n                }\n                \"warning\" | \"rerun-if-changed\" | \"rerun-if-env-changed\" => {\n                    anyhow::bail!(\"`{}` is not supported in build script overrides\", key);\n                }\n                _ => {\n                    let val = value.string(key)?.0;\n                    output.metadata.push((key.clone(), val.to_string()));\n                }\n            }\n        }\n        links_overrides.insert(lib_name, output);\n    }\n    Ok(links_overrides)\n}\n\nfn extra_link_args(\n    link_type: LinkArgTarget,\n    key: &str,\n    value: &CV,\n) -> CargoResult<Vec<(LinkArgTarget, String)>> {\n    let args = value.string_list(key)?;\n    Ok(args.into_iter().map(|v| (link_type.clone(), v.0)).collect())\n}\n"
  },
  {
    "path": "src/cargo/util/context/value.rs",
    "content": "//! Deserialization of a [`Value<T>`] type which tracks where it was deserialized from.\n//!\n//! ## Rationale for `Value<T>`\n//!\n//! Often Cargo wants to report semantic error information or other sorts of\n//! error information about configuration keys but it also may wish to indicate\n//! as an error context where the key was defined as well (to help user\n//! debugging). The `Value<T>` type here can be used to deserialize a `T` value\n//! from configuration, but also record where it was deserialized from when it\n//! was read.\n//!\n//! Deserializing `Value<T>` is pretty special, and serde doesn't have built-in\n//! support for this operation. To implement this we extend serde's \"data model\"\n//! a bit. We configure deserialization of `Value<T>` to basically only work with\n//! our one deserializer using configuration.\n//!\n//! ## How `Value<T>` deserialization works\n//!\n//! `Value<T>` uses a custom protocol to inject source location information\n//! into serde's deserialization process:\n//!\n//! **Magic identifiers**: `Value<T>::deserialize` requests a struct with special\n//! [name](NAME) and [field names](FIELDS) that use invalid Rust syntax to avoid\n//! conflicts. This signals to Cargo's deserializer that location tracking is needed.\n//!\n//! **Custom deserializer response**: When Cargo's deserializer sees these magic\n//! identifiers, it switches to `ValueDeserializer` (from the [`de`] module)\n//! instead of normal struct deserialization.\n//!\n//! **Two-field protocol**: `ValueDeserializer` presents exactly two fields\n//! through map visiting:\n//! * The actual value (deserialized normally)\n//! * The definition context (encoded as a `(u32, String)` tuple acting as a\n//!   tagged union of [`Definition`] variants)\n//!\n//! This allows `Value<T>` to capture both the deserialized data and where it\n//! came from.\n//!\n//! **Note**: When modifying [`Definition`] variants, be sure to update both\n//! the `Definition::deserialize` implementation here and the\n//! `MapAccess::next_value_seed` implementation in `ValueDeserializer`.\n//!\n//! [`de`]: crate::util::context::de\n\nuse serde::de;\nuse std::cmp::Ordering;\nuse std::fmt;\nuse std::marker;\nuse std::mem;\nuse std::path::{Path, PathBuf};\n\n/// A type which can be deserialized as a configuration value which records\n/// where it was deserialized from.\n#[derive(Debug, PartialEq, Clone)]\npub struct Value<T> {\n    /// The inner value that was deserialized.\n    pub val: T,\n    /// The location where `val` was defined in configuration (e.g. file it was\n    /// defined in, env var etc).\n    pub definition: Definition,\n}\n\npub type OptValue<T> = Option<Value<T>>;\n\n// The names below are intended to be invalid Rust identifiers\n// to avoid conflicts with other valid structures.\npub(crate) const VALUE_FIELD: &str = \"$__cargo_private_value\";\npub(crate) const DEFINITION_FIELD: &str = \"$__cargo_private_definition\";\npub(crate) const NAME: &str = \"$__cargo_private_Value\";\npub(crate) static FIELDS: [&str; 2] = [VALUE_FIELD, DEFINITION_FIELD];\n\n/// Location where a config value is defined.\n#[derive(Clone, Debug, Eq)]\npub enum Definition {\n    BuiltIn,\n    /// Defined in a `.cargo/config`, includes the path to the file.\n    Path(PathBuf),\n    /// Defined in an environment variable, includes the environment key.\n    Environment(String),\n    /// Passed in on the command line.\n    /// A path is attached when the config value is a path to a config file.\n    Cli(Option<PathBuf>),\n}\n\nimpl PartialOrd for Definition {\n    fn partial_cmp(&self, other: &Definition) -> Option<Ordering> {\n        Some(self.cmp(other))\n    }\n}\n\nimpl Ord for Definition {\n    fn cmp(&self, other: &Definition) -> Ordering {\n        if mem::discriminant(self) == mem::discriminant(other) {\n            Ordering::Equal\n        } else if self.is_higher_priority(other) {\n            Ordering::Greater\n        } else {\n            Ordering::Less\n        }\n    }\n}\n\nimpl Definition {\n    /// Root directory where this is defined.\n    ///\n    /// If from a file, it is the directory above `.cargo/config.toml`.\n    /// CLI and env use the provided current working directory.\n    pub fn root<'a>(&'a self, cwd: &'a Path) -> &'a Path {\n        match self {\n            Definition::Path(p) | Definition::Cli(Some(p)) => p.parent().unwrap().parent().unwrap(),\n            Definition::Environment(_) | Definition::Cli(None) | Definition::BuiltIn => cwd,\n        }\n    }\n\n    /// Returns true if self is a higher priority to other.\n    ///\n    /// CLI is preferred over environment, which is preferred over files.\n    pub fn is_higher_priority(&self, other: &Definition) -> bool {\n        matches!(\n            (self, other),\n            (Definition::Cli(_), Definition::Environment(_))\n                | (Definition::Cli(_), Definition::Path(_))\n                | (Definition::Cli(_), Definition::BuiltIn)\n                | (Definition::Environment(_), Definition::Path(_))\n                | (Definition::Environment(_), Definition::BuiltIn)\n                | (Definition::Path(_), Definition::BuiltIn)\n        )\n    }\n}\n\nimpl PartialEq for Definition {\n    fn eq(&self, other: &Definition) -> bool {\n        // configuration values are equivalent no matter where they're defined,\n        // but they need to be defined in the same location. For example if\n        // they're defined in the environment that's different than being\n        // defined in a file due to path interpretations.\n        mem::discriminant(self) == mem::discriminant(other)\n    }\n}\n\nimpl fmt::Display for Definition {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            Definition::Path(p) | Definition::Cli(Some(p)) => p.display().fmt(f),\n            Definition::Environment(key) => write!(f, \"environment variable `{}`\", key),\n            Definition::Cli(None) => write!(f, \"--config cli option\"),\n            Definition::BuiltIn => write!(f, \"default\"),\n        }\n    }\n}\n\nimpl<T> From<T> for Value<T> {\n    fn from(val: T) -> Self {\n        Self {\n            val,\n            definition: Definition::BuiltIn,\n        }\n    }\n}\n\nimpl<'de, T> de::Deserialize<'de> for Value<T>\nwhere\n    T: de::Deserialize<'de>,\n{\n    fn deserialize<D>(deserializer: D) -> Result<Value<T>, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        struct ValueVisitor<T> {\n            _marker: marker::PhantomData<T>,\n        }\n\n        impl<'de, T> de::Visitor<'de> for ValueVisitor<T>\n        where\n            T: de::Deserialize<'de>,\n        {\n            type Value = Value<T>;\n\n            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n                formatter.write_str(\"a value\")\n            }\n\n            fn visit_map<V>(self, mut visitor: V) -> Result<Value<T>, V::Error>\n            where\n                V: de::MapAccess<'de>,\n            {\n                let value = visitor.next_key::<ValueKey>()?;\n                if value.is_none() {\n                    return Err(de::Error::custom(\"value not found\"));\n                }\n                let val: T = visitor.next_value()?;\n\n                let definition = visitor.next_key::<DefinitionKey>()?;\n                if definition.is_none() {\n                    return Err(de::Error::custom(\"definition not found\"));\n                }\n                let definition: Definition = visitor.next_value()?;\n                Ok(Value { val, definition })\n            }\n        }\n\n        deserializer.deserialize_struct(\n            NAME,\n            &FIELDS,\n            ValueVisitor {\n                _marker: marker::PhantomData,\n            },\n        )\n    }\n}\n\nstruct FieldVisitor {\n    expected: &'static str,\n}\n\nimpl<'de> de::Visitor<'de> for FieldVisitor {\n    type Value = ();\n\n    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {\n        formatter.write_str(\"a valid value field\")\n    }\n\n    fn visit_str<E>(self, s: &str) -> Result<(), E>\n    where\n        E: de::Error,\n    {\n        if s == self.expected {\n            Ok(())\n        } else {\n            Err(de::Error::custom(\"expected field with custom name\"))\n        }\n    }\n}\n\nstruct ValueKey;\n\nimpl<'de> de::Deserialize<'de> for ValueKey {\n    fn deserialize<D>(deserializer: D) -> Result<ValueKey, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        deserializer.deserialize_identifier(FieldVisitor {\n            expected: VALUE_FIELD,\n        })?;\n        Ok(ValueKey)\n    }\n}\n\nstruct DefinitionKey;\n\nimpl<'de> de::Deserialize<'de> for DefinitionKey {\n    fn deserialize<D>(deserializer: D) -> Result<DefinitionKey, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        deserializer.deserialize_identifier(FieldVisitor {\n            expected: DEFINITION_FIELD,\n        })?;\n        Ok(DefinitionKey)\n    }\n}\n\nimpl<'de> de::Deserialize<'de> for Definition {\n    fn deserialize<D>(deserializer: D) -> Result<Definition, D::Error>\n    where\n        D: de::Deserializer<'de>,\n    {\n        let (discr, value) = <(u32, String)>::deserialize(deserializer)?;\n        match discr {\n            0 => Ok(Definition::BuiltIn),\n            1 => Ok(Definition::Path(value.into())),\n            2 => Ok(Definition::Environment(value)),\n            3 => {\n                let path = (value.len() > 0).then_some(value.into());\n                Ok(Definition::Cli(path))\n            }\n            _ => panic!(\"unexpected discriminant {discr} value {value}\"),\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/counter.rs",
    "content": "use std::time::Instant;\n\n/// A metrics counter storing only latest `N` records.\npub struct MetricsCounter<const N: usize> {\n    /// Slots to store metrics.\n    slots: [(usize, Instant); N],\n    /// The slot of the oldest record.\n    /// Also the next slot to store the new record.\n    index: usize,\n}\n\nimpl<const N: usize> MetricsCounter<N> {\n    /// Creates a new counter with an initial value.\n    pub fn new(init: usize, init_at: Instant) -> Self {\n        assert!(N > 0, \"number of slots must be greater than zero\");\n        Self {\n            slots: [(init, init_at); N],\n            index: 0,\n        }\n    }\n\n    /// Adds record to the counter.\n    pub fn add(&mut self, data: usize, added_at: Instant) {\n        self.slots[self.index] = (data, added_at);\n        self.index = (self.index + 1) % N;\n    }\n\n    /// Calculates per-second average rate of all slots.\n    pub fn rate(&self) -> f32 {\n        let latest = self.slots[self.index.checked_sub(1).unwrap_or(N - 1)];\n        let oldest = self.slots[self.index];\n        let duration = (latest.1 - oldest.1).as_secs_f32();\n        let avg = (latest.0 - oldest.0) as f32 / duration;\n        if f32::is_nan(avg) { 0f32 } else { avg }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::MetricsCounter;\n    use std::time::{Duration, Instant};\n\n    #[test]\n    fn counter() {\n        let now = Instant::now();\n        let mut counter = MetricsCounter::<3>::new(0, now);\n        assert_eq!(counter.rate(), 0f32);\n        counter.add(1, now + Duration::from_secs(1));\n        assert_eq!(counter.rate(), 1f32);\n        counter.add(4, now + Duration::from_secs(2));\n        assert_eq!(counter.rate(), 2f32);\n        counter.add(7, now + Duration::from_secs(3));\n        assert_eq!(counter.rate(), 3f32);\n        counter.add(12, now + Duration::from_secs(4));\n        assert_eq!(counter.rate(), 4f32);\n    }\n\n    #[test]\n    #[should_panic(expected = \"number of slots must be greater than zero\")]\n    fn counter_zero_slot() {\n        let _counter = MetricsCounter::<0>::new(0, Instant::now());\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/cpu.rs",
    "content": "use std::io;\n\npub struct State(imp::State);\n\nimpl State {\n    /// Captures the current state of all CPUs on the system.\n    ///\n    /// The `State` returned here isn't too meaningful in terms of\n    /// interpretation across platforms, but it can be compared to previous\n    /// states to get a meaningful cross-platform number.\n    pub fn current() -> io::Result<State> {\n        imp::current().map(State)\n    }\n\n    /// Returns the percentage of time CPUs were idle from the current state\n    /// relative to the previous state, as a percentage from 0.0 to 100.0.\n    ///\n    /// This function will return, as a percentage, the amount of time that the\n    /// entire system was idle between the `previous` state and this own state.\n    /// This can be useful to compare two snapshots in time of CPU usage to see\n    /// how the CPU usage compares between the two.\n    pub fn idle_since(&self, previous: &State) -> f64 {\n        imp::pct_idle(&previous.0, &self.0)\n    }\n}\n\n#[cfg(target_os = \"linux\")]\nmod imp {\n    use std::{fs, io};\n\n    pub struct State {\n        user: u64,\n        nice: u64,\n        system: u64,\n        idle: u64,\n        iowait: u64,\n        irq: u64,\n        softirq: u64,\n        steal: u64,\n        guest: u64,\n        guest_nice: u64,\n    }\n\n    pub fn current() -> io::Result<State> {\n        let state = fs::read_to_string(\"/proc/stat\")?;\n\n        (|| {\n            let mut parts = state.lines().next()?.split_whitespace();\n            if parts.next()? != \"cpu\" {\n                return None;\n            }\n            Some(State {\n                user: parts.next()?.parse::<u64>().ok()?,\n                nice: parts.next()?.parse::<u64>().ok()?,\n                system: parts.next()?.parse::<u64>().ok()?,\n                idle: parts.next()?.parse::<u64>().ok()?,\n                iowait: parts.next()?.parse::<u64>().ok()?,\n                irq: parts.next()?.parse::<u64>().ok()?,\n                softirq: parts.next()?.parse::<u64>().ok()?,\n                steal: parts.next()?.parse::<u64>().ok()?,\n                guest: parts.next()?.parse::<u64>().ok()?,\n                guest_nice: parts.next()?.parse::<u64>().ok()?,\n            })\n        })()\n        .ok_or_else(|| io::Error::new(io::ErrorKind::Other, \"first line of /proc/stat malformed\"))\n    }\n\n    pub fn pct_idle(prev: &State, next: &State) -> f64 {\n        let user = next.user - prev.user;\n        let nice = next.nice - prev.nice;\n        let system = next.system - prev.system;\n        let idle = next.idle - prev.idle;\n        let iowait = next.iowait.saturating_sub(prev.iowait);\n        let irq = next.irq - prev.irq;\n        let softirq = next.softirq - prev.softirq;\n        let steal = next.steal - prev.steal;\n        let guest = next.guest - prev.guest;\n        let guest_nice = next.guest_nice - prev.guest_nice;\n        let total =\n            user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice;\n\n        (idle as f64) / (total as f64) * 100.0\n    }\n}\n\n#[cfg(target_os = \"macos\")]\n#[allow(bad_style)]\nmod imp {\n    use std::io;\n    use std::ptr;\n\n    type host_t = u32;\n    type mach_port_t = u32;\n    type vm_map_t = mach_port_t;\n    type vm_offset_t = usize;\n    type vm_size_t = usize;\n    type vm_address_t = vm_offset_t;\n    type processor_flavor_t = i32;\n    type natural_t = u32;\n    type processor_info_array_t = *mut i32;\n    type mach_msg_type_number_t = i32;\n    type kern_return_t = i32;\n\n    const PROESSOR_CPU_LOAD_INFO: processor_flavor_t = 2;\n    const CPU_STATE_USER: usize = 0;\n    const CPU_STATE_SYSTEM: usize = 1;\n    const CPU_STATE_IDLE: usize = 2;\n    const CPU_STATE_NICE: usize = 3;\n    const CPU_STATE_MAX: usize = 4;\n\n    unsafe extern \"C\" {\n        static mut mach_task_self_: mach_port_t;\n\n        fn mach_host_self() -> mach_port_t;\n        fn host_processor_info(\n            host: host_t,\n            flavor: processor_flavor_t,\n            out_processor_count: *mut natural_t,\n            out_processor_info: *mut processor_info_array_t,\n            out_processor_infoCnt: *mut mach_msg_type_number_t,\n        ) -> kern_return_t;\n        fn vm_deallocate(\n            target_task: vm_map_t,\n            address: vm_address_t,\n            size: vm_size_t,\n        ) -> kern_return_t;\n    }\n\n    pub struct State {\n        user: u64,\n        system: u64,\n        idle: u64,\n        nice: u64,\n    }\n\n    #[repr(C)]\n    struct processor_cpu_load_info_data_t {\n        cpu_ticks: [u32; CPU_STATE_MAX],\n    }\n\n    pub fn current() -> io::Result<State> {\n        // There's scant little documentation on `host_processor_info`\n        // throughout the internet, so this is just modeled after what everyone\n        // else is doing. For now this is modeled largely after libuv.\n\n        unsafe {\n            let mut num_cpus_u = 0;\n            let mut cpu_info = ptr::null_mut();\n            let mut msg_type = 0;\n            let err = host_processor_info(\n                mach_host_self(),\n                PROESSOR_CPU_LOAD_INFO,\n                &mut num_cpus_u,\n                &mut cpu_info,\n                &mut msg_type,\n            );\n            if err != 0 {\n                return Err(io::Error::last_os_error());\n            }\n            let mut ret = State {\n                user: 0,\n                system: 0,\n                idle: 0,\n                nice: 0,\n            };\n            let mut current = cpu_info as *const processor_cpu_load_info_data_t;\n            for _ in 0..num_cpus_u {\n                ret.user += (*current).cpu_ticks[CPU_STATE_USER] as u64;\n                ret.system += (*current).cpu_ticks[CPU_STATE_SYSTEM] as u64;\n                ret.idle += (*current).cpu_ticks[CPU_STATE_IDLE] as u64;\n                ret.nice += (*current).cpu_ticks[CPU_STATE_NICE] as u64;\n                current = current.offset(1);\n            }\n            vm_deallocate(mach_task_self_, cpu_info as vm_address_t, msg_type as usize);\n            Ok(ret)\n        }\n    }\n\n    pub fn pct_idle(prev: &State, next: &State) -> f64 {\n        let user = next.user - prev.user;\n        let system = next.system - prev.system;\n        let idle = next.idle - prev.idle;\n        let nice = next.nice - prev.nice;\n        let total = user + system + idle + nice;\n        (idle as f64) / (total as f64) * 100.0\n    }\n}\n\n#[cfg(windows)]\nmod imp {\n    use std::io;\n    use std::mem;\n\n    use windows_sys::Win32::Foundation::FILETIME;\n    use windows_sys::Win32::System::Threading::GetSystemTimes;\n\n    pub struct State {\n        idle: FILETIME,\n        kernel: FILETIME,\n        user: FILETIME,\n    }\n\n    pub fn current() -> io::Result<State> {\n        unsafe {\n            let mut ret = mem::zeroed::<State>();\n            let r = GetSystemTimes(&mut ret.idle, &mut ret.kernel, &mut ret.user);\n            if r != 0 {\n                Ok(ret)\n            } else {\n                Err(io::Error::last_os_error())\n            }\n        }\n    }\n\n    pub fn pct_idle(prev: &State, next: &State) -> f64 {\n        fn to_u64(a: &FILETIME) -> u64 {\n            ((a.dwHighDateTime as u64) << 32) | (a.dwLowDateTime as u64)\n        }\n\n        let idle = to_u64(&next.idle) - to_u64(&prev.idle);\n        let kernel = to_u64(&next.kernel) - to_u64(&prev.kernel);\n        let user = to_u64(&next.user) - to_u64(&prev.user);\n        let total = user + kernel;\n        (idle as f64) / (total as f64) * 100.0\n    }\n}\n\n#[cfg(not(any(target_os = \"linux\", target_os = \"macos\", windows)))]\nmod imp {\n    use std::io;\n\n    pub struct State;\n\n    pub fn current() -> io::Result<State> {\n        Err(io::Error::new(\n            io::ErrorKind::Other,\n            \"unsupported platform to learn CPU state\",\n        ))\n    }\n\n    pub fn pct_idle(_prev: &State, _next: &State) -> f64 {\n        unimplemented!()\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/credential/adaptor.rs",
    "content": "//! Credential provider that launches an external process that only outputs a credential\n\nuse std::{\n    io::Read,\n    process::{Command, Stdio},\n};\n\nuse anyhow::Context;\nuse cargo_credential::{\n    Action, CacheControl, Credential, CredentialResponse, RegistryInfo, Secret,\n};\n\npub struct BasicProcessCredential {}\n\nimpl Credential for BasicProcessCredential {\n    fn perform(\n        &self,\n        registry: &RegistryInfo<'_>,\n        action: &Action<'_>,\n        args: &[&str],\n    ) -> Result<CredentialResponse, cargo_credential::Error> {\n        match action {\n            Action::Get(_) => {\n                let mut args = args.iter();\n                let exe = args.next()\n                    .ok_or(\"The first argument to `cargo:token-from-stdout` must be a command that prints a token on stdout\")?;\n                let args = args.map(|arg| arg.replace(\"{index_url}\", registry.index_url));\n\n                let mut cmd = Command::new(exe);\n                cmd.args(args)\n                    .env(\"CARGO_REGISTRY_INDEX_URL\", registry.index_url);\n                if let Some(name) = registry.name {\n                    cmd.env(\"CARGO_REGISTRY_NAME_OPT\", name);\n                }\n                cmd.stdout(Stdio::piped());\n                let mut child = cmd.spawn().context(\"failed to spawn credential process\")?;\n                let mut buffer = String::new();\n                child\n                    .stdout\n                    .take()\n                    .unwrap()\n                    .read_to_string(&mut buffer)\n                    .context(\"failed to read from credential provider\")?;\n                if let Some(end) = buffer.find('\\n') {\n                    if buffer.len() > end + 1 {\n                        return Err(format!(\n                            \"process `{}` returned more than one line of output; \\\n                            expected a single token\",\n                            exe\n                        )\n                        .into());\n                    }\n                    buffer.truncate(end);\n                }\n                let status = child.wait().context(\"credential process never started\")?;\n                if !status.success() {\n                    return Err(format!(\"process `{}` failed with status `{status}`\", exe).into());\n                }\n                Ok(CredentialResponse::Get {\n                    token: Secret::from(buffer),\n                    cache: CacheControl::Session,\n                    operation_independent: true,\n                })\n            }\n            _ => Err(cargo_credential::Error::OperationNotSupported),\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/credential/mod.rs",
    "content": "//! Built-in Cargo credential providers\n\n#![allow(clippy::print_stderr)]\n\npub mod adaptor;\npub mod paseto;\npub mod process;\npub mod token;\n"
  },
  {
    "path": "src/cargo/util/credential/paseto.rs",
    "content": "//! Credential provider that implements PASETO asymmetric tokens stored in Cargo's config.\n\nuse anyhow::Context as _;\nuse cargo_credential::{\n    Action, CacheControl, Credential, CredentialResponse, Error, Operation, RegistryInfo, Secret,\n};\nuse clap::Command;\nuse pasetors::{\n    keys::{AsymmetricKeyPair, AsymmetricPublicKey, AsymmetricSecretKey, Generate},\n    paserk::FormatAsPaserk,\n};\nuse time::{OffsetDateTime, format_description::well_known::Rfc3339};\nuse url::Url;\n\nuse crate::{\n    GlobalContext,\n    core::SourceId,\n    ops::RegistryCredentialConfig,\n    util::{auth::registry_credential_config_raw, command_prelude::opt, context},\n};\n\n/// The main body of an asymmetric token as describe in RFC 3231.\n#[derive(serde::Serialize)]\nstruct Message<'a> {\n    iat: &'a str,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    sub: Option<&'a str>,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    mutation: Option<&'a str>,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    name: Option<&'a str>,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    vers: Option<&'a str>,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    cksum: Option<&'a str>,\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    challenge: Option<&'a str>,\n    /// This field is not yet used. This field can be set to a value >1 to indicate a breaking change in the token format.\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    v: Option<u8>,\n}\n/// The footer of an asymmetric token as describe in RFC 3231.\n#[derive(serde::Serialize)]\nstruct Footer<'a> {\n    url: &'a str,\n    kip: pasetors::paserk::Id,\n}\n\npub(crate) struct PasetoCredential<'a> {\n    gctx: &'a GlobalContext,\n}\n\nimpl<'a> PasetoCredential<'a> {\n    pub fn new(gctx: &'a GlobalContext) -> Self {\n        Self { gctx }\n    }\n}\n\nimpl<'a> Credential for PasetoCredential<'a> {\n    fn perform(\n        &self,\n        registry: &RegistryInfo<'_>,\n        action: &Action<'_>,\n        args: &[&str],\n    ) -> Result<CredentialResponse, Error> {\n        let index_url = Url::parse(registry.index_url).context(\"parsing index url\")?;\n        let sid = if let Some(name) = registry.name {\n            SourceId::for_alt_registry(&index_url, name)\n        } else {\n            SourceId::for_registry(&index_url)\n        }?;\n\n        let reg_cfg = registry_credential_config_raw(self.gctx, &sid)?;\n\n        let matches = Command::new(\"cargo:paseto\")\n            .no_binary_name(true)\n            .arg(opt(\"key-subject\", \"Set the key subject for this registry\").value_name(\"SUBJECT\"))\n            .try_get_matches_from(args)\n            .map_err(Box::new)?;\n        let key_subject = matches.get_one(\"key-subject\").map(String::as_str);\n\n        match action {\n            Action::Get(operation) => {\n                let Some(reg_cfg) = reg_cfg else {\n                    return Err(Error::NotFound);\n                };\n                let Some(secret_key) = reg_cfg.secret_key.as_ref() else {\n                    return Err(Error::NotFound);\n                };\n\n                let secret_key_subject = reg_cfg.secret_key_subject;\n                let secret: Secret<AsymmetricSecretKey<pasetors::version3::V3>> = secret_key\n                    .val\n                    .as_ref()\n                    .map(|key| key.as_str().try_into())\n                    .transpose()\n                    .context(\"failed to load private key\")?;\n                let public: AsymmetricPublicKey<pasetors::version3::V3> = secret\n                    .as_ref()\n                    .map(|key| key.try_into())\n                    .transpose()\n                    .context(\"failed to load public key from private key\")?\n                    .expose();\n                let kip: pasetors::paserk::Id = (&public).into();\n\n                let iat = OffsetDateTime::now_utc();\n\n                let message = Message {\n                    iat: &iat.format(&Rfc3339).unwrap(),\n                    sub: secret_key_subject.as_deref(),\n                    mutation: match operation {\n                        Operation::Publish { .. } => Some(\"publish\"),\n                        Operation::Yank { .. } => Some(\"yank\"),\n                        Operation::Unyank { .. } => Some(\"unyank\"),\n                        Operation::Owners { .. } => Some(\"owners\"),\n                        _ => None,\n                    },\n                    name: match operation {\n                        Operation::Publish { name, .. }\n                        | Operation::Yank { name, .. }\n                        | Operation::Unyank { name, .. }\n                        | Operation::Owners { name, .. } => Some(name),\n                        _ => None,\n                    },\n                    vers: match operation {\n                        Operation::Publish { vers, .. }\n                        | Operation::Yank { vers, .. }\n                        | Operation::Unyank { vers, .. } => Some(vers),\n                        _ => None,\n                    },\n                    cksum: match operation {\n                        Operation::Publish { cksum, .. } => Some(cksum),\n                        _ => None,\n                    },\n                    challenge: None, // todo: PASETO with challenges\n                    v: None,\n                };\n                let footer = Footer {\n                    url: &registry.index_url,\n                    kip,\n                };\n\n                // Only read operations can be cached with asymmetric tokens.\n                let cache = match operation {\n                    Operation::Read => CacheControl::Session,\n                    _ => CacheControl::Never,\n                };\n\n                let token = secret\n                    .map(|secret| {\n                        pasetors::version3::PublicToken::sign(\n                            &secret,\n                            serde_json::to_string(&message)\n                                .expect(\"cannot serialize\")\n                                .as_bytes(),\n                            Some(\n                                serde_json::to_string(&footer)\n                                    .expect(\"cannot serialize\")\n                                    .as_bytes(),\n                            ),\n                            None,\n                        )\n                    })\n                    .transpose()\n                    .context(\"failed to sign request\")?;\n\n                Ok(CredentialResponse::Get {\n                    token,\n                    cache,\n                    operation_independent: false,\n                })\n            }\n            Action::Login(options) => {\n                let old_key_subject = reg_cfg.and_then(|cfg| cfg.secret_key_subject);\n                let new_token;\n                let secret_key: Secret<String>;\n                if let Some(key) = &options.token {\n                    secret_key = key.clone().map(str::to_string);\n                } else {\n                    let kp = AsymmetricKeyPair::<pasetors::version3::V3>::generate().unwrap();\n                    secret_key = Secret::default().map(|mut key| {\n                        FormatAsPaserk::fmt(&kp.secret, &mut key).unwrap();\n                        key\n                    });\n                }\n\n                if let Some(p) = paserk_public_from_paserk_secret(secret_key.as_deref()) {\n                    eprintln!(\"{}\", &p);\n                } else {\n                    return Err(\"not a validly formatted PASERK secret key\".into());\n                }\n                new_token = RegistryCredentialConfig::AsymmetricKey((\n                    secret_key,\n                    match key_subject {\n                        Some(key_subject) => Some(key_subject.to_string()),\n                        None => old_key_subject,\n                    },\n                ));\n                context::save_credentials(self.gctx, Some(new_token), &sid)?;\n                Ok(CredentialResponse::Login)\n            }\n            Action::Logout => {\n                if reg_cfg.and_then(|c| c.secret_key).is_some() {\n                    context::save_credentials(self.gctx, None, &sid)?;\n                    let reg_name = sid.display_registry_name();\n                    let _ = self.gctx.shell().status(\n                        \"Logout\",\n                        format!(\"secret-key for `{reg_name}` has been removed from local storage\"),\n                    );\n                    Ok(CredentialResponse::Logout)\n                } else {\n                    Err(Error::NotFound)\n                }\n            }\n            _ => Err(Error::OperationNotSupported),\n        }\n    }\n}\n\n/// Checks that a secret key is valid, and returns the associated public key in Paserk format.\npub(crate) fn paserk_public_from_paserk_secret(secret_key: Secret<&str>) -> Option<String> {\n    let secret: Secret<AsymmetricSecretKey<pasetors::version3::V3>> =\n        secret_key.map(|key| key.try_into()).transpose().ok()?;\n    let public: AsymmetricPublicKey<pasetors::version3::V3> = secret\n        .as_ref()\n        .map(|key| key.try_into())\n        .transpose()\n        .ok()?\n        .expose();\n    let mut paserk_pub_key = String::new();\n    FormatAsPaserk::fmt(&public, &mut paserk_pub_key).unwrap();\n    Some(paserk_pub_key)\n}\n"
  },
  {
    "path": "src/cargo/util/credential/process.rs",
    "content": "//! Credential provider that launches an external process using Cargo's credential\n//! protocol.\n\nuse std::{\n    io::{BufRead, BufReader, Write},\n    path::PathBuf,\n    process::{Child, Command, Stdio},\n};\n\nuse anyhow::Context;\nuse cargo_credential::{\n    Action, Credential, CredentialHello, CredentialRequest, CredentialResponse, Error, RegistryInfo,\n};\n\npub struct CredentialProcessCredential {\n    path: PathBuf,\n}\n\nimpl<'a> CredentialProcessCredential {\n    pub fn new(path: &str) -> Self {\n        Self {\n            path: PathBuf::from(path),\n        }\n    }\n\n    fn run(\n        &self,\n        child: &mut Child,\n        action: &Action<'_>,\n        registry: &RegistryInfo<'_>,\n        args: &[&str],\n    ) -> Result<Result<CredentialResponse, Error>, Error> {\n        let mut output_from_child = BufReader::new(child.stdout.take().unwrap());\n        let mut input_to_child = child.stdin.take().unwrap();\n        let mut buffer = String::new();\n\n        // Read the CredentialHello\n        output_from_child\n            .read_line(&mut buffer)\n            .context(\"failed to read hello from credential provider\")?;\n        let credential_hello: CredentialHello =\n            serde_json::from_str(&buffer).context(\"failed to deserialize hello\")?;\n        tracing::debug!(\"credential-process > {credential_hello:?}\");\n        if !credential_hello\n            .v\n            .contains(&cargo_credential::PROTOCOL_VERSION_1)\n        {\n            return Err(format!(\n                \"credential provider supports protocol versions {:?}, while Cargo supports {:?}\",\n                credential_hello.v,\n                [cargo_credential::PROTOCOL_VERSION_1]\n            )\n            .into());\n        }\n\n        // Send the Credential Request\n        let req = CredentialRequest {\n            v: cargo_credential::PROTOCOL_VERSION_1,\n            action: action.clone(),\n            registry: registry.clone(),\n            args: args.to_vec(),\n        };\n        let request = serde_json::to_string(&req).context(\"failed to serialize request\")?;\n        tracing::debug!(\"credential-process < {req:?}\");\n        writeln!(input_to_child, \"{request}\").context(\"failed to write to credential provider\")?;\n        buffer.clear();\n        output_from_child\n            .read_line(&mut buffer)\n            .context(\"failed to read response from credential provider\")?;\n\n        // Read the Credential Response\n        let response: Result<CredentialResponse, Error> =\n            serde_json::from_str(&buffer).context(\"failed to deserialize response\")?;\n        tracing::debug!(\"credential-process > {response:?}\");\n\n        // Tell the credential process we're done by closing stdin. It should exit cleanly.\n        drop(input_to_child);\n        let status = child.wait().context(\"credential process never started\")?;\n        if !status.success() {\n            return Err(anyhow::anyhow!(\n                \"credential process `{}` failed with status {}`\",\n                self.path.display(),\n                status\n            )\n            .into());\n        }\n        tracing::trace!(\"credential process exited successfully\");\n        Ok(response)\n    }\n}\n\nimpl<'a> Credential for CredentialProcessCredential {\n    fn perform(\n        &self,\n        registry: &RegistryInfo<'_>,\n        action: &Action<'_>,\n        args: &[&str],\n    ) -> Result<CredentialResponse, Error> {\n        let mut cmd = Command::new(&self.path);\n        cmd.stdout(Stdio::piped());\n        cmd.stdin(Stdio::piped());\n        cmd.arg(\"--cargo-plugin\");\n        tracing::debug!(\"credential-process: {cmd:?}\");\n        let mut child = cmd.spawn().context(\"failed to spawn credential process\")?;\n        match self.run(&mut child, action, registry, args) {\n            Err(e) => {\n                // Since running the credential process itself failed, ensure the\n                // process is stopped.\n                let _ = child.kill();\n                Err(e)\n            }\n            Ok(response) => response,\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/credential/token.rs",
    "content": "//! Credential provider that uses plaintext tokens in Cargo's config.\n\nuse anyhow::Context as _;\nuse cargo_credential::{Action, CacheControl, Credential, CredentialResponse, Error, RegistryInfo};\nuse url::Url;\n\nuse crate::{\n    GlobalContext,\n    core::SourceId,\n    ops::RegistryCredentialConfig,\n    util::{auth::registry_credential_config_raw, context},\n};\n\npub struct TokenCredential<'a> {\n    gctx: &'a GlobalContext,\n}\n\nimpl<'a> TokenCredential<'a> {\n    pub fn new(gctx: &'a GlobalContext) -> Self {\n        Self { gctx }\n    }\n}\n\nimpl<'a> Credential for TokenCredential<'a> {\n    fn perform(\n        &self,\n        registry: &RegistryInfo<'_>,\n        action: &Action<'_>,\n        _args: &[&str],\n    ) -> Result<CredentialResponse, Error> {\n        let index_url = Url::parse(registry.index_url).context(\"parsing index url\")?;\n        let sid = if let Some(name) = registry.name {\n            SourceId::for_alt_registry(&index_url, name)\n        } else {\n            SourceId::for_registry(&index_url)\n        }?;\n        let previous_token = registry_credential_config_raw(self.gctx, &sid)?.and_then(|c| c.token);\n\n        match action {\n            Action::Get(_) => {\n                let token = previous_token.ok_or_else(|| Error::NotFound)?.val;\n                Ok(CredentialResponse::Get {\n                    token,\n                    cache: CacheControl::Session,\n                    operation_independent: true,\n                })\n            }\n            Action::Login(options) => {\n                // Automatically remove `cargo login` from an inputted token to\n                // allow direct pastes from `registry.host()`/me.\n                let new_token = cargo_credential::read_token(options, registry)?\n                    .map(|line| line.replace(\"cargo login\", \"\").trim().to_string());\n\n                crates_io::check_token(new_token.as_ref().expose()).map_err(Box::new)?;\n                context::save_credentials(\n                    self.gctx,\n                    Some(RegistryCredentialConfig::Token(new_token)),\n                    &sid,\n                )?;\n                let _ = self.gctx.shell().status(\n                    \"Login\",\n                    format!(\"token for `{}` saved\", sid.display_registry_name()),\n                );\n                Ok(CredentialResponse::Login)\n            }\n            Action::Logout => {\n                if previous_token.is_none() {\n                    return Err(Error::NotFound);\n                }\n                let reg_name = sid.display_registry_name();\n                context::save_credentials(self.gctx, None, &sid)?;\n                let _ = self.gctx.shell().status(\n                    \"Logout\",\n                    format!(\"token for `{reg_name}` has been removed from local storage\"),\n                );\n                let location = if sid.is_crates_io() {\n                    \"<https://crates.io/me>\".to_string()\n                } else {\n                    // The URL for the source requires network access to load the config.\n                    // That could be a fairly heavy operation to perform just to provide a\n                    // help message, so for now this just provides some generic text.\n                    // Perhaps in the future this could have an API to fetch the config if\n                    // it is cached, but avoid network access otherwise?\n                    format!(\"the `{reg_name}` website\")\n                };\n                eprintln!(\n                    \"note: This does not revoke the token on the registry server.\\n    \\\n                    If you need to revoke the token, visit {location} and follow the instructions there.\"\n                );\n                Ok(CredentialResponse::Logout)\n            }\n            _ => Err(Error::OperationNotSupported),\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/dependency_queue.rs",
    "content": "//! A graph-like structure used to represent a set of dependencies and in what\n//! order they should be built.\n//!\n//! This structure is used to store the dependency graph and dynamically update\n//! it to figure out when a dependency should be built.\n//!\n//! Dependencies in this queue are represented as a (node, edge) pair. This is\n//! used to model nodes which produce multiple outputs at different times but\n//! some nodes may only require one of the outputs and can start before the\n//! whole node is finished.\n\nuse std::collections::{HashMap, HashSet};\nuse std::hash::Hash;\n\n#[derive(Debug)]\npub struct DependencyQueue<N: Hash + Eq, E: Hash + Eq, V> {\n    /// A list of all known keys to build.\n    ///\n    /// The value of the hash map is list of dependencies which still need to be\n    /// built before the package can be built. Note that the set is dynamically\n    /// updated as more dependencies are built.\n    dep_map: HashMap<N, (HashSet<(N, E)>, V)>,\n\n    /// A reverse mapping of a package to all packages that depend on that\n    /// package.\n    ///\n    /// This map is statically known and does not get updated throughout the\n    /// lifecycle of the `DependencyQueue`.\n    ///\n    /// This is sort of like a `HashMap<(N, E), HashSet<N>>` map, but more\n    /// easily indexable with just an `N`\n    reverse_dep_map: HashMap<N, HashMap<E, HashSet<N>>>,\n\n    /// The relative priority of this package. Higher values should be scheduled sooner.\n    priority: HashMap<N, usize>,\n\n    /// An expected cost for building this package. Used to determine priority.\n    cost: HashMap<N, usize>,\n}\n\nimpl<N: Hash + Eq, E: Hash + Eq, V> Default for DependencyQueue<N, E, V> {\n    fn default() -> DependencyQueue<N, E, V> {\n        DependencyQueue::new()\n    }\n}\n\nimpl<N: Hash + Eq, E: Hash + Eq, V> DependencyQueue<N, E, V> {\n    /// Creates a new dependency queue with 0 packages.\n    pub fn new() -> DependencyQueue<N, E, V> {\n        DependencyQueue {\n            dep_map: HashMap::new(),\n            reverse_dep_map: HashMap::new(),\n            priority: HashMap::new(),\n            cost: HashMap::new(),\n        }\n    }\n}\n\nimpl<N: Hash + Eq + Clone, E: Eq + Hash + Clone, V> DependencyQueue<N, E, V> {\n    /// Adds a new node and its dependencies to this queue.\n    ///\n    /// The `key` specified is a new node in the dependency graph, and the node\n    /// depend on all the dependencies iterated by `dependencies`. Each\n    /// dependency is a node/edge pair, where edges can be thought of as\n    /// productions from nodes (aka if it's just `()` it's just waiting for the\n    /// node to finish).\n    ///\n    /// An optional `value` can also be associated with `key` which is reclaimed\n    /// when the node is ready to go.\n    ///\n    /// The cost parameter can be used to hint at the relative cost of building\n    /// this node. This implementation does not care about the units of this value, so\n    /// the calling code is free to use whatever they'd like. In general, higher cost\n    /// nodes are expected to take longer to build.\n    pub fn queue(\n        &mut self,\n        key: N,\n        value: V,\n        dependencies: impl IntoIterator<Item = (N, E)>,\n        cost: usize,\n    ) {\n        assert!(!self.dep_map.contains_key(&key));\n\n        let mut my_dependencies = HashSet::new();\n        for (dep, edge) in dependencies {\n            my_dependencies.insert((dep.clone(), edge.clone()));\n            self.reverse_dep_map\n                .entry(dep)\n                .or_insert_with(HashMap::new)\n                .entry(edge)\n                .or_insert_with(HashSet::new)\n                .insert(key.clone());\n        }\n        self.dep_map.insert(key.clone(), (my_dependencies, value));\n        self.cost.insert(key, cost);\n    }\n\n    /// All nodes have been added, calculate some internal metadata and prepare\n    /// for `dequeue`.\n    pub fn queue_finished(&mut self) {\n        let mut out = HashMap::new();\n        for key in self.dep_map.keys() {\n            depth(key, &self.reverse_dep_map, &mut out);\n        }\n        self.priority = out\n            .into_iter()\n            .map(|(n, set)| {\n                let total_cost =\n                    self.cost[&n] + set.iter().map(|key| self.cost[key]).sum::<usize>();\n                (n, total_cost)\n            })\n            .collect();\n\n        /// Creates a flattened reverse dependency list. For a given key, finds the\n        /// set of nodes which depend on it, including transitively. This is different\n        /// from `self.reverse_dep_map` because `self.reverse_dep_map` only maps one level\n        /// of reverse dependencies.\n        fn depth<'a, N: Hash + Eq + Clone, E: Hash + Eq + Clone>(\n            key: &N,\n            map: &HashMap<N, HashMap<E, HashSet<N>>>,\n            results: &'a mut HashMap<N, HashSet<N>>,\n        ) -> &'a HashSet<N> {\n            if results.contains_key(key) {\n                let depth = &results[key];\n                assert!(!depth.is_empty(), \"cycle in DependencyQueue\");\n                return depth;\n            }\n            results.insert(key.clone(), HashSet::new());\n\n            let mut set = HashSet::new();\n            set.insert(key.clone());\n\n            for dep in map\n                .get(key)\n                .into_iter()\n                .flat_map(|it| it.values())\n                .flatten()\n            {\n                set.extend(depth(dep, map, results).iter().cloned())\n            }\n\n            let slot = results.get_mut(key).unwrap();\n            *slot = set;\n            &*slot\n        }\n    }\n\n    /// Dequeues a package that is ready to be built.\n    ///\n    /// A package is ready to be built when it has 0 un-built dependencies. If\n    /// `None` is returned then no packages are ready to be built.\n    pub fn dequeue(&mut self) -> Option<(N, V, usize)> {\n        let (key, priority) = self\n            .dep_map\n            .iter()\n            .filter(|(_, (deps, _))| deps.is_empty())\n            .map(|(key, _)| (key.clone(), self.priority[key]))\n            .max_by_key(|(_, priority)| *priority)?;\n        let (_, data) = self.dep_map.remove(&key).unwrap();\n        Some((key, data, priority))\n    }\n\n    /// Returns `true` if there are remaining packages to be built.\n    pub fn is_empty(&self) -> bool {\n        self.dep_map.is_empty()\n    }\n\n    /// Returns the number of remaining packages to be built.\n    pub fn len(&self) -> usize {\n        self.dep_map.len()\n    }\n\n    /// Indicate that something has finished.\n    ///\n    /// Calling this function indicates that the `node` has produced `edge`. All\n    /// remaining work items which only depend on this node/edge pair are now\n    /// candidates to start their job.\n    ///\n    /// Returns the nodes that are now allowed to be dequeued as a result of\n    /// finishing this node.\n    pub fn finish(&mut self, node: &N, edge: &E) -> Vec<&N> {\n        // hashset<Node>\n        let reverse_deps = self.reverse_dep_map.get(node).and_then(|map| map.get(edge));\n        let Some(reverse_deps) = reverse_deps else {\n            return Vec::new();\n        };\n        let key = (node.clone(), edge.clone());\n        let mut result = Vec::new();\n        for dep in reverse_deps.iter() {\n            let edges = &mut self.dep_map.get_mut(dep).unwrap().0;\n            assert!(edges.remove(&key));\n            if edges.is_empty() {\n                result.push(dep);\n            }\n        }\n        result\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::DependencyQueue;\n\n    #[test]\n    fn deep_first_equal_cost() {\n        let mut q = DependencyQueue::new();\n\n        q.queue(1, (), vec![], 1);\n        q.queue(2, (), vec![(1, ())], 1);\n        q.queue(3, (), vec![], 1);\n        q.queue(4, (), vec![(2, ()), (3, ())], 1);\n        q.queue(5, (), vec![(4, ()), (3, ())], 1);\n        q.queue_finished();\n\n        assert_eq!(q.dequeue(), Some((1, (), 5)));\n        assert_eq!(q.dequeue(), Some((3, (), 4)));\n        assert_eq!(q.dequeue(), None);\n        q.finish(&3, &());\n        assert_eq!(q.dequeue(), None);\n        q.finish(&1, &());\n        assert_eq!(q.dequeue(), Some((2, (), 4)));\n        assert_eq!(q.dequeue(), None);\n        q.finish(&2, &());\n        assert_eq!(q.dequeue(), Some((4, (), 3)));\n        assert_eq!(q.dequeue(), None);\n        q.finish(&4, &());\n        assert_eq!(q.dequeue(), Some((5, (), 2)));\n    }\n\n    #[test]\n    fn sort_by_highest_cost() {\n        let mut q = DependencyQueue::new();\n\n        q.queue(1, (), vec![], 1);\n        q.queue(2, (), vec![(1, ())], 1);\n        q.queue(3, (), vec![], 4);\n        q.queue(4, (), vec![(2, ()), (3, ())], 1);\n        q.queue_finished();\n\n        assert_eq!(q.dequeue(), Some((3, (), 9)));\n        assert_eq!(q.dequeue(), Some((1, (), 4)));\n        assert_eq!(q.dequeue(), None);\n        q.finish(&3, &());\n        assert_eq!(q.dequeue(), None);\n        q.finish(&1, &());\n        assert_eq!(q.dequeue(), Some((2, (), 3)));\n        assert_eq!(q.dequeue(), None);\n        q.finish(&2, &());\n        assert_eq!(q.dequeue(), Some((4, (), 2)));\n        assert_eq!(q.dequeue(), None);\n        q.finish(&4, &());\n        assert_eq!(q.dequeue(), None);\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/diagnostic_server.rs",
    "content": "//! A small TCP server to handle collection of diagnostics information in a\n//! cross-platform way for the `cargo fix` command.\n\nuse std::collections::HashSet;\nuse std::io::{BufReader, Read, Write};\nuse std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};\nuse std::path::PathBuf;\nuse std::sync::Arc;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::thread::{self, JoinHandle};\n\nuse annotate_snippets::Group;\nuse annotate_snippets::Level;\nuse annotate_snippets::Origin;\nuse anyhow::{Context as _, Error};\nuse cargo_util::ProcessBuilder;\nuse serde::{Deserialize, Serialize};\nuse tracing::warn;\n\nuse crate::core::Edition;\nuse crate::util::GlobalContext;\nuse crate::util::errors::CargoResult;\nuse crate::util::network::LOCALHOST;\n\nconst DIAGNOSTICS_SERVER_VAR: &str = \"__CARGO_FIX_DIAGNOSTICS_SERVER\";\n\n#[derive(Deserialize, Serialize, Hash, Eq, PartialEq, Clone)]\npub enum Message {\n    Migrating {\n        file: String,\n        from_edition: Edition,\n        to_edition: Edition,\n    },\n    Fixing {\n        file: String,\n    },\n    Fixed {\n        file: String,\n        fixes: u32,\n    },\n    FixFailed {\n        files: Vec<String>,\n        krate: Option<String>,\n        errors: Vec<String>,\n        abnormal_exit: Option<String>,\n    },\n    ReplaceFailed {\n        file: String,\n        message: String,\n    },\n    EditionAlreadyEnabled {\n        message: String,\n        edition: Edition,\n    },\n}\n\nimpl Message {\n    pub fn post(&self, gctx: &GlobalContext) -> Result<(), Error> {\n        let addr = gctx\n            .get_env(DIAGNOSTICS_SERVER_VAR)\n            .context(\"diagnostics collector misconfigured\")?;\n        let mut client =\n            TcpStream::connect(&addr).context(\"failed to connect to parent diagnostics target\")?;\n\n        let s = serde_json::to_string(self).context(\"failed to serialize message\")?;\n        client\n            .write_all(s.as_bytes())\n            .context(\"failed to write message to diagnostics target\")?;\n        client\n            .shutdown(Shutdown::Write)\n            .context(\"failed to shutdown\")?;\n\n        client\n            .read_to_end(&mut Vec::new())\n            .context(\"failed to receive a disconnect\")?;\n\n        Ok(())\n    }\n}\n\n/// A printer that will print diagnostics messages to the shell.\npub struct DiagnosticPrinter<'a> {\n    /// The context to get the shell to print to.\n    gctx: &'a GlobalContext,\n    /// An optional wrapper to be used in addition to `rustc.wrapper` for workspace crates.\n    /// This is used to get the correct bug report URL. For instance,\n    /// if `clippy-driver` is set as the value for the wrapper,\n    /// then the correct bug report URL for `clippy` can be obtained.\n    workspace_wrapper: &'a Option<PathBuf>,\n    // A set of messages that have already been printed.\n    dedupe: HashSet<Message>,\n}\n\nimpl<'a> DiagnosticPrinter<'a> {\n    pub fn new(\n        gctx: &'a GlobalContext,\n        workspace_wrapper: &'a Option<PathBuf>,\n    ) -> DiagnosticPrinter<'a> {\n        DiagnosticPrinter {\n            gctx,\n            workspace_wrapper,\n            dedupe: HashSet::new(),\n        }\n    }\n\n    pub fn print(&mut self, msg: &Message) -> CargoResult<()> {\n        match msg {\n            Message::Migrating {\n                file,\n                from_edition,\n                to_edition,\n            } => {\n                if !self.dedupe.insert(msg.clone()) {\n                    return Ok(());\n                }\n                self.gctx.shell().status(\n                    \"Migrating\",\n                    &format!(\"{file} from {from_edition} edition to {to_edition}\"),\n                )\n            }\n            Message::Fixing { file } => self\n                .gctx\n                .shell()\n                .verbose(|shell| shell.status(\"Fixing\", file)),\n            Message::Fixed { file, fixes } => {\n                let msg = if *fixes == 1 { \"fix\" } else { \"fixes\" };\n                let msg = format!(\"{file} ({fixes} {msg})\");\n                self.gctx.shell().status(\"Fixed\", msg)\n            }\n            Message::ReplaceFailed { file, message } => {\n                let issue_link = get_bug_report_url(self.workspace_wrapper);\n\n                let report = &[\n                    Level::ERROR\n                        .secondary_title(\"error applying suggestions\")\n                        .element(Origin::path(file))\n                        .element(Level::ERROR.with_name(\"cause\").message(message)),\n                    gen_please_report_this_bug_group(issue_link),\n                    gen_suggest_broken_code_group(),\n                ];\n                self.gctx.shell().print_report(report, false)?;\n                Ok(())\n            }\n            Message::FixFailed {\n                files,\n                krate,\n                errors,\n                abnormal_exit,\n            } => {\n                let to_crate = if let Some(ref krate) = *krate {\n                    format!(\" to crate `{krate}`\",)\n                } else {\n                    \"\".to_owned()\n                };\n                let issue_link = get_bug_report_url(self.workspace_wrapper);\n\n                let cause_message = if !errors.is_empty() {\n                    Some(errors.join(\"\\n\").trim().to_owned())\n                } else {\n                    None\n                };\n\n                let report = &[\n                    Level::ERROR\n                        .secondary_title(format!(\"errors present after applying fixes{to_crate}\"))\n                        .elements(files.iter().map(|f| Origin::path(f)))\n                        .elements(\n                            cause_message\n                                .into_iter()\n                                .map(|err| Level::ERROR.with_name(\"cause\").message(err)),\n                        )\n                        .elements(abnormal_exit.iter().map(|exit| {\n                            Level::ERROR\n                                .with_name(\"cause\")\n                                .message(format!(\"rustc exited abnormally: {exit}\"))\n                        })),\n                    gen_please_report_this_bug_group(issue_link),\n                    gen_suggest_broken_code_group(),\n                    Group::with_title(\n                        Level::NOTE.secondary_title(\"original diagnostics will follow:\"),\n                    ),\n                ];\n\n                self.gctx.shell().print_report(report, false)?;\n                Ok(())\n            }\n            Message::EditionAlreadyEnabled { message, edition } => {\n                if !self.dedupe.insert(msg.clone()) {\n                    return Ok(());\n                }\n                // Don't give a really verbose warning if it has already been issued.\n                if self.dedupe.insert(Message::EditionAlreadyEnabled {\n                    message: \"\".to_string(), // Dummy, so that this only long-warns once.\n                    edition: *edition,\n                }) {\n                    self.gctx.shell().warn(&format!(\"\\\n{message}\n\nIf you are trying to migrate from the previous edition ({prev_edition}), the\nprocess requires following these steps:\n\n1. Start with `edition = \\\"{prev_edition}\\\"` in `Cargo.toml`\n2. Run `cargo fix --edition`\n3. Modify `Cargo.toml` to set `edition = \\\"{this_edition}\\\"`\n4. Run `cargo build` or `cargo test` to verify the fixes worked\n\nMore details may be found at\nhttps://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html\n\",\n                        this_edition=edition, prev_edition=edition.previous().unwrap()\n                    ))\n                } else {\n                    self.gctx.shell().warn(message)\n                }\n            }\n        }\n    }\n}\n\nfn gen_please_report_this_bug_group(url: &str) -> Group<'static> {\n    Group::with_title(Level::HELP.secondary_title(format!(\n        \"to report this as a bug, open an issue at {url}, quoting the full output of this command\"\n    )))\n}\n\nfn gen_suggest_broken_code_group() -> Group<'static> {\n    Group::with_title(\n        Level::HELP\n            .secondary_title(\"to possibly apply more fixes, pass in the `--broken-code` flag\"),\n    )\n}\n\nfn get_bug_report_url(rustc_workspace_wrapper: &Option<PathBuf>) -> &str {\n    let clippy = std::ffi::OsStr::new(\"clippy-driver\");\n    let issue_link = match rustc_workspace_wrapper.as_ref().and_then(|x| x.file_stem()) {\n        Some(wrapper) if wrapper == clippy => \"https://github.com/rust-lang/rust-clippy/issues\",\n        _ => \"https://github.com/rust-lang/rust/issues\",\n    };\n\n    issue_link\n}\n\n#[derive(Debug)]\npub struct RustfixDiagnosticServer {\n    listener: TcpListener,\n    addr: SocketAddr,\n}\n\npub struct StartedServer {\n    addr: SocketAddr,\n    done: Arc<AtomicBool>,\n    thread: Option<JoinHandle<()>>,\n}\n\nimpl RustfixDiagnosticServer {\n    pub fn new() -> Result<Self, Error> {\n        let listener = TcpListener::bind(&LOCALHOST[..])\n            .context(\"failed to bind TCP listener to manage locking\")?;\n        let addr = listener.local_addr()?;\n\n        Ok(RustfixDiagnosticServer { listener, addr })\n    }\n\n    pub fn configure(&self, process: &mut ProcessBuilder) {\n        process.env(DIAGNOSTICS_SERVER_VAR, self.addr.to_string());\n    }\n\n    pub fn start<F>(self, on_message: F) -> Result<StartedServer, Error>\n    where\n        F: Fn(Message) + Send + 'static,\n    {\n        let addr = self.addr;\n        let done = Arc::new(AtomicBool::new(false));\n        let done2 = done.clone();\n        let thread = thread::spawn(move || {\n            self.run(&on_message, &done2);\n        });\n\n        Ok(StartedServer {\n            addr,\n            thread: Some(thread),\n            done,\n        })\n    }\n\n    fn run(self, on_message: &dyn Fn(Message), done: &AtomicBool) {\n        while let Ok((client, _)) = self.listener.accept() {\n            if done.load(Ordering::SeqCst) {\n                break;\n            }\n            let mut client = BufReader::new(client);\n            let mut s = String::new();\n            if let Err(e) = client.read_to_string(&mut s) {\n                warn!(\"diagnostic server failed to read: {e}\");\n            } else {\n                match serde_json::from_str(&s) {\n                    Ok(message) => on_message(message),\n                    Err(e) => warn!(\"invalid diagnostics message: {e}\"),\n                }\n            }\n            // The client should be kept alive until after `on_message` is\n            // called to ensure that the client doesn't exit too soon (and\n            // Message::Finish getting posted before Message::FixDiagnostic).\n            drop(client);\n        }\n    }\n}\n\nimpl Drop for StartedServer {\n    fn drop(&mut self) {\n        self.done.store(true, Ordering::SeqCst);\n        // Ignore errors here as this is largely best-effort\n        if TcpStream::connect(&self.addr).is_err() {\n            return;\n        }\n        drop(self.thread.take().unwrap().join());\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/edit_distance.rs",
    "content": "use std::{cmp, mem};\n\n/// Finds the [edit distance] between two strings.\n///\n/// Returns `None` if the distance exceeds the limit.\n///\n/// [edit distance]: https://en.wikipedia.org/wiki/Edit_distance\npub fn edit_distance(a: &str, b: &str, limit: usize) -> Option<usize> {\n    // Comparing the strings lowercased will result in a difference in capitalization being less distance away\n    // than being a completely different letter. Otherwise `CHECK` is as far away from `check` as it\n    // is from `build` (both with a distance of 5). For a single letter shortcut (e.g. `b` or `c`), they will\n    // all be as far away from any capital single letter entry (all with a distance of 1).\n    // By first lowercasing the strings, `C` and `c` are closer than `C` and `b`, for example.\n    let a = a.to_lowercase();\n    let b = b.to_lowercase();\n\n    let mut a = &a.chars().collect::<Vec<_>>()[..];\n    let mut b = &b.chars().collect::<Vec<_>>()[..];\n\n    // Ensure that `b` is the shorter string, minimizing memory use.\n    if a.len() < b.len() {\n        mem::swap(&mut a, &mut b);\n    }\n\n    let min_dist = a.len() - b.len();\n    // If we know the limit will be exceeded, we can return early.\n    if min_dist > limit {\n        return None;\n    }\n\n    // Strip common prefix.\n    while let Some(((b_char, b_rest), (a_char, a_rest))) = b.split_first().zip(a.split_first()) {\n        if a_char != b_char {\n            break;\n        }\n        a = a_rest;\n        b = b_rest;\n    }\n    // Strip common suffix.\n    while let Some(((b_char, b_rest), (a_char, a_rest))) = b.split_last().zip(a.split_last()) {\n        if a_char != b_char {\n            break;\n        }\n        a = a_rest;\n        b = b_rest;\n    }\n\n    // If either string is empty, the distance is the length of the other.\n    // We know that `b` is the shorter string, so we don't need to check `a`.\n    if b.len() == 0 {\n        return Some(min_dist);\n    }\n\n    let mut prev_prev = vec![usize::MAX; b.len() + 1];\n    let mut prev = (0..=b.len()).collect::<Vec<_>>();\n    let mut current = vec![0; b.len() + 1];\n\n    // row by row\n    for i in 1..=a.len() {\n        current[0] = i;\n        let a_idx = i - 1;\n\n        // column by column\n        for j in 1..=b.len() {\n            let b_idx = j - 1;\n\n            // There is no cost to substitute a character with itself.\n            let substitution_cost = if a[a_idx] == b[b_idx] { 0 } else { 1 };\n\n            current[j] = cmp::min(\n                // deletion\n                prev[j] + 1,\n                cmp::min(\n                    // insertion\n                    current[j - 1] + 1,\n                    // substitution\n                    prev[j - 1] + substitution_cost,\n                ),\n            );\n\n            if (i > 1) && (j > 1) && (a[a_idx] == b[b_idx - 1]) && (a[a_idx - 1] == b[b_idx]) {\n                // transposition\n                current[j] = cmp::min(current[j], prev_prev[j - 2] + 1);\n            }\n        }\n\n        // Rotate the buffers, reusing the memory.\n        [prev_prev, prev, current] = [prev, current, prev_prev];\n    }\n\n    // `prev` because we already rotated the buffers.\n    let distance = prev[b.len()];\n    (distance <= limit).then_some(distance)\n}\n\n/// Find the closest element from `iter` matching `choice`. The `key` callback\n/// is used to select a `&str` from the iterator to compare against `choice`.\npub fn closest<'a, T>(\n    choice: &str,\n    iter: impl Iterator<Item = T>,\n    key: impl Fn(&T) -> &'a str,\n) -> Option<T> {\n    // Only consider candidates with an edit distance of 3 or less so we don't\n    // suggest out-of-the-blue options.\n    iter.filter_map(|e| Some((edit_distance(choice, key(&e), 3)?, e)))\n        .min_by_key(|t| t.0)\n        .map(|t| t.1)\n}\n\n/// Version of `closest` that returns a common \"suggestion\" that can be tacked\n/// onto the end of an error message.\npub fn closest_msg<'a, T>(\n    choice: &str,\n    iter: impl Iterator<Item = T>,\n    key: impl Fn(&T) -> &'a str,\n    kind: &str,\n) -> String {\n    match closest(choice, iter, &key) {\n        Some(e) => format!(\n            \"\\n\\nhelp: a {kind} with a similar name exists: `{}`\",\n            key(&e)\n        ),\n        None => String::new(),\n    }\n}\n\n#[test]\nfn test_edit_distance() {\n    use std::char::{MAX, from_u32};\n    // Test bytelength agnosticity\n    for c in (0u32..MAX as u32)\n        .filter_map(from_u32)\n        .map(|i| i.to_string())\n    {\n        assert_eq!(edit_distance(&c, &c, usize::MAX), Some(0));\n    }\n\n    let a = \"\\nMäry häd ä little lämb\\n\\nLittle lämb\\n\";\n    let b = \"\\nMary häd ä little lämb\\n\\nLittle lämb\\n\";\n    let c = \"Mary häd ä little lämb\\n\\nLittle lämb\\n\";\n    assert_eq!(edit_distance(a, b, usize::MAX), Some(1));\n    assert_eq!(edit_distance(b, a, usize::MAX), Some(1));\n    assert_eq!(edit_distance(a, c, usize::MAX), Some(2));\n    assert_eq!(edit_distance(c, a, usize::MAX), Some(2));\n    assert_eq!(edit_distance(b, c, usize::MAX), Some(1));\n    assert_eq!(edit_distance(c, b, usize::MAX), Some(1));\n}\n"
  },
  {
    "path": "src/cargo/util/errors.rs",
    "content": "use anyhow::Error;\nuse curl::easy::Easy;\nuse std::fmt::{self, Write};\nuse std::path::PathBuf;\n\nuse super::truncate_with_ellipsis;\n\npub type CargoResult<T> = anyhow::Result<T>;\n\n/// These are headers that are included in error messages to help with\n/// diagnosing issues.\npub const DEBUG_HEADERS: &[&str] = &[\n    // This is the unique ID that identifies the request in CloudFront which\n    // can be used for looking at the AWS logs.\n    \"x-amz-cf-id\",\n    // This is the CloudFront POP (Point of Presence) that identifies the\n    // region where the request was routed. This can help identify if an issue\n    // is region-specific.\n    \"x-amz-cf-pop\",\n    // The unique token used for troubleshooting S3 requests via AWS logs or support.\n    \"x-amz-request-id\",\n    // Another token used in conjunction with x-amz-request-id.\n    \"x-amz-id-2\",\n    // Whether or not there was a cache hit or miss (both CloudFront and Fastly).\n    \"x-cache\",\n    // The cache server that processed the request (Fastly).\n    \"x-served-by\",\n];\n\n#[derive(Debug)]\npub struct HttpNotSuccessful {\n    pub code: u32,\n    pub url: String,\n    pub ip: Option<String>,\n    pub body: Vec<u8>,\n    pub headers: Vec<String>,\n}\n\nimpl HttpNotSuccessful {\n    pub fn new_from_handle(\n        handle: &mut Easy,\n        initial_url: &str,\n        body: Vec<u8>,\n        headers: Vec<String>,\n    ) -> HttpNotSuccessful {\n        let ip = handle.primary_ip().ok().flatten().map(|s| s.to_string());\n        let url = handle\n            .effective_url()\n            .ok()\n            .flatten()\n            .unwrap_or(initial_url)\n            .to_string();\n        HttpNotSuccessful {\n            code: handle.response_code().unwrap_or(0),\n            url,\n            ip,\n            body,\n            headers,\n        }\n    }\n\n    /// Renders the error in a compact form.\n    pub fn display_short(&self) -> String {\n        self.render(false)\n    }\n\n    fn render(&self, show_headers: bool) -> String {\n        let mut result = String::new();\n        let body = std::str::from_utf8(&self.body)\n            .map(|s| truncate_with_ellipsis(s, 512))\n            .unwrap_or_else(|_| format!(\"[{} non-utf8 bytes]\", self.body.len()));\n\n        write!(\n            result,\n            \"failed to get successful HTTP response from `{}`\",\n            self.url\n        )\n        .unwrap();\n        if let Some(ip) = &self.ip {\n            write!(result, \" ({ip})\").unwrap();\n        }\n        write!(result, \", got {}\\n\", self.code).unwrap();\n        if show_headers {\n            let headers: Vec<_> = self\n                .headers\n                .iter()\n                .filter(|header| {\n                    let Some((name, _)) = header.split_once(\":\") else {\n                        return false;\n                    };\n                    DEBUG_HEADERS.contains(&name.to_ascii_lowercase().trim())\n                })\n                .collect();\n            if !headers.is_empty() {\n                writeln!(result, \"debug headers:\").unwrap();\n                for header in headers {\n                    writeln!(result, \"{header}\").unwrap();\n                }\n            }\n        }\n        write!(result, \"body:\\n{body}\").unwrap();\n        result\n    }\n}\n\nimpl fmt::Display for HttpNotSuccessful {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(&self.render(true))\n    }\n}\n\nimpl std::error::Error for HttpNotSuccessful {}\n\n// =============================================================================\n// Verbose error\n\n/// An error wrapper for errors that should only be displayed with `--verbose`.\n///\n/// This should only be used in rare cases. When emitting this error, you\n/// should have a normal error higher up the error-cause chain (like \"could\n/// not compile `foo`\"), so at least *something* gets printed without\n/// `--verbose`.\npub struct VerboseError {\n    inner: Error,\n}\n\nimpl VerboseError {\n    pub fn new(inner: Error) -> VerboseError {\n        VerboseError { inner }\n    }\n}\n\nimpl std::error::Error for VerboseError {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        self.inner.source()\n    }\n}\n\nimpl fmt::Debug for VerboseError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.inner.fmt(f)\n    }\n}\n\nimpl fmt::Display for VerboseError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.inner.fmt(f)\n    }\n}\n\n// =============================================================================\n// Internal error\n\n/// An unexpected, internal error.\n///\n/// This should only be used for unexpected errors. It prints a message asking\n/// the user to file a bug report.\npub struct InternalError {\n    inner: Error,\n}\n\nimpl InternalError {\n    pub fn new(inner: Error) -> InternalError {\n        InternalError { inner }\n    }\n}\n\nimpl std::error::Error for InternalError {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        self.inner.source()\n    }\n}\n\nimpl fmt::Debug for InternalError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.inner.fmt(f)\n    }\n}\n\nimpl fmt::Display for InternalError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.inner.fmt(f)\n    }\n}\n\n// =============================================================================\n// Already printed error\n\n/// An error that does not need to be printed because it does not add any new\n/// information to what has already been printed.\npub struct AlreadyPrintedError {\n    inner: Error,\n}\n\nimpl AlreadyPrintedError {\n    pub fn new(inner: Error) -> Self {\n        AlreadyPrintedError { inner }\n    }\n}\n\nimpl std::error::Error for AlreadyPrintedError {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        self.inner.source()\n    }\n}\n\nimpl fmt::Debug for AlreadyPrintedError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.inner.fmt(f)\n    }\n}\n\nimpl fmt::Display for AlreadyPrintedError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.inner.fmt(f)\n    }\n}\n\n// =============================================================================\n// Manifest error\n\n/// Error wrapper related to a particular manifest and providing it's path.\n///\n/// This error adds no displayable info of it's own.\npub struct ManifestError {\n    cause: Error,\n    manifest: PathBuf,\n}\n\nimpl ManifestError {\n    pub fn new<E: Into<Error>>(cause: E, manifest: PathBuf) -> Self {\n        Self {\n            cause: cause.into(),\n            manifest,\n        }\n    }\n\n    pub fn manifest_path(&self) -> &PathBuf {\n        &self.manifest\n    }\n\n    /// Returns an iterator over the `ManifestError` chain of causes.\n    ///\n    /// So if this error was not caused by another `ManifestError` this will be empty.\n    pub fn manifest_causes(&self) -> ManifestCauses<'_> {\n        ManifestCauses { current: self }\n    }\n}\n\nimpl std::error::Error for ManifestError {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        self.cause.source()\n    }\n}\n\nimpl fmt::Debug for ManifestError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.cause.fmt(f)\n    }\n}\n\nimpl fmt::Display for ManifestError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.cause.fmt(f)\n    }\n}\n\n/// An iterator over the `ManifestError` chain of causes.\npub struct ManifestCauses<'a> {\n    current: &'a ManifestError,\n}\n\nimpl<'a> Iterator for ManifestCauses<'a> {\n    type Item = &'a ManifestError;\n\n    fn next(&mut self) -> Option<Self::Item> {\n        self.current = self.current.cause.downcast_ref()?;\n        Some(self.current)\n    }\n}\n\nimpl<'a> ::std::iter::FusedIterator for ManifestCauses<'a> {}\n\n// =============================================================================\n// CLI errors\n\npub type CliResult = Result<(), CliError>;\n\n#[derive(Debug)]\n/// The CLI error is the error type used at Cargo's CLI-layer.\n///\n/// All errors from the lib side of Cargo will get wrapped with this error.\n/// Other errors (such as command-line argument validation) will create this\n/// directly.\npub struct CliError {\n    /// The error to display. This can be `None` in rare cases to exit with a\n    /// code without displaying a message. For example `cargo run -q` where\n    /// the resulting process exits with a nonzero code (on Windows), or an\n    /// external subcommand that exits nonzero (we assume it printed its own\n    /// message).\n    pub error: Option<anyhow::Error>,\n    /// The process exit code.\n    pub exit_code: i32,\n}\n\nimpl CliError {\n    pub fn new(error: anyhow::Error, code: i32) -> CliError {\n        CliError {\n            error: Some(error),\n            exit_code: code,\n        }\n    }\n\n    pub fn code(code: i32) -> CliError {\n        CliError {\n            error: None,\n            exit_code: code,\n        }\n    }\n}\n\nimpl From<anyhow::Error> for CliError {\n    fn from(err: anyhow::Error) -> CliError {\n        CliError::new(err, 101)\n    }\n}\n\nimpl From<clap::Error> for CliError {\n    fn from(err: clap::Error) -> CliError {\n        let code = if err.use_stderr() { 1 } else { 0 };\n        CliError::new(err.into(), code)\n    }\n}\n\nimpl From<std::io::Error> for CliError {\n    fn from(err: std::io::Error) -> CliError {\n        CliError::new(err.into(), 1)\n    }\n}\n\n// =============================================================================\n// Git CLI errors\n\npub type GitCliResult = Result<(), GitCliError>;\n\n/// An error that occurred while invoking the `git` command-line tool.\n///\n/// This is used for errors from Git operations performed via CLI.\n/// It wraps a lower-level error and indicates whether the failure\n/// should be considered *spurious*.\n///\n/// Spurious failures might involve retry mechanism.\n#[derive(Debug)]\npub struct GitCliError {\n    inner: Error,\n    is_spurious: bool,\n}\n\nimpl GitCliError {\n    pub fn new(inner: Error, is_spurious: bool) -> GitCliError {\n        GitCliError { inner, is_spurious }\n    }\n\n    pub fn is_spurious(&self) -> bool {\n        self.is_spurious\n    }\n}\n\nimpl std::error::Error for GitCliError {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        self.inner.source()\n    }\n}\n\nimpl fmt::Display for GitCliError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.inner.fmt(f)\n    }\n}\n\n// =============================================================================\n// Construction helpers\n\npub fn internal<S: fmt::Display>(error: S) -> anyhow::Error {\n    InternalError::new(anyhow::format_err!(\"{}\", error)).into()\n}\n"
  },
  {
    "path": "src/cargo/util/flock.rs",
    "content": "//! File-locking support.\n//!\n//! This module defines the [`Filesystem`] type which is an abstraction over a\n//! filesystem, ensuring that access to the filesystem is only done through\n//! coordinated locks.\n//!\n//! The [`FileLock`] type represents a locked file, and provides access to the\n//! file.\n\nuse std::fs::TryLockError;\nuse std::fs::{File, OpenOptions};\nuse std::io;\nuse std::io::{Read, Seek, SeekFrom, Write};\nuse std::path::{Display, Path, PathBuf};\n\nuse crate::util::GlobalContext;\nuse crate::util::errors::CargoResult;\nuse crate::util::style;\nuse anyhow::Context as _;\nuse cargo_util::paths;\n\n/// A locked file.\n///\n/// This provides access to file while holding a lock on the file. This type\n/// implements the [`Read`], [`Write`], and [`Seek`] traits to provide access\n/// to the underlying file.\n///\n/// Locks are either shared (multiple processes can access the file) or\n/// exclusive (only one process can access the file).\n///\n/// This type is created via methods on the [`Filesystem`] type.\n///\n/// When this value is dropped, the lock will be released.\n#[derive(Debug)]\npub struct FileLock {\n    f: Option<File>,\n    path: PathBuf,\n}\n\nimpl FileLock {\n    /// Returns the underlying file handle of this lock.\n    pub fn file(&self) -> &File {\n        self.f.as_ref().unwrap()\n    }\n\n    /// Returns the underlying path that this lock points to.\n    ///\n    /// Note that special care must be taken to ensure that the path is not\n    /// referenced outside the lifetime of this lock.\n    pub fn path(&self) -> &Path {\n        &self.path\n    }\n\n    /// Returns the parent path containing this file\n    pub fn parent(&self) -> &Path {\n        self.path.parent().unwrap()\n    }\n\n    /// Removes all sibling files to this locked file.\n    ///\n    /// This can be useful if a directory is locked with a sentinel file but it\n    /// needs to be cleared out as it may be corrupt.\n    pub fn remove_siblings(&self) -> CargoResult<()> {\n        let path = self.path();\n        for entry in path.parent().unwrap().read_dir()? {\n            let entry = entry?;\n            if Some(&entry.file_name()[..]) == path.file_name() {\n                continue;\n            }\n            let kind = entry.file_type()?;\n            if kind.is_dir() {\n                paths::remove_dir_all(entry.path())?;\n            } else {\n                paths::remove_file(entry.path())?;\n            }\n        }\n        Ok(())\n    }\n\n    /// Renames the file and updates the internal path.\n    ///\n    /// This method performs a filesystem rename operation using [`std::fs::rename`]\n    /// while keeping the FileLock's internal path synchronized with the actual\n    /// file location.\n    ///\n    /// ## Difference from `std::fs::rename`\n    ///\n    /// - `std::fs::rename(old, new)` only moves the file on the filesystem\n    /// - `FileLock::rename(new)` moves the file AND updates `self.path` to point to the new location\n    pub fn rename<P: AsRef<Path>>(&mut self, new_path: P) -> CargoResult<()> {\n        let new_path = new_path.as_ref();\n        std::fs::rename(&self.path, new_path).with_context(|| {\n            format!(\n                \"failed to rename {} to {}\",\n                self.path.display(),\n                new_path.display()\n            )\n        })?;\n        self.path = new_path.to_path_buf();\n        Ok(())\n    }\n}\n\nimpl Read for FileLock {\n    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {\n        self.file().read(buf)\n    }\n}\n\nimpl Seek for FileLock {\n    fn seek(&mut self, to: SeekFrom) -> io::Result<u64> {\n        self.file().seek(to)\n    }\n}\n\nimpl Write for FileLock {\n    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {\n        self.file().write(buf)\n    }\n\n    fn flush(&mut self) -> io::Result<()> {\n        self.file().flush()\n    }\n}\n\nimpl Drop for FileLock {\n    fn drop(&mut self) {\n        if let Some(f) = self.f.take() {\n            if let Err(e) = f.unlock() {\n                tracing::warn!(\"failed to release lock: {e:?}\");\n            }\n        }\n    }\n}\n\n/// A \"filesystem\" is intended to be a globally shared, hence locked, resource\n/// in Cargo.\n///\n/// The `Path` of a filesystem cannot be learned unless it's done in a locked\n/// fashion, and otherwise functions on this structure are prepared to handle\n/// concurrent invocations across multiple instances of Cargo.\n///\n/// The methods on `Filesystem` that open files return a [`FileLock`] which\n/// holds the lock, and that type provides methods for accessing the\n/// underlying file.\n///\n/// If the blocking methods (like [`Filesystem::open_ro_shared`]) detect that\n/// they will block, then they will display a message to the user letting them\n/// know it is blocked. There are non-blocking variants starting with the\n/// `try_` prefix like [`Filesystem::try_open_ro_shared_create`].\n///\n/// The behavior of locks acquired by the `Filesystem` depend on the operating\n/// system. On unix-like system, they are advisory using [`flock`], and thus\n/// not enforced against processes which do not try to acquire the lock. On\n/// Windows, they are mandatory using [`LockFileEx`], enforced against all\n/// processes.\n///\n/// This **does not** guarantee that a lock is acquired. In some cases, for\n/// example on filesystems that don't support locking, it will return a\n/// [`FileLock`] even though the filesystem lock was not acquired. This is\n/// intended to provide a graceful fallback instead of refusing to work.\n/// Usually there aren't multiple processes accessing the same resource. In\n/// that case, it is the user's responsibility to not run concurrent\n/// processes.\n///\n/// [`flock`]: https://linux.die.net/man/2/flock\n/// [`LockFileEx`]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-lockfileex\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct Filesystem {\n    root: PathBuf,\n}\n\nimpl Filesystem {\n    /// Creates a new filesystem to be rooted at the given path.\n    pub fn new(path: PathBuf) -> Filesystem {\n        Filesystem { root: path }\n    }\n\n    /// Like `Path::join`, creates a new filesystem rooted at this filesystem\n    /// joined with the given path.\n    pub fn join<T: AsRef<Path>>(&self, other: T) -> Filesystem {\n        Filesystem::new(self.root.join(other))\n    }\n\n    /// Like `Path::push`, pushes a new path component onto this filesystem.\n    pub fn push<T: AsRef<Path>>(&mut self, other: T) {\n        self.root.push(other);\n    }\n\n    /// Consumes this filesystem and returns the underlying `PathBuf`.\n    ///\n    /// Note that this is a relatively dangerous operation and should be used\n    /// with great caution!.\n    pub fn into_path_unlocked(self) -> PathBuf {\n        self.root\n    }\n\n    /// Returns the underlying `Path`.\n    ///\n    /// Note that this is a relatively dangerous operation and should be used\n    /// with great caution!.\n    pub fn as_path_unlocked(&self) -> &Path {\n        &self.root\n    }\n\n    /// Creates the directory pointed to by this filesystem.\n    ///\n    /// Handles errors where other Cargo processes are also attempting to\n    /// concurrently create this directory.\n    pub fn create_dir(&self) -> CargoResult<()> {\n        paths::create_dir_all(&self.root)\n    }\n\n    /// Returns an adaptor that can be used to print the path of this\n    /// filesystem.\n    pub fn display(&self) -> Display<'_> {\n        self.root.display()\n    }\n\n    /// Opens read-write exclusive access to a file, returning the locked\n    /// version of a file.\n    ///\n    /// This function will create a file at `path` if it doesn't already exist\n    /// (including intermediate directories), and then it will acquire an\n    /// exclusive lock on `path`. If the process must block waiting for the\n    /// lock, the `msg` is printed to [`GlobalContext`].\n    ///\n    /// The returned file can be accessed to look at the path and also has\n    /// read/write access to the underlying file.\n    pub fn open_rw_exclusive_create<P>(\n        &self,\n        path: P,\n        gctx: &GlobalContext,\n        msg: &str,\n    ) -> CargoResult<FileLock>\n    where\n        P: AsRef<Path>,\n    {\n        let mut opts = OpenOptions::new();\n        opts.read(true).write(true).create(true);\n        let (path, f) = self.open(path.as_ref(), &opts, true)?;\n        acquire(gctx, msg, &path, &|| f.try_lock(), &|| f.lock())?;\n        Ok(FileLock { f: Some(f), path })\n    }\n\n    /// A non-blocking version of [`Filesystem::open_rw_exclusive_create`].\n    ///\n    /// Returns `None` if the operation would block due to another process\n    /// holding the lock.\n    pub fn try_open_rw_exclusive_create<P: AsRef<Path>>(\n        &self,\n        path: P,\n    ) -> CargoResult<Option<FileLock>> {\n        let mut opts = OpenOptions::new();\n        opts.read(true).write(true).create(true);\n        let (path, f) = self.open(path.as_ref(), &opts, true)?;\n        if try_acquire(&path, &|| f.try_lock())? {\n            Ok(Some(FileLock { f: Some(f), path }))\n        } else {\n            Ok(None)\n        }\n    }\n\n    /// Opens read-only shared access to a file, returning the locked version of a file.\n    ///\n    /// This function will fail if `path` doesn't already exist, but if it does\n    /// then it will acquire a shared lock on `path`. If the process must block\n    /// waiting for the lock, the `msg` is printed to [`GlobalContext`].\n    ///\n    /// The returned file can be accessed to look at the path and also has read\n    /// access to the underlying file. Any writes to the file will return an\n    /// error.\n    pub fn open_ro_shared<P>(\n        &self,\n        path: P,\n        gctx: &GlobalContext,\n        msg: &str,\n    ) -> CargoResult<FileLock>\n    where\n        P: AsRef<Path>,\n    {\n        let (path, f) = self.open(path.as_ref(), &OpenOptions::new().read(true), false)?;\n        acquire(gctx, msg, &path, &|| f.try_lock_shared(), &|| {\n            f.lock_shared()\n        })?;\n        Ok(FileLock { f: Some(f), path })\n    }\n\n    /// Opens read-only shared access to a file, returning the locked version of a file.\n    ///\n    /// Compared to [`Filesystem::open_ro_shared`], this will create the file\n    /// (and any directories in the parent) if the file does not already\n    /// exist.\n    pub fn open_ro_shared_create<P: AsRef<Path>>(\n        &self,\n        path: P,\n        gctx: &GlobalContext,\n        msg: &str,\n    ) -> CargoResult<FileLock> {\n        let mut opts = OpenOptions::new();\n        opts.read(true).write(true).create(true);\n        let (path, f) = self.open(path.as_ref(), &opts, true)?;\n        acquire(gctx, msg, &path, &|| f.try_lock_shared(), &|| {\n            f.lock_shared()\n        })?;\n        Ok(FileLock { f: Some(f), path })\n    }\n\n    /// A non-blocking version of [`Filesystem::open_ro_shared_create`].\n    ///\n    /// Returns `None` if the operation would block due to another process\n    /// holding the lock.\n    pub fn try_open_ro_shared_create<P: AsRef<Path>>(\n        &self,\n        path: P,\n    ) -> CargoResult<Option<FileLock>> {\n        let mut opts = OpenOptions::new();\n        opts.read(true).write(true).create(true);\n        let (path, f) = self.open(path.as_ref(), &opts, true)?;\n        if try_acquire(&path, &|| f.try_lock_shared())? {\n            Ok(Some(FileLock { f: Some(f), path }))\n        } else {\n            Ok(None)\n        }\n    }\n\n    fn open(&self, path: &Path, opts: &OpenOptions, create: bool) -> CargoResult<(PathBuf, File)> {\n        let path = self.root.join(path);\n        let f = opts\n            .open(&path)\n            .or_else(|e| {\n                // If we were requested to create this file, and there was a\n                // NotFound error, then that was likely due to missing\n                // intermediate directories. Try creating them and try again.\n                if e.kind() == io::ErrorKind::NotFound && create {\n                    paths::create_dir_all(path.parent().unwrap())?;\n                    Ok(opts.open(&path)?)\n                } else {\n                    Err(anyhow::Error::from(e))\n                }\n            })\n            .with_context(|| format!(\"failed to open: {}\", path.display()))?;\n        Ok((path, f))\n    }\n}\n\nimpl PartialEq<Path> for Filesystem {\n    fn eq(&self, other: &Path) -> bool {\n        self.root == other\n    }\n}\n\nimpl PartialEq<Filesystem> for Path {\n    fn eq(&self, other: &Filesystem) -> bool {\n        self == other.root\n    }\n}\n\nfn try_acquire(path: &Path, lock_try: &dyn Fn() -> Result<(), TryLockError>) -> CargoResult<bool> {\n    // File locking on Unix is currently implemented via `flock`, which is known\n    // to be broken on NFS. We could in theory just ignore errors that happen on\n    // NFS, but apparently the failure mode [1] for `flock` on NFS is **blocking\n    // forever**, even if the \"non-blocking\" flag is passed!\n    //\n    // As a result, we just skip all file locks entirely on NFS mounts. That\n    // should avoid calling any `flock` functions at all, and it wouldn't work\n    // there anyway.\n    //\n    // [1]: https://github.com/rust-lang/cargo/issues/2615\n    if is_on_nfs_mount(path) {\n        tracing::debug!(\"{path:?} appears to be an NFS mount, not trying to lock\");\n        return Ok(true);\n    }\n\n    match lock_try() {\n        Ok(()) => Ok(true),\n\n        // In addition to ignoring NFS which is commonly not working we also\n        // just ignore locking on filesystems that look like they don't\n        // implement file locking.\n        Err(TryLockError::Error(e)) if error_unsupported(&e) => Ok(true),\n\n        Err(TryLockError::Error(e)) => {\n            let e = anyhow::Error::from(e);\n            let cx = format!(\"failed to lock file: {}\", path.display());\n            Err(e.context(cx))\n        }\n\n        Err(TryLockError::WouldBlock) => Ok(false),\n    }\n}\n\n/// Acquires a lock on a file in a \"nice\" manner.\n///\n/// Almost all long-running blocking actions in Cargo have a status message\n/// associated with them as we're not sure how long they'll take. Whenever a\n/// conflicted file lock happens, this is the case (we're not sure when the lock\n/// will be released).\n///\n/// This function will acquire the lock on a `path`, printing out a nice message\n/// to the console if we have to wait for it. It will first attempt to use `try`\n/// to acquire a lock on the crate, and in the case of contention it will emit a\n/// status message based on `msg` to [`GlobalContext`]'s shell, and then use `block` to\n/// block waiting to acquire a lock.\n///\n/// Returns an error if the lock could not be acquired or if any error other\n/// than a contention error happens.\nfn acquire(\n    gctx: &GlobalContext,\n    msg: &str,\n    path: &Path,\n    lock_try: &dyn Fn() -> Result<(), TryLockError>,\n    lock_block: &dyn Fn() -> io::Result<()>,\n) -> CargoResult<()> {\n    // Ensure `shell` is not already in use,\n    // regardless of whether we hit contention or not\n    gctx.debug_assert_shell_not_borrowed();\n    if try_acquire(path, lock_try)? {\n        return Ok(());\n    }\n\n    let msg = if gctx.extra_verbose() {\n        format!(\"waiting for file lock on {} ({})\", msg, path.display())\n    } else {\n        format!(\"waiting for file lock on {}\", msg)\n    };\n\n    gctx.shell()\n        .status_with_color(\"Blocking\", &msg, &style::NOTE)?;\n\n    lock_block().with_context(|| format!(\"failed to lock file: {}\", path.display()))?;\n    Ok(())\n}\n\n#[cfg(all(target_os = \"linux\", not(target_env = \"musl\")))]\npub fn is_on_nfs_mount(path: &Path) -> bool {\n    use std::ffi::CString;\n    use std::mem;\n    use std::os::unix::prelude::*;\n\n    let Ok(path) = CString::new(path.as_os_str().as_bytes()) else {\n        return false;\n    };\n\n    unsafe {\n        let mut buf: libc::statfs = mem::zeroed();\n        let r = libc::statfs(path.as_ptr(), &mut buf);\n\n        r == 0 && buf.f_type as u32 == libc::NFS_SUPER_MAGIC as u32\n    }\n}\n\n#[cfg(any(not(target_os = \"linux\"), target_env = \"musl\"))]\npub fn is_on_nfs_mount(_path: &Path) -> bool {\n    false\n}\n\n#[cfg(unix)]\nfn error_unsupported(err: &std::io::Error) -> bool {\n    match err.raw_os_error() {\n        // Unfortunately, depending on the target, these may or may not be the same.\n        // For targets in which they are the same, the duplicate pattern causes a warning.\n        #[allow(unreachable_patterns)]\n        Some(libc::ENOTSUP | libc::EOPNOTSUPP) => true,\n        Some(libc::ENOSYS) => true,\n        _ => err.kind() == std::io::ErrorKind::Unsupported,\n    }\n}\n\n#[cfg(windows)]\nfn error_unsupported(err: &std::io::Error) -> bool {\n    use windows_sys::Win32::Foundation::ERROR_INVALID_FUNCTION;\n    match err.raw_os_error() {\n        Some(code) if code == ERROR_INVALID_FUNCTION as i32 => true,\n        _ => err.kind() == std::io::ErrorKind::Unsupported,\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/frontmatter.rs",
    "content": "type Span = std::ops::Range<usize>;\n\n#[derive(Debug)]\npub struct ScriptSource<'s> {\n    /// The full file\n    raw: &'s str,\n    /// The `#!/usr/bin/env cargo` line, if present\n    shebang: Option<Span>,\n    /// The code fence opener (`---`)\n    open: Option<Span>,\n    /// Trailing text after `ScriptSource::open` that identifies the meaning of\n    /// `ScriptSource::frontmatter`\n    info: Option<Span>,\n    /// The lines between `ScriptSource::open` and `ScriptSource::close`\n    frontmatter: Option<Span>,\n    /// The code fence closer (`---`)\n    close: Option<Span>,\n    /// All content after the frontmatter and shebang\n    content: Span,\n}\n\nimpl<'s> ScriptSource<'s> {\n    pub fn parse(raw: &'s str) -> Result<Self, FrontmatterError> {\n        use winnow::stream::FindSlice as _;\n        use winnow::stream::Location as _;\n        use winnow::stream::Offset as _;\n        use winnow::stream::Stream as _;\n\n        let content_end = raw.len();\n        let mut source = Self {\n            raw,\n            shebang: None,\n            open: None,\n            info: None,\n            frontmatter: None,\n            close: None,\n            content: 0..content_end,\n        };\n\n        let mut input = winnow::stream::LocatingSlice::new(raw);\n\n        if let Some(shebang_end) = strip_shebang(input.as_ref()) {\n            let shebang_start = input.current_token_start();\n            let _ = input.next_slice(shebang_end);\n            let shebang_end = input.current_token_start();\n            source.shebang = Some(shebang_start..shebang_end);\n            source.content = shebang_end..content_end;\n        }\n\n        // Whitespace may precede a frontmatter but must end with a newline\n        if let Some(nl_end) = strip_ws_lines(input.as_ref()) {\n            let _ = input.next_slice(nl_end);\n        }\n\n        // Opens with a line that starts with 3 or more `-` followed by an optional identifier\n        const FENCE_CHAR: char = '-';\n        let fence_length = input\n            .as_ref()\n            .char_indices()\n            .find_map(|(i, c)| (c != FENCE_CHAR).then_some(i))\n            .unwrap_or_else(|| input.eof_offset());\n        let open_start = input.current_token_start();\n        let fence_pattern = input.next_slice(fence_length);\n        let open_end = input.current_token_start();\n        match fence_length {\n            0 => {\n                return Ok(source);\n            }\n            1 | 2 => {\n                // either not a frontmatter or invalid frontmatter opening\n                return Err(FrontmatterError::new(\n                    format!(\n                        \"found {fence_length} `{FENCE_CHAR}` in rust frontmatter, expected at least 3\"\n                    ),\n                    raw.len()..raw.len(),\n                ).push_visible_span(open_start..open_end));\n            }\n            _ if u8::try_from(fence_length).is_err() => {\n                return Err(FrontmatterError::new(\n                    format!(\n                        \"too many `-` symbols: frontmatter openings may be delimited by up to 255 `-` symbols, but found {fence_length}\"\n                    ),\n                    open_start..open_end,\n                ));\n            }\n            _ => {}\n        }\n        source.open = Some(open_start..open_end);\n        let Some(info_nl) = input.find_slice(\"\\n\") else {\n            return Err(FrontmatterError::new(\n                format!(\"unclosed frontmatter; expected `{fence_pattern}`\"),\n                raw.len()..raw.len(),\n            )\n            .push_visible_span(open_start..open_end));\n        };\n        let info = input.next_slice(info_nl.start);\n        let info = info.strip_suffix('\\r').unwrap_or(info); // already excludes `\\n`\n        let info = info.trim_matches(is_horizontal_whitespace);\n        if !info.is_empty() {\n            let info_start = info.offset_from(&raw);\n            let info_end = info_start + info.len();\n            source.info = Some(info_start..info_end);\n        }\n\n        // Ends with a line that starts with a matching number of `-` only followed by whitespace\n        let nl_fence_pattern = format!(\"\\n{fence_pattern}\");\n        let Some(frontmatter_nl) = input.find_slice(nl_fence_pattern.as_str()) else {\n            for len in (2..(nl_fence_pattern.len() - 1)).rev() {\n                let Some(frontmatter_nl) = input.find_slice(&nl_fence_pattern[0..len]) else {\n                    continue;\n                };\n                let _ = input.next_slice(frontmatter_nl.start + 1);\n                let close_start = input.current_token_start();\n                let _ = input.next_slice(len);\n                let close_end = input.current_token_start();\n                let fewer_dashes = fence_length - len;\n                return Err(FrontmatterError::new(\n                    format!(\n                        \"closing code fence has {fewer_dashes} less `-` than the opening fence\"\n                    ),\n                    close_start..close_end,\n                )\n                .push_visible_span(open_start..open_end));\n            }\n            return Err(FrontmatterError::new(\n                format!(\"unclosed frontmatter; expected `{fence_pattern}`\"),\n                raw.len()..raw.len(),\n            )\n            .push_visible_span(open_start..open_end));\n        };\n        let frontmatter_start = input.current_token_start() + 1; // skip nl from infostring\n        let _ = input.next_slice(frontmatter_nl.start + 1);\n        let frontmatter_end = input.current_token_start();\n        source.frontmatter = Some(frontmatter_start..frontmatter_end);\n        let close_start = input.current_token_start();\n        let _ = input.next_slice(fence_length);\n        let close_end = input.current_token_start();\n        source.close = Some(close_start..close_end);\n\n        let nl = input.find_slice(\"\\n\");\n        let after_closing_fence = input.next_slice(\n            nl.map(|span| span.end)\n                .unwrap_or_else(|| input.eof_offset()),\n        );\n        let content_start = input.current_token_start();\n        let extra_dashes = after_closing_fence\n            .chars()\n            .take_while(|b| *b == FENCE_CHAR)\n            .count();\n        if 0 < extra_dashes {\n            let extra_start = close_end;\n            let extra_end = extra_start + extra_dashes;\n            return Err(FrontmatterError::new(\n                format!(\"closing code fence has {extra_dashes} more `-` than the opening fence\"),\n                extra_start..extra_end,\n            )\n            .push_visible_span(open_start..open_end));\n        } else {\n            let after_closing_fence = strip_newline(after_closing_fence);\n            let after_closing_fence = after_closing_fence.trim_matches(is_horizontal_whitespace);\n            if !after_closing_fence.is_empty() {\n                // extra characters beyond the original fence pattern\n                let after_start = after_closing_fence.offset_from(&raw);\n                let after_end = after_start + after_closing_fence.len();\n                return Err(FrontmatterError::new(\n                    format!(\"unexpected characters after frontmatter close\"),\n                    after_start..after_end,\n                )\n                .push_visible_span(open_start..open_end));\n            }\n        }\n\n        source.content = content_start..content_end;\n\n        if let Some(nl_end) = strip_ws_lines(input.as_ref()) {\n            let _ = input.next_slice(nl_end);\n        }\n        let fence_length = input\n            .as_ref()\n            .char_indices()\n            .find_map(|(i, c)| (c != FENCE_CHAR).then_some(i))\n            .unwrap_or_else(|| input.eof_offset());\n        if 0 < fence_length {\n            let fence_start = input.current_token_start();\n            let fence_end = fence_start + fence_length;\n            return Err(FrontmatterError::new(\n                format!(\"only one frontmatter is supported\"),\n                fence_start..fence_end,\n            )\n            .push_visible_span(open_start..open_end)\n            .push_visible_span(close_start..close_end));\n        }\n\n        Ok(source)\n    }\n\n    pub fn shebang(&self) -> Option<&'s str> {\n        self.shebang.clone().map(|span| &self.raw[span])\n    }\n\n    pub fn shebang_span(&self) -> Option<Span> {\n        self.shebang.clone()\n    }\n\n    pub fn open_span(&self) -> Option<Span> {\n        self.open.clone()\n    }\n\n    pub fn info(&self) -> Option<&'s str> {\n        self.info.clone().map(|span| &self.raw[span])\n    }\n\n    pub fn info_span(&self) -> Option<Span> {\n        self.info.clone()\n    }\n\n    pub fn frontmatter(&self) -> Option<&'s str> {\n        self.frontmatter.clone().map(|span| &self.raw[span])\n    }\n\n    pub fn frontmatter_span(&self) -> Option<Span> {\n        self.frontmatter.clone()\n    }\n\n    pub fn close_span(&self) -> Option<Span> {\n        self.close.clone()\n    }\n\n    pub fn content(&self) -> &'s str {\n        &self.raw[self.content.clone()]\n    }\n\n    pub fn content_span(&self) -> Span {\n        self.content.clone()\n    }\n}\n\n/// Returns the index after the shebang line, if present\npub fn strip_shebang(input: &str) -> Option<usize> {\n    // See rust-lang/rust's compiler/rustc_lexer/src/lib.rs's `strip_shebang`\n    // Shebang must start with `#!` literally, without any preceding whitespace.\n    // For simplicity we consider any line starting with `#!` a shebang,\n    // regardless of restrictions put on shebangs by specific platforms.\n    if let Some(rest) = input.strip_prefix(\"#!\") {\n        // Ok, this is a shebang but if the next non-whitespace token is `[`,\n        // then it may be valid Rust code, so consider it Rust code.\n        //\n        // NOTE: rustc considers line and block comments to be whitespace but to avoid\n        // any more awareness of Rust grammar, we are excluding it.\n        if !rest.trim_start().starts_with('[') {\n            // No other choice than to consider this a shebang.\n            let newline_end = input.find('\\n').map(|pos| pos + 1).unwrap_or(input.len());\n            return Some(newline_end);\n        }\n    }\n    None\n}\n\n/// Returns the index after any lines with only whitespace, if present\npub fn strip_ws_lines(input: &str) -> Option<usize> {\n    let ws_end = input.find(|c| !is_whitespace(c)).unwrap_or(input.len());\n    if ws_end == 0 {\n        return None;\n    }\n\n    let nl_start = input[0..ws_end].rfind('\\n')?;\n    let nl_end = nl_start + 1;\n    Some(nl_end)\n}\n\n/// True if `c` is considered a whitespace according to Rust language definition.\n/// See [Rust language reference](https://doc.rust-lang.org/reference/whitespace.html)\n/// for definitions of these classes.\nfn is_whitespace(c: char) -> bool {\n    // This is Pattern_White_Space.\n    //\n    // Note that this set is stable (ie, it doesn't change with different\n    // Unicode versions), so it's ok to just hard-code the values.\n\n    matches!(\n        c,\n        // End-of-line characters\n        | '\\u{000A}' // line feed (\\n)\n        | '\\u{000B}' // vertical tab\n        | '\\u{000C}' // form feed\n        | '\\u{000D}' // carriage return (\\r)\n        | '\\u{0085}' // next line (from latin1)\n        | '\\u{2028}' // LINE SEPARATOR\n        | '\\u{2029}' // PARAGRAPH SEPARATOR\n\n        // `Default_Ignorable_Code_Point` characters\n        | '\\u{200E}' // LEFT-TO-RIGHT MARK\n        | '\\u{200F}' // RIGHT-TO-LEFT MARK\n\n        // Horizontal space characters\n        | '\\u{0009}'   // tab (\\t)\n        | '\\u{0020}' // space\n    )\n}\n\n/// True if `c` is considered horizontal whitespace according to Rust language definition.\nfn is_horizontal_whitespace(c: char) -> bool {\n    // This is Pattern_White_Space.\n    //\n    // Note that this set is stable (ie, it doesn't change with different\n    // Unicode versions), so it's ok to just hard-code the values.\n\n    matches!(\n        c,\n        // Horizontal space characters\n        '\\u{0009}'   // tab (\\t)\n        | '\\u{0020}' // space\n    )\n}\n\nfn strip_newline(text: &str) -> &str {\n    text.strip_suffix(\"\\r\\n\")\n        .or_else(|| text.strip_suffix('\\n'))\n        .unwrap_or(text)\n}\n\n#[derive(Debug)]\npub struct FrontmatterError {\n    message: String,\n    primary_span: Span,\n    visible_spans: Vec<Span>,\n}\n\nimpl FrontmatterError {\n    pub fn new(message: impl Into<String>, span: Span) -> Self {\n        Self {\n            message: message.into(),\n            primary_span: span,\n            visible_spans: Vec::new(),\n        }\n    }\n\n    pub fn push_visible_span(mut self, span: Span) -> Self {\n        self.visible_spans.push(span);\n        self\n    }\n\n    pub fn message(&self) -> &str {\n        self.message.as_str()\n    }\n\n    pub fn primary_span(&self) -> Span {\n        self.primary_span.clone()\n    }\n\n    pub fn visible_spans(&self) -> &[Span] {\n        &self.visible_spans\n    }\n}\n\nimpl std::fmt::Display for FrontmatterError {\n    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.message.fmt(fmt)\n    }\n}\n\nimpl std::error::Error for FrontmatterError {}\n\n#[cfg(test)]\nmod test {\n    use snapbox::assert_data_eq;\n    use snapbox::prelude::*;\n    use snapbox::str;\n\n    use super::*;\n\n    #[track_caller]\n    fn assert_source(source: &str, expected: impl IntoData) {\n        use std::fmt::Write as _;\n\n        let actual = match ScriptSource::parse(source) {\n            Ok(actual) => actual,\n            Err(err) => panic!(\"unexpected err: {err}\"),\n        };\n\n        let mut rendered = String::new();\n        write_optional_field(&mut rendered, \"shebang\", actual.shebang());\n        write_optional_field(&mut rendered, \"info\", actual.info());\n        write_optional_field(&mut rendered, \"frontmatter\", actual.frontmatter());\n        writeln!(&mut rendered, \"content: {:?}\", actual.content()).unwrap();\n        assert_data_eq!(rendered, expected.raw());\n    }\n\n    fn write_optional_field(writer: &mut dyn std::fmt::Write, field: &str, value: Option<&str>) {\n        if let Some(value) = value {\n            writeln!(writer, \"{field}: {value:?}\").unwrap();\n        } else {\n            writeln!(writer, \"{field}: None\").unwrap();\n        }\n    }\n\n    #[track_caller]\n    fn assert_err(\n        result: Result<impl std::fmt::Debug, impl std::fmt::Display>,\n        err: impl IntoData,\n    ) {\n        match result {\n            Ok(d) => panic!(\"unexpected Ok({d:#?})\"),\n            Err(actual) => snapbox::assert_data_eq!(actual.to_string(), err.raw()),\n        }\n    }\n\n    #[test]\n    fn split_default() {\n        assert_source(\n            r#\"fn main() {}\n\"#,\n            str![[r#\"\nshebang: None\ninfo: None\nfrontmatter: None\ncontent: \"fn main() {}\\n\"\n\n\"#]],\n        );\n    }\n\n    #[test]\n    fn split_dependencies() {\n        assert_source(\n            r#\"---\n[dependencies]\ntime=\"0.1.25\"\n---\nfn main() {}\n\"#,\n            str![[r#\"\nshebang: None\ninfo: None\nfrontmatter: \"[dependencies]\\ntime=\\\"0.1.25\\\"\\n\"\ncontent: \"fn main() {}\\n\"\n\n\"#]],\n        );\n    }\n\n    #[test]\n    fn split_infostring() {\n        assert_source(\n            r#\"---cargo\n[dependencies]\ntime=\"0.1.25\"\n---\nfn main() {}\n\"#,\n            str![[r#\"\nshebang: None\ninfo: \"cargo\"\nfrontmatter: \"[dependencies]\\ntime=\\\"0.1.25\\\"\\n\"\ncontent: \"fn main() {}\\n\"\n\n\"#]],\n        );\n    }\n\n    #[test]\n    fn split_infostring_whitespace() {\n        assert_source(\n            r#\"--- cargo \n[dependencies]\ntime=\"0.1.25\"\n---\nfn main() {}\n\"#,\n            str![[r#\"\nshebang: None\ninfo: \"cargo\"\nfrontmatter: \"[dependencies]\\ntime=\\\"0.1.25\\\"\\n\"\ncontent: \"fn main() {}\\n\"\n\n\"#]],\n        );\n    }\n\n    #[test]\n    fn split_shebang() {\n        assert_source(\n            r#\"#!/usr/bin/env cargo\n---\n[dependencies]\ntime=\"0.1.25\"\n---\nfn main() {}\n\"#,\n            str![[r##\"\nshebang: \"#!/usr/bin/env cargo\\n\"\ninfo: None\nfrontmatter: \"[dependencies]\\ntime=\\\"0.1.25\\\"\\n\"\ncontent: \"fn main() {}\\n\"\n\n\"##]],\n        );\n    }\n\n    #[test]\n    fn split_crlf() {\n        assert_source(\n            \"#!/usr/bin/env cargo\\r\\n---\\r\\n[dependencies]\\r\\ntime=\\\"0.1.25\\\"\\r\\n---\\r\\nfn main() {}\",\n            str![[r##\"\nshebang: \"#!/usr/bin/env cargo\\r\\n\"\ninfo: None\nfrontmatter: \"[dependencies]\\r\\ntime=\\\"0.1.25\\\"\\r\\n\"\ncontent: \"fn main() {}\"\n\n\"##]],\n        );\n    }\n\n    #[test]\n    fn split_leading_newlines() {\n        assert_source(\n            r#\"#!/usr/bin/env cargo\n    \n\n\n---\n[dependencies]\ntime=\"0.1.25\"\n---\n\n\nfn main() {}\n\"#,\n            str![[r##\"\nshebang: \"#!/usr/bin/env cargo\\n\"\ninfo: None\nfrontmatter: \"[dependencies]\\ntime=\\\"0.1.25\\\"\\n\"\ncontent: \"\\n\\nfn main() {}\\n\"\n\n\"##]],\n        );\n    }\n\n    #[test]\n    fn split_attribute() {\n        assert_source(\n            r#\"#[allow(dead_code)]\n---\n[dependencies]\ntime=\"0.1.25\"\n---\nfn main() {}\n\"#,\n            str![[r##\"\nshebang: None\ninfo: None\nfrontmatter: None\ncontent: \"#[allow(dead_code)]\\n---\\n[dependencies]\\ntime=\\\"0.1.25\\\"\\n---\\nfn main() {}\\n\"\n\n\"##]],\n        );\n    }\n\n    #[test]\n    fn split_extra_dash() {\n        assert_source(\n            r#\"#!/usr/bin/env cargo\n----------\n[dependencies]\ntime=\"0.1.25\"\n----------\n\nfn main() {}\"#,\n            str![[r##\"\nshebang: \"#!/usr/bin/env cargo\\n\"\ninfo: None\nfrontmatter: \"[dependencies]\\ntime=\\\"0.1.25\\\"\\n\"\ncontent: \"\\nfn main() {}\"\n\n\"##]],\n        );\n    }\n\n    #[test]\n    fn split_too_few_dashes() {\n        assert_err(\n            ScriptSource::parse(\n                r#\"#!/usr/bin/env cargo\n--\n[dependencies]\ntime=\"0.1.25\"\n--\nfn main() {}\n\"#,\n            ),\n            str![\"found 2 `-` in rust frontmatter, expected at least 3\"],\n        );\n    }\n\n    #[test]\n    fn split_indent() {\n        assert_source(\n            r#\"#!/usr/bin/env cargo\n    ---\n    [dependencies]\n    time=\"0.1.25\"\n    ----\n\nfn main() {}\n\"#,\n            str![[r##\"\nshebang: \"#!/usr/bin/env cargo\\n\"\ninfo: None\nfrontmatter: None\ncontent: \"    ---\\n    [dependencies]\\n    time=\\\"0.1.25\\\"\\n    ----\\n\\nfn main() {}\\n\"\n\n\"##]],\n        );\n    }\n\n    #[test]\n    fn split_escaped() {\n        assert_source(\n            r#\"#!/usr/bin/env cargo\n-----\n---\n---\n-----\n\nfn main() {}\n\"#,\n            str![[r##\"\nshebang: \"#!/usr/bin/env cargo\\n\"\ninfo: None\nfrontmatter: \"---\\n---\\n\"\ncontent: \"\\nfn main() {}\\n\"\n\n\"##]],\n        );\n    }\n\n    #[test]\n    fn split_invalid_escaped() {\n        assert_err(\n            ScriptSource::parse(\n                r#\"#!/usr/bin/env cargo\n---\n-----\n-----\n---\n\nfn main() {}\n\"#,\n            ),\n            str![\"closing code fence has 2 more `-` than the opening fence\"],\n        );\n    }\n\n    #[test]\n    fn split_dashes_in_body() {\n        assert_source(\n            r#\"#!/usr/bin/env cargo\n---\nHello---\nWorld\n---\n\nfn main() {}\n\"#,\n            str![[r##\"\nshebang: \"#!/usr/bin/env cargo\\n\"\ninfo: None\nfrontmatter: \"Hello---\\nWorld\\n\"\ncontent: \"\\nfn main() {}\\n\"\n\n\"##]],\n        );\n    }\n\n    #[test]\n    fn split_mismatched_dashes() {\n        assert_err(\n            ScriptSource::parse(\n                r#\"#!/usr/bin/env cargo\n---\n[dependencies]\ntime=\"0.1.25\"\n----\nfn main() {}\n\"#,\n            ),\n            str![\"closing code fence has 1 more `-` than the opening fence\"],\n        );\n    }\n\n    #[test]\n    fn split_missing_close() {\n        assert_err(\n            ScriptSource::parse(\n                r#\"#!/usr/bin/env cargo\n---\n[dependencies]\ntime=\"0.1.25\"\nfn main() {}\n\"#,\n            ),\n            str![\"unclosed frontmatter; expected `---`\"],\n        );\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/graph.rs",
    "content": "use std::borrow::Borrow;\nuse std::collections::{BTreeMap, BTreeSet, VecDeque};\nuse std::fmt;\n\npub struct Graph<N: Clone, E: Clone> {\n    nodes: im_rc::OrdMap<N, im_rc::OrdMap<N, E>>,\n}\n\nimpl<N: Eq + Ord + Clone, E: Default + Clone> Graph<N, E> {\n    pub fn new() -> Graph<N, E> {\n        Graph {\n            nodes: im_rc::OrdMap::new(),\n        }\n    }\n\n    pub fn add(&mut self, node: N) {\n        self.nodes.entry(node).or_insert_with(im_rc::OrdMap::new);\n    }\n\n    pub fn link(&mut self, node: N, child: N) -> &mut E {\n        self.nodes\n            .entry(node)\n            .or_insert_with(im_rc::OrdMap::new)\n            .entry(child)\n            .or_default()\n    }\n\n    /// Returns the graph obtained by reversing all edges.\n    pub fn reversed(&self) -> Graph<N, E> {\n        let mut ret = Graph::new();\n\n        for n in self.iter() {\n            ret.add(n.clone());\n            for (m, e) in self.edges(n) {\n                *ret.link(m.clone(), n.clone()) = e.clone();\n            }\n        }\n\n        ret\n    }\n\n    pub fn contains<Q: ?Sized>(&self, k: &Q) -> bool\n    where\n        N: Borrow<Q>,\n        Q: Ord + Eq,\n    {\n        self.nodes.contains_key(k)\n    }\n\n    pub fn edge(&self, from: &N, to: &N) -> Option<&E> {\n        self.nodes.get(from)?.get(to)\n    }\n\n    pub fn edges(&self, from: &N) -> impl Iterator<Item = (&N, &E)> + use<'_, N, E> {\n        self.nodes.get(from).into_iter().flat_map(|x| x.iter())\n    }\n\n    /// A topological sort of the `Graph`\n    pub fn sort(&self) -> Vec<N> {\n        let mut ret = Vec::new();\n        let mut marks = BTreeSet::new();\n\n        for node in self.nodes.keys() {\n            self.sort_inner_visit(node, &mut ret, &mut marks);\n        }\n\n        ret\n    }\n\n    fn sort_inner_visit(&self, node: &N, dst: &mut Vec<N>, marks: &mut BTreeSet<N>) {\n        if !marks.insert(node.clone()) {\n            return;\n        }\n\n        for child in self.nodes[node].keys() {\n            self.sort_inner_visit(child, dst, marks);\n        }\n\n        dst.push(node.clone());\n    }\n\n    pub fn iter(&self) -> impl Iterator<Item = &N> {\n        self.nodes.keys()\n    }\n\n    pub fn len(&self) -> usize {\n        self.nodes.len()\n    }\n\n    /// Checks if there is a path from `from` to `to`.\n    pub fn is_path_from_to<'a>(&'a self, from: &'a N, to: &'a N) -> bool {\n        let mut stack = vec![from];\n        let mut seen = BTreeSet::new();\n        seen.insert(from);\n        while let Some(iter) = stack.pop().and_then(|p| self.nodes.get(p)) {\n            for p in iter.keys() {\n                if p == to {\n                    return true;\n                }\n                if seen.insert(p) {\n                    stack.push(p);\n                }\n            }\n        }\n        false\n    }\n\n    /// Resolves one of the paths from the given dependent package down to a leaf.\n    ///\n    /// The path return will be the shortest path, or more accurately one of the paths with the shortest length.\n    ///\n    /// Each element contains a node along with an edge except the first one.\n    /// The representation would look like:\n    ///\n    /// (Node0,) -> (Node1, Edge01) -> (Node2, Edge12)...\n    pub fn path_to_bottom<'a>(&'a self, pkg: &'a N) -> Vec<(&'a N, Option<&'a E>)> {\n        self.path_to(pkg, |s, p| s.edges(p))\n    }\n\n    /// Resolves one of the paths from the given dependent package up to the root.\n    ///\n    /// The path return will be the shortest path, or more accurately one of the paths with the shortest length.\n    ///\n    /// Each element contains a node along with an edge except the first one.\n    /// The representation would look like:\n    ///\n    /// (Node0,) -> (Node1, Edge01) -> (Node2, Edge12)...\n    pub fn path_to_top<'a>(&'a self, pkg: &'a N) -> Vec<(&'a N, Option<&'a E>)> {\n        self.path_to(pkg, |s, pk| {\n            // Note that this implementation isn't the most robust per se, we'll\n            // likely have to tweak this over time. For now though it works for what\n            // it's used for!\n            s.nodes\n                .iter()\n                .filter_map(|(p, adjacent)| adjacent.get(pk).map(|e| (p, e)))\n        })\n    }\n}\n\nimpl<'s, N: Eq + Ord + Clone + 's, E: Default + Clone + 's> Graph<N, E> {\n    fn path_to<'a, F, I>(&'s self, pkg: &'a N, fn_edge: F) -> Vec<(&'a N, Option<&'a E>)>\n    where\n        I: Iterator<Item = (&'a N, &'a E)>,\n        F: Fn(&'s Self, &'a N) -> I,\n        'a: 's,\n    {\n        let mut back_link = BTreeMap::new();\n        let mut queue = VecDeque::from([pkg]);\n        let mut last = pkg;\n\n        while let Some(p) = queue.pop_front() {\n            last = p;\n            let mut out_edges = true;\n            for (child, edge) in fn_edge(&self, p) {\n                out_edges = false;\n                back_link.entry(child).or_insert_with(|| {\n                    queue.push_back(child);\n                    (p, edge)\n                });\n            }\n            if out_edges {\n                break;\n            }\n        }\n\n        let mut result = Vec::new();\n        let mut next = last;\n        while let Some((p, e)) = back_link.remove(&next) {\n            result.push((next, Some(e)));\n            next = p;\n        }\n        if result.iter().all(|(n, _)| n != &next) {\n            result.push((next, None));\n        }\n        result.reverse();\n        #[cfg(debug_assertions)]\n        {\n            for x in result.windows(2) {\n                let [(n2, _), (n1, Some(e12))] = x else {\n                    unreachable!()\n                };\n                assert!(std::ptr::eq(\n                    self.edge(n1, n2).or(self.edge(n2, n1)).unwrap(),\n                    *e12\n                ));\n            }\n            let last = result.last().unwrap().0;\n            let set: Vec<_> = result.iter().map(|(k, _)| k).collect();\n            if !fn_edge(&self, last)\n                .filter(|(e, _)| !set.contains(&e))\n                .next()\n                .is_none()\n            {\n                self.print_for_test();\n                unreachable!(\"The last element in the path should not have outgoing edges\");\n            }\n        }\n        result\n    }\n}\n\n#[test]\nfn path_to_case() {\n    let mut new = Graph::new();\n    new.link(0, 3);\n    new.link(1, 0);\n    new.link(2, 0);\n    new.link(2, 1);\n    assert_eq!(\n        new.path_to_bottom(&2),\n        vec![(&2, None), (&0, Some(&())), (&3, Some(&()))]\n    );\n}\n\n#[test]\nfn path_to_self() {\n    // Extracted from #12941\n    let mut new: Graph<i32, ()> = Graph::new();\n    new.link(0, 0);\n    assert_eq!(new.path_to_bottom(&0), vec![(&0, Some(&()))]);\n}\n\n#[test]\nfn reverse() {\n    let mut new: Graph<i32, ()> = Graph::new();\n    new.link(0, 1);\n    new.link(0, 2);\n\n    let mut expected: Graph<i32, ()> = Graph::new();\n    expected.add(0);\n    expected.link(1, 0);\n    expected.link(2, 0);\n    assert_eq!(new.reversed(), expected);\n}\n\nimpl<N: Eq + Ord + Clone, E: Default + Clone> Default for Graph<N, E> {\n    fn default() -> Graph<N, E> {\n        Graph::new()\n    }\n}\n\nimpl<N: fmt::Display + Eq + Ord + Clone, E: Clone> fmt::Debug for Graph<N, E> {\n    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {\n        writeln!(fmt, \"Graph {{\")?;\n\n        for (n, e) in &self.nodes {\n            writeln!(fmt, \"  - {}\", n)?;\n\n            for n in e.keys() {\n                writeln!(fmt, \"    - {}\", n)?;\n            }\n        }\n\n        write!(fmt, \"}}\")?;\n\n        Ok(())\n    }\n}\n\nimpl<N: Eq + Ord + Clone, E: Clone> Graph<N, E> {\n    /// Prints the graph for constructing unit tests.\n    ///\n    /// For purposes of graph traversal algorithms the edge values do not matter,\n    /// and the only value of the node we care about is the order it gets compared in.\n    /// This constructs a graph with the same topology but with integer keys and unit edges.\n    #[cfg(debug_assertions)]\n    #[allow(clippy::print_stderr)]\n    fn print_for_test(&self) {\n        // Isolate and print a test case.\n        let names = self\n            .nodes\n            .keys()\n            .chain(self.nodes.values().flat_map(|vs| vs.keys()))\n            .collect::<BTreeSet<_>>()\n            .into_iter()\n            .collect::<Vec<_>>();\n        let mut new = Graph::new();\n        for n1 in self.nodes.keys() {\n            let name1 = names.binary_search(&n1).unwrap();\n            new.add(name1);\n            for n2 in self.nodes[n1].keys() {\n                let name2 = names.binary_search(&n2).unwrap();\n                *new.link(name1, name2) = ();\n            }\n        }\n        eprintln!(\"Graph for tests = {new:#?}\");\n    }\n}\n\nimpl<N: Eq + Ord + Clone, E: Eq + Clone> PartialEq for Graph<N, E> {\n    fn eq(&self, other: &Graph<N, E>) -> bool {\n        self.nodes.eq(&other.nodes)\n    }\n}\nimpl<N: Eq + Ord + Clone, E: Eq + Clone> Eq for Graph<N, E> {}\n\nimpl<N: Eq + Ord + Clone, E: Clone> Clone for Graph<N, E> {\n    fn clone(&self) -> Graph<N, E> {\n        Graph {\n            nodes: self.nodes.clone(),\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/hasher.rs",
    "content": "//! A hasher that produces the same values across releases and platforms.\n//!\n//! The hasher should be fast and have a low chance of collisions (but is not\n//! sufficient for cryptographic purposes).\n\npub use rustc_stable_hash::StableSipHasher128 as StableHasher;\n"
  },
  {
    "path": "src/cargo/util/hex.rs",
    "content": "use super::StableHasher;\nuse std::fs::File;\nuse std::hash::{Hash, Hasher};\nuse std::io::Read;\n\npub fn to_hex(num: u64) -> String {\n    hex::encode(num.to_le_bytes())\n}\n\npub fn hash_u64<H: Hash>(hashable: H) -> u64 {\n    let mut hasher = StableHasher::new();\n    hashable.hash(&mut hasher);\n    Hasher::finish(&hasher)\n}\n\npub fn hash_u64_file(mut file: &File) -> std::io::Result<u64> {\n    let mut hasher = StableHasher::new();\n    let mut buf = [0; 64 * 1024];\n    loop {\n        let n = file.read(&mut buf)?;\n        if n == 0 {\n            break;\n        }\n        hasher.write(&buf[..n]);\n    }\n    Ok(Hasher::finish(&hasher))\n}\n\npub fn short_hash<H: Hash>(hashable: &H) -> String {\n    to_hex(hash_u64(hashable))\n}\n"
  },
  {
    "path": "src/cargo/util/important_paths.rs",
    "content": "use crate::util::errors::CargoResult;\nuse cargo_util::paths;\nuse std::path::{Path, PathBuf};\n\n/// Finds the root `Cargo.toml`.\npub fn find_root_manifest_for_wd(cwd: &Path) -> CargoResult<PathBuf> {\n    let valid_cargo_toml_file_name = \"Cargo.toml\";\n    let invalid_cargo_toml_file_name = \"cargo.toml\";\n    let mut invalid_cargo_toml_path_exists = false;\n\n    for current in paths::ancestors(cwd, None) {\n        let manifest = current.join(valid_cargo_toml_file_name);\n        if manifest.exists() {\n            return Ok(manifest);\n        }\n        if current.join(invalid_cargo_toml_file_name).exists() {\n            invalid_cargo_toml_path_exists = true;\n        }\n    }\n\n    if invalid_cargo_toml_path_exists {\n        anyhow::bail!(\n            \"could not find `{}` in `{}` or any parent directory, but found cargo.toml please try to rename it to Cargo.toml\",\n            valid_cargo_toml_file_name,\n            cwd.display()\n        )\n    } else {\n        anyhow::bail!(\n            \"could not find `{}` in `{}` or any parent directory\",\n            valid_cargo_toml_file_name,\n            cwd.display()\n        )\n    }\n}\n\n/// Returns the path to the `file` in `pwd`, if it exists.\npub fn find_project_manifest_exact(pwd: &Path, file: &str) -> CargoResult<PathBuf> {\n    let manifest = pwd.join(file);\n\n    if manifest.exists() {\n        Ok(manifest)\n    } else {\n        anyhow::bail!(\"Could not find `{}` in `{}`\", file, pwd.display())\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/interning.rs",
    "content": "use serde::{Serialize, Serializer};\nuse serde_untagged::UntaggedEnumVisitor;\nuse std::borrow::Borrow;\nuse std::borrow::Cow;\nuse std::cmp::Ordering;\nuse std::collections::HashSet;\nuse std::ffi::OsStr;\nuse std::fmt;\nuse std::hash::{Hash, Hasher};\nuse std::ops::Deref;\nuse std::path::Path;\nuse std::ptr;\nuse std::str;\nuse std::sync::Mutex;\nuse std::sync::OnceLock;\n\npub static INTERNED_DEFAULT: InternedString = InternedString { inner: \"default\" };\n\nfn interned_storage() -> std::sync::MutexGuard<'static, HashSet<&'static str>> {\n    static STRING_CACHE: OnceLock<Mutex<HashSet<&'static str>>> = OnceLock::new();\n    STRING_CACHE\n        .get_or_init(|| {\n            let mut out: HashSet<&'static str> = Default::default();\n            out.insert(INTERNED_DEFAULT.as_str());\n            Mutex::new(out)\n        })\n        .lock()\n        .unwrap()\n}\n\n#[derive(Clone, Copy)]\npub struct InternedString {\n    inner: &'static str,\n}\n\nimpl<'a> From<&'a str> for InternedString {\n    fn from(item: &'a str) -> Self {\n        InternedString::new(item)\n    }\n}\n\nimpl<'a> From<&'a String> for InternedString {\n    fn from(item: &'a String) -> Self {\n        InternedString::new(item)\n    }\n}\n\nimpl From<String> for InternedString {\n    fn from(item: String) -> Self {\n        InternedString::from(Cow::Owned(item))\n    }\n}\n\nimpl PartialEq for InternedString {\n    fn eq(&self, other: &InternedString) -> bool {\n        ptr::eq(self.as_str(), other.as_str())\n    }\n}\n\nimpl PartialEq<str> for InternedString {\n    fn eq(&self, other: &str) -> bool {\n        *self == other\n    }\n}\n\nimpl<'a> PartialEq<&'a str> for InternedString {\n    fn eq(&self, other: &&str) -> bool {\n        **self == **other\n    }\n}\n\nimpl<'a> From<Cow<'a, str>> for InternedString {\n    fn from(cs: Cow<'a, str>) -> Self {\n        let mut cache = interned_storage();\n        let s = cache.get(cs.as_ref()).copied().unwrap_or_else(|| {\n            let s = cs.into_owned().leak();\n            cache.insert(s);\n            s\n        });\n\n        InternedString { inner: s }\n    }\n}\n\nimpl Eq for InternedString {}\n\nimpl InternedString {\n    pub fn new(s: &str) -> InternedString {\n        InternedString::from(Cow::Borrowed(s))\n    }\n    pub fn as_str(&self) -> &'static str {\n        self.inner\n    }\n}\n\nimpl Deref for InternedString {\n    type Target = str;\n\n    fn deref(&self) -> &'static str {\n        self.as_str()\n    }\n}\n\nimpl AsRef<str> for InternedString {\n    fn as_ref(&self) -> &str {\n        self.as_str()\n    }\n}\n\nimpl AsRef<OsStr> for InternedString {\n    fn as_ref(&self) -> &OsStr {\n        self.as_str().as_ref()\n    }\n}\n\nimpl AsRef<Path> for InternedString {\n    fn as_ref(&self) -> &Path {\n        self.as_str().as_ref()\n    }\n}\n\nimpl Hash for InternedString {\n    // N.B., we can't implement this as `identity(self).hash(state)`,\n    // because we use this for on-disk fingerprints and so need\n    // stability across Cargo invocations.\n    fn hash<H: Hasher>(&self, state: &mut H) {\n        self.as_str().hash(state);\n    }\n}\n\nimpl Borrow<str> for InternedString {\n    // If we implement Hash as `identity(self).hash(state)`,\n    // then this will need to be removed.\n    fn borrow(&self) -> &str {\n        self.as_str()\n    }\n}\n\nimpl fmt::Debug for InternedString {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt::Debug::fmt(self.as_str(), f)\n    }\n}\n\nimpl fmt::Display for InternedString {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt::Display::fmt(self.as_str(), f)\n    }\n}\n\nimpl Ord for InternedString {\n    fn cmp(&self, other: &InternedString) -> Ordering {\n        self.as_str().cmp(other.as_str())\n    }\n}\n\nimpl PartialOrd for InternedString {\n    fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {\n        Some(self.cmp(other))\n    }\n}\n\nimpl Serialize for InternedString {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: Serializer,\n    {\n        serializer.serialize_str(self.inner)\n    }\n}\n\nimpl<'de> serde::Deserialize<'de> for InternedString {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        UntaggedEnumVisitor::new()\n            .expecting(\"an String like thing\")\n            .string(|value| Ok(value.into()))\n            .deserialize(deserializer)\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/into_url.rs",
    "content": "use std::path::{Path, PathBuf};\n\nuse url::Url;\n\nuse crate::util::CargoResult;\n\n/// A type that can be converted to a Url\npub trait IntoUrl {\n    /// Performs the conversion\n    fn into_url(self) -> CargoResult<Url>;\n}\n\nimpl<'a> IntoUrl for &'a str {\n    fn into_url(self) -> CargoResult<Url> {\n        Url::parse(self).map_err(|s| {\n            if self.starts_with(\"git@\") {\n                anyhow::format_err!(\n                    \"invalid url `{}`: {}; try using `{}` instead\",\n                    self,\n                    s,\n                    format_args!(\"ssh://{}\", self.replacen(':', \"/\", 1))\n                )\n            } else {\n                anyhow::format_err!(\"invalid url `{}`: {}\", self, s)\n            }\n        })\n    }\n}\n\nimpl<'a> IntoUrl for &'a Path {\n    fn into_url(self) -> CargoResult<Url> {\n        Url::from_file_path(self)\n            .map_err(|()| anyhow::format_err!(\"invalid path url `{}`\", self.display()))\n    }\n}\n\nimpl<'a> IntoUrl for &'a PathBuf {\n    fn into_url(self) -> CargoResult<Url> {\n        self.as_path().into_url()\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/into_url_with_base.rs",
    "content": "use crate::util::{CargoResult, IntoUrl};\n\nuse url::Url;\n\n/// A type that can be interpreted as a relative Url and converted to\n/// a Url.\npub trait IntoUrlWithBase {\n    /// Performs the conversion\n    fn into_url_with_base<U: IntoUrl>(self, base: Option<U>) -> CargoResult<Url>;\n}\n\nimpl<'a> IntoUrlWithBase for &'a str {\n    fn into_url_with_base<U: IntoUrl>(self, base: Option<U>) -> CargoResult<Url> {\n        let base_url = match base {\n            Some(base) => Some(\n                base.into_url()\n                    .map_err(|s| anyhow::format_err!(\"invalid url `{}`: {}\", self, s))?,\n            ),\n            None => None,\n        };\n\n        Url::options()\n            .base_url(base_url.as_ref())\n            .parse(self)\n            .map_err(|s| anyhow::format_err!(\"invalid url `{}`: {}\", self, s))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::util::IntoUrlWithBase;\n\n    #[test]\n    fn into_url_with_base() {\n        assert_eq!(\n            \"rel/path\"\n                .into_url_with_base(Some(\"file:///abs/path/\"))\n                .unwrap()\n                .to_string(),\n            \"file:///abs/path/rel/path\"\n        );\n        assert_eq!(\n            \"rel/path\"\n                .into_url_with_base(Some(\"file:///abs/path/popped-file\"))\n                .unwrap()\n                .to_string(),\n            \"file:///abs/path/rel/path\"\n        );\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/io.rs",
    "content": "use std::io::{self, Read, Take};\n\n#[derive(Debug)]\npub struct LimitErrorReader<R> {\n    inner: Take<R>,\n}\n\nimpl<R: Read> LimitErrorReader<R> {\n    pub fn new(r: R, limit: u64) -> LimitErrorReader<R> {\n        LimitErrorReader {\n            inner: r.take(limit),\n        }\n    }\n}\n\nimpl<R: Read> Read for LimitErrorReader<R> {\n    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {\n        match self.inner.read(buf) {\n            Ok(0) if self.inner.limit() == 0 => Err(io::Error::new(\n                io::ErrorKind::Other,\n                \"maximum limit reached when reading\",\n            )),\n            e => e,\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::LimitErrorReader;\n\n    use std::io::Read;\n\n    #[test]\n    fn under_the_limit() {\n        let buf = &[1; 7][..];\n        let mut r = LimitErrorReader::new(buf, 8);\n        let mut out = Vec::new();\n        assert!(matches!(r.read_to_end(&mut out), Ok(7)));\n        assert_eq!(buf, out.as_slice());\n    }\n\n    #[test]\n    #[should_panic = \"maximum limit reached when reading\"]\n    fn over_the_limit() {\n        let buf = &[1; 8][..];\n        let mut r = LimitErrorReader::new(buf, 8);\n        let mut out = Vec::new();\n        r.read_to_end(&mut out).unwrap();\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/job.rs",
    "content": "//! Job management (mostly for windows)\n//!\n//! Most of the time when you're running cargo you expect Ctrl-C to actually\n//! terminate the entire tree of processes in play, not just the one at the top\n//! (cargo). This currently works \"by default\" on Unix platforms because Ctrl-C\n//! actually sends a signal to the *process group* rather than the parent\n//! process, so everything will get torn down. On Windows, however, this does\n//! not happen and Ctrl-C just kills cargo.\n//!\n//! To achieve the same semantics on Windows we use Job Objects to ensure that\n//! all processes die at the same time. Job objects have a mode of operation\n//! where when all handles to the object are closed it causes all child\n//! processes associated with the object to be terminated immediately.\n//! Conveniently whenever a process in the job object spawns a new process the\n//! child will be associated with the job object as well. This means if we add\n//! ourselves to the job object we create then everything will get torn down!\n\npub use self::imp::Setup;\n\npub fn setup() -> Option<Setup> {\n    unsafe { imp::setup() }\n}\n\n#[cfg(unix)]\nmod imp {\n    use std::env;\n\n    pub type Setup = ();\n\n    pub unsafe fn setup() -> Option<()> {\n        // There's a test case for the behavior of\n        // when-cargo-is-killed-subprocesses-are-also-killed, but that requires\n        // one cargo spawned to become its own session leader, so we do that\n        // here.\n        #[expect(\n            clippy::disallowed_methods,\n            reason = \"testing only, no reason for config support\"\n        )]\n        if env::var(\"__CARGO_TEST_SETSID_PLEASE_DONT_USE_ELSEWHERE\").is_ok() {\n            // SAFETY: I'm unaware of any safety requirements for this function.\n            unsafe {\n                libc::setsid();\n            }\n        }\n        Some(())\n    }\n}\n\n#[cfg(windows)]\nmod imp {\n    use std::io;\n    use std::mem;\n    use std::ptr;\n    use std::ptr::addr_of;\n\n    use tracing::info;\n\n    use windows_sys::Win32::Foundation::CloseHandle;\n    use windows_sys::Win32::Foundation::HANDLE;\n    use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;\n    use windows_sys::Win32::System::JobObjects::AssignProcessToJobObject;\n    use windows_sys::Win32::System::JobObjects::CreateJobObjectW;\n    use windows_sys::Win32::System::JobObjects::JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;\n    use windows_sys::Win32::System::JobObjects::JOBOBJECT_EXTENDED_LIMIT_INFORMATION;\n    use windows_sys::Win32::System::JobObjects::JobObjectExtendedLimitInformation;\n    use windows_sys::Win32::System::JobObjects::SetInformationJobObject;\n    use windows_sys::Win32::System::Threading::GetCurrentProcess;\n\n    pub struct Setup {\n        job: Handle,\n    }\n\n    pub struct Handle {\n        inner: HANDLE,\n    }\n\n    fn last_err() -> io::Error {\n        io::Error::last_os_error()\n    }\n\n    pub unsafe fn setup() -> Option<Setup> {\n        // Creates a new job object for us to use and then adds ourselves to it.\n        // Note that all errors are basically ignored in this function,\n        // intentionally. Job objects are \"relatively new\" in Windows,\n        // particularly the ability to support nested job objects. Older\n        // Windows installs don't support this ability. We probably don't want\n        // to force Cargo to abort in this situation or force others to *not*\n        // use job objects, so we instead just ignore errors and assume that\n        // we're otherwise part of someone else's job object in this case.\n\n        let job = unsafe { CreateJobObjectW(ptr::null_mut(), ptr::null()) };\n        if job == INVALID_HANDLE_VALUE {\n            return None;\n        }\n        let job = Handle { inner: job };\n\n        // Indicate that when all handles to the job object are gone that all\n        // process in the object should be killed. Note that this includes our\n        // entire process tree by default because we've added ourselves and\n        // our children will reside in the job once we spawn a process.\n        let mut info: JOBOBJECT_EXTENDED_LIMIT_INFORMATION;\n        info = unsafe { mem::zeroed() };\n        info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;\n        let r = unsafe {\n            SetInformationJobObject(\n                job.inner,\n                JobObjectExtendedLimitInformation,\n                addr_of!(info) as *const _,\n                mem::size_of_val(&info) as u32,\n            )\n        };\n        if r == 0 {\n            return None;\n        }\n\n        // Assign our process to this job object, meaning that our children will\n        // now live or die based on our existence.\n        let me = unsafe { GetCurrentProcess() };\n        let r = unsafe { AssignProcessToJobObject(job.inner, me) };\n        if r == 0 {\n            return None;\n        }\n\n        Some(Setup { job })\n    }\n\n    impl Drop for Setup {\n        fn drop(&mut self) {\n            // On normal exits (not ctrl-c), we don't want to kill any child\n            // processes. The destructor here configures our job object to\n            // **not** kill everything on close, then closes the job object.\n            unsafe {\n                let info: JOBOBJECT_EXTENDED_LIMIT_INFORMATION;\n                info = mem::zeroed();\n                let r = SetInformationJobObject(\n                    self.job.inner,\n                    JobObjectExtendedLimitInformation,\n                    addr_of!(info) as *const _,\n                    mem::size_of_val(&info) as u32,\n                );\n                if r == 0 {\n                    info!(\"failed to configure job object to defaults: {}\", last_err());\n                }\n            }\n        }\n    }\n\n    impl Drop for Handle {\n        fn drop(&mut self) {\n            unsafe {\n                CloseHandle(self.inner);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/lockserver.rs",
    "content": "//! An implementation of IPC locks, guaranteed to be released if a process dies\n//!\n//! This module implements a locking server/client where the main `cargo fix`\n//! process will start up a server and then all the client processes will\n//! connect to it. The main purpose of this file is to ensure that each crate\n//! (aka file entry point) is only fixed by one process at a time, currently\n//! concurrent fixes can't happen.\n//!\n//! The basic design here is to use a TCP server which is pretty portable across\n//! platforms. For simplicity it just uses threads as well. Clients connect to\n//! the main server, inform the server what its name is, and then wait for the\n//! server to give it the lock (aka write a byte).\n\nuse std::collections::HashMap;\nuse std::io::{BufRead, BufReader, Read, Write};\nuse std::net::{SocketAddr, TcpListener, TcpStream};\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::sync::{Arc, Mutex};\nuse std::thread::{self, JoinHandle};\n\nuse anyhow::{Context, Error};\n\nuse crate::util::network::LOCALHOST;\n\npub struct LockServer {\n    listener: TcpListener,\n    addr: SocketAddr,\n    threads: HashMap<String, ServerClient>,\n    done: Arc<AtomicBool>,\n}\n\npub struct LockServerStarted {\n    done: Arc<AtomicBool>,\n    addr: SocketAddr,\n    thread: Option<JoinHandle<()>>,\n}\n\npub struct LockServerClient {\n    _socket: TcpStream,\n}\n\nstruct ServerClient {\n    thread: Option<JoinHandle<()>>,\n    lock: Arc<Mutex<(bool, Vec<TcpStream>)>>,\n}\n\nimpl LockServer {\n    pub fn new() -> Result<LockServer, Error> {\n        let listener = TcpListener::bind(&LOCALHOST[..])\n            .context(\"failed to bind TCP listener to manage locking\")?;\n        let addr = listener.local_addr()?;\n        Ok(LockServer {\n            listener,\n            addr,\n            threads: HashMap::new(),\n            done: Arc::new(AtomicBool::new(false)),\n        })\n    }\n\n    pub fn addr(&self) -> &SocketAddr {\n        &self.addr\n    }\n\n    pub fn start(self) -> Result<LockServerStarted, Error> {\n        let addr = self.addr;\n        let done = self.done.clone();\n        let thread = thread::spawn(|| {\n            self.run();\n        });\n        Ok(LockServerStarted {\n            addr,\n            thread: Some(thread),\n            done,\n        })\n    }\n\n    fn run(mut self) {\n        while let Ok((client, _)) = self.listener.accept() {\n            if self.done.load(Ordering::SeqCst) {\n                break;\n            }\n\n            // Learn the name of our connected client to figure out if it needs\n            // to wait for another process to release the lock.\n            let mut client = BufReader::new(client);\n            let mut name = String::new();\n            if client.read_line(&mut name).is_err() {\n                continue;\n            }\n            let client = client.into_inner();\n\n            // If this \"named mutex\" is already registered and the thread is\n            // still going, put it on the queue. Otherwise wait on the previous\n            // thread and we'll replace it just below.\n            if let Some(t) = self.threads.get_mut(&name) {\n                let mut state = t.lock.lock().unwrap();\n                if state.0 {\n                    state.1.push(client);\n                    continue;\n                }\n                drop(t.thread.take().unwrap().join());\n            }\n\n            let lock = Arc::new(Mutex::new((true, vec![client])));\n            let lock2 = lock.clone();\n            let thread = thread::spawn(move || {\n                loop {\n                    let mut client = {\n                        let mut state = lock2.lock().unwrap();\n                        if state.1.is_empty() {\n                            state.0 = false;\n                            break;\n                        } else {\n                            state.1.remove(0)\n                        }\n                    };\n                    // Inform this client that it now has the lock and wait for\n                    // it to disconnect by waiting for EOF.\n                    if client.write_all(&[1]).is_err() {\n                        continue;\n                    }\n                    let mut dst = Vec::new();\n                    drop(client.read_to_end(&mut dst));\n                }\n            });\n\n            self.threads.insert(\n                name,\n                ServerClient {\n                    thread: Some(thread),\n                    lock,\n                },\n            );\n        }\n    }\n}\n\nimpl Drop for LockServer {\n    fn drop(&mut self) {\n        for (_, mut client) in self.threads.drain() {\n            if let Some(thread) = client.thread.take() {\n                drop(thread.join());\n            }\n        }\n    }\n}\n\nimpl Drop for LockServerStarted {\n    fn drop(&mut self) {\n        self.done.store(true, Ordering::SeqCst);\n        // Ignore errors here as this is largely best-effort\n        if TcpStream::connect(&self.addr).is_err() {\n            return;\n        }\n        drop(self.thread.take().unwrap().join());\n    }\n}\n\nimpl LockServerClient {\n    pub fn lock(addr: &SocketAddr, name: impl AsRef<[u8]>) -> Result<LockServerClient, Error> {\n        let mut client =\n            TcpStream::connect(&addr).context(\"failed to connect to parent lock server\")?;\n        client\n            .write_all(name.as_ref())\n            .and_then(|_| client.write_all(b\"\\n\"))\n            .context(\"failed to write to lock server\")?;\n        let mut buf = [0];\n        client\n            .read_exact(&mut buf)\n            .context(\"failed to acquire lock\")?;\n        Ok(LockServerClient { _socket: client })\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/log_message.rs",
    "content": "//! Messages for logging.\n\nuse std::borrow::Cow;\nuse std::io::Write;\nuse std::path::PathBuf;\n\nuse cargo_util_schemas::core::PackageIdSpec;\nuse jiff::Timestamp;\nuse serde::Deserialize;\nuse serde::Serialize;\n\nuse crate::core::compiler::CompileMode;\nuse crate::core::compiler::UnitIndex;\nuse crate::core::compiler::fingerprint::DirtyReason;\n\n/// A log message.\n///\n/// Each variant represents a different type of event.\n#[derive(Serialize, Deserialize, Clone)]\n#[serde(tag = \"reason\", rename_all = \"kebab-case\")]\npub enum LogMessage {\n    /// Emitted when a build starts.\n    BuildStarted {\n        /// The command-line arguments Cargo was invoked with.\n        command: Vec<String>,\n        /// Current working directory.\n        cwd: PathBuf,\n        /// Host triple.\n        host: String,\n        /// Number of parallel jobs.\n        jobs: u32,\n        /// Available parallelism of the compilation environment.\n        num_cpus: Option<u64>,\n        /// Build profile name (e.g., \"dev\", \"release\").\n        profile: String,\n        /// The rustc version (`1.23.4-beta.2`).\n        rustc_version: String,\n        /// The rustc verbose version information (the output of `rustc -vV`).\n        rustc_version_verbose: String,\n        /// Target directory for build artifacts.\n        target_dir: PathBuf,\n        /// Workspace root directory.\n        workspace_root: PathBuf,\n    },\n    /// Emitted when resolving dependencies starts.\n    ResolutionStarted {\n        /// Seconds elapsed from build start.\n        elapsed: f64,\n    },\n    /// Emitted when resolving dependencies finishes.\n    ResolutionFinished {\n        /// Seconds elapsed from build start.\n        elapsed: f64,\n    },\n    /// Emitted when unit graph generation starts.\n    UnitGraphStarted {\n        /// Seconds elapsed from build start.\n        elapsed: f64,\n    },\n    /// Emitted when unit graph generation finishes.\n    UnitGraphFinished {\n        /// Seconds elapsed from build start.\n        elapsed: f64,\n    },\n    /// Emitted when a compilation unit is registered in the unit graph,\n    /// right before [`LogMessage::UnitGraphFinished`] that Cargo finalizes\n    /// the unit graph.\n    UnitRegistered {\n        /// Package ID specification.\n        package_id: PackageIdSpec,\n        /// Cargo target (lib, bin, example, etc.).\n        target: Target,\n        /// The compilation action this unit is for (check, build, test, etc.).\n        mode: CompileMode,\n        /// The target platform this unit builds for.\n        ///\n        /// It is either a [target triple] the compiler accepts,\n        /// or a file name with the `json` extension for a [custom target].\n        ///\n        /// [target triple]: https://doc.rust-lang.org/nightly/rustc/platform-support.html\n        /// [custom target]: https://doc.rust-lang.org/nightly/rustc/targets/custom.html\n        platform: String,\n        /// Unit index for compact reference in subsequent events.\n        index: UnitIndex,\n        /// Enabled features.\n        #[serde(default, skip_serializing_if = \"Vec::is_empty\")]\n        features: Vec<String>,\n        /// Whether this is requested to build by user directly,\n        /// like via the `-p` flag or the default workspace members.\n        #[serde(default, skip_serializing_if = \"std::ops::Not::not\")]\n        requested: bool,\n        /// Unit indices that this unit depends on.\n        #[serde(default, skip_serializing_if = \"Vec::is_empty\")]\n        dependencies: Vec<UnitIndex>,\n    },\n    /// Emitted when a compilation unit starts.\n    UnitStarted {\n        /// Unit index from the associated unit-registered event.\n        index: UnitIndex,\n        /// Seconds elapsed from build start.\n        elapsed: f64,\n    },\n    /// Emitted when a section (e.g., rmeta, link) of the compilation unit finishes.\n    UnitRmetaFinished {\n        /// Unit index from the associated unit-registered event.\n        index: UnitIndex,\n        /// Seconds elapsed from build start.\n        elapsed: f64,\n        /// Unit indices that were unblocked by this rmeta completion.\n        #[serde(default, skip_serializing_if = \"Vec::is_empty\")]\n        unblocked: Vec<UnitIndex>,\n    },\n    /// Emitted when a section (e.g., rmeta, link) of the compilation unit starts.\n    ///\n    /// Requires `-Zsection-timings` to be enabled.\n    UnitSectionStarted {\n        /// Unit index from the associated unit-registered event.\n        index: UnitIndex,\n        /// Seconds elapsed from build start.\n        elapsed: f64,\n        /// Section name from rustc's `-Zjson=timings` (e.g., \"codegen\", \"link\").\n        section: String,\n    },\n    /// Emitted when a section (e.g., rmeta, link) of the compilation unit finishes.\n    ///\n    /// Requires `-Zsection-timings` to be enabled.\n    UnitSectionFinished {\n        /// Unit index from the associated unit-registered event.\n        index: UnitIndex,\n        /// Seconds elapsed from build start.\n        elapsed: f64,\n        /// Section name from rustc's `-Zjson=timings` (e.g., \"codegen\", \"link\").\n        section: String,\n    },\n    /// Emitted when a compilation unit finishes.\n    UnitFinished {\n        /// Unit index from the associated unit-registered event.\n        index: UnitIndex,\n        /// Seconds elapsed from build start.\n        elapsed: f64,\n        /// Unit indices that were unblocked by this completion.\n        #[serde(default, skip_serializing_if = \"Vec::is_empty\")]\n        unblocked: Vec<UnitIndex>,\n    },\n    /// Emitted when rebuild fingerprint information is determined for a unit.\n    UnitFingerprint {\n        /// Unit index from the associated unit-registered event.\n        index: UnitIndex,\n        /// Status of the rebuild detection fingerprint of this unit\n        status: FingerprintStatus,\n        /// Reason why the unit is dirty and needs rebuilding.\n        #[serde(default, skip_serializing_if = \"Option::is_none\")]\n        cause: Option<DirtyReason>,\n    },\n}\n\n/// Cargo target information.\n#[derive(Serialize, Deserialize, Clone)]\npub struct Target {\n    /// Target name.\n    pub name: String,\n    /// Target kind (lib, bin, test, bench, example, build-script).\n    pub kind: Cow<'static, str>,\n}\n\n/// Status of the rebuild detection fingerprint.\n#[derive(Serialize, Deserialize, Clone)]\n#[serde(rename_all = \"kebab-case\")]\npub enum FingerprintStatus {\n    /// There is no previous fingerprints for this unit.\n    /// Might be a brand-new build.\n    New,\n    /// The current fingerprint doesn't match the previous fingerprints.\n    /// Rebuild needed.\n    Dirty,\n    /// The current fingerprint matches the previous fingerprints.\n    /// No rebuild needed.\n    Fresh,\n}\n\nimpl From<&crate::core::Target> for Target {\n    fn from(target: &crate::core::Target) -> Self {\n        use crate::core::TargetKind;\n        Self {\n            name: target.name().to_string(),\n            kind: match target.kind() {\n                TargetKind::Lib(..) => \"lib\",\n                TargetKind::Bin => \"bin\",\n                TargetKind::Test => \"test\",\n                TargetKind::Bench => \"bench\",\n                TargetKind::ExampleLib(..) | TargetKind::ExampleBin => \"example\",\n                TargetKind::CustomBuild => \"build-script\",\n            }\n            .into(),\n        }\n    }\n}\n\nimpl LogMessage {\n    /// Serializes this message as a JSON log line directly to the writer.\n    pub fn write_json_log<W: Write>(&self, writer: &mut W, run_id: &str) -> std::io::Result<()> {\n        #[derive(Serialize)]\n        struct LogEntry<'a> {\n            run_id: &'a str,\n            timestamp: Timestamp,\n            #[serde(flatten)]\n            msg: &'a LogMessage,\n        }\n\n        let entry = LogEntry {\n            run_id,\n            timestamp: Timestamp::now(),\n            msg: self,\n        };\n\n        serde_json::to_writer(&mut *writer, &entry)?;\n        writer.write_all(b\"\\n\")?;\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/logger.rs",
    "content": "//! Build analysis logging infrastructure.\n\nuse std::cell::RefCell;\nuse std::hash::Hash;\nuse std::io::{BufWriter, Write};\nuse std::mem::ManuallyDrop;\nuse std::path::Path;\nuse std::sync::mpsc::{self, Sender};\nuse std::thread::JoinHandle;\n\nuse anyhow::Context as _;\nuse cargo_util::paths;\n\nuse crate::CargoResult;\nuse crate::core::Workspace;\nuse crate::core::compiler::BuildConfig;\nuse crate::util::log_message::LogMessage;\nuse crate::util::short_hash;\n\n// for newer `cargo report` commands\nstruct FileLogger {\n    tx: ManuallyDrop<Sender<LogMessage>>,\n    handle: Option<JoinHandle<()>>,\n}\n\nimpl FileLogger {\n    /// Creates a logger if `-Zbuild-analysis` is enabled\n    fn maybe_new(ws: &Workspace<'_>, run_id: &RunId) -> CargoResult<Option<FileLogger>> {\n        let analysis = ws.gctx().build_config()?.analysis.as_ref();\n        match (analysis, ws.gctx().cli_unstable().build_analysis) {\n            (Some(analysis), true) if analysis.enabled => {\n                let log_dir = ws.gctx().home().join(\"log\");\n                paths::create_dir_all(log_dir.as_path_unlocked())?;\n\n                let filename = format!(\"{run_id}.jsonl\");\n                let log_file = log_dir.open_rw_exclusive_create(\n                    Path::new(&filename),\n                    ws.gctx(),\n                    \"build analysis log\",\n                )?;\n\n                let (tx, rx) = mpsc::channel::<LogMessage>();\n\n                let run_id_str = run_id.to_string();\n                let handle = std::thread::spawn(move || {\n                    let mut writer = BufWriter::new(log_file);\n                    for msg in rx {\n                        let _ = msg.write_json_log(&mut writer, &run_id_str);\n                    }\n                    let _ = writer.flush();\n                });\n\n                Ok(Some(Self {\n                    tx: ManuallyDrop::new(tx),\n                    handle: Some(handle),\n                }))\n            }\n            (Some(_), false) => {\n                ws.gctx().shell().warn(\n                    \"ignoring 'build.analysis' config, pass `-Zbuild-analysis` to enable it\",\n                )?;\n                Ok(None)\n            }\n            _ => Ok(None),\n        }\n    }\n}\n\nimpl Drop for FileLogger {\n    fn drop(&mut self) {\n        // SAFETY: tx is dropped exactly once here to signal thread shutdown.\n        // ManuallyDrop prevents automatic drop after this impl runs.\n        unsafe {\n            ManuallyDrop::drop(&mut self.tx);\n        }\n\n        if let Some(handle) = self.handle.take() {\n            let _ = handle.join();\n        }\n    }\n}\n\n/// For legacy `cargo build --timings` flag\nstruct InMemoryLogger {\n    // using mutex to hide mutability\n    logs: RefCell<Vec<LogMessage>>,\n}\n\nimpl InMemoryLogger {\n    fn maybe_new(options: &BuildConfig) -> Option<Self> {\n        if options.timing_report {\n            Some(Self {\n                logs: RefCell::new(Vec::new()),\n            })\n        } else {\n            None\n        }\n    }\n}\n\n/// Logger for `-Zbuild-analysis`.\npub struct BuildLogger {\n    run_id: RunId,\n    file_logger: Option<FileLogger>,\n    in_memory_logger: Option<InMemoryLogger>,\n}\n\nimpl BuildLogger {\n    pub fn maybe_new(ws: &Workspace<'_>, options: &BuildConfig) -> CargoResult<Option<Self>> {\n        let run_id = Self::generate_run_id(ws);\n        let file_logger = FileLogger::maybe_new(ws, &run_id)?;\n        let in_memory_logger = InMemoryLogger::maybe_new(options);\n\n        if file_logger.is_none() && in_memory_logger.is_none() {\n            return Ok(None);\n        }\n\n        Ok(Some(Self {\n            run_id,\n            file_logger,\n            in_memory_logger,\n        }))\n    }\n\n    /// Generates a unique run ID.\n    pub fn generate_run_id(ws: &Workspace<'_>) -> RunId {\n        RunId::new(&ws.root())\n    }\n\n    /// Returns the run ID for this build session.\n    pub fn run_id(&self) -> &RunId {\n        &self.run_id\n    }\n\n    /// Logs a message.\n    pub fn log(&self, msg: LogMessage) {\n        if let Some(ref logger) = self.in_memory_logger {\n            let mut borrowed = logger.logs.try_borrow_mut().expect(\n                \"Unable to get a mutable reference to in-memory logger; please file a bug report\",\n            );\n            borrowed.push(msg.clone());\n        };\n\n        if let Some(ref logger) = self.file_logger {\n            let _ = logger.tx.send(msg);\n        };\n    }\n\n    pub fn get_logs(&self) -> Option<Vec<LogMessage>> {\n        self.in_memory_logger.as_ref().map(|l| {\n            l.logs\n                .try_borrow()\n                .expect(\"Unable to get a reference to in-memory logger; please file a bug report\")\n                .clone()\n        })\n    }\n}\n\n/// A unique identifier for a Cargo invocation.\n#[derive(Clone)]\npub struct RunId {\n    timestamp: jiff::Timestamp,\n    hash: String,\n}\n\nimpl RunId {\n    const FORMAT: &str = \"%Y%m%dT%H%M%S%3fZ\";\n\n    pub fn new<H: Hash>(h: &H) -> RunId {\n        RunId {\n            timestamp: jiff::Timestamp::now(),\n            hash: short_hash(h),\n        }\n    }\n\n    pub fn timestamp(&self) -> &jiff::Timestamp {\n        &self.timestamp\n    }\n\n    /// Checks whether ID was generated from the same workspace.\n    pub fn same_workspace(&self, other: &RunId) -> bool {\n        self.hash == other.hash\n    }\n}\n\nimpl std::fmt::Display for RunId {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let hash = &self.hash;\n        let timestamp = self.timestamp.strftime(Self::FORMAT);\n        write!(f, \"{timestamp}-{hash}\")\n    }\n}\n\nimpl std::str::FromStr for RunId {\n    type Err = anyhow::Error;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        let msg =\n            || format!(\"expect run ID in format `20060724T012128000Z-<16-char-hex>`, got `{s}`\");\n        let Some((timestamp, hash)) = s.rsplit_once('-') else {\n            anyhow::bail!(msg());\n        };\n\n        if hash.len() != 16 || !hash.chars().all(|c| c.is_ascii_hexdigit()) {\n            anyhow::bail!(msg());\n        }\n        let timestamp = jiff::civil::DateTime::strptime(Self::FORMAT, timestamp)\n            .and_then(|dt| dt.to_zoned(jiff::tz::TimeZone::UTC))\n            .map(|zoned| zoned.timestamp())\n            .with_context(msg)?;\n\n        Ok(RunId {\n            timestamp,\n            hash: hash.into(),\n        })\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn run_id_round_trip() {\n        let id = \"20060724T012128000Z-b0fd440798ab3cfb\";\n        assert_eq!(id, &id.parse::<RunId>().unwrap().to_string());\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/machine_message.rs",
    "content": "use std::path::{Path, PathBuf};\n\nuse cargo_util_schemas::core::PackageIdSpec;\nuse serde::Serialize;\nuse serde::ser;\nuse serde_json::value::RawValue;\n\nuse crate::core::Target;\n\npub trait Message: ser::Serialize {\n    fn reason(&self) -> &str;\n\n    fn to_json_string(&self) -> String {\n        #[derive(Serialize)]\n        struct WithReason<'a, S: Serialize> {\n            reason: &'a str,\n            #[serde(flatten)]\n            msg: &'a S,\n        }\n        let with_reason = WithReason {\n            reason: self.reason(),\n            msg: &self,\n        };\n        serde_json::to_string(&with_reason).unwrap()\n    }\n}\n\n#[derive(Serialize)]\npub struct FromCompiler<'a> {\n    pub package_id: PackageIdSpec,\n    pub manifest_path: &'a Path,\n    pub target: &'a Target,\n    pub message: Box<RawValue>,\n}\n\nimpl<'a> Message for FromCompiler<'a> {\n    fn reason(&self) -> &str {\n        \"compiler-message\"\n    }\n}\n\n#[derive(Serialize)]\npub struct Artifact<'a> {\n    pub package_id: PackageIdSpec,\n    pub manifest_path: PathBuf,\n    pub target: &'a Target,\n    pub profile: ArtifactProfile,\n    pub features: Vec<String>,\n    pub filenames: Vec<PathBuf>,\n    pub executable: Option<PathBuf>,\n    pub fresh: bool,\n}\n\nimpl<'a> Message for Artifact<'a> {\n    fn reason(&self) -> &str {\n        \"compiler-artifact\"\n    }\n}\n\n/// This is different from the regular `Profile` to maintain backwards\n/// compatibility (in particular, `test` is no longer in `Profile`, but we\n/// still want it to be included here).\n#[derive(Serialize)]\npub struct ArtifactProfile {\n    pub opt_level: &'static str,\n    pub debuginfo: Option<ArtifactDebuginfo>,\n    pub debug_assertions: bool,\n    pub overflow_checks: bool,\n    pub test: bool,\n}\n\n/// Internally this is an enum with different variants, but keep using 0/1/2 as integers for compatibility.\n#[derive(Serialize)]\n#[serde(untagged)]\npub enum ArtifactDebuginfo {\n    Int(u32),\n    Named(&'static str),\n}\n\n#[derive(Serialize)]\npub struct BuildScript<'a> {\n    pub package_id: PackageIdSpec,\n    pub linked_libs: &'a [String],\n    pub linked_paths: &'a [String],\n    pub cfgs: &'a [String],\n    pub env: &'a [(String, String)],\n    pub out_dir: &'a Path,\n}\n\nimpl<'a> Message for BuildScript<'a> {\n    fn reason(&self) -> &str {\n        \"build-script-executed\"\n    }\n}\n\n#[derive(Serialize)]\npub struct BuildFinished {\n    pub success: bool,\n}\n\nimpl Message for BuildFinished {\n    fn reason(&self) -> &str {\n        \"build-finished\"\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/mod.rs",
    "content": "use std::path::{Path, PathBuf};\nuse std::time::Duration;\n\npub use self::canonical_url::CanonicalUrl;\npub use self::context::{ConfigValue, GlobalContext, homedir};\npub(crate) use self::counter::MetricsCounter;\npub use self::dependency_queue::DependencyQueue;\npub use self::diagnostic_server::RustfixDiagnosticServer;\npub use self::edit_distance::{closest, closest_msg, edit_distance};\npub use self::errors::CliError;\npub use self::errors::{CargoResult, CliResult, internal};\npub use self::flock::{FileLock, Filesystem};\npub use self::graph::Graph;\npub use self::hasher::StableHasher;\npub use self::hex::{hash_u64, short_hash, to_hex};\npub use self::into_url::IntoUrl;\npub use self::into_url_with_base::IntoUrlWithBase;\npub(crate) use self::io::LimitErrorReader;\npub use self::lockserver::{LockServer, LockServerClient, LockServerStarted};\npub use self::logger::BuildLogger;\npub use self::once::OnceExt;\npub use self::progress::{Progress, ProgressStyle};\npub use self::queue::Queue;\npub use self::rustc::Rustc;\npub use self::semver_ext::{OptVersionReq, VersionExt};\npub use self::vcs::{FossilRepo, GitRepo, HgRepo, PijulRepo, existing_vcs_repo};\npub use self::workspace::{\n    add_path_args, path_args, print_available_benches, print_available_binaries,\n    print_available_examples, print_available_packages, print_available_tests,\n};\n\npub mod auth;\npub mod cache_lock;\nmod canonical_url;\npub mod command_prelude;\npub mod context;\nmod counter;\npub mod cpu;\npub mod credential;\nmod dependency_queue;\npub mod diagnostic_server;\npub mod edit_distance;\npub mod errors;\npub mod flock;\npub mod frontmatter;\npub mod graph;\nmod hasher;\npub mod hex;\npub mod important_paths;\npub mod interning;\npub mod into_url;\nmod into_url_with_base;\nmod io;\npub mod job;\nmod lockserver;\npub mod log_message;\npub mod logger;\npub mod machine_message;\npub mod network;\nmod once;\npub mod open;\nmod progress;\nmod queue;\npub mod restricted_names;\npub mod rustc;\nmod semver_eval_ext;\nmod semver_ext;\npub mod sqlite;\npub mod style;\npub mod toml;\npub mod toml_mut;\nmod vcs;\nmod workspace;\n\npub fn is_rustup() -> bool {\n    #[expect(clippy::disallowed_methods, reason = \"consistency with rustup\")]\n    std::env::var_os(\"RUSTUP_HOME\").is_some()\n}\n\npub fn elapsed(duration: Duration) -> String {\n    let secs = duration.as_secs();\n\n    if secs >= 60 {\n        format!(\"{}m {:02}s\", secs / 60, secs % 60)\n    } else {\n        format!(\"{}.{:02}s\", secs, duration.subsec_nanos() / 10_000_000)\n    }\n}\n\n/// Formats a number of bytes into a human readable SI-prefixed size.\npub struct HumanBytes(pub u64);\n\nimpl std::fmt::Display for HumanBytes {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        const UNITS: [&str; 7] = [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\", \"PiB\", \"EiB\"];\n        let bytes = self.0 as f32;\n        let i = ((bytes.log2() / 10.0) as usize).min(UNITS.len() - 1);\n        let unit = UNITS[i];\n        let size = bytes / 1024_f32.powi(i as i32);\n\n        // Don't show a fractional number of bytes.\n        if i == 0 {\n            return write!(f, \"{size}{unit}\");\n        }\n\n        let Some(precision) = f.precision() else {\n            return write!(f, \"{size}{unit}\");\n        };\n        write!(f, \"{size:.precision$}{unit}\",)\n    }\n}\n\npub fn indented_lines(text: &str) -> String {\n    text.lines()\n        .map(|line| {\n            if line.is_empty() {\n                String::from(\"\\n\")\n            } else {\n                format!(\"  {}\\n\", line)\n            }\n        })\n        .collect()\n}\n\npub fn truncate_with_ellipsis(s: &str, max_width: usize) -> String {\n    // We should truncate at grapheme-boundary and compute character-widths,\n    // yet the dependencies on unicode-segmentation and unicode-width are\n    // not worth it.\n    let mut chars = s.chars();\n    let mut prefix = (&mut chars).take(max_width - 1).collect::<String>();\n    if chars.next().is_some() {\n        prefix.push('…');\n    }\n    prefix\n}\n\n#[cfg(not(windows))]\n#[inline]\npub fn try_canonicalize<P: AsRef<Path>>(path: P) -> std::io::Result<PathBuf> {\n    std::fs::canonicalize(&path)\n}\n\n#[cfg(windows)]\n#[inline]\npub fn try_canonicalize<P: AsRef<Path>>(path: P) -> std::io::Result<PathBuf> {\n    use std::io::Error;\n    use std::io::ErrorKind;\n\n    // On Windows `canonicalize` may fail, so we fall back to getting an absolute path.\n    std::fs::canonicalize(&path).or_else(|_| {\n        // Return an error if a file does not exist for better compatibility with `canonicalize`\n        if !path.as_ref().try_exists()? {\n            return Err(Error::new(ErrorKind::NotFound, \"the path was not found\"));\n        }\n        std::path::absolute(&path)\n    })\n}\n\n/// Get the current [`umask`] value.\n///\n/// [`umask`]: https://man7.org/linux/man-pages/man2/umask.2.html\n#[cfg(unix)]\npub fn get_umask() -> u32 {\n    use std::sync::OnceLock;\n    static UMASK: OnceLock<libc::mode_t> = OnceLock::new();\n    // SAFETY: Syscalls are unsafe. Calling `umask` twice is even unsafer for\n    // multithreading program, since it doesn't provide a way to retrieve the\n    // value without modifications. We use a static `OnceLock` here to ensure\n    // it only gets call once during the entire program lifetime.\n    *UMASK.get_or_init(|| unsafe {\n        let umask = libc::umask(0o022);\n        libc::umask(umask);\n        umask\n    }) as u32 // it is u16 on macos\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n\n    #[track_caller]\n    fn t(bytes: u64, expected: &str) {\n        assert_eq!(&HumanBytes(bytes).to_string(), expected);\n    }\n\n    #[test]\n    fn test_human_readable_bytes() {\n        t(0, \"0B\");\n        t(8, \"8B\");\n        t(1000, \"1000B\");\n        t(1024, \"1KiB\");\n        t(1024 * 420 + 512, \"420.5KiB\");\n        t(1024 * 1024, \"1MiB\");\n        t(1024 * 1024 + 1024 * 256, \"1.25MiB\");\n        t(1024 * 1024 * 1024, \"1GiB\");\n        t((1024. * 1024. * 1024. * 1.2345) as u64, \"1.2345GiB\");\n        t(1024 * 1024 * 1024 * 1024, \"1TiB\");\n        t(1024 * 1024 * 1024 * 1024 * 1024, \"1PiB\");\n        t(1024 * 1024 * 1024 * 1024 * 1024 * 1024, \"1EiB\");\n        t(u64::MAX, \"16EiB\");\n\n        assert_eq!(\n            &format!(\"{:.3}\", HumanBytes((1024. * 1.23456) as u64)),\n            \"1.234KiB\"\n        );\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/network/http.rs",
    "content": "//! Configures libcurl's http handles.\n\nuse std::str;\nuse std::time::Duration;\n\nuse anyhow::bail;\nuse curl::easy::Easy;\nuse curl::easy::InfoType;\nuse curl::easy::SslOpt;\nuse curl::easy::SslVersion;\nuse tracing::debug;\nuse tracing::trace;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::util::context::SslVersionConfig;\nuse crate::util::context::SslVersionConfigRange;\nuse crate::version;\n\n/// Creates a new HTTP handle with appropriate global configuration for cargo.\npub fn http_handle(gctx: &GlobalContext) -> CargoResult<Easy> {\n    let (mut handle, timeout) = http_handle_and_timeout(gctx)?;\n    timeout.configure(&mut handle)?;\n    Ok(handle)\n}\n\npub fn http_handle_and_timeout(gctx: &GlobalContext) -> CargoResult<(Easy, HttpTimeout)> {\n    if let Some(offline_flag) = gctx.offline_flag() {\n        bail!(\n            \"attempting to make an HTTP request, but {offline_flag} was \\\n             specified\"\n        )\n    }\n\n    // The timeout option for libcurl by default times out the entire transfer,\n    // but we probably don't want this. Instead we only set timeouts for the\n    // connect phase as well as a \"low speed\" timeout so if we don't receive\n    // many bytes in a large-ish period of time then we time out.\n    let mut handle = Easy::new();\n    let timeout = configure_http_handle(gctx, &mut handle)?;\n    Ok((handle, timeout))\n}\n\n// Only use a custom transport if any HTTP options are specified,\n// such as proxies or custom certificate authorities.\n//\n// The custom transport, however, is not as well battle-tested.\npub fn needs_custom_http_transport(gctx: &GlobalContext) -> CargoResult<bool> {\n    Ok(super::proxy::http_proxy_exists(gctx.http_config()?, gctx)\n        || *gctx.http_config()? != Default::default()\n        || gctx.get_env_os(\"HTTP_TIMEOUT\").is_some())\n}\n\n/// Configure a libcurl http handle with the defaults options for Cargo\npub fn configure_http_handle(gctx: &GlobalContext, handle: &mut Easy) -> CargoResult<HttpTimeout> {\n    let http = gctx.http_config()?;\n    if let Some(proxy) = super::proxy::http_proxy(http) {\n        handle.proxy(&proxy)?;\n    }\n    if let Some(cainfo) = &http.cainfo {\n        let cainfo = cainfo.resolve_path(gctx);\n        handle.cainfo(&cainfo)?;\n    }\n    // Use `proxy_cainfo` if explicitly set; otherwise, fall back to `cainfo` as curl does #15376.\n    if let Some(proxy_cainfo) = http.proxy_cainfo.as_ref().or(http.cainfo.as_ref()) {\n        let proxy_cainfo = proxy_cainfo.resolve_path(gctx);\n        handle.proxy_cainfo(&format!(\"{}\", proxy_cainfo.display()))?;\n    }\n    if let Some(check) = http.check_revoke {\n        handle.ssl_options(SslOpt::new().no_revoke(!check))?;\n    }\n\n    if let Some(user_agent) = &http.user_agent {\n        handle.useragent(user_agent)?;\n    } else {\n        handle.useragent(&format!(\"cargo/{}\", version()))?;\n    }\n\n    fn to_ssl_version(s: &str) -> CargoResult<SslVersion> {\n        let version = match s {\n            \"default\" => SslVersion::Default,\n            \"tlsv1\" => SslVersion::Tlsv1,\n            \"tlsv1.0\" => SslVersion::Tlsv10,\n            \"tlsv1.1\" => SslVersion::Tlsv11,\n            \"tlsv1.2\" => SslVersion::Tlsv12,\n            \"tlsv1.3\" => SslVersion::Tlsv13,\n            _ => bail!(\n                \"Invalid ssl version `{s}`,\\\n                 choose from 'default', 'tlsv1', 'tlsv1.0', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3'.\"\n            ),\n        };\n        Ok(version)\n    }\n\n    // Empty string accept encoding expands to the encodings supported by the current libcurl.\n    handle.accept_encoding(\"\")?;\n    if let Some(ssl_version) = &http.ssl_version {\n        match ssl_version {\n            SslVersionConfig::Single(s) => {\n                let version = to_ssl_version(s.as_str())?;\n                handle.ssl_version(version)?;\n            }\n            SslVersionConfig::Range(SslVersionConfigRange { min, max }) => {\n                let min_version = min\n                    .as_ref()\n                    .map_or(Ok(SslVersion::Default), |s| to_ssl_version(s))?;\n                let max_version = max\n                    .as_ref()\n                    .map_or(Ok(SslVersion::Default), |s| to_ssl_version(s))?;\n                handle.ssl_min_max_version(min_version, max_version)?;\n            }\n        }\n    } else if cfg!(windows) {\n        // This is a temporary workaround for some bugs with libcurl and\n        // schannel and TLS 1.3.\n        //\n        // Our libcurl on Windows is usually built with schannel.\n        // On Windows 11 (or Windows Server 2022), libcurl recently (late\n        // 2022) gained support for TLS 1.3 with schannel, and it now defaults\n        // to 1.3. Unfortunately there have been some bugs with this.\n        // https://github.com/curl/curl/issues/9431 is the most recent. Once\n        // that has been fixed, and some time has passed where we can be more\n        // confident that the 1.3 support won't cause issues, this can be\n        // removed.\n        //\n        // Windows 10 is unaffected. libcurl does not support TLS 1.3 on\n        // Windows 10. (Windows 10 sorta had support, but it required enabling\n        // an advanced option in the registry which was buggy, and libcurl\n        // does runtime checks to prevent it.)\n        handle.ssl_min_max_version(SslVersion::Default, SslVersion::Tlsv12)?;\n    }\n\n    if let Some(true) = http.debug {\n        handle.verbose(true)?;\n        tracing::debug!(target: \"network\", \"{:#?}\", curl::Version::get());\n        handle.debug_function(debug)?;\n    }\n\n    HttpTimeout::new(gctx)\n}\n\npub fn debug(kind: InfoType, data: &[u8]) {\n    enum LogLevel {\n        Debug,\n        Trace,\n    }\n    use LogLevel::*;\n    let (prefix, level) = match kind {\n        InfoType::Text => (\"*\", Debug),\n        InfoType::HeaderIn => (\"<\", Debug),\n        InfoType::HeaderOut => (\">\", Debug),\n        InfoType::DataIn => (\"{\", Trace),\n        InfoType::DataOut => (\"}\", Trace),\n        InfoType::SslDataIn | InfoType::SslDataOut => return,\n        _ => return,\n    };\n    let starts_with_ignore_case = |line: &str, text: &str| -> bool {\n        let line = line.as_bytes();\n        let text = text.as_bytes();\n        line[..line.len().min(text.len())].eq_ignore_ascii_case(text)\n    };\n    match str::from_utf8(data) {\n        Ok(s) => {\n            for mut line in s.lines() {\n                if starts_with_ignore_case(line, \"authorization:\") {\n                    line = \"Authorization: [REDACTED]\";\n                } else if starts_with_ignore_case(line, \"h2h3 [authorization:\") {\n                    line = \"h2h3 [Authorization: [REDACTED]]\";\n                } else if starts_with_ignore_case(line, \"set-cookie\") {\n                    line = \"set-cookie: [REDACTED]\";\n                }\n                match level {\n                    Debug => debug!(target: \"network\", \"http-debug: {prefix} {line}\"),\n                    Trace => trace!(target: \"network\", \"http-debug: {prefix} {line}\"),\n                }\n            }\n        }\n        Err(_) => {\n            let len = data.len();\n            match level {\n                Debug => {\n                    debug!(target: \"network\", \"http-debug: {prefix} ({len} bytes of data)\")\n                }\n                Trace => {\n                    trace!(target: \"network\", \"http-debug: {prefix} ({len} bytes of data)\")\n                }\n            }\n        }\n    }\n}\n\n#[must_use]\npub struct HttpTimeout {\n    pub dur: Duration,\n    pub low_speed_limit: u32,\n}\n\nimpl HttpTimeout {\n    pub fn new(gctx: &GlobalContext) -> CargoResult<HttpTimeout> {\n        let http_config = gctx.http_config()?;\n        let low_speed_limit = http_config.low_speed_limit.unwrap_or(10);\n        let seconds = http_config\n            .timeout\n            .or_else(|| {\n                gctx.get_env(\"HTTP_TIMEOUT\")\n                    .ok()\n                    .and_then(|s| s.parse().ok())\n            })\n            .unwrap_or(30);\n        Ok(HttpTimeout {\n            dur: Duration::new(seconds, 0),\n            low_speed_limit,\n        })\n    }\n\n    pub fn configure(&self, handle: &mut Easy) -> CargoResult<()> {\n        // The timeout option for libcurl by default times out the entire\n        // transfer, but we probably don't want this. Instead we only set\n        // timeouts for the connect phase as well as a \"low speed\" timeout so\n        // if we don't receive many bytes in a large-ish period of time then we\n        // time out.\n        handle.connect_timeout(self.dur)?;\n        handle.low_speed_time(self.dur)?;\n        handle.low_speed_limit(self.low_speed_limit)?;\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/network/mod.rs",
    "content": "//! Utilities for networking.\n\nuse std::net::Ipv4Addr;\nuse std::net::Ipv6Addr;\nuse std::net::SocketAddr;\nuse std::net::SocketAddrV4;\nuse std::net::SocketAddrV6;\nuse std::task::Poll;\n\npub mod http;\npub mod proxy;\npub mod retry;\npub mod sleep;\n\n/// LOCALHOST constants for both IPv4 and IPv6.\npub const LOCALHOST: [SocketAddr; 2] = [\n    SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0)),\n    SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 0, 0, 0)),\n];\n\npub trait PollExt<T> {\n    fn expect(self, msg: &str) -> T;\n}\n\nimpl<T> PollExt<T> for Poll<T> {\n    #[track_caller]\n    fn expect(self, msg: &str) -> T {\n        match self {\n            Poll::Ready(val) => val,\n            Poll::Pending => panic!(\"{}\", msg),\n        }\n    }\n}\n\n/// When dynamically linked against libcurl, we want to ignore some failures\n/// when using old versions that don't support certain features.\n#[macro_export]\nmacro_rules! try_old_curl {\n    ($e:expr, $msg:expr) => {\n        let result = $e;\n        if cfg!(target_os = \"macos\") {\n            if let Err(e) = result {\n                ::tracing::warn!(target: \"network\", \"ignoring libcurl {} error: {}\", $msg, e);\n            }\n        } else {\n            use ::anyhow::Context;\n            result.with_context(|| {\n                ::anyhow::format_err!(\"failed to enable {}, is curl not built right?\", $msg)\n            })?;\n        }\n    };\n}\n\n/// Enable HTTP/2 and pipewait to be used as it'll allow true multiplexing\n/// which makes downloads much faster.\n///\n/// Currently Cargo requests the `http2` feature of the `curl` crate which\n/// means it should always be built in. On OSX, however, we ship cargo still\n/// linked against the system libcurl. Building curl with ALPN support for\n/// HTTP/2 requires newer versions of OSX (the SecureTransport API) than we\n/// want to ship Cargo for. By linking Cargo against the system libcurl then\n/// older curl installations won't use HTTP/2 but newer ones will. All that to\n/// basically say we ignore errors here on OSX, but consider this a fatal error\n/// to not activate HTTP/2 on all other platforms.\n///\n/// `pipewait` is an option which indicates that if there's a bunch of parallel\n/// requests to the same host they all wait until the pipelining status of the\n/// host is known. This means that we won't initiate dozens of connections but\n/// rather only one. Once the main one is opened we realized that pipelining is\n/// possible and multiplexing is possible. All in all this reduces the number\n/// of connections down to a more manageable state.\n#[macro_export]\nmacro_rules! try_old_curl_http2_pipewait {\n    ($multiplexing:expr, $handle:expr) => {\n        if $multiplexing {\n            $crate::try_old_curl!($handle.http_version(curl::easy::HttpVersion::V2), \"HTTP/2\");\n        } else {\n            $handle.http_version(curl::easy::HttpVersion::V11)?;\n        }\n        $crate::try_old_curl!($handle.pipewait(true), \"pipewait\");\n    };\n}\n"
  },
  {
    "path": "src/cargo/util/network/proxy.rs",
    "content": "//! Utilities for network proxies.\n\nuse crate::util::context::CargoHttpConfig;\nuse crate::util::context::GlobalContext;\n\n/// Proxy environment variables that are picked up by libcurl.\nconst LIBCURL_HTTP_PROXY_ENVS: [&str; 4] =\n    [\"http_proxy\", \"HTTP_PROXY\", \"https_proxy\", \"HTTPS_PROXY\"];\n\n/// Finds an explicit HTTP proxy if one is available.\n///\n/// Favor [Cargo's `http.proxy`], then [Git's `http.proxy`].\n/// Proxies specified via environment variables are picked up by libcurl.\n/// See [`LIBCURL_HTTP_PROXY_ENVS`].\n///\n/// [Cargo's `http.proxy`]: https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpproxy\n/// [Git's `http.proxy`]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-httpproxy\npub fn http_proxy(http: &CargoHttpConfig) -> Option<String> {\n    if let Some(s) = &http.proxy {\n        return Some(s.into());\n    }\n    git2::Config::open_default()\n        .and_then(|cfg| cfg.get_string(\"http.proxy\"))\n        .ok()\n}\n\n/// Determine if an http proxy exists.\n///\n/// Checks the following for existence, in order:\n///\n/// * Cargo's `http.proxy`\n/// * Git's `http.proxy`\n/// * `http_proxy` env var\n/// * `HTTP_PROXY` env var\n/// * `https_proxy` env var\n/// * `HTTPS_PROXY` env var\npub fn http_proxy_exists(http: &CargoHttpConfig, gctx: &GlobalContext) -> bool {\n    http_proxy(http).is_some()\n        || LIBCURL_HTTP_PROXY_ENVS\n            .iter()\n            .any(|v| gctx.get_env(v).is_ok())\n}\n"
  },
  {
    "path": "src/cargo/util/network/retry.rs",
    "content": "//! Utilities for retrying a network operation.\n//!\n//! Some network errors are considered \"spurious\", meaning it is not a real\n//! error (such as a 404 not found) and is likely a transient error (like a\n//! bad network connection) that we can hope will resolve itself shortly. The\n//! [`Retry`] type offers a way to repeatedly perform some kind of network\n//! operation with a delay if it detects one of these possibly transient\n//! errors.\n//!\n//! This supports errors from [`git2`], [`gix`], [`curl`], and\n//! [`HttpNotSuccessful`] 5xx HTTP errors.\n//!\n//! The number of retries can be configured by the user via the `net.retry`\n//! config option. This indicates the number of times to retry the operation\n//! (default 3 times for a total of 4 attempts).\n//!\n//! There are hard-coded constants that indicate how long to sleep between\n//! retries. The constants are tuned to balance a few factors, such as the\n//! responsiveness to the user (we don't want cargo to hang for too long\n//! retrying things), and accommodating things like Cloudfront's default\n//! negative TTL of 10 seconds (if Cloudfront gets a 5xx error for whatever\n//! reason it won't try to fetch again for 10 seconds).\n//!\n//! The timeout also implements a primitive form of random jitter. This is so\n//! that if multiple requests fail at the same time that they don't all flood\n//! the server at the same time when they are retried. This jitter still has\n//! some clumping behavior, but should be good enough.\n//!\n//! [`Retry`] is the core type for implementing retry logic. The\n//! [`Retry::try`] method can be called with a callback, and it will\n//! indicate if it needs to be called again sometime in the future if there\n//! was a possibly transient error. The caller is responsible for sleeping the\n//! appropriate amount of time and then calling [`Retry::try`] again.\n//!\n//! [`with_retry`] is a convenience function that will create a [`Retry`] and\n//! handle repeatedly running a callback until it succeeds, or it runs out of\n//! retries.\n//!\n//! Some interesting resources about retries:\n//! - <https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/>\n//! - <https://en.wikipedia.org/wiki/Exponential_backoff>\n//! - <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After>\n\nuse crate::util::errors::{GitCliError, HttpNotSuccessful};\nuse crate::{CargoResult, GlobalContext};\nuse anyhow::Error;\nuse rand::RngExt;\nuse std::cmp::min;\nuse std::time::Duration;\n\n/// State for managing retrying a network operation.\npub struct Retry<'a> {\n    gctx: &'a GlobalContext,\n    /// The number of failed attempts that have been done so far.\n    ///\n    /// Starts at 0, and increases by one each time an attempt fails.\n    retries: u64,\n    /// The maximum number of times the operation should be retried.\n    ///\n    /// 0 means it should never retry.\n    max_retries: u64,\n}\n\n/// The result of attempting some operation via [`Retry::try`].\npub enum RetryResult<T> {\n    /// The operation was successful.\n    ///\n    /// The wrapped value is the return value of the callback function.\n    Success(T),\n    /// The operation was an error, and it should not be tried again.\n    Err(anyhow::Error),\n    /// The operation failed, and should be tried again in the future.\n    ///\n    /// The wrapped value is the number of milliseconds to wait before trying\n    /// again. The caller is responsible for waiting this long and then\n    /// calling [`Retry::try`] again.\n    Retry(u64),\n}\n\n/// Maximum amount of time a single retry can be delayed (milliseconds).\nconst MAX_RETRY_SLEEP_MS: u64 = 10 * 1000;\n/// The minimum initial amount of time a retry will be delayed (milliseconds).\n///\n/// The actual amount of time will be a random value above this.\nconst INITIAL_RETRY_SLEEP_BASE_MS: u64 = 500;\n/// The maximum amount of additional time the initial retry will take (milliseconds).\n///\n/// The initial delay will be [`INITIAL_RETRY_SLEEP_BASE_MS`] plus a random range\n/// from 0 to this value.\nconst INITIAL_RETRY_JITTER_MS: u64 = 1000;\n\nimpl<'a> Retry<'a> {\n    pub fn new(gctx: &'a GlobalContext) -> CargoResult<Retry<'a>> {\n        Ok(Retry {\n            gctx,\n            retries: 0,\n            max_retries: gctx.net_config()?.retry.unwrap_or(3) as u64,\n        })\n    }\n\n    /// Calls the given callback, and returns a [`RetryResult`] which\n    /// indicates whether or not this needs to be called again at some point\n    /// in the future to retry the operation if it failed.\n    pub fn r#try<T>(&mut self, f: impl FnOnce() -> CargoResult<T>) -> RetryResult<T> {\n        match f() {\n            Err(ref e) if maybe_spurious(e) && self.retries < self.max_retries => {\n                let err = e.downcast_ref::<HttpNotSuccessful>();\n                let err_msg = err\n                    .map(|http_err| http_err.display_short())\n                    .unwrap_or_else(|| e.root_cause().to_string());\n                let left_retries = self.max_retries - self.retries;\n                let msg = format!(\n                    \"spurious network error ({} {} remaining): {err_msg}\",\n                    left_retries,\n                    if left_retries != 1 { \"tries\" } else { \"try\" }\n                );\n                if let Err(e) = self.gctx.shell().warn(msg) {\n                    return RetryResult::Err(e);\n                }\n                self.retries += 1;\n                let sleep = err\n                    .and_then(|v| Self::parse_retry_after(v, &jiff::Timestamp::now()))\n                    // Limit the Retry-After to a maximum value to avoid waiting too long.\n                    .map(|retry_after| retry_after.min(MAX_RETRY_SLEEP_MS))\n                    .unwrap_or_else(|| self.next_sleep_ms());\n                RetryResult::Retry(sleep)\n            }\n            Err(e) => RetryResult::Err(e),\n            Ok(r) => RetryResult::Success(r),\n        }\n    }\n\n    /// Gets the next sleep duration in milliseconds.\n    fn next_sleep_ms(&self) -> u64 {\n        if let Ok(sleep) = self.gctx.get_env(\"__CARGO_TEST_FIXED_RETRY_SLEEP_MS\") {\n            return sleep.parse().expect(\"a u64\");\n        }\n\n        if self.retries == 1 {\n            let mut rng = rand::rng();\n            INITIAL_RETRY_SLEEP_BASE_MS + rng.random_range(0..INITIAL_RETRY_JITTER_MS)\n        } else {\n            min(\n                ((self.retries - 1) * 3) * 1000 + INITIAL_RETRY_SLEEP_BASE_MS,\n                MAX_RETRY_SLEEP_MS,\n            )\n        }\n    }\n\n    /// Parse the HTTP `Retry-After` header.\n    /// Returns the number of milliseconds to wait before retrying according to the header.\n    fn parse_retry_after(response: &HttpNotSuccessful, now: &jiff::Timestamp) -> Option<u64> {\n        // Only applies to HTTP 429 (too many requests) and 503 (service unavailable).\n        if !matches!(response.code, 429 | 503) {\n            return None;\n        }\n\n        // Extract the Retry-After header value.\n        let retry_after = response\n            .headers\n            .iter()\n            .filter_map(|h| h.split_once(':'))\n            .map(|(k, v)| (k.trim(), v.trim()))\n            .find(|(k, _)| k.eq_ignore_ascii_case(\"retry-after\"))?\n            .1;\n\n        // First option: Retry-After is a positive integer of seconds to wait.\n        if let Ok(delay_secs) = retry_after.parse::<u32>() {\n            return Some(delay_secs as u64 * 1000);\n        }\n\n        // Second option: Retry-After is a future HTTP date string that tells us when to retry.\n        if let Ok(retry_time) = jiff::fmt::rfc2822::parse(retry_after) {\n            let diff_ms = now\n                .until(&retry_time)\n                .unwrap()\n                .total(jiff::Unit::Millisecond)\n                .unwrap();\n            if diff_ms > 0.0 {\n                return Some(diff_ms as u64);\n            }\n        }\n        None\n    }\n}\n\nfn maybe_spurious(err: &Error) -> bool {\n    if let Some(git_err) = err.downcast_ref::<git2::Error>() {\n        match git_err.class() {\n            git2::ErrorClass::Net\n            | git2::ErrorClass::Os\n            | git2::ErrorClass::Zlib\n            | git2::ErrorClass::Http => return git_err.code() != git2::ErrorCode::Certificate,\n            _ => (),\n        }\n    }\n    if let Some(curl_err) = err.downcast_ref::<curl::Error>() {\n        if curl_err.is_couldnt_connect()\n            || curl_err.is_couldnt_resolve_proxy()\n            || curl_err.is_couldnt_resolve_host()\n            || curl_err.is_operation_timedout()\n            || curl_err.is_recv_error()\n            || curl_err.is_send_error()\n            || curl_err.is_http2_error()\n            || curl_err.is_http2_stream_error()\n            || curl_err.is_ssl_connect_error()\n            || curl_err.is_partial_file()\n        {\n            return true;\n        }\n    }\n    if let Some(not_200) = err.downcast_ref::<HttpNotSuccessful>() {\n        if 500 <= not_200.code && not_200.code < 600 || not_200.code == 429 {\n            return true;\n        }\n    }\n\n    use gix::protocol::transport::IsSpuriousError;\n\n    if let Some(err) = err.downcast_ref::<crate::sources::git::fetch::Error>() {\n        if err.is_spurious() {\n            return true;\n        }\n    }\n\n    if let Some(err) = err.downcast_ref::<GitCliError>() {\n        if err.is_spurious() {\n            return true;\n        }\n    }\n\n    false\n}\n\n/// Wrapper method for network call retry logic.\n///\n/// Retry counts provided by Config object `net.retry`. Config shell outputs\n/// a warning on per retry.\n///\n/// Closure must return a `CargoResult`.\n///\n/// # Examples\n///\n/// ```\n/// # use crate::cargo::util::{CargoResult, GlobalContext};\n/// # let download_something = || return Ok(());\n/// # let gctx = GlobalContext::default().unwrap();\n/// use cargo::util::network;\n/// let cargo_result = network::retry::with_retry(&gctx, || download_something());\n/// ```\npub fn with_retry<T, F>(gctx: &GlobalContext, mut callback: F) -> CargoResult<T>\nwhere\n    F: FnMut() -> CargoResult<T>,\n{\n    let mut retry = Retry::new(gctx)?;\n    loop {\n        match retry.r#try(&mut callback) {\n            RetryResult::Success(r) => return Ok(r),\n            RetryResult::Err(e) => return Err(e),\n            RetryResult::Retry(sleep) => std::thread::sleep(Duration::from_millis(sleep)),\n        }\n    }\n}\n\n#[test]\nfn with_retry_repeats_the_call_then_works() {\n    use crate::core::Shell;\n\n    //Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry\n    let error1 = HttpNotSuccessful {\n        code: 501,\n        url: \"Uri\".to_string(),\n        ip: None,\n        body: Vec::new(),\n        headers: Vec::new(),\n    }\n    .into();\n    let error2 = HttpNotSuccessful {\n        code: 502,\n        url: \"Uri\".to_string(),\n        ip: None,\n        body: Vec::new(),\n        headers: Vec::new(),\n    }\n    .into();\n    let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];\n    let gctx = GlobalContext::default().unwrap();\n    *gctx.shell() = Shell::from_write(Box::new(Vec::new()));\n    let result = with_retry(&gctx, || results.pop().unwrap());\n    assert!(result.is_ok())\n}\n\n#[test]\nfn with_retry_finds_nested_spurious_errors() {\n    use crate::core::Shell;\n\n    //Error HTTP codes (5xx) are considered maybe_spurious and will prompt retry\n    //String error messages are not considered spurious\n    let error1 = anyhow::Error::from(HttpNotSuccessful {\n        code: 501,\n        url: \"Uri\".to_string(),\n        ip: None,\n        body: Vec::new(),\n        headers: Vec::new(),\n    });\n    let error1 = anyhow::Error::from(error1.context(\"A non-spurious wrapping err\"));\n    let error2 = anyhow::Error::from(HttpNotSuccessful {\n        code: 502,\n        url: \"Uri\".to_string(),\n        ip: None,\n        body: Vec::new(),\n        headers: Vec::new(),\n    });\n    let error2 = anyhow::Error::from(error2.context(\"A second chained error\"));\n    let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];\n    let gctx = GlobalContext::default().unwrap();\n    *gctx.shell() = Shell::from_write(Box::new(Vec::new()));\n    let result = with_retry(&gctx, || results.pop().unwrap());\n    assert!(result.is_ok())\n}\n\n#[test]\nfn default_retry_schedule() {\n    use crate::core::Shell;\n\n    let spurious = || -> CargoResult<()> {\n        Err(anyhow::Error::from(HttpNotSuccessful {\n            code: 500,\n            url: \"Uri\".to_string(),\n            ip: None,\n            body: Vec::new(),\n            headers: Vec::new(),\n        }))\n    };\n    let gctx = GlobalContext::default().unwrap();\n    *gctx.shell() = Shell::from_write(Box::new(Vec::new()));\n    let mut retry = Retry::new(&gctx).unwrap();\n    match retry.r#try(|| spurious()) {\n        RetryResult::Retry(sleep) => {\n            assert!(\n                sleep >= INITIAL_RETRY_SLEEP_BASE_MS\n                    && sleep < INITIAL_RETRY_SLEEP_BASE_MS + INITIAL_RETRY_JITTER_MS\n            );\n        }\n        _ => panic!(\"unexpected non-retry\"),\n    }\n    match retry.r#try(|| spurious()) {\n        RetryResult::Retry(sleep) => assert_eq!(sleep, 3500),\n        _ => panic!(\"unexpected non-retry\"),\n    }\n    match retry.r#try(|| spurious()) {\n        RetryResult::Retry(sleep) => assert_eq!(sleep, 6500),\n        _ => panic!(\"unexpected non-retry\"),\n    }\n    match retry.r#try(|| spurious()) {\n        RetryResult::Err(_) => {}\n        _ => panic!(\"unexpected non-retry\"),\n    }\n}\n\n#[test]\nfn curle_http2_stream_is_spurious() {\n    let code = curl_sys::CURLE_HTTP2_STREAM;\n    let err = curl::Error::new(code);\n    assert!(maybe_spurious(&err.into()));\n}\n\n#[test]\nfn retry_after_parsing() {\n    use crate::core::Shell;\n    fn spurious(code: u32, header: &str) -> HttpNotSuccessful {\n        HttpNotSuccessful {\n            code,\n            url: \"Uri\".to_string(),\n            ip: None,\n            body: Vec::new(),\n            headers: vec![header.to_string()],\n        }\n    }\n\n    // Start of year 2025.\n    let now = jiff::Timestamp::new(1735689600, 0).unwrap();\n    let headers = spurious(429, \"Retry-After: 10\");\n    assert_eq!(Retry::parse_retry_after(&headers, &now), Some(10_000));\n    let headers = spurious(429, \"retry-after: Wed, 01 Jan 2025 00:00:10 GMT\");\n    let actual = Retry::parse_retry_after(&headers, &now).unwrap();\n    assert_eq!(10000, actual);\n\n    let headers = spurious(429, \"Content-Type: text/html\");\n    assert_eq!(Retry::parse_retry_after(&headers, &now), None);\n\n    let headers = spurious(429, \"retry-after: Fri, 01 Jan 2000 00:00:00 GMT\");\n    assert_eq!(Retry::parse_retry_after(&headers, &now), None);\n\n    let headers = spurious(429, \"retry-after: -1\");\n    assert_eq!(Retry::parse_retry_after(&headers, &now), None);\n\n    let headers = spurious(400, \"retry-after: 1\");\n    assert_eq!(Retry::parse_retry_after(&headers, &now), None);\n\n    let gctx = GlobalContext::default().unwrap();\n    *gctx.shell() = Shell::from_write(Box::new(Vec::new()));\n    let mut retry = Retry::new(&gctx).unwrap();\n    match retry\n        .r#try(|| -> CargoResult<()> { Err(anyhow::Error::from(spurious(429, \"Retry-After: 7\"))) })\n    {\n        RetryResult::Retry(sleep) => assert_eq!(sleep, 7_000),\n        _ => panic!(\"unexpected non-retry\"),\n    }\n}\n\n#[test]\nfn git_cli_error_spurious() {\n    let error = GitCliError::new(Error::msg(\"test-git-cli-error\"), false);\n    assert!(!maybe_spurious(&error.into()));\n\n    let error = GitCliError::new(Error::msg(\"test-git-cli-error\"), true);\n    assert!(maybe_spurious(&error.into()));\n}\n"
  },
  {
    "path": "src/cargo/util/network/sleep.rs",
    "content": "//! Utility for tracking network requests that will be retried in the future.\n\nuse core::cmp::Ordering;\nuse std::collections::BinaryHeap;\nuse std::time::{Duration, Instant};\n\n/// A tracker for network requests that have failed, and are awaiting to be\n/// retried in the future.\npub struct SleepTracker<T> {\n    /// This is a priority queue that tracks the time when the next sleeper\n    /// should awaken (based on the [`Sleeper::wakeup`] property).\n    heap: BinaryHeap<Sleeper<T>>,\n}\n\n/// An individual network request that is waiting to be retried in the future.\nstruct Sleeper<T> {\n    /// The time when this requests should be retried.\n    wakeup: Instant,\n    /// Information about the network request.\n    data: T,\n}\n\nimpl<T> PartialEq for Sleeper<T> {\n    fn eq(&self, other: &Sleeper<T>) -> bool {\n        self.wakeup == other.wakeup\n    }\n}\n\nimpl<T> PartialOrd for Sleeper<T> {\n    fn partial_cmp(&self, other: &Sleeper<T>) -> Option<Ordering> {\n        // This reverses the comparison so that the BinaryHeap tracks the\n        // entry with the *lowest* wakeup time.\n        Some(other.wakeup.cmp(&self.wakeup))\n    }\n}\n\nimpl<T> Eq for Sleeper<T> {}\n\nimpl<T> Ord for Sleeper<T> {\n    fn cmp(&self, other: &Sleeper<T>) -> Ordering {\n        self.wakeup.cmp(&other.wakeup)\n    }\n}\n\nimpl<T> SleepTracker<T> {\n    pub fn new() -> SleepTracker<T> {\n        SleepTracker {\n            heap: BinaryHeap::new(),\n        }\n    }\n\n    /// Adds a new download that should be retried in the future.\n    pub fn push(&mut self, sleep: u64, data: T) {\n        self.heap.push(Sleeper {\n            wakeup: Instant::now()\n                .checked_add(Duration::from_millis(sleep))\n                .expect(\"instant should not wrap\"),\n            data,\n        });\n    }\n\n    pub fn len(&self) -> usize {\n        self.heap.len()\n    }\n\n    /// Returns any downloads that are ready to go now.\n    pub fn to_retry(&mut self) -> Vec<T> {\n        let now = Instant::now();\n        let mut result = Vec::new();\n        while let Some(next) = self.heap.peek() {\n            if next.wakeup < now {\n                result.push(self.heap.pop().unwrap().data);\n            } else {\n                break;\n            }\n        }\n        result\n    }\n\n    /// Returns the time when the next download is ready to go.\n    ///\n    /// Returns None if there are no sleepers remaining.\n    pub fn time_to_next(&self) -> Option<Duration> {\n        self.heap\n            .peek()\n            .map(|s| s.wakeup.saturating_duration_since(Instant::now()))\n    }\n}\n\n#[test]\nfn returns_in_order() {\n    let mut s = SleepTracker::new();\n    s.push(30_000, 30_000);\n    s.push(1, 1);\n    assert_eq!(s.len(), 2);\n    std::thread::sleep(Duration::from_millis(2));\n    assert_eq!(s.to_retry(), &[1]);\n    assert!(s.to_retry().is_empty());\n    let next = s.time_to_next().expect(\"should be next\");\n    assert!(\n        next < Duration::from_millis(30_000),\n        \"{next:?} should be less than 30s\"\n    );\n}\n"
  },
  {
    "path": "src/cargo/util/once.rs",
    "content": "//! Extension functions for [`std::sync::OnceLock`] / [`std::cell::OnceCell`]\n//!\n//! This adds polyfills for functionality in `lazycell` that is not stable within `std`.\n\npub trait OnceExt {\n    type T;\n\n    /// This might run `f` multiple times if different threads start initializing at once.\n    fn try_borrow_with<F, E>(&self, f: F) -> Result<&Self::T, E>\n    where\n        F: FnOnce() -> Result<Self::T, E>;\n\n    /// This might run `f` multiple times if different threads start initializing at once.\n    fn try_borrow_mut_with<F, E>(&mut self, f: F) -> Result<&mut Self::T, E>\n    where\n        F: FnOnce() -> Result<Self::T, E>;\n\n    fn replace(&mut self, new_value: Self::T) -> Option<Self::T>;\n\n    fn filled(&self) -> bool;\n}\n\nimpl<T> OnceExt for std::sync::OnceLock<T> {\n    type T = T;\n\n    fn try_borrow_with<F, E>(&self, f: F) -> Result<&T, E>\n    where\n        F: FnOnce() -> Result<T, E>,\n    {\n        if let Some(value) = self.get() {\n            return Ok(value);\n        }\n\n        // This is not how the unstable `OnceLock::get_or_try_init` works. That only starts `f` if\n        // no other `f` is executing and the value is not initialized. However, correctly implementing that is\n        // hard (one has properly handle panics in `f`) and not doable with the stable API of `OnceLock`.\n        let value = f()?;\n        // Another thread might have initialized `self` since we checked that `self.get()` returns `None`. If this is the case, `self.set()`\n        // returns an error. We ignore it and return the value set by the other\n        // thread.\n        let _ = self.set(value);\n        Ok(self.get().unwrap())\n    }\n\n    fn try_borrow_mut_with<F, E>(&mut self, f: F) -> Result<&mut T, E>\n    where\n        F: FnOnce() -> Result<T, E>,\n    {\n        let value = if let Some(value) = self.take() {\n            value\n        } else {\n            // This is not how the unstable `OnceLock::get_or_try_init` works. That only starts `f` if\n            // no other `f` is executing and the value is not initialized. However, correctly implementing that is\n            // hard (one has properly handle panics in `f`) and not doable with the stable API of `OnceLock`.\n            f()?\n        };\n        // Another thread might have initialized `self` since we checked that `self.get()` returns `None`. If this is the case, `self.set()`\n        // returns an error. We ignore it and return the value set by the other\n        // thread.\n        let _ = self.set(value);\n        Ok(self.get_mut().unwrap())\n    }\n\n    fn replace(&mut self, new_value: T) -> Option<T> {\n        if let Some(value) = self.get_mut() {\n            Some(std::mem::replace(value, new_value))\n        } else {\n            let result = self.set(new_value);\n            assert!(result.is_ok());\n            None\n        }\n    }\n\n    fn filled(&self) -> bool {\n        self.get().is_some()\n    }\n}\n\nimpl<T> OnceExt for std::cell::OnceCell<T> {\n    type T = T;\n\n    fn try_borrow_with<F, E>(&self, f: F) -> Result<&T, E>\n    where\n        F: FnOnce() -> Result<T, E>,\n    {\n        if let Some(value) = self.get() {\n            return Ok(value);\n        }\n\n        // This is not how the unstable `OnceLock::get_or_try_init` works. That only starts `f` if\n        // no other `f` is executing and the value is not initialized. However, correctly implementing that is\n        // hard (one has properly handle panics in `f`) and not doable with the stable API of `OnceLock`.\n        let value = f()?;\n        // Another thread might have initialized `self` since we checked that `self.get()` returns `None`. If this is the case, `self.set()`\n        // returns an error. We ignore it and return the value set by the other\n        // thread.\n        let _ = self.set(value);\n        Ok(self.get().unwrap())\n    }\n\n    fn try_borrow_mut_with<F, E>(&mut self, f: F) -> Result<&mut T, E>\n    where\n        F: FnOnce() -> Result<T, E>,\n    {\n        let value = if let Some(value) = self.take() {\n            value\n        } else {\n            // This is not how the unstable `OnceLock::get_or_try_init` works. That only starts `f` if\n            // no other `f` is executing and the value is not initialized. However, correctly implementing that is\n            // hard (one has properly handle panics in `f`) and not doable with the stable API of `OnceLock`.\n            f()?\n        };\n        // Another thread might have initialized `self` since we checked that `self.get()` returns `None`. If this is the case, `self.set()`\n        // returns an error. We ignore it and return the value set by the other\n        // thread.\n        let _ = self.set(value);\n        Ok(self.get_mut().unwrap())\n    }\n\n    fn replace(&mut self, new_value: T) -> Option<T> {\n        if let Some(value) = self.get_mut() {\n            Some(std::mem::replace(value, new_value))\n        } else {\n            let result = self.set(new_value);\n            assert!(result.is_ok());\n            None\n        }\n    }\n\n    fn filled(&self) -> bool {\n        self.get().is_some()\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/open.rs",
    "content": "//! For opening files or URLs with the preferred application.\n\nuse std::path::Path;\nuse std::path::PathBuf;\nuse std::process::Command;\n\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::util::context::PathAndArgs;\n\n/// Opens a file path using the preferred application.\n///\n/// 1. Try `doc.browser` config first\n/// 2. Then `$BROWSER`\n/// 3. Finally system default opener\npub fn open(path: &Path, gctx: &GlobalContext) -> CargoResult<()> {\n    let config_browser = {\n        let cfg: Option<PathAndArgs> = gctx.get(\"doc.browser\")?;\n        cfg.map(|path_args| (path_args.path.resolve_program(gctx), path_args.args))\n    };\n\n    let mut shell = gctx.shell();\n    let link = shell.err_file_hyperlink(&path);\n    shell.status(\"Opening\", format!(\"{link}{}{link:#}\", path.display()))?;\n\n    let browser =\n        config_browser.or_else(|| Some((PathBuf::from(gctx.get_env_os(\"BROWSER\")?), Vec::new())));\n\n    match browser {\n        Some((browser, initial_args)) => {\n            if let Err(e) = Command::new(&browser).args(initial_args).arg(path).status() {\n                shell.warn(format!(\n                    \"Couldn't open docs with {}: {}\",\n                    browser.to_string_lossy(),\n                    e\n                ))?;\n            }\n        }\n        None => {\n            if let Err(e) = opener::open(&path) {\n                let e = e.into();\n                crate::display_warning_with_error(\"couldn't open docs\", &e, &mut shell);\n            }\n        }\n    };\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/cargo/util/progress.rs",
    "content": "//! Support for CLI progress bars.\n\nuse std::cmp;\nuse std::time::{Duration, Instant};\n\nuse crate::core::shell::Verbosity;\nuse crate::util::context::ProgressWhen;\nuse crate::util::{CargoResult, GlobalContext};\nuse anstyle_progress::TermProgress;\nuse cargo_util::is_ci;\nuse unicode_width::UnicodeWidthChar;\n\n/// CLI progress bar.\n///\n/// The `Progress` object can be in an enabled or disabled state. When\n/// disabled, calling any of the methods to update it will not display\n/// anything. Disabling is typically done by the user with options such as\n/// `--quiet` or the `term.progress` config option.\n///\n/// There are several methods to update the progress bar and to cause it to\n/// update its display.\n///\n/// The bar will be removed from the display when the `Progress` object is\n/// dropped or [`Progress::clear`] is called.\n///\n/// The progress bar has built-in rate limiting to avoid updating the display\n/// too fast. It should usually be fine to call [`Progress::tick`] as often as\n/// needed, though be cautious if the tick rate is very high or it is\n/// expensive to compute the progress value.\npub struct Progress<'gctx> {\n    state: Option<State<'gctx>>,\n}\n\n/// Indicates the style of information for displaying the amount of progress.\n///\n/// See also [`Progress::print_now`] for displaying progress without a bar.\npub enum ProgressStyle {\n    /// Displays progress as a percentage.\n    ///\n    /// Example: `Fetch [=====================>   ]  88.15%`\n    ///\n    /// This is good for large values like number of bytes downloaded.\n    Percentage,\n    /// Displays progress as a ratio.\n    ///\n    /// Example: `Building [===>                      ] 35/222`\n    ///\n    /// This is good for smaller values where the exact number is useful to see.\n    Ratio,\n    /// Does not display an exact value of how far along it is.\n    ///\n    /// Example: `Fetch [===========>                     ]`\n    ///\n    /// This is good for situations where the exact value is an approximation,\n    /// and thus there isn't anything accurate to display to the user.\n    Indeterminate,\n}\n\nstruct Throttle {\n    first: bool,\n    last_update: Instant,\n}\n\nstruct State<'gctx> {\n    gctx: &'gctx GlobalContext,\n    format: Format,\n    name: String,\n    done: bool,\n    throttle: Throttle,\n    last_line: Option<String>,\n    fixed_width: Option<usize>,\n}\n\nstruct Format {\n    style: ProgressStyle,\n    max_width: usize,\n    max_print: usize,\n    term_integration: TerminalIntegration,\n    unicode: bool,\n}\n\n/// Controls terminal progress integration via OSC sequences.\nstruct TerminalIntegration {\n    enabled: bool,\n    error: bool,\n}\n\n/// A progress status value printable as an ANSI OSC 9;4 escape code.\n#[cfg_attr(test, derive(PartialEq, Debug))]\nenum StatusValue {\n    /// No output.\n    None,\n    /// Remove progress.\n    Remove,\n    /// Progress value (0-100).\n    Value(u8),\n    /// Indeterminate state (no bar, just animation)\n    Indeterminate,\n    /// Progress value in an error state (0-100).\n    Error(u8),\n}\n\nenum ProgressOutput {\n    /// Print progress without a message\n    PrintNow,\n    /// Progress, message and progress report\n    TextAndReport(String, StatusValue),\n    /// Only progress report, no message and no text progress\n    Report(StatusValue),\n}\n\nimpl TerminalIntegration {\n    #[cfg(test)]\n    fn new(enabled: bool) -> Self {\n        Self {\n            enabled,\n            error: false,\n        }\n    }\n\n    /// Creates a `TerminalIntegration` from Cargo's configuration.\n    /// Autodetect support if not explicitly enabled or disabled.\n    fn from_config(gctx: &GlobalContext) -> Self {\n        let enabled = gctx\n            .progress_config()\n            .term_integration\n            .unwrap_or_else(|| gctx.shell().is_err_term_integration_available());\n\n        Self {\n            enabled,\n            error: false,\n        }\n    }\n\n    fn progress_state(&self, value: StatusValue) -> StatusValue {\n        match (self.enabled, self.error) {\n            (true, false) => value,\n            (true, true) => match value {\n                StatusValue::Value(v) => StatusValue::Error(v),\n                _ => StatusValue::Error(100),\n            },\n            (false, _) => StatusValue::None,\n        }\n    }\n\n    pub fn remove(&self) -> StatusValue {\n        self.progress_state(StatusValue::Remove)\n    }\n\n    pub fn value(&self, percent: u8) -> StatusValue {\n        self.progress_state(StatusValue::Value(percent))\n    }\n\n    pub fn indeterminate(&self) -> StatusValue {\n        self.progress_state(StatusValue::Indeterminate)\n    }\n\n    pub fn error(&mut self) {\n        self.error = true;\n    }\n}\n\nimpl std::fmt::Display for StatusValue {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let progress = match self {\n            Self::None => TermProgress::none(),\n            Self::Remove => TermProgress::remove(),\n            Self::Value(v) => TermProgress::start().percent(*v),\n            Self::Indeterminate => TermProgress::start(),\n            Self::Error(v) => TermProgress::error().percent(*v),\n        };\n\n        progress.fmt(f)\n    }\n}\n\nimpl<'gctx> Progress<'gctx> {\n    /// Creates a new progress bar.\n    ///\n    /// The first parameter is the text displayed to the left of the bar, such\n    /// as \"Fetching\".\n    ///\n    /// The progress bar is not displayed until explicitly updated with one if\n    /// its methods.\n    ///\n    /// The progress bar may be created in a disabled state if the user has\n    /// disabled progress display (such as with the `--quiet` option).\n    pub fn with_style(\n        name: &str,\n        style: ProgressStyle,\n        gctx: &'gctx GlobalContext,\n    ) -> Progress<'gctx> {\n        // report no progress when -q (for quiet) or TERM=dumb are set\n        // or if running on Continuous Integration service like Travis where the\n        // output logs get mangled.\n        let dumb = match gctx.get_env(\"TERM\") {\n            Ok(term) => term == \"dumb\",\n            Err(_) => false,\n        };\n        let progress_config = gctx.progress_config();\n        match progress_config.when {\n            ProgressWhen::Always => return Progress::new_priv(name, style, gctx),\n            ProgressWhen::Never => return Progress { state: None },\n            ProgressWhen::Auto => {}\n        }\n        if gctx.shell().verbosity() == Verbosity::Quiet || dumb || is_ci() {\n            return Progress { state: None };\n        }\n        Progress::new_priv(name, style, gctx)\n    }\n\n    fn new_priv(name: &str, style: ProgressStyle, gctx: &'gctx GlobalContext) -> Progress<'gctx> {\n        let progress_config = gctx.progress_config();\n        let width = progress_config\n            .width\n            .or_else(|| gctx.shell().err_width().progress_max_width());\n\n        Progress {\n            state: width.map(|n| State {\n                gctx,\n                format: Format {\n                    style,\n                    max_width: n,\n                    // 50 gives some space for text after the progress bar,\n                    // even on narrow (e.g. 80 char) terminals.\n                    max_print: 50,\n                    term_integration: TerminalIntegration::from_config(gctx),\n                    unicode: gctx.shell().err_unicode(),\n                },\n                name: name.to_string(),\n                done: false,\n                throttle: Throttle::new(),\n                last_line: None,\n                fixed_width: progress_config.width,\n            }),\n        }\n    }\n\n    /// Disables the progress bar, ensuring it won't be displayed.\n    pub fn disable(&mut self) {\n        self.state = None;\n    }\n\n    /// Returns whether or not the progress bar is allowed to be displayed.\n    pub fn is_enabled(&self) -> bool {\n        self.state.is_some()\n    }\n\n    /// Creates a new `Progress` with the [`ProgressStyle::Percentage`] style.\n    ///\n    /// See [`Progress::with_style`] for more information.\n    pub fn new(name: &str, gctx: &'gctx GlobalContext) -> Progress<'gctx> {\n        Self::with_style(name, ProgressStyle::Percentage, gctx)\n    }\n\n    /// Updates the state of the progress bar.\n    ///\n    /// * `cur` should be how far along the progress is.\n    /// * `max` is the maximum value for the progress bar.\n    /// * `msg` is a small piece of text to display at the end of the progress\n    ///   bar. It will be truncated with `…` if it does not fit on the terminal.\n    ///\n    /// This may not actually update the display if `tick` is being called too\n    /// quickly.\n    pub fn tick(&mut self, cur: usize, max: usize, msg: &str) -> CargoResult<()> {\n        let Some(s) = &mut self.state else {\n            return Ok(());\n        };\n\n        // Don't update too often as it can cause excessive performance loss\n        // just putting stuff onto the terminal. We also want to avoid\n        // flickering by not drawing anything that goes away too quickly. As a\n        // result we've got two branches here:\n        //\n        // 1. If we haven't drawn anything, we wait for a period of time to\n        //    actually start drawing to the console. This ensures that\n        //    short-lived operations don't flicker on the console. Currently\n        //    there's a 500ms delay to when we first draw something.\n        // 2. If we've drawn something, then we rate limit ourselves to only\n        //    draw to the console every so often. Currently there's a 100ms\n        //    delay between updates.\n        if !s.throttle.allowed() {\n            return Ok(());\n        }\n\n        s.tick(cur, max, msg)\n    }\n\n    /// Updates the state of the progress bar.\n    ///\n    /// This is the same as [`Progress::tick`], but ignores rate throttling\n    /// and forces the display to be updated immediately.\n    ///\n    /// This may be useful for situations where you know you aren't calling\n    /// `tick` too fast, and accurate information is more important than\n    /// limiting the console update rate.\n    pub fn tick_now(&mut self, cur: usize, max: usize, msg: &str) -> CargoResult<()> {\n        match self.state {\n            Some(ref mut s) => s.tick(cur, max, msg),\n            None => Ok(()),\n        }\n    }\n\n    /// Returns whether or not updates are currently being throttled.\n    ///\n    /// This can be useful if computing the values for calling the\n    /// [`Progress::tick`] function may require some expensive work.\n    pub fn update_allowed(&mut self) -> bool {\n        match &mut self.state {\n            Some(s) => s.throttle.allowed(),\n            None => false,\n        }\n    }\n\n    /// Displays progress without a bar.\n    ///\n    /// The given `msg` is the text to display after the status message.\n    ///\n    /// Example: `Downloading 61 crates, remaining bytes: 28.0 MB`\n    ///\n    /// This does not have any rate limit throttling, so be careful about\n    /// calling it too often.\n    pub fn print_now(&mut self, msg: &str) -> CargoResult<()> {\n        match &mut self.state {\n            Some(s) => s.print(ProgressOutput::PrintNow, msg),\n            None => Ok(()),\n        }\n    }\n\n    /// Clears the progress bar from the console.\n    pub fn clear(&mut self) {\n        if let Some(ref mut s) = self.state {\n            s.clear();\n        }\n    }\n\n    /// Sets the progress reporter to the error state.\n    pub fn indicate_error(&mut self) {\n        if let Some(s) = &mut self.state {\n            s.format.term_integration.error()\n        }\n    }\n}\n\nimpl Throttle {\n    fn new() -> Throttle {\n        Throttle {\n            first: true,\n            last_update: Instant::now(),\n        }\n    }\n\n    fn allowed(&mut self) -> bool {\n        if self.first {\n            let delay = Duration::from_millis(500);\n            if self.last_update.elapsed() < delay {\n                return false;\n            }\n        } else {\n            let interval = Duration::from_millis(100);\n            if self.last_update.elapsed() < interval {\n                return false;\n            }\n        }\n        self.update();\n        true\n    }\n\n    fn update(&mut self) {\n        self.first = false;\n        self.last_update = Instant::now();\n    }\n}\n\nimpl<'gctx> State<'gctx> {\n    fn tick(&mut self, cur: usize, max: usize, msg: &str) -> CargoResult<()> {\n        if self.done {\n            write!(\n                self.gctx.shell().err(),\n                \"{}\",\n                self.format.term_integration.remove()\n            )?;\n            return Ok(());\n        }\n\n        if max > 0 && cur == max {\n            self.done = true;\n        }\n\n        // Write out a pretty header, then the progress bar itself, and then\n        // return back to the beginning of the line for the next print.\n        self.try_update_max_width();\n        if let Some(pbar) = self.format.progress(cur, max) {\n            self.print(pbar, msg)?;\n        }\n        Ok(())\n    }\n\n    fn print(&mut self, progress: ProgressOutput, msg: &str) -> CargoResult<()> {\n        self.throttle.update();\n        self.try_update_max_width();\n\n        let (mut line, report) = match progress {\n            ProgressOutput::PrintNow => (String::new(), None),\n            ProgressOutput::TextAndReport(prefix, report) => (prefix, Some(report)),\n            ProgressOutput::Report(report) => (String::new(), Some(report)),\n        };\n\n        // make sure we have enough room for the header\n        if self.format.max_width < 15 {\n            // even if we don't have space we can still output progress report\n            if let Some(tb) = report {\n                write!(self.gctx.shell().err(), \"{tb}\\r\")?;\n            }\n            return Ok(());\n        }\n\n        self.format.render(&mut line, msg);\n        while line.len() < self.format.max_width - 15 {\n            line.push(' ');\n        }\n\n        // Only update if the line has changed.\n        if self.gctx.shell().is_cleared() || self.last_line.as_ref() != Some(&line) {\n            let mut shell = self.gctx.shell();\n            shell.set_needs_clear(false);\n            shell.transient_status(&self.name)?;\n            if let Some(tb) = report {\n                write!(shell.err(), \"{line}{tb}\\r\")?;\n            } else {\n                write!(shell.err(), \"{line}\\r\")?;\n            }\n            self.last_line = Some(line);\n            shell.set_needs_clear(true);\n        }\n\n        Ok(())\n    }\n\n    fn clear(&mut self) {\n        // Always clear the progress report\n        let _ = write!(\n            self.gctx.shell().err(),\n            \"{}\",\n            self.format.term_integration.remove()\n        );\n        // No need to clear if the progress is not currently being displayed.\n        if self.last_line.is_some() && !self.gctx.shell().is_cleared() {\n            self.gctx.shell().err_erase_line();\n            self.last_line = None;\n        }\n    }\n\n    fn try_update_max_width(&mut self) {\n        if self.fixed_width.is_none() {\n            if let Some(n) = self.gctx.shell().err_width().progress_max_width() {\n                self.format.max_width = n;\n            }\n        }\n    }\n}\n\nimpl Format {\n    fn progress(&self, cur: usize, max: usize) -> Option<ProgressOutput> {\n        assert!(cur <= max);\n        // Render the percentage at the far right and then figure how long the\n        // progress bar is\n        let pct = (cur as f64) / (max as f64);\n        let pct = if !pct.is_finite() { 0.0 } else { pct };\n        let stats = match self.style {\n            ProgressStyle::Percentage => format!(\" {:6.02}%\", pct * 100.0),\n            ProgressStyle::Ratio => format!(\" {cur}/{max}\"),\n            ProgressStyle::Indeterminate => String::new(),\n        };\n        let report = match self.style {\n            ProgressStyle::Percentage | ProgressStyle::Ratio => {\n                let pct = (pct * 100.0) as u8;\n                let pct = pct.clamp(0, 100);\n                self.term_integration.value(pct)\n            }\n            ProgressStyle::Indeterminate => self.term_integration.indeterminate(),\n        };\n\n        let extra_len = stats.len() + 2 /* [ and ] */ + 15 /* status header */;\n        let Some(display_width) = self.width().checked_sub(extra_len) else {\n            if self.term_integration.enabled {\n                return Some(ProgressOutput::Report(report));\n            }\n            return None;\n        };\n\n        let mut string = String::with_capacity(self.max_width);\n        string.push('[');\n        let hashes = display_width as f64 * pct;\n        let hashes = hashes as usize;\n\n        // Draw the `===>`\n        if hashes > 0 {\n            for _ in 0..hashes - 1 {\n                string.push('=');\n            }\n            if cur == max {\n                string.push('=');\n            } else {\n                string.push('>');\n            }\n        }\n\n        // Draw the empty space we have left to do\n        for _ in 0..(display_width - hashes) {\n            string.push(' ');\n        }\n        string.push(']');\n        string.push_str(&stats);\n\n        Some(ProgressOutput::TextAndReport(string, report))\n    }\n\n    fn render(&self, string: &mut String, msg: &str) {\n        let mut avail_msg_len = self.max_width - string.len() - 15;\n        let mut ellipsis_pos = 0;\n\n        let (ellipsis, ellipsis_width) = if self.unicode { (\"…\", 1) } else { (\"...\", 3) };\n\n        if avail_msg_len <= ellipsis_width {\n            return;\n        }\n        for c in msg.chars() {\n            let display_width = c.width().unwrap_or(0);\n            if avail_msg_len >= display_width {\n                avail_msg_len -= display_width;\n                string.push(c);\n                if avail_msg_len >= ellipsis_width {\n                    ellipsis_pos = string.len();\n                }\n            } else {\n                string.truncate(ellipsis_pos);\n                string.push_str(ellipsis);\n                break;\n            }\n        }\n    }\n\n    #[cfg(test)]\n    fn progress_status(&self, cur: usize, max: usize, msg: &str) -> Option<String> {\n        let mut ret = match self.progress(cur, max)? {\n            // Check only the variant that contains text.\n            ProgressOutput::TextAndReport(text, _) => text,\n            _ => return None,\n        };\n        self.render(&mut ret, msg);\n        Some(ret)\n    }\n\n    fn width(&self) -> usize {\n        cmp::min(self.max_width, self.max_print)\n    }\n}\n\nimpl<'gctx> Drop for State<'gctx> {\n    fn drop(&mut self) {\n        self.clear();\n    }\n}\n\n#[test]\nfn test_progress_status() {\n    let format = Format {\n        style: ProgressStyle::Ratio,\n        max_print: 40,\n        max_width: 60,\n        term_integration: TerminalIntegration::new(false),\n        unicode: true,\n    };\n    assert_eq!(\n        format.progress_status(0, 4, \"\"),\n        Some(\"[                   ] 0/4\".to_string())\n    );\n    assert_eq!(\n        format.progress_status(1, 4, \"\"),\n        Some(\"[===>               ] 1/4\".to_string())\n    );\n    assert_eq!(\n        format.progress_status(2, 4, \"\"),\n        Some(\"[========>          ] 2/4\".to_string())\n    );\n    assert_eq!(\n        format.progress_status(3, 4, \"\"),\n        Some(\"[=============>     ] 3/4\".to_string())\n    );\n    assert_eq!(\n        format.progress_status(4, 4, \"\"),\n        Some(\"[===================] 4/4\".to_string())\n    );\n\n    assert_eq!(\n        format.progress_status(3999, 4000, \"\"),\n        Some(\"[===========> ] 3999/4000\".to_string())\n    );\n    assert_eq!(\n        format.progress_status(4000, 4000, \"\"),\n        Some(\"[=============] 4000/4000\".to_string())\n    );\n\n    assert_eq!(\n        format.progress_status(3, 4, \": short message\"),\n        Some(\"[=============>     ] 3/4: short message\".to_string())\n    );\n    assert_eq!(\n        format.progress_status(3, 4, \": msg thats just fit\"),\n        Some(\"[=============>     ] 3/4: msg thats just fit\".to_string())\n    );\n    assert_eq!(\n        format.progress_status(3, 4, \": msg that's just fit\"),\n        Some(\"[=============>     ] 3/4: msg that's just f…\".to_string())\n    );\n\n    // combining diacritics have width zero and thus can fit max_width.\n    let zalgo_msg = \"z̸̧̢̗͉̝̦͍̱ͧͦͨ̑̅̌ͥ́͢a̢ͬͨ̽ͯ̅̑ͥ͋̏̑ͫ̄͢͏̫̝̪̤͎̱̣͍̭̞̙̱͙͍̘̭͚l̶̡̛̥̝̰̭̹̯̯̞̪͇̱̦͙͔̘̼͇͓̈ͨ͗ͧ̓͒ͦ̀̇ͣ̈ͭ͊͛̃̑͒̿̕͜g̸̷̢̩̻̻͚̠͓̞̥͐ͩ͌̑ͥ̊̽͋͐̐͌͛̐̇̑ͨ́ͅo͙̳̣͔̰̠̜͕͕̞̦̙̭̜̯̹̬̻̓͑ͦ͋̈̉͌̃ͯ̀̂͠ͅ ̸̡͎̦̲̖̤̺̜̮̱̰̥͔̯̅̏ͬ̂ͨ̋̃̽̈́̾̔̇ͣ̚͜͜h̡ͫ̐̅̿̍̀͜҉̛͇̭̹̰̠͙̞ẽ̶̙̹̳̖͉͎̦͂̋̓ͮ̔ͬ̐̀͂̌͑̒͆̚͜͠ ͓͓̟͍̮̬̝̝̰͓͎̼̻ͦ͐̾̔͒̃̓͟͟c̮̦͍̺͈͚̯͕̄̒͐̂͊̊͗͊ͤͣ̀͘̕͝͞o̶͍͚͍̣̮͌ͦ̽̑ͩ̅ͮ̐̽̏͗́͂̅ͪ͠m̷̧͖̻͔̥̪̭͉͉̤̻͖̩̤͖̘ͦ̂͌̆̂ͦ̒͊ͯͬ͊̉̌ͬ͝͡e̵̹̣͍̜̺̤̤̯̫̹̠̮͎͙̯͚̰̼͗͐̀̒͂̉̀̚͝͞s̵̲͍͙͖̪͓͓̺̱̭̩̣͖̣ͤͤ͂̎̈͗͆ͨͪ̆̈͗͝͠\";\n    assert_eq!(\n        format.progress_status(3, 4, zalgo_msg),\n        Some(\"[=============>     ] 3/4\".to_string() + zalgo_msg)\n    );\n\n    // some non-ASCII ellipsize test\n    assert_eq!(\n        format.progress_status(3, 4, \"_123456789123456e\\u{301}\\u{301}8\\u{301}90a\"),\n        Some(\"[=============>     ] 3/4_123456789123456e\\u{301}\\u{301}8\\u{301}9…\".to_string())\n    );\n    assert_eq!(\n        format.progress_status(3, 4, \"：每個漢字佔據了兩個字元\"),\n        Some(\"[=============>     ] 3/4：每個漢字佔據了兩…\".to_string())\n    );\n    assert_eq!(\n        // handle breaking at middle of character\n        format.progress_status(3, 4, \"：-每個漢字佔據了兩個字元\"),\n        Some(\"[=============>     ] 3/4：-每個漢字佔據了兩…\".to_string())\n    );\n}\n\n#[test]\nfn test_progress_status_percentage() {\n    let format = Format {\n        style: ProgressStyle::Percentage,\n        max_print: 40,\n        max_width: 60,\n        term_integration: TerminalIntegration::new(false),\n        unicode: true,\n    };\n    assert_eq!(\n        format.progress_status(0, 77, \"\"),\n        Some(\"[               ]   0.00%\".to_string())\n    );\n    assert_eq!(\n        format.progress_status(1, 77, \"\"),\n        Some(\"[               ]   1.30%\".to_string())\n    );\n    assert_eq!(\n        format.progress_status(76, 77, \"\"),\n        Some(\"[=============> ]  98.70%\".to_string())\n    );\n    assert_eq!(\n        format.progress_status(77, 77, \"\"),\n        Some(\"[===============] 100.00%\".to_string())\n    );\n}\n\n#[test]\nfn test_progress_status_too_short() {\n    let format = Format {\n        style: ProgressStyle::Percentage,\n        max_print: 25,\n        max_width: 25,\n        term_integration: TerminalIntegration::new(false),\n        unicode: true,\n    };\n    assert_eq!(\n        format.progress_status(1, 1, \"\"),\n        Some(\"[] 100.00%\".to_string())\n    );\n\n    let format = Format {\n        style: ProgressStyle::Percentage,\n        max_print: 24,\n        max_width: 24,\n        term_integration: TerminalIntegration::new(false),\n        unicode: true,\n    };\n    assert_eq!(format.progress_status(1, 1, \"\"), None);\n}\n\n#[test]\nfn test_term_integration_disabled() {\n    let report = TerminalIntegration::new(false);\n    let mut out = String::new();\n    out.push_str(&report.remove().to_string());\n    out.push_str(&report.value(10).to_string());\n    out.push_str(&report.indeterminate().to_string());\n    assert!(out.is_empty());\n}\n\n#[test]\nfn test_term_integration_error_state() {\n    let mut report = TerminalIntegration::new(true);\n    assert_eq!(report.value(10), StatusValue::Value(10));\n    report.error();\n    assert_eq!(report.value(50), StatusValue::Error(50));\n}\n"
  },
  {
    "path": "src/cargo/util/queue.rs",
    "content": "use std::collections::VecDeque;\nuse std::sync::{Condvar, Mutex};\nuse std::time::Duration;\n\n/// A simple, threadsafe, queue of items of type `T`\n///\n/// This is a sort of channel where any thread can push to a queue and any\n/// thread can pop from a queue.\n///\n/// This supports both bounded and unbounded operations. [`push`] will never block,\n/// and allows the queue to grow without bounds. [`push_bounded`] will block if\n/// the queue is over capacity, and will resume once there is enough capacity.\n///\n/// [`push`]: Self::push\n/// [`push_bounded`]: Self::push_bounded\npub struct Queue<T> {\n    state: Mutex<State<T>>,\n    popper_cv: Condvar,\n    bounded_cv: Condvar,\n    bound: usize,\n}\n\nstruct State<T> {\n    items: VecDeque<T>,\n}\n\nimpl<T> Queue<T> {\n    /// Creates a queue with a given bound.\n    pub fn new(bound: usize) -> Queue<T> {\n        Queue {\n            state: Mutex::new(State {\n                items: VecDeque::new(),\n            }),\n            popper_cv: Condvar::new(),\n            bounded_cv: Condvar::new(),\n            bound,\n        }\n    }\n\n    /// Pushes an item onto the queue, regardless of the capacity of the queue.\n    pub fn push(&self, item: T) {\n        self.state.lock().unwrap().items.push_back(item);\n        self.popper_cv.notify_one();\n    }\n\n    /// Pushes an item onto the queue, blocking if the queue is full.\n    pub fn push_bounded(&self, item: T) {\n        let locked_state = self.state.lock().unwrap();\n        let mut state = self\n            .bounded_cv\n            .wait_while(locked_state, |s| s.items.len() >= self.bound)\n            .unwrap();\n        state.items.push_back(item);\n        self.popper_cv.notify_one();\n    }\n\n    /// Pops an item from the queue, blocking if the queue is empty.\n    pub fn pop(&self, timeout: Duration) -> Option<T> {\n        let (mut state, result) = self\n            .popper_cv\n            .wait_timeout_while(self.state.lock().unwrap(), timeout, |s| s.items.is_empty())\n            .unwrap();\n        if result.timed_out() {\n            None\n        } else {\n            let value = state.items.pop_front()?;\n            if state.items.len() < self.bound {\n                // Assumes threads cannot be canceled.\n                self.bounded_cv.notify_one();\n            }\n            Some(value)\n        }\n    }\n\n    /// Pops all items from the queue without blocking.\n    pub fn try_pop_all(&self) -> Vec<T> {\n        let mut state = self.state.lock().unwrap();\n        let result = state.items.drain(..).collect();\n        self.bounded_cv.notify_all();\n        result\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/restricted_names.rs",
    "content": "//! Helpers for validating and checking names like package and crate names.\n\nuse std::path::Path;\n\n/// Returns `true` if the name contains non-ASCII characters.\npub fn is_non_ascii_name(name: &str) -> bool {\n    name.chars().any(|ch| ch > '\\x7f')\n}\n\n/// A Rust keyword.\npub fn is_keyword(name: &str) -> bool {\n    // See https://doc.rust-lang.org/reference/keywords.html\n    [\n        \"Self\", \"abstract\", \"as\", \"async\", \"await\", \"become\", \"box\", \"break\", \"const\", \"continue\",\n        \"crate\", \"do\", \"dyn\", \"else\", \"enum\", \"extern\", \"false\", \"final\", \"fn\", \"for\", \"if\",\n        \"impl\", \"in\", \"let\", \"loop\", \"macro\", \"match\", \"mod\", \"move\", \"mut\", \"override\", \"priv\",\n        \"pub\", \"ref\", \"return\", \"self\", \"static\", \"struct\", \"super\", \"trait\", \"true\", \"try\",\n        \"type\", \"typeof\", \"unsafe\", \"unsized\", \"use\", \"virtual\", \"where\", \"while\", \"yield\",\n    ]\n    .contains(&name)\n}\n\n/// These names cannot be used on Windows, even with an extension.\npub fn is_windows_reserved(name: &str) -> bool {\n    [\n        \"con\", \"prn\", \"aux\", \"nul\", \"com1\", \"com2\", \"com3\", \"com4\", \"com5\", \"com6\", \"com7\", \"com8\",\n        \"com9\", \"lpt1\", \"lpt2\", \"lpt3\", \"lpt4\", \"lpt5\", \"lpt6\", \"lpt7\", \"lpt8\", \"lpt9\",\n    ]\n    .contains(&name.to_ascii_lowercase().as_str())\n}\n\n/// An artifact with this name will conflict with one of Cargo's build directories.\npub fn is_conflicting_artifact_name(name: &str) -> bool {\n    [\"deps\", \"examples\", \"build\", \"incremental\"].contains(&name)\n}\n\n/// Check the entire path for names reserved in Windows.\npub fn is_windows_reserved_path(path: &Path) -> bool {\n    path.iter()\n        .filter_map(|component| component.to_str())\n        .any(|component| {\n            let stem = component.split('.').next().unwrap();\n            is_windows_reserved(stem)\n        })\n}\n\n/// Returns `true` if the name contains any glob pattern wildcards.\npub fn is_glob_pattern<T: AsRef<str>>(name: T) -> bool {\n    name.as_ref().contains(&['*', '?', '[', ']'][..])\n}\n"
  },
  {
    "path": "src/cargo/util/rustc.rs",
    "content": "use std::collections::hash_map::HashMap;\nuse std::env;\nuse std::hash::{Hash, Hasher};\nuse std::path::{Path, PathBuf};\nuse std::sync::Mutex;\n\nuse anyhow::Context as _;\nuse cargo_util::{ProcessBuilder, ProcessError, paths};\nuse filetime::FileTime;\nuse serde::{Deserialize, Serialize};\nuse tracing::{debug, info, warn};\n\nuse crate::core::compiler::apply_env_config;\nuse crate::util::interning::InternedString;\nuse crate::util::{CargoResult, GlobalContext, StableHasher};\n\n/// Information on the `rustc` executable\n#[derive(Debug)]\npub struct Rustc {\n    /// The location of the exe\n    pub path: PathBuf,\n    /// An optional program that will be passed the path of the rust exe as its first argument, and\n    /// rustc args following this.\n    pub wrapper: Option<PathBuf>,\n    /// An optional wrapper to be used in addition to `rustc.wrapper` for workspace crates\n    pub workspace_wrapper: Option<PathBuf>,\n    /// Verbose version information (the output of `rustc -vV`)\n    pub verbose_version: String,\n    /// The rustc version (`1.23.4-beta.2`), this comes from `verbose_version`.\n    pub version: semver::Version,\n    /// The host triple (arch-platform-OS), this comes from `verbose_version`.\n    pub host: InternedString,\n    /// The rustc full commit hash, this comes from `verbose_version`.\n    pub commit_hash: Option<String>,\n    cache: Mutex<Cache>,\n}\n\nimpl Rustc {\n    /// Runs the compiler at `path` to learn various pieces of information about\n    /// it, with an optional wrapper.\n    ///\n    /// If successful this function returns a description of the compiler along\n    /// with a list of its capabilities.\n    #[tracing::instrument(skip(gctx))]\n    pub fn new(\n        path: PathBuf,\n        wrapper: Option<PathBuf>,\n        workspace_wrapper: Option<PathBuf>,\n        rustup_rustc: &Path,\n        cache_location: Option<PathBuf>,\n        gctx: &GlobalContext,\n    ) -> CargoResult<Rustc> {\n        let mut cache = Cache::load(\n            wrapper.as_deref(),\n            workspace_wrapper.as_deref(),\n            &path,\n            rustup_rustc,\n            cache_location,\n            gctx,\n        );\n\n        let mut cmd = ProcessBuilder::new(&path)\n            .wrapped(workspace_wrapper.as_ref())\n            .wrapped(wrapper.as_deref());\n        apply_env_config(gctx, &mut cmd)?;\n        cmd.arg(\"-vV\");\n        let verbose_version = cache.cached_output(&cmd, 0)?.0;\n\n        let extract = |field: &str| -> CargoResult<&str> {\n            verbose_version\n                .lines()\n                .find_map(|l| l.strip_prefix(field))\n                .ok_or_else(|| {\n                    anyhow::format_err!(\n                        \"`rustc -vV` didn't have a line for `{}`, got:\\n{}\",\n                        field.trim(),\n                        verbose_version\n                    )\n                })\n        };\n\n        let host = extract(\"host: \")?.into();\n        let version = semver::Version::parse(extract(\"release: \")?).with_context(|| {\n            format!(\n                \"rustc version does not appear to be a valid semver version, from:\\n{}\",\n                verbose_version\n            )\n        })?;\n        let commit_hash = extract(\"commit-hash: \").ok().map(|hash| {\n            // Possible commit-hash values from rustc are SHA hex string and \"unknown\". See:\n            // * https://github.com/rust-lang/rust/blob/531cb83fc/src/bootstrap/src/utils/channel.rs#L73\n            // * https://github.com/rust-lang/rust/blob/531cb83fc/compiler/rustc_driver_impl/src/lib.rs#L911-L913\n            #[cfg(debug_assertions)]\n            if hash != \"unknown\" {\n                debug_assert!(\n                    hash.chars().all(|ch| ch.is_ascii_hexdigit()),\n                    \"commit hash must be a hex string, got: {hash:?}\"\n                );\n                debug_assert!(\n                    hash.len() == 40 || hash.len() == 64,\n                    \"hex string must be generated from sha1 or sha256 (i.e., it must be 40 or 64 characters long)\\ngot: {hash:?}\"\n                );\n            }\n            hash.to_string()\n        });\n\n        Ok(Rustc {\n            path,\n            wrapper,\n            workspace_wrapper,\n            verbose_version,\n            version,\n            host,\n            commit_hash,\n            cache: Mutex::new(cache),\n        })\n    }\n\n    /// Gets a process builder set up to use the found rustc version, with a wrapper if `Some`.\n    pub fn process(&self) -> ProcessBuilder {\n        let mut cmd = ProcessBuilder::new(self.path.as_path()).wrapped(self.wrapper.as_ref());\n        cmd.retry_with_argfile(true);\n        cmd\n    }\n\n    /// Gets a process builder set up to use the found rustc version, with a wrapper if `Some`.\n    pub fn workspace_process(&self) -> ProcessBuilder {\n        let mut cmd = ProcessBuilder::new(self.path.as_path())\n            .wrapped(self.workspace_wrapper.as_ref())\n            .wrapped(self.wrapper.as_ref());\n        cmd.retry_with_argfile(true);\n        cmd\n    }\n\n    pub fn process_no_wrapper(&self) -> ProcessBuilder {\n        let mut cmd = ProcessBuilder::new(&self.path);\n        cmd.retry_with_argfile(true);\n        cmd\n    }\n\n    /// Gets the output for the given command.\n    ///\n    /// This will return the cached value if available, otherwise it will run\n    /// the command and cache the output.\n    ///\n    /// `extra_fingerprint` is extra data to include in the cache fingerprint.\n    /// Use this if there is other information about the environment that may\n    /// affect the output that is not part of `cmd`.\n    ///\n    /// Returns a tuple of strings `(stdout, stderr)`.\n    pub fn cached_output(\n        &self,\n        cmd: &ProcessBuilder,\n        extra_fingerprint: u64,\n    ) -> CargoResult<(String, String)> {\n        self.cache\n            .lock()\n            .unwrap()\n            .cached_output(cmd, extra_fingerprint)\n    }\n}\n\n/// It is a well known fact that `rustc` is not the fastest compiler in the\n/// world.  What is less known is that even `rustc --version --verbose` takes\n/// about a hundred milliseconds! Because we need compiler version info even\n/// for no-op builds, we cache it here, based on compiler's mtime and rustup's\n/// current toolchain.\n///\n/// <https://github.com/rust-lang/cargo/issues/5315>\n/// <https://github.com/rust-lang/rust/issues/49761>\n#[derive(Debug)]\nstruct Cache {\n    cache_location: Option<PathBuf>,\n    dirty: bool,\n    data: CacheData,\n}\n\n#[derive(Serialize, Deserialize, Debug, Default)]\nstruct CacheData {\n    rustc_fingerprint: u64,\n    outputs: HashMap<u64, Output>,\n    successes: HashMap<u64, bool>,\n}\n\n#[derive(Serialize, Deserialize, Debug)]\nstruct Output {\n    success: bool,\n    status: String,\n    code: Option<i32>,\n    stdout: String,\n    stderr: String,\n}\n\nimpl Cache {\n    fn load(\n        wrapper: Option<&Path>,\n        workspace_wrapper: Option<&Path>,\n        rustc: &Path,\n        rustup_rustc: &Path,\n        cache_location: Option<PathBuf>,\n        gctx: &GlobalContext,\n    ) -> Cache {\n        match (\n            cache_location,\n            rustc_fingerprint(wrapper, workspace_wrapper, rustc, rustup_rustc, gctx),\n        ) {\n            (Some(cache_location), Ok(rustc_fingerprint)) => {\n                let empty = CacheData {\n                    rustc_fingerprint,\n                    outputs: HashMap::new(),\n                    successes: HashMap::new(),\n                };\n                let mut dirty = true;\n                let data = match read(&cache_location) {\n                    Ok(data) => {\n                        if data.rustc_fingerprint == rustc_fingerprint {\n                            debug!(\"reusing existing rustc info cache\");\n                            dirty = false;\n                            data\n                        } else {\n                            debug!(\"different compiler, creating new rustc info cache\");\n                            empty\n                        }\n                    }\n                    Err(e) => {\n                        debug!(\"failed to read rustc info cache: {}\", e);\n                        empty\n                    }\n                };\n                return Cache {\n                    cache_location: Some(cache_location),\n                    dirty,\n                    data,\n                };\n\n                fn read(path: &Path) -> CargoResult<CacheData> {\n                    let json = paths::read(path)?;\n                    Ok(serde_json::from_str(&json)?)\n                }\n            }\n            (_, fingerprint) => {\n                if let Err(e) = fingerprint {\n                    warn!(\"failed to calculate rustc fingerprint: {}\", e);\n                }\n                debug!(\"rustc info cache disabled\");\n                Cache {\n                    cache_location: None,\n                    dirty: false,\n                    data: CacheData::default(),\n                }\n            }\n        }\n    }\n\n    fn cached_output(\n        &mut self,\n        cmd: &ProcessBuilder,\n        extra_fingerprint: u64,\n    ) -> CargoResult<(String, String)> {\n        let key = process_fingerprint(cmd, extra_fingerprint);\n        if let std::collections::hash_map::Entry::Vacant(e) = self.data.outputs.entry(key) {\n            debug!(\"rustc info cache miss\");\n            debug!(\"running {}\", cmd);\n            let output = cmd.output()?;\n            let stdout = String::from_utf8(output.stdout)\n                .map_err(|e| anyhow::anyhow!(\"{}: {:?}\", e, e.as_bytes()))\n                .with_context(|| format!(\"`{}` didn't return utf8 output\", cmd))?;\n            let stderr = String::from_utf8(output.stderr)\n                .map_err(|e| anyhow::anyhow!(\"{}: {:?}\", e, e.as_bytes()))\n                .with_context(|| format!(\"`{}` didn't return utf8 output\", cmd))?;\n            e.insert(Output {\n                success: output.status.success(),\n                status: if output.status.success() {\n                    String::new()\n                } else {\n                    cargo_util::exit_status_to_string(output.status)\n                },\n                code: output.status.code(),\n                stdout,\n                stderr,\n            });\n            self.dirty = true;\n        } else {\n            debug!(\"rustc info cache hit\");\n        }\n        let output = &self.data.outputs[&key];\n        if output.success {\n            Ok((output.stdout.clone(), output.stderr.clone()))\n        } else {\n            Err(ProcessError::new_raw(\n                &format!(\"process didn't exit successfully: {}\", cmd),\n                output.code,\n                &output.status,\n                Some(output.stdout.as_ref()),\n                Some(output.stderr.as_ref()),\n            )\n            .into())\n        }\n    }\n}\n\nimpl Drop for Cache {\n    fn drop(&mut self) {\n        if !self.dirty {\n            return;\n        }\n        if let Some(ref path) = self.cache_location {\n            let json = serde_json::to_string(&self.data).unwrap();\n            match paths::write(path, json.as_bytes()) {\n                Ok(()) => info!(\"updated rustc info cache\"),\n                Err(e) => warn!(\"failed to update rustc info cache: {}\", e),\n            }\n        }\n    }\n}\n\nfn rustc_fingerprint(\n    wrapper: Option<&Path>,\n    workspace_wrapper: Option<&Path>,\n    rustc: &Path,\n    rustup_rustc: &Path,\n    gctx: &GlobalContext,\n) -> CargoResult<u64> {\n    let mut hasher = StableHasher::new();\n\n    let hash_exe = |hasher: &mut _, path| -> CargoResult<()> {\n        let path = paths::resolve_executable(path)?;\n        path.hash(hasher);\n\n        let meta = paths::metadata(&path)?;\n        meta.len().hash(hasher);\n\n        // Often created and modified are the same, but not all filesystems support the former,\n        // and distro reproducible builds may clamp the latter, so we try to use both.\n        FileTime::from_creation_time(&meta).hash(hasher);\n        FileTime::from_last_modification_time(&meta).hash(hasher);\n        Ok(())\n    };\n\n    hash_exe(&mut hasher, rustc)?;\n    if let Some(wrapper) = wrapper {\n        hash_exe(&mut hasher, wrapper)?;\n    }\n    if let Some(workspace_wrapper) = workspace_wrapper {\n        hash_exe(&mut hasher, workspace_wrapper)?;\n    }\n\n    // Rustup can change the effective compiler without touching\n    // the `rustc` binary, so we try to account for this here.\n    // If we see rustup's env vars, we mix them into the fingerprint,\n    // but we also mix in the mtime of the actual compiler (and not\n    // the rustup shim at `~/.cargo/bin/rustup`), because `RUSTUP_TOOLCHAIN`\n    // could be just `stable-x86_64-unknown-linux-gnu`, i.e, it could\n    // not mention the version of Rust at all, which changes after\n    // `rustup update`.\n    //\n    // If we don't see rustup env vars, but it looks like the compiler\n    // is managed by rustup, we conservatively bail out.\n    let maybe_rustup = rustup_rustc == rustc;\n    match (\n        maybe_rustup,\n        gctx.get_env(\"RUSTUP_HOME\"),\n        gctx.get_env(\"RUSTUP_TOOLCHAIN\"),\n    ) {\n        (_, Ok(rustup_home), Ok(rustup_toolchain)) => {\n            debug!(\"adding rustup info to rustc fingerprint\");\n            rustup_toolchain.hash(&mut hasher);\n            rustup_home.hash(&mut hasher);\n            let real_rustc = Path::new(&rustup_home)\n                .join(\"toolchains\")\n                .join(rustup_toolchain)\n                .join(\"bin\")\n                .join(\"rustc\")\n                .with_extension(env::consts::EXE_EXTENSION);\n            paths::mtime(&real_rustc)?.hash(&mut hasher);\n        }\n        (true, _, _) => anyhow::bail!(\"probably rustup rustc, but without rustup's env vars\"),\n        _ => (),\n    }\n\n    Ok(Hasher::finish(&hasher))\n}\n\nfn process_fingerprint(cmd: &ProcessBuilder, extra_fingerprint: u64) -> u64 {\n    let mut hasher = StableHasher::new();\n    extra_fingerprint.hash(&mut hasher);\n    cmd.get_args().for_each(|arg| arg.hash(&mut hasher));\n    let mut env = cmd.get_envs().iter().collect::<Vec<_>>();\n    env.sort_unstable();\n    env.hash(&mut hasher);\n    Hasher::finish(&hasher)\n}\n"
  },
  {
    "path": "src/cargo/util/semver_eval_ext.rs",
    "content": "//! Extend `semver::VersionReq` with  [`matches_prerelease`] which doesn't preclude pre-releases by default.\n//!\n//! Please refer to the semantic proposal, see [RFC 3493].\n//!\n//! [RFC 3493]: https://rust-lang.github.io/rfcs/3493-precise-pre-release-cargo-update.html\n\nuse semver::{Comparator, Op, Prerelease, Version, VersionReq};\n\npub(crate) fn matches_prerelease(req: &VersionReq, ver: &Version) -> bool {\n    // Whether there are pre release version can be as lower bound\n    let lower_bound_prerelease = &req.comparators.iter().any(|cmp| {\n        if matches!(cmp.op, Op::Greater | Op::GreaterEq) && !cmp.pre.is_empty() {\n            true\n        } else {\n            false\n        }\n    });\n    for cmp in &req.comparators {\n        if !matches_prerelease_impl(cmp, ver, lower_bound_prerelease) {\n            return false;\n        }\n    }\n\n    true\n}\n\nfn matches_prerelease_impl(cmp: &Comparator, ver: &Version, lower_bound_prerelease: &bool) -> bool {\n    match cmp.op {\n        Op::Exact | Op::Wildcard => matches_exact_prerelease(cmp, ver),\n        Op::Greater => matches_greater(cmp, ver),\n        Op::GreaterEq => {\n            if matches_exact_prerelease(cmp, ver) {\n                return true;\n            }\n            matches_greater(cmp, ver)\n        }\n        Op::Less => {\n            if *lower_bound_prerelease {\n                matches_less(&fill_partial_req(cmp), ver)\n            } else {\n                matches_less(&fill_partial_req_include_pre(cmp), ver)\n            }\n        }\n        Op::LessEq => {\n            if matches_exact_prerelease(cmp, ver) {\n                return true;\n            }\n            matches_less(&fill_partial_req(cmp), ver)\n        }\n        Op::Tilde => matches_tilde_prerelease(cmp, ver),\n        Op::Caret => matches_caret_prerelease(cmp, ver),\n        _ => unreachable!(),\n    }\n}\n\n// See https://github.com/dtolnay/semver/blob/69efd3cc770ead273a06ad1788477b3092996d29/src/eval.rs#L44-L62\nfn matches_exact(cmp: &Comparator, ver: &Version) -> bool {\n    if ver.major != cmp.major {\n        return false;\n    }\n\n    if let Some(minor) = cmp.minor {\n        if ver.minor != minor {\n            return false;\n        }\n    }\n\n    if let Some(patch) = cmp.patch {\n        if ver.patch != patch {\n            return false;\n        }\n    }\n\n    ver.pre == cmp.pre\n}\n\n// See https://github.com/dtolnay/semver/blob/69efd3cc770ead273a06ad1788477b3092996d29/src/eval.rs#L64-L88\nfn matches_greater(cmp: &Comparator, ver: &Version) -> bool {\n    if ver.major != cmp.major {\n        return ver.major > cmp.major;\n    }\n\n    match cmp.minor {\n        None => return false,\n        Some(minor) => {\n            if ver.minor != minor {\n                return ver.minor > minor;\n            }\n        }\n    }\n\n    match cmp.patch {\n        None => return false,\n        Some(patch) => {\n            if ver.patch != patch {\n                return ver.patch > patch;\n            }\n        }\n    }\n\n    ver.pre > cmp.pre\n}\n\n// See https://github.com/dtolnay/semver/blob/69efd3cc770ead273a06ad1788477b3092996d29/src/eval.rs#L90-L114\nfn matches_less(cmp: &Comparator, ver: &Version) -> bool {\n    if ver.major != cmp.major {\n        return ver.major < cmp.major;\n    }\n\n    match cmp.minor {\n        None => return false,\n        Some(minor) => {\n            if ver.minor != minor {\n                return ver.minor < minor;\n            }\n        }\n    }\n\n    match cmp.patch {\n        None => return false,\n        Some(patch) => {\n            if ver.patch != patch {\n                return ver.patch < patch;\n            }\n        }\n    }\n\n    ver.pre < cmp.pre\n}\n\nfn fill_partial_req(cmp: &Comparator) -> Comparator {\n    let mut cmp = cmp.clone();\n    if cmp.minor.is_none() {\n        cmp.minor = Some(0);\n        cmp.patch = Some(0);\n    } else if cmp.patch.is_none() {\n        cmp.patch = Some(0);\n    }\n    cmp\n}\n\nfn fill_partial_req_include_pre(cmp: &Comparator) -> Comparator {\n    let mut cmp = cmp.clone();\n    if cmp.minor.is_none() {\n        cmp.minor = Some(0);\n        cmp.patch = Some(0);\n        cmp.pre = Prerelease::new(\"0\").unwrap();\n    } else if cmp.patch.is_none() {\n        cmp.patch = Some(0);\n    }\n    if cmp.pre.is_empty() {\n        cmp.pre = Prerelease::new(\"0\").unwrap();\n    }\n    cmp\n}\n\nfn matches_exact_prerelease(cmp: &Comparator, ver: &Version) -> bool {\n    if matches_exact(cmp, ver) {\n        return true;\n    }\n\n    // If the comparator has a prerelease tag like =3.0.0-alpha.24,\n    // then it should be only exactly match 3.0.0-alpha.24.\n    if !cmp.pre.is_empty() {\n        return false;\n    }\n\n    if !matches_greater(&fill_partial_req(cmp), ver) {\n        return false;\n    }\n\n    let mut upper = Comparator {\n        op: Op::Less,\n        pre: Prerelease::new(\"0\").unwrap(),\n        ..cmp.clone()\n    };\n\n    match (upper.minor.is_some(), upper.patch.is_some()) {\n        (true, true) => {\n            upper.patch = Some(upper.patch.unwrap() + 1);\n        }\n        (true, false) => {\n            // Partial Exact VersionReq eg. =0.24\n            upper.minor = Some(upper.minor.unwrap() + 1);\n            upper.patch = Some(0);\n        }\n        (false, false) => {\n            // Partial Exact VersionReq eg. =0\n            upper.major += 1;\n            upper.minor = Some(0);\n            upper.patch = Some(0);\n        }\n        _ => {}\n    }\n\n    matches_less(&upper, ver)\n}\n\nfn matches_tilde_prerelease(cmp: &Comparator, ver: &Version) -> bool {\n    if matches_exact(cmp, ver) {\n        return true;\n    }\n\n    if !matches_greater(&fill_partial_req(cmp), ver) {\n        return false;\n    }\n\n    let mut upper = Comparator {\n        op: Op::Less,\n        pre: Prerelease::new(\"0\").unwrap(),\n        ..cmp.clone()\n    };\n\n    match (upper.minor.is_some(), upper.patch.is_some()) {\n        (true, _) => {\n            upper.minor = Some(upper.minor.unwrap() + 1);\n            upper.patch = Some(0);\n        }\n        (false, false) => {\n            upper.major += 1;\n            upper.minor = Some(0);\n            upper.patch = Some(0);\n        }\n        _ => {}\n    }\n\n    matches_less(&upper, ver)\n}\n\nfn matches_caret_prerelease(cmp: &Comparator, ver: &Version) -> bool {\n    if matches_exact(cmp, ver) {\n        return true;\n    }\n\n    if !matches_greater(&fill_partial_req(cmp), ver) {\n        return false;\n    }\n\n    let mut upper = Comparator {\n        op: Op::Less,\n        pre: Prerelease::new(\"0\").unwrap(),\n        ..cmp.clone()\n    };\n\n    match (\n        upper.major > 0,\n        upper.minor.is_some(),\n        upper.patch.is_some(),\n    ) {\n        (true, _, _) | (_, false, false) => {\n            upper.major += 1;\n            upper.minor = Some(0);\n            upper.patch = Some(0);\n        }\n        (_, true, false) => {\n            upper.minor = Some(upper.minor.unwrap() + 1);\n            upper.patch = Some(0);\n        }\n        (_, true, _) if upper.minor.unwrap() > 0 => {\n            upper.minor = Some(upper.minor.unwrap() + 1);\n            upper.patch = Some(0);\n        }\n        (_, true, _) if upper.minor.unwrap() == 0 => {\n            if upper.patch.is_none() {\n                upper.patch = Some(1);\n            } else {\n                upper.patch = Some(upper.patch.unwrap() + 1);\n            }\n        }\n        _ => {}\n    }\n\n    matches_less(&upper, ver)\n}\n\n#[cfg(test)]\nmod matches_prerelease_semantic {\n    use crate::util::semver_ext::VersionReqExt;\n    use semver::{Version, VersionReq};\n\n    fn assert_match_all(req: &VersionReq, versions: &[&str]) {\n        for string in versions {\n            let parsed = Version::parse(string).unwrap();\n            assert!(\n                req.matches_prerelease(&parsed),\n                \"{} did not match {}\",\n                req,\n                string,\n            );\n        }\n    }\n\n    fn assert_match_none(req: &VersionReq, versions: &[&str]) {\n        for string in versions {\n            let parsed = Version::parse(string).unwrap();\n            assert!(\n                !req.matches_prerelease(&parsed),\n                \"{} matched {}\",\n                req,\n                string\n            );\n        }\n    }\n\n    pub(super) fn req(text: &str) -> VersionReq {\n        VersionReq::parse(text).unwrap()\n    }\n\n    #[test]\n    fn test_exact() {\n        // =I.J.K-pre only match I.J.K-pre\n        let ref r = req(\"=4.2.1-0\");\n        // Only exactly match 4.2.1-0\n        assert_match_all(r, &[\"4.2.1-0\"]);\n        // Not match others\n        assert_match_none(r, &[\"1.2.3\", \"4.2.0\", \"4.2.1-1\", \"4.2.2\"]);\n\n        // =I.J.K equivalent to >=I.J.K, <I.J.(K+1)-0\n        for r in &[req(\"=4.2.1\"), req(\">=4.2.1, <4.2.2-0\")] {\n            assert_match_all(r, &[\"4.2.1\"]);\n            assert_match_none(r, &[\"1.2.3\", \"4.2.1-0\", \"4.2.2-0\", \"4.2.2\"]);\n        }\n\n        // =I.J equivalent to >=I.J.0, <I.(J+1).0-0\n        for r in &[req(\"=4.2\"), req(\">=4.2.0, <4.3.0-0\")] {\n            assert_match_all(r, &[\"4.2.0\", \"4.2.1\", \"4.2.9\"]);\n            assert_match_none(r, &[\"0.0.1\", \"2.1.2-0\", \"4.2.0-0\"]);\n            assert_match_none(r, &[\"4.3.0-0\", \"4.3.0\", \"5.0.0-0\", \"5.0.0\"]);\n        }\n\n        // =I equivalent to >=I.0.0, <(I+1).0.0-0\n        for r in &[req(\"=4\"), req(\">=4.0.0, <5.0.0-0\")] {\n            assert_match_all(r, &[\"4.0.0\", \"4.2.1\", \"4.2.4-0\", \"4.9.9\"]);\n            assert_match_none(r, &[\"0.0.1\", \"2.1.2-0\", \"4.0.0-0\"]);\n            assert_match_none(r, &[\"5.0.0-0\", \"5.0.0\", \"5.0.1\"]);\n        }\n    }\n\n    #[test]\n    fn test_greater_eq() {\n        // >=I.J.K-0\n        let ref r = req(\">=4.2.1-0\");\n        assert_match_all(r, &[\"4.2.1-0\", \"4.2.1\", \"5.0.0\"]);\n        assert_match_none(r, &[\"0.0.0\", \"1.2.3\"]);\n\n        // >=I.J.K\n        let ref r = req(\">=4.2.1\");\n        assert_match_all(r, &[\"4.2.1\", \"5.0.0\"]);\n        assert_match_none(r, &[\"0.0.0\", \"4.2.1-0\"]);\n\n        // >=I.J equivalent to >=I.J.0\n        for r in &[req(\">=4.2\"), req(\">=4.2.0\")] {\n            assert_match_all(r, &[\"4.2.1-0\", \"4.2.0\", \"4.3.0\"]);\n            assert_match_none(r, &[\"0.0.0\", \"4.1.1\", \"4.2.0-0\"]);\n        }\n\n        // >=I equivalent to >=I.0.0\n        for r in &[req(\">=4\"), req(\">=4.0.0\")] {\n            assert_match_all(r, &[\"4.0.0\", \"4.1.0-1\", \"5.0.0\"]);\n            assert_match_none(r, &[\"0.0.0\", \"1.2.3\", \"4.0.0-0\"]);\n        }\n    }\n\n    #[test]\n    fn test_less() {\n        // <I.J.K equivalent to <I.J.K-0\n        for r in &[req(\"<4.2.1\"), req(\"<4.2.1-0\")] {\n            assert_match_all(r, &[\"0.0.0\", \"4.0.0\"]);\n            assert_match_none(r, &[\"4.2.1-0\", \"4.2.2\", \"5.0.0-0\", \"5.0.0\"]);\n        }\n\n        // <I.J equivalent to <I.J.0-0\n        for r in &[req(\"<4.2\"), req(\"<4.2.0-0\")] {\n            assert_match_all(r, &[\"0.0.0\", \"4.1.0\"]);\n            assert_match_none(r, &[\"4.2.0-0\", \"4.2.0\", \"4.3.0-0\", \"4.3.0\"]);\n        }\n\n        // <I equivalent to <I.0.0-0\n        for r in &[req(\"<4\"), req(\"<4.0.0-0\")] {\n            assert_match_all(r, &[\"0.0.0\", \"3.9.0\"]);\n            assert_match_none(r, &[\"4.0.0-0\", \"4.0.0\", \"5.0.0-1\", \"5.0.0\"]);\n        }\n    }\n\n    #[test]\n    fn test_less_upper_bound() {\n        // Lower bound without prerelease tag, so upper bound equivalent to <I.J.K-0\n        for r in &[\n            req(\">1.2.3, <2\"),\n            req(\">1.2.3, <2.0\"),\n            req(\">1.2.3, <2.0.0\"),\n            req(\">=1.2.3, <2.0.0\"),\n            req(\">1.2.3, <2.0.0-0\"),\n        ] {\n            assert_match_all(r, &[\"1.2.4\", \"1.9.9\"]);\n            assert_match_none(r, &[\"2.0.0-0\", \"2.0.0\", \"2.1.2\"]);\n        }\n\n        // Lower bound has prerelease tag, so upper bound doesn't change.\n        for r in &[\n            req(\">1.2.3-0, <2\"),\n            req(\">1.2.3-0, <2.0\"),\n            req(\">1.2.3-0, <2.0.0\"),\n            req(\">=1.2.3-0, <2.0.0\"),\n        ] {\n            assert_match_all(r, &[\"1.2.4\", \"1.9.9\", \"2.0.0-0\"]);\n            assert_match_none(r, &[\"2.0.0\", \"2.1.2\"]);\n        }\n\n        for r in &[\n            req(\">=2.0.0-0, <2\"),\n            req(\">=2.0.0-0, <2.0\"),\n            req(\">=2.0.0-0, <2.0.0\"),\n        ] {\n            assert_match_all(r, &[\"2.0.0-0\", \"2.0.0-11\"]);\n            assert_match_none(r, &[\"0.0.9\", \"2.0.0\"]);\n        }\n\n        // There is no intersection between lower bound and upper bound, in this case nothing matches\n        let ref r = req(\">5.0.0, <2.0.0\");\n        assert_match_none(r, &[\"1.2.3\", \"3.0.0\", \"6.0.0\"]);\n        let ref r = req(\">5.0.0-0, <2.0.0\");\n        assert_match_none(r, &[\"1.2.3\", \"3.0.0\", \"6.0.0\"]);\n    }\n\n    #[test]\n    fn test_caret() {\n        // ^I.J.K.0 (for I>0) — equivalent to >=I.J.K-0, <(I+1).0.0-0\n        for r in &[req(\"^1.2.3-0\"), req(\">=1.2.3-0, <2.0.0-0\")] {\n            assert_match_all(r, &[\"1.2.3-0\", \"1.2.3-1\", \"1.2.3\", \"1.9.9\"]);\n            assert_match_none(r, &[\"0.0.9\", \"1.1.1-0\", \"2.0.0-0\", \"2.1.1\"]);\n        }\n\n        // ^I.J.K (for I>0) — equivalent to >=I.J.K, <(I+1).0.0-0\n        for r in &[req(\"^1.2.3\"), req(\">=1.2.3, <2.0.0-0\")] {\n            assert_match_all(r, &[\"1.2.3\", \"1.9.9\"]);\n            assert_match_none(\n                r,\n                &[\"0.0.9\", \"1.1.1-0\", \"1.2.3-0\", \"1.2.3-1\", \"2.0.0-0\", \"2.1.1\"],\n            );\n        }\n\n        // ^0.J.K-0 (for J>0) — equivalent to >=0.J.K-0, <0.(J+1).0-0\n        for r in &[req(\"^0.2.3-0\"), req(\">=0.2.3-0, <0.3.0-0\")] {\n            assert_match_all(r, &[\"0.2.3-0\", \"0.2.3\", \"0.2.9-0\", \"0.2.9\"]);\n            assert_match_none(r, &[\"0.0.9\", \"0.3.0-0\", \"0.3.11\", \"1.1.1\"]);\n        }\n\n        // ^0.J.K (for J>0) — equivalent to >=0.J.K-0, <0.(J+1).0-0\n        for r in &[req(\"^0.2.3\"), req(\">=0.2.3, <0.3.0-0\")] {\n            assert_match_all(r, &[\"0.2.3\", \"0.2.9-0\", \"0.2.9\"]);\n            assert_match_none(r, &[\"0.0.9\", \"0.2.3-0\", \"0.3.0-0\", \"0.3.11\", \"1.1.1\"]);\n        }\n\n        // ^0.0.K-0 — equivalent to >=0.0.K-0, <0.0.(K+1)-0\n        for r in &[req(\"^0.0.3-0\"), req(\">=0.0.3-0, <0.1.0-0\")] {\n            assert_match_all(r, &[\"0.0.3-0\", \"0.0.3-1\", \"0.0.3\"]);\n            assert_match_none(r, &[\"0.0.1\", \"0.3.0-0\", \"0.4.0-0\", \"1.1.1\"]);\n        }\n\n        // ^0.0.K — equivalent to >=0.0.K, <0.0.(K+1)-0\n        for r in &[req(\"^0.0.3\"), req(\">=0.0.3, <0.1.0-0\")] {\n            assert_match_all(r, &[\"0.0.3\"]);\n            assert_match_none(\n                r,\n                &[\"0.0.1\", \"0.0.3-0\", \"0.3.0-0\", \"0.0.3-1\", \"0.4.0-0\", \"1.1.1\"],\n            );\n        }\n\n        // ^I.J (for I>0 or J>0) — equivalent to >=I.J.0, <(I+1).0.0-0)\n        for r in &[req(\"^1.2\"), req(\">=1.2.0, <2.0.0-0\")] {\n            assert_match_all(r, &[\"1.2.0\", \"1.9.0-0\", \"1.9.9\"]);\n            assert_match_none(r, &[\"0.0.1\", \"0.0.4-0\", \"1.2.0-0\", \"2.0.0-0\", \"4.0.1\"]);\n        }\n\n        // ^0.0 — equivalent to >=0.0.0, <0.1.0-0\n        for r in &[req(\"^0.0\"), req(\">=0.0.0, <0.1.0-0\")] {\n            assert_match_all(r, &[\"0.0.0\", \"0.0.1\", \"0.0.4-0\"]);\n            assert_match_none(r, &[\"0.0.0-0\", \"0.1.0-0\", \"0.1.0\", \"1.1.1\"]);\n        }\n\n        // ^I — equivalent to >=I.0.0, <(I+1).0.0-0\n        for r in &[req(\"^1\"), req(\">=1.0.0, <2.0.0-0\")] {\n            assert_match_all(r, &[\"1.0.0\", \"1.0.1\"]);\n            assert_match_none(r, &[\"0.1.0-0\", \"0.1.0\", \"1.0.0-0\", \"2.0.0-0\", \"3.1.2\"]);\n        }\n    }\n\n    #[test]\n    fn test_wildcard() {\n        // I.J.* — equivalent to =I.J\n        //\n        // =I.J equivalent to >=I.J.0, <I.(J+1).0-0\n        for r in &[req(\"4.2.*\"), req(\"=4.2\")] {\n            // Match >= 4.2.0, < 4.3.0-0\n            assert_match_all(r, &[\"4.2.0\", \"4.2.1\", \"4.2.9\"]);\n            // Not Match < 4.2.0\n            assert_match_none(r, &[\"0.0.1\", \"2.1.2-0\", \"4.2.0-0\"]);\n            // Not Match >= 4.3.0-0\n            assert_match_none(r, &[\"4.3.0-0\", \"4.3.0\", \"5.0.0\", \"5.0.1\"]);\n        }\n\n        // I.* or I.*.* — equivalent to =I\n        //\n        // =I equivalent to >=I.0.0, <(I+1).0.0-0\n        for r in &[req(\"4.*\"), req(\"4.*.*\"), req(\"=4\")] {\n            // Match >= 4.0.0, < 5.0.0-0\n            assert_match_all(r, &[\"4.0.0\", \"4.2.1\", \"4.9.9\"]);\n            // Not Match < 4.0.0\n            assert_match_none(r, &[\"0.0.1\", \"2.1.2-0\", \"4.0.0-0\"]);\n            // Not Match >= 5.0.0-0\n            assert_match_none(r, &[\"5.0.0-0\", \"5.0.0\", \"5.0.1\"]);\n        }\n    }\n\n    #[test]\n    fn test_greater() {\n        // >I.J.K-0\n        let ref r = req(\">4.2.1-0\");\n        assert_match_all(r, &[\"4.2.1\", \"4.2.2\", \"5.0.0\"]);\n        assert_match_none(r, &[\"0.0.0\", \"4.2.1-0\"]);\n\n        // >I.J.K\n        let ref r = req(\">4.2.1\");\n        assert_match_all(r, &[\"4.2.2\", \"5.0.0-0\", \"5.0.0\"]);\n        assert_match_none(r, &[\"0.0.0\", \"4.2.1-0\", \"4.2.1\"]);\n\n        // >I.J equivalent to >=I.(J+1).0-0\n        for r in &[req(\">4.2\"), req(\">=4.3.0-0\")] {\n            assert_match_all(r, &[\"4.3.0-0\", \"4.3.0\", \"5.0.0\"]);\n            assert_match_none(r, &[\"0.0.0\", \"4.2.1\"]);\n        }\n\n        // >I equivalent to >=(I+1).0.0-0\n        for r in &[req(\">4\"), req(\">=5.0.0-0\")] {\n            assert_match_all(r, &[\"5.0.0-0\", \"5.0.0\"]);\n            assert_match_none(r, &[\"0.0.0\", \"4.2.1\"]);\n        }\n    }\n\n    #[test]\n    fn test_less_eq() {\n        // <=I.J.K\n        let ref r = req(\"<=4.2.1\");\n        assert_match_all(r, &[\"0.0.0\", \"4.2.1-0\", \"4.2.1\"]);\n        assert_match_none(r, &[\"4.2.2\", \"5.0.0-0\", \"5.0.0\"]);\n        // <=I.J.K-0\n        let ref r = req(\"<=4.2.1-0\");\n        assert_match_all(r, &[\"0.0.0\", \"4.2.1-0\"]);\n        assert_match_none(r, &[\"4.2.1\", \"4.2.2\", \"5.0.0-0\", \"5.0.0\"]);\n\n        // <=I.J equivalent to <I.(J+1).0-0\n        for r in &[req(\"<=4.2\"), req(\"<4.3.0-0\")] {\n            assert_match_all(r, &[\"0.0.0\", \"4.2.0-0\"]);\n            assert_match_none(r, &[\"4.3.0-0\", \"4.3.0\", \"4.4.0\"]);\n        }\n\n        // <=I equivalent to <(I+1).0.0-0\n        for r in &[req(\"<=4\"), req(\"<5.0.0-0\")] {\n            assert_match_all(r, &[\"0.0.0\", \"4.0.0-0\", \"4.0.0\"]);\n            assert_match_none(r, &[\"5.0.0-1\", \"5.0.0\"]);\n        }\n    }\n\n    #[test]\n    fn test_tilde() {\n        // ~I.J.K-0 — equivalent to >=I.J.K-0, <I.(J+1).0-0\n        for r in &[req(\"~1.2.3-0\"), req(\">= 1.2.3-0, < 1.3.0-0\")] {\n            assert_match_all(r, &[\"1.2.3-0\", \"1.2.3\", \"1.2.4-0\", \"1.2.4\"]);\n            assert_match_none(r, &[\"0.0.1\", \"1.1.0-0\"]);\n            assert_match_none(r, &[\"1.3.0-0\", \"1.3.0\", \"1.3.1\", \"2.0.0\"]);\n        }\n\n        // ~I.J.K — equivalent to >=I.J.K, <I.(J+1).0-0\n        for r in &[req(\"~1.2.3\"), req(\">= 1.2.3, < 1.3.0-0\")] {\n            assert_match_all(r, &[\"1.2.3\", \"1.2.4-0\", \"1.2.4\"]);\n            assert_match_none(r, &[\"0.0.1\", \"1.1.0-0\", \"1.2.3-0\"]);\n            assert_match_none(r, &[\"1.3.0-0\", \"1.3.0\", \"1.3.1\", \"2.0.0\"]);\n        }\n\n        // ~I.J — equivalent to >=I.J.0, <I.(J+1).0-0\n        for r in &[req(\"~0.24\"), req(\">=0.24.0, <0.25.0-0\")] {\n            assert_match_all(r, &[\"0.24.0\", \"0.24.1-0\", \"0.24.1\", \"0.24.9\"]);\n            assert_match_none(r, &[\"0.0.1\", \"0.9.9\", \"0.24.0-0\"]);\n            assert_match_none(r, &[\"0.25.0-0\", \"1.1.0\", \"1.2.3\", \"2.0.0\"]);\n        }\n\n        // ~I — >=I.0.0, <(I+1).0.0-0\n        for r in &[req(\"~1\"), req(\">=1.0.0, <2.0.0-0\")] {\n            assert_match_all(r, &[\"1.0.0\", \"1.1.0-0\", \"1.1.0\"]);\n            assert_match_none(r, &[\"0.0.1\", \"0.9.9\", \"1.0.0-0\"]);\n            assert_match_none(r, &[\"2.0.0-0\", \"2.0.0\", \"2.0.1\"]);\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/semver_ext.rs",
    "content": "use super::semver_eval_ext;\nuse semver::{Comparator, Op, Version, VersionReq};\nuse std::fmt::{self, Display};\n\npub trait VersionExt {\n    fn is_prerelease(&self) -> bool;\n\n    fn to_req(&self, op: Op) -> VersionReq;\n\n    fn to_exact_req(&self) -> VersionReq {\n        self.to_req(Op::Exact)\n    }\n\n    fn to_caret_req(&self) -> VersionReq {\n        self.to_req(Op::Caret)\n    }\n}\n\nimpl VersionExt for Version {\n    fn is_prerelease(&self) -> bool {\n        !self.pre.is_empty()\n    }\n\n    fn to_req(&self, op: Op) -> VersionReq {\n        VersionReq {\n            comparators: vec![Comparator {\n                op,\n                major: self.major,\n                minor: Some(self.minor),\n                patch: Some(self.patch),\n                pre: self.pre.clone(),\n            }],\n        }\n    }\n}\n\npub trait VersionReqExt {\n    fn matches_prerelease(&self, version: &Version) -> bool;\n}\n\nimpl VersionReqExt for VersionReq {\n    fn matches_prerelease(&self, version: &Version) -> bool {\n        semver_eval_ext::matches_prerelease(self, version)\n    }\n}\n\n#[derive(PartialEq, Eq, Hash, Clone, Debug)]\npub enum OptVersionReq {\n    Any,\n    Req(VersionReq),\n    /// The exact locked version and the original version requirement.\n    Locked(Version, VersionReq),\n    /// The exact requested version and the original version requirement.\n    ///\n    /// This looks identical to [`OptVersionReq::Locked`] but has a different\n    /// meaning, and is used for the `--precise` field of `cargo update`.\n    /// See comments in [`OptVersionReq::matches`] for more.\n    Precise(Version, VersionReq),\n}\n\nimpl OptVersionReq {\n    pub fn exact(version: &Version) -> Self {\n        OptVersionReq::Req(version.to_exact_req())\n    }\n\n    // Since some registries have allowed crate versions to differ only by build metadata,\n    // A query using OptVersionReq::exact return nondeterministic results.\n    // So we `lock_to` the exact version were interested in.\n    pub fn lock_to_exact(version: &Version) -> Self {\n        OptVersionReq::Locked(version.clone(), version.to_exact_req())\n    }\n\n    pub fn is_exact(&self) -> bool {\n        match self {\n            OptVersionReq::Any => false,\n            OptVersionReq::Req(req) | OptVersionReq::Precise(_, req) => {\n                req.comparators.len() == 1 && {\n                    let cmp = &req.comparators[0];\n                    cmp.op == Op::Exact && cmp.minor.is_some() && cmp.patch.is_some()\n                }\n            }\n            OptVersionReq::Locked(..) => true,\n        }\n    }\n\n    pub fn lock_to(&mut self, version: &Version) {\n        assert!(self.matches(version), \"cannot lock {} to {}\", self, version);\n        use OptVersionReq::*;\n        let version = version.clone();\n        *self = match self {\n            Any => Locked(version, VersionReq::STAR),\n            Req(req) | Locked(_, req) | Precise(_, req) => Locked(version, req.clone()),\n        };\n    }\n\n    /// Makes the requirement precise to the requested version.\n    ///\n    /// This is used for the `--precise` field of `cargo update`.\n    pub fn precise_to(&mut self, version: &Version) {\n        use OptVersionReq::*;\n        let version = version.clone();\n        *self = match self {\n            Any => Precise(version, VersionReq::STAR),\n            Req(req) | Locked(_, req) | Precise(_, req) => Precise(version, req.clone()),\n        };\n    }\n\n    pub fn is_precise(&self) -> bool {\n        matches!(self, OptVersionReq::Precise(..))\n    }\n\n    /// Gets the version to which this req is precise to, if any.\n    pub fn precise_version(&self) -> Option<&Version> {\n        match self {\n            OptVersionReq::Precise(version, _) => Some(version),\n            _ => None,\n        }\n    }\n\n    pub fn is_locked(&self) -> bool {\n        matches!(self, OptVersionReq::Locked(..))\n    }\n\n    /// Gets the version to which this req is locked, if any.\n    pub fn locked_version(&self) -> Option<&Version> {\n        match self {\n            OptVersionReq::Locked(version, _) => Some(version),\n            _ => None,\n        }\n    }\n\n    /// Allows to match pre-release in SemVer-Compatible way.\n    /// See [`semver_eval_ext`] for `matches_prerelease` semantics.\n    pub fn matches_prerelease(&self, version: &Version) -> bool {\n        if let OptVersionReq::Req(req) = self {\n            return req.matches_prerelease(version);\n        } else {\n            return self.matches(version);\n        }\n    }\n\n    pub fn matches(&self, version: &Version) -> bool {\n        match self {\n            OptVersionReq::Any => true,\n            OptVersionReq::Req(req) => req.matches(version),\n            OptVersionReq::Locked(v, _) => {\n                // Generally, cargo is of the opinion that semver metadata should be ignored.\n                // If your registry has two versions that only differing metadata you get the bugs you deserve.\n                // We also believe that lock files should ensure reproducibility\n                // and protect against mutations from the registry.\n                // In this circumstance these two goals are in conflict, and we pick reproducibility.\n                // If the lock file tells us that there is a version called `1.0.0+bar` then\n                // we should not silently use `1.0.0+foo` even though they have the same version.\n                v == version\n            }\n            OptVersionReq::Precise(v, _) => {\n                // This is used for the `--precise` field of cargo update.\n                //\n                // Unfortunately crates.io allowed versions to differ only\n                // by build metadata. This shouldn't be allowed, but since\n                // it is, this will honor it if requested.\n                //\n                // In that context we treat a requirement that does not have\n                // build metadata as allowing any metadata. But, if a requirement\n                // has build metadata, then we only allow it to match the exact\n                // metadata.\n                v.major == version.major\n                    && v.minor == version.minor\n                    && v.patch == version.patch\n                    && v.pre == version.pre\n                    && (v.build == version.build || v.build.is_empty())\n            }\n        }\n    }\n}\n\nimpl Display for OptVersionReq {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            OptVersionReq::Any => f.write_str(\"*\"),\n            OptVersionReq::Req(req)\n            | OptVersionReq::Locked(_, req)\n            | OptVersionReq::Precise(_, req) => Display::fmt(req, f),\n        }\n    }\n}\n\nimpl From<VersionReq> for OptVersionReq {\n    fn from(req: VersionReq) -> Self {\n        OptVersionReq::Req(req)\n    }\n}\n\n#[cfg(test)]\nmod matches_prerelease {\n    use semver::VersionReq;\n\n    use super::OptVersionReq;\n    use super::Version;\n\n    #[test]\n    fn prerelease() {\n        // As of the writing, this test is not the final semantic of pre-release\n        // semver matching. Part of the behavior is buggy. This test just tracks\n        // the current behavior of the unstable `--precise <prerelease>`.\n        //\n        // The below transformation proposed in the RFC is hard to implement\n        // outside the semver crate.\n        //\n        // ```\n        // >=1.2.3, <2.0.0 -> >=1.2.3, <2.0.0-0\n        // ```\n        //\n        // The upper bound semantic is also not resolved. So, at least two\n        // outstanding issues are required to be fixed before the stabilization:\n        //\n        // * Bug 1: `x.y.z-pre.0` shouldn't match `x.y.z`.\n        // * Upper bound: Whether `>=x.y.z-0, <x.y.z` should match `x.y.z-0`.\n        //\n        // See the RFC 3493 for the unresolved upper bound issue:\n        // https://rust-lang.github.io/rfcs/3493-precise-pre-release-cargo-update.html#version-ranges-with-pre-release-upper-bounds\n        let cases = [\n            //\n            (\"1.2.3\", \"1.2.3-0\", false),\n            (\"1.2.3\", \"1.2.3-1\", false),\n            (\"1.2.3\", \"1.2.4-0\", true),\n            //\n            (\">=1.2.3\", \"1.2.3-0\", false),\n            (\">=1.2.3\", \"1.2.3-1\", false),\n            (\">=1.2.3\", \"1.2.4-0\", true),\n            //\n            (\">1.2.3\", \"1.2.3-0\", false),\n            (\">1.2.3\", \"1.2.3-1\", false),\n            (\">1.2.3\", \"1.2.4-0\", true),\n            //\n            (\">1.2.3, <1.2.4\", \"1.2.3-0\", false),\n            (\">1.2.3, <1.2.4\", \"1.2.3-1\", false),\n            (\">1.2.3, <1.2.4\", \"1.2.4-0\", false), // upper bound semantic\n            //\n            (\">=1.2.3, <1.2.4\", \"1.2.3-0\", false),\n            (\">=1.2.3, <1.2.4\", \"1.2.3-1\", false),\n            (\">=1.2.3, <1.2.4\", \"1.2.4-0\", false), // upper bound semantic\n            //\n            (\">1.2.3, <=1.2.4\", \"1.2.3-0\", false),\n            (\">1.2.3, <=1.2.4\", \"1.2.3-1\", false),\n            (\">1.2.3, <=1.2.4\", \"1.2.4-0\", true),\n            //\n            (\">=1.2.3-0, <1.2.3\", \"1.2.3-0\", true), // upper bound semantic\n            (\">=1.2.3-0, <1.2.3\", \"1.2.3-1\", true), // upper bound semantic\n            (\">=1.2.3-0, <1.2.3\", \"1.2.4-0\", false),\n            //\n            (\"1.2.3\", \"2.0.0-0\", false), // upper bound semantics\n            (\"=1.2.3-0\", \"1.2.3\", false),\n            (\"=1.2.3-0\", \"1.2.3-0\", true),\n            (\"=1.2.3-0\", \"1.2.4\", false),\n            (\">=1.2.3-2, <1.2.3-4\", \"1.2.3-0\", false),\n            (\">=1.2.3-2, <1.2.3-4\", \"1.2.3-3\", true),\n            (\">=1.2.3-2, <1.2.3-4\", \"1.2.3-5\", false), // upper bound semantics\n        ];\n        for (req, ver, expected) in cases {\n            let version_req = req.parse().unwrap();\n            let version = ver.parse().unwrap();\n            let matched = OptVersionReq::Req(version_req).matches_prerelease(&version);\n            assert_eq!(expected, matched, \"req: {req}; ver: {ver}\");\n        }\n    }\n\n    #[test]\n    fn opt_version_req_matches_prerelease() {\n        let req_ver: VersionReq = \"^1.2.3-rc.0\".parse().unwrap();\n        let to_ver: Version = \"1.2.3-rc.0\".parse().unwrap();\n\n        let req = OptVersionReq::Req(req_ver.clone());\n        assert!(req.matches_prerelease(&to_ver));\n\n        let req = OptVersionReq::Locked(to_ver.clone(), req_ver.clone());\n        assert!(req.matches_prerelease(&to_ver));\n\n        let req = OptVersionReq::Precise(to_ver.clone(), req_ver.clone());\n        assert!(req.matches_prerelease(&to_ver));\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/sqlite.rs",
    "content": "//! Utilities to help with working with sqlite.\n\nuse crate::CargoResult;\nuse crate::util::interning::InternedString;\nuse rusqlite::types::{FromSql, FromSqlError, ToSql, ToSqlOutput};\nuse rusqlite::{Connection, TransactionBehavior};\n\nimpl FromSql for InternedString {\n    fn column_result(value: rusqlite::types::ValueRef<'_>) -> Result<Self, FromSqlError> {\n        value.as_str().map(InternedString::from)\n    }\n}\n\nimpl ToSql for InternedString {\n    fn to_sql(&self) -> Result<ToSqlOutput<'_>, rusqlite::Error> {\n        Ok(ToSqlOutput::from(self.as_str()))\n    }\n}\n\n/// A function or closure representing a database migration.\n///\n/// Migrations support evolving the schema and contents of the database across\n/// new versions of cargo. The [`migrate`] function should be called\n/// immediately after opening a connection to a database in order to configure\n/// the schema. Whether or not a migration has been done is tracked by the\n/// `pragma_user_version` value in the database. Typically you include the\n/// initial `CREATE TABLE` statements in the initial list, but as time goes on\n/// you can add new tables or `ALTER TABLE` statements. The migration code\n/// will only execute statements that haven't previously been run.\n///\n/// Important things to note about how you define migrations:\n///\n/// * Never remove a migration entry from the list. Migrations are tracked by\n///   the index number in the list.\n/// * Never perform any schema modifications that would be backwards\n///   incompatible. For example, don't drop tables or columns.\n///\n/// The [`basic_migration`] function is a convenience function for specifying\n/// migrations that are simple SQL statements. If you need to do something\n/// more complex, then you can specify a closure that takes a [`Connection`]\n/// and does whatever is needed.\n///\n/// For example:\n///\n/// ```rust\n/// # use cargo::util::sqlite::*;\n/// # use rusqlite::Connection;\n/// # let mut conn = Connection::open_in_memory()?;\n/// # fn generate_name() -> String { \"example\".to_string() };\n/// migrate(\n///     &mut conn,\n///     &[\n///         basic_migration(\n///             \"CREATE TABLE foo (\n///                 id INTEGER PRIMARY KEY AUTOINCREMENT,\n///                 name STRING NOT NULL\n///             )\",\n///         ),\n///         Box::new(|conn| {\n///             conn.execute(\"INSERT INTO foo (name) VALUES (?1)\", [generate_name()])?;\n///             Ok(())\n///         }),\n///         basic_migration(\"ALTER TABLE foo ADD COLUMN size INTEGER\"),\n///     ],\n/// )?;\n/// # Ok::<(), anyhow::Error>(())\n/// ```\npub type Migration = Box<dyn Fn(&Connection) -> CargoResult<()>>;\n\n/// A basic migration that is a single static SQL statement.\n///\n/// See [`Migration`] for more information.\npub fn basic_migration(stmt: &'static str) -> Migration {\n    Box::new(|conn| {\n        conn.execute(stmt, [])?;\n        Ok(())\n    })\n}\n\n/// Perform one-time SQL migrations.\n///\n/// See [`Migration`] for more information.\npub fn migrate(conn: &mut Connection, migrations: &[Migration]) -> CargoResult<()> {\n    // EXCLUSIVE ensures that it starts with an exclusive write lock. No other\n    // readers will be allowed. This generally shouldn't be needed if there is\n    // a file lock, but might be helpful in cases where cargo's `FileLock`\n    // failed.\n    let tx = conn.transaction_with_behavior(TransactionBehavior::Exclusive)?;\n    let user_version = tx.query_row(\"SELECT user_version FROM pragma_user_version\", [], |row| {\n        row.get(0)\n    })?;\n    if user_version < migrations.len() {\n        for migration in &migrations[user_version..] {\n            migration(&tx)?;\n        }\n        tx.pragma_update(None, \"user_version\", &migrations.len())?;\n    }\n    tx.commit()?;\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn migrate_twice() -> CargoResult<()> {\n        // Check that a second migration will apply.\n        let mut conn = Connection::open_in_memory()?;\n        let mut migrations = vec![basic_migration(\"CREATE TABLE foo (a, b, c)\")];\n        migrate(&mut conn, &migrations)?;\n        conn.execute(\"INSERT INTO foo VALUES (1,2,3)\", [])?;\n        migrations.push(basic_migration(\"ALTER TABLE foo ADD COLUMN d\"));\n        migrate(&mut conn, &migrations)?;\n        conn.execute(\"INSERT INTO foo VALUES (1,2,3,4)\", [])?;\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/style.rs",
    "content": "use anstyle::*;\n\npub const NOP: Style = Style::new();\npub const HEADER: Style = AnsiColor::BrightGreen.on_default().effects(Effects::BOLD);\npub const USAGE: Style = AnsiColor::BrightGreen.on_default().effects(Effects::BOLD);\npub const LITERAL: Style = AnsiColor::BrightCyan.on_default().effects(Effects::BOLD);\npub const PLACEHOLDER: Style = AnsiColor::Cyan.on_default();\npub const ERROR: Style = annotate_snippets::renderer::DEFAULT_ERROR_STYLE;\npub const WARN: Style = annotate_snippets::renderer::DEFAULT_WARNING_STYLE;\npub const NOTE: Style = annotate_snippets::renderer::DEFAULT_NOTE_STYLE;\npub const GOOD: Style = AnsiColor::BrightGreen.on_default().effects(Effects::BOLD);\npub const VALID: Style = AnsiColor::BrightCyan.on_default().effects(Effects::BOLD);\npub const INVALID: Style = annotate_snippets::renderer::DEFAULT_WARNING_STYLE;\npub const TRANSIENT: Style = annotate_snippets::renderer::DEFAULT_HELP_STYLE;\npub const CONTEXT: Style = annotate_snippets::renderer::DEFAULT_CONTEXT_STYLE;\n\npub const UPDATE_ADDED: Style = NOTE;\npub const UPDATE_REMOVED: Style = ERROR;\npub const UPDATE_UPGRADED: Style = GOOD;\npub const UPDATE_DOWNGRADED: Style = WARN;\npub const UPDATE_UNCHANGED: Style = anstyle::Style::new().bold();\n\npub const DEP_NORMAL: Style = anstyle::Style::new().effects(anstyle::Effects::DIMMED);\npub const DEP_BUILD: Style = anstyle::AnsiColor::Blue\n    .on_default()\n    .effects(anstyle::Effects::BOLD);\npub const DEP_DEV: Style = anstyle::AnsiColor::Cyan\n    .on_default()\n    .effects(anstyle::Effects::BOLD);\npub const DEP_FEATURE: Style = anstyle::AnsiColor::Magenta\n    .on_default()\n    .effects(anstyle::Effects::DIMMED);\n"
  },
  {
    "path": "src/cargo/util/toml/embedded.rs",
    "content": "use cargo_util_schemas::manifest::PackageName;\n\nuse crate::util::frontmatter::FrontmatterError;\nuse crate::util::frontmatter::ScriptSource;\n\npub(super) fn expand_manifest(content: &str) -> Result<String, FrontmatterError> {\n    let source = ScriptSource::parse(content)?;\n    if let Some(span) = source.frontmatter_span() {\n        match source.info() {\n            Some(\"cargo\") | None => {}\n            Some(other) => {\n                let info_span = source.info_span().unwrap();\n                let close_span = source.close_span().unwrap();\n                if let Some(remainder) = other.strip_prefix(\"cargo,\") {\n                    return Err(FrontmatterError::new(\n                        format!(\"unsupported frontmatter infostring attributes: `{remainder}`\"),\n                        info_span,\n                    )\n                    .push_visible_span(close_span));\n                } else {\n                    return Err(FrontmatterError::new(\n                        format!(\n                            \"unsupported frontmatter infostring `{other}`; specify `cargo` for embedding a manifest\"\n                        ),\n                        info_span,\n                    ).push_visible_span(close_span));\n                }\n            }\n        }\n\n        // Include from file start to frontmatter end when we parse the TOML to get line numbers\n        // correct and so if a TOML error says \"entire file\", it shows the existing content, rather\n        // than blank lines.\n        //\n        // HACK: Since frontmatter open isn't valid TOML, we insert a comment\n        let mut frontmatter = content[0..span.end].to_owned();\n        let open_span = source.open_span().unwrap();\n        frontmatter.insert(open_span.start, '#');\n        Ok(frontmatter)\n    } else {\n        // Consider the shebang to be part of the frontmatter\n        // so if a TOML error says \"entire file\", it shows the existing content, rather\n        // than blank lines.\n        let span = source.shebang_span().unwrap_or(0..0);\n        Ok(content[span].to_owned())\n    }\n}\n\n/// Ensure the package name matches the validation from `ops::cargo_new::check_name`\npub fn sanitize_name(name: &str) -> String {\n    let placeholder = if name.contains('_') {\n        '_'\n    } else {\n        // Since embedded manifests only support `[[bin]]`s, prefer arrow-case as that is the\n        // more common convention for CLIs\n        '-'\n    };\n\n    PackageName::sanitize(name, placeholder).into_inner()\n}\n\n#[cfg(test)]\nmod test {\n    use snapbox::assert_data_eq;\n    use snapbox::str;\n\n    use super::*;\n\n    #[track_caller]\n    fn expand(source: &str) -> String {\n        expand_manifest(source).unwrap_or_else(|err| panic!(\"{}\", err))\n    }\n\n    #[test]\n    fn expand_default() {\n        assert_data_eq!(expand(r#\"fn main() {}\"#), str![\"\"]);\n    }\n\n    #[test]\n    fn expand_dependencies() {\n        assert_data_eq!(\n            expand(\n                r#\"---cargo\n[dependencies]\ntime=\"0.1.25\"\n---\nfn main() {}\n\"#\n            ),\n            str![[r##\"\n#---cargo\n[dependencies]\ntime=\"0.1.25\"\n\n\"##]]\n        );\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/toml/mod.rs",
    "content": "use annotate_snippets::{AnnotationKind, Group, Level, Snippet};\nuse std::borrow::Cow;\nuse std::cell::OnceCell;\nuse std::collections::{BTreeMap, BTreeSet, HashMap};\nuse std::ffi::OsStr;\nuse std::path::{Path, PathBuf};\nuse std::rc::Rc;\nuse std::str::{self, FromStr};\n\nuse crate::AlreadyPrintedError;\nuse crate::core::summary::MissingDependencyError;\nuse anyhow::{Context as _, anyhow, bail};\nuse cargo_platform::Platform;\nuse cargo_util::paths;\nuse cargo_util_schemas::manifest::{\n    self, PackageName, PathBaseName, TomlDependency, TomlDetailedDependency, TomlManifest,\n    TomlPackageBuild, TomlWorkspace,\n};\nuse cargo_util_schemas::manifest::{RustVersion, StringOrBool};\nuse itertools::Itertools;\nuse pathdiff::diff_paths;\nuse url::Url;\n\nuse crate::core::compiler::{CompileKind, CompileTarget};\nuse crate::core::dependency::{Artifact, ArtifactTarget, DepKind};\nuse crate::core::manifest::{ManifestMetadata, TargetSourcePath};\nuse crate::core::resolver::ResolveBehavior;\nuse crate::core::{\n    CliUnstable, FeatureValue, Patch, PatchLocation, find_workspace_root, resolve_relative_path,\n};\nuse crate::core::{Dependency, Manifest, Package, PackageId, Summary, Target};\nuse crate::core::{Edition, EitherManifest, Feature, Features, VirtualManifest, Workspace};\nuse crate::core::{GitReference, PackageIdSpec, SourceId, WorkspaceConfig, WorkspaceRootConfig};\nuse crate::lints::get_key_value_span;\nuse crate::lints::rel_cwd_manifest_path;\nuse crate::sources::{CRATES_IO_INDEX, CRATES_IO_REGISTRY};\nuse crate::util::errors::{CargoResult, ManifestError};\nuse crate::util::interning::InternedString;\nuse crate::util::{\n    self, GlobalContext, IntoUrl, OnceExt, OptVersionReq, context::ConfigRelativePath,\n    context::TOP_LEVEL_CONFIG_KEYS,\n};\n\nmod embedded;\nmod targets;\n\nuse self::targets::to_targets;\n\n/// See also `bin/cargo/commands/run.rs`s `is_manifest_command`\npub fn is_embedded(path: &Path) -> bool {\n    let ext = path.extension();\n    ext == Some(OsStr::new(\"rs\")) || ext.is_none()\n}\n\n/// Loads a `Cargo.toml` from a file on disk.\n///\n/// This could result in a real or virtual manifest being returned.\n///\n/// A list of nested paths is also returned, one for each path dependency\n/// within the manifest. For virtual manifests, these paths can only\n/// come from patched or replaced dependencies. These paths are not\n/// canonicalized.\n#[tracing::instrument(skip(gctx))]\npub fn read_manifest(\n    path: &Path,\n    source_id: SourceId,\n    gctx: &GlobalContext,\n) -> CargoResult<EitherManifest> {\n    let mut warnings = Default::default();\n    let mut errors = Default::default();\n\n    let is_embedded = is_embedded(path);\n    let contents = read_toml_string(path, is_embedded, gctx)?;\n    let document = parse_document(&contents)\n        .map_err(|e| emit_toml_diagnostic(e.into(), &contents, path, gctx))?;\n    let original_toml = deserialize_toml(&document)\n        .map_err(|e| emit_toml_diagnostic(e.into(), &contents, path, gctx))?;\n\n    let mut manifest = (|| {\n        let empty = Vec::new();\n        let cargo_features = original_toml.cargo_features.as_ref().unwrap_or(&empty);\n        let features = Features::new(cargo_features, gctx, &mut warnings, source_id.is_path())?;\n        let workspace_config =\n            to_workspace_config(&original_toml, path, is_embedded, gctx, &mut warnings)?;\n        if let WorkspaceConfig::Root(ws_root_config) = &workspace_config {\n            let package_root = path.parent().unwrap();\n            gctx.ws_roots()\n                .insert(package_root.to_owned(), ws_root_config.clone());\n        }\n        let normalized_toml = normalize_toml(\n            &original_toml,\n            &features,\n            &workspace_config,\n            path,\n            is_embedded,\n            gctx,\n            &mut warnings,\n            &mut errors,\n        )?;\n\n        if normalized_toml.package().is_some() {\n            to_real_manifest(\n                Some(contents),\n                Some(document),\n                original_toml,\n                normalized_toml,\n                features,\n                workspace_config,\n                source_id,\n                path,\n                is_embedded,\n                gctx,\n                &mut warnings,\n                &mut errors,\n            )\n            .map(EitherManifest::Real)\n        } else if normalized_toml.workspace.is_some() {\n            assert!(!is_embedded);\n            to_virtual_manifest(\n                Some(contents),\n                Some(document),\n                original_toml,\n                normalized_toml,\n                features,\n                workspace_config,\n                source_id,\n                path,\n                gctx,\n                &mut warnings,\n                &mut errors,\n            )\n            .map(EitherManifest::Virtual)\n        } else {\n            anyhow::bail!(\"manifest is missing either a `[package]` or a `[workspace]`\")\n        }\n    })()\n    .map_err(|err| {\n        ManifestError::new(\n            err.context(format!(\"failed to parse manifest at `{}`\", path.display())),\n            path.into(),\n        )\n    })?;\n\n    for warning in warnings {\n        manifest.warnings_mut().add_warning(warning);\n    }\n    for error in errors {\n        manifest.warnings_mut().add_critical_warning(error);\n    }\n\n    Ok(manifest)\n}\n\n#[tracing::instrument(skip_all)]\nfn read_toml_string(path: &Path, is_embedded: bool, gctx: &GlobalContext) -> CargoResult<String> {\n    let mut contents = paths::read(path).map_err(|err| ManifestError::new(err, path.into()))?;\n    if is_embedded {\n        if !gctx.cli_unstable().script {\n            anyhow::bail!(\"parsing `{}` requires `-Zscript`\", path.display());\n        }\n        contents = embedded::expand_manifest(&contents)\n            .map_err(|e| emit_frontmatter_diagnostic(e, &contents, path, gctx))?;\n    }\n    Ok(contents)\n}\n\n#[tracing::instrument(skip_all)]\nfn parse_document(\n    contents: &str,\n) -> Result<toml::Spanned<toml::de::DeTable<'static>>, toml::de::Error> {\n    let mut table = toml::de::DeTable::parse(contents)?;\n    table.get_mut().make_owned();\n    // SAFETY: `DeTable::make_owned` ensures no borrows remain and the lifetime does not affect\n    // layout\n    let table = unsafe {\n        std::mem::transmute::<\n            toml::Spanned<toml::de::DeTable<'_>>,\n            toml::Spanned<toml::de::DeTable<'static>>,\n        >(table)\n    };\n    Ok(table)\n}\n\n#[tracing::instrument(skip_all)]\nfn deserialize_toml(\n    document: &toml::Spanned<toml::de::DeTable<'static>>,\n) -> Result<manifest::TomlManifest, toml::de::Error> {\n    let mut unused = BTreeSet::new();\n    let deserializer = toml::de::Deserializer::from(document.clone());\n    let mut document: manifest::TomlManifest = serde_ignored::deserialize(deserializer, |path| {\n        let mut key = String::new();\n        stringify(&mut key, &path);\n        unused.insert(key);\n    })?;\n    document._unused_keys = unused;\n    Ok(document)\n}\n\nfn stringify(dst: &mut String, path: &serde_ignored::Path<'_>) {\n    use serde_ignored::Path;\n\n    match *path {\n        Path::Root => {}\n        Path::Seq { parent, index } => {\n            stringify(dst, parent);\n            if !dst.is_empty() {\n                dst.push('.');\n            }\n            dst.push_str(&index.to_string());\n        }\n        Path::Map { parent, ref key } => {\n            stringify(dst, parent);\n            if !dst.is_empty() {\n                dst.push('.');\n            }\n            dst.push_str(key);\n        }\n        Path::Some { parent }\n        | Path::NewtypeVariant { parent }\n        | Path::NewtypeStruct { parent } => stringify(dst, parent),\n    }\n}\n\nfn to_workspace_config(\n    original_toml: &manifest::TomlManifest,\n    manifest_file: &Path,\n    is_embedded: bool,\n    gctx: &GlobalContext,\n    warnings: &mut Vec<String>,\n) -> CargoResult<WorkspaceConfig> {\n    if is_embedded {\n        let ws_root_config = to_workspace_root_config(&TomlWorkspace::default(), manifest_file);\n        return Ok(WorkspaceConfig::Root(ws_root_config));\n    }\n    let workspace_config = match (\n        original_toml.workspace.as_ref(),\n        original_toml.package().and_then(|p| p.workspace.as_ref()),\n    ) {\n        (Some(toml_config), None) => {\n            verify_lints(toml_config.lints.as_ref(), gctx, warnings)?;\n            if let Some(ws_deps) = &toml_config.dependencies {\n                for (name, dep) in ws_deps {\n                    if dep.is_optional() {\n                        bail!(\"{name} is optional, but workspace dependencies cannot be optional\",);\n                    }\n                    if dep.is_public() {\n                        bail!(\"{name} is public, but workspace dependencies cannot be public\",);\n                    }\n                }\n\n                for (name, dep) in ws_deps {\n                    unused_dep_keys(name, \"workspace.dependencies\", dep.unused_keys(), warnings);\n                }\n            }\n            let ws_root_config = to_workspace_root_config(toml_config, manifest_file);\n            WorkspaceConfig::Root(ws_root_config)\n        }\n        (None, root) => WorkspaceConfig::Member {\n            root: root.cloned(),\n        },\n        (Some(..), Some(..)) => bail!(\n            \"cannot configure both `package.workspace` and \\\n                 `[workspace]`, only one can be specified\"\n        ),\n    };\n    Ok(workspace_config)\n}\n\nfn to_workspace_root_config(\n    normalized_toml: &manifest::TomlWorkspace,\n    manifest_file: &Path,\n) -> WorkspaceRootConfig {\n    let package_root = manifest_file.parent().unwrap();\n    let inheritable = InheritableFields {\n        package: normalized_toml.package.clone(),\n        dependencies: normalized_toml.dependencies.clone(),\n        lints: normalized_toml.lints.clone(),\n        _ws_root: package_root.to_owned(),\n    };\n    let ws_root_config = WorkspaceRootConfig::new(\n        package_root,\n        &normalized_toml.members,\n        &normalized_toml.default_members,\n        &normalized_toml.exclude,\n        &Some(inheritable),\n        &normalized_toml.metadata,\n    );\n    ws_root_config\n}\n\n/// See [`Manifest::normalized_toml`] for more details\n#[tracing::instrument(skip_all)]\nfn normalize_toml(\n    original_toml: &manifest::TomlManifest,\n    features: &Features,\n    workspace_config: &WorkspaceConfig,\n    manifest_file: &Path,\n    is_embedded: bool,\n    gctx: &GlobalContext,\n    warnings: &mut Vec<String>,\n    errors: &mut Vec<String>,\n) -> CargoResult<manifest::TomlManifest> {\n    let package_root = manifest_file.parent().unwrap();\n\n    let inherit_cell: OnceCell<InheritableFields> = OnceCell::new();\n    let inherit = || {\n        inherit_cell\n            .try_borrow_with(|| load_inheritable_fields(gctx, manifest_file, &workspace_config))\n    };\n    let workspace_root = || inherit().map(|fields| fields.ws_root().as_path());\n\n    let mut normalized_toml = manifest::TomlManifest {\n        cargo_features: original_toml.cargo_features.clone(),\n        package: None,\n        project: None,\n        badges: None,\n        features: None,\n        lib: None,\n        bin: None,\n        example: None,\n        test: None,\n        bench: None,\n        dependencies: None,\n        dev_dependencies: None,\n        dev_dependencies2: None,\n        build_dependencies: None,\n        build_dependencies2: None,\n        target: None,\n        lints: None,\n        hints: None,\n        workspace: original_toml.workspace.clone().or_else(|| {\n            // Prevent looking for a workspace by `read_manifest_from_str`\n            is_embedded.then(manifest::TomlWorkspace::default)\n        }),\n        profile: original_toml.profile.clone(),\n        patch: normalize_patch(\n            gctx,\n            original_toml.patch.as_ref(),\n            &workspace_root,\n            features,\n        )?,\n        replace: original_toml.replace.clone(),\n        _unused_keys: Default::default(),\n    };\n\n    if let Some(original_package) = original_toml.package().map(Cow::Borrowed).or_else(|| {\n        if is_embedded {\n            Some(Cow::Owned(Box::new(manifest::TomlPackage::default())))\n        } else {\n            None\n        }\n    }) {\n        let normalized_package = normalize_package_toml(\n            &original_package,\n            manifest_file,\n            is_embedded,\n            gctx,\n            &inherit,\n            features,\n        )?;\n        let package_name = &normalized_package\n            .normalized_name()\n            .expect(\"previously normalized\")\n            .clone();\n        let edition = normalized_package\n            .normalized_edition()\n            .expect(\"previously normalized\")\n            .map_or(Edition::default(), |e| {\n                Edition::from_str(&e).unwrap_or_default()\n            });\n        normalized_toml.package = Some(normalized_package);\n\n        normalized_toml.features = normalize_features(original_toml.features.as_ref())?;\n\n        let auto_embedded = is_embedded.then_some(false);\n        normalized_toml.lib = targets::normalize_lib(\n            original_toml.lib.as_ref(),\n            package_root,\n            package_name,\n            edition,\n            original_package.autolib.or(auto_embedded),\n            warnings,\n        )?;\n        let original_toml_bin = if is_embedded {\n            let name = package_name.as_ref().to_owned();\n            let manifest_file_name = manifest_file\n                .file_name()\n                .expect(\"file name enforced previously\");\n            let path = PathBuf::from(manifest_file_name);\n            Cow::Owned(Some(vec![manifest::TomlBinTarget {\n                name: Some(name),\n                crate_type: None,\n                crate_type2: None,\n                path: Some(manifest::PathValue(path)),\n                filename: None,\n                test: None,\n                doctest: None,\n                bench: None,\n                doc: None,\n                doc_scrape_examples: None,\n                proc_macro: None,\n                proc_macro2: None,\n                harness: None,\n                required_features: None,\n                edition: None,\n            }]))\n        } else {\n            Cow::Borrowed(&original_toml.bin)\n        };\n        normalized_toml.bin = Some(targets::normalize_bins(\n            original_toml_bin.as_ref().as_ref(),\n            package_root,\n            package_name,\n            edition,\n            original_package.autobins.or(auto_embedded),\n            warnings,\n            errors,\n            normalized_toml.lib.is_some(),\n        )?);\n        normalized_toml.example = Some(targets::normalize_examples(\n            original_toml.example.as_ref(),\n            package_root,\n            edition,\n            original_package.autoexamples.or(auto_embedded),\n            warnings,\n            errors,\n        )?);\n        normalized_toml.test = Some(targets::normalize_tests(\n            original_toml.test.as_ref(),\n            package_root,\n            edition,\n            original_package.autotests.or(auto_embedded),\n            warnings,\n            errors,\n        )?);\n        normalized_toml.bench = Some(targets::normalize_benches(\n            original_toml.bench.as_ref(),\n            package_root,\n            edition,\n            original_package.autobenches.or(auto_embedded),\n            warnings,\n            errors,\n        )?);\n\n        normalized_toml.dependencies = normalize_dependencies(\n            gctx,\n            edition,\n            &features,\n            original_toml.dependencies.as_ref(),\n            DepKind::Normal,\n            &inherit,\n            &workspace_root,\n            package_root,\n            warnings,\n        )?;\n        deprecated_underscore(\n            &original_toml.dev_dependencies2,\n            &original_toml.dev_dependencies,\n            \"dev-dependencies\",\n            package_name,\n            \"package\",\n            edition,\n            warnings,\n        )?;\n        normalized_toml.dev_dependencies = normalize_dependencies(\n            gctx,\n            edition,\n            &features,\n            original_toml.dev_dependencies(),\n            DepKind::Development,\n            &inherit,\n            &workspace_root,\n            package_root,\n            warnings,\n        )?;\n        deprecated_underscore(\n            &original_toml.build_dependencies2,\n            &original_toml.build_dependencies,\n            \"build-dependencies\",\n            package_name,\n            \"package\",\n            edition,\n            warnings,\n        )?;\n        normalized_toml.build_dependencies = normalize_dependencies(\n            gctx,\n            edition,\n            &features,\n            original_toml.build_dependencies(),\n            DepKind::Build,\n            &inherit,\n            &workspace_root,\n            package_root,\n            warnings,\n        )?;\n        let mut normalized_target = BTreeMap::new();\n        for (name, platform) in original_toml.target.iter().flatten() {\n            let normalized_dependencies = normalize_dependencies(\n                gctx,\n                edition,\n                &features,\n                platform.dependencies.as_ref(),\n                DepKind::Normal,\n                &inherit,\n                &workspace_root,\n                package_root,\n                warnings,\n            )?;\n            deprecated_underscore(\n                &platform.dev_dependencies2,\n                &platform.dev_dependencies,\n                \"dev-dependencies\",\n                name,\n                \"platform target\",\n                edition,\n                warnings,\n            )?;\n            let normalized_dev_dependencies = normalize_dependencies(\n                gctx,\n                edition,\n                &features,\n                platform.dev_dependencies(),\n                DepKind::Development,\n                &inherit,\n                &workspace_root,\n                package_root,\n                warnings,\n            )?;\n            deprecated_underscore(\n                &platform.build_dependencies2,\n                &platform.build_dependencies,\n                \"build-dependencies\",\n                name,\n                \"platform target\",\n                edition,\n                warnings,\n            )?;\n            let normalized_build_dependencies = normalize_dependencies(\n                gctx,\n                edition,\n                &features,\n                platform.build_dependencies(),\n                DepKind::Build,\n                &inherit,\n                &workspace_root,\n                package_root,\n                warnings,\n            )?;\n            normalized_target.insert(\n                name.clone(),\n                manifest::TomlPlatform {\n                    dependencies: normalized_dependencies,\n                    build_dependencies: normalized_build_dependencies,\n                    build_dependencies2: None,\n                    dev_dependencies: normalized_dev_dependencies,\n                    dev_dependencies2: None,\n                },\n            );\n        }\n        normalized_toml.target = (!normalized_target.is_empty()).then_some(normalized_target);\n\n        let normalized_lints = original_toml\n            .lints\n            .clone()\n            .map(|value| lints_inherit_with(value, || inherit()?.lints()))\n            .transpose()?;\n        normalized_toml.lints = normalized_lints.map(|lints| manifest::InheritableLints {\n            workspace: false,\n            lints,\n        });\n\n        normalized_toml.hints = original_toml.hints.clone();\n\n        normalized_toml.badges = original_toml.badges.clone();\n    } else {\n        if let Some(field) = original_toml.requires_package().next() {\n            bail!(\"this virtual manifest specifies a `{field}` section, which is not allowed\");\n        }\n    }\n\n    Ok(normalized_toml)\n}\n\nfn normalize_patch<'a>(\n    gctx: &GlobalContext,\n    original_patch: Option<&BTreeMap<String, BTreeMap<PackageName, TomlDependency>>>,\n    workspace_root: &dyn Fn() -> CargoResult<&'a Path>,\n    features: &Features,\n) -> CargoResult<Option<BTreeMap<String, BTreeMap<PackageName, TomlDependency>>>> {\n    if let Some(patch) = original_patch {\n        let mut normalized_patch = BTreeMap::new();\n        for (name, packages) in patch {\n            let mut normalized_packages = BTreeMap::new();\n            for (pkg, dep) in packages {\n                let dep = if let TomlDependency::Detailed(dep) = dep {\n                    let mut dep = dep.clone();\n                    normalize_path_dependency(gctx, &mut dep, workspace_root, features)\n                        .with_context(|| {\n                            format!(\"resolving path for patch of ({pkg}) for source ({name})\")\n                        })?;\n                    TomlDependency::Detailed(dep)\n                } else {\n                    dep.clone()\n                };\n                normalized_packages.insert(pkg.clone(), dep);\n            }\n            normalized_patch.insert(name.clone(), normalized_packages);\n        }\n        Ok(Some(normalized_patch))\n    } else {\n        Ok(None)\n    }\n}\n\n#[tracing::instrument(skip_all)]\nfn normalize_package_toml<'a>(\n    original_package: &manifest::TomlPackage,\n    manifest_file: &Path,\n    is_embedded: bool,\n    gctx: &GlobalContext,\n    inherit: &dyn Fn() -> CargoResult<&'a InheritableFields>,\n    features: &Features,\n) -> CargoResult<Box<manifest::TomlPackage>> {\n    let package_root = manifest_file.parent().unwrap();\n\n    let edition = original_package\n        .edition\n        .clone()\n        .map(|value| field_inherit_with(value, \"edition\", || inherit()?.edition()))\n        .transpose()?\n        .map(manifest::InheritableField::Value)\n        .or_else(|| {\n            if is_embedded {\n                const DEFAULT_EDITION: crate::core::features::Edition =\n                    crate::core::features::Edition::LATEST_STABLE;\n                let _ = gctx.shell().warn(format_args!(\n                    \"`package.edition` is unspecified, defaulting to the latest edition (currently `{DEFAULT_EDITION}`)\"\n                ));\n                Some(manifest::InheritableField::Value(\n                    DEFAULT_EDITION.to_string(),\n                ))\n            } else {\n                None\n            }\n        });\n    let rust_version = original_package\n        .rust_version\n        .clone()\n        .map(|value| field_inherit_with(value, \"rust-version\", || inherit()?.rust_version()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let name = Some(\n        original_package\n            .name\n            .clone()\n            .or_else(|| {\n                if is_embedded {\n                    let file_stem = manifest_file\n                        .file_stem()\n                        .expect(\"file name enforced previously\")\n                        .to_string_lossy();\n                    let name = embedded::sanitize_name(file_stem.as_ref());\n                    let name =\n                        manifest::PackageName::new(name).expect(\"sanitize made the name valid\");\n                    Some(name)\n                } else {\n                    None\n                }\n            })\n            .ok_or_else(|| anyhow::format_err!(\"missing field `package.name`\"))?,\n    );\n    let version = original_package\n        .version\n        .clone()\n        .map(|value| field_inherit_with(value, \"version\", || inherit()?.version()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let authors = original_package\n        .authors\n        .clone()\n        .map(|value| field_inherit_with(value, \"authors\", || inherit()?.authors()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let build = if is_embedded {\n        Some(TomlPackageBuild::Auto(false))\n    } else {\n        if let Some(TomlPackageBuild::MultipleScript(_)) = original_package.build {\n            features.require(Feature::multiple_build_scripts())?;\n        }\n        targets::normalize_build(original_package.build.as_ref(), package_root)?\n    };\n    let metabuild = original_package.metabuild.clone();\n    let default_target = original_package.default_target.clone();\n    let forced_target = original_package.forced_target.clone();\n    let links = original_package.links.clone();\n    let exclude = original_package\n        .exclude\n        .clone()\n        .map(|value| field_inherit_with(value, \"exclude\", || inherit()?.exclude()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let include = original_package\n        .include\n        .clone()\n        .map(|value| field_inherit_with(value, \"include\", || inherit()?.include()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let publish = original_package\n        .publish\n        .clone()\n        .map(|value| field_inherit_with(value, \"publish\", || inherit()?.publish()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let workspace = original_package.workspace.clone();\n    let im_a_teapot = original_package.im_a_teapot.clone();\n    let autolib = Some(false);\n    let autobins = Some(false);\n    let autoexamples = Some(false);\n    let autotests = Some(false);\n    let autobenches = Some(false);\n    let default_run = original_package.default_run.clone();\n    let description = original_package\n        .description\n        .clone()\n        .map(|value| field_inherit_with(value, \"description\", || inherit()?.description()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let homepage = original_package\n        .homepage\n        .clone()\n        .map(|value| field_inherit_with(value, \"homepage\", || inherit()?.homepage()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let documentation = original_package\n        .documentation\n        .clone()\n        .map(|value| field_inherit_with(value, \"documentation\", || inherit()?.documentation()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let readme = normalize_package_readme(\n        package_root,\n        original_package\n            .readme\n            .clone()\n            .map(|value| field_inherit_with(value, \"readme\", || inherit()?.readme(package_root)))\n            .transpose()?\n            .as_ref(),\n    )\n    .map(|s| manifest::InheritableField::Value(StringOrBool::String(s)))\n    .or(Some(manifest::InheritableField::Value(StringOrBool::Bool(\n        false,\n    ))));\n    let keywords = original_package\n        .keywords\n        .clone()\n        .map(|value| field_inherit_with(value, \"keywords\", || inherit()?.keywords()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let categories = original_package\n        .categories\n        .clone()\n        .map(|value| field_inherit_with(value, \"categories\", || inherit()?.categories()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let license = original_package\n        .license\n        .clone()\n        .map(|value| field_inherit_with(value, \"license\", || inherit()?.license()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let license_file = original_package\n        .license_file\n        .clone()\n        .map(|value| {\n            field_inherit_with(value, \"license-file\", || {\n                inherit()?.license_file(package_root)\n            })\n        })\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let repository = original_package\n        .repository\n        .clone()\n        .map(|value| field_inherit_with(value, \"repository\", || inherit()?.repository()))\n        .transpose()?\n        .map(manifest::InheritableField::Value);\n    let resolver = original_package.resolver.clone();\n    let metadata = original_package.metadata.clone();\n\n    let normalized_package = manifest::TomlPackage {\n        edition,\n        rust_version,\n        name,\n        version,\n        authors,\n        build,\n        metabuild,\n        default_target,\n        forced_target,\n        links,\n        exclude,\n        include,\n        publish,\n        workspace,\n        im_a_teapot,\n        autolib,\n        autobins,\n        autoexamples,\n        autotests,\n        autobenches,\n        default_run,\n        description,\n        homepage,\n        documentation,\n        readme,\n        keywords,\n        categories,\n        license,\n        license_file,\n        repository,\n        resolver,\n        metadata,\n        _invalid_cargo_features: Default::default(),\n    };\n\n    Ok(Box::new(normalized_package))\n}\n\n/// Returns the name of the README file for a [`manifest::TomlPackage`].\nfn normalize_package_readme(\n    package_root: &Path,\n    readme: Option<&manifest::StringOrBool>,\n) -> Option<String> {\n    match &readme {\n        None => default_readme_from_package_root(package_root),\n        Some(value) => match value {\n            manifest::StringOrBool::Bool(false) => None,\n            manifest::StringOrBool::Bool(true) => Some(\"README.md\".to_string()),\n            manifest::StringOrBool::String(v) => Some(v.clone()),\n        },\n    }\n}\n\npub const DEFAULT_README_FILES: [&str; 3] = [\"README.md\", \"README.txt\", \"README\"];\n\n/// Checks if a file with any of the default README file names exists in the package root.\n/// If so, returns a `String` representing that name.\nfn default_readme_from_package_root(package_root: &Path) -> Option<String> {\n    for &readme_filename in DEFAULT_README_FILES.iter() {\n        if package_root.join(readme_filename).is_file() {\n            return Some(readme_filename.to_string());\n        }\n    }\n\n    None\n}\n\n#[tracing::instrument(skip_all)]\nfn normalize_features(\n    original_features: Option<&BTreeMap<manifest::FeatureName, Vec<String>>>,\n) -> CargoResult<Option<BTreeMap<manifest::FeatureName, Vec<String>>>> {\n    let Some(normalized_features) = original_features.cloned() else {\n        return Ok(None);\n    };\n\n    Ok(Some(normalized_features))\n}\n\n#[tracing::instrument(skip_all)]\nfn normalize_dependencies<'a>(\n    gctx: &GlobalContext,\n    edition: Edition,\n    features: &Features,\n    orig_deps: Option<&BTreeMap<manifest::PackageName, manifest::InheritableDependency>>,\n    kind: DepKind,\n    inherit: &dyn Fn() -> CargoResult<&'a InheritableFields>,\n    workspace_root: &dyn Fn() -> CargoResult<&'a Path>,\n    package_root: &Path,\n    warnings: &mut Vec<String>,\n) -> CargoResult<Option<BTreeMap<manifest::PackageName, manifest::InheritableDependency>>> {\n    let Some(dependencies) = orig_deps else {\n        return Ok(None);\n    };\n\n    let mut deps = BTreeMap::new();\n    for (name_in_toml, v) in dependencies.iter() {\n        let mut resolved = dependency_inherit_with(\n            v.clone(),\n            name_in_toml,\n            inherit,\n            package_root,\n            edition,\n            warnings,\n        )?;\n        if let manifest::TomlDependency::Detailed(ref mut d) = resolved {\n            deprecated_underscore(\n                &d.default_features2,\n                &d.default_features,\n                \"default-features\",\n                name_in_toml,\n                \"dependency\",\n                edition,\n                warnings,\n            )?;\n            if d.public.is_some() {\n                let with_public_feature = features.require(Feature::public_dependency()).is_ok();\n                let with_z_public = gctx.cli_unstable().public_dependency;\n                match kind {\n                    DepKind::Normal => {\n                        if !with_public_feature && !with_z_public {\n                            d.public = None;\n                            warnings.push(format!(\n                                \"ignoring `public` on dependency {name_in_toml}, pass `-Zpublic-dependency` to enable support for it\"\n                            ));\n                        }\n                    }\n                    DepKind::Development | DepKind::Build => {\n                        let kind_name = kind.kind_table();\n                        let hint = format!(\n                            \"'public' specifier can only be used on regular dependencies, not {kind_name}\",\n                        );\n                        if with_public_feature || with_z_public {\n                            bail!(hint)\n                        } else {\n                            // If public feature isn't enabled in nightly, we instead warn that.\n                            warnings.push(hint);\n                            d.public = None;\n                        }\n                    }\n                }\n            }\n            normalize_path_dependency(gctx, d, workspace_root, features)\n                .with_context(|| format!(\"resolving path dependency {name_in_toml}\"))?;\n        }\n\n        deps.insert(\n            name_in_toml.clone(),\n            manifest::InheritableDependency::Value(resolved.clone()),\n        );\n    }\n    Ok(Some(deps))\n}\n\nfn normalize_path_dependency<'a>(\n    gctx: &GlobalContext,\n    detailed_dep: &mut TomlDetailedDependency,\n    workspace_root: &dyn Fn() -> CargoResult<&'a Path>,\n    features: &Features,\n) -> CargoResult<()> {\n    if let Some(base) = detailed_dep.base.take() {\n        if let Some(path) = detailed_dep.path.as_mut() {\n            let new_path = lookup_path_base(&base, gctx, workspace_root, features)?.join(&path);\n            *path = new_path.to_str().unwrap().to_string();\n        } else {\n            bail!(\"`base` can only be used with path dependencies\");\n        }\n    }\n    Ok(())\n}\n\nfn load_inheritable_fields(\n    gctx: &GlobalContext,\n    normalized_path: &Path,\n    workspace_config: &WorkspaceConfig,\n) -> CargoResult<InheritableFields> {\n    match workspace_config {\n        WorkspaceConfig::Root(root) => Ok(root.inheritable().clone()),\n        WorkspaceConfig::Member {\n            root: Some(path_to_root),\n        } => {\n            let path = normalized_path\n                .parent()\n                .unwrap()\n                .join(path_to_root)\n                .join(\"Cargo.toml\");\n            let root_path = paths::normalize_path(&path);\n            inheritable_from_path(gctx, root_path)\n        }\n        WorkspaceConfig::Member { root: None } => {\n            match find_workspace_root(&normalized_path, gctx)? {\n                Some(path_to_root) => inheritable_from_path(gctx, path_to_root),\n                None => Err(anyhow!(\"failed to find a workspace root\")),\n            }\n        }\n    }\n}\n\nfn inheritable_from_path(\n    gctx: &GlobalContext,\n    workspace_path: PathBuf,\n) -> CargoResult<InheritableFields> {\n    // Workspace path should have Cargo.toml at the end\n    let workspace_path_root = workspace_path.parent().unwrap();\n\n    // Let the borrow exit scope so that it can be picked up if there is a need to\n    // read a manifest\n    if let Some(ws_root) = gctx.ws_roots().get(workspace_path_root) {\n        return Ok(ws_root.inheritable().clone());\n    };\n\n    let source_id = SourceId::for_manifest_path(&workspace_path)?;\n    let man = read_manifest(&workspace_path, source_id, gctx)?;\n    match man.workspace_config() {\n        WorkspaceConfig::Root(root) => {\n            gctx.ws_roots().insert(workspace_path, root.clone());\n            Ok(root.inheritable().clone())\n        }\n        _ => bail!(\n            \"root of a workspace inferred but wasn't a root: {}\",\n            workspace_path.display()\n        ),\n    }\n}\n\n/// Defines simple getter methods for inheritable fields.\nmacro_rules! package_field_getter {\n    ( $(($key:literal, $field:ident -> $ret:ty),)* ) => (\n        $(\n            #[doc = concat!(\"Gets the field `workspace.package.\", $key, \"`.\")]\n            fn $field(&self) -> CargoResult<$ret> {\n                let Some(val) = self.package.as_ref().and_then(|p| p.$field.as_ref()) else  {\n                    bail!(\"`workspace.package.{}` was not defined\", $key);\n                };\n                Ok(val.clone())\n            }\n        )*\n    )\n}\n\n/// A group of fields that are inheritable by members of the workspace\n#[derive(Clone, Debug, Default)]\npub struct InheritableFields {\n    package: Option<manifest::InheritablePackage>,\n    dependencies: Option<BTreeMap<manifest::PackageName, manifest::TomlDependency>>,\n    lints: Option<manifest::TomlLints>,\n\n    // Bookkeeping to help when resolving values from above\n    _ws_root: PathBuf,\n}\n\nimpl InheritableFields {\n    package_field_getter! {\n        // Please keep this list lexicographically ordered.\n        (\"authors\",       authors       -> Vec<String>),\n        (\"categories\",    categories    -> Vec<String>),\n        (\"description\",   description   -> String),\n        (\"documentation\", documentation -> String),\n        (\"edition\",       edition       -> String),\n        (\"exclude\",       exclude       -> Vec<String>),\n        (\"homepage\",      homepage      -> String),\n        (\"include\",       include       -> Vec<String>),\n        (\"keywords\",      keywords      -> Vec<String>),\n        (\"license\",       license       -> String),\n        (\"publish\",       publish       -> manifest::VecStringOrBool),\n        (\"repository\",    repository    -> String),\n        (\"rust-version\",  rust_version  -> RustVersion),\n        (\"version\",       version       -> semver::Version),\n    }\n\n    /// Gets a workspace dependency with the `name`.\n    fn get_dependency(\n        &self,\n        name: &str,\n        package_root: &Path,\n    ) -> CargoResult<manifest::TomlDependency> {\n        let Some(deps) = &self.dependencies else {\n            bail!(\"`workspace.dependencies` was not defined\");\n        };\n        let Some(dep) = deps.get(name) else {\n            bail!(\"`dependency.{name}` was not found in `workspace.dependencies`\");\n        };\n        let mut dep = dep.clone();\n        if let manifest::TomlDependency::Detailed(detailed) = &mut dep {\n            if detailed.base.is_none() {\n                // If this is a path dependency without a base, then update the path to be relative\n                // to the workspace root instead.\n                if let Some(rel_path) = &detailed.path {\n                    detailed.path = Some(resolve_relative_path(\n                        name,\n                        self.ws_root(),\n                        package_root,\n                        rel_path,\n                    )?);\n                }\n            }\n        }\n        Ok(dep)\n    }\n\n    /// Gets the field `workspace.lints`.\n    pub fn lints(&self) -> CargoResult<manifest::TomlLints> {\n        let Some(val) = &self.lints else {\n            bail!(\"`workspace.lints` was not defined\");\n        };\n        Ok(val.clone())\n    }\n\n    /// Gets the field `workspace.package.license-file`.\n    fn license_file(&self, package_root: &Path) -> CargoResult<String> {\n        let Some(license_file) = self.package.as_ref().and_then(|p| p.license_file.as_ref()) else {\n            bail!(\"`workspace.package.license-file` was not defined\");\n        };\n        resolve_relative_path(\"license-file\", &self._ws_root, package_root, license_file)\n    }\n\n    /// Gets the field `workspace.package.readme`.\n    fn readme(&self, package_root: &Path) -> CargoResult<manifest::StringOrBool> {\n        let Some(readme) = normalize_package_readme(\n            self._ws_root.as_path(),\n            self.package.as_ref().and_then(|p| p.readme.as_ref()),\n        ) else {\n            bail!(\"`workspace.package.readme` was not defined\");\n        };\n        resolve_relative_path(\"readme\", &self._ws_root, package_root, &readme)\n            .map(manifest::StringOrBool::String)\n    }\n\n    fn ws_root(&self) -> &PathBuf {\n        &self._ws_root\n    }\n}\n\nfn field_inherit_with<'a, T>(\n    field: manifest::InheritableField<T>,\n    label: &str,\n    get_ws_inheritable: impl FnOnce() -> CargoResult<T>,\n) -> CargoResult<T> {\n    match field {\n        manifest::InheritableField::Value(value) => Ok(value),\n        manifest::InheritableField::Inherit(_) => get_ws_inheritable().with_context(|| {\n            format!(\n                \"error inheriting `{label}` from workspace root manifest's `workspace.package.{label}`\",\n            )\n        }),\n    }\n}\n\nfn lints_inherit_with(\n    lints: manifest::InheritableLints,\n    get_ws_inheritable: impl FnOnce() -> CargoResult<manifest::TomlLints>,\n) -> CargoResult<manifest::TomlLints> {\n    if lints.workspace {\n        if !lints.lints.is_empty() {\n            anyhow::bail!(\n                \"cannot override `workspace.lints` in `lints`, either remove the overrides or `lints.workspace = true` and manually specify the lints\"\n            );\n        }\n        get_ws_inheritable().with_context(\n            || \"error inheriting `lints` from workspace root manifest's `workspace.lints`\",\n        )\n    } else {\n        Ok(lints.lints)\n    }\n}\n\nfn dependency_inherit_with<'a>(\n    dependency: manifest::InheritableDependency,\n    name: &str,\n    inherit: &dyn Fn() -> CargoResult<&'a InheritableFields>,\n    package_root: &Path,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n) -> CargoResult<manifest::TomlDependency> {\n    match dependency {\n        manifest::InheritableDependency::Value(value) => Ok(value),\n        manifest::InheritableDependency::Inherit(w) => {\n            inner_dependency_inherit_with(w, name, inherit, package_root, edition, warnings).with_context(|| {\n                format!(\n                    \"error inheriting `{name}` from workspace root manifest's `workspace.dependencies.{name}`\",\n                )\n            })\n        }\n    }\n}\n\nfn inner_dependency_inherit_with<'a>(\n    pkg_dep: manifest::TomlInheritedDependency,\n    name: &str,\n    inherit: &dyn Fn() -> CargoResult<&'a InheritableFields>,\n    package_root: &Path,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n) -> CargoResult<manifest::TomlDependency> {\n    let ws_dep = inherit()?.get_dependency(name, package_root)?;\n    let mut merged_dep = match ws_dep {\n        manifest::TomlDependency::Simple(ws_version) => manifest::TomlDetailedDependency {\n            version: Some(ws_version),\n            ..Default::default()\n        },\n        manifest::TomlDependency::Detailed(ws_dep) => ws_dep.clone(),\n    };\n    let manifest::TomlInheritedDependency {\n        workspace: _,\n\n        features,\n        optional,\n        default_features,\n        default_features2,\n        public,\n\n        _unused_keys: _,\n    } = &pkg_dep;\n    let default_features = default_features.or(*default_features2);\n\n    match (default_features, merged_dep.default_features()) {\n        // member: default-features = true and\n        // workspace: default-features = false should turn on\n        // default-features\n        (Some(true), Some(false)) => {\n            merged_dep.default_features = Some(true);\n        }\n        // member: default-features = false and\n        // workspace: default-features = true should ignore member\n        // default-features\n        (Some(false), Some(true)) => {\n            deprecated_ws_default_features(name, Some(true), edition, warnings)?;\n        }\n        // member: default-features = false and\n        // workspace: dep = \"1.0\" should ignore member default-features\n        (Some(false), None) => {\n            deprecated_ws_default_features(name, None, edition, warnings)?;\n        }\n        _ => {}\n    }\n    merged_dep.features = match (merged_dep.features.clone(), features.clone()) {\n        (Some(dep_feat), Some(inherit_feat)) => Some(\n            dep_feat\n                .into_iter()\n                .chain(inherit_feat)\n                .collect::<Vec<String>>(),\n        ),\n        (Some(dep_fet), None) => Some(dep_fet),\n        (None, Some(inherit_feat)) => Some(inherit_feat),\n        (None, None) => None,\n    };\n    merged_dep.optional = *optional;\n    merged_dep.public = *public;\n    Ok(manifest::TomlDependency::Detailed(merged_dep))\n}\n\nfn deprecated_ws_default_features(\n    label: &str,\n    ws_def_feat: Option<bool>,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n) -> CargoResult<()> {\n    let ws_def_feat = match ws_def_feat {\n        Some(true) => \"true\",\n        Some(false) => \"false\",\n        None => \"not specified\",\n    };\n    if Edition::Edition2024 <= edition {\n        anyhow::bail!(\"`default-features = false` cannot override workspace's `default-features`\");\n    } else {\n        warnings.push(format!(\n            \"`default-features` is ignored for {label}, since `default-features` was \\\n                {ws_def_feat} for `workspace.dependencies.{label}`, \\\n                this could become a hard error in the future\"\n        ));\n    }\n    Ok(())\n}\n\n#[tracing::instrument(skip_all)]\npub fn to_real_manifest(\n    contents: Option<String>,\n    document: Option<toml::Spanned<toml::de::DeTable<'static>>>,\n    original_toml: manifest::TomlManifest,\n    normalized_toml: manifest::TomlManifest,\n    features: Features,\n    workspace_config: WorkspaceConfig,\n    source_id: SourceId,\n    manifest_file: &Path,\n    is_embedded: bool,\n    gctx: &GlobalContext,\n    warnings: &mut Vec<String>,\n    _errors: &mut Vec<String>,\n) -> CargoResult<Manifest> {\n    let package_root = manifest_file.parent().unwrap();\n    if !package_root.is_dir() {\n        bail!(\n            \"package root '{}' is not a directory\",\n            package_root.display()\n        );\n    };\n\n    let normalized_package = normalized_toml\n        .package()\n        .expect(\"previously verified to have a `[package]`\");\n    let package_name = normalized_package\n        .normalized_name()\n        .expect(\"previously normalized\");\n    if package_name.contains(':') {\n        features.require(Feature::open_namespaces())?;\n    }\n    let rust_version = normalized_package\n        .normalized_rust_version()\n        .expect(\"previously normalized\")\n        .cloned();\n\n    let edition = if let Some(edition) = normalized_package\n        .normalized_edition()\n        .expect(\"previously normalized\")\n    {\n        let edition: Edition = edition\n            .parse()\n            .context(\"failed to parse the `edition` key\")?;\n        if let Some(pkg_msrv) = &rust_version {\n            if let Some(edition_msrv) = edition.first_version() {\n                let edition_msrv = RustVersion::try_from(edition_msrv).unwrap();\n                if !edition_msrv.is_compatible_with(&pkg_msrv.to_partial()) {\n                    bail!(\n                        \"rust-version {} is incompatible with the version ({}) required by \\\n                            the specified edition ({})\",\n                        pkg_msrv,\n                        edition_msrv,\n                        edition,\n                    )\n                }\n            }\n        }\n        edition\n    } else {\n        let msrv_edition = if let Some(pkg_msrv) = &rust_version {\n            Edition::ALL\n                .iter()\n                .filter(|e| {\n                    e.first_version()\n                        .map(|e| {\n                            let e = RustVersion::try_from(e).unwrap();\n                            e.is_compatible_with(&pkg_msrv.to_partial())\n                        })\n                        .unwrap_or_default()\n                })\n                .max()\n                .copied()\n        } else {\n            None\n        }\n        .unwrap_or_default();\n        let default_edition = Edition::default();\n        let latest_edition = Edition::LATEST_STABLE;\n\n        // We're trying to help the user who might assume they are using a new edition,\n        // so if they can't use a new edition, don't bother to tell them to set it.\n        // This also avoids having to worry about whether `package.edition` is compatible with\n        // their MSRV.\n        if msrv_edition != default_edition || rust_version.is_none() {\n            let tip = if msrv_edition == latest_edition || rust_version.is_none() {\n                format!(\" while the latest is `{latest_edition}`\")\n            } else {\n                format!(\" while {msrv_edition} is compatible with `rust-version`\")\n            };\n            warnings.push(format!(\n                \"`package.edition` is unspecified, defaulting to `{default_edition}`{tip}\"\n            ));\n        }\n        default_edition\n    };\n    if !edition.is_stable() {\n        let version = normalized_package\n            .normalized_version()\n            .expect(\"previously normalized\")\n            .map(|v| format!(\"@{v}\"))\n            .unwrap_or_default();\n        let hint = rust_version\n            .as_ref()\n            .map(|rv| format!(\"help: {package_name}{version} requires rust {rv}\"));\n        features.require_with_hint(Feature::unstable_editions(), hint.as_deref())?;\n    }\n\n    if original_toml.project.is_some() {\n        if Edition::Edition2024 <= edition {\n            anyhow::bail!(\n                \"`[project]` is not supported as of the 2024 Edition, please use `[package]`\"\n            );\n        } else {\n            warnings.push(format!(\"`[project]` is deprecated in favor of `[package]`\"));\n        }\n    }\n\n    if normalized_package.metabuild.is_some() {\n        features.require(Feature::metabuild())?;\n    }\n\n    if is_embedded {\n        let manifest::TomlManifest {\n            cargo_features: _,\n            package: _,\n            project: _,\n            badges: _,\n            features: _,\n            lib,\n            bin,\n            example,\n            test,\n            bench,\n            dependencies: _,\n            dev_dependencies: _,\n            dev_dependencies2: _,\n            build_dependencies,\n            build_dependencies2,\n            target: _,\n            lints: _,\n            hints: _,\n            workspace,\n            profile: _,\n            patch: _,\n            replace: _,\n            _unused_keys: _,\n        } = &original_toml;\n        let mut invalid_fields = vec![\n            (\"`workspace`\", workspace.is_some()),\n            (\"`lib`\", lib.is_some()),\n            (\"`bin`\", bin.is_some()),\n            (\"`example`\", example.is_some()),\n            (\"`test`\", test.is_some()),\n            (\"`bench`\", bench.is_some()),\n            (\"`build-dependencies`\", build_dependencies.is_some()),\n            (\"`build_dependencies`\", build_dependencies2.is_some()),\n        ];\n        if let Some(package) = original_toml.package() {\n            let manifest::TomlPackage {\n                edition: _,\n                rust_version: _,\n                name: _,\n                version: _,\n                authors: _,\n                build,\n                metabuild,\n                default_target: _,\n                forced_target: _,\n                links,\n                exclude: _,\n                include: _,\n                publish: _,\n                workspace,\n                im_a_teapot: _,\n                autolib,\n                autobins,\n                autoexamples,\n                autotests,\n                autobenches,\n                default_run,\n                description: _,\n                homepage: _,\n                documentation: _,\n                readme: _,\n                keywords: _,\n                categories: _,\n                license: _,\n                license_file: _,\n                repository: _,\n                resolver: _,\n                metadata: _,\n                _invalid_cargo_features: _,\n            } = package.as_ref();\n            invalid_fields.extend([\n                (\"`package.workspace`\", workspace.is_some()),\n                (\"`package.build`\", build.is_some()),\n                (\"`package.metabuild`\", metabuild.is_some()),\n                (\"`package.links`\", links.is_some()),\n                (\"`package.autolib`\", autolib.is_some()),\n                (\"`package.autobins`\", autobins.is_some()),\n                (\"`package.autoexamples`\", autoexamples.is_some()),\n                (\"`package.autotests`\", autotests.is_some()),\n                (\"`package.autobenches`\", autobenches.is_some()),\n                (\"`package.default-run`\", default_run.is_some()),\n            ]);\n        }\n        let invalid_fields = invalid_fields\n            .into_iter()\n            .filter_map(|(name, invalid)| invalid.then_some(name))\n            .collect::<Vec<_>>();\n        if !invalid_fields.is_empty() {\n            let fields = invalid_fields.join(\", \");\n            let are = if invalid_fields.len() == 1 {\n                \"is\"\n            } else {\n                \"are\"\n            };\n            anyhow::bail!(\"{fields} {are} not allowed in embedded manifests\")\n        }\n    }\n\n    let resolve_behavior = match (\n        normalized_package.resolver.as_ref(),\n        normalized_toml\n            .workspace\n            .as_ref()\n            .and_then(|ws| ws.resolver.as_ref()),\n    ) {\n        (None, None) => None,\n        (Some(s), None) | (None, Some(s)) => Some(ResolveBehavior::from_manifest(s)?),\n        (Some(_), Some(_)) => {\n            bail!(\"cannot specify `resolver` field in both `[workspace]` and `[package]`\")\n        }\n    };\n\n    // If we have no lib at all, use the inferred lib, if available.\n    // If we have a lib with a path, we're done.\n    // If we have a lib with no path, use the inferred lib or else the package name.\n    let targets = to_targets(\n        &features,\n        &original_toml,\n        &normalized_toml,\n        package_root,\n        edition,\n        &normalized_package.metabuild,\n        warnings,\n    )?;\n\n    if targets.iter().all(|t| t.is_custom_build()) {\n        bail!(\n            \"no targets specified in the manifest\\n\\\n                 either src/lib.rs, src/main.rs, a [lib] section, or \\\n                 [[bin]] section must be present\"\n        )\n    }\n\n    if let Err(conflict_targets) = unique_build_targets(&targets, package_root) {\n        conflict_targets\n            .iter()\n            .for_each(|(target_path, conflicts)| {\n                warnings.push(format!(\n                    \"file `{}` found to be present in multiple \\\n                 build targets:\\n{}\",\n                    target_path.display(),\n                    conflicts\n                        .iter()\n                        .map(|t| format!(\"  * `{}` target `{}`\", t.kind().description(), t.name(),))\n                        .join(\"\\n\")\n                ));\n            })\n    }\n\n    if let Some(links) = &normalized_package.links {\n        if !targets.iter().any(|t| t.is_custom_build()) {\n            bail!(\n                \"package specifies that it links to `{links}` but does not have a custom build script\"\n            )\n        }\n    }\n\n    validate_dependencies(original_toml.dependencies.as_ref(), None, None, warnings)?;\n    validate_dependencies(\n        original_toml.dev_dependencies(),\n        None,\n        Some(DepKind::Development),\n        warnings,\n    )?;\n    validate_dependencies(\n        original_toml.build_dependencies(),\n        None,\n        Some(DepKind::Build),\n        warnings,\n    )?;\n    for (name, platform) in original_toml.target.iter().flatten() {\n        let platform_kind: Platform = name.parse()?;\n        platform_kind.check_cfg_attributes(warnings);\n        platform_kind.check_cfg_keywords(warnings, manifest_file);\n        let platform_kind = Some(platform_kind);\n        validate_dependencies(\n            platform.dependencies.as_ref(),\n            platform_kind.as_ref(),\n            None,\n            warnings,\n        )?;\n        validate_dependencies(\n            platform.build_dependencies(),\n            platform_kind.as_ref(),\n            Some(DepKind::Build),\n            warnings,\n        )?;\n        validate_dependencies(\n            platform.dev_dependencies(),\n            platform_kind.as_ref(),\n            Some(DepKind::Development),\n            warnings,\n        )?;\n    }\n\n    // Collect the dependencies.\n    let mut deps = Vec::new();\n    let mut manifest_ctx = ManifestContext {\n        deps: &mut deps,\n        source_id,\n        gctx,\n        warnings,\n        platform: None,\n        file: manifest_file,\n    };\n    gather_dependencies(\n        &mut manifest_ctx,\n        normalized_toml.dependencies.as_ref(),\n        None,\n    )?;\n    gather_dependencies(\n        &mut manifest_ctx,\n        normalized_toml.dev_dependencies(),\n        Some(DepKind::Development),\n    )?;\n    gather_dependencies(\n        &mut manifest_ctx,\n        normalized_toml.build_dependencies(),\n        Some(DepKind::Build),\n    )?;\n    for (name, platform) in normalized_toml.target.iter().flatten() {\n        manifest_ctx.platform = Some(name.parse()?);\n        gather_dependencies(&mut manifest_ctx, platform.dependencies.as_ref(), None)?;\n        gather_dependencies(\n            &mut manifest_ctx,\n            platform.build_dependencies(),\n            Some(DepKind::Build),\n        )?;\n        gather_dependencies(\n            &mut manifest_ctx,\n            platform.dev_dependencies(),\n            Some(DepKind::Development),\n        )?;\n    }\n    let replace = replace(&normalized_toml, &mut manifest_ctx)?;\n    let patch = patch(&normalized_toml, &mut manifest_ctx)?;\n\n    {\n        let mut names_sources = BTreeMap::new();\n        for dep in &deps {\n            let name = dep.name_in_toml();\n            let prev = names_sources.insert(name, dep.source_id());\n            if prev.is_some() && prev != Some(dep.source_id()) {\n                bail!(\n                    \"Dependency '{}' has different source paths depending on the build \\\n                         target. Each dependency must have a single canonical source path \\\n                         irrespective of build target.\",\n                    name\n                );\n            }\n        }\n    }\n\n    verify_lints(\n        normalized_toml\n            .normalized_lints()\n            .expect(\"previously normalized\"),\n        gctx,\n        warnings,\n    )?;\n    let default = manifest::TomlLints::default();\n    let rustflags = lints_to_rustflags(\n        normalized_toml\n            .normalized_lints()\n            .expect(\"previously normalized\")\n            .unwrap_or(&default),\n    )?;\n\n    let hints = normalized_toml.hints.clone();\n\n    let metadata = ManifestMetadata {\n        description: normalized_package\n            .normalized_description()\n            .expect(\"previously normalized\")\n            .cloned(),\n        homepage: normalized_package\n            .normalized_homepage()\n            .expect(\"previously normalized\")\n            .cloned(),\n        documentation: normalized_package\n            .normalized_documentation()\n            .expect(\"previously normalized\")\n            .cloned(),\n        readme: normalized_package\n            .normalized_readme()\n            .expect(\"previously normalized\")\n            .cloned(),\n        authors: normalized_package\n            .normalized_authors()\n            .expect(\"previously normalized\")\n            .cloned()\n            .unwrap_or_default(),\n        license: normalized_package\n            .normalized_license()\n            .expect(\"previously normalized\")\n            .cloned(),\n        license_file: normalized_package\n            .normalized_license_file()\n            .expect(\"previously normalized\")\n            .cloned(),\n        repository: normalized_package\n            .normalized_repository()\n            .expect(\"previously normalized\")\n            .cloned(),\n        keywords: normalized_package\n            .normalized_keywords()\n            .expect(\"previously normalized\")\n            .cloned()\n            .unwrap_or_default(),\n        categories: normalized_package\n            .normalized_categories()\n            .expect(\"previously normalized\")\n            .cloned()\n            .unwrap_or_default(),\n        badges: normalized_toml.badges.clone().unwrap_or_default(),\n        links: normalized_package.links.clone(),\n        rust_version: rust_version.clone(),\n    };\n\n    if let Some(profiles) = &normalized_toml.profile {\n        let cli_unstable = gctx.cli_unstable();\n        validate_profiles(profiles, cli_unstable, &features, warnings)?;\n    }\n\n    let version = normalized_package\n        .normalized_version()\n        .expect(\"previously normalized\");\n    let publish = match normalized_package\n        .normalized_publish()\n        .expect(\"previously normalized\")\n    {\n        Some(manifest::VecStringOrBool::VecString(vecstring)) => Some(vecstring.clone()),\n        Some(manifest::VecStringOrBool::Bool(false)) => Some(vec![]),\n        Some(manifest::VecStringOrBool::Bool(true)) => None,\n        None => version.is_none().then_some(vec![]),\n    };\n\n    if version.is_none() && publish != Some(vec![]) {\n        bail!(\"`package.publish` requires `package.version` be specified\");\n    }\n\n    let pkgid = PackageId::new(\n        package_name.as_str().into(),\n        version\n            .cloned()\n            .unwrap_or_else(|| semver::Version::new(0, 0, 0)),\n        source_id,\n    );\n    let summary = {\n        let summary = Summary::new(\n            pkgid,\n            deps,\n            &normalized_toml\n                .features\n                .as_ref()\n                .unwrap_or(&Default::default())\n                .iter()\n                .map(|(k, v)| {\n                    (\n                        k.to_string().into(),\n                        v.iter().map(InternedString::from).collect(),\n                    )\n                })\n                .collect(),\n            normalized_package.links.as_deref(),\n            rust_version.clone(),\n        );\n        // edition2024 stops exposing implicit features, which will strip weak optional dependencies from `dependencies`,\n        // need to check whether `dep_name` is stripped as unused dependency\n        if let Err(ref err) = summary {\n            if let Some(missing_dep) = err.downcast_ref::<MissingDependencyError>() {\n                missing_dep_diagnostic(\n                    missing_dep,\n                    &original_toml,\n                    document.as_ref(),\n                    contents.as_deref(),\n                    manifest_file,\n                    gctx,\n                )?;\n            }\n        }\n        summary?\n    };\n\n    if summary.features().contains_key(\"default-features\") {\n        warnings.push(\n            \"`[features]` defines a feature named `default-features`\nnote: only a feature named `default` will be enabled by default\"\n                .to_string(),\n        )\n    }\n\n    if let Some(run) = &normalized_package.default_run {\n        if !targets\n            .iter()\n            .filter(|t| t.is_bin())\n            .any(|t| t.name() == run)\n        {\n            let suggestion = util::closest_msg(\n                run,\n                targets.iter().filter(|t| t.is_bin()),\n                |t| t.name(),\n                \"target\",\n            );\n            bail!(\"default-run target `{}` not found{}\", run, suggestion);\n        }\n    }\n\n    let default_kind = normalized_package\n        .default_target\n        .as_ref()\n        .map(|t| CompileTarget::new(&*t, gctx.cli_unstable().json_target_spec))\n        .transpose()?\n        .map(CompileKind::Target);\n    let forced_kind = normalized_package\n        .forced_target\n        .as_ref()\n        .map(|t| CompileTarget::new(&*t, gctx.cli_unstable().json_target_spec))\n        .transpose()?\n        .map(CompileKind::Target);\n    let include = normalized_package\n        .normalized_include()\n        .expect(\"previously normalized\")\n        .cloned()\n        .unwrap_or_default();\n    let exclude = normalized_package\n        .normalized_exclude()\n        .expect(\"previously normalized\")\n        .cloned()\n        .unwrap_or_default();\n    let links = normalized_package.links.clone();\n    let custom_metadata = normalized_package.metadata.clone();\n    let im_a_teapot = normalized_package.im_a_teapot;\n    let default_run = normalized_package.default_run.clone();\n    let metabuild = normalized_package.metabuild.clone().map(|sov| sov.0);\n    let manifest = Manifest::new(\n        contents.map(Rc::new),\n        document.map(Rc::new),\n        Some(Rc::new(original_toml)),\n        Rc::new(normalized_toml),\n        summary,\n        default_kind,\n        forced_kind,\n        targets,\n        exclude,\n        include,\n        links,\n        metadata,\n        custom_metadata,\n        publish,\n        replace,\n        patch,\n        workspace_config,\n        features,\n        edition,\n        rust_version,\n        im_a_teapot,\n        default_run,\n        metabuild,\n        resolve_behavior,\n        rustflags,\n        hints,\n        is_embedded,\n    );\n    if manifest\n        .normalized_toml()\n        .package()\n        .unwrap()\n        .license_file\n        .is_some()\n        && manifest\n            .normalized_toml()\n            .package()\n            .unwrap()\n            .license\n            .is_some()\n    {\n        warnings.push(\n            \"only one of `license` or `license-file` is necessary\\n\\\n                 `license` should be used if the package license can be expressed \\\n                 with a standard SPDX expression.\\n\\\n                 `license-file` should be used if the package uses a non-standard license.\\n\\\n                 See https://doc.rust-lang.org/cargo/reference/manifest.html#the-license-and-license-file-fields \\\n                 for more information.\"\n                .to_owned(),\n        );\n    }\n    if let Some(original_toml) = manifest.original_toml() {\n        warn_on_unused(&original_toml._unused_keys, warnings);\n    }\n\n    manifest.feature_gate()?;\n\n    Ok(manifest)\n}\n\nfn missing_dep_diagnostic(\n    missing_dep: &MissingDependencyError,\n    orig_toml: &TomlManifest,\n    document: Option<&toml::Spanned<toml::de::DeTable<'static>>>,\n    contents: Option<&str>,\n    manifest_file: &Path,\n    gctx: &GlobalContext,\n) -> CargoResult<()> {\n    let dep_name = missing_dep.dep_name;\n    let manifest_path = rel_cwd_manifest_path(manifest_file, gctx);\n\n    let title = format!(\n        \"feature `{}` includes `{}`, but `{}` is not a dependency\",\n        missing_dep.feature, missing_dep.feature_value, &dep_name\n    );\n    let help = format!(\"enable the dependency with `dep:{dep_name}`\");\n    let info_label = format!(\n        \"`{}` is an unused optional dependency since no feature enables it\",\n        &dep_name\n    );\n    let group = Group::with_title(Level::ERROR.primary_title(&title));\n    let group =\n        if let Some(contents) = contents\n            && let Some(document) = document\n        {\n            let feature_span =\n                get_key_value_span(&document, &[\"features\", missing_dep.feature.as_str()]).unwrap();\n\n            let snippet = Snippet::source(contents)\n                .path(manifest_path)\n                .annotation(AnnotationKind::Primary.span(feature_span.value));\n\n            if missing_dep.weak_optional {\n                let mut orig_deps = vec![\n                    (\n                        orig_toml.dependencies.as_ref(),\n                        vec![DepKind::Normal.kind_table()],\n                    ),\n                    (\n                        orig_toml.build_dependencies.as_ref(),\n                        vec![DepKind::Build.kind_table()],\n                    ),\n                ];\n                for (name, platform) in orig_toml.target.iter().flatten() {\n                    orig_deps.push((\n                        platform.dependencies.as_ref(),\n                        vec![\"target\", name, DepKind::Normal.kind_table()],\n                    ));\n                    orig_deps.push((\n                        platform.build_dependencies.as_ref(),\n                        vec![\"target\", name, DepKind::Normal.kind_table()],\n                    ));\n                }\n\n                if let Some((_, toml_path)) = orig_deps.iter().find(|(deps, _)| {\n                    if let Some(deps) = deps {\n                        deps.keys().any(|p| *p.as_str() == *dep_name)\n                    } else {\n                        false\n                    }\n                }) {\n                    let toml_path = toml_path\n                        .iter()\n                        .map(|s| *s)\n                        .chain(std::iter::once(dep_name.as_str()))\n                        .collect::<Vec<_>>();\n                    let dep_span = get_key_value_span(&document, &toml_path).unwrap();\n\n                    group\n                        .element(snippet.annotation(\n                            AnnotationKind::Context.span(dep_span.key).label(info_label),\n                        ))\n                        .element(Level::HELP.message(help))\n                } else {\n                    group.element(snippet)\n                }\n            } else {\n                group.element(snippet)\n            }\n        } else {\n            group\n        };\n\n    if let Err(err) = gctx.shell().print_report(&[group], true) {\n        return Err(err.into());\n    }\n    Err(AlreadyPrintedError::new(anyhow!(\"\").into()).into())\n}\n\nfn to_virtual_manifest(\n    contents: Option<String>,\n    document: Option<toml::Spanned<toml::de::DeTable<'static>>>,\n    original_toml: manifest::TomlManifest,\n    normalized_toml: manifest::TomlManifest,\n    features: Features,\n    workspace_config: WorkspaceConfig,\n    source_id: SourceId,\n    manifest_file: &Path,\n    gctx: &GlobalContext,\n    warnings: &mut Vec<String>,\n    _errors: &mut Vec<String>,\n) -> CargoResult<VirtualManifest> {\n    let mut deps = Vec::new();\n    let (replace, patch) = {\n        let mut manifest_ctx = ManifestContext {\n            deps: &mut deps,\n            source_id,\n            gctx,\n            warnings,\n            platform: None,\n            file: manifest_file,\n        };\n        (\n            replace(&normalized_toml, &mut manifest_ctx)?,\n            patch(&normalized_toml, &mut manifest_ctx)?,\n        )\n    };\n    if let Some(profiles) = &normalized_toml.profile {\n        validate_profiles(profiles, gctx.cli_unstable(), &features, warnings)?;\n    }\n    let resolve_behavior = normalized_toml\n        .workspace\n        .as_ref()\n        .and_then(|ws| ws.resolver.as_deref())\n        .map(|r| ResolveBehavior::from_manifest(r))\n        .transpose()?;\n    if let WorkspaceConfig::Member { .. } = &workspace_config {\n        bail!(\"virtual manifests must be configured with [workspace]\");\n    }\n    let manifest = VirtualManifest::new(\n        contents.map(Rc::new),\n        document.map(Rc::new),\n        Some(Rc::new(original_toml)),\n        Rc::new(normalized_toml),\n        replace,\n        patch,\n        workspace_config,\n        features,\n        resolve_behavior,\n    );\n\n    if let Some(original_toml) = manifest.original_toml() {\n        warn_on_unused(&original_toml._unused_keys, warnings);\n    }\n\n    Ok(manifest)\n}\n\n#[tracing::instrument(skip_all)]\nfn validate_dependencies(\n    original_deps: Option<&BTreeMap<manifest::PackageName, manifest::InheritableDependency>>,\n    platform: Option<&Platform>,\n    kind: Option<DepKind>,\n    warnings: &mut Vec<String>,\n) -> CargoResult<()> {\n    let Some(dependencies) = original_deps else {\n        return Ok(());\n    };\n\n    for (name_in_toml, v) in dependencies.iter() {\n        let kind_name = match kind {\n            Some(k) => k.kind_table(),\n            None => \"dependencies\",\n        };\n        let table_in_toml = if let Some(platform) = platform {\n            format!(\"target.{platform}.{kind_name}\")\n        } else {\n            kind_name.to_string()\n        };\n        unused_dep_keys(name_in_toml, &table_in_toml, v.unused_keys(), warnings);\n    }\n    Ok(())\n}\n\nstruct ManifestContext<'a, 'b> {\n    deps: &'a mut Vec<Dependency>,\n    source_id: SourceId,\n    gctx: &'b GlobalContext,\n    warnings: &'a mut Vec<String>,\n    platform: Option<Platform>,\n    file: &'a Path,\n}\n\n#[tracing::instrument(skip_all)]\nfn gather_dependencies(\n    manifest_ctx: &mut ManifestContext<'_, '_>,\n    normalized_deps: Option<&BTreeMap<manifest::PackageName, manifest::InheritableDependency>>,\n    kind: Option<DepKind>,\n) -> CargoResult<()> {\n    let Some(dependencies) = normalized_deps else {\n        return Ok(());\n    };\n\n    for (n, v) in dependencies.iter() {\n        let resolved = v.normalized().expect(\"previously normalized\");\n        let dep = dep_to_dependency(&resolved, n, manifest_ctx, kind)?;\n        manifest_ctx.deps.push(dep);\n    }\n    Ok(())\n}\n\nfn replace(\n    me: &manifest::TomlManifest,\n    manifest_ctx: &mut ManifestContext<'_, '_>,\n) -> CargoResult<Vec<(PackageIdSpec, Dependency)>> {\n    if me.patch.is_some() && me.replace.is_some() {\n        bail!(\"cannot specify both [replace] and [patch]\");\n    }\n    let mut replace = Vec::new();\n    for (spec, replacement) in me.replace.iter().flatten() {\n        let mut spec = PackageIdSpec::parse(spec).with_context(|| {\n            format!(\n                \"replacements must specify a valid semver \\\n                     version to replace, but `{}` does not\",\n                spec\n            )\n        })?;\n        if spec.url().is_none() {\n            spec.set_url(CRATES_IO_INDEX.parse().unwrap());\n        }\n\n        if replacement.is_version_specified() {\n            bail!(\n                \"replacements cannot specify a version \\\n                     requirement, but found one for `{}`\",\n                spec\n            );\n        }\n\n        let mut dep = dep_to_dependency(replacement, spec.name(), manifest_ctx, None)?;\n        let version = spec.version().ok_or_else(|| {\n            anyhow!(\n                \"replacements must specify a version \\\n                     to replace, but `{}` does not\",\n                spec\n            )\n        })?;\n        unused_dep_keys(\n            dep.name_in_toml().as_str(),\n            \"replace\",\n            replacement.unused_keys(),\n            &mut manifest_ctx.warnings,\n        );\n        dep.set_version_req(OptVersionReq::exact(&version));\n        replace.push((spec, dep));\n    }\n    Ok(replace)\n}\n\nfn patch(\n    me: &TomlManifest,\n    manifest_ctx: &mut ManifestContext<'_, '_>,\n) -> CargoResult<HashMap<Url, Vec<Patch>>> {\n    let mut patch = HashMap::new();\n    for (toml_url, deps) in me.patch.iter().flatten() {\n        let url = match &toml_url[..] {\n            CRATES_IO_REGISTRY => CRATES_IO_INDEX.parse().unwrap(),\n            _ => manifest_ctx\n                .gctx\n                .get_registry_index(toml_url)\n                .or_else(|_| toml_url.into_url())\n                .with_context(|| {\n                    format!(\n                        \"[patch] entry `{}` should be a URL or registry name{}\",\n                        toml_url,\n                        if toml_url == \"crates\" {\n                            \"\\nFor crates.io, use [patch.crates-io] (with a dash)\"\n                        } else {\n                            \"\"\n                        }\n                    )\n                })?,\n        };\n        patch.insert(\n            url,\n            deps.iter()\n                .map(|(name, dep)| {\n                    unused_dep_keys(\n                        name,\n                        &format!(\"patch.{toml_url}\",),\n                        dep.unused_keys(),\n                        &mut manifest_ctx.warnings,\n                    );\n\n                    let dep = dep_to_dependency(dep, name, manifest_ctx, None)?;\n                    let loc = PatchLocation::Manifest(manifest_ctx.file.to_path_buf());\n                    Ok(Patch { dep, loc })\n                })\n                .collect::<CargoResult<Vec<_>>>()?,\n        );\n    }\n    Ok(patch)\n}\n\n/// Transforms a `patch` entry from Cargo config to a [`Dependency`].\npub(crate) fn config_patch_to_dependency<P: ResolveToPath + Clone>(\n    config_patch: &manifest::TomlDependency<P>,\n    name: &str,\n    source_id: SourceId,\n    gctx: &GlobalContext,\n    warnings: &mut Vec<String>,\n) -> CargoResult<Dependency> {\n    let manifest_ctx = &mut ManifestContext {\n        deps: &mut Vec::new(),\n        source_id,\n        gctx,\n        warnings,\n        platform: None,\n        // config path doesn't have manifest file path, and doesn't use it.\n        file: Path::new(\"unused\"),\n    };\n    dep_to_dependency(config_patch, name, manifest_ctx, None)\n}\n\nfn dep_to_dependency<P: ResolveToPath + Clone>(\n    orig: &manifest::TomlDependency<P>,\n    name_in_toml: &str,\n    manifest_ctx: &mut ManifestContext<'_, '_>,\n    kind: Option<DepKind>,\n) -> CargoResult<Dependency> {\n    let orig = match orig {\n        manifest::TomlDependency::Simple(version) => &manifest::TomlDetailedDependency::<P> {\n            version: Some(version.clone()),\n            ..Default::default()\n        },\n        manifest::TomlDependency::Detailed(details) => details,\n    };\n\n    if orig.version.is_none() && orig.path.is_none() && orig.git.is_none() {\n        anyhow::bail!(\n            \"dependency ({name_in_toml}) specified without \\\n                 providing a local path, Git repository, version, or \\\n                 workspace dependency to use\"\n        );\n    }\n\n    if let Some(version) = &orig.version {\n        if version.contains('+') {\n            manifest_ctx.warnings.push(format!(\n                \"version requirement `{}` for dependency `{}` \\\n                     includes semver metadata which will be ignored, removing the \\\n                     metadata is recommended to avoid confusion\",\n                version, name_in_toml\n            ));\n        }\n    }\n\n    if orig.git.is_none() {\n        let git_only_keys = [\n            (&orig.branch, \"branch\"),\n            (&orig.tag, \"tag\"),\n            (&orig.rev, \"rev\"),\n        ];\n\n        for &(key, key_name) in &git_only_keys {\n            if key.is_some() {\n                bail!(\n                    \"key `{}` is ignored for dependency ({}).\",\n                    key_name,\n                    name_in_toml\n                );\n            }\n        }\n    }\n\n    // Early detection of potentially misused feature syntax\n    // instead of generating a \"feature not found\" error.\n    if let Some(features) = &orig.features {\n        for feature in features {\n            if feature.contains('/') {\n                bail!(\n                    \"feature `{}` in dependency `{}` is not allowed to contain slashes\\n\\\n                         If you want to enable features of a transitive dependency, \\\n                         the direct dependency needs to re-export those features from \\\n                         the `[features]` table.\",\n                    feature,\n                    name_in_toml\n                );\n            }\n            if feature.starts_with(\"dep:\") {\n                bail!(\n                    \"feature `{}` in dependency `{}` is not allowed to use explicit \\\n                        `dep:` syntax\\n\\\n                         If you want to enable an optional dependency, specify the name \\\n                         of the optional dependency without the `dep:` prefix, or specify \\\n                         a feature from the dependency's `[features]` table that enables \\\n                         the optional dependency.\",\n                    feature,\n                    name_in_toml\n                );\n            }\n        }\n    }\n\n    let new_source_id = to_dependency_source_id(orig, name_in_toml, manifest_ctx)?;\n\n    let (pkg_name, explicit_name_in_toml) = match orig.package {\n        Some(ref s) => (&s[..], Some(name_in_toml)),\n        None => (name_in_toml, None),\n    };\n\n    let version = orig.version.as_deref();\n    let mut dep = Dependency::parse(pkg_name, version, new_source_id)?;\n    dep.set_features(orig.features.iter().flatten())\n        .set_default_features(orig.default_features().unwrap_or(true))\n        .set_optional(orig.optional.unwrap_or(false))\n        .set_platform(manifest_ctx.platform.clone());\n    if let Some(registry) = &orig.registry {\n        let registry_id = SourceId::alt_registry(manifest_ctx.gctx, registry)?;\n        dep.set_registry_id(registry_id);\n    }\n    if let Some(registry_index) = &orig.registry_index {\n        let url = registry_index.into_url()?;\n        let registry_id = SourceId::for_registry(&url)?;\n        dep.set_registry_id(registry_id);\n    }\n\n    if let Some(kind) = kind {\n        dep.set_kind(kind);\n    }\n    if let Some(name_in_toml) = explicit_name_in_toml {\n        dep.set_explicit_name_in_toml(name_in_toml);\n    }\n\n    if let Some(p) = orig.public {\n        dep.set_public(p);\n    }\n\n    if let (Some(artifact), is_lib, target) = (\n        orig.artifact.as_ref(),\n        orig.lib.unwrap_or(false),\n        orig.target.as_deref(),\n    ) {\n        if manifest_ctx.gctx.cli_unstable().bindeps {\n            let artifact = Artifact::parse(\n                &artifact.0,\n                is_lib,\n                target,\n                manifest_ctx.gctx.cli_unstable().json_target_spec,\n            )?;\n            if dep.kind() != DepKind::Build\n                && artifact.target() == Some(ArtifactTarget::BuildDependencyAssumeTarget)\n            {\n                bail!(\n                    r#\"`target = \"target\"` in normal- or dev-dependencies has no effect ({})\"#,\n                    name_in_toml\n                );\n            }\n            dep.set_artifact(artifact)\n        } else {\n            bail!(\"`artifact = …` requires `-Z bindeps` ({})\", name_in_toml);\n        }\n    } else if orig.lib.is_some() || orig.target.is_some() {\n        for (is_set, specifier) in [\n            (orig.lib.is_some(), \"lib\"),\n            (orig.target.is_some(), \"target\"),\n        ] {\n            if !is_set {\n                continue;\n            }\n            bail!(\n                \"'{}' specifier cannot be used without an 'artifact = …' value ({})\",\n                specifier,\n                name_in_toml\n            )\n        }\n    }\n    Ok(dep)\n}\n\nfn to_dependency_source_id<P: ResolveToPath + Clone>(\n    orig: &manifest::TomlDetailedDependency<P>,\n    name_in_toml: &str,\n    manifest_ctx: &mut ManifestContext<'_, '_>,\n) -> CargoResult<SourceId> {\n    match (\n        orig.git.as_ref(),\n        orig.path.as_ref(),\n        orig.registry.as_deref(),\n        orig.registry_index.as_ref(),\n    ) {\n        (Some(_git), _, Some(_registry), _) | (Some(_git), _, _, Some(_registry)) => bail!(\n            \"dependency ({name_in_toml}) specification is ambiguous. \\\n                 Only one of `git` or `registry` is allowed.\",\n        ),\n        (_, _, Some(_registry), Some(_registry_index)) => bail!(\n            \"dependency ({name_in_toml}) specification is ambiguous. \\\n                 Only one of `registry` or `registry-index` is allowed.\",\n        ),\n        (Some(_git), Some(_path), None, None) => {\n            bail!(\n                \"dependency ({name_in_toml}) specification is ambiguous. \\\n                     Only one of `git` or `path` is allowed.\",\n            );\n        }\n        (Some(git), None, None, None) => {\n            let n_details = [&orig.branch, &orig.tag, &orig.rev]\n                .iter()\n                .filter(|d| d.is_some())\n                .count();\n\n            if n_details > 1 {\n                bail!(\n                    \"dependency ({name_in_toml}) specification is ambiguous. \\\n                         Only one of `branch`, `tag` or `rev` is allowed.\",\n                );\n            }\n\n            let reference = orig\n                .branch\n                .clone()\n                .map(GitReference::Branch)\n                .or_else(|| orig.tag.clone().map(GitReference::Tag))\n                .or_else(|| orig.rev.clone().map(GitReference::Rev))\n                .unwrap_or(GitReference::DefaultBranch);\n            let loc = git.into_url()?;\n\n            if let Some(fragment) = loc.fragment() {\n                let msg = format!(\n                    \"URL fragment `#{fragment}` in git URL is ignored for dependency ({name_in_toml}). \\\n                        If you were trying to specify a specific git revision, \\\n                        use `rev = \\\"{fragment}\\\"` in the dependency declaration.\",\n                );\n                manifest_ctx.warnings.push(msg);\n            }\n\n            SourceId::for_git(&loc, reference)\n        }\n        (None, Some(path), _, _) => {\n            let path = path.resolve(manifest_ctx.gctx);\n            // If the source ID for the package we're parsing is a path\n            // source, then we normalize the path here to get rid of\n            // components like `..`.\n            //\n            // The purpose of this is to get a canonical ID for the package\n            // that we're depending on to ensure that builds of this package\n            // always end up hashing to the same value no matter where it's\n            // built from.\n            if manifest_ctx.source_id.is_path() {\n                let path = manifest_ctx.file.parent().unwrap().join(path);\n                let path = paths::normalize_path(&path);\n                SourceId::for_path(&path)\n            } else {\n                Ok(manifest_ctx.source_id)\n            }\n        }\n        (None, None, Some(registry), None) => SourceId::alt_registry(manifest_ctx.gctx, registry),\n        (None, None, None, Some(registry_index)) => {\n            let url = registry_index.into_url()?;\n            SourceId::for_registry(&url)\n        }\n        (None, None, None, None) => SourceId::crates_io(manifest_ctx.gctx),\n    }\n}\n\npub(crate) fn lookup_path_base<'a>(\n    base: &PathBaseName,\n    gctx: &GlobalContext,\n    workspace_root: &dyn Fn() -> CargoResult<&'a Path>,\n    features: &Features,\n) -> CargoResult<PathBuf> {\n    features.require(Feature::path_bases())?;\n\n    // HACK: The `base` string is user controlled, but building the path is safe from injection\n    // attacks since the `PathBaseName` type restricts the characters that can be used to exclude `.`\n    let base_key = format!(\"path-bases.{base}\");\n\n    // Look up the relevant base in the Config and use that as the root.\n    if let Some(path_bases) = gctx.get::<Option<ConfigRelativePath>>(&base_key)? {\n        Ok(path_bases.resolve_path(gctx))\n    } else {\n        // Otherwise, check the built-in bases.\n        match base.as_str() {\n            \"workspace\" => Ok(workspace_root()?.to_path_buf()),\n            _ => bail!(\n                \"path base `{base}` is undefined. \\\n            You must add an entry for `{base}` in the Cargo configuration [path-bases] table.\"\n            ),\n        }\n    }\n}\n\npub trait ResolveToPath {\n    fn resolve(&self, gctx: &GlobalContext) -> PathBuf;\n}\n\nimpl ResolveToPath for String {\n    fn resolve(&self, _: &GlobalContext) -> PathBuf {\n        self.into()\n    }\n}\n\nimpl ResolveToPath for ConfigRelativePath {\n    fn resolve(&self, gctx: &GlobalContext) -> PathBuf {\n        self.resolve_path(gctx)\n    }\n}\n\n/// Checks a list of build targets, and ensures the target names are unique within a vector.\n/// If not, the name of the offending build target is returned.\n#[tracing::instrument(skip_all)]\nfn unique_build_targets(\n    targets: &[Target],\n    package_root: &Path,\n) -> Result<(), HashMap<PathBuf, Vec<Target>>> {\n    let mut source_targets = HashMap::<_, Vec<_>>::new();\n    for target in targets {\n        if let TargetSourcePath::Path(path) = target.src_path() {\n            let full = package_root.join(path);\n            source_targets.entry(full).or_default().push(target.clone());\n        }\n    }\n\n    let conflict_targets = source_targets\n        .into_iter()\n        .filter(|(_, targets)| targets.len() > 1)\n        .collect::<HashMap<_, _>>();\n\n    if !conflict_targets.is_empty() {\n        return Err(conflict_targets);\n    }\n\n    Ok(())\n}\n\n/// Checks syntax validity and unstable feature gate for each profile.\n///\n/// It's a bit unfortunate both `-Z` flags and `cargo-features` are required,\n/// because profiles can now be set in either `Cargo.toml` or `config.toml`.\nfn validate_profiles(\n    profiles: &manifest::TomlProfiles,\n    cli_unstable: &CliUnstable,\n    features: &Features,\n    warnings: &mut Vec<String>,\n) -> CargoResult<()> {\n    for (name, profile) in &profiles.0 {\n        validate_profile(profile, name, cli_unstable, features, warnings)?;\n    }\n    Ok(())\n}\n\n/// Checks syntax validity and unstable feature gate for a given profile.\npub fn validate_profile(\n    root: &manifest::TomlProfile,\n    name: &str,\n    cli_unstable: &CliUnstable,\n    features: &Features,\n    warnings: &mut Vec<String>,\n) -> CargoResult<()> {\n    validate_profile_layer(root, cli_unstable, features)?;\n    if let Some(ref profile) = root.build_override {\n        validate_profile_override(profile, \"build-override\")?;\n        validate_profile_layer(profile, cli_unstable, features)?;\n    }\n    if let Some(ref packages) = root.package {\n        for profile in packages.values() {\n            validate_profile_override(profile, \"package\")?;\n            validate_profile_layer(profile, cli_unstable, features)?;\n        }\n    }\n\n    if let Some(dir_name) = &root.dir_name {\n        // This is disabled for now, as we would like to stabilize named\n        // profiles without this, and then decide in the future if it is\n        // needed. This helps simplify the UI a little.\n        bail!(\n            \"dir-name=\\\"{}\\\" in profile `{}` is not currently allowed, \\\n                 directory names are tied to the profile name for custom profiles\",\n            dir_name,\n            name\n        );\n    }\n\n    // `inherits` validation\n    if matches!(root.inherits.as_deref(), Some(\"debug\")) {\n        bail!(\n            \"profile.{}.inherits=\\\"debug\\\" should be profile.{}.inherits=\\\"dev\\\"\",\n            name,\n            name\n        );\n    }\n\n    match name {\n        \"doc\" => {\n            warnings.push(\"profile `doc` is deprecated and has no effect\".to_string());\n        }\n        \"test\" | \"bench\" => {\n            if root.panic.is_some() {\n                warnings.push(format!(\"`panic` setting is ignored for `{}` profile\", name))\n            }\n        }\n        _ => {}\n    }\n\n    if let Some(panic) = &root.panic {\n        if panic != \"unwind\" && panic != \"abort\" && panic != \"immediate-abort\" {\n            bail!(\n                \"`panic` setting of `{}` is not a valid setting, \\\n                     must be `unwind`, `abort`, or `immediate-abort`.\",\n                panic\n            );\n        }\n    }\n\n    if let Some(manifest::StringOrBool::String(arg)) = &root.lto {\n        if arg == \"true\" || arg == \"false\" {\n            bail!(\n                \"`lto` setting of string `\\\"{arg}\\\"` for `{name}` profile is not \\\n                     a valid setting, must be a boolean (`true`/`false`) or a string \\\n                    (`\\\"thin\\\"`/`\\\"fat\\\"`/`\\\"off\\\"`) or omitted.\",\n            );\n        }\n    }\n\n    Ok(())\n}\n\n/// Validates a profile.\n///\n/// This is a shallow check, which is reused for the profile itself and any overrides.\nfn validate_profile_layer(\n    profile: &manifest::TomlProfile,\n    cli_unstable: &CliUnstable,\n    features: &Features,\n) -> CargoResult<()> {\n    if profile.codegen_backend.is_some() {\n        match (\n            features.require(Feature::codegen_backend()),\n            cli_unstable.codegen_backend,\n        ) {\n            (Err(e), false) => return Err(e),\n            _ => {}\n        }\n    }\n    if profile.rustflags.is_some() {\n        match (\n            features.require(Feature::profile_rustflags()),\n            cli_unstable.profile_rustflags,\n        ) {\n            (Err(e), false) => return Err(e),\n            _ => {}\n        }\n    }\n    if profile.trim_paths.is_some() {\n        match (\n            features.require(Feature::trim_paths()),\n            cli_unstable.trim_paths,\n        ) {\n            (Err(e), false) => return Err(e),\n            _ => {}\n        }\n    }\n    if profile.panic.as_deref() == Some(\"immediate-abort\") {\n        match (\n            features.require(Feature::panic_immediate_abort()),\n            cli_unstable.panic_immediate_abort,\n        ) {\n            (Err(e), false) => return Err(e),\n            _ => {}\n        }\n    }\n    Ok(())\n}\n\n/// Validation that is specific to an override.\nfn validate_profile_override(profile: &manifest::TomlProfile, which: &str) -> CargoResult<()> {\n    if profile.package.is_some() {\n        bail!(\"package-specific profiles cannot be nested\");\n    }\n    if profile.build_override.is_some() {\n        bail!(\"build-override profiles cannot be nested\");\n    }\n    if profile.panic.is_some() {\n        bail!(\"`panic` may not be specified in a `{}` profile\", which)\n    }\n    if profile.lto.is_some() {\n        bail!(\"`lto` may not be specified in a `{}` profile\", which)\n    }\n    if profile.rpath.is_some() {\n        bail!(\"`rpath` may not be specified in a `{}` profile\", which)\n    }\n    Ok(())\n}\n\nfn verify_lints(\n    lints: Option<&manifest::TomlLints>,\n    gctx: &GlobalContext,\n    warnings: &mut Vec<String>,\n) -> CargoResult<()> {\n    let Some(lints) = lints else {\n        return Ok(());\n    };\n\n    for (tool, lints) in lints {\n        let supported = [\"cargo\", \"clippy\", \"rust\", \"rustdoc\"];\n        if !supported.contains(&tool.as_str()) {\n            let message = format!(\n                \"unrecognized lint tool `lints.{tool}`, specifying unrecognized tools may break in the future.\nsupported tools: {}\",\n                supported.join(\", \"),\n            );\n            warnings.push(message);\n            continue;\n        }\n        if tool == \"cargo\" && !gctx.cli_unstable().cargo_lints {\n            warn_for_cargo_lint_feature(gctx, warnings);\n        }\n        for (name, config) in lints {\n            if let Some((prefix, suffix)) = name.split_once(\"::\") {\n                if tool == prefix {\n                    anyhow::bail!(\n                        \"`lints.{tool}.{name}` is not valid lint name; try `lints.{prefix}.{suffix}`\"\n                    )\n                } else if tool == \"rust\" && supported.contains(&prefix) {\n                    anyhow::bail!(\n                        \"`lints.{tool}.{name}` is not valid lint name; try `lints.{prefix}.{suffix}`\"\n                    )\n                } else {\n                    anyhow::bail!(\"`lints.{tool}.{name}` is not a valid lint name\")\n                }\n            } else if let Some(config) = config.config() {\n                for config_name in config.keys() {\n                    // manually report unused manifest key warning since we collect all the \"extra\"\n                    // keys and values inside the config table\n                    //\n                    // except for `rust.unexpected_cfgs.check-cfg` which is used by rustc/rustdoc\n                    if !(tool == \"rust\" && name == \"unexpected_cfgs\" && config_name == \"check-cfg\")\n                    {\n                        let message =\n                            format!(\"unused manifest key: `lints.{tool}.{name}.{config_name}`\");\n                        warnings.push(message);\n                    }\n                }\n            }\n        }\n    }\n\n    Ok(())\n}\n\nfn warn_for_cargo_lint_feature(gctx: &GlobalContext, warnings: &mut Vec<String>) {\n    use std::fmt::Write as _;\n\n    let key_name = \"lints.cargo\";\n    let feature_name = \"cargo-lints\";\n\n    let mut message = String::new();\n\n    let _ = write!(\n        message,\n        \"unused manifest key `{key_name}` (may be supported in a future version)\"\n    );\n    if gctx.nightly_features_allowed {\n        let _ = write!(\n            message,\n            \"\n\nconsider passing `-Z{feature_name}` to enable this feature.\"\n        );\n    } else {\n        let _ = write!(\n            message,\n            \"\n\nthis Cargo does not support nightly features, but if you\nswitch to nightly channel you can pass\n`-Z{feature_name}` to enable this feature.\",\n        );\n    }\n    warnings.push(message);\n}\n\nfn lints_to_rustflags(lints: &manifest::TomlLints) -> CargoResult<Vec<String>> {\n    let mut rustflags = lints\n        .iter()\n        // We don't want to pass any of the `cargo` lints to `rustc`\n        .filter(|(tool, _)| tool != &\"cargo\")\n        .flat_map(|(tool, lints)| {\n            lints.iter().map(move |(name, config)| {\n                let flag = match config.level() {\n                    manifest::TomlLintLevel::Forbid => \"--forbid\",\n                    manifest::TomlLintLevel::Deny => \"--deny\",\n                    manifest::TomlLintLevel::Warn => \"--warn\",\n                    manifest::TomlLintLevel::Allow => \"--allow\",\n                };\n\n                let option = if tool == \"rust\" {\n                    format!(\"{flag}={name}\")\n                } else {\n                    format!(\"{flag}={tool}::{name}\")\n                };\n                (\n                    config.priority(),\n                    // Since the most common group will be `all`, put it last so people are more\n                    // likely to notice that they need to use `priority`.\n                    std::cmp::Reverse(name),\n                    option,\n                )\n            })\n        })\n        .collect::<Vec<_>>();\n    rustflags.sort();\n\n    let mut rustflags: Vec<_> = rustflags.into_iter().map(|(_, _, option)| option).collect();\n\n    // Also include the custom arguments specified in `[lints.rust.unexpected_cfgs.check_cfg]`\n    if let Some(rust_lints) = lints.get(\"rust\") {\n        if let Some(unexpected_cfgs) = rust_lints.get(\"unexpected_cfgs\") {\n            if let Some(config) = unexpected_cfgs.config() {\n                if let Some(check_cfg) = config.get(\"check-cfg\") {\n                    if let Ok(check_cfgs) = toml::Value::try_into::<Vec<String>>(check_cfg.clone())\n                    {\n                        for check_cfg in check_cfgs {\n                            rustflags.push(\"--check-cfg\".to_string());\n                            rustflags.push(check_cfg);\n                        }\n                    // error about `check-cfg` not being a list-of-string\n                    } else {\n                        bail!(\"`lints.rust.unexpected_cfgs.check-cfg` must be a list of string\");\n                    }\n                }\n            }\n        }\n    }\n\n    Ok(rustflags)\n}\n\nfn emit_frontmatter_diagnostic(\n    e: crate::util::frontmatter::FrontmatterError,\n    contents: &str,\n    manifest_file: &Path,\n    gctx: &GlobalContext,\n) -> anyhow::Error {\n    let primary_span = e.primary_span();\n\n    // Get the path to the manifest, relative to the cwd\n    let manifest_path = diff_paths(manifest_file, gctx.cwd())\n        .unwrap_or_else(|| manifest_file.to_path_buf())\n        .display()\n        .to_string();\n    let group = Group::with_title(Level::ERROR.primary_title(e.message())).element(\n        Snippet::source(contents)\n            .path(manifest_path)\n            .annotation(AnnotationKind::Primary.span(primary_span))\n            .annotations(\n                e.visible_spans()\n                    .iter()\n                    .map(|s| AnnotationKind::Visible.span(s.clone())),\n            ),\n    );\n\n    if let Err(err) = gctx.shell().print_report(&[group], true) {\n        return err.into();\n    }\n    return AlreadyPrintedError::new(e.into()).into();\n}\n\nfn emit_toml_diagnostic(\n    e: toml::de::Error,\n    contents: &str,\n    manifest_file: &Path,\n    gctx: &GlobalContext,\n) -> anyhow::Error {\n    let Some(span) = e.span() else {\n        return e.into();\n    };\n\n    // Get the path to the manifest, relative to the cwd\n    let manifest_path = diff_paths(manifest_file, gctx.cwd())\n        .unwrap_or_else(|| manifest_file.to_path_buf())\n        .display()\n        .to_string();\n    let group = Group::with_title(Level::ERROR.primary_title(e.message())).element(\n        Snippet::source(contents)\n            .path(manifest_path)\n            .annotation(AnnotationKind::Primary.span(span)),\n    );\n\n    if let Err(err) = gctx.shell().print_report(&[group], true) {\n        return err.into();\n    }\n    return AlreadyPrintedError::new(e.into()).into();\n}\n\n/// Warn about paths that have been deprecated and may conflict.\nfn deprecated_underscore<T>(\n    old: &Option<T>,\n    new: &Option<T>,\n    new_path: &str,\n    name: &str,\n    kind: &str,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n) -> CargoResult<()> {\n    let old_path = new_path.replace(\"-\", \"_\");\n    if old.is_some() && Edition::Edition2024 <= edition {\n        anyhow::bail!(\n            \"`{old_path}` is unsupported as of the 2024 edition; instead use `{new_path}`\\n(in the `{name}` {kind})\"\n        );\n    } else if old.is_some() && new.is_some() {\n        warnings.push(format!(\n            \"`{old_path}` is redundant with `{new_path}`, preferring `{new_path}` in the `{name}` {kind}\"\n        ))\n    } else if old.is_some() {\n        warnings.push(format!(\n            \"`{old_path}` is deprecated in favor of `{new_path}` and will not work in the 2024 edition\\n(in the `{name}` {kind})\"\n        ))\n    }\n    Ok(())\n}\n\nfn warn_on_unused(unused: &BTreeSet<String>, warnings: &mut Vec<String>) {\n    use std::fmt::Write as _;\n\n    for key in unused {\n        let mut message = format!(\"unused manifest key: {}\", key);\n        if TOP_LEVEL_CONFIG_KEYS.iter().any(|c| c == key) {\n            write!(\n                &mut message,\n                \"\\nhelp: {key} is a valid .cargo/config.toml key\"\n            )\n            .unwrap();\n        }\n        warnings.push(message);\n    }\n}\n\nfn unused_dep_keys(\n    dep_name: &str,\n    kind: &str,\n    unused_keys: Vec<String>,\n    warnings: &mut Vec<String>,\n) {\n    for unused in unused_keys {\n        let key = format!(\"unused manifest key: {kind}.{dep_name}.{unused}\");\n        warnings.push(key);\n    }\n}\n\n/// Make the [`Package`] self-contained so its ready for packaging\npub fn prepare_for_publish(\n    me: &Package,\n    ws: &Workspace<'_>,\n    packaged_files: Option<&[PathBuf]>,\n) -> CargoResult<Package> {\n    let contents = me.manifest().contents();\n    let document = me.manifest().document();\n    let original_toml = prepare_toml_for_publish(\n        me.manifest().normalized_toml(),\n        ws,\n        me.root(),\n        packaged_files,\n    )?;\n    let normalized_toml = original_toml.clone();\n    let features = me.manifest().unstable_features().clone();\n    let workspace_config = me.manifest().workspace_config().clone();\n    let source_id = me.package_id().source_id();\n    let mut warnings = Default::default();\n    let mut errors = Default::default();\n    let gctx = ws.gctx();\n    let manifest = to_real_manifest(\n        contents.map(|c| c.to_owned()),\n        document.cloned(),\n        original_toml,\n        normalized_toml,\n        features,\n        workspace_config,\n        source_id,\n        me.manifest_path(),\n        me.manifest().is_embedded(),\n        gctx,\n        &mut warnings,\n        &mut errors,\n    )?;\n    let new_pkg = Package::new(manifest, me.manifest_path());\n    Ok(new_pkg)\n}\n\n/// Prepares the manifest for publishing.\n// - Path and git components of dependency specifications are removed.\n// - License path is updated to point within the package.\nfn prepare_toml_for_publish(\n    me: &manifest::TomlManifest,\n    ws: &Workspace<'_>,\n    package_root: &Path,\n    packaged_files: Option<&[PathBuf]>,\n) -> CargoResult<manifest::TomlManifest> {\n    let gctx = ws.gctx();\n\n    if me\n        .cargo_features\n        .iter()\n        .flat_map(|f| f.iter())\n        .any(|f| f == \"open-namespaces\")\n    {\n        anyhow::bail!(\"cannot publish with `open-namespaces`\")\n    }\n\n    let mut package = me.package().unwrap().clone();\n    package.workspace = None;\n    // Validates if build script file is included in package. If not, warn and ignore.\n    if let Some(custom_build_scripts) = package.normalized_build().expect(\"previously normalized\") {\n        let mut included_scripts = Vec::new();\n        for script in custom_build_scripts {\n            let path = Path::new(script).to_path_buf();\n            let included = packaged_files.map(|i| i.contains(&path)).unwrap_or(true);\n            if included {\n                let path = path\n                    .into_os_string()\n                    .into_string()\n                    .map_err(|_err| anyhow::format_err!(\"non-UTF8 `package.build`\"))?;\n                let path = normalize_path_string_sep(path);\n                included_scripts.push(path);\n            } else {\n                ws.gctx().shell().warn(format!(\n                    \"ignoring `package.build` entry `{}` as it is not included in the published package\",\n                    path.display()\n                ))?;\n            }\n        }\n\n        package.build = Some(match included_scripts.len() {\n            0 => TomlPackageBuild::Auto(false),\n            1 => TomlPackageBuild::SingleScript(included_scripts[0].clone()),\n            _ => TomlPackageBuild::MultipleScript(included_scripts),\n        });\n    }\n    let current_resolver = package\n        .resolver\n        .as_ref()\n        .map(|r| ResolveBehavior::from_manifest(r))\n        .unwrap_or_else(|| {\n            package\n                .edition\n                .as_ref()\n                .and_then(|e| e.as_value())\n                .map(|e| Edition::from_str(e))\n                .unwrap_or(Ok(Edition::Edition2015))\n                .map(|e| e.default_resolve_behavior())\n        })?;\n    if ws.resolve_behavior() != current_resolver {\n        // This ensures the published crate if built as a root (e.g. `cargo install`) will\n        // use the same resolver behavior it was tested with in the workspace.\n        // To avoid forcing a higher MSRV we don't explicitly set this if it would implicitly\n        // result in the same thing.\n        package.resolver = Some(ws.resolve_behavior().to_manifest());\n    }\n    if let Some(license_file) = &package.license_file {\n        let license_file = license_file\n            .as_value()\n            .context(\"license file should have been resolved before `prepare_for_publish()`\")?;\n        let license_path = Path::new(&license_file);\n        let abs_license_path = paths::normalize_path(&package_root.join(license_path));\n        if let Ok(license_file) = abs_license_path.strip_prefix(package_root) {\n            package.license_file = Some(manifest::InheritableField::Value(\n                normalize_path_string_sep(\n                    license_file\n                        .to_str()\n                        .ok_or_else(|| anyhow::format_err!(\"non-UTF8 `package.license-file`\"))?\n                        .to_owned(),\n                ),\n            ));\n        } else {\n            // This path points outside of the package root. `cargo package`\n            // will copy it into the root, so adjust the path to this location.\n            package.license_file = Some(manifest::InheritableField::Value(\n                license_path\n                    .file_name()\n                    .unwrap()\n                    .to_str()\n                    .unwrap()\n                    .to_string(),\n            ));\n        }\n    }\n\n    if let Some(readme) = &package.readme {\n        let readme = readme\n            .as_value()\n            .context(\"readme should have been resolved before `prepare_for_publish()`\")?;\n        match readme {\n            manifest::StringOrBool::String(readme) => {\n                let readme_path = Path::new(&readme);\n                let abs_readme_path = paths::normalize_path(&package_root.join(readme_path));\n                if let Ok(readme_path) = abs_readme_path.strip_prefix(package_root) {\n                    package.readme = Some(manifest::InheritableField::Value(StringOrBool::String(\n                        normalize_path_string_sep(\n                            readme_path\n                                .to_str()\n                                .ok_or_else(|| {\n                                    anyhow::format_err!(\"non-UTF8 `package.license-file`\")\n                                })?\n                                .to_owned(),\n                        ),\n                    )));\n                } else {\n                    // This path points outside of the package root. `cargo package`\n                    // will copy it into the root, so adjust the path to this location.\n                    package.readme = Some(manifest::InheritableField::Value(\n                        manifest::StringOrBool::String(\n                            readme_path\n                                .file_name()\n                                .unwrap()\n                                .to_str()\n                                .unwrap()\n                                .to_string(),\n                        ),\n                    ));\n                }\n            }\n            manifest::StringOrBool::Bool(_) => {}\n        }\n    }\n\n    let lib = if let Some(target) = &me.lib {\n        prepare_target_for_publish(target, packaged_files, \"library\", ws.gctx())?\n    } else {\n        None\n    };\n    let bin = prepare_targets_for_publish(me.bin.as_ref(), packaged_files, \"binary\", ws.gctx())?;\n    let example =\n        prepare_targets_for_publish(me.example.as_ref(), packaged_files, \"example\", ws.gctx())?;\n    let test = prepare_targets_for_publish(me.test.as_ref(), packaged_files, \"test\", ws.gctx())?;\n    let bench =\n        prepare_targets_for_publish(me.bench.as_ref(), packaged_files, \"benchmark\", ws.gctx())?;\n\n    let all = |_d: &manifest::TomlDependency| true;\n    let mut manifest = manifest::TomlManifest {\n        cargo_features: me.cargo_features.clone(),\n        package: Some(package),\n        project: None,\n        badges: me.badges.clone(),\n        features: me.features.clone(),\n        lib,\n        bin,\n        example,\n        test,\n        bench,\n        dependencies: map_deps(gctx, me.dependencies.as_ref(), all)?,\n        dev_dependencies: map_deps(\n            gctx,\n            me.dev_dependencies(),\n            manifest::TomlDependency::is_version_specified,\n        )?,\n        dev_dependencies2: None,\n        build_dependencies: map_deps(gctx, me.build_dependencies(), all)?,\n        build_dependencies2: None,\n        target: match me.target.as_ref().map(|target_map| {\n            target_map\n                .iter()\n                .map(|(k, v)| {\n                    Ok((\n                        k.clone(),\n                        manifest::TomlPlatform {\n                            dependencies: map_deps(gctx, v.dependencies.as_ref(), all)?,\n                            dev_dependencies: map_deps(\n                                gctx,\n                                v.dev_dependencies(),\n                                manifest::TomlDependency::is_version_specified,\n                            )?,\n                            dev_dependencies2: None,\n                            build_dependencies: map_deps(gctx, v.build_dependencies(), all)?,\n                            build_dependencies2: None,\n                        },\n                    ))\n                })\n                .collect()\n        }) {\n            Some(Ok(v)) => Some(v),\n            Some(Err(e)) => return Err(e),\n            None => None,\n        },\n        lints: me.lints.clone(),\n        hints: me.hints.clone(),\n        workspace: None,\n        profile: me.profile.clone(),\n        patch: None,\n        replace: None,\n        _unused_keys: Default::default(),\n    };\n    strip_features(&mut manifest);\n    return Ok(manifest);\n\n    fn strip_features(manifest: &mut TomlManifest) {\n        fn insert_dep_name(\n            dep_name_set: &mut BTreeSet<manifest::PackageName>,\n            deps: Option<&BTreeMap<manifest::PackageName, manifest::InheritableDependency>>,\n        ) {\n            let Some(deps) = deps else {\n                return;\n            };\n            deps.iter().for_each(|(k, _v)| {\n                dep_name_set.insert(k.clone());\n            });\n        }\n        let mut dep_name_set = BTreeSet::new();\n        insert_dep_name(&mut dep_name_set, manifest.dependencies.as_ref());\n        insert_dep_name(&mut dep_name_set, manifest.dev_dependencies());\n        insert_dep_name(&mut dep_name_set, manifest.build_dependencies());\n        if let Some(target_map) = manifest.target.as_ref() {\n            target_map.iter().for_each(|(_k, v)| {\n                insert_dep_name(&mut dep_name_set, v.dependencies.as_ref());\n                insert_dep_name(&mut dep_name_set, v.dev_dependencies());\n                insert_dep_name(&mut dep_name_set, v.build_dependencies());\n            });\n        }\n        let features = manifest.features.as_mut();\n\n        let Some(features) = features else {\n            return;\n        };\n\n        features.values_mut().for_each(|feature_deps| {\n            feature_deps.retain(|feature_dep| {\n                let feature_value = FeatureValue::new(feature_dep.into());\n                match feature_value {\n                    FeatureValue::Dep { dep_name } | FeatureValue::DepFeature { dep_name, .. } => {\n                        let k = &manifest::PackageName::new(dep_name.to_string()).unwrap();\n                        dep_name_set.contains(k)\n                    }\n                    _ => true,\n                }\n            });\n        });\n    }\n\n    fn map_deps(\n        gctx: &GlobalContext,\n        deps: Option<&BTreeMap<manifest::PackageName, manifest::InheritableDependency>>,\n        filter: impl Fn(&manifest::TomlDependency) -> bool,\n    ) -> CargoResult<Option<BTreeMap<manifest::PackageName, manifest::InheritableDependency>>> {\n        let Some(deps) = deps else {\n            return Ok(None);\n        };\n        let deps = deps\n            .iter()\n            .filter(|(_k, v)| {\n                if let manifest::InheritableDependency::Value(def) = v {\n                    filter(def)\n                } else {\n                    false\n                }\n            })\n            .map(|(k, v)| Ok((k.clone(), map_dependency(gctx, v)?)))\n            .collect::<CargoResult<BTreeMap<_, _>>>()?;\n        Ok(Some(deps))\n    }\n\n    fn map_dependency(\n        gctx: &GlobalContext,\n        dep: &manifest::InheritableDependency,\n    ) -> CargoResult<manifest::InheritableDependency> {\n        let dep = match dep {\n            manifest::InheritableDependency::Value(manifest::TomlDependency::Detailed(d)) => {\n                let mut d = d.clone();\n                // Path dependencies become crates.io deps.\n                d.path.take();\n                d.base.take();\n                // Same with git dependencies.\n                d.git.take();\n                d.branch.take();\n                d.tag.take();\n                d.rev.take();\n                // registry specifications are elaborated to the index URL\n                if let Some(registry) = d.registry.take() {\n                    d.registry_index = Some(gctx.get_registry_index(&registry)?.to_string());\n                }\n                Ok(d)\n            }\n            manifest::InheritableDependency::Value(manifest::TomlDependency::Simple(s)) => {\n                Ok(manifest::TomlDetailedDependency {\n                    version: Some(s.clone()),\n                    ..Default::default()\n                })\n            }\n            _ => unreachable!(),\n        };\n        dep.map(manifest::TomlDependency::Detailed)\n            .map(manifest::InheritableDependency::Value)\n    }\n}\n\npub fn prepare_targets_for_publish(\n    targets: Option<&Vec<manifest::TomlTarget>>,\n    packaged_files: Option<&[PathBuf]>,\n    context: &str,\n    gctx: &GlobalContext,\n) -> CargoResult<Option<Vec<manifest::TomlTarget>>> {\n    let Some(targets) = targets else {\n        return Ok(None);\n    };\n\n    let mut prepared = Vec::with_capacity(targets.len());\n    for target in targets {\n        let Some(target) = prepare_target_for_publish(target, packaged_files, context, gctx)?\n        else {\n            continue;\n        };\n        prepared.push(target);\n    }\n\n    if prepared.is_empty() {\n        Ok(None)\n    } else {\n        Ok(Some(prepared))\n    }\n}\n\npub fn prepare_target_for_publish(\n    target: &manifest::TomlTarget,\n    packaged_files: Option<&[PathBuf]>,\n    context: &str,\n    gctx: &GlobalContext,\n) -> CargoResult<Option<manifest::TomlTarget>> {\n    let path = target.path.as_ref().expect(\"previously normalized\");\n    let path = &path.0;\n    if let Some(packaged_files) = packaged_files {\n        if !packaged_files.contains(&path) {\n            let name = target.name.as_ref().expect(\"previously normalized\");\n            gctx.shell().warn(format!(\n                \"ignoring {context} `{name}` as `{}` is not included in the published package\",\n                path.display()\n            ))?;\n            return Ok(None);\n        }\n    }\n\n    let mut target = target.clone();\n    let path = normalize_path_sep(path.to_path_buf(), context)?;\n    target.path = Some(manifest::PathValue(path.into()));\n\n    Ok(Some(target))\n}\n\nfn normalize_path_sep(path: PathBuf, context: &str) -> CargoResult<PathBuf> {\n    let path = path\n        .into_os_string()\n        .into_string()\n        .map_err(|_err| anyhow::format_err!(\"non-UTF8 path for {context}\"))?;\n    let path = normalize_path_string_sep(path);\n    Ok(path.into())\n}\n\npub fn normalize_path_string_sep(path: String) -> String {\n    if std::path::MAIN_SEPARATOR != '/' {\n        path.replace(std::path::MAIN_SEPARATOR, \"/\")\n    } else {\n        path\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/toml/targets.rs",
    "content": "//! This module implements Cargo conventions for directory layout:\n//!\n//!  * `src/lib.rs` is a library\n//!  * `src/main.rs` is a binary\n//!  * `src/bin/*.rs` are binaries\n//!  * `examples/*.rs` are examples\n//!  * `tests/*.rs` are integration tests\n//!  * `benches/*.rs` are benchmarks\n//!\n//! It is a bit tricky because we need match explicit information from `Cargo.toml`\n//! with implicit info in directory layout.\n\nuse std::collections::{HashMap, HashSet};\nuse std::fmt::Write;\nuse std::fs::{self, DirEntry};\nuse std::path::{Path, PathBuf};\n\nuse anyhow::Context as _;\nuse cargo_util::paths;\nuse cargo_util_schemas::manifest::{\n    PathValue, StringOrVec, TomlBenchTarget, TomlBinTarget, TomlExampleTarget, TomlLibTarget,\n    TomlManifest, TomlPackageBuild, TomlTarget, TomlTestTarget,\n};\n\nuse crate::core::compiler::{CrateType, rustdoc::RustdocScrapeExamples};\nuse crate::core::{Edition, Feature, Features, Target};\nuse crate::util::{\n    closest_msg, errors::CargoResult, restricted_names, toml::deprecated_underscore,\n};\n\nconst DEFAULT_TEST_DIR_NAME: &'static str = \"tests\";\nconst DEFAULT_BENCH_DIR_NAME: &'static str = \"benches\";\nconst DEFAULT_EXAMPLE_DIR_NAME: &'static str = \"examples\";\n\nconst TARGET_KIND_HUMAN_LIB: &str = \"library\";\nconst TARGET_KIND_HUMAN_BIN: &str = \"binary\";\nconst TARGET_KIND_HUMAN_EXAMPLE: &str = \"example\";\nconst TARGET_KIND_HUMAN_TEST: &str = \"test\";\nconst TARGET_KIND_HUMAN_BENCH: &str = \"benchmark\";\n\nconst TARGET_KIND_LIB: &str = \"lib\";\nconst TARGET_KIND_BIN: &str = \"bin\";\nconst TARGET_KIND_EXAMPLE: &str = \"example\";\nconst TARGET_KIND_TEST: &str = \"test\";\nconst TARGET_KIND_BENCH: &str = \"bench\";\n\n#[tracing::instrument(skip_all)]\npub(super) fn to_targets(\n    features: &Features,\n    original_toml: &TomlManifest,\n    normalized_toml: &TomlManifest,\n    package_root: &Path,\n    edition: Edition,\n    metabuild: &Option<StringOrVec>,\n    warnings: &mut Vec<String>,\n) -> CargoResult<Vec<Target>> {\n    let mut targets = Vec::new();\n\n    if let Some(target) = to_lib_target(\n        original_toml.lib.as_ref(),\n        normalized_toml.lib.as_ref(),\n        package_root,\n        edition,\n        warnings,\n    )? {\n        targets.push(target);\n    }\n\n    let package = normalized_toml\n        .package\n        .as_ref()\n        .ok_or_else(|| anyhow::format_err!(\"manifest has no `package` (or `project`)\"))?;\n\n    targets.extend(to_bin_targets(\n        features,\n        normalized_toml.bin.as_deref().unwrap_or_default(),\n        package_root,\n        edition,\n        warnings,\n    )?);\n\n    targets.extend(to_example_targets(\n        normalized_toml.example.as_deref().unwrap_or_default(),\n        package_root,\n        edition,\n        warnings,\n    )?);\n\n    targets.extend(to_test_targets(\n        normalized_toml.test.as_deref().unwrap_or_default(),\n        package_root,\n        edition,\n        warnings,\n    )?);\n\n    targets.extend(to_bench_targets(\n        normalized_toml.bench.as_deref().unwrap_or_default(),\n        package_root,\n        edition,\n        warnings,\n    )?);\n\n    // processing the custom build script\n    if let Some(custom_build) = package.normalized_build().expect(\"previously normalized\") {\n        if metabuild.is_some() {\n            anyhow::bail!(\"cannot specify both `metabuild` and `build`\");\n        }\n        validate_unique_build_scripts(custom_build)?;\n        for script in custom_build {\n            let script_path = Path::new(script);\n            let name = format!(\n                \"build-script-{}\",\n                script_path\n                    .file_stem()\n                    .and_then(|s| s.to_str())\n                    .unwrap_or(\"\")\n            );\n            targets.push(Target::custom_build_target(\n                &name,\n                package_root.join(script_path),\n                edition,\n            ));\n        }\n    }\n    if let Some(metabuild) = metabuild {\n        // Verify names match available build deps.\n        let bdeps = normalized_toml.build_dependencies.as_ref();\n        for name in &metabuild.0 {\n            if !bdeps.map_or(false, |bd| bd.contains_key(name.as_str())) {\n                anyhow::bail!(\n                    \"metabuild package `{}` must be specified in `build-dependencies`\",\n                    name\n                );\n            }\n        }\n\n        targets.push(Target::metabuild_target(&format!(\n            \"metabuild-{}\",\n            package.normalized_name().expect(\"previously normalized\")\n        )));\n    }\n\n    Ok(targets)\n}\n\n#[tracing::instrument(skip_all)]\npub fn normalize_lib(\n    original_lib: Option<&TomlLibTarget>,\n    package_root: &Path,\n    package_name: &str,\n    edition: Edition,\n    autodiscover: Option<bool>,\n    warnings: &mut Vec<String>,\n) -> CargoResult<Option<TomlLibTarget>> {\n    if is_normalized(original_lib, autodiscover) {\n        let Some(mut lib) = original_lib.cloned() else {\n            return Ok(None);\n        };\n\n        // Check early to improve error messages\n        validate_lib_name(&lib, warnings)?;\n\n        validate_proc_macro(&lib, TARGET_KIND_HUMAN_LIB, edition, warnings)?;\n        validate_crate_types(&lib, TARGET_KIND_HUMAN_LIB, edition, warnings)?;\n\n        if let Some(PathValue(path)) = &lib.path {\n            lib.path = Some(PathValue(paths::normalize_path(path).into()));\n        }\n\n        Ok(Some(lib))\n    } else {\n        let inferred = inferred_lib(package_root);\n        let lib = original_lib.cloned().or_else(|| {\n            inferred.as_ref().map(|lib| TomlTarget {\n                path: Some(PathValue(lib.clone())),\n                ..TomlTarget::new()\n            })\n        });\n        let Some(mut lib) = lib else { return Ok(None) };\n        lib.name\n            .get_or_insert_with(|| package_name.replace(\"-\", \"_\"));\n\n        // Check early to improve error messages\n        validate_lib_name(&lib, warnings)?;\n\n        validate_proc_macro(&lib, TARGET_KIND_HUMAN_LIB, edition, warnings)?;\n        validate_crate_types(&lib, TARGET_KIND_HUMAN_LIB, edition, warnings)?;\n\n        if lib.path.is_none() {\n            if let Some(inferred) = inferred {\n                lib.path = Some(PathValue(inferred));\n            } else {\n                let name = name_or_panic(&lib);\n                let legacy_path = Path::new(\"src\").join(format!(\"{name}.rs\"));\n                if edition == Edition::Edition2015 && package_root.join(&legacy_path).exists() {\n                    warnings.push(format!(\n                        \"path `{}` was erroneously implicitly accepted for library `{name}`,\\n\\\n                     please rename the file to `src/lib.rs` or set lib.path in Cargo.toml\",\n                        legacy_path.display(),\n                    ));\n                    lib.path = Some(PathValue(legacy_path));\n                } else {\n                    anyhow::bail!(\n                        \"can't find library `{name}`, \\\n                     rename file to `src/lib.rs` or specify lib.path\",\n                    )\n                }\n            }\n        }\n\n        if let Some(PathValue(path)) = lib.path.as_ref() {\n            lib.path = Some(PathValue(paths::normalize_path(&path).into()));\n        }\n\n        Ok(Some(lib))\n    }\n}\n\n#[tracing::instrument(skip_all)]\nfn to_lib_target(\n    original_lib: Option<&TomlLibTarget>,\n    normalized_lib: Option<&TomlLibTarget>,\n    package_root: &Path,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n) -> CargoResult<Option<Target>> {\n    let Some(lib) = normalized_lib else {\n        return Ok(None);\n    };\n\n    let path = lib.path.as_ref().expect(\"previously normalized\");\n    let path = package_root.join(&path.0);\n\n    // Per the Macros 1.1 RFC:\n    //\n    // > Initially if a crate is compiled with the `proc-macro` crate type\n    // > (and possibly others) it will forbid exporting any items in the\n    // > crate other than those functions tagged #[proc_macro_derive] and\n    // > those functions must also be placed at the crate root.\n    //\n    // A plugin requires exporting plugin_registrar so a crate cannot be\n    // both at once.\n    let crate_types = match (lib.crate_types(), lib.proc_macro()) {\n        (Some(kinds), _)\n            if kinds.contains(&CrateType::Dylib.as_str().to_owned())\n                && kinds.contains(&CrateType::Cdylib.as_str().to_owned()) =>\n        {\n            anyhow::bail!(format!(\n                \"library `{}` cannot set the crate type of both `dylib` and `cdylib`\",\n                name_or_panic(lib)\n            ));\n        }\n        (Some(kinds), _) if kinds.contains(&\"proc-macro\".to_string()) => {\n            warnings.push(format!(\n                \"library `{}` should only specify `proc-macro = true` instead of setting `crate-type`\",\n                name_or_panic(lib)\n            ));\n            if kinds.len() > 1 {\n                anyhow::bail!(\"cannot mix `proc-macro` crate type with others\");\n            }\n            vec![CrateType::ProcMacro]\n        }\n        (Some(kinds), _) => kinds.iter().map(|s| s.into()).collect(),\n        (None, Some(true)) => vec![CrateType::ProcMacro],\n        (None, _) => vec![CrateType::Lib],\n    };\n\n    let mut target = Target::lib_target(name_or_panic(lib), crate_types, path, edition);\n    configure(lib, &mut target, TARGET_KIND_HUMAN_LIB, warnings)?;\n    target.set_name_inferred(original_lib.map_or(true, |v| v.name.is_none()));\n    Ok(Some(target))\n}\n\n#[tracing::instrument(skip_all)]\npub fn normalize_bins(\n    toml_bins: Option<&Vec<TomlBinTarget>>,\n    package_root: &Path,\n    package_name: &str,\n    edition: Edition,\n    autodiscover: Option<bool>,\n    warnings: &mut Vec<String>,\n    errors: &mut Vec<String>,\n    has_lib: bool,\n) -> CargoResult<Vec<TomlBinTarget>> {\n    if are_normalized(toml_bins, autodiscover) {\n        let mut toml_bins = toml_bins.cloned().unwrap_or_default();\n        for bin in toml_bins.iter_mut() {\n            validate_bin_name(bin, warnings)?;\n            validate_bin_crate_types(bin, edition, warnings, errors)?;\n            validate_bin_proc_macro(bin, edition, warnings, errors)?;\n\n            if let Some(PathValue(path)) = &bin.path {\n                bin.path = Some(PathValue(paths::normalize_path(path).into()));\n            }\n        }\n        Ok(toml_bins)\n    } else {\n        let inferred = inferred_bins(package_root, package_name);\n\n        let mut bins = toml_targets_and_inferred(\n            toml_bins,\n            &inferred,\n            package_root,\n            autodiscover,\n            edition,\n            warnings,\n            TARGET_KIND_HUMAN_BIN,\n            TARGET_KIND_BIN,\n            \"autobins\",\n        );\n\n        for bin in &mut bins {\n            // Check early to improve error messages\n            validate_bin_name(bin, warnings)?;\n\n            validate_bin_crate_types(bin, edition, warnings, errors)?;\n            validate_bin_proc_macro(bin, edition, warnings, errors)?;\n\n            let path = target_path(\n                bin,\n                &inferred,\n                TARGET_KIND_BIN,\n                package_root,\n                edition,\n                &mut |_| {\n                    if let Some(legacy_path) =\n                        legacy_bin_path(package_root, name_or_panic(bin), has_lib)\n                    {\n                        warnings.push(format!(\n                            \"path `{}` was erroneously implicitly accepted for binary `{}`,\\n\\\n                     please set bin.path in Cargo.toml\",\n                            legacy_path.display(),\n                            name_or_panic(bin)\n                        ));\n                        Some(legacy_path)\n                    } else {\n                        None\n                    }\n                },\n            );\n            let path = match path {\n                Ok(path) => paths::normalize_path(&path).into(),\n                Err(e) => anyhow::bail!(\"{}\", e),\n            };\n            bin.path = Some(PathValue(path));\n        }\n\n        Ok(bins)\n    }\n}\n\n#[tracing::instrument(skip_all)]\nfn to_bin_targets(\n    features: &Features,\n    bins: &[TomlBinTarget],\n    package_root: &Path,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n) -> CargoResult<Vec<Target>> {\n    // This loop performs basic checks on each of the TomlTarget in `bins`.\n    for bin in bins {\n        // For each binary, check if the `filename` parameter is populated. If it is,\n        // check if the corresponding cargo feature has been activated.\n        if bin.filename.is_some() {\n            features.require(Feature::different_binary_name())?;\n        }\n    }\n\n    validate_unique_names(&bins, TARGET_KIND_HUMAN_BIN)?;\n\n    let mut result = Vec::new();\n    for bin in bins {\n        let path = package_root.join(&bin.path.as_ref().expect(\"previously normalized\").0);\n        let mut target = Target::bin_target(\n            name_or_panic(bin),\n            bin.filename.clone(),\n            path,\n            bin.required_features.clone(),\n            edition,\n        );\n\n        configure(bin, &mut target, TARGET_KIND_HUMAN_BIN, warnings)?;\n        result.push(target);\n    }\n    Ok(result)\n}\n\nfn legacy_bin_path(package_root: &Path, name: &str, has_lib: bool) -> Option<PathBuf> {\n    if !has_lib {\n        let rel_path = Path::new(\"src\").join(format!(\"{}.rs\", name));\n        if package_root.join(&rel_path).exists() {\n            return Some(rel_path);\n        }\n    }\n\n    let rel_path = Path::new(\"src\").join(\"main.rs\");\n    if package_root.join(&rel_path).exists() {\n        return Some(rel_path);\n    }\n\n    let default_bin_dir_name = Path::new(\"src\").join(\"bin\");\n    let rel_path = default_bin_dir_name.join(\"main.rs\");\n    if package_root.join(&rel_path).exists() {\n        return Some(rel_path);\n    }\n    None\n}\n\n#[tracing::instrument(skip_all)]\npub fn normalize_examples(\n    toml_examples: Option<&Vec<TomlExampleTarget>>,\n    package_root: &Path,\n    edition: Edition,\n    autodiscover: Option<bool>,\n    warnings: &mut Vec<String>,\n    errors: &mut Vec<String>,\n) -> CargoResult<Vec<TomlExampleTarget>> {\n    let mut inferred = || infer_from_directory(&package_root, Path::new(DEFAULT_EXAMPLE_DIR_NAME));\n\n    let targets = normalize_targets(\n        TARGET_KIND_HUMAN_EXAMPLE,\n        TARGET_KIND_EXAMPLE,\n        toml_examples,\n        &mut inferred,\n        package_root,\n        edition,\n        autodiscover,\n        warnings,\n        errors,\n        \"autoexamples\",\n    )?;\n\n    Ok(targets)\n}\n\n#[tracing::instrument(skip_all)]\nfn to_example_targets(\n    targets: &[TomlExampleTarget],\n    package_root: &Path,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n) -> CargoResult<Vec<Target>> {\n    validate_unique_names(&targets, TARGET_KIND_EXAMPLE)?;\n\n    let mut result = Vec::new();\n    for toml in targets {\n        let path = package_root.join(&toml.path.as_ref().expect(\"previously normalized\").0);\n        let crate_types = match toml.crate_types() {\n            Some(kinds) => kinds.iter().map(|s| s.into()).collect(),\n            None => Vec::new(),\n        };\n\n        let mut target = Target::example_target(\n            name_or_panic(&toml),\n            crate_types,\n            path,\n            toml.required_features.clone(),\n            edition,\n        );\n        configure(&toml, &mut target, TARGET_KIND_HUMAN_EXAMPLE, warnings)?;\n        result.push(target);\n    }\n\n    Ok(result)\n}\n\n#[tracing::instrument(skip_all)]\npub fn normalize_tests(\n    toml_tests: Option<&Vec<TomlTestTarget>>,\n    package_root: &Path,\n    edition: Edition,\n    autodiscover: Option<bool>,\n    warnings: &mut Vec<String>,\n    errors: &mut Vec<String>,\n) -> CargoResult<Vec<TomlTestTarget>> {\n    let mut inferred = || infer_from_directory(&package_root, Path::new(DEFAULT_TEST_DIR_NAME));\n\n    let targets = normalize_targets(\n        TARGET_KIND_HUMAN_TEST,\n        TARGET_KIND_TEST,\n        toml_tests,\n        &mut inferred,\n        package_root,\n        edition,\n        autodiscover,\n        warnings,\n        errors,\n        \"autotests\",\n    )?;\n\n    Ok(targets)\n}\n\n#[tracing::instrument(skip_all)]\nfn to_test_targets(\n    targets: &[TomlTestTarget],\n    package_root: &Path,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n) -> CargoResult<Vec<Target>> {\n    validate_unique_names(&targets, TARGET_KIND_TEST)?;\n\n    let mut result = Vec::new();\n    for toml in targets {\n        let path = package_root.join(&toml.path.as_ref().expect(\"previously normalized\").0);\n        let mut target = Target::test_target(\n            name_or_panic(&toml),\n            path,\n            toml.required_features.clone(),\n            edition,\n        );\n        configure(&toml, &mut target, TARGET_KIND_HUMAN_TEST, warnings)?;\n        result.push(target);\n    }\n    Ok(result)\n}\n\n#[tracing::instrument(skip_all)]\npub fn normalize_benches(\n    toml_benches: Option<&Vec<TomlBenchTarget>>,\n    package_root: &Path,\n    edition: Edition,\n    autodiscover: Option<bool>,\n    warnings: &mut Vec<String>,\n    errors: &mut Vec<String>,\n) -> CargoResult<Vec<TomlBenchTarget>> {\n    let mut legacy_warnings = vec![];\n    let mut legacy_bench_path = |bench: &TomlTarget| {\n        let legacy_path = Path::new(\"src\").join(\"bench.rs\");\n        if !(name_or_panic(bench) == \"bench\" && package_root.join(&legacy_path).exists()) {\n            return None;\n        }\n        legacy_warnings.push(format!(\n            \"path `{}` was erroneously implicitly accepted for benchmark `{}`,\\n\\\n                 please set bench.path in Cargo.toml\",\n            legacy_path.display(),\n            name_or_panic(bench)\n        ));\n        Some(legacy_path)\n    };\n\n    let mut inferred = || infer_from_directory(&package_root, Path::new(DEFAULT_BENCH_DIR_NAME));\n\n    let targets = normalize_targets_with_legacy_path(\n        TARGET_KIND_HUMAN_BENCH,\n        TARGET_KIND_BENCH,\n        toml_benches,\n        &mut inferred,\n        package_root,\n        edition,\n        autodiscover,\n        warnings,\n        errors,\n        &mut legacy_bench_path,\n        \"autobenches\",\n    )?;\n    warnings.append(&mut legacy_warnings);\n\n    Ok(targets)\n}\n\n#[tracing::instrument(skip_all)]\nfn to_bench_targets(\n    targets: &[TomlBenchTarget],\n    package_root: &Path,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n) -> CargoResult<Vec<Target>> {\n    validate_unique_names(&targets, TARGET_KIND_BENCH)?;\n\n    let mut result = Vec::new();\n    for toml in targets {\n        let path = package_root.join(&toml.path.as_ref().expect(\"previously normalized\").0);\n        let mut target = Target::bench_target(\n            name_or_panic(&toml),\n            path,\n            toml.required_features.clone(),\n            edition,\n        );\n        configure(&toml, &mut target, TARGET_KIND_HUMAN_BENCH, warnings)?;\n        result.push(target);\n    }\n\n    Ok(result)\n}\n\nfn is_normalized(toml_target: Option<&TomlTarget>, autodiscover: Option<bool>) -> bool {\n    are_normalized_(toml_target.map(std::slice::from_ref), autodiscover)\n}\n\nfn are_normalized(toml_targets: Option<&Vec<TomlTarget>>, autodiscover: Option<bool>) -> bool {\n    are_normalized_(toml_targets.map(|v| v.as_slice()), autodiscover)\n}\n\nfn are_normalized_(toml_targets: Option<&[TomlTarget]>, autodiscover: Option<bool>) -> bool {\n    if autodiscover != Some(false) {\n        return false;\n    }\n\n    let Some(toml_targets) = toml_targets else {\n        return true;\n    };\n    toml_targets\n        .iter()\n        .all(|t| t.name.is_some() && t.path.is_some())\n}\n\nfn normalize_targets(\n    target_kind_human: &str,\n    target_kind: &str,\n    toml_targets: Option<&Vec<TomlTarget>>,\n    inferred: &mut dyn FnMut() -> Vec<(String, PathBuf)>,\n    package_root: &Path,\n    edition: Edition,\n    autodiscover: Option<bool>,\n    warnings: &mut Vec<String>,\n    errors: &mut Vec<String>,\n    autodiscover_flag_name: &str,\n) -> CargoResult<Vec<TomlTarget>> {\n    normalize_targets_with_legacy_path(\n        target_kind_human,\n        target_kind,\n        toml_targets,\n        inferred,\n        package_root,\n        edition,\n        autodiscover,\n        warnings,\n        errors,\n        &mut |_| None,\n        autodiscover_flag_name,\n    )\n}\n\nfn normalize_targets_with_legacy_path(\n    target_kind_human: &str,\n    target_kind: &str,\n    toml_targets: Option<&Vec<TomlTarget>>,\n    inferred: &mut dyn FnMut() -> Vec<(String, PathBuf)>,\n    package_root: &Path,\n    edition: Edition,\n    autodiscover: Option<bool>,\n    warnings: &mut Vec<String>,\n    errors: &mut Vec<String>,\n    legacy_path: &mut dyn FnMut(&TomlTarget) -> Option<PathBuf>,\n    autodiscover_flag_name: &str,\n) -> CargoResult<Vec<TomlTarget>> {\n    if are_normalized(toml_targets, autodiscover) {\n        let mut toml_targets = toml_targets.cloned().unwrap_or_default();\n        for target in toml_targets.iter_mut() {\n            // Check early to improve error messages\n            validate_target_name(target, target_kind_human, target_kind, warnings)?;\n\n            validate_proc_macro(target, target_kind_human, edition, warnings)?;\n            validate_crate_types(target, target_kind_human, edition, warnings)?;\n\n            if let Some(PathValue(path)) = &target.path {\n                target.path = Some(PathValue(paths::normalize_path(path).into()));\n            }\n        }\n        Ok(toml_targets)\n    } else {\n        let inferred = inferred();\n        let toml_targets = toml_targets_and_inferred(\n            toml_targets,\n            &inferred,\n            package_root,\n            autodiscover,\n            edition,\n            warnings,\n            target_kind_human,\n            target_kind,\n            autodiscover_flag_name,\n        );\n\n        for target in &toml_targets {\n            // Check early to improve error messages\n            validate_target_name(target, target_kind_human, target_kind, warnings)?;\n\n            validate_proc_macro(target, target_kind_human, edition, warnings)?;\n            validate_crate_types(target, target_kind_human, edition, warnings)?;\n        }\n\n        let mut result = Vec::new();\n        for mut target in toml_targets {\n            let path = target_path(\n                &target,\n                &inferred,\n                target_kind,\n                package_root,\n                edition,\n                legacy_path,\n            );\n            let path = match path {\n                Ok(path) => path,\n                Err(e) => {\n                    errors.push(e);\n                    continue;\n                }\n            };\n            target.path = Some(PathValue(paths::normalize_path(&path).into()));\n            result.push(target);\n        }\n        Ok(result)\n    }\n}\n\nfn inferred_lib(package_root: &Path) -> Option<PathBuf> {\n    let lib = Path::new(\"src\").join(\"lib.rs\");\n    if package_root.join(&lib).exists() {\n        Some(lib)\n    } else {\n        None\n    }\n}\n\nfn inferred_bins(package_root: &Path, package_name: &str) -> Vec<(String, PathBuf)> {\n    let main = \"src/main.rs\";\n    let mut result = Vec::new();\n    if package_root.join(main).exists() {\n        let main = PathBuf::from(main);\n        result.push((package_name.to_string(), main));\n    }\n    let default_bin_dir_name = Path::new(\"src\").join(\"bin\");\n    result.extend(infer_from_directory(package_root, &default_bin_dir_name));\n\n    result\n}\n\nfn infer_from_directory(package_root: &Path, relpath: &Path) -> Vec<(String, PathBuf)> {\n    let directory = package_root.join(relpath);\n    let entries = match fs::read_dir(directory) {\n        Err(_) => return Vec::new(),\n        Ok(dir) => dir,\n    };\n\n    entries\n        .filter_map(|e| e.ok())\n        .filter(is_not_dotfile)\n        .filter_map(|d| infer_any(package_root, &d))\n        .collect()\n}\n\nfn infer_any(package_root: &Path, entry: &DirEntry) -> Option<(String, PathBuf)> {\n    if entry.file_type().map_or(false, |t| t.is_dir()) {\n        infer_subdirectory(package_root, entry)\n    } else if entry.path().extension().and_then(|p| p.to_str()) == Some(\"rs\") {\n        infer_file(package_root, entry)\n    } else {\n        None\n    }\n}\n\nfn infer_file(package_root: &Path, entry: &DirEntry) -> Option<(String, PathBuf)> {\n    let path = entry.path();\n    let stem = path.file_stem()?.to_str()?.to_owned();\n    let path = path\n        .strip_prefix(package_root)\n        .map(|p| p.to_owned())\n        .unwrap_or(path);\n    Some((stem, path))\n}\n\nfn infer_subdirectory(package_root: &Path, entry: &DirEntry) -> Option<(String, PathBuf)> {\n    let path = entry.path();\n    let main = path.join(\"main.rs\");\n    let name = path.file_name()?.to_str()?.to_owned();\n    if main.exists() {\n        let main = main\n            .strip_prefix(package_root)\n            .map(|p| p.to_owned())\n            .unwrap_or(main);\n        Some((name, main))\n    } else {\n        None\n    }\n}\n\nfn is_not_dotfile(entry: &DirEntry) -> bool {\n    entry.file_name().to_str().map(|s| s.starts_with('.')) == Some(false)\n}\n\nfn toml_targets_and_inferred(\n    toml_targets: Option<&Vec<TomlTarget>>,\n    inferred: &[(String, PathBuf)],\n    package_root: &Path,\n    autodiscover: Option<bool>,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n    target_kind_human: &str,\n    target_kind: &str,\n    autodiscover_flag_name: &str,\n) -> Vec<TomlTarget> {\n    let inferred_targets = inferred_to_toml_targets(inferred);\n    let mut toml_targets = match toml_targets {\n        None => {\n            if let Some(false) = autodiscover {\n                vec![]\n            } else {\n                inferred_targets\n            }\n        }\n        Some(targets) => {\n            let mut targets = targets.clone();\n\n            let target_path =\n                |target: &TomlTarget| target.path.clone().map(|p| package_root.join(p.0));\n\n            let mut seen_names = HashSet::new();\n            let mut seen_paths = HashSet::new();\n            for target in targets.iter() {\n                seen_names.insert(target.name.clone());\n                seen_paths.insert(target_path(target));\n            }\n\n            let mut rem_targets = vec![];\n            for target in inferred_targets {\n                if !seen_names.contains(&target.name) && !seen_paths.contains(&target_path(&target))\n                {\n                    rem_targets.push(target);\n                }\n            }\n\n            let autodiscover = match autodiscover {\n                Some(autodiscover) => autodiscover,\n                None => {\n                    if edition == Edition::Edition2015 {\n                        if !rem_targets.is_empty() {\n                            let mut rem_targets_str = String::new();\n                            for t in rem_targets.iter() {\n                                if let Some(p) = t.path.clone() {\n                                    rem_targets_str.push_str(&format!(\"* {}\\n\", p.0.display()))\n                                }\n                            }\n                            warnings.push(format!(\n                                \"\\\nAn explicit [[{section}]] section is specified in Cargo.toml which currently\ndisables Cargo from automatically inferring other {target_kind_human} targets.\nThis inference behavior will change in the Rust 2018 edition and the following\nfiles will be included as a {target_kind_human} target:\n\n{rem_targets_str}\nThis is likely to break cargo build or cargo test as these files may not be\nready to be compiled as a {target_kind_human} target today. You can future-proof yourself\nand disable this warning by adding `{autodiscover_flag_name} = false` to your [package]\nsection. You may also move the files to a location where Cargo would not\nautomatically infer them to be a target, such as in subfolders.\n\nFor more information on this warning you can consult\nhttps://github.com/rust-lang/cargo/issues/5330\",\n                                section = target_kind,\n                                target_kind_human = target_kind_human,\n                                rem_targets_str = rem_targets_str,\n                                autodiscover_flag_name = autodiscover_flag_name,\n                            ));\n                        };\n                        false\n                    } else {\n                        true\n                    }\n                }\n            };\n\n            if autodiscover {\n                targets.append(&mut rem_targets);\n            }\n\n            targets\n        }\n    };\n    // Ensure target order is deterministic, particularly for `cargo vendor` where re-vendoring\n    // should not cause changes.\n    //\n    // `unstable` should be deterministic because we enforce that `t.name` is unique\n    toml_targets.sort_unstable_by_key(|t| t.name.clone());\n    toml_targets\n}\n\nfn inferred_to_toml_targets(inferred: &[(String, PathBuf)]) -> Vec<TomlTarget> {\n    inferred\n        .iter()\n        .map(|(name, path)| TomlTarget {\n            name: Some(name.clone()),\n            path: Some(PathValue(path.clone())),\n            ..TomlTarget::new()\n        })\n        .collect()\n}\n\n/// Will check a list of toml targets, and make sure the target names are unique within a vector.\nfn validate_unique_names(targets: &[TomlTarget], target_kind: &str) -> CargoResult<()> {\n    let mut seen = HashSet::new();\n    for name in targets.iter().map(|e| name_or_panic(e)) {\n        if !seen.insert(name) {\n            anyhow::bail!(\n                \"found duplicate {target_kind} name {name}, \\\n                 but all {target_kind} targets must have a unique name\",\n                target_kind = target_kind,\n                name = name\n            );\n        }\n    }\n    Ok(())\n}\n\n/// Will check a list of build scripts, and make sure script file stems are unique within a vector.\nfn validate_unique_build_scripts(scripts: &[String]) -> CargoResult<()> {\n    let mut seen = HashMap::new();\n    for script in scripts {\n        let stem = Path::new(script).file_stem().unwrap().to_str().unwrap();\n        seen.entry(stem)\n            .or_insert_with(Vec::new)\n            .push(script.as_str());\n    }\n    let mut conflict_file_stem = false;\n    let mut err_msg = String::from(\n        \"found build scripts with duplicate file stems, but all build scripts must have a unique file stem\",\n    );\n    for (stem, paths) in seen {\n        if paths.len() > 1 {\n            conflict_file_stem = true;\n            write!(&mut err_msg, \"\\n  for stem `{stem}`: {}\", paths.join(\", \"))?;\n        }\n    }\n    if conflict_file_stem {\n        anyhow::bail!(err_msg);\n    }\n    Ok(())\n}\n\nfn configure(\n    toml: &TomlTarget,\n    target: &mut Target,\n    target_kind_human: &str,\n    warnings: &mut Vec<String>,\n) -> CargoResult<()> {\n    let t2 = target.clone();\n    target\n        .set_tested(toml.test.unwrap_or_else(|| t2.tested()))\n        .set_doc(toml.doc.unwrap_or_else(|| t2.documented()))\n        .set_doctest(toml.doctest.unwrap_or_else(|| t2.doctested()))\n        .set_benched(toml.bench.unwrap_or_else(|| t2.benched()))\n        .set_harness(toml.harness.unwrap_or_else(|| t2.harness()))\n        .set_proc_macro(toml.proc_macro().unwrap_or_else(|| t2.proc_macro()))\n        .set_doc_scrape_examples(match toml.doc_scrape_examples {\n            None => RustdocScrapeExamples::Unset,\n            Some(false) => RustdocScrapeExamples::Disabled,\n            Some(true) => RustdocScrapeExamples::Enabled,\n        })\n        .set_for_host(toml.proc_macro().unwrap_or_else(|| t2.for_host()));\n\n    if let Some(edition) = toml.edition.clone() {\n        let name = target.name();\n        warnings.push(format!(\n            \"`edition` is set on {target_kind_human} `{name}` which is deprecated\"\n        ));\n        target.set_edition(\n            edition\n                .parse()\n                .context(\"failed to parse the `edition` key\")?,\n        );\n    }\n    Ok(())\n}\n\n/// Build an error message for a target path that cannot be determined either\n/// by auto-discovery or specifying.\n///\n/// This function tries to detect commonly wrong paths for targets:\n///\n/// test -> tests/*.rs, tests/*/main.rs\n/// bench -> benches/*.rs, benches/*/main.rs\n/// example -> examples/*.rs, examples/*/main.rs\n/// bin -> src/bin/*.rs, src/bin/*/main.rs\n///\n/// Note that the logic need to sync with [`infer_from_directory`] if changes.\nfn target_path_not_found_error_message(\n    package_root: &Path,\n    target: &TomlTarget,\n    target_kind: &str,\n    inferred: &[(String, PathBuf)],\n) -> String {\n    fn possible_target_paths(name: &str, kind: &str, commonly_wrong: bool) -> [PathBuf; 2] {\n        let mut target_path = PathBuf::new();\n        match (kind, commonly_wrong) {\n            // commonly wrong paths\n            (\"test\" | \"bench\" | \"example\", true) => target_path.push(kind),\n            (\"bin\", true) => target_path.extend([\"src\", \"bins\"]),\n            // default inferred paths\n            (\"test\", false) => target_path.push(DEFAULT_TEST_DIR_NAME),\n            (\"bench\", false) => target_path.push(DEFAULT_BENCH_DIR_NAME),\n            (\"example\", false) => target_path.push(DEFAULT_EXAMPLE_DIR_NAME),\n            (\"bin\", false) => target_path.extend([\"src\", \"bin\"]),\n            _ => unreachable!(\"invalid target kind: {}\", kind),\n        }\n\n        let target_path_file = {\n            let mut path = target_path.clone();\n            path.push(format!(\"{name}.rs\"));\n            path\n        };\n        let target_path_subdir = {\n            target_path.extend([name, \"main.rs\"]);\n            target_path\n        };\n        return [target_path_file, target_path_subdir];\n    }\n\n    let target_name = name_or_panic(target);\n\n    let commonly_wrong_paths = possible_target_paths(&target_name, target_kind, true);\n    let possible_paths = possible_target_paths(&target_name, target_kind, false);\n\n    let msg = closest_msg(target_name, inferred.iter(), |(n, _p)| n, target_kind);\n    if let Some((wrong_path, possible_path)) = commonly_wrong_paths\n        .iter()\n        .zip(possible_paths.iter())\n        .filter(|(wp, _)| package_root.join(wp).exists())\n        .next()\n    {\n        let [wrong_path, possible_path] = [wrong_path, possible_path].map(|p| p.display());\n        format!(\n            \"can't find `{target_name}` {target_kind} at default paths, but found a file at `{wrong_path}`.\\n\\\n             Perhaps rename the file to `{possible_path}` for target auto-discovery, \\\n             or specify {target_kind}.path if you want to use a non-default path.{msg}\",\n        )\n    } else {\n        let [path_file, path_dir] = possible_paths.each_ref().map(|p| p.display());\n        format!(\n            \"can't find `{target_name}` {target_kind} at `{path_file}` or `{path_dir}`. \\\n             Please specify {target_kind}.path if you want to use a non-default path.{msg}\"\n        )\n    }\n}\n\nfn target_path(\n    target: &TomlTarget,\n    inferred: &[(String, PathBuf)],\n    target_kind: &str,\n    package_root: &Path,\n    edition: Edition,\n    legacy_path: &mut dyn FnMut(&TomlTarget) -> Option<PathBuf>,\n) -> Result<PathBuf, String> {\n    if let Some(ref path) = target.path {\n        // Should we verify that this path exists here?\n        return Ok(path.0.clone());\n    }\n    let name = name_or_panic(target).to_owned();\n\n    let mut matching = inferred\n        .iter()\n        .filter(|(n, _)| n == &name)\n        .map(|(_, p)| p.clone());\n\n    let first = matching.next();\n    let second = matching.next();\n    match (first, second) {\n        (Some(path), None) => Ok(path),\n        (None, None) => {\n            if edition == Edition::Edition2015 {\n                if let Some(path) = legacy_path(target) {\n                    return Ok(path);\n                }\n            }\n            Err(target_path_not_found_error_message(\n                package_root,\n                target,\n                target_kind,\n                inferred,\n            ))\n        }\n        (Some(p0), Some(p1)) => {\n            if edition == Edition::Edition2015 {\n                if let Some(path) = legacy_path(target) {\n                    return Ok(path);\n                }\n            }\n            Err(format!(\n                \"\\\ncannot infer path for `{}` {}\nCargo doesn't know which to use because multiple target files found at `{}` and `{}`.\",\n                name_or_panic(target),\n                target_kind,\n                p0.strip_prefix(package_root).unwrap_or(&p0).display(),\n                p1.strip_prefix(package_root).unwrap_or(&p1).display(),\n            ))\n        }\n        (None, Some(_)) => unreachable!(),\n    }\n}\n\n/// Returns the path to the build script if one exists for this crate.\n#[tracing::instrument(skip_all)]\npub fn normalize_build(\n    build: Option<&TomlPackageBuild>,\n    package_root: &Path,\n) -> CargoResult<Option<TomlPackageBuild>> {\n    const BUILD_RS: &str = \"build.rs\";\n    match build {\n        None => {\n            // If there is a `build.rs` file next to the `Cargo.toml`, assume it is\n            // a build script.\n            let build_rs = package_root.join(BUILD_RS);\n            if build_rs.is_file() {\n                Ok(Some(TomlPackageBuild::SingleScript(BUILD_RS.to_owned())))\n            } else {\n                Ok(Some(TomlPackageBuild::Auto(false)))\n            }\n        }\n        // Explicitly no build script.\n        Some(TomlPackageBuild::Auto(false)) => Ok(build.cloned()),\n        Some(TomlPackageBuild::SingleScript(build_file)) => {\n            let build_file = paths::normalize_path(Path::new(build_file));\n            let build = build_file.into_os_string().into_string().expect(\n                \"`build_file` started as a String and `normalize_path` shouldn't have changed that\",\n            );\n            Ok(Some(TomlPackageBuild::SingleScript(build)))\n        }\n        Some(TomlPackageBuild::Auto(true)) => {\n            Ok(Some(TomlPackageBuild::SingleScript(BUILD_RS.to_owned())))\n        }\n        Some(TomlPackageBuild::MultipleScript(_scripts)) => Ok(build.cloned()),\n    }\n}\n\nfn name_or_panic(target: &TomlTarget) -> &str {\n    target\n        .name\n        .as_deref()\n        .unwrap_or_else(|| panic!(\"target name is required\"))\n}\n\nfn validate_lib_name(target: &TomlTarget, warnings: &mut Vec<String>) -> CargoResult<()> {\n    validate_target_name(target, TARGET_KIND_HUMAN_LIB, TARGET_KIND_LIB, warnings)?;\n    let name = name_or_panic(target);\n    if name.contains('-') {\n        anyhow::bail!(\"library target names cannot contain hyphens: {}\", name)\n    }\n\n    Ok(())\n}\n\nfn validate_bin_name(bin: &TomlTarget, warnings: &mut Vec<String>) -> CargoResult<()> {\n    validate_target_name(bin, TARGET_KIND_HUMAN_BIN, TARGET_KIND_BIN, warnings)?;\n    let name = name_or_panic(bin).to_owned();\n    if restricted_names::is_conflicting_artifact_name(&name) {\n        anyhow::bail!(\n            \"the binary target name `{name}` is forbidden, \\\n                 it conflicts with cargo's build directory names\",\n        )\n    }\n\n    Ok(())\n}\n\nfn validate_target_name(\n    target: &TomlTarget,\n    target_kind_human: &str,\n    target_kind: &str,\n    warnings: &mut Vec<String>,\n) -> CargoResult<()> {\n    match target.name {\n        Some(ref name) => {\n            if name.trim().is_empty() {\n                anyhow::bail!(\"{} target names cannot be empty\", target_kind_human)\n            }\n            if cfg!(windows) && restricted_names::is_windows_reserved(name) {\n                warnings.push(format!(\n                    \"{} target `{}` is a reserved Windows filename, \\\n                        this target will not work on Windows platforms\",\n                    target_kind_human, name\n                ));\n            }\n        }\n        None => anyhow::bail!(\n            \"{} target {}.name is required\",\n            target_kind_human,\n            target_kind\n        ),\n    }\n\n    Ok(())\n}\n\nfn validate_bin_proc_macro(\n    target: &TomlTarget,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n    errors: &mut Vec<String>,\n) -> CargoResult<()> {\n    if target.proc_macro() == Some(true) {\n        let name = name_or_panic(target);\n        errors.push(format!(\n            \"the target `{}` is a binary and can't have `proc-macro` \\\n                 set `true`\",\n            name\n        ));\n    } else {\n        validate_proc_macro(target, TARGET_KIND_HUMAN_BIN, edition, warnings)?;\n    }\n    Ok(())\n}\n\nfn validate_proc_macro(\n    target: &TomlTarget,\n    kind: &str,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n) -> CargoResult<()> {\n    deprecated_underscore(\n        &target.proc_macro2,\n        &target.proc_macro,\n        \"proc-macro\",\n        name_or_panic(target),\n        format!(\"{kind} target\").as_str(),\n        edition,\n        warnings,\n    )\n}\n\nfn validate_bin_crate_types(\n    target: &TomlTarget,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n    errors: &mut Vec<String>,\n) -> CargoResult<()> {\n    if let Some(crate_types) = target.crate_types() {\n        if !crate_types.is_empty() {\n            let name = name_or_panic(target);\n            errors.push(format!(\n                \"the target `{}` is a binary and can't have any \\\n                     crate-types set (currently \\\"{}\\\")\",\n                name,\n                crate_types.join(\", \")\n            ));\n        } else {\n            validate_crate_types(target, TARGET_KIND_HUMAN_BIN, edition, warnings)?;\n        }\n    }\n    Ok(())\n}\n\nfn validate_crate_types(\n    target: &TomlTarget,\n    kind: &str,\n    edition: Edition,\n    warnings: &mut Vec<String>,\n) -> CargoResult<()> {\n    deprecated_underscore(\n        &target.crate_type2,\n        &target.crate_type,\n        \"crate-type\",\n        name_or_panic(target),\n        format!(\"{kind} target\").as_str(),\n        edition,\n        warnings,\n    )\n}\n"
  },
  {
    "path": "src/cargo/util/toml_mut/dependency.rs",
    "content": "//! Information about dependencies in a manifest.\n\nuse std::borrow::Cow;\nuse std::fmt::{Display, Formatter};\nuse std::path::{Path, PathBuf};\n\nuse cargo_util_schemas::manifest::PathBaseName;\nuse indexmap::IndexSet;\nuse itertools::Itertools;\nuse toml_edit::KeyMut;\n\nuse super::manifest::str_or_1_len_table;\nuse crate::CargoResult;\nuse crate::GlobalContext;\nuse crate::core::SourceId;\nuse crate::core::Summary;\nuse crate::core::{Features, GitReference};\nuse crate::util::toml::lookup_path_base;\n\n/// A dependency handled by Cargo.\n///\n/// `None` means the field will be blank in TOML.\n#[derive(Debug, PartialEq, Eq, Clone)]\n#[non_exhaustive]\npub struct Dependency {\n    /// The name of the dependency (as it is set in its `Cargo.toml` and known\n    /// to crates.io).\n    pub name: String,\n    /// Whether the dependency is opted-in with a feature flag.\n    pub optional: Option<bool>,\n\n    /// Whether the dependency is marked as public.\n    pub public: Option<bool>,\n\n    /// List of features to add (or None to keep features unchanged).\n    pub features: Option<IndexSet<String>>,\n    /// Whether default features are enabled.\n    pub default_features: Option<bool>,\n    /// List of features inherited from a workspace dependency.\n    pub inherited_features: Option<IndexSet<String>>,\n\n    /// Where the dependency comes from.\n    pub source: Option<Source>,\n    /// Non-default registry.\n    pub registry: Option<String>,\n\n    /// If the dependency is renamed, this is the new name for the dependency\n    /// as a string.  None if it is not renamed.\n    pub rename: Option<String>,\n}\n\nimpl Dependency {\n    /// Create a new dependency with a name.\n    pub fn new(name: &str) -> Self {\n        Self {\n            name: name.into(),\n            optional: None,\n            public: None,\n            features: None,\n            default_features: None,\n            inherited_features: None,\n            source: None,\n            registry: None,\n            rename: None,\n        }\n    }\n\n    /// Set dependency to a given version.\n    pub fn set_source(mut self, source: impl Into<Source>) -> Self {\n        self.source = Some(source.into());\n        self\n    }\n\n    /// Remove the existing version requirement.\n    pub fn clear_version(mut self) -> Self {\n        match &mut self.source {\n            Some(Source::Registry(_)) => {\n                self.source = None;\n            }\n            Some(Source::Path(path)) => {\n                path.version = None;\n            }\n            Some(Source::Git(git)) => {\n                git.version = None;\n            }\n            Some(Source::Workspace(_workspace)) => {}\n            None => {}\n        }\n        self\n    }\n\n    /// Set whether the dependency is optional.\n    #[allow(dead_code)]\n    pub fn set_optional(mut self, opt: bool) -> Self {\n        self.optional = Some(opt);\n        self\n    }\n\n    /// Set features as an array of string (does some basic parsing).\n    #[allow(dead_code)]\n    pub fn set_features(mut self, features: IndexSet<String>) -> Self {\n        self.features = Some(features);\n        self\n    }\n\n    /// Set features as an array of string (does some basic parsing).\n    pub fn extend_features(mut self, features: impl IntoIterator<Item = String>) -> Self {\n        self.features\n            .get_or_insert_with(Default::default)\n            .extend(features);\n        self\n    }\n\n    /// Set the value of default-features for the dependency.\n    #[allow(dead_code)]\n    pub fn set_default_features(mut self, default_features: bool) -> Self {\n        self.default_features = Some(default_features);\n        self\n    }\n\n    /// Set the alias for the dependency.\n    pub fn set_rename(mut self, rename: &str) -> Self {\n        self.rename = Some(rename.into());\n        self\n    }\n\n    /// Set the value of registry for the dependency.\n    pub fn set_registry(mut self, registry: impl Into<String>) -> Self {\n        self.registry = Some(registry.into());\n        self\n    }\n\n    /// Set features as an array of string (does some basic parsing).\n    pub fn set_inherited_features(mut self, features: IndexSet<String>) -> Self {\n        self.inherited_features = Some(features);\n        self\n    }\n\n    /// Get the dependency source.\n    pub fn source(&self) -> Option<&Source> {\n        self.source.as_ref()\n    }\n\n    /// Get version of dependency.\n    pub fn version(&self) -> Option<&str> {\n        match self.source()? {\n            Source::Registry(src) => Some(src.version.as_str()),\n            Source::Path(src) => src.version.as_deref(),\n            Source::Git(src) => src.version.as_deref(),\n            Source::Workspace(_) => None,\n        }\n    }\n\n    /// Get registry of the dependency.\n    pub fn registry(&self) -> Option<&str> {\n        self.registry.as_deref()\n    }\n\n    /// Get the alias for the dependency (if any).\n    pub fn rename(&self) -> Option<&str> {\n        self.rename.as_deref()\n    }\n\n    /// Whether default features are activated.\n    pub fn default_features(&self) -> Option<bool> {\n        self.default_features\n    }\n\n    /// Get whether the dep is optional.\n    pub fn optional(&self) -> Option<bool> {\n        self.optional\n    }\n\n    /// Get whether the dep is public.\n    pub fn public(&self) -> Option<bool> {\n        self.public\n    }\n\n    /// Get the `SourceID` for this dependency.\n    pub fn source_id(&self, gctx: &GlobalContext) -> CargoResult<MaybeWorkspace<SourceId>> {\n        match &self.source.as_ref() {\n            Some(Source::Registry(_)) | None => {\n                if let Some(r) = self.registry() {\n                    let source_id = SourceId::alt_registry(gctx, r)?;\n                    Ok(MaybeWorkspace::Other(source_id))\n                } else {\n                    let source_id = SourceId::crates_io(gctx)?;\n                    Ok(MaybeWorkspace::Other(source_id))\n                }\n            }\n            Some(Source::Path(source)) => Ok(MaybeWorkspace::Other(source.source_id()?)),\n            Some(Source::Git(source)) => Ok(MaybeWorkspace::Other(source.source_id()?)),\n            Some(Source::Workspace(workspace)) => Ok(MaybeWorkspace::Workspace(workspace.clone())),\n        }\n    }\n\n    /// Query to find this dependency.\n    pub fn query(\n        &self,\n        gctx: &GlobalContext,\n    ) -> CargoResult<MaybeWorkspace<crate::core::dependency::Dependency>> {\n        let source_id = self.source_id(gctx)?;\n        match source_id {\n            MaybeWorkspace::Workspace(workspace) => Ok(MaybeWorkspace::Workspace(workspace)),\n            MaybeWorkspace::Other(source_id) => Ok(MaybeWorkspace::Other(\n                crate::core::dependency::Dependency::parse(\n                    self.name.as_str(),\n                    self.version(),\n                    source_id,\n                )?,\n            )),\n        }\n    }\n}\n\n/// Either a workspace or another type.\npub enum MaybeWorkspace<T> {\n    Workspace(WorkspaceSource),\n    Other(T),\n}\n\nimpl Dependency {\n    /// Create a dependency from a TOML table entry.\n    pub fn from_toml(\n        gctx: &GlobalContext,\n        workspace_root: &Path,\n        crate_root: &Path,\n        unstable_features: &Features,\n        key: &str,\n        item: &toml_edit::Item,\n    ) -> CargoResult<Self> {\n        if let Some(version) = item.as_str() {\n            let dep = Self::new(key).set_source(RegistrySource::new(version));\n            Ok(dep)\n        } else if let Some(table) = item.as_table_like() {\n            let (name, rename) = if let Some(value) = table.get(\"package\") {\n                (\n                    value\n                        .as_str()\n                        .ok_or_else(|| invalid_type(key, \"package\", value.type_name(), \"string\"))?\n                        .to_owned(),\n                    Some(key.to_owned()),\n                )\n            } else {\n                (key.to_owned(), None)\n            };\n\n            let source: Source =\n                if let Some(git) = table.get(\"git\") {\n                    let mut src = GitSource::new(\n                        git.as_str()\n                            .ok_or_else(|| invalid_type(key, \"git\", git.type_name(), \"string\"))?,\n                    );\n                    if let Some(value) = table.get(\"branch\") {\n                        src = src.set_branch(value.as_str().ok_or_else(|| {\n                            invalid_type(key, \"branch\", value.type_name(), \"string\")\n                        })?);\n                    }\n                    if let Some(value) = table.get(\"tag\") {\n                        src = src.set_tag(value.as_str().ok_or_else(|| {\n                            invalid_type(key, \"tag\", value.type_name(), \"string\")\n                        })?);\n                    }\n                    if let Some(value) = table.get(\"rev\") {\n                        src = src.set_rev(value.as_str().ok_or_else(|| {\n                            invalid_type(key, \"rev\", value.type_name(), \"string\")\n                        })?);\n                    }\n                    if let Some(value) = table.get(\"version\") {\n                        src = src.set_version(value.as_str().ok_or_else(|| {\n                            invalid_type(key, \"version\", value.type_name(), \"string\")\n                        })?);\n                    }\n                    src.into()\n                } else if let Some(path) = table.get(\"path\") {\n                    let base = table\n                        .get(\"base\")\n                        .map(|base| {\n                            base.as_str()\n                                .ok_or_else(|| {\n                                    invalid_type(key, \"base\", base.type_name(), \"string\")\n                                })\n                                .map(|s| s.to_owned())\n                        })\n                        .transpose()?;\n                    let relative_to = if let Some(base) = &base {\n                        Cow::Owned(lookup_path_base(\n                            &PathBaseName::new(base.clone())?,\n                            gctx,\n                            &|| Ok(workspace_root),\n                            unstable_features,\n                        )?)\n                    } else {\n                        Cow::Borrowed(crate_root)\n                    };\n                    let path = relative_to\n                        .join(path.as_str().ok_or_else(|| {\n                            invalid_type(key, \"path\", path.type_name(), \"string\")\n                        })?);\n                    let mut src = PathSource::new(path);\n                    src.base = base;\n                    if let Some(value) = table.get(\"version\") {\n                        src = src.set_version(value.as_str().ok_or_else(|| {\n                            invalid_type(key, \"version\", value.type_name(), \"string\")\n                        })?);\n                    }\n                    src.into()\n                } else if let Some(version) = table.get(\"version\") {\n                    let src = RegistrySource::new(version.as_str().ok_or_else(|| {\n                        invalid_type(key, \"version\", version.type_name(), \"string\")\n                    })?);\n                    src.into()\n                } else if let Some(workspace) = table.get(\"workspace\") {\n                    let workspace_bool = workspace.as_bool().ok_or_else(|| {\n                        invalid_type(key, \"workspace\", workspace.type_name(), \"bool\")\n                    })?;\n                    if !workspace_bool {\n                        anyhow::bail!(\"`{key}.workspace = false` is unsupported\")\n                    }\n                    let src = WorkspaceSource::new();\n                    src.into()\n                } else {\n                    anyhow::bail!(\n                        \"dependency ({key}) specified without \\\n                        providing a local path, Git repository, version, or \\\n                        workspace dependency to use\"\n                    );\n                };\n            let registry = if let Some(value) = table.get(\"registry\") {\n                Some(\n                    value\n                        .as_str()\n                        .ok_or_else(|| invalid_type(key, \"registry\", value.type_name(), \"string\"))?\n                        .to_owned(),\n                )\n            } else {\n                None\n            };\n\n            let default_features = table.get(\"default-features\").and_then(|v| v.as_bool());\n            if table.contains_key(\"default_features\") {\n                anyhow::bail!(\n                    \"Use of `default_features` in `{key}` is unsupported, please switch to `default-features`\"\n                );\n            }\n\n            let features = if let Some(value) = table.get(\"features\") {\n                Some(\n                    value\n                        .as_array()\n                        .ok_or_else(|| invalid_type(key, \"features\", value.type_name(), \"array\"))?\n                        .iter()\n                        .map(|v| {\n                            v.as_str().map(|s| s.to_owned()).ok_or_else(|| {\n                                invalid_type(key, \"features\", v.type_name(), \"string\")\n                            })\n                        })\n                        .collect::<CargoResult<IndexSet<String>>>()?,\n                )\n            } else {\n                None\n            };\n\n            let optional = table.get(\"optional\").and_then(|v| v.as_bool());\n            let public = table.get(\"public\").and_then(|v| v.as_bool());\n\n            let dep = Self {\n                name,\n                optional,\n                public,\n                features,\n                default_features,\n                inherited_features: None,\n                source: Some(source),\n                registry,\n                rename,\n            };\n            Ok(dep)\n        } else {\n            anyhow::bail!(\"Unrecognized` dependency entry format for `{key}\");\n        }\n    }\n\n    /// Get the dependency name as defined in the manifest,\n    /// that is, either the alias (rename field if Some),\n    /// or the official package name (name field).\n    pub fn toml_key(&self) -> &str {\n        self.rename().unwrap_or(&self.name)\n    }\n\n    /// Convert dependency to TOML.\n    ///\n    /// Returns a tuple with the dependency's name and either the version as a\n    /// `String` or the path/git repository as an `InlineTable`.\n    /// (If the dependency is set as `optional` or `default-features` is set to\n    /// `false`, an `InlineTable` is returned in any case.)\n    ///\n    /// # Panic\n    ///\n    /// Panics if the path is relative\n    pub fn to_toml<'a>(\n        &self,\n        gctx: &GlobalContext,\n        workspace_root: &Path,\n        crate_root: &Path,\n        unstable_features: &Features,\n    ) -> CargoResult<toml_edit::Item> {\n        assert!(\n            crate_root.is_absolute(),\n            \"Absolute path needed, got: {}\",\n            crate_root.display()\n        );\n        let table: toml_edit::Item = match (\n            self.public.unwrap_or(false),\n            self.optional.unwrap_or(false),\n            self.features.as_ref(),\n            self.default_features.unwrap_or(true),\n            self.source.as_ref(),\n            self.registry.as_ref(),\n            self.rename.as_ref(),\n        ) {\n            // Extra short when version flag only\n            (\n                false,\n                false,\n                None,\n                true,\n                Some(Source::Registry(RegistrySource { version: v })),\n                None,\n                None,\n            ) => toml_edit::value(v),\n            (false, false, None, true, Some(Source::Workspace(WorkspaceSource {})), None, None) => {\n                let mut table = toml_edit::InlineTable::default();\n                table.set_dotted(true);\n                table.insert(\"workspace\", true.into());\n                toml_edit::value(toml_edit::Value::InlineTable(table))\n            }\n            // Other cases are represented as an inline table\n            (_, _, _, _, _, _, _) => {\n                let mut table = toml_edit::InlineTable::default();\n\n                match &self.source {\n                    Some(Source::Registry(src)) => {\n                        table.insert(\"version\", src.version.as_str().into());\n                    }\n                    Some(Source::Path(src)) => {\n                        let relpath =\n                            path_field(&src, gctx, workspace_root, crate_root, unstable_features)?;\n                        if let Some(r) = src.version.as_deref() {\n                            table.insert(\"version\", r.into());\n                        }\n                        if let Some(base) = &src.base {\n                            table.insert(\"base\", base.into());\n                        }\n                        table.insert(\"path\", relpath.into());\n                    }\n                    Some(Source::Git(src)) => {\n                        table.insert(\"git\", src.git.as_str().into());\n                        if let Some(branch) = src.branch.as_deref() {\n                            table.insert(\"branch\", branch.into());\n                        }\n                        if let Some(tag) = src.tag.as_deref() {\n                            table.insert(\"tag\", tag.into());\n                        }\n                        if let Some(rev) = src.rev.as_deref() {\n                            table.insert(\"rev\", rev.into());\n                        }\n                        if let Some(r) = src.version.as_deref() {\n                            table.insert(\"version\", r.into());\n                        }\n                    }\n                    Some(Source::Workspace(_)) => {\n                        table.insert(\"workspace\", true.into());\n                    }\n                    None => {}\n                }\n                if table.contains_key(\"version\") {\n                    if let Some(r) = self.registry.as_deref() {\n                        table.insert(\"registry\", r.into());\n                    }\n                }\n\n                if self.rename.is_some() {\n                    table.insert(\"package\", self.name.as_str().into());\n                }\n                if let Some(v) = self.default_features {\n                    table.insert(\"default-features\", v.into());\n                }\n                if let Some(features) = self.features.as_ref() {\n                    let features: toml_edit::Value = features.iter().cloned().collect();\n                    table.insert(\"features\", features);\n                }\n                if let Some(v) = self.optional {\n                    table.insert(\"optional\", v.into());\n                }\n                if let Some(v) = self.public {\n                    table.insert(\"public\", v.into());\n                }\n\n                toml_edit::value(toml_edit::Value::InlineTable(table))\n            }\n        };\n\n        Ok(table)\n    }\n\n    /// Modify existing entry to match this dependency.\n    pub fn update_toml<'k, 'a>(\n        &self,\n        gctx: &GlobalContext,\n        workspace_root: &Path,\n        crate_root: &Path,\n        unstable_features: &Features,\n        key: &mut KeyMut<'k>,\n        item: &mut toml_edit::Item,\n    ) -> CargoResult<()> {\n        if str_or_1_len_table(item) {\n            // Little to preserve\n            let mut new_item = self.to_toml(gctx, workspace_root, crate_root, unstable_features)?;\n            match (&item, &mut new_item) {\n                (toml_edit::Item::Value(old), toml_edit::Item::Value(new)) => {\n                    *new.decor_mut() = old.decor().clone();\n                }\n                (toml_edit::Item::Table(old), toml_edit::Item::Table(new)) => {\n                    *new.decor_mut() = old.decor().clone();\n                }\n                (_, _) => {}\n            }\n            *item = new_item;\n        } else if let Some(table) = item.as_table_like_mut() {\n            match &self.source {\n                Some(Source::Registry(src)) => {\n                    overwrite_value(table, \"version\", src.version.as_str());\n\n                    for key in [\"path\", \"git\", \"branch\", \"tag\", \"rev\", \"workspace\", \"base\"] {\n                        table.remove(key);\n                    }\n                }\n                Some(Source::Path(src)) => {\n                    if let Some(base) = &src.base {\n                        overwrite_value(table, \"base\", base);\n                    } else {\n                        table.remove(\"base\");\n                    }\n                    let relpath =\n                        path_field(&src, gctx, workspace_root, crate_root, unstable_features)?;\n                    overwrite_value(table, \"path\", relpath);\n                    if let Some(r) = src.version.as_deref() {\n                        overwrite_value(table, \"version\", r);\n                    } else {\n                        table.remove(\"version\");\n                    }\n\n                    for key in [\"git\", \"branch\", \"tag\", \"rev\", \"workspace\"] {\n                        table.remove(key);\n                    }\n                }\n                Some(Source::Git(src)) => {\n                    overwrite_value(table, \"git\", src.git.as_str());\n                    if let Some(branch) = src.branch.as_deref() {\n                        overwrite_value(table, \"branch\", branch);\n                    } else {\n                        table.remove(\"branch\");\n                    }\n                    if let Some(tag) = src.tag.as_deref() {\n                        overwrite_value(table, \"tag\", tag);\n                    } else {\n                        table.remove(\"tag\");\n                    }\n                    if let Some(rev) = src.rev.as_deref() {\n                        overwrite_value(table, \"rev\", rev);\n                    } else {\n                        table.remove(\"rev\");\n                    }\n                    if let Some(r) = src.version.as_deref() {\n                        overwrite_value(table, \"version\", r);\n                    } else {\n                        table.remove(\"version\");\n                    }\n\n                    for key in [\"path\", \"workspace\", \"base\"] {\n                        table.remove(key);\n                    }\n                }\n                Some(Source::Workspace(_)) => {\n                    overwrite_value(table, \"workspace\", true);\n                    table.set_dotted(true);\n                    key.fmt();\n                    for key in [\n                        \"version\",\n                        \"registry\",\n                        \"registry-index\",\n                        \"path\",\n                        \"git\",\n                        \"branch\",\n                        \"tag\",\n                        \"rev\",\n                        \"package\",\n                        \"default-features\",\n                        \"base\",\n                    ] {\n                        table.remove(key);\n                    }\n                }\n                None => {}\n            }\n            if table.contains_key(\"version\") {\n                if let Some(r) = self.registry.as_deref() {\n                    overwrite_value(table, \"registry\", r);\n                } else {\n                    table.remove(\"registry\");\n                }\n            } else {\n                table.remove(\"registry\");\n            }\n\n            if self.rename.is_some() {\n                overwrite_value(table, \"package\", self.name.as_str());\n            }\n            match self.default_features {\n                Some(v) => {\n                    overwrite_value(table, \"default-features\", v);\n                }\n                None => {\n                    table.remove(\"default-features\");\n                }\n            }\n            if let Some(new_features) = self.features.as_ref() {\n                let mut features = table\n                    .get(\"features\")\n                    .and_then(|i| i.as_value())\n                    .and_then(|v| v.as_array())\n                    .and_then(|a| {\n                        a.iter()\n                            .map(|v| v.as_str())\n                            .collect::<Option<IndexSet<_>>>()\n                    })\n                    .unwrap_or_default();\n                let is_already_sorted = features.iter().is_sorted();\n                features.extend(new_features.iter().map(|s| s.as_str()));\n                let features = if is_already_sorted {\n                    features.into_iter().sorted().collect::<toml_edit::Value>()\n                } else {\n                    features.into_iter().collect::<toml_edit::Value>()\n                };\n                table.set_dotted(false);\n                overwrite_value(table, \"features\", features);\n            } else {\n                table.remove(\"features\");\n            }\n            match self.optional {\n                Some(v) => {\n                    table.set_dotted(false);\n                    overwrite_value(table, \"optional\", v);\n                }\n                None => {\n                    table.remove(\"optional\");\n                }\n            }\n            match self.public {\n                Some(v) => {\n                    table.set_dotted(false);\n                    overwrite_value(table, \"public\", v);\n                }\n                None => {\n                    table.remove(\"public\");\n                }\n            }\n        } else {\n            unreachable!(\"Invalid dependency type: {}\", item.type_name());\n        }\n        Ok(())\n    }\n}\n\nfn overwrite_value(\n    table: &mut dyn toml_edit::TableLike,\n    key: &str,\n    value: impl Into<toml_edit::Value>,\n) {\n    let mut value = value.into();\n    let existing = table.entry(key).or_insert_with(|| Default::default());\n    if let Some(existing_value) = existing.as_value() {\n        *value.decor_mut() = existing_value.decor().clone();\n    }\n    *existing = toml_edit::Item::Value(value);\n}\n\nfn invalid_type(dep: &str, key: &str, actual: &str, expected: &str) -> anyhow::Error {\n    anyhow::format_err!(\"Found {actual} for {key} when {expected} was expected for {dep}\")\n}\n\nimpl std::fmt::Display for Dependency {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        if let Some(source) = self.source() {\n            write!(f, \"{}@{}\", self.name, source)\n        } else {\n            self.toml_key().fmt(f)\n        }\n    }\n}\n\nimpl<'s> From<&'s Summary> for Dependency {\n    fn from(other: &'s Summary) -> Self {\n        let source: Source = if let Some(path) = other.source_id().local_path() {\n            PathSource::new(path)\n                .set_version(other.version().to_string())\n                .into()\n        } else if let Some(git_ref) = other.source_id().git_reference() {\n            let mut src = GitSource::new(other.source_id().url().to_string())\n                .set_version(other.version().to_string());\n            match git_ref {\n                GitReference::Branch(branch) => src = src.set_branch(branch),\n                GitReference::Tag(tag) => src = src.set_tag(tag),\n                GitReference::Rev(rev) => src = src.set_rev(rev),\n                GitReference::DefaultBranch => {}\n            }\n            src.into()\n        } else {\n            RegistrySource::new(other.version().to_string()).into()\n        };\n        Dependency::new(other.name().as_str()).set_source(source)\n    }\n}\n\nimpl From<Summary> for Dependency {\n    fn from(other: Summary) -> Self {\n        (&other).into()\n    }\n}\n\nfn path_field<'a>(\n    source: &PathSource,\n    gctx: &GlobalContext,\n    workspace_root: &Path,\n    crate_root: &Path,\n    unstable_features: &Features,\n) -> CargoResult<String> {\n    let relative_to = if let Some(base) = &source.base {\n        Cow::Owned(lookup_path_base(\n            &PathBaseName::new(base.clone())?,\n            gctx,\n            &|| Ok(workspace_root),\n            unstable_features,\n        )?)\n    } else {\n        Cow::Borrowed(crate_root)\n    };\n    let relpath = pathdiff::diff_paths(&source.path, relative_to)\n        .expect(\"PathSource::path and workspace path must be absolute\");\n    let relpath = relpath.to_str().unwrap().replace('\\\\', \"/\");\n    Ok(relpath)\n}\n\n/// Primary location of a dependency.\n#[derive(Debug, Hash, PartialEq, Eq, Clone)]\npub enum Source {\n    /// Dependency from a registry.\n    Registry(RegistrySource),\n    /// Dependency from a local path.\n    Path(PathSource),\n    /// Dependency from a git repo.\n    Git(GitSource),\n    /// Dependency from a workspace.\n    Workspace(WorkspaceSource),\n}\n\nimpl Source {\n    /// Access the registry source, if present.\n    pub fn as_registry(&self) -> Option<&RegistrySource> {\n        match self {\n            Self::Registry(src) => Some(src),\n            _ => None,\n        }\n    }\n\n    /// Access the path source, if present.\n    #[allow(dead_code)]\n    pub fn as_path(&self) -> Option<&PathSource> {\n        match self {\n            Self::Path(src) => Some(src),\n            _ => None,\n        }\n    }\n\n    /// Access the git source, if present.\n    #[allow(dead_code)]\n    pub fn as_git(&self) -> Option<&GitSource> {\n        match self {\n            Self::Git(src) => Some(src),\n            _ => None,\n        }\n    }\n\n    /// Access the workspace source, if present.\n    #[allow(dead_code)]\n    pub fn as_workspace(&self) -> Option<&WorkspaceSource> {\n        match self {\n            Self::Workspace(src) => Some(src),\n            _ => None,\n        }\n    }\n}\n\nimpl std::fmt::Display for Source {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            Self::Registry(src) => src.fmt(f),\n            Self::Path(src) => src.fmt(f),\n            Self::Git(src) => src.fmt(f),\n            Self::Workspace(src) => src.fmt(f),\n        }\n    }\n}\n\nimpl<'s> From<&'s Source> for Source {\n    fn from(inner: &'s Source) -> Self {\n        inner.clone()\n    }\n}\n\nimpl From<RegistrySource> for Source {\n    fn from(inner: RegistrySource) -> Self {\n        Self::Registry(inner)\n    }\n}\n\nimpl From<PathSource> for Source {\n    fn from(inner: PathSource) -> Self {\n        Self::Path(inner)\n    }\n}\n\nimpl From<GitSource> for Source {\n    fn from(inner: GitSource) -> Self {\n        Self::Git(inner)\n    }\n}\n\nimpl From<WorkspaceSource> for Source {\n    fn from(inner: WorkspaceSource) -> Self {\n        Self::Workspace(inner)\n    }\n}\n\n/// Dependency from a registry.\n#[derive(Debug, Hash, PartialEq, Eq, Clone)]\n#[non_exhaustive]\npub struct RegistrySource {\n    /// Version requirement.\n    pub version: String,\n}\n\nimpl RegistrySource {\n    /// Specify dependency by version requirement.\n    pub fn new(version: impl AsRef<str>) -> Self {\n        // versions might have semver metadata appended which we do not want to\n        // store in the cargo toml files.  This would cause a warning upon compilation\n        // (\"version requirement […] includes semver metadata which will be ignored\")\n        let version = version.as_ref().split('+').next().unwrap();\n        Self {\n            version: version.to_owned(),\n        }\n    }\n}\n\nimpl std::fmt::Display for RegistrySource {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.version.fmt(f)\n    }\n}\n\n/// Dependency from a local path.\n#[derive(Debug, Hash, PartialEq, Eq, Clone)]\n#[non_exhaustive]\npub struct PathSource {\n    /// Local, absolute path.\n    pub path: PathBuf,\n    /// The path base, if using one.\n    pub base: Option<String>,\n    /// Version requirement for when published.\n    pub version: Option<String>,\n}\n\nimpl PathSource {\n    /// Specify dependency from a path.\n    pub fn new(path: impl Into<PathBuf>) -> Self {\n        Self {\n            path: path.into(),\n            base: None,\n            version: None,\n        }\n    }\n\n    /// Set an optional version requirement.\n    pub fn set_version(mut self, version: impl AsRef<str>) -> Self {\n        // versions might have semver metadata appended which we do not want to\n        // store in the cargo toml files.  This would cause a warning upon compilation\n        // (\"version requirement […] includes semver metadata which will be ignored\")\n        let version = version.as_ref().split('+').next().unwrap();\n        self.version = Some(version.to_owned());\n        self\n    }\n\n    /// Get the `SourceID` for this dependency.\n    pub fn source_id(&self) -> CargoResult<SourceId> {\n        SourceId::for_path(&self.path)\n    }\n}\n\nimpl std::fmt::Display for PathSource {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.path.display().fmt(f)\n    }\n}\n\n/// Dependency from a git repo.\n#[derive(Debug, Hash, PartialEq, Eq, Clone)]\n#[non_exhaustive]\npub struct GitSource {\n    /// Repository URL.\n    pub git: String,\n    /// Select specific branch.\n    pub branch: Option<String>,\n    /// Select specific tag.\n    pub tag: Option<String>,\n    /// Select specific rev.\n    pub rev: Option<String>,\n    /// Version requirement for when published.\n    pub version: Option<String>,\n}\n\nimpl GitSource {\n    /// Specify dependency from a git repo.\n    pub fn new(git: impl Into<String>) -> Self {\n        Self {\n            git: git.into(),\n            branch: None,\n            tag: None,\n            rev: None,\n            version: None,\n        }\n    }\n\n    /// Specify an optional branch.\n    pub fn set_branch(mut self, branch: impl Into<String>) -> Self {\n        self.branch = Some(branch.into());\n        self.tag = None;\n        self.rev = None;\n        self\n    }\n\n    /// Specify an optional tag.\n    pub fn set_tag(mut self, tag: impl Into<String>) -> Self {\n        self.branch = None;\n        self.tag = Some(tag.into());\n        self.rev = None;\n        self\n    }\n\n    /// Specify an optional rev.\n    pub fn set_rev(mut self, rev: impl Into<String>) -> Self {\n        self.branch = None;\n        self.tag = None;\n        self.rev = Some(rev.into());\n        self\n    }\n\n    /// Get the `SourceID` for this dependency.\n    pub fn source_id(&self) -> CargoResult<SourceId> {\n        let git_url = self.git.parse::<url::Url>()?;\n        let git_ref = self.git_ref();\n        SourceId::for_git(&git_url, git_ref)\n    }\n\n    fn git_ref(&self) -> GitReference {\n        match (\n            self.branch.as_deref(),\n            self.tag.as_deref(),\n            self.rev.as_deref(),\n        ) {\n            (Some(branch), _, _) => GitReference::Branch(branch.to_owned()),\n            (_, Some(tag), _) => GitReference::Tag(tag.to_owned()),\n            (_, _, Some(rev)) => GitReference::Rev(rev.to_owned()),\n            _ => GitReference::DefaultBranch,\n        }\n    }\n\n    /// Set an optional version requirement.\n    pub fn set_version(mut self, version: impl AsRef<str>) -> Self {\n        // versions might have semver metadata appended which we do not want to\n        // store in the cargo toml files.  This would cause a warning upon compilation\n        // (\"version requirement […] includes semver metadata which will be ignored\")\n        let version = version.as_ref().split('+').next().unwrap();\n        self.version = Some(version.to_owned());\n        self\n    }\n}\n\nimpl std::fmt::Display for GitSource {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let git_ref = self.git_ref();\n        if let Some(pretty_ref) = git_ref.pretty_ref(true) {\n            write!(f, \"{}?{}\", self.git, pretty_ref)\n        } else {\n            write!(f, \"{}\", self.git)\n        }\n    }\n}\n\n/// Dependency from a workspace.\n#[derive(Debug, Hash, PartialEq, Eq, Clone)]\n#[non_exhaustive]\npub struct WorkspaceSource;\n\nimpl WorkspaceSource {\n    pub fn new() -> Self {\n        Self\n    }\n}\n\nimpl Display for WorkspaceSource {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        \"workspace\".fmt(f)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::util::toml_mut::manifest::LocalManifest;\n    use cargo_util::paths;\n\n    use super::*;\n\n    #[test]\n    fn to_toml_simple_dep() {\n        let crate_root =\n            paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new(\"/\")));\n        let dep = Dependency::new(\"dep\").set_source(RegistrySource::new(\"1.0\"));\n        let key = dep.toml_key();\n        let gctx = GlobalContext::default().unwrap();\n        let item = dep\n            .to_toml(&gctx, &crate_root, &crate_root, &Features::default())\n            .unwrap();\n\n        assert_eq!(key, \"dep\".to_owned());\n\n        verify_roundtrip(&crate_root, &gctx, key, &item);\n    }\n\n    #[test]\n    fn to_toml_simple_dep_with_version() {\n        let crate_root =\n            paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new(\"/\")));\n        let dep = Dependency::new(\"dep\").set_source(RegistrySource::new(\"1.0\"));\n        let key = dep.toml_key();\n        let gctx = GlobalContext::default().unwrap();\n        let item = dep\n            .to_toml(&gctx, &crate_root, &crate_root, &Features::default())\n            .unwrap();\n\n        assert_eq!(key, \"dep\".to_owned());\n        assert_eq!(item.as_str(), Some(\"1.0\"));\n\n        verify_roundtrip(&crate_root, &gctx, key, &item);\n    }\n\n    #[test]\n    fn to_toml_optional_dep() {\n        let crate_root =\n            paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new(\"/\")));\n        let dep = Dependency::new(\"dep\")\n            .set_source(RegistrySource::new(\"1.0\"))\n            .set_optional(true);\n        let key = dep.toml_key();\n        let gctx = GlobalContext::default().unwrap();\n        let item = dep\n            .to_toml(&gctx, &crate_root, &crate_root, &Features::default())\n            .unwrap();\n\n        assert_eq!(key, \"dep\".to_owned());\n        assert!(item.is_inline_table());\n\n        let dep = item.as_inline_table().unwrap();\n        assert_eq!(dep.get(\"optional\").unwrap().as_bool(), Some(true));\n\n        verify_roundtrip(&crate_root, &gctx, key, &item);\n    }\n\n    #[test]\n    fn to_toml_dep_without_default_features() {\n        let crate_root =\n            paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new(\"/\")));\n        let dep = Dependency::new(\"dep\")\n            .set_source(RegistrySource::new(\"1.0\"))\n            .set_default_features(false);\n        let key = dep.toml_key();\n        let gctx = GlobalContext::default().unwrap();\n        let item = dep\n            .to_toml(&gctx, &crate_root, &crate_root, &Features::default())\n            .unwrap();\n\n        assert_eq!(key, \"dep\".to_owned());\n        assert!(item.is_inline_table());\n\n        let dep = item.as_inline_table().unwrap();\n        assert_eq!(dep.get(\"default-features\").unwrap().as_bool(), Some(false));\n\n        verify_roundtrip(&crate_root, &gctx, key, &item);\n    }\n\n    #[test]\n    fn to_toml_dep_with_path_source() {\n        let root = paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new(\"/\")));\n        let crate_root = root.join(\"foo\");\n        let dep = Dependency::new(\"dep\").set_source(PathSource::new(root.join(\"bar\")));\n        let key = dep.toml_key();\n        let gctx = GlobalContext::default().unwrap();\n        let item = dep\n            .to_toml(&gctx, &crate_root, &crate_root, &Features::default())\n            .unwrap();\n\n        assert_eq!(key, \"dep\".to_owned());\n        assert!(item.is_inline_table());\n\n        let dep = item.as_inline_table().unwrap();\n        assert_eq!(dep.get(\"path\").unwrap().as_str(), Some(\"../bar\"));\n\n        verify_roundtrip(&crate_root, &gctx, key, &item);\n    }\n\n    #[test]\n    fn to_toml_dep_with_git_source() {\n        let crate_root =\n            paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new(\"/\")));\n        let dep = Dependency::new(\"dep\").set_source(GitSource::new(\"https://foor/bar.git\"));\n        let key = dep.toml_key();\n        let gctx = GlobalContext::default().unwrap();\n        let item = dep\n            .to_toml(&gctx, &crate_root, &crate_root, &Features::default())\n            .unwrap();\n\n        assert_eq!(key, \"dep\".to_owned());\n        assert!(item.is_inline_table());\n\n        let dep = item.as_inline_table().unwrap();\n        assert_eq!(\n            dep.get(\"git\").unwrap().as_str(),\n            Some(\"https://foor/bar.git\")\n        );\n\n        verify_roundtrip(&crate_root, &gctx, key, &item);\n    }\n\n    #[test]\n    fn to_toml_renamed_dep() {\n        let crate_root =\n            paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new(\"/\")));\n        let dep = Dependency::new(\"dep\")\n            .set_source(RegistrySource::new(\"1.0\"))\n            .set_rename(\"d\");\n        let key = dep.toml_key();\n        let gctx = GlobalContext::default().unwrap();\n        let item = dep\n            .to_toml(&gctx, &crate_root, &crate_root, &Features::default())\n            .unwrap();\n\n        assert_eq!(key, \"d\".to_owned());\n        assert!(item.is_inline_table());\n\n        let dep = item.as_inline_table().unwrap();\n        assert_eq!(dep.get(\"package\").unwrap().as_str(), Some(\"dep\"));\n\n        verify_roundtrip(&crate_root, &gctx, key, &item);\n    }\n\n    #[test]\n    fn to_toml_dep_from_alt_registry() {\n        let crate_root =\n            paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new(\"/\")));\n        let dep = Dependency::new(\"dep\")\n            .set_source(RegistrySource::new(\"1.0\"))\n            .set_registry(\"alternative\");\n        let key = dep.toml_key();\n        let gctx = GlobalContext::default().unwrap();\n        let item = dep\n            .to_toml(&gctx, &crate_root, &crate_root, &Features::default())\n            .unwrap();\n\n        assert_eq!(key, \"dep\".to_owned());\n        assert!(item.is_inline_table());\n\n        let dep = item.as_inline_table().unwrap();\n        assert_eq!(dep.get(\"registry\").unwrap().as_str(), Some(\"alternative\"));\n\n        verify_roundtrip(&crate_root, &gctx, key, &item);\n    }\n\n    #[test]\n    fn to_toml_complex_dep() {\n        let crate_root =\n            paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new(\"/\")));\n        let dep = Dependency::new(\"dep\")\n            .set_source(RegistrySource::new(\"1.0\"))\n            .set_default_features(false)\n            .set_rename(\"d\");\n        let key = dep.toml_key();\n        let gctx = GlobalContext::default().unwrap();\n        let item = dep\n            .to_toml(&gctx, &crate_root, &crate_root, &Features::default())\n            .unwrap();\n\n        assert_eq!(key, \"d\".to_owned());\n        assert!(item.is_inline_table());\n\n        let dep = item.as_inline_table().unwrap();\n        assert_eq!(dep.get(\"package\").unwrap().as_str(), Some(\"dep\"));\n        assert_eq!(dep.get(\"version\").unwrap().as_str(), Some(\"1.0\"));\n        assert_eq!(dep.get(\"default-features\").unwrap().as_bool(), Some(false));\n\n        verify_roundtrip(&crate_root, &gctx, key, &item);\n    }\n\n    #[test]\n    fn paths_with_forward_slashes_are_left_as_is() {\n        let crate_root =\n            paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new(\"/\")));\n        let path = crate_root.join(\"sibling/crate\");\n        let relpath = \"sibling/crate\";\n        let dep = Dependency::new(\"dep\").set_source(PathSource::new(path));\n        let key = dep.toml_key();\n        let gctx = GlobalContext::default().unwrap();\n        let item = dep\n            .to_toml(&gctx, &crate_root, &crate_root, &Features::default())\n            .unwrap();\n\n        let table = item.as_inline_table().unwrap();\n        let got = table.get(\"path\").unwrap().as_str().unwrap();\n        assert_eq!(got, relpath);\n\n        verify_roundtrip(&crate_root, &gctx, key, &item);\n    }\n\n    #[test]\n    fn overwrite_with_workspace_source_fmt_key() {\n        let crate_root =\n            paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new(\"./\")));\n        let toml = \"dep = \\\"1.0\\\"\\n\";\n        let manifest = toml.parse().unwrap();\n        let mut local = LocalManifest {\n            path: crate_root.clone(),\n            manifest,\n            embedded: None,\n            raw: toml.to_owned(),\n        };\n        assert_eq!(local.manifest.to_string(), toml);\n        let gctx = GlobalContext::default().unwrap();\n        for (key, item) in local.data.clone().iter() {\n            let dep = Dependency::from_toml(\n                &gctx,\n                &crate_root,\n                &crate_root,\n                &Features::default(),\n                key,\n                item,\n            )\n            .unwrap();\n            let dep = dep.set_source(WorkspaceSource::new());\n            local\n                .insert_into_table(&[], &dep, &gctx, &crate_root, &Features::default())\n                .unwrap();\n            assert_eq!(local.data.to_string(), \"dep.workspace = true\\n\");\n        }\n    }\n\n    #[test]\n    #[cfg(windows)]\n    fn normalise_windows_style_paths() {\n        let crate_root =\n            paths::normalize_path(&std::env::current_dir().unwrap().join(Path::new(\"/\")));\n        let original = crate_root.join(r\"sibling\\crate\");\n        let should_be = \"sibling/crate\";\n        let dep = Dependency::new(\"dep\").set_source(PathSource::new(original));\n        let key = dep.toml_key();\n        let gctx = GlobalContext::default().unwrap();\n        let item = dep\n            .to_toml(&gctx, &crate_root, &crate_root, &Features::default())\n            .unwrap();\n\n        let table = item.as_inline_table().unwrap();\n        let got = table.get(\"path\").unwrap().as_str().unwrap();\n        assert_eq!(got, should_be);\n\n        verify_roundtrip(&crate_root, &gctx, key, &item);\n    }\n\n    #[track_caller]\n    fn verify_roundtrip(\n        crate_root: &Path,\n        gctx: &GlobalContext,\n        key: &str,\n        item: &toml_edit::Item,\n    ) {\n        let roundtrip = Dependency::from_toml(\n            gctx,\n            crate_root,\n            crate_root,\n            &Features::default(),\n            key,\n            item,\n        )\n        .unwrap();\n        let round_key = roundtrip.toml_key();\n        let round_item = roundtrip\n            .to_toml(gctx, crate_root, crate_root, &Features::default())\n            .unwrap();\n        assert_eq!(key, round_key);\n        assert_eq!(item.to_string(), round_item.to_string());\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/toml_mut/manifest.rs",
    "content": "//! Parsing and editing of manifest files.\n\nuse std::ops::{Deref, DerefMut};\nuse std::path::{Path, PathBuf};\nuse std::str;\n\nuse anyhow::Context as _;\n\nuse super::dependency::Dependency;\nuse crate::core::dependency::DepKind;\nuse crate::core::{FeatureValue, Features, Workspace};\nuse crate::util::closest;\nuse crate::util::frontmatter::ScriptSource;\nuse crate::util::toml::is_embedded;\nuse crate::{CargoResult, GlobalContext};\n\n/// Dependency table to add deps to.\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct DepTable {\n    kind: DepKind,\n    target: Option<String>,\n}\n\nimpl DepTable {\n    const KINDS: &'static [Self] = &[\n        Self::new().set_kind(DepKind::Normal),\n        Self::new().set_kind(DepKind::Development),\n        Self::new().set_kind(DepKind::Build),\n    ];\n\n    /// Reference to a Dependency Table.\n    pub const fn new() -> Self {\n        Self {\n            kind: DepKind::Normal,\n            target: None,\n        }\n    }\n\n    /// Choose the type of dependency.\n    pub const fn set_kind(mut self, kind: DepKind) -> Self {\n        self.kind = kind;\n        self\n    }\n\n    /// Choose the platform for the dependency.\n    pub fn set_target(mut self, target: impl Into<String>) -> Self {\n        self.target = Some(target.into());\n        self\n    }\n\n    /// Type of dependency.\n    pub fn kind(&self) -> DepKind {\n        self.kind\n    }\n\n    /// Platform for the dependency.\n    pub fn target(&self) -> Option<&str> {\n        self.target.as_deref()\n    }\n\n    /// Keys to the table.\n    pub fn to_table(&self) -> Vec<&str> {\n        if let Some(target) = &self.target {\n            vec![\"target\", target, self.kind.kind_table()]\n        } else {\n            vec![self.kind.kind_table()]\n        }\n    }\n}\n\nimpl Default for DepTable {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl From<DepKind> for DepTable {\n    fn from(other: DepKind) -> Self {\n        Self::new().set_kind(other)\n    }\n}\n\n/// An editable Cargo manifest.\n#[derive(Debug, Clone)]\npub struct Manifest {\n    /// Manifest contents as TOML data.\n    pub data: toml_edit::DocumentMut,\n}\n\nimpl Manifest {\n    /// Get the manifest's package name.\n    pub fn package_name(&self) -> CargoResult<&str> {\n        self.data\n            .as_table()\n            .get(\"package\")\n            .and_then(|m| m.get(\"name\"))\n            .and_then(|m| m.as_str())\n            .ok_or_else(parse_manifest_err)\n    }\n\n    /// Get the specified table from the manifest.\n    pub fn get_table<'a>(&'a self, table_path: &[String]) -> Option<&'a toml_edit::Item> {\n        /// Descend into a manifest until the required table is found.\n        fn descend<'a>(input: &'a toml_edit::Item, path: &[String]) -> Option<&'a toml_edit::Item> {\n            if let Some(segment) = path.get(0) {\n                let value = input.get(&segment)?;\n\n                if value.is_table_like() {\n                    descend(value, &path[1..])\n                } else {\n                    None\n                }\n            } else {\n                Some(input)\n            }\n        }\n\n        descend(self.data.as_item(), table_path)\n    }\n\n    /// Get the specified table from the manifest.\n    pub fn get_table_mut<'a>(\n        &'a mut self,\n        table_path: &[String],\n    ) -> Option<&'a mut toml_edit::Item> {\n        /// Descend into a manifest until the required table is found.\n        fn descend<'a>(\n            input: &'a mut toml_edit::Item,\n            path: &[String],\n        ) -> Option<&'a mut toml_edit::Item> {\n            if let Some(segment) = path.get(0) {\n                let mut default_table = toml_edit::Table::new();\n                default_table.set_implicit(true);\n                let value = input[&segment].or_insert(toml_edit::Item::Table(default_table));\n\n                if value.is_table_like() {\n                    descend(value, &path[1..])\n                } else {\n                    None\n                }\n            } else {\n                Some(input)\n            }\n        }\n\n        descend(self.data.as_item_mut(), table_path)\n    }\n\n    /// Get all sections in the manifest that exist and might contain\n    /// dependencies. The returned items are always `Table` or\n    /// `InlineTable`.\n    pub fn get_sections(&self) -> Vec<(DepTable, toml_edit::Item)> {\n        let mut sections = Vec::new();\n\n        for table in DepTable::KINDS {\n            let dependency_type = table.kind.kind_table();\n            // Dependencies can be in the three standard sections...\n            if self\n                .data\n                .get(dependency_type)\n                .map(|t| t.is_table_like())\n                .unwrap_or(false)\n            {\n                sections.push((table.clone(), self.data[dependency_type].clone()))\n            }\n\n            // ... and in `target.<target>.(build-/dev-)dependencies`.\n            let target_sections = self\n                .data\n                .as_table()\n                .get(\"target\")\n                .and_then(toml_edit::Item::as_table_like)\n                .into_iter()\n                .flat_map(toml_edit::TableLike::iter)\n                .filter_map(|(target_name, target_table)| {\n                    let dependency_table = target_table.get(dependency_type)?;\n                    dependency_table.as_table_like().map(|_| {\n                        (\n                            table.clone().set_target(target_name),\n                            dependency_table.clone(),\n                        )\n                    })\n                });\n\n            sections.extend(target_sections);\n        }\n\n        sections\n    }\n\n    pub fn get_legacy_sections(&self) -> Vec<String> {\n        let mut result = Vec::new();\n\n        for dependency_type in [\"dev_dependencies\", \"build_dependencies\"] {\n            if self.data.contains_key(dependency_type) {\n                result.push(dependency_type.to_owned());\n            }\n\n            // ... and in `target.<target>.(build-/dev-)dependencies`.\n            result.extend(\n                self.data\n                    .as_table()\n                    .get(\"target\")\n                    .and_then(toml_edit::Item::as_table_like)\n                    .into_iter()\n                    .flat_map(toml_edit::TableLike::iter)\n                    .filter_map(|(target_name, target_table)| {\n                        if target_table.as_table_like()?.contains_key(dependency_type) {\n                            Some(format!(\"target.{target_name}.{dependency_type}\"))\n                        } else {\n                            None\n                        }\n                    }),\n            );\n        }\n        result\n    }\n}\n\nimpl str::FromStr for Manifest {\n    type Err = anyhow::Error;\n\n    /// Read manifest data from string\n    fn from_str(input: &str) -> ::std::result::Result<Self, Self::Err> {\n        let d: toml_edit::DocumentMut = input.parse().context(\"Manifest not valid TOML\")?;\n\n        Ok(Manifest { data: d })\n    }\n}\n\nimpl std::fmt::Display for Manifest {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.data.fmt(f)\n    }\n}\n\n/// An editable Cargo manifest that is available locally.\n#[derive(Debug, Clone)]\npub struct LocalManifest {\n    /// Path to the manifest.\n    pub path: PathBuf,\n    /// Manifest contents.\n    pub manifest: Manifest,\n    /// The raw, unparsed package file\n    pub raw: String,\n    /// Edit location for an embedded manifest, if relevant\n    pub embedded: Option<Embedded>,\n}\n\nimpl Deref for LocalManifest {\n    type Target = Manifest;\n\n    fn deref(&self) -> &Manifest {\n        &self.manifest\n    }\n}\n\nimpl DerefMut for LocalManifest {\n    fn deref_mut(&mut self) -> &mut Manifest {\n        &mut self.manifest\n    }\n}\n\nimpl LocalManifest {\n    /// Construct the `LocalManifest` corresponding to the `Path` provided..\n    pub fn try_new(path: &Path) -> CargoResult<Self> {\n        if !path.is_absolute() {\n            anyhow::bail!(\"can only edit absolute paths, got {}\", path.display());\n        }\n        let raw = cargo_util::paths::read(&path)?;\n        let mut data = raw.clone();\n        let mut embedded = None;\n        if is_embedded(path) {\n            let source = ScriptSource::parse(&data)?;\n            if let Some(frontmatter) = source.frontmatter_span() {\n                embedded = Some(Embedded::exists(frontmatter));\n                data = source.frontmatter().unwrap().to_owned();\n            } else if let Some(shebang) = source.shebang_span() {\n                embedded = Some(Embedded::after(shebang));\n                data = String::new();\n            } else {\n                embedded = Some(Embedded::start());\n                data = String::new();\n            }\n        }\n        let manifest = data.parse().context(\"Unable to parse Cargo.toml\")?;\n        Ok(LocalManifest {\n            manifest,\n            path: path.to_owned(),\n            raw,\n            embedded,\n        })\n    }\n\n    /// Write changes back to the file.\n    pub fn write(&self) -> CargoResult<()> {\n        let mut manifest = self.manifest.data.to_string();\n        let raw = match self.embedded.as_ref() {\n            Some(Embedded::Implicit(start)) => {\n                if !manifest.ends_with(\"\\n\") {\n                    manifest.push_str(\"\\n\");\n                }\n                let fence = \"---\\n\";\n                let prefix = &self.raw[0..*start];\n                let suffix = &self.raw[*start..];\n                let empty_line = if prefix.is_empty() { \"\\n\" } else { \"\" };\n                format!(\"{prefix}{fence}{manifest}{fence}{empty_line}{suffix}\")\n            }\n            Some(Embedded::Explicit(span)) => {\n                if !manifest.ends_with(\"\\n\") {\n                    manifest.push_str(\"\\n\");\n                }\n                let prefix = &self.raw[0..span.start];\n                let suffix = &self.raw[span.end..];\n                format!(\"{prefix}{manifest}{suffix}\")\n            }\n            None => manifest,\n        };\n        let new_contents_bytes = raw.as_bytes();\n\n        cargo_util::paths::write_atomic(&self.path, new_contents_bytes)\n    }\n\n    /// Lookup a dependency.\n    pub fn get_dependencies<'s>(\n        &'s self,\n        ws: &'s Workspace<'_>,\n        unstable_features: &'s Features,\n    ) -> impl Iterator<Item = (String, DepTable, CargoResult<Dependency>)> + 's {\n        let crate_root = self.path.parent().expect(\"manifest path is absolute\");\n        self.get_sections()\n            .into_iter()\n            .filter_map(move |(table_path, table)| {\n                let table = table.into_table().ok()?;\n                Some(\n                    table\n                        .into_iter()\n                        .map(|(key, item)| (table_path.clone(), key, item))\n                        .collect::<Vec<_>>(),\n                )\n            })\n            .flatten()\n            .map(move |(table_path, dep_key, dep_item)| {\n                let dep = Dependency::from_toml(\n                    ws.gctx(),\n                    ws.root(),\n                    crate_root,\n                    unstable_features,\n                    &dep_key,\n                    &dep_item,\n                );\n                (dep_key, table_path, dep)\n            })\n    }\n\n    /// Add entry to a Cargo.toml.\n    pub fn insert_into_table(\n        &mut self,\n        table_path: &[String],\n        dep: &Dependency,\n        gctx: &GlobalContext,\n        workspace_root: &Path,\n        unstable_features: &Features,\n    ) -> CargoResult<()> {\n        let crate_root = self\n            .path\n            .parent()\n            .expect(\"manifest path is absolute\")\n            .to_owned();\n        let dep_key = dep.toml_key();\n\n        let table = self\n            .get_table_mut(table_path)\n            .expect(\"manifest validated, path should be to a table\");\n        if let Some((mut dep_key, dep_item)) = table\n            .as_table_like_mut()\n            .unwrap()\n            .get_key_value_mut(dep_key)\n        {\n            dep.update_toml(\n                gctx,\n                workspace_root,\n                &crate_root,\n                unstable_features,\n                &mut dep_key,\n                dep_item,\n            )?;\n            if let Some(table) = dep_item.as_inline_table_mut() {\n                // So long as we don't have `Cargo.toml` auto-formatting and inline-tables can only\n                // be on one line, there isn't really much in the way of interesting formatting to\n                // include (no comments), so let's just wipe it clean\n                table.fmt();\n            }\n        } else {\n            let new_dependency =\n                dep.to_toml(gctx, workspace_root, &crate_root, unstable_features)?;\n            table[dep_key] = new_dependency;\n        }\n\n        Ok(())\n    }\n\n    /// Remove entry from a Cargo.toml.\n    pub fn remove_from_table(\n        &mut self,\n        table_path: &[String],\n        name: &str,\n    ) -> Result<(), MissingDependencyError> {\n        let parent_table = self\n            .get_table_mut(table_path)\n            .expect(\"manifest validated, path should be to a table\");\n\n        match parent_table.get_mut(name).filter(|t| !t.is_none()) {\n            Some(dep) => {\n                // remove the dependency\n                *dep = toml_edit::Item::None;\n\n                // remove table if empty\n                if parent_table.as_table_like().unwrap().is_empty() {\n                    *parent_table = toml_edit::Item::None;\n                }\n            }\n            None => {\n                let names = parent_table\n                    .as_table_like()\n                    .map(|t| t.iter())\n                    .into_iter()\n                    .flatten();\n                let alt_name = closest(name, names.map(|(k, _)| k), |k| k).map(|n| n.to_owned());\n\n                // Search in other tables.\n                let sections = self.get_sections();\n                let found_table_path = sections.iter().find_map(|(t, i)| {\n                    let table_path: Vec<String> =\n                        t.to_table().iter().map(|s| s.to_string()).collect();\n                    i.get(name).is_some().then(|| table_path)\n                });\n\n                return Err(MissingDependencyError {\n                    expected_name: name.to_owned(),\n                    expected_path: table_path.to_owned(),\n                    alt_name: alt_name,\n                    alt_path: found_table_path,\n                });\n            }\n        }\n\n        Ok(())\n    }\n\n    /// Allow mutating dependencies, wherever they live.\n    /// Copied from cargo-edit.\n    pub fn get_dependency_tables_mut(\n        &mut self,\n    ) -> impl Iterator<Item = &mut dyn toml_edit::TableLike> + '_ {\n        let root = self.data.as_table_mut();\n        root.iter_mut().flat_map(|(k, v)| {\n            if DepTable::KINDS\n                .iter()\n                .any(|dt| dt.kind.kind_table() == k.get())\n            {\n                v.as_table_like_mut().into_iter().collect::<Vec<_>>()\n            } else if k == \"workspace\" {\n                v.as_table_like_mut()\n                    .unwrap()\n                    .iter_mut()\n                    .filter_map(|(k, v)| {\n                        if k.get() == \"dependencies\" {\n                            v.as_table_like_mut()\n                        } else {\n                            None\n                        }\n                    })\n                    .collect::<Vec<_>>()\n            } else if k == \"target\" {\n                v.as_table_like_mut()\n                    .unwrap()\n                    .iter_mut()\n                    .flat_map(|(_, v)| {\n                        v.as_table_like_mut().into_iter().flat_map(|v| {\n                            v.iter_mut().filter_map(|(k, v)| {\n                                if DepTable::KINDS\n                                    .iter()\n                                    .any(|dt| dt.kind.kind_table() == k.get())\n                                {\n                                    v.as_table_like_mut()\n                                } else {\n                                    None\n                                }\n                            })\n                        })\n                    })\n                    .collect::<Vec<_>>()\n            } else {\n                Vec::new()\n            }\n        })\n    }\n\n    /// Remove references to `dep_key` if its no longer present.\n    pub fn gc_dep(&mut self, dep_key: &str) {\n        let explicit_dep_activation = self.is_explicit_dep_activation(dep_key);\n        let status = self.dep_status(dep_key);\n\n        if let Some(toml_edit::Item::Table(feature_table)) =\n            self.data.as_table_mut().get_mut(\"features\")\n        {\n            for (_feature, mut feature_values) in feature_table.iter_mut() {\n                if let toml_edit::Item::Value(toml_edit::Value::Array(feature_values)) =\n                    &mut feature_values\n                {\n                    fix_feature_activations(\n                        feature_values,\n                        dep_key,\n                        status,\n                        explicit_dep_activation,\n                    );\n                }\n            }\n        }\n    }\n\n    pub fn is_explicit_dep_activation(&self, dep_key: &str) -> bool {\n        if let Some(toml_edit::Item::Table(feature_table)) = self.data.as_table().get(\"features\") {\n            for values in feature_table\n                .iter()\n                .map(|(_, a)| a)\n                .filter_map(|i| i.as_value())\n                .filter_map(|v| v.as_array())\n            {\n                for value in values.iter().filter_map(|v| v.as_str()) {\n                    let value = FeatureValue::new(value.into());\n                    if let FeatureValue::Dep { dep_name } = &value {\n                        if dep_name.as_str() == dep_key {\n                            return true;\n                        }\n                    }\n                }\n            }\n        }\n\n        false\n    }\n\n    fn dep_status(&self, dep_key: &str) -> DependencyStatus {\n        let mut status = DependencyStatus::None;\n        for (_, tbl) in self.get_sections() {\n            if let toml_edit::Item::Table(tbl) = tbl {\n                if let Some(dep_item) = tbl.get(dep_key) {\n                    let optional = dep_item\n                        .get(\"optional\")\n                        .and_then(|i| i.as_value())\n                        .and_then(|i| i.as_bool())\n                        .unwrap_or(false);\n                    if optional {\n                        return DependencyStatus::Optional;\n                    } else {\n                        status = DependencyStatus::Required;\n                    }\n                }\n            }\n        }\n        status\n    }\n}\n\nimpl std::fmt::Display for LocalManifest {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.manifest.fmt(f)\n    }\n}\n\n/// Edit location for an embedded manifest\n#[derive(Clone, Debug)]\npub enum Embedded {\n    /// Manifest is implicit\n    ///\n    /// This is the insert location for a frontmatter\n    Implicit(usize),\n    /// Manifest is explicit in a frontmatter\n    ///\n    /// This is the span of the frontmatter body\n    Explicit(std::ops::Range<usize>),\n}\n\nimpl Embedded {\n    fn start() -> Self {\n        Self::Implicit(0)\n    }\n\n    fn after(after: std::ops::Range<usize>) -> Self {\n        Self::Implicit(after.end)\n    }\n\n    fn exists(exists: std::ops::Range<usize>) -> Self {\n        Self::Explicit(exists)\n    }\n}\n\n#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]\nenum DependencyStatus {\n    None,\n    Optional,\n    Required,\n}\n\nfn fix_feature_activations(\n    feature_values: &mut toml_edit::Array,\n    dep_key: &str,\n    status: DependencyStatus,\n    explicit_dep_activation: bool,\n) {\n    let remove_list: Vec<usize> = feature_values\n        .iter()\n        .enumerate()\n        .filter_map(|(idx, value)| value.as_str().map(|s| (idx, s)))\n        .filter_map(|(idx, value)| {\n            let parsed_value = FeatureValue::new(value.into());\n            match status {\n                DependencyStatus::None => match (parsed_value, explicit_dep_activation) {\n                    (FeatureValue::Feature(dep_name), false)\n                    | (FeatureValue::Dep { dep_name }, _)\n                    | (FeatureValue::DepFeature { dep_name, .. }, _) => dep_name == dep_key,\n                    _ => false,\n                },\n                DependencyStatus::Optional => false,\n                DependencyStatus::Required => match (parsed_value, explicit_dep_activation) {\n                    (FeatureValue::Feature(dep_name), false)\n                    | (FeatureValue::Dep { dep_name }, _) => dep_name == dep_key,\n                    (FeatureValue::Feature(_), true) | (FeatureValue::DepFeature { .. }, _) => {\n                        false\n                    }\n                },\n            }\n            .then(|| idx)\n        })\n        .collect();\n\n    // Remove found idx in revers order so we don't invalidate the idx.\n    for idx in remove_list.iter().rev() {\n        remove_array_index(feature_values, *idx);\n    }\n\n    if status == DependencyStatus::Required {\n        for value in feature_values.iter_mut() {\n            let parsed_value = if let Some(value) = value.as_str() {\n                FeatureValue::new(value.into())\n            } else {\n                continue;\n            };\n            if let FeatureValue::DepFeature {\n                dep_name,\n                dep_feature,\n                weak,\n            } = parsed_value\n            {\n                if dep_name == dep_key && weak {\n                    let mut new_value = toml_edit::Value::from(format!(\"{dep_name}/{dep_feature}\"));\n                    *new_value.decor_mut() = value.decor().clone();\n                    *value = new_value;\n                }\n            }\n        }\n    }\n}\n\npub fn str_or_1_len_table(item: &toml_edit::Item) -> bool {\n    item.is_str() || item.as_table_like().map(|t| t.len() == 1).unwrap_or(false)\n}\n\nfn parse_manifest_err() -> anyhow::Error {\n    anyhow::format_err!(\"unable to parse external Cargo.toml\")\n}\n\n#[derive(Debug)]\npub struct MissingDependencyError {\n    pub expected_name: String,\n    pub expected_path: Vec<String>,\n    pub alt_path: Option<Vec<String>>,\n    pub alt_name: Option<String>,\n}\n\nimpl std::fmt::Display for MissingDependencyError {\n    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let expected_name = &self.expected_name;\n        let expected_path = self.expected_path.join(\".\");\n        write!(\n            fmt,\n            \"the dependency `{expected_name}` could not be found in `{expected_path}`\"\n        )?;\n        if let Some(alt_path) = &self.alt_path {\n            let alt_path = alt_path.join(\".\");\n            write!(\n                fmt,\n                \"\\n\\nhelp: a dependency with the same name exists in `{alt_path}`\"\n            )?;\n        } else if let Some(alt_name) = &self.alt_name {\n            write!(\n                fmt,\n                \"\\n\\nhelp: a dependency with a similar name exists: `{alt_name}`\"\n            )?;\n        }\n        Ok(())\n    }\n}\n\nimpl std::error::Error for MissingDependencyError {}\n\nfn remove_array_index(array: &mut toml_edit::Array, index: usize) {\n    let value = array.remove(index);\n\n    // Captures all lines before leading whitespace\n    let prefix_lines = value\n        .decor()\n        .prefix()\n        .and_then(|p| p.as_str().expect(\"spans removed\").rsplit_once('\\n'))\n        .map(|(lines, _current)| lines);\n    // Captures all lines after trailing whitespace, before the next comma\n    let suffix_lines = value\n        .decor()\n        .suffix()\n        .and_then(|p| p.as_str().expect(\"spans removed\").split_once('\\n'))\n        .map(|(_current, lines)| lines);\n    let mut merged_lines = String::new();\n    if let Some(prefix_lines) = prefix_lines {\n        merged_lines.push_str(prefix_lines);\n        merged_lines.push('\\n');\n    }\n    if let Some(suffix_lines) = suffix_lines {\n        merged_lines.push_str(suffix_lines);\n        merged_lines.push('\\n');\n    }\n\n    let next_index = index; // Since `index` was removed, that effectively auto-advances us\n    if let Some(next) = array.get_mut(next_index) {\n        let next_decor = next.decor_mut();\n        let next_prefix = next_decor\n            .prefix()\n            .map(|s| s.as_str().expect(\"spans removed\"))\n            .unwrap_or_default();\n        merged_lines.push_str(next_prefix);\n        next_decor.set_prefix(merged_lines);\n    } else {\n        let trailing = array.trailing().as_str().expect(\"spans removed\");\n        merged_lines.push_str(trailing);\n        array.set_trailing(merged_lines);\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/toml_mut/mod.rs",
    "content": "//! Utilities for in-place editing of Cargo.toml manifests.\n//!\n//! These utilities operate only on the level of a TOML document, and generally\n//! do not perform any processing of information beyond what is required for\n//! editing. For more comprehensive usage of manifests, see\n//! [`Manifest`](crate::core::manifest::Manifest).\n//!\n//! In most cases, the entrypoint for editing is\n//! [`LocalManifest`](crate::util::toml_mut::manifest::LocalManifest),\n//! which contains editing functionality for a given manifest's dependencies.\n\npub mod dependency;\npub mod manifest;\npub mod upgrade;\n"
  },
  {
    "path": "src/cargo/util/toml_mut/upgrade.rs",
    "content": "use std::fmt::Display;\n\nuse crate::CargoResult;\n\n/// Upgrade an existing requirement to a new version.\n/// Copied from cargo-edit.\npub(crate) fn upgrade_requirement(\n    req: &str,\n    version: &semver::Version,\n) -> CargoResult<Option<(String, semver::VersionReq)>> {\n    let req_text = req.to_string();\n    let raw_req = semver::VersionReq::parse(&req_text)\n        .expect(\"semver to generate valid version requirements\");\n    if raw_req.comparators.is_empty() {\n        // Empty matches everything, no-change.\n        Ok(None)\n    } else {\n        let comparators: Vec<_> = raw_req\n            .comparators\n            .into_iter()\n            // Don't downgrade if pre-release was used, see https://github.com/rust-lang/cargo/issues/14178 and https://github.com/rust-lang/cargo/issues/13290.\n            .filter(|p| p.pre.is_empty() || matches_greater(p, version))\n            .map(|p| set_comparator(p, version))\n            .collect::<CargoResult<_>>()?;\n        if comparators.is_empty() {\n            return Ok(None);\n        }\n        let new_req = semver::VersionReq { comparators };\n        let mut new_req_text = new_req.to_string();\n        if new_req_text.starts_with('^') && !req.starts_with('^') {\n            new_req_text.remove(0);\n        }\n        // Validate contract\n        #[cfg(debug_assertions)]\n        {\n            assert!(\n                new_req.matches(version),\n                \"New req {} is invalid, because {} does not match {}\",\n                new_req_text,\n                new_req,\n                version\n            )\n        }\n        if new_req_text == req_text {\n            Ok(None)\n        } else {\n            Ok(Some((new_req_text, new_req)))\n        }\n    }\n}\n\nfn set_comparator(\n    mut pred: semver::Comparator,\n    version: &semver::Version,\n) -> CargoResult<semver::Comparator> {\n    match pred.op {\n        semver::Op::Wildcard => {\n            pred.major = version.major;\n            if pred.minor.is_some() {\n                pred.minor = Some(version.minor);\n            }\n            if pred.patch.is_some() {\n                pred.patch = Some(version.patch);\n            }\n            Ok(pred)\n        }\n        semver::Op::Exact => Ok(assign_partial_req(version, pred)),\n        semver::Op::Greater | semver::Op::GreaterEq | semver::Op::Less | semver::Op::LessEq => {\n            let user_pred = pred.to_string();\n            Err(unsupported_version_req(user_pred))\n        }\n        semver::Op::Tilde => Ok(assign_partial_req(version, pred)),\n        semver::Op::Caret => Ok(assign_partial_req(version, pred)),\n        _ => {\n            let user_pred = pred.to_string();\n            Err(unsupported_version_req(user_pred))\n        }\n    }\n}\n\n// See https://github.com/dtolnay/semver/blob/69efd3cc770ead273a06ad1788477b3092996d29/src/eval.rs#L64-L88\nfn matches_greater(cmp: &semver::Comparator, ver: &semver::Version) -> bool {\n    if ver.major != cmp.major {\n        return ver.major > cmp.major;\n    }\n\n    match cmp.minor {\n        None => return false,\n        Some(minor) => {\n            if ver.minor != minor {\n                return ver.minor > minor;\n            }\n        }\n    }\n\n    match cmp.patch {\n        None => return false,\n        Some(patch) => {\n            if ver.patch != patch {\n                return ver.patch > patch;\n            }\n        }\n    }\n\n    ver.pre > cmp.pre\n}\n\nfn assign_partial_req(\n    version: &semver::Version,\n    mut pred: semver::Comparator,\n) -> semver::Comparator {\n    pred.major = version.major;\n    if pred.minor.is_some() {\n        pred.minor = Some(version.minor);\n    }\n    if pred.patch.is_some() {\n        pred.patch = Some(version.patch);\n    }\n    pred.pre = version.pre.clone();\n    pred\n}\n\nfn unsupported_version_req(req: impl Display) -> anyhow::Error {\n    anyhow::format_err!(\"Support for modifying {} is currently unsupported\", req)\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n\n    mod upgrade_requirement {\n        use super::*;\n\n        #[track_caller]\n        fn assert_req_bump<'a, O: Into<Option<&'a str>>>(version: &str, req: &str, expected: O) {\n            let version = semver::Version::parse(version).unwrap();\n            let actual = upgrade_requirement(req, &version)\n                .unwrap()\n                .map(|(actual, _req)| actual);\n            let expected = expected.into();\n            assert_eq!(actual.as_deref(), expected);\n        }\n\n        #[test]\n        fn wildcard_major() {\n            assert_req_bump(\"1.0.0\", \"*\", None);\n        }\n\n        #[test]\n        fn wildcard_minor() {\n            assert_req_bump(\"1.0.0\", \"1.*\", None);\n            assert_req_bump(\"1.1.0\", \"1.*\", None);\n            assert_req_bump(\"2.0.0\", \"1.*\", \"2.*\");\n        }\n\n        #[test]\n        fn wildcard_patch() {\n            assert_req_bump(\"1.0.0\", \"1.0.*\", None);\n            assert_req_bump(\"1.1.0\", \"1.0.*\", \"1.1.*\");\n            assert_req_bump(\"1.1.1\", \"1.0.*\", \"1.1.*\");\n            assert_req_bump(\"2.0.0\", \"1.0.*\", \"2.0.*\");\n        }\n\n        #[test]\n        fn caret_major() {\n            assert_req_bump(\"1.0.0\", \"1\", None);\n            assert_req_bump(\"1.0.0\", \"^1\", None);\n\n            assert_req_bump(\"1.1.0\", \"1\", None);\n            assert_req_bump(\"1.1.0\", \"^1\", None);\n\n            assert_req_bump(\"2.0.0\", \"1\", \"2\");\n            assert_req_bump(\"2.0.0\", \"^1\", \"^2\");\n        }\n\n        #[test]\n        fn caret_minor() {\n            assert_req_bump(\"1.0.0\", \"1.0\", None);\n            assert_req_bump(\"1.0.0\", \"^1.0\", None);\n\n            assert_req_bump(\"1.1.0\", \"1.0\", \"1.1\");\n            assert_req_bump(\"1.1.0\", \"^1.0\", \"^1.1\");\n\n            assert_req_bump(\"1.1.1\", \"1.0\", \"1.1\");\n            assert_req_bump(\"1.1.1\", \"^1.0\", \"^1.1\");\n\n            assert_req_bump(\"2.0.0\", \"1.0\", \"2.0\");\n            assert_req_bump(\"2.0.0\", \"^1.0\", \"^2.0\");\n        }\n\n        #[test]\n        fn caret_patch() {\n            assert_req_bump(\"1.0.0\", \"1.0.0\", None);\n            assert_req_bump(\"1.0.0\", \"^1.0.0\", None);\n\n            assert_req_bump(\"1.1.0\", \"1.0.0\", \"1.1.0\");\n            assert_req_bump(\"1.1.0\", \"^1.0.0\", \"^1.1.0\");\n\n            assert_req_bump(\"1.1.1\", \"1.0.0\", \"1.1.1\");\n            assert_req_bump(\"1.1.1\", \"^1.0.0\", \"^1.1.1\");\n\n            assert_req_bump(\"2.0.0\", \"1.0.0\", \"2.0.0\");\n            assert_req_bump(\"2.0.0\", \"^1.0.0\", \"^2.0.0\");\n        }\n\n        #[test]\n        fn tilde_major() {\n            assert_req_bump(\"1.0.0\", \"~1\", None);\n            assert_req_bump(\"1.1.0\", \"~1\", None);\n            assert_req_bump(\"2.0.0\", \"~1\", \"~2\");\n        }\n\n        #[test]\n        fn tilde_minor() {\n            assert_req_bump(\"1.0.0\", \"~1.0\", None);\n            assert_req_bump(\"1.1.0\", \"~1.0\", \"~1.1\");\n            assert_req_bump(\"1.1.1\", \"~1.0\", \"~1.1\");\n            assert_req_bump(\"2.0.0\", \"~1.0\", \"~2.0\");\n        }\n\n        #[test]\n        fn tilde_patch() {\n            assert_req_bump(\"1.0.0\", \"~1.0.0\", None);\n            assert_req_bump(\"1.1.0\", \"~1.0.0\", \"~1.1.0\");\n            assert_req_bump(\"1.1.1\", \"~1.0.0\", \"~1.1.1\");\n            assert_req_bump(\"2.0.0\", \"~1.0.0\", \"~2.0.0\");\n        }\n\n        #[test]\n        fn equal_major() {\n            assert_req_bump(\"1.0.0\", \"=1\", None);\n            assert_req_bump(\"1.1.0\", \"=1\", None);\n            assert_req_bump(\"2.0.0\", \"=1\", \"=2\");\n        }\n\n        #[test]\n        fn equal_minor() {\n            assert_req_bump(\"1.0.0\", \"=1.0\", None);\n            assert_req_bump(\"1.1.0\", \"=1.0\", \"=1.1\");\n            assert_req_bump(\"1.1.1\", \"=1.0\", \"=1.1\");\n            assert_req_bump(\"2.0.0\", \"=1.0\", \"=2.0\");\n        }\n\n        #[test]\n        fn equal_patch() {\n            assert_req_bump(\"1.0.0\", \"=1.0.0\", None);\n            assert_req_bump(\"1.1.0\", \"=1.0.0\", \"=1.1.0\");\n            assert_req_bump(\"1.1.1\", \"=1.0.0\", \"=1.1.1\");\n            assert_req_bump(\"2.0.0\", \"=1.0.0\", \"=2.0.0\");\n        }\n\n        #[test]\n        fn greater_prerelease() {\n            assert_req_bump(\"1.7.0\", \"2.0.0-beta.21\", None);\n            assert_req_bump(\"1.7.0\", \"=2.0.0-beta.21\", None);\n            assert_req_bump(\"1.7.0\", \"~2.0.0-beta.21\", None);\n            assert_req_bump(\"2.0.0-beta.20\", \"2.0.0-beta.21\", None);\n            assert_req_bump(\"2.0.0-beta.21\", \"2.0.0-beta.21\", None);\n            assert_req_bump(\"2.0.0-beta.22\", \"2.0.0-beta.21\", \"2.0.0-beta.22\");\n            assert_req_bump(\"2.0.0\", \"2.0.0-beta.21\", \"2.0.0\");\n            assert_req_bump(\"3.0.0\", \"2.0.0-beta.21\", \"3.0.0\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/vcs.rs",
    "content": "use crate::util::CargoResult;\nuse cargo_util::ProcessBuilder;\nuse cargo_util::paths;\nuse std::path::Path;\n\n// Check if we are in an existing repo. We define that to be true if either:\n//\n// 1. We are in a git repo and the path to the new package is not an ignored\n//    path in that repo.\n// 2. We are in an HG repo.\npub fn existing_vcs_repo(path: &Path, cwd: &Path) -> bool {\n    fn in_git_repo(path: &Path, cwd: &Path) -> bool {\n        if let Ok(repo) = GitRepo::discover(path, cwd) {\n            // Don't check if the working directory itself is ignored.\n            if repo.workdir().map_or(false, |workdir| workdir == path) {\n                true\n            } else {\n                !repo.is_path_ignored(path).unwrap_or(false)\n            }\n        } else {\n            false\n        }\n    }\n\n    in_git_repo(path, cwd) || HgRepo::discover(path, cwd).is_ok()\n}\n\npub struct HgRepo;\npub struct GitRepo;\npub struct PijulRepo;\npub struct FossilRepo;\n\nimpl GitRepo {\n    pub fn init(path: &Path, _: &Path) -> CargoResult<GitRepo> {\n        git2::Repository::init(path)?;\n        Ok(GitRepo)\n    }\n    pub fn discover(path: &Path, _: &Path) -> Result<git2::Repository, git2::Error> {\n        git2::Repository::discover(path)\n    }\n}\n\nimpl HgRepo {\n    pub fn init(path: &Path, cwd: &Path) -> CargoResult<HgRepo> {\n        ProcessBuilder::new(\"hg\")\n            .cwd(cwd)\n            .arg(\"init\")\n            .arg(\"--\")\n            .arg(path)\n            .exec()?;\n        Ok(HgRepo)\n    }\n    pub fn discover(path: &Path, cwd: &Path) -> CargoResult<HgRepo> {\n        ProcessBuilder::new(\"hg\")\n            .cwd(cwd)\n            .arg(\"--cwd\")\n            .arg(path)\n            .arg(\"root\")\n            .exec_with_output()?;\n        Ok(HgRepo)\n    }\n}\n\nimpl PijulRepo {\n    pub fn init(path: &Path, cwd: &Path) -> CargoResult<PijulRepo> {\n        ProcessBuilder::new(\"pijul\")\n            .cwd(cwd)\n            .arg(\"init\")\n            .arg(\"--\")\n            .arg(path)\n            .exec()?;\n        Ok(PijulRepo)\n    }\n}\n\nimpl FossilRepo {\n    pub fn init(path: &Path, cwd: &Path) -> CargoResult<FossilRepo> {\n        // fossil doesn't create the directory so we'll do that first\n        paths::create_dir_all(path)?;\n\n        // set up the paths we'll use\n        let db_fname = \".fossil\";\n        let mut db_path = path.to_owned();\n        db_path.push(db_fname);\n\n        // then create the fossil DB in that location\n        ProcessBuilder::new(\"fossil\")\n            .cwd(cwd)\n            .arg(\"init\")\n            .arg(\"--\")\n            .arg(&db_path)\n            .exec()?;\n\n        // open it in that new directory\n        ProcessBuilder::new(\"fossil\")\n            .cwd(&path)\n            .arg(\"open\")\n            .arg(\"--\")\n            .arg(db_fname)\n            .exec()?;\n\n        Ok(FossilRepo)\n    }\n}\n"
  },
  {
    "path": "src/cargo/util/workspace.rs",
    "content": "use crate::core::compiler::Unit;\nuse crate::core::manifest::TargetSourcePath;\nuse crate::core::{Target, Workspace};\nuse crate::ops::CompileOptions;\nuse crate::util::CargoResult;\nuse anyhow::bail;\nuse cargo_util::ProcessBuilder;\nuse cargo_util::paths::normalize_path;\nuse std::fmt::Write;\nuse std::path::Path;\nuse std::path::PathBuf;\n\nconst ITEM_INDENT: &str = \"    \";\n\nfn get_available_targets<'a>(\n    filter_fn: fn(&Target) -> bool,\n    ws: &'a Workspace<'_>,\n    options: &'a CompileOptions,\n) -> CargoResult<Vec<(&'a str, &'a Path)>> {\n    let packages = options.spec.get_packages(ws)?;\n\n    let mut targets: Vec<_> = packages\n        .into_iter()\n        .flat_map(|pkg| {\n            pkg.manifest()\n                .targets()\n                .iter()\n                .filter(|target| filter_fn(target))\n        })\n        .map(|target| {\n            (\n                target.name(),\n                target.src_path().path().expect(\"Target is not a `Metabuild` but one of `Bin` | `Test` | `Bench` | `ExampleBin`\")\n            )\n        })\n        .collect();\n\n    targets.sort();\n\n    Ok(targets)\n}\n\nfn print_available_targets(\n    filter_fn: fn(&Target) -> bool,\n    ws: &Workspace<'_>,\n    options: &CompileOptions,\n    option_name: &str,\n    plural_name: &str,\n) -> CargoResult<()> {\n    let targets = get_available_targets(filter_fn, ws, options)?;\n\n    let mut output = String::new();\n    writeln!(output, \"\\\"{}\\\" takes one argument.\", option_name)?;\n\n    if targets.is_empty() {\n        writeln!(output, \"No {} available.\", plural_name)?;\n    } else {\n        writeln!(output, \"Available {}:\", plural_name)?;\n        let mut shell = ws.gctx().shell();\n        for (name, src_path) in targets {\n            let link = shell.err_file_hyperlink(src_path);\n            writeln!(output, \"{ITEM_INDENT}{link}{}{link:#}\", name)?;\n        }\n    }\n    bail!(\"{}\", output)\n}\n\npub fn print_available_packages(ws: &Workspace<'_>) -> CargoResult<()> {\n    let packages = ws\n        .members()\n        .map(|pkg| (pkg.name().as_str(), pkg.manifest_path()))\n        .collect::<Vec<_>>();\n\n    let mut output = \"\\\"--package <SPEC>\\\" requires a SPEC format value, \\\n        which can be any package ID specifier in the dependency graph.\\n\\\n        Run `cargo help pkgid` for more information about SPEC format.\\n\\n\"\n        .to_string();\n\n    if packages.is_empty() {\n        // This would never happen.\n        // Just in case something regresses we covers it here.\n        writeln!(output, \"No packages available.\")?;\n    } else {\n        writeln!(output, \"Possible packages/workspace members:\")?;\n        let mut shell = ws.gctx().shell();\n        for (name, manifest_path) in packages {\n            let link = shell.err_file_hyperlink(manifest_path);\n            writeln!(output, \"{ITEM_INDENT}{link}{}{link:#}\", name)?;\n        }\n    }\n    bail!(\"{}\", output)\n}\n\npub fn print_available_examples(ws: &Workspace<'_>, options: &CompileOptions) -> CargoResult<()> {\n    print_available_targets(Target::is_example, ws, options, \"--example\", \"examples\")\n}\n\npub fn print_available_binaries(ws: &Workspace<'_>, options: &CompileOptions) -> CargoResult<()> {\n    print_available_targets(Target::is_bin, ws, options, \"--bin\", \"binaries\")\n}\n\npub fn print_available_benches(ws: &Workspace<'_>, options: &CompileOptions) -> CargoResult<()> {\n    print_available_targets(Target::is_bench, ws, options, \"--bench\", \"bench targets\")\n}\n\npub fn print_available_tests(ws: &Workspace<'_>, options: &CompileOptions) -> CargoResult<()> {\n    print_available_targets(Target::is_test, ws, options, \"--test\", \"test targets\")\n}\n\n/// The source path and its current dir for use in compilation.\n///\n/// The path that we pass to rustc is actually fairly important because it will\n/// show up in error messages (important for readability), debug information\n/// (important for caching), etc. As a result we need to be pretty careful how we\n/// actually invoke rustc.\n///\n/// In general users don't expect `cargo build` to cause rebuilds if you change\n/// directories. That could be if you just change directories in the package or\n/// if you literally move the whole package wholesale to a new directory. As a\n/// result we mostly don't factor in `cwd` to this calculation. Instead we try to\n/// track the workspace as much as possible and we update the current directory\n/// of rustc/rustdoc where appropriate.\n///\n/// The first returned value here is the argument to pass to rustc, and the\n/// second is the cwd that rustc should operate in.\npub fn path_args(ws: &Workspace<'_>, unit: &Unit) -> (PathBuf, PathBuf) {\n    let src = match unit.target.src_path() {\n        TargetSourcePath::Path(path) => path.to_path_buf(),\n        TargetSourcePath::Metabuild => unit.pkg.manifest().metabuild_path(ws.build_dir()),\n    };\n    assert!(src.is_absolute());\n    if unit.pkg.package_id().source_id().is_path() {\n        // Determine which path we make this relative to: usually it's the workspace root,\n        // but this can be overwritten with a `-Z` flag.\n        let root = match &ws.gctx().cli_unstable().root_dir {\n            None => ws.root().to_owned(),\n            Some(root_dir) => normalize_path(&ws.gctx().cwd().join(root_dir)),\n        };\n        if let Ok(path) = src.strip_prefix(&root) {\n            return (path.to_path_buf(), root);\n        }\n    }\n    (src, unit.pkg.root().to_path_buf())\n}\n\npub fn add_path_args(ws: &Workspace<'_>, unit: &Unit, cmd: &mut ProcessBuilder) {\n    let (arg, cwd) = path_args(ws, unit);\n    cmd.arg(arg);\n    cmd.cwd(cwd);\n}\n"
  },
  {
    "path": "src/cargo/version.rs",
    "content": "//! Code for representing cargo's release version number.\n\nuse std::fmt;\n\n/// Information about the git repository where cargo was built from.\npub struct CommitInfo {\n    pub short_commit_hash: String,\n    pub commit_hash: String,\n    pub commit_date: String,\n}\n\n/// Cargo's version.\npub struct VersionInfo {\n    /// Cargo's version, such as \"1.57.0\", \"1.58.0-beta.1\", \"1.59.0-nightly\", etc.\n    pub version: String,\n    /// The release channel we were built for (stable/beta/nightly/dev).\n    ///\n    /// `None` if not built via bootstrap.\n    pub release_channel: Option<String>,\n    /// Information about the Git repository we may have been built from.\n    ///\n    /// `None` if not built from a git repo.\n    pub commit_info: Option<CommitInfo>,\n\n    /// A descriptive string to be appended to version output.\n    ///\n    /// This is usually set by the bootstrap in rust-lang/rust\n    /// via the `CFG_VER_DESCRIPTION` environment variable.\n    /// Useful for showing vendor build information.\n    /// For example,\n    ///\n    /// ```text\n    /// cargo 1.85.0 (d73d2caf9 2024-12-31) (MyCustomBuild 1.85.0-3)\n    /// ```\n    pub description: Option<String>,\n}\n\nimpl fmt::Display for VersionInfo {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{}\", self.version)?;\n\n        if let Some(ref ci) = self.commit_info {\n            write!(f, \" ({} {})\", ci.short_commit_hash, ci.commit_date)?;\n        };\n\n        if let Some(description) = self.description.as_ref().filter(|d| !d.is_empty()) {\n            write!(f, \" ({description})\")?;\n        };\n        Ok(())\n    }\n}\n\n/// Returns information about cargo's version.\npub fn version() -> VersionInfo {\n    macro_rules! option_env_str {\n        ($name:expr) => {\n            option_env!($name).map(|s| s.to_string())\n        };\n    }\n\n    // This is the version set in bootstrap, which we use to match rustc.\n    let version = option_env_str!(\"CFG_RELEASE\").unwrap_or_else(|| {\n        // If cargo is not being built by bootstrap, then we just use the\n        // version from cargo's own `Cargo.toml`.\n        //\n        // There are two versions at play here:\n        //   - version of cargo-the-binary, which you see when you type `cargo --version`\n        //   - version of cargo-the-library, which you download from crates.io for use\n        //     in your packages.\n        //\n        // The library is permanently unstable, so it always has a 0 major\n        // version. However, the CLI now reports a stable 1.x version\n        // (starting in 1.26) which stays in sync with rustc's version.\n        //\n        // Coincidentally, the minor version for cargo-the-library is always\n        // +1 of rustc's minor version (that is, `rustc 1.11.0` corresponds to\n        // `cargo `0.12.0`). The versions always get bumped in lockstep, so\n        // this should continue to hold.\n        let minor = env!(\"CARGO_PKG_VERSION_MINOR\").parse::<u8>().unwrap() - 1;\n        let patch = env!(\"CARGO_PKG_VERSION_PATCH\").parse::<u8>().unwrap();\n        format!(\"1.{}.{}\", minor, patch)\n    });\n\n    let release_channel = option_env_str!(\"CFG_RELEASE_CHANNEL\");\n    let commit_info = option_env_str!(\"CARGO_COMMIT_HASH\").map(|commit_hash| CommitInfo {\n        short_commit_hash: option_env_str!(\"CARGO_COMMIT_SHORT_HASH\").unwrap(),\n        commit_hash,\n        commit_date: option_env_str!(\"CARGO_COMMIT_DATE\").unwrap(),\n    });\n    let description = option_env_str!(\"CFG_VER_DESCRIPTION\");\n\n    VersionInfo {\n        version,\n        release_channel,\n        commit_info,\n        description,\n    }\n}\n"
  },
  {
    "path": "src/doc/.gitignore",
    "content": "# Ignore built book\nbook/\n"
  },
  {
    "path": "src/doc/README.md",
    "content": "## Contributing\n\nTo contribute to Cargo's documentation. See <https://rust-lang.github.io/cargo/contrib/>.\n\nFor docs specific topics, see <https://rust-lang.github.io/cargo/contrib/documentation>.\n\nFor API doc, see <https://docs.rs/cargo>.\n"
  },
  {
    "path": "src/doc/book.toml",
    "content": "[book]\ntitle = \"The Cargo Book\"\nauthors = [\"Alex Crichton\", \"Steve Klabnik\", \"Carol Nichols\", \"with contributions from the Rust community\"]\n\n[output.html]\nadditional-css = [\"theme/cargo.css\"]\nsmart-punctuation = true # Enable smart-punctuation feature for more than quotes.\ngit-repository-url = \"https://github.com/rust-lang/cargo/tree/master/src/doc/src\"\nedit-url-template = \"https://github.com/rust-lang/cargo/edit/master/src/doc/{path}\"\n\n[output.html.search]\nuse-boolean-and = true\n\n[output.html.search.chapter]\n\"CHANGELOG.md\" = { enable = false }\n\n[output.html.redirect]\n\"/commands/cargo-git-checkout.html\" = \"./deprecated-and-removed.html\"\n\"/commands/cargo-read-manifest.html\" = \"./deprecated-and-removed.html\"\n\"/commands/cargo-verify-project.html\" = \"./deprecated-and-removed.html\"\n\"/guide/build-cache.html\" = \"../reference/build-cache.html\"\n\"/reference/manifest.html#building-dynamic-or-static-libraries\" = \"cargo-targets.html#the-crate-type-field\"\n\"/reference/manifest.html#configuring-a-target\" = \"cargo-targets.html#configuring-a-target\"\n\"/reference/manifest.html#examples\" = \"cargo-targets.html#examples\"\n\"/reference/manifest.html#integration-tests\" = \"cargo-targets.html#integration-tests\"\n\"/reference/manifest.html#package-build\" = \"manifest.html#the-build-field\"\n\"/reference/manifest.html#package-metadata\" = \"manifest.html#the-package-section\"\n\"/reference/manifest.html#package-selection\" = \"workspaces.html#package-selection\"\n\"/reference/manifest.html#rules\" = \"features.html\"\n\"/reference/manifest.html#rust-version\" = \"rust-version.html\"\n\"/reference/manifest.html#target-auto-discovery\" = \"cargo-targets.html#target-auto-discovery\"\n\"/reference/manifest.html#tests\" = \"cargo-targets.html#tests\"\n\"/reference/manifest.html#the-authors-field-optional\" = \"manifest.html#the-authors-field\"\n\"/reference/manifest.html#the-build-field-optional\" = \"manifest.html#the-build-field\"\n\"/reference/manifest.html#the-documentation-field-optional\" = \"manifest.html#the-documentation-field\"\n\"/reference/manifest.html#the-edition-field-optional\" = \"manifest.html#the-edition-field\"\n\"/reference/manifest.html#the-exclude-and-include-fields-optional\" = \"manifest.html#the-exclude-and-include-fields\"\n\"/reference/manifest.html#the-features-section\" = \"features.html#the-features-section\"\n\"/reference/manifest.html#the-links-field-optional\" = \"manifest.html#the-links-field\"\n\"/reference/manifest.html#the-metadata-table-optional\" = \"manifest.html#the-metadata-table\"\n\"/reference/manifest.html#the-patch-section\" = \"overriding-dependencies.html#the-patch-section\"\n\"/reference/manifest.html#the-project-layout\" = \"../guide/project-layout.html\"\n\"/reference/manifest.html#the-publish--field-optional\" = \"manifest.html#the-publish-field\"\n\"/reference/manifest.html#the-replace-section\" = \"overriding-dependencies.html#the-replace-section\"\n\"/reference/manifest.html#the-required-features-field-optional\" = \"cargo-targets.html#the-required-features-field\"\n\"/reference/manifest.html#the-workspace--field-optional\" = \"manifest.html#the-workspace-field\"\n\"/reference/manifest.html#the-workspace-section\" = \"workspaces.html#the-workspace-section\"\n\"/reference/manifest.html#usage-in-end-products\" = \"features.html\"\n\"/reference/manifest.html#usage-in-packages\" = \"features.html\"\n\"/reference/manifest.html#using-patch-with-multiple-versions\" = \"overriding-dependencies.html#using-patch-with-multiple-versions\"\n\"/reference/manifest.html#virtual-workspace\" = \"workspaces.html\"\n\"/reference/registries.html#index-format\" = \"registry-index.html\"\n\"/reference/registries.html#login\" = \"registry-web-api.html#login\"\n\"/reference/registries.html#owners\" = \"registry-web-api.html#owners\"\n\"/reference/registries.html#owners-add\" = \"registry-web-api.html#owners-add\"\n\"/reference/registries.html#owners-list\" = \"registry-web-api.html#owners-list\"\n\"/reference/registries.html#owners-remove\" = \"registry-web-api.html#owners-remove\"\n\"/reference/registries.html#publish\" = \"registry-web-api.html#publish\"\n\"/reference/registries.html#running-a-registry\" = \"running-a-registry.html\"\n\"/reference/registries.html#search\" = \"registry-web-api.html#search\"\n\"/reference/registries.html#unyank\" = \"registry-web-api.html#unyank\"\n\"/reference/registries.html#web-api\" = \"registry-web-api.html\"\n\"/reference/registries.html#yank\" = \"registry-web-api.html#yank\"\n\"/reference/resolver.html#other-constraints\" = \"#constraints-and-heuristics\"\n\"/reference/resolver.html#pre-releases\" = \"specifying-dependencies.html#pre-releases\"\n\"/reference/resolver.html#version-metadata\" = \"specifying-dependencies.html#version-metadata\"\n\"/reference/specifying-dependencies.html#overriding-dependencies\" = \"overriding-dependencies.html\"\n\"/reference/specifying-dependencies.html#overriding-repository-url\" = \"overriding-dependencies.html#overriding-repository-url\"\n\"/reference/specifying-dependencies.html#overriding-with-local-dependencies\" = \"overriding-dependencies.html#paths-overrides\"\n\"/reference/specifying-dependencies.html#prepublishing-a-breaking-change\" = \"overriding-dependencies.html#prepublishing-a-breaking-change\"\n\"/reference/specifying-dependencies.html#testing-a-bugfix\" = \"overriding-dependencies.html#testing-a-bugfix\"\n\"/reference/specifying-dependencies.html#working-with-an-unpublished-minor-version\" = \"overriding-dependencies.html#working-with-an-unpublished-minor-version\"\n\"/reference/workspaces.html#virtual-manifest\" = \"workspaces.html#virtual-workspace\"\n"
  },
  {
    "path": "src/doc/contrib/README.md",
    "content": "# Cargo Contributor Guide\n\nThis is the source of the Cargo Contributor Guide, published at\n<https://rust-lang.github.io/cargo/contrib/>. It is written in Markdown, using\nthe [mdbook] tool to convert to HTML. If you are editing these pages, the best\noption to view the results is to run `mdbook serve`, which will start a web\nserver on localhost that you can visit to view the book, and it will\nautomatically reload each time you edit a page.\n\nThis is published via GitHub Actions to GitHub Pages.\n\n[mdbook]: https://rust-lang.github.io/mdBook/\n"
  },
  {
    "path": "src/doc/contrib/book.toml",
    "content": "[book]\ntitle = \"Cargo Contributor Guide\"\nauthors = [\"Eric Huss\"]\n\n[output.html]\ngit-repository-url = \"https://github.com/rust-lang/cargo/tree/master/src/doc/contrib/src\"\nedit-url-template = \"https://github.com/rust-lang/cargo/edit/master/src/doc/contrib/{path}\"\nsearch.use-boolean-and = true\n\n[output.html.redirect]\n\"/apidoc/cargo/index.html\" = \"https://doc.rust-lang.org/nightly/nightly-rustc/cargo/\"\n\"/architecture/index.html\" = \"../implementation/architecture.html\"\n\"/architecture/console.html\" = \"../implementation/console.html\"\n\"/architecture/subcommands.html\" = \"../implementation/subcommands.html\"\n\"/architecture/codebase.html\" = \"https://doc.rust-lang.org/nightly/nightly-rustc/cargo\"\n\"/architecture/compilation.html\" = \"https://doc.rust-lang.org/nightly/nightly-rustc/cargo\"\n\"/architecture/files.html\" = \"https://doc.rust-lang.org/nightly/nightly-rustc/cargo\"\n\"/architecture/packages.html\" = \"https://doc.rust-lang.org/nightly/nightly-rustc/cargo\"\n"
  },
  {
    "path": "src/doc/contrib/src/SUMMARY.md",
    "content": "# Summary\n\n- [Introduction](./index.md)\n- [Issue Tracker](./issues.md)\n- [Cargo Team](./team.md)\n- [Process](./process/index.md)\n    - [Working on Cargo](./process/working-on-cargo.md)\n    - [Release process](./process/release.md)\n    - [Writing an RFC](./process/rfc.md)\n    - [Unstable features](./process/unstable.md)\n    - [Security issues](./process/security.md)\n- [Design Principles](./design.md)\n- [Implementing a Change](./implementation/index.md)\n    - [Architecture](./implementation/architecture.md)\n    - [New packages](./implementation/packages.md)\n    - [New subcommands](./implementation/subcommands.md)\n    - [Data Schemas](./implementation/schemas.md)\n    - [Console Output](./implementation/console.md)\n    - [Filesystem](./implementation/filesystem.md)\n    - [Formatting](./implementation/formatting.md)\n    - [Debugging](./implementation/debugging.md)\n- [Tests](./tests/index.md)\n    - [Running Tests](./tests/running.md)\n    - [Writing Tests](./tests/writing.md)\n    - [Benchmarking and Profiling](./tests/profiling.md)\n    - [Crater](./tests/crater.md)\n- [Documentation](./documentation/index.md)\n"
  },
  {
    "path": "src/doc/contrib/src/design.md",
    "content": "# Design Principles\n\nThe purpose of Cargo is to formalize a canonical Rust workflow, by automating\nthe standard tasks associated with distributing software. Cargo simplifies\nstructuring a new project, adding dependencies, writing and running unit\ntests, and more.\n\nCargo is not intended to be a general-purpose build tool. Ideally, it should\nbe easy to integrate it within another build tool, though admittedly that is\nnot as seamless as desired.\n\n## Stability and compatibility\n\n### Backwards compatibility\n\nCargo strives to remain backwards compatible with projects created in previous\nversions. The CLI interface also strives to remain backwards compatible, such\nthat the commands and options behave the same. That being said, changes in\nbehavior, and even outright breakage are sometimes done in limited situations.\nThe following outlines some situations where backwards-incompatible changes are\nmade:\n\n* Anything that addresses a security concern.\n* Dropping support for older platforms and tooling. Cargo follows the Rust\n  [tiered platform support].\n* Changes to resolve possibly unsafe or unreliable behavior.\n\nNone of these changes should be taken lightly, and should be avoided if\npossible, or possibly with some transition period to alert the user of the\npotential change.\n\nBehavior is sometimes changed in ways that have a high confidence that it\nwon't break existing workflows. Almost every change carries this risk, so it\nis often a judgment call balancing the benefit of the change with the\nperceived possibility of its negative consequences.\n\nAt times, some changes fall in the gray area, where the current behavior is\nundocumented, or not working as intended. These are more difficult judgment\ncalls. The general preference is to balance towards avoiding breaking existing\nworkflows.\n\nSupport for older registry APIs and index formats may be dropped, if there is\nhigh confidence that there aren't any active registries that may be affected.\nThis has never (to my knowledge) happened so far, and is unlikely to happen in\nthe future, but remains a possibility.\n\nIn all of the above, a transition period may be employed if a change is known\nto cause breakage. A warning can be issued to alert the user that something\nwill change, and provide them with an alternative to resolve the issue\n(preferably in a way that is compatible across versions if possible).\n\nCargo is only expected to work with the version of the related Rust tools\n(`rustc`, `rustdoc`, etc.) that it is released with. As a matter of choice,\nthe latest nightly works with the most recent stable release, but that is\nmostly to accommodate development of Cargo itself, and should not be expected\nby users.\n\n### Forwards compatibility\n\nAdditionally, Cargo strives a limited degree of *forwards compatibility*.\nChanges should not egregiously prevent older versions from working. This is\nmostly relevant for persistent data, such as on-disk files and the registry\ninterface and index. It also applies to a lesser degree to the registry API.\n\nChanges to `Cargo.lock` require a transition time, where the new format is not\nautomatically written when the lock file is updated. The transition time\nshould not be less than 6 months, though preferably longer. New projects may\nuse the new format in a shorter time frame.\n\nChanges to `Cargo.toml` can be made in any release. This is because the user\nmust manually modify the file, and opt-in to any new changes. Additionally,\nCargo will usually only issue a warning about new fields it doesn't\nunderstand, but otherwise continue to function.\n\nChanges to cache files (such as artifacts in the `target` directory, or cached\ndata in Cargo's home directory) should not *prevent* older versions from\nrunning, but they may cause older versions to recreate the cache, which may\nresult in a performance impact.\n\nChanges to the registry index should not prevent older versions from working.\nGenerally, older versions ignore new fields, so the format should be easily\nextensible. Changes to the format or interpretation of existing fields should\nbe done very carefully to avoid preventing older versions of Cargo from\nworking. In some cases, this may mean that older versions of Cargo will not be\nable to *select* a newly published crate, but it shouldn't prevent them from\nworking at all. This level of compatibility may not last forever, but the\nexact time frame for such a change has not yet been decided.\n\nThe registry API may be changed in such a way to prevent older versions of\nCargo from working. Generally, compatibility should be retained for as long as\npossible, but the exact length of time is not specified.\n\n## Simplicity and layers\n\nStandard workflows should be easy and consistent. Each knob that is added has\na high cost, regardless if it is intended for a small audience. Layering and\ndefaults can help avoid the surface area that the user needs to be concerned\nwith. Try to avoid small functionalities that may have complex interactions\nwith one another.\n\n[tiered platform support]: https://doc.rust-lang.org/nightly/rustc/platform-support.html\n"
  },
  {
    "path": "src/doc/contrib/src/documentation/index.md",
    "content": "# Documentation\n\nCargo has several types of documentation that contributors work with:\n\n* [The Cargo Book]\n  * The primary user-facing Cargo documentation\n  * Source at <https://github.com/rust-lang/cargo/tree/master/src/doc>\n  * Built with [mdbook]\n  * Published through [\"the doc publishing process\"]\n* Man pages\n  * Man pages of the `cargo` command\n  * Built with [mdman]\n  * Published through [\"the doc publishing process\"]\n* [Contributor guide]\n  * This guide itself\n  * Source at <https://github.com/rust-lang/cargo/tree/master/src/doc/contrib>\n  * Published independently on GitHub Pages at\n    <https://rust-lang.github.io/cargo/contrib>\n    when committing to the master branch.\n\n[The Cargo Book]: https://doc.rust-lang.org/cargo/\n[Crate API docs]: https://docs.rs/cargo\n[Contributor guide]: https://rust-lang.github.io/cargo/contrib\n[mdBook]: https://github.com/rust-lang/mdBook\n[mdman]: https://github.com/rust-lang/cargo/tree/master/crates/mdman/\n[\"the doc publishing process\"]: ../process/release.md#docs-publishing\n\n## Building the book\n\nBuilding the book requires [mdBook]. To get it:\n\n```console\n$ cargo install mdbook\n```\n\nTo build the book:\n\n```console\n$ mdbook build\n```\n\n`mdbook` provides a variety of different commands and options to help you work\non the book:\n\n* `mdbook build --open`: Build the book and open it in a web browser.\n* `mdbook serve`: Launches a web server on localhost. It also automatically\n  rebuilds the book whenever any file changes and automatically reloads your\n  web browser.\n\nThe book contents are driven by a `SUMMARY.md` file,\nand every file must be linked there.\nSee <https://rust-lang.github.io/mdBook/> for its usage.\n\n## Building the man pages\n\nThe man pages use a tool called [mdman] to convert Markdown templates into several output formats.\nSee <https://github.com/rust-lang/cargo/tree/master/crates/mdman/doc>\nfor usage details and template syntax.\n\nThe templates are located in\n<https://github.com/rust-lang/cargo/tree/master/src/doc/man>\nand are converted into three formats:\n\n1. Troff man pages --- used by the `cargo help` command,\n   and by distributions to provide man pages which people can install,\n   saved in <https://github.com/rust-lang/cargo/tree/master/src/etc/man>.\n2. Plain text --- used for embedded help on platforms without `man` (such as Windows),\n   saved in <https://github.com/rust-lang/cargo/tree/master/src/doc/man/generated_txt>.\n3. Markdown (with some HTML) --- used for the Cargo Book,\n   saved in <https://github.com/rust-lang/cargo/tree/master/src/doc/src/commands>.\n\nTo rebuild the man pages, run `cargo build-man` inside the workspace.\n\n## Writing guidelines\n\nCargo's documentation is a collective effort,\nso there isn't a single fixed writing style.\nWe recommend following the style of the surrounding text to keep things consistent.\n\nA few important guidelines:\n\n* The [Cargo Commands](https://doc.rust-lang.org/nightly/cargo/commands/index.html)\n  chapters in the book are generated from man page templates.\n  To update them, see the [Building the man pages](#building-the-man-pages) section.\n  Do not edit the generated Markdown files directly.\n* Links to pages under <https://doc.rust-lang.org/> should use relative paths.\n  This ensures versioned docs are redirected correctly.\n  For example, if you are at <https://doc.rust-lang.org/cargo/reference/config.html>\n  and want to link to <https://doc.rust-lang.org/rustc/codegen-options/index.html>,\n  you should write the link as `../../rustc/codegen-options/index.html`.\n  This rule doesn't apply if you specifically want to link to docs of a fixed version or channel.\n* When renaming or removing any headings or pages,\n  make sure to set up proper redirects via the [`output.html.redirect`] mdbook option.\n* If a section refers to a concept explained elsewhere\n  (like profiles, features, or workspaces), link to it.\n  That keeps the book navigable without duplicating content.\n\n[[`output.html.redirect`]]: https://rust-lang.github.io/mdBook/format/configuration/renderers.html#outputhtmlredirect\n\n## SemVer chapter tests\n\nThere is a script to verify that the examples in [the SemVer chapter] work as\nintended. To run the tests, run `cargo +stable run -p semver-check`.\n\nNote that these tests run on the most recent stable release because they\nvalidate the output of the compiler diagnostics. The output can change between\nreleases, so we pin to a specific release to avoid frequent and unexpected\nbreakage.\n\n[the SemVer chapter]: https://doc.rust-lang.org/nightly/cargo/reference/semver.html\n"
  },
  {
    "path": "src/doc/contrib/src/implementation/architecture.md",
    "content": "# Architecture Overview\n\nSee the\n[nightly docs](https://doc.rust-lang.org/nightly/nightly-rustc/cargo/index.html)\nfor an overview of `cargo`s architecture and links out to further details.\n"
  },
  {
    "path": "src/doc/contrib/src/implementation/console.md",
    "content": "# Console Output\n\nAll of Cargo's output should go through the [`Shell`] struct. You can normally\nobtain the `Shell` instance from the [`GlobalContext`] struct. Do **not** use\nthe std `println!` macros.\n\nMost of Cargo's output goes to stderr. When running in JSON mode, the output\ngoes to stdout.\n\nIt is important to properly handle errors when writing to the console.\nInformational commands, like `cargo list`, should ignore any errors writing\nthe output. There are some [`drop_print`] macros that are intended to make\nthis easier.\n\nMessages written during compilation should handle errors, and abort the build\nif they are unable to be displayed. This is generally automatically handled in\nthe [`JobQueue`] as it processes each message.\n\n[`Shell`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/core/shell.rs\n[`GlobalContext`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/util/context/mod.rs\n[`drop_print`]: https://github.com/rust-lang/cargo/blob/e4b65bdc80f2a293447f2f6a808fa7c84bf9a357/src/cargo/util/config/mod.rs#L1820-L1848\n[`JobQueue`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/job_queue/mod.rs\n\n## Diagnostics\n\nSee rustc's [Errors and lints] for:\n- diagnostic structure\n- hard diagnostics vs lints\n- diagnostic style guide\n- lint naming\n- diagnostic levels\n- suggestion style guide\n\n### Errors\n\nCargo uses [`anyhow`] for managing errors. This makes it convenient to \"chain\"\nerrors together, so that Cargo can report how an error originated, and what it\nwas trying to do at the time.\n\nError helpers are implemented in the [`errors`] module. Use the\n`InternalError` error type for errors that are not expected to happen. This\nwill print a message to the user to file a bug report.\n\nThe binary side of Cargo uses the `CliError` struct to wrap the process exit\ncode. Usually Cargo exits with 101 for an error, but some commands like `cargo\ntest` will exit with different codes.\n\n[`errors`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/util/errors.rs\n\n## Style\n\nSome guidelines for Cargo's output:\n\n* Keep the normal output brief. Cargo is already fairly noisy, so try to keep\n  the output as brief and clean as possible.\n* Good error messages are very important! Try to keep them brief and to the\n  point, but good enough that a beginner can understand what is wrong and can\n  figure out how to fix. It is a difficult balance to hit! Err on the side of\n  providing extra information.\n* When using any low-level routines, such as `std::fs`, *always* add error\n  context about what it is doing. For example, reading from a file should\n  include context about which file is being read if there is an error.\n* Cargo's error style is usually a phrase, starting with a lowercase letter.\n  If there is a longer error message that needs multiple sentences, go ahead\n  and use multiple sentences. This should probably be improved sometime in the\n  future to be more structured.\n\n[`anyhow`]: https://docs.rs/anyhow\n[Errors and lints]: https://rustc-dev-guide.rust-lang.org/diagnostics.html\n"
  },
  {
    "path": "src/doc/contrib/src/implementation/debugging.md",
    "content": "# Debugging\n\n## Logging\n\nCargo uses the [`tracing`] crate to display debug log messages.\nThe `CARGO_LOG` environment variable can be set to enable debug logging, with a value such as `trace`, `debug`, or `warn`.\nIt also supports filtering for specific modules with comma-separated [directives].\nFeel free to use [shorthand macros] to help with diagnosing problems.\nWe're looking forward to making Cargo logging mechanism more structural!\n\n```sh\n# Outputs all logs with levels debug and higher\nCARGO_LOG=debug cargo generate-lockfile\n\n# Don't forget that you can filter by module as well\nCARGO_LOG=cargo::core::resolver=trace cargo generate-lockfile\n\n# This will print lots of info about the download process. `trace` prints even more.\nCARGO_HTTP_DEBUG=true CARGO_LOG=network=debug cargo fetch\n\n# This is an important command for diagnosing fingerprint issues.\nCARGO_LOG=cargo::core::compiler::fingerprint=trace cargo build\n```\n\n[`tracing`]: https://docs.rs/tracing\n[directive]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives\n[shorthand macros]: https://docs.rs/tracing/latest/tracing/index.html#shorthand-macros\n"
  },
  {
    "path": "src/doc/contrib/src/implementation/filesystem.md",
    "content": "# Filesystem\n\nCargo tends to get run on a very wide array of file systems. Different file\nsystems can have a wide range of capabilities, and Cargo should strive to do\nits best to handle them. Some examples of issues to deal with:\n\n* Not all file systems support locking. Cargo tries to detect if locking is\n  supported, and if not, will ignore lock errors. This isn't ideal, but it is\n  difficult to deal with.\n* The [`fs::canonicalize`] function doesn't work on all file systems\n  (particularly some Windows file systems). If that function is used, there\n  should be a fallback if it fails. This function will also return `\\\\?\\`\n  style paths on Windows, which can have some issues (such as some tools not\n  supporting them, or having issues with relative paths).\n* Timestamps can be unreliable. The [`fingerprint`] module has a deeper\n  discussion of this. One example is that Docker cache layers will erase the\n  fractional part of the time stamp.\n* Symlinks are not always supported, particularly on Windows.\n\n[`fingerprint`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/fingerprint/mod.rs\n[`fs::canonicalize`]: https://doc.rust-lang.org/std/fs/fn.canonicalize.html\n"
  },
  {
    "path": "src/doc/contrib/src/implementation/formatting.md",
    "content": "# Formatting\n\nWhen modifying user files, like `Cargo.toml`, we should not change other\nsections of the file,\npreserving the general formatting.\nThis includes the table, inline-table, or array that a field is being edited in.\n\nWhen adding new entries, they do not need to match the canonical style of the\ndocument but can use the default formatting.\nIf the entry is already sorted, preserving the sort order is preferred.\n\nWhen removing entries,\ncomments on the same line should be removed but comments on following lines\nshould be preserved.\n\nInconsistencies in style after making a change are left to the user and their\npreferred auto-formatter.\n"
  },
  {
    "path": "src/doc/contrib/src/implementation/index.md",
    "content": "# Implementing a Change\n\nThis chapter gives an overview of what you need to know in making a change to cargo.\n\nIf you feel something is missing that would help you, feel free to ask on\n[Zulip](https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo).\n"
  },
  {
    "path": "src/doc/contrib/src/implementation/packages.md",
    "content": "# New Packages\n\nThis chapter sketches out how to add a new package to the cargo workspace.\n\n## Steps\n\nChoose the relevant parent directory\n- `credential/` for credential-process related packages\n- `benches/` for benchmarking of cargo itself\n- `crates/` for everything else\n\nRun `cargo new <name>`\n- `<name>`:\n  - We tend to use `-` over `_`\n  - For internal APIs, to avoid collisions with third-party subcommands, we can use the `cargo-util-` prefix\n  - For xtasks, we use the `xtask-` prefix\n- `package.rust-version`\n  - Internal packages tend to have a policy of \"latest\" with a [`# MSRV:1` comment](#msrv-policy)\n  - Ecosystem packages tend to have a policy of \"N-2\" with a [`# MSRV:3` comment](#msrv-policy)\n  - If the right choice is inherited from the workspace, feel free to keep it that way\n- If running without [cargo new automatically adding to workspace](https://github.com/rust-lang/cargo/pull/12779), add it as a workspace member if not already captured by a glob\n\nIf its an xtask,\n- Add it to `.cargo/config.toml`s `[alias]` table\n- Mark `package.publish = false`\n\nIf needed to be published with `cargo`,\nadd the package to `publish.py` in the repo root,\nin dependency order.\n\nNote: by adding the package to the workspace, you automatically get\n- CI running `cargo test`\n- CI verifying MSRV\n- CI checking for `cargo doc` warnings\n\n## MSRV Policy\n\nOur MSRV policies are\n- Internal packages: support latest version\n- Ecosystem packages: support latest 3 versions\n\nWe proactively update the MSRV\n- So contributors don't shy away from using newer features, either assuming they\n  can't ask or feeling like they have to have a justification when asking\n- To avoid a de facto MSRV developing from staying on a version for a long\n  period of time, leaving users unhappy when their expectations aren't met\n\nTo proactively update the MSRV, we use [RenovateBot](https://docs.renovatebot.com/)\nwith the configuration file in `.github/renovatebot.json5`.\nTo know what MSRV policy to use,\nit looks for comments of the form `# MSRV:N`,\nwhere `N` is the number of supported rust versions.\n"
  },
  {
    "path": "src/doc/contrib/src/implementation/schemas.md",
    "content": "# Data Schemas\n\nCargo reads and writes user and machine facing data formats, like\n- `Cargo.toml`, read and written on `cargo package`\n- `Cargo.lock`, read and written\n- `.cargo/config.toml`, read-only\n- `cargo metadata` output\n- `cargo build --message-format` output\n\n## Schema Design\n\nGenerally,\n- Fields should be kebab case\n  - `#[serde(rename_all = \"kebab-case\")]` should be applied defensively\n- Fields should only be present when needed, saving space and parse time\n  - Also, we can always switch to always outputting the fields but its harder to stop outputting them\n  - `#[serde(skip_serializing_if = \"Default::default\")]` should be applied liberally\n- For output, prefer [jsonlines](https://jsonlines.org/) as it allows streaming output and flexibility to mix content (e.g. adding diagnostics to output that didn't previously have it\n- `#[serde(deny_unknown_fields)]` should not be used to allow evolution of formats, including feature gating\n\n## Schema Evolution Strategies\n\nWhen changing a schema for data that is read, some options include:\n- Adding new fields is relatively safe\n  - If the field must not be ignored when present,\n    have a transition period where it is invalid to use on stable Cargo before stabilizing it or\n    error if its used before supported within the schema version\n    (e.g. `edition` requires a minimum `package.rust-version`, if present)\n- Adding new values to a field is relatively safe\n  - Unstable values should fail on stable Cargo\n- Version the structure and interpretation of the data (e.g. the `edition` field or `package.resolver` which has an `edition` fallback)\n\nNote: some formats that are read are also written back out\n(e.g. `cargo package` generating a `Cargo.toml` file)\nand those strategies need to be considered as well.\n\nWhen changing a schema for data that is written, some options include:\n- Add new fields if the presence can be ignored\n- Infer permission from the users use of the new schema (e.g. a new alias for an `enum` variant)\n- Version the structure and interpretation of the format\n  - Defaulting to the latest version with a warning that behavior may change (e.g. `cargo metadata --format-version`, `edition` in cargo script)\n  - Defaulting to the first version, eventually warning the user of the implicit stale behavior (e.g. `package.edition` in `Cargo.toml`)\n  - Without a default (e.g. `package.rust-version`, or a command-line flag like `--format-version`)\n\nNote: While `serde` makes it easy to support data formats that add new fields,\nnew data types or supported values for a field are more difficult to future-proof\nagainst.\n"
  },
  {
    "path": "src/doc/contrib/src/implementation/subcommands.md",
    "content": "# New Subcommands\n\nCargo is a single binary composed of a set of [`clap`] subcommands. All\nsubcommands live in [`src/bin/cargo/commands`] directory.\n[`src/bin/cargo/main.rs`] is the entry point.\n\nEach subcommand, such as [`src/bin/cargo/commands/build.rs`], usually performs\nthe following:\n\n1. Parse the CLI flags. See the [`command_prelude`] module for some helpers to make this easier.\n2. Load the config files.\n3. Discover and load the workspace.\n4. Calls the actual implementation of the subcommand which resides in [`src/cargo/ops`].\n\nIf the subcommand is not found in the built-in list, then Cargo will\nautomatically search for a subcommand named `cargo-{NAME}` in the users `PATH`\nto execute the subcommand.\n\n\n[`clap`]: https://docs.rs/clap\n[`src/bin/cargo/commands/build.rs`]: https://github.com/rust-lang/cargo/tree/master/src/bin/cargo/commands/build.rs\n[`src/cargo/ops`]: https://github.com/rust-lang/cargo/tree/master/src/cargo/ops\n[`src/bin/cargo/commands`]: https://github.com/rust-lang/cargo/tree/master/src/bin/cargo/commands\n[`src/bin/cargo/main.rs`]: https://github.com/rust-lang/cargo/blob/master/src/bin/cargo/main.rs\n[`command_prelude`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/util/command_prelude.rs\n"
  },
  {
    "path": "src/doc/contrib/src/index.md",
    "content": "# Introduction\n\nThank you for your interest in contributing to [Cargo]! This guide provides an\noverview of how to contribute to Cargo, how to dive into the code, and how the\ntesting infrastructure works.\n\nThere are many ways to contribute, such as [helping other users], [filing\nissues], improving [the documentation], [triaging issues], [fixing bugs], and\nworking on [small] and [large features].\n\nIf you have a general question about Cargo or its internals, feel free to ask\non [Zulip].\n\nThis guide assumes you have some familiarity with Rust, and how to use Cargo,\n[rustup], and general development tools like [git].\n\nPlease also read the [Rust Code of Conduct].\n\n[Cargo]: https://doc.rust-lang.org/cargo/\n[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo\n[Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct\n[helping other users]: https://users.rust-lang.org/\n[filing issues]: issues.md\n[rustup]: https://rust-lang.github.io/rustup/\n[git]: https://git-scm.com/\n[the documentation]: https://github.com/rust-lang/cargo/tree/master/src/doc\n[fixing bugs]: process/index.md#working-on-issues\n[small]: process/index.md#working-on-small-features\n[large features]: process/index.md#working-on-large-features\n[triaging issues]: issues.md#triaging-issues\n"
  },
  {
    "path": "src/doc/contrib/src/issues.md",
    "content": "# Issue Tracker\n\nCargo's issue tracker is located at\n<https://github.com/rust-lang/cargo/issues/>. This is the primary spot where\nwe track bugs and small feature requests. See [Process] for more about our\nprocess for proposing changes.\n\n## Filing issues\n\nWe can't fix what we don't know about, so please report problems liberally.\nThis includes problems with understanding the documentation, unhelpful error\nmessages, and unexpected behavior.\n\n**If you think that you have identified an issue with Cargo that might\ncompromise its users' security, please do not open a public issue on GitHub.\nInstead, we ask you to refer to Rust's [security policy].**\n\nOpening an issue is as easy as following [this link][new-issues]. There are\nseveral templates for different issue kinds, but if none of them fit your\nissue, don't hesitate to modify one of the templates, or click the [Open a\nblank issue] link.\n\nThe Rust tools are spread across multiple repositories in the Rust\norganization. It may not always be clear where to file an issue. No worries!\nIf you file in the wrong tracker, someone will either transfer it to the\ncorrect one or ask you to move it. Some other repositories that may be\nrelevant are:\n\n* [`rust-lang/rust`] --- Home for the [`rustc`] compiler and [`rustdoc`].\n* [`rust-lang/rustup`] --- Home for the [`rustup`] toolchain installer.\n* [`rust-lang/rustfmt`] --- Home for the `rustfmt` tool, which also includes `cargo fmt`.\n* [`rust-lang/rust-clippy`] --- Home for the `clippy` tool, which also includes `cargo clippy`.\n* [`rust-lang/crates.io`] --- Home for the [crates.io] website.\n\nIssues with [`cargo fix`] can be tricky to know where they should be filed,\nsince the fixes are driven by `rustc`, and the front-interface is implemented\nin Cargo. Feel free to file in the Cargo issue tracker, and it will get moved\nto the [`rust-lang/rust`] issue tracker if necessary.\n\n[Process]: process/index.md\n[security policy]: https://www.rust-lang.org/security.html\n[new-issues]: https://github.com/rust-lang/cargo/issues/new/choose\n[Open a blank issue]: https://github.com/rust-lang/cargo/issues/new\n[`rust-lang/rust`]: https://github.com/rust-lang/rust\n[`rust-lang/rustup`]: https://github.com/rust-lang/rustup\n[`rust-lang/rustfmt`]: https://github.com/rust-lang/rustfmt\n[`rust-lang/rust-clippy`]: https://github.com/rust-lang/rust-clippy\n[`rustc`]: https://doc.rust-lang.org/rustc/\n[`rustdoc`]: https://doc.rust-lang.org/rustdoc/\n[`rustup`]: https://rust-lang.github.io/rustup/\n[`rust-lang/crates.io`]: https://github.com/rust-lang/crates.io\n[crates.io]: https://crates.io/\n[`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html\n\n## Issue labels\n\n[Issue labels] are very helpful to identify the types of issues and which\ncategory they are related to.\n\nAnyone can apply most labels by posting comments with a form such as:\n\n```text\n@rustbot label: +A-doctests, -A-dependency-resolution\n```\n\nThis example will add the [`A-doctests`] label and remove the\n[`A-dependency-resolution`] label.\n\n[Issue labels]: https://github.com/rust-lang/cargo/labels\n[`A-doctests`]: https://github.com/rust-lang/cargo/labels/A-doctests\n[`A-dependency-resolution`]: https://github.com/rust-lang/cargo/labels/A-dependency-resolution\n\nThe labels use a naming convention with short prefixes and colors to indicate\nthe kind of label:\n\n<style>\n.label-color {\n    border-radius:0.5em;\n}\ntable td:nth-child(2) {\n    white-space: nowrap;\n}\n\n</style>\n\n| Labels | Color | Description |\n|--------|-------|-------------|\n| [A-]   | <span class=\"label-color\" style=\"background-color:#fbca04;\">&#x2003;</span>&nbsp;Yellow | The **area** of the project an issue relates to. |\n| [beta-] | <span class=\"label-color\" style=\"background-color:#1e76d9;\">&#x2003;</span>&nbsp;Dark Blue | Tracks changes which need to be [backported to beta][beta-backport] |\n| [C-] | <span class=\"label-color\" style=\"background-color:#f5f1fd;\">&#x2003;</span>&nbsp;Light Purple | The **category** of an issue. |\n| [Command-] | <span class=\"label-color\" style=\"background-color:#5319e7;\">&#x2003;</span>&nbsp;Dark Purple | The `cargo` command it is related to. |\n| [E-] | <span class=\"label-color\" style=\"background-color:#02e10c;\">&#x2003;</span>&nbsp;Green | The **experience** level necessary to fix an issue. |\n| [I-] | <span class=\"label-color\" style=\"background-color:#fc2929;\">&#x2003;</span>&nbsp;Red | The **importance** of the issue. |\n| [O-] | <span class=\"label-color\" style=\"background-color:#7e7ec8;\">&#x2003;</span>&nbsp;Purple Grey | The **operating system** or platform that the issue is specific to. |\n| [P-] | <span class=\"label-color\" style=\"background-color:#eb6420;\">&#x2003;</span>&nbsp;Orange | The issue **priority**. |\n| [regression-] | <span class=\"label-color\" style=\"background-color:#e4008a;\">&#x2003;</span>&nbsp;Pink | Tracks regressions from a stable release. |\n| [relnotes] | <span class=\"label-color\" style=\"background-color:#fad8c7;\">&#x2003;</span>&nbsp;Light Orange | Marks issues or PRs that should be highlighted in the [Rust release notes] of the next release. |\n| [S-] | Varies | Tracks the **status** of issues and pull requests (see [Issue status labels](#issue-status-labels)) |\n| [Z-] | <span class=\"label-color\" style=\"background-color:#453574;\">&#x2003;</span>&nbsp;Dark Blue | Unstable, [nightly features]. |\n\n\n[A-]: https://github.com/rust-lang/cargo/labels?q=A\n[beta-]: https://github.com/rust-lang/cargo/labels?q=beta\n[beta-backport]: https://forge.rust-lang.org/release/backporting.html#beta-backporting-in-rust-langcargo\n[C-]: https://github.com/rust-lang/cargo/labels?q=C\n[Command-]: https://github.com/rust-lang/cargo/labels?q=Command\n[E-]: https://github.com/rust-lang/cargo/labels?q=E\n[I-]: https://github.com/rust-lang/cargo/labels?q=I\n[nightly features]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html\n[O-]: https://github.com/rust-lang/cargo/labels?q=O\n[P-]: https://github.com/rust-lang/cargo/labels?q=P\n[regression-]: https://github.com/rust-lang/cargo/labels?q=regression\n[relnotes]: https://github.com/rust-lang/cargo/issues?q=label%3Arelnotes\n[Rust release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md\n[S-]: https://github.com/rust-lang/cargo/labels?q=S\n[Z-]: https://github.com/rust-lang/cargo/labels?q=nightly\n\n### Issue status labels\n\nThe `S-` prefixed *status* labels are the primary mechanism we use to track\nwhat is happening with an issue and what it is waiting on. The following is a\nlist of the status labels and what they mean. This is listed roughly in the\norder that an issue might go through, though issues will often jump to\ndifferent steps, or in rare cases have multiple statuses.\n\n* **[S-triage]** --- New issues get this label automatically assigned to them\n  to indicate that nobody has yet looked at them, and they need someone to\n  assign other labels and decide what the next step is.\n\n* **[S-needs-info]** --- Needs more info, such as a reproduction or more\n  background for a feature request.\n\n  Anyone is welcome to help with providing additional info to help reproduce\n  or provide more detail on use cases and such. But usually this is a request\n  to the initial author.\n\n  When adding this label, there should also usually be a comment that goes\n  along with it stating the information requested.\n\n* **[S-needs-team-input]** --- Needs input from team on whether/how to\n  proceed.\n\n  Here it is essentially blocked waiting for a team member to move it to the\n  next stage.\n\n* **[S-needs-design]** --- Needs someone to work further on the design for the\n  feature or fix.\n\n  Anyone is welcome to help at this stage, but it should be clear that it is\n  not yet accepted. It is expected that people should contribute comments and\n  ideas to the issue which furthers the process of fleshing out what is\n  needed, or alternate ideas. This may also require reaching out to the wider\n  community via forums and such.\n\n* **[S-needs-rfc]** --- Needs an [RFC] before this can make more progress.\n\n  Anyone is welcome to help at this stage, but it should be clear that it is\n  not yet accepted.\n  See [Before creating an RFC](https://github.com/rust-lang/rfcs?tab=readme-ov-file#before-creating-an-rfc)\n  for next steps.\n\n* **[S-needs-mentor]** --- Needs a Cargo team member to commit to helping and\n  reviewing.\n\n  This is for something that is accepted, such as after an RFC or a team\n  discussion, or an obvious issue that just needs fixing, but no team member\n  is available to help or review.\n\n* **[S-accepted]** --- Issue or feature is accepted, and has a team member\n  available to help mentor or review.\n\n* **[S-waiting-on-feedback]** --- An implemented feature is waiting on\n  community feedback for bugs or design concerns.\n\n  This is typically used on a [tracking issue] after it has been implemented\n  to indicate what it is waiting on.\n\n\n[S-triage]: https://github.com/rust-lang/cargo/labels/S-triage\n[S-needs-info]: https://github.com/rust-lang/cargo/labels/S-needs-info\n[S-needs-team-input]: https://github.com/rust-lang/cargo/labels/S-needs-team-input\n[S-needs-design]: https://github.com/rust-lang/cargo/labels/S-needs-design\n[S-needs-rfc]: https://github.com/rust-lang/cargo/labels/S-needs-rfc\n[S-needs-mentor]: https://github.com/rust-lang/cargo/labels/S-needs-mentor\n[S-accepted]: https://github.com/rust-lang/cargo/labels/S-accepted\n[S-waiting-on-feedback]: https://github.com/rust-lang/cargo/labels/S-waiting-on-feedback\n[RFC]: https://github.com/rust-lang/rfcs/\n[tracking issue]: https://github.com/rust-lang/cargo/labels/C-tracking-issue\n\n## Triaging issues\n\nTriaging issues involves processing issues to assign appropriate labels, make\nsure the issue has sufficient information, and to decide the next steps.\nWhen new issues are filed, they should automatically get the [S-triage] label\nassuming the author uses one of the templates. This helps identify which\nissues have not yet been triaged.\n\nThere are several things to consider when triaging an issue:\n\n* Is this a duplicate? Search the issue tracker (including closed issues) to\n  see if there is an issue with a similar or identical root cause to what is reported.\n  We generally focus issues around root causes so alternative solutions can be\n  discussed and evaluated together.\n  If it is obviously a duplicate, write a comment that it is a duplicate of the\n  other issue, and close the issue.\n  If it isn't obvious that it is a duplicate, leave a comment asking the author\n  if the other issue covers what they reported.\n\n* For a bug, check if the report contains enough information to reproduce it.\n  If you can't reproduce it, solicit more information from the author to\n  better understand the issue.\n  Change the label from [S-triage] to [S-needs-info] if this is the case.\n\n* Add labels that describe what the issue is related to.\n\n    * Add the appropriate [A-], [Command-], [O-], and [Z-] prefixed labels.\n    * If this is a regression from stable, add one of the [regression-]\n      prefixed labels (depending on if it is a regression in an already\n      released stable release, or it is in nightly).\n\n* Assuming the issue looks valid, switch the [S-triage] label for one of the following:\n\n  * [S-needs-team-input] --- The next steps are not clear, and the Cargo team\n    needs to discuss whether or not to proceed and what needs to be done to\n    address the issue.\n  * [S-needs-design] --- The resolution of the issue or small feature request\n    will need more work to come up with the appropriate design.\n  * [S-needs-rfc] --- This is a large feature request that will require a\n    public design process.\n  * [S-needs-mentor] --- This is something the Cargo team wants to address,\n    but does not currently have the capacity to help with reviewing. **(reserved for Cargo team)**\n  * [S-accepted] --- This is something that clearly needs to be addressed, and\n    a Cargo team member has volunteered to help review. **(reserved for Cargo team)**\n\nAnyone is welcome to help with the triaging process. You can help with\nreproducing issues, checking for duplicates, gathering more information from\nthe reporter, assigning labels using [`@rustbot` comments](#issue-labels), and\ncreating a test using [Cargo's testsuite] ([example][cargotest-example]).\n\n[Cargo's testsuite]: tests/writing.md\n[cargotest-example]: https://github.com/rust-lang/cargo/issues/11628#issuecomment-1411088951\n"
  },
  {
    "path": "src/doc/contrib/src/process/index.md",
    "content": "# Process\n\nThis chapter gives an overview of how Cargo comes together, and how you can be\na part of that process.\n\nSee the [Working on Cargo] chapter for an overview of the contribution\nprocess.\n\nPlease read the guidelines below before working on an issue or new feature.\n\n[Working on Cargo]: working-on-cargo.md\n\n## Mentorship\n\nSome Cargo team members are available to directly mentor contributions to Cargo.\nSee the [office hours] page for more information.\n\n[office hours]: https://github.com/rust-lang/cargo/wiki/Office-Hours\n\n## Roadmap\n\nThe [Roadmap Project Board] is used for tracking major initiatives. This gives\nan overview of the things the team is interested in and thinking about.\n\nThe [RFC Project Board] is used for tracking [RFCs].\n\n[the 2020 roadmap]: https://blog.rust-lang.org/inside-rust/2020/01/10/cargo-in-2020.html\n[Roadmap Project Board]: https://github.com/orgs/rust-lang/projects/37\n[RFC Project Board]: https://github.com/orgs/rust-lang/projects/36\n[RFCs]: https://github.com/rust-lang/rfcs/\n\n## Working on issues\n\nIssues labeled with the [S-accepted] [label] are typically issues that the\nCargo team wants to see addressed. If you are interested in one of those, and\nit has not already been assigned to someone, leave a comment. See [Issue\nassignment](#issue-assignment) below for assigning yourself.\n\nWhen possible, the Cargo team will try to also include [E-easy], [E-medium],\nor [E-hard] labels to try to give an estimate of the difficulty involved with\nthe issue.\n\nIf there is a specific issue that you are interested in, but it is not marked\nas [S-accepted], leave a comment on the issue. If a Cargo team member has the\ntime to help out, they will respond to help with the next steps.\n\n[E-easy]: https://github.com/rust-lang/cargo/labels/E-easy\n[E-medium]: https://github.com/rust-lang/cargo/labels/E-medium\n[E-hard]: https://github.com/rust-lang/cargo/labels/E-hard\n[S-accepted]: https://github.com/rust-lang/cargo/labels/S-accepted\n[label]: ../issues.md#issue-labels\n\n## Working on small features\n\nSmall feature requests are typically managed on the [issue\ntracker][issue-feature-request]. Features that the Cargo team have approved\nwill have the [S-accepted] label.\n\nIf there is a feature request that you are interested in, but it is not marked\nas [S-accepted], feel free to leave a comment expressing your interest. If a\nCargo team member has the time to help out, they will respond to help with the\nnext steps. Keep in mind that the Cargo team has limited time, and may not be\nable to help with every feature request. Most of them require some design\nwork, which can be difficult. Check out the [design principles chapter] for\nsome guidance.\n\n## Working on large features\n\nCargo follows the Rust model of evolution. Major features usually go through\nan [RFC process]. Therefore, before opening a feature request issue create a\nPre-RFC thread on the [internals][irlo] forum to get preliminary feedback.\n\nImplementing a feature as a [custom subcommand][subcommands] is encouraged as\nit helps demonstrate the demand for the functionality and is a great way to\ndeliver a working solution faster as it can iterate outside of Cargo's release\ncadence.\n\nSee the [unstable chapter] for how new major features are typically\nimplemented.\n\n[unstable chapter]: unstable.md\n\n## Bots and infrastructure\n\nThe Cargo project uses several bots:\n\n* [GitHub Actions] are used to automatically run all tests for each PR.\n* [triagebot] automatically assigns reviewers for PRs, see [PR Assignment] for\n  how to configure.\n* [GitHub merge queue] is used to merge PRs. See [The merging process].\n* [triagebot] is used for assigning issues to non-members, see [Issue\n  assignment](#issue-assignment).\n* [rfcbot] is used for making asynchronous decisions by team members.\n\n[GitHub merge queue]: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue\n[The merging process]: working-on-cargo.md#the-merging-process\n[GitHub Actions]: https://github.com/features/actions\n[triagebot]: https://forge.rust-lang.org/triagebot/index.html\n[rfcbot]: https://github.com/rust-lang/rfcbot-rs\n[PR Assignment]: https://forge.rust-lang.org/triagebot/pr-assignment.html\n\n## Issue assignment\n\nNormally, if you plan to work on an issue that has been marked with the\n[S-accepted] label, it is sufficient just to leave a comment that you are\nworking on it. We also have a bot that allows you to formally claim an issue\nby entering the text `@rustbot claim` in a comment. See the [Issue Assignment] docs\non how this works.\n\n\n[Issue Assignment]: https://forge.rust-lang.org/triagebot/issue-assignment.html\n[team]: https://www.rust-lang.org/governance/teams/dev-tools#cargo\n[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo\n[issue-feature-request]: https://github.com/rust-lang/cargo/labels/C-feature-request\n[Feature accepted]: https://github.com/rust-lang/cargo/labels/Feature%20accepted\n[design principles chapter]: ../design.md\n[RFC process]: ./rfc.md\n[irlo]: https://internals.rust-lang.org/\n[subcommands]: https://doc.rust-lang.org/cargo/reference/external-tools.html#custom-subcommands\n"
  },
  {
    "path": "src/doc/contrib/src/process/release.md",
    "content": "# Release process\n\nCargo is released with `rustc` using a [\"train model\"][choochoo]. After a\nchange lands in Cargo's master branch, it will be synced with the\n[rust-lang/rust] repository by a Cargo team member, which happens about once a\nweek. If there are complications, it can take longer. After it is synced and\nmerged, the changes will appear in the next nightly release, which is usually\npublished around 00:30 UTC.\n\nAfter changes are in the nightly release, they will make their way to the\nstable release anywhere from 6 to 12 weeks later, depending on when during the\ncycle it landed.\n\nThe current release schedule is posted on the [Rust Forge]. See the [release\nprocess] for more details on how Rust's releases are created. Rust releases\nare managed by the [Release team].\n\n[Rust Forge]: https://forge.rust-lang.org/\n\n## Build process\n\nThe build process for Cargo is handled as part of building Rust. Every PR on\nthe [rust-lang/rust] repository creates a full collection of release artifacts\nfor every platform. The code for this is in the [`dist` bootstrap module].\nEvery night at 00:00 UTC, the artifacts from the most recently merged PR are\npromoted to the nightly release channel. A similar process happens for beta\nand stable releases.\n\n[`dist` bootstrap module]: https://github.com/rust-lang/rust/blob/master/src/bootstrap/src/core/build_steps/dist.rs\n\n## Submodule updates\n\nCargo is tracked in the [rust-lang/rust] repository using a [git submodule].\nIt is updated manually about once a week by a Cargo team member.\nHowever, anyone is welcome to update it as needed.\n\n[@ehuss] has a tool called [subup](https://github.com/ehuss/subup) to automate the process of updating the submodule, updating the lockfile, running tests, and creating a PR.\nRunning the tests ahead-of-time helps avoid long cycle times waiting for bors if there are any errors.\nSubup will also provide a message to include in the PR with a list of all PRs it covers.\nPosting this in the PR message also helps create reference links on each Cargo PR to the submodule update PR to help track when it gets merged.\n\nThe following is an example of the command to run in a local clone of rust-lang/rust to run a certain set of tests of things that are likely to get broken by a Cargo update:\n\n```bash\nsubup --up-branch update-cargo \\\n    --commit-message \"Update cargo\" \\\n    --test=\"src/tools/linkchecker tidy \\\n        src/tools/cargo \\\n        src/tools/rustfmt\" \\\n    src/tools/cargo\n```\n\nIf doing a [beta backport](#beta-backports), the command is similar, but needs to point to the correct branches:\n\n```bash\nsubup --up-branch update-beta-cargo \\\n    --rust-branch beta \\\n    --set-config rust.channel=beta \\\n    --commit-message \"[beta] Update cargo\" \\\n    --test=\"src/tools/linkchecker tidy \\\n        src/tools/cargo \\\n        src/tools/rustfmt\" \\\n    rust-1.66.0:src/tools/cargo\n```\n\n[@ehuss]: https://github.com/ehuss/\n[git submodule]: https://git-scm.com/book/en/v2/Git-Tools-Submodules\n\n## Version updates\n\nShortly after each major release, a Cargo team member will post a PR to update\nCargo's version in `Cargo.toml`. Cargo's library is permanently unstable, so\nits version number starts with a `0`. The minor version is always 1 greater\nthan the Rust release it is a part of, so cargo 0.49.0 is part of the 1.48\nRust release. The [CHANGELOG] is also usually updated at this time.\n\nAlso, any version-specific checks that are no longer needed can be removed.\nFor example, some tests are disabled on stable if they require some nightly\nbehavior. Once that behavior is available on the new stable release, the\nchecks are no longer necessary. (I usually search for the word \"nightly\" in\nthe testsuite directory, and read the comments to see if any of those nightly\nchecks can be removed.)\n\nSometimes Cargo will have a runtime check to probe `rustc` if it supports a\nspecific feature. This is usually stored in the [`TargetInfo`] struct. If this\nbehavior is now stable, those checks should be removed.\n\nCargo has several other packages in the [`crates/` directory]. If any of these\npackages have changed, the version should be bumped **before the beta\nrelease**. It is rare that these get updated. Bumping these as-needed helps\navoid churning incompatible version numbers. This process should be improved\nin the future!\n\n[@ehuss] has a tool called [cargo-new-release] to automate the process of doing a version bump.\nIt runs through several steps:\n1. Creates a branch\n2. Updates the version numbers\n3. Creates a changelog for anything on the master branch that is not part of beta\n4. Creates a changelog for anything on the beta branch\n\nIt opens a browser tab for every PR in order to review each change.\nIt places each PR in the changelog with its title, but usually every PR should be rewritten to explain the change from the user's perspective.\nEach PR should also be categorized as an Addition, Change, Fix, or Nightly-only change.\nMost PRs are deleted, since they are not relevant to users of Cargo.\nFor example, remove all PRs related to Cargo internals, infrastructure, documentation, error changes, refactorings, etc.\nUsually about half of the PRs get removed.\nThis process usually takes @ehuss about an hour to finish.\n\n[@ehuss]: https://github.com/ehuss/\n[cargo-new-release]: https://github.com/ehuss/cargo-new-release\n[`crates/` directory]: https://github.com/rust-lang/cargo/tree/master/crates\n\n## Docs publishing\n\nDocs are automatically published during the Rust release process. The nightly\nchannel's docs appear at <https://doc.rust-lang.org/nightly/cargo/>. Once\nnightly is promoted to beta, those docs will appear at\n<https://doc.rust-lang.org/beta/cargo/>. Once the stable release is made, it\nwill appear on <https://doc.rust-lang.org/cargo/> (which is the \"current\"\nstable) and the release-specific URL such as\n<https://doc.rust-lang.org/1.46.0/cargo/>.\n\nThe code that builds the documentation is located in the [`doc` bootstrap\nmodule].\n\n[`doc` bootstrap module]: https://github.com/rust-lang/rust/blob/master/src/bootstrap/src/core/build_steps/doc.rs\n\n## crates.io publishing\n\nCargo's library and its related dependencies (like `cargo-util`) are published\nto [crates.io] as part of the 6-week stable release process by the [Release\nteam]. The release process involves a series of steps:\n\n1. The Release team's automation scripts (see <https://github.com/rust-lang/simpleinfra/>) will run [`promote-release`] which will create a tag in the `rust-lang/cargo` repository associated with the version of the cargo submodule for that release.\n2. The creation of a tag will trigger the [release workflow] in `rust-lang/cargo`.\n3. The release workflow will run the [`publish.py` script] on the commit associated with the tag.\n4. The `publish.py` script will run `cargo publish` on any crates that are not already published.\n\n[`promote-release`]: https://github.com/rust-lang/promote-release\n[release workflow]: https://github.com/rust-lang/cargo/blob/master/.github/workflows/release.yml\n\nOn very rare cases, the Cargo team may decide to manually publish a new\nrelease to [crates.io]. For example, this may be necessary if there is a\nproblem with the current version that only affects API users, and does not\naffect the `cargo` binary shipped in the stable release. In this situation,\nPRs should be merged to the associated stable release branch in the cargo repo\n(like `rust-1.70.0`) that fix the issue and bump the patch version of the\naffected package. Then you need to work with the Release Team to get a release\npublished to crates.io.[^release-problem]\n\nSome packages are not published automatically because they are not part of the\nRust release train. This currently only includes the [`home`] package. These\nare published manually on an as-needed or as-requested basis by whoever has\npermissions (currently [@ehuss] or the Release/Infra team)[^fix-manual-release].\n\n[^release-problem]: Unfortunately there are some complications with this process. See <https://github.com/rust-lang/cargo/issues/14538> for more detail, and thoughts on how to improve this.\n\n[^fix-manual-release]: This should be fixed, see [crate ownership policy](https://forge.rust-lang.org/policies/crate-ownership.html) about removing ownership. Also see <https://github.com/rust-lang/cargo/issues/14538> for problems with tagging. In general, these should be published from GitHub Actions, but we don't have the infrastructure set up for that, yet.\n\n[`home`]: https://github.com/rust-lang/cargo/tree/master/crates/home\n[`publish.py` script]: https://github.com/rust-lang/cargo/blob/master/publish.py\n\n## Beta backports\n\nIf there is a regression or major problem detected during the beta phase, it\nmay be necessary to backport a fix to beta. The process is documented in the\n[Beta Backporting] page.\n\n[Beta Backporting]: https://forge.rust-lang.org/release/beta-backporting.html\n\n## Stable backports\n\nIn (hopefully!) very rare cases, a major regression or problem may be reported\nafter the stable release. Decisions about this are usually coordinated between\nthe [Release team] and the Cargo team. There is usually a high bar for making\na stable patch release, and the decision may be influenced by whether or not\nthere are other changes that need a new stable release.\n\nThe process here is similar to the beta-backporting process. The\n[rust-lang/cargo] branch is the same as beta (`rust-1.XX.0`). The\n[rust-lang/rust] branch is called `stable`.\n\n[choochoo]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\n[rust-lang/rust]: https://github.com/rust-lang/rust/\n[rust-lang/cargo]: https://github.com/rust-lang/cargo/\n[CHANGELOG]: https://github.com/rust-lang/cargo/blob/master/src/doc/src/CHANGELOG.md\n[release process]: https://forge.rust-lang.org/release/process.html\n[`TargetInfo`]: https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/build_context/target_info.rs\n[crates.io]: https://crates.io/\n[release team]: https://www.rust-lang.org/governance/teams/operations#release\n"
  },
  {
    "path": "src/doc/contrib/src/process/rfc.md",
    "content": "# Writing an RFC\n\nGenerally, an RFC goes through:\n1. Pre-RFC discussions on the [internals forum][irlo]\n2. [RFC]\n3. [Development and stabilization][unstable]\n\nPlease keep in mind our [design principles](../design.md).\n\nFor more concrete areas of consideration:\n\n## `.cargo/config.toml` and `Cargo.toml`\n\n`.cargo/config.toml` is for environment or transient configuration,\nbeing dependent on what directory you are running from and settable on the command-line,\nindependent of other flags like `--manifest-path` or `--package`.\n\nOn the other hand `Cargo.toml` is for static, high-level project configuration.\n\nFor example,\n- [RFC 3537] chose\n  configuration for the MSRV-aware resolver because users would likely need\n  to change this setting, like in CI to verify the opposite case of\n  what they run by default.\n- The Cargo team rejected a [`[cfg]` table][cfg table] to represent `rustc`\n  `--cfg` flags as it was a direct port of low-level rustc behavior that didn't\n  mesh with the other high level abstractions of manifests.\n  - For stabilization, this was worked around through a build script directive and a `[lints]` field configuration.\n- [#12738][cargo#12738] for exploring how existing config might be representable in `Cargo.toml`.\n\n\n[irlo]: https://internals.rust-lang.org/\n[RFC]: https://github.com/rust-lang/rfcs/\n[unstable]: unstable.md\n[RFC 3537]: https://rust-lang.github.io/rfcs/3537-msrv-resolver.html\n[cfg table]: https://github.com/rust-lang/cargo/pull/11631#issuecomment-1487424886\n[cargo#12738]: https://github.com/rust-lang/cargo/issues/12738\n\n## `Cargo.toml`\n\nWhen adding a table to a manifest,\n- Should it be inheritable?\n- Ensure the package table and the inheritable table under `workspace` align\n- Care is needed to ensure a `workspace = true` field doesn't conflict with other entries\n  - e.g. [RFC 3389] had to explicitly exclude ever supporting a `workspace` linter\n\nWhen adding a field,\n- Is it inheritable?\n  - Consider whether sharing of the field would be driven by requirements or is a manifestation of the current implementation.\n    For example, in most cases, dependency sources (e.g. `version` field) should be aligned across a workspace\n    However, frequently dependency `features` will vary across a workspace.\n- When inheriting, can specify it in your package?\n- How does specifying a field in both `workspace` and a package interact?\n  - e.g. dependency sources cannot be overridden\n  - e.g. dependency `features` get merged\n  - e.g. dependency `default-features` has been hard to get right ([#12162][cargo#12162])\n\nWhen working extending `dependencies` tables:\n- How does this affect `cargo add` or `cargo remove`?\n- How does this affect `[patches]` which are just modified dependencies?\n\n[RFC 3389]: https://rust-lang.github.io/rfcs/3389-manifest-lint.html\n[cargo#12162]: https://github.com/rust-lang/cargo/issues/12162\n\n"
  },
  {
    "path": "src/doc/contrib/src/process/security.md",
    "content": "# Security issues\n\nIssues involving reporting a security vulnerability in cargo usually start by following the [Rust security policy].\nThe Security Response Working Group (\"the WG\") is responsible for running the process of handling the response to a security issue.\nTheir process is documented at [Handling Reports].\nThis document gives an overview of the process from a Cargo team member's perspective.\n\nThe general order of events happens as follows:\n\n1. The \"reporter\" (even if it is a Cargo team member) reports an issue to <security@rust-lang.org>.\n1. The WG will evaluate if the report is credible, and manages responses to the reporter.\n1. The WG will start a private Zulip stream to coordinate discussion and plans for a fix.\n1. The WG will pull in one or more team members into the Zulip stream (\"responders\").\n    - Security vulnerabilities are **embargoed** until they are released publicly.\n      People who are brought into these discussions should **not** discuss the issue with *anyone* outside of the group, including your employer, without first consulting The WG.\n1. A discussion then starts to evaluate the severity of the issue and what possible solutions should be considered.\n   This includes figuring out who will volunteer to actually develop the patches to resolve the issue, and who will review it.\n1. The WG will create a temporary private fork of the `rust-lang/cargo` repo using GitHub's [repository security advisory][github-advisory] system.\n   This provides a space where changes can be securely posted, and the security advisory can be drafted.\n   See [\"Collaborating in a temporary private fork\"][private-fork] for some screenshots of what this looks like.\n   GitHub includes instructions on how to work with the fork.\n\n   Beware that the private fork has some limitations, such as not supporting CI, or (for some weird reason) not supporting syntax highlighting.\n1. Someone will need to review the patches and make sure everyone agrees on the solution.\n   This may also involve the WG conferring with the reporter to validate the fix.\n1. Create a rollout plan.\n   This includes deciding if there will be a new patch release of Rust, or if it should wait for the next stable release, or whether to remove the embargo on the fix.\n1. The WG will handle drafting a Security Advisory using GitHub's Security Advisory (\"GHSA\") system.\n   [GHSA-r5w3-xm58-jv6j] is an example of what this looks like.\n   This process also involves reserving a [CVE](https://www.cve.org/) number, where the report will eventually be posted.\n\n   The responders should carefully review the report to make sure it is correct.\n\n   This process may also involve deciding on the CVSS score.\n   There are a bunch of calculators on the web where you can see how this works (such as the [FIRST CVSS Calculator][calc], or you can view GitHub's calculator by drafting a security advisory in one of your personal repos).\n   FIRST has a [user guide][first-guide] for deciding how to score each characteristic.\n1. If it is decided to do a patch release of Rust, the general overview of steps is:\n    1. Finalizing the patches.\n       This includes all the little details like updating changelogs, version numbers, and such.\n    1. Preparing PRs in the private fork against the stable, beta, and nightly (master) branches.\n    1. The WG handles creating a private fork of `rust-lang/rust` to prepare the point release.\n       This usually includes changes for stable, beta, and nightly.\n    1. The WG handles posting patches in various places (such as mailing lists), possibly several days in advance.\n    1. The WG handles posting public PRs to `rust-lang/rust` to incorporate the fix and prepare a new release.\n    1. The WG handles announcing everything, including publishing the GHSA, publishing a blog post, and several other places.\n\n## External dependency patches\n\nSometimes it may be necessary to make changes to external dependencies to support a fix.\nThis can make things complicated.\nIf the change is by itself benign and not directly related to the security issue,\nthen it may be safe to publicly propose the change (but not giving context) and try to get a new release of the dependency made (though confer with the WG first!).\nHowever, if the issue is directly related to the dependency, then it becomes significantly more awkward.\n\nThe general process for [GHSA-r5w3-xm58-jv6j] which involved a fix in `git2-rs` was handled by the responders because it is a dependency owned by the rust-lang org.\nThe general outline of how we managed this is:\n\n- Pre-release:\n    1. Created a private fork of `rust-lang/git2-rs` just like we did for `rust-lang/cargo`.\n       git2-rs also had its own Security Advisory just like cargo did.\n    1. Created and reviewed PRs in the private fork for the fixes.\n        - The PRs in the `rust-lang/cargo` private fork had to have a temporary `[patch]` git dependency on the `git2-rs` private fork.\n    1. Before the release, the PRs were changed to remove the `[patch]`, and pretend as-if git2-rs had already been published.\n- Showtime:\n    1. The git2-rs changes were publicly merged, and a new release was published to crates.io.\n    1. The cargo PR was merged to cargo's stable branch.\n    1. The private rust-lang/rust PR updated the cargo submodule and updated `Cargo.lock` to pick up the new git2 dependencies.\n    1. Release proceeds as normal (publish both GHSA, create release, etc.).\n- Post-release:\n    1. Various forward ports were created in git2-rs, and new releases were made.\n\nIf the change is in a crate not managed by any responder, then confer with the WG on a strategy.\nOne option is to create a temporary fork used for the security response that will be removed as soon as the security advisory is released and a new public release of the dependency is made with the fix.\n\n## Checklist\n\nThere are a lot of details to handle, and it can be a bit of a challenge under time pressure.\nThe following is a checklist of some items to pay attention to during the process.\n\nPre-release:\n- [ ] Check for any SemVer-incompatible changes in the public API of any crates that are modified.\n  - Try to avoid these if at all possible.\n    Although not a severe problem, making Cargo's version number drift farther from Rust's can contribute to confusion.\n  - If a SemVer-breaking release is made to a dependency, make sure this is coordinated correctly between the stable, beta, and master branches.\n- [ ] With a checkout of the proposed fixes, run as much of cargo's CI testsuite locally as you can.\n  Since private forks don't support CI, the responders will be responsible for making sure all tests pass.\n  Enlist other responders if you don't have the necessary systems like Windows.\n- [ ] Manually exercise the fix locally.\n  Since we will essentially have *no* nightly testing, the responders are responsible for making sure things work.\n  Try to consider all the different environments users may be using.\n- [ ] Make sure any comments or docs that need updating get updated.\n- [ ] Review the git commit messages of the patch.\n  Make sure they clearly and accurately reflect what is being changed and why.\n  Clean up the commit history if it goes through several revisions during review.\n- [ ] Make sure that the *public* cargo repo's stable and beta branches are in a state where they are passing CI.\n  This may require backporting changes that fix problems that have already been fixed in master.\n  This can be done publicly at any time, and helps with ensuring a smooth process once the security issue is released.\n  (The WG may disable branch protections to push directly to the stable branch, but this step is still useful to assist with local testing and the beta branch.)\n- [ ] After the fix is approved, create backports to the stable and beta master branches and post PRs to the private fork.\n- [ ] If any internal dependencies are changed, make sure their versions are bumped appropriately, and dependency specifications are updated (stable, beta, and master branches).\n- [ ] Thoroughly test the stable and beta PRs locally, too. We want to make sure everything goes smoothly, and we can't assume that just because a patch applied cleanly that there won't be issues.\n- [ ] Make sure cargo's version in [`Cargo.toml`] is updated correctly on the stable branch private PR.\n- [ ] Make sure cargo's `Cargo.lock` is updated (stable, beta, master branches).\n- [ ] Update [`CHANGELOG.md`] on cargo's master branch private PR.\n- [ ] Update [`RELEASES.md`] on rust's master branch private PR (and stable and beta?).\n- [ ] Remove any temporary things in the patch, like a temporary `[patch]` table.\n\nShowtime:\n- [ ] Publish any embargoed external dependencies to crates.io.\n- [ ] (WG) Merge the cargo stable change.\n- [ ] (WG) Update the cargo submodule in the rust-lang/rust private PR to point to the new stable commit.\n    - [ ] Also update `Cargo.lock`.\n- [ ] (WG) Make a new stable release.\n- [ ] (WG) Publish the GHSA.\n- [ ] (WG) Send announcements.\n- [ ] Make sure stable, beta, and master branches of `rust-lang/cargo` get updated.\n- [ ] Make sure stable, beta, and master branches of `rust-lang/rust` get updated, pointing to the correct submodule versions.\n- [ ] If any external dependencies are updated, make sure their back or forward ports are handled.\n\nPost release:\n- [ ] Verify that the appropriate crates are published on crates.io.\n- [ ] Verify that `rust-lang/cargo` got a new tag.\n- [ ] Verify that the patches were backported to the correct branches in the `rust-lang/cargo` repository (stable, beta, and master).\n- [ ] Verify that the cargo submodule is updated on the correct branches in the `rust-lang/rust` repository (stable, beta, and master).\n- [ ] Follow up on any non-critical tasks that were identified during review.\n\n[Rust security policy]: https://www.rust-lang.org/policies/security\n[github-advisory]: https://docs.github.com/en/code-security/security-advisories/repository-security-advisories\n[private-fork]: https://docs.github.com/en/code-security/security-advisories/repository-security-advisories/collaborating-in-a-temporary-private-fork-to-resolve-a-repository-security-vulnerability\n[calc]: https://www.first.org/cvss/calculator\n[GHSA-r5w3-xm58-jv6j]: https://github.com/rust-lang/cargo/security/advisories/GHSA-r5w3-xm58-jv6j\n[handling reports]: https://github.com/rust-lang/wg-security-response/blob/main/docs/handling-reports.md\n[first-guide]: https://www.first.org/cvss/user-guide\n[`CHANGELOG.md`]: https://github.com/rust-lang/cargo/blob/master/src/doc/src/CHANGELOG.md\n[`Cargo.toml`]: https://github.com/rust-lang/cargo/blob/master/Cargo.toml\n[`RELEASES.md`]: https://github.com/rust-lang/rust/blob/master/RELEASES.md\n"
  },
  {
    "path": "src/doc/contrib/src/process/unstable.md",
    "content": "# Unstable features\n\nMost new features should go through the unstable process. This means that the\nfeature will only be usable on the nightly channel, and requires a specific\nopt-in by the user. Small changes can skip this process, but please consult\nwith the Cargo team first.\n\n## Tracking issues\n\nEach unstable feature should get a [tracking issue]. These issues are\ntypically created when a PR is close to being merged, or soon after it is\nmerged. Use the [tracking issue template] when creating a tracking issue.\n\nLarger features should also get a new label in the issue tracker so that when\nissues are filed, they can be easily tied together. Typically this would be\none of the `Z-` prefixed labels for nightly features.\n\nWhen opening a tracking issue, be sure to also add an `S-` status label to\nindicate what needs to happen for it to move forward:\n\n* [S-needs-mentor] --- The feature isn't yet implemented, and needs a Cargo\n  team member to commit to helping guide and review the implementation.\n* [S-accepted] --- The feature isn't yet implemented, and has a Cargo team\n  member willing to help review the implementation.\n* [S-waiting-on-feedback] --- After the feature has been implemented, this\n  label indicates that it is waiting on community feedback for bugs or design\n  concerns.\n\nTracking issues may have multiple status labels if necessary, for example if\nsomething is only partially implemented, it may have both\n[S-waiting-on-feedback] (for what is implemented) and [S-needs-mentor] or\n[S-accepted] to finish the rest of the work.\n\n[tracking issue]: https://github.com/rust-lang/cargo/labels/C-tracking-issue\n[tracking issue template]: https://github.com/rust-lang/cargo/issues/new?labels=C-tracking-issue&template=tracking_issue.yml\n[S-needs-mentor]: https://github.com/rust-lang/cargo/labels/S-needs-mentor\n[S-accepted]: https://github.com/rust-lang/cargo/labels/S-accepted\n[S-waiting-on-feedback]: https://github.com/rust-lang/cargo/labels/S-waiting-on-feedback\n\n## Implementation\n\nSee [Working on Cargo](working-on-cargo.md).\n\nDuring implementation and testing, you may find reasons to deviate from the RFC.\nPlease call these out in the tracking issue, with links to more information justifying the change\n(e.g. see [workspace inheritance tracking issue]).\n\n[workspace inheritance tracking issue]: https://github.com/rust-lang/cargo/issues/8415\n\n#### Unstable feature opt-in\n\nFor features that require behavior changes or new syntax in `Cargo.toml`, then\nit will need a `cargo-features` value placed at the top of `Cargo.toml` to\nenable it. The process for adding a new feature is described in the\n[`features` module]. Code that implements the feature will need to manually\ncheck that the feature is enabled for the current manifest.\n\nFor features that add new command-line flags, config options, or environment\nvariables, then the `-Z` flags will be needed to enable them. The [`features`\nmodule] also describes how to add these. New flags should use the\n`fail_if_stable_opt` method to check if the `-Z unstable-options` flag has\nbeen passed.\n\n#### Unstable documentation\n\nEvery unstable feature should have a section added to the [unstable chapter]\ndescribing how to use the feature.\nThis can also serve as a place for the final documentation to live until its stabilized.\n\n[unstable chapter]: https://github.com/rust-lang/cargo/blob/master/src/doc/src/reference/unstable.md\n\n## Pre-Stabilization \n\nOnce an unstable feature is \"complete\", the search for users to test\nand give feedback begins:\n1. Write up test instructions for users, summarizing where the feature is useful, how to use it (with links to the unstable documentation), and if there are any areas of particular concern\n  - This could be on the tracking issue or in a dedicated issue for feedback\n  - e.g. [workspace inheritance testing notes]\n2. Call for testing\n  - In the RFC, link to the test instructions and label it with `call-for-testing` to be picked up by [This Week in Rust]\n    - If there is not an RFC, a pull request should be made to the [TWiR repo]\n      adding the feature to the `Call for Testing` section ([example]).\n  - Post on various Rust communities ([rust subreddit], [users], [internals], etc)\n  - e.g. [reddit post], [users post], [internals post]\n\n[workspace inheritance testing notes]: https://github.com/rust-lang/cargo/blob/6d6dd9d9be9c91390da620adf43581619c2fa90e/src/doc/src/reference/unstable.md#testing-notes\n[rust subreddit]: https://www.reddit.com/r/rust/\n[users]: https://users.rust-lang.org/\n[internals]: https://internals.rust-lang.org/\n[reddit post]: https://www.reddit.com/r/rust/comments/uo8zeh/help_test_workspace_inheritance_in_preparation/\n[users post]: https://users.rust-lang.org/t/help-test-workspace-inheritance-in-preparation-for-stablization/75582\n[internals post]: https://internals.rust-lang.org/t/help-test-workspace-inheritance-in-preparation-for-stablization/16618\n[This Week in Rust]: https://this-week-in-rust.org/\n[TWiR repo]: https://github.com/rust-lang/this-week-in-rust\n[example]: https://github.com/rust-lang/this-week-in-rust/pull/3256\n\n## Stabilization\n\nAfter some period of time, typically measured in months, the feature can be\nconsidered to be stabilized. The feature should not have any significant known\nbugs or issues, and any design concerns should be resolved.\n\nThe stabilization process depends on the kind of feature. For smaller\nfeatures, you can leave a comment on the tracking issue expressing interest in\nstabilizing it. It can usually help to indicate that the feature has received\nsome real-world testing, and has exhibited some demand for broad use.\n\nFor larger features that have not gone through the [RFC process], then an RFC\nto call for stabilization might be warranted. This gives the community a final\nchance to provide feedback about the proposed design.\n\nFor a small feature, or one that has already gone through the RFC process, a\nCargo Team member may decide to call for a \"final comment period\" using\n[rfcbot]. This is a public signal that a major change is being made, and gives\nthe Cargo Team members an opportunity to confirm or block the change. This\nprocess can take a few days or weeks, or longer if a concern is raised.\n\nOnce the stabilization has been approved, the person who called for\nstabilization should prepare a PR to stabilize the feature. This PR should:\n\n* Flip the feature to stable in the [`features` module].\n* Remove any unstable checks that aren't automatically handled by the feature\n  system.\n* Move the documentation from the [unstable chapter] into the appropriate\n  places in the Cargo book and man pages.\n* Remove the `-Z` flags and help message if applicable.\n* Update all tests to remove nightly checks.\n* Tag the PR with [relnotes] label if it seems important enough to highlight\n  in the [Rust release notes].\n\n[`features` module]: https://github.com/rust-lang/cargo/blob/master/src/cargo/core/features.rs\n[RFC process]: https://github.com/rust-lang/rfcs/\n[rfcbot]: https://github.com/rust-lang/rfcbot-rs\n[Rust release notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md\n[relnotes]: https://github.com/rust-lang/cargo/issues?q=label%3Arelnotes\n"
  },
  {
    "path": "src/doc/contrib/src/process/working-on-cargo.md",
    "content": "# Working on Cargo\n\nThis chapter gives an overview of how to build Cargo, make a change, and\nsubmit a Pull Request.\n\n0. [Before hacking on Cargo.](#before-hacking-on-cargo)\n1. [Check out the Cargo source.](#checkout-out-the-source)\n2. [Building Cargo.](#building-cargo)\n3. [Making a change.](#making-a-change)\n4. [Writing and running tests.](../tests/index.md)\n5. [Submitting a Pull Request.](#submitting-a-pull-request)\n6. [The merging process.](#the-merging-process)\n\n## Before hacking on Cargo\n\nWe encourage people to discuss their design before hacking on code. This gives\nthe Cargo team a chance to know your idea more. Sometimes after a discussion,\nwe even find a way to solve the problem without coding! Typically, you\n[file an issue] or start a thread on the [internals forum] before submitting a\npull request.\n\nPlease read [the process] of how features and bugs are managed in Cargo.\n**Only issues that have been explicitly marked as [accepted] will be reviewed.**\n\n## Checkout the source\n\nWe use the \"fork and pull\" model [described here][development-models], where\ncontributors push changes to their personal fork and [create pull requests] to\nbring those changes into the source repository. Cargo uses [git] and [GitHub]\nfor all development.\n\n1. Fork the [`rust-lang/cargo`] repository on GitHub to your personal account\n   (see [GitHub docs][how-to-fork]).\n2. Clone your fork to your local machine using `git clone` (see [GitHub\n   docs][how-to-clone])\n3. It is recommended to start a new branch for the change you want to make.\n   All Pull Requests are made against the master branch.\n\n## Building Cargo\n\nCargo is built by...running `cargo`! There are a few prerequisites that you\nneed to have installed:\n\n* `rustc` and `cargo` need to be installed. Cargo is expected to build and\n  test with the current stable, beta, and nightly releases. It is your choice\n  which to use. Nightly is recommended, since some nightly-specific tests are\n  disabled when using the stable release. But using stable is fine if you\n  aren't working on those.\n* A C compiler (typically gcc, clang, or MSVC).\n* [git]\n* Unix:\n    * pkg-config\n    * OpenSSL (`libssl-dev` on Ubuntu, `openssl-devel` on Fedora)\n* macOS:\n    * OpenSSL ([homebrew] is recommended to install the `openssl` package)\n\nIf you can successfully run `cargo build`, you should be good to go!\n\n[homebrew]: https://brew.sh/\n\n## Running Cargo\n\nYou can use `cargo run` to run cargo itself, or you can use the path directly\nto the cargo binary, such as `target/debug/cargo`.\n\nIf you are using [`rustup`], beware that running the binary directly can cause\nissues with rustup overrides. Usually, when `cargo` is executed as part of\nrustup, the toolchain becomes sticky (via an environment variable), and all\ncalls to `rustc` will use the same toolchain. But when `cargo` is not run via\nrustup, the toolchain may change based on the directory. Since Cargo changes\nthe directory for each compilation, this can cause different calls to `rustc`\nto use different versions. There are a few workarounds:\n\n* Don't use rustup overrides.\n* Use `rustup run <toolchain> target/debug/cargo` to specify the toolchain(rustc) to use.\n  For example, `rustup run nightly target/debug/cargo`.\n* Set the `RUSTC` environment variable to a specific `rustc` executable (not\n  the rustup wrapper).\n* Create a [custom toolchain]. This is a bit of a hack, but you can create a\n  directory in the rustup `toolchains` directory, and create symlinks for all\n  the files and directories in there to your toolchain of choice (such as\n  nightly), except for the `cargo` binary, which you can symlink to your\n  `target/debug/cargo` binary in your project directory.\n\n*Normally*, all development is done by running Cargo's test suite, so running\nit directly usually isn't required. But it can be useful for testing Cargo on\nmore complex projects.\n\n[`rustup`]: https://rust-lang.github.io/rustup/\n[custom toolchain]: https://rust-lang.github.io/rustup/concepts/toolchains.html#custom-toolchains\n\n## Making a change\n\nSome guidelines on working on a change:\n\n* All code changes are expected to comply with the formatting suggested by\n  `rustfmt`. You can use `rustup component add rustfmt` to install `rustfmt`\n  and use `cargo fmt` to automatically format your code.\n* Include tests that cover all non-trivial code. See the [Testing chapter] for\n  more about writing and running tests.\n* All code should be warning-free. This is checked during tests.\n* All changes should be free of typos. Cargo's CI has a job that runs [`typos`]\n  to enforce this. You can use `cargo spellcheck` to run this check locally,\n  and `cargo spellcheck --write-changes` to fix most typos automatically.\n\n[`typos`]: https://github.com/crate-ci/typos\n\n## Submitting a Pull Request\n\nAfter you have committed your work, and pushed it to GitHub, you can\nopen a Pull Request\n\n* Push your commits to GitHub and create a pull request against Cargo's\n  `master` branch.\n* Include a clear description of what the change is and why it is being made.\n* Use [GitHub's keywords] in the description to automatically link to an issue\n  if the PR resolves the issue. For example `Closes #1234` will link issue\n  #1234 to the PR. When the PR is merged, GitHub will automatically close the\n  issue.\n\n[`@rustbot`] will automatically assign a reviewer for the PR. It\nmay take at least a few days for someone to respond. If you don't get a\nresponse in over a week, feel free to ping the assigned reviewer.\n\nWhen your PR is submitted, GitHub automatically runs all tests. The GitHub\ninterface will show a green checkmark if it passes, or a red X if it fails.\nThere are links to the logs on the PR page to diagnose any issues. The tests\ntypically finish in under 30 minutes.\n\nThe reviewer might point out changes deemed necessary. Large or tricky changes\nmay require several passes of review and changes.\n\n> **tip:** Prefer atomic commits where each commit is a single, complete, and coherent unit of work.\n> For example, if your feature work leads to renaming a module, make the rename its own commit.\n> However, adding an internal function that is unused is not complete or coherent.\n>\n> As part of your atomic commits, prefer adding tests as their own commit *before* any functionality changes.\n> The tests should pass in each commit, demonstrating the behavior before your\n> change and how each commit affects behavior.\n> This makes it easier for reviewers and community members to understand the\n> precise details of the side effects of your change and gives you confidence\n> that your tests are verifying the right behavior.\n>\n> Examples:\n> - [#13910: fix: remove symlink dir on Windows](https://github.com/rust-lang/cargo/pull/13910)\n> - [#14006: fix(add): Avoid escaping double-quotes by using string literals](https://github.com/rust-lang/cargo/pull/14006)\n\n### Status labeling\n\nPRs will get marked with [labels] like [`S-waiting-on-review`] or [`S-waiting-on-author`] to indicate their status.\nThe [`@rustbot`] bot can be used by anyone to adjust the labels.\nIf a PR gets marked as `S-waiting-on-author`, and you have pushed new changes that you would like to be reviewed, you can write a comment on the PR with the text `@rustbot ready`.\nThe bot will switch the labels on the PR.\n\nMore information about these commands can be found at the [shortcuts documentation].\n\n[labels]: https://github.com/rust-lang/cargo/labels\n[`S-waiting-on-review`]: https://github.com/rust-lang/cargo/labels/S-waiting-on-review\n[`S-waiting-on-author`]: https://github.com/rust-lang/cargo/labels/S-waiting-on-author\n[`@rustbot`]: https://github.com/rustbot\n[shortcuts documentation]: https://forge.rust-lang.org/triagebot/shortcuts.html\n\n## The merging process\n\nAfter a reviewer has approved your PR,\nthey will add the PR to [GitHub merge queue].\nThe merge queue will create a temporary branch with your PR,\nand run all required jobs.\nIf it fails, it will be removed from the queue.\nThe merge queue ensures that the master branch is always in a good state,\nand that merges are processed one at a time.\nThe [merge queue dashboard] shows the current queued pull requests.\n\nAssuming everything works, congratulations! It may take at least a week for\nthe changes to arrive on the nightly channel. See the [release chapter] for\nmore information on how Cargo releases are made.\n\n[development-models]: https://help.github.com/articles/about-collaborative-development-models/\n[create pull requests]: https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request\n[how-to-fork]: https://docs.github.com/en/github/getting-started-with-github/fork-a-repo\n[`rust-lang/cargo`]: https://github.com/rust-lang/cargo/\n[git]: https://git-scm.com/\n[GitHub]: https://github.com/\n[how-to-clone]: https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository\n[Testing chapter]: ../tests/index.md\n[GitHub's keywords]: https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue\n[GitHub merge queue]: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue\n[merge queue dashboard]: https://github.com/rust-lang/cargo/queue/master\n[release chapter]: release.md\n[internals forum]: https://internals.rust-lang.org/c/tools-and-infrastructure/cargo\n[file an issue]: https://github.com/rust-lang/cargo/issues\n[the process]: index.md\n[accepted]: https://github.com/rust-lang/cargo/issues?q=is%3Aissue+is%3Aopen+label%3AS-accepted\n"
  },
  {
    "path": "src/doc/contrib/src/team.md",
    "content": "# Cargo Team\n\n## Mission\n\nThe Cargo Team is a group of volunteers that support the Rust community in developing and maintaining Cargo, the Rust package manager and build tool.\nThe team is responsible for deciding how Cargo and its related libraries operate and evolve.\nThe team has a shared responsibility with the [crates.io team] for the design and usage of Cargo's index format and its registry API as it relates to the [crates.io] service.\n\nThe team is expected to keep Cargo in an operational state, to support Rust's 6-week release cycle, and to uphold the [Design Principles] of Cargo.\n\n[crates.io team]: https://www.rust-lang.org/governance/teams/crates-io\n[crates.io]: https://crates.io/\n[Design Principles]: design.md\n\n## Team membership\n\nThe Cargo Team consists of team members with one serving as a team leader.\nThe team leader is responsible for coordinating the team and providing a contact point with other teams.\nThe leader is selected by consensus of the existing members with no objections.\n\nMembership is maintained in the [Rust team database].\n\n[Rust team database]: https://github.com/rust-lang/team/blob/master/teams/cargo.toml\n\n### Membership expectations\n\nTeam members are expected to participate in voting on RFCs and major change proposals\n\nTeam members are expected to regularly participate in at least some of the following membership-related activities.\nMembers are not expected to participate in all of these activities, but exhibit some interest and involvement in the project that covers some of these activities.\n\n- Attending meetings\n- Reviewing contributions (auto-assignment is managed in [triagebot.toml])\n- Triaging and responding to issues\n- Mentoring new contributors\n- Shepherding major changes and RFCs\n- Coordinating interaction with other Rust groups and outside interests\n- Managing and updating the policies of the Cargo Team itself\n- Keeping up with maintenance of the Cargo codebase, ensuring it stays functional and that infrastructure and team processes continue to run smoothly\n\nBreaks and vacations are welcome and encouraged.\nIf a member is no longer participating after a few months, they may be asked to step down.\n\nMembers are required to always:\n\n- Represent the Rust project in a way that upholds the [Rust code of conduct][coc] to a high standard.\n- Represent the Cargo Team in a way that upholds the expectations of this charter, and be friendly, welcoming, and constructive with contributors and users.\n\nMembers are given privileges, such as:\n\n- Merge permissions (GitHub permissions)\n- Issue and project management (GitHub permissions)\n- Voting and decision making (RFCs, major changes)\n- Access to private communications related to team management and security discussions\n\n[coc]: https://www.rust-lang.org/policies/code-of-conduct\n[triagebot.toml]: https://github.com/rust-lang/cargo/blob/master/triagebot.toml\n\n### Meetings\n\nThe primary focus of team meetings is for unblocking designs, including discussing\n- [RFCs][t-cargo-rfcs]\n- [FCPs][cargo-status-tracker]\n- [Items marked **I-nominated-to-discuss**][i-nominated] or [**I-cargo-nominated** on `rust-lang/rust`][i-cargo-nominated]\n- [Items marked **S-needs-team-input**][s-team-input]\n- Topics proposed on [Zulip][zulip-meeting], subject to availability\n\nGenerally, topics for the agenda should be posted a day in advance to give people the opportunity to review them before the meeting.\n\nThe team meets on a weekly basis ([ics][meeting-ics]) on a video chat.\nMembers of the community are welcome to attend.\nMinutes for all meetings are recorded on [HackMD][meeting-minutes]. After the meeting, meeting notes are permanently recorded in <https://github.com/rust-lang/cargo-team/tree/main/meetings/sync-meeting>.\n\nFor discussing contributions, [Office Hours](process/index.md#mentorship) would be more appropriate venue.\n\n[t-cargo-rfcs]: https://github.com/rust-lang/rfcs/pulls?q=is%3Apr+is%3Aopen+label%3AT-cargo\n[cargo-status-tracker]: https://github.com/orgs/rust-lang/projects/47\n[i-nominated]: https://github.com/rust-lang/cargo/labels/I-nominated-to-discuss\n[i-cargo-nominated]: https://github.com/rust-lang/rust/issues?q=label%3AI-cargo-nominated\n[s-team-input]: https://github.com/rust-lang/cargo/labels/S-needs-team-input\n[meeting-ics]: https://rust-lang.github.io/calendar/cargo/team-meeting.ics\n[meeting-minutes]: https://hackmd.io/@rust-cargo-team?tags=%5B%22meetings%22%5D\n[zulip-meeting]: https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/Cargo.20meeting\n\n### Becoming a member\n\nA contributor can become a member of the Cargo Team by requesting a review or being nominated by one of the existing members.\nThey can be added by unanimous consent of the team.\nThe team lead or another member of the team will also confirm with the moderation team that there are no concerns involving the proposed team member.\n\nContributors who wish to join the team should exhibit an interest in carrying the design principles of Cargo and participate in some of the activities listed above in [Membership Expectations](#membership-expectations).\n\nMembers may leave at any time, preferably by letting the team know ahead of time.\n\n## Team resources\n\n### GitHub\n\nThe Cargo team has various permissions on GitHub:\n\n- [`rust-lang/cargo`](https://github.com/rust-lang/cargo) --- The primary repository for Cargo development.\n- [`rust-lang/cargo-team`](https://github.com/rust-lang/cargo-team) --- The repository for the Cargo team, primarily hosting meeting notes.\n- [`rust-lang/rust`](https://github.com/rust-lang/rust) --- The primary repository for Rust releases. The cargo team has \"write\" permission, and also permission to approve merges via [bors](https://bors.rust-lang.org/) (primarily for [submodule updates]).\n- [`rust-lang/annotate-snippets-rs`](https://github.com/rust-lang/annotate-snippets-rs) --- The diagnostic formatting library shared between `rustc` and `cargo`.\n- [`rust-lang/git2-rs`](https://github.com/rust-lang/annotate-snippets-rs) --- The bindings to the libgit2 library used by `cargo`.\n- [`rust-lang/jobserver-rs`](https://github.com/rust-lang/jobserver-rs) --- The jobserver library.\n- [`rust-lang/wg-cargo-std-aware`](https://github.com/rust-lang/wg-cargo-std-aware) --- Repository used to coordinate the efforts to support building `std` with cargo.\n\n[submodule updates]: process/release.md#submodule-updates\n\n### Zulip\n\nThe Cargo team has several streams on Zulip:\n\n- [`#t-cargo`](https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo) --- General public channel for discussing any topics related to Cargo.\n- [`#t-cargo/build-integration`](https://rust-lang.zulipchat.com/#narrow/stream/334885-t-cargo.2Fbuild-integration) --- Discussions about integration with build systems.\n- [`#t-cargo/PubGrub`](https://rust-lang.zulipchat.com/#narrow/stream/260232-t-cargo.2FPubGrub) --- Discussions about the [PubGrub](https://github.com/pubgrub-rs/pubgrub) project.\n\nThe following are private streams for the Cargo team. The team should avoid using this unless necessary (for example, discussing a security issue or team and meeting organization).\n\n- [`#t-cargo/private`](https://rust-lang.zulipchat.com/#narrow/stream/296752-t-cargo.2Fprivate) --- Private channel for discussions among the team.\n- [`#t-cargo/meetings`](https://rust-lang.zulipchat.com/#narrow/stream/364532-t-cargo.2Fmeetings) --- Private channel for discussions about team meetings, including non-members who regularly attend the meetings.\n\n### HackMD\n\nThe Cargo team has a shared, public workspace on HackMD at <https://hackmd.io/@rust-cargo-team> for drafting documents and recording meeting minutes.\n\nSince this HackMD workspace is using the free service, it does not support private documents. If you need to draft a private document, create it in your personal workspace and use private channels to share the link.\n\n### Misc services\n\nThe Cargo team has permissions and access to various services provided by the Rust organization:\n\n- Crater --- The Cargo team has permissions to do crater runs as needed. See [the Crater chapter](tests/crater.md) for more information.\n- Perf --- The Cargo team has permissions to do perf runs as needed. See [the compiler performance chapter][perf] for more information. Note that this generally only exercises the compiler, so its use may be limited.\n- Blog --- The Cargo team is welcome to post on [the Rust blog] (usually [Inside Rust]). See the [blogs policy] for more information.\n- Travel grants --- Travel grants are available for going to conferences. See the [travel policy] for more information.\n\n[perf]: https://rustc-dev-guide.rust-lang.org/tests/perf.html#manual-perf-runs\n[the Rust blog]: https://blog.rust-lang.org/\n[Inside Rust]: https://blog.rust-lang.org/inside-rust/\n[blogs policy]: https://forge.rust-lang.org/platforms/blogs.html\n[travel policy]: https://github.com/rust-lang/leadership-council/blob/main/policies/spending/travel.md\n\n## Decision process\n\nThe team uses a consensus-driven process for making decisions ranging from new features and major changes to management of the team itself.\nThe degree of process is correlated with the degree of change being proposed:\n\n- Bug fixes, refactorings, documentation updates, and other small changes are usually delegated to a single team member (who is not the author) to approve based on their judgement.\n  Team members may also solicit feedback from other members or the whole team for any change should they want to gather other perspectives from the team.\n\n  Some examples of what this might cover are:\n  - Bug fixes that do not introduce backwards-incompatible changes, and adhere to Cargo's expected behavior.\n  - Addition of new warnings, or other diagnostic changes.\n  - New or updated documentation.\n  - Localized refactorings (that is, those that do not have a significant, wide-ranging impact to the usage and maintenance of the codebase).\n  - Minor or planned changes to Cargo's console output.\n  - Beta backports that clearly address a regression, and are expected to be low-risk.\n  - Development of a previously approved unstable feature that matches the expected development of that feature.\n\n- Small features or changes, large refactorings, or major changes to Cargo's codebase or process require an approval by the team via consensus.\n  These decisions can be done via the FCP process of [rfcbot], or in an ad-hoc manner such as during a team meeting.\n  rfcbot FCP requests do not require waiting for the 10-day feedback window if there is a complete team consensus, as this process is mostly aimed at polling the team rather than publicly soliciting feedback.\n  Though, public feedback is welcome at any time.\n\n  Some examples of what this might cover are:\n  - Addition of a new, minor command-line argument, or an addition of an option to an existing one.\n  - Addition of new fields and values to JSON outputs.\n  - A bug fix or change that may technically involve a backwards-incompatible change.\n    See the [Backwards compatibility] section for some examples.\n  - Documentation changes that may substantially change the expected usage of Rust and Cargo.\n    For example, the [SemVer chapter] contains subjective prescriptions for how users should develop their code.\n  - A significant change in Cargo's console output.\n  - A significant change to Cargo's code structure, or how maintenance or usage of the Cargo codebase is handled.\n  - Beta backports that are risky or have any uncertainty about their necessity.\n  - [Stable backports].\n    These usually also require involvement with the Release team.\n  - A significant change to the management of the Cargo team itself or the processes it uses, such as significant updates to this document.\n  - Addition of new members to the Cargo team, or other actions involving the team membership.\n    These decisions are usually processed via private channels by the entirety of the team.\n  - A change that is a \"one-way door\".\n    That is, something that is difficult to reverse without breaking backwards compatibility.\n  - New or transferred \"Intentional Artifact\" crates to the team, see also [Rust crate ownership policy](https://forge.rust-lang.org/policies/crate-ownership.html)\n\n- Larger features should usually go through the [RFC process].\n  This usually involves first soliciting feedback from the Cargo team and the rest of the community, often via the [Rust Internals] discussion board, [Cargo's issue tracker], and the [Zulip] channel.\n  If there is positive feedback to the idea, the next step is to formally post an RFC on the RFC repo.\n  The community and the Cargo team will have an opportunity to provide feedback on the proposal.\n  After some period of time, the Cargo team may decide to either accept, postpone, or close a proposal based on the interest in the proposal and the team's availability.\n\n  Some examples of what this might cover are:\n  - Major changes or new features or options in `Cargo.toml` or the config files.\n  - Changes to the registry index or API.\n  - New or changed CLI options that are expected to have a significant impact on how Cargo is used.\n  - New `cargo` commands that are not trivial.\n    In some cases, the team may decide to adopt a pre-existing external command without an RFC if the command has already been broadly adopted.\n\n- Stabilization of [Unstable] features requires an approval via the FCP process of [rfcbot].\n  This provides a final opportunity to solicit feedback from the public, and for the Cargo team to agree via consensus.\n\n- The team may decide to experiment with larger features without starting the RFC process if it is an initiative that the team has consensus that it is something they want to pursue.\n  This is usually reserved for something that has an unclear path that the RFC process is not expected to provide feedback that would substantially move the process forward.\n  Such experiments are expected to be nightly-only (see the [Unstable] chapter), and involve efforts to shape the final result via exploration, testing, and public involvement.\n  Any such features *must* ultimately have an RFC approved before they can be stabilized.\n\n[rfcbot]: https://github.com/rust-lang/rfcbot-rs\n[RFC process]: https://github.com/rust-lang/rfcs/\n[Rust Internals]: https://internals.rust-lang.org/\n[Unstable]: process/unstable.md\n[Backwards compatibility]: design.md#backwards-compatibility\n[Stable backports]: process/release.md#stable-backports\n[SemVer chapter]: https://doc.rust-lang.org/cargo/reference/semver.html\n\n## Intentional Artifacts\n\nPer the [Rust crate ownership policy](https://forge.rust-lang.org/policies/crate-ownership.html), the Cargo team's \"Intentional Artifacts\" include:\n\n- [build-rs](https://crates.io/crates/build-rs)\n- [cargo-credential](https://crates.io/crates/cargo-credential)\n- [cargo-platform](https://crates.io/crates/cargo-platform)\n- [cargo-util-schemas](https://crates.io/crates/cargo-util-schemas)\n- [crates-io](https://crates.io/crates/crates-io)\n\n## Contacting the team\n\nThe team may be contacted through several channels:\n\n- If you have a **security concern**, please refer to Rust's [security policy] for the correct contact method.\n- Issues and feature requests can be submitted to [Cargo's issue tracker].\n  Please see the [Issues chapter] for more detail.\n- The [`t-cargo` Zulip channel][Zulip] stream is the chat platform the Cargo Team uses to coordinate on.\n- The <cargo@rust-lang.org> email address can be used to contact the team.\n  However, using one of the other channels is strongly encouraged.\n\n[Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo\n[security policy]: https://www.rust-lang.org/security.html\n[Cargo's issue tracker]: https://github.com/rust-lang/cargo/issues/\n[Issues chapter]: issues.md\n"
  },
  {
    "path": "src/doc/contrib/src/tests/crater.md",
    "content": "# Crater\n\n[Crater](https://github.com/rust-lang/crater) is a tool for compiling and running tests for _every_ crate on [crates.io](https://crates.io) (and a few on GitHub).\nIt is mainly used for checking the extent of breakage when implementing potentially breaking changes and ensuring lack of breakage by running beta vs stable compiler versions.\n\nEssentially it runs some `cargo` command on every crate twice; once against the \"start\" toolchain and again against the \"end\" toolchain.\nFor example, \"start\" could be the stable release, and \"end\" could be beta.\nIf it passes in \"start\" but fails with \"end\", then that is reported as a regression.\n\nThere is a bot called [craterbot] which is used to run crater on hardware managed by the rust-lang organization.\n\nCrater is run by the release team during the beta cycle.\nIf there are any regressions that look like they are caused by Cargo, they should contact the Cargo team to decide how to handle it.\n\n## Running crater\n\nIf you have a change that you want to test before the beta release, or you want to test behavior that is not normally exercised by crater, you can do a manual run of crater.\nRoughly the steps are:\n\n1. Create a branch with your changes.\n\n   In your clone of cargo, make the changes to incorporate whatever new thing you want to test and push it to a branch on your fork on GitHub.\n\n2. Get a clone of <https://github.com/rust-lang/rust>\n\n3. Create a branch in your rust-lang/rust clone to add your changes.\n\n4. Change the `src/tools/cargo` submodule to point to your new branch.\n\n   Modify `.gitmodules` to point to your clone and branch of cargo with the changes you want to test.\n   For example:\n\n   ```bash\n   git submodule set-url src/tools/cargo https://github.com/ehuss/cargo.git\n   git submodule set-branch --branch my-awesome-feature src/tools/cargo\n   git submodule update --remote src/tools/cargo\n   git add .gitmodules src/tools/cargo\n   git commit\n   ```\n\n5. Create a PR on rust-lang/rust.\n\n   Push your submodule changes to GitHub and make a PR.\n   Start the PR title with `[EXPERIMENT]` to make it clear what the PR is for and assign yourself or @ghost.\n\n6. Make a \"try\" build.\n\n   A \"try\" build creates a full release of x86_64-unknown-linux-gnu and stores it on rust-lang servers.\n   This can be done with a comment `@bors try` on the PR (all Cargo team members should have permission to do this).\n\n7. Run crater.\n\n   Look at the [craterbot] docs to determine the command that you want to run.\n   There are different modes like `check-only`, `build-and-test`, `rustdoc`, etc.\n\n   You can also choose how many crates to run against.\n   If you are uncertain if your cargo changes will work correctly, it might be a good idea to run against `top-100` first to check its behavior.\n   This will run much faster.\n   You can do a full run afterwards.\n\n   After the try build finishes (which should take a couple hours), ask someone to make a crater run.\n   The Cargo team does not have that permission, so just ask someone on Zulip.\n   They will need to write a comment to `@craterbot` with the command that you have specified.\n\n8. Wait.\n\n   Crater can take anywhere from a few hours to a few weeks to run depending on how long the [craterbot queue](https://crater.rust-lang.org/) is and which mode you picked and the priority of your job.\n   When the crater run finishes, craterbot will post a comment to the PR with a link to a report of the results.\n\n9. Investigate the report.\n\n   Look through the report which contains links to build logs for any regressions or errors.\n\n10. Close the PR.\n\n    Whenever you are done doing crater runs, close your PR.\n\n[craterbot]: https://github.com/rust-lang/crater/blob/master/docs/bot-usage.md\n\n\n## Advanced crater modes\n\nCrater only has a few built-in modes, such as running `cargo check` or `cargo test`.\nYou can pass extra flags with `+cargoflags`.\n\nMore complex tests can be accomplished by customizing Cargo to perform whatever actions you want.\nSince crater essentially runs `cargo check`, you can modify the `check` command to perform whichever actions you want.\nFor example, to test `cargo fix --edition`, [this commit](https://github.com/ehuss/cargo/commit/6901690a6f8d519efb4fabf48c1c2b94af0c3bd8) intercepted `cargo check` and modified it to instead:\n\n1. Only run on crates with the 2018 edition.\n2. Run `cargo fix --edition`.\n3. Modify the manifest to switch to the 2021 edition.\n4. Run `cargo check` to verify.\n\nIf you need to compare the before and after of a command that is not part of crater's built-in modes, that can be more difficult.\nTwo possible options:\n\n* Work with the infra team to add a new mode.\n* Build two custom try builds.\n  Each one should modify the `cargo check` command as described above.\n  The \"start\" build should perform whichever action you want with an otherwise unmodified cargo.\n  The \"end\" build should perform whichever action you want with your modified cargo.\n  Then, in the `@craterbot` command, specify the start and end hashes of the two try builds.\n\n## Limitations\n\nThere are some limitations of crater to consider when running Cargo:\n\n* A crater run without regressions is not a green light to move forward.\n   * A large portion of Rust code is not tested, such as closed-source projects or things otherwise not collected by crater.\n   * Many crates can't build in crater's environment or are otherwise broken.\n   * Some crates have flaky tests.\n* Crater runs in an isolated environment.\n    * It only runs on Linux x86-64.\n    * It does not have network access.\n    * The crate source is in a read-only mount.\n* Crater does several steps before running the test (using its own copy of the stable toolchain):\n    * It generates a lockfile using `generate-lockfile` and includes `-Zno-index-update` to prevent index updates (which makes it run much faster).\n    * All dependencies are downloaded ahead-of-time with `cargo fetch`.\n* The built-in modes pass several flags to cargo such as `--frozen` or `--message-format=json`.\n  It will sometimes use `--all-targets` and sometimes not.\n  Check the [crater source](https://github.com/rust-lang/crater/blob/master/src/runner/test.rs) for more details on how it works.\n"
  },
  {
    "path": "src/doc/contrib/src/tests/index.md",
    "content": "# Tests\n\nCargo has an extensive test suite. Most of it is implemented as integration\ntests in the [`testsuite`] directory. There are several other tests:\n\n* Unit tests are scattered throughout.\n* The dependency resolver has its own set of tests in the [`resolver-tests`]\n  directory.\n* All of the packages in the [`crates`] directory have their own set of tests.\n* The [`build-std`] test is for the [build-std feature]. It is separate since\n  it has some special requirements.\n* Documentation has a variety of tests, such as link validation, and the\n  [SemVer chapter validity checks].\n\n[`testsuite`]: https://github.com/rust-lang/cargo/tree/master/tests/testsuite/\n[`resolver-tests`]: https://github.com/rust-lang/cargo/tree/master/crates/resolver-tests\n[`crates`]: https://github.com/rust-lang/cargo/tree/master/crates\n[`build-std`]: https://github.com/rust-lang/cargo/blob/master/tests/build-std/main.rs\n[build-std feature]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std\n[SemVer chapter validity checks]: https://github.com/rust-lang/cargo/tree/master/src/doc/semver-check\n"
  },
  {
    "path": "src/doc/contrib/src/tests/profiling.md",
    "content": "# Benchmarking and Profiling\n\n## Internal profiler\n\nCargo leverages [tracing](https://crates.io/crates/tracing)\nas a basic, hierarchical built-in profiler.\n\nEnvironment variables:\n- `CARGO_LOG_PROFILE=<true|1>`: log tracing events to a file in the current working directory\n- `CARGO_LOG_PROFILE_CAPTURE_ARGS=<true|1>`: include arguments in the events\n\nAt process exit, your trace will be in a file like `trace-1668480819035032.json`.\nOpen that file with [ui.perfetto.dev](https://ui.perfetto.dev) (or chrome://tracing) to browse your trace.\n\nExample:\n```console\n$ # Output first three levels of profiling info\n$ CARGO_LOG_PROFILE=true cargo generate-lockfile\n```\n\n**Note:** This is intended for the development of cargo and there are no compatibility guarantees on this functionality.\n\n## Benchmarking\n\n### Benchsuite\n\nHead over to the [`benches`\ndirectory](https://github.com/rust-lang/cargo/tree/master/benches) for more\ninformation about the benchmarking suite.\n\n### Informal benchmarking\n\nThe overhead for starting a build should be kept as low as possible\n(preferably, well under 0.5 seconds on most projects and systems). Currently,\nthe primary parts that affect this are:\n\n* Running the resolver.\n* Querying the index.\n* Checking git dependencies.\n* Scanning the local project.\n* Building the unit dependency graph.\n\nOne way to test this is to use [hyperfine]. This is a tool that can be used to\nmeasure the difference between different commands and settings. Usually this\nis done by measuring the time it takes for `cargo build` to finish in a large\nproject where the build is fresh (no actual compilation is performed). Just\nrun `cargo build` once before using hyperfine.\n\n[hyperfine]: https://github.com/sharkdp/hyperfine\n"
  },
  {
    "path": "src/doc/contrib/src/tests/running.md",
    "content": "# Running Tests\n\nUsing `cargo test` is usually sufficient for running the full test suite. This\ncan take a few minutes, so you may want to use more targeted flags to pick the\nspecific test you want to run, such as `cargo test --test testsuite\n-- check::check_success`.\n\n## Running nightly tests\n\nSome tests only run on the nightly toolchain, and will be ignored on other\nchannels. It is recommended that you run tests with both nightly and stable to\nensure everything is working as expected.\n\nSome of the nightly tests require the `rustc-dev` and `llvm-tools-preview`\nrustup components installed. These components include the compiler as a\nlibrary. This may already be installed with your nightly toolchain, but if it\nisn't, run `rustup component add rustc-dev llvm-tools-preview\n--toolchain=nightly`.\n\n## Running cross tests\n\nSome tests exercise cross compiling to a different target. This will require\nyou to install the appropriate target. This typically is the 32-bit target of\nyour host platform. For example, if your host is a 64-bit\n`x86_64-unknown-linux-gnu`, then you should install the 32-bit target with\n`rustup target add i686-unknown-linux-gnu`. If you don't have the alternate\ntarget installed, there should be an error message telling you what to do. You\nmay also need to install additional tools for the target. For example, on Ubuntu\nyou should install the `gcc-multilib` package.\n\nIf you can't install an alternate target, you can set the\n`CFG_DISABLE_CROSS_TESTS=1` environment variable to disable these tests. The\nWindows cross tests only support the MSVC toolchain.\n\n## Running build-std tests\n\nThe `build-std` tests are disabled by default, but you can run them by setting\nthe `CARGO_RUN_BUILD_STD_TESTS=1` environment variable and running `cargo test\n--test build-std`. This requires the nightly channel, and also requires the\n`rust-src` component installed with `rustup component add rust-src\n--toolchain=nightly`.\n\n## Running with `gitoxide` as default git backend in tests\n\nBy default, the `git2` backend is used for most git operations. As tests need to explicitly\nopt-in to use nightly features and feature flags, adjusting all tests to run with nightly\nand `-Zgitoxide` is unfeasible.\n\nThis is why the private environment variable named `__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2` can be\nset while running tests to automatically enable the `-Zgitoxide` flag implicitly, allowing to\ntest `gitoxide` for the entire cargo test suite.\n\n## Running public network tests\n\nSome (very rare) tests involve connecting to the public internet.\nThese tests are disabled by default,\nbut you can run them by setting the `CARGO_PUBLIC_NETWORK_TESTS=1` environment variable.\nAdditionally our CI suite has a smoke test for fetching dependencies.\nFor most contributors, you will never need to bother with this.\n\n## Running container tests\n\nTests marked with `container_test` involve running Docker to test more complex configurations.\nThese tests are disabled by default,\nbut you can run them by setting the `CARGO_CONTAINER_TESTS=1` environment variable.\nYou will need to have Docker installed and running to use these.\n\n> Note: Container tests mostly do not work on Windows.\n> * The SSH tests require ssh-agent, but the two versions of ssh-agent\n> on Windows are not suitable for testing.\n>     * The Microsoft version of ssh-agent runs as a global service, and can't be isolated per test.\n>     * The mingw/cygwin one can't be accessed from a Windows executable like cargo.\n>     * Pageant similarly does not seem to have a way to isolate it (and I'm not certain it can be driven completely from the command-line).\n>\n> The tests also can't run on Windows CI because the Docker that is preinstalled doesn't support Linux containers, and setting up Windows containers is a pain.\n>\n> macOS should work with Docker installed and running,\n> but unfortunately the tests are not run on CI because Docker is not available.\n"
  },
  {
    "path": "src/doc/contrib/src/tests/writing.md",
    "content": "# Writing Tests\n\nThe following focuses on writing an integration test. However, writing unit\ntests is also encouraged!\n\n## Testsuite\n\nCargo has a wide variety of integration tests that execute the `cargo` binary\nand verify its behavior, located in the [`testsuite`] directory.  The\n[`support`] crate and [`snapbox`] contain many helpers to make this process easy.\n\nThere are two styles of tests that can roughly be categorized as\n- functional tests\n  - The fixture is programmatically defined\n  - The assertions may be in-source snapshots, hard-coded strings, or programmatically generated\n  - Easier to share in an issue as a code block is completely self-contained\n- ui tests\n  - The fixture is file-based\n  - The assertions use file-backed snapshots that can be updated with an env variable\n  - Easier to review the expected behavior of the command as more details are included\n  - Easier to get up and running from an existing project\n  - Easier to reason about as everything is just files in the repo\n\nThese tests typically work by creating a temporary \"project\" with a\n`Cargo.toml` file, executing the `cargo` binary process, and checking the\nstdout and stderr output against the expected output.\n\n### Functional Tests\n\nGenerally, a functional test will be placed in `tests/testsuite/<command>.rs` and will look roughly like:\n```rust,ignore\nuse crate::prelude::*;\nuse cargo_test_support::str;\nuse cargo_test_support::project;\n\n#[cargo_test]\nfn <description>() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hi!\"); }\"#)\n        .build();\n\n    p.cargo(\"run --bin foo\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo [..]\n[FINISHED] [..]\n[RUNNING] `target/debug/foo`\n\"#]])\n        .with_stdout_data(str![[\"hi!\"]])\n        .run();\n}\n```\n\nThe [`#[cargo_test]` attribute][cargo_test attribute] is used in place of\n`#[test]` to inject some setup code and declare requirements for running the\ntest.\n\n[`ProjectBuilder`] via `project()`:\n- Each project is in a separate directory in the sandbox\n- If you do not specify a `Cargo.toml` manifest using `file()`, one is\n  automatically created with a project name of `foo` using `basic_manifest()`.\n\n[`Execs`] via `p.cargo(...)`:\n- This executes the command and evaluates different assertions\n  - See [`support::compare`] for an explanation of the string pattern matching.\n    Patterns are used to make it easier to match against the expected output.\n\n#### Filesystem layout testing\n\nTests often to need to verify Cargo created/removed files.\nThe `CargoPathExt` trait (implemented by `Path` and `PathBuf`) provides a `assert_dir_layout()` to verify the files in a directory (including nested directories).\nThis takes a snapshot of file paths for the given directory and asserts that all files are present and no new files have been created.\nThis function also takes a list of patterns to ignore from the snapshot to make working with platform specific files easier.\n\nNote: You will commonly need to call `unordered()` before passing your snapshot to deal with platform differences like binaries having `.exe` on Windows.\n`assert_build_dir_layout` is a more specialized version of `assert_dir_layout()` that is automatically unordered and ignores common platform specific files designed for the Cargo build cache.\n\n#### Testing Nightly Features\n\nIf you are testing a Cargo feature that only works on \"nightly\" Cargo, then\nyou need to call `masquerade_as_nightly_cargo` on the process builder and pass \nthe name of the feature as the reason, like this:\n\n```rust,ignore\np.cargo(\"build\").masquerade_as_nightly_cargo(&[\"print-im-a-teapot\"])\n```\n\nIf you are testing a feature that only works on *nightly rustc* (such as\nbenchmarks), then you should use the `nightly` option of the `cargo_test`\nattribute, like this:\n\n```rust,ignore\n#[cargo_test(nightly, reason = \"-Zfoo is unstable\")]\n```\n\nThis will cause the test to be ignored if not running on the nightly toolchain.\n\n#### Specifying Dependencies\n\nYou should not write any tests that use the network such as contacting\ncrates.io. Typically, simple path dependencies are the easiest way to add a\ndependency. Example:\n\n```rust,ignore\nlet p = project()\n    .file(\"Cargo.toml\", r#\"\n        [package]\n        name = \"foo\"\n        version = \"1.0.0\"\n\n        [dependencies]\n        bar = {path = \"bar\"}\n    \"#)\n    .file(\"src/lib.rs\", \"extern crate bar;\")\n    .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n    .file(\"bar/src/lib.rs\", \"\")\n    .build();\n```\n\nIf you need to test with registry dependencies, see\n[`support::registry::Package`] for creating packages you can depend on.\n\nIf you need to test git dependencies, see [`support::git`] to create a git\ndependency.\n\n#### Cross compilation\n\nThere are some utilities to help support tests that need to work against a\ntarget other than the host. See [Running cross\ntests](running.md#running-cross-tests) for more an introduction on cross\ncompilation tests.\n\nTests that need to do cross-compilation should include this at the top of the\ntest to disable it in scenarios where cross compilation isn't available:\n\n```rust,ignore\nif crate::utils::cross_compile::disabled() {\n    return;\n}\n```\n\nThe name of the target can be fetched with the [`cross_compile::alternate()`]\nfunction. The name of the host target can be fetched with\n[`cargo_test_support::rustc_host()`].\n\nIf the test needs to run the cross-compiled binary, then it should have\nsomething like this to exit the test before doing so:\n\n```rust,ignore\nif crate::utils::cross_compile::can_run_on_host() {\n    return;\n}\n```\n\n[`cross_compile::alternate()`]: https://github.com/rust-lang/cargo/blob/d58902e22e148426193cf3b8c4449fd3c05c0afd/crates/cargo-test-support/src/cross_compile.rs#L208-L225\n[`cargo_test_support::rustc_host()`]: https://github.com/rust-lang/cargo/blob/d58902e22e148426193cf3b8c4449fd3c05c0afd/crates/cargo-test-support/src/lib.rs#L1137-L1140\n\n### UI Tests\n\nUI Tests are a bit more spread out and generally look like:\n\n`tests/testsuite/<command>/mod.rs`:\n```rust,ignore\nmod <case>;\n```\n\n`tests/testsuite/<command>/<case>/mod.rs`:\n```rust,ignore\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::Project;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"run\")\n        .arg_line(\"--bin foo\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_matches(file!(\"stdout.log\"))\n        .stderr_matches(file!(\"stderr.log\"));\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n```\n\nThen populate\n- `tests/testsuite/<command>/<case>/in` with the project's directory structure\n- `tests/testsuite/<command>/<case>/out` with the files you want verified\n- `tests/testsuite/<command>/<case>/stdout.log` with nothing\n- `tests/testsuite/<command>/<case>/stderr.log` with nothing\n\n`#[cargo_test]`:\n- This is used in place of `#[test]`\n- This attribute injects code which does some setup before starting the\n  test, creating a filesystem \"sandbox\" under the \"cargo integration test\"\n  directory for each test. The directory for each test is based on the\n  integration test name, module (if there is one), and function name[^1]:\n\n  `/path/to/cargo/target/tmp/cit/<integration test>/<module>/<fn name>/`\n- The sandbox will contain a `home` directory that will be used instead of your normal home directory\n\n`Project`:\n- The project is copied from a directory in the repo\n- Each project is in a separate directory in the sandbox\n\n[`Command`] via `Command::cargo_ui()`:\n- Set up and run a command.\n\n[`OutputAssert`] via `Command::assert()`:\n- Perform assertions on the result of the [`Command`]\n\n[`Assert`] via `assert_ui()`:\n- Verify the command modified the file system as expected\n\n#### Updating Snapshots\n\nThe project, stdout, and stderr snapshots can be updated by running with the\n`SNAPSHOTS=overwrite` environment variable, like:\n```console\n$ SNAPSHOTS=overwrite cargo test\n```\n\nBe sure to check the snapshots to make sure they make sense.\n\n#### Testing Nightly Features\n\nIf you are testing a Cargo feature that only works on \"nightly\" Cargo, then\nyou need to call `masquerade_as_nightly_cargo` on the process builder and pass\nthe name of the feature as the reason, like this:\n\n```rust,ignore\n    snapbox::cmd::Command::cargo()\n        .masquerade_as_nightly_cargo(&[\"print-im-a-teapot\"])\n```\n\nIf you are testing a feature that only works on *nightly rustc* (such as\nbenchmarks), then you should use the `nightly` option of the `cargo_test`\nattribute, like this:\n\n```rust,ignore\n#[cargo_test(nightly, reason = \"-Zfoo is unstable\")]\n```\n\nThis will cause the test to be ignored if not running on the nightly toolchain.\n\n### Platform-specific Notes\n\nWhen checking output, use `/` for paths even on Windows: the actual output\nof `\\` on Windows will be replaced with `/`.\n\nBe careful when executing binaries on Windows. You should not rename, delete,\nor overwrite a binary immediately after running it. Under some conditions\nWindows will fail with errors like \"directory not empty\" or \"failed to remove\"\nor \"access is denied\".\n\nOn Windows, to avoid path length limitations, the tests use the following\ndirectory structure instead:\n\n`/path/to/cargo/target/tmp/cit/t123/`\n\n## Debugging tests\n\nIn some cases, you may need to dig into a test that is not working as you\nexpect, or you just generally want to experiment within the sandbox\nenvironment. The general process is:\n\n1. Build the sandbox for the test you want to investigate. For example:\n\n   `cargo test --test testsuite -- features2::inactivate_targets`.\n2. In another terminal, head into the sandbox directory to inspect the files and run `cargo` directly.\n    1. The first test's sandbox directory is called `t0`.\n\n       `cd target/tmp/cit/t0`\n    2. Set up the environment so that the sandbox configuration takes effect:\n\n       `export CARGO_HOME=$(pwd)/home/.cargo`\n    3. Most tests create a `foo` project, so head into that:\n\n       `cd foo`\n3. Run whatever cargo command you want. See [Running Cargo] for more details\n   on running the correct `cargo` process. Some examples:\n\n   * `/path/to/my/cargo/target/debug/cargo check`\n   * Using a debugger like `lldb` or `gdb`:\n        1. `lldb /path/to/my/cargo/target/debug/cargo`\n        2. Set a breakpoint, for example: `b generate_root_units`\n        3. Run with arguments: `r check`\n\n[cargo_test attribute]: https://doc.rust-lang.org/nightly/nightly-rustc/cargo_test_macro/attr.cargo_test.html\n[`testsuite`]: https://github.com/rust-lang/cargo/tree/master/tests/testsuite/\n[`ProjectBuilder`]: https://github.com/rust-lang/cargo/blob/d847468768446168b596f721844193afaaf9d3f2/crates/cargo-test-support/src/lib.rs#L196-L202\n[`Execs`]: https://github.com/rust-lang/cargo/blob/d847468768446168b596f721844193afaaf9d3f2/crates/cargo-test-support/src/lib.rs#L531-L550\n[`support`]: https://github.com/rust-lang/cargo/blob/master/crates/cargo-test-support/src/lib.rs\n[`support::compare`]: https://github.com/rust-lang/cargo/blob/master/crates/cargo-test-support/src/compare.rs\n[`support::registry::Package`]: https://github.com/rust-lang/cargo/blob/d847468768446168b596f721844193afaaf9d3f2/crates/cargo-test-support/src/registry.rs#L311-L389\n[`support::git`]: https://github.com/rust-lang/cargo/blob/master/crates/cargo-test-support/src/git.rs\n[Running Cargo]: ../process/working-on-cargo.md#running-cargo\n[`snapbox`]: https://docs.rs/snapbox/latest/snapbox/\n[`Command`]: https://docs.rs/snapbox/latest/snapbox/cmd/struct.Command.html\n[`OutputAssert`]: https://docs.rs/snapbox/latest/snapbox/cmd/struct.OutputAssert.html\n[`Assert`]: https://docs.rs/snapbox/latest/snapbox/struct.Assert.html\n\n[^1]: Windows uses a separate directory layout, see [Platform-Specific Notes](#platform-specific-notes)\n    for more details.\n"
  },
  {
    "path": "src/doc/man/cargo-add.md",
    "content": "# cargo-add(1)\n{{~*set command=\"add\"}}\n{{~*set actionverb=\"Add\"}}\n{{~*set nouns=\"adds\"}}\n\n## NAME\n\ncargo-add --- Add dependencies to a Cargo.toml manifest file\n\n## SYNOPSIS\n\n`cargo add` [_options_] _crate_...\\\n`cargo add` [_options_] `--path` _path_\\\n`cargo add` [_options_] `--git` _url_ [_crate_...]\n\n\n## DESCRIPTION\n\nThis command can add or modify dependencies.\n\nThe source for the dependency can be specified with:\n\n* _crate_`@`_version_: Fetch from a registry with a version constraint of \"_version_\"\n* `--path` _path_: Fetch from the specified _path_\n* `--git` _url_: Pull from a git repo at _url_\n\nIf no source is specified, then a best effort will be made to select one, including:\n\n* Existing dependencies in other tables (like `dev-dependencies`)\n* Workspace members\n* Latest release in the registry\n\nWhen you add a package that is already present, the existing entry will be updated with the flags specified.\n\nUpon successful invocation, the enabled (`+`) and disabled (`-`) [features] of the specified\ndependency will be listed in the command's output.\n\n[features]: ../reference/features.html\n\n## OPTIONS\n\n### Source options\n\n{{#options}}\n\n{{#option \"`--git` _url_\" }}\n[Git URL to add the specified crate from](../reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories).\n{{/option}}\n\n{{#option \"`--branch` _branch_\" }}\nBranch to use when adding from git.\n{{/option}}\n\n{{#option \"`--tag` _tag_\" }}\nTag to use when adding from git.\n{{/option}}\n\n{{#option \"`--rev` _sha_\" }}\nSpecific commit to use when adding from git.\n{{/option}}\n\n{{#option \"`--path` _path_\" }}\n[Filesystem path](../reference/specifying-dependencies.html#specifying-path-dependencies) to local crate to add.\n{{/option}}\n\n{{#option \"`--base` _base_\" }}\nThe [path base](../reference/unstable.html#path-bases) to use when adding a local crate.\n\n[Unstable (nightly-only)](../reference/unstable.html#path-bases)\n{{/option}}\n\n{{> options-registry }}\n\n{{/options}}\n\n### Section options\n\n{{#options}}\n\n{{#option \"`--dev`\" }}\nAdd as a [development dependency](../reference/specifying-dependencies.html#development-dependencies).\n{{/option}}\n\n{{#option \"`--build`\" }}\nAdd as a [build dependency](../reference/specifying-dependencies.html#build-dependencies).\n{{/option}}\n\n{{#option \"`--target` _target_\" }}\nAdd as a dependency to the [given target platform](../reference/specifying-dependencies.html#platform-specific-dependencies).\n\nTo avoid unexpected shell expansions, you may use quotes around each target, e.g., `--target 'cfg(unix)'`.\n{{/option}}\n\n{{/options}}\n\n### Dependency options\n\n{{#options}}\n\n{{#option \"`--dry-run`\" }}\nDon't actually write the manifest\n{{/option}}\n\n{{#option \"`--rename` _name_\" }}\n[Rename](../reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml) the dependency.\n{{/option}}\n\n{{#option \"`--optional`\" }}\nMark the dependency as [optional](../reference/features.html#optional-dependencies).\n{{/option}}\n\n{{#option \"`--no-optional`\" }}\nMark the dependency as [required](../reference/features.html#optional-dependencies).\n{{/option}}\n\n{{#option \"`--public`\" }}\nMark the dependency as public. \n\nThe dependency can be referenced in your library's public API.\n\n[Unstable (nightly-only)](../reference/unstable.html#public-dependency)\n{{/option}}\n\n{{#option \"`--no-public`\" }}\nMark the dependency as private. \n\nWhile you can use the crate in your implementation, it cannot be referenced in your public API.\n\n[Unstable (nightly-only)](../reference/unstable.html#public-dependency)\n{{/option}}\n\n{{#option \"`--no-default-features`\" }}\nDisable the [default features](../reference/features.html#dependency-features).\n{{/option}}\n\n{{#option \"`--default-features`\" }}\nRe-enable the [default features](../reference/features.html#dependency-features).\n{{/option}}\n\n{{#option \"`-F` _features_\" \"`--features` _features_\" }}\nSpace or comma separated list of [features to\nactivate](../reference/features.html#dependency-features). When adding multiple\ncrates, the features for a specific crate may be enabled with\n`package-name/feature-name` syntax. This flag may be specified multiple times,\nwhich enables all specified features.\n{{/option}}\n\n{{/options}}\n\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n\n{{#option \"`-p` _spec_\" \"`--package` _spec_\" }}\nAdd dependencies to only the specified package.\n{{/option}}\n\n{{> options-ignore-rust-version }}\n\n{{> options-locked }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Add `regex` as a dependency\n\n       cargo add regex\n\n2. Add `trybuild` as a dev-dependency\n\n       cargo add --dev trybuild\n\n3. Add an older version of `nom` as a dependency\n\n       cargo add nom@5\n\n4. Add support for serializing data structures to json with `derive`s\n\n       cargo add serde serde_json -F serde/derive\n\n5. Add `windows` as a platform specific dependency on `cfg(windows)`\n\n       cargo add windows --target 'cfg(windows)'\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-remove\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-bench.md",
    "content": "# cargo-bench(1)\n{{~*set command=\"bench\"}}\n{{~*set actionverb=\"Benchmark\"}}\n{{~*set nouns=\"benchmarks\"}}\n{{~*set multitarget=true}}\n\n## NAME\n\ncargo-bench --- Execute benchmarks of a package\n\n## SYNOPSIS\n\n`cargo bench` [_options_] [_benchname_] [`--` _bench-options_]\n\n## DESCRIPTION\n\nCompile and execute benchmarks.\n\nThe benchmark filtering argument _benchname_ and all the arguments following\nthe two dashes (`--`) are passed to the benchmark binaries and thus to\n_libtest_ (rustc's built in unit-test and micro-benchmarking framework). If\nyou are passing arguments to both Cargo and the binary, the ones after `--` go\nto the binary, the ones before go to Cargo. For details about libtest's\narguments see the output of `cargo bench -- --help` and check out the rustc\nbook's chapter on how tests work at\n<https://doc.rust-lang.org/rustc/tests/index.html>.\n\nAs an example, this will run only the benchmark named `foo` (and skip other\nsimilarly named benchmarks like `foobar`):\n\n    cargo bench -- foo --exact\n\nBenchmarks are built with the `--test` option to `rustc` which creates a\nspecial executable by linking your code with libtest. The executable\nautomatically runs all functions annotated with the `#[bench]` attribute.\nCargo passes the `--bench` flag to the test harness to tell it to run\nonly benchmarks, regardless of whether the harness is libtest or a custom harness.\n\nThe libtest harness may be disabled by setting `harness = false` in the target\nmanifest settings, in which case your code will need to provide its own `main`\nfunction to handle running benchmarks.\n\n> **Note**: The\n> [`#[bench]` attribute](https://doc.rust-lang.org/nightly/unstable-book/library-features/test.html)\n> is currently unstable and only available on the\n> [nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html).\n> There are some packages available on\n> [crates.io](https://crates.io/keywords/benchmark) that may help with\n> running benchmarks on the stable channel, such as\n> [Criterion](https://crates.io/crates/criterion).\n\nBy default, `cargo bench` uses the [`bench` profile], which enables\noptimizations and disables debugging information. If you need to debug a\nbenchmark, you can use the `--profile=dev` command-line option to switch to\nthe dev profile. You can then run the debug-enabled benchmark within a\ndebugger.\n\n[`bench` profile]: ../reference/profiles.html#bench\n\n### Working directory of benchmarks\n\nThe working directory of every benchmark is set to the root directory of the \npackage the benchmark belongs to.\nSetting the working directory of benchmarks to the package's root directory \nmakes it possible for benchmarks to reliably access the package's files using \nrelative paths, regardless from where `cargo bench` was executed from.\n\n## OPTIONS\n\n### Benchmark Options\n\n{{> options-test }}\n\n{{> section-package-selection }}\n\n### Target Selection\n\nWhen no target selection options are given, `cargo bench` will build the\nfollowing targets of the selected packages:\n\n- lib --- used to link with binaries and benchmarks\n- bins (only if benchmark targets are built and required features are\n  available)\n- lib as a benchmark\n- bins as benchmarks\n- benchmark targets\n\nThe default behavior can be changed by setting the `bench` flag for the target\nin the manifest settings. Setting examples to `bench = true` will build and\nrun the example as a benchmark, replacing the example's `main` function with\nthe libtest harness.\n\nSetting targets to `bench = false` will stop them from being benchmarked by\ndefault. Target selection options that take a target by name (such as\n`--example foo`) ignore the `bench` flag and will always benchmark the given\ntarget.\n\nSee [Configuring a target](../reference/cargo-targets.html#configuring-a-target)\nfor more information on per-target settings.\n\n{{> options-targets-bin-auto-built }}\n\n{{> options-targets }}\n\n{{> section-features }}\n\n### Compilation Options\n\n{{#options}}\n\n{{> options-target-triple }}\n\n{{> options-profile }}\n\n{{> options-timings }}\n\n{{/options}}\n\n### Output Options\n\n{{#options}}\n{{> options-target-dir }}\n{{/options}}\n\n### Display Options\n\nBy default the Rust test harness hides output from benchmark execution to keep\nresults readable. Benchmark output can be recovered (e.g., for debugging) by\npassing `--no-capture` to the benchmark binaries:\n\n    cargo bench -- --no-capture\n\n{{#options}}\n\n{{> options-display }}\n\n{{> options-message-format }}\n\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n\n{{> options-ignore-rust-version }}\n\n{{> options-locked }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n### Miscellaneous Options\n\nThe `--jobs` argument affects the building of the benchmark executable but\ndoes not affect how many threads are used when running the benchmarks. The\nRust test harness runs benchmarks serially in a single thread.\n\n{{#options}}\n{{> options-jobs }}\n{{/options}}\n\nWhile `cargo bench` involves compilation, it does not provide a `--keep-going`\nflag. Use `--no-fail-fast` to run as many benchmarks as possible without\nstopping at the first failure. To \"compile\" as many benchmarks as possible, use\n`--benches` to build benchmark binaries separately. For example:\n\n    cargo build --benches --release --keep-going\n    cargo bench --no-fail-fast\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Build and execute all the benchmarks of the current package:\n\n       cargo bench\n\n2. Run only a specific benchmark within a specific benchmark target:\n\n       cargo bench --bench bench_name -- modname::some_benchmark\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-test\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-build.md",
    "content": "# cargo-build(1)\n{{~*set command=\"build\"}}\n{{~*set actionverb=\"Build\"}}\n{{~*set multitarget=true}}\n\n## NAME\n\ncargo-build --- Compile the current package\n\n## SYNOPSIS\n\n`cargo build` [_options_]\n\n## DESCRIPTION\n\nCompile local packages and all of their dependencies.\n\n## OPTIONS\n\n{{> section-package-selection }}\n\n### Target Selection\n\nWhen no target selection options are given, `cargo build` will build all\nbinary and library targets of the selected packages. Binaries are skipped if\nthey have `required-features` that are missing.\n\n{{> options-targets-bin-auto-built }}\n\n{{> options-targets }}\n\n{{> section-features }}\n\n### Compilation Options\n\n{{#options}}\n\n{{> options-target-triple }}\n\n{{> options-release }}\n\n{{> options-profile }}\n\n{{> options-timings }}\n\n{{/options}}\n\n### Output Options\n\n{{#options}}\n{{> options-target-dir }}\n\n{{#option \"`--artifact-dir` _directory_\" }}\nCopy final artifacts to this directory.\n\nThis option is unstable and available only on the\n[nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)\nand requires the `-Z unstable-options` flag to enable.\nSee <https://github.com/rust-lang/cargo/issues/6790> for more information.\n{{/option}}\n\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n\n{{> options-message-format }}\n\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n\n{{> options-ignore-rust-version }}\n\n{{> options-locked }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n### Miscellaneous Options\n\n{{#options}}\n{{> options-jobs }}\n{{> options-keep-going }}\n{{> options-future-incompat }}\n{{/options}}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Build the local package and all of its dependencies:\n\n       cargo build\n\n2. Build with optimizations:\n\n       cargo build --release\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-rustc\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-check.md",
    "content": "# cargo-check(1)\n{{~*set command=\"check\"}}\n{{~*set actionverb=\"Check\"}}\n{{~*set multitarget=true}}\n\n## NAME\n\ncargo-check --- Check the current package\n\n## SYNOPSIS\n\n`cargo check` [_options_]\n\n## DESCRIPTION\n\nCheck a local package and all of its dependencies for errors. This will\nessentially compile the packages without performing the final step of code\ngeneration, which is faster than running `cargo build`. The compiler will save\nmetadata files to disk so that future runs will reuse them if the source has\nnot been modified. Some diagnostics and errors are only emitted during code\ngeneration, so they inherently won't be reported with `cargo check`.\n\n## OPTIONS\n\n{{> section-package-selection }}\n\n### Target Selection\n\nWhen no target selection options are given, `cargo check` will check all\nbinary and library targets of the selected packages. Binaries are skipped if\nthey have `required-features` that are missing.\n\n{{> options-targets }}\n\n{{> section-features }}\n\n### Compilation Options\n\n{{#options}}\n\n{{> options-target-triple }}\n\n{{> options-release }}\n\n{{> options-profile-legacy-check }}\n\n{{> options-timings }}\n\n{{/options}}\n\n### Output Options\n\n{{#options}}\n{{> options-target-dir }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n\n{{> options-message-format }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n\n{{> options-ignore-rust-version }}\n\n{{> options-locked }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n### Miscellaneous Options\n\n{{#options}}\n{{> options-jobs }}\n{{> options-keep-going }}\n{{> options-future-incompat }}\n{{/options}}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Check the local package for errors:\n\n       cargo check\n\n2. Check all targets, including unit tests:\n\n       cargo check --all-targets --profile=test\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-build\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-clean.md",
    "content": "# cargo-clean(1)\n{{~*set command=\"clean\"}}\n{{~*set actionverb=\"Clean\"}}\n{{~*set multitarget=true}}\n\n## NAME\n\ncargo-clean --- Remove generated artifacts\n\n## SYNOPSIS\n\n`cargo clean` [_options_]\n\n## DESCRIPTION\n\nRemove artifacts from the target directory that Cargo has generated in the\npast.\n\nWith no options, `cargo clean` will delete the entire target directory.\n\n## OPTIONS\n\n### Package Selection\n\nWhen no packages are selected, all packages and all dependencies in the\nworkspace are cleaned.\n\n{{#options}}\n\n{{#option \"`-p` _spec_...\" \"`--package` _spec_...\" }}\nClean only the specified packages. This flag may be specified\nmultiple times. See {{man \"cargo-pkgid\" 1}} for the SPEC format.\n{{/option}}\n\n{{#option \"`--workspace`\" }}\nClean artifacts of the workspace members. \n{{/option}}\n\n{{/options}}\n\n### Clean Options\n\n{{#options}}\n\n{{#option \"`--dry-run`\" }}\nDisplays a summary of what would be deleted without deleting anything.\nUse with `--verbose` to display the actual files that would be deleted.\n{{/option}}\n\n{{#option \"`--doc`\" }}\nThis option will cause `cargo clean` to remove only the `doc` directory in\nthe target directory.\n{{/option}}\n\n{{#option \"`--release`\" }}\nRemove all artifacts in the `release` directory.\n{{/option}}\n\n{{#option \"`--profile` _name_\" }}\nRemove all artifacts in the directory with the given profile name.\n{{/option}}\n\n{{> options-target-dir }}\n\n{{> options-target-triple }}\n\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n\n{{> options-locked }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Remove the entire target directory:\n\n       cargo clean\n\n2. Remove only the release artifacts:\n\n       cargo clean --release\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-build\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-doc.md",
    "content": "# cargo-doc(1)\n{{~*set command=\"doc\"}}\n{{~*set actionverb=\"Document\"}}\n{{~*set multitarget=true}}\n\n## NAME\n\ncargo-doc --- Build a package's documentation\n\n## SYNOPSIS\n\n`cargo doc` [_options_]\n\n## DESCRIPTION\n\nBuild the documentation for the local package and all dependencies. The output\nis placed in `target/doc` in rustdoc's usual format.\n\n**Note:** Documentation generation is cumulative: existing doc files in the target directory are preserved across different `cargo doc` invocations. To remove existing generated docs, pass `--doc` to {{man \"cargo-clean\" 1}}.\n\n## OPTIONS\n\n### Documentation Options\n\n{{#options}}\n\n{{#option \"`--open`\" }}\nOpen the docs in a browser after building them. This will use your default\nbrowser unless you define another one in the `BROWSER` environment variable\nor use the [`doc.browser`](../reference/config.html#docbrowser) configuration\noption.\n{{/option}}\n\n{{#option \"`--no-deps`\" }}\nDo not build documentation for dependencies.\n{{/option}}\n\n{{#option \"`--document-private-items`\" }}\nInclude non-public items in the documentation. This will be enabled by default if documenting a binary target.\n{{/option}}\n\n{{/options}}\n\n{{> section-package-selection }}\n\n### Target Selection\n\nWhen no target selection options are given, `cargo doc` will document all\nbinary and library targets of the selected package. The binary will be skipped\nif its name is the same as the lib target. Binaries are skipped if they have\n`required-features` that are missing.\n\nThe default behavior can be changed by setting `doc = false` for the target in\nthe manifest settings. Using target selection options will ignore the `doc`\nflag and will always document the given target.\n\n{{#options}}\n{{> options-targets-lib-bin }}\n\n{{#option \"`--example` _name_...\" }}\n{{actionverb}} the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.\n{{/option}}\n\n{{#option \"`--examples`\" }}\n{{actionverb}} all example targets.\n{{/option}}\n\n{{/options}}\n\n{{> section-features }}\n\n### Compilation Options\n\n{{#options}}\n\n{{> options-target-triple }}\n\n{{> options-release }}\n\n{{> options-profile }}\n\n{{> options-timings }}\n\n{{/options}}\n\n### Output Options\n\n{{#options}}\n{{> options-target-dir }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n\n{{> options-message-format }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n\n{{> options-ignore-rust-version }}\n\n{{> options-locked }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n### Miscellaneous Options\n\n{{#options}}\n{{> options-jobs }}\n{{> options-keep-going }}\n{{/options}}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Build the local package documentation and its dependencies and output to\n   `target/doc`.\n\n       cargo doc\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-rustdoc\" 1}}, {{man \"rustdoc\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-fetch.md",
    "content": "# cargo-fetch(1)\n{{~*set command=\"fetch\"}}\n{{~*set actionverb=\"Fetch\"}}\n{{~*set target-default-to-all-arch=true}}\n{{~*set multitarget=true}}\n\n## NAME\n\ncargo-fetch --- Fetch dependencies of a package from the network\n\n## SYNOPSIS\n\n`cargo fetch` [_options_]\n\n## DESCRIPTION\n\nIf a `Cargo.lock` file is available, this command will ensure that all of the\ngit dependencies and/or registry dependencies are downloaded and locally\navailable. Subsequent Cargo commands will be able to run offline after a `cargo\nfetch` unless the lock file changes.\n\nIf the lock file is not available, then this command will generate the lock\nfile before fetching the dependencies.\n\nIf `--target` is not specified, then all target dependencies are fetched.\n\nSee also the [cargo-prefetch](https://crates.io/crates/cargo-prefetch)\nplugin which adds a command to download popular crates. This may be useful if\nyou plan to use Cargo without a network with the `--offline` flag.\n\n## OPTIONS\n\n### Fetch options\n\n{{#options}}\n{{> options-target-triple }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n\n{{> options-locked }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Fetch all dependencies:\n\n       cargo fetch\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-update\" 1}}, {{man \"cargo-generate-lockfile\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-fix.md",
    "content": "# cargo-fix(1)\n{{~*set command=\"fix\"}}\n{{~*set actionverb=\"Fix\"}}\n{{~*set multitarget=true}}\n\n## NAME\n\ncargo-fix --- Automatically fix lint warnings reported by rustc\n\n## SYNOPSIS\n\n`cargo fix` [_options_]\n\n## DESCRIPTION\n\nThis Cargo subcommand will automatically take rustc's suggestions from\ndiagnostics like warnings and apply them to your source code. This is intended\nto help automate tasks that rustc itself already knows how to tell you to fix!\n\nExecuting `cargo fix` will under the hood execute {{man \"cargo-check\" 1}}. Any warnings\napplicable to your crate will be automatically fixed (if possible) and all\nremaining warnings will be displayed when the check process is finished. For\nexample if you'd like to apply all fixes to the current package, you can run:\n\n    cargo fix\n\nwhich behaves the same as `cargo check --all-targets`.\n\n`cargo fix` is only capable of fixing code that is normally compiled with\n`cargo check`. If code is conditionally enabled with optional features, you\nwill need to enable those features for that code to be analyzed:\n\n    cargo fix --features foo\n\nSimilarly, other `cfg` expressions like platform-specific code will need to\npass `--target` to fix code for the given target.\n\n    cargo fix --target x86_64-pc-windows-gnu\n\nIf you encounter any problems with `cargo fix` or otherwise have any questions\nor feature requests please don't hesitate to file an issue at\n<https://github.com/rust-lang/cargo>.\n\n### Edition migration\n\nThe `cargo fix` subcommand can also be used to migrate a package from one\n[edition] to the next. The general procedure is:\n\n1. Run `cargo fix --edition`. Consider also using the `--all-features` flag if\n   your project has multiple features. You may also want to run `cargo fix\n   --edition` multiple times with different `--target` flags if your project\n   has platform-specific code gated by `cfg` attributes.\n2. Modify `Cargo.toml` to set the [edition field] to the new edition.\n3. Run your project tests to verify that everything still works. If new\n   warnings are issued, you may want to consider running `cargo fix` again\n   (without the `--edition` flag) to apply any suggestions given by the\n   compiler.\n\nAnd hopefully that's it! Just keep in mind of the caveats mentioned above that\n`cargo fix` cannot update code for inactive features or `cfg` expressions.\nAlso, in some rare cases the compiler is unable to automatically migrate all\ncode to the new edition, and this may require manual changes after building\nwith the new edition.\n\n[edition]: https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html\n[edition field]: ../reference/manifest.html#the-edition-field\n\n## OPTIONS\n\n### Fix options\n\n{{#options}}\n\n{{#option \"`--broken-code`\" }}\nFix code even if it already has compiler errors. This is useful if `cargo fix`\nfails to apply the changes. It will apply the changes and leave the broken\ncode in the working directory for you to inspect and manually fix.\n{{/option}}\n\n{{#option \"`--edition`\" }}\nApply changes that will update the code to the next edition. This will not\nupdate the edition in the `Cargo.toml` manifest, which must be updated\nmanually after `cargo fix --edition` has finished.\n{{/option}}\n\n{{#option \"`--edition-idioms`\" }}\nApply suggestions that will update code to the preferred style for the current\nedition.\n{{/option}}\n\n{{#option \"`--allow-no-vcs`\" }}\nFix code even if a VCS was not detected.\n{{/option}}\n\n{{#option \"`--allow-dirty`\" }}\nFix code even if the working directory has changes (including staged changes).\n{{/option}}\n\n{{#option \"`--allow-staged`\" }}\nFix code even if the working directory has staged changes.\n{{/option}}\n\n{{/options}}\n\n{{> section-package-selection }}\n\n### Target Selection\n\nWhen no target selection options are given, `cargo fix` will fix all targets\n(`--all-targets` implied). Binaries are skipped if they have\n`required-features` that are missing.\n\n{{> options-targets }}\n\n{{> section-features }}\n\n### Compilation Options\n\n{{#options}}\n\n{{> options-target-triple }}\n\n{{> options-release }}\n\n{{> options-profile-legacy-check }}\n\n{{> options-timings }}\n\n{{/options}}\n\n### Output Options\n\n{{#options}}\n{{> options-target-dir }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n\n{{> options-message-format }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n\n{{> options-ignore-rust-version }}\n\n{{> options-locked }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n### Miscellaneous Options\n\n{{#options}}\n{{> options-jobs }}\n{{> options-keep-going }}\n{{/options}}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Apply compiler suggestions to the local package:\n\n       cargo fix\n\n2. Update a package to prepare it for the next edition:\n\n       cargo fix --edition\n\n3. Apply suggested idioms for the current edition:\n\n       cargo fix --edition-idioms\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-check\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-generate-lockfile.md",
    "content": "# cargo-generate-lockfile(1)\n\n## NAME\n\ncargo-generate-lockfile --- Generate the lockfile for a package\n\n## SYNOPSIS\n\n`cargo generate-lockfile` [_options_]\n\n## DESCRIPTION\n\nThis command will create the `Cargo.lock` lockfile for the current package or\nworkspace. If the lockfile already exists, it will be rebuilt with the latest\navailable version of every package.\n\nSee also {{man \"cargo-update\" 1}} which is also capable of creating a `Cargo.lock`\nlockfile and has more options for controlling update behavior.\n\n## OPTIONS\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n\n{{> options-ignore-rust-version }}\n\n{{#option \"`--publish-time` _yyyy-mm-ddThh:mm:ssZ_\" }}\nLatest publish time allowed for registry packages (Unstable)\n\nThis is a best-effort filter on allowed packages, including:\n- packages from unsupported registries are always accepted\n- only the current yank state is respected, not the state as of `--publish-time`\n- precision of the publish time\n{{/option}}\n\n{{> options-locked }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Create or update the lockfile for the current package or workspace:\n\n       cargo generate-lockfile\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-update\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-help.md",
    "content": "# cargo-help(1)\n\n## NAME\n\ncargo-help --- Get help for a Cargo command\n\n## SYNOPSIS\n\n`cargo help` [_subcommand_]\n\n## DESCRIPTION\n\nPrints a help message for the given command.\n\nFor commands with subcommands, separate the command levels with spaces. For\nexample, `cargo help report future-incompatibilities` displays help for the\n`cargo report future-incompatibilities` command.\n\nSpaces separate hierarchy levels only between a parent command and its\nsubcommands. Dashes that are part of a command's name, such as\n`generate-lockfile`, must always be preserved.\n\nMultiple command levels can also be written as a single dash-joined word.\nFor example, `cargo help report-future-incompatibilities` is equivalent to\n`cargo help report future-incompatibilities`.\n\n## OPTIONS\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-locked }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Get help for a command:\n\n       cargo help build\n\n2. Get help for a nested command:\n\n       cargo help report future-incompatibilities\n\n3. The dash-joined form also works:\n\n       cargo help report-future-incompatibilities\n\n4. Help is also available with the `--help` flag:\n\n       cargo build --help\n\n## SEE ALSO\n{{man \"cargo\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-info.md",
    "content": "# cargo-info(1)\n\n## NAME\n\ncargo-info --- Display information about a package.\n\n## SYNOPSIS\n\n`cargo info` [_options_] _spec_\n\n## DESCRIPTION\n\nThis command displays information about a package. It fetches data from the package's Cargo.toml file\nand presents it in a human-readable format.\n\n## OPTIONS\n\n### Info Options\n\n{{#options}}\n\n{{#option \"_spec_\" }}\n\nFetch information about the specified package. The _spec_ can be a package ID, see {{man \"cargo-pkgid\" 1}} for the SPEC\nformat.\nIf the specified package is part of the current workspace, information from the local Cargo.toml file will be displayed.\nIf the `Cargo.lock` file does not exist, it will be created. If no version is specified, the appropriate version will be\nselected based on the Minimum Supported Rust Version (MSRV).\n\n{{/option}}\n{{> options-index }}\n{{> options-registry }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-locked }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Inspect the `serde` package from crates.io:\n\n        cargo info serde\n2. Inspect the `serde` package with version `1.0.0`:\n\n        cargo info serde@1.0.0\n3. Inspect the `serde` package form the local registry:\n\n        cargo info serde --registry my-registry\n\n## SEE ALSO\n\n{{man \"cargo\" 1}}, {{man \"cargo-search\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-init.md",
    "content": "# cargo-init(1)\n\n## NAME\n\ncargo-init --- Create a new Cargo package in an existing directory\n\n## SYNOPSIS\n\n`cargo init` [_options_] [_path_]\n\n## DESCRIPTION\n\nThis command will create a new Cargo manifest in the current directory. Give a\npath as an argument to create in the given directory.\n\nIf there are typically-named Rust source files already in the directory, those\nwill be used. If not, then a sample `src/main.rs` file will be created, or\n`src/lib.rs` if `--lib` is passed.\n\nIf the directory is not already in a VCS repository, then a new repository\nis created (see `--vcs` below).\n\nSee {{man \"cargo-new\" 1}} for a similar command which will create a new package in\na new directory.\n\n## OPTIONS\n\n### Init Options\n\n{{> options-new }}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Create a binary Cargo package in the current directory:\n\n       cargo init\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-new\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-install.md",
    "content": "# cargo-install(1)\n{{~*set command=\"install\"}}\n{{~*set actionverb=\"Install\"}}\n{{~*set temp-target-dir=true}}\n\n## NAME\n\ncargo-install --- Build and install a Rust binary\n\n## SYNOPSIS\n\n`cargo install` [_options_] _crate_[@_version_]...\\\n`cargo install` [_options_] `--path` _path_\\\n`cargo install` [_options_] `--git` _url_ [_crate_...]\\\n`cargo install` [_options_] `--list`\n\n## DESCRIPTION\n\nThis command manages Cargo's local set of installed binary crates. Only\npackages which have executable `[[bin]]` or `[[example]]` targets can be\ninstalled, and all executables are installed into the installation root's\n`bin` folder. By default only binaries, not examples, are installed.\n\n{{> description-install-root }}\n\nThere are multiple sources from which a crate can be installed. The default\nsource location is crates.io but the `--git`, `--path`, and `--registry` flags\ncan change this source. If the source contains more than one package (such as\ncrates.io or a git repository with multiple crates) the _crate_ argument is\nrequired to indicate which crate should be installed.\n\nCrates from crates.io can optionally specify the version they wish to install\nvia the `--version` flags, and similarly packages from git repositories can\noptionally specify the branch, tag, or revision that should be installed. If a\ncrate has multiple binaries, the `--bin` argument can selectively install only\none of them, and if you'd rather install examples the `--example` argument can\nbe used as well.\n\nIf the package is already installed, Cargo will reinstall it if the installed\nversion does not appear to be up-to-date. If any of the following values\nchange, then Cargo will reinstall the package:\n\n- The package version and source.\n- The set of binary names installed.\n- The chosen features.\n- The profile (`--profile`).\n- The target (`--target`).\n\nInstalling with `--path` will always build and install, unless there are\nconflicting binaries from another package. The `--force` flag may be used to\nforce Cargo to always reinstall the package.\n\nIf the source is crates.io or `--git` then by default the crate will be built\nin a temporary target directory. To avoid this, the target directory can be\nspecified by setting the `CARGO_TARGET_DIR` environment variable to a\npath. In particular, this can be useful for caching build artifacts on\ncontinuous integration systems.\n\n### Dealing with the Lockfile\n\nBy default, the `Cargo.lock` file that is included with the package will be\nignored. This means that Cargo will recompute which versions of dependencies\nto use, possibly using newer versions that have been released since the\npackage was published. The `--locked` flag can be used to force Cargo to use\nthe packaged `Cargo.lock` file if it is available. This may be useful for\nensuring reproducible builds, to use the exact same set of dependencies that\nwere available when the package was published. It may also be useful if a\nnewer version of a dependency is published that no longer builds on your\nsystem, or has other problems. The downside to using `--locked` is that you\nwill not receive any fixes or updates to any dependency. Note that Cargo did\nnot start publishing `Cargo.lock` files until version 1.37, which means\npackages published with prior versions will not have a `Cargo.lock` file\navailable.\n\n### Configuration Discovery\n\nThis command operates on system or user level, not project level.\nThis means that the local [configuration discovery] is ignored.\nInstead, the configuration discovery begins at `$CARGO_HOME/config.toml`. \nIf the package is installed with `--path $PATH`, the local configuration \nwill be used, beginning discovery at `$PATH/.cargo/config.toml`.\n\n[configuration discovery]: ../reference/config.html#hierarchical-structure\n\n## OPTIONS\n\n### Install Options\n\n{{#options}}\n\n{{#option \"`--vers` _version_\" \"`--version` _version_\" }}\nSpecify a version to install. This may be a [version\nrequirement](../reference/specifying-dependencies.html), like `~1.2`, to have Cargo\nselect the newest version from the given requirement. If the version does not\nhave a requirement operator (such as `^` or `~`), then it must be in the form\n_MAJOR.MINOR.PATCH_, and will install exactly that version; it is *not*\ntreated as a caret requirement like Cargo dependencies are.\n{{/option}}\n\n{{#option \"`--git` _url_\" }}\nGit URL to install the specified crate from.\n{{/option}}\n\n{{#option \"`--branch` _branch_\" }}\nBranch to use when installing from git.\n{{/option}}\n\n{{#option \"`--tag` _tag_\" }}\nTag to use when installing from git.\n{{/option}}\n\n{{#option \"`--rev` _sha_\" }}\nSpecific commit to use when installing from git.\n{{/option}}\n\n{{#option \"`--path` _path_\" }}\nFilesystem path to local crate to install from.\n{{/option}}\n\n{{#option \"`--list`\" }}\nList all installed packages and their versions.\n{{/option}}\n\n{{#option \"`-n`\" \"`--dry-run`\" }}\n(unstable) Perform all checks without installing.\n{{/option}}\n\n{{#option \"`-f`\" \"`--force`\" }}\nForce overwriting existing crates or binaries. This can be used if a package\nhas installed a binary with the same name as another package. This is also\nuseful if something has changed on the system that you want to rebuild with,\nsuch as a newer version of `rustc`.\n{{/option}}\n\n{{#option \"`--no-track`\" }}\nBy default, Cargo keeps track of the installed packages with a metadata file\nstored in the installation root directory. This flag tells Cargo not to use or\ncreate that file. With this flag, Cargo will refuse to overwrite any existing\nfiles unless the `--force` flag is used. This also disables Cargo's ability to\nprotect against multiple concurrent invocations of Cargo installing at the\nsame time.\n{{/option}}\n\n{{#option \"`--bin` _name_...\" }}\nInstall only the specified binary.\n{{/option}}\n\n{{#option \"`--bins`\" }}\nInstall all binaries. This is the default behavior.\n{{/option}}\n\n{{#option \"`--example` _name_...\" }}\nInstall only the specified example.\n{{/option}}\n\n{{#option \"`--examples`\" }}\nInstall all examples.\n{{/option}}\n\n{{#option \"`--root` _dir_\" }}\nDirectory to install packages into.\n{{/option}}\n\n{{> options-registry }}\n\n{{> options-index }}\n\n{{/options}}\n\n{{> section-features }}\n\n### Compilation Options\n\n{{#options}}\n\n{{> options-target-triple }}\n\n{{> options-target-dir }}\n\n{{#option \"`--debug`\" }}\nBuild with the `dev` profile instead of the `release` profile.\nSee also the `--profile` option for choosing a specific profile by name.\n{{/option}}\n\n{{> options-profile }}\n\n{{> options-timings }}\n\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-ignore-rust-version }}\n\n{{> options-locked }}\n{{/options}}\n\n### Miscellaneous Options\n\n{{#options}}\n{{> options-jobs }}\n{{> options-keep-going }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n\n{{> options-message-format }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Install or upgrade a package from crates.io:\n\n       cargo install ripgrep\n\n2. Install or reinstall the package in the current directory:\n\n       cargo install --path .\n\n3. View the list of installed packages:\n\n       cargo install --list\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-uninstall\" 1}}, {{man \"cargo-search\" 1}}, {{man \"cargo-publish\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-locate-project.md",
    "content": "# cargo-locate-project(1)\n\n## NAME\n\ncargo-locate-project --- Print a JSON representation of a Cargo.toml file's location\n\n## SYNOPSIS\n\n`cargo locate-project` [_options_]\n\n## DESCRIPTION\n\nThis command will print a JSON object to stdout with the full path to the manifest. The\nmanifest is found by searching upward for a file named `Cargo.toml` starting from the current\nworking directory.\n\nIf the project happens to be a part of a workspace, the manifest of the project, rather than\nthe workspace root, is output. This can be overridden by the `--workspace` flag. The root\nworkspace is found by traversing further upward or by using the field `package.workspace` after\nlocating the manifest of a workspace member.\n\n## OPTIONS\n\n{{#options}}\n\n{{#option \"`--workspace`\" }}\nLocate the `Cargo.toml` at the root of the workspace, as opposed to the current\nworkspace member.\n{{/option}}\n\n{{/options}}\n\n### Display Options\n\n{{#options}}\n\n{{#option \"`--message-format` _fmt_\" }}\nThe representation in which to print the project location. Valid values:\n\n- `json` (default): JSON object with the path under the key \"root\".\n- `plain`: Just the path.\n{{/option}}\n\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Display the path to the manifest based on the current directory:\n\n       cargo locate-project\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-metadata\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-login.md",
    "content": "# cargo-login(1)\n\n## NAME\n\ncargo-login --- Log in to a registry\n\n## SYNOPSIS\n\n`cargo login` [_options_] [`--` _args_]\n\n## DESCRIPTION\n\nThis command will run a credential provider to save a token so that commands\nthat require authentication, such as {{man \"cargo-publish\" 1}}, will be\nautomatically authenticated.\n\nAll the arguments following the two dashes (`--`) are passed to the credential provider.\n\nFor the default `cargo:token` credential provider, the token is saved\nin `$CARGO_HOME/credentials.toml`. `CARGO_HOME` defaults to `.cargo`\nin your home directory.\n\nIf a registry has a credential-provider specified, it will be used. Otherwise,\nthe providers from the config value `registry.global-credential-providers` will\nbe attempted, starting from the end of the list.\n\nThe _token_ will be read from stdin.\n\nThe API token for crates.io may be retrieved from <https://crates.io/me>.\n\nTake care to keep the token secret, it should not be shared with anyone else.\n\n## OPTIONS\n\n### Login Options\n\n{{#options}}\n{{> options-registry }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Save the token for the default registry:\n\n       cargo login\n\n2. Save the token for a specific registry:\n\n       cargo login --registry my-registry\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-logout\" 1}}, {{man \"cargo-publish\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-logout.md",
    "content": "# cargo-logout(1)\n\n## NAME\n\ncargo-logout --- Remove an API token from the registry locally\n\n## SYNOPSIS\n\n`cargo logout` [_options_]\n\n## DESCRIPTION\n\nThis command will run a credential provider to remove a saved token.\n\nFor the default `cargo:token` credential provider, credentials are stored\nin `$CARGO_HOME/credentials.toml` where `$CARGO_HOME` defaults to `.cargo`\nin your home directory.\n\nIf a registry has a credential-provider specified, it will be used. Otherwise,\nthe providers from the config value `registry.global-credential-providers` will\nbe attempted, starting from the end of the list.\n\nIf `--registry` is not specified, then the credentials for the default\nregistry will be removed (configured by\n[`registry.default`](../reference/config.html#registrydefault), which defaults\nto <https://crates.io/>).\n\nThis will not revoke the token on the server. If you need to revoke the token,\nvisit the registry website and follow its instructions (see\n<https://crates.io/me> to revoke the token for <https://crates.io/>).\n\n## OPTIONS\n\n### Logout Options\n\n{{#options}}\n{{> options-registry }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Remove the default registry token:\n\n       cargo logout\n\n2. Remove the token for a specific registry:\n\n       cargo logout --registry my-registry\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-login\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-metadata.md",
    "content": "# cargo-metadata(1)\n\n## NAME\n\ncargo-metadata --- Machine-readable metadata about the current package\n\n## SYNOPSIS\n\n`cargo metadata` [_options_]\n\n## DESCRIPTION\n\nOutput JSON to stdout containing information about the workspace members and\nresolved dependencies of the current package.\n\nThe output format is subject to change in future versions of Cargo. It\nis recommended to include the `--format-version` flag to future-proof your code\nand ensure the output is in the format you are expecting. For more on the\nexpectations, see [\"Compatibility\"](#compatibility).\n\nSee the [cargo_metadata crate](https://crates.io/crates/cargo_metadata)\nfor a Rust API for reading the metadata.\n\n## OUTPUT FORMAT\n\n### Compatibility\n\nWithin the same output format version, the compatibility is maintained, except\nsome scenarios. The following is a non-exhaustive list of changes that are not\nconsidered as incompatible:\n\n* **Adding new fields** — New fields will be added when needed. Reserving this\n  helps Cargo evolve without bumping the format version too often.\n* **Adding new values for enum-like fields** — Same as adding new fields. It\n  keeps metadata evolving without stagnation.\n* **Changing opaque representations** — The inner representations of some\n  fields are implementation details. For example, fields related to\n  \"Source ID\" are treated as opaque identifiers to differentiate packages or\n  sources. Consumers shouldn't rely on those representations unless specified.\n\n### JSON format\n\nThe JSON output has the following format:\n\n```javascript\n{\n    /* Array of all packages in the workspace.\n       It also includes all feature-enabled dependencies unless --no-deps is used.\n    */\n    \"packages\": [\n        {\n            /* The name of the package. */\n            \"name\": \"my-package\",\n            /* The version of the package. */\n            \"version\": \"0.1.0\",\n            /* The Package ID for referring to the\n               package within the document and as the `--package` argument to many commands\n            */\n            \"id\": \"file:///path/to/my-package#0.1.0\",\n            /* The license value from the manifest, or null. */\n            \"license\": \"MIT/Apache-2.0\",\n            /* The license-file value from the manifest, or null. */\n            \"license_file\": \"LICENSE\",\n            /* The description value from the manifest, or null. */\n            \"description\": \"Package description.\",\n            /* The source ID of the package, an \"opaque\" identifier representing\n               where a package is retrieved from. See \"Compatibility\" above for\n               the stability guarantee.\n\n               This is null for path dependencies and workspace members.\n\n               For other dependencies, it is a string with the format:\n               - \"registry+URL\" for registry-based dependencies.\n                 Example: \"registry+https://github.com/rust-lang/crates.io-index\"\n               - \"git+URL\" for git-based dependencies.\n                 Example: \"git+https://github.com/rust-lang/cargo?rev=5e85ba14aaa20f8133863373404cb0af69eeef2c#5e85ba14aaa20f8133863373404cb0af69eeef2c\"\n               - \"sparse+URL\" for dependencies from a sparse registry\n                 Example: \"sparse+https://my-sparse-registry.org\"\n\n               The value after the `+` is not explicitly defined, and may change\n               between versions of Cargo and may not directly correlate to other\n               things, such as registry definitions in a config file. New source\n               kinds may be added in the future which will have different `+`\n               prefixed identifiers.\n            */\n            \"source\": null,\n            /* Array of dependencies declared in the package's manifest. */\n            \"dependencies\": [\n                {\n                    /* The name of the dependency. */\n                    \"name\": \"bitflags\",\n                    /* The source ID of the dependency. May be null, see\n                       description for the package source.\n                    */\n                    \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n                    /* The version requirement for the dependency.\n                       Dependencies without a version requirement have a value of \"*\".\n                    */\n                    \"req\": \"^1.0\",\n                    /* The dependency kind.\n                       \"dev\", \"build\", or null for a normal dependency.\n                    */\n                    \"kind\": null,\n                    /* If the dependency is renamed, this is the new name for\n                       the dependency as a string.  null if it is not renamed.\n                    */\n                    \"rename\": null,\n                    /* Boolean of whether or not this is an optional dependency. */\n                    \"optional\": false,\n                    /* Boolean of whether or not default features are enabled. */\n                    \"uses_default_features\": true,\n                    /* Array of features enabled. */\n                    \"features\": [],\n                    /* The target platform for the dependency.\n                       null if not a target dependency.\n                    */\n                    \"target\": \"cfg(windows)\",\n                    /* The file system path for a local path dependency.\n                       not present if not a path dependency.\n                    */\n                    \"path\": \"/path/to/dep\",\n                    /* A string of the URL of the registry this dependency is from.\n                       If not specified or null, the dependency is from the default\n                       registry (crates.io).\n                    */\n                    \"registry\": null,\n                    /* (unstable) Boolean flag of whether or not this is a pulbic\n                       dependency. This field is only present when\n                       `-Zpublic-dependency` is enabled.\n                    */\n                    \"public\": false\n                }\n            ],\n            /* Array of Cargo targets. */\n            \"targets\": [\n                {\n                    /* Array of target kinds.\n                       - lib targets list the `crate-type` values from the\n                         manifest such as \"lib\", \"rlib\", \"dylib\",\n                         \"proc-macro\", etc. (default [\"lib\"])\n                       - binary is [\"bin\"]\n                       - example is [\"example\"]\n                       - integration test is [\"test\"]\n                       - benchmark is [\"bench\"]\n                       - build script is [\"custom-build\"]\n                    */\n                    \"kind\": [\n                        \"bin\"\n                    ],\n                    /* Array of crate types.\n                       - lib and example libraries list the `crate-type` values\n                         from the manifest such as \"lib\", \"rlib\", \"dylib\",\n                         \"proc-macro\", etc. (default [\"lib\"])\n                       - all other target kinds are [\"bin\"]\n                    */\n                    \"crate_types\": [\n                        \"bin\"\n                    ],\n                    /* The name of the target.\n                       For lib targets, dashes will be replaced with underscores.\n                    */\n                    \"name\": \"my-package\",\n                    /* Absolute path to the root source file of the target. */\n                    \"src_path\": \"/path/to/my-package/src/main.rs\",\n                    /* The Rust edition of the target.\n                       Defaults to the package edition.\n                    */\n                    \"edition\": \"2018\",\n                    /* Array of required features.\n                       This property is not included if no required features are set.\n                    */\n                    \"required-features\": [\"feat1\"],\n                    /* Whether the target should be documented by `cargo doc`. */\n                    \"doc\": true,\n                    /* Whether or not this target has doc tests enabled, and\n                       the target is compatible with doc testing.\n                    */\n                    \"doctest\": false,\n                    /* Whether or not this target should be built and run with `--test`\n                    */\n                    \"test\": true\n                }\n            ],\n            /* Set of features defined for the package.\n               Each feature maps to an array of features or dependencies it\n               enables.\n            */\n            \"features\": {\n                \"default\": [\n                    \"feat1\"\n                ],\n                \"feat1\": [],\n                \"feat2\": []\n            },\n            /* Absolute path to this package's manifest. */\n            \"manifest_path\": \"/path/to/my-package/Cargo.toml\",\n            /* Package metadata.\n               This is null if no metadata is specified.\n            */\n            \"metadata\": {\n                \"docs\": {\n                    \"rs\": {\n                        \"all-features\": true\n                    }\n                }\n            },\n            /* List of registries to which this package may be published.\n               Publishing is unrestricted if null, and forbidden if an empty array. */\n            \"publish\": [\n                \"crates-io\"\n            ],\n            /* Array of authors from the manifest.\n               Empty array if no authors specified.\n            */\n            \"authors\": [\n                \"Jane Doe <user@example.com>\"\n            ],\n            /* Array of categories from the manifest. */\n            \"categories\": [\n                \"command-line-utilities\"\n            ],\n            /* Optional string that is the default binary picked by cargo run. */\n            \"default_run\": null,\n            /* Optional string that is the minimum supported rust version */\n            \"rust_version\": \"1.56\",\n            /* Array of keywords from the manifest. */\n            \"keywords\": [\n                \"cli\"\n            ],\n            /* The readme value from the manifest or null if not specified. */\n            \"readme\": \"README.md\",\n            /* The repository value from the manifest or null if not specified. */\n            \"repository\": \"https://github.com/rust-lang/cargo\",\n            /* The homepage value from the manifest or null if not specified. */\n            \"homepage\": \"https://rust-lang.org\",\n            /* The documentation value from the manifest or null if not specified. */\n            \"documentation\": \"https://doc.rust-lang.org/stable/std\",\n            /* The default edition of the package.\n               Note that individual targets may have different editions.\n            */\n            \"edition\": \"2018\",\n            /* Optional string that is the name of a native library the package\n               is linking to.\n            */\n            \"links\": null,\n        }\n    ],\n    /* Array of members of the workspace.\n       Each entry is the Package ID for the package.\n    */\n    \"workspace_members\": [\n        \"file:///path/to/my-package#0.1.0\",\n    ],\n    /* Array of default members of the workspace.\n       Each entry is the Package ID for the package.\n    */\n    \"workspace_default_members\": [\n        \"file:///path/to/my-package#0.1.0\",\n    ],\n    // The resolved dependency graph for the entire workspace. The enabled\n    // features are based on the enabled features for the \"current\" package.\n    // Inactivated optional dependencies are not listed.\n    //\n    // This is null if --no-deps is specified.\n    //\n    // By default, this includes all dependencies for all target platforms.\n    // The `--filter-platform` flag may be used to narrow to a specific\n    // target triple.\n    \"resolve\": {\n        /* Array of nodes within the dependency graph.\n           Each node is a package.\n        */\n        \"nodes\": [\n            {\n                /* The Package ID of this node. */\n                \"id\": \"file:///path/to/my-package#0.1.0\",\n                /* The dependencies of this package, an array of Package IDs. */\n                \"dependencies\": [\n                    \"https://github.com/rust-lang/crates.io-index#bitflags@1.0.4\"\n                ],\n                /* The dependencies of this package. This is an alternative to\n                   \"dependencies\" which contains additional information. In\n                   particular, this handles renamed dependencies.\n                */\n                \"deps\": [\n                    {\n                        /* The name of the dependency's library target.\n                           If this is a renamed dependency, this is the new\n                           name.\n                        */\n                        \"name\": \"bitflags\",\n                        /* The Package ID of the dependency. */\n                        \"pkg\": \"https://github.com/rust-lang/crates.io-index#bitflags@1.0.4\"\n                        /* Array of dependency kinds. Added in Cargo 1.40. */\n                        \"dep_kinds\": [\n                            {\n                                /* The dependency kind.\n                                   \"dev\", \"build\", or null for a normal dependency.\n                                */\n                                \"kind\": null,\n                                /* The target platform for the dependency.\n                                   null if not a target dependency.\n                                */\n                                \"target\": \"cfg(windows)\"\n                            }\n                        ]\n                    }\n                ],\n                /* Array of features enabled on this package. */\n                \"features\": [\n                    \"default\"\n                ]\n            }\n        ],\n        /* The package in the current working directory (if --manifest-path is not given).\n           This is null if there is a virtual workspace. Otherwise it is\n           the Package ID of the package.\n        */\n        \"root\": \"file:///path/to/my-package#0.1.0\",\n    },\n    /* The absolute path to the target directory where Cargo places its output. */\n    \"target_directory\": \"/path/to/my-package/target\",\n    /* The absolute path to the build directory where Cargo places intermediate build artifacts. (unstable) */\n    \"build_directory\": \"/path/to/my-package/build-dir\",\n    /* The version of the schema for this metadata structure.\n       This will be changed if incompatible changes are ever made.\n    */\n    \"version\": 1,\n    /* The absolute path to the root of the workspace. */\n    \"workspace_root\": \"/path/to/my-package\"\n    /* Workspace metadata.\n       This is null if no metadata is specified. */\n    \"metadata\": {\n        \"docs\": {\n            \"rs\": {\n                \"all-features\": true\n            }\n        }\n    }\n}\n````\n\nNotes:\n- For `\"id\"` field syntax, see [Package ID Specifications] in the reference.\n\n## OPTIONS\n\n### Output Options\n\n{{#options}}\n\n{{#option \"`--no-deps`\" }}\nOutput information only about the workspace members and don't fetch\ndependencies.\n{{/option}}\n\n{{#option \"`--format-version` _version_\" }}\nSpecify the version of the output format to use. Currently `1` is the only\npossible value.\n{{/option}}\n\n{{#option \"`--filter-platform` _triple_\" }}\nThis filters the `resolve` output to only include dependencies for the\ngiven [target triple](../appendix/glossary.html#target).\nA literal `\"host-tuple\"` can be used, which will internally be substituted by the host's target.\nWithout this flag, the resolve includes all targets.\n\nNote that the dependencies listed in the \"packages\" array still includes all\ndependencies. Each package definition is intended to be an unaltered\nreproduction of the information within `Cargo.toml`.\n{{/option}}\n\n{{/options}}\n\n{{> section-features }}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n\n{{> options-locked }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Output JSON about the current package:\n\n       cargo metadata --format-version=1\n\n## SEE ALSO\n\n{{man \"cargo\" 1}}, {{man \"cargo-pkgid\" 1}}, [Package ID Specifications], [JSON messages]\n\n[Package ID Specifications]: ../reference/pkgid-spec.html\n[JSON messages]: ../reference/external-tools.html#json-messages\n"
  },
  {
    "path": "src/doc/man/cargo-new.md",
    "content": "# cargo-new(1)\n\n## NAME\n\ncargo-new --- Create a new Cargo package\n\n## SYNOPSIS\n\n`cargo new` [_options_] _path_\n\n## DESCRIPTION\n\nThis command will create a new Cargo package in the given directory. This\nincludes a simple template with a `Cargo.toml` manifest, sample source file,\nand a VCS ignore file. If the directory is not already in a VCS repository,\nthen a new repository is created (see `--vcs` below).\n\nSee {{man \"cargo-init\" 1}} for a similar command which will create a new manifest\nin an existing directory.\n\n## OPTIONS\n\n### New Options\n\n{{> options-new }}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Create a binary Cargo package in the given directory:\n\n       cargo new foo\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-init\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-owner.md",
    "content": "# cargo-owner(1)\n\n## NAME\n\ncargo-owner --- Manage the owners of a crate on the registry\n\n## SYNOPSIS\n\n`cargo owner` [_options_] `--add` _login_ [_crate_]\\\n`cargo owner` [_options_] `--remove` _login_ [_crate_]\\\n`cargo owner` [_options_] `--list` [_crate_]\n\n## DESCRIPTION\n\nThis command will modify the owners for a crate on the registry. Owners of a\ncrate can upload new versions and yank old versions. Non-team owners can also\nmodify the set of owners, so take care!\n\nThis command requires you to be authenticated with either the `--token` option\nor using {{man \"cargo-login\" 1}}.\n\nIf the crate name is not specified, it will use the package name from the\ncurrent directory.\n\nSee [the reference](../reference/publishing.html#cargo-owner) for more\ninformation about owners and publishing.\n\n## OPTIONS\n\n### Owner Options\n\n{{#options}}\n\n{{#option \"`-a`\" \"`--add` _login_...\" }}\nInvite the given user or team as an owner.\n{{/option}}\n\n{{#option \"`-r`\" \"`--remove` _login_...\" }}\nRemove the given user or team as an owner.\n{{/option}}\n\n{{#option \"`-l`\" \"`--list`\" }}\nList owners of a crate.\n{{/option}}\n\n{{> options-token }}\n\n{{> options-index }}\n\n{{> options-registry }}\n\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. List owners of a package:\n\n       cargo owner --list foo\n\n2. Invite an owner to a package:\n\n       cargo owner --add username foo\n\n3. Remove an owner from a package:\n\n       cargo owner --remove username foo\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-login\" 1}}, {{man \"cargo-publish\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-package.md",
    "content": "# cargo-package(1)\n{{~*set command=\"package\"}}\n{{~*set actionverb=\"Package\"}}\n{{~*set noall=true}}\n{{~*set multitarget=true}}\n\n## NAME\n\ncargo-package --- Assemble the local package into a distributable tarball\n\n## SYNOPSIS\n\n`cargo package` [_options_]\n\n## DESCRIPTION\n\nThis command will create a distributable, compressed `.crate` file with the\nsource code of the package in the current directory. The resulting file will be\nstored in the `target/package` directory. This performs the following steps:\n\n1. Load and check the current workspace, performing some basic checks.\n    - Path dependencies are not allowed unless they have a version key. Cargo\n      will ignore the path key for dependencies in published packages.\n      `dev-dependencies` do not have this restriction.\n2. Create the compressed `.crate` file.\n    - The original `Cargo.toml` file is rewritten and normalized.\n    - `[patch]`, `[replace]`, and `[workspace]` sections are removed from the\n      manifest.\n    - `Cargo.lock` is always included. When missing, a new lock file will be\n      generated unless the `--exclude-lockfile` flag is used. {{man \"cargo-install\" 1}}\n      will use the packaged lock file if the `--locked` flag is used.\n    - A `.cargo_vcs_info.json` file is included that contains information\n      about the current VCS checkout hash if available, as well as a flag if the\n      worktree is dirty.\n    - Symlinks are flattened to their target files.\n    - Files and directories are included or excluded based on rules mentioned in\n      [the `[include]` and `[exclude]` fields](../reference/manifest.html#the-exclude-and-include-fields).\n\n3. Extract the `.crate` file and build it to verify it can build.\n    - This will rebuild your package from scratch to ensure that it can be\n      built from a pristine state. The `--no-verify` flag can be used to skip\n      this step.\n4. Check that build scripts did not modify any source files.\n\nThe list of files included can be controlled with the `include` and `exclude`\nfields in the manifest.\n\nSee [the reference](../reference/publishing.html) for more details about\npackaging and publishing.\n\n### .cargo_vcs_info.json format\n\nWill generate a `.cargo_vcs_info.json` in the following format\n\n```javascript\n{\n \"git\": {\n   \"sha1\": \"aac20b6e7e543e6dd4118b246c77225e3a3a1302\",\n   \"dirty\": true\n },\n \"path_in_vcs\": \"\"\n}\n```\n\n`dirty` indicates that the Git worktree was dirty when the package\nwas built.\n\n`path_in_vcs` will be set to a repo-relative path for packages\nin subdirectories of the version control repository.\n\nThe compatibility of this file is maintained under the same policy\nas the JSON output of {{man \"cargo-metadata\" 1}}.\n\nNote that this file provides a best-effort snapshot of the VCS information.\nHowever, the provenance of the package is not verified.\nThere is no guarantee that the source code in the tarball matches the VCS information.\n\n## OPTIONS\n\n### Package Options\n\n{{#options}}\n\n{{#option \"`-l`\" \"`--list`\" }}\nPrint files included in a package without making one.\n{{/option}}\n\n{{#option \"`--no-verify`\" }}\nDon't verify the contents by building them.\n{{/option}}\n\n{{#option \"`--no-metadata`\" }}\nIgnore warnings about a lack of human-usable metadata (such as the description\nor the license).\n{{/option}}\n\n{{#option \"`--allow-dirty`\" }}\nAllow working directories with uncommitted VCS changes to be packaged.\n{{/option}}\n\n{{#option \"`--exclude-lockfile`\" }}\nDon't include the lock file when packaging.\n\nThis flag is not for general use.\nSome tools may expect a lock file to be present (e.g. `cargo install --locked`).\nConsider other options before using this.\n{{/option}}\n\n{{> options-index }}\n\n{{#option \"`--registry` _registry_\"}}\nName of the registry to package for; see `cargo publish --help` for more details\nabout configuration of registry names. The packages will not be published\nto this registry, but if we are packaging multiple inter-dependent crates,\nlock-files will be generated under the assumption that dependencies will be\npublished to this registry.\n{{/option}}\n\n{{#option \"`--message-format` _fmt_\" }}\nSpecifies the output message format.\nCurrently, it only works with `--list` and affects the file listing format.\nThis is unstable and requires `-Zunstable-options`.\nValid output formats:\n\n- `human` (default): Display in a file-per-line format.\n- `json`: Emit machine-readable JSON information about each package.\n  One package per JSON line (Newline delimited JSON).\n  ```javascript\n  {\n    /* The Package ID Spec of the package. */\n    \"id\": \"path+file:///home/foo#0.0.0\",\n    /* Files of this package */\n    \"files\" {\n      /* Relative path in the archive file. */\n      \"Cargo.toml.orig\": {\n        /* Where the file is from.\n           - \"generate\" for file being generated during packaging\n           - \"copy\" for file being copied from another location.\n        */\n        \"kind\": \"copy\",\n        /* For the \"copy\" kind,\n           it is an absolute path to the actual file content.\n           For the \"generate\" kind,\n           it is the original file the generated one is based on.\n        */\n        \"path\": \"/home/foo/Cargo.toml\"\n      },\n      \"Cargo.toml\": {\n        \"kind\": \"generate\",\n        \"path\": \"/home/foo/Cargo.toml\"\n      },\n      \"src/main.rs\": {\n        \"kind\": \"copy\",\n        \"path\": \"/home/foo/src/main.rs\"\n      }\n    }\n  }\n  ```\n{{/option}}\n\n{{/options}}\n\n{{> section-package-selection }}\n\n### Compilation Options\n\n{{#options}}\n\n{{> options-target-triple }}\n\n{{> options-target-dir }}\n\n{{/options}}\n\n{{> section-features }}\n\n### Manifest Options\n\n{{#options}}\n\n{{> options-manifest-path }}\n\n{{> options-locked }}\n\n\n{{/options}}\n\n### Miscellaneous Options\n\n{{#options}}\n{{> options-jobs }}\n{{> options-keep-going }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Create a compressed `.crate` file of the current package:\n\n       cargo package\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-publish\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-pkgid.md",
    "content": "# cargo-pkgid(1)\n\n## NAME\n\ncargo-pkgid --- Print a fully qualified package specification\n\n## SYNOPSIS\n\n`cargo pkgid` [_options_] [_spec_]\n\n## DESCRIPTION\n\nGiven a _spec_ argument, print out the fully qualified package ID specifier\nfor a package or dependency in the current workspace. This command will\ngenerate an error if _spec_ is ambiguous as to which package it refers to in\nthe dependency graph. If no _spec_ is given, then the specifier for the local\npackage is printed.\n\nThis command requires that a lockfile is available and dependencies have been\nfetched.\n\nA package specifier consists of a name, version, and source URL. You are\nallowed to use partial specifiers to succinctly match a specific package as\nlong as it matches only one package. This specifier is also used by other parts\nin Cargo, such as {{man \"cargo-metadata\" 1}} and [JSON messages] emitted by Cargo.\n\nThe format of a _spec_ can be one of the following:\n\nSPEC Structure             | Example SPEC\n---------------------------|--------------\n_name_                     | `bitflags`\n_name_`@`_version_         | `bitflags@1.0.4`\n_url_                      | `https://github.com/rust-lang/cargo`\n_url_`#`_version_          | `https://github.com/rust-lang/cargo#0.33.0`\n_url_`#`_name_             | `https://github.com/rust-lang/crates.io-index#bitflags`\n_url_`#`_name_`@`_version_ | `https://github.com/rust-lang/cargo#crates-io@0.21.0`\n\nThe specification grammar can be found in chapter [Package ID Specifications].\n\n## OPTIONS\n\n### Package Selection\n\n{{#options}}\n\n{{#option \"`-p` _spec_\" \"`--package` _spec_\" }}\nGet the package ID for the given package instead of the current package.\n{{/option}}\n\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n\n{{> options-manifest-path }}\n\n{{> options-locked }}\n\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Retrieve package specification for `foo` package:\n\n       cargo pkgid foo\n\n2. Retrieve package specification for version 1.0.0 of `foo`:\n\n       cargo pkgid foo@1.0.0\n\n3. Retrieve package specification for `foo` from crates.io:\n\n       cargo pkgid https://github.com/rust-lang/crates.io-index#foo\n\n4. Retrieve package specification for `foo` from a local package:\n\n       cargo pkgid file:///path/to/local/package#foo\n\n## SEE ALSO\n\n{{man \"cargo\" 1}}, {{man \"cargo-generate-lockfile\" 1}}, {{man \"cargo-metadata\" 1}},\n[Package ID Specifications], [JSON messages]\n\n[Package ID Specifications]: ../reference/pkgid-spec.html\n[JSON messages]: ../reference/external-tools.html#json-messages\n"
  },
  {
    "path": "src/doc/man/cargo-publish.md",
    "content": "# cargo-publish(1)\n{{~*set command=\"publish\"}}\n{{~*set actionverb=\"Publish\"}}\n{{~*set multitarget=true}}\n\n## NAME\n\ncargo-publish --- Upload a package to the registry\n\n## SYNOPSIS\n\n`cargo publish` [_options_]\n\n## DESCRIPTION\n\nThis command will create a distributable, compressed `.crate` file with the\nsource code of the package in the current directory and upload it to a\nregistry. The default registry is <https://crates.io>. This performs the\nfollowing steps:\n\n1. Performs a few checks, including:\n   - Checks the `package.publish` key in the manifest for restrictions on\n     which registries you are allowed to publish to.\n2. Create a `.crate` file by following the steps in {{man \"cargo-package\" 1}}.\n3. Upload the crate to the registry. The server will perform additional\n   checks on the crate. \n4. The client will poll waiting for the package to appear in the index,\n   and may timeout. In that case, you will need to check for completion\n   manually. This timeout does not affect the upload.\n\nThis command requires you to be authenticated using {{man \"cargo-login\" 1}}\nor environment variables of the [`registry.token`](../reference/config.html#registrytoken)\nand [`registries.<name>.token`](../reference/config.html#registriesnametoken) config fields.\n\nSee [the reference](../reference/publishing.html) for more details about\npackaging and publishing.\n\n## OPTIONS\n\n### Publish Options\n\n{{#options}}\n\n{{#option \"`--dry-run`\" }}\nPerform all checks without uploading.\n{{/option}}\n\n{{#option \"`--no-verify`\" }}\nDon't verify the contents by building them.\n{{/option}}\n\n{{#option \"`--allow-dirty`\" }}\nAllow working directories with uncommitted VCS changes to be packaged.\n{{/option}}\n\n{{> options-index }}\n\n{{#option \"`--registry` _registry_\"}}\nName of the registry to publish to. Registry names are defined in [Cargo\nconfig files](../reference/config.html). If not specified, and there is a\n[`package.publish`](../reference/manifest.html#the-publish-field) field in\n`Cargo.toml` with a single registry, then it will publish to that registry.\nOtherwise it will use the default registry, which is defined by the\n[`registry.default`](../reference/config.html#registrydefault) config key\nwhich defaults to `crates-io`.\n{{/option}}\n\n{{/options}}\n\n{{> section-package-selection }}\n\n### Compilation Options\n\n{{#options}}\n\n{{> options-target-triple }}\n\n{{> options-target-dir }}\n\n{{/options}}\n\n{{> section-features }}\n\n### Manifest Options\n\n{{#options}}\n\n{{> options-manifest-path }}\n\n{{> options-locked }}\n\n\n{{/options}}\n\n### Miscellaneous Options\n\n{{#options}}\n{{> options-jobs }}\n{{> options-keep-going }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Publish the current package:\n\n       cargo publish\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-package\" 1}}, {{man \"cargo-login\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-remove.md",
    "content": "# cargo-remove(1)\n{{~*set command=\"remove\"}}\n{{~*set actionverb=\"Remove\"}}\n{{~*set nouns=\"removes\"}}\n\n## NAME\n\ncargo-remove --- Remove dependencies from a Cargo.toml manifest file\n\n## SYNOPSIS\n\n`cargo remove` [_options_] _dependency_...\n\n## DESCRIPTION\n\nRemove one or more dependencies from a `Cargo.toml` manifest.\n\n## OPTIONS\n\n### Section options\n\n{{#options}}\n\n{{#option \"`--dev`\" }}\nRemove as a [development dependency](../reference/specifying-dependencies.html#development-dependencies).\n{{/option}}\n\n{{#option \"`--build`\" }}\nRemove as a [build dependency](../reference/specifying-dependencies.html#build-dependencies).\n{{/option}}\n\n{{#option \"`--target` _target_\" }}\nRemove as a dependency to the [given target platform](../reference/specifying-dependencies.html#platform-specific-dependencies).\n\nTo avoid unexpected shell expansions, you may use quotes around each target, e.g., `--target 'cfg(unix)'`.\n{{/option}}\n\n{{/options}}\n\n### Miscellaneous Options\n\n{{#options}}\n\n{{#option \"`--dry-run`\" }}\nDon't actually write to the manifest.\n{{/option}}\n\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n\n{{> options-locked }}\n\n{{/options}}\n\n### Package Selection\n\n{{#options}}\n\n{{#option \"`-p` _spec_...\" \"`--package` _spec_...\" }}\nPackage to remove from.\n{{/option}}\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Remove `regex` as a dependency\n\n       cargo remove regex\n\n2. Remove `trybuild` as a dev-dependency\n\n       cargo remove --dev trybuild\n\n3. Remove `nom` from the `wasm32-unknown-unknown` dependencies table\n\n       cargo remove --target wasm32-unknown-unknown nom\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-add\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-report-future-incompatibilities.md",
    "content": "# cargo-report-future-incompatibilities(1)\n{{~*set actionverb=\"Display a report for\"}}\n\n## NAME\n\ncargo-report-future-incompatibilities --- Reports any crates which will eventually stop compiling\n\n## SYNOPSIS\n\n`cargo report future-incompatibilities` [_options_]\n\n## DESCRIPTION\n\nDisplays a report of future-incompatible warnings that were emitted during\nprevious builds.\nThese are warnings for changes that may become hard errors in the future,\ncausing dependencies to stop building in a future version of rustc.\n\nFor more, see the chapter on [Future incompat report](../reference/future-incompat-report.html).\n\n## OPTIONS\n\n{{#options}}\n\n{{#option \"`--id` _id_\" }}\nShow the report with the specified Cargo-generated id.\nIf not specified, shows the most recent report.\n{{/option}}\n\n{{/options}}\n\n{{> section-options-package }}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-locked }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Display the latest future-incompat report:\n\n       cargo report future-incompat\n\n2. Display the latest future-incompat report for a specific package:\n\n       cargo report future-incompat --package my-dep@0.0.1\n\n## SEE ALSO\n\n{{man \"cargo\" 1}}, {{man \"cargo-report\" 1}}, {{man \"cargo-build\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-report.md",
    "content": "# cargo-report(1)\n\n## NAME\n\ncargo-report --- Generate and display various kinds of reports\n\n## SYNOPSIS\n\n`cargo report` _type_ [_options_]\n\n## DESCRIPTION\n\nDisplays a report of the given _type_ --- currently, only `future-incompat` is supported\n\n## OPTIONS\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-locked }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Display the available kinds of reports:\n\n       cargo report --help\n\n## SEE ALSO\n\n{{man \"cargo\" 1}}, {{man \"cargo-report-future-incompatibilities\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-run.md",
    "content": "# cargo-run(1)\n{{~*set command=\"run\"}}\n{{~*set actionverb=\"Run\"}}\n\n## NAME\n\ncargo-run --- Run the current package\n\n## SYNOPSIS\n\n`cargo run` [_options_] [`--` _args_]\n\n## DESCRIPTION\n\nRun a binary or example of the local package.\n\nAll the arguments following the two dashes (`--`) are passed to the binary to\nrun. If you're passing arguments to both Cargo and the binary, the ones after\n`--` go to the binary, the ones before go to Cargo.\n\nUnlike {{man \"cargo-test\" 1}} and {{man \"cargo-bench\" 1}}, `cargo run` sets the \nworking directory of the binary executed to the current working directory, same \nas if it was executed in the shell directly.\n\n## OPTIONS\n\n{{> section-options-package }}\n\n### Target Selection\n\nWhen no target selection options are given, `cargo run` will run the binary\ntarget. If there are multiple binary targets, you must pass a target flag to\nchoose one. Or, the `default-run` field may be specified in the `[package]`\nsection of `Cargo.toml` to choose the name of the binary to run by default.\n\n{{#options}}\n\n{{#option \"`--bin` _name_\" }}\nRun the specified binary.\n{{/option}}\n\n{{#option \"`--example` _name_\" }}\nRun the specified example.\n{{/option}}\n\n{{/options}}\n\n{{> section-features }}\n\n### Compilation Options\n\n{{#options}}\n\n{{> options-target-triple }}\n\n{{> options-release }}\n\n{{> options-profile }}\n\n{{> options-timings }}\n\n{{/options}}\n\n### Output Options\n\n{{#options}}\n{{> options-target-dir }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n\n{{> options-display }}\n\n{{> options-message-format }}\n\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n\n{{> options-manifest-path }}\n\n{{> options-ignore-rust-version }}\n\n{{> options-locked }}\n\n\n{{/options}}\n\n{{> section-options-common }}\n\n### Miscellaneous Options\n\n{{#options}}\n{{> options-jobs }}\n{{> options-keep-going }}\n{{/options}}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Build the local package and run its main target (assuming only one binary):\n\n       cargo run\n\n2. Run an example with extra arguments:\n\n       cargo run --example exname -- --exoption exarg1 exarg2\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-build\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-rustc.md",
    "content": "# cargo-rustc(1)\n{{~*set command=\"rustc\"}}\n{{~*set actionverb=\"Build\"}}\n{{~*set multitarget=true}}\n\n## NAME\n\ncargo-rustc --- Compile the current package, and pass extra options to the compiler\n\n## SYNOPSIS\n\n`cargo rustc` [_options_] [`--` _args_]\n\n## DESCRIPTION\n\nThe specified target for the current package (or package specified by `-p` if\nprovided) will be compiled along with all of its dependencies. The specified\n_args_ will all be passed to the final compiler invocation, not any of the\ndependencies. Note that the compiler will still unconditionally receive\narguments such as `-L`, `--extern`, and `--crate-type`, and the specified\n_args_ will simply be added to the compiler invocation.\n\nSee <https://doc.rust-lang.org/rustc/index.html> for documentation on rustc\nflags.\n\n{{> description-one-target }}\n\nTo pass flags to all compiler processes spawned by Cargo, use the `RUSTFLAGS`\n[environment variable](../reference/environment-variables.html) or the\n`build.rustflags` [config value](../reference/config.html).\n\n## OPTIONS\n\n{{> section-options-package }}\n\n### Target Selection\n\nWhen no target selection options are given, `cargo rustc` will build all\nbinary and library targets of the selected package.\n\n{{> options-targets-bin-auto-built }}\n\n{{> options-targets }}\n\n{{> section-features }}\n\n### Compilation Options\n\n{{#options}}\n\n{{> options-target-triple }}\n\n{{> options-release }}\n\n{{#option \"`--profile` _name_\" }}\nBuild with the given profile.\n\nThe `rustc` subcommand will treat the following named profiles with special behaviors:\n\n* `check` --- Builds in the same way as the {{man \"cargo-check\" 1}} command with\n  the `dev` profile.\n* `test` --- Builds in the same way as the {{man \"cargo-test\" 1}} command,\n  enabling building in test mode which will enable tests and enable the `test`\n  cfg option. See [rustc\n  tests](https://doc.rust-lang.org/rustc/tests/index.html) for more detail.\n* `bench` --- Builds in the same was as the {{man \"cargo-bench\" 1}} command,\n  similar to the `test` profile.\n\nSee [the reference](../reference/profiles.html) for more details on profiles.\n{{/option}}\n\n{{> options-timings }}\n\n{{#option \"`--crate-type` _crate-type_\"}}\nBuild for the given crate type. This flag accepts a comma-separated list of\n1 or more crate types, of which the allowed values are the same as `crate-type`\nfield in the manifest for configuring a Cargo target. See\n[`crate-type` field](../reference/cargo-targets.html#the-crate-type-field)\nfor possible values.\n\nIf the manifest contains a list, and `--crate-type` is provided,\nthe command-line argument value will override what is in the manifest.\n\nThis flag only works when building a `lib` or `example` library target.\n{{/option}}\n\n{{/options}}\n\n### Output Options\n\n{{#options}}\n{{> options-target-dir }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n\n{{> options-display }}\n\n{{> options-message-format }}\n\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n\n{{> options-manifest-path }}\n\n{{> options-ignore-rust-version }}\n\n{{> options-locked }}\n\n\n{{/options}}\n\n{{> section-options-common }}\n\n### Miscellaneous Options\n\n{{#options}}\n{{> options-jobs }}\n{{> options-keep-going }}\n{{> options-future-incompat }}\n{{/options}}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Check if your package (not including dependencies) uses unsafe code:\n\n       cargo rustc --lib -- -D unsafe-code\n\n2. Try an experimental flag on the nightly compiler, such as this which prints\n   the size of every type:\n\n       cargo rustc --lib -- -Z print-type-sizes\n\n3. Override `crate-type` field in Cargo.toml with command-line option:\n\n       cargo rustc --lib --crate-type lib,cdylib\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-build\" 1}}, {{man \"rustc\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-rustdoc.md",
    "content": "# cargo-rustdoc(1)\n{{~*set command=\"rustdoc\"}}\n{{~*set actionverb=\"Document\"}}\n{{~*set multitarget=true}}\n\n## NAME\n\ncargo-rustdoc --- Build a package's documentation, using specified custom flags\n\n## SYNOPSIS\n\n`cargo rustdoc` [_options_] [`--` _args_]\n\n## DESCRIPTION\n\nThe specified target for the current package (or package specified by `-p` if\nprovided) will be documented with the specified _args_ being passed to the\nfinal rustdoc invocation. Dependencies will not be documented as part of this\ncommand. Note that rustdoc will still unconditionally receive arguments such\nas `-L`, `--extern`, and `--crate-type`, and the specified _args_ will simply\nbe added to the rustdoc invocation.\n\nSee <https://doc.rust-lang.org/rustdoc/index.html> for documentation on rustdoc\nflags.\n\n{{> description-one-target }}\n\nTo pass flags to all rustdoc processes spawned by Cargo, use the\n`RUSTDOCFLAGS` [environment variable](../reference/environment-variables.html)\nor the `build.rustdocflags` [config value](../reference/config.html).\n\n## OPTIONS\n\n### Documentation Options\n\n{{#options}}\n\n{{#option \"`--open`\" }}\nOpen the docs in a browser after building them. This will use your default\nbrowser unless you define another one in the `BROWSER` environment variable\nor use the [`doc.browser`](../reference/config.html#docbrowser) configuration\noption.\n{{/option}}\n\n{{/options}}\n\n{{> section-options-package }}\n\n### Target Selection\n\nWhen no target selection options are given, `cargo rustdoc` will document all\nbinary and library targets of the selected package. The binary will be skipped\nif its name is the same as the lib target. Binaries are skipped if they have\n`required-features` that are missing.\n\n{{> options-targets }}\n\n{{> section-features }}\n\n### Compilation Options\n\n{{#options}}\n\n{{> options-target-triple }}\n\n{{> options-release }}\n\n{{> options-profile }}\n\n{{> options-timings }}\n\n{{/options}}\n\n### Output Options\n\n{{#options}}\n{{> options-target-dir }}\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n\n{{> options-message-format }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-manifest-path }}\n\n{{> options-ignore-rust-version }}\n\n{{> options-locked }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n### Miscellaneous Options\n\n{{#options}}\n{{> options-jobs }}\n{{> options-keep-going }}\n{{> options-output-format }}\n{{/options}}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Build documentation with custom CSS included from a given file:\n\n       cargo rustdoc --lib -- --extend-css extra.css\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-doc\" 1}}, {{man \"rustdoc\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-search.md",
    "content": "# cargo-search(1)\n\n## NAME\n\ncargo-search --- Search packages in the registry. Default registry is crates.io\n\n## SYNOPSIS\n\n`cargo search` [_options_] [_query_...]\n\n## DESCRIPTION\n\nThis performs a textual search for crates on <https://crates.io>. The matching\ncrates will be displayed along with their description in TOML format suitable\nfor copying into a `Cargo.toml` manifest.\n\n## OPTIONS\n\n### Search Options\n\n{{#options}}\n\n{{#option \"`--limit` _limit_\" }}\nLimit the number of results (default: 10, max: 100).\n{{/option}}\n\n{{> options-index }}\n\n{{> options-registry }}\n\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Search for a package from crates.io:\n\n       cargo search serde\n\n## SEE ALSO\n\n{{man \"cargo\" 1}}, {{man \"cargo-install\" 1}}, {{man \"cargo-publish\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-test.md",
    "content": "# cargo-test(1)\n{{~*set command=\"test\"}}\n{{~*set actionverb=\"Test\"}}\n{{~*set nouns=\"tests\"}}\n{{~*set multitarget=true}}\n\n## NAME\n\ncargo-test --- Execute unit and integration tests of a package\n\n## SYNOPSIS\n\n`cargo test` [_options_] [_testname_] [`--` _test-options_]\n\n## DESCRIPTION\n\nCompile and execute unit, integration, and documentation tests.\n\nThe test filtering argument `TESTNAME` and all the arguments following the two\ndashes (`--`) are passed to the test binaries and thus to _libtest_ (rustc's\nbuilt in unit-test and micro-benchmarking framework).  If you're passing\narguments to both Cargo and the binary, the ones after `--` go to the binary,\nthe ones before go to Cargo.  For details about libtest's arguments see the\noutput of `cargo test -- --help` and check out the rustc book's chapter on\nhow tests work at <https://doc.rust-lang.org/rustc/tests/index.html>.\n\nAs an example, this will filter for tests with `foo` in their name and run them\non 3 threads in parallel:\n\n    cargo test foo -- --test-threads 3\n\nTests are built with the `--test` option to `rustc` which creates a special\nexecutable by linking your code with libtest. The executable automatically\nruns all functions annotated with the `#[test]` attribute in multiple threads.\n`#[bench]` annotated functions will also be run with one iteration to verify\nthat they are functional.\n\nIf the package contains multiple test targets, each target compiles to a\nspecial executable as aforementioned, and then is run serially.\n\nThe libtest harness may be disabled by setting `harness = false` in the target\nmanifest settings, in which case your code will need to provide its own `main`\nfunction to handle running tests.\n\n### Documentation tests\n\nDocumentation tests are also run by default, which is handled by `rustdoc`. It\nextracts code samples from documentation comments of the library target, and\nthen executes them.\n\nDifferent from normal test targets, each code block compiles to a doctest\nexecutable on the fly with `rustc`. These executables run in parallel in\nseparate processes. The compilation of a code block is in fact a part of test\nfunction controlled by libtest, so some options such as `--jobs` might not\ntake effect. Note that this execution model of doctests is not guaranteed\nand may change in the future; beware of depending on it.\n\nSee the [rustdoc book](https://doc.rust-lang.org/rustdoc/) for more information\non writing doc tests.\n\n### Working directory of tests\n\nThe working directory when running each unit and integration test is set to the\nroot directory of the package the test belongs to.\nSetting the working directory of tests to the package's root directory makes it\npossible for tests to reliably access the package's files using relative paths,\nregardless from where `cargo test` was executed from.\n\nFor documentation tests, the working directory when invoking `rustdoc` is set to\nthe workspace root directory, and is also the directory `rustdoc` uses as the\ncompilation directory of each documentation test.\nThe working directory when running each documentation test is set to the root\ndirectory of the package the test belongs to, and is controlled via `rustdoc`'s\n`--test-run-directory` option.\n\n## OPTIONS\n\n### Test Options\n\n{{> options-test }}\n\n{{> section-package-selection }}\n\n### Target Selection\n\nWhen no target selection options are given, `cargo test` will build the\nfollowing targets of the selected packages:\n\n- lib --- used to link with binaries, examples, integration tests, and doc tests\n- bins (only if integration tests are built and required features are\n  available)\n- examples --- to ensure they compile\n- lib as a unit test\n- bins as unit tests\n- integration tests\n- doc tests for the lib target\n\nThe default behavior can be changed by setting the `test` flag for the target\nin the manifest settings. Setting examples to `test = true` will build and run\nthe example as a test, replacing the example's `main` function with the\nlibtest harness. If you don't want the `main` function replaced, also include\n`harness = false`, in which case the example will be built and executed as-is.\n\nSetting targets to `test = false` will stop them from being tested by default.\nTarget selection options that take a target by name (such as `--example foo`)\nignore the `test` flag and will always test the given target.\n\nDoc tests for libraries may be disabled by setting `doctest = false` for the\nlibrary in the manifest.\n\nSee [Configuring a target](../reference/cargo-targets.html#configuring-a-target)\nfor more information on per-target settings.\n\n{{> options-targets-bin-auto-built }}\n\n{{> options-targets }}\n\n{{#options}}\n\n{{#option \"`--doc`\" }}\nTest only the library's documentation. This cannot be mixed with other\ntarget options.\n{{/option}}\n\n{{/options}}\n\n{{> section-features }}\n\n### Compilation Options\n\n{{#options}}\n\n{{> options-target-triple }}\n\n{{> options-release }}\n\n{{> options-profile }}\n\n{{> options-timings }}\n\n{{/options}}\n\n### Output Options\n\n{{#options}}\n{{> options-target-dir }}\n{{/options}}\n\n### Display Options\n\nBy default the Rust test harness hides output from test execution to keep\nresults readable. Test output can be recovered (e.g., for debugging) by passing\n`--no-capture` to the test binaries:\n\n    cargo test -- --no-capture\n\n{{#options}}\n\n{{> options-display }}\n\n{{> options-message-format }}\n\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n\n{{> options-manifest-path }}\n\n{{> options-ignore-rust-version }}\n\n{{> options-locked }}\n\n\n{{/options}}\n\n{{> section-options-common }}\n\n### Miscellaneous Options\n\nThe `--jobs` argument affects the building of the test executable but does not\naffect how many threads are used when running the tests. The Rust test harness\nincludes an option to control the number of threads used:\n\n    cargo test -j 2 -- --test-threads=2\n\n{{#options}}\n\n{{> options-jobs }}\n{{> options-future-incompat }}\n\n{{/options}}\n\nWhile `cargo test` involves compilation, it does not provide a `--keep-going`\nflag. Use `--no-fail-fast` to run as many tests as possible without stopping at\nthe first failure. To \"compile\" as many tests as possible, use `--tests` to\nbuild test binaries separately. For example:\n\n    cargo build --tests --keep-going\n    cargo test --tests --no-fail-fast\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Execute all the unit and integration tests of the current package:\n\n       cargo test\n\n2. Run only tests whose names match against a filter string:\n\n       cargo test name_filter\n\n3. Run only a specific test within a specific integration test:\n\n       cargo test --test int_test_name -- modname::test_name\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-bench\" 1}}, [types of tests](../reference/cargo-targets.html#tests), [how to write tests](https://doc.rust-lang.org/rustc/tests/index.html)\n"
  },
  {
    "path": "src/doc/man/cargo-tree.md",
    "content": "# cargo-tree(1)\n{{~*set command=\"tree\"}}\n{{~*set actionverb=\"Display\"}}\n{{~*set noall=true}}\n\n## NAME\n\ncargo-tree --- Display a tree visualization of a dependency graph\n\n## SYNOPSIS\n\n`cargo tree` [_options_]\n\n## DESCRIPTION\n\nThis command will display a tree of dependencies to the terminal. An example\nof a simple project that depends on the \"rand\" package:\n\n```\nmyproject v0.1.0 (/myproject)\n└── rand v0.7.3\n    ├── getrandom v0.1.14\n    │   ├── cfg-if v0.1.10\n    │   └── libc v0.2.68\n    ├── libc v0.2.68 (*)\n    ├── rand_chacha v0.2.2\n    │   ├── ppv-lite86 v0.2.6\n    │   └── rand_core v0.5.1\n    │       └── getrandom v0.1.14 (*)\n    └── rand_core v0.5.1 (*)\n[build-dependencies]\n└── cc v1.0.50\n```\n\nPackages marked with `(*)` have been \"de-duplicated\". The dependencies for the\npackage have already been shown elsewhere in the graph, and so are not\nrepeated. Use the `--no-dedupe` option to repeat the duplicates.\n\nThe `-e` flag can be used to select the dependency kinds to display. The\n\"features\" kind changes the output to display the features enabled by\neach dependency. For example, `cargo tree -e features`:\n\n```\nmyproject v0.1.0 (/myproject)\n└── log feature \"serde\"\n    └── log v0.4.8\n        ├── serde v1.0.106\n        └── cfg-if feature \"default\"\n            └── cfg-if v0.1.10\n```\n\nIn this tree, `myproject` depends on `log` with the `serde` feature. `log` in\nturn depends on `cfg-if` with \"default\" features. When using `-e features` it\ncan be helpful to use `-i` flag to show how the features flow into a package.\nSee the examples below for more detail.\n\n### Feature Unification\n\nThis command shows a graph much closer to a feature-unified graph Cargo will\nbuild, rather than what you list in `Cargo.toml`. For instance, if you specify\nthe same dependency in both `[dependencies]` and `[dev-dependencies]` but with\ndifferent features on. This command may merge all features and show a `(*)` on\none of the dependency to indicate the duplicate.\n\nAs a result, for a mostly equivalent overview of what `cargo build` does,\n`cargo tree -e normal,build` is pretty close; for a mostly equivalent overview\nof what `cargo test` does, `cargo tree` is pretty close. However, it doesn't\nguarantee the exact equivalence to what Cargo is going to build, since a\ncompilation is complex and depends on lots of different factors.\n\nTo learn more about feature unification, check out this\n[dedicated section](../reference/features.html#feature-unification).\n\n## OPTIONS\n\n### Tree Options\n\n{{#options}}\n\n{{#option \"`-i` _spec_\" \"`--invert` _spec_\" }}\nShow the reverse dependencies for the given package. This flag will invert\nthe tree and display the packages that depend on the given package.\n\nNote that in a workspace, by default it will only display the package's\nreverse dependencies inside the tree of the workspace member in the current\ndirectory. The `--workspace` flag can be used to extend it so that it will\nshow the package's reverse dependencies across the entire workspace. The `-p`\nflag can be used to display the package's reverse dependencies only with the\nsubtree of the package given to `-p`.\n{{/option}}\n\n{{#option \"`--prune` _spec_\" }}\nPrune the given package from the display of the dependency tree.\n{{/option}}\n\n{{#option \"`--depth` _depth_\" }}\nMaximum display depth of the dependency tree. A depth of 1 displays the direct\ndependencies, for example.\n\nIf the given value is `workspace`, only shows the dependencies that are member\nof the current workspace, instead.\n{{/option}}\n\n{{#option \"`--no-dedupe`\" }}\nDo not de-duplicate repeated dependencies. Usually, when a package has already\ndisplayed its dependencies, further occurrences will not re-display its\ndependencies, and will include a `(*)` to indicate it has already been shown.\nThis flag will cause those duplicates to be repeated.\n{{/option}}\n\n{{#option \"`-d`\" \"`--duplicates`\" }}\nShow only dependencies which come in multiple versions (implies `--invert`).\nWhen used with the `-p` flag, only shows duplicates within the subtree of the\ngiven package.\n\nIt can be beneficial for build times and executable sizes to avoid building\nthat same package multiple times. This flag can help identify the offending\npackages. You can then investigate if the package that depends on the\nduplicate with the older version can be updated to the newer version so that\nonly one instance is built.\n{{/option}}\n\n{{#option \"`-e` _kinds_\" \"`--edges` _kinds_\" }}\nThe dependency kinds to display. Takes a comma separated list of values:\n\n- `all` --- Show all edge kinds.\n- `normal` --- Show normal dependencies.\n- `build` --- Show build dependencies.\n- `dev` --- Show development dependencies.\n- `features` --- Show features enabled by each dependency. If this is the only\n  kind given, then it will automatically include the other dependency kinds.\n- `no-normal` --- Do not include normal dependencies.\n- `no-build` --- Do not include build dependencies.\n- `no-dev` --- Do not include development dependencies.\n- `no-proc-macro` --- Do not include procedural macro dependencies.\n\nThe `normal`, `build`, `dev`, and `all` dependency kinds cannot be mixed with\n`no-normal`, `no-build`, or `no-dev` dependency kinds.\n\nThe default is `normal,build,dev`.\n{{/option}}\n\n{{#option \"`--target` _triple_\" }}\nFilter dependencies matching the given [target triple](../appendix/glossary.html#target). \nThe default is the host platform. Use the value `all` to include *all* targets.\n{{/option}}\n\n{{/options}}\n\n### Tree Formatting Options\n\n{{#options}}\n\n{{#option \"`--charset` _charset_\" }}\nChooses the character set to use for the tree. Valid values are \"utf8\" or\n\"ascii\". When unspecified, cargo will auto-select a value.\n{{/option}}\n\n{{#option \"`-f` _format_\" \"`--format` _format_\" }}\nSet the format string for each package. The default is \"{p}\".\n\nThis is an arbitrary string which will be used to display each package. The following\nstrings will be replaced with the corresponding value:\n\n- `{p}`, `{package}` --- The package name.\n- `{l}`, `{license}` --- The package license.\n- `{r}`, `{repository}` --- The package repository URL.\n- `{f}`, `{features}` --- Comma-separated list of package features that are enabled.\n- `{lib}` --- The name, as used in a `use` statement, of the package's library.\n{{/option}}\n\n{{#option \"`--prefix` _prefix_\" }}\nSets how each line is displayed. The _prefix_ value can be one of:\n\n- `indent` (default) --- Shows each line indented as a tree.\n- `depth` --- Show as a list, with the numeric depth printed before each entry.\n- `none` --- Show as a flat list.\n{{/option}}\n\n{{/options}}\n\n{{> section-package-selection }}\n\n### Manifest Options\n\n{{#options}}\n\n{{> options-manifest-path }}\n\n{{> options-locked }}\n\n{{/options}}\n\n{{> section-features }}\n\n### Display Options\n\n{{#options}}\n\n{{> options-display }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Display the tree for the package in the current directory:\n\n       cargo tree\n\n2. Display all the packages that depend on the `syn` package:\n\n       cargo tree -i syn\n\n3. Show the features enabled on each package:\n\n       cargo tree --format \"{p} {f}\"\n\n4. Show all packages that are built multiple times. This can happen if multiple\n   semver-incompatible versions appear in the tree (like 1.0.0 and 2.0.0).\n\n       cargo tree -d\n\n5. Explain why features are enabled for the `syn` package:\n\n       cargo tree -e features -i syn\n\n   The `-e features` flag is used to show features. The `-i` flag is used to\n   invert the graph so that it displays the packages that depend on `syn`. An\n   example of what this would display:\n\n   ```\n   syn v1.0.17\n   ├── syn feature \"clone-impls\"\n   │   └── syn feature \"default\"\n   │       └── rustversion v1.0.2\n   │           └── rustversion feature \"default\"\n   │               └── myproject v0.1.0 (/myproject)\n   │                   └── myproject feature \"default\" (command-line)\n   ├── syn feature \"default\" (*)\n   ├── syn feature \"derive\"\n   │   └── syn feature \"default\" (*)\n   ├── syn feature \"full\"\n   │   └── rustversion v1.0.2 (*)\n   ├── syn feature \"parsing\"\n   │   └── syn feature \"default\" (*)\n   ├── syn feature \"printing\"\n   │   └── syn feature \"default\" (*)\n   ├── syn feature \"proc-macro\"\n   │   └── syn feature \"default\" (*)\n   └── syn feature \"quote\"\n       ├── syn feature \"printing\" (*)\n       └── syn feature \"proc-macro\" (*)\n   ```\n\n   To read this graph, you can follow the chain for each feature from the root\n   to see why it is included. For example, the \"full\" feature is added by the\n   `rustversion` crate which is included from `myproject` (with the default\n   features), and `myproject` is the package selected on the command-line. All\n   of the other `syn` features are added by the \"default\" feature (\"quote\" is\n   added by \"printing\" and \"proc-macro\", both of which are default features).\n\n   If you're having difficulty cross-referencing the de-duplicated `(*)`\n   entries, try with the `--no-dedupe` flag to get the full output.\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-metadata\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-uninstall.md",
    "content": "# cargo-uninstall(1)\n\n## NAME\n\ncargo-uninstall --- Remove a Rust binary\n\n## SYNOPSIS\n\n`cargo uninstall` [_options_] [_spec_...]\n\n## DESCRIPTION\n\nThis command removes a package installed with {{man \"cargo-install\" 1}}. The _spec_\nargument is a package ID specification of the package to remove (see\n{{man \"cargo-pkgid\" 1}}).\n\nBy default all binaries are removed for a crate but the `--bin` and\n`--example` flags can be used to only remove particular binaries.\n\n{{> description-install-root }}\n\n## OPTIONS\n\n### Uninstall Options\n\n{{#options}}\n\n{{#option \"`-p`\" \"`--package` _spec_...\" }}\nPackage to uninstall.\n{{/option}}\n\n{{#option \"`--bin` _name_...\" }}\nOnly uninstall the binary _name_.\n{{/option}}\n\n{{#option \"`--root` _dir_\" }}\nDirectory to uninstall packages from.\n{{/option}}\n\n{{/options}}\n\n### Display Options\n\n{{#options}}\n\n{{> options-display }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Uninstall a previously installed package.\n\n       cargo uninstall ripgrep\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-install\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-update.md",
    "content": "# cargo-update(1)\n\n## NAME\n\ncargo-update --- Update dependencies as recorded in the local lock file\n\n## SYNOPSIS\n\n`cargo update` [_options_] _spec_\n\n## DESCRIPTION\n\nThis command will update dependencies in the `Cargo.lock` file to the latest\nversion. If the `Cargo.lock` file does not exist, it will be created with the\nlatest available versions.\n\n## OPTIONS\n\n### Update Options\n\n{{#options}}\n\n{{#option \"_spec_...\" }}\nUpdate only the specified packages. This flag may be specified\nmultiple times. See {{man \"cargo-pkgid\" 1}} for the SPEC format.\n\nIf packages are specified with _spec_, then a conservative update of\nthe lockfile will be performed. This means that only the dependency specified\nby SPEC will be updated. Its transitive dependencies will be updated only if\nSPEC cannot be updated without updating dependencies.  All other dependencies\nwill remain locked at their currently recorded versions.\n\nIf _spec_ is not specified, all dependencies are updated.\n{{/option}}\n\n{{#option \"`--recursive`\" }}\nWhen used with _spec_, dependencies of _spec_ are forced to update as well.\nCannot be used with `--precise`.\n{{/option}}\n\n{{#option \"`--precise` _precise_\" }}\nWhen used with _spec_, allows you to specify a specific version number to set\nthe package to. If the package comes from a git repository, this can be a git\nrevision (such as a SHA hash or tag).\n\nWhile not recommended, you can specify a yanked version of a package.\nWhen possible, try other non-yanked SemVer-compatible versions or seek help\nfrom the maintainers of the package.\n\nA compatible `pre-release` version can also be specified even when the version\nrequirement in `Cargo.toml` doesn't contain any pre-release identifier (nightly only).\n{{/option}}\n\n{{#option \"`--breaking` _directory_\" }}\nUpdate _spec_ to latest SemVer-breaking version.\n\nVersion requirements will be modified to allow this update.\n\nThis only applies to dependencies when\n- The package is a dependency of a workspace member\n- The dependency is not renamed\n- A SemVer-incompatible version is available\n- The \"SemVer operator\" is used (`^` which is the default)\n\nThis option is unstable and available only on the\n[nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)\nand requires the `-Z unstable-options` flag to enable.\nSee <https://github.com/rust-lang/cargo/issues/12425> for more information.\n{{/option}}\n\n{{#option \"`-w`\" \"`--workspace`\" }}\nAttempt to update only packages defined in the workspace. Other packages\nare updated only if they don't already exist in the lockfile. This\noption is useful for updating `Cargo.lock` after you've changed version\nnumbers in `Cargo.toml`.\n{{/option}}\n\n{{#option \"`--dry-run`\" }}\nDisplays what would be updated, but doesn't actually write the lockfile.\n{{/option}}\n\n{{/options}}\n\n### Display Options\n\n{{#options}}\n{{> options-display }}\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n\n{{> options-manifest-path }}\n\n{{> options-ignore-rust-version }}\n\n{{> options-locked }}\n\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Update all dependencies in the lockfile:\n\n       cargo update\n\n2. Update only specific dependencies:\n\n       cargo update foo bar\n\n3. Set a specific dependency to a specific version:\n\n       cargo update foo --precise 1.2.3\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-generate-lockfile\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-vendor.md",
    "content": "# cargo-vendor(1)\n\n## NAME\n\ncargo-vendor --- Vendor all dependencies locally\n\n## SYNOPSIS\n\n`cargo vendor` [_options_] [_path_]\n\n## DESCRIPTION\n\nThis cargo subcommand will vendor all crates.io and git dependencies for a\nproject into the specified directory at `<path>`. After this command completes\nthe vendor directory specified by `<path>` will contain all remote sources from\ndependencies specified. Additional manifests beyond the default one can be\nspecified with the `-s` option.\n\nThe configuration necessary to use the vendored sources would be printed to\nstdout after `cargo vendor` completes the vendoring process.\nYou will need to add or redirect it to your Cargo configuration file,\nwhich is usually `.cargo/config.toml` locally for the current package.\n\nCargo treats vendored sources as read-only as it does to registry and git sources.\nIf you intend to modify a crate from a remote source,\nuse `[patch]` or a `path` dependency pointing to a local copy of that crate.\nCargo will then correctly handle the crate on incremental rebuilds,\nas it knows that it is no longer a read-only dependency.\n\n## OPTIONS\n\n### Vendor Options\n\n{{#options}}\n\n{{#option \"`-s` _manifest_\" \"`--sync` _manifest_\" }}\nSpecify an extra `Cargo.toml` manifest to workspaces which should also be\nvendored and synced to the output. May be specified multiple times.\n{{/option}}\n\n{{#option \"`--no-delete`\" }}\nDon't delete the \"vendor\" directory when vendoring, but rather keep all\nexisting contents of the vendor directory\n{{/option}}\n\n{{#option \"`--respect-source-config`\" }}\nInstead of ignoring `[source]` configuration by default in `.cargo/config.toml`\nread it and use it when downloading crates from crates.io, for example\n{{/option}}\n\n{{#option \"`--versioned-dirs`\" }}\nNormally versions are only added to disambiguate multiple versions of the\nsame package. This option causes all directories in the \"vendor\" directory\nto be versioned, which makes it easier to track the history of vendored\npackages over time, and can help with the performance of re-vendoring when\nonly a subset of the packages have changed.\n{{/option}}\n\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n\n{{> options-manifest-path }}\n\n{{> options-locked }}\n\n\n{{/options}}\n\n### Display Options\n\n{{#options}}\n\n{{> options-display }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Vendor all dependencies into a local \"vendor\" folder\n\n       cargo vendor\n\n2. Vendor all dependencies into a local \"third-party/vendor\" folder\n\n       cargo vendor third-party/vendor\n\n3. Vendor the current workspace as well as another to \"vendor\"\n\n       cargo vendor -s ../path/to/Cargo.toml\n\n4. Vendor and redirect the necessary vendor configs to a config file.\n\n       cargo vendor > path/to/my/cargo/config.toml\n\n## SEE ALSO\n{{man \"cargo\" 1}}\n\n"
  },
  {
    "path": "src/doc/man/cargo-version.md",
    "content": "# cargo-version(1)\n\n## NAME\n\ncargo-version --- Show version information\n\n## SYNOPSIS\n\n`cargo version` [_options_]\n\n## DESCRIPTION\n\nDisplays the version of Cargo.\n\n## OPTIONS\n\n{{#options}}\n\n{{#option \"`-v`\" \"`--verbose`\" }}\nDisplay additional version information.\n{{/option}}\n\n{{/options}}\n\n## EXAMPLES\n\n1. Display the version:\n\n       cargo version\n\n2. The version is also available via flags:\n\n       cargo --version\n       cargo -V\n\n3. Display extra version information:\n\n       cargo -Vv\n\n## SEE ALSO\n{{man \"cargo\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo-yank.md",
    "content": "# cargo-yank(1)\n\n## NAME\n\ncargo-yank --- Remove a pushed crate from the index\n\n## SYNOPSIS\n\n`cargo yank` [_options_] _crate_@_version_\\\n`cargo yank` [_options_] `--version` _version_ [_crate_]\n\n## DESCRIPTION\n\nThe yank command removes a previously published crate's version from the\nserver's index. This command does not delete any data, and the crate will\nstill be available for download via the registry's download link.\n\nCargo will not use a yanked version for any new project or checkout without a\npre-existing lockfile, and will generate an error if there are no longer\nany compatible versions for your crate.\n\nThis command requires you to be authenticated with either the `--token` option\nor using {{man \"cargo-login\" 1}}.\n\nIf the crate name is not specified, it will use the package name from the\ncurrent directory.\n\n### How yank works\n\nFor example, the `foo` crate published version `1.5.0` and another crate `bar`\ndeclared a dependency on version `foo = \"1.5\"`. Now `foo` releases a new, but\nnot semver compatible, version `2.0.0`, and finds a critical issue with `1.5.0`.\nIf `1.5.0` is yanked, no new project or checkout without an existing lockfile\nwill be able to use crate `bar` as it relies on `1.5`.\n\nIn this case, the maintainers of `foo` should first publish a semver compatible\nversion such as `1.5.1` prior to yanking `1.5.0` so that `bar` and all projects\nthat depend on `bar` will continue to work.\n\nAs another example, consider a crate `bar` with published versions `1.5.0`,\n`1.5.1`, `1.5.2`, `2.0.0` and `3.0.0`. The following table identifies the\nversions cargo could use in the absence of a lockfile for different SemVer\nrequirements, following a given release being yanked:\n\n| Yanked Version / SemVer requirement | `bar = \"1.5.0\"`                         | `bar = \"=1.5.0\"` | `bar = \"2.0.0\"`  |\n|-------------------------------------|-----------------------------------------|------------------|------------------|\n| `1.5.0`                             | Use either `1.5.1` or `1.5.2`           | **Return Error** | Use `2.0.0`      |\n| `1.5.1`                             | Use either `1.5.0` or `1.5.2`           | Use `1.5.0`      | Use `2.0.0`      |\n| `2.0.0`                             | Use either `1.5.0`, `1.5.1` or `1.5.2`  | Use `1.5.0`      | **Return Error** |\n\n### When to yank\n\nCrates should only be yanked in exceptional circumstances, for example, an\naccidental publish, unintentional SemVer breakages, or a significantly\nbroken and unusable crate. In the case of security vulnerabilities, [RustSec]\nis typically a less disruptive mechanism to inform users and encourage them\nto upgrade, and avoids the possibility of significant downstream disruption\nirrespective of susceptibility to the vulnerability in question.\n\nA common workflow is to yank a crate having already published a semver\ncompatible version, to reduce the probability of preventing dependent\ncrates from compiling.\n\nWhen addressing copyright, licensing, or personal data issues with a published\ncrate, simply yanking it may not suffice. In such cases, contact the maintainers\nof the registry you used. For crates.io, refer to their [policies] and contact\nthem at <help@crates.io>.\n\nIf credentials have been leaked, the recommended course of action is to revoke\nthem immediately. Once a crate has been published, it is impossible to determine\nif the leaked credentials have been copied. Yanking only prevents Cargo from\nselecting this version when resolving dependencies by default. Existing lock\nfiles or direct downloads are not affected, so yanking cannot stop further\nspreading of the leaked credentials.\n\n[RustSec]: https://rustsec.org/\n[policies]: https://crates.io/policies\n\n## OPTIONS\n\n### Yank Options\n\n{{#options}}\n\n{{#option \"`--vers` _version_\" \"`--version` _version_\" }}\nThe version to yank or un-yank.\n{{/option}}\n\n{{#option \"`--undo`\" }}\nUndo a yank, putting a version back into the index.\n{{/option}}\n\n{{> options-token }}\n\n{{> options-index }}\n\n{{> options-registry }}\n\n{{/options}}\n\n### Display Options\n\n{{#options}}\n\n{{> options-display }}\n\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## EXAMPLES\n\n1. Yank a crate from the index:\n\n       cargo yank foo@1.0.7\n\n## SEE ALSO\n{{man \"cargo\" 1}}, {{man \"cargo-login\" 1}}, {{man \"cargo-publish\" 1}}\n"
  },
  {
    "path": "src/doc/man/cargo.md",
    "content": "# cargo(1)\n\n## NAME\n\ncargo --- The Rust package manager\n\n## SYNOPSIS\n\n`cargo` [_options_] _command_ [_args_]\\\n`cargo` [_options_] `--version`\\\n`cargo` [_options_] `--list`\\\n`cargo` [_options_] `--help`\\\n`cargo` [_options_] `--explain` _code_\n\n## DESCRIPTION\n\nThis program is a package manager and build tool for the Rust language,\navailable at <https://rust-lang.org>.\n\n_command_ may be one of:\n- built-in commands, see below\n- [aliases]\n- [external tools]\n\n[aliases]: ../reference/config.html#alias\n[external tools]: ../reference/external-tools.html#custom-subcommands\n\n## COMMANDS\n\n### Build Commands\n\n{{man \"cargo-bench\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Execute benchmarks of a package.\n\n{{man \"cargo-build\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Compile a package.\n\n{{man \"cargo-check\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Check a local package and all of its dependencies for errors.\n\n{{man \"cargo-clean\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Remove artifacts that Cargo has generated in the past.\n\n{{man \"cargo-doc\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Build a package's documentation.\n\n{{man \"cargo-fetch\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Fetch dependencies of a package from the network.\n\n{{man \"cargo-fix\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Automatically fix lint warnings reported by rustc.\n\n{{man \"cargo-run\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Run a binary or example of the local package.\n\n{{man \"cargo-rustc\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Compile a package, and pass extra options to the compiler.\n\n{{man \"cargo-rustdoc\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Build a package's documentation, using specified custom flags.\n\n{{man \"cargo-test\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Execute unit and integration tests of a package.\n\n### Manifest Commands\n\n{{man \"cargo-add\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Add dependencies to a `Cargo.toml` manifest file.\n\n{{man \"cargo-generate-lockfile\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Generate `Cargo.lock` for a project.\n\n{{man \"cargo-info\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Display information about a package in the registry. Default registry is crates.io.\n\n{{man \"cargo-locate-project\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Print a JSON representation of a `Cargo.toml` file's location.\n\n{{man \"cargo-metadata\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Output the resolved dependencies of a package in machine-readable format.\n\n{{man \"cargo-pkgid\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Print a fully qualified package specification.\n\n{{man \"cargo-remove\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Remove dependencies from a `Cargo.toml` manifest file.\n\n{{man \"cargo-tree\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Display a tree visualization of a dependency graph.\n\n{{man \"cargo-update\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Update dependencies as recorded in the local lock file.\n\n{{man \"cargo-vendor\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Vendor all dependencies locally.\n\n### Package Commands\n\n{{man \"cargo-init\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Create a new Cargo package in an existing directory.\n\n{{man \"cargo-install\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Build and install a Rust binary.\n\n{{man \"cargo-new\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Create a new Cargo package.\n\n{{man \"cargo-search\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Search packages in crates.io.\n\n{{man \"cargo-uninstall\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Remove a Rust binary.\n\n### Publishing Commands\n\n{{man \"cargo-login\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Save an API token from the registry locally.\n\n{{man \"cargo-logout\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Remove an API token from the registry locally.\n\n{{man \"cargo-owner\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Manage the owners of a crate on the registry.\n\n{{man \"cargo-package\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Assemble the local package into a distributable tarball.\n\n{{man \"cargo-publish\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Upload a package to the registry.\n\n{{man \"cargo-yank\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Remove a pushed crate from the index.\n\n### Report Commands\n\n{{man \"cargo-report\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Generate and display various kinds of reports.\n\n{{man \"cargo-report-future-incompatibilities\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Reports any crates which will eventually stop compiling.\n\n### General Commands\n\n{{man \"cargo-help\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Display help information about Cargo.\n\n{{man \"cargo-version\" 1}}\\\n&nbsp;&nbsp;&nbsp;&nbsp;Show version information.\n\n## OPTIONS\n\n### Special Options\n\n{{#options}}\n\n{{#option \"`-V`\" \"`--version`\" }}\nPrint version info and exit. If used with `--verbose`, prints extra\ninformation.\n{{/option}}\n\n{{#option \"`--list`\" }}\nList all installed Cargo subcommands. If used with `--verbose`, prints extra\ninformation.\n{{/option}}\n\n{{#option \"`--explain` _code_\" }}\nRun `rustc --explain CODE` which will print out a detailed explanation of an\nerror message (for example, `E0004`).\n{{/option}}\n\n{{/options}}\n\n### Display Options\n\n{{#options}}\n\n{{> options-display }}\n\n{{/options}}\n\n### Manifest Options\n\n{{#options}}\n{{> options-locked }}\n{{/options}}\n\n{{> section-options-common }}\n\n{{> section-environment }}\n\n{{> section-exit-status }}\n\n## FILES\n\n`~/.cargo/`\\\n&nbsp;&nbsp;&nbsp;&nbsp;Default location for Cargo's \"home\" directory where it\nstores various files. The location can be changed with the `CARGO_HOME`\nenvironment variable.\n\n`$CARGO_HOME/bin/`\\\n&nbsp;&nbsp;&nbsp;&nbsp;Binaries installed by {{man \"cargo-install\" 1}} will be located here. If using\n[rustup], executables distributed with Rust are also located here.\n\n`$CARGO_HOME/config.toml`\\\n&nbsp;&nbsp;&nbsp;&nbsp;The global configuration file. See [the reference](../reference/config.html)\nfor more information about configuration files.\n\n`.cargo/config.toml`\\\n&nbsp;&nbsp;&nbsp;&nbsp;Cargo automatically searches for a file named `.cargo/config.toml` in the\ncurrent directory, and all parent directories. These configuration files\nwill be merged with the global configuration file.\n\n`$CARGO_HOME/credentials.toml`\\\n&nbsp;&nbsp;&nbsp;&nbsp;Private authentication information for logging in to a registry.\n\n`$CARGO_HOME/registry/`\\\n&nbsp;&nbsp;&nbsp;&nbsp;This directory contains cached downloads of the registry index and any\ndownloaded dependencies.\n\n`$CARGO_HOME/git/`\\\n&nbsp;&nbsp;&nbsp;&nbsp;This directory contains cached downloads of git dependencies.\n\nPlease note that the internal structure of the `$CARGO_HOME` directory is not\nstable yet and may be subject to change.\n\n[rustup]: https://rust-lang.github.io/rustup/\n\n## EXAMPLES\n\n1. Build a local package and all of its dependencies:\n\n       cargo build\n\n2. Build a package with optimizations:\n\n       cargo build --release\n\n3. Run tests for a cross-compiled target:\n\n       cargo test --target i686-unknown-linux-gnu\n\n4. Create a new package that builds an executable:\n\n       cargo new foobar\n\n5. Create a package in the current directory:\n\n       mkdir foo && cd foo\n       cargo init .\n\n6. Learn about a command's options and usage:\n\n       cargo help clean\n\n## BUGS\n\nSee <https://github.com/rust-lang/cargo/issues> for issues.\n\n## SEE ALSO\n\n{{man \"rustc\" 1}}, {{man \"rustdoc\" 1}}\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-add.txt",
    "content": "CARGO-ADD(1)\n\nNAME\n       cargo-add — Add dependencies to a Cargo.toml manifest file\n\nSYNOPSIS\n       cargo add [options] crate…\n       cargo add [options] --path path\n       cargo add [options] --git url [crate…]\n\nDESCRIPTION\n       This command can add or modify dependencies.\n\n       The source for the dependency can be specified with:\n\n       o  crate@version: Fetch from a registry with a version constraint of\n          “version”\n\n       o  --path path: Fetch from the specified path\n\n       o  --git url: Pull from a git repo at url\n\n       If no source is specified, then a best effort will be made to select\n       one, including:\n\n       o  Existing dependencies in other tables (like dev-dependencies)\n\n       o  Workspace members\n\n       o  Latest release in the registry\n\n       When you add a package that is already present, the existing entry will\n       be updated with the flags specified.\n\n       Upon successful invocation, the enabled (+) and disabled (-) features\n       <https://doc.rust-lang.org/cargo/reference/features.html> of the\n       specified dependency will be listed in the command’s output.\n\nOPTIONS\n   Source options\n       --git url\n           Git URL to add the specified crate from\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories>.\n\n       --branch branch\n           Branch to use when adding from git.\n\n       --tag tag\n           Tag to use when adding from git.\n\n       --rev sha\n           Specific commit to use when adding from git.\n\n       --path path\n           Filesystem path\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-path-dependencies>\n           to local crate to add.\n\n       --base base\n           The path base\n           <https://doc.rust-lang.org/cargo/reference/unstable.html#path-bases>\n           to use when adding a local crate.\n\n           Unstable (nightly-only)\n           <https://doc.rust-lang.org/cargo/reference/unstable.html#path-bases>\n\n       --registry registry\n           Name of the registry to use. Registry names are defined in Cargo\n           config files\n           <https://doc.rust-lang.org/cargo/reference/config.html>. If not\n           specified, the default registry is used, which is defined by the\n           registry.default config key which defaults to crates-io.\n\n   Section options\n       --dev\n           Add as a development dependency\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#development-dependencies>.\n\n       --build\n           Add as a build dependency\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#build-dependencies>.\n\n       --target target\n           Add as a dependency to the given target platform\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies>.\n\n           To avoid unexpected shell expansions, you may use quotes around each\n           target, e.g., --target 'cfg(unix)'.\n\n   Dependency options\n       --dry-run\n           Don’t actually write the manifest\n\n       --rename name\n           Rename\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml>\n           the dependency.\n\n       --optional\n           Mark the dependency as optional\n           <https://doc.rust-lang.org/cargo/reference/features.html#optional-dependencies>.\n\n       --no-optional\n           Mark the dependency as required\n           <https://doc.rust-lang.org/cargo/reference/features.html#optional-dependencies>.\n\n       --public\n           Mark the dependency as public.\n\n           The dependency can be referenced in your library’s public API.\n\n           Unstable (nightly-only)\n           <https://doc.rust-lang.org/cargo/reference/unstable.html#public-dependency>\n\n       --no-public\n           Mark the dependency as private.\n\n           While you can use the crate in your implementation, it cannot be\n           referenced in your public API.\n\n           Unstable (nightly-only)\n           <https://doc.rust-lang.org/cargo/reference/unstable.html#public-dependency>\n\n       --no-default-features\n           Disable the default features\n           <https://doc.rust-lang.org/cargo/reference/features.html#dependency-features>.\n\n       --default-features\n           Re-enable the default features\n           <https://doc.rust-lang.org/cargo/reference/features.html#dependency-features>.\n\n       -F features, --features features\n           Space or comma separated list of features to activate\n           <https://doc.rust-lang.org/cargo/reference/features.html#dependency-features>.\n           When adding multiple crates, the features for a specific crate may\n           be enabled with package-name/feature-name syntax. This flag may be\n           specified multiple times, which enables all specified features.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       -p spec, --package spec\n           Add dependencies to only the specified package.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Add regex as a dependency\n\n              cargo add regex\n\n       2. Add trybuild as a dev-dependency\n\n              cargo add --dev trybuild\n\n       3. Add an older version of nom as a dependency\n\n              cargo add nom@5\n\n       4. Add support for serializing data structures to json with derives\n\n              cargo add serde serde_json -F serde/derive\n\n       5. Add windows as a platform specific dependency on cfg(windows)\n\n              cargo add windows --target 'cfg(windows)'\n\nSEE ALSO\n       cargo(1), cargo-remove(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-bench.txt",
    "content": "CARGO-BENCH(1)\n\nNAME\n       cargo-bench — Execute benchmarks of a package\n\nSYNOPSIS\n       cargo bench [options] [benchname] [-- bench-options]\n\nDESCRIPTION\n       Compile and execute benchmarks.\n\n       The benchmark filtering argument benchname and all the arguments\n       following the two dashes (--) are passed to the benchmark binaries and\n       thus to libtest (rustc’s built in unit-test and micro-benchmarking\n       framework). If you are passing arguments to both Cargo and the binary,\n       the ones after -- go to the binary, the ones before go to Cargo. For\n       details about libtest’s arguments see the output of cargo bench --\n       --help and check out the rustc book’s chapter on how tests work at\n       <https://doc.rust-lang.org/rustc/tests/index.html>.\n\n       As an example, this will run only the benchmark named foo (and skip\n       other similarly named benchmarks like foobar):\n\n           cargo bench -- foo --exact\n\n       Benchmarks are built with the --test option to rustc which creates a\n       special executable by linking your code with libtest. The executable\n       automatically runs all functions annotated with the #[bench] attribute.\n       Cargo passes the --bench flag to the test harness to tell it to run only\n       benchmarks, regardless of whether the harness is libtest or a custom\n       harness.\n\n       The libtest harness may be disabled by setting harness = false in the\n       target manifest settings, in which case your code will need to provide\n       its own main function to handle running benchmarks.\n\n          Note: The #[bench] attribute\n          <https://doc.rust-lang.org/nightly/unstable-book/library-features/test.html>\n          is currently unstable and only available on the nightly channel\n          <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html>. There\n          are some packages available on crates.io\n          <https://crates.io/keywords/benchmark> that may help with running\n          benchmarks on the stable channel, such as Criterion\n          <https://crates.io/crates/criterion>.\n\n       By default, cargo bench uses the bench profile\n       <https://doc.rust-lang.org/cargo/reference/profiles.html#bench>, which\n       enables optimizations and disables debugging information. If you need to\n       debug a benchmark, you can use the --profile=dev command-line option to\n       switch to the dev profile. You can then run the debug-enabled benchmark\n       within a debugger.\n\n   Working directory of benchmarks\n       The working directory of every benchmark is set to the root directory of\n       the package the benchmark belongs to. Setting the working directory of\n       benchmarks to the package’s root directory makes it possible for\n       benchmarks to reliably access the package’s files using relative\n       paths, regardless from where cargo bench was executed from.\n\nOPTIONS\n   Benchmark Options\n       --no-run\n           Compile, but don’t run benchmarks.\n\n       --no-fail-fast\n           Run all benchmarks regardless of failure. Without this flag, Cargo\n           will exit after the first executable fails. The Rust test harness\n           will run all benchmarks within the executable to completion, this\n           flag only applies to the executable as a whole.\n\n   Package Selection\n       By default, when no package selection options are given, the packages\n       selected depend on the selected manifest file (based on the current\n       working directory if --manifest-path is not given). If the manifest is\n       the root of a workspace then the workspaces default members are\n       selected, otherwise only the package defined by the manifest will be\n       selected.\n\n       The default members of a workspace can be set explicitly with the\n       workspace.default-members key in the root manifest. If this is not set,\n       a virtual workspace will include all workspace members (equivalent to\n       passing --workspace), and a non-virtual workspace will include only the\n       root crate itself.\n\n       -p spec…, --package spec…\n           Benchmark only the specified packages. See cargo-pkgid(1) for the\n           SPEC format. This flag may be specified multiple times and supports\n           common Unix glob patterns like *, ? and []. However, to avoid your\n           shell accidentally expanding glob patterns before Cargo handles\n           them, you must use single quotes or double quotes around each\n           pattern.\n\n       --workspace\n           Benchmark all members in the workspace.\n\n       --all\n           Deprecated alias for --workspace.\n\n       --exclude SPEC…\n           Exclude the specified packages. Must be used in conjunction with the\n           --workspace flag. This flag may be specified multiple times and\n           supports common Unix glob patterns like *, ? and []. However, to\n           avoid your shell accidentally expanding glob patterns before Cargo\n           handles them, you must use single quotes or double quotes around\n           each pattern.\n\n   Target Selection\n       When no target selection options are given, cargo bench will build the\n       following targets of the selected packages:\n\n       o  lib — used to link with binaries and benchmarks\n\n       o  bins (only if benchmark targets are built and required features are\n          available)\n\n       o  lib as a benchmark\n\n       o  bins as benchmarks\n\n       o  benchmark targets\n\n       The default behavior can be changed by setting the bench flag for the\n       target in the manifest settings. Setting examples to bench = true will\n       build and run the example as a benchmark, replacing the example’s main\n       function with the libtest harness.\n\n       Setting targets to bench = false will stop them from being benchmarked\n       by default. Target selection options that take a target by name (such as\n       --example foo) ignore the bench flag and will always benchmark the given\n       target.\n\n       See Configuring a target\n       <https://doc.rust-lang.org/cargo/reference/cargo-targets.html#configuring-a-target>\n       for more information on per-target settings.\n\n       Binary targets are automatically built if there is an integration test\n       or benchmark being selected to benchmark. This allows an integration\n       test to execute the binary to exercise and test its behavior. The\n       CARGO_BIN_EXE_<name> environment variable\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates>\n       is set when the integration test is built and run so that it can use the\n       env macro <https://doc.rust-lang.org/std/macro.env.html> or the var\n       function <https://doc.rust-lang.org/std/env/fn.var.html> to locate the\n       executable.\n\n       Passing target selection flags will benchmark only the specified\n       targets.\n\n       Note that --bin, --example, --test and --bench flags also support common\n       Unix glob patterns like *, ? and []. However, to avoid your shell\n       accidentally expanding glob patterns before Cargo handles them, you must\n       use single quotes or double quotes around each glob pattern.\n\n       --lib\n           Benchmark the package’s library.\n\n       --bin name…\n           Benchmark the specified binary. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --bins\n           Benchmark all binary targets.\n\n       --example name…\n           Benchmark the specified example. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --examples\n           Benchmark all example targets.\n\n       --test name…\n           Benchmark the specified integration test. This flag may be specified\n           multiple times and supports common Unix glob patterns.\n\n       --tests\n           Benchmark all targets that have the test = true manifest flag set.\n           By default this includes the library and binaries built as\n           unittests, and integration tests. Be aware that this will also build\n           any required dependencies, so the lib target may be built twice\n           (once as a unittest, and once as a dependency for binaries,\n           integration tests, etc.). Targets may be enabled or disabled by\n           setting the test flag in the manifest settings for the target.\n\n       --bench name…\n           Benchmark the specified benchmark. This flag may be specified\n           multiple times and supports common Unix glob patterns.\n\n       --benches\n           Benchmark all targets that have the bench = true manifest flag set.\n           By default this includes the library and binaries built as\n           benchmarks, and bench targets. Be aware that this will also build\n           any required dependencies, so the lib target may be built twice\n           (once as a benchmark, and once as a dependency for binaries,\n           benchmarks, etc.). Targets may be enabled or disabled by setting the\n           bench flag in the manifest settings for the target.\n\n       --all-targets\n           Benchmark all targets. This is equivalent to specifying --lib --bins\n           --tests --benches --examples.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Compilation Options\n       --target triple\n           Benchmark for the specified target architecture. Flag may be\n           specified multiple times. The default is the host architecture. The\n           general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       --profile name\n           Benchmark with the given profile. See the reference\n           <https://doc.rust-lang.org/cargo/reference/profiles.html> for more\n           details on profiles.\n\n       --timings\n           Output information how long each compilation takes, and track\n           concurrency information over time.\n\n           A file cargo-timing.html will be written to the target/cargo-timings\n           directory at the end of the build. An additional report with a\n           timestamp in its filename is also written if you want to look at a\n           previous run. These reports are suitable for human consumption only,\n           and do not provide machine-readable timing data.\n\n   Output Options\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n   Display Options\n       By default the Rust test harness hides output from benchmark execution\n       to keep results readable. Benchmark output can be recovered (e.g., for\n       debugging) by passing --no-capture to the benchmark binaries:\n\n           cargo bench -- --no-capture\n\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --message-format fmt\n           The output format for diagnostic messages. Can be specified multiple\n           times and consists of comma-separated values. Valid values:\n\n           o  human (default): Display in a human-readable text format.\n              Conflicts with short and json.\n\n           o  short: Emit shorter, human-readable text messages. Conflicts with\n              human and json.\n\n           o  json: Emit JSON messages to stdout. See the reference\n              <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n              for more details. Conflicts with human and short.\n\n           o  json-diagnostic-short: Ensure the rendered field of JSON messages\n              contains the “short” rendering from rustc. Cannot be used\n              with human or short.\n\n           o  json-diagnostic-rendered-ansi: Ensure the rendered field of JSON\n              messages contains embedded ANSI color codes for respecting\n              rustc’s default color scheme. Cannot be used with human or\n              short.\n\n           o  json-render-diagnostics: Instruct Cargo to not include rustc\n              diagnostics in JSON messages printed, but instead Cargo itself\n              should render the JSON diagnostics coming from rustc. Cargo’s\n              own JSON diagnostics and others coming from rustc are still\n              emitted. Cannot be used with human or short.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\n   Miscellaneous Options\n       The --jobs argument affects the building of the benchmark executable but\n       does not affect how many threads are used when running the benchmarks.\n       The Rust test harness runs benchmarks serially in a single thread.\n\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       While cargo bench involves compilation, it does not provide a\n       --keep-going flag. Use --no-fail-fast to run as many benchmarks as\n       possible without stopping at the first failure. To “compile” as many\n       benchmarks as possible, use --benches to build benchmark binaries\n       separately. For example:\n\n           cargo build --benches --release --keep-going\n           cargo bench --no-fail-fast\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Build and execute all the benchmarks of the current package:\n\n              cargo bench\n\n       2. Run only a specific benchmark within a specific benchmark target:\n\n              cargo bench --bench bench_name -- modname::some_benchmark\n\nSEE ALSO\n       cargo(1), cargo-test(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-build.txt",
    "content": "CARGO-BUILD(1)\n\nNAME\n       cargo-build — Compile the current package\n\nSYNOPSIS\n       cargo build [options]\n\nDESCRIPTION\n       Compile local packages and all of their dependencies.\n\nOPTIONS\n   Package Selection\n       By default, when no package selection options are given, the packages\n       selected depend on the selected manifest file (based on the current\n       working directory if --manifest-path is not given). If the manifest is\n       the root of a workspace then the workspaces default members are\n       selected, otherwise only the package defined by the manifest will be\n       selected.\n\n       The default members of a workspace can be set explicitly with the\n       workspace.default-members key in the root manifest. If this is not set,\n       a virtual workspace will include all workspace members (equivalent to\n       passing --workspace), and a non-virtual workspace will include only the\n       root crate itself.\n\n       -p spec…, --package spec…\n           Build only the specified packages. See cargo-pkgid(1) for the SPEC\n           format. This flag may be specified multiple times and supports\n           common Unix glob patterns like *, ? and []. However, to avoid your\n           shell accidentally expanding glob patterns before Cargo handles\n           them, you must use single quotes or double quotes around each\n           pattern.\n\n       --workspace\n           Build all members in the workspace.\n\n       --all\n           Deprecated alias for --workspace.\n\n       --exclude SPEC…\n           Exclude the specified packages. Must be used in conjunction with the\n           --workspace flag. This flag may be specified multiple times and\n           supports common Unix glob patterns like *, ? and []. However, to\n           avoid your shell accidentally expanding glob patterns before Cargo\n           handles them, you must use single quotes or double quotes around\n           each pattern.\n\n   Target Selection\n       When no target selection options are given, cargo build will build all\n       binary and library targets of the selected packages. Binaries are\n       skipped if they have required-features that are missing.\n\n       Binary targets are automatically built if there is an integration test\n       or benchmark being selected to build. This allows an integration test to\n       execute the binary to exercise and test its behavior. The\n       CARGO_BIN_EXE_<name> environment variable\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates>\n       is set when the integration test is built and run so that it can use the\n       env macro <https://doc.rust-lang.org/std/macro.env.html> or the var\n       function <https://doc.rust-lang.org/std/env/fn.var.html> to locate the\n       executable.\n\n       Passing target selection flags will build only the specified targets.\n\n       Note that --bin, --example, --test and --bench flags also support common\n       Unix glob patterns like *, ? and []. However, to avoid your shell\n       accidentally expanding glob patterns before Cargo handles them, you must\n       use single quotes or double quotes around each glob pattern.\n\n       --lib\n           Build the package’s library.\n\n       --bin name…\n           Build the specified binary. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --bins\n           Build all binary targets.\n\n       --example name…\n           Build the specified example. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --examples\n           Build all example targets.\n\n       --test name…\n           Build the specified integration test. This flag may be specified\n           multiple times and supports common Unix glob patterns.\n\n       --tests\n           Build all targets that have the test = true manifest flag set. By\n           default this includes the library and binaries built as unittests,\n           and integration tests. Be aware that this will also build any\n           required dependencies, so the lib target may be built twice (once as\n           a unittest, and once as a dependency for binaries, integration\n           tests, etc.). Targets may be enabled or disabled by setting the test\n           flag in the manifest settings for the target.\n\n       --bench name…\n           Build the specified benchmark. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --benches\n           Build all targets that have the bench = true manifest flag set. By\n           default this includes the library and binaries built as benchmarks,\n           and bench targets. Be aware that this will also build any required\n           dependencies, so the lib target may be built twice (once as a\n           benchmark, and once as a dependency for binaries, benchmarks, etc.).\n           Targets may be enabled or disabled by setting the bench flag in the\n           manifest settings for the target.\n\n       --all-targets\n           Build all targets. This is equivalent to specifying --lib --bins\n           --tests --benches --examples.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Compilation Options\n       --target triple\n           Build for the specified target architecture. Flag may be specified\n           multiple times. The default is the host architecture. The general\n           format of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       -r, --release\n           Build optimized artifacts with the release profile. See also the\n           --profile option for choosing a specific profile by name.\n\n       --profile name\n           Build with the given profile. See the reference\n           <https://doc.rust-lang.org/cargo/reference/profiles.html> for more\n           details on profiles.\n\n       --timings\n           Output information how long each compilation takes, and track\n           concurrency information over time.\n\n           A file cargo-timing.html will be written to the target/cargo-timings\n           directory at the end of the build. An additional report with a\n           timestamp in its filename is also written if you want to look at a\n           previous run. These reports are suitable for human consumption only,\n           and do not provide machine-readable timing data.\n\n   Output Options\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n       --artifact-dir directory\n           Copy final artifacts to this directory.\n\n           This option is unstable and available only on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable. See\n           <https://github.com/rust-lang/cargo/issues/6790> for more\n           information.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --message-format fmt\n           The output format for diagnostic messages. Can be specified multiple\n           times and consists of comma-separated values. Valid values:\n\n           o  human (default): Display in a human-readable text format.\n              Conflicts with short and json.\n\n           o  short: Emit shorter, human-readable text messages. Conflicts with\n              human and json.\n\n           o  json: Emit JSON messages to stdout. See the reference\n              <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n              for more details. Conflicts with human and short.\n\n           o  json-diagnostic-short: Ensure the rendered field of JSON messages\n              contains the “short” rendering from rustc. Cannot be used\n              with human or short.\n\n           o  json-diagnostic-rendered-ansi: Ensure the rendered field of JSON\n              messages contains embedded ANSI color codes for respecting\n              rustc’s default color scheme. Cannot be used with human or\n              short.\n\n           o  json-render-diagnostics: Instruct Cargo to not include rustc\n              diagnostics in JSON messages printed, but instead Cargo itself\n              should render the JSON diagnostics coming from rustc. Cargo’s\n              own JSON diagnostics and others coming from rustc are still\n              emitted. Cannot be used with human or short.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\n   Miscellaneous Options\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       --keep-going\n           Build as many crates in the dependency graph as possible, rather\n           than aborting the build on the first one that fails to build.\n\n           For example if the current package depends on dependencies fails and\n           works, one of which fails to build, cargo build -j1 may or may not\n           build the one that succeeds (depending on which one of the two\n           builds Cargo picked to run first), whereas cargo build -j1\n           --keep-going would definitely run both builds, even if the one run\n           first fails.\n\n       --future-incompat-report\n           Displays a future-incompat report for any future-incompatible\n           warnings produced during execution of this command\n\n           See cargo-report(1)\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Build the local package and all of its dependencies:\n\n              cargo build\n\n       2. Build with optimizations:\n\n              cargo build --release\n\nSEE ALSO\n       cargo(1), cargo-rustc(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-check.txt",
    "content": "CARGO-CHECK(1)\n\nNAME\n       cargo-check — Check the current package\n\nSYNOPSIS\n       cargo check [options]\n\nDESCRIPTION\n       Check a local package and all of its dependencies for errors. This will\n       essentially compile the packages without performing the final step of\n       code generation, which is faster than running cargo build. The compiler\n       will save metadata files to disk so that future runs will reuse them if\n       the source has not been modified. Some diagnostics and errors are only\n       emitted during code generation, so they inherently won’t be reported\n       with cargo check.\n\nOPTIONS\n   Package Selection\n       By default, when no package selection options are given, the packages\n       selected depend on the selected manifest file (based on the current\n       working directory if --manifest-path is not given). If the manifest is\n       the root of a workspace then the workspaces default members are\n       selected, otherwise only the package defined by the manifest will be\n       selected.\n\n       The default members of a workspace can be set explicitly with the\n       workspace.default-members key in the root manifest. If this is not set,\n       a virtual workspace will include all workspace members (equivalent to\n       passing --workspace), and a non-virtual workspace will include only the\n       root crate itself.\n\n       -p spec…, --package spec…\n           Check only the specified packages. See cargo-pkgid(1) for the SPEC\n           format. This flag may be specified multiple times and supports\n           common Unix glob patterns like *, ? and []. However, to avoid your\n           shell accidentally expanding glob patterns before Cargo handles\n           them, you must use single quotes or double quotes around each\n           pattern.\n\n       --workspace\n           Check all members in the workspace.\n\n       --all\n           Deprecated alias for --workspace.\n\n       --exclude SPEC…\n           Exclude the specified packages. Must be used in conjunction with the\n           --workspace flag. This flag may be specified multiple times and\n           supports common Unix glob patterns like *, ? and []. However, to\n           avoid your shell accidentally expanding glob patterns before Cargo\n           handles them, you must use single quotes or double quotes around\n           each pattern.\n\n   Target Selection\n       When no target selection options are given, cargo check will check all\n       binary and library targets of the selected packages. Binaries are\n       skipped if they have required-features that are missing.\n\n       Passing target selection flags will check only the specified targets.\n\n       Note that --bin, --example, --test and --bench flags also support common\n       Unix glob patterns like *, ? and []. However, to avoid your shell\n       accidentally expanding glob patterns before Cargo handles them, you must\n       use single quotes or double quotes around each glob pattern.\n\n       --lib\n           Check the package’s library.\n\n       --bin name…\n           Check the specified binary. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --bins\n           Check all binary targets.\n\n       --example name…\n           Check the specified example. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --examples\n           Check all example targets.\n\n       --test name…\n           Check the specified integration test. This flag may be specified\n           multiple times and supports common Unix glob patterns.\n\n       --tests\n           Check all targets that have the test = true manifest flag set. By\n           default this includes the library and binaries built as unittests,\n           and integration tests. Be aware that this will also build any\n           required dependencies, so the lib target may be built twice (once as\n           a unittest, and once as a dependency for binaries, integration\n           tests, etc.). Targets may be enabled or disabled by setting the test\n           flag in the manifest settings for the target.\n\n       --bench name…\n           Check the specified benchmark. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --benches\n           Check all targets that have the bench = true manifest flag set. By\n           default this includes the library and binaries built as benchmarks,\n           and bench targets. Be aware that this will also build any required\n           dependencies, so the lib target may be built twice (once as a\n           benchmark, and once as a dependency for binaries, benchmarks, etc.).\n           Targets may be enabled or disabled by setting the bench flag in the\n           manifest settings for the target.\n\n       --all-targets\n           Check all targets. This is equivalent to specifying --lib --bins\n           --tests --benches --examples.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Compilation Options\n       --target triple\n           Check for the specified target architecture. Flag may be specified\n           multiple times. The default is the host architecture. The general\n           format of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       -r, --release\n           Check optimized artifacts with the release profile. See also the\n           --profile option for choosing a specific profile by name.\n\n       --profile name\n           Check with the given profile.\n\n           As a special case, specifying the test profile will also enable\n           checking in test mode which will enable checking tests and enable\n           the test cfg option. See rustc tests\n           <https://doc.rust-lang.org/rustc/tests/index.html> for more detail.\n\n           See the reference\n           <https://doc.rust-lang.org/cargo/reference/profiles.html> for more\n           details on profiles.\n\n       --timings\n           Output information how long each compilation takes, and track\n           concurrency information over time.\n\n           A file cargo-timing.html will be written to the target/cargo-timings\n           directory at the end of the build. An additional report with a\n           timestamp in its filename is also written if you want to look at a\n           previous run. These reports are suitable for human consumption only,\n           and do not provide machine-readable timing data.\n\n   Output Options\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --message-format fmt\n           The output format for diagnostic messages. Can be specified multiple\n           times and consists of comma-separated values. Valid values:\n\n           o  human (default): Display in a human-readable text format.\n              Conflicts with short and json.\n\n           o  short: Emit shorter, human-readable text messages. Conflicts with\n              human and json.\n\n           o  json: Emit JSON messages to stdout. See the reference\n              <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n              for more details. Conflicts with human and short.\n\n           o  json-diagnostic-short: Ensure the rendered field of JSON messages\n              contains the “short” rendering from rustc. Cannot be used\n              with human or short.\n\n           o  json-diagnostic-rendered-ansi: Ensure the rendered field of JSON\n              messages contains embedded ANSI color codes for respecting\n              rustc’s default color scheme. Cannot be used with human or\n              short.\n\n           o  json-render-diagnostics: Instruct Cargo to not include rustc\n              diagnostics in JSON messages printed, but instead Cargo itself\n              should render the JSON diagnostics coming from rustc. Cargo’s\n              own JSON diagnostics and others coming from rustc are still\n              emitted. Cannot be used with human or short.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\n   Miscellaneous Options\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       --keep-going\n           Build as many crates in the dependency graph as possible, rather\n           than aborting the build on the first one that fails to build.\n\n           For example if the current package depends on dependencies fails and\n           works, one of which fails to build, cargo check -j1 may or may not\n           build the one that succeeds (depending on which one of the two\n           builds Cargo picked to run first), whereas cargo check -j1\n           --keep-going would definitely run both builds, even if the one run\n           first fails.\n\n       --future-incompat-report\n           Displays a future-incompat report for any future-incompatible\n           warnings produced during execution of this command\n\n           See cargo-report(1)\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Check the local package for errors:\n\n              cargo check\n\n       2. Check all targets, including unit tests:\n\n              cargo check --all-targets --profile=test\n\nSEE ALSO\n       cargo(1), cargo-build(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-clean.txt",
    "content": "CARGO-CLEAN(1)\n\nNAME\n       cargo-clean — Remove generated artifacts\n\nSYNOPSIS\n       cargo clean [options]\n\nDESCRIPTION\n       Remove artifacts from the target directory that Cargo has generated in\n       the past.\n\n       With no options, cargo clean will delete the entire target directory.\n\nOPTIONS\n   Package Selection\n       When no packages are selected, all packages and all dependencies in the\n       workspace are cleaned.\n\n       -p spec…, --package spec…\n           Clean only the specified packages. This flag may be specified\n           multiple times. See cargo-pkgid(1) for the SPEC format.\n\n       --workspace\n           Clean artifacts of the workspace members.\n\n   Clean Options\n       --dry-run\n           Displays a summary of what would be deleted without deleting\n           anything. Use with --verbose to display the actual files that would\n           be deleted.\n\n       --doc\n           This option will cause cargo clean to remove only the doc directory\n           in the target directory.\n\n       --release\n           Remove all artifacts in the release directory.\n\n       --profile name\n           Remove all artifacts in the directory with the given profile name.\n\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n       --target triple\n           Clean for the specified target architecture. Flag may be specified\n           multiple times. The default is the host architecture. The general\n           format of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Remove the entire target directory:\n\n              cargo clean\n\n       2. Remove only the release artifacts:\n\n              cargo clean --release\n\nSEE ALSO\n       cargo(1), cargo-build(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-doc.txt",
    "content": "CARGO-DOC(1)\n\nNAME\n       cargo-doc — Build a package’s documentation\n\nSYNOPSIS\n       cargo doc [options]\n\nDESCRIPTION\n       Build the documentation for the local package and all dependencies. The\n       output is placed in target/doc in rustdoc’s usual format.\n\n       Note: Documentation generation is cumulative: existing doc files in the\n       target directory are preserved across different cargo doc invocations.\n       To remove existing generated docs, pass --doc to cargo-clean(1).\n\nOPTIONS\n   Documentation Options\n       --open\n           Open the docs in a browser after building them. This will use your\n           default browser unless you define another one in the BROWSER\n           environment variable or use the doc.browser\n           <https://doc.rust-lang.org/cargo/reference/config.html#docbrowser>\n           configuration option.\n\n       --no-deps\n           Do not build documentation for dependencies.\n\n       --document-private-items\n           Include non-public items in the documentation. This will be enabled\n           by default if documenting a binary target.\n\n   Package Selection\n       By default, when no package selection options are given, the packages\n       selected depend on the selected manifest file (based on the current\n       working directory if --manifest-path is not given). If the manifest is\n       the root of a workspace then the workspaces default members are\n       selected, otherwise only the package defined by the manifest will be\n       selected.\n\n       The default members of a workspace can be set explicitly with the\n       workspace.default-members key in the root manifest. If this is not set,\n       a virtual workspace will include all workspace members (equivalent to\n       passing --workspace), and a non-virtual workspace will include only the\n       root crate itself.\n\n       -p spec…, --package spec…\n           Document only the specified packages. See cargo-pkgid(1) for the\n           SPEC format. This flag may be specified multiple times and supports\n           common Unix glob patterns like *, ? and []. However, to avoid your\n           shell accidentally expanding glob patterns before Cargo handles\n           them, you must use single quotes or double quotes around each\n           pattern.\n\n       --workspace\n           Document all members in the workspace.\n\n       --all\n           Deprecated alias for --workspace.\n\n       --exclude SPEC…\n           Exclude the specified packages. Must be used in conjunction with the\n           --workspace flag. This flag may be specified multiple times and\n           supports common Unix glob patterns like *, ? and []. However, to\n           avoid your shell accidentally expanding glob patterns before Cargo\n           handles them, you must use single quotes or double quotes around\n           each pattern.\n\n   Target Selection\n       When no target selection options are given, cargo doc will document all\n       binary and library targets of the selected package. The binary will be\n       skipped if its name is the same as the lib target. Binaries are skipped\n       if they have required-features that are missing.\n\n       The default behavior can be changed by setting doc = false for the\n       target in the manifest settings. Using target selection options will\n       ignore the doc flag and will always document the given target.\n\n       --lib\n           Document the package’s library.\n\n       --bin name…\n           Document the specified binary. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --bins\n           Document all binary targets.\n\n       --example name…\n           Document the specified example. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --examples\n           Document all example targets.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Compilation Options\n       --target triple\n           Document for the specified target architecture. Flag may be\n           specified multiple times. The default is the host architecture. The\n           general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       -r, --release\n           Document optimized artifacts with the release profile. See also the\n           --profile option for choosing a specific profile by name.\n\n       --profile name\n           Document with the given profile. See the reference\n           <https://doc.rust-lang.org/cargo/reference/profiles.html> for more\n           details on profiles.\n\n       --timings\n           Output information how long each compilation takes, and track\n           concurrency information over time.\n\n           A file cargo-timing.html will be written to the target/cargo-timings\n           directory at the end of the build. An additional report with a\n           timestamp in its filename is also written if you want to look at a\n           previous run. These reports are suitable for human consumption only,\n           and do not provide machine-readable timing data.\n\n   Output Options\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --message-format fmt\n           The output format for diagnostic messages. Can be specified multiple\n           times and consists of comma-separated values. Valid values:\n\n           o  human (default): Display in a human-readable text format.\n              Conflicts with short and json.\n\n           o  short: Emit shorter, human-readable text messages. Conflicts with\n              human and json.\n\n           o  json: Emit JSON messages to stdout. See the reference\n              <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n              for more details. Conflicts with human and short.\n\n           o  json-diagnostic-short: Ensure the rendered field of JSON messages\n              contains the “short” rendering from rustc. Cannot be used\n              with human or short.\n\n           o  json-diagnostic-rendered-ansi: Ensure the rendered field of JSON\n              messages contains embedded ANSI color codes for respecting\n              rustc’s default color scheme. Cannot be used with human or\n              short.\n\n           o  json-render-diagnostics: Instruct Cargo to not include rustc\n              diagnostics in JSON messages printed, but instead Cargo itself\n              should render the JSON diagnostics coming from rustc. Cargo’s\n              own JSON diagnostics and others coming from rustc are still\n              emitted. Cannot be used with human or short.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\n   Miscellaneous Options\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       --keep-going\n           Build as many crates in the dependency graph as possible, rather\n           than aborting the build on the first one that fails to build.\n\n           For example if the current package depends on dependencies fails and\n           works, one of which fails to build, cargo doc -j1 may or may not\n           build the one that succeeds (depending on which one of the two\n           builds Cargo picked to run first), whereas cargo doc -j1\n           --keep-going would definitely run both builds, even if the one run\n           first fails.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Build the local package documentation and its dependencies and output\n          to target/doc.\n\n              cargo doc\n\nSEE ALSO\n       cargo(1), cargo-rustdoc(1), rustdoc(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-fetch.txt",
    "content": "CARGO-FETCH(1)\n\nNAME\n       cargo-fetch — Fetch dependencies of a package from the network\n\nSYNOPSIS\n       cargo fetch [options]\n\nDESCRIPTION\n       If a Cargo.lock file is available, this command will ensure that all of\n       the git dependencies and/or registry dependencies are downloaded and\n       locally available. Subsequent Cargo commands will be able to run offline\n       after a cargo fetch unless the lock file changes.\n\n       If the lock file is not available, then this command will generate the\n       lock file before fetching the dependencies.\n\n       If --target is not specified, then all target dependencies are fetched.\n\n       See also the cargo-prefetch <https://crates.io/crates/cargo-prefetch>\n       plugin which adds a command to download popular crates. This may be\n       useful if you plan to use Cargo without a network with the --offline\n       flag.\n\nOPTIONS\n   Fetch options\n       --target triple\n           Fetch for the specified target architecture. Flag may be specified\n           multiple times. The default is all architectures. The general format\n           of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Fetch all dependencies:\n\n              cargo fetch\n\nSEE ALSO\n       cargo(1), cargo-update(1), cargo-generate-lockfile(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-fix.txt",
    "content": "CARGO-FIX(1)\n\nNAME\n       cargo-fix — Automatically fix lint warnings reported by rustc\n\nSYNOPSIS\n       cargo fix [options]\n\nDESCRIPTION\n       This Cargo subcommand will automatically take rustc’s suggestions from\n       diagnostics like warnings and apply them to your source code. This is\n       intended to help automate tasks that rustc itself already knows how to\n       tell you to fix!\n\n       Executing cargo fix will under the hood execute cargo-check(1). Any\n       warnings applicable to your crate will be automatically fixed (if\n       possible) and all remaining warnings will be displayed when the check\n       process is finished. For example if you’d like to apply all fixes to\n       the current package, you can run:\n\n           cargo fix\n\n       which behaves the same as cargo check --all-targets.\n\n       cargo fix is only capable of fixing code that is normally compiled with\n       cargo check. If code is conditionally enabled with optional features,\n       you will need to enable those features for that code to be analyzed:\n\n           cargo fix --features foo\n\n       Similarly, other cfg expressions like platform-specific code will need\n       to pass --target to fix code for the given target.\n\n           cargo fix --target x86_64-pc-windows-gnu\n\n       If you encounter any problems with cargo fix or otherwise have any\n       questions or feature requests please don’t hesitate to file an issue\n       at <https://github.com/rust-lang/cargo>.\n\n   Edition migration\n       The cargo fix subcommand can also be used to migrate a package from one\n       edition\n       <https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html>\n       to the next. The general procedure is:\n\n       1. Run cargo fix --edition. Consider also using the --all-features flag\n          if your project has multiple features. You may also want to run cargo\n          fix --edition multiple times with different --target flags if your\n          project has platform-specific code gated by cfg attributes.\n\n       2. Modify Cargo.toml to set the edition field\n          <https://doc.rust-lang.org/cargo/reference/manifest.html#the-edition-field>\n          to the new edition.\n\n       3. Run your project tests to verify that everything still works. If new\n          warnings are issued, you may want to consider running cargo fix again\n          (without the --edition flag) to apply any suggestions given by the\n          compiler.\n\n       And hopefully that’s it! Just keep in mind of the caveats mentioned\n       above that cargo fix cannot update code for inactive features or cfg\n       expressions. Also, in some rare cases the compiler is unable to\n       automatically migrate all code to the new edition, and this may require\n       manual changes after building with the new edition.\n\nOPTIONS\n   Fix options\n       --broken-code\n           Fix code even if it already has compiler errors. This is useful if\n           cargo fix fails to apply the changes. It will apply the changes and\n           leave the broken code in the working directory for you to inspect\n           and manually fix.\n\n       --edition\n           Apply changes that will update the code to the next edition. This\n           will not update the edition in the Cargo.toml manifest, which must\n           be updated manually after cargo fix --edition has finished.\n\n       --edition-idioms\n           Apply suggestions that will update code to the preferred style for\n           the current edition.\n\n       --allow-no-vcs\n           Fix code even if a VCS was not detected.\n\n       --allow-dirty\n           Fix code even if the working directory has changes (including staged\n           changes).\n\n       --allow-staged\n           Fix code even if the working directory has staged changes.\n\n   Package Selection\n       By default, when no package selection options are given, the packages\n       selected depend on the selected manifest file (based on the current\n       working directory if --manifest-path is not given). If the manifest is\n       the root of a workspace then the workspaces default members are\n       selected, otherwise only the package defined by the manifest will be\n       selected.\n\n       The default members of a workspace can be set explicitly with the\n       workspace.default-members key in the root manifest. If this is not set,\n       a virtual workspace will include all workspace members (equivalent to\n       passing --workspace), and a non-virtual workspace will include only the\n       root crate itself.\n\n       -p spec…, --package spec…\n           Fix only the specified packages. See cargo-pkgid(1) for the SPEC\n           format. This flag may be specified multiple times and supports\n           common Unix glob patterns like *, ? and []. However, to avoid your\n           shell accidentally expanding glob patterns before Cargo handles\n           them, you must use single quotes or double quotes around each\n           pattern.\n\n       --workspace\n           Fix all members in the workspace.\n\n       --all\n           Deprecated alias for --workspace.\n\n       --exclude SPEC…\n           Exclude the specified packages. Must be used in conjunction with the\n           --workspace flag. This flag may be specified multiple times and\n           supports common Unix glob patterns like *, ? and []. However, to\n           avoid your shell accidentally expanding glob patterns before Cargo\n           handles them, you must use single quotes or double quotes around\n           each pattern.\n\n   Target Selection\n       When no target selection options are given, cargo fix will fix all\n       targets (--all-targets implied). Binaries are skipped if they have\n       required-features that are missing.\n\n       Passing target selection flags will fix only the specified targets.\n\n       Note that --bin, --example, --test and --bench flags also support common\n       Unix glob patterns like *, ? and []. However, to avoid your shell\n       accidentally expanding glob patterns before Cargo handles them, you must\n       use single quotes or double quotes around each glob pattern.\n\n       --lib\n           Fix the package’s library.\n\n       --bin name…\n           Fix the specified binary. This flag may be specified multiple times\n           and supports common Unix glob patterns.\n\n       --bins\n           Fix all binary targets.\n\n       --example name…\n           Fix the specified example. This flag may be specified multiple times\n           and supports common Unix glob patterns.\n\n       --examples\n           Fix all example targets.\n\n       --test name…\n           Fix the specified integration test. This flag may be specified\n           multiple times and supports common Unix glob patterns.\n\n       --tests\n           Fix all targets that have the test = true manifest flag set. By\n           default this includes the library and binaries built as unittests,\n           and integration tests. Be aware that this will also build any\n           required dependencies, so the lib target may be built twice (once as\n           a unittest, and once as a dependency for binaries, integration\n           tests, etc.). Targets may be enabled or disabled by setting the test\n           flag in the manifest settings for the target.\n\n       --bench name…\n           Fix the specified benchmark. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --benches\n           Fix all targets that have the bench = true manifest flag set. By\n           default this includes the library and binaries built as benchmarks,\n           and bench targets. Be aware that this will also build any required\n           dependencies, so the lib target may be built twice (once as a\n           benchmark, and once as a dependency for binaries, benchmarks, etc.).\n           Targets may be enabled or disabled by setting the bench flag in the\n           manifest settings for the target.\n\n       --all-targets\n           Fix all targets. This is equivalent to specifying --lib --bins\n           --tests --benches --examples.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Compilation Options\n       --target triple\n           Fix for the specified target architecture. Flag may be specified\n           multiple times. The default is the host architecture. The general\n           format of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       -r, --release\n           Fix optimized artifacts with the release profile. See also the\n           --profile option for choosing a specific profile by name.\n\n       --profile name\n           Fix with the given profile.\n\n           As a special case, specifying the test profile will also enable\n           checking in test mode which will enable checking tests and enable\n           the test cfg option. See rustc tests\n           <https://doc.rust-lang.org/rustc/tests/index.html> for more detail.\n\n           See the reference\n           <https://doc.rust-lang.org/cargo/reference/profiles.html> for more\n           details on profiles.\n\n       --timings\n           Output information how long each compilation takes, and track\n           concurrency information over time.\n\n           A file cargo-timing.html will be written to the target/cargo-timings\n           directory at the end of the build. An additional report with a\n           timestamp in its filename is also written if you want to look at a\n           previous run. These reports are suitable for human consumption only,\n           and do not provide machine-readable timing data.\n\n   Output Options\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --message-format fmt\n           The output format for diagnostic messages. Can be specified multiple\n           times and consists of comma-separated values. Valid values:\n\n           o  human (default): Display in a human-readable text format.\n              Conflicts with short and json.\n\n           o  short: Emit shorter, human-readable text messages. Conflicts with\n              human and json.\n\n           o  json: Emit JSON messages to stdout. See the reference\n              <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n              for more details. Conflicts with human and short.\n\n           o  json-diagnostic-short: Ensure the rendered field of JSON messages\n              contains the “short” rendering from rustc. Cannot be used\n              with human or short.\n\n           o  json-diagnostic-rendered-ansi: Ensure the rendered field of JSON\n              messages contains embedded ANSI color codes for respecting\n              rustc’s default color scheme. Cannot be used with human or\n              short.\n\n           o  json-render-diagnostics: Instruct Cargo to not include rustc\n              diagnostics in JSON messages printed, but instead Cargo itself\n              should render the JSON diagnostics coming from rustc. Cargo’s\n              own JSON diagnostics and others coming from rustc are still\n              emitted. Cannot be used with human or short.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\n   Miscellaneous Options\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       --keep-going\n           Build as many crates in the dependency graph as possible, rather\n           than aborting the build on the first one that fails to build.\n\n           For example if the current package depends on dependencies fails and\n           works, one of which fails to build, cargo fix -j1 may or may not\n           build the one that succeeds (depending on which one of the two\n           builds Cargo picked to run first), whereas cargo fix -j1\n           --keep-going would definitely run both builds, even if the one run\n           first fails.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Apply compiler suggestions to the local package:\n\n              cargo fix\n\n       2. Update a package to prepare it for the next edition:\n\n              cargo fix --edition\n\n       3. Apply suggested idioms for the current edition:\n\n              cargo fix --edition-idioms\n\nSEE ALSO\n       cargo(1), cargo-check(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-generate-lockfile.txt",
    "content": "CARGO-GENERATE-LOCKFILE(1)\n\nNAME\n       cargo-generate-lockfile — Generate the lockfile for a package\n\nSYNOPSIS\n       cargo generate-lockfile [options]\n\nDESCRIPTION\n       This command will create the Cargo.lock lockfile for the current package\n       or workspace. If the lockfile already exists, it will be rebuilt with\n       the latest available version of every package.\n\n       See also cargo-update(1) which is also capable of creating a Cargo.lock\n       lockfile and has more options for controlling update behavior.\n\nOPTIONS\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --publish-time yyyy-mm-ddThh:mm:ssZ\n           Latest publish time allowed for registry packages (Unstable)\n\n           This is a best-effort filter on allowed packages, including:\n\n           o  packages from unsupported registries are always accepted\n\n           o  only the current yank state is respected, not the state as of\n              --publish-time\n\n           o  precision of the publish time\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Create or update the lockfile for the current package or workspace:\n\n              cargo generate-lockfile\n\nSEE ALSO\n       cargo(1), cargo-update(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-help.txt",
    "content": "CARGO-HELP(1)\n\nNAME\n       cargo-help — Get help for a Cargo command\n\nSYNOPSIS\n       cargo help [subcommand]\n\nDESCRIPTION\n       Prints a help message for the given command.\n\n       For commands with subcommands, separate the command levels with spaces.\n       For example, cargo help report future-incompatibilities displays help\n       for the cargo report future-incompatibilities command.\n\n       Spaces separate hierarchy levels only between a parent command and its\n       subcommands. Dashes that are part of a command’s name, such as\n       generate-lockfile, must always be preserved.\n\n       Multiple command levels can also be written as a single dash-joined\n       word. For example, cargo help report-future-incompatibilities is\n       equivalent to cargo help report future-incompatibilities.\n\nOPTIONS\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Get help for a command:\n\n              cargo help build\n\n       2. Get help for a nested command:\n\n              cargo help report future-incompatibilities\n\n       3. The dash-joined form also works:\n\n              cargo help report-future-incompatibilities\n\n       4. Help is also available with the --help flag:\n\n              cargo build --help\n\nSEE ALSO\n       cargo(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-info.txt",
    "content": "CARGO-INFO(1)\n\nNAME\n       cargo-info — Display information about a package.\n\nSYNOPSIS\n       cargo info [options] spec\n\nDESCRIPTION\n       This command displays information about a package. It fetches data from\n       the package’s Cargo.toml file and presents it in a human-readable\n       format.\n\nOPTIONS\n   Info Options\n       spec\n           Fetch information about the specified package. The spec can be a\n           package ID, see cargo-pkgid(1) for the SPEC format. If the specified\n           package is part of the current workspace, information from the local\n           Cargo.toml file will be displayed. If the Cargo.lock file does not\n           exist, it will be created. If no version is specified, the\n           appropriate version will be selected based on the Minimum Supported\n           Rust Version (MSRV).\n\n       --index index\n           The URL of the registry index to use.\n\n       --registry registry\n           Name of the registry to use. Registry names are defined in Cargo\n           config files\n           <https://doc.rust-lang.org/cargo/reference/config.html>. If not\n           specified, the default registry is used, which is defined by the\n           registry.default config key which defaults to crates-io.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Inspect the serde package from crates.io:\n\n               cargo info serde\n\n       2. Inspect the serde package with version 1.0.0:\n\n               cargo info serde@1.0.0\n\n       3. Inspect the serde package form the local registry:\n\n               cargo info serde --registry my-registry\n\nSEE ALSO\n       cargo(1), cargo-search(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-init.txt",
    "content": "CARGO-INIT(1)\n\nNAME\n       cargo-init — Create a new Cargo package in an existing directory\n\nSYNOPSIS\n       cargo init [options] [path]\n\nDESCRIPTION\n       This command will create a new Cargo manifest in the current directory.\n       Give a path as an argument to create in the given directory.\n\n       If there are typically-named Rust source files already in the directory,\n       those will be used. If not, then a sample src/main.rs file will be\n       created, or src/lib.rs if --lib is passed.\n\n       If the directory is not already in a VCS repository, then a new\n       repository is created (see --vcs below).\n\n       See cargo-new(1) for a similar command which will create a new package\n       in a new directory.\n\nOPTIONS\n   Init Options\n       --bin\n           Create a package with a binary target (src/main.rs). This is the\n           default behavior.\n\n       --lib\n           Create a package with a library target (src/lib.rs).\n\n       --edition edition\n           Specify the Rust edition to use. Default is 2024. Possible values:\n           2015, 2018, 2021, 2024\n\n       --name name\n           Set the package name. Defaults to the directory name.\n\n       --vcs vcs\n           Initialize a new VCS repository for the given version control system\n           (git, hg, pijul, or fossil) or do not initialize any version control\n           at all (none). If not specified, defaults to git or the\n           configuration value cargo-new.vcs, or none if already inside a VCS\n           repository.\n\n       --registry registry\n           This sets the publish field in Cargo.toml to the given registry name\n           which will restrict publishing only to that registry.\n\n           Registry names are defined in Cargo config files\n           <https://doc.rust-lang.org/cargo/reference/config.html>. If not\n           specified, the default registry defined by the registry.default\n           config key is used. If the default registry is not set and\n           --registry is not used, the publish field will not be set which\n           means that publishing will not be restricted.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Create a binary Cargo package in the current directory:\n\n              cargo init\n\nSEE ALSO\n       cargo(1), cargo-new(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-install.txt",
    "content": "CARGO-INSTALL(1)\n\nNAME\n       cargo-install — Build and install a Rust binary\n\nSYNOPSIS\n       cargo install [options] crate[@version]…\n       cargo install [options] --path path\n       cargo install [options] --git url [crate…]\n       cargo install [options] --list\n\nDESCRIPTION\n       This command manages Cargo’s local set of installed binary crates.\n       Only packages which have executable [[bin]] or [[example]] targets can\n       be installed, and all executables are installed into the installation\n       root’s bin folder. By default only binaries, not examples, are\n       installed.\n\n       The installation root is determined, in order of precedence:\n\n       o  --root option\n\n       o  CARGO_INSTALL_ROOT environment variable\n\n       o  install.root Cargo config value\n          <https://doc.rust-lang.org/cargo/reference/config.html>\n\n       o  CARGO_HOME environment variable\n\n       o  $HOME/.cargo\n\n       There are multiple sources from which a crate can be installed. The\n       default source location is crates.io but the --git, --path, and\n       --registry flags can change this source. If the source contains more\n       than one package (such as crates.io or a git repository with multiple\n       crates) the crate argument is required to indicate which crate should be\n       installed.\n\n       Crates from crates.io can optionally specify the version they wish to\n       install via the --version flags, and similarly packages from git\n       repositories can optionally specify the branch, tag, or revision that\n       should be installed. If a crate has multiple binaries, the --bin\n       argument can selectively install only one of them, and if you’d rather\n       install examples the --example argument can be used as well.\n\n       If the package is already installed, Cargo will reinstall it if the\n       installed version does not appear to be up-to-date. If any of the\n       following values change, then Cargo will reinstall the package:\n\n       o  The package version and source.\n\n       o  The set of binary names installed.\n\n       o  The chosen features.\n\n       o  The profile (--profile).\n\n       o  The target (--target).\n\n       Installing with --path will always build and install, unless there are\n       conflicting binaries from another package. The --force flag may be used\n       to force Cargo to always reinstall the package.\n\n       If the source is crates.io or --git then by default the crate will be\n       built in a temporary target directory. To avoid this, the target\n       directory can be specified by setting the CARGO_TARGET_DIR environment\n       variable to a path. In particular, this can be useful for caching build\n       artifacts on continuous integration systems.\n\n   Dealing with the Lockfile\n       By default, the Cargo.lock file that is included with the package will\n       be ignored. This means that Cargo will recompute which versions of\n       dependencies to use, possibly using newer versions that have been\n       released since the package was published. The --locked flag can be used\n       to force Cargo to use the packaged Cargo.lock file if it is available.\n       This may be useful for ensuring reproducible builds, to use the exact\n       same set of dependencies that were available when the package was\n       published. It may also be useful if a newer version of a dependency is\n       published that no longer builds on your system, or has other problems.\n       The downside to using --locked is that you will not receive any fixes or\n       updates to any dependency. Note that Cargo did not start publishing\n       Cargo.lock files until version 1.37, which means packages published with\n       prior versions will not have a Cargo.lock file available.\n\n   Configuration Discovery\n       This command operates on system or user level, not project level. This\n       means that the local configuration discovery\n       <https://doc.rust-lang.org/cargo/reference/config.html#hierarchical-structure>\n       is ignored. Instead, the configuration discovery begins at\n       $CARGO_HOME/config.toml. If the package is installed with --path $PATH,\n       the local configuration will be used, beginning discovery at\n       $PATH/.cargo/config.toml.\n\nOPTIONS\n   Install Options\n       --vers version, --version version\n           Specify a version to install. This may be a version requirement\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html>,\n           like ~1.2, to have Cargo select the newest version from the given\n           requirement. If the version does not have a requirement operator\n           (such as ^ or ~), then it must be in the form MAJOR.MINOR.PATCH, and\n           will install exactly that version; it is not treated as a caret\n           requirement like Cargo dependencies are.\n\n       --git url\n           Git URL to install the specified crate from.\n\n       --branch branch\n           Branch to use when installing from git.\n\n       --tag tag\n           Tag to use when installing from git.\n\n       --rev sha\n           Specific commit to use when installing from git.\n\n       --path path\n           Filesystem path to local crate to install from.\n\n       --list\n           List all installed packages and their versions.\n\n       -n, --dry-run\n           (unstable) Perform all checks without installing.\n\n       -f, --force\n           Force overwriting existing crates or binaries. This can be used if a\n           package has installed a binary with the same name as another\n           package. This is also useful if something has changed on the system\n           that you want to rebuild with, such as a newer version of rustc.\n\n       --no-track\n           By default, Cargo keeps track of the installed packages with a\n           metadata file stored in the installation root directory. This flag\n           tells Cargo not to use or create that file. With this flag, Cargo\n           will refuse to overwrite any existing files unless the --force flag\n           is used. This also disables Cargo’s ability to protect against\n           multiple concurrent invocations of Cargo installing at the same\n           time.\n\n       --bin name…\n           Install only the specified binary.\n\n       --bins\n           Install all binaries. This is the default behavior.\n\n       --example name…\n           Install only the specified example.\n\n       --examples\n           Install all examples.\n\n       --root dir\n           Directory to install packages into.\n\n       --registry registry\n           Name of the registry to use. Registry names are defined in Cargo\n           config files\n           <https://doc.rust-lang.org/cargo/reference/config.html>. If not\n           specified, the default registry is used, which is defined by the\n           registry.default config key which defaults to crates-io.\n\n       --index index\n           The URL of the registry index to use.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Compilation Options\n       --target triple\n           Install for the specified target architecture. The default is the\n           host architecture. The general format of the triple is\n           <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           a new temporary folder located in the temporary directory of the\n           platform.\n\n           When using --path, by default it will use target directory in the\n           workspace of the local crate unless --target-dir is specified.\n\n       --debug\n           Build with the dev profile instead of the release profile. See also\n           the --profile option for choosing a specific profile by name.\n\n       --profile name\n           Install with the given profile. See the reference\n           <https://doc.rust-lang.org/cargo/reference/profiles.html> for more\n           details on profiles.\n\n       --timings\n           Output information how long each compilation takes, and track\n           concurrency information over time.\n\n           A file cargo-timing.html will be written to the target/cargo-timings\n           directory at the end of the build. An additional report with a\n           timestamp in its filename is also written if you want to look at a\n           previous run. These reports are suitable for human consumption only,\n           and do not provide machine-readable timing data.\n\n   Manifest Options\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Miscellaneous Options\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       --keep-going\n           Build as many crates in the dependency graph as possible, rather\n           than aborting the build on the first one that fails to build.\n\n           For example if the current package depends on dependencies fails and\n           works, one of which fails to build, cargo install -j1 may or may not\n           build the one that succeeds (depending on which one of the two\n           builds Cargo picked to run first), whereas cargo install -j1\n           --keep-going would definitely run both builds, even if the one run\n           first fails.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --message-format fmt\n           The output format for diagnostic messages. Can be specified multiple\n           times and consists of comma-separated values. Valid values:\n\n           o  human (default): Display in a human-readable text format.\n              Conflicts with short and json.\n\n           o  short: Emit shorter, human-readable text messages. Conflicts with\n              human and json.\n\n           o  json: Emit JSON messages to stdout. See the reference\n              <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n              for more details. Conflicts with human and short.\n\n           o  json-diagnostic-short: Ensure the rendered field of JSON messages\n              contains the “short” rendering from rustc. Cannot be used\n              with human or short.\n\n           o  json-diagnostic-rendered-ansi: Ensure the rendered field of JSON\n              messages contains embedded ANSI color codes for respecting\n              rustc’s default color scheme. Cannot be used with human or\n              short.\n\n           o  json-render-diagnostics: Instruct Cargo to not include rustc\n              diagnostics in JSON messages printed, but instead Cargo itself\n              should render the JSON diagnostics coming from rustc. Cargo’s\n              own JSON diagnostics and others coming from rustc are still\n              emitted. Cannot be used with human or short.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Install or upgrade a package from crates.io:\n\n              cargo install ripgrep\n\n       2. Install or reinstall the package in the current directory:\n\n              cargo install --path .\n\n       3. View the list of installed packages:\n\n              cargo install --list\n\nSEE ALSO\n       cargo(1), cargo-uninstall(1), cargo-search(1), cargo-publish(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-locate-project.txt",
    "content": "CARGO-LOCATE-PROJECT(1)\n\nNAME\n       cargo-locate-project — Print a JSON representation of a Cargo.toml\n       file’s location\n\nSYNOPSIS\n       cargo locate-project [options]\n\nDESCRIPTION\n       This command will print a JSON object to stdout with the full path to\n       the manifest. The manifest is found by searching upward for a file named\n       Cargo.toml starting from the current working directory.\n\n       If the project happens to be a part of a workspace, the manifest of the\n       project, rather than the workspace root, is output. This can be\n       overridden by the --workspace flag. The root workspace is found by\n       traversing further upward or by using the field package.workspace after\n       locating the manifest of a workspace member.\n\nOPTIONS\n       --workspace\n           Locate the Cargo.toml at the root of the workspace, as opposed to\n           the current workspace member.\n\n   Display Options\n       --message-format fmt\n           The representation in which to print the project location. Valid\n           values:\n\n           o  json (default): JSON object with the path under the key\n              “root”.\n\n           o  plain: Just the path.\n\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Display the path to the manifest based on the current directory:\n\n              cargo locate-project\n\nSEE ALSO\n       cargo(1), cargo-metadata(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-login.txt",
    "content": "CARGO-LOGIN(1)\n\nNAME\n       cargo-login — Log in to a registry\n\nSYNOPSIS\n       cargo login [options] [-- args]\n\nDESCRIPTION\n       This command will run a credential provider to save a token so that\n       commands that require authentication, such as cargo-publish(1), will be\n       automatically authenticated.\n\n       All the arguments following the two dashes (--) are passed to the\n       credential provider.\n\n       For the default cargo:token credential provider, the token is saved in\n       $CARGO_HOME/credentials.toml. CARGO_HOME defaults to .cargo in your home\n       directory.\n\n       If a registry has a credential-provider specified, it will be used.\n       Otherwise, the providers from the config value\n       registry.global-credential-providers will be attempted, starting from\n       the end of the list.\n\n       The token will be read from stdin.\n\n       The API token for crates.io may be retrieved from\n       <https://crates.io/me>.\n\n       Take care to keep the token secret, it should not be shared with anyone\n       else.\n\nOPTIONS\n   Login Options\n       --registry registry\n           Name of the registry to use. Registry names are defined in Cargo\n           config files\n           <https://doc.rust-lang.org/cargo/reference/config.html>. If not\n           specified, the default registry is used, which is defined by the\n           registry.default config key which defaults to crates-io.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Save the token for the default registry:\n\n              cargo login\n\n       2. Save the token for a specific registry:\n\n              cargo login --registry my-registry\n\nSEE ALSO\n       cargo(1), cargo-logout(1), cargo-publish(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-logout.txt",
    "content": "CARGO-LOGOUT(1)\n\nNAME\n       cargo-logout — Remove an API token from the registry locally\n\nSYNOPSIS\n       cargo logout [options]\n\nDESCRIPTION\n       This command will run a credential provider to remove a saved token.\n\n       For the default cargo:token credential provider, credentials are stored\n       in $CARGO_HOME/credentials.toml where $CARGO_HOME defaults to .cargo in\n       your home directory.\n\n       If a registry has a credential-provider specified, it will be used.\n       Otherwise, the providers from the config value\n       registry.global-credential-providers will be attempted, starting from\n       the end of the list.\n\n       If --registry is not specified, then the credentials for the default\n       registry will be removed (configured by registry.default\n       <https://doc.rust-lang.org/cargo/reference/config.html#registrydefault>,\n       which defaults to <https://crates.io/>).\n\n       This will not revoke the token on the server. If you need to revoke the\n       token, visit the registry website and follow its instructions (see\n       <https://crates.io/me> to revoke the token for <https://crates.io/>).\n\nOPTIONS\n   Logout Options\n       --registry registry\n           Name of the registry to use. Registry names are defined in Cargo\n           config files\n           <https://doc.rust-lang.org/cargo/reference/config.html>. If not\n           specified, the default registry is used, which is defined by the\n           registry.default config key which defaults to crates-io.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Remove the default registry token:\n\n              cargo logout\n\n       2. Remove the token for a specific registry:\n\n              cargo logout --registry my-registry\n\nSEE ALSO\n       cargo(1), cargo-login(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-metadata.txt",
    "content": "CARGO-METADATA(1)\n\nNAME\n       cargo-metadata — Machine-readable metadata about the current package\n\nSYNOPSIS\n       cargo metadata [options]\n\nDESCRIPTION\n       Output JSON to stdout containing information about the workspace members\n       and resolved dependencies of the current package.\n\n       The output format is subject to change in future versions of Cargo. It\n       is recommended to include the --format-version flag to future-proof your\n       code and ensure the output is in the format you are expecting. For more\n       on the expectations, see “Compatibility”.\n\n       See the cargo_metadata crate <https://crates.io/crates/cargo_metadata>\n       for a Rust API for reading the metadata.\n\nOUTPUT FORMAT\n   Compatibility\n       Within the same output format version, the compatibility is maintained,\n       except some scenarios. The following is a non-exhaustive list of changes\n       that are not considered as incompatible:\n\n       o  Adding new fields — New fields will be added when needed. Reserving\n          this helps Cargo evolve without bumping the format version too often.\n\n       o  Adding new values for enum-like fields — Same as adding new fields.\n          It keeps metadata evolving without stagnation.\n\n       o  Changing opaque representations — The inner representations of some\n          fields are implementation details. For example, fields related to\n          “Source ID” are treated as opaque identifiers to differentiate\n          packages or sources. Consumers shouldn’t rely on those\n          representations unless specified.\n\n   JSON format\n       The JSON output has the following format:\n\n           {\n               /* Array of all packages in the workspace.\n                  It also includes all feature-enabled dependencies unless --no-deps is used.\n               */\n               \"packages\": [\n                   {\n                       /* The name of the package. */\n                       \"name\": \"my-package\",\n                       /* The version of the package. */\n                       \"version\": \"0.1.0\",\n                       /* The Package ID for referring to the\n                          package within the document and as the `--package` argument to many commands\n                       */\n                       \"id\": \"file:///path/to/my-package#0.1.0\",\n                       /* The license value from the manifest, or null. */\n                       \"license\": \"MIT/Apache-2.0\",\n                       /* The license-file value from the manifest, or null. */\n                       \"license_file\": \"LICENSE\",\n                       /* The description value from the manifest, or null. */\n                       \"description\": \"Package description.\",\n                       /* The source ID of the package, an \"opaque\" identifier representing\n                          where a package is retrieved from. See \"Compatibility\" above for\n                          the stability guarantee.\n           \n                          This is null for path dependencies and workspace members.\n           \n                          For other dependencies, it is a string with the format:\n                          - \"registry+URL\" for registry-based dependencies.\n                            Example: \"registry+https://github.com/rust-lang/crates.io-index\"\n                          - \"git+URL\" for git-based dependencies.\n                            Example: \"git+https://github.com/rust-lang/cargo?rev=5e85ba14aaa20f8133863373404cb0af69eeef2c#5e85ba14aaa20f8133863373404cb0af69eeef2c\"\n                          - \"sparse+URL\" for dependencies from a sparse registry\n                            Example: \"sparse+https://my-sparse-registry.org\"\n           \n                          The value after the `+` is not explicitly defined, and may change\n                          between versions of Cargo and may not directly correlate to other\n                          things, such as registry definitions in a config file. New source\n                          kinds may be added in the future which will have different `+`\n                          prefixed identifiers.\n                       */\n                       \"source\": null,\n                       /* Array of dependencies declared in the package's manifest. */\n                       \"dependencies\": [\n                           {\n                               /* The name of the dependency. */\n                               \"name\": \"bitflags\",\n                               /* The source ID of the dependency. May be null, see\n                                  description for the package source.\n                               */\n                               \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n                               /* The version requirement for the dependency.\n                                  Dependencies without a version requirement have a value of \"*\".\n                               */\n                               \"req\": \"^1.0\",\n                               /* The dependency kind.\n                                  \"dev\", \"build\", or null for a normal dependency.\n                               */\n                               \"kind\": null,\n                               /* If the dependency is renamed, this is the new name for\n                                  the dependency as a string.  null if it is not renamed.\n                               */\n                               \"rename\": null,\n                               /* Boolean of whether or not this is an optional dependency. */\n                               \"optional\": false,\n                               /* Boolean of whether or not default features are enabled. */\n                               \"uses_default_features\": true,\n                               /* Array of features enabled. */\n                               \"features\": [],\n                               /* The target platform for the dependency.\n                                  null if not a target dependency.\n                               */\n                               \"target\": \"cfg(windows)\",\n                               /* The file system path for a local path dependency.\n                                  not present if not a path dependency.\n                               */\n                               \"path\": \"/path/to/dep\",\n                               /* A string of the URL of the registry this dependency is from.\n                                  If not specified or null, the dependency is from the default\n                                  registry (crates.io).\n                               */\n                               \"registry\": null,\n                               /* (unstable) Boolean flag of whether or not this is a pulbic\n                                  dependency. This field is only present when\n                                  `-Zpublic-dependency` is enabled.\n                               */\n                               \"public\": false\n                           }\n                       ],\n                       /* Array of Cargo targets. */\n                       \"targets\": [\n                           {\n                               /* Array of target kinds.\n                                  - lib targets list the `crate-type` values from the\n                                    manifest such as \"lib\", \"rlib\", \"dylib\",\n                                    \"proc-macro\", etc. (default [\"lib\"])\n                                  - binary is [\"bin\"]\n                                  - example is [\"example\"]\n                                  - integration test is [\"test\"]\n                                  - benchmark is [\"bench\"]\n                                  - build script is [\"custom-build\"]\n                               */\n                               \"kind\": [\n                                   \"bin\"\n                               ],\n                               /* Array of crate types.\n                                  - lib and example libraries list the `crate-type` values\n                                    from the manifest such as \"lib\", \"rlib\", \"dylib\",\n                                    \"proc-macro\", etc. (default [\"lib\"])\n                                  - all other target kinds are [\"bin\"]\n                               */\n                               \"crate_types\": [\n                                   \"bin\"\n                               ],\n                               /* The name of the target.\n                                  For lib targets, dashes will be replaced with underscores.\n                               */\n                               \"name\": \"my-package\",\n                               /* Absolute path to the root source file of the target. */\n                               \"src_path\": \"/path/to/my-package/src/main.rs\",\n                               /* The Rust edition of the target.\n                                  Defaults to the package edition.\n                               */\n                               \"edition\": \"2018\",\n                               /* Array of required features.\n                                  This property is not included if no required features are set.\n                               */\n                               \"required-features\": [\"feat1\"],\n                               /* Whether the target should be documented by `cargo doc`. */\n                               \"doc\": true,\n                               /* Whether or not this target has doc tests enabled, and\n                                  the target is compatible with doc testing.\n                               */\n                               \"doctest\": false,\n                               /* Whether or not this target should be built and run with `--test`\n                               */\n                               \"test\": true\n                           }\n                       ],\n                       /* Set of features defined for the package.\n                          Each feature maps to an array of features or dependencies it\n                          enables.\n                       */\n                       \"features\": {\n                           \"default\": [\n                               \"feat1\"\n                           ],\n                           \"feat1\": [],\n                           \"feat2\": []\n                       },\n                       /* Absolute path to this package's manifest. */\n                       \"manifest_path\": \"/path/to/my-package/Cargo.toml\",\n                       /* Package metadata.\n                          This is null if no metadata is specified.\n                       */\n                       \"metadata\": {\n                           \"docs\": {\n                               \"rs\": {\n                                   \"all-features\": true\n                               }\n                           }\n                       },\n                       /* List of registries to which this package may be published.\n                          Publishing is unrestricted if null, and forbidden if an empty array. */\n                       \"publish\": [\n                           \"crates-io\"\n                       ],\n                       /* Array of authors from the manifest.\n                          Empty array if no authors specified.\n                       */\n                       \"authors\": [\n                           \"Jane Doe <user@example.com>\"\n                       ],\n                       /* Array of categories from the manifest. */\n                       \"categories\": [\n                           \"command-line-utilities\"\n                       ],\n                       /* Optional string that is the default binary picked by cargo run. */\n                       \"default_run\": null,\n                       /* Optional string that is the minimum supported rust version */\n                       \"rust_version\": \"1.56\",\n                       /* Array of keywords from the manifest. */\n                       \"keywords\": [\n                           \"cli\"\n                       ],\n                       /* The readme value from the manifest or null if not specified. */\n                       \"readme\": \"README.md\",\n                       /* The repository value from the manifest or null if not specified. */\n                       \"repository\": \"https://github.com/rust-lang/cargo\",\n                       /* The homepage value from the manifest or null if not specified. */\n                       \"homepage\": \"https://rust-lang.org\",\n                       /* The documentation value from the manifest or null if not specified. */\n                       \"documentation\": \"https://doc.rust-lang.org/stable/std\",\n                       /* The default edition of the package.\n                          Note that individual targets may have different editions.\n                       */\n                       \"edition\": \"2018\",\n                       /* Optional string that is the name of a native library the package\n                          is linking to.\n                       */\n                       \"links\": null,\n                   }\n               ],\n               /* Array of members of the workspace.\n                  Each entry is the Package ID for the package.\n               */\n               \"workspace_members\": [\n                   \"file:///path/to/my-package#0.1.0\",\n               ],\n               /* Array of default members of the workspace.\n                  Each entry is the Package ID for the package.\n               */\n               \"workspace_default_members\": [\n                   \"file:///path/to/my-package#0.1.0\",\n               ],\n               // The resolved dependency graph for the entire workspace. The enabled\n               // features are based on the enabled features for the \"current\" package.\n               // Inactivated optional dependencies are not listed.\n               //\n               // This is null if --no-deps is specified.\n               //\n               // By default, this includes all dependencies for all target platforms.\n               // The `--filter-platform` flag may be used to narrow to a specific\n               // target triple.\n               \"resolve\": {\n                   /* Array of nodes within the dependency graph.\n                      Each node is a package.\n                   */\n                   \"nodes\": [\n                       {\n                           /* The Package ID of this node. */\n                           \"id\": \"file:///path/to/my-package#0.1.0\",\n                           /* The dependencies of this package, an array of Package IDs. */\n                           \"dependencies\": [\n                               \"https://github.com/rust-lang/crates.io-index#bitflags@1.0.4\"\n                           ],\n                           /* The dependencies of this package. This is an alternative to\n                              \"dependencies\" which contains additional information. In\n                              particular, this handles renamed dependencies.\n                           */\n                           \"deps\": [\n                               {\n                                   /* The name of the dependency's library target.\n                                      If this is a renamed dependency, this is the new\n                                      name.\n                                   */\n                                   \"name\": \"bitflags\",\n                                   /* The Package ID of the dependency. */\n                                   \"pkg\": \"https://github.com/rust-lang/crates.io-index#bitflags@1.0.4\"\n                                   /* Array of dependency kinds. Added in Cargo 1.40. */\n                                   \"dep_kinds\": [\n                                       {\n                                           /* The dependency kind.\n                                              \"dev\", \"build\", or null for a normal dependency.\n                                           */\n                                           \"kind\": null,\n                                           /* The target platform for the dependency.\n                                              null if not a target dependency.\n                                           */\n                                           \"target\": \"cfg(windows)\"\n                                       }\n                                   ]\n                               }\n                           ],\n                           /* Array of features enabled on this package. */\n                           \"features\": [\n                               \"default\"\n                           ]\n                       }\n                   ],\n                   /* The package in the current working directory (if --manifest-path is not given).\n                      This is null if there is a virtual workspace. Otherwise it is\n                      the Package ID of the package.\n                   */\n                   \"root\": \"file:///path/to/my-package#0.1.0\",\n               },\n               /* The absolute path to the target directory where Cargo places its output. */\n               \"target_directory\": \"/path/to/my-package/target\",\n               /* The absolute path to the build directory where Cargo places intermediate build artifacts. (unstable) */\n               \"build_directory\": \"/path/to/my-package/build-dir\",\n               /* The version of the schema for this metadata structure.\n                  This will be changed if incompatible changes are ever made.\n               */\n               \"version\": 1,\n               /* The absolute path to the root of the workspace. */\n               \"workspace_root\": \"/path/to/my-package\"\n               /* Workspace metadata.\n                  This is null if no metadata is specified. */\n               \"metadata\": {\n                   \"docs\": {\n                       \"rs\": {\n                           \"all-features\": true\n                       }\n                   }\n               }\n           }\n\n       Notes:\n\n       o  For \"id\" field syntax, see Package ID Specifications\n          <https://doc.rust-lang.org/cargo/reference/pkgid-spec.html> in the\n          reference.\n\nOPTIONS\n   Output Options\n       --no-deps\n           Output information only about the workspace members and don’t\n           fetch dependencies.\n\n       --format-version version\n           Specify the version of the output format to use. Currently 1 is the\n           only possible value.\n\n       --filter-platform triple\n           This filters the resolve output to only include dependencies for the\n           given target triple\n           <https://doc.rust-lang.org/cargo/appendix/glossary.html#target>. A\n           literal \"host-tuple\" can be used, which will internally be\n           substituted by the host’s target. Without this flag, the resolve\n           includes all targets.\n\n           Note that the dependencies listed in the “packages” array still\n           includes all dependencies. Each package definition is intended to be\n           an unaltered reproduction of the information within Cargo.toml.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Output JSON about the current package:\n\n              cargo metadata --format-version=1\n\nSEE ALSO\n       cargo(1), cargo-pkgid(1), Package ID Specifications\n       <https://doc.rust-lang.org/cargo/reference/pkgid-spec.html>, JSON\n       messages\n       <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-new.txt",
    "content": "CARGO-NEW(1)\n\nNAME\n       cargo-new — Create a new Cargo package\n\nSYNOPSIS\n       cargo new [options] path\n\nDESCRIPTION\n       This command will create a new Cargo package in the given directory.\n       This includes a simple template with a Cargo.toml manifest, sample\n       source file, and a VCS ignore file. If the directory is not already in a\n       VCS repository, then a new repository is created (see --vcs below).\n\n       See cargo-init(1) for a similar command which will create a new manifest\n       in an existing directory.\n\nOPTIONS\n   New Options\n       --bin\n           Create a package with a binary target (src/main.rs). This is the\n           default behavior.\n\n       --lib\n           Create a package with a library target (src/lib.rs).\n\n       --edition edition\n           Specify the Rust edition to use. Default is 2024. Possible values:\n           2015, 2018, 2021, 2024\n\n       --name name\n           Set the package name. Defaults to the directory name.\n\n       --vcs vcs\n           Initialize a new VCS repository for the given version control system\n           (git, hg, pijul, or fossil) or do not initialize any version control\n           at all (none). If not specified, defaults to git or the\n           configuration value cargo-new.vcs, or none if already inside a VCS\n           repository.\n\n       --registry registry\n           This sets the publish field in Cargo.toml to the given registry name\n           which will restrict publishing only to that registry.\n\n           Registry names are defined in Cargo config files\n           <https://doc.rust-lang.org/cargo/reference/config.html>. If not\n           specified, the default registry defined by the registry.default\n           config key is used. If the default registry is not set and\n           --registry is not used, the publish field will not be set which\n           means that publishing will not be restricted.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Create a binary Cargo package in the given directory:\n\n              cargo new foo\n\nSEE ALSO\n       cargo(1), cargo-init(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-owner.txt",
    "content": "CARGO-OWNER(1)\n\nNAME\n       cargo-owner — Manage the owners of a crate on the registry\n\nSYNOPSIS\n       cargo owner [options] --add login [crate]\n       cargo owner [options] --remove login [crate]\n       cargo owner [options] --list [crate]\n\nDESCRIPTION\n       This command will modify the owners for a crate on the registry. Owners\n       of a crate can upload new versions and yank old versions. Non-team\n       owners can also modify the set of owners, so take care!\n\n       This command requires you to be authenticated with either the --token\n       option or using cargo-login(1).\n\n       If the crate name is not specified, it will use the package name from\n       the current directory.\n\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/publishing.html#cargo-owner>\n       for more information about owners and publishing.\n\nOPTIONS\n   Owner Options\n       -a, --add login…\n           Invite the given user or team as an owner.\n\n       -r, --remove login…\n           Remove the given user or team as an owner.\n\n       -l, --list\n           List owners of a crate.\n\n       --token token\n           API token to use when authenticating. This overrides the token\n           stored in the credentials file (which is created by cargo-login(1)).\n\n           Cargo config <https://doc.rust-lang.org/cargo/reference/config.html>\n           environment variables can be used to override the tokens stored in\n           the credentials file. The token for crates.io may be specified with\n           the CARGO_REGISTRY_TOKEN environment variable. Tokens for other\n           registries may be specified with environment variables of the form\n           CARGO_REGISTRIES_NAME_TOKEN where NAME is the name of the registry\n           in all capital letters.\n\n       --index index\n           The URL of the registry index to use.\n\n       --registry registry\n           Name of the registry to use. Registry names are defined in Cargo\n           config files\n           <https://doc.rust-lang.org/cargo/reference/config.html>. If not\n           specified, the default registry is used, which is defined by the\n           registry.default config key which defaults to crates-io.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. List owners of a package:\n\n              cargo owner --list foo\n\n       2. Invite an owner to a package:\n\n              cargo owner --add username foo\n\n       3. Remove an owner from a package:\n\n              cargo owner --remove username foo\n\nSEE ALSO\n       cargo(1), cargo-login(1), cargo-publish(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-package.txt",
    "content": "CARGO-PACKAGE(1)\n\nNAME\n       cargo-package — Assemble the local package into a distributable\n       tarball\n\nSYNOPSIS\n       cargo package [options]\n\nDESCRIPTION\n       This command will create a distributable, compressed .crate file with\n       the source code of the package in the current directory. The resulting\n       file will be stored in the target/package directory. This performs the\n       following steps:\n\n       1. Load and check the current workspace, performing some basic checks.\n\n          o  Path dependencies are not allowed unless they have a version key.\n             Cargo will ignore the path key for dependencies in published\n             packages. dev-dependencies do not have this restriction.\n\n       2. Create the compressed .crate file.\n\n          o  The original Cargo.toml file is rewritten and normalized.\n\n          o  [patch], [replace], and [workspace] sections are removed from the\n             manifest.\n\n          o  Cargo.lock is always included. When missing, a new lock file will\n             be generated unless the --exclude-lockfile flag is used.\n             cargo-install(1) will use the packaged lock file if the --locked\n             flag is used.\n\n          o  A .cargo_vcs_info.json file is included that contains information\n             about the current VCS checkout hash if available, as well as a\n             flag if the worktree is dirty.\n\n          o  Symlinks are flattened to their target files.\n\n          o  Files and directories are included or excluded based on rules\n             mentioned in the [include] and [exclude] fields\n             <https://doc.rust-lang.org/cargo/reference/manifest.html#the-exclude-and-include-fields>.\n\n       3. Extract the .crate file and build it to verify it can build.\n\n          o  This will rebuild your package from scratch to ensure that it can\n             be built from a pristine state. The --no-verify flag can be used\n             to skip this step.\n\n       4. Check that build scripts did not modify any source files.\n\n       The list of files included can be controlled with the include and\n       exclude fields in the manifest.\n\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/publishing.html> for more\n       details about packaging and publishing.\n\n   .cargo_vcs_info.json format\n       Will generate a .cargo_vcs_info.json in the following format\n\n           {\n            \"git\": {\n              \"sha1\": \"aac20b6e7e543e6dd4118b246c77225e3a3a1302\",\n              \"dirty\": true\n            },\n            \"path_in_vcs\": \"\"\n           }\n\n       dirty indicates that the Git worktree was dirty when the package was\n       built.\n\n       path_in_vcs will be set to a repo-relative path for packages in\n       subdirectories of the version control repository.\n\n       The compatibility of this file is maintained under the same policy as\n       the JSON output of cargo-metadata(1).\n\n       Note that this file provides a best-effort snapshot of the VCS\n       information. However, the provenance of the package is not verified.\n       There is no guarantee that the source code in the tarball matches the\n       VCS information.\n\nOPTIONS\n   Package Options\n       -l, --list\n           Print files included in a package without making one.\n\n       --no-verify\n           Don’t verify the contents by building them.\n\n       --no-metadata\n           Ignore warnings about a lack of human-usable metadata (such as the\n           description or the license).\n\n       --allow-dirty\n           Allow working directories with uncommitted VCS changes to be\n           packaged.\n\n       --exclude-lockfile\n           Don’t include the lock file when packaging.\n\n           This flag is not for general use. Some tools may expect a lock file\n           to be present (e.g. cargo install --locked). Consider other options\n           before using this.\n\n       --index index\n           The URL of the registry index to use.\n\n       --registry registry\n           Name of the registry to package for; see cargo publish --help for\n           more details about configuration of registry names. The packages\n           will not be published to this registry, but if we are packaging\n           multiple inter-dependent crates, lock-files will be generated under\n           the assumption that dependencies will be published to this registry.\n\n       --message-format fmt\n           Specifies the output message format. Currently, it only works with\n           --list and affects the file listing format. This is unstable and\n           requires -Zunstable-options. Valid output formats:\n\n           o  human (default): Display in a file-per-line format.\n\n           o  json: Emit machine-readable JSON information about each package.\n              One package per JSON line (Newline delimited JSON).\n                  {\n                    /* The Package ID Spec of the package. */\n                    \"id\": \"path+file:///home/foo#0.0.0\",\n                    /* Files of this package */\n                    \"files\" {\n                      /* Relative path in the archive file. */\n                      \"Cargo.toml.orig\": {\n                        /* Where the file is from.\n                           - \"generate\" for file being generated during packaging\n                           - \"copy\" for file being copied from another location.\n                        */\n                        \"kind\": \"copy\",\n                        /* For the \"copy\" kind,\n                           it is an absolute path to the actual file content.\n                           For the \"generate\" kind,\n                           it is the original file the generated one is based on.\n                        */\n                        \"path\": \"/home/foo/Cargo.toml\"\n                      },\n                      \"Cargo.toml\": {\n                        \"kind\": \"generate\",\n                        \"path\": \"/home/foo/Cargo.toml\"\n                      },\n                      \"src/main.rs\": {\n                        \"kind\": \"copy\",\n                        \"path\": \"/home/foo/src/main.rs\"\n                      }\n                    }\n                  }\n\n   Package Selection\n       By default, when no package selection options are given, the packages\n       selected depend on the selected manifest file (based on the current\n       working directory if --manifest-path is not given). If the manifest is\n       the root of a workspace then the workspaces default members are\n       selected, otherwise only the package defined by the manifest will be\n       selected.\n\n       The default members of a workspace can be set explicitly with the\n       workspace.default-members key in the root manifest. If this is not set,\n       a virtual workspace will include all workspace members (equivalent to\n       passing --workspace), and a non-virtual workspace will include only the\n       root crate itself.\n\n       -p spec…, --package spec…\n           Package only the specified packages. See cargo-pkgid(1) for the SPEC\n           format. This flag may be specified multiple times and supports\n           common Unix glob patterns like *, ? and []. However, to avoid your\n           shell accidentally expanding glob patterns before Cargo handles\n           them, you must use single quotes or double quotes around each\n           pattern.\n\n       --workspace\n           Package all members in the workspace.\n\n       --exclude SPEC…\n           Exclude the specified packages. Must be used in conjunction with the\n           --workspace flag. This flag may be specified multiple times and\n           supports common Unix glob patterns like *, ? and []. However, to\n           avoid your shell accidentally expanding glob patterns before Cargo\n           handles them, you must use single quotes or double quotes around\n           each pattern.\n\n   Compilation Options\n       --target triple\n           Package for the specified target architecture. Flag may be specified\n           multiple times. The default is the host architecture. The general\n           format of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Miscellaneous Options\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       --keep-going\n           Build as many crates in the dependency graph as possible, rather\n           than aborting the build on the first one that fails to build.\n\n           For example if the current package depends on dependencies fails and\n           works, one of which fails to build, cargo package -j1 may or may not\n           build the one that succeeds (depending on which one of the two\n           builds Cargo picked to run first), whereas cargo package -j1\n           --keep-going would definitely run both builds, even if the one run\n           first fails.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Create a compressed .crate file of the current package:\n\n              cargo package\n\nSEE ALSO\n       cargo(1), cargo-publish(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-pkgid.txt",
    "content": "CARGO-PKGID(1)\n\nNAME\n       cargo-pkgid — Print a fully qualified package specification\n\nSYNOPSIS\n       cargo pkgid [options] [spec]\n\nDESCRIPTION\n       Given a spec argument, print out the fully qualified package ID\n       specifier for a package or dependency in the current workspace. This\n       command will generate an error if spec is ambiguous as to which package\n       it refers to in the dependency graph. If no spec is given, then the\n       specifier for the local package is printed.\n\n       This command requires that a lockfile is available and dependencies have\n       been fetched.\n\n       A package specifier consists of a name, version, and source URL. You are\n       allowed to use partial specifiers to succinctly match a specific package\n       as long as it matches only one package. This specifier is also used by\n       other parts in Cargo, such as cargo-metadata(1) and JSON messages\n       <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n       emitted by Cargo.\n\n       The format of a spec can be one of the following:\n\n       +-----------------+--------------------------------------------------+\n       | SPEC Structure  | Example SPEC                                     |\n       +-----------------+--------------------------------------------------+\n       | name            | bitflags                                         |\n       +-----------------+--------------------------------------------------+\n       | name@version    | bitflags@1.0.4                                   |\n       +-----------------+--------------------------------------------------+\n       | url             | https://github.com/rust-lang/cargo               |\n       +-----------------+--------------------------------------------------+\n       | url#version     | https://github.com/rust-lang/cargo#0.33.0        |\n       +-----------------+--------------------------------------------------+\n       | url#name        |                                                  |\n       |                 | https://github.com/rust-lang/crates.io-index#bitflags |\n       +-----------------+--------------------------------------------------+\n       |                 |                                                  |\n       | url#name@version | https://github.com/rust-lang/cargo#crates-io@0.21.0 |\n       +-----------------+--------------------------------------------------+\n\n       The specification grammar can be found in chapter Package ID\n       Specifications\n       <https://doc.rust-lang.org/cargo/reference/pkgid-spec.html>.\n\nOPTIONS\n   Package Selection\n       -p spec, --package spec\n           Get the package ID for the given package instead of the current\n           package.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Retrieve package specification for foo package:\n\n              cargo pkgid foo\n\n       2. Retrieve package specification for version 1.0.0 of foo:\n\n              cargo pkgid foo@1.0.0\n\n       3. Retrieve package specification for foo from crates.io:\n\n              cargo pkgid https://github.com/rust-lang/crates.io-index#foo\n\n       4. Retrieve package specification for foo from a local package:\n\n              cargo pkgid file:///path/to/local/package#foo\n\nSEE ALSO\n       cargo(1), cargo-generate-lockfile(1), cargo-metadata(1), Package ID\n       Specifications\n       <https://doc.rust-lang.org/cargo/reference/pkgid-spec.html>, JSON\n       messages\n       <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-publish.txt",
    "content": "CARGO-PUBLISH(1)\n\nNAME\n       cargo-publish — Upload a package to the registry\n\nSYNOPSIS\n       cargo publish [options]\n\nDESCRIPTION\n       This command will create a distributable, compressed .crate file with\n       the source code of the package in the current directory and upload it to\n       a registry. The default registry is <https://crates.io>. This performs\n       the following steps:\n\n       1. Performs a few checks, including:\n          o  Checks the package.publish key in the manifest for restrictions on\n             which registries you are allowed to publish to.\n\n       2. Create a .crate file by following the steps in cargo-package(1).\n\n       3. Upload the crate to the registry. The server will perform additional\n          checks on the crate.\n\n       4. The client will poll waiting for the package to appear in the index,\n          and may timeout. In that case, you will need to check for completion\n          manually. This timeout does not affect the upload.\n\n       This command requires you to be authenticated using cargo-login(1) or\n       environment variables of the registry.token\n       <https://doc.rust-lang.org/cargo/reference/config.html#registrytoken>\n       and registries.<name>.token\n       <https://doc.rust-lang.org/cargo/reference/config.html#registriesnametoken>\n       config fields.\n\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/publishing.html> for more\n       details about packaging and publishing.\n\nOPTIONS\n   Publish Options\n       --dry-run\n           Perform all checks without uploading.\n\n       --no-verify\n           Don’t verify the contents by building them.\n\n       --allow-dirty\n           Allow working directories with uncommitted VCS changes to be\n           packaged.\n\n       --index index\n           The URL of the registry index to use.\n\n       --registry registry\n           Name of the registry to publish to. Registry names are defined in\n           Cargo config files\n           <https://doc.rust-lang.org/cargo/reference/config.html>. If not\n           specified, and there is a package.publish\n           <https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field>\n           field in Cargo.toml with a single registry, then it will publish to\n           that registry. Otherwise it will use the default registry, which is\n           defined by the registry.default\n           <https://doc.rust-lang.org/cargo/reference/config.html#registrydefault>\n           config key which defaults to crates-io.\n\n   Package Selection\n       By default, when no package selection options are given, the packages\n       selected depend on the selected manifest file (based on the current\n       working directory if --manifest-path is not given). If the manifest is\n       the root of a workspace then the workspaces default members are\n       selected, otherwise only the package defined by the manifest will be\n       selected.\n\n       The default members of a workspace can be set explicitly with the\n       workspace.default-members key in the root manifest. If this is not set,\n       a virtual workspace will include all workspace members (equivalent to\n       passing --workspace), and a non-virtual workspace will include only the\n       root crate itself.\n\n       -p spec…, --package spec…\n           Publish only the specified packages. See cargo-pkgid(1) for the SPEC\n           format. This flag may be specified multiple times and supports\n           common Unix glob patterns like *, ? and []. However, to avoid your\n           shell accidentally expanding glob patterns before Cargo handles\n           them, you must use single quotes or double quotes around each\n           pattern.\n\n       --workspace\n           Publish all members in the workspace.\n\n       --all\n           Deprecated alias for --workspace.\n\n       --exclude SPEC…\n           Exclude the specified packages. Must be used in conjunction with the\n           --workspace flag. This flag may be specified multiple times and\n           supports common Unix glob patterns like *, ? and []. However, to\n           avoid your shell accidentally expanding glob patterns before Cargo\n           handles them, you must use single quotes or double quotes around\n           each pattern.\n\n   Compilation Options\n       --target triple\n           Publish for the specified target architecture. Flag may be specified\n           multiple times. The default is the host architecture. The general\n           format of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Miscellaneous Options\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       --keep-going\n           Build as many crates in the dependency graph as possible, rather\n           than aborting the build on the first one that fails to build.\n\n           For example if the current package depends on dependencies fails and\n           works, one of which fails to build, cargo publish -j1 may or may not\n           build the one that succeeds (depending on which one of the two\n           builds Cargo picked to run first), whereas cargo publish -j1\n           --keep-going would definitely run both builds, even if the one run\n           first fails.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Publish the current package:\n\n              cargo publish\n\nSEE ALSO\n       cargo(1), cargo-package(1), cargo-login(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-remove.txt",
    "content": "CARGO-REMOVE(1)\n\nNAME\n       cargo-remove — Remove dependencies from a Cargo.toml manifest file\n\nSYNOPSIS\n       cargo remove [options] dependency…\n\nDESCRIPTION\n       Remove one or more dependencies from a Cargo.toml manifest.\n\nOPTIONS\n   Section options\n       --dev\n           Remove as a development dependency\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#development-dependencies>.\n\n       --build\n           Remove as a build dependency\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#build-dependencies>.\n\n       --target target\n           Remove as a dependency to the given target platform\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies>.\n\n           To avoid unexpected shell expansions, you may use quotes around each\n           target, e.g., --target 'cfg(unix)'.\n\n   Miscellaneous Options\n       --dry-run\n           Don’t actually write to the manifest.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Package Selection\n       -p spec…, --package spec…\n           Package to remove from.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Remove regex as a dependency\n\n              cargo remove regex\n\n       2. Remove trybuild as a dev-dependency\n\n              cargo remove --dev trybuild\n\n       3. Remove nom from the wasm32-unknown-unknown dependencies table\n\n              cargo remove --target wasm32-unknown-unknown nom\n\nSEE ALSO\n       cargo(1), cargo-add(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-report-future-incompatibilities.txt",
    "content": "CARGO-REPORT-FUTURE-INCOMPATIBILITIES(1)\n\nNAME\n       cargo-report-future-incompatibilities — Reports any crates which will\n       eventually stop compiling\n\nSYNOPSIS\n       cargo report future-incompatibilities [options]\n\nDESCRIPTION\n       Displays a report of future-incompatible warnings that were emitted\n       during previous builds. These are warnings for changes that may become\n       hard errors in the future, causing dependencies to stop building in a\n       future version of rustc.\n\n       For more, see the chapter on Future incompat report\n       <https://doc.rust-lang.org/cargo/reference/future-incompat-report.html>.\n\nOPTIONS\n       --id id\n           Show the report with the specified Cargo-generated id. If not\n           specified, shows the most recent report.\n\n   Package Selection\n       By default, the package in the current working directory is selected.\n       The -p flag can be used to choose a different package in a workspace.\n\n       -p spec, --package spec\n           The package to display a report for. See cargo-pkgid(1) for the SPEC\n           format.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Display the latest future-incompat report:\n\n              cargo report future-incompat\n\n       2. Display the latest future-incompat report for a specific package:\n\n              cargo report future-incompat --package my-dep@0.0.1\n\nSEE ALSO\n       cargo(1), cargo-report(1), cargo-build(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-report.txt",
    "content": "CARGO-REPORT(1)\n\nNAME\n       cargo-report — Generate and display various kinds of reports\n\nSYNOPSIS\n       cargo report type [options]\n\nDESCRIPTION\n       Displays a report of the given type — currently, only future-incompat\n       is supported\n\nOPTIONS\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Display the available kinds of reports:\n\n              cargo report --help\n\nSEE ALSO\n       cargo(1), cargo-report-future-incompatibilities(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-run.txt",
    "content": "CARGO-RUN(1)\n\nNAME\n       cargo-run — Run the current package\n\nSYNOPSIS\n       cargo run [options] [-- args]\n\nDESCRIPTION\n       Run a binary or example of the local package.\n\n       All the arguments following the two dashes (--) are passed to the binary\n       to run. If you’re passing arguments to both Cargo and the binary, the\n       ones after -- go to the binary, the ones before go to Cargo.\n\n       Unlike cargo-test(1) and cargo-bench(1), cargo run sets the working\n       directory of the binary executed to the current working directory, same\n       as if it was executed in the shell directly.\n\nOPTIONS\n   Package Selection\n       By default, the package in the current working directory is selected.\n       The -p flag can be used to choose a different package in a workspace.\n\n       -p spec, --package spec\n           The package to run. See cargo-pkgid(1) for the SPEC format.\n\n   Target Selection\n       When no target selection options are given, cargo run will run the\n       binary target. If there are multiple binary targets, you must pass a\n       target flag to choose one. Or, the default-run field may be specified in\n       the [package] section of Cargo.toml to choose the name of the binary to\n       run by default.\n\n       --bin name\n           Run the specified binary.\n\n       --example name\n           Run the specified example.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Compilation Options\n       --target triple\n           Run for the specified target architecture. The default is the host\n           architecture. The general format of the triple is\n           <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       -r, --release\n           Run optimized artifacts with the release profile. See also the\n           --profile option for choosing a specific profile by name.\n\n       --profile name\n           Run with the given profile. See the reference\n           <https://doc.rust-lang.org/cargo/reference/profiles.html> for more\n           details on profiles.\n\n       --timings\n           Output information how long each compilation takes, and track\n           concurrency information over time.\n\n           A file cargo-timing.html will be written to the target/cargo-timings\n           directory at the end of the build. An additional report with a\n           timestamp in its filename is also written if you want to look at a\n           previous run. These reports are suitable for human consumption only,\n           and do not provide machine-readable timing data.\n\n   Output Options\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --message-format fmt\n           The output format for diagnostic messages. Can be specified multiple\n           times and consists of comma-separated values. Valid values:\n\n           o  human (default): Display in a human-readable text format.\n              Conflicts with short and json.\n\n           o  short: Emit shorter, human-readable text messages. Conflicts with\n              human and json.\n\n           o  json: Emit JSON messages to stdout. See the reference\n              <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n              for more details. Conflicts with human and short.\n\n           o  json-diagnostic-short: Ensure the rendered field of JSON messages\n              contains the “short” rendering from rustc. Cannot be used\n              with human or short.\n\n           o  json-diagnostic-rendered-ansi: Ensure the rendered field of JSON\n              messages contains embedded ANSI color codes for respecting\n              rustc’s default color scheme. Cannot be used with human or\n              short.\n\n           o  json-render-diagnostics: Instruct Cargo to not include rustc\n              diagnostics in JSON messages printed, but instead Cargo itself\n              should render the JSON diagnostics coming from rustc. Cargo’s\n              own JSON diagnostics and others coming from rustc are still\n              emitted. Cannot be used with human or short.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\n   Miscellaneous Options\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       --keep-going\n           Build as many crates in the dependency graph as possible, rather\n           than aborting the build on the first one that fails to build.\n\n           For example if the current package depends on dependencies fails and\n           works, one of which fails to build, cargo run -j1 may or may not\n           build the one that succeeds (depending on which one of the two\n           builds Cargo picked to run first), whereas cargo run -j1\n           --keep-going would definitely run both builds, even if the one run\n           first fails.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Build the local package and run its main target (assuming only one\n          binary):\n\n              cargo run\n\n       2. Run an example with extra arguments:\n\n              cargo run --example exname -- --exoption exarg1 exarg2\n\nSEE ALSO\n       cargo(1), cargo-build(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-rustc.txt",
    "content": "CARGO-RUSTC(1)\n\nNAME\n       cargo-rustc — Compile the current package, and pass extra options to\n       the compiler\n\nSYNOPSIS\n       cargo rustc [options] [-- args]\n\nDESCRIPTION\n       The specified target for the current package (or package specified by -p\n       if provided) will be compiled along with all of its dependencies. The\n       specified args will all be passed to the final compiler invocation, not\n       any of the dependencies. Note that the compiler will still\n       unconditionally receive arguments such as -L, --extern, and\n       --crate-type, and the specified args will simply be added to the\n       compiler invocation.\n\n       See <https://doc.rust-lang.org/rustc/index.html> for documentation on\n       rustc flags.\n\n       This command requires that only one target is being compiled when\n       additional arguments are provided. If more than one target is available\n       for the current package the filters of --lib, --bin, etc, must be used\n       to select which target is compiled.\n\n       To pass flags to all compiler processes spawned by Cargo, use the\n       RUSTFLAGS environment variable\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       or the build.rustflags config value\n       <https://doc.rust-lang.org/cargo/reference/config.html>.\n\nOPTIONS\n   Package Selection\n       By default, the package in the current working directory is selected.\n       The -p flag can be used to choose a different package in a workspace.\n\n       -p spec, --package spec\n           The package to build. See cargo-pkgid(1) for the SPEC format.\n\n   Target Selection\n       When no target selection options are given, cargo rustc will build all\n       binary and library targets of the selected package.\n\n       Binary targets are automatically built if there is an integration test\n       or benchmark being selected to build. This allows an integration test to\n       execute the binary to exercise and test its behavior. The\n       CARGO_BIN_EXE_<name> environment variable\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates>\n       is set when the integration test is built and run so that it can use the\n       env macro <https://doc.rust-lang.org/std/macro.env.html> or the var\n       function <https://doc.rust-lang.org/std/env/fn.var.html> to locate the\n       executable.\n\n       Passing target selection flags will build only the specified targets.\n\n       Note that --bin, --example, --test and --bench flags also support common\n       Unix glob patterns like *, ? and []. However, to avoid your shell\n       accidentally expanding glob patterns before Cargo handles them, you must\n       use single quotes or double quotes around each glob pattern.\n\n       --lib\n           Build the package’s library.\n\n       --bin name…\n           Build the specified binary. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --bins\n           Build all binary targets.\n\n       --example name…\n           Build the specified example. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --examples\n           Build all example targets.\n\n       --test name…\n           Build the specified integration test. This flag may be specified\n           multiple times and supports common Unix glob patterns.\n\n       --tests\n           Build all targets that have the test = true manifest flag set. By\n           default this includes the library and binaries built as unittests,\n           and integration tests. Be aware that this will also build any\n           required dependencies, so the lib target may be built twice (once as\n           a unittest, and once as a dependency for binaries, integration\n           tests, etc.). Targets may be enabled or disabled by setting the test\n           flag in the manifest settings for the target.\n\n       --bench name…\n           Build the specified benchmark. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --benches\n           Build all targets that have the bench = true manifest flag set. By\n           default this includes the library and binaries built as benchmarks,\n           and bench targets. Be aware that this will also build any required\n           dependencies, so the lib target may be built twice (once as a\n           benchmark, and once as a dependency for binaries, benchmarks, etc.).\n           Targets may be enabled or disabled by setting the bench flag in the\n           manifest settings for the target.\n\n       --all-targets\n           Build all targets. This is equivalent to specifying --lib --bins\n           --tests --benches --examples.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Compilation Options\n       --target triple\n           Build for the specified target architecture. Flag may be specified\n           multiple times. The default is the host architecture. The general\n           format of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       -r, --release\n           Build optimized artifacts with the release profile. See also the\n           --profile option for choosing a specific profile by name.\n\n       --profile name\n           Build with the given profile.\n\n           The rustc subcommand will treat the following named profiles with\n           special behaviors:\n\n           o  check — Builds in the same way as the cargo-check(1) command\n              with the dev profile.\n\n           o  test — Builds in the same way as the cargo-test(1) command,\n              enabling building in test mode which will enable tests and enable\n              the test cfg option. See rustc tests\n              <https://doc.rust-lang.org/rustc/tests/index.html> for more\n              detail.\n\n           o  bench — Builds in the same was as the cargo-bench(1) command,\n              similar to the test profile.\n\n           See the reference\n           <https://doc.rust-lang.org/cargo/reference/profiles.html> for more\n           details on profiles.\n\n       --timings\n           Output information how long each compilation takes, and track\n           concurrency information over time.\n\n           A file cargo-timing.html will be written to the target/cargo-timings\n           directory at the end of the build. An additional report with a\n           timestamp in its filename is also written if you want to look at a\n           previous run. These reports are suitable for human consumption only,\n           and do not provide machine-readable timing data.\n\n       --crate-type crate-type\n           Build for the given crate type. This flag accepts a comma-separated\n           list of 1 or more crate types, of which the allowed values are the\n           same as crate-type field in the manifest for configuring a Cargo\n           target. See crate-type field\n           <https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-crate-type-field>\n           for possible values.\n\n           If the manifest contains a list, and --crate-type is provided, the\n           command-line argument value will override what is in the manifest.\n\n           This flag only works when building a lib or example library target.\n\n   Output Options\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --message-format fmt\n           The output format for diagnostic messages. Can be specified multiple\n           times and consists of comma-separated values. Valid values:\n\n           o  human (default): Display in a human-readable text format.\n              Conflicts with short and json.\n\n           o  short: Emit shorter, human-readable text messages. Conflicts with\n              human and json.\n\n           o  json: Emit JSON messages to stdout. See the reference\n              <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n              for more details. Conflicts with human and short.\n\n           o  json-diagnostic-short: Ensure the rendered field of JSON messages\n              contains the “short” rendering from rustc. Cannot be used\n              with human or short.\n\n           o  json-diagnostic-rendered-ansi: Ensure the rendered field of JSON\n              messages contains embedded ANSI color codes for respecting\n              rustc’s default color scheme. Cannot be used with human or\n              short.\n\n           o  json-render-diagnostics: Instruct Cargo to not include rustc\n              diagnostics in JSON messages printed, but instead Cargo itself\n              should render the JSON diagnostics coming from rustc. Cargo’s\n              own JSON diagnostics and others coming from rustc are still\n              emitted. Cannot be used with human or short.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\n   Miscellaneous Options\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       --keep-going\n           Build as many crates in the dependency graph as possible, rather\n           than aborting the build on the first one that fails to build.\n\n           For example if the current package depends on dependencies fails and\n           works, one of which fails to build, cargo rustc -j1 may or may not\n           build the one that succeeds (depending on which one of the two\n           builds Cargo picked to run first), whereas cargo rustc -j1\n           --keep-going would definitely run both builds, even if the one run\n           first fails.\n\n       --future-incompat-report\n           Displays a future-incompat report for any future-incompatible\n           warnings produced during execution of this command\n\n           See cargo-report(1)\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Check if your package (not including dependencies) uses unsafe code:\n\n              cargo rustc --lib -- -D unsafe-code\n\n       2. Try an experimental flag on the nightly compiler, such as this which\n          prints the size of every type:\n\n              cargo rustc --lib -- -Z print-type-sizes\n\n       3. Override crate-type field in Cargo.toml with command-line option:\n\n              cargo rustc --lib --crate-type lib,cdylib\n\nSEE ALSO\n       cargo(1), cargo-build(1), rustc(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-rustdoc.txt",
    "content": "CARGO-RUSTDOC(1)\n\nNAME\n       cargo-rustdoc — Build a package’s documentation, using specified\n       custom flags\n\nSYNOPSIS\n       cargo rustdoc [options] [-- args]\n\nDESCRIPTION\n       The specified target for the current package (or package specified by -p\n       if provided) will be documented with the specified args being passed to\n       the final rustdoc invocation. Dependencies will not be documented as\n       part of this command. Note that rustdoc will still unconditionally\n       receive arguments such as -L, --extern, and --crate-type, and the\n       specified args will simply be added to the rustdoc invocation.\n\n       See <https://doc.rust-lang.org/rustdoc/index.html> for documentation on\n       rustdoc flags.\n\n       This command requires that only one target is being compiled when\n       additional arguments are provided. If more than one target is available\n       for the current package the filters of --lib, --bin, etc, must be used\n       to select which target is compiled.\n\n       To pass flags to all rustdoc processes spawned by Cargo, use the\n       RUSTDOCFLAGS environment variable\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       or the build.rustdocflags config value\n       <https://doc.rust-lang.org/cargo/reference/config.html>.\n\nOPTIONS\n   Documentation Options\n       --open\n           Open the docs in a browser after building them. This will use your\n           default browser unless you define another one in the BROWSER\n           environment variable or use the doc.browser\n           <https://doc.rust-lang.org/cargo/reference/config.html#docbrowser>\n           configuration option.\n\n   Package Selection\n       By default, the package in the current working directory is selected.\n       The -p flag can be used to choose a different package in a workspace.\n\n       -p spec, --package spec\n           The package to document. See cargo-pkgid(1) for the SPEC format.\n\n   Target Selection\n       When no target selection options are given, cargo rustdoc will document\n       all binary and library targets of the selected package. The binary will\n       be skipped if its name is the same as the lib target. Binaries are\n       skipped if they have required-features that are missing.\n\n       Passing target selection flags will document only the specified targets.\n\n       Note that --bin, --example, --test and --bench flags also support common\n       Unix glob patterns like *, ? and []. However, to avoid your shell\n       accidentally expanding glob patterns before Cargo handles them, you must\n       use single quotes or double quotes around each glob pattern.\n\n       --lib\n           Document the package’s library.\n\n       --bin name…\n           Document the specified binary. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --bins\n           Document all binary targets.\n\n       --example name…\n           Document the specified example. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --examples\n           Document all example targets.\n\n       --test name…\n           Document the specified integration test. This flag may be specified\n           multiple times and supports common Unix glob patterns.\n\n       --tests\n           Document all targets that have the test = true manifest flag set. By\n           default this includes the library and binaries built as unittests,\n           and integration tests. Be aware that this will also build any\n           required dependencies, so the lib target may be built twice (once as\n           a unittest, and once as a dependency for binaries, integration\n           tests, etc.). Targets may be enabled or disabled by setting the test\n           flag in the manifest settings for the target.\n\n       --bench name…\n           Document the specified benchmark. This flag may be specified\n           multiple times and supports common Unix glob patterns.\n\n       --benches\n           Document all targets that have the bench = true manifest flag set.\n           By default this includes the library and binaries built as\n           benchmarks, and bench targets. Be aware that this will also build\n           any required dependencies, so the lib target may be built twice\n           (once as a benchmark, and once as a dependency for binaries,\n           benchmarks, etc.). Targets may be enabled or disabled by setting the\n           bench flag in the manifest settings for the target.\n\n       --all-targets\n           Document all targets. This is equivalent to specifying --lib --bins\n           --tests --benches --examples.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Compilation Options\n       --target triple\n           Document for the specified target architecture. Flag may be\n           specified multiple times. The default is the host architecture. The\n           general format of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       -r, --release\n           Document optimized artifacts with the release profile. See also the\n           --profile option for choosing a specific profile by name.\n\n       --profile name\n           Document with the given profile. See the reference\n           <https://doc.rust-lang.org/cargo/reference/profiles.html> for more\n           details on profiles.\n\n       --timings\n           Output information how long each compilation takes, and track\n           concurrency information over time.\n\n           A file cargo-timing.html will be written to the target/cargo-timings\n           directory at the end of the build. An additional report with a\n           timestamp in its filename is also written if you want to look at a\n           previous run. These reports are suitable for human consumption only,\n           and do not provide machine-readable timing data.\n\n   Output Options\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --message-format fmt\n           The output format for diagnostic messages. Can be specified multiple\n           times and consists of comma-separated values. Valid values:\n\n           o  human (default): Display in a human-readable text format.\n              Conflicts with short and json.\n\n           o  short: Emit shorter, human-readable text messages. Conflicts with\n              human and json.\n\n           o  json: Emit JSON messages to stdout. See the reference\n              <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n              for more details. Conflicts with human and short.\n\n           o  json-diagnostic-short: Ensure the rendered field of JSON messages\n              contains the “short” rendering from rustc. Cannot be used\n              with human or short.\n\n           o  json-diagnostic-rendered-ansi: Ensure the rendered field of JSON\n              messages contains embedded ANSI color codes for respecting\n              rustc’s default color scheme. Cannot be used with human or\n              short.\n\n           o  json-render-diagnostics: Instruct Cargo to not include rustc\n              diagnostics in JSON messages printed, but instead Cargo itself\n              should render the JSON diagnostics coming from rustc. Cargo’s\n              own JSON diagnostics and others coming from rustc are still\n              emitted. Cannot be used with human or short.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\n   Miscellaneous Options\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       --keep-going\n           Build as many crates in the dependency graph as possible, rather\n           than aborting the build on the first one that fails to build.\n\n           For example if the current package depends on dependencies fails and\n           works, one of which fails to build, cargo rustdoc -j1 may or may not\n           build the one that succeeds (depending on which one of the two\n           builds Cargo picked to run first), whereas cargo rustdoc -j1\n           --keep-going would definitely run both builds, even if the one run\n           first fails.\n\n       --output-format\n           The output type for the documentation emitted. Valid values:\n\n           o  html (default): Emit the documentation in HTML format.\n\n           o  json: Emit the documentation in the experimental JSON format\n              <https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types>.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Build documentation with custom CSS included from a given file:\n\n              cargo rustdoc --lib -- --extend-css extra.css\n\nSEE ALSO\n       cargo(1), cargo-doc(1), rustdoc(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-search.txt",
    "content": "CARGO-SEARCH(1)\n\nNAME\n       cargo-search — Search packages in the registry. Default registry is\n       crates.io\n\nSYNOPSIS\n       cargo search [options] [query…]\n\nDESCRIPTION\n       This performs a textual search for crates on <https://crates.io>. The\n       matching crates will be displayed along with their description in TOML\n       format suitable for copying into a Cargo.toml manifest.\n\nOPTIONS\n   Search Options\n       --limit limit\n           Limit the number of results (default: 10, max: 100).\n\n       --index index\n           The URL of the registry index to use.\n\n       --registry registry\n           Name of the registry to use. Registry names are defined in Cargo\n           config files\n           <https://doc.rust-lang.org/cargo/reference/config.html>. If not\n           specified, the default registry is used, which is defined by the\n           registry.default config key which defaults to crates-io.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Search for a package from crates.io:\n\n              cargo search serde\n\nSEE ALSO\n       cargo(1), cargo-install(1), cargo-publish(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-test.txt",
    "content": "CARGO-TEST(1)\n\nNAME\n       cargo-test — Execute unit and integration tests of a package\n\nSYNOPSIS\n       cargo test [options] [testname] [-- test-options]\n\nDESCRIPTION\n       Compile and execute unit, integration, and documentation tests.\n\n       The test filtering argument TESTNAME and all the arguments following the\n       two dashes (--) are passed to the test binaries and thus to libtest\n       (rustc’s built in unit-test and micro-benchmarking framework). If\n       you’re passing arguments to both Cargo and the binary, the ones after\n       -- go to the binary, the ones before go to Cargo. For details about\n       libtest’s arguments see the output of cargo test -- --help and check\n       out the rustc book’s chapter on how tests work at\n       <https://doc.rust-lang.org/rustc/tests/index.html>.\n\n       As an example, this will filter for tests with foo in their name and run\n       them on 3 threads in parallel:\n\n           cargo test foo -- --test-threads 3\n\n       Tests are built with the --test option to rustc which creates a special\n       executable by linking your code with libtest. The executable\n       automatically runs all functions annotated with the #[test] attribute in\n       multiple threads. #[bench] annotated functions will also be run with one\n       iteration to verify that they are functional.\n\n       If the package contains multiple test targets, each target compiles to a\n       special executable as aforementioned, and then is run serially.\n\n       The libtest harness may be disabled by setting harness = false in the\n       target manifest settings, in which case your code will need to provide\n       its own main function to handle running tests.\n\n   Documentation tests\n       Documentation tests are also run by default, which is handled by\n       rustdoc. It extracts code samples from documentation comments of the\n       library target, and then executes them.\n\n       Different from normal test targets, each code block compiles to a\n       doctest executable on the fly with rustc. These executables run in\n       parallel in separate processes. The compilation of a code block is in\n       fact a part of test function controlled by libtest, so some options such\n       as --jobs might not take effect. Note that this execution model of\n       doctests is not guaranteed and may change in the future; beware of\n       depending on it.\n\n       See the rustdoc book <https://doc.rust-lang.org/rustdoc/> for more\n       information on writing doc tests.\n\n   Working directory of tests\n       The working directory when running each unit and integration test is set\n       to the root directory of the package the test belongs to. Setting the\n       working directory of tests to the package’s root directory makes it\n       possible for tests to reliably access the package’s files using\n       relative paths, regardless from where cargo test was executed from.\n\n       For documentation tests, the working directory when invoking rustdoc is\n       set to the workspace root directory, and is also the directory rustdoc\n       uses as the compilation directory of each documentation test. The\n       working directory when running each documentation test is set to the\n       root directory of the package the test belongs to, and is controlled via\n       rustdoc’s --test-run-directory option.\n\nOPTIONS\n   Test Options\n       --no-run\n           Compile, but don’t run tests.\n\n       --no-fail-fast\n           Run all tests regardless of failure. Without this flag, Cargo will\n           exit after the first executable fails. The Rust test harness will\n           run all tests within the executable to completion, this flag only\n           applies to the executable as a whole.\n\n   Package Selection\n       By default, when no package selection options are given, the packages\n       selected depend on the selected manifest file (based on the current\n       working directory if --manifest-path is not given). If the manifest is\n       the root of a workspace then the workspaces default members are\n       selected, otherwise only the package defined by the manifest will be\n       selected.\n\n       The default members of a workspace can be set explicitly with the\n       workspace.default-members key in the root manifest. If this is not set,\n       a virtual workspace will include all workspace members (equivalent to\n       passing --workspace), and a non-virtual workspace will include only the\n       root crate itself.\n\n       -p spec…, --package spec…\n           Test only the specified packages. See cargo-pkgid(1) for the SPEC\n           format. This flag may be specified multiple times and supports\n           common Unix glob patterns like *, ? and []. However, to avoid your\n           shell accidentally expanding glob patterns before Cargo handles\n           them, you must use single quotes or double quotes around each\n           pattern.\n\n       --workspace\n           Test all members in the workspace.\n\n       --all\n           Deprecated alias for --workspace.\n\n       --exclude SPEC…\n           Exclude the specified packages. Must be used in conjunction with the\n           --workspace flag. This flag may be specified multiple times and\n           supports common Unix glob patterns like *, ? and []. However, to\n           avoid your shell accidentally expanding glob patterns before Cargo\n           handles them, you must use single quotes or double quotes around\n           each pattern.\n\n   Target Selection\n       When no target selection options are given, cargo test will build the\n       following targets of the selected packages:\n\n       o  lib — used to link with binaries, examples, integration tests, and\n          doc tests\n\n       o  bins (only if integration tests are built and required features are\n          available)\n\n       o  examples — to ensure they compile\n\n       o  lib as a unit test\n\n       o  bins as unit tests\n\n       o  integration tests\n\n       o  doc tests for the lib target\n\n       The default behavior can be changed by setting the test flag for the\n       target in the manifest settings. Setting examples to test = true will\n       build and run the example as a test, replacing the example’s main\n       function with the libtest harness. If you don’t want the main function\n       replaced, also include harness = false, in which case the example will\n       be built and executed as-is.\n\n       Setting targets to test = false will stop them from being tested by\n       default. Target selection options that take a target by name (such as\n       --example foo) ignore the test flag and will always test the given\n       target.\n\n       Doc tests for libraries may be disabled by setting doctest = false for\n       the library in the manifest.\n\n       See Configuring a target\n       <https://doc.rust-lang.org/cargo/reference/cargo-targets.html#configuring-a-target>\n       for more information on per-target settings.\n\n       Binary targets are automatically built if there is an integration test\n       or benchmark being selected to test. This allows an integration test to\n       execute the binary to exercise and test its behavior. The\n       CARGO_BIN_EXE_<name> environment variable\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates>\n       is set when the integration test is built and run so that it can use the\n       env macro <https://doc.rust-lang.org/std/macro.env.html> or the var\n       function <https://doc.rust-lang.org/std/env/fn.var.html> to locate the\n       executable.\n\n       Passing target selection flags will test only the specified targets.\n\n       Note that --bin, --example, --test and --bench flags also support common\n       Unix glob patterns like *, ? and []. However, to avoid your shell\n       accidentally expanding glob patterns before Cargo handles them, you must\n       use single quotes or double quotes around each glob pattern.\n\n       --lib\n           Test the package’s library.\n\n       --bin name…\n           Test the specified binary. This flag may be specified multiple times\n           and supports common Unix glob patterns.\n\n       --bins\n           Test all binary targets.\n\n       --example name…\n           Test the specified example. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --examples\n           Test all example targets.\n\n       --test name…\n           Test the specified integration test. This flag may be specified\n           multiple times and supports common Unix glob patterns.\n\n       --tests\n           Test all targets that have the test = true manifest flag set. By\n           default this includes the library and binaries built as unittests,\n           and integration tests. Be aware that this will also build any\n           required dependencies, so the lib target may be built twice (once as\n           a unittest, and once as a dependency for binaries, integration\n           tests, etc.). Targets may be enabled or disabled by setting the test\n           flag in the manifest settings for the target.\n\n       --bench name…\n           Test the specified benchmark. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --benches\n           Test all targets that have the bench = true manifest flag set. By\n           default this includes the library and binaries built as benchmarks,\n           and bench targets. Be aware that this will also build any required\n           dependencies, so the lib target may be built twice (once as a\n           benchmark, and once as a dependency for binaries, benchmarks, etc.).\n           Targets may be enabled or disabled by setting the bench flag in the\n           manifest settings for the target.\n\n       --all-targets\n           Test all targets. This is equivalent to specifying --lib --bins\n           --tests --benches --examples.\n\n       --doc\n           Test only the library’s documentation. This cannot be mixed with\n           other target options.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Compilation Options\n       --target triple\n           Test for the specified target architecture. Flag may be specified\n           multiple times. The default is the host architecture. The general\n           format of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       -r, --release\n           Test optimized artifacts with the release profile. See also the\n           --profile option for choosing a specific profile by name.\n\n       --profile name\n           Test with the given profile. See the reference\n           <https://doc.rust-lang.org/cargo/reference/profiles.html> for more\n           details on profiles.\n\n       --timings\n           Output information how long each compilation takes, and track\n           concurrency information over time.\n\n           A file cargo-timing.html will be written to the target/cargo-timings\n           directory at the end of the build. An additional report with a\n           timestamp in its filename is also written if you want to look at a\n           previous run. These reports are suitable for human consumption only,\n           and do not provide machine-readable timing data.\n\n   Output Options\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n   Display Options\n       By default the Rust test harness hides output from test execution to\n       keep results readable. Test output can be recovered (e.g., for\n       debugging) by passing --no-capture to the test binaries:\n\n           cargo test -- --no-capture\n\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --message-format fmt\n           The output format for diagnostic messages. Can be specified multiple\n           times and consists of comma-separated values. Valid values:\n\n           o  human (default): Display in a human-readable text format.\n              Conflicts with short and json.\n\n           o  short: Emit shorter, human-readable text messages. Conflicts with\n              human and json.\n\n           o  json: Emit JSON messages to stdout. See the reference\n              <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n              for more details. Conflicts with human and short.\n\n           o  json-diagnostic-short: Ensure the rendered field of JSON messages\n              contains the “short” rendering from rustc. Cannot be used\n              with human or short.\n\n           o  json-diagnostic-rendered-ansi: Ensure the rendered field of JSON\n              messages contains embedded ANSI color codes for respecting\n              rustc’s default color scheme. Cannot be used with human or\n              short.\n\n           o  json-render-diagnostics: Instruct Cargo to not include rustc\n              diagnostics in JSON messages printed, but instead Cargo itself\n              should render the JSON diagnostics coming from rustc. Cargo’s\n              own JSON diagnostics and others coming from rustc are still\n              emitted. Cannot be used with human or short.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\n   Miscellaneous Options\n       The --jobs argument affects the building of the test executable but does\n       not affect how many threads are used when running the tests. The Rust\n       test harness includes an option to control the number of threads used:\n\n           cargo test -j 2 -- --test-threads=2\n\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       --future-incompat-report\n           Displays a future-incompat report for any future-incompatible\n           warnings produced during execution of this command\n\n           See cargo-report(1)\n\n       While cargo test involves compilation, it does not provide a\n       --keep-going flag. Use --no-fail-fast to run as many tests as possible\n       without stopping at the first failure. To “compile” as many tests as\n       possible, use --tests to build test binaries separately. For example:\n\n           cargo build --tests --keep-going\n           cargo test --tests --no-fail-fast\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Execute all the unit and integration tests of the current package:\n\n              cargo test\n\n       2. Run only tests whose names match against a filter string:\n\n              cargo test name_filter\n\n       3. Run only a specific test within a specific integration test:\n\n              cargo test --test int_test_name -- modname::test_name\n\nSEE ALSO\n       cargo(1), cargo-bench(1), types of tests\n       <https://doc.rust-lang.org/cargo/reference/cargo-targets.html#tests>,\n       how to write tests <https://doc.rust-lang.org/rustc/tests/index.html>\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-tree.txt",
    "content": "CARGO-TREE(1)\n\nNAME\n       cargo-tree — Display a tree visualization of a dependency graph\n\nSYNOPSIS\n       cargo tree [options]\n\nDESCRIPTION\n       This command will display a tree of dependencies to the terminal. An\n       example of a simple project that depends on the “rand” package:\n\n           myproject v0.1.0 (/myproject)\n           └── rand v0.7.3\n               ├── getrandom v0.1.14\n               │   ├── cfg-if v0.1.10\n               │   └── libc v0.2.68\n               ├── libc v0.2.68 (*)\n               ├── rand_chacha v0.2.2\n               │   ├── ppv-lite86 v0.2.6\n               │   └── rand_core v0.5.1\n               │       └── getrandom v0.1.14 (*)\n               └── rand_core v0.5.1 (*)\n           [build-dependencies]\n           └── cc v1.0.50\n\n       Packages marked with (*) have been “de-duplicated”. The dependencies\n       for the package have already been shown elsewhere in the graph, and so\n       are not repeated. Use the --no-dedupe option to repeat the duplicates.\n\n       The -e flag can be used to select the dependency kinds to display. The\n       “features” kind changes the output to display the features enabled\n       by each dependency. For example, cargo tree -e features:\n\n           myproject v0.1.0 (/myproject)\n           └── log feature \"serde\"\n               └── log v0.4.8\n                   ├── serde v1.0.106\n                   └── cfg-if feature \"default\"\n                       └── cfg-if v0.1.10\n\n       In this tree, myproject depends on log with the serde feature. log in\n       turn depends on cfg-if with “default” features. When using -e\n       features it can be helpful to use -i flag to show how the features flow\n       into a package. See the examples below for more detail.\n\n   Feature Unification\n       This command shows a graph much closer to a feature-unified graph Cargo\n       will build, rather than what you list in Cargo.toml. For instance, if\n       you specify the same dependency in both [dependencies] and\n       [dev-dependencies] but with different features on. This command may\n       merge all features and show a (*) on one of the dependency to indicate\n       the duplicate.\n\n       As a result, for a mostly equivalent overview of what cargo build does,\n       cargo tree -e normal,build is pretty close; for a mostly equivalent\n       overview of what cargo test does, cargo tree is pretty close. However,\n       it doesn’t guarantee the exact equivalence to what Cargo is going to\n       build, since a compilation is complex and depends on lots of different\n       factors.\n\n       To learn more about feature unification, check out this dedicated\n       section\n       <https://doc.rust-lang.org/cargo/reference/features.html#feature-unification>.\n\nOPTIONS\n   Tree Options\n       -i spec, --invert spec\n           Show the reverse dependencies for the given package. This flag will\n           invert the tree and display the packages that depend on the given\n           package.\n\n           Note that in a workspace, by default it will only display the\n           package’s reverse dependencies inside the tree of the workspace\n           member in the current directory. The --workspace flag can be used to\n           extend it so that it will show the package’s reverse dependencies\n           across the entire workspace. The -p flag can be used to display the\n           package’s reverse dependencies only with the subtree of the\n           package given to -p.\n\n       --prune spec\n           Prune the given package from the display of the dependency tree.\n\n       --depth depth\n           Maximum display depth of the dependency tree. A depth of 1 displays\n           the direct dependencies, for example.\n\n           If the given value is workspace, only shows the dependencies that\n           are member of the current workspace, instead.\n\n       --no-dedupe\n           Do not de-duplicate repeated dependencies. Usually, when a package\n           has already displayed its dependencies, further occurrences will not\n           re-display its dependencies, and will include a (*) to indicate it\n           has already been shown. This flag will cause those duplicates to be\n           repeated.\n\n       -d, --duplicates\n           Show only dependencies which come in multiple versions (implies\n           --invert). When used with the -p flag, only shows duplicates within\n           the subtree of the given package.\n\n           It can be beneficial for build times and executable sizes to avoid\n           building that same package multiple times. This flag can help\n           identify the offending packages. You can then investigate if the\n           package that depends on the duplicate with the older version can be\n           updated to the newer version so that only one instance is built.\n\n       -e kinds, --edges kinds\n           The dependency kinds to display. Takes a comma separated list of\n           values:\n\n           o  all — Show all edge kinds.\n\n           o  normal — Show normal dependencies.\n\n           o  build — Show build dependencies.\n\n           o  dev — Show development dependencies.\n\n           o  features — Show features enabled by each dependency. If this is\n              the only kind given, then it will automatically include the other\n              dependency kinds.\n\n           o  no-normal — Do not include normal dependencies.\n\n           o  no-build — Do not include build dependencies.\n\n           o  no-dev — Do not include development dependencies.\n\n           o  no-proc-macro — Do not include procedural macro dependencies.\n\n           The normal, build, dev, and all dependency kinds cannot be mixed\n           with no-normal, no-build, or no-dev dependency kinds.\n\n           The default is normal,build,dev.\n\n       --target triple\n           Filter dependencies matching the given target triple\n           <https://doc.rust-lang.org/cargo/appendix/glossary.html#target>. The\n           default is the host platform. Use the value all to include all\n           targets.\n\n   Tree Formatting Options\n       --charset charset\n           Chooses the character set to use for the tree. Valid values are\n           “utf8” or “ascii”. When unspecified, cargo will auto-select\n           a value.\n\n       -f format, --format format\n           Set the format string for each package. The default is “{p}”.\n\n           This is an arbitrary string which will be used to display each\n           package. The following strings will be replaced with the\n           corresponding value:\n\n           o  {p}, {package} — The package name.\n\n           o  {l}, {license} — The package license.\n\n           o  {r}, {repository} — The package repository URL.\n\n           o  {f}, {features} — Comma-separated list of package features that\n              are enabled.\n\n           o  {lib} — The name, as used in a use statement, of the\n              package’s library.\n\n       --prefix prefix\n           Sets how each line is displayed. The prefix value can be one of:\n\n           o  indent (default) — Shows each line indented as a tree.\n\n           o  depth — Show as a list, with the numeric depth printed before\n              each entry.\n\n           o  none — Show as a flat list.\n\n   Package Selection\n       By default, when no package selection options are given, the packages\n       selected depend on the selected manifest file (based on the current\n       working directory if --manifest-path is not given). If the manifest is\n       the root of a workspace then the workspaces default members are\n       selected, otherwise only the package defined by the manifest will be\n       selected.\n\n       The default members of a workspace can be set explicitly with the\n       workspace.default-members key in the root manifest. If this is not set,\n       a virtual workspace will include all workspace members (equivalent to\n       passing --workspace), and a non-virtual workspace will include only the\n       root crate itself.\n\n       -p spec…, --package spec…\n           Display only the specified packages. See cargo-pkgid(1) for the SPEC\n           format. This flag may be specified multiple times and supports\n           common Unix glob patterns like *, ? and []. However, to avoid your\n           shell accidentally expanding glob patterns before Cargo handles\n           them, you must use single quotes or double quotes around each\n           pattern.\n\n       --workspace\n           Display all members in the workspace.\n\n       --exclude SPEC…\n           Exclude the specified packages. Must be used in conjunction with the\n           --workspace flag. This flag may be specified multiple times and\n           supports common Unix glob patterns like *, ? and []. However, to\n           avoid your shell accidentally expanding glob patterns before Cargo\n           handles them, you must use single quotes or double quotes around\n           each pattern.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Display the tree for the package in the current directory:\n\n              cargo tree\n\n       2. Display all the packages that depend on the syn package:\n\n              cargo tree -i syn\n\n       3. Show the features enabled on each package:\n\n              cargo tree --format \"{p} {f}\"\n\n       4. Show all packages that are built multiple times. This can happen if\n          multiple semver-incompatible versions appear in the tree (like 1.0.0\n          and 2.0.0).\n\n              cargo tree -d\n\n       5. Explain why features are enabled for the syn package:\n\n              cargo tree -e features -i syn\n\n          The -e features flag is used to show features. The -i flag is used to\n          invert the graph so that it displays the packages that depend on syn.\n          An example of what this would display:\n\n              syn v1.0.17\n              ├── syn feature \"clone-impls\"\n              │   └── syn feature \"default\"\n              │       └── rustversion v1.0.2\n              │           └── rustversion feature \"default\"\n              │               └── myproject v0.1.0 (/myproject)\n              │                   └── myproject feature \"default\" (command-line)\n              ├── syn feature \"default\" (*)\n              ├── syn feature \"derive\"\n              │   └── syn feature \"default\" (*)\n              ├── syn feature \"full\"\n              │   └── rustversion v1.0.2 (*)\n              ├── syn feature \"parsing\"\n              │   └── syn feature \"default\" (*)\n              ├── syn feature \"printing\"\n              │   └── syn feature \"default\" (*)\n              ├── syn feature \"proc-macro\"\n              │   └── syn feature \"default\" (*)\n              └── syn feature \"quote\"\n                  ├── syn feature \"printing\" (*)\n                  └── syn feature \"proc-macro\" (*)\n\n          To read this graph, you can follow the chain for each feature from\n          the root to see why it is included. For example, the “full”\n          feature is added by the rustversion crate which is included from\n          myproject (with the default features), and myproject is the package\n          selected on the command-line. All of the other syn features are added\n          by the “default” feature (“quote” is added by “printing”\n          and “proc-macro”, both of which are default features).\n\n          If you’re having difficulty cross-referencing the de-duplicated (*)\n          entries, try with the --no-dedupe flag to get the full output.\n\nSEE ALSO\n       cargo(1), cargo-metadata(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-uninstall.txt",
    "content": "CARGO-UNINSTALL(1)\n\nNAME\n       cargo-uninstall — Remove a Rust binary\n\nSYNOPSIS\n       cargo uninstall [options] [spec…]\n\nDESCRIPTION\n       This command removes a package installed with cargo-install(1). The spec\n       argument is a package ID specification of the package to remove (see\n       cargo-pkgid(1)).\n\n       By default all binaries are removed for a crate but the --bin and\n       --example flags can be used to only remove particular binaries.\n\n       The installation root is determined, in order of precedence:\n\n       o  --root option\n\n       o  CARGO_INSTALL_ROOT environment variable\n\n       o  install.root Cargo config value\n          <https://doc.rust-lang.org/cargo/reference/config.html>\n\n       o  CARGO_HOME environment variable\n\n       o  $HOME/.cargo\n\nOPTIONS\n   Uninstall Options\n       -p, --package spec…\n           Package to uninstall.\n\n       --bin name…\n           Only uninstall the binary name.\n\n       --root dir\n           Directory to uninstall packages from.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Uninstall a previously installed package.\n\n              cargo uninstall ripgrep\n\nSEE ALSO\n       cargo(1), cargo-install(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-update.txt",
    "content": "CARGO-UPDATE(1)\n\nNAME\n       cargo-update — Update dependencies as recorded in the local lock file\n\nSYNOPSIS\n       cargo update [options] spec\n\nDESCRIPTION\n       This command will update dependencies in the Cargo.lock file to the\n       latest version. If the Cargo.lock file does not exist, it will be\n       created with the latest available versions.\n\nOPTIONS\n   Update Options\n       spec…\n           Update only the specified packages. This flag may be specified\n           multiple times. See cargo-pkgid(1) for the SPEC format.\n\n           If packages are specified with spec, then a conservative update of\n           the lockfile will be performed. This means that only the dependency\n           specified by SPEC will be updated. Its transitive dependencies will\n           be updated only if SPEC cannot be updated without updating\n           dependencies. All other dependencies will remain locked at their\n           currently recorded versions.\n\n           If spec is not specified, all dependencies are updated.\n\n       --recursive\n           When used with spec, dependencies of spec are forced to update as\n           well. Cannot be used with --precise.\n\n       --precise precise\n           When used with spec, allows you to specify a specific version number\n           to set the package to. If the package comes from a git repository,\n           this can be a git revision (such as a SHA hash or tag).\n\n           While not recommended, you can specify a yanked version of a\n           package. When possible, try other non-yanked SemVer-compatible\n           versions or seek help from the maintainers of the package.\n\n           A compatible pre-release version can also be specified even when the\n           version requirement in Cargo.toml doesn’t contain any pre-release\n           identifier (nightly only).\n\n       --breaking directory\n           Update spec to latest SemVer-breaking version.\n\n           Version requirements will be modified to allow this update.\n\n           This only applies to dependencies when\n\n           o  The package is a dependency of a workspace member\n\n           o  The dependency is not renamed\n\n           o  A SemVer-incompatible version is available\n\n           o  The “SemVer operator” is used (^ which is the default)\n\n           This option is unstable and available only on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable. See\n           <https://github.com/rust-lang/cargo/issues/12425> for more\n           information.\n\n       -w, --workspace\n           Attempt to update only packages defined in the workspace. Other\n           packages are updated only if they don’t already exist in the\n           lockfile. This option is useful for updating Cargo.lock after\n           you’ve changed version numbers in Cargo.toml.\n\n       --dry-run\n           Displays what would be updated, but doesn’t actually write the\n           lockfile.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Update all dependencies in the lockfile:\n\n              cargo update\n\n       2. Update only specific dependencies:\n\n              cargo update foo bar\n\n       3. Set a specific dependency to a specific version:\n\n              cargo update foo --precise 1.2.3\n\nSEE ALSO\n       cargo(1), cargo-generate-lockfile(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-vendor.txt",
    "content": "CARGO-VENDOR(1)\n\nNAME\n       cargo-vendor — Vendor all dependencies locally\n\nSYNOPSIS\n       cargo vendor [options] [path]\n\nDESCRIPTION\n       This cargo subcommand will vendor all crates.io and git dependencies for\n       a project into the specified directory at <path>. After this command\n       completes the vendor directory specified by <path> will contain all\n       remote sources from dependencies specified. Additional manifests beyond\n       the default one can be specified with the -s option.\n\n       The configuration necessary to use the vendored sources would be printed\n       to stdout after cargo vendor completes the vendoring process. You will\n       need to add or redirect it to your Cargo configuration file, which is\n       usually .cargo/config.toml locally for the current package.\n\n       Cargo treats vendored sources as read-only as it does to registry and\n       git sources. If you intend to modify a crate from a remote source, use\n       [patch] or a path dependency pointing to a local copy of that crate.\n       Cargo will then correctly handle the crate on incremental rebuilds, as\n       it knows that it is no longer a read-only dependency.\n\nOPTIONS\n   Vendor Options\n       -s manifest, --sync manifest\n           Specify an extra Cargo.toml manifest to workspaces which should also\n           be vendored and synced to the output. May be specified multiple\n           times.\n\n       --no-delete\n           Don’t delete the “vendor” directory when vendoring, but rather\n           keep all existing contents of the vendor directory\n\n       --respect-source-config\n           Instead of ignoring [source] configuration by default in\n           .cargo/config.toml read it and use it when downloading crates from\n           crates.io, for example\n\n       --versioned-dirs\n           Normally versions are only added to disambiguate multiple versions\n           of the same package. This option causes all directories in the\n           “vendor” directory to be versioned, which makes it easier to\n           track the history of vendored packages over time, and can help with\n           the performance of re-vendoring when only a subset of the packages\n           have changed.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Vendor all dependencies into a local “vendor” folder\n\n              cargo vendor\n\n       2. Vendor all dependencies into a local “third-party/vendor” folder\n\n              cargo vendor third-party/vendor\n\n       3. Vendor the current workspace as well as another to “vendor”\n\n              cargo vendor -s ../path/to/Cargo.toml\n\n       4. Vendor and redirect the necessary vendor configs to a config file.\n\n              cargo vendor > path/to/my/cargo/config.toml\n\nSEE ALSO\n       cargo(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-version.txt",
    "content": "CARGO-VERSION(1)\n\nNAME\n       cargo-version — Show version information\n\nSYNOPSIS\n       cargo version [options]\n\nDESCRIPTION\n       Displays the version of Cargo.\n\nOPTIONS\n       -v, --verbose\n           Display additional version information.\n\nEXAMPLES\n       1. Display the version:\n\n              cargo version\n\n       2. The version is also available via flags:\n\n              cargo --version\n              cargo -V\n\n       3. Display extra version information:\n\n              cargo -Vv\n\nSEE ALSO\n       cargo(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo-yank.txt",
    "content": "CARGO-YANK(1)\n\nNAME\n       cargo-yank — Remove a pushed crate from the index\n\nSYNOPSIS\n       cargo yank [options] crate@version\n       cargo yank [options] --version version [crate]\n\nDESCRIPTION\n       The yank command removes a previously published crate’s version from\n       the server’s index. This command does not delete any data, and the\n       crate will still be available for download via the registry’s download\n       link.\n\n       Cargo will not use a yanked version for any new project or checkout\n       without a pre-existing lockfile, and will generate an error if there are\n       no longer any compatible versions for your crate.\n\n       This command requires you to be authenticated with either the --token\n       option or using cargo-login(1).\n\n       If the crate name is not specified, it will use the package name from\n       the current directory.\n\n   How yank works\n       For example, the foo crate published version 1.5.0 and another crate bar\n       declared a dependency on version foo = \"1.5\". Now foo releases a new,\n       but not semver compatible, version 2.0.0, and finds a critical issue\n       with 1.5.0. If 1.5.0 is yanked, no new project or checkout without an\n       existing lockfile will be able to use crate bar as it relies on 1.5.\n\n       In this case, the maintainers of foo should first publish a semver\n       compatible version such as 1.5.1 prior to yanking 1.5.0 so that bar and\n       all projects that depend on bar will continue to work.\n\n       As another example, consider a crate bar with published versions 1.5.0,\n       1.5.1, 1.5.2, 2.0.0 and 3.0.0. The following table identifies the\n       versions cargo could use in the absence of a lockfile for different\n       SemVer requirements, following a given release being yanked:\n\n       +------------------------+----------------------+----------+----------+\n       | Yanked Version /       | bar = \"1.5.0\"        | bar =    | bar =    |\n       | SemVer requirement     |                      | \"=1.5.0\" | \"2.0.0\"  |\n       +------------------------+----------------------+----------+----------+\n       | 1.5.0                  | Use either 1.5.1 or  | Return   | Use      |\n       |                        | 1.5.2                | Error    | 2.0.0    |\n       +------------------------+----------------------+----------+----------+\n       | 1.5.1                  | Use either 1.5.0 or  | Use      | Use      |\n       |                        | 1.5.2                | 1.5.0    | 2.0.0    |\n       +------------------------+----------------------+----------+----------+\n       | 2.0.0                  | Use either 1.5.0,    | Use      | Return   |\n       |                        | 1.5.1 or 1.5.2       | 1.5.0    | Error    |\n       +------------------------+----------------------+----------+----------+\n\n   When to yank\n       Crates should only be yanked in exceptional circumstances, for example,\n       an accidental publish, unintentional SemVer breakages, or a\n       significantly broken and unusable crate. In the case of security\n       vulnerabilities, RustSec <https://rustsec.org/> is typically a less\n       disruptive mechanism to inform users and encourage them to upgrade, and\n       avoids the possibility of significant downstream disruption irrespective\n       of susceptibility to the vulnerability in question.\n\n       A common workflow is to yank a crate having already published a semver\n       compatible version, to reduce the probability of preventing dependent\n       crates from compiling.\n\n       When addressing copyright, licensing, or personal data issues with a\n       published crate, simply yanking it may not suffice. In such cases,\n       contact the maintainers of the registry you used. For crates.io, refer\n       to their policies <https://crates.io/policies> and contact them at\n       <help@crates.io>.\n\n       If credentials have been leaked, the recommended course of action is to\n       revoke them immediately. Once a crate has been published, it is\n       impossible to determine if the leaked credentials have been copied.\n       Yanking only prevents Cargo from selecting this version when resolving\n       dependencies by default. Existing lock files or direct downloads are not\n       affected, so yanking cannot stop further spreading of the leaked\n       credentials.\n\nOPTIONS\n   Yank Options\n       --vers version, --version version\n           The version to yank or un-yank.\n\n       --undo\n           Undo a yank, putting a version back into the index.\n\n       --token token\n           API token to use when authenticating. This overrides the token\n           stored in the credentials file (which is created by cargo-login(1)).\n\n           Cargo config <https://doc.rust-lang.org/cargo/reference/config.html>\n           environment variables can be used to override the tokens stored in\n           the credentials file. The token for crates.io may be specified with\n           the CARGO_REGISTRY_TOKEN environment variable. Tokens for other\n           registries may be specified with environment variables of the form\n           CARGO_REGISTRIES_NAME_TOKEN where NAME is the name of the registry\n           in all capital letters.\n\n       --index index\n           The URL of the registry index to use.\n\n       --registry registry\n           Name of the registry to use. Registry names are defined in Cargo\n           config files\n           <https://doc.rust-lang.org/cargo/reference/config.html>. If not\n           specified, the default registry is used, which is defined by the\n           registry.default config key which defaults to crates-io.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Yank a crate from the index:\n\n              cargo yank foo@1.0.7\n\nSEE ALSO\n       cargo(1), cargo-login(1), cargo-publish(1)\n\n"
  },
  {
    "path": "src/doc/man/generated_txt/cargo.txt",
    "content": "CARGO(1)\n\nNAME\n       cargo — The Rust package manager\n\nSYNOPSIS\n       cargo [options] command [args]\n       cargo [options] --version\n       cargo [options] --list\n       cargo [options] --help\n       cargo [options] --explain code\n\nDESCRIPTION\n       This program is a package manager and build tool for the Rust language,\n       available at <https://rust-lang.org>.\n\n       command may be one of:\n\n       o  built-in commands, see below\n\n       o  aliases <https://doc.rust-lang.org/cargo/reference/config.html#alias>\n\n       o  external tools\n          <https://doc.rust-lang.org/cargo/reference/external-tools.html#custom-subcommands>\n\nCOMMANDS\n   Build Commands\n       cargo-bench(1)\n           Execute benchmarks of a package.\n\n       cargo-build(1)\n           Compile a package.\n\n       cargo-check(1)\n           Check a local package and all of its dependencies for errors.\n\n       cargo-clean(1)\n           Remove artifacts that Cargo has generated in the past.\n\n       cargo-doc(1)\n           Build a package’s documentation.\n\n       cargo-fetch(1)\n           Fetch dependencies of a package from the network.\n\n       cargo-fix(1)\n           Automatically fix lint warnings reported by rustc.\n\n       cargo-run(1)\n           Run a binary or example of the local package.\n\n       cargo-rustc(1)\n           Compile a package, and pass extra options to the compiler.\n\n       cargo-rustdoc(1)\n           Build a package’s documentation, using specified custom flags.\n\n       cargo-test(1)\n           Execute unit and integration tests of a package.\n\n   Manifest Commands\n       cargo-add(1)\n           Add dependencies to a Cargo.toml manifest file.\n\n       cargo-generate-lockfile(1)\n           Generate Cargo.lock for a project.\n\n       cargo-info(1)\n           Display information about a package in the registry. Default\n       registry is crates.io.\n\n       cargo-locate-project(1)\n           Print a JSON representation of a Cargo.toml file’s location.\n\n       cargo-metadata(1)\n           Output the resolved dependencies of a package in\n       machine-readable format.\n\n       cargo-pkgid(1)\n           Print a fully qualified package specification.\n\n       cargo-remove(1)\n           Remove dependencies from a Cargo.toml manifest file.\n\n       cargo-tree(1)\n           Display a tree visualization of a dependency graph.\n\n       cargo-update(1)\n           Update dependencies as recorded in the local lock file.\n\n       cargo-vendor(1)\n           Vendor all dependencies locally.\n\n   Package Commands\n       cargo-init(1)\n           Create a new Cargo package in an existing directory.\n\n       cargo-install(1)\n           Build and install a Rust binary.\n\n       cargo-new(1)\n           Create a new Cargo package.\n\n       cargo-search(1)\n           Search packages in crates.io.\n\n       cargo-uninstall(1)\n           Remove a Rust binary.\n\n   Publishing Commands\n       cargo-login(1)\n           Save an API token from the registry locally.\n\n       cargo-logout(1)\n           Remove an API token from the registry locally.\n\n       cargo-owner(1)\n           Manage the owners of a crate on the registry.\n\n       cargo-package(1)\n           Assemble the local package into a distributable tarball.\n\n       cargo-publish(1)\n           Upload a package to the registry.\n\n       cargo-yank(1)\n           Remove a pushed crate from the index.\n\n   Report Commands\n       cargo-report(1)\n           Generate and display various kinds of reports.\n\n       cargo-report-future-incompatibilities(1)\n           Reports any crates which will eventually stop compiling.\n\n   General Commands\n       cargo-help(1)\n           Display help information about Cargo.\n\n       cargo-version(1)\n           Show version information.\n\nOPTIONS\n   Special Options\n       -V, --version\n           Print version info and exit. If used with --verbose, prints extra\n           information.\n\n       --list\n           List all installed Cargo subcommands. If used with --verbose, prints\n           extra information.\n\n       --explain code\n           Run rustc --explain CODE which will print out a detailed explanation\n           of an error message (for example, E0004).\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nFILES\n       ~/.cargo/\n           Default location for Cargo’s “home” directory where it\n       stores various files. The location can be changed with the CARGO_HOME\n       environment variable.\n\n       $CARGO_HOME/bin/\n           Binaries installed by cargo-install(1) will be located here. If\n       using rustup <https://rust-lang.github.io/rustup/>, executables\n       distributed with Rust are also located here.\n\n       $CARGO_HOME/config.toml\n           The global configuration file. See the reference\n       <https://doc.rust-lang.org/cargo/reference/config.html> for more\n       information about configuration files.\n\n       .cargo/config.toml\n           Cargo automatically searches for a file named .cargo/config.toml\n       in the current directory, and all parent directories. These\n       configuration files will be merged with the global configuration file.\n\n       $CARGO_HOME/credentials.toml\n           Private authentication information for logging in to a registry.\n\n       $CARGO_HOME/registry/\n           This directory contains cached downloads of the registry index\n       and any downloaded dependencies.\n\n       $CARGO_HOME/git/\n           This directory contains cached downloads of git dependencies.\n\n       Please note that the internal structure of the $CARGO_HOME directory is\n       not stable yet and may be subject to change.\n\nEXAMPLES\n       1. Build a local package and all of its dependencies:\n\n              cargo build\n\n       2. Build a package with optimizations:\n\n              cargo build --release\n\n       3. Run tests for a cross-compiled target:\n\n              cargo test --target i686-unknown-linux-gnu\n\n       4. Create a new package that builds an executable:\n\n              cargo new foobar\n\n       5. Create a package in the current directory:\n\n              mkdir foo && cd foo\n              cargo init .\n\n       6. Learn about a command’s options and usage:\n\n              cargo help clean\n\nBUGS\n       See <https://github.com/rust-lang/cargo/issues> for issues.\n\nSEE ALSO\n       rustc(1), rustdoc(1)\n\n"
  },
  {
    "path": "src/doc/man/includes/description-install-root.md",
    "content": "The installation root is determined, in order of precedence:\n\n- `--root` option\n- `CARGO_INSTALL_ROOT` environment variable\n- `install.root` Cargo [config value](../reference/config.html)\n- `CARGO_HOME` environment variable\n- `$HOME/.cargo`\n"
  },
  {
    "path": "src/doc/man/includes/description-one-target.md",
    "content": "This command requires that only one target is being compiled when additional\narguments are provided. If more than one target is available for the current\npackage the filters of `--lib`, `--bin`, etc, must be used to select which\ntarget is compiled.\n"
  },
  {
    "path": "src/doc/man/includes/options-display.md",
    "content": "{{#option \"`-v`\" \"`--verbose`\"}}\nUse verbose output. May be specified twice for \"very verbose\" output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the `term.verbose`\n[config value](../reference/config.html).\n{{/option}}\n\n{{#option \"`-q`\" \"`--quiet`\"}}\nDo not print cargo log messages.\nMay also be specified with the `term.quiet`\n[config value](../reference/config.html).\n{{/option}}\n\n{{#option \"`--color` _when_\"}}\nControl when colored output is used. Valid values:\n\n- `auto` (default): Automatically detect if color support is available on the\n  terminal.\n- `always`: Always display colors.\n- `never`: Never display colors.\n\nMay also be specified with the `term.color`\n[config value](../reference/config.html).\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-future-incompat.md",
    "content": "{{#option \"`--future-incompat-report`\"}}\nDisplays a future-incompat report for any future-incompatible warnings\nproduced during execution of this command\n\nSee {{man \"cargo-report\" 1}}\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-ignore-rust-version.md",
    "content": "{{#option \"`--ignore-rust-version`\"}}\nIgnore `rust-version` specification in packages.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-index.md",
    "content": "{{#option \"`--index` _index_\"}}\nThe URL of the registry index to use.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-jobs.md",
    "content": "{{#option \"`-j` _N_\" \"`--jobs` _N_\"}}\nNumber of parallel jobs to run. May also be specified with the\n`build.jobs` [config value](../reference/config.html). Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string `default` is provided, it sets the value back to defaults.\nShould not be 0.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-keep-going.md",
    "content": "{{#option \"`--keep-going`\"}}\nBuild as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.\n\nFor example if the current package depends on dependencies `fails` and `works`,\none of which fails to build, `cargo {{command}} -j1` may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas `cargo {{command}} -j1 --keep-going` would definitely run both\nbuilds, even if the one run first fails.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-locked.md",
    "content": "{{#option \"`--locked`\"}}\nAsserts that the exact same dependencies and versions are used as when the\nexisting `Cargo.lock` file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n\n* The lock file is missing.\n* Cargo attempted to change the lock file due to a different dependency resolution.\n\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n{{/option}}\n\n{{#option \"`--offline`\"}}\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\n{{#if (ne command \"fetch\")}}\nSee the {{man \"cargo-fetch\" 1}} command to download dependencies before going\noffline.\n{{/if}}\n\nMay also be specified with the `net.offline` [config value](../reference/config.html).\n{{/option}}\n\n{{#option \"`--frozen`\"}}\nEquivalent to specifying both `--locked` and `--offline`.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-manifest-path.md",
    "content": "{{#option \"`--manifest-path` _path_\" }}\nPath to the `Cargo.toml` file. By default, Cargo searches for the\n`Cargo.toml` file in the current directory or any parent directory.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-message-format.md",
    "content": "{{#option \"`--message-format` _fmt_\" }}\nThe output format for diagnostic messages. Can be specified multiple times\nand consists of comma-separated values. Valid values:\n\n- `human` (default): Display in a human-readable text format. Conflicts with\n  `short` and `json`.\n- `short`: Emit shorter, human-readable text messages. Conflicts with `human`\n  and `json`.\n- `json`: Emit JSON messages to stdout. See\n  [the reference](../reference/external-tools.html#json-messages)\n  for more details. Conflicts with `human` and `short`.\n- `json-diagnostic-short`: Ensure the `rendered` field of JSON messages contains\n  the \"short\" rendering from rustc. Cannot be used with `human` or `short`.\n- `json-diagnostic-rendered-ansi`: Ensure the `rendered` field of JSON messages\n  contains embedded ANSI color codes for respecting rustc's default color\n  scheme. Cannot be used with `human` or `short`.\n- `json-render-diagnostics`: Instruct Cargo to not include rustc diagnostics\n  in JSON messages printed, but instead Cargo itself should render the\n  JSON diagnostics coming from rustc. Cargo's own JSON diagnostics and others\n  coming from rustc are still emitted. Cannot be used with `human` or `short`.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-new.md",
    "content": "{{#options}}\n\n{{#option \"`--bin`\" }}\nCreate a package with a binary target (`src/main.rs`).\nThis is the default behavior.\n{{/option}}\n\n{{#option \"`--lib`\" }}\nCreate a package with a library target (`src/lib.rs`).\n{{/option}}\n\n{{#option \"`--edition` _edition_\" }}\nSpecify the Rust edition to use. Default is 2024.\nPossible values: 2015, 2018, 2021, 2024\n{{/option}}\n\n{{#option \"`--name` _name_\" }}\nSet the package name. Defaults to the directory name.\n{{/option}}\n\n{{#option \"`--vcs` _vcs_\" }}\nInitialize a new VCS repository for the given version control system (git,\nhg, pijul, or fossil) or do not initialize any version control at all\n(none). If not specified, defaults to `git` or the configuration value\n`cargo-new.vcs`, or `none` if already inside a VCS repository.\n{{/option}}\n\n{{#option \"`--registry` _registry_\" }}\nThis sets the `publish` field in `Cargo.toml` to the given registry name\nwhich will restrict publishing only to that registry.\n\nRegistry names are defined in [Cargo config files](../reference/config.html).\nIf not specified, the default registry defined by the `registry.default`\nconfig key is used. If the default registry is not set and `--registry` is not\nused, the `publish` field will not be set which means that publishing will not\nbe restricted.\n{{/option}}\n\n{{/options}}\n"
  },
  {
    "path": "src/doc/man/includes/options-output-format.md",
    "content": "{{#option \"`--output-format`\"}}\nThe output type for the documentation emitted. Valid values:\n\n* `html` (default): Emit the documentation in HTML format.\n* `json`: Emit the documentation in the [experimental JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types).\n\nThis option is only available on the [nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)\nand requires the `-Z unstable-options` flag to enable.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-profile-legacy-check.md",
    "content": "{{#option \"`--profile` _name_\" }}\n{{actionverb}} with the given profile.\n\nAs a special case, specifying the `test` profile will also enable checking in\ntest mode which will enable checking tests and enable the `test` cfg option.\nSee [rustc tests](https://doc.rust-lang.org/rustc/tests/index.html) for more\ndetail.\n\nSee [the reference](../reference/profiles.html) for more details on profiles.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-profile.md",
    "content": "{{#option \"`--profile` _name_\" }}\n{{actionverb}} with the given profile.\nSee [the reference](../reference/profiles.html) for more details on profiles.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-registry.md",
    "content": "{{#option \"`--registry` _registry_\"}}\nName of the registry to use. Registry names are defined in [Cargo config\nfiles](../reference/config.html). If not specified, the default registry is used,\nwhich is defined by the `registry.default` config key which defaults to\n`crates-io`.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-release.md",
    "content": "{{#option \"`-r`\" \"`--release`\"}}\n{{actionverb}} optimized artifacts with the `release` profile.\nSee also the `--profile` option for choosing a specific profile by name.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-target-dir.md",
    "content": "{{#option \"`--target-dir` _directory_\"}}\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the `CARGO_TARGET_DIR` environment variable, or the\n`build.target-dir` [config value](../reference/config.html).\n{{#if temp-target-dir}} Defaults to a new temporary folder located in the\ntemporary directory of the platform. \n\nWhen using `--path`, by default it will use `target` directory in the workspace\nof the local crate unless `--target-dir`\nis specified.\n{{else}} Defaults to `target` in the root of the workspace.\n{{/if}}\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-target-triple.md",
    "content": "{{#option \"`--target` _triple_\"}}\n{{actionverb}} for the specified target architecture. {{~#if multitarget }} Flag may be specified multiple times. {{~/if}}\n{{~#if target-default-to-all-arch}} The default is all architectures.\n{{~else}} The default is the host architecture.\n{{~/if}} The general format of the triple is\n`<arch><sub>-<vendor>-<sys>-<abi>`.\n\nPossible values:\n- Any supported target in `rustc --print target-list`.\n- `\"host-tuple\"`, which will internally be substituted by the host's target. This can be particularly useful if you're cross-compiling some crates, and don't want to specify your host's machine as a target (for instance, an `xtask` in a shared project that may be worked on by many hosts).\n- A path to a custom target specification. See [Custom Target Lookup Path](../../rustc/targets/custom.html#custom-target-lookup-path) for more information.\n\n\nThis may also be specified with the `build.target` [config value](../reference/config.html).\n\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n[build cache](../reference/build-cache.html) documentation for more details.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-targets-bin-auto-built.md",
    "content": "Binary targets are automatically built if there is an integration test or\nbenchmark being selected to {{lower actionverb}}. This allows an integration\ntest to execute the binary to exercise and test its behavior. \nThe `CARGO_BIN_EXE_<name>`\n[environment variable](../reference/environment-variables.html#environment-variables-cargo-sets-for-crates)\nis set when the integration test is built and run so that it can use the\n[`env` macro](https://doc.rust-lang.org/std/macro.env.html) or the \n[`var` function](https://doc.rust-lang.org/std/env/fn.var.html) to locate the\nexecutable.\n"
  },
  {
    "path": "src/doc/man/includes/options-targets-lib-bin.md",
    "content": "{{#option \"`--lib`\" }}\n{{actionverb}} the package's library.\n{{/option}}\n\n{{#option \"`--bin` _name_...\" }}\n{{actionverb}} the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.\n{{/option}}\n\n{{#option \"`--bins`\" }}\n{{actionverb}} all binary targets.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/options-targets.md",
    "content": "Passing target selection flags will {{lower actionverb}} only the specified\ntargets. \n\nNote that `--bin`, `--example`, `--test` and `--bench` flags also \nsupport common Unix glob patterns like `*`, `?` and `[]`. However, to avoid your \nshell accidentally expanding glob patterns before Cargo handles them, you must \nuse single quotes or double quotes around each glob pattern.\n\n{{#options}}\n\n{{> options-targets-lib-bin }}\n\n{{#option \"`--example` _name_...\" }}\n{{actionverb}} the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.\n{{/option}}\n\n{{#option \"`--examples`\" }}\n{{actionverb}} all example targets.\n{{/option}}\n\n{{#option \"`--test` _name_...\" }}\n{{actionverb}} the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.\n{{/option}}\n\n{{#option \"`--tests`\" }}\n{{actionverb}} all targets that have the `test = true` manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the `test` flag in the\nmanifest settings for the target.\n{{/option}}\n\n{{#option \"`--bench` _name_...\" }}\n{{actionverb}} the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.\n{{/option}}\n\n{{#option \"`--benches`\" }}\n{{actionverb}} all targets that have the `bench = true`\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the `bench` flag in the\nmanifest settings for the target.\n{{/option}}\n\n{{#option \"`--all-targets`\" }}\n{{actionverb}} all targets. This is equivalent to specifying `--lib --bins\n--tests --benches --examples`.\n{{/option}}\n\n{{/options}}\n"
  },
  {
    "path": "src/doc/man/includes/options-test.md",
    "content": "{{#options}}\n\n{{#option \"`--no-run`\" }}\nCompile, but don't run {{nouns}}.\n{{/option}}\n\n{{#option \"`--no-fail-fast`\" }}\nRun all {{nouns}} regardless of failure. Without this flag, Cargo will exit\nafter the first executable fails. The Rust test harness will run all {{nouns}}\nwithin the executable to completion, this flag only applies to the executable\nas a whole.\n{{/option}}\n\n{{/options}}\n"
  },
  {
    "path": "src/doc/man/includes/options-timings.md",
    "content": "{{#option \"`--timings`\"}}\nOutput information how long each compilation takes, and track concurrency\ninformation over time.\n\nA file `cargo-timing.html` will be written to the `target/cargo-timings`\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine-readable timing data.\n{{/option}}\n\n"
  },
  {
    "path": "src/doc/man/includes/options-token.md",
    "content": "{{#option \"`--token` _token_\" }}\nAPI token to use when authenticating. This overrides the token stored in\nthe credentials file (which is created by {{man \"cargo-login\" 1}}).\n\n[Cargo config](../reference/config.html) environment variables can be\nused to override the tokens stored in the credentials file. The token for\ncrates.io may be specified with the `CARGO_REGISTRY_TOKEN` environment\nvariable. Tokens for other registries may be specified with environment\nvariables of the form `CARGO_REGISTRIES_NAME_TOKEN` where `NAME` is the name\nof the registry in all capital letters.\n{{/option}}\n"
  },
  {
    "path": "src/doc/man/includes/section-environment.md",
    "content": "## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n"
  },
  {
    "path": "src/doc/man/includes/section-exit-status.md",
    "content": "## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n"
  },
  {
    "path": "src/doc/man/includes/section-features.md",
    "content": "### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n{{#options}}\n\n{{#option \"`-F` _features_\" \"`--features` _features_\" }}\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with `package-name/feature-name` syntax. This flag may\nbe specified multiple times, which enables all specified features.\n{{/option}}\n\n{{#option \"`--all-features`\" }}\nActivate all available features of all selected packages.\n{{/option}}\n\n{{#option \"`--no-default-features`\" }}\nDo not activate the `default` feature of the selected packages.\n{{/option}}\n\n{{/options}}\n"
  },
  {
    "path": "src/doc/man/includes/section-options-common.md",
    "content": "### Common Options\n\n{{#options}}\n\n{{#option \"`+`_toolchain_\"}}\nIf Cargo has been installed with rustup, and the first argument to `cargo`\nbegins with `+`, it will be interpreted as a rustup toolchain name (such\nas `+stable` or `+nightly`).\nSee the [rustup documentation](https://rust-lang.github.io/rustup/overrides.html)\nfor more information about how toolchain overrides work.\n{{/option}}\n\n{{#option \"`--config` _KEY=VALUE_ or _PATH_\"}}\nOverrides a Cargo configuration value. The argument should be in TOML syntax of `KEY=VALUE`,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the [command-line overrides section](../reference/config.html#command-line-overrides) for more information.\n{{/option}}\n\n{{#option \"`-C` _PATH_\"}}\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (`Cargo.toml`), as well as\nthe directories searched for discovering `.cargo/config.toml`, for example. This option must\nappear before the command name, for example `cargo -C path/to/my-project build`.\n\nThis option is only available on the [nightly\nchannel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html) and\nrequires the `-Z unstable-options` flag to enable (see\n[#10098](https://github.com/rust-lang/cargo/issues/10098)).\n{{/option}}\n\n{{#option \"`-h`\" \"`--help`\"}}\nPrints help information.\n{{/option}}\n\n{{#option \"`-Z` _flag_\"}}\nUnstable (nightly-only) flags to Cargo. Run `cargo -Z help` for details.\n{{/option}}\n\n{{/options}}\n"
  },
  {
    "path": "src/doc/man/includes/section-options-package.md",
    "content": "### Package Selection\n\nBy default, the package in the current working directory is selected. The `-p`\nflag can be used to choose a different package in a workspace.\n\n{{#options}}\n\n{{#option \"`-p` _spec_\" \"`--package` _spec_\" }}\nThe package to {{lower actionverb}}. See {{man \"cargo-pkgid\" 1}} for the SPEC\nformat.\n{{/option}}\n\n{{/options}}\n"
  },
  {
    "path": "src/doc/man/includes/section-package-selection.md",
    "content": "### Package Selection\n\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n`--manifest-path` is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n\nThe default members of a workspace can be set explicitly with the\n`workspace.default-members` key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n`--workspace`), and a non-virtual workspace will include only the root crate itself.\n\n{{#options}}\n\n{{#option \"`-p` _spec_...\" \"`--package` _spec_...\"}}\n{{actionverb}} only the specified packages. See {{man \"cargo-pkgid\" 1}} for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like `*`, `?` and `[]`. However, to avoid your shell accidentally \nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.\n{{/option}}\n\n{{#option \"`--workspace`\" }}\n{{actionverb}} all members in the workspace.\n{{/option}}\n\n{{#unless noall}}\n{{#option \"`--all`\" }}\nDeprecated alias for `--workspace`.\n{{/option}}\n{{/unless}}\n\n{{#option \"`--exclude` _SPEC_...\" }}\nExclude the specified packages. Must be used in conjunction with the\n`--workspace` flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like `*`, `?` and `[]`. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.\n{{/option}}\n\n{{/options}}\n"
  },
  {
    "path": "src/doc/src/CHANGELOG.md",
    "content": "# Changelog\n\n## Cargo 1.96 (2026-05-28)\n[f298b8c8...HEAD](https://github.com/rust-lang/cargo/compare/f298b8c8...HEAD)\n\n### Added\n\n- cargo-help: display manpages for nested subcommands.\n  For example, `cargo help report future-incompat`.\n  [#16432](https://github.com/rust-lang/cargo/pull/16432)\n\n### Changed\n\n- Improved error message when searching for a parent workspace\n  to explain why Cargo searches upward and suggest a workaround.\n  [#16669](https://github.com/rust-lang/cargo/pull/16669)\n- Clarified edition-related warning messages\n  for `Cargo.toml` and scripts to use more consistent wording.\n  [#16676](https://github.com/rust-lang/cargo/pull/16676)\n\n### Fixed\n\n### Nightly only\n\n- `unstable-editions`: Show the required Rust version in the error\n  when a package declares an unstable edition.\n  [#16653](https://github.com/rust-lang/cargo/pull/16653)\n- `-Zscript`: Inject an edition into scripts for `cargo fix`.\n  [#16678](https://github.com/rust-lang/cargo/pull/16678)\n\n### Documentation\n\n### Internal\n\n- Update dependencies.\n  [#16685](https://github.com/rust-lang/cargo/pull/16685)\n  [#16690](https://github.com/rust-lang/cargo/pull/16690)\n\n## Cargo 1.95 (2026-04-16)\n[85eff7c8...rust-1.95.0](https://github.com/rust-lang/cargo/compare/85eff7c8...rust-1.95.0)\n\n### Added\n\n### Changed\n\n- ❗️ Forbid `cargo init` in the home directory to avoid problems with manifest discovery.\n  This previously led to confusing states for new users experimenting with Cargo.\n  [#16566](https://github.com/rust-lang/cargo/pull/16566)\n- The HTML timing report is now rendered using SVG instead of canvas.\n  The canvas renderer option is removed entirely.\n  This improves responsiveness and performance on large dependency graphs,\n  as well as enabling text selection in charts.\n  [#16602](https://github.com/rust-lang/cargo/pull/16602)\n  [#16607](https://github.com/rust-lang/cargo/pull/16607)\n- Improve error messages to follow rustc diagnostic style.\n  [#16498](https://github.com/rust-lang/cargo/pull/16498)\n  [#16625](https://github.com/rust-lang/cargo/pull/16625)\n  [#16643](https://github.com/rust-lang/cargo/pull/16643)\n- Improve bad manifest error\n  [#16630](https://github.com/rust-lang/cargo/pull/16630)\n- Suggest a `workspace.members` entry even from outside the workspace root\n  [#16616](https://github.com/rust-lang/cargo/pull/16616)\n- `term.progress.term-integration` detects if iTerm supports ANSI OSC 9;4 sequences.\n  [#16506](https://github.com/rust-lang/cargo/pull/16506)\n- cargo-install: Make the error messaging aware of `build.build-dir`\n  [#16623](https://github.com/rust-lang/cargo/pull/16623)\n- cargo-remove: Suggest `--dev`, `--build`, or `--target` flags when removing\n  a dependency that exists in a different table.\n  [#16533](https://github.com/rust-lang/cargo/pull/16533)\n\n### Fixed\n\n- Fixed `cargo test --frozen` attempting to download dependencies\n  that are not actually required for the specified tests.\n  [#16221](https://github.com/rust-lang/cargo/pull/16221)\n- Fix `net.known_hosts` parsing for negations.\n  [#16596](https://github.com/rust-lang/cargo/pull/16596)\n- Only compute `y_ticks` when the `units` is not empty for timings SVG renderer.\n  [#16575](https://github.com/rust-lang/cargo/pull/16575)\n- Respect Clippy CLI arguments `CLIPPY_ARGS` in suggested fix message.\n  [#16652](https://github.com/rust-lang/cargo/pull/16652)\n\n### Nightly only\n\n- 🔥 `-Zhost-config`: Add `host.runner` for wrapping host build target executions\n  [#16599](https://github.com/rust-lang/cargo/pull/16599)\n  [#16674](https://github.com/rust-lang/cargo/pull/16674)\n  [#16638](https://github.com/rust-lang/cargo/pull/16638)\n  [#16631](https://github.com/rust-lang/cargo/pull/16631)\n- `--artifact-dir`: Remove deprecated, unstable `--out-dir`\n  [#16608](https://github.com/rust-lang/cargo/pull/16608)\n- `-Zbuild-analysis`: Add command field to BuildStarted message\n  [#16577](https://github.com/rust-lang/cargo/pull/16577)\n- `-Zbuild-dir-new-layout`: Update layout module docs to document new layout\n  [#16502](https://github.com/rust-lang/cargo/pull/16502)\n- `-Zbuild-dir-new-layout`: store artifact dependencies in build unit directory.\n  [#16519](https://github.com/rust-lang/cargo/pull/16519)\n- `-Zbuild-dir-new-layout`: Change build script run `output` dir to `stdout` in new build-dir layout\n  [#16644](https://github.com/rust-lang/cargo/pull/16644)\n  [#16645](https://github.com/rust-lang/cargo/pull/16645)\n- `-Zbuild-dir-new-layout`: Reorganize build unit directory layout for new build-dir layout\n  [#16542](https://github.com/rust-lang/cargo/pull/16542)\n- `-Zcargo-lints`: Add `non_kebab_case_bins` lint\n  [#16524](https://github.com/rust-lang/cargo/pull/16524)\n  [#16553](https://github.com/rust-lang/cargo/pull/16553)\n- `-Zcargo-lints`: Add `missing_lints_inheritance` lint\n  [#16588](https://github.com/rust-lang/cargo/pull/16588)\n- `-Zcargo-lints`: Add `unused_workspace_package_fields` lint\n  [#16585](https://github.com/rust-lang/cargo/pull/16585)\n- `-Zcargo-lints`: Add `unused_workspace_dependencies` lint\n  [#16571](https://github.com/rust-lang/cargo/pull/16571)\n- `-Zcargo-lints`: Add `redundant_homepage` lint\n  [#16561](https://github.com/rust-lang/cargo/pull/16561)\n  [#16564](https://github.com/rust-lang/cargo/pull/16564)\n- `-Zcargo-lints`: Add `redundant_readme` lint\n  [#16552](https://github.com/rust-lang/cargo/pull/16552)\n- `-Zcargo-lints`: Add `non_*_case_features` lints\n  [#16560](https://github.com/rust-lang/cargo/pull/16560)\n- `-Zcargo-lints`: Add mutually exclusive `non_{kebab,snake}_case_packages`\n  [#16554](https://github.com/rust-lang/cargo/pull/16554)\n- `-Zcargo-lints`: show `implicit_minimum_version_req` lint source once per package.\n  [#16535](https://github.com/rust-lang/cargo/pull/16535)\n- `-Zcargo-lints`: Don't run on-by-default lints when MSRV is too old\n  [#16618](https://github.com/rust-lang/cargo/pull/16618)\n- `-Zfine-grain-locking`: Fix parallel locking\n  [#16659](https://github.com/rust-lang/cargo/pull/16659)\n- `-Zhost-config`: `host.linker` should not apply to non host unit\n  [#16641](https://github.com/rust-lang/cargo/pull/16641)\n- `-Zjson-target-spec`: Add the new `-Zjson-target-spec` flag to assist with\n  using custom `.json` target spec files.\n  [#16557](https://github.com/rust-lang/cargo/pull/16557)\n- `-Zlockfile-path`: Remove `--lockfile-path`\n  [#16621](https://github.com/rust-lang/cargo/pull/16621)\n- `-Zlockfile-path`: Respect the config in fix, install\n  [#16617](https://github.com/rust-lang/cargo/pull/16617)\n- `-Zscript`: Load config relative to the script\n  [#16620](https://github.com/rust-lang/cargo/pull/16620)\n- `-Zscript`: Make the lockfile script-specific independent of build-dir\n  [#16619](https://github.com/rust-lang/cargo/pull/16619)\n- `-Zscript`: Correct style of help message\n  [#16580](https://github.com/rust-lang/cargo/pull/16580)\n- `-Zscript`: Show remaining workspace behaviors\n  [#16633](https://github.com/rust-lang/cargo/pull/16633)\n- `-Ztrim-paths`: use stabilized `-Cremap-path-scope` rustc flag.\n  [#16536](https://github.com/rust-lang/cargo/pull/16536)\n\n### Documentation\n\n- Improve documentation on reading cfg values with build scripts\n  [#16671](https://github.com/rust-lang/cargo/pull/16671)\n- Discuss commands and aliases\n  [#16581](https://github.com/rust-lang/cargo/pull/16581)\n- Remove redundant homepage link\n  [#16572](https://github.com/rust-lang/cargo/pull/16572)\n- cargo-report: enhance man pages for `cargo report *`\n  [#16430](https://github.com/rust-lang/cargo/pull/16430)\n\n### Internal\n\n- Reuse timing metric collection logic between `--timings` and `-Zbuild-analysis`.\n  [#16497](https://github.com/rust-lang/cargo/pull/16497)\n- Add a test for fingerprint checking when a symlink target changes\n  [#16661](https://github.com/rust-lang/cargo/pull/16661)\n- Update build-std tests to reflect compiler updates.\n  [#16550](https://github.com/rust-lang/cargo/pull/16550)\n  [#16551](https://github.com/rust-lang/cargo/pull/16551)\n  [#16559](https://github.com/rust-lang/cargo/pull/16559)\n  [#16658](https://github.com/rust-lang/cargo/pull/16658)\n- Enable triagebot new `[view-all-comments-link]` feature\n  [#16629](https://github.com/rust-lang/cargo/pull/16629)\n- Increase cache_lock test timeout\n  [#16545](https://github.com/rust-lang/cargo/pull/16545)\n- cargo-help: snapshot cargo help tests\n  [#16626](https://github.com/rust-lang/cargo/pull/16626)\n  [#16627](https://github.com/rust-lang/cargo/pull/16627)\n- Update dependencies.\n  [#16387](https://github.com/rust-lang/cargo/pull/16387)\n  [#16538](https://github.com/rust-lang/cargo/pull/16538)\n  [#16548](https://github.com/rust-lang/cargo/pull/16548)\n  [#16570](https://github.com/rust-lang/cargo/pull/16570)\n  [#16578](https://github.com/rust-lang/cargo/pull/16578)\n  [#16579](https://github.com/rust-lang/cargo/pull/16579)\n  [#16587](https://github.com/rust-lang/cargo/pull/16587)\n  [#16589](https://github.com/rust-lang/cargo/pull/16589)\n  [#16593](https://github.com/rust-lang/cargo/pull/16593)\n  [#16601](https://github.com/rust-lang/cargo/pull/16601)\n  [#16613](https://github.com/rust-lang/cargo/pull/16613)\n  [#16615](https://github.com/rust-lang/cargo/pull/16615)\n  [#16624](https://github.com/rust-lang/cargo/pull/16624)\n\n## Cargo 1.94 (2026-03-05)\n\n[2c283a9a...rust-1.94.0](https://github.com/rust-lang/cargo/compare/2c283a9a...rust-1.94.0)\n\n### Added\n\n- 🎉 Stabilize the config `include` key.\n  The top-level `include` config key allows loading additional config files,\n  enabling better organization, sharing, and management of Cargo configurations\n  across projects and environments.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#including-extra-configuration-files)\n  [#16284](https://github.com/rust-lang/cargo/pull/16284)\n- 🎉 Stabilize the `pubtime` field in registry index.\n  This records when a crate version was published and enables time-based dependency resolution in the future.\n  Note that crates.io will gradually backfill existing packages when a new version is published.\n  Not all crates have `pubtime` yet.\n  [#16369](https://github.com/rust-lang/cargo/pull/16369)\n  [#16372](https://github.com/rust-lang/cargo/pull/16372)\n- Cargo now parses [TOML v1.1](https://toml.io/en/v1.1.0) for manifests and configuration files.\n  Note that using these features in `Cargo.toml` will raise your development MSRV,\n  but the published manifest remains compatible with older parsers.\n  [#16415](https://github.com/rust-lang/cargo/pull/16415)\n- The timing HTML report now has a new SVG rendering option for a better\n  rendering performance with large builds.\n  Canvas rendering is still available but will be phased out.\n  [#15091](https://github.com/rust-lang/cargo/pull/15091)\n- The `CARGO_BIN_EXE_<name>` environment variable is now available at runtime not just compile time.\n  [#16421](https://github.com/rust-lang/cargo/pull/16421)\n- perf: Optimize `cargo clean` with multiple `--package` specifiers.\n  [#16264](https://github.com/rust-lang/cargo/pull/16264)\n- perf: Optimize `cargo locate-project --workspace` by avoiding full workspace\n  loading when only the workspace root path is needed.\n  [#16423](https://github.com/rust-lang/cargo/pull/16423)\n\n### Changed\n\n- Improve error message when Cargo build target source files are missing.\n  [#16338](https://github.com/rust-lang/cargo/pull/16338)\n- Improve error message for missing dependencies using rustc diagnostic style.\n  [#16500](https://github.com/rust-lang/cargo/pull/16500)\n- Display where the patch was defined in patch-related error messages.\n  [#16407](https://github.com/rust-lang/cargo/pull/16407)\n- List all available features when the requested feature has no close match.\n  [#16445](https://github.com/rust-lang/cargo/pull/16445)\n- Display lockfile path in very verbose mode `-vv`) when waiting on a file lock.\n  [#16491](https://github.com/rust-lang/cargo/pull/16491)\n- cargo-new: Improve quality of package name error messages.\n  [#16398](https://github.com/rust-lang/cargo/pull/16398)\n\n### Fixed\n\n- Don't read config file twice when `$CARGO_HOME` is a symlinked directory.\n  [#16325](https://github.com/rust-lang/cargo/pull/16325)\n- cargo-info: default to inspecting local package when no registry is explicitly specified.\n  [#16358](https://github.com/rust-lang/cargo/pull/16358)\n- cargo-info: resolve underscore vs hyphen mismatch in schema lookup.\n  [#16455](https://github.com/rust-lang/cargo/pull/16455)\n- cargo-package: skip registry verification when using `--list`.\n  [#16341](https://github.com/rust-lang/cargo/pull/16341)\n- cargo-package: detect dirty files when run from workspace member directory.\n  [#16479](https://github.com/rust-lang/cargo/pull/16479)\n- cargo-vendor: recursively filter `.gitattributes` and `.gitignores` in subdirectories.\n  Previously only top-level Git files were filtered,\n  causing checksum failures when vendored code is committed to a Git repository.\n  [#16439](https://github.com/rust-lang/cargo/pull/16439)\n- cargo-vendor: unpack from local-registry cache path correctly.\n  [#16435](https://github.com/rust-lang/cargo/pull/16435)\n\n### Nightly only\n\n- 🔥 `-Zany-build-script-metadata`: Allow any build script to emit `cargo::metadata=KEY=VALUE`\n  and expose it to dependents via `CARGO_DEP_<name>_<key>` environment variables.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#any-build-script-metadata)\n  [#16436](https://github.com/rust-lang/cargo/pull/16436)\n  [#16486](https://github.com/rust-lang/cargo/pull/16486)\n  [#16489](https://github.com/rust-lang/cargo/pull/16489)\n  [#16494](https://github.com/rust-lang/cargo/pull/16494)\n  [#16496](https://github.com/rust-lang/cargo/pull/16496)\n- `timings`: Remove `--timings=<FMT>` optional format values.\n  The `-Zbuild-analysis` logging is now the recommended approach for machine-readable timing data.\n  Use the unstable `cargo report timings` to generate HTML reports.\n  [#16420](https://github.com/rust-lang/cargo/pull/16420)\n- `-Zlockfile-path`: Add new `resolver.lockfile-path` config to replace CLI `--lockfile-path` option.\n  `--lockfile-path` CLI option will be removed in a future release.\n  [#16510](https://github.com/rust-lang/cargo/pull/16510)\n- `-Zbuild-analysis`: new `cargo report rebuilds` command to analyze rebuild\n  reasons from previous sessions.\n  [#16408](https://github.com/rust-lang/cargo/pull/16408)\n  [#16456](https://github.com/rust-lang/cargo/pull/16456)\n- `-Zbuild-analysis`: new `cargo report sessions` command to list build session IDs.\n  [#16428](https://github.com/rust-lang/cargo/pull/16428)\n- `-Zbuild-analysis`: new `cargo report timings` command for HTML replay.\n  [#16346](https://github.com/rust-lang/cargo/pull/16346)\n  [#16350](https://github.com/rust-lang/cargo/pull/16350)\n  [#16352](https://github.com/rust-lang/cargo/pull/16352)\n  [#16377](https://github.com/rust-lang/cargo/pull/16377)\n  [#16378](https://github.com/rust-lang/cargo/pull/16378)\n  [#16382](https://github.com/rust-lang/cargo/pull/16382)\n  [#16390](https://github.com/rust-lang/cargo/pull/16390)\n  [#16414](https://github.com/rust-lang/cargo/pull/16414)\n  [#16441](https://github.com/rust-lang/cargo/pull/16441)\n  [#16448](https://github.com/rust-lang/cargo/pull/16448)\n  [#16485](https://github.com/rust-lang/cargo/pull/16485)\n  [#16490](https://github.com/rust-lang/cargo/pull/16490)\n- `-Zbuild-dir`: implement fine-grained unit-level locking for build cache.\n  [#16155](https://github.com/rust-lang/cargo/pull/16155)\n- `-Zbuild-dir-new-layout`: move build script binaries to `deps` directory.\n  [#16515](https://github.com/rust-lang/cargo/pull/16515)\n- `-Zbuild-dir-new-layout`: do not create `examples` dir when using new layout.\n  [#16514](https://github.com/rust-lang/cargo/pull/16514)\n- `-Zbuild-dir-new-layout`: remove hashes from bins in new layout.\n  [#16351](https://github.com/rust-lang/cargo/pull/16351)\n- `-Zbuild-dir-new-layout`: use unit_id, not pkg hash, for bin/lib pkg_dirs.\n  [#16345](https://github.com/rust-lang/cargo/pull/16345)\n- `-Zbuild-dir-new-layout`: include all search paths with new build layout.\n  [#16348](https://github.com/rust-lang/cargo/pull/16348)\n- `-Zcargo-lints`: add Clippy-like lint groups.\n  [#16464](https://github.com/rust-lang/cargo/pull/16464)\n- `-Zcargo-lints`: new `implicit_minimum_version_req` lint.\n  [#16321](https://github.com/rust-lang/cargo/pull/16321)\n- `-Zno-embed-metadata`: invalidate the whole build cache when the flag changes.\n  [#16513](https://github.com/rust-lang/cargo/pull/16513)\n- `-Zsbom`: don't set `CARGO_SBOM_PATH` when empty.\n  [#16419](https://github.com/rust-lang/cargo/pull/16419)\n\n### Documentation\n\n- Clarify that `OUT_DIR` is not cleaned between builds.\n  [#16437](https://github.com/rust-lang/cargo/pull/16437)\n- Document the only possible values for `DEBUG` in build scripts.\n  [#16413](https://github.com/rust-lang/cargo/pull/16413)\n- Add best practice for how to check in generated files.\n  [#16405](https://github.com/rust-lang/cargo/pull/16405)\n- Document more services and permissions of the Cargo team.\n  [#16402](https://github.com/rust-lang/cargo/pull/16402)\n- FAQ: Include an entry on disk space.\n  [#16349](https://github.com/rust-lang/cargo/pull/16349)\n\n### Internal\n\n- Cache Git submodules into the Git database for faster subsequent fetches.\n  [#16246](https://github.com/rust-lang/cargo/pull/16246)\n- Fixed Git partial OIDs being incorrectly zero-padded.\n  [#16511](https://github.com/rust-lang/cargo/pull/16511)\n- Migrate some cases to expect/reason.\n  [#16461](https://github.com/rust-lang/cargo/pull/16461)\n- Support in-memory only `Manifest` for libcargo\n  [#16409](https://github.com/rust-lang/cargo/pull/16409)\n- cargo-test-support: Use test name for dir when running tests.\n  [#16121](https://github.com/rust-lang/cargo/pull/16121)\n- test: Use a larger default term width.\n  [#16403](https://github.com/rust-lang/cargo/pull/16403)\n  [#16391](https://github.com/rust-lang/cargo/pull/16391)\n- test: Adjust output for out-of-tree build-dir.\n  [#16343](https://github.com/rust-lang/cargo/pull/16343)\n- test: update to `proc_macro::tracked::path`.\n  [#16380](https://github.com/rust-lang/cargo/pull/16380)\n- test: Remove unused build script.\n  [#16344](https://github.com/rust-lang/cargo/pull/16344)\n- Update dependencies.\n  [#16379](https://github.com/rust-lang/cargo/pull/16379)\n  [#16381](https://github.com/rust-lang/cargo/pull/16381)\n  [#16460](https://github.com/rust-lang/cargo/pull/16460)\n  [#16457](https://github.com/rust-lang/cargo/pull/16457)\n  [#16454](https://github.com/rust-lang/cargo/pull/16454)\n  [#16507](https://github.com/rust-lang/cargo/pull/16507)\n\n## Cargo 1.93 (2026-01-22)\n[344c4567...rust-1.93.0](https://github.com/rust-lang/cargo/compare/344c4567...rust-1.93.0)\n\n### Added\n\n- Enable `CARGO_CFG_DEBUG_ASSERTIONS` environment variable in build scripts based on profile settings.\n  [#16160](https://github.com/rust-lang/cargo/pull/16160)\n- Add support for completing `--config` values in Bash\n  [#16245](https://github.com/rust-lang/cargo/pull/16245)\n- cargo-clean: Add `--workspace` flag to clean artifacts of the workspace members.\n  [#16263](https://github.com/rust-lang/cargo/pull/16263)\n- cargo-tree: Support long forms for `--format` variables\n  [#16204](https://github.com/rust-lang/cargo/pull/16204)\n\n### Changed\n\n- ❗️ `cargo publish` no longer keeps `.crate` tarballs as final build artifacts\n  even when the `build.build-dir` config is unset.\n  [#15915](https://github.com/rust-lang/cargo/pull/15915)\n- Migrate more diagnostic formatting to rustc-like style (annotate-snippets style)\n  [#16143](https://github.com/rust-lang/cargo/pull/16143)\n- Point out when a key belongs to Cargo configuration when seeing an unused field in Cargo manifest.\n  [#16256](https://github.com/rust-lang/cargo/pull/16256)\n- When failing to update or create lockfile, provide clearer context and suggested\n  user actions to help resolve it.\n  [#16233](https://github.com/rust-lang/cargo/pull/16233)\n  [#16227](https://github.com/rust-lang/cargo/pull/16227)\n- Emit helpful error messages when GitHub pull request URLs are used as dependencies\n  in the manifest.\n  [#16207](https://github.com/rust-lang/cargo/pull/16207)\n- Avoid unnecessary artifact directory locking for `check` builds.\n  [#16230](https://github.com/rust-lang/cargo/pull/16230)\n  [#16299](https://github.com/rust-lang/cargo/pull/16299)\n  [#16307](https://github.com/rust-lang/cargo/pull/16307)\n  [#16385](https://github.com/rust-lang/cargo/pull/16385)\n  [#16386](https://github.com/rust-lang/cargo/pull/16386)\n- Refer to commands, not subcommands in CLI help text.\n  [#16226](https://github.com/rust-lang/cargo/pull/16226)\n- cargo-install: Cargo treated a relative path in `install.root` without a\n  trailing slash as relative path to the current working directory. This case\n  will now get a deprecation warning. It was an oversight and will be changed\n  to config-relative path like other config fields in the future.\n  [#16125](https://github.com/rust-lang/cargo/pull/16125)\n- cargo-package: Suppress missing metadata warnings for non-crates.io publishable packages\n  [#16241](https://github.com/rust-lang/cargo/pull/16241)\n- cargo-publish: emit a warning when both `package.publish` and `--index` are specified\n  [#16268](https://github.com/rust-lang/cargo/pull/16268)\n- cargo-run: in help text, teach how to escape arguments to be forwarded\n  literally to an underlying program\n  [#16225](https://github.com/rust-lang/cargo/pull/16225)\n\n### Fixed\n\n- Zsh shell completion variables no longer leak into user's environment\n  [#16144](https://github.com/rust-lang/cargo/pull/16144)\n- Fixed Cargo generating dep-info file with invalid trailing backslashes on Windows.\n  [#16223](https://github.com/rust-lang/cargo/pull/16223)\n- Fixed non-mergeable list from `--config` CLI being overridden by environment variables.\n  [#16220](https://github.com/rust-lang/cargo/pull/16220)\n- Fixed nested non-mergeable list from `--config` CLI got merged with other configurations.\n  [#16219](https://github.com/rust-lang/cargo/pull/16219)\n- Cargo now updates mtime for files generated by `cargo package`\n  after unpacking `.crate` source tarballs.\n  This ensures files do not have overly old mtime that some zip tools can't handle.\n  [#16250](https://github.com/rust-lang/cargo/pull/16250)\n- Shift mtime for `cargo check` artifacts (.rmeta files).\n  This addresses a regression in rustc incremental compilation skipping\n  unnecessary rmeta generation but didn't update mtime for existing rmeta files.\n  [#16262](https://github.com/rust-lang/cargo/pull/16262)\n- cargo-doc: clean generated doc directories for only requested targets.\n  Previously when rustc version mismatches, Cargo removes all generated doc\n  directories including target platforms that are not part of the build.\n  [#16331](https://github.com/rust-lang/cargo/pull/16331)\n- cargo-install: fix out-of-bound error in crate name validation\n  [#16314](https://github.com/rust-lang/cargo/pull/16314)\n- cargo-package: generated files in tarball should have deterministic timestamp.\n  [#16242](https://github.com/rust-lang/cargo/pull/16242)\n- cargo-package: exclude `target/package` directory from backups via `CACHEDIR.TAG`.\n  [#16272](https://github.com/rust-lang/cargo/pull/16272)\n- cargo-vendor: fix panic on Windows caused by fallback of `fs::rename`.\n  [#16214](https://github.com/rust-lang/cargo/pull/16214)\n\n### Nightly only\n\n- 🔥 `-Zrustc-unicode` enables `rustc`'s unicode error format in Cargo's error messages.\n  [#16243](https://github.com/rust-lang/cargo/pull/16243)\n- 🔥 `-Zrustdoc-mergeable-info` leverages rustdoc's mergeable crate info, so\n  `cargo doc` can merge cross-crate information (like the search index, source\n  files index) from separate output directories, and run `rustdoc` in parallel.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#rustdoc-mergeable-info)\n  [#16309](https://github.com/rust-lang/cargo/pull/16309)\n- 🔥 `cargo generate-lockfile` now has an unstable `--publish-time` flag that\n  package resolution will not consider any package newer than the specified time.\n  _This is not useful until registry index starts including the `pubtime` field._\n  [#16265](https://github.com/rust-lang/cargo/pull/16265)\n- `build-plan`: Remove the unstable feature `build-plan` entirely.\n  The Cargo team are looking forward to other alternatives like\n  [plumbing commands](https://github.com/crate-ci/cargo-plumbing),\n  [`--unit-graph](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#unit-graph),\n  and [structured logging](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-analysis)\n  helping to fill the gap.\n  [#16212](https://github.com/rust-lang/cargo/pull/16212)\n- `native-completions`: Put host-tuple before actual tuples\n  [#16327](https://github.com/rust-lang/cargo/pull/16327)\n- `native-completions`: include `all` in `cargo tree --target` candidates\n  [#16322](https://github.com/rust-lang/cargo/pull/16322)\n- `native-completions`: don't wrap completion item help in parenthesis\n  [#16215](https://github.com/rust-lang/cargo/pull/16215)\n- `native-completions`: Add more native completions  for `cargo tree`\n  [#16296](https://github.com/rust-lang/cargo/pull/16296)\n- `native-completions`: `--package` on various commands\n  [#16210](https://github.com/rust-lang/cargo/pull/16210)\n- `update-breaking`: silent failure on non-matching package specs with --breaking\n  [#16276](https://github.com/rust-lang/cargo/pull/16276)\n- `-Zbindeps`: do not propagate artifact dependency to proc macro or build deps\n  [#15788](https://github.com/rust-lang/cargo/pull/15788)\n- `-Zbuild-analysis`: Emit timing-info logs with JSONL-based logging\n  infrastructure. Logs are stored in `~/.cargo/log/` with unique files\n  per cargo invocation.\n  [#16150](https://github.com/rust-lang/cargo/pull/16150)\n  [#16179](https://github.com/rust-lang/cargo/pull/16179)\n  [#16303](https://github.com/rust-lang/cargo/pull/16303)\n  [#16337](https://github.com/rust-lang/cargo/pull/16337)\n- `-Zbuild-analysis`: emit rebuild reason log entry.\n  [#16203](https://github.com/rust-lang/cargo/pull/16203)\n- `-Zbuild-build`: Add test for LTO\n  [#16277](https://github.com/rust-lang/cargo/pull/16277)\n- `-Zbuild-dir-new-layout`: Better divide old / new layout\n  [#16304](https://github.com/rust-lang/cargo/pull/16304)\n- `-Zbuild-dir-new-layout`: Clean hosts builds with new layout\n  [#16300](https://github.com/rust-lang/cargo/pull/16300)\n- `-Zbuild-dir-new-layout`: Put examples in their unit dir in new layout\n  [#16335](https://github.com/rust-lang/cargo/pull/16335)\n- `-Zcargo-lints`: show lint error number\n  [#16320](https://github.com/rust-lang/cargo/pull/16320)\n  [#16324](https://github.com/rust-lang/cargo/pull/16324)\n- `-Zconfig-include`: Allow using `optional = true` to silently skip\n  missing config files.\n  [#16103](https://github.com/rust-lang/cargo/pull/16103)\n  [#16174](https://github.com/rust-lang/cargo/pull/16174)\n  [#16180](https://github.com/rust-lang/cargo/pull/16180)\n- `-Zconfig-include`: disallow glob and template syntax in `include.path`\n  [#16285](https://github.com/rust-lang/cargo/pull/16285)\n- `-Zconfig-include`: remove support of single string shorthand\n  [#16298](https://github.com/rust-lang/cargo/pull/16298)\n- `-Zgit`: Support shallow fetch for Git CLI backend (`net.git-fetch-with-cli`)\n  [#16156](https://github.com/rust-lang/cargo/pull/16156)\n- `-Zgit`: Add more git fetch-index backend interop tests\n  [#16162](https://github.com/rust-lang/cargo/pull/16162)\n- `-Zscript`: Update script tests from rustc's test suite\n  [#16169](https://github.com/rust-lang/cargo/pull/16169)\n  [#16334](https://github.com/rust-lang/cargo/pull/16334)\n- `-Zscript`: Fallback to non-canonical path for workspace-path-hash.\n  This ensure script paths that cannot be canonicalized, like `memfd`,\n  still work.\n  [#16248](https://github.com/rust-lang/cargo/pull/16248)\n- `-Zwarnings`: build.warnings=deny shouldn't block hard warnings\n  [#16213](https://github.com/rust-lang/cargo/pull/16213)\n\n\n### Documentation\n\n- Move `compile-time-deps` out of Stabilized section\n  [#16211](https://github.com/rust-lang/cargo/pull/16211)\n- Rename `DEP_NAME_KEY` to `DEP_LINKS_KEY` to make the association of the\n  `package.links` field clearer\n  [#16205](https://github.com/rust-lang/cargo/pull/16205)\n- Clarify `cargo yank` only affects Cargo's dependency resolution,\n  not crate availability\n  [#16274](https://github.com/rust-lang/cargo/pull/16274)\n- In build performance guide, when suggesting alt dev profile, link to related issue.\n  [#16275](https://github.com/rust-lang/cargo/pull/16275)\n- cargo-metadata: document the `\"host-tuple\"` literal is also supported for `-filter-platform`.\n  [#16312](https://github.com/rust-lang/cargo/pull/16312)\n- contrib: Link out to rustc diagnostic style guide\n  [#16216](https://github.com/rust-lang/cargo/pull/16216)\n- resolver: fix compile errors in pseudocode\n  [#16333](https://github.com/rust-lang/cargo/pull/16333)\n\n### Internal\n\n- Make disabling locking on NFS mounts explicit\n  [#16177](https://github.com/rust-lang/cargo/pull/16177)\n- Extract ConfigValue and config schemas to their own separate modules\n  [#16222](https://github.com/rust-lang/cargo/pull/16222)\n  [#16195](https://github.com/rust-lang/cargo/pull/16195)\n- Embed deserialize validation logic in `ProgressConfig`\n  [#16194](https://github.com/rust-lang/cargo/pull/16194)\n- Separate Cargo timings data collection and presentation\n  [#16282](https://github.com/rust-lang/cargo/pull/16282)\n- cargo-util-schemas: add into_value utility function for inheritableField\n  [#16234](https://github.com/rust-lang/cargo/pull/16234)\n- ci: Add a typos/spellcheck CI job\n  [#16122](https://github.com/rust-lang/cargo/pull/16122)\n- ci: Run clippy CI on more targets\n  [#16340](https://github.com/rust-lang/cargo/pull/16340)\n- mdman: Fix mdman to not incorrectly strip `<p>` tags\n  [#16158](https://github.com/rust-lang/cargo/pull/16158)\n  [#16172](https://github.com/rust-lang/cargo/pull/16172)\n- test: re-enable Windows reserved name test since not flaky anymore\n  [#16287](https://github.com/rust-lang/cargo/pull/16287)\n- test: Remove legacy tmpdir support\n  [#16342](https://github.com/rust-lang/cargo/pull/16342)\n- Update to mdbook 0.5.\n  [#16292](https://github.com/rust-lang/cargo/pull/16292)\n- Update dependencies.\n  [#16137](https://github.com/rust-lang/cargo/pull/16137)\n  [#16140](https://github.com/rust-lang/cargo/pull/16140)\n  [#16178](https://github.com/rust-lang/cargo/pull/16178)\n  [#16186](https://github.com/rust-lang/cargo/pull/16186)\n  [#16190](https://github.com/rust-lang/cargo/pull/16190)\n  [#16200](https://github.com/rust-lang/cargo/pull/16200)\n  [#16224](https://github.com/rust-lang/cargo/pull/16224)\n  [#16316](https://github.com/rust-lang/cargo/pull/16316)\n  [#16318](https://github.com/rust-lang/cargo/pull/16318)\n\n## Cargo 1.92 (2025-12-11)\n[24bb93c3...rust-1.92.0](https://github.com/rust-lang/cargo/compare/24bb93c3...rust-1.92.0)\n\n### Added\n\n- Add Ghostty as a supported terminal for term integration (OSC 9;4)\n  [#15977](https://github.com/rust-lang/cargo/pull/15977)\n- Add retry for `git fetch` failures in `net.git-fetch-with-cli` path\n  [#16016](https://github.com/rust-lang/cargo/pull/16016)\n\n### Changed\n\n- Migrate some diagnostic formatting to rustc-like style (annotate-snippets style)\n  [#15943](https://github.com/rust-lang/cargo/pull/15943)\n  [#15945](https://github.com/rust-lang/cargo/pull/15945)\n  [#16019](https://github.com/rust-lang/cargo/pull/16019)\n  [#16035](https://github.com/rust-lang/cargo/pull/16035)\n  [#16066](https://github.com/rust-lang/cargo/pull/16066)\n  [#16113](https://github.com/rust-lang/cargo/pull/16113)\n  [#16126](https://github.com/rust-lang/cargo/pull/16126)\n- Suggested `cargo fix` command from compilation diagnostics is now more accurate.\n  [#16127](https://github.com/rust-lang/cargo/pull/16127)\n- Prefer unicode ellipses when truncating progress\n  [#15955](https://github.com/rust-lang/cargo/pull/15955)\n- Eliminate the last three \"did you mean\" warning phrasings\n  [#15356](https://github.com/rust-lang/cargo/pull/15356)\n- Clarify warning for using `features` or `default-features` in `patch`\n  [#15953](https://github.com/rust-lang/cargo/pull/15953)\n- Config parsing errors now show more precise key path with array index\n  [#16004](https://github.com/rust-lang/cargo/pull/16004)\n- Improve error message for `rust-version` incompatibility diagnostics\n  [#16021](https://github.com/rust-lang/cargo/pull/16021)\n- cargo-add: Report a missing source error for workspace dependencies\n  [#16063](https://github.com/rust-lang/cargo/pull/16063)\n- cargo-info: Suggest a more universal `cargo tree` command\n  [#15954](https://github.com/rust-lang/cargo/pull/15954)\n- cargo-publish: Switch the 'ctrl-c on wait' line to a help message\n  [#15942](https://github.com/rust-lang/cargo/pull/15942)\n- cargo-publish: soft-deprecate the `--token` option\n  [#16046](https://github.com/rust-lang/cargo/pull/16046)\n\n### Fixed\n\n### Nightly only\n\n- 🔥 `immediate-abort`: Add `panic=immediate-abort` support\n  [#16041](https://github.com/rust-lang/cargo/pull/16041)\n  [#16054](https://github.com/rust-lang/cargo/pull/16054)\n- `-Zbuild-dir-new-layout`: Reorganize build-dir layout\n  [#15947](https://github.com/rust-lang/cargo/pull/15947)\n- `-Zbuild-std`: test move away from panic_immediate_abort\n  [#16006](https://github.com/rust-lang/cargo/pull/16006)\n- `-Zcargo-lints`: Add lint for global use of `hint-mostly-unused`\n  [#15995](https://github.com/rust-lang/cargo/pull/15995)\n- `-Zpublic-dependency`: `cargo add` now considers public dependencies when choosing a version\n  [#15966](https://github.com/rust-lang/cargo/pull/15966)\n- `-Zpublic-dependency`: Switch from `--depth public` to `--edges public` for `cargo tree` to display public dependencies\n  [#16081](https://github.com/rust-lang/cargo/pull/16081)\n- `-Zpublic-dependency`: Improve public-in-private manifest errors\n  [#16002](https://github.com/rust-lang/cargo/pull/16002)\n  [#16075](https://github.com/rust-lang/cargo/pull/16075)\n- `-Zscript`: Improve frontmatter parsing error quality\n  [#15972](https://github.com/rust-lang/cargo/pull/15972)\n  [#15939](https://github.com/rust-lang/cargo/pull/15939)\n  [#15952](https://github.com/rust-lang/cargo/pull/15952)\n- `-Zscript`: Only allow horizontal whitespace after fences\n  [#15975](https://github.com/rust-lang/cargo/pull/15975)\n- `-Zscript`: Override arg0 for cargo scripts\n  [#16027](https://github.com/rust-lang/cargo/pull/16027)\n- `-Zscript`: Tweak cargo script build-dir / target-dir\n  [#16086](https://github.com/rust-lang/cargo/pull/16086)\n- `-Zscript`: Remove name sanitiztion outside what is strictly required\n  [#16120](https://github.com/rust-lang/cargo/pull/16120)\n- `-Zscript`: Store cargo script lockfiles in build-dir\n  [#16087](https://github.com/rust-lang/cargo/pull/16087)\n- `-Zscript`: Define cargo script's target-dir using build-dir templating\n  [#16073](https://github.com/rust-lang/cargo/pull/16073)\n- `-Zscript`: Prevent non-script fields in Cargo scripts\n  [#16026](https://github.com/rust-lang/cargo/pull/16026)\n- `-Zscript`: Default bin.name to package.name\n  [#16064](https://github.com/rust-lang/cargo/pull/16064)\n- `multiple-build-scripts`: Access each build script's `OUT_DIR` via `<script-name>_OUT_DIR`\n  [#15891](https://github.com/rust-lang/cargo/pull/15891)\n- `native-completions`: Added completion for `--features` flag\n  [#15309](https://github.com/rust-lang/cargo/pull/15309)\n- `native-completions`: Show local crates/features over other members\n  [#15956](https://github.com/rust-lang/cargo/pull/15956)\n- `native-completions`: Allow completions for third-party subcommand names\n  [#15961](https://github.com/rust-lang/cargo/pull/15961)\n\n### Documentation\n\n- 🎉 Add a new \"Optimizing Build Performance\" chapter\n  [#15924](https://github.com/rust-lang/cargo/pull/15924)\n  [#15970](https://github.com/rust-lang/cargo/pull/15970)\n  [#15991](https://github.com/rust-lang/cargo/pull/15991)\n  [#16078](https://github.com/rust-lang/cargo/pull/16078)\n  [#16085](https://github.com/rust-lang/cargo/pull/16085)\n  [#16107](https://github.com/rust-lang/cargo/pull/16107)\n  [#16108](https://github.com/rust-lang/cargo/pull/16108)\n- Clarify git sources vs git registries in source replacement documentation\n  [#15974](https://github.com/rust-lang/cargo/pull/15974)\n- Clarify what we mean by omitting features in registry index documentation\n  [#15957](https://github.com/rust-lang/cargo/pull/15957)\n- Clarify the role of the lockfile in dependency resolution\n  [#15958](https://github.com/rust-lang/cargo/pull/15958)\n- Clarify multiple version requirement behavior\n  [#15979](https://github.com/rust-lang/cargo/pull/15979)\n- Clarify that `target.<cfg>.linker` is supported\n  [#16112](https://github.com/rust-lang/cargo/pull/16112)\n- Explain Cargo config deserialization internals\n  [#16105](https://github.com/rust-lang/cargo/pull/16105)\n  [#16094](https://github.com/rust-lang/cargo/pull/16094)\n- contrib: Move docs building process to contributor guide\n  [#15854](https://github.com/rust-lang/cargo/pull/15854)\n- SemVer: Recommend `package.rust-version` in the Rust version section\n  [#15806](https://github.com/rust-lang/cargo/pull/15806)\n\n### Internal\n\n- Make GlobalContext Sync\n  [#15967](https://github.com/rust-lang/cargo/pull/15967)\n- Centralize Cargo console output styling\n  [#16124](https://github.com/rust-lang/cargo/pull/16124)\n  [#16135](https://github.com/rust-lang/cargo/pull/16135)\n- Refactor `Layout` into `BuildDirLayout` and `ArtifactDirLayout`\n  [#16092](https://github.com/rust-lang/cargo/pull/16092)\n- cargo-test-support: Add track_caller to know the actual failure\n  [#16069](https://github.com/rust-lang/cargo/pull/16069)\n- cargo-test-support: Added better filesystem layout testing harness\n  [#15874](https://github.com/rust-lang/cargo/pull/15874)\n- cargo-util-schemas: Move lockfile schemas in\n  [#15980](https://github.com/rust-lang/cargo/pull/15980)\n  [#15990](https://github.com/rust-lang/cargo/pull/15990)\n  [#16039](https://github.com/rust-lang/cargo/pull/16039)\n- ci: Skip check-version-bump ci job in forks\n  [#15959](https://github.com/rust-lang/cargo/pull/15959)\n- config: various internal cleanup and refactor for `ConfigValue`\n  [#16067](https://github.com/rust-lang/cargo/pull/16067)\n  [#16084](https://github.com/rust-lang/cargo/pull/16084)\n  [#16091](https://github.com/rust-lang/cargo/pull/16091)\n  [#16100](https://github.com/rust-lang/cargo/pull/16100)\n  [#16109](https://github.com/rust-lang/cargo/pull/16109)\n- perf: JSON message with less allocations\n  [#16130](https://github.com/rust-lang/cargo/pull/16130)\n- test: null-terminated path for reserved windows name detection\n  [#16052](https://github.com/rust-lang/cargo/pull/16052)\n- test: Don't look for a specific ANSI color\n  [#16118](https://github.com/rust-lang/cargo/pull/16118)\n- test: Fix test that assumes `CARGO_CFG_TARGET_FAMILY` is a single value\n  [#16079](https://github.com/rust-lang/cargo/pull/16079)\n- Update dependencies.\n  [#15988](https://github.com/rust-lang/cargo/pull/15988)\n  [#15984](https://github.com/rust-lang/cargo/pull/15984)\n  [#15989](https://github.com/rust-lang/cargo/pull/15989)\n  [#15992](https://github.com/rust-lang/cargo/pull/15992)\n  [#15993](https://github.com/rust-lang/cargo/pull/15993)\n  [#16009](https://github.com/rust-lang/cargo/pull/16009)\n  [#16031](https://github.com/rust-lang/cargo/pull/16031)\n  [#16034](https://github.com/rust-lang/cargo/pull/16034)\n\n## Cargo 1.91 (2025-10-30)\n[840b83a1...rust-1.91.0](https://github.com/rust-lang/cargo/compare/840b83a1...rust-1.91.0)\n\n### Added\n\n- 🎉 Stabilize `build.build-dir`.\n  This config sets the directory where intermediate build artifacts are stored.\n  These artifacts are produced by Cargo and rustc during the build process.\n  End users usually won't need to interact with them, and the layout inside\n  `build-dir` is an implementation detail that may change without notice.\n  ([config doc](https://doc.rust-lang.org/nightly/cargo/reference/config.html#buildbuild-dir))\n  ([build cache doc](https://doc.rust-lang.org/nightly/cargo/reference/build-cache.html))\n  [#15833](https://github.com/rust-lang/cargo/pull/15833)\n  [#15840](https://github.com/rust-lang/cargo/pull/15840)\n- The `--target` flag and the `build.target` configuration can now take literal\n  `\"host-tuple\"` string, which will internally be substituted by the host\n  machine's target triple.\n  [#15838](https://github.com/rust-lang/cargo/pull/15838)\n  [#16003](https://github.com/rust-lang/cargo/pull/16003)\n  [#16032](https://github.com/rust-lang/cargo/pull/16032)\n\n### Changed\n\n- ❗️ `cargo publish` no longer keeps `.crate` tarballs as final build artifacts\n  when `build.build-dir` is set. These tarballs were previously included due to\n  an oversight and are now treated as intermediate artifacts.\n  To get `.crate` tarballs as final artifacts, use `cargo package`.\n  In a future version, this change will apply regardless of `build.build-dir`.\n  [#15910](https://github.com/rust-lang/cargo/pull/15910)\n- Adjust Cargo messages to match rustc diagnostic style\n  [#15928](https://github.com/rust-lang/cargo/pull/15928)\n- More helpful error for invalid `cargo-features = []`\n  [#15781](https://github.com/rust-lang/cargo/pull/15781)\n- Don't stop at first error when emitting lints and warnings\n  [#15889](https://github.com/rust-lang/cargo/pull/15889)\n- Show the bad manifest path in the error message\n  [#15896](https://github.com/rust-lang/cargo/pull/15896)\n- Suggest workspace hints for invalid boolean dependencies\n  [#15507](https://github.com/rust-lang/cargo/pull/15507)\n- cargo-package: Always reuse the workspace's target-dir during the package\n  verification. Previously Cargo created a new standalone target directory\n  within the unpacked source.\n  [#15783](https://github.com/rust-lang/cargo/pull/15783)\n- cargo-publish: Add more context to publish-failed error message\n  [#15879](https://github.com/rust-lang/cargo/pull/15879)\n\n### Fixed\n\n### Nightly only\n\n- 🔥 `-Zsection-timings` extend the output of `cargo build --timings`. It tells\n  rustc to produce timings of individual compilation sections, which will be\n  then displayed in the timings HTML/JSON output.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#section-timings))\n  [#15780](https://github.com/rust-lang/cargo/pull/15780)\n  [#15923](https://github.com/rust-lang/cargo/pull/15923)\n- 🔥 `-Zbuild-dir-new-layout` enables the new build-dir filesystem layout, which\n  unblocks work towards caching and locking improvements.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-dir-new-layout))\n  ([project goal](https://rust-lang.github.io/rust-project-goals/2025h2/cargo-build-dir-layout.html))\n  [#15848](https://github.com/rust-lang/cargo/pull/15848)\n- 🔥 `-Zbuild-analysis` records and persists detailed build metrics (timings, rebuild reasons, etc.)\n  across runs, with new commands to query past builds.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-analysis))\n  ([project goal](https://rust-lang.github.io/rust-project-goals/2025h2/cargo-build-analysis.html))\n  [#15845](https://github.com/rust-lang/cargo/pull/15845)\n- `multiple-build-scripts`:  Accessing each build script's `OUT_DIR` and in the\n  correct order\n  [#15776](https://github.com/rust-lang/cargo/pull/15776)\n- `-Zcargo-lints`: Linting system infra improvement\n  [#15865](https://github.com/rust-lang/cargo/pull/15865)\n- `-Zscript`: Cover some frontmatter corner cases\n  [#15886](https://github.com/rust-lang/cargo/pull/15886)\n- `-Zscript`: Match test updates in rustc\n  [#15878](https://github.com/rust-lang/cargo/pull/15878)\n- `-Zscript`: Switch frontmatter tests to end-to-end\n  [#15899](https://github.com/rust-lang/cargo/pull/15899)\n- `-Zscript`: Report script manifest errors for the right line number\n  [#15927](https://github.com/rust-lang/cargo/pull/15927)\n- `-Zscript`: Pull out as a dedicated mod\n  [#15914](https://github.com/rust-lang/cargo/pull/15914)\n\n### Documentation\n\n- Clarify that `cargo doc --no-deps` is cumulative and won’t delete prev\n  [#15800](https://github.com/rust-lang/cargo/pull/15800)\n- Switch from `--nocapture` to `--no-capture` in docs and help text.\n  [#15930](https://github.com/rust-lang/cargo/pull/15930)\n- Mention how Cargo fetch git submodules\n  [#15853](https://github.com/rust-lang/cargo/pull/15853)\n  [#15860](https://github.com/rust-lang/cargo/pull/15860)\n- Link out to the Plumbing commands effort\n  [#15821](https://github.com/rust-lang/cargo/pull/15821)\n- Switch to using native mdbook fragment redirects\n  [#15861](https://github.com/rust-lang/cargo/pull/15861)\n- Reorder `lto` options in profiles\n  [#15841](https://github.com/rust-lang/cargo/pull/15841)\n  [#15855](https://github.com/rust-lang/cargo/pull/15855)\n\n### Internal\n\n- Replace ad-hoc flock implementation with std flock\n  [#15935](https://github.com/rust-lang/cargo/pull/15935)\n  [#15941](https://github.com/rust-lang/cargo/pull/15941)\n- Prepare for annotate-snippets `Report`s being generated in more places\n  [#15920](https://github.com/rust-lang/cargo/pull/15920)\n  [#15926](https://github.com/rust-lang/cargo/pull/15926)\n- test: avoid hardcoded target spec json\n  [#15880](https://github.com/rust-lang/cargo/pull/15880)\n- test: Ensure consistent behavior regardless of rustup use\n  [#15949](https://github.com/rust-lang/cargo/pull/15949)\n- test: Switch more expected results to snapshots for credential process\n  [#15929](https://github.com/rust-lang/cargo/pull/15929)\n- ci: Add Arm64 Windows CI jobs\n  [#15790](https://github.com/rust-lang/cargo/pull/15790)\n- ci: remove x86_64-apple-darwin from CI and tests\n  [#15831](https://github.com/rust-lang/cargo/pull/15831)\n- Update dependencies.\n  [#15795](https://github.com/rust-lang/cargo/pull/15795)\n  [#15804](https://github.com/rust-lang/cargo/pull/15804)\n  [#15815](https://github.com/rust-lang/cargo/pull/15815)\n  [#15816](https://github.com/rust-lang/cargo/pull/15816)\n  [#15819](https://github.com/rust-lang/cargo/pull/15819)\n  [#15825](https://github.com/rust-lang/cargo/pull/15825)\n  [#15832](https://github.com/rust-lang/cargo/pull/15832)\n  [#15851](https://github.com/rust-lang/cargo/pull/15851)\n  [#15898](https://github.com/rust-lang/cargo/pull/15898)\n  [#15904](https://github.com/rust-lang/cargo/pull/15904)\n  [#15909](https://github.com/rust-lang/cargo/pull/15909)\n  [#15918](https://github.com/rust-lang/cargo/pull/15918)\n  [#15950](https://github.com/rust-lang/cargo/pull/15950)\n\n## Cargo 1.90 (2025-09-18)\n[c24e1064...rust-1.90.0](https://github.com/rust-lang/cargo/compare/c24e1064...rust-1.90.0)\n\n### Added\n\n- 🎉 Stabilize multi-package publishing.\n  This allows cargo to publish multiple crates in a workspace, even if they\n  have inter-dependencies. For example, `cargo publish --workspace` or\n  `cargo publish -p foo -p bar`.\n  Note that `cargo publish` is still non-atomic at this time. If there is a\n  server side error during the publish, the workspace will be left in a\n  partially published state.\n  [#15636](https://github.com/rust-lang/cargo/pull/15636)\n  [#15711](https://github.com/rust-lang/cargo/pull/15711)\n- Added `http.proxy-cainfo` config for proxy TLS certificates.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#httpproxy-cainfo)\n  [#15374](https://github.com/rust-lang/cargo/pull/15374)\n\n### Changed\n\n- cargo-package: Use `gix` to speed up Git status check by 10-20%.\n  [#15534](https://github.com/rust-lang/cargo/pull/15534)\n- Make timings graphs scalable to user's window.\n  [#15766](https://github.com/rust-lang/cargo/pull/15766)\n- Report valid file name when we can't find a build target for `name = \"foo.rs\"` \n  [#15707](https://github.com/rust-lang/cargo/pull/15707)\n\n### Fixed\n\n- cargo-credential-libsecret: give FFI correctly-sized object \n  [#15767](https://github.com/rust-lang/cargo/pull/15767)\n- cargo-publish: includes manifest paths in errors when verifying\n  [#15705](https://github.com/rust-lang/cargo/pull/15705)\n- cargo-tree: Fixed `no-proc-macro` being overridden by subsequent edges.\n  [#15764](https://github.com/rust-lang/cargo/pull/15764)\n\n### Nightly only\n\n- 🔥 `multiple-build-scripts`: Allows you to have multiple build scripts in your package.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#multiple-build-scripts)\n  [#15630](https://github.com/rust-lang/cargo/pull/15630)\n  [#15704](https://github.com/rust-lang/cargo/pull/15704)\n- 🔥 `-Zprofile-hint-mostly-unused`: Add `[hints]` table in `Cargo.toml`,\n  and a `hints.mostly-unused` hint.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-hint-mostly-unused-option)\n  [#15673](https://github.com/rust-lang/cargo/pull/15673)\n- `-Zfeature-unification`: implemented per-package feature unification\n  [#15684](https://github.com/rust-lang/cargo/pull/15684)\n- `-Zsbom`: Clarify package ID specifications in SBOMs are fully qualified \n  [#15731](https://github.com/rust-lang/cargo/pull/15731)\n\n### Documentation\n\n### Internal\n\n- build-rs: auto-publish on toolchain release\n  [#15708](https://github.com/rust-lang/cargo/pull/15708)\n- cargo-util-schemas: Expose `IndexPackage`, the description of a package within a Registry Index \n  [#15770](https://github.com/rust-lang/cargo/pull/15770)\n- ci: update cargo-semver-checks to v0.42.0 \n  [#15730](https://github.com/rust-lang/cargo/pull/15730)\n- perf: Speed up TOML parsing by upgrading toml \n  [#15736](https://github.com/rust-lang/cargo/pull/15736)\n  [#15779](https://github.com/rust-lang/cargo/pull/15779)\n- test: Rework `cargo-test-support` & `testsuite` to use `CARGO_BIN_EXE_*` for Cargo \n  [#15692](https://github.com/rust-lang/cargo/pull/15692)\n- test: Use a different lint to simulate diagnostic duplicates\n  [#15713](https://github.com/rust-lang/cargo/pull/15713)\n  [#15717](https://github.com/rust-lang/cargo/pull/15717)\n- test: Switch config tests to use snapshots \n  [#15729](https://github.com/rust-lang/cargo/pull/15729)\n- test: Remove unnecessary target-c-int-width from target specs \n  [#15759](https://github.com/rust-lang/cargo/pull/15759)\n- test: Mark cachelock tests that rely on interprocess blocking behaviour as unsupported on AIX. \n  [#15734](https://github.com/rust-lang/cargo/pull/15734)\n- Expose artifact dependency getters in cargo-as-a-library \n  [#15753](https://github.com/rust-lang/cargo/pull/15753)\n- Allow using Cargo-as-a-library with gix's reqwest backend \n  [#15653](https://github.com/rust-lang/cargo/pull/15653)\n- Update to Rust 2024\n  [#15732](https://github.com/rust-lang/cargo/pull/15732)\n- Update dependencies.\n  [#15706](https://github.com/rust-lang/cargo/pull/15706)\n  [#15709](https://github.com/rust-lang/cargo/pull/15709)\n  [#15722](https://github.com/rust-lang/cargo/pull/15722)\n\n## Cargo 1.89 (2025-08-07)\n[873a0649...rust-1.89.0](https://github.com/rust-lang/cargo/compare/873a0649...rust-1.89.0)\n\n### Added\n\n- Add `*` and `?` pattern support for SSH known hosts matching.\n  [#15508](https://github.com/rust-lang/cargo/pull/15508)\n- Stabilize doctest-xcompile. Doctests will now automatically be tested when cross-compiling to a target that is different from the host, just like other tests.\n  [#15462](https://github.com/rust-lang/cargo/pull/15462)\n\n### Changed\n\n- ❗️ `cargo fix` and `cargo clippy --fix` now run only on the default Cargo\n  targets by default, matching the behavior of `cargo check`. To run on all\n  Cargo targets, use the `--all-targets` flag. This change aligns the behavior\n  with other commands. Edition flags like `--edition` and `--edition-idioms`\n  remain implying `--all-targets` by default.\n  [#15192](https://github.com/rust-lang/cargo/pull/15192)\n- Respect `Retry-After` header for HTTP 429 responses when talking to registries.\n  [#15463](https://github.com/rust-lang/cargo/pull/15463)\n- Improved error message for the `CRATE[@<VER>]` argument prefixed with `v`.\n  [#15484](https://github.com/rust-lang/cargo/pull/15484)\n- Improved error message for the `CRATE[@<VER>]` argument with invalid package\n  name characters.\n  [#15441](https://github.com/rust-lang/cargo/pull/15441)\n- cargo-add: suggest similarly named features \n  [#15438](https://github.com/rust-lang/cargo/pull/15438)\n\n### Fixed\n\n- Fixed potential deadlock in `CacheState::lock`\n  [#15698](https://github.com/rust-lang/cargo/pull/15698)\n  [#15699](https://github.com/rust-lang/cargo/pull/15699)\n- Fixed the `--manifest-path` arg being ignored in `cargo fix`\n  [#15633](https://github.com/rust-lang/cargo/pull/15633)\n- When publishing, don't tell people to ctrl-c without knowing consequences.\n  [#15632](https://github.com/rust-lang/cargo/pull/15632)\n- Added missing `--offline` in shell completions.\n  [#15623](https://github.com/rust-lang/cargo/pull/15623)\n- cargo-credential-libsecret: load libsecret only once\n  [#15295](https://github.com/rust-lang/cargo/pull/15295)\n- When failing to find the mtime of a file for rebuild detection, report an explicit reason rather than \"stale; unknown reason\".\n  [#15617](https://github.com/rust-lang/cargo/pull/15617)\n- Fixed cargo add overwriting symlinked Cargo.toml files\n  [#15281](https://github.com/rust-lang/cargo/pull/15281)\n- Vendor files with .rej/.orig suffix\n  [#15569](https://github.com/rust-lang/cargo/pull/15569)\n- Vendor using direct extraction for registry sources. This should ensure that vendored files now always match the originals.\n  [#15514](https://github.com/rust-lang/cargo/pull/15514)\n- In the network retry message, use singular \"try\" for the last retry.\n  [#15328](https://github.com/rust-lang/cargo/pull/15328)\n\n### Nightly only\n\n- 🔥 `-Zno-embed-metadata`: This tells Cargo to pass the `-Zembed-metadata=no`\n  flag to the compiler, which instructs it not to embed metadata within rlib\n  and dylib artifacts. In this case, the metadata will only be stored in\n  `.rmeta` files.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#no-embed-metadata))\n  [#15378](https://github.com/rust-lang/cargo/pull/15378)\n- 🔥 Plumb rustc `-Zhint-mostly-unused` flag through as a profile option\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-hint-mostly-unused-option))\n  [#15643](https://github.com/rust-lang/cargo/pull/15643)\n- Added the \"future\" edition\n  [#15595](https://github.com/rust-lang/cargo/pull/15595)\n- Added `-Zfix-edition`\n  [#15596](https://github.com/rust-lang/cargo/pull/15596)\n- Added perma unstable `--compile-time-deps` option for `cargo build`\n  [#15674](https://github.com/rust-lang/cargo/pull/15674)\n- `-Zscript`: Make cargo script ignore workspaces.\n  [#15496](https://github.com/rust-lang/cargo/pull/15496)\n- `-Zpackage-workspace`: keep dev-dependencies if they have a version.\n  [#15470](https://github.com/rust-lang/cargo/pull/15470)\n- Added custom completer for `cargo remove <TAB>`\n  [#15662](https://github.com/rust-lang/cargo/pull/15662)\n- Test improvements in prep for `-Zpackage-workspace` stabilization\n  [#15628](https://github.com/rust-lang/cargo/pull/15628)\n- Allow packaging of self-cycles with `-Zpackage-workspace`\n  [#15626](https://github.com/rust-lang/cargo/pull/15626)\n- With trim-paths, remap all paths to `build.build-dir`\n  [#15614](https://github.com/rust-lang/cargo/pull/15614)\n- Enable more trim-paths tests for windows-msvc\n  [#15621](https://github.com/rust-lang/cargo/pull/15621)\n- Fix doc rebuild detection by passing `toolchain-shared-resources` to get doc styled for rustdoc-depinfo tracking\n  [#15605](https://github.com/rust-lang/cargo/pull/15605)\n- Resolve multiple bugs in frontmatter parser for `-Zscript`\n  [#15573](https://github.com/rust-lang/cargo/pull/15573)\n- Remove workaround for rustc frontmatter support for `-Zscript`\n  [#15570](https://github.com/rust-lang/cargo/pull/15570)\n- Allow configuring arbitrary codegen backends\n  [#15562](https://github.com/rust-lang/cargo/pull/15562)\n- skip `publish=false` pkg when publishing entire workspace for `-Zpackage-workspace`.\n  [#15525](https://github.com/rust-lang/cargo/pull/15525)\n- Update instructions on using native-completions\n  [#15480](https://github.com/rust-lang/cargo/pull/15480)\n- Skip registry check if its not needed with `-Zpackage-workspace`.\n  [#15629](https://github.com/rust-lang/cargo/pull/15629)\n\n### Documentation\n\n- Clarify what commands need and remove confusing example\n  [#15457](https://github.com/rust-lang/cargo/pull/15457)\n- Update fingerprint footnote\n  [#15478](https://github.com/rust-lang/cargo/pull/15478)\n- home: update version notice for deprecation removal \n  [#15511](https://github.com/rust-lang/cargo/pull/15511)\n- docs(contrib): change clap URL to docs.rs/clap\n  [#15682](https://github.com/rust-lang/cargo/pull/15682)\n- Update links in contrib docs\n  [#15659](https://github.com/rust-lang/cargo/pull/15659)\n- docs: clarify `--all-features` not available for all commands\n  [#15572](https://github.com/rust-lang/cargo/pull/15572)\n- docs(README): fix the link to the changelog in the Cargo book\n  [#15597](https://github.com/rust-lang/cargo/pull/15597)\n\n### Internal\n\n- Refactor artifact deps in FeatureResolver::deps\n  [#15492](https://github.com/rust-lang/cargo/pull/15492)\n- Added tracing spans for rustc invocations\n  [#15464](https://github.com/rust-lang/cargo/pull/15464)\n- ci: migrate renovate config \n  [#15501](https://github.com/rust-lang/cargo/pull/15501)\n- ci: Require schema job to pass\n  [#15504](https://github.com/rust-lang/cargo/pull/15504)\n- test: Remove unused nightly requirements\n  [#15498](https://github.com/rust-lang/cargo/pull/15498)\n- Update dependencies.\n  [#15456](https://github.com/rust-lang/cargo/pull/15456)\n- refactor: replace InternedString with Cow in IndexPackage\n  [#15559](https://github.com/rust-lang/cargo/pull/15559)\n- Use `Not::not` rather than a custom `is_false` function\n  [#15645](https://github.com/rust-lang/cargo/pull/15645)\n- fix: Make UI tests handle hyperlinks consistently\n  [#15640](https://github.com/rust-lang/cargo/pull/15640)\n- Update dependencies\n  [#15635](https://github.com/rust-lang/cargo/pull/15635)\n  [#15557](https://github.com/rust-lang/cargo/pull/15557)\n- refactor: clean up `clippy::perf` lint warnings\n  [#15631](https://github.com/rust-lang/cargo/pull/15631)\n- chore(deps): update alpine docker tag to v3.22\n  [#15616](https://github.com/rust-lang/cargo/pull/15616)\n- chore: remove HTML comments in PR template and inline guide\n  [#15613](https://github.com/rust-lang/cargo/pull/15613)\n- Added .git-blame-ignore-revs\n  [#15612](https://github.com/rust-lang/cargo/pull/15612)\n- refactor: cleanup for `CompileMode`\n  [#15608](https://github.com/rust-lang/cargo/pull/15608)\n- refactor: separate \"global\" mode from CompileMode\n  [#15601](https://github.com/rust-lang/cargo/pull/15601)\n- chore: Upgrade schemars\n  [#15602](https://github.com/rust-lang/cargo/pull/15602)\n- Update gix & socket2\n  [#15600](https://github.com/rust-lang/cargo/pull/15600)\n- chore(toml): disable `toml`'s default features, unless necessary, to reduce cargo-util-schemas build time\n  [#15598](https://github.com/rust-lang/cargo/pull/15598)\n- chore(gh): Add new-lint issue template\n  [#15575](https://github.com/rust-lang/cargo/pull/15575)\n- Fix comment for cargo/core/compiler/fingerprint/mod.rs\n  [#15565](https://github.com/rust-lang/cargo/pull/15565)\n\n## Cargo 1.88 (2025-06-26)\n[a6c604d1...rust-1.88.0](https://github.com/rust-lang/cargo/compare/a6c604d1...rust-1.88.0)\n\n### Added\n\n- 🎉 Stabilize automatic garbage collection for global caches.\n\n  When building, Cargo downloads and caches crates needed as dependencies.\n  Historically, these downloaded files would never be cleaned up, leading to an\n  unbounded amount of disk usage in Cargo's home directory. In this version,\n  Cargo introduces a garbage collection mechanism to automatically clean up old\n  files (e.g. .crate files). Cargo will remove files downloaded from the network\n  if not accessed in 3 months, and files obtained from the local system if not\n  accessed in 1 month. Note that this automatic garbage collection will not take\n  place if running offline (using `--offline` or `--frozen`).\n\n  Cargo 1.78 and newer track the access information needed for this garbage\n  collection. If you regularly use versions of Cargo older than 1.78, in\n  addition to running current versions of Cargo, and you expect to have some\n  crates accessed exclusively by the older versions of Cargo and don't want to\n  re-download those crates every ~3 months, you may wish to set\n  `cache.auto-clean-frequency = \"never\"` in the Cargo configuration.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#cache))\n  [#14287](https://github.com/rust-lang/cargo/pull/14287)\n- Allow boolean literals as cfg predicates in Cargo.toml and configurations.\n  For example, `[target.'cfg(not(false))'.dependencies]` is a valid cfg predicate.\n  ([RFC 3695](https://github.com/rust-lang/rfcs/pull/3695))\n  [#14649](https://github.com/rust-lang/cargo/pull/14649)\n\n### Changed\n\n- Don't canonicalize executable path for the `CARGO` environment variable.\n  [#15355](https://github.com/rust-lang/cargo/pull/15355)\n- Print target and package names formatted as file hyperlinks.\n  [#15405](https://github.com/rust-lang/cargo/pull/15405)\n- Make sure library search paths inside `OUT_DIR` precede external paths.\n  [#15221](https://github.com/rust-lang/cargo/pull/15221)\n- Suggest similar looking feature names when feature is missing.\n  [#15454](https://github.com/rust-lang/cargo/pull/15454)\n- Use `zlib-rs` for gzip (de)compression for `.crate` tarballs.\n  [#15417](https://github.com/rust-lang/cargo/pull/15417)\n\n### Fixed\n\n- build-rs: Correct name of `CARGO_CFG_FEATURE`\n  [#15420](https://github.com/rust-lang/cargo/pull/15420)\n- cargo-tree: Make output more deterministic\n  [#15369](https://github.com/rust-lang/cargo/pull/15369)\n- cargo-package: dont fail the entire command when the dirtiness check failed,\n  as git status check is mostly informational.\n  [#15416](https://github.com/rust-lang/cargo/pull/15416)\n  [#15419](https://github.com/rust-lang/cargo/pull/15419)\n- Fixed `cargo rustc --bin` panicking on unknown bin names\n  [#15515](https://github.com/rust-lang/cargo/pull/15515)\n  [#15497](https://github.com/rust-lang/cargo/pull/15497)\n\n### Nightly only\n\n- 🔥 `-Zrustdoc-depinfo`: A new unstable flag leveraging rustdoc’s dep-info\n  files to determine whether documentations are required to re-generate.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#rustdoc-depinfo))\n  [#15359](https://github.com/rust-lang/cargo/pull/15359)\n  [#15371](https://github.com/rust-lang/cargo/pull/15371)\n- `build-dir`: Added validation for unmatched brackets in build-dir template \n  [#15414](https://github.com/rust-lang/cargo/pull/15414)\n- `build-dir`: Improved error message when build-dir template var is invalid \n  [#15418](https://github.com/rust-lang/cargo/pull/15418)\n- `build-dir`: Added `build_directory` field to cargo metadata output \n  [#15377](https://github.com/rust-lang/cargo/pull/15377)\n- `build-dir`: Added symlink resolution for `workspace-path-hash` \n  [#15400](https://github.com/rust-lang/cargo/pull/15400)\n- `build-dir`: Added build_directory to cargo metadata documentation \n  [#15410](https://github.com/rust-lang/cargo/pull/15410)\n- `unit-graph`: switch to Package ID Spec.\n  [#15447](https://github.com/rust-lang/cargo/pull/15447)\n- `-Zgc`: Rename the `gc` config table to `[cache]`.\n  Low-level settings is now under `[cache.global-clean]`.\n  [#15367](https://github.com/rust-lang/cargo/pull/15367)\n- `-Zdoctest-xcompile`: Update doctest xcompile flags.\n  [#15455](https://github.com/rust-lang/cargo/pull/15455)\n\n### Documentation\n\n- Mention the convention of kebab-case for Cargo targets naming.\n  [#14439](https://github.com/rust-lang/cargo/pull/14439)\n- Use better example value in `CARGO_CFG_TARGET_ABI` \n  [#15404](https://github.com/rust-lang/cargo/pull/15404)\n\n### Internal\n\n- Fix formatting of CliUnstable parsing\n  [#15434](https://github.com/rust-lang/cargo/pull/15434)\n- ci: restore semver-checks for cargo-util\n  [#15389](https://github.com/rust-lang/cargo/pull/15389)\n- ci: add aarch64 linux runner\n  [#15077](https://github.com/rust-lang/cargo/pull/15077)\n- rustfix: Use `snapbox` for snapshot testing\n  [#15429](https://github.com/rust-lang/cargo/pull/15429)\n- test:Prevent undeclared public network access \n  [#15368](https://github.com/rust-lang/cargo/pull/15368)\n- Update dependencies.\n  [#15373](https://github.com/rust-lang/cargo/pull/15373)\n  [#15381](https://github.com/rust-lang/cargo/pull/15381)\n  [#15391](https://github.com/rust-lang/cargo/pull/15391)\n  [#15394](https://github.com/rust-lang/cargo/pull/15394)\n  [#15403](https://github.com/rust-lang/cargo/pull/15403)\n  [#15415](https://github.com/rust-lang/cargo/pull/15415)\n  [#15421](https://github.com/rust-lang/cargo/pull/15421)\n  [#15446](https://github.com/rust-lang/cargo/pull/15446)\n\n\n## Cargo 1.87 (2025-05-15)\n[ce948f46...rust-1.87.0](https://github.com/rust-lang/cargo/compare/ce948f46...rust-1.87.0)\n\n### Added\n\n- Add terminal integration via ANSI OSC 9;4 sequences via the\n  `term.progress.term-integration` configuration field. This reports progress\n  to the terminal emulator for display in places like the task bar.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#termprogressterm-integration))\n  [#14615](https://github.com/rust-lang/cargo/pull/14615)\n- Forward bash completions of third party subcommands \n  [#15247](https://github.com/rust-lang/cargo/pull/15247)\n- cargo-tree: Color the output.\n  [#15242](https://github.com/rust-lang/cargo/pull/15242)\n- cargo-package: add `--exclude-lockfile` flag, which will stop verifying the\n  lock file if present.\n  [#15234](https://github.com/rust-lang/cargo/pull/15234)\n\n### Changed\n\n- ❗️ Cargo now depends on OpenSSL v3. This implies that Cargo in the official\n  Rust distribution will have a hard dependency on libatomic on 32-bit platforms.\n  [#15232](https://github.com/rust-lang/cargo/pull/15232)\n- Report `<target>.edition` deprecation to users.\n  [#15321](https://github.com/rust-lang/cargo/pull/15321)\n- Leverage clap for providing default values for `--vcs`, `--color`, and `--message-format` flags.\n  [#15322](https://github.com/rust-lang/cargo/pull/15322)\n- Mention \"3\" as a valid value for \"resolver\" field in error message \n  [#15215](https://github.com/rust-lang/cargo/pull/15215)\n- Uplift windows Cygwin DLL import libraries \n  [#15193](https://github.com/rust-lang/cargo/pull/15193)\n- Include the package name also in the target hint message.\n  [#15199](https://github.com/rust-lang/cargo/pull/15199)\n- cargo-add: collapse large feature lists\n  [#15200](https://github.com/rust-lang/cargo/pull/15200)\n- cargo-vendor: Add context which workspace failed to resolve\n  [#15297](https://github.com/rust-lang/cargo/pull/15297)\n\n### Fixed\n\n- Do not pass cdylib link args from `cargo::rustc-link-arg-cdylib` to tests.\n  [#15317](https://github.com/rust-lang/cargo/pull/15317)\n  [#15326](https://github.com/rust-lang/cargo/pull/15326)\n- Don't use `$CARGO_BUILD_TARGET` in `cargo metadata`.\n  [#15271](https://github.com/rust-lang/cargo/pull/15271)\n- Allow `term.progress.when` to have default values. `CARGO_TERM_PROGRESS_WIDTH`\n  can now be correctly set even when other settings are missing.\n  [#15287](https://github.com/rust-lang/cargo/pull/15287)\n- Fix the `CARGO` environment variable setting for external subcommands\n  pointing to the wrong Cargo binary path . Note that the environment variable\n  is never designed as a general Cargo wrapper.\n  [#15208](https://github.com/rust-lang/cargo/pull/15208)\n- Fix some issues with future-incompat report generation.\n  [#15345](https://github.com/rust-lang/cargo/pull/15345)\n- Respect `--frozen` everywhere `--offline` or `--locked` is accepted.\n  [#15263](https://github.com/rust-lang/cargo/pull/15263)\n- cargo-package: report also the VCS status of the workspace manifest if dirty.\n  [#15276](https://github.com/rust-lang/cargo/pull/15276)\n  [#15341](https://github.com/rust-lang/cargo/pull/15341)\n- cargo-publish: Fix man page with malformed `{{#options}}` block\n  [#15191](https://github.com/rust-lang/cargo/pull/15191)\n- cargo-run: Disambiguate bins from different packages that share a name.\n  [#15298](https://github.com/rust-lang/cargo/pull/15298)\n- cargo-rustc: de-duplicate crate types.\n  [#15314](https://github.com/rust-lang/cargo/pull/15314)\n- cargo-vendor: dont remove non-cached sources.\n  [#15260](https://github.com/rust-lang/cargo/pull/15260)\n\n### Nightly only\n\n- 🔥 cargo-package: add unstable `--message-format` flag. The flag is providing\n  an alternative JSON output format for file listing of the `--list` flag.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#package-message-format))\n  [#15311](https://github.com/rust-lang/cargo/pull/15311)\n  [#15354](https://github.com/rust-lang/cargo/pull/15354)\n- 🔥 `build-dir`: the `build.build-dir` config option to set the directory where\n  intermediate build artifacts will be stored.\n  Intermediate artifacts are produced by Rustc/Cargo during the build process.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-dir))\n  [#15104](https://github.com/rust-lang/cargo/pull/15104)\n  [#15236](https://github.com/rust-lang/cargo/pull/15236)\n  [#15334](https://github.com/rust-lang/cargo/pull/15334)\n- 🔥 `-Zsbom`: The `build.sbom` config allows to generate so-called SBOM\n  pre-cursor files alongside each compiled artifact.\n  ([RFC 3553](https://github.com/rust-lang/rfcs/pull/3553))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#sbom))\n  [#13709](https://github.com/rust-lang/cargo/pull/13709)\n- 🔥 `-Zpublic-dependency`: new `--depth public` value for `cargo tree` to\n  display public dependencies.\n  [#15243](https://github.com/rust-lang/cargo/pull/15243)\n- `-Zscript`: Handle more frontmatter parsing corner cases\n  [#15187](https://github.com/rust-lang/cargo/pull/15187)\n- `-Zpackage-workspace`: Fix lookups to capitalized workspace member's index entry \n  [#15216](https://github.com/rust-lang/cargo/pull/15216)\n- `-Zpackage-workspace`: Register workspace member renames in overlay \n  [#15228](https://github.com/rust-lang/cargo/pull/15228)\n- `-Zpackage-workspace`: Ensure we can package directories ending with '.rs' \n  [#15240](https://github.com/rust-lang/cargo/pull/15240)\n- `native-completions`: add completions for `--profile`\n  [#15308](https://github.com/rust-lang/cargo/pull/15308)\n- `native-completions`: add completions for aliases\n  [#15319](https://github.com/rust-lang/cargo/pull/15319)\n- `native-completions`: add completions for `cargo add --path`\n  [#15288](https://github.com/rust-lang/cargo/pull/15288)\n- `native-completions`: add completions for `--manifest-path` \n  [#15225](https://github.com/rust-lang/cargo/pull/15225)\n- `native-completions`: add completions for `--lockfile-path` \n  [#15238](https://github.com/rust-lang/cargo/pull/15238)\n- `native-completions`: add completions for `cargo install --path`\n  [#15266](https://github.com/rust-lang/cargo/pull/15266)\n- `native-completions`: add completions fro `+<toolchain>`\n  [#15301](https://github.com/rust-lang/cargo/pull/15301)\n\n### Documentation\n\n- Note that target-edition is deprecated \n  [#15292](https://github.com/rust-lang/cargo/pull/15292)\n- Mention wrong URLs as a cause of git authentication errors \n  [#15304](https://github.com/rust-lang/cargo/pull/15304)\n- Shift focus to resolver v3 \n  [#15213](https://github.com/rust-lang/cargo/pull/15213)\n- Lockfile is always included since 1.84 \n  [#15257](https://github.com/rust-lang/cargo/pull/15257)\n- Remove `Cargo.toml` from `package.include` in example \n  [#15253](https://github.com/rust-lang/cargo/pull/15253)\n- Make it clearer that `rust_version` is enforced during compile\n  [#15303](https://github.com/rust-lang/cargo/pull/15303)\n- Fix `[env]` `relative` description in reference \n  [#15332](https://github.com/rust-lang/cargo/pull/15332)\n- Add `unsafe` to `extern` while using build scripts in Cargo Book \n  [#15294](https://github.com/rust-lang/cargo/pull/15294)\n- Mention `x.y.*` as a kind of version requirement to avoid. \n  [#15310](https://github.com/rust-lang/cargo/pull/15310)\n- contrib: Expand the description of team meetings \n  [#15349](https://github.com/rust-lang/cargo/pull/15349)\n\n### Internal\n\n- Show extra build description from bootstrap via the `CFG_VER_DESCRIPTION` env var.\n  [#15269](https://github.com/rust-lang/cargo/pull/15269)\n- Control byte display precision with `std::fmt` options.\n  [#15246](https://github.com/rust-lang/cargo/pull/15246)\n- Replace humantime crate with jiff.\n  [#15290](https://github.com/rust-lang/cargo/pull/15290)\n- Dont check cargo-util semver until 1.86 is released \n  [#15222](https://github.com/rust-lang/cargo/pull/15222)\n- Redox OS is part of the unix family \n  [#15307](https://github.com/rust-lang/cargo/pull/15307)\n- cargo-tree: Abstract the concept of a NodeId \n  [#15237](https://github.com/rust-lang/cargo/pull/15237)\n- cargo-tree: Abstract the concept of an edge \n  [#15233](https://github.com/rust-lang/cargo/pull/15233)\n- ci: Auto-update cargo-semver-checks \n  [#15212](https://github.com/rust-lang/cargo/pull/15212)\n- ci: Visually group output in Github \n  [#15218](https://github.com/rust-lang/cargo/pull/15218)\n- manifest: Centralize Cargo target descriptions \n  [#15291](https://github.com/rust-lang/cargo/pull/15291)\n- Update dependencies.\n  [#15250](https://github.com/rust-lang/cargo/pull/15250)\n  [#15249](https://github.com/rust-lang/cargo/pull/15249)\n  [#15245](https://github.com/rust-lang/cargo/pull/15245)\n  [#15224](https://github.com/rust-lang/cargo/pull/15224)\n  [#15282](https://github.com/rust-lang/cargo/pull/15282)\n  [#15211](https://github.com/rust-lang/cargo/pull/15211)\n  [#15217](https://github.com/rust-lang/cargo/pull/15217)\n  [#15268](https://github.com/rust-lang/cargo/pull/15268)\n\n## Cargo 1.86 (2025-04-03)\n[d73d2caf...rust-1.86.0](https://github.com/rust-lang/cargo/compare/d73d2caf...rust-1.86.0)\n\n### Added\n\n### Changed\n\n- ❗️ When merging, replace rather than combine configuration keys that refer\n  to a program path and its arguments.\n  [#15066](https://github.com/rust-lang/cargo/pull/15066)  \n  These keys include:\n  - `registry.credential-provider`\n  - `registries.*.credential-provider`\n  - `target.*.runner`\n  - `host.runner`\n  - `credential-alias.*`\n  - `doc.browser`\n- ❗️ Error if both `--package` and `--workspace` are passed but the requested\n  package is missing. This was previously silently ignored, which was considered\n  a bug since missing packages should be reported.\n  [#15071](https://github.com/rust-lang/cargo/pull/15071)\n- Added warning when failing to update index cache.\n  [#15014](https://github.com/rust-lang/cargo/pull/15014)\n- Don't use \"did you mean\" in errors. Be upfront about what the suggestion is.\n  [#15138](https://github.com/rust-lang/cargo/pull/15138)\n- Provide a better error message for invalid SSH URLs in dependency sources.\n  [#15185](https://github.com/rust-lang/cargo/pull/15185)\n- Suggest similar feature names when the package doesn't have given features.\n  [#15133](https://github.com/rust-lang/cargo/pull/15133)\n- Print globs when workspace members can't be found.\n  [#15093](https://github.com/rust-lang/cargo/pull/15093)\n- cargo-fix: Make `--allow-dirty` imply `--allow-staged`\n  [#15013](https://github.com/rust-lang/cargo/pull/15013)\n- cargo-login: hide the `token` argument from CLI help for the preparation of deprecation.\n  [#15057](https://github.com/rust-lang/cargo/pull/15057)\n- cargo-login: Don't suggest `cargo login` when using incompatible credential providers.\n  [#15124](https://github.com/rust-lang/cargo/pull/15124)\n- cargo-package: improve the performance of VCS status check by matching certain\n  path prefixes with pathspec.\n  [#14997](https://github.com/rust-lang/cargo/pull/14997)\n\n### Fixed\n\n- The `rerun-if-env-changed` build script instruction can now correctly detect\n  changes in the `[env]` configuration table.\n  [#14756](https://github.com/rust-lang/cargo/pull/14756)\n- Force emitting warnings as warnings when learning Rust target info for an unsupported crate type.\n  [#15036](https://github.com/rust-lang/cargo/pull/15036)\n- cargo-package: Verify the VCS status of symlinks\n  when they point to paths outside the current package root.\n  [#14981](https://github.com/rust-lang/cargo/pull/14981)\n\n### Nightly only\n\n- 🔥 `-Z feature-unification`: This new unstable flag enables the\n  `resolver.feature-unification` configuration option to control how features\n  are unified across a workspace.\n  ([RFC 3529](https://github.com/rust-lang/rfcs/blob/master/text/3692-feature-unification.md))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#feature-unification))\n  [#15157](https://github.com/rust-lang/cargo/pull/15157)\n- cargo-util-schemas: Correct and update the JSON Schema\n  [#15000](https://github.com/rust-lang/cargo/pull/15000)\n- cargo-util-schemas: Fix the `[lints]` JSON Schema \n  [#15035](https://github.com/rust-lang/cargo/pull/15035)\n- cargo-util-schemas: Fix 'metadata' JSON Schema \n  [#15033](https://github.com/rust-lang/cargo/pull/15033)\n- `cargo rustc --print`: Setup cargo environment for `cargo rustc --print`.\n  [#15026](https://github.com/rust-lang/cargo/pull/15026)\n- `-Zbuild-std`: parse value as comma-separated list, also extends the behavior\n  to `build-std-features`.\n  [#15065](https://github.com/rust-lang/cargo/pull/15065)\n- `-Zgc`: Make cache tracking resilient to unexpected files.\n  [#15147](https://github.com/rust-lang/cargo/pull/15147)\n- `-Zscript`: Consolidate creation of SourceId from manifest path \n  [#15172](https://github.com/rust-lang/cargo/pull/15172)\n- `-Zscript`: Integrate cargo-script logic into main parser \n  [#15168](https://github.com/rust-lang/cargo/pull/15168)\n- `-Zscript`: add `cargo pkgid` support for cargo-script \n  [#14961](https://github.com/rust-lang/cargo/pull/14961)\n- `-Zpackage-workspace`: Report all unpublishable packages \n  [#15070](https://github.com/rust-lang/cargo/pull/15070)\n\n### Documentation\n\n- Document that Cargo automatically registers variables used in the `env!`\n  macro to trigger rebuilds since 1.46.\n  [#15062](https://github.com/rust-lang/cargo/pull/15062)\n- Move the changelog to The Cargo Book.\n  [#15119](https://github.com/rust-lang/cargo/pull/15119)\n  [#15123](https://github.com/rust-lang/cargo/pull/15123)\n  [#15142](https://github.com/rust-lang/cargo/pull/15142)\n- Note `package.authors` is deprecated.\n  [#15068](https://github.com/rust-lang/cargo/pull/15068)\n- Fix the wrong grammar of a Package Id Specification.\n  [#15049](https://github.com/rust-lang/cargo/pull/15049)\n- Fix the inverted logic about MSRV\n  [#15044](https://github.com/rust-lang/cargo/pull/15044)\n- cargo-metadata: Fix description of the `\"root\"` field.\n  [#15182](https://github.com/rust-lang/cargo/pull/15182)\n- cargo-package: note the lock file is always included.\n  [#15067](https://github.com/rust-lang/cargo/pull/15067)\n- contrib: Start guidelines for schema design.\n  [#15037](https://github.com/rust-lang/cargo/pull/15037)\n\n### Internal\n\n- Don't use `libc::LOCK_*` on Solaris.\n  [#15143](https://github.com/rust-lang/cargo/pull/15143)\n- Clean up field -> env var handling.\n  [#15008](https://github.com/rust-lang/cargo/pull/15008)\n- Simplify SourceID Ord/Eq.\n  [#14980](https://github.com/rust-lang/cargo/pull/14980)\n  [#15103](https://github.com/rust-lang/cargo/pull/15103)\n- Add manual Hash impl for SourceKind and document the reason.\n  [#15029](https://github.com/rust-lang/cargo/pull/15029)\n- ci: allow Windows reserved names in CI \n  [#15135](https://github.com/rust-lang/cargo/pull/15135)\n- cargo-test-macro: Remove condition on `RUSTUP_WINDOWS_PATH_ADD_BIN`\n  [#15017](https://github.com/rust-lang/cargo/pull/15017)\n- resolver: Simplify backtrack\n  [#15150](https://github.com/rust-lang/cargo/pull/15150)\n- resolver: Small cleanups \n  [#15040](https://github.com/rust-lang/cargo/pull/15040)\n- test: Clean up shallow fetch tests\n  [#15002](https://github.com/rust-lang/cargo/pull/15002)\n- test: Fix `https::self_signed_should_fail` for macOS\n  [#15016](https://github.com/rust-lang/cargo/pull/15016)\n- test: Fix benchsuite issue with newer versions of git\n  [#15069](https://github.com/rust-lang/cargo/pull/15069)\n- test: Fix shared_std_dependency_rebuild running on Windows\n  [#15111](https://github.com/rust-lang/cargo/pull/15111)\n- test: Update tests to fix nightly errors\n  [#15110](https://github.com/rust-lang/cargo/pull/15110)\n- test: Remove unused `-C link-arg=-fuse-ld=lld`\n  [#15097](https://github.com/rust-lang/cargo/pull/15097)\n- test: Remove `unsafe` by using `LazyLock`\n  [#15096](https://github.com/rust-lang/cargo/pull/15096)\n- test: Remove unnecessary into conversions\n  [#15042](https://github.com/rust-lang/cargo/pull/15042)\n- test: Fix race condition in panic_abort_tests\n  [#15169](https://github.com/rust-lang/cargo/pull/15169)\n- Update deny.toml\n  [#15164](https://github.com/rust-lang/cargo/pull/15164)\n- Update dependencies.\n  [#14995](https://github.com/rust-lang/cargo/pull/14995)\n  [#14996](https://github.com/rust-lang/cargo/pull/14996)\n  [#14998](https://github.com/rust-lang/cargo/pull/14998)\n  [#15012](https://github.com/rust-lang/cargo/pull/15012)\n  [#15018](https://github.com/rust-lang/cargo/pull/15018)\n  [#15041](https://github.com/rust-lang/cargo/pull/15041)\n  [#15050](https://github.com/rust-lang/cargo/pull/15050)\n  [#15121](https://github.com/rust-lang/cargo/pull/15121)\n  [#15128](https://github.com/rust-lang/cargo/pull/15128)\n  [#15129](https://github.com/rust-lang/cargo/pull/15129)\n  [#15162](https://github.com/rust-lang/cargo/pull/15162)\n  [#15163](https://github.com/rust-lang/cargo/pull/15163)\n  [#15165](https://github.com/rust-lang/cargo/pull/15165)\n  [#15166](https://github.com/rust-lang/cargo/pull/15166)\n\n## Cargo 1.85 (2025-02-20)\n[66221abd...rust-1.85.0](https://github.com/rust-lang/cargo/compare/66221abd...rust-1.85.0)\n\n### Added\n\n- 🎉 Cargo now supports the 2024 edition.\n  More information is available in the [edition guide](https://doc.rust-lang.org/nightly/edition-guide/rust-2024/index.html).\n  [#14828](https://github.com/rust-lang/cargo/pull/14828)\n- cargo-tree: The `--depth` flag now accepts `workspace`,\n  which shows only dependencies that are members of the current workspace.\n  [#14928](https://github.com/rust-lang/cargo/pull/14928)\n- Build scripts now receive a new environment variable, `CARGO_CFG_FEATURE`,\n  which contains each activated feature of the package being built.\n  [#14902](https://github.com/rust-lang/cargo/pull/14902)\n- perf: Dependency resolution is now faster due to a more efficient hash for `ActivationsKey`\n  [#14915](https://github.com/rust-lang/cargo/pull/14915)\n\n### Changed\n\n- ❗️ cargo-rustc: Trailing flags now have higher precedence.\n  This behavior was nightly-only since 1.83 and is now stabilized.\n  [#14900](https://github.com/rust-lang/cargo/pull/14900)\n- ❗️ Cargo now uses a cross-platform hash algorithm from `rustc-stable-hash`.\n  As a result, the hash part of paths to dependency caches\n  (e.g., `$CARGO_HOME/registry/index/index.crates.io-<hash>`) will change.\n  This will trigger re-downloads of registry indices and `.crate` tarballs,\n  as well as re-cloning of Git dependencies.\n  [#14917](https://github.com/rust-lang/cargo/pull/14917)\n- Added a future-incompatibility warning for keywords in `cfg`s in Cargo.toml\n  and Cargo configuration. `cfg`s with keywords like `cfg(true)` and `cfg(false)`\n  were incorrectly accepted. For backward compatibility, support for raw\n  identifiers has been introduced; for example, use `cfg(r#true)` instead.\n  [#14671](https://github.com/rust-lang/cargo/pull/14671)\n- Dependency resolution now provides richer error messages explaining why some versions were rejected, unmatched, or invalid.  \n  [#14897](https://github.com/rust-lang/cargo/pull/14897)\n  [#14921](https://github.com/rust-lang/cargo/pull/14921)\n  [#14923](https://github.com/rust-lang/cargo/pull/14923)\n  [#14927](https://github.com/rust-lang/cargo/pull/14927)\n- cargo-doc: improve the error message when `--open`ing a doc while no doc generated.\n  [#14969](https://github.com/rust-lang/cargo/pull/14969)\n- cargo-package: warn if symlinks checked out as plain text files \n  [#14994](https://github.com/rust-lang/cargo/pull/14994)\n- cargo-package: Shows dirty file paths relative to the Git working directory.\n  [#14968](https://github.com/rust-lang/cargo/pull/14968)\n  [#14970](https://github.com/rust-lang/cargo/pull/14970)\n\n### Fixed\n\n- Set `GIT_DIR` to ensure compatibility with bare repositories\n  for `net.git-fetch-with-cli=true`.\n  [#14860](https://github.com/rust-lang/cargo/pull/14860)\n- Fixed workspace Cargo.toml modification didn't invalidate build cache.\n  [#14973](https://github.com/rust-lang/cargo/pull/14973)\n- Prevented build caches from being discarded after changes to `RUSTFLAGS`.\n  [#14830](https://github.com/rust-lang/cargo/pull/14830)\n  [#14898](https://github.com/rust-lang/cargo/pull/14898)\n- cargo-add: Don't select yanked versions when normalizing names.\n  [#14895](https://github.com/rust-lang/cargo/pull/14895)\n- cargo-fix: Migrate workspace dependencies to the 2024 edition also for virtual manifests.\n  [#14890](https://github.com/rust-lang/cargo/pull/14890)\n- cargo-package: Verify the VCS status of `package.readme` and `package.license-file`\n  when they point to paths outside the current package root.\n  [#14966](https://github.com/rust-lang/cargo/pull/14966)\n- cargo-package: assure possibly blocking non-files (like FIFOs) won't be\n  picked up for publishing.\n  [#14977](https://github.com/rust-lang/cargo/pull/14977)\n\n### Nightly only\n\n- `path-bases`: Support bases in `[patch]`es in virtual manifests\n  [#14931](https://github.com/rust-lang/cargo/pull/14931)\n- `unit-graph`: Use the configured shell to print output.\n  [#14926](https://github.com/rust-lang/cargo/pull/14926)\n- `-Zbuild-std`: Check if the build target supports `std`\n  by probing the `metadata.std` field in the target spec JSON.\n  [#14183](https://github.com/rust-lang/cargo/pull/14183)\n  [#14938](https://github.com/rust-lang/cargo/pull/14938)\n  [#14899](https://github.com/rust-lang/cargo/pull/14899)\n- `-Zbuild-std`: always link to std when testing proc-macros.\n  [#14850](https://github.com/rust-lang/cargo/pull/14850)\n  [#14861](https://github.com/rust-lang/cargo/pull/14861)\n- `-Zbuild-std`: clean up build-std tests\n  [#14943](https://github.com/rust-lang/cargo/pull/14943)\n  [#14933](https://github.com/rust-lang/cargo/pull/14933)\n  [#14896](https://github.com/rust-lang/cargo/pull/14896)\n- `-Zbuild-std`: Hash relative paths to std workspace instead of absolute paths.\n  [#14951](https://github.com/rust-lang/cargo/pull/14951)\n- `-Zpackage-workspace`: Allow dry-run of a non-bumped workspace.\n  [#14847](https://github.com/rust-lang/cargo/pull/14847)\n- `-Zscript`: Allow adding/removing dependencies from cargo scripts\n  [#14857](https://github.com/rust-lang/cargo/pull/14857)\n- `-Zscript`: Migrate cargo script manifests across editions\n  [#14864](https://github.com/rust-lang/cargo/pull/14864)\n- `-Zscript`: Don't override the release profile.\n  [#14925](https://github.com/rust-lang/cargo/pull/14925)\n- `-Ztrim-paths`: Use `Path::push` to construct the `remap-path-prefix` flag.\n  [#14908](https://github.com/rust-lang/cargo/pull/14908)\n\n### Documentation\n\n- Clarify how `cargo::metadata` env var is selected.\n  [#14842](https://github.com/rust-lang/cargo/pull/14842)\n- cargo-info: Remove references to the default registry in `cargo-info` docs\n  [#14880](https://github.com/rust-lang/cargo/pull/14880)\n- contrib: add missing argument to Rustup Cargo workaround \n  [#14954](https://github.com/rust-lang/cargo/pull/14954)\n- SemVer: Add section on RPIT capturing \n  [#14849](https://github.com/rust-lang/cargo/pull/14849)\n\n### Internal\n\n- Add the `test` cfg as a well known cfg before of compiler change.\n  [#14963](https://github.com/rust-lang/cargo/pull/14963)\n- Enable triagebot merge conflict notifications\n  [#14972](https://github.com/rust-lang/cargo/pull/14972)\n- Limit release trigger to `0.*` tags\n  [#14940](https://github.com/rust-lang/cargo/pull/14940)\n- Simplify `SourceID` Hash.\n  [#14800](https://github.com/rust-lang/cargo/pull/14800)\n- build-rs: Automatically emits `rerun-if-env-changed`\n  when accessing environment variables Cargo sets for build script executions.\n  [#14911](https://github.com/rust-lang/cargo/pull/14911)\n- build-rs: Correctly refer to the item in assert \n  [#14913](https://github.com/rust-lang/cargo/pull/14913)\n- build-rs: Add the 'error' directive \n  [#14910](https://github.com/rust-lang/cargo/pull/14910)\n- build-rs: Remove meaningless 'cargo_cfg_debug_assertions' \n  [#14901](https://github.com/rust-lang/cargo/pull/14901)\n- cargo-package: split `cargo_package` to modules \n  [#14959](https://github.com/rust-lang/cargo/pull/14959)\n  [#14982](https://github.com/rust-lang/cargo/pull/14982)\n- cargo-test-support: `requires` attribute accepts string literals for cmds\n  [#14875](https://github.com/rust-lang/cargo/pull/14875)\n- cargo-test-support: Switch from 'exec_with_output' to 'run'\n  [#14848](https://github.com/rust-lang/cargo/pull/14848)\n- cargo-test-support: track caller for `.crate` file publish verification \n  [#14992](https://github.com/rust-lang/cargo/pull/14992)\n- test: Verify `-Cmetadata` directly, not through `-Cextra-filename`\n  [#14846](https://github.com/rust-lang/cargo/pull/14846)\n- test: ensure PGO works\n  [#14859](https://github.com/rust-lang/cargo/pull/14859)\n  [#14874](https://github.com/rust-lang/cargo/pull/14874)\n  [#14887](https://github.com/rust-lang/cargo/pull/14887)\n- Update dependencies.\n  [#14867](https://github.com/rust-lang/cargo/pull/14867)\n  [#14871](https://github.com/rust-lang/cargo/pull/14871)\n  [#14878](https://github.com/rust-lang/cargo/pull/14878)\n  [#14879](https://github.com/rust-lang/cargo/pull/14879)\n  [#14975](https://github.com/rust-lang/cargo/pull/14975)\n\n## Cargo 1.84 (2025-01-09)\n[15fbd2f6...rust-1.84.0](https://github.com/rust-lang/cargo/compare/15fbd2f6...rust-1.84.0)\n\n### Added\n\n- 🎉 Stabilize resolver v3, a.k.a the MSRV-aware dependency resolver.\n  The stabilization includes `package.resolver = \"3\"` in Cargo.toml,\n  and the `[resolver]` table in Cargo configuration.\n  ([RFC 3537](https://github.com/rust-lang/rfcs/blob/master/text/3537-msrv-resolver.md))\n  ([manifest docs](https://doc.rust-lang.org/nightly/cargo/reference/resolver.html#resolver-versions))\n  ([config docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#resolver))\n  [#14639](https://github.com/rust-lang/cargo/pull/14639)\n  [#14662](https://github.com/rust-lang/cargo/pull/14662)\n  [#14711](https://github.com/rust-lang/cargo/pull/14711)\n  [#14725](https://github.com/rust-lang/cargo/pull/14725)\n  [#14748](https://github.com/rust-lang/cargo/pull/14748)\n  [#14753](https://github.com/rust-lang/cargo/pull/14753)\n  [#14754](https://github.com/rust-lang/cargo/pull/14754)\n- Added a new build script invocation `cargo::error=MESSAGE` to report error messages.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargo-error))\n  [#14743](https://github.com/rust-lang/cargo/pull/14743)\n\n### Changed\n\n- ❗️ cargo-publish: Always include Cargo.lock in published crates.\n  Originally it was only included for packages that have executables or examples\n  for use with `cargo install`.\n  [#14815](https://github.com/rust-lang/cargo/pull/14815)\n- Dependency resolver performance improvements, including shared caching,\n  reduced iteration overhead, and removing redundant fetches and clones.\n  [#14663](https://github.com/rust-lang/cargo/pull/14663)\n  [#14690](https://github.com/rust-lang/cargo/pull/14690)\n  [#14692](https://github.com/rust-lang/cargo/pull/14692)\n  [#14694](https://github.com/rust-lang/cargo/pull/14694)\n- Deprecate `cargo verify-project`.\n  [#14736](https://github.com/rust-lang/cargo/pull/14736)\n- Add source replacement info when no matching package found during dependency resolving.\n  [#14715](https://github.com/rust-lang/cargo/pull/14715)\n- Hint for using `crates-io` when `[patch.crates.io]` found.\n  [#14700](https://github.com/rust-lang/cargo/pull/14700)\n- Normalize source paths of Cargo targets for better diagnostics.\n  [#14497](https://github.com/rust-lang/cargo/pull/14497)\n  [#14750](https://github.com/rust-lang/cargo/pull/14750)\n- Allow registries to omit empty/default fields in index metadata JSON.\n  Due to backward compatibility, crates.io continues to emit them.\n  [#14838](https://github.com/rust-lang/cargo/pull/14838)\n  [#14839](https://github.com/rust-lang/cargo/pull/14839)\n- cargo-doc: display env vars in extra verbose mode.\n  [#14812](https://github.com/rust-lang/cargo/pull/14812)\n- cargo-fix: replace special-case handling of duplicate insert-only replacement.\n  [#14765](https://github.com/rust-lang/cargo/pull/14765)\n  [#14782](https://github.com/rust-lang/cargo/pull/14782)\n- cargo-remove: when a dependency is not found, try suggesting other dependencies\n  with similar names.\n  [#14818](https://github.com/rust-lang/cargo/pull/14818)\n- git: skip unnecessary submodule validations for fresh checkouts on Git dependencies.\n  [#14605](https://github.com/rust-lang/cargo/pull/14605)\n- git: Enhanced the error message for fetching Git dependencies when refspec not found.\n  [#14806](https://github.com/rust-lang/cargo/pull/14806)\n- git: Pass `--no-tags` by default to git CLI when `net.git-fetch-with-cli = true`.\n  [#14688](https://github.com/rust-lang/cargo/pull/14688)\n\n### Fixed\n\n- Fixed old Cargos failing to read the newer format of dep-info in build caches.\n  [#14751](https://github.com/rust-lang/cargo/pull/14751)\n  [#14745](https://github.com/rust-lang/cargo/pull/14745)\n- Fixed rebuild detection not respecting changes in the `[env]` table.\n  [#14701](https://github.com/rust-lang/cargo/pull/14701)\n  [#14730](https://github.com/rust-lang/cargo/pull/14730)\n- cargo-fix: Added transactional semantics to `rustfix` to keep code fix in a\n  valid state when multiple suggestions contain overlapping spans.\n  [#14747](https://github.com/rust-lang/cargo/pull/14747)\n\n### Nightly only\n\n- The unstable environment variable `CARGO_RUSTC_CURRENT_DIR` has been removed.\n  [#14799](https://github.com/rust-lang/cargo/pull/14799)\n- 🔥 Cargo now includes an experimental JSON Schema file for `Cargo.toml` in the source code.\n  It helps external tools validate or auto-complete the schema of the manifest.\n  ([manifest.schema.json](https://github.com/rust-lang/cargo/blob/master/crates/cargo-util-schemas/manifest.schema.json))\n  [#14683](https://github.com/rust-lang/cargo/pull/14683)\n- 🔥 `Zroot-dir`: A new unstable `-Zroot-dir` flag to configure the path from\n  which rustc should be invoked.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#root-dir))\n  [#14752](https://github.com/rust-lang/cargo/pull/14752)\n- 🔥 `-Zwarnings`: A new unstable feature to control how Cargo handles warnings\n  via the `build.warnings` configuration field.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#warnings))\n  [#14388](https://github.com/rust-lang/cargo/pull/14388)\n  [#14827](https://github.com/rust-lang/cargo/pull/14827)\n  [#14836](https://github.com/rust-lang/cargo/pull/14836)\n- `edition2024`: Verify 2024 edition / resolver=3 doesn't affect resolution\n  [#14724](https://github.com/rust-lang/cargo/pull/14724)\n- `native-completions`: Include descriptions in zsh\n  [#14726](https://github.com/rust-lang/cargo/pull/14726)\n- `-Zbindeps`: Fix panic when running cargo tree on a package with a cross compiled bindep\n  [#14593](https://github.com/rust-lang/cargo/pull/14593)\n- `-Zbindeps`: download targeted transitive deps of with artifact deps' target platform\n  [#14723](https://github.com/rust-lang/cargo/pull/14723)\n- `-Zbuild-std`: Remove the requirement for `--target`.\n  [#14317](https://github.com/rust-lang/cargo/pull/14317)\n- `-Zpackage-workspace`: Support package selection options, such as `--exclude`,\n  in `cargo publish`\n  [#14659](https://github.com/rust-lang/cargo/pull/14659)\n- `-Zscript`: Remove support for accepting `Cargo.toml`.\n  [#14670](https://github.com/rust-lang/cargo/pull/14670)\n- `-Zscript`: Change config paths to only check `CARGO_HOME`\n  [#14749](https://github.com/rust-lang/cargo/pull/14749)\n- `-Zscript`: Update the frontmatter parser for RFC 3503.\n  [#14792](https://github.com/rust-lang/cargo/pull/14792)\n\n### Documentation\n\n- Clarify the meaning of `--tests` and `--benches` flags.\n  [#14675](https://github.com/rust-lang/cargo/pull/14675)\n- Clarify tools should only interpret messages with a line starting with `{` as JSON.\n  [#14677](https://github.com/rust-lang/cargo/pull/14677)\n- Clarify what is and isn't included by `cargo package`\n  [#14684](https://github.com/rust-lang/cargo/pull/14684)\n- Document official external commands: `cargo-clippy`, `cargo-fmt`, and `cargo-miri`.\n  [#14669](https://github.com/rust-lang/cargo/pull/14669)\n  [#14805](https://github.com/rust-lang/cargo/pull/14805)\n- Enhance documentation on environment variables\n  [#14676](https://github.com/rust-lang/cargo/pull/14676)\n- Simplify English used in documentations.\n  [#14825](https://github.com/rust-lang/cargo/pull/14825)\n  [#14829](https://github.com/rust-lang/cargo/pull/14829)\n- A new doc page for deprecated and removed commands.\n  [#14739](https://github.com/rust-lang/cargo/pull/14739)\n- cargo-test-support: Document `Execs` assertions based on port effort \n  [#14793](https://github.com/rust-lang/cargo/pull/14793)\n\n### Internal\n\n- 🎉 Migrate `build-rs` crate to the `rust-lang/cargo` repository as an\n  intentional artifact of the Cargo team.\n  [#14786](https://github.com/rust-lang/cargo/pull/14786)\n  [#14817](https://github.com/rust-lang/cargo/pull/14817)\n- Enable transfer feature in triagebot\n  [#14777](https://github.com/rust-lang/cargo/pull/14777)\n- clone-on-write when needed for InternedString\n  [#14808](https://github.com/rust-lang/cargo/pull/14808)\n- ci: Switch CI from bors to merge queue \n  [#14718](https://github.com/rust-lang/cargo/pull/14718)\n- ci: make the `lint-docs` job required \n  [#14797](https://github.com/rust-lang/cargo/pull/14797)\n- ci: Check for clippy `correctness`\n  [#14796](https://github.com/rust-lang/cargo/pull/14796)\n- ci: Switch matchPackageNames to matchDepNames for renovate\n  [#14704](https://github.com/rust-lang/cargo/pull/14704)\n- fingerprint: Track the intent for each use of `UnitHash`\n  [#14826](https://github.com/rust-lang/cargo/pull/14826)\n- fingerprint: Add more metadata to `rustc_fingerprint`.\n  [#14761](https://github.com/rust-lang/cargo/pull/14761)\n- test: Migrate remaining snapshotting to snapbox\n  [#14642](https://github.com/rust-lang/cargo/pull/14642)\n  [#14760](https://github.com/rust-lang/cargo/pull/14760)\n  [#14781](https://github.com/rust-lang/cargo/pull/14781)\n  [#14785](https://github.com/rust-lang/cargo/pull/14785)\n  [#14790](https://github.com/rust-lang/cargo/pull/14790)\n- Update dependencies.\n  [#14668](https://github.com/rust-lang/cargo/pull/14668)\n  [#14705](https://github.com/rust-lang/cargo/pull/14705)\n  [#14762](https://github.com/rust-lang/cargo/pull/14762)\n  [#14766](https://github.com/rust-lang/cargo/pull/14766)\n  [#14772](https://github.com/rust-lang/cargo/pull/14772)\n\n## Cargo 1.83 (2024-11-28)\n[8f40fc59...rust-1.83.0](https://github.com/rust-lang/cargo/compare/8f40fc59...rust-1.83.0)\n\n### Added\n\n- `--timings` HTML output can now auto-switch between light and dark color\n  schemes based on browser preference.\n  [#14588](https://github.com/rust-lang/cargo/pull/14588)\n- Introduced a new `CARGO_MANIFEST_PATH` environment variable,\n  similar to `CARGO_MANIFEST_DIR` but pointing directly to the manifest file.\n  [#14404](https://github.com/rust-lang/cargo/pull/14404)\n- manifest: Added `package.autolib`, allowing `[lib]` auto-discovery to be disabled.\n  [#14591](https://github.com/rust-lang/cargo/pull/14591)\n\n### Changed\n\n- ❗️ Lockfile format v4 is now the default for creating/updating a lockfile.\n  Rust toolchains 1.78+ support lockfile v4.\n  For compatibility with earlier MSRV,\n  consider setting the `package.rust-version` to 1.82 or earlier.\n  [#14595](https://github.com/rust-lang/cargo/pull/14595)\n- ❗️ cargo-package: When using the `--package` flag, only the specified\n  packages are packaged. Previously, the package in the current working\n  directory was automatically selected for packaging.\n  [#14488](https://github.com/rust-lang/cargo/pull/14488)\n- cargo-publish: Now fails fast if the package version is already published.\n  [#14448](https://github.com/rust-lang/cargo/pull/14448)\n- Improved error messages for missing features.\n  [#14436](https://github.com/rust-lang/cargo/pull/14436)\n- Log details of `rustc` invocation failure if no errors are seen\n  [#14453](https://github.com/rust-lang/cargo/pull/14453)\n- Uplifted `windows-gnullvm` import libraries, aligning them with `windows-gnu`.\n  [#14451](https://github.com/rust-lang/cargo/pull/14451)\n- Suggest `cargo info` command in the `cargo search` result\n  [#14537](https://github.com/rust-lang/cargo/pull/14537)\n- Enhanced dependency update status messages, now displaying updates\n  (compatible, incompatible, direct-dep) in different colors,\n  along with messages and MSRVs.\n  [#14440](https://github.com/rust-lang/cargo/pull/14440)\n  [#14457](https://github.com/rust-lang/cargo/pull/14457)\n  [#14459](https://github.com/rust-lang/cargo/pull/14459)\n  [#14461](https://github.com/rust-lang/cargo/pull/14461)\n  [#14471](https://github.com/rust-lang/cargo/pull/14471)\n  [#14568](https://github.com/rust-lang/cargo/pull/14568)\n- The `Locking` status message no longer displays workspace members.\n  [#14445](https://github.com/rust-lang/cargo/pull/14445)\n\n### Fixed\n\n- Prevented duplicate library search environment variables when calling `cargo` recursively.\n  [#14464](https://github.com/rust-lang/cargo/pull/14464)\n- Don't double-warn about `$CARGO_HOME/config` not having `.toml` extension.\n  [#14579](https://github.com/rust-lang/cargo/pull/14579)\n- Correct diagnostic count message when using `--message-format json`.\n  [#14598](https://github.com/rust-lang/cargo/pull/14598)\n- cargo-add: Perform fuzzy searches when translating package names\n  [#13765](https://github.com/rust-lang/cargo/pull/13765)\n- cargo-new: only auto-add new packages to the workspace relative to the manifest,\n  rather than the current directory.\n  [#14505](https://github.com/rust-lang/cargo/pull/14505)\n- cargo-rustc: Fixed parsing of comma-separated values in the `--crate-type` flag.\n  [#14499](https://github.com/rust-lang/cargo/pull/14499)\n- cargo-vendor: trusts the crate version only when it originates from registries.\n  This causes git dependencies to be re-vendored even if they haven't changed.\n  [#14530](https://github.com/rust-lang/cargo/pull/14530)\n- cargo-publish: Downgrade version-exists error to warning on dry-run\n  [#14742](https://github.com/rust-lang/cargo/pull/14742)\n  [#14744](https://github.com/rust-lang/cargo/pull/14744)\n\n### Nightly only\n\n- ❗️ cargo-rustc: give trailing flags higher precedence on nightly.\n  The nightly gate will be removed after a few releases.\n  Please give feedback if it breaks any workflow.\n  A temporary environment variable `__CARGO_RUSTC_ORIG_ARGS_PRIO=1` is provided\n  to opt-out of the behavior.\n  [#14587](https://github.com/rust-lang/cargo/pull/14587)\n- 🔥 cargo-install: a new `--dry-run` flag without actually installing binaries.\n  [#14280](https://github.com/rust-lang/cargo/pull/14280)\n- 🔥 `native-completions`: moves the handwritten shell completion scripts to\n  Rust native, making it easier for us to add, extend, and test new completions.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#native-completions))\n  [#14493](https://github.com/rust-lang/cargo/pull/14493)\n  [#14531](https://github.com/rust-lang/cargo/pull/14531)\n  [#14532](https://github.com/rust-lang/cargo/pull/14532)\n  [#14533](https://github.com/rust-lang/cargo/pull/14533)\n  [#14534](https://github.com/rust-lang/cargo/pull/14534)\n  [#14535](https://github.com/rust-lang/cargo/pull/14535)\n  [#14536](https://github.com/rust-lang/cargo/pull/14536)\n  [#14546](https://github.com/rust-lang/cargo/pull/14546)\n  [#14547](https://github.com/rust-lang/cargo/pull/14547)\n  [#14548](https://github.com/rust-lang/cargo/pull/14548)\n  [#14552](https://github.com/rust-lang/cargo/pull/14552)\n  [#14557](https://github.com/rust-lang/cargo/pull/14557)\n  [#14558](https://github.com/rust-lang/cargo/pull/14558)\n  [#14563](https://github.com/rust-lang/cargo/pull/14563)\n  [#14564](https://github.com/rust-lang/cargo/pull/14564)\n  [#14573](https://github.com/rust-lang/cargo/pull/14573)\n  [#14590](https://github.com/rust-lang/cargo/pull/14590)\n  [#14592](https://github.com/rust-lang/cargo/pull/14592)\n  [#14653](https://github.com/rust-lang/cargo/pull/14653)\n  [#14656](https://github.com/rust-lang/cargo/pull/14656)\n- 🔥 `-Zchecksum-freshness`: replace the use of file mtimes in cargo’s rebuild\n  detection with a file checksum algorithm. This is most useful on systems with\n  a poor mtime implementation, or in CI/CD.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#checksum-freshness))\n  [#14137](https://github.com/rust-lang/cargo/pull/14137)\n- cargo-update: Add `matches_prerelease` semantic\n  [#14305](https://github.com/rust-lang/cargo/pull/14305)\n- `build-plan`: document it as being deprecated.\n  [#14657](https://github.com/rust-lang/cargo/pull/14657)\n- `edition2024`: Remove implicit feature removal from 2024 edition.\n  [#14630](https://github.com/rust-lang/cargo/pull/14630)\n- `lockfile-path`: implies `--locked` on `cargo install`.\n  [#14556](https://github.com/rust-lang/cargo/pull/14556)\n- `open-namespaces`: Allow open namespaces in `PackageIdSpec`s\n  [#14467](https://github.com/rust-lang/cargo/pull/14467)\n- `path-bases`: `cargo [add|remove|update]` support \n  [#14427](https://github.com/rust-lang/cargo/pull/14427)\n- `-Zmsrv-policy`: determine the workspace's MSRV by the most number of MSRVs within it.\n  [#14569](https://github.com/rust-lang/cargo/pull/14569)\n- `-Zpackage-workspace`: allows to publish multiple crates in a workspace,\n  even if they have inter-dependencies.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#package-workspace))\n  [#14433](https://github.com/rust-lang/cargo/pull/14433)\n  [#14496](https://github.com/rust-lang/cargo/pull/14496)\n- `-Zpublic-dependency`: Include public/private dependency status in `cargo metadata` \n  [#14504](https://github.com/rust-lang/cargo/pull/14504)\n- `-Zpublic-dependency`: Don't require MSRV bump\n  [#14507](https://github.com/rust-lang/cargo/pull/14507)\n\n### Documentation\n\n- 🎉 New chapter about the uses, support expectations, and management of\n  `package.rust-version` a.k.a MSRV.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/rust-version.html))\n  [#14619](https://github.com/rust-lang/cargo/pull/14619)\n  [#14636](https://github.com/rust-lang/cargo/pull/14636)\n- Clarify `target.'cfg(...)'` doesn't respect cfg from build script \n  [#14312](https://github.com/rust-lang/cargo/pull/14312)\n- Clarify `[[bin]]` target auto-discovery can be `src/main.rs` and/or in `src/bin/`\n  [#14515](https://github.com/rust-lang/cargo/pull/14515)\n- Disambiguate the use of 'target' in the feature resolver v2 doc.\n  [#14540](https://github.com/rust-lang/cargo/pull/14540)\n- Make `--config <PATH>` more prominent \n  [#14631](https://github.com/rust-lang/cargo/pull/14631)\n- Minor re-grouping of pages.\n  [#14620](https://github.com/rust-lang/cargo/pull/14620)\n- contrib: Update docs for how cargo is published \n  [#14539](https://github.com/rust-lang/cargo/pull/14539)\n- contrib: Declare support level for each crate in Cargo's Charter / crate docs\n  [#14600](https://github.com/rust-lang/cargo/pull/14600)\n- contrib: Declare new Intentional Artifacts as 'small' changes\n  [#14599](https://github.com/rust-lang/cargo/pull/14599)\n\n### Internal\n\n- Cleanup duplicated check-cfg lint logic \n  [#14567](https://github.com/rust-lang/cargo/pull/14567)\n- Fix elided lifetime due to nightly rustc changes\n  [#14487](https://github.com/rust-lang/cargo/pull/14487)\n- Improved error reporting when a feature is not found in `activated_features`.\n  [#14647](https://github.com/rust-lang/cargo/pull/14647)\n- cargo-info: Use the `shell.note` to print the note \n  [#14554](https://github.com/rust-lang/cargo/pull/14554)\n- ci: bump CI tools\n  [#14503](https://github.com/rust-lang/cargo/pull/14503)\n  [#14628](https://github.com/rust-lang/cargo/pull/14628)\n- perf: zero-copy deserialization for compiler messages when possible\n  [#14608](https://github.com/rust-lang/cargo/pull/14608)\n- resolver: Add more SAT resolver tests\n  [#14583](https://github.com/rust-lang/cargo/pull/14583)\n  [#14614](https://github.com/rust-lang/cargo/pull/14614)\n- test: Migrated more tests to snapbox\n  [#14576](https://github.com/rust-lang/cargo/pull/14576)\n  [#14577](https://github.com/rust-lang/cargo/pull/14577)\n- Update dependencies.\n  [#14475](https://github.com/rust-lang/cargo/pull/14475)\n  [#14478](https://github.com/rust-lang/cargo/pull/14478)\n  [#14489](https://github.com/rust-lang/cargo/pull/14489)\n  [#14607](https://github.com/rust-lang/cargo/pull/14607)\n  [#14624](https://github.com/rust-lang/cargo/pull/14624)\n  [#14632](https://github.com/rust-lang/cargo/pull/14632)\n\n## Cargo 1.82 (2024-10-17)\n[a2b58c3d...rust-1.82.0](https://github.com/rust-lang/cargo/compare/a2b58c3d...rust-1.82.0)\n\n### Added\n\n- 🎉 Added `cargo info` command for displaying information about a package.\n  [docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-info.html)\n  [#14141](https://github.com/rust-lang/cargo/pull/14141)\n  [#14418](https://github.com/rust-lang/cargo/pull/14418)\n  [#14430](https://github.com/rust-lang/cargo/pull/14430)\n\n### Changed\n\n- ❗️ Doctest respects Cargo's color options by passing `--color` to rustdoc invocations.\n  [#14425](https://github.com/rust-lang/cargo/pull/14425)\n- Improved error message for missing both `[package]` and `[workspace]` in Cargo.toml.\n  [#14261](https://github.com/rust-lang/cargo/pull/14261)\n- Enumerate all possible values of `profile.*.debug` for the error message.\n  [#14413](https://github.com/rust-lang/cargo/pull/14413)\n\n### Fixed\n\n- Use longhand gitoxide path-spec patterns. Previously the implementation used \n  shorthand pathspecs, which could produce invalid syntax, for example, if the\n  path to the manifest file contained a leading `_` underscore\n  [#14380](https://github.com/rust-lang/cargo/pull/14380)\n- cargo-package: fix failures on bare commit git repo.\n  [#14359](https://github.com/rust-lang/cargo/pull/14359)\n- cargo-publish: Don't strip non-dev features for renamed dependencies from the\n  HTTP JSON body sent to the registry.\n  The bug only affected third-party registries.\n  [#14325](https://github.com/rust-lang/cargo/pull/14325)\n  [#14327](https://github.com/rust-lang/cargo/pull/14327)\n- cargo-vendor: don't copy source files of excluded Cargo targets when vendoring.\n  [#14367](https://github.com/rust-lang/cargo/pull/14367)\n\n### Nightly only\n\n- 🔥 `lockfile-path`: Added `--lockfile-path` flag that allows specifying a path\n  to the lockfile other than the default path `<workspace_root>/Cargo.lock`.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#lockfile-path))\n  [#14326](https://github.com/rust-lang/cargo/pull/14326)\n  [#14417](https://github.com/rust-lang/cargo/pull/14417)\n  [#14423](https://github.com/rust-lang/cargo/pull/14423)\n  [#14424](https://github.com/rust-lang/cargo/pull/14424)\n- 🔥 `path-bases`: Introduced a table of path \"bases\" in Cargo configuration files\n  that can be used to prefix the paths of path dependencies and patch entries.\n  ([RFC 3529](https://github.com/rust-lang/rfcs/blob/master/text/3529-cargo-path-bases.md))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#path-bases))\n  [#14360](https://github.com/rust-lang/cargo/pull/14360)\n- 🔥 `-Zpackage-workspace`: Enhanced the experience of `cargo package --workspace`\n  when there are dependencies between crates in the workspace.\n  Crates in a workspace are no longer required to publish to actual registries.\n  This is a step toward supporting `cargo publish --workspace`.\n  [#13947](https://github.com/rust-lang/cargo/pull/13947)\n  [#14408](https://github.com/rust-lang/cargo/pull/14408)\n  [#14340](https://github.com/rust-lang/cargo/pull/14340)\n- cargo-update: Limit pre-release match semantics to use only on `OptVersionReq::Req` \n  [#14412](https://github.com/rust-lang/cargo/pull/14412)\n- `edition2024`: Revert \"fix: Ensure dep/feature activates the dependency on 2024\".\n  [#14295](https://github.com/rust-lang/cargo/pull/14295)\n- `update-breaking`: Improved error message when `update --breaking` has an invalid spec\n  [#14279](https://github.com/rust-lang/cargo/pull/14279)\n- `update-breaking`: Don’t downgrade on prerelease `VersionReq` when updating with `--breaking`\n  [#14250](https://github.com/rust-lang/cargo/pull/14250)\n- `-Zbuild-std`: remove hack on creating virtual std workspace \n  [#14358](https://github.com/rust-lang/cargo/pull/14358)\n  [#14370](https://github.com/rust-lang/cargo/pull/14370)\n- `-Zmsrv-policy`: Adjust MSRV resolve config field name / values.\n  The previous placeholder `resolver.something-like-precedence`\n  is now renamed to `resolver.incompatible-rust-versions`.\n  [#14296](https://github.com/rust-lang/cargo/pull/14296)\n- `-Zmsrv-policy`: : Report when incompatible-rust-version packages are selected\n  [#14401](https://github.com/rust-lang/cargo/pull/14401)\n- `-Ztarget-applies-to-host`: Fixed passing of links-overrides with\n  target-applies-to-host and an implicit target\n  [#14205](https://github.com/rust-lang/cargo/pull/14205)\n- `-Ztarget-applies-to-host`: `-Cmetadata` includes whether extra rustflags is same as host\n  [#14432](https://github.com/rust-lang/cargo/pull/14432)\n- `-Ztrim-paths`: rustdoc supports trim-paths for diagnostics \n  [#14389](https://github.com/rust-lang/cargo/pull/14389)\n\n### Documentation\n\n- Convert comments to doc comments for `Workspace`.\n  [#14397](https://github.com/rust-lang/cargo/pull/14397)\n- Fix MSRV indicator for `workspace.package` and `workspace.dependencies`.\n  [#14400](https://github.com/rust-lang/cargo/pull/14400)\n- FAQ: remove outdated Cargo offline usage section.\n  [#14336](https://github.com/rust-lang/cargo/pull/14336)\n\n### Internal\n\n- Enhanced `cargo-test-support` usability and documentation.\n  [#14266](https://github.com/rust-lang/cargo/pull/14266)\n  [#14268](https://github.com/rust-lang/cargo/pull/14268)\n  [#14269](https://github.com/rust-lang/cargo/pull/14269)\n  [#14270](https://github.com/rust-lang/cargo/pull/14270)\n  [#14272](https://github.com/rust-lang/cargo/pull/14272)\n- Made summary sync by using Arc instead of Rc\n  [#14260](https://github.com/rust-lang/cargo/pull/14260)\n- Used `Rc` instead of `Arc` for storing rustflags\n  [#14273](https://github.com/rust-lang/cargo/pull/14273)\n- Removed rustc probe for `--check-cfg` support \n  [#14302](https://github.com/rust-lang/cargo/pull/14302)\n- Renamed 'resolved' to 'normalized' for all manifest normalization related items.\n  [#14342](https://github.com/rust-lang/cargo/pull/14342)\n- cargo-util-schemas: Added `TomlPackage::new`, `Default` for `TomlWorkspace`\n  [#14271](https://github.com/rust-lang/cargo/pull/14271)\n- ci: Switch macos aarch64 to nightly \n  [#14382](https://github.com/rust-lang/cargo/pull/14382)\n- mdman: Normalize newlines when rendering options \n  [#14428](https://github.com/rust-lang/cargo/pull/14428)\n- perf: dont call wrap in a no-op `source_id::with*`\n  [#14318](https://github.com/rust-lang/cargo/pull/14318)\n- test: Migrated more tests to snapbox\n  [#14242](https://github.com/rust-lang/cargo/pull/14242)\n  [#14244](https://github.com/rust-lang/cargo/pull/14244)\n  [#14293](https://github.com/rust-lang/cargo/pull/14293)\n  [#14297](https://github.com/rust-lang/cargo/pull/14297)\n  [#14319](https://github.com/rust-lang/cargo/pull/14319)\n  [#14402](https://github.com/rust-lang/cargo/pull/14402)\n  [#14410](https://github.com/rust-lang/cargo/pull/14410)\n- test: don't rely on absence of `RUST_BACKTRACE`\n  [#14441](https://github.com/rust-lang/cargo/pull/14441)\n- test: Use gmake on AIX \n  [#14323](https://github.com/rust-lang/cargo/pull/14323)\n- Updated to `gix` 0.64.0 \n  [#14332](https://github.com/rust-lang/cargo/pull/14332)\n- Updated to `rusqlite` 0.32.0 \n  [#14334](https://github.com/rust-lang/cargo/pull/14334)\n- Updated to `windows-sys` 0.59\n  [#14335](https://github.com/rust-lang/cargo/pull/14335)\n- Update dependencies.\n  [#14299](https://github.com/rust-lang/cargo/pull/14299)\n  [#14303](https://github.com/rust-lang/cargo/pull/14303)\n  [#14324](https://github.com/rust-lang/cargo/pull/14324)\n  [#14329](https://github.com/rust-lang/cargo/pull/14329)\n  [#14331](https://github.com/rust-lang/cargo/pull/14331)\n  [#14391](https://github.com/rust-lang/cargo/pull/14391)\n\n## Cargo 1.81 (2024-09-05)\n[34a6a87d...rust-1.81.0](https://github.com/rust-lang/cargo/compare/34a6a87d...rust-1.81.0)\n\n### Added\n\n### Changed\n\n- ❗️ cargo-package: Disallow `package.license-file` and `package.readme` pointing\n  to non-existent files during packaging.\n  [#13921](https://github.com/rust-lang/cargo/pull/13921)\n- ❗️ cargo-package: generated `.cargo_vcs_info.json` is always included,\n  even when `--allow-dirty` is passed.\n  [#13960](https://github.com/rust-lang/cargo/pull/13960)\n- ❗️ Disallow passing `--release`/`--debug` flag along with the `--profile` flag.\n  [#13971](https://github.com/rust-lang/cargo/pull/13971)\n- ❗️ Remove `lib.plugin` key support in Cargo.toml.\n  Rust plugin support has been deprecated for four years and was removed in 1.75.0.\n  [#13902](https://github.com/rust-lang/cargo/pull/13902)\n  [#14038](https://github.com/rust-lang/cargo/pull/14038)\n- Make the calculation of `-Cmetadata` for rustc consistent across platforms.\n  [#14107](https://github.com/rust-lang/cargo/pull/14107)\n- Emit a warning when `edition` is unset, even when MSRV is unset.\n  [#14110](https://github.com/rust-lang/cargo/pull/14110)\n\n### Fixed\n\n- Fix a proc-macro example from a dependency affecting feature resolution.\n  [#13892](https://github.com/rust-lang/cargo/pull/13892)\n- Don't warn on duplicate packages from using '..'.\n  [#14234](https://github.com/rust-lang/cargo/pull/14234)\n- Don't `du` on every git source load.\n  [#14252](https://github.com/rust-lang/cargo/pull/14252)\n- Don't warn about unreferenced duplicate packages \n  [#14239](https://github.com/rust-lang/cargo/pull/14239)\n- cargo-publish: Don't strip non-dev features for renamed dependencies from the\n  HTTP JSON body sent to the registry.\n  The bug only affected third-party registries.\n  [#14328](https://github.com/rust-lang/cargo/pull/14328)\n- cargo-vendor: don't copy source files of excluded Cargo targets when vendoring.\n  [#14368](https://github.com/rust-lang/cargo/pull/14368)\n\n### Nightly only\n\n- 🔥 `update-breaking`: Add `--breaking` to `cargo update`,\n  allowing upgrading dependencies to breaking versions.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#update-breaking)\n  [#13979](https://github.com/rust-lang/cargo/pull/13979)\n  [#14047](https://github.com/rust-lang/cargo/pull/14047)\n  [#14049](https://github.com/rust-lang/cargo/pull/14049)\n- `--artifact-dir`: Rename `--out-dir` to `--artifact-dir`.\n  The `--out-dir` flag is kept for compatibility\n  and may be removed when the feature gets stabilized.\n  [#13809](https://github.com/rust-lang/cargo/pull/13809)\n- `edition2024`: Ensure unused optional dependencies fire for shadowed dependencies.\n  [#14028](https://github.com/rust-lang/cargo/pull/14028)\n- `edition2024`: Address problems with implicit -> explicit feature migration \n  [#14018](https://github.com/rust-lang/cargo/pull/14018)\n- `-Zcargo-lints`: Add `unknown_lints` to lints list.\n  [#14024](https://github.com/rust-lang/cargo/pull/14024)\n- `-Zcargo-lints`: Add tooling to document lints.\n  [#14025](https://github.com/rust-lang/cargo/pull/14025)\n- `-Zcargo-lints`: Keep lints updated and sorted.\n  [#14030](https://github.com/rust-lang/cargo/pull/14030)\n- `-Zconfig-include`: Allow enabling `config-include` feature in config.\n  [#14196](https://github.com/rust-lang/cargo/pull/14196)\n- `-Zpublic-dependency`: remove some legacy public dependency code from the resolver\n  [#14090](https://github.com/rust-lang/cargo/pull/14090)\n- `-Ztarget-applies-to-host`: Pass rustflags to artifacts built with implicit targets when using target-applies-to-host\n  [#13900](https://github.com/rust-lang/cargo/pull/13900)\n  [#14201](https://github.com/rust-lang/cargo/pull/14201)\n- cargo-update: Track the behavior of `--precise <prerelease>`.\n  [#14013](https://github.com/rust-lang/cargo/pull/14013)\n\n### Documentation\n\n- Clarify `CARGO_CFG_TARGET_FAMILY` is multi-valued.\n  [#14165](https://github.com/rust-lang/cargo/pull/14165)\n- Document `CARGO_CFG_TARGET_ABI`\n  [#14164](https://github.com/rust-lang/cargo/pull/14164)\n- Document MSRV for each manifest field and build script invocations.\n  [#14224](https://github.com/rust-lang/cargo/pull/14224)\n- Remove duplicate `strip` section. \n  [#14146](https://github.com/rust-lang/cargo/pull/14146)\n- Update summary of Cargo configuration to include missing keys. \n  [#14145](https://github.com/rust-lang/cargo/pull/14145)\n- Update index of Cargo documentation.\n  [#14228](https://github.com/rust-lang/cargo/pull/14228)\n- Don't mention non-existent `workspace.badges` field.\n  [#14042](https://github.com/rust-lang/cargo/pull/14042)\n- contrib: Suggest atomic commits with separate test commits.\n  [#14014](https://github.com/rust-lang/cargo/pull/14014)\n- contrib: Document how to write an RFC for Cargo.\n  [#14222](https://github.com/rust-lang/cargo/pull/14222)\n- contrib: Improve triage instructions \n  [#14052](https://github.com/rust-lang/cargo/pull/14052)\n\n### Internal\n\n- cargo-package: Change verification order during packaging. \n  [#14074](https://github.com/rust-lang/cargo/pull/14074)\n- ci: Add workflow to publish Cargo automatically \n  [#14202](https://github.com/rust-lang/cargo/pull/14202)\n- ci: bump CI tools \n  [#14062](https://github.com/rust-lang/cargo/pull/14062)\n  [#14257](https://github.com/rust-lang/cargo/pull/14257)\n- registry: Add local registry overlays.\n  [#13926](https://github.com/rust-lang/cargo/pull/13926)\n- registry: move `get_source_id` out of registry\n  [#14218](https://github.com/rust-lang/cargo/pull/14218)\n- resolver: Simplify checking for dependency cycles \n  [#14089](https://github.com/rust-lang/cargo/pull/14089)\n- rustfix: Add `CodeFix::apply_solution` and impl `Clone` \n  [#14092](https://github.com/rust-lang/cargo/pull/14092)\n- source: Clean up after `PathSource`/`RecursivePathSource` split\n  [#14169](https://github.com/rust-lang/cargo/pull/14169)\n  [#14231](https://github.com/rust-lang/cargo/pull/14231)\n- Remove the temporary `__CARGO_GITOXIDE_DISABLE_LIST_FILES` environment variable.\n  [#14036](https://github.com/rust-lang/cargo/pull/14036)\n- Simplify checking feature syntax \n  [#14106](https://github.com/rust-lang/cargo/pull/14106)\n- Dont make new constant `InternedString` in hot path \n  [#14211](https://github.com/rust-lang/cargo/pull/14211)\n- Use `std::fs::absolute` instead of reimplementing it \n  [#14075](https://github.com/rust-lang/cargo/pull/14075)\n- Remove unnecessary feature activations from cargo.\n  [#14122](https://github.com/rust-lang/cargo/pull/14122)\n  [#14160](https://github.com/rust-lang/cargo/pull/14160)\n- Revert #13630 as rustc ignores `-C strip` on MSVC.\n  [#14061](https://github.com/rust-lang/cargo/pull/14061)\n- test: Allow `unexpected_builtin_cfgs` lint in `user_specific_cfgs` test \n  [#14153](https://github.com/rust-lang/cargo/pull/14153)\n- test: Add cargo_test to test-support prelude \n  [#14243](https://github.com/rust-lang/cargo/pull/14243)\n- test: migrate Cargo testsuite to `snapbox`.\n  For the complete list of migration pull requests,\n  see [#14039](https://github.com/rust-lang/cargo/issues/14039#issuecomment-2158974033)\n- Updated to `gix` 0.64.0 \n  [#14431](https://github.com/rust-lang/cargo/pull/14431)\n- Update dependencies.\n  [#13995](https://github.com/rust-lang/cargo/pull/13995)\n  [#13998](https://github.com/rust-lang/cargo/pull/13998)\n  [#14037](https://github.com/rust-lang/cargo/pull/14037)\n  [#14063](https://github.com/rust-lang/cargo/pull/14063)\n  [#14067](https://github.com/rust-lang/cargo/pull/14067)\n  [#14174](https://github.com/rust-lang/cargo/pull/14174)\n  [#14186](https://github.com/rust-lang/cargo/pull/14186)\n  [#14254](https://github.com/rust-lang/cargo/pull/14254)\n\n## Cargo 1.80 (2024-07-25)\n[b60a1555...rust-1.80.0](https://github.com/rust-lang/cargo/compare/b60a1555...rust-1.80.0)\n\n### Added\n\n- 🎉 Stabilize `-Zcheck-cfg`! This by default enables rustc's checking of\n  conditional compilation at compile time, which verifies that the crate is\n  correctly handling conditional compilation for different target platforms or\n  features. Internally, cargo will be passing a new command line option\n  `--check-cfg` to all rustc and rustdoc invocations.\n\n  A new build script invocation\n  [`cargo::rustc-check-cfg=CHECK_CFG`](https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg)\n  is added along with this stabilization, as a way to add custom cfgs to the\n  list of expected cfg names and values.\n\n  If a build script is not an option for your package, Cargo provides a config\n  [`[lints.rust.unexpected_cfgs.check-cfg]`](https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html#check-cfg-in-lintsrust-table)\n  to add known custom cfgs statically.\n\n  ([RFC 3013](https://github.com/rust-lang/rfcs/blob/master/text/3013-conditional-compilation-checking.md))\n  ([docs](https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html))\n  [#13571](https://github.com/rust-lang/cargo/pull/13571)\n  [#13865](https://github.com/rust-lang/cargo/pull/13865)\n  [#13869](https://github.com/rust-lang/cargo/pull/13869)\n  [#13884](https://github.com/rust-lang/cargo/pull/13884)\n  [#13913](https://github.com/rust-lang/cargo/pull/13913)\n  [#13937](https://github.com/rust-lang/cargo/pull/13937)\n  [#13958](https://github.com/rust-lang/cargo/pull/13958)\n\n- 🎉 cargo-update: Allows `--precise` to specify a yanked version of a package,\n  and will update the lockfile accordingly.\n  [#13974](https://github.com/rust-lang/cargo/pull/13974)\n\n### Changed\n\n- ❗️ manifest: Disallow `[badges]` to inherit from `[workspace.package.badges]`.\n  This was considered a bug.\n  Keep in mind that `[badges]` is effectively deprecated.\n  [#13788](https://github.com/rust-lang/cargo/pull/13788)\n- build-script: Suggest old syntax based on MSRV.\n  [#13874](https://github.com/rust-lang/cargo/pull/13874)\n- cargo-add: Avoid escaping double quotes by using string literals.\n  [#14006](https://github.com/rust-lang/cargo/pull/14006)\n- cargo-clean: Performance improvements for cleaning specific packages via `-p` flag.\n  [#13818](https://github.com/rust-lang/cargo/pull/13818)\n- cargo-new: Use `i32` rather than `usize` as the \"default integer\" in library template.\n  [#13939](https://github.com/rust-lang/cargo/pull/13939)\n- cargo-package: Warn, rather than fail, if a Cargo target is excluded during packaging.\n  [#13713](https://github.com/rust-lang/cargo/pull/13713)\n- manifest: Warn, not error, on unsupported lint tool in the `[lints]` table.\n  [#13833](https://github.com/rust-lang/cargo/pull/13833)\n- perf: Avoid inferring when Cargo targets are known.\n  [#13849](https://github.com/rust-lang/cargo/pull/13849)\n- Populate git information when building Cargo from Rust's source tarball.\n  [#13832](https://github.com/rust-lang/cargo/pull/13832)\n- Improve the error message when deserializing Cargo configuration from partial environment variables.\n  [#13956](https://github.com/rust-lang/cargo/pull/13956)\n\n### Fixed\n\n- resolver: Make path dependencies with the same name stay locked.\n  [#13572](https://github.com/rust-lang/cargo/pull/13572)\n- cargo-add: Preserve file permissions on Unix during `write_atomic`.\n  [#13898](https://github.com/rust-lang/cargo/pull/13898)\n- cargo-clean: Remove symlink directory on Windows.\n  [#13910](https://github.com/rust-lang/cargo/pull/13910)\n- cargo-fix: Don't fix into the standard library.\n  [#13792](https://github.com/rust-lang/cargo/pull/13792)\n- cargo-fix: Support IPv6-only networks.\n  [#13907](https://github.com/rust-lang/cargo/pull/13907)\n- cargo-new: Don't say we're adding to a workspace when a regular package is in the root.\n  [#13987](https://github.com/rust-lang/cargo/pull/13987)\n- cargo-vendor: Silence the warning about forgetting the vendoring.\n  [#13886](https://github.com/rust-lang/cargo/pull/13886)\n- cargo-publish/cargo-vendor: Ensure targets in generated Cargo.toml are in a deterministic order.\n  [#13989](https://github.com/rust-lang/cargo/pull/13989)\n  [#14004](https://github.com/rust-lang/cargo/pull/14004)\n- cargo-credential-libsecret: Load `libsecret` by its `SONAME`, `libsecret-1.so.0`.\n  [#13927](https://github.com/rust-lang/cargo/pull/13927)\n- Don't panic when an alias doesn't include a subcommand.\n  [#13819](https://github.com/rust-lang/cargo/pull/13819)\n- Workaround copying file returning EAGAIN on ZFS on macOS.\n  [#13845](https://github.com/rust-lang/cargo/pull/13845)\n- Fetch specific commits even if the GitHub fast path fails.\n  [#13946](https://github.com/rust-lang/cargo/pull/13946)\n  [#13969](https://github.com/rust-lang/cargo/pull/13969)\n- Distinguish Cargo config from different environment variables that share the same prefix.\n  [#14000](https://github.com/rust-lang/cargo/pull/14000)\n\n### Nightly only\n\n- `-Zcargo-lints`: Don't always inherit workspace lints.\n  [#13812](https://github.com/rust-lang/cargo/pull/13812)\n- `-Zcargo-lints`: Add a test to ensure cap-lints works.\n  [#13829](https://github.com/rust-lang/cargo/pull/13829)\n- `-Zcargo-lints`: Error when unstable lints are specified but not enabled.\n  [#13805](https://github.com/rust-lang/cargo/pull/13805)\n- `-Zcargo-lints`: Add cargo-lints to unstable docs.\n  [#13881](https://github.com/rust-lang/cargo/pull/13881)\n- `-Zcargo-lints`: Refactor cargo lint tests.\n  [#13880](https://github.com/rust-lang/cargo/pull/13880)\n- `-Zcargo-lints`: Remove ability to specify `-` in lint name.\n  [#13837](https://github.com/rust-lang/cargo/pull/13837)\n- `-Zscript`: Remove unstable rejected frontmatter syntax for cargo script.\n  The only allowed frontmatter syntax now is `---`.\n  [#13861](https://github.com/rust-lang/cargo/pull/13861)\n  [#13893](https://github.com/rust-lang/cargo/pull/13893)\n- `-Zbindeps`: Build only the specified artifact library when multiple types are available.\n  [#13842](https://github.com/rust-lang/cargo/pull/13842)\n- `-Zmsrv-policy`: Treat unset MSRV as compatible.\n  [#13791](https://github.com/rust-lang/cargo/pull/13791)\n- `-Zgit`/`-Zgitoxide`: Default configuration to be obtained from both environment variables and Cargo configuration.\n  [#13687](https://github.com/rust-lang/cargo/pull/13687)\n- `-Zpublic-dependency`: Don't lose 'public' when inheriting a dependency.\n  [#13836](https://github.com/rust-lang/cargo/pull/13836)\n- `edition2024`: Disallow ignored `default-features` when inheriting.\n  [#13839](https://github.com/rust-lang/cargo/pull/13839)\n- `edition2024`: Validate crate-types/proc-macro for bin like other Cargo targets.\n  [#13841](https://github.com/rust-lang/cargo/pull/13841)\n\n### Documentation\n\n- cargo-package: Clarify no guarantee of VCS provenance.\n  [#13984](https://github.com/rust-lang/cargo/pull/13984)\n- cargo-metadata: Clarify dash replacement rule in Cargo target names.\n  [#13887](https://github.com/rust-lang/cargo/pull/13887)\n- config: Fix wrong type of `rustc-flags` in build script overrides.\n  [#13957](https://github.com/rust-lang/cargo/pull/13957)\n- resolver: Add README for `resolver-tests`.\n  [#13977](https://github.com/rust-lang/cargo/pull/13977)\n- contrib: Update UI example code in contributor guide.\n  [#13864](https://github.com/rust-lang/cargo/pull/13864)\n- Fix libcurl proxy documentation link.\n  [#13990](https://github.com/rust-lang/cargo/pull/13990)\n- Add missing `CARGO_MAKEFLAGS` env for plugins.\n  [#13872](https://github.com/rust-lang/cargo/pull/13872)\n- Include CircleCI reference in the Continuous Integration chapter.\n  [#13850](https://github.com/rust-lang/cargo/pull/13850)\n\n### Internal\n\n- ci: Don't check `cargo` against beta channel.\n  [#13827](https://github.com/rust-lang/cargo/pull/13827)\n- test: Set safe.directory for git repo in apache container.\n  [#13920](https://github.com/rust-lang/cargo/pull/13920)\n- test: Silence warnings running embedded unittests.\n  [#13929](https://github.com/rust-lang/cargo/pull/13929)\n- test: Update test formatting due to nightly rustc changes.\n  [#13890](https://github.com/rust-lang/cargo/pull/13890)\n  [#13901](https://github.com/rust-lang/cargo/pull/13901)\n  [#13964](https://github.com/rust-lang/cargo/pull/13964)\n- test: Make `git::use_the_cli` test truly locale independent.\n  [#13935](https://github.com/rust-lang/cargo/pull/13935)\n- cargo-test-support: Transition direct assertions from cargo-test-support to snapbox.\n  [#13980](https://github.com/rust-lang/cargo/pull/13980)\n- cargo-test-support: Auto-redact elapsed time.\n  [#13973](https://github.com/rust-lang/cargo/pull/13973)\n- cargo-test-support: Clean up unnecessary uses of `match_exact`.\n  [#13879](https://github.com/rust-lang/cargo/pull/13879)\n- Split `RecursivePathSource` out of `PathSource`.\n  [#13993](https://github.com/rust-lang/cargo/pull/13993)\n- Adjust custom errors from cert-check due to libgit2 1.8 change.\n  [#13970](https://github.com/rust-lang/cargo/pull/13970)\n- Move diagnostic printing to Shell.\n  [#13813](https://github.com/rust-lang/cargo/pull/13813)\n- Update dependencies.\n  [#13834](https://github.com/rust-lang/cargo/pull/13834)\n  [#13840](https://github.com/rust-lang/cargo/pull/13840)\n  [#13948](https://github.com/rust-lang/cargo/pull/13948)\n  [#13963](https://github.com/rust-lang/cargo/pull/13963)\n  [#13976](https://github.com/rust-lang/cargo/pull/13976)\n\n## Cargo 1.79 (2024-06-13)\n[2fe739fc...rust-1.79.0](https://github.com/rust-lang/cargo/compare/2fe739fc...rust-1.79.0)\n\n### Added\n\n- 🎉 `cargo add` respects `package.rust-version` a.k.a. MSRV when adding new\n  dependencies. The behavior can be overridden by specifying a version requirement,\n  or passing the `--ignore-rust-version` flag.\n  ([RFC 3537](https://github.com/rust-lang/rfcs/blob/master/text/3537-msrv-resolver.md))\n  [#13608](https://github.com/rust-lang/cargo/pull/13608)\n- A new `Locking` status message shows dependency changes on any command.\n  For `cargo update`, it also tells you if any dependency version is outdated.\n  [#13561](https://github.com/rust-lang/cargo/pull/13561)\n  [#13647](https://github.com/rust-lang/cargo/pull/13647)\n  [#13651](https://github.com/rust-lang/cargo/pull/13651)\n  [#13657](https://github.com/rust-lang/cargo/pull/13657)\n  [#13759](https://github.com/rust-lang/cargo/pull/13759)\n  [#13764](https://github.com/rust-lang/cargo/pull/13764)\n\n### Changed\n\n- ❗️ `RUSTC_WRAPPER`, `RUSTC_WORKSPACE_WRAPPER`, and variables from the `[env]`\n  table now also apply to the initial `rustc -vV` invocation Cargo uses for\n  probing rustc information.\n  [#13659](https://github.com/rust-lang/cargo/pull/13659)\n- ❗️ Turns dependencies like `foo = { optional = true }` from `version=\"*\"`\n  dependencies with a warning into errors.\n  This behavior has been considered a bug from the beginning.\n  [#13775](https://github.com/rust-lang/cargo/pull/13775)\n- ❗️ Replace dashes with underscores also if `lib.name` is inferred from `package.name`.\n  This change aligns to the documented behavior. One caveat is that JSON messages\n  emitted by Cargo, like via `cargo metadata` or `--message-format=json`,\n  will start reporting underscore lib names.\n  [#12783](https://github.com/rust-lang/cargo/pull/12783)\n- Switch to `gitoxide` for listing files. This improves the performance of\n  build script and `cargo doc` for computing cache freshness,\n  as well as fixes some subtle bugs for `cargo publish`.\n  [#13592](https://github.com/rust-lang/cargo/pull/13592)\n  [#13696](https://github.com/rust-lang/cargo/pull/13696)\n  [#13704](https://github.com/rust-lang/cargo/pull/13704)\n  [#13777](https://github.com/rust-lang/cargo/pull/13777)\n- Warn on `-Zlints` being passed and no longer necessary.\n  [#13632](https://github.com/rust-lang/cargo/pull/13632)\n- Warn on unused `workspace.dependencies` keys on virtual workspaces.\n  [#13664](https://github.com/rust-lang/cargo/pull/13664)\n- Emit 1.77 build script syntax error only when msrv is incompatible.\n  [#13808](https://github.com/rust-lang/cargo/pull/13808)\n- Don't warn on `lints.rust.unexpected_cfgs.check-cfg`.\n  [#13925](https://github.com/rust-lang/cargo/pull/13925)\n- cargo-init: don't assign `target.name` in Cargo.toml if the value can be inferred.\n  [#13606](https://github.com/rust-lang/cargo/pull/13606)\n- cargo-package: normalize paths in `Cargo.toml`, including replacing `\\` with `/`.\n  [#13729](https://github.com/rust-lang/cargo/pull/13729)\n- cargo-test: recategorize cargo test's `--doc` flag under “Target Selection”.\n  [#13756](https://github.com/rust-lang/cargo/pull/13756)\n\n### Fixed\n\n- Ensure `--config net.git-fetch-with-cli=true` is respected.\n  [#13992](https://github.com/rust-lang/cargo/pull/13992)\n  [#13997](https://github.com/rust-lang/cargo/pull/13997)\n- Dont panic when resolving an empty alias.\n  [#13613](https://github.com/rust-lang/cargo/pull/13613)\n- When using `--target`, the default debuginfo strip rule also applies.\n  Note that on Windows MSVC Cargo no longer strips by default.\n  [#13618](https://github.com/rust-lang/cargo/pull/13618)\n- Don't crash on Cargo.toml parse errors that point to multi-byte character\n  [#13780](https://github.com/rust-lang/cargo/pull/13780)\n- Don't emit deprecation warning if one of `.cargo/{config,config.toml}` is\n  a symlink to the other.\n  [#13793](https://github.com/rust-lang/cargo/pull/13793)\n- Follow HTTP redirections when checking if a repo on GitHub is up-to-date.\n  [#13718](https://github.com/rust-lang/cargo/pull/13718)\n- Bash completion fallback in `nounset` mode.\n  [#13686](https://github.com/rust-lang/cargo/pull/13686)\n- Rerun build script when rustflags changed and `--target` was passed.\n  [#13560](https://github.com/rust-lang/cargo/pull/13560)\n- Fix doc collision for lib/bin with a dash in the inferred name.\n  [#13640](https://github.com/rust-lang/cargo/pull/13640)\n- cargo-add: Maintain sorting of dependency features.\n  [#13682](https://github.com/rust-lang/cargo/pull/13682)\n- cargo-add: Preserve comments when updating simple deps\n  [#13655](https://github.com/rust-lang/cargo/pull/13655)\n- cargo-fix: dont apply same suggestion twice.\n  [#13728](https://github.com/rust-lang/cargo/pull/13728)\n- cargo-package: error when the package specified via `--package` cannot be found\n  [#13735](https://github.com/rust-lang/cargo/pull/13735)\n- credential-provider: trim newlines in tokens from stdin.\n  [#13770](https://github.com/rust-lang/cargo/pull/13770)\n\n### Nightly only\n\n- 🔥 cargo-update: allows `--precise` to specify a pre-release version of a package\n  ([RFC 3493](https://github.com/rust-lang/rfcs/blob/master/text/3493-precise-pre-release-cargo-update.md))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#precise-pre-release))\n  [#13626](https://github.com/rust-lang/cargo/pull/13626)\n- RFC 3491: Unused dependencies cleanup\n  [#13778](https://github.com/rust-lang/cargo/pull/13778)\n- `-Zcargo-lints`: Add a basic linting system for Cargo.\n  This is still under development and not available for general use.\n  [#13621](https://github.com/rust-lang/cargo/pull/13621)\n  [#13635](https://github.com/rust-lang/cargo/pull/13635)\n  [#13797](https://github.com/rust-lang/cargo/pull/13797)\n  [#13740](https://github.com/rust-lang/cargo/pull/13740)\n  [#13801](https://github.com/rust-lang/cargo/pull/13801)\n  [#13852](https://github.com/rust-lang/cargo/pull/13852)\n  [#13853](https://github.com/rust-lang/cargo/pull/13853)\n- 🔥 `edition2024`: Add default Edition2024 to resolver v3 (MSRV-aware resolver).\n  [#13785](https://github.com/rust-lang/cargo/pull/13785)\n- `edition2024`: Remove underscore field support in 2024.\n  [#13783](https://github.com/rust-lang/cargo/pull/13783)\n  [#13798](https://github.com/rust-lang/cargo/pull/13798)\n  [#13800](https://github.com/rust-lang/cargo/pull/13800)\n  [#13804](https://github.com/rust-lang/cargo/pull/13804)\n- `edition2024`: Error on `[project]` in Edition 2024\n  [#13747](https://github.com/rust-lang/cargo/pull/13747)\n- `-Zmsrv-policy`: Respect '--ignore-rust-version'\n  [#13738](https://github.com/rust-lang/cargo/pull/13738)\n- `-Zmsrv-policy`: Add `--ignore-rust-version` to update/generate-lockfile\n  [#13741](https://github.com/rust-lang/cargo/pull/13741)\n  [#13742](https://github.com/rust-lang/cargo/pull/13742)\n- `-Zmsrv-policy`: Put MSRV-aware resolver behind a config\n  [#13769](https://github.com/rust-lang/cargo/pull/13769)\n- `-Zmsrv-policy`: Error, rather than panic, on rust-version 'x'\n  [#13771](https://github.com/rust-lang/cargo/pull/13771)\n- `-Zmsrv-policy`: Fallback to 'rustc -V' for MSRV resolving.\n  [#13743](https://github.com/rust-lang/cargo/pull/13743)\n- `-Zmsrv-policy`: Add v3 resolver for MSRV-aware resolving\n  [#13776](https://github.com/rust-lang/cargo/pull/13776)\n- `-Zmsrv-policy`: Don't respect MSRV for non-local installs\n  [#13790](https://github.com/rust-lang/cargo/pull/13790)\n- `-Zmsrv-policy`: Track when MSRV is explicitly set, either way\n  [#13732](https://github.com/rust-lang/cargo/pull/13732)\n- test: don't compress test registry crates.\n  [#13744](https://github.com/rust-lang/cargo/pull/13744)\n\n### Documentation\n\n- Clarify `--locked` ensuring that Cargo uses dependency versions in lockfile\n  [#13665](https://github.com/rust-lang/cargo/pull/13665)\n- Clarify the precedence of  `RUSTC_WORKSPACE_WRAPPER` and `RUSTC_WRAPPER`.\n  [#13648](https://github.com/rust-lang/cargo/pull/13648)\n- Clarify only in the root Cargo.toml the `[workspace]` section is allowed.\n  [#13753](https://github.com/rust-lang/cargo/pull/13753)\n- Clarify the differences between virtual and real manifests.\n  [#13794](https://github.com/rust-lang/cargo/pull/13794)\n\n### Internal\n\n- 🎉 New member crates [`cargo-test-support`](https://crates.io/crates/cargo-test-support)\n  and [`cargo-test-macro`](https://crates.io/crates/cargo-test-macro)!\n  They are designed for testing Cargo itself,\n  so no guarantee on any stability across versions.\n  The crates.io publish of this crate is the same as other members crates.\n  They follow Rust's [6-week release process](https://doc.crates.io/contrib/process/release.html#cratesio-publishing).\n  [#13418](https://github.com/rust-lang/cargo/pull/13418)\n- Fix publish script due to crates.io CDN change\n  [#13614](https://github.com/rust-lang/cargo/pull/13614)\n- Push diagnostic complexity on annotate-snippets\n  [#13619](https://github.com/rust-lang/cargo/pull/13619)\n- cargo-package: Simplify getting of published Manifest\n  [#13666](https://github.com/rust-lang/cargo/pull/13666)\n- ci: update macos images to macos-13\n  [#13685](https://github.com/rust-lang/cargo/pull/13685)\n- manifest: Split out an explicit step to resolve `Cargo.toml`\n  [#13693](https://github.com/rust-lang/cargo/pull/13693)\n- manifest: Decouple target discovery from Target creation\n  [#13701](https://github.com/rust-lang/cargo/pull/13701)\n- manifest: Expose surce/spans for VirtualManifests\n  [#13603](https://github.com/rust-lang/cargo/pull/13603)\n- Update dependencies\n  [#13609](https://github.com/rust-lang/cargo/pull/13609)\n  [#13674](https://github.com/rust-lang/cargo/pull/13674)\n  [#13675](https://github.com/rust-lang/cargo/pull/13675)\n  [#13679](https://github.com/rust-lang/cargo/pull/13679)\n  [#13680](https://github.com/rust-lang/cargo/pull/13680)\n  [#13692](https://github.com/rust-lang/cargo/pull/13692)\n  [#13731](https://github.com/rust-lang/cargo/pull/13731)\n  [#13760](https://github.com/rust-lang/cargo/pull/13760)\n  [#13950](https://github.com/rust-lang/cargo/pull/13950)\n\n## Cargo 1.78 (2024-05-02)\n[7bb7b539...rust-1.78.0](https://github.com/rust-lang/cargo/compare/7bb7b539...rust-1.78.0)\n\n### Added\n\n- Stabilize global cache data tracking. The `-Zgc` flag is still unstable.\n  This is only for Cargo to start data collection, so that when automatic gc\n  is stabilized, it's less likely to see cache misses.\n  [#13492](https://github.com/rust-lang/cargo/pull/13492)\n  [#13467](https://github.com/rust-lang/cargo/pull/13467)\n- Stabilize lockfile format v4. Lockfile v3 is still the default version.\n  [#12852](https://github.com/rust-lang/cargo/pull/12852)\n- Auto-detecting whether output can be rendered using non-ASCII Unicode characters.\n  A configuration value `term.unicode` is added to control the behavior manually.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#termunicode)\n  [#13337](https://github.com/rust-lang/cargo/pull/13337)\n- Support `target.<triple>.rustdocflags` in Cargo configuration.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#targettriplerustdocflags)\n  [#13197](https://github.com/rust-lang/cargo/pull/13197)\n\n### Changed\n\n- cargo-add: Print a status when a dep feature is being created\n  [#13434](https://github.com/rust-lang/cargo/pull/13434)\n- cargo-add: improve the error message when adding a package from a replaced source.\n  [#13281](https://github.com/rust-lang/cargo/pull/13281)\n- cargo-doc: Collapse down `Generated` statuses without `--verbose`.\n  [#13557](https://github.com/rust-lang/cargo/pull/13557)\n- cargo-new: Print a 'Creating', rather than 'Created' status\n  [#13367](https://github.com/rust-lang/cargo/pull/13367)\n- cargo-new: Print a note, rather than a comment, for more information\n  [#13371](https://github.com/rust-lang/cargo/pull/13371)\n- cargo-new: Print a hint when adding members to workspace\n  [#13411](https://github.com/rust-lang/cargo/pull/13411)\n- cargo-test: Suggest `--` for libtest arguments \n  [#13448](https://github.com/rust-lang/cargo/pull/13448)\n- cargo-update: Tell users when some dependencies are still behind latest.\n  [#13372](https://github.com/rust-lang/cargo/pull/13372)\n- Deprecate non-extension `.cargo/config` files.\n  [#13349](https://github.com/rust-lang/cargo/pull/13349)\n- Don't print rustdoc command lines on failure by default\n  [#13387](https://github.com/rust-lang/cargo/pull/13387)\n- Respect `package.rust-version` when generating new lockfiles.\n  [#12861](https://github.com/rust-lang/cargo/pull/12861)\n- Send `User-Agent: cargo/1.2.3` header when communicating with remote registries.\n  Previously it was `cargo 1.2.3`, which didn't follow the HTTP specifications.\n  [#13548](https://github.com/rust-lang/cargo/pull/13548)\n- Emit a warning when `package.edition` field is missing in Cargo.toml.\n  [#13499](https://github.com/rust-lang/cargo/pull/13499)\n  [#13504](https://github.com/rust-lang/cargo/pull/13504)\n  [#13505](https://github.com/rust-lang/cargo/pull/13505)\n  [#13533](https://github.com/rust-lang/cargo/pull/13533)\n- Emit warnings from parsing virtual manifests.\n  [#13589](https://github.com/rust-lang/cargo/pull/13589)\n- Mention the workspace root location in the error message when collecting\n  workspace members.\n  [#13480](https://github.com/rust-lang/cargo/pull/13480)\n- Clarify the profile in use in `Finished` status message.\n  [#13422](https://github.com/rust-lang/cargo/pull/13422)\n- Switched more notes/warnings to lowercase.\n  [#13410](https://github.com/rust-lang/cargo/pull/13410)\n- Report all packages incompatible with `package.rust-version.`, not just a random one.\n  [#13514](https://github.com/rust-lang/cargo/pull/13514)\n\n### Fixed\n\n- cargo-add: don't add the new package to `workspace.members` if there is no\n  existing workspace in Cargo.toml.\n  [#13391](https://github.com/rust-lang/cargo/pull/13391)\n- cargo-add: Fix markdown line break in cargo-add\n  [#13400](https://github.com/rust-lang/cargo/pull/13400)\n- cargo-run: use Package ID Spec match packages\n  [#13335](https://github.com/rust-lang/cargo/pull/13335)\n- cargo-doc: doctest searches native libs in build script outputs.\n  [#13490](https://github.com/rust-lang/cargo/pull/13490)\n- cargo-publish: strip also features from dev-dependencies from Cargo.toml to publish.\n  [#13518](https://github.com/rust-lang/cargo/pull/13518)\n- Don't duplicate comments when editing TOML via `cargo add/rm/init/new`.\n  [#13402](https://github.com/rust-lang/cargo/pull/13402)\n- Fix confusing error messages for sparse index replaced source.\n  [#13433](https://github.com/rust-lang/cargo/pull/13433)\n- Respect `CARGO_TERM_COLOR` in '--list' and '-Zhelp'.\n  [#13479](https://github.com/rust-lang/cargo/pull/13479)\n- Control colors of errors and help texts from clap through `CARGO_TERM_COLOR`.\n  [#13463](https://github.com/rust-lang/cargo/pull/13463)\n- Don't panic on empty spans in Cargo.toml.\n  [#13375](https://github.com/rust-lang/cargo/pull/13375)\n  [#13376](https://github.com/rust-lang/cargo/pull/13376)\n\n### Nightly only\n\n- 🔥 cargo-update: allows `--precise` to specify a yanked version of a package\n  [#13333](https://github.com/rust-lang/cargo/pull/13333)\n- `-Zcheck-cfg`: Add `docsrs` cfg as a well known `--check-cfg`\n  [#13383](https://github.com/rust-lang/cargo/pull/13383)\n- `-Zcheck-cfg`: Silently ignore `cargo::rustc-check-cfg` to avoid MSRV\n  annoyance when stabilizing `-Zcheck-cfg`.\n  [#13438](https://github.com/rust-lang/cargo/pull/13438)\n- `-Zmsrv-policy`: Fallback to `rustc -v` when no MSRV is set \n  [#13516](https://github.com/rust-lang/cargo/pull/13516)\n- `-Zscript`: Improve errors related to cargo script\n  [#13346](https://github.com/rust-lang/cargo/pull/13346)\n- `-Zpanic-abort-tests`: applies to doctests too\n  [#13388](https://github.com/rust-lang/cargo/pull/13388)\n- `-Zpublic-dependency`: supports enabling via the `-Zpublic-dependency` flag.\n  [#13340](https://github.com/rust-lang/cargo/pull/13340)\n  [#13556](https://github.com/rust-lang/cargo/pull/13556)\n  [#13547](https://github.com/rust-lang/cargo/pull/13547)\n- `-Zpublic-dependency`: test for packaging a public dependency\n  [#13536](https://github.com/rust-lang/cargo/pull/13536)\n- `-Zrustdoc-map`: Add all unit's children recursively for `doc.extern-map` option \n  [#13481](https://github.com/rust-lang/cargo/pull/13481)\n  [#13544](https://github.com/rust-lang/cargo/pull/13544)\n- `edition2024`: Enable edition migration for 2024.\n  [#13429](https://github.com/rust-lang/cargo/pull/13429)\n- `open-namespaces`: basic support for open namespaces\n  ([RFC 3243](https://github.com/rust-lang/rfcs/blob/master/text/3243-packages-as-optional-namespaces.md))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#open-namespaces))\n  [#13591](https://github.com/rust-lang/cargo/pull/13591)\n\n### Documentation\n\n- cargo-fetch: hide `cargo-fetch` recursive link in `--offline` man page.\n  [#13364](https://github.com/rust-lang/cargo/pull/13364)\n- cargo-install: `--list` option description starting with uppercase\n  [#13344](https://github.com/rust-lang/cargo/pull/13344)\n- cargo-vendor: clarify vendored sources as read-only and ways to modify them\n  [#13512](https://github.com/rust-lang/cargo/pull/13512)\n- build-script: clarification of build script metadata set via `cargo::metadata=KEY=VALUE`.\n  [#13436](https://github.com/rust-lang/cargo/pull/13436)\n- Clarify the `version` field in `[package]` is optional in Cargo.toml\n  [#13390](https://github.com/rust-lang/cargo/pull/13390)\n- Improve \"Registry Authentication\" docs\n  [#13351](https://github.com/rust-lang/cargo/pull/13351)\n- Improve \"Specifying Dependencies\" docs\n  [#13341](https://github.com/rust-lang/cargo/pull/13341)\n- Remove `package.documentation` from the “before publishing” list.\n  [#13398](https://github.com/rust-lang/cargo/pull/13398)\n\n### Internal\n\n- 🎉 Integrated tracing-chrome as a basic profiler for Cargo itself.\n  [docs](https://doc.crates.io/contrib/tests/profiling.html)\n  [#13399](https://github.com/rust-lang/cargo/pull/13399)\n  [#13551](https://github.com/rust-lang/cargo/pull/13551)\n- Updated to `gix` 0.58.0\n  [#13380](https://github.com/rust-lang/cargo/pull/13380)\n- Updated to `git2` 0.18.2\n  [#13412](https://github.com/rust-lang/cargo/pull/13412)\n- Updated to `jobserver` 0.1.28 \n  [#13419](https://github.com/rust-lang/cargo/pull/13419)\n- Updated to `supports-hyperlinks` 3.0.0\n  [#13511](https://github.com/rust-lang/cargo/pull/13511)\n- Updated to `rusqlite` 0.31.0\n  [#13510](https://github.com/rust-lang/cargo/pull/13510)\n- bump-check: use symmetric difference when comparing source code\n    [#13581](https://github.com/rust-lang/cargo/pull/13581)\n- bump-check: include rustfix and cargo-util-schemas\n    [#13421](https://github.com/rust-lang/cargo/pull/13421)\n- ci: enable m1 runner\n  [#13377](https://github.com/rust-lang/cargo/pull/13377)\n- ci: Ensure lockfile is respected during MSRV testing via `cargo-hack`.\n  [#13523](https://github.com/rust-lang/cargo/pull/13523)\n- cargo-util-schemas: Consistently compare MSRVs via `RustVersion::is_compatible_with`.\n  [#13537](https://github.com/rust-lang/cargo/pull/13537)\n- console: Use new fancy `anstyle` API\n  [#13368](https://github.com/rust-lang/cargo/pull/13368)\n  [#13562](https://github.com/rust-lang/cargo/pull/13562)\n- fingerprint: remove unnecessary Option in `Freshness::Dirty`\n  [#13361](https://github.com/rust-lang/cargo/pull/13361)\n- fingerprint: abstract `std::fs` away from on-disk index cache\n  [#13515](https://github.com/rust-lang/cargo/pull/13515)\n- mdman: Updated to `pulldown-cmark` 0.10.0\n  [#13517](https://github.com/rust-lang/cargo/pull/13517)\n- refactor: Renamed `Config` to `GlobalContext` \n  [#13409](https://github.com/rust-lang/cargo/pull/13409)\n  [#13486](https://github.com/rust-lang/cargo/pull/13486)\n  [#13506](https://github.com/rust-lang/cargo/pull/13506)\n- refactor: Removed unused `sysroot_host_libdir`.\n  [#13468](https://github.com/rust-lang/cargo/pull/13468)\n- refactor: Expose source/spans to Manifest for emitting lints\n  [#13593](https://github.com/rust-lang/cargo/pull/13593)\n- refactor: Flatten manifest parsing \n  [#13589](https://github.com/rust-lang/cargo/pull/13589)\n- refactor: Make lockfile diffing/printing more reusable\n  [#13564](https://github.com/rust-lang/cargo/pull/13564)\n- test: Updated to `snapbox` 0.5.0\n  [#13441](https://github.com/rust-lang/cargo/pull/13441)\n- test: Verify terminal styling via snapbox's `term-svg` feature.\n  [#13461](https://github.com/rust-lang/cargo/pull/13461)\n  [#13465](https://github.com/rust-lang/cargo/pull/13465)\n  [#13520](https://github.com/rust-lang/cargo/pull/13520)\n- test: Ensure `nonzero_exit_code` test isn't affected by developers `RUST_BACKTRACE` setting \n  [#13385](https://github.com/rust-lang/cargo/pull/13385)\n- test: Add tests for using worktrees.\n  [#13567](https://github.com/rust-lang/cargo/pull/13567)\n- test: Fix old_cargos tests \n  [#13435](https://github.com/rust-lang/cargo/pull/13435)\n- test: Fixed tests due to changes in rust-lang/rust.\n  [#13362](https://github.com/rust-lang/cargo/pull/13362)\n  [#13382](https://github.com/rust-lang/cargo/pull/13382)\n  [#13415](https://github.com/rust-lang/cargo/pull/13415)\n  [#13424](https://github.com/rust-lang/cargo/pull/13424)\n  [#13444](https://github.com/rust-lang/cargo/pull/13444)\n  [#13455](https://github.com/rust-lang/cargo/pull/13455)\n  [#13464](https://github.com/rust-lang/cargo/pull/13464)\n  [#13466](https://github.com/rust-lang/cargo/pull/13466)\n  [#13469](https://github.com/rust-lang/cargo/pull/13469)\n- test: disable lldb test as it requires privileges to run on macOS \n  [#13416](https://github.com/rust-lang/cargo/pull/13416)\n\n## Cargo 1.77.1 (2024-03-28)\n\n### Fixed\n\n- Debuginfo is no longer stripped by default for Windows MSVC targets. This caused an unexpected regression in 1.77.0 that broke backtraces.\n  [#13654](https://github.com/rust-lang/cargo/pull/13654)\n\n## Cargo 1.77 (2024-03-21)\n[1a2666dd...rust-1.77.0](https://github.com/rust-lang/cargo/compare/1a2666dd...rust-1.77.0)\n\n### Added\n\n- 🎉 Stabilize the package identifier format as [Package ID Spec](https://doc.rust-lang.org/nightly/cargo/reference/pkgid-spec.html).\n  This format can be used across most of the commands in Cargo, including the\n  `--package`/`-p` flag, `cargo pkgid`, `cargo metadata`, and JSON messages\n  from `--message-format=json`.\n  [#12914](https://github.com/rust-lang/cargo/pull/12914)\n  [#13202](https://github.com/rust-lang/cargo/pull/13202)\n  [#13311](https://github.com/rust-lang/cargo/pull/13311)\n  [#13298](https://github.com/rust-lang/cargo/pull/13298)\n  [#13322](https://github.com/rust-lang/cargo/pull/13322)\n- Add colors to `-Zhelp` console output\n  [#13269](https://github.com/rust-lang/cargo/pull/13269)\n- build script: Extend the build directive syntax with `cargo::`.\n  [#12201](https://github.com/rust-lang/cargo/pull/12201)\n  [#13212](https://github.com/rust-lang/cargo/pull/13212)\n\n### Changed\n\n- 🎉 Disabling debuginfo now implies `strip = \"debuginfo\"` (when `strip` is not set)\n  to strip pre-existing debuginfo coming from the standard library,\n  reducing the default size of release binaries considerably\n  (from ~4.5 MiB down to ~450 KiB for helloworld on Linux x64).\n  [#13257](https://github.com/rust-lang/cargo/pull/13257)\n- Add `rustc` style errors for manifest parsing.\n  [#13172](https://github.com/rust-lang/cargo/pull/13172)\n- Deprecate rustc plugin support in cargo\n  [#13248](https://github.com/rust-lang/cargo/pull/13248)\n- cargo-vendor: Hold the mutate exclusive lock when vendoring.\n  [#12509](https://github.com/rust-lang/cargo/pull/12509)\n- crates-io: Set `Content-Type: application/json` only for requests with a body payload\n  [#13264](https://github.com/rust-lang/cargo/pull/13264)\n\n### Fixed\n\n- jobserver: inherit jobserver from env for all kinds of runner\n  [#12776](https://github.com/rust-lang/cargo/pull/12776)\n- build script: Set `OUT_DIR` for all units with build scripts\n  [#13204](https://github.com/rust-lang/cargo/pull/13204)\n- cargo-add: find the correct package with given features from Git repositories\n  with multiple packages.\n  [#13213](https://github.com/rust-lang/cargo/pull/13213)\n- cargo-fix: always inherit the jobserver\n  [#13225](https://github.com/rust-lang/cargo/pull/13225)\n- cargo-fix: Call rustc fewer times to improve the performance.\n  [#13243](https://github.com/rust-lang/cargo/pull/13243)\n- cargo-new: only inherit workspace package table if the new package is a member\n  [#13261](https://github.com/rust-lang/cargo/pull/13261)\n- cargo-update: `--precise` accepts arbitrary git revisions\n  [#13250](https://github.com/rust-lang/cargo/pull/13250)\n- manifest: Provide unused key warnings for lints table\n  [#13262](https://github.com/rust-lang/cargo/pull/13262)\n- rustfix: Support inserting new lines.\n  [#13226](https://github.com/rust-lang/cargo/pull/13226)\n\n### Nightly only\n\n- 🔥 `-Zgit`: Implementation of shallow libgit2 fetches behind an unstable flag\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#git)\n  [#13252](https://github.com/rust-lang/cargo/pull/13252)\n- 🔥 Add unstable `--output-format` option to  `cargo rustdoc`, providing tools\n  with a way to lean on rustdoc’s experimental JSON format.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#output-format-for-rustdoc)\n  [#12252](https://github.com/rust-lang/cargo/pull/12252)\n  [#13284](https://github.com/rust-lang/cargo/pull/13284)\n  [#13325](https://github.com/rust-lang/cargo/pull/13325)\n- `-Zcheck-cfg`: Rework `--check-cfg` generation comment\n  [#13195](https://github.com/rust-lang/cargo/pull/13195)\n- `-Zcheck-cfg`: Go back to passing an empty `values()` when no features are declared\n  [#13316](https://github.com/rust-lang/cargo/pull/13316)\n- `-Zprecise-pre-release`: the flag is added but not implemented yet.\n  [#13296](https://github.com/rust-lang/cargo/pull/13296)\n  [#13320](https://github.com/rust-lang/cargo/pull/13320)\n- `-Zpublic-dependency`: support publish package with a `public` field.\n  [#13245](https://github.com/rust-lang/cargo/pull/13245)\n- `-Zpublic-dependency`: help text of `--public`/`--no-public` flags for `cargo add`\n  [#13272](https://github.com/rust-lang/cargo/pull/13272)\n- `-Zscript`: Add prefix-char frontmatter syntax support\n  [#13247](https://github.com/rust-lang/cargo/pull/13247)\n- `-Zscript`: Add multiple experimental manifest syntaxes\n  [#13241](https://github.com/rust-lang/cargo/pull/13241)\n- `-Ztrim-paths`: remap common prefix only\n  [#13210](https://github.com/rust-lang/cargo/pull/13210)\n\n### Documentation\n\n- Added guidance on setting homepage in manifest\n  [#13293](https://github.com/rust-lang/cargo/pull/13293)\n- Clarified how custom subcommands are looked up.\n  [#13203](https://github.com/rust-lang/cargo/pull/13203)\n- Clarified why `du` function uses mutex\n  [#13273](https://github.com/rust-lang/cargo/pull/13273)\n- Highlighted \"How to find features enabled on dependencies\"\n  [#13305](https://github.com/rust-lang/cargo/pull/13305)\n- Delete sentence about parentheses being unsupported in license\n  [#13292](https://github.com/rust-lang/cargo/pull/13292)\n- resolver: clarify how pre-release version is handled in dependency resolution.\n  [#13286](https://github.com/rust-lang/cargo/pull/13286)\n- cargo-test: clarify the target selection of the test options.\n  [#13236](https://github.com/rust-lang/cargo/pull/13236)\n- cargo-install: clarify `--path` is the installation source not destination\n  [#13205](https://github.com/rust-lang/cargo/pull/13205)\n- contrib: Fix team HackMD links\n  [#13237](https://github.com/rust-lang/cargo/pull/13237)\n- contrib: Highlight the non-blocking feature gating technique\n  [#13307](https://github.com/rust-lang/cargo/pull/13307)\n\n### Internal\n\n- 🎉 New member crate [`cargo-util-schemas`](https://crates.io/crates/cargo-util-schemas)!\n  This contains low-level Cargo schema types, focusing on `serde` and `FromStr`\n  for use in reading files and parsing command-lines.\n  Any logic for getting final semantics from these will likely need other tools\n  to process, like `cargo metadata`.\n  The crates.io publish of this crate is the same as other members crates.\n  It follows Rust's [6-week release process](https://doc.crates.io/contrib/process/release.html#cratesio-publishing).\n  [#13178](https://github.com/rust-lang/cargo/pull/13178)\n  [#13185](https://github.com/rust-lang/cargo/pull/13185)\n  [#13186](https://github.com/rust-lang/cargo/pull/13186)\n  [#13209](https://github.com/rust-lang/cargo/pull/13209)\n  [#13267](https://github.com/rust-lang/cargo/pull/13267)\n- Updated to `gix` 0.57.1.\n  [#13230](https://github.com/rust-lang/cargo/pull/13230)\n- cargo-fix: Remove error-format special-case in `cargo fix`\n  [#13224](https://github.com/rust-lang/cargo/pull/13224)\n- cargo-credential: bump to 0.4.3\n  [#13221](https://github.com/rust-lang/cargo/pull/13221)\n- mdman: updated to `handlebars` 5.0.0.\n  [#13168](https://github.com/rust-lang/cargo/pull/13168)\n  [#13249](https://github.com/rust-lang/cargo/pull/13249)\n- rustfix: remove useless clippy rules and fix a typo\n  [#13182](https://github.com/rust-lang/cargo/pull/13182)\n- ci: fix Dependabot's MSRV auto-update\n  [#13265](https://github.com/rust-lang/cargo/pull/13265)\n  [#13324](https://github.com/rust-lang/cargo/pull/13324)\n  [#13268](https://github.com/rust-lang/cargo/pull/13268)\n- ci: Add [dependency dashboard](https://github.com/rust-lang/cargo/issues/13256).\n  [#13255](https://github.com/rust-lang/cargo/pull/13255)\n- ci: update alpine docker tag to v3.19\n  [#13228](https://github.com/rust-lang/cargo/pull/13228)\n- ci: Improve GitHub Actions CI config\n  [#13317](https://github.com/rust-lang/cargo/pull/13317)\n- resolver: do not panic when sorting empty summaries\n  [#13287](https://github.com/rust-lang/cargo/pull/13287)\n\n## Cargo 1.76 (2024-02-08)\n[6790a512...rust-1.76.0](https://github.com/rust-lang/cargo/compare/6790a512...rust-1.76.0)\n\n### Added\n\n- Added a Windows application manifest file to the built `cargo.exe` for windows msvc.\n  [#13131](https://github.com/rust-lang/cargo/pull/13131)  \n  Notable changes:\n  - States the compatibility with Windows versions 7, 8, 8.1, 10 and 11.\n  - Sets the code page to UTF-8.\n  - Enables long path awareness.\n- Added color output for `cargo --list`.\n  [#12992](https://github.com/rust-lang/cargo/pull/12992)\n- cargo-add: `--optional <dep>` would create a `<dep> = \"dep:<dep>\"` feature.\n  [#13071](https://github.com/rust-lang/cargo/pull/13071)\n- Extends Package ID spec for unambiguous specs.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/pkgid-spec.html)\n  [#12933](https://github.com/rust-lang/cargo/pull/12933)  \n  Specifically,\n  - Supports `git+` and `path+` schemes.\n  - Supports Git ref query strings, such as `?branch=dev` or `?tag=1.69.0`.\n\n### Changed\n\n- ❗️ Disallow `[lints]` in virtual workspaces as they are ignored  and users likely meant `[workspace.lints]`.\n  This was an oversight in the initial implementation (e.g. a `[dependencies]` produces the same error).\n  [#13155](https://github.com/rust-lang/cargo/pull/13155)\n- Disallow empty name in several places like package ID spec and `cargo new`.\n  [#13152](https://github.com/rust-lang/cargo/pull/13152)\n- Respect `rust-lang/rust`'s `omit-git-hash` option.\n  [#12968](https://github.com/rust-lang/cargo/pull/12968)\n- Displays error count with a number, even when there is only one error.\n  [#12484](https://github.com/rust-lang/cargo/pull/12484)\n- `all-static` feature now includes `vendored-libgit2`.\n  [#13134](https://github.com/rust-lang/cargo/pull/13134)\n- crates-io: Add support for other 2xx HTTP status codes when interacting with registries.\n  [#13158](https://github.com/rust-lang/cargo/pull/13158)\n  [#13160](https://github.com/rust-lang/cargo/pull/13160)\n- home: Replace SHGetFolderPathW with SHGetKnownFolderPath.\n  [#13173](https://github.com/rust-lang/cargo/pull/13173)\n\n### Fixed\n\n- Print rustc messages colored on wincon.\n  [#13140](https://github.com/rust-lang/cargo/pull/13140)\n- Fixed bash completion in directory with spaces.\n  [#13126](https://github.com/rust-lang/cargo/pull/13126)\n- Fixed uninstall a running binary failed on Windows.\n  [#13053](https://github.com/rust-lang/cargo/pull/13053)\n  [#13099](https://github.com/rust-lang/cargo/pull/13099)\n- Fixed the error message for duplicate links.\n  [#12973](https://github.com/rust-lang/cargo/pull/12973)\n- Fixed `--quiet` being used with nested subcommands.\n  [#12959](https://github.com/rust-lang/cargo/pull/12959)\n- Fixed panic when there is a cycle in dev-dependencies.\n  [#12977](https://github.com/rust-lang/cargo/pull/12977)\n- Don't panic when failed to parse rustc commit-hash.\n  [#12963](https://github.com/rust-lang/cargo/pull/12963)\n  [#12965](https://github.com/rust-lang/cargo/pull/12965)\n- Don't do git fetches when updating workspace members.\n  [#12975](https://github.com/rust-lang/cargo/pull/12975)\n- Avoid writing CACHEDIR.TAG if it already exists.\n  [#13132](https://github.com/rust-lang/cargo/pull/13132)\n- Accept `?` in the `--package` flag if it's a valid pkgid spec.\n  [#13315](https://github.com/rust-lang/cargo/pull/13315)\n  [#13318](https://github.com/rust-lang/cargo/pull/13318)\n- cargo-package: Only filter out `target` directory if it's in the package root.\n  [#12944](https://github.com/rust-lang/cargo/pull/12944)\n- cargo-package: errors out when a build script doesn't exist or is outside the package root.\n  [#12995](https://github.com/rust-lang/cargo/pull/12995)\n- cargo-credential-1password: Add missing `--account` argument to `op signin` command.\n  [#12985](https://github.com/rust-lang/cargo/pull/12985)\n  [#12986](https://github.com/rust-lang/cargo/pull/12986)\n\n\n### Nightly only\n\n- 🔥 The `-Zgc` flag enables garbage collection for deleting old, unused files\n  in cargo's cache. That is, downloaded source files and registry index under\n  the `CARGO_HOME` directory.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#gc)\n  [#12634](https://github.com/rust-lang/cargo/pull/12634)\n  [#12958](https://github.com/rust-lang/cargo/pull/12958)\n  [#12981](https://github.com/rust-lang/cargo/pull/12981)\n  [#13055](https://github.com/rust-lang/cargo/pull/13055)\n- 🔥 Added a new environment variable `CARGO_RUSTC_CURRENT_DIR`.\n  This is a path that rustc is invoked from.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/environment-variables.html?highlight=CARGO_RUSTC_CURRENT_DIR#environment-variables-cargo-sets-for-crates)\n  [#12996](https://github.com/rust-lang/cargo/pull/12996)\n- `-Zcheck-cfg`: Include declared list of features in fingerprint for `-Zcheck-cfg`.\n  [#13012](https://github.com/rust-lang/cargo/pull/13012)\n- `-Zcheck-cfg`: Fix `--check-cfg` invocations with zero features.\n  [#13011](https://github.com/rust-lang/cargo/pull/13011)\n- `-Ztrim-paths`: reorder `--remap-path-prefix` flags for `-Zbuild-std`.\n  [#13065](https://github.com/rust-lang/cargo/pull/13065)\n- `-Ztrim-paths`: explicitly remap current dir by using `.`.\n  [#13114](https://github.com/rust-lang/cargo/pull/13114)\n- `-Ztrim-paths`: exercise with real world debugger.\n  [#13091](https://github.com/rust-lang/cargo/pull/13091)\n  [#13118](https://github.com/rust-lang/cargo/pull/13118)\n- `-Zpublic-dependency`: Limit `exported-private-dependencies` lints to libraries.\n  [#13135](https://github.com/rust-lang/cargo/pull/13135)\n- `-Zpublic-dependency`: Disallow workspace-inheriting of dependency public status.\n  [#13125](https://github.com/rust-lang/cargo/pull/13125)\n- `-Zpublic-dependency`: Add `--public` for `cargo add`.\n  [#13046](https://github.com/rust-lang/cargo/pull/13046)\n- `-Zpublic-dependency`: Remove unused public-deps error handling \n  [#13036](https://github.com/rust-lang/cargo/pull/13036)\n- `-Zmsrv-policy`: Prefer MSRV, rather than ignore incompatible.\n  [#12950](https://github.com/rust-lang/cargo/pull/12950)\n- `-Zmsrv-policy`: De-prioritize no-rust-version in MSRV resolver.\n  [#13066](https://github.com/rust-lang/cargo/pull/13066)\n- `-Zrustdoc-scrape-examples`: Don't filter on workspace members when scraping doc examples.\n  [#13077](https://github.com/rust-lang/cargo/pull/13077)\n\n### Documentation\n\n- Recommends a wider selection of libsecret-compatible password managers.\n  [#12993](https://github.com/rust-lang/cargo/pull/12993)\n- Clarified different targets has different sets of `CARGO_CFG_*` values.\n  [#13069](https://github.com/rust-lang/cargo/pull/13069)\n- Clarified `[lints]` table only affects local development of the current package.\n  [#12976](https://github.com/rust-lang/cargo/pull/12976)\n- Clarified `cargo search` can search in alternative registries.\n  [#12962](https://github.com/rust-lang/cargo/pull/12962)\n- Added common CI practices for verifying `rust-version` (MSRV) field.\n  [#13056](https://github.com/rust-lang/cargo/pull/13056)\n- Added a link to rustc lint levels doc.\n  [#12990](https://github.com/rust-lang/cargo/pull/12990)\n- Added a link to the packages lint table from the related workspace table \n  [#13057](https://github.com/rust-lang/cargo/pull/13057)\n- contrib: Add more resources to the contrib docs.\n  [#13008](https://github.com/rust-lang/cargo/pull/13008)\n- contrib: Update how that credential crates are published. \n  [#13006](https://github.com/rust-lang/cargo/pull/13006)\n- contrib: remove review capacity notice.\n  [#13070](https://github.com/rust-lang/cargo/pull/13070)\n\n### Internal\n\n- 🎉 Migrate `rustfix` crate to the `rust-lang/cargo` repository.\n  [#13005](https://github.com/rust-lang/cargo/pull/13005)\n  [#13042](https://github.com/rust-lang/cargo/pull/13042)\n  [#13047](https://github.com/rust-lang/cargo/pull/13047)\n  [#13048](https://github.com/rust-lang/cargo/pull/13048)\n  [#13050](https://github.com/rust-lang/cargo/pull/13050)\n- Updated to `curl-sys` 0.4.70, which corresponds to curl 8.4.0.\n  [#13147](https://github.com/rust-lang/cargo/pull/13147)\n- Updated to `gix-index` 0.27.1.\n  [#13148](https://github.com/rust-lang/cargo/pull/13148)\n- Updated to `itertools` 0.12.0.\n  [#13086](https://github.com/rust-lang/cargo/pull/13086)\n- Updated to `rusqlite` 0.30.0.\n  [#13087](https://github.com/rust-lang/cargo/pull/13087)\n- Updated to `toml_edit` 0.21.0.\n  [#13088](https://github.com/rust-lang/cargo/pull/13088)\n- Updated to `windows-sys` 0.52.0.\n  [#13089](https://github.com/rust-lang/cargo/pull/13089)\n- Updated to `tracing` 0.1.37 for being be compatible with rustc_log.\n  [#13239](https://github.com/rust-lang/cargo/pull/13239)\n  [#13242](https://github.com/rust-lang/cargo/pull/13242)\n- Re-enable flaky gitoxide auth tests thanks to update to `gix-config`.\n  [#13117](https://github.com/rust-lang/cargo/pull/13117)\n  [#13129](https://github.com/rust-lang/cargo/pull/13129)\n  [#13130](https://github.com/rust-lang/cargo/pull/13130)\n- Dogfood Cargo `-Zlints` table feature.\n  [#12178](https://github.com/rust-lang/cargo/pull/12178)\n- Refactored `Cargo.toml` parsing code in preparation of extracting an official\n  schema API.\n  [#12954](https://github.com/rust-lang/cargo/pull/12954)\n  [#12960](https://github.com/rust-lang/cargo/pull/12960)\n  [#12961](https://github.com/rust-lang/cargo/pull/12961)\n  [#12971](https://github.com/rust-lang/cargo/pull/12971)\n  [#13000](https://github.com/rust-lang/cargo/pull/13000)\n  [#13021](https://github.com/rust-lang/cargo/pull/13021)\n  [#13080](https://github.com/rust-lang/cargo/pull/13080)\n  [#13097](https://github.com/rust-lang/cargo/pull/13097)\n  [#13123](https://github.com/rust-lang/cargo/pull/13123)\n  [#13128](https://github.com/rust-lang/cargo/pull/13128)\n  [#13154](https://github.com/rust-lang/cargo/pull/13154)\n  [#13166](https://github.com/rust-lang/cargo/pull/13166)\n- Use `IndexSummary` in `query{_vec}` functions.\n  [#12970](https://github.com/rust-lang/cargo/pull/12970)\n- ci: migrate renovate config \n  [#13106](https://github.com/rust-lang/cargo/pull/13106)\n- ci: Always update gix packages together \n  [#13093](https://github.com/rust-lang/cargo/pull/13093)\n- ci: Catch naive use of AtomicU64 early \n  [#12988](https://github.com/rust-lang/cargo/pull/12988)\n- xtask-bump-check: dont check `home` against beta/stable branches \n  [#13167](https://github.com/rust-lang/cargo/pull/13167)\n- cargo-test-support: Handle $message_type in JSON diagnostics \n  [#13016](https://github.com/rust-lang/cargo/pull/13016)\n- cargo-test-support: Add more options to registry test support. \n  [#13085](https://github.com/rust-lang/cargo/pull/13085)\n- cargo-test-support: Add features to the default Cargo.toml file \n  [#12997](https://github.com/rust-lang/cargo/pull/12997)\n- cargo-test-support: Fix clippy-wrapper test race condition. \n  [#12999](https://github.com/rust-lang/cargo/pull/12999)\n- test: Don't rely on mtime to test changes \n  [#13143](https://github.com/rust-lang/cargo/pull/13143)\n- test: remove unnecessary packages and versions for `optionals` tests \n  [#13108](https://github.com/rust-lang/cargo/pull/13108)\n- test: Remove the deleted feature `test_2018_feature` from the test.\n  [#13156](https://github.com/rust-lang/cargo/pull/13156)\n- test: remove jobserver env var in some tests.\n  [#13072](https://github.com/rust-lang/cargo/pull/13072)\n- test: Fix a rustflags test using a wrong buildfile name \n  [#12987](https://github.com/rust-lang/cargo/pull/12987)\n- test: Fix some test output validation. \n  [#12982](https://github.com/rust-lang/cargo/pull/12982)\n- test: Ignore changing_spec_relearns_crate_types on windows-gnu \n  [#12972](https://github.com/rust-lang/cargo/pull/12972)\n\n## Cargo 1.75 (2023-12-28)\n[59596f0f...rust-1.75.0](https://github.com/rust-lang/cargo/compare/59596f0f...rust-1.75.0)\n\n### Added\n\n- `package.version` field in `Cargo.toml` is now optional and defaults to `0.0.0`.\n  Packages without the `package.version` field cannot be published.\n  [#12786](https://github.com/rust-lang/cargo/pull/12786)\n- Links in `--timings` and `cargo doc` outputs are clickable on supported terminals,\n  controllable through `term.hyperlinks` config value.\n  [#12889](https://github.com/rust-lang/cargo/pull/12889)\n- Print environment variables for build script executions with `-vv`.\n  [#12829](https://github.com/rust-lang/cargo/pull/12829)\n- cargo-new: add new packages to [workspace.members] automatically.\n  [#12779](https://github.com/rust-lang/cargo/pull/12779)\n- cargo-doc: print a new `Generated` status displaying the full path.\n  [#12859](https://github.com/rust-lang/cargo/pull/12859)\n\n### Changed\n\n- cargo-new: warn if crate name doesn't follow snake_case or kebab-case.\n  [#12766](https://github.com/rust-lang/cargo/pull/12766)\n- cargo-install: clarify the arg `<crate>` to install is positional.\n  [#12841](https://github.com/rust-lang/cargo/pull/12841)\n- cargo-install: Suggest an alternative version on MSRV failure.\n  [#12798](https://github.com/rust-lang/cargo/pull/12798)\n- cargo-install: reports more detailed SemVer errors.\n  [#12924](https://github.com/rust-lang/cargo/pull/12924)\n- cargo-install: install only once if there are crates duplicated.\n  [#12868](https://github.com/rust-lang/cargo/pull/12868)\n- cargo-remove: Clarify flag behavior of different dependency kinds.\n  [#12823](https://github.com/rust-lang/cargo/pull/12823)\n- cargo-remove: suggest the dependency to remove exists only in the other section.\n  [#12865](https://github.com/rust-lang/cargo/pull/12865)\n- cargo-update: Do not call it \"Downgrading\" when difference is only build metadata.\n  [#12796](https://github.com/rust-lang/cargo/pull/12796)\n- Enhanced help text to clarify `--test` flag is for Cargo targets, not test functions.\n  [#12915](https://github.com/rust-lang/cargo/pull/12915)\n- Included package name/version in build script warnings.\n  [#12799](https://github.com/rust-lang/cargo/pull/12799)\n- Provide next steps for bad -Z flag.\n  [#12857](https://github.com/rust-lang/cargo/pull/12857)\n- Suggest `cargo search` when `cargo-<command>` cannot be found.\n  [#12840](https://github.com/rust-lang/cargo/pull/12840)\n- Do not allow empty feature name.\n  [#12928](https://github.com/rust-lang/cargo/pull/12928)\n- Added unsupported short flag suggestion for `--target` and `--exclude` flags.\n  [#12805](https://github.com/rust-lang/cargo/pull/12805)\n- Added unsupported short flag suggestion for `--out-dir` flag.\n  [#12755](https://github.com/rust-lang/cargo/pull/12755)\n- Added unsupported lowercase `-z` flag suggestion for `-Z` flag.\n  [#12788](https://github.com/rust-lang/cargo/pull/12788)\n- Added better suggestion for unsupported `--path` flag.\n  [#12811](https://github.com/rust-lang/cargo/pull/12811)\n- Added detailed message when target directory path is invalid.\n  [#12820](https://github.com/rust-lang/cargo/pull/12820)\n\n### Fixed\n\n- Fixed corruption when cargo was killed while writing to files.\n  [#12744](https://github.com/rust-lang/cargo/pull/12744)\n- cargo-add: Preserve more comments \n  [#12838](https://github.com/rust-lang/cargo/pull/12838)\n- cargo-fix: preserve jobserver file descriptors on rustc invocation.\n  [#12951](https://github.com/rust-lang/cargo/pull/12951)\n- cargo-remove: Preserve feature comments \n  [#12837](https://github.com/rust-lang/cargo/pull/12837)\n- Removed unnecessary backslash in timings HTML report when error happens.\n  [#12934](https://github.com/rust-lang/cargo/pull/12934)\n- Fixed error message that invalid a feature name can contain `-`.\n  [#12939](https://github.com/rust-lang/cargo/pull/12939)\n- When there's a version of a dependency in the lockfile,\n  Cargo would use that \"exact\" version, including the build metadata.\n  [#12772](https://github.com/rust-lang/cargo/pull/12772)\n\n### Nightly only\n\n- Added `Edition2024` unstable feature.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#edition-2024)\n  [#12771](https://github.com/rust-lang/cargo/pull/12771)\n- 🔥 The `-Ztrim-paths` feature adds a new profile setting to control how paths\n  are sanitized in the resulting binary.\n  ([RFC 3127](https://github.com/rust-lang/rfcs/blob/master/text/3127-trim-paths.md))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-trim-paths-option))\n  [#12625](https://github.com/rust-lang/cargo/pull/12625)\n  [#12900](https://github.com/rust-lang/cargo/pull/12900)\n  [#12908](https://github.com/rust-lang/cargo/pull/12908)\n- `-Zcheck-cfg`: Adjusted for new rustc syntax and behavior.\n  [#12845](https://github.com/rust-lang/cargo/pull/12845)\n- `-Zcheck-cfg`: Remove outdated option to `-Zcheck-cfg` warnings.\n  [#12884](https://github.com/rust-lang/cargo/pull/12884)\n- `public-dependency`: Support `public` dependency configuration with workspace deps.\n  [#12817](https://github.com/rust-lang/cargo/pull/12817)\n\n### Documentation\n\n- profile: add missing `strip` info.\n  [#12754](https://github.com/rust-lang/cargo/pull/12754)\n- features: a note about the new limit on number of features.\n  [#12913](https://github.com/rust-lang/cargo/pull/12913)\n- crates-io: Add doc comment for `NewCrate` struct.\n  [#12782](https://github.com/rust-lang/cargo/pull/12782)\n- resolver: Highlight commands to answer dep resolution questions.\n  [#12903](https://github.com/rust-lang/cargo/pull/12903)\n- cargo-bench: `--bench` is passed in unconditionally to bench harnesses.\n  [#12850](https://github.com/rust-lang/cargo/pull/12850)\n- cargo-login: mention args after `--` in manpage.\n  [#12832](https://github.com/rust-lang/cargo/pull/12832)\n- cargo-vendor: clarify config to use vendored source is printed to stdout \n  [#12893](https://github.com/rust-lang/cargo/pull/12893)\n- manifest: update to SPDX 2.3 license expression and 3.20 license list.\n  [#12827](https://github.com/rust-lang/cargo/pull/12827)\n- contrib: Policy on manifest editing \n  [#12836](https://github.com/rust-lang/cargo/pull/12836)\n- contrib: use `AND` search terms in mdbook search and fixed broken links.\n  [#12812](https://github.com/rust-lang/cargo/pull/12812)\n  [#12813](https://github.com/rust-lang/cargo/pull/12813)\n  [#12814](https://github.com/rust-lang/cargo/pull/12814)\n- contrib: Describe how to add a new package \n  [#12878](https://github.com/rust-lang/cargo/pull/12878)\n- contrib: Removed review capacity notice.\n  [#12842](https://github.com/rust-lang/cargo/pull/12842)\n\n### Internal\n\n- Updated to `itertools` 0.11.0.\n  [#12759](https://github.com/rust-lang/cargo/pull/12759)\n- Updated to `cargo_metadata` 0.18.0.\n  [#12758](https://github.com/rust-lang/cargo/pull/12758)\n- Updated to `curl-sys` 0.4.68, which corresponds to curl 8.4.0.\n  [#12808](https://github.com/rust-lang/cargo/pull/12808)\n- Updated to `toml` 0.8.2.\n  [#12760](https://github.com/rust-lang/cargo/pull/12760)\n- Updated to `toml_edit` 0.20.2.\n  [#12761](https://github.com/rust-lang/cargo/pull/12761)\n- Updated to `gix` to 0.55.2 \n  [#12906](https://github.com/rust-lang/cargo/pull/12906)\n- Disabled the `custom_target::custom_bin_target` test on windows-gnu.\n  [#12763](https://github.com/rust-lang/cargo/pull/12763)\n- Refactored `Cargo.toml` parsing code in preparation of extracting an official\n  schema API.\n  [#12768](https://github.com/rust-lang/cargo/pull/12768)\n  [#12881](https://github.com/rust-lang/cargo/pull/12881)\n  [#12902](https://github.com/rust-lang/cargo/pull/12902)\n  [#12911](https://github.com/rust-lang/cargo/pull/12911)\n  [#12948](https://github.com/rust-lang/cargo/pull/12948)\n- Split out SemVer logic to its own module.\n  [#12926](https://github.com/rust-lang/cargo/pull/12926)\n  [#12940](https://github.com/rust-lang/cargo/pull/12940)\n- source: Prepare for new `PackageIDSpec` syntax\n  [#12938](https://github.com/rust-lang/cargo/pull/12938)\n- resolver: Consolidate logic in `VersionPreferences` \n  [#12930](https://github.com/rust-lang/cargo/pull/12930)\n- Make the `SourceId::precise` field an Enum.\n  [#12849](https://github.com/rust-lang/cargo/pull/12849)\n- shell: Write at once rather than in fragments.\n  [#12880](https://github.com/rust-lang/cargo/pull/12880)\n- Move up looking at index summary enum \n  [#12749](https://github.com/rust-lang/cargo/pull/12749)\n  [#12923](https://github.com/rust-lang/cargo/pull/12923)\n- Generate redirection HTML pages in CI for Cargo Contributor Guide.\n  [#12846](https://github.com/rust-lang/cargo/pull/12846)\n- Add new package cache lock modes.\n  [#12706](https://github.com/rust-lang/cargo/pull/12706)\n- Add regression test for issue 6915: features and transitive dev deps.\n  [#12907](https://github.com/rust-lang/cargo/pull/12907)\n- Auto-labeling when PR review state changes.\n  [#12856](https://github.com/rust-lang/cargo/pull/12856)\n- credential: include license files in all published crates.\n  [#12953](https://github.com/rust-lang/cargo/pull/12953)\n- credential: Filter `cargo-credential-*` dependencies by OS.\n  [#12949](https://github.com/rust-lang/cargo/pull/12949)\n- ci: bump cargo-semver-checks to 0.24.0\n  [#12795](https://github.com/rust-lang/cargo/pull/12795)\n- ci: set and verify all MSRVs for Cargo's crates automatically.\n  [#12767](https://github.com/rust-lang/cargo/pull/12767)\n  [#12654](https://github.com/rust-lang/cargo/pull/12654)\n- ci: use separate concurrency group for publishing Cargo Contributor Book.\n  [#12834](https://github.com/rust-lang/cargo/pull/12834)\n  [#12835](https://github.com/rust-lang/cargo/pull/12835)\n- ci: update `actions/checkout` action to v4\n  [#12762](https://github.com/rust-lang/cargo/pull/12762)\n- cargo-search: improved the margin calculation for the output.\n  [#12890](https://github.com/rust-lang/cargo/pull/12890)\n\n## Cargo 1.74 (2023-11-16)\n[80eca0e5...rust-1.74.0](https://github.com/rust-lang/cargo/compare/80eca0e5...rust-1.74.0)\n\n### Added\n\n- 🎉 The `[lints]` table has been stabilized, allowing you to configure reporting levels for rustc and other tool lints in `Cargo.toml`.\n  ([RFC 3389](https://github.com/rust-lang/rfcs/blob/master/text/3389-manifest-lint.md))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/manifest.html#the-lints-section))\n  [#12584](https://github.com/rust-lang/cargo/pull/12584)\n  [#12648](https://github.com/rust-lang/cargo/pull/12648)\n- 🎉 The unstable features `credential-process` and `registry-auth` have been stabilized.\n  These features consolidate the way to authenticate with private registries.\n  ([RFC 2730](https://github.com/rust-lang/rfcs/blob/master/text/2730-cargo-token-from-process.md))\n  ([RFC 3139](https://github.com/rust-lang/rfcs/blob/master/text/3139-cargo-alternative-registry-auth.md))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/registry-authentication.html))\n  [#12590](https://github.com/rust-lang/cargo/pull/12590)\n  [#12622](https://github.com/rust-lang/cargo/pull/12622)\n  [#12623](https://github.com/rust-lang/cargo/pull/12623)\n  [#12626](https://github.com/rust-lang/cargo/pull/12626)\n  [#12641](https://github.com/rust-lang/cargo/pull/12641)\n  [#12644](https://github.com/rust-lang/cargo/pull/12644)\n  [#12649](https://github.com/rust-lang/cargo/pull/12649)\n  [#12671](https://github.com/rust-lang/cargo/pull/12671)\n  [#12709](https://github.com/rust-lang/cargo/pull/12709)  \n  Notable changes:\n  - Introducing a new protocol for both external and built-in providers to store and retrieve credentials for registry authentication.\n  - Adding the `auth-required` field in the registry index's `config.json`, enabling authenticated sparse index, crate downloads, and search API.\n  - For using alternative registries with authentication, a credential provider must be configured to avoid unknowingly storing unencrypted credentials on disk. \n  - These settings can be configured in `[registry]` and `[registries]` tables.\n- 🎉 `--keep-going` flag has been stabilized and is now available in each build command\n  (except `bench` and `test`, which have `--no-fail-fast` instead).\n  ([docs](commands/cargo-build.md#option-cargo-build---keep-going))\n  [#12568](https://github.com/rust-lang/cargo/pull/12568)\n- Added `--dry-run` flag and summary line at the end for `cargo clean`.\n  [#12638](https://github.com/rust-lang/cargo/pull/12638)\n- Added a short alias `-n` for cli option `--dry-run`. \n  [#12660](https://github.com/rust-lang/cargo/pull/12660)\n- Added support for `target.'cfg(..)'.linker`.\n  [#12535](https://github.com/rust-lang/cargo/pull/12535)\n- Allowed incomplete versions when they are unambiguous for flags like `--package`.\n  [#12591](https://github.com/rust-lang/cargo/pull/12591)\n  [#12614](https://github.com/rust-lang/cargo/pull/12614)\n  [#12806](https://github.com/rust-lang/cargo/pull/12806)\n\n### Changed\n\n- ❗️ Changed how arrays in configuration are merged.\n  The order was unspecified and now follows how other configuration types work for consistency.\n  [summary](https://blog.rust-lang.org/inside-rust/2023/08/24/cargo-config-merging.html)\n  [#12515](https://github.com/rust-lang/cargo/pull/12515)\n- ❗️ cargo-clean: error out if `--doc` is mixed with `-p`.\n  [#12637](https://github.com/rust-lang/cargo/pull/12637)\n- ❗ cargo-new / cargo-init no longer exclude `Cargo.lock` in VCS ignore files for libraries.\n  [#12382](https://github.com/rust-lang/cargo/pull/12382)\n- cargo-update: silently deprecate `--aggressive` in favor of the new `--recursive`.\n  [#12544](https://github.com/rust-lang/cargo/pull/12544)\n- cargo-update: `-p/--package` can be used as a positional argument.\n  [#12545](https://github.com/rust-lang/cargo/pull/12545)\n  [#12586](https://github.com/rust-lang/cargo/pull/12586)\n- cargo-install: suggest `--git` when the package name looks like a URL.\n  [#12575](https://github.com/rust-lang/cargo/pull/12575)\n- cargo-add: summarize the feature list when it's too long.\n  [#12662](https://github.com/rust-lang/cargo/pull/12662)\n  [#12702](https://github.com/rust-lang/cargo/pull/12702)\n- Shell completion for `--target` uses rustup but falls back to rustc.\n  [#12606](https://github.com/rust-lang/cargo/pull/12606)\n- Help users know possible `--target` values.\n  [#12607](https://github.com/rust-lang/cargo/pull/12607)\n- Enhanced \"registry index not found\" error message.\n  [#12732](https://github.com/rust-lang/cargo/pull/12732)\n- Enhanced CLI help message of `--explain`. \n  [#12592](https://github.com/rust-lang/cargo/pull/12592)\n- Enhanced deserialization errors of untagged enums with `serde-untagged`.\n  [#12574](https://github.com/rust-lang/cargo/pull/12574)\n  [#12581](https://github.com/rust-lang/cargo/pull/12581)\n- Enhanced the error when mismatching prerelease version candidates.\n  [#12659](https://github.com/rust-lang/cargo/pull/12659)\n- Enhanced the suggestion on ambiguous Package ID spec.\n  [#12685](https://github.com/rust-lang/cargo/pull/12685)\n- Enhanced TOML parse errors to show the context.\n  [#12556](https://github.com/rust-lang/cargo/pull/12556)\n- Enhanced filesystem error by adding wrappers around `std::fs::metadata`.\n  [#12636](https://github.com/rust-lang/cargo/pull/12636)\n- Enhanced resolver version mismatch warning.\n  [#12573](https://github.com/rust-lang/cargo/pull/12573)\n- Use clap to suggest alternative argument for unsupported arguments.\n  [#12529](https://github.com/rust-lang/cargo/pull/12529)\n  [#12693](https://github.com/rust-lang/cargo/pull/12693)\n  [#12723](https://github.com/rust-lang/cargo/pull/12723)\n- Removed redundant information from cargo new/init `--help` output.\n  [#12594](https://github.com/rust-lang/cargo/pull/12594)\n- Console output and styling tweaks.\n  [#12578](https://github.com/rust-lang/cargo/pull/12578)\n  [#12655](https://github.com/rust-lang/cargo/pull/12655)\n  [#12593](https://github.com/rust-lang/cargo/pull/12593)\n\n### Fixed\n\n- Use full target spec for `cargo rustc --print --target`.\n  [#12743](https://github.com/rust-lang/cargo/pull/12743)\n- Copy PDBs also for EFI targets.\n  [#12688](https://github.com/rust-lang/cargo/pull/12688)\n- Fixed resolver behavior being independent of package order.\n  [#12602](https://github.com/rust-lang/cargo/pull/12602)\n- Fixed unnecessary clean up of `profile.release.package.\"*\"` for `cargo remove`.\n  [#12624](https://github.com/rust-lang/cargo/pull/12624)\n\n### Nightly only\n\n- `-Zasymmetric-token`: Created dedicated unstable flag for asymmetric-token support.\n  [#12551](https://github.com/rust-lang/cargo/pull/12551)\n- `-Zasymmetric-token`: Improved logout message for asymmetric tokens.\n  [#12587](https://github.com/rust-lang/cargo/pull/12587)\n- `-Zmsrv-policy`: **Very** preliminary MSRV resolver support.\n  [#12560](https://github.com/rust-lang/cargo/pull/12560)\n- `-Zscript`: Hack in code fence support.\n  [#12681](https://github.com/rust-lang/cargo/pull/12681)\n- `-Zbindeps`: Support dependencies from registries.\n  [#12421](https://github.com/rust-lang/cargo/pull/12421)\n\n### Documentation\n\n- ❗ Policy change: Checking `Cargo.lock` into version control is now the default choice,\n  even for libraries. Lockfile and CI integration documentations are also expanded.\n  [Policy docs](https://doc.rust-lang.org/nightly/cargo/faq.html#why-have-cargolock-in-version-control),\n  [Lockfile docs](https://doc.rust-lang.org/nightly/cargo/guide/cargo-toml-vs-cargo-lock.html),\n  [CI docs](https://doc.rust-lang.org/nightly/cargo/guide/continuous-integration.html),\n  [#12382](https://github.com/rust-lang/cargo/pull/12382)\n  [#12630](https://github.com/rust-lang/cargo/pull/12630)\n- SemVer: Update documentation about removing optional dependencies.\n  [#12687](https://github.com/rust-lang/cargo/pull/12687)\n- Contrib: Add process for security responses.\n  [#12487](https://github.com/rust-lang/cargo/pull/12487)\n- cargo-publish: warn about upload timeout.\n  [#12733](https://github.com/rust-lang/cargo/pull/12733)\n- mdbook: use *AND* search when having multiple terms.\n  [#12548](https://github.com/rust-lang/cargo/pull/12548)\n- Established publish best practices \n  [#12745](https://github.com/rust-lang/cargo/pull/12745)\n- Clarify caret requirements.\n  [#12679](https://github.com/rust-lang/cargo/pull/12679)\n- Clarify how `version` works for `git` dependencies.\n  [#12270](https://github.com/rust-lang/cargo/pull/12270)\n- Clarify and differentiate defaults for split-debuginfo.\n  [#12680](https://github.com/rust-lang/cargo/pull/12680)\n- Added missing `strip` entries in `dev` and `release` profiles.\n  [#12748](https://github.com/rust-lang/cargo/pull/12748)\n\n### Internal\n\n- Updated to `curl-sys` 0.4.66, which corresponds to curl 8.3.0.\n  [#12718](https://github.com/rust-lang/cargo/pull/12718)\n- Updated to `gitoxide` 0.54.1.\n  [#12731](https://github.com/rust-lang/cargo/pull/12731)\n- Updated to `git2` 0.18.0, which corresponds to libgit2 1.7.1.\n  [#12580](https://github.com/rust-lang/cargo/pull/12580)\n- Updated to `cargo_metadata` 0.17.0.\n  [#12758](https://github.com/rust-lang/cargo/pull/12610)\n- Updated target-arch-aware crates to support mips r6 targets \n  [#12720](https://github.com/rust-lang/cargo/pull/12720)\n- publish.py: Remove obsolete `sleep()` calls.\n  [#12686](https://github.com/rust-lang/cargo/pull/12686)\n- Define `{{command}}` for use in src/doc/man/includes \n  [#12570](https://github.com/rust-lang/cargo/pull/12570)\n- Set tracing target `network` for networking messages.\n  [#12582](https://github.com/rust-lang/cargo/pull/12582)\n- cargo-test-support: Add `with_stdout_unordered`.\n  [#12635](https://github.com/rust-lang/cargo/pull/12635)\n- dep: Switch from `termcolor` to `anstream`.\n  [#12751](https://github.com/rust-lang/cargo/pull/12751)\n- Put `Source` trait under `cargo::sources`.\n  [#12527](https://github.com/rust-lang/cargo/pull/12527)\n- SourceId: merge `name` and `alt_registry_key` into one enum.\n  [#12675](https://github.com/rust-lang/cargo/pull/12675)\n- TomlManifest: fail when package_root is not a directory.\n  [#12722](https://github.com/rust-lang/cargo/pull/12722)\n- util: enhanced doc of `network::retry` doc.\n  [#12583](https://github.com/rust-lang/cargo/pull/12583)\n- refactor: Pull out cargo-add MSRV code for reuse \n  [#12553](https://github.com/rust-lang/cargo/pull/12553)\n- refactor(install): Move value parsing to clap \n  [#12547](https://github.com/rust-lang/cargo/pull/12547)\n- Fixed spurious errors with networking tests. \n  [#12726](https://github.com/rust-lang/cargo/pull/12726)\n- Use a more compact relative-time format for `CARGO_LOG` internal logging.\n  [#12542](https://github.com/rust-lang/cargo/pull/12542)\n- Use newer std API for cleaner code.\n  [#12559](https://github.com/rust-lang/cargo/pull/12559)\n  [#12604](https://github.com/rust-lang/cargo/pull/12604)\n  [#12615](https://github.com/rust-lang/cargo/pull/12615)\n  [#12631](https://github.com/rust-lang/cargo/pull/12631)\n- Buffer console status messages. \n  [#12727](https://github.com/rust-lang/cargo/pull/12727)\n- Use enum to describe index summaries to provide a richer information when summaries are not available for resolution.\n  [#12643](https://github.com/rust-lang/cargo/pull/12643)\n- Use shortest path for resolving the path from the given dependency up to the root.\n  [#12678](https://github.com/rust-lang/cargo/pull/12678)\n- Read/write the encoded `cargo update --precise` in the same place \n  [#12629](https://github.com/rust-lang/cargo/pull/12629)\n- Set MSRV for internal packages.\n  [#12381](https://github.com/rust-lang/cargo/pull/12381)\n- ci: Update Renovate schema \n  [#12741](https://github.com/rust-lang/cargo/pull/12741)\n- ci: Ignore patch version in MSRV \n  [#12716](https://github.com/rust-lang/cargo/pull/12716)\n\n## Cargo 1.73 (2023-10-05)\n[45782b6b...rust-1.73.0](https://github.com/rust-lang/cargo/compare/45782b6b...rust-1.73.0)\n\n### Added\n\n- Print environment variables for `cargo run/bench/test` in extra verbose mode `-vv`.\n  [#12498](https://github.com/rust-lang/cargo/pull/12498)\n- Display package versions on Cargo timings graph.\n  [#12420](https://github.com/rust-lang/cargo/pull/12420)\n\n### Changed\n\n- ❗️ Cargo now bails out when using `cargo::` in custom build scripts. This is\n  a preparation for an upcoming change in build script invocations.\n  [#12332](https://github.com/rust-lang/cargo/pull/12332)\n- ❗️ `cargo login` no longer accept any token after the `--` syntax.\n  Arguments after `--` are now reserved in the preparation of the new credential provider feature.\n  This introduces a regression that overlooks the `cargo login -- <token>` support in previous versions.\n  [#12499](https://github.com/rust-lang/cargo/pull/12499)\n- Make Cargo `--help` easier to browse.\n  [#11905](https://github.com/rust-lang/cargo/pull/11905)\n- Prompt the use of `--nocapture` flag if `cargo test` process is terminated via a signal.\n  [#12463](https://github.com/rust-lang/cargo/pull/12463)\n- Preserve jobserver file descriptors on the rustc invocation for getting target information.\n  [#12447](https://github.com/rust-lang/cargo/pull/12447)\n- Clarify in `--help` that `cargo test --all-targets` excludes doctests.\n  [#12422](https://github.com/rust-lang/cargo/pull/12422)\n- Normalize `cargo.toml` to `Cargo.toml` on publish, and warn on other cases of `Cargo.toml`.\n  [#12399](https://github.com/rust-lang/cargo/pull/12399)\n\n### Fixed\n\n- Only skip mtime check on `~/.cargo/{git,registry}`.\n  [#12369](https://github.com/rust-lang/cargo/pull/12369)\n- Fixed `cargo doc --open` crash on WSL2.\n  [#12373](https://github.com/rust-lang/cargo/pull/12373)\n- Fixed panic when enabling `http.debug` for certain strings.\n  [#12468](https://github.com/rust-lang/cargo/pull/12468)\n- Fixed `cargo remove` incorrectly removing used patches.\n  [#12454](https://github.com/rust-lang/cargo/pull/12454)\n- Fixed crate checksum lookup query should match on semver build metadata.\n  [#11447](https://github.com/rust-lang/cargo/pull/11447)\n- Fixed printing multiple warning messages for unused fields in `[registries]` table.\n  [#12439](https://github.com/rust-lang/cargo/pull/12439)\n\n### Nightly only\n\n- 🔥 The `-Zcredential-process` has been reimplemented with a clearer way to\n  communicate  with different credential providers. Several built-in providers\n  are also added to Cargo.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#credential-process)\n  [#12334](https://github.com/rust-lang/cargo/pull/12334)\n  [#12396](https://github.com/rust-lang/cargo/pull/12396)\n  [#12424](https://github.com/rust-lang/cargo/pull/12424)\n  [#12440](https://github.com/rust-lang/cargo/pull/12440)\n  [#12461](https://github.com/rust-lang/cargo/pull/12461)\n  [#12469](https://github.com/rust-lang/cargo/pull/12469)\n  [#12483](https://github.com/rust-lang/cargo/pull/12483)\n  [#12499](https://github.com/rust-lang/cargo/pull/12499)\n  [#12507](https://github.com/rust-lang/cargo/pull/12507)\n  [#12512](https://github.com/rust-lang/cargo/pull/12512)\n  [#12518](https://github.com/rust-lang/cargo/pull/12518)\n  [#12521](https://github.com/rust-lang/cargo/pull/12521)\n  [#12526](https://github.com/rust-lang/cargo/pull/12526)  \n  Some notable changes:\n  - Renamed `credential-process` to `credential-provider` in Cargo configurations.\n  - New JSON protocol for communicating with external credential providers via stdin/stdout.\n  - The GNOME Secret provider now dynamically loads `libsecert`.\n  - The 1password provider is no longer built-in.\n  - Changed the unstable key for asymmetric tokens from `registry-auth` to `credential-process`.\n- ❗️ Removed `--keep-going` flag support from `cargo test` and `cargo bench`.\n  [#12478](https://github.com/rust-lang/cargo/pull/12478)\n  [#12492](https://github.com/rust-lang/cargo/pull/12492)\n- Fixed invalid package names generated by `-Zscript`.\n  [#12349](https://github.com/rust-lang/cargo/pull/12349)\n- `-Zscript` now errors out on unsupported commands — `publish` and `package`.\n  [#12350](https://github.com/rust-lang/cargo/pull/12350)\n- Encode URL params correctly for source ID in Cargo.lock.\n  [#12280](https://github.com/rust-lang/cargo/pull/12280)\n- Replaced invalid `panic_unwind` std feature with `panic-unwind`.\n  [#12364](https://github.com/rust-lang/cargo/pull/12364)\n- `-Zlints`: doctest extraction should respect `[lints]`.\n  [#12501](https://github.com/rust-lang/cargo/pull/12501)\n\n### Documentation\n\n- SemVer: Adding a section for changing the alignment, layout, or size of a\n  well-defined type.\n  [#12169](https://github.com/rust-lang/cargo/pull/12169)\n- Use heading attributes to control the fragment.\n  [#12339](https://github.com/rust-lang/cargo/pull/12339)\n- Use \"number\" instead of \"digit\" when explaining Cargo's use of semver.\n  [#12340](https://github.com/rust-lang/cargo/pull/12340)\n- contrib: Add some more detail about how publishing works.\n  [#12344](https://github.com/rust-lang/cargo/pull/12344)\n- Clarify \"Package ID\" and \"Source ID\" in `cargo metadata` are opaque strings.\n  [#12313](https://github.com/rust-lang/cargo/pull/12313)\n- Clarify that `rerun-if-env-changed` doesn't monitor the environment variables\n  it set for crates and build script.\n  [#12482](https://github.com/rust-lang/cargo/pull/12482)\n- Clarify that multiple versions that differ only in the metadata tag are\n  disallowed on crates.io.\n  [#12335](https://github.com/rust-lang/cargo/pull/12335)\n- Clarify `lto` setting passing `-Clinker-plugin-lto`.\n  [#12407](https://github.com/rust-lang/cargo/pull/12407)\n- Added `profile.strip` to configuration and environment variable docs.\n  [#12337](https://github.com/rust-lang/cargo/pull/12337)\n  [#12408](https://github.com/rust-lang/cargo/pull/12408)\n- Added docs for artifact JSON debuginfo levels.\n  [#12376](https://github.com/rust-lang/cargo/pull/12376)\n- Added a notice for the backward compatible `.cargo/credential` file existence.\n  [#12479](https://github.com/rust-lang/cargo/pull/12479)\n- Raised the awareness of `resolver = 2` used inside workspaces.\n  [#12388](https://github.com/rust-lang/cargo/pull/12388)\n- Replaced `master` branch by default branch in documentation.\n  [#12435](https://github.com/rust-lang/cargo/pull/12435)\n\n### Internal\n\n- Updated to `criterion` 0.5.1.\n  [#12338](https://github.com/rust-lang/cargo/pull/12338)\n- Updated to `curl-sys` 0.4.65, which corresponds to curl 8.2.1.\n  [#12406](https://github.com/rust-lang/cargo/pull/12406)\n- Updated to `indexmap` v2.\n  [#12368](https://github.com/rust-lang/cargo/pull/12368)\n- Updated to `miow` 0.6.0, which drops old versions of `windows-sys`.\n  [#12453](https://github.com/rust-lang/cargo/pull/12453)\n- ci: automatically test new packages by using `--workspace`.\n  [#12342](https://github.com/rust-lang/cargo/pull/12342)\n- ci: automatically update dependencies monthly with Renovate.\n  [#12341](https://github.com/rust-lang/cargo/pull/12341)\n  [#12466](https://github.com/rust-lang/cargo/pull/12466)\n- ci: rewrote `xtask-bump-check` for respecting semver by adopting `cargo-semver-checks`.\n  [#12395](https://github.com/rust-lang/cargo/pull/12395)\n  [#12513](https://github.com/rust-lang/cargo/pull/12513)\n  [#12508](https://github.com/rust-lang/cargo/pull/12508)\n- Rearranged and renamed test directories\n  [#12397](https://github.com/rust-lang/cargo/pull/12397)\n  [#12398](https://github.com/rust-lang/cargo/pull/12398)\n- Migrated from `log` to `tracing`.\n  [#12458](https://github.com/rust-lang/cargo/pull/12458)\n  [#12488](https://github.com/rust-lang/cargo/pull/12488)\n- Track `--help` output in tests.\n  [#11912](https://github.com/rust-lang/cargo/pull/11912)\n- Cleaned up and shared package metadata within workspace.\n  [#12352](https://github.com/rust-lang/cargo/pull/12352)\n- `crates-io`: expose HTTP headers and `Error` type.\n  [#12310](https://github.com/rust-lang/cargo/pull/12310)\n- For `cargo update`, caught CLI flags conflict between `--aggressive` and `--precise` in clap.\n  [#12428](https://github.com/rust-lang/cargo/pull/12428)\n- Several fixes for either making Cargo testsuite pass on nightly or in `rust-lang/rust`.\n  [#12413](https://github.com/rust-lang/cargo/pull/12413)\n  [#12416](https://github.com/rust-lang/cargo/pull/12416)\n  [#12429](https://github.com/rust-lang/cargo/pull/12429)\n  [#12450](https://github.com/rust-lang/cargo/pull/12450)\n  [#12491](https://github.com/rust-lang/cargo/pull/12491)\n  [#12500](https://github.com/rust-lang/cargo/pull/12500)\n\n## Cargo 1.72 (2023-08-24)\n[64fb38c9...rust-1.72.0](https://github.com/rust-lang/cargo/compare/64fb38c9...rust-1.72.0)\n\n### Added\n\n- ❗ Enable `-Zdoctest-in-workspace` by default. When running each documentation\n  test, the working directory is set to the root directory of the package the\n  test belongs to.\n  [docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-test.html#working-directory-of-tests)\n  [#12221](https://github.com/rust-lang/cargo/pull/12221)\n  [#12288](https://github.com/rust-lang/cargo/pull/12288)\n- Add support of the \"default\" keyword to reset previously set `build.jobs`\n  parallelism back to the default.\n  [#12222](https://github.com/rust-lang/cargo/pull/12222)\n\n### Changed\n\n- 🚨 [CVE-2023-40030](https://github.com/rust-lang/cargo/security/advisories/GHSA-wrrj-h57r-vx9p):\n  Malicious dependencies can inject arbitrary JavaScript into cargo-generated timing reports.\n  To mitigate this, feature name validation check is now turned into a hard error.\n  The warning was added in Rust 1.49. These extended characters aren't allowed on crates.io,\n  so this should only impact users of other registries, or people who don't publish to a registry.\n  [#12291](https://github.com/rust-lang/cargo/pull/12291)\n- Cargo now warns when an edition 2021 package is in a virtual workspace and\n  `workspace.resolver` is not set. It is recommended to set the resolver\n  version for workspaces explicitly.\n  [#10910](https://github.com/rust-lang/cargo/pull/10910)\n- Set IBM AIX shared libraries search path to `LIBPATH`.\n  [#11968](https://github.com/rust-lang/cargo/pull/11968)\n- Don't pass `-C debuginfo=0` to rustc as it is the default value.\n  [#12022](https://github.com/rust-lang/cargo/pull/12022)\n  [#12205](https://github.com/rust-lang/cargo/pull/12205)\n- Added a message on reusing previous temporary path on `cargo install` failures.\n  [#12231](https://github.com/rust-lang/cargo/pull/12231)\n- Added a message when `rustup` override shorthand is put in a wrong position.\n  [#12226](https://github.com/rust-lang/cargo/pull/12226)\n- Respect scp-like URL as much as possible when fetching nested submodules.\n  [#12359](https://github.com/rust-lang/cargo/pull/12359)\n  [#12411](https://github.com/rust-lang/cargo/pull/12411)\n\n### Fixed\n\n- `cargo clean` uses `remove_dir_all` as a fallback to resolve race conditions.\n  [#11442](https://github.com/rust-lang/cargo/pull/11442)\n- Reduced the chance Cargo re-formats the user's `[features]` table.\n  [#12191](https://github.com/rust-lang/cargo/pull/12191)\n- Fixed nested Git submodules not able to fetch.\n  [#12244](https://github.com/rust-lang/cargo/pull/12244)\n\n### Nightly only\n\n- 🔥 The `-Zscript` is an experimental feature to add unstable support for\n  single-file packages in Cargo, so we can explore the design and resolve\n  questions with an implementation to collect feedback on.\n  ([eRFC 3424](https://github.com/rust-lang/rfcs/blob/master/text/3424-cargo-script.md))\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#script)\n  [#12245](https://github.com/rust-lang/cargo/pull/12245)\n  [#12255](https://github.com/rust-lang/cargo/pull/12255)\n  [#12258](https://github.com/rust-lang/cargo/pull/12258)\n  [#12262](https://github.com/rust-lang/cargo/pull/12262)\n  [#12268](https://github.com/rust-lang/cargo/pull/12268)\n  [#12269](https://github.com/rust-lang/cargo/pull/12269)\n  [#12281](https://github.com/rust-lang/cargo/pull/12281)\n  [#12282](https://github.com/rust-lang/cargo/pull/12282)\n  [#12283](https://github.com/rust-lang/cargo/pull/12283)\n  [#12284](https://github.com/rust-lang/cargo/pull/12284)\n  [#12287](https://github.com/rust-lang/cargo/pull/12287)\n  [#12289](https://github.com/rust-lang/cargo/pull/12289)\n  [#12303](https://github.com/rust-lang/cargo/pull/12303)\n  [#12305](https://github.com/rust-lang/cargo/pull/12305)\n  [#12308](https://github.com/rust-lang/cargo/pull/12308)\n- Automatically inherit workspace lints when running `cargo new`/`cargo init`.\n  [#12174](https://github.com/rust-lang/cargo/pull/12174)\n- Removed `-Zjobserver-per-rustc` again.\n  [#12285](https://github.com/rust-lang/cargo/pull/12285)\n- Added `.toml` file extension restriction for `-Zconfig-include`.\n  [#12298](https://github.com/rust-lang/cargo/pull/12298)\n- Added `-Znext-lockfile-bump` to prepare for the next lockfile bump.\n  [#12279](https://github.com/rust-lang/cargo/pull/12279)\n  [#12302](https://github.com/rust-lang/cargo/pull/12302)\n\n### Documentation\n\n- Added a description of `Cargo.lock` conflicts in the Cargo FAQ.\n  [#12185](https://github.com/rust-lang/cargo/pull/12185)\n- Added a small note about indexes ignoring SemVer build metadata.\n  [#12206](https://github.com/rust-lang/cargo/pull/12206)\n- Added doc comments for types and friends in `cargo::sources` module.\n  [#12192](https://github.com/rust-lang/cargo/pull/12192)\n  [#12239](https://github.com/rust-lang/cargo/pull/12239)\n  [#12247](https://github.com/rust-lang/cargo/pull/12247)\n- Added more documentation for `Source` download functions.\n  [#12319](https://github.com/rust-lang/cargo/pull/12319)\n- Added READMEs for the credential helpers.\n  [#12322](https://github.com/rust-lang/cargo/pull/12322)\n- Fixed version requirement example in Dependency Resolution.\n  [#12267](https://github.com/rust-lang/cargo/pull/12267)\n- Clarify the default behavior of cargo-install.\n  [#12276](https://github.com/rust-lang/cargo/pull/12276)\n- Clarify the use of \"default\" branch instead of `main` by default.\n  [#12251](https://github.com/rust-lang/cargo/pull/12251)\n- Provide guidance on version requirements.\n  [#12323](https://github.com/rust-lang/cargo/pull/12323)\n\n### Internal\n\n- Updated to `gix` 0.45 for multi-round pack negotiations.\n  [#12236](https://github.com/rust-lang/cargo/pull/12236)\n- Updated to `curl-sys` 0.4.63, which corresponds to curl 8.1.2.\n  [#12218](https://github.com/rust-lang/cargo/pull/12218)\n- Updated to `openssl` 0.10.55.\n  [#12300](https://github.com/rust-lang/cargo/pull/12300)\n- Updated several dependencies.\n  [#12261](https://github.com/rust-lang/cargo/pull/12261)\n- Removed unused features from `windows-sys` dependency.\n  [#12176](https://github.com/rust-lang/cargo/pull/12176)\n- Refactored compiler invocations.\n  [#12211](https://github.com/rust-lang/cargo/pull/12211)\n- Refactored git and registry sources, and registry data.\n  [#12203](https://github.com/rust-lang/cargo/pull/12203)\n  [#12197](https://github.com/rust-lang/cargo/pull/12197)\n  [#12240](https://github.com/rust-lang/cargo/pull/12240)\n  [#12248](https://github.com/rust-lang/cargo/pull/12248)\n- Lexicographically order `-Z` flags.\n  [#12182](https://github.com/rust-lang/cargo/pull/12182)\n  [#12223](https://github.com/rust-lang/cargo/pull/12223)\n  [#12224](https://github.com/rust-lang/cargo/pull/12224)\n- Several Cargo's own test infra improvements and speed-ups.\n  [#12184](https://github.com/rust-lang/cargo/pull/12184)\n  [#12188](https://github.com/rust-lang/cargo/pull/12188)\n  [#12189](https://github.com/rust-lang/cargo/pull/12189)\n  [#12194](https://github.com/rust-lang/cargo/pull/12194)\n  [#12199](https://github.com/rust-lang/cargo/pull/12199)\n- Migrated print-ban from test to clippy\n  [#12246](https://github.com/rust-lang/cargo/pull/12246)\n- Switched to `OnceLock` for interning uses.\n  [#12217](https://github.com/rust-lang/cargo/pull/12217)\n- Removed a unnecessary `.clone`.\n  [#12213](https://github.com/rust-lang/cargo/pull/12213)\n- Don't try to compile `cargo-credential-gnome-secret` on non-Linux platforms.\n  [#12321](https://github.com/rust-lang/cargo/pull/12321)\n- Use macro to remove duplication of workspace inheritable fields getters.\n  [#12317](https://github.com/rust-lang/cargo/pull/12317)\n- Extracted and rearranged registry API items to their own modules.\n  [#12290](https://github.com/rust-lang/cargo/pull/12290)\n- Show a better error when container tests fail.\n  [#12264](https://github.com/rust-lang/cargo/pull/12264)\n\n## Cargo 1.71.1 (2023-08-03)\n\n### Fixed\n\n- 🚨 [CVE-2023-38497](https://github.com/rust-lang/cargo/security/advisories/GHSA-j3xp-wfr4-hx87):\n  Cargo 1.71.1 or later respects umask when extracting crate archives. It also\n  purges the caches it tries to access if they were generated by older Cargo versions.\n\n## Cargo 1.71 (2023-07-13)\n[84b7041f...rust-1.71.0](https://github.com/rust-lang/cargo/compare/84b7041f...rust-1.71.0)\n\n### Added\n\n- Allowed named debuginfo options in Cargo.toml.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/profiles.html#debug)\n  [#11958](https://github.com/rust-lang/cargo/pull/11958)\n- Added `workspace_default_members` to the output of `cargo metadata`.\n  [#11978](https://github.com/rust-lang/cargo/pull/11978)\n- Automatically inherit workspace fields when running `cargo new`/`cargo init`.\n  [#12069](https://github.com/rust-lang/cargo/pull/12069)\n\n### Changed\n\n- ❗ Optimized the usage under `rustup`. When Cargo detects it will run `rustc`\n  pointing a rustup proxy, it'll try bypassing the proxy and use the underlying\n  binary directly. There are assumptions around the interaction with rustup and\n  `RUSTUP_TOOLCHAIN`. However, it's not expected to affect normal users.\n  [#11917](https://github.com/rust-lang/cargo/pull/11917)\n- ❗ When querying a package, Cargo tries only the original name, all hyphens,\n  and all underscores to handle misspellings. Previously, Cargo tried each\n  combination of hyphens and underscores, causing excessive requests to crates.io.\n  [#12083](https://github.com/rust-lang/cargo/pull/12083)\n- ❗ Disallow `RUSTUP_HOME` and `RUSTUP_TOOLCHAIN` in the `[env]` configuration\n  table. This is considered to be not a use case Cargo would like to support,\n  since it will likely cause problems or lead to confusion.\n  [#12101](https://github.com/rust-lang/cargo/pull/12101)\n  [#12107](https://github.com/rust-lang/cargo/pull/12107)\n- Better error message when getting an empty dependency table in Cargo.toml.\n  [#11997](https://github.com/rust-lang/cargo/pull/11997)\n- Better error message when empty dependency was specified in Cargo.toml.\n  [#12001](https://github.com/rust-lang/cargo/pull/12001)\n- `--help` text is now wrapping for readability on narrow screens.\n  [#12013](https://github.com/rust-lang/cargo/pull/12013)\n- Tweaked the order of arguments in `--help` text to clarify role of `--bin`.\n  [#12157](https://github.com/rust-lang/cargo/pull/12157)\n- `rust-version` is included in `cargo publish` requests to registries.\n  [#12041](https://github.com/rust-lang/cargo/pull/12041)\n\n### Fixed\n\n- Corrected the bug report URL for `cargo clippy --fix`.\n  [#11882](https://github.com/rust-lang/cargo/pull/11882)\n- Cargo now applies `[env]` to rust invocations for target info discovery.\n  [#12029](https://github.com/rust-lang/cargo/pull/12029)\n- Fixed tokens not redacted in http debug when using HTTP/2.\n  [#12095](https://github.com/rust-lang/cargo/pull/12095)\n- Fixed `-C debuginfo` not passed in some situation, leading to build cache miss.\n  [#12165](https://github.com/rust-lang/cargo/pull/12165)\n- Fixed the ambiguity when `cargo install` found packages with the same name.\n  The ambiguity happened in a situation like a package depending on old versions\n  of itself.\n  [#12015](https://github.com/rust-lang/cargo/pull/12015)\n- Fixed a false positive that `cargo package` checks for conflict files.\n  [#12135](https://github.com/rust-lang/cargo/pull/12135)\n- Fixed `dep/feat` syntax not working when co-exist with `dep:` syntax, and\n  trying to enable features of an optional dependency.\n  [#12130](https://github.com/rust-lang/cargo/pull/12130)\n- Fixed `cargo tree` not handling the output with `-e no-proc-macro` correctly.\n  [#12044](https://github.com/rust-lang/cargo/pull/12044)\n- Warn instead of error in `cargo package` on empty `readme` or `license-file`\n  in Cargo.toml.\n  [#12036](https://github.com/rust-lang/cargo/pull/12036)\n- Fixed when an HTTP proxy is in use and the Cargo executable links to a\n  certain version of system libcurl, CURL connections might fail. Affected\n  libcurl versions: 7.87.0, 7.88.0, 7.88.1.\n  [#12234](https://github.com/rust-lang/cargo/pull/12234)\n  [#12242](https://github.com/rust-lang/cargo/pull/12242)\n\n### Nightly only\n\n- 🔥 The `-Zgitoxide` feature now supports shallow clones and fetches for\n  dependencies and registry indexes.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#gitoxide)\n  [#11840](https://github.com/rust-lang/cargo/pull/11840)\n- 🔥 The `-Zlints` feature enables configuring lints rules in Cargo.toml\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#lints)\n  [#12148](https://github.com/rust-lang/cargo/pull/12148)\n  [#12168](https://github.com/rust-lang/cargo/pull/12168)\n- The `-Zbuild-std` breakage of missing features in `nightly-2023-05-04` has\n  been fixed in `nightly-2023-05-05`.\n  [#12088](https://github.com/rust-lang/cargo/pull/12088)\n- Recompile on profile rustflags changes.\n  [#11981](https://github.com/rust-lang/cargo/pull/11981)\n- Added `-Zmsrv-policy` feature flag placeholder.\n  [#12043](https://github.com/rust-lang/cargo/pull/12043)\n- `cargo add` now considers `rust-version` when selecting packages with `-Zmsrv-policy`.\n  [#12078](https://github.com/rust-lang/cargo/pull/12078)\n\n### Documentation\n\n- Added Cargo team charter.\n  [docs](https://doc.crates.io/contrib/team.html)\n  [#12010](https://github.com/rust-lang/cargo/pull/12010)\n- SemVer: Adding `#[non_exhaustive]` on existing items is a breaking change.\n  [#10877](https://github.com/rust-lang/cargo/pull/10877)\n- SemVer: It is not a breaking change to make an unsafe function safe.\n  [#12116](https://github.com/rust-lang/cargo/pull/12116)\n- SemVer: changing MSRV is generally a minor change.\n  [#12122](https://github.com/rust-lang/cargo/pull/12122)\n- Clarify when and how to `cargo yank`.\n  [#11862](https://github.com/rust-lang/cargo/pull/11862)\n- Clarify that crates.io doesn't link to docs.rs right away.\n  [#12146](https://github.com/rust-lang/cargo/pull/12146)\n- Clarify documentation around test target setting. \n  [#12032](https://github.com/rust-lang/cargo/pull/12032)\n- Specify `rust_version` in Index format.\n  [#12040](https://github.com/rust-lang/cargo/pull/12040)\n- Specify `msg` in owner-remove registry API response.\n  [#12068](https://github.com/rust-lang/cargo/pull/12068)\n- Added more documentation for artifact-dependencies. \n  [#12110](https://github.com/rust-lang/cargo/pull/12110)\n- Added doc comments for `Source` and build script for cargo-the-library.\n  [#12133](https://github.com/rust-lang/cargo/pull/12133)\n  [#12153](https://github.com/rust-lang/cargo/pull/12153)\n  [#12159](https://github.com/rust-lang/cargo/pull/12159)\n- Several typo and broken link fixes.\n  [#12018](https://github.com/rust-lang/cargo/pull/12018)\n  [#12020](https://github.com/rust-lang/cargo/pull/12020)\n  [#12049](https://github.com/rust-lang/cargo/pull/12049)\n  [#12067](https://github.com/rust-lang/cargo/pull/12067)\n  [#12073](https://github.com/rust-lang/cargo/pull/12073)\n  [#12143](https://github.com/rust-lang/cargo/pull/12143)\n- home: clarify the behavior on each platform\n  [#12047](https://github.com/rust-lang/cargo/pull/12047)\n\n### Internal\n\n- Updated to `linux-raw-sys` 0.3.2 \n  [#11998](https://github.com/rust-lang/cargo/pull/11998)\n- Updated to `git2` 0.17.1, which corresponds to libgit2 1.6.4.\n  [#12096](https://github.com/rust-lang/cargo/pull/12096)\n- Updated to `windows-sys` 0.48.0 \n  [#12021](https://github.com/rust-lang/cargo/pull/12021)\n- Updated to `libc` 0.2.144 \n  [#12014](https://github.com/rust-lang/cargo/pull/12014)\n  [#12098](https://github.com/rust-lang/cargo/pull/12098)\n- Updated to `openssl-src` 111.25.3+1.1.1t \n  [#12005](https://github.com/rust-lang/cargo/pull/12005)\n- Updated to `home` 0.5.5\n  [#12037](https://github.com/rust-lang/cargo/pull/12037)\n- Enabled feature `Win32_System_Console` feature since it is used.\n  [#12016](https://github.com/rust-lang/cargo/pull/12016)\n- Cargo is now a Cargo workspace. We dogfood ourselves finally!\n  [#11851](https://github.com/rust-lang/cargo/pull/11851)\n  [#11994](https://github.com/rust-lang/cargo/pull/11994)\n  [#11996](https://github.com/rust-lang/cargo/pull/11996)\n  [#12024](https://github.com/rust-lang/cargo/pull/12024)\n  [#12025](https://github.com/rust-lang/cargo/pull/12025)\n  [#12057](https://github.com/rust-lang/cargo/pull/12057)\n- 🔥 A new, straightforward issue labels system for Cargo contributors.\n  [docs](https://doc.crates.io/contrib/issues.html)\n  [#11995](https://github.com/rust-lang/cargo/pull/11995)\n  [#12002](https://github.com/rust-lang/cargo/pull/12002)\n  [#12003](https://github.com/rust-lang/cargo/pull/12003)\n- Allow win/mac credential managers to build on all platforms.\n  [#11993](https://github.com/rust-lang/cargo/pull/11993)\n  [#12027](https://github.com/rust-lang/cargo/pull/12027)\n- Use `openssl` only on non-Windows platforms.\n  [#11979](https://github.com/rust-lang/cargo/pull/11979)\n- Use restricted Damerau-Levenshtein algorithm to provide typo suggestions.\n  [#11963](https://github.com/rust-lang/cargo/pull/11963)\n- Added a new xtask `cargo build-man`.\n  [#12048](https://github.com/rust-lang/cargo/pull/12048)\n- Added a new xtask `cargo stale-label`.\n  [#12051](https://github.com/rust-lang/cargo/pull/12051)\n- Added a new xtask `cargo unpublished`.\n  [#12039](https://github.com/rust-lang/cargo/pull/12039)\n  [#12045](https://github.com/rust-lang/cargo/pull/12045)\n  [#12085](https://github.com/rust-lang/cargo/pull/12085)\n- CI: check if any version bump needed for member crates.\n  [#12126](https://github.com/rust-lang/cargo/pull/12126)\n- Fixed some test infra issues.\n  [#11976](https://github.com/rust-lang/cargo/pull/11976)\n  [#12026](https://github.com/rust-lang/cargo/pull/12026)\n  [#12055](https://github.com/rust-lang/cargo/pull/12055)\n  [#12117](https://github.com/rust-lang/cargo/pull/12117)\n\n## Cargo 1.70 (2023-06-01)\n[9880b408...rust-1.70.0](https://github.com/rust-lang/cargo/compare/9880b408...rust-1.70.0)\n\n### Added\n\n- 🎉 Added `cargo logout` command for removing an API token from the registry locally.\n  [docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-logout.html)\n  [#11919](https://github.com/rust-lang/cargo/pull/11919)\n  [#11950](https://github.com/rust-lang/cargo/pull/11950)\n- Added `--ignore-rust-version` flag to `cargo install`.\n  [#11859](https://github.com/rust-lang/cargo/pull/11859)\n- The `CARGO_PKG_README` environment variable is now set to the path to the\n  README file when compiling a crate.\n  [#11645](https://github.com/rust-lang/cargo/pull/11645)\n- Cargo now displays richer information of Cargo target failed to compile.\n  [#11636](https://github.com/rust-lang/cargo/pull/11636)\n\n### Changed\n\n- 🎉 The `sparse` protocol is now the default protocol for crates.io!\n  ([RFC 2789](https://github.com/rust-lang/rfcs/blob/master/text/2789-sparse-index.md))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/registries.html#registry-protocols))\n  [#11791](https://github.com/rust-lang/cargo/pull/11791)\n  [#11783](https://github.com/rust-lang/cargo/pull/11783)\n- ❗ `cargo login` and `cargo logout` now uses the registry specified in\n  `registry.default`. This was an unintentional regression.\n  [#11949](https://github.com/rust-lang/cargo/pull/11949)\n- `cargo update` accurately shows `Downgrading` status when downgrading dependencies.\n  [#11839](https://github.com/rust-lang/cargo/pull/11839)\n- Added more information to HTTP errors to help with debugging.\n  [#11878](https://github.com/rust-lang/cargo/pull/11878)\n- Added delays to network retries in Cargo.\n  [#11881](https://github.com/rust-lang/cargo/pull/11881)\n- Refined `cargo publish` message when waiting for a publish complete.\n  [#11713](https://github.com/rust-lang/cargo/pull/11713)\n- Better error message when `cargo install` from a git repository but found\n  multiple packages.\n  [#11835](https://github.com/rust-lang/cargo/pull/11835)\n\n### Fixed\n\n- Removed duplicates of possible values in `--charset` option of `cargo tree`.\n  [#11785](https://github.com/rust-lang/cargo/pull/11785)\n- Fixed `CARGO_CFG_` vars for configs defined both with and without value.\n  [#11790](https://github.com/rust-lang/cargo/pull/11790)\n- Broke endless loop on cyclic features in added dependency in `cargo add`.\n  [#11805](https://github.com/rust-lang/cargo/pull/11805)\n- Don't panic when `[patch]` involved in dependency resolution results in a conflict.\n  [#11770](https://github.com/rust-lang/cargo/pull/11770)\n- Fixed credential token format validation.\n  [#11951](https://github.com/rust-lang/cargo/pull/11951)\n- Added the missing token format validation on publish.\n  [#11952](https://github.com/rust-lang/cargo/pull/11952)\n- Fixed case mismatches when looking up env vars in the Config snapshot.\n  [#11824](https://github.com/rust-lang/cargo/pull/11824)\n- `cargo new` generates the correct `.hgignore` aligning semantics with other\n  VCS ignore files.\n  [#11855](https://github.com/rust-lang/cargo/pull/11855)\n- Stopped doing unnecessary fuzzy registry index queries. This significantly\n  reduces the amount of HTTP requests to remote registries for crates\n  containing `-` or `_` in their names.\n  [#11936](https://github.com/rust-lang/cargo/pull/11936)\n  [#11937](https://github.com/rust-lang/cargo/pull/11937)\n\n### Nightly only\n\n- Added `-Zdirect-minimal-versions`. This behaves like `-Zminimal-versions` but\n  only for direct dependencies.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#direct-minimal-versions))\n  [#11688](https://github.com/rust-lang/cargo/pull/11688)\n- Added `-Zgitoxide` which switches all `git fetch` operation in Cargo to\n  use `gitoxide` crate. This is still an MVP but could improve the performance\n  up to 2 times.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html##gitoxide))\n  [#11448](https://github.com/rust-lang/cargo/pull/11448)\n  [#11800](https://github.com/rust-lang/cargo/pull/11800)\n  [#11822](https://github.com/rust-lang/cargo/pull/11822)\n  [#11830](https://github.com/rust-lang/cargo/pull/11830)\n- Removed `-Zjobserver-per-rustc`. Its rustc counterpart never got landed.\n  [#11764](https://github.com/rust-lang/cargo/pull/11764)\n\n### Documentation\n\n- Cleaned-up unstable documentation.\n  [#11793](https://github.com/rust-lang/cargo/pull/11793)\n- Enhanced the documentation of timing report with graphs.\n  [#11798](https://github.com/rust-lang/cargo/pull/11798)\n- Clarified requirements about the state of the registry index after publish.\n  [#11926](https://github.com/rust-lang/cargo/pull/11926)\n- Clarified docs on `-C` that it appears before the command.\n  [#11947](https://github.com/rust-lang/cargo/pull/11947)\n- Clarified working directory behaviour for `cargo test`, `cargo bench` and\n  `cargo run`.\n  [#11901](https://github.com/rust-lang/cargo/pull/11901)\n- Fixed the doc of `registries.name.index` configuration.\n  [#11880](https://github.com/rust-lang/cargo/pull/11880)\n- Notice for potential unexpected shell expansions in help text of `cargo-add`.\n  [#11826](https://github.com/rust-lang/cargo/pull/11826)\n- Updated external-tools JSON docs.\n  [#11918](https://github.com/rust-lang/cargo/pull/11918)\n- Call out the differences between the index JSON and the API or metadata. \n  [#11927](https://github.com/rust-lang/cargo/pull/11927)\n- Consistently use `@` when mentioning pkgid format.\n  [#11956](https://github.com/rust-lang/cargo/pull/11956)\n- Enhanced Cargo Contributor Guide.\n  [#11825](https://github.com/rust-lang/cargo/pull/11825)\n  [#11842](https://github.com/rust-lang/cargo/pull/11842)\n  [#11869](https://github.com/rust-lang/cargo/pull/11869)\n  [#11876](https://github.com/rust-lang/cargo/pull/11876)\n- Moved a part of Cargo Contributor Guide to Cargo API documentation.\n  [docs](https://doc.rust-lang.org/nightly/nightly-rustc/cargo)\n  [#11809](https://github.com/rust-lang/cargo/pull/11809)\n  [#11841](https://github.com/rust-lang/cargo/pull/11841)\n  [#11850](https://github.com/rust-lang/cargo/pull/11850)\n  [#11870](https://github.com/rust-lang/cargo/pull/11870)\n- Cargo team now arranges\n  [office hours](https://github.com/rust-lang/cargo/wiki/Office-Hours)!\n  [#11903](https://github.com/rust-lang/cargo/pull/11903)\n\n### Internal\n\n- Switched to `sha2` crate for SHA256 calculation.\n  [#11795](https://github.com/rust-lang/cargo/pull/11795)\n  [#11807](https://github.com/rust-lang/cargo/pull/11807)\n- Switched benchsuite to the index archive.\n  [#11933](https://github.com/rust-lang/cargo/pull/11933)\n- Updated to `base64` 0.21.0.\n  [#11796](https://github.com/rust-lang/cargo/pull/11796)\n- Updated to `curl-sys` 0.4.61, which corresponds to curl 8.0.1.\n  [#11871](https://github.com/rust-lang/cargo/pull/11871)\n- Updated to `proptest` 1.1.0.\n  [#11886](https://github.com/rust-lang/cargo/pull/11886)\n- Updated to `git2` 0.17.0, which corresponds to libgit2 1.6.3.\n  [#11928](https://github.com/rust-lang/cargo/pull/11928)\n- Updated to `clap` 4.2.\n  [#11904](https://github.com/rust-lang/cargo/pull/11904)\n- Integrated `cargo-deny` in Cargo its own CI pipeline.\n  [#11761](https://github.com/rust-lang/cargo/pull/11761)\n- Made non-blocking IO calls more robust.\n  [#11624](https://github.com/rust-lang/cargo/pull/11624)\n- Dropped `derive` feature from `serde` in `cargo-platform`.\n  [#11915](https://github.com/rust-lang/cargo/pull/11915)\n- Replaced `std::fs::canonicalize` with a more robust `try_canonicalize`.\n  [#11866](https://github.com/rust-lang/cargo/pull/11866)\n- Enabled clippy warning on `disallowed_methods` for `std::env::var` and friends.\n  [#11828](https://github.com/rust-lang/cargo/pull/11828)\n\n## Cargo 1.69 (2023-04-20)\n[985d561f...rust-1.69.0](https://github.com/rust-lang/cargo/compare/985d561f...rust-1.69.0)\n\n### Added\n\n- Cargo now suggests `cargo fix` or `cargo clippy --fix`\n  when compilation warnings are auto-fixable.\n  [#11558](https://github.com/rust-lang/cargo/pull/11558)\n- Cargo now suggests `cargo add` if you try to install a library crate.\n  [#11410](https://github.com/rust-lang/cargo/pull/11410)\n- Cargo now sets the `CARGO_BIN_NAME` environment variable also for binary examples.\n  [#11705](https://github.com/rust-lang/cargo/pull/11705)\n\n### Changed\n\n- ❗ When `default-features` is set to false of a workspace dependency,\n  and an inherited dependency of a member has `default-features = true`,\n  Cargo will enable default features of that dependency.\n  [#11409](https://github.com/rust-lang/cargo/pull/11409)\n- ❗ Deny `CARGO_HOME` in `[env]` configuration table. Cargo itself doesn't\n  pick up this value, but recursive calls to cargo would, which was not intended.\n  [#11644](https://github.com/rust-lang/cargo/pull/11644)\n- ❗ Debuginfo for build dependencies is now off if not explicitly set. This is\n  expected to improve the overall build time.\n  [#11252](https://github.com/rust-lang/cargo/pull/11252)\n- Cargo now emits errors on invalid alphanumeric characters in a registry token.\n  [#11600](https://github.com/rust-lang/cargo/pull/11600)\n- `cargo add` now checks only the order of `[dependencies]`\n  without considering `[dependencies.*]`.\n  [#11612](https://github.com/rust-lang/cargo/pull/11612)\n- Cargo now respects the new jobserver IPC style in GNU Make 4.4, by updating\n  its dependency `jobserver`.\n  [#11767](https://github.com/rust-lang/cargo/pull/11767)\n- `cargo install` now reports required features when no binary meets its requirements.\n  [#11647](https://github.com/rust-lang/cargo/pull/11647)\n\n### Fixed\n\n- Uplifted `.dwp` DWARF package file next to the executable for debuggers to\n  locate them.\n  [#11572](https://github.com/rust-lang/cargo/pull/11572)\n- Fixed build scripts triggering recompiles when a `rerun-if-changed` points to\n  a directory whose mtime is not preserved by the filesystem.\n  [#11613](https://github.com/rust-lang/cargo/pull/11613)\n- Fixed panics when using dependencies from `[workspace.dependencies]`\n  for `[patch]`. This usage is not supposed to be supported.\n  [#11565](https://github.com/rust-lang/cargo/pull/11565)\n  [#11630](https://github.com/rust-lang/cargo/pull/11630)\n- Fixed `cargo report` saving the same future-incompat reports multiple times.\n  [#11648](https://github.com/rust-lang/cargo/pull/11648)\n- Fixed the incorrect inference of a directory ending with `.rs` as a file.\n  [#11678](https://github.com/rust-lang/cargo/pull/11678)\n- Fixed `.cargo-ok` file being truncated wrongly, preventing from using a dependency.\n  [#11665](https://github.com/rust-lang/cargo/pull/11665)\n  [#11724](https://github.com/rust-lang/cargo/pull/11724)\n\n### Nightly only\n\n- `-Zrustdoc-scrape-example` must fail with bad build script.\n  [#11694](https://github.com/rust-lang/cargo/pull/11694)\n- Updated 1password credential manager integration to the version 2 CLI.\n  [#11692](https://github.com/rust-lang/cargo/pull/11692)\n- Emit an error message for transitive artifact dependencies with targets the\n  package doesn't directly interact with.\n  [#11643](https://github.com/rust-lang/cargo/pull/11643)\n- Added `-C` flag for changing current dir before build starts.\n  [#10952](https://github.com/rust-lang/cargo/pull/10952)\n\n### Documentation\n\n- Clarified the difference between `CARGO_CRATE_NAME` and `CARGO_PKG_NAME`.\n  [#11576](https://github.com/rust-lang/cargo/pull/11576)\n- Added links to the Target section of the glossary for occurrences of target triple.\n  [#11603](https://github.com/rust-lang/cargo/pull/11603)\n- Described how the current resolver sometimes duplicates dependencies.\n  [#11604](https://github.com/rust-lang/cargo/pull/11604)\n- Added a note about verifying your email address on crates.io.\n  [#11620](https://github.com/rust-lang/cargo/pull/11620)\n- Mention current default value in `publish.timeout` docs.\n  [#11652](https://github.com/rust-lang/cargo/pull/11652)\n- More doc comments for `cargo::core::compiler` modules.\n  [#11669](https://github.com/rust-lang/cargo/pull/11669)\n  [#11703](https://github.com/rust-lang/cargo/pull/11703)\n  [#11711](https://github.com/rust-lang/cargo/pull/11711)\n  [#11758](https://github.com/rust-lang/cargo/pull/11758)\n- Added more guidance on how to implement unstable features.\n  [#11675](https://github.com/rust-lang/cargo/pull/11675)\n- Fixed unstable chapter layout for `codegen-backend`.\n  [#11676](https://github.com/rust-lang/cargo/pull/11676)\n- Add a link to LTO doc.\n  [#11701](https://github.com/rust-lang/cargo/pull/11701)\n- Added documentation for the configuration discovery of `cargo install`\n  to the man pages\n  [#11763](https://github.com/rust-lang/cargo/pull/11763)\n- Documented `-F` flag as an alias for `--features` in `cargo add`.\n  [#11774](https://github.com/rust-lang/cargo/pull/11774)\n\n### Internal\n\n- Disable network SSH tests on Windows.\n  [#11610](https://github.com/rust-lang/cargo/pull/11610)\n- Made some blocking tests non-blocking.\n  [#11650](https://github.com/rust-lang/cargo/pull/11650)\n- Deny warnings in CI, not locally.\n  [#11699](https://github.com/rust-lang/cargo/pull/11699)\n- Re-export `cargo_new::NewProjectKind` as public.\n  [#11700](https://github.com/rust-lang/cargo/pull/11700)\n- Made dependencies in alphabetical order.\n  [#11719](https://github.com/rust-lang/cargo/pull/11719)\n- Switched some tests from `build` to `check`.\n  [#11725](https://github.com/rust-lang/cargo/pull/11725)\n- Consolidated how Cargo reads environments variables internally.\n  [#11727](https://github.com/rust-lang/cargo/pull/11727)\n  [#11754](https://github.com/rust-lang/cargo/pull/11754)\n- Fixed tests with nondeterministic ordering\n  [#11766](https://github.com/rust-lang/cargo/pull/11766)\n- Added a test to verify the intermediate artifacts persist in the temp directory.\n  [#11771](https://github.com/rust-lang/cargo/pull/11771)\n- Updated cross test instructions for aarch64-apple-darwin.\n  [#11663](https://github.com/rust-lang/cargo/pull/11663)\n- Updated to `toml` v0.6 and `toml_edit` v0.18 for TOML manipulations.\n  [#11618](https://github.com/rust-lang/cargo/pull/11618)\n- Updated to `clap` v4.1.3.\n  [#11619](https://github.com/rust-lang/cargo/pull/11619)\n- Replaced `winapi` with `windows-sys` crate for Windows bindings.\n  [#11656](https://github.com/rust-lang/cargo/pull/11656)\n- Reused `url` crate for percent encoding instead of `percent-encoding`.\n  [#11750](https://github.com/rust-lang/cargo/pull/11750)\n- Cargo contributors can benefit from smart punctuations when writing\n  documentations, e.g., `---` is auto-converted into an em dash.\n  ([docs](https://rust-lang.github.io/mdBook/format/markdown.html#smart-punctuation))\n  [#11646](https://github.com/rust-lang/cargo/pull/11646)\n  [#11715](https://github.com/rust-lang/cargo/pull/11715)\n- Cargo's CI pipeline now covers macOS on nightly.\n  [#11712](https://github.com/rust-lang/cargo/pull/11712)\n- Re-enabled some clippy lints in Cargo itself.\n  [#11722](https://github.com/rust-lang/cargo/pull/11722)\n- Enabled sparse protocol in Cargo's CI.\n  [#11632](https://github.com/rust-lang/cargo/pull/11632)\n- Pull requests in Cargo now get autolabelled for label `A-*` and `Command-*`.\n  [#11664](https://github.com/rust-lang/cargo/pull/11664)\n  [#11679](https://github.com/rust-lang/cargo/pull/11679)\n\n## Cargo 1.68.2 (2023-03-28)\n[115f3455...rust-1.68.0](https://github.com/rust-lang/cargo/compare/115f3455...rust-1.68.0)\n\n- Updated the GitHub RSA SSH host key bundled within cargo.\n  The key was [rotated by\n  GitHub](https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/) on\n  2023-03-24 after the old one leaked.\n  [#11883](https://github.com/rust-lang/cargo/pull/11883)\n- Added support for SSH known hosts marker `@revoked`.\n  [#11635](https://github.com/rust-lang/cargo/pull/11635)\n- Marked the old GitHub RSA host key as revoked. This will prevent Cargo from\n  accepting the leaked key even when trusted by the system.\n  [#11889](https://github.com/rust-lang/cargo/pull/11889)\n\n## Cargo 1.68 (2023-03-09)\n[f6e737b1...rust-1.68.0](https://github.com/rust-lang/cargo/compare/f6e737b1...rust-1.68.0)\n\n### Added\n\n- 🎉 The new \"sparse\" protocol has been stabilized.\n  It should provide a significant performance improvement when accessing crates.io.\n  ([RFC 2789](https://github.com/rust-lang/rfcs/blob/master/text/2789-sparse-index.md))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/registries.html#registry-protocols))\n  [#11224](https://github.com/rust-lang/cargo/pull/11224)\n  [#11480](https://github.com/rust-lang/cargo/pull/11480)\n  [#11733](https://github.com/rust-lang/cargo/pull/11733)\n  [#11756](https://github.com/rust-lang/cargo/pull/11756)\n- 🎉 `home` crate is now a subcrate in `rust-lang/cargo` repository. Welcome!\n  [#11359](https://github.com/rust-lang/cargo/pull/11359)\n  [#11481](https://github.com/rust-lang/cargo/pull/11481)\n- Long diagnostic messages now can be truncated to be more readable.\n  [#11494](https://github.com/rust-lang/cargo/pull/11494)\n- Shows the progress of crates.io index update even when `net.git-fetch-with-cli` enabled.\n  [#11579](https://github.com/rust-lang/cargo/pull/11579)\n- `cargo build --verbose` tells you more about why it recompiles.\n  [#11407](https://github.com/rust-lang/cargo/pull/11407)\n- Cargo's file locking mechanism now supports Solaris by using `fcntl`.\n  [#11439](https://github.com/rust-lang/cargo/pull/11439)\n  [#11474](https://github.com/rust-lang/cargo/pull/11474)\n- Added a new SemVer compatibility rule explaining the expectations around diagnostic lints \n  [#11596](https://github.com/rust-lang/cargo/pull/11596)\n- `cargo vendor` generates a different source replacement entry\n  for each revision from the same git repository.\n  [#10690](https://github.com/rust-lang/cargo/pull/1090)\n- Cargo contributors can relabel issues via triagebot.\n  [doc](https://forge.rust-lang.org/triagebot/labeling.html)\n  [#11498](https://github.com/rust-lang/cargo/pull/11498)\n- Cargo contributors can write tests in containers.\n  [#11583](https://github.com/rust-lang/cargo/pull/11583)\n\n### Changed\n\n- Cargo now by default saves credentials to `.cargo/credentials.toml`.\n  If `.cargo/credentials` exists, writes to it for backward compatibility reasons.\n  [#11533](https://github.com/rust-lang/cargo/pull/11533)\n- To prevent sensitive data from being logged, Cargo introduces a new wrapper type internally.\n  [#11545](https://github.com/rust-lang/cargo/pull/11545)\n- Several documentation improvements.\n  [#11475](https://github.com/rust-lang/cargo/pull/11475)\n  [#11504](https://github.com/rust-lang/cargo/pull/11504)\n  [#11516](https://github.com/rust-lang/cargo/pull/11516)\n  [#11517](https://github.com/rust-lang/cargo/pull/11517)\n  [#11568](https://github.com/rust-lang/cargo/pull/11568)\n  [#11586](https://github.com/rust-lang/cargo/pull/11586)\n  [#11592](https://github.com/rust-lang/cargo/pull/11592)\n\n### Fixed\n\n- ❗ `cargo package` and `cargo publish` now respects workspace's `Cargo.lock`.\n  This is an expected behavior but previously got overlooked.\n  [#11477](https://github.com/rust-lang/cargo/pull/11477)\n- Fixed `cargo vendor` failing on resolving git dependencies inherited from a workspace.\n  [#11414](https://github.com/rust-lang/cargo/pull/11414)\n- `cargo install` can now correctly install root package when `workspace.default-members` is specified.\n  [#11067](https://github.com/rust-lang/cargo/pull/11067)\n- Fixed panic on target specific dependency errors.\n  [#11541](https://github.com/rust-lang/cargo/pull/11541)\n- Shows `--help` if there is no man page for a subcommand.\n  [#11473](https://github.com/rust-lang/cargo/pull/11473)\n- Setting `target.cfg(…).rustflags` shouldn't erase `build.rustdocflags`.\n  [#11323](https://github.com/rust-lang/cargo/pull/11323)\n- Unsupported `profile.split-debuginfo` options are now ignored,\n  which previously made Cargo fail to compile on certain platforms.\n  [#11347](https://github.com/rust-lang/cargo/pull/11347)\n  [#11633](https://github.com/rust-lang/cargo/pull/11633)\n- Don't panic in Windows headless session with really long file names.\n  [#11759](https://github.com/rust-lang/cargo/pull/11759)\n\n### Nightly only\n\n- Implemented initial support of asymmetric token authentication for registries.\n  ([RFC 3231](https://github.com/rust-lang/rfcs/blob/master/text/3231-cargo-asymmetric-tokens.md))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#registry-auth))\n  [#10771](https://github.com/rust-lang/cargo/pull/10771)\n- Do not error for `auth-required: true` without `-Z sparse-registry`\n  [#11661](https://github.com/rust-lang/cargo/pull/11661)\n- Supports `codegen-backend` and `rustflags` in profiles in config file.\n  [#11562](https://github.com/rust-lang/cargo/pull/11562)\n- Suggests `cargo clippy --fix` when warnings/errors could be fixed with clippy.\n  [#11399](https://github.com/rust-lang/cargo/pull/11399)\n- Fixed artifact deps not working when target field specified coexists with `optional = true`.\n  [#11434](https://github.com/rust-lang/cargo/pull/11434)\n- Make Cargo distinguish `Unit`s with and without artifact targets.\n  [#11478](https://github.com/rust-lang/cargo/pull/11478)\n- `cargo metadata` supports artifact dependencies.\n  [#11550](https://github.com/rust-lang/cargo/pull/11550)\n- Allows builds of some crate to fail during optional doc-scraping.\n  [#11450](https://github.com/rust-lang/cargo/pull/11450)\n- Add warning if potentially-scrapable examples are skipped due to dev-dependencies.\n  [#11503](https://github.com/rust-lang/cargo/pull/11503)\n- Don't scrape examples from library targets by default. \n  [#11499](https://github.com/rust-lang/cargo/pull/11499)\n- Fixed examples of proc-macro crates being scraped for examples.\n  [#11497](https://github.com/rust-lang/cargo/pull/11497)\n\n## Cargo 1.67 (2023-01-26)\n[7e484fc1...rust-1.67.0](https://github.com/rust-lang/cargo/compare/7e484fc1...rust-1.67.0)\n\n### Added\n\n- `cargo remove` now cleans up the referenced dependency of the root\n  workspace manifest, `profile`, `patch`, and `replace` sections\n  after a successful removal of a dependency.\n  [#11194](https://github.com/rust-lang/cargo/pull/11194)\n  [#11242](https://github.com/rust-lang/cargo/pull/11242)\n  [#11351](https://github.com/rust-lang/cargo/pull/11351)\n- `cargo package` and `cargo publish` now report total and compressed crate size\n  after packaging.\n  [#11270](https://github.com/rust-lang/cargo/pull/11270)\n\n### Changed\n\n- ❗ Cargo now reuses the value of `$CARGO` if it's already set in the environment,\n  and forwards the value when executing external subcommands and build scripts.\n  [#11285](https://github.com/rust-lang/cargo/pull/11285)\n- ❗ Cargo now emits an error when running `cargo update --precise` without a `-p` flag.\n  [#11349](https://github.com/rust-lang/cargo/pull/11349)\n- ❗ Cargo now emits an error if there are multiple registries in the configuration with the same index URL.\n  [#10592](https://github.com/rust-lang/cargo/pull/10592)\n- Cargo now is aware of compression ratio when extracting crate files.\n  This relaxes the hard size limit introduced in 1.64.0 to mitigate zip bomb attack.\n  [#11337](https://github.com/rust-lang/cargo/pull/11337)\n- Cargo now errors out when `cargo fix` on a git repo with uncommitted changes.\n  [#11400](https://github.com/rust-lang/cargo/pull/11400)\n- Cargo now warns when `cargo tree -i <spec>` cannot find any package.\n  [#11377](https://github.com/rust-lang/cargo/pull/11377)\n- Cargo now warns when running `cargo new/init` and `PATH` env separator\n  is in the project path.\n  [#11318](https://github.com/rust-lang/cargo/pull/11318)\n- Better error messages when multiple packages were found and \n  `cargo add/remove` gets confused.\n  [#11186](https://github.com/rust-lang/cargo/pull/11186)\n  [#11375](https://github.com/rust-lang/cargo/pull/11375)\n- A better error message when `cargo init` but existing ignore files aren't UTF-8.\n  [#11321](https://github.com/rust-lang/cargo/pull/11321)\n- A better error message for `cargo install .`.\n  [#11401](https://github.com/rust-lang/cargo/pull/11401)\n- A better warning when the same file path found in multiple build targets.\n  [#11299](https://github.com/rust-lang/cargo/pull/11299)\n- Updated the internal HTTP library libcurl with various fixes and updates.\n  [#11307](https://github.com/rust-lang/cargo/pull/11307)\n  [#11326](https://github.com/rust-lang/cargo/pull/11326)\n\n### Fixed\n\n- Fixed `cargo clean` for removing fingerprints and build script\n  artifacts of only the requested package\n  [#10621](https://github.com/rust-lang/cargo/pull/10621)\n- Fixed `cargo install --index` not working when config `registry.default` is set.\n  [#11302](https://github.com/rust-lang/cargo/pull/11302)\n- Fixed git2 safe-directory accidentally disabled when no network configuration was found.\n  [#11366](https://github.com/rust-lang/cargo/pull/11366)\n- Migrate from crate `atty` to resolve potential soundness issue.\n  [#11420](https://github.com/rust-lang/cargo/pull/11420)\n- Cleans stale git temp files left when libgit2 indexing is interrupted.\n  [#11308](https://github.com/rust-lang/cargo/pull/11308)\n\n### Nightly only\n\n- Suggests `cargo fix` when some compilation warnings/errors can be auto-fixed.\n  [#10989](https://github.com/rust-lang/cargo/pull/10989)\n  [#11368](https://github.com/rust-lang/cargo/pull/11368)\n- Changed `rustdoc-scrape-examples` to be a target-level configuration.\n  [#10343](https://github.com/rust-lang/cargo/pull/10343)\n  [#11425](https://github.com/rust-lang/cargo/pull/11425)\n  [#11430](https://github.com/rust-lang/cargo/pull/11430)\n  [#11445](https://github.com/rust-lang/cargo/pull/11445)\n- Propagates change of artifact bin dependency to its parent fingerprint.\n  [#11353](https://github.com/rust-lang/cargo/pull/11353)\n- Fixed `wait-for-publish` to work with sparse registry.\n  [#11356](https://github.com/rust-lang/cargo/pull/11356)\n  [#11327](https://github.com/rust-lang/cargo/pull/11327)\n  [#11388](https://github.com/rust-lang/cargo/pull/11388)\n- Stores the `sparse+` prefix in the `SourceId` for sparse registries \n  [#11387](https://github.com/rust-lang/cargo/pull/11387)\n  [#11403](https://github.com/rust-lang/cargo/pull/11403)\n- Implemented alternative registry authentication support.\n  ([RFC 3139](https://github.com/rust-lang/rfcs/blob/master/text/3139-cargo-alternative-registry-auth.md))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#registry-auth))\n  [#10592](https://github.com/rust-lang/cargo/pull/10592)\n- Added documentation of config option `registries.crates-io.protocol`.\n  [#11350](https://github.com/rust-lang/cargo/pull/11350)\n\n## Cargo 1.66.1 (2023-01-10)\n\n### Fixed\n- 🚨 [CVE-2022-46176](https://github.com/rust-lang/cargo/security/advisories/GHSA-r5w3-xm58-jv6j):\n  Added validation of SSH host keys for git URLs.\n  See [the docs](appendix/git-authentication.md#ssh-known-hosts) for more information on how to configure the known host keys.\n\n## Cargo 1.66 (2022-12-15)\n[08250398...rust-1.66.0](https://github.com/rust-lang/cargo/compare/08250398...rust-1.66.0)\n\n### Added\n\n- 🎉 Added `cargo remove` command for removing dependencies from `Cargo.toml`.\n  [docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-remove.html)\n  [#11059](https://github.com/rust-lang/cargo/pull/11059)\n  [#11099](https://github.com/rust-lang/cargo/pull/11099)\n  [#11193](https://github.com/rust-lang/cargo/pull/11193)\n  [#11204](https://github.com/rust-lang/cargo/pull/11204)\n  [#11227](https://github.com/rust-lang/cargo/pull/11227)\n- Added support for git dependencies having git submodules with relative paths.\n  [#11106](https://github.com/rust-lang/cargo/pull/11106)\n- Cargo now sends requests with an `Accept-Encoding` header to registries.\n  [#11292](https://github.com/rust-lang/cargo/pull/11292)\n- Cargo now forwards non-UTF8 arguments to external subcommands.\n  [#11118](https://github.com/rust-lang/cargo/pull/11118)\n\n### Changed\n\n- ❗ Disambiguate source replacements from various angles.\n  [RFC-3289](https://github.com/rust-lang/rfcs/blob/master/text/3289-source_replacement_ambiguity.md)\n  [#10907](https://github.com/rust-lang/cargo/pull/10907)\n  - When the crates-io source is replaced, the user is required to specify which registry to use with `--registry <NAME>` when performing an API operation.\n  - Publishing to source-replaced crates.io is no longer permitted using the crates.io token (`registry.token`).\n  - In source replacement, the `replace-with` key can reference the name of an alternative registry in the `[registries]` table.\n- ❗ `cargo publish` now blocks until it sees the published package in the index.\n  [#11062](https://github.com/rust-lang/cargo/pull/11062)\n  [#11210](https://github.com/rust-lang/cargo/pull/11210)\n  [#11216](https://github.com/rust-lang/cargo/pull/11216)\n  [#11255](https://github.com/rust-lang/cargo/pull/11255)\n- Cargo now uses the clap v4 library for command-line argument parsing.\n  [#11116](https://github.com/rust-lang/cargo/pull/11116)\n  [#11119](https://github.com/rust-lang/cargo/pull/11119)\n  [#11159](https://github.com/rust-lang/cargo/pull/11159)\n  [#11190](https://github.com/rust-lang/cargo/pull/11190)\n  [#11239](https://github.com/rust-lang/cargo/pull/11239)\n  [#11280](https://github.com/rust-lang/cargo/pull/11280)\n- Cargo now only warns on a user-defined alias shadowing an external command.\n  [#11170](https://github.com/rust-lang/cargo/pull/11170)\n- Several documentation improvements.\n  [#10770](https://github.com/rust-lang/cargo/pull/10770)\n  [#10938](https://github.com/rust-lang/cargo/pull/10938)\n  [#11082](https://github.com/rust-lang/cargo/pull/11082)\n  [#11093](https://github.com/rust-lang/cargo/pull/11093)\n  [#11157](https://github.com/rust-lang/cargo/pull/11157)\n  [#11185](https://github.com/rust-lang/cargo/pull/11185)\n  [#11207](https://github.com/rust-lang/cargo/pull/11207)\n  [#11219](https://github.com/rust-lang/cargo/pull/11219)\n  [#11240](https://github.com/rust-lang/cargo/pull/11240)\n  [#11241](https://github.com/rust-lang/cargo/pull/11241)\n  [#11282](https://github.com/rust-lang/cargo/pull/11282)\n\n### Fixed\n\n- ❗ Config file loaded via `cargo --config <file>` now takes priority over\n  environment variables. This is a documented behaviour but the old\n  implementation accidentally got it wrong.\n  [#11077](https://github.com/rust-lang/cargo/pull/11077)\n- ❗ Cargo collects rustflags in `target.cfg(…).rustflags` more correctly\n  and warns if that's not enough for convergence.\n  [#11114](https://github.com/rust-lang/cargo/pull/11114)\n- Final artifacts not removed by linker should be removed before a compilation gets started.\n  [#11122](https://github.com/rust-lang/cargo/pull/11122)\n- `cargo add` now reports unknown features in a more discoverable manner.\n  [#11098](https://github.com/rust-lang/cargo/pull/11098)\n- Cargo now reports command aliasing failure with more error contexts.\n  [#11087](https://github.com/rust-lang/cargo/pull/11087)\n- A better error message when `cargo login` prompt receives empty input.\n  [#11145](https://github.com/rust-lang/cargo/pull/11145)\n- A better error message for fields with wrong types\n  where workspace inheritance is supported.\n  [#11113](https://github.com/rust-lang/cargo/pull/11113)\n- A better error message when mixing feature syntax `dep:` with `/`.\n  [#11172](https://github.com/rust-lang/cargo/pull/11172)\n- A better error message when publishing but `package.publish` is `false`\n  in the manifest.\n  [#11280](https://github.com/rust-lang/cargo/pull/11280)\n\n### Nightly only\n\n- Added new config option `publish.timeout` behind `-Zpublish-timeout`.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#publish-timeout)\n  [#11230](https://github.com/rust-lang/cargo/pull/11230)\n- Added retry support to sparse registries.\n  [#11069](https://github.com/rust-lang/cargo/pull/11069)\n- Fixed sparse registry lockfile urls containing `registry+sparse+`.\n  [#11177](https://github.com/rust-lang/cargo/pull/11177)\n- Add new config option `registries.crates-io.protocol`\n  for controlling crates.io protocol.\n  [#11215](https://github.com/rust-lang/cargo/pull/11215)\n- Removed `sparse+` prefix for index.crates.io.\n  [#11247](https://github.com/rust-lang/cargo/pull/11247)\n- Fixed publishing with a dependency on a sparse registry.\n  [#11268](https://github.com/rust-lang/cargo/pull/11268)\n- Fixed confusing error messages when using `-Zsparse-registry`.\n  [#11283](https://github.com/rust-lang/cargo/pull/11283)\n- Fixed 410 gone response handling for sparse registries.\n  [#11286](https://github.com/rust-lang/cargo/pull/11286)\n\n## Cargo 1.65 (2022-11-03)\n[4fd148c4...rust-1.65.0](https://github.com/rust-lang/cargo/compare/4fd148c4...rust-1.65.0)\n\n### Added\n\n- External subcommands can now inherit jobserver file descriptors from Cargo.\n  [#10511](https://github.com/rust-lang/cargo/pull/10511)\n- Added an API documentation for private items in cargo-the-library. See\n  <https://doc.rust-lang.org/nightly/nightly-rustc/cargo>.\n  [#11019](https://github.com/rust-lang/cargo/pull/11019)\n\n### Changed\n\n- Cargo now stops adding its bin path to `PATH` if it's already there.\n  [#11023](https://github.com/rust-lang/cargo/pull/11023)\n- Improved the performance of Cargo build scheduling\n  by sorting the queue of pending jobs.\n  [#11032](https://github.com/rust-lang/cargo/pull/11032)\n- Improved the performance fetching git dependencies from GitHub even\n  when using a partial hash in the `rev` field.\n  [#10807](https://github.com/rust-lang/cargo/pull/10807)\n- Cargo now uses git2 v0.15 and libgit2-sys v0.14,\n  which bring several compatibility fixes with git's new behaviors.\n  [#11004](https://github.com/rust-lang/cargo/pull/11004)\n- Registry index files are cached in a more granular way based on content hash.\n  [#11044](https://github.com/rust-lang/cargo/pull/11044)\n- Cargo now uses the standard library's `std::thread::scope` instead of the\n  `crossbeam` crate for spawning scoped threads.\n  [#10977](https://github.com/rust-lang/cargo/pull/10977)\n- Cargo now uses the standard library's `available_parallelism` instead of the\n  `num_cpus` crate for determining the default parallelism.\n  [#10969](https://github.com/rust-lang/cargo/pull/10969)\n- Cargo now guides you how to solve it when seeing an error message of\n  `rust-version` requirement not satisfied.\n  [#10891](https://github.com/rust-lang/cargo/pull/10891)\n- Cargo now tells you more about possible causes and how to fix it\n  when a subcommand cannot be found.\n  [#10924](https://github.com/rust-lang/cargo/pull/10924)\n- Cargo now lists available target names when a given Cargo target cannot be found.\n  [#10999](https://github.com/rust-lang/cargo/pull/10999)\n- `cargo update` now warns if `--precise` is given without `--package` flag.\n  This will become a hard error after a transition period.\n  [#10988](https://github.com/rust-lang/cargo/pull/10988)\n  [#11011](https://github.com/rust-lang/cargo/pull/11011)\n- `cargo bench` and `cargo test` now report a more precise test execution error\n  right after a test fails.\n  [#11028](https://github.com/rust-lang/cargo/pull/11028)\n- `cargo add` now tells you for which version the features are added.\n  [#11075](https://github.com/rust-lang/cargo/pull/11075)\n- Call out that non-ASCII crate names are not supported by Rust anymore.\n  [#11017](https://github.com/rust-lang/cargo/pull/11017)\n- Enhanced the error message when in the manifest a field is expected to be\n  an array but a string is used.\n  [#10944](https://github.com/rust-lang/cargo/pull/10944)\n\n### Fixed\n\n- Removed the restriction on file locking supports on platforms other than Linux.\n  [#10975](https://github.com/rust-lang/cargo/pull/10975)\n- Fixed incorrect OS detection by bumping os_info to 3.5.0.\n  [#10943](https://github.com/rust-lang/cargo/pull/10943)\n- Scanning the package directory now ignores errors from broken\n  but excluded symlink files.\n  [#11008](https://github.com/rust-lang/cargo/pull/11008)\n- Fixed deadlock when build scripts are waiting for input on stdin.\n  [#11257](https://github.com/rust-lang/cargo/pull/11257)\n\n### Nightly\n\n- Progress indicator for sparse registries becomes more straightforward.\n  [#11068](https://github.com/rust-lang/cargo/pull/11068)\n\n## Cargo 1.64 (2022-09-22)\n[a5e08c47...rust-1.64.0](https://github.com/rust-lang/cargo/compare/a5e08c47...rust-1.64.0)\n\n### Added\n\n- 🎉 Packages can now inherit settings from the workspace so that the settings\n  can be centralized in one place. See\n  [`workspace.package`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#the-package-table)\n  and\n  [`workspace.dependencies`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#the-dependencies-table)\n  for more details on how to define these common settings.\n  [#10859](https://github.com/rust-lang/cargo/pull/10859)\n- Added the\n  [`--crate-type`](https://doc.rust-lang.org/nightly/cargo/commands/cargo-rustc.html#option-cargo-rustc---crate-type)\n  flag to `cargo rustc` to override the crate type.\n  [#10838](https://github.com/rust-lang/cargo/pull/10838)\n- Cargo commands can now accept multiple `--target` flags to build for\n  multiple targets at once, and the\n  [`build.target`](https://doc.rust-lang.org/nightly/cargo/reference/config.html#buildtarget)\n  config option may now take an array of multiple targets.\n  [#10766](https://github.com/rust-lang/cargo/pull/10766)\n- The `--jobs` argument can now take a negative number to count backwards from\n  the max CPUs.\n  [#10844](https://github.com/rust-lang/cargo/pull/10844)\n\n### Changed\n- Bash completion of `cargo install --path` now supports path completion.\n  [#10798](https://github.com/rust-lang/cargo/pull/10798)\n- Significantly improved the performance fetching git dependencies from GitHub\n  when using a hash in the `rev` field.\n  [#10079](https://github.com/rust-lang/cargo/pull/10079)\n- Published packages will now include the resolver setting from the workspace\n  to ensure that they use the same resolver when used in isolation.\n  [#10911](https://github.com/rust-lang/cargo/pull/10911)\n  [#10961](https://github.com/rust-lang/cargo/pull/10961)\n  [#10970](https://github.com/rust-lang/cargo/pull/10970)\n- `cargo add` will now update `Cargo.lock`.\n  [#10902](https://github.com/rust-lang/cargo/pull/10902)\n- The path in the config output of `cargo vendor` now translates backslashes\n  to forward slashes so that the settings should work across platforms.\n  [#10668](https://github.com/rust-lang/cargo/pull/10668)\n- The\n  [`workspace.default-members`](https://doc.rust-lang.org/nightly/cargo/reference/workspaces.html#package-selection)\n  setting now allows a value of `\".\"` in a non-virtual workspace to refer to\n  the root package.\n  [#10784](https://github.com/rust-lang/cargo/pull/10784)\n\n### Fixed\n\n- 🚨 [CVE-2022-36113](https://github.com/rust-lang/cargo/security/advisories/GHSA-rfj2-q3h3-hm5j):\n  Extracting malicious crates can corrupt arbitrary files.\n  [#11089](https://github.com/rust-lang/cargo/pull/11089)\n  [#11088](https://github.com/rust-lang/cargo/pull/11088)\n- 🚨 [CVE-2022-36114](https://github.com/rust-lang/cargo/security/advisories/GHSA-2hvr-h6gw-qrxp):\n  Extracting malicious crates can fill the file system.\n  [#11089](https://github.com/rust-lang/cargo/pull/11089)\n  [#11088](https://github.com/rust-lang/cargo/pull/11088)\n- The `os` output in `cargo --version --verbose` now supports more platforms.\n  [#10802](https://github.com/rust-lang/cargo/pull/10802)\n- Cached git checkouts will now be rebuilt if they are corrupted. This may\n  happen when using `net.git-fetch-with-cli` and interrupting the clone\n  process.\n  [#10829](https://github.com/rust-lang/cargo/pull/10829)\n- Fixed panic in `cargo add --offline`.\n  [#10817](https://github.com/rust-lang/cargo/pull/10817)\n\n\n### Nightly only\n- Fixed deserialization of unstable `check-cfg` in `config.toml`.\n  [#10799](https://github.com/rust-lang/cargo/pull/10799)\n\n\n## Cargo 1.63 (2022-08-11)\n[3f052d8e...rust-1.63.0](https://github.com/rust-lang/cargo/compare/3f052d8e...rust-1.63.0)\n\n### Added\n\n- 🎉 Added the `--config` CLI option to pass config options directly on the CLI.\n  [#10755](https://github.com/rust-lang/cargo/pull/10755)\n- The `CARGO_PKG_RUST_VERSION` environment variable is now set when compiling\n  a crate if the manifest has the `rust-version` field set.\n  [#10713](https://github.com/rust-lang/cargo/pull/10713)\n\n\n### Changed\n- A warning is emitted when encountering multiple packages with the same name\n  in a git dependency. This will ignore packages with `publish=false`.\n  [#10701](https://github.com/rust-lang/cargo/pull/10701)\n  [#10767](https://github.com/rust-lang/cargo/pull/10767)\n- Change tracking now uses the contents of a `.json` target spec file instead\n  of its path. This should help avoid rebuilds if the path changes.\n  [#10746](https://github.com/rust-lang/cargo/pull/10746)\n- Git dependencies with a submodule configured with the `update=none` strategy\n  in `.gitmodules` is now honored, and the submodule will not be fetched.\n  [#10717](https://github.com/rust-lang/cargo/pull/10717)\n- Crate files now use a more recent date (Jul 23, 2006 instead of Nov 29, 1973)\n  for deterministic behavior.\n  [#10720](https://github.com/rust-lang/cargo/pull/10720)\n- The initial template used for `cargo new` now includes a slightly more\n  realistic test structure that has `use super::*;` in the test module.\n  [#10706](https://github.com/rust-lang/cargo/pull/10706)\n- Updated the internal HTTP library libcurl with various small fixes and updates.\n  [#10696](https://github.com/rust-lang/cargo/pull/10696)\n\n### Fixed\n- Fix zsh completions for `cargo add` and `cargo locate-project`\n  [#10810](https://github.com/rust-lang/cargo/pull/10810)\n  [#10811](https://github.com/rust-lang/cargo/pull/10811)\n- Fixed `-p` being ignored with `cargo publish` in the root of a virtual\n  workspace. Some additional checks were also added to generate an error if\n  multiple packages were selected (previously it would pick the first one).\n  [#10677](https://github.com/rust-lang/cargo/pull/10677)\n- The human-readable executable name is no longer displayed for `cargo test`\n  when using JSON output.\n  [#10691](https://github.com/rust-lang/cargo/pull/10691)\n\n### Nightly only\n\n- Added `-Zcheck-cfg=output` to support build-scripts declaring their\n  supported set of `cfg` values with `cargo:rustc-check-cfg`.\n  [#10539](https://github.com/rust-lang/cargo/pull/10539)\n- `-Z sparse-registry` now uses https://index.crates.io/ when accessing crates-io.\n  [#10725](https://github.com/rust-lang/cargo/pull/10725)\n- Fixed formatting of `.workspace` key in `cargo add` for workspace inheritance.\n  [#10705](https://github.com/rust-lang/cargo/pull/10705)\n- Sparse HTTP registry URLs must now end with a `/`.\n  [#10698](https://github.com/rust-lang/cargo/pull/10698)\n- Fixed issue with `cargo add` and workspace inheritance of the `default-features` key.\n  [#10685](https://github.com/rust-lang/cargo/pull/10685)\n\n\n\n## Cargo 1.62 (2022-06-30)\n[1ef1e0a1...rust-1.62.0](https://github.com/rust-lang/cargo/compare/1ef1e0a1...rust-1.62.0)\n\n### Added\n\n- 🎉 Added the `cargo add` command for adding dependencies to `Cargo.toml` from\n  the command-line.\n  [docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-add.html)\n  [#10472](https://github.com/rust-lang/cargo/pull/10472)\n  [#10577](https://github.com/rust-lang/cargo/pull/10577)\n  [#10578](https://github.com/rust-lang/cargo/pull/10578)\n- Package ID specs now support `name@version` syntax in addition to the\n  previous `name:version` to align with the behavior in `cargo add` and other\n  tools. `cargo install` and `cargo yank` also now support this syntax so the\n  version does not need to passed as a separate flag.\n  [#10582](https://github.com/rust-lang/cargo/pull/10582)\n  [#10650](https://github.com/rust-lang/cargo/pull/10650)\n  [#10597](https://github.com/rust-lang/cargo/pull/10597)\n- Added the CLI option `-F` as an alias of `--features`.\n  [#10576](https://github.com/rust-lang/cargo/pull/10576)\n- The `git` and `registry` directories in Cargo's home directory (usually\n  `~/.cargo`) are now marked as cache directories so that they are not\n  included in backups or content indexing (on Windows).\n  [#10553](https://github.com/rust-lang/cargo/pull/10553)\n- Added the `--version` flag to `cargo yank` to replace the `--vers` flag to\n  be consistent with `cargo install`.\n  [#10575](https://github.com/rust-lang/cargo/pull/10575)\n- Added automatic `@` argfile support, which will use \"response files\" if the\n  command-line to `rustc` exceeds the operating system's limit.\n  [#10546](https://github.com/rust-lang/cargo/pull/10546)\n- `cargo clean` now has a progress bar (if it takes longer than half a second).\n  [#10236](https://github.com/rust-lang/cargo/pull/10236)\n\n### Changed\n\n- `cargo install` no longer generates an error if no binaries were found\n  to install (such as missing required features).\n  [#10508](https://github.com/rust-lang/cargo/pull/10508)\n- `cargo test` now passes `--target` to `rustdoc` if the specified target is\n  the same as the host target.\n  [#10594](https://github.com/rust-lang/cargo/pull/10594)\n- `cargo doc` now automatically passes `-Arustdoc::private-intra-doc-links`\n  when documenting a binary (which automatically includes\n  `--document-private-items`). The\n  [`private-intra-doc-links`](https://doc.rust-lang.org/rustdoc/lints.html#private_intra_doc_links)\n  lint is only relevant when *not* documenting private items, which doesn't\n  apply to binaries.\n  [#10142](https://github.com/rust-lang/cargo/pull/10142)\n- The length of the short git hash in the `cargo --version` output is now\n  fixed to 9 characters. Previously the length was inconsistent between\n  different platforms.\n  [#10579](https://github.com/rust-lang/cargo/pull/10579)\n- Attempting to publish a package with a `Cargo.toml.orig` file will now\n  result in an error. The filename would otherwise conflict with the\n  automatically-generated file.\n  [#10551](https://github.com/rust-lang/cargo/pull/10551)\n\n### Fixed\n\n- The `build.dep-info-basedir` configuration setting now properly supports the\n  use of `..` in the path to refer to a parent directory.\n  [#10281](https://github.com/rust-lang/cargo/pull/10281)\n- Fixed regression in automatic detection of the default number of CPUs to use\n  on systems using cgroups v1.\n  [#10737](https://github.com/rust-lang/cargo/pull/10737)\n  [#10739](https://github.com/rust-lang/cargo/pull/10739)\n\n\n### Nightly only\n\n- `cargo fetch` now works with `-Zbuild-std` to fetch the standard library's dependencies.\n  [#10129](https://github.com/rust-lang/cargo/pull/10129)\n- Added support for workspace inheritance.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#workspace-inheritance)\n  [#10584](https://github.com/rust-lang/cargo/pull/10584)\n  [#10568](https://github.com/rust-lang/cargo/pull/10568)\n  [#10565](https://github.com/rust-lang/cargo/pull/10565)\n  [#10564](https://github.com/rust-lang/cargo/pull/10564)\n  [#10563](https://github.com/rust-lang/cargo/pull/10563)\n  [#10606](https://github.com/rust-lang/cargo/pull/10606)\n  [#10548](https://github.com/rust-lang/cargo/pull/10548)\n  [#10538](https://github.com/rust-lang/cargo/pull/10538)\n- Added `-Zcheck-cfg` which adds various forms of validating `cfg` expressions\n  for unknown names and values.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg)\n  [#10486](https://github.com/rust-lang/cargo/pull/10486)\n  [#10566](https://github.com/rust-lang/cargo/pull/10566)\n- The `--config` CLI option no longer allows setting a registry token.\n  [#10580](https://github.com/rust-lang/cargo/pull/10580)\n- Fixed issues with proc-macros and `-Z rustdoc-scrape-examples`.\n  [#10549](https://github.com/rust-lang/cargo/pull/10549)\n  [#10533](https://github.com/rust-lang/cargo/pull/10533)\n\n\n## Cargo 1.61 (2022-05-19)\n[ea2a21c9...rust-1.61.0](https://github.com/rust-lang/cargo/compare/ea2a21c9...rust-1.61.0)\n\n### Added\n\n### Changed\n\n- `cargo test --no-run` will now display the path to the test executables.\n  [#10346](https://github.com/rust-lang/cargo/pull/10346)\n- `cargo tree --duplicates` no longer reports dependencies that are shared\n  between the host and the target as duplicates.\n  [#10466](https://github.com/rust-lang/cargo/pull/10466)\n- Updated to the 1.4.2 release of libgit2 which brings in several fixes\n  [#10442](https://github.com/rust-lang/cargo/pull/10442)\n  [#10479](https://github.com/rust-lang/cargo/pull/10479)\n- `cargo vendor` no longer allows multiple values for `--sync`, you must pass\n  multiple `--sync` flags instead.\n  [#10448](https://github.com/rust-lang/cargo/pull/10448)\n- Warnings are now issued for manifest keys that have mixed both underscore\n  and dash variants (such as specifying both `proc_macro` and `proc-macro`)\n  [#10316](https://github.com/rust-lang/cargo/pull/10316)\n- Cargo now uses the standard library's `available_parallelism` instead of the\n  `num_cpus` crate for determining the default parallelism.\n  [#10427](https://github.com/rust-lang/cargo/pull/10427)\n- `cargo search` terms are now highlighted.\n  [#10425](https://github.com/rust-lang/cargo/pull/10425)\n\n### Fixed\n\n- Paths passed to VCS tools like `hg` are now added after `--` to avoid\n  conflict with VCS flags.\n  [#10483](https://github.com/rust-lang/cargo/pull/10483)\n- Fixed the `http.timeout` configuration value to actually work.\n  [#10456](https://github.com/rust-lang/cargo/pull/10456)\n- Fixed issues with `cargo rustc --crate-type` not working in some situations.\n  [#10388](https://github.com/rust-lang/cargo/pull/10388)\n\n### Nightly only\n\n- Added `-Z check-cfg-features` to enable compile-time checking of features\n  [#10408](https://github.com/rust-lang/cargo/pull/10408)\n- Added `-Z bindeps` to support binary artifact dependencies (RFC-3028)\n  [#9992](https://github.com/rust-lang/cargo/pull/9992)\n- `-Z multitarget` is now supported in the `build.target` config value with an array.\n  [#10473](https://github.com/rust-lang/cargo/pull/10473)\n- Added `--keep-going` flag which will continue compilation even if one crate\n  fails to compile.\n  [#10383](https://github.com/rust-lang/cargo/pull/10383)\n- Start work on inheriting manifest values in a workspace.\n  [#10497](https://github.com/rust-lang/cargo/pull/10497)\n  [#10517](https://github.com/rust-lang/cargo/pull/10517)\n- Added support for sparse HTTP registries.\n  [#10470](https://github.com/rust-lang/cargo/pull/10470)\n  [#10064](https://github.com/rust-lang/cargo/pull/10064)\n- Fixed panic when artifact target is used for `[target.'cfg(<target>)'.dependencies]`\n  [#10433](https://github.com/rust-lang/cargo/pull/10433)\n- Fixed host flags to pass to build scripts (`-Z target-applies-to-host`)\n  [#10395](https://github.com/rust-lang/cargo/pull/10395)\n- Added `-Z check-cfg-features` support for rustdoc\n  [#10428](https://github.com/rust-lang/cargo/pull/10428)\n\n\n## Cargo 1.60 (2022-04-07)\n[358e79fe...rust-1.60.0](https://github.com/rust-lang/cargo/compare/358e79fe...rust-1.60.0)\n\n### Added\n\n- 🎉 Added the `dep:` prefix in the `[features]` table to refer to an optional\n  dependency. This allows creating feature names with the same name as a\n  dependency, and allows for \"hiding\" optional dependencies so that they do\n  not implicitly expose a feature name.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/features.html#optional-dependencies)\n  [#10269](https://github.com/rust-lang/cargo/pull/10269)\n- 🎉 Added the `dep-name?/feature-name` syntax to the `[features]` table to\n  only enable the feature `feature-name` if the optional dependency `dep-name`\n  is already enabled by some other feature.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/features.html#dependency-features)\n  [#10269](https://github.com/rust-lang/cargo/pull/10269)\n- 🎉 Added `--timings` option to generate an HTML report about build timing,\n  concurrency, and CPU use.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/timings.html)\n  [#10245](https://github.com/rust-lang/cargo/pull/10245)\n- Added the `\"v\"` and `\"features2\"` fields to the registry index.\n  The `\"v\"` field provides a method for compatibility with future changes to the index.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/registries.html#index-format)\n  [#10269](https://github.com/rust-lang/cargo/pull/10269)\n- Added bash completion for `cargo clippy`\n  [#10347](https://github.com/rust-lang/cargo/pull/10347)\n- Added bash completion for `cargo report`\n  [#10295](https://github.com/rust-lang/cargo/pull/10295)\n- Added support to build scripts for `rustc-link-arg-tests`,\n  `rustc-link-arg-examples`, and `rustc-link-arg-benches`.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#outputs-of-the-build-script)\n  [#10274](https://github.com/rust-lang/cargo/pull/10274)\n\n### Changed\n\n- Cargo now uses the clap 3 library for command-line argument parsing.\n  [#10265](https://github.com/rust-lang/cargo/pull/10265)\n- The `build.pipelining` config option is now deprecated, pipelining will now\n  always be enabled.\n  [#10258](https://github.com/rust-lang/cargo/pull/10258)\n- `cargo new` will now generate a `.gitignore` which only ignores `Cargo.lock`\n  in the root of the repo, instead of any directory.\n  [#10379](https://github.com/rust-lang/cargo/pull/10379)\n- Improved startup time of bash completion.\n  [#10365](https://github.com/rust-lang/cargo/pull/10365)\n- The `--features` flag is now honored when used with the `--all-features`\n  flag, which allows enabling features from other packages.\n  [#10337](https://github.com/rust-lang/cargo/pull/10337)\n- Cargo now uses a different TOML parser. This should not introduce any\n  user-visible changes. This paves the way to support format-preserving\n  programmatic modification of TOML files for supporting `cargo add` and other\n  future enhancements.\n  [#10086](https://github.com/rust-lang/cargo/pull/10086)\n- Setting a library to emit both a `dylib` and `cdylib` is now an error, as\n  this combination is not supported.\n  [#10243](https://github.com/rust-lang/cargo/pull/10243)\n- `cargo --list` now includes the `help` command.\n  [#10300](https://github.com/rust-lang/cargo/pull/10300)\n\n### Fixed\n\n- Fixed running `cargo doc` on examples with dev-dependencies.\n  [#10341](https://github.com/rust-lang/cargo/pull/10341)\n- Fixed `cargo install --path` for a path that is relative to a directory\n  outside of the workspace in the current directory.\n  [#10335](https://github.com/rust-lang/cargo/pull/10335)\n- `cargo test TEST_FILTER` should no longer build binaries that are explicitly\n  disabled with `test = false`.\n  [#10305](https://github.com/rust-lang/cargo/pull/10305)\n- Fixed regression with `term.verbose` without `term.quiet`, and vice versa.\n  [#10429](https://github.com/rust-lang/cargo/pull/10429)\n  [#10436](https://github.com/rust-lang/cargo/pull/10436)\n\n### Nightly only\n\n- Added `rustflags` option to a profile definition.\n  [#10217](https://github.com/rust-lang/cargo/pull/10217)\n- Changed `--config` to only support dotted keys.\n  [#10176](https://github.com/rust-lang/cargo/pull/10176)\n- Fixed profile `rustflags` not being gated in profile overrides.\n  [#10411](https://github.com/rust-lang/cargo/pull/10411)\n  [#10413](https://github.com/rust-lang/cargo/pull/10413)\n\n## Cargo 1.59 (2022-02-24)\n[7f08ace4...rust-1.59.0](https://github.com/rust-lang/cargo/compare/7f08ace4...rust-1.59.0)\n\n### Added\n\n- 🎉 The `strip` option can now be specified in a profile to specify the\n  behavior for removing symbols and debug information from binaries.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/profiles.html#strip)\n  [#10088](https://github.com/rust-lang/cargo/pull/10088)\n  [#10376](https://github.com/rust-lang/cargo/pull/10376)\n- 🎉 Added future incompatible reporting.\n  This provides reporting for when a future change in `rustc` may cause a\n  package or any of its dependencies to stop building.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/future-incompat-report.html)\n  [#10165](https://github.com/rust-lang/cargo/pull/10165)\n- SSH authentication on Windows now supports ssh-agent.\n  [docs](https://doc.rust-lang.org/nightly/cargo/appendix/git-authentication.html#ssh-authentication)\n  [#10248](https://github.com/rust-lang/cargo/pull/10248)\n- Added `term.quiet` configuration option to enable the `--quiet` behavior\n  from a config file.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#termquiet)\n  [#10152](https://github.com/rust-lang/cargo/pull/10152)\n- Added `-r` CLI option as an alias for `--release`.\n  [#10133](https://github.com/rust-lang/cargo/pull/10133)\n\n### Changed\n\n- Scanning the package directory should now be resilient to errors, such as\n  filesystem loops or access issues.\n  [#10188](https://github.com/rust-lang/cargo/pull/10188)\n  [#10214](https://github.com/rust-lang/cargo/pull/10214)\n  [#10286](https://github.com/rust-lang/cargo/pull/10286)\n- `cargo help <alias>` will now show the target of the alias.\n  [#10193](https://github.com/rust-lang/cargo/pull/10193)\n- Removed the deprecated `--host` CLI option.\n  [#10145](https://github.com/rust-lang/cargo/pull/10145)\n  [#10327](https://github.com/rust-lang/cargo/pull/10327)\n- Cargo should now report its version to always be in sync with `rustc`.\n  [#10178](https://github.com/rust-lang/cargo/pull/10178)\n- Added EOPNOTSUPP to ignored file locking errors, which is relevant to BSD\n  operating systems.\n  [#10157](https://github.com/rust-lang/cargo/pull/10157)\n\n### Fixed\n\n- macOS: Fixed an issue where running an executable would sporadically be\n  killed by the kernel (likely starting in macOS 12).\n  [#10196](https://github.com/rust-lang/cargo/pull/10196)\n- Fixed so that the `doc=false` setting is honored in the `[lib]` definition\n  of a dependency.\n  [#10201](https://github.com/rust-lang/cargo/pull/10201)\n  [#10324](https://github.com/rust-lang/cargo/pull/10324)\n- The `\"executable\"` field in the JSON option was incorrectly including the\n  path to `index.html` when documenting a binary. It is now null.\n  [#10171](https://github.com/rust-lang/cargo/pull/10171)\n- Documenting a binary now waits for the package library to finish documenting\n  before starting. This fixes some race conditions if the binary has intra-doc\n  links to the library.\n  [#10172](https://github.com/rust-lang/cargo/pull/10172)\n- Fixed panic when displaying help text to a closed pipe.\n  [#10164](https://github.com/rust-lang/cargo/pull/10164)\n\n### Nightly only\n- Added the `--crate-type` flag to `cargo rustc`.\n  [#10093](https://github.com/rust-lang/cargo/pull/10093)\n\n\n## Cargo 1.58 (2022-01-13)\n[b2e52d7c...rust-1.58.0](https://github.com/rust-lang/cargo/compare/b2e52d7c...rust-1.58.0)\n\n### Added\n\n- Added `rust_version` field to package data in `cargo metadata`.\n  [#9967](https://github.com/rust-lang/cargo/pull/9967)\n- Added `--message-format` option to `cargo install`.\n  [#10107](https://github.com/rust-lang/cargo/pull/10107)\n\n### Changed\n\n- A warning is now shown when an alias shadows an external command.\n  [#10082](https://github.com/rust-lang/cargo/pull/10082)\n- Updated curl to 7.80.0.\n  [#10040](https://github.com/rust-lang/cargo/pull/10040)\n  [#10106](https://github.com/rust-lang/cargo/pull/10106)\n\n### Fixed\n\n- Doctests now include rustc-link-args from build scripts.\n  [#9916](https://github.com/rust-lang/cargo/pull/9916)\n- Fixed `cargo tree` entering an infinite loop with cyclical dev-dependencies.\n  Fixed an edge case where the resolver would fail to handle a cyclical dev-dependency with a feature.\n  [#10103](https://github.com/rust-lang/cargo/pull/10103)\n- Fixed `cargo clean -p` when the directory path contains glob characters.\n  [#10072](https://github.com/rust-lang/cargo/pull/10072)\n- Fixed debug builds of `cargo` which could panic when downloading a crate\n  when the server has a redirect with a non-empty body.\n  [#10048](https://github.com/rust-lang/cargo/pull/10048)\n\n### Nightly only\n\n- Make future-incompat-report output more user-friendly.\n  [#9953](https://github.com/rust-lang/cargo/pull/9953)\n- Added support to scrape code examples from the `examples` directory to be included in the documentation.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#scrape-examples)\n  [#9525](https://github.com/rust-lang/cargo/pull/9525)\n  [#10037](https://github.com/rust-lang/cargo/pull/10037)\n  [#10017](https://github.com/rust-lang/cargo/pull/10017)\n- Fixed `cargo report future-incompatibilities` to check stdout if it supports color.\n  [#10024](https://github.com/rust-lang/cargo/pull/10024)\n\n## Cargo 1.57 (2021-12-02)\n[18751dd3...rust-1.57.0](https://github.com/rust-lang/cargo/compare/18751dd3...rust-1.57.0)\n\n### Added\n\n- 🎉 Added custom named profiles. This also changes the `test` and `bench`\n  profiles to inherit their settings from `dev` and `release`, and Cargo will\n  now only use a single profile during a given command instead of using\n  different profiles for dependencies and cargo-targets.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/profiles.html#custom-profiles)\n  [#9943](https://github.com/rust-lang/cargo/pull/9943)\n- The `rev` option for a git dependency now supports git references that start\n  with `refs/`. An example where this can be used is to depend on a pull\n  request from a service like GitHub before it is merged.\n  [#9859](https://github.com/rust-lang/cargo/pull/9859)\n- Added `path_in_vcs` field to the `.cargo_vcs_info.json` file.\n  [docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-package.html#cargo_vcs_infojson-format)\n  [#9866](https://github.com/rust-lang/cargo/pull/9866)\n\n### Changed\n\n- ❗ `RUSTFLAGS` is no longer set for build scripts. This change was made in\n  1.55, but the release notes did not highlight this change. Build scripts\n  should use `CARGO_ENCODED_RUSTFLAGS` instead. See the\n  [documentation](https://doc.rust-lang.org/nightly/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts)\n  for more details.\n- The `cargo version` command now includes some extra information.\n  [#9968](https://github.com/rust-lang/cargo/pull/9968)\n- Updated libgit2 to 1.3 which brings in a number of fixes and changes to git\n  handling.\n  [#9963](https://github.com/rust-lang/cargo/pull/9963)\n  [#9988](https://github.com/rust-lang/cargo/pull/9988)\n- Shell completions now include shorthand b/r/c/d subcommands.\n  [#9951](https://github.com/rust-lang/cargo/pull/9951)\n- `cargo update --precise` now allows specifying a version without semver\n  metadata (stuff after `+` in the version number).\n  [#9945](https://github.com/rust-lang/cargo/pull/9945)\n- zsh completions now complete `--example` names.\n  [#9939](https://github.com/rust-lang/cargo/pull/9939)\n- The progress bar now differentiates when building unittests.\n  [#9934](https://github.com/rust-lang/cargo/pull/9934)\n- Some backwards-compatibility support for invalid TOML syntax has been removed.\n  [#9932](https://github.com/rust-lang/cargo/pull/9932)\n- Reverted the change from 1.55 that triggered an error for dependency\n  specifications that did not include any fields.\n  [#9911](https://github.com/rust-lang/cargo/pull/9911)\n\n### Fixed\n\n- Removed a log message (from `CARGO_LOG`) that may leak tokens.\n  [#9873](https://github.com/rust-lang/cargo/pull/9873)\n- `cargo fix` will now avoid writing fixes to the global registry cache.\n  [#9938](https://github.com/rust-lang/cargo/pull/9938)\n- Fixed `-Z help` CLI option when used with a shorthand alias (b/c/r/d).\n  [#9933](https://github.com/rust-lang/cargo/pull/9933)\n\n\n### Nightly only\n\n\n## Cargo 1.56 (2021-10-21)\n[cebef295...rust-1.56.0](https://github.com/rust-lang/cargo/compare/cebef295...rust-1.56.0)\n\n### Added\n\n- 🎉 Cargo now supports the 2021 edition.\n  More information may be found in the [edition\n  guide](https://doc.rust-lang.org/nightly/edition-guide/rust-2021/index.html).\n  [#9800](https://github.com/rust-lang/cargo/pull/9800)\n- 🎉 Added the\n  [`rust-version`](https://doc.rust-lang.org/nightly/cargo/reference/manifest.html#the-rust-version-field)\n  field to `Cargo.toml` to specify the minimum supported Rust version, and the\n  `--ignore-rust-version` command line option to override it.\n  [#9732](https://github.com/rust-lang/cargo/pull/9732)\n- Added the `[env]` table to config files to specify environment variables to\n  set.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#env)\n  [#9411](https://github.com/rust-lang/cargo/pull/9411)\n- `[patch]` tables may now be specified in config files.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#patch)\n  [#9839](https://github.com/rust-lang/cargo/pull/9839)\n- `cargo doc` now supports the `--example` and `--examples` flags.\n  [#9808](https://github.com/rust-lang/cargo/pull/9808)\n- 🎉 Build scripts can now pass additional linker arguments for binaries or all\n  linkable targets. [docs](https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#outputs-of-the-build-script)\n  [#9557](https://github.com/rust-lang/cargo/pull/9557)\n- Added support for the `-p` flag for `cargo publish` to publish a specific\n  package in a workspace. `cargo package` also now supports `-p` and\n  `--workspace`.\n  [#9559](https://github.com/rust-lang/cargo/pull/9559)\n- Added documentation about third-party registries.\n  [#9830](https://github.com/rust-lang/cargo/pull/9830)\n- Added the `{sha256-checksum}` placeholder for URLs in a registry `config.json`.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/registries.html#index-format)\n  [#9801](https://github.com/rust-lang/cargo/pull/9801)\n- Added a warning when a dependency does not have a library.\n  [#9771](https://github.com/rust-lang/cargo/pull/9771)\n\n### Changed\n\n- Doc tests now support the `-q` flag to show terse test output.\n  [#9730](https://github.com/rust-lang/cargo/pull/9730)\n- `features` used in a `[replace]` table now issues a warning, as they are ignored.\n  [#9681](https://github.com/rust-lang/cargo/pull/9681)\n- Changed so that only `wasm32-unknown-emscripten` executables are built\n  without a hash in the filename. Previously it was all `wasm32` targets.\n  Additionally, all `apple` binaries are now built with a hash in the\n  filename. This allows multiple copies to be cached at once, and matches the\n  behavior on other platforms (except `msvc`).\n  [#9653](https://github.com/rust-lang/cargo/pull/9653)\n- `cargo new` now generates an example that doesn't generate a warning with\n  clippy.\n  [#9796](https://github.com/rust-lang/cargo/pull/9796)\n- `cargo fix --edition` now only applies edition-specific lints.\n  [#9846](https://github.com/rust-lang/cargo/pull/9846)\n- Improve resolver message to include dependency requirements.\n  [#9827](https://github.com/rust-lang/cargo/pull/9827)\n- `cargo fix` now has more debug logging available with the `CARGO_LOG`\n  environment variable.\n  [#9831](https://github.com/rust-lang/cargo/pull/9831)\n- Changed `cargo fix --edition` to emit a warning when on the latest stable\n  edition when running on stable instead of generating an error.\n  [#9792](https://github.com/rust-lang/cargo/pull/9792)\n- `cargo install` will now determine all of the packages to install before\n  starting the installation, which should help with reporting errors without\n  partially installing.\n  [#9793](https://github.com/rust-lang/cargo/pull/9793)\n- The resolver report for `cargo fix --edition` now includes differences for\n  dev-dependencies.\n  [#9803](https://github.com/rust-lang/cargo/pull/9803)\n- `cargo fix` will now show better diagnostics for abnormal errors from `rustc`.\n  [#9799](https://github.com/rust-lang/cargo/pull/9799)\n- Entries in `cargo --list` are now deduplicated.\n  [#9773](https://github.com/rust-lang/cargo/pull/9773)\n- Aliases are now included in `cargo --list`.\n  [#9764](https://github.com/rust-lang/cargo/pull/9764)\n\n### Fixed\n\n- Fixed panic with build-std of a proc-macro.\n  [#9834](https://github.com/rust-lang/cargo/pull/9834)\n- Fixed running `cargo` recursively from proc-macros while running `cargo fix`.\n  [#9818](https://github.com/rust-lang/cargo/pull/9818)\n- Return an error instead of a stack overflow for command alias loops.\n  [#9791](https://github.com/rust-lang/cargo/pull/9791)\n- Updated to curl 7.79.1, which will hopefully fix intermittent http2 errors.\n  [#9937](https://github.com/rust-lang/cargo/pull/9937)\n\n### Nightly only\n\n- Added `[future-incompat-report]` config section.\n  [#9774](https://github.com/rust-lang/cargo/pull/9774)\n- Fixed value-after-table error with custom named profiles.\n  [#9789](https://github.com/rust-lang/cargo/pull/9789)\n- Added the `different-binary-name` feature to support specifying a\n  non-rust-identifier for a binary name.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#different-binary-name)\n  [#9627](https://github.com/rust-lang/cargo/pull/9627)\n- Added a profile option to select the codegen backend.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#codegen-backend)\n  [#9118](https://github.com/rust-lang/cargo/pull/9118)\n\n\n## Cargo 1.55 (2021-09-09)\n[aa8b0929...rust-1.55.0](https://github.com/rust-lang/cargo/compare/aa8b0929...rust-1.55.0)\n\n### Added\n\n- The package definition in `cargo metadata` now includes the `\"default_run\"`\n  field from the manifest.\n  [#9550](https://github.com/rust-lang/cargo/pull/9550)\n- ❗ Build scripts now have access to the following environment variables:\n  `RUSTC_WRAPPER`, `RUSTC_WORKSPACE_WRAPPER`, `CARGO_ENCODED_RUSTFLAGS`.\n  `RUSTFLAGS` is no longer set for build scripts; they should use\n  `CARGO_ENCODED_RUSTFLAGS` instead.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts)\n  [#9601](https://github.com/rust-lang/cargo/pull/9601)\n- Added `cargo d` as an alias for `cargo doc`.\n  [#9680](https://github.com/rust-lang/cargo/pull/9680)\n- Added `{lib}` to the `cargo tree --format` option to display the library\n  name of a package.\n  [#9663](https://github.com/rust-lang/cargo/pull/9663)\n- Added `members_mut` method to the `Workspace` API.\n  [#9547](https://github.com/rust-lang/cargo/pull/9547)\n\n### Changed\n\n- If a build command does not match any targets when using the\n  `--all-targets`, `--bins`, `--tests`, `--examples`, or `--benches` flags, a\n  warning is now displayed to inform you that there were no matching targets.\n  [#9549](https://github.com/rust-lang/cargo/pull/9549)\n- The way `cargo init` detects whether or not existing source files represent\n  a binary or library has been changed to respect the command-line flags\n  instead of trying to guess which type it is.\n  [#9522](https://github.com/rust-lang/cargo/pull/9522)\n- Registry names are now displayed instead of registry URLs when possible.\n  [#9632](https://github.com/rust-lang/cargo/pull/9632)\n- Duplicate compiler diagnostics are no longer shown. This can often happen\n  with `cargo test` which builds multiple copies of the same code in parallel.\n  This also updates the warning summary to provide more context.\n  [#9675](https://github.com/rust-lang/cargo/pull/9675)\n- The output for warnings or errors is now improved to be leaner, cleaner, and\n  show more context.\n  [#9655](https://github.com/rust-lang/cargo/pull/9655)\n- Network send errors are now treated as \"spurious\" which means they will be retried.\n  [#9695](https://github.com/rust-lang/cargo/pull/9695)\n- Git keys (`branch`, `tag`, `rev`) on a non-git dependency are now an error.\n  Additionally, specifying both `git` and `path` is now an error.\n  [#9689](https://github.com/rust-lang/cargo/pull/9689)\n- Specifying a dependency without any keys is now an error.\n  [#9686](https://github.com/rust-lang/cargo/pull/9686)\n- The resolver now prefers to use `[patch]` table entries of dependencies when\n  possible.\n  [#9639](https://github.com/rust-lang/cargo/pull/9639)\n- Package name typo errors in dependencies are now displayed aligned with the\n  original to help make it easier to see the difference.\n  [#9665](https://github.com/rust-lang/cargo/pull/9665)\n- Windows platforms may now warn on environment variables that have the wrong case.\n  [#9654](https://github.com/rust-lang/cargo/pull/9654)\n- `features` used in a `[patch]` table now issues a warning, as they are ignored.\n  [#9666](https://github.com/rust-lang/cargo/pull/9666)\n- The `target` directory is now excluded from content indexing on Windows.\n  [#9635](https://github.com/rust-lang/cargo/pull/9635)\n- When `Cargo.toml` is not found, the error message now detects if it was\n  misnamed with a lowercase `c` to suggest the correct form.\n  [#9607](https://github.com/rust-lang/cargo/pull/9607)\n- Building `diesel` with the new resolver displays a compatibility notice.\n  [#9602](https://github.com/rust-lang/cargo/pull/9602)\n- Updated the `opener` dependency, which handles opening a web browser, which\n  includes several changes, such as new behavior when run on WSL, and using\n  the system `xdg-open` on Linux.\n  [#9583](https://github.com/rust-lang/cargo/pull/9583)\n- Updated to libcurl 7.78.\n  [#9809](https://github.com/rust-lang/cargo/pull/9809)\n  [#9810](https://github.com/rust-lang/cargo/pull/9810)\n\n### Fixed\n\n- Fixed dep-info files including non-local build script paths.\n  [#9596](https://github.com/rust-lang/cargo/pull/9596)\n- Handle \"jobs = 0\" case in cargo config files\n  [#9584](https://github.com/rust-lang/cargo/pull/9584)\n- Implement warning for ignored trailing arguments after `--`\n  [#9561](https://github.com/rust-lang/cargo/pull/9561)\n- Fixed rustc/rustdoc config values to be config-relative.\n  [#9566](https://github.com/rust-lang/cargo/pull/9566)\n- `cargo fix` now supports rustc's suggestions with multiple spans.\n  [#9567](https://github.com/rust-lang/cargo/pull/9567)\n- `cargo fix` now fixes each target serially instead of in parallel to avoid\n  problems with fixing the same file concurrently.\n  [#9677](https://github.com/rust-lang/cargo/pull/9677)\n- Changes to the target `linker` config value now trigger a rebuild.\n  [#9647](https://github.com/rust-lang/cargo/pull/9647)\n- Git unstaged deleted files are now ignored when using the `--allow-dirty`\n  flag with `cargo publish` or `cargo package`.\n  [#9645](https://github.com/rust-lang/cargo/pull/9645)\n\n### Nightly only\n\n- Enabled support for `cargo fix --edition` for 2021.\n  [#9588](https://github.com/rust-lang/cargo/pull/9588)\n- Several changes to named profiles.\n  [#9685](https://github.com/rust-lang/cargo/pull/9685)\n- Extended instructions on what to do when running `cargo fix --edition` on\n  the 2021 edition.\n  [#9694](https://github.com/rust-lang/cargo/pull/9694)\n- Multiple updates to error messages using nightly features to help better\n  explain the situation.\n  [#9657](https://github.com/rust-lang/cargo/pull/9657)\n- Adjusted the edition 2021 resolver diff report.\n  [#9649](https://github.com/rust-lang/cargo/pull/9649)\n- Fixed error using `cargo doc --open` with `doc.extern-map`.\n  [#9531](https://github.com/rust-lang/cargo/pull/9531)\n- Unified weak and namespaced features.\n  [#9574](https://github.com/rust-lang/cargo/pull/9574)\n- Various updates to future-incompatible reporting.\n  [#9606](https://github.com/rust-lang/cargo/pull/9606)\n- `[env]` environment variables are not allowed to set vars set by Cargo.\n  [#9579](https://github.com/rust-lang/cargo/pull/9579)\n\n## Cargo 1.54 (2021-07-29)\n[4369396c...rust-1.54.0](https://github.com/rust-lang/cargo/compare/4369396c...rust-1.54.0)\n\n### Added\n\n- Fetching from a git repository (such as the crates.io index) now displays\n  the network transfer rate.\n  [#9395](https://github.com/rust-lang/cargo/pull/9395)\n- Added `--prune` option for `cargo tree` to limit what is displayed.\n  [#9520](https://github.com/rust-lang/cargo/pull/9520)\n- Added `--depth` option for `cargo tree` to limit what is displayed.\n  [#9499](https://github.com/rust-lang/cargo/pull/9499)\n- Added `cargo tree -e no-proc-macro` to hide procedural macro dependencies.\n  [#9488](https://github.com/rust-lang/cargo/pull/9488)\n- Added `doc.browser` config option to set which browser to open with `cargo doc --open`.\n  [#9473](https://github.com/rust-lang/cargo/pull/9473)\n- Added `CARGO_TARGET_TMPDIR` environment variable set for integration tests &\n  benches. This provides a temporary or \"scratch\" directory in the `target`\n  directory for tests and benches to use.\n  [#9375](https://github.com/rust-lang/cargo/pull/9375)\n\n### Changed\n\n- `--features` CLI flags now provide typo suggestions with the new feature resolver.\n  [#9420](https://github.com/rust-lang/cargo/pull/9420)\n- Cargo now uses a new parser for SemVer versions. This should behave mostly\n  the same as before with some minor exceptions where invalid syntax for\n  version requirements is now rejected.\n  [#9508](https://github.com/rust-lang/cargo/pull/9508)\n- Mtime handling of `.crate` published packages has changed slightly to avoid\n  mtime values of 0. This was causing problems with lldb which refused to read\n  those files.\n  [#9517](https://github.com/rust-lang/cargo/pull/9517)\n- Improved performance of git status check in `cargo package`.\n  [#9478](https://github.com/rust-lang/cargo/pull/9478)\n- `cargo new` with fossil now places the ignore settings in the new repository\n  instead of using `fossil settings` to set them globally. This also includes\n  several other cleanups to make it more consistent with other VCS\n  configurations.\n  [#9469](https://github.com/rust-lang/cargo/pull/9469)\n- `rustc-cdylib-link-arg` applying transitively displays a warning that this\n  was not intended, and may be an error in the future.\n  [#9563](https://github.com/rust-lang/cargo/pull/9563)\n\n### Fixed\n\n- Fixed `package.exclude` in `Cargo.toml` using inverted exclusions\n  (`!somefile`) when not in a git repository or when vendoring a dependency.\n  [#9186](https://github.com/rust-lang/cargo/pull/9186)\n- Dep-info files now adjust build script `rerun-if-changed` paths to be\n  absolute paths.\n  [#9421](https://github.com/rust-lang/cargo/pull/9421)\n- Fixed a bug when with resolver = \"1\" non-virtual package was allowing\n  unknown features.\n  [#9437](https://github.com/rust-lang/cargo/pull/9437)\n- Fixed an issue with the index cache mishandling versions that only\n  differed in build metadata (such as `110.0.0` and `110.0.0+1.1.0f`).\n  [#9476](https://github.com/rust-lang/cargo/pull/9476)\n- Fixed `cargo install` with a semver metadata version.\n  [#9467](https://github.com/rust-lang/cargo/pull/9467)\n\n### Nightly only\n\n- Added `report` subcommand, and changed `cargo\n  describe-future-incompatibilitie` to `cargo report\n  future-incompatibilities`.\n  [#9438](https://github.com/rust-lang/cargo/pull/9438)\n- Added a `[host]` table to the config files to be able to set build flags for\n  host target. Also added `target-applies-to-host` to control how the\n  `[target]` tables behave.\n  [#9322](https://github.com/rust-lang/cargo/pull/9322)\n- Added some validation to build script `rustc-link-arg-*` instructions to\n  return an error if the target doesn't exist.\n  [#9523](https://github.com/rust-lang/cargo/pull/9523)\n- Added `cargo:rustc-link-arg-bin` instruction for build scripts.\n  [#9486](https://github.com/rust-lang/cargo/pull/9486)\n\n\n## Cargo 1.53 (2021-06-17)\n[90691f2b...rust-1.53.0](https://github.com/rust-lang/cargo/compare/90691f2b...rust-1.53.0)\n\n### Added\n\n### Changed\n- 🔥 Cargo now supports git repositories where the default `HEAD` branch is not\n  \"master\". This also includes a switch to the version 3 `Cargo.lock` format\n  which can handle default branches correctly.\n  [#9133](https://github.com/rust-lang/cargo/pull/9133)\n  [#9397](https://github.com/rust-lang/cargo/pull/9397)\n  [#9384](https://github.com/rust-lang/cargo/pull/9384)\n  [#9392](https://github.com/rust-lang/cargo/pull/9392)\n- 🔥 macOS targets now default to `unpacked` split-debuginfo.\n  [#9298](https://github.com/rust-lang/cargo/pull/9298)\n- ❗ The `authors` field is no longer included in `Cargo.toml` for new\n  projects.\n  [#9282](https://github.com/rust-lang/cargo/pull/9282)\n- `cargo update` may now work with the `--offline` flag.\n  [#9279](https://github.com/rust-lang/cargo/pull/9279)\n- `cargo doc` will now erase the `doc` directory when switching between\n  different toolchain versions. There are shared, unversioned files (such as\n  the search index) that can become broken when using different versions.\n  [#8640](https://github.com/rust-lang/cargo/pull/8640)\n  [#9404](https://github.com/rust-lang/cargo/pull/9404)\n- Improved error messages when path dependency/workspace member is missing.\n  [#9368](https://github.com/rust-lang/cargo/pull/9368)\n\n### Fixed\n- Fixed `cargo doc` detecting if the documentation needs to be rebuilt when\n  changing some settings such as features.\n  [#9419](https://github.com/rust-lang/cargo/pull/9419)\n- `cargo doc` now deletes the output directory for the package before running\n  rustdoc to clear out any stale files.\n  [#9419](https://github.com/rust-lang/cargo/pull/9419)\n- Fixed the `-C metadata` value to always include all information for all\n  builds. Previously, in some situations, the hash only included the package\n  name and version. This fixes some issues, such as incremental builds with\n  split-debuginfo on macOS corrupting the incremental cache in some cases.\n  [#9418](https://github.com/rust-lang/cargo/pull/9418)\n- Fixed man pages not working on Windows if `man` is in `PATH`.\n  [#9378](https://github.com/rust-lang/cargo/pull/9378)\n- The `rustc` cache is now aware of `RUSTC_WRAPPER` and `RUSTC_WORKSPACE_WRAPPER`.\n  [#9348](https://github.com/rust-lang/cargo/pull/9348)\n- Track the `CARGO` environment variable in the rebuild fingerprint if the\n  code uses `env!(\"CARGO\")`.\n  [#9363](https://github.com/rust-lang/cargo/pull/9363)\n\n### Nightly only\n- Fixed config includes not working.\n  [#9299](https://github.com/rust-lang/cargo/pull/9299)\n- Emit note when `--future-incompat-report` had nothing to report.\n  [#9263](https://github.com/rust-lang/cargo/pull/9263)\n- Error messages for nightly features flags (like `-Z` and `cargo-features`)\n  now provides more information.\n  [#9290](https://github.com/rust-lang/cargo/pull/9290)\n- Added the ability to set the target for an individual package in `Cargo.toml`.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#per-package-target)\n  [#9030](https://github.com/rust-lang/cargo/pull/9030)\n- Fixed build-std updating the index on every build.\n  [#9393](https://github.com/rust-lang/cargo/pull/9393)\n- `-Z help` now displays all the `-Z` options.\n  [#9369](https://github.com/rust-lang/cargo/pull/9369)\n- Added `-Zallow-features` to specify which nightly features are allowed to be used.\n  [#9283](https://github.com/rust-lang/cargo/pull/9283)\n- Added `cargo config` subcommand.\n  [#9302](https://github.com/rust-lang/cargo/pull/9302)\n\n## Cargo 1.52 (2021-05-06)\n[34170fcd...rust-1.52.0](https://github.com/rust-lang/cargo/compare/34170fcd...rust-1.52.0)\n\n### Added\n- Added the `\"manifest_path\"` field to JSON messages for a package.\n  [#9022](https://github.com/rust-lang/cargo/pull/9022)\n  [#9247](https://github.com/rust-lang/cargo/pull/9247)\n\n### Changed\n- Build scripts are now forbidden from setting `RUSTC_BOOTSTRAP` on stable.\n  [#9181](https://github.com/rust-lang/cargo/pull/9181)\n  [#9385](https://github.com/rust-lang/cargo/pull/9385)\n- crates.io now supports SPDX 3.11 licenses.\n  [#9209](https://github.com/rust-lang/cargo/pull/9209)\n- An error is now reported if `CARGO_TARGET_DIR` is an empty string.\n  [#8939](https://github.com/rust-lang/cargo/pull/8939)\n- Doc tests now pass the `--message-format` flag into the test so that the\n  \"short\" format can now be used for doc tests.\n  [#9128](https://github.com/rust-lang/cargo/pull/9128)\n- `cargo test` now prints a clearer indicator of which target is currently running.\n  [#9195](https://github.com/rust-lang/cargo/pull/9195)\n- The `CARGO_TARGET_<TRIPLE>` environment variable will now issue a warning if\n  it is using lowercase letters.\n  [#9169](https://github.com/rust-lang/cargo/pull/9169)\n\n### Fixed\n- Fixed publication of packages with metadata and resolver fields in `Cargo.toml`.\n  [#9300](https://github.com/rust-lang/cargo/pull/9300)\n  [#9304](https://github.com/rust-lang/cargo/pull/9304)\n- Fixed logic for determining prefer-dynamic for a dylib which differed in a\n  workspace vs a single package.\n  [#9252](https://github.com/rust-lang/cargo/pull/9252)\n- Fixed an issue where exclusive target-specific dependencies that overlapped\n  across dependency kinds (like regular and build-dependencies) would\n  incorrectly include the dependencies in both.\n  [#9255](https://github.com/rust-lang/cargo/pull/9255)\n- Fixed panic with certain styles of Package IDs when passed to the `-p` flag.\n  [#9188](https://github.com/rust-lang/cargo/pull/9188)\n- When running cargo with output not going to a TTY, and with the progress bar\n  and color force-enabled, the output will now correctly clear the progress\n  line.\n  [#9231](https://github.com/rust-lang/cargo/pull/9231)\n- Error instead of panic when JSON may contain non-utf8 paths.\n  [#9226](https://github.com/rust-lang/cargo/pull/9226)\n- Fixed a hang that can happen on broken stderr.\n  [#9201](https://github.com/rust-lang/cargo/pull/9201)\n- Fixed thin-local LTO not being disabled correctly when `lto=off` is set.\n  [#9182](https://github.com/rust-lang/cargo/pull/9182)\n\n### Nightly only\n- The `strip` profile option now supports `true` and `false` values.\n  [#9153](https://github.com/rust-lang/cargo/pull/9153)\n- `cargo fix --edition` now displays a report when switching to 2021 if the\n  new resolver changes features.\n  [#9268](https://github.com/rust-lang/cargo/pull/9268)\n- Added `[patch]` table support in `.cargo/config` files.\n  [#9204](https://github.com/rust-lang/cargo/pull/9204)\n- Added `cargo describe-future-incompatibilities` for generating a report on\n  dependencies that contain future-incompatible warnings.\n  [#8825](https://github.com/rust-lang/cargo/pull/8825)\n- Added easier support for testing the 2021 edition.\n  [#9184](https://github.com/rust-lang/cargo/pull/9184)\n- Switch the default resolver to \"2\" in the 2021 edition.\n  [#9184](https://github.com/rust-lang/cargo/pull/9184)\n- `cargo fix --edition` now supports 2021.\n  [#9184](https://github.com/rust-lang/cargo/pull/9184)\n- Added `--print` flag to `cargo rustc` to pass along to `rustc` to display\n  information from rustc.\n  [#9002](https://github.com/rust-lang/cargo/pull/9002)\n- Added `-Zdoctest-in-workspace` for changing the directory where doctests are\n  *run* versus where they are *compiled*.\n  [#9105](https://github.com/rust-lang/cargo/pull/9105)\n- Added support for an `[env]` section in `.cargo/config.toml` to set\n  environment variables when running cargo.\n  [#9175](https://github.com/rust-lang/cargo/pull/9175)\n- Added a schema field and `features2` field to the index.\n  [#9161](https://github.com/rust-lang/cargo/pull/9161)\n- Changes to JSON spec targets will now trigger a rebuild.\n  [#9223](https://github.com/rust-lang/cargo/pull/9223)\n\n## Cargo 1.51 (2021-03-25)\n[75d5d8cf...rust-1.51.0](https://github.com/rust-lang/cargo/compare/75d5d8cf...rust-1.51.0)\n\n### Added\n- 🔥 Added the `split-debuginfo` profile option.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/profiles.html#split-debuginfo)\n  [#9112](https://github.com/rust-lang/cargo/pull/9112)\n- Added the `path` field to `cargo metadata` for the package dependencies list\n  to show the path for \"path\" dependencies.\n  [#8994](https://github.com/rust-lang/cargo/pull/8994)\n- 🔥 Added a new feature resolver, and new CLI feature flag behavior. See the\n  new [features](https://doc.rust-lang.org/nightly/cargo/reference/features.html#feature-resolver-version-2)\n  and [resolver](https://doc.rust-lang.org/nightly/cargo/reference/resolver.html#feature-resolver-version-2)\n  documentation for the `resolver = \"2\"` option. See the\n  [CLI](https://doc.rust-lang.org/nightly/cargo/reference/features.html#command-line-feature-options)\n  and [resolver 2 CLI](https://doc.rust-lang.org/nightly/cargo/reference/features.html#resolver-version-2-command-line-flags)\n  options for the new CLI behavior. And, finally, see\n  [RFC 2957](https://github.com/rust-lang/rfcs/blob/master/text/2957-cargo-features2.md)\n  for a detailed look at what has changed.\n  [#8997](https://github.com/rust-lang/cargo/pull/8997)\n\n### Changed\n- `cargo install --locked` now emits a warning if `Cargo.lock` is not found.\n  [#9108](https://github.com/rust-lang/cargo/pull/9108)\n- Unknown or ambiguous package IDs passed on the command-line now display\n  suggestions for the correct package ID.\n  [#9095](https://github.com/rust-lang/cargo/pull/9095)\n- Slightly optimize `cargo vendor`\n  [#8937](https://github.com/rust-lang/cargo/pull/8937)\n  [#9131](https://github.com/rust-lang/cargo/pull/9131)\n  [#9132](https://github.com/rust-lang/cargo/pull/9132)\n\n### Fixed\n- Fixed environment variables and cfg settings emitted by a build script that\n  are set for `cargo test` and `cargo run` when the build script runs multiple\n  times during the same build session.\n  [#9122](https://github.com/rust-lang/cargo/pull/9122)\n- Fixed a panic with `cargo doc` and the new feature resolver. This also\n  introduces some heuristics to try to avoid path collisions with `rustdoc` by\n  only documenting one variant of a package if there are multiple (such as\n  multiple versions, or the same package shared for host and target\n  platforms).\n  [#9077](https://github.com/rust-lang/cargo/pull/9077)\n- Fixed a bug in Cargo's cyclic dep graph detection that caused a stack\n  overflow.\n  [#9075](https://github.com/rust-lang/cargo/pull/9075)\n- Fixed build script `links` environment variables (`DEP_*`) not showing up\n  for testing packages in some cases.\n  [#9065](https://github.com/rust-lang/cargo/pull/9065)\n- Fixed features being selected in a nondeterministic way for a specific\n  scenario when building an entire workspace with all targets with a\n  proc-macro in the workspace with `resolver=\"2\"`.\n  [#9059](https://github.com/rust-lang/cargo/pull/9059)\n- Fixed to use `http.proxy` setting in `~/.gitconfig`.\n  [#8986](https://github.com/rust-lang/cargo/pull/8986)\n- Fixed --feature pkg/feat for V1 resolver for non-member.\n  [#9275](https://github.com/rust-lang/cargo/pull/9275)\n  [#9277](https://github.com/rust-lang/cargo/pull/9277)\n- Fixed panic in `cargo doc` when there are colliding output filenames in a workspace.\n  [#9276](https://github.com/rust-lang/cargo/pull/9276)\n  [#9277](https://github.com/rust-lang/cargo/pull/9277)\n- Fixed `cargo install` from exiting with success if one of several packages\n  did not install successfully.\n  [#9185](https://github.com/rust-lang/cargo/pull/9185)\n  [#9196](https://github.com/rust-lang/cargo/pull/9196)\n- Fix panic with doc collision orphan.\n  [#9142](https://github.com/rust-lang/cargo/pull/9142)\n  [#9196](https://github.com/rust-lang/cargo/pull/9196)\n\n### Nightly only\n- Removed the `publish-lockfile` unstable feature, it was stabilized without\n  the need for an explicit flag 1.5 years ago.\n  [#9092](https://github.com/rust-lang/cargo/pull/9092)\n- Added better diagnostics, help messages, and documentation for nightly\n  features (such as those passed with the `-Z` flag, or specified with\n  `cargo-features` in `Cargo.toml`).\n  [#9092](https://github.com/rust-lang/cargo/pull/9092)\n- Added support for Rust edition 2021.\n  [#8922](https://github.com/rust-lang/cargo/pull/8922)\n- Added support for the `rust-version` field in project metadata.\n  [#8037](https://github.com/rust-lang/cargo/pull/8037)\n- Added a schema field to the index.\n  [#9161](https://github.com/rust-lang/cargo/pull/9161)\n  [#9196](https://github.com/rust-lang/cargo/pull/9196)\n\n## Cargo 1.50 (2021-02-11)\n[8662ab42...rust-1.50.0](https://github.com/rust-lang/cargo/compare/8662ab42...rust-1.50.0)\n\n### Added\n- Added the `doc` field to `cargo metadata`, which indicates if a target is\n  documented.\n  [#8869](https://github.com/rust-lang/cargo/pull/8869)\n- Added `RUSTC_WORKSPACE_WRAPPER`, an alternate RUSTC wrapper that only runs\n  for the local workspace packages, and caches its artifacts independently of\n  non-wrapped builds.\n  [#8976](https://github.com/rust-lang/cargo/pull/8976)\n- Added `--workspace` to `cargo update` to update only the workspace members,\n  and not their dependencies. This is particularly useful if you update the\n  version in `Cargo.toml` and want to update `Cargo.lock` without running any\n  other commands.\n  [#8725](https://github.com/rust-lang/cargo/pull/8725)\n\n### Changed\n- `.crate` files uploaded to a registry are now built with reproducible\n  settings, so that the same `.crate` file created on different machines\n  should be identical.\n  [#8864](https://github.com/rust-lang/cargo/pull/8864)\n- Git dependencies that specify more than one of `branch`, `tag`, or `rev` are\n  now rejected.\n  [#8984](https://github.com/rust-lang/cargo/pull/8984)\n- The `rerun-if-changed` build script directive can now point to a directory,\n  in which case Cargo will check if any file in that directory changes.\n  [#8973](https://github.com/rust-lang/cargo/pull/8973)\n- If Cargo cannot determine the username or email address, `cargo new` will no\n  longer fail, and instead create an empty authors list.\n  [#8912](https://github.com/rust-lang/cargo/pull/8912)\n- The progress bar width has been reduced to provide more room to display the\n  crates currently being built.\n  [#8892](https://github.com/rust-lang/cargo/pull/8892)\n- `cargo new` will now support `includeIf` directives in `.gitconfig` to match\n  the correct directory when determining the username and email address.\n  [#8886](https://github.com/rust-lang/cargo/pull/8886)\n\n### Fixed\n- Fixed `cargo metadata` and `cargo tree` to only download packages for the\n  requested target.\n  [#8987](https://github.com/rust-lang/cargo/pull/8987)\n- Updated libgit2, which brings in many fixes, particularly fixing a zlib\n  error that occasionally appeared on 32-bit systems.\n  [#8998](https://github.com/rust-lang/cargo/pull/8998)\n- Fixed stack overflow with a circular dev-dependency that uses the `links`\n  field.\n  [#8969](https://github.com/rust-lang/cargo/pull/8969)\n- Fixed `cargo publish` failing on some filesystems, particularly 9p on WSL2.\n  [#8950](https://github.com/rust-lang/cargo/pull/8950)\n\n### Nightly only\n- Allow `resolver=\"1\"` to specify the original feature resolution behavior.\n  [#8857](https://github.com/rust-lang/cargo/pull/8857)\n- Added `-Z extra-link-arg` which adds the `cargo:rustc-link-arg-bins`\n  and `cargo:rustc-link-arg` build script options.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#extra-link-arg)\n  [#8441](https://github.com/rust-lang/cargo/pull/8441)\n- Implemented external credential process support, and added `cargo logout`.\n  ([RFC 2730](https://github.com/rust-lang/rfcs/blob/master/text/2730-cargo-token-from-process.md))\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#credential-process))\n  [#8934](https://github.com/rust-lang/cargo/pull/8934)\n- Fix panic with `-Zbuild-std` and no roots.\n  [#8942](https://github.com/rust-lang/cargo/pull/8942)\n- Set docs.rs as the default extern-map for crates.io\n  [#8877](https://github.com/rust-lang/cargo/pull/8877)\n\n## Cargo 1.49 (2020-12-31)\n[75615f8e...rust-1.49.0](https://github.com/rust-lang/cargo/compare/75615f8e...rust-1.49.0)\n\n### Added\n- Added `homepage` and `documentation` fields to `cargo metadata`.\n  [#8744](https://github.com/rust-lang/cargo/pull/8744)\n- Added the `CARGO_PRIMARY_PACKAGE` environment variable which is set when\n  running `rustc` if the package is one of the \"root\" packages selected on the\n  command line.\n  [#8758](https://github.com/rust-lang/cargo/pull/8758)\n- Added support for Unix-style glob patterns for package and target selection\n  flags on the command-line (such as `-p 'serde*'` or `--test '*'`).\n  [#8752](https://github.com/rust-lang/cargo/pull/8752)\n\n### Changed\n- Computed LTO flags are now included in the filename metadata hash so that\n  changes in LTO settings will independently cache build artifacts instead of\n  overwriting previous ones. This prevents rebuilds in some situations such as\n  switching between `cargo build` and `cargo test` in some circumstances.\n  [#8755](https://github.com/rust-lang/cargo/pull/8755)\n- `cargo tree` now displays `(proc-macro)` next to proc-macro packages.\n  [#8765](https://github.com/rust-lang/cargo/pull/8765)\n- Added a warning that the allowed characters for a feature name have been\n  restricted to letters, digits, `_`, `-`, and `+` to accommodate future\n  syntax changes. This is still a superset of the allowed syntax on crates.io,\n  which requires ASCII. This is intended to be changed to an error in the\n  future.\n  [#8814](https://github.com/rust-lang/cargo/pull/8814)\n- `-p` without a value will now print a list of workspace package names.\n  [#8808](https://github.com/rust-lang/cargo/pull/8808)\n- Add period to allowed feature name characters.\n  [#8932](https://github.com/rust-lang/cargo/pull/8932)\n  [#8943](https://github.com/rust-lang/cargo/pull/8943)\n\n### Fixed\n- Fixed building a library with both \"dylib\" and \"rlib\" crate types with LTO enabled.\n  [#8754](https://github.com/rust-lang/cargo/pull/8754)\n- Fixed paths in Cargo's dep-info files.\n  [#8819](https://github.com/rust-lang/cargo/pull/8819)\n- Fixed inconsistent source IDs in `cargo metadata` for git dependencies that\n  explicitly specify `branch=\"master\"`.\n  [#8824](https://github.com/rust-lang/cargo/pull/8824)\n- Fixed re-extracting dependencies which contained a `.cargo-ok` file.\n  [#8835](https://github.com/rust-lang/cargo/pull/8835)\n\n### Nightly only\n- Fixed a panic with `cargo doc -Zfeatures=itarget` in some situations.\n  [#8777](https://github.com/rust-lang/cargo/pull/8777)\n- New implementation for namespaced features, using the syntax `dep:serde`.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#namespaced-features)\n  [#8799](https://github.com/rust-lang/cargo/pull/8799)\n- Added support for \"weak\" dependency features, using the syntax\n  `dep_name?/feat_name`, which will enable a feature for a dependency without\n  also enabling the dependency.\n  [#8818](https://github.com/rust-lang/cargo/pull/8818)\n- Fixed the new feature resolver downloading extra dependencies that weren't\n  strictly necessary.\n  [#8823](https://github.com/rust-lang/cargo/pull/8823)\n\n## Cargo 1.48 (2020-11-19)\n[51b66125...rust-1.48.0](https://github.com/rust-lang/cargo/compare/51b66125...rust-1.48.0)\n\n### Added\n- Added `term.progress` configuration option to control when and how the\n  progress bar is displayed.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#termprogresswhen)\n  [#8165](https://github.com/rust-lang/cargo/pull/8165)\n- Added `--message-format plain` option to `cargo locate-project` to display\n  the project location without JSON to make it easier to use in a script.\n  [#8707](https://github.com/rust-lang/cargo/pull/8707)\n- Added `--workspace` option to `cargo locate-project` to display the path to\n  the workspace manifest.\n  [#8712](https://github.com/rust-lang/cargo/pull/8712)\n- A new contributor guide has been added for contributing to Cargo itself.\n  This is published at <https://rust-lang.github.io/cargo/contrib/>.\n  [#8715](https://github.com/rust-lang/cargo/pull/8715)\n- Zsh `--target` completion will now complete with the built-in rustc targets.\n  [#8740](https://github.com/rust-lang/cargo/pull/8740)\n\n### Changed\n\n### Fixed\n- Fixed `cargo new` creating a fossil repository to properly ignore the `target` directory.\n  [#8671](https://github.com/rust-lang/cargo/pull/8671)\n- Don't show warnings about the workspace in the current directory when using `cargo install`\n  of a remote package.\n  [#8681](https://github.com/rust-lang/cargo/pull/8681)\n- Automatically reinitialize the index when an \"Object not found\" error is\n  encountered in the git repository.\n  [#8735](https://github.com/rust-lang/cargo/pull/8735)\n- Updated libgit2, which brings in several fixes for git repository handling.\n  [#8778](https://github.com/rust-lang/cargo/pull/8778)\n  [#8780](https://github.com/rust-lang/cargo/pull/8780)\n\n### Nightly only\n- Fixed `cargo install` so that it will ignore the `[unstable]` table in local config files.\n  [#8656](https://github.com/rust-lang/cargo/pull/8656)\n- Fixed nondeterministic behavior of the new feature resolver.\n  [#8701](https://github.com/rust-lang/cargo/pull/8701)\n- Fixed running `cargo test` on a proc-macro with the new feature resolver\n  under a specific combination of circumstances.\n  [#8742](https://github.com/rust-lang/cargo/pull/8742)\n\n## Cargo 1.47 (2020-10-08)\n[4f74d9b2...rust-1.47.0](https://github.com/rust-lang/cargo/compare/4f74d9b2...rust-1.47.0)\n\n### Added\n- `cargo doc` will now include the package's version in the left sidebar.\n  [#8509](https://github.com/rust-lang/cargo/pull/8509)\n- Added the `test` field to `cargo metadata` targets.\n  [#8478](https://github.com/rust-lang/cargo/pull/8478)\n- Cargo's man pages are now displayed via the `cargo help` command (such as\n  `cargo help build`).\n  [#8456](https://github.com/rust-lang/cargo/pull/8456)\n  [#8577](https://github.com/rust-lang/cargo/pull/8577)\n- Added new documentation chapters on [how dependency resolution\n  works](https://doc.rust-lang.org/nightly/cargo/reference/resolver.html) and\n  [SemVer\n  compatibility](https://doc.rust-lang.org/nightly/cargo/reference/semver.html),\n  along with suggestions on how to version your project and work with\n  dependencies.\n  [#8609](https://github.com/rust-lang/cargo/pull/8609)\n\n### Changed\n- The comments added to `.gitignore` when it is modified have been tweaked to\n  add some spacing.\n  [#8476](https://github.com/rust-lang/cargo/pull/8476)\n- `cargo metadata` output should now be sorted to be deterministic.\n  [#8489](https://github.com/rust-lang/cargo/pull/8489)\n- By default, build scripts and proc-macros are now built with `opt-level=0`\n  and the default codegen units, even in release mode.\n  [#8500](https://github.com/rust-lang/cargo/pull/8500)\n- `workspace.default-members` is now filtered by `workspace.exclude`.\n  [#8485](https://github.com/rust-lang/cargo/pull/8485)\n- `workspace.members` globs now ignore non-directory paths.\n  [#8511](https://github.com/rust-lang/cargo/pull/8511)\n- git zlib errors now trigger a retry.\n  [#8520](https://github.com/rust-lang/cargo/pull/8520)\n- \"http\" class git errors now trigger a retry.\n  [#8553](https://github.com/rust-lang/cargo/pull/8553)\n- git dependencies now override the `core.autocrlf` git configuration value to\n  ensure they behave consistently across platforms, particularly when\n  vendoring git dependencies on Windows.\n  [#8523](https://github.com/rust-lang/cargo/pull/8523)\n- If `Cargo.lock` needs to be updated, then it will be automatically\n  transitioned to the new V2 format. This format removes the `[metadata]`\n  table, and should be easier to merge changes in source control systems. This\n  format was introduced in 1.38, and made the default for new projects in\n  1.41.\n  [#8554](https://github.com/rust-lang/cargo/pull/8554)\n- Added preparation for support of git repositories with a non-\"master\"\n  default branch. Actual support will arrive in a future version. This\n  introduces some warnings:\n  - Warn if a git dependency does not specify a branch, and the default branch\n    on the repository is not \"master\". In the future, Cargo will fetch the\n    default branch. In this scenario, the branch should be explicitly\n    specified.\n  - Warn if a workspace has multiple dependencies to the same git repository,\n    one without a `branch` and one with `branch=\"master\"`. Dependencies should\n    all use one form or the other.\n  [#8522](https://github.com/rust-lang/cargo/pull/8522)\n- Warnings are now issued if a `required-features` entry lists a feature that\n  does not exist.\n  [#7950](https://github.com/rust-lang/cargo/pull/7950)\n- Built-in aliases are now included in `cargo --list`.\n  [#8542](https://github.com/rust-lang/cargo/pull/8542)\n- `cargo install` with a specific version that has been yanked will now\n  display an error message that it has been yanked, instead of \"could not\n  find\".\n  [#8565](https://github.com/rust-lang/cargo/pull/8565)\n- `cargo publish` with a package that has the `publish` field set to a single\n  registry, and no `--registry` flag has been given, will now publish to that\n  registry instead of generating an error.\n  [#8571](https://github.com/rust-lang/cargo/pull/8571)\n\n### Fixed\n- Fixed issue where if a project directory was moved, and one of the\n  build scripts did not use the `rerun-if-changed` directive, then that\n  build script was being rebuilt when it shouldn't.\n  [#8497](https://github.com/rust-lang/cargo/pull/8497)\n- Console colors should now work on Windows 7 and 8.\n  [#8540](https://github.com/rust-lang/cargo/pull/8540)\n- The `CARGO_TARGET_{triplet}_RUNNER` environment variable will now correctly\n  override the config file instead of trying to merge the commands.\n  [#8629](https://github.com/rust-lang/cargo/pull/8629)\n- Fixed LTO with doctests.\n  [#8657](https://github.com/rust-lang/cargo/pull/8657)\n  [#8658](https://github.com/rust-lang/cargo/pull/8658)\n\n### Nightly only\n- Added support for `-Z terminal-width` which tells `rustc` the width of the\n  terminal so that it can format diagnostics better.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#terminal-width)\n  [#8427](https://github.com/rust-lang/cargo/pull/8427)\n- Added ability to configure `-Z` unstable flags in config files via the\n  `[unstable]` table.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html)\n  [#8393](https://github.com/rust-lang/cargo/pull/8393)\n- Added `-Z build-std-features` flag to set features for the standard library.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std-features)\n  [#8490](https://github.com/rust-lang/cargo/pull/8490)\n\n## Cargo 1.46 (2020-08-27)\n[9fcb8c1d...rust-1.46.0](https://github.com/rust-lang/cargo/compare/9fcb8c1d...rust-1.46.0)\n\n### Added\n- The `dl` key in `config.json` of a registry index now supports the\n  replacement markers `{prefix}` and `{lowerprefix}` to allow spreading crates\n  across directories similar to how the index itself is structured.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/registries.html#index-format)\n  [#8267](https://github.com/rust-lang/cargo/pull/8267)\n- Added new environment variables that are set during compilation:\n  - `CARGO_CRATE_NAME`: The name of the crate being built.\n  - `CARGO_BIN_NAME`: The name of the executable binary (if this is a binary crate).\n  - `CARGO_PKG_LICENSE`: The `license` field from the manifest.\n  - `CARGO_PKG_LICENSE_FILE`: The `license-file` field from the manifest.\n  [#8270](https://github.com/rust-lang/cargo/pull/8270)\n  [#8325](https://github.com/rust-lang/cargo/pull/8325)\n  [#8387](https://github.com/rust-lang/cargo/pull/8387)\n- If the value for `readme` is not specified in `Cargo.toml`, it is now\n  automatically inferred from the existence of a file named `README`,\n  `README.md`, or `README.txt`. This can be suppressed by setting\n  `readme = false`.\n  [#8277](https://github.com/rust-lang/cargo/pull/8277)\n- `cargo install` now supports the `--index` flag to install directly from an index.\n  [#8344](https://github.com/rust-lang/cargo/pull/8344)\n- Added the `metadata` table to the `workspace` definition in `Cargo.toml`.\n  This can be used for arbitrary data similar to the `package.metadata` table.\n  [#8323](https://github.com/rust-lang/cargo/pull/8323)\n- Added the `--target-dir` flag to `cargo install` to set the target directory.\n  [#8391](https://github.com/rust-lang/cargo/pull/8391)\n- Changes to environment variables used by the\n  [`env!`](https://doc.rust-lang.org/std/macro.env.html) or\n  [`option_env!`](https://doc.rust-lang.org/std/macro.option_env.html) macros\n  are now automatically detected to trigger a rebuild.\n  [#8421](https://github.com/rust-lang/cargo/pull/8421)\n- The `target` directory now includes the `CACHEDIR.TAG` file which is used by\n  some tools to exclude the directory from backups.\n  [#8378](https://github.com/rust-lang/cargo/pull/8378)\n- Added docs about rustup's `+toolchain` syntax.\n  [#8455](https://github.com/rust-lang/cargo/pull/8455)\n\n### Changed\n- A warning is now displayed if a git dependency includes a `#` fragment in\n  the URL. This was potentially confusing because Cargo itself displays git\n  URLs with this syntax, but it does not have any meaning outside of the\n  `Cargo.lock` file, and would not work properly.\n  [#8297](https://github.com/rust-lang/cargo/pull/8297)\n- Various optimizations and fixes for bitcode embedding and LTO.\n  [#8349](https://github.com/rust-lang/cargo/pull/8349)\n- Reduced the amount of data fetched for git dependencies. If Cargo knows the\n  branch or tag to fetch, it will now only fetch that branch or tag instead of\n  all branches and tags.\n  [#8363](https://github.com/rust-lang/cargo/pull/8363)\n- Enhanced git fetch error messages.\n  [#8409](https://github.com/rust-lang/cargo/pull/8409)\n- `.crate` files are now generated with GNU tar format instead of UStar, which\n  supports longer file names.\n  [#8453](https://github.com/rust-lang/cargo/pull/8453)\n\n### Fixed\n- Fixed a rare situation where an update to `Cargo.lock` failed once, but then\n  subsequent runs allowed it proceed.\n  [#8274](https://github.com/rust-lang/cargo/pull/8274)\n- Removed assertion that Windows dylibs must have a `.dll` extension. Some\n  custom JSON spec targets may change the extension.\n  [#8310](https://github.com/rust-lang/cargo/pull/8310)\n- Updated libgit2, which brings in a fix for zlib errors for some remote\n  git servers like googlesource.com.\n  [#8320](https://github.com/rust-lang/cargo/pull/8320)\n- Fixed the GitHub fast-path check for up-to-date git dependencies on\n  non-master branches.\n  [#8363](https://github.com/rust-lang/cargo/pull/8363)\n- Fixed issue when enabling a feature with `pkg/feature` syntax, and `pkg` is\n  an optional dependency, but also a dev-dependency, and the dev-dependency\n  appears before the optional normal dependency in the registry summary, then\n  the optional dependency would not get activated.\n  [#8395](https://github.com/rust-lang/cargo/pull/8395)\n- Fixed `clean -p` deleting the build directory if there is a test named\n  `build`.\n  [#8398](https://github.com/rust-lang/cargo/pull/8398)\n- Fixed indentation of multi-line Cargo error messages.\n  [#8409](https://github.com/rust-lang/cargo/pull/8409)\n- Fixed issue where the automatic inclusion of the `--document-private-items`\n  flag for rustdoc would override any flags passed to the `cargo rustdoc`\n  command.\n  [#8449](https://github.com/rust-lang/cargo/pull/8449)\n- Cargo will now include a version in the hash of the fingerprint directories\n  to support backwards-incompatible changes to the fingerprint structure.\n  [#8473](https://github.com/rust-lang/cargo/pull/8473)\n  [#8488](https://github.com/rust-lang/cargo/pull/8488)\n\n### Nightly only\n- Added `-Zrustdoc-map` feature which provides external mappings for rustdoc\n  (such as https://docs.rs/ links).\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#rustdoc-map)\n  [#8287](https://github.com/rust-lang/cargo/pull/8287)\n- Fixed feature calculation when a proc-macro is declared in `Cargo.toml` with\n  an underscore (like `proc_macro = true`).\n  [#8319](https://github.com/rust-lang/cargo/pull/8319)\n- Added support for setting `-Clinker` with `-Zdoctest-xcompile`.\n  [#8359](https://github.com/rust-lang/cargo/pull/8359)\n- Fixed setting the `strip` profile field in config files.\n  [#8454](https://github.com/rust-lang/cargo/pull/8454)\n\n## Cargo 1.45 (2020-07-16)\n[ebda5065e...rust-1.45.0](https://github.com/rust-lang/cargo/compare/ebda5065...rust-1.45.0)\n\n### Added\n\n### Changed\n- Changed official documentation to recommend `.cargo/config.toml` filenames\n  (with the `.toml` extension). `.toml` extension support was added in 1.39.\n  [#8121](https://github.com/rust-lang/cargo/pull/8121)\n- The `registry.index` config value is no longer allowed (it has been\n  deprecated for 4 years).\n  [#7973](https://github.com/rust-lang/cargo/pull/7973)\n- An error is generated if both `--index` and `--registry` are passed\n  (previously `--index` was silently ignored).\n  [#7973](https://github.com/rust-lang/cargo/pull/7973)\n- The `registry.token` config value is no longer used with the `--index` flag.\n  This is intended to avoid potentially leaking the crates.io token to another\n  registry.\n  [#7973](https://github.com/rust-lang/cargo/pull/7973)\n- Added a warning if `registry.token` is used with source replacement. It is\n  intended this will be an error in future versions.\n  [#7973](https://github.com/rust-lang/cargo/pull/7973)\n- Windows GNU targets now copy `.dll.a` import library files for DLL crate\n  types to the output directory.\n  [#8141](https://github.com/rust-lang/cargo/pull/8141)\n- Dylibs for all dependencies are now unconditionally copied to the output\n  directory. Some obscure scenarios can cause an old dylib to be referenced\n  between builds, and this ensures that all the latest copies are used.\n  [#8139](https://github.com/rust-lang/cargo/pull/8139)\n- `package.exclude` can now match directory names. If a directory is\n  specified, the entire directory will be excluded, and Cargo will not attempt\n  to inspect it further. Previously Cargo would try to check every file in the\n  directory which could cause problems if the directory contained unreadable\n  files.\n  [#8095](https://github.com/rust-lang/cargo/pull/8095)\n- When packaging with `cargo publish` or `cargo package`, Cargo can use git to\n  guide its decision on which files to include. Previously this git-based\n  logic required a `Cargo.toml` file to exist at the root of the repository.\n  This is no longer required, so Cargo will now use git-based guidance even if\n  there is not a `Cargo.toml` in the root of the repository.\n  [#8095](https://github.com/rust-lang/cargo/pull/8095)\n- While unpacking a crate on Windows, if it fails to write a file because the\n  file is a reserved Windows filename (like \"aux.rs\"), Cargo will display an\n  extra message to explain why it failed.\n  [#8136](https://github.com/rust-lang/cargo/pull/8136)\n- Failures to set mtime on files are now ignored. Some filesystems did not\n  support this.\n  [#8185](https://github.com/rust-lang/cargo/pull/8185)\n- Certain classes of git errors will now recommend enabling\n  `net.git-fetch-with-cli`.\n  [#8166](https://github.com/rust-lang/cargo/pull/8166)\n- When doing an LTO build, Cargo will now instruct rustc not to perform\n  codegen when possible. This may result in a faster build and use less disk\n  space. Additionally, for non-LTO builds, Cargo will instruct rustc to not\n  embed LLVM bitcode in libraries, which should decrease their size.\n  [#8192](https://github.com/rust-lang/cargo/pull/8192)\n  [#8226](https://github.com/rust-lang/cargo/pull/8226)\n  [#8254](https://github.com/rust-lang/cargo/pull/8254)\n- The implementation for `cargo clean -p` has been rewritten so that it can\n  more accurately remove the files for a specific package.\n  [#8210](https://github.com/rust-lang/cargo/pull/8210)\n- The way Cargo computes the outputs from a build has been rewritten to be\n  more complete and accurate. Newly tracked files will be displayed in JSON\n  messages, and may be uplifted to the output directory in some cases. Some of\n  the changes from this are:\n\n  - `.exp` export files on Windows MSVC dynamic libraries are now tracked.\n  - Proc-macros on Windows track import/export files.\n  - All targets (like tests, etc.) that generate separate debug files\n    (pdb/dSYM) are tracked.\n  - Added .map files for wasm32-unknown-emscripten.\n  - macOS dSYM directories are tracked for all dynamic libraries\n    (dylib/cdylib/proc-macro) and for build scripts.\n\n  There are a variety of other changes as a consequence of this:\n\n  - Binary examples on Windows MSVC with a hyphen will now show up twice in\n    the examples directory (`foo_bar.exe` and `foo-bar.exe`). Previously Cargo\n    just renamed the file instead of hard-linking it.\n  - Example libraries now follow the same rules for hyphen/underscore\n    translation as normal libs (they will now use underscores).\n\n  [#8210](https://github.com/rust-lang/cargo/pull/8210)\n- Cargo attempts to scrub any secrets from the debug log for HTTP debugging.\n  [#8222](https://github.com/rust-lang/cargo/pull/8222)\n- Context has been added to many of Cargo's filesystem operations, so that\n  error messages now provide more information, such as the path that caused\n  the problem.\n  [#8232](https://github.com/rust-lang/cargo/pull/8232)\n- Several commands now ignore the error if stdout or stderr is closed while it\n  is running. For example `cargo install --list | grep -q cargo-fuzz` would\n  previously sometimes panic because `grep -q` may close stdout before the\n  command finishes. Regular builds continue to fail if stdout or stderr is\n  closed, matching the behavior of many other build systems.\n  [#8236](https://github.com/rust-lang/cargo/pull/8236)\n- If `cargo install` is given an exact version, like `--version=1.2.3`, it\n  will now avoid updating the index if that version is already installed, and\n  exit quickly indicating it is already installed.\n  [#8022](https://github.com/rust-lang/cargo/pull/8022)\n- Changes to the `[patch]` section will now attempt to automatically update\n  `Cargo.lock` to the new version. It should now also provide better error\n  messages for the rare cases where it is unable to automatically update.\n  [#8248](https://github.com/rust-lang/cargo/pull/8248)\n\n### Fixed\n- Fixed copying Windows `.pdb` files to the output directory when the filename\n  contained dashes.\n  [#8123](https://github.com/rust-lang/cargo/pull/8123)\n- Fixed error where Cargo would fail when scanning if a package is inside a\n  git repository when any of its ancestor paths is a symlink.\n  [#8186](https://github.com/rust-lang/cargo/pull/8186)\n- Fixed `cargo update` with an unused `[patch]` so that it does not get\n  stuck and refuse to update.\n  [#8243](https://github.com/rust-lang/cargo/pull/8243)\n- Fixed a situation where Cargo would hang if stderr is closed, and the\n  compiler generated a large number of messages.\n  [#8247](https://github.com/rust-lang/cargo/pull/8247)\n- Fixed backtraces on macOS not showing filenames or line numbers. As a\n  consequence of this, binary executables on apple targets do not include a\n  hash in the filename in Cargo's cache. This means Cargo can only track one\n  copy, so if you switch features or rustc versions, Cargo will need to\n  rebuild the executable.\n  [#8329](https://github.com/rust-lang/cargo/pull/8329)\n  [#8335](https://github.com/rust-lang/cargo/pull/8335)\n- Fixed fingerprinting when using lld on Windows with a dylib. Cargo was\n  erroneously thinking the dylib was never fresh.\n  [#8290](https://github.com/rust-lang/cargo/pull/8290)\n  [#8335](https://github.com/rust-lang/cargo/pull/8335)\n\n### Nightly only\n- Fixed passing the full path for `--target` to `rustdoc` when using JSON spec\n  targets.\n  [#8094](https://github.com/rust-lang/cargo/pull/8094)\n- `-Cembed-bitcode=no` renamed to `-Cbitcode-in-rlib=no`\n  [#8134](https://github.com/rust-lang/cargo/pull/8134)\n- Added new `resolver` field to `Cargo.toml` to opt-in to the new feature\n  resolver.\n  [#8129](https://github.com/rust-lang/cargo/pull/8129)\n- `-Zbuild-std` no longer treats std dependencies as \"local\". This means that\n  it won't use incremental compilation for those dependencies, removes them\n  from dep-info files, and caps lints at \"allow\".\n  [#8177](https://github.com/rust-lang/cargo/pull/8177)\n- Added `-Zmultitarget` which allows multiple `--target` flags to build the\n  same thing for multiple targets at once.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#multitarget)\n  [#8167](https://github.com/rust-lang/cargo/pull/8167)\n- Added `strip` option to the profile to remove symbols and debug information.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-strip-option)\n  [#8246](https://github.com/rust-lang/cargo/pull/8246)\n- Fixed panic with `cargo tree --target=all -Zfeatures=all`.\n  [#8269](https://github.com/rust-lang/cargo/pull/8269)\n\n## Cargo 1.44 (2020-06-04)\n[bda50510...rust-1.44.0](https://github.com/rust-lang/cargo/compare/bda50510...rust-1.44.0)\n\n### Added\n- 🔥 Added the `cargo tree` command.\n  [docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-tree.html)\n  [#8062](https://github.com/rust-lang/cargo/pull/8062)\n- Added warnings if a package has Windows-restricted filenames (like `nul`,\n  `con`, `aux`, `prn`, etc.).\n  [#7959](https://github.com/rust-lang/cargo/pull/7959)\n- Added a `\"build-finished\"` JSON message when compilation is complete so that\n  tools can detect when they can stop listening for JSON messages with\n  commands like `cargo run` or `cargo test`.\n  [#8069](https://github.com/rust-lang/cargo/pull/8069)\n\n### Changed\n- Valid package names are now restricted to Unicode XID identifiers. This is\n  mostly the same as before, except package names cannot start with a number\n  or `-`.\n  [#7959](https://github.com/rust-lang/cargo/pull/7959)\n- `cargo new` and `init` will warn or reject additional package names\n  (reserved Windows names, reserved Cargo directories, non-ASCII names,\n  conflicting std names like `core`, etc.).\n  [#7959](https://github.com/rust-lang/cargo/pull/7959)\n- Tests are no longer hard-linked into the output directory (`target/debug/`).\n  This ensures tools will have access to debug symbols and execute tests in\n  the same way as Cargo. Tools should use JSON messages to discover the path\n  to the executable.\n  [#7965](https://github.com/rust-lang/cargo/pull/7965)\n- Updating git submodules now displays an \"Updating\" message for each\n  submodule.\n  [#7989](https://github.com/rust-lang/cargo/pull/7989)\n- File modification times are now preserved when extracting a `.crate` file.\n  This reverses the change made in 1.40 where the mtime was not preserved.\n  [#7935](https://github.com/rust-lang/cargo/pull/7935)\n- Build script warnings are now displayed separately when the build script\n  fails.\n  [#8017](https://github.com/rust-lang/cargo/pull/8017)\n- Removed the `git-checkout` subcommand.\n  [#8040](https://github.com/rust-lang/cargo/pull/8040)\n- The progress bar is now enabled for all unix platforms. Previously it was\n  only Linux, macOS, and FreeBSD.\n  [#8054](https://github.com/rust-lang/cargo/pull/8054)\n- Artifacts generated by pre-release versions of `rustc` now share the same\n  filenames. This means that changing nightly versions will not leave stale\n  files in the build directory.\n  [#8073](https://github.com/rust-lang/cargo/pull/8073)\n- Invalid package names are rejected when using renamed dependencies.\n  [#8090](https://github.com/rust-lang/cargo/pull/8090)\n- Added a certain class of HTTP2 errors as \"spurious\" that will get retried.\n  [#8102](https://github.com/rust-lang/cargo/pull/8102)\n- Allow `cargo package --list` to succeed, even if there are other validation\n  errors (such as `Cargo.lock` generation problem, or missing dependencies).\n  [#8175](https://github.com/rust-lang/cargo/pull/8175)\n  [#8215](https://github.com/rust-lang/cargo/pull/8215)\n\n### Fixed\n- Cargo no longer buffers excessive amounts of compiler output in memory.\n  [#7838](https://github.com/rust-lang/cargo/pull/7838)\n- Symbolic links in git repositories now work on Windows.\n  [#7996](https://github.com/rust-lang/cargo/pull/7996)\n- Fixed an issue where `profile.dev` was not loaded from a config file with\n  `cargo test` when the `dev` profile was not defined in `Cargo.toml`.\n  [#8012](https://github.com/rust-lang/cargo/pull/8012)\n- When a binary is built as an implicit dependency of an integration test,\n  it now checks `dep_name/feature_name` syntax in `required-features` correctly.\n  [#8020](https://github.com/rust-lang/cargo/pull/8020)\n- Fixed an issue where Cargo would not detect that an executable (such as an\n  integration test) needs to be rebuilt when the previous build was\n  interrupted with Ctrl-C.\n  [#8087](https://github.com/rust-lang/cargo/pull/8087)\n- Protect against some (unknown) situations where Cargo could panic when the\n  system monotonic clock doesn't appear to be monotonic.\n  [#8114](https://github.com/rust-lang/cargo/pull/8114)\n- Fixed panic with `cargo clean -p` if the package has a build script.\n  [#8216](https://github.com/rust-lang/cargo/pull/8216)\n\n### Nightly only\n- Fixed panic with new feature resolver and required-features.\n  [#7962](https://github.com/rust-lang/cargo/pull/7962)\n- Added `RUSTC_WORKSPACE_WRAPPER` environment variable, which provides a way\n  to wrap `rustc` for workspace members only, and affects the filename hash so\n  that artifacts produced by the wrapper are cached separately. This usage can\n  be seen on nightly clippy with `cargo clippy -Zunstable-options`.\n  [#7533](https://github.com/rust-lang/cargo/pull/7533)\n- Added `--unit-graph` CLI option to display Cargo's internal dependency graph\n  as JSON.\n  [#7977](https://github.com/rust-lang/cargo/pull/7977)\n- Changed `-Zbuild_dep` to `-Zhost_dep`, and added proc-macros to the feature\n  decoupling logic.\n  [#8003](https://github.com/rust-lang/cargo/pull/8003)\n  [#8028](https://github.com/rust-lang/cargo/pull/8028)\n- Fixed so that `--crate-version` is not automatically passed when the flag\n  is found in `RUSTDOCFLAGS`.\n  [#8014](https://github.com/rust-lang/cargo/pull/8014)\n- Fixed panic with `-Zfeatures=dev_dep` and `check --profile=test`.\n  [#8027](https://github.com/rust-lang/cargo/pull/8027)\n- Fixed panic with `-Zfeatures=itarget` with certain host dependencies.\n  [#8048](https://github.com/rust-lang/cargo/pull/8048)\n- Added support for `-Cembed-bitcode=no`, which provides a performance boost\n  and disk-space usage reduction for non-LTO builds.\n  [#8066](https://github.com/rust-lang/cargo/pull/8066)\n- `-Zpackage-features` has been extended with several changes intended to make\n  it easier to select features on the command-line in a workspace.\n  [#8074](https://github.com/rust-lang/cargo/pull/8074)\n\n## Cargo 1.43 (2020-04-23)\n[9d32b7b0...rust-1.43.0](https://github.com/rust-lang/cargo/compare/9d32b7b0...rust-1.43.0)\n\n### Added\n- 🔥 Profiles may now be specified in config files (and environment variables).\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/config.html#profile)\n  [#7823](https://github.com/rust-lang/cargo/pull/7823)\n- ❗ Added `CARGO_BIN_EXE_<name>` environment variable when building\n  integration tests. This variable contains the path to any `[[bin]]` targets\n  in the package. Integration tests should use the `env!` macro to determine\n  the path to a binary to execute.\n  [docs](https://doc.rust-lang.org/nightly/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates)\n  [#7697](https://github.com/rust-lang/cargo/pull/7697)\n\n### Changed\n- `cargo install --git` now honors workspaces in a git repository. This allows\n  workspace settings, like `[patch]`, `[replace]`, or `[profile]` to be used.\n  [#7768](https://github.com/rust-lang/cargo/pull/7768)\n- `cargo new` will now run `rustfmt` on the new files to pick up rustfmt\n  settings like `tab_spaces` so that the new file matches the user's preferred\n  indentation settings.\n  [#7827](https://github.com/rust-lang/cargo/pull/7827)\n- Environment variables printed with \"very verbose\" output (`-vv`) are now\n  consistently sorted.\n  [#7877](https://github.com/rust-lang/cargo/pull/7877)\n- Debug logging for fingerprint rebuild-detection now includes more information.\n  [#7888](https://github.com/rust-lang/cargo/pull/7888)\n  [#7890](https://github.com/rust-lang/cargo/pull/7890)\n  [#7952](https://github.com/rust-lang/cargo/pull/7952)\n- Added warning during publish if the license-file doesn't exist.\n  [#7905](https://github.com/rust-lang/cargo/pull/7905)\n- The `license-file` file is automatically included during publish, even if it\n  is not explicitly listed in the `include` list or is in a location outside\n  of the root of the package.\n  [#7905](https://github.com/rust-lang/cargo/pull/7905)\n- `CARGO_CFG_DEBUG_ASSERTIONS` and `CARGO_CFG_PROC_MACRO` are no longer set\n  when running a build script. These were inadvertently set in the past, but\n  had no meaning as they were always true. Additionally, `cfg(proc-macro)`\n  is no longer supported in a `target` expression.\n  [#7943](https://github.com/rust-lang/cargo/pull/7943)\n  [#7970](https://github.com/rust-lang/cargo/pull/7970)\n\n### Fixed\n- Global command-line flags now work with aliases (like `cargo -v b`).\n  [#7837](https://github.com/rust-lang/cargo/pull/7837)\n- Required-features using dependency syntax (like `renamed_dep/feat_name`) now\n  handle renamed dependencies correctly.\n  [#7855](https://github.com/rust-lang/cargo/pull/7855)\n- Fixed a rare situation where if a build script is run multiple times during\n  the same build, Cargo will now keep the results separate instead of losing\n  the output of the first execution.\n  [#7857](https://github.com/rust-lang/cargo/pull/7857)\n- Fixed incorrect interpretation of environment variable\n  `CARGO_TARGET_*_RUNNER=true` as a boolean. Also improved related env var\n  error messages.\n  [#7891](https://github.com/rust-lang/cargo/pull/7891)\n- Updated internal libgit2 library, bringing various fixes to git support.\n  [#7939](https://github.com/rust-lang/cargo/pull/7939)\n- `cargo package` / `cargo publish` should no longer buffer the entire\n  contents of each file in memory.\n  [#7946](https://github.com/rust-lang/cargo/pull/7946)\n- Ignore more invalid `Cargo.toml` files in a git dependency. Cargo currently\n  walks the entire repo to find the requested package. Certain invalid\n  manifests were already skipped, and now it should skip all of them.\n  [#7947](https://github.com/rust-lang/cargo/pull/7947)\n\n### Nightly only\n- Added `build.out-dir` config variable to set the output directory.\n  [#7810](https://github.com/rust-lang/cargo/pull/7810)\n- Added `-Zjobserver-per-rustc` feature to support improved performance for\n  parallel rustc.\n  [#7731](https://github.com/rust-lang/cargo/pull/7731)\n- Fixed filename collision with `build-std` and crates like `cc`.\n  [#7860](https://github.com/rust-lang/cargo/pull/7860)\n- `-Ztimings` will now save its report even if there is an error.\n  [#7872](https://github.com/rust-lang/cargo/pull/7872)\n- Updated `--config` command-line flag to support taking a path to a config\n  file to load.\n  [#7901](https://github.com/rust-lang/cargo/pull/7901)\n- Added new feature resolver.\n  [#7820](https://github.com/rust-lang/cargo/pull/7820)\n- Rustdoc docs now automatically include the version of the package in the\n  side bar (requires `-Z crate-versions` flag).\n  [#7903](https://github.com/rust-lang/cargo/pull/7903)\n\n## Cargo 1.42 (2020-03-12)\n[0bf7aafe...rust-1.42.0](https://github.com/rust-lang/cargo/compare/0bf7aafe...rust-1.42.0)\n\n### Added\n- Added documentation on git authentication.\n  [#7658](https://github.com/rust-lang/cargo/pull/7658)\n- Bitbucket Pipeline badges are now supported on crates.io.\n  [#7663](https://github.com/rust-lang/cargo/pull/7663)\n- `cargo vendor` now accepts the `--versioned-dirs` option to force it to\n  always include the version number in each package's directory name.\n  [#7631](https://github.com/rust-lang/cargo/pull/7631)\n- The `proc_macro` crate is now automatically added to the extern prelude for\n  proc-macro packages. This means that `extern crate proc_macro;` is no longer\n  necessary for proc-macros.\n  [#7700](https://github.com/rust-lang/cargo/pull/7700)\n\n### Changed\n- Emit a warning if `debug_assertions`, `test`, `proc_macro`, or `feature=` is\n  used in a `cfg()` expression.\n  [#7660](https://github.com/rust-lang/cargo/pull/7660)\n- Large update to the Cargo documentation, adding new chapters on Cargo\n  targets, workspaces, and features.\n  [#7733](https://github.com/rust-lang/cargo/pull/7733)\n- Windows: `.lib` DLL import libraries are now copied next to the dll for all\n  Windows MSVC targets. Previously it was only supported for\n  `pc-windows-msvc`. This adds DLL support for `uwp-windows-msvc` targets.\n  [#7758](https://github.com/rust-lang/cargo/pull/7758)\n- The `ar` field in the `[target]` configuration is no longer read. It has\n  been ignored for over 4 years.\n  [#7763](https://github.com/rust-lang/cargo/pull/7763)\n- Bash completion file simplified and updated for latest changes.\n  [#7789](https://github.com/rust-lang/cargo/pull/7789)\n- Credentials are only loaded when needed, instead of every Cargo command.\n  [#7774](https://github.com/rust-lang/cargo/pull/7774)\n\n### Fixed\n- Removed `--offline` empty index check, which was a false positive in some\n  cases.\n  [#7655](https://github.com/rust-lang/cargo/pull/7655)\n- Files and directories starting with a `.` can now be included in a package\n  by adding it to the `include` list.\n  [#7680](https://github.com/rust-lang/cargo/pull/7680)\n- Fixed `cargo login` removing alternative registry tokens when previous\n  entries existed in the credentials file.\n  [#7708](https://github.com/rust-lang/cargo/pull/7708)\n- Fixed `cargo vendor` from panicking when used with alternative registries.\n  [#7718](https://github.com/rust-lang/cargo/pull/7718)\n- Fixed incorrect explanation in the fingerprint debug log message.\n  [#7749](https://github.com/rust-lang/cargo/pull/7749)\n- A `[source]` that is defined multiple times will now result in an error.\n  Previously it was randomly picking a source, which could cause\n  non-deterministic behavior.\n  [#7751](https://github.com/rust-lang/cargo/pull/7751)\n- `dep_kinds` in `cargo metadata` are now de-duplicated.\n  [#7756](https://github.com/rust-lang/cargo/pull/7756)\n- Fixed packaging where `Cargo.lock` was listed in `.gitignore` in a\n  subdirectory inside a git repository. Previously it was assuming\n  `Cargo.lock` was at the root of the repo.\n  [#7779](https://github.com/rust-lang/cargo/pull/7779)\n- Partial file transfer errors will now cause an automatic retry.\n  [#7788](https://github.com/rust-lang/cargo/pull/7788)\n- Linux: Fixed panic if CPU iowait stat decreases.\n  [#7803](https://github.com/rust-lang/cargo/pull/7803)\n- Fixed using the wrong sysroot for detecting host compiler settings when\n  `--sysroot` is passed in via `RUSTFLAGS`.\n  [#7798](https://github.com/rust-lang/cargo/pull/7798)\n\n### Nightly only\n- `build-std` now uses `--extern` instead of `--sysroot` to find sysroot\n  packages.\n  [#7699](https://github.com/rust-lang/cargo/pull/7699)\n- Added `--config` command-line option to set config settings.\n  [#7649](https://github.com/rust-lang/cargo/pull/7649)\n- Added `include` config setting which allows including another config file.\n  [#7649](https://github.com/rust-lang/cargo/pull/7649)\n- Profiles in config files now support any named profile. Previously it was\n  limited to dev/release.\n  [#7750](https://github.com/rust-lang/cargo/pull/7750)\n\n## Cargo 1.41 (2020-01-30)\n[5da4b4d4...rust-1.41.0](https://github.com/rust-lang/cargo/compare/5da4b4d4...rust-1.41.0)\n\n### Added\n- 🔥 Cargo now uses a new `Cargo.lock` file format. This new format should\n  support easier merges in source control systems. Projects using the old\n  format will continue to use the old format, only new `Cargo.lock` files will\n  use the new format.\n  [#7579](https://github.com/rust-lang/cargo/pull/7579)\n- 🔥 `cargo install` will now upgrade already installed packages instead of\n  failing.\n  [#7560](https://github.com/rust-lang/cargo/pull/7560)\n- 🔥 Profile overrides have been added. This allows overriding profiles for\n  individual dependencies or build scripts. See [the\n  documentation](https://doc.rust-lang.org/nightly/cargo/reference/profiles.html#overrides)\n  for more.\n  [#7591](https://github.com/rust-lang/cargo/pull/7591)\n- Added new documentation for build scripts.\n  [#7565](https://github.com/rust-lang/cargo/pull/7565)\n- Added documentation for Cargo's JSON output.\n  [#7595](https://github.com/rust-lang/cargo/pull/7595)\n- Significant expansion of config and environment variable documentation.\n  [#7650](https://github.com/rust-lang/cargo/pull/7650)\n- Add back support for `BROWSER` environment variable for `cargo doc --open`.\n  [#7576](https://github.com/rust-lang/cargo/pull/7576)\n- Added `kind` and `platform` for dependencies in `cargo metadata`.\n  [#7132](https://github.com/rust-lang/cargo/pull/7132)\n- The `OUT_DIR` value is now included in the `build-script-executed` JSON message.\n  [#7622](https://github.com/rust-lang/cargo/pull/7622)\n\n### Changed\n- `cargo doc` will now document private items in binaries by default.\n  [#7593](https://github.com/rust-lang/cargo/pull/7593)\n- Subcommand typo suggestions now include aliases.\n  [#7486](https://github.com/rust-lang/cargo/pull/7486)\n- Tweak how the \"already existing...\" comment is added to `.gitignore`.\n  [#7570](https://github.com/rust-lang/cargo/pull/7570)\n- Ignore `cargo login` text from copy/paste in token.\n  [#7588](https://github.com/rust-lang/cargo/pull/7588)\n- Windows: Ignore errors for locking files when not supported by the filesystem.\n  [#7602](https://github.com/rust-lang/cargo/pull/7602)\n- Remove `**/*.rs.bk` from `.gitignore`.\n  [#7647](https://github.com/rust-lang/cargo/pull/7647)\n\n### Fixed\n- Fix unused warnings for some keys in the `build` config section.\n  [#7575](https://github.com/rust-lang/cargo/pull/7575)\n- Linux: Don't panic when parsing `/proc/stat`.\n  [#7580](https://github.com/rust-lang/cargo/pull/7580)\n- Don't show canonical path in `cargo vendor`.\n  [#7629](https://github.com/rust-lang/cargo/pull/7629)\n\n### Nightly only\n\n\n## Cargo 1.40 (2019-12-19)\n[1c6ec66d...5da4b4d4](https://github.com/rust-lang/cargo/compare/1c6ec66d...5da4b4d4)\n\n### Added\n- Added `http.ssl-version` config option to control the version of TLS,\n  along with min/max versions.\n  [#7308](https://github.com/rust-lang/cargo/pull/7308)\n- 🔥 Compiler warnings are now cached on disk. If a build generates warnings,\n  re-running the build will now re-display the warnings.\n  [#7450](https://github.com/rust-lang/cargo/pull/7450)\n- Added `--filter-platform` option to `cargo metadata` to narrow the nodes\n  shown in the resolver graph to only packages included for the given target\n  triple.\n  [#7376](https://github.com/rust-lang/cargo/pull/7376)\n\n### Changed\n- Cargo's \"platform\" `cfg` parsing has been extracted into a separate crate\n  named `cargo-platform`.\n  [#7375](https://github.com/rust-lang/cargo/pull/7375)\n- Dependencies extracted into Cargo's cache no longer preserve mtimes to\n  reduce syscall overhead.\n  [#7465](https://github.com/rust-lang/cargo/pull/7465)\n- Windows: EXE files no longer include a metadata hash in the filename.\n  This helps with debuggers correlating the filename with the PDB file.\n  [#7400](https://github.com/rust-lang/cargo/pull/7400)\n- Wasm32: `.wasm` files are no longer treated as an \"executable\", allowing\n  `cargo test` and `cargo run` to work properly with the generated `.js` file.\n  [#7476](https://github.com/rust-lang/cargo/pull/7476)\n- crates.io now supports SPDX 3.6 licenses.\n  [#7481](https://github.com/rust-lang/cargo/pull/7481)\n- Improved cyclic dependency error message.\n  [#7470](https://github.com/rust-lang/cargo/pull/7470)\n- Bare `cargo clean` no longer locks the package cache.\n  [#7502](https://github.com/rust-lang/cargo/pull/7502)\n- `cargo publish` now allows dev-dependencies without a version key to be\n  published. A git or path-only dev-dependency will be removed from the\n  package manifest before uploading.\n  [#7333](https://github.com/rust-lang/cargo/pull/7333)\n- `--features` and `--no-default-features` in the root of a virtual workspace\n  will now generate an error instead of being ignored.\n  [#7507](https://github.com/rust-lang/cargo/pull/7507)\n- Generated files (like `Cargo.toml` and `Cargo.lock`) in a package archive\n  now have their timestamp set to the current time instead of the epoch.\n  [#7523](https://github.com/rust-lang/cargo/pull/7523)\n- The `-Z` flag parser is now more strict, rejecting more invalid syntax.\n  [#7531](https://github.com/rust-lang/cargo/pull/7531)\n\n### Fixed\n- Fixed an issue where if a package had an `include` field, and `Cargo.lock`\n  in `.gitignore`, and a binary or example target, and the `Cargo.lock` exists\n  in the current project, it would fail to publish complaining the\n  `Cargo.lock` was dirty.\n  [#7448](https://github.com/rust-lang/cargo/pull/7448)\n- Fixed a panic in a particular combination of `[patch]` entries.\n  [#7452](https://github.com/rust-lang/cargo/pull/7452)\n- Windows: Better error message when `cargo test` or `rustc` crashes in an\n  abnormal way, such as a signal or seg fault.\n  [#7535](https://github.com/rust-lang/cargo/pull/7535)\n\n### Nightly only\n- The `mtime-on-use` feature may now be enabled via the\n  `unstable.mtime_on_use` config option.\n  [#7411](https://github.com/rust-lang/cargo/pull/7411)\n- Added support for named profiles.\n  [#6989](https://github.com/rust-lang/cargo/pull/6989)\n- Added `-Zpanic-abort-tests` to allow building and running tests with the\n  \"abort\" panic strategy.\n  [#7460](https://github.com/rust-lang/cargo/pull/7460)\n- Changed `build-std` to use `--sysroot`.\n  [#7421](https://github.com/rust-lang/cargo/pull/7421)\n- Various fixes and enhancements to `-Ztimings`.\n  [#7395](https://github.com/rust-lang/cargo/pull/7395)\n  [#7398](https://github.com/rust-lang/cargo/pull/7398)\n  [#7397](https://github.com/rust-lang/cargo/pull/7397)\n  [#7403](https://github.com/rust-lang/cargo/pull/7403)\n  [#7428](https://github.com/rust-lang/cargo/pull/7428)\n  [#7429](https://github.com/rust-lang/cargo/pull/7429)\n- Profile overrides have renamed the syntax to be\n  `[profile.dev.package.NAME]`.\n  [#7504](https://github.com/rust-lang/cargo/pull/7504)\n- Fixed warnings for unused profile overrides in a workspace.\n  [#7536](https://github.com/rust-lang/cargo/pull/7536)\n\n## Cargo 1.39 (2019-11-07)\n[e853aa97...1c6ec66d](https://github.com/rust-lang/cargo/compare/e853aa97...1c6ec66d)\n\n### Added\n- Config files may now use the `.toml` filename extension.\n  [#7295](https://github.com/rust-lang/cargo/pull/7295)\n- The `--workspace` flag has been added as an alias for `--all` to help avoid\n  confusion about the meaning of \"all\".\n  [#7241](https://github.com/rust-lang/cargo/pull/7241)\n- The `publish` field has been added to `cargo metadata`.\n  [#7354](https://github.com/rust-lang/cargo/pull/7354)\n\n### Changed\n- Display more information if parsing the output from `rustc` fails.\n  [#7236](https://github.com/rust-lang/cargo/pull/7236)\n- TOML errors now show the column number.\n  [#7248](https://github.com/rust-lang/cargo/pull/7248)\n- `cargo vendor` no longer deletes files in the `vendor` directory that starts\n  with a `.`.\n  [#7242](https://github.com/rust-lang/cargo/pull/7242)\n- `cargo fetch` will now show manifest warnings.\n  [#7243](https://github.com/rust-lang/cargo/pull/7243)\n- `cargo publish` will now check git submodules if they contain any\n  uncommitted changes.\n  [#7245](https://github.com/rust-lang/cargo/pull/7245)\n- In a build script, `cargo:rustc-flags` now allows `-l` and `-L` flags\n  without spaces.\n  [#7257](https://github.com/rust-lang/cargo/pull/7257)\n- When `cargo install` replaces an older version of a package it will now\n  delete any installed binaries that are no longer present in the newly\n  installed version.\n  [#7246](https://github.com/rust-lang/cargo/pull/7246)\n- A git dependency may now also specify a `version` key when published. The\n  `git` value will be stripped from the uploaded crate, matching the behavior\n  of `path` dependencies.\n  [#7237](https://github.com/rust-lang/cargo/pull/7237)\n- The behavior of workspace default-members has changed. The default-members\n  now only applies when running Cargo in the root of the workspace. Previously\n  it would always apply regardless of which directory Cargo is running in.\n  [#7270](https://github.com/rust-lang/cargo/pull/7270)\n- libgit2 updated pulling in all upstream changes.\n  [#7275](https://github.com/rust-lang/cargo/pull/7275)\n- Bump `home` dependency for locating home directories.\n  [#7277](https://github.com/rust-lang/cargo/pull/7277)\n- zsh completions have been updated.\n  [#7296](https://github.com/rust-lang/cargo/pull/7296)\n- SSL connect errors are now retried.\n  [#7318](https://github.com/rust-lang/cargo/pull/7318)\n- The jobserver has been changed to acquire N tokens (instead of N-1), and\n  then immediately acquires the extra token. This was changed to accommodate\n  the `cc` crate on Windows to allow it to release its implicit token.\n  [#7344](https://github.com/rust-lang/cargo/pull/7344)\n- The scheduling algorithm for choosing which crate to build next has been\n  changed. It now chooses the crate with the greatest number of transitive\n  crates waiting on it. Previously it used a maximum topological depth.\n  [#7390](https://github.com/rust-lang/cargo/pull/7390)\n- RUSTFLAGS are no longer incorporated in the metadata and filename hash,\n  reversing the change from 1.33 that added it. This means that any change to\n  RUSTFLAGS will cause a recompile, and will not affect symbol munging.\n  [#7459](https://github.com/rust-lang/cargo/pull/7459)\n\n### Fixed\n- Git dependencies with submodules with shorthand SSH URLs (like\n  `git@github.com/user/repo.git`) should now work.\n  [#7238](https://github.com/rust-lang/cargo/pull/7238)\n- Handle broken symlinks when creating `.dSYM` symlinks on macOS.\n  [#7268](https://github.com/rust-lang/cargo/pull/7268)\n- Fixed issues with multiple versions of the same crate in a `[patch]` table.\n  [#7303](https://github.com/rust-lang/cargo/pull/7303)\n- Fixed issue with custom target `.json` files where a substring of the name\n  matches an unsupported crate type (like \"bin\").\n  [#7363](https://github.com/rust-lang/cargo/issues/7363)\n- Fixed issues with generating documentation for proc-macro crate types.\n  [#7159](https://github.com/rust-lang/cargo/pull/7159)\n- Fixed hang if Cargo panics within a build thread.\n  [#7366](https://github.com/rust-lang/cargo/pull/7366)\n- Fixed rebuild detection if a `build.rs` script issues different `rerun-if`\n  directives between builds. Cargo was erroneously causing a rebuild after the\n  change.\n  [#7373](https://github.com/rust-lang/cargo/pull/7373)\n- Properly handle canonical URLs for `[patch]` table entries, preventing\n  the patch from working after the first time it is used.\n  [#7368](https://github.com/rust-lang/cargo/pull/7368)\n- Fixed an issue where integration tests were waiting for the package binary\n  to finish building before starting their own build. They now may build\n  concurrently.\n  [#7394](https://github.com/rust-lang/cargo/pull/7394)\n- Fixed accidental change in the previous release on how `--features a b` flag\n  is interpreted, restoring the original behavior where this is interpreted as\n  `--features a` along with the argument `b` passed to the command. To pass\n  multiple features, use quotes around the features to pass multiple features\n  like `--features \"a b\"`, or use commas, or use multiple `--features` flags.\n  [#7419](https://github.com/rust-lang/cargo/pull/7419)\n\n### Nightly only\n- Basic support for building the standard library directly from Cargo has been\n  added.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std))\n  [#7216](https://github.com/rust-lang/cargo/pull/7216)\n- Added `-Ztimings` feature to generate an HTML report on the time spent on\n  individual compilation steps. This also may output completion steps on the\n  console and JSON data.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#timings))\n  [#7311](https://github.com/rust-lang/cargo/pull/7311)\n- Added ability to cross-compile doctests.\n  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#doctest-xcompile))\n  [#6892](https://github.com/rust-lang/cargo/pull/6892)\n\n## Cargo 1.38 (2019-09-26)\n[4c1fa54d...23ef9a4e](https://github.com/rust-lang/cargo/compare/4c1fa54d...23ef9a4e)\n\n### Added\n- 🔥 Cargo build pipelining has been enabled by default to leverage more idle CPU\n  parallelism during builds.\n  [#7143](https://github.com/rust-lang/cargo/pull/7143)\n- The `--message-format` option to Cargo can now be specified multiple times and\n  accepts a comma-separated list of values. In addition to the previous values\n  it also now accepts `json-diagnostic-short` and\n  `json-diagnostic-rendered-ansi` which configures the output coming from rustc\n  in `json` message mode.\n  [#7214](https://github.com/rust-lang/cargo/pull/7214)\n- Cirrus CI badges are now supported on crates.io.\n  [#7119](https://github.com/rust-lang/cargo/pull/7119)\n- A new format for `Cargo.lock` has been introduced. This new format is\n  intended to avoid source-control merge conflicts more often, and to\n  generally make it safer to merge changes. This new format is *not* enabled\n  at this time, though Cargo will use it if it sees it. At some point in the\n  future, it is intended that this will become the default.\n  [#7070](https://github.com/rust-lang/cargo/pull/7070)\n- Progress bar support added for FreeBSD.\n  [#7222](https://github.com/rust-lang/cargo/pull/7222)\n\n### Changed\n- The `-q` flag will no longer suppress the root error message for an error\n  from Cargo itself.\n  [#7116](https://github.com/rust-lang/cargo/pull/7116)\n- The Cargo Book is now published with mdbook 0.3 providing a number of\n  formatting fixes and improvements.\n  [#7140](https://github.com/rust-lang/cargo/pull/7140)\n- The `--features` command-line flag can now be specified multiple times.\n  The list of features from all the flags are joined together.\n  [#7084](https://github.com/rust-lang/cargo/pull/7084)\n- Package include/exclude glob-vs-gitignore warnings have been removed.\n  Packages may now use gitignore-style matching without producing any\n  warnings.\n  [#7170](https://github.com/rust-lang/cargo/pull/7170)\n- Cargo now shows the command and output when parsing `rustc` output fails\n  when querying `rustc` for information like `cfg` values.\n  [#7185](https://github.com/rust-lang/cargo/pull/7185)\n- `cargo package`/`cargo publish` now allows a symbolic link to a git\n  submodule to include that submodule.\n  [#6817](https://github.com/rust-lang/cargo/pull/6817)\n- Improved the error message when a version requirement does not\n  match any versions, but there are pre-release versions available.\n  [#7191](https://github.com/rust-lang/cargo/pull/7191)\n\n### Fixed\n- Fixed using the wrong directory when updating git repositories when using\n  the `git-fetch-with-cli` config option, and the `GIT_DIR` environment\n  variable is set. This may happen when running cargo from git callbacks.\n  [#7082](https://github.com/rust-lang/cargo/pull/7082)\n- Fixed dep-info files being overwritten for targets that have separate debug\n  outputs. For example, binaries on `-apple-` targets with `.dSYM` directories\n  would overwrite the `.d` file.\n  [#7057](https://github.com/rust-lang/cargo/pull/7057)\n- Fix `[patch]` table not preserving \"one major version per source\" rule.\n  [#7118](https://github.com/rust-lang/cargo/pull/7118)\n- Ignore `--remap-path-prefix` flags for the metadata hash in the `cargo\n  rustc` command. This was causing the remap settings to inadvertently affect\n  symbol names.\n  [#7134](https://github.com/rust-lang/cargo/pull/7134)\n- Fixed cycle detection in `[patch]` dependencies.\n  [#7174](https://github.com/rust-lang/cargo/pull/7174)\n- Fixed `cargo new` leaving behind a symlink on Windows when `core.symlinks`\n  git config is true. Also adds a number of fixes and updates from upstream\n  libgit2.\n  [#7176](https://github.com/rust-lang/cargo/pull/7176)\n- macOS: Fixed setting the flag to mark the `target` directory to be excluded\n  from backups.\n  [#7192](https://github.com/rust-lang/cargo/pull/7192)\n- Fixed `cargo fix` panicking under some situations involving multi-byte\n  characters.\n  [#7221](https://github.com/rust-lang/cargo/pull/7221)\n\n### Nightly only\n- Added `cargo fix --clippy` which will apply machine-applicable fixes from\n  Clippy.\n  [#7069](https://github.com/rust-lang/cargo/pull/7069)\n- Added `-Z binary-dep-depinfo` flag to add change tracking for binary\n  dependencies like the standard library.\n  [#7137](https://github.com/rust-lang/cargo/pull/7137)\n  [#7219](https://github.com/rust-lang/cargo/pull/7219)\n- `cargo clippy-preview` will always run, even if no changes have been made.\n  [#7157](https://github.com/rust-lang/cargo/pull/7157)\n- Fixed exponential blowup when using `CARGO_BUILD_PIPELINING`.\n  [#7062](https://github.com/rust-lang/cargo/pull/7062)\n- Fixed passing args to clippy in `cargo clippy-preview`.\n  [#7162](https://github.com/rust-lang/cargo/pull/7162)\n\n## Cargo 1.37 (2019-08-15)\n[c4fcfb72...9edd0891](https://github.com/rust-lang/cargo/compare/c4fcfb72...9edd0891)\n\n### Added\n- Added `doctest` field to `cargo metadata` to determine if a target's\n  documentation is tested.\n  [#6953](https://github.com/rust-lang/cargo/pull/6953)\n  [#6965](https://github.com/rust-lang/cargo/pull/6965)\n- 🔥 The [`cargo\n  vendor`](https://doc.rust-lang.org/nightly/cargo/commands/cargo-vendor.html)\n  command is now built-in to Cargo. This command may be used to create a local\n  copy of the sources of all dependencies.\n  [#6869](https://github.com/rust-lang/cargo/pull/6869)\n- 🔥 The \"publish lockfile\" feature is now stable. This feature will\n  automatically include the `Cargo.lock` file when a package is published if\n  it contains a binary executable target. By default, Cargo will ignore\n  `Cargo.lock` when installing a package. To force Cargo to use the\n  `Cargo.lock` file included in the published package, use `cargo install\n  --locked`. This may be useful to ensure that `cargo install` consistently\n  reproduces the same result. It may also be useful when a semver-incompatible\n  change is accidentally published to a dependency, providing a way to fall\n  back to a version that is known to work.\n  [#7026](https://github.com/rust-lang/cargo/pull/7026)\n- 🔥 The `default-run` feature has been stabilized. This feature allows you to\n  specify which binary executable to run by default with `cargo run` when a\n  package includes multiple binaries. Set the `default-run` key in the\n  `[package]` table in `Cargo.toml` to the name of the binary to use by\n  default.\n  [#7056](https://github.com/rust-lang/cargo/pull/7056)\n\n### Changed\n- `cargo package` now verifies that build scripts do not create empty\n  directories.\n  [#6973](https://github.com/rust-lang/cargo/pull/6973)\n- A warning is now issued if `cargo doc` generates duplicate outputs, which\n  causes files to be randomly stomped on. This may happen for a variety of\n  reasons (renamed dependencies, multiple versions of the same package,\n  packages with renamed libraries, etc.). This is a known bug, which needs\n  more work to handle correctly.\n  [#6998](https://github.com/rust-lang/cargo/pull/6998)\n- Enabling a dependency's feature with `--features foo/bar` will no longer\n  compile the current crate with the `foo` feature if `foo` is not an optional\n  dependency.\n  [#7010](https://github.com/rust-lang/cargo/pull/7010)\n- If `--remap-path-prefix` is passed via RUSTFLAGS, it will no longer affect\n  the filename metadata hash.\n  [#6966](https://github.com/rust-lang/cargo/pull/6966)\n- libgit2 has been updated to 0.28.2, which Cargo uses to access git\n  repositories. This brings in hundreds of changes and fixes since it was last\n  updated in November.\n  [#7018](https://github.com/rust-lang/cargo/pull/7018)\n- Cargo now supports absolute paths in the dep-info files generated by rustc.\n  This is laying the groundwork for [tracking\n  binaries](https://github.com/rust-lang/rust/pull/61727), such as libstd, for\n  rebuild detection. (Note: this contains a known bug.)\n  [#7030](https://github.com/rust-lang/cargo/pull/7030)\n\n### Fixed\n- Fixed how zsh completions fetch the list of commands.\n  [#6956](https://github.com/rust-lang/cargo/pull/6956)\n- \"+ debuginfo\" is no longer printed in the build summary when `debug` is set\n  to 0.\n  [#6971](https://github.com/rust-lang/cargo/pull/6971)\n- Fixed `cargo doc` with an example configured with `doc = true` to document\n  correctly.\n  [#7023](https://github.com/rust-lang/cargo/pull/7023)\n- Don't fail if a read-only lock cannot be acquired in CARGO_HOME. This helps\n  when CARGO_HOME doesn't exist, but `--locked` is used which means CARGO_HOME\n  is not needed.\n  [#7149](https://github.com/rust-lang/cargo/pull/7149)\n- Reverted a change in 1.35 which released jobserver tokens when Cargo blocked\n  on a lock file. It caused a deadlock in some situations.\n  [#7204](https://github.com/rust-lang/cargo/pull/7204)\n\n### Nightly only\n- Added [compiler message\n  caching](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#cache-messages).\n  The `-Z cache-messages` flag makes cargo cache the compiler output so that\n  future runs can redisplay previous warnings.\n  [#6933](https://github.com/rust-lang/cargo/pull/6933)\n- `-Z mtime-on-use` no longer touches intermediate artifacts.\n  [#7050](https://github.com/rust-lang/cargo/pull/7050)\n\n## Cargo 1.36 (2019-07-04)\n[6f3e9c36...c4fcfb72](https://github.com/rust-lang/cargo/compare/6f3e9c36...c4fcfb72)\n\n### Added\n- Added more detailed documentation on target auto-discovery.\n  [#6898](https://github.com/rust-lang/cargo/pull/6898)\n- 🔥 Stabilize the `--offline` flag which allows using cargo without a network\n  connection.\n  [#6934](https://github.com/rust-lang/cargo/pull/6934)\n  [#6871](https://github.com/rust-lang/cargo/pull/6871)\n\n### Changed\n- `publish = [\"crates-io\"]` may be added to the manifest to restrict\n  publishing to crates.io only.\n  [#6838](https://github.com/rust-lang/cargo/pull/6838)\n- macOS: Only include the default paths if `DYLD_FALLBACK_LIBRARY_PATH` is not\n  set. Also, remove `/lib` from the default set.\n  [#6856](https://github.com/rust-lang/cargo/pull/6856)\n- `cargo publish` will now exit early if the login token is not available.\n  [#6854](https://github.com/rust-lang/cargo/pull/6854)\n- HTTP/2 stream errors are now considered \"spurious\" and will cause a retry.\n  [#6861](https://github.com/rust-lang/cargo/pull/6861)\n- Setting a feature on a dependency where that feature points to a *required*\n  dependency is now an error. Previously it was a warning.\n  [#6860](https://github.com/rust-lang/cargo/pull/6860)\n- The `registry.index` config value now supports relative `file:` URLs.\n  [#6873](https://github.com/rust-lang/cargo/pull/6873)\n- macOS: The `.dSYM` directory is now symbolically linked next to example\n  binaries without the metadata hash so that debuggers can find it.\n  [#6891](https://github.com/rust-lang/cargo/pull/6891)\n- The default `Cargo.toml` template for now projects now includes a comment\n  providing a link to the documentation.\n  [#6881](https://github.com/rust-lang/cargo/pull/6881)\n- Some improvements to the wording of the crate download summary.\n  [#6916](https://github.com/rust-lang/cargo/pull/6916)\n  [#6920](https://github.com/rust-lang/cargo/pull/6920)\n- ✨ Changed `RUST_LOG` environment variable to `CARGO_LOG` so that user code\n  that uses the `log` crate will not display cargo's debug output.\n  [#6918](https://github.com/rust-lang/cargo/pull/6918)\n- `Cargo.toml` is now always included when packaging, even if it is not listed\n  in `package.include`.\n  [#6925](https://github.com/rust-lang/cargo/pull/6925)\n- Package include/exclude values now use gitignore patterns instead of glob\n  patterns. [#6924](https://github.com/rust-lang/cargo/pull/6924)\n- Provide a better error message when crates.io times out. Also improve error\n  messages with other HTTP response codes.\n  [#6936](https://github.com/rust-lang/cargo/pull/6936)\n\n### Performance\n- Resolver performance improvements for some cases.\n  [#6853](https://github.com/rust-lang/cargo/pull/6853)\n- Optimized how cargo reads the index JSON files by caching the results.\n  [#6880](https://github.com/rust-lang/cargo/pull/6880)\n  [#6912](https://github.com/rust-lang/cargo/pull/6912)\n  [#6940](https://github.com/rust-lang/cargo/pull/6940)\n- Various performance improvements.\n  [#6867](https://github.com/rust-lang/cargo/pull/6867)\n\n### Fixed\n- More carefully track the on-disk fingerprint information for dependencies.\n  This can help in some rare cases where the build is interrupted and\n  restarted. [#6832](https://github.com/rust-lang/cargo/pull/6832)\n- `cargo run` now correctly passes non-UTF8 arguments to the child process.\n  [#6849](https://github.com/rust-lang/cargo/pull/6849)\n- Fixed bash completion to run on bash 3.2, the stock version in macOS.\n  [#6905](https://github.com/rust-lang/cargo/pull/6905)\n- Various fixes and improvements to zsh completion.\n  [#6926](https://github.com/rust-lang/cargo/pull/6926)\n  [#6929](https://github.com/rust-lang/cargo/pull/6929)\n- Fix `cargo update` ignoring `-p` arguments if the `Cargo.lock` file was\n  missing.\n  [#6904](https://github.com/rust-lang/cargo/pull/6904)\n\n### Nightly only\n- Added [`-Z install-upgrade`\n  feature](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#install-upgrade)\n  to track details about installed crates and to update them if they are\n  out-of-date. [#6798](https://github.com/rust-lang/cargo/pull/6798)\n- Added the [`public-dependency`\n  feature](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#public-dependency)\n  which allows tracking public versus private dependencies.\n  [#6772](https://github.com/rust-lang/cargo/pull/6772)\n- Added build pipelining via the `build.pipelining` config\n  option (`CARGO_BUILD_PIPELINING` env var).\n  [#6883](https://github.com/rust-lang/cargo/pull/6883)\n- The `publish-lockfile` feature has had some significant changes. The default\n  is now `true`, the `Cargo.lock` will always be published for binary crates.\n  The `Cargo.lock` is now regenerated during publishing. `cargo install` now\n  ignores the `Cargo.lock` file by default, and requires `--locked` to use the\n  lock file. Warnings have been added if yanked dependencies are detected.\n  [#6840](https://github.com/rust-lang/cargo/pull/6840)\n\n## Cargo 1.35 (2019-05-23)\n[6789d8a0...6f3e9c36](https://github.com/rust-lang/cargo/compare/6789d8a0...6f3e9c36)\n\n### Added\n- Added the `rustc-cdylib-link-arg` key for build scripts to specify linker\n  arguments for cdylib crates.\n  [#6298](https://github.com/rust-lang/cargo/pull/6298)\n\n### Changed\n- When passing a test filter, such as `cargo test foo`, don't build examples\n  (unless they set `test = true`).\n  [#6683](https://github.com/rust-lang/cargo/pull/6683)\n- Forward the `--quiet` flag from `cargo test` to the libtest harness so that\n  tests are actually quiet.\n  [#6358](https://github.com/rust-lang/cargo/pull/6358)\n- The verification step in `cargo package` that checks if any files are\n  modified is now stricter. It uses a hash of the contents instead of checking\n  filesystem mtimes. It also checks *all* files in the package.\n  [#6740](https://github.com/rust-lang/cargo/pull/6740)\n- Jobserver tokens are now released whenever Cargo blocks on a file lock.\n  [#6748](https://github.com/rust-lang/cargo/pull/6748)\n- Issue a warning for a previous bug in the TOML parser that allowed multiple\n  table headers with the same name.\n  [#6761](https://github.com/rust-lang/cargo/pull/6761)\n- Removed the `CARGO_PKG_*` environment variables from the metadata hash and\n  added them to the fingerprint instead. This means that when these values\n  change, stale artifacts are not left behind. Also added the \"repository\"\n  value to the fingerprint.\n  [#6785](https://github.com/rust-lang/cargo/pull/6785)\n- `cargo metadata` no longer shows a `null` field for a dependency without a\n  library in `resolve.nodes.deps`. The dependency is no longer shown.\n  [#6534](https://github.com/rust-lang/cargo/pull/6534)\n- `cargo new` will no longer include an email address in the `authors` field\n  if it is set to the empty string.\n  [#6802](https://github.com/rust-lang/cargo/pull/6802)\n- `cargo doc --open` now works when documenting multiple packages.\n  [#6803](https://github.com/rust-lang/cargo/pull/6803)\n- `cargo install --path P` now loads the `.cargo/config` file from the\n  directory P. [#6805](https://github.com/rust-lang/cargo/pull/6805)\n- Using semver metadata in a version requirement (such as `1.0.0+1234`) now\n  issues a warning that it is ignored.\n  [#6806](https://github.com/rust-lang/cargo/pull/6806)\n- `cargo install` now rejects certain combinations of flags where some flags\n  would have been ignored.\n  [#6801](https://github.com/rust-lang/cargo/pull/6801)\n- Resolver performance improvements for some cases.\n  [#6776](https://github.com/rust-lang/cargo/pull/6776)\n\n### Fixed\n- Fixed running separate commands (such as `cargo build` then `cargo test`)\n  where the second command could use stale results from a build script.\n  [#6720](https://github.com/rust-lang/cargo/pull/6720)\n- Fixed `cargo fix` not working properly if a `.gitignore` file that matched\n  the root package directory.\n  [#6767](https://github.com/rust-lang/cargo/pull/6767)\n- Fixed accidentally compiling a lib multiple times if `panic=unwind` was set\n  in a profile. [#6781](https://github.com/rust-lang/cargo/pull/6781)\n- Paths to JSON files in `build.target` config value are now canonicalized to\n  fix building dependencies.\n  [#6778](https://github.com/rust-lang/cargo/pull/6778)\n- Fixed re-running a build script if its compilation was interrupted (such as\n  if it is killed). [#6782](https://github.com/rust-lang/cargo/pull/6782)\n- Fixed `cargo new` initializing a fossil repo.\n  [#6792](https://github.com/rust-lang/cargo/pull/6792)\n- Fixed supporting updating a git repo that has a force push when using the\n  `git-fetch-with-cli` feature. `git-fetch-with-cli` also shows more error\n  information now when it fails.\n  [#6800](https://github.com/rust-lang/cargo/pull/6800)\n- `--example` binaries built for the WASM target are fixed to no longer\n  include a metadata hash in the filename, and are correctly emitted in the\n  `compiler-artifact` JSON message.\n  [#6812](https://github.com/rust-lang/cargo/pull/6812)\n\n### Nightly only\n- `cargo clippy-preview` is now a built-in cargo command.\n  [#6759](https://github.com/rust-lang/cargo/pull/6759)\n- The `build-override` profile setting now includes proc-macros and their\n  dependencies.\n  [#6811](https://github.com/rust-lang/cargo/pull/6811)\n- Optional and target dependencies now work better with `-Z offline`.\n  [#6814](https://github.com/rust-lang/cargo/pull/6814)\n\n## Cargo 1.34 (2019-04-11)\n[f099fe94...6789d8a0](https://github.com/rust-lang/cargo/compare/f099fe94...6789d8a0)\n\n### Added\n- 🔥 Stabilized support for [alternate\n  registries](https://doc.rust-lang.org/1.34.0/cargo/reference/registries.html).\n  [#6654](https://github.com/rust-lang/cargo/pull/6654)\n- Added documentation on using builds.sr.ht Continuous Integration with Cargo.\n  [#6565](https://github.com/rust-lang/cargo/pull/6565)\n- `Cargo.lock` now includes a comment at the top that it is `@generated`.\n  [#6548](https://github.com/rust-lang/cargo/pull/6548)\n- Azure DevOps badges are now supported.\n  [#6264](https://github.com/rust-lang/cargo/pull/6264)\n- Added a warning if `--exclude` flag specifies an unknown package.\n  [#6679](https://github.com/rust-lang/cargo/pull/6679)\n\n### Changed\n- `cargo test --doc --no-run` doesn't do anything, so it now displays an error\n  to that effect. [#6628](https://github.com/rust-lang/cargo/pull/6628)\n- Various updates to bash completion: add missing options and commands,\n  support libtest completions, use rustup for `--target` completion, fallback\n  to filename completion, fix editing the command line.\n  [#6644](https://github.com/rust-lang/cargo/pull/6644)\n- Publishing a crate with a `[patch]` section no longer generates an error.\n  The `[patch]` section is removed from the manifest before publishing.\n  [#6535](https://github.com/rust-lang/cargo/pull/6535)\n- `build.incremental = true` config value is now treated the same as\n  `CARGO_INCREMENTAL=1`, previously it was ignored.\n  [#6688](https://github.com/rust-lang/cargo/pull/6688)\n- Errors from a registry are now always displayed regardless of the HTTP\n  response code. [#6771](https://github.com/rust-lang/cargo/pull/6771)\n\n### Fixed\n- Fixed bash completion for `cargo run --example`.\n  [#6578](https://github.com/rust-lang/cargo/pull/6578)\n- Fixed a race condition when using a *local* registry and running multiple\n  cargo commands at the same time that build the same crate.\n  [#6591](https://github.com/rust-lang/cargo/pull/6591)\n- Fixed some flickering and excessive updates of the progress bar.\n  [#6615](https://github.com/rust-lang/cargo/pull/6615)\n- Fixed a hang when using a git credential helper that returns incorrect\n  credentials. [#6681](https://github.com/rust-lang/cargo/pull/6681)\n- Fixed resolving yanked crates with a local registry.\n  [#6750](https://github.com/rust-lang/cargo/pull/6750)\n\n### Nightly only\n- Added `-Z mtime-on-use` flag to cause the mtime to be updated on the\n  filesystem when a crate is used. This is intended to be able to track stale\n  artifacts in the future for cleaning up unused files.\n  [#6477](https://github.com/rust-lang/cargo/pull/6477)\n  [#6573](https://github.com/rust-lang/cargo/pull/6573)\n- Added experimental `-Z dual-proc-macros` to build proc macros for both the\n  host and the target.\n  [#6547](https://github.com/rust-lang/cargo/pull/6547)\n\n## Cargo 1.33 (2019-02-28)\n[8610973a...f099fe94](https://github.com/rust-lang/cargo/compare/8610973a...f099fe94)\n\n### Added\n- `compiler-artifact` JSON messages now include an `\"executable\"` key which\n  includes the path to the executable that was built.\n  [#6363](https://github.com/rust-lang/cargo/pull/6363)\n- The man pages have been rewritten, and are now published with the web\n  documentation. [#6405](https://github.com/rust-lang/cargo/pull/6405)\n- `cargo login` now displays a confirmation after saving the token.\n  [#6466](https://github.com/rust-lang/cargo/pull/6466)\n- A warning is now emitted if a `[patch]` entry does not match any package.\n  [#6470](https://github.com/rust-lang/cargo/pull/6470)\n- `cargo metadata` now includes the `links` key for a package.\n  [#6480](https://github.com/rust-lang/cargo/pull/6480)\n- \"Very verbose\" output with `-vv` now displays the environment variables that\n  cargo sets when it runs a process.\n  [#6492](https://github.com/rust-lang/cargo/pull/6492)\n- `--example`, `--bin`, `--bench`, or `--test` without an argument now lists\n  the available targets for those options.\n  [#6505](https://github.com/rust-lang/cargo/pull/6505)\n- Windows: If a process fails with an extended status exit code, a\n  human-readable name for the code is now displayed.\n  [#6532](https://github.com/rust-lang/cargo/pull/6532)\n- Added `--features`, `--no-default-features`, and `--all-features` flags to\n  the `cargo package` and `cargo publish` commands to use the given features\n  when verifying the package.\n  [#6453](https://github.com/rust-lang/cargo/pull/6453)\n\n### Changed\n- If `cargo fix` fails to compile the fixed code, the rustc errors are now\n  displayed on the console.\n  [#6419](https://github.com/rust-lang/cargo/pull/6419)\n- Hide the `--host` flag from `cargo login`, it is unused.\n  [#6466](https://github.com/rust-lang/cargo/pull/6466)\n- Build script fingerprints now include the rustc version.\n  [#6473](https://github.com/rust-lang/cargo/pull/6473)\n- macOS: Switched to setting `DYLD_FALLBACK_LIBRARY_PATH` instead of\n  `DYLD_LIBRARY_PATH`. [#6355](https://github.com/rust-lang/cargo/pull/6355)\n- `RUSTFLAGS` is now included in the metadata hash, meaning that changing\n  the flags will not overwrite previously built files.\n  [#6503](https://github.com/rust-lang/cargo/pull/6503)\n- When updating the crate graph, unrelated yanked crates were erroneously\n  removed. They are now kept at their original version if possible. This was\n  causing unrelated packages to be downgraded during `cargo update -p\n  somecrate`. [#5702](https://github.com/rust-lang/cargo/issues/5702)\n- TOML files now support the [0.5 TOML\n  syntax](https://github.com/toml-lang/toml/blob/master/CHANGELOG.md#050--2018-07-11).\n\n### Fixed\n- `cargo fix` will now ignore suggestions that modify multiple files.\n  [#6402](https://github.com/rust-lang/cargo/pull/6402)\n- `cargo fix` will now only fix one target at a time, to deal with targets\n  which share the same source files.\n  [#6434](https://github.com/rust-lang/cargo/pull/6434)\n- Fixed bash completion showing the list of cargo commands.\n  [#6461](https://github.com/rust-lang/cargo/issues/6461)\n- `cargo init` will now avoid creating duplicate entries in `.gitignore`\n  files. [#6521](https://github.com/rust-lang/cargo/pull/6521)\n- Builds now attempt to detect if a file is modified in the middle of a\n  compilation, allowing you to build again and pick up the new changes. This\n  is done by keeping track of when the compilation *starts* not when it\n  finishes. Also, [#5919](https://github.com/rust-lang/cargo/pull/5919) was\n  reverted, meaning that cargo does *not* treat equal filesystem mtimes as\n  requiring a rebuild. [#6484](https://github.com/rust-lang/cargo/pull/6484)\n\n### Nightly only\n- Allow using registry *names* in `[patch]` tables instead of just URLs.\n  [#6456](https://github.com/rust-lang/cargo/pull/6456)\n- `cargo metadata` added the `registry` key for dependencies.\n  [#6500](https://github.com/rust-lang/cargo/pull/6500)\n- Registry names are now restricted to the same style as\n  package names (alphanumeric, `-` and `_` characters).\n  [#6469](https://github.com/rust-lang/cargo/pull/6469)\n- `cargo login` now displays the `/me` URL from the registry config.\n  [#6466](https://github.com/rust-lang/cargo/pull/6466)\n- `cargo login --registry=NAME` now supports interactive input for the token.\n  [#6466](https://github.com/rust-lang/cargo/pull/6466)\n- Registries may now elide the `api` key from `config.json` to indicate they\n  do not support API access.\n  [#6466](https://github.com/rust-lang/cargo/pull/6466)\n- Fixed panic when using `--message-format=json` with metabuild.\n  [#6432](https://github.com/rust-lang/cargo/pull/6432)\n- Fixed detection of publishing to crates.io when using alternate registries.\n  [#6525](https://github.com/rust-lang/cargo/pull/6525)\n\n## Cargo 1.32 (2019-01-17)\n[339d9f9c...8610973a](https://github.com/rust-lang/cargo/compare/339d9f9c...8610973a)\n\n### Added\n- Registries may now display warnings after a successful publish.\n  [#6303](https://github.com/rust-lang/cargo/pull/6303)\n- Added a [glossary](appendix/glossary.md)\n  to the documentation. [#6321](https://github.com/rust-lang/cargo/pull/6321)\n- Added the alias `c` for `cargo check`.\n  [#6218](https://github.com/rust-lang/cargo/pull/6218)\n\n### Changed\n- 🔥 HTTP/2 multiplexing is now enabled by default. The `http.multiplexing`\n  config value may be used to disable it.\n  [#6271](https://github.com/rust-lang/cargo/pull/6271)\n- Use ANSI escape sequences to clear lines instead of spaces.\n  [#6233](https://github.com/rust-lang/cargo/pull/6233)\n- Disable git templates when checking out git dependencies, which can cause\n  problems. [#6252](https://github.com/rust-lang/cargo/pull/6252)\n- Include the `--update-head-ok` git flag when using the\n  `net.git-fetch-with-cli` option. This can help prevent failures when\n  fetching some repositories.\n  [#6250](https://github.com/rust-lang/cargo/pull/6250)\n- When extracting a crate during the verification step of `cargo package`, the\n  filesystem mtimes are no longer set, which was failing on some rare\n  filesystems. [#6257](https://github.com/rust-lang/cargo/pull/6257)\n- `crate-type = [\"proc-macro\"]` is now treated the same as `proc-macro = true`\n  in `Cargo.toml`. [#6256](https://github.com/rust-lang/cargo/pull/6256)\n- An error is raised if `dependencies`, `features`, `target`, or `badges` is\n  set in a virtual workspace. Warnings are displayed if `replace` or `patch`\n  is used in a workspace member.\n  [#6276](https://github.com/rust-lang/cargo/pull/6276)\n- Improved performance of the resolver in some cases.\n  [#6283](https://github.com/rust-lang/cargo/pull/6283)\n  [#6366](https://github.com/rust-lang/cargo/pull/6366)\n- `.rmeta` files are no longer hard-linked into the base target directory\n  (`target/debug`). [#6292](https://github.com/rust-lang/cargo/pull/6292)\n- A warning is issued if multiple targets are built with the same output\n  filenames. [#6308](https://github.com/rust-lang/cargo/pull/6308)\n- When using `cargo build` (without `--release`) benchmarks are now built\n  using the \"test\" profile instead of \"bench\". This makes it easier to debug\n  benchmarks, and avoids confusing behavior.\n  [#6309](https://github.com/rust-lang/cargo/pull/6309)\n- User aliases may now override built-in aliases (`b`, `r`, `t`, and `c`).\n  [#6259](https://github.com/rust-lang/cargo/pull/6259)\n- Setting `autobins=false` now disables auto-discovery of inferred targets.\n  [#6329](https://github.com/rust-lang/cargo/pull/6329)\n- `cargo verify-project` will now fail on stable if the project uses unstable\n  features. [#6326](https://github.com/rust-lang/cargo/pull/6326)\n- Platform targets with an internal `.` within the name are now allowed.\n  [#6255](https://github.com/rust-lang/cargo/pull/6255)\n- `cargo clean --release` now only deletes the release directory.\n  [#6349](https://github.com/rust-lang/cargo/pull/6349)\n\n### Fixed\n- Avoid adding extra angle brackets in email address for `cargo new`.\n  [#6243](https://github.com/rust-lang/cargo/pull/6243)\n- The progress bar is disabled if the CI environment variable is set.\n  [#6281](https://github.com/rust-lang/cargo/pull/6281)\n- Avoid retaining all rustc output in memory.\n  [#6289](https://github.com/rust-lang/cargo/pull/6289)\n- If JSON parsing fails, and rustc exits nonzero, don't lose the parse failure\n  message. [#6290](https://github.com/rust-lang/cargo/pull/6290)\n- Fixed renaming a project directory with build scripts.\n  [#6328](https://github.com/rust-lang/cargo/pull/6328)\n- Fixed `cargo run --example NAME` to work correctly if the example sets\n  `crate_type = [\"bin\"]`.\n  [#6330](https://github.com/rust-lang/cargo/pull/6330)\n- Fixed issue with `cargo package` git discovery being too aggressive. The\n  `--allow-dirty` now completely disables the git repo checks.\n  [#6280](https://github.com/rust-lang/cargo/pull/6280)\n- Fixed build change tracking for `[patch]` deps which resulted in `cargo\n  build` rebuilding when it shouldn't.\n  [#6493](https://github.com/rust-lang/cargo/pull/6493)\n\n### Nightly only\n- Allow usernames in registry URLs.\n  [#6242](https://github.com/rust-lang/cargo/pull/6242)\n- Added `\"compile_mode\"` key to the build-plan JSON structure to be able to\n  distinguish running a custom build script versus compiling the build script.\n  [#6331](https://github.com/rust-lang/cargo/pull/6331)\n- `--out-dir` no longer copies over build scripts.\n  [#6300](https://github.com/rust-lang/cargo/pull/6300)\n\n## Cargo 1.31 (2018-12-06)\n[36d96825...339d9f9c](https://github.com/rust-lang/cargo/compare/36d96825...339d9f9c)\n\n### Added\n- 🔥 Stabilized support for the 2018 edition.\n  [#5984](https://github.com/rust-lang/cargo/pull/5984)\n  [#5989](https://github.com/rust-lang/cargo/pull/5989)\n- 🔥 Added the ability to [rename\n  dependencies](https://doc.rust-lang.org/1.31.0/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml)\n  in Cargo.toml. [#6319](https://github.com/rust-lang/cargo/pull/6319)\n- 🔥 Added support for HTTP/2 pipelining and multiplexing. Set the\n  `http.multiplexing` config value to enable.\n  [#6005](https://github.com/rust-lang/cargo/pull/6005)\n- Added `http.debug` configuration value to debug HTTP connections. Use\n  `CARGO_HTTP_DEBUG=true RUST_LOG=cargo::ops::registry cargo build` to display\n  the debug information. [#6166](https://github.com/rust-lang/cargo/pull/6166)\n- `CARGO_PKG_REPOSITORY` environment variable is set with the repository value\n  from `Cargo.toml` when building .\n  [#6096](https://github.com/rust-lang/cargo/pull/6096)\n\n### Changed\n- `cargo test --doc` now rejects other flags instead of ignoring them.\n  [#6037](https://github.com/rust-lang/cargo/pull/6037)\n- `cargo install` ignores `~/.cargo/config`.\n  [#6026](https://github.com/rust-lang/cargo/pull/6026)\n- `cargo version --verbose` is now the same as `cargo -vV`.\n  [#6076](https://github.com/rust-lang/cargo/pull/6076)\n- Comments at the top of `Cargo.lock` are now preserved.\n  [#6181](https://github.com/rust-lang/cargo/pull/6181)\n- When building in \"very verbose\" mode (`cargo build -vv`), build script\n  output is prefixed with the package name and version, such as `[foo 0.0.1]`.\n  [#6164](https://github.com/rust-lang/cargo/pull/6164)\n- If `cargo fix --broken-code` fails to compile after fixes have been applied,\n  the files are no longer reverted and are left in their broken state.\n  [#6316](https://github.com/rust-lang/cargo/pull/6316)\n\n### Fixed\n- Windows: Pass Ctrl-C to the process with `cargo run`.\n  [#6004](https://github.com/rust-lang/cargo/pull/6004)\n- macOS: Fix bash completion.\n  [#6038](https://github.com/rust-lang/cargo/pull/6038)\n- Support arbitrary toolchain names when completing `+toolchain` in bash\n  completion. [#6038](https://github.com/rust-lang/cargo/pull/6038)\n- Fixed edge cases in the resolver, when backtracking on failed dependencies.\n  [#5988](https://github.com/rust-lang/cargo/pull/5988)\n- Fixed `cargo test --all-targets` running lib tests three times.\n  [#6039](https://github.com/rust-lang/cargo/pull/6039)\n- Fixed publishing renamed dependencies to crates.io.\n  [#5993](https://github.com/rust-lang/cargo/pull/5993)\n- Fixed `cargo install` on a git repo with multiple binaries.\n  [#6060](https://github.com/rust-lang/cargo/pull/6060)\n- Fixed deeply nested JSON emitted by rustc being lost.\n  [#6081](https://github.com/rust-lang/cargo/pull/6081)\n- Windows: Fix locking msys terminals to 60 characters.\n  [#6122](https://github.com/rust-lang/cargo/pull/6122)\n- Fixed renamed dependencies with dashes.\n  [#6140](https://github.com/rust-lang/cargo/pull/6140)\n- Fixed linking against the wrong dylib when the dylib existed in both\n  `target/debug` and `target/debug/deps`.\n  [#6167](https://github.com/rust-lang/cargo/pull/6167)\n- Fixed some unnecessary recompiles when `panic=abort` is used.\n  [#6170](https://github.com/rust-lang/cargo/pull/6170)\n\n### Nightly only\n- Added `--registry` flag to `cargo install`.\n  [#6128](https://github.com/rust-lang/cargo/pull/6128)\n- Added `registry.default` configuration value to specify the\n  default registry to use if `--registry` flag is not passed.\n  [#6135](https://github.com/rust-lang/cargo/pull/6135)\n- Added `--registry` flag to `cargo new` and `cargo init`.\n  [#6135](https://github.com/rust-lang/cargo/pull/6135)\n\n## Cargo 1.30 (2018-10-25)\n[524a578d...36d96825](https://github.com/rust-lang/cargo/compare/524a578d...36d96825)\n\n### Added\n- 🔥 Added an animated progress bar shows progress during building.\n  [#5995](https://github.com/rust-lang/cargo/pull/5995/)\n- Added `resolve.nodes.deps` key to `cargo metadata`, which includes more\n  information about resolved dependencies, and properly handles renamed\n  dependencies. [#5871](https://github.com/rust-lang/cargo/pull/5871)\n- When creating a package, provide more detail with `-v` when failing to\n  discover if files are dirty in a git repository. Also fix a problem with\n  discovery on Windows. [#5858](https://github.com/rust-lang/cargo/pull/5858)\n- Filters like `--bin`, `--test`, `--example`, `--bench`, or `--lib` can be\n  used in a workspace without selecting a specific package.\n  [#5873](https://github.com/rust-lang/cargo/pull/5873)\n- `cargo run` can be used in a workspace without selecting a specific package.\n  [#5877](https://github.com/rust-lang/cargo/pull/5877)\n- `cargo doc --message-format=json` now outputs JSON messages from rustdoc.\n  [#5878](https://github.com/rust-lang/cargo/pull/5878)\n- Added `--message-format=short` to show one-line messages.\n  [#5879](https://github.com/rust-lang/cargo/pull/5879)\n- Added `.cargo_vcs_info.json` file to `.crate` packages that captures the\n  current git hash. [#5886](https://github.com/rust-lang/cargo/pull/5886)\n- Added `net.git-fetch-with-cli` configuration option to use the `git`\n  executable to fetch repositories instead of using the built-in libgit2\n  library. [#5914](https://github.com/rust-lang/cargo/pull/5914)\n- Added `required-features` to `cargo metadata`.\n  [#5902](https://github.com/rust-lang/cargo/pull/5902)\n- `cargo uninstall` within a package will now uninstall that package.\n  [#5927](https://github.com/rust-lang/cargo/pull/5927)\n- Added `--allow-staged` flag to `cargo fix` to allow it to run if files are\n  staged in git. [#5943](https://github.com/rust-lang/cargo/pull/5943)\n- Added `net.low-speed-limit` config value, and also honor `net.timeout` for\n  http operations. [#5957](https://github.com/rust-lang/cargo/pull/5957)\n- Added `--edition` flag to `cargo new`.\n  [#5984](https://github.com/rust-lang/cargo/pull/5984)\n- Temporarily stabilized 2018 edition support for the duration of the beta.\n  [#5984](https://github.com/rust-lang/cargo/pull/5984)\n  [#5989](https://github.com/rust-lang/cargo/pull/5989)\n- Added support for `target.'cfg(…)'.runner` config value to specify the\n  run/test/bench runner for targets that use config expressions.\n  [#5959](https://github.com/rust-lang/cargo/pull/5959)\n\n### Changed\n- Windows: `cargo run` will not kill child processes when the main process\n  exits. [#5887](https://github.com/rust-lang/cargo/pull/5887)\n- Switched to the `opener` crate to open a web browser with `cargo doc\n  --open`. This should more reliably select the system-preferred browser on\n  all platforms. [#5888](https://github.com/rust-lang/cargo/pull/5888)\n- Equal file mtimes now cause a target to be rebuilt. Previously only if files\n  were strictly *newer* than the last build would it cause a rebuild.\n  [#5919](https://github.com/rust-lang/cargo/pull/5919)\n- Ignore `build.target` config value when running `cargo install`.\n  [#5874](https://github.com/rust-lang/cargo/pull/5874)\n- Ignore `RUSTC_WRAPPER` for `cargo fix`.\n  [#5983](https://github.com/rust-lang/cargo/pull/5983)\n- Ignore empty `RUSTC_WRAPPER`.\n  [#5985](https://github.com/rust-lang/cargo/pull/5985)\n\n### Fixed\n- Fixed error when creating a package with an edition field in `Cargo.toml`.\n  [#5908](https://github.com/rust-lang/cargo/pull/5908)\n- More consistently use relative paths for path dependencies in a workspace.\n  [#5935](https://github.com/rust-lang/cargo/pull/5935)\n- `cargo fix` now always runs, even if it was run previously.\n  [#5944](https://github.com/rust-lang/cargo/pull/5944)\n- Windows: Attempt to more reliably detect terminal width. msys-based\n  terminals are forced to 60 characters wide.\n  [#6010](https://github.com/rust-lang/cargo/pull/6010)\n- Allow multiple target flags with `cargo doc --document-private-items`.\n  [6022](https://github.com/rust-lang/cargo/pull/6022)\n\n### Nightly only\n- Added\n  [metabuild](https://doc.rust-lang.org/1.30.0/cargo/reference/unstable.html#metabuild).\n  [#5628](https://github.com/rust-lang/cargo/pull/5628)\n"
  },
  {
    "path": "src/doc/src/SUMMARY.md",
    "content": "# Summary\n\n[Introduction](index.md)\n\n* [Getting Started](getting-started/index.md)\n    * [Installation](getting-started/installation.md)\n    * [First Steps with Cargo](getting-started/first-steps.md)\n\n* [Cargo Guide](guide/index.md)\n    * [Why Cargo Exists](guide/why-cargo-exists.md)\n    * [Creating a New Package](guide/creating-a-new-project.md)\n    * [Working on an Existing Package](guide/working-on-an-existing-project.md)\n    * [Dependencies](guide/dependencies.md)\n    * [Package Layout](guide/project-layout.md)\n    * [Cargo.toml vs Cargo.lock](guide/cargo-toml-vs-cargo-lock.md)\n    * [Tests](guide/tests.md)\n    * [Continuous Integration](guide/continuous-integration.md)\n    * [Publishing on crates.io](reference/publishing.md)\n    * [Cargo Home](guide/cargo-home.md)\n    * [Optimizing Build Performance](guide/build-performance.md)\n\n* [Cargo Reference](reference/index.md)\n    * [The Manifest Format](reference/manifest.md)\n        * [Cargo Targets](reference/cargo-targets.md)\n        * [Rust version](reference/rust-version.md)\n    * [Workspaces](reference/workspaces.md)\n    * [Specifying Dependencies](reference/specifying-dependencies.md)\n        * [Overriding Dependencies](reference/overriding-dependencies.md)\n        * [Source Replacement](reference/source-replacement.md)\n        * [Dependency Resolution](reference/resolver.md)\n    * [Features](reference/features.md)\n        * [Features Examples](reference/features-examples.md)\n    * [Profiles](reference/profiles.md)\n    * [Configuration](reference/config.md)\n    * [Environment Variables](reference/environment-variables.md)\n    * [Build Scripts](reference/build-scripts.md)\n        * [Build Script Examples](reference/build-script-examples.md)\n    * [Build Cache](reference/build-cache.md)\n    * [Package ID Specifications](reference/pkgid-spec.md)\n    * [External Tools](reference/external-tools.md)\n    * [Registries](reference/registries.md)\n        * [Registry Authentication](reference/registry-authentication.md)\n            * [Credential Provider Protocol](reference/credential-provider-protocol.md)\n        * [Running a Registry](reference/running-a-registry.md)\n            * [Registry Index](reference/registry-index.md)\n            * [Registry Web API](reference/registry-web-api.md)\n    * [SemVer Compatibility](reference/semver.md)\n    * [Future incompat report](reference/future-incompat-report.md)\n    * [Reporting build timings](reference/timings.md)\n    * [Lints](reference/lints.md)\n    * [Unstable Features](reference/unstable.md)\n\n* [Cargo Commands](commands/index.md)\n    * [General Commands](commands/general-commands.md)\n        * [cargo](commands/cargo.md)\n        * [cargo help](commands/cargo-help.md)\n        * [cargo version](commands/cargo-version.md)\n    * [Build Commands](commands/build-commands.md)\n        * [cargo bench](commands/cargo-bench.md)\n        * [cargo build](commands/cargo-build.md)\n        * [cargo check](commands/cargo-check.md)\n        * [cargo clean](commands/cargo-clean.md)\n        * [cargo clippy](commands/cargo-clippy.md)\n        * [cargo doc](commands/cargo-doc.md)\n        * [cargo fetch](commands/cargo-fetch.md)\n        * [cargo fix](commands/cargo-fix.md)\n        * [cargo fmt](commands/cargo-fmt.md)\n        * [cargo miri](commands/cargo-miri.md)\n        * [cargo run](commands/cargo-run.md)\n        * [cargo rustc](commands/cargo-rustc.md)\n        * [cargo rustdoc](commands/cargo-rustdoc.md)\n        * [cargo test](commands/cargo-test.md)\n    * [Manifest Commands](commands/manifest-commands.md)\n        * [cargo add](commands/cargo-add.md)\n        * [cargo generate-lockfile](commands/cargo-generate-lockfile.md)\n        * [cargo info](commands/cargo-info.md)\n        * [cargo locate-project](commands/cargo-locate-project.md)\n        * [cargo metadata](commands/cargo-metadata.md)\n        * [cargo pkgid](commands/cargo-pkgid.md)\n        * [cargo remove](commands/cargo-remove.md)\n        * [cargo tree](commands/cargo-tree.md)\n        * [cargo update](commands/cargo-update.md)\n        * [cargo vendor](commands/cargo-vendor.md)\n    * [Package Commands](commands/package-commands.md)\n        * [cargo init](commands/cargo-init.md)\n        * [cargo install](commands/cargo-install.md)\n        * [cargo new](commands/cargo-new.md)\n        * [cargo search](commands/cargo-search.md)\n        * [cargo uninstall](commands/cargo-uninstall.md)\n    * [Publishing Commands](commands/publishing-commands.md)\n        * [cargo login](commands/cargo-login.md)\n        * [cargo logout](commands/cargo-logout.md)\n        * [cargo owner](commands/cargo-owner.md)\n        * [cargo package](commands/cargo-package.md)\n        * [cargo publish](commands/cargo-publish.md)\n        * [cargo yank](commands/cargo-yank.md)\n    * [Report Commands](commands/report-commands.md)\n        * [cargo report](commands/cargo-report.md)\n        * [cargo report future-incompatibilities](commands/cargo-report-future-incompatibilities.md)\n    * [Deprecated and Removed](commands/deprecated-and-removed.md)\n\n* [FAQ](faq.md)\n* [Changelog](CHANGELOG.md)\n* [Appendix: Glossary](appendix/glossary.md)\n* [Appendix: Git Authentication](appendix/git-authentication.md)\n"
  },
  {
    "path": "src/doc/src/appendix/git-authentication.md",
    "content": "# Git Authentication\n\nCargo supports some forms of authentication when using git dependencies and\nregistries. This appendix contains some information for setting up git\nauthentication in a way that works with Cargo.\n\nIf you need other authentication methods, the [`net.git-fetch-with-cli`]\nconfig value can be set to cause Cargo to execute the `git` executable to\nhandle fetching remote repositories instead of using the built-in support.\nThis can be enabled with the `CARGO_NET_GIT_FETCH_WITH_CLI=true` environment\nvariable.\n\n> **Note:** Cargo does not require authentication for public git dependencies\n> so if you see an authentication failure in that context, ensure that the\n> URL is correct.\n\n## HTTPS authentication\n\nHTTPS authentication requires the [`credential.helper`] mechanism. There are\nmultiple credential helpers, and you specify the one you want to use in your\nglobal git configuration file.\n\n```ini\n# ~/.gitconfig\n\n[credential]\nhelper = store\n```\n\nCargo does not ask for passwords, so for most helpers you will need to give\nthe helper the initial username/password before running Cargo. One way to do\nthis is to run `git clone` of the private git repo and enter the\nusername/password.\n\n> **Tip:**<br>\n> macOS users may want to consider using the osxkeychain helper.<br>\n> Windows users may want to consider using the [GCM] helper.\n\n> **Note:** Windows users will need to make sure that the `sh` shell is\n> available in your `PATH`. This typically is available with the Git for\n> Windows installation.\n\n## SSH authentication\n\nSSH authentication requires `ssh-agent` to be running to acquire the SSH key.\nMake sure the appropriate environment variables are set up (`SSH_AUTH_SOCK` on\nmost Unix-like systems), and that the correct keys are added (with `ssh-add`).\n\nWindows can use Pageant (part of [PuTTY]) or `ssh-agent`.\nTo use `ssh-agent`, Cargo needs to use the OpenSSH that is distributed as part\nof Windows, as Cargo does not support the simulated Unix-domain sockets used\nby MinGW or Cygwin.\nMore information about installing with Windows can be found at the [Microsoft\ninstallation documentation] and the page on [key management] has instructions\non how to start `ssh-agent` and to add keys.\n\n> **Note:** Cargo does not support git's shorthand SSH URLs like\n> `git@example.com:user/repo.git`. Use a full SSH URL like\n> `ssh://git@example.com/user/repo.git`.\n\n> **Note:** SSH configuration files (like OpenSSH's `~/.ssh/config`) are not\n> used by Cargo's built-in SSH library. More advanced requirements should use\n> [`net.git-fetch-with-cli`].\n\n### SSH Known Hosts\n\nWhen connecting to an SSH host, Cargo must verify the identity of the host\nusing \"known hosts\", which are a list of host keys. Cargo can look for these\nknown hosts in OpenSSH-style `known_hosts` files located in their standard\nlocations (`.ssh/known_hosts` in your home directory, or\n`/etc/ssh/ssh_known_hosts` on Unix-like platforms or\n`%PROGRAMDATA%\\ssh\\ssh_known_hosts` on Windows). More information about these\nfiles can be found in the [sshd man page]. Alternatively, keys may be\nconfigured in a Cargo configuration file with [`net.ssh.known-hosts`].\n\nWhen connecting to an SSH host before the known hosts has been configured,\nCargo will display an error message instructing you how to add the host key.\nThis also includes a \"fingerprint\", which is a smaller hash of the host key,\nwhich should be easier to visually verify. The server administrator can get\nthe fingerprint by running `ssh-keygen` against the public key (for example,\n`ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub`). Well-known sites may\npublish their fingerprints on the web; for example GitHub posts theirs at\n<https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints>.\n\nCargo comes with the host keys for [github.com](https://github.com) built-in.\nIf those ever change, you can add the new keys to the config or known_hosts file.\n\n> **Note:** Cargo doesn't support the `@cert-authority` or `@revoked`\n> markers in `known_hosts` files. To make use of this functionality, use\n> [`net.git-fetch-with-cli`]. This is also a good tip if Cargo's SSH client\n> isn't behaving the way you expect it to.\n\n[`credential.helper`]: https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage\n[`net.git-fetch-with-cli`]: ../reference/config.md#netgit-fetch-with-cli\n[`net.ssh.known-hosts`]: ../reference/config.md#netsshknown-hosts\n[GCM]: https://github.com/microsoft/Git-Credential-Manager-Core/\n[PuTTY]: https://www.chiark.greenend.org.uk/~sgtatham/putty/\n[Microsoft installation documentation]: https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse\n[key management]: https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_keymanagement\n[sshd man page]: https://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT\n"
  },
  {
    "path": "src/doc/src/appendix/glossary.md",
    "content": "# Glossary\n\n## Artifact\n\nAn *artifact* is the file or set of files created as a result of the\ncompilation process. This includes linkable libraries, executable binaries,\nand generated documentation.\n\n## Cargo\n\n*Cargo* is the Rust [*package manager*](#package-manager), and the primary\ntopic of this book.\n\n## Cargo.lock\n\nSee [*lock file*](#lock-file).\n\n## Cargo.toml\n\nSee [*manifest*](#manifest).\n\n## Crate\n\nA Rust *crate* is either a library or an executable program, referred to as\neither a *library crate* or a *binary crate*, respectively.\n\nEvery [target](#target) defined for a Cargo [package](#package) is a *crate*.\n\nLoosely, the term *crate* may refer to either the source code of the target or\nto the compiled artifact that the target produces. It may also refer to a\ncompressed package fetched from a [registry](#registry).\n\nThe source code for a given crate may be subdivided into [*modules*](#module).\n\n## Edition\n\nA *Rust edition* is a developmental landmark of the Rust language. The\n[edition of a package][edition-field] is specified in the `Cargo.toml`\n[manifest](#manifest), and individual targets can specify which edition they\nuse. See the [Edition Guide] for more information.\n\n## Feature\n\nThe meaning of *feature* depends on the context:\n\n- A [*feature*][feature] is a named flag which allows for conditional\n  compilation. A feature can refer to an optional dependency, or an arbitrary\n  name defined in a `Cargo.toml` [manifest](#manifest) that can be checked\n  within source code.\n\n- Cargo has [*unstable feature flags*][cargo-unstable] which can be used to\n  enable experimental behavior of Cargo itself.\n\n- The Rust compiler and Rustdoc have their own unstable feature flags (see\n  [The Unstable Book][unstable-book] and [The Rustdoc\n  Book][rustdoc-unstable]).\n\n- CPU targets have [*target features*][target-feature] which specify\n  capabilities of a CPU.\n\n## Index\n\nThe *index* is the searchable list of [*crates*](#crate) in a\n[*registry*](#registry).\n\n## Lock file\n\nThe `Cargo.lock` *lock file* is a file that captures the exact version of\nevery dependency used in a [*workspace*](#workspace) or\n[*package*](#package). It is automatically generated by Cargo. See\n[Cargo.toml vs Cargo.lock].\n\n## Manifest\n\nA [*manifest*][manifest] is a description of a [package](#package) or a\n[workspace](#workspace) in a file named `Cargo.toml`.\n\nA [*virtual manifest*][virtual] is a `Cargo.toml` file that only describes a\nworkspace, and does not include a package.\n\n## Member\n\nA *member* is a [*package*](#package) that belongs to a\n[*workspace*](#workspace).\n\n## Module\n\nRust's module system is used to organize code into logical units called\n*modules*, which provide isolated namespaces within the code.\n\nThe source code for a given [crate](#crate) may be subdivided into one or more\nseparate modules. This is usually done to organize the code into areas of\nrelated functionality or to control the visible scope (public/private) of\nsymbols within the source (structs, functions, and so on).\n\nA [`Cargo.toml`](#manifest) file is primarily concerned with the\n[package](#package) it defines, its crates, and the packages of the crates on\nwhich they depend. Nevertheless, you will see the term \"module\" often when\nworking with Rust, so you should understand its relationship to a given crate.\n\n## Package\n\nA *package* is a collection of source files and a `Cargo.toml`\n[*manifest*](#manifest) file which describes the package. A package has a name\nand version which is used for specifying dependencies between packages.\n\nA package contains multiple [*targets*](#target), each of which is a\n[*crate*](#crate). The `Cargo.toml` file describes the type of the crates\n(binary or library) within the package, along with some metadata about each\none --- how each is to be built, what their direct dependencies are, etc., as\ndescribed throughout this book.\n\nThe *package root* is the directory where the package's `Cargo.toml` manifest\nis located. (Compare with [*workspace root*](#workspace).)\n\nThe [*package ID specification*][pkgid-spec], or *SPEC*, is a string used to\nuniquely reference a specific version of a package from a specific source.\n\nSmall to medium sized Rust projects will only need a single package, though it\nis common for them to have multiple crates.\n\nLarger projects may involve multiple packages, in which case Cargo\n[*workspaces*](#workspace) can be used to manage common dependencies and other\nrelated metadata between the packages.\n\n## Package manager\n\nBroadly speaking, a *package manager* is a program (or collection of related\nprograms) in a software ecosystem that automates the process of obtaining,\ninstalling, and upgrading artifacts. Within a programming language ecosystem,\na package manager is a developer-focused tool whose primary functionality is\nto download library artifacts and their dependencies from some central\nrepository; this capability is often combined with the ability to perform\nsoftware builds (by invoking the language-specific compiler).\n\n[*Cargo*](#cargo) is the package manager within the Rust ecosystem. Cargo\ndownloads your Rust [package](#package)’s dependencies\n([*artifacts*](#artifact) known as [*crates*](#crate)), compiles your\npackages, makes distributable packages, and (optionally) uploads them to\n[crates.io][], the Rust community’s [*package registry*](#registry).\n\n## Package registry\n\nSee [*registry*](#registry).\n\n## Project\n\nAnother name for a [package](#package).\n\n## Registry\n\nA *registry* is a service that contains a collection of downloadable\n[*crates*](#crate) that can be installed or used as dependencies for a\n[*package*](#package). The default registry in the Rust ecosystem is\n[crates.io](https://crates.io). The registry has an [*index*](#index) which\ncontains a list of all crates, and tells Cargo how to download the crates that\nare needed.\n\n## Source\n\nA *source* is a provider that contains [*crates*](#crate) that may be included\nas dependencies for a [*package*](#package). There are several kinds of\nsources:\n\n- **Registry source** --- See [registry](#registry).\n- **Local registry source** --- A set of crates stored as compressed files on\n  the filesystem. See [Local Registry Sources].\n- **Directory source** --- A set of crates stored as uncompressed files on the\n  filesystem. See [Directory Sources].\n- **Path source** --- An individual package located on the filesystem (such as a\n  [path dependency]) or a set of multiple packages (such as [path overrides]).\n- **Git source** --- Packages located in a git repository (such as a [git\n  dependency] or [git source]).\n\nSee [Source Replacement] for more information.\n\n## Spec\n\nSee [package ID specification](#package).\n\n## Target\n\nThe meaning of the term *target* depends on the context:\n\n- **Cargo Target** --- Cargo [*packages*](#package) consist of *targets* which\n  correspond to [*artifacts*](#artifact) that will be produced. Packages can\n  have library, binary, example, test, and benchmark targets. The\n  [list of targets][targets] are configured in the `Cargo.toml`\n  [*manifest*](#manifest), often inferred automatically by the [directory\n  layout] of the source files.\n- **Target Directory** --- Cargo places built artifacts in the *target* directory.\n  By default this is a directory named `target` at the [*workspace*](#workspace) root,\n  or the package root if not using a workspace. The directory may be changed with \n  the `--target-dir` command-line option, the `CARGO_TARGET_DIR` [environment variable],\n  or the `build.target-dir` [config option]. \n  For more information see the [build cache] documentation.\n- **Target Architecture** --- The OS and machine architecture for the built\n  artifacts are typically referred to as a *target*.\n- **Target Triple** --- A triple is a specific format for specifying a target\n  architecture. Triples may be referred to as a *target triple* which is the\n  architecture for the artifact produced, and the *host triple* which is the\n  architecture that the compiler is running on. The target triple can be\n  specified with the `--target` command-line option or the `build.target`\n  [config option]. The general format of the triple is\n  `<arch><sub>-<vendor>-<sys>-<abi>` where:\n\n  - `arch` = The base CPU architecture, for example `x86_64`, `i686`, `arm`,\n    `thumb`, `mips`, etc.\n  - `sub` = The CPU sub-architecture, for example `arm` has `v7`, `v7s`,\n    `v5te`, etc.\n  - `vendor` = The vendor, for example `unknown`, `apple`, `pc`, `nvidia`, etc.\n  - `sys` = The system name, for example `linux`, `windows`, `darwin`, etc.\n    `none` is typically used for bare-metal without an OS.\n  - `abi` = The ABI, for example `gnu`, `android`, `eabi`, etc.\n\n  Some parameters may be omitted. Run `rustc --print target-list` for a list of\n  supported targets.\n\n## Test Targets\n\nCargo *test targets* generate binaries which help verify proper operation and\ncorrectness of code. There are two types of test artifacts:\n\n* **Unit test** --- A *unit test* is an executable binary compiled directly from\n  a library or a binary target. It contains the entire contents of the library\n  or binary code, and runs `#[test]` annotated functions, intended to verify\n  individual units of code.\n* **Integration test target** --- An [*integration test\n  target*][integration-tests] is an executable binary compiled from a *test\n  target* which is a distinct [*crate*](#crate) whose source is located in the\n  `tests` directory or specified by the [`[[test]]` table][targets] in the\n  `Cargo.toml` [*manifest*](#manifest). It is intended to only test the public\n  API of a library, or execute a binary to verify its operation.\n\n## Workspace\n\nA [*workspace*][workspace] is a collection of one or more\n[*packages*](#package) that share common dependency resolution (with a shared\n`Cargo.lock` [*lock file*](#lock-file)), output directory, and various\nsettings such as profiles.\n\nA [*virtual workspace*][virtual] is a workspace where the root `Cargo.toml`\n[*manifest*](#manifest) does not define a package, and only lists the\nworkspace [*members*](#member).\n\nThe *workspace root* is the directory where the workspace's `Cargo.toml`\nmanifest is located. (Compare with [*package root*](#package).)\n\n\n[Cargo.toml vs Cargo.lock]: ../guide/cargo-toml-vs-cargo-lock.md\n[Directory Sources]: ../reference/source-replacement.md#directory-sources\n[Local Registry Sources]: ../reference/source-replacement.md#local-registry-sources\n[Source Replacement]: ../reference/source-replacement.md\n[build cache]: ../reference/build-cache.html\n[cargo-unstable]: ../reference/unstable.md\n[config option]: ../reference/config.md\n[crates.io]: https://crates.io/\n[directory layout]: ../guide/project-layout.md\n[edition guide]: ../../edition-guide/index.html\n[edition-field]: ../reference/manifest.md#the-edition-field\n[environment variable]: ../reference/environment-variables.md\n[feature]: ../reference/features.md\n[git dependency]: ../reference/specifying-dependencies.md#specifying-dependencies-from-git-repositories\n[git source]: ../reference/source-replacement.md\n[integration-tests]: ../reference/cargo-targets.md#integration-tests\n[manifest]: ../reference/manifest.md\n[path dependency]: ../reference/specifying-dependencies.md#specifying-path-dependencies\n[path overrides]: ../reference/overriding-dependencies.md#paths-overrides\n[pkgid-spec]: ../reference/pkgid-spec.md\n[rustdoc-unstable]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html\n[target-feature]: ../../reference/attributes/codegen.html#the-target_feature-attribute\n[targets]: ../reference/cargo-targets.md#configuring-a-target\n[unstable-book]: https://doc.rust-lang.org/nightly/unstable-book/index.html\n[virtual]: ../reference/workspaces.md\n[workspace]: ../reference/workspaces.md\n"
  },
  {
    "path": "src/doc/src/commands/build-commands.md",
    "content": "# Build Commands\n* [cargo bench](cargo-bench.md)\n* [cargo build](cargo-build.md)\n* [cargo check](cargo-check.md)\n* [cargo clean](cargo-clean.md)\n* [cargo clippy](cargo-clippy.md)\n* [cargo doc](cargo-doc.md)\n* [cargo fetch](cargo-fetch.md)\n* [cargo fix](cargo-fix.md)\n* [cargo fmt](cargo-fmt.md)\n* [cargo miri](cargo-miri.md)\n* [cargo run](cargo-run.md)\n* [cargo rustc](cargo-rustc.md)\n* [cargo rustdoc](cargo-rustdoc.md)\n* [cargo test](cargo-test.md)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-add.md",
    "content": "# cargo-add(1)\n## NAME\n\ncargo-add --- Add dependencies to a Cargo.toml manifest file\n\n## SYNOPSIS\n\n`cargo add` [_options_] _crate_...\\\n`cargo add` [_options_] `--path` _path_\\\n`cargo add` [_options_] `--git` _url_ [_crate_...]\n\n\n## DESCRIPTION\n\nThis command can add or modify dependencies.\n\nThe source for the dependency can be specified with:\n\n* _crate_`@`_version_: Fetch from a registry with a version constraint of \"_version_\"\n* `--path` _path_: Fetch from the specified _path_\n* `--git` _url_: Pull from a git repo at _url_\n\nIf no source is specified, then a best effort will be made to select one, including:\n\n* Existing dependencies in other tables (like `dev-dependencies`)\n* Workspace members\n* Latest release in the registry\n\nWhen you add a package that is already present, the existing entry will be updated with the flags specified.\n\nUpon successful invocation, the enabled (`+`) and disabled (`-`) [features] of the specified\ndependency will be listed in the command's output.\n\n[features]: ../reference/features.html\n\n## OPTIONS\n\n### Source options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-add---git\"><a class=\"option-anchor\" href=\"#option-cargo-add---git\"><code>--git</code> <em>url</em></a></dt>\n<dd class=\"option-desc\"><p><a href=\"../reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories\">Git URL to add the specified crate from</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---branch\"><a class=\"option-anchor\" href=\"#option-cargo-add---branch\"><code>--branch</code> <em>branch</em></a></dt>\n<dd class=\"option-desc\"><p>Branch to use when adding from git.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---tag\"><a class=\"option-anchor\" href=\"#option-cargo-add---tag\"><code>--tag</code> <em>tag</em></a></dt>\n<dd class=\"option-desc\"><p>Tag to use when adding from git.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---rev\"><a class=\"option-anchor\" href=\"#option-cargo-add---rev\"><code>--rev</code> <em>sha</em></a></dt>\n<dd class=\"option-desc\"><p>Specific commit to use when adding from git.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---path\"><a class=\"option-anchor\" href=\"#option-cargo-add---path\"><code>--path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p><a href=\"../reference/specifying-dependencies.html#specifying-path-dependencies\">Filesystem path</a> to local crate to add.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---base\"><a class=\"option-anchor\" href=\"#option-cargo-add---base\"><code>--base</code> <em>base</em></a></dt>\n<dd class=\"option-desc\"><p>The <a href=\"../reference/unstable.html#path-bases\">path base</a> to use when adding a local crate.</p>\n<p><a href=\"../reference/unstable.html#path-bases\">Unstable (nightly-only)</a></p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---registry\"><a class=\"option-anchor\" href=\"#option-cargo-add---registry\"><code>--registry</code> <em>registry</em></a></dt>\n<dd class=\"option-desc\"><p>Name of the registry to use. Registry names are defined in <a href=\"../reference/config.html\">Cargo config\nfiles</a>. If not specified, the default registry is used,\nwhich is defined by the <code>registry.default</code> config key which defaults to\n<code>crates-io</code>.</p>\n</dd>\n\n\n</dl>\n\n### Section options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-add---dev\"><a class=\"option-anchor\" href=\"#option-cargo-add---dev\"><code>--dev</code></a></dt>\n<dd class=\"option-desc\"><p>Add as a <a href=\"../reference/specifying-dependencies.html#development-dependencies\">development dependency</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---build\"><a class=\"option-anchor\" href=\"#option-cargo-add---build\"><code>--build</code></a></dt>\n<dd class=\"option-desc\"><p>Add as a <a href=\"../reference/specifying-dependencies.html#build-dependencies\">build dependency</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---target\"><a class=\"option-anchor\" href=\"#option-cargo-add---target\"><code>--target</code> <em>target</em></a></dt>\n<dd class=\"option-desc\"><p>Add as a dependency to the <a href=\"../reference/specifying-dependencies.html#platform-specific-dependencies\">given target platform</a>.</p>\n<p>To avoid unexpected shell expansions, you may use quotes around each target, e.g., <code>--target 'cfg(unix)'</code>.</p>\n</dd>\n\n\n</dl>\n\n### Dependency options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-add---dry-run\"><a class=\"option-anchor\" href=\"#option-cargo-add---dry-run\"><code>--dry-run</code></a></dt>\n<dd class=\"option-desc\"><p>Don’t actually write the manifest</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---rename\"><a class=\"option-anchor\" href=\"#option-cargo-add---rename\"><code>--rename</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p><a href=\"../reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml\">Rename</a> the dependency.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---optional\"><a class=\"option-anchor\" href=\"#option-cargo-add---optional\"><code>--optional</code></a></dt>\n<dd class=\"option-desc\"><p>Mark the dependency as <a href=\"../reference/features.html#optional-dependencies\">optional</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---no-optional\"><a class=\"option-anchor\" href=\"#option-cargo-add---no-optional\"><code>--no-optional</code></a></dt>\n<dd class=\"option-desc\"><p>Mark the dependency as <a href=\"../reference/features.html#optional-dependencies\">required</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---public\"><a class=\"option-anchor\" href=\"#option-cargo-add---public\"><code>--public</code></a></dt>\n<dd class=\"option-desc\"><p>Mark the dependency as public.</p>\n<p>The dependency can be referenced in your library’s public API.</p>\n<p><a href=\"../reference/unstable.html#public-dependency\">Unstable (nightly-only)</a></p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---no-public\"><a class=\"option-anchor\" href=\"#option-cargo-add---no-public\"><code>--no-public</code></a></dt>\n<dd class=\"option-desc\"><p>Mark the dependency as private.</p>\n<p>While you can use the crate in your implementation, it cannot be referenced in your public API.</p>\n<p><a href=\"../reference/unstable.html#public-dependency\">Unstable (nightly-only)</a></p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-add---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Disable the <a href=\"../reference/features.html#dependency-features\">default features</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---default-features\"><a class=\"option-anchor\" href=\"#option-cargo-add---default-features\"><code>--default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Re-enable the <a href=\"../reference/features.html#dependency-features\">default features</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add--F\"><a class=\"option-anchor\" href=\"#option-cargo-add--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-add---features\"><a class=\"option-anchor\" href=\"#option-cargo-add---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of <a href=\"../reference/features.html#dependency-features\">features to\nactivate</a>. When adding multiple\ncrates, the features for a specific crate may be enabled with\n<code>package-name/feature-name</code> syntax. This flag may be specified multiple times,\nwhich enables all specified features.</p>\n</dd>\n\n\n</dl>\n\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-add--v\"><a class=\"option-anchor\" href=\"#option-cargo-add--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-add---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-add---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add--q\"><a class=\"option-anchor\" href=\"#option-cargo-add--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-add---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-add---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---color\"><a class=\"option-anchor\" href=\"#option-cargo-add---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-add---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-add---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add--p\"><a class=\"option-anchor\" href=\"#option-cargo-add--p\"><code>-p</code> <em>spec</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-add---package\"><a class=\"option-anchor\" href=\"#option-cargo-add---package\"><code>--package</code> <em>spec</em></a></dt>\n<dd class=\"option-desc\"><p>Add dependencies to only the specified package.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-add---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---locked\"><a class=\"option-anchor\" href=\"#option-cargo-add---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---offline\"><a class=\"option-anchor\" href=\"#option-cargo-add---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-add---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-add-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-add-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add---config\"><a class=\"option-anchor\" href=\"#option-cargo-add---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add--C\"><a class=\"option-anchor\" href=\"#option-cargo-add--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add--h\"><a class=\"option-anchor\" href=\"#option-cargo-add--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-add---help\"><a class=\"option-anchor\" href=\"#option-cargo-add---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-add--Z\"><a class=\"option-anchor\" href=\"#option-cargo-add--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Add `regex` as a dependency\n\n       cargo add regex\n\n2. Add `trybuild` as a dev-dependency\n\n       cargo add --dev trybuild\n\n3. Add an older version of `nom` as a dependency\n\n       cargo add nom@5\n\n4. Add support for serializing data structures to json with `derive`s\n\n       cargo add serde serde_json -F serde/derive\n\n5. Add `windows` as a platform specific dependency on `cfg(windows)`\n\n       cargo add windows --target 'cfg(windows)'\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-remove(1)](cargo-remove.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-bench.md",
    "content": "# cargo-bench(1)\n## NAME\n\ncargo-bench --- Execute benchmarks of a package\n\n## SYNOPSIS\n\n`cargo bench` [_options_] [_benchname_] [`--` _bench-options_]\n\n## DESCRIPTION\n\nCompile and execute benchmarks.\n\nThe benchmark filtering argument _benchname_ and all the arguments following\nthe two dashes (`--`) are passed to the benchmark binaries and thus to\n_libtest_ (rustc's built in unit-test and micro-benchmarking framework). If\nyou are passing arguments to both Cargo and the binary, the ones after `--` go\nto the binary, the ones before go to Cargo. For details about libtest's\narguments see the output of `cargo bench -- --help` and check out the rustc\nbook's chapter on how tests work at\n<https://doc.rust-lang.org/rustc/tests/index.html>.\n\nAs an example, this will run only the benchmark named `foo` (and skip other\nsimilarly named benchmarks like `foobar`):\n\n    cargo bench -- foo --exact\n\nBenchmarks are built with the `--test` option to `rustc` which creates a\nspecial executable by linking your code with libtest. The executable\nautomatically runs all functions annotated with the `#[bench]` attribute.\nCargo passes the `--bench` flag to the test harness to tell it to run\nonly benchmarks, regardless of whether the harness is libtest or a custom harness.\n\nThe libtest harness may be disabled by setting `harness = false` in the target\nmanifest settings, in which case your code will need to provide its own `main`\nfunction to handle running benchmarks.\n\n> **Note**: The\n> [`#[bench]` attribute](https://doc.rust-lang.org/nightly/unstable-book/library-features/test.html)\n> is currently unstable and only available on the\n> [nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html).\n> There are some packages available on\n> [crates.io](https://crates.io/keywords/benchmark) that may help with\n> running benchmarks on the stable channel, such as\n> [Criterion](https://crates.io/crates/criterion).\n\nBy default, `cargo bench` uses the [`bench` profile], which enables\noptimizations and disables debugging information. If you need to debug a\nbenchmark, you can use the `--profile=dev` command-line option to switch to\nthe dev profile. You can then run the debug-enabled benchmark within a\ndebugger.\n\n[`bench` profile]: ../reference/profiles.html#bench\n\n### Working directory of benchmarks\n\nThe working directory of every benchmark is set to the root directory of the \npackage the benchmark belongs to.\nSetting the working directory of benchmarks to the package's root directory \nmakes it possible for benchmarks to reliably access the package's files using \nrelative paths, regardless from where `cargo bench` was executed from.\n\n## OPTIONS\n\n### Benchmark Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-bench---no-run\"><a class=\"option-anchor\" href=\"#option-cargo-bench---no-run\"><code>--no-run</code></a></dt>\n<dd class=\"option-desc\"><p>Compile, but don’t run benchmarks.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---no-fail-fast\"><a class=\"option-anchor\" href=\"#option-cargo-bench---no-fail-fast\"><code>--no-fail-fast</code></a></dt>\n<dd class=\"option-desc\"><p>Run all benchmarks regardless of failure. Without this flag, Cargo will exit\nafter the first executable fails. The Rust test harness will run all benchmarks\nwithin the executable to completion, this flag only applies to the executable\nas a whole.</p>\n</dd>\n\n\n</dl>\n\n### Package Selection\n\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n`--manifest-path` is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n\nThe default members of a workspace can be set explicitly with the\n`workspace.default-members` key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n`--workspace`), and a non-virtual workspace will include only the root crate itself.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-bench--p\"><a class=\"option-anchor\" href=\"#option-cargo-bench--p\"><code>-p</code> <em>spec</em>…</a></dt>\n<dt class=\"option-term\" id=\"option-cargo-bench---package\"><a class=\"option-anchor\" href=\"#option-cargo-bench---package\"><code>--package</code> <em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Benchmark only the specified packages. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---workspace\"><a class=\"option-anchor\" href=\"#option-cargo-bench---workspace\"><code>--workspace</code></a></dt>\n<dd class=\"option-desc\"><p>Benchmark all members in the workspace.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---all\"><a class=\"option-anchor\" href=\"#option-cargo-bench---all\"><code>--all</code></a></dt>\n<dd class=\"option-desc\"><p>Deprecated alias for <code>--workspace</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---exclude\"><a class=\"option-anchor\" href=\"#option-cargo-bench---exclude\"><code>--exclude</code> <em>SPEC</em>…</a></dt>\n<dd class=\"option-desc\"><p>Exclude the specified packages. Must be used in conjunction with the\n<code>--workspace</code> flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.</p>\n</dd>\n\n\n</dl>\n\n### Target Selection\n\nWhen no target selection options are given, `cargo bench` will build the\nfollowing targets of the selected packages:\n\n- lib --- used to link with binaries and benchmarks\n- bins (only if benchmark targets are built and required features are\n  available)\n- lib as a benchmark\n- bins as benchmarks\n- benchmark targets\n\nThe default behavior can be changed by setting the `bench` flag for the target\nin the manifest settings. Setting examples to `bench = true` will build and\nrun the example as a benchmark, replacing the example's `main` function with\nthe libtest harness.\n\nSetting targets to `bench = false` will stop them from being benchmarked by\ndefault. Target selection options that take a target by name (such as\n`--example foo`) ignore the `bench` flag and will always benchmark the given\ntarget.\n\nSee [Configuring a target](../reference/cargo-targets.html#configuring-a-target)\nfor more information on per-target settings.\n\nBinary targets are automatically built if there is an integration test or\nbenchmark being selected to benchmark. This allows an integration\ntest to execute the binary to exercise and test its behavior. \nThe `CARGO_BIN_EXE_<name>`\n[environment variable](../reference/environment-variables.html#environment-variables-cargo-sets-for-crates)\nis set when the integration test is built and run so that it can use the\n[`env` macro](https://doc.rust-lang.org/std/macro.env.html) or the \n[`var` function](https://doc.rust-lang.org/std/env/fn.var.html) to locate the\nexecutable.\n\nPassing target selection flags will benchmark only the specified\ntargets. \n\nNote that `--bin`, `--example`, `--test` and `--bench` flags also \nsupport common Unix glob patterns like `*`, `?` and `[]`. However, to avoid your \nshell accidentally expanding glob patterns before Cargo handles them, you must \nuse single quotes or double quotes around each glob pattern.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-bench---lib\"><a class=\"option-anchor\" href=\"#option-cargo-bench---lib\"><code>--lib</code></a></dt>\n<dd class=\"option-desc\"><p>Benchmark the package’s library.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---bin\"><a class=\"option-anchor\" href=\"#option-cargo-bench---bin\"><code>--bin</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Benchmark the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---bins\"><a class=\"option-anchor\" href=\"#option-cargo-bench---bins\"><code>--bins</code></a></dt>\n<dd class=\"option-desc\"><p>Benchmark all binary targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---example\"><a class=\"option-anchor\" href=\"#option-cargo-bench---example\"><code>--example</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Benchmark the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---examples\"><a class=\"option-anchor\" href=\"#option-cargo-bench---examples\"><code>--examples</code></a></dt>\n<dd class=\"option-desc\"><p>Benchmark all example targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---test\"><a class=\"option-anchor\" href=\"#option-cargo-bench---test\"><code>--test</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Benchmark the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---tests\"><a class=\"option-anchor\" href=\"#option-cargo-bench---tests\"><code>--tests</code></a></dt>\n<dd class=\"option-desc\"><p>Benchmark all targets that have the <code>test = true</code> manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the <code>test</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---bench\"><a class=\"option-anchor\" href=\"#option-cargo-bench---bench\"><code>--bench</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Benchmark the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---benches\"><a class=\"option-anchor\" href=\"#option-cargo-bench---benches\"><code>--benches</code></a></dt>\n<dd class=\"option-desc\"><p>Benchmark all targets that have the <code>bench = true</code>\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the <code>bench</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---all-targets\"><a class=\"option-anchor\" href=\"#option-cargo-bench---all-targets\"><code>--all-targets</code></a></dt>\n<dd class=\"option-desc\"><p>Benchmark all targets. This is equivalent to specifying <code>--lib --bins --tests --benches --examples</code>.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-bench--F\"><a class=\"option-anchor\" href=\"#option-cargo-bench--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-bench---features\"><a class=\"option-anchor\" href=\"#option-cargo-bench---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-bench---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-bench---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Compilation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-bench---target\"><a class=\"option-anchor\" href=\"#option-cargo-bench---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Benchmark for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---profile\"><a class=\"option-anchor\" href=\"#option-cargo-bench---profile\"><code>--profile</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Benchmark with the given profile.\nSee <a href=\"../reference/profiles.html\">the reference</a> for more details on profiles.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---timings\"><a class=\"option-anchor\" href=\"#option-cargo-bench---timings\"><code>--timings</code></a></dt>\n<dd class=\"option-desc\"><p>Output information how long each compilation takes, and track concurrency\ninformation over time.</p>\n<p>A file <code>cargo-timing.html</code> will be written to the <code>target/cargo-timings</code>\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine-readable timing data.</p>\n</dd>\n\n\n\n</dl>\n\n### Output Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-bench---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-bench---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to <code>target</code> in the root of the workspace.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\nBy default the Rust test harness hides output from benchmark execution to keep\nresults readable. Benchmark output can be recovered (e.g., for debugging) by\npassing `--no-capture` to the benchmark binaries:\n\n    cargo bench -- --no-capture\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-bench--v\"><a class=\"option-anchor\" href=\"#option-cargo-bench--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-bench---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-bench---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench--q\"><a class=\"option-anchor\" href=\"#option-cargo-bench--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-bench---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-bench---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---color\"><a class=\"option-anchor\" href=\"#option-cargo-bench---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---message-format\"><a class=\"option-anchor\" href=\"#option-cargo-bench---message-format\"><code>--message-format</code> <em>fmt</em></a></dt>\n<dd class=\"option-desc\"><p>The output format for diagnostic messages. Can be specified multiple times\nand consists of comma-separated values. Valid values:</p>\n<ul>\n<li><code>human</code> (default): Display in a human-readable text format. Conflicts with\n<code>short</code> and <code>json</code>.</li>\n<li><code>short</code>: Emit shorter, human-readable text messages. Conflicts with <code>human</code>\nand <code>json</code>.</li>\n<li><code>json</code>: Emit JSON messages to stdout. See\n<a href=\"../reference/external-tools.html#json-messages\">the reference</a>\nfor more details. Conflicts with <code>human</code> and <code>short</code>.</li>\n<li><code>json-diagnostic-short</code>: Ensure the <code>rendered</code> field of JSON messages contains\nthe “short” rendering from rustc. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-diagnostic-rendered-ansi</code>: Ensure the <code>rendered</code> field of JSON messages\ncontains embedded ANSI color codes for respecting rustc’s default color\nscheme. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-render-diagnostics</code>: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo’s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with <code>human</code> or <code>short</code>.</li>\n</ul>\n</dd>\n\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-bench---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-bench---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-bench---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---locked\"><a class=\"option-anchor\" href=\"#option-cargo-bench---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---offline\"><a class=\"option-anchor\" href=\"#option-cargo-bench---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-bench---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-bench-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-bench-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench---config\"><a class=\"option-anchor\" href=\"#option-cargo-bench---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench--C\"><a class=\"option-anchor\" href=\"#option-cargo-bench--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench--h\"><a class=\"option-anchor\" href=\"#option-cargo-bench--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-bench---help\"><a class=\"option-anchor\" href=\"#option-cargo-bench---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-bench--Z\"><a class=\"option-anchor\" href=\"#option-cargo-bench--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n### Miscellaneous Options\n\nThe `--jobs` argument affects the building of the benchmark executable but\ndoes not affect how many threads are used when running the benchmarks. The\nRust test harness runs benchmarks serially in a single thread.\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-bench--j\"><a class=\"option-anchor\" href=\"#option-cargo-bench--j\"><code>-j</code> <em>N</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-bench---jobs\"><a class=\"option-anchor\" href=\"#option-cargo-bench---jobs\"><code>--jobs</code> <em>N</em></a></dt>\n<dd class=\"option-desc\"><p>Number of parallel jobs to run. May also be specified with the\n<code>build.jobs</code> <a href=\"../reference/config.html\">config value</a>. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string <code>default</code> is provided, it sets the value back to defaults.\nShould not be 0.</p>\n</dd>\n\n</dl>\n\nWhile `cargo bench` involves compilation, it does not provide a `--keep-going`\nflag. Use `--no-fail-fast` to run as many benchmarks as possible without\nstopping at the first failure. To \"compile\" as many benchmarks as possible, use\n`--benches` to build benchmark binaries separately. For example:\n\n    cargo build --benches --release --keep-going\n    cargo bench --no-fail-fast\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Build and execute all the benchmarks of the current package:\n\n       cargo bench\n\n2. Run only a specific benchmark within a specific benchmark target:\n\n       cargo bench --bench bench_name -- modname::some_benchmark\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-test(1)](cargo-test.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-build.md",
    "content": "# cargo-build(1)\n## NAME\n\ncargo-build --- Compile the current package\n\n## SYNOPSIS\n\n`cargo build` [_options_]\n\n## DESCRIPTION\n\nCompile local packages and all of their dependencies.\n\n## OPTIONS\n\n### Package Selection\n\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n`--manifest-path` is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n\nThe default members of a workspace can be set explicitly with the\n`workspace.default-members` key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n`--workspace`), and a non-virtual workspace will include only the root crate itself.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-build--p\"><a class=\"option-anchor\" href=\"#option-cargo-build--p\"><code>-p</code> <em>spec</em>…</a></dt>\n<dt class=\"option-term\" id=\"option-cargo-build---package\"><a class=\"option-anchor\" href=\"#option-cargo-build---package\"><code>--package</code> <em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Build only the specified packages. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---workspace\"><a class=\"option-anchor\" href=\"#option-cargo-build---workspace\"><code>--workspace</code></a></dt>\n<dd class=\"option-desc\"><p>Build all members in the workspace.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---all\"><a class=\"option-anchor\" href=\"#option-cargo-build---all\"><code>--all</code></a></dt>\n<dd class=\"option-desc\"><p>Deprecated alias for <code>--workspace</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---exclude\"><a class=\"option-anchor\" href=\"#option-cargo-build---exclude\"><code>--exclude</code> <em>SPEC</em>…</a></dt>\n<dd class=\"option-desc\"><p>Exclude the specified packages. Must be used in conjunction with the\n<code>--workspace</code> flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.</p>\n</dd>\n\n\n</dl>\n\n### Target Selection\n\nWhen no target selection options are given, `cargo build` will build all\nbinary and library targets of the selected packages. Binaries are skipped if\nthey have `required-features` that are missing.\n\nBinary targets are automatically built if there is an integration test or\nbenchmark being selected to build. This allows an integration\ntest to execute the binary to exercise and test its behavior. \nThe `CARGO_BIN_EXE_<name>`\n[environment variable](../reference/environment-variables.html#environment-variables-cargo-sets-for-crates)\nis set when the integration test is built and run so that it can use the\n[`env` macro](https://doc.rust-lang.org/std/macro.env.html) or the \n[`var` function](https://doc.rust-lang.org/std/env/fn.var.html) to locate the\nexecutable.\n\nPassing target selection flags will build only the specified\ntargets. \n\nNote that `--bin`, `--example`, `--test` and `--bench` flags also \nsupport common Unix glob patterns like `*`, `?` and `[]`. However, to avoid your \nshell accidentally expanding glob patterns before Cargo handles them, you must \nuse single quotes or double quotes around each glob pattern.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-build---lib\"><a class=\"option-anchor\" href=\"#option-cargo-build---lib\"><code>--lib</code></a></dt>\n<dd class=\"option-desc\"><p>Build the package’s library.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---bin\"><a class=\"option-anchor\" href=\"#option-cargo-build---bin\"><code>--bin</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Build the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---bins\"><a class=\"option-anchor\" href=\"#option-cargo-build---bins\"><code>--bins</code></a></dt>\n<dd class=\"option-desc\"><p>Build all binary targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---example\"><a class=\"option-anchor\" href=\"#option-cargo-build---example\"><code>--example</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Build the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---examples\"><a class=\"option-anchor\" href=\"#option-cargo-build---examples\"><code>--examples</code></a></dt>\n<dd class=\"option-desc\"><p>Build all example targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---test\"><a class=\"option-anchor\" href=\"#option-cargo-build---test\"><code>--test</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Build the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---tests\"><a class=\"option-anchor\" href=\"#option-cargo-build---tests\"><code>--tests</code></a></dt>\n<dd class=\"option-desc\"><p>Build all targets that have the <code>test = true</code> manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the <code>test</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---bench\"><a class=\"option-anchor\" href=\"#option-cargo-build---bench\"><code>--bench</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Build the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---benches\"><a class=\"option-anchor\" href=\"#option-cargo-build---benches\"><code>--benches</code></a></dt>\n<dd class=\"option-desc\"><p>Build all targets that have the <code>bench = true</code>\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the <code>bench</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---all-targets\"><a class=\"option-anchor\" href=\"#option-cargo-build---all-targets\"><code>--all-targets</code></a></dt>\n<dd class=\"option-desc\"><p>Build all targets. This is equivalent to specifying <code>--lib --bins --tests --benches --examples</code>.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-build--F\"><a class=\"option-anchor\" href=\"#option-cargo-build--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-build---features\"><a class=\"option-anchor\" href=\"#option-cargo-build---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-build---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-build---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Compilation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-build---target\"><a class=\"option-anchor\" href=\"#option-cargo-build---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Build for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build--r\"><a class=\"option-anchor\" href=\"#option-cargo-build--r\"><code>-r</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-build---release\"><a class=\"option-anchor\" href=\"#option-cargo-build---release\"><code>--release</code></a></dt>\n<dd class=\"option-desc\"><p>Build optimized artifacts with the <code>release</code> profile.\nSee also the <code>--profile</code> option for choosing a specific profile by name.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---profile\"><a class=\"option-anchor\" href=\"#option-cargo-build---profile\"><code>--profile</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Build with the given profile.\nSee <a href=\"../reference/profiles.html\">the reference</a> for more details on profiles.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---timings\"><a class=\"option-anchor\" href=\"#option-cargo-build---timings\"><code>--timings</code></a></dt>\n<dd class=\"option-desc\"><p>Output information how long each compilation takes, and track concurrency\ninformation over time.</p>\n<p>A file <code>cargo-timing.html</code> will be written to the <code>target/cargo-timings</code>\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine-readable timing data.</p>\n</dd>\n\n\n\n</dl>\n\n### Output Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-build---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-build---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to <code>target</code> in the root of the workspace.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---artifact-dir\"><a class=\"option-anchor\" href=\"#option-cargo-build---artifact-dir\"><code>--artifact-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Copy final artifacts to this directory.</p>\n<p>This option is unstable and available only on the\n<a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly channel</a>\nand requires the <code>-Z unstable-options</code> flag to enable.\nSee <a href=\"https://github.com/rust-lang/cargo/issues/6790\">https://github.com/rust-lang/cargo/issues/6790</a> for more information.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-build--v\"><a class=\"option-anchor\" href=\"#option-cargo-build--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-build---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-build---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build--q\"><a class=\"option-anchor\" href=\"#option-cargo-build--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-build---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-build---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---color\"><a class=\"option-anchor\" href=\"#option-cargo-build---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---message-format\"><a class=\"option-anchor\" href=\"#option-cargo-build---message-format\"><code>--message-format</code> <em>fmt</em></a></dt>\n<dd class=\"option-desc\"><p>The output format for diagnostic messages. Can be specified multiple times\nand consists of comma-separated values. Valid values:</p>\n<ul>\n<li><code>human</code> (default): Display in a human-readable text format. Conflicts with\n<code>short</code> and <code>json</code>.</li>\n<li><code>short</code>: Emit shorter, human-readable text messages. Conflicts with <code>human</code>\nand <code>json</code>.</li>\n<li><code>json</code>: Emit JSON messages to stdout. See\n<a href=\"../reference/external-tools.html#json-messages\">the reference</a>\nfor more details. Conflicts with <code>human</code> and <code>short</code>.</li>\n<li><code>json-diagnostic-short</code>: Ensure the <code>rendered</code> field of JSON messages contains\nthe “short” rendering from rustc. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-diagnostic-rendered-ansi</code>: Ensure the <code>rendered</code> field of JSON messages\ncontains embedded ANSI color codes for respecting rustc’s default color\nscheme. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-render-diagnostics</code>: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo’s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with <code>human</code> or <code>short</code>.</li>\n</ul>\n</dd>\n\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-build---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-build---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-build---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---locked\"><a class=\"option-anchor\" href=\"#option-cargo-build---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---offline\"><a class=\"option-anchor\" href=\"#option-cargo-build---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-build---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-build-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-build-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build---config\"><a class=\"option-anchor\" href=\"#option-cargo-build---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build--C\"><a class=\"option-anchor\" href=\"#option-cargo-build--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build--h\"><a class=\"option-anchor\" href=\"#option-cargo-build--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-build---help\"><a class=\"option-anchor\" href=\"#option-cargo-build---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-build--Z\"><a class=\"option-anchor\" href=\"#option-cargo-build--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n### Miscellaneous Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-build--j\"><a class=\"option-anchor\" href=\"#option-cargo-build--j\"><code>-j</code> <em>N</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-build---jobs\"><a class=\"option-anchor\" href=\"#option-cargo-build---jobs\"><code>--jobs</code> <em>N</em></a></dt>\n<dd class=\"option-desc\"><p>Number of parallel jobs to run. May also be specified with the\n<code>build.jobs</code> <a href=\"../reference/config.html\">config value</a>. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string <code>default</code> is provided, it sets the value back to defaults.\nShould not be 0.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-build---keep-going\"><a class=\"option-anchor\" href=\"#option-cargo-build---keep-going\"><code>--keep-going</code></a></dt>\n<dd class=\"option-desc\"><p>Build as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.</p>\n<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,\none of which fails to build, <code>cargo build -j1</code> may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas <code>cargo build -j1 --keep-going</code> would definitely run both\nbuilds, even if the one run first fails.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-build---future-incompat-report\"><a class=\"option-anchor\" href=\"#option-cargo-build---future-incompat-report\"><code>--future-incompat-report</code></a></dt>\n<dd class=\"option-desc\"><p>Displays a future-incompat report for any future-incompatible warnings\nproduced during execution of this command</p>\n<p>See <a href=\"cargo-report.html\">cargo-report(1)</a></p>\n</dd>\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Build the local package and all of its dependencies:\n\n       cargo build\n\n2. Build with optimizations:\n\n       cargo build --release\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-rustc(1)](cargo-rustc.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-check.md",
    "content": "# cargo-check(1)\n## NAME\n\ncargo-check --- Check the current package\n\n## SYNOPSIS\n\n`cargo check` [_options_]\n\n## DESCRIPTION\n\nCheck a local package and all of its dependencies for errors. This will\nessentially compile the packages without performing the final step of code\ngeneration, which is faster than running `cargo build`. The compiler will save\nmetadata files to disk so that future runs will reuse them if the source has\nnot been modified. Some diagnostics and errors are only emitted during code\ngeneration, so they inherently won't be reported with `cargo check`.\n\n## OPTIONS\n\n### Package Selection\n\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n`--manifest-path` is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n\nThe default members of a workspace can be set explicitly with the\n`workspace.default-members` key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n`--workspace`), and a non-virtual workspace will include only the root crate itself.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-check--p\"><a class=\"option-anchor\" href=\"#option-cargo-check--p\"><code>-p</code> <em>spec</em>…</a></dt>\n<dt class=\"option-term\" id=\"option-cargo-check---package\"><a class=\"option-anchor\" href=\"#option-cargo-check---package\"><code>--package</code> <em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Check only the specified packages. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---workspace\"><a class=\"option-anchor\" href=\"#option-cargo-check---workspace\"><code>--workspace</code></a></dt>\n<dd class=\"option-desc\"><p>Check all members in the workspace.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---all\"><a class=\"option-anchor\" href=\"#option-cargo-check---all\"><code>--all</code></a></dt>\n<dd class=\"option-desc\"><p>Deprecated alias for <code>--workspace</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---exclude\"><a class=\"option-anchor\" href=\"#option-cargo-check---exclude\"><code>--exclude</code> <em>SPEC</em>…</a></dt>\n<dd class=\"option-desc\"><p>Exclude the specified packages. Must be used in conjunction with the\n<code>--workspace</code> flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.</p>\n</dd>\n\n\n</dl>\n\n### Target Selection\n\nWhen no target selection options are given, `cargo check` will check all\nbinary and library targets of the selected packages. Binaries are skipped if\nthey have `required-features` that are missing.\n\nPassing target selection flags will check only the specified\ntargets. \n\nNote that `--bin`, `--example`, `--test` and `--bench` flags also \nsupport common Unix glob patterns like `*`, `?` and `[]`. However, to avoid your \nshell accidentally expanding glob patterns before Cargo handles them, you must \nuse single quotes or double quotes around each glob pattern.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-check---lib\"><a class=\"option-anchor\" href=\"#option-cargo-check---lib\"><code>--lib</code></a></dt>\n<dd class=\"option-desc\"><p>Check the package’s library.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---bin\"><a class=\"option-anchor\" href=\"#option-cargo-check---bin\"><code>--bin</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Check the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---bins\"><a class=\"option-anchor\" href=\"#option-cargo-check---bins\"><code>--bins</code></a></dt>\n<dd class=\"option-desc\"><p>Check all binary targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---example\"><a class=\"option-anchor\" href=\"#option-cargo-check---example\"><code>--example</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Check the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---examples\"><a class=\"option-anchor\" href=\"#option-cargo-check---examples\"><code>--examples</code></a></dt>\n<dd class=\"option-desc\"><p>Check all example targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---test\"><a class=\"option-anchor\" href=\"#option-cargo-check---test\"><code>--test</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Check the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---tests\"><a class=\"option-anchor\" href=\"#option-cargo-check---tests\"><code>--tests</code></a></dt>\n<dd class=\"option-desc\"><p>Check all targets that have the <code>test = true</code> manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the <code>test</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---bench\"><a class=\"option-anchor\" href=\"#option-cargo-check---bench\"><code>--bench</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Check the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---benches\"><a class=\"option-anchor\" href=\"#option-cargo-check---benches\"><code>--benches</code></a></dt>\n<dd class=\"option-desc\"><p>Check all targets that have the <code>bench = true</code>\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the <code>bench</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---all-targets\"><a class=\"option-anchor\" href=\"#option-cargo-check---all-targets\"><code>--all-targets</code></a></dt>\n<dd class=\"option-desc\"><p>Check all targets. This is equivalent to specifying <code>--lib --bins --tests --benches --examples</code>.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-check--F\"><a class=\"option-anchor\" href=\"#option-cargo-check--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-check---features\"><a class=\"option-anchor\" href=\"#option-cargo-check---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-check---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-check---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Compilation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-check---target\"><a class=\"option-anchor\" href=\"#option-cargo-check---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Check for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check--r\"><a class=\"option-anchor\" href=\"#option-cargo-check--r\"><code>-r</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-check---release\"><a class=\"option-anchor\" href=\"#option-cargo-check---release\"><code>--release</code></a></dt>\n<dd class=\"option-desc\"><p>Check optimized artifacts with the <code>release</code> profile.\nSee also the <code>--profile</code> option for choosing a specific profile by name.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---profile\"><a class=\"option-anchor\" href=\"#option-cargo-check---profile\"><code>--profile</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Check with the given profile.</p>\n<p>As a special case, specifying the <code>test</code> profile will also enable checking in\ntest mode which will enable checking tests and enable the <code>test</code> cfg option.\nSee <a href=\"https://doc.rust-lang.org/rustc/tests/index.html\">rustc tests</a> for more\ndetail.</p>\n<p>See <a href=\"../reference/profiles.html\">the reference</a> for more details on profiles.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---timings\"><a class=\"option-anchor\" href=\"#option-cargo-check---timings\"><code>--timings</code></a></dt>\n<dd class=\"option-desc\"><p>Output information how long each compilation takes, and track concurrency\ninformation over time.</p>\n<p>A file <code>cargo-timing.html</code> will be written to the <code>target/cargo-timings</code>\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine-readable timing data.</p>\n</dd>\n\n\n\n</dl>\n\n### Output Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-check---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-check---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to <code>target</code> in the root of the workspace.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-check--v\"><a class=\"option-anchor\" href=\"#option-cargo-check--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-check---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-check---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check--q\"><a class=\"option-anchor\" href=\"#option-cargo-check--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-check---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-check---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---color\"><a class=\"option-anchor\" href=\"#option-cargo-check---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---message-format\"><a class=\"option-anchor\" href=\"#option-cargo-check---message-format\"><code>--message-format</code> <em>fmt</em></a></dt>\n<dd class=\"option-desc\"><p>The output format for diagnostic messages. Can be specified multiple times\nand consists of comma-separated values. Valid values:</p>\n<ul>\n<li><code>human</code> (default): Display in a human-readable text format. Conflicts with\n<code>short</code> and <code>json</code>.</li>\n<li><code>short</code>: Emit shorter, human-readable text messages. Conflicts with <code>human</code>\nand <code>json</code>.</li>\n<li><code>json</code>: Emit JSON messages to stdout. See\n<a href=\"../reference/external-tools.html#json-messages\">the reference</a>\nfor more details. Conflicts with <code>human</code> and <code>short</code>.</li>\n<li><code>json-diagnostic-short</code>: Ensure the <code>rendered</code> field of JSON messages contains\nthe “short” rendering from rustc. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-diagnostic-rendered-ansi</code>: Ensure the <code>rendered</code> field of JSON messages\ncontains embedded ANSI color codes for respecting rustc’s default color\nscheme. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-render-diagnostics</code>: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo’s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with <code>human</code> or <code>short</code>.</li>\n</ul>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-check---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-check---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-check---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---locked\"><a class=\"option-anchor\" href=\"#option-cargo-check---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---offline\"><a class=\"option-anchor\" href=\"#option-cargo-check---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-check---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-check-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-check-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check---config\"><a class=\"option-anchor\" href=\"#option-cargo-check---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check--C\"><a class=\"option-anchor\" href=\"#option-cargo-check--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check--h\"><a class=\"option-anchor\" href=\"#option-cargo-check--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-check---help\"><a class=\"option-anchor\" href=\"#option-cargo-check---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-check--Z\"><a class=\"option-anchor\" href=\"#option-cargo-check--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n### Miscellaneous Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-check--j\"><a class=\"option-anchor\" href=\"#option-cargo-check--j\"><code>-j</code> <em>N</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-check---jobs\"><a class=\"option-anchor\" href=\"#option-cargo-check---jobs\"><code>--jobs</code> <em>N</em></a></dt>\n<dd class=\"option-desc\"><p>Number of parallel jobs to run. May also be specified with the\n<code>build.jobs</code> <a href=\"../reference/config.html\">config value</a>. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string <code>default</code> is provided, it sets the value back to defaults.\nShould not be 0.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-check---keep-going\"><a class=\"option-anchor\" href=\"#option-cargo-check---keep-going\"><code>--keep-going</code></a></dt>\n<dd class=\"option-desc\"><p>Build as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.</p>\n<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,\none of which fails to build, <code>cargo check -j1</code> may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas <code>cargo check -j1 --keep-going</code> would definitely run both\nbuilds, even if the one run first fails.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-check---future-incompat-report\"><a class=\"option-anchor\" href=\"#option-cargo-check---future-incompat-report\"><code>--future-incompat-report</code></a></dt>\n<dd class=\"option-desc\"><p>Displays a future-incompat report for any future-incompatible warnings\nproduced during execution of this command</p>\n<p>See <a href=\"cargo-report.html\">cargo-report(1)</a></p>\n</dd>\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Check the local package for errors:\n\n       cargo check\n\n2. Check all targets, including unit tests:\n\n       cargo check --all-targets --profile=test\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-build(1)](cargo-build.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-clean.md",
    "content": "# cargo-clean(1)\n## NAME\n\ncargo-clean --- Remove generated artifacts\n\n## SYNOPSIS\n\n`cargo clean` [_options_]\n\n## DESCRIPTION\n\nRemove artifacts from the target directory that Cargo has generated in the\npast.\n\nWith no options, `cargo clean` will delete the entire target directory.\n\n## OPTIONS\n\n### Package Selection\n\nWhen no packages are selected, all packages and all dependencies in the\nworkspace are cleaned.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-clean--p\"><a class=\"option-anchor\" href=\"#option-cargo-clean--p\"><code>-p</code> <em>spec</em>…</a></dt>\n<dt class=\"option-term\" id=\"option-cargo-clean---package\"><a class=\"option-anchor\" href=\"#option-cargo-clean---package\"><code>--package</code> <em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Clean only the specified packages. This flag may be specified\nmultiple times. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the SPEC format.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean---workspace\"><a class=\"option-anchor\" href=\"#option-cargo-clean---workspace\"><code>--workspace</code></a></dt>\n<dd class=\"option-desc\"><p>Clean artifacts of the workspace members.</p>\n</dd>\n\n\n</dl>\n\n### Clean Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-clean---dry-run\"><a class=\"option-anchor\" href=\"#option-cargo-clean---dry-run\"><code>--dry-run</code></a></dt>\n<dd class=\"option-desc\"><p>Displays a summary of what would be deleted without deleting anything.\nUse with <code>--verbose</code> to display the actual files that would be deleted.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean---doc\"><a class=\"option-anchor\" href=\"#option-cargo-clean---doc\"><code>--doc</code></a></dt>\n<dd class=\"option-desc\"><p>This option will cause <code>cargo clean</code> to remove only the <code>doc</code> directory in\nthe target directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean---release\"><a class=\"option-anchor\" href=\"#option-cargo-clean---release\"><code>--release</code></a></dt>\n<dd class=\"option-desc\"><p>Remove all artifacts in the <code>release</code> directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean---profile\"><a class=\"option-anchor\" href=\"#option-cargo-clean---profile\"><code>--profile</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Remove all artifacts in the directory with the given profile name.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-clean---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to <code>target</code> in the root of the workspace.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean---target\"><a class=\"option-anchor\" href=\"#option-cargo-clean---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Clean for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-clean--v\"><a class=\"option-anchor\" href=\"#option-cargo-clean--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-clean---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-clean---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean--q\"><a class=\"option-anchor\" href=\"#option-cargo-clean--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-clean---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-clean---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean---color\"><a class=\"option-anchor\" href=\"#option-cargo-clean---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-clean---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-clean---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean---locked\"><a class=\"option-anchor\" href=\"#option-cargo-clean---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean---offline\"><a class=\"option-anchor\" href=\"#option-cargo-clean---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-clean---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-clean-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-clean-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean---config\"><a class=\"option-anchor\" href=\"#option-cargo-clean---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean--C\"><a class=\"option-anchor\" href=\"#option-cargo-clean--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean--h\"><a class=\"option-anchor\" href=\"#option-cargo-clean--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-clean---help\"><a class=\"option-anchor\" href=\"#option-cargo-clean---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-clean--Z\"><a class=\"option-anchor\" href=\"#option-cargo-clean--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Remove the entire target directory:\n\n       cargo clean\n\n2. Remove only the release artifacts:\n\n       cargo clean --release\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-build(1)](cargo-build.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-clippy.md",
    "content": "# cargo-clippy(1)\n\n## NAME\n\ncargo-clippy --- Checks a package to catch common mistakes and improve your Rust code\n\n## DESCRIPTION\n\nThis is an external command distributed with the Rust toolchain as an optional component.\nIt is not built into Cargo, and may require additional installation.\n\nFor information about usage and installation,\nsee [Clippy Documentation](../../clippy/index.html).\n\n## SEE ALSO\n\n[cargo(1)](cargo.md),\n[cargo-fix(1)](cargo-fix.md),\n[cargo-fmt(1)](cargo-fmt.md),\n[Custom subcommands](../reference/external-tools.md#custom-subcommands)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-doc.md",
    "content": "# cargo-doc(1)\n## NAME\n\ncargo-doc --- Build a package's documentation\n\n## SYNOPSIS\n\n`cargo doc` [_options_]\n\n## DESCRIPTION\n\nBuild the documentation for the local package and all dependencies. The output\nis placed in `target/doc` in rustdoc's usual format.\n\n**Note:** Documentation generation is cumulative: existing doc files in the target directory are preserved across different `cargo doc` invocations. To remove existing generated docs, pass `--doc` to [cargo-clean(1)](cargo-clean.html).\n\n## OPTIONS\n\n### Documentation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-doc---open\"><a class=\"option-anchor\" href=\"#option-cargo-doc---open\"><code>--open</code></a></dt>\n<dd class=\"option-desc\"><p>Open the docs in a browser after building them. This will use your default\nbrowser unless you define another one in the <code>BROWSER</code> environment variable\nor use the <a href=\"../reference/config.html#docbrowser\"><code>doc.browser</code></a> configuration\noption.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---no-deps\"><a class=\"option-anchor\" href=\"#option-cargo-doc---no-deps\"><code>--no-deps</code></a></dt>\n<dd class=\"option-desc\"><p>Do not build documentation for dependencies.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---document-private-items\"><a class=\"option-anchor\" href=\"#option-cargo-doc---document-private-items\"><code>--document-private-items</code></a></dt>\n<dd class=\"option-desc\"><p>Include non-public items in the documentation. This will be enabled by default if documenting a binary target.</p>\n</dd>\n\n\n</dl>\n\n### Package Selection\n\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n`--manifest-path` is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n\nThe default members of a workspace can be set explicitly with the\n`workspace.default-members` key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n`--workspace`), and a non-virtual workspace will include only the root crate itself.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-doc--p\"><a class=\"option-anchor\" href=\"#option-cargo-doc--p\"><code>-p</code> <em>spec</em>…</a></dt>\n<dt class=\"option-term\" id=\"option-cargo-doc---package\"><a class=\"option-anchor\" href=\"#option-cargo-doc---package\"><code>--package</code> <em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Document only the specified packages. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---workspace\"><a class=\"option-anchor\" href=\"#option-cargo-doc---workspace\"><code>--workspace</code></a></dt>\n<dd class=\"option-desc\"><p>Document all members in the workspace.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---all\"><a class=\"option-anchor\" href=\"#option-cargo-doc---all\"><code>--all</code></a></dt>\n<dd class=\"option-desc\"><p>Deprecated alias for <code>--workspace</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---exclude\"><a class=\"option-anchor\" href=\"#option-cargo-doc---exclude\"><code>--exclude</code> <em>SPEC</em>…</a></dt>\n<dd class=\"option-desc\"><p>Exclude the specified packages. Must be used in conjunction with the\n<code>--workspace</code> flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.</p>\n</dd>\n\n\n</dl>\n\n### Target Selection\n\nWhen no target selection options are given, `cargo doc` will document all\nbinary and library targets of the selected package. The binary will be skipped\nif its name is the same as the lib target. Binaries are skipped if they have\n`required-features` that are missing.\n\nThe default behavior can be changed by setting `doc = false` for the target in\nthe manifest settings. Using target selection options will ignore the `doc`\nflag and will always document the given target.\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-doc---lib\"><a class=\"option-anchor\" href=\"#option-cargo-doc---lib\"><code>--lib</code></a></dt>\n<dd class=\"option-desc\"><p>Document the package’s library.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---bin\"><a class=\"option-anchor\" href=\"#option-cargo-doc---bin\"><code>--bin</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Document the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---bins\"><a class=\"option-anchor\" href=\"#option-cargo-doc---bins\"><code>--bins</code></a></dt>\n<dd class=\"option-desc\"><p>Document all binary targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---example\"><a class=\"option-anchor\" href=\"#option-cargo-doc---example\"><code>--example</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Document the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---examples\"><a class=\"option-anchor\" href=\"#option-cargo-doc---examples\"><code>--examples</code></a></dt>\n<dd class=\"option-desc\"><p>Document all example targets.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-doc--F\"><a class=\"option-anchor\" href=\"#option-cargo-doc--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-doc---features\"><a class=\"option-anchor\" href=\"#option-cargo-doc---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-doc---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-doc---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Compilation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-doc---target\"><a class=\"option-anchor\" href=\"#option-cargo-doc---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Document for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc--r\"><a class=\"option-anchor\" href=\"#option-cargo-doc--r\"><code>-r</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-doc---release\"><a class=\"option-anchor\" href=\"#option-cargo-doc---release\"><code>--release</code></a></dt>\n<dd class=\"option-desc\"><p>Document optimized artifacts with the <code>release</code> profile.\nSee also the <code>--profile</code> option for choosing a specific profile by name.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---profile\"><a class=\"option-anchor\" href=\"#option-cargo-doc---profile\"><code>--profile</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Document with the given profile.\nSee <a href=\"../reference/profiles.html\">the reference</a> for more details on profiles.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---timings\"><a class=\"option-anchor\" href=\"#option-cargo-doc---timings\"><code>--timings</code></a></dt>\n<dd class=\"option-desc\"><p>Output information how long each compilation takes, and track concurrency\ninformation over time.</p>\n<p>A file <code>cargo-timing.html</code> will be written to the <code>target/cargo-timings</code>\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine-readable timing data.</p>\n</dd>\n\n\n\n</dl>\n\n### Output Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-doc---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-doc---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to <code>target</code> in the root of the workspace.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-doc--v\"><a class=\"option-anchor\" href=\"#option-cargo-doc--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-doc---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-doc---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc--q\"><a class=\"option-anchor\" href=\"#option-cargo-doc--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-doc---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-doc---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---color\"><a class=\"option-anchor\" href=\"#option-cargo-doc---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---message-format\"><a class=\"option-anchor\" href=\"#option-cargo-doc---message-format\"><code>--message-format</code> <em>fmt</em></a></dt>\n<dd class=\"option-desc\"><p>The output format for diagnostic messages. Can be specified multiple times\nand consists of comma-separated values. Valid values:</p>\n<ul>\n<li><code>human</code> (default): Display in a human-readable text format. Conflicts with\n<code>short</code> and <code>json</code>.</li>\n<li><code>short</code>: Emit shorter, human-readable text messages. Conflicts with <code>human</code>\nand <code>json</code>.</li>\n<li><code>json</code>: Emit JSON messages to stdout. See\n<a href=\"../reference/external-tools.html#json-messages\">the reference</a>\nfor more details. Conflicts with <code>human</code> and <code>short</code>.</li>\n<li><code>json-diagnostic-short</code>: Ensure the <code>rendered</code> field of JSON messages contains\nthe “short” rendering from rustc. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-diagnostic-rendered-ansi</code>: Ensure the <code>rendered</code> field of JSON messages\ncontains embedded ANSI color codes for respecting rustc’s default color\nscheme. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-render-diagnostics</code>: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo’s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with <code>human</code> or <code>short</code>.</li>\n</ul>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-doc---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-doc---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-doc---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---locked\"><a class=\"option-anchor\" href=\"#option-cargo-doc---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---offline\"><a class=\"option-anchor\" href=\"#option-cargo-doc---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-doc---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-doc-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-doc-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc---config\"><a class=\"option-anchor\" href=\"#option-cargo-doc---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc--C\"><a class=\"option-anchor\" href=\"#option-cargo-doc--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc--h\"><a class=\"option-anchor\" href=\"#option-cargo-doc--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-doc---help\"><a class=\"option-anchor\" href=\"#option-cargo-doc---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-doc--Z\"><a class=\"option-anchor\" href=\"#option-cargo-doc--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n### Miscellaneous Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-doc--j\"><a class=\"option-anchor\" href=\"#option-cargo-doc--j\"><code>-j</code> <em>N</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-doc---jobs\"><a class=\"option-anchor\" href=\"#option-cargo-doc---jobs\"><code>--jobs</code> <em>N</em></a></dt>\n<dd class=\"option-desc\"><p>Number of parallel jobs to run. May also be specified with the\n<code>build.jobs</code> <a href=\"../reference/config.html\">config value</a>. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string <code>default</code> is provided, it sets the value back to defaults.\nShould not be 0.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-doc---keep-going\"><a class=\"option-anchor\" href=\"#option-cargo-doc---keep-going\"><code>--keep-going</code></a></dt>\n<dd class=\"option-desc\"><p>Build as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.</p>\n<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,\none of which fails to build, <code>cargo doc -j1</code> may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas <code>cargo doc -j1 --keep-going</code> would definitely run both\nbuilds, even if the one run first fails.</p>\n</dd>\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Build the local package documentation and its dependencies and output to\n   `target/doc`.\n\n       cargo doc\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-rustdoc(1)](cargo-rustdoc.html), [rustdoc(1)](https://doc.rust-lang.org/rustdoc/index.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-fetch.md",
    "content": "# cargo-fetch(1)\n## NAME\n\ncargo-fetch --- Fetch dependencies of a package from the network\n\n## SYNOPSIS\n\n`cargo fetch` [_options_]\n\n## DESCRIPTION\n\nIf a `Cargo.lock` file is available, this command will ensure that all of the\ngit dependencies and/or registry dependencies are downloaded and locally\navailable. Subsequent Cargo commands will be able to run offline after a `cargo\nfetch` unless the lock file changes.\n\nIf the lock file is not available, then this command will generate the lock\nfile before fetching the dependencies.\n\nIf `--target` is not specified, then all target dependencies are fetched.\n\nSee also the [cargo-prefetch](https://crates.io/crates/cargo-prefetch)\nplugin which adds a command to download popular crates. This may be useful if\nyou plan to use Cargo without a network with the `--offline` flag.\n\n## OPTIONS\n\n### Fetch options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-fetch---target\"><a class=\"option-anchor\" href=\"#option-cargo-fetch---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Fetch for the specified target architecture. Flag may be specified multiple times. The default is all architectures. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-fetch--v\"><a class=\"option-anchor\" href=\"#option-cargo-fetch--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-fetch---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-fetch---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fetch--q\"><a class=\"option-anchor\" href=\"#option-cargo-fetch--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-fetch---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-fetch---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fetch---color\"><a class=\"option-anchor\" href=\"#option-cargo-fetch---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-fetch---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-fetch---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fetch---locked\"><a class=\"option-anchor\" href=\"#option-cargo-fetch---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fetch---offline\"><a class=\"option-anchor\" href=\"#option-cargo-fetch---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fetch---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-fetch---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-fetch-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-fetch-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fetch---config\"><a class=\"option-anchor\" href=\"#option-cargo-fetch---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fetch--C\"><a class=\"option-anchor\" href=\"#option-cargo-fetch--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fetch--h\"><a class=\"option-anchor\" href=\"#option-cargo-fetch--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-fetch---help\"><a class=\"option-anchor\" href=\"#option-cargo-fetch---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fetch--Z\"><a class=\"option-anchor\" href=\"#option-cargo-fetch--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Fetch all dependencies:\n\n       cargo fetch\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-update(1)](cargo-update.html), [cargo-generate-lockfile(1)](cargo-generate-lockfile.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-fix.md",
    "content": "# cargo-fix(1)\n## NAME\n\ncargo-fix --- Automatically fix lint warnings reported by rustc\n\n## SYNOPSIS\n\n`cargo fix` [_options_]\n\n## DESCRIPTION\n\nThis Cargo subcommand will automatically take rustc's suggestions from\ndiagnostics like warnings and apply them to your source code. This is intended\nto help automate tasks that rustc itself already knows how to tell you to fix!\n\nExecuting `cargo fix` will under the hood execute [cargo-check(1)](cargo-check.html). Any warnings\napplicable to your crate will be automatically fixed (if possible) and all\nremaining warnings will be displayed when the check process is finished. For\nexample if you'd like to apply all fixes to the current package, you can run:\n\n    cargo fix\n\nwhich behaves the same as `cargo check --all-targets`.\n\n`cargo fix` is only capable of fixing code that is normally compiled with\n`cargo check`. If code is conditionally enabled with optional features, you\nwill need to enable those features for that code to be analyzed:\n\n    cargo fix --features foo\n\nSimilarly, other `cfg` expressions like platform-specific code will need to\npass `--target` to fix code for the given target.\n\n    cargo fix --target x86_64-pc-windows-gnu\n\nIf you encounter any problems with `cargo fix` or otherwise have any questions\nor feature requests please don't hesitate to file an issue at\n<https://github.com/rust-lang/cargo>.\n\n### Edition migration\n\nThe `cargo fix` subcommand can also be used to migrate a package from one\n[edition] to the next. The general procedure is:\n\n1. Run `cargo fix --edition`. Consider also using the `--all-features` flag if\n   your project has multiple features. You may also want to run `cargo fix\n   --edition` multiple times with different `--target` flags if your project\n   has platform-specific code gated by `cfg` attributes.\n2. Modify `Cargo.toml` to set the [edition field] to the new edition.\n3. Run your project tests to verify that everything still works. If new\n   warnings are issued, you may want to consider running `cargo fix` again\n   (without the `--edition` flag) to apply any suggestions given by the\n   compiler.\n\nAnd hopefully that's it! Just keep in mind of the caveats mentioned above that\n`cargo fix` cannot update code for inactive features or `cfg` expressions.\nAlso, in some rare cases the compiler is unable to automatically migrate all\ncode to the new edition, and this may require manual changes after building\nwith the new edition.\n\n[edition]: https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html\n[edition field]: ../reference/manifest.html#the-edition-field\n\n## OPTIONS\n\n### Fix options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-fix---broken-code\"><a class=\"option-anchor\" href=\"#option-cargo-fix---broken-code\"><code>--broken-code</code></a></dt>\n<dd class=\"option-desc\"><p>Fix code even if it already has compiler errors. This is useful if <code>cargo fix</code>\nfails to apply the changes. It will apply the changes and leave the broken\ncode in the working directory for you to inspect and manually fix.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---edition\"><a class=\"option-anchor\" href=\"#option-cargo-fix---edition\"><code>--edition</code></a></dt>\n<dd class=\"option-desc\"><p>Apply changes that will update the code to the next edition. This will not\nupdate the edition in the <code>Cargo.toml</code> manifest, which must be updated\nmanually after <code>cargo fix --edition</code> has finished.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---edition-idioms\"><a class=\"option-anchor\" href=\"#option-cargo-fix---edition-idioms\"><code>--edition-idioms</code></a></dt>\n<dd class=\"option-desc\"><p>Apply suggestions that will update code to the preferred style for the current\nedition.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---allow-no-vcs\"><a class=\"option-anchor\" href=\"#option-cargo-fix---allow-no-vcs\"><code>--allow-no-vcs</code></a></dt>\n<dd class=\"option-desc\"><p>Fix code even if a VCS was not detected.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---allow-dirty\"><a class=\"option-anchor\" href=\"#option-cargo-fix---allow-dirty\"><code>--allow-dirty</code></a></dt>\n<dd class=\"option-desc\"><p>Fix code even if the working directory has changes (including staged changes).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---allow-staged\"><a class=\"option-anchor\" href=\"#option-cargo-fix---allow-staged\"><code>--allow-staged</code></a></dt>\n<dd class=\"option-desc\"><p>Fix code even if the working directory has staged changes.</p>\n</dd>\n\n\n</dl>\n\n### Package Selection\n\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n`--manifest-path` is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n\nThe default members of a workspace can be set explicitly with the\n`workspace.default-members` key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n`--workspace`), and a non-virtual workspace will include only the root crate itself.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-fix--p\"><a class=\"option-anchor\" href=\"#option-cargo-fix--p\"><code>-p</code> <em>spec</em>…</a></dt>\n<dt class=\"option-term\" id=\"option-cargo-fix---package\"><a class=\"option-anchor\" href=\"#option-cargo-fix---package\"><code>--package</code> <em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Fix only the specified packages. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---workspace\"><a class=\"option-anchor\" href=\"#option-cargo-fix---workspace\"><code>--workspace</code></a></dt>\n<dd class=\"option-desc\"><p>Fix all members in the workspace.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---all\"><a class=\"option-anchor\" href=\"#option-cargo-fix---all\"><code>--all</code></a></dt>\n<dd class=\"option-desc\"><p>Deprecated alias for <code>--workspace</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---exclude\"><a class=\"option-anchor\" href=\"#option-cargo-fix---exclude\"><code>--exclude</code> <em>SPEC</em>…</a></dt>\n<dd class=\"option-desc\"><p>Exclude the specified packages. Must be used in conjunction with the\n<code>--workspace</code> flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.</p>\n</dd>\n\n\n</dl>\n\n### Target Selection\n\nWhen no target selection options are given, `cargo fix` will fix all targets\n(`--all-targets` implied). Binaries are skipped if they have\n`required-features` that are missing.\n\nPassing target selection flags will fix only the specified\ntargets. \n\nNote that `--bin`, `--example`, `--test` and `--bench` flags also \nsupport common Unix glob patterns like `*`, `?` and `[]`. However, to avoid your \nshell accidentally expanding glob patterns before Cargo handles them, you must \nuse single quotes or double quotes around each glob pattern.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-fix---lib\"><a class=\"option-anchor\" href=\"#option-cargo-fix---lib\"><code>--lib</code></a></dt>\n<dd class=\"option-desc\"><p>Fix the package’s library.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---bin\"><a class=\"option-anchor\" href=\"#option-cargo-fix---bin\"><code>--bin</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Fix the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---bins\"><a class=\"option-anchor\" href=\"#option-cargo-fix---bins\"><code>--bins</code></a></dt>\n<dd class=\"option-desc\"><p>Fix all binary targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---example\"><a class=\"option-anchor\" href=\"#option-cargo-fix---example\"><code>--example</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Fix the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---examples\"><a class=\"option-anchor\" href=\"#option-cargo-fix---examples\"><code>--examples</code></a></dt>\n<dd class=\"option-desc\"><p>Fix all example targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---test\"><a class=\"option-anchor\" href=\"#option-cargo-fix---test\"><code>--test</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Fix the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---tests\"><a class=\"option-anchor\" href=\"#option-cargo-fix---tests\"><code>--tests</code></a></dt>\n<dd class=\"option-desc\"><p>Fix all targets that have the <code>test = true</code> manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the <code>test</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---bench\"><a class=\"option-anchor\" href=\"#option-cargo-fix---bench\"><code>--bench</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Fix the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---benches\"><a class=\"option-anchor\" href=\"#option-cargo-fix---benches\"><code>--benches</code></a></dt>\n<dd class=\"option-desc\"><p>Fix all targets that have the <code>bench = true</code>\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the <code>bench</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---all-targets\"><a class=\"option-anchor\" href=\"#option-cargo-fix---all-targets\"><code>--all-targets</code></a></dt>\n<dd class=\"option-desc\"><p>Fix all targets. This is equivalent to specifying <code>--lib --bins --tests --benches --examples</code>.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-fix--F\"><a class=\"option-anchor\" href=\"#option-cargo-fix--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-fix---features\"><a class=\"option-anchor\" href=\"#option-cargo-fix---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-fix---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-fix---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Compilation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-fix---target\"><a class=\"option-anchor\" href=\"#option-cargo-fix---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Fix for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix--r\"><a class=\"option-anchor\" href=\"#option-cargo-fix--r\"><code>-r</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-fix---release\"><a class=\"option-anchor\" href=\"#option-cargo-fix---release\"><code>--release</code></a></dt>\n<dd class=\"option-desc\"><p>Fix optimized artifacts with the <code>release</code> profile.\nSee also the <code>--profile</code> option for choosing a specific profile by name.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---profile\"><a class=\"option-anchor\" href=\"#option-cargo-fix---profile\"><code>--profile</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Fix with the given profile.</p>\n<p>As a special case, specifying the <code>test</code> profile will also enable checking in\ntest mode which will enable checking tests and enable the <code>test</code> cfg option.\nSee <a href=\"https://doc.rust-lang.org/rustc/tests/index.html\">rustc tests</a> for more\ndetail.</p>\n<p>See <a href=\"../reference/profiles.html\">the reference</a> for more details on profiles.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---timings\"><a class=\"option-anchor\" href=\"#option-cargo-fix---timings\"><code>--timings</code></a></dt>\n<dd class=\"option-desc\"><p>Output information how long each compilation takes, and track concurrency\ninformation over time.</p>\n<p>A file <code>cargo-timing.html</code> will be written to the <code>target/cargo-timings</code>\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine-readable timing data.</p>\n</dd>\n\n\n\n</dl>\n\n### Output Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-fix---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-fix---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to <code>target</code> in the root of the workspace.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-fix--v\"><a class=\"option-anchor\" href=\"#option-cargo-fix--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-fix---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-fix---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix--q\"><a class=\"option-anchor\" href=\"#option-cargo-fix--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-fix---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-fix---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---color\"><a class=\"option-anchor\" href=\"#option-cargo-fix---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---message-format\"><a class=\"option-anchor\" href=\"#option-cargo-fix---message-format\"><code>--message-format</code> <em>fmt</em></a></dt>\n<dd class=\"option-desc\"><p>The output format for diagnostic messages. Can be specified multiple times\nand consists of comma-separated values. Valid values:</p>\n<ul>\n<li><code>human</code> (default): Display in a human-readable text format. Conflicts with\n<code>short</code> and <code>json</code>.</li>\n<li><code>short</code>: Emit shorter, human-readable text messages. Conflicts with <code>human</code>\nand <code>json</code>.</li>\n<li><code>json</code>: Emit JSON messages to stdout. See\n<a href=\"../reference/external-tools.html#json-messages\">the reference</a>\nfor more details. Conflicts with <code>human</code> and <code>short</code>.</li>\n<li><code>json-diagnostic-short</code>: Ensure the <code>rendered</code> field of JSON messages contains\nthe “short” rendering from rustc. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-diagnostic-rendered-ansi</code>: Ensure the <code>rendered</code> field of JSON messages\ncontains embedded ANSI color codes for respecting rustc’s default color\nscheme. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-render-diagnostics</code>: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo’s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with <code>human</code> or <code>short</code>.</li>\n</ul>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-fix---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-fix---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-fix---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---locked\"><a class=\"option-anchor\" href=\"#option-cargo-fix---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---offline\"><a class=\"option-anchor\" href=\"#option-cargo-fix---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-fix---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-fix-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-fix-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix---config\"><a class=\"option-anchor\" href=\"#option-cargo-fix---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix--C\"><a class=\"option-anchor\" href=\"#option-cargo-fix--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix--h\"><a class=\"option-anchor\" href=\"#option-cargo-fix--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-fix---help\"><a class=\"option-anchor\" href=\"#option-cargo-fix---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-fix--Z\"><a class=\"option-anchor\" href=\"#option-cargo-fix--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n### Miscellaneous Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-fix--j\"><a class=\"option-anchor\" href=\"#option-cargo-fix--j\"><code>-j</code> <em>N</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-fix---jobs\"><a class=\"option-anchor\" href=\"#option-cargo-fix---jobs\"><code>--jobs</code> <em>N</em></a></dt>\n<dd class=\"option-desc\"><p>Number of parallel jobs to run. May also be specified with the\n<code>build.jobs</code> <a href=\"../reference/config.html\">config value</a>. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string <code>default</code> is provided, it sets the value back to defaults.\nShould not be 0.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-fix---keep-going\"><a class=\"option-anchor\" href=\"#option-cargo-fix---keep-going\"><code>--keep-going</code></a></dt>\n<dd class=\"option-desc\"><p>Build as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.</p>\n<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,\none of which fails to build, <code>cargo fix -j1</code> may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas <code>cargo fix -j1 --keep-going</code> would definitely run both\nbuilds, even if the one run first fails.</p>\n</dd>\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Apply compiler suggestions to the local package:\n\n       cargo fix\n\n2. Update a package to prepare it for the next edition:\n\n       cargo fix --edition\n\n3. Apply suggested idioms for the current edition:\n\n       cargo fix --edition-idioms\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-check(1)](cargo-check.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-fmt.md",
    "content": "# cargo-fmt(1)\n\n## NAME\n\ncargo-fmt --- Formats all bin and lib files of the current crate using rustfmt\n\n## DESCRIPTION\n\nThis is an external command distributed with the Rust toolchain as an optional component.\nIt is not built into Cargo, and may require additional installation.\n\nFor information about usage and installation,\nsee <https://github.com/rust-lang/rustfmt>.\n\n## SEE ALSO\n\n[cargo(1)](cargo.md),\n[cargo-fix(1)](cargo-fix.md),\n[cargo-clippy(1)](cargo-clippy.md),\n[Custom subcommands](../reference/external-tools.md#custom-subcommands)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-generate-lockfile.md",
    "content": "# cargo-generate-lockfile(1)\n\n## NAME\n\ncargo-generate-lockfile --- Generate the lockfile for a package\n\n## SYNOPSIS\n\n`cargo generate-lockfile` [_options_]\n\n## DESCRIPTION\n\nThis command will create the `Cargo.lock` lockfile for the current package or\nworkspace. If the lockfile already exists, it will be rebuilt with the latest\navailable version of every package.\n\nSee also [cargo-update(1)](cargo-update.html) which is also capable of creating a `Cargo.lock`\nlockfile and has more options for controlling update behavior.\n\n## OPTIONS\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile--v\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile--q\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile---color\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile---publish-time\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile---publish-time\"><code>--publish-time</code> <em>yyyy-mm-ddThh:mm:ssZ</em></a></dt>\n<dd class=\"option-desc\"><p>Latest publish time allowed for registry packages (Unstable)</p>\n<p>This is a best-effort filter on allowed packages, including:</p>\n<ul>\n<li>packages from unsupported registries are always accepted</li>\n<li>only the current yank state is respected, not the state as of <code>--publish-time</code></li>\n<li>precision of the publish time</li>\n</ul>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile---locked\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile---offline\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile---config\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile--C\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile--h\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile---help\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-generate-lockfile--Z\"><a class=\"option-anchor\" href=\"#option-cargo-generate-lockfile--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Create or update the lockfile for the current package or workspace:\n\n       cargo generate-lockfile\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-update(1)](cargo-update.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-help.md",
    "content": "# cargo-help(1)\n\n## NAME\n\ncargo-help --- Get help for a Cargo command\n\n## SYNOPSIS\n\n`cargo help` [_subcommand_]\n\n## DESCRIPTION\n\nPrints a help message for the given command.\n\nFor commands with subcommands, separate the command levels with spaces. For\nexample, `cargo help report future-incompatibilities` displays help for the\n`cargo report future-incompatibilities` command.\n\nSpaces separate hierarchy levels only between a parent command and its\nsubcommands. Dashes that are part of a command's name, such as\n`generate-lockfile`, must always be preserved.\n\nMultiple command levels can also be written as a single dash-joined word.\nFor example, `cargo help report-future-incompatibilities` is equivalent to\n`cargo help report future-incompatibilities`.\n\n## OPTIONS\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-help--v\"><a class=\"option-anchor\" href=\"#option-cargo-help--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-help---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-help---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-help--q\"><a class=\"option-anchor\" href=\"#option-cargo-help--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-help---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-help---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-help---color\"><a class=\"option-anchor\" href=\"#option-cargo-help---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-help---locked\"><a class=\"option-anchor\" href=\"#option-cargo-help---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-help---offline\"><a class=\"option-anchor\" href=\"#option-cargo-help---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-help---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-help---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-help-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-help-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-help---config\"><a class=\"option-anchor\" href=\"#option-cargo-help---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-help--C\"><a class=\"option-anchor\" href=\"#option-cargo-help--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-help--h\"><a class=\"option-anchor\" href=\"#option-cargo-help--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-help---help\"><a class=\"option-anchor\" href=\"#option-cargo-help---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-help--Z\"><a class=\"option-anchor\" href=\"#option-cargo-help--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Get help for a command:\n\n       cargo help build\n\n2. Get help for a nested command:\n\n       cargo help report future-incompatibilities\n\n3. The dash-joined form also works:\n\n       cargo help report-future-incompatibilities\n\n4. Help is also available with the `--help` flag:\n\n       cargo build --help\n\n## SEE ALSO\n[cargo(1)](cargo.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-info.md",
    "content": "# cargo-info(1)\n\n## NAME\n\ncargo-info --- Display information about a package.\n\n## SYNOPSIS\n\n`cargo info` [_options_] _spec_\n\n## DESCRIPTION\n\nThis command displays information about a package. It fetches data from the package's Cargo.toml file\nand presents it in a human-readable format.\n\n## OPTIONS\n\n### Info Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-info-spec\"><a class=\"option-anchor\" href=\"#option-cargo-info-spec\"><em>spec</em></a></dt>\n<dd class=\"option-desc\"><p>Fetch information about the specified package. The <em>spec</em> can be a package ID, see <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the SPEC\nformat.\nIf the specified package is part of the current workspace, information from the local Cargo.toml file will be displayed.\nIf the <code>Cargo.lock</code> file does not exist, it will be created. If no version is specified, the appropriate version will be\nselected based on the Minimum Supported Rust Version (MSRV).</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-info---index\"><a class=\"option-anchor\" href=\"#option-cargo-info---index\"><code>--index</code> <em>index</em></a></dt>\n<dd class=\"option-desc\"><p>The URL of the registry index to use.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-info---registry\"><a class=\"option-anchor\" href=\"#option-cargo-info---registry\"><code>--registry</code> <em>registry</em></a></dt>\n<dd class=\"option-desc\"><p>Name of the registry to use. Registry names are defined in <a href=\"../reference/config.html\">Cargo config\nfiles</a>. If not specified, the default registry is used,\nwhich is defined by the <code>registry.default</code> config key which defaults to\n<code>crates-io</code>.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-info--v\"><a class=\"option-anchor\" href=\"#option-cargo-info--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-info---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-info---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-info--q\"><a class=\"option-anchor\" href=\"#option-cargo-info--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-info---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-info---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-info---color\"><a class=\"option-anchor\" href=\"#option-cargo-info---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-info---locked\"><a class=\"option-anchor\" href=\"#option-cargo-info---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-info---offline\"><a class=\"option-anchor\" href=\"#option-cargo-info---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-info---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-info---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-info-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-info-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-info---config\"><a class=\"option-anchor\" href=\"#option-cargo-info---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-info--C\"><a class=\"option-anchor\" href=\"#option-cargo-info--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-info--h\"><a class=\"option-anchor\" href=\"#option-cargo-info--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-info---help\"><a class=\"option-anchor\" href=\"#option-cargo-info---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-info--Z\"><a class=\"option-anchor\" href=\"#option-cargo-info--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Inspect the `serde` package from crates.io:\n\n        cargo info serde\n2. Inspect the `serde` package with version `1.0.0`:\n\n        cargo info serde@1.0.0\n3. Inspect the `serde` package form the local registry:\n\n        cargo info serde --registry my-registry\n\n## SEE ALSO\n\n[cargo(1)](cargo.html), [cargo-search(1)](cargo-search.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-init.md",
    "content": "# cargo-init(1)\n\n## NAME\n\ncargo-init --- Create a new Cargo package in an existing directory\n\n## SYNOPSIS\n\n`cargo init` [_options_] [_path_]\n\n## DESCRIPTION\n\nThis command will create a new Cargo manifest in the current directory. Give a\npath as an argument to create in the given directory.\n\nIf there are typically-named Rust source files already in the directory, those\nwill be used. If not, then a sample `src/main.rs` file will be created, or\n`src/lib.rs` if `--lib` is passed.\n\nIf the directory is not already in a VCS repository, then a new repository\nis created (see `--vcs` below).\n\nSee [cargo-new(1)](cargo-new.html) for a similar command which will create a new package in\na new directory.\n\n## OPTIONS\n\n### Init Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-init---bin\"><a class=\"option-anchor\" href=\"#option-cargo-init---bin\"><code>--bin</code></a></dt>\n<dd class=\"option-desc\"><p>Create a package with a binary target (<code>src/main.rs</code>).\nThis is the default behavior.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-init---lib\"><a class=\"option-anchor\" href=\"#option-cargo-init---lib\"><code>--lib</code></a></dt>\n<dd class=\"option-desc\"><p>Create a package with a library target (<code>src/lib.rs</code>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-init---edition\"><a class=\"option-anchor\" href=\"#option-cargo-init---edition\"><code>--edition</code> <em>edition</em></a></dt>\n<dd class=\"option-desc\"><p>Specify the Rust edition to use. Default is 2024.\nPossible values: 2015, 2018, 2021, 2024</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-init---name\"><a class=\"option-anchor\" href=\"#option-cargo-init---name\"><code>--name</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Set the package name. Defaults to the directory name.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-init---vcs\"><a class=\"option-anchor\" href=\"#option-cargo-init---vcs\"><code>--vcs</code> <em>vcs</em></a></dt>\n<dd class=\"option-desc\"><p>Initialize a new VCS repository for the given version control system (git,\nhg, pijul, or fossil) or do not initialize any version control at all\n(none). If not specified, defaults to <code>git</code> or the configuration value\n<code>cargo-new.vcs</code>, or <code>none</code> if already inside a VCS repository.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-init---registry\"><a class=\"option-anchor\" href=\"#option-cargo-init---registry\"><code>--registry</code> <em>registry</em></a></dt>\n<dd class=\"option-desc\"><p>This sets the <code>publish</code> field in <code>Cargo.toml</code> to the given registry name\nwhich will restrict publishing only to that registry.</p>\n<p>Registry names are defined in <a href=\"../reference/config.html\">Cargo config files</a>.\nIf not specified, the default registry defined by the <code>registry.default</code>\nconfig key is used. If the default registry is not set and <code>--registry</code> is not\nused, the <code>publish</code> field will not be set which means that publishing will not\nbe restricted.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-init--v\"><a class=\"option-anchor\" href=\"#option-cargo-init--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-init---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-init---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-init--q\"><a class=\"option-anchor\" href=\"#option-cargo-init--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-init---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-init---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-init---color\"><a class=\"option-anchor\" href=\"#option-cargo-init---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-init-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-init-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-init---config\"><a class=\"option-anchor\" href=\"#option-cargo-init---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-init--C\"><a class=\"option-anchor\" href=\"#option-cargo-init--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-init--h\"><a class=\"option-anchor\" href=\"#option-cargo-init--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-init---help\"><a class=\"option-anchor\" href=\"#option-cargo-init---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-init--Z\"><a class=\"option-anchor\" href=\"#option-cargo-init--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Create a binary Cargo package in the current directory:\n\n       cargo init\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-new(1)](cargo-new.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-install.md",
    "content": "# cargo-install(1)\n## NAME\n\ncargo-install --- Build and install a Rust binary\n\n## SYNOPSIS\n\n`cargo install` [_options_] _crate_[@_version_]...\\\n`cargo install` [_options_] `--path` _path_\\\n`cargo install` [_options_] `--git` _url_ [_crate_...]\\\n`cargo install` [_options_] `--list`\n\n## DESCRIPTION\n\nThis command manages Cargo's local set of installed binary crates. Only\npackages which have executable `[[bin]]` or `[[example]]` targets can be\ninstalled, and all executables are installed into the installation root's\n`bin` folder. By default only binaries, not examples, are installed.\n\nThe installation root is determined, in order of precedence:\n\n- `--root` option\n- `CARGO_INSTALL_ROOT` environment variable\n- `install.root` Cargo [config value](../reference/config.html)\n- `CARGO_HOME` environment variable\n- `$HOME/.cargo`\n\nThere are multiple sources from which a crate can be installed. The default\nsource location is crates.io but the `--git`, `--path`, and `--registry` flags\ncan change this source. If the source contains more than one package (such as\ncrates.io or a git repository with multiple crates) the _crate_ argument is\nrequired to indicate which crate should be installed.\n\nCrates from crates.io can optionally specify the version they wish to install\nvia the `--version` flags, and similarly packages from git repositories can\noptionally specify the branch, tag, or revision that should be installed. If a\ncrate has multiple binaries, the `--bin` argument can selectively install only\none of them, and if you'd rather install examples the `--example` argument can\nbe used as well.\n\nIf the package is already installed, Cargo will reinstall it if the installed\nversion does not appear to be up-to-date. If any of the following values\nchange, then Cargo will reinstall the package:\n\n- The package version and source.\n- The set of binary names installed.\n- The chosen features.\n- The profile (`--profile`).\n- The target (`--target`).\n\nInstalling with `--path` will always build and install, unless there are\nconflicting binaries from another package. The `--force` flag may be used to\nforce Cargo to always reinstall the package.\n\nIf the source is crates.io or `--git` then by default the crate will be built\nin a temporary target directory. To avoid this, the target directory can be\nspecified by setting the `CARGO_TARGET_DIR` environment variable to a\npath. In particular, this can be useful for caching build artifacts on\ncontinuous integration systems.\n\n### Dealing with the Lockfile\n\nBy default, the `Cargo.lock` file that is included with the package will be\nignored. This means that Cargo will recompute which versions of dependencies\nto use, possibly using newer versions that have been released since the\npackage was published. The `--locked` flag can be used to force Cargo to use\nthe packaged `Cargo.lock` file if it is available. This may be useful for\nensuring reproducible builds, to use the exact same set of dependencies that\nwere available when the package was published. It may also be useful if a\nnewer version of a dependency is published that no longer builds on your\nsystem, or has other problems. The downside to using `--locked` is that you\nwill not receive any fixes or updates to any dependency. Note that Cargo did\nnot start publishing `Cargo.lock` files until version 1.37, which means\npackages published with prior versions will not have a `Cargo.lock` file\navailable.\n\n### Configuration Discovery\n\nThis command operates on system or user level, not project level.\nThis means that the local [configuration discovery] is ignored.\nInstead, the configuration discovery begins at `$CARGO_HOME/config.toml`. \nIf the package is installed with `--path $PATH`, the local configuration \nwill be used, beginning discovery at `$PATH/.cargo/config.toml`.\n\n[configuration discovery]: ../reference/config.html#hierarchical-structure\n\n## OPTIONS\n\n### Install Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-install---vers\"><a class=\"option-anchor\" href=\"#option-cargo-install---vers\"><code>--vers</code> <em>version</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-install---version\"><a class=\"option-anchor\" href=\"#option-cargo-install---version\"><code>--version</code> <em>version</em></a></dt>\n<dd class=\"option-desc\"><p>Specify a version to install. This may be a <a href=\"../reference/specifying-dependencies.html\">version\nrequirement</a>, like <code>~1.2</code>, to have Cargo\nselect the newest version from the given requirement. If the version does not\nhave a requirement operator (such as <code>^</code> or <code>~</code>), then it must be in the form\n<em>MAJOR.MINOR.PATCH</em>, and will install exactly that version; it is <em>not</em>\ntreated as a caret requirement like Cargo dependencies are.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---git\"><a class=\"option-anchor\" href=\"#option-cargo-install---git\"><code>--git</code> <em>url</em></a></dt>\n<dd class=\"option-desc\"><p>Git URL to install the specified crate from.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---branch\"><a class=\"option-anchor\" href=\"#option-cargo-install---branch\"><code>--branch</code> <em>branch</em></a></dt>\n<dd class=\"option-desc\"><p>Branch to use when installing from git.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---tag\"><a class=\"option-anchor\" href=\"#option-cargo-install---tag\"><code>--tag</code> <em>tag</em></a></dt>\n<dd class=\"option-desc\"><p>Tag to use when installing from git.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---rev\"><a class=\"option-anchor\" href=\"#option-cargo-install---rev\"><code>--rev</code> <em>sha</em></a></dt>\n<dd class=\"option-desc\"><p>Specific commit to use when installing from git.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---path\"><a class=\"option-anchor\" href=\"#option-cargo-install---path\"><code>--path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Filesystem path to local crate to install from.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---list\"><a class=\"option-anchor\" href=\"#option-cargo-install---list\"><code>--list</code></a></dt>\n<dd class=\"option-desc\"><p>List all installed packages and their versions.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install--n\"><a class=\"option-anchor\" href=\"#option-cargo-install--n\"><code>-n</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-install---dry-run\"><a class=\"option-anchor\" href=\"#option-cargo-install---dry-run\"><code>--dry-run</code></a></dt>\n<dd class=\"option-desc\"><p>(unstable) Perform all checks without installing.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install--f\"><a class=\"option-anchor\" href=\"#option-cargo-install--f\"><code>-f</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-install---force\"><a class=\"option-anchor\" href=\"#option-cargo-install---force\"><code>--force</code></a></dt>\n<dd class=\"option-desc\"><p>Force overwriting existing crates or binaries. This can be used if a package\nhas installed a binary with the same name as another package. This is also\nuseful if something has changed on the system that you want to rebuild with,\nsuch as a newer version of <code>rustc</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---no-track\"><a class=\"option-anchor\" href=\"#option-cargo-install---no-track\"><code>--no-track</code></a></dt>\n<dd class=\"option-desc\"><p>By default, Cargo keeps track of the installed packages with a metadata file\nstored in the installation root directory. This flag tells Cargo not to use or\ncreate that file. With this flag, Cargo will refuse to overwrite any existing\nfiles unless the <code>--force</code> flag is used. This also disables Cargo’s ability to\nprotect against multiple concurrent invocations of Cargo installing at the\nsame time.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---bin\"><a class=\"option-anchor\" href=\"#option-cargo-install---bin\"><code>--bin</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Install only the specified binary.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---bins\"><a class=\"option-anchor\" href=\"#option-cargo-install---bins\"><code>--bins</code></a></dt>\n<dd class=\"option-desc\"><p>Install all binaries. This is the default behavior.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---example\"><a class=\"option-anchor\" href=\"#option-cargo-install---example\"><code>--example</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Install only the specified example.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---examples\"><a class=\"option-anchor\" href=\"#option-cargo-install---examples\"><code>--examples</code></a></dt>\n<dd class=\"option-desc\"><p>Install all examples.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---root\"><a class=\"option-anchor\" href=\"#option-cargo-install---root\"><code>--root</code> <em>dir</em></a></dt>\n<dd class=\"option-desc\"><p>Directory to install packages into.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---registry\"><a class=\"option-anchor\" href=\"#option-cargo-install---registry\"><code>--registry</code> <em>registry</em></a></dt>\n<dd class=\"option-desc\"><p>Name of the registry to use. Registry names are defined in <a href=\"../reference/config.html\">Cargo config\nfiles</a>. If not specified, the default registry is used,\nwhich is defined by the <code>registry.default</code> config key which defaults to\n<code>crates-io</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---index\"><a class=\"option-anchor\" href=\"#option-cargo-install---index\"><code>--index</code> <em>index</em></a></dt>\n<dd class=\"option-desc\"><p>The URL of the registry index to use.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-install--F\"><a class=\"option-anchor\" href=\"#option-cargo-install--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-install---features\"><a class=\"option-anchor\" href=\"#option-cargo-install---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-install---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-install---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Compilation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-install---target\"><a class=\"option-anchor\" href=\"#option-cargo-install---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Install for the specified target architecture. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-install---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to a new temporary folder located in the\ntemporary directory of the platform.</p>\n<p>When using <code>--path</code>, by default it will use <code>target</code> directory in the workspace\nof the local crate unless <code>--target-dir</code>\nis specified.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---debug\"><a class=\"option-anchor\" href=\"#option-cargo-install---debug\"><code>--debug</code></a></dt>\n<dd class=\"option-desc\"><p>Build with the <code>dev</code> profile instead of the <code>release</code> profile.\nSee also the <code>--profile</code> option for choosing a specific profile by name.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---profile\"><a class=\"option-anchor\" href=\"#option-cargo-install---profile\"><code>--profile</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Install with the given profile.\nSee <a href=\"../reference/profiles.html\">the reference</a> for more details on profiles.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---timings\"><a class=\"option-anchor\" href=\"#option-cargo-install---timings\"><code>--timings</code></a></dt>\n<dd class=\"option-desc\"><p>Output information how long each compilation takes, and track concurrency\ninformation over time.</p>\n<p>A file <code>cargo-timing.html</code> will be written to the <code>target/cargo-timings</code>\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine-readable timing data.</p>\n</dd>\n\n\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-install---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-install---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---locked\"><a class=\"option-anchor\" href=\"#option-cargo-install---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---offline\"><a class=\"option-anchor\" href=\"#option-cargo-install---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-install---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n</dl>\n\n### Miscellaneous Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-install--j\"><a class=\"option-anchor\" href=\"#option-cargo-install--j\"><code>-j</code> <em>N</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-install---jobs\"><a class=\"option-anchor\" href=\"#option-cargo-install---jobs\"><code>--jobs</code> <em>N</em></a></dt>\n<dd class=\"option-desc\"><p>Number of parallel jobs to run. May also be specified with the\n<code>build.jobs</code> <a href=\"../reference/config.html\">config value</a>. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string <code>default</code> is provided, it sets the value back to defaults.\nShould not be 0.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-install---keep-going\"><a class=\"option-anchor\" href=\"#option-cargo-install---keep-going\"><code>--keep-going</code></a></dt>\n<dd class=\"option-desc\"><p>Build as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.</p>\n<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,\none of which fails to build, <code>cargo install -j1</code> may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas <code>cargo install -j1 --keep-going</code> would definitely run both\nbuilds, even if the one run first fails.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-install--v\"><a class=\"option-anchor\" href=\"#option-cargo-install--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-install---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-install---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install--q\"><a class=\"option-anchor\" href=\"#option-cargo-install--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-install---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-install---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---color\"><a class=\"option-anchor\" href=\"#option-cargo-install---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---message-format\"><a class=\"option-anchor\" href=\"#option-cargo-install---message-format\"><code>--message-format</code> <em>fmt</em></a></dt>\n<dd class=\"option-desc\"><p>The output format for diagnostic messages. Can be specified multiple times\nand consists of comma-separated values. Valid values:</p>\n<ul>\n<li><code>human</code> (default): Display in a human-readable text format. Conflicts with\n<code>short</code> and <code>json</code>.</li>\n<li><code>short</code>: Emit shorter, human-readable text messages. Conflicts with <code>human</code>\nand <code>json</code>.</li>\n<li><code>json</code>: Emit JSON messages to stdout. See\n<a href=\"../reference/external-tools.html#json-messages\">the reference</a>\nfor more details. Conflicts with <code>human</code> and <code>short</code>.</li>\n<li><code>json-diagnostic-short</code>: Ensure the <code>rendered</code> field of JSON messages contains\nthe “short” rendering from rustc. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-diagnostic-rendered-ansi</code>: Ensure the <code>rendered</code> field of JSON messages\ncontains embedded ANSI color codes for respecting rustc’s default color\nscheme. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-render-diagnostics</code>: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo’s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with <code>human</code> or <code>short</code>.</li>\n</ul>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-install-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-install-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install---config\"><a class=\"option-anchor\" href=\"#option-cargo-install---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install--C\"><a class=\"option-anchor\" href=\"#option-cargo-install--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install--h\"><a class=\"option-anchor\" href=\"#option-cargo-install--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-install---help\"><a class=\"option-anchor\" href=\"#option-cargo-install---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-install--Z\"><a class=\"option-anchor\" href=\"#option-cargo-install--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Install or upgrade a package from crates.io:\n\n       cargo install ripgrep\n\n2. Install or reinstall the package in the current directory:\n\n       cargo install --path .\n\n3. View the list of installed packages:\n\n       cargo install --list\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-uninstall(1)](cargo-uninstall.html), [cargo-search(1)](cargo-search.html), [cargo-publish(1)](cargo-publish.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-locate-project.md",
    "content": "# cargo-locate-project(1)\n\n## NAME\n\ncargo-locate-project --- Print a JSON representation of a Cargo.toml file's location\n\n## SYNOPSIS\n\n`cargo locate-project` [_options_]\n\n## DESCRIPTION\n\nThis command will print a JSON object to stdout with the full path to the manifest. The\nmanifest is found by searching upward for a file named `Cargo.toml` starting from the current\nworking directory.\n\nIf the project happens to be a part of a workspace, the manifest of the project, rather than\nthe workspace root, is output. This can be overridden by the `--workspace` flag. The root\nworkspace is found by traversing further upward or by using the field `package.workspace` after\nlocating the manifest of a workspace member.\n\n## OPTIONS\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-locate-project---workspace\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project---workspace\"><code>--workspace</code></a></dt>\n<dd class=\"option-desc\"><p>Locate the <code>Cargo.toml</code> at the root of the workspace, as opposed to the current\nworkspace member.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-locate-project---message-format\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project---message-format\"><code>--message-format</code> <em>fmt</em></a></dt>\n<dd class=\"option-desc\"><p>The representation in which to print the project location. Valid values:</p>\n<ul>\n<li><code>json</code> (default): JSON object with the path under the key “root”.</li>\n<li><code>plain</code>: Just the path.</li>\n</ul>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-locate-project--v\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-locate-project---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-locate-project--q\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-locate-project---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-locate-project---color\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-locate-project---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-locate-project-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-locate-project---config\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-locate-project--C\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-locate-project--h\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-locate-project---help\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-locate-project--Z\"><a class=\"option-anchor\" href=\"#option-cargo-locate-project--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Display the path to the manifest based on the current directory:\n\n       cargo locate-project\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-metadata(1)](cargo-metadata.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-login.md",
    "content": "# cargo-login(1)\n\n## NAME\n\ncargo-login --- Log in to a registry\n\n## SYNOPSIS\n\n`cargo login` [_options_] [`--` _args_]\n\n## DESCRIPTION\n\nThis command will run a credential provider to save a token so that commands\nthat require authentication, such as [cargo-publish(1)](cargo-publish.html), will be\nautomatically authenticated.\n\nAll the arguments following the two dashes (`--`) are passed to the credential provider.\n\nFor the default `cargo:token` credential provider, the token is saved\nin `$CARGO_HOME/credentials.toml`. `CARGO_HOME` defaults to `.cargo`\nin your home directory.\n\nIf a registry has a credential-provider specified, it will be used. Otherwise,\nthe providers from the config value `registry.global-credential-providers` will\nbe attempted, starting from the end of the list.\n\nThe _token_ will be read from stdin.\n\nThe API token for crates.io may be retrieved from <https://crates.io/me>.\n\nTake care to keep the token secret, it should not be shared with anyone else.\n\n## OPTIONS\n\n### Login Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-login---registry\"><a class=\"option-anchor\" href=\"#option-cargo-login---registry\"><code>--registry</code> <em>registry</em></a></dt>\n<dd class=\"option-desc\"><p>Name of the registry to use. Registry names are defined in <a href=\"../reference/config.html\">Cargo config\nfiles</a>. If not specified, the default registry is used,\nwhich is defined by the <code>registry.default</code> config key which defaults to\n<code>crates-io</code>.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-login--v\"><a class=\"option-anchor\" href=\"#option-cargo-login--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-login---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-login---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-login--q\"><a class=\"option-anchor\" href=\"#option-cargo-login--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-login---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-login---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-login---color\"><a class=\"option-anchor\" href=\"#option-cargo-login---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-login-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-login-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-login---config\"><a class=\"option-anchor\" href=\"#option-cargo-login---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-login--C\"><a class=\"option-anchor\" href=\"#option-cargo-login--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-login--h\"><a class=\"option-anchor\" href=\"#option-cargo-login--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-login---help\"><a class=\"option-anchor\" href=\"#option-cargo-login---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-login--Z\"><a class=\"option-anchor\" href=\"#option-cargo-login--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Save the token for the default registry:\n\n       cargo login\n\n2. Save the token for a specific registry:\n\n       cargo login --registry my-registry\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-logout(1)](cargo-logout.html), [cargo-publish(1)](cargo-publish.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-logout.md",
    "content": "# cargo-logout(1)\n\n## NAME\n\ncargo-logout --- Remove an API token from the registry locally\n\n## SYNOPSIS\n\n`cargo logout` [_options_]\n\n## DESCRIPTION\n\nThis command will run a credential provider to remove a saved token.\n\nFor the default `cargo:token` credential provider, credentials are stored\nin `$CARGO_HOME/credentials.toml` where `$CARGO_HOME` defaults to `.cargo`\nin your home directory.\n\nIf a registry has a credential-provider specified, it will be used. Otherwise,\nthe providers from the config value `registry.global-credential-providers` will\nbe attempted, starting from the end of the list.\n\nIf `--registry` is not specified, then the credentials for the default\nregistry will be removed (configured by\n[`registry.default`](../reference/config.html#registrydefault), which defaults\nto <https://crates.io/>).\n\nThis will not revoke the token on the server. If you need to revoke the token,\nvisit the registry website and follow its instructions (see\n<https://crates.io/me> to revoke the token for <https://crates.io/>).\n\n## OPTIONS\n\n### Logout Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-logout---registry\"><a class=\"option-anchor\" href=\"#option-cargo-logout---registry\"><code>--registry</code> <em>registry</em></a></dt>\n<dd class=\"option-desc\"><p>Name of the registry to use. Registry names are defined in <a href=\"../reference/config.html\">Cargo config\nfiles</a>. If not specified, the default registry is used,\nwhich is defined by the <code>registry.default</code> config key which defaults to\n<code>crates-io</code>.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-logout--v\"><a class=\"option-anchor\" href=\"#option-cargo-logout--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-logout---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-logout---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-logout--q\"><a class=\"option-anchor\" href=\"#option-cargo-logout--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-logout---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-logout---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-logout---color\"><a class=\"option-anchor\" href=\"#option-cargo-logout---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-logout-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-logout-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-logout---config\"><a class=\"option-anchor\" href=\"#option-cargo-logout---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-logout--C\"><a class=\"option-anchor\" href=\"#option-cargo-logout--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-logout--h\"><a class=\"option-anchor\" href=\"#option-cargo-logout--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-logout---help\"><a class=\"option-anchor\" href=\"#option-cargo-logout---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-logout--Z\"><a class=\"option-anchor\" href=\"#option-cargo-logout--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Remove the default registry token:\n\n       cargo logout\n\n2. Remove the token for a specific registry:\n\n       cargo logout --registry my-registry\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-login(1)](cargo-login.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-metadata.md",
    "content": "# cargo-metadata(1)\n\n## NAME\n\ncargo-metadata --- Machine-readable metadata about the current package\n\n## SYNOPSIS\n\n`cargo metadata` [_options_]\n\n## DESCRIPTION\n\nOutput JSON to stdout containing information about the workspace members and\nresolved dependencies of the current package.\n\nThe output format is subject to change in future versions of Cargo. It\nis recommended to include the `--format-version` flag to future-proof your code\nand ensure the output is in the format you are expecting. For more on the\nexpectations, see [\"Compatibility\"](#compatibility).\n\nSee the [cargo_metadata crate](https://crates.io/crates/cargo_metadata)\nfor a Rust API for reading the metadata.\n\n## OUTPUT FORMAT\n\n### Compatibility\n\nWithin the same output format version, the compatibility is maintained, except\nsome scenarios. The following is a non-exhaustive list of changes that are not\nconsidered as incompatible:\n\n* **Adding new fields** — New fields will be added when needed. Reserving this\n  helps Cargo evolve without bumping the format version too often.\n* **Adding new values for enum-like fields** — Same as adding new fields. It\n  keeps metadata evolving without stagnation.\n* **Changing opaque representations** — The inner representations of some\n  fields are implementation details. For example, fields related to\n  \"Source ID\" are treated as opaque identifiers to differentiate packages or\n  sources. Consumers shouldn't rely on those representations unless specified.\n\n### JSON format\n\nThe JSON output has the following format:\n\n```javascript\n{\n    /* Array of all packages in the workspace.\n       It also includes all feature-enabled dependencies unless --no-deps is used.\n    */\n    \"packages\": [\n        {\n            /* The name of the package. */\n            \"name\": \"my-package\",\n            /* The version of the package. */\n            \"version\": \"0.1.0\",\n            /* The Package ID for referring to the\n               package within the document and as the `--package` argument to many commands\n            */\n            \"id\": \"file:///path/to/my-package#0.1.0\",\n            /* The license value from the manifest, or null. */\n            \"license\": \"MIT/Apache-2.0\",\n            /* The license-file value from the manifest, or null. */\n            \"license_file\": \"LICENSE\",\n            /* The description value from the manifest, or null. */\n            \"description\": \"Package description.\",\n            /* The source ID of the package, an \"opaque\" identifier representing\n               where a package is retrieved from. See \"Compatibility\" above for\n               the stability guarantee.\n\n               This is null for path dependencies and workspace members.\n\n               For other dependencies, it is a string with the format:\n               - \"registry+URL\" for registry-based dependencies.\n                 Example: \"registry+https://github.com/rust-lang/crates.io-index\"\n               - \"git+URL\" for git-based dependencies.\n                 Example: \"git+https://github.com/rust-lang/cargo?rev=5e85ba14aaa20f8133863373404cb0af69eeef2c#5e85ba14aaa20f8133863373404cb0af69eeef2c\"\n               - \"sparse+URL\" for dependencies from a sparse registry\n                 Example: \"sparse+https://my-sparse-registry.org\"\n\n               The value after the `+` is not explicitly defined, and may change\n               between versions of Cargo and may not directly correlate to other\n               things, such as registry definitions in a config file. New source\n               kinds may be added in the future which will have different `+`\n               prefixed identifiers.\n            */\n            \"source\": null,\n            /* Array of dependencies declared in the package's manifest. */\n            \"dependencies\": [\n                {\n                    /* The name of the dependency. */\n                    \"name\": \"bitflags\",\n                    /* The source ID of the dependency. May be null, see\n                       description for the package source.\n                    */\n                    \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n                    /* The version requirement for the dependency.\n                       Dependencies without a version requirement have a value of \"*\".\n                    */\n                    \"req\": \"^1.0\",\n                    /* The dependency kind.\n                       \"dev\", \"build\", or null for a normal dependency.\n                    */\n                    \"kind\": null,\n                    /* If the dependency is renamed, this is the new name for\n                       the dependency as a string.  null if it is not renamed.\n                    */\n                    \"rename\": null,\n                    /* Boolean of whether or not this is an optional dependency. */\n                    \"optional\": false,\n                    /* Boolean of whether or not default features are enabled. */\n                    \"uses_default_features\": true,\n                    /* Array of features enabled. */\n                    \"features\": [],\n                    /* The target platform for the dependency.\n                       null if not a target dependency.\n                    */\n                    \"target\": \"cfg(windows)\",\n                    /* The file system path for a local path dependency.\n                       not present if not a path dependency.\n                    */\n                    \"path\": \"/path/to/dep\",\n                    /* A string of the URL of the registry this dependency is from.\n                       If not specified or null, the dependency is from the default\n                       registry (crates.io).\n                    */\n                    \"registry\": null,\n                    /* (unstable) Boolean flag of whether or not this is a pulbic\n                       dependency. This field is only present when\n                       `-Zpublic-dependency` is enabled.\n                    */\n                    \"public\": false\n                }\n            ],\n            /* Array of Cargo targets. */\n            \"targets\": [\n                {\n                    /* Array of target kinds.\n                       - lib targets list the `crate-type` values from the\n                         manifest such as \"lib\", \"rlib\", \"dylib\",\n                         \"proc-macro\", etc. (default [\"lib\"])\n                       - binary is [\"bin\"]\n                       - example is [\"example\"]\n                       - integration test is [\"test\"]\n                       - benchmark is [\"bench\"]\n                       - build script is [\"custom-build\"]\n                    */\n                    \"kind\": [\n                        \"bin\"\n                    ],\n                    /* Array of crate types.\n                       - lib and example libraries list the `crate-type` values\n                         from the manifest such as \"lib\", \"rlib\", \"dylib\",\n                         \"proc-macro\", etc. (default [\"lib\"])\n                       - all other target kinds are [\"bin\"]\n                    */\n                    \"crate_types\": [\n                        \"bin\"\n                    ],\n                    /* The name of the target.\n                       For lib targets, dashes will be replaced with underscores.\n                    */\n                    \"name\": \"my-package\",\n                    /* Absolute path to the root source file of the target. */\n                    \"src_path\": \"/path/to/my-package/src/main.rs\",\n                    /* The Rust edition of the target.\n                       Defaults to the package edition.\n                    */\n                    \"edition\": \"2018\",\n                    /* Array of required features.\n                       This property is not included if no required features are set.\n                    */\n                    \"required-features\": [\"feat1\"],\n                    /* Whether the target should be documented by `cargo doc`. */\n                    \"doc\": true,\n                    /* Whether or not this target has doc tests enabled, and\n                       the target is compatible with doc testing.\n                    */\n                    \"doctest\": false,\n                    /* Whether or not this target should be built and run with `--test`\n                    */\n                    \"test\": true\n                }\n            ],\n            /* Set of features defined for the package.\n               Each feature maps to an array of features or dependencies it\n               enables.\n            */\n            \"features\": {\n                \"default\": [\n                    \"feat1\"\n                ],\n                \"feat1\": [],\n                \"feat2\": []\n            },\n            /* Absolute path to this package's manifest. */\n            \"manifest_path\": \"/path/to/my-package/Cargo.toml\",\n            /* Package metadata.\n               This is null if no metadata is specified.\n            */\n            \"metadata\": {\n                \"docs\": {\n                    \"rs\": {\n                        \"all-features\": true\n                    }\n                }\n            },\n            /* List of registries to which this package may be published.\n               Publishing is unrestricted if null, and forbidden if an empty array. */\n            \"publish\": [\n                \"crates-io\"\n            ],\n            /* Array of authors from the manifest.\n               Empty array if no authors specified.\n            */\n            \"authors\": [\n                \"Jane Doe <user@example.com>\"\n            ],\n            /* Array of categories from the manifest. */\n            \"categories\": [\n                \"command-line-utilities\"\n            ],\n            /* Optional string that is the default binary picked by cargo run. */\n            \"default_run\": null,\n            /* Optional string that is the minimum supported rust version */\n            \"rust_version\": \"1.56\",\n            /* Array of keywords from the manifest. */\n            \"keywords\": [\n                \"cli\"\n            ],\n            /* The readme value from the manifest or null if not specified. */\n            \"readme\": \"README.md\",\n            /* The repository value from the manifest or null if not specified. */\n            \"repository\": \"https://github.com/rust-lang/cargo\",\n            /* The homepage value from the manifest or null if not specified. */\n            \"homepage\": \"https://rust-lang.org\",\n            /* The documentation value from the manifest or null if not specified. */\n            \"documentation\": \"https://doc.rust-lang.org/stable/std\",\n            /* The default edition of the package.\n               Note that individual targets may have different editions.\n            */\n            \"edition\": \"2018\",\n            /* Optional string that is the name of a native library the package\n               is linking to.\n            */\n            \"links\": null,\n        }\n    ],\n    /* Array of members of the workspace.\n       Each entry is the Package ID for the package.\n    */\n    \"workspace_members\": [\n        \"file:///path/to/my-package#0.1.0\",\n    ],\n    /* Array of default members of the workspace.\n       Each entry is the Package ID for the package.\n    */\n    \"workspace_default_members\": [\n        \"file:///path/to/my-package#0.1.0\",\n    ],\n    // The resolved dependency graph for the entire workspace. The enabled\n    // features are based on the enabled features for the \"current\" package.\n    // Inactivated optional dependencies are not listed.\n    //\n    // This is null if --no-deps is specified.\n    //\n    // By default, this includes all dependencies for all target platforms.\n    // The `--filter-platform` flag may be used to narrow to a specific\n    // target triple.\n    \"resolve\": {\n        /* Array of nodes within the dependency graph.\n           Each node is a package.\n        */\n        \"nodes\": [\n            {\n                /* The Package ID of this node. */\n                \"id\": \"file:///path/to/my-package#0.1.0\",\n                /* The dependencies of this package, an array of Package IDs. */\n                \"dependencies\": [\n                    \"https://github.com/rust-lang/crates.io-index#bitflags@1.0.4\"\n                ],\n                /* The dependencies of this package. This is an alternative to\n                   \"dependencies\" which contains additional information. In\n                   particular, this handles renamed dependencies.\n                */\n                \"deps\": [\n                    {\n                        /* The name of the dependency's library target.\n                           If this is a renamed dependency, this is the new\n                           name.\n                        */\n                        \"name\": \"bitflags\",\n                        /* The Package ID of the dependency. */\n                        \"pkg\": \"https://github.com/rust-lang/crates.io-index#bitflags@1.0.4\"\n                        /* Array of dependency kinds. Added in Cargo 1.40. */\n                        \"dep_kinds\": [\n                            {\n                                /* The dependency kind.\n                                   \"dev\", \"build\", or null for a normal dependency.\n                                */\n                                \"kind\": null,\n                                /* The target platform for the dependency.\n                                   null if not a target dependency.\n                                */\n                                \"target\": \"cfg(windows)\"\n                            }\n                        ]\n                    }\n                ],\n                /* Array of features enabled on this package. */\n                \"features\": [\n                    \"default\"\n                ]\n            }\n        ],\n        /* The package in the current working directory (if --manifest-path is not given).\n           This is null if there is a virtual workspace. Otherwise it is\n           the Package ID of the package.\n        */\n        \"root\": \"file:///path/to/my-package#0.1.0\",\n    },\n    /* The absolute path to the target directory where Cargo places its output. */\n    \"target_directory\": \"/path/to/my-package/target\",\n    /* The absolute path to the build directory where Cargo places intermediate build artifacts. (unstable) */\n    \"build_directory\": \"/path/to/my-package/build-dir\",\n    /* The version of the schema for this metadata structure.\n       This will be changed if incompatible changes are ever made.\n    */\n    \"version\": 1,\n    /* The absolute path to the root of the workspace. */\n    \"workspace_root\": \"/path/to/my-package\"\n    /* Workspace metadata.\n       This is null if no metadata is specified. */\n    \"metadata\": {\n        \"docs\": {\n            \"rs\": {\n                \"all-features\": true\n            }\n        }\n    }\n}\n````\n\nNotes:\n- For `\"id\"` field syntax, see [Package ID Specifications] in the reference.\n\n## OPTIONS\n\n### Output Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-metadata---no-deps\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---no-deps\"><code>--no-deps</code></a></dt>\n<dd class=\"option-desc\"><p>Output information only about the workspace members and don’t fetch\ndependencies.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata---format-version\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---format-version\"><code>--format-version</code> <em>version</em></a></dt>\n<dd class=\"option-desc\"><p>Specify the version of the output format to use. Currently <code>1</code> is the only\npossible value.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata---filter-platform\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---filter-platform\"><code>--filter-platform</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>This filters the <code>resolve</code> output to only include dependencies for the\ngiven <a href=\"../appendix/glossary.html#target\">target triple</a>.\nA literal <code>\"host-tuple\"</code> can be used, which will internally be substituted by the host’s target.\nWithout this flag, the resolve includes all targets.</p>\n<p>Note that the dependencies listed in the “packages” array still includes all\ndependencies. Each package definition is intended to be an unaltered\nreproduction of the information within <code>Cargo.toml</code>.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-metadata--F\"><a class=\"option-anchor\" href=\"#option-cargo-metadata--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-metadata---features\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-metadata--v\"><a class=\"option-anchor\" href=\"#option-cargo-metadata--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-metadata---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata--q\"><a class=\"option-anchor\" href=\"#option-cargo-metadata--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-metadata---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata---color\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-metadata---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata---locked\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata---offline\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-metadata-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-metadata-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata---config\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata--C\"><a class=\"option-anchor\" href=\"#option-cargo-metadata--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata--h\"><a class=\"option-anchor\" href=\"#option-cargo-metadata--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-metadata---help\"><a class=\"option-anchor\" href=\"#option-cargo-metadata---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-metadata--Z\"><a class=\"option-anchor\" href=\"#option-cargo-metadata--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Output JSON about the current package:\n\n       cargo metadata --format-version=1\n\n## SEE ALSO\n\n[cargo(1)](cargo.html), [cargo-pkgid(1)](cargo-pkgid.html), [Package ID Specifications], [JSON messages]\n\n[Package ID Specifications]: ../reference/pkgid-spec.html\n[JSON messages]: ../reference/external-tools.html#json-messages\n"
  },
  {
    "path": "src/doc/src/commands/cargo-miri.md",
    "content": "# cargo-miri(1)\n\n## NAME\n\ncargo-miri --- Runs binary crates and tests in Miri\n\n## DESCRIPTION\n\nThis is an external command distributed with the Rust toolchain as an optional component.\nIt is not built into Cargo, and may require additional installation.\n\nThis command is only available on the [nightly](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html) channel.\n\nFor information about usage and installation,\nsee <https://github.com/rust-lang/miri>.\n\n## SEE ALSO\n\n[cargo(1)](cargo.md),\n[cargo-run(1)](cargo-run.md),\n[cargo-test(1)](cargo-test.md),\n[Custom subcommands](../reference/external-tools.md#custom-subcommands)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-new.md",
    "content": "# cargo-new(1)\n\n## NAME\n\ncargo-new --- Create a new Cargo package\n\n## SYNOPSIS\n\n`cargo new` [_options_] _path_\n\n## DESCRIPTION\n\nThis command will create a new Cargo package in the given directory. This\nincludes a simple template with a `Cargo.toml` manifest, sample source file,\nand a VCS ignore file. If the directory is not already in a VCS repository,\nthen a new repository is created (see `--vcs` below).\n\nSee [cargo-init(1)](cargo-init.html) for a similar command which will create a new manifest\nin an existing directory.\n\n## OPTIONS\n\n### New Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-new---bin\"><a class=\"option-anchor\" href=\"#option-cargo-new---bin\"><code>--bin</code></a></dt>\n<dd class=\"option-desc\"><p>Create a package with a binary target (<code>src/main.rs</code>).\nThis is the default behavior.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-new---lib\"><a class=\"option-anchor\" href=\"#option-cargo-new---lib\"><code>--lib</code></a></dt>\n<dd class=\"option-desc\"><p>Create a package with a library target (<code>src/lib.rs</code>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-new---edition\"><a class=\"option-anchor\" href=\"#option-cargo-new---edition\"><code>--edition</code> <em>edition</em></a></dt>\n<dd class=\"option-desc\"><p>Specify the Rust edition to use. Default is 2024.\nPossible values: 2015, 2018, 2021, 2024</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-new---name\"><a class=\"option-anchor\" href=\"#option-cargo-new---name\"><code>--name</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Set the package name. Defaults to the directory name.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-new---vcs\"><a class=\"option-anchor\" href=\"#option-cargo-new---vcs\"><code>--vcs</code> <em>vcs</em></a></dt>\n<dd class=\"option-desc\"><p>Initialize a new VCS repository for the given version control system (git,\nhg, pijul, or fossil) or do not initialize any version control at all\n(none). If not specified, defaults to <code>git</code> or the configuration value\n<code>cargo-new.vcs</code>, or <code>none</code> if already inside a VCS repository.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-new---registry\"><a class=\"option-anchor\" href=\"#option-cargo-new---registry\"><code>--registry</code> <em>registry</em></a></dt>\n<dd class=\"option-desc\"><p>This sets the <code>publish</code> field in <code>Cargo.toml</code> to the given registry name\nwhich will restrict publishing only to that registry.</p>\n<p>Registry names are defined in <a href=\"../reference/config.html\">Cargo config files</a>.\nIf not specified, the default registry defined by the <code>registry.default</code>\nconfig key is used. If the default registry is not set and <code>--registry</code> is not\nused, the <code>publish</code> field will not be set which means that publishing will not\nbe restricted.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-new--v\"><a class=\"option-anchor\" href=\"#option-cargo-new--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-new---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-new---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-new--q\"><a class=\"option-anchor\" href=\"#option-cargo-new--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-new---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-new---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-new---color\"><a class=\"option-anchor\" href=\"#option-cargo-new---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-new-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-new-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-new---config\"><a class=\"option-anchor\" href=\"#option-cargo-new---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-new--C\"><a class=\"option-anchor\" href=\"#option-cargo-new--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-new--h\"><a class=\"option-anchor\" href=\"#option-cargo-new--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-new---help\"><a class=\"option-anchor\" href=\"#option-cargo-new---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-new--Z\"><a class=\"option-anchor\" href=\"#option-cargo-new--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Create a binary Cargo package in the given directory:\n\n       cargo new foo\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-init(1)](cargo-init.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-owner.md",
    "content": "# cargo-owner(1)\n\n## NAME\n\ncargo-owner --- Manage the owners of a crate on the registry\n\n## SYNOPSIS\n\n`cargo owner` [_options_] `--add` _login_ [_crate_]\\\n`cargo owner` [_options_] `--remove` _login_ [_crate_]\\\n`cargo owner` [_options_] `--list` [_crate_]\n\n## DESCRIPTION\n\nThis command will modify the owners for a crate on the registry. Owners of a\ncrate can upload new versions and yank old versions. Non-team owners can also\nmodify the set of owners, so take care!\n\nThis command requires you to be authenticated with either the `--token` option\nor using [cargo-login(1)](cargo-login.html).\n\nIf the crate name is not specified, it will use the package name from the\ncurrent directory.\n\nSee [the reference](../reference/publishing.html#cargo-owner) for more\ninformation about owners and publishing.\n\n## OPTIONS\n\n### Owner Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-owner--a\"><a class=\"option-anchor\" href=\"#option-cargo-owner--a\"><code>-a</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-owner---add\"><a class=\"option-anchor\" href=\"#option-cargo-owner---add\"><code>--add</code> <em>login</em>…</a></dt>\n<dd class=\"option-desc\"><p>Invite the given user or team as an owner.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-owner--r\"><a class=\"option-anchor\" href=\"#option-cargo-owner--r\"><code>-r</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-owner---remove\"><a class=\"option-anchor\" href=\"#option-cargo-owner---remove\"><code>--remove</code> <em>login</em>…</a></dt>\n<dd class=\"option-desc\"><p>Remove the given user or team as an owner.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-owner--l\"><a class=\"option-anchor\" href=\"#option-cargo-owner--l\"><code>-l</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-owner---list\"><a class=\"option-anchor\" href=\"#option-cargo-owner---list\"><code>--list</code></a></dt>\n<dd class=\"option-desc\"><p>List owners of a crate.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-owner---token\"><a class=\"option-anchor\" href=\"#option-cargo-owner---token\"><code>--token</code> <em>token</em></a></dt>\n<dd class=\"option-desc\"><p>API token to use when authenticating. This overrides the token stored in\nthe credentials file (which is created by <a href=\"cargo-login.html\">cargo-login(1)</a>).</p>\n<p><a href=\"../reference/config.html\">Cargo config</a> environment variables can be\nused to override the tokens stored in the credentials file. The token for\ncrates.io may be specified with the <code>CARGO_REGISTRY_TOKEN</code> environment\nvariable. Tokens for other registries may be specified with environment\nvariables of the form <code>CARGO_REGISTRIES_NAME_TOKEN</code> where <code>NAME</code> is the name\nof the registry in all capital letters.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-owner---index\"><a class=\"option-anchor\" href=\"#option-cargo-owner---index\"><code>--index</code> <em>index</em></a></dt>\n<dd class=\"option-desc\"><p>The URL of the registry index to use.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-owner---registry\"><a class=\"option-anchor\" href=\"#option-cargo-owner---registry\"><code>--registry</code> <em>registry</em></a></dt>\n<dd class=\"option-desc\"><p>Name of the registry to use. Registry names are defined in <a href=\"../reference/config.html\">Cargo config\nfiles</a>. If not specified, the default registry is used,\nwhich is defined by the <code>registry.default</code> config key which defaults to\n<code>crates-io</code>.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-owner--v\"><a class=\"option-anchor\" href=\"#option-cargo-owner--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-owner---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-owner---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-owner--q\"><a class=\"option-anchor\" href=\"#option-cargo-owner--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-owner---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-owner---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-owner---color\"><a class=\"option-anchor\" href=\"#option-cargo-owner---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-owner-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-owner-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-owner---config\"><a class=\"option-anchor\" href=\"#option-cargo-owner---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-owner--C\"><a class=\"option-anchor\" href=\"#option-cargo-owner--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-owner--h\"><a class=\"option-anchor\" href=\"#option-cargo-owner--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-owner---help\"><a class=\"option-anchor\" href=\"#option-cargo-owner---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-owner--Z\"><a class=\"option-anchor\" href=\"#option-cargo-owner--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. List owners of a package:\n\n       cargo owner --list foo\n\n2. Invite an owner to a package:\n\n       cargo owner --add username foo\n\n3. Remove an owner from a package:\n\n       cargo owner --remove username foo\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-login(1)](cargo-login.html), [cargo-publish(1)](cargo-publish.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-package.md",
    "content": "# cargo-package(1)\n## NAME\n\ncargo-package --- Assemble the local package into a distributable tarball\n\n## SYNOPSIS\n\n`cargo package` [_options_]\n\n## DESCRIPTION\n\nThis command will create a distributable, compressed `.crate` file with the\nsource code of the package in the current directory. The resulting file will be\nstored in the `target/package` directory. This performs the following steps:\n\n1. Load and check the current workspace, performing some basic checks.\n    - Path dependencies are not allowed unless they have a version key. Cargo\n      will ignore the path key for dependencies in published packages.\n      `dev-dependencies` do not have this restriction.\n2. Create the compressed `.crate` file.\n    - The original `Cargo.toml` file is rewritten and normalized.\n    - `[patch]`, `[replace]`, and `[workspace]` sections are removed from the\n      manifest.\n    - `Cargo.lock` is always included. When missing, a new lock file will be\n      generated unless the `--exclude-lockfile` flag is used. [cargo-install(1)](cargo-install.html)\n      will use the packaged lock file if the `--locked` flag is used.\n    - A `.cargo_vcs_info.json` file is included that contains information\n      about the current VCS checkout hash if available, as well as a flag if the\n      worktree is dirty.\n    - Symlinks are flattened to their target files.\n    - Files and directories are included or excluded based on rules mentioned in\n      [the `[include]` and `[exclude]` fields](../reference/manifest.html#the-exclude-and-include-fields).\n\n3. Extract the `.crate` file and build it to verify it can build.\n    - This will rebuild your package from scratch to ensure that it can be\n      built from a pristine state. The `--no-verify` flag can be used to skip\n      this step.\n4. Check that build scripts did not modify any source files.\n\nThe list of files included can be controlled with the `include` and `exclude`\nfields in the manifest.\n\nSee [the reference](../reference/publishing.html) for more details about\npackaging and publishing.\n\n### .cargo_vcs_info.json format\n\nWill generate a `.cargo_vcs_info.json` in the following format\n\n```javascript\n{\n \"git\": {\n   \"sha1\": \"aac20b6e7e543e6dd4118b246c77225e3a3a1302\",\n   \"dirty\": true\n },\n \"path_in_vcs\": \"\"\n}\n```\n\n`dirty` indicates that the Git worktree was dirty when the package\nwas built.\n\n`path_in_vcs` will be set to a repo-relative path for packages\nin subdirectories of the version control repository.\n\nThe compatibility of this file is maintained under the same policy\nas the JSON output of [cargo-metadata(1)](cargo-metadata.html).\n\nNote that this file provides a best-effort snapshot of the VCS information.\nHowever, the provenance of the package is not verified.\nThere is no guarantee that the source code in the tarball matches the VCS information.\n\n## OPTIONS\n\n### Package Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-package--l\"><a class=\"option-anchor\" href=\"#option-cargo-package--l\"><code>-l</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-package---list\"><a class=\"option-anchor\" href=\"#option-cargo-package---list\"><code>--list</code></a></dt>\n<dd class=\"option-desc\"><p>Print files included in a package without making one.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---no-verify\"><a class=\"option-anchor\" href=\"#option-cargo-package---no-verify\"><code>--no-verify</code></a></dt>\n<dd class=\"option-desc\"><p>Don’t verify the contents by building them.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---no-metadata\"><a class=\"option-anchor\" href=\"#option-cargo-package---no-metadata\"><code>--no-metadata</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore warnings about a lack of human-usable metadata (such as the description\nor the license).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---allow-dirty\"><a class=\"option-anchor\" href=\"#option-cargo-package---allow-dirty\"><code>--allow-dirty</code></a></dt>\n<dd class=\"option-desc\"><p>Allow working directories with uncommitted VCS changes to be packaged.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---exclude-lockfile\"><a class=\"option-anchor\" href=\"#option-cargo-package---exclude-lockfile\"><code>--exclude-lockfile</code></a></dt>\n<dd class=\"option-desc\"><p>Don’t include the lock file when packaging.</p>\n<p>This flag is not for general use.\nSome tools may expect a lock file to be present (e.g. <code>cargo install --locked</code>).\nConsider other options before using this.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---index\"><a class=\"option-anchor\" href=\"#option-cargo-package---index\"><code>--index</code> <em>index</em></a></dt>\n<dd class=\"option-desc\"><p>The URL of the registry index to use.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---registry\"><a class=\"option-anchor\" href=\"#option-cargo-package---registry\"><code>--registry</code> <em>registry</em></a></dt>\n<dd class=\"option-desc\"><p>Name of the registry to package for; see <code>cargo publish --help</code> for more details\nabout configuration of registry names. The packages will not be published\nto this registry, but if we are packaging multiple inter-dependent crates,\nlock-files will be generated under the assumption that dependencies will be\npublished to this registry.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---message-format\"><a class=\"option-anchor\" href=\"#option-cargo-package---message-format\"><code>--message-format</code> <em>fmt</em></a></dt>\n<dd class=\"option-desc\"><p>Specifies the output message format.\nCurrently, it only works with <code>--list</code> and affects the file listing format.\nThis is unstable and requires <code>-Zunstable-options</code>.\nValid output formats:</p>\n<ul>\n<li><code>human</code> (default): Display in a file-per-line format.</li>\n<li><code>json</code>: Emit machine-readable JSON information about each package.\nOne package per JSON line (Newline delimited JSON).\n<pre><code class=\"language-javascript\">{\n  /* The Package ID Spec of the package. */\n  \"id\": \"path+file:///home/foo#0.0.0\",\n  /* Files of this package */\n  \"files\" {\n    /* Relative path in the archive file. */\n    \"Cargo.toml.orig\": {\n      /* Where the file is from.\n         - \"generate\" for file being generated during packaging\n         - \"copy\" for file being copied from another location.\n      */\n      \"kind\": \"copy\",\n      /* For the \"copy\" kind,\n         it is an absolute path to the actual file content.\n         For the \"generate\" kind,\n         it is the original file the generated one is based on.\n      */\n      \"path\": \"/home/foo/Cargo.toml\"\n    },\n    \"Cargo.toml\": {\n      \"kind\": \"generate\",\n      \"path\": \"/home/foo/Cargo.toml\"\n    },\n    \"src/main.rs\": {\n      \"kind\": \"copy\",\n      \"path\": \"/home/foo/src/main.rs\"\n    }\n  }\n}\n</code></pre>\n</li>\n</ul>\n</dd>\n\n\n</dl>\n\n### Package Selection\n\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n`--manifest-path` is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n\nThe default members of a workspace can be set explicitly with the\n`workspace.default-members` key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n`--workspace`), and a non-virtual workspace will include only the root crate itself.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-package--p\"><a class=\"option-anchor\" href=\"#option-cargo-package--p\"><code>-p</code> <em>spec</em>…</a></dt>\n<dt class=\"option-term\" id=\"option-cargo-package---package\"><a class=\"option-anchor\" href=\"#option-cargo-package---package\"><code>--package</code> <em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Package only the specified packages. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---workspace\"><a class=\"option-anchor\" href=\"#option-cargo-package---workspace\"><code>--workspace</code></a></dt>\n<dd class=\"option-desc\"><p>Package all members in the workspace.</p>\n</dd>\n\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---exclude\"><a class=\"option-anchor\" href=\"#option-cargo-package---exclude\"><code>--exclude</code> <em>SPEC</em>…</a></dt>\n<dd class=\"option-desc\"><p>Exclude the specified packages. Must be used in conjunction with the\n<code>--workspace</code> flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.</p>\n</dd>\n\n\n</dl>\n\n### Compilation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-package---target\"><a class=\"option-anchor\" href=\"#option-cargo-package---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Package for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-package---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to <code>target</code> in the root of the workspace.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-package--F\"><a class=\"option-anchor\" href=\"#option-cargo-package--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-package---features\"><a class=\"option-anchor\" href=\"#option-cargo-package---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-package---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-package---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Manifest Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-package---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-package---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---locked\"><a class=\"option-anchor\" href=\"#option-cargo-package---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---offline\"><a class=\"option-anchor\" href=\"#option-cargo-package---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-package---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n\n</dl>\n\n### Miscellaneous Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-package--j\"><a class=\"option-anchor\" href=\"#option-cargo-package--j\"><code>-j</code> <em>N</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-package---jobs\"><a class=\"option-anchor\" href=\"#option-cargo-package---jobs\"><code>--jobs</code> <em>N</em></a></dt>\n<dd class=\"option-desc\"><p>Number of parallel jobs to run. May also be specified with the\n<code>build.jobs</code> <a href=\"../reference/config.html\">config value</a>. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string <code>default</code> is provided, it sets the value back to defaults.\nShould not be 0.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-package---keep-going\"><a class=\"option-anchor\" href=\"#option-cargo-package---keep-going\"><code>--keep-going</code></a></dt>\n<dd class=\"option-desc\"><p>Build as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.</p>\n<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,\none of which fails to build, <code>cargo package -j1</code> may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas <code>cargo package -j1 --keep-going</code> would definitely run both\nbuilds, even if the one run first fails.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-package--v\"><a class=\"option-anchor\" href=\"#option-cargo-package--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-package---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-package---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package--q\"><a class=\"option-anchor\" href=\"#option-cargo-package--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-package---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-package---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---color\"><a class=\"option-anchor\" href=\"#option-cargo-package---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-package-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-package-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package---config\"><a class=\"option-anchor\" href=\"#option-cargo-package---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package--C\"><a class=\"option-anchor\" href=\"#option-cargo-package--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package--h\"><a class=\"option-anchor\" href=\"#option-cargo-package--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-package---help\"><a class=\"option-anchor\" href=\"#option-cargo-package---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-package--Z\"><a class=\"option-anchor\" href=\"#option-cargo-package--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Create a compressed `.crate` file of the current package:\n\n       cargo package\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-publish(1)](cargo-publish.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-pkgid.md",
    "content": "# cargo-pkgid(1)\n\n## NAME\n\ncargo-pkgid --- Print a fully qualified package specification\n\n## SYNOPSIS\n\n`cargo pkgid` [_options_] [_spec_]\n\n## DESCRIPTION\n\nGiven a _spec_ argument, print out the fully qualified package ID specifier\nfor a package or dependency in the current workspace. This command will\ngenerate an error if _spec_ is ambiguous as to which package it refers to in\nthe dependency graph. If no _spec_ is given, then the specifier for the local\npackage is printed.\n\nThis command requires that a lockfile is available and dependencies have been\nfetched.\n\nA package specifier consists of a name, version, and source URL. You are\nallowed to use partial specifiers to succinctly match a specific package as\nlong as it matches only one package. This specifier is also used by other parts\nin Cargo, such as [cargo-metadata(1)](cargo-metadata.html) and [JSON messages] emitted by Cargo.\n\nThe format of a _spec_ can be one of the following:\n\nSPEC Structure             | Example SPEC\n---------------------------|--------------\n_name_                     | `bitflags`\n_name_`@`_version_         | `bitflags@1.0.4`\n_url_                      | `https://github.com/rust-lang/cargo`\n_url_`#`_version_          | `https://github.com/rust-lang/cargo#0.33.0`\n_url_`#`_name_             | `https://github.com/rust-lang/crates.io-index#bitflags`\n_url_`#`_name_`@`_version_ | `https://github.com/rust-lang/cargo#crates-io@0.21.0`\n\nThe specification grammar can be found in chapter [Package ID Specifications].\n\n## OPTIONS\n\n### Package Selection\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-pkgid--p\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid--p\"><code>-p</code> <em>spec</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-pkgid---package\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid---package\"><code>--package</code> <em>spec</em></a></dt>\n<dd class=\"option-desc\"><p>Get the package ID for the given package instead of the current package.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-pkgid--v\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-pkgid---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-pkgid--q\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-pkgid---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-pkgid---color\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-pkgid---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-pkgid---locked\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-pkgid---offline\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-pkgid---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-pkgid-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-pkgid---config\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-pkgid--C\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-pkgid--h\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-pkgid---help\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-pkgid--Z\"><a class=\"option-anchor\" href=\"#option-cargo-pkgid--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Retrieve package specification for `foo` package:\n\n       cargo pkgid foo\n\n2. Retrieve package specification for version 1.0.0 of `foo`:\n\n       cargo pkgid foo@1.0.0\n\n3. Retrieve package specification for `foo` from crates.io:\n\n       cargo pkgid https://github.com/rust-lang/crates.io-index#foo\n\n4. Retrieve package specification for `foo` from a local package:\n\n       cargo pkgid file:///path/to/local/package#foo\n\n## SEE ALSO\n\n[cargo(1)](cargo.html), [cargo-generate-lockfile(1)](cargo-generate-lockfile.html), [cargo-metadata(1)](cargo-metadata.html),\n[Package ID Specifications], [JSON messages]\n\n[Package ID Specifications]: ../reference/pkgid-spec.html\n[JSON messages]: ../reference/external-tools.html#json-messages\n"
  },
  {
    "path": "src/doc/src/commands/cargo-publish.md",
    "content": "# cargo-publish(1)\n## NAME\n\ncargo-publish --- Upload a package to the registry\n\n## SYNOPSIS\n\n`cargo publish` [_options_]\n\n## DESCRIPTION\n\nThis command will create a distributable, compressed `.crate` file with the\nsource code of the package in the current directory and upload it to a\nregistry. The default registry is <https://crates.io>. This performs the\nfollowing steps:\n\n1. Performs a few checks, including:\n   - Checks the `package.publish` key in the manifest for restrictions on\n     which registries you are allowed to publish to.\n2. Create a `.crate` file by following the steps in [cargo-package(1)](cargo-package.html).\n3. Upload the crate to the registry. The server will perform additional\n   checks on the crate. \n4. The client will poll waiting for the package to appear in the index,\n   and may timeout. In that case, you will need to check for completion\n   manually. This timeout does not affect the upload.\n\nThis command requires you to be authenticated using [cargo-login(1)](cargo-login.html)\nor environment variables of the [`registry.token`](../reference/config.html#registrytoken)\nand [`registries.<name>.token`](../reference/config.html#registriesnametoken) config fields.\n\nSee [the reference](../reference/publishing.html) for more details about\npackaging and publishing.\n\n## OPTIONS\n\n### Publish Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-publish---dry-run\"><a class=\"option-anchor\" href=\"#option-cargo-publish---dry-run\"><code>--dry-run</code></a></dt>\n<dd class=\"option-desc\"><p>Perform all checks without uploading.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---no-verify\"><a class=\"option-anchor\" href=\"#option-cargo-publish---no-verify\"><code>--no-verify</code></a></dt>\n<dd class=\"option-desc\"><p>Don’t verify the contents by building them.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---allow-dirty\"><a class=\"option-anchor\" href=\"#option-cargo-publish---allow-dirty\"><code>--allow-dirty</code></a></dt>\n<dd class=\"option-desc\"><p>Allow working directories with uncommitted VCS changes to be packaged.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---index\"><a class=\"option-anchor\" href=\"#option-cargo-publish---index\"><code>--index</code> <em>index</em></a></dt>\n<dd class=\"option-desc\"><p>The URL of the registry index to use.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---registry\"><a class=\"option-anchor\" href=\"#option-cargo-publish---registry\"><code>--registry</code> <em>registry</em></a></dt>\n<dd class=\"option-desc\"><p>Name of the registry to publish to. Registry names are defined in <a href=\"../reference/config.html\">Cargo\nconfig files</a>. If not specified, and there is a\n<a href=\"../reference/manifest.html#the-publish-field\"><code>package.publish</code></a> field in\n<code>Cargo.toml</code> with a single registry, then it will publish to that registry.\nOtherwise it will use the default registry, which is defined by the\n<a href=\"../reference/config.html#registrydefault\"><code>registry.default</code></a> config key\nwhich defaults to <code>crates-io</code>.</p>\n</dd>\n\n\n</dl>\n\n### Package Selection\n\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n`--manifest-path` is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n\nThe default members of a workspace can be set explicitly with the\n`workspace.default-members` key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n`--workspace`), and a non-virtual workspace will include only the root crate itself.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-publish--p\"><a class=\"option-anchor\" href=\"#option-cargo-publish--p\"><code>-p</code> <em>spec</em>…</a></dt>\n<dt class=\"option-term\" id=\"option-cargo-publish---package\"><a class=\"option-anchor\" href=\"#option-cargo-publish---package\"><code>--package</code> <em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Publish only the specified packages. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---workspace\"><a class=\"option-anchor\" href=\"#option-cargo-publish---workspace\"><code>--workspace</code></a></dt>\n<dd class=\"option-desc\"><p>Publish all members in the workspace.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---all\"><a class=\"option-anchor\" href=\"#option-cargo-publish---all\"><code>--all</code></a></dt>\n<dd class=\"option-desc\"><p>Deprecated alias for <code>--workspace</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---exclude\"><a class=\"option-anchor\" href=\"#option-cargo-publish---exclude\"><code>--exclude</code> <em>SPEC</em>…</a></dt>\n<dd class=\"option-desc\"><p>Exclude the specified packages. Must be used in conjunction with the\n<code>--workspace</code> flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.</p>\n</dd>\n\n\n</dl>\n\n### Compilation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-publish---target\"><a class=\"option-anchor\" href=\"#option-cargo-publish---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Publish for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-publish---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to <code>target</code> in the root of the workspace.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-publish--F\"><a class=\"option-anchor\" href=\"#option-cargo-publish--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-publish---features\"><a class=\"option-anchor\" href=\"#option-cargo-publish---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-publish---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-publish---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Manifest Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-publish---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-publish---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---locked\"><a class=\"option-anchor\" href=\"#option-cargo-publish---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---offline\"><a class=\"option-anchor\" href=\"#option-cargo-publish---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-publish---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n\n</dl>\n\n### Miscellaneous Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-publish--j\"><a class=\"option-anchor\" href=\"#option-cargo-publish--j\"><code>-j</code> <em>N</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-publish---jobs\"><a class=\"option-anchor\" href=\"#option-cargo-publish---jobs\"><code>--jobs</code> <em>N</em></a></dt>\n<dd class=\"option-desc\"><p>Number of parallel jobs to run. May also be specified with the\n<code>build.jobs</code> <a href=\"../reference/config.html\">config value</a>. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string <code>default</code> is provided, it sets the value back to defaults.\nShould not be 0.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-publish---keep-going\"><a class=\"option-anchor\" href=\"#option-cargo-publish---keep-going\"><code>--keep-going</code></a></dt>\n<dd class=\"option-desc\"><p>Build as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.</p>\n<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,\none of which fails to build, <code>cargo publish -j1</code> may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas <code>cargo publish -j1 --keep-going</code> would definitely run both\nbuilds, even if the one run first fails.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-publish--v\"><a class=\"option-anchor\" href=\"#option-cargo-publish--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-publish---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-publish---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish--q\"><a class=\"option-anchor\" href=\"#option-cargo-publish--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-publish---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-publish---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---color\"><a class=\"option-anchor\" href=\"#option-cargo-publish---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-publish-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-publish-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish---config\"><a class=\"option-anchor\" href=\"#option-cargo-publish---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish--C\"><a class=\"option-anchor\" href=\"#option-cargo-publish--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish--h\"><a class=\"option-anchor\" href=\"#option-cargo-publish--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-publish---help\"><a class=\"option-anchor\" href=\"#option-cargo-publish---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-publish--Z\"><a class=\"option-anchor\" href=\"#option-cargo-publish--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Publish the current package:\n\n       cargo publish\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-package(1)](cargo-package.html), [cargo-login(1)](cargo-login.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-remove.md",
    "content": "# cargo-remove(1)\n## NAME\n\ncargo-remove --- Remove dependencies from a Cargo.toml manifest file\n\n## SYNOPSIS\n\n`cargo remove` [_options_] _dependency_...\n\n## DESCRIPTION\n\nRemove one or more dependencies from a `Cargo.toml` manifest.\n\n## OPTIONS\n\n### Section options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-remove---dev\"><a class=\"option-anchor\" href=\"#option-cargo-remove---dev\"><code>--dev</code></a></dt>\n<dd class=\"option-desc\"><p>Remove as a <a href=\"../reference/specifying-dependencies.html#development-dependencies\">development dependency</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-remove---build\"><a class=\"option-anchor\" href=\"#option-cargo-remove---build\"><code>--build</code></a></dt>\n<dd class=\"option-desc\"><p>Remove as a <a href=\"../reference/specifying-dependencies.html#build-dependencies\">build dependency</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-remove---target\"><a class=\"option-anchor\" href=\"#option-cargo-remove---target\"><code>--target</code> <em>target</em></a></dt>\n<dd class=\"option-desc\"><p>Remove as a dependency to the <a href=\"../reference/specifying-dependencies.html#platform-specific-dependencies\">given target platform</a>.</p>\n<p>To avoid unexpected shell expansions, you may use quotes around each target, e.g., <code>--target 'cfg(unix)'</code>.</p>\n</dd>\n\n\n</dl>\n\n### Miscellaneous Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-remove---dry-run\"><a class=\"option-anchor\" href=\"#option-cargo-remove---dry-run\"><code>--dry-run</code></a></dt>\n<dd class=\"option-desc\"><p>Don’t actually write to the manifest.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-remove--v\"><a class=\"option-anchor\" href=\"#option-cargo-remove--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-remove---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-remove---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-remove--q\"><a class=\"option-anchor\" href=\"#option-cargo-remove--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-remove---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-remove---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-remove---color\"><a class=\"option-anchor\" href=\"#option-cargo-remove---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-remove---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-remove---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-remove---locked\"><a class=\"option-anchor\" href=\"#option-cargo-remove---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-remove---offline\"><a class=\"option-anchor\" href=\"#option-cargo-remove---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-remove---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-remove---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Package Selection\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-remove--p\"><a class=\"option-anchor\" href=\"#option-cargo-remove--p\"><code>-p</code> <em>spec</em>…</a></dt>\n<dt class=\"option-term\" id=\"option-cargo-remove---package\"><a class=\"option-anchor\" href=\"#option-cargo-remove---package\"><code>--package</code> <em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Package to remove from.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-remove-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-remove-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-remove---config\"><a class=\"option-anchor\" href=\"#option-cargo-remove---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-remove--C\"><a class=\"option-anchor\" href=\"#option-cargo-remove--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-remove--h\"><a class=\"option-anchor\" href=\"#option-cargo-remove--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-remove---help\"><a class=\"option-anchor\" href=\"#option-cargo-remove---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-remove--Z\"><a class=\"option-anchor\" href=\"#option-cargo-remove--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Remove `regex` as a dependency\n\n       cargo remove regex\n\n2. Remove `trybuild` as a dev-dependency\n\n       cargo remove --dev trybuild\n\n3. Remove `nom` from the `wasm32-unknown-unknown` dependencies table\n\n       cargo remove --target wasm32-unknown-unknown nom\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-add(1)](cargo-add.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-report-future-incompatibilities.md",
    "content": "# cargo-report-future-incompatibilities(1)\n## NAME\n\ncargo-report-future-incompatibilities --- Reports any crates which will eventually stop compiling\n\n## SYNOPSIS\n\n`cargo report future-incompatibilities` [_options_]\n\n## DESCRIPTION\n\nDisplays a report of future-incompatible warnings that were emitted during\nprevious builds.\nThese are warnings for changes that may become hard errors in the future,\ncausing dependencies to stop building in a future version of rustc.\n\nFor more, see the chapter on [Future incompat report](../reference/future-incompat-report.html).\n\n## OPTIONS\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities---id\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities---id\"><code>--id</code> <em>id</em></a></dt>\n<dd class=\"option-desc\"><p>Show the report with the specified Cargo-generated id.\nIf not specified, shows the most recent report.</p>\n</dd>\n\n\n</dl>\n\n### Package Selection\n\nBy default, the package in the current working directory is selected. The `-p`\nflag can be used to choose a different package in a workspace.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities--p\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities--p\"><code>-p</code> <em>spec</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities---package\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities---package\"><code>--package</code> <em>spec</em></a></dt>\n<dd class=\"option-desc\"><p>The package to display a report for. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the SPEC\nformat.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities--v\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities--q\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities---color\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities---locked\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities---offline\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities---config\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities--C\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities--h\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities---help\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report-future-incompatibilities--Z\"><a class=\"option-anchor\" href=\"#option-cargo-report-future-incompatibilities--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Display the latest future-incompat report:\n\n       cargo report future-incompat\n\n2. Display the latest future-incompat report for a specific package:\n\n       cargo report future-incompat --package my-dep@0.0.1\n\n## SEE ALSO\n\n[cargo(1)](cargo.html), [cargo-report(1)](cargo-report.html), [cargo-build(1)](cargo-build.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-report.md",
    "content": "# cargo-report(1)\n\n## NAME\n\ncargo-report --- Generate and display various kinds of reports\n\n## SYNOPSIS\n\n`cargo report` _type_ [_options_]\n\n## DESCRIPTION\n\nDisplays a report of the given _type_ --- currently, only `future-incompat` is supported\n\n## OPTIONS\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-report--v\"><a class=\"option-anchor\" href=\"#option-cargo-report--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-report---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-report---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report--q\"><a class=\"option-anchor\" href=\"#option-cargo-report--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-report---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-report---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report---color\"><a class=\"option-anchor\" href=\"#option-cargo-report---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-report---locked\"><a class=\"option-anchor\" href=\"#option-cargo-report---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report---offline\"><a class=\"option-anchor\" href=\"#option-cargo-report---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-report---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-report-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-report-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report---config\"><a class=\"option-anchor\" href=\"#option-cargo-report---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report--C\"><a class=\"option-anchor\" href=\"#option-cargo-report--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report--h\"><a class=\"option-anchor\" href=\"#option-cargo-report--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-report---help\"><a class=\"option-anchor\" href=\"#option-cargo-report---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-report--Z\"><a class=\"option-anchor\" href=\"#option-cargo-report--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Display the available kinds of reports:\n\n       cargo report --help\n\n## SEE ALSO\n\n[cargo(1)](cargo.html), [cargo-report-future-incompatibilities(1)](cargo-report-future-incompatibilities.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-run.md",
    "content": "# cargo-run(1)\n## NAME\n\ncargo-run --- Run the current package\n\n## SYNOPSIS\n\n`cargo run` [_options_] [`--` _args_]\n\n## DESCRIPTION\n\nRun a binary or example of the local package.\n\nAll the arguments following the two dashes (`--`) are passed to the binary to\nrun. If you're passing arguments to both Cargo and the binary, the ones after\n`--` go to the binary, the ones before go to Cargo.\n\nUnlike [cargo-test(1)](cargo-test.html) and [cargo-bench(1)](cargo-bench.html), `cargo run` sets the \nworking directory of the binary executed to the current working directory, same \nas if it was executed in the shell directly.\n\n## OPTIONS\n\n### Package Selection\n\nBy default, the package in the current working directory is selected. The `-p`\nflag can be used to choose a different package in a workspace.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-run--p\"><a class=\"option-anchor\" href=\"#option-cargo-run--p\"><code>-p</code> <em>spec</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-run---package\"><a class=\"option-anchor\" href=\"#option-cargo-run---package\"><code>--package</code> <em>spec</em></a></dt>\n<dd class=\"option-desc\"><p>The package to run. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the SPEC\nformat.</p>\n</dd>\n\n\n</dl>\n\n### Target Selection\n\nWhen no target selection options are given, `cargo run` will run the binary\ntarget. If there are multiple binary targets, you must pass a target flag to\nchoose one. Or, the `default-run` field may be specified in the `[package]`\nsection of `Cargo.toml` to choose the name of the binary to run by default.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-run---bin\"><a class=\"option-anchor\" href=\"#option-cargo-run---bin\"><code>--bin</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Run the specified binary.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run---example\"><a class=\"option-anchor\" href=\"#option-cargo-run---example\"><code>--example</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Run the specified example.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-run--F\"><a class=\"option-anchor\" href=\"#option-cargo-run--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-run---features\"><a class=\"option-anchor\" href=\"#option-cargo-run---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-run---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-run---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Compilation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-run---target\"><a class=\"option-anchor\" href=\"#option-cargo-run---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Run for the specified target architecture. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run--r\"><a class=\"option-anchor\" href=\"#option-cargo-run--r\"><code>-r</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-run---release\"><a class=\"option-anchor\" href=\"#option-cargo-run---release\"><code>--release</code></a></dt>\n<dd class=\"option-desc\"><p>Run optimized artifacts with the <code>release</code> profile.\nSee also the <code>--profile</code> option for choosing a specific profile by name.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run---profile\"><a class=\"option-anchor\" href=\"#option-cargo-run---profile\"><code>--profile</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Run with the given profile.\nSee <a href=\"../reference/profiles.html\">the reference</a> for more details on profiles.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run---timings\"><a class=\"option-anchor\" href=\"#option-cargo-run---timings\"><code>--timings</code></a></dt>\n<dd class=\"option-desc\"><p>Output information how long each compilation takes, and track concurrency\ninformation over time.</p>\n<p>A file <code>cargo-timing.html</code> will be written to the <code>target/cargo-timings</code>\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine-readable timing data.</p>\n</dd>\n\n\n\n</dl>\n\n### Output Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-run---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-run---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to <code>target</code> in the root of the workspace.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-run--v\"><a class=\"option-anchor\" href=\"#option-cargo-run--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-run---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-run---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run--q\"><a class=\"option-anchor\" href=\"#option-cargo-run--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-run---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-run---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run---color\"><a class=\"option-anchor\" href=\"#option-cargo-run---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run---message-format\"><a class=\"option-anchor\" href=\"#option-cargo-run---message-format\"><code>--message-format</code> <em>fmt</em></a></dt>\n<dd class=\"option-desc\"><p>The output format for diagnostic messages. Can be specified multiple times\nand consists of comma-separated values. Valid values:</p>\n<ul>\n<li><code>human</code> (default): Display in a human-readable text format. Conflicts with\n<code>short</code> and <code>json</code>.</li>\n<li><code>short</code>: Emit shorter, human-readable text messages. Conflicts with <code>human</code>\nand <code>json</code>.</li>\n<li><code>json</code>: Emit JSON messages to stdout. See\n<a href=\"../reference/external-tools.html#json-messages\">the reference</a>\nfor more details. Conflicts with <code>human</code> and <code>short</code>.</li>\n<li><code>json-diagnostic-short</code>: Ensure the <code>rendered</code> field of JSON messages contains\nthe “short” rendering from rustc. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-diagnostic-rendered-ansi</code>: Ensure the <code>rendered</code> field of JSON messages\ncontains embedded ANSI color codes for respecting rustc’s default color\nscheme. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-render-diagnostics</code>: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo’s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with <code>human</code> or <code>short</code>.</li>\n</ul>\n</dd>\n\n\n</dl>\n\n### Manifest Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-run---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-run---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-run---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run---locked\"><a class=\"option-anchor\" href=\"#option-cargo-run---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run---offline\"><a class=\"option-anchor\" href=\"#option-cargo-run---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-run---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-run-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-run-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run---config\"><a class=\"option-anchor\" href=\"#option-cargo-run---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run--C\"><a class=\"option-anchor\" href=\"#option-cargo-run--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run--h\"><a class=\"option-anchor\" href=\"#option-cargo-run--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-run---help\"><a class=\"option-anchor\" href=\"#option-cargo-run---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-run--Z\"><a class=\"option-anchor\" href=\"#option-cargo-run--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n### Miscellaneous Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-run--j\"><a class=\"option-anchor\" href=\"#option-cargo-run--j\"><code>-j</code> <em>N</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-run---jobs\"><a class=\"option-anchor\" href=\"#option-cargo-run---jobs\"><code>--jobs</code> <em>N</em></a></dt>\n<dd class=\"option-desc\"><p>Number of parallel jobs to run. May also be specified with the\n<code>build.jobs</code> <a href=\"../reference/config.html\">config value</a>. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string <code>default</code> is provided, it sets the value back to defaults.\nShould not be 0.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-run---keep-going\"><a class=\"option-anchor\" href=\"#option-cargo-run---keep-going\"><code>--keep-going</code></a></dt>\n<dd class=\"option-desc\"><p>Build as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.</p>\n<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,\none of which fails to build, <code>cargo run -j1</code> may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas <code>cargo run -j1 --keep-going</code> would definitely run both\nbuilds, even if the one run first fails.</p>\n</dd>\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Build the local package and run its main target (assuming only one binary):\n\n       cargo run\n\n2. Run an example with extra arguments:\n\n       cargo run --example exname -- --exoption exarg1 exarg2\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-build(1)](cargo-build.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-rustc.md",
    "content": "# cargo-rustc(1)\n## NAME\n\ncargo-rustc --- Compile the current package, and pass extra options to the compiler\n\n## SYNOPSIS\n\n`cargo rustc` [_options_] [`--` _args_]\n\n## DESCRIPTION\n\nThe specified target for the current package (or package specified by `-p` if\nprovided) will be compiled along with all of its dependencies. The specified\n_args_ will all be passed to the final compiler invocation, not any of the\ndependencies. Note that the compiler will still unconditionally receive\narguments such as `-L`, `--extern`, and `--crate-type`, and the specified\n_args_ will simply be added to the compiler invocation.\n\nSee <https://doc.rust-lang.org/rustc/index.html> for documentation on rustc\nflags.\n\nThis command requires that only one target is being compiled when additional\narguments are provided. If more than one target is available for the current\npackage the filters of `--lib`, `--bin`, etc, must be used to select which\ntarget is compiled.\n\nTo pass flags to all compiler processes spawned by Cargo, use the `RUSTFLAGS`\n[environment variable](../reference/environment-variables.html) or the\n`build.rustflags` [config value](../reference/config.html).\n\n## OPTIONS\n\n### Package Selection\n\nBy default, the package in the current working directory is selected. The `-p`\nflag can be used to choose a different package in a workspace.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustc--p\"><a class=\"option-anchor\" href=\"#option-cargo-rustc--p\"><code>-p</code> <em>spec</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustc---package\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---package\"><code>--package</code> <em>spec</em></a></dt>\n<dd class=\"option-desc\"><p>The package to build. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the SPEC\nformat.</p>\n</dd>\n\n\n</dl>\n\n### Target Selection\n\nWhen no target selection options are given, `cargo rustc` will build all\nbinary and library targets of the selected package.\n\nBinary targets are automatically built if there is an integration test or\nbenchmark being selected to build. This allows an integration\ntest to execute the binary to exercise and test its behavior. \nThe `CARGO_BIN_EXE_<name>`\n[environment variable](../reference/environment-variables.html#environment-variables-cargo-sets-for-crates)\nis set when the integration test is built and run so that it can use the\n[`env` macro](https://doc.rust-lang.org/std/macro.env.html) or the \n[`var` function](https://doc.rust-lang.org/std/env/fn.var.html) to locate the\nexecutable.\n\nPassing target selection flags will build only the specified\ntargets. \n\nNote that `--bin`, `--example`, `--test` and `--bench` flags also \nsupport common Unix glob patterns like `*`, `?` and `[]`. However, to avoid your \nshell accidentally expanding glob patterns before Cargo handles them, you must \nuse single quotes or double quotes around each glob pattern.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---lib\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---lib\"><code>--lib</code></a></dt>\n<dd class=\"option-desc\"><p>Build the package’s library.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---bin\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---bin\"><code>--bin</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Build the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---bins\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---bins\"><code>--bins</code></a></dt>\n<dd class=\"option-desc\"><p>Build all binary targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---example\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---example\"><code>--example</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Build the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---examples\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---examples\"><code>--examples</code></a></dt>\n<dd class=\"option-desc\"><p>Build all example targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---test\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---test\"><code>--test</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Build the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---tests\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---tests\"><code>--tests</code></a></dt>\n<dd class=\"option-desc\"><p>Build all targets that have the <code>test = true</code> manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the <code>test</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---bench\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---bench\"><code>--bench</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Build the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---benches\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---benches\"><code>--benches</code></a></dt>\n<dd class=\"option-desc\"><p>Build all targets that have the <code>bench = true</code>\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the <code>bench</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---all-targets\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---all-targets\"><code>--all-targets</code></a></dt>\n<dd class=\"option-desc\"><p>Build all targets. This is equivalent to specifying <code>--lib --bins --tests --benches --examples</code>.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustc--F\"><a class=\"option-anchor\" href=\"#option-cargo-rustc--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustc---features\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Compilation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---target\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Build for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc--r\"><a class=\"option-anchor\" href=\"#option-cargo-rustc--r\"><code>-r</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustc---release\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---release\"><code>--release</code></a></dt>\n<dd class=\"option-desc\"><p>Build optimized artifacts with the <code>release</code> profile.\nSee also the <code>--profile</code> option for choosing a specific profile by name.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---profile\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---profile\"><code>--profile</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Build with the given profile.</p>\n<p>The <code>rustc</code> subcommand will treat the following named profiles with special behaviors:</p>\n<ul>\n<li><code>check</code> — Builds in the same way as the <a href=\"cargo-check.html\">cargo-check(1)</a> command with\nthe <code>dev</code> profile.</li>\n<li><code>test</code> — Builds in the same way as the <a href=\"cargo-test.html\">cargo-test(1)</a> command,\nenabling building in test mode which will enable tests and enable the <code>test</code>\ncfg option. See <a href=\"https://doc.rust-lang.org/rustc/tests/index.html\">rustc\ntests</a> for more detail.</li>\n<li><code>bench</code> — Builds in the same was as the <a href=\"cargo-bench.html\">cargo-bench(1)</a> command,\nsimilar to the <code>test</code> profile.</li>\n</ul>\n<p>See <a href=\"../reference/profiles.html\">the reference</a> for more details on profiles.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---timings\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---timings\"><code>--timings</code></a></dt>\n<dd class=\"option-desc\"><p>Output information how long each compilation takes, and track concurrency\ninformation over time.</p>\n<p>A file <code>cargo-timing.html</code> will be written to the <code>target/cargo-timings</code>\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine-readable timing data.</p>\n</dd>\n\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---crate-type\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---crate-type\"><code>--crate-type</code> <em>crate-type</em></a></dt>\n<dd class=\"option-desc\"><p>Build for the given crate type. This flag accepts a comma-separated list of\n1 or more crate types, of which the allowed values are the same as <code>crate-type</code>\nfield in the manifest for configuring a Cargo target. See\n<a href=\"../reference/cargo-targets.html#the-crate-type-field\"><code>crate-type</code> field</a>\nfor possible values.</p>\n<p>If the manifest contains a list, and <code>--crate-type</code> is provided,\nthe command-line argument value will override what is in the manifest.</p>\n<p>This flag only works when building a <code>lib</code> or <code>example</code> library target.</p>\n</dd>\n\n\n</dl>\n\n### Output Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-rustc---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to <code>target</code> in the root of the workspace.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustc--v\"><a class=\"option-anchor\" href=\"#option-cargo-rustc--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustc---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc--q\"><a class=\"option-anchor\" href=\"#option-cargo-rustc--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustc---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---color\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---message-format\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---message-format\"><code>--message-format</code> <em>fmt</em></a></dt>\n<dd class=\"option-desc\"><p>The output format for diagnostic messages. Can be specified multiple times\nand consists of comma-separated values. Valid values:</p>\n<ul>\n<li><code>human</code> (default): Display in a human-readable text format. Conflicts with\n<code>short</code> and <code>json</code>.</li>\n<li><code>short</code>: Emit shorter, human-readable text messages. Conflicts with <code>human</code>\nand <code>json</code>.</li>\n<li><code>json</code>: Emit JSON messages to stdout. See\n<a href=\"../reference/external-tools.html#json-messages\">the reference</a>\nfor more details. Conflicts with <code>human</code> and <code>short</code>.</li>\n<li><code>json-diagnostic-short</code>: Ensure the <code>rendered</code> field of JSON messages contains\nthe “short” rendering from rustc. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-diagnostic-rendered-ansi</code>: Ensure the <code>rendered</code> field of JSON messages\ncontains embedded ANSI color codes for respecting rustc’s default color\nscheme. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-render-diagnostics</code>: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo’s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with <code>human</code> or <code>short</code>.</li>\n</ul>\n</dd>\n\n\n</dl>\n\n### Manifest Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---locked\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---offline\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustc-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-rustc-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---config\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc--C\"><a class=\"option-anchor\" href=\"#option-cargo-rustc--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc--h\"><a class=\"option-anchor\" href=\"#option-cargo-rustc--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustc---help\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustc--Z\"><a class=\"option-anchor\" href=\"#option-cargo-rustc--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n### Miscellaneous Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-rustc--j\"><a class=\"option-anchor\" href=\"#option-cargo-rustc--j\"><code>-j</code> <em>N</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustc---jobs\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---jobs\"><code>--jobs</code> <em>N</em></a></dt>\n<dd class=\"option-desc\"><p>Number of parallel jobs to run. May also be specified with the\n<code>build.jobs</code> <a href=\"../reference/config.html\">config value</a>. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string <code>default</code> is provided, it sets the value back to defaults.\nShould not be 0.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---keep-going\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---keep-going\"><code>--keep-going</code></a></dt>\n<dd class=\"option-desc\"><p>Build as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.</p>\n<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,\none of which fails to build, <code>cargo rustc -j1</code> may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas <code>cargo rustc -j1 --keep-going</code> would definitely run both\nbuilds, even if the one run first fails.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-rustc---future-incompat-report\"><a class=\"option-anchor\" href=\"#option-cargo-rustc---future-incompat-report\"><code>--future-incompat-report</code></a></dt>\n<dd class=\"option-desc\"><p>Displays a future-incompat report for any future-incompatible warnings\nproduced during execution of this command</p>\n<p>See <a href=\"cargo-report.html\">cargo-report(1)</a></p>\n</dd>\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Check if your package (not including dependencies) uses unsafe code:\n\n       cargo rustc --lib -- -D unsafe-code\n\n2. Try an experimental flag on the nightly compiler, such as this which prints\n   the size of every type:\n\n       cargo rustc --lib -- -Z print-type-sizes\n\n3. Override `crate-type` field in Cargo.toml with command-line option:\n\n       cargo rustc --lib --crate-type lib,cdylib\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-build(1)](cargo-build.html), [rustc(1)](https://doc.rust-lang.org/rustc/index.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-rustdoc.md",
    "content": "# cargo-rustdoc(1)\n## NAME\n\ncargo-rustdoc --- Build a package's documentation, using specified custom flags\n\n## SYNOPSIS\n\n`cargo rustdoc` [_options_] [`--` _args_]\n\n## DESCRIPTION\n\nThe specified target for the current package (or package specified by `-p` if\nprovided) will be documented with the specified _args_ being passed to the\nfinal rustdoc invocation. Dependencies will not be documented as part of this\ncommand. Note that rustdoc will still unconditionally receive arguments such\nas `-L`, `--extern`, and `--crate-type`, and the specified _args_ will simply\nbe added to the rustdoc invocation.\n\nSee <https://doc.rust-lang.org/rustdoc/index.html> for documentation on rustdoc\nflags.\n\nThis command requires that only one target is being compiled when additional\narguments are provided. If more than one target is available for the current\npackage the filters of `--lib`, `--bin`, etc, must be used to select which\ntarget is compiled.\n\nTo pass flags to all rustdoc processes spawned by Cargo, use the\n`RUSTDOCFLAGS` [environment variable](../reference/environment-variables.html)\nor the `build.rustdocflags` [config value](../reference/config.html).\n\n## OPTIONS\n\n### Documentation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---open\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---open\"><code>--open</code></a></dt>\n<dd class=\"option-desc\"><p>Open the docs in a browser after building them. This will use your default\nbrowser unless you define another one in the <code>BROWSER</code> environment variable\nor use the <a href=\"../reference/config.html#docbrowser\"><code>doc.browser</code></a> configuration\noption.</p>\n</dd>\n\n\n</dl>\n\n### Package Selection\n\nBy default, the package in the current working directory is selected. The `-p`\nflag can be used to choose a different package in a workspace.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc--p\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc--p\"><code>-p</code> <em>spec</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---package\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---package\"><code>--package</code> <em>spec</em></a></dt>\n<dd class=\"option-desc\"><p>The package to document. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the SPEC\nformat.</p>\n</dd>\n\n\n</dl>\n\n### Target Selection\n\nWhen no target selection options are given, `cargo rustdoc` will document all\nbinary and library targets of the selected package. The binary will be skipped\nif its name is the same as the lib target. Binaries are skipped if they have\n`required-features` that are missing.\n\nPassing target selection flags will document only the specified\ntargets. \n\nNote that `--bin`, `--example`, `--test` and `--bench` flags also \nsupport common Unix glob patterns like `*`, `?` and `[]`. However, to avoid your \nshell accidentally expanding glob patterns before Cargo handles them, you must \nuse single quotes or double quotes around each glob pattern.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---lib\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---lib\"><code>--lib</code></a></dt>\n<dd class=\"option-desc\"><p>Document the package’s library.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---bin\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---bin\"><code>--bin</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Document the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---bins\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---bins\"><code>--bins</code></a></dt>\n<dd class=\"option-desc\"><p>Document all binary targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---example\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---example\"><code>--example</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Document the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---examples\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---examples\"><code>--examples</code></a></dt>\n<dd class=\"option-desc\"><p>Document all example targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---test\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---test\"><code>--test</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Document the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---tests\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---tests\"><code>--tests</code></a></dt>\n<dd class=\"option-desc\"><p>Document all targets that have the <code>test = true</code> manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the <code>test</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---bench\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---bench\"><code>--bench</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Document the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---benches\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---benches\"><code>--benches</code></a></dt>\n<dd class=\"option-desc\"><p>Document all targets that have the <code>bench = true</code>\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the <code>bench</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---all-targets\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---all-targets\"><code>--all-targets</code></a></dt>\n<dd class=\"option-desc\"><p>Document all targets. This is equivalent to specifying <code>--lib --bins --tests --benches --examples</code>.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc--F\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---features\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Compilation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---target\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Document for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc--r\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc--r\"><code>-r</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---release\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---release\"><code>--release</code></a></dt>\n<dd class=\"option-desc\"><p>Document optimized artifacts with the <code>release</code> profile.\nSee also the <code>--profile</code> option for choosing a specific profile by name.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---profile\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---profile\"><code>--profile</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Document with the given profile.\nSee <a href=\"../reference/profiles.html\">the reference</a> for more details on profiles.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---timings\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---timings\"><code>--timings</code></a></dt>\n<dd class=\"option-desc\"><p>Output information how long each compilation takes, and track concurrency\ninformation over time.</p>\n<p>A file <code>cargo-timing.html</code> will be written to the <code>target/cargo-timings</code>\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine-readable timing data.</p>\n</dd>\n\n\n\n</dl>\n\n### Output Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to <code>target</code> in the root of the workspace.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-rustdoc--v\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc--q\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---color\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---message-format\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---message-format\"><code>--message-format</code> <em>fmt</em></a></dt>\n<dd class=\"option-desc\"><p>The output format for diagnostic messages. Can be specified multiple times\nand consists of comma-separated values. Valid values:</p>\n<ul>\n<li><code>human</code> (default): Display in a human-readable text format. Conflicts with\n<code>short</code> and <code>json</code>.</li>\n<li><code>short</code>: Emit shorter, human-readable text messages. Conflicts with <code>human</code>\nand <code>json</code>.</li>\n<li><code>json</code>: Emit JSON messages to stdout. See\n<a href=\"../reference/external-tools.html#json-messages\">the reference</a>\nfor more details. Conflicts with <code>human</code> and <code>short</code>.</li>\n<li><code>json-diagnostic-short</code>: Ensure the <code>rendered</code> field of JSON messages contains\nthe “short” rendering from rustc. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-diagnostic-rendered-ansi</code>: Ensure the <code>rendered</code> field of JSON messages\ncontains embedded ANSI color codes for respecting rustc’s default color\nscheme. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-render-diagnostics</code>: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo’s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with <code>human</code> or <code>short</code>.</li>\n</ul>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---locked\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---offline\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---config\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc--C\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc--h\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---help\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc--Z\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n### Miscellaneous Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-rustdoc--j\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc--j\"><code>-j</code> <em>N</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---jobs\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---jobs\"><code>--jobs</code> <em>N</em></a></dt>\n<dd class=\"option-desc\"><p>Number of parallel jobs to run. May also be specified with the\n<code>build.jobs</code> <a href=\"../reference/config.html\">config value</a>. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string <code>default</code> is provided, it sets the value back to defaults.\nShould not be 0.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---keep-going\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---keep-going\"><code>--keep-going</code></a></dt>\n<dd class=\"option-desc\"><p>Build as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.</p>\n<p>For example if the current package depends on dependencies <code>fails</code> and <code>works</code>,\none of which fails to build, <code>cargo rustdoc -j1</code> may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas <code>cargo rustdoc -j1 --keep-going</code> would definitely run both\nbuilds, even if the one run first fails.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-rustdoc---output-format\"><a class=\"option-anchor\" href=\"#option-cargo-rustdoc---output-format\"><code>--output-format</code></a></dt>\n<dd class=\"option-desc\"><p>The output type for the documentation emitted. Valid values:</p>\n<ul>\n<li><code>html</code> (default): Emit the documentation in HTML format.</li>\n<li><code>json</code>: Emit the documentation in the <a href=\"https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types\">experimental JSON format</a>.</li>\n</ul>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly channel</a>\nand requires the <code>-Z unstable-options</code> flag to enable.</p>\n</dd>\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Build documentation with custom CSS included from a given file:\n\n       cargo rustdoc --lib -- --extend-css extra.css\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-doc(1)](cargo-doc.html), [rustdoc(1)](https://doc.rust-lang.org/rustdoc/index.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-search.md",
    "content": "# cargo-search(1)\n\n## NAME\n\ncargo-search --- Search packages in the registry. Default registry is crates.io\n\n## SYNOPSIS\n\n`cargo search` [_options_] [_query_...]\n\n## DESCRIPTION\n\nThis performs a textual search for crates on <https://crates.io>. The matching\ncrates will be displayed along with their description in TOML format suitable\nfor copying into a `Cargo.toml` manifest.\n\n## OPTIONS\n\n### Search Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-search---limit\"><a class=\"option-anchor\" href=\"#option-cargo-search---limit\"><code>--limit</code> <em>limit</em></a></dt>\n<dd class=\"option-desc\"><p>Limit the number of results (default: 10, max: 100).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-search---index\"><a class=\"option-anchor\" href=\"#option-cargo-search---index\"><code>--index</code> <em>index</em></a></dt>\n<dd class=\"option-desc\"><p>The URL of the registry index to use.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-search---registry\"><a class=\"option-anchor\" href=\"#option-cargo-search---registry\"><code>--registry</code> <em>registry</em></a></dt>\n<dd class=\"option-desc\"><p>Name of the registry to use. Registry names are defined in <a href=\"../reference/config.html\">Cargo config\nfiles</a>. If not specified, the default registry is used,\nwhich is defined by the <code>registry.default</code> config key which defaults to\n<code>crates-io</code>.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-search--v\"><a class=\"option-anchor\" href=\"#option-cargo-search--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-search---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-search---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-search--q\"><a class=\"option-anchor\" href=\"#option-cargo-search--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-search---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-search---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-search---color\"><a class=\"option-anchor\" href=\"#option-cargo-search---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-search-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-search-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-search---config\"><a class=\"option-anchor\" href=\"#option-cargo-search---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-search--C\"><a class=\"option-anchor\" href=\"#option-cargo-search--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-search--h\"><a class=\"option-anchor\" href=\"#option-cargo-search--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-search---help\"><a class=\"option-anchor\" href=\"#option-cargo-search---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-search--Z\"><a class=\"option-anchor\" href=\"#option-cargo-search--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Search for a package from crates.io:\n\n       cargo search serde\n\n## SEE ALSO\n\n[cargo(1)](cargo.html), [cargo-install(1)](cargo-install.html), [cargo-publish(1)](cargo-publish.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-test.md",
    "content": "# cargo-test(1)\n## NAME\n\ncargo-test --- Execute unit and integration tests of a package\n\n## SYNOPSIS\n\n`cargo test` [_options_] [_testname_] [`--` _test-options_]\n\n## DESCRIPTION\n\nCompile and execute unit, integration, and documentation tests.\n\nThe test filtering argument `TESTNAME` and all the arguments following the two\ndashes (`--`) are passed to the test binaries and thus to _libtest_ (rustc's\nbuilt in unit-test and micro-benchmarking framework).  If you're passing\narguments to both Cargo and the binary, the ones after `--` go to the binary,\nthe ones before go to Cargo.  For details about libtest's arguments see the\noutput of `cargo test -- --help` and check out the rustc book's chapter on\nhow tests work at <https://doc.rust-lang.org/rustc/tests/index.html>.\n\nAs an example, this will filter for tests with `foo` in their name and run them\non 3 threads in parallel:\n\n    cargo test foo -- --test-threads 3\n\nTests are built with the `--test` option to `rustc` which creates a special\nexecutable by linking your code with libtest. The executable automatically\nruns all functions annotated with the `#[test]` attribute in multiple threads.\n`#[bench]` annotated functions will also be run with one iteration to verify\nthat they are functional.\n\nIf the package contains multiple test targets, each target compiles to a\nspecial executable as aforementioned, and then is run serially.\n\nThe libtest harness may be disabled by setting `harness = false` in the target\nmanifest settings, in which case your code will need to provide its own `main`\nfunction to handle running tests.\n\n### Documentation tests\n\nDocumentation tests are also run by default, which is handled by `rustdoc`. It\nextracts code samples from documentation comments of the library target, and\nthen executes them.\n\nDifferent from normal test targets, each code block compiles to a doctest\nexecutable on the fly with `rustc`. These executables run in parallel in\nseparate processes. The compilation of a code block is in fact a part of test\nfunction controlled by libtest, so some options such as `--jobs` might not\ntake effect. Note that this execution model of doctests is not guaranteed\nand may change in the future; beware of depending on it.\n\nSee the [rustdoc book](https://doc.rust-lang.org/rustdoc/) for more information\non writing doc tests.\n\n### Working directory of tests\n\nThe working directory when running each unit and integration test is set to the\nroot directory of the package the test belongs to.\nSetting the working directory of tests to the package's root directory makes it\npossible for tests to reliably access the package's files using relative paths,\nregardless from where `cargo test` was executed from.\n\nFor documentation tests, the working directory when invoking `rustdoc` is set to\nthe workspace root directory, and is also the directory `rustdoc` uses as the\ncompilation directory of each documentation test.\nThe working directory when running each documentation test is set to the root\ndirectory of the package the test belongs to, and is controlled via `rustdoc`'s\n`--test-run-directory` option.\n\n## OPTIONS\n\n### Test Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-test---no-run\"><a class=\"option-anchor\" href=\"#option-cargo-test---no-run\"><code>--no-run</code></a></dt>\n<dd class=\"option-desc\"><p>Compile, but don’t run tests.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---no-fail-fast\"><a class=\"option-anchor\" href=\"#option-cargo-test---no-fail-fast\"><code>--no-fail-fast</code></a></dt>\n<dd class=\"option-desc\"><p>Run all tests regardless of failure. Without this flag, Cargo will exit\nafter the first executable fails. The Rust test harness will run all tests\nwithin the executable to completion, this flag only applies to the executable\nas a whole.</p>\n</dd>\n\n\n</dl>\n\n### Package Selection\n\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n`--manifest-path` is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n\nThe default members of a workspace can be set explicitly with the\n`workspace.default-members` key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n`--workspace`), and a non-virtual workspace will include only the root crate itself.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-test--p\"><a class=\"option-anchor\" href=\"#option-cargo-test--p\"><code>-p</code> <em>spec</em>…</a></dt>\n<dt class=\"option-term\" id=\"option-cargo-test---package\"><a class=\"option-anchor\" href=\"#option-cargo-test---package\"><code>--package</code> <em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Test only the specified packages. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---workspace\"><a class=\"option-anchor\" href=\"#option-cargo-test---workspace\"><code>--workspace</code></a></dt>\n<dd class=\"option-desc\"><p>Test all members in the workspace.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---all\"><a class=\"option-anchor\" href=\"#option-cargo-test---all\"><code>--all</code></a></dt>\n<dd class=\"option-desc\"><p>Deprecated alias for <code>--workspace</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---exclude\"><a class=\"option-anchor\" href=\"#option-cargo-test---exclude\"><code>--exclude</code> <em>SPEC</em>…</a></dt>\n<dd class=\"option-desc\"><p>Exclude the specified packages. Must be used in conjunction with the\n<code>--workspace</code> flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.</p>\n</dd>\n\n\n</dl>\n\n### Target Selection\n\nWhen no target selection options are given, `cargo test` will build the\nfollowing targets of the selected packages:\n\n- lib --- used to link with binaries, examples, integration tests, and doc tests\n- bins (only if integration tests are built and required features are\n  available)\n- examples --- to ensure they compile\n- lib as a unit test\n- bins as unit tests\n- integration tests\n- doc tests for the lib target\n\nThe default behavior can be changed by setting the `test` flag for the target\nin the manifest settings. Setting examples to `test = true` will build and run\nthe example as a test, replacing the example's `main` function with the\nlibtest harness. If you don't want the `main` function replaced, also include\n`harness = false`, in which case the example will be built and executed as-is.\n\nSetting targets to `test = false` will stop them from being tested by default.\nTarget selection options that take a target by name (such as `--example foo`)\nignore the `test` flag and will always test the given target.\n\nDoc tests for libraries may be disabled by setting `doctest = false` for the\nlibrary in the manifest.\n\nSee [Configuring a target](../reference/cargo-targets.html#configuring-a-target)\nfor more information on per-target settings.\n\nBinary targets are automatically built if there is an integration test or\nbenchmark being selected to test. This allows an integration\ntest to execute the binary to exercise and test its behavior. \nThe `CARGO_BIN_EXE_<name>`\n[environment variable](../reference/environment-variables.html#environment-variables-cargo-sets-for-crates)\nis set when the integration test is built and run so that it can use the\n[`env` macro](https://doc.rust-lang.org/std/macro.env.html) or the \n[`var` function](https://doc.rust-lang.org/std/env/fn.var.html) to locate the\nexecutable.\n\nPassing target selection flags will test only the specified\ntargets. \n\nNote that `--bin`, `--example`, `--test` and `--bench` flags also \nsupport common Unix glob patterns like `*`, `?` and `[]`. However, to avoid your \nshell accidentally expanding glob patterns before Cargo handles them, you must \nuse single quotes or double quotes around each glob pattern.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-test---lib\"><a class=\"option-anchor\" href=\"#option-cargo-test---lib\"><code>--lib</code></a></dt>\n<dd class=\"option-desc\"><p>Test the package’s library.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---bin\"><a class=\"option-anchor\" href=\"#option-cargo-test---bin\"><code>--bin</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Test the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---bins\"><a class=\"option-anchor\" href=\"#option-cargo-test---bins\"><code>--bins</code></a></dt>\n<dd class=\"option-desc\"><p>Test all binary targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---example\"><a class=\"option-anchor\" href=\"#option-cargo-test---example\"><code>--example</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Test the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---examples\"><a class=\"option-anchor\" href=\"#option-cargo-test---examples\"><code>--examples</code></a></dt>\n<dd class=\"option-desc\"><p>Test all example targets.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---test\"><a class=\"option-anchor\" href=\"#option-cargo-test---test\"><code>--test</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Test the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---tests\"><a class=\"option-anchor\" href=\"#option-cargo-test---tests\"><code>--tests</code></a></dt>\n<dd class=\"option-desc\"><p>Test all targets that have the <code>test = true</code> manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the <code>test</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---bench\"><a class=\"option-anchor\" href=\"#option-cargo-test---bench\"><code>--bench</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Test the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---benches\"><a class=\"option-anchor\" href=\"#option-cargo-test---benches\"><code>--benches</code></a></dt>\n<dd class=\"option-desc\"><p>Test all targets that have the <code>bench = true</code>\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the <code>bench</code> flag in the\nmanifest settings for the target.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---all-targets\"><a class=\"option-anchor\" href=\"#option-cargo-test---all-targets\"><code>--all-targets</code></a></dt>\n<dd class=\"option-desc\"><p>Test all targets. This is equivalent to specifying <code>--lib --bins --tests --benches --examples</code>.</p>\n</dd>\n\n\n</dl>\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-test---doc\"><a class=\"option-anchor\" href=\"#option-cargo-test---doc\"><code>--doc</code></a></dt>\n<dd class=\"option-desc\"><p>Test only the library’s documentation. This cannot be mixed with other\ntarget options.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-test--F\"><a class=\"option-anchor\" href=\"#option-cargo-test--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-test---features\"><a class=\"option-anchor\" href=\"#option-cargo-test---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-test---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-test---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Compilation Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-test---target\"><a class=\"option-anchor\" href=\"#option-cargo-test---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Test for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n<code>&lt;arch&gt;&lt;sub&gt;-&lt;vendor&gt;-&lt;sys&gt;-&lt;abi&gt;</code>.</p>\n<p>Possible values:</p>\n<ul>\n<li>Any supported target in <code>rustc --print target-list</code>.</li>\n<li><code>\"host-tuple\"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>\n<li>A path to a custom target specification. See <a href=\"../../rustc/targets/custom.html#custom-target-lookup-path\">Custom Target Lookup Path</a> for more information.</li>\n</ul>\n<p>This may also be specified with the <code>build.target</code> <a href=\"../reference/config.html\">config value</a>.</p>\n<p>Note that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n<a href=\"../reference/build-cache.html\">build cache</a> documentation for more details.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test--r\"><a class=\"option-anchor\" href=\"#option-cargo-test--r\"><code>-r</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-test---release\"><a class=\"option-anchor\" href=\"#option-cargo-test---release\"><code>--release</code></a></dt>\n<dd class=\"option-desc\"><p>Test optimized artifacts with the <code>release</code> profile.\nSee also the <code>--profile</code> option for choosing a specific profile by name.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---profile\"><a class=\"option-anchor\" href=\"#option-cargo-test---profile\"><code>--profile</code> <em>name</em></a></dt>\n<dd class=\"option-desc\"><p>Test with the given profile.\nSee <a href=\"../reference/profiles.html\">the reference</a> for more details on profiles.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---timings\"><a class=\"option-anchor\" href=\"#option-cargo-test---timings\"><code>--timings</code></a></dt>\n<dd class=\"option-desc\"><p>Output information how long each compilation takes, and track concurrency\ninformation over time.</p>\n<p>A file <code>cargo-timing.html</code> will be written to the <code>target/cargo-timings</code>\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine-readable timing data.</p>\n</dd>\n\n\n\n</dl>\n\n### Output Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-test---target-dir\"><a class=\"option-anchor\" href=\"#option-cargo-test---target-dir\"><code>--target-dir</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Directory for all generated artifacts and intermediate files. May also be\nspecified with the <code>CARGO_TARGET_DIR</code> environment variable, or the\n<code>build.target-dir</code> <a href=\"../reference/config.html\">config value</a>.\nDefaults to <code>target</code> in the root of the workspace.</p>\n</dd>\n\n</dl>\n\n### Display Options\n\nBy default the Rust test harness hides output from test execution to keep\nresults readable. Test output can be recovered (e.g., for debugging) by passing\n`--no-capture` to the test binaries:\n\n    cargo test -- --no-capture\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-test--v\"><a class=\"option-anchor\" href=\"#option-cargo-test--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-test---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-test---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test--q\"><a class=\"option-anchor\" href=\"#option-cargo-test--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-test---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-test---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---color\"><a class=\"option-anchor\" href=\"#option-cargo-test---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---message-format\"><a class=\"option-anchor\" href=\"#option-cargo-test---message-format\"><code>--message-format</code> <em>fmt</em></a></dt>\n<dd class=\"option-desc\"><p>The output format for diagnostic messages. Can be specified multiple times\nand consists of comma-separated values. Valid values:</p>\n<ul>\n<li><code>human</code> (default): Display in a human-readable text format. Conflicts with\n<code>short</code> and <code>json</code>.</li>\n<li><code>short</code>: Emit shorter, human-readable text messages. Conflicts with <code>human</code>\nand <code>json</code>.</li>\n<li><code>json</code>: Emit JSON messages to stdout. See\n<a href=\"../reference/external-tools.html#json-messages\">the reference</a>\nfor more details. Conflicts with <code>human</code> and <code>short</code>.</li>\n<li><code>json-diagnostic-short</code>: Ensure the <code>rendered</code> field of JSON messages contains\nthe “short” rendering from rustc. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-diagnostic-rendered-ansi</code>: Ensure the <code>rendered</code> field of JSON messages\ncontains embedded ANSI color codes for respecting rustc’s default color\nscheme. Cannot be used with <code>human</code> or <code>short</code>.</li>\n<li><code>json-render-diagnostics</code>: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo’s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with <code>human</code> or <code>short</code>.</li>\n</ul>\n</dd>\n\n\n</dl>\n\n### Manifest Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-test---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-test---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-test---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---locked\"><a class=\"option-anchor\" href=\"#option-cargo-test---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---offline\"><a class=\"option-anchor\" href=\"#option-cargo-test---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-test---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-test-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-test-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test---config\"><a class=\"option-anchor\" href=\"#option-cargo-test---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test--C\"><a class=\"option-anchor\" href=\"#option-cargo-test--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test--h\"><a class=\"option-anchor\" href=\"#option-cargo-test--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-test---help\"><a class=\"option-anchor\" href=\"#option-cargo-test---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-test--Z\"><a class=\"option-anchor\" href=\"#option-cargo-test--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n### Miscellaneous Options\n\nThe `--jobs` argument affects the building of the test executable but does not\naffect how many threads are used when running the tests. The Rust test harness\nincludes an option to control the number of threads used:\n\n    cargo test -j 2 -- --test-threads=2\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-test--j\"><a class=\"option-anchor\" href=\"#option-cargo-test--j\"><code>-j</code> <em>N</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-test---jobs\"><a class=\"option-anchor\" href=\"#option-cargo-test---jobs\"><code>--jobs</code> <em>N</em></a></dt>\n<dd class=\"option-desc\"><p>Number of parallel jobs to run. May also be specified with the\n<code>build.jobs</code> <a href=\"../reference/config.html\">config value</a>. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string <code>default</code> is provided, it sets the value back to defaults.\nShould not be 0.</p>\n</dd>\n\n<dt class=\"option-term\" id=\"option-cargo-test---future-incompat-report\"><a class=\"option-anchor\" href=\"#option-cargo-test---future-incompat-report\"><code>--future-incompat-report</code></a></dt>\n<dd class=\"option-desc\"><p>Displays a future-incompat report for any future-incompatible warnings\nproduced during execution of this command</p>\n<p>See <a href=\"cargo-report.html\">cargo-report(1)</a></p>\n</dd>\n\n\n</dl>\n\nWhile `cargo test` involves compilation, it does not provide a `--keep-going`\nflag. Use `--no-fail-fast` to run as many tests as possible without stopping at\nthe first failure. To \"compile\" as many tests as possible, use `--tests` to\nbuild test binaries separately. For example:\n\n    cargo build --tests --keep-going\n    cargo test --tests --no-fail-fast\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Execute all the unit and integration tests of the current package:\n\n       cargo test\n\n2. Run only tests whose names match against a filter string:\n\n       cargo test name_filter\n\n3. Run only a specific test within a specific integration test:\n\n       cargo test --test int_test_name -- modname::test_name\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-bench(1)](cargo-bench.html), [types of tests](../reference/cargo-targets.html#tests), [how to write tests](https://doc.rust-lang.org/rustc/tests/index.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-tree.md",
    "content": "# cargo-tree(1)\n## NAME\n\ncargo-tree --- Display a tree visualization of a dependency graph\n\n## SYNOPSIS\n\n`cargo tree` [_options_]\n\n## DESCRIPTION\n\nThis command will display a tree of dependencies to the terminal. An example\nof a simple project that depends on the \"rand\" package:\n\n```\nmyproject v0.1.0 (/myproject)\n└── rand v0.7.3\n    ├── getrandom v0.1.14\n    │   ├── cfg-if v0.1.10\n    │   └── libc v0.2.68\n    ├── libc v0.2.68 (*)\n    ├── rand_chacha v0.2.2\n    │   ├── ppv-lite86 v0.2.6\n    │   └── rand_core v0.5.1\n    │       └── getrandom v0.1.14 (*)\n    └── rand_core v0.5.1 (*)\n[build-dependencies]\n└── cc v1.0.50\n```\n\nPackages marked with `(*)` have been \"de-duplicated\". The dependencies for the\npackage have already been shown elsewhere in the graph, and so are not\nrepeated. Use the `--no-dedupe` option to repeat the duplicates.\n\nThe `-e` flag can be used to select the dependency kinds to display. The\n\"features\" kind changes the output to display the features enabled by\neach dependency. For example, `cargo tree -e features`:\n\n```\nmyproject v0.1.0 (/myproject)\n└── log feature \"serde\"\n    └── log v0.4.8\n        ├── serde v1.0.106\n        └── cfg-if feature \"default\"\n            └── cfg-if v0.1.10\n```\n\nIn this tree, `myproject` depends on `log` with the `serde` feature. `log` in\nturn depends on `cfg-if` with \"default\" features. When using `-e features` it\ncan be helpful to use `-i` flag to show how the features flow into a package.\nSee the examples below for more detail.\n\n### Feature Unification\n\nThis command shows a graph much closer to a feature-unified graph Cargo will\nbuild, rather than what you list in `Cargo.toml`. For instance, if you specify\nthe same dependency in both `[dependencies]` and `[dev-dependencies]` but with\ndifferent features on. This command may merge all features and show a `(*)` on\none of the dependency to indicate the duplicate.\n\nAs a result, for a mostly equivalent overview of what `cargo build` does,\n`cargo tree -e normal,build` is pretty close; for a mostly equivalent overview\nof what `cargo test` does, `cargo tree` is pretty close. However, it doesn't\nguarantee the exact equivalence to what Cargo is going to build, since a\ncompilation is complex and depends on lots of different factors.\n\nTo learn more about feature unification, check out this\n[dedicated section](../reference/features.html#feature-unification).\n\n## OPTIONS\n\n### Tree Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-tree--i\"><a class=\"option-anchor\" href=\"#option-cargo-tree--i\"><code>-i</code> <em>spec</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-tree---invert\"><a class=\"option-anchor\" href=\"#option-cargo-tree---invert\"><code>--invert</code> <em>spec</em></a></dt>\n<dd class=\"option-desc\"><p>Show the reverse dependencies for the given package. This flag will invert\nthe tree and display the packages that depend on the given package.</p>\n<p>Note that in a workspace, by default it will only display the package’s\nreverse dependencies inside the tree of the workspace member in the current\ndirectory. The <code>--workspace</code> flag can be used to extend it so that it will\nshow the package’s reverse dependencies across the entire workspace. The <code>-p</code>\nflag can be used to display the package’s reverse dependencies only with the\nsubtree of the package given to <code>-p</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---prune\"><a class=\"option-anchor\" href=\"#option-cargo-tree---prune\"><code>--prune</code> <em>spec</em></a></dt>\n<dd class=\"option-desc\"><p>Prune the given package from the display of the dependency tree.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---depth\"><a class=\"option-anchor\" href=\"#option-cargo-tree---depth\"><code>--depth</code> <em>depth</em></a></dt>\n<dd class=\"option-desc\"><p>Maximum display depth of the dependency tree. A depth of 1 displays the direct\ndependencies, for example.</p>\n<p>If the given value is <code>workspace</code>, only shows the dependencies that are member\nof the current workspace, instead.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---no-dedupe\"><a class=\"option-anchor\" href=\"#option-cargo-tree---no-dedupe\"><code>--no-dedupe</code></a></dt>\n<dd class=\"option-desc\"><p>Do not de-duplicate repeated dependencies. Usually, when a package has already\ndisplayed its dependencies, further occurrences will not re-display its\ndependencies, and will include a <code>(*)</code> to indicate it has already been shown.\nThis flag will cause those duplicates to be repeated.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree--d\"><a class=\"option-anchor\" href=\"#option-cargo-tree--d\"><code>-d</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-tree---duplicates\"><a class=\"option-anchor\" href=\"#option-cargo-tree---duplicates\"><code>--duplicates</code></a></dt>\n<dd class=\"option-desc\"><p>Show only dependencies which come in multiple versions (implies <code>--invert</code>).\nWhen used with the <code>-p</code> flag, only shows duplicates within the subtree of the\ngiven package.</p>\n<p>It can be beneficial for build times and executable sizes to avoid building\nthat same package multiple times. This flag can help identify the offending\npackages. You can then investigate if the package that depends on the\nduplicate with the older version can be updated to the newer version so that\nonly one instance is built.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree--e\"><a class=\"option-anchor\" href=\"#option-cargo-tree--e\"><code>-e</code> <em>kinds</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-tree---edges\"><a class=\"option-anchor\" href=\"#option-cargo-tree---edges\"><code>--edges</code> <em>kinds</em></a></dt>\n<dd class=\"option-desc\"><p>The dependency kinds to display. Takes a comma separated list of values:</p>\n<ul>\n<li><code>all</code> — Show all edge kinds.</li>\n<li><code>normal</code> — Show normal dependencies.</li>\n<li><code>build</code> — Show build dependencies.</li>\n<li><code>dev</code> — Show development dependencies.</li>\n<li><code>features</code> — Show features enabled by each dependency. If this is the only\nkind given, then it will automatically include the other dependency kinds.</li>\n<li><code>no-normal</code> — Do not include normal dependencies.</li>\n<li><code>no-build</code> — Do not include build dependencies.</li>\n<li><code>no-dev</code> — Do not include development dependencies.</li>\n<li><code>no-proc-macro</code> — Do not include procedural macro dependencies.</li>\n</ul>\n<p>The <code>normal</code>, <code>build</code>, <code>dev</code>, and <code>all</code> dependency kinds cannot be mixed with\n<code>no-normal</code>, <code>no-build</code>, or <code>no-dev</code> dependency kinds.</p>\n<p>The default is <code>normal,build,dev</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---target\"><a class=\"option-anchor\" href=\"#option-cargo-tree---target\"><code>--target</code> <em>triple</em></a></dt>\n<dd class=\"option-desc\"><p>Filter dependencies matching the given <a href=\"../appendix/glossary.html#target\">target triple</a>.\nThe default is the host platform. Use the value <code>all</code> to include <em>all</em> targets.</p>\n</dd>\n\n\n</dl>\n\n### Tree Formatting Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-tree---charset\"><a class=\"option-anchor\" href=\"#option-cargo-tree---charset\"><code>--charset</code> <em>charset</em></a></dt>\n<dd class=\"option-desc\"><p>Chooses the character set to use for the tree. Valid values are “utf8” or\n“ascii”. When unspecified, cargo will auto-select a value.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree--f\"><a class=\"option-anchor\" href=\"#option-cargo-tree--f\"><code>-f</code> <em>format</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-tree---format\"><a class=\"option-anchor\" href=\"#option-cargo-tree---format\"><code>--format</code> <em>format</em></a></dt>\n<dd class=\"option-desc\"><p>Set the format string for each package. The default is “{p}”.</p>\n<p>This is an arbitrary string which will be used to display each package. The following\nstrings will be replaced with the corresponding value:</p>\n<ul>\n<li><code>{p}</code>, <code>{package}</code> — The package name.</li>\n<li><code>{l}</code>, <code>{license}</code> — The package license.</li>\n<li><code>{r}</code>, <code>{repository}</code> — The package repository URL.</li>\n<li><code>{f}</code>, <code>{features}</code> — Comma-separated list of package features that are enabled.</li>\n<li><code>{lib}</code> — The name, as used in a <code>use</code> statement, of the package’s library.</li>\n</ul>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---prefix\"><a class=\"option-anchor\" href=\"#option-cargo-tree---prefix\"><code>--prefix</code> <em>prefix</em></a></dt>\n<dd class=\"option-desc\"><p>Sets how each line is displayed. The <em>prefix</em> value can be one of:</p>\n<ul>\n<li><code>indent</code> (default) — Shows each line indented as a tree.</li>\n<li><code>depth</code> — Show as a list, with the numeric depth printed before each entry.</li>\n<li><code>none</code> — Show as a flat list.</li>\n</ul>\n</dd>\n\n\n</dl>\n\n### Package Selection\n\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n`--manifest-path` is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n\nThe default members of a workspace can be set explicitly with the\n`workspace.default-members` key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n`--workspace`), and a non-virtual workspace will include only the root crate itself.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-tree--p\"><a class=\"option-anchor\" href=\"#option-cargo-tree--p\"><code>-p</code> <em>spec</em>…</a></dt>\n<dt class=\"option-term\" id=\"option-cargo-tree---package\"><a class=\"option-anchor\" href=\"#option-cargo-tree---package\"><code>--package</code> <em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Display only the specified packages. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---workspace\"><a class=\"option-anchor\" href=\"#option-cargo-tree---workspace\"><code>--workspace</code></a></dt>\n<dd class=\"option-desc\"><p>Display all members in the workspace.</p>\n</dd>\n\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---exclude\"><a class=\"option-anchor\" href=\"#option-cargo-tree---exclude\"><code>--exclude</code> <em>SPEC</em>…</a></dt>\n<dd class=\"option-desc\"><p>Exclude the specified packages. Must be used in conjunction with the\n<code>--workspace</code> flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like <code>*</code>, <code>?</code> and <code>[]</code>. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.</p>\n</dd>\n\n\n</dl>\n\n### Manifest Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-tree---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-tree---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---locked\"><a class=\"option-anchor\" href=\"#option-cargo-tree---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---offline\"><a class=\"option-anchor\" href=\"#option-cargo-tree---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-tree---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n</dl>\n\n### Feature Selection\n\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the `default` feature is activated for every\nselected package.\n\nSee [the features documentation](../reference/features.html#command-line-feature-options)\nfor more details.\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-tree--F\"><a class=\"option-anchor\" href=\"#option-cargo-tree--F\"><code>-F</code> <em>features</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-tree---features\"><a class=\"option-anchor\" href=\"#option-cargo-tree---features\"><code>--features</code> <em>features</em></a></dt>\n<dd class=\"option-desc\"><p>Space or comma separated list of features to activate. Features of workspace\nmembers may be enabled with <code>package-name/feature-name</code> syntax. This flag may\nbe specified multiple times, which enables all specified features.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---all-features\"><a class=\"option-anchor\" href=\"#option-cargo-tree---all-features\"><code>--all-features</code></a></dt>\n<dd class=\"option-desc\"><p>Activate all available features of all selected packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---no-default-features\"><a class=\"option-anchor\" href=\"#option-cargo-tree---no-default-features\"><code>--no-default-features</code></a></dt>\n<dd class=\"option-desc\"><p>Do not activate the <code>default</code> feature of the selected packages.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-tree--v\"><a class=\"option-anchor\" href=\"#option-cargo-tree--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-tree---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-tree---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree--q\"><a class=\"option-anchor\" href=\"#option-cargo-tree--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-tree---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-tree---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---color\"><a class=\"option-anchor\" href=\"#option-cargo-tree---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-tree-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-tree-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree---config\"><a class=\"option-anchor\" href=\"#option-cargo-tree---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree--C\"><a class=\"option-anchor\" href=\"#option-cargo-tree--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree--h\"><a class=\"option-anchor\" href=\"#option-cargo-tree--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-tree---help\"><a class=\"option-anchor\" href=\"#option-cargo-tree---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-tree--Z\"><a class=\"option-anchor\" href=\"#option-cargo-tree--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Display the tree for the package in the current directory:\n\n       cargo tree\n\n2. Display all the packages that depend on the `syn` package:\n\n       cargo tree -i syn\n\n3. Show the features enabled on each package:\n\n       cargo tree --format \"{p} {f}\"\n\n4. Show all packages that are built multiple times. This can happen if multiple\n   semver-incompatible versions appear in the tree (like 1.0.0 and 2.0.0).\n\n       cargo tree -d\n\n5. Explain why features are enabled for the `syn` package:\n\n       cargo tree -e features -i syn\n\n   The `-e features` flag is used to show features. The `-i` flag is used to\n   invert the graph so that it displays the packages that depend on `syn`. An\n   example of what this would display:\n\n   ```\n   syn v1.0.17\n   ├── syn feature \"clone-impls\"\n   │   └── syn feature \"default\"\n   │       └── rustversion v1.0.2\n   │           └── rustversion feature \"default\"\n   │               └── myproject v0.1.0 (/myproject)\n   │                   └── myproject feature \"default\" (command-line)\n   ├── syn feature \"default\" (*)\n   ├── syn feature \"derive\"\n   │   └── syn feature \"default\" (*)\n   ├── syn feature \"full\"\n   │   └── rustversion v1.0.2 (*)\n   ├── syn feature \"parsing\"\n   │   └── syn feature \"default\" (*)\n   ├── syn feature \"printing\"\n   │   └── syn feature \"default\" (*)\n   ├── syn feature \"proc-macro\"\n   │   └── syn feature \"default\" (*)\n   └── syn feature \"quote\"\n       ├── syn feature \"printing\" (*)\n       └── syn feature \"proc-macro\" (*)\n   ```\n\n   To read this graph, you can follow the chain for each feature from the root\n   to see why it is included. For example, the \"full\" feature is added by the\n   `rustversion` crate which is included from `myproject` (with the default\n   features), and `myproject` is the package selected on the command-line. All\n   of the other `syn` features are added by the \"default\" feature (\"quote\" is\n   added by \"printing\" and \"proc-macro\", both of which are default features).\n\n   If you're having difficulty cross-referencing the de-duplicated `(*)`\n   entries, try with the `--no-dedupe` flag to get the full output.\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-metadata(1)](cargo-metadata.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-uninstall.md",
    "content": "# cargo-uninstall(1)\n\n## NAME\n\ncargo-uninstall --- Remove a Rust binary\n\n## SYNOPSIS\n\n`cargo uninstall` [_options_] [_spec_...]\n\n## DESCRIPTION\n\nThis command removes a package installed with [cargo-install(1)](cargo-install.html). The _spec_\nargument is a package ID specification of the package to remove (see\n[cargo-pkgid(1)](cargo-pkgid.html)).\n\nBy default all binaries are removed for a crate but the `--bin` and\n`--example` flags can be used to only remove particular binaries.\n\nThe installation root is determined, in order of precedence:\n\n- `--root` option\n- `CARGO_INSTALL_ROOT` environment variable\n- `install.root` Cargo [config value](../reference/config.html)\n- `CARGO_HOME` environment variable\n- `$HOME/.cargo`\n\n## OPTIONS\n\n### Uninstall Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-uninstall--p\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall--p\"><code>-p</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-uninstall---package\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall---package\"><code>--package</code> <em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Package to uninstall.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-uninstall---bin\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall---bin\"><code>--bin</code> <em>name</em>…</a></dt>\n<dd class=\"option-desc\"><p>Only uninstall the binary <em>name</em>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-uninstall---root\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall---root\"><code>--root</code> <em>dir</em></a></dt>\n<dd class=\"option-desc\"><p>Directory to uninstall packages from.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-uninstall--v\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-uninstall---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-uninstall--q\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-uninstall---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-uninstall---color\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-uninstall-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-uninstall---config\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-uninstall--C\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-uninstall--h\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-uninstall---help\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-uninstall--Z\"><a class=\"option-anchor\" href=\"#option-cargo-uninstall--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Uninstall a previously installed package.\n\n       cargo uninstall ripgrep\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-install(1)](cargo-install.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-update.md",
    "content": "# cargo-update(1)\n\n## NAME\n\ncargo-update --- Update dependencies as recorded in the local lock file\n\n## SYNOPSIS\n\n`cargo update` [_options_] _spec_\n\n## DESCRIPTION\n\nThis command will update dependencies in the `Cargo.lock` file to the latest\nversion. If the `Cargo.lock` file does not exist, it will be created with the\nlatest available versions.\n\n## OPTIONS\n\n### Update Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-update-spec…\"><a class=\"option-anchor\" href=\"#option-cargo-update-spec…\"><em>spec</em>…</a></dt>\n<dd class=\"option-desc\"><p>Update only the specified packages. This flag may be specified\nmultiple times. See <a href=\"cargo-pkgid.html\">cargo-pkgid(1)</a> for the SPEC format.</p>\n<p>If packages are specified with <em>spec</em>, then a conservative update of\nthe lockfile will be performed. This means that only the dependency specified\nby SPEC will be updated. Its transitive dependencies will be updated only if\nSPEC cannot be updated without updating dependencies.  All other dependencies\nwill remain locked at their currently recorded versions.</p>\n<p>If <em>spec</em> is not specified, all dependencies are updated.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update---recursive\"><a class=\"option-anchor\" href=\"#option-cargo-update---recursive\"><code>--recursive</code></a></dt>\n<dd class=\"option-desc\"><p>When used with <em>spec</em>, dependencies of <em>spec</em> are forced to update as well.\nCannot be used with <code>--precise</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update---precise\"><a class=\"option-anchor\" href=\"#option-cargo-update---precise\"><code>--precise</code> <em>precise</em></a></dt>\n<dd class=\"option-desc\"><p>When used with <em>spec</em>, allows you to specify a specific version number to set\nthe package to. If the package comes from a git repository, this can be a git\nrevision (such as a SHA hash or tag).</p>\n<p>While not recommended, you can specify a yanked version of a package.\nWhen possible, try other non-yanked SemVer-compatible versions or seek help\nfrom the maintainers of the package.</p>\n<p>A compatible <code>pre-release</code> version can also be specified even when the version\nrequirement in <code>Cargo.toml</code> doesn’t contain any pre-release identifier (nightly only).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update---breaking\"><a class=\"option-anchor\" href=\"#option-cargo-update---breaking\"><code>--breaking</code> <em>directory</em></a></dt>\n<dd class=\"option-desc\"><p>Update <em>spec</em> to latest SemVer-breaking version.</p>\n<p>Version requirements will be modified to allow this update.</p>\n<p>This only applies to dependencies when</p>\n<ul>\n<li>The package is a dependency of a workspace member</li>\n<li>The dependency is not renamed</li>\n<li>A SemVer-incompatible version is available</li>\n<li>The “SemVer operator” is used (<code>^</code> which is the default)</li>\n</ul>\n<p>This option is unstable and available only on the\n<a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly channel</a>\nand requires the <code>-Z unstable-options</code> flag to enable.\nSee <a href=\"https://github.com/rust-lang/cargo/issues/12425\">https://github.com/rust-lang/cargo/issues/12425</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update--w\"><a class=\"option-anchor\" href=\"#option-cargo-update--w\"><code>-w</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-update---workspace\"><a class=\"option-anchor\" href=\"#option-cargo-update---workspace\"><code>--workspace</code></a></dt>\n<dd class=\"option-desc\"><p>Attempt to update only packages defined in the workspace. Other packages\nare updated only if they don’t already exist in the lockfile. This\noption is useful for updating <code>Cargo.lock</code> after you’ve changed version\nnumbers in <code>Cargo.toml</code>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update---dry-run\"><a class=\"option-anchor\" href=\"#option-cargo-update---dry-run\"><code>--dry-run</code></a></dt>\n<dd class=\"option-desc\"><p>Displays what would be updated, but doesn’t actually write the lockfile.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo-update--v\"><a class=\"option-anchor\" href=\"#option-cargo-update--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-update---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-update---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update--q\"><a class=\"option-anchor\" href=\"#option-cargo-update--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-update---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-update---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update---color\"><a class=\"option-anchor\" href=\"#option-cargo-update---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n</dl>\n\n### Manifest Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-update---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-update---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update---ignore-rust-version\"><a class=\"option-anchor\" href=\"#option-cargo-update---ignore-rust-version\"><code>--ignore-rust-version</code></a></dt>\n<dd class=\"option-desc\"><p>Ignore <code>rust-version</code> specification in packages.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update---locked\"><a class=\"option-anchor\" href=\"#option-cargo-update---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update---offline\"><a class=\"option-anchor\" href=\"#option-cargo-update---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-update---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-update-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-update-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update---config\"><a class=\"option-anchor\" href=\"#option-cargo-update---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update--C\"><a class=\"option-anchor\" href=\"#option-cargo-update--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update--h\"><a class=\"option-anchor\" href=\"#option-cargo-update--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-update---help\"><a class=\"option-anchor\" href=\"#option-cargo-update---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-update--Z\"><a class=\"option-anchor\" href=\"#option-cargo-update--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Update all dependencies in the lockfile:\n\n       cargo update\n\n2. Update only specific dependencies:\n\n       cargo update foo bar\n\n3. Set a specific dependency to a specific version:\n\n       cargo update foo --precise 1.2.3\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-generate-lockfile(1)](cargo-generate-lockfile.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-vendor.md",
    "content": "# cargo-vendor(1)\n\n## NAME\n\ncargo-vendor --- Vendor all dependencies locally\n\n## SYNOPSIS\n\n`cargo vendor` [_options_] [_path_]\n\n## DESCRIPTION\n\nThis cargo subcommand will vendor all crates.io and git dependencies for a\nproject into the specified directory at `<path>`. After this command completes\nthe vendor directory specified by `<path>` will contain all remote sources from\ndependencies specified. Additional manifests beyond the default one can be\nspecified with the `-s` option.\n\nThe configuration necessary to use the vendored sources would be printed to\nstdout after `cargo vendor` completes the vendoring process.\nYou will need to add or redirect it to your Cargo configuration file,\nwhich is usually `.cargo/config.toml` locally for the current package.\n\nCargo treats vendored sources as read-only as it does to registry and git sources.\nIf you intend to modify a crate from a remote source,\nuse `[patch]` or a `path` dependency pointing to a local copy of that crate.\nCargo will then correctly handle the crate on incremental rebuilds,\nas it knows that it is no longer a read-only dependency.\n\n## OPTIONS\n\n### Vendor Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-vendor--s\"><a class=\"option-anchor\" href=\"#option-cargo-vendor--s\"><code>-s</code> <em>manifest</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-vendor---sync\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---sync\"><code>--sync</code> <em>manifest</em></a></dt>\n<dd class=\"option-desc\"><p>Specify an extra <code>Cargo.toml</code> manifest to workspaces which should also be\nvendored and synced to the output. May be specified multiple times.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-vendor---no-delete\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---no-delete\"><code>--no-delete</code></a></dt>\n<dd class=\"option-desc\"><p>Don’t delete the “vendor” directory when vendoring, but rather keep all\nexisting contents of the vendor directory</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-vendor---respect-source-config\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---respect-source-config\"><code>--respect-source-config</code></a></dt>\n<dd class=\"option-desc\"><p>Instead of ignoring <code>[source]</code> configuration by default in <code>.cargo/config.toml</code>\nread it and use it when downloading crates from crates.io, for example</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-vendor---versioned-dirs\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---versioned-dirs\"><code>--versioned-dirs</code></a></dt>\n<dd class=\"option-desc\"><p>Normally versions are only added to disambiguate multiple versions of the\nsame package. This option causes all directories in the “vendor” directory\nto be versioned, which makes it easier to track the history of vendored\npackages over time, and can help with the performance of re-vendoring when\nonly a subset of the packages have changed.</p>\n</dd>\n\n\n</dl>\n\n### Manifest Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-vendor---manifest-path\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---manifest-path\"><code>--manifest-path</code> <em>path</em></a></dt>\n<dd class=\"option-desc\"><p>Path to the <code>Cargo.toml</code> file. By default, Cargo searches for the\n<code>Cargo.toml</code> file in the current directory or any parent directory.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-vendor---locked\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-vendor---offline\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-vendor---frozen\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n\n\n</dl>\n\n### Display Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-vendor--v\"><a class=\"option-anchor\" href=\"#option-cargo-vendor--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-vendor---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-vendor--q\"><a class=\"option-anchor\" href=\"#option-cargo-vendor--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-vendor---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-vendor---color\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-vendor-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-vendor-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-vendor---config\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-vendor--C\"><a class=\"option-anchor\" href=\"#option-cargo-vendor--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-vendor--h\"><a class=\"option-anchor\" href=\"#option-cargo-vendor--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-vendor---help\"><a class=\"option-anchor\" href=\"#option-cargo-vendor---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-vendor--Z\"><a class=\"option-anchor\" href=\"#option-cargo-vendor--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Vendor all dependencies into a local \"vendor\" folder\n\n       cargo vendor\n\n2. Vendor all dependencies into a local \"third-party/vendor\" folder\n\n       cargo vendor third-party/vendor\n\n3. Vendor the current workspace as well as another to \"vendor\"\n\n       cargo vendor -s ../path/to/Cargo.toml\n\n4. Vendor and redirect the necessary vendor configs to a config file.\n\n       cargo vendor > path/to/my/cargo/config.toml\n\n## SEE ALSO\n[cargo(1)](cargo.html)\n\n"
  },
  {
    "path": "src/doc/src/commands/cargo-version.md",
    "content": "# cargo-version(1)\n\n## NAME\n\ncargo-version --- Show version information\n\n## SYNOPSIS\n\n`cargo version` [_options_]\n\n## DESCRIPTION\n\nDisplays the version of Cargo.\n\n## OPTIONS\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-version--v\"><a class=\"option-anchor\" href=\"#option-cargo-version--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-version---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-version---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Display additional version information.</p>\n</dd>\n\n\n</dl>\n\n## EXAMPLES\n\n1. Display the version:\n\n       cargo version\n\n2. The version is also available via flags:\n\n       cargo --version\n       cargo -V\n\n3. Display extra version information:\n\n       cargo -Vv\n\n## SEE ALSO\n[cargo(1)](cargo.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo-yank.md",
    "content": "# cargo-yank(1)\n\n## NAME\n\ncargo-yank --- Remove a pushed crate from the index\n\n## SYNOPSIS\n\n`cargo yank` [_options_] _crate_@_version_\\\n`cargo yank` [_options_] `--version` _version_ [_crate_]\n\n## DESCRIPTION\n\nThe yank command removes a previously published crate's version from the\nserver's index. This command does not delete any data, and the crate will\nstill be available for download via the registry's download link.\n\nCargo will not use a yanked version for any new project or checkout without a\npre-existing lockfile, and will generate an error if there are no longer\nany compatible versions for your crate.\n\nThis command requires you to be authenticated with either the `--token` option\nor using [cargo-login(1)](cargo-login.html).\n\nIf the crate name is not specified, it will use the package name from the\ncurrent directory.\n\n### How yank works\n\nFor example, the `foo` crate published version `1.5.0` and another crate `bar`\ndeclared a dependency on version `foo = \"1.5\"`. Now `foo` releases a new, but\nnot semver compatible, version `2.0.0`, and finds a critical issue with `1.5.0`.\nIf `1.5.0` is yanked, no new project or checkout without an existing lockfile\nwill be able to use crate `bar` as it relies on `1.5`.\n\nIn this case, the maintainers of `foo` should first publish a semver compatible\nversion such as `1.5.1` prior to yanking `1.5.0` so that `bar` and all projects\nthat depend on `bar` will continue to work.\n\nAs another example, consider a crate `bar` with published versions `1.5.0`,\n`1.5.1`, `1.5.2`, `2.0.0` and `3.0.0`. The following table identifies the\nversions cargo could use in the absence of a lockfile for different SemVer\nrequirements, following a given release being yanked:\n\n| Yanked Version / SemVer requirement | `bar = \"1.5.0\"`                         | `bar = \"=1.5.0\"` | `bar = \"2.0.0\"`  |\n|-------------------------------------|-----------------------------------------|------------------|------------------|\n| `1.5.0`                             | Use either `1.5.1` or `1.5.2`           | **Return Error** | Use `2.0.0`      |\n| `1.5.1`                             | Use either `1.5.0` or `1.5.2`           | Use `1.5.0`      | Use `2.0.0`      |\n| `2.0.0`                             | Use either `1.5.0`, `1.5.1` or `1.5.2`  | Use `1.5.0`      | **Return Error** |\n\n### When to yank\n\nCrates should only be yanked in exceptional circumstances, for example, an\naccidental publish, unintentional SemVer breakages, or a significantly\nbroken and unusable crate. In the case of security vulnerabilities, [RustSec]\nis typically a less disruptive mechanism to inform users and encourage them\nto upgrade, and avoids the possibility of significant downstream disruption\nirrespective of susceptibility to the vulnerability in question.\n\nA common workflow is to yank a crate having already published a semver\ncompatible version, to reduce the probability of preventing dependent\ncrates from compiling.\n\nWhen addressing copyright, licensing, or personal data issues with a published\ncrate, simply yanking it may not suffice. In such cases, contact the maintainers\nof the registry you used. For crates.io, refer to their [policies] and contact\nthem at <help@crates.io>.\n\nIf credentials have been leaked, the recommended course of action is to revoke\nthem immediately. Once a crate has been published, it is impossible to determine\nif the leaked credentials have been copied. Yanking only prevents Cargo from\nselecting this version when resolving dependencies by default. Existing lock\nfiles or direct downloads are not affected, so yanking cannot stop further\nspreading of the leaked credentials.\n\n[RustSec]: https://rustsec.org/\n[policies]: https://crates.io/policies\n\n## OPTIONS\n\n### Yank Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-yank---vers\"><a class=\"option-anchor\" href=\"#option-cargo-yank---vers\"><code>--vers</code> <em>version</em></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-yank---version\"><a class=\"option-anchor\" href=\"#option-cargo-yank---version\"><code>--version</code> <em>version</em></a></dt>\n<dd class=\"option-desc\"><p>The version to yank or un-yank.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-yank---undo\"><a class=\"option-anchor\" href=\"#option-cargo-yank---undo\"><code>--undo</code></a></dt>\n<dd class=\"option-desc\"><p>Undo a yank, putting a version back into the index.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-yank---token\"><a class=\"option-anchor\" href=\"#option-cargo-yank---token\"><code>--token</code> <em>token</em></a></dt>\n<dd class=\"option-desc\"><p>API token to use when authenticating. This overrides the token stored in\nthe credentials file (which is created by <a href=\"cargo-login.html\">cargo-login(1)</a>).</p>\n<p><a href=\"../reference/config.html\">Cargo config</a> environment variables can be\nused to override the tokens stored in the credentials file. The token for\ncrates.io may be specified with the <code>CARGO_REGISTRY_TOKEN</code> environment\nvariable. Tokens for other registries may be specified with environment\nvariables of the form <code>CARGO_REGISTRIES_NAME_TOKEN</code> where <code>NAME</code> is the name\nof the registry in all capital letters.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-yank---index\"><a class=\"option-anchor\" href=\"#option-cargo-yank---index\"><code>--index</code> <em>index</em></a></dt>\n<dd class=\"option-desc\"><p>The URL of the registry index to use.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-yank---registry\"><a class=\"option-anchor\" href=\"#option-cargo-yank---registry\"><code>--registry</code> <em>registry</em></a></dt>\n<dd class=\"option-desc\"><p>Name of the registry to use. Registry names are defined in <a href=\"../reference/config.html\">Cargo config\nfiles</a>. If not specified, the default registry is used,\nwhich is defined by the <code>registry.default</code> config key which defaults to\n<code>crates-io</code>.</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-yank--v\"><a class=\"option-anchor\" href=\"#option-cargo-yank--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-yank---verbose\"><a class=\"option-anchor\" href=\"#option-cargo-yank---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-yank--q\"><a class=\"option-anchor\" href=\"#option-cargo-yank--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-yank---quiet\"><a class=\"option-anchor\" href=\"#option-cargo-yank---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-yank---color\"><a class=\"option-anchor\" href=\"#option-cargo-yank---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-yank-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-yank-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-yank---config\"><a class=\"option-anchor\" href=\"#option-cargo-yank---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-yank--C\"><a class=\"option-anchor\" href=\"#option-cargo-yank--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-yank--h\"><a class=\"option-anchor\" href=\"#option-cargo-yank--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo-yank---help\"><a class=\"option-anchor\" href=\"#option-cargo-yank---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo-yank--Z\"><a class=\"option-anchor\" href=\"#option-cargo-yank--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## EXAMPLES\n\n1. Yank a crate from the index:\n\n       cargo yank foo@1.0.7\n\n## SEE ALSO\n[cargo(1)](cargo.html), [cargo-login(1)](cargo-login.html), [cargo-publish(1)](cargo-publish.html)\n"
  },
  {
    "path": "src/doc/src/commands/cargo.md",
    "content": "# cargo(1)\n\n## NAME\n\ncargo --- The Rust package manager\n\n## SYNOPSIS\n\n`cargo` [_options_] _command_ [_args_]\\\n`cargo` [_options_] `--version`\\\n`cargo` [_options_] `--list`\\\n`cargo` [_options_] `--help`\\\n`cargo` [_options_] `--explain` _code_\n\n## DESCRIPTION\n\nThis program is a package manager and build tool for the Rust language,\navailable at <https://rust-lang.org>.\n\n_command_ may be one of:\n- built-in commands, see below\n- [aliases]\n- [external tools]\n\n[aliases]: ../reference/config.html#alias\n[external tools]: ../reference/external-tools.html#custom-subcommands\n\n## COMMANDS\n\n### Build Commands\n\n[cargo-bench(1)](cargo-bench.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Execute benchmarks of a package.\n\n[cargo-build(1)](cargo-build.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Compile a package.\n\n[cargo-check(1)](cargo-check.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Check a local package and all of its dependencies for errors.\n\n[cargo-clean(1)](cargo-clean.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Remove artifacts that Cargo has generated in the past.\n\n[cargo-doc(1)](cargo-doc.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Build a package's documentation.\n\n[cargo-fetch(1)](cargo-fetch.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Fetch dependencies of a package from the network.\n\n[cargo-fix(1)](cargo-fix.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Automatically fix lint warnings reported by rustc.\n\n[cargo-run(1)](cargo-run.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Run a binary or example of the local package.\n\n[cargo-rustc(1)](cargo-rustc.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Compile a package, and pass extra options to the compiler.\n\n[cargo-rustdoc(1)](cargo-rustdoc.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Build a package's documentation, using specified custom flags.\n\n[cargo-test(1)](cargo-test.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Execute unit and integration tests of a package.\n\n### Manifest Commands\n\n[cargo-add(1)](cargo-add.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Add dependencies to a `Cargo.toml` manifest file.\n\n[cargo-generate-lockfile(1)](cargo-generate-lockfile.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Generate `Cargo.lock` for a project.\n\n[cargo-info(1)](cargo-info.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Display information about a package in the registry. Default registry is crates.io.\n\n[cargo-locate-project(1)](cargo-locate-project.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Print a JSON representation of a `Cargo.toml` file's location.\n\n[cargo-metadata(1)](cargo-metadata.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Output the resolved dependencies of a package in machine-readable format.\n\n[cargo-pkgid(1)](cargo-pkgid.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Print a fully qualified package specification.\n\n[cargo-remove(1)](cargo-remove.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Remove dependencies from a `Cargo.toml` manifest file.\n\n[cargo-tree(1)](cargo-tree.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Display a tree visualization of a dependency graph.\n\n[cargo-update(1)](cargo-update.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Update dependencies as recorded in the local lock file.\n\n[cargo-vendor(1)](cargo-vendor.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Vendor all dependencies locally.\n\n### Package Commands\n\n[cargo-init(1)](cargo-init.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Create a new Cargo package in an existing directory.\n\n[cargo-install(1)](cargo-install.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Build and install a Rust binary.\n\n[cargo-new(1)](cargo-new.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Create a new Cargo package.\n\n[cargo-search(1)](cargo-search.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Search packages in crates.io.\n\n[cargo-uninstall(1)](cargo-uninstall.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Remove a Rust binary.\n\n### Publishing Commands\n\n[cargo-login(1)](cargo-login.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Save an API token from the registry locally.\n\n[cargo-logout(1)](cargo-logout.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Remove an API token from the registry locally.\n\n[cargo-owner(1)](cargo-owner.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Manage the owners of a crate on the registry.\n\n[cargo-package(1)](cargo-package.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Assemble the local package into a distributable tarball.\n\n[cargo-publish(1)](cargo-publish.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Upload a package to the registry.\n\n[cargo-yank(1)](cargo-yank.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Remove a pushed crate from the index.\n\n### Report Commands\n\n[cargo-report(1)](cargo-report.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Generate and display various kinds of reports.\n\n[cargo-report-future-incompatibilities(1)](cargo-report-future-incompatibilities.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Reports any crates which will eventually stop compiling.\n\n### General Commands\n\n[cargo-help(1)](cargo-help.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Display help information about Cargo.\n\n[cargo-version(1)](cargo-version.html)\\\n&nbsp;&nbsp;&nbsp;&nbsp;Show version information.\n\n## OPTIONS\n\n### Special Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo--V\"><a class=\"option-anchor\" href=\"#option-cargo--V\"><code>-V</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo---version\"><a class=\"option-anchor\" href=\"#option-cargo---version\"><code>--version</code></a></dt>\n<dd class=\"option-desc\"><p>Print version info and exit. If used with <code>--verbose</code>, prints extra\ninformation.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo---list\"><a class=\"option-anchor\" href=\"#option-cargo---list\"><code>--list</code></a></dt>\n<dd class=\"option-desc\"><p>List all installed Cargo subcommands. If used with <code>--verbose</code>, prints extra\ninformation.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo---explain\"><a class=\"option-anchor\" href=\"#option-cargo---explain\"><code>--explain</code> <em>code</em></a></dt>\n<dd class=\"option-desc\"><p>Run <code>rustc --explain CODE</code> which will print out a detailed explanation of an\nerror message (for example, <code>E0004</code>).</p>\n</dd>\n\n\n</dl>\n\n### Display Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo--v\"><a class=\"option-anchor\" href=\"#option-cargo--v\"><code>-v</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo---verbose\"><a class=\"option-anchor\" href=\"#option-cargo---verbose\"><code>--verbose</code></a></dt>\n<dd class=\"option-desc\"><p>Use verbose output. May be specified twice for “very verbose” output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the <code>term.verbose</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo--q\"><a class=\"option-anchor\" href=\"#option-cargo--q\"><code>-q</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo---quiet\"><a class=\"option-anchor\" href=\"#option-cargo---quiet\"><code>--quiet</code></a></dt>\n<dd class=\"option-desc\"><p>Do not print cargo log messages.\nMay also be specified with the <code>term.quiet</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo---color\"><a class=\"option-anchor\" href=\"#option-cargo---color\"><code>--color</code> <em>when</em></a></dt>\n<dd class=\"option-desc\"><p>Control when colored output is used. Valid values:</p>\n<ul>\n<li><code>auto</code> (default): Automatically detect if color support is available on the\nterminal.</li>\n<li><code>always</code>: Always display colors.</li>\n<li><code>never</code>: Never display colors.</li>\n</ul>\n<p>May also be specified with the <code>term.color</code>\n<a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n</dl>\n\n### Manifest Options\n\n<dl>\n<dt class=\"option-term\" id=\"option-cargo---locked\"><a class=\"option-anchor\" href=\"#option-cargo---locked\"><code>--locked</code></a></dt>\n<dd class=\"option-desc\"><p>Asserts that the exact same dependencies and versions are used as when the\nexisting <code>Cargo.lock</code> file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:</p>\n<ul>\n<li>The lock file is missing.</li>\n<li>Cargo attempted to change the lock file due to a different dependency resolution.</li>\n</ul>\n<p>It may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo---offline\"><a class=\"option-anchor\" href=\"#option-cargo---offline\"><code>--offline</code></a></dt>\n<dd class=\"option-desc\"><p>Prevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.</p>\n<p>Beware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the <a href=\"cargo-fetch.html\">cargo-fetch(1)</a> command to download dependencies before going\noffline.</p>\n<p>May also be specified with the <code>net.offline</code> <a href=\"../reference/config.html\">config value</a>.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo---frozen\"><a class=\"option-anchor\" href=\"#option-cargo---frozen\"><code>--frozen</code></a></dt>\n<dd class=\"option-desc\"><p>Equivalent to specifying both <code>--locked</code> and <code>--offline</code>.</p>\n</dd>\n\n</dl>\n\n### Common Options\n\n<dl>\n\n<dt class=\"option-term\" id=\"option-cargo-+toolchain\"><a class=\"option-anchor\" href=\"#option-cargo-+toolchain\"><code>+</code><em>toolchain</em></a></dt>\n<dd class=\"option-desc\"><p>If Cargo has been installed with rustup, and the first argument to <code>cargo</code>\nbegins with <code>+</code>, it will be interpreted as a rustup toolchain name (such\nas <code>+stable</code> or <code>+nightly</code>).\nSee the <a href=\"https://rust-lang.github.io/rustup/overrides.html\">rustup documentation</a>\nfor more information about how toolchain overrides work.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo---config\"><a class=\"option-anchor\" href=\"#option-cargo---config\"><code>--config</code> <em>KEY=VALUE</em> or <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Overrides a Cargo configuration value. The argument should be in TOML syntax of <code>KEY=VALUE</code>,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the <a href=\"../reference/config.html#command-line-overrides\">command-line overrides section</a> for more information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo--C\"><a class=\"option-anchor\" href=\"#option-cargo--C\"><code>-C</code> <em>PATH</em></a></dt>\n<dd class=\"option-desc\"><p>Changes the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (<code>Cargo.toml</code>), as well as\nthe directories searched for discovering <code>.cargo/config.toml</code>, for example. This option must\nappear before the command name, for example <code>cargo -C path/to/my-project build</code>.</p>\n<p>This option is only available on the <a href=\"https://doc.rust-lang.org/book/appendix-07-nightly-rust.html\">nightly\nchannel</a> and\nrequires the <code>-Z unstable-options</code> flag to enable (see\n<a href=\"https://github.com/rust-lang/cargo/issues/10098\">#10098</a>).</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo--h\"><a class=\"option-anchor\" href=\"#option-cargo--h\"><code>-h</code></a></dt>\n<dt class=\"option-term\" id=\"option-cargo---help\"><a class=\"option-anchor\" href=\"#option-cargo---help\"><code>--help</code></a></dt>\n<dd class=\"option-desc\"><p>Prints help information.</p>\n</dd>\n\n\n<dt class=\"option-term\" id=\"option-cargo--Z\"><a class=\"option-anchor\" href=\"#option-cargo--Z\"><code>-Z</code> <em>flag</em></a></dt>\n<dd class=\"option-desc\"><p>Unstable (nightly-only) flags to Cargo. Run <code>cargo -Z help</code> for details.</p>\n</dd>\n\n\n</dl>\n\n## ENVIRONMENT\n\nSee [the reference](../reference/environment-variables.html) for\ndetails on environment variables that Cargo reads.\n\n## EXIT STATUS\n\n* `0`: Cargo succeeded.\n* `101`: Cargo failed to complete.\n\n## FILES\n\n`~/.cargo/`\\\n&nbsp;&nbsp;&nbsp;&nbsp;Default location for Cargo's \"home\" directory where it\nstores various files. The location can be changed with the `CARGO_HOME`\nenvironment variable.\n\n`$CARGO_HOME/bin/`\\\n&nbsp;&nbsp;&nbsp;&nbsp;Binaries installed by [cargo-install(1)](cargo-install.html) will be located here. If using\n[rustup], executables distributed with Rust are also located here.\n\n`$CARGO_HOME/config.toml`\\\n&nbsp;&nbsp;&nbsp;&nbsp;The global configuration file. See [the reference](../reference/config.html)\nfor more information about configuration files.\n\n`.cargo/config.toml`\\\n&nbsp;&nbsp;&nbsp;&nbsp;Cargo automatically searches for a file named `.cargo/config.toml` in the\ncurrent directory, and all parent directories. These configuration files\nwill be merged with the global configuration file.\n\n`$CARGO_HOME/credentials.toml`\\\n&nbsp;&nbsp;&nbsp;&nbsp;Private authentication information for logging in to a registry.\n\n`$CARGO_HOME/registry/`\\\n&nbsp;&nbsp;&nbsp;&nbsp;This directory contains cached downloads of the registry index and any\ndownloaded dependencies.\n\n`$CARGO_HOME/git/`\\\n&nbsp;&nbsp;&nbsp;&nbsp;This directory contains cached downloads of git dependencies.\n\nPlease note that the internal structure of the `$CARGO_HOME` directory is not\nstable yet and may be subject to change.\n\n[rustup]: https://rust-lang.github.io/rustup/\n\n## EXAMPLES\n\n1. Build a local package and all of its dependencies:\n\n       cargo build\n\n2. Build a package with optimizations:\n\n       cargo build --release\n\n3. Run tests for a cross-compiled target:\n\n       cargo test --target i686-unknown-linux-gnu\n\n4. Create a new package that builds an executable:\n\n       cargo new foobar\n\n5. Create a package in the current directory:\n\n       mkdir foo && cd foo\n       cargo init .\n\n6. Learn about a command's options and usage:\n\n       cargo help clean\n\n## BUGS\n\nSee <https://github.com/rust-lang/cargo/issues> for issues.\n\n## SEE ALSO\n\n[rustc(1)](https://doc.rust-lang.org/rustc/index.html), [rustdoc(1)](https://doc.rust-lang.org/rustdoc/index.html)\n"
  },
  {
    "path": "src/doc/src/commands/deprecated-and-removed.md",
    "content": "## Deprecated and Removed Commands\n\nThese commands have been deprecated or removed in early Rust releases.\nDeprecated commands receive only critical bug fixes,\nand may be removed in future versions.\nRemoved commands are no longer functional and are unsupported.\n\n* `read-manifest` --- deprecated since Rust 1.13\n* `git-checkout` --- removed since Rust 1.44\n* `verify-project` --- deprecated since Rust 1.84\n"
  },
  {
    "path": "src/doc/src/commands/general-commands.md",
    "content": "# General Commands\n* [cargo](cargo.md)\n* [cargo help](cargo-help.md)\n* [cargo version](cargo-version.md)\n"
  },
  {
    "path": "src/doc/src/commands/index.md",
    "content": "# Cargo Commands\n* [General Commands](general-commands.md)\n* [Build Commands](build-commands.md)\n* [Manifest Commands](manifest-commands.md)\n* [Package Commands](package-commands.md)\n* [Publishing Commands](publishing-commands.md)\n* [Report Commands](report-commands.md)\n* [Deprecated and Removed](deprecated-and-removed.md)\n"
  },
  {
    "path": "src/doc/src/commands/manifest-commands.md",
    "content": "# Manifest Commands\n\n* [cargo add](cargo-add.md)\n* [cargo_info](cargo-info.md)\n* [cargo generate-lockfile](cargo-generate-lockfile.md)\n* [cargo locate-project](cargo-locate-project.md)\n* [cargo metadata](cargo-metadata.md)\n* [cargo pkgid](cargo-pkgid.md)\n* [cargo remove](cargo-remove.md)\n* [cargo tree](cargo-tree.md)\n* [cargo update](cargo-update.md)\n* [cargo vendor](cargo-vendor.md)\n"
  },
  {
    "path": "src/doc/src/commands/package-commands.md",
    "content": "# Package Commands\n* [cargo init](cargo-init.md)\n* [cargo install](cargo-install.md)\n* [cargo new](cargo-new.md)\n* [cargo search](cargo-search.md)\n* [cargo uninstall](cargo-uninstall.md)\n"
  },
  {
    "path": "src/doc/src/commands/publishing-commands.md",
    "content": "# Publishing Commands\n* [cargo login](cargo-login.md)\n* [cargo logout](cargo-logout.md)\n* [cargo owner](cargo-owner.md)\n* [cargo package](cargo-package.md)\n* [cargo publish](cargo-publish.md)\n* [cargo yank](cargo-yank.md)\n"
  },
  {
    "path": "src/doc/src/commands/report-commands.md",
    "content": "# Report Commands\n\n* [cargo report](cargo-report.md)\n"
  },
  {
    "path": "src/doc/src/faq.md",
    "content": "# Frequently Asked Questions\n\n## Is the plan to use GitHub as a package repository?\n\nNo. The plan for Cargo is to use [crates.io], like npm or Rubygems do with\n[npmjs.com][1] and [rubygems.org][3].\n\nWe plan to support git repositories as a source of packages forever,\nbecause they can be used for early development and temporary patches,\neven when people use the registry as the primary source of packages.\n\n## Why build crates.io rather than use GitHub as a registry?\n\nWe think that it’s very important to support multiple ways to download\npackages, including downloading from GitHub and copying packages into\nyour package itself.\n\nThat said, we think that [crates.io] offers a number of important benefits, and\nwill likely become the primary way that people download packages in Cargo.\n\nFor precedent, both Node.js’s [npm][1] and Ruby’s [bundler][2] support both a\ncentral registry model as well as a Git-based model, and most packages\nare downloaded through the registry in those ecosystems, with an\nimportant minority of packages making use of git-based packages.\n\n[1]: https://www.npmjs.com\n[2]: https://bundler.io\n[3]: https://rubygems.org\n\nSome of the advantages that make a central registry popular in other\nlanguages include:\n\n* **Discoverability**. A central registry provides an easy place to look\n  for existing packages. Combined with tagging, this also makes it\n  possible for a registry to provide ecosystem-wide information, such as a\n  list of the most popular or most-depended-on packages.\n* **Speed**. A central registry makes it possible to easily fetch just\n  the metadata for packages quickly and efficiently, and then to\n  efficiently download just the published package, and not other bloat\n  that happens to exist in the repository. This adds up to a significant\n  improvement in the speed of dependency resolution and fetching. As\n  dependency graphs scale up, downloading all of the git repositories bogs\n  down fast. Also remember that not everybody has a high-speed,\n  low-latency Internet connection.\n\n## Will Cargo work with C code (or other languages)?\n\nYes!\n\nCargo handles compiling Rust code, but we know that many Rust packages\nlink against C code. We also know that there are decades of tooling\nbuilt up around compiling languages other than Rust.\n\nOur solution: Cargo allows a package to [specify a script](reference/build-scripts.md)\n(written in Rust) to run before invoking `rustc`. Rust is leveraged to\nimplement platform-specific configuration and refactor out common build\nfunctionality among packages.\n\n## Can Cargo be used inside of `make` (or `ninja`, or ...)\n\nIndeed. While we intend Cargo to be useful as a standalone way to\ncompile Rust packages at the top-level, we know that some people will\nwant to invoke Cargo from other build tools.\n\nWe have designed Cargo to work well in those contexts, paying attention\nto things like error codes and machine-readable output modes. We still\nhave some work to do on those fronts, but using Cargo in the context of\nconventional scripts is something we designed for from the beginning and\nwill continue to prioritize.\n\n## Does Cargo handle multi-platform packages or cross-compilation?\n\nRust itself provides facilities for configuring sections of code based\non the platform. Cargo also supports [platform-specific\ndependencies][target-deps], and we plan to support more per-platform\nconfiguration in `Cargo.toml` in the future.\n\n[target-deps]: reference/specifying-dependencies.md#platform-specific-dependencies\n\nIn the longer-term, we’re looking at ways to conveniently cross-compile\npackages using Cargo.\n\n## Does Cargo support environments, like `production` or `test`?\n\nWe support environments through the use of [profiles] to support:\n\n[profiles]: reference/profiles.md\n\n* environment-specific flags (like `-g --opt-level=0` for development\n  and `--opt-level=3` for production).\n* environment-specific dependencies (like `hamcrest` for test assertions).\n* environment-specific `#[cfg]`\n* a `cargo test` command\n\n## Does Cargo work on Windows?\n\nYes!\n\nAll commits to Cargo are required to pass the local test suite on Windows.\nIf you encounter an issue while running on Windows, we consider it a bug, so [please file an\nissue][cargo-issues].\n\n[cargo-issues]: https://github.com/rust-lang/cargo/issues\n\n## Why have `Cargo.lock` in version control?\n\nWhile [`cargo new`] defaults to tracking `Cargo.lock` in version control,\nwhether you do is dependent on the needs of your package.\n\nThe purpose of a `Cargo.lock` lockfile is to describe the state of the world at\nthe time of a successful build.\nCargo uses the lockfile to provide deterministic builds at different times and\non different systems,\nby ensuring that the exact same dependencies and versions are used as when the\n`Cargo.lock` file was originally generated.\n\nDeterministic builds help with\n- Running `git bisect` to find the root cause of a bug\n- Ensuring CI only fails due to new commits and not external factors\n- Reducing confusion when contributors see different behavior as compared to\n  other contributors or CI\n\nHaving this snapshot of dependencies can also help when projects need to be\nverified against consistent versions of dependencies, like when\n- Verifying a minimum-supported Rust version (MSRV) that is less than the latest\n  version of a dependency supports\n- Verifying human readable output which won't have compatibility guarantees\n  (e.g. snapshot testing error messages to ensure they are \"understandable\", a\n  metric too fuzzy to automate)\n\nHowever, this determinism can give a false sense of security because\n`Cargo.lock` does not affect the consumers of your package, only `Cargo.toml` does that.\nFor example:\n- [`cargo install`] will select the latest dependencies unless\n[`--locked`](commands/cargo.html#option-cargo---locked) is passed in.\n- New dependencies, like those added with [`cargo add`], will be locked to the latest version\n\nThe lockfile can also be a source of merge conflicts.\n\nFor strategies to verify newer versions of dependencies via CI,\nsee [Verifying Latest Dependencies](guide/continuous-integration.md#verifying-latest-dependencies).\n\n[`cargo new`]: commands/cargo-new.md\n[`cargo add`]: commands/cargo-add.md\n[`cargo install`]: commands/cargo-install.md\n\n## Can libraries use `*` as a version for their dependencies?\n\n**As of January 22nd, 2016, [crates.io] rejects all packages (not just libraries)\nwith wildcard dependency constraints.**\n\nWhile libraries _can_, strictly speaking, they should not. A version requirement\nof `*` says “This will work with every version ever”, which is never going\nto be true. Libraries should always specify the range that they do work with,\neven if it’s something as general as “every 1.x.y version”.\n\n## Why `Cargo.toml`?\n\nAs one of the most frequent interactions with Cargo, the question of why the\nconfiguration file is named `Cargo.toml` arises from time to time. The leading\ncapital-`C` was chosen to ensure that the manifest was grouped with other\nsimilar configuration files in directory listings. Sorting files often puts\ncapital letters before lowercase letters, ensuring files like `Makefile` and\n`Cargo.toml` are placed together. The trailing `.toml` was chosen to emphasize\nthe fact that the file is in the [TOML configuration\nformat](https://toml.io/).\n\nCargo does not allow other names such as `cargo.toml` or `Cargofile` to\nemphasize the ease of how a Cargo repository can be identified. An option of\nmany possible names has historically led to confusion where one case was handled\nbut others were accidentally forgotten.\n\n[crates.io]: https://crates.io/\n\n## How can Cargo work offline?\n\nThe [`--offline`](commands/cargo.html#option-cargo---offline) or\n [`--frozen`](commands/cargo.html#option-cargo---frozen) flags tell Cargo to not\n touch the network. It returns an error in case it would access the network. \nYou can use [`cargo fetch`] in one project to download\ndependencies before going offline, and then use those same dependencies in\nanother project. Refer to [configuration value][offline config]) to set via\nCargo configuration.\n\n\n\nVendoring is also related, for more information see documentation on [source\nreplacement][replace].\n\n[replace]: reference/source-replacement.md\n[`cargo fetch`]: commands/cargo-fetch.md\n[offline config]: reference/config.md#netoffline\n\n## Why is Cargo rebuilding my code?\n\nCargo is responsible for incrementally compiling crates in your project. This\nmeans that if you type `cargo build` twice the second one shouldn't rebuild your\ncrates.io dependencies, for example. Nevertheless bugs arise and Cargo can\nsometimes rebuild code when you're not expecting it!\n\nWe've long [wanted to provide better diagnostics about\nthis](https://github.com/rust-lang/cargo/issues/2904) but unfortunately haven't\nbeen able to make progress on that issue in quite some time. In the meantime,\nhowever, you can debug a rebuild at least a little by setting the `CARGO_LOG`\nenvironment variable:\n\n```sh\n$ CARGO_LOG=cargo::core::compiler::fingerprint=info cargo build\n```\n\nThis will cause Cargo to print out a lot of information about diagnostics and\nrebuilding. This can often contain clues as to why your project is getting\nrebuilt, although you'll often need to connect some dots yourself since this\noutput isn't super easy to read just yet. Note that the `CARGO_LOG` needs to be\nset for the command that rebuilds when you think it should not. Unfortunately\nCargo has no way right now of after-the-fact debugging \"why was that rebuilt?\"\n\nSome issues we've seen historically which can cause crates to get rebuilt are:\n\n* A build script prints `cargo::rerun-if-changed=foo` where `foo` is a file that\n  doesn't exist and nothing generates it. In this case Cargo will keep running\n  the build script thinking it will generate the file but nothing ever does. The\n  fix is to avoid printing `rerun-if-changed` in this scenario.\n\n* Two successive Cargo builds may differ in the set of features enabled for some\n  dependencies. For example if the first build command builds the whole\n  workspace and the second command builds only one crate, this may cause a\n  dependency on crates.io to have a different set of features enabled, causing\n  it and everything that depends on it to get rebuilt. There's unfortunately not\n  really a great fix for this, although if possible it's best to have the set of\n  features enabled on a crate constant regardless of what you're building in\n  your workspace.\n\n* Some filesystems exhibit unusual behavior around timestamps. Cargo primarily\n  uses timestamps on files to govern whether rebuilding needs to happen, but if\n  you're using a nonstandard filesystem it may be affecting the timestamps\n  somehow (e.g. truncating them, causing them to drift, etc). In this scenario,\n  feel free to open an issue and we can see if we can accommodate the filesystem\n  somehow.\n\n* A concurrent build process is either deleting artifacts or modifying files.\n  Sometimes you might have a background process that either tries to build or\n  check your project. These background processes might surprisingly delete some\n  build artifacts or touch files (or maybe just by accident), which can cause\n  rebuilds to look spurious! The best fix here would be to wrangle the\n  background process to avoid clashing with your work.\n\nIf after trying to debug your issue, however, you're still running into problems\nthen feel free to [open an\nissue](https://github.com/rust-lang/cargo/issues/new)!\n\n## What does \"version conflict\" mean and how to resolve it?\n\n> failed to select a version for `x` which could resolve this conflict\n\nHave you seen the error message above?\n\nThis is one of the most annoying error messages for Cargo users. There are several\nsituations which may lead to a version conflict. Below we'll walk through possible\ncauses and provide diagnostic techniques to help you out there:\n\n- The project and its dependencies use [links] to repeatedly link the local\n  library. Cargo forbids linking two packages with the same native library, so\n  even with multiple layers of dependencies it is not allowed. In this case, the\n  error message will prompt: `Only one package in the dependency graph may specify\n  the same links value`, you may need to manually check and delete duplicate link\n  values. The community also have [conventions in place] to alleviate this.\n\n- When depending on different crates in the project, if these crates use the same\n  dependent library, but the version used is restricted, making it impossible to\n  determine the correct version, it will also cause conflicts. The error message\n  will prompt: `all possible versions conflict with previously selected packages`.\n  You may need to modify the version requirements to make them consistent.\n\n- If there are multiple versions of dependencies in the project, when using\n  [`direct-minimal-versions`], the minimum version requirements cannot be met,\n  which will cause conflicts. You may need to modify version requirements of your\n  direct dependencies to meet the minimum SemVer version accordingly.\n\n- If the dependent crate does not have the features you choose, it will also\n  cause conflicts. At this time, you need to check the dependent version and its\n  features.\n\n- Conflicts may occur when merging branches or PRs, if there are non-trivial\n  conflicts, you can reset all \"yours\" changes, fix all other conflicts in the\n  branch, and then run some cargo command (like `cargo tree` or `cargo check`),\n  which should re-update the lockfile with your own local changes. If you previously\n  ran some `cargo update` commands in your branch, you can re-run them that this\n  time. The community has been looking to resolve merge conflicts with `Cargo.lock`\n  and `Cargo.toml` using a [custom merge tool].\n\n\n[links]: reference/resolver.md#links\n[conventions in place]: reference/build-scripts.md#-sys-packages\n[`direct-minimal-versions`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#direct-minimal-versions\n[custom merge tool]: https://github.com/rust-lang/cargo/issues/1818\n\n## Why does my build take up so much space?\n\nCargo trades off disk space for faster builds including:\n- Maintaining a [cache] of intermediate build artifacts to avoid rebuilding everything when making changes to one package\n- Maintaining distinct [cache] entries for different combinations of toolchain versions, package versions, features, etc to avoid rebuilding packages when switching back and forth between configurations\n- Enabling [incremental compilation] for local packages for faster rebuilds for the package that changed\n- Enabling [debuginfo] in the [`dev` profile] in case you use a debugger\n\n[incremental compilation]: reference/profiles.md#incremental\n[debuginfo]: reference/profiles.md#debug\n[`dev` profile]: reference/profiles.md#dev\n[cache]: reference/build-cache.md\n"
  },
  {
    "path": "src/doc/src/getting-started/first-steps.md",
    "content": "# First Steps with Cargo\n\nThis section provides a quick sense for the `cargo` command line tool. We\ndemonstrate its ability to generate a new [***package***][def-package] for us,\nits ability to compile the [***crate***][def-crate] within the package, and\nits ability to run the resulting program.\n\nTo start a new package with Cargo, use `cargo new`:\n\n```console\n$ cargo new hello_world\n```\n\nCargo defaults to `--bin` to make a binary program. To make a library, we\nwould pass `--lib`, instead.\n\nLet’s check out what Cargo has generated for us:\n\n```console\n$ cd hello_world\n$ tree .\n.\n├── Cargo.toml\n└── src\n    └── main.rs\n\n1 directory, 2 files\n```\n\nThis is all we need to get started. First, let’s check out `Cargo.toml`:\n\n```toml\n[package]\nname = \"hello_world\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n```\n\nThis is called a [***manifest***][def-manifest], and it contains all of the\nmetadata that Cargo needs to compile your package.\n\nHere’s what’s in `src/main.rs`:\n\n```rust\nfn main() {\n    println!(\"Hello, world!\");\n}\n```\n\nCargo generated a “hello world” program for us, otherwise known as a\n[***binary crate***][def-crate]. Let’s compile it:\n\n```console\n$ cargo build\n   Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)\n```\n\nAnd then run it:\n\n```console\n$ ./target/debug/hello_world\nHello, world!\n```\n\nWe can also use `cargo run` to compile and then run it, all in one step:\n\n```console\n$ cargo run\n     Fresh hello_world v0.1.0 (file:///path/to/package/hello_world)\n   Running `target/hello_world`\nHello, world!\n```\n\n## Going further\n\nFor more details on using Cargo, check out the [Cargo Guide](../guide/index.md)\n\n[def-crate]:     ../appendix/glossary.md#crate     '\"crate\" (glossary entry)'\n[def-manifest]:  ../appendix/glossary.md#manifest  '\"manifest\" (glossary entry)'\n[def-package]:   ../appendix/glossary.md#package   '\"package\" (glossary entry)'\n"
  },
  {
    "path": "src/doc/src/getting-started/index.md",
    "content": "# Getting Started\n\nTo get started with Cargo, install Cargo (and Rust) and set up your first\n[*crate*][def-crate].\n\n* [Installation](installation.md)\n* [First steps with Cargo](first-steps.md)\n\n[def-crate]:  ../appendix/glossary.md#crate  '\"crate\" (glossary entry)'\n"
  },
  {
    "path": "src/doc/src/getting-started/installation.md",
    "content": "# Installation\n\n## Install Rust and Cargo\n\nThe easiest way to get Cargo is to install the current stable release of [Rust]\nby using [rustup]. Installing Rust using `rustup` will also install `cargo`.\n\nOn Linux and macOS systems, this is done as follows:\n\n```console\ncurl https://sh.rustup.rs -sSf | sh\n```\n\nIt will download a script, and start the installation. If everything goes well,\nyou’ll see this appear:\n\n```console\nRust is installed now. Great!\n```\n\nOn Windows, download and run [rustup-init.exe]. It will start the installation\nin a console and present the above message on success.\n\nAfter this, you can use the `rustup` command to also install `beta` or `nightly`\nchannels for Rust and Cargo.\n\nFor other installation options and information, visit the\n[install][install-rust] page of the Rust website.\n\n## Build and Install Cargo from Source\n\nAlternatively, you can [build Cargo from source][compiling-from-source].\n\n[rust]: https://www.rust-lang.org/\n[rustup]: https://rustup.rs/\n[rustup-init.exe]: https://win.rustup.rs/\n[install-rust]: https://www.rust-lang.org/tools/install\n[compiling-from-source]: https://github.com/rust-lang/cargo#compiling-from-source\n"
  },
  {
    "path": "src/doc/src/guide/build-performance.md",
    "content": "# Optimizing Build Performance\n\nCargo configuration options and source code organization patterns can help improve build performance, by prioritizing it over other aspects which may not be as important for your circumstances.\n\nSame as when optimizing runtime performance, be sure to measure these changes against the workflows you actually care about, as we provide general guidelines and your circumstances may be different, it is possible that some of these approaches might actually make build performance worse for your use-case.\n\nExample workflows to consider include:\n- Compiler feedback as you develop (`cargo check` after making a code change)\n- Test feedback as you develop (`cargo test` after making a code change)\n- CI builds\n\n## Cargo and Compiler Configuration\n\nCargo uses configuration defaults that try to balance several aspects, including debuggability, runtime performance, build performance, binary size and others. This section describes several approaches for changing these defaults that should be designed to maximize build performance.\n\nCommon locations to override defaults are:\n- [`Cargo.toml` manifest](../reference/profiles.md)\n  - Available to all developers contributing to your project\n  - Limited in what configuration is supported (see [#12738](https://github.com/rust-lang/cargo/issues/12738) for expanding this)\n- [`$WORKSPACE_ROOT/.cargo/config.toml` configuration file](../reference/config.md)\n  - Available to all developers contributing to your project\n  - Unlike `Cargo.toml`, this is sensitive to what directory you invoke `cargo` from (see [#2930](https://github.com/rust-lang/cargo/issues/2930))\n- [`$CARGO_HOME/.cargo/config.toml` configuration file](../reference/config.md)\n  - For a developer to control the defaults for their development\n\n### Reduce amount of generated debug information\n\nRecommendation: Add to your `Cargo.toml` or `.cargo/config.toml`:\n\n```toml\n[profile.dev]\ndebug = \"line-tables-only\"\n\n[profile.dev.package.\"*\"]\ndebug = false\n\n[profile.debugging]\ninherits = \"dev\"\ndebug = true\n```\n\nThis will:\n- Change the [`dev` profile](../reference/profiles.md#dev) (default for development commands) to:\n  - Limit [debug information](../reference/profiles.md#debug) for workspace members to what is needed for useful panic backtraces\n  - Avoid generating any debug information for dependencies\n- Provide an opt-in for when debugging via [`--profile debugging`](../reference/profiles.md#custom-profiles)\n\n> **Note:** re-evaluating the `dev` profile is being tracked in [#15931](https://github.com/rust-lang/cargo/issues/15931).\n\nTrade-offs:\n- ✅ Faster code generation (`cargo build`)\n- ✅ Faster link times\n- ✅ Smaller disk usage of the `target` directory\n- ❌ Requires a full rebuild to have a high-quality debugger experience\n\n### Use an alternative codegen backend\n\nRecommendation:\n\n- Install the Cranelift codegen backend rustup component\n    ```console\n    $ rustup component add rustc-codegen-cranelift-preview --toolchain nightly\n    ```\n- Add to your `Cargo.toml` or `.cargo/config.toml`:\n    ```toml\n    [profile.dev]\n    codegen-backend = \"cranelift\"\n    ```\n- Run Cargo with `-Z codegen-backend` or enable the [`codegen-backend`](../reference/unstable.md#codegen-backend) feature in `.cargo/config.toml`.\n  - This is required because this is currently an unstable feature.\n\nThis will change the [`dev` profile](../reference/profiles.md#dev) to use the [Cranelift codegen backend](https://github.com/rust-lang/rustc_codegen_cranelift) for generating machine code, instead of the default LLVM backend. The Cranelift backend should generate code faster than LLVM, which should result in improved build performance.\n\nTrade-offs:\n- ✅ Faster code generation (`cargo build`)\n- ❌ **Requires using nightly Rust and an [unstable Cargo feature][codegen-backend-feature]**\n- ❌ Worse runtime performance of the generated code\n  - Speeds up build part of `cargo test`, but might increase its test execution part\n- ❌ Only available for [certain targets](https://github.com/rust-lang/rustc_codegen_cranelift?tab=readme-ov-file#platform-support)\n- ❌ Might not support all Rust features (e.g. unwinding)\n\n[codegen-backend-feature]: ../reference/unstable.md#codegen-backend\n\n### Enable the experimental parallel frontend\n\nRecommendation: Add to your `.cargo/config.toml`:\n\n```toml\n[build]\nrustflags = \"-Zthreads=8\"\n```\n\nThis [`rustflags`][build.rustflags] will enable the [parallel frontend][parallel-frontend-blog] of the Rust compiler, and tell it to use `n` threads. The value of `n` should be chosen according to the number of cores available on your system, although there are diminishing returns. We recommend using at most `8` threads.\n\nTrade-offs:\n- ✅ Faster build times (both `cargo check` and `cargo build`)\n- ❌ **Requires using nightly Rust and an [unstable Rust feature][parallel-frontend-issue]**\n\n[parallel-frontend-blog]: https://blog.rust-lang.org/2023/11/09/parallel-rustc/\n[parallel-frontend-issue]: https://github.com/rust-lang/rust/issues/113349\n[build.rustflags]: ../reference/config.md#buildrustflags\n\n### Use an alternative linker\n\nConsider: installing and configuring an alternative linker, like [LLD](https://lld.llvm.org/), [mold](https://github.com/rui314/mold) or [wild](https://github.com/davidlattimore/wild). For example, to configure mold on Linux, you can add to your `.cargo/config.toml`:\n\n```toml\n[target.'cfg(target_os = \"linux\")']\n# mold, if you have GCC 12+\nrustflags = [\"-C\", \"link-arg=-fuse-ld=mold\"]\n\n# mold, otherwise\nlinker = \"clang\"\nrustflags = [\"-C\", \"link-arg=-fuse-ld=/path/to/mold\"]\n```\n\nWhile dependencies may be built in parallel, linking all of your dependencies happens at once at the end of your build, which can make linking dominate your build times, especially for incremental rebuilds. Often, the linker Rust uses is already fairly fast and the gains from switching may not be worth it, but it is not always the case. For example, Linux targets besides `x86_64-unknown-linux-gnu` still use the Linux system linker which is quite slow (see [rust#39915](https://github.com/rust-lang/rust/issues/39915) for more details).\n\nTrade-offs:\n- ✅ Faster link times\n- ❌ Might not support all use-cases, in particular if you depend on C or C++ dependencies\n\n### Resolve features for the whole workspace\n\nConsider: adding to your project's `.cargo/config.toml`\n\n```toml\n[resolver]\nfeature-unification = \"workspace\"\n```\n\nWhen invoking `cargo`,\n[features get activated][resolver-features] based on which workspace members you have selected.\nHowever, when contributing to an application,\nyou may need to build and test various packages within the application,\nwhich can cause extraneous rebuilds because different sets of features may be activated for common dependencies.\nWith [`feature-unification`][feature-unification],\nyou can reuse more dependency builds by ensuring the same set of dependency features are activated,\nindependent of which package you are currently building and testing.\n\nTrade-offs:\n- ✅ Fewer rebuilds when building different packages in a workspace\n- ❌ **Requires using nightly Rust and an [unstable Cargo feature][feature-unification]**\n- ❌ A package activating a feature can mask bugs in other packages that should activate it but don't\n- ❌ If the feature unification from `--workspace` doesn't work for you, then this won't either\n\n[resolver-features]: ../reference/resolver.md#features\n[feature-unification]: ../reference/unstable.md#feature-unification\n\n## Reducing built code\n\n### Removing unused dependencies\n\nRecommendation: Periodically review unused dependencies for removal using third-party tools like\n[cargo-machete](https://crates.io/crates/cargo-machete),\n[cargo-udeps](https://crates.io/crates/cargo-udeps),\n[cargo-shear](https://crates.io/crates/cargo-shear).\n\nWhen changing code,\nit can be easy to miss that a dependency is no longer used and can be removed.\n\n> **Note:** native support for this in Cargo is being tracked in [#15813](https://github.com/rust-lang/cargo/issues/15813).\n\nTrade-offs:\n- ✅ Faster full build and link times\n- ❌ May incorrectly flag dependencies as unused or miss some\n\n### Removing unused features from dependencies\n\nRecommendation: Periodically review unused features from dependencies for removal using third-party tools like\n[cargo-features-manager](https://crates.io/crates/cargo-features-manager),\n[cargo-unused-features](https://crates.io/crates/cargo-unused-features).\n\nWhen changing code,\nit can be easy to miss that a dependency's feature is no longer used and can be removed.\nThis can reduce the number of transitive dependencies being built or\nreduce the amount of code within a crate being built.\nWhen removing features, extra caution is needed because features\nmay also be used for desired behavior or performance changes\nwhich may not always be obvious from compiling or testing.\n\nTrade-offs:\n- ✅ Faster full build and link times\n- ❌ May incorrectly flag features as unused\n"
  },
  {
    "path": "src/doc/src/guide/cargo-home.md",
    "content": "# Cargo Home\n\nThe \"Cargo home\" functions as a download and source cache.\nWhen building a [crate][def-crate], Cargo stores downloaded build dependencies in the Cargo home.\nYou can alter the location of the Cargo home by setting the `CARGO_HOME` [environmental variable][env].\nThe [home](https://crates.io/crates/home) crate provides an API for getting this location if you need this information inside your Rust crate.\nBy default, the Cargo home is located in `$HOME/.cargo/`.\n\nPlease note that the internal structure of the Cargo home is not stabilized and may be subject to change at any time.\n\nThe Cargo home consists of following components:\n\n## Files:\n\n* `config.toml`\n\tCargo's global configuration file, see the [config entry in the reference][config].\n\n* `credentials.toml`\n \tPrivate login credentials from [`cargo login`] in order to log in to a [registry][def-registry].\n\n* `.crates.toml`, `.crates2.json`\n\tThese hidden files contain [package][def-package] information of crates installed via [`cargo install`]. Do NOT edit by hand!\n\n## Directories:\n\n* `bin`\nThe bin directory contains executables of crates that were installed via [`cargo install`] or [`rustup`](https://rust-lang.github.io/rustup/).\nTo be able to make these binaries accessible, add the path of the directory to your `$PATH` environment variable.\n\n *  `git`\n\tGit sources are stored here:\n\n    * `git/db`\n\t\tWhen a crate depends on a git repository, Cargo clones the repo as a bare repo into this directory and updates it if necessary.\n\n    * `git/checkouts`\n\t\tIf a git source is used, the required commit of the repo is checked out from the bare repo inside `git/db` into this directory.\n\t\tThis provides the compiler with the actual files contained in the repo of the commit specified for that dependency.\n\t\tMultiple checkouts of different commits of the same repo are possible.\n\n* `registry`\n\tPackages and metadata of crate registries (such as [crates.io](https://crates.io/)) are located here.\n\n  * `registry/index`\n\t\tThe index is a bare git repository which contains the metadata (versions, dependencies etc) of all available crates of a registry.\n\n  *  `registry/cache`\n\t\tDownloaded dependencies are stored in the cache. The crates are compressed gzip archives named with a `.crate` extension.\n\n  * `registry/src`\n\t\tIf a downloaded `.crate` archive is required by a package, it is unpacked into `registry/src` folder where rustc will find the `.rs` files.\n\n\n## Caching the Cargo home in CI\n\nTo avoid redownloading all crate dependencies during continuous integration, you can cache the `$CARGO_HOME` directory.\nHowever, caching the entire directory is often inefficient as it will contain downloaded sources twice.\nIf we depend on a crate such as `serde 1.0.92` and cache the entire `$CARGO_HOME` we would actually cache the sources twice, the `serde-1.0.92.crate` inside `registry/cache` and the extracted `.rs` files of serde inside `registry/src`.\nThat can unnecessarily slow down the build as downloading, extracting, recompressing and reuploading the cache to the CI servers can take some time.\n\nIf you wish to cache binaries installed with [`cargo install`], you need to cache the `bin/` folder and the `.crates.toml` and `.crates2.json` files.\n\nIt should be sufficient to cache the following files and directories across builds:\n\n* `.crates.toml`\n* `.crates2.json`\n* `bin/`\n* `registry/index/`\n* `registry/cache/`\n* `git/db/`\n\n\n\n## Vendoring all dependencies of a project\n\nSee the [`cargo vendor`] subcommand.\n\n\n\n## Clearing the cache\n\nIn theory, you can always remove any part of the cache and Cargo will do its best to restore sources if a crate needs them either by reextracting an archive or checking out a bare repo or by simply redownloading the sources from the web.\n\nAlternatively, the [cargo-cache](https://crates.io/crates/cargo-cache) crate provides a simple CLI tool to only clear selected parts of the cache or show sizes of its components in your command-line.\n\n[`cargo install`]: ../commands/cargo-install.md\n[`cargo login`]: ../commands/cargo-login.md\n[`cargo vendor`]: ../commands/cargo-vendor.md\n[config]: ../reference/config.md\n[def-crate]:     ../appendix/glossary.md#crate     '\"crate\" (glossary entry)'\n[def-package]:   ../appendix/glossary.md#package   '\"package\" (glossary entry)'\n[def-registry]:  ../appendix/glossary.md#registry  '\"registry\" (glossary entry)'\n[env]: ../reference/environment-variables.md\n"
  },
  {
    "path": "src/doc/src/guide/cargo-toml-vs-cargo-lock.md",
    "content": "# Cargo.toml vs Cargo.lock\n\n`Cargo.toml` and `Cargo.lock` serve two different purposes. Before we talk\nabout them, here’s a summary:\n\n* `Cargo.toml` is about describing your dependencies in a broad sense, and is\n  written by you.\n* `Cargo.lock` contains exact information about your dependencies. It is\n  maintained by Cargo and should not be manually edited.\n\nWhen in doubt, check `Cargo.lock` into the version control system (e.g. Git).\nFor a better understanding of why and what the alternatives might be, see\n[“Why have Cargo.lock in version control?” in the FAQ](../faq.md#why-have-cargolock-in-version-control).\nWe recommend pairing this with\n[Verifying Latest Dependencies](continuous-integration.md#verifying-latest-dependencies)\n\nLet’s dig in a little bit more.\n\n`Cargo.toml` is a [**manifest**][def-manifest] file in which you can specify a\nbunch of different metadata about your package. For example, you can say that you\ndepend on another package:\n\n```toml\n[package]\nname = \"hello_world\"\nversion = \"0.1.0\"\n\n[dependencies]\nregex = { git = \"https://github.com/rust-lang/regex.git\" }\n```\n\nThis package has a single dependency, on the `regex` library. It states in\nthis case to rely on a particular Git repository that lives on\nGitHub. Since you haven’t specified any other information, Cargo assumes that\nyou intend to use the latest commit on the default branch to build our package.\n\nSound good? Well, there’s one problem: If you build this package today, and\nthen you send a copy to me, and I build this package tomorrow, something bad\ncould happen. There could be more commits to `regex` in the meantime, and my\nbuild would include new commits while yours would not. Therefore, we would\nget different builds. This would be bad because we want reproducible builds.\n\nYou could fix this problem by defining a specific `rev` value in our `Cargo.toml`,\nso Cargo could know exactly which revision to use when building the package:\n\n```toml\n[dependencies]\nregex = { git = \"https://github.com/rust-lang/regex.git\", rev = \"9f9f693\" }\n```\n\nNow our builds will be the same. But there’s a big drawback: now you have to\nmanually think about SHA-1s every time you want to update our library. This is\nboth tedious and error prone.\n\nEnter the `Cargo.lock`. Because of its existence, you don’t need to manually\nkeep track of the exact revisions: Cargo will do it for you. When you have a\nmanifest like this:\n\n```toml\n[package]\nname = \"hello_world\"\nversion = \"0.1.0\"\n\n[dependencies]\nregex = { git = \"https://github.com/rust-lang/regex.git\" }\n```\n\nCargo will take the latest commit and write that information out into your\n`Cargo.lock` when you build for the first time. That file will look like this:\n\n```toml\n[[package]]\nname = \"hello_world\"\nversion = \"0.1.0\"\ndependencies = [\n \"regex 1.5.0 (git+https://github.com/rust-lang/regex.git#9f9f693768c584971a4d53bc3c586c33ed3a6831)\",\n]\n\n[[package]]\nname = \"regex\"\nversion = \"1.5.0\"\nsource = \"git+https://github.com/rust-lang/regex.git#9f9f693768c584971a4d53bc3c586c33ed3a6831\"\n```\n\nYou can see that there’s a lot more information here, including the exact\nrevision you used to build. Now when you give your package to someone else,\nthey’ll use the exact same SHA, even though you didn’t specify it in your\n`Cargo.toml`.\n\nWhen you're ready to opt in to a new version of the library, Cargo can\nre-calculate the dependencies and update things for you:\n\n```console\n$ cargo update         # updates all dependencies\n$ cargo update regex   # updates just “regex”\n```\n\nThis will write out a new `Cargo.lock` with the new version information. Note\nthat the argument to `cargo update` is actually a\n[Package ID Specification](../reference/pkgid-spec.md) and `regex` is just a\nshort specification.\n\n[def-manifest]:  ../appendix/glossary.md#manifest  '\"manifest\" (glossary entry)'\n[def-package]:   ../appendix/glossary.md#package   '\"package\" (glossary entry)'\n"
  },
  {
    "path": "src/doc/src/guide/continuous-integration.md",
    "content": "# Continuous Integration\n\n## Getting Started\n\nA basic CI will build and test your projects:\n\n### GitHub Actions\n\nTo test your package on GitHub Actions, here is a sample `.github/workflows/ci.yml` file:\n\n```yaml\nname: Cargo Build & Test\n\non:\n  push:\n  pull_request:\n\nenv: \n  CARGO_TERM_COLOR: always\n\njobs:\n  build_and_test:\n    name: Rust project - latest\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        toolchain:\n          - stable\n          - beta\n          - nightly\n    steps:\n      - uses: actions/checkout@v4\n      - run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}\n      - run: cargo build --verbose\n      - run: cargo test --verbose\n  \n```\n\nThis will test all three release channels (note a failure in any toolchain version will fail the entire job). You can also click `\"Actions\" > \"new workflow\"` in the GitHub UI and select Rust to add the [default configuration](https://github.com/actions/starter-workflows/blob/main/ci/rust.yml) to your repo. See [GitHub Actions documentation](https://docs.github.com/en/actions) for more information.\n\n### GitLab CI\n\nTo test your package on GitLab CI, here is a sample `.gitlab-ci.yml` file:\n\n```yaml\nstages:\n  - build\n\nrust-latest:\n  stage: build\n  image: rust:latest\n  script:\n    - cargo build --verbose\n    - cargo test --verbose\n\nrust-nightly:\n  stage: build\n  image: rustlang/rust:nightly\n  script:\n    - cargo build --verbose\n    - cargo test --verbose\n  allow_failure: true\n```\n\nThis will test on the stable channel and nightly channel, but any\nbreakage in nightly will not fail your overall build. Please see the\n[GitLab CI documentation](https://docs.gitlab.com/ce/ci/yaml/index.html) for more\ninformation.\n\n### builds.sr.ht\n\nTo test your package on sr.ht, here is a sample `.build.yml` file.\nBe sure to change `<your repo>` and `<your project>` to the repo to clone and\nthe directory where it was cloned.\n\n```yaml\nimage: archlinux\npackages:\n  - rustup\nsources:\n  - <your repo>\ntasks:\n  - setup: |\n      rustup toolchain install nightly stable\n      cd <your project>/\n      rustup run stable cargo fetch\n  - stable: |\n      rustup default stable\n      cd <your project>/\n      cargo build --verbose\n      cargo test --verbose\n  - nightly: |\n      rustup default nightly\n      cd <your project>/\n      cargo build --verbose ||:\n      cargo test --verbose  ||:\n  - docs: |\n      cd <your project>/\n      rustup run stable cargo doc --no-deps\n      rustup run nightly cargo doc --no-deps ||:\n```\n\nThis will test and build documentation on the stable channel and nightly\nchannel, but any breakage in nightly will not fail your overall build. Please\nsee the [builds.sr.ht documentation](https://man.sr.ht/builds.sr.ht/) for more\ninformation.\n\n\n### CircleCI\n\nTo test your package on CircleCI, here is a sample `.circleci/config.yml` file:\n\n```yaml\nversion: 2.1\njobs:\n  build:\n    docker:\n      # check https://circleci.com/developer/images/image/cimg/rust#image-tags for latest\n      - image: cimg/rust:1.77.2\n    steps:\n      - checkout\n      - run: cargo test\n```\n\nTo run more complex pipelines, including flaky test detection, caching, and artifact management, please see [CircleCI Configuration Reference](https://circleci.com/docs/configuration-reference/).\n\n## Verifying Latest Dependencies\n\nWhen [specifying dependencies](../reference/specifying-dependencies.md) in\n`Cargo.toml`, they generally match a range of versions.\nExhaustively testing all version combination would be unwieldy.\nVerifying the latest versions would at least test for users who run [`cargo\nadd`] or [`cargo install`].\n\nWhen testing the latest versions some considerations are:\n- Minimizing external factors affecting local development or CI\n- Rate of new dependencies being published\n- Level of risk a project is willing to accept\n- CI costs, including indirect costs like if a CI service has a maximum for\n  parallel runners, causing new jobs to be serialized when at the maximum.\n\nSome potential solutions include:\n- [Not checking in the `Cargo.lock`](../faq.md#why-have-cargolock-in-version-control)\n  - Depending on PR velocity, many versions may go untested\n  - This comes at the cost of determinism\n- Have a CI job verify the latest dependencies but mark it to \"continue on failure\"\n  - Depending on the CI service, failures might not be obvious\n  - Depending on PR velocity, may use more resources than necessary\n- Have a scheduled CI job to verify latest dependencies\n  - A hosted CI service may disable scheduled jobs for repositories that\n    haven't been touched in a while, affecting passively maintained packages\n  - Depending on the CI service, notifications might not be routed to people\n    who can act on the failure\n  - If not balanced with dependency publish rate, may not test enough versions\n    or may do redundant testing\n- Regularly update dependencies through PRs, like with [Dependabot] or [RenovateBot]\n  - Can isolate dependencies to their own PR or roll them up into a single PR\n  - Only uses the resources necessary\n  - Can configure the frequency to balance CI resources and coverage of dependency versions\n\nAn example CI job to verify latest dependencies, using GitHub Actions:\n```yaml\njobs:\n  latest_deps:\n    name: Latest Dependencies\n    runs-on: ubuntu-latest\n    continue-on-error: true\n    env:\n      CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: allow\n    steps:\n      - uses: actions/checkout@v4\n      - run: rustup update stable && rustup default stable\n      - run: cargo update --verbose\n      - run: cargo build --verbose\n      - run: cargo test --verbose\n```\nNotes:\n- [`CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS`](../reference/config.md#resolverincompatible-rust-versions) is set to ensure the [resolver](../reference/resolver.md) doesn't limit selected dependencies because of your project's [Rust version](../reference/rust-version.md).\n\nFor projects with higher risks of per-platform or per-Rust version failures,\nmore combinations may want to be tested.\n\n## Verifying `rust-version`\n\nWhen publishing packages that specify [`rust-version`](../reference/manifest.md#the-rust-version-field),\nit is important to verify the correctness of that field.\n\nSome third-party tools that can help with this include:\n- [`cargo-msrv`](https://crates.io/crates/cargo-msrv)\n- [`cargo-hack`](https://crates.io/crates/cargo-hack)\n\nAn example of one way to do this, using GitHub Actions:\n```yaml\njobs:\n  msrv:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v4\n    - uses: taiki-e/install-action@cargo-hack\n    - run: cargo hack check --rust-version --workspace --all-targets --ignore-private\n```\nThis tries to balance thoroughness with turnaround time:\n- A single platform is used as most projects are platform-agnostic, trusting platform-specific dependencies to verify their behavior.\n- `cargo check` is used as most issues contributors will run into are API availability and not behavior.\n- Unpublished packages are skipped as this assumes only consumers of the verified project, through a registry, will care about `rust-version`.\n\n[`cargo add`]: ../commands/cargo-add.md\n[`cargo install`]: ../commands/cargo-install.md\n[Dependabot]: https://docs.github.com/en/code-security/dependabot/working-with-dependabot\n[RenovateBot]: https://renovatebot.com/\n"
  },
  {
    "path": "src/doc/src/guide/creating-a-new-project.md",
    "content": "# Creating a New Package\n\nTo start a new [package][def-package] with Cargo, use `cargo new`:\n\n```console\n$ cargo new hello_world --bin\n```\n\nWe’re passing `--bin` because we’re making a binary program: if we\nwere making a library, we’d pass `--lib`. This also initializes a new `git`\nrepository by default. If you don't want it to do that, pass `--vcs none`.\n\nLet’s check out what Cargo has generated for us:\n\n```console\n$ cd hello_world\n$ tree .\n.\n├── Cargo.toml\n└── src\n    └── main.rs\n\n1 directory, 2 files\n```\n\nLet’s take a closer look at `Cargo.toml`:\n\n```toml\n[package]\nname = \"hello_world\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n\n```\n\nThis is called a [***manifest***][def-manifest], and it contains all of the\nmetadata that Cargo needs to compile your package. This file is written in the\n[TOML] format (pronounced /tɑməl/).\n\nHere’s what’s in `src/main.rs`:\n\n```rust\nfn main() {\n    println!(\"Hello, world!\");\n}\n```\n\nCargo generated a “hello world” program for you, otherwise known as a\n[*binary crate*][def-crate]. Let’s compile it:\n\n```console\n$ cargo build\n   Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)\n```\n\nAnd then run it:\n\n```console\n$ ./target/debug/hello_world\nHello, world!\n```\n\nYou can also use `cargo run` to compile and then run it, all in one step (You\nwon't see the `Compiling` line if you have not made any changes since you last\ncompiled):\n\n```console\n$ cargo run\n   Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)\n     Running `target/debug/hello_world`\nHello, world!\n```\n\nYou’ll now notice a new file, `Cargo.lock`. It contains information about your\ndependencies. Since there are none yet, it’s not very interesting.\n\nOnce you’re ready for release, you can use `cargo build --release` to compile\nyour files with optimizations turned on:\n\n```console\n$ cargo build --release\n   Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)\n```\n\n`cargo build --release` puts the resulting binary in `target/release` instead of\n`target/debug`.\n\nCompiling in debug mode is the default for development. Compilation time is\nshorter since the compiler doesn't do optimizations, but the code will run\nslower. Release mode takes longer to compile, but the code will run faster.\n\n[TOML]: https://toml.io/\n[def-crate]:     ../appendix/glossary.md#crate     '\"crate\" (glossary entry)'\n[def-manifest]:  ../appendix/glossary.md#manifest  '\"manifest\" (glossary entry)'\n[def-package]:   ../appendix/glossary.md#package   '\"package\" (glossary entry)'\n"
  },
  {
    "path": "src/doc/src/guide/dependencies.md",
    "content": "# Dependencies\n\n[crates.io] is the Rust community's central [*package registry*][def-package-registry]\nthat serves as a location to discover and download\n[packages][def-package]. `cargo` is configured to use it by default to find\nrequested packages.\n\nTo depend on a library hosted on [crates.io], add it to your `Cargo.toml`.\n\n[crates.io]: https://crates.io/\n\n## Adding a dependency\n\nIf your `Cargo.toml` doesn't already have a `[dependencies]` section, add\nthat, then list the [crate][def-crate] name and version that you would like to\nuse. This example adds a dependency on the `time` crate:\n\n```toml\n[dependencies]\ntime = \"0.1.12\"\n```\n\nThe version string is a [SemVer] version requirement. The [specifying\ndependencies](../reference/specifying-dependencies.md) docs have more information about\nthe options you have here.\n\n[SemVer]: https://semver.org\n\nIf you also wanted to add a dependency on the `regex` crate, you would not need\nto add `[dependencies]` for each crate listed. Here's what your whole\n`Cargo.toml` file would look like with dependencies on the `time` and `regex`\ncrates:\n\n```toml\n[package]\nname = \"hello_world\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\ntime = \"0.1.12\"\nregex = \"0.1.41\"\n```\n\nRe-run `cargo build`, and Cargo will fetch the new dependencies and all of\ntheir dependencies, compile them all, and update the `Cargo.lock`:\n\n```console\n$ cargo build\n      Updating crates.io index\n   Downloading memchr v0.1.5\n   Downloading libc v0.1.10\n   Downloading regex-syntax v0.2.1\n   Downloading memchr v0.1.5\n   Downloading aho-corasick v0.3.0\n   Downloading regex v0.1.41\n     Compiling memchr v0.1.5\n     Compiling libc v0.1.10\n     Compiling regex-syntax v0.2.1\n     Compiling memchr v0.1.5\n     Compiling aho-corasick v0.3.0\n     Compiling regex v0.1.41\n     Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)\n```\n\n`Cargo.lock` contains the exact information about which revision was used\nfor all of these dependencies.\n\nNow, if `regex` gets updated, you will still build with the same revision until\nyou choose to run `cargo update`.\n\nYou can now use the `regex` library in `main.rs`.\n\n```rust,ignore\nuse regex::Regex;\n\nfn main() {\n    let re = Regex::new(r\"^\\d{4}-\\d{2}-\\d{2}$\").unwrap();\n    println!(\"Did our date match? {}\", re.is_match(\"2014-01-01\"));\n}\n```\n\nRunning it will show:\n\n```console\n$ cargo run\n   Running `target/hello_world`\nDid our date match? true\n```\n\n[def-crate]:             ../appendix/glossary.md#crate             '\"crate\" (glossary entry)'\n[def-package]:           ../appendix/glossary.md#package           '\"package\" (glossary entry)'\n[def-package-registry]:  ../appendix/glossary.md#package-registry  '\"package-registry\" (glossary entry)'\n"
  },
  {
    "path": "src/doc/src/guide/index.md",
    "content": "# Cargo Guide\n\nThis guide will give you all that you need to know about how to use Cargo to\ndevelop Rust packages.\n\n* [Why Cargo Exists](why-cargo-exists.md)\n* [Creating a New Package](creating-a-new-project.md)\n* [Working on an Existing Cargo Package](working-on-an-existing-project.md)\n* [Dependencies](dependencies.md)\n* [Package Layout](project-layout.md)\n* [Cargo.toml vs Cargo.lock](cargo-toml-vs-cargo-lock.md)\n* [Tests](tests.md)\n* [Continuous Integration](continuous-integration.md)\n* [Publishing on crates.io](../reference/publishing.md)\n* [Cargo Home](cargo-home.md)\n* [Optimizing Build Performance](build-performance.md)\n"
  },
  {
    "path": "src/doc/src/guide/project-layout.md",
    "content": "# Package Layout\n\nCargo uses conventions for file placement to make it easy to dive into a new\nCargo [package][def-package]:\n\n```text\n.\n├── Cargo.lock\n├── Cargo.toml\n├── src/\n│   ├── lib.rs\n│   ├── main.rs\n│   └── bin/\n│       ├── named-executable.rs\n│       ├── another-executable.rs\n│       └── multi-file-executable/\n│           ├── main.rs\n│           └── some_module.rs\n├── benches/\n│   ├── large-input.rs\n│   └── multi-file-bench/\n│       ├── main.rs\n│       └── bench_module.rs\n├── examples/\n│   ├── simple.rs\n│   └── multi-file-example/\n│       ├── main.rs\n│       └── ex_module.rs\n└── tests/\n    ├── some-integration-tests.rs\n    └── multi-file-test/\n        ├── main.rs\n        └── test_module.rs\n```\n\n* `Cargo.toml` and `Cargo.lock` are stored in the root of your package (*package\n  root*).\n* Source code goes in the `src` directory.\n* The default library file is `src/lib.rs`.\n* The default executable file is `src/main.rs`.\n    * Other executables can be placed in `src/bin/`.\n* Benchmarks go in the `benches` directory.\n* Examples go in the `examples` directory.\n* Integration tests go in the `tests` directory.\n\nIf a binary, example, bench, or integration test consists of multiple source\nfiles, place a `main.rs` file along with the extra [*modules*][def-module]\nwithin a subdirectory of the `src/bin`, `examples`, `benches`, or `tests`\ndirectory. The name of the executable will be the directory name.\n\n> **Note:** By convention, binaries, examples, benches and integration tests follow `kebab-case` naming style, unless there are compatibility reasons to do otherwise (e.g. compatibility with a pre-existing binary name). Modules within those targets are `snake_case` following the [Rust standard](https://rust-lang.github.io/rfcs/0430-finalizing-naming-conventions.html).\n\nYou can learn more about Rust's module system in [the book][book-modules].\n\nSee [Configuring a target] for more details on manually configuring targets.\nSee [Target auto-discovery] for more information on controlling how Cargo\nautomatically infers target names.\n\n[book-modules]: ../../book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html\n[Configuring a target]: ../reference/cargo-targets.md#configuring-a-target\n[def-package]:           ../appendix/glossary.md#package          '\"package\" (glossary entry)'\n[def-module]:            ../appendix/glossary.md#module           '\"module\" (glossary entry)'\n[Target auto-discovery]: ../reference/cargo-targets.md#target-auto-discovery\n"
  },
  {
    "path": "src/doc/src/guide/tests.md",
    "content": "# Tests\n\nCargo can run your tests with the `cargo test` command. Cargo looks for tests\nto run in two places: in each of your `src` files and any tests in `tests/`.\nTests in your `src` files should be unit tests and [documentation tests].\nTests in `tests/` should be integration-style tests. As such, you’ll need to\nimport your crates into the files in `tests`.\n\nHere's an example of running `cargo test` in our [package][def-package], which\ncurrently has no tests:\n\n```console\n$ cargo test\n   Compiling regex v1.5.0 (https://github.com/rust-lang/regex.git#9f9f693)\n   Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)\n     Running target/test/hello_world-9c2b65bbb79eabce\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out\n```\n\nIf your package had tests, you would see more output with the correct number of\ntests.\n\nYou can also run a specific test by passing a filter:\n\n```console\n$ cargo test foo\n```\n\nThis will run any test with `foo` in its name.\n\n`cargo test` runs additional checks as well. It will compile any examples\nyou’ve included to ensure they still compile. It also runs documentation\ntests to ensure your code samples from documentation comments compile.\nPlease see the [testing guide][testing] in the Rust documentation for a general\nview of writing and organizing tests. See [Cargo Targets: Tests] to learn more\nabout different styles of tests in Cargo.\n\n[documentation tests]: ../../rustdoc/write-documentation/documentation-tests.html\n[def-package]:  ../appendix/glossary.md#package  '\"package\" (glossary entry)'\n[testing]: ../../book/ch11-00-testing.html\n[Cargo Targets: Tests]: ../reference/cargo-targets.html#tests\n"
  },
  {
    "path": "src/doc/src/guide/why-cargo-exists.md",
    "content": "# Why Cargo Exists\n\n## Preliminaries\n\nIn Rust, as you may know, a library or executable program is called a\n[*crate*][def-crate]. Crates are compiled using the Rust compiler,\n`rustc`. When starting with Rust, the first source code most people encounter\nis that of the classic “hello world” program, which they compile by invoking\n`rustc` directly:\n\n```console\n$ rustc hello.rs\n$ ./hello\nHello, world!\n```\n\nNote that the above command required that you specify the file name\nexplicitly. If you were to directly use `rustc` to compile a different program,\na different command line invocation would be required. If you needed to specify\nany specific compiler flags or include external dependencies, then the\nneeded command would be even more specific (and complex).\n\nFurthermore, most non-trivial programs will likely have dependencies on\nexternal libraries, and will therefore also depend transitively on *their*\ndependencies. Obtaining the correct versions of all the necessary dependencies\nand keeping them up to date would be hard and error-prone if done by\nhand.\n\nRather than work only with crates and `rustc`, you can avoid the difficulties\ninvolved with performing the above tasks by introducing a higher-level\n[\"*package*\"][def-package] abstraction and by using a\n[*package manager*][def-package-manager].\n\n## Enter: Cargo\n\n*Cargo* is the Rust package manager. It is a tool that allows Rust\n[*packages*][def-package] to declare their various dependencies and ensure\nthat you’ll always get a repeatable build.\n\nTo accomplish this goal, Cargo does four things:\n\n* Introduces two metadata files with various bits of package information.\n* Fetches and builds your package’s dependencies.\n* Invokes `rustc` or another build tool with the correct parameters to build\n  your package.\n* Introduces conventions to make working with Rust packages easier.\n\nTo a large extent, Cargo normalizes the commands needed to build a given\nprogram or library; this is one aspect to the above mentioned conventions. As\nwe show later, the same command can be used to build different\n[*artifacts*][def-artifact], regardless of their names. Rather than invoke\n`rustc` directly, you can instead invoke something generic such as `cargo\nbuild` and let cargo worry about constructing the correct `rustc`\ninvocation. Furthermore, Cargo will automatically fetch any dependencies\nyou have defined for your artifact from a [*registry*][def-registry],\nand arrange for them to be added into your build as needed.\n\nIt is only a slight exaggeration to say that once you know how to build one\nCargo-based project, you know how to build *all* of them.\n\n[def-artifact]:         ../appendix/glossary.md#artifact         '\"artifact\" (glossary entry)'\n[def-crate]:            ../appendix/glossary.md#crate            '\"crate\" (glossary entry)'\n[def-package]:          ../appendix/glossary.md#package          '\"package\" (glossary entry)'\n[def-package-manager]:  ../appendix/glossary.md#package-manager  '\"package manager\" (glossary entry)'\n[def-registry]:         ../appendix/glossary.md#registry         '\"registry\" (glossary entry)'\n"
  },
  {
    "path": "src/doc/src/guide/working-on-an-existing-project.md",
    "content": "# Working on an Existing Cargo Package\n\nIf you download an existing [package][def-package] that uses Cargo, it’s\nreally easy to get going.\n\nFirst, get the package from somewhere. In this example, we’ll use `regex`\ncloned from its repository on GitHub:\n\n```console\n$ git clone https://github.com/rust-lang/regex.git\n$ cd regex\n```\n\nTo build, use `cargo build`:\n\n```console\n$ cargo build\n   Compiling regex v1.5.0 (file:///path/to/package/regex)\n```\n\nThis will fetch all of the dependencies and then build them, along with the\npackage.\n\n[def-package]:  ../appendix/glossary.md#package  '\"package\" (glossary entry)'\n"
  },
  {
    "path": "src/doc/src/index.md",
    "content": "# The Cargo Book\n\n![Cargo Logo](images/Cargo-Logo-Small.png)\n\nCargo is the [Rust] [*package manager*][def-package-manager]. Cargo downloads your Rust [package][def-package]'s\ndependencies, compiles your packages, makes distributable packages, and uploads them to\n[crates.io], the Rust community’s [*package registry*][def-package-registry]. You can contribute\nto this book on [GitHub].\n\n## Sections\n\n**[Getting Started](getting-started/index.md)**\n\nTo get started with Cargo, install Cargo (and Rust) and set up your first\n[*crate*][def-crate].\n\n**[Cargo Guide](guide/index.md)**\n\nThe guide will give you all you need to know about how to use Cargo to develop\nRust packages.\n\n**[Cargo Reference](reference/index.md)**\n\nThe reference covers the details of various areas of Cargo.\n\n**[Cargo Commands](commands/index.md)**\n\nThe commands will let you interact with Cargo using its command-line interface.\n\n**[Frequently Asked Questions](faq.md)**\n\n**Appendices:**\n* [Glossary](appendix/glossary.md)\n* [Git Authentication](appendix/git-authentication.md)\n\n**Other Documentation:**\n* [Changelog](CHANGELOG.md)\n  --- Detailed notes about changes in Cargo in each release.\n* [Rust documentation website](https://doc.rust-lang.org/) --- Links to official\n  Rust documentation and tools.\n\n[def-crate]:            ./appendix/glossary.md#crate            '\"crate\" (glossary entry)'\n[def-package]:          ./appendix/glossary.md#package          '\"package\" (glossary entry)'\n[def-package-manager]:  ./appendix/glossary.md#package-manager  '\"package manager\" (glossary entry)'\n[def-package-registry]: ./appendix/glossary.md#package-registry '\"package registry\" (glossary entry)'\n[rust]: https://www.rust-lang.org/\n[crates.io]: https://crates.io/\n[GitHub]: https://github.com/rust-lang/cargo/tree/master/src/doc\n"
  },
  {
    "path": "src/doc/src/reference/build-cache.md",
    "content": "# Build cache\n\nCargo stores the output of a build into the \"target\" and \"build\" directories. By default,\nboth directories point to a directory named `target` in the root of your\n[*workspace*][def-workspace]. To change the location of the target-dir, you can set the\n`CARGO_TARGET_DIR` [environment variable], the [`build.target-dir`] config\nvalue, or the `--target-dir` command-line flag. To change the location of the build-dir, you can set the\n`CARGO_BUILD_BUILD_DIR` [environment variable] or the [`build.build-dir`] config value.\n\nArtifacts are split in two categories:\n* Final build artifacts\n  * Final build artifacts are output meant for end users of Cargo\n  * e.g. binaries for bin crates, output of `cargo doc`, Cargo `--timings` reports\n  * Stored in the target-dir\n* Intermediate build artifacts\n  * Intermediate build artifacts are internal to Cargo and the Rust compiler\n  * End users will generally not need to interact with intermediate build artifacts\n  * Stored in the Cargo build-dir\n\nThe directory layout depends on whether or not you are using the `--target`\nflag to build for a specific platform. If `--target` is not specified, Cargo\nruns in a mode where it builds for the host architecture. The output goes into\nthe root of the target directory, with each [profile] stored in a separate\nsubdirectory:\n\nDirectory | Description\n----------|------------\n<code style=\"white-space: nowrap\">target/debug/</code> | Contains output for the `dev` profile.\n<code style=\"white-space: nowrap\">target/release/</code> | Contains output for the `release` profile (with the `--release` option).\n<code style=\"white-space: nowrap\">target/foo/</code> | Contains build output for the `foo` profile (with the `--profile=foo` option).\n\nFor historical reasons, the `dev` and `test` profiles are stored in the\n`debug` directory, and the `release` and `bench` profiles are stored in the\n`release` directory. User-defined profiles are stored in a directory with the\nsame name as the profile.\n\nWhen building for another target with `--target`, the output is placed in a\ndirectory with the name of the [target]:\n\nDirectory | Example\n----------|--------\n<code style=\"white-space: nowrap\">target/&lt;triple&gt;/debug/</code> | <code style=\"white-space: nowrap\">target/thumbv7em-none-eabihf/debug/</code>\n<code style=\"white-space: nowrap\">target/&lt;triple&gt;/release/</code> | <code style=\"white-space: nowrap\">target/thumbv7em-none-eabihf/release/</code>\n\n> **Note**: When not using `--target`, this has a consequence that Cargo will\n> share your dependencies with build scripts and proc macros. [`RUSTFLAGS`]\n> will be shared with every `rustc` invocation. With the `--target` flag,\n> build scripts and proc macros are built separately (for the host\n> architecture), and do not share `RUSTFLAGS`.\n\nWithin the profile directory (such as `debug` or `release`), artifacts are\nplaced into the following directories:\n\nDirectory | Description\n----------|------------\n<code style=\"white-space: nowrap\">target/debug/</code> | Contains the output of the package being built (the [binary executables] and [library targets]).\n<code style=\"white-space: nowrap\">target/debug/examples/</code> | Contains [example targets].\n\nSome commands place their output in dedicated directories in the top level of\nthe `target` directory:\n\nDirectory | Description\n----------|------------\n<code style=\"white-space: nowrap\">target/doc/</code> | Contains rustdoc documentation ([`cargo doc`]).\n<code style=\"white-space: nowrap\">target/package/</code> | Contains the output of the [`cargo package`].\n\nCargo also creates several other directories and files in the build-dir needed for the build\nprocess. The build-dir layout is considered internal to Cargo, and is subject to\nchange. Some of these directories are:\n\nDirectory | Description\n----------|------------\n<code style=\"white-space: nowrap\">\\<build-dir>/debug/deps/</code> | Dependencies and other artifacts.\n<code style=\"white-space: nowrap\">\\<build-dir>/debug/incremental/</code> | `rustc` [incremental output], a cache used to speed up subsequent builds.\n<code style=\"white-space: nowrap\">\\<build-dir>/debug/build/</code> | Output from [build scripts].\n\n## Dep-info files\n\nNext to each compiled artifact is a file called a \"dep info\" file with a `.d`\nsuffix. This file is a Makefile-like syntax that indicates all of the file\ndependencies required to rebuild the artifact. These are intended to be used\nwith external build systems so that they can detect if Cargo needs to be\nre-executed. The paths in the file are absolute by default. See the\n[`build.dep-info-basedir`] config option to use relative paths.\n\n```Makefile\n# Example dep-info file found in target/debug/foo.d\n/path/to/myproj/target/debug/foo: /path/to/myproj/src/lib.rs /path/to/myproj/src/main.rs\n```\n\n## Shared cache\n\nA third party tool, [sccache], can be used to share built dependencies across\ndifferent workspaces.\n\nTo setup `sccache`, install it with `cargo install sccache` and set\n`RUSTC_WRAPPER` environment variable to `sccache` before invoking Cargo. If\nyou use bash, it makes sense to add `export RUSTC_WRAPPER=sccache` to\n`.bashrc`. Alternatively, you can set [`build.rustc-wrapper`] in the [Cargo\nconfiguration][config]. Refer to sccache documentation for more details.\n\n[`RUSTFLAGS`]: ../reference/config.md#buildrustflags\n[`build.dep-info-basedir`]: ../reference/config.md#builddep-info-basedir\n[`build.rustc-wrapper`]: ../reference/config.md#buildrustc-wrapper\n[`build.target-dir`]: ../reference/config.md#buildtarget-dir\n[`build.build-dir`]: ../reference/config.md#buildbuild-dir\n[`cargo doc`]: ../commands/cargo-doc.md\n[`cargo package`]: ../commands/cargo-package.md\n[`cargo publish`]: ../commands/cargo-publish.md\n[build scripts]: ../reference/build-scripts.md\n[config]: ../reference/config.md\n[def-workspace]:  ../appendix/glossary.md#workspace  '\"workspace\" (glossary entry)'\n[target]: ../appendix/glossary.md#target '\"target\" (glossary entry)'\n[environment variable]: ../reference/environment-variables.md\n[incremental output]: ../reference/profiles.md#incremental\n[sccache]: https://github.com/mozilla/sccache\n[profile]: ../reference/profiles.md\n[binary executables]: ../reference/cargo-targets.md#binaries\n[library targets]: ../reference/cargo-targets.md#library\n[example targets]: ../reference/cargo-targets.md#examples\n"
  },
  {
    "path": "src/doc/src/reference/build-script-examples.md",
    "content": "# Build Script Examples\n\nThe following sections illustrate some examples of writing build scripts.\n\nSome common build script functionality can be found via crates on [crates.io].\nCheck out the [`build-dependencies`\nkeyword](https://crates.io/keywords/build-dependencies) to see what is\navailable. The following is a sample of some popular crates[^†]:\n\n* [`bindgen`](https://crates.io/crates/bindgen) --- Automatically generate Rust\n  FFI bindings to C libraries.\n* [`cc`](https://crates.io/crates/cc) --- Compiles C/C++/assembly.\n* [`pkg-config`](https://crates.io/crates/pkg-config) --- Detect system\n  libraries using the `pkg-config` utility.\n* [`cmake`](https://crates.io/crates/cmake) --- Runs the `cmake` build tool to build a native library.\n* [`autocfg`](https://crates.io/crates/autocfg),\n  [`rustc_version`](https://crates.io/crates/rustc_version),\n  [`version_check`](https://crates.io/crates/version_check) --- These crates\n  provide ways to implement conditional compilation based on the current\n  `rustc` such as the version of the compiler.\n\n[^†]: This list is not an endorsement. Evaluate your dependencies to see which\nis right for your project.\n\n## Code generation\n\nSome Cargo packages need to have code generated just before they are compiled\nfor various reasons. Here we’ll walk through a simple example which generates a\nlibrary call as part of the build script.\n\nFirst, let’s take a look at the directory structure of this package:\n\n```text\n.\n├── Cargo.toml\n├── build.rs\n└── src\n    └── main.rs\n\n1 directory, 3 files\n```\n\nHere we can see that we have a `build.rs` build script and our binary in\n`main.rs`. This package has a basic manifest:\n\n```toml\n# Cargo.toml\n\n[package]\nname = \"hello-from-generated-code\"\nversion = \"0.1.0\"\nedition = \"2024\"\n```\n\nLet’s see what’s inside the build script:\n\n```rust,no_run\n// build.rs\n\nuse std::env;\nuse std::fs;\nuse std::path::Path;\n\nfn main() {\n    let out_dir = env::var_os(\"OUT_DIR\").unwrap();\n    let dest_path = Path::new(&out_dir).join(\"hello.rs\");\n    fs::write(\n        &dest_path,\n        \"pub fn message() -> &'static str {\n            \\\"Hello, World!\\\"\n        }\n        \"\n    ).unwrap();\n    println!(\"cargo::rerun-if-changed=build.rs\");\n}\n```\n\nThere’s a couple of points of note here:\n\n* The script uses the `OUT_DIR` environment variable to discover where the\n  output files should be located. It can use the process’ current working\n  directory to find where the input files should be located, but in this case we\n  don’t have any input files.\n* In general, build scripts should not modify any files outside of `OUT_DIR`.\n  It may seem fine on the first blush, but it does cause problems when you use\n  such crate as a dependency, because there's an *implicit* invariant that\n  sources in `.cargo/registry` should be immutable. `cargo` won't allow such\n  scripts when packaging.\n  * Sometimes, projects want to check in a generated file, and treat it as\n    source code. However, in this case, the file shouldn't be generated from\n    `build.rs`. Instead, have a test or similar which checks that the file\n    precisely matches the generated version *and fails if the result doesn't\n    match*, and run that test as part of your CI. (The test can generate a\n    temporary file to compare to, and if you want to update the generated file,\n    you can replace the checked-in file with that temporary file.)\n* This script is relatively simple as it just writes out a small generated file.\n  One could imagine that other more complex operations could take place such as\n  generating a Rust module from a C header file or another language definition,\n  for example.\n* The [`rerun-if-changed` instruction](build-scripts.md#rerun-if-changed)\n  tells Cargo that the build script only needs to re-run if the build script\n  itself changes. Without this line, Cargo will automatically run the build\n  script if any file in the package changes. If your code generation uses some\n  input files, this is where you would print a list of each of those files.\n\nNext, let’s peek at the library itself:\n\n```rust,ignore\n// src/main.rs\n\ninclude!(concat!(env!(\"OUT_DIR\"), \"/hello.rs\"));\n\nfn main() {\n    println!(\"{}\", message());\n}\n```\n\nThis is where the real magic happens. The library is using the rustc-defined\n[`include!` macro][include-macro] in combination with the\n[`concat!`][concat-macro] and [`env!`][env-macro] macros to include the\ngenerated file (`hello.rs`) into the crate’s compilation.\n\nUsing the structure shown here, crates can include any number of generated files\nfrom the build script itself.\n\n[include-macro]: ../../std/macro.include.html\n[concat-macro]: ../../std/macro.concat.html\n[env-macro]: ../../std/macro.env.html\n\n## Building a native library\n\nSometimes it’s necessary to build some native C or C++ code as part of a\npackage. This is another excellent use case of leveraging the build script to\nbuild a native library before the Rust crate itself. As an example, we’ll create\na Rust library which calls into C to print “Hello, World!”.\n\nLike above, let’s first take a look at the package layout:\n\n```text\n.\n├── Cargo.toml\n├── build.rs\n└── src\n    ├── hello.c\n    └── main.rs\n\n1 directory, 4 files\n```\n\nPretty similar to before! Next, the manifest:\n\n```toml\n# Cargo.toml\n\n[package]\nname = \"hello-world-from-c\"\nversion = \"0.1.0\"\nedition = \"2024\"\n```\n\nFor now we’re not going to use any build dependencies, so let’s take a look at\nthe build script now:\n\n```rust,no_run\n// build.rs\n\nuse std::process::Command;\nuse std::env;\nuse std::path::Path;\n\nfn main() {\n    let out_dir = env::var(\"OUT_DIR\").unwrap();\n\n    // Note that there are a number of downsides to this approach, the comments\n    // below detail how to improve the portability of these commands.\n    Command::new(\"gcc\").args(&[\"src/hello.c\", \"-c\", \"-fPIC\", \"-o\"])\n                       .arg(&format!(\"{}/hello.o\", out_dir))\n                       .status().unwrap();\n    Command::new(\"ar\").args(&[\"crus\", \"libhello.a\", \"hello.o\"])\n                      .current_dir(&Path::new(&out_dir))\n                      .status().unwrap();\n\n    println!(\"cargo::rustc-link-search=native={}\", out_dir);\n    println!(\"cargo::rustc-link-lib=static=hello\");\n    println!(\"cargo::rerun-if-changed=src/hello.c\");\n}\n```\n\nThis build script starts out by compiling our C file into an object file (by\ninvoking `gcc`) and then converting this object file into a static library (by\ninvoking `ar`). The final step is feedback to Cargo itself to say that our\noutput was in `out_dir` and the compiler should link the crate to `libhello.a`\nstatically via the `-l static=hello` flag.\n\nNote that there are a number of drawbacks to this hard-coded approach:\n\n* The `gcc` command itself is not portable across platforms. For example it’s\n  unlikely that Windows platforms have `gcc`, and not even all Unix platforms\n  may have `gcc`. The `ar` command is also in a similar situation.\n* These commands do not take cross-compilation into account. If we’re cross\n  compiling for a platform such as Android it’s unlikely that `gcc` will produce\n  an ARM executable.\n\nNot to fear, though, this is where a `build-dependencies` entry would help!\nThe Cargo ecosystem has a number of packages to make this sort of task much\neasier, portable, and standardized. Let's try the [`cc`\ncrate](https://crates.io/crates/cc) from [crates.io]. First, add it to the\n`build-dependencies` in `Cargo.toml`:\n\n```toml\n[build-dependencies]\ncc = \"1.0\"\n```\n\nAnd rewrite the build script to use this crate:\n\n```rust,ignore\n// build.rs\n\nfn main() {\n    cc::Build::new()\n        .file(\"src/hello.c\")\n        .compile(\"hello\");\n    println!(\"cargo::rerun-if-changed=src/hello.c\");\n}\n```\n\nThe [`cc` crate] abstracts a range of build script requirements for C code:\n\n* It invokes the appropriate compiler (MSVC for windows, `gcc` for MinGW, `cc`\n  for Unix platforms, etc.).\n* It takes the `TARGET` variable into account by passing appropriate flags to\n  the compiler being used.\n* Other environment variables, such as `OPT_LEVEL`, `DEBUG`, etc., are all\n  handled automatically.\n* The stdout output and `OUT_DIR` locations are also handled by the `cc`\n  library.\n\nHere we can start to see some of the major benefits of farming as much\nfunctionality as possible out to common build dependencies rather than\nduplicating logic across all build scripts!\n\nBack to the case study though, let’s take a quick look at the contents of the\n`src` directory:\n\n```c\n// src/hello.c\n\n#include <stdio.h>\n\nvoid hello() {\n    printf(\"Hello, World!\\n\");\n}\n```\n\n```rust,ignore\n// src/main.rs\n\n// Note the lack of the `#[link]` attribute. We’re delegating the responsibility\n// of selecting what to link over to the build script rather than hard-coding\n// it in the source file.\nunsafe extern { fn hello(); }\n\nfn main() {\n    unsafe { hello(); }\n}\n```\n\nAnd there we go! This should complete our example of building some C code from a\nCargo package using the build script itself. This also shows why using a build\ndependency can be crucial in many situations and even much more concise!\n\nWe’ve also seen a brief example of how a build script can use a crate as a\ndependency purely for the build process and not for the crate itself at runtime.\n\n[`cc` crate]: https://crates.io/crates/cc\n\n## Linking to system libraries\n\nThis example demonstrates how to link a system library and how the build\nscript is used to support this use case.\n\nQuite frequently a Rust crate wants to link to a native library provided on\nthe system to bind its functionality or just use it as part of an\nimplementation detail. This is quite a nuanced problem when it comes to\nperforming this in a platform-agnostic fashion. It is best, if possible, to\nfarm out as much of this as possible to make this as easy as possible for\nconsumers.\n\nFor this example, we will be creating a binding to the system's zlib library.\nThis is a library that is commonly found on most Unix-like systems that\nprovides data compression. This is already wrapped up in the [`libz-sys`\ncrate], but for this example, we'll do an extremely simplified version. Check\nout [the source code][libz-source] for the full example.\n\nTo make it easy to find the location of the library, we will use the\n[`pkg-config` crate]. This crate uses the system's `pkg-config` utility to\ndiscover information about a library. It will automatically tell Cargo what is\nneeded to link the library. This will likely only work on Unix-like systems\nwith `pkg-config` installed. Let's start by setting up the manifest:\n\n```toml\n# Cargo.toml\n\n[package]\nname = \"libz-sys\"\nversion = \"0.1.0\"\nedition = \"2024\"\nlinks = \"z\"\n\n[build-dependencies]\npkg-config = \"0.3.16\"\n```\n\nTake note that we included the `links` key in the `package` table. This tells\nCargo that we are linking to the `libz` library. See [\"Using another sys\ncrate\"](#using-another-sys-crate) for an example that will leverage this.\n\nThe build script is fairly simple:\n\n```rust,ignore\n// build.rs\n\nfn main() {\n    pkg_config::Config::new().probe(\"zlib\").unwrap();\n    println!(\"cargo::rerun-if-changed=build.rs\");\n}\n```\n\nLet's round out the example with a basic FFI binding:\n\n```rust,ignore\n// src/lib.rs\n\nuse std::os::raw::{c_uint, c_ulong};\n\nunsafe extern \"C\" {\n    pub fn crc32(crc: c_ulong, buf: *const u8, len: c_uint) -> c_ulong;\n}\n\n#[test]\nfn test_crc32() {\n    let s = \"hello\";\n    unsafe {\n        assert_eq!(crc32(0, s.as_ptr(), s.len() as c_uint), 0x3610a686);\n    }\n}\n```\n\nRun `cargo build -vv` to see the output from the build script. On a system\nwith `libz` already installed, it may look something like this:\n\n```text\n[libz-sys 0.1.0] cargo::rustc-link-search=native=/usr/lib\n[libz-sys 0.1.0] cargo::rustc-link-lib=z\n[libz-sys 0.1.0] cargo::rerun-if-changed=build.rs\n```\n\nNice! `pkg-config` did all the work of finding the library and telling Cargo\nwhere it is.\n\nIt is not unusual for packages to include the source for the library, and\nbuild it statically if it is not found on the system, or if a feature or\nenvironment variable is set. For example, the real [`libz-sys` crate] checks the\nenvironment variable `LIBZ_SYS_STATIC` or the `static` feature to build it\nfrom source instead of using the system library. Check out [the\nsource][libz-source] for a more complete example.\n\n[`libz-sys` crate]: https://crates.io/crates/libz-sys\n[`pkg-config` crate]: https://crates.io/crates/pkg-config\n[libz-source]: https://github.com/rust-lang/libz-sys\n\n## Using another `sys` crate\n\nWhen using the `links` key, crates may set metadata that can be read by other\ncrates that depend on it. This provides a mechanism to communicate information\nbetween crates. In this example, we'll be creating a C library that makes use\nof zlib from the real [`libz-sys` crate].\n\nIf you have a C library that depends on zlib, you can leverage the [`libz-sys`\ncrate] to automatically find it or build it. This is great for cross-platform\nsupport, such as Windows where zlib is not usually installed. `libz-sys` [sets\nthe `include`\nmetadata](https://github.com/rust-lang/libz-sys/blob/3c594e677c79584500da673f918c4d2101ac97a1/build.rs#L156)\nto tell other packages where to find the header files for zlib. Our build\nscript can read that metadata with the `DEP_Z_INCLUDE` environment variable.\nHere's an example:\n\n```toml\n# Cargo.toml\n\n[package]\nname = \"z_user\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\nlibz-sys = \"1.0.25\"\n\n[build-dependencies]\ncc = \"1.0.46\"\n```\n\nHere we have included `libz-sys` which will ensure that there is only one\n`libz` used in the final library, and give us access to it from our build\nscript:\n\n```rust,ignore\n// build.rs\n\nfn main() {\n    let mut cfg = cc::Build::new();\n    cfg.file(\"src/z_user.c\");\n    if let Some(include) = std::env::var_os(\"DEP_Z_INCLUDE\") {\n        cfg.include(include);\n    }\n    cfg.compile(\"z_user\");\n    println!(\"cargo::rerun-if-changed=src/z_user.c\");\n}\n```\n\nWith `libz-sys` doing all the heavy lifting, the C source code may now include\nthe zlib header, and it should find the header, even on systems where it isn't\nalready installed.\n\n```c\n// src/z_user.c\n\n#include \"zlib.h\"\n\n// … rest of code that makes use of zlib.\n```\n## Reading target configuration\n\nWhen a build script needs to make decisions based on the target platform, it should read the `CARGO_CFG_*` environment\nvariables rather than using `cfg!` or `#[cfg]` attributes. This is because\nthe build script is compiled for and runs on the *host* machine, while\n`CARGO_CFG_*` variables reflect the *target* platform, an important distinction\nwhen cross-compiling.\n```rust,ignore\n// build.rs\n\nfn main() {\n    // reads the TARGET configuration\n    let target_os = std::env::var(\"CARGO_CFG_TARGET_OS\").unwrap();\n\n    if target_os == \"windows\" {\n        println!(\"cargo::rustc-link-lib=userenv\");\n    } else if target_os == \"linux\" {\n        println!(\"cargo::rustc-link-lib=pthread\");\n    }\n}\n```\n\nNote that some configuration values may contain multiple values separated by\ncommas (for example, `CARGO_CFG_TARGET_FAMILY` may be `unix,wasm`). When\nchecking these values, be sure to handle this appropriately.\n\nFor a more convenient, typed API, consider using the [`build-rs`] crate\nwhich handles these details for you.\n\n[`build-rs`]: https://crates.io/crates/build-rs\n\n## Conditional compilation\n\nA build script may emit [`rustc-cfg` instructions] which can enable conditions\nthat can be checked at compile time. In this example, we'll take a look at how\nthe [`openssl` crate] uses this to support multiple versions of the OpenSSL\nlibrary.\n\nThe [`openssl-sys` crate] implements building and linking the OpenSSL library.\nIt supports multiple different implementations (like LibreSSL) and multiple\nversions. It makes use of the `links` key so that it may pass information to\nother build scripts. One of the things it passes is the `version_number` key,\nwhich is the version of OpenSSL that was detected. The code in the build\nscript looks something [like\nthis](https://github.com/sfackler/rust-openssl/blob/dc72a8e2c429e46c275e528b61a733a66e7877fc/openssl-sys/build/main.rs#L216):\n\n```rust,ignore\nprintln!(\"cargo::metadata=version_number={openssl_version:x}\");\n```\n\nThis instruction causes the `DEP_OPENSSL_VERSION_NUMBER` environment variable\nto be set in any crates that directly depend on `openssl-sys`.\n\nThe `openssl` crate, which provides the higher-level interface, specifies\n`openssl-sys` as a dependency. The `openssl` build script can read the\nversion information generated by the `openssl-sys` build script with the\n`DEP_OPENSSL_VERSION_NUMBER` environment variable. It uses this to generate\nsome [`cfg`\nvalues](https://github.com/sfackler/rust-openssl/blob/dc72a8e2c429e46c275e528b61a733a66e7877fc/openssl/build.rs#L18-L36):\n\n```rust,ignore\n// (portion of build.rs)\n\nprintln!(\"cargo::rustc-check-cfg=cfg(ossl101,ossl102)\");\nprintln!(\"cargo::rustc-check-cfg=cfg(ossl110,ossl110g,ossl111)\");\n\nif let Ok(version) = env::var(\"DEP_OPENSSL_VERSION_NUMBER\") {\n    let version = u64::from_str_radix(&version, 16).unwrap();\n\n    if version >= 0x1_00_01_00_0 {\n        println!(\"cargo::rustc-cfg=ossl101\");\n    }\n    if version >= 0x1_00_02_00_0 {\n        println!(\"cargo::rustc-cfg=ossl102\");\n    }\n    if version >= 0x1_01_00_00_0 {\n        println!(\"cargo::rustc-cfg=ossl110\");\n    }\n    if version >= 0x1_01_00_07_0 {\n        println!(\"cargo::rustc-cfg=ossl110g\");\n    }\n    if version >= 0x1_01_01_00_0 {\n        println!(\"cargo::rustc-cfg=ossl111\");\n    }\n}\n```\n\nThese `cfg` values can then be used with the [`cfg` attribute] or the [`cfg`\nmacro] to conditionally include code. For example, SHA3 support was added in\nOpenSSL 1.1.1, so it is [conditionally\nexcluded](https://github.com/sfackler/rust-openssl/blob/dc72a8e2c429e46c275e528b61a733a66e7877fc/openssl/src/hash.rs#L67-L85)\nfor older versions:\n\n```rust,ignore\n// (portion of openssl crate)\n\n#[cfg(ossl111)]\npub fn sha3_224() -> MessageDigest {\n    unsafe { MessageDigest(ffi::EVP_sha3_224()) }\n}\n```\n\nOf course, one should be careful when using this, since it makes the resulting\nbinary even more dependent on the build environment. In this example, if the\nbinary is distributed to another system, it may not have the exact same shared\nlibraries, which could cause problems.\n\n[`cfg` attribute]: ../../reference/conditional-compilation.md#the-cfg-attribute\n[`cfg` macro]: ../../std/macro.cfg.html\n[`rustc-cfg` instructions]: build-scripts.md#rustc-cfg\n[`openssl` crate]: https://crates.io/crates/openssl\n[`openssl-sys` crate]: https://crates.io/crates/openssl-sys\n\n[crates.io]: https://crates.io/\n"
  },
  {
    "path": "src/doc/src/reference/build-scripts.md",
    "content": "# Build Scripts\n\nSome packages need to compile third-party non-Rust code, for example C\nlibraries. Other packages need to link to C libraries which can either be\nlocated on the system or possibly need to be built from source. Others still\nneed facilities for functionality such as code generation before building (think\nparser generators).\n\nCargo does not aim to replace other tools that are well-optimized for these\ntasks, but it does integrate with them with custom build scripts. Placing a\nfile named `build.rs` in the root of a package will cause Cargo to compile\nthat script and execute it just before building the package.\n\n```rust,ignore\n// Example custom build script.\nfn main() {\n    // Tell Cargo that if the given file changes, to rerun this build script.\n    println!(\"cargo::rerun-if-changed=src/hello.c\");\n    // Use the `cc` crate to build a C file and statically link it.\n    cc::Build::new()\n        .file(\"src/hello.c\")\n        .compile(\"hello\");\n}\n```\n\nSome example use cases of build scripts are:\n\n* Building a bundled C library.\n* Finding a C library on the host system.\n* Generating a Rust module from a specification.\n* Performing any platform-specific configuration needed for the crate.\n\nThe sections below describe how build scripts work, and the [examples\nchapter](build-script-examples.md) shows a variety of examples on how to write\nscripts.\n\n> Note: The [`package.build` manifest key](manifest.md#the-build-field) can be\n> used to change the name of the build script, or disable it entirely.\n\n## Life Cycle of a Build Script\n\nJust before a package is built, Cargo will compile a build script into an\nexecutable (if it has not already been built). It will then run the script,\nwhich may perform any number of tasks. The script may communicate with Cargo\nby printing specially formatted commands prefixed with `cargo::` to stdout.\n\nThe build script will be rebuilt if any of its source files or dependencies\nchange.\n\nBy default, Cargo will re-run the build script if any of the files in the\npackage changes. Typically it is best to use the `rerun-if` commands,\ndescribed in the [change detection](#change-detection) section below, to\nnarrow the focus of what triggers a build script to run again.\n\nOnce the build script successfully finishes executing, the rest of the package\nwill be compiled. Scripts should exit with a non-zero exit code to halt the\nbuild if there is an error, in which case the build script's output will be\ndisplayed on the terminal.\n\n## Inputs to the Build Script\n\nWhen the build script is run, there are a number of inputs to the build script,\nall passed in the form of [environment variables][build-env].\n\nIn addition to environment variables, the build script’s current directory is\nthe root directory of the build script’s package.\n\n[build-env]: environment-variables.md#environment-variables-cargo-sets-for-build-scripts\n\n> **Note:** When checking [configuration options] like `target_os` or `target_arch`\n> in a build script, do not use the `cfg!` macro or `#[cfg]` attribute, these\n> check the **host** machine (where the build script runs), not the **target**\n> platform you're compiling for. This distinction matters when cross-compiling.\n>\n> Instead, read the corresponding [`CARGO_CFG_*`][build-env] environment variables,\n> which correctly reflect the target's configuration. For a typed API, consider\n> using the [`build-rs`] crate. See the [build script examples] for more details.\n\n[configuration options]: ../../reference/conditional-compilation.html\n[`build-rs`]: https://crates.io/crates/build-rs\n[build script examples]: build-script-examples.md#conditional-compilation\n\n## Outputs of the Build Script\n\nBuild scripts may save any output files or intermediate artifacts in the\ndirectory specified in the [`OUT_DIR` environment variable][build-env]. Scripts\nshould not modify any files outside of that directory.\n\n> **Note:** Cargo does not clean or reset `OUT_DIR` between builds. The contents\n> of this directory may persist across rebuilds, even if the build script is\n> re-run. This behavior is intentional to support incremental builds, such as\n> native code compilation.\n>\n>Build scripts should not rely on `OUT_DIR` being empty, as its contents may\n>persist across rebuilds. If a script requires a clean directory, it is currently\n>responsible for managing or cleaning up any files or subdirectories it creates.\n>Future improvements in this area are being discussed (see\n>[#16427](https://github.com/rust-lang/cargo/issues/16427) and\n>[#9661](https://github.com/rust-lang/cargo/issues/9661)).\n\nBuild scripts communicate with Cargo by printing to stdout. Cargo will\ninterpret each line that starts with `cargo::` as an instruction that will\ninfluence compilation of the package. All other lines are ignored.\n\n> The order of `cargo::` instructions printed by the build script *may*\n> affect the order of arguments that `cargo` passes to `rustc`. In turn, the\n> order of arguments passed to `rustc` may affect the order of arguments passed\n> to the linker. Therefore, you will want to pay attention to the order of the\n> build script's instructions. For example, if object `foo` needs to link against\n> library `bar`, you may want to make sure that library `bar`'s\n> [`cargo::rustc-link-lib`](#rustc-link-lib) instruction appears *after*\n> instructions to link object `foo`.\n\nThe output of the script is hidden from the terminal during normal\ncompilation. If you would like to see the output directly in your terminal,\ninvoke Cargo as \"very verbose\" with the `-vv` flag. This only happens when the\nbuild script is run. If Cargo determines nothing has changed, it will not\nre-run the script, see [change detection](#change-detection) below for more.\n\nAll the lines printed to stdout by a build script are written to a file like\n`target/debug/build/<pkg>/output` (the precise location may depend on your\nconfiguration). The stderr output is also saved in that same directory.\n\nThe following is a summary of the instructions that Cargo recognizes, with each\none detailed below.\n\n* [`cargo::rerun-if-changed=PATH`](#rerun-if-changed) --- Tells Cargo when to\n  re-run the script.\n* [`cargo::rerun-if-env-changed=VAR`](#rerun-if-env-changed) --- Tells Cargo when\n  to re-run the script.\n* [`cargo::rustc-link-arg=FLAG`](#rustc-link-arg) --- Passes custom flags to a\n  linker for benchmarks, binaries, `cdylib` crates, examples, and tests.\n* [`cargo::rustc-link-arg-cdylib=FLAG`](#rustc-cdylib-link-arg) --- Passes custom\n  flags to a linker for cdylib crates.\n* [`cargo::rustc-link-arg-bin=BIN=FLAG`](#rustc-link-arg-bin) --- Passes custom\n  flags to a linker for the binary `BIN`.\n* [`cargo::rustc-link-arg-bins=FLAG`](#rustc-link-arg-bins) --- Passes custom\n  flags to a linker for binaries.\n* [`cargo::rustc-link-arg-tests=FLAG`](#rustc-link-arg-tests) --- Passes custom\n  flags to a linker for tests.\n* [`cargo::rustc-link-arg-examples=FLAG`](#rustc-link-arg-examples) --- Passes custom\n  flags to a linker for examples.\n* [`cargo::rustc-link-arg-benches=FLAG`](#rustc-link-arg-benches) --- Passes custom\n  flags to a linker for benchmarks.\n* [`cargo::rustc-link-lib=LIB`](#rustc-link-lib) --- Adds a library to\n  link.\n* [`cargo::rustc-link-search=[KIND=]PATH`](#rustc-link-search) --- Adds to the\n  library search path.\n* [`cargo::rustc-flags=FLAGS`](#rustc-flags) --- Passes certain flags to the\n  compiler.\n* [`cargo::rustc-cfg=KEY[=\"VALUE\"]`](#rustc-cfg) --- Enables compile-time `cfg`\n  settings.\n* [`cargo::rustc-check-cfg=CHECK_CFG`](#rustc-check-cfg) -- Register custom `cfg`s as\n  expected for compile-time checking of configs. \n* [`cargo::rustc-env=VAR=VALUE`](#rustc-env) --- Sets an environment variable.\n- [`cargo::error=MESSAGE`](#cargo-error) --- Displays an error on the terminal.\n* [`cargo::warning=MESSAGE`](#cargo-warning) --- Displays a warning on the\n  terminal.\n* [`cargo::metadata=KEY=VALUE`](#the-links-manifest-key) --- Metadata, used by `links`\n  scripts.\n\n> **MSRV:** 1.77 is required for `cargo::KEY=VALUE` syntax.\n> To support older versions, use the `cargo:KEY=VALUE` syntax.\n\n### `cargo::rustc-link-arg=FLAG` {#rustc-link-arg}\n\nThe `rustc-link-arg` instruction tells Cargo to pass the [`-C link-arg=FLAG`\noption][link-arg] to the compiler, but only when building supported targets\n(benchmarks, binaries, `cdylib` crates, examples, and tests). Its usage is\nhighly platform specific. It is useful to set the shared library version or\nlinker script.\n\n[link-arg]: ../../rustc/codegen-options/index.md#link-arg\n\n### `cargo::rustc-link-arg-cdylib=FLAG` {#rustc-cdylib-link-arg}\n\nThe `rustc-link-arg-cdylib` instruction tells Cargo to pass the [`-C\nlink-arg=FLAG` option][link-arg] to the compiler, but only when building a\n`cdylib` library target. Its usage is highly platform specific. It is useful\nto set the shared library version or the runtime-path.\n\nFor historical reasons, the `cargo::rustc-cdylib-link-arg` form is an alias\nfor `cargo::rustc-link-arg-cdylib`, and has the same meaning.\n\n### `cargo::rustc-link-arg-bin=BIN=FLAG` {#rustc-link-arg-bin}\n\nThe `rustc-link-arg-bin` instruction tells Cargo to pass the [`-C\nlink-arg=FLAG` option][link-arg] to the compiler, but only when building\nthe binary target with name `BIN`. Its usage is highly platform specific. It is useful\nto set a linker script or other linker options.\n\n### `cargo::rustc-link-arg-bins=FLAG` {#rustc-link-arg-bins}\n\nThe `rustc-link-arg-bins` instruction tells Cargo to pass the [`-C\nlink-arg=FLAG` option][link-arg] to the compiler, but only when building a\nbinary target. Its usage is highly platform specific. It is useful\nto set a linker script or other linker options.\n\n### `cargo::rustc-link-arg-tests=FLAG` {#rustc-link-arg-tests}\n\nThe `rustc-link-arg-tests` instruction tells Cargo to pass the [`-C\nlink-arg=FLAG` option][link-arg] to the compiler, but only when building a\ntests target.\n\n### `cargo::rustc-link-arg-examples=FLAG` {#rustc-link-arg-examples}\n\nThe `rustc-link-arg-examples` instruction tells Cargo to pass the [`-C\nlink-arg=FLAG` option][link-arg] to the compiler, but only when building an examples\ntarget.\n\n### `cargo::rustc-link-arg-benches=FLAG` {#rustc-link-arg-benches}\n\nThe `rustc-link-arg-benches` instruction tells Cargo to pass the [`-C\nlink-arg=FLAG` option][link-arg] to the compiler, but only when building a benchmark\ntarget.\n\n### `cargo::rustc-link-lib=LIB` {#rustc-link-lib}\n\nThe `rustc-link-lib` instruction tells Cargo to link the given library using\nthe compiler's [`-l` flag][option-link]. This is typically used to link a\nnative library using [FFI].\n\nThe `LIB` string is passed directly to rustc, so it supports any syntax that\n`-l` does. \\\nCurrently the fully supported syntax for `LIB` is `[KIND[:MODIFIERS]=]NAME[:RENAME]`.\n\nThe `-l` flag is only passed to the library target of the package, unless\nthere is no library target, in which case it is passed to all targets. This is\ndone because all other targets have an implicit dependency on the library\ntarget, and the given library to link should only be included once. This means\nthat if a package has both a library and a binary target, the *library* has\naccess to the symbols from the given lib, and the binary should access them\nthrough the library target's public API.\n\nThe optional `KIND` may be one of `dylib`, `static`, or `framework`. See the\n[rustc book][option-link] for more detail.\n\n[option-link]: ../../rustc/command-line-arguments.md#option-l-link-lib\n[FFI]: ../../nomicon/ffi.md\n\n### `cargo::rustc-link-search=[KIND=]PATH` {#rustc-link-search}\n\nThe `rustc-link-search` instruction tells Cargo to pass the [`-L`\nflag][option-search] to the compiler to add a directory to the library search\npath.\n\nThe optional `KIND` may be one of `dependency`, `crate`, `native`,\n`framework`, or `all`. See the [rustc book][option-search] for more detail.\n\nThese paths are also added to the [dynamic library search path environment\nvariable](environment-variables.md#dynamic-library-paths) if they are within\nthe `OUT_DIR`. Depending on this behavior is discouraged since this makes it\ndifficult to use the resulting binary. In general, it is best to avoid\ncreating dynamic libraries in a build script (using existing system libraries\nis fine).\n\n[option-search]: ../../rustc/command-line-arguments.md#option-l-search-path\n\n### `cargo::rustc-flags=FLAGS` {#rustc-flags}\n\nThe `rustc-flags` instruction tells Cargo to pass the given space-separated\nflags to the compiler. This only allows the `-l` and `-L` flags, and is\nequivalent to using [`rustc-link-lib`](#rustc-link-lib) and\n[`rustc-link-search`](#rustc-link-search).\n\n### `cargo::rustc-cfg=KEY[=\"VALUE\"]` {#rustc-cfg}\n\nThe `rustc-cfg` instruction tells Cargo to pass the given value to the\n[`--cfg` flag][option-cfg] to the compiler. This may be used for compile-time\ndetection of features to enable [conditional compilation]. Custom cfgs\nmust either be expected using the [`cargo::rustc-check-cfg`](#rustc-check-cfg)\ninstruction or usage will need to allow the [`unexpected_cfgs`][unexpected-cfgs]\nlint to avoid unexpected cfgs warnings.\n\nNote that this does *not* affect Cargo's dependency resolution. This cannot be\nused to enable an optional dependency, or enable other Cargo features.\n\nBe aware that [Cargo features] use the form `feature=\"foo\"`. `cfg` values\npassed with this flag are not restricted to that form, and may provide just a\nsingle identifier, or any arbitrary key/value pair. For example, emitting\n`cargo::rustc-cfg=abc` will then allow code to use `#[cfg(abc)]` (note the lack\nof `feature=`). Or an arbitrary key/value pair may be used with an `=` symbol\nlike `cargo::rustc-cfg=my_component=\"foo\"`. The key should be a Rust\nidentifier, the value should be a string.\n\n[cargo features]: features.md\n[conditional compilation]: ../../reference/conditional-compilation.md\n[option-cfg]: ../../rustc/command-line-arguments.md#option-cfg\n[unexpected-cfgs]: ../../rustc/lints/listing/warn-by-default.md#unexpected-cfgs\n\n### `cargo::rustc-check-cfg=CHECK_CFG` {#rustc-check-cfg}\n\nAdd to the list of expected config names and values that is used when checking\nthe _reachable_ cfg expressions with the [`unexpected_cfgs`][unexpected-cfgs] lint.\n\nThe syntax of `CHECK_CFG` mirrors the `rustc` [`--check-cfg` flag][option-check-cfg], see\n[Checking conditional configurations][checking-conditional-configurations] for more details.\n\nThe instruction can be used like this:\n\n```rust,no_run\n// build.rs\nprintln!(\"cargo::rustc-check-cfg=cfg(foo, values(\\\"bar\\\"))\");\nif foo_bar_condition {\n    println!(\"cargo::rustc-cfg=foo=\\\"bar\\\"\");\n}\n```\n\nNote that all possible cfgs should be defined, regardless of which cfgs are\ncurrently enabled. This includes all possible values of a given cfg name.\n\nIt is recommended to group the `cargo::rustc-check-cfg` and\n[`cargo::rustc-cfg`][option-cfg] instructions as closely as possible in order to\navoid typos, missing check-cfg, stale cfgs...\n\nSee also the\n[conditional compilation][conditional-compilation-example] example.\n\n> **MSRV:** Respected as of 1.80\n\n[checking-conditional-configurations]: ../../rustc/check-cfg.html\n[option-check-cfg]: ../../rustc/command-line-arguments.md#option-check-cfg\n[conditional-compilation-example]: build-script-examples.md#conditional-compilation\n\n### `cargo::rustc-env=VAR=VALUE` {#rustc-env}\n\nThe `rustc-env` instruction tells Cargo to set the given environment variable\nwhen compiling the package. The value can be then retrieved by the [`env!`\nmacro][env-macro] in the compiled crate. This is useful for embedding\nadditional metadata in crate's code, such as the hash of git HEAD or the\nunique identifier of a continuous integration server.\n\nSee also the [environment variables automatically included by\nCargo][env-cargo].\n\n> **Note**: These environment variables are also set when running an\n> executable with `cargo run` or `cargo test`. However, this usage is\n> discouraged since it ties the executable to Cargo's execution environment.\n> Normally, these environment variables should only be checked at compile-time\n> with the `env!` macro.\n\n[env-macro]: ../../std/macro.env.html\n[env-cargo]: environment-variables.md#environment-variables-cargo-sets-for-crates\n\n### `cargo::error=MESSAGE` {#cargo-error}\n\nThe `error` instruction tells Cargo to display an error after the build script\nhas finished running, and then fail the build.\n\n > Note: Build script libraries should carefully consider if they want to\n > use `cargo::error` versus returning a `Result`. It may be better to return\n > a `Result`, and allow the caller to decide if the error is fatal or not.\n > The caller can then decide whether or not to display the `Err` variant\n > using `cargo::error`.\n\n> **MSRV:** Respected as of 1.84\n\n### `cargo::warning=MESSAGE` {#cargo-warning}\n\nThe `warning` instruction tells Cargo to display a warning after the build\nscript has finished running. Warnings are only shown for `path` dependencies\n(that is, those you're working on locally), so for example warnings printed\nout in [crates.io] crates are not emitted by default, unless the build fails.\nThe `-vv` \"very verbose\" flag may be used to have Cargo display warnings for\nall crates.\n\n## Build Dependencies\n\nBuild scripts are also allowed to have dependencies on other Cargo-based crates.\nDependencies are declared through the `build-dependencies` section of the\nmanifest.\n\n```toml\n[build-dependencies]\ncc = \"1.0.46\"\n```\n\nThe build script **does not** have access to the dependencies listed in the\n`dependencies` or `dev-dependencies` section (they’re not built yet!). Also,\nbuild dependencies are not available to the package itself unless also\nexplicitly added in the `[dependencies]` table.\n\nIt is recommended to carefully consider each dependency you add, weighing\nagainst the impact on compile time, licensing, maintenance, etc. Cargo will\nattempt to reuse a dependency if it is shared between build dependencies and\nnormal dependencies. However, this is not always possible, for example when\ncross-compiling, so keep that in consideration of the impact on compile time.\n\n## Change Detection\n\nWhen rebuilding a package, Cargo does not necessarily know if the build script\nneeds to be run again. By default, it takes a conservative approach of always\nre-running the build script if any file within the package is changed (or the\nlist of files controlled by the [`exclude` and `include` fields]). For most\ncases, this is not a good choice, so it is recommended that every build script\nemit at least one of the `rerun-if` instructions (described below). If these\nare emitted, then Cargo will only re-run the script if the given value has\nchanged. If Cargo is re-running the build scripts of your own crate or a\ndependency and you don't know why, see [\"Why is Cargo rebuilding my code?\" in the\nFAQ](../faq.md#why-is-cargo-rebuilding-my-code).\n\n[`exclude` and `include` fields]: manifest.md#the-exclude-and-include-fields\n\n### `cargo::rerun-if-changed=PATH` {#rerun-if-changed}\n\nThe `rerun-if-changed` instruction tells Cargo to re-run the build script if\nthe file at the given path has changed. Currently, Cargo only uses the\nfilesystem last-modified \"mtime\" timestamp to determine if the file has\nchanged. It compares against an internal cached timestamp of when the build\nscript last ran.\n\nIf the path points to a directory, it will scan the entire directory for\nany modifications.\n\nIf the build script inherently does not need to re-run under any circumstance,\nthen emitting `cargo::rerun-if-changed=build.rs` is a simple way to prevent it\nfrom being re-run (otherwise, the default if no `rerun-if` instructions are\nemitted is to scan the entire package directory for changes). Cargo\nautomatically handles whether or not the script itself needs to be recompiled,\nand of course the script will be re-run after it has been recompiled.\nOtherwise, specifying `build.rs` is redundant and unnecessary.\n\n### `cargo::rerun-if-env-changed=NAME` {#rerun-if-env-changed}\n\nThe `rerun-if-env-changed` instruction tells Cargo to re-run the build script\nif the value of an environment variable of the given name has changed.\n\nNote that the environment variables here are intended for global environment\nvariables like `CC` and such, it is not possible to use this for environment\nvariables like `TARGET` that [Cargo sets for build scripts][build-env]. The\nenvironment variables in use are those received by `cargo` invocations, not\nthose received by the executable of the build script.\n\nAs of 1.46, using [`env!`][env-macro] and [`option_env!`][option-env-macro] in\nsource code will automatically detect changes and trigger rebuilds.\n`rerun-if-env-changed` is no longer needed for variables already referenced by\nthese macros.\n\n[option-env-macro]: ../../std/macro.option_env.html\n\n## The `links` Manifest Key\n\nThe `package.links` key may be set in the `Cargo.toml` manifest to declare\nthat the package links with the given native library. The purpose of this\nmanifest key is to give Cargo an understanding about the set of native\ndependencies that a package has, as well as providing a principled system of\npassing metadata between package build scripts.\n\n```toml\n[package]\n# ...\nlinks = \"foo\"\n```\n\nThis manifest states that the package links to the `libfoo` native library.\nWhen using the `links` key, the package must have a build script, and the\nbuild script should use the [`rustc-link-lib` instruction](#rustc-link-lib) to\nlink the library.\n\nPrimarily, Cargo requires that there is at most one package per `links` value.\nIn other words, it is forbidden to have two packages link to the same native\nlibrary. This helps prevent duplicate symbols between crates. Note, however,\nthat there are [conventions in place](#-sys-packages) to alleviate this.\n\nBuild scripts can generate an arbitrary set of metadata in the form of\nkey-value pairs. This metadata is set with the `cargo::metadata=KEY=VALUE`\ninstruction.\n\nThe metadata is passed to the build scripts of **dependent** packages. For\nexample, if the package `foo` depends on `bar`, which links `baz`, then if \n`bar` generates `key=value` as part of its build script metadata, then the\nbuild script of `foo` will have the environment variables `DEP_BAZ_KEY=value`\n(note that the value of the `links` key is used and the case change for `key`).\nSee the [\"Using another `sys` crate\"][using-another-sys] for an example of \nhow this can be used.\n\nNote that metadata is only passed to immediate dependents, not transitive\ndependents.\n\n> **MSRV:** 1.77 is required for `cargo::metadata=KEY=VALUE`.\n> To support older versions, use `cargo:KEY=VALUE` (unsupported directives are assumed to be metadata keys).\n\n[using-another-sys]: build-script-examples.md#using-another-sys-crate\n\n## `*-sys` Packages\n\nSome Cargo packages that link to system libraries have a naming convention of\nhaving a `-sys` suffix. Any package named `foo-sys` should provide two major\npieces of functionality:\n\n* The library crate should link to the native library `libfoo`. This will often\n  probe the current system for `libfoo` before resorting to building from\n  source.\n* The library crate should provide **declarations** for types and functions in\n  `libfoo`, but **not** higher-level abstractions.\n\nThe set of `*-sys` packages provides a common set of dependencies for linking\nto native libraries. There are a number of benefits earned from having this\nconvention of native-library-related packages:\n\n* Common dependencies on `foo-sys` alleviates the rule about one package per\n  value of `links`.\n* Other `-sys` packages can take advantage of the `DEP_LINKS_KEY=value`\n  environment variables to better integrate with other packages. See the\n  [\"Using another `sys` crate\"][using-another-sys] example.\n* A common dependency allows centralizing logic on discovering `libfoo` itself\n  (or building it from source).\n* These dependencies are easily [overridable](#overriding-build-scripts).\n\nIt is common to have a companion package without the `-sys` suffix that\nprovides a safe, high-level abstractions on top of the sys package. For\nexample, the [`git2` crate] provides a high-level interface to the\n[`libgit2-sys` crate].\n\n[`git2` crate]: https://crates.io/crates/git2\n[`libgit2-sys` crate]: https://crates.io/crates/libgit2-sys\n\n## Overriding Build Scripts\n\nIf a manifest contains a `links` key, then Cargo supports overriding the build\nscript specified with a custom library. The purpose of this functionality is to\nprevent running the build script in question altogether and instead supply the\nmetadata ahead of time.\n\nTo override a build script, place the following configuration in any acceptable [`config.toml`](config.md) file.\n\n```toml\n[target.x86_64-unknown-linux-gnu.foo]\nrustc-link-lib = [\"foo\"]\nrustc-link-search = [\"/path/to/foo\"]\nrustc-flags = \"-L /some/path\"\nrustc-cfg = ['key=\"value\"']\nrustc-env = {key = \"value\"}\nrustc-cdylib-link-arg = [\"…\"]\nmetadata_key1 = \"value\"\nmetadata_key2 = \"value\"\n```\n\nWith this configuration, if a package declares that it links to `foo` then the\nbuild script will **not** be compiled or run, and the metadata specified will\nbe used instead.\n\nThe `warning`, `rerun-if-changed`, and `rerun-if-env-changed` keys should not\nbe used and will be ignored.\n\n## Jobserver\n\nCargo and `rustc` use the [jobserver protocol], developed for GNU make, to\ncoordinate concurrency across processes. It is essentially a semaphore that\ncontrols the number of jobs running concurrently. The concurrency may be set\nwith the `--jobs` flag, which defaults to the number of logical CPUs.\n\nEach build script inherits one job slot from Cargo, and should endeavor to\nonly use one CPU while it runs. If the script wants to use more CPUs in\nparallel, it should use the [`jobserver` crate] to coordinate with Cargo.\n\nAs an example, the [`cc` crate] may enable the optional `parallel` feature\nwhich will use the jobserver protocol to attempt to build multiple C files\nat the same time.\n\n[`cc` crate]: https://crates.io/crates/cc\n[`jobserver` crate]: https://crates.io/crates/jobserver\n[jobserver protocol]: http://make.mad-scientist.net/papers/jobserver-implementation/\n[crates.io]: https://crates.io/\n"
  },
  {
    "path": "src/doc/src/reference/cargo-targets.md",
    "content": "# Cargo Targets\n\nCargo packages consist of *targets* which correspond to source files which can\nbe compiled into a crate. Packages can have [library](#library),\n[binary](#binaries), [example](#examples), [test](#tests), and\n[benchmark](#benchmarks) targets. The list of targets can be configured in the\n`Cargo.toml` manifest, often [inferred automatically](#target-auto-discovery)\nby the [directory layout][package layout] of the source files.\n\nSee [Configuring a target](#configuring-a-target) below for details on\nconfiguring the settings for a target.\n\n## Library\n\nThe library target defines a \"library\" that can be used and linked by other\nlibraries and executables. The filename defaults to `src/lib.rs`, and the name\nof the library defaults to the name of the package, with any dashes replaced\nwith underscores. A package can have only one library. The settings for the\nlibrary can be [customized] in the `[lib]` table in `Cargo.toml`.\n\n```toml\n# Example of customizing the library in Cargo.toml.\n[lib]\ncrate-type = [\"cdylib\"]\nbench = false\n```\n\n## Binaries\n\nBinary targets are executable programs that can be run after being compiled.\nA binary's source can be `src/main.rs` and/or stored in the [`src/bin/`\ndirectory][package layout]. For `src/main.rs`, the default binary name is the\npackage name. The settings for each binary can be [customized] in the`[[bin]]`\ntables in `Cargo.toml`.\n\nBinaries can use the public API of the package's library. They are also linked\nwith the [`[dependencies]`][dependencies] defined in `Cargo.toml`.\n\nYou can run individual binaries with the [`cargo run`] command with the `--bin\n<bin-name>` option. [`cargo install`] can be used to copy the executable to a\ncommon location.\n\n```toml\n# Example of customizing binaries in Cargo.toml.\n[[bin]]\nname = \"cool-tool\"\ntest = false\nbench = false\n\n[[bin]]\nname = \"frobnicator\"\nrequired-features = [\"frobnicate\"]\n```\n\n## Examples\n\nFiles located under the [`examples` directory][package layout] are example\nuses of the functionality provided by the library. When compiled, they are\nplaced in the [`target/debug/examples` directory][build cache].\n\nExamples can use the public API of the package's library. They are also linked\nwith the [`[dependencies]`][dependencies] and\n[`[dev-dependencies]`][dev-dependencies] defined in `Cargo.toml`.\n\nBy default, examples are executable binaries (with a `main()` function). You\ncan specify the [`crate-type` field](#the-crate-type-field) to make an example\nbe compiled as a library:\n\n```toml\n[[example]]\nname = \"foo\"\ncrate-type = [\"staticlib\"]\n```\n\nYou can run individual executable examples with the [`cargo run`] command with\nthe `--example <example-name>` option. Library examples can be built with\n[`cargo build`] with the `--example <example-name>` option. [`cargo install`]\nwith the `--example <example-name>` option can be used to copy executable\nbinaries to a common location. Examples are compiled by [`cargo test`] by\ndefault to protect them from bit-rotting. Set [the `test`\nfield](#the-test-field) to `true` if you have `#[test]` functions in the\nexample that you want to run with [`cargo test`].\n\n## Tests\n\nThere are two styles of tests within a Cargo project:\n\n* *Unit tests* which are functions marked with the [`#[test]`\n  attribute][test-attribute] located within your library or binaries (or any\n  target enabled with [the `test` field](#the-test-field)). These tests have\n  access to private APIs located within the target they are defined in.\n* *Integration tests* which is a separate executable binary, also containing\n  `#[test]` functions, which is linked with the project's library and has\n  access to its *public* API.\n\nTests are run with the [`cargo test`] command. By default, Cargo and `rustc`\nuse the [libtest harness] which is responsible for collecting functions\nannotated with the [`#[test]` attribute][test-attribute] and executing them in\nparallel, reporting the success and failure of each test. See [the `harness`\nfield](#the-harness-field) if you want to use a different harness or test\nstrategy.\n\n> **Note**: There is another special style of test in Cargo:\n> [documentation tests][documentation examples].\n> They are handled by `rustdoc` and have a slightly different execution model.\n> For more information, please see [`cargo test`][cargo-test-documentation-tests].\n\n[libtest harness]: ../../rustc/tests/index.html\n[cargo-test-documentation-tests]: ../commands/cargo-test.md#documentation-tests\n\n### Integration tests\n\nFiles located under the [`tests` directory][package layout] are integration\ntests. When you run [`cargo test`], Cargo will compile each of these files as\na separate crate, and execute them.\n\nIntegration tests can use the public API of the package's library. They are\nalso linked with the [`[dependencies]`][dependencies] and\n[`[dev-dependencies]`][dev-dependencies] defined in `Cargo.toml`.\n\nIf you want to share code among multiple integration tests, you can place it\nin a separate module such as `tests/common/mod.rs` and then put `mod common;`\nin each test to import it.\n\nEach integration test results in a separate executable binary, and [`cargo\ntest`] will run them serially. In some cases this can be inefficient, as it\ncan take longer to compile, and may not make full use of multiple CPUs when\nrunning the tests. If you have a lot of integration tests, you may want to\nconsider creating a single integration test, and split the tests into multiple\nmodules. The libtest harness will automatically find all of the `#[test]`\nannotated functions and run them in parallel. You can pass module names to\n[`cargo test`] to only run the tests within that module.\n\nBinary targets are automatically built if there is an integration test. This\nallows an integration test to execute the binary to exercise and test its\nbehavior. The `CARGO_BIN_EXE_<name>` [environment variable] is set when the\nintegration test is built and run so that it can use the [`env` macro] or [`var` function]\nto locate the executable.\n\n[environment variable]: environment-variables.md#environment-variables-cargo-sets-for-crates\n[`env` macro]: ../../std/macro.env.html\n[`var` function]: ../../std/env/fn.var.html\n\n## Benchmarks\n\nBenchmarks provide a way to test the performance of your code using the\n[`cargo bench`] command. They follow the same structure as [tests](#tests),\nwith each benchmark function annotated with the `#[bench]` attribute.\nSimilarly to tests:\n\n* Benchmarks are placed in the [`benches` directory][package layout].\n* Benchmark functions defined in libraries and binaries have access to the\n  *private* API within the target they are defined in. Benchmarks in the\n  `benches` directory may use the *public* API.\n* [The `bench` field](#the-bench-field) can be used to define which targets\n  are benchmarked by default.\n* [The `harness` field](#the-harness-field) can be used to disable the\n  built-in harness.\n\n> **Note**: The [`#[bench]`\n> attribute](../../unstable-book/library-features/test.html) is currently\n> unstable and only available on the [nightly channel]. There are some\n> packages available on [crates.io](https://crates.io/keywords/benchmark) that\n> may help with running benchmarks on the stable channel, such as\n> [Criterion](https://crates.io/crates/criterion).\n\n## Configuring a target\n\nAll of the  `[lib]`, `[[bin]]`, `[[example]]`, `[[test]]`, and `[[bench]]`\nsections in `Cargo.toml` support similar configuration for specifying how a\ntarget should be built. The double-bracket sections like `[[bin]]` are\n[array-of-table of TOML](https://toml.io/en/v1.0.0-rc.3#array-of-tables),\nwhich means you can write more than one `[[bin]]` section to make several\nexecutables in your crate. You can only specify one library, so `[lib]` is a\nnormal TOML table.\n\nThe following is an overview of the TOML settings for each target, with each\nfield described in detail below.\n\n```toml\n[lib]\nname = \"foo\"           # The name of the target.\npath = \"src/lib.rs\"    # The source file of the target.\ntest = true            # Is tested by default.\ndoctest = true         # Documentation examples are tested by default.\nbench = true           # Is benchmarked by default.\ndoc = true             # Is documented by default.\nproc-macro = false     # Set to `true` for a proc-macro library.\nharness = true         # Use libtest harness.\ncrate-type = [\"lib\"]   # The crate types to generate.\nrequired-features = [] # Features required to build this target (N/A for lib).\n```\n\n### The `name` field\n\nThe `name` field specifies the name of the target, which corresponds to the\nfilename of the artifact that will be generated. For a library, this is the\ncrate name that dependencies will use to reference it.\n\nFor the library target, this defaults to the name of the package , with any\ndashes replaced with underscores. For the default binary (`src/main.rs`),\nit also defaults to the name of the package, with no replacement for dashes.\nFor [auto discovered](#target-auto-discovery) targets, it defaults to the\ndirectory or file name.\n\nThis is required for all targets except `[lib]`.\n\n### The `path` field\n\nThe `path` field specifies where the source for the crate is located, relative\nto the `Cargo.toml` file.\n\nIf not specified, the [inferred path](#target-auto-discovery) is used based on\nthe target name.\n\n### The `test` field\n\nThe `test` field indicates whether or not the target is tested by default by\n[`cargo test`]. The default is `true` for lib, bins, and tests.\n\n> **Note**: Examples are built by [`cargo test`] by default to ensure they\n> continue to compile, but they are not *tested* by default. Setting `test =\n> true` for an example will also build it as a test and run any\n> [`#[test]`][test-attribute] functions defined in the example.\n\n### The `doctest` field\n\nThe `doctest` field indicates whether or not [documentation examples] are\ntested by default by [`cargo test`]. This is only relevant for libraries, it\nhas no effect on other sections. The default is `true` for the library.\n\n### The `bench` field\n\nThe `bench` field indicates whether or not the target is benchmarked by\ndefault by [`cargo bench`]. The default is `true` for lib, bins, and\nbenchmarks.\n\n### The `doc` field\n\nThe `doc` field indicates whether or not the target is included in the\ndocumentation generated by [`cargo doc`] by default. The default is `true` for\nlibraries and binaries.\n\n> **Note**: The binary will be skipped if its name is the same as the lib\n> target.\n\n### The `plugin` field\n\nThis option is deprecated and unused.\n\n### The `proc-macro` field\n\nThe `proc-macro` field indicates that the library is a [procedural macro]\n([reference][proc-macro-reference]). This is only valid for the `[lib]`\ntarget.\n\n### The `harness` field\n\nThe `harness` field indicates that the [`--test` flag] will be passed to\n`rustc` which will automatically include the libtest library which is the\ndriver for collecting and running tests marked with the [`#[test]`\nattribute][test-attribute] or benchmarks with the `#[bench]` attribute. The\ndefault is `true` for all targets.\n\nIf set to `false`, then you are responsible for defining a `main()` function\nto run tests and benchmarks.\n\nTests have the [`cfg(test)` conditional expression][cfg-test] enabled whether\nor not the harness is enabled.\n\n### The `crate-type` field\n\nThe `crate-type` field defines the [crate types] that will be generated by the\ntarget. It is an array of strings, allowing you to specify multiple crate\ntypes for a single target. This can only be specified for libraries and\nexamples. Binaries, tests, and benchmarks are always the \"bin\" crate type. The\ndefaults are:\n\nTarget | Crate Type\n-------|-----------\nNormal library | `\"lib\"`\nProc-macro library | `\"proc-macro\"`\nExample | `\"bin\"`\n\nThe available options are `bin`, `lib`, `rlib`, `dylib`, `cdylib`,\n`staticlib`, and `proc-macro`. You can read more about the different crate\ntypes in the [Rust Reference Manual][crate types].\n\n### The `required-features` field\n\nThe `required-features` field specifies which [features] the target needs in\norder to be built. If any of the required features are not enabled, the\ntarget will be skipped. This is only relevant for the `[[bin]]`, `[[bench]]`,\n`[[test]]`, and `[[example]]` sections, it has no effect on `[lib]`.\n\n```toml\n[features]\n# ...\npostgres = []\nsqlite = []\ntools = []\n\n[[bin]]\nname = \"my-pg-tool\"\nrequired-features = [\"postgres\", \"tools\"]\n```\n\n### The `edition` field\n\nThe `edition` field defines the [Rust edition] the target will use. If not\nspecified, it defaults to the [`edition` field][package-edition] for the\n`[package]`.\n\n> **Note:** This field is deprecated and will be removed in a future Edition\n\n## Target auto-discovery\n\nBy default, Cargo automatically determines the targets to build based on the\n[layout of the files][package layout] on the filesystem. The target\nconfiguration tables, such as `[lib]`, `[[bin]]`, `[[test]]`, `[[bench]]`, or\n`[[example]]`, can be used to add additional targets that don't follow the\nstandard directory layout.\n\nThe automatic target discovery can be disabled so that only manually\nconfigured targets will be built. Setting the keys `autolib`, `autobins`, `autoexamples`,\n`autotests`, or `autobenches` to `false` in the `[package]` section will\ndisable auto-discovery of the corresponding target type.\n\n```toml\n[package]\n# ...\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\n```\n\nDisabling automatic discovery should only be needed for specialized\nsituations. For example, if you have a library where you want a *module* named\n`bin`, this would present a problem because Cargo would usually attempt to\ncompile anything in the `bin` directory as an executable. Here is a sample\nlayout of this scenario:\n\n```text\n├── Cargo.toml\n└── src\n    ├── lib.rs\n    └── bin\n        └── mod.rs\n```\n\nTo prevent Cargo from inferring `src/bin/mod.rs` as an executable, set\n`autobins = false` in `Cargo.toml` to disable auto-discovery:\n\n```toml\n[package]\n# …\nautobins = false\n```\n\n> **Note**: For packages with the 2015 edition, the default for auto-discovery\n> is `false` if at least one target is manually defined in `Cargo.toml`.\n> Beginning with the 2018 edition, the default is always `true`.\n\n> **MSRV:** Respected as of 1.27 for `autobins`, `autoexamples`, `autotests`, and `autobenches`\n\n> **MSRV:** Respected as of 1.83 for `autolib`\n\n[Build cache]: build-cache.md\n[Rust Edition]: ../../edition-guide/index.html\n[`--test` flag]: ../../rustc/command-line-arguments.html#option-test\n[`cargo bench`]: ../commands/cargo-bench.md\n[`cargo build`]: ../commands/cargo-build.md\n[`cargo doc`]: ../commands/cargo-doc.md\n[`cargo install`]: ../commands/cargo-install.md\n[`cargo run`]: ../commands/cargo-run.md\n[`cargo test`]: ../commands/cargo-test.md\n[cfg-test]: ../../reference/conditional-compilation.html#test\n[crate types]: ../../reference/linkage.html\n[crates.io]: https://crates.io/\n[customized]: #configuring-a-target\n[dependencies]: specifying-dependencies.md\n[dev-dependencies]: specifying-dependencies.md#development-dependencies\n[documentation examples]: ../../rustdoc/documentation-tests.html\n[features]: features.md\n[nightly channel]: ../../book/appendix-07-nightly-rust.html\n[package layout]: ../guide/project-layout.md\n[package-edition]: manifest.md#the-edition-field\n[proc-macro-reference]: ../../reference/procedural-macros.html\n[procedural macro]: ../../book/ch19-06-macros.html\n[test-attribute]: ../../reference/attributes/testing.html#the-test-attribute\n"
  },
  {
    "path": "src/doc/src/reference/config.md",
    "content": "# Configuration\n\nThis document explains how Cargo’s configuration system works, as well as\navailable keys or configuration. For configuration of a package through its\nmanifest, see the [manifest format](manifest.md).\n\n## Hierarchical structure\n\nCargo allows local configuration for a particular package as well as global\nconfiguration. It looks for configuration files in the current directory and\nall parent directories. If, for example, Cargo were invoked in\n`/projects/foo/bar/baz`, then the following configuration files would be\nprobed for and unified in this order:\n\n* `/projects/foo/bar/baz/.cargo/config.toml`\n* `/projects/foo/bar/.cargo/config.toml`\n* `/projects/foo/.cargo/config.toml`\n* `/projects/.cargo/config.toml`\n* `/.cargo/config.toml`\n* `$CARGO_HOME/config.toml` which defaults to:\n    * Windows: `%USERPROFILE%\\.cargo\\config.toml`\n    * Unix: `$HOME/.cargo/config.toml`\n\nWith this structure, you can specify configuration per-package, and even\npossibly check it into version control. You can also specify personal defaults\nwith a configuration file in your home directory.\n\nIf a key is specified in multiple config files, the values will get merged\ntogether. Numbers, strings, and booleans will use the value in the deeper\nconfig directory taking precedence over ancestor directories, where the\nhome directory is the lowest priority. Arrays will be joined together\nwith higher precedence items being placed later in the merged array.\n\nAt present, when being invoked from a workspace, Cargo does not read config\nfiles from crates within the workspace. i.e. if a workspace has two crates in\nit, named `/projects/foo/bar/baz/mylib` and `/projects/foo/bar/baz/mybin`, and\nthere are Cargo configs at `/projects/foo/bar/baz/mylib/.cargo/config.toml`\nand `/projects/foo/bar/baz/mybin/.cargo/config.toml`, Cargo does not read\nthose configuration files if it is invoked from the workspace root\n(`/projects/foo/bar/baz/`).\n\n> **Note:** Cargo also reads config files without the `.toml` extension, such as\n> `.cargo/config`. Support for the `.toml` extension was added in version 1.39\n> and is the preferred form. If both files exist, Cargo will use the file\n> without the extension.\n\n## Configuration format\n\nConfiguration files are written in the [TOML format][toml] (like the\nmanifest), with simple key-value pairs inside of sections (tables). The\nfollowing is a quick overview of all settings, with detailed descriptions\nfound below.\n\n```toml\npaths = [\"/path/to/override\"] # path dependency overrides\n\n[alias]     # command aliases\nb = \"build\"\nc = \"check\"\nt = \"test\"\nr = \"run\"\nrr = \"run --release\"\nrecursive_example = \"rr --example recursions\"\nspace_example = [\"run\", \"--release\", \"--\", \"\\\"command list\\\"\"]\n\n[build]\njobs = 1                      # number of parallel jobs, defaults to # of CPUs\nrustc = \"rustc\"               # the rust compiler tool\nrustc-wrapper = \"…\"           # run this wrapper instead of `rustc`\nrustc-workspace-wrapper = \"…\" # run this wrapper instead of `rustc` for workspace members\nrustdoc = \"rustdoc\"           # the doc generator tool\ntarget = \"triple\"             # build for the target triple (ignored by `cargo install`)\ntarget-dir = \"target\"         # path of where to place generated artifacts\nbuild-dir = \"target\"          # path of where to place intermediate build artifacts\nrustflags = [\"…\", \"…\"]        # custom flags to pass to all compiler invocations\nrustdocflags = [\"…\", \"…\"]     # custom flags to pass to rustdoc\nincremental = true            # whether or not to enable incremental compilation\ndep-info-basedir = \"…\"        # path for the base directory for targets in depfiles\n\n[credential-alias]\n# Provides a way to define aliases for credential providers.\nmy-alias = [\"/usr/bin/cargo-credential-example\", \"--argument\", \"value\", \"--flag\"]\n\n[doc]\nbrowser = \"chromium\"          # browser to use with `cargo doc --open`,\n                              # overrides the `BROWSER` environment variable\n\n[env]\n# Set ENV_VAR_NAME=value for any process run by Cargo\nENV_VAR_NAME = \"value\"\n# Set even if already present in environment\nENV_VAR_NAME_2 = { value = \"value\", force = true }\n# `value` is relative to the parent of `.cargo/config.toml`, env var will be the full absolute path\nENV_VAR_NAME_3 = { value = \"relative/path\", relative = true }\n\n[future-incompat-report]\nfrequency = 'always' # when to display a notification about a future incompat report\n\n[cache]\nauto-clean-frequency = \"1 day\"   # How often to perform automatic cache cleaning\n\n[cargo-new]\nvcs = \"none\"              # VCS to use ('git', 'hg', 'pijul', 'fossil', 'none')\n\n[http]\ndebug = false               # HTTP debugging\nproxy = \"host:port\"         # HTTP proxy in libcurl format\nssl-version = \"tlsv1.3\"     # TLS version to use\nssl-version.max = \"tlsv1.3\" # maximum TLS version\nssl-version.min = \"tlsv1.1\" # minimum TLS version\ntimeout = 30                # timeout for each HTTP request, in seconds\nlow-speed-limit = 10        # network timeout threshold (bytes/sec)\ncainfo = \"cert.pem\"         # path to Certificate Authority (CA) bundle\nproxy-cainfo = \"cert.pem\"   # path to proxy Certificate Authority (CA) bundle\ncheck-revoke = true         # check for SSL certificate revocation\nmultiplexing = true         # HTTP/2 multiplexing\nuser-agent = \"…\"            # the user-agent header\n\n[install]\nroot = \"/some/path\"         # `cargo install` destination directory\n\n[net]\nretry = 3                   # network retries\ngit-fetch-with-cli = true   # use the `git` executable for git operations\noffline = true              # do not access the network\n\n[net.ssh]\nknown-hosts = [\"...\"]       # known SSH host keys\n\n[patch.<registry>]\n# Same keys as for [patch] in Cargo.toml\n\n[profile.<name>]         # Modify profile settings via config.\ninherits = \"dev\"         # Inherits settings from [profile.dev].\nopt-level = 0            # Optimization level.\ndebug = true             # Include debug info.\nsplit-debuginfo = '...'  # Debug info splitting behavior.\nstrip = \"none\"           # Removes symbols or debuginfo.\ndebug-assertions = true  # Enables debug assertions.\noverflow-checks = true   # Enables runtime integer overflow checks.\nlto = false              # Sets link-time optimization.\npanic = 'unwind'         # The panic strategy.\nincremental = true       # Incremental compilation.\ncodegen-units = 16       # Number of code generation units.\nrpath = false            # Sets the rpath linking option.\n[profile.<name>.build-override]  # Overrides build-script settings.\n# Same keys for a normal profile.\n[profile.<name>.package.<name>]  # Override profile for a package.\n# Same keys for a normal profile (minus `panic`, `lto`, and `rpath`).\n\n[resolver]\nincompatible-rust-versions = \"allow\"  # Specifies how resolver reacts to these\n\n[registries.<name>]  # registries other than crates.io\nindex = \"…\"          # URL of the registry index\ntoken = \"…\"          # authentication token for the registry\ncredential-provider = \"cargo:token\" # The credential provider for this registry.\n\n[registries.crates-io]\nprotocol = \"sparse\"  # The protocol to use to access crates.io.\n\n[registry]\ndefault = \"…\"        # name of the default registry\ntoken = \"…\"          # authentication token for crates.io\ncredential-provider = \"cargo:token\"           # The credential provider for crates.io.\nglobal-credential-providers = [\"cargo:token\"] # The credential providers to use by default.\n\n[source.<name>]      # source definition and replacement\nreplace-with = \"…\"   # replace this source with the given named source\ndirectory = \"…\"      # path to a directory source\nregistry = \"…\"       # URL to a registry source\nlocal-registry = \"…\" # path to a local registry source\ngit = \"…\"            # URL of a git repository source\nbranch = \"…\"         # branch name for the git repository\ntag = \"…\"            # tag name for the git repository\nrev = \"…\"            # revision for the git repository\n\n[target.<triple>]\nlinker = \"…\"              # linker to use\nrunner = \"…\"              # wrapper to run executables\nrustflags = [\"…\", \"…\"]    # custom flags for `rustc`\nrustdocflags = [\"…\", \"…\"] # custom flags for `rustdoc`\n\n[target.<cfg>]\nlinker = \"…\"            # linker to use\nrunner = \"…\"            # wrapper to run executables\nrustflags = [\"…\", \"…\"]  # custom flags for `rustc`\n\n[target.<triple>.<links>] # `links` build script override\nrustc-link-lib = [\"foo\"]\nrustc-link-search = [\"/path/to/foo\"]\nrustc-flags = \"-L /some/path\"\nrustc-cfg = ['key=\"value\"']\nrustc-env = {key = \"value\"}\nrustc-cdylib-link-arg = [\"…\"]\nmetadata_key1 = \"value\"\nmetadata_key2 = \"value\"\n\n[term]\nquiet = false                    # whether cargo output is quiet\nverbose = false                  # whether cargo provides verbose output\ncolor = 'auto'                   # whether cargo colorizes output\nhyperlinks = true                # whether cargo inserts links into output\nunicode = true                   # whether cargo can render output using non-ASCII unicode characters\nprogress.when = 'auto'           # whether cargo shows progress bar\nprogress.width = 80              # width of progress bar\nprogress.term-integration = true # whether cargo reports progress to terminal emulator\n```\n\n## Environment variables\n\nCargo can also be configured through environment variables in addition to the\nTOML configuration files. For each configuration key of the form `foo.bar` the\nenvironment variable `CARGO_FOO_BAR` can also be used to define the value.\nKeys are converted to uppercase, dots and dashes are converted to underscores.\nFor example the `target.x86_64-unknown-linux-gnu.runner` key can also be\ndefined by the `CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER` environment\nvariable.\n\nEnvironment variables will take precedence over TOML configuration files.\nCurrently only integer, boolean, string and some array values are supported to\nbe defined by environment variables. [Descriptions below](#configuration-keys)\nindicate which keys support environment variables and otherwise they are not\nsupported due to [technical issues](https://github.com/rust-lang/cargo/issues/5416).\n\nIn addition to the system above, Cargo recognizes a few other specific\n[environment variables][env].\n\n## Command-line overrides\n\nCargo also accepts arbitrary configuration overrides through the\n`--config` command-line option. The argument should be in TOML syntax of\n`KEY=VALUE` or provided as a path to an extra configuration file:\n\n```console\n# With `KEY=VALUE` in TOML syntax\ncargo --config net.git-fetch-with-cli=true fetch\n\n# With a path to a configuration file\ncargo --config ./path/to/my/extra-config.toml fetch\n```\n\nThe `--config` option may be specified multiple times, in which case the\nvalues are merged in left-to-right order, using the same merging logic\nthat is used when multiple configuration files apply. Configuration\nvalues specified this way take precedence over environment variables,\nwhich take precedence over configuration files.\n\nWhen the `--config` option is provided as an extra configuration file,\nThe configuration file loaded this way follow the same precedence rules\nas other options specified directly with `--config`.\n\nSome examples of what it looks like using Bourne shell syntax:\n\n```console\n# Most shells will require escaping.\ncargo --config http.proxy=\\\"http://example.com\\\" …\n\n# Spaces may be used.\ncargo --config \"net.git-fetch-with-cli = true\" …\n\n# TOML array example. Single quotes make it easier to read and write.\ncargo --config 'build.rustdocflags = [\"--html-in-header\", \"header.html\"]' …\n\n# Example of a complex TOML key.\ncargo --config \"target.'cfg(all(target_arch = \\\"arm\\\", target_os = \\\"none\\\"))'.runner = 'my-runner'\" …\n\n# Example of overriding a profile setting.\ncargo --config profile.dev.package.image.opt-level=3 …\n```\n\n## Including extra configuration files\n\nConfiguration can include other configuration files using the top-level `include` key.\nThis allows sharing configuration across multiple projects\nor splitting complex configurations into multiple files.\n\n### `include`\n\n* Type: array of strings or tables\n* Default: none\n* Environment: not supported\n\nLoads additional configuration files.\nPaths are relative to the configuration file that includes them.\nOnly paths ending with `.toml` are accepted.\n\nSupports the following formats:\n\n```toml\n# array of paths\ninclude = [\n    \"frodo.toml\",\n    \"samwise.toml\",\n]\n\n# inline tables for more control\ninclude = [\n    { path = \"required.toml\" },\n    { path = \"optional.toml\", optional = true },\n]\n```\n\n> **Note:** For better readability and to avoid confusion, it is recommended to:\n> - Place `include` at the top of the configuration file\n> - Put one include per line for clearer version control diffs\n> - Use inline table syntax when optional includes are needed\n\nWhen using table syntax, the following fields are supported:\n\n* `path` (string, required): Path to the config file to include.\n* `optional` (boolean, default: false): If `true`, missing files are silently\n  skipped instead of causing an error.\n\nThe merge behavior of `include` is different from other config values:\n\n1. Config values are first loaded from the `include` paths.\n    * Included files are loaded left to right,\n      with values from later files taking precedence over earlier ones.\n    * This step recurses if included config files also contain `include` keys.\n2. Then, the config file's own values are merged on top of the included config,\n   taking highest precedence.\n\n## Config-relative paths\n\nPaths in config files may be absolute, relative, or a bare name without any path separators.\nPaths for executables without a path separator will use the `PATH` environment variable to search for the executable.\nPaths for non-executables will be relative to where the config value is defined.\n\nIn particular, rules are:\n\n* For environment variables, paths are relative to the current working directory.\n* For config values loaded directly from the [`--config KEY=VALUE`](#command-line-overrides) option,\n  paths are relative to the current working directory.\n* For config files, paths are relative to the parent directory of the directory where the config files were defined,\n  no matter those files are from either the [hierarchical probing](#hierarchical-structure)\n  or the [`--config <path>`](#command-line-overrides) option.\n\n> **Note:** To maintain consistency with existing `.cargo/config.toml` probing behavior,\n> it is by design that a path in a config file passed via `--config <path>`\n> is also relative to two levels up from the config file itself.\n>\n> To avoid unexpected results, the rule of thumb is putting your extra config files\n> at the same level of discovered `.cargo/config.toml` in your project.\n> For instance, given a project `/my/project`,\n> it is recommended to put config files under `/my/project/.cargo`\n> or a new directory at the same level, such as `/my/project/.config`.\n\n```toml\n# Relative path examples.\n\n[target.x86_64-unknown-linux-gnu]\nrunner = \"foo\"  # Searches `PATH` for `foo`.\n\n[source.vendored-sources]\n# Directory is relative to the parent where `.cargo/config.toml` is located.\n# For example, `/my/project/.cargo/config.toml` would result in `/my/project/vendor`.\ndirectory = \"vendor\"\n```\n\n## Executable paths with arguments\n\nSome Cargo commands invoke external programs, which can be configured as a path\nand some number of arguments.\n\nThe value may be an array of strings like `['/path/to/program', 'somearg']` or\na space-separated string like `'/path/to/program somearg'`. If the path to the\nexecutable contains a space, the list form must be used.\n\nIf Cargo is passing other arguments to the program such as a path to open or\nrun, they will be passed after the last specified argument in the value of an\noption of this format. If the specified program does not have path separators,\nCargo will search `PATH` for its executable.\n\n## Credentials\n\nConfiguration values with sensitive information are stored in the\n`$CARGO_HOME/credentials.toml` file. This file is automatically created and updated\nby [`cargo login`] and [`cargo logout`] when using the [`cargo:token`] credential provider.\n\nTokens are used by some Cargo commands such as [`cargo publish`] for\nauthenticating with remote registries. Care should be taken to protect the\ntokens and to keep them secret.\n\nIt follows the same format as Cargo config files.\n\n```toml\n[registry]\ntoken = \"…\"   # Access token for crates.io\n\n[registries.<name>]\ntoken = \"…\"   # Access token for the named registry\n```\n\nAs with most other config values, tokens may be specified with environment\nvariables. The token for [crates.io] may be specified with the\n`CARGO_REGISTRY_TOKEN` environment variable. Tokens for other registries may\nbe specified with environment variables of the form\n`CARGO_REGISTRIES_<name>_TOKEN` where `<name>` is the name of the registry in\nall capital letters.\n\n> **Note:** Cargo also reads and writes credential files without the `.toml`\n> extension, such as `.cargo/credentials`. Support for the `.toml` extension\n> was added in version 1.39. In version 1.68, Cargo writes to the file with the\n> extension by default. However, for backward compatibility reason, when both\n> files exist, Cargo will read and write the file without the extension.\n\n## Configuration keys\n\nThis section documents all configuration keys. The description for keys with\nvariable parts are annotated with angled brackets like `target.<triple>` where\nthe `<triple>` part can be any [target triple] like\n`target.x86_64-pc-windows-msvc`.\n\n### `paths`\n* Type: array of strings (paths)\n* Default: none\n* Environment: not supported\n\nAn array of paths to local packages which are to be used as overrides for\ndependencies. For more information see the [Overriding Dependencies\nguide](overriding-dependencies.md#paths-overrides).\n\n### `[alias]`\n* Type: string or array of strings\n* Default: see below\n* Environment: `CARGO_ALIAS_<name>`\n\nThe `[alias]` table defines CLI command aliases. For example, running `cargo\nb` is an alias for running `cargo build`. Each key in the table is the\nsubcommand, and the value is the actual command to run. The value may be an\narray of strings, where the first element is the command and the following are\narguments. It may also be a string, which will be split on spaces into\nsubcommand and arguments. The following aliases are built-in to Cargo:\n\n```toml\n[alias]\nb = \"build\"\nc = \"check\"\nd = \"doc\"\nt = \"test\"\nr = \"run\"\nrm = \"remove\"\n```\n\nAliases are not allowed to redefine existing built-in commands.\n\nAliases are recursive:\n\n```toml\n[alias]\nrr = \"run --release\"\nrecursive_example = \"rr --example recursions\"\n```\n\n### `[build]`\n\nThe `[build]` table controls build-time operations and compiler settings.\n\n#### `build.jobs`\n* Type: integer or string\n* Default: number of logical CPUs\n* Environment: `CARGO_BUILD_JOBS`\n\nSets the maximum number of compiler processes to run in parallel. If negative,\nit sets the maximum number of compiler processes to the number of logical CPUs\nplus provided value. Should not be 0. If a string `default` is provided, it sets\nthe value back to defaults.\n\nCan be overridden with the `--jobs` CLI option.\n\n#### `build.rustc`\n* Type: string (program path)\n* Default: `\"rustc\"`\n* Environment: `CARGO_BUILD_RUSTC` or `RUSTC`\n\nSets the executable to use for `rustc`.\n\n#### `build.rustc-wrapper`\n* Type: string (program path)\n* Default: none\n* Environment: `CARGO_BUILD_RUSTC_WRAPPER` or `RUSTC_WRAPPER`\n\nSets a wrapper to execute instead of `rustc`. The first argument passed to the\nwrapper is the path to the actual executable to use\n(i.e., `build.rustc`, if that is set, or `\"rustc\"` otherwise).\n\n#### `build.rustc-workspace-wrapper`\n* Type: string (program path)\n* Default: none\n* Environment: `CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER` or `RUSTC_WORKSPACE_WRAPPER`\n\nSets a wrapper to execute instead of `rustc`, for workspace members only. When building a\nsingle-package project without workspaces, that package is considered to be the workspace. The first\nargument passed to the wrapper is the path to the actual executable to use (i.e., `build.rustc`, if\nthat is set, or `\"rustc\"` otherwise). It affects the filename hash so that artifacts produced by the\nwrapper are cached separately.\n\nIf both `rustc-wrapper` and `rustc-workspace-wrapper` are set, then they will be nested:\nthe final invocation is `$RUSTC_WRAPPER $RUSTC_WORKSPACE_WRAPPER $RUSTC`.\n\n#### `build.rustdoc`\n* Type: string (program path)\n* Default: `\"rustdoc\"`\n* Environment: `CARGO_BUILD_RUSTDOC` or `RUSTDOC`\n\nSets the executable to use for `rustdoc`.\n\n#### `build.target`\n* Type: string or array of strings\n* Default: host platform\n* Environment: `CARGO_BUILD_TARGET`\n\nThe default [target platform triples][target triple] to compile to.\n\nPossible values:\n- Any supported target in `rustc --print target-list`.\n- `\"host-tuple\"`, which will internally be substituted by the host's target. This can be particularly useful if you're cross-compiling some crates, and don't want to specify your host's machine as a target (for instance, an `xtask` in a shared project that may be worked on by many hosts).\n- A path to a custom target specification. See [Custom Target Lookup Path](../../rustc/targets/custom.html#custom-target-lookup-path) for more information.\n\nCan be overridden with the `--target` CLI option.\n\n```toml\n[build]\ntarget = [\"x86_64-unknown-linux-gnu\", \"i686-unknown-linux-gnu\"]\n```\n\n#### `build.target-dir`\n* Type: string (path)\n* Default: `\"target\"`\n* Environment: `CARGO_BUILD_TARGET_DIR` or `CARGO_TARGET_DIR`\n\nThe path to where all compiler output is placed. The default if not specified\nis a directory named `target` located at the root of the workspace.\n\nCan be overridden with the `--target-dir` CLI option.\n\nFor more information see the [build cache documentation](../reference/build-cache.md).\n\n#### `build.build-dir`\n\n* Type: string (path)\n* Default: Defaults to the value of `build.target-dir`\n* Environment: `CARGO_BUILD_BUILD_DIR`\n\nThe directory where intermediate build artifacts will be stored.\nIntermediate artifacts are produced by Rustc/Cargo during the build process.\n\nThis option supports path templating.\n\nAvailable template variables:\n* `{workspace-root}` resolves to root of the current workspace.\n* `{cargo-cache-home}` resolves to `CARGO_HOME`\n* `{workspace-path-hash}` resolves to a hash of the manifest path\n\nFor more information see the [build cache documentation](../reference/build-cache.md).\n\n#### `build.rustflags`\n* Type: string or array of strings\n* Default: none\n* Environment: `CARGO_BUILD_RUSTFLAGS` or `CARGO_ENCODED_RUSTFLAGS` or `RUSTFLAGS`\n\nExtra command-line flags to pass to `rustc`. The value may be an array of\nstrings or a space-separated string.\n\nThere are four mutually exclusive sources of extra flags. They are checked in\norder, with the first one being used:\n\n1. `CARGO_ENCODED_RUSTFLAGS` environment variable.\n2. `RUSTFLAGS` environment variable.\n3. All matching `target.<triple>.rustflags` and `target.<cfg>.rustflags`\n   config entries joined together.\n4. `build.rustflags` config value.\n\nAdditional flags may also be passed with the [`cargo rustc`] command.\n\nIf the `--target` flag (or [`build.target`](#buildtarget)) is used, then the\nflags will only be passed to the compiler for the target. Things being built\nfor the host, such as build scripts or proc macros, will not receive the args.\nWithout `--target`, the flags will be passed to all compiler invocations\n(including build scripts and proc macros) because dependencies are shared. If\nyou have args that you do not want to pass to build scripts or proc macros and\nare building for the host, pass `--target` with the [host triple][target triple].\n\nIt is not recommended to pass in flags that Cargo itself usually manages. For\nexample, the flags driven by [profiles](profiles.md) are best handled by setting the\nappropriate profile setting.\n\n> **Caution**: Due to the low-level nature of passing flags directly to the\n> compiler, this may cause a conflict with future versions of Cargo which may\n> issue the same or similar flags on its own which may interfere with the\n> flags you specify. This is an area where Cargo may not always be backwards\n> compatible.\n\n#### `build.rustdocflags`\n* Type: string or array of strings\n* Default: none\n* Environment: `CARGO_BUILD_RUSTDOCFLAGS` or `CARGO_ENCODED_RUSTDOCFLAGS` or `RUSTDOCFLAGS`\n\nExtra command-line flags to pass to `rustdoc`. The value may be an array of\nstrings or a space-separated string.\n\nThere are four mutually exclusive sources of extra flags. They are checked in\norder, with the first one being used:\n\n1. `CARGO_ENCODED_RUSTDOCFLAGS` environment variable.\n2. `RUSTDOCFLAGS` environment variable.\n3. All matching `target.<triple>.rustdocflags` config entries joined together.\n4. `build.rustdocflags` config value.\n\nAdditional flags may also be passed with the [`cargo rustdoc`] command.\n\n> **Caution**: Due to the low-level nature of passing flags directly to the\n> compiler, this may cause a conflict with future versions of Cargo which may\n> issue the same or similar flags on its own which may interfere with the\n> flags you specify. This is an area where Cargo may not always be backwards\n> compatible.\n\n#### `build.incremental`\n* Type: bool\n* Default: from profile\n* Environment: `CARGO_BUILD_INCREMENTAL` or `CARGO_INCREMENTAL`\n\nWhether or not to perform [incremental compilation]. The default if not set is\nto use the value from the [profile](profiles.md#incremental). Otherwise this overrides the setting of\nall profiles.\n\nThe `CARGO_INCREMENTAL` environment variable can be set to `1` to force enable\nincremental compilation for all profiles, or `0` to disable it. This env var\noverrides the config setting.\n\n#### `build.dep-info-basedir`\n* Type: string (path)\n* Default: none\n* Environment: `CARGO_BUILD_DEP_INFO_BASEDIR`\n\nStrips the given path prefix from [dep\ninfo](../reference/build-cache.md#dep-info-files) file paths. This config setting\nis intended to convert absolute paths to relative paths for tools that require\nrelative paths.\n\nThe setting itself is a config-relative path. So, for example, a value of\n`\".\"` would strip all paths starting with the parent directory of the `.cargo`\ndirectory.\n\n#### `build.pipelining`\n\nThis option is deprecated and unused. Cargo always has pipelining enabled.\n\n### `[credential-alias]`\n* Type: string or array of strings\n* Default: empty\n* Environment: `CARGO_CREDENTIAL_ALIAS_<name>`\n\nThe `[credential-alias]` table defines credential provider aliases.\nThese aliases can be referenced as an element of the `registry.global-credential-providers`\narray, or as a credential provider for a specific registry\nunder `registries.<NAME>.credential-provider`.\n\nIf specified as a string, the value will be split on spaces into path and arguments.\n\nFor example, to define an alias called `my-alias`:\n\n```toml\n[credential-alias]\nmy-alias = [\"/usr/bin/cargo-credential-example\", \"--argument\", \"value\", \"--flag\"]\n```\nSee [Registry Authentication](registry-authentication.md) for more information.\n\n### `[doc]`\n\nThe `[doc]` table defines options for the [`cargo doc`] command.\n\n#### `doc.browser`\n\n* Type: string or array of strings ([program path with args])\n* Default: `BROWSER` environment variable, or, if that is missing,\n  opening the link in a system specific way\n\nThis option sets the browser to be used by [`cargo doc`], overriding the\n`BROWSER` environment variable when opening documentation with the `--open`\noption.\n\n### `[cargo-new]`\n\nThe `[cargo-new]` table defines defaults for the [`cargo new`] command.\n\n#### `cargo-new.name`\n\nThis option is deprecated and unused.\n\n#### `cargo-new.email`\n\nThis option is deprecated and unused.\n\n#### `cargo-new.vcs`\n* Type: string\n* Default: `\"git\"` or `\"none\"`\n* Environment: `CARGO_CARGO_NEW_VCS`\n\nSpecifies the source control system to use for initializing a new repository.\nValid values are `git`, `hg` (for Mercurial), `pijul`, `fossil` or `none` to\ndisable this behavior. Defaults to `git`, or `none` if already inside a VCS\nrepository. Can be overridden with the `--vcs` CLI option.\n\n### `[env]`\n\nThe `[env]` section allows you to set additional environment variables for\nbuild scripts, rustc invocations, `cargo run` and `cargo build`.\n\n```toml\n[env]\nOPENSSL_DIR = \"/opt/openssl\"\n```\n\nBy default, the variables specified will not override values that already exist\nin the environment. This behavior can be changed by setting the `force` flag.\n\nSetting the `relative` flag evaluates the value as a config-relative path that\nis relative to the parent directory of the `.cargo` directory that contains the\n`config.toml` file. The value of the environment variable will be the full\nabsolute path.\n\n```toml\n[env]\nTMPDIR = { value = \"/home/tmp\", force = true }\nOPENSSL_DIR = { value = \"vendor/openssl\", relative = true }\n```\n\n### `[future-incompat-report]`\n\nThe `[future-incompat-report]` table controls setting for [future incompat reporting](future-incompat-report.md)\n\n#### `future-incompat-report.frequency`\n* Type: string\n* Default: `\"always\"`\n* Environment: `CARGO_FUTURE_INCOMPAT_REPORT_FREQUENCY`\n\nControls how often we display a notification to the terminal when a future incompat report is available. Possible values:\n\n* `always` (default): Always display a notification when a command (e.g. `cargo build`) produces a future incompat report\n* `never`: Never display a notification\n\n### `[cache]`\n\nThe `[cache]` table defines settings for cargo's caches.\n\n#### Global caches\n\nWhen running `cargo` commands, Cargo will automatically track which files you are using within the global cache.\nPeriodically, Cargo will delete files that have not been used for some period of time.\nIt will delete files that have to be downloaded from the network if they have not been used in 3 months. Files that can be generated without network access will be deleted if they have not been used in 1 month.\n\nThe automatic deletion of files only occurs when running commands that are already doing a significant amount of work, such as all of the build commands (`cargo build`, `cargo test`, `cargo check`, etc.), and `cargo fetch`.\n\nAutomatic deletion is disabled if cargo is offline such as with `--offline` or `--frozen` to avoid deleting artifacts that may need to be used if you are offline for a long period of time.\n\n> **Note**: This tracking is currently only implemented for the global cache in Cargo's home directory.\n> This includes registry indexes and source files downloaded from registries and git dependencies.\n> Support for tracking build artifacts is not yet implemented, and tracked in [cargo#13136](https://github.com/rust-lang/cargo/issues/13136).\n>\n> Additionally, there is an unstable feature to support *manually* triggering cache cleaning, and to further customize the configuration options.\n> See the [Unstable chapter](unstable.md#gc) for more information.\n\n#### `cache.auto-clean-frequency`\n* Type: string\n* Default: `\"1 day\"`\n* Environment: `CARGO_CACHE_AUTO_CLEAN_FREQUENCY`\n\nThis option defines how often Cargo will automatically delete unused files in the global cache.\nThis does *not* define how old the files must be, those thresholds are described [above](#global-caches).\n\nIt supports the following settings:\n\n* `\"never\"` --- Never deletes old files.\n* `\"always\"` --- Checks to delete old files every time Cargo runs.\n* An integer followed by \"seconds\", \"minutes\", \"hours\", \"days\", \"weeks\", or \"months\" --- Checks to delete old files at most the given time frame.\n\n### `[http]`\n\nThe `[http]` table defines settings for HTTP behavior. This includes fetching\ncrate dependencies and accessing remote git repositories.\n\n#### `http.debug`\n* Type: boolean\n* Default: false\n* Environment: `CARGO_HTTP_DEBUG`\n\nIf `true`, enables debugging of HTTP requests. The debug information can be\nseen by setting the `CARGO_LOG=network=debug` environment\nvariable (or use `network=trace` for even more information).\n\nBe wary when posting logs from this output in a public location. The output\nmay include headers with authentication tokens which you don't want to leak!\nBe sure to review logs before posting them.\n\n#### `http.proxy`\n* Type: string\n* Default: none\n* Environment: `CARGO_HTTP_PROXY` or `HTTPS_PROXY` or `https_proxy` or `http_proxy`\n\nSets an HTTP and HTTPS proxy to use. The format is in [libcurl format] as in\n`[protocol://]host[:port]`. If not set, Cargo will also check the `http.proxy`\nsetting in your global git configuration. If none of those are set, the\n`HTTPS_PROXY` or `https_proxy` environment variables set the proxy for HTTPS\nrequests, and `http_proxy` sets it for HTTP requests.\n\n#### `http.timeout`\n* Type: integer\n* Default: 30\n* Environment: `CARGO_HTTP_TIMEOUT` or `HTTP_TIMEOUT`\n\nSets the timeout for each HTTP request, in seconds.\n\n#### `http.cainfo`\n* Type: string (path)\n* Default: none\n* Environment: `CARGO_HTTP_CAINFO`\n\nPath to a Certificate Authority (CA) bundle file, used to verify TLS\ncertificates. If not specified, Cargo attempts to use the system certificates.\n\n#### `http.proxy-cainfo`\n* Type: string (path)\n* Default: falls back to `http.cainfo` if not set\n* Environment: `CARGO_HTTP_PROXY_CAINFO`\n\nPath to a Certificate Authority (CA) bundle file, used to verify proxy TLS\ncertificates.\n\n#### `http.check-revoke`\n* Type: boolean\n* Default: true (Windows) false (all others)\n* Environment: `CARGO_HTTP_CHECK_REVOKE`\n\nThis determines whether or not TLS certificate revocation checks should be\nperformed. This only works on Windows.\n\n#### `http.ssl-version`\n* Type: string or min/max table\n* Default: none\n* Environment: `CARGO_HTTP_SSL_VERSION`\n\nThis sets the minimum TLS version to use. It takes a string, with one of the\npossible values of `\"default\"`, `\"tlsv1\"`, `\"tlsv1.0\"`, `\"tlsv1.1\"`, `\"tlsv1.2\"`, or\n`\"tlsv1.3\"`.\n\nThis may alternatively take a table with two keys, `min` and `max`, which each\ntake a string value of the same kind that specifies the minimum and maximum\nrange of TLS versions to use.\n\nThe default is a minimum version of `\"tlsv1.0\"` and a max of the newest version\nsupported on your platform, typically `\"tlsv1.3\"`.\n\n#### `http.low-speed-limit`\n* Type: integer\n* Default: 10\n* Environment: `CARGO_HTTP_LOW_SPEED_LIMIT`\n\nThis setting controls timeout behavior for slow connections. If the average\ntransfer speed in bytes per second is below the given value for\n[`http.timeout`](#httptimeout) seconds (default 30 seconds), then the\nconnection is considered too slow and Cargo will abort and retry.\n\n#### `http.multiplexing`\n* Type: boolean\n* Default: true\n* Environment: `CARGO_HTTP_MULTIPLEXING`\n\nWhen `true`, Cargo will attempt to use the HTTP2 protocol with multiplexing.\nThis allows multiple requests to use the same connection, usually improving\nperformance when fetching multiple files. If `false`, Cargo will use HTTP 1.1\nwithout pipelining.\n\n#### `http.user-agent`\n* Type: string\n* Default: Cargo's version\n* Environment: `CARGO_HTTP_USER_AGENT`\n\nSpecifies a custom user-agent header to use. The default if not specified is a\nstring that includes Cargo's version.\n\n### `[install]`\n\nThe `[install]` table defines defaults for the [`cargo install`] command.\n\n#### `install.root`\n* Type: string (path)\n* Default: Cargo's home directory\n* Environment: `CARGO_INSTALL_ROOT`\n\nSets the path to the root directory for installing executables for [`cargo\ninstall`]. Executables go into a `bin` directory underneath the root.\n\nTo track information of installed executables, some extra files, such as\n`.crates.toml` and `.crates2.json`, are also created under this root.\n\nThe default if not specified is Cargo's home directory (default `.cargo` in\nyour home directory).\n\nCan be overridden with the `--root` command-line option.\n\n### `[net]`\n\nThe `[net]` table controls networking configuration.\n\n#### `net.retry`\n* Type: integer\n* Default: 3\n* Environment: `CARGO_NET_RETRY`\n\nNumber of times to retry possibly spurious network errors.\n\n#### `net.git-fetch-with-cli`\n* Type: boolean\n* Default: false\n* Environment: `CARGO_NET_GIT_FETCH_WITH_CLI`\n\nIf this is `true`, then Cargo will use the `git` executable to fetch registry\nindexes and git dependencies. If `false`, then it uses a built-in `git`\nlibrary.\n\nSetting this to `true` can be helpful if you have special authentication\nrequirements that Cargo does not support. See [Git\nAuthentication](../appendix/git-authentication.md) for more information about\nsetting up git authentication.\n\n#### `net.offline`\n* Type: boolean\n* Default: false\n* Environment: `CARGO_NET_OFFLINE`\n\nIf this is `true`, then Cargo will avoid accessing the network, and attempt to\nproceed with locally cached data. If `false`, Cargo will access the network as\nneeded, and generate an error if it encounters a network error.\n\nCan be overridden with the `--offline` command-line option.\n\n#### `net.ssh`\n\nThe `[net.ssh]` table contains settings for SSH connections.\n\n#### `net.ssh.known-hosts`\n* Type: array of strings\n* Default: see description\n* Environment: not supported\n\nThe `known-hosts` array contains a list of SSH host keys that should be\naccepted as valid when connecting to an SSH server (such as for SSH git\ndependencies). Each entry should be a string in a format similar to OpenSSH\n`known_hosts` files. Each string should start with one or more hostnames\nseparated by commas, a space, the key type name, a space, and the\nbase64-encoded key. For example:\n\n```toml\n[net.ssh]\nknown-hosts = [\n    \"example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFO4Q5T0UV0SQevair9PFwoxY9dl4pQl3u5phoqJH3cF\"\n]\n```\n\nCargo will attempt to load known hosts keys from common locations supported in\nOpenSSH, and will join those with any listed in a Cargo configuration file.\nIf any matching entry has the correct key, the connection will be allowed.\n\nCargo comes with the host keys for [github.com][github-keys] built-in. If\nthose ever change, you can add the new keys to the config or known_hosts file.\n\nSee [Git Authentication](../appendix/git-authentication.md#ssh-known-hosts)\nfor more details.\n\n[github-keys]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints\n\n### `[patch]`\n\nJust as you can override dependencies using [`[patch]` in\n`Cargo.toml`](overriding-dependencies.md#the-patch-section), you can\noverride them in the cargo configuration file to apply those patches to\nany affected build. The format is identical to the one used in\n`Cargo.toml`.\n\nSince `.cargo/config.toml` files are not usually checked into source\ncontrol, you should prefer patching using `Cargo.toml` where possible to\nensure that other developers can compile your crate in their own\nenvironments. Patching through cargo configuration files is generally\nonly appropriate when the patch section is automatically generated by an\nexternal build tool.\n\nIf a given dependency is patched both in a cargo configuration file and\na `Cargo.toml` file, the patch in the configuration file is used. If\nmultiple configuration files patch the same dependency, standard cargo\nconfiguration merging is used, which prefers the value defined closest\nto the current directory, with `$HOME/.cargo/config.toml` taking the\nlowest precedence.\n\nRelative `path` dependencies in such a `[patch]` section are resolved\nrelative to the configuration file they appear in.\n\n### `[profile]`\n\nThe `[profile]` table can be used to globally change profile settings, and\noverride settings specified in `Cargo.toml`. It has the same syntax and\noptions as profiles specified in `Cargo.toml`. See the [Profiles chapter] for\ndetails about the options.\n\n[Profiles chapter]: profiles.md\n\n#### `[profile.<name>.build-override]`\n* Environment: `CARGO_PROFILE_<name>_BUILD_OVERRIDE_<key>`\n\nThe build-override table overrides settings for build scripts, proc macros,\nand their dependencies. It has the same keys as a normal profile. See the\n[overrides section](profiles.md#overrides) for more details.\n\n#### `[profile.<name>.package.<name>]`\n* Environment: not supported\n\nThe package table overrides settings for specific packages. It has the same\nkeys as a normal profile, minus the `panic`, `lto`, and `rpath` settings. See\nthe [overrides section](profiles.md#overrides) for more details.\n\n#### `profile.<name>.codegen-units`\n* Type: integer\n* Default: See profile docs.\n* Environment: `CARGO_PROFILE_<name>_CODEGEN_UNITS`\n\nSee [codegen-units](profiles.md#codegen-units).\n\n#### `profile.<name>.debug`\n* Type: integer or boolean\n* Default: See profile docs.\n* Environment: `CARGO_PROFILE_<name>_DEBUG`\n\nSee [debug](profiles.md#debug).\n\n#### `profile.<name>.split-debuginfo`\n* Type: string\n* Default: See profile docs.\n* Environment: `CARGO_PROFILE_<name>_SPLIT_DEBUGINFO`\n\nSee [split-debuginfo](profiles.md#split-debuginfo).\n\n#### `profile.<name>.debug-assertions`\n* Type: boolean\n* Default: See profile docs.\n* Environment: `CARGO_PROFILE_<name>_DEBUG_ASSERTIONS`\n\nSee [debug-assertions](profiles.md#debug-assertions).\n\n#### `profile.<name>.incremental`\n* Type: boolean\n* Default: See profile docs.\n* Environment: `CARGO_PROFILE_<name>_INCREMENTAL`\n\nSee [incremental](profiles.md#incremental).\n\n#### `profile.<name>.lto`\n* Type: string or boolean\n* Default: See profile docs.\n* Environment: `CARGO_PROFILE_<name>_LTO`\n\nSee [lto](profiles.md#lto).\n\n#### `profile.<name>.overflow-checks`\n* Type: boolean\n* Default: See profile docs.\n* Environment: `CARGO_PROFILE_<name>_OVERFLOW_CHECKS`\n\nSee [overflow-checks](profiles.md#overflow-checks).\n\n#### `profile.<name>.opt-level`\n* Type: integer or string\n* Default: See profile docs.\n* Environment: `CARGO_PROFILE_<name>_OPT_LEVEL`\n\nSee [opt-level](profiles.md#opt-level).\n\n#### `profile.<name>.panic`\n* Type: string\n* Default: See profile docs.\n* Environment: `CARGO_PROFILE_<name>_PANIC`\n\nSee [panic](profiles.md#panic).\n\n#### `profile.<name>.rpath`\n* Type: boolean\n* Default: See profile docs.\n* Environment: `CARGO_PROFILE_<name>_RPATH`\n\nSee [rpath](profiles.md#rpath).\n\n#### `profile.<name>.strip`\n* Type: string or boolean\n* Default: See profile docs.\n* Environment: `CARGO_PROFILE_<name>_STRIP`\n\nSee [strip](profiles.md#strip).\n\n### `[resolver]`\n\nThe `[resolver]` table overrides [dependency resolution behavior](resolver.md) for local development (e.g. excludes `cargo install`).\n\n#### `resolver.incompatible-rust-versions`\n* Type: string\n* Default: See [`resolver`](resolver.md#resolver-versions) docs\n* Environment: `CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS`\n\nWhen resolving which version of a dependency to use, select how versions with incompatible `package.rust-version`s are treated.\nValues include:\n- `allow`: treat `rust-version`-incompatible versions like any other version\n- `fallback`: only consider `rust-version`-incompatible versions if no other version matched\n\nCan be overridden with\n- `--ignore-rust-version` CLI option\n- Setting the dependency's version requirement higher than any version with a compatible `rust-version`\n- Specifying the version to `cargo update` with `--precise`\n\nSee the [resolver](resolver.md#rust-version) chapter for more details.\n\n> **MSRV:**\n> - `allow` is supported on any version\n> - `fallback` is respected as of 1.84\n\n### `[registries]`\n\nThe `[registries]` table is used for specifying additional [registries]. It\nconsists of a sub-table for each named registry.\n\n#### `registries.<name>.index`\n* Type: string (url)\n* Default: none\n* Environment: `CARGO_REGISTRIES_<name>_INDEX`\n\nSpecifies the URL of the index for the registry.\n\n#### `registries.<name>.token`\n* Type: string\n* Default: none\n* Environment: `CARGO_REGISTRIES_<name>_TOKEN`\n\nSpecifies the authentication token for the given registry. This value should\nonly appear in the [credentials](#credentials) file. This is used for registry\ncommands like [`cargo publish`] that require authentication.\n\nCan be overridden with the `--token` command-line option.\n\n#### `registries.<name>.credential-provider`\n* Type: string or array of path and arguments\n* Default: none\n* Environment: `CARGO_REGISTRIES_<name>_CREDENTIAL_PROVIDER`\n\nSpecifies the credential provider for the given registry. If not set, the\nproviders in [`registry.global-credential-providers`](#registryglobal-credential-providers)\nwill be used.\n\nIf specified as a string, path and arguments will be split on spaces. For\npaths or arguments that contain spaces, use an array.\n\nIf the value exists in the [`[credential-alias]`](#credential-alias) table, the alias will be used.\n\nSee [Registry Authentication](registry-authentication.md) for more information.\n\n#### `registries.crates-io.protocol`\n* Type: string\n* Default: `\"sparse\"`\n* Environment: `CARGO_REGISTRIES_CRATES_IO_PROTOCOL`\n\nSpecifies the protocol used to access crates.io. Allowed values are `git` or `sparse`.\n\n`git` causes Cargo to clone the entire index of all packages ever published to [crates.io] from <https://github.com/rust-lang/crates.io-index/>.\nThis can have performance implications due to the size of the index.\n`sparse` is a newer protocol which uses HTTPS to download only what is necessary from <https://index.crates.io/>.\nThis can result in a significant performance improvement for resolving new dependencies in most situations.\n\nMore information about registry protocols may be found in the [Registries chapter](registries.md).\n\n### `[registry]`\n\nThe `[registry]` table controls the default registry used when one is not\nspecified.\n\n#### `registry.index`\n\nThis value is no longer accepted and should not be used.\n\n#### `registry.default`\n* Type: string\n* Default: `\"crates-io\"`\n* Environment: `CARGO_REGISTRY_DEFAULT`\n\nThe name of the registry (from the [`registries` table](#registries)) to use\nby default for registry commands like [`cargo publish`].\n\nCan be overridden with the `--registry` command-line option.\n\n#### `registry.credential-provider`\n* Type: string or array of path and arguments\n* Default: none\n* Environment: `CARGO_REGISTRY_CREDENTIAL_PROVIDER`\n\nSpecifies the credential provider for [crates.io]. If not set, the\nproviders in [`registry.global-credential-providers`](#registryglobal-credential-providers)\nwill be used.\n\nIf specified as a string, path and arguments will be split on spaces. For\npaths or arguments that contain spaces, use an array.\n\nIf the value exists in the `[credential-alias]` table, the alias will be used.\n\nSee [Registry Authentication](registry-authentication.md) for more information.\n\n#### `registry.token`\n* Type: string\n* Default: none\n* Environment: `CARGO_REGISTRY_TOKEN`\n\nSpecifies the authentication token for [crates.io]. This value should only\nappear in the [credentials](#credentials) file. This is used for registry\ncommands like [`cargo publish`] that require authentication.\n\nCan be overridden with the `--token` command-line option.\n\n#### `registry.global-credential-providers`\n* Type: array\n* Default: `[\"cargo:token\"]`\n* Environment: `CARGO_REGISTRY_GLOBAL_CREDENTIAL_PROVIDERS`\n\nSpecifies the list of global credential providers. If credential provider is not set\nfor a specific registry using `registries.<name>.credential-provider`, Cargo will use\nthe credential providers in this list. Providers toward the end of the list have precedence.\n\nPath and arguments are split on spaces. If the path or arguments contains spaces, the credential\nprovider should be defined in the [`[credential-alias]`](#credential-alias) table and\nreferenced here by its alias.\n\nSee [Registry Authentication](registry-authentication.md) for more information.\n\n### `[source]`\n\nThe `[source]` table defines the registry sources available. See [Source\nReplacement] for more information. It consists of a sub-table for each named\nsource. A source should only define one kind (directory, registry,\nlocal-registry, or git).\n\n#### `source.<name>.replace-with`\n* Type: string\n* Default: none\n* Environment: not supported\n\nIf set, replace this source with the given named source or named registry.\n\n#### `source.<name>.directory`\n* Type: string (path)\n* Default: none\n* Environment: not supported\n\nSets the path to a directory to use as a directory source.\n\n#### `source.<name>.registry`\n* Type: string (url)\n* Default: none\n* Environment: not supported\n\nSets the URL to use for a registry source.\n\n#### `source.<name>.local-registry`\n* Type: string (path)\n* Default: none\n* Environment: not supported\n\nSets the path to a directory to use as a local registry source.\n\n#### `source.<name>.git`\n* Type: string (url)\n* Default: none\n* Environment: not supported\n\nSets the URL to use for a git repository source.\n\n#### `source.<name>.branch`\n* Type: string\n* Default: none\n* Environment: not supported\n\nSets the branch name to use for a git repository.\n\nIf none of `branch`, `tag`, or `rev` is set, defaults to the `master` branch.\n\n#### `source.<name>.tag`\n* Type: string\n* Default: none\n* Environment: not supported\n\nSets the tag name to use for a git repository.\n\nIf none of `branch`, `tag`, or `rev` is set, defaults to the `master` branch.\n\n#### `source.<name>.rev`\n* Type: string\n* Default: none\n* Environment: not supported\n\nSets the [revision] to use for a git repository.\n\nIf none of `branch`, `tag`, or `rev` is set, defaults to the `master` branch.\n\n\n### `[target]`\n\nThe `[target]` table is used for specifying settings for specific platform\ntargets. It consists of a sub-table which is either a [platform triple][target triple] \nor a [`cfg()` expression]. The given values will be used if the target platform\nmatches either the `<triple>` value or the `<cfg>` expression.\n\n```toml\n[target.thumbv7m-none-eabi]\nlinker = \"arm-none-eabi-gcc\"\nrunner = \"my-emulator\"\nrustflags = [\"…\", \"…\"]\n\n[target.'cfg(all(target_arch = \"arm\", target_os = \"none\"))']\nrunner = \"my-arm-wrapper\"\nrustflags = [\"…\", \"…\"]\n```\n\n`cfg` values come from those built-in to the compiler (run `rustc --print=cfg`\nto view) and extra `--cfg` flags passed to `rustc` (such as those defined in\n`RUSTFLAGS`). Do not try to match on `debug_assertions`, `test`, Cargo features\nlike `feature=\"foo\"`, or values set by [build scripts].\n\nIf using a target spec JSON file, the [`<triple>`] value is the filename stem.\nFor example `--target foo/bar.json` would match `[target.bar]`.\n\n#### `target.<triple>.ar`\n\nThis option is deprecated and unused.\n\n#### `target.<triple>.linker`\n* Type: string (program path)\n* Default: none\n* Environment: `CARGO_TARGET_<triple>_LINKER`\n\nSpecifies the linker which is passed to `rustc` (via [`-C linker`]) when the\n[`<triple>`] is being compiled for. By default, the linker is not overridden.\n\n#### `target.<cfg>.linker`\nThis is similar to the [target linker](#targettriplelinker), but using\na [`cfg()` expression]. If both a [`<triple>`] and `<cfg>` runner match,\nthe `<triple>` will take precedence. It is an error if more than one\n`<cfg>` runner matches the current target.\n\n#### `target.<triple>.runner`\n* Type: string or array of strings ([program path with args])\n* Default: none\n* Environment: `CARGO_TARGET_<triple>_RUNNER`\n\nIf a runner is provided, executables for the target [`<triple>`] will be\nexecuted by invoking the specified runner with the actual executable passed as\nan argument. This applies to [`cargo run`], [`cargo test`] and [`cargo bench`]\ncommands. By default, compiled executables are executed directly.\n\n#### `target.<cfg>.runner`\n\nThis is similar to the [target runner](#targettriplerunner), but using\na [`cfg()` expression]. If both a [`<triple>`] and `<cfg>` runner match,\nthe `<triple>` will take precedence. It is an error if more than one\n`<cfg>` runner matches the current target.\n\n#### `target.<triple>.rustflags`\n* Type: string or array of strings\n* Default: none\n* Environment: `CARGO_TARGET_<triple>_RUSTFLAGS`\n\nPasses a set of custom flags to the compiler for this [`<triple>`]. \nThe value may be an array of strings or a space-separated string.\n\nSee [`build.rustflags`](#buildrustflags) for more details on the different\nways to specific extra flags.\n\n#### `target.<cfg>.rustflags`\n\nThis is similar to the [target rustflags](#targettriplerustflags), but\nusing a [`cfg()` expression]. If several `<cfg>` and [`<triple>`] entries\nmatch the current target, the flags are joined together.\n\n#### `target.<triple>.rustdocflags`\n* Type: string or array of strings\n* Default: none\n* Environment: `CARGO_TARGET_<triple>_RUSTDOCFLAGS`\n\nPasses a set of custom flags to the compiler for this [`<triple>`].\nThe value may be an array of strings or a space-separated string.\n\nSee [`build.rustdocflags`](#buildrustdocflags) for more details on the different\nways to specific extra flags.\n\n#### `target.<triple>.<links>`\n\nThe links sub-table provides a way to [override a build script]. When\nspecified, the build script for the given `links` library will not be\nrun, and the given values will be used instead.\n\n```toml\n[target.x86_64-unknown-linux-gnu.foo]\nrustc-link-lib = [\"foo\"]\nrustc-link-search = [\"/path/to/foo\"]\nrustc-flags = \"-L /some/path\"\nrustc-cfg = ['key=\"value\"']\nrustc-env = {key = \"value\"}\nrustc-cdylib-link-arg = [\"…\"]\nmetadata_key1 = \"value\"\nmetadata_key2 = \"value\"\n```\n\n### `[term]`\n\nThe `[term]` table controls terminal output and interaction.\n\n#### `term.quiet`\n* Type: boolean\n* Default: false\n* Environment: `CARGO_TERM_QUIET`\n\nControls whether or not log messages are displayed by Cargo.\n\nSpecifying the `--quiet` flag will override and force quiet output.\nSpecifying the `--verbose` flag will override and disable quiet output.\n\n#### `term.verbose`\n* Type: boolean\n* Default: false\n* Environment: `CARGO_TERM_VERBOSE`\n\nControls whether or not extra detailed messages are displayed by Cargo.\n\nSpecifying the `--quiet` flag will override and disable verbose output.\nSpecifying the `--verbose` flag will override and force verbose output.\n\n#### `term.color`\n* Type: string\n* Default: `\"auto\"`\n* Environment: `CARGO_TERM_COLOR`\n\nControls whether or not colored output is used in the terminal. Possible values:\n\n* `auto` (default): Automatically detect if color support is available on the\n  terminal.\n* `always`: Always display colors.\n* `never`: Never display colors.\n\nCan be overridden with the `--color` command-line option.\n\n#### `term.hyperlinks`\n* Type: bool\n* Default: auto-detect\n* Environment: `CARGO_TERM_HYPERLINKS`\n\nControls whether or not hyperlinks are used in the terminal.\n\n#### `term.unicode`\n* Type: bool\n* Default: auto-detect\n* Environment: `CARGO_TERM_UNICODE`\n\nControl whether output can be rendered using non-ASCII unicode characters.\n\n#### `term.progress.when`\n* Type: string\n* Default: `\"auto\"`\n* Environment: `CARGO_TERM_PROGRESS_WHEN`\n\nControls whether or not progress bar is shown in the terminal. Possible values:\n\n* `auto` (default): Intelligently guess whether to show progress bar.\n* `always`: Always show progress bar.\n* `never`: Never show progress bar.\n\n#### `term.progress.width`\n* Type: integer\n* Default: none\n* Environment: `CARGO_TERM_PROGRESS_WIDTH`\n\nSets the width for progress bar.\n\n#### `term.progress.term-integration`\n* Type: bool\n* Default: auto-detect\n* Environment: `CARGO_TERM_PROGRESS_TERM_INTEGRATION`\n\nReport progress to the terminal emulator for display in places like the task bar.\n\n[`cargo bench`]: ../commands/cargo-bench.md\n[`cargo login`]: ../commands/cargo-login.md\n[`cargo logout`]: ../commands/cargo-logout.md\n[`cargo doc`]: ../commands/cargo-doc.md\n[`cargo new`]: ../commands/cargo-new.md\n[`cargo publish`]: ../commands/cargo-publish.md\n[`cargo run`]: ../commands/cargo-run.md\n[`cargo rustc`]: ../commands/cargo-rustc.md\n[`cargo test`]: ../commands/cargo-test.md\n[`cargo rustdoc`]: ../commands/cargo-rustdoc.md\n[`cargo install`]: ../commands/cargo-install.md\n[env]: environment-variables.md\n[`cfg()` expression]: ../../reference/conditional-compilation.html\n[build scripts]: build-scripts.md\n[`-C linker`]: ../../rustc/codegen-options/index.md#linker\n[override a build script]: build-scripts.md#overriding-build-scripts\n[toml]: https://toml.io/\n[incremental compilation]: profiles.md#incremental\n[program path with args]: #executable-paths-with-arguments\n[libcurl format]: https://everything.curl.dev/transfers/conn/proxies#proxy-types\n[source replacement]: source-replacement.md\n[revision]: https://git-scm.com/docs/gitrevisions\n[registries]: registries.md\n[`cargo:token`]: registry-authentication.md#cargotoken\n[crates.io]: https://crates.io/\n[target triple]: ../appendix/glossary.md#target '\"target\" (glossary)'\n[`<triple>`]: ../appendix/glossary.md#target '\"target\" (glossary)'\n"
  },
  {
    "path": "src/doc/src/reference/credential-provider-protocol.md",
    "content": "# Credential Provider Protocol\nThis document describes information for building a Cargo credential provider. For information on\nsetting up or using a credential provider, see [Registry Authentication](registry-authentication.md).\n\nWhen using an external credential provider, Cargo communicates with the credential\nprovider using stdin/stdout messages passed as single lines of JSON.\n\nCargo will always execute the credential provider with the `--cargo-plugin` argument.\nThis enables a credential provider executable to have additional functionality beyond\nwhat Cargo needs. Additional arguments are included in the JSON via the `args` field.\n\n## JSON messages\nThe JSON messages in this document have newlines added for readability.\nActual messages must not contain newlines.\n\n### Credential hello\n* Sent by: credential provider\n* Purpose: used to identify the supported protocols on process startup\n```javascript\n{\n    \"v\":[1]\n}\n```\n\nRequests sent by Cargo will include a `v` field set to one of the versions listed here.\nIf Cargo does not support any of the versions offered by the credential provider, it will issue an\nerror and shut down the credential process.\n\n### Registry information\n* Sent by: Cargo\nNot a message by itself. Included in all messages sent by Cargo as the `registry` field.\n```javascript\n{\n    // Index URL of the registry\n    \"index-url\":\"https://github.com/rust-lang/crates.io-index\",\n    // Name of the registry in configuration (optional)\n    \"name\": \"crates-io\",\n    // HTTP headers received from attempting to access an authenticated registry (optional)\n    \"headers\": [\"WWW-Authenticate: cargo\"]\n}\n```\n\n### Login request\n* Sent by: Cargo\n* Purpose: collect and store credentials\n```javascript\n{\n    // Protocol version\n    \"v\":1,\n    // Action to perform: login\n    \"kind\":\"login\",\n    // Registry information (see Registry information)\n    \"registry\":{\"index-url\":\"sparse+https://registry-url/index/\", \"name\": \"my-registry\"},\n    // User-specified token from stdin or command line (optional)\n    \"token\": \"<the token value>\",\n    // URL that the user could visit to get a token (optional)\n    \"login-url\": \"http://registry-url/login\",\n    // Additional command-line args (optional)\n    \"args\":[]\n}\n```\n\nIf the `token` field is set, then the credential provider should use the token provided. If\nthe `token` is not set, then the credential provider should prompt the user for a token.\n\nIn addition to the arguments that may be passed to the credential provider in\nconfiguration, `cargo login` also supports passing additional command line args\nvia `cargo login -- <additional args>`. These additional arguments will be included\nin the `args` field after any args from Cargo configuration.\n\n### Read request\n* Sent by: Cargo\n* Purpose: Get the credential for reading crate information\n```javascript\n{\n    // Protocol version\n    \"v\":1,\n    // Request kind: get credentials\n    \"kind\":\"get\",\n    // Action to perform: read crate information\n    \"operation\":\"read\",\n    // Registry information (see Registry information)\n    \"registry\":{\"index-url\":\"sparse+https://registry-url/index/\", \"name\": \"my-registry\"},\n    // Additional command-line args (optional)\n    \"args\":[]\n}\n```\n\n### Publish request\n* Sent by: Cargo\n* Purpose: Get the credential for publishing a crate\n```javascript\n{\n    // Protocol version\n    \"v\":1,\n    // Request kind: get credentials\n    \"kind\":\"get\",\n    // Action to perform: publish crate\n    \"operation\":\"publish\",\n    // Crate name\n    \"name\":\"sample\",\n    // Crate version\n    \"vers\":\"0.1.0\",\n    // Crate checksum\n    \"cksum\":\"...\",\n    // Registry information (see Registry information)\n    \"registry\":{\"index-url\":\"sparse+https://registry-url/index/\", \"name\": \"my-registry\"},\n    // Additional command-line args (optional)\n    \"args\":[]\n}\n```\n\n### Get success response\n* Sent by: credential provider\n* Purpose: Gives the credential to Cargo\n```javascript\n{\"Ok\":{\n    // Response kind: this was a get request\n    \"kind\":\"get\",\n    // Token to send to the registry\n    \"token\":\"...\",\n    // Cache control. Can be one of the following:\n    // * \"never\": do not cache\n    // * \"session\": cache for the current cargo session\n    // * \"expires\": cache for the current cargo session until expiration\n    \"cache\":\"expires\",\n    // Unix timestamp (only for \"cache\": \"expires\")\n    \"expiration\":1693942857,\n    // Is the token operation independent?\n    \"operation_independent\":true\n}}\n```\n\nThe `token` will be sent to the registry as the value of the `Authorization` HTTP header.\n\n`operation_independent` indicates whether the token can be cached across different\noperations (such as publishing or fetching). In general, this should be `true` unless\nthe provider wants to generate tokens that are scoped to specific operations.\n\n### Login success response\n* Sent by: credential provider\n* Purpose: Indicates the login was successful\n```javascript\n{\"Ok\":{\n    // Response kind: this was a login request\n    \"kind\":\"login\"\n}}\n```\n\n### Logout success response\n* Sent by: credential provider\n* Purpose: Indicates the logout was successful\n```javascript\n{\"Ok\":{\n    // Response kind: this was a logout request\n    \"kind\":\"logout\"\n}}\n```\n\n### Failure response (URL not supported)\n* Sent by: credential provider\n* Purpose: Gives error information to Cargo\n```javascript\n{\"Err\":{\n    \"kind\":\"url-not-supported\"\n}}\n```\nSent if the credential provider is designed\nto only handle specific registry URLs and the given URL\nis not supported. Cargo will attempt another provider if\navailable.\n\n### Failure response (not found)\n* Sent by: credential provider\n* Purpose: Gives error information to Cargo\n```javascript\n{\"Err\":{\n    // Error: The credential could not be found in the provider.\n    \"kind\":\"not-found\"\n}}\n```\nSent if the credential could not be found. This is expected for\n`get` requests where the credential is not available, or `logout`\nrequests where there is nothing found to erase.\n\n### Failure response (operation not supported)\n* Sent by: credential provider\n* Purpose: Gives error information to Cargo\n```javascript\n{\"Err\":{\n    // Error: The credential could not be found in the provider.\n    \"kind\":\"operation-not-supported\"\n}}\n```\nSent if the credential provider does not support the requested operation.\nIf a provider only supports `get` and a `login` is requested, the\nprovider should respond with this error.\n\n### Failure response (other)\n* Sent by: credential provider\n* Purpose: Gives error information to Cargo\n```javascript\n{\"Err\":{\n    // Error: something else has failed\n    \"kind\":\"other\",\n    // Error message string to be displayed\n    \"message\": \"free form string error message\",\n    // Detailed cause chain for the error (optional)\n    \"caused-by\": [\"cause 1\", \"cause 2\"]\n}}\n```\n\n## Example communication to request a token for reading:\n1. Cargo spawns the credential process, capturing stdin and stdout.\n2. Credential process sends the Hello message to Cargo\n    ```javascript\n    { \"v\": [1] }\n   ```\n3. Cargo sends the CredentialRequest message to the credential process (newlines added for readability).\n    ```javascript\n    {\n        \"v\": 1,\n        \"kind\": \"get\",\n        \"operation\": \"read\",\n        \"registry\":{\"index-url\":\"sparse+https://registry-url/index/\"}\n    }\n    ```\n4. Credential process sends the CredentialResponse to Cargo (newlines added for readability).\n    ```javascript\n    {\n        \"token\": \"...\",\n        \"cache\": \"session\",\n        \"operation_independent\": true\n    }\n    ```\n5. Cargo closes the stdin pipe to the credential provider and it exits.\n6. Cargo uses the token for the remainder of the session (until Cargo exits) when interacting with this registry.\n"
  },
  {
    "path": "src/doc/src/reference/environment-variables.md",
    "content": "# Environment Variables\n\nCargo sets and reads a number of environment variables which your code can detect\nor override. Here is a list of the variables Cargo sets, organized by when it interacts\nwith them:\n\n## Environment variables Cargo reads\n\nYou can override these environment variables to change Cargo's behavior on your\nsystem:\n\n* `CARGO_LOG` --- Cargo uses the [`tracing`] crate to display debug log messages.\n  The `CARGO_LOG` environment variable can be set to enable debug logging,\n  with a value such as `trace`, `debug`, or `warn`.\n  Usually it is only used during debugging. For more details refer to the\n  [Debug logging].\n* `CARGO_HOME` --- Cargo maintains a local cache of the registry index and of\n  git checkouts of crates. By default these are stored under `$HOME/.cargo`\n  (`%USERPROFILE%\\.cargo` on Windows), but this variable overrides the\n  location of this directory. Once a crate is cached it is not removed by the\n  clean command.\n  For more details refer to the [guide](../guide/cargo-home.md).\n* `CARGO_TARGET_DIR` --- Location of where to place all generated artifacts,\n  relative to the current working directory. See [`build.target-dir`] to set\n  via config.\n* `CARGO` --- If set, Cargo will forward this value instead of setting it\n  to its own auto-detected path when it builds crates and when it\n  executes build scripts and external subcommands. This value is not\n  directly executed by Cargo, and should always point at a command that\n  behaves exactly like `cargo`, as that's what users of the variable\n  will be expecting.\n* `RUSTC` --- Instead of running `rustc`, Cargo will execute this specified\n  compiler instead. See [`build.rustc`] to set via config.\n* `RUSTC_WRAPPER` --- Instead of simply running `rustc`, Cargo will execute this\n  specified wrapper, passing as its command-line arguments the rustc\n  invocation, with the first argument being the path to the actual rustc.\n  Useful to set up a build cache tool such as `sccache`. See\n  [`build.rustc-wrapper`] to set via config. Setting this to the empty string\n  overwrites the config and resets cargo to not use a wrapper.\n* `RUSTC_WORKSPACE_WRAPPER` --- Instead of simply running `rustc`, for workspace members Cargo will\n  execute this specified wrapper, passing as its command-line arguments the rustc invocation, with\n  the first argument being the path to the actual rustc. When building a single-package project\n  without workspaces, that package is considered to be the workspace. It affects the filename hash\n  so that artifacts produced by the wrapper are cached separately. See\n  [`build.rustc-workspace-wrapper`] to set via config. Setting this to the empty string overwrites\n  the config and resets cargo to not use a wrapper for workspace members. If both `RUSTC_WRAPPER`\n  and `RUSTC_WORKSPACE_WRAPPER` are set, then they will be nested: the final invocation is\n  `$RUSTC_WRAPPER $RUSTC_WORKSPACE_WRAPPER $RUSTC`.\n* `RUSTDOC` --- Instead of running `rustdoc`, Cargo will execute this specified\n  `rustdoc` instance instead. See [`build.rustdoc`] to set via config.\n* `RUSTDOCFLAGS` --- A space-separated list of custom flags to pass to all `rustdoc`\n  invocations that Cargo performs. In contrast with [`cargo rustdoc`], this is\n  useful for passing a flag to *all* `rustdoc` instances. See\n  [`build.rustdocflags`] for some more ways to set flags. This string is\n  split by whitespace; for a more robust encoding of multiple arguments,\n  see `CARGO_ENCODED_RUSTDOCFLAGS`.\n* `CARGO_ENCODED_RUSTDOCFLAGS` ---  A list of custom flags separated by `0x1f`\n  (ASCII Unit Separator) to pass to all `rustdoc` invocations that Cargo performs.\n* `RUSTFLAGS` --- A space-separated list of custom flags to pass to all compiler\n  invocations that Cargo performs. In contrast with [`cargo rustc`], this is\n  useful for passing a flag to *all* compiler instances. See\n  [`build.rustflags`] for some more ways to set flags. This string is\n  split by whitespace; for a more robust encoding of multiple arguments,\n  see `CARGO_ENCODED_RUSTFLAGS`.\n* `CARGO_ENCODED_RUSTFLAGS` --- A list of custom flags separated by `0x1f`\n  (ASCII Unit Separator) to pass to all compiler invocations that Cargo performs.\n* `CARGO_INCREMENTAL` --- If this is set to 1 then Cargo will force [incremental\n  compilation] to be enabled for the current compilation, and when set to 0 it\n  will force disabling it. If this env var isn't present then cargo's defaults\n  will otherwise be used. See also [`build.incremental`] config value.\n* `CARGO_CACHE_RUSTC_INFO` --- If this is set to 0 then Cargo will not try to cache\n  compiler version information.\n* `HTTPS_PROXY` or `https_proxy` or `http_proxy` --- The HTTP proxy to use, see\n  [`http.proxy`] for more detail.\n* `HTTP_TIMEOUT` --- The HTTP timeout in seconds, see [`http.timeout`] for more\n  detail.\n* `TERM` --- If this is set to `dumb`, it disables the progress bar.\n* `BROWSER` --- The web browser to execute to open documentation with [`cargo\n  doc`]'s `--open` flag, see [`doc.browser`] for more details.\n* `RUSTFMT` --- Instead of running `rustfmt`,\n  [`cargo fmt`](https://github.com/rust-lang/rustfmt) will execute this specified\n  `rustfmt` instance instead.\n\n### Configuration environment variables\n\nCargo reads environment variables for some configuration values.\nSee the [configuration chapter][config-env] for more details.\nIn summary, the supported environment variables are:\n\n* `CARGO_ALIAS_<name>` --- Command aliases, see [`alias`].\n* `CARGO_BUILD_JOBS` --- Number of parallel jobs, see [`build.jobs`].\n* `CARGO_BUILD_RUSTC` --- The `rustc` executable, see [`build.rustc`].\n* `CARGO_BUILD_RUSTC_WRAPPER` --- The `rustc` wrapper, see [`build.rustc-wrapper`].\n* `CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER` --- The `rustc` wrapper for workspace members only, see [`build.rustc-workspace-wrapper`].\n* `CARGO_BUILD_RUSTDOC` --- The `rustdoc` executable, see [`build.rustdoc`].\n* `CARGO_BUILD_TARGET` --- The default target platform, see [`build.target`].\n* `CARGO_BUILD_TARGET_DIR` --- The default output directory, see [`build.target-dir`].\n* `CARGO_BUILD_BUILD_DIR` --- The default build directory, see [`build.build-dir`].\n* `CARGO_BUILD_RUSTFLAGS` --- Extra `rustc` flags, see [`build.rustflags`].\n* `CARGO_BUILD_RUSTDOCFLAGS` --- Extra `rustdoc` flags, see [`build.rustdocflags`].\n* `CARGO_BUILD_INCREMENTAL` --- Incremental compilation, see [`build.incremental`].\n* `CARGO_BUILD_DEP_INFO_BASEDIR` --- Dep-info relative directory, see [`build.dep-info-basedir`].\n* `CARGO_CACHE_AUTO_CLEAN_FREQUENCY` --- Configures how often automatic cache cleaning runs, see [`cache.auto-clean-frequency`].\n* `CARGO_CARGO_NEW_VCS` --- The default source control system with [`cargo new`], see [`cargo-new.vcs`].\n* `CARGO_FUTURE_INCOMPAT_REPORT_FREQUENCY` --- How often we should generate a future incompat report notification, see [`future-incompat-report.frequency`].\n* `CARGO_HTTP_DEBUG` --- Enables HTTP debugging, see [`http.debug`].\n* `CARGO_HTTP_PROXY` --- Enables HTTP proxy, see [`http.proxy`].\n* `CARGO_HTTP_TIMEOUT` --- The HTTP timeout, see [`http.timeout`].\n* `CARGO_HTTP_CAINFO` --- The TLS certificate Certificate Authority file, see [`http.cainfo`].\n* `CARGO_HTTP_PROXY_CAINFO` --- The proxy TLS certificate Certificate Authority file, see [`http.proxy-cainfo`].\n* `CARGO_HTTP_CHECK_REVOKE` --- Disables TLS certificate revocation checks, see [`http.check-revoke`].\n* `CARGO_HTTP_SSL_VERSION` --- The TLS version to use, see [`http.ssl-version`].\n* `CARGO_HTTP_LOW_SPEED_LIMIT` --- The HTTP low-speed limit, see [`http.low-speed-limit`].\n* `CARGO_HTTP_MULTIPLEXING` --- Whether HTTP/2 multiplexing is used, see [`http.multiplexing`].\n* `CARGO_HTTP_USER_AGENT` --- The HTTP user-agent header, see [`http.user-agent`].\n* `CARGO_INSTALL_ROOT` --- The default directory for [`cargo install`], see [`install.root`].\n* `CARGO_NET_RETRY` --- Number of times to retry network errors, see [`net.retry`].\n* `CARGO_NET_GIT_FETCH_WITH_CLI` --- Enables the use of the `git` executable to fetch, see [`net.git-fetch-with-cli`].\n* `CARGO_NET_OFFLINE` --- Offline mode, see [`net.offline`].\n* `CARGO_PROFILE_<name>_BUILD_OVERRIDE_<key>` --- Override build script profile, see [`profile.<name>.build-override`].\n* `CARGO_PROFILE_<name>_CODEGEN_UNITS` --- Set code generation units, see [`profile.<name>.codegen-units`].\n* `CARGO_PROFILE_<name>_DEBUG` --- What kind of debug info to include, see [`profile.<name>.debug`].\n* `CARGO_PROFILE_<name>_DEBUG_ASSERTIONS` --- Enable/disable debug assertions, see [`profile.<name>.debug-assertions`].\n* `CARGO_PROFILE_<name>_INCREMENTAL` --- Enable/disable incremental compilation, see [`profile.<name>.incremental`].\n* `CARGO_PROFILE_<name>_LTO` --- Link-time optimization, see [`profile.<name>.lto`].\n* `CARGO_PROFILE_<name>_OVERFLOW_CHECKS` --- Enable/disable overflow checks, see [`profile.<name>.overflow-checks`].\n* `CARGO_PROFILE_<name>_OPT_LEVEL` --- Set the optimization level, see [`profile.<name>.opt-level`].\n* `CARGO_PROFILE_<name>_PANIC` --- The panic strategy to use, see [`profile.<name>.panic`].\n* `CARGO_PROFILE_<name>_RPATH` --- The rpath linking option, see [`profile.<name>.rpath`].\n* `CARGO_PROFILE_<name>_SPLIT_DEBUGINFO` --- Controls debug file output behavior, see [`profile.<name>.split-debuginfo`].\n* `CARGO_PROFILE_<name>_STRIP` --- Controls stripping of symbols and/or debuginfos, see [`profile.<name>.strip`].\n* `CARGO_REGISTRIES_<name>_CREDENTIAL_PROVIDER` --- Credential provider for a registry, see [`registries.<name>.credential-provider`].\n* `CARGO_REGISTRIES_<name>_INDEX` --- URL of a registry index, see [`registries.<name>.index`].\n* `CARGO_REGISTRIES_<name>_TOKEN` --- Authentication token of a registry, see [`registries.<name>.token`].\n* `CARGO_REGISTRY_CREDENTIAL_PROVIDER` --- Credential provider for [crates.io], see [`registry.credential-provider`].\n* `CARGO_REGISTRY_DEFAULT` --- Default registry for the `--registry` flag, see [`registry.default`].\n* `CARGO_REGISTRY_GLOBAL_CREDENTIAL_PROVIDERS` --- Credential providers for registries that do not have a specific provider defined. See [`registry.global-credential-providers`].\n* `CARGO_REGISTRY_TOKEN` --- Authentication token for [crates.io], see [`registry.token`].\n* `CARGO_TARGET_<triple>_LINKER` --- The linker to use, see [`target.<triple>.linker`]. The triple must be [converted to uppercase and underscores](config.md#environment-variables).\n* `CARGO_TARGET_<triple>_RUNNER` --- The executable runner, see [`target.<triple>.runner`].\n* `CARGO_TARGET_<triple>_RUSTFLAGS` --- Extra `rustc` flags for a target, see [`target.<triple>.rustflags`].\n* `CARGO_TERM_QUIET` --- Quiet mode, see [`term.quiet`].\n* `CARGO_TERM_VERBOSE` --- The default terminal verbosity, see [`term.verbose`].\n* `CARGO_TERM_COLOR` --- The default color mode, see [`term.color`].\n* `CARGO_TERM_PROGRESS_WHEN` --- The default progress bar showing mode, see [`term.progress.when`].\n* `CARGO_TERM_PROGRESS_WIDTH` --- The default progress bar width, see [`term.progress.width`].\n\n[`cargo doc`]: ../commands/cargo-doc.md\n[`cargo install`]: ../commands/cargo-install.md\n[`cargo new`]: ../commands/cargo-new.md\n[`cargo rustc`]: ../commands/cargo-rustc.md\n[`cargo rustdoc`]: ../commands/cargo-rustdoc.md\n[config-env]: config.md#environment-variables\n[crates.io]: https://crates.io/\n[incremental compilation]: profiles.md#incremental\n[`alias`]: config.md#alias\n[`build.jobs`]: config.md#buildjobs\n[`build.rustc`]: config.md#buildrustc\n[`build.rustc-wrapper`]: config.md#buildrustc-wrapper\n[`build.rustc-workspace-wrapper`]: config.md#buildrustc-workspace-wrapper\n[`build.rustdoc`]: config.md#buildrustdoc\n[`build.target`]: config.md#buildtarget\n[`build.target-dir`]: config.md#buildtarget-dir\n[`build.build-dir`]: config.md#buildbuild-dir\n[`build.rustflags`]: config.md#buildrustflags\n[`build.rustdocflags`]: config.md#buildrustdocflags\n[`build.incremental`]: config.md#buildincremental\n[`build.dep-info-basedir`]: config.md#builddep-info-basedir\n[`doc.browser`]: config.md#docbrowser\n[`cache.auto-clean-frequency`]: config.md#cacheauto-clean-frequency\n[`cargo-new.name`]: config.md#cargo-newname\n[`cargo-new.email`]: config.md#cargo-newemail\n[`cargo-new.vcs`]: config.md#cargo-newvcs\n[`future-incompat-report.frequency`]: config.md#future-incompat-reportfrequency\n[`http.debug`]: config.md#httpdebug\n[`http.proxy`]: config.md#httpproxy\n[`http.timeout`]: config.md#httptimeout\n[`http.cainfo`]: config.md#httpcainfo\n[`http.proxy-cainfo`]: config.md#httpproxy-cainfo\n[`http.check-revoke`]: config.md#httpcheck-revoke\n[`http.ssl-version`]: config.md#httpssl-version\n[`http.low-speed-limit`]: config.md#httplow-speed-limit\n[`http.multiplexing`]: config.md#httpmultiplexing\n[`http.user-agent`]: config.md#httpuser-agent\n[`install.root`]: config.md#installroot\n[`net.retry`]: config.md#netretry\n[`net.git-fetch-with-cli`]: config.md#netgit-fetch-with-cli\n[`net.offline`]: config.md#netoffline\n[`profile.<name>.build-override`]: config.md#profilenamebuild-override\n[`profile.<name>.codegen-units`]: config.md#profilenamecodegen-units\n[`profile.<name>.debug`]: config.md#profilenamedebug\n[`profile.<name>.debug-assertions`]: config.md#profilenamedebug-assertions\n[`profile.<name>.incremental`]: config.md#profilenameincremental\n[`profile.<name>.lto`]: config.md#profilenamelto\n[`profile.<name>.overflow-checks`]: config.md#profilenameoverflow-checks\n[`profile.<name>.opt-level`]: config.md#profilenameopt-level\n[`profile.<name>.panic`]: config.md#profilenamepanic\n[`profile.<name>.rpath`]: config.md#profilenamerpath\n[`profile.<name>.split-debuginfo`]: config.md#profilenamesplit-debuginfo\n[`profile.<name>.strip`]: config.md#profilenamestrip\n[`registries.<name>.credential-provider`]: config.md#registriesnamecredential-provider\n[`registries.<name>.index`]: config.md#registriesnameindex\n[`registries.<name>.token`]: config.md#registriesnametoken\n[`registry.credential-provider`]: config.md#registrycredential-provider\n[`registry.default`]: config.md#registrydefault\n[`registry.global-credential-providers`]: config.md#registryglobal-credential-providers\n[`registry.token`]: config.md#registrytoken\n[`target.<triple>.linker`]: config.md#targettriplelinker\n[`target.<triple>.runner`]: config.md#targettriplerunner\n[`target.<triple>.rustflags`]: config.md#targettriplerustflags\n[`term.quiet`]: config.md#termquiet\n[`term.verbose`]: config.md#termverbose\n[`term.color`]: config.md#termcolor\n[`term.progress.when`]: config.md#termprogresswhen\n[`term.progress.width`]: config.md#termprogresswidth\n\n## Environment variables Cargo sets for crates\n\nCargo exposes these environment variables to your crate when it is compiled.\nNote that this applies for running binaries with `cargo run` and `cargo test`\nas well. To get the value of any of these variables in a Rust program, do\nthis:\n\n```rust,ignore\nlet version = env!(\"CARGO_PKG_VERSION\");\n```\n\n`version` will now contain the value of `CARGO_PKG_VERSION`.\n\nNote that if one of these values is not provided in the manifest, the\ncorresponding environment variable is set to the empty string, `\"\"`.\n\n* `CARGO` --- Path to the `cargo` binary performing the build.\n* `CARGO_MANIFEST_DIR` --- The directory containing the manifest of your package.\n* `CARGO_MANIFEST_PATH` --- The path to the manifest of your package.\n* `CARGO_PKG_VERSION` --- The full version of your package.\n* `CARGO_PKG_VERSION_MAJOR` --- The major version of your package.\n* `CARGO_PKG_VERSION_MINOR` --- The minor version of your package.\n* `CARGO_PKG_VERSION_PATCH` --- The patch version of your package.\n* `CARGO_PKG_VERSION_PRE` --- The pre-release version of your package.\n* `CARGO_PKG_AUTHORS` --- Colon separated list of authors from the manifest of your package.\n* `CARGO_PKG_NAME` --- The name of your package.\n* `CARGO_PKG_DESCRIPTION` --- The description from the manifest of your package.\n* `CARGO_PKG_HOMEPAGE` --- The home page from the manifest of your package.\n* `CARGO_PKG_REPOSITORY` --- The repository from the manifest of your package.\n* `CARGO_PKG_LICENSE` --- The license from the manifest of your package.\n* `CARGO_PKG_LICENSE_FILE` --- The license file from the manifest of your package.\n* `CARGO_PKG_RUST_VERSION` --- The Rust version from the manifest of your package.\n  Note that this is the minimum Rust version supported by the package, not the\n  current Rust version.\n* `CARGO_PKG_README` --- Path to the README file of your package.\n* `CARGO_CRATE_NAME` --- The name of the crate that is currently being compiled. It is the name of the [Cargo target] with `-` converted to `_`, such as the name of the library, binary, example, integration test, or benchmark.\n* `CARGO_BIN_NAME` --- The name of the binary that is currently being compiled.\n  Only set for [binaries] or binary [examples]. This name does not include any\n  file extension, such as `.exe`.\n* `OUT_DIR` --- If the package has a build script, this is set to the folder\n  where the build script should place its output. See below for more information.\n  (Only set during compilation.) Cargo does not guarantee that this directory\n  is empty, and it is not cleaned between builds.\n* `CARGO_BIN_EXE_<name>` --- The absolute path to a binary target's executable.\n  This is only set when building an [integration test] or benchmark. This may\n  be used with the [`env` macro] to find the executable to run for testing\n  purposes. The `<name>` is the name of the binary target, exactly as-is. For\n  example, `CARGO_BIN_EXE_my-program` for a binary named `my-program`.\n  Binaries are automatically built when the test is built, unless the binary\n  has required features that are not enabled.\n* `CARGO_PRIMARY_PACKAGE` --- This environment variable will be set if the\n  package being built is primary. Primary packages are the ones the user\n  selected on the command-line, either with `-p` flags or the defaults based\n  on the current directory and the default workspace members.\n  This variable will not be set when building dependencies,\n  unless a dependency is also a workspace member that was also selected on the command-line.\n  This is only set when compiling the package (not when running binaries or tests).\n* `CARGO_TARGET_TMPDIR` --- Only set when building [integration test] or benchmark code.\n  This is a path to a directory inside the target directory\n  where integration tests or benchmarks are free to put any data needed by\n  the tests/benches. Cargo initially creates this directory but doesn't\n  manage its content in any way, this is the responsibility of the test code.\n\n[Cargo target]: cargo-targets.md\n[binaries]: cargo-targets.md#binaries\n[examples]: cargo-targets.md#examples\n[integration test]: cargo-targets.md#integration-tests\n[`env` macro]: ../../std/macro.env.html\n\n### Dynamic library paths\n\nCargo also sets the dynamic library path when compiling and running binaries\nwith commands like `cargo run` and `cargo test`. This helps with locating\nshared libraries that are part of the build process. The variable name depends\non the platform:\n\n* Windows: `PATH`\n* macOS: `DYLD_FALLBACK_LIBRARY_PATH`\n* Unix: `LD_LIBRARY_PATH`\n* AIX: `LIBPATH`\n\nThe value is extended from the existing value when Cargo starts. macOS has\nspecial consideration where if `DYLD_FALLBACK_LIBRARY_PATH` is not already\nset, it will add the default `$HOME/lib:/usr/local/lib:/usr/lib`.\n\nCargo includes the following paths:\n\n* Search paths included from any build script with the [`rustc-link-search`\n  instruction](build-scripts.md#rustc-link-search). Paths outside of the\n  `target` directory are removed. It is the responsibility of the user running\n  Cargo to properly set the environment if additional libraries on the system\n  are needed in the search path.\n* The base output directory, such as `target/debug`, and the \"deps\" directory.\n  This is mostly for support of proc-macros.\n* The rustc sysroot library path. This generally is not important to most\n  users.\n\n## Environment variables Cargo sets for build scripts\n\nCargo sets several environment variables when build scripts are run. Because these variables\nare not yet set when the build script is compiled, the above example using `env!` won't work\nand instead you'll need to retrieve the values when the build script is run:\n\n```rust,ignore\nuse std::env;\nlet out_dir = env::var(\"OUT_DIR\").unwrap();\n```\n\n`out_dir` will now contain the value of `OUT_DIR`.\n\n* `CARGO` --- Path to the `cargo` binary performing the build.\n* `CARGO_MANIFEST_DIR` --- The directory containing the manifest for the package\n  being built (the package containing the build script). Also note that this is\n  the value of the current working directory of the build script when it starts.\n* `CARGO_MANIFEST_PATH` --- The path to the manifest of your package.\n* `CARGO_MANIFEST_LINKS` --- the manifest `links` value.\n* `CARGO_MAKEFLAGS` --- Contains parameters needed for Cargo's [jobserver]\n  implementation to parallelize subprocesses. Rustc or cargo invocations from\n  build.rs can already read `CARGO_MAKEFLAGS`, but GNU Make requires the flags\n  to be specified either directly as arguments, or through the `MAKEFLAGS`\n  environment variable. Currently Cargo doesn't set the `MAKEFLAGS` variable,\n  but it's free for build scripts invoking GNU Make to set it to the contents\n  of `CARGO_MAKEFLAGS`.\n* `CARGO_FEATURE_<name>` --- For each activated feature of the package being built,\n  this environment variable will be present where `<name>` is the name of the\n  feature uppercased and having `-` translated to `_`.\n* `CARGO_CFG_<cfg>` --- For each [configuration option][configuration] of the\n  package being built, this environment variable will contain the value of the\n  configuration, where `<cfg>` is the name of the configuration uppercased and\n  having `-` translated to `_`. Boolean configurations are present if they are\n  set, and not present otherwise. Configurations with multiple values are\n  joined to a single variable with the values delimited by `,`. This includes\n  values built-in to the compiler (which can be seen with `rustc --print=cfg`)\n  and values set by build scripts and extra flags passed to `rustc` (such as\n  those defined in `RUSTFLAGS`). Some examples of what these variables are:\n    * `CARGO_CFG_FEATURE` --- Each activated feature of the package being built.\n    * `CARGO_CFG_UNIX` --- Set on [unix-like platforms].\n    * `CARGO_CFG_WINDOWS` --- Set on [windows-like platforms].\n    * `CARGO_CFG_TARGET_FAMILY=unix,wasm` --- The [target family].\n    * `CARGO_CFG_TARGET_OS=macos` --- The [target operating system].\n    * `CARGO_CFG_TARGET_ARCH=x86_64` --- The CPU [target architecture].\n    * `CARGO_CFG_TARGET_VENDOR=apple` --- The [target vendor].\n    * `CARGO_CFG_TARGET_ENV=gnu` --- The [target environment] ABI.\n    * `CARGO_CFG_TARGET_ABI=eabihf` --- The [target ABI].\n    * `CARGO_CFG_TARGET_POINTER_WIDTH=64` --- The CPU [pointer width].\n    * `CARGO_CFG_TARGET_ENDIAN=little` --- The CPU [target endianness].\n    * `CARGO_CFG_TARGET_FEATURE=mmx,sse` --- List of CPU [target features] enabled.\n  > Note that different [target triples][Target Triple] have different sets of `cfg` values,\n  > hence variables present in one target triple might not be available in the other.\n  >\n  > Some cfg values like `test` are not available.\n  >\n  > **Tip:** For a typed API to read these values, consider using the [`build-rs`]\n  > crate instead of parsing environment variables manually. Also note that\n  > `CARGO_CFG_*` variables should be used instead of the `cfg!` macro or `#[cfg]`\n  > attribute in build scripts, those check the *host* platform, not the *target*.\n* `OUT_DIR` --- the folder in which all output and intermediate artifacts should\n  be placed. This folder is inside the build directory for the package being built,\n  and it is unique for the package in question. Cargo does not clean or reset this\n  directory between builds, and its contents may persist across rebuilds. Build\n  scripts should not assume that `OUT_DIR` is empty, and are responsible for\n  managing or cleaning up any files they create.\n* `TARGET` --- the target triple that is being compiled for. Native code should be\n  compiled for this triple. See the [Target Triple] description for more information.\n* `HOST` --- the host triple of the Rust compiler.\n* `NUM_JOBS` --- the parallelism specified as the top-level parallelism. This can\n  be useful to pass a `-j` parameter to a system like `make`. Note that care\n  should be taken when interpreting this environment variable. For historical\n  purposes this is still provided but recent versions of Cargo, for example, do\n  not need to run `make -j`, and instead can set the `MAKEFLAGS` env var to the\n  content of `CARGO_MAKEFLAGS` to activate the use of Cargo's GNU Make compatible\n  [jobserver] for sub-make invocations.\n* `DEBUG` --- `true` if any [`debug`] information will be generated and `false` otherwise.\n* `OPT_LEVEL` --- values of the corresponding [`opt-level`] variable for the profile currently being built.\n* `PROFILE` --- `release` for release builds, `debug` for other builds. This is\n  determined based on if the [profile] inherits from the [`dev`] or\n  [`release`] profile. Using this environment variable is not recommended.\n  Using other environment variables like `OPT_LEVEL` provide a more correct\n  view of the actual settings being used.\n* `DEP_<links>_<key>` --- For more information about this set of environment variables,\n  see build script documentation about [`links`][links].\n* `RUSTC`, `RUSTDOC` --- the compiler and documentation generator that Cargo has\n  resolved to use, passed to the build script so it might use it as well.\n* `RUSTC_WRAPPER` --- the `rustc` wrapper, if any, that Cargo is using. See [`build.rustc-wrapper`].\n* `RUSTC_WORKSPACE_WRAPPER` --- the `rustc` wrapper, if any, that Cargo is using\n  for workspace members. See [`build.rustc-workspace-wrapper`].\n* `RUSTC_LINKER` --- The path to the linker binary that Cargo has resolved to use\n  for the current target, if specified. The linker can be changed by editing\n  `.cargo/config.toml`; see the documentation about [cargo configuration][cargo-config]\n  for more information.\n* `CARGO_ENCODED_RUSTFLAGS` --- extra flags that Cargo invokes `rustc` with,\n  separated by a `0x1f` character (ASCII Unit Separator). See\n  [`build.rustflags`]. Note that since Rust 1.55, `RUSTFLAGS` is removed from\n  the environment; scripts should use `CARGO_ENCODED_RUSTFLAGS` instead.\n* `CARGO_PKG_<var>` --- The package information variables, with the same names and values as are [provided during crate building][variables set for crates].\n\n[`tracing`]: https://docs.rs/tracing\n[debug logging]: https://doc.crates.io/contrib/implementation/debugging.html#logging\n[unix-like platforms]: ../../reference/conditional-compilation.html#unix-and-windows\n[windows-like platforms]: ../../reference/conditional-compilation.html#unix-and-windows\n[target family]: ../../reference/conditional-compilation.html#target_family\n[target operating system]: ../../reference/conditional-compilation.html#target_os\n[target architecture]: ../../reference/conditional-compilation.html#target_arch\n[target vendor]: ../../reference/conditional-compilation.html#target_vendor\n[target environment]: ../../reference/conditional-compilation.html#target_env\n[target ABI]: ../../reference/conditional-compilation.html#target_abi\n[pointer width]: ../../reference/conditional-compilation.html#target_pointer_width\n[target endianness]: ../../reference/conditional-compilation.html#target_endian\n[target features]: ../../reference/conditional-compilation.html#target_feature\n[links]: build-scripts.md#the-links-manifest-key\n[configuration]: ../../reference/conditional-compilation.html\n[jobserver]: https://www.gnu.org/software/make/manual/html_node/Job-Slots.html\n[cargo-config]: config.md\n[Target Triple]: ../appendix/glossary.md#target\n[variables set for crates]: #environment-variables-cargo-sets-for-crates\n[profile]: profiles.md\n[`dev`]: profiles.md#dev\n[`release`]: profiles.md#release\n[`debug`]: profiles.md#debug\n[`opt-level`]: profiles.md#opt-level\n[`build-rs`]: https://crates.io/crates/build-rs\n\n## Environment variables Cargo sets for `cargo test`\n\nCargo sets several environment variables when tests are run.\nYou can retrieve the values when the tests are run:\n\n```rust,ignore\nuse std::env;\nlet out_dir = env::var(\"CARGO_BIN_EXE_foo\").unwrap();\n```\n\n* `CARGO_BIN_EXE_<name>` --- The absolute path to a binary target's executable.\n  This is only set when running an [integration test] or benchmark.\n  The `<name>` is the name of the binary target, exactly as-is. For\n  example, `CARGO_BIN_EXE_my-program` for a binary named `my-program`.\n  Binaries are automatically built when the test is built, unless the binary\n  has required features that are not enabled.\n\n## Environment variables Cargo sets for 3rd party subcommands\n\nCargo exposes this environment variable to 3rd party subcommands\n(ie. programs named `cargo-foobar` placed in `$PATH`):\n\n* `CARGO` --- Path to the `cargo` binary performing the build.\n* `CARGO_MAKEFLAGS` --- Contains parameters needed for Cargo's [jobserver]\n  implementation to parallelize subprocesses.\n  This is set only when Cargo detects the existence of a jobserver.\n\nFor extended information about your environment you may run `cargo metadata`.\n"
  },
  {
    "path": "src/doc/src/reference/external-tools.md",
    "content": "# External tools\n\nOne of the goals of Cargo is simple integration with third-party tools, like\nIDEs and other build systems. To make integration easier, Cargo has several\nfacilities:\n\n* a [`cargo metadata`] command, which outputs package structure and dependencies\n  information in JSON,\n\n* a `--message-format` flag, which outputs information about a particular build,\n  and\n\n* support for custom subcommands.\n\n\n## Information about package structure\n\nYou can use [`cargo metadata`] command to get information about package\nstructure and dependencies. See the [`cargo metadata`] documentation\nfor details on the format of the output.\n\nThe format is stable and versioned. When calling `cargo metadata`, you should\npass `--format-version` flag explicitly to avoid forward incompatibility\nhazard.\n\nIf you are using Rust, the [cargo_metadata] crate can be used to parse the\noutput.\n\n[cargo_metadata]: https://crates.io/crates/cargo_metadata\n[`cargo metadata`]: ../commands/cargo-metadata.md\n\n## JSON messages\n\nWhen passing `--message-format=json`, Cargo will output the following\ninformation during the build:\n\n* compiler errors and warnings,\n\n* produced artifacts,\n\n* results of the build scripts (for example, native dependencies).\n\nThe output goes to stdout in the JSON object per line format. The `reason` field\ndistinguishes different kinds of messages.\nThe `package_id` field is a unique identifier for referring to the package, and\nas the `--package` argument to many commands. The syntax grammar can be found in\nchapter [Package ID Specifications].\n\n> **Note:** `--message-format=json` only controls Cargo and Rustc's output.\n> This cannot control the output of other tools,\n> e.g. `cargo run --message-format=json`,\n> or arbitrary output from procedural macros.\n> A possible workaround in these situations is to only interpret a line as JSON if it starts with `{`.\n\nThe `--message-format` option can also take additional formatting values which\nalter the way the JSON messages are computed and rendered. See the description\nof the `--message-format` option in the [build command documentation] for more\ndetails.\n\nIf you are using Rust, the [cargo_metadata] crate can be used to parse these\nmessages.\n\n> **MSRV:** 1.77 is required for `package_id` to be a Package ID Specification. Before that, it was opaque.\n\n[build command documentation]: ../commands/cargo-build.md\n[cargo_metadata]: https://crates.io/crates/cargo_metadata\n[Package ID Specifications]: ./pkgid-spec.md\n\n### Compiler messages\n\nThe \"compiler-message\" message includes output from the compiler, such as\nwarnings and errors. See the [rustc JSON chapter](../../rustc/json.md) for\ndetails on `rustc`'s message format, which is embedded in the following\nstructure:\n\n```javascript\n{\n    /* The \"reason\" indicates the kind of message. */\n    \"reason\": \"compiler-message\",\n    /* The Package ID, a unique identifier for referring to the package. */\n    \"package_id\": \"file:///path/to/my-package#0.1.0\",\n    /* Absolute path to the package manifest. */\n    \"manifest_path\": \"/path/to/my-package/Cargo.toml\",\n    /* The Cargo target (lib, bin, example, etc.) that generated the message. */\n    \"target\": {\n        /* Array of target kinds.\n           - lib targets list the `crate-type` values from the\n             manifest such as \"lib\", \"rlib\", \"dylib\",\n             \"proc-macro\", etc. (default [\"lib\"])\n           - binary is [\"bin\"]\n           - example is [\"example\"]\n           - integration test is [\"test\"]\n           - benchmark is [\"bench\"]\n           - build script is [\"custom-build\"]\n        */\n        \"kind\": [\n            \"lib\"\n        ],\n        /* Array of crate types.\n           - lib and example libraries list the `crate-type` values\n             from the manifest such as \"lib\", \"rlib\", \"dylib\",\n             \"proc-macro\", etc. (default [\"lib\"])\n           - all other target kinds are [\"bin\"]\n        */\n        \"crate_types\": [\n            \"lib\"\n        ],\n        /* The name of the target.\n           For lib targets, dashes will be replaced with underscores.\n        */\n        \"name\": \"my_package\",\n        /* Absolute path to the root source file of the target. */\n        \"src_path\": \"/path/to/my-package/src/lib.rs\",\n        /* The Rust edition of the target.\n           Defaults to the package edition.\n        */\n        \"edition\": \"2018\",\n        /* Array of required features.\n           This property is not included if no required features are set.\n        */\n        \"required-features\": [\"feat1\"],\n        /* Whether the target should be documented by `cargo doc`. */\n        \"doc\": true,\n        /* Whether or not this target has doc tests enabled, and\n           the target is compatible with doc testing.\n        */\n        \"doctest\": true\n        /* Whether or not this target should be built and run with `--test`\n        */\n        \"test\": true\n    },\n    /* The message emitted by the compiler.\n\n    See https://doc.rust-lang.org/rustc/json.html for details.\n    */\n    \"message\": {\n        /* ... */\n    }\n}\n```\n\n### Artifact messages\n\nFor every compilation step, a \"compiler-artifact\" message is emitted with the\nfollowing structure:\n\n```javascript\n{\n    /* The \"reason\" indicates the kind of message. */\n    \"reason\": \"compiler-artifact\",\n    /* The Package ID, a unique identifier for referring to the package. */\n    \"package_id\": \"file:///path/to/my-package#0.1.0\",\n    /* Absolute path to the package manifest. */\n    \"manifest_path\": \"/path/to/my-package/Cargo.toml\",\n    /* The Cargo target (lib, bin, example, etc.) that generated the artifacts.\n       See the definition above for `compiler-message` for details.\n    */\n    \"target\": {\n        \"kind\": [\n            \"lib\"\n        ],\n        \"crate_types\": [\n            \"lib\"\n        ],\n        \"name\": \"my_package\",\n        \"src_path\": \"/path/to/my-package/src/lib.rs\",\n        \"edition\": \"2018\",\n        \"doc\": true,\n        \"doctest\": true,\n        \"test\": true\n    },\n    /* The profile indicates which compiler settings were used. */\n    \"profile\": {\n        /* The optimization level. */\n        \"opt_level\": \"0\",\n        /* The debug level, an integer of 0, 1, or 2, or a string\n           \"line-directives-only\" or \"line-tables-only\". If `null`, it implies\n           rustc's default of 0.\n        */\n        \"debuginfo\": 2,\n        /* Whether or not debug assertions are enabled. */\n        \"debug_assertions\": true,\n        /* Whether or not overflow checks are enabled. */\n        \"overflow_checks\": true,\n        /* Whether or not the `--test` flag is used. */\n        \"test\": false\n    },\n    /* Array of features enabled. */\n    \"features\": [\"feat1\", \"feat2\"],\n    /* Array of files generated by this step. */\n    \"filenames\": [\n        \"/path/to/my-package/target/debug/libmy_package.rlib\",\n        \"/path/to/my-package/target/debug/deps/libmy_package-be9f3faac0a26ef0.rmeta\"\n    ],\n    /* A string of the path to the executable that was created, or null if\n       this step did not generate an executable.\n    */\n    \"executable\": null,\n    /* Whether or not this step was actually executed.\n       When `true`, this means that the pre-existing artifacts were\n       up-to-date, and `rustc` was not executed. When `false`, this means that\n       `rustc` was run to generate the artifacts.\n    */\n    \"fresh\": true\n}\n\n```\n\n### Build script output\n\nThe \"build-script-executed\" message includes the parsed output of a build\nscript. Note that this is emitted even if the build script is not run; it will\ndisplay the previously cached value. More details about build script output\nmay be found in [the chapter on build scripts](build-scripts.md).\n\n```javascript\n{\n    /* The \"reason\" indicates the kind of message. */\n    \"reason\": \"build-script-executed\",\n    /* The Package ID, a unique identifier for referring to the package. */\n    \"package_id\": \"file:///path/to/my-package#0.1.0\",\n    /* Array of libraries to link, as indicated by the `cargo::rustc-link-lib`\n       instruction. Note that this may include a \"KIND=\" prefix in the string\n       where KIND is the library kind.\n    */\n    \"linked_libs\": [\"foo\", \"static=bar\"],\n    /* Array of paths to include in the library search path, as indicated by\n       the `cargo::rustc-link-search` instruction. Note that this may include a\n       \"KIND=\" prefix in the string where KIND is the library kind.\n    */\n    \"linked_paths\": [\"/some/path\", \"native=/another/path\"],\n    /* Array of cfg values to enable, as indicated by the `cargo::rustc-cfg`\n       instruction.\n    */\n    \"cfgs\": [\"cfg1\", \"cfg2=\\\"string\\\"\"],\n    /* Array of [KEY, VALUE] arrays of environment variables to set, as\n       indicated by the `cargo::rustc-env` instruction.\n    */\n    \"env\": [\n        [\"SOME_KEY\", \"some value\"],\n        [\"ANOTHER_KEY\", \"another value\"]\n    ],\n    /* An absolute path which is used as a value of `OUT_DIR` environmental\n       variable when compiling current package.\n    */\n    \"out_dir\": \"/some/path/in/target/dir\"\n}\n```\n\n### Build finished\n\nThe \"build-finished\" message is emitted at the end of the build.\n\n```javascript\n{\n    /* The \"reason\" indicates the kind of message. */\n    \"reason\": \"build-finished\",\n    /* Whether or not the build finished successfully. */\n    \"success\": true,\n}\n````\n\nThis message can be helpful for tools to know when to stop reading JSON\nmessages. Commands such as `cargo test` or `cargo run` can produce additional\noutput after the build has finished. This message lets a tool know that Cargo\nwill not produce additional JSON messages, but there may be additional output\nthat may be generated afterwards (such as the output generated by the program\nexecuted by `cargo run`).\n\n> Note: There is experimental nightly-only support for JSON output for tests,\n> so additional test-specific JSON messages may begin arriving after the\n> \"build-finished\" message if that is enabled.\n\n## Custom subcommands\n\nCargo is designed to be extensible with new subcommands without having to modify\nCargo itself. This is achieved by translating a cargo invocation of the form\ncargo `(?<command>[^ ]+)` into an invocation of an external tool\n`cargo-${command}`. The external tool must be present in one of the user's\n`$PATH` directories.\n\n> **Note**: Cargo defaults to prioritizing external tools in `$CARGO_HOME/bin`\n> over `$PATH`. Users can override this precedence by adding `$CARGO_HOME/bin`\n> to `$PATH`.\n\nWhen Cargo invokes a custom subcommand, the first argument to the subcommand\nwill be the filename of the custom subcommand, as usual. The second argument\nwill be the subcommand name itself. For example, the second argument would be\n`${command}` when invoking `cargo-${command}`. Any additional arguments on the\ncommand line will be forwarded unchanged.\n\nCargo can also display the help output of a custom subcommand with `cargo help\n${command}`. Cargo assumes that the subcommand will print a help message if its\nthird argument is `--help`. So, `cargo help ${command}` would invoke\n`cargo-${command} ${command} --help`.\n\nCustom subcommands may use the `CARGO` environment variable to call back to\nCargo. Alternatively, it can link to `cargo` crate as a library, but this\napproach has drawbacks:\n\n* Cargo as a library is unstable: the  API may change without deprecation\n* versions of the linked Cargo library may be different from the Cargo binary\n\nInstead, it is encouraged to use the CLI interface to drive Cargo. The [`cargo\nmetadata`] command can be used to obtain information about the current project\n(the [`cargo_metadata`] crate provides a Rust interface to this command).\n\n[`cargo metadata`]: ../commands/cargo-metadata.md\n[`cargo_metadata`]: https://crates.io/crates/cargo_metadata\n"
  },
  {
    "path": "src/doc/src/reference/features-examples.md",
    "content": "# Features Examples\n\nThe following illustrates some real-world examples of features in action.\n\n## Minimizing build times and file sizes\n\nSome packages use features so that if the features are not enabled, it reduces\nthe size of the crate and reduces compile time. Some examples are:\n\n* [`syn`] is a popular crate for parsing Rust code. Since it is so popular, it\n  is helpful to reduce compile times since it affects so many projects. It has\n  a [clearly documented list][syn-features] of features which can be used to\n  minimize the amount of code it contains.\n* [`regex`] has a [several features][regex-features] that are [well\n  documented][regex-docs]. Cutting out Unicode support can reduce the\n  resulting file size as it can remove some large tables.\n* [`winapi`] has [a large number][winapi-features] of features that\n  limit which Windows API bindings it supports.\n* [`web-sys`] is another example similar to `winapi` that provides a [huge\n  surface area][web-sys-features] of API bindings that are limited by using\n  features.\n\n[`winapi`]: https://crates.io/crates/winapi\n[winapi-features]: https://github.com/retep998/winapi-rs/blob/0.3.9/Cargo.toml#L25-L431\n[`regex`]: https://crates.io/crates/regex\n[`syn`]: https://crates.io/crates/syn\n[syn-features]: https://docs.rs/syn/1.0.54/syn/#optional-features\n[regex-features]: https://github.com/rust-lang/regex/blob/1.4.2/Cargo.toml#L33-L101\n[regex-docs]: https://docs.rs/regex/1.4.2/regex/#crate-features\n[`web-sys`]: https://crates.io/crates/web-sys\n[web-sys-features]: https://github.com/rustwasm/wasm-bindgen/blob/0.2.69/crates/web-sys/Cargo.toml#L32-L1395\n\n## Extending behavior\n\nThe [`serde_json`] package has a [`preserve_order` feature][serde_json-preserve_order]\nwhich [changes the behavior][serde_json-code] of JSON maps to preserve the\norder that keys are inserted. Notice that it enables an optional dependency\n[`indexmap`] to implement the new behavior.\n\nWhen changing behavior like this, be careful to make sure the changes are\n[SemVer compatible]. That is, enabling the feature should not break code that\nusually builds with the feature off.\n\n[`serde_json`]: https://crates.io/crates/serde_json\n[serde_json-preserve_order]: https://github.com/serde-rs/json/blob/v1.0.60/Cargo.toml#L53-L56\n[SemVer compatible]: features.md#semver-compatibility\n[serde_json-code]: https://github.com/serde-rs/json/blob/v1.0.60/src/map.rs#L23-L26\n[`indexmap`]: https://crates.io/crates/indexmap\n\n## `no_std` support\n\nSome packages want to support both [`no_std`] and `std` environments. This is\nuseful for supporting embedded and resource-constrained platforms, but still\nallowing extended capabilities for platforms that support the full standard\nlibrary.\n\nThe [`wasm-bindgen`] package defines a [`std` feature][wasm-bindgen-std] that\nis [enabled by default][wasm-bindgen-default]. At the top of the library, it\n[unconditionally enables the `no_std` attribute][wasm-bindgen-no_std]. This\nensures that `std` and the [`std` prelude] are not automatically in scope.\nThen, in various places in the code ([example1][wasm-bindgen-cfg1],\n[example2][wasm-bindgen-cfg2]), it uses `#[cfg(feature = \"std\")]` attributes\nto conditionally enable extra functionality that requires `std`.\n\n[`no_std`]: ../../reference/names/preludes.html#the-no_std-attribute\n[`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen\n[`std` prelude]: ../../std/prelude/index.html\n[wasm-bindgen-std]: https://github.com/rustwasm/wasm-bindgen/blob/0.2.69/Cargo.toml#L25\n[wasm-bindgen-default]: https://github.com/rustwasm/wasm-bindgen/blob/0.2.69/Cargo.toml#L23\n[wasm-bindgen-no_std]: https://github.com/rustwasm/wasm-bindgen/blob/0.2.69/src/lib.rs#L8\n[wasm-bindgen-cfg1]: https://github.com/rustwasm/wasm-bindgen/blob/0.2.69/src/lib.rs#L270-L273\n[wasm-bindgen-cfg2]: https://github.com/rustwasm/wasm-bindgen/blob/0.2.69/src/lib.rs#L67-L75\n\n## Re-exporting dependency features\n\nIt can be convenient to re-export the features from a dependency. This allows\nthe user depending on the crate to control those features without needing to\nspecify those dependencies directly. For example, [`regex`] [re-exports the\nfeatures][regex-re-export] from the [`regex_syntax`][regex_syntax-features]\npackage. Users of `regex` don't need to know about the `regex_syntax` package,\nbut they can still access the features it contains.\n\n[regex-re-export]: https://github.com/rust-lang/regex/blob/1.4.2/Cargo.toml#L65-L89\n[regex_syntax-features]: https://github.com/rust-lang/regex/blob/1.4.2/regex-syntax/Cargo.toml#L17-L32\n\n## Vendoring of C libraries\n\nSome packages provide bindings to common C libraries (sometimes referred to as\n[\"sys\" crates][sys]). Sometimes these packages give you the choice to use the\nC library installed on the system, or to build it from source. For example,\nthe [`openssl`] package has a [`vendored` feature][openssl-vendored] which\nenables the corresponding `vendored` feature of [`openssl-sys`]. The\n`openssl-sys` build script has some [conditional logic][openssl-sys-cfg] which\ncauses it to build from a local copy of the OpenSSL source code instead of\nusing the version from the system.\n\nThe [`curl-sys`] package is another example where the [`static-curl`\nfeature][curl-sys-static] causes it to build libcurl from source. Notice that\nit also has a [`force-system-lib-on-osx`][curl-sys-macos] feature which forces\nit [to use the system libcurl][curl-sys-macos-code], overriding the\nstatic-curl setting.\n\n[`openssl`]: https://crates.io/crates/openssl\n[`openssl-sys`]: https://crates.io/crates/openssl-sys\n[sys]: build-scripts.md#-sys-packages\n[openssl-vendored]: https://github.com/sfackler/rust-openssl/blob/openssl-v0.10.31/openssl/Cargo.toml#L19\n[build script]: build-scripts.md\n[openssl-sys-cfg]: https://github.com/sfackler/rust-openssl/blob/openssl-v0.10.31/openssl-sys/build/main.rs#L47-L54\n[`curl-sys`]: https://crates.io/crates/curl-sys\n[curl-sys-static]: https://github.com/alexcrichton/curl-rust/blob/0.4.34/curl-sys/Cargo.toml#L49\n[curl-sys-macos]: https://github.com/alexcrichton/curl-rust/blob/0.4.34/curl-sys/Cargo.toml#L52\n[curl-sys-macos-code]: https://github.com/alexcrichton/curl-rust/blob/0.4.34/curl-sys/build.rs#L15-L20\n\n## Feature precedence\n\nSome packages may have mutually-exclusive features. One option to handle this\nis to prefer one feature over another. The [`log`] package is an example. It\nhas [several features][log-features] for choosing the maximum logging level at\ncompile-time described [here][log-docs]. It uses [`cfg-if`] to [choose a\nprecedence][log-cfg-if]. If multiple features are enabled, the higher \"max\"\nlevels will be preferred over the lower levels.\n\n[`log`]: https://crates.io/crates/log\n[log-features]: https://github.com/rust-lang/log/blob/0.4.11/Cargo.toml#L29-L42\n[log-docs]: https://docs.rs/log/0.4.11/log/#compile-time-filters\n[log-cfg-if]: https://github.com/rust-lang/log/blob/0.4.11/src/lib.rs#L1422-L1448\n[`cfg-if`]: https://crates.io/crates/cfg-if\n\n## Proc-macro companion package\n\nSome packages have a proc-macro that is intimately tied with it. However, not\nall users will need to use the proc-macro. By making the proc-macro an\noptional-dependency, this allows you to conveniently choose whether or not it\nis included. This is helpful, because sometimes the proc-macro version must\nstay in sync with the parent package, and you don't want to force the users to\nhave to specify both dependencies and keep them in sync.\n\nAn example is [`serde`] which has a [`derive`][serde-derive] feature which\nenables the [`serde_derive`] proc-macro. The `serde_derive` crate is very\ntightly tied to `serde`, so it uses an [equals version\nrequirement][serde-equals] to ensure they stay in sync.\n\n[`serde`]: https://crates.io/crates/serde\n[`serde_derive`]: https://crates.io/crates/serde_derive\n[serde-derive]: https://github.com/serde-rs/serde/blob/v1.0.118/serde/Cargo.toml#L34-L35\n[serde-equals]: https://github.com/serde-rs/serde/blob/v1.0.118/serde/Cargo.toml#L17\n\n## Nightly-only features\n\nSome packages want to experiment with APIs or language features that are only\navailable on the Rust [nightly channel]. However, they may not want to require\ntheir users to also use the nightly channel. An example is [`wasm-bindgen`]\nwhich has a [`nightly` feature][wasm-bindgen-nightly] which enables an\n[extended API][wasm-bindgen-unsize] that uses the [`Unsize`] marker trait that\nis only available on the nightly channel at the time of this writing.\n\nNote that at the root of the crate it uses [`cfg_attr` to enable the nightly\nfeature][wasm-bindgen-cfg_attr]. Keep in mind that the [`feature` attribute]\nis unrelated to Cargo features, and is used to opt-in to experimental language\nfeatures.\n\nThe [`simd_support` feature][rand-simd_support] of the [`rand`] package is another example,\nwhich relies on a dependency that only builds on the nightly channel.\n\n[`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen\n[nightly channel]: ../../book/appendix-07-nightly-rust.html\n[wasm-bindgen-nightly]: https://github.com/rustwasm/wasm-bindgen/blob/0.2.69/Cargo.toml#L27\n[wasm-bindgen-unsize]: https://github.com/rustwasm/wasm-bindgen/blob/0.2.69/src/closure.rs#L257-L269\n[`Unsize`]: ../../std/marker/trait.Unsize.html\n[wasm-bindgen-cfg_attr]: https://github.com/rustwasm/wasm-bindgen/blob/0.2.69/src/lib.rs#L11\n[`feature` attribute]: ../../unstable-book/index.html\n[`rand`]: https://crates.io/crates/rand\n[rand-simd_support]: https://github.com/rust-random/rand/blob/0.7.3/Cargo.toml#L40\n\n## Experimental features\n\nSome packages have new functionality that they may want to experiment with,\nwithout having to commit to the stability of those APIs. The features are\nusually documented that they are experimental, and thus may change or break in\nthe future, even during a minor release. An example is the [`async-std`]\npackage, which has an [`unstable` feature][async-std-unstable], which [gates\nnew APIs][async-std-gate] that people can opt-in to using, but may not be\ncompletely ready to be relied upon.\n\n[`async-std`]: https://crates.io/crates/async-std\n[async-std-unstable]: https://github.com/async-rs/async-std/blob/v1.8.0/Cargo.toml#L38-L42\n[async-std-gate]: https://github.com/async-rs/async-std/blob/v1.8.0/src/macros.rs#L46\n"
  },
  {
    "path": "src/doc/src/reference/features.md",
    "content": "# Features\n\nCargo \"features\" provide a mechanism to express [conditional compilation] and\n[optional dependencies](#optional-dependencies). A package defines a set of\nnamed features in the `[features]` table of `Cargo.toml`, and each feature can\neither be enabled or disabled. Features for the package being built can be\nenabled on the command-line with flags such as `--features`. Features for\ndependencies can be enabled in the dependency declaration in `Cargo.toml`.\n\n> **Note**: New crates or versions published on crates.io are now limited to\n> a maximum of 300 features. Exceptions are granted on a case-by-case basis.\n> See this [blog post] for details. Participation in solution discussions is\n> encouraged via the crates.io Zulip stream.\n\n[blog post]: https://blog.rust-lang.org/2023/10/26/broken-badges-and-23k-keywords.html\n\nSee also the [Features Examples] chapter for some examples of how features can\nbe used.\n\n[conditional compilation]: ../../reference/conditional-compilation.md\n[Features Examples]: features-examples.md\n\n## The `[features]` section\n\nFeatures are defined in the `[features]` table in `Cargo.toml`. Each feature\nspecifies an array of other features or optional dependencies that it enables.\nThe following examples illustrate how features could be used for a 2D image\nprocessing library where support for different image formats can be optionally\nincluded:\n\n```toml\n[features]\n# Defines a feature named `webp` that does not enable any other features.\nwebp = []\n```\n\nWith this feature defined, [`cfg` expressions] can be used to conditionally\ninclude code to support the requested feature at compile time. For example,\ninside `lib.rs` of the package could include this:\n\n```rust\n// This conditionally includes a module which implements WEBP support.\n#[cfg(feature = \"webp\")]\npub mod webp;\n```\n\nCargo sets features in the package using the `rustc` [`--cfg` flag], and code\ncan test for their presence with the [`cfg` attribute] or the [`cfg` macro].\n\nFeatures can list other features to enable. For example, the ICO image format\ncan contain BMP and PNG images, so when it is enabled, it should make sure\nthose other features are enabled, too:\n\n```toml\n[features]\nbmp = []\npng = []\nico = [\"bmp\", \"png\"]\nwebp = []\n```\n\nFeature names may include characters from the [Unicode XID standard] (which\nincludes most letters), and additionally allows starting with `_` or digits\n`0` through `9`, and after the first character may also contain `-`, `+`, or\n`.`.\n\n> **Note**: [crates.io] imposes additional constraints on feature name syntax\n> that they must only be [ASCII alphanumeric] characters or `_`, `-`, or `+`.\n\n[crates.io]: https://crates.io/\n[Unicode XID standard]: https://unicode.org/reports/tr31/\n[ASCII alphanumeric]: ../../std/primitive.char.html#method.is_ascii_alphanumeric\n[`--cfg` flag]: ../../rustc/command-line-arguments.md#option-cfg\n[`cfg` expressions]: ../../reference/conditional-compilation.md\n[`cfg` attribute]: ../../reference/conditional-compilation.md#the-cfg-attribute\n[`cfg` macro]: ../../std/macro.cfg.html\n\n## The `default` feature\n\nBy default, all features are disabled unless explicitly enabled. This can be\nchanged by specifying the `default` feature:\n\n```toml\n[features]\ndefault = [\"ico\", \"webp\"]\nbmp = []\npng = []\nico = [\"bmp\", \"png\"]\nwebp = []\n```\n\nWhen the package is built, the `default` feature is enabled which in turn\nenables the listed features. This behavior can be changed by:\n\n* The `--no-default-features` [command-line\n  flag](#command-line-feature-options) disables the default features of the\n  package.\n* The `default-features = false` option can be specified in a [dependency\n  declaration](#dependency-features).\n\n> **Note**: Be careful about choosing the default feature set. The default\n> features are a convenience that make it easier to use a package without\n> forcing the user to carefully select which features to enable for common\n> use, but there are some drawbacks. Dependencies automatically enable default\n> features unless `default-features = false` is specified. This can make it\n> difficult to ensure that the default features are not enabled, especially\n> for a dependency that appears multiple times in the dependency graph. Every\n> package must ensure that `default-features = false` is specified to avoid\n> enabling them.\n>\n> Another issue is that it can be a [SemVer incompatible\n> change](#semver-compatibility) to remove a feature from the default set, so\n> you should be confident that you will keep those features.\n\n## Optional dependencies\n\nDependencies can be marked \"optional\", which means they will not be compiled\nby default. For example, let's say that our 2D image processing library uses\nan external package to handle GIF images. This can be expressed like this:\n\n```toml\n[dependencies]\ngif = { version = \"0.11.1\", optional = true }\n```\n\nBy default, this optional dependency implicitly defines a feature that looks\nlike this:\n\n```toml\n[features]\ngif = [\"dep:gif\"]\n```\n\nThis means that this dependency will only be included if the `gif`\nfeature is enabled.\nThe same `cfg(feature = \"gif\")` syntax can be used in the code, and the\ndependency can be enabled just like any feature such as `--features gif` (see\n[Command-line feature options](#command-line-feature-options) below).\n\nIn some cases, you may not want to expose a feature that has the same name\nas the optional dependency.\nFor example, perhaps the optional dependency is an internal detail, or you\nwant to group multiple optional dependencies together, or you just want to use\na better name.\nIf you specify the optional dependency with the `dep:` prefix anywhere\nin the `[features]` table, that disables the implicit feature.\n\n> **Note**: The `dep:` syntax is only available starting with Rust 1.60.\n> Previous versions can only use the implicit feature name.\n\nFor example, let's say in order to support the AVIF image format, our library\nneeds two other dependencies to be enabled:\n\n```toml\n[dependencies]\nravif = { version = \"0.6.3\", optional = true }\nrgb = { version = \"0.8.25\", optional = true }\n\n[features]\navif = [\"dep:ravif\", \"dep:rgb\"]\n```\n\nIn this example, the `avif` feature will enable the two listed dependencies.\nThis also avoids creating the implicit `ravif` and `rgb` features, since we\ndon't want users to enable those individually as they are internal details to\nour crate.\n\n> **Note**: Another way to optionally include a dependency is to use\n> [platform-specific dependencies]. Instead of using features, these are\n> conditional based on the target platform.\n\n[platform-specific dependencies]: specifying-dependencies.md#platform-specific-dependencies\n\n## Dependency features\n\nFeatures of dependencies can be enabled within the dependency declaration. The\n`features` key indicates which features to enable:\n\n```toml\n[dependencies]\n# Enables the `derive` feature of serde.\nserde = { version = \"1.0.118\", features = [\"derive\"] }\n```\n\nThe [`default` features](#the-default-feature) can be disabled using\n`default-features = false`:\n\n```toml\n[dependencies]\nflate2 = { version = \"1.0.3\", default-features = false, features = [\"zlib-rs\"] }\n```\n\n> **Note**: This may not ensure the default features are disabled. If another\n> dependency includes `flate2` without specifying `default-features = false`,\n> then the default features will be enabled. See [feature\n> unification](#feature-unification) below for more details.\n\nFeatures of dependencies can also be enabled in the `[features]` table. The\nsyntax is `\"package-name/feature-name\"`. For example:\n\n```toml\n[dependencies]\njpeg-decoder = { version = \"0.1.20\", default-features = false }\n\n[features]\n# Enables parallel processing support by enabling the \"rayon\" feature of jpeg-decoder.\nparallel = [\"jpeg-decoder/rayon\"]\n```\n\nThe `\"package-name/feature-name\"` syntax will also enable `package-name`\nif it is an optional dependency. Often this is not what you want.\nYou can add a `?` as in `\"package-name?/feature-name\"` which will only enable\nthe given feature if something else enables the optional dependency.\n\n> **Note**: The `?` syntax is only available starting with Rust 1.60.\n\nFor example, let's say we have added some serialization support to our\nlibrary, and it requires enabling a corresponding feature in some optional\ndependencies.\nThat can be done like this:\n\n```toml\n[dependencies]\nserde = { version = \"1.0.133\", optional = true }\nrgb = { version = \"0.8.25\", optional = true }\n\n[features]\nserde = [\"dep:serde\", \"rgb?/serde\"]\n```\n\nIn this example, enabling the `serde` feature will enable the serde\ndependency.\nIt will also enable the `serde` feature for the `rgb` dependency, but only if\nsomething else has enabled the `rgb` dependency.\n\n## Command-line feature options\n\nThe following command-line flags can be used to control which features are\nenabled:\n\n* `--features` _FEATURES_: Enables the listed features. Multiple features may\n  be separated with commas or spaces. If using spaces, be sure to use quotes\n  around all the features if running Cargo from a shell (such as `--features\n  \"foo bar\"`). If building multiple packages in a [workspace], the\n  `package-name/feature-name` syntax can be used to specify features for\n  specific workspace members.\n* `--all-features`: Activates all features of all packages selected on the command line.\n* `--no-default-features`: Does not activate the [`default`\n  feature](#the-default-feature) of the selected packages.\n  \n**NOTE**: check the individual subcommand documentation for details. Not all flags are available for all subcommands.\n\n[workspace]: workspaces.md\n\n## Feature unification\n\nFeatures are unique to the package that defines them. Enabling a feature on a\npackage does not enable a feature of the same name on other packages.\n\nWhen a dependency is used by multiple packages, Cargo will use the union of\nall features enabled on that dependency when building it. This helps ensure\nthat only a single copy of the dependency is used. See the [features section]\nof the resolver documentation for more details.\n\nFor example, let's look at the [`winapi`] package which uses a [large\nnumber][winapi-features] of features. If your package depends on a package\n`foo` which enables the \"fileapi\" and \"handleapi\" features of `winapi`, and\nanother dependency `bar` which enables the \"std\" and \"winnt\" features of\n`winapi`, then `winapi` will be built with all four of those features enabled.\n\n![winapi features example](../images/winapi-features.svg)\n\n[`winapi`]: https://crates.io/crates/winapi\n[winapi-features]: https://github.com/retep998/winapi-rs/blob/0.3.9/Cargo.toml#L25-L431\n\nA consequence of this is that features should be *additive*. That is, enabling\na feature should not disable functionality, and it should usually be safe to\nenable any combination of features. A feature should not introduce a\n[SemVer-incompatible change](#semver-compatibility).\n\nFor example, if you want to optionally support [`no_std`] environments, **do\nnot** use a `no_std` feature. Instead, use a `std` feature that *enables*\n`std`. For example:\n\n```rust\n#![no_std]\n\n#[cfg(feature = \"std\")]\nextern crate std;\n\n#[cfg(feature = \"std\")]\npub fn function_that_requires_std() {\n    // ...\n}\n```\n\n[`no_std`]: ../../reference/names/preludes.html#the-no_std-attribute\n[features section]: resolver.md#features\n\n### Mutually exclusive features\n\nThere are rare cases where features may be mutually incompatible with one\nanother. This should be avoided if at all possible, because it requires\ncoordinating all uses of the package in the dependency graph to cooperate to\navoid enabling them together. If it is not possible, consider adding a compile\nerror to detect this scenario. For example:\n\n```rust,ignore\n#[cfg(all(feature = \"foo\", feature = \"bar\"))]\ncompile_error!(\"feature \\\"foo\\\" and feature \\\"bar\\\" cannot be enabled at the same time\");\n```\n\nInstead of using mutually exclusive features, consider some other options:\n\n* Split the functionality into separate packages.\n* When there is a conflict, [choose one feature over\n  another][feature-precedence]. The [`cfg-if`] package can help with writing\n  more complex `cfg` expressions.\n* Architect the code to allow the features to be enabled concurrently, and use\n  runtime options to control which is used. For example, use a config file,\n  command-line argument, or environment variable to choose which behavior to\n  enable.\n\n[`cfg-if`]: https://crates.io/crates/cfg-if\n[feature-precedence]: features-examples.md#feature-precedence\n\n### Inspecting resolved features\n\nIn complex dependency graphs, it can sometimes be difficult to understand how\ndifferent features get enabled on various packages. The [`cargo tree`] command\noffers several options to help inspect and visualize which features are\nenabled. Some options to try:\n\n* `cargo tree -e features`: This will show features in the dependency graph.\n  Each feature will appear showing which package enabled it.\n* `cargo tree -f \"{p} {f}\"`: This is a more compact view that shows a\n  comma-separated list of features enabled on each package.\n* `cargo tree -e features -i foo`: This will invert the tree, showing how\n  features flow into the given package \"foo\". This can be useful because\n  viewing the entire graph can be quite large and overwhelming. Use this when\n  you are trying to figure out which features are enabled on a specific\n  package and why. See the example at the bottom of the [`cargo tree`] page on\n  how to read this.\n\n[`cargo tree`]: ../commands/cargo-tree.md\n\n## Feature resolver version 2\n\nA different feature resolver can be specified with the `resolver` field in\n`Cargo.toml`, like this:\n\n```toml\n[package]\nname = \"my-package\"\nversion = \"1.0.0\"\nresolver = \"2\"\n```\n\nSee the [resolver versions] section for more detail on specifying resolver\nversions.\n\nThe version `\"2\"` resolver avoids unifying features in a few situations where\nthat unification can be unwanted. The exact situations are described in the\n[resolver chapter][resolver-v2], but in short, it avoids unifying in these\nsituations:\n\n* Features enabled on [platform-specific dependencies] for [target architectures][target] not\n  currently being built are ignored.\n* [Build-dependencies] and proc-macros do not share features with normal\n  dependencies.\n* [Dev-dependencies] do not activate features unless building a [Cargo target][target] that\n  needs them (like tests or examples).\n\nAvoiding the unification is necessary for some situations. For example, if a\nbuild-dependency enables a `std` feature, and the same dependency is used as a\nnormal dependency for a `no_std` environment, enabling `std` would break the\nbuild.\n\nHowever, one drawback is that this can increase build times because the\ndependency is built multiple times (each with different features). When using\nthe version `\"2\"` resolver, it is recommended to check for dependencies that\nare built multiple times to reduce overall build time. If it is not *required*\nto build those duplicated packages with separate features, consider adding\nfeatures to the `features` list in the [dependency\ndeclaration](#dependency-features) so that the duplicates end up with the same\nfeatures (and thus Cargo will build it only once). You can detect these\nduplicate dependencies with the [`cargo tree --duplicates`][`cargo tree`]\ncommand. It will show which packages are built multiple times; look for any\nentries listed with the same version. See [Inspecting resolved\nfeatures](#inspecting-resolved-features) for more on fetching information on\nthe resolved features. For build dependencies, this is not necessary if you\nare cross-compiling with the `--target` flag because build dependencies are\nalways built separately from normal dependencies in that scenario.\n\n[target]: ../appendix/glossary.md#target\n\n### Resolver version 2 command-line flags\n\nThe `resolver = \"2\"` setting also changes the behavior of the `--features` and\n`--no-default-features` [command-line options](#command-line-feature-options).\n\nWith version `\"1\"`, you can only enable features for the package in the\ncurrent working directory. For example, in a workspace with packages `foo` and\n`bar`, and you are in the directory for package `foo`, and ran the command\n`cargo build -p bar --features bar-feat`, this would fail because the\n`--features` flag only allowed enabling features on `foo`.\n\nWith `resolver = \"2\"`, the features flags allow enabling features for any of\nthe packages selected on the command-line with `-p` and `--workspace` flags.\nFor example:\n\n```sh\n# This command is allowed with resolver = \"2\", regardless of which directory\n# you are in.\ncargo build -p foo -p bar --features foo-feat,bar-feat\n\n# This explicit equivalent works with any resolver version:\ncargo build -p foo -p bar --features foo/foo-feat,bar/bar-feat\n```\n\nAdditionally, with `resolver = \"1\"`, the `--no-default-features` flag only\ndisables the default feature for the package in the current directory. With\nversion \"2\", it will disable the default features for all workspace members.\n\n[resolver versions]: resolver.md#resolver-versions\n[build-dependencies]: specifying-dependencies.md#build-dependencies\n[dev-dependencies]: specifying-dependencies.md#development-dependencies\n[resolver-v2]: resolver.md#feature-resolver-version-2\n\n## Build scripts\n\n[Build scripts] can detect which features are enabled on the package by\ninspecting the `CARGO_FEATURE_<name>` environment variable, where `<name>` is\nthe feature name converted to uppercase and `-` converted to `_`.\n\n[build scripts]: build-scripts.md\n\n## Required features\n\nThe [`required-features` field] can be used to disable specific [Cargo\ntargets] if a feature is not enabled. See the linked documentation for more\ndetails.\n\n[`required-features` field]: cargo-targets.md#the-required-features-field\n[Cargo targets]: cargo-targets.md\n\n## SemVer compatibility\n\nEnabling a feature should not introduce a SemVer-incompatible change. For\nexample, the feature shouldn't change an existing API in a way that could\nbreak existing uses. More details about what changes are compatible can be\nfound in the [SemVer Compatibility chapter](semver.md).\n\nCare should be taken when adding and removing feature definitions and optional\ndependencies, as these can sometimes be backwards-incompatible changes. More\ndetails can be found in the [Cargo section](semver.md#cargo) of the SemVer\nCompatibility chapter. In short, follow these rules:\n\n* The following is usually safe to do in a minor release:\n  * Add a [new feature][cargo-feature-add] or [optional dependency][cargo-dep-add].\n  * [Change the features used on a dependency][cargo-change-dep-feature].\n* The following should usually **not** be done in a minor release:\n  * [Remove a feature][cargo-feature-remove] or [optional dependency][cargo-remove-opt-dep].\n  * [Moving existing public code behind a feature][item-remove].\n  * [Remove a feature from a feature list][cargo-feature-remove-another].\n\nSee the links for caveats and examples.\n\n[cargo-change-dep-feature]: semver.md#cargo-change-dep-feature\n[cargo-dep-add]: semver.md#cargo-dep-add\n[cargo-feature-add]: semver.md#cargo-feature-add\n[item-remove]: semver.md#item-remove\n[cargo-feature-remove]: semver.md#cargo-feature-remove\n[cargo-remove-opt-dep]: semver.md#cargo-remove-opt-dep\n[cargo-feature-remove-another]: semver.md#cargo-feature-remove-another\n\n## Feature documentation and discovery\n\nYou are encouraged to document which features are available in your package.\nThis can be done by adding [doc comments] at the top of `lib.rs`. As an\nexample, see the [regex crate source], which when rendered can be viewed on\n[docs.rs][regex-docs-rs]. If you have other documentation, such as a user\nguide, consider adding the documentation there (for example, see [serde.rs]).\nIf you have a binary project, consider documenting the features in the README\nor other documentation for the project (for example, see [sccache]).\n\nClearly documenting the features can set expectations about features that are\nconsidered \"unstable\" or otherwise shouldn't be used. For example, if there is\nan optional dependency, but you don't want users to explicitly list that\noptional dependency as a feature, exclude it from the documented list.\n\nDocumentation published on [docs.rs] can use metadata in `Cargo.toml` to\ncontrol which features are enabled when the documentation is built. See\n[docs.rs metadata documentation] for more details.\n\n> **Note**: Rustdoc has experimental support for annotating the documentation\n> to indicate which features are required to use certain APIs. See the\n> `doc_cfg` documentation for more details. An example is the [`syn`\n> documentation], where you can see colored boxes which note which features\n> are required to use it.\n\n[docs.rs metadata documentation]: https://docs.rs/about/metadata\n[docs.rs]: https://docs.rs/\n[serde.rs]: https://serde.rs/feature-flags.html\n[doc comments]: ../../rustdoc/how-to-write-documentation.html\n[regex crate source]: https://github.com/rust-lang/regex/blob/1.4.2/src/lib.rs#L488-L583\n[regex-docs-rs]: https://docs.rs/regex/1.4.2/regex/#crate-features\n[sccache]: https://github.com/mozilla/sccache/blob/0.2.13/README.md#build-requirements\n[`syn` documentation]: https://docs.rs/syn/1.0.54/syn/#modules\n\n### Discovering features\n\nWhen features are documented in the library API, this can make it easier for\nyour users to discover which features are available and what they do. If the\nfeature documentation for a package isn't readily available, you can look at\nthe `Cargo.toml` file, but sometimes it can be hard to track it down. The\ncrate page on [crates.io] has a link to the source repository if available.\nTools like [`cargo vendor`] or [cargo-clone-crate] can be used to download the\nsource and inspect it.\n\n[`cargo vendor`]: ../commands/cargo-vendor.md\n[cargo-clone-crate]: https://crates.io/crates/cargo-clone-crate\n\n## Feature combinations\n\nBecause features are a form of conditional compilation, they require an exponential number of configurations and test cases to be 100% covered. By default, tests, docs, and other tooling such as [Clippy](https://github.com/rust-lang/rust-clippy) will only run with the default set of features.\n\nWe encourage you to consider your strategy and tooling in regards to different feature combinations --- Every project will have different requirements in conjunction with time, resources, and the cost-benefit of covering specific scenarios. Common configurations may be with / without default features, specific combinations of features, or all combinations of features.\n"
  },
  {
    "path": "src/doc/src/reference/future-incompat-report.md",
    "content": "# Future incompat report\n\nCargo checks for future-incompatible warnings in all dependencies. These are warnings for\nchanges that may become hard errors in the future, causing the dependency to\nstop building in a future version of rustc. If any warnings are found, a small\nnotice is displayed indicating that the warnings were found, and provides\ninstructions on how to display a full report.\n\nFor example, you may see something like this at the end of a build:\n\n```text\nwarning: the following packages contain code that will be rejected by a future\n         version of Rust: rental v0.5.5\nnote: to see what the problems were, use the option `--future-incompat-report`,\n      or run `cargo report future-incompatibilities --id 1`\n```\n\nA full report can be displayed with the `cargo report future-incompatibilities\n--id ID` command, or by running the build again with\nthe `--future-incompat-report` flag. The developer should then update their\ndependencies to a version where the issue is fixed, or work with the\ndevelopers of the dependencies to help resolve the issue.\n\n## Configuration\n\nThis feature can be configured through a [`[future-incompat-report]`][config]\nsection in `.cargo/config.toml`. Currently, the supported options are:\n\n```toml\n[future-incompat-report]\nfrequency = \"always\"\n```\n\nThe supported values for the frequency are `\"always\"` and `\"never\"`, which control\nwhether or not a message is printed out at the end of `cargo build` / `cargo check`.\n\n[config]: config.md#future-incompat-report\n"
  },
  {
    "path": "src/doc/src/reference/index.md",
    "content": "# Cargo Reference\n\nThe reference covers the details of various areas of Cargo.\n\n* [The Manifest Format](manifest.md)\n    * [Cargo Targets](cargo-targets.md)\n    * [Rust version](rust-version.md)\n* [Workspaces](workspaces.md)\n* [Specifying Dependencies](specifying-dependencies.md)\n    * [Overriding Dependencies](overriding-dependencies.md)\n    * [Source Replacement](source-replacement.md)\n    * [Dependency Resolution](resolver.md)\n* [Features](features.md)\n    * [Features Examples](features-examples.md)\n* [Profiles](profiles.md)\n* [Configuration](config.md)\n* [Environment Variables](environment-variables.md)\n* [Build Scripts](build-scripts.md)\n    * [Build Script Examples](build-script-examples.md)\n* [Build Cache](build-cache.md)\n* [Package ID Specifications](pkgid-spec.md)\n* [External Tools](external-tools.md)\n* [Registries](registries.md)\n    * [Registry Authentication](registry-authentication.md)\n        * [Credential Provider Protocol](credential-provider-protocol.md)\n    * [Running a Registry](running-a-registry.md)\n        * [Registry Index](registry-index.md)\n        * [Registry Web API](registry-web-api.md)\n* [SemVer Compatibility](semver.md)\n* [Future incompat report](future-incompat-report.md)\n* [Reporting build timings](timings.md)\n* [Lints](lints.md)\n* [Unstable Features](unstable.md)\n"
  },
  {
    "path": "src/doc/src/reference/lints.md",
    "content": "# Lints\n\nNote: [Cargo's linting system is unstable](unstable.md#lintscargo) and can only be used on nightly toolchains\n\n\n\n| Group                | Description                                                      | Default level |\n|----------------------|------------------------------------------------------------------|---------------|\n| `cargo::complexity`  | code that does something simple but in a complex way             | warn          |\n| `cargo::correctness` | code that is outright wrong or useless                           | deny          |\n| `cargo::nursery`     | new lints that are still under development                       | allow         |\n| `cargo::pedantic`    | lints which are rather strict or have occasional false positives | allow         |\n| `cargo::perf`        | code that can be written to run faster                           | warn          |\n| `cargo::restriction` | lints which prevent the use of Cargo features                    | allow         |\n| `cargo::style`       | code that should be written in a more idiomatic way              | warn          |\n| `cargo::suspicious`  | code that is most likely wrong or useless                        | warn          |\n\n\n## Allowed-by-default\n\nThese lints are all set to the 'allow' level by default.\n- [`implicit_minimum_version_req`](#implicit_minimum_version_req)\n- [`non_kebab_case_features`](#non_kebab_case_features)\n- [`non_kebab_case_packages`](#non_kebab_case_packages)\n- [`non_snake_case_features`](#non_snake_case_features)\n- [`non_snake_case_packages`](#non_snake_case_packages)\n\n## Warn-by-default\n\nThese lints are all set to the 'warn' level by default.\n- [`blanket_hint_mostly_unused`](#blanket_hint_mostly_unused)\n- [`missing_lints_inheritance`](#missing_lints_inheritance)\n- [`non_kebab_case_bins`](#non_kebab_case_bins)\n- [`redundant_homepage`](#redundant_homepage)\n- [`redundant_readme`](#redundant_readme)\n- [`unknown_lints`](#unknown_lints)\n- [`unused_workspace_dependencies`](#unused_workspace_dependencies)\n- [`unused_workspace_package_fields`](#unused_workspace_package_fields)\n\n## `blanket_hint_mostly_unused`\nGroup: `suspicious`\n\nLevel: `warn`\n\nMSRV: `1.79.0`\n\n### What it does\nChecks if `hint-mostly-unused` being applied to all dependencies.\n\n### Why it is bad\n`hint-mostly-unused` indicates that most of a crate's API surface will go\nunused by anything depending on it; this hint can speed up the build by\nattempting to minimize compilation time for items that aren't used at all.\nMisapplication to crates that don't fit that criteria will slow down the build\nrather than speeding it up. It should be selectively applied to dependencies\nthat meet these criteria. Applying it globally is always a misapplication and\nwill likely slow down the build.\n\n### Example\n```toml\n[profile.dev.package.\"*\"]\nhint-mostly-unused = true\n```\n\nShould instead be:\n```toml\n[profile.dev.package.huge-mostly-unused-dependency]\nhint-mostly-unused = true\n```\n\n\n## `implicit_minimum_version_req`\nGroup: `pedantic`\n\nLevel: `allow`\n\n### What it does\n\nChecks for dependency version requirements\nthat do not explicitly specify a full `major.minor.patch` version requirement,\nsuch as `serde = \"1\"` or `serde = \"1.0\"`.\n\nThis lint currently only applies to caret requirements\n(the [default requirements](specifying-dependencies.md#default-requirements)).\n\n### Why it is bad\n\nVersion requirements without an explicit full version\ncan be misleading about the actual minimum supported version.\nFor example,\n`serde = \"1\"` has an implicit minimum bound of `1.0.0`.\nIf your code actually requires features from `1.0.219`,\nthe implicit minimum bound of `1.0.0` gives a false impression about compatibility.\n\nSpecifying the full version helps with:\n\n- Accurate minimum version documentation\n- Better compatibility with `-Z minimal-versions`\n- Clearer dependency constraints for consumers\n\n### Drawbacks\n\nEven with a fully specified version,\nthe minimum bound might still be incorrect if untested.\nThis lint helps make the minimum version requirement explicit\nbut doesn't guarantee correctness.\n\n### Example\n\n```toml\n[dependencies]\nserde = \"1\"\n```\n\nShould be written as a full specific version:\n\n```toml\n[dependencies]\nserde = \"1.0.219\"\n```\n\n\n## `missing_lints_inheritance`\nGroup: `suspicious`\n\nLevel: `warn`\n\nMSRV: `1.79.0`\n\n### What it does\n\nChecks for packages without a `lints` table while `workspace.lints` is present.\n\n### Why it is bad\n\nMany people mistakenly think that `workspace.lints` is implicitly inherited when it is not.\n\n### Drawbacks\n\n### Example\n\n```toml\n[workspace.lints.cargo]\n```\n\nShould be written as:\n\n```toml\n[workspace.lints.cargo]\n\n[lints]\nworkspace = true\n```\n\n\n## `non_kebab_case_bins`\nGroup: `style`\n\nLevel: `warn`\n\nMSRV: `1.79.0`\n\n### What it does\n\nDetect binary names, explicit and implicit, that are not kebab-case\n\n### Why it is bad\n\nKebab-case binary names is a common convention among command line tools.\n\n### Drawbacks\n\nIt would be disruptive to existing users to change the binary name.\n\nA binary may need to conform to externally controlled conventions which can include a different naming convention.\n\nGUI applications may wish to choose a more user focused naming convention, like \"Title Case\" or \"Sentence case\".\n\n### Example\n\n```toml\n[[bin]]\nname = \"foo_bar\"\n```\n\nShould be written as:\n\n```toml\n[[bin]]\nname = \"foo-bar\"\n```\n\n\n## `non_kebab_case_features`\nGroup: `restriction`\n\nLevel: `allow`\n\n### What it does\n\nDetect feature names that are not kebab-case.\n\n### Why it is bad\n\nHaving multiple naming styles within a workspace can be confusing.\n\n### Drawbacks\n\nUsers would expect that a feature tightly coupled to a dependency would match the dependency's name.\n\n### Example\n\n```toml\n[features]\nfoo_bar = []\n```\n\nShould be written as:\n\n```toml\n[features]\nfoo-bar = []\n```\n\n\n## `non_kebab_case_packages`\nGroup: `restriction`\n\nLevel: `allow`\n\n### What it does\n\nDetect package names that are not kebab-case.\n\n### Why it is bad\n\nHaving multiple naming styles within a workspace can be confusing.\n\n### Drawbacks\n\nUsers have to mentally translate package names to namespaces in Rust.\n\n### Example\n\n```toml\n[package]\nname = \"foo_bar\"\n```\n\nShould be written as:\n\n```toml\n[package]\nname = \"foo-bar\"\n```\n\n\n## `non_snake_case_features`\nGroup: `restriction`\n\nLevel: `allow`\n\n### What it does\n\nDetect feature names that are not snake-case.\n\n### Why it is bad\n\nHaving multiple naming styles within a workspace can be confusing.\n\n### Drawbacks\n\nUsers would expect that a feature tightly coupled to a dependency would match the dependency's name.\n\n### Example\n\n```toml\n[features]\nfoo-bar = []\n```\n\nShould be written as:\n\n```toml\n[features]\nfoo_bar = []\n```\n\n\n## `non_snake_case_packages`\nGroup: `restriction`\n\nLevel: `allow`\n\n### What it does\n\nDetect package names that are not snake-case.\n\n### Why it is bad\n\nHaving multiple naming styles within a workspace can be confusing.\n\n### Drawbacks\n\nUsers have to mentally translate package names to namespaces in Rust.\n\n### Example\n\n```toml\n[package]\nname = \"foo_bar\"\n```\n\nShould be written as:\n\n```toml\n[package]\nname = \"foo-bar\"\n```\n\n\n## `redundant_homepage`\nGroup: `style`\n\nLevel: `warn`\n\nMSRV: `1.79.0`\n\n### What it does\n\nChecks if the value of `package.homepage` is already covered by another field.\n\nSee also [`package.homepage` reference documentation](manifest.md#the-homepage-field).\n\n### Why it is bad\n\nWhen package browsers render each link, a redundant link adds visual noise.\n\n### Drawbacks\n\n### Example\n\n```toml\n[package]\nname = \"foo\"\nhomepage = \"https://github.com/rust-lang/cargo/\"\nrepository = \"https://github.com/rust-lang/cargo/\"\n```\n\nShould be written as:\n\n```toml\n[package]\nname = \"foo\"\nrepository = \"https://github.com/rust-lang/cargo/\"\n```\n\n\n## `redundant_readme`\nGroup: `style`\n\nLevel: `warn`\n\nMSRV: `1.79.0`\n\n### What it does\n\nChecks for `package.readme` fields that can be inferred.\n\nSee also [`package.readme` reference documentation](manifest.md#the-readme-field).\n\n### Why it is bad\n\nAdds boilerplate.\n\n### Drawbacks\n\nIt might not be obvious if they named their file correctly.\n\n### Example\n\n```toml\n[package]\nname = \"foo\"\nreadme = \"README.md\"\n```\n\nShould be written as:\n\n```toml\n[package]\nname = \"foo\"\n```\n\n\n## `unknown_lints`\nGroup: `suspicious`\n\nLevel: `warn`\n\nMSRV: `1.79.0`\n\n### What it does\nChecks for unknown lints in the `[lints.cargo]` table\n\n### Why it is bad\n- The lint name could be misspelled, leading to confusion as to why it is\n  not working as expected\n- The unknown lint could end up causing an error if `cargo` decides to make\n  a lint with the same name in the future\n\n### Example\n```toml\n[lints.cargo]\nthis-lint-does-not-exist = \"warn\"\n```\n\n\n## `unused_workspace_dependencies`\nGroup: `suspicious`\n\nLevel: `warn`\n\nMSRV: `1.79.0`\n\n### What it does\nChecks for any entry in `[workspace.dependencies]` that has not been inherited\n\n### Why it is bad\nThey can give the false impression that these dependencies are used\n\n### Example\n```toml\n[workspace.dependencies]\nregex = \"1\"\n\n[dependencies]\n```\n\n\n## `unused_workspace_package_fields`\nGroup: `suspicious`\n\nLevel: `warn`\n\nMSRV: `1.79.0`\n\n### What it does\nChecks for any fields in `[workspace.package]` that has not been inherited\n\n### Why it is bad\nThey can give the false impression that these fields are used\n\n### Example\n```toml\n[workspace.package]\nedition = \"2024\"\n\n[package]\nname = \"foo\"\n```\n\n\n"
  },
  {
    "path": "src/doc/src/reference/manifest.md",
    "content": "# The Manifest Format\n\nThe `Cargo.toml` file for each package is called its *manifest*. It is written\nin the [TOML] format. It contains metadata that is needed to compile the package. Checkout\nthe `cargo locate-project` section for more detail on how cargo finds the manifest file.\n\nEvery manifest file consists of the following sections:\n\n* [`cargo-features`](unstable.md) --- Unstable, nightly-only features.\n* [`[package]`](#the-package-section) --- Defines a package.\n  * [`name`](#the-name-field) --- The name of the package.\n  * [`version`](#the-version-field) --- The version of the package.\n  * [`authors`](#the-authors-field) --- The authors of the package.\n  * [`edition`](#the-edition-field) --- The Rust edition.\n  * [`rust-version`](rust-version.md) --- The minimal supported Rust version.\n  * [`description`](#the-description-field) --- A description of the package.\n  * [`documentation`](#the-documentation-field) --- URL of the package documentation.\n  * [`readme`](#the-readme-field) --- Path to the package's README file.\n  * [`homepage`](#the-homepage-field) --- URL of the package homepage.\n  * [`repository`](#the-repository-field) --- URL of the package source repository.\n  * [`license`](#the-license-and-license-file-fields) --- The package license.\n  * [`license-file`](#the-license-and-license-file-fields) --- Path to the text of the license.\n  * [`keywords`](#the-keywords-field) --- Keywords for the package.\n  * [`categories`](#the-categories-field) --- Categories of the package.\n  * [`workspace`](#the-workspace-field) --- Path to the workspace for the package.\n  * [`build`](#the-build-field) --- Path to the package build script.\n  * [`links`](#the-links-field) --- Name of the native library the package links with.\n  * [`exclude`](#the-exclude-and-include-fields) --- Files to exclude when publishing.\n  * [`include`](#the-exclude-and-include-fields) --- Files to include when publishing.\n  * [`publish`](#the-publish-field) --- Can be used to prevent publishing the package.\n  * [`metadata`](#the-metadata-table) --- Extra settings for external tools.\n  * [`default-run`](#the-default-run-field) --- The default binary to run by [`cargo run`].\n  * [`autolib`](cargo-targets.md#target-auto-discovery) --- Disables library auto discovery.\n  * [`autobins`](cargo-targets.md#target-auto-discovery) --- Disables binary auto discovery.\n  * [`autoexamples`](cargo-targets.md#target-auto-discovery) --- Disables example auto discovery.\n  * [`autotests`](cargo-targets.md#target-auto-discovery) --- Disables test auto discovery.\n  * [`autobenches`](cargo-targets.md#target-auto-discovery) --- Disables bench auto discovery.\n  * [`resolver`](resolver.md#resolver-versions) --- Sets the dependency resolver to use.\n* Target tables: (see [configuration](cargo-targets.md#configuring-a-target) for settings)\n  * [`[lib]`](cargo-targets.md#library) --- Library target settings.\n  * [`[[bin]]`](cargo-targets.md#binaries) --- Binary target settings.\n  * [`[[example]]`](cargo-targets.md#examples) --- Example target settings.\n  * [`[[test]]`](cargo-targets.md#tests) --- Test target settings.\n  * [`[[bench]]`](cargo-targets.md#benchmarks) --- Benchmark target settings.\n* Dependency tables:\n  * [`[dependencies]`](specifying-dependencies.md) --- Package library dependencies.\n  * [`[dev-dependencies]`](specifying-dependencies.md#development-dependencies) --- Dependencies for examples, tests, and benchmarks.\n  * [`[build-dependencies]`](specifying-dependencies.md#build-dependencies) --- Dependencies for build scripts.\n  * [`[target]`](specifying-dependencies.md#platform-specific-dependencies) --- Platform-specific dependencies.\n* [`[badges]`](#the-badges-section) --- Badges to display on a registry.\n* [`[features]`](features.md) --- Conditional compilation features.\n* [`[lints]`](#the-lints-section) --- Configure linters for this package.\n* [`[hints]`](#the-hints-section) --- Provide hints for compiling this package.\n* [`[patch]`](overriding-dependencies.md#the-patch-section) --- Override dependencies.\n* [`[replace]`](overriding-dependencies.md#the-replace-section) --- Override dependencies (deprecated).\n* [`[profile]`](profiles.md) --- Compiler settings and optimizations.\n* [`[workspace]`](workspaces.md) --- The workspace definition.\n\n## The `[package]` section\n\nThe first section in a `Cargo.toml` is `[package]`.\n\n```toml\n[package]\nname = \"hello_world\" # the name of the package\nversion = \"0.1.0\"    # the current version, obeying semver\n```\n\nThe only field required by Cargo is [`name`](#the-name-field). If publishing to\na registry, the registry may require additional fields. See the notes below and\n[the publishing chapter][publishing] for requirements for publishing to\n[crates.io].\n\n### The `name` field\n\nThe package name is an identifier used to refer to the package. It is used\nwhen listed as a dependency in another package, and as the default name of\ninferred lib and bin targets.\n\nThe name must use only [alphanumeric] characters or `-` or `_`, and cannot be empty.\n\nNote that [`cargo new`] and [`cargo init`] impose some additional restrictions on\nthe package name, such as enforcing that it is a valid Rust identifier and not\na keyword. [crates.io] imposes even more restrictions, such as:\n\n- Only ASCII characters are allowed.\n- Do not use reserved names.\n- Do not use special Windows names such as \"nul\".\n- Use a maximum of 64 characters of length.\n\n[alphanumeric]: ../../std/primitive.char.html#method.is_alphanumeric\n\n### The `version` field\n\nThe `version` field is formatted according to the [SemVer] specification:\n\nVersions must have three numeric parts,\nthe major version, the minor version, and the patch version.\n\nA pre-release part can be added after a dash such as `1.0.0-alpha`.\nThe pre-release part may be separated with periods to distinguish separate\ncomponents. Numeric components will use numeric comparison while\neverything else will be compared lexicographically.\nFor example, `1.0.0-alpha.11` is higher than `1.0.0-alpha.4`.\n\nA metadata part can be added after a plus, such as `1.0.0+21AF26D3`.\nThis is for informational purposes only and is generally ignored by Cargo.\n\nCargo bakes in the concept of [Semantic Versioning](https://semver.org/),\nso versions are considered [compatible](semver.md) if their left-most non-zero major/minor/patch component is the same.\nSee the [Resolver] chapter for more information on how Cargo uses versions to\nresolve dependencies.\n\nThis field is optional and defaults to `0.0.0`.  The field is required for publishing packages.\n\n> **MSRV:** Before 1.75, this field was required\n\n[SemVer]: https://semver.org\n[Resolver]: resolver.md\n[SemVer compatibility]: semver.md\n\n### The `authors` field\n\n> **Warning**: This field is deprecated\n\nThe optional `authors` field lists in an array the people or organizations that are considered\nthe \"authors\" of the package. An optional email address may be included within angled brackets at\nthe end of each author entry.\n\n```toml\n[package]\n# ...\nauthors = [\"Graydon Hoare\", \"Fnu Lnu <no-reply@rust-lang.org>\"]\n```\n\nThis field is surfaced in package metadata and in the `CARGO_PKG_AUTHORS`\nenvironment variable within `build.rs` for backwards compatibility.\n\n### The `edition` field\n\nThe `edition` key is an optional key that affects which [Rust Edition] your package\nis compiled with. Setting the `edition` key in `[package]` will affect all\ntargets/crates in the package, including test suites, benchmarks, binaries,\nexamples, etc.\n\n```toml\n[package]\n# ...\nedition = '2024'\n```\n\nMost manifests have the `edition` field filled in automatically by [`cargo new`]\nwith the latest stable edition. By default `cargo new` creates a manifest with\nthe 2024 edition currently.\n\nIf the `edition` field is not present in `Cargo.toml`, then the 2015 edition is\nassumed for backwards compatibility. Note that all manifests\ncreated with [`cargo new`] will not use this historical fallback because they\nwill have `edition` explicitly specified to a newer value.\n\n### The `rust-version` field\n\nThe `rust-version` field tells cargo what version of the\nRust toolchain you support for your package.\nSee [the Rust version chapter](rust-version.md) for more detail.\n\n### The `description` field\n\nThe description is a short blurb about the package. [crates.io] will display\nthis with your package. This should be plain text (not Markdown).\n\n```toml\n[package]\n# ...\ndescription = \"A short description of my package\"\n```\n\n> **Note**: [crates.io] requires the `description` to be set.\n\n### The `documentation` field\n\nThe `documentation` field specifies a URL to a website hosting the crate's\ndocumentation. If no URL is specified in the manifest file, [crates.io] will\nautomatically link your crate to the corresponding [docs.rs] page when the\ndocumentation has been built and is available (see [docs.rs queue]).\n\n```toml\n[package]\n# ...\ndocumentation = \"https://docs.rs/bitflags\"\n```\n\n[docs.rs queue]: https://docs.rs/releases/queue\n\n### The `readme` field\n\nThe `readme` field should be the path to a file in the package root (relative\nto this `Cargo.toml`) that contains general information about the package.\nThis file will be transferred to the registry when you publish. [crates.io]\nwill interpret it as Markdown and render it on the crate's page.\n\n```toml\n[package]\n# ...\nreadme = \"README.md\"\n```\n\nIf no value is specified for this field, and a file named `README.md`,\n`README.txt` or `README` exists in the package root, then the name of that\nfile will be used. You can suppress this behavior by setting this field to\n`false`. If the field is set to `true`, a default value of `README.md` will\nbe assumed.\n\n### The `homepage` field\n\nThe `homepage` field should be a URL to a site that is the home page for your\npackage.\n\n```toml\n[package]\n# ...\nhomepage = \"https://serde.rs\"\n```\n\nA value should only be set for `homepage` if there is a dedicated website for\nthe crate other than the source repository or API documentation. Do not make\n`homepage` redundant with either the `documentation` or `repository` values.\n\n### The `repository` field\n\nThe `repository` field should be a URL to the source repository for your\npackage.\n\n```toml\n[package]\n# ...\nrepository = \"https://github.com/rust-lang/cargo\"\n```\n\n### The `license` and `license-file` fields\n\nThe `license` field contains the name of the software license that the package\nis released under. The `license-file` field contains the path to a file\ncontaining the text of the license (relative to this `Cargo.toml`).\n\n[crates.io] interprets the `license` field as an [SPDX 2.3 license\nexpression][spdx-2.3-license-expressions]. The name must be a known license\nfrom the [SPDX license list 3.20][spdx-license-list-3.20]. See the [SPDX site]\nfor more information.\n\nSPDX license expressions support AND and OR operators to combine multiple\nlicenses.[^slash]\n\n```toml\n[package]\n# ...\nlicense = \"MIT OR Apache-2.0\"\n```\n\nUsing `OR` indicates the user may choose either license. Using `AND` indicates\nthe user must comply with both licenses simultaneously. The `WITH` operator\nindicates a license with a special exception. Some examples:\n\n* `MIT OR Apache-2.0`\n* `LGPL-2.1-only AND MIT AND BSD-2-Clause`\n* `GPL-2.0-or-later WITH Bison-exception-2.2`\n\nIf a package is using a nonstandard license, then the `license-file` field may\nbe specified in lieu of the `license` field.\n\n```toml\n[package]\n# ...\nlicense-file = \"LICENSE.txt\"\n```\n\n> **Note**: [crates.io] requires either `license` or `license-file` to be set.\n\n[^slash]: Previously multiple licenses could be separated with a `/`, but that\nusage is deprecated.\n\n### The `keywords` field\n\nThe `keywords` field is an array of strings that describe this package. This\ncan help when searching for the package on a registry, and you may choose any\nwords that would help someone find this crate.\n\n```toml\n[package]\n# ...\nkeywords = [\"gamedev\", \"graphics\"]\n```\n\n> **Note**: [crates.io] allows a maximum of 5 keywords. Each keyword must be\n> ASCII text, have at most 20 characters, start with an alphanumeric character,\n> and only contain letters, numbers, `_`, `-` or `+`.\n\n### The `categories` field\n\nThe `categories` field is an array of strings of the categories this package\nbelongs to.\n\n```toml\ncategories = [\"command-line-utilities\", \"development-tools::cargo-plugins\"]\n```\n\n> **Note**: [crates.io] has a maximum of 5 categories. Each category should\n> match one of the strings available at <https://crates.io/category_slugs>, and\n> must match exactly.\n\n### The `workspace` field\n\nThe `workspace` field can be used to configure the workspace that this package\nwill be a member of. If not specified this will be inferred as the first\nCargo.toml with `[workspace]` upwards in the filesystem. Setting this is\nuseful if the member is not inside a subdirectory of the workspace root.\n\n```toml\n[package]\n# ...\nworkspace = \"path/to/workspace/root\"\n```\n\nThis field cannot be specified if the manifest already has a `[workspace]`\ntable defined. That is, a crate cannot both be a root crate in a workspace\n(contain `[workspace]`) and also be a member crate of another workspace\n(contain `package.workspace`).\n\nFor more information, see the [workspaces chapter](workspaces.md).\n\n### The `build` field\n\nThe `build` field specifies a file in the package root which is a [build\nscript] for building native code. More information can be found in the [build\nscript guide][build script].\n\n[build script]: build-scripts.md\n\n```toml\n[package]\n# ...\nbuild = \"build.rs\"\n```\n\nThe default is `\"build.rs\"`, which loads the script from a file named\n`build.rs` in the root of the package. Use `build = \"custom_build_name.rs\"` to\nspecify a path to a different file or `build = false` to disable automatic\ndetection of the build script.\n\n### The `links` field\n\nThe `links` field specifies the name of a native library that is being linked\nto. More information can be found in the [`links`][links] section of the build\nscript guide.\n\n[links]: build-scripts.md#the-links-manifest-key\n\nFor example, a crate that links a native library called \"git2\" (e.g. `libgit2.a`\non Linux) may specify:\n\n```toml\n[package]\n# ...\nlinks = \"git2\"\n```\n\n### The `exclude` and `include` fields\n\nThe `exclude` and `include` fields can be used to explicitly specify which\nfiles are included when packaging a project to be [published][publishing],\nand certain kinds of change tracking (described below).\nThe patterns specified in the `exclude` field identify a set of files that are\nnot included, and the patterns in `include` specify files that are explicitly\nincluded.\nYou may run [`cargo package --list`][`cargo package`] to verify which files will\nbe included in the package.\n\n```toml\n[package]\n# ...\nexclude = [\"/ci\", \"images/\", \".*\"]\n```\n\n```toml\n[package]\n# ...\ninclude = [\"/src\", \"COPYRIGHT\", \"/examples\", \"!/examples/big_example\"]\n```\n\nThe default if neither field is specified is to include all files from the\nroot of the package, except for the exclusions listed below.\n\nIf `include` is not specified, then the following files will be excluded:\n\n* If the package is not in a git repository, all \"hidden\" files starting with\n  a dot will be skipped.\n* If the package is in a git repository, any files that are ignored by the\n  [gitignore] rules of the repository and global git configuration will be\n  skipped.\n\nRegardless of whether `exclude` or `include` is specified, the following files\nare always excluded:\n\n* Any sub-packages will be skipped (any subdirectory that contains a\n  `Cargo.toml` file).\n* A directory named `target` in the root of the package will be skipped.\n\nThe following files are always included:\n\n* The `Cargo.toml` file of the package itself is always included, it does not\n  need to be listed in `include`.\n* A minimized `Cargo.lock` is automatically included.\n  See [`cargo package`] for more information.\n* If a [`license-file`](#the-license-and-license-file-fields) is specified, it\n  is always included.\n\nThe options are mutually exclusive; setting `include` will override an\n`exclude`. If you need to have exclusions to a set of `include` files, use the\n`!` operator described below.\n\nThe patterns should be [gitignore]-style patterns. Briefly:\n\n- `foo` matches any file or directory with the name `foo` anywhere in the\n  package. This is equivalent to the pattern `**/foo`.\n- `/foo` matches any file or directory with the name `foo` only in the root of\n  the package.\n- `foo/` matches any *directory* with the name `foo` anywhere in the package.\n- Common glob patterns like `*`, `?`, and `[]` are supported:\n  - `*` matches zero or more characters except `/`.  For example, `*.html`\n    matches any file or directory with the `.html` extension anywhere in the\n    package.\n  - `?` matches any character except `/`. For example, `foo?` matches `food`,\n    but not `foo`.\n  - `[]` allows for matching a range of characters. For example, `[ab]`\n    matches either `a` or `b`. `[a-z]` matches letters a through z.\n- `**/` prefix matches in any directory. For example, `**/foo/bar` matches the\n  file or directory `bar` anywhere that is directly under directory `foo`.\n- `/**` suffix matches everything inside. For example, `foo/**` matches all\n  files inside directory `foo`, including all files in subdirectories below\n  `foo`.\n- `/**/` matches zero or more directories. For example, `a/**/b` matches\n  `a/b`, `a/x/b`, `a/x/y/b`, and so on.\n- `!` prefix negates a pattern. For example, a pattern of `src/*.rs` and\n  `!foo.rs` would match all files with the `.rs` extension inside the `src`\n  directory, except for any file named `foo.rs`.\n\nThe include/exclude list is also used for change tracking in some situations.\nFor targets built with `rustdoc`, it is used to determine the list of files to\ntrack to determine if the target should be rebuilt. If the package has a\n[build script] that does not emit any `rerun-if-*` directives, then the\ninclude/exclude list is used for tracking if the build script should be re-run\nif any of those files change.\n\n[gitignore]: https://git-scm.com/docs/gitignore\n\n### The `publish` field\n\nThe `publish` field can be used to control which registries names the package\nmay be published to:\n```toml\n[package]\n# ...\npublish = [\"some-registry-name\"]\n```\n\nTo prevent a package from being published to a registry (like crates.io) by mistake,\nfor instance to keep a package private in a company,\nyou can omit the [`version`](#the-version-field) field.\nIf you'd like to be more explicit, you can disable publishing:\n```toml\n[package]\n# ...\npublish = false\n```\n\nIf publish array contains a single registry, `cargo publish` command will use\nit when `--registry` flag is not specified.\n\n### The `metadata` table\n\nCargo by default will warn about unused keys in `Cargo.toml` to assist in\ndetecting typos and such. The `package.metadata` table, however, is completely\nignored by Cargo and will not be warned about. This section can be used for\ntools which would like to store package configuration in `Cargo.toml`. For\nexample:\n\n```toml\n[package]\nname = \"...\"\n# ...\n\n# Metadata used when generating an Android APK, for example.\n[package.metadata.android]\npackage-name = \"my-awesome-android-app\"\nassets = \"path/to/static\"\n```\n\nYou'll need to look in the documentation for your tool to see how to use this field.\nFor Rust Projects that use `package.metadata` tables, see:\n- [docs.rs](https://docs.rs/about/metadata)\n\nThere is a similar table at the workspace level at\n[`workspace.metadata`][workspace-metadata]. While cargo does not specify a\nformat for the content of either of these tables, it is suggested that\nexternal tools may wish to use them in a consistent fashion, such as referring\nto the data in `workspace.metadata` if data is missing from `package.metadata`,\nif that makes sense for the tool in question.\n\n[workspace-metadata]: workspaces.md#the-metadata-table\n\n### The `default-run` field\n\nThe `default-run` field in the `[package]` section of the manifest can be used\nto specify a default binary picked by [`cargo run`]. For example, when there is\nboth `src/bin/a.rs` and `src/bin/b.rs`:\n\n```toml\n[package]\ndefault-run = \"a\"\n```\n\n## The `[lints]` section\n\nOverride the default level of lints from different tools by assigning them to a new level in a\ntable, for example:\n```toml\n[lints.rust]\nunsafe_code = \"forbid\"\n```\n\nThis is short-hand for:\n```toml\n[lints.rust]\nunsafe_code = { level = \"forbid\", priority = 0 }\n```\n\n`level` corresponds to the [lint levels](https://doc.rust-lang.org/rustc/lints/levels.html) in `rustc`:\n- `forbid`\n- `deny`\n- `warn`\n- `allow`\n\n`priority` is a signed integer that controls which lints or lint groups override other lint groups:\n- lower (particularly negative) numbers have lower priority, being overridden\n  by higher numbers, and show up first on the command-line to tools like\n  `rustc`\n\nTo know which table under `[lints]` a particular lint belongs under, it is the part before `::` in the lint\nname.  If there isn't a `::`, then the tool is `rust`.  For example a warning\nabout `unsafe_code` would be `lints.rust.unsafe_code` but a lint about\n`clippy::enum_glob_use` would be `lints.clippy.enum_glob_use`.\n\nFor example:\n```toml\n[lints.rust]\nunsafe_code = \"forbid\"\n\n[lints.clippy]\nenum_glob_use = \"deny\"\n```\n\nGenerally, these will only affect local development of the current package.\nCargo only applies these to the current package and not to dependencies.\nAs for dependents, Cargo suppresses lints from non-path dependencies with features like\n[`--cap-lints`](../../rustc/lints/levels.html#capping-lints).\n\n> **MSRV:** Respected as of 1.74\n\n## The `[hints]` section\n\nThe `[hints]` section allows specifying hints for compiling this package. Cargo\nwill respect these hints by default when compiling this package, though the\ntop-level package being built can override these values through the `[profile]`\nmechanism. Hints are, by design, always safe for Cargo to ignore; if Cargo\nencounters a hint it doesn't understand, or a hint it understands but with a\nvalue it doesn't understand, it will warn, but not error. As a result,\nspecifying hints in a crate does not impact the MSRV of the crate.\n\nIndividual hints may have an associated unstable feature gate that you need to\npass in order to apply the configuration they specify, but if you don't specify\nthat unstable feature gate, you will again get only a warning, not an error.\n\nThere are no stable hints at this time. See the [hint-mostly-unused\ndocumentation](unstable.md#profile-hint-mostly-unused-option) for information\non an unstable hint.\n\n> **MSRV:** Respected as of 1.90.\n\n## The `[badges]` section\n\nThe `[badges]` section is for specifying status badges that can be displayed\non a registry website when the package is published.\n\n> Note: [crates.io] previously displayed badges next to a crate on its\n> website, but that functionality has been removed. Packages should place\n> badges in its README file which will be displayed on [crates.io] (see [the\n> `readme` field](#the-readme-field)).\n\n```toml\n[badges]\n# The `maintenance` table indicates the status of the maintenance of\n# the crate. This may be used by a registry, but is currently not\n# used by crates.io. See https://github.com/rust-lang/crates.io/issues/2437\n# and https://github.com/rust-lang/crates.io/issues/2438 for more details.\n#\n# The `status` field is required. Available options are:\n# - `actively-developed`: New features are being added and bugs are being fixed.\n# - `passively-maintained`: There are no plans for new features, but the maintainer intends to\n#   respond to issues that get filed.\n# - `as-is`: The crate is feature complete, the maintainer does not intend to continue working on\n#   it or providing support, but it works for the purposes it was designed for.\n# - `experimental`: The author wants to share it with the community but is not intending to meet\n#   anyone's particular use case.\n# - `looking-for-maintainer`: The current maintainer would like to transfer the crate to someone\n#   else.\n# - `deprecated`: The maintainer does not recommend using this crate (the description of the crate\n#   can describe why, there could be a better solution available or there could be problems with\n#   the crate that the author does not want to fix).\n# - `none`: Displays no badge on crates.io, since the maintainer has not chosen to specify\n#   their intentions, potential crate users will need to investigate on their own.\nmaintenance = { status = \"...\" }\n```\n\n## Dependency sections\n\nSee the [specifying dependencies page](specifying-dependencies.md) for\ninformation on the `[dependencies]`, `[dev-dependencies]`,\n`[build-dependencies]`, and target-specific `[target.*.dependencies]` sections.\n\n## The `[profile.*]` sections\n\nThe `[profile]` tables provide a way to customize compiler settings such as\noptimizations and debug settings. See [the Profiles chapter](profiles.md) for\nmore detail.\n\n\n\n[`cargo init`]: ../commands/cargo-init.md\n[`cargo new`]: ../commands/cargo-new.md\n[`cargo package`]: ../commands/cargo-package.md\n[`cargo run`]: ../commands/cargo-run.md\n[crates.io]: https://crates.io/\n[docs.rs]: https://docs.rs/\n[publishing]: publishing.md\n[Rust Edition]: ../../edition-guide/index.html\n[spdx-2.3-license-expressions]: https://spdx.github.io/spdx-spec/v2.3/SPDX-license-expressions/\n[spdx-license-list-3.20]: https://github.com/spdx/license-list-data/tree/v3.20\n[SPDX site]: https://spdx.org\n[TOML]: https://toml.io/\n"
  },
  {
    "path": "src/doc/src/reference/overriding-dependencies.md",
    "content": "# Overriding Dependencies\n\nThe desire to override a dependency can arise through a number of scenarios.\nMost of them, however, boil down to the ability to work with a crate before\nit's been published to [crates.io]. For example:\n\n* A crate you're working on is also used in a much larger application you're\n  working on, and you'd like to test a bug fix to the library inside of the\n  larger application.\n* An upstream crate you don't work on has a new feature or a bug fix on the\n  master branch of its git repository which you'd like to test out.\n* You're about to publish a new major version of your crate, but you'd like to\n  do integration testing across an entire package to ensure the new major\n  version works.\n* You've submitted a fix to an upstream crate for a bug you found, but you'd\n  like to immediately have your application start depending on the fixed\n  version of the crate to avoid blocking on the bug fix getting merged.\n\nThese scenarios can be solved with the [`[patch]` manifest\nsection](#the-patch-section).\n\nThis chapter walks through a few different use cases, and includes details\non the different ways to override a dependency.\n\n* Example use cases\n    * [Testing a bugfix](#testing-a-bugfix)\n    * [Working with an unpublished minor version](#working-with-an-unpublished-minor-version)\n        * [Overriding repository URL](#overriding-repository-url)\n    * [Prepublishing a breaking change](#prepublishing-a-breaking-change)\n    * [Using `[patch]` with multiple versions](#using-patch-with-multiple-versions)\n* Reference\n    * [The `[patch]` section](#the-patch-section)\n    * [The `[replace]` section](#the-replace-section)\n    * [`paths` overrides](#paths-overrides)\n\n> **Note**: See also specifying a dependency with [multiple locations], which\n> can be used to override the source for a single dependency declaration in a\n> local package.\n\n## Testing a bugfix\n\nLet's say you're working with the [`uuid` crate] but while you're working on it\nyou discover a bug. You are, however, quite enterprising so you decide to also\ntry to fix the bug! Originally your manifest will look like:\n\n[`uuid` crate]: https://crates.io/crates/uuid\n\n```toml\n[package]\nname = \"my-library\"\nversion = \"0.1.0\"\n\n[dependencies]\nuuid = \"1.0\"\n```\n\nFirst thing we'll do is to clone the [`uuid` repository][uuid-repository]\nlocally via:\n\n```console\n$ git clone https://github.com/uuid-rs/uuid.git\n```\n\nNext we'll edit the manifest of `my-library` to contain:\n\n```toml\n[patch.crates-io]\nuuid = { path = \"../path/to/uuid\" }\n```\n\nHere we declare that we're *patching* the source `crates-io` with a new\ndependency. This will effectively add the local checked out version of `uuid` to\nthe crates.io registry for our local package.\n\nNext up we need to ensure that our lock file is updated to use this new version\nof `uuid` so our package uses the locally checked out copy instead of one from\ncrates.io. The way `[patch]` works is that it'll load the dependency at\n`../path/to/uuid` and then whenever crates.io is queried for versions of `uuid`\nit'll *also* return the local version.\n\nThis means that the version number of the local checkout is significant and will\naffect whether the patch is used. Our manifest declared `uuid = \"1.0\"` which\nmeans we'll only resolve to `>= 1.0.0, < 2.0.0`, and Cargo's greedy resolution\nalgorithm also means that we'll resolve to the maximum version within that\nrange. Typically this doesn't matter as the version of the git repository will\nalready be greater or match the maximum version published on crates.io, but it's\nimportant to keep this in mind!\n\nIn any case, typically all you need to do now is:\n\n```console\n$ cargo build\n   Compiling uuid v1.0.0 (.../uuid)\n   Compiling my-library v0.1.0 (.../my-library)\n    Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs\n```\n\nAnd that's it! You're now building with the local version of `uuid` (note the\npath in parentheses in the build output). If you don't see the local path version getting\nbuilt then you may need to run `cargo update uuid --precise $version` where\n`$version` is the version of the locally checked out copy of `uuid`.\n\nOnce you've fixed the bug you originally found the next thing you'll want to do\nis to likely submit that as a pull request to the `uuid` crate itself. Once\nyou've done this then you can also update the `[patch]` section. The listing\ninside of `[patch]` is just like the `[dependencies]` section, so once your pull\nrequest is merged you could change your `path` dependency to:\n\n```toml\n[patch.crates-io]\nuuid = { git = 'https://github.com/uuid-rs/uuid.git' }\n```\n\n[uuid-repository]: https://github.com/uuid-rs/uuid\n\n## Working with an unpublished minor version\n\nLet's now shift gears a bit from bug fixes to adding features. While working on\n`my-library` you discover that a whole new feature is needed in the `uuid`\ncrate. You've implemented this feature, tested it locally above with `[patch]`,\nand submitted a pull request. Let's go over how you continue to use and test it\nbefore it's actually published.\n\nLet's also say that the current version of `uuid` on crates.io is `1.0.0`, but\nsince then the master branch of the git repository has updated to `1.0.1`. This\nbranch includes your new feature you submitted previously. To use this\nrepository we'll edit our `Cargo.toml` to look like\n\n```toml\n[package]\nname = \"my-library\"\nversion = \"0.1.0\"\n\n[dependencies]\nuuid = \"1.0.1\"\n\n[patch.crates-io]\nuuid = { git = 'https://github.com/uuid-rs/uuid.git' }\n```\n\nNote that our local dependency on `uuid` has been updated to `1.0.1` as it's\nwhat we'll actually require once the crate is published. This version doesn't\nexist on crates.io, though, so we provide it with the `[patch]` section of the\nmanifest.\n\nNow when our library is built it'll fetch `uuid` from the git repository and\nresolve to 1.0.1 inside the repository instead of trying to download a version\nfrom crates.io. Once 1.0.1 is published on crates.io the `[patch]` section can\nbe deleted.\n\nIt's also worth noting that `[patch]` applies *transitively*. Let's say you use\n`my-library` in a larger package, such as:\n\n```toml\n[package]\nname = \"my-binary\"\nversion = \"0.1.0\"\n\n[dependencies]\nmy-library = { git = 'https://example.com/git/my-library' }\nuuid = \"1.0\"\n\n[patch.crates-io]\nuuid = { git = 'https://github.com/uuid-rs/uuid.git' }\n```\n\nRemember that `[patch]` is applicable *transitively* but can only be defined at\nthe *top level* so we consumers of `my-library` have to repeat the `[patch]` section\nif necessary. Here, though, the new `uuid` crate applies to *both* our dependency on\n`uuid` and the `my-library -> uuid` dependency. The `uuid` crate will be resolved to\none version for this entire crate graph, 1.0.1, and it'll be pulled from the git\nrepository.\n\n### Overriding repository URL\n\nIn case the dependency you want to override isn't loaded from `crates.io`,\nyou'll have to change a bit how you use `[patch]`. For example, if the\ndependency is a git dependency, you can override it to a local path with:\n\n```toml\n[patch.\"https://github.com/your/repository\"]\nmy-library = { path = \"../my-library/path\" }\n```\n\nAnd that's it!\n\n## Prepublishing a breaking change\n\nLet's take a look at working with a new major version of a crate, typically\naccompanied with breaking changes. Sticking with our previous crates, this\nmeans that we're going to be creating version 2.0.0 of the `uuid` crate. After\nwe've submitted all changes upstream we can update our manifest for\n`my-library` to look like:\n\n```toml\n[dependencies]\nuuid = \"2.0\"\n\n[patch.crates-io]\nuuid = { git = \"https://github.com/uuid-rs/uuid.git\", branch = \"2.0.0\" }\n```\n\nAnd that's it! Like with the previous example the 2.0.0 version doesn't actually\nexist on crates.io but we can still put it in through a git dependency through\nthe usage of the `[patch]` section. As a thought exercise let's take another\nlook at the `my-binary` manifest from above again as well:\n\n```toml\n[package]\nname = \"my-binary\"\nversion = \"0.1.0\"\n\n[dependencies]\nmy-library = { git = 'https://example.com/git/my-library' }\nuuid = \"1.0\"\n\n[patch.crates-io]\nuuid = { git = 'https://github.com/uuid-rs/uuid.git', branch = '2.0.0' }\n```\n\nNote that this will actually resolve to two versions of the `uuid` crate. The\n`my-binary` crate will continue to use the 1.x.y series of the `uuid` crate but\nthe `my-library` crate will use the `2.0.0` version of `uuid`. This will allow you\nto gradually roll out breaking changes to a crate through a dependency graph\nwithout being forced to update everything all at once.\n\n## Using `[patch]` with multiple versions\n\nYou can patch in multiple versions of the same crate with the `package` key\nused to rename dependencies. For example let's say that the `serde` crate has\na bugfix that we'd like to use to its `1.*` series but we'd also like to\nprototype using a `2.0.0` version of serde we have in our git repository. To\nconfigure this we'd do:\n\n```toml\n[patch.crates-io]\nserde = { git = 'https://github.com/serde-rs/serde.git' }\nserde2 = { git = 'https://github.com/example/serde.git', package = 'serde', branch = 'v2' }\n```\n\nThe first `serde = ...` directive indicates that serde `1.*` should be used\nfrom the git repository (pulling in the bugfix we need) and the second `serde2\n= ...` directive indicates that the `serde` package should also be pulled from\nthe `v2` branch of `https://github.com/example/serde`. We're assuming here\nthat `Cargo.toml` on that branch mentions version `2.0.0`.\n\nNote that when using the `package` key the `serde2` identifier here is actually\nignored. We simply need a unique name which doesn't conflict with other patched\ncrates.\n\n## The `[patch]` section\n\nThe `[patch]` section of `Cargo.toml` can be used to override dependencies\nwith other copies. The syntax is similar to the\n[`[dependencies]`][dependencies] section:\n\n```toml\n[patch.crates-io]\nfoo = { git = 'https://github.com/example/foo.git' }\nbar = { path = 'my/local/bar' }\n\n[dependencies.baz]\ngit = 'https://github.com/example/baz.git'\n\n[patch.'https://github.com/example/baz']\nbaz = { git = 'https://github.com/example/patched-baz.git', branch = 'my-branch' }\n```\n\n> **Note**: The `[patch]` table can also be specified as a [configuration\n> option](config.md), such as in a `.cargo/config.toml` file or a CLI option\n> like `--config 'patch.crates-io.rand.path=\"rand\"'`. This can be useful for\n> local-only changes that you don't want to commit, or temporarily testing a\n> patch.\n\nThe `[patch]` table is made of dependency-like sub-tables. Each key after\n`[patch]` is a URL of the source that is being patched, or the name of a\nregistry. The name `crates-io` may be used to override the default registry\n[crates.io]. The first `[patch]` in the example above demonstrates overriding\n[crates.io], and the second `[patch]` demonstrates overriding a git source.\n\nEach entry in these tables is a normal dependency specification, the same as\nfound in the `[dependencies]` section of the manifest. The dependencies listed\nin the `[patch]` section are resolved and used to patch the source at the\nURL specified. The above manifest snippet patches the `crates-io` source (e.g.\ncrates.io itself) with the `foo` crate and `bar` crate. It also\npatches the `https://github.com/example/baz` source with a `my-branch` that\ncomes from elsewhere.\n\nSources can be patched with versions of crates that do not exist, and they can\nalso be patched with versions of crates that already exist. If a source is\npatched with a crate version that already exists in the source, then the\nsource's original crate is replaced.\n\nCargo only looks at the patch settings in the `Cargo.toml` manifest at the\nroot of the workspace. Patch settings defined in dependencies will be\nignored.\n\n## The `[replace]` section\n\n> **Note**: `[replace]` is deprecated. You should use the\n> [`[patch]`](#the-patch-section) table instead.\n\nThis section of Cargo.toml can be used to override dependencies with other\ncopies. The syntax is similar to the `[dependencies]` section:\n\n```toml\n[replace]\n\"foo:0.1.0\" = { git = 'https://github.com/example/foo.git' }\n\"bar:1.0.2\" = { path = 'my/local/bar' }\n```\n\nEach key in the `[replace]` table is a [package ID\nspecification](pkgid-spec.md), which allows arbitrarily choosing a node in the\ndependency graph to override (the 3-part version number is required). The\nvalue of each key is the same as the `[dependencies]` syntax for specifying\ndependencies, except that you can't specify features. Note that when a crate\nis overridden the copy it's overridden with must have both the same name and\nversion, but it can come from a different source (e.g., git or a local path).\n\nCargo only looks at the replace settings in the `Cargo.toml` manifest at the\nroot of the workspace. Replace settings defined in dependencies will be\nignored.\n\n## `paths` overrides\n\nSometimes you're only temporarily working on a crate and you don't want to have\nto modify `Cargo.toml` like with the `[patch]` section above. For this use\ncase Cargo offers a much more limited version of overrides called **path\noverrides**.\n\nPath overrides are specified through [`.cargo/config.toml`](config.md) instead of\n`Cargo.toml`. Inside of `.cargo/config.toml` you'll specify a key called `paths`:\n\n```toml\npaths = [\"/path/to/uuid\"]\n```\n\nThis array should be filled with directories that contain a `Cargo.toml`. In\nthis instance, we’re just adding `uuid`, so it will be the only one that’s\noverridden. This path can be either absolute or relative to the directory that\ncontains the `.cargo` folder.\n\nPath overrides are more restricted than the `[patch]` section, however, in\nthat they cannot change the structure of the dependency graph. When a\npath replacement is used then the previous set of dependencies\nmust all match exactly to the new `Cargo.toml` specification. For example this\nmeans that path overrides cannot be used to test out adding a dependency to a\ncrate. Instead, `[patch]` must be used in that situation. As a result, usage of a\npath override is typically isolated to quick bug fixes rather than larger\nchanges.\n\n> **Note**: using a local configuration to override paths will only work for\n> crates that have been published to [crates.io]. You cannot use this feature\n> to tell Cargo how to find local unpublished crates.\n\n\n[crates.io]: https://crates.io/\n[multiple locations]: specifying-dependencies.md#multiple-locations\n[dependencies]: specifying-dependencies.md\n"
  },
  {
    "path": "src/doc/src/reference/pkgid-spec.md",
    "content": "# Package ID Specifications\n\n## Package ID specifications\n\nSubcommands of Cargo frequently need to refer to a particular package within a\ndependency graph for various operations like updating, cleaning, building, etc.\nTo solve this problem, Cargo supports *Package ID Specifications*. A specification\nis a string which is used to uniquely refer to one package within a graph of\npackages.\n\nThe specification may be fully qualified, such as\n`registry+https://github.com/rust-lang/crates.io-index#regex@1.4.3` or it may be\nabbreviated, such as `regex`. The abbreviated form may be used as long as it\nuniquely identifies a single package in the dependency graph. If there is\nambiguity, additional qualifiers can be added to make it unique. For example,\nif there are two versions of the `regex` package in the graph, then it can be\nqualified with a version to make it unique, such as `regex@1.4.3`.\n\nPackage ID specifications output by cargo, for example in [cargo metadata](../commands/cargo-metadata.md) output, are fully qualified.\n\n### Specification grammar\n\nThe formal grammar for a Package Id Specification is:\n\n```notrust\nspec := pkgname |\n        [ kind \"+\" ] proto \"://\" hostname-and-path [ \"?\" query] [ \"#\" ( pkgname | semver ) ]\nquery = ( \"branch\" | \"tag\" | \"rev\" ) \"=\" ref\npkgname := name [ (\"@\" | \":\" ) semver ]\nsemver := digits [ \".\" digits [ \".\" digits [ \"-\" prerelease ] [ \"+\" build ]]]\n\nkind = \"registry\" | \"git\" | \"path\"\nproto := \"http\" | \"git\" | \"file\" | ...\n```\n\nHere, brackets indicate that the contents are optional.\n\nThe URL form can be used for git dependencies, or to differentiate packages\nthat come from different sources such as different registries.\n\n### Example specifications\n\nThe following are references to the `regex` package on `crates.io`:\n\n| Spec                                                              | Name    | Version |\n|:------------------------------------------------------------------|:-------:|:-------:|\n| `regex`                                                           | `regex` | `*`     |\n| `regex@1.4`                                                       | `regex` | `1.4.*` |\n| `regex@1.4.3`                                                     | `regex` | `1.4.3` |\n| `https://github.com/rust-lang/crates.io-index#regex`              | `regex` | `*`     |\n| `https://github.com/rust-lang/crates.io-index#regex@1.4.3`        | `regex` | `1.4.3` |\n| `registry+https://github.com/rust-lang/crates.io-index#regex@1.4.3` | `regex` | `1.4.3` |\n\nThe following are some examples of specs for several different git dependencies:\n\n| Spec                                                       | Name             | Version  |\n|:-----------------------------------------------------------|:----------------:|:--------:|\n| `https://github.com/rust-lang/cargo#0.52.0`                | `cargo`          | `0.52.0` |\n| `https://github.com/rust-lang/cargo#cargo-platform@0.1.2`  | <nobr>`cargo-platform`</nobr> | `0.1.2`  |\n| `ssh://git@github.com/rust-lang/regex.git#regex@1.4.3`     | `regex`          | `1.4.3`  |\n| `git+ssh://git@github.com/rust-lang/regex.git#regex@1.4.3` | `regex`          | `1.4.3`  |\n| `git+ssh://git@github.com/rust-lang/regex.git?branch=dev#regex@1.4.3` | `regex`          | `1.4.3`  |\n\nLocal packages on the filesystem can use `file://` URLs to reference them:\n\n| Spec                                        | Name  | Version |\n|:--------------------------------------------|:-----:|:-------:|\n| `file:///path/to/my/project/foo`            | `foo` | `*`     |\n| `file:///path/to/my/project/foo#1.1.8`      | `foo` | `1.1.8` |\n| `path+file:///path/to/my/project/foo#1.1.8` | `foo` | `1.1.8` |\n\n### Brevity of specifications\n\nThe goal of this is to enable both succinct and exhaustive syntaxes for\nreferring to packages in a dependency graph. Ambiguous references may refer to\none or more packages. Most commands generate an error if more than one package\ncould be referred to with the same specification.\n"
  },
  {
    "path": "src/doc/src/reference/profiles.md",
    "content": "# Profiles\n\nProfiles provide a way to alter the compiler settings, influencing things like\noptimizations and debugging symbols.\n\nCargo has 4 built-in profiles: `dev`, `release`, `test`, and `bench`. The\nprofile is automatically chosen based on which command is being run if a\nprofile is not specified on the command-line. In addition to the built-in\nprofiles, custom user-defined profiles can also be specified.\n\nProfile settings can be changed in [`Cargo.toml`](manifest.md) with the\n`[profile]` table. Within each named profile, individual settings can be changed\nwith key/value pairs like this:\n\n```toml\n[profile.dev]\nopt-level = 1               # Use slightly better optimizations.\noverflow-checks = false     # Disable integer overflow checks.\n```\n\nCargo only looks at the profile settings in the `Cargo.toml` manifest at the\nroot of the workspace. Profile settings defined in dependencies will be\nignored.\n\nAdditionally, profiles can be overridden from a [config] definition.\nSpecifying a profile in a config file or environment variable will override\nthe settings from `Cargo.toml`.\n\n[config]: config.md\n\n## Profile settings\n\nThe following is a list of settings that can be controlled in a profile.\n\n### opt-level\n\nThe `opt-level` setting controls the [`-C opt-level` flag] which controls the level\nof optimization. Higher optimization levels may produce faster runtime code at\nthe expense of longer compiler times. Higher levels may also change and\nrearrange the compiled code which may make it harder to use with a debugger.\n\nThe valid options are:\n\n* `0`: no optimizations\n* `1`: basic optimizations\n* `2`: some optimizations\n* `3`: all optimizations\n* `\"s\"`: optimize for binary size\n* `\"z\"`: optimize for binary size, but also turn off loop vectorization.\n\nIt is recommended to experiment with different levels to find the right\nbalance for your project. There may be surprising results, such as level `3`\nbeing slower than `2`, or the `\"s\"` and `\"z\"` levels not being necessarily\nsmaller. You may also want to reevaluate your settings over time as newer\nversions of `rustc` change optimization behavior.\n\nSee also [Profile Guided Optimization] for more advanced optimization\ntechniques.\n\n[`-C opt-level` flag]: ../../rustc/codegen-options/index.html#opt-level\n[Profile Guided Optimization]: ../../rustc/profile-guided-optimization.html\n\n### debug\n\nThe `debug` setting controls the [`-C debuginfo` flag] which controls the\namount of debug information included in the compiled binary.\n\nThe valid options are:\n\n* `0`, `false`, or `\"none\"`: no debug info at all, default for [`release`](#release)\n* `\"line-directives-only\"`: line info directives only. For the nvptx* targets this enables [profiling]. For other use cases, `line-tables-only` is the better, more compatible choice.\n* `\"line-tables-only\"`: line tables only. Generates the minimal amount of debug info for backtraces with filename/line number info, but not anything else, i.e. no variable or function parameter info.\n* `1` or `\"limited\"`: debug info without type or variable-level information. Generates more detailed module-level info than `line-tables-only`.\n* `2`, `true`, or `\"full\"`: full debug info, default for [`dev`](#dev)\n\nFor more information on what each option does see `rustc`'s docs on [debuginfo].\n\nYou may wish to also configure the [`split-debuginfo`](#split-debuginfo) option\ndepending on your needs as well.\n\n> **MSRV:** 1.71 is required for `none`, `limited`, `full`, `line-directives-only`, and `line-tables-only`\n\n[`-C debuginfo` flag]: ../../rustc/codegen-options/index.html#debuginfo\n[debuginfo]: ../../rustc/codegen-options/index.html#debuginfo\n[profiling]: https://reviews.llvm.org/D46061\n\n### split-debuginfo\n\nThe `split-debuginfo` setting controls the [`-C split-debuginfo` flag] which\ncontrols whether debug information, if generated, is either placed in the\nexecutable itself or adjacent to it.\n\nThis option is a string and acceptable values are the same as those the\n[compiler accepts][`-C split-debuginfo` flag]. The default value for this option\nis `unpacked` on macOS for profiles that have debug information otherwise\nenabled. Otherwise the default for this option is [documented with rustc][`-C\nsplit-debuginfo` flag] and is platform-specific. Some options are only\navailable on the [nightly channel]. The Cargo default may change in the future\nonce more testing has been performed, and support for DWARF is stabilized.\n\nBe aware that Cargo and rustc have different defaults for this option. This\noption exists to allow Cargo to experiment on different combinations of flags\nthus providing better debugging and developer experience.\n\n[nightly channel]: ../../book/appendix-07-nightly-rust.html\n[`-C split-debuginfo` flag]: ../../rustc/codegen-options/index.html#split-debuginfo\n\n### strip\n\nThe `strip` option controls the [`-C strip` flag], which directs rustc to\nstrip either symbols or debuginfo from a binary. This can be enabled like so:\n\n```toml\n[package]\n# ...\n\n[profile.release]\nstrip = \"debuginfo\"\n```\n\nPossible string values of `strip` are `\"none\"`, `\"debuginfo\"`, and `\"symbols\"`.\nThe default is `\"none\"`.\n\nYou can also configure this option with the boolean values `true` or `false`.\n`strip = true` is equivalent to `strip = \"symbols\"`. `strip = false` is\nequivalent to `strip = \"none\"` and disables `strip` completely.\n\n[`-C strip` flag]: ../../rustc/codegen-options/index.html#strip\n\n### debug-assertions\n\nThe `debug-assertions` setting controls the [`-C debug-assertions` flag] which\nturns `cfg(debug_assertions)` [conditional compilation] on or off. Debug\nassertions are intended to include runtime validation which is only available\nin debug/development builds. These may be things that are too expensive or\notherwise undesirable in a release build. Debug assertions enables the\n[`debug_assert!` macro] in the standard library.\n\nThe valid options are:\n\n* `true`: enabled\n* `false`: disabled\n\n[`-C debug-assertions` flag]: ../../rustc/codegen-options/index.html#debug-assertions\n[conditional compilation]: ../../reference/conditional-compilation.md#debug_assertions\n[`debug_assert!` macro]: ../../std/macro.debug_assert.html\n\n### overflow-checks\n\nThe `overflow-checks` setting controls the [`-C overflow-checks` flag] which\ncontrols the behavior of [runtime integer overflow]. When overflow-checks are\nenabled, a panic will occur on overflow.\n\nThe valid options are:\n\n* `true`: enabled\n* `false`: disabled\n\n[`-C overflow-checks` flag]: ../../rustc/codegen-options/index.html#overflow-checks\n[runtime integer overflow]: ../../reference/expressions/operator-expr.md#overflow\n\n### lto\n\nThe `lto` setting controls `rustc`'s [`-C lto`], [`-C linker-plugin-lto`], and\n[`-C embed-bitcode`] options, which control LLVM's [link time optimizations].\nLTO can produce better optimized code, using whole-program analysis, at the cost\nof longer linking time.\n\nThe valid options are:\n\n* `true` or `\"fat\"`: Performs \"fat\" LTO which attempts to perform\n  optimizations across all crates within the dependency graph.\n* `\"thin\"`: Performs [\"thin\" LTO]. This is similar to \"fat\", but takes\n  substantially less time to run while still achieving performance gains\n  similar to \"fat\".\n* `false`: Performs \"thin local LTO\" which performs \"thin\" LTO on the local\n  crate only across its [codegen units](#codegen-units). No LTO is performed\n  if codegen units is 1 or [opt-level](#opt-level) is 0.\n* `\"off\"`: Disables LTO.\n\nSee the [linker-plugin-lto chapter] if you are interested in cross-language LTO.\nThis is not yet supported natively in Cargo, but can be performed via\n`RUSTFLAGS`.\n\n[`-C lto`]: ../../rustc/codegen-options/index.html#lto\n[link time optimizations]: https://llvm.org/docs/LinkTimeOptimization.html\n[`-C linker-plugin-lto`]: ../../rustc/codegen-options/index.html#linker-plugin-lto\n[`-C embed-bitcode`]: ../../rustc/codegen-options/index.html#embed-bitcode\n[linker-plugin-lto chapter]: ../../rustc/linker-plugin-lto.html\n[\"thin\" LTO]: http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html\n\n### panic\n\nThe `panic` setting controls the [`-C panic` flag] which controls which panic\nstrategy to use.\n\nThe valid options are:\n\n* `\"unwind\"`: Unwind the stack upon panic.\n* `\"abort\"`: Terminate the process upon panic.\n\nWhen set to `\"unwind\"`, the actual value depends on the default of the target\nplatform. For example, the NVPTX platform does not support unwinding, so it\nalways uses `\"abort\"`.\n\nTests, benchmarks, build scripts, and proc macros ignore the `panic` setting.\nThe `rustc` test harness currently requires `unwind` behavior. See the\n[`panic-abort-tests`] unstable flag which enables `abort` behavior.\n\nAdditionally, when using the `abort` strategy and building a test, all of the\ndependencies will also be forced to build with the `unwind` strategy.\n\n[`-C panic` flag]: ../../rustc/codegen-options/index.html#panic\n[`panic-abort-tests`]: unstable.md#panic-abort-tests\n\n### incremental\n\nThe `incremental` setting controls the [`-C incremental` flag] which controls\nwhether or not incremental compilation is enabled. Incremental compilation\ncauses `rustc` to save additional information to disk which will be reused\nwhen recompiling the crate, improving re-compile times. The additional\ninformation is stored in the `target` directory.\n\nThe valid options are:\n\n* `true`: enabled\n* `false`: disabled\n\nIncremental compilation is only used for workspace members and \"path\"\ndependencies.\n\nThe incremental value can be overridden globally with the `CARGO_INCREMENTAL`\n[environment variable] or the [`build.incremental`] config variable.\n\n[`-C incremental` flag]: ../../rustc/codegen-options/index.html#incremental\n[environment variable]: environment-variables.md\n[`build.incremental`]: config.md#buildincremental\n\n### codegen-units\n\nThe `codegen-units` setting controls the [`-C codegen-units` flag] which\ncontrols how many \"code generation units\" a crate will be split into. More\ncode generation units allows more of a crate to be processed in parallel\npossibly reducing compile time, but may produce slower code.\n\nThis option takes an integer greater than 0.\n\nThe default is 256 for [incremental](#incremental) builds, and 16 for\nnon-incremental builds.\n\n[`-C codegen-units` flag]: ../../rustc/codegen-options/index.html#codegen-units\n\n### rpath\n\nThe `rpath` setting controls the [`-C rpath` flag] which controls\nwhether or not [`rpath`] is enabled.\n\n[`-C rpath` flag]: ../../rustc/codegen-options/index.html#rpath\n[`rpath`]: https://en.wikipedia.org/wiki/Rpath\n\n## Default profiles\n\n### dev\n\nThe `dev` profile is used for normal development and debugging. It is the\ndefault for build commands like [`cargo build`], and is used for `cargo install --debug`.\n\nThe default settings for the `dev` profile are:\n\n```toml\n[profile.dev]\nopt-level = 0\ndebug = true\nsplit-debuginfo = '...'  # Platform-specific.\nstrip = \"none\"\ndebug-assertions = true\noverflow-checks = true\nlto = false\npanic = 'unwind'\nincremental = true\ncodegen-units = 256\nrpath = false\n```\n\n### release\n\nThe `release` profile is intended for optimized artifacts used for releases\nand in production. This profile is used when the `--release` flag is used, and\nis the default for [`cargo install`].\n\nThe default settings for the `release` profile are:\n\n```toml\n[profile.release]\nopt-level = 3\ndebug = false\nsplit-debuginfo = '...'  # Platform-specific.\nstrip = \"none\"\ndebug-assertions = false\noverflow-checks = false\nlto = false\npanic = 'unwind'\nincremental = false\ncodegen-units = 16\nrpath = false\n```\n\n### test\n\nThe `test` profile is the default profile used by [`cargo test`].\nThe `test` profile inherits the settings from the [`dev`](#dev) profile.\n\n### bench\n\nThe `bench` profile is the default profile used by [`cargo bench`].\nThe `bench` profile inherits the settings from the [`release`](#release) profile.\n\n### Build Dependencies\n\nTo compile quickly, all profiles, by default, do not optimize build\ndependencies (build scripts, proc macros, and their dependencies), and avoid\ncomputing debug info when a build dependency is not used as a runtime\ndependency. The default settings for build overrides are:\n\n```toml\n[profile.dev.build-override]\nopt-level = 0\ncodegen-units = 256\ndebug = false # when possible\n\n[profile.release.build-override]\nopt-level = 0\ncodegen-units = 256\n```\n\nHowever, if errors occur while running build dependencies, turning full debug\ninfo on will improve backtraces and debuggability when needed:\n\n```toml\ndebug = true\n```\n\nBuild dependencies otherwise inherit settings from the active profile in use, as\ndescribed in [Profile selection](#profile-selection).\n\n## Custom profiles\n\nIn addition to the built-in profiles, additional custom profiles can be\ndefined. These may be useful for setting up multiple workflows and build\nmodes. When defining a custom profile, you must specify the `inherits` key to\nspecify which profile the custom profile inherits settings from when the\nsetting is not specified.\n\nFor example, let's say you want to compare a normal release build with a\nrelease build with [LTO](#lto) optimizations, you can specify something like\nthe following in `Cargo.toml`:\n\n```toml\n[profile.release-lto]\ninherits = \"release\"\nlto = true\n```\n\nThe `--profile` flag can then be used to choose this custom profile:\n\n```console\ncargo build --profile release-lto\n```\n\nThe output for each profile will be placed in a directory of the same name\nas the profile in the [`target` directory]. As in the example above, the\noutput would go into the `target/release-lto` directory.\n\n[`target` directory]: build-cache.md\n\n## Profile selection\n\nThe profile used depends on the command, the command-line flags like\n`--release` or `--profile`, and the package (in the case of\n[overrides](#overrides)). The default profile if none is specified is:\n\n| Command | Default Profile |\n|---------|-----------------|\n| [`cargo run`], [`cargo build`],<br>[`cargo check`], [`cargo rustc`] | [`dev` profile](#dev) |\n| [`cargo test`] | [`test` profile](#test)\n| [`cargo bench`] | [`bench` profile](#bench)\n| [`cargo install`] | [`release` profile](#release)\n\nYou can switch to a different profile using the `--profile=NAME` option which will used the given profile.\nThe `--release` flag is equivalent to `--profile=release`.\n\nThe selected profile applies to all Cargo targets, \nincluding [library](./cargo-targets.md#library),\n[binary](./cargo-targets.md#binaries), \n[example](./cargo-targets.md#examples), \n[test](./cargo-targets.md#tests), \nand [benchmark](./cargo-targets.md#benchmarks).\n\nThe profile for specific packages can be specified with\n[overrides](#overrides), described below.\n\n[`cargo bench`]: ../commands/cargo-bench.md\n[`cargo build`]: ../commands/cargo-build.md\n[`cargo check`]: ../commands/cargo-check.md\n[`cargo install`]: ../commands/cargo-install.md\n[`cargo run`]: ../commands/cargo-run.md\n[`cargo rustc`]: ../commands/cargo-rustc.md\n[`cargo test`]: ../commands/cargo-test.md\n\n## Overrides\n\nProfile settings can be overridden for specific packages and build-time\ncrates. To override the settings for a specific package, use the `package`\ntable to change the settings for the named package:\n\n```toml\n# The `foo` package will use the -Copt-level=3 flag.\n[profile.dev.package.foo]\nopt-level = 3\n```\n\nThe package name is actually a [Package ID Spec](pkgid-spec.md), so you can\ntarget individual versions of a package with syntax such as\n`[profile.dev.package.\"foo:2.1.0\"]`.\n\nTo override the settings for all dependencies (but not any workspace member),\nuse the `\"*\"` package name:\n\n```toml\n# Set the default for dependencies.\n[profile.dev.package.\"*\"]\nopt-level = 2\n```\n\nTo override the settings for build scripts, proc macros, and their\ndependencies, use the `build-override` table:\n\n```toml\n# Set the settings for build scripts and proc-macros.\n[profile.dev.build-override]\nopt-level = 3\n```\n\n> Note: When a dependency is both a normal dependency and a build dependency,\n> Cargo will try to only build it once when `--target` is not specified. When\n> using `build-override`, the dependency may need to be built twice, once as a\n> normal dependency and once with the overridden build settings. This may\n> increase initial build times.\n\nThe precedence for which value is used is done in the following order (first\nmatch wins):\n\n1. `[profile.dev.package.name]` --- A named package.\n2. `[profile.dev.package.\"*\"]` --- For any non-workspace member.\n3. `[profile.dev.build-override]` --- Only for build scripts, proc macros, and\n   their dependencies.\n4. `[profile.dev]` --- Settings in `Cargo.toml`.\n5. Default values built-in to Cargo.\n\nOverrides cannot specify the `panic`, `lto`, or `rpath` settings.\n\n### Overrides and generics\n\nThe location where generic code is instantiated will influence the\noptimization settings used for that generic code. This can cause subtle\ninteractions when using profile overrides to change the optimization level of\na specific crate. If you attempt to raise the optimization level of a\ndependency which defines generic functions, those generic functions may not be\noptimized when used in your local crate. This is because the code may be\ngenerated in the crate where it is instantiated, and thus may use the\noptimization settings of that crate.\n\nFor example, [nalgebra] is a library which defines vectors and matrices making\nheavy use of generic parameters. If your local code defines concrete nalgebra\ntypes like `Vector4<f64>` and uses their methods, the corresponding nalgebra\ncode will be instantiated and built within your crate. Thus, if you attempt to\nincrease the optimization level of `nalgebra` using a profile override, it may\nnot result in faster performance.\n\nFurther complicating the issue, `rustc` has some optimizations where it will\nattempt to share monomorphized generics between crates. If the opt-level is 2\nor 3, then a crate will not use monomorphized generics from other crates, nor\nwill it export locally defined monomorphized items to be shared with other\ncrates. When experimenting with optimizing dependencies for development,\nconsider trying opt-level 1, which will apply some optimizations while still\nallowing monomorphized items to be shared.\n\n[nalgebra]: https://crates.io/crates/nalgebra\n"
  },
  {
    "path": "src/doc/src/reference/publishing.md",
    "content": "# Publishing on crates.io\n\nOnce you've got a library that you'd like to share with the world, it's time to\npublish it on [crates.io]! Publishing a crate is when a specific\nversion is uploaded to be hosted on [crates.io].\n\nTake care when publishing a crate, because a publish is **permanent**. The\nversion can never be overwritten, and the code cannot be deleted. There is no\nlimit to the number of versions which can be published, however.\n\n## Before your first publish\n\nFirst things first, you’ll need an account on [crates.io] to acquire\nan API token. To do so, [visit the home page][crates.io] and log in via a GitHub\naccount (required for now). You will also need to provide and verify your email\naddress on the [Account Settings](https://crates.io/settings/profile) page. Once\nthat is done [create an API token](https://crates.io/settings/tokens), make sure\nyou copy it. Once you leave the page you will not be able to see it again.\n\nThen run the [`cargo login`] command.\n\n```console\n$ cargo login\n```\n\nThen at the prompt put in the token specified.\n```console\nplease paste the API Token found on https://crates.io/me below\nabcdefghijklmnopqrstuvwxyz012345\n```\n\nThis command will inform Cargo of your API token and store it locally in your\n`~/.cargo/credentials.toml`. Note that this token is a **secret** and should not be\nshared with anyone else. If it leaks for any reason, you should revoke it\nimmediately.\n\n> **Note**: The [`cargo logout`] command can be used to remove the token from\n> `credentials.toml`. This can be useful if you no longer need it stored on\n> the local machine.\n\n## Before publishing a new crate\n\nKeep in mind that crate names on [crates.io] are allocated on a first-come-first-serve\nbasis. Once a crate name is taken, it cannot be used for another crate.\n\nCheck out the [metadata you can specify](manifest.md) in `Cargo.toml` to\nensure your crate can be discovered more easily! Before publishing, make sure\nyou have filled out the following fields:\n\n- [`license` or `license-file`]\n- [`description`]\n- [`homepage`]\n- [`repository`]\n- [`readme`]\n\nIt would also be a good idea to include some [`keywords`] and [`categories`],\nthough they are not required.\n\nIf you are publishing a library, you may also want to consult the [Rust API\nGuidelines].\n\n### Packaging a crate\n\nThe next step is to package up your crate and upload it to [crates.io]. For\nthis we’ll use the [`cargo publish`] subcommand. This command performs the following\nsteps:\n\n1. Perform some verification checks on your package.\n2. Compress your source code into a `.crate` file.\n3. Extract the `.crate` file into a temporary directory and verify that it\n   compiles.\n4. Upload the `.crate` file to [crates.io].\n5. The registry will perform some additional checks on the uploaded package\n   before adding it.\n\nIt is recommended that you first run `cargo publish --dry-run` (or [`cargo\npackage`] which is equivalent) to ensure there aren't any warnings or errors\nbefore publishing. This will perform the first three steps listed above.\n\n```console\n$ cargo publish --dry-run\n```\n\nYou can inspect the generated `.crate` file in the `target/package` directory.\n[crates.io] currently has a 10MB size limit on the `.crate` file. You may want\nto check the size of the `.crate` file to ensure you didn't accidentally\npackage up large assets that are not required to build your package, such as\ntest data, website documentation, or code generation. You can check which\nfiles are included with the following command:\n\n```console\n$ cargo package --list\n```\n\nCargo will automatically ignore files ignored by your version control system\nwhen packaging, but if you want to specify an extra set of files to ignore you\ncan use the [`exclude` key](manifest.md#the-exclude-and-include-fields) in the\nmanifest:\n\n```toml\n[package]\n# ...\nexclude = [\n    \"public/assets/*\",\n    \"videos/*\",\n]\n```\n\nIf you’d rather explicitly list the files to include, Cargo also supports an\n[`include` key](manifest.md#the-exclude-and-include-fields), which if set, overrides the `exclude` key:\n\n```toml\n[package]\n# ...\ninclude = [\n    \"**/*.rs\",\n]\n```\n\n## Uploading the crate\n\nWhen you are ready to publish, use the [`cargo publish`] command\nto upload to [crates.io]:\n\n```console\n$ cargo publish\n```\n\nAnd that’s it, you’ve now published your first crate!\n\n## Publishing a new version of an existing crate\n\nIn order to release a new version, change [the `version` value](manifest.md#the-version-field) specified in your `Cargo.toml` manifest.\nKeep in mind [the SemVer rules](semver.md) which provide guidelines on what is a compatible change.\nThen run [`cargo publish`] as described above to upload the new version.\n\n> **Recommendation:** Consider the full release process and automate what you can.\n>\n> Each version should include:\n> - A changelog entry, preferably [manually curated](https://keepachangelog.com/en/1.0.0/) though a generated one is better than nothing\n> - A [git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) pointing to the published commit\n>\n> Examples of third-party tools that are representative of different workflows include (in alphabetical order):\n> - [cargo-release](https://crates.io/crates/cargo-release)\n> - [cargo-smart-release](https://crates.io/crates/cargo-smart-release)\n> - [release-plz](https://crates.io/crates/release-plz)\n>\n> For more, see [crates.io](https://crates.io/search?q=cargo%20release).\n\n## Managing a crates.io-based crate\n\nManagement of crates is primarily done through the command line `cargo` tool\nrather than the [crates.io] web interface. For this, there are a few subcommands\nto manage a crate.\n\n### `cargo yank`\n\nOccasions may arise where you publish a version of a crate that actually ends up\nbeing broken for one reason or another (syntax error, forgot to include a file,\netc.). For situations such as this, Cargo supports a “yank” of a version of a\ncrate.\n\n```console\n$ cargo yank --version 1.0.1\n$ cargo yank --version 1.0.1 --undo\n```\n\nA yank **does not** delete any code. This feature is not intended for deleting\naccidentally uploaded secrets, for example. If that happens, you must reset\nthose secrets immediately.\n\nThe semantics of a yanked version are that no new dependencies can be created\nagainst that version, but all existing dependencies continue to work. One of the\nmajor goals of [crates.io] is to act as a permanent archive of crates that does\nnot change over time, and allowing deletion of a version would go against this\ngoal. Essentially a yank means that all packages with a `Cargo.lock` will not\nbreak, while any future `Cargo.lock` files generated will not list the yanked\nversion.\n\n### `cargo owner`\n\nA crate is often developed by more than one person, or the primary maintainer\nmay change over time! The owner of a crate is the only person allowed to publish\nnew versions of the crate, but an owner may designate additional owners.\n\n```console\n$ cargo owner --add github-handle\n$ cargo owner --remove github-handle\n$ cargo owner --add github:rust-lang:owners\n$ cargo owner --remove github:rust-lang:owners\n```\n\nThe owner IDs given to these commands must be GitHub user names or GitHub teams.\n\nIf a user name is given to `--add`, that user is invited as a “named” owner, with\nfull rights to the crate. In addition to being able to publish or yank versions\nof the crate, they have the ability to add or remove owners, *including* the\nowner that made *them* an owner. Needless to say, you shouldn’t make people you\ndon’t fully trust into a named owner. In order to become a named owner, a user\nmust have logged into [crates.io] previously.\n\nIf a team name is given to `--add`, that team is invited as a “team” owner, with\nrestricted right to the crate. While they have permission to publish or yank\nversions of the crate, they *do not* have the ability to add or remove owners.\nIn addition to being more convenient for managing groups of owners, teams are\njust a bit more secure against owners becoming malicious.\n\nThe syntax for teams is currently `github:org:team` (see examples above).\nIn order to invite a team as an owner one must be a member of that team. No\nsuch restriction applies to removing a team as an owner.\n\n## GitHub permissions\n\nTeam membership is not something GitHub provides simple public access to, and it\nis likely for you to encounter the following message when working with them:\n\n> It looks like you don’t have permission to query a necessary property from\nGitHub to complete this request. You may need to re-authenticate on [crates.io]\nto grant permission to read GitHub org memberships.\n\nThis is basically a catch-all for “you tried to query a team, and one of the\nfive levels of membership access control denied this”. That is not an\nexaggeration. GitHub’s support for team access control is Enterprise Grade.\n\nThe most likely cause of this is simply that you last logged in before this\nfeature was added. We originally requested *no* permissions from GitHub when\nauthenticating users, because we didn’t actually ever use the user’s token for\nanything other than logging them in. However to query team membership on your\nbehalf, we now require [the `read:org` scope][oauth-scopes].\n\nYou are free to deny us this scope, and everything that worked before teams\nwere introduced will keep working. However you will never be able to add a team\nas an owner, or publish a crate as a team owner. If you ever attempt to do this,\nyou will get the error above. You may also see this error if you ever try to\npublish a crate that you don’t own at all, but otherwise happens to have a team.\n\nIf you ever change your mind, or just aren’t sure if [crates.io] has sufficient\npermission, you can always go to <https://crates.io/> and re-authenticate,\nwhich will prompt you for permission if [crates.io] doesn’t have all the scopes\nit would like to.\n\nAn additional barrier to querying GitHub is that the organization may be\nactively denying third party access. To check this, you can go to:\n\n```text\nhttps://github.com/organizations/:org/settings/oauth_application_policy\n```\n\nwhere `:org` is the name of the organization (e.g., `rust-lang`). You may see\nsomething like:\n\n![Organization Access Control](../images/org-level-acl.png)\n\nWhere you may choose to explicitly remove [crates.io] from your organization’s\nblacklist, or simply press the “Remove Restrictions” button to allow all third\nparty applications to access this data.\n\nAlternatively, when [crates.io] requested the `read:org` scope, you could have\nexplicitly whitelisted [crates.io] querying the org in question by pressing\nthe “Grant Access” button next to its name:\n\n![Authentication Access Control](../images/auth-level-acl.png)\n\n### Troubleshooting GitHub team access errors\n\nWhen trying to add a GitHub team as crate owner, you may see an error like:\n\n```text\nerror: failed to invite owners to crate <crate_name>: api errors (status 200 OK): could not find the github team org/repo\n```\nIn that case, you should go to [the GitHub Application settings page] and\ncheck if crates.io is listed in the `Authorized OAuth Apps` tab.\nIf it isn't, you should go to <https://crates.io/> and authorize it.\nThen go back to the Application Settings page on GitHub, click on the\ncrates.io application in the list, and make sure you or your organization is\nlisted in the \"Organization access\" list with a green check mark. If there's\na button labeled `Grant` or `Request`, you should grant the access or\nrequest the org owner to do so.\n\n[Rust API Guidelines]: https://rust-lang.github.io/api-guidelines/\n[`cargo login`]: ../commands/cargo-login.md\n[`cargo logout`]: ../commands/cargo-logout.md\n[`cargo package`]: ../commands/cargo-package.md\n[`cargo publish`]: ../commands/cargo-publish.md\n[`categories`]: manifest.md#the-categories-field\n[`description`]: manifest.md#the-description-field\n[`documentation`]: manifest.md#the-documentation-field\n[`homepage`]: manifest.md#the-homepage-field\n[`keywords`]: manifest.md#the-keywords-field\n[`license` or `license-file`]: manifest.md#the-license-and-license-file-fields\n[`readme`]: manifest.md#the-readme-field\n[`repository`]: manifest.md#the-repository-field\n[crates.io]: https://crates.io/\n[oauth-scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/\n[the GitHub Application settings page]: https://github.com/settings/applications\n"
  },
  {
    "path": "src/doc/src/reference/registries.md",
    "content": "# Registries\n\nCargo installs crates and fetches dependencies from a \"registry\". The default\nregistry is [crates.io]. A registry contains an \"index\" which contains a\nsearchable list of available crates. A registry may also provide a web API to\nsupport publishing new crates directly from Cargo.\n\n> Note: If you are interested in mirroring or vendoring an existing registry,\n> take a look at [Source Replacement].\n\nIf you are implementing a registry server, see [Running a Registry] for more\ndetails about the protocol between Cargo and a registry.\n\nIf you're using a registry that requires authentication, see [Registry Authentication].\nIf you are implementing a credential provider, see [Credential Provider Protocol]\nfor details.\n\n## Using an Alternate Registry\n\nTo use a registry other than [crates.io], the name and index URL of the\nregistry must be added to a [`.cargo/config.toml` file][config]. The `registries`\ntable has a key for each registry, for example:\n\n```toml\n[registries]\nmy-registry = { index = \"https://my-intranet:8080/git/index\" }\n```\n\nThe `index` key should be a URL to a git repository with the registry's index or a\nCargo sparse registry URL with the `sparse+` prefix.\n\nA crate can then depend on a crate from another registry by specifying the\n`registry` key and a value of the registry's name in that dependency's entry\nin `Cargo.toml`:\n\n```toml\n# Sample Cargo.toml\n[package]\nname = \"my-project\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\nother-crate = { version = \"1.0\", registry = \"my-registry\" }\n```\n\nAs with most config values, the index may be specified with an environment\nvariable instead of a config file. For example, setting the following\nenvironment variable will accomplish the same thing as defining a config file:\n\n```ignore\nCARGO_REGISTRIES_MY_REGISTRY_INDEX=https://my-intranet:8080/git/index\n```\n\n> Note: [crates.io] does not accept packages that depend on crates from other\n> registries.\n\n## Publishing to an Alternate Registry\n\nIf the registry supports web API access, then packages can be published\ndirectly to the registry from Cargo. Several of Cargo's commands such as\n[`cargo publish`] take a `--registry` command-line flag to indicate which\nregistry to use. For example, to publish the package in the current directory:\n\n1. `cargo login --registry=my-registry`\n\n    This only needs to be done once. You must enter the secret API token\n    retrieved from the registry's website. Alternatively the token may be\n    passed directly to the `publish` command with the `--token` command-line\n    flag or an environment variable with the name of the registry such as\n    `CARGO_REGISTRIES_MY_REGISTRY_TOKEN`.\n\n2. `cargo publish --registry=my-registry`\n\nInstead of always passing the `--registry` command-line option, the default\nregistry may be set in [`.cargo/config.toml`][config] with the `registry.default`\nkey. For example:\n\n```toml\n[registry]\ndefault = \"my-registry\"\n```\n\nSetting the `package.publish` key in the `Cargo.toml` manifest restricts which\nregistries the package is allowed to be published to. This is useful to\nprevent accidentally publishing a closed-source package to [crates.io]. The\nvalue may be a list of registry names, for example:\n\n```toml\n[package]\n# ...\npublish = [\"my-registry\"]\n```\n\nThe `publish` value may also be `false` to restrict all publishing, which is\nthe same as an empty list.\n\nThe authentication information saved by [`cargo login`] is stored in the\n`credentials.toml` file in the Cargo home directory (default `$HOME/.cargo`). It\nhas a separate table for each registry, for example:\n\n```toml\n[registries.my-registry]\ntoken = \"854DvwSlUwEHtIo3kWy6x7UCPKHfzCmy\"\n```\n\n## Registry Protocols\nCargo supports two remote registry protocols: `git` and `sparse`. If the registry\nindex URL starts with `sparse+`, Cargo uses the sparse protocol. Otherwise\nCargo uses the `git` protocol.\n\nThe `git` protocol stores index metadata in a git repository and requires Cargo to clone\nthe entire repo.\n\nThe `sparse` protocol fetches individual metadata files using plain HTTP requests.\nSince Cargo only downloads the metadata for relevant crates, the `sparse` protocol can\nsave significant time and bandwidth.\n\nThe [crates.io] registry supports both protocols. The protocol for crates.io is\ncontrolled via the [`registries.crates-io.protocol`] config key.\n\n[Source Replacement]: source-replacement.md\n[Running a Registry]: running-a-registry.md\n[Credential Provider Protocol]: credential-provider-protocol.md\n[Registry Authentication]: registry-authentication.md\n[`cargo publish`]: ../commands/cargo-publish.md\n[`cargo package`]: ../commands/cargo-package.md\n[`cargo login`]: ../commands/cargo-login.md\n[config]: config.md\n[crates.io]: https://crates.io/\n[`registries.crates-io.protocol`]: config.md#registriescrates-ioprotocol\n"
  },
  {
    "path": "src/doc/src/reference/registry-authentication.md",
    "content": "# Registry Authentication\nCargo authenticates to registries with credential providers. These\ncredential providers are external executables or built-in providers that Cargo\nuses to store and retrieve credentials.\n\nUsing alternative registries with authentication *requires* a credential provider to be configured\nto avoid unknowingly storing unencrypted credentials on disk. For historical reasons, public\n(non-authenticated) registries do not require credential provider configuration, and the `cargo:token`\nprovider is used if no providers are configured.\n\nCargo also includes platform-specific providers that use the operating system to securely store\ntokens. The `cargo:token` provider is also included which stores credentials in unencrypted plain\ntext in the [credentials](config.md#credentials) file.\n\n## Recommended configuration\nIt's recommended to configure a global credential provider list in `$CARGO_HOME/config.toml`\nwhich defaults to:\n* Windows: `%USERPROFILE%\\.cargo\\config.toml`\n* Unix: `~/.cargo/config.toml`\n\nThis recommended configuration uses the operating system provider, with a fallback to `cargo:token`\nto look in Cargo's [credentials](config.md#credentials) file or environment variables:\n```toml\n# ~/.cargo/config.toml\n[registry]\nglobal-credential-providers = [\"cargo:token\", \"cargo:libsecret\", \"cargo:macos-keychain\", \"cargo:wincred\"]\n```\n*Note that later entries have higher precedence.\nSee [`registry.global-credential-providers`](config.md#registryglobal-credential-providers)\nfor more details.*\n\nSome private registries may also recommend a registry-specific credential-provider. Check your\nregistry's documentation to see if this is the case.\n\n## Built-in providers\nCargo includes several built-in credential providers. The available built-in providers\nmay change in future Cargo releases (though there are currently no plans to do so).\n\n### `cargo:token`\nUses Cargo's [credentials](config.md#credentials) file to store tokens unencrypted in plain text.\nWhen retrieving tokens, checks the `CARGO_REGISTRIES_<NAME>_TOKEN` environment variable.\nIf this credential provider is not listed, then the `*_TOKEN` environment variables will not work.\n\n### `cargo:wincred`\nUses the Windows Credential Manager to store tokens.\n\nThe credentials are stored as `cargo-registry:<index-url>` in the Credential Manager\nunder \"Windows Credentials\".\n\n### `cargo:macos-keychain`\nUses the macOS Keychain to store tokens.\n\nThe Keychain Access app can be used to view stored tokens.\n\n### `cargo:libsecret`\nUses [libsecret](https://wiki.gnome.org/Projects/Libsecret) to store tokens.\n\nAny password manager with libsecret support can be used to view stored tokens.\nThe following are a few examples (non-exhaustive):\n\n- [GNOME Keyring](https://wiki.gnome.org/Projects/GnomeKeyring)\n- [KDE Wallet Manager](https://apps.kde.org/kwalletmanager5/) (since KDE Frameworks 5.97.0)\n- [KeePassXC](https://keepassxc.org/) (since 2.5.0)\n\n### `cargo:token-from-stdout <command> <args>`\nLaunch a subprocess that returns a token on stdout. Newlines will be trimmed.\n* The process inherits the user's stdin and stderr.\n* It should exit 0 on success, and nonzero on error.\n* [`cargo login`] and [`cargo logout`] are not supported and return an error if used.\n\nThe following environment variables will be provided to the executed command:\n\n* `CARGO` --- Path to the `cargo` binary executing the command.\n* `CARGO_REGISTRY_INDEX_URL` --- The URL of the registry index.\n* `CARGO_REGISTRY_NAME_OPT` --- Optional name of the registry. Should not be used as a lookup key.\n\nArguments will be passed on to the subcommand.\n\n[`cargo login`]: ../commands/cargo-login.md\n[`cargo logout`]: ../commands/cargo-logout.md\n\n## Credential plugins\nFor credential provider plugins that follow Cargo's [credential provider protocol](credential-provider-protocol.md),\nthe configuration value should be a string with the path to the executable (or the executable name if on the `PATH`).\n\nFor example, to install [cargo-credential-1password](https://crates.io/crates/cargo-credential-1password)\nfrom crates.io do the following:\n\nInstall the provider with `cargo install cargo-credential-1password`\n\nIn the config, add to (or create) `registry.global-credential-providers`:\n```toml\n[registry]\nglobal-credential-providers = [\"cargo:token\", \"cargo-credential-1password --account my.1password.com\"]\n```\n\nThe values in `global-credential-providers` are split on spaces into path and command-line arguments. To\ndefine a global credential provider where the path or arguments contain spaces, use\nthe [`[credential-alias]` table](config.md#credential-alias).\n"
  },
  {
    "path": "src/doc/src/reference/registry-index.md",
    "content": "# Index Format\n\nThe following defines the format of the index. New features are occasionally\nadded, which are only understood starting with the version of Cargo that\nintroduced them. Older versions of Cargo may not be able to use packages that\nmake use of new features. However, the format for older packages should not\nchange, so older versions of Cargo should be able to use them.\n\n## Index Configuration\nThe root of the index contains a file named `config.json` which contains JSON\ninformation used by Cargo for accessing the registry. This is an example of\nwhat the [crates.io] config file looks like:\n\n```javascript\n{\n    \"dl\": \"https://crates.io/api/v1/crates\",\n    \"api\": \"https://crates.io\"\n}\n```\n\nThe keys are:\n- `dl`: This is the URL for downloading crates listed in the index. The value\n  may have the following markers which will be replaced with their\n  corresponding value:\n\n  - `{crate}`: The name of crate.\n  - `{version}`: The crate version.\n  - `{prefix}`: A directory prefix computed from the crate name. For example,\n    a crate named `cargo` has a prefix of `ca/rg`. See below for details.\n  - `{lowerprefix}`: Lowercase variant of `{prefix}`.\n  - `{sha256-checksum}`: The crate's sha256 checksum.\n\n  If none of the markers are present, then the value\n  `/{crate}/{version}/download` is appended to the end.\n- `api`: This is the base URL for the web API. This key is optional, but if it\n  is not specified, commands such as [`cargo publish`] will not work. The web\n  API is described below.\n- `auth-required`: indicates whether this is a private registry that requires\n  all operations to be authenticated including API requests, crate downloads\n  and sparse index updates.\n\n\n## Download Endpoint\nThe download endpoint should send the `.crate` file for the requested package.\nCargo supports https, http, and file URLs, HTTP redirects, HTTP1 and HTTP2.\nThe exact specifics of TLS support depend on the platform that Cargo is\nrunning on, the version of Cargo, and how it was compiled.\n\nIf `auth-required: true` is set in `config.json`, the `Authorization` header\nwill be included with http(s) download requests.\n\n## Index files\nThe rest of the index repository contains one file for each package, where the\nfilename is the name of the package in lowercase. Each version of the package\nhas a separate line in the file. The files are organized in a tier of\ndirectories:\n\n- Packages with 1 character names are placed in a directory named `1`.\n- Packages with 2 character names are placed in a directory named `2`.\n- Packages with 3 character names are placed in the directory\n  `3/{first-character}` where `{first-character}` is the first character of\n  the package name.\n- All other packages are stored in directories named\n  `{first-two}/{second-two}` where the top directory is the first two\n  characters of the package name, and the next subdirectory is the third and\n  fourth characters of the package name. For example, `cargo` would be stored\n  in a file named `ca/rg/cargo`.\n\n> Note: Although the index filenames are in lowercase, the fields that contain\n> package names in `Cargo.toml` and the index JSON data are case-sensitive and\n> may contain upper and lower case characters.\n\nThe directory name above is calculated based on the package name converted to\nlowercase; it is represented by the marker `{lowerprefix}`.  When the original\npackage name is used without case conversion, the resulting directory name is\nrepresented by the marker `{prefix}`.  For example, the package `MyCrate` would\nhave a `{prefix}` of `My/Cr` and a `{lowerprefix}` of `my/cr`.  In general,\nusing `{prefix}` is recommended over `{lowerprefix}`, but there are pros and\ncons to each choice.  Using `{prefix}` on case-insensitive filesystems results\nin (harmless-but-inelegant) directory aliasing.  For example, `crate` and\n`CrateTwo` have `{prefix}` values of `cr/at` and `Cr/at`; these are distinct on\nUnix machines but alias to the same directory on Windows.  Using directories\nwith normalized case avoids aliasing, but on case-sensitive filesystems it's\nharder to support older versions of Cargo that lack `{prefix}`/`{lowerprefix}`.\nFor example, nginx rewrite rules can easily construct `{prefix}` but can't\nperform case-conversion to construct `{lowerprefix}`.\n\n## Name restrictions\n\nRegistries should consider enforcing limitations on package names added to\ntheir index. Cargo itself allows names with any [alphanumeric], `-`, or `_`\ncharacters. [crates.io] imposes its own limitations, including the following:\n\n- Only allows ASCII characters.\n- Only alphanumeric, `-`, and `_` characters.\n- First character must be alphabetic.\n- Case-insensitive collision detection.\n- Prevent differences of `-` vs `_`.\n- Under a specific length (max 64).\n- Rejects reserved names, such as Windows special filenames like \"nul\".\n\nRegistries should consider incorporating similar restrictions, and consider\nthe security implications, such as [IDN homograph\nattacks](https://en.wikipedia.org/wiki/IDN_homograph_attack) and other\nconcerns in [UTR36](https://www.unicode.org/reports/tr36/) and\n[UTS39](https://www.unicode.org/reports/tr39/).\n\n## Version uniqueness\n\nIndexes *must* ensure that each version only appears once for each package.\nThis includes ignoring SemVer build metadata.\nFor example, the index must *not* contain two entries with a version `1.0.7` and `1.0.7+extra`.\n\n## JSON schema\n\nEach line in a package file contains a JSON object that describes a published\nversion of the package. The following is a pretty-printed example with comments\nexplaining the format of the entry.\n\n```javascript\n{\n    // The name of the package.\n    // This must only contain alphanumeric, `-`, or `_` characters.\n    \"name\": \"foo\",\n    // The version of the package this row is describing.\n    // This must be a valid version number according to the Semantic\n    // Versioning 2.0.0 spec at https://semver.org/.\n    \"vers\": \"0.1.0\",\n    // Array of direct dependencies of the package.\n    \"deps\": [\n        {\n            // Name of the dependency.\n            // If the dependency is renamed from the original package name,\n            // this is the new name. The original package name is stored in\n            // the `package` field.\n            \"name\": \"rand\",\n            // The SemVer requirement for this dependency.\n            // This must be a valid version requirement defined at\n            // https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html.\n            \"req\": \"^0.6\",\n            // Array of features (as strings) enabled for this dependency.\n            // Since Cargo 1.84, defaults to `[]` if not specified.\n            \"features\": [\"i128_support\"],\n            // Boolean of whether or not this is an optional dependency.\n            // Since Cargo 1.84, defaults to `false` if not specified.\n            \"optional\": false,\n            // Boolean of whether or not default features are enabled.\n            // Since Cargo 1.84, defaults to `true` if not specified.\n            \"default_features\": true,\n            // The target platform for the dependency.\n            // If not specified or `null`, it is not a target dependency.\n            // Otherwise, a string such as \"cfg(windows)\".\n            \"target\": null,\n            // The dependency kind.\n            // \"dev\", \"build\", or \"normal\".\n            // If not specified or `null`, it defaults to \"normal\".\n            \"kind\": \"normal\",\n            // The URL of the index of the registry where this dependency is\n            // from as a string. If not specified or `null`, it is assumed the\n            // dependency is in the current registry.\n            \"registry\": null,\n            // If the dependency is renamed, this is a string of the actual\n            // package name. If not specified or `null`, this dependency is not\n            // renamed.\n            \"package\": null,\n        }\n    ],\n    // A SHA256 checksum of the `.crate` file.\n    \"cksum\": \"d867001db0e2b6e0496f9fac96930e2d42233ecd3ca0413e0753d4c7695d289c\",\n    // Set of features defined for the package.\n    // Each feature maps to an array of features or dependencies it enables.\n    // Since Cargo 1.84, defaults to `{}` if not specified.\n    \"features\": {\n        \"extras\": [\"rand/simd_support\"]\n    },\n    // Boolean of whether or not this version has been yanked.\n    \"yanked\": false,\n    // The `links` string value from the package's manifest, or null if not\n    // specified. This field is optional and defaults to null.\n    \"links\": null,\n    // An unsigned 32-bit integer value indicating the schema version of this\n    // entry.\n    //\n    // If this is not specified, it should be interpreted as the default of 1.\n    //\n    // Cargo (starting with version 1.51) will ignore versions it does not\n    // recognize. This provides a method to safely introduce changes to index\n    // entries and allow older versions of cargo to ignore newer entries it\n    // doesn't understand. Versions older than 1.51 ignore this field, and\n    // thus may misinterpret the meaning of the index entry.\n    //\n    // The current values are:\n    //\n    // * 1: The schema as documented here, not including newer additions.\n    //      This is honored in Rust version 1.51 and newer.\n    // * 2: The addition of the `features2` field.\n    //      This is honored in Rust version 1.60 and newer.\n    \"v\": 2,\n    // This optional field contains features with new, extended syntax.\n    // Specifically, namespaced features (`dep:`) and weak dependencies\n    // (`pkg?/feat`).\n    //\n    // This is separated from `features` because versions older than 1.19\n    // will fail to load due to not being able to parse the new syntax, even\n    // with a `Cargo.lock` file.\n    //\n    // Cargo will merge any values listed here with the \"features\" field.\n    //\n    // If this field is included, the \"v\" field should be set to at least 2.\n    //\n    // Registries are not required to use this field for extended feature\n    // syntax, they are allowed to include those in the \"features\" field.\n    // Using this is only necessary if the registry wants to support cargo\n    // versions older than 1.19, which in practice is only crates.io since\n    // those older versions do not support other registries.\n    \"features2\": {\n        \"serde\": [\"dep:serde\", \"chrono?/serde\"]\n    }\n    // The minimal supported Rust version (optional)\n    // This must be a valid version requirement without an operator (e.g. no `=`)\n    \"rust_version\": \"1.60\",\n    // The publish time of this package version (optional).\n    //\n    // The format is a subset of ISO8601:\n    // - `yyyy-mm-ddThh:mm:ssZ`\n    // - no fractional seconds\n    // - always `Z` for UTC timezone, no timezone offsets supported\n    // - fields are 0-padded\n    //\n    // Example: 2025-11-12T19:30:12Z\n    //\n    // This should be the original publish time and not changed on any status changes,\n    // like `yanked`.\n    \"pubtime\": \"2025-11-12T19:30:12Z\"\n}\n```\n\nThe JSON objects should not be modified after they are added except for the\n`yanked` field whose value may change at any time.\n\n> **Note**: The index JSON format has subtle differences from the JSON format of the [Publish API] and [`cargo metadata`].\n> If you are using one of those as a source to generate index entries, you are encouraged to carefully inspect the documentation differences between them.\n>\n> For the [Publish API], the differences are:\n>\n> * `deps`\n>     * `name` --- When the dependency is [renamed] in `Cargo.toml`, the publish API puts the original package name in the `name` field and the aliased name in the `explicit_name_in_toml` field.\n>       The index places the aliased name in the `name` field, and the original package name in the `package` field.\n>     * `req` --- The Publish API field is called `version_req`.\n> * `cksum` --- The publish API does not specify the checksum, it must be computed by the registry before adding to the index.\n> * `features` --- Some features may be placed in the `features2` field.\n>   Note: This is only a legacy requirement for [crates.io]; other registries should not need to bother with modifying the features map.\n>   The `v` field indicates the presence of the `features2` field.\n> * The publish API includes several other fields, such as `description` and `readme`, which don't appear in the index.\n>   These are intended to make it easier for a registry to obtain the metadata about the crate to display on a website without needing to extract and parse the `.crate` file.\n>   This additional information is typically added to a database on the registry server.\n> * Although `rust_version` is included here, [crates.io] will ignore this field\n>   and instead read it from the `Cargo.toml` contained in the `.crate` file.\n>\n> For [`cargo metadata`], the differences are:\n>\n> * `vers` --- The `cargo metadata` field is called `version`.\n> * `deps`\n>   * `name` --- When the dependency is [renamed] in `Cargo.toml`, `cargo metadata` puts the original package name in the `name` field and the aliased name in the `rename` field.\n>     The index places the aliased name in the `name` field, and the original package name in the `package` field.\n>   * `default_features` --- The `cargo metadata` field is called `uses_default_features`.\n>   * `registry` --- `cargo metadata` uses a value of `null` to indicate that the dependency comes from [crates.io].\n>     The index uses a value of `null` to indicate that the dependency comes from the same registry as the index.\n>     When creating an index entry, a registry other than [crates.io] should translate a value of `null` to be `https://github.com/rust-lang/crates.io-index` and translate a URL that matches the current index to be `null`.\n>   * `cargo metadata` includes some extra fields, such as `source` and `path`.\n> * The index includes additional fields such as `yanked`, `cksum`, and `v`.\n\n[renamed]: specifying-dependencies.md#renaming-dependencies-in-cargotoml\n[Publish API]: registry-web-api.md#publish\n[`cargo metadata`]: ../commands/cargo-metadata.md\n\n## Index Protocols\nCargo supports two remote registry protocols: `git` and `sparse`. The `git` protocol\nstores index files in a git repository and the `sparse` protocol fetches individual\nfiles over HTTP.\n\n### Git Protocol\nThe git protocol has no protocol prefix in the index url. For example the git index URL\nfor [crates.io] is `https://github.com/rust-lang/crates.io-index`.\n\nCargo caches the git repository on disk so that it can efficiently incrementally fetch\nupdates.\n\n### Sparse Protocol\nThe sparse protocol uses the `sparse+` protocol prefix in the registry URL. For example,\nthe sparse index URL for [crates.io] is `sparse+https://index.crates.io/`.\n\nThe sparse protocol downloads each index file using an individual HTTP request. Since\nthis results in a large number of small HTTP requests, performance is significantly\nimproved with a server that supports pipelining and HTTP/2.\n\n#### Sparse authentication\nCargo will attempt to fetch the `config.json` file before\nfetching any other files. If the server responds with an HTTP 401, then Cargo will assume\nthat the registry requires authentication and re-attempt the request for `config.json`\nwith the authentication token included.\n\nOn authentication failure (or a missing authentication token) the server may include a\n`www-authenticate` header with a `Cargo login_url=\"<URL>\"` challenge to indicate where the user\ncan go to get a token.\n\nRegistries that require authentication must set `auth-required: true` in `config.json`.\n\n#### Caching\nCargo caches the crate metadata files, and captures the `ETag` or `Last-Modified` \nHTTP header from the server for each entry. When refreshing crate metadata, Cargo\nsends the `If-None-Match` or `If-Modified-Since` header to allow the server to respond\nwith HTTP 304 \"Not Modified\" if the local cache is valid, saving time and bandwidth.\nIf both `ETag` and `Last-Modified` headers are present, Cargo uses the `ETag` only.\n\n#### Cache Invalidation\nIf a registry is using some kind of CDN or proxy which caches access to the index files,\nthen it is recommended that registries implement some form of cache invalidation when\nthe files are updated. If these caches are not updated, then users may not be able to\naccess new crates until the cache is cleared.\n\n#### Nonexistent Crates\nFor crates that do not exist, the registry should respond with a 404 \"Not Found\", 410 \"Gone\"\nor 451 \"Unavailable For Legal Reasons\" code.\n\n#### Sparse Limitations\nSince the URL of the registry is stored in the lockfile, it's not recommended to offer\na registry with both protocols. Discussion about a transition plan is ongoing in issue \n[#10964]. The [crates.io] registry is an exception, since Cargo internally substitutes\nthe equivalent git URL when the sparse protocol is used.\n\nIf a registry does offer both protocols, it's currently recommended to choose one protocol\nas the canonical protocol and use [source replacement] for the other protocol.\n\n\n[`cargo publish`]: ../commands/cargo-publish.md\n[alphanumeric]: ../../std/primitive.char.html#method.is_alphanumeric\n[crates.io]: https://crates.io/\n[source replacement]: ../reference/source-replacement.md\n[#10964]: https://github.com/rust-lang/cargo/issues/10964\n"
  },
  {
    "path": "src/doc/src/reference/registry-web-api.md",
    "content": "# Web API\n\nA registry may host a web API at the location defined in `config.json` to\nsupport any of the actions listed below.\n\nCargo includes the `Authorization` header for requests that require\nauthentication. The header value is the API token. The server should respond\nwith a 403 response code if the token is not valid. Users are expected to\nvisit the registry's website to obtain a token, and Cargo can store the token\nusing the [`cargo login`] command, or by passing the token on the\ncommand-line.\n\nResponses use a 2xx response code for success.\nErrors should use an appropriate response code, such as 404.\nFailure\nresponses should have a JSON object with the following structure:\n\n```javascript\n{\n    // Array of errors to display to the user.\n    \"errors\": [\n        {\n            // The error message as a string.\n            \"detail\": \"error message text\"\n        }\n    ]\n}\n```\n\nIf the response has this structure Cargo will display the detailed message to the user, even if the response code is 200.\nIf the response code indicates an error and the content does not have this structure, Cargo will display to the user a\n message intended to help debugging the server error. A server returning an `errors` object allows a registry to provide a more\ndetailed or user-centric error message.\n\nFor backwards compatibility, servers should ignore any unexpected query\nparameters or JSON fields. If a JSON field is missing, it should be assumed to\nbe null. The endpoints are versioned with the `v1` component of the path, and\nCargo is responsible for handling backwards compatibility fallbacks should any\nbe required in the future.\n\nCargo sets the following headers for all requests:\n\n- `Content-Type`: `application/json` (for requests with a body payload)\n- `Accept`: `application/json`\n- `User-Agent`: The Cargo version such as `cargo/1.32.0 (8610973aa\n  2019-01-02)`. This may be modified by the user in a configuration value.\n  Added in 1.29.\n\n## Publish\n\n- Endpoint: `/api/v1/crates/new`\n- Method: PUT\n- Authorization: Included\n\nThe publish endpoint is used to publish a new version of a crate. The server\nshould validate the crate, make it available for download, and add it to the\nindex.\n\nIt is not required for the index to be updated before the successful response is sent.\nAfter a successful response, Cargo will poll the index for a short period of time to identify that the new crate has been added.\nIf the crate does not appear in the index after a short period of time, then Cargo will display a warning letting the user know that the new crate is not yet available.\n\nThe body of the data sent by Cargo is:\n\n- 32-bit unsigned little-endian integer of the length of JSON data.\n- Metadata of the package as a JSON object.\n- 32-bit unsigned little-endian integer of the length of the `.crate` file.\n- The `.crate` file.\n\nThe following is a commented example of the JSON object. Some notes of some\nrestrictions imposed by [crates.io] are included only to illustrate some\nsuggestions on types of validation that may be done, and should not be\nconsidered as an exhaustive list of restrictions [crates.io] imposes.\n\n```javascript\n{\n    // The name of the package.\n    \"name\": \"foo\",\n    // The version of the package being published.\n    \"vers\": \"0.1.0\",\n    // Array of direct dependencies of the package.\n    \"deps\": [\n        {\n            // Name of the dependency.\n            // If the dependency is renamed from the original package name,\n            // this is the original name. The new package name is stored in\n            // the `explicit_name_in_toml` field.\n            \"name\": \"rand\",\n            // The semver requirement for this dependency.\n            \"version_req\": \"^0.6\",\n            // Array of features (as strings) enabled for this dependency.\n            \"features\": [\"i128_support\"],\n            // Boolean of whether or not this is an optional dependency.\n            \"optional\": false,\n            // Boolean of whether or not default features are enabled.\n            \"default_features\": true,\n            // The target platform for the dependency.\n            // null if not a target dependency.\n            // Otherwise, a string such as \"cfg(windows)\".\n            \"target\": null,\n            // The dependency kind.\n            // \"dev\", \"build\", or \"normal\".\n            \"kind\": \"normal\",\n            // The URL of the index of the registry where this dependency is\n            // from as a string. If not specified or null, it is assumed the\n            // dependency is in the current registry.\n            \"registry\": null,\n            // If the dependency is renamed, this is a string of the new\n            // package name. If not specified or null, this dependency is not\n            // renamed.\n            \"explicit_name_in_toml\": null,\n        }\n    ],\n    // Set of features defined for the package.\n    // Each feature maps to an array of features or dependencies it enables.\n    // Cargo does not impose limitations on feature names, but crates.io\n    // requires alphanumeric ASCII, `_` or `-` characters.\n    \"features\": {\n        \"extras\": [\"rand/simd_support\"]\n    },\n    // List of strings of the authors.\n    // May be empty.\n    \"authors\": [\"Alice <a@example.com>\"],\n    // Description field from the manifest.\n    // May be null. crates.io requires at least some content.\n    \"description\": null,\n    // String of the URL to the website for this package's documentation.\n    // May be null.\n    \"documentation\": null,\n    // String of the URL to the website for this package's home page.\n    // May be null.\n    \"homepage\": null,\n    // String of the content of the README file.\n    // May be null.\n    \"readme\": null,\n    // String of a relative path to a README file in the crate.\n    // May be null.\n    \"readme_file\": null,\n    // Array of strings of keywords for the package.\n    \"keywords\": [],\n    // Array of strings of categories for the package.\n    \"categories\": [],\n    // String of the license for the package.\n    // May be null. crates.io requires either `license` or `license_file` to be set.\n    \"license\": null,\n    // String of a relative path to a license file in the crate.\n    // May be null.\n    \"license_file\": null,\n    // String of the URL to the website for the source repository of this package.\n    // May be null.\n    \"repository\": null,\n    // Optional object of \"status\" badges. Each value is an object of\n    // arbitrary string to string mappings.\n    // crates.io has special interpretation of the format of the badges.\n    \"badges\": {\n        \"travis-ci\": {\n            \"branch\": \"master\",\n            \"repository\": \"rust-lang/cargo\"\n        }\n    },\n    // The `links` string value from the package's manifest, or null if not\n    // specified. This field is optional and defaults to null.\n    \"links\": null,\n    // The minimal supported Rust version (optional)\n    // This must be a valid version requirement without an operator (e.g. no `=`)\n    \"rust_version\": null\n}\n```\n\nA successful response includes the JSON object:\n\n```javascript\n{\n    // Optional object of warnings to display to the user.\n    \"warnings\": {\n        // Array of strings of categories that are invalid and ignored.\n        \"invalid_categories\": [],\n        // Array of strings of badge names that are invalid and ignored.\n        \"invalid_badges\": [],\n        // Array of strings of arbitrary warnings to display to the user.\n        \"other\": []\n    }\n}\n```\n\n## Yank\n\n- Endpoint: `/api/v1/crates/{crate_name}/{version}/yank`\n- Method: DELETE\n- Authorization: Included\n\nThe yank endpoint will set the `yank` field of the given version of a crate to\n`true` in the index.\n\nA successful response includes the JSON object:\n\n```javascript\n{\n    // Indicates the yank succeeded, always true.\n    \"ok\": true,\n}\n```\n\n## Unyank\n\n- Endpoint: `/api/v1/crates/{crate_name}/{version}/unyank`\n- Method: PUT\n- Authorization: Included\n\nThe unyank endpoint will set the `yank` field of the given version of a crate\nto `false` in the index.\n\nA successful response includes the JSON object:\n\n```javascript\n{\n    // Indicates the unyank succeeded, always true.\n    \"ok\": true,\n}\n```\n\n## Owners\n\nCargo does not have an inherent notion of users and owners, but it does\nprovide the `owner` command to assist managing who has authorization to\ncontrol a crate. It is up to the registry to decide exactly how users and\nowners are handled. See the [publishing documentation] for a description of\nhow [crates.io] handles owners via GitHub users and teams.\n\n### Owners: List\n\n- Endpoint: `/api/v1/crates/{crate_name}/owners`\n- Method: GET\n- Authorization: Included\n\nThe owners endpoint returns a list of owners of the crate.\n\nA successful response includes the JSON object:\n\n```javascript\n{\n    // Array of owners of the crate.\n    \"users\": [\n        {\n            // Unique unsigned 32-bit integer of the owner.\n            \"id\": 70,\n            // The unique username of the owner.\n            \"login\": \"github:rust-lang:core\",\n            // Name of the owner.\n            // This is optional and may be null.\n            \"name\": \"Core\",\n        }\n    ]\n}\n```\n\n### Owners: Add\n\n- Endpoint: `/api/v1/crates/{crate_name}/owners`\n- Method: PUT\n- Authorization: Included\n\nA PUT request will send a request to the registry to add a new owner to a\ncrate. It is up to the registry how to handle the request. For example,\n[crates.io] sends an invite to the user that they must accept before being\nadded.\n\nThe request should include the following JSON object:\n\n```javascript\n{\n    // Array of `login` strings of owners to add.\n    \"users\": [\"login_name\"]\n}\n```\n\nA successful response includes the JSON object:\n\n```javascript\n{\n    // Indicates the add succeeded, always true.\n    \"ok\": true,\n    // A string to be displayed to the user.\n    \"msg\": \"user ehuss has been invited to be an owner of crate cargo\"\n}\n```\n\n### Owners: Remove\n\n- Endpoint: `/api/v1/crates/{crate_name}/owners`\n- Method: DELETE\n- Authorization: Included\n\nA DELETE request will remove an owner from a crate. The request should include\nthe following JSON object:\n\n```javascript\n{\n    // Array of `login` strings of owners to remove.\n    \"users\": [\"login_name\"]\n}\n```\n\nA successful response includes the JSON object:\n\n```javascript\n{\n    // Indicates the remove succeeded, always true.\n    \"ok\": true\n    // A string to be displayed to the user. Currently ignored by cargo.\n    \"msg\": \"owners successfully removed\",\n}\n```\n\n## Search\n\n- Endpoint: `/api/v1/crates`\n- Method: GET\n- Query Parameters:\n    - `q`: The search query string.\n    - `per_page`: Number of results, default 10, max 100.\n\nThe search request will perform a search for crates, using criteria defined on\nthe server.\n\nA successful response includes the JSON object:\n\n```javascript\n{\n    // Array of results.\n    \"crates\": [\n        {\n            // Name of the crate.\n            \"name\": \"rand\",\n            // The highest version available.\n            \"max_version\": \"0.6.1\",\n            // Textual description of the crate.\n            \"description\": \"Random number generators and other randomness functionality.\\n\",\n        }\n    ],\n    \"meta\": {\n        // Total number of results available on the server.\n        \"total\": 119\n    }\n}\n```\n\n## Login\n\n- Endpoint: `/me`\n\nThe \"login\" endpoint is not an actual API request. It exists solely for the\n[`cargo login`] command to display a URL to instruct a user to visit in a web\nbrowser to log in and retrieve an API token.\n\n[`cargo login`]: ../commands/cargo-login.md\n[`cargo package`]: ../commands/cargo-package.md\n[`cargo publish`]: ../commands/cargo-publish.md\n[alphanumeric]: ../../std/primitive.char.html#method.is_alphanumeric\n[config]: config.md\n[crates.io]: https://crates.io/\n[publishing documentation]: publishing.md#cargo-owner\n"
  },
  {
    "path": "src/doc/src/reference/resolver.md",
    "content": "# Dependency Resolution\n\nOne of Cargo's primary tasks is to determine the versions of dependencies to\nuse based on the version requirements specified in each package. This process\nis called \"dependency resolution\" and is performed by the \"resolver\". The\nresult of the resolution is stored in the [`Cargo.lock` file] which \"locks\" the\ndependencies to specific versions, and keeps them fixed over time.\nThe [`cargo tree`] command can be used to visualize the result of the\nresolver.\n\n[`Cargo.lock` file]: ../guide/cargo-toml-vs-cargo-lock.md\n[dependency specifications]: specifying-dependencies.md\n[dependency specification]: specifying-dependencies.md\n[`cargo tree`]: ../commands/cargo-tree.md\n\n## Constraints and Heuristics\n\nIn many cases there is no single \"best\" dependency resolution.\nThe resolver operates under various constraints and heuristics to find a generally applicable resolution.\nTo understand how these interact, it is helpful to have a coarse understanding of how dependency resolution works.\n\nThis pseudo-code approximates what Cargo's resolver does:\n```rust\npub fn resolve(workspace: &[Package], policy: Policy) -> Option<ResolveGraph> {\n    let dep_queue = Queue::new(workspace);\n    let resolved = ResolveGraph::new();\n    resolve_next(dep_queue, resolved, policy)\n}\n\nfn resolve_next(dep_queue: Queue, resolved: ResolveGraph, policy: Policy) -> Option<ResolveGraph> {\n    let Some(dep_spec) = policy.pick_next_dep(&mut dep_queue) else {\n        // Done\n        return Some(resolved);\n    };\n\n    if let Some(resolved) = policy.try_unify_version(dep_spec, resolved.clone()) {\n        return Some(resolved);\n    }\n\n    let dep_versions = dep_spec.lookup_versions()?;\n    let mut dep_versions = policy.filter_versions(dep_spec, dep_versions);\n    while let Some(dep_version) = policy.pick_next_version(&mut dep_versions) {\n        if policy.needs_version_unification(&dep_version, &resolved) {\n            continue;\n        }\n\n        let mut dep_queue = dep_queue.clone();\n        dep_queue.enqueue(&dep_version.dependencies);\n        let mut resolved = resolved.clone();\n        resolved.register(dep_version);\n        if let Some(resolved) = resolve_next(dep_queue, resolved, policy) {\n            return Some(resolved);\n        }\n    }\n\n    // No valid solution found, backtrack and `pick_next_version`\n    None\n}\n```\n\nKey steps:\n- Walking dependencies (`pick_next_dep`):\n  The order dependencies are walked can affect\n  how related version requirements for the same dependency get resolved, see unifying versions,\n  and how much the resolver backtracks, affecting resolver performance,\n- Unifying versions (`try_unify_version`, `needs_version_unification`):\n  Cargo reuses versions where possible to reduce build times and allow types from common dependencies to be passed between APIs.\n  If multiple versions would have been unified if it wasn't for conflicts in their [dependency specifications], Cargo will backtrack, erroring if no solution is found, rather than selecting multiple versions.\n  A [dependency specification] or Cargo may decide that a version is undesirable,\n  preferring to backtrack or error rather than use it.\n- Preferring versions (`pick_next_version`):\n  Cargo may decide that it should prefer a specific version,\n  falling back to the next version when backtracking.\n\n### Version numbers\n\nGenerally, Cargo prefers the highest version currently available.\n\nFor example, if you had a package in the resolve graph with:\n```toml\n[dependencies]\nbitflags = \"*\"\n```\nIf at the time the `Cargo.lock` file is generated, the greatest version of\n`bitflags` is `1.2.1`, then the package will use `1.2.1`.\n\nFor an example of a possible exception, see [Rust version](#rust-version).\n\n### Version requirements\n\nPackage specify what versions they support, rejecting all others, through\n[version requirements].\n\nFor example, if you had a package in the resolve graph with:\n```toml\n[dependencies]\nbitflags = \"1.0\"  # meaning `>=1.0.0,<2.0.0`\n```\nIf at the time the `Cargo.lock` file is generated, the greatest version of\n`bitflags` is `1.2.1`, then the package will use `1.2.1` because it is the\ngreatest within the compatibility range. If `2.0.0` is published, it will\nstill use `1.2.1` because `2.0.0` is considered incompatible.\n\n[version requirements]: specifying-dependencies.md#version-requirement-syntax\n\n### SemVer compatibility\n\nCargo assumes packages follow [SemVer] and will unify dependency versions if they are\n[SemVer] compatible according to the [Caret version requirements].\nIf two compatible versions cannot be unified because of conflicting version requirements,\nCargo will error.\n\nSee the [SemVer Compatibility] chapter for guidance on what is considered a\n\"compatible\" change.\n\nExamples:\n\nThe following two packages will have their dependencies on `bitflags` unified because any version picked will be compatible with each other.\n```toml\n# Package A\n[dependencies]\nbitflags = \"1.0\"  # meaning `>=1.0.0,<2.0.0`\n\n# Package B\n[dependencies]\nbitflags = \"1.1\"  # meaning `>=1.1.0,<2.0.0`\n```\n\nThe following packages will error because the version requirements conflict, selecting two distinct compatible versions.\n```toml\n# Package A\n[dependencies]\nlog = \"=0.4.11\"\n\n# Package B\n[dependencies]\nlog = \"=0.4.8\"\n```\n\nThe following two packages will not have their dependencies on `rand` unified because only incompatible versions are available for each.\nInstead, two different versions (e.g. 0.6.5 and 0.7.3) will be resolved and built.\nThis can lead to potential problems, see the [Version-incompatibility hazards] section for more details.\n```toml\n# Package A\n[dependencies]\nrand = \"0.7\"  # meaning `>=0.7.0,<0.8.0`\n\n# Package B\n[dependencies]\nrand = \"0.6\"  # meaning `>=0.6.0,<0.7.0`\n```\n\nGenerally, the following two packages will not have their dependencies unified because incompatible versions are available that satisfy the version requirements:\nInstead, two different versions (e.g. 0.6.5 and 0.7.3) will be resolved and built.\nThe application of other constraints or heuristics may cause these to be unified,\npicking one version (e.g. 0.6.5).\n```toml\n# Package A\n[dependencies]\nrand = \">=0.6,<0.8.0\"\n\n# Package B\n[dependencies]\nrand = \"0.6\"  # meaning `>=0.6.0,<0.7.0`\n```\n\n[SemVer]: https://semver.org/\n[SemVer Compatibility]: semver.md\n[Caret version requirements]: specifying-dependencies.md#default-requirements\n[Version-incompatibility hazards]: #version-incompatibility-hazards\n\n#### Version-incompatibility hazards\n\nWhen multiple versions of a crate appear in the resolve graph, this can cause\nproblems when types from those crates are exposed by the crates using them.\nThis is because the types and items are considered different by the Rust\ncompiler, even if they have the same name. Libraries should take care when\npublishing a SemVer-incompatible version (for example, publishing `2.0.0`\nafter `1.0.0` has been in use), particularly for libraries that are widely\nused.\n\nThe \"[semver trick]\" is a workaround for this problem of publishing a breaking\nchange while retaining compatibility with older versions. The linked page goes\ninto detail about what the problem is and how to address it. In short, when a\nlibrary wants to publish a SemVer-breaking release, publish the new release,\nand also publish a point release of the previous version that reexports the\ntypes from the newer version.\n\nThese incompatibilities usually manifest as a compile-time error, but\nsometimes they will only appear as a runtime misbehavior. For example, let's\nsay there is a common library named `foo` that ends up appearing with both\nversion `1.0.0` and `2.0.0` in the resolve graph. If [`downcast_ref`] is used\non an object created by a library using version `1.0.0`, and the code calling\n`downcast_ref` is downcasting to a type from version `2.0.0`, the downcast\nwill fail at runtime.\n\nIt is important to make sure that if you have multiple versions of a library\nthat you are properly using them, especially if it is ever possible for the\ntypes from different versions to be used together. The [`cargo tree\n-d`][`cargo tree`] command can be used to identify duplicate versions and\nwhere they come from. Similarly, it is important to consider the impact on the\necosystem if you publish a SemVer-incompatible version of a popular library.\n\n[semver trick]: https://github.com/dtolnay/semver-trick\n[`downcast_ref`]: ../../std/any/trait.Any.html#method.downcast_ref\n\n### Lock file\n\nCargo gives the highest priority to versions contained in the [`Cargo.lock` file], when used.\nThis is intended to balance reproducible builds with adjusting to changes in the manifest.\n\nFor example, if you had a package in the resolve graph with:\n```toml\n[dependencies]\nbitflags = \"*\"\n```\nIf at the time your `Cargo.lock` file is generated, the greatest version of\n`bitflags` is `1.2.1`, then the package will use `1.2.1` and recorded in the `Cargo.lock` file.\n\nBy the time Cargo next runs, `bitflags` `1.3.5` is out.\nWhen resolving dependencies,\n`1.2.1` will still be used because it is present in your `Cargo.lock` file.\n\nThe package is then edited to:\n```toml\n[dependencies]\nbitflags = \"1.3.0\"\n```\n`bitflags` `1.2.1` does not match this version requirement and so that entry in your `Cargo.lock` file is ignored and version `1.3.5` will now be used and recorded in your `Cargo.lock` file.\n\n### Rust version\n\nTo support developing software with a minimum supported [Rust version],\nthe resolver can take into account a dependency version's compatibility with your Rust version.\nThis is controlled by the config field [`resolver.incompatible-rust-versions`].\n\nWith the `fallback` setting, the resolver will prefer packages with a Rust version that is\nless than or equal to your own Rust version.\nFor example, you are using Rust 1.85 to develop the following package:\n```toml\n[package]\nname = \"my-cli\"\nrust-version = \"1.62\"\n\n[dependencies]\nclap = \"4.0\"  # resolves to 4.0.32\n```\nThe resolver would pick version 4.0.32 because it has a Rust version of 1.60.0.\n- 4.0.0 is not picked because it is a [lower version number](#version-numbers) despite it also having a Rust version of 1.60.0.\n- 4.5.20 is not picked because it is incompatible with `my-cli`'s Rust version of 1.62 despite having a much [higher version](#version-numbers) and it has a Rust version of 1.74.0 which is compatible with your 1.85 toolchain.\n\nIf a version requirement does not include a Rust version compatible dependency version,\nthe resolver won't error but will instead pick a version, even if its potentially suboptimal.\nFor example, you change the dependency on `clap`:\n```toml\n[package]\nname = \"my-cli\"\nrust-version = \"1.62\"\n\n[dependencies]\nclap = \"4.2\"  # resolves to 4.5.20\n```\nNo version of `clap` matches that [version requirement](#version-requirements)\nthat is compatible with Rust version 1.62.\nThe resolver will then pick an incompatible version, like 4.5.20 despite it having a Rust version of 1.74.\n\nWhen the resolver selects a dependency version of a package,\nit does not know all the workspace members that will eventually have a transitive dependency on that version\nand so it cannot take into account only the Rust versions relevant for that dependency.\nThe resolver has heuristics to find a \"good enough\" solution when workspace members have different Rust versions.\nThis applies even for packages in a workspace without a Rust version.\n\nWhen a workspace has members with different Rust versions,\nthe resolver may pick a lower dependency version than necessary.\nFor example, you have the following workspace members:\n```toml\n[package]\nname = \"a\"\nrust-version = \"1.62\"\n\n[package]\nname = \"b\"\n\n[dependencies]\nclap = \"4.2\"  # resolves to 4.5.20\n```\nThough package `b` does not have a Rust version and could use a higher version like 4.5.20,\n4.0.32 will be selected because of package `a`'s Rust version of 1.62.\n\nOr the resolver may pick too high of a version.\nFor example, you have the following workspace members:\n```toml\n[package]\nname = \"a\"\nrust-version = \"1.62\"\n\n[dependencies]\nclap = \"4.2\"  # resolves to 4.5.20\n\n[package]\nname = \"b\"\n\n[dependencies]\nclap = \"4.5\"  # resolves to 4.5.20\n```\nThough each package has a version requirement for `clap` that would meet its own Rust version,\nbecause of [version unification](#version-numbers),\nthe resolver will need to pick one version that works in both cases and that would be a version like 4.5.20.\n\n[Rust version]: rust-version.md\n[`resolver.incompatible-rust-versions`]: config.md#resolverincompatible-rust-versions\n\n### Features\n\nFor the purpose of generating `Cargo.lock`, the resolver builds the dependency\ngraph as-if all [features] of all [workspace] members are enabled. This\nensures that any optional dependencies are available and properly resolved\nwith the rest of the graph when features are added or removed with the\n[`--features` command-line flag](features.md#command-line-feature-options).\nThe resolver runs a second time to determine the actual features used when\n*compiling* a crate, based on the features selected on the command-line.\n\nDependencies are resolved with the union of all features enabled on them. For\nexample, if one package depends on the [`im`] package with the [`serde`\ndependency] enabled and another package depends on it with the [`rayon`\ndependency] enabled, then `im` will be built with both features enabled, and\nthe `serde` and `rayon` crates will be included in the resolve graph. If no\npackages depend on `im` with those features, then those optional dependencies\nwill be ignored, and they will not affect resolution.\n\nWhen building multiple packages in a workspace (such as with `--workspace` or\nmultiple `-p` flags), the features of the dependencies of all of those\npackages are unified. If you have a circumstance where you want to avoid that\nunification for different workspace members, you will need to build them via\nseparate `cargo` invocations.\n\nThe resolver will skip over versions of packages that are missing required\nfeatures. For example, if a package depends on version `^1` of [`regex`] with\nthe [`perf` feature], then the oldest version it can select is `1.3.0`,\nbecause versions prior to that did not contain the `perf` feature. Similarly,\nif a feature is removed from a new release, then packages that require that\nfeature will be stuck on the older releases that contain that feature. It is\ndiscouraged to remove features in a SemVer-compatible release. Beware that\noptional dependencies also define an implicit feature, so removing an optional\ndependency or making it non-optional can cause problems, see [removing an\noptional dependency].\n\n[`im`]: https://crates.io/crates/im\n[`perf` feature]: https://github.com/rust-lang/regex/blob/1.3.0/Cargo.toml#L56\n[`rayon` dependency]: https://github.com/bodil/im-rs/blob/v15.0.0/Cargo.toml#L47\n[`regex`]: https://crates.io/crates/regex\n[`serde` dependency]: https://github.com/bodil/im-rs/blob/v15.0.0/Cargo.toml#L46\n[features]: features.md\n[removing an optional dependency]: semver.md#cargo-remove-opt-dep\n[workspace]: workspaces.md\n\n#### Feature resolver version 2\n\nWhen `resolver = \"2\"` is specified in `Cargo.toml` (see [resolver\nversions](#resolver-versions) below), a different feature resolver is used\nwhich uses a different algorithm for unifying features. The version `\"1\"`\nresolver will unify features for a package no matter where it is specified.\nThe version `\"2\"` resolver will avoid unifying features in the following\nsituations:\n\n* Features for target-specific dependencies are not enabled if the target is\n  not currently being built. For example:\n\n  ```toml\n  [dependencies.common]\n  version = \"1.0\"\n  features = [\"f1\"]\n\n  [target.'cfg(windows)'.dependencies.common]\n  version = \"1.0\"\n  features = [\"f2\"]\n  ```\n\n  When building this example for a non-Windows platform, the `f2` feature will\n  *not* be enabled.\n\n* Features enabled on [build-dependencies] or proc-macros will not be unified\n  when those same dependencies are used as a normal dependency. For example:\n\n  ```toml\n  [dependencies]\n  log = \"0.4\"\n\n  [build-dependencies]\n  log = {version = \"0.4\", features=['std']}\n  ```\n\n  When building the build script, the `log` crate will be built with the `std`\n  feature. When building the library of your package, it will not enable the\n  feature.\n\n* Features enabled on [dev-dependencies] will not be unified when those same\n  dependencies are used as a normal dependency, unless those dev-dependencies\n  are currently being built. For example:\n\n  ```toml\n  [dependencies]\n  serde = {version = \"1.0\", default-features = false}\n\n  [dev-dependencies]\n  serde = {version = \"1.0\", features = [\"std\"]}\n  ```\n\n  In this example, the library will normally link against `serde` without the\n  `std` feature. However, when built as a test or example, it will include the\n  `std` feature. For example, `cargo test` or `cargo build --all-targets` will\n  unify these features. Note that dev-dependencies in dependencies are always\n  ignored, this is only relevant for the top-level package or workspace\n  members.\n\n[build-dependencies]: specifying-dependencies.md#build-dependencies\n[dev-dependencies]: specifying-dependencies.md#development-dependencies\n[resolver-field]: features.md#resolver-versions\n\n### `links`\n\nThe [`links` field] is used to ensure only one copy of a native library is\nlinked into a binary. The resolver will attempt to find a graph where there is\nonly one instance of each `links` name. If it is unable to find a graph that\nsatisfies that constraint, it will return an error.\n\nFor example, it is an error if one package depends on [`libgit2-sys`] version\n`0.11` and another depends on `0.12`, because Cargo is unable to unify those,\nbut they both link to the `git2` native library. Due to this requirement, it\nis encouraged to be very careful when making SemVer-incompatible releases with\nthe `links` field if your library is in common use.\n\n[`links` field]: manifest.md#the-links-field\n[`libgit2-sys`]: https://crates.io/crates/libgit2-sys\n\n### Yanked versions\n\n[Yanked releases][yank] are those that are marked that they should not be\nused. When the resolver is building the graph, it will ignore all yanked\nreleases unless they already exist in the `Cargo.lock` file or are explicitly\nrequested by the [`--precise`] flag of `cargo update` (nightly only).\n\n[yank]: publishing.md#cargo-yank\n[`--precise`]: ../commands/cargo-update.md#option-cargo-update---precise\n\n## Dependency updates\n\nDependency resolution is automatically performed by all Cargo commands that\nneed to know about the dependency graph. For example, [`cargo build`] will run\nthe resolver to discover all the dependencies to build. After the first time\nit runs, the result is stored in the `Cargo.lock` file. Subsequent commands\nwill run the resolver, keeping dependencies locked to the versions in\n`Cargo.lock` *if it can*.\n\nIf the dependency list in `Cargo.toml` has been modified, for example changing\nthe version of a dependency from `1.0` to `2.0`, then the resolver will select\na new version for that dependency that matches the new requirements. If that\nnew dependency introduces new requirements, those new requirements may also\ntrigger additional updates. The `Cargo.lock` file will be updated with the new\nresult. The `--locked` or `--frozen` flags can be used to change this behavior\nto prevent automatic updates when requirements change, and return an error\ninstead.\n\n[`cargo update`] can be used to update the entries in `Cargo.lock` when new\nversions are published. Without any options, it will attempt to update all\npackages in the lock file. The `-p` flag can be used to target the update for\na specific package, and other flags such as `--recursive` or `--precise` can\nbe used to control how versions are selected.\n\n[`cargo build`]: ../commands/cargo-build.md\n[`cargo update`]: ../commands/cargo-update.md\n\n## Overrides\n\nCargo has several mechanisms to override dependencies within the graph. The\n[Overriding Dependencies] chapter goes into detail on how to use overrides.\nThe overrides appear as an overlay to a registry, replacing the patched\nversion with the new entry. Otherwise, resolution is performed like normal.\n\n[Overriding Dependencies]: overriding-dependencies.md\n\n## Dependency kinds\n\nThere are three kinds of dependencies in a package: normal, [build], and\n[dev][dev-dependencies]. For the most part these are all treated the same from\nthe perspective of the resolver. One difference is that dev-dependencies for\nnon-workspace members are always ignored, and do not influence resolution.\n\n[Platform-specific dependencies] with the `[target]` table are resolved as-if\nall platforms are enabled. In other words, the resolver ignores the platform\nor `cfg` expression.\n\n[build]: specifying-dependencies.md#build-dependencies\n[dev-dependencies]: specifying-dependencies.md#development-dependencies\n[Platform-specific dependencies]: specifying-dependencies.md#platform-specific-dependencies\n\n### dev-dependency cycles\n\nUsually the resolver does not allow cycles in the graph, but it does allow\nthem for [dev-dependencies]. For example, project \"foo\" has a dev-dependency\non \"bar\", which has a normal dependency on \"foo\" (usually as a \"path\"\ndependency). This is allowed because there isn't really a cycle from the\nperspective of the build artifacts. In this example, the \"foo\" library is\nbuilt (which does not need \"bar\" because \"bar\" is only used for tests), and\nthen \"bar\" can be built depending on \"foo\", then the \"foo\" tests can be built\nlinking to \"bar\".\n\nBeware that this can lead to confusing errors. In the case of building library\nunit tests, there are actually two copies of the library linked into the final\ntest binary: the one that was linked with \"bar\", and the one built that\ncontains the unit tests. Similar to the issues highlighted in the\n[Version-incompatibility hazards] section, the types between the two are not\ncompatible. Be careful when exposing types of \"foo\" from \"bar\" in this\nsituation, since the \"foo\" unit tests won't treat them the same as the local\ntypes.\n\nIf possible, try to split your package into multiple packages and restructure\nit so that it remains strictly acyclic.\n\n## Resolver versions\n\nDifferent resolver behavior can be specified through the resolver\nversion in `Cargo.toml` like this:\n\n```toml\n[package]\nname = \"my-package\"\nversion = \"1.0.0\"\nresolver = \"2\"\n```\n- `\"1\"` (default)\n- `\"2\"` ([`edition = \"2021\"`](manifest.md#the-edition-field) default): Introduces changes in [feature\nunification](#features). See the [features chapter][features-2] for more\ndetails.\n- `\"3\"` ([`edition = \"2024\"`](manifest.md#the-edition-field) default, requires Rust 1.84+): Change the default for [`resolver.incompatible-rust-versions`] from `allow` to `fallback`\n\nThe resolver is a global option that affects the entire workspace. The\n`resolver` version in dependencies is ignored, only the value in the top-level\npackage will be used. If using a [virtual workspace], the version should be\nspecified in the `[workspace]` table, for example:\n\n```toml\n[workspace]\nmembers = [\"member1\", \"member2\"]\nresolver = \"2\"\n```\n\n> **MSRV:** Requires 1.51+\n\n[virtual workspace]: workspaces.md#virtual-workspace\n[features-2]: features.md#feature-resolver-version-2\n\n## Recommendations\n\nThe following are some recommendations for setting the version within your\npackage, and for specifying dependency requirements. These are general\nguidelines that should apply to common situations, but of course some\nsituations may require specifying unusual requirements.\n\n* Follow the [SemVer guidelines] when deciding how to update your version\n  number, and whether or not you will need to make a SemVer-incompatible\n  version change.\n* Use caret requirements for dependencies, such as `\"1.2.3\"`, for most\n  situations. This ensures that the resolver can be maximally flexible in\n  choosing a version while maintaining build compatibility.\n  * Specify all three components with the version you are currently using.\n    This helps set the minimum version that will be used, and ensures that\n    other users won't end up with an older version of the dependency that\n    might be missing something that your package requires.\n  * Avoid `*` requirements, as they are not allowed on [crates.io], and they\n    can pull in SemVer-breaking changes during a normal `cargo update`.\n  * Avoid overly broad version requirements. For example, `>=2.0.0` can pull\n    in any SemVer-incompatible version, like version `5.0.0`, which can result\n    in broken builds in the future.\n  * Avoid overly narrow version requirements if possible. For example, if you\n    specify a tilde requirement like `bar=\"~1.3\"`, and another package\n    specifies a requirement of `bar=\"1.4\"`, this will fail to resolve, even\n    though minor releases should be compatible.\n* Try to keep the dependency versions up-to-date with the actual minimum\n  versions that your library requires. For example, if you have a requirement\n  of `bar=\"1.0.12\"`, and then in a future release you start using new features\n  added in the `1.1.0` release of \"bar\", update your dependency requirement to\n  `bar=\"1.1.0\"`.\n\n  If you fail to do this, it may not be immediately obvious because Cargo can\n  opportunistically choose the newest version when you run a blanket `cargo\n  update`. However, if another user depends on your library, and runs `cargo\n  update your-library`, it will *not* automatically update \"bar\" if it is\n  locked in their `Cargo.lock`. It will only update \"bar\" in that situation if\n  the dependency declaration is also updated. Failure to do so can cause\n  confusing build errors for the user using `cargo update your-library`.\n* If two packages are tightly coupled, then an `=` dependency requirement may\n  help ensure that they stay in sync. For example, a library with a companion\n  proc-macro library will sometimes make assumptions between the two libraries\n  that won't work well if the two are out of sync (and it is never expected to\n  use the two libraries independently). The parent library can use an `=`\n  requirement on the proc-macro, and re-export the macros for easy access.\n* `0.0.x` versions can be used for packages that are permanently unstable.\n\nIn general, the stricter you make the dependency requirements, the more likely\nit will be for the resolver to fail. Conversely, if you use requirements that\nare too loose, it may be possible for new versions to be published that will\nbreak the build.\n\n[SemVer guidelines]: semver.md\n[crates.io]: https://crates.io/\n\n## Troubleshooting\n\nThe following illustrates some problems you may experience, and some possible\nsolutions.\n\n### Why was a dependency included?\n\nSay you see dependency `rand` in the `cargo check` output but don't think it's needed and want to understand why it's being pulled in.\n\nYou can run\n```console\n$ cargo tree --workspace --target all --all-features --invert rand\nrand v0.8.5\n└── ...\n\nrand v0.8.5\n└── ...\n```\n\n### Why was that feature on this dependency enabled?\n\nYou might identify that it was an activated feature that caused `rand` to show up.  **To figure out which package activated the feature, you can add the `--edges features`**\n```console\n$ cargo tree --workspace --target all --all-features --edges features --invert rand\nrand v0.8.5\n└── ...\n\nrand v0.8.5\n└── ...\n```\n\n### Unexpected dependency duplication\n\nYou see multiple instances of `rand` when you run\n```console\n$ cargo tree --workspace --target all --all-features --duplicates\nrand v0.7.3\n└── ...\n\nrand v0.8.5\n└── ...\n```\n\nThe resolver algorithm has converged on a solution that includes two copies of a\ndependency when one would suffice. For example:\n\n```toml\n# Package A\n[dependencies]\nrand = \"0.7\"\n\n# Package B\n[dependencies]\nrand = \">=0.6\"  # note: open requirements such as this are discouraged\n```\n\nIn this example, Cargo may build two copies of the `rand` crate, even though a\nsingle copy at version `0.7.3` would meet all requirements. This is because the\nresolver's algorithm favors building the latest available version of `rand` for\nPackage B, which is `0.8.5` at the time of this writing, and that is\nincompatible with Package A's specification. The resolver's algorithm does not\ncurrently attempt to \"deduplicate\" in this situation.\n\nThe use of open-ended version requirements like `>=0.6` is discouraged in Cargo.\nBut, if you run into this situation, the [`cargo update`] command with the\n`--precise` flag can be used to manually remove such duplications.\n\n[`cargo update`]: ../commands/cargo-update.md\n\n### Why wasn't a newer version selected?\n\nSay you noticed that the latest version of a dependency wasn't selected when you ran:\n```console\n$ cargo update\n```\nYou can enable some extra logging to see why this happened:\n```console\n$ env CARGO_LOG=cargo::core::resolver=trace cargo update\n```\n**Note:** Cargo log targets and levels may change over time.\n\n### SemVer-breaking patch release breaks the build\n\nSometimes a project may inadvertently publish a point release with a\nSemVer-breaking change. When users update with `cargo update`, they will pick\nup this new release, and then their build may break. In this situation, it is\nrecommended that the project should [yank] the release, and either remove the\nSemVer-breaking change, or publish it as a new SemVer-major version increase.\n\nIf the change happened in a third-party project, if possible try to\n(politely!) work with the project to resolve the issue.\n\nWhile waiting for the release to be yanked, some workarounds depend on the\ncircumstances:\n\n* If your project is the end product (such as a binary executable), just avoid\n  updating the offending package in `Cargo.lock`. This can be done with the\n  `--precise` flag in [`cargo update`].\n* If you publish a binary on [crates.io], then you can temporarily add an `=`\n  requirement to force the dependency to a specific good version.\n  * Binary projects can alternatively recommend users to use the `--locked`\n    flag with [`cargo install`] to use the original `Cargo.lock` that contains\n    the known good version.\n* Libraries may also consider publishing a temporary new release with stricter\n  requirements that avoid the troublesome dependency. You may want to consider\n  using range requirements (instead of `=`) to avoid overly-strict\n  requirements that may conflict with other packages using the same\n  dependency. Once the problem has been resolved, you can publish another\n  point release that relaxes the dependency back to a caret requirement.\n* If it looks like the third-party project is unable or unwilling to yank the\n  release, then one option is to update your code to be compatible with the\n  changes, and update the dependency requirement to set the minimum version to\n  the new release. You will also need to consider if this is a SemVer-breaking\n  change of your own library, for example if it exposes types from the\n  dependency.\n\n[`cargo install`]: ../commands/cargo-install.md\n"
  },
  {
    "path": "src/doc/src/reference/running-a-registry.md",
    "content": "# Running a Registry\n\nA minimal registry can be implemented by having a git repository that contains\nan index, and a server that contains the compressed `.crate` files created by\n[`cargo package`]. Users won't be able to use Cargo to publish to it, but this\nmay be sufficient for closed environments. The index format is described in\n[Registry Index].\n\nA full-featured registry that supports publishing will additionally need to\nhave a web API service that conforms to the API used by Cargo. The web API is\ndescribed in [Registry Web API].\n\nCommercial and community projects are available for building and running a\nregistry. See <https://github.com/rust-lang/cargo/wiki/Third-party-registries>\nfor a list of what is available.\n\n[Registry Web API]: registry-web-api.md\n[Registry Index]: registry-index.md\n[`cargo publish`]: ../commands/cargo-publish.md\n[`cargo package`]: ../commands/cargo-package.md\n"
  },
  {
    "path": "src/doc/src/reference/rust-version.md",
    "content": "# Rust Version\n\nThe `rust-version` field is an optional key that tells cargo what version of the\nRust toolchain you support for your package.\n\n```toml\n[package]\n# ...\nrust-version = \"1.56\"\n```\n\nThe Rust version must be a bare version number with at least one component; it\ncannot include semver operators or pre-release identifiers. Compiler pre-release\nidentifiers such as -nightly will be ignored while checking the Rust version.\n\n> **MSRV:** Respected as of 1.56\n\n## Uses\n\n**Diagnostics:**\n\nWhen your package is compiled on an unsupported toolchain, Cargo will report that as an error to the user. This makes the support expectations clear and avoids reporting a less direct diagnostic like invalid syntax or missing functionality\nin the standard library. This affects all [Cargo targets](cargo-targets.md) in the\npackage, including binaries, examples, test suites, benchmarks, etc.\nA user can opt-in to an unsupported build of a package with the `--ignore-rust-version` flag.\n\n\n**Development aid:**\n\n`cargo add` will auto-select the dependency's version requirement to be the latest version compatible with your `rust-version`.\nIf that isn't the latest version, `cargo add` will inform users so they can make the choice on whether to keep it or update your `rust-version`.\n\nThe [resolver](resolver.md#rust-version) may take Rust version into account when picking dependencies.\n\nOther tools may also take advantage of it, like `cargo clippy`'s\n[`incompatible_msrv` lint](https://rust-lang.github.io/rust-clippy/stable/index.html#incompatible_msrv).\n\n> **Note:** The `rust-version` may be ignored using the `--ignore-rust-version` option.\n\n## Support Expectations\n\nThese are general expectations; some packages may document when they do not follow these.\n\n**Complete:**\n\nAll functionality, including binaries and API, are available on the supported Rust versions under every [feature](features.md).\n\n**Verified:**\n\nA package's functionality is verified on its supported Rust versions, including automated testing.\nSee also our\n[Rust version CI guide](../guide/continuous-integration.md#verifying-rust-version).\n\n**Patchable:**\n\nWhen licenses allow it,\nusers can [override their local dependency](overriding-dependencies.md) with a fork of your package.\nIn this situation, Cargo may load the entire workspace for the patched dependency which should work on the supported Rust versions, even if other packages in the workspace have different supported Rust versions.\n\n**Dependency Support:**\n\nIn support of the above,\nit is expected that each dependency's version-requirement supports at least one version compatible with your `rust-version`.\nHowever,\nit is **not** expected that the dependency specification excludes versions incompatible with your `rust-version`.\nIn fact, supporting both allows you to balance the needs of users that support older Rust versions with those that don't.\n\n## Setting and Updating Rust Version\n\nWhat Rust versions to support is a trade off between\n- Costs for the maintainer in not using newer features of the Rust toolchain or their dependencies\n- Costs to users who would benefit from a package using newer features of a toolchain, e.g. reducing build times by migrating to a feature in the standard library from a polyfill\n- Availability of a package to users supporting older Rust versions\n\n> **Note:** [Changing `rust-version`](semver.md#env-new-rust) is assumed to be a minor incompatibility\n\n> **Recommendation:** Choose a policy for what Rust versions to support and when that is changed so users can compare it with their own policy and,\n> if it isn't compatible,\n> decide whether the loss of general improvements or the risk of a blocking bug that won't be fixed is acceptable or not.\n>\n> The simplest policy to support is to always use the latest Rust version.\n>\n> Depending on your risk profile, the next simplest approach is to continue to support old major or minor versions of your package that support older Rust versions.\n\n### Selecting supported Rust versions\n\nUsers of your package are most likely to track their supported Rust versions to:\n- Their Rust toolchain vendor's support policy, e.g. The Rust Project or a Linux distribution\n  - Note: the Rust Project only offers bug fixes and security updates for the latest version.\n- A fixed schedule for users to re-verify their packages with the new toolchain, e.g. the first release of the year, every 5 releases.\n\nIn addition, users are unlikely to be using the new Rust version immediately but need time to notice and re-verify or might not be aligned on the exact same schedule..\n\nExample version policies:\n- \"N-2\", meaning \"latest version with a 2 release grace window for updating\"\n- Every even release with a 2 release grace window for updating\n- Every version from this calendar year with a one year grace window for updating\n\n> **Note:** To find the minimum `rust-version` compatible with your project as-is, you can use third-party tools like [`cargo-msrv`](https://crates.io/crates/cargo-msrv).\n\n### Update timeline\n\nWhen your policy specifies you no longer need to support a Rust version, you can update `rust-version` immediately or when needed.\n\nBy allowing `rust-version` to drift from your policy,\nyou offer users more of a grace window for upgrading.\nHowever, this is too unpredictable to be relied on for aligning with the Rust version users track.\n\nThe further `rust-version` drifts from your specified policy,\nthe more likely users are to infer a policy you did not intend,\nleading to frustration at the unmet expectations.\n\nWhen drift is allowed,\nthere is the question of what is \"justifiable enough\" to drop supported Versions.\nEach person can come to a reasonably different justification;\nworking through that discussion can be frustrating for the involved parties.\nThis will disempower those who would want to avoid that type of conflict,\nwhich is particularly the case for new or casual contributors who either\nfeel that they are not in a position to raise the question or\nthat the conflict may hurt the chance of their change being merged.\n\n### Multiple Policies in a Workspace\n\nCargo allows supporting multiple policies within one workspace.\n\nVerifying specific packages under specific Rust versions can get complicated.\nTools like [`cargo-hack`](https://crates.io/crates/cargo-hack) can help.\n\nFor any dependency shared across policies,\nthe lowest common versions must be used as Cargo\n[unifies SemVer-compatible versions](resolver.md#semver-compatibility),\npotentially limiting access to features of the shared dependency for the workspace member with the higher `rust-version`.\n\nTo allow users to patch a dependency on one of your workspace members,\nevery package in the workspace would need to be loadable in the oldest Rust version supported by the workspace.\n\nWhen using [`incompatible-rust-versions = \"fallback\"`](config.md#resolverincompatible-rust-versions),\nthe Rust version of one package can affect dependency versions selected for another package with a different Rust version.\nSee the [resolver](resolver.md#rust-version) chapter for more details.\n\n### One or More Policies\n\nOne way to mitigate the downsides of supporting older Rust versions is to apply your policy to older major or minor versions of your package that you continue to support.\nYou likely still need a policy for what Rust versions the development branch support compared to the release branches for those major or minor versions.\n\nOnly updating the development branch when \"needed\"' can help reduce the number of supported release branches.\n\nThere is the question of what can be backported into these release branches.\nBy backporting new functionality between minor versions,\nthe next available version would be missing it which could be considered a breaking change, violating SemVer.\nBackporting changes also comes with the risk of introducing bugs.\n\nSupporting older versions comes at a cost.\nThis cost is dependent on the risk and impact of bugs within the package and what is acceptable for backporting.\nCreating the release branches on-demand and putting the backport burden on the community are ways to balance this cost.\n\nThere is not yet a way for dependency management tools to report that a non-latest version is still supported,\nshifting the responsibility to users to notice this in documentation.\n\nFor example, a Rust version support policy could look like:\n- The development branch tracks to the latest stable release from the Rust Project, updated when needed\n  - The minor version will be raised when changing `rust-version`\n- The project supports every version for this calendar year, with another year grace window\n  - The last minor version that supports a supported Rust version will receive community provided bug fixes\n  - Fixes must be backported to all supported minor releases between the development branch and the needed supported Rust version\n"
  },
  {
    "path": "src/doc/src/reference/semver.md",
    "content": "# SemVer Compatibility\n\nThis chapter provides details on what is conventionally considered a\ncompatible or breaking SemVer change for new releases of a package. See the\n[SemVer compatibility] section for details on what SemVer is, and how Cargo\nuses it to ensure compatibility of libraries.\n\nThese are only *guidelines*, and not necessarily hard-and-fast rules that all\nprojects will obey. The [Change categories] section details how this guide\nclassifies the level and severity of a change. Most of this guide focuses on\nchanges that will cause `cargo` and `rustc` to fail to build something that\npreviously worked. Almost every change carries some risk that it will\nnegatively affect the runtime behavior, and for those cases it is usually a\njudgment call by the project maintainers whether or not it is a\nSemVer-incompatible change.\n\n[Change categories]: #change-categories\n[SemVer compatibility]: resolver.md#semver-compatibility\n\n## Change categories\n\nAll of the policies listed below are categorized by the level of change:\n\n* **Major change**: a change that requires a major SemVer bump.\n* **Minor change**: a change that requires only a minor SemVer bump.\n* **Possibly-breaking change**: a change that some projects may consider major\n  and others consider minor.\n\nThe \"Possibly-breaking\" category covers changes that have the *potential* to\nbreak during an update, but may not necessarily cause a breakage. The impact\nof these changes should be considered carefully. The exact nature will depend\non the change and the principles of the project maintainers.\n\nSome projects may choose to only bump the patch number on a minor change. It\nis encouraged to follow the SemVer spec, and only apply bug fixes in patch\nreleases. However, a bug fix may require an API change that is marked as a\n\"minor change\", and shouldn't affect compatibility. This guide does not take a\nstance on how each individual \"minor change\" should be treated, as the\ndifference between minor and patch changes are conventions that depend on the\nnature of the change.\n\nSome changes are marked as \"minor\", even though they carry the potential risk\nof breaking a build. This is for situations where the potential is extremely\nlow, and the potentially breaking code is unlikely to be written in idiomatic\nRust, or is specifically discouraged from use.\n\nThis guide uses the terms \"major\" and \"minor\" assuming this relates to a\n\"1.0.0\" release or later. Initial development releases starting with \"0.y.z\"\ncan treat changes in \"y\" as a major release, and \"z\" as a minor release.\n\"0.0.z\" releases are always major changes. This is because Cargo uses the\nconvention that only changes in the left-most non-zero component are\nconsidered incompatible.\n\n* API compatibility\n    * Items\n        * [Major: renaming/moving/removing any public items](#item-remove)\n        * [Minor: adding new public items](#item-new)\n    * Types\n        * [Major: Changing the alignment, layout, or size of a well-defined type](#type-layout)\n    * Structs\n        * [Major: adding a private struct field when all current fields are public](#struct-add-private-field-when-public)\n        * [Major: adding a public field when no private field exists](#struct-add-public-field-when-no-private)\n        * [Minor: adding or removing private fields when at least one already exists](#struct-private-fields-with-private)\n        * [Minor: going from a tuple struct with all private fields (with at least one field) to a normal struct, or vice versa](#struct-tuple-normal-with-private)\n    * Enums\n        * [Major: adding new enum variants (without `non_exhaustive`)](#enum-variant-new)\n        * [Major: adding new fields to an enum variant](#enum-fields-new)\n    * Traits\n        * [Major: adding a non-defaulted trait item](#trait-new-item-no-default)\n        * [Major: any change to trait item signatures](#trait-item-signature)\n        * [Possibly-breaking: adding a defaulted trait item](#trait-new-default-item)\n        * [Major: adding a trait item that makes the trait non-object safe](#trait-object-safety)\n        * [Major: adding a type parameter without a default](#trait-new-parameter-no-default)\n        * [Minor: adding a defaulted trait type parameter](#trait-new-parameter-default)\n    * Implementations\n        * [Possibly-breaking change: adding any inherent items](#impl-item-new)\n    * Generics\n        * [Major: tightening generic bounds](#generic-bounds-tighten)\n        * [Minor: loosening generic bounds](#generic-bounds-loosen)\n        * [Minor: adding defaulted type parameters](#generic-new-default)\n        * [Minor: generalizing a type to use generics (with identical types)](#generic-generalize-identical)\n        * [Major: generalizing a type to use generics (with possibly different types)](#generic-generalize-different)\n        * [Minor: changing a generic type to a more generic type](#generic-more-generic)\n        * [Major: capturing more generic parameters in RPIT](#generic-rpit-capture)\n    * Functions\n        * [Major: adding/removing function parameters](#fn-change-arity)\n        * [Possibly-breaking: introducing a new function type parameter](#fn-generic-new)\n        * [Minor: generalizing a function to use generics (supporting original type)](#fn-generalize-compatible)\n        * [Major: generalizing a function to use generics with type mismatch](#fn-generalize-mismatch)\n        * [Minor: making an `unsafe` function safe](#fn-unsafe-safe)\n    * Attributes\n        * [Major: switching from `no_std` support to requiring `std`](#attr-no-std-to-std)\n        * [Major: adding `non_exhaustive` to an existing enum, variant, or struct with no private fields](#attr-adding-non-exhaustive)\n* Tooling and environment compatibility\n    * [Possibly-breaking: changing the minimum version of Rust required](#env-new-rust)\n    * [Possibly-breaking: changing the platform and environment requirements](#env-change-requirements)\n    * [Minor: introducing new lints](#new-lints)\n    * Cargo\n        * [Minor: adding a new Cargo feature](#cargo-feature-add)\n        * [Major: removing a Cargo feature](#cargo-feature-remove)\n        * [Major: removing a feature from a feature list if that changes functionality or public items](#cargo-feature-remove-another)\n        * [Possibly-breaking: removing an optional dependency](#cargo-remove-opt-dep)\n        * [Minor: changing dependency features](#cargo-change-dep-feature)\n        * [Minor: adding dependencies](#cargo-dep-add)\n* [Application compatibility](#application-compatibility)\n\n## API compatibility\n\nAll of the examples below contain three parts: the original code, the code\nafter it has been modified, and an example usage of the code that could appear\nin another project. In a minor change, the example usage should successfully\nbuild with both the before and after versions.\n\n### Major: renaming/moving/removing any public items {#item-remove}\n\nThe absence of a publicly exposed [item][items] will cause any uses of that item to\nfail to compile.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub fn foo() {}\n\n///////////////////////////////////////////////////////////\n// After\n// ... item has been removed\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nfn main() {\n    updated_crate::foo(); // Error: cannot find function `foo`\n}\n```\n\nThis includes adding any sort of [`cfg` attribute] which can change which\nitems or behavior is available based on [conditional compilation].\n\nMitigating strategies:\n* Mark items to be removed as [deprecated], and then remove them at a later\n  date in a SemVer-breaking release.\n* Mark renamed items as [deprecated], and use a [`pub use`] item to re-export\n  to the old name.\n\n### Minor: adding new public items {#item-new}\n\nAdding new, public [items] is a minor change.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n// ... absence of item\n\n///////////////////////////////////////////////////////////\n// After\npub fn foo() {}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\n// `foo` is not used since it didn't previously exist.\n```\n\nNote that in some rare cases this can be a **breaking change** due to glob\nimports. For example, if you add a new trait, and a project has used a glob\nimport that brings that trait into scope, and the new trait introduces an\nassociated item that conflicts with any types it is implemented on, this can\ncause a compile-time error due to the ambiguity. Example:\n\n```rust,ignore\n// Breaking change example\n\n///////////////////////////////////////////////////////////\n// Before\n// ... absence of trait\n\n///////////////////////////////////////////////////////////\n// After\npub trait NewTrait {\n    fn foo(&self) {}\n}\n\nimpl NewTrait for i32 {}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::*;\n\npub trait LocalTrait {\n    fn foo(&self) {}\n}\n\nimpl LocalTrait for i32 {}\n\nfn main() {\n    123i32.foo(); // Error:  multiple applicable items in scope\n}\n```\n\nThis is not considered a major change because conventionally glob imports are\na known forwards-compatibility hazard. Glob imports of items from external\ncrates should be avoided.\n\n### Major: Changing the alignment, layout, or size of a well-defined type {#type-layout}\n\nIt is a breaking change to change the alignment, layout, or size of a type that was previously well-defined.\n\nIn general, types that use the [the default representation] do not have a well-defined alignment, layout, or size.\nThe compiler is free to alter the alignment, layout, or size, so code should not make any assumptions about it.\n\n> **Note**: It may be possible for external crates to break if they make assumptions about the alignment, layout, or size of a type even if it is not well-defined.\n> This is not considered a SemVer breaking change since those assumptions should not be made.\n\nSome examples of changes that are not a breaking change are (assuming no other rules in this guide are violated):\n\n* Adding, removing, reordering, or changing fields of a default representation struct, union, or enum in such a way that the change follows the other rules in this guide (for example, using `non_exhaustive` to allow those changes, or changes to private fields that are already private).\n  See [struct-add-private-field-when-public](#struct-add-private-field-when-public), [struct-add-public-field-when-no-private](#struct-add-public-field-when-no-private), [struct-private-fields-with-private](#struct-private-fields-with-private), [enum-fields-new](#enum-fields-new).\n* Adding variants to a default representation enum, if the enum uses `non_exhaustive`.\n  This may change the alignment or size of the enumeration, but those are not well-defined.\n  See [enum-variant-new](#enum-variant-new).\n* Adding, removing, reordering, or changing private fields of a `repr(C)` struct, union, or enum, following the other rules in this guide (for example, using `non_exhaustive`, or adding private fields when other private fields already exist).\n  See [repr-c-private-change](#repr-c-private-change).\n* Adding variants to a `repr(C)` enum, if the enum uses `non_exhaustive`.\n  See [repr-c-enum-variant-new](#repr-c-enum-variant-new).\n* Adding `repr(C)` to a default representation struct, union, or enum.\n  See [repr-c-add](#repr-c-add).\n* Adding `repr(<int>)` [primitive representation] to an enum.\n  See [repr-int-enum-add](#repr-int-enum-add).\n* Adding `repr(transparent)` to a default representation struct or enum.\n  See [repr-transparent-add](#repr-transparent-add).\n\nTypes that use the [`repr` attribute] can be said to have an alignment and layout that is defined in some way that code may make some assumptions about that may break as a result of changing that type.\n\nIn some cases, types with a `repr` attribute may not have an alignment, layout, or size that is well-defined.\nIn these cases, it may be safe to make changes to the types, though care should be exercised.\nFor example, types with private fields that do not otherwise document their alignment, layout, or size guarantees cannot be relied upon by external crates since the public API does not fully define the alignment, layout, or size of the type.\n\nA common example where a type with *private* fields is well-defined is a type with a single private field with a generic type, using `repr(transparent)`,\nand the prose of the documentation discusses that it is transparent to the generic type.\nFor example, see [`UnsafeCell`].\n\nSome examples of breaking changes are:\n\n* Adding `repr(packed)` to a struct or union.\n  See [repr-packed-add](#repr-packed-add).\n* Adding `repr(align)` to a struct, union, or enum.\n  See [repr-align-add](#repr-align-add).\n* Removing `repr(packed)` from a struct or union.\n  See [repr-packed-remove](#repr-packed-remove).\n* Changing the value N of `repr(packed(N))` if that changes the alignment or layout.\n  See [repr-packed-n-change](#repr-packed-n-change).\n* Changing the value N of `repr(align(N))` if that changes the alignment.\n  See [repr-align-n-change](#repr-align-n-change).\n* Removing `repr(align)` from a struct, union, or enum.\n  See [repr-align-remove](#repr-align-remove).\n* Changing the order of public fields of a `repr(C)` type.\n  See [repr-c-shuffle](#repr-c-shuffle).\n* Removing `repr(C)` from a struct, union, or enum.\n  See [repr-c-remove](#repr-c-remove).\n* Removing `repr(<int>)` from an enum.\n  See [repr-int-enum-remove](#repr-int-enum-remove).\n* Changing the primitive representation of a `repr(<int>)` enum.\n  See [repr-int-enum-change](#repr-int-enum-change).\n* Removing `repr(transparent)` from a struct or enum.\n  See [repr-transparent-remove](#repr-transparent-remove).\n\n[the default representation]: ../../reference/type-layout.html#the-default-representation\n[primitive representation]: ../../reference/type-layout.html#primitive-representations\n[`repr` attribute]: ../../reference/type-layout.html#representations\n[`std::mem::transmute`]: ../../std/mem/fn.transmute.html\n[`UnsafeCell`]: ../../std/cell/struct.UnsafeCell.html#memory-layout\n\n#### Minor: `repr(C)` add, remove, or change a private field {#repr-c-private-change}\n\nIt is usually safe to add, remove, or change a private field of a `repr(C)` struct, union, or enum, assuming it follows the other guidelines in this guide (see [struct-add-private-field-when-public](#struct-add-private-field-when-public), [struct-add-public-field-when-no-private](#struct-add-public-field-when-no-private), [struct-private-fields-with-private](#struct-private-fields-with-private), [enum-fields-new](#enum-fields-new)).\n\nFor example, adding private fields can only be done if there are already other private fields, or it is `non_exhaustive`.\nPublic fields may be added if there are private fields, or it is `non_exhaustive`, and the addition does not alter the layout of the other fields.\n\nHowever, this may change the size and alignment of the type.\nCare should be taken if the size or alignment changes.\nCode should not make assumptions about the size or alignment of types with private fields or `non_exhaustive` unless it has a documented size or alignment.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[derive(Default)]\n#[repr(C)]\npub struct Example {\n    pub f1: i32,\n    f2: i32, // a private field\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[derive(Default)]\n#[repr(C)]\npub struct Example {\n    pub f1: i32,\n    f2: i32,\n    f3: i32, // a new field\n}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nfn main() {\n    // NOTE: Users should not make assumptions about the size or alignment\n    // since they are not documented.\n    let f = updated_crate::Example::default();\n}\n```\n\n#### Minor: `repr(C)` add enum variant {#repr-c-enum-variant-new}\n\nIt is usually safe to add variants to a `repr(C)` enum, if the enum uses `non_exhaustive`.\nSee [enum-variant-new](#enum-variant-new) for more discussion.\n\nNote that this may be a breaking change since it changes the size and alignment of the type.\nSee [repr-c-private-change](#repr-c-private-change) for similar concerns.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[repr(C)]\n#[non_exhaustive]\npub enum Example {\n    Variant1 { f1: i16 },\n    Variant2 { f1: i32 },\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(C)]\n#[non_exhaustive]\npub enum Example {\n    Variant1 { f1: i16 },\n    Variant2 { f1: i32 },\n    Variant3 { f1: i64 }, // added\n}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nfn main() {\n    // NOTE: Users should not make assumptions about the size or alignment\n    // since they are not specified. For example, this raised the size from 8\n    // to 16 bytes.\n    let f = updated_crate::Example::Variant2 { f1: 123 };\n}\n```\n\n#### Minor: Adding `repr(C)` to a default representation {#repr-c-add}\n\nIt is safe to add `repr(C)` to a struct, union, or enum with [the default representation].\nThis is safe because users should not make assumptions about the alignment, layout, or size of types with the default representation.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Example {\n    pub f1: i32,\n    pub f2: i16,\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(C)] // added\npub struct Example {\n    pub f1: i32,\n    pub f2: i16,\n}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nfn main() {\n    let f = updated_crate::Example { f1: 123, f2: 456 };\n}\n```\n\n#### Minor: Adding `repr(<int>)` to an enum {#repr-int-enum-add}\n\nIt is safe to add `repr(<int>)` [primitive representation] to an enum with [the default representation].\nThis is safe because users should not make assumptions about the alignment, layout, or size of an enum with the default representation.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub enum E {\n    Variant1,\n    Variant2(i32),\n    Variant3 { f1: f64 },\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(i32)] // added\npub enum E {\n    Variant1,\n    Variant2(i32),\n    Variant3 { f1: f64 },\n}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nfn main() {\n    let x = updated_crate::E::Variant3 { f1: 1.23 };\n}\n```\n\n#### Minor: Adding `repr(transparent)` to a default representation struct or enum {#repr-transparent-add}\n\nIt is safe to add `repr(transparent)` to a struct or enum with [the default representation].\nThis is safe because users should not make assumptions about the alignment, layout, or size of a struct or enum with the default representation.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[derive(Default)]\npub struct Example<T>(T);\n\n///////////////////////////////////////////////////////////\n// After\n#[derive(Default)]\n#[repr(transparent)] // added\npub struct Example<T>(T);\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nfn main() {\n    let x = updated_crate::Example::<i32>::default();\n}\n```\n\n#### Major: Adding `repr(packed)` to a struct or union {#repr-packed-add}\n\nIt is a breaking change to add `repr(packed)` to a struct or union.\nMaking a type `repr(packed)` makes changes that can break code, such as being invalid to take a reference to a field, or causing truncation of disjoint closure captures.\n\n<!-- TODO: If all fields are private, should this be safe to do? -->\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Example {\n    pub f1: u8,\n    pub f2: u16,\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(packed)] // added\npub struct Example {\n    pub f1: u8,\n    pub f2: u16,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nfn main() {\n    let f = updated_crate::Example { f1: 1, f2: 2 };\n    let x = &f.f2; // Error: error[E0793]: reference to field of packed struct is unaligned\n}\n```\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Example(pub i32, pub i32);\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(packed)]\npub struct Example(pub i32, pub i32);\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nfn main() {\n    let mut f = updated_crate::Example(123, 456);\n    let c = || {\n        // Without repr(packed), the closure precisely captures `&f.0`.\n        // With repr(packed), the closure captures `&f` to avoid undefined behavior.\n        let a = f.0;\n    };\n    f.1 = 789; // Error: cannot assign to `f.1` because it is borrowed\n    c();\n}\n```\n\n#### Major: Adding `repr(align)` to a struct, union, or enum {#repr-align-add}\n\nIt is a breaking change to add `repr(align)` to a struct, union, or enum.\nMaking a type `repr(align)` would break any use of that type in a `repr(packed)` type because that combination is not allowed.\n\n<!-- TODO: This seems like it should be extraordinarily rare. Should there be any exceptions carved out for this? -->\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Aligned {\n    pub a: i32,\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(align(8))] // added\npub struct Aligned {\n    pub a: i32,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Aligned;\n\n#[repr(packed)]\npub struct Packed { // Error: packed type cannot transitively contain a `#[repr(align)]` type\n    f1: Aligned,\n}\n\nfn main() {\n    let p = Packed {\n        f1: Aligned { a: 123 },\n    };\n}\n```\n\n#### Major: Removing `repr(packed)` from a struct or union {#repr-packed-remove}\n\nIt is a breaking change to remove `repr(packed)` from a struct or union.\nThis may change the alignment or layout that extern crates are relying on.\n\nIf any fields are public, then removing `repr(packed)` may change the way disjoint closure captures work.\nIn some cases, this can cause code to break, similar to those outlined in the [edition guide][edition-closures].\n\n[edition-closures]: ../../edition-guide/rust-2021/disjoint-capture-in-closures.html\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[repr(C, packed)]\npub struct Packed {\n    pub a: u8,\n    pub b: u16,\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(C)] // removed packed\npub struct Packed {\n    pub a: u8,\n    pub b: u16,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Packed;\n\nfn main() {\n    let p = Packed { a: 1, b: 2 };\n    // Some assumption about the size of the type.\n    // Without `packed`, this fails since the size is 4.\n    const _: () = assert!(std::mem::size_of::<Packed>() == 3); // Error: assertion failed\n}\n```\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[repr(C, packed)]\npub struct Packed {\n    pub a: *mut i32,\n    pub b: i32,\n}\nunsafe impl Send for Packed {}\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(C)] // removed packed\npub struct Packed {\n    pub a: *mut i32,\n    pub b: i32,\n}\nunsafe impl Send for Packed {}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Packed;\n\nfn main() {\n    let mut x = 123;\n\n    let p = Packed {\n        a: &mut x as *mut i32,\n        b: 456,\n    };\n\n    // When the structure was packed, the closure captures `p` which is Send.\n    // When `packed` is removed, this ends up capturing `p.a` which is not Send.\n    std::thread::spawn(move || unsafe {\n        *(p.a) += 1; // Error: cannot be sent between threads safely\n    });\n}\n```\n\n#### Major: Changing the value N of `repr(packed(N))` if that changes the alignment or layout {#repr-packed-n-change}\n\nIt is a breaking change to change the value of N of `repr(packed(N))` if that changes the alignment or layout.\nThis may change the alignment or layout that external crates are relying on.\n\nIf the value `N` is lowered below the alignment of a public field, then that would break any code that attempts to take a reference of that field.\n\nNote that some changes to `N` may not change the alignment or layout, for example increasing it when the current value is already equal to the natural alignment of the type.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[repr(packed(4))]\npub struct Packed {\n    pub a: u8,\n    pub b: u32,\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(packed(2))] // changed to 2\npub struct Packed {\n    pub a: u8,\n    pub b: u32,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Packed;\n\nfn main() {\n    let p = Packed { a: 1, b: 2 };\n    let x = &p.b; // Error: error[E0793]: reference to field of packed struct is unaligned\n}\n```\n\n#### Major: Changing the value N of `repr(align(N))` if that changes the alignment {#repr-align-n-change}\n\nIt is a breaking change to change the value `N` of `repr(align(N))` if that changes the alignment.\nThis may change the alignment that external crates are relying on.\n\nThis change should be safe to make if the type is not well-defined as discussed in [type layout](#type-layout) (such as having any private fields and having an undocumented alignment or layout).\n\nNote that some changes to `N` may not change the alignment or layout, for example decreasing it when the current value is already equal to or less than the natural alignment of the type.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[repr(align(8))]\npub struct Packed {\n    pub a: u8,\n    pub b: u32,\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(align(4))] // changed to 4\npub struct Packed {\n    pub a: u8,\n    pub b: u32,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Packed;\n\nfn main() {\n    let p = Packed { a: 1, b: 2 };\n    // Some assumption about the size of the type.\n    // The alignment has changed from 8 to 4.\n    const _: () = assert!(std::mem::align_of::<Packed>() == 8); // Error: assertion failed\n}\n```\n\n#### Major: Removing `repr(align)` from a struct, union, or enum {#repr-align-remove}\n\nIt is a breaking change to remove `repr(align)` from a struct, union, or enum, if their layout was well-defined.\nThis may change the alignment or layout that external crates are relying on.\n\nThis change should be safe to make if the type is not well-defined as discussed in [type layout](#type-layout) (such as having any private fields and having an undocumented alignment).\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[repr(C, align(8))]\npub struct Packed {\n    pub a: u8,\n    pub b: u32,\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(C)] // removed align\npub struct Packed {\n    pub a: u8,\n    pub b: u32,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Packed;\n\nfn main() {\n    let p = Packed { a: 1, b: 2 };\n    // Some assumption about the size of the type.\n    // The alignment has changed from 8 to 4.\n    const _: () = assert!(std::mem::align_of::<Packed>() == 8); // Error: assertion failed\n}\n```\n\n#### Major: Changing the order of public fields of a `repr(C)` type {#repr-c-shuffle}\n\nIt is a breaking change to change the order of public fields of a `repr(C)` type.\nExternal crates may be relying on the specific ordering of the fields.\n\n```rust,ignore,run-fail\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[repr(C)]\npub struct SpecificLayout {\n    pub a: u8,\n    pub b: u32,\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(C)]\npub struct SpecificLayout {\n    pub b: u32, // changed order\n    pub a: u8,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::SpecificLayout;\n\nunsafe extern \"C\" {\n    // This C function is assuming a specific layout defined in a C header.\n    fn c_fn_get_b(x: &SpecificLayout) -> u32;\n}\n\nfn main() {\n    let p = SpecificLayout { a: 1, b: 2 };\n    unsafe { assert_eq!(c_fn_get_b(&p), 2) } // Error: value not equal to 2\n}\n\n# mod cdep {\n#     // This simulates what would normally be something included from a build script.\n#     // This definition would be in a C header.\n#     #[repr(C)]\n#     pub struct SpecificLayout {\n#         pub a: u8,\n#         pub b: u32,\n#     }\n#\n#     #[no_mangle]\n#     pub fn c_fn_get_b(x: &SpecificLayout) -> u32 {\n#         x.b\n#     }\n# }\n```\n\n#### Major: Removing `repr(C)` from a struct, union, or enum {#repr-c-remove}\n\nIt is a breaking change to remove `repr(C)` from a struct, union, or enum.\nExternal crates may be relying on the specific layout of the type.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[repr(C)]\npub struct SpecificLayout {\n    pub a: u8,\n    pub b: u32,\n}\n\n///////////////////////////////////////////////////////////\n// After\n// removed repr(C)\npub struct SpecificLayout {\n    pub a: u8,\n    pub b: u32,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::SpecificLayout;\n\nunsafe extern \"C\" {\n    // This C function is assuming a specific layout defined in a C header.\n    fn c_fn_get_b(x: &SpecificLayout) -> u32; // Error: is not FFI-safe\n}\n\nfn main() {\n    let p = SpecificLayout { a: 1, b: 2 };\n    unsafe { assert_eq!(c_fn_get_b(&p), 2) }\n}\n\n# mod cdep {\n#     // This simulates what would normally be something included from a build script.\n#     // This definition would be in a C header.\n#     #[repr(C)]\n#     pub struct SpecificLayout {\n#         pub a: u8,\n#         pub b: u32,\n#     }\n#\n#     #[no_mangle]\n#     pub fn c_fn_get_b(x: &SpecificLayout) -> u32 {\n#         x.b\n#     }\n# }\n```\n\n#### Major: Removing `repr(<int>)` from an enum {#repr-int-enum-remove}\n\nIt is a breaking change to remove `repr(<int>)` from an enum.\nExternal crates may be assuming that the discriminant is a specific size.\nFor example, [`std::mem::transmute`] of an enum may fail.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[repr(u16)]\npub enum Example {\n    Variant1,\n    Variant2,\n    Variant3,\n}\n\n///////////////////////////////////////////////////////////\n// After\n// removed repr(u16)\npub enum Example {\n    Variant1,\n    Variant2,\n    Variant3,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\n\nfn main() {\n    let e = updated_crate::Example::Variant2;\n    let i: u16 = unsafe { std::mem::transmute(e) }; // Error: cannot transmute between types of different sizes\n}\n```\n\n#### Major: Changing the primitive representation of a `repr(<int>)` enum {#repr-int-enum-change}\n\nIt is a breaking change to change the primitive representation of a `repr(<int>)` enum.\nExternal crates may be assuming that the discriminant is a specific size.\nFor example, [`std::mem::transmute`] of an enum may fail.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[repr(u16)]\npub enum Example {\n    Variant1,\n    Variant2,\n    Variant3,\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[repr(u8)] // changed repr size\npub enum Example {\n    Variant1,\n    Variant2,\n    Variant3,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\n\nfn main() {\n    let e = updated_crate::Example::Variant2;\n    let i: u16 = unsafe { std::mem::transmute(e) }; // Error: cannot transmute between types of different sizes\n}\n```\n\n#### Major: Removing `repr(transparent)` from a struct or enum {#repr-transparent-remove}\n\nIt is a breaking change to remove `repr(transparent)` from a struct or enum.\nExternal crates may be relying on the type having the alignment, layout, or size of the transparent field.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[repr(transparent)]\npub struct Transparent<T>(T);\n\n///////////////////////////////////////////////////////////\n// After\n// removed repr\npub struct Transparent<T>(T);\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\n#![deny(improper_ctypes)]\nuse updated_crate::Transparent;\n\nunsafe extern \"C\" {\n    fn c_fn() -> Transparent<f64>; // Error: is not FFI-safe\n}\n\nfn main() {}\n```\n\n### Major: adding a private struct field when all current fields are public {#struct-add-private-field-when-public}\n\nWhen a private field is added to a struct that previously had all public fields,\nthis will break any code that attempts to construct it with a [struct literal].\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Foo {\n    pub f1: i32,\n}\n\n///////////////////////////////////////////////////////////\n// After\npub struct Foo {\n    pub f1: i32,\n    f2: i32,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nfn main() {\n    let x = updated_crate::Foo { f1: 123 }; // Error: cannot construct `Foo`\n}\n```\n\nMitigation strategies:\n* Do not add new fields to all-public field structs.\n* Mark structs as [`#[non_exhaustive]`][non_exhaustive] when first introducing\n  a struct to prevent users from using struct literal syntax, and instead\n  provide a constructor method and/or [Default] implementation.\n\n### Major: adding a public field when no private field exists {#struct-add-public-field-when-no-private}\n\nWhen a public field is added to a struct that has all public fields, this will\nbreak any code that attempts to construct it with a [struct literal].\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Foo {\n    pub f1: i32,\n}\n\n///////////////////////////////////////////////////////////\n// After\npub struct Foo {\n    pub f1: i32,\n    pub f2: i32,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nfn main() {\n    let x = updated_crate::Foo { f1: 123 }; // Error: missing field `f2`\n}\n```\n\nMitigation strategies:\n* Do not add new fields to all-public field structs.\n* Mark structs as [`#[non_exhaustive]`][non_exhaustive] when first introducing\n  a struct to prevent users from using struct literal syntax, and instead\n  provide a constructor method and/or [Default] implementation.\n\n### Minor: adding or removing private fields when at least one already exists {#struct-private-fields-with-private}\n\nIt is safe to add or remove private fields from a struct when the struct\nalready has at least one private field.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[derive(Default)]\npub struct Foo {\n    f1: i32,\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[derive(Default)]\npub struct Foo {\n    f2: f64,\n}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nfn main() {\n    // Cannot access private fields.\n    let x = updated_crate::Foo::default();\n}\n```\n\nThis is safe because existing code cannot use a [struct literal] to construct\nit, nor exhaustively match its contents.\n\nNote that for tuple structs, this is a **major change** if the tuple contains\npublic fields, and the addition or removal of a private field changes the\nindex of any public field.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[derive(Default)]\npub struct Foo(pub i32, i32);\n\n///////////////////////////////////////////////////////////\n// After\n#[derive(Default)]\npub struct Foo(f64, pub i32, i32);\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nfn main() {\n    let x = updated_crate::Foo::default();\n    let y = x.0; // Error: is private\n}\n```\n\n### Minor: going from a tuple struct with all private fields (with at least one field) to a normal struct, or vice versa {#struct-tuple-normal-with-private}\n\nChanging a tuple struct to a normal struct (or vice-versa) is safe if all\nfields are private.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[derive(Default)]\npub struct Foo(i32);\n\n///////////////////////////////////////////////////////////\n// After\n#[derive(Default)]\npub struct Foo {\n    f1: i32,\n}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nfn main() {\n    // Cannot access private fields.\n    let x = updated_crate::Foo::default();\n}\n```\n\nThis is safe because existing code cannot use a [struct literal] to construct\nit, nor match its contents.\n\n### Major: adding new enum variants (without `non_exhaustive`) {#enum-variant-new}\n\nIt is a breaking change to add a new enum variant if the enum does not use the\n[`#[non_exhaustive]`][non_exhaustive] attribute.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub enum E {\n    Variant1,\n}\n\n///////////////////////////////////////////////////////////\n// After\npub enum E {\n    Variant1,\n    Variant2,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nfn main() {\n    use updated_crate::E;\n    let x = E::Variant1;\n    match x { // Error: `E::Variant2` not covered\n        E::Variant1 => {}\n    }\n}\n```\n\nMitigation strategies:\n* When introducing the enum, mark it as [`#[non_exhaustive]`][non_exhaustive]\n  to force users to use [wildcard patterns] to catch new variants.\n\n### Major: adding new fields to an enum variant {#enum-fields-new}\n\nIt is a breaking change to add new fields to an enum variant because all\nfields are public, and constructors and matching will fail to compile.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub enum E {\n    Variant1 { f1: i32 },\n}\n\n///////////////////////////////////////////////////////////\n// After\npub enum E {\n    Variant1 { f1: i32, f2: i32 },\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nfn main() {\n    use updated_crate::E;\n    let x = E::Variant1 { f1: 1 }; // Error: missing f2\n    match x {\n        E::Variant1 { f1 } => {} // Error: missing f2\n    }\n}\n```\n\nMitigation strategies:\n* When introducing the enum, mark the variant as [`non_exhaustive`][non_exhaustive]\n  so that it cannot be constructed or matched without wildcards.\n  ```rust,ignore,skip\n  pub enum E {\n      #[non_exhaustive]\n      Variant1{f1: i32}\n  }\n  ```\n* When introducing the enum, use an explicit struct as a value, where you can\n  have control over the field visibility.\n  ```rust,ignore,skip\n  pub struct Foo {\n     f1: i32,\n     f2: i32,\n  }\n  pub enum E {\n      Variant1(Foo)\n  }\n  ```\n\n### Major: adding a non-defaulted trait item {#trait-new-item-no-default}\n\nIt is a breaking change to add a non-defaulted item to a trait. This will\nbreak any implementors of the trait.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub trait Trait {}\n\n///////////////////////////////////////////////////////////\n// After\npub trait Trait {\n    fn foo(&self);\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Trait;\nstruct Foo;\n\nimpl Trait for Foo {}  // Error: not all trait items implemented\n```\n\nMitigation strategies:\n* Always provide a default implementation or value for new associated trait\n  items.\n* When introducing the trait, use the [sealed trait] technique to prevent\n  users outside of the crate from implementing the trait.\n\n### Major: any change to trait item signatures {#trait-item-signature}\n\nIt is a breaking change to make any change to a trait item signature. This can\nbreak external implementors of the trait.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub trait Trait {\n    fn f(&self, x: i32) {}\n}\n\n///////////////////////////////////////////////////////////\n// After\npub trait Trait {\n    // For sealed traits or normal functions, this would be a minor change\n    // because generalizing with generics strictly expands the possible uses.\n    // But in this case, trait implementations must use the same signature.\n    fn f<V>(&self, x: V) {}\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Trait;\nstruct Foo;\n\nimpl Trait for Foo {\n    fn f(&self, x: i32) {}  // Error: trait declaration has 1 type parameter\n}\n```\n\nMitigation strategies:\n* Introduce new items with default implementations to cover the new\n  functionality instead of modifying existing items.\n* When introducing the trait, use the [sealed trait] technique to prevent\n  users outside of the crate from implementing the trait.\n\n### Possibly-breaking: adding a defaulted trait item {#trait-new-default-item}\n\nIt is usually safe to add a defaulted trait item. However, this can sometimes\ncause a compile error. For example, this can introduce an ambiguity if a\nmethod of the same name exists in another trait.\n\n```rust,ignore\n// Breaking change example\n\n///////////////////////////////////////////////////////////\n// Before\npub trait Trait {}\n\n///////////////////////////////////////////////////////////\n// After\npub trait Trait {\n    fn foo(&self) {}\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Trait;\nstruct Foo;\n\ntrait LocalTrait {\n    fn foo(&self) {}\n}\n\nimpl Trait for Foo {}\nimpl LocalTrait for Foo {}\n\nfn main() {\n    let x = Foo;\n    x.foo(); // Error: multiple applicable items in scope\n}\n```\n\nNote that this ambiguity does *not* exist for name collisions on [inherent\nimplementations], as they take priority over trait items.\n\nSee [trait-object-safety](#trait-object-safety) for a special case to consider\nwhen adding trait items.\n\nMitigation strategies:\n* Some projects may deem this acceptable breakage, particularly if the new\n  item name is unlikely to collide with any existing code. Choose names\n  carefully to help avoid these collisions. Additionally, it may be acceptable\n  to require downstream users to add [disambiguation syntax] to select the\n  correct function when updating the dependency.\n\n### Major: adding a trait item that makes the trait non-object safe {#trait-object-safety}\n\nIt is a breaking change to add a trait item that changes the trait to not be\n[object safe].\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub trait Trait {}\n\n///////////////////////////////////////////////////////////\n// After\npub trait Trait {\n    // An associated const makes the trait not object-safe.\n    const CONST: i32 = 123;\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Trait;\nstruct Foo;\n\nimpl Trait for Foo {}\n\nfn main() {\n    let obj: Box<dyn Trait> = Box::new(Foo); // Error: the trait `Trait` is not dyn compatible\n}\n```\n\nIt is safe to do the converse (making a non-object safe trait into a safe\none).\n\n### Major: adding a type parameter without a default {#trait-new-parameter-no-default}\n\nIt is a breaking change to add a type parameter without a default to a trait.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub trait Trait {}\n\n///////////////////////////////////////////////////////////\n// After\npub trait Trait<T> {}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Trait;\nstruct Foo;\n\nimpl Trait for Foo {}  // Error: missing generics\n```\n\nMitigating strategies:\n* See [adding a defaulted trait type parameter](#trait-new-parameter-default).\n\n### Minor: adding a defaulted trait type parameter {#trait-new-parameter-default}\n\nIt is safe to add a type parameter to a trait as long as it has a default.\nExternal implementors will use the default without needing to specify the\nparameter.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub trait Trait {}\n\n///////////////////////////////////////////////////////////\n// After\npub trait Trait<T = i32> {}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nuse updated_crate::Trait;\nstruct Foo;\n\nimpl Trait for Foo {}\n```\n\n### Possibly-breaking change: adding any inherent items {#impl-item-new}\n\nUsually adding inherent items to an implementation should be safe because\ninherent items take priority over trait items. However, in some cases the\ncollision can cause problems if the name is the same as an implemented trait\nitem with a different signature.\n\n```rust,ignore\n// Breaking change example\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Foo;\n\n///////////////////////////////////////////////////////////\n// After\npub struct Foo;\n\nimpl Foo {\n    pub fn foo(&self) {}\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Foo;\n\ntrait Trait {\n    fn foo(&self, x: i32) {}\n}\n\nimpl Trait for Foo {}\n\nfn main() {\n    let x = Foo;\n    x.foo(1); // Error: this method takes 0 arguments but 1 argument was supplied\n}\n```\n\nNote that if the signatures match, there would not be a compile-time error,\nbut possibly a silent change in runtime behavior (because it is now executing\na different function).\n\nMitigation strategies:\n* Some projects may deem this acceptable breakage, particularly if the new\n  item name is unlikely to collide with any existing code. Choose names\n  carefully to help avoid these collisions. Additionally, it may be acceptable\n  to require downstream users to add [disambiguation syntax] to select the\n  correct function when updating the dependency.\n\n### Major: tightening generic bounds {#generic-bounds-tighten}\n\nIt is a breaking change to tighten generic bounds on a type since this can\nbreak users expecting the looser bounds.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Foo<A> {\n    pub f1: A,\n}\n\n///////////////////////////////////////////////////////////\n// After\npub struct Foo<A: Eq> {\n    pub f1: A,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Foo;\n\nfn main() {\n    let s = Foo { f1: 1.23 }; // Error: the trait bound `{float}: Eq` is not satisfied\n}\n```\n\n### Minor: loosening generic bounds {#generic-bounds-loosen}\n\nIt is safe to loosen the generic bounds on a type, as it only expands what is\nallowed.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Foo<A: Clone> {\n    pub f1: A,\n}\n\n///////////////////////////////////////////////////////////\n// After\npub struct Foo<A> {\n    pub f1: A,\n}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nuse updated_crate::Foo;\n\nfn main() {\n    let s = Foo { f1: 123 };\n}\n```\n\n### Minor: adding defaulted type parameters {#generic-new-default}\n\nIt is safe to add a type parameter to a type as long as it has a default. All\nexisting references will use the default without needing to specify the\nparameter.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#[derive(Default)]\npub struct Foo {}\n\n///////////////////////////////////////////////////////////\n// After\n#[derive(Default)]\npub struct Foo<A = i32> {\n    f1: A,\n}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nuse updated_crate::Foo;\n\nfn main() {\n    let s: Foo = Default::default();\n}\n```\n\n### Minor: generalizing a type to use generics (with identical types) {#generic-generalize-identical}\n\nA struct or enum field can change from a concrete type to a generic type\nparameter, provided that the change results in an identical type for all\nexisting use cases. For example, the following change is permitted:\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Foo(pub u8);\n\n///////////////////////////////////////////////////////////\n// After\npub struct Foo<T = u8>(pub T);\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nuse updated_crate::Foo;\n\nfn main() {\n    let s: Foo = Foo(123);\n}\n```\n\nbecause existing uses of `Foo` are shorthand for `Foo<u8>` which yields the\nidentical field type.\n\n### Major: generalizing a type to use generics (with possibly different types) {#generic-generalize-different}\n\nChanging a struct or enum field from a concrete type to a generic type\nparameter can break if the type can change.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Foo<T = u8>(pub T, pub u8);\n\n///////////////////////////////////////////////////////////\n// After\npub struct Foo<T = u8>(pub T, pub T);\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::Foo;\n\nfn main() {\n    let s: Foo<f32> = Foo(3.14, 123); // Error: mismatched types\n}\n```\n\n### Minor: changing a generic type to a more generic type {#generic-more-generic}\n\nIt is safe to change a generic type to a more generic one. For example, the\nfollowing adds a generic parameter that defaults to the original type, which\nis safe because all existing users will be using the same type for both\nfields, the defaulted parameter does not need to be specified.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Foo<T>(pub T, pub T);\n\n///////////////////////////////////////////////////////////\n// After\npub struct Foo<T, U = T>(pub T, pub U);\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nuse updated_crate::Foo;\n\nfn main() {\n    let s: Foo<f32> = Foo(1.0, 2.0);\n}\n```\n\n### Major: capturing more generic parameters in RPIT {#generic-rpit-capture}\n\nIt is a breaking change to capture additional generic parameters in an [RPIT] (return-position impl trait).\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub fn f<'a, 'b>(x: &'a str, y: &'b str) -> impl Iterator<Item = char> + use<'a> {\n    x.chars()\n}\n\n///////////////////////////////////////////////////////////\n// After\npub fn f<'a, 'b>(x: &'a str, y: &'b str) -> impl Iterator<Item = char> + use<'a, 'b> {\n    x.chars().chain(y.chars())\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nfn main() {\n    let a = String::new();\n    let b = String::new();\n    let iter = updated_crate::f(&a, &b);\n    drop(b); // Error: cannot move out of `b` because it is borrowed\n}\n```\n\nAdding generic parameters to an RPIT places additional constraints on how the resulting type may be used.\n\nNote that there are implicit captures when the `use<>` syntax is not specified. In Rust 2021 and earlier editions, the lifetime parameters are only captured if they appear syntactically within a bound in the RPIT type signature. Starting in Rust 2024, all lifetime parameters are unconditionally captured. This means that starting in Rust 2024, the default is maximally compatible, requiring you to be explicit when you want to capture less, which is a SemVer commitment.\n\nSee the [edition guide][rpit-capture-guide] and the [reference][rpit-reference] for more information on RPIT capturing.\n\nIt is a minor change to capture fewer generic parameters in an RPIT.\n\n> Note: All in-scope type and const generic parameters must be either implicitly captured (no `+ use<…>` specified) or explicitly captured (must be listed in `+ use<…>`), and thus currently it is not allowed to change what is captured of those kinds of generics.\n\n[RPIT]: ../../reference/types/impl-trait.md#abstract-return-types\n[rpit-capture-guide]: ../../edition-guide/rust-2024/rpit-lifetime-capture.html\n[rpit-reference]: ../../reference/types/impl-trait.md#capturing\n\n### Major: adding/removing function parameters {#fn-change-arity}\n\nChanging the arity of a function is a breaking change.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub fn foo() {}\n\n///////////////////////////////////////////////////////////\n// After\npub fn foo(x: i32) {}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nfn main() {\n    updated_crate::foo(); // Error: this function takes 1 argument\n}\n```\n\nMitigating strategies:\n* Introduce a new function with the new signature and possibly\n  [deprecate][deprecated] the old one.\n* Introduce functions that take a struct argument, where the struct is built\n  with the builder pattern. This allows new fields to be added to the struct\n  in the future.\n\n### Possibly-breaking: introducing a new function type parameter {#fn-generic-new}\n\nUsually, adding a non-defaulted type parameter is safe, but in some\ncases it can be a breaking change:\n\n```rust,ignore\n// Breaking change example\n\n///////////////////////////////////////////////////////////\n// Before\npub fn foo<T>() {}\n\n///////////////////////////////////////////////////////////\n// After\npub fn foo<T, U>() {}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::foo;\n\nfn main() {\n    foo::<u8>(); // Error: function takes 2 generic arguments but 1 generic argument was supplied\n}\n```\n\nHowever, such explicit calls are rare enough (and can usually be written in\nother ways) that this breakage is usually acceptable. One should take into\naccount how likely it is that the function in question is being called with\nexplicit type arguments.\n\n### Minor: generalizing a function to use generics (supporting original type) {#fn-generalize-compatible}\n\nThe type of a parameter to a function, or its return value, can be\n*generalized* to use generics, including by introducing a new type parameter,\nas long as it can be instantiated to the original type. For example, the\nfollowing changes are allowed:\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub fn foo(x: u8) -> u8 {\n    x\n}\npub fn bar<T: Iterator<Item = u8>>(t: T) {}\n\n///////////////////////////////////////////////////////////\n// After\nuse std::ops::Add;\npub fn foo<T: Add>(x: T) -> T {\n    x\n}\npub fn bar<T: IntoIterator<Item = u8>>(t: T) {}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nuse updated_crate::{bar, foo};\n\nfn main() {\n    foo(1);\n    bar(vec![1, 2, 3].into_iter());\n}\n```\n\nbecause all existing uses are instantiations of the new signature.\n\nPerhaps somewhat surprisingly, generalization applies to trait objects as\nwell, given that every trait implements itself:\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub trait Trait {}\npub fn foo(t: &dyn Trait) {}\n\n///////////////////////////////////////////////////////////\n// After\npub trait Trait {}\npub fn foo<T: Trait + ?Sized>(t: &T) {}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\nuse updated_crate::{foo, Trait};\n\nstruct Foo;\nimpl Trait for Foo {}\n\nfn main() {\n    let obj = Foo;\n    foo(&obj);\n}\n```\n\n(The use of `?Sized` is essential; otherwise you couldn't recover the original\nsignature.)\n\nIntroducing generics in this way can potentially create type inference\nfailures. These are usually rare, and may be acceptable breakage for some\nprojects, as this can be fixed with additional type annotations.\n\n```rust,ignore\n// Breaking change example\n\n///////////////////////////////////////////////////////////\n// Before\npub fn foo() -> i32 {\n    0\n}\n\n///////////////////////////////////////////////////////////\n// After\npub fn foo<T: Default>() -> T {\n    Default::default()\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::foo;\n\nfn main() {\n    let x = foo(); // Error: type annotations needed\n}\n```\n\n### Major: generalizing a function to use generics with type mismatch {#fn-generalize-mismatch}\n\nIt is a breaking change to change a function parameter or return type if the\ngeneric type constrains or changes the types previously allowed. For example,\nthe following adds a generic constraint that may not be satisfied by existing\ncode:\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub fn foo(x: Vec<u8>) {}\n\n///////////////////////////////////////////////////////////\n// After\npub fn foo<T: Copy + IntoIterator<Item = u8>>(x: T) {}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::foo;\n\nfn main() {\n    foo(vec![1, 2, 3]); // Error: `Copy` is not implemented for `Vec<u8>`\n}\n```\n\n### Minor: making an `unsafe` function safe {#fn-unsafe-safe}\n\nA previously `unsafe` function can be made safe without breaking code.\n\nNote however that it may cause the [`unused_unsafe`][unused_unsafe] lint to\ntrigger as in the example below, which will cause local crates that have\nspecified `#![deny(warnings)]` to stop compiling. Per [introducing new\nlints](#new-lints), it is allowed for updates to introduce new warnings.\n\nGoing the other way (making a safe function `unsafe`) is a breaking change.\n\n```rust,ignore\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub unsafe fn foo() {}\n\n///////////////////////////////////////////////////////////\n// After\npub fn foo() {}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will trigger a lint.\nuse updated_crate::foo;\n\nunsafe fn bar(f: unsafe fn()) {\n    f()\n}\n\nfn main() {\n    unsafe { foo() }; // The `unused_unsafe` lint will trigger here\n    unsafe { bar(foo) };\n}\n```\n\nMaking a previously `unsafe` associated function or method on structs / enums\nsafe is also a minor change, while the same is not true for associated\nfunction on traits (see [any change to trait item signatures](#trait-item-signature)).\n\n### Major: switching from `no_std` support to requiring `std` {#attr-no-std-to-std}\n\nIf your library specifically supports a [`no_std`] environment, it is a\nbreaking change to make a new release that requires `std`.\n\n```rust,ignore,skip\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\n#![no_std]\npub fn foo() {}\n\n///////////////////////////////////////////////////////////\n// After\npub fn foo() {\n    std::time::SystemTime::now();\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\n// This will fail to link for no_std targets because they don't have a `std` crate.\n#![no_std]\nuse updated_crate::foo;\n\nfn example() {\n    foo();\n}\n```\n\nMitigation strategies:\n* A common idiom to avoid this is to include a `std` [Cargo feature] that\n  optionally enables `std` support, and when the feature is off, the library\n  can be used in a `no_std` environment.\n\n### Major: adding `non_exhaustive` to an existing enum, variant, or struct with no private fields {#attr-adding-non-exhaustive}\n\nMaking items [`#[non_exhaustive]`][non_exhaustive] changes how they may\nbe used outside the crate where they are defined:\n\n- Non-exhaustive structs and enum variants cannot be constructed\n  using [struct literal] syntax, including [functional update syntax].\n- Pattern matching on non-exhaustive structs requires `..` and\n  matching on enums does not count towards exhaustiveness.\n- Casting enum variants to their discriminant with `as` is not allowed.\n\nStructs with private fields cannot be constructed using [struct literal] syntax\nregardless of whether [`#[non_exhaustive]`][non_exhaustive] is used.\nAdding [`#[non_exhaustive]`][non_exhaustive] to such a struct is not\na breaking change.\n\n```rust,ignore\n// MAJOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub struct Foo {\n    pub bar: usize,\n}\n\npub enum Bar {\n    X,\n    Y(usize),\n    Z { a: usize },\n}\n\npub enum Quux {\n    Var,\n}\n\n///////////////////////////////////////////////////////////\n// After\n#[non_exhaustive]\npub struct Foo {\n    pub bar: usize,\n}\n\npub enum Bar {\n    #[non_exhaustive]\n    X,\n\n    #[non_exhaustive]\n    Y(usize),\n\n    #[non_exhaustive]\n    Z { a: usize },\n}\n\n#[non_exhaustive]\npub enum Quux {\n    Var,\n}\n\n///////////////////////////////////////////////////////////\n// Example usage that will break.\nuse updated_crate::{Bar, Foo, Quux};\n\nfn main() {\n    let foo = Foo { bar: 0 }; // Error: cannot create non-exhaustive struct using struct expression\n\n    let bar_x = Bar::X; // Error: unit variant `X` is private\n    let bar_y = Bar::Y(0); // Error: tuple variant `Y` is private\n    let bar_z = Bar::Z { a: 0 }; // Error: cannot create non-exhaustive variant using struct expression\n\n    let q = Quux::Var;\n    match q {\n        Quux::Var => 0,\n        // Error: non-exhaustive patterns: `_` not covered\n    };\n}\n```\n\nMitigation strategies:\n* Mark structs, enums, and enum variants as\n  [`#[non_exhaustive]`][non_exhaustive] when first introducing them,\n  rather than adding [`#[non_exhaustive]`][non_exhaustive] later on.\n\n## Tooling and environment compatibility\n\n### Possibly-breaking: changing the minimum version of Rust required {#env-new-rust}\n\nIntroducing the use of new features in a new release of Rust can break\nprojects that are using older versions of Rust. This also includes using new\nfeatures in a new release of Cargo, and requiring the use of a nightly-only\nfeature in a crate that previously worked on stable.\n\nIt is generally recommended to treat this as a minor change, rather than as\na major change, for [various reasons][msrv-is-minor]. It\nis usually relatively easy to update to a newer version of Rust. Rust also has\na rapid 6-week release cycle, and some projects will provide compatibility\nwithin a window of releases (such as the current stable release plus N\nprevious releases). Just keep in mind that some large projects may not be able\nto update their Rust toolchain rapidly.\n\nMitigation strategies:\n* Document your package’s minimum-supported Rust version by setting\n  [`package.rust-version`], allowing Cargo’s dependency resolution to\n  attempt to [select older versions of your package] when needed.\n  Be sure to consider the [support expectations] when doing so.\n* Use [Cargo features] to make the new features opt-in.\n* Provide a large window of support for older releases.\n* Copy the source of new standard library items if possible so that you\n  can continue to use an older version but take advantage of the new feature.\n* Provide a separate branch of older minor releases that can receive backports\n  of important bugfixes.\n* Keep an eye out for the [`[cfg(version(..))]`][cfg-version] and\n  [`#[cfg(accessible(..))]`][cfg-accessible] features which provide an opt-in\n  mechanism for new features. These are currently unstable and only available\n  in the nightly channel.\n\n[select older versions of your package]: resolver.md#rust-version\n[support expectations]: rust-version.md#support-expectations\n\n### Possibly-breaking: changing the platform and environment requirements {#env-change-requirements}\n\nThere is a very wide range of assumptions a library makes about the\nenvironment that it runs in, such as the host platform, operating system\nversion, available services, filesystem support, etc. It can be a breaking\nchange if you make a new release that restricts what was previously supported,\nfor example requiring a newer version of an operating system. These changes\ncan be difficult to track, since you may not always know if a change breaks in\nan environment that is not automatically tested.\n\nSome projects may deem this acceptable breakage, particularly if the breakage\nis unlikely for most users, or the project doesn't have the resources to\nsupport all environments. Another notable situation is when a vendor\ndiscontinues support for some hardware or OS, the project may deem it\nreasonable to also discontinue support.\n\nMitigation strategies:\n* Document the platforms and environments you specifically support.\n* Test your code on a wide range of environments in CI.\n\n### Minor: introducing new lints {#new-lints}\n\nSome changes to a library may cause new lints to be triggered in users of that library.\nThis should generally be considered a compatible change.\n\n```rust,ignore,dont-deny\n// MINOR CHANGE\n\n///////////////////////////////////////////////////////////\n// Before\npub fn foo() {}\n\n///////////////////////////////////////////////////////////\n// After\n#[deprecated]\npub fn foo() {}\n\n///////////////////////////////////////////////////////////\n// Example use of the library that will safely work.\n\nfn main() {\n    updated_crate::foo(); // Warning: use of deprecated function\n}\n```\n\nBeware that it may be possible for this to technically cause a project to fail if they have explicitly denied the warning, and the updated crate is a direct dependency.\nDenying warnings should be done with care and the understanding that new lints may be introduced over time.\nHowever, library authors should be cautious about introducing new warnings and may want to consider the potential impact on their users.\n\nThe following lints are examples of those that may be introduced when updating a dependency:\n\n* [`deprecated`][deprecated-lint] --- Introduced when a dependency adds the [`#[deprecated]` attribute][deprecated] to an item you are using.\n* [`unused_must_use`] --- Introduced when a dependency adds the [`#[must_use]` attribute][must-use-attr] to an item where you are not consuming the result.\n* [`unused_unsafe`] --- Introduced when a dependency *removes* the `unsafe` qualifier from a function, and that is the only unsafe function called in an unsafe block.\n\nAdditionally, updating `rustc` to a new version may introduce new lints.\n\nTransitive dependencies which introduce new lints should not usually cause a failure because Cargo uses [`--cap-lints`](../../rustc/lints/levels.html#capping-lints) to suppress all lints in dependencies.\n\nMitigating strategies:\n* If you build with warnings denied, understand you may need to deal with resolving new warnings whenever you update your dependencies.\n  If using RUSTFLAGS to pass `-Dwarnings`, also add the `-A` flag to allow lints that are likely to cause issues, such as `-Adeprecated`.\n* Introduce deprecations behind a [feature][Cargo features].\n  For example `#[cfg_attr(feature = \"deprecated\", deprecated=\"use bar instead\")]`.\n  Then, when you plan to remove an item in a future SemVer breaking change, you can communicate with your users that they should enable the `deprecated` feature *before* updating to remove the use of the deprecated items.\n  This allows users to choose when to respond to deprecations without needing to immediately respond to them.\n  A downside is that it can be difficult to communicate to users that they need to take these manual steps to prepare for a major update.\n\n[`unused_must_use`]: ../../rustc/lints/listing/warn-by-default.html#unused-must-use\n[deprecated-lint]: ../../rustc/lints/listing/warn-by-default.html#deprecated\n[must-use-attr]: ../../reference/attributes/diagnostics.html#the-must_use-attribute\n[`unused_unsafe`]: ../../rustc/lints/listing/warn-by-default.html#unused-unsafe\n\n### Cargo\n\n#### Minor: adding a new Cargo feature {#cargo-feature-add}\n\nIt is usually safe to add new [Cargo features]. If the feature introduces new\nchanges that cause a breaking change, this can cause difficulties for projects\nthat have stricter backwards-compatibility needs. In that scenario, avoid\nadding the feature to the \"default\" list, and possibly document the\nconsequences of enabling the feature.\n\n```toml\n# MINOR CHANGE\n\n###########################################################\n# Before\n[features]\n# ..empty\n\n###########################################################\n# After\n[features]\nstd = []\n```\n\n#### Major: removing a Cargo feature {#cargo-feature-remove}\n\nIt is usually a breaking change to remove [Cargo features]. This will cause\nan error for any project that enabled the feature.\n\n```toml\n# MAJOR CHANGE\n\n###########################################################\n# Before\n[features]\nlogging = []\n\n###########################################################\n# After\n[dependencies]\n# ..logging removed\n```\n\nMitigation strategies:\n* Clearly document your features. If there is an internal or experimental\n  feature, mark it as such, so that users know the status of the feature.\n* Leave the old feature in `Cargo.toml`, but otherwise remove its\n  functionality. Document that the feature is deprecated, and remove it in a\n  future major SemVer release.\n\n#### Major: removing a feature from a feature list if that changes functionality or public items {#cargo-feature-remove-another}\n\nIf removing a feature from another feature, this can break existing users if\nthey are expecting that functionality to be available through that feature.\n\n```toml\n# Breaking change example\n\n###########################################################\n# Before\n[features]\ndefault = [\"std\"]\nstd = []\n\n###########################################################\n# After\n[features]\ndefault = []  # This may cause packages to fail if they are expecting std to be enabled.\nstd = []\n```\n\n#### Possibly-breaking: removing an optional dependency {#cargo-remove-opt-dep}\n\nRemoving an [optional dependency][opt-dep] can break a project using your library because\nanother project may be enabling that dependency via [Cargo features].\n\nWhen there is an optional dependency, cargo implicitly defines a feature of\nthe same name to provide a mechanism to enable the dependency and to check\nwhen it is enabled. This problem can be avoided by using the `dep:` syntax in\nthe `[features]` table, which disables this implicit feature. Using `dep:`\nmakes it possible to hide the existence of optional dependencies under more\nsemantically-relevant names which can be more safely modified.\n\n```toml\n# Breaking change example\n\n###########################################################\n# Before\n[dependencies]\ncurl = { version = \"0.4.31\", optional = true }\n\n###########################################################\n# After\n[dependencies]\n# ..curl removed\n```\n\n```toml\n# MINOR CHANGE\n#\n# This example shows how to avoid breaking changes with optional dependencies.\n\n###########################################################\n# Before\n[dependencies]\ncurl = { version = \"0.4.31\", optional = true }\n\n[features]\nnetworking = [\"dep:curl\"]\n\n###########################################################\n# After\n[dependencies]\n# Here, one optional dependency was replaced with another.\nhyper = { version = \"0.14.27\", optional = true }\n\n[features]\nnetworking = [\"dep:hyper\"]\n```\n\nMitigation strategies:\n* Use the `dep:` syntax in the `[features]` table to avoid exposing optional\n  dependencies in the first place. See [optional dependencies][opt-dep] for\n  more information.\n* Clearly document your features. If the optional dependency is not included\n  in the documented list of features, then you may decide to consider it safe\n  to change undocumented entries.\n* Leave the optional dependency, and just don't use it within your library.\n* Replace the optional dependency with a [Cargo feature] that does nothing,\n  and document that it is deprecated.\n* Use high-level features which enable optional dependencies, and document\n  those as the preferred way to enable the extended functionality. For\n  example, if your library has optional support for something like\n  \"networking\", create a generic feature name \"networking\" that enables the\n  optional dependencies necessary to implement \"networking\". Then document the\n  \"networking\" feature.\n\n[opt-dep]: features.md#optional-dependencies\n\n#### Minor: changing dependency features {#cargo-change-dep-feature}\n\nIt is usually safe to change the features on a dependency, as long as the\nfeature does not introduce a breaking change.\n\n```toml\n# MINOR CHANGE\n\n###########################################################\n# Before\n[dependencies]\nrand = { version = \"0.7.3\", features = [\"small_rng\"] }\n\n\n###########################################################\n# After\n[dependencies]\nrand = \"0.7.3\"\n```\n\n#### Minor: adding dependencies {#cargo-dep-add}\n\nIt is usually safe to add new dependencies, as long as the new dependency\ndoes not introduce new requirements that result in a breaking change.\nFor example, adding a new dependency that requires nightly in a project\nthat previously worked on stable is a major change.\n\n```toml\n# MINOR CHANGE\n\n###########################################################\n# Before\n[dependencies]\n# ..empty\n\n###########################################################\n# After\n[dependencies]\nlog = \"0.4.11\"\n```\n\n## Application compatibility\n\nCargo projects may also include executable binaries which have their own\ninterfaces (such as a CLI interface, OS-level interaction, etc.). Since these\nare part of the Cargo package, they often use and share the same version as\nthe package. You will need to decide if and how you want to employ a SemVer\ncontract with your users in the changes you make to your application. The\npotential breaking and compatible changes to an application are too numerous\nto list, so you are encouraged to use the spirit of the [SemVer] spec to guide\nyour decisions on how to apply versioning to your application, or at least\ndocument what your commitments are.\n\n[`cfg` attribute]: ../../reference/conditional-compilation.md#the-cfg-attribute\n[`no_std`]: ../../reference/names/preludes.html#the-no_std-attribute\n[`package.rust-version`]: rust-version.md\n[`pub use`]: ../../reference/items/use-declarations.html\n[Cargo feature]: features.md\n[Cargo features]: features.md\n[cfg-accessible]: https://github.com/rust-lang/rust/issues/64797\n[cfg-version]: https://github.com/rust-lang/rust/issues/64796\n[conditional compilation]: ../../reference/conditional-compilation.md\n[Default]: ../../std/default/trait.Default.html\n[deprecated]: ../../reference/attributes/diagnostics.html#the-deprecated-attribute\n[disambiguation syntax]: ../../reference/expressions/call-expr.html#disambiguating-function-calls\n[functional update syntax]: ../../reference/expressions/struct-expr.html#functional-update-syntax\n[inherent implementations]: ../../reference/items/implementations.html#inherent-implementations\n[items]: ../../reference/items.html\n[non_exhaustive]: ../../reference/attributes/type_system.html#the-non_exhaustive-attribute\n[object safe]: ../../reference/items/traits.html#object-safety\n[rust-feature]: https://doc.rust-lang.org/nightly/unstable-book/\n[sealed trait]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed\n[SemVer]: https://semver.org/\n[struct literal]: ../../reference/expressions/struct-expr.html\n[wildcard patterns]: ../../reference/patterns.html#wildcard-pattern\n[unused_unsafe]: ../../rustc/lints/listing/warn-by-default.html#unused-unsafe\n[msrv-is-minor]: https://github.com/rust-lang/api-guidelines/discussions/231\n"
  },
  {
    "path": "src/doc/src/reference/source-replacement.md",
    "content": "# Source Replacement\n\nThis document is about redirecting communication with [registries]\nor repositories of [git-based dependencies] to another data source, such as a\nserver mirroring the original registry or an exact local copy.\n\nIf you want to patch individual dependencies, see [overriding dependencies] section of this\ndocumentation. If you want to control how Cargo makes network requests, see [`[http]`](config.md#http)\nand [`[net]`](config.md#net) configuration.\n\nA *source* is a provider that contains crates that may be included as\ndependencies for a package. Cargo supports the ability to **replace one source\nwith another** to express strategies such as:\n\n* Vendoring --- custom sources can be defined which represent crates on the local\n  filesystem. These sources are subsets of the source that they're replacing and\n  can be checked into packages if necessary.\n\n* Mirroring --- sources can be replaced with an equivalent version which acts as a\n  cache for crates.io itself.\n\nCargo has a core assumption about source replacement that the source code is\nexactly the same from both sources. Note that this also means that\na replacement source is not allowed to have crates which are not present in the\noriginal source.\n\nAs a consequence, source replacement is not appropriate for situations such as\npatching a dependency or a private registry. Cargo supports patching\ndependencies through the usage of [the `[patch]` key][overriding\ndependencies], and private registry support is described in [the Registries\nchapter][registries].\n\nWhen using source replacement, running commands that need to\ncontact the registry directly[^1] requires passing the `--registry` option. This helps avoid\nany ambiguity about which registry to contact, and will use the authentication\ntoken for the specified registry.\n\n[^1]: Examples of such commands are in [Publishing Commands].\n\n[Publishing Commands]: ../commands/publishing-commands.md\n[overriding dependencies]: overriding-dependencies.md\n[registries]: registries.md\n\n## Configuration\n\nConfiguration of replacement sources is done through [`.cargo/config.toml`][config]\nand the full set of available keys are:\n\n```toml\n# The `source` table is where all keys related to source-replacement\n# are stored.\n[source]\n\n# Under the `source` table are a number of other tables whose keys are a\n# name for the relevant source. For example this section defines a new\n# source, called `my-vendor-source`, which comes from a directory\n# located at `vendor` relative to the directory containing this `.cargo/config.toml`\n# file\n[source.my-vendor-source]\ndirectory = \"vendor\"\n\n# The crates.io default source for crates is available under the name\n# \"crates-io\", and here we use the `replace-with` key to indicate that it's\n# replaced with our source above.\n#\n# The `replace-with` key can also reference an alternative registry name\n# defined in the `[registries]` table.\n[source.crates-io]\nreplace-with = \"my-vendor-source\"\n\n# Each source has its own table where the key is the name of the source\n[source.the-source-name]\n\n# Indicate that `the-source-name` will be replaced with `another-source`,\n# defined elsewhere\nreplace-with = \"another-source\"\n\n# Several kinds of sources can be specified (described in more detail below):\nregistry = \"https://example.com/path/to/index\"\nlocal-registry = \"path/to/registry\"\ndirectory = \"path/to/vendor\"\n\n# Git sources can optionally specify a branch/tag/rev as well\ngit = \"https://example.com/path/to/repo\"\n# branch = \"master\"\n# tag = \"v1.0.1\"\n# rev = \"313f44e8\"\n```\n\n[config]: config.md\n\n## Registry Sources\n\nA \"registry source\" is one that works like crates.io itself. It's an index\nthat conforms to the specification at https://doc.rust-lang.org/cargo/reference/registry-index.html\nwith a configuration file indicating where to download crates from.\n\nRegistry sources can use [either git or sparse HTTP protocol][protocols]:\n\n```toml\n# Git protocol\nregistry = \"ssh://git@example.com/path/to/index.git\"\n\n# Sparse HTTP protocol  \nregistry = \"sparse+https://example.com/path/to/index\"\n\n# HTTPS git protocol\nregistry = \"https://example.com/path/to/index\"\n```\n\n[protocols]: registries.md#registry-protocols\n\n[crates.io index]: registry-index.md\n\n## Local Registry Sources\n\nA \"local registry source\" is intended to be a subset of another registry\nsource, but available on the local filesystem (aka vendoring). Local registries\nare downloaded ahead of time, typically sync'd with a `Cargo.lock`, and are\nmade up of a set of `*.crate` files and an index like the normal registry is.\n\nThe primary way to manage and create local registry sources is through the\n[`cargo-local-registry`][cargo-local-registry] subcommand,\n[available on crates.io][cargo-local-registry] and can be installed with\n`cargo install cargo-local-registry`.\n\n[cargo-local-registry]: https://crates.io/crates/cargo-local-registry\n\nLocal registries are contained within one directory and contain a number of\n`*.crate` files downloaded from crates.io as well as an `index` directory with\nthe same format as the crates.io-index project (populated with just entries for\nthe crates that are present).\n\n## Directory Sources\n\nA \"directory source\" is similar to a local registry source where it contains a\nnumber of crates available on the local filesystem, suitable for vendoring\ndependencies. Directory sources are primarily managed by the `cargo vendor`\nsubcommand.\n\nDirectory sources are distinct from local registries though in that they contain\nthe unpacked version of `*.crate` files, making it more suitable in some\nsituations to check everything into source control. A directory source is just a\ndirectory containing a number of other directories which contain the source code\nfor crates (the unpacked version of `*.crate` files). Currently no restriction\nis placed on the name of each directory.\n\nEach crate in a directory source also has an associated metadata file indicating\nthe checksum of each file in the crate to protect against accidental\nmodifications.\n\n## Git sources\n\nGit sources represent repositories used by [git-based dependencies]. They're\nused to specify which git-based dependencies should be replaced with alternative sources.\n\nGit sources are *not* related to the [git registries][protocols],\nand can't be used to replace registry sources.\n\n[git-based dependencies]: specifying-dependencies.md#specifying-dependencies-from-git-repositories\n"
  },
  {
    "path": "src/doc/src/reference/specifying-dependencies.md",
    "content": "# Specifying Dependencies\n\nYour crates can depend on other libraries from [crates.io] or other\nregistries, `git` repositories, or subdirectories on your local file system.\nYou can also temporarily override the location of a dependency --- for example,\nto be able to test out a bug fix in the dependency that you are working on\nlocally. You can have different dependencies for different platforms, and\ndependencies that are only used during development. Let's take a look at how\nto do each of these.\n\n## Specifying dependencies from crates.io\n\nCargo is configured to look for dependencies on [crates.io] by default. Only\nthe name and a version string are required in this case. In [the cargo\nguide](../guide/index.md), we specified a dependency on the `time` crate:\n\n```toml\n[dependencies]\ntime = \"0.1.12\"\n```\n\nThe version string `\"0.1.12\"` is called a [version requirement](#version-requirement-syntax).\nIt specifies a range of versions that can be selected from when [resolving dependencies](resolver.md).\nIn this case, `\"0.1.12\"` represents the version range `>=0.1.12, <0.2.0`.\nAn update is allowed if it is within that range.\nIn this case, if we ran `cargo update time`, cargo should\nupdate us to version `0.1.13` if it is the latest `0.1.z` release, but would not\nupdate us to `0.2.0`.\n\n## Version requirement syntax\n\n### Default requirements\n\n**Default requirements** specify a minimum version with the ability to update to [SemVer] compatible versions.\nVersions are considered compatible if their left-most non-zero major/minor/patch component is the same.\nThis is different from [SemVer] which considers all pre-1.0.0 packages to be incompatible.\n\n`1.2.3` is an example of a default requirement.\n\n```notrust\n1.2.3  :=  >=1.2.3, <2.0.0\n1.2    :=  >=1.2.0, <2.0.0\n1      :=  >=1.0.0, <2.0.0\n0.2.3  :=  >=0.2.3, <0.3.0\n0.2    :=  >=0.2.0, <0.3.0\n0.0.3  :=  >=0.0.3, <0.0.4\n0.0    :=  >=0.0.0, <0.1.0\n0      :=  >=0.0.0, <1.0.0\n```\n\n### Caret requirements\n\n**Caret requirements** are the default version requirement strategy. \nThis version strategy allows [SemVer] compatible updates.\nThey are specified as version requirements with a leading caret (`^`).\n\n`^1.2.3` is an example of a caret requirement.\n\nLeaving off the caret is a simplified equivalent syntax to using caret requirements.\nWhile caret requirements are the default, it is recommended to use the\nsimplified syntax when possible.\n\n`log = \"^1.2.3\"` is exactly equivalent to `log = \"1.2.3\"`.\n\n### Tilde requirements\n\n**Tilde requirements** specify a minimal version with some ability to update.\nIf you specify a major, minor, and patch version or only a major and minor\nversion, only patch-level changes are allowed. If you only specify a major\nversion, then minor- and patch-level changes are allowed.\n\n`~1.2.3` is an example of a tilde requirement.\n\n```notrust\n~1.2.3  := >=1.2.3, <1.3.0\n~1.2    := >=1.2.0, <1.3.0\n~1      := >=1.0.0, <2.0.0\n```\n\n### Wildcard requirements\n\n**Wildcard requirements** allow for any version where the wildcard is\npositioned.\n\n`*`, `1.*` and `1.2.*` are examples of wildcard requirements.\n\n```notrust\n*     := >=0.0.0\n1.*   := >=1.0.0, <2.0.0\n1.2.* := >=1.2.0, <1.3.0\n```\n\n> **Note**: [crates.io] does not allow bare `*` versions.\n\n### Comparison requirements\n\n**Comparison requirements** allow manually specifying a version range or an\nexact version to depend on.\n\nHere are some examples of comparison requirements:\n\n```notrust\n>= 1.2.0\n> 1\n< 2\n= 1.2.3\n```\n\n<span id=\"multiple-requirements\"></span>\n### Multiple version requirements\n\nAs shown in the examples above, multiple version requirements can be\nseparated with a comma, e.g., `>= 1.2, < 1.5`.\nAll requirements must be satisfied,\nso non-overlapping requirements like `<1.2, ^1.2.2` result in no matching versions.\n\n### Pre-releases\n\nVersion requirements exclude [pre-release versions](manifest.md#the-version-field), such as `1.0.0-alpha`,\nunless specifically asked for.\nFor example, if `1.0.0-alpha` of package\n`foo` is published, then a requirement of `foo = \"1.0\"` will *not* match, and\nwill return an error. The pre-release must be specified, such as `foo =\n\"1.0.0-alpha\"`.\nSimilarly [`cargo install`] will avoid pre-releases unless\nexplicitly asked to install one.\n\nCargo allows \"newer\" pre-releases to be used automatically. For example, if\n`1.0.0-beta` is published, then a requirement `foo = \"1.0.0-alpha\"` will allow\nupdating to the `beta` version. Note that this only works on the same release\nversion, `foo = \"1.0.0-alpha\"` will not allow updating to `foo = \"1.0.1-alpha\"`\nor `foo = \"1.0.1-beta\"`.\n\nCargo will also upgrade automatically to semver-compatible released versions\nfrom prereleases. The requirement `foo = \"1.0.0-alpha\"` will allow updating to\n`foo = \"1.0.0\"` as well as `foo = \"1.2.0\"`.\n\nBeware that pre-release versions can be unstable, and as such care should be\ntaken when using them. Some projects may choose to publish breaking changes\nbetween pre-release versions. It is recommended to not use pre-release\ndependencies in a library if your library is not also a pre-release. Care\nshould also be taken when updating your `Cargo.lock`, and be prepared if a\npre-release update causes issues.\n\n[`cargo install`]: ../commands/cargo-install.md\n\n### Version metadata\n\n[Version metadata](manifest.md#the-version-field), such as `1.0.0+21AF26D3`,\nis ignored and should not be used in version requirements.\n\n> **Recommendation:** When in doubt, use the default version requirement operator.\n>\n> In rare circumstances, a package with a \"public dependency\"\n> (re-exports the dependency or interoperates with it in its public API)\n> that is compatible with multiple semver-incompatible versions\n> (e.g. only uses a simple type that hasn't changed between releases, like an `Id`)\n> may support users choosing which version of the \"public dependency\" to use.\n> In this case, a version requirement like `\">=0.4, <2\"` may be of interest.\n> *However* users of the package will likely run into errors and need to\n> manually select a version of the \"public dependency\" via `cargo update` if\n> they also depend on it as Cargo might pick different versions of the \"public\n> dependency\" when [resolving dependency versions](resolver.md)  (see\n> [#10599]).\n>\n> Avoid constraining the upper bound of a version to be anything less than the\n> next semver incompatible version\n> (e.g. avoid `\">=2.0, <2.4\"`, `\"2.0.*\"`, or `~2.0`),\n> as other packages in the dependency tree may\n> require a newer version, leading to an unresolvable error (see [#9029]).\n> Consider whether controlling the version in your [`Cargo.lock`] would be more\n> appropriate.\n>\n> In some instances this won't matter or the benefits might outweigh the cost, including:\n> - When no one else depends on your package; e.g. it only has a `[[bin]]`\n> - When depending on a pre-release package and wishing to avoid breaking\n>   changes, then a fully specified `\"=1.2.3-alpha.3\"` might be warranted (see\n>   [#2222])\n> - When a library re-exports a proc-macro but the proc-macro generates code that\n>   calls into the re-exporting library, then a fully specified `=1.2.3` might be\n>   warranted to ensure the proc-macro isn't newer than the re-exporting library\n>   and generating code that uses parts of the API that don't exist within the\n>   current version\n\n[`Cargo.lock`]: ../guide/cargo-toml-vs-cargo-lock.md\n[#2222]: https://github.com/rust-lang/cargo/issues/2222\n[#9029]: https://github.com/rust-lang/cargo/issues/9029\n[#10599]: https://github.com/rust-lang/cargo/issues/10599\n\n## Specifying dependencies from other registries\n\nTo specify a dependency from a registry other than [crates.io] set the `registry` key\nto the name of the registry to use:\n\n```toml\n[dependencies]\nsome-crate = { version = \"1.0\", registry = \"my-registry\" }\n```\n\nwhere `my-registry` is the registry name configured in `.cargo/config.toml` file.\nSee the [registries documentation] for more information.\n\n> **Note**: [crates.io] does not allow packages to be published with\n> dependencies on code published outside of [crates.io].\n\n[registries documentation]: registries.md\n\n## Specifying dependencies from `git` repositories\n\nTo depend on a library located in a `git` repository, the minimum information\nyou need to specify is the location of the repository with the `git` key:\n\n```toml\n[dependencies]\nregex = { git = \"https://github.com/rust-lang/regex.git\" }\n```\n\nCargo fetches the `git` repository at that location and traverses the file tree to find\n`Cargo.toml` file for the requested crate anywhere inside the `git` repository. \nFor example, `regex-lite` and `regex-syntax` are members of `rust-lang/regex` repo\nand can be referred to by the repo's root URL (`https://github.com/rust-lang/regex.git`)\nregardless of where in the file tree they reside.\n\n```toml\nregex-lite   = { git = \"https://github.com/rust-lang/regex.git\" }\nregex-syntax = { git = \"https://github.com/rust-lang/regex.git\" }\n```\n\nThe above rule does not apply to [`path` dependencies](#specifying-path-dependencies).\n\n### Choice of commit\n\nCargo assumes that we intend to use the latest commit on the default branch to build\nour package if we only specify the repo URL, as in the examples above.\n\nYou can combine the `git` key with the `rev`, `tag`, or `branch` keys to be more specific about\nwhich commit to use. Here's an example of using the latest commit on a branch named `next`:\n\n```toml\n[dependencies]\nregex = { git = \"https://github.com/rust-lang/regex.git\", branch = \"next\" }\n```\n\nAnything that is not a branch or a tag falls under `rev` key. This can be a commit\nhash like `rev = \"4c59b707\"`, or a named reference exposed by the remote\nrepository such as `rev = \"refs/pull/493/head\"`. \n\nWhat references are available for the `rev` key varies by where the repo is hosted.  \nGitHub exposes a reference to the most recent commit of every pull request as in the example above.\nOther git hosts may provide something equivalent under a different naming scheme.\n\n**More `git` dependency examples:**\n\n```toml\n# .git suffix can be omitted if the host accepts such URLs - both examples work the same\nregex = { git = \"https://github.com/rust-lang/regex\" }\nregex = { git = \"https://github.com/rust-lang/regex.git\" }\n\n# a commit with a particular tag\nregex = { git = \"https://github.com/rust-lang/regex.git\", tag = \"1.10.3\" }\n\n# a commit by its SHA1 hash\nregex = { git = \"https://github.com/rust-lang/regex.git\", rev = \"0c0990399270277832fbb5b91a1fa118e6f63dba\" }\n\n# HEAD commit of PR 493\nregex = { git = \"https://github.com/rust-lang/regex.git\", rev = \"refs/pull/493/head\" }\n\n# INVALID EXAMPLES\n\n# specifying the commit after # ignores the commit ID and generates a warning\nregex = { git = \"https://github.com/rust-lang/regex.git#4c59b70\" }\n\n# git and path cannot be used at the same time\nregex = { git = \"https://github.com/rust-lang/regex.git#4c59b70\", path = \"../regex\" }\n```\n\nCargo locks the commits of `git` dependencies in `Cargo.lock` file at the time of their addition\nand checks for updates only when you run `cargo update` command.\n\n### The role of the `version` key\n\nThe `version` key always implies that the package is available in a registry,\nregardless of the presence of `git` or `path` keys.\n\nThe `version` key does _not_ affect which commit is used when Cargo retrieves the `git` dependency,\nbut Cargo checks the version information in the dependency's `Cargo.toml` file \nagainst the `version` key and raises an error if the check fails.\n\nIn this example, Cargo retrieves the HEAD commit of the branch called `next` from Git and checks if the crate's version\nis compatible with `version = \"1.10.3\"`:\n\n```toml\n[dependencies]\nregex = { version = \"1.10.3\", git = \"https://github.com/rust-lang/regex.git\", branch = \"next\" }\n```\n\n`version`, `git`, and `path` keys are considered separate locations for resolving the dependency. \nSee [Multiple locations](#multiple-locations) section below for detailed explanations.\n\n> **Note**: [crates.io] does not allow packages to be published with\n> dependencies on code published outside of [crates.io] itself\n> ([dev-dependencies] are ignored). See the [Multiple\n> locations](#multiple-locations) section for a fallback alternative for `git`\n> and `path` dependencies.\n\n### Git submodules\n\nWhen cloning a `git` dependency,\nCargo automatically fetches its submodules recursively\nso that all required code is available for the build.\n\nTo skip fetching submodules unrelated to the build,\nyou can set [`submodule.<name>.update = none`][submodule-update] in the dependency repo's `.gitmodules`.\nThis requires write access to the repo and will disable submodule updates more generally.\n\n[submodule-update]: https://git-scm.com/docs/gitmodules#Documentation/gitmodules.txt-submodulenameupdate\n\n### Accessing private Git repositories\n\nSee [Git Authentication](../appendix/git-authentication.md) for help with Git authentication for private repos.\n\n## Specifying path dependencies\n\nOver time, our `hello_world` package from [the guide](../guide/index.md) has\ngrown significantly in size! It’s gotten to the point that we probably want to\nsplit out a separate crate for others to use. To do this Cargo supports **path\ndependencies** which are typically sub-crates that live within one repository.\nLet’s start by making a new crate inside of our `hello_world` package:\n\n```console\n# inside of hello_world/\n$ cargo new hello_utils\n```\n\nThis will create a new folder `hello_utils` inside of which a `Cargo.toml` and\n`src` folder are ready to be configured. To tell Cargo about this, open\nup `hello_world/Cargo.toml` and add `hello_utils` to your dependencies:\n\n```toml\n[dependencies]\nhello_utils = { path = \"hello_utils\" }\n```\n\nThis tells Cargo that we depend on a crate called `hello_utils` which is found\nin the `hello_utils` folder, relative to the `Cargo.toml` file it’s written in.\n\nThe next `cargo build` will automatically build `hello_utils` and\nall of its dependencies.\n\n### No local path traversal\n\nThe local paths must point to the exact folder with the dependency's `Cargo.toml`.\nUnlike with `git` dependencies, Cargo does not traverse local paths.\nFor example, if `regex-lite` and `regex-syntax` are members of a\nlocally cloned `rust-lang/regex` repo, they have to be referred to by the full path:\n\n```toml\n# git key accepts the repo root URL and Cargo traverses the tree to find the crate\n[dependencies]\nregex-lite   = { git = \"https://github.com/rust-lang/regex.git\" }\nregex-syntax = { git = \"https://github.com/rust-lang/regex.git\" }\n\n# path key requires the member name to be included in the local path\n[dependencies]\nregex-lite   = { path = \"../regex/regex-lite\" }\nregex-syntax = { path = \"../regex/regex-syntax\" }\n```\n\n### Local paths in published crates\n\nCrates that use dependencies specified with only a path are not\npermitted on [crates.io].\n\nIf we wanted to publish our `hello_world` crate,\nwe would need to publish a version of `hello_utils` to [crates.io] as a separate crate\nand specify its version in the dependencies line of `hello_world`:\n\n```toml\n[dependencies]\nhello_utils = { path = \"hello_utils\", version = \"0.1.0\" }\n```\n\nThe use of `path` and `version` keys together is explained in the [Multiple locations](#multiple-locations) section.\n\n> **Note**: [crates.io] does not allow packages to be published with\n> dependencies on code outside of [crates.io], except for [dev-dependencies].\n> See the [Multiple locations](#multiple-locations) section\n> for a fallback alternative for `git` and `path` dependencies.\n\n## Multiple locations\n\nIt is possible to specify both a registry version and a `git` or `path`\nlocation. The `git` or `path` dependency will be used locally (in which case\nthe `version` is checked against the local copy), and when published to a\nregistry like [crates.io], it will use the registry version. Other\ncombinations are not allowed. Examples:\n\n```toml\n[dependencies]\n# Uses `my-bitflags` when used locally, and uses\n# version 1.0 from crates.io when published.\nbitflags = { path = \"my-bitflags\", version = \"1.0\" }\n\n# Uses the given git repo when used locally, and uses\n# version 1.0 from crates.io when published.\nsmallvec = { git = \"https://github.com/servo/rust-smallvec.git\", version = \"1.0\" }\n\n# Note: if a version doesn't match, Cargo will fail to compile!\n```\n\nOne example where this can be useful is when you have split up a library into\nmultiple packages within the same workspace. You can then use `path`\ndependencies to point to the local packages within the workspace to use the\nlocal version during development, and then use the [crates.io] version once it\nis published. This is similar to specifying an\n[override](overriding-dependencies.md), but only applies to this one\ndependency declaration.\n\n## Platform specific dependencies\n\nPlatform-specific dependencies take the same format, but are listed under a\n`target` section. Normally Rust-like [`#[cfg]`\nsyntax](../../reference/conditional-compilation.html) will be used to define\nthese sections:\n\n```toml\n[target.'cfg(windows)'.dependencies]\nwinhttp = \"0.4.0\"\n\n[target.'cfg(unix)'.dependencies]\nopenssl = \"1.0.1\"\n\n[target.'cfg(target_arch = \"x86\")'.dependencies]\nnative-i686 = { path = \"native/i686\" }\n\n[target.'cfg(target_arch = \"x86_64\")'.dependencies]\nnative-x86_64 = { path = \"native/x86_64\" }\n```\n\nLike with Rust, the syntax here supports the `not`, `any`, and `all` operators\nto combine various cfg name/value pairs.\n\nIf you want to know which cfg targets are available on your platform, run\n`rustc --print=cfg` from the command line. If you want to know which `cfg`\ntargets are available for another platform, such as 64-bit Windows,\nrun `rustc --print=cfg --target=x86_64-pc-windows-msvc`.\n\nUnlike in your Rust source code, you cannot use\n`[target.'cfg(feature = \"fancy-feature\")'.dependencies]` to add dependencies\nbased on optional features. Use [the `[features]` section](features.md)\ninstead:\n\n```toml\n[dependencies]\nfoo = { version = \"1.0\", optional = true }\nbar = { version = \"1.0\", optional = true }\n\n[features]\nfancy-feature = [\"foo\", \"bar\"]\n```\n\nThe same applies to `cfg(debug_assertions)`, `cfg(test)` and `cfg(proc_macro)`.\nThese values will not work as expected and will always have the default value\nreturned by `rustc --print=cfg`.\nThere is currently no way to add dependencies based on these configuration values.\n\nIn addition to `#[cfg]` syntax, Cargo also supports listing out the full target\nthe dependencies would apply to:\n\n```toml\n[target.x86_64-pc-windows-gnu.dependencies]\nwinhttp = \"0.4.0\"\n\n[target.i686-unknown-linux-gnu.dependencies]\nopenssl = \"1.0.1\"\n```\n\n### Custom target specifications\n\nIf you’re using a custom target specification (such as `--target\nfoo/bar.json`), use the base filename without the `.json` extension:\n\n```toml\n[target.bar.dependencies]\nwinhttp = \"0.4.0\"\n\n[target.my-special-i686-platform.dependencies]\nopenssl = \"1.0.1\"\nnative = { path = \"native/i686\" }\n```\n\n> **Note**: Custom target specifications are not usable on the stable channel.\n\n## Development dependencies\n\nYou can add a `[dev-dependencies]` section to your `Cargo.toml` whose format\nis equivalent to `[dependencies]`:\n\n```toml\n[dev-dependencies]\ntempdir = \"0.3\"\n```\n\nDev-dependencies are not used when compiling\na package for building, but are used for compiling tests, examples, and\nbenchmarks.\n\nThese dependencies are *not* propagated to other packages which depend on this\npackage.\n\nYou can also have target-specific development dependencies by using\n`dev-dependencies` in the target section header instead of `dependencies`. For\nexample:\n\n```toml\n[target.'cfg(unix)'.dev-dependencies]\nmio = \"0.0.1\"\n```\n\n> **Note**: When a package is published, only dev-dependencies that specify a\n> `version` will be included in the published crate. For most use cases,\n> dev-dependencies are not needed when published, though some users (like OS\n> packagers) may want to run tests within a crate, so providing a `version` if\n> possible can still be beneficial.\n\n## Build dependencies\n\nYou can depend on other Cargo-based crates for use in your build scripts.\nDependencies are declared through the `build-dependencies` section of the\nmanifest:\n\n```toml\n[build-dependencies]\ncc = \"1.0.3\"\n```\n\n\nYou can also have target-specific build dependencies by using\n`build-dependencies` in the target section header instead of `dependencies`. For\nexample:\n\n```toml\n[target.'cfg(unix)'.build-dependencies]\ncc = \"1.0.3\"\n```\n\nIn this case, the dependency will only be built when the host platform matches the\nspecified target.\n\nThe build script **does not** have access to the dependencies listed\nin the `dependencies` or `dev-dependencies` section. Build\ndependencies will likewise not be available to the package itself\nunless listed under the `dependencies` section as well. A package\nitself and its build script are built separately, so their\ndependencies need not coincide. Cargo is kept simpler and cleaner by\nusing independent dependencies for independent purposes.\n\n## Choosing features\n\nIf a package you depend on offers conditional features, you can\nspecify which to use:\n\n```toml\n[dependencies.awesome]\nversion = \"1.3.5\"\ndefault-features = false # do not include the default features, and optionally\n                         # cherry-pick individual features\nfeatures = [\"secure-password\", \"civet\"]\n```\n\nMore information about features can be found in the [features\nchapter](features.md#dependency-features).\n\n## Renaming dependencies in `Cargo.toml`\n\nWhen writing a `[dependencies]` section in `Cargo.toml` the key you write for a\ndependency typically matches up to the name of the crate you import from in the\ncode. For some projects, though, you may wish to reference the crate with a\ndifferent name in the code regardless of how it's published on crates.io. For\nexample you may wish to:\n\n* Avoid the need to  `use foo as bar` in Rust source.\n* Depend on multiple versions of a crate.\n* Depend on crates with the same name from different registries.\n\nTo support this Cargo supports a `package` key in the `[dependencies]` section\nof which package should be depended on:\n\n```toml\n[package]\nname = \"mypackage\"\nversion = \"0.0.1\"\n\n[dependencies]\nfoo = \"0.1\"\nbar = { git = \"https://github.com/example/project.git\", package = \"foo\" }\nbaz = { version = \"0.1\", registry = \"custom\", package = \"foo\" }\n```\n\nIn this example, three crates are now available in your Rust code:\n\n```rust,ignore\nextern crate foo; // crates.io\nextern crate bar; // git repository\nextern crate baz; // registry `custom`\n```\n\nAll three of these crates have the package name of `foo` in their own\n`Cargo.toml`, so we're explicitly using the `package` key to inform Cargo that\nwe want the `foo` package even though we're calling it something else locally.\nThe `package` key, if not specified, defaults to the name of the dependency\nbeing requested.\n\nNote that if you have an optional dependency like:\n\n```toml\n[dependencies]\nbar = { version = \"0.1\", package = 'foo', optional = true }\n```\n\nyou're depending on the crate `foo` from crates.io, but your crate has a `bar`\nfeature instead of a `foo` feature. That is, names of features take after the\nname of the dependency, not the package name, when renamed.\n\nEnabling transitive dependencies works similarly, for example we could add the\nfollowing to the above manifest:\n\n```toml\n[features]\nlog-debug = ['bar/log-debug'] # using 'foo/log-debug' would be an error!\n```\n\n## Inheriting a dependency from a workspace\n\nDependencies can be inherited from a workspace by specifying the\ndependency in the workspace's [`[workspace.dependencies]`][workspace.dependencies] table.\nAfter that, add it to the `[dependencies]` table with `workspace = true`.\n\nAlong with the `workspace` key, dependencies can also include these keys:\n- [`optional`][optional]: Note that the`[workspace.dependencies]` table is not allowed to specify `optional`.\n- [`features`][features]: These are additive with the features declared in the `[workspace.dependencies]`\n\nOther than `optional` and `features`, inherited dependencies cannot use any other\ndependency key (such as `version` or `default-features`).\n\nDependencies in the `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`, and\n`[target.\"...\".dependencies]` sections support the ability to reference the\n`[workspace.dependencies]` definition of dependencies.\n\n```toml\n[package]\nname = \"bar\"\nversion = \"0.2.0\"\n\n[dependencies]\nregex = { workspace = true, features = [\"unicode\"] }\n\n[build-dependencies]\ncc.workspace = true\n\n[dev-dependencies]\nrand = { workspace = true, optional = true }\n```\n\n\n[SemVer]: https://semver.org\n[crates.io]: https://crates.io/\n[dev-dependencies]: #development-dependencies\n[workspace.dependencies]: workspaces.md#the-dependencies-table\n[optional]: features.md#optional-dependencies\n[features]: features.md\n"
  },
  {
    "path": "src/doc/src/reference/timings.md",
    "content": "# Reporting build timings\nThe `--timings` option gives some information about how long each compilation\ntakes, and tracks concurrency information over time.\n\n```sh\ncargo build --timings\n```\n\nThis writes an HTML report in `target/cargo-timings/cargo-timing.html`. This\nalso writes a copy of the report to the same directory with a timestamp in the\nfilename, if you want to look at older runs.\n\n## Reading the graphs\n\nThere are two tables and two graphs in the output. \n\nThe first table displays the build information of the project, including the \nnumber of units built, the maximum number of concurrency, build time, and the \nversion information of the currently used compiler.\n\n![build-info](../images/build-info.png)\n\nThe \"unit\" graph shows the duration of each unit over time.\nA \"unit\" is a single compiler invocation.\nThere are lines that show which additional units are \"unblocked\" when a unit finishes.\nThat is, it shows the new units that are now allowed to run because their dependencies are all finished.\nHover the mouse over a unit to highlight the lines.\nThis can help visualize the critical path of dependencies.\nThis may change between runs because the units may finish in different orders.\n\nThe \"codegen\" times are highlighted in a lavender color. In some cases, build\npipelining allows units to start when their dependencies are performing code\ngeneration. This information is not always displayed (for example, binary\nunits do not show when code generation starts).\n\nThe \"custom build\" units are `build.rs` scripts, which when run are\nhighlighted in orange.\n\n![build-unit-time](../images/build-unit-time.png)\n\nThe second graph shows Cargo's concurrency over time. The background\nindicates CPU usage. The three lines are:\n- \"Waiting\" (red) --- This is the number of units waiting for a CPU slot to\n  open.\n- \"Inactive\" (blue) --- This is the number of units that are waiting for their\n  dependencies to finish.\n- \"Active\" (green) --- This is the number of units currently running.\n\n![cargo-concurrency-over-time](../images/cargo-concurrency-over-time.png)\n\nNote: This does not show the concurrency in the compiler itself. `rustc`\ncoordinates with Cargo via the \"job server\" to stay within the concurrency\nlimit. This currently mostly applies to the code generation phase.\n\nTips for addressing compile times:\n- Look for slow dependencies.\n    - Check if they have features that you may wish to consider disabling.\n    - Consider trying to remove the dependency completely.\n- Look for a crate being built multiple times with different versions. Try to\n  remove the older versions from the dependency graph.\n- Split large crates into smaller pieces.\n- If there are a large number of crates bottlenecked on a single crate, focus\n  your attention on improving that one crate to improve parallelism.\n\nThe last table lists the total time and \"codegen\" time spent on each unit,\nas well as the features that were enabled during each unit's compilation.\n"
  },
  {
    "path": "src/doc/src/reference/unstable.md",
    "content": "# Unstable Features\n\nExperimental Cargo features are only available on the [nightly channel]. You\nare encouraged to experiment with these features to see if they meet your\nneeds, and if there are any issues or problems. Check the linked tracking\nissues listed below for more information on the feature, and click the GitHub\nsubscribe button if you want future updates.\n\nAfter some period of time, if the feature does not have any major concerns, it\ncan be [stabilized], which will make it available on stable once the current\nnightly release reaches the stable channel (anywhere from 6 to 12 weeks).\n\nThere are three different ways that unstable features can be enabled based on\nhow the feature works:\n\n* New syntax in `Cargo.toml` requires a `cargo-features` key at the top of\n  `Cargo.toml`, before any tables. For example:\n\n  ```toml\n  # This specifies which new Cargo.toml features are enabled.\n  cargo-features = [\"test-dummy-unstable\"]\n\n  [package]\n  name = \"my-package\"\n  version = \"0.1.0\"\n  im-a-teapot = true  # This is a new option enabled by test-dummy-unstable.\n  ```\n\n* New command-line flags, options, and subcommands require the `-Z\n  unstable-options` CLI option to also be included. For example, the new\n  `--artifact-dir` option is only available on nightly:\n\n  ```cargo +nightly build --artifact-dir=out -Z unstable-options```\n\n* `-Z` command-line flags are used to enable new functionality that may not\n  have an interface, or the interface has not yet been designed, or for more\n  complex features that affect multiple parts of Cargo. For example, the\n  [mtime-on-use](#mtime-on-use) feature can be enabled with:\n\n  ```cargo +nightly build -Z mtime-on-use```\n\n  Run `cargo -Z help` to see a list of flags available.\n\n  Anything which can be configured with a `-Z` flag can also be set in the\n  cargo [config file] (`.cargo/config.toml`) in the `unstable` table. For\n  example:\n\n  ```toml\n  [unstable]\n  mtime-on-use = true\n  build-std = [\"core\", \"alloc\"]\n  ```\n\nEach new feature described below should explain how to use it.\n\n*For the latest nightly, see the [nightly version] of this page.*\n\n[config file]: config.md\n[nightly channel]: ../../book/appendix-07-nightly-rust.html\n[stabilized]: https://doc.crates.io/contrib/process/unstable.html#stabilization\n[nightly version]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html\n\n## List of unstable features\n\n* Unstable-specific features\n    * [-Z allow-features](#allow-features) --- Provides a way to restrict which unstable features are used.\n* Build scripts and linking\n    * [Metabuild](#metabuild) --- Provides declarative build scripts.\n    * [Multiple Build Scripts](#multiple-build-scripts) --- Allows use of multiple build scripts.\n    * [Any Build Script Metadata](#any-build-script-metadata) --- Allow any build script to specify env vars via `cargo::metadata=key=value`\n* Resolver and features\n    * [no-index-update](#no-index-update) --- Prevents cargo from updating the index cache.\n    * [avoid-dev-deps](#avoid-dev-deps) --- Prevents the resolver from including dev-dependencies during resolution.\n    * [minimal-versions](#minimal-versions) --- Forces the resolver to use the lowest compatible version instead of the highest.\n    * [direct-minimal-versions](#direct-minimal-versions) — Forces the resolver to use the lowest compatible version instead of the highest.\n    * [public-dependency](#public-dependency) --- Allows dependencies to be classified as either public or private.\n    * [msrv-policy](#msrv-policy) --- MSRV-aware resolver and version selection\n    * [precise-pre-release](#precise-pre-release) --- Allows pre-release versions to be selected with `update --precise`\n    * [sbom](#sbom) --- Generates SBOM pre-cursor files for compiled artifacts\n    * [update-breaking](#update-breaking) --- Allows upgrading to breaking versions with `update --breaking`\n    * [feature-unification](#feature-unification) --- Enable new feature unification modes in workspaces\n    * [lockfile-publish-time](#lockfile-publish-time) --- Limit resolver to packages older than the specified time\n* Output behavior\n    * [artifact-dir](#artifact-dir) --- Adds a directory where artifacts are copied to.\n    * [build-dir-new-layout](#build-dir-new-layout) --- Enables the new build-dir filesystem layout\n    * [Different binary name](#different-binary-name) --- Assign a name to the built binary that is separate from the crate name.\n    * [root-dir](#root-dir) --- Controls the root directory relative to which paths are printed\n* Compile behavior\n    * [mtime-on-use](#mtime-on-use) --- Updates the last-modified timestamp on every dependency every time it is used, to provide a mechanism to delete unused artifacts.\n    * [build-std](#build-std) --- Builds the standard library instead of using pre-built binaries.\n    * [build-std-features](#build-std-features) --- Sets features to use with the standard library.\n    * [binary-dep-depinfo](#binary-dep-depinfo) --- Causes the dep-info file to track binary dependencies.\n    * [checksum-freshness](#checksum-freshness) --- When passed, the decision as to whether a crate needs to be rebuilt is made using file checksums instead of the file mtime.\n    * [panic-abort-tests](#panic-abort-tests) --- Allows running tests with the \"abort\" panic strategy.\n    * [host-config](#host-config) --- Allows setting `[target]`-like configuration settings for host build targets.\n    * [no-embed-metadata](#no-embed-metadata) --- Passes `-Zembed-metadata=no` to the compiler, which avoid embedding metadata into rlib and dylib artifacts, to save disk space.\n    * [target-applies-to-host](#target-applies-to-host) --- Alters whether certain flags will be passed to host build targets.\n    * [gc](#gc) --- Global cache garbage collection.\n    * [open-namespaces](#open-namespaces) --- Allow multiple packages to participate in the same API namespace\n    * [panic-immediate-abort](#panic-immediate-abort) --- Passes `-Cpanic=immediate-abort` to the compiler.\n    * [compile-time-deps](#compile-time-deps) --- Perma-unstable feature for rust-analyzer\n    * [fine-grain-locking](#fine-grain-locking) --- Use fine grain locking instead of locking the entire build cache\n    * [target-spec-json](#target-spec-json) --- Allows the use of `.json` custom target specs.\n* rustdoc\n    * [rustdoc-map](#rustdoc-map) --- Provides mappings for documentation to link to external sites like [docs.rs](https://docs.rs/).\n    * [scrape-examples](#scrape-examples) --- Shows examples within documentation.\n    * [output-format](#output-format-for-rustdoc) --- Allows documentation to also be emitted in the experimental [JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/).\n    * [rustdoc-depinfo](#rustdoc-depinfo) --- Use dep-info files in rustdoc rebuild detection.\n    * [rustdoc-mergeable-info](#rustdoc-mergeable-info) --- Use rustdoc mergeable cross-crate-info files.\n* `Cargo.toml` extensions\n    * [Profile `rustflags` option](#profile-rustflags-option) --- Passed directly to rustc.\n    * [Profile `hint-mostly-unused` option](#profile-hint-mostly-unused-option) --- Hint that a dependency is mostly unused, to optimize compilation time.\n    * [codegen-backend](#codegen-backend) --- Select the codegen backend used by rustc.\n    * [per-package-target](#per-package-target) --- Sets the `--target` to use for each individual package.\n    * [artifact dependencies](#artifact-dependencies) --- Allow build artifacts to be included into other build artifacts and build them for different targets.\n    * [Profile `trim-paths` option](#profile-trim-paths-option) --- Control the sanitization of file paths in build outputs.\n    * [`[lints.cargo]`](#lintscargo) --- Allows configuring lints for Cargo.\n    * [path bases](#path-bases) --- Named base directories for path dependencies.\n    * [`unstable-editions`](#unstable-editions) --- Allows use of editions that are not yet stable.\n* Information and metadata\n    * [unit-graph](#unit-graph) --- Emits JSON for Cargo's internal graph structure.\n    * [`cargo rustc --print`](#rustc---print) --- Calls rustc with `--print` to display information from rustc.\n    * [Build analysis](#build-analysis) --- Record and persist detailed build metrics across runs, with new commands to query past builds.\n    * [`rustc-unicode`](#rustc-unicode) --- Enables `rustc`'s unicode error format in Cargo's error messages \n* Configuration\n    * [`cargo config`](#cargo-config) --- Adds a new subcommand for viewing config files.\n* Registries\n    * [publish-timeout](#publish-timeout) --- Controls the timeout between uploading the crate and being available in the index\n    * [asymmetric-token](#asymmetric-token) --- Adds support for authentication tokens using asymmetric cryptography (`cargo:paseto` provider).\n* Other\n    * [gitoxide](#gitoxide) --- Use `gitoxide` instead of `git2` for a set of operations.\n    * [script](#script) --- Enable support for single-file `.rs` packages.\n    * [lockfile-path](#lockfile-path) --- Allows to specify a path to lockfile other than the default path `<workspace_root>/Cargo.lock`.\n    * [native-completions](#native-completions) --- Move cargo shell completions to native completions.\n    * [warnings](#warnings) --- controls warning behavior; options for allowing or denying warnings.\n    * [Package message format](#package-message-format) --- Message format for `cargo package`.\n    * [`fix-edition`](#fix-edition) --- A permanently unstable edition migration helper.\n    * [Plumbing subcommands](https://github.com/crate-ci/cargo-plumbing) --- Low, level commands that act as APIs for Cargo, like `cargo metadata`\n\n## allow-features\n\nThis permanently-unstable flag makes it so that only a listed set of\nunstable features can be used. Specifically, if you pass\n`-Zallow-features=foo,bar`, you'll continue to be able to pass `-Zfoo`\nand `-Zbar` to `cargo`, but you will be unable to pass `-Zbaz`. You can\npass an empty string (`-Zallow-features=`) to disallow all unstable\nfeatures.\n\n`-Zallow-features` also restricts which unstable features can be passed\nto the `cargo-features` entry in `Cargo.toml`. If, for example, you want\nto allow\n\n```toml\ncargo-features = [\"test-dummy-unstable\"]\n```\n\nwhere `test-dummy-unstable` is unstable, that features would also be\ndisallowed by `-Zallow-features=`, and allowed with\n`-Zallow-features=test-dummy-unstable`.\n\nThe list of features passed to cargo's `-Zallow-features` is also passed\nto any Rust tools that cargo ends up calling (like `rustc` or\n`rustdoc`). Thus, if you run `cargo -Zallow-features=`, no unstable\nCargo _or_ Rust features can be used.\n\n## no-index-update\n* Original Issue: [#3479](https://github.com/rust-lang/cargo/issues/3479)\n* Tracking Issue: [#7404](https://github.com/rust-lang/cargo/issues/7404)\n\nThe `-Z no-index-update` flag ensures that Cargo does not attempt to update\nthe registry index. This is intended for tools such as Crater that issue many\nCargo commands, and you want to avoid the network latency for updating the\nindex each time.\n\n## mtime-on-use\n* Original Issue: [#6477](https://github.com/rust-lang/cargo/pull/6477)\n* Cache usage meta tracking issue: [#7150](https://github.com/rust-lang/cargo/issues/7150)\n\nThe `-Z mtime-on-use` flag is an experiment to have Cargo update the mtime of\nused files to make it easier for tools like cargo-sweep to detect which files\nare stale. For many workflows this needs to be set on *all* invocations of cargo.\nTo make this more practical setting the `unstable.mtime_on_use` flag in `.cargo/config.toml`\nor the corresponding ENV variable will apply the `-Z mtime-on-use` to all\ninvocations of nightly cargo. (the config flag is ignored by stable)\n\n## avoid-dev-deps\n* Original Issue: [#4988](https://github.com/rust-lang/cargo/issues/4988)\n* Tracking Issue: [#5133](https://github.com/rust-lang/cargo/issues/5133)\n\nWhen running commands such as `cargo install` or `cargo build`, Cargo\ncurrently requires dev-dependencies to be downloaded, even if they are not\nused. The `-Z avoid-dev-deps` flag allows Cargo to avoid downloading\ndev-dependencies if they are not needed. The `Cargo.lock` file will not be\ngenerated if dev-dependencies are skipped.\n\n## minimal-versions\n* Original Issue: [#4100](https://github.com/rust-lang/cargo/issues/4100)\n* Tracking Issue: [#5657](https://github.com/rust-lang/cargo/issues/5657)\n\n> Note: It is not recommended to use this feature. Because it enforces minimal\n> versions for all transitive dependencies, its usefulness is limited since\n> not all external dependencies declare proper lower version bounds. It is\n> intended that it will be changed in the future to only enforce minimal\n> versions for direct dependencies.\n\nWhen a `Cargo.lock` file is generated, the `-Z minimal-versions` flag will\nresolve the dependencies to the minimum SemVer version that will satisfy the\nrequirements (instead of the greatest version).\n\nThe intended use-case of this flag is to check, during continuous integration,\nthat the versions specified in Cargo.toml are a correct reflection of the\nminimum versions that you are actually using. That is, if Cargo.toml says\n`foo = \"1.0.0\"` that you don't accidentally depend on features added only in\n`foo 1.5.0`.\n\n## direct-minimal-versions\n* Original Issue: [#4100](https://github.com/rust-lang/cargo/issues/4100)\n* Tracking Issue: [#5657](https://github.com/rust-lang/cargo/issues/5657)\n\nWhen a `Cargo.lock` file is generated, the `-Z direct-minimal-versions` flag will\nresolve the dependencies to the minimum SemVer version that will satisfy the\nrequirements (instead of the greatest version) for direct dependencies only.\n\nThe intended use-case of this flag is to check, during continuous integration,\nthat the versions specified in Cargo.toml are a correct reflection of the\nminimum versions that you are actually using. That is, if Cargo.toml says\n`foo = \"1.0.0\"` that you don't accidentally depend on features added only in\n`foo 1.5.0`.\n\nIndirect dependencies are resolved as normal so as not to be blocked on their\nminimal version validation.\n\n## artifact-dir\n* Original Issue: [#4875](https://github.com/rust-lang/cargo/issues/4875)\n* Tracking Issue: [#6790](https://github.com/rust-lang/cargo/issues/6790)\n\nThis feature allows you to specify the directory where artifacts will be copied\nto after they are built. Typically artifacts are only written to the\n`target/release` or `target/debug` directories. However, determining the exact\nfilename can be tricky since you need to parse JSON output. The `--artifact-dir`\nflag makes it easier to predictably access the artifacts. Note that the\nartifacts are copied, so the originals are still in the `target` directory.\nExample:\n\n```sh\ncargo +nightly build --artifact-dir=out -Z unstable-options\n```\n\nThis can also be specified in `.cargo/config.toml` files.\n\n```toml\n[build]\nartifact-dir = \"out\"\n```\n\n## root-dir\n* Original Issue: [#9887](https://github.com/rust-lang/cargo/issues/9887)\n* Tracking Issue: None (not currently slated for stabilization)\n\nThe `-Zroot-dir` flag sets the root directory relative to which paths are printed.\nThis affects both diagnostics and paths emitted by the `file!()` macro.\n\n## Metabuild\n* Tracking Issue: [rust-lang/rust#49803](https://github.com/rust-lang/rust/issues/49803)\n* RFC: [#2196](https://github.com/rust-lang/rfcs/blob/master/text/2196-metabuild.md)\n\nMetabuild is a feature to have declarative build scripts. Instead of writing\na `build.rs` script, you specify a list of build dependencies in the\n`metabuild` key in `Cargo.toml`. A build script is automatically generated\nthat runs each build dependency in order. Metabuild packages can then read\nmetadata from `Cargo.toml` to specify their behavior.\n\nInclude `cargo-features` at the top of `Cargo.toml`, a `metabuild` key in the\n`package`, list the dependencies in `build-dependencies`, and add any metadata\nthat the metabuild packages require under `package.metadata`. Example:\n\n```toml\ncargo-features = [\"metabuild\"]\n\n[package]\nname = \"mypackage\"\nversion = \"0.0.1\"\nmetabuild = [\"foo\", \"bar\"]\n\n[build-dependencies]\nfoo = \"1.0\"\nbar = \"1.0\"\n\n[package.metadata.foo]\nextra-info = \"qwerty\"\n```\n\nMetabuild packages should have a public function called `metabuild` that\nperforms the same actions as a regular `build.rs` script would perform.\n\n## Multiple Build Scripts\n* Tracking Issue: [#14903](https://github.com/rust-lang/cargo/issues/14903)\n* Original Pull Request: [#15630](https://github.com/rust-lang/cargo/pull/15630)\n\nMultiple Build Scripts feature allows you to have multiple build scripts in your package.\n\nInclude `cargo-features` at the top of `Cargo.toml` and add `multiple-build-scripts` to enable feature.\nAdd the paths of the build scripts as an array in `package.build`. For example:\n\n```toml\ncargo-features = [\"multiple-build-scripts\"]\n\n[package]\nname = \"mypackage\"\nversion = \"0.0.1\"\nbuild = [\"foo.rs\", \"bar.rs\"]\n```\n\n**Accessing Output Directories**:  Output directory of each build script can be accessed by using `<script-name>_OUT_DIR` \n  where the `<script-name>` is the file-stem of the build script, exactly as-is.\n  For example, `bar_OUT_DIR` for script at `foo/bar.rs`. (Only set during compilation, can be accessed via `env!` macro)\n\n## Any Build Script Metadata\n* Tracking Issue: [#14903](https://github.com/rust-lang/cargo/issues/3544)\n\nAllow any build script to specify env vars via `cargo::metadata=key=value`\n\nDepedant build scripts can access these key/value pair by reading the `CARGO_DEP_<dep>_<key>` env variable at runtime.\nFor build scripts of crates with a `links`, both `DEP_<links>_<key>` and `CARGO_DEP_<dep>_<key>` will be set.\n\nNote that `dep` and `key` in `CARGO_DEP_<dep>_<key>` are uppercased and hyphens (`-`) replaced with underscores (`_`).\n\n## public-dependency\n* Tracking Issue: [#44663](https://github.com/rust-lang/rust/issues/44663)\n\nThe 'public-dependency' feature allows marking dependencies as 'public'\nor 'private'. When this feature is enabled, additional information is passed to rustc to allow\nthe [exported_private_dependencies](../../rustc/lints/listing/warn-by-default.html#exported-private-dependencies) lint to function properly.\n\nTo enable this feature, you can either use `-Zpublic-dependency`\n\n```sh\ncargo +nightly run -Zpublic-dependency\n```\n\nor `[unstable]` table, for example,\n\n```toml\n# .cargo/config.toml\n[unstable]\npublic-dependency = true\n```\n\n`public-dependency` could also be enabled in `cargo-features`, **though this is deprecated and will be removed soon**.\n\n```toml\ncargo-features = [\"public-dependency\"]\n\n[dependencies]\nmy_dep = { version = \"1.2.3\", public = true }\nprivate_dep = \"2.0.0\" # Will be 'private' by default\n```\n\nDocumentation updates:\n- For workspace's \"The `dependencies` table\" section, include `public` as an unsupported field for `workspace.dependencies`\n\n## msrv-policy\n- [RFC: MSRV-aware Resolver](https://rust-lang.github.io/rfcs/3537-msrv-resolver.html)\n- [#9930](https://github.com/rust-lang/cargo/issues/9930) (MSRV-aware resolver)\n\nCatch-all unstable feature for MSRV-aware cargo features under\n[RFC 2495](https://github.com/rust-lang/rfcs/pull/2495).\n\n### MSRV-aware cargo add\n\nThis was stabilized in 1.79 in [#13608](https://github.com/rust-lang/cargo/pull/13608).\n\n### MSRV-aware resolver\n\nThis was stabilized in 1.84 in [#14639](https://github.com/rust-lang/cargo/pull/14639).\n\n### Convert `incompatible_toolchain` error into a lint\n\nUnimplemented\n\n### `--update-rust-version` flag for `cargo add`, `cargo update`\n\nUnimplemented\n\n### `package.rust-version = \"toolchain\"`\n\nUnimplemented\n\n### Update `cargo new` template to set `package.rust-version = \"toolchain\"`\n\nUnimplemented\n\n## precise-pre-release\n\n* Tracking Issue: [#13290](https://github.com/rust-lang/cargo/issues/13290)\n* RFC: [#3493](https://github.com/rust-lang/rfcs/pull/3493)\n\nThe `precise-pre-release` feature allows pre-release versions to be selected with `update --precise`\neven when a pre-release is not specified by a projects `Cargo.toml`.\n\nTake for example this `Cargo.toml`.\n\n```toml\n[dependencies]\nmy-dependency = \"0.1.1\"\n```\n\nIt's possible to update `my-dependency` to a pre-release with `update -Zunstable-options my-dependency --precise 0.1.2-pre.0`.\nThis is because `0.1.2-pre.0` is considered compatible with `0.1.1`.\nIt would not be possible to upgrade to `0.2.0-pre.0` from `0.1.1` in the same way.\n\n## sbom\n* Tracking Issue: [#13709](https://github.com/rust-lang/cargo/pull/13709)\n* RFC: [#3553](https://github.com/rust-lang/rfcs/pull/3553)\n\nThe `sbom` build config allows to generate so-called SBOM pre-cursor files\nalongside each compiled artifact. A Software Bill Of Material (SBOM) tool can\nincorporate these generated files to collect important information from the cargo\nbuild process that are difficult or impossible to obtain in another way.\n\nTo enable this feature either set the `sbom` field in the `.cargo/config.toml`\n\n```toml\n[unstable]\nsbom = true\n\n[build]\nsbom = true\n```\n\nor set the `CARGO_BUILD_SBOM` environment variable to `true`. The functionality\nis available behind the flag `-Z sbom`.\n\nThe generated output files are in JSON format and follow the naming scheme\n`<artifact>.cargo-sbom.json`. The JSON file contains information about dependencies,\ntarget, features and the used `rustc` compiler.\n\nSBOM pre-cursor files are generated for all executable and linkable outputs\nthat are uplifted into the target or artifact directories.\n\n### Environment variables Cargo sets for crates\n\n* `CARGO_SBOM_PATH` -- a list of generated SBOM precursor files, separated by the platform PATH separator. The list can be split with `std::env::split_paths`.\n\n### SBOM pre-cursor schema\n\n```json5\n{\n  // Schema version.\n  \"version\": 1,\n  // Index into the crates array for the root crate.\n  \"root\": 0,\n  // Array of all crates. There may be duplicates of the same crate if that\n  // crate is compiled differently (different opt-level, features, etc).\n  \"crates\": [\n    {\n      // Fully qualified package ID specification\n      \"id\": \"path+file:///sample-package#0.1.0\",\n      // List of target kinds: bin, lib, rlib, dylib, cdylib, staticlib, proc-macro, example, test, bench, custom-build\n      \"kind\": [\"bin\"],\n      // Enabled feature flags.\n      \"features\": [],\n      // Dependencies for this crate.\n      \"dependencies\": [\n        {\n          // Index in to the crates array.\n          \"index\": 1,\n          // Dependency kind: \n          // Normal: A dependency linked to the artifact produced by this crate.\n          // Build: A compile-time dependency used to build this crate (build-script or proc-macro).\n          \"kind\": \"normal\"\n        },\n        {\n          // A crate can depend on another crate with both normal and build edges.\n          \"index\": 1,\n          \"kind\": \"build\"\n        }\n      ]\n    },\n    {\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#zerocopy@0.8.16\",\n      \"kind\": [\"bin\"],\n      \"features\": [],\n      \"dependencies\": []\n    }\n  ],\n  // Information about rustc used to perform the compilation.\n  \"rustc\": {\n    // Compiler version\n    \"version\": \"1.86.0-nightly\",\n    // Compiler wrapper\n    \"wrapper\": null,\n    // Compiler workspace wrapper\n    \"workspace_wrapper\": null,\n    // Commit hash for rustc\n    \"commit_hash\": \"bef3c3b01f690de16738b1c9f36470fbfc6ac623\",\n    // Host target triple\n    \"host\": \"x86_64-pc-windows-msvc\",\n    // Verbose version string: `rustc -vV`\n    \"verbose_version\": \"rustc 1.86.0-nightly (bef3c3b01 2025-02-04)\\nbinary: rustc\\ncommit-hash: bef3c3b01f690de16738b1c9f36470fbfc6ac623\\ncommit-date: 2025-02-04\\nhost: x86_64-pc-windows-msvc\\nrelease: 1.86.0-nightly\\nLLVM version: 19.1.7\\n\"\n  }\n}\n```\n\n## update-breaking\n\n* Tracking Issue: [#12425](https://github.com/rust-lang/cargo/issues/12425)\n\nAllow upgrading dependencies version requirements in `Cargo.toml` across SemVer\nincompatible versions using with the `--breaking` flag.\n\nThis only applies to dependencies when\n- The package is a dependency of a workspace member\n- The dependency is not renamed\n- A SemVer-incompatible version is available\n- The \"SemVer operator\" is used (`^` which is the default)\n\nUsers may further restrict which packages get upgraded by specifying them on\nthe command line.\n\nExample:\n```console\n$ cargo +nightly -Zunstable-options update --breaking\n$ cargo +nightly -Zunstable-options update --breaking clap\n```\n\n*This is meant to fill a similar role as [cargo-upgrade](https://github.com/killercup/cargo-edit/)*\n\n## build-std\n* Tracking Repository: <https://github.com/rust-lang/wg-cargo-std-aware>\n\nThe `build-std` feature enables Cargo to compile the standard library itself as\npart of a crate graph compilation. This feature has also historically been known\nas \"std-aware Cargo\". This feature is still in very early stages of development,\nand is also a possible massive feature addition to Cargo. This is a very large\nfeature to document, even in the minimal form that it exists in today, so if\nyou're curious to stay up to date you'll want to follow the [tracking\nrepository](https://github.com/rust-lang/wg-cargo-std-aware) and its set of\nissues.\n\nThe functionality implemented today is behind a flag called `-Z build-std`. This\nflag indicates that Cargo should compile the standard library from source code\nusing the same profile as the main build itself. Note that for this to work you\nneed to have the source code for the standard library available, and at this\ntime the only supported method of doing so is to add the `rust-src` rust rustup\ncomponent:\n\n```console\n$ rustup component add rust-src --toolchain nightly\n```\n\nUsage looks like:\n\n```console\n$ cargo new foo\n$ cd foo\n$ cargo +nightly run -Z build-std --target x86_64-unknown-linux-gnu\n   Compiling core v0.0.0 (...)\n   ...\n   Compiling foo v0.1.0 (...)\n    Finished dev [unoptimized + debuginfo] target(s) in 21.00s\n     Running `target/x86_64-unknown-linux-gnu/debug/foo`\nHello, world!\n```\n\nHere we recompiled the standard library in debug mode with debug assertions\n(like `src/main.rs` is compiled) and everything was linked together at the end.\n\nUsing `-Z build-std` will implicitly compile the stable crates `core`, `std`,\n`alloc`, and `proc_macro`. If you're using `cargo test` it will also compile the\n`test` crate. If you're working with an environment which does not support some\nof these crates, then you can pass an argument to `-Zbuild-std` as well:\n\n```console\n$ cargo +nightly build -Z build-std=core,alloc\n```\n\nThe value here is a comma-separated list of standard library crates to build.\n\n### Requirements\n\nAs a summary, a list of requirements today to use `-Z build-std` are:\n\n* You must install libstd's source code through `rustup component add rust-src`\n* You must use both a nightly Cargo and a nightly rustc\n* The `-Z build-std` flag must be passed to all `cargo` invocations.\n\n### Reporting bugs and helping out\n\nThe `-Z build-std` feature is in the very early stages of development! This\nfeature for Cargo has an extremely long history and is very large in scope, and\nthis is just the beginning. If you'd like to report bugs please either report\nthem to:\n\n* Cargo --- <https://github.com/rust-lang/cargo/issues/new> --- for implementation bugs\n* The tracking repository ---\n  <https://github.com/rust-lang/wg-cargo-std-aware/issues/new> --- for larger design\n  questions.\n\nAlso if you'd like to see a feature that's not yet implemented and/or if\nsomething doesn't quite work the way you'd like it to, feel free to check out\nthe [issue tracker](https://github.com/rust-lang/wg-cargo-std-aware/issues) of\nthe tracking repository, and if it's not there please file a new issue!\n\n## build-std-features\n* Tracking Repository: <https://github.com/rust-lang/wg-cargo-std-aware>\n\nThis flag is a sibling to the `-Zbuild-std` feature flag. This will configure\nthe features enabled for the standard library itself when building the standard\nlibrary. The default enabled features, at this time, are `backtrace` and\n`panic-unwind`. This flag expects a comma-separated list and, if provided, will\noverride the default list of features enabled.\n\n## binary-dep-depinfo\n* Tracking rustc issue: [#63012](https://github.com/rust-lang/rust/issues/63012)\n\nThe `-Z binary-dep-depinfo` flag causes Cargo to forward the same flag to\n`rustc` which will then cause `rustc` to include the paths of all binary\ndependencies in the \"dep info\" file (with the `.d` extension). Cargo then uses\nthat information for change-detection (if any binary dependency changes, then\nthe crate will be rebuilt). The primary use case is for building the compiler\nitself, which has implicit dependencies on the standard library that would\notherwise be untracked for change-detection.\n\n## checksum-freshness\n* Tracking issue: [#14136](https://github.com/rust-lang/cargo/issues/14136)\n\nThe `-Z checksum-freshness` flag will replace the use of file mtimes in cargo's\nfingerprints with a file checksum value. This is most useful on systems with a poor\nmtime implementation, or in CI/CD. The checksum algorithm can change without notice\nbetween cargo versions. Fingerprints are used by cargo to determine when a crate needs to be rebuilt.\n\nFor the time being files ingested by build script will continue to use mtimes, even when `checksum-freshness`\nis enabled. This is not intended as a long term solution.\n\n## panic-abort-tests\n* Tracking Issue: [#67650](https://github.com/rust-lang/rust/issues/67650)\n* Original Pull Request: [#7460](https://github.com/rust-lang/cargo/pull/7460)\n\nThe `-Z panic-abort-tests` flag will enable nightly support to compile test\nharness crates with `-Cpanic=abort`. Without this flag Cargo will compile tests,\nand everything they depend on, with `-Cpanic=unwind` because it's the only way\n`test`-the-crate knows how to operate. As of [rust-lang/rust#64158], however,\nthe `test` crate supports `-C panic=abort` with a test-per-process, and can help\navoid compiling crate graphs multiple times.\n\nIt's currently unclear how this feature will be stabilized in Cargo, but we'd\nlike to stabilize it somehow!\n\n[rust-lang/rust#64158]: https://github.com/rust-lang/rust/pull/64158\n\n## target-applies-to-host\n* Original Pull Request: [#9322](https://github.com/rust-lang/cargo/pull/9322)\n* Tracking Issue: [#9453](https://github.com/rust-lang/cargo/issues/9453)\n\nHistorically, Cargo's behavior for whether the `linker` and `rustflags`\nconfiguration options from environment variables and\n[`[target]`](config.md#target) are respected for build scripts, plugins,\nand other artifacts that are _always_ built for the host platform has\nbeen somewhat inconsistent.\nWhen `--target` is _not_ passed, Cargo respects the same `linker` and\n`rustflags` for build scripts as for all other compile artifacts. When\n`--target` _is_ passed, however, Cargo respects `linker` from\n[`[target.<host triple>]`](config.md#targettriplelinker), and does not\npick up any `rustflags` configuration.\nThis dual behavior is confusing, but also makes it difficult to correctly\nconfigure builds where the host triple and the [target triple] happen to\nbe the same, but artifacts intended to run on the build host should still\nbe configured differently.\n\n`-Ztarget-applies-to-host` enables the top-level\n`target-applies-to-host` setting in Cargo configuration files which\nallows users to opt into different (and more consistent) behavior for\nthese properties. When `target-applies-to-host` is unset, or set to\n`true`, in the configuration file, the existing Cargo behavior is\npreserved (though see `-Zhost-config`, which changes that default). When\nit is set to `false`, no options from `[target.<host triple>]`,\n`RUSTFLAGS`, or `[build]` are respected for host artifacts regardless of\nwhether `--target` is passed to Cargo. To customize artifacts intended\nto be run on the host, use `[host]` ([`host-config`](#host-config)).\n\nIn the future, `target-applies-to-host` may end up defaulting to `false`\nto provide more sane and consistent default behavior.\n\n```toml\n# config.toml\ntarget-applies-to-host = false\n```\n\n```console\ncargo +nightly -Ztarget-applies-to-host build --target x86_64-unknown-linux-gnu\n```\n\n## host-config\n* Original Pull Request: [#9322](https://github.com/rust-lang/cargo/pull/9322)\n* Tracking Issue: [#9452](https://github.com/rust-lang/cargo/issues/9452)\n\nThe `host` key in a config file can be used to pass flags to host build targets\nsuch as build scripts that must run on the host system instead of the target\nsystem when cross compiling. It supports both generic and host arch specific\ntables. Matching host arch tables take precedence over generic host tables.\n\nIt requires the `-Zhost-config` and `-Ztarget-applies-to-host`\ncommand-line options to be set, and that `target-applies-to-host =\nfalse` is set in the Cargo configuration file.\n\n```toml\n# config.toml\n[host]\nlinker = \"/path/to/host/linker\"\nrunner = \"host-runner\"\n[host.x86_64-unknown-linux-gnu]\nlinker = \"/path/to/host/arch/linker\"\nrunner = \"host-arch-runner\"\nrustflags = [\"-Clink-arg=--verbose\"]\n[target.x86_64-unknown-linux-gnu]\nlinker = \"/path/to/target/linker\"\n```\n\nThe `host.runner` setting wraps execution of host build targets such as build\nscripts, similar to how `target.<triple>.runner` wraps `cargo run`/`test`/`bench`.\n\nThe generic `host` table above will be entirely ignored when building on an\n`x86_64-unknown-linux-gnu` host as the `host.x86_64-unknown-linux-gnu` table\ntakes precedence.\n\nSetting `-Zhost-config` changes the default for `target-applies-to-host` to\n`false` from `true`.\n\n```console\ncargo +nightly -Ztarget-applies-to-host -Zhost-config build --target x86_64-unknown-linux-gnu\n```\n\n## unit-graph\n* Tracking Issue: [#8002](https://github.com/rust-lang/cargo/issues/8002)\n\nThe `--unit-graph` flag can be passed to any build command (`build`, `check`,\n`run`, `test`, `bench`, `doc`, etc.) to emit a JSON object to stdout which\nrepresents Cargo's internal unit graph. Nothing is actually built, and the\ncommand returns immediately after printing. Each \"unit\" corresponds to an\nexecution of the compiler. These objects also include which unit each unit\ndepends on.\n\n```\ncargo +nightly build --unit-graph -Z unstable-options\n```\n\nThis structure provides a more complete view of the dependency relationship as\nCargo sees it. In particular, the \"features\" field supports the new feature\nresolver where a dependency can be built multiple times with different\nfeatures. `cargo metadata` fundamentally cannot represent the relationship of\nfeatures between different dependency kinds, and features now depend on which\ncommand is run and which packages and targets are selected. Additionally it\ncan provide details about intra-package dependencies like build scripts or\ntests.\n\nThe following is a description of the JSON structure:\n\n```javascript\n{\n  /* Version of the JSON output structure. If any backwards incompatible\n     changes are made, this value will be increased.\n  */\n  \"version\": 1,\n  /* Array of all build units. */\n  \"units\": [\n    {\n      /* An opaque string which indicates the package.\n         Information about the package can be obtained from `cargo metadata`.\n      */\n      \"pkg_id\": \"my-package 0.1.0 (path+file:///path/to/my-package)\",\n      /* The Cargo target. See the `cargo metadata` documentation for more\n         information about these fields.\n         https://doc.rust-lang.org/cargo/commands/cargo-metadata.html\n      */\n      \"target\": {\n        \"kind\": [\"lib\"],\n        \"crate_types\": [\"lib\"],\n        \"name\": \"my_package\",\n        \"src_path\": \"/path/to/my-package/src/lib.rs\",\n        \"edition\": \"2018\",\n        \"test\": true,\n        \"doctest\": true\n      },\n      /* The profile settings for this unit.\n         These values may not match the profile defined in the manifest.\n         Units can use modified profile settings. For example, the \"panic\"\n         setting can be overridden for tests to force it to \"unwind\".\n      */\n      \"profile\": {\n        /* The profile name these settings are derived from. */\n        \"name\": \"dev\",\n        /* The optimization level as a string. */\n        \"opt_level\": \"0\",\n        /* The LTO setting as a string. */\n        \"lto\": \"false\",\n        /* The codegen units as an integer.\n           `null` if it should use the compiler's default.\n        */\n        \"codegen_units\": null,\n        /* The debug information level as an integer.\n           `null` if it should use the compiler's default (0).\n        */\n        \"debuginfo\": 2,\n        /* Whether or not debug-assertions are enabled. */\n        \"debug_assertions\": true,\n        /* Whether or not overflow-checks are enabled. */\n        \"overflow_checks\": true,\n        /* Whether or not rpath is enabled. */\n        \"rpath\": false,\n        /* Whether or not incremental is enabled. */\n        \"incremental\": true,\n        /* The panic strategy, \"unwind\" or \"abort\". */\n        \"panic\": \"unwind\"\n      },\n      /* Which platform this target is being built for.\n         A value of `null` indicates it is for the host.\n         Otherwise it is a string of the target triple (such as\n         \"x86_64-unknown-linux-gnu\").\n      */\n      \"platform\": null,\n      /* The \"mode\" for this unit. Valid values:\n\n         * \"test\" --- Build using `rustc` as a test.\n         * \"build\" --- Build using `rustc`.\n         * \"check\" --- Build using `rustc` in \"check\" mode.\n         * \"doc\" --- Build using `rustdoc`.\n         * \"doctest\" --- Test using `rustdoc`.\n         * \"run-custom-build\" --- Represents the execution of a build script.\n      */\n      \"mode\": \"build\",\n      /* Array of features enabled on this unit as strings. */\n      \"features\": [\"somefeat\"],\n      /* Whether or not this is a standard-library unit,\n         part of the unstable build-std feature.\n         If not set, treat as `false`.\n      */\n      \"is_std\": false,\n      /* Array of dependencies of this unit. */\n      \"dependencies\": [\n        {\n          /* Index in the \"units\" array for the dependency. */\n          \"index\": 1,\n          /* The name that this dependency will be referred as. */\n          \"extern_crate_name\": \"unicode_xid\",\n          /* Whether or not this dependency is \"public\",\n             part of the unstable public-dependency feature.\n             If not set, the public-dependency feature is not enabled.\n          */\n          \"public\": false,\n          /* Whether or not this dependency is injected into the prelude,\n             currently used by the build-std feature.\n             If not set, treat as `false`.\n          */\n          \"noprelude\": false\n        }\n      ]\n    },\n    // ...\n  ],\n  /* Array of indices in the \"units\" array that are the \"roots\" of the\n     dependency graph.\n  */\n  \"roots\": [0],\n}\n```\n\n## Profile `rustflags` option\n* Original Issue: [rust-lang/cargo#7878](https://github.com/rust-lang/cargo/issues/7878)\n* Tracking Issue: [rust-lang/cargo#10271](https://github.com/rust-lang/cargo/issues/10271)\n\nThis feature provides a new option in the `[profile]` section to specify flags\nthat are passed directly to rustc.\nThis can be enabled like so:\n\n```toml\ncargo-features = [\"profile-rustflags\"]\n\n[package]\n# ...\n\n[profile.release]\nrustflags = [ \"-C\", \"...\" ]\n```\n\nTo set this in a profile in Cargo configuration, you need to use either\n`-Z profile-rustflags` or `[unstable]` table to enable it. For example,\n\n```toml\n# .cargo/config.toml\n[unstable]\nprofile-rustflags = true\n\n[profile.release]\nrustflags = [ \"-C\", \"...\" ]\n```\n\n## Profile `hint-mostly-unused` option\n* Tracking Issue: [#15644](https://github.com/rust-lang/cargo/issues/15644)\n\nThis feature provides a new option in the `[profile]` section to enable the\nrustc `hint-mostly-unused` option. This is primarily useful to enable for\nspecific dependencies:\n\n```toml\n[profile.dev.package.huge-mostly-unused-dependency]\nhint-mostly-unused = true\n```\n\nTo enable this feature, pass `-Zprofile-hint-mostly-unused`. However, since\nthis option is a hint, using it without passing `-Zprofile-hint-mostly-unused`\nwill only warn and ignore the profile option. Versions of Cargo prior to the\nintroduction of this feature will give an \"unused manifest key\" warning, but\nwill otherwise function without erroring. This allows using the hint in a\ncrate's `Cargo.toml` without mandating the use of a newer Cargo to build it.\n\nA crate can also provide this hint automatically for crates that depend on it,\nusing the `[hints]` table (which will likewise be ignored by older Cargo):\n\n```toml\n[hints]\nmostly-unused = true\n```\n\nThis will cause the crate to default to hint-mostly-unused, unless overridden\nvia `profile`, which takes precedence, and which can only be specified in the\ntop-level crate being built.\n\n## rustdoc-map\n* Tracking Issue: [#8296](https://github.com/rust-lang/cargo/issues/8296)\n\nThis feature adds configuration settings that are passed to `rustdoc` so that\nit can generate links to dependencies whose documentation is hosted elsewhere\nwhen the dependency is not documented. First, add this to `.cargo/config`:\n\n```toml\n[doc.extern-map.registries]\ncrates-io = \"https://docs.rs/\"\n```\n\nThen, when building documentation, use the following flags to cause links\nto dependencies to link to [docs.rs](https://docs.rs/):\n\n```\ncargo +nightly doc --no-deps -Zrustdoc-map\n```\n\nThe `registries` table contains a mapping of registry name to the URL to link\nto. The URL may have the markers `{pkg_name}` and `{version}` which will get\nreplaced with the corresponding values. If neither are specified, then Cargo\ndefaults to appending `{pkg_name}/{version}/` to the end of the URL.\n\nAnother config setting is available to redirect standard library links. By\ndefault, rustdoc creates links to <https://doc.rust-lang.org/nightly/>. To\nchange this behavior, use the `doc.extern-map.std` setting:\n\n```toml\n[doc.extern-map]\nstd = \"local\"\n```\n\nA value of `\"local\"` means to link to the documentation found in the `rustc`\nsysroot. If you are using rustup, this documentation can be installed with\n`rustup component add rust-docs`.\n\nThe default value is `\"remote\"`.\n\nThe value may also take a URL for a custom location.\n\n## per-package-target\n* Tracking Issue: [#9406](https://github.com/rust-lang/cargo/pull/9406)\n* Original Pull Request: [#9030](https://github.com/rust-lang/cargo/pull/9030)\n* Original Issue: [#7004](https://github.com/rust-lang/cargo/pull/7004)\n\nThe `per-package-target` feature adds two keys to the manifest:\n`package.default-target` and `package.forced-target`. The first makes\nthe package be compiled by default (ie. when no `--target` argument is\npassed) for some target. The second one makes the package always be\ncompiled for the target.\n\nExample:\n\n```toml\n[package]\nforced-target = \"wasm32-unknown-unknown\"\n```\n\nIn this example, the crate is always built for\n`wasm32-unknown-unknown`, for instance because it is going to be used\nas a plugin for a main program that runs on the host (or provided on\nthe command line) target.\n\n## artifact-dependencies\n\n* Tracking Issue: [#9096](https://github.com/rust-lang/cargo/pull/9096)\n* Original Pull Request: [#9992](https://github.com/rust-lang/cargo/pull/9992)\n\nArtifact dependencies allow Cargo packages to depend on `bin`, `cdylib`, and `staticlib` crates,\nand use the artifacts built by those crates at compile time.\n\nRun `cargo` with `-Z bindeps` to enable this functionality.\n\n### artifact-dependencies: Dependency declarations\n\nArtifact-dependencies adds the following keys to a dependency declaration in `Cargo.toml`:\n\n- `artifact` --- This specifies the [Cargo Target](cargo-targets.md) to build.\n  Normally without this field, Cargo will only build the `[lib]` target from a dependency.\n  This field allows specifying which target will be built, and made available as a binary at build time:\n\n  * `\"bin\"` --- Compiled executable binaries, corresponding to all of the `[[bin]]` sections in the dependency's manifest.\n  * `\"bin:<bin-name>\"` --- Compiled executable binary, corresponding to a specific binary target specified by the given `<bin-name>`.\n  * `\"cdylib\"` --- A C-compatible dynamic library, corresponding to a `[lib]` section with `crate-type = [\"cdylib\"]` in the dependency's manifest.\n  * `\"staticlib\"` --- A C-compatible static library, corresponding to a `[lib]` section with `crate-type = [\"staticlib\"]` in the dependency's manifest.\n\n  The `artifact` value can be a string, or it can be an array of strings to specify multiple targets.\n\n  Example:\n\n  ```toml\n  [dependencies]\n  bar = { version = \"1.0\", artifact = \"staticlib\" }\n  zoo = { version = \"1.0\", artifact = [\"bin:cat\", \"bin:dog\"]}\n  ```\n\n- `lib` --- This is a Boolean value which indicates whether or not to also build the dependency's library as a normal Rust `lib` dependency.\n  This field can only be specified when `artifact` is specified.\n\n  The default for this field is `false` when `artifact` is specified.\n  If this is set to `true`, then the dependency's `[lib]` target will also be built for the platform target the declaring package is being built for.\n  This allows the package to use the dependency from Rust code like a normal dependency in addition to an artifact dependency.\n\n  Example:\n\n  ```toml\n  [dependencies]\n  bar = { version = \"1.0\", artifact = \"bin\", lib = true }\n  ```\n\n- `target` --- The platform target to build the dependency for.\n  This field can only be specified when `artifact` is specified.\n\n  The default if this is not specified depends on the dependency kind.\n  For build dependencies, it will be built for the host target.\n  For all other dependencies, it will be built for the same targets the declaring package is built for.\n\n  For a build dependency, this can also take the special value of `\"target\"` which means to build the dependency for the same targets that the package is being built for.\n\n  ```toml\n  [build-dependencies]\n  bar = { version = \"1.0\", artifact = \"cdylib\", target = \"wasm32-unknown-unknown\"}\n  same-target = { version = \"1.0\", artifact = \"bin\", target = \"target\" }\n  ```\n\n### artifact-dependencies: Environment variables\n\nAfter building an artifact dependency, Cargo provides the following environment variables that you can use to access the artifact:\n\n- `CARGO_<ARTIFACT-TYPE>_DIR_<DEP>` --- This is the directory containing all the artifacts from the dependency.\n\n  `<ARTIFACT-TYPE>` is the `artifact` specified for the dependency (uppercased as in `CDYLIB`, `STATICLIB`, or `BIN`) and `<DEP>` is the name of the dependency.\n  As with other Cargo environment variables, dependency names are converted to uppercase, with dashes replaced by underscores.\n\n  If your manifest renames the dependency, `<DEP>` corresponds to the name you specify, not the original package name.\n\n- `CARGO_<ARTIFACT-TYPE>_FILE_<DEP>_<NAME>` --- This is the full path to the artifact.\n\n  `<ARTIFACT-TYPE>` is the `artifact` specified for the dependency (uppercased as above), `<DEP>` is the name of the dependency (transformed as above), and `<NAME>` is the name of the artifact from the dependency.\n\n  Note that `<NAME>` is not modified in any way from the `name` specified in the crate supplying the artifact, or the crate name if not specified; for instance, it may be in lowercase, or contain dashes.\n\n  For convenience, if the artifact name matches the original package name, cargo additionally supplies a copy of this variable with the `_<NAME>` suffix omitted.\n  For instance, if the `cmake` crate supplies a binary named `cmake`, Cargo supplies both `CARGO_BIN_FILE_CMAKE` and `CARGO_BIN_FILE_CMAKE_cmake`.\n\nFor each kind of dependency, these variables are supplied to the same part of the build process that has access to that kind of dependency:\n\n- For build-dependencies, these variables are supplied to the `build.rs` script, and can be accessed using [`std::env::var_os`](https://doc.rust-lang.org/std/env/fn.var_os.html).\n  (As with any OS file path, these may or may not be valid UTF-8.)\n- For normal dependencies, these variables are supplied during the compilation of the crate, and can be accessed using the [`env!`] macro.\n- For dev-dependencies, these variables are supplied during the compilation of examples, tests, and benchmarks, and can be accessed using the [`env!`] macro.\n\n[`env!`]: https://doc.rust-lang.org/std/macro.env.html\n\n### artifact-dependencies: Examples\n\n#### Example: use a binary executable from a build script\n\nIn the `Cargo.toml` file, you can specify a dependency on a binary to make available for a build script:\n\n```toml\n[build-dependencies]\nsome-build-tool = { version = \"1.0\", artifact = \"bin\" }\n```\n\nThen inside the build script, the binary can be executed at build time:\n\n```rust\nfn main() {\n    let build_tool = std::env::var_os(\"CARGO_BIN_FILE_SOME_BUILD_TOOL\").unwrap();\n    let status = std::process::Command::new(build_tool)\n        .arg(\"do-stuff\")\n        .status()\n        .unwrap();\n    if !status.success() {\n        eprintln!(\"failed!\");\n        std::process::exit(1);\n    }\n}\n```\n\n#### Example: use _cdylib_ artifact in build script\n\nThe `Cargo.toml` in the consuming package, building the `bar` library as `cdylib`\nfor a specific build target…\n\n```toml\n[build-dependencies]\nbar = { artifact = \"cdylib\", version = \"1.0\", target = \"wasm32-unknown-unknown\" }\n```\n\n…along with the build script in `build.rs`.\n\n```rust\nfn main() {\n    wasm::run_file(std::env::var(\"CARGO_CDYLIB_FILE_BAR\").unwrap());\n}\n```\n\n#### Example: use _binary_ artifact and its library in a binary\n\nThe `Cargo.toml` in the consuming package, building the `bar` binary for inclusion\nas artifact while making it available as library as well…\n\n```toml\n[dependencies]\nbar = { artifact = \"bin\", version = \"1.0\", lib = true }\n```\n\n…along with the executable using `main.rs`.\n\n```rust\nfn main() {\n    bar::init();\n    command::run(env!(\"CARGO_BIN_FILE_BAR\"));\n}\n```\n\n## publish-timeout\n* Tracking Issue: [11222](https://github.com/rust-lang/cargo/issues/11222)\n\nThe `publish.timeout` key in a config file can be used to control how long\n`cargo publish` waits between posting a package to the registry and it being\navailable in the local index.\n\nA timeout of `0` prevents any checks from occurring. The current default is\n`60` seconds.\n\nIt requires the `-Zpublish-timeout` command-line options to be set.\n\n```toml\n# config.toml\n[publish]\ntimeout = 300  # in seconds\n```\n\n## asymmetric-token\n* Tracking Issue: [10519](https://github.com/rust-lang/cargo/issues/10519)\n* RFC: [#3231](https://github.com/rust-lang/rfcs/pull/3231)\n\nThe `-Z asymmetric-token` flag enables the `cargo:paseto` credential provider which allows Cargo to authenticate to registries without sending secrets over the network.\n\nIn [`config.toml`](config.md) and `credentials.toml` files there is a field called `private-key`, which is a private key formatted in the secret [subset of `PASERK`](https://github.com/paseto-standard/paserk/blob/master/types/secret.md) and is used to sign asymmetric tokens\n\nA keypair can be generated with `cargo login --generate-keypair` which will:\n- generate a public/private keypair in the currently recommended fashion.\n- save the private key in `credentials.toml`.\n- print the public key in [PASERK public](https://github.com/paseto-standard/paserk/blob/master/types/public.md) format.\n\nIt is recommended that the `private-key` be saved in `credentials.toml`. It is also supported in `config.toml`, primarily so that it can be set using the associated environment variable, which is the recommended way to provide it in CI contexts. This setup is what we have for the `token` field for setting a secret token.\n\nThere is also an optional field called `private-key-subject` which is a string chosen by the registry.\nThis string will be included as part of an asymmetric token and should not be secret.\nIt is intended for the rare use cases like \"cryptographic proof that the central CA server authorized this action\". Cargo requires it to be non-whitespace printable ASCII. Registries that need non-ASCII data should base64 encode it.\n\nBoth fields can be set with `cargo login --registry=name --private-key --private-key-subject=\"subject\"` which will prompt you to put in the key value.\n\nA registry can have at most one of `private-key` or `token` set.\n\nAll PASETOs will include `iat`, the current time in ISO 8601 format. Cargo will include the following where appropriate:\n- `sub` an optional, non-secret string chosen by the registry that is expected to be claimed with every request. The value will be the `private-key-subject` from the `config.toml` file.\n- `mutation` if present, indicates that this request is a mutating operation (or a read-only operation if not present), must be one of the strings `publish`, `yank`, or `unyank`.\n  - `name` name of the crate related to this request.\n  - `vers` version string of the crate related to this request.\n  - `cksum` the SHA256 hash of the crate contents, as a string of 64 lowercase hexadecimal digits, must be present only when `mutation` is equal to `publish`\n- `challenge` the challenge string received from a 401/403 from this server this session. Registries that issue challenges must track which challenges have been issued/used and never accept a given challenge more than once within the same validity period (avoiding the need to track every challenge ever issued).\n\nThe \"footer\" (which is part of the signature) will be a JSON string in UTF-8 and include:\n- `url` the RFC 3986 compliant URL where cargo got the config.json file,\n  - If this is a registry with an HTTP index, then this is the base URL that all index queries are relative to.\n  - If this is a registry with a GIT index, it is the URL Cargo used to clone the index.\n- `kid` the identifier of the private key used to sign the request, using the [PASERK IDs](https://github.com/paseto-standard/paserk/blob/master/operations/ID.md) standard.\n\nPASETO includes the message that was signed, so the server does not have to reconstruct the exact string from the request in order to check the signature. The server does need to check that the signature is valid for the string in the PASETO and that the contents of that string matches the request.\nIf a claim should be expected for the request but is missing in the PASETO then the request must be rejected.\n\n## `cargo config`\n\n* Original Issue: [#2362](https://github.com/rust-lang/cargo/issues/2362)\n* Tracking Issue: [#9301](https://github.com/rust-lang/cargo/issues/9301)\n\nThe `cargo config` subcommand provides a way to display the configuration\nfiles that cargo loads. It currently includes the `get` subcommand which\ncan take an optional config value to display.\n\n```console\ncargo +nightly -Zunstable-options config get build.rustflags\n```\n\nIf no config value is included, it will display all config values. See the\n`--help` output for more options available.\n\n## rustc `--print`\n\n* Tracking Issue: [#9357](https://github.com/rust-lang/cargo/issues/9357)\n\n`cargo rustc --print=VAL` forwards the `--print` flag to `rustc` in order to\nextract information from `rustc`. This runs `rustc` with the corresponding\n[`--print`](https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information)\nflag, and then immediately exits without compiling. Exposing this as a cargo\nflag allows cargo to inject the correct target and RUSTFLAGS based on the\ncurrent configuration.\n\nThe primary use case is to run `cargo rustc --print=cfg` to get config values\nfor the appropriate target and influenced by any other RUSTFLAGS.\n\n\n## Different binary name\n\n* Tracking Issue: [#9778](https://github.com/rust-lang/cargo/issues/9778)\n* PR: [#9627](https://github.com/rust-lang/cargo/pull/9627)\n\nThe `different-binary-name` feature allows setting the filename of the binary without having to obey the\nrestrictions placed on crate names. For example, the crate name must use only `alphanumeric` characters\nor `-` or `_`, and cannot be empty.\n\nThe `filename` parameter should **not** include the binary extension, `cargo` will figure out the appropriate\nextension and use that for the binary on its own.\n\nThe `filename` parameter is only available in the `[[bin]]` section of the manifest.\n\n```toml\ncargo-features = [\"different-binary-name\"]\n\n[package]\nname =  \"foo\"\nversion = \"0.0.1\"\n\n[[bin]]\nname = \"foo\"\nfilename = \"007bar\"\npath = \"src/main.rs\"\n```\n\n## scrape-examples\n\n* RFC: [#3123](https://github.com/rust-lang/rfcs/pull/3123)\n* Tracking Issue: [#9910](https://github.com/rust-lang/cargo/issues/9910)\n\nThe `-Z rustdoc-scrape-examples` flag tells Rustdoc to search crates in the current workspace\nfor calls to functions. Those call-sites are then included as documentation. You can use the flag\nlike this:\n\n```\ncargo doc -Z unstable-options -Z rustdoc-scrape-examples\n```\n\nBy default, Cargo will scrape examples from the example targets of packages being documented.\nYou can individually enable or disable targets from being scraped with the `doc-scrape-examples` flag, such as:\n\n```toml\n# Enable scraping examples from a library\n[lib]\ndoc-scrape-examples = true\n\n# Disable scraping examples from an example target\n[[example]]\nname = \"my-example\"\ndoc-scrape-examples = false\n```\n\n**Note on tests:** enabling `doc-scrape-examples` on test targets will not currently have any effect. Scraping\nexamples from tests is a work-in-progress.\n\n**Note on dev-dependencies:** documenting a library does not normally require the crate's dev-dependencies. However,\nexample targets require dev-deps. For backwards compatibility, `-Z rustdoc-scrape-examples` will *not* introduce a\ndev-deps requirement for `cargo doc`. Therefore examples will *not* be scraped from example targets under the\nfollowing conditions:\n\n1. No target being documented requires dev-deps, AND\n2. At least one crate with targets being documented has dev-deps, AND\n3. The `doc-scrape-examples` parameter is unset or false for all `[[example]]` targets.\n\nIf you want examples to be scraped from example targets, then you must not satisfy one of the above conditions.\nFor example, you can set `doc-scrape-examples` to true for one example target, and that signals to Cargo that\nyou are ok with dev-deps being build for `cargo doc`.\n\n## output-format for rustdoc\n\n* Tracking Issue: [#13283](https://github.com/rust-lang/cargo/issues/13283)\n\nThis flag determines the output format of `cargo rustdoc`, accepting `html` or `json`, providing tools with a way to lean on [rustdoc's experimental JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/).\n\nYou can use the flag like this:\n\n```\ncargo rustdoc -Z unstable-options --output-format json\n```\n\n## codegen-backend\n\nThe `codegen-backend` feature makes it possible to select the codegen backend used by rustc using a profile.\n\nExample:\n\n```toml\n[package]\nname = \"foo\"\n\n[dependencies]\nserde = \"1.0.117\"\n\n[profile.dev.package.foo]\ncodegen-backend = \"cranelift\"\n```\n\nTo set this in a profile in Cargo configuration, you need to use either\n`-Z codegen-backend` or `[unstable]` table to enable it. For example,\n\n```toml\n# .cargo/config.toml\n[unstable]\ncodegen-backend = true\n\n[profile.dev.package.foo]\ncodegen-backend = \"cranelift\"\n```\n\n## gitoxide\n\n* Tracking Issue: [#11813](https://github.com/rust-lang/cargo/issues/11813)\n\nWith the 'gitoxide' unstable feature, all or the specified git operations will be performed by\nthe `gitoxide` crate instead of `git2`.\n\nWhile `-Zgitoxide` enables all currently implemented features, one can individually select git operations\nto run with `gitoxide` with the `-Zgitoxide=operation[,operationN]` syntax.\n\nValid operations are the following:\n\n* `fetch` - All fetches are done with `gitoxide`, which includes git dependencies as well as the crates index.\n* `checkout` *(planned)* - checkout the worktree, with support for filters and submodules.\n\n## git\n\n* Tracking Issue: [#13285](https://github.com/rust-lang/cargo/issues/13285)\n\nWith the 'git' unstable feature, both `gitoxide` and `git2` will perform shallow fetches of the crate\nindex and git dependencies.\n\nWhile `-Zgit` enables all currently implemented features, one can individually select when to perform\nshallow fetches with the `-Zgit=operation[,operationN]` syntax.\n\nValid operations are the following:\n\n* `shallow-index` - perform a shallow clone of the index.\n* `shallow-deps` - perform a shallow clone of git dependencies.\n\n**Details on shallow clones**\n\n* To enable shallow clones, add `-Zgit=shallow-deps` for fetching git dependencies or `-Zgit=shallow-index` for fetching registry index.\n* Shallow-cloned and shallow-checked-out git repositories reside at their own `-shallow` suffixed directories, i.e,\n  - `~/.cargo/registry/index/*-shallow`\n  - `~/.cargo/git/db/*-shallow`\n  - `~/.cargo/git/checkouts/*-shallow`\n* When the unstable feature is on, fetching/cloning a git repository is always a shallow fetch. This roughly equals to `git fetch --depth 1` everywhere.\n* Even with the presence of `Cargo.lock` or specifying a commit `{ rev = \"…\" }`, gitoxide and libgit2 are still smart enough to shallow fetch without unshallowing the existing repository.\n\n## script\n\n* Tracking Issue: [#12207](https://github.com/rust-lang/cargo/issues/12207)\n\nCargo can directly run `.rs` files as:\n```console\n$ cargo +nightly -Zscript file.rs\n```\nwhere `file.rs` can be as simple as:\n```rust\nfn main() {}\n```\n\nA user may optionally specify a manifest in a `cargo` code fence in a module-level comment, like:\n````rust\n#!/usr/bin/env -S cargo +nightly -Zscript\n---cargo\n[dependencies]\nclap = { version = \"4.2\", features = [\"derive\"] }\n---\n\nuse clap::Parser;\n\n#[derive(Parser, Debug)]\n#[clap(version)]\nstruct Args {\n    #[clap(short, long, help = \"Path to config\")]\n    config: Option<std::path::PathBuf>,\n}\n\nfn main() {\n    let args = Args::parse();\n    println!(\"{:?}\", args);\n}\n````\n\n### Single-file packages\n\nIn addition to today's multi-file packages (`Cargo.toml` file with other `.rs`\nfiles), we are adding the concept of single-file packages which may contain an\nembedded manifest.  There is no required distinguishment for a single-file\n`.rs` package from any other `.rs` file.\n\nSingle-file packages may be selected via `--manifest-path`, like\n`cargo test --manifest-path foo.rs`. Unlike `Cargo.toml`, these files cannot be auto-discovered.\n\nA single-file package may contain an embedded manifest.  An embedded manifest\nis stored using `TOML` in rust \"frontmatter\", a markdown code-fence with `cargo`\nat the start of the infostring at the top of the file.\n\nInferred / defaulted manifest fields:\n- `package.name = <slugified file stem>`\n- `package.edition = <current>` to avoid always having to add an embedded\n  manifest at the cost of potentially breaking scripts on rust upgrades\n  - Warn when `edition` is unspecified to raise awareness of this\n\nDisallowed manifest fields:\n- `[workspace]`, `[lib]`, `[[bin]]`, `[[example]]`, `[[test]]`, `[[bench]]`\n- `package.workspace`, `package.build`, `package.links`, `package.autolib`, `package.autobins`, `package.autoexamples`, `package.autotests`, `package.autobenches`\n\nThe default `CARGO_TARGET_DIR` for single-file packages is at `$CARGO_HOME/target/<hash>`:\n- Avoid conflicts from multiple single-file packages being in the same directory\n- Avoid problems with the single-file package's parent directory being read-only\n- Avoid cluttering the user's directory\n\nThe lockfile for single-file packages will be placed in `CARGO_TARGET_DIR`.  In\nthe future, when workspaces are supported, that will allow a user to have a\npersistent lockfile.\n\n### Manifest-commands\n\nYou may pass a manifest directly to the `cargo` command, without a subcommand,\nlike `foo/Cargo.toml` or a single-file package like `foo.rs`.  This is mostly\nintended for being put in `#!` lines.\n\nThe precedence for how to interpret `cargo <subcommand>` is\n1. Built-in xor single-file packages\n2. Aliases\n3. External subcommands\n\nA parameter is identified as a manifest-command if it has one of:\n- Path separators\n- A `.rs` extension\n- The file name is `Cargo.toml`\n\nDifferences between `cargo run --manifest-path <path>` and `cargo <path>`\n- `cargo <path>` runs with the config for `<path>` and not the current dir, more like `cargo install --path <path>`\n- `cargo <path>` is at a verbosity level below the normal default.  Pass `-v` to get normal output.\n\nWhen running a package with an embedded manifest,\n[`arg0`](https://doc.rust-lang.org/std/os/unix/process/trait.CommandExt.html#tymethod.arg0) will be the scripts path.\nTo get the executable's path, see [`current_exe`](https://doc.rust-lang.org/std/env/fn.current_exe.html).\n\n### Documentation Updates\n\n## Profile `trim-paths` option\n\n* Tracking Issue: [rust-lang/cargo#12137](https://github.com/rust-lang/cargo/issues/12137)\n* Tracking Rustc Issue: [rust-lang/rust#111540](https://github.com/rust-lang/rust/issues/111540)\n\nThis adds a new profile setting to control how paths are sanitized in the resulting binary.\nThis can be enabled like so:\n\n```toml\ncargo-features = [\"trim-paths\"]\n\n[package]\n# ...\n\n[profile.release]\ntrim-paths = [\"diagnostics\", \"object\"]\n```\n\nTo set this in a profile in Cargo configuration,\nyou need to use either `-Z trim-paths` or `[unstable]` table to enable it.\nFor example,\n\n```toml\n# .cargo/config.toml\n[unstable]\ntrim-paths = true\n\n[profile.release]\ntrim-paths = [\"diagnostics\", \"object\"]\n```\n\n### Documentation updates\n\n#### trim-paths\n\n*as a new [\"Profiles settings\" entry](./profiles.html#profile-settings)*\n\n`trim-paths` is a profile setting which enables and controls the sanitization of file paths in build outputs.\nIt takes the following values:\n\n- `\"none\"` and `false` --- disable path sanitization\n- `\"macro\"` --- sanitize paths in the expansion of `std::file!()` macro.\n    This is where paths in embedded panic messages come from\n- `\"diagnostics\"` --- sanitize paths in printed compiler diagnostics\n- `\"object\"` --- sanitize paths in compiled executables or libraries\n- `\"all\"` and `true` --- sanitize paths in all possible locations\n\nIt also takes an array with the combinations of `\"macro\"`, `\"diagnostics\"`, and `\"object\"`.\n\nIt is defaulted to `none` for the `dev` profile, and `object` for the `release` profile.\nYou can manually override it by specifying this option in `Cargo.toml`:\n\n```toml\n[profile.dev]\ntrim-paths = \"all\"\n\n[profile.release]\ntrim-paths = [\"object\", \"diagnostics\"]\n```\n\nThe default `release` profile setting (`object`) sanitizes only the paths in emitted executable or library files.\nIt always affects paths from macros such as panic messages, and in debug information only if they will be embedded together with the binary\n(the default on platforms with ELF binaries, such as Linux and windows-gnu),\nbut will not touch them if they are in separate files (the default on Windows MSVC and macOS).\nBut the paths to these separate files are sanitized.\n\nIf `trim-paths` is not `none` or `false`, then the following paths are sanitized if they appear in a selected scope:\n\n1. Path to the source files of the standard and core library (sysroot) will begin with `/rustc/[rustc commit hash]`,\n   e.g. `/home/username/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs` ->\n   `/rustc/fe72845f7bb6a77b9e671e6a4f32fe714962cec4/library/core/src/result.rs`\n2. Path to the current package will be stripped, relatively to the current workspace root, e.g. `/home/username/crate/src/lib.rs` -> `src/lib.rs`.\n3. Path to dependency packages will be replaced with `[package name]-[version]`. E.g. `/home/username/deps/foo/src/lib.rs` -> `foo-0.1.0/src/lib.rs`\n\nWhen a path to the source files of the standard and core library is *not* in scope for sanitization,\nthe emitted path will depend on if `rust-src` component is present.\nIf it is, then some paths will point to the copy of the source files on your file system;\nif it isn't, then they will show up as `/rustc/[rustc commit hash]/library/...`\n(just like when it is selected for sanitization).\nPaths to all other source files will not be affected.\n\nThis will not affect any hard-coded paths in the source code, such as in strings.\n\n#### Environment variable\n\n*as a new entry of [\"Environment variables Cargo sets for build scripts\"](./environment-variables.md#environment-variables-cargo-sets-for-crates)*\n\n* `CARGO_TRIM_PATHS` --- The value of `trim-paths` profile option.\n    `false`, `\"none\"`, and empty arrays would be converted to `none`.\n    `true` and `\"all\"` become `all`.\n    Values in a non-empty array would be joined into a comma-separated list.\n    If the build script introduces absolute paths to built artifacts (such as by invoking a compiler),\n    the user may request them to be sanitized in different types of artifacts.\n    Common paths requiring sanitization include `OUT_DIR`, `CARGO_MANIFEST_DIR` and `CARGO_MANIFEST_PATH`,\n    plus any other introduced by the build script, such as include directories.\n\n## gc\n\n* Tracking Issue: [#12633](https://github.com/rust-lang/cargo/issues/12633)\n\nThe `-Zgc` flag is used to enable certain features related to garbage-collection of cargo's global cache within the cargo home directory.\n\n#### Automatic gc configuration\n\nThe `-Zgc` flag will enable Cargo to read extra configuration options related to garbage collection.\nThe settings available are:\n\n```toml\n# Example config.toml file.\n\n# Sub-table for defining specific settings for cleaning the global cache.\n[cache.global-clean]\n# Anything older than this duration will be deleted in the source cache.\nmax-src-age = \"1 month\"\n# Anything older than this duration will be deleted in the compressed crate cache.\nmax-crate-age = \"3 months\"\n# Any index older than this duration will be deleted from the index cache.\nmax-index-age = \"3 months\"\n# Any git checkout older than this duration will be deleted from the checkout cache.\nmax-git-co-age = \"1 month\"\n# Any git clone older than this duration will be deleted from the git cache.\nmax-git-db-age = \"3 months\"\n```\n\nNote that the [`cache.auto-clean-frequency`] option was stabilized in Rust 1.88.\n\n[`cache.auto-clean-frequency`]: config.md#cacheauto-clean-frequency\n\n### Manual garbage collection with `cargo clean`\n\nManual deletion can be done with the `cargo clean gc -Zgc` command.\nDeletion of cache contents can be performed by passing one of the cache options:\n\n- `--max-src-age=DURATION` --- Deletes source cache files that have not been used since the given age.\n- `--max-crate-age=DURATION` --- Deletes crate cache files that have not been used since the given age.\n- `--max-index-age=DURATION` --- Deletes registry indexes that have not been used since then given age (including their `.crate` and `src` files).\n- `--max-git-co-age=DURATION` --- Deletes git dependency checkouts that have not been used since then given age.\n- `--max-git-db-age=DURATION` --- Deletes git dependency clones that have not been used since then given age.\n- `--max-download-age=DURATION` --- Deletes any downloaded cache data that has not been used since then given age.\n- `--max-src-size=SIZE` --- Deletes the oldest source cache files until the cache is under the given size.\n- `--max-crate-size=SIZE` --- Deletes the oldest crate cache files until the cache is under the given size.\n- `--max-git-size=SIZE` --- Deletes the oldest git dependency caches until the cache is under the given size.\n- `--max-download-size=SIZE` --- Deletes the oldest downloaded cache data until the cache is under the given size.\n\nA DURATION is specified in the form \"N seconds/minutes/days/weeks/months\" where N is an integer.\n\nA SIZE is specified in the form \"N *suffix*\" where *suffix* is B, kB, MB, GB, kiB, MiB, or GiB, and N is an integer or floating point number. If no suffix is specified, the number is the number of bytes.\n\n```sh\ncargo clean gc -Zgc\ncargo clean gc -Zgc --max-download-age=1week\ncargo clean gc -Zgc --max-git-size=0 --max-download-size=100MB\n```\n\n## open-namespaces\n\n* Tracking Issue: [#13576](https://github.com/rust-lang/cargo/issues/13576)\n\nAllow multiple packages to participate in the same API namespace\n\nThis can be enabled like so:\n```toml\ncargo-features = [\"open-namespaces\"]\n\n[package]\n# ...\n```\n\n## panic-immediate-abort\n\n* Tracking Issue: [#16042](https://github.com/rust-lang/cargo/issues/16042)\n* Upstream Tracking Issue: [rust-lang/rust#147286](https://github.com/rust-lang/rust/issues/147286)\n\nExtends the `panic` profile setting to support the\n[`immediate-abort`](../../rustc/codegen-options/index.html#panic) panic strategy.\nThis can be enabled like so:\n\n```toml\n# Cargo.toml\ncargo-features = [\"panic-immediate-abort\"]\n\n[package]\n# ...\n\n[profile.release]\npanic = \"immediate-abort\"\n```\n\nTo set this in a profile in Cargo configuration,\nyou need to use either `-Z panic-immediate-abort` CLI flag\nor the `[unstable]` table to enable it.\nFor example,\n\n```toml\n# .cargo/config.toml\n[unstable]\npanic-immediate-abort = true\n\n[profile.release]\npanic = \"immediate-abort\"\n```\n\n## fine-grain-locking\n\n* Tracking Issue: [#4282](https://github.com/rust-lang/cargo/issues/4282)\n\nUse fine grain locking instead of locking the entire build cache.\n\nNote: Fine grain locking implicitly enables [build-dir-new-layout](#build-dir-new-layout) as fine grain locking builds on that directory reoganization.\n\n## `[lints.cargo]`\n\n* Tracking Issue: [#12235](https://github.com/rust-lang/cargo/issues/12235)\n\nA new `lints` tool table for `cargo` that can be used to configure lints emitted\nby `cargo` itself when `-Zcargo-lints` is used\n```toml\n[lints.cargo]\nimplicit-features = \"warn\"\n```\n\nThis will work with\n[RFC 2906 `workspace-deduplicate`](https://rust-lang.github.io/rfcs/2906-cargo-workspace-deduplicate.html):\n```toml\n[workspace.lints.cargo]\nimplicit-features = \"warn\"\n\n[lints]\nworkspace = true\n```\n\n## Path Bases\n\n* Tracking Issue: [#14355](https://github.com/rust-lang/cargo/issues/14355)\n\nA `path` dependency may optionally specify a base by setting the `base` key to\nthe name of a path base from the `[path-bases]` table in either the\n[configuration](config.md) or one of the [built-in path bases](#built-in-path-bases).\nThe value of that path base is prepended to the `path` value (along with a path\nseparator if necessary) to produce the actual location where Cargo will look for\nthe dependency.\n\nFor example, if the `Cargo.toml` contains:\n\n```toml\ncargo-features = [\"path-bases\"]\n\n[dependencies]\nfoo = { base = \"dev\", path = \"foo\" }\n```\n\nGiven a `[path-bases]` table in the configuration that contains:\n\n```toml\n[path-bases]\ndev = \"/home/user/dev/rust/libraries/\"\n```\n\nThis will produce a `path` dependency `foo` located at\n`/home/user/dev/rust/libraries/foo`.\n\nPath bases can be either absolute or relative. Relative path bases are relative\nto the parent directory of the configuration file that declared that path base.\n\nThe name of a path base must use only [alphanumeric](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphanumeric)\ncharacters or `-` or `_`, must start with an [alphabetic](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphabetic)\ncharacter, and must not be empty.\n\nIf the name of path base used in a dependency is neither in the configuration\nnor one of the built-in path base, then Cargo will raise an error.\n\n#### Built-in path bases\n\nCargo provides implicit path bases that can be used without the need to specify\nthem in a `[path-bases]` table.\n\n* `workspace` - If a project is [a workspace or workspace member](workspaces.md)\nthen this path base is defined as the parent directory of the root `Cargo.toml`\nof the workspace.\n\nIf a built-in path base name is also declared in the configuration, then Cargo\nwill prefer the value in the configuration. The allows Cargo to add new built-in\npath bases without compatibility issues (as existing uses will shadow the\nbuilt-in name).\n\n## lockfile-path\n\n* Original Issue: [#5707](https://github.com/rust-lang/cargo/issues/5707)\n* Tracking Issue: [#14421](https://github.com/rust-lang/cargo/issues/14421)\n\nThe `-Zlockfile-path` flag enables the `resolver.lockfile-path` configuration option,\nwhich allows you to specify the path of the lockfile `Cargo.lock`.\n\nBy default, lockfile is written into `<workspace_root>/Cargo.lock`. \nHowever, when sources are stored in read-only directory,\nmost of the cargo commands would fail when trying to write a lockfile.\nThis configuration makes it easier to work with readonly sources. \n\nNote, that currently path must end with `Cargo.lock`.\nIf you want to use this feature in multiple projects,\nlockfiles should be stored in different directories.\n\n### Documentation updates\n\n*as a new `resolver.lockfile-path` entry in config.md*\n\n#### `resolver.lockfile-path`\n\n* Type: string (path)\n* Default: `<workspace_root>/Cargo.lock`\n* Environment: `CARGO_RESOLVER_LOCKFILE_PATH`\n\nSpecifies the path to the lockfile.\nBy default, the lockfile is written to `<workspace_root>/Cargo.lock`.\nThis option is useful when working with read-only source directories.\n\nThe path must end with `Cargo.lock`.\n\n## native-completions\n* Original Issue: [#6645](https://github.com/rust-lang/cargo/issues/6645)\n* Tracking Issue: [#14520](https://github.com/rust-lang/cargo/issues/14520)\n\nThis feature moves the handwritten completion scripts to Rust native, making it\neasier for us to add, extend and test new completions. This feature is enabled with the\nnightly channel, without requiring additional `-Z` options.\n\nAreas of particular interest for feedback\n- Arguments that need escaping or quoting that aren't handled correctly\n- Inaccuracies in the information\n- Bugs in parsing of the command-line\n- Arguments that don't report their completions\n- If a known issue is being problematic\n\nFeedback can be broken down into\n- What completion candidates are reported\n  - Known issues: [#14520](https://github.com/rust-lang/cargo/issues/14520), [`A-completions`](https://github.com/rust-lang/cargo/labels/A-completions)\n  - [Report an issue](https://github.com/rust-lang/cargo/issues/new) or [discuss the behavior](https://github.com/rust-lang/cargo/issues/14520)\n- Shell integration, command-line parsing, and completion filtering\n  - Known issues: [clap#3166](https://github.com/clap-rs/clap/issues/3166), [clap's `A-completions`](https://github.com/clap-rs/clap/labels/A-completion)\n  - [Report an issue](https://github.com/clap-rs/clap/issues/new/choose) or [discuss the behavior](https://github.com/clap-rs/clap/discussions/new/choose)\n\nWhen in doubt, you can discuss this in [#14520](https://github.com/rust-lang/cargo/issues/14520) or on [zulip](https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo)\n\n### How to use native-completions feature:\n- bash:\n  Add `source <(CARGO_COMPLETE=bash cargo +nightly)` to `~/.local/share/bash-completion/completions/cargo`.\n\n- zsh:\n  Add `source <(CARGO_COMPLETE=zsh cargo +nightly)` to your `.zshrc`.\n  \n- fish:\n  Add `source (CARGO_COMPLETE=fish cargo +nightly | psub)` to `$XDG_CONFIG_HOME/fish/completions/cargo.fish`\n\n- elvish:\n  Add `eval (E:CARGO_COMPLETE=elvish cargo +nightly | slurp)` to `$XDG_CONFIG_HOME/elvish/rc.elv`\n\n- powershell:\n  Add `CARGO_COMPLETE=powershell cargo +nightly | Invoke-Expression` to `$PROFILE`.\n\n## warnings\n\n* Original Issue: [#8424](https://github.com/rust-lang/cargo/issues/8424)\n* Tracking Issue: [#14802](https://github.com/rust-lang/cargo/issues/14802)\n\nThe `-Z warnings` feature enables the `build.warnings` configuration option to control how\nCargo handles warnings. If the `-Z warnings` unstable flag is not enabled, then\nthe `build.warnings` config will be ignored.\n\nThis setting currently only applies to rustc warnings. It may apply to additional warnings (such as Cargo lints or Cargo warnings)\nin the future.\n\n### `build.warnings`\n* Type: string\n* Default: `warn`\n* Environment: `CARGO_BUILD_WARNINGS`\n\nControls how Cargo handles warnings. Allowed values are:\n* `warn`: warnings are emitted as warnings (default).\n* `allow`: warnings are hidden.\n* `deny`: if warnings are emitted, an error will be raised at the end of the current crate and the process. Use `--keep-going` to see all warnings.\n\n## feature unification\n\n* RFC: [#3692](https://github.com/rust-lang/rfcs/blob/master/text/3692-feature-unification.md)\n* Tracking Issue: [#14774](https://github.com/rust-lang/cargo/issues/14774)\n\nThe `-Z feature-unification` enables the `resolver.feature-unification`\nconfiguration option to control how features are unified across a workspace.\nIf the `-Z feature-unification` unstable flag is not enabled,\nthen the `resolver.feature-unification` configuration will be ignored.\n\n### `resolver.feature-unification`\n\n* Type: string\n* Default: `\"selected\"`\n* Environment: `CARGO_RESOLVER_FEATURE_UNIFICATION`\n\nSpecify which packages participate in [feature unification](../reference/features.html#feature-unification).\n\n* `selected`: Merge dependency features from all packages specified for the current build.\n* `workspace`: Merge dependency features across all workspace members,\n  regardless of which packages are specified for the current build.\n* `package`: Dependency features are considered on a package-by-package basis,\n  preferring duplicate builds of dependencies when different sets of features are activated by the packages.\n\n## lockfile-publish-time\n\n* Original Issue: [#5221](https://github.com/rust-lang/cargo/issues/5221)\n* Tracking Issue: [#16271](https://github.com/rust-lang/cargo/issues/16271)\n\nWith `cargo generate-lockfile -Zunstable-options --publish-time <time>`,\npackage resolution will not consider any package newer than the specified time.\n\n## Package message format\n\n* Original Issue: [#11666](https://github.com/rust-lang/cargo/issues/11666)\n* Tracking Issue: [#15353](https://github.com/rust-lang/cargo/issues/15353)\n\nThe `--message-format` flag in `cargo package` controls the output message format.\nCurrently, it only works with the `--list` flag and affects the file listing format,\nRequires `-Zunstable-options`.\nSee [`cargo package --message-format`](../commands/cargo-package.md#option-cargo-package---message-format)\nfor more information.\n\n## rustdoc depinfo\n\n* Original Issue: [#12266](https://github.com/rust-lang/cargo/issues/12266)\n* Tracking Issue: [#15370](https://github.com/rust-lang/cargo/issues/15370)\n\nThe `-Z rustdoc-depinfo` flag leverages rustdoc's dep-info files to determine\nwhether documentations are required to re-generate. This can be combined with\n`-Z checksum-freshness` to detect checksum changes rather than file mtime.\n\n## no-embed-metadata\n* Original Pull Request: [#15378](https://github.com/rust-lang/cargo/pull/15378)\n* Tracking Issue: [#15495](https://github.com/rust-lang/cargo/issues/15495)\n\nThe default behavior of Rust is to embed crate metadata into `rlib` and `dylib` artifacts.\nSince Cargo also passes `--emit=metadata` to these intermediate artifacts to enable pipelined\ncompilation, this means that a lot of metadata ends up being duplicated on disk, which wastes\ndisk space in the target directory.\n\nThis feature tells Cargo to pass the `-Zembed-metadata=no` flag to the compiler, which instructs\nit not to embed metadata within rlib and dylib artifacts. In this case, the metadata will only\nbe stored in `.rmeta` files.\n\n```console\ncargo +nightly -Zno-embed-metadata build\n```\n\n## `unstable-editions`\n\nThe `unstable-editions` value in the `cargo-features` list allows a `Cargo.toml` manifest to specify an edition that is not yet stable.\n\n```toml\ncargo-features = [\"unstable-editions\"]\n\n[package]\nname = \"my-package\"\nedition = \"future\"\n```\n\nWhen new editions are introduced, the `unstable-editions` feature is required until the edition is stabilized.\n\nThe special \"future\" edition is a home for new features that are under development, and is permanently unstable. The \"future\" edition also has no new behavior by itself. Each change in the future edition requires an opt-in such as a `#![feature(...)]` attribute.\n\n## `fix-edition`\n\n`-Zfix-edition` is a permanently unstable flag to assist with testing edition migrations, particularly with the use of crater. It only works with the `cargo fix` subcommand. It takes two different forms:\n\n- `-Zfix-edition=start=$INITIAL` --- This form checks if the current edition is equal to the given number. If not, it exits with success (because we want to ignore older editions). If it is, then it runs the equivalent of `cargo check`. This is intended to be used with crater's \"start\" toolchain to set a baseline for the \"before\" toolchain.\n- `-Zfix-edition=end=$INITIAL,$NEXT` --- This form checks if the current edition is equal to the given `$INITIAL` value. If not, it exits with success. If it is, then it performs an edition migration to the edition specified in `$NEXT`. Afterwards, it will modify `Cargo.toml` to add the appropriate `cargo-features = [\"unstable-edition\"]`, update the `edition` field, and run the equivalent of `cargo check` to verify that the migration works on the new edition.\n\nFor example:\n\n```console\ncargo +nightly fix -Zfix-edition=end=2024,future\n```\n\n## section-timings\n* Original Pull Request: [#15780](https://github.com/rust-lang/cargo/pull/15780)\n* Tracking Issue: [#15817](https://github.com/rust-lang/cargo/issues/15817)\n\nThis feature can be used to extend the output of `cargo build --timings`. It will tell rustc\nto produce timings of individual compilation sections, which will be then displayed in the timings\nHTML/JSON output.\n\n```console\ncargo +nightly -Zsection-timings build --timings\n```\n\n## Build analysis\n\n* Original Issue: [rust-lang/rust-project-goals#332](https://github.com/rust-lang/rust-project-goals/pull/332)\n* Tracking Issue: [#15844](https://github.com/rust-lang/cargo/issues/15844)\n\nThe `-Zbuild-analysis` feature records and persists detailed build metrics on disk,\nwith new commands to query past builds.\n\nWhen enabled,\nCargo writes build logs in JSONL format to the `$CARGO_HOME/log/` directory \nEach cargo invocation produces a log file named with a unique session ID.\nThese logs contain timing information, rebuild reasons, and other build metadata\nthat can be analyzed with the `cargo report` subcommands.\n\nTo enable build analysis, add the following [Cargo configuration](config.md):\n\n```toml\n# Example config.toml file.\n\n[unstable]\nbuild-analysis = true\n\n# Enable the build metric collection\n[build.analysis]\nenabled = true\n```\n\nSetting it on a stable toolchain only emits an unknown config warning,\nso it's safe to keep enabled in your Cargo configuration.\n\n### `cargo report` commands\n\nThe following commands are available under `-Zbuild-analysis`:\n\n- `cargo report sessions` --- Lists previous build sessions.\n  Use this to find session IDs for other report commands.\n- `cargo report timings` --- Generates an HTML timing report from a previous session,\n  similar to `cargo build --timings` but without rebuilding.\n- `cargo report rebuilds` --- Reports why crates were rebuilt,\n  helping diagnose unexpected recompilations.\n\n## build-dir-new-layout\n\n* Tracking Issue: [#15010](https://github.com/rust-lang/cargo/issues/15010)\n\nEnables the new build-dir filesystem layout.\nThis layout change unblocks work towards caching and locking improvements.\n\n\n## compile-time-deps\n\nThis permanently-unstable flag to only build proc-macros and build scripts (and their required dependencies),\nas well as run the build scripts.\n\nIt is intended for use by tools like rust-analyzer and will never be stabilized.\n\nExample:\n\n```console\ncargo +nightly build --compile-time-deps -Z unstable-options\ncargo +nightly check --compile-time-deps --all-targets -Z unstable-options\n```\n\n## `rustc-unicode`\n* Tracking Issue: [rust#148607](https://github.com/rust-lang/rust/issues/148607)\n\nEnable `rustc`'s unicode error format in Cargo's error messages\n\n## rustdoc mergeable info\n\n* Original Pull Request: [#16309](https://github.com/rust-lang/cargo/pull/16309)\n* Tracking issue: [#16306](https://github.com/rust-lang/cargo/issues/16306)\n* Tracking rustc issue: [rust-lang/rust#130676](https://github.com/rust-lang/rust/issues/130676)\n\nThe `-Z rustdoc-mergeable-info` leverage rustdoc's mergeable crate info,\nso that `cargo doc` can merge cross-crate information\n(like the search index, source files index, etc.)\nfrom separate output directories,\nand run `rustdoc` in parallel.\n\n## target-spec-json\n* Tracking Issue: [rust-lang/rust#151528](https://github.com/rust-lang/rust/issues/151528)\n\nThe `-Z target-spec-json` CLI flag enables the ability to use [custom target spec JSON files](https://doc.rust-lang.org/nightly/rustc/targets/custom.html) as a target.\n\n```console\ncargo +nightly build --target my-target.json -Z target-spec-json\n```\n\nThis usually must be combined with [build-std](#build-std).\n\n# Stabilized and removed features\n\n## Compile progress\n\nThe compile-progress feature has been stabilized in the 1.30 release.\nProgress bars are now enabled by default.\nSee [`term.progress`](config.md#termprogresswhen) for more information about\ncontrolling this feature.\n\n## Edition\n\nSpecifying the `edition` in `Cargo.toml` has been stabilized in the 1.31 release.\nSee [the edition field](manifest.md#the-edition-field) for more information\nabout specifying this field.\n\n## rename-dependency\n\nSpecifying renamed dependencies in `Cargo.toml` has been stabilized in the 1.31 release.\nSee [renaming dependencies](specifying-dependencies.md#renaming-dependencies-in-cargotoml)\nfor more information about renaming dependencies.\n\n## Alternate Registries\n\nSupport for alternate registries has been stabilized in the 1.34 release.\nSee the [Registries chapter](registries.md) for more information about alternate registries.\n\n## Offline Mode\n\nThe offline feature has been stabilized in the 1.36 release.\nSee the [`--offline` flag](../commands/cargo.md#option-cargo---offline) for\nmore information on using the offline mode.\n\n## publish-lockfile\n\nThe `publish-lockfile` feature has been removed in the 1.37 release.\nThe `Cargo.lock` file is always included when a package is published if the\npackage contains a binary target. `cargo install` requires the `--locked` flag\nto use the `Cargo.lock` file.\nSee [`cargo package`](../commands/cargo-package.md) and\n[`cargo install`](../commands/cargo-install.md) for more information.\n\n## default-run\n\nThe `default-run` feature has been stabilized in the 1.37 release.\nSee [the `default-run` field](manifest.md#the-default-run-field) for more\ninformation about specifying the default target to run.\n\n## cache-messages\n\nCompiler message caching has been stabilized in the 1.40 release.\nCompiler warnings are now cached by default and will be replayed automatically\nwhen re-running Cargo.\n\n## install-upgrade\n\nThe `install-upgrade` feature has been stabilized in the 1.41 release.\n[`cargo install`] will now automatically upgrade packages if they appear to be\nout-of-date. See the [`cargo install`] documentation for more information.\n\n[`cargo install`]: ../commands/cargo-install.md\n\n## Profile Overrides\n\nProfile overrides have been stabilized in the 1.41 release.\nSee [Profile Overrides](profiles.md#overrides) for more information on using\noverrides.\n\n## Config Profiles\n\nSpecifying profiles in Cargo config files and environment variables has been\nstabilized in the 1.43 release.\nSee the [config `[profile]` table](config.md#profile) for more information\nabout specifying [profiles](profiles.md) in config files.\n\n## crate-versions\n\nThe `-Z crate-versions` flag has been stabilized in the 1.47 release.\nThe crate version is now automatically included in the\n[`cargo doc`](../commands/cargo-doc.md) documentation sidebar.\n\n## Features\n\nThe `-Z features` flag has been stabilized in the 1.51 release.\nSee [feature resolver version 2](features.md#feature-resolver-version-2)\nfor more information on using the new feature resolver.\n\n## package-features\n\nThe `-Z package-features` flag has been stabilized in the 1.51 release.\nSee the [resolver version 2 command-line flags](features.md#resolver-version-2-command-line-flags)\nfor more information on using the features CLI options.\n\n## Resolver\n\nThe `resolver` feature in `Cargo.toml` has been stabilized in the 1.51 release.\nSee the [resolver versions](resolver.md#resolver-versions) for more\ninformation about specifying resolvers.\n\n## extra-link-arg\n\nThe `extra-link-arg` feature to specify additional linker arguments in build\nscripts has been stabilized in the 1.56 release. See the [build script\ndocumentation](build-scripts.md#outputs-of-the-build-script) for more\ninformation on specifying extra linker arguments.\n\n## configurable-env\n\nThe `configurable-env` feature to specify environment variables in Cargo\nconfiguration has been stabilized in the 1.56 release. See the [config\ndocumentation](config.html#env) for more information about configuring\nenvironment variables.\n\n## rust-version\n\nThe `rust-version` field in `Cargo.toml` has been stabilized in the 1.56 release.\nSee the [rust-version field](manifest.html#the-rust-version-field) for more\ninformation on using the `rust-version` field and the `--ignore-rust-version` option.\n\n## patch-in-config\n\nThe `-Z patch-in-config` flag, and the corresponding support for\n`[patch]` section in Cargo configuration files has been stabilized in\nthe 1.56 release. See the [patch field](config.html#patch) for more\ninformation.\n\n## edition 2021\n\nThe 2021 edition has been stabilized in the 1.56 release.\nSee the [`edition` field](manifest.md#the-edition-field) for more information on setting the edition.\nSee [`cargo fix --edition`](../commands/cargo-fix.md) and [The Edition Guide](../../edition-guide/index.html) for more information on migrating existing projects.\n\n\n## Custom named profiles\n\nCustom named profiles have been stabilized in the 1.57 release. See the\n[profiles chapter](profiles.md#custom-profiles) for more information.\n\n## Profile `strip` option\n\nThe profile `strip` option has been stabilized in the 1.59 release. See the\n[profiles chapter](profiles.md#strip) for more information.\n\n## Future incompat report\n\nSupport for generating a future-incompat report has been stabilized\nin the 1.59 release. See the [future incompat report chapter](future-incompat-report.md)\nfor more information.\n\n## Namespaced features\n\nNamespaced features has been stabilized in the 1.60 release.\nSee the [Features chapter](features.md#optional-dependencies) for more information.\n\n## Weak dependency features\n\nWeak dependency features has been stabilized in the 1.60 release.\nSee the [Features chapter](features.md#dependency-features) for more information.\n\n## timings\n\nThe `-Ztimings` option has been stabilized as `--timings` in the 1.60 release.\nThe timings output format option\n(e.g., the `--timings=html` and the machine-readable `--timings=json` output)\nhas been removed in 1.94.0-nightly.\n\n## config-cli\n\nThe `--config` CLI option has been stabilized in the 1.63 release. See\nthe [config documentation](config.html#command-line-overrides) for more\ninformation.\n\n## multitarget\n\nThe `-Z multitarget` option has been stabilized in the 1.64 release.\nSee [`build.target`](config.md#buildtarget) for more information about\nsetting the default [target platform triples][target triple].\n\n## crate-type\n\nThe `--crate-type` flag for `cargo rustc` has been stabilized in the 1.64\nrelease. See the [`cargo rustc` documentation](../commands/cargo-rustc.md)\nfor more information.\n\n\n## Workspace Inheritance\n\nWorkspace Inheritance has been stabilized in the 1.64 release.\nSee [workspace.package](workspaces.md#the-package-table),\n[workspace.dependencies](workspaces.md#the-dependencies-table),\nand [inheriting-a-dependency-from-a-workspace](specifying-dependencies.md#inheriting-a-dependency-from-a-workspace)\nfor more information.\n\n## terminal-width\n\nThe `-Z terminal-width` option has been stabilized in the 1.68 release.\nThe terminal width is always passed to the compiler when running from a\nterminal where Cargo can automatically detect the width.\n\n## sparse-registry\n\nSparse registry support has been stabilized in the 1.68 release.\nSee [Registry Protocols](registries.md#registry-protocols) for more information.\n\n### `cargo logout`\n\nThe [`cargo logout`] command has been stabilized in the 1.70 release.\n\n[target triple]: ../appendix/glossary.md#target '\"target\" (glossary)'\n[`cargo logout`]: ../commands/cargo-logout.md\n\n## `doctest-in-workspace`\n\nThe `-Z doctest-in-workspace` option for `cargo test` has been stabilized and\nenabled by default in the 1.72 release. See the\n[`cargo test` documentation](../commands/cargo-test.md#working-directory-of-tests)\nfor more information about the working directory for compiling and running tests.\n\n## keep-going\n\nThe `--keep-going` option has been stabilized in the 1.74 release. See the\n[`--keep-going` flag](../commands/cargo-build.html#option-cargo-build---keep-going)\nin `cargo build` as an example for more details.\n\n## `[lints]`\n\n[`[lints]`](manifest.html#the-lints-section) (enabled via `-Zlints`) has been stabilized in the 1.74 release.\n\n## credential-process\n\nThe `-Z credential-process` feature has been stabilized in the 1.74 release.\n\nSee [Registry Authentication](registry-authentication.md) documentation for details.\n\n## registry-auth\n\nThe `-Z registry-auth` feature has been stabilized in the 1.74 release with the additional\nrequirement that a credential-provider is configured.\n\nSee [Registry Authentication](registry-authentication.md) documentation for details.\n\n## check-cfg\n\nThe `-Z check-cfg` feature has been stabilized in the 1.80 release by making it the\ndefault behavior.\n\nSee the [build script documentation](build-scripts.md#rustc-check-cfg) for information\nabout specifying custom cfgs.\n\n## Edition 2024\n\nThe 2024 edition has been stabilized in the 1.85 release.\nSee the [`edition` field](manifest.md#the-edition-field) for more information on setting the edition.\nSee [`cargo fix --edition`](../commands/cargo-fix.md) and [The Edition Guide](../../edition-guide/index.html) for more information on migrating existing projects.\n\n## Automatic garbage collection\n\nSupport for automatically deleting old files was stabilized in Rust 1.88.\nMore information can be found in the [config chapter](config.md#cache).\n\n## doctest-xcompile\n\nDoctest cross-compiling is now unconditionally enabled starting in Rust 1.89. Running doctests with `cargo test` will now honor the `--target` flag.\n\n## package-workspace\n\nMulti-package publishing has been stabilized in Rust 1.90.0.\n\n## build-dir\n\nSupport for `build.build-dir` was stabilized in the 1.91 release.\nSee the [config documentation](config.md#buildbuild-dir) for information about changing the build-dir\n\n## Build-plan\n\nThe `--build-plan` argument for the `build` command has been removed in 1.93.0-nightly.\nSee <https://github.com/rust-lang/cargo/issues/7614> for the reason for its removal.\n\n## config-include\n\nSupport for including extra configuration files via the `include` config key\nhas been stabilized in 1.93.0.\nSee the [`include` config documentation](config.md#include) for more.\n\n## pubtime\n\nThe `pubtime` index field  has been stabilized in Rust 1.94.0.\n"
  },
  {
    "path": "src/doc/src/reference/workspaces.md",
    "content": "# Workspaces\n\nA *workspace* is a collection of one or more packages, called *workspace\nmembers*, that are managed together.\n\nThe key points of workspaces are:\n\n* Common commands can run across all workspace members, like `cargo check --workspace`.\n* All packages share a common [`Cargo.lock`] file which resides in the\n  *workspace root*.\n* All packages share a common [output directory], which defaults to a\n  directory named `target` in the *workspace root*.\n* Sharing package metadata, like with [`workspace.package`](#the-package-table).\n* The [`[patch]`][patch], [`[replace]`][replace] and [`[profile.*]`][profiles]\n  sections in `Cargo.toml` are only recognized in the *root* manifest, and\n  ignored in member crates' manifests.\n\nThe root `Cargo.toml` of a workspace supports the following sections:\n\n* [`[workspace]`](#the-workspace-section) --- Defines a workspace.\n  * [`resolver`](resolver.md#resolver-versions) --- Sets the dependency resolver to use.\n  * [`members`](#the-members-and-exclude-fields) --- Packages to include in the workspace.\n  * [`exclude`](#the-members-and-exclude-fields) --- Packages to exclude from the workspace.\n  * [`default-members`](#the-default-members-field) --- Packages to operate on when a specific package wasn't selected.\n  * [`package`](#the-package-table) --- Keys for inheriting in packages.\n  * [`dependencies`](#the-dependencies-table) --- Keys for inheriting in package dependencies.\n  * [`lints`](#the-lints-table) --- Keys for inheriting in package lints.\n  * [`metadata`](#the-metadata-table) --- Extra settings for external tools.\n* [`[patch]`](overriding-dependencies.md#the-patch-section) --- Override dependencies.\n* [`[replace]`](overriding-dependencies.md#the-replace-section) --- Override dependencies (deprecated).\n* [`[profile]`](profiles.md) --- Compiler settings and optimizations.\n\n## The `[workspace]` section\n\nTo create a workspace, you add the `[workspace]` table to a `Cargo.toml`:\n```toml\n[workspace]\n# ...\n```\n\nAt minimum, a workspace has to have a member, either with a root package or as\na virtual manifest.\n\n### Root package\n\nIf the [`[workspace]` section](#the-workspace-section) is added to a\n`Cargo.toml` that already defines a `[package]`, the package is\nthe *root package* of the workspace. The *workspace root* is the directory\nwhere the workspace's `Cargo.toml` is located.\n\n```toml\n[workspace]\n\n[package]\nname = \"hello_world\" # the name of the package\nversion = \"0.1.0\"    # the current version, obeying semver\n```\n\n### Virtual workspace\n\nAlternatively, a `Cargo.toml` file can be created with a `[workspace]` section\nbut without a [`[package]` section][package]. This is called a *virtual\nmanifest*. This is typically useful when there isn't a \"primary\" package, or\nyou want to keep all the packages organized in separate directories.\n\n```toml\n# [PROJECT_DIR]/Cargo.toml\n[workspace]\nmembers = [\"hello_world\"]\nresolver = \"3\"\n```\n\n```toml\n# [PROJECT_DIR]/hello_world/Cargo.toml\n[package]\nname = \"hello_world\" # the name of the package\nversion = \"0.1.0\"    # the current version, obeying semver\nedition = \"2024\"     # the edition, will have no effect on a resolver used in the workspace\n```\n\nBy having a workspace without a root package,\n\n- [`resolver`](resolver.md#resolver-versions) must be\n  set explicitly in virtual workspaces as they have no\n  [`package.edition`][package-edition] to infer it from\n  [resolver version](resolver.md#resolver-versions).\n- Commands run in the workspace root will run against all workspace\n  members by default, see [`default-members`](#the-default-members-field).\n\n## The `members` and `exclude` fields \n\nThe `members` and `exclude` fields define which packages are members of\nthe workspace:\n\n```toml\n[workspace]\nmembers = [\"member1\", \"path/to/member2\", \"crates/*\"]\nexclude = [\"crates/foo\", \"path/to/other\"]\n```\n\nAll [`path` dependencies] residing in the workspace directory automatically\nbecome members. Additional members can be listed with the `members` key, which\nshould be an array of strings containing directories with `Cargo.toml` files.\n\nThe `members` list also supports [globs] to match multiple paths, using\ntypical filename glob patterns like `*` and `?`.\n\nThe `exclude` key can be used to prevent paths from being included in a\nworkspace. This can be useful if some path dependencies aren't desired to be\nin the workspace at all, or using a glob pattern and you want to remove a\ndirectory.\n\nWhen inside a subdirectory within the workspace, Cargo will automatically\nsearch the parent directories for a `Cargo.toml` file with a `[workspace]`\ndefinition to determine which workspace to use. The [`package.workspace`]\nmanifest key can be used in member crates to point at a workspace's root to\noverride this automatic search. The manual setting can be useful if the member\nis not inside a subdirectory of the workspace root.\n\n### Package selection\n\nIn a workspace, package-related Cargo commands like [`cargo build`] can use\nthe `-p` / `--package` or `--workspace` command-line flags to determine which\npackages to operate on. If neither of those flags are specified, Cargo will\nuse the package in the current working directory. However, if the current directory is\na workspace root, the [`default-members`](#the-default-members-field) will be used.\n\n## The `default-members` field\n\nThe `default-members` field specifies paths of [members](#the-members-and-exclude-fields) to\noperate on when in the workspace root and the package selection flags are not\nused:\n\n```toml\n[workspace]\nmembers = [\"path/to/member1\", \"path/to/member2\", \"path/to/member3/*\"]\ndefault-members = [\"path/to/member2\", \"path/to/member3/foo\"]\n```\n\n> Note: when a [root package](#root-package) is present,\n> you can only operate on it using `--package` and `--workspace` flags.\n\nWhen unspecified, the [root package](#root-package) will be used.\nIn the case of a [virtual workspace](#virtual-workspace), all members will be used\n(as if `--workspace` were specified on the command-line).\n\n## The `package` table\n\nThe `workspace.package` table is where you define keys that can be\ninherited by members of a workspace. These keys can be inherited by\ndefining them in the member package with `{key}.workspace = true`.\n\nKeys that are supported:\n\n|                |                 |\n|----------------|-----------------|\n| `authors`      | `categories`    |\n| `description`  | `documentation` |\n| `edition`      | `exclude`       |\n| `homepage`     | `include`       |\n| `keywords`     | `license`       |\n| `license-file` | `publish`       |\n| `readme`       | `repository`    |\n| `rust-version` | `version`       |\n\n- `license-file` and `readme` are relative to the workspace root\n- `include` and `exclude` are relative to your package root\n\nExample:\n```toml\n# [PROJECT_DIR]/Cargo.toml\n[workspace]\nmembers = [\"bar\"]\n\n[workspace.package]\nversion = \"1.2.3\"\nauthors = [\"Nice Folks\"]\ndescription = \"A short description of my package\"\ndocumentation = \"https://example.com/bar\"\n```\n\n```toml\n# [PROJECT_DIR]/bar/Cargo.toml\n[package]\nname = \"bar\"\nversion.workspace = true\nauthors.workspace = true\ndescription.workspace = true\ndocumentation.workspace = true\n```\n\n> **MSRV:** Requires 1.64+\n\n## The `dependencies` table\n\nThe `workspace.dependencies` table is where you define dependencies to be\ninherited by members of a workspace.\n\nSpecifying a workspace dependency is similar to [package dependencies][specifying-dependencies] except:\n- Dependencies from this table cannot be declared as `optional`\n- [`features`][features] declared in this table are additive with the `features` from `[dependencies]`\n\nYou can then [inherit the workspace dependency as a package dependency][inheriting-a-dependency-from-a-workspace]\n\nExample:\n```toml\n# [PROJECT_DIR]/Cargo.toml\n[workspace]\nmembers = [\"bar\"]\n\n[workspace.dependencies]\ncc = \"1.0.73\"\nrand = \"0.8.5\"\nregex = { version = \"1.6.0\", default-features = false, features = [\"std\"] }\n```\n\n```toml\n# [PROJECT_DIR]/bar/Cargo.toml\n[package]\nname = \"bar\"\nversion = \"0.2.0\"\n\n[dependencies]\nregex = { workspace = true, features = [\"unicode\"] }\n\n[build-dependencies]\ncc.workspace = true\n\n[dev-dependencies]\nrand.workspace = true\n```\n\n> **MSRV:** Requires 1.64+\n\n## The `lints` table\n\nThe `workspace.lints` table is where you define lint configuration to be inherited by members of a workspace.\n\nSpecifying a workspace lint configuration is similar to [package lints](manifest.md#the-lints-section).\n\nExample:\n\n```toml\n# [PROJECT_DIR]/Cargo.toml\n[workspace]\nmembers = [\"crates/*\"]\n\n[workspace.lints.rust]\nunsafe_code = \"forbid\"\n```\n\n```toml\n# [PROJECT_DIR]/crates/bar/Cargo.toml\n[package]\nname = \"bar\"\nversion = \"0.1.0\"\n\n[lints]\nworkspace = true\n```\n\n> **MSRV:** Respected as of 1.74\n\n## The `metadata` table\n\nThe `workspace.metadata` table is ignored by Cargo and will not be warned\nabout. This section can be used for tools that would like to store workspace\nconfiguration in `Cargo.toml`. For example:\n\n```toml\n[workspace]\nmembers = [\"member1\", \"member2\"]\n\n[workspace.metadata.webcontents]\nroot = \"path/to/webproject\"\ntool = [\"npm\", \"run\", \"build\"]\n# ...\n```\n\nThere is a similar set of tables at the package level at\n[`package.metadata`][package-metadata]. While cargo does not specify a\nformat for the content of either of these tables, it is suggested that\nexternal tools may wish to use them in a consistent fashion, such as referring\nto the data in `workspace.metadata` if data is missing from `package.metadata`,\nif that makes sense for the tool in question.\n\n[package]: manifest.md#the-package-section\n[`Cargo.lock`]: ../guide/cargo-toml-vs-cargo-lock.md\n[package-metadata]: manifest.md#the-metadata-table\n[package-edition]: manifest.md#the-edition-field\n[output directory]: build-cache.md\n[patch]: overriding-dependencies.md#the-patch-section\n[replace]: overriding-dependencies.md#the-replace-section\n[profiles]: profiles.md\n[`path` dependencies]: specifying-dependencies.md#specifying-path-dependencies\n[`package.workspace`]: manifest.md#the-workspace-field\n[globs]: https://docs.rs/glob/0.3.0/glob/struct.Pattern.html\n[`cargo build`]: ../commands/cargo-build.md\n[specifying-dependencies]: specifying-dependencies.md\n[features]: features.md\n[inheriting-a-dependency-from-a-workspace]: specifying-dependencies.md#inheriting-a-dependency-from-a-workspace\n"
  },
  {
    "path": "src/doc/theme/cargo.css",
    "content": "dd > p {\n    /* For loose definitions that have a p tag inside, don't add a bunch of\n    space before the definition. This can removed after updating to mdbook 0.5. */\n    margin-top: 0;\n}\n\n/* Override mdbook's link color for option links. */\na.option-anchor, a.option-anchor > * {\n    color: var(--fg) !important;\n}\n"
  },
  {
    "path": "src/doc/theme/head.hbs",
    "content": "<style>\n    dd {\n        margin-bottom: 1em;\n    }\n</style>\n"
  },
  {
    "path": "src/etc/_cargo",
    "content": "#compdef cargo\n\nautoload -U regexp-replace\n\n_cargo() {\n    local curcontext=\"$curcontext\" ret=1\n    local -a command_scope_spec common jobs parallel features manifest msgfmt triple target registry\n    local -a state line state_descr # These are set by _arguments\n    typeset -A opt_args\n\n    common=(\n        '(-q --quiet)*'{-v,--verbose}'[use verbose output]'\n        '(-q --quiet -v --verbose)'{-q,--quiet}'[no output printed to stdout]'\n        '-Z+[pass unstable (nightly-only) flags to cargo]: :_cargo_unstable_flags'\n        '--offline[run without accessing the network]'\n        '--frozen[require that Cargo.lock and cache are up-to-date]'\n        '--locked[require that Cargo.lock is up-to-date]'\n        '--color=[specify colorization option]:coloring:(auto always never)'\n        '(- 1 *)'{-h,--help}'[show help message]'\n    )\n\n    # leading items in parentheses are an exclusion list for the arguments following that arg\n    # See: http://zsh.sourceforge.net/Doc/Release/Completion-System.html#Completion-Functions\n    #   - => exclude all other options\n    #   1 => exclude positional arg 1\n    #   * => exclude all other args\n    #   +blah => exclude +blah\n    _arguments -s -S -C $common \\\n        '(- 1 *)--list[list installed commands]' \\\n        '(- 1 *)--explain=[provide a detailed explanation of an error message]:error code' \\\n        '(- 1 *)'{-V,--version}'[show version information]' \\\n        '(+beta +nightly)+stable[use the stable toolchain]' \\\n        '(+stable +nightly)+beta[use the beta toolchain]' \\\n        '(+stable +beta)+nightly[use the nightly toolchain]' \\\n        '1: :_cargo_cmds' \\\n        '*:: :->args'\n\n    # These flags are mutually exclusive specifiers for the scope of a command; as\n    # they are used in multiple places without change, they are expanded into the\n    # appropriate command's `_arguments` where appropriate.\n    command_scope_spec=(\n        '(--bin --example --test --lib)--bench=[specify benchmark name]: :_cargo_benchmark_names'\n        '(--bench --bin --test --lib)--example=[specify example name]:example name:_cargo_example_names'\n        '(--bench --example --test --lib)--bin=[specify binary name]:binary name'\n        '(--bench --bin --example --test)--lib=[specify library name]:library name'\n        '(--bench --bin --example --lib)--test=[specify test name]:test name'\n    )\n\n    jobs=(\n        '(-j --jobs)'{-j+,--jobs=}'[specify number of parallel jobs]:jobs [# of CPUs]'\n    )\n\n    parallel=(\n        \"${jobs[@]}\"\n        '--keep-going[do not abort build on first build error]'\n    )\n\n    features=(\n        '(--all-features)'{-F+,--features=}'[specify features to activate]:feature'\n        '(--features -F)--all-features[activate all available features]'\n        \"--no-default-features[don't build the default features]\"\n    )\n\n    msgfmt='--message-format=[specify error format]:error format [human]:(human json short)'\n    triple='--target=[specify target triple]:target triple:_cargo_target_triple'\n    target='--target-dir=[specify directory for all generated artifacts]:directory:_directories'\n    manifest='--manifest-path=[specify path to manifest]:path:_directories'\n    registry='--registry=[specify registry to use]:registry'\n\n    case $state in\n        args)\n            curcontext=\"${curcontext%:*}-${words[1]}:\"\n            case ${words[1]} in\n                add)\n                    _arguments -s -A \"^--\" $common $manifest $registry \\\n                        {-F+,--features=}'[specify features to activate]:feature' \\\n                        \"--default-features[enable the default features]\" \\\n                        \"--no-default-features[don't enable the default features]\" \\\n                        \"--optional[mark the dependency as optional]\" \\\n                        \"--no-optional[mark the dependency as required]\" \\\n                        \"--dev[add as a dev dependency]\" \\\n                        \"--build[add as a build dependency]\" \\\n                        \"--target=[add as a dependency to the given target platform]\" \\\n                        \"--rename=[rename the dependency]\" \\\n                        \"--dry-run[don't actually write the manifest]\" \\\n                        '--branch=[branch to use when adding from git]:branch' \\\n                        '--git=[specify URL from which to add the crate]:url:_urls' \\\n                        '--path=[local filesystem path to crate to add]: :_directories' \\\n                        '--rev=[specific commit to use when adding from git]:commit' \\\n                        '--tag=[tag to use when adding from git]:tag' \\\n                        '--ignore-rust-version[Ignore rust-version specification in packages]' \\\n                        '1: :_guard \"^-*\" \"crate name\"' \\\n                        '*:args:_default'\n                        ;;\n                bench)\n                    _arguments -s -A \"^--\" $common $jobs $features $msgfmt $triple $target $manifest \\\n                        \"${command_scope_spec[@]}\" \\\n                        '--all-targets[benchmark all targets]' \\\n                        \"--no-run[compile but don't run]\" \\\n                        '(-p --package)'{-p+,--package=}'[specify package to run benchmarks for]:package:_cargo_package_names' \\\n                        '--exclude=[exclude packages from the benchmark]:spec' \\\n                        '--no-fail-fast[run all benchmarks regardless of failure]' \\\n                        '--ignore-rust-version[Ignore rust-version specification in packages]' \\\n                        '1: :_guard \"^-*\" \"bench name\"' \\\n                        '*:args:_default'\n                        ;;\n\n                build | b)\n                    _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \\\n                        '--all-targets[equivalent to specifying --lib --bins --tests --benches --examples]' \\\n                        \"${command_scope_spec[@]}\" \\\n                        '(-p --package)'{-p+,--package=}'[specify package to build]:package:_cargo_package_names' \\\n                        '--release[build in release mode]' \\\n                        '--ignore-rust-version[Ignore rust-version specification in packages]'\n                        ;;\n\n                check | c)\n                    _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \\\n                        '--all-targets[equivalent to specifying --lib --bins --tests --benches --examples]' \\\n                        \"${command_scope_spec[@]}\" \\\n                        '(-p --package)'{-p+,--package=}'[specify package to check]:package:_cargo_package_names' \\\n                        '--release[check in release mode]' \\\n                        '--ignore-rust-version[Ignore rust-version specification in packages]'\n                        ;;\n\n                clean)\n                    _arguments -s -S $common $triple $target $manifest \\\n                        '(-p --package)'{-p+,--package=}'[specify package to clean]:package:_cargo_package_names' \\\n                        '--release[clean release artifacts]' \\\n                        '--doc[clean just the documentation directory]'\n                        ;;\n\n                doc | d)\n                    _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \\\n                        '--no-deps[do not build docs for dependencies]' \\\n                        '--document-private-items[include non-public items in the documentation]' \\\n                        '--open[open docs in browser after the build]' \\\n                        '(-p --package)'{-p+,--package=}'[specify package to document]:package:_cargo_package_names' \\\n                        '--release[build artifacts in release mode, with optimizations]' \\\n                        '--ignore-rust-version[Ignore rust-version specification in packages]'\n                        ;;\n\n                fetch)\n                    _arguments -s -S $common $triple $manifest\n                        ;;\n\n                fix)\n                    _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \\\n                        \"${command_scope_spec[@]}\" \\\n                        '--broken-code[fix code even if it already has compiler errors]' \\\n                        '--edition[fix in preparation for the next edition]' \\\n                        '--edition-idioms[fix warnings to migrate to the idioms of an edition]' \\\n                        '--allow-no-vcs[fix code even if a VCS was not detected]' \\\n                        '--allow-dirty[fix code even if the working directory is dirty]' \\\n                        '--allow-staged[fix code even if the working directory has staged changes]' \\\n                        '--ignore-rust-version[Ignore rust-version specification in packages]'\n                ;;\n\n                generate-lockfile)\n                    _arguments -s -S $common $manifest\n                        ;;\n\n                help)\n                    _cargo_cmds\n                        ;;\n                info)\n                    _arguments -s -A \"^--\" $common $registry \\\n                        '--index=[specify registry index]:index' \\\n                        '*: :_guard \"^-*\" \"crate\"'\n                        ;;\n\n                init)\n                    _arguments -s -S $common $registry \\\n                        '--lib[use library template]' \\\n                        '--edition=[specify edition to set for the crate generated]:edition:(2015 2018 2021)' \\\n                        '--vcs=[initialize a new repo with a given VCS]:vcs:(git hg pijul fossil none)' \\\n                        '--name=[set the resulting package name]:name' \\\n                        '1:path:_directories'\n                        ;;\n\n                install)\n                    _arguments -s -S $common $parallel $features $triple $registry \\\n                        '(-f --force)'{-f,--force}'[force overwriting of existing crates or binaries]' \\\n                        '--bin=[only install the specified binary]:binary' \\\n                        '--branch=[branch to use when installing from git]:branch' \\\n                        '--debug[Build in debug mode (with the \"dev\" profile) instead of release mode]' \\\n                        '--example=[install the specified example instead of binaries]:example:_cargo_example_names' \\\n                        '--git=[specify URL from which to install the crate]:url:_urls' \\\n                        '--path=[local filesystem path to crate to install]: :_directories' \\\n                        '--rev=[specific commit to use when installing from git]:commit' \\\n                        '--root=[directory to install packages into]: :_directories' \\\n                        '--tag=[tag to use when installing from git]:tag' \\\n                        '--version=[version to install from crates.io]:version' \\\n                        '--list[list all installed packages and their versions]' \\\n                        '--ignore-rust-version[Ignore rust-version specification in packages]' \\\n                        '*: :_guard \"^-*\" \"crate\"'\n                        ;;\n\n                locate-project)\n                    _arguments -s -S $common $manifest \\\n                        '--message-format=[specify output representation]:output representation [json]:(json plain)' \\\n                        '--workspace[locate Cargo.toml of the workspace root]'\n                        ;;\n\n                login)\n                    _arguments -s -S $common $registry \\\n                        '*: :_guard \"^-*\" \"token\"'\n                        ;;\n\n                metadata)\n                    _arguments -s -S $common $features $manifest \\\n                        \"--no-deps[output information only about the root package and don't fetch dependencies]\" \\\n                        '--format-version=[specify format version]:version [1]:(1)'\n                        ;;\n\n                new)\n                    _arguments -s -S $common $registry \\\n                        '--lib[use library template]' \\\n                        '--vcs:initialize a new repo with a given VCS:(git hg none)' \\\n                        '--name=[set the resulting package name]'\n                        ;;\n\n                owner)\n                    _arguments -s -S $common $registry \\\n                        '(-a --add)'{-a,--add}'[specify name of a user or team to invite as an owner]:name' \\\n                        '--index=[specify registry index]:index' \\\n                        '(-l --list)'{-l,--list}'[list owners of a crate]' \\\n                        '(-r --remove)'{-r,--remove}'[specify name of a user or team to remove as an owner]:name' \\\n                        '--token=[specify API token to use when authenticating]:token' \\\n                        '*: :_guard \"^-*\" \"crate\"'\n                        ;;\n\n                package)\n                    _arguments -s -S $common $parallel $features $triple $target $manifest $registry \\\n                        '--index=[specify registry index]:index' \\\n                        '(-l --list)'{-l,--list}'[print files included in a package without making one]' \\\n                        '--no-metadata[ignore warnings about a lack of human-usable metadata]' \\\n                        '--allow-dirty[allow dirty working directories to be packaged]' \\\n                        \"--no-verify[don't build to verify contents]\"\n                        ;;\n\n                pkgid)\n                    _arguments -s -S $common $manifest \\\n                        '(-p --package)'{-p+,--package=}'[specify package to get ID specifier for]:package:_cargo_package_names' \\\n                        '*: :_guard \"^-*\" \"spec\"'\n                        ;;\n\n                publish)\n                    _arguments -s -S $common $parallel $features $triple $target $manifest $registry \\\n                        '--index=[specify registry index]:index' \\\n                        '--allow-dirty[allow dirty working directories to be packaged]' \\\n                        \"--no-verify[don't verify the contents by building them]\" \\\n                        '--dry-run[perform all checks without uploading]'\n                        ;;\n\n                remove | rm)\n                    _arguments -s -A \"^--\" $common $manifest \\\n                        \"--dev[remove as a dev dependency]\" \\\n                        \"--build[remove as a build dependency]\" \\\n                        \"--target=[remove as a dependency from the given target platform]\" \\\n                        \"--dry-run[don't actually write the manifest]\" \\\n                        '(-p --package)'{-p+,--package=}'[package to remove from]:package:_cargo_package_names' \\\n                        '1: :_guard \"^-*\" \"crate name\"' \\\n                        '*:args:_default'\n                        ;;\n\n                run | r)\n                    _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \\\n                        '--example=[name of the bin target]:name:_cargo_example_names' \\\n                        '--bin=[name of the bin target]:name' \\\n                        '(-p --package)'{-p+,--package=}'[specify package with the target to run]:package:_cargo_package_names' \\\n                        '--release[build in release mode]' \\\n                        '--ignore-rust-version[Ignore rust-version specification in packages]' \\\n                        '*: :_default'\n                        ;;\n\n                rustc)\n                    _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \\\n                        '(-p --package)'{-p+,--package=}'[specify package to build]:package:_cargo_package_names' \\\n                        '--profile=[specify profile to build the selected target for]:profile' \\\n                        '--release[build artifacts in release mode, with optimizations]' \\\n                        \"${command_scope_spec[@]}\" \\\n                        '--ignore-rust-version[Ignore rust-version specification in packages]' \\\n                        '*: : _dispatch rustc rustc -default-'\n                        ;;\n\n                rustdoc)\n                    _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \\\n                        '--document-private-items[include non-public items in the documentation]' \\\n                        '--open[open the docs in a browser after the operation]' \\\n                        '(-p --package)'{-p+,--package=}'[specify package to document]:package:_cargo_package_names' \\\n                        '--release[build artifacts in release mode, with optimizations]' \\\n                        \"${command_scope_spec[@]}\" \\\n                        '--ignore-rust-version[Ignore rust-version specification in packages]' \\\n                        '*: : _dispatch rustdoc rustdoc -default-'\n                        ;;\n\n                search)\n                    _arguments -s -S $common $registry \\\n                        '--index=[specify registry index]:index' \\\n                        '--limit=[limit the number of results]:results [10]' \\\n                        '*: :_guard \"^-*\" \"query\"'\n                        ;;\n\n                test | t)\n                    _arguments -s -S $common $jobs $features $msgfmt $triple $target $manifest \\\n                        '--test=[test name]: :_cargo_test_names' \\\n                        '--no-fail-fast[run all tests regardless of failure]' \\\n                        '--no-run[compile but do not run]' \\\n                        '(-p --package)'{-p+,--package=}'[package to run tests for]:package:_cargo_package_names' \\\n                        '--all[test all packages in the workspace]' \\\n                        '--release[build artifacts in release mode, with optimizations]' \\\n                        '1: :_cargo_test_names' \\\n                        '(--doc --bin --example --test --bench)--lib[only test library]' \\\n                        '(--lib --bin --example --test --bench)--doc[only test documentation]' \\\n                        '(--lib --doc --example --test --bench)--bin=[binary name]' \\\n                        '(--lib --doc --bin --test --bench)--example=[example name]:_cargo_example_names' \\\n                        '(--lib --doc --bin --example --bench)--test=[test name]' \\\n                        '(--lib --doc --bin --example --test)--bench=[benchmark name]' \\\n                        '--ignore-rust-version[Ignore rust-version specification in packages]' \\\n                        '*: :_default'\n                        ;;\n\n                tree)\n                    _arguments -s -S $common $features $triple $manifest \\\n                        '(-p --package)'{-p+,--package=}'[package to use as the root]:package:_cargo_package_names' \\\n                        '(-i --invert)'{-i+,--invert=}'[invert the tree for the given package]:package:_cargo_package_names' \\\n                        '--prefix=[line prefix]:prefix:(depth indent none)' \\\n                        '--no-dedupe[repeat shared dependencies]' \\\n                        '(-d --duplicates)'{-d,--duplicates}'[packages with multiple versions]' \\\n                        '--charset=[utf8 or ascii]:charset:(utf8 ascii)' \\\n                        '(-f --format)'{-f,--format=}'[format string]:format' \\\n                        '(-e --edges)'{-e,--edges=}'[edge kinds]:kind:(features normal build dev all no-dev no-build no-normal)' \\\n                        ;;\n\n                uninstall)\n                    _arguments -s -S $common \\\n                        '(-p --package)'{-p+,--package=}'[specify package to uninstall]:package:_cargo_package_names' \\\n                        '--bin=[only uninstall the specified binary]:name' \\\n                        '--root=[directory to uninstall packages from]: :_files -/' \\\n                        '*:crate:_cargo_installed_crates -F line'\n                        ;;\n\n                update)\n                    _arguments -s -S $common $manifest \\\n                        '--aggressive=[force dependency update]' \\\n                        '--recursive=[force dependency update]' \\\n                        \"--dry-run[don't actually write the lockfile]\" \\\n                        '(-p --package)'{-p+,--package=}'[specify package to update]:package:_cargo_package_names' \\\n                        '--precise=[update single dependency to precise release]:release' \\\n                        '*:package:_cargo_package_names'\n                        ;;\n\n                version)\n                    _arguments -s -S $common\n                        ;;\n\n                yank)\n                    _arguments -s -S $common $registry \\\n                        '--version=[specify yank version]:version' \\\n                        '--undo[undo a yank, putting a version back into the index]' \\\n                        '--index=[specify registry index to yank from]:registry index' \\\n                        '--token=[specify API token to use when authenticating]:token' \\\n                        '*: :_guard \"^-*\" \"crate\"'\n                        ;;\n                *)\n                    # allow plugins to define their own functions\n                    if ! _call_function ret _cargo-${words[1]}; then\n                        # fallback on default completion for unknown commands\n                        _default && ret=0\n                    fi\n                    (( ! ret ))\n                ;;\n            esac\n            ;;\n    esac\n}\n\n_cargo_unstable_flags() {\n    local flags\n    flags=( help ${${${(M)${(f)\"$(_call_program flags cargo -Z help)\"}:#*--*}/ #-- #/:}##*-Z } )\n    _describe -t flags 'unstable flag' flags\n}\n\n_cargo_installed_crates() {\n    local expl\n    _description crates expl 'crate'\n    compadd \"$@\" \"$expl[@]\" - ${${${(f)\"$(cargo install --list)\"}:# *}%% *}\n}\n\n_cargo_cmds() {\n    local -a commands\n    # This uses Parameter Expansion Flags, which are a built-in Zsh feature.\n    # See more: http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion-Flags\n    # and       http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion\n    #\n    # # How this work?\n    #\n    # First it splits the result of `cargo --list` at newline, then it removes the first line.\n    # Then it removes indentation (4 whitespaces) before each items. (Note the x## pattern [1]).\n    # Then it replaces those spaces between item and description with a `:`\n    #\n    # [1]: https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org#patterns\n    commands=( ${${${(M)\"${(f)$(_call_program commands cargo --list)}\":#    *}/ ##/}/ ##/:} )\n    _describe -t commands 'command' commands\n}\n\n_cargo_target_triple() {\n    local -a result\n\n    if (( $+commands[rustup] )); then\n        result=( ${(f)\"$(rustup target list --installed)\"} )\n    else\n        result=( ${(f)\"$(rustc --print target-list)\"} )\n    fi\n\n    _describe 'target triple' result\n}\n\n#FIXME: Disabled until fixed\n#gets package names from the manifest file\n_cargo_package_names() {\n    _message -e packages package\n}\n\n# Extracts the values of \"name\" from the array given in $1 and shows them as\n# command line options for completion\n_cargo_names_from_array() {\n    local manifest=$(cargo locate-project --message-format plain)\n    if [[ -z $manifest ]]; then\n        return 0\n    fi\n\n    local last_line\n    local -a names;\n    local in_block=false\n    local block_name=$1\n    names=()\n    while read -r line; do\n        if [[ $last_line == \"[[$block_name]]\" ]]; then\n            in_block=true\n        else\n            if [[ $last_line =~ '\\s*\\[\\[.*' ]]; then\n                in_block=false\n            fi\n        fi\n\n        if [[ $in_block == true ]]; then\n            if [[ $line =~ '\\s*name\\s*=' ]]; then\n                regexp-replace line '^\\s*name\\s*=\\s*|\"' ''\n                names+=( \"$line\" )\n            fi\n        fi\n\n        last_line=$line\n    done < \"$manifest\"\n    _describe \"$block_name\" names\n\n}\n\n#Gets the test names from the manifest file\n_cargo_test_names() {\n    _cargo_names_from_array \"test\"\n}\n\n#Gets the bench names from the manifest file\n_cargo_benchmark_names() {\n    _cargo_names_from_array \"bench\"\n}\n\n_cargo_example_names() {\n    if [[ -d examples ]]; then\n        local -a files=(${(@f)$(echo examples/*.rs(:t:r))})\n        _values 'example' \"${files[@]}\"\n    fi\n}\n\n_cargo\n"
  },
  {
    "path": "src/etc/cargo.bashcomp.sh",
    "content": "# Required for bash versions < 4.1\n# Default bash version is 3.2 on latest macOS. See #6874\nshopt -s extglob\n\ncommand -v cargo >/dev/null 2>&1 &&\n_cargo()\n{\n\tlocal cur prev words cword\n\t_get_comp_words_by_ref cur prev words cword\n\n\tCOMPREPLY=()\n\n\t# Skip past - and + options to find the command.\n\tlocal nwords=${#words[@]}\n\tlocal cmd_i cmd dd_i\n\tfor (( cmd_i=1; cmd_i<$nwords; cmd_i++ ));\n\tdo\n\t\tif [[ ! \"${words[$cmd_i]}\" =~ ^[+-] ]]; then\n\t\t\tcmd=\"${words[$cmd_i]}\"\n\t\t\tbreak\n\t\tfi\n\tdone\n\t# Find the location of the -- separator.\n\tfor (( dd_i=1; dd_i<$nwords-1; dd_i++ ));\n\tdo\n\t\tif [[ \"${words[$dd_i]}\" = \"--\" ]]; then\n\t\t\tbreak\n\t\tfi\n\tdone\n\n\tlocal vcs='git hg none pijul fossil'\n\tlocal color='auto always never'\n\tlocal msg_format='human json short'\n\n\tlocal opt_help='-h --help'\n\tlocal opt_verbose='-v --verbose'\n\tlocal opt_quiet='-q --quiet'\n\tlocal opt_color='--color'\n\tlocal opt_config='--config'\n\tlocal opt_common=\"$opt_help $opt_verbose $opt_quiet $opt_color $opt_config\"\n\tlocal opt_pkg_spec='-p --package --all --exclude --workspace'\n\tlocal opt_pkg='-p --package'\n\tlocal opt_feat='-F --features --all-features --no-default-features'\n\tlocal opt_mani='--manifest-path'\n\tlocal opt_jobs='-j --jobs'\n\tlocal opt_parallel=\"$opt_jobs --keep-going\"\n\tlocal opt_force='-f --force'\n\tlocal opt_sync='-s --sync'\n\tlocal opt_lock='--frozen --locked --offline'\n\tlocal opt_targets=\"--lib --bin --bins --example --examples --test --tests --bench --benches --all-targets\"\n\n\tlocal opt___nocmd=\"$opt_common -V --version --list --explain\"\n\tlocal opt__add=\"$opt_common -p --package --features --default-features --no-default-features $opt_mani $opt_lock --optional --no-optional --rename --dry-run --path --git --branch --tag --rev --registry --dev --build --target --ignore-rust-version\"\n\tlocal opt__bench=\"$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_jobs $opt_targets --message-format --target --no-run --no-fail-fast --target-dir --ignore-rust-version\"\n\tlocal opt__build=\"$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets --message-format --target --release --profile --target-dir --ignore-rust-version\"\n\tlocal opt__b=\"$opt__build\"\n\tlocal opt__check=\"$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets --message-format --target --release --profile --target-dir --ignore-rust-version\"\n\tlocal opt__c=\"$opt__check\"\n\tlocal opt__clean=\"$opt_common $opt_pkg $opt_mani $opt_lock --target --release --doc --target-dir --profile\"\n\tlocal opt__clippy=\"$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets --message-format --target --release --profile --target-dir --no-deps --fix\"\n\tlocal opt__doc=\"$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_parallel --message-format --bin --bins --lib --target --open --no-deps --release --document-private-items --target-dir --profile --ignore-rust-version\"\n\tlocal opt__d=\"$opt__doc\"\n\tlocal opt__fetch=\"$opt_common $opt_mani $opt_lock --target\"\n\tlocal opt__fix=\"$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_parallel $opt_targets $opt_lock --release --target --message-format --broken-code --edition --edition-idioms --allow-no-vcs --allow-dirty --allow-staged --profile --target-dir --ignore-rust-version\"\n\tlocal opt__generate_lockfile=\"$opt_common $opt_mani $opt_lock\"\n\tlocal opt__help=\"$opt_help\"\n\tlocal opt__info=\"$opt_common $opt_lock --registry --index\"\n\tlocal opt__init=\"$opt_common $opt_lock --bin --lib --name --vcs --edition --registry\"\n\tlocal opt__install=\"$opt_common $opt_feat $opt_parallel $opt_lock $opt_force --bin --bins --branch --debug --example --examples --git --list --path --rev --root --tag --version --registry --target --profile --no-track --ignore-rust-version\"\n\tlocal opt__locate_project=\"$opt_common $opt_mani $opt_lock --message-format --workspace\"\n\tlocal opt__login=\"$opt_common $opt_lock --registry\"\n\tlocal opt__metadata=\"$opt_common $opt_feat $opt_mani $opt_lock --format-version=1 --no-deps --filter-platform\"\n\tlocal opt__new=\"$opt_common $opt_lock --vcs --bin --lib --name --edition --registry\"\n\tlocal opt__owner=\"$opt_common $opt_lock -a --add -r --remove -l --list --index --token --registry\"\n\tlocal opt__package=\"$opt_common $opt_mani $opt_feat $opt_lock $opt_parallel --allow-dirty -l --list --no-verify --no-metadata --index --registry --target --target-dir\"\n\tlocal opt__pkgid=\"$opt_common $opt_mani $opt_lock $opt_pkg\"\n\tlocal opt__publish=\"$opt_common $opt_mani $opt_feat $opt_lock $opt_parallel --allow-dirty --dry-run --no-verify --index --registry --target --target-dir\"\n\tlocal opt__remove=\"$opt_common $opt_pkg $opt_lock $opt_mani --dry-run --dev --build --target\"\n\tlocal opt__rm=\"$opt__remove\"\n\tlocal opt__report=\"$opt_help $opt_verbose $opt_color future-incompat future-incompatibilities\"\n\tlocal opt__report__future_incompat=\"$opt_help $opt_verbose $opt_color $opt_pkg --id\"\n\tlocal opt__run=\"$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_parallel --message-format --target --bin --example --release --target-dir --profile --ignore-rust-version\"\n\tlocal opt__r=\"$opt__run\"\n\tlocal opt__rustc=\"$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets -L --crate-type --extern --message-format --profile --target --release --target-dir --ignore-rust-version\"\n\tlocal opt__rustdoc=\"$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets --message-format --target --release --open --target-dir --profile --ignore-rust-version\"\n\tlocal opt__search=\"$opt_common $opt_lock --limit --index --registry\"\n\tlocal opt__test=\"$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_jobs $opt_targets --message-format --doc --target --no-run --release --no-fail-fast --target-dir --profile --ignore-rust-version\"\n\tlocal opt__t=\"$opt__test\"\n\tlocal opt__tree=\"$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock --target -i --invert --prefix --no-dedupe --duplicates -d --charset -f --format -e --edges\"\n\tlocal opt__uninstall=\"$opt_common $opt_lock $opt_pkg --bin --root\"\n\tlocal opt__update=\"$opt_common $opt_mani $opt_lock $opt_pkg --aggressive --recursive --precise --dry-run\"\n\tlocal opt__vendor=\"$opt_common $opt_mani $opt_lock $opt_sync --no-delete --respect-source-config --versioned-dirs\"\n\tlocal opt__version=\"$opt_common $opt_lock\"\n\tlocal opt__yank=\"$opt_common $opt_lock --version --undo --index --token --registry\"\n\tlocal opt__libtest=\"--help --include-ignored --ignored --test --bench --list --logfile --no-capture --test-threads --skip -q --quiet --exact --color --format\"\n\n\tif [[ $cword -gt $dd_i ]]; then\n\t\t# Completion after -- separator.\n\t\tif [[ \"${cmd}\" = @(test|bench) ]]; then\n\t\t\tCOMPREPLY=( $( compgen -W \"${opt__libtest}\" -- \"$cur\" ) )\n\t\telse\n\t\t\t# Fallback to filename completion, useful with `cargo run`.\n\t\t\t_filedir\n\t\tfi\n\telif [[ $cword -le $cmd_i ]]; then\n\t\t# Completion before or at the command.\n\t\tif [[ \"$cur\" == -* ]]; then\n\t\t\tCOMPREPLY=( $( compgen -W \"${opt___nocmd}\" -- \"$cur\" ) )\n\t\telif [[ \"$cur\" == +* ]]; then\n\t\t\tCOMPREPLY=( $( compgen -W \"$(_toolchains)\" -- \"$cur\" ) )\n\t\telse\n\t\t\t_ensure_cargo_commands_cache_filled\n\t\t\tCOMPREPLY=( $( compgen -W \"$__cargo_commands_cache\" -- \"$cur\" ) )\n\t\tfi\n\telse\n\t\tcase \"${prev}\" in\n\t\t\t--vcs)\n\t\t\t\tCOMPREPLY=( $( compgen -W \"$vcs\" -- \"$cur\" ) )\n\t\t\t\t;;\n\t\t\t--color)\n\t\t\t\tCOMPREPLY=( $( compgen -W \"$color\" -- \"$cur\" ) )\n\t\t\t\t;;\n\t\t\t--message-format)\n\t\t\t\tCOMPREPLY=( $( compgen -W \"$msg_format\" -- \"$cur\" ) )\n\t\t\t\t;;\n\t\t\t--manifest-path)\n\t\t\t\t_filedir toml\n\t\t\t\t;;\n\t\t\t--bin)\n\t\t\t\tCOMPREPLY=( $( compgen -W \"$(_bin_names)\" -- \"$cur\" ) )\n\t\t\t\t;;\n\t\t\t--test)\n\t\t\t\tCOMPREPLY=( $( compgen -W \"$(_test_names)\" -- \"$cur\" ) )\n\t\t\t\t;;\n\t\t\t--bench)\n\t\t\t\tCOMPREPLY=( $( compgen -W \"$(_benchmark_names)\" -- \"$cur\" ) )\n\t\t\t\t;;\n\t\t\t--example)\n\t\t\t\tCOMPREPLY=( $( compgen -W \"$(_get_examples)\" -- \"$cur\" ) )\n\t\t\t\t;;\n\t\t\t--target)\n\t\t\t\tCOMPREPLY=( $( compgen -W \"$(_get_targets)\" -- \"$cur\" ) )\n\t\t\t\t;;\n\t\t\t--target-dir|--path)\n\t\t\t\t_filedir -d\n\t\t\t\t;;\n\t\t\t--config)\n\t\t\t\t_filedir\n\t\t\t\t;;\n\t\t\thelp)\n\t\t\t\t_ensure_cargo_commands_cache_filled\n\t\t\t\tCOMPREPLY=( $( compgen -W \"$__cargo_commands_cache\" -- \"$cur\" ) )\n\t\t\t\t;;\n\t\t\t*)\n\t\t\t\tif [[ \"$cmd\" == \"report\" && \"$prev\" == future-incompat* ]]; then\n\t\t\t\t\tlocal opt_var=opt__${cmd//-/_}__${prev//-/_}\n\t\t\t\telse\n\t\t\t\t\tlocal opt_var=opt__${cmd//-/_}\n\t\t\t\tfi\n\t\t\t\tif [[ -z \"${!opt_var-}\" ]]; then\n\t\t\t\t\t# Forward to subcommands completion if bash-completion >= 2.12 is available\n\t\t\t\t\tif [[ $BASH_COMPLETION_VERSINFO && (${BASH_COMPLETION_VERSINFO[0]} -gt 2 || (${BASH_COMPLETION_VERSINFO[0]} -eq 2 && ${BASH_COMPLETION_VERSINFO[1]} -ge 12)) ]]; then\n\t\t\t\t\t\tCOMP_WORDS[cmd_i]=\"cargo-$cmd\"\n\t\t\t\t\t\t_comp_command_offset \"$cmd_i\"\n\t\t\t\t\t\tCOMP_WORDS[cmd_i]=\"$cmd\"\n\t\t\t\t\telse\n\t\t\t\t\t\t# Fallback to filename completion.\n\t\t\t\t\t\t_filedir\n\t\t\t\t\tfi\n\t\t\t\telse\n\t\t\t\t\tCOMPREPLY=( $( compgen -W \"${!opt_var}\" -- \"$cur\" ) )\n\t\t\t\tfi\n\t\t\t\t;;\n\t\tesac\n\tfi\n\n\t# compopt does not work in bash version 3\n\n\treturn 0\n} &&\ncomplete -F _cargo cargo\n\n__cargo_commands_cache=\n_ensure_cargo_commands_cache_filled(){\n\tif [[ -z $__cargo_commands_cache ]]; then\n\t\t__cargo_commands_cache=\"$(cargo --list 2>/dev/null | awk 'NR>1 {print $1}')\"\n\tfi\n}\n\n_locate_manifest(){\n\tcargo locate-project --message-format plain 2>/dev/null\n}\n\n# Extracts the values of \"name\" from the array given in $1 and shows them as\n# command line options for completion\n_get_names_from_array()\n{\n\tlocal manifest=$(_locate_manifest)\n\tif [[ -z $manifest ]]; then\n\t\treturn 0\n\tfi\n\n\tlocal last_line\n\tlocal -a names\n\tlocal in_block=false\n\tlocal block_name=$1\n\twhile read line\n\tdo\n\t\tif [[ $last_line == \"[[$block_name]]\" ]]; then\n\t\t\tin_block=true\n\t\telse\n\t\t\tif [[ $last_line =~ .*\\[\\[.* ]]; then\n\t\t\t\tin_block=false\n\t\t\tfi\n\t\tfi\n\n\t\tif [[ $in_block == true ]]; then\n\t\t\tif [[ $line =~ .*name.*\\= ]]; then\n\t\t\t\tline=${line##*=}\n\t\t\t\tline=${line%%\\\"}\n\t\t\t\tline=${line##*\\\"}\n\t\t\t\tnames+=(\"$line\")\n\t\t\tfi\n\t\tfi\n\n\t\tlast_line=$line\n\tdone < \"$manifest\"\n\techo \"${names[@]}\"\n}\n\n#Gets the bin names from the manifest file\n_bin_names()\n{\n\t_get_names_from_array \"bin\"\n}\n\n#Gets the test names from the manifest file\n_test_names()\n{\n\t_get_names_from_array \"test\"\n}\n\n#Gets the bench names from the manifest file\n_benchmark_names()\n{\n\t_get_names_from_array \"bench\"\n}\n\n_get_examples(){\n\tlocal manifest=$(_locate_manifest)\n\t[ -z \"$manifest\" ] && return 0\n\n\tlocal files=(\"${manifest%/*}\"/examples/*.rs)\n\tlocal names=(\"${files[@]##*/}\")\n\tlocal names=(\"${names[@]%.*}\")\n\t# \"*\" means no examples found\n\tif [[ \"${names[@]}\" != \"*\" ]]; then\n\t\techo \"${names[@]}\"\n\tfi\n}\n\n_get_targets(){\n\tif command -v rustup >/dev/null 2>/dev/null; then\n\t  rustup target list --installed\n\telse\n\t  rustc --print target-list\n\tfi\n}\n\n_toolchains(){\n\tlocal result=()\n\tlocal toolchains=$(rustup toolchain list)\n\tlocal channels=\"nightly|beta|stable|[0-9]\\.[0-9]{1,2}\\.[0-9]\"\n\tlocal date=\"[0-9]{4}-[0-9]{2}-[0-9]{2}\"\n\twhile read line\n\tdo\n\t\t# Strip \" (default)\"\n\t\tline=${line%% *}\n\t\tif [[ \"$line\" =~ ^($channels)(-($date))?(-.*) ]]; then\n\t\t\tif [[ -z ${BASH_REMATCH[3]} ]]; then\n\t\t\t\tresult+=(\"+${BASH_REMATCH[1]}\")\n\t\t\telse\n\t\t\t\t# channel-date\n\t\t\t\tresult+=(\"+${BASH_REMATCH[1]}-${BASH_REMATCH[3]}\")\n\t\t\tfi\n\t\t\tresult+=(\"+$line\")\n\t\telse\n\t\t\tresult+=(\"+$line\")\n\t\tfi\n\tdone <<< \"$toolchains\"\n\techo \"${result[@]}\"\n}\n\n# vim:ft=sh\n"
  },
  {
    "path": "src/etc/man/cargo-add.1",
    "content": "'\\\" t\n.TH \"CARGO\\-ADD\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-add \\[em] Add dependencies to a Cargo.toml manifest file\n.SH \"SYNOPSIS\"\n\\fBcargo add\\fR [\\fIoptions\\fR] \\fIcrate\\fR\\[u2026]\n.br\n\\fBcargo add\\fR [\\fIoptions\\fR] \\fB\\-\\-path\\fR \\fIpath\\fR\n.br\n\\fBcargo add\\fR [\\fIoptions\\fR] \\fB\\-\\-git\\fR \\fIurl\\fR [\\fIcrate\\fR\\[u2026]]\n.SH \"DESCRIPTION\"\nThis command can add or modify dependencies.\n.sp\nThe source for the dependency can be specified with:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fIcrate\\fR\\fB@\\fR\\fIversion\\fR: Fetch from a registry with a version constraint of \\[lq]\\fIversion\\fR\\[rq]\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\\-\\-path\\fR \\fIpath\\fR: Fetch from the specified \\fIpath\\fR\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\\-\\-git\\fR \\fIurl\\fR: Pull from a git repo at \\fIurl\\fR\n.RE\n.sp\nIf no source is specified, then a best effort will be made to select one, including:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Existing dependencies in other tables (like \\fBdev\\-dependencies\\fR)\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Workspace members\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Latest release in the registry\n.RE\n.sp\nWhen you add a package that is already present, the existing entry will be updated with the flags specified.\n.sp\nUpon successful invocation, the enabled (\\fB+\\fR) and disabled (\\fB\\-\\fR) \\fIfeatures\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html> of the specified\ndependency will be listed in the command\\[cq]s output.\n.SH \"OPTIONS\"\n.SS \"Source options\"\n.sp\n\\fB\\-\\-git\\fR \\fIurl\\fR\n.RS 4\n\\fIGit URL to add the specified crate from\\fR <https://doc.rust\\-lang.org/cargo/reference/specifying\\-dependencies.html#specifying\\-dependencies\\-from\\-git\\-repositories>\\&.\n.RE\n.sp\n\\fB\\-\\-branch\\fR \\fIbranch\\fR\n.RS 4\nBranch to use when adding from git.\n.RE\n.sp\n\\fB\\-\\-tag\\fR \\fItag\\fR\n.RS 4\nTag to use when adding from git.\n.RE\n.sp\n\\fB\\-\\-rev\\fR \\fIsha\\fR\n.RS 4\nSpecific commit to use when adding from git.\n.RE\n.sp\n\\fB\\-\\-path\\fR \\fIpath\\fR\n.RS 4\n\\fIFilesystem path\\fR <https://doc.rust\\-lang.org/cargo/reference/specifying\\-dependencies.html#specifying\\-path\\-dependencies> to local crate to add.\n.RE\n.sp\n\\fB\\-\\-base\\fR \\fIbase\\fR\n.RS 4\nThe \\fIpath base\\fR <https://doc.rust\\-lang.org/cargo/reference/unstable.html#path\\-bases> to use when adding a local crate.\n.sp\n\\fIUnstable (nightly\\-only)\\fR <https://doc.rust\\-lang.org/cargo/reference/unstable.html#path\\-bases>\n.RE\n.sp\n\\fB\\-\\-registry\\fR \\fIregistry\\fR\n.RS 4\nName of the registry to use. Registry names are defined in \\fICargo config\nfiles\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. If not specified, the default registry is used,\nwhich is defined by the \\fBregistry.default\\fR config key which defaults to\n\\fBcrates\\-io\\fR\\&.\n.RE\n.SS \"Section options\"\n.sp\n\\fB\\-\\-dev\\fR\n.RS 4\nAdd as a \\fIdevelopment dependency\\fR <https://doc.rust\\-lang.org/cargo/reference/specifying\\-dependencies.html#development\\-dependencies>\\&.\n.RE\n.sp\n\\fB\\-\\-build\\fR\n.RS 4\nAdd as a \\fIbuild dependency\\fR <https://doc.rust\\-lang.org/cargo/reference/specifying\\-dependencies.html#build\\-dependencies>\\&.\n.RE\n.sp\n\\fB\\-\\-target\\fR \\fItarget\\fR\n.RS 4\nAdd as a dependency to the \\fIgiven target platform\\fR <https://doc.rust\\-lang.org/cargo/reference/specifying\\-dependencies.html#platform\\-specific\\-dependencies>\\&.\n.sp\nTo avoid unexpected shell expansions, you may use quotes around each target, e.g., \\fB\\-\\-target 'cfg(unix)'\\fR\\&.\n.RE\n.SS \"Dependency options\"\n.sp\n\\fB\\-\\-dry\\-run\\fR\n.RS 4\nDon\\[cq]t actually write the manifest\n.RE\n.sp\n\\fB\\-\\-rename\\fR \\fIname\\fR\n.RS 4\n\\fIRename\\fR <https://doc.rust\\-lang.org/cargo/reference/specifying\\-dependencies.html#renaming\\-dependencies\\-in\\-cargotoml> the dependency.\n.RE\n.sp\n\\fB\\-\\-optional\\fR\n.RS 4\nMark the dependency as \\fIoptional\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#optional\\-dependencies>\\&.\n.RE\n.sp\n\\fB\\-\\-no\\-optional\\fR\n.RS 4\nMark the dependency as \\fIrequired\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#optional\\-dependencies>\\&.\n.RE\n.sp\n\\fB\\-\\-public\\fR\n.RS 4\nMark the dependency as public.\n.sp\nThe dependency can be referenced in your library\\[cq]s public API.\n.sp\n\\fIUnstable (nightly\\-only)\\fR <https://doc.rust\\-lang.org/cargo/reference/unstable.html#public\\-dependency>\n.RE\n.sp\n\\fB\\-\\-no\\-public\\fR\n.RS 4\nMark the dependency as private.\n.sp\nWhile you can use the crate in your implementation, it cannot be referenced in your public API.\n.sp\n\\fIUnstable (nightly\\-only)\\fR <https://doc.rust\\-lang.org/cargo/reference/unstable.html#public\\-dependency>\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDisable the \\fIdefault features\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#dependency\\-features>\\&.\n.RE\n.sp\n\\fB\\-\\-default\\-features\\fR\n.RS 4\nRe\\-enable the \\fIdefault features\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#dependency\\-features>\\&.\n.RE\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of \\fIfeatures to\nactivate\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#dependency\\-features>\\&. When adding multiple\ncrates, the features for a specific crate may be enabled with\n\\fBpackage\\-name/feature\\-name\\fR syntax. This flag may be specified multiple times,\nwhich enables all specified features.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-p\\fR \\fIspec\\fR, \n\\fB\\-\\-package\\fR \\fIspec\\fR\n.RS 4\nAdd dependencies to only the specified package.\n.RE\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Add \\fBregex\\fR as a dependency\n.sp\n.RS 4\n.nf\ncargo add regex\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Add \\fBtrybuild\\fR as a dev\\-dependency\n.sp\n.RS 4\n.nf\ncargo add \\-\\-dev trybuild\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Add an older version of \\fBnom\\fR as a dependency\n.sp\n.RS 4\n.nf\ncargo add nom@5\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 4.\\h'+01'Add support for serializing data structures to json with \\fBderive\\fRs\n.sp\n.RS 4\n.nf\ncargo add serde serde_json \\-F serde/derive\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 5.\\h'+01'Add \\fBwindows\\fR as a platform specific dependency on \\fBcfg(windows)\\fR\n.sp\n.RS 4\n.nf\ncargo add windows \\-\\-target 'cfg(windows)'\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-remove\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-bench.1",
    "content": "'\\\" t\n.TH \"CARGO\\-BENCH\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-bench \\[em] Execute benchmarks of a package\n.SH \"SYNOPSIS\"\n\\fBcargo bench\\fR [\\fIoptions\\fR] [\\fIbenchname\\fR] [\\fB\\-\\-\\fR \\fIbench\\-options\\fR]\n.SH \"DESCRIPTION\"\nCompile and execute benchmarks.\n.sp\nThe benchmark filtering argument \\fIbenchname\\fR and all the arguments following\nthe two dashes (\\fB\\-\\-\\fR) are passed to the benchmark binaries and thus to\n\\fIlibtest\\fR (rustc\\[cq]s built in unit\\-test and micro\\-benchmarking framework). If\nyou are passing arguments to both Cargo and the binary, the ones after \\fB\\-\\-\\fR go\nto the binary, the ones before go to Cargo. For details about libtest\\[cq]s\narguments see the output of \\fBcargo bench \\-\\- \\-\\-help\\fR and check out the rustc\nbook\\[cq]s chapter on how tests work at\n<https://doc.rust\\-lang.org/rustc/tests/index.html>\\&.\n.sp\nAs an example, this will run only the benchmark named \\fBfoo\\fR (and skip other\nsimilarly named benchmarks like \\fBfoobar\\fR):\n.sp\n.RS 4\n.nf\ncargo bench \\-\\- foo \\-\\-exact\n.fi\n.RE\n.sp\nBenchmarks are built with the \\fB\\-\\-test\\fR option to \\fBrustc\\fR which creates a\nspecial executable by linking your code with libtest. The executable\nautomatically runs all functions annotated with the \\fB#[bench]\\fR attribute.\nCargo passes the \\fB\\-\\-bench\\fR flag to the test harness to tell it to run\nonly benchmarks, regardless of whether the harness is libtest or a custom harness.\n.sp\nThe libtest harness may be disabled by setting \\fBharness = false\\fR in the target\nmanifest settings, in which case your code will need to provide its own \\fBmain\\fR\nfunction to handle running benchmarks.\n.RS 3\n.ll -5\n.sp\n\\fBNote\\fR: The\n\\fI\\f(BI#[bench]\\fI attribute\\fR <https://doc.rust\\-lang.org/nightly/unstable\\-book/library\\-features/test.html>\nis currently unstable and only available on the\n\\fInightly channel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html>\\&.\nThere are some packages available on\n\\fIcrates.io\\fR <https://crates.io/keywords/benchmark> that may help with\nrunning benchmarks on the stable channel, such as\n\\fICriterion\\fR <https://crates.io/crates/criterion>\\&.\n.br\n.RE\n.ll\n.sp\nBy default, \\fBcargo bench\\fR uses the \\fI\\f(BIbench\\fI profile\\fR <https://doc.rust\\-lang.org/cargo/reference/profiles.html#bench>, which enables\noptimizations and disables debugging information. If you need to debug a\nbenchmark, you can use the \\fB\\-\\-profile=dev\\fR command\\-line option to switch to\nthe dev profile. You can then run the debug\\-enabled benchmark within a\ndebugger.\n.SS \"Working directory of benchmarks\"\nThe working directory of every benchmark is set to the root directory of the\npackage the benchmark belongs to.\nSetting the working directory of benchmarks to the package\\[cq]s root directory\nmakes it possible for benchmarks to reliably access the package\\[cq]s files using\nrelative paths, regardless from where \\fBcargo bench\\fR was executed from.\n.SH \"OPTIONS\"\n.SS \"Benchmark Options\"\n.sp\n\\fB\\-\\-no\\-run\\fR\n.RS 4\nCompile, but don\\[cq]t run benchmarks.\n.RE\n.sp\n\\fB\\-\\-no\\-fail\\-fast\\fR\n.RS 4\nRun all benchmarks regardless of failure. Without this flag, Cargo will exit\nafter the first executable fails. The Rust test harness will run all benchmarks\nwithin the executable to completion, this flag only applies to the executable\nas a whole.\n.RE\n.SS \"Package Selection\"\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n\\fB\\-\\-manifest\\-path\\fR is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n.sp\nThe default members of a workspace can be set explicitly with the\n\\fBworkspace.default\\-members\\fR key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n\\fB\\-\\-workspace\\fR), and a non\\-virtual workspace will include only the root crate itself.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR\\[u2026], \n\\fB\\-\\-package\\fR \\fIspec\\fR\\[u2026]\n.RS 4\nBenchmark only the specified packages. See \\fBcargo\\-pkgid\\fR(1) for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.\n.RE\n.sp\n\\fB\\-\\-workspace\\fR\n.RS 4\nBenchmark all members in the workspace.\n.RE\n.sp\n\\fB\\-\\-all\\fR\n.RS 4\nDeprecated alias for \\fB\\-\\-workspace\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-exclude\\fR \\fISPEC\\fR\\[u2026]\n.RS 4\nExclude the specified packages. Must be used in conjunction with the\n\\fB\\-\\-workspace\\fR flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.\n.RE\n.SS \"Target Selection\"\nWhen no target selection options are given, \\fBcargo bench\\fR will build the\nfollowing targets of the selected packages:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'lib \\[em] used to link with binaries and benchmarks\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'bins (only if benchmark targets are built and required features are\navailable)\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'lib as a benchmark\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'bins as benchmarks\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'benchmark targets\n.RE\n.sp\nThe default behavior can be changed by setting the \\fBbench\\fR flag for the target\nin the manifest settings. Setting examples to \\fBbench = true\\fR will build and\nrun the example as a benchmark, replacing the example\\[cq]s \\fBmain\\fR function with\nthe libtest harness.\n.sp\nSetting targets to \\fBbench = false\\fR will stop them from being benchmarked by\ndefault. Target selection options that take a target by name (such as\n\\fB\\-\\-example foo\\fR) ignore the \\fBbench\\fR flag and will always benchmark the given\ntarget.\n.sp\nSee \\fIConfiguring a target\\fR <https://doc.rust\\-lang.org/cargo/reference/cargo\\-targets.html#configuring\\-a\\-target>\nfor more information on per\\-target settings.\n.sp\nBinary targets are automatically built if there is an integration test or\nbenchmark being selected to benchmark. This allows an integration\ntest to execute the binary to exercise and test its behavior.\nThe \\fBCARGO_BIN_EXE_<name>\\fR\n\\fIenvironment variable\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html#environment\\-variables\\-cargo\\-sets\\-for\\-crates>\nis set when the integration test is built and run so that it can use the\n\\fI\\f(BIenv\\fI macro\\fR <https://doc.rust\\-lang.org/std/macro.env.html> or the\n\\fI\\f(BIvar\\fI function\\fR <https://doc.rust\\-lang.org/std/env/fn.var.html> to locate the\nexecutable.\n.sp\nPassing target selection flags will benchmark only the specified\ntargets.\n.sp\nNote that \\fB\\-\\-bin\\fR, \\fB\\-\\-example\\fR, \\fB\\-\\-test\\fR and \\fB\\-\\-bench\\fR flags also\nsupport common Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your\nshell accidentally expanding glob patterns before Cargo handles them, you must\nuse single quotes or double quotes around each glob pattern.\n.sp\n\\fB\\-\\-lib\\fR\n.RS 4\nBenchmark the package\\[cq]s library.\n.RE\n.sp\n\\fB\\-\\-bin\\fR \\fIname\\fR\\[u2026]\n.RS 4\nBenchmark the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-bins\\fR\n.RS 4\nBenchmark all binary targets.\n.RE\n.sp\n\\fB\\-\\-example\\fR \\fIname\\fR\\[u2026]\n.RS 4\nBenchmark the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-examples\\fR\n.RS 4\nBenchmark all example targets.\n.RE\n.sp\n\\fB\\-\\-test\\fR \\fIname\\fR\\[u2026]\n.RS 4\nBenchmark the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-tests\\fR\n.RS 4\nBenchmark all targets that have the \\fBtest = true\\fR manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the \\fBtest\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-bench\\fR \\fIname\\fR\\[u2026]\n.RS 4\nBenchmark the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-benches\\fR\n.RS 4\nBenchmark all targets that have the \\fBbench = true\\fR\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the \\fBbench\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-all\\-targets\\fR\n.RS 4\nBenchmark all targets. This is equivalent to specifying \\fB\\-\\-lib \\-\\-bins \\-\\-tests \\-\\-benches \\-\\-examples\\fR\\&.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Compilation Options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nBenchmark for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.sp\n\\fB\\-\\-profile\\fR \\fIname\\fR\n.RS 4\nBenchmark with the given profile.\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/profiles.html> for more details on profiles.\n.RE\n.sp\n\\fB\\-\\-timings\\fR\n.RS 4\nOutput information how long each compilation takes, and track concurrency\ninformation over time.\n.sp\nA file \\fBcargo\\-timing.html\\fR will be written to the \\fBtarget/cargo\\-timings\\fR\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine\\-readable timing data.\n.RE\n.SS \"Output Options\"\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to \\fBtarget\\fR in the root of the workspace.\n.RE\n.SS \"Display Options\"\nBy default the Rust test harness hides output from benchmark execution to keep\nresults readable. Benchmark output can be recovered (e.g., for debugging) by\npassing \\fB\\-\\-no\\-capture\\fR to the benchmark binaries:\n.sp\n.RS 4\n.nf\ncargo bench \\-\\- \\-\\-no\\-capture\n.fi\n.RE\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-message\\-format\\fR \\fIfmt\\fR\n.RS 4\nThe output format for diagnostic messages. Can be specified multiple times\nand consists of comma\\-separated values. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBhuman\\fR (default): Display in a human\\-readable text format. Conflicts with\n\\fBshort\\fR and \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBshort\\fR: Emit shorter, human\\-readable text messages. Conflicts with \\fBhuman\\fR\nand \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR: Emit JSON messages to stdout. See\n\\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages>\nfor more details. Conflicts with \\fBhuman\\fR and \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-short\\fR: Ensure the \\fBrendered\\fR field of JSON messages contains\nthe \\[lq]short\\[rq] rendering from rustc. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-rendered\\-ansi\\fR: Ensure the \\fBrendered\\fR field of JSON messages\ncontains embedded ANSI color codes for respecting rustc\\[cq]s default color\nscheme. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-render\\-diagnostics\\fR: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo\\[cq]s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SS \"Miscellaneous Options\"\nThe \\fB\\-\\-jobs\\fR argument affects the building of the benchmark executable but\ndoes not affect how many threads are used when running the benchmarks. The\nRust test harness runs benchmarks serially in a single thread.\n.sp\n\\fB\\-j\\fR \\fIN\\fR, \n\\fB\\-\\-jobs\\fR \\fIN\\fR\n.RS 4\nNumber of parallel jobs to run. May also be specified with the\n\\fBbuild.jobs\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string \\fBdefault\\fR is provided, it sets the value back to defaults.\nShould not be 0.\n.RE\n.sp\nWhile \\fBcargo bench\\fR involves compilation, it does not provide a \\fB\\-\\-keep\\-going\\fR\nflag. Use \\fB\\-\\-no\\-fail\\-fast\\fR to run as many benchmarks as possible without\nstopping at the first failure. To \\[lq]compile\\[rq] as many benchmarks as possible, use\n\\fB\\-\\-benches\\fR to build benchmark binaries separately. For example:\n.sp\n.RS 4\n.nf\ncargo build \\-\\-benches \\-\\-release \\-\\-keep\\-going\ncargo bench \\-\\-no\\-fail\\-fast\n.fi\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Build and execute all the benchmarks of the current package:\n.sp\n.RS 4\n.nf\ncargo bench\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Run only a specific benchmark within a specific benchmark target:\n.sp\n.RS 4\n.nf\ncargo bench \\-\\-bench bench_name \\-\\- modname::some_benchmark\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-test\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-build.1",
    "content": "'\\\" t\n.TH \"CARGO\\-BUILD\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-build \\[em] Compile the current package\n.SH \"SYNOPSIS\"\n\\fBcargo build\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nCompile local packages and all of their dependencies.\n.SH \"OPTIONS\"\n.SS \"Package Selection\"\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n\\fB\\-\\-manifest\\-path\\fR is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n.sp\nThe default members of a workspace can be set explicitly with the\n\\fBworkspace.default\\-members\\fR key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n\\fB\\-\\-workspace\\fR), and a non\\-virtual workspace will include only the root crate itself.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR\\[u2026], \n\\fB\\-\\-package\\fR \\fIspec\\fR\\[u2026]\n.RS 4\nBuild only the specified packages. See \\fBcargo\\-pkgid\\fR(1) for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.\n.RE\n.sp\n\\fB\\-\\-workspace\\fR\n.RS 4\nBuild all members in the workspace.\n.RE\n.sp\n\\fB\\-\\-all\\fR\n.RS 4\nDeprecated alias for \\fB\\-\\-workspace\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-exclude\\fR \\fISPEC\\fR\\[u2026]\n.RS 4\nExclude the specified packages. Must be used in conjunction with the\n\\fB\\-\\-workspace\\fR flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.\n.RE\n.SS \"Target Selection\"\nWhen no target selection options are given, \\fBcargo build\\fR will build all\nbinary and library targets of the selected packages. Binaries are skipped if\nthey have \\fBrequired\\-features\\fR that are missing.\n.sp\nBinary targets are automatically built if there is an integration test or\nbenchmark being selected to build. This allows an integration\ntest to execute the binary to exercise and test its behavior.\nThe \\fBCARGO_BIN_EXE_<name>\\fR\n\\fIenvironment variable\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html#environment\\-variables\\-cargo\\-sets\\-for\\-crates>\nis set when the integration test is built and run so that it can use the\n\\fI\\f(BIenv\\fI macro\\fR <https://doc.rust\\-lang.org/std/macro.env.html> or the\n\\fI\\f(BIvar\\fI function\\fR <https://doc.rust\\-lang.org/std/env/fn.var.html> to locate the\nexecutable.\n.sp\nPassing target selection flags will build only the specified\ntargets.\n.sp\nNote that \\fB\\-\\-bin\\fR, \\fB\\-\\-example\\fR, \\fB\\-\\-test\\fR and \\fB\\-\\-bench\\fR flags also\nsupport common Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your\nshell accidentally expanding glob patterns before Cargo handles them, you must\nuse single quotes or double quotes around each glob pattern.\n.sp\n\\fB\\-\\-lib\\fR\n.RS 4\nBuild the package\\[cq]s library.\n.RE\n.sp\n\\fB\\-\\-bin\\fR \\fIname\\fR\\[u2026]\n.RS 4\nBuild the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-bins\\fR\n.RS 4\nBuild all binary targets.\n.RE\n.sp\n\\fB\\-\\-example\\fR \\fIname\\fR\\[u2026]\n.RS 4\nBuild the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-examples\\fR\n.RS 4\nBuild all example targets.\n.RE\n.sp\n\\fB\\-\\-test\\fR \\fIname\\fR\\[u2026]\n.RS 4\nBuild the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-tests\\fR\n.RS 4\nBuild all targets that have the \\fBtest = true\\fR manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the \\fBtest\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-bench\\fR \\fIname\\fR\\[u2026]\n.RS 4\nBuild the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-benches\\fR\n.RS 4\nBuild all targets that have the \\fBbench = true\\fR\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the \\fBbench\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-all\\-targets\\fR\n.RS 4\nBuild all targets. This is equivalent to specifying \\fB\\-\\-lib \\-\\-bins \\-\\-tests \\-\\-benches \\-\\-examples\\fR\\&.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Compilation Options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nBuild for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.sp\n\\fB\\-r\\fR, \n\\fB\\-\\-release\\fR\n.RS 4\nBuild optimized artifacts with the \\fBrelease\\fR profile.\nSee also the \\fB\\-\\-profile\\fR option for choosing a specific profile by name.\n.RE\n.sp\n\\fB\\-\\-profile\\fR \\fIname\\fR\n.RS 4\nBuild with the given profile.\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/profiles.html> for more details on profiles.\n.RE\n.sp\n\\fB\\-\\-timings\\fR\n.RS 4\nOutput information how long each compilation takes, and track concurrency\ninformation over time.\n.sp\nA file \\fBcargo\\-timing.html\\fR will be written to the \\fBtarget/cargo\\-timings\\fR\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine\\-readable timing data.\n.RE\n.SS \"Output Options\"\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to \\fBtarget\\fR in the root of the workspace.\n.RE\n.sp\n\\fB\\-\\-artifact\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nCopy final artifacts to this directory.\n.sp\nThis option is unstable and available only on the\n\\fInightly channel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html>\nand requires the \\fB\\-Z unstable\\-options\\fR flag to enable.\nSee <https://github.com/rust\\-lang/cargo/issues/6790> for more information.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-message\\-format\\fR \\fIfmt\\fR\n.RS 4\nThe output format for diagnostic messages. Can be specified multiple times\nand consists of comma\\-separated values. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBhuman\\fR (default): Display in a human\\-readable text format. Conflicts with\n\\fBshort\\fR and \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBshort\\fR: Emit shorter, human\\-readable text messages. Conflicts with \\fBhuman\\fR\nand \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR: Emit JSON messages to stdout. See\n\\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages>\nfor more details. Conflicts with \\fBhuman\\fR and \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-short\\fR: Ensure the \\fBrendered\\fR field of JSON messages contains\nthe \\[lq]short\\[rq] rendering from rustc. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-rendered\\-ansi\\fR: Ensure the \\fBrendered\\fR field of JSON messages\ncontains embedded ANSI color codes for respecting rustc\\[cq]s default color\nscheme. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-render\\-diagnostics\\fR: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo\\[cq]s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SS \"Miscellaneous Options\"\n.sp\n\\fB\\-j\\fR \\fIN\\fR, \n\\fB\\-\\-jobs\\fR \\fIN\\fR\n.RS 4\nNumber of parallel jobs to run. May also be specified with the\n\\fBbuild.jobs\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string \\fBdefault\\fR is provided, it sets the value back to defaults.\nShould not be 0.\n.RE\n.sp\n\\fB\\-\\-keep\\-going\\fR\n.RS 4\nBuild as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.\n.sp\nFor example if the current package depends on dependencies \\fBfails\\fR and \\fBworks\\fR,\none of which fails to build, \\fBcargo build \\-j1\\fR may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas \\fBcargo build \\-j1 \\-\\-keep\\-going\\fR would definitely run both\nbuilds, even if the one run first fails.\n.RE\n.sp\n\\fB\\-\\-future\\-incompat\\-report\\fR\n.RS 4\nDisplays a future\\-incompat report for any future\\-incompatible warnings\nproduced during execution of this command\n.sp\nSee \\fBcargo\\-report\\fR(1)\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Build the local package and all of its dependencies:\n.sp\n.RS 4\n.nf\ncargo build\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Build with optimizations:\n.sp\n.RS 4\n.nf\ncargo build \\-\\-release\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-rustc\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-check.1",
    "content": "'\\\" t\n.TH \"CARGO\\-CHECK\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-check \\[em] Check the current package\n.SH \"SYNOPSIS\"\n\\fBcargo check\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nCheck a local package and all of its dependencies for errors. This will\nessentially compile the packages without performing the final step of code\ngeneration, which is faster than running \\fBcargo build\\fR\\&. The compiler will save\nmetadata files to disk so that future runs will reuse them if the source has\nnot been modified. Some diagnostics and errors are only emitted during code\ngeneration, so they inherently won\\[cq]t be reported with \\fBcargo check\\fR\\&.\n.SH \"OPTIONS\"\n.SS \"Package Selection\"\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n\\fB\\-\\-manifest\\-path\\fR is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n.sp\nThe default members of a workspace can be set explicitly with the\n\\fBworkspace.default\\-members\\fR key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n\\fB\\-\\-workspace\\fR), and a non\\-virtual workspace will include only the root crate itself.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR\\[u2026], \n\\fB\\-\\-package\\fR \\fIspec\\fR\\[u2026]\n.RS 4\nCheck only the specified packages. See \\fBcargo\\-pkgid\\fR(1) for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.\n.RE\n.sp\n\\fB\\-\\-workspace\\fR\n.RS 4\nCheck all members in the workspace.\n.RE\n.sp\n\\fB\\-\\-all\\fR\n.RS 4\nDeprecated alias for \\fB\\-\\-workspace\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-exclude\\fR \\fISPEC\\fR\\[u2026]\n.RS 4\nExclude the specified packages. Must be used in conjunction with the\n\\fB\\-\\-workspace\\fR flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.\n.RE\n.SS \"Target Selection\"\nWhen no target selection options are given, \\fBcargo check\\fR will check all\nbinary and library targets of the selected packages. Binaries are skipped if\nthey have \\fBrequired\\-features\\fR that are missing.\n.sp\nPassing target selection flags will check only the specified\ntargets.\n.sp\nNote that \\fB\\-\\-bin\\fR, \\fB\\-\\-example\\fR, \\fB\\-\\-test\\fR and \\fB\\-\\-bench\\fR flags also\nsupport common Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your\nshell accidentally expanding glob patterns before Cargo handles them, you must\nuse single quotes or double quotes around each glob pattern.\n.sp\n\\fB\\-\\-lib\\fR\n.RS 4\nCheck the package\\[cq]s library.\n.RE\n.sp\n\\fB\\-\\-bin\\fR \\fIname\\fR\\[u2026]\n.RS 4\nCheck the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-bins\\fR\n.RS 4\nCheck all binary targets.\n.RE\n.sp\n\\fB\\-\\-example\\fR \\fIname\\fR\\[u2026]\n.RS 4\nCheck the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-examples\\fR\n.RS 4\nCheck all example targets.\n.RE\n.sp\n\\fB\\-\\-test\\fR \\fIname\\fR\\[u2026]\n.RS 4\nCheck the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-tests\\fR\n.RS 4\nCheck all targets that have the \\fBtest = true\\fR manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the \\fBtest\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-bench\\fR \\fIname\\fR\\[u2026]\n.RS 4\nCheck the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-benches\\fR\n.RS 4\nCheck all targets that have the \\fBbench = true\\fR\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the \\fBbench\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-all\\-targets\\fR\n.RS 4\nCheck all targets. This is equivalent to specifying \\fB\\-\\-lib \\-\\-bins \\-\\-tests \\-\\-benches \\-\\-examples\\fR\\&.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Compilation Options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nCheck for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.sp\n\\fB\\-r\\fR, \n\\fB\\-\\-release\\fR\n.RS 4\nCheck optimized artifacts with the \\fBrelease\\fR profile.\nSee also the \\fB\\-\\-profile\\fR option for choosing a specific profile by name.\n.RE\n.sp\n\\fB\\-\\-profile\\fR \\fIname\\fR\n.RS 4\nCheck with the given profile.\n.sp\nAs a special case, specifying the \\fBtest\\fR profile will also enable checking in\ntest mode which will enable checking tests and enable the \\fBtest\\fR cfg option.\nSee \\fIrustc tests\\fR <https://doc.rust\\-lang.org/rustc/tests/index.html> for more\ndetail.\n.sp\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/profiles.html> for more details on profiles.\n.RE\n.sp\n\\fB\\-\\-timings\\fR\n.RS 4\nOutput information how long each compilation takes, and track concurrency\ninformation over time.\n.sp\nA file \\fBcargo\\-timing.html\\fR will be written to the \\fBtarget/cargo\\-timings\\fR\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine\\-readable timing data.\n.RE\n.SS \"Output Options\"\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to \\fBtarget\\fR in the root of the workspace.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-message\\-format\\fR \\fIfmt\\fR\n.RS 4\nThe output format for diagnostic messages. Can be specified multiple times\nand consists of comma\\-separated values. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBhuman\\fR (default): Display in a human\\-readable text format. Conflicts with\n\\fBshort\\fR and \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBshort\\fR: Emit shorter, human\\-readable text messages. Conflicts with \\fBhuman\\fR\nand \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR: Emit JSON messages to stdout. See\n\\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages>\nfor more details. Conflicts with \\fBhuman\\fR and \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-short\\fR: Ensure the \\fBrendered\\fR field of JSON messages contains\nthe \\[lq]short\\[rq] rendering from rustc. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-rendered\\-ansi\\fR: Ensure the \\fBrendered\\fR field of JSON messages\ncontains embedded ANSI color codes for respecting rustc\\[cq]s default color\nscheme. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-render\\-diagnostics\\fR: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo\\[cq]s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SS \"Miscellaneous Options\"\n.sp\n\\fB\\-j\\fR \\fIN\\fR, \n\\fB\\-\\-jobs\\fR \\fIN\\fR\n.RS 4\nNumber of parallel jobs to run. May also be specified with the\n\\fBbuild.jobs\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string \\fBdefault\\fR is provided, it sets the value back to defaults.\nShould not be 0.\n.RE\n.sp\n\\fB\\-\\-keep\\-going\\fR\n.RS 4\nBuild as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.\n.sp\nFor example if the current package depends on dependencies \\fBfails\\fR and \\fBworks\\fR,\none of which fails to build, \\fBcargo check \\-j1\\fR may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas \\fBcargo check \\-j1 \\-\\-keep\\-going\\fR would definitely run both\nbuilds, even if the one run first fails.\n.RE\n.sp\n\\fB\\-\\-future\\-incompat\\-report\\fR\n.RS 4\nDisplays a future\\-incompat report for any future\\-incompatible warnings\nproduced during execution of this command\n.sp\nSee \\fBcargo\\-report\\fR(1)\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Check the local package for errors:\n.sp\n.RS 4\n.nf\ncargo check\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Check all targets, including unit tests:\n.sp\n.RS 4\n.nf\ncargo check \\-\\-all\\-targets \\-\\-profile=test\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-build\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-clean.1",
    "content": "'\\\" t\n.TH \"CARGO\\-CLEAN\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-clean \\[em] Remove generated artifacts\n.SH \"SYNOPSIS\"\n\\fBcargo clean\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nRemove artifacts from the target directory that Cargo has generated in the\npast.\n.sp\nWith no options, \\fBcargo clean\\fR will delete the entire target directory.\n.SH \"OPTIONS\"\n.SS \"Package Selection\"\nWhen no packages are selected, all packages and all dependencies in the\nworkspace are cleaned.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR\\[u2026], \n\\fB\\-\\-package\\fR \\fIspec\\fR\\[u2026]\n.RS 4\nClean only the specified packages. This flag may be specified\nmultiple times. See \\fBcargo\\-pkgid\\fR(1) for the SPEC format.\n.RE\n.sp\n\\fB\\-\\-workspace\\fR\n.RS 4\nClean artifacts of the workspace members.\n.RE\n.SS \"Clean Options\"\n.sp\n\\fB\\-\\-dry\\-run\\fR\n.RS 4\nDisplays a summary of what would be deleted without deleting anything.\nUse with \\fB\\-\\-verbose\\fR to display the actual files that would be deleted.\n.RE\n.sp\n\\fB\\-\\-doc\\fR\n.RS 4\nThis option will cause \\fBcargo clean\\fR to remove only the \\fBdoc\\fR directory in\nthe target directory.\n.RE\n.sp\n\\fB\\-\\-release\\fR\n.RS 4\nRemove all artifacts in the \\fBrelease\\fR directory.\n.RE\n.sp\n\\fB\\-\\-profile\\fR \\fIname\\fR\n.RS 4\nRemove all artifacts in the directory with the given profile name.\n.RE\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to \\fBtarget\\fR in the root of the workspace.\n.RE\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nClean for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Remove the entire target directory:\n.sp\n.RS 4\n.nf\ncargo clean\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Remove only the release artifacts:\n.sp\n.RS 4\n.nf\ncargo clean \\-\\-release\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-build\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-doc.1",
    "content": "'\\\" t\n.TH \"CARGO\\-DOC\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-doc \\[em] Build a package\\[cq]s documentation\n.SH \"SYNOPSIS\"\n\\fBcargo doc\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nBuild the documentation for the local package and all dependencies. The output\nis placed in \\fBtarget/doc\\fR in rustdoc\\[cq]s usual format.\n.sp\n\\fBNote:\\fR Documentation generation is cumulative: existing doc files in the target directory are preserved across different \\fBcargo doc\\fR invocations. To remove existing generated docs, pass \\fB\\-\\-doc\\fR to \\fBcargo\\-clean\\fR(1).\n.SH \"OPTIONS\"\n.SS \"Documentation Options\"\n.sp\n\\fB\\-\\-open\\fR\n.RS 4\nOpen the docs in a browser after building them. This will use your default\nbrowser unless you define another one in the \\fBBROWSER\\fR environment variable\nor use the \\fI\\f(BIdoc.browser\\fI\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#docbrowser> configuration\noption.\n.RE\n.sp\n\\fB\\-\\-no\\-deps\\fR\n.RS 4\nDo not build documentation for dependencies.\n.RE\n.sp\n\\fB\\-\\-document\\-private\\-items\\fR\n.RS 4\nInclude non\\-public items in the documentation. This will be enabled by default if documenting a binary target.\n.RE\n.SS \"Package Selection\"\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n\\fB\\-\\-manifest\\-path\\fR is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n.sp\nThe default members of a workspace can be set explicitly with the\n\\fBworkspace.default\\-members\\fR key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n\\fB\\-\\-workspace\\fR), and a non\\-virtual workspace will include only the root crate itself.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR\\[u2026], \n\\fB\\-\\-package\\fR \\fIspec\\fR\\[u2026]\n.RS 4\nDocument only the specified packages. See \\fBcargo\\-pkgid\\fR(1) for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.\n.RE\n.sp\n\\fB\\-\\-workspace\\fR\n.RS 4\nDocument all members in the workspace.\n.RE\n.sp\n\\fB\\-\\-all\\fR\n.RS 4\nDeprecated alias for \\fB\\-\\-workspace\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-exclude\\fR \\fISPEC\\fR\\[u2026]\n.RS 4\nExclude the specified packages. Must be used in conjunction with the\n\\fB\\-\\-workspace\\fR flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.\n.RE\n.SS \"Target Selection\"\nWhen no target selection options are given, \\fBcargo doc\\fR will document all\nbinary and library targets of the selected package. The binary will be skipped\nif its name is the same as the lib target. Binaries are skipped if they have\n\\fBrequired\\-features\\fR that are missing.\n.sp\nThe default behavior can be changed by setting \\fBdoc = false\\fR for the target in\nthe manifest settings. Using target selection options will ignore the \\fBdoc\\fR\nflag and will always document the given target.\n.sp\n\\fB\\-\\-lib\\fR\n.RS 4\nDocument the package\\[cq]s library.\n.RE\n.sp\n\\fB\\-\\-bin\\fR \\fIname\\fR\\[u2026]\n.RS 4\nDocument the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-bins\\fR\n.RS 4\nDocument all binary targets.\n.RE\n.sp\n\\fB\\-\\-example\\fR \\fIname\\fR\\[u2026]\n.RS 4\nDocument the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-examples\\fR\n.RS 4\nDocument all example targets.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Compilation Options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nDocument for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.sp\n\\fB\\-r\\fR, \n\\fB\\-\\-release\\fR\n.RS 4\nDocument optimized artifacts with the \\fBrelease\\fR profile.\nSee also the \\fB\\-\\-profile\\fR option for choosing a specific profile by name.\n.RE\n.sp\n\\fB\\-\\-profile\\fR \\fIname\\fR\n.RS 4\nDocument with the given profile.\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/profiles.html> for more details on profiles.\n.RE\n.sp\n\\fB\\-\\-timings\\fR\n.RS 4\nOutput information how long each compilation takes, and track concurrency\ninformation over time.\n.sp\nA file \\fBcargo\\-timing.html\\fR will be written to the \\fBtarget/cargo\\-timings\\fR\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine\\-readable timing data.\n.RE\n.SS \"Output Options\"\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to \\fBtarget\\fR in the root of the workspace.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-message\\-format\\fR \\fIfmt\\fR\n.RS 4\nThe output format for diagnostic messages. Can be specified multiple times\nand consists of comma\\-separated values. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBhuman\\fR (default): Display in a human\\-readable text format. Conflicts with\n\\fBshort\\fR and \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBshort\\fR: Emit shorter, human\\-readable text messages. Conflicts with \\fBhuman\\fR\nand \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR: Emit JSON messages to stdout. See\n\\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages>\nfor more details. Conflicts with \\fBhuman\\fR and \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-short\\fR: Ensure the \\fBrendered\\fR field of JSON messages contains\nthe \\[lq]short\\[rq] rendering from rustc. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-rendered\\-ansi\\fR: Ensure the \\fBrendered\\fR field of JSON messages\ncontains embedded ANSI color codes for respecting rustc\\[cq]s default color\nscheme. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-render\\-diagnostics\\fR: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo\\[cq]s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SS \"Miscellaneous Options\"\n.sp\n\\fB\\-j\\fR \\fIN\\fR, \n\\fB\\-\\-jobs\\fR \\fIN\\fR\n.RS 4\nNumber of parallel jobs to run. May also be specified with the\n\\fBbuild.jobs\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string \\fBdefault\\fR is provided, it sets the value back to defaults.\nShould not be 0.\n.RE\n.sp\n\\fB\\-\\-keep\\-going\\fR\n.RS 4\nBuild as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.\n.sp\nFor example if the current package depends on dependencies \\fBfails\\fR and \\fBworks\\fR,\none of which fails to build, \\fBcargo doc \\-j1\\fR may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas \\fBcargo doc \\-j1 \\-\\-keep\\-going\\fR would definitely run both\nbuilds, even if the one run first fails.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Build the local package documentation and its dependencies and output to\n\\fBtarget/doc\\fR\\&.\n.sp\n.RS 4\n.nf\ncargo doc\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-rustdoc\\fR(1), \\fBrustdoc\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-fetch.1",
    "content": "'\\\" t\n.TH \"CARGO\\-FETCH\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-fetch \\[em] Fetch dependencies of a package from the network\n.SH \"SYNOPSIS\"\n\\fBcargo fetch\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nIf a \\fBCargo.lock\\fR file is available, this command will ensure that all of the\ngit dependencies and/or registry dependencies are downloaded and locally\navailable. Subsequent Cargo commands will be able to run offline after a \\fBcargo fetch\\fR unless the lock file changes.\n.sp\nIf the lock file is not available, then this command will generate the lock\nfile before fetching the dependencies.\n.sp\nIf \\fB\\-\\-target\\fR is not specified, then all target dependencies are fetched.\n.sp\nSee also the \\fIcargo\\-prefetch\\fR <https://crates.io/crates/cargo\\-prefetch>\nplugin which adds a command to download popular crates. This may be useful if\nyou plan to use Cargo without a network with the \\fB\\-\\-offline\\fR flag.\n.SH \"OPTIONS\"\n.SS \"Fetch options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nFetch for the specified target architecture. Flag may be specified multiple times. The default is all architectures. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Fetch all dependencies:\n.sp\n.RS 4\n.nf\ncargo fetch\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-update\\fR(1), \\fBcargo\\-generate\\-lockfile\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-fix.1",
    "content": "'\\\" t\n.TH \"CARGO\\-FIX\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-fix \\[em] Automatically fix lint warnings reported by rustc\n.SH \"SYNOPSIS\"\n\\fBcargo fix\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nThis Cargo subcommand will automatically take rustc\\[cq]s suggestions from\ndiagnostics like warnings and apply them to your source code. This is intended\nto help automate tasks that rustc itself already knows how to tell you to fix!\n.sp\nExecuting \\fBcargo fix\\fR will under the hood execute \\fBcargo\\-check\\fR(1). Any warnings\napplicable to your crate will be automatically fixed (if possible) and all\nremaining warnings will be displayed when the check process is finished. For\nexample if you\\[cq]d like to apply all fixes to the current package, you can run:\n.sp\n.RS 4\n.nf\ncargo fix\n.fi\n.RE\n.sp\nwhich behaves the same as \\fBcargo check \\-\\-all\\-targets\\fR\\&.\n.sp\n\\fBcargo fix\\fR is only capable of fixing code that is normally compiled with\n\\fBcargo check\\fR\\&. If code is conditionally enabled with optional features, you\nwill need to enable those features for that code to be analyzed:\n.sp\n.RS 4\n.nf\ncargo fix \\-\\-features foo\n.fi\n.RE\n.sp\nSimilarly, other \\fBcfg\\fR expressions like platform\\-specific code will need to\npass \\fB\\-\\-target\\fR to fix code for the given target.\n.sp\n.RS 4\n.nf\ncargo fix \\-\\-target x86_64\\-pc\\-windows\\-gnu\n.fi\n.RE\n.sp\nIf you encounter any problems with \\fBcargo fix\\fR or otherwise have any questions\nor feature requests please don\\[cq]t hesitate to file an issue at\n<https://github.com/rust\\-lang/cargo>\\&.\n.SS \"Edition migration\"\nThe \\fBcargo fix\\fR subcommand can also be used to migrate a package from one\n\\fIedition\\fR <https://doc.rust\\-lang.org/edition\\-guide/editions/transitioning\\-an\\-existing\\-project\\-to\\-a\\-new\\-edition.html> to the next. The general procedure is:\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Run \\fBcargo fix \\-\\-edition\\fR\\&. Consider also using the \\fB\\-\\-all\\-features\\fR flag if\nyour project has multiple features. You may also want to run \\fBcargo fix \\-\\-edition\\fR multiple times with different \\fB\\-\\-target\\fR flags if your project\nhas platform\\-specific code gated by \\fBcfg\\fR attributes.\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Modify \\fBCargo.toml\\fR to set the \\fIedition field\\fR <https://doc.rust\\-lang.org/cargo/reference/manifest.html#the\\-edition\\-field> to the new edition.\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Run your project tests to verify that everything still works. If new\nwarnings are issued, you may want to consider running \\fBcargo fix\\fR again\n(without the \\fB\\-\\-edition\\fR flag) to apply any suggestions given by the\ncompiler.\n.RE\n.sp\nAnd hopefully that\\[cq]s it! Just keep in mind of the caveats mentioned above that\n\\fBcargo fix\\fR cannot update code for inactive features or \\fBcfg\\fR expressions.\nAlso, in some rare cases the compiler is unable to automatically migrate all\ncode to the new edition, and this may require manual changes after building\nwith the new edition.\n.SH \"OPTIONS\"\n.SS \"Fix options\"\n.sp\n\\fB\\-\\-broken\\-code\\fR\n.RS 4\nFix code even if it already has compiler errors. This is useful if \\fBcargo fix\\fR\nfails to apply the changes. It will apply the changes and leave the broken\ncode in the working directory for you to inspect and manually fix.\n.RE\n.sp\n\\fB\\-\\-edition\\fR\n.RS 4\nApply changes that will update the code to the next edition. This will not\nupdate the edition in the \\fBCargo.toml\\fR manifest, which must be updated\nmanually after \\fBcargo fix \\-\\-edition\\fR has finished.\n.RE\n.sp\n\\fB\\-\\-edition\\-idioms\\fR\n.RS 4\nApply suggestions that will update code to the preferred style for the current\nedition.\n.RE\n.sp\n\\fB\\-\\-allow\\-no\\-vcs\\fR\n.RS 4\nFix code even if a VCS was not detected.\n.RE\n.sp\n\\fB\\-\\-allow\\-dirty\\fR\n.RS 4\nFix code even if the working directory has changes (including staged changes).\n.RE\n.sp\n\\fB\\-\\-allow\\-staged\\fR\n.RS 4\nFix code even if the working directory has staged changes.\n.RE\n.SS \"Package Selection\"\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n\\fB\\-\\-manifest\\-path\\fR is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n.sp\nThe default members of a workspace can be set explicitly with the\n\\fBworkspace.default\\-members\\fR key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n\\fB\\-\\-workspace\\fR), and a non\\-virtual workspace will include only the root crate itself.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR\\[u2026], \n\\fB\\-\\-package\\fR \\fIspec\\fR\\[u2026]\n.RS 4\nFix only the specified packages. See \\fBcargo\\-pkgid\\fR(1) for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.\n.RE\n.sp\n\\fB\\-\\-workspace\\fR\n.RS 4\nFix all members in the workspace.\n.RE\n.sp\n\\fB\\-\\-all\\fR\n.RS 4\nDeprecated alias for \\fB\\-\\-workspace\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-exclude\\fR \\fISPEC\\fR\\[u2026]\n.RS 4\nExclude the specified packages. Must be used in conjunction with the\n\\fB\\-\\-workspace\\fR flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.\n.RE\n.SS \"Target Selection\"\nWhen no target selection options are given, \\fBcargo fix\\fR will fix all targets\n(\\fB\\-\\-all\\-targets\\fR implied). Binaries are skipped if they have\n\\fBrequired\\-features\\fR that are missing.\n.sp\nPassing target selection flags will fix only the specified\ntargets.\n.sp\nNote that \\fB\\-\\-bin\\fR, \\fB\\-\\-example\\fR, \\fB\\-\\-test\\fR and \\fB\\-\\-bench\\fR flags also\nsupport common Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your\nshell accidentally expanding glob patterns before Cargo handles them, you must\nuse single quotes or double quotes around each glob pattern.\n.sp\n\\fB\\-\\-lib\\fR\n.RS 4\nFix the package\\[cq]s library.\n.RE\n.sp\n\\fB\\-\\-bin\\fR \\fIname\\fR\\[u2026]\n.RS 4\nFix the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-bins\\fR\n.RS 4\nFix all binary targets.\n.RE\n.sp\n\\fB\\-\\-example\\fR \\fIname\\fR\\[u2026]\n.RS 4\nFix the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-examples\\fR\n.RS 4\nFix all example targets.\n.RE\n.sp\n\\fB\\-\\-test\\fR \\fIname\\fR\\[u2026]\n.RS 4\nFix the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-tests\\fR\n.RS 4\nFix all targets that have the \\fBtest = true\\fR manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the \\fBtest\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-bench\\fR \\fIname\\fR\\[u2026]\n.RS 4\nFix the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-benches\\fR\n.RS 4\nFix all targets that have the \\fBbench = true\\fR\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the \\fBbench\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-all\\-targets\\fR\n.RS 4\nFix all targets. This is equivalent to specifying \\fB\\-\\-lib \\-\\-bins \\-\\-tests \\-\\-benches \\-\\-examples\\fR\\&.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Compilation Options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nFix for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.sp\n\\fB\\-r\\fR, \n\\fB\\-\\-release\\fR\n.RS 4\nFix optimized artifacts with the \\fBrelease\\fR profile.\nSee also the \\fB\\-\\-profile\\fR option for choosing a specific profile by name.\n.RE\n.sp\n\\fB\\-\\-profile\\fR \\fIname\\fR\n.RS 4\nFix with the given profile.\n.sp\nAs a special case, specifying the \\fBtest\\fR profile will also enable checking in\ntest mode which will enable checking tests and enable the \\fBtest\\fR cfg option.\nSee \\fIrustc tests\\fR <https://doc.rust\\-lang.org/rustc/tests/index.html> for more\ndetail.\n.sp\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/profiles.html> for more details on profiles.\n.RE\n.sp\n\\fB\\-\\-timings\\fR\n.RS 4\nOutput information how long each compilation takes, and track concurrency\ninformation over time.\n.sp\nA file \\fBcargo\\-timing.html\\fR will be written to the \\fBtarget/cargo\\-timings\\fR\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine\\-readable timing data.\n.RE\n.SS \"Output Options\"\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to \\fBtarget\\fR in the root of the workspace.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-message\\-format\\fR \\fIfmt\\fR\n.RS 4\nThe output format for diagnostic messages. Can be specified multiple times\nand consists of comma\\-separated values. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBhuman\\fR (default): Display in a human\\-readable text format. Conflicts with\n\\fBshort\\fR and \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBshort\\fR: Emit shorter, human\\-readable text messages. Conflicts with \\fBhuman\\fR\nand \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR: Emit JSON messages to stdout. See\n\\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages>\nfor more details. Conflicts with \\fBhuman\\fR and \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-short\\fR: Ensure the \\fBrendered\\fR field of JSON messages contains\nthe \\[lq]short\\[rq] rendering from rustc. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-rendered\\-ansi\\fR: Ensure the \\fBrendered\\fR field of JSON messages\ncontains embedded ANSI color codes for respecting rustc\\[cq]s default color\nscheme. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-render\\-diagnostics\\fR: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo\\[cq]s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SS \"Miscellaneous Options\"\n.sp\n\\fB\\-j\\fR \\fIN\\fR, \n\\fB\\-\\-jobs\\fR \\fIN\\fR\n.RS 4\nNumber of parallel jobs to run. May also be specified with the\n\\fBbuild.jobs\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string \\fBdefault\\fR is provided, it sets the value back to defaults.\nShould not be 0.\n.RE\n.sp\n\\fB\\-\\-keep\\-going\\fR\n.RS 4\nBuild as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.\n.sp\nFor example if the current package depends on dependencies \\fBfails\\fR and \\fBworks\\fR,\none of which fails to build, \\fBcargo fix \\-j1\\fR may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas \\fBcargo fix \\-j1 \\-\\-keep\\-going\\fR would definitely run both\nbuilds, even if the one run first fails.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Apply compiler suggestions to the local package:\n.sp\n.RS 4\n.nf\ncargo fix\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Update a package to prepare it for the next edition:\n.sp\n.RS 4\n.nf\ncargo fix \\-\\-edition\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Apply suggested idioms for the current edition:\n.sp\n.RS 4\n.nf\ncargo fix \\-\\-edition\\-idioms\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-check\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-generate-lockfile.1",
    "content": "'\\\" t\n.TH \"CARGO\\-GENERATE\\-LOCKFILE\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-generate\\-lockfile \\[em] Generate the lockfile for a package\n.SH \"SYNOPSIS\"\n\\fBcargo generate\\-lockfile\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nThis command will create the \\fBCargo.lock\\fR lockfile for the current package or\nworkspace. If the lockfile already exists, it will be rebuilt with the latest\navailable version of every package.\n.sp\nSee also \\fBcargo\\-update\\fR(1) which is also capable of creating a \\fBCargo.lock\\fR\nlockfile and has more options for controlling update behavior.\n.SH \"OPTIONS\"\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-publish\\-time\\fR \\fIyyyy\\-mm\\-ddThh:mm:ssZ\\fR\n.RS 4\nLatest publish time allowed for registry packages (Unstable)\n.sp\nThis is a best\\-effort filter on allowed packages, including:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'packages from unsupported registries are always accepted\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'only the current yank state is respected, not the state as of \\fB\\-\\-publish\\-time\\fR\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'precision of the publish time\n.RE\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Create or update the lockfile for the current package or workspace:\n.sp\n.RS 4\n.nf\ncargo generate\\-lockfile\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-update\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-help.1",
    "content": "'\\\" t\n.TH \"CARGO\\-HELP\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-help \\[em] Get help for a Cargo command\n.SH \"SYNOPSIS\"\n\\fBcargo help\\fR [\\fIsubcommand\\fR]\n.SH \"DESCRIPTION\"\nPrints a help message for the given command.\n.sp\nFor commands with subcommands, separate the command levels with spaces. For\nexample, \\fBcargo help report future\\-incompatibilities\\fR displays help for the\n\\fBcargo report future\\-incompatibilities\\fR command.\n.sp\nSpaces separate hierarchy levels only between a parent command and its\nsubcommands. Dashes that are part of a command\\[cq]s name, such as\n\\fBgenerate\\-lockfile\\fR, must always be preserved.\n.sp\nMultiple command levels can also be written as a single dash\\-joined word.\nFor example, \\fBcargo help report\\-future\\-incompatibilities\\fR is equivalent to\n\\fBcargo help report future\\-incompatibilities\\fR\\&.\n.SH \"OPTIONS\"\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Get help for a command:\n.sp\n.RS 4\n.nf\ncargo help build\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Get help for a nested command:\n.sp\n.RS 4\n.nf\ncargo help report future\\-incompatibilities\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'The dash\\-joined form also works:\n.sp\n.RS 4\n.nf\ncargo help report\\-future\\-incompatibilities\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 4.\\h'+01'Help is also available with the \\fB\\-\\-help\\fR flag:\n.sp\n.RS 4\n.nf\ncargo build \\-\\-help\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-info.1",
    "content": "'\\\" t\n.TH \"CARGO\\-INFO\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-info \\[em] Display information about a package.\n.SH \"SYNOPSIS\"\n\\fBcargo info\\fR [\\fIoptions\\fR] \\fIspec\\fR\n.SH \"DESCRIPTION\"\nThis command displays information about a package. It fetches data from the package\\[cq]s Cargo.toml file\nand presents it in a human\\-readable format.\n.SH \"OPTIONS\"\n.SS \"Info Options\"\n.sp\n\\fIspec\\fR\n.RS 4\nFetch information about the specified package. The \\fIspec\\fR can be a package ID, see \\fBcargo\\-pkgid\\fR(1) for the SPEC\nformat.\nIf the specified package is part of the current workspace, information from the local Cargo.toml file will be displayed.\nIf the \\fBCargo.lock\\fR file does not exist, it will be created. If no version is specified, the appropriate version will be\nselected based on the Minimum Supported Rust Version (MSRV).\n.RE\n.sp\n\\fB\\-\\-index\\fR \\fIindex\\fR\n.RS 4\nThe URL of the registry index to use.\n.RE\n.sp\n\\fB\\-\\-registry\\fR \\fIregistry\\fR\n.RS 4\nName of the registry to use. Registry names are defined in \\fICargo config\nfiles\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. If not specified, the default registry is used,\nwhich is defined by the \\fBregistry.default\\fR config key which defaults to\n\\fBcrates\\-io\\fR\\&.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Inspect the \\fBserde\\fR package from crates.io:\n.sp\n.RS 4\n.nf\n cargo info serde\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Inspect the \\fBserde\\fR package with version \\fB1.0.0\\fR:\n.sp\n.RS 4\n.nf\n cargo info serde@1.0.0\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Inspect the \\fBserde\\fR package form the local registry:\n.sp\n.RS 4\n.nf\n cargo info serde \\-\\-registry my\\-registry\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-search\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-init.1",
    "content": "'\\\" t\n.TH \"CARGO\\-INIT\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-init \\[em] Create a new Cargo package in an existing directory\n.SH \"SYNOPSIS\"\n\\fBcargo init\\fR [\\fIoptions\\fR] [\\fIpath\\fR]\n.SH \"DESCRIPTION\"\nThis command will create a new Cargo manifest in the current directory. Give a\npath as an argument to create in the given directory.\n.sp\nIf there are typically\\-named Rust source files already in the directory, those\nwill be used. If not, then a sample \\fBsrc/main.rs\\fR file will be created, or\n\\fBsrc/lib.rs\\fR if \\fB\\-\\-lib\\fR is passed.\n.sp\nIf the directory is not already in a VCS repository, then a new repository\nis created (see \\fB\\-\\-vcs\\fR below).\n.sp\nSee \\fBcargo\\-new\\fR(1) for a similar command which will create a new package in\na new directory.\n.SH \"OPTIONS\"\n.SS \"Init Options\"\n.sp\n\\fB\\-\\-bin\\fR\n.RS 4\nCreate a package with a binary target (\\fBsrc/main.rs\\fR).\nThis is the default behavior.\n.RE\n.sp\n\\fB\\-\\-lib\\fR\n.RS 4\nCreate a package with a library target (\\fBsrc/lib.rs\\fR).\n.RE\n.sp\n\\fB\\-\\-edition\\fR \\fIedition\\fR\n.RS 4\nSpecify the Rust edition to use. Default is 2024.\nPossible values: 2015, 2018, 2021, 2024\n.RE\n.sp\n\\fB\\-\\-name\\fR \\fIname\\fR\n.RS 4\nSet the package name. Defaults to the directory name.\n.RE\n.sp\n\\fB\\-\\-vcs\\fR \\fIvcs\\fR\n.RS 4\nInitialize a new VCS repository for the given version control system (git,\nhg, pijul, or fossil) or do not initialize any version control at all\n(none). If not specified, defaults to \\fBgit\\fR or the configuration value\n\\fBcargo\\-new.vcs\\fR, or \\fBnone\\fR if already inside a VCS repository.\n.RE\n.sp\n\\fB\\-\\-registry\\fR \\fIregistry\\fR\n.RS 4\nThis sets the \\fBpublish\\fR field in \\fBCargo.toml\\fR to the given registry name\nwhich will restrict publishing only to that registry.\n.sp\nRegistry names are defined in \\fICargo config files\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nIf not specified, the default registry defined by the \\fBregistry.default\\fR\nconfig key is used. If the default registry is not set and \\fB\\-\\-registry\\fR is not\nused, the \\fBpublish\\fR field will not be set which means that publishing will not\nbe restricted.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Create a binary Cargo package in the current directory:\n.sp\n.RS 4\n.nf\ncargo init\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-new\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-install.1",
    "content": "'\\\" t\n.TH \"CARGO\\-INSTALL\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-install \\[em] Build and install a Rust binary\n.SH \"SYNOPSIS\"\n\\fBcargo install\\fR [\\fIoptions\\fR] \\fIcrate\\fR[@\\fIversion\\fR]\\[u2026]\n.br\n\\fBcargo install\\fR [\\fIoptions\\fR] \\fB\\-\\-path\\fR \\fIpath\\fR\n.br\n\\fBcargo install\\fR [\\fIoptions\\fR] \\fB\\-\\-git\\fR \\fIurl\\fR [\\fIcrate\\fR\\[u2026]]\n.br\n\\fBcargo install\\fR [\\fIoptions\\fR] \\fB\\-\\-list\\fR\n.SH \"DESCRIPTION\"\nThis command manages Cargo\\[cq]s local set of installed binary crates. Only\npackages which have executable \\fB[[bin]]\\fR or \\fB[[example]]\\fR targets can be\ninstalled, and all executables are installed into the installation root\\[cq]s\n\\fBbin\\fR folder. By default only binaries, not examples, are installed.\n.sp\nThe installation root is determined, in order of precedence:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\\-\\-root\\fR option\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBCARGO_INSTALL_ROOT\\fR environment variable\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBinstall.root\\fR Cargo \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBCARGO_HOME\\fR environment variable\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB$HOME/.cargo\\fR\n.RE\n.sp\nThere are multiple sources from which a crate can be installed. The default\nsource location is crates.io but the \\fB\\-\\-git\\fR, \\fB\\-\\-path\\fR, and \\fB\\-\\-registry\\fR flags\ncan change this source. If the source contains more than one package (such as\ncrates.io or a git repository with multiple crates) the \\fIcrate\\fR argument is\nrequired to indicate which crate should be installed.\n.sp\nCrates from crates.io can optionally specify the version they wish to install\nvia the \\fB\\-\\-version\\fR flags, and similarly packages from git repositories can\noptionally specify the branch, tag, or revision that should be installed. If a\ncrate has multiple binaries, the \\fB\\-\\-bin\\fR argument can selectively install only\none of them, and if you\\[cq]d rather install examples the \\fB\\-\\-example\\fR argument can\nbe used as well.\n.sp\nIf the package is already installed, Cargo will reinstall it if the installed\nversion does not appear to be up\\-to\\-date. If any of the following values\nchange, then Cargo will reinstall the package:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The package version and source.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The set of binary names installed.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The chosen features.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The profile (\\fB\\-\\-profile\\fR).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The target (\\fB\\-\\-target\\fR).\n.RE\n.sp\nInstalling with \\fB\\-\\-path\\fR will always build and install, unless there are\nconflicting binaries from another package. The \\fB\\-\\-force\\fR flag may be used to\nforce Cargo to always reinstall the package.\n.sp\nIf the source is crates.io or \\fB\\-\\-git\\fR then by default the crate will be built\nin a temporary target directory. To avoid this, the target directory can be\nspecified by setting the \\fBCARGO_TARGET_DIR\\fR environment variable to a\npath. In particular, this can be useful for caching build artifacts on\ncontinuous integration systems.\n.SS \"Dealing with the Lockfile\"\nBy default, the \\fBCargo.lock\\fR file that is included with the package will be\nignored. This means that Cargo will recompute which versions of dependencies\nto use, possibly using newer versions that have been released since the\npackage was published. The \\fB\\-\\-locked\\fR flag can be used to force Cargo to use\nthe packaged \\fBCargo.lock\\fR file if it is available. This may be useful for\nensuring reproducible builds, to use the exact same set of dependencies that\nwere available when the package was published. It may also be useful if a\nnewer version of a dependency is published that no longer builds on your\nsystem, or has other problems. The downside to using \\fB\\-\\-locked\\fR is that you\nwill not receive any fixes or updates to any dependency. Note that Cargo did\nnot start publishing \\fBCargo.lock\\fR files until version 1.37, which means\npackages published with prior versions will not have a \\fBCargo.lock\\fR file\navailable.\n.SS \"Configuration Discovery\"\nThis command operates on system or user level, not project level.\nThis means that the local \\fIconfiguration discovery\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#hierarchical\\-structure> is ignored.\nInstead, the configuration discovery begins at \\fB$CARGO_HOME/config.toml\\fR\\&.\nIf the package is installed with \\fB\\-\\-path $PATH\\fR, the local configuration\nwill be used, beginning discovery at \\fB$PATH/.cargo/config.toml\\fR\\&.\n.SH \"OPTIONS\"\n.SS \"Install Options\"\n.sp\n\\fB\\-\\-vers\\fR \\fIversion\\fR, \n\\fB\\-\\-version\\fR \\fIversion\\fR\n.RS 4\nSpecify a version to install. This may be a \\fIversion\nrequirement\\fR <https://doc.rust\\-lang.org/cargo/reference/specifying\\-dependencies.html>, like \\fB~1.2\\fR, to have Cargo\nselect the newest version from the given requirement. If the version does not\nhave a requirement operator (such as \\fB^\\fR or \\fB~\\fR), then it must be in the form\n\\fIMAJOR.MINOR.PATCH\\fR, and will install exactly that version; it is \\fInot\\fR\ntreated as a caret requirement like Cargo dependencies are.\n.RE\n.sp\n\\fB\\-\\-git\\fR \\fIurl\\fR\n.RS 4\nGit URL to install the specified crate from.\n.RE\n.sp\n\\fB\\-\\-branch\\fR \\fIbranch\\fR\n.RS 4\nBranch to use when installing from git.\n.RE\n.sp\n\\fB\\-\\-tag\\fR \\fItag\\fR\n.RS 4\nTag to use when installing from git.\n.RE\n.sp\n\\fB\\-\\-rev\\fR \\fIsha\\fR\n.RS 4\nSpecific commit to use when installing from git.\n.RE\n.sp\n\\fB\\-\\-path\\fR \\fIpath\\fR\n.RS 4\nFilesystem path to local crate to install from.\n.RE\n.sp\n\\fB\\-\\-list\\fR\n.RS 4\nList all installed packages and their versions.\n.RE\n.sp\n\\fB\\-n\\fR, \n\\fB\\-\\-dry\\-run\\fR\n.RS 4\n(unstable) Perform all checks without installing.\n.RE\n.sp\n\\fB\\-f\\fR, \n\\fB\\-\\-force\\fR\n.RS 4\nForce overwriting existing crates or binaries. This can be used if a package\nhas installed a binary with the same name as another package. This is also\nuseful if something has changed on the system that you want to rebuild with,\nsuch as a newer version of \\fBrustc\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-no\\-track\\fR\n.RS 4\nBy default, Cargo keeps track of the installed packages with a metadata file\nstored in the installation root directory. This flag tells Cargo not to use or\ncreate that file. With this flag, Cargo will refuse to overwrite any existing\nfiles unless the \\fB\\-\\-force\\fR flag is used. This also disables Cargo\\[cq]s ability to\nprotect against multiple concurrent invocations of Cargo installing at the\nsame time.\n.RE\n.sp\n\\fB\\-\\-bin\\fR \\fIname\\fR\\[u2026]\n.RS 4\nInstall only the specified binary.\n.RE\n.sp\n\\fB\\-\\-bins\\fR\n.RS 4\nInstall all binaries. This is the default behavior.\n.RE\n.sp\n\\fB\\-\\-example\\fR \\fIname\\fR\\[u2026]\n.RS 4\nInstall only the specified example.\n.RE\n.sp\n\\fB\\-\\-examples\\fR\n.RS 4\nInstall all examples.\n.RE\n.sp\n\\fB\\-\\-root\\fR \\fIdir\\fR\n.RS 4\nDirectory to install packages into.\n.RE\n.sp\n\\fB\\-\\-registry\\fR \\fIregistry\\fR\n.RS 4\nName of the registry to use. Registry names are defined in \\fICargo config\nfiles\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. If not specified, the default registry is used,\nwhich is defined by the \\fBregistry.default\\fR config key which defaults to\n\\fBcrates\\-io\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-index\\fR \\fIindex\\fR\n.RS 4\nThe URL of the registry index to use.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Compilation Options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nInstall for the specified target architecture. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to a new temporary folder located in the\ntemporary directory of the platform.\n.sp\nWhen using \\fB\\-\\-path\\fR, by default it will use \\fBtarget\\fR directory in the workspace\nof the local crate unless \\fB\\-\\-target\\-dir\\fR\nis specified.\n.RE\n.sp\n\\fB\\-\\-debug\\fR\n.RS 4\nBuild with the \\fBdev\\fR profile instead of the \\fBrelease\\fR profile.\nSee also the \\fB\\-\\-profile\\fR option for choosing a specific profile by name.\n.RE\n.sp\n\\fB\\-\\-profile\\fR \\fIname\\fR\n.RS 4\nInstall with the given profile.\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/profiles.html> for more details on profiles.\n.RE\n.sp\n\\fB\\-\\-timings\\fR\n.RS 4\nOutput information how long each compilation takes, and track concurrency\ninformation over time.\n.sp\nA file \\fBcargo\\-timing.html\\fR will be written to the \\fBtarget/cargo\\-timings\\fR\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine\\-readable timing data.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Miscellaneous Options\"\n.sp\n\\fB\\-j\\fR \\fIN\\fR, \n\\fB\\-\\-jobs\\fR \\fIN\\fR\n.RS 4\nNumber of parallel jobs to run. May also be specified with the\n\\fBbuild.jobs\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string \\fBdefault\\fR is provided, it sets the value back to defaults.\nShould not be 0.\n.RE\n.sp\n\\fB\\-\\-keep\\-going\\fR\n.RS 4\nBuild as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.\n.sp\nFor example if the current package depends on dependencies \\fBfails\\fR and \\fBworks\\fR,\none of which fails to build, \\fBcargo install \\-j1\\fR may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas \\fBcargo install \\-j1 \\-\\-keep\\-going\\fR would definitely run both\nbuilds, even if the one run first fails.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-message\\-format\\fR \\fIfmt\\fR\n.RS 4\nThe output format for diagnostic messages. Can be specified multiple times\nand consists of comma\\-separated values. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBhuman\\fR (default): Display in a human\\-readable text format. Conflicts with\n\\fBshort\\fR and \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBshort\\fR: Emit shorter, human\\-readable text messages. Conflicts with \\fBhuman\\fR\nand \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR: Emit JSON messages to stdout. See\n\\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages>\nfor more details. Conflicts with \\fBhuman\\fR and \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-short\\fR: Ensure the \\fBrendered\\fR field of JSON messages contains\nthe \\[lq]short\\[rq] rendering from rustc. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-rendered\\-ansi\\fR: Ensure the \\fBrendered\\fR field of JSON messages\ncontains embedded ANSI color codes for respecting rustc\\[cq]s default color\nscheme. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-render\\-diagnostics\\fR: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo\\[cq]s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Install or upgrade a package from crates.io:\n.sp\n.RS 4\n.nf\ncargo install ripgrep\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Install or reinstall the package in the current directory:\n.sp\n.RS 4\n.nf\ncargo install \\-\\-path .\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'View the list of installed packages:\n.sp\n.RS 4\n.nf\ncargo install \\-\\-list\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-uninstall\\fR(1), \\fBcargo\\-search\\fR(1), \\fBcargo\\-publish\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-locate-project.1",
    "content": "'\\\" t\n.TH \"CARGO\\-LOCATE\\-PROJECT\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-locate\\-project \\[em] Print a JSON representation of a Cargo.toml file\\[cq]s location\n.SH \"SYNOPSIS\"\n\\fBcargo locate\\-project\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nThis command will print a JSON object to stdout with the full path to the manifest. The\nmanifest is found by searching upward for a file named \\fBCargo.toml\\fR starting from the current\nworking directory.\n.sp\nIf the project happens to be a part of a workspace, the manifest of the project, rather than\nthe workspace root, is output. This can be overridden by the \\fB\\-\\-workspace\\fR flag. The root\nworkspace is found by traversing further upward or by using the field \\fBpackage.workspace\\fR after\nlocating the manifest of a workspace member.\n.SH \"OPTIONS\"\n.sp\n\\fB\\-\\-workspace\\fR\n.RS 4\nLocate the \\fBCargo.toml\\fR at the root of the workspace, as opposed to the current\nworkspace member.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-\\-message\\-format\\fR \\fIfmt\\fR\n.RS 4\nThe representation in which to print the project location. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR (default): JSON object with the path under the key \\[lq]root\\[rq]\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBplain\\fR: Just the path.\n.RE\n.RE\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Display the path to the manifest based on the current directory:\n.sp\n.RS 4\n.nf\ncargo locate\\-project\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-metadata\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-login.1",
    "content": "'\\\" t\n.TH \"CARGO\\-LOGIN\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-login \\[em] Log in to a registry\n.SH \"SYNOPSIS\"\n\\fBcargo login\\fR [\\fIoptions\\fR] [\\fB\\-\\-\\fR \\fIargs\\fR]\n.SH \"DESCRIPTION\"\nThis command will run a credential provider to save a token so that commands\nthat require authentication, such as \\fBcargo\\-publish\\fR(1), will be\nautomatically authenticated.\n.sp\nAll the arguments following the two dashes (\\fB\\-\\-\\fR) are passed to the credential provider.\n.sp\nFor the default \\fBcargo:token\\fR credential provider, the token is saved\nin \\fB$CARGO_HOME/credentials.toml\\fR\\&. \\fBCARGO_HOME\\fR defaults to \\fB\\&.cargo\\fR\nin your home directory.\n.sp\nIf a registry has a credential\\-provider specified, it will be used. Otherwise,\nthe providers from the config value \\fBregistry.global\\-credential\\-providers\\fR will\nbe attempted, starting from the end of the list.\n.sp\nThe \\fItoken\\fR will be read from stdin.\n.sp\nThe API token for crates.io may be retrieved from <https://crates.io/me>\\&.\n.sp\nTake care to keep the token secret, it should not be shared with anyone else.\n.SH \"OPTIONS\"\n.SS \"Login Options\"\n.sp\n\\fB\\-\\-registry\\fR \\fIregistry\\fR\n.RS 4\nName of the registry to use. Registry names are defined in \\fICargo config\nfiles\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. If not specified, the default registry is used,\nwhich is defined by the \\fBregistry.default\\fR config key which defaults to\n\\fBcrates\\-io\\fR\\&.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Save the token for the default registry:\n.sp\n.RS 4\n.nf\ncargo login\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Save the token for a specific registry:\n.sp\n.RS 4\n.nf\ncargo login \\-\\-registry my\\-registry\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-logout\\fR(1), \\fBcargo\\-publish\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-logout.1",
    "content": "'\\\" t\n.TH \"CARGO\\-LOGOUT\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-logout \\[em] Remove an API token from the registry locally\n.SH \"SYNOPSIS\"\n\\fBcargo logout\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nThis command will run a credential provider to remove a saved token.\n.sp\nFor the default \\fBcargo:token\\fR credential provider, credentials are stored\nin \\fB$CARGO_HOME/credentials.toml\\fR where \\fB$CARGO_HOME\\fR defaults to \\fB\\&.cargo\\fR\nin your home directory.\n.sp\nIf a registry has a credential\\-provider specified, it will be used. Otherwise,\nthe providers from the config value \\fBregistry.global\\-credential\\-providers\\fR will\nbe attempted, starting from the end of the list.\n.sp\nIf \\fB\\-\\-registry\\fR is not specified, then the credentials for the default\nregistry will be removed (configured by\n\\fI\\f(BIregistry.default\\fI\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#registrydefault>, which defaults\nto <https://crates.io/>).\n.sp\nThis will not revoke the token on the server. If you need to revoke the token,\nvisit the registry website and follow its instructions (see\n<https://crates.io/me> to revoke the token for <https://crates.io/>).\n.SH \"OPTIONS\"\n.SS \"Logout Options\"\n.sp\n\\fB\\-\\-registry\\fR \\fIregistry\\fR\n.RS 4\nName of the registry to use. Registry names are defined in \\fICargo config\nfiles\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. If not specified, the default registry is used,\nwhich is defined by the \\fBregistry.default\\fR config key which defaults to\n\\fBcrates\\-io\\fR\\&.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Remove the default registry token:\n.sp\n.RS 4\n.nf\ncargo logout\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Remove the token for a specific registry:\n.sp\n.RS 4\n.nf\ncargo logout \\-\\-registry my\\-registry\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-login\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-metadata.1",
    "content": "'\\\" t\n.TH \"CARGO\\-METADATA\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-metadata \\[em] Machine\\-readable metadata about the current package\n.SH \"SYNOPSIS\"\n\\fBcargo metadata\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nOutput JSON to stdout containing information about the workspace members and\nresolved dependencies of the current package.\n.sp\nThe output format is subject to change in future versions of Cargo. It\nis recommended to include the \\fB\\-\\-format\\-version\\fR flag to future\\-proof your code\nand ensure the output is in the format you are expecting. For more on the\nexpectations, see \\[lq]Compatibility\\[rq]\\&.\n.sp\nSee the \\fIcargo_metadata crate\\fR <https://crates.io/crates/cargo_metadata>\nfor a Rust API for reading the metadata.\n.SH \"OUTPUT FORMAT\"\n.SS \"Compatibility\"\nWithin the same output format version, the compatibility is maintained, except\nsome scenarios. The following is a non\\-exhaustive list of changes that are not\nconsidered as incompatible:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBAdding new fields\\fR \\[em] New fields will be added when needed. Reserving this\nhelps Cargo evolve without bumping the format version too often.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBAdding new values for enum\\-like fields\\fR \\[em] Same as adding new fields. It\nkeeps metadata evolving without stagnation.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBChanging opaque representations\\fR \\[em] The inner representations of some\nfields are implementation details. For example, fields related to\n\\[lq]Source ID\\[rq] are treated as opaque identifiers to differentiate packages or\nsources. Consumers shouldn\\[cq]t rely on those representations unless specified.\n.RE\n.SS \"JSON format\"\nThe JSON output has the following format:\n.sp\n.RS 4\n.nf\n{\n    /* Array of all packages in the workspace.\n       It also includes all feature\\-enabled dependencies unless \\-\\-no\\-deps is used.\n    */\n    \"packages\": [\n        {\n            /* The name of the package. */\n            \"name\": \"my\\-package\",\n            /* The version of the package. */\n            \"version\": \"0.1.0\",\n            /* The Package ID for referring to the\n               package within the document and as the `\\-\\-package` argument to many commands\n            */\n            \"id\": \"file:///path/to/my\\-package#0.1.0\",\n            /* The license value from the manifest, or null. */\n            \"license\": \"MIT/Apache\\-2.0\",\n            /* The license\\-file value from the manifest, or null. */\n            \"license_file\": \"LICENSE\",\n            /* The description value from the manifest, or null. */\n            \"description\": \"Package description.\",\n            /* The source ID of the package, an \"opaque\" identifier representing\n               where a package is retrieved from. See \"Compatibility\" above for\n               the stability guarantee.\n\n               This is null for path dependencies and workspace members.\n\n               For other dependencies, it is a string with the format:\n               \\- \"registry+URL\" for registry\\-based dependencies.\n                 Example: \"registry+https://github.com/rust\\-lang/crates.io\\-index\"\n               \\- \"git+URL\" for git\\-based dependencies.\n                 Example: \"git+https://github.com/rust\\-lang/cargo?rev=5e85ba14aaa20f8133863373404cb0af69eeef2c#5e85ba14aaa20f8133863373404cb0af69eeef2c\"\n               \\- \"sparse+URL\" for dependencies from a sparse registry\n                 Example: \"sparse+https://my\\-sparse\\-registry.org\"\n\n               The value after the `+` is not explicitly defined, and may change\n               between versions of Cargo and may not directly correlate to other\n               things, such as registry definitions in a config file. New source\n               kinds may be added in the future which will have different `+`\n               prefixed identifiers.\n            */\n            \"source\": null,\n            /* Array of dependencies declared in the package's manifest. */\n            \"dependencies\": [\n                {\n                    /* The name of the dependency. */\n                    \"name\": \"bitflags\",\n                    /* The source ID of the dependency. May be null, see\n                       description for the package source.\n                    */\n                    \"source\": \"registry+https://github.com/rust\\-lang/crates.io\\-index\",\n                    /* The version requirement for the dependency.\n                       Dependencies without a version requirement have a value of \"*\".\n                    */\n                    \"req\": \"^1.0\",\n                    /* The dependency kind.\n                       \"dev\", \"build\", or null for a normal dependency.\n                    */\n                    \"kind\": null,\n                    /* If the dependency is renamed, this is the new name for\n                       the dependency as a string.  null if it is not renamed.\n                    */\n                    \"rename\": null,\n                    /* Boolean of whether or not this is an optional dependency. */\n                    \"optional\": false,\n                    /* Boolean of whether or not default features are enabled. */\n                    \"uses_default_features\": true,\n                    /* Array of features enabled. */\n                    \"features\": [],\n                    /* The target platform for the dependency.\n                       null if not a target dependency.\n                    */\n                    \"target\": \"cfg(windows)\",\n                    /* The file system path for a local path dependency.\n                       not present if not a path dependency.\n                    */\n                    \"path\": \"/path/to/dep\",\n                    /* A string of the URL of the registry this dependency is from.\n                       If not specified or null, the dependency is from the default\n                       registry (crates.io).\n                    */\n                    \"registry\": null,\n                    /* (unstable) Boolean flag of whether or not this is a pulbic\n                       dependency. This field is only present when\n                       `\\-Zpublic\\-dependency` is enabled.\n                    */\n                    \"public\": false\n                }\n            ],\n            /* Array of Cargo targets. */\n            \"targets\": [\n                {\n                    /* Array of target kinds.\n                       \\- lib targets list the `crate\\-type` values from the\n                         manifest such as \"lib\", \"rlib\", \"dylib\",\n                         \"proc\\-macro\", etc. (default [\"lib\"])\n                       \\- binary is [\"bin\"]\n                       \\- example is [\"example\"]\n                       \\- integration test is [\"test\"]\n                       \\- benchmark is [\"bench\"]\n                       \\- build script is [\"custom\\-build\"]\n                    */\n                    \"kind\": [\n                        \"bin\"\n                    ],\n                    /* Array of crate types.\n                       \\- lib and example libraries list the `crate\\-type` values\n                         from the manifest such as \"lib\", \"rlib\", \"dylib\",\n                         \"proc\\-macro\", etc. (default [\"lib\"])\n                       \\- all other target kinds are [\"bin\"]\n                    */\n                    \"crate_types\": [\n                        \"bin\"\n                    ],\n                    /* The name of the target.\n                       For lib targets, dashes will be replaced with underscores.\n                    */\n                    \"name\": \"my\\-package\",\n                    /* Absolute path to the root source file of the target. */\n                    \"src_path\": \"/path/to/my\\-package/src/main.rs\",\n                    /* The Rust edition of the target.\n                       Defaults to the package edition.\n                    */\n                    \"edition\": \"2018\",\n                    /* Array of required features.\n                       This property is not included if no required features are set.\n                    */\n                    \"required\\-features\": [\"feat1\"],\n                    /* Whether the target should be documented by `cargo doc`. */\n                    \"doc\": true,\n                    /* Whether or not this target has doc tests enabled, and\n                       the target is compatible with doc testing.\n                    */\n                    \"doctest\": false,\n                    /* Whether or not this target should be built and run with `\\-\\-test`\n                    */\n                    \"test\": true\n                }\n            ],\n            /* Set of features defined for the package.\n               Each feature maps to an array of features or dependencies it\n               enables.\n            */\n            \"features\": {\n                \"default\": [\n                    \"feat1\"\n                ],\n                \"feat1\": [],\n                \"feat2\": []\n            },\n            /* Absolute path to this package's manifest. */\n            \"manifest_path\": \"/path/to/my\\-package/Cargo.toml\",\n            /* Package metadata.\n               This is null if no metadata is specified.\n            */\n            \"metadata\": {\n                \"docs\": {\n                    \"rs\": {\n                        \"all\\-features\": true\n                    }\n                }\n            },\n            /* List of registries to which this package may be published.\n               Publishing is unrestricted if null, and forbidden if an empty array. */\n            \"publish\": [\n                \"crates\\-io\"\n            ],\n            /* Array of authors from the manifest.\n               Empty array if no authors specified.\n            */\n            \"authors\": [\n                \"Jane Doe <user@example.com>\"\n            ],\n            /* Array of categories from the manifest. */\n            \"categories\": [\n                \"command\\-line\\-utilities\"\n            ],\n            /* Optional string that is the default binary picked by cargo run. */\n            \"default_run\": null,\n            /* Optional string that is the minimum supported rust version */\n            \"rust_version\": \"1.56\",\n            /* Array of keywords from the manifest. */\n            \"keywords\": [\n                \"cli\"\n            ],\n            /* The readme value from the manifest or null if not specified. */\n            \"readme\": \"README.md\",\n            /* The repository value from the manifest or null if not specified. */\n            \"repository\": \"https://github.com/rust\\-lang/cargo\",\n            /* The homepage value from the manifest or null if not specified. */\n            \"homepage\": \"https://rust\\-lang.org\",\n            /* The documentation value from the manifest or null if not specified. */\n            \"documentation\": \"https://doc.rust\\-lang.org/stable/std\",\n            /* The default edition of the package.\n               Note that individual targets may have different editions.\n            */\n            \"edition\": \"2018\",\n            /* Optional string that is the name of a native library the package\n               is linking to.\n            */\n            \"links\": null,\n        }\n    ],\n    /* Array of members of the workspace.\n       Each entry is the Package ID for the package.\n    */\n    \"workspace_members\": [\n        \"file:///path/to/my\\-package#0.1.0\",\n    ],\n    /* Array of default members of the workspace.\n       Each entry is the Package ID for the package.\n    */\n    \"workspace_default_members\": [\n        \"file:///path/to/my\\-package#0.1.0\",\n    ],\n    // The resolved dependency graph for the entire workspace. The enabled\n    // features are based on the enabled features for the \"current\" package.\n    // Inactivated optional dependencies are not listed.\n    //\n    // This is null if \\-\\-no\\-deps is specified.\n    //\n    // By default, this includes all dependencies for all target platforms.\n    // The `\\-\\-filter\\-platform` flag may be used to narrow to a specific\n    // target triple.\n    \"resolve\": {\n        /* Array of nodes within the dependency graph.\n           Each node is a package.\n        */\n        \"nodes\": [\n            {\n                /* The Package ID of this node. */\n                \"id\": \"file:///path/to/my\\-package#0.1.0\",\n                /* The dependencies of this package, an array of Package IDs. */\n                \"dependencies\": [\n                    \"https://github.com/rust\\-lang/crates.io\\-index#bitflags@1.0.4\"\n                ],\n                /* The dependencies of this package. This is an alternative to\n                   \"dependencies\" which contains additional information. In\n                   particular, this handles renamed dependencies.\n                */\n                \"deps\": [\n                    {\n                        /* The name of the dependency's library target.\n                           If this is a renamed dependency, this is the new\n                           name.\n                        */\n                        \"name\": \"bitflags\",\n                        /* The Package ID of the dependency. */\n                        \"pkg\": \"https://github.com/rust\\-lang/crates.io\\-index#bitflags@1.0.4\"\n                        /* Array of dependency kinds. Added in Cargo 1.40. */\n                        \"dep_kinds\": [\n                            {\n                                /* The dependency kind.\n                                   \"dev\", \"build\", or null for a normal dependency.\n                                */\n                                \"kind\": null,\n                                /* The target platform for the dependency.\n                                   null if not a target dependency.\n                                */\n                                \"target\": \"cfg(windows)\"\n                            }\n                        ]\n                    }\n                ],\n                /* Array of features enabled on this package. */\n                \"features\": [\n                    \"default\"\n                ]\n            }\n        ],\n        /* The package in the current working directory (if \\-\\-manifest\\-path is not given).\n           This is null if there is a virtual workspace. Otherwise it is\n           the Package ID of the package.\n        */\n        \"root\": \"file:///path/to/my\\-package#0.1.0\",\n    },\n    /* The absolute path to the target directory where Cargo places its output. */\n    \"target_directory\": \"/path/to/my\\-package/target\",\n    /* The absolute path to the build directory where Cargo places intermediate build artifacts. (unstable) */\n    \"build_directory\": \"/path/to/my\\-package/build\\-dir\",\n    /* The version of the schema for this metadata structure.\n       This will be changed if incompatible changes are ever made.\n    */\n    \"version\": 1,\n    /* The absolute path to the root of the workspace. */\n    \"workspace_root\": \"/path/to/my\\-package\"\n    /* Workspace metadata.\n       This is null if no metadata is specified. */\n    \"metadata\": {\n        \"docs\": {\n            \"rs\": {\n                \"all\\-features\": true\n            }\n        }\n    }\n}\n.fi\n.RE\n.sp\nNotes:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'For \\fB\"id\"\\fR field syntax, see \\fIPackage ID Specifications\\fR <https://doc.rust\\-lang.org/cargo/reference/pkgid\\-spec.html> in the reference.\n.RE\n.SH \"OPTIONS\"\n.SS \"Output Options\"\n.sp\n\\fB\\-\\-no\\-deps\\fR\n.RS 4\nOutput information only about the workspace members and don\\[cq]t fetch\ndependencies.\n.RE\n.sp\n\\fB\\-\\-format\\-version\\fR \\fIversion\\fR\n.RS 4\nSpecify the version of the output format to use. Currently \\fB1\\fR is the only\npossible value.\n.RE\n.sp\n\\fB\\-\\-filter\\-platform\\fR \\fItriple\\fR\n.RS 4\nThis filters the \\fBresolve\\fR output to only include dependencies for the\ngiven \\fItarget triple\\fR <https://doc.rust\\-lang.org/cargo/appendix/glossary.html#target>\\&.\nA literal \\fB\"host\\-tuple\"\\fR can be used, which will internally be substituted by the host\\[cq]s target.\nWithout this flag, the resolve includes all targets.\n.sp\nNote that the dependencies listed in the \\[lq]packages\\[rq] array still includes all\ndependencies. Each package definition is intended to be an unaltered\nreproduction of the information within \\fBCargo.toml\\fR\\&.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Output JSON about the current package:\n.sp\n.RS 4\n.nf\ncargo metadata \\-\\-format\\-version=1\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-pkgid\\fR(1), \\fIPackage ID Specifications\\fR <https://doc.rust\\-lang.org/cargo/reference/pkgid\\-spec.html>, \\fIJSON messages\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages>\n"
  },
  {
    "path": "src/etc/man/cargo-new.1",
    "content": "'\\\" t\n.TH \"CARGO\\-NEW\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-new \\[em] Create a new Cargo package\n.SH \"SYNOPSIS\"\n\\fBcargo new\\fR [\\fIoptions\\fR] \\fIpath\\fR\n.SH \"DESCRIPTION\"\nThis command will create a new Cargo package in the given directory. This\nincludes a simple template with a \\fBCargo.toml\\fR manifest, sample source file,\nand a VCS ignore file. If the directory is not already in a VCS repository,\nthen a new repository is created (see \\fB\\-\\-vcs\\fR below).\n.sp\nSee \\fBcargo\\-init\\fR(1) for a similar command which will create a new manifest\nin an existing directory.\n.SH \"OPTIONS\"\n.SS \"New Options\"\n.sp\n\\fB\\-\\-bin\\fR\n.RS 4\nCreate a package with a binary target (\\fBsrc/main.rs\\fR).\nThis is the default behavior.\n.RE\n.sp\n\\fB\\-\\-lib\\fR\n.RS 4\nCreate a package with a library target (\\fBsrc/lib.rs\\fR).\n.RE\n.sp\n\\fB\\-\\-edition\\fR \\fIedition\\fR\n.RS 4\nSpecify the Rust edition to use. Default is 2024.\nPossible values: 2015, 2018, 2021, 2024\n.RE\n.sp\n\\fB\\-\\-name\\fR \\fIname\\fR\n.RS 4\nSet the package name. Defaults to the directory name.\n.RE\n.sp\n\\fB\\-\\-vcs\\fR \\fIvcs\\fR\n.RS 4\nInitialize a new VCS repository for the given version control system (git,\nhg, pijul, or fossil) or do not initialize any version control at all\n(none). If not specified, defaults to \\fBgit\\fR or the configuration value\n\\fBcargo\\-new.vcs\\fR, or \\fBnone\\fR if already inside a VCS repository.\n.RE\n.sp\n\\fB\\-\\-registry\\fR \\fIregistry\\fR\n.RS 4\nThis sets the \\fBpublish\\fR field in \\fBCargo.toml\\fR to the given registry name\nwhich will restrict publishing only to that registry.\n.sp\nRegistry names are defined in \\fICargo config files\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nIf not specified, the default registry defined by the \\fBregistry.default\\fR\nconfig key is used. If the default registry is not set and \\fB\\-\\-registry\\fR is not\nused, the \\fBpublish\\fR field will not be set which means that publishing will not\nbe restricted.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Create a binary Cargo package in the given directory:\n.sp\n.RS 4\n.nf\ncargo new foo\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-init\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-owner.1",
    "content": "'\\\" t\n.TH \"CARGO\\-OWNER\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-owner \\[em] Manage the owners of a crate on the registry\n.SH \"SYNOPSIS\"\n\\fBcargo owner\\fR [\\fIoptions\\fR] \\fB\\-\\-add\\fR \\fIlogin\\fR [\\fIcrate\\fR]\n.br\n\\fBcargo owner\\fR [\\fIoptions\\fR] \\fB\\-\\-remove\\fR \\fIlogin\\fR [\\fIcrate\\fR]\n.br\n\\fBcargo owner\\fR [\\fIoptions\\fR] \\fB\\-\\-list\\fR [\\fIcrate\\fR]\n.SH \"DESCRIPTION\"\nThis command will modify the owners for a crate on the registry. Owners of a\ncrate can upload new versions and yank old versions. Non\\-team owners can also\nmodify the set of owners, so take care!\n.sp\nThis command requires you to be authenticated with either the \\fB\\-\\-token\\fR option\nor using \\fBcargo\\-login\\fR(1).\n.sp\nIf the crate name is not specified, it will use the package name from the\ncurrent directory.\n.sp\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/publishing.html#cargo\\-owner> for more\ninformation about owners and publishing.\n.SH \"OPTIONS\"\n.SS \"Owner Options\"\n.sp\n\\fB\\-a\\fR, \n\\fB\\-\\-add\\fR \\fIlogin\\fR\\[u2026]\n.RS 4\nInvite the given user or team as an owner.\n.RE\n.sp\n\\fB\\-r\\fR, \n\\fB\\-\\-remove\\fR \\fIlogin\\fR\\[u2026]\n.RS 4\nRemove the given user or team as an owner.\n.RE\n.sp\n\\fB\\-l\\fR, \n\\fB\\-\\-list\\fR\n.RS 4\nList owners of a crate.\n.RE\n.sp\n\\fB\\-\\-token\\fR \\fItoken\\fR\n.RS 4\nAPI token to use when authenticating. This overrides the token stored in\nthe credentials file (which is created by \\fBcargo\\-login\\fR(1)).\n.sp\n\\fICargo config\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html> environment variables can be\nused to override the tokens stored in the credentials file. The token for\ncrates.io may be specified with the \\fBCARGO_REGISTRY_TOKEN\\fR environment\nvariable. Tokens for other registries may be specified with environment\nvariables of the form \\fBCARGO_REGISTRIES_NAME_TOKEN\\fR where \\fBNAME\\fR is the name\nof the registry in all capital letters.\n.RE\n.sp\n\\fB\\-\\-index\\fR \\fIindex\\fR\n.RS 4\nThe URL of the registry index to use.\n.RE\n.sp\n\\fB\\-\\-registry\\fR \\fIregistry\\fR\n.RS 4\nName of the registry to use. Registry names are defined in \\fICargo config\nfiles\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. If not specified, the default registry is used,\nwhich is defined by the \\fBregistry.default\\fR config key which defaults to\n\\fBcrates\\-io\\fR\\&.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'List owners of a package:\n.sp\n.RS 4\n.nf\ncargo owner \\-\\-list foo\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Invite an owner to a package:\n.sp\n.RS 4\n.nf\ncargo owner \\-\\-add username foo\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Remove an owner from a package:\n.sp\n.RS 4\n.nf\ncargo owner \\-\\-remove username foo\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-login\\fR(1), \\fBcargo\\-publish\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-package.1",
    "content": "'\\\" t\n.TH \"CARGO\\-PACKAGE\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-package \\[em] Assemble the local package into a distributable tarball\n.SH \"SYNOPSIS\"\n\\fBcargo package\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nThis command will create a distributable, compressed \\fB\\&.crate\\fR file with the\nsource code of the package in the current directory. The resulting file will be\nstored in the \\fBtarget/package\\fR directory. This performs the following steps:\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Load and check the current workspace, performing some basic checks.\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Path dependencies are not allowed unless they have a version key. Cargo\nwill ignore the path key for dependencies in published packages.\n\\fBdev\\-dependencies\\fR do not have this restriction.\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Create the compressed \\fB\\&.crate\\fR file.\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The original \\fBCargo.toml\\fR file is rewritten and normalized.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB[patch]\\fR, \\fB[replace]\\fR, and \\fB[workspace]\\fR sections are removed from the\nmanifest.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBCargo.lock\\fR is always included. When missing, a new lock file will be\ngenerated unless the \\fB\\-\\-exclude\\-lockfile\\fR flag is used. \\fBcargo\\-install\\fR(1)\nwill use the packaged lock file if the \\fB\\-\\-locked\\fR flag is used.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A \\fB\\&.cargo_vcs_info.json\\fR file is included that contains information\nabout the current VCS checkout hash if available, as well as a flag if the\nworktree is dirty.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Symlinks are flattened to their target files.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Files and directories are included or excluded based on rules mentioned in\n\\fIthe \\f(BI[include]\\fI and \\f(BI[exclude]\\fI fields\\fR <https://doc.rust\\-lang.org/cargo/reference/manifest.html#the\\-exclude\\-and\\-include\\-fields>\\&.\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Extract the \\fB\\&.crate\\fR file and build it to verify it can build.\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'This will rebuild your package from scratch to ensure that it can be\nbuilt from a pristine state. The \\fB\\-\\-no\\-verify\\fR flag can be used to skip\nthis step.\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 4.\\h'+01'Check that build scripts did not modify any source files.\n.RE\n.sp\nThe list of files included can be controlled with the \\fBinclude\\fR and \\fBexclude\\fR\nfields in the manifest.\n.sp\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/publishing.html> for more details about\npackaging and publishing.\n.SS \".cargo_vcs_info.json format\"\nWill generate a \\fB\\&.cargo_vcs_info.json\\fR in the following format\n.sp\n.RS 4\n.nf\n{\n \"git\": {\n   \"sha1\": \"aac20b6e7e543e6dd4118b246c77225e3a3a1302\",\n   \"dirty\": true\n },\n \"path_in_vcs\": \"\"\n}\n.fi\n.RE\n.sp\n\\fBdirty\\fR indicates that the Git worktree was dirty when the package\nwas built.\n.sp\n\\fBpath_in_vcs\\fR will be set to a repo\\-relative path for packages\nin subdirectories of the version control repository.\n.sp\nThe compatibility of this file is maintained under the same policy\nas the JSON output of \\fBcargo\\-metadata\\fR(1).\n.sp\nNote that this file provides a best\\-effort snapshot of the VCS information.\nHowever, the provenance of the package is not verified.\nThere is no guarantee that the source code in the tarball matches the VCS information.\n.SH \"OPTIONS\"\n.SS \"Package Options\"\n.sp\n\\fB\\-l\\fR, \n\\fB\\-\\-list\\fR\n.RS 4\nPrint files included in a package without making one.\n.RE\n.sp\n\\fB\\-\\-no\\-verify\\fR\n.RS 4\nDon\\[cq]t verify the contents by building them.\n.RE\n.sp\n\\fB\\-\\-no\\-metadata\\fR\n.RS 4\nIgnore warnings about a lack of human\\-usable metadata (such as the description\nor the license).\n.RE\n.sp\n\\fB\\-\\-allow\\-dirty\\fR\n.RS 4\nAllow working directories with uncommitted VCS changes to be packaged.\n.RE\n.sp\n\\fB\\-\\-exclude\\-lockfile\\fR\n.RS 4\nDon\\[cq]t include the lock file when packaging.\n.sp\nThis flag is not for general use.\nSome tools may expect a lock file to be present (e.g. \\fBcargo install \\-\\-locked\\fR).\nConsider other options before using this.\n.RE\n.sp\n\\fB\\-\\-index\\fR \\fIindex\\fR\n.RS 4\nThe URL of the registry index to use.\n.RE\n.sp\n\\fB\\-\\-registry\\fR \\fIregistry\\fR\n.RS 4\nName of the registry to package for; see \\fBcargo publish \\-\\-help\\fR for more details\nabout configuration of registry names. The packages will not be published\nto this registry, but if we are packaging multiple inter\\-dependent crates,\nlock\\-files will be generated under the assumption that dependencies will be\npublished to this registry.\n.RE\n.sp\n\\fB\\-\\-message\\-format\\fR \\fIfmt\\fR\n.RS 4\nSpecifies the output message format.\nCurrently, it only works with \\fB\\-\\-list\\fR and affects the file listing format.\nThis is unstable and requires \\fB\\-Zunstable\\-options\\fR\\&.\nValid output formats:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBhuman\\fR (default): Display in a file\\-per\\-line format.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR: Emit machine\\-readable JSON information about each package.\nOne package per JSON line (Newline delimited JSON).\n.sp\n.RS 4\n.nf\n{\n  /* The Package ID Spec of the package. */\n  \"id\": \"path+file:///home/foo#0.0.0\",\n  /* Files of this package */\n  \"files\" {\n    /* Relative path in the archive file. */\n    \"Cargo.toml.orig\": {\n      /* Where the file is from.\n         \\- \"generate\" for file being generated during packaging\n         \\- \"copy\" for file being copied from another location.\n      */\n      \"kind\": \"copy\",\n      /* For the \"copy\" kind,\n         it is an absolute path to the actual file content.\n         For the \"generate\" kind,\n         it is the original file the generated one is based on.\n      */\n      \"path\": \"/home/foo/Cargo.toml\"\n    },\n    \"Cargo.toml\": {\n      \"kind\": \"generate\",\n      \"path\": \"/home/foo/Cargo.toml\"\n    },\n    \"src/main.rs\": {\n      \"kind\": \"copy\",\n      \"path\": \"/home/foo/src/main.rs\"\n    }\n  }\n}\n.fi\n.RE\n.RE\n.RE\n.SS \"Package Selection\"\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n\\fB\\-\\-manifest\\-path\\fR is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n.sp\nThe default members of a workspace can be set explicitly with the\n\\fBworkspace.default\\-members\\fR key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n\\fB\\-\\-workspace\\fR), and a non\\-virtual workspace will include only the root crate itself.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR\\[u2026], \n\\fB\\-\\-package\\fR \\fIspec\\fR\\[u2026]\n.RS 4\nPackage only the specified packages. See \\fBcargo\\-pkgid\\fR(1) for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.\n.RE\n.sp\n\\fB\\-\\-workspace\\fR\n.RS 4\nPackage all members in the workspace.\n.RE\n.sp\n\\fB\\-\\-exclude\\fR \\fISPEC\\fR\\[u2026]\n.RS 4\nExclude the specified packages. Must be used in conjunction with the\n\\fB\\-\\-workspace\\fR flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.\n.RE\n.SS \"Compilation Options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nPackage for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to \\fBtarget\\fR in the root of the workspace.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Miscellaneous Options\"\n.sp\n\\fB\\-j\\fR \\fIN\\fR, \n\\fB\\-\\-jobs\\fR \\fIN\\fR\n.RS 4\nNumber of parallel jobs to run. May also be specified with the\n\\fBbuild.jobs\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string \\fBdefault\\fR is provided, it sets the value back to defaults.\nShould not be 0.\n.RE\n.sp\n\\fB\\-\\-keep\\-going\\fR\n.RS 4\nBuild as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.\n.sp\nFor example if the current package depends on dependencies \\fBfails\\fR and \\fBworks\\fR,\none of which fails to build, \\fBcargo package \\-j1\\fR may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas \\fBcargo package \\-j1 \\-\\-keep\\-going\\fR would definitely run both\nbuilds, even if the one run first fails.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Create a compressed \\fB\\&.crate\\fR file of the current package:\n.sp\n.RS 4\n.nf\ncargo package\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-publish\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-pkgid.1",
    "content": "'\\\" t\n.TH \"CARGO\\-PKGID\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-pkgid \\[em] Print a fully qualified package specification\n.SH \"SYNOPSIS\"\n\\fBcargo pkgid\\fR [\\fIoptions\\fR] [\\fIspec\\fR]\n.SH \"DESCRIPTION\"\nGiven a \\fIspec\\fR argument, print out the fully qualified package ID specifier\nfor a package or dependency in the current workspace. This command will\ngenerate an error if \\fIspec\\fR is ambiguous as to which package it refers to in\nthe dependency graph. If no \\fIspec\\fR is given, then the specifier for the local\npackage is printed.\n.sp\nThis command requires that a lockfile is available and dependencies have been\nfetched.\n.sp\nA package specifier consists of a name, version, and source URL. You are\nallowed to use partial specifiers to succinctly match a specific package as\nlong as it matches only one package. This specifier is also used by other parts\nin Cargo, such as \\fBcargo\\-metadata\\fR(1) and \\fIJSON messages\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages> emitted by Cargo.\n.sp\nThe format of a \\fIspec\\fR can be one of the following:\n\n.TS\nallbox tab(:);\nlt lt.\nT{\nSPEC Structure\nT}:T{\nExample SPEC\nT}\nT{\n\\fIname\\fR\nT}:T{\n\\fBbitflags\\fR\nT}\nT{\n\\fIname\\fR\\fB@\\fR\\fIversion\\fR\nT}:T{\n\\fBbitflags@1.0.4\\fR\nT}\nT{\n\\fIurl\\fR\nT}:T{\n\\fBhttps://github.com/rust\\-lang/cargo\\fR\nT}\nT{\n\\fIurl\\fR\\fB#\\fR\\fIversion\\fR\nT}:T{\n\\fBhttps://github.com/rust\\-lang/cargo#0.33.0\\fR\nT}\nT{\n\\fIurl\\fR\\fB#\\fR\\fIname\\fR\nT}:T{\n\\fBhttps://github.com/rust\\-lang/crates.io\\-index#bitflags\\fR\nT}\nT{\n\\fIurl\\fR\\fB#\\fR\\fIname\\fR\\fB@\\fR\\fIversion\\fR\nT}:T{\n\\fBhttps://github.com/rust\\-lang/cargo#crates\\-io@0.21.0\\fR\nT}\n.TE\n.sp\n.sp\nThe specification grammar can be found in chapter \\fIPackage ID Specifications\\fR <https://doc.rust\\-lang.org/cargo/reference/pkgid\\-spec.html>\\&.\n.SH \"OPTIONS\"\n.SS \"Package Selection\"\n.sp\n\\fB\\-p\\fR \\fIspec\\fR, \n\\fB\\-\\-package\\fR \\fIspec\\fR\n.RS 4\nGet the package ID for the given package instead of the current package.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Retrieve package specification for \\fBfoo\\fR package:\n.sp\n.RS 4\n.nf\ncargo pkgid foo\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Retrieve package specification for version 1.0.0 of \\fBfoo\\fR:\n.sp\n.RS 4\n.nf\ncargo pkgid foo@1.0.0\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Retrieve package specification for \\fBfoo\\fR from crates.io:\n.sp\n.RS 4\n.nf\ncargo pkgid https://github.com/rust\\-lang/crates.io\\-index#foo\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 4.\\h'+01'Retrieve package specification for \\fBfoo\\fR from a local package:\n.sp\n.RS 4\n.nf\ncargo pkgid file:///path/to/local/package#foo\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-generate\\-lockfile\\fR(1), \\fBcargo\\-metadata\\fR(1),\n\\fIPackage ID Specifications\\fR <https://doc.rust\\-lang.org/cargo/reference/pkgid\\-spec.html>, \\fIJSON messages\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages>\n"
  },
  {
    "path": "src/etc/man/cargo-publish.1",
    "content": "'\\\" t\n.TH \"CARGO\\-PUBLISH\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-publish \\[em] Upload a package to the registry\n.SH \"SYNOPSIS\"\n\\fBcargo publish\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nThis command will create a distributable, compressed \\fB\\&.crate\\fR file with the\nsource code of the package in the current directory and upload it to a\nregistry. The default registry is <https://crates.io>\\&. This performs the\nfollowing steps:\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Performs a few checks, including:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Checks the \\fBpackage.publish\\fR key in the manifest for restrictions on\nwhich registries you are allowed to publish to.\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Create a \\fB\\&.crate\\fR file by following the steps in \\fBcargo\\-package\\fR(1).\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Upload the crate to the registry. The server will perform additional\nchecks on the crate.\n.RE\n.sp\n.RS 4\n\\h'-04' 4.\\h'+01'The client will poll waiting for the package to appear in the index,\nand may timeout. In that case, you will need to check for completion\nmanually. This timeout does not affect the upload.\n.RE\n.sp\nThis command requires you to be authenticated using \\fBcargo\\-login\\fR(1)\nor environment variables of the \\fI\\f(BIregistry.token\\fI\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#registrytoken>\nand \\fI\\f(BIregistries.<name>.token\\fI\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#registriesnametoken> config fields.\n.sp\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/publishing.html> for more details about\npackaging and publishing.\n.SH \"OPTIONS\"\n.SS \"Publish Options\"\n.sp\n\\fB\\-\\-dry\\-run\\fR\n.RS 4\nPerform all checks without uploading.\n.RE\n.sp\n\\fB\\-\\-no\\-verify\\fR\n.RS 4\nDon\\[cq]t verify the contents by building them.\n.RE\n.sp\n\\fB\\-\\-allow\\-dirty\\fR\n.RS 4\nAllow working directories with uncommitted VCS changes to be packaged.\n.RE\n.sp\n\\fB\\-\\-index\\fR \\fIindex\\fR\n.RS 4\nThe URL of the registry index to use.\n.RE\n.sp\n\\fB\\-\\-registry\\fR \\fIregistry\\fR\n.RS 4\nName of the registry to publish to. Registry names are defined in \\fICargo\nconfig files\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. If not specified, and there is a\n\\fI\\f(BIpackage.publish\\fI\\fR <https://doc.rust\\-lang.org/cargo/reference/manifest.html#the\\-publish\\-field> field in\n\\fBCargo.toml\\fR with a single registry, then it will publish to that registry.\nOtherwise it will use the default registry, which is defined by the\n\\fI\\f(BIregistry.default\\fI\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#registrydefault> config key\nwhich defaults to \\fBcrates\\-io\\fR\\&.\n.RE\n.SS \"Package Selection\"\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n\\fB\\-\\-manifest\\-path\\fR is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n.sp\nThe default members of a workspace can be set explicitly with the\n\\fBworkspace.default\\-members\\fR key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n\\fB\\-\\-workspace\\fR), and a non\\-virtual workspace will include only the root crate itself.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR\\[u2026], \n\\fB\\-\\-package\\fR \\fIspec\\fR\\[u2026]\n.RS 4\nPublish only the specified packages. See \\fBcargo\\-pkgid\\fR(1) for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.\n.RE\n.sp\n\\fB\\-\\-workspace\\fR\n.RS 4\nPublish all members in the workspace.\n.RE\n.sp\n\\fB\\-\\-all\\fR\n.RS 4\nDeprecated alias for \\fB\\-\\-workspace\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-exclude\\fR \\fISPEC\\fR\\[u2026]\n.RS 4\nExclude the specified packages. Must be used in conjunction with the\n\\fB\\-\\-workspace\\fR flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.\n.RE\n.SS \"Compilation Options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nPublish for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to \\fBtarget\\fR in the root of the workspace.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Miscellaneous Options\"\n.sp\n\\fB\\-j\\fR \\fIN\\fR, \n\\fB\\-\\-jobs\\fR \\fIN\\fR\n.RS 4\nNumber of parallel jobs to run. May also be specified with the\n\\fBbuild.jobs\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string \\fBdefault\\fR is provided, it sets the value back to defaults.\nShould not be 0.\n.RE\n.sp\n\\fB\\-\\-keep\\-going\\fR\n.RS 4\nBuild as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.\n.sp\nFor example if the current package depends on dependencies \\fBfails\\fR and \\fBworks\\fR,\none of which fails to build, \\fBcargo publish \\-j1\\fR may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas \\fBcargo publish \\-j1 \\-\\-keep\\-going\\fR would definitely run both\nbuilds, even if the one run first fails.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Publish the current package:\n.sp\n.RS 4\n.nf\ncargo publish\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-package\\fR(1), \\fBcargo\\-login\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-remove.1",
    "content": "'\\\" t\n.TH \"CARGO\\-REMOVE\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-remove \\[em] Remove dependencies from a Cargo.toml manifest file\n.SH \"SYNOPSIS\"\n\\fBcargo remove\\fR [\\fIoptions\\fR] \\fIdependency\\fR\\[u2026]\n.SH \"DESCRIPTION\"\nRemove one or more dependencies from a \\fBCargo.toml\\fR manifest.\n.SH \"OPTIONS\"\n.SS \"Section options\"\n.sp\n\\fB\\-\\-dev\\fR\n.RS 4\nRemove as a \\fIdevelopment dependency\\fR <https://doc.rust\\-lang.org/cargo/reference/specifying\\-dependencies.html#development\\-dependencies>\\&.\n.RE\n.sp\n\\fB\\-\\-build\\fR\n.RS 4\nRemove as a \\fIbuild dependency\\fR <https://doc.rust\\-lang.org/cargo/reference/specifying\\-dependencies.html#build\\-dependencies>\\&.\n.RE\n.sp\n\\fB\\-\\-target\\fR \\fItarget\\fR\n.RS 4\nRemove as a dependency to the \\fIgiven target platform\\fR <https://doc.rust\\-lang.org/cargo/reference/specifying\\-dependencies.html#platform\\-specific\\-dependencies>\\&.\n.sp\nTo avoid unexpected shell expansions, you may use quotes around each target, e.g., \\fB\\-\\-target 'cfg(unix)'\\fR\\&.\n.RE\n.SS \"Miscellaneous Options\"\n.sp\n\\fB\\-\\-dry\\-run\\fR\n.RS 4\nDon\\[cq]t actually write to the manifest.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Package Selection\"\n.sp\n\\fB\\-p\\fR \\fIspec\\fR\\[u2026], \n\\fB\\-\\-package\\fR \\fIspec\\fR\\[u2026]\n.RS 4\nPackage to remove from.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Remove \\fBregex\\fR as a dependency\n.sp\n.RS 4\n.nf\ncargo remove regex\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Remove \\fBtrybuild\\fR as a dev\\-dependency\n.sp\n.RS 4\n.nf\ncargo remove \\-\\-dev trybuild\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Remove \\fBnom\\fR from the \\fBwasm32\\-unknown\\-unknown\\fR dependencies table\n.sp\n.RS 4\n.nf\ncargo remove \\-\\-target wasm32\\-unknown\\-unknown nom\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-add\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-report-future-incompatibilities.1",
    "content": "'\\\" t\n.TH \"CARGO\\-REPORT\\-FUTURE\\-INCOMPATIBILITIES\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-report\\-future\\-incompatibilities \\[em] Reports any crates which will eventually stop compiling\n.SH \"SYNOPSIS\"\n\\fBcargo report future\\-incompatibilities\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nDisplays a report of future\\-incompatible warnings that were emitted during\nprevious builds.\nThese are warnings for changes that may become hard errors in the future,\ncausing dependencies to stop building in a future version of rustc.\n.sp\nFor more, see the chapter on \\fIFuture incompat report\\fR <https://doc.rust\\-lang.org/cargo/reference/future\\-incompat\\-report.html>\\&.\n.SH \"OPTIONS\"\n.sp\n\\fB\\-\\-id\\fR \\fIid\\fR\n.RS 4\nShow the report with the specified Cargo\\-generated id.\nIf not specified, shows the most recent report.\n.RE\n.SS \"Package Selection\"\nBy default, the package in the current working directory is selected. The \\fB\\-p\\fR\nflag can be used to choose a different package in a workspace.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR, \n\\fB\\-\\-package\\fR \\fIspec\\fR\n.RS 4\nThe package to display a report for. See \\fBcargo\\-pkgid\\fR(1) for the SPEC\nformat.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Display the latest future\\-incompat report:\n.sp\n.RS 4\n.nf\ncargo report future\\-incompat\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Display the latest future\\-incompat report for a specific package:\n.sp\n.RS 4\n.nf\ncargo report future\\-incompat \\-\\-package my\\-dep@0.0.1\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-report\\fR(1), \\fBcargo\\-build\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-report.1",
    "content": "'\\\" t\n.TH \"CARGO\\-REPORT\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-report \\[em] Generate and display various kinds of reports\n.SH \"SYNOPSIS\"\n\\fBcargo report\\fR \\fItype\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nDisplays a report of the given \\fItype\\fR \\[em] currently, only \\fBfuture\\-incompat\\fR is supported\n.SH \"OPTIONS\"\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Display the available kinds of reports:\n.sp\n.RS 4\n.nf\ncargo report \\-\\-help\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-report\\-future\\-incompatibilities\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-run.1",
    "content": "'\\\" t\n.TH \"CARGO\\-RUN\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-run \\[em] Run the current package\n.SH \"SYNOPSIS\"\n\\fBcargo run\\fR [\\fIoptions\\fR] [\\fB\\-\\-\\fR \\fIargs\\fR]\n.SH \"DESCRIPTION\"\nRun a binary or example of the local package.\n.sp\nAll the arguments following the two dashes (\\fB\\-\\-\\fR) are passed to the binary to\nrun. If you\\[cq]re passing arguments to both Cargo and the binary, the ones after\n\\fB\\-\\-\\fR go to the binary, the ones before go to Cargo.\n.sp\nUnlike \\fBcargo\\-test\\fR(1) and \\fBcargo\\-bench\\fR(1), \\fBcargo run\\fR sets the\nworking directory of the binary executed to the current working directory, same\nas if it was executed in the shell directly.\n.SH \"OPTIONS\"\n.SS \"Package Selection\"\nBy default, the package in the current working directory is selected. The \\fB\\-p\\fR\nflag can be used to choose a different package in a workspace.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR, \n\\fB\\-\\-package\\fR \\fIspec\\fR\n.RS 4\nThe package to run. See \\fBcargo\\-pkgid\\fR(1) for the SPEC\nformat.\n.RE\n.SS \"Target Selection\"\nWhen no target selection options are given, \\fBcargo run\\fR will run the binary\ntarget. If there are multiple binary targets, you must pass a target flag to\nchoose one. Or, the \\fBdefault\\-run\\fR field may be specified in the \\fB[package]\\fR\nsection of \\fBCargo.toml\\fR to choose the name of the binary to run by default.\n.sp\n\\fB\\-\\-bin\\fR \\fIname\\fR\n.RS 4\nRun the specified binary.\n.RE\n.sp\n\\fB\\-\\-example\\fR \\fIname\\fR\n.RS 4\nRun the specified example.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Compilation Options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nRun for the specified target architecture. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.sp\n\\fB\\-r\\fR, \n\\fB\\-\\-release\\fR\n.RS 4\nRun optimized artifacts with the \\fBrelease\\fR profile.\nSee also the \\fB\\-\\-profile\\fR option for choosing a specific profile by name.\n.RE\n.sp\n\\fB\\-\\-profile\\fR \\fIname\\fR\n.RS 4\nRun with the given profile.\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/profiles.html> for more details on profiles.\n.RE\n.sp\n\\fB\\-\\-timings\\fR\n.RS 4\nOutput information how long each compilation takes, and track concurrency\ninformation over time.\n.sp\nA file \\fBcargo\\-timing.html\\fR will be written to the \\fBtarget/cargo\\-timings\\fR\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine\\-readable timing data.\n.RE\n.SS \"Output Options\"\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to \\fBtarget\\fR in the root of the workspace.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-message\\-format\\fR \\fIfmt\\fR\n.RS 4\nThe output format for diagnostic messages. Can be specified multiple times\nand consists of comma\\-separated values. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBhuman\\fR (default): Display in a human\\-readable text format. Conflicts with\n\\fBshort\\fR and \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBshort\\fR: Emit shorter, human\\-readable text messages. Conflicts with \\fBhuman\\fR\nand \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR: Emit JSON messages to stdout. See\n\\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages>\nfor more details. Conflicts with \\fBhuman\\fR and \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-short\\fR: Ensure the \\fBrendered\\fR field of JSON messages contains\nthe \\[lq]short\\[rq] rendering from rustc. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-rendered\\-ansi\\fR: Ensure the \\fBrendered\\fR field of JSON messages\ncontains embedded ANSI color codes for respecting rustc\\[cq]s default color\nscheme. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-render\\-diagnostics\\fR: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo\\[cq]s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SS \"Miscellaneous Options\"\n.sp\n\\fB\\-j\\fR \\fIN\\fR, \n\\fB\\-\\-jobs\\fR \\fIN\\fR\n.RS 4\nNumber of parallel jobs to run. May also be specified with the\n\\fBbuild.jobs\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string \\fBdefault\\fR is provided, it sets the value back to defaults.\nShould not be 0.\n.RE\n.sp\n\\fB\\-\\-keep\\-going\\fR\n.RS 4\nBuild as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.\n.sp\nFor example if the current package depends on dependencies \\fBfails\\fR and \\fBworks\\fR,\none of which fails to build, \\fBcargo run \\-j1\\fR may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas \\fBcargo run \\-j1 \\-\\-keep\\-going\\fR would definitely run both\nbuilds, even if the one run first fails.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Build the local package and run its main target (assuming only one binary):\n.sp\n.RS 4\n.nf\ncargo run\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Run an example with extra arguments:\n.sp\n.RS 4\n.nf\ncargo run \\-\\-example exname \\-\\- \\-\\-exoption exarg1 exarg2\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-build\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-rustc.1",
    "content": "'\\\" t\n.TH \"CARGO\\-RUSTC\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-rustc \\[em] Compile the current package, and pass extra options to the compiler\n.SH \"SYNOPSIS\"\n\\fBcargo rustc\\fR [\\fIoptions\\fR] [\\fB\\-\\-\\fR \\fIargs\\fR]\n.SH \"DESCRIPTION\"\nThe specified target for the current package (or package specified by \\fB\\-p\\fR if\nprovided) will be compiled along with all of its dependencies. The specified\n\\fIargs\\fR will all be passed to the final compiler invocation, not any of the\ndependencies. Note that the compiler will still unconditionally receive\narguments such as \\fB\\-L\\fR, \\fB\\-\\-extern\\fR, and \\fB\\-\\-crate\\-type\\fR, and the specified\n\\fIargs\\fR will simply be added to the compiler invocation.\n.sp\nSee <https://doc.rust\\-lang.org/rustc/index.html> for documentation on rustc\nflags.\n.sp\nThis command requires that only one target is being compiled when additional\narguments are provided. If more than one target is available for the current\npackage the filters of \\fB\\-\\-lib\\fR, \\fB\\-\\-bin\\fR, etc, must be used to select which\ntarget is compiled.\n.sp\nTo pass flags to all compiler processes spawned by Cargo, use the \\fBRUSTFLAGS\\fR\n\\fIenvironment variable\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> or the\n\\fBbuild.rustflags\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.SH \"OPTIONS\"\n.SS \"Package Selection\"\nBy default, the package in the current working directory is selected. The \\fB\\-p\\fR\nflag can be used to choose a different package in a workspace.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR, \n\\fB\\-\\-package\\fR \\fIspec\\fR\n.RS 4\nThe package to build. See \\fBcargo\\-pkgid\\fR(1) for the SPEC\nformat.\n.RE\n.SS \"Target Selection\"\nWhen no target selection options are given, \\fBcargo rustc\\fR will build all\nbinary and library targets of the selected package.\n.sp\nBinary targets are automatically built if there is an integration test or\nbenchmark being selected to build. This allows an integration\ntest to execute the binary to exercise and test its behavior.\nThe \\fBCARGO_BIN_EXE_<name>\\fR\n\\fIenvironment variable\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html#environment\\-variables\\-cargo\\-sets\\-for\\-crates>\nis set when the integration test is built and run so that it can use the\n\\fI\\f(BIenv\\fI macro\\fR <https://doc.rust\\-lang.org/std/macro.env.html> or the\n\\fI\\f(BIvar\\fI function\\fR <https://doc.rust\\-lang.org/std/env/fn.var.html> to locate the\nexecutable.\n.sp\nPassing target selection flags will build only the specified\ntargets.\n.sp\nNote that \\fB\\-\\-bin\\fR, \\fB\\-\\-example\\fR, \\fB\\-\\-test\\fR and \\fB\\-\\-bench\\fR flags also\nsupport common Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your\nshell accidentally expanding glob patterns before Cargo handles them, you must\nuse single quotes or double quotes around each glob pattern.\n.sp\n\\fB\\-\\-lib\\fR\n.RS 4\nBuild the package\\[cq]s library.\n.RE\n.sp\n\\fB\\-\\-bin\\fR \\fIname\\fR\\[u2026]\n.RS 4\nBuild the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-bins\\fR\n.RS 4\nBuild all binary targets.\n.RE\n.sp\n\\fB\\-\\-example\\fR \\fIname\\fR\\[u2026]\n.RS 4\nBuild the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-examples\\fR\n.RS 4\nBuild all example targets.\n.RE\n.sp\n\\fB\\-\\-test\\fR \\fIname\\fR\\[u2026]\n.RS 4\nBuild the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-tests\\fR\n.RS 4\nBuild all targets that have the \\fBtest = true\\fR manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the \\fBtest\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-bench\\fR \\fIname\\fR\\[u2026]\n.RS 4\nBuild the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-benches\\fR\n.RS 4\nBuild all targets that have the \\fBbench = true\\fR\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the \\fBbench\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-all\\-targets\\fR\n.RS 4\nBuild all targets. This is equivalent to specifying \\fB\\-\\-lib \\-\\-bins \\-\\-tests \\-\\-benches \\-\\-examples\\fR\\&.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Compilation Options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nBuild for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.sp\n\\fB\\-r\\fR, \n\\fB\\-\\-release\\fR\n.RS 4\nBuild optimized artifacts with the \\fBrelease\\fR profile.\nSee also the \\fB\\-\\-profile\\fR option for choosing a specific profile by name.\n.RE\n.sp\n\\fB\\-\\-profile\\fR \\fIname\\fR\n.RS 4\nBuild with the given profile.\n.sp\nThe \\fBrustc\\fR subcommand will treat the following named profiles with special behaviors:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBcheck\\fR \\[em] Builds in the same way as the \\fBcargo\\-check\\fR(1) command with\nthe \\fBdev\\fR profile.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBtest\\fR \\[em] Builds in the same way as the \\fBcargo\\-test\\fR(1) command,\nenabling building in test mode which will enable tests and enable the \\fBtest\\fR\ncfg option. See \\fIrustc\ntests\\fR <https://doc.rust\\-lang.org/rustc/tests/index.html> for more detail.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBbench\\fR \\[em] Builds in the same was as the \\fBcargo\\-bench\\fR(1) command,\nsimilar to the \\fBtest\\fR profile.\n.RE\n.sp\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/profiles.html> for more details on profiles.\n.RE\n.sp\n\\fB\\-\\-timings\\fR\n.RS 4\nOutput information how long each compilation takes, and track concurrency\ninformation over time.\n.sp\nA file \\fBcargo\\-timing.html\\fR will be written to the \\fBtarget/cargo\\-timings\\fR\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine\\-readable timing data.\n.RE\n.sp\n\\fB\\-\\-crate\\-type\\fR \\fIcrate\\-type\\fR\n.RS 4\nBuild for the given crate type. This flag accepts a comma\\-separated list of\n1 or more crate types, of which the allowed values are the same as \\fBcrate\\-type\\fR\nfield in the manifest for configuring a Cargo target. See\n\\fI\\f(BIcrate\\-type\\fI field\\fR <https://doc.rust\\-lang.org/cargo/reference/cargo\\-targets.html#the\\-crate\\-type\\-field>\nfor possible values.\n.sp\nIf the manifest contains a list, and \\fB\\-\\-crate\\-type\\fR is provided,\nthe command\\-line argument value will override what is in the manifest.\n.sp\nThis flag only works when building a \\fBlib\\fR or \\fBexample\\fR library target.\n.RE\n.SS \"Output Options\"\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to \\fBtarget\\fR in the root of the workspace.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-message\\-format\\fR \\fIfmt\\fR\n.RS 4\nThe output format for diagnostic messages. Can be specified multiple times\nand consists of comma\\-separated values. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBhuman\\fR (default): Display in a human\\-readable text format. Conflicts with\n\\fBshort\\fR and \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBshort\\fR: Emit shorter, human\\-readable text messages. Conflicts with \\fBhuman\\fR\nand \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR: Emit JSON messages to stdout. See\n\\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages>\nfor more details. Conflicts with \\fBhuman\\fR and \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-short\\fR: Ensure the \\fBrendered\\fR field of JSON messages contains\nthe \\[lq]short\\[rq] rendering from rustc. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-rendered\\-ansi\\fR: Ensure the \\fBrendered\\fR field of JSON messages\ncontains embedded ANSI color codes for respecting rustc\\[cq]s default color\nscheme. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-render\\-diagnostics\\fR: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo\\[cq]s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SS \"Miscellaneous Options\"\n.sp\n\\fB\\-j\\fR \\fIN\\fR, \n\\fB\\-\\-jobs\\fR \\fIN\\fR\n.RS 4\nNumber of parallel jobs to run. May also be specified with the\n\\fBbuild.jobs\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string \\fBdefault\\fR is provided, it sets the value back to defaults.\nShould not be 0.\n.RE\n.sp\n\\fB\\-\\-keep\\-going\\fR\n.RS 4\nBuild as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.\n.sp\nFor example if the current package depends on dependencies \\fBfails\\fR and \\fBworks\\fR,\none of which fails to build, \\fBcargo rustc \\-j1\\fR may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas \\fBcargo rustc \\-j1 \\-\\-keep\\-going\\fR would definitely run both\nbuilds, even if the one run first fails.\n.RE\n.sp\n\\fB\\-\\-future\\-incompat\\-report\\fR\n.RS 4\nDisplays a future\\-incompat report for any future\\-incompatible warnings\nproduced during execution of this command\n.sp\nSee \\fBcargo\\-report\\fR(1)\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Check if your package (not including dependencies) uses unsafe code:\n.sp\n.RS 4\n.nf\ncargo rustc \\-\\-lib \\-\\- \\-D unsafe\\-code\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Try an experimental flag on the nightly compiler, such as this which prints\nthe size of every type:\n.sp\n.RS 4\n.nf\ncargo rustc \\-\\-lib \\-\\- \\-Z print\\-type\\-sizes\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Override \\fBcrate\\-type\\fR field in Cargo.toml with command\\-line option:\n.sp\n.RS 4\n.nf\ncargo rustc \\-\\-lib \\-\\-crate\\-type lib,cdylib\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-build\\fR(1), \\fBrustc\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-rustdoc.1",
    "content": "'\\\" t\n.TH \"CARGO\\-RUSTDOC\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-rustdoc \\[em] Build a package\\[cq]s documentation, using specified custom flags\n.SH \"SYNOPSIS\"\n\\fBcargo rustdoc\\fR [\\fIoptions\\fR] [\\fB\\-\\-\\fR \\fIargs\\fR]\n.SH \"DESCRIPTION\"\nThe specified target for the current package (or package specified by \\fB\\-p\\fR if\nprovided) will be documented with the specified \\fIargs\\fR being passed to the\nfinal rustdoc invocation. Dependencies will not be documented as part of this\ncommand. Note that rustdoc will still unconditionally receive arguments such\nas \\fB\\-L\\fR, \\fB\\-\\-extern\\fR, and \\fB\\-\\-crate\\-type\\fR, and the specified \\fIargs\\fR will simply\nbe added to the rustdoc invocation.\n.sp\nSee <https://doc.rust\\-lang.org/rustdoc/index.html> for documentation on rustdoc\nflags.\n.sp\nThis command requires that only one target is being compiled when additional\narguments are provided. If more than one target is available for the current\npackage the filters of \\fB\\-\\-lib\\fR, \\fB\\-\\-bin\\fR, etc, must be used to select which\ntarget is compiled.\n.sp\nTo pass flags to all rustdoc processes spawned by Cargo, use the\n\\fBRUSTDOCFLAGS\\fR \\fIenvironment variable\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html>\nor the \\fBbuild.rustdocflags\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.SH \"OPTIONS\"\n.SS \"Documentation Options\"\n.sp\n\\fB\\-\\-open\\fR\n.RS 4\nOpen the docs in a browser after building them. This will use your default\nbrowser unless you define another one in the \\fBBROWSER\\fR environment variable\nor use the \\fI\\f(BIdoc.browser\\fI\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#docbrowser> configuration\noption.\n.RE\n.SS \"Package Selection\"\nBy default, the package in the current working directory is selected. The \\fB\\-p\\fR\nflag can be used to choose a different package in a workspace.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR, \n\\fB\\-\\-package\\fR \\fIspec\\fR\n.RS 4\nThe package to document. See \\fBcargo\\-pkgid\\fR(1) for the SPEC\nformat.\n.RE\n.SS \"Target Selection\"\nWhen no target selection options are given, \\fBcargo rustdoc\\fR will document all\nbinary and library targets of the selected package. The binary will be skipped\nif its name is the same as the lib target. Binaries are skipped if they have\n\\fBrequired\\-features\\fR that are missing.\n.sp\nPassing target selection flags will document only the specified\ntargets.\n.sp\nNote that \\fB\\-\\-bin\\fR, \\fB\\-\\-example\\fR, \\fB\\-\\-test\\fR and \\fB\\-\\-bench\\fR flags also\nsupport common Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your\nshell accidentally expanding glob patterns before Cargo handles them, you must\nuse single quotes or double quotes around each glob pattern.\n.sp\n\\fB\\-\\-lib\\fR\n.RS 4\nDocument the package\\[cq]s library.\n.RE\n.sp\n\\fB\\-\\-bin\\fR \\fIname\\fR\\[u2026]\n.RS 4\nDocument the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-bins\\fR\n.RS 4\nDocument all binary targets.\n.RE\n.sp\n\\fB\\-\\-example\\fR \\fIname\\fR\\[u2026]\n.RS 4\nDocument the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-examples\\fR\n.RS 4\nDocument all example targets.\n.RE\n.sp\n\\fB\\-\\-test\\fR \\fIname\\fR\\[u2026]\n.RS 4\nDocument the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-tests\\fR\n.RS 4\nDocument all targets that have the \\fBtest = true\\fR manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the \\fBtest\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-bench\\fR \\fIname\\fR\\[u2026]\n.RS 4\nDocument the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-benches\\fR\n.RS 4\nDocument all targets that have the \\fBbench = true\\fR\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the \\fBbench\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-all\\-targets\\fR\n.RS 4\nDocument all targets. This is equivalent to specifying \\fB\\-\\-lib \\-\\-bins \\-\\-tests \\-\\-benches \\-\\-examples\\fR\\&.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Compilation Options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nDocument for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.sp\n\\fB\\-r\\fR, \n\\fB\\-\\-release\\fR\n.RS 4\nDocument optimized artifacts with the \\fBrelease\\fR profile.\nSee also the \\fB\\-\\-profile\\fR option for choosing a specific profile by name.\n.RE\n.sp\n\\fB\\-\\-profile\\fR \\fIname\\fR\n.RS 4\nDocument with the given profile.\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/profiles.html> for more details on profiles.\n.RE\n.sp\n\\fB\\-\\-timings\\fR\n.RS 4\nOutput information how long each compilation takes, and track concurrency\ninformation over time.\n.sp\nA file \\fBcargo\\-timing.html\\fR will be written to the \\fBtarget/cargo\\-timings\\fR\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine\\-readable timing data.\n.RE\n.SS \"Output Options\"\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to \\fBtarget\\fR in the root of the workspace.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-message\\-format\\fR \\fIfmt\\fR\n.RS 4\nThe output format for diagnostic messages. Can be specified multiple times\nand consists of comma\\-separated values. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBhuman\\fR (default): Display in a human\\-readable text format. Conflicts with\n\\fBshort\\fR and \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBshort\\fR: Emit shorter, human\\-readable text messages. Conflicts with \\fBhuman\\fR\nand \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR: Emit JSON messages to stdout. See\n\\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages>\nfor more details. Conflicts with \\fBhuman\\fR and \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-short\\fR: Ensure the \\fBrendered\\fR field of JSON messages contains\nthe \\[lq]short\\[rq] rendering from rustc. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-rendered\\-ansi\\fR: Ensure the \\fBrendered\\fR field of JSON messages\ncontains embedded ANSI color codes for respecting rustc\\[cq]s default color\nscheme. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-render\\-diagnostics\\fR: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo\\[cq]s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SS \"Miscellaneous Options\"\n.sp\n\\fB\\-j\\fR \\fIN\\fR, \n\\fB\\-\\-jobs\\fR \\fIN\\fR\n.RS 4\nNumber of parallel jobs to run. May also be specified with the\n\\fBbuild.jobs\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string \\fBdefault\\fR is provided, it sets the value back to defaults.\nShould not be 0.\n.RE\n.sp\n\\fB\\-\\-keep\\-going\\fR\n.RS 4\nBuild as many crates in the dependency graph as possible, rather than aborting\nthe build on the first one that fails to build.\n.sp\nFor example if the current package depends on dependencies \\fBfails\\fR and \\fBworks\\fR,\none of which fails to build, \\fBcargo rustdoc \\-j1\\fR may or may not build the\none that succeeds (depending on which one of the two builds Cargo picked to run\nfirst), whereas \\fBcargo rustdoc \\-j1 \\-\\-keep\\-going\\fR would definitely run both\nbuilds, even if the one run first fails.\n.RE\n.sp\n\\fB\\-\\-output\\-format\\fR\n.RS 4\nThe output type for the documentation emitted. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBhtml\\fR (default): Emit the documentation in HTML format.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR: Emit the documentation in the \\fIexperimental JSON format\\fR <https://doc.rust\\-lang.org/nightly/nightly\\-rustc/rustdoc_json_types>\\&.\n.RE\n.sp\nThis option is only available on the \\fInightly channel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html>\nand requires the \\fB\\-Z unstable\\-options\\fR flag to enable.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Build documentation with custom CSS included from a given file:\n.sp\n.RS 4\n.nf\ncargo rustdoc \\-\\-lib \\-\\- \\-\\-extend\\-css extra.css\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-doc\\fR(1), \\fBrustdoc\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-search.1",
    "content": "'\\\" t\n.TH \"CARGO\\-SEARCH\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-search \\[em] Search packages in the registry. Default registry is crates.io\n.SH \"SYNOPSIS\"\n\\fBcargo search\\fR [\\fIoptions\\fR] [\\fIquery\\fR\\[u2026]]\n.SH \"DESCRIPTION\"\nThis performs a textual search for crates on <https://crates.io>\\&. The matching\ncrates will be displayed along with their description in TOML format suitable\nfor copying into a \\fBCargo.toml\\fR manifest.\n.SH \"OPTIONS\"\n.SS \"Search Options\"\n.sp\n\\fB\\-\\-limit\\fR \\fIlimit\\fR\n.RS 4\nLimit the number of results (default: 10, max: 100).\n.RE\n.sp\n\\fB\\-\\-index\\fR \\fIindex\\fR\n.RS 4\nThe URL of the registry index to use.\n.RE\n.sp\n\\fB\\-\\-registry\\fR \\fIregistry\\fR\n.RS 4\nName of the registry to use. Registry names are defined in \\fICargo config\nfiles\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. If not specified, the default registry is used,\nwhich is defined by the \\fBregistry.default\\fR config key which defaults to\n\\fBcrates\\-io\\fR\\&.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Search for a package from crates.io:\n.sp\n.RS 4\n.nf\ncargo search serde\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-install\\fR(1), \\fBcargo\\-publish\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-test.1",
    "content": "'\\\" t\n.TH \"CARGO\\-TEST\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-test \\[em] Execute unit and integration tests of a package\n.SH \"SYNOPSIS\"\n\\fBcargo test\\fR [\\fIoptions\\fR] [\\fItestname\\fR] [\\fB\\-\\-\\fR \\fItest\\-options\\fR]\n.SH \"DESCRIPTION\"\nCompile and execute unit, integration, and documentation tests.\n.sp\nThe test filtering argument \\fBTESTNAME\\fR and all the arguments following the two\ndashes (\\fB\\-\\-\\fR) are passed to the test binaries and thus to \\fIlibtest\\fR (rustc\\[cq]s\nbuilt in unit\\-test and micro\\-benchmarking framework).  If you\\[cq]re passing\narguments to both Cargo and the binary, the ones after \\fB\\-\\-\\fR go to the binary,\nthe ones before go to Cargo.  For details about libtest\\[cq]s arguments see the\noutput of \\fBcargo test \\-\\- \\-\\-help\\fR and check out the rustc book\\[cq]s chapter on\nhow tests work at <https://doc.rust\\-lang.org/rustc/tests/index.html>\\&.\n.sp\nAs an example, this will filter for tests with \\fBfoo\\fR in their name and run them\non 3 threads in parallel:\n.sp\n.RS 4\n.nf\ncargo test foo \\-\\- \\-\\-test\\-threads 3\n.fi\n.RE\n.sp\nTests are built with the \\fB\\-\\-test\\fR option to \\fBrustc\\fR which creates a special\nexecutable by linking your code with libtest. The executable automatically\nruns all functions annotated with the \\fB#[test]\\fR attribute in multiple threads.\n\\fB#[bench]\\fR annotated functions will also be run with one iteration to verify\nthat they are functional.\n.sp\nIf the package contains multiple test targets, each target compiles to a\nspecial executable as aforementioned, and then is run serially.\n.sp\nThe libtest harness may be disabled by setting \\fBharness = false\\fR in the target\nmanifest settings, in which case your code will need to provide its own \\fBmain\\fR\nfunction to handle running tests.\n.SS \"Documentation tests\"\nDocumentation tests are also run by default, which is handled by \\fBrustdoc\\fR\\&. It\nextracts code samples from documentation comments of the library target, and\nthen executes them.\n.sp\nDifferent from normal test targets, each code block compiles to a doctest\nexecutable on the fly with \\fBrustc\\fR\\&. These executables run in parallel in\nseparate processes. The compilation of a code block is in fact a part of test\nfunction controlled by libtest, so some options such as \\fB\\-\\-jobs\\fR might not\ntake effect. Note that this execution model of doctests is not guaranteed\nand may change in the future; beware of depending on it.\n.sp\nSee the \\fIrustdoc book\\fR <https://doc.rust\\-lang.org/rustdoc/> for more information\non writing doc tests.\n.SS \"Working directory of tests\"\nThe working directory when running each unit and integration test is set to the\nroot directory of the package the test belongs to.\nSetting the working directory of tests to the package\\[cq]s root directory makes it\npossible for tests to reliably access the package\\[cq]s files using relative paths,\nregardless from where \\fBcargo test\\fR was executed from.\n.sp\nFor documentation tests, the working directory when invoking \\fBrustdoc\\fR is set to\nthe workspace root directory, and is also the directory \\fBrustdoc\\fR uses as the\ncompilation directory of each documentation test.\nThe working directory when running each documentation test is set to the root\ndirectory of the package the test belongs to, and is controlled via \\fBrustdoc\\fR\\[cq]s\n\\fB\\-\\-test\\-run\\-directory\\fR option.\n.SH \"OPTIONS\"\n.SS \"Test Options\"\n.sp\n\\fB\\-\\-no\\-run\\fR\n.RS 4\nCompile, but don\\[cq]t run tests.\n.RE\n.sp\n\\fB\\-\\-no\\-fail\\-fast\\fR\n.RS 4\nRun all tests regardless of failure. Without this flag, Cargo will exit\nafter the first executable fails. The Rust test harness will run all tests\nwithin the executable to completion, this flag only applies to the executable\nas a whole.\n.RE\n.SS \"Package Selection\"\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n\\fB\\-\\-manifest\\-path\\fR is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n.sp\nThe default members of a workspace can be set explicitly with the\n\\fBworkspace.default\\-members\\fR key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n\\fB\\-\\-workspace\\fR), and a non\\-virtual workspace will include only the root crate itself.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR\\[u2026], \n\\fB\\-\\-package\\fR \\fIspec\\fR\\[u2026]\n.RS 4\nTest only the specified packages. See \\fBcargo\\-pkgid\\fR(1) for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.\n.RE\n.sp\n\\fB\\-\\-workspace\\fR\n.RS 4\nTest all members in the workspace.\n.RE\n.sp\n\\fB\\-\\-all\\fR\n.RS 4\nDeprecated alias for \\fB\\-\\-workspace\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-exclude\\fR \\fISPEC\\fR\\[u2026]\n.RS 4\nExclude the specified packages. Must be used in conjunction with the\n\\fB\\-\\-workspace\\fR flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.\n.RE\n.SS \"Target Selection\"\nWhen no target selection options are given, \\fBcargo test\\fR will build the\nfollowing targets of the selected packages:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'lib \\[em] used to link with binaries, examples, integration tests, and doc tests\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'bins (only if integration tests are built and required features are\navailable)\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'examples \\[em] to ensure they compile\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'lib as a unit test\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'bins as unit tests\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'integration tests\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'doc tests for the lib target\n.RE\n.sp\nThe default behavior can be changed by setting the \\fBtest\\fR flag for the target\nin the manifest settings. Setting examples to \\fBtest = true\\fR will build and run\nthe example as a test, replacing the example\\[cq]s \\fBmain\\fR function with the\nlibtest harness. If you don\\[cq]t want the \\fBmain\\fR function replaced, also include\n\\fBharness = false\\fR, in which case the example will be built and executed as\\-is.\n.sp\nSetting targets to \\fBtest = false\\fR will stop them from being tested by default.\nTarget selection options that take a target by name (such as \\fB\\-\\-example foo\\fR)\nignore the \\fBtest\\fR flag and will always test the given target.\n.sp\nDoc tests for libraries may be disabled by setting \\fBdoctest = false\\fR for the\nlibrary in the manifest.\n.sp\nSee \\fIConfiguring a target\\fR <https://doc.rust\\-lang.org/cargo/reference/cargo\\-targets.html#configuring\\-a\\-target>\nfor more information on per\\-target settings.\n.sp\nBinary targets are automatically built if there is an integration test or\nbenchmark being selected to test. This allows an integration\ntest to execute the binary to exercise and test its behavior.\nThe \\fBCARGO_BIN_EXE_<name>\\fR\n\\fIenvironment variable\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html#environment\\-variables\\-cargo\\-sets\\-for\\-crates>\nis set when the integration test is built and run so that it can use the\n\\fI\\f(BIenv\\fI macro\\fR <https://doc.rust\\-lang.org/std/macro.env.html> or the\n\\fI\\f(BIvar\\fI function\\fR <https://doc.rust\\-lang.org/std/env/fn.var.html> to locate the\nexecutable.\n.sp\nPassing target selection flags will test only the specified\ntargets.\n.sp\nNote that \\fB\\-\\-bin\\fR, \\fB\\-\\-example\\fR, \\fB\\-\\-test\\fR and \\fB\\-\\-bench\\fR flags also\nsupport common Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your\nshell accidentally expanding glob patterns before Cargo handles them, you must\nuse single quotes or double quotes around each glob pattern.\n.sp\n\\fB\\-\\-lib\\fR\n.RS 4\nTest the package\\[cq]s library.\n.RE\n.sp\n\\fB\\-\\-bin\\fR \\fIname\\fR\\[u2026]\n.RS 4\nTest the specified binary. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-bins\\fR\n.RS 4\nTest all binary targets.\n.RE\n.sp\n\\fB\\-\\-example\\fR \\fIname\\fR\\[u2026]\n.RS 4\nTest the specified example. This flag may be specified multiple times\nand supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-examples\\fR\n.RS 4\nTest all example targets.\n.RE\n.sp\n\\fB\\-\\-test\\fR \\fIname\\fR\\[u2026]\n.RS 4\nTest the specified integration test. This flag may be specified\nmultiple times and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-tests\\fR\n.RS 4\nTest all targets that have the \\fBtest = true\\fR manifest\nflag set. By default this includes the library and binaries built as\nunittests, and integration tests. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nunittest, and once as a dependency for binaries, integration tests, etc.).\nTargets may be enabled or disabled by setting the \\fBtest\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-bench\\fR \\fIname\\fR\\[u2026]\n.RS 4\nTest the specified benchmark. This flag may be specified multiple\ntimes and supports common Unix glob patterns.\n.RE\n.sp\n\\fB\\-\\-benches\\fR\n.RS 4\nTest all targets that have the \\fBbench = true\\fR\nmanifest flag set. By default this includes the library and binaries built\nas benchmarks, and bench targets. Be aware that this will also build any\nrequired dependencies, so the lib target may be built twice (once as a\nbenchmark, and once as a dependency for binaries, benchmarks, etc.).\nTargets may be enabled or disabled by setting the \\fBbench\\fR flag in the\nmanifest settings for the target.\n.RE\n.sp\n\\fB\\-\\-all\\-targets\\fR\n.RS 4\nTest all targets. This is equivalent to specifying \\fB\\-\\-lib \\-\\-bins \\-\\-tests \\-\\-benches \\-\\-examples\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-doc\\fR\n.RS 4\nTest only the library\\[cq]s documentation. This cannot be mixed with other\ntarget options.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Compilation Options\"\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nTest for the specified target architecture. Flag may be specified multiple times. The default is the host architecture. The general format of the triple is\n\\fB<arch><sub>\\-<vendor>\\-<sys>\\-<abi>\\fR\\&.\n.sp\nPossible values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Any supported target in \\fBrustc \\-\\-print target\\-list\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\"host\\-tuple\"\\fR, which will internally be substituted by the host\\[cq]s target. This can be particularly useful if you\\[cq]re cross\\-compiling some crates, and don\\[cq]t want to specify your host\\[cq]s machine as a target (for instance, an \\fBxtask\\fR in a shared project that may be worked on by many hosts).\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A path to a custom target specification. See \\fICustom Target Lookup Path\\fR <https://doc.rust\\-lang.org/rustc/targets/custom.html#custom\\-target\\-lookup\\-path> for more information.\n.RE\n.sp\nThis may also be specified with the \\fBbuild.target\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.sp\nNote that specifying this flag makes Cargo run in a different mode where the\ntarget artifacts are placed in a separate directory. See the\n\\fIbuild cache\\fR <https://doc.rust\\-lang.org/cargo/reference/build\\-cache.html> documentation for more details.\n.RE\n.sp\n\\fB\\-r\\fR, \n\\fB\\-\\-release\\fR\n.RS 4\nTest optimized artifacts with the \\fBrelease\\fR profile.\nSee also the \\fB\\-\\-profile\\fR option for choosing a specific profile by name.\n.RE\n.sp\n\\fB\\-\\-profile\\fR \\fIname\\fR\n.RS 4\nTest with the given profile.\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/profiles.html> for more details on profiles.\n.RE\n.sp\n\\fB\\-\\-timings\\fR\n.RS 4\nOutput information how long each compilation takes, and track concurrency\ninformation over time.\n.sp\nA file \\fBcargo\\-timing.html\\fR will be written to the \\fBtarget/cargo\\-timings\\fR\ndirectory at the end of the build. An additional report with a timestamp\nin its filename is also written if you want to look at a previous run.\nThese reports are suitable for human consumption only, and do not provide\nmachine\\-readable timing data.\n.RE\n.SS \"Output Options\"\n.sp\n\\fB\\-\\-target\\-dir\\fR \\fIdirectory\\fR\n.RS 4\nDirectory for all generated artifacts and intermediate files. May also be\nspecified with the \\fBCARGO_TARGET_DIR\\fR environment variable, or the\n\\fBbuild.target\\-dir\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\nDefaults to \\fBtarget\\fR in the root of the workspace.\n.RE\n.SS \"Display Options\"\nBy default the Rust test harness hides output from test execution to keep\nresults readable. Test output can be recovered (e.g., for debugging) by passing\n\\fB\\-\\-no\\-capture\\fR to the test binaries:\n.sp\n.RS 4\n.nf\ncargo test \\-\\- \\-\\-no\\-capture\n.fi\n.RE\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-message\\-format\\fR \\fIfmt\\fR\n.RS 4\nThe output format for diagnostic messages. Can be specified multiple times\nand consists of comma\\-separated values. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBhuman\\fR (default): Display in a human\\-readable text format. Conflicts with\n\\fBshort\\fR and \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBshort\\fR: Emit shorter, human\\-readable text messages. Conflicts with \\fBhuman\\fR\nand \\fBjson\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\fR: Emit JSON messages to stdout. See\n\\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#json\\-messages>\nfor more details. Conflicts with \\fBhuman\\fR and \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-short\\fR: Ensure the \\fBrendered\\fR field of JSON messages contains\nthe \\[lq]short\\[rq] rendering from rustc. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-diagnostic\\-rendered\\-ansi\\fR: Ensure the \\fBrendered\\fR field of JSON messages\ncontains embedded ANSI color codes for respecting rustc\\[cq]s default color\nscheme. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBjson\\-render\\-diagnostics\\fR: Instruct Cargo to not include rustc diagnostics\nin JSON messages printed, but instead Cargo itself should render the\nJSON diagnostics coming from rustc. Cargo\\[cq]s own JSON diagnostics and others\ncoming from rustc are still emitted. Cannot be used with \\fBhuman\\fR or \\fBshort\\fR\\&.\n.RE\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SS \"Miscellaneous Options\"\nThe \\fB\\-\\-jobs\\fR argument affects the building of the test executable but does not\naffect how many threads are used when running the tests. The Rust test harness\nincludes an option to control the number of threads used:\n.sp\n.RS 4\n.nf\ncargo test \\-j 2 \\-\\- \\-\\-test\\-threads=2\n.fi\n.RE\n.sp\n\\fB\\-j\\fR \\fIN\\fR, \n\\fB\\-\\-jobs\\fR \\fIN\\fR\n.RS 4\nNumber of parallel jobs to run. May also be specified with the\n\\fBbuild.jobs\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. Defaults to\nthe number of logical CPUs. If negative, it sets the maximum number of\nparallel jobs to the number of logical CPUs plus provided value. If\na string \\fBdefault\\fR is provided, it sets the value back to defaults.\nShould not be 0.\n.RE\n.sp\n\\fB\\-\\-future\\-incompat\\-report\\fR\n.RS 4\nDisplays a future\\-incompat report for any future\\-incompatible warnings\nproduced during execution of this command\n.sp\nSee \\fBcargo\\-report\\fR(1)\n.RE\n.sp\nWhile \\fBcargo test\\fR involves compilation, it does not provide a \\fB\\-\\-keep\\-going\\fR\nflag. Use \\fB\\-\\-no\\-fail\\-fast\\fR to run as many tests as possible without stopping at\nthe first failure. To \\[lq]compile\\[rq] as many tests as possible, use \\fB\\-\\-tests\\fR to\nbuild test binaries separately. For example:\n.sp\n.RS 4\n.nf\ncargo build \\-\\-tests \\-\\-keep\\-going\ncargo test \\-\\-tests \\-\\-no\\-fail\\-fast\n.fi\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Execute all the unit and integration tests of the current package:\n.sp\n.RS 4\n.nf\ncargo test\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Run only tests whose names match against a filter string:\n.sp\n.RS 4\n.nf\ncargo test name_filter\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Run only a specific test within a specific integration test:\n.sp\n.RS 4\n.nf\ncargo test \\-\\-test int_test_name \\-\\- modname::test_name\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-bench\\fR(1), \\fItypes of tests\\fR <https://doc.rust\\-lang.org/cargo/reference/cargo\\-targets.html#tests>, \\fIhow to write tests\\fR <https://doc.rust\\-lang.org/rustc/tests/index.html>\n"
  },
  {
    "path": "src/etc/man/cargo-tree.1",
    "content": "'\\\" t\n.TH \"CARGO\\-TREE\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-tree \\[em] Display a tree visualization of a dependency graph\n.SH \"SYNOPSIS\"\n\\fBcargo tree\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nThis command will display a tree of dependencies to the terminal. An example\nof a simple project that depends on the \\[lq]rand\\[rq] package:\n.sp\n.RS 4\n.nf\nmyproject v0.1.0 (/myproject)\n`\\-\\- rand v0.7.3\n    |\\-\\- getrandom v0.1.14\n    |   |\\-\\- cfg\\-if v0.1.10\n    |   `\\-\\- libc v0.2.68\n    |\\-\\- libc v0.2.68 (*)\n    |\\-\\- rand_chacha v0.2.2\n    |   |\\-\\- ppv\\-lite86 v0.2.6\n    |   `\\-\\- rand_core v0.5.1\n    |       `\\-\\- getrandom v0.1.14 (*)\n    `\\-\\- rand_core v0.5.1 (*)\n[build\\-dependencies]\n`\\-\\- cc v1.0.50\n.fi\n.RE\n.sp\nPackages marked with \\fB(*)\\fR have been \\[lq]de\\-duplicated\\[rq]\\&. The dependencies for the\npackage have already been shown elsewhere in the graph, and so are not\nrepeated. Use the \\fB\\-\\-no\\-dedupe\\fR option to repeat the duplicates.\n.sp\nThe \\fB\\-e\\fR flag can be used to select the dependency kinds to display. The\n\\[lq]features\\[rq] kind changes the output to display the features enabled by\neach dependency. For example, \\fBcargo tree \\-e features\\fR:\n.sp\n.RS 4\n.nf\nmyproject v0.1.0 (/myproject)\n`\\-\\- log feature \"serde\"\n    `\\-\\- log v0.4.8\n        |\\-\\- serde v1.0.106\n        `\\-\\- cfg\\-if feature \"default\"\n            `\\-\\- cfg\\-if v0.1.10\n.fi\n.RE\n.sp\nIn this tree, \\fBmyproject\\fR depends on \\fBlog\\fR with the \\fBserde\\fR feature. \\fBlog\\fR in\nturn depends on \\fBcfg\\-if\\fR with \\[lq]default\\[rq] features. When using \\fB\\-e features\\fR it\ncan be helpful to use \\fB\\-i\\fR flag to show how the features flow into a package.\nSee the examples below for more detail.\n.SS \"Feature Unification\"\nThis command shows a graph much closer to a feature\\-unified graph Cargo will\nbuild, rather than what you list in \\fBCargo.toml\\fR\\&. For instance, if you specify\nthe same dependency in both \\fB[dependencies]\\fR and \\fB[dev\\-dependencies]\\fR but with\ndifferent features on. This command may merge all features and show a \\fB(*)\\fR on\none of the dependency to indicate the duplicate.\n.sp\nAs a result, for a mostly equivalent overview of what \\fBcargo build\\fR does,\n\\fBcargo tree \\-e normal,build\\fR is pretty close; for a mostly equivalent overview\nof what \\fBcargo test\\fR does, \\fBcargo tree\\fR is pretty close. However, it doesn\\[cq]t\nguarantee the exact equivalence to what Cargo is going to build, since a\ncompilation is complex and depends on lots of different factors.\n.sp\nTo learn more about feature unification, check out this\n\\fIdedicated section\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#feature\\-unification>\\&.\n.SH \"OPTIONS\"\n.SS \"Tree Options\"\n.sp\n\\fB\\-i\\fR \\fIspec\\fR, \n\\fB\\-\\-invert\\fR \\fIspec\\fR\n.RS 4\nShow the reverse dependencies for the given package. This flag will invert\nthe tree and display the packages that depend on the given package.\n.sp\nNote that in a workspace, by default it will only display the package\\[cq]s\nreverse dependencies inside the tree of the workspace member in the current\ndirectory. The \\fB\\-\\-workspace\\fR flag can be used to extend it so that it will\nshow the package\\[cq]s reverse dependencies across the entire workspace. The \\fB\\-p\\fR\nflag can be used to display the package\\[cq]s reverse dependencies only with the\nsubtree of the package given to \\fB\\-p\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-prune\\fR \\fIspec\\fR\n.RS 4\nPrune the given package from the display of the dependency tree.\n.RE\n.sp\n\\fB\\-\\-depth\\fR \\fIdepth\\fR\n.RS 4\nMaximum display depth of the dependency tree. A depth of 1 displays the direct\ndependencies, for example.\n.sp\nIf the given value is \\fBworkspace\\fR, only shows the dependencies that are member\nof the current workspace, instead.\n.RE\n.sp\n\\fB\\-\\-no\\-dedupe\\fR\n.RS 4\nDo not de\\-duplicate repeated dependencies. Usually, when a package has already\ndisplayed its dependencies, further occurrences will not re\\-display its\ndependencies, and will include a \\fB(*)\\fR to indicate it has already been shown.\nThis flag will cause those duplicates to be repeated.\n.RE\n.sp\n\\fB\\-d\\fR, \n\\fB\\-\\-duplicates\\fR\n.RS 4\nShow only dependencies which come in multiple versions (implies \\fB\\-\\-invert\\fR).\nWhen used with the \\fB\\-p\\fR flag, only shows duplicates within the subtree of the\ngiven package.\n.sp\nIt can be beneficial for build times and executable sizes to avoid building\nthat same package multiple times. This flag can help identify the offending\npackages. You can then investigate if the package that depends on the\nduplicate with the older version can be updated to the newer version so that\nonly one instance is built.\n.RE\n.sp\n\\fB\\-e\\fR \\fIkinds\\fR, \n\\fB\\-\\-edges\\fR \\fIkinds\\fR\n.RS 4\nThe dependency kinds to display. Takes a comma separated list of values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBall\\fR \\[em] Show all edge kinds.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnormal\\fR \\[em] Show normal dependencies.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBbuild\\fR \\[em] Show build dependencies.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBdev\\fR \\[em] Show development dependencies.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBfeatures\\fR \\[em] Show features enabled by each dependency. If this is the only\nkind given, then it will automatically include the other dependency kinds.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBno\\-normal\\fR \\[em] Do not include normal dependencies.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBno\\-build\\fR \\[em] Do not include build dependencies.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBno\\-dev\\fR \\[em] Do not include development dependencies.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBno\\-proc\\-macro\\fR \\[em] Do not include procedural macro dependencies.\n.RE\n.sp\nThe \\fBnormal\\fR, \\fBbuild\\fR, \\fBdev\\fR, and \\fBall\\fR dependency kinds cannot be mixed with\n\\fBno\\-normal\\fR, \\fBno\\-build\\fR, or \\fBno\\-dev\\fR dependency kinds.\n.sp\nThe default is \\fBnormal,build,dev\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-target\\fR \\fItriple\\fR\n.RS 4\nFilter dependencies matching the given \\fItarget triple\\fR <https://doc.rust\\-lang.org/cargo/appendix/glossary.html#target>\\&.\nThe default is the host platform. Use the value \\fBall\\fR to include \\fIall\\fR targets.\n.RE\n.SS \"Tree Formatting Options\"\n.sp\n\\fB\\-\\-charset\\fR \\fIcharset\\fR\n.RS 4\nChooses the character set to use for the tree. Valid values are \\[lq]utf8\\[rq] or\n\\[lq]ascii\\[rq]\\&. When unspecified, cargo will auto\\-select a value.\n.RE\n.sp\n\\fB\\-f\\fR \\fIformat\\fR, \n\\fB\\-\\-format\\fR \\fIformat\\fR\n.RS 4\nSet the format string for each package. The default is \\[lq]{p}\\[rq]\\&.\n.sp\nThis is an arbitrary string which will be used to display each package. The following\nstrings will be replaced with the corresponding value:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB{p}\\fR, \\fB{package}\\fR \\[em] The package name.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB{l}\\fR, \\fB{license}\\fR \\[em] The package license.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB{r}\\fR, \\fB{repository}\\fR \\[em] The package repository URL.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB{f}\\fR, \\fB{features}\\fR \\[em] Comma\\-separated list of package features that are enabled.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB{lib}\\fR \\[em] The name, as used in a \\fBuse\\fR statement, of the package\\[cq]s library.\n.RE\n.RE\n.sp\n\\fB\\-\\-prefix\\fR \\fIprefix\\fR\n.RS 4\nSets how each line is displayed. The \\fIprefix\\fR value can be one of:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBindent\\fR (default) \\[em] Shows each line indented as a tree.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBdepth\\fR \\[em] Show as a list, with the numeric depth printed before each entry.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnone\\fR \\[em] Show as a flat list.\n.RE\n.RE\n.SS \"Package Selection\"\nBy default, when no package selection options are given, the packages selected\ndepend on the selected manifest file (based on the current working directory if\n\\fB\\-\\-manifest\\-path\\fR is not given). If the manifest is the root of a workspace then\nthe workspaces default members are selected, otherwise only the package defined\nby the manifest will be selected.\n.sp\nThe default members of a workspace can be set explicitly with the\n\\fBworkspace.default\\-members\\fR key in the root manifest. If this is not set, a\nvirtual workspace will include all workspace members (equivalent to passing\n\\fB\\-\\-workspace\\fR), and a non\\-virtual workspace will include only the root crate itself.\n.sp\n\\fB\\-p\\fR \\fIspec\\fR\\[u2026], \n\\fB\\-\\-package\\fR \\fIspec\\fR\\[u2026]\n.RS 4\nDisplay only the specified packages. See \\fBcargo\\-pkgid\\fR(1) for the\nSPEC format. This flag may be specified multiple times and supports common Unix\nglob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell accidentally\nexpanding glob patterns before Cargo handles them, you must use single quotes or\ndouble quotes around each pattern.\n.RE\n.sp\n\\fB\\-\\-workspace\\fR\n.RS 4\nDisplay all members in the workspace.\n.RE\n.sp\n\\fB\\-\\-exclude\\fR \\fISPEC\\fR\\[u2026]\n.RS 4\nExclude the specified packages. Must be used in conjunction with the\n\\fB\\-\\-workspace\\fR flag. This flag may be specified multiple times and supports\ncommon Unix glob patterns like \\fB*\\fR, \\fB?\\fR and \\fB[]\\fR\\&. However, to avoid your shell\naccidentally expanding glob patterns before Cargo handles them, you must use\nsingle quotes or double quotes around each pattern.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Feature Selection\"\nThe feature flags allow you to control which features are enabled. When no\nfeature options are given, the \\fBdefault\\fR feature is activated for every\nselected package.\n.sp\nSee \\fIthe features documentation\\fR <https://doc.rust\\-lang.org/cargo/reference/features.html#command\\-line\\-feature\\-options>\nfor more details.\n.sp\n\\fB\\-F\\fR \\fIfeatures\\fR, \n\\fB\\-\\-features\\fR \\fIfeatures\\fR\n.RS 4\nSpace or comma separated list of features to activate. Features of workspace\nmembers may be enabled with \\fBpackage\\-name/feature\\-name\\fR syntax. This flag may\nbe specified multiple times, which enables all specified features.\n.RE\n.sp\n\\fB\\-\\-all\\-features\\fR\n.RS 4\nActivate all available features of all selected packages.\n.RE\n.sp\n\\fB\\-\\-no\\-default\\-features\\fR\n.RS 4\nDo not activate the \\fBdefault\\fR feature of the selected packages.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Display the tree for the package in the current directory:\n.sp\n.RS 4\n.nf\ncargo tree\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Display all the packages that depend on the \\fBsyn\\fR package:\n.sp\n.RS 4\n.nf\ncargo tree \\-i syn\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Show the features enabled on each package:\n.sp\n.RS 4\n.nf\ncargo tree \\-\\-format \"{p} {f}\"\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 4.\\h'+01'Show all packages that are built multiple times. This can happen if multiple\nsemver\\-incompatible versions appear in the tree (like 1.0.0 and 2.0.0).\n.sp\n.RS 4\n.nf\ncargo tree \\-d\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 5.\\h'+01'Explain why features are enabled for the \\fBsyn\\fR package:\n.sp\n.RS 4\n.nf\ncargo tree \\-e features \\-i syn\n.fi\n.RE\n.sp\nThe \\fB\\-e features\\fR flag is used to show features. The \\fB\\-i\\fR flag is used to\ninvert the graph so that it displays the packages that depend on \\fBsyn\\fR\\&. An\nexample of what this would display:\n.sp\n.RS 4\n.nf\nsyn v1.0.17\n|\\-\\- syn feature \"clone\\-impls\"\n|   `\\-\\- syn feature \"default\"\n|       `\\-\\- rustversion v1.0.2\n|           `\\-\\- rustversion feature \"default\"\n|               `\\-\\- myproject v0.1.0 (/myproject)\n|                   `\\-\\- myproject feature \"default\" (command\\-line)\n|\\-\\- syn feature \"default\" (*)\n|\\-\\- syn feature \"derive\"\n|   `\\-\\- syn feature \"default\" (*)\n|\\-\\- syn feature \"full\"\n|   `\\-\\- rustversion v1.0.2 (*)\n|\\-\\- syn feature \"parsing\"\n|   `\\-\\- syn feature \"default\" (*)\n|\\-\\- syn feature \"printing\"\n|   `\\-\\- syn feature \"default\" (*)\n|\\-\\- syn feature \"proc\\-macro\"\n|   `\\-\\- syn feature \"default\" (*)\n`\\-\\- syn feature \"quote\"\n    |\\-\\- syn feature \"printing\" (*)\n    `\\-\\- syn feature \"proc\\-macro\" (*)\n.fi\n.RE\n.sp\nTo read this graph, you can follow the chain for each feature from the root\nto see why it is included. For example, the \\[lq]full\\[rq] feature is added by the\n\\fBrustversion\\fR crate which is included from \\fBmyproject\\fR (with the default\nfeatures), and \\fBmyproject\\fR is the package selected on the command\\-line. All\nof the other \\fBsyn\\fR features are added by the \\[lq]default\\[rq] feature (\\[lq]quote\\[rq] is\nadded by \\[lq]printing\\[rq] and \\[lq]proc\\-macro\\[rq], both of which are default features).\n.sp\nIf you\\[cq]re having difficulty cross\\-referencing the de\\-duplicated \\fB(*)\\fR\nentries, try with the \\fB\\-\\-no\\-dedupe\\fR flag to get the full output.\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-metadata\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-uninstall.1",
    "content": "'\\\" t\n.TH \"CARGO\\-UNINSTALL\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-uninstall \\[em] Remove a Rust binary\n.SH \"SYNOPSIS\"\n\\fBcargo uninstall\\fR [\\fIoptions\\fR] [\\fIspec\\fR\\[u2026]]\n.SH \"DESCRIPTION\"\nThis command removes a package installed with \\fBcargo\\-install\\fR(1). The \\fIspec\\fR\nargument is a package ID specification of the package to remove (see\n\\fBcargo\\-pkgid\\fR(1)).\n.sp\nBy default all binaries are removed for a crate but the \\fB\\-\\-bin\\fR and\n\\fB\\-\\-example\\fR flags can be used to only remove particular binaries.\n.sp\nThe installation root is determined, in order of precedence:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB\\-\\-root\\fR option\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBCARGO_INSTALL_ROOT\\fR environment variable\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBinstall.root\\fR Cargo \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBCARGO_HOME\\fR environment variable\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB$HOME/.cargo\\fR\n.RE\n.SH \"OPTIONS\"\n.SS \"Uninstall Options\"\n.sp\n\\fB\\-p\\fR, \n\\fB\\-\\-package\\fR \\fIspec\\fR\\[u2026]\n.RS 4\nPackage to uninstall.\n.RE\n.sp\n\\fB\\-\\-bin\\fR \\fIname\\fR\\[u2026]\n.RS 4\nOnly uninstall the binary \\fIname\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-root\\fR \\fIdir\\fR\n.RS 4\nDirectory to uninstall packages from.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Uninstall a previously installed package.\n.sp\n.RS 4\n.nf\ncargo uninstall ripgrep\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-install\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-update.1",
    "content": "'\\\" t\n.TH \"CARGO\\-UPDATE\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-update \\[em] Update dependencies as recorded in the local lock file\n.SH \"SYNOPSIS\"\n\\fBcargo update\\fR [\\fIoptions\\fR] \\fIspec\\fR\n.SH \"DESCRIPTION\"\nThis command will update dependencies in the \\fBCargo.lock\\fR file to the latest\nversion. If the \\fBCargo.lock\\fR file does not exist, it will be created with the\nlatest available versions.\n.SH \"OPTIONS\"\n.SS \"Update Options\"\n.sp\n\\fIspec\\fR\\[u2026]\n.RS 4\nUpdate only the specified packages. This flag may be specified\nmultiple times. See \\fBcargo\\-pkgid\\fR(1) for the SPEC format.\n.sp\nIf packages are specified with \\fIspec\\fR, then a conservative update of\nthe lockfile will be performed. This means that only the dependency specified\nby SPEC will be updated. Its transitive dependencies will be updated only if\nSPEC cannot be updated without updating dependencies.  All other dependencies\nwill remain locked at their currently recorded versions.\n.sp\nIf \\fIspec\\fR is not specified, all dependencies are updated.\n.RE\n.sp\n\\fB\\-\\-recursive\\fR\n.RS 4\nWhen used with \\fIspec\\fR, dependencies of \\fIspec\\fR are forced to update as well.\nCannot be used with \\fB\\-\\-precise\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-precise\\fR \\fIprecise\\fR\n.RS 4\nWhen used with \\fIspec\\fR, allows you to specify a specific version number to set\nthe package to. If the package comes from a git repository, this can be a git\nrevision (such as a SHA hash or tag).\n.sp\nWhile not recommended, you can specify a yanked version of a package.\nWhen possible, try other non\\-yanked SemVer\\-compatible versions or seek help\nfrom the maintainers of the package.\n.sp\nA compatible \\fBpre\\-release\\fR version can also be specified even when the version\nrequirement in \\fBCargo.toml\\fR doesn\\[cq]t contain any pre\\-release identifier (nightly only).\n.RE\n.sp\n\\fB\\-\\-breaking\\fR \\fIdirectory\\fR\n.RS 4\nUpdate \\fIspec\\fR to latest SemVer\\-breaking version.\n.sp\nVersion requirements will be modified to allow this update.\n.sp\nThis only applies to dependencies when\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The package is a dependency of a workspace member\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The dependency is not renamed\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'A SemVer\\-incompatible version is available\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The \\[lq]SemVer operator\\[rq] is used (\\fB^\\fR which is the default)\n.RE\n.sp\nThis option is unstable and available only on the\n\\fInightly channel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html>\nand requires the \\fB\\-Z unstable\\-options\\fR flag to enable.\nSee <https://github.com/rust\\-lang/cargo/issues/12425> for more information.\n.RE\n.sp\n\\fB\\-w\\fR, \n\\fB\\-\\-workspace\\fR\n.RS 4\nAttempt to update only packages defined in the workspace. Other packages\nare updated only if they don\\[cq]t already exist in the lockfile. This\noption is useful for updating \\fBCargo.lock\\fR after you\\[cq]ve changed version\nnumbers in \\fBCargo.toml\\fR\\&.\n.RE\n.sp\n\\fB\\-\\-dry\\-run\\fR\n.RS 4\nDisplays what would be updated, but doesn\\[cq]t actually write the lockfile.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-ignore\\-rust\\-version\\fR\n.RS 4\nIgnore \\fBrust\\-version\\fR specification in packages.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Update all dependencies in the lockfile:\n.sp\n.RS 4\n.nf\ncargo update\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Update only specific dependencies:\n.sp\n.RS 4\n.nf\ncargo update foo bar\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Set a specific dependency to a specific version:\n.sp\n.RS 4\n.nf\ncargo update foo \\-\\-precise 1.2.3\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-generate\\-lockfile\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-vendor.1",
    "content": "'\\\" t\n.TH \"CARGO\\-VENDOR\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-vendor \\[em] Vendor all dependencies locally\n.SH \"SYNOPSIS\"\n\\fBcargo vendor\\fR [\\fIoptions\\fR] [\\fIpath\\fR]\n.SH \"DESCRIPTION\"\nThis cargo subcommand will vendor all crates.io and git dependencies for a\nproject into the specified directory at \\fB<path>\\fR\\&. After this command completes\nthe vendor directory specified by \\fB<path>\\fR will contain all remote sources from\ndependencies specified. Additional manifests beyond the default one can be\nspecified with the \\fB\\-s\\fR option.\n.sp\nThe configuration necessary to use the vendored sources would be printed to\nstdout after \\fBcargo vendor\\fR completes the vendoring process.\nYou will need to add or redirect it to your Cargo configuration file,\nwhich is usually \\fB\\&.cargo/config.toml\\fR locally for the current package.\n.sp\nCargo treats vendored sources as read\\-only as it does to registry and git sources.\nIf you intend to modify a crate from a remote source,\nuse \\fB[patch]\\fR or a \\fBpath\\fR dependency pointing to a local copy of that crate.\nCargo will then correctly handle the crate on incremental rebuilds,\nas it knows that it is no longer a read\\-only dependency.\n.SH \"OPTIONS\"\n.SS \"Vendor Options\"\n.sp\n\\fB\\-s\\fR \\fImanifest\\fR, \n\\fB\\-\\-sync\\fR \\fImanifest\\fR\n.RS 4\nSpecify an extra \\fBCargo.toml\\fR manifest to workspaces which should also be\nvendored and synced to the output. May be specified multiple times.\n.RE\n.sp\n\\fB\\-\\-no\\-delete\\fR\n.RS 4\nDon\\[cq]t delete the \\[lq]vendor\\[rq] directory when vendoring, but rather keep all\nexisting contents of the vendor directory\n.RE\n.sp\n\\fB\\-\\-respect\\-source\\-config\\fR\n.RS 4\nInstead of ignoring \\fB[source]\\fR configuration by default in \\fB\\&.cargo/config.toml\\fR\nread it and use it when downloading crates from crates.io, for example\n.RE\n.sp\n\\fB\\-\\-versioned\\-dirs\\fR\n.RS 4\nNormally versions are only added to disambiguate multiple versions of the\nsame package. This option causes all directories in the \\[lq]vendor\\[rq] directory\nto be versioned, which makes it easier to track the history of vendored\npackages over time, and can help with the performance of re\\-vendoring when\nonly a subset of the packages have changed.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-manifest\\-path\\fR \\fIpath\\fR\n.RS 4\nPath to the \\fBCargo.toml\\fR file. By default, Cargo searches for the\n\\fBCargo.toml\\fR file in the current directory or any parent directory.\n.RE\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Vendor all dependencies into a local \\[lq]vendor\\[rq] folder\n.sp\n.RS 4\n.nf\ncargo vendor\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Vendor all dependencies into a local \\[lq]third\\-party/vendor\\[rq] folder\n.sp\n.RS 4\n.nf\ncargo vendor third\\-party/vendor\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Vendor the current workspace as well as another to \\[lq]vendor\\[rq]\n.sp\n.RS 4\n.nf\ncargo vendor \\-s ../path/to/Cargo.toml\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 4.\\h'+01'Vendor and redirect the necessary vendor configs to a config file.\n.sp\n.RS 4\n.nf\ncargo vendor > path/to/my/cargo/config.toml\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-version.1",
    "content": "'\\\" t\n.TH \"CARGO\\-VERSION\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-version \\[em] Show version information\n.SH \"SYNOPSIS\"\n\\fBcargo version\\fR [\\fIoptions\\fR]\n.SH \"DESCRIPTION\"\nDisplays the version of Cargo.\n.SH \"OPTIONS\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nDisplay additional version information.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Display the version:\n.sp\n.RS 4\n.nf\ncargo version\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'The version is also available via flags:\n.sp\n.RS 4\n.nf\ncargo \\-\\-version\ncargo \\-V\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Display extra version information:\n.sp\n.RS 4\n.nf\ncargo \\-Vv\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo-yank.1",
    "content": "'\\\" t\n.TH \"CARGO\\-YANK\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo\\-yank \\[em] Remove a pushed crate from the index\n.SH \"SYNOPSIS\"\n\\fBcargo yank\\fR [\\fIoptions\\fR] \\fIcrate\\fR@\\fIversion\\fR\n.br\n\\fBcargo yank\\fR [\\fIoptions\\fR] \\fB\\-\\-version\\fR \\fIversion\\fR [\\fIcrate\\fR]\n.SH \"DESCRIPTION\"\nThe yank command removes a previously published crate\\[cq]s version from the\nserver\\[cq]s index. This command does not delete any data, and the crate will\nstill be available for download via the registry\\[cq]s download link.\n.sp\nCargo will not use a yanked version for any new project or checkout without a\npre\\-existing lockfile, and will generate an error if there are no longer\nany compatible versions for your crate.\n.sp\nThis command requires you to be authenticated with either the \\fB\\-\\-token\\fR option\nor using \\fBcargo\\-login\\fR(1).\n.sp\nIf the crate name is not specified, it will use the package name from the\ncurrent directory.\n.SS \"How yank works\"\nFor example, the \\fBfoo\\fR crate published version \\fB1.5.0\\fR and another crate \\fBbar\\fR\ndeclared a dependency on version \\fBfoo = \"1.5\"\\fR\\&. Now \\fBfoo\\fR releases a new, but\nnot semver compatible, version \\fB2.0.0\\fR, and finds a critical issue with \\fB1.5.0\\fR\\&.\nIf \\fB1.5.0\\fR is yanked, no new project or checkout without an existing lockfile\nwill be able to use crate \\fBbar\\fR as it relies on \\fB1.5\\fR\\&.\n.sp\nIn this case, the maintainers of \\fBfoo\\fR should first publish a semver compatible\nversion such as \\fB1.5.1\\fR prior to yanking \\fB1.5.0\\fR so that \\fBbar\\fR and all projects\nthat depend on \\fBbar\\fR will continue to work.\n.sp\nAs another example, consider a crate \\fBbar\\fR with published versions \\fB1.5.0\\fR,\n\\fB1.5.1\\fR, \\fB1.5.2\\fR, \\fB2.0.0\\fR and \\fB3.0.0\\fR\\&. The following table identifies the\nversions cargo could use in the absence of a lockfile for different SemVer\nrequirements, following a given release being yanked:\n\n.TS\nallbox tab(:);\nlt lt lt lt.\nT{\nYanked Version / SemVer requirement\nT}:T{\n\\fBbar = \"1.5.0\"\\fR\nT}:T{\n\\fBbar = \"=1.5.0\"\\fR\nT}:T{\n\\fBbar = \"2.0.0\"\\fR\nT}\nT{\n\\fB1.5.0\\fR\nT}:T{\nUse either \\fB1.5.1\\fR or \\fB1.5.2\\fR\nT}:T{\n\\fBReturn Error\\fR\nT}:T{\nUse \\fB2.0.0\\fR\nT}\nT{\n\\fB1.5.1\\fR\nT}:T{\nUse either \\fB1.5.0\\fR or \\fB1.5.2\\fR\nT}:T{\nUse \\fB1.5.0\\fR\nT}:T{\nUse \\fB2.0.0\\fR\nT}\nT{\n\\fB2.0.0\\fR\nT}:T{\nUse either \\fB1.5.0\\fR, \\fB1.5.1\\fR or \\fB1.5.2\\fR\nT}:T{\nUse \\fB1.5.0\\fR\nT}:T{\n\\fBReturn Error\\fR\nT}\n.TE\n.sp\n.SS \"When to yank\"\nCrates should only be yanked in exceptional circumstances, for example, an\naccidental publish, unintentional SemVer breakages, or a significantly\nbroken and unusable crate. In the case of security vulnerabilities, \\fIRustSec\\fR <https://rustsec.org/>\nis typically a less disruptive mechanism to inform users and encourage them\nto upgrade, and avoids the possibility of significant downstream disruption\nirrespective of susceptibility to the vulnerability in question.\n.sp\nA common workflow is to yank a crate having already published a semver\ncompatible version, to reduce the probability of preventing dependent\ncrates from compiling.\n.sp\nWhen addressing copyright, licensing, or personal data issues with a published\ncrate, simply yanking it may not suffice. In such cases, contact the maintainers\nof the registry you used. For crates.io, refer to their \\fIpolicies\\fR <https://crates.io/policies> and contact\nthem at <help@crates.io>\\&.\n.sp\nIf credentials have been leaked, the recommended course of action is to revoke\nthem immediately. Once a crate has been published, it is impossible to determine\nif the leaked credentials have been copied. Yanking only prevents Cargo from\nselecting this version when resolving dependencies by default. Existing lock\nfiles or direct downloads are not affected, so yanking cannot stop further\nspreading of the leaked credentials.\n.SH \"OPTIONS\"\n.SS \"Yank Options\"\n.sp\n\\fB\\-\\-vers\\fR \\fIversion\\fR, \n\\fB\\-\\-version\\fR \\fIversion\\fR\n.RS 4\nThe version to yank or un\\-yank.\n.RE\n.sp\n\\fB\\-\\-undo\\fR\n.RS 4\nUndo a yank, putting a version back into the index.\n.RE\n.sp\n\\fB\\-\\-token\\fR \\fItoken\\fR\n.RS 4\nAPI token to use when authenticating. This overrides the token stored in\nthe credentials file (which is created by \\fBcargo\\-login\\fR(1)).\n.sp\n\\fICargo config\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html> environment variables can be\nused to override the tokens stored in the credentials file. The token for\ncrates.io may be specified with the \\fBCARGO_REGISTRY_TOKEN\\fR environment\nvariable. Tokens for other registries may be specified with environment\nvariables of the form \\fBCARGO_REGISTRIES_NAME_TOKEN\\fR where \\fBNAME\\fR is the name\nof the registry in all capital letters.\n.RE\n.sp\n\\fB\\-\\-index\\fR \\fIindex\\fR\n.RS 4\nThe URL of the registry index to use.\n.RE\n.sp\n\\fB\\-\\-registry\\fR \\fIregistry\\fR\n.RS 4\nName of the registry to use. Registry names are defined in \\fICargo config\nfiles\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&. If not specified, the default registry is used,\nwhich is defined by the \\fBregistry.default\\fR config key which defaults to\n\\fBcrates\\-io\\fR\\&.\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Yank a crate from the index:\n.sp\n.RS 4\n.nf\ncargo yank foo@1.0.7\n.fi\n.RE\n.RE\n.SH \"SEE ALSO\"\n\\fBcargo\\fR(1), \\fBcargo\\-login\\fR(1), \\fBcargo\\-publish\\fR(1)\n"
  },
  {
    "path": "src/etc/man/cargo.1",
    "content": "'\\\" t\n.TH \"CARGO\" \"1\"\n.nh\n.ad l\n.ss \\n[.ss] 0\n.SH \"NAME\"\ncargo \\[em] The Rust package manager\n.SH \"SYNOPSIS\"\n\\fBcargo\\fR [\\fIoptions\\fR] \\fIcommand\\fR [\\fIargs\\fR]\n.br\n\\fBcargo\\fR [\\fIoptions\\fR] \\fB\\-\\-version\\fR\n.br\n\\fBcargo\\fR [\\fIoptions\\fR] \\fB\\-\\-list\\fR\n.br\n\\fBcargo\\fR [\\fIoptions\\fR] \\fB\\-\\-help\\fR\n.br\n\\fBcargo\\fR [\\fIoptions\\fR] \\fB\\-\\-explain\\fR \\fIcode\\fR\n.SH \"DESCRIPTION\"\nThis program is a package manager and build tool for the Rust language,\navailable at <https://rust\\-lang.org>\\&.\n.sp\n\\fIcommand\\fR may be one of:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'built\\-in commands, see below\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fIaliases\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#alias>\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fIexternal tools\\fR <https://doc.rust\\-lang.org/cargo/reference/external\\-tools.html#custom\\-subcommands>\n.RE\n.SH \"COMMANDS\"\n.SS \"Build Commands\"\n\\fBcargo\\-bench\\fR(1)\n.br\n\\ \\ \\ \\ Execute benchmarks of a package.\n.sp\n\\fBcargo\\-build\\fR(1)\n.br\n\\ \\ \\ \\ Compile a package.\n.sp\n\\fBcargo\\-check\\fR(1)\n.br\n\\ \\ \\ \\ Check a local package and all of its dependencies for errors.\n.sp\n\\fBcargo\\-clean\\fR(1)\n.br\n\\ \\ \\ \\ Remove artifacts that Cargo has generated in the past.\n.sp\n\\fBcargo\\-doc\\fR(1)\n.br\n\\ \\ \\ \\ Build a package\\[cq]s documentation.\n.sp\n\\fBcargo\\-fetch\\fR(1)\n.br\n\\ \\ \\ \\ Fetch dependencies of a package from the network.\n.sp\n\\fBcargo\\-fix\\fR(1)\n.br\n\\ \\ \\ \\ Automatically fix lint warnings reported by rustc.\n.sp\n\\fBcargo\\-run\\fR(1)\n.br\n\\ \\ \\ \\ Run a binary or example of the local package.\n.sp\n\\fBcargo\\-rustc\\fR(1)\n.br\n\\ \\ \\ \\ Compile a package, and pass extra options to the compiler.\n.sp\n\\fBcargo\\-rustdoc\\fR(1)\n.br\n\\ \\ \\ \\ Build a package\\[cq]s documentation, using specified custom flags.\n.sp\n\\fBcargo\\-test\\fR(1)\n.br\n\\ \\ \\ \\ Execute unit and integration tests of a package.\n.SS \"Manifest Commands\"\n\\fBcargo\\-add\\fR(1)\n.br\n\\ \\ \\ \\ Add dependencies to a \\fBCargo.toml\\fR manifest file.\n.sp\n\\fBcargo\\-generate\\-lockfile\\fR(1)\n.br\n\\ \\ \\ \\ Generate \\fBCargo.lock\\fR for a project.\n.sp\n\\fBcargo\\-info\\fR(1)\n.br\n\\ \\ \\ \\ Display information about a package in the registry. Default registry is crates.io.\n.sp\n\\fBcargo\\-locate\\-project\\fR(1)\n.br\n\\ \\ \\ \\ Print a JSON representation of a \\fBCargo.toml\\fR file\\[cq]s location.\n.sp\n\\fBcargo\\-metadata\\fR(1)\n.br\n\\ \\ \\ \\ Output the resolved dependencies of a package in machine\\-readable format.\n.sp\n\\fBcargo\\-pkgid\\fR(1)\n.br\n\\ \\ \\ \\ Print a fully qualified package specification.\n.sp\n\\fBcargo\\-remove\\fR(1)\n.br\n\\ \\ \\ \\ Remove dependencies from a \\fBCargo.toml\\fR manifest file.\n.sp\n\\fBcargo\\-tree\\fR(1)\n.br\n\\ \\ \\ \\ Display a tree visualization of a dependency graph.\n.sp\n\\fBcargo\\-update\\fR(1)\n.br\n\\ \\ \\ \\ Update dependencies as recorded in the local lock file.\n.sp\n\\fBcargo\\-vendor\\fR(1)\n.br\n\\ \\ \\ \\ Vendor all dependencies locally.\n.SS \"Package Commands\"\n\\fBcargo\\-init\\fR(1)\n.br\n\\ \\ \\ \\ Create a new Cargo package in an existing directory.\n.sp\n\\fBcargo\\-install\\fR(1)\n.br\n\\ \\ \\ \\ Build and install a Rust binary.\n.sp\n\\fBcargo\\-new\\fR(1)\n.br\n\\ \\ \\ \\ Create a new Cargo package.\n.sp\n\\fBcargo\\-search\\fR(1)\n.br\n\\ \\ \\ \\ Search packages in crates.io.\n.sp\n\\fBcargo\\-uninstall\\fR(1)\n.br\n\\ \\ \\ \\ Remove a Rust binary.\n.SS \"Publishing Commands\"\n\\fBcargo\\-login\\fR(1)\n.br\n\\ \\ \\ \\ Save an API token from the registry locally.\n.sp\n\\fBcargo\\-logout\\fR(1)\n.br\n\\ \\ \\ \\ Remove an API token from the registry locally.\n.sp\n\\fBcargo\\-owner\\fR(1)\n.br\n\\ \\ \\ \\ Manage the owners of a crate on the registry.\n.sp\n\\fBcargo\\-package\\fR(1)\n.br\n\\ \\ \\ \\ Assemble the local package into a distributable tarball.\n.sp\n\\fBcargo\\-publish\\fR(1)\n.br\n\\ \\ \\ \\ Upload a package to the registry.\n.sp\n\\fBcargo\\-yank\\fR(1)\n.br\n\\ \\ \\ \\ Remove a pushed crate from the index.\n.SS \"Report Commands\"\n\\fBcargo\\-report\\fR(1)\n.br\n\\ \\ \\ \\ Generate and display various kinds of reports.\n.sp\n\\fBcargo\\-report\\-future\\-incompatibilities\\fR(1)\n.br\n\\ \\ \\ \\ Reports any crates which will eventually stop compiling.\n.SS \"General Commands\"\n\\fBcargo\\-help\\fR(1)\n.br\n\\ \\ \\ \\ Display help information about Cargo.\n.sp\n\\fBcargo\\-version\\fR(1)\n.br\n\\ \\ \\ \\ Show version information.\n.SH \"OPTIONS\"\n.SS \"Special Options\"\n.sp\n\\fB\\-V\\fR, \n\\fB\\-\\-version\\fR\n.RS 4\nPrint version info and exit. If used with \\fB\\-\\-verbose\\fR, prints extra\ninformation.\n.RE\n.sp\n\\fB\\-\\-list\\fR\n.RS 4\nList all installed Cargo subcommands. If used with \\fB\\-\\-verbose\\fR, prints extra\ninformation.\n.RE\n.sp\n\\fB\\-\\-explain\\fR \\fIcode\\fR\n.RS 4\nRun \\fBrustc \\-\\-explain CODE\\fR which will print out a detailed explanation of an\nerror message (for example, \\fBE0004\\fR).\n.RE\n.SS \"Display Options\"\n.sp\n\\fB\\-v\\fR, \n\\fB\\-\\-verbose\\fR\n.RS 4\nUse verbose output. May be specified twice for \\[lq]very verbose\\[rq] output which\nincludes extra output such as dependency warnings and build script output.\nMay also be specified with the \\fBterm.verbose\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-q\\fR, \n\\fB\\-\\-quiet\\fR\n.RS 4\nDo not print cargo log messages.\nMay also be specified with the \\fBterm.quiet\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-color\\fR \\fIwhen\\fR\n.RS 4\nControl when colored output is used. Valid values:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBauto\\fR (default): Automatically detect if color support is available on the\nterminal.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBalways\\fR: Always display colors.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fBnever\\fR: Never display colors.\n.RE\n.sp\nMay also be specified with the \\fBterm.color\\fR\n\\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.SS \"Manifest Options\"\n.sp\n\\fB\\-\\-locked\\fR\n.RS 4\nAsserts that the exact same dependencies and versions are used as when the\nexisting \\fBCargo.lock\\fR file was originally generated. Cargo will exit with an\nerror when either of the following scenarios arises:\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'The lock file is missing.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'Cargo attempted to change the lock file due to a different dependency resolution.\n.RE\n.sp\nIt may be used in environments where deterministic builds are desired,\nsuch as in CI pipelines.\n.RE\n.sp\n\\fB\\-\\-offline\\fR\n.RS 4\nPrevents Cargo from accessing the network for any reason. Without this\nflag, Cargo will stop with an error if it needs to access the network and\nthe network is not available. With this flag, Cargo will attempt to\nproceed without the network if possible.\n.sp\nBeware that this may result in different dependency resolution than online\nmode. Cargo will restrict itself to crates that are downloaded locally, even\nif there might be a newer version as indicated in the local copy of the index.\nSee the \\fBcargo\\-fetch\\fR(1) command to download dependencies before going\noffline.\n.sp\nMay also be specified with the \\fBnet.offline\\fR \\fIconfig value\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\\&.\n.RE\n.sp\n\\fB\\-\\-frozen\\fR\n.RS 4\nEquivalent to specifying both \\fB\\-\\-locked\\fR and \\fB\\-\\-offline\\fR\\&.\n.RE\n.SS \"Common Options\"\n.sp\n\\fB+\\fR\\fItoolchain\\fR\n.RS 4\nIf Cargo has been installed with rustup, and the first argument to \\fBcargo\\fR\nbegins with \\fB+\\fR, it will be interpreted as a rustup toolchain name (such\nas \\fB+stable\\fR or \\fB+nightly\\fR).\nSee the \\fIrustup documentation\\fR <https://rust\\-lang.github.io/rustup/overrides.html>\nfor more information about how toolchain overrides work.\n.RE\n.sp\n\\fB\\-\\-config\\fR \\fIKEY=VALUE\\fR or \\fIPATH\\fR\n.RS 4\nOverrides a Cargo configuration value. The argument should be in TOML syntax of \\fBKEY=VALUE\\fR,\nor provided as a path to an extra configuration file. This flag may be specified multiple times.\nSee the \\fIcommand\\-line overrides section\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html#command\\-line\\-overrides> for more information.\n.RE\n.sp\n\\fB\\-C\\fR \\fIPATH\\fR\n.RS 4\nChanges the current working directory before executing any specified operations. This affects\nthings like where cargo looks by default for the project manifest (\\fBCargo.toml\\fR), as well as\nthe directories searched for discovering \\fB\\&.cargo/config.toml\\fR, for example. This option must\nappear before the command name, for example \\fBcargo \\-C path/to/my\\-project build\\fR\\&.\n.sp\nThis option is only available on the \\fInightly\nchannel\\fR <https://doc.rust\\-lang.org/book/appendix\\-07\\-nightly\\-rust.html> and\nrequires the \\fB\\-Z unstable\\-options\\fR flag to enable (see\n\\fI#10098\\fR <https://github.com/rust\\-lang/cargo/issues/10098>).\n.RE\n.sp\n\\fB\\-h\\fR, \n\\fB\\-\\-help\\fR\n.RS 4\nPrints help information.\n.RE\n.sp\n\\fB\\-Z\\fR \\fIflag\\fR\n.RS 4\nUnstable (nightly\\-only) flags to Cargo. Run \\fBcargo \\-Z help\\fR for details.\n.RE\n.SH \"ENVIRONMENT\"\nSee \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/environment\\-variables.html> for\ndetails on environment variables that Cargo reads.\n.SH \"EXIT STATUS\"\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB0\\fR: Cargo succeeded.\n.RE\n.sp\n.RS 4\n\\h'-04'\\(bu\\h'+03'\\fB101\\fR: Cargo failed to complete.\n.RE\n.SH \"FILES\"\n\\fB~/.cargo/\\fR\n.br\n\\ \\ \\ \\ Default location for Cargo\\[cq]s \\[lq]home\\[rq] directory where it\nstores various files. The location can be changed with the \\fBCARGO_HOME\\fR\nenvironment variable.\n.sp\n\\fB$CARGO_HOME/bin/\\fR\n.br\n\\ \\ \\ \\ Binaries installed by \\fBcargo\\-install\\fR(1) will be located here. If using\n\\fIrustup\\fR <https://rust\\-lang.github.io/rustup/>, executables distributed with Rust are also located here.\n.sp\n\\fB$CARGO_HOME/config.toml\\fR\n.br\n\\ \\ \\ \\ The global configuration file. See \\fIthe reference\\fR <https://doc.rust\\-lang.org/cargo/reference/config.html>\nfor more information about configuration files.\n.sp\n\\fB\\&.cargo/config.toml\\fR\n.br\n\\ \\ \\ \\ Cargo automatically searches for a file named \\fB\\&.cargo/config.toml\\fR in the\ncurrent directory, and all parent directories. These configuration files\nwill be merged with the global configuration file.\n.sp\n\\fB$CARGO_HOME/credentials.toml\\fR\n.br\n\\ \\ \\ \\ Private authentication information for logging in to a registry.\n.sp\n\\fB$CARGO_HOME/registry/\\fR\n.br\n\\ \\ \\ \\ This directory contains cached downloads of the registry index and any\ndownloaded dependencies.\n.sp\n\\fB$CARGO_HOME/git/\\fR\n.br\n\\ \\ \\ \\ This directory contains cached downloads of git dependencies.\n.sp\nPlease note that the internal structure of the \\fB$CARGO_HOME\\fR directory is not\nstable yet and may be subject to change.\n.SH \"EXAMPLES\"\n.sp\n.RS 4\n\\h'-04' 1.\\h'+01'Build a local package and all of its dependencies:\n.sp\n.RS 4\n.nf\ncargo build\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 2.\\h'+01'Build a package with optimizations:\n.sp\n.RS 4\n.nf\ncargo build \\-\\-release\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 3.\\h'+01'Run tests for a cross\\-compiled target:\n.sp\n.RS 4\n.nf\ncargo test \\-\\-target i686\\-unknown\\-linux\\-gnu\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 4.\\h'+01'Create a new package that builds an executable:\n.sp\n.RS 4\n.nf\ncargo new foobar\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 5.\\h'+01'Create a package in the current directory:\n.sp\n.RS 4\n.nf\nmkdir foo && cd foo\ncargo init .\n.fi\n.RE\n.RE\n.sp\n.RS 4\n\\h'-04' 6.\\h'+01'Learn about a command\\[cq]s options and usage:\n.sp\n.RS 4\n.nf\ncargo help clean\n.fi\n.RE\n.RE\n.SH \"BUGS\"\nSee <https://github.com/rust\\-lang/cargo/issues> for issues.\n.SH \"SEE ALSO\"\n\\fBrustc\\fR(1), \\fBrustdoc\\fR(1)\n"
  },
  {
    "path": "tests/build-std/main.rs",
    "content": "//! A test suite for `-Zbuild-std` which is much more expensive than the\n//! standard test suite.\n//!\n//! This test suite attempts to perform a full integration test where we\n//! actually compile the standard library from source (like the real one) and\n//! the various tests associated with that.\n//!\n//! YOU SHOULD IDEALLY NOT WRITE TESTS HERE.\n//!\n//! If possible, use `tests/testsuite/standard_lib.rs` instead. That uses a\n//! 'mock' sysroot which is much faster to compile. The tests here are\n//! extremely intensive and are only intended to run on CI and are theoretically\n//! not catching any regressions that `tests/testsuite/standard_lib.rs` isn't\n//! already catching.\n//!\n//! All tests here should use `#[cargo_test(build_std_real)]` to indicate that\n//! boilerplate should be generated to require the nightly toolchain and the\n//! `CARGO_RUN_BUILD_STD_TESTS` env var to be set to actually run these tests.\n//! Otherwise the tests are skipped.\n\n#![allow(clippy::disallowed_methods)]\n\nuse cargo_test_support::Execs;\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::paths;\nuse cargo_test_support::project;\nuse cargo_test_support::rustc_host;\nuse cargo_test_support::str;\nuse cargo_test_support::target_spec_json;\nuse cargo_test_support::{Project, prelude::*};\nuse std::env;\nuse std::path::{Path, PathBuf};\n\nfn enable_build_std(e: &mut Execs, arg: Option<&str>, isolated: bool) {\n    if !isolated {\n        e.env_remove(\"CARGO_HOME\");\n        e.env_remove(\"HOME\");\n    }\n\n    // And finally actually enable `build-std` for now\n    let arg = match arg {\n        Some(s) => format!(\"-Zbuild-std={}\", s),\n        None => \"-Zbuild-std\".to_string(),\n    };\n    e.arg(arg).arg(\"-Zpublic-dependency\");\n    e.masquerade_as_nightly_cargo(&[\"build-std\"]);\n}\n\n// Helper methods used in the tests below\ntrait BuildStd: Sized {\n    /// Set `-Zbuild-std` args and will download dependencies of the standard\n    /// library in users's `CARGO_HOME` (`~/.cargo/`) instead of isolated\n    /// environment `cargo-test-support` usually provides.\n    ///\n    /// The environment is not isolated is to avoid excessive network requests\n    /// and downloads. A side effect is `[BLOCKING]` will show up in stderr,\n    /// as a sign of package cache lock contention when running other build-std\n    /// tests concurrently.\n    fn build_std(&mut self) -> &mut Self;\n\n    /// Like [`BuildStd::build_std`] and is able to specify what crates to build.\n    fn build_std_arg(&mut self, arg: &str) -> &mut Self;\n\n    /// Like [`BuildStd::build_std`] but use an isolated `CARGO_HOME` environment\n    /// to avoid package cache lock contention.\n    ///\n    /// Don't use this unless you really need to assert the full stderr\n    /// and avoid any `[BLOCKING]` message.\n    fn build_std_isolated(&mut self) -> &mut Self;\n    fn target_host(&mut self) -> &mut Self;\n}\n\nimpl BuildStd for Execs {\n    fn build_std(&mut self) -> &mut Self {\n        enable_build_std(self, None, false);\n        self\n    }\n\n    fn build_std_arg(&mut self, arg: &str) -> &mut Self {\n        enable_build_std(self, Some(arg), false);\n        self\n    }\n\n    fn build_std_isolated(&mut self) -> &mut Self {\n        enable_build_std(self, None, true);\n        self\n    }\n\n    fn target_host(&mut self) -> &mut Self {\n        self.arg(\"--target\").arg(rustc_host());\n        self\n    }\n}\n\n#[cargo_test(build_std_real)]\nfn basic() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            \"\n                fn main() {\n                    foo::f();\n                }\n\n                #[test]\n                fn smoke_bin_unit() {\n                    foo::f();\n                }\n            \",\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n                extern crate alloc;\n                extern crate proc_macro;\n\n                /// ```\n                /// foo::f();\n                /// ```\n                pub fn f() {\n                }\n\n                #[test]\n                fn smoke_lib_unit() {\n                    f();\n                }\n            \",\n        )\n        .file(\n            \"tests/smoke.rs\",\n            \"\n                #[test]\n                fn smoke_integration() {\n                    foo::f();\n                }\n            \",\n        )\n        .build();\n\n    // HACK: use an isolated the isolated CARGO_HOME environment (`build_std_isolated`)\n    // to avoid `[BLOCKING]` messages (from lock contention with other tests)\n    // from getting in this test's asserts\n    p.cargo(\"check\").build_std_isolated().target_host().run();\n    p.cargo(\"build\")\n        .build_std_isolated()\n        .target_host()\n        // Importantly, this should not say [UPDATING]\n        // There have been multiple bugs where every build triggers and update.\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"run\")\n        .build_std_isolated()\n        .target_host()\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/[HOST_TARGET]/debug/foo`\n\n\"#]])\n        .run();\n    p.cargo(\"test\")\n        .build_std_isolated()\n        .target_host()\n        .with_stderr_data(str![[r#\"\n[COMPILING] [..]\n...\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/[HOST_TARGET]/debug/deps/foo-[HASH])\n[RUNNING] unittests src/main.rs (target/[HOST_TARGET]/debug/deps/foo-[HASH])\n[RUNNING] tests/smoke.rs (target/[HOST_TARGET]/debug/deps/smoke-[HASH])\n[DOCTEST] foo\n\n\"#]])\n        .run();\n\n    // Check for hack that removes dylibs.\n    let deps_dir = Path::new(\"target\")\n        .join(rustc_host())\n        .join(\"debug\")\n        .join(\"deps\");\n    assert!(p.glob(deps_dir.join(\"*.rlib\")).count() > 0);\n    assert_eq!(p.glob(deps_dir.join(\"*.dylib\")).count(), 0);\n}\n\n#[cargo_test(build_std_real)]\nfn lto() {\n    // Checks that `-Zbuild-std` can work with `lto = \"thin\"`.\n    // This regression is from https://github.com/rust-lang/rust/issues/146109.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [profile.dev]\n                lto = \"thin\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {}\n            \"#,\n        )\n        .build();\n\n    let mut exec = p.cargo(\"build\");\n    exec.build_std_arg(\"std\");\n    // Include `-lld` to disable the self-contained linker. This test is\n    // checking for the behavior when using the system linker (like GNU ld or\n    // older versions of lld) which have problems with the bitcode sections in\n    // compiler_builtins.\n    //\n    // This option is only available on x86-64-unknown-linux-gnu.\n    if cfg!(all(\n        target_arch = \"x86_64\",\n        target_os = \"linux\",\n        target_env = \"gnu\"\n    )) {\n        exec.env(\"RUSTFLAGS\", \"-C linker-features=-lld\");\n    }\n    exec.run();\n}\n\n#[cargo_test(build_std_real)]\nfn host_proc_macro() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                macro_test = { path = \"macro_test\" }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            extern crate macro_test;\n            use macro_test::make_answer;\n\n            make_answer!();\n\n            fn main() {\n                println!(\"Hello, World: {}\", answer());\n            }\n            \"#,\n        )\n        .file(\n            \"macro_test/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"macro_test\"\n            version = \"0.1.0\"\n            edition = \"2021\"\n\n            [lib]\n            proc-macro = true\n            \"#,\n        )\n        .file(\n            \"macro_test/src/lib.rs\",\n            r#\"\n            extern crate proc_macro;\n            use proc_macro::TokenStream;\n\n            #[proc_macro]\n            pub fn make_answer(_item: TokenStream) -> TokenStream {\n                \"fn answer() -> u32 { 42 }\".parse().unwrap()\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .build_std_arg(\"std\")\n        .build_std_arg(\"proc_macro\")\n        .run();\n}\n\n#[cargo_test(build_std_real)]\nfn cross_custom() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [target.custom-target.dependencies]\n                dep = { path = \"dep\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"#![no_std] pub fn f() -> u32 { dep::answer() }\",\n        )\n        .file(\"dep/Cargo.toml\", &basic_manifest(\"dep\", \"0.1.0\"))\n        .file(\"dep/src/lib.rs\", \"#![no_std] pub fn answer() -> u32 { 42 }\")\n        .file(\"custom-target.json\", target_spec_json())\n        .build();\n\n    p.cargo(\"build --target custom-target.json -v -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .build_std_arg(\"core\")\n        .run();\n}\n\n#[cargo_test(build_std_real)]\nfn custom_test_framework() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            #![no_std]\n            #![cfg_attr(test, no_main)]\n            #![feature(custom_test_frameworks)]\n            #![test_runner(crate::test_runner)]\n\n            pub fn test_runner(_tests: &[&dyn Fn()]) {}\n\n            #[panic_handler]\n            fn panic(_info: &core::panic::PanicInfo) -> ! {\n                loop {}\n            }\n            \"#,\n        )\n        .file(\"target.json\", target_spec_json())\n        .build();\n\n    // This is a bit of a hack to use the rust-lld that ships with most toolchains.\n    let sysroot = paths::sysroot();\n    let sysroot = Path::new(&sysroot);\n    let sysroot_bin = sysroot\n        .join(\"lib\")\n        .join(\"rustlib\")\n        .join(rustc_host())\n        .join(\"bin\");\n    let path = env::var_os(\"PATH\").unwrap_or_default();\n    let mut paths = env::split_paths(&path).collect::<Vec<_>>();\n    paths.insert(0, sysroot_bin);\n    let new_path = env::join_paths(paths).unwrap();\n\n    p.cargo(\"test --target target.json --no-run -v -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .env(\"PATH\", new_path)\n        .build_std_arg(\"core\")\n        .run();\n}\n\n// Fixing rust-lang/rust#117839.\n// on macOS it never gets remapped.\n// Might be a separate issue, so only run on Linux.\n#[cargo_test(build_std_real)]\n#[cfg(target_os = \"linux\")]\nfn remap_path_scope() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            \"\n                fn main() {\n                    panic!(\\\"remap to /rustc/<hash>\\\");\n                }\n            \",\n        )\n        .file(\n            \".cargo/config.toml\",\n            \"\n                [profile.release]\n                debug = \\\"line-tables-only\\\"\n            \",\n        )\n        .build();\n\n    p.cargo(\"run --release -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .env(\"RUST_BACKTRACE\", \"1\")\n        .build_std()\n        .target_host()\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n[FINISHED] `release` profile [optimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/[HOST_TARGET]/release/foo`\n...\n[..]thread [..] panicked at [..]src/main.rs:3:[..]:\n[..]remap to /rustc/<hash>[..]\n[..]at /rustc/[..]/library/std/src/[..]\n[..]at ./src/main.rs:3:[..]\n[..]at /rustc/[..]/library/core/src/[..]\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(build_std_real)]\nfn test_proc_macro() {\n    // See rust-lang/cargo#14735\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2021\"\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test --lib\")\n        .env_remove(cargo_util::paths::dylib_path_envvar())\n        .build_std()\n        .with_stderr_data(str![[r#\"\n...\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(build_std_real)]\nfn build_std_does_not_warn_about_implicit_std_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"buildstd_test\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .build_std()\n        .target_host()\n        .env(\"RUSTFLAGS\", \"-W unused-crate-dependencies\")\n        .with_stderr_data(\n            str![[r#\"\n[WARNING] extern crate `bar` is unused in crate `buildstd_test`\n[WARNING] `buildstd_test` (bin \"buildstd_test\") generated 1 warning\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(build_std_real)]\nfn default_features_still_included_with_extra_build_std_features() {\n    // This is a regression test to ensure when adding extra `build-std-features`,\n    // the default feature set is still respected and included.\n    // See rust-lang/cargo#14935\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"#![no_std]\")\n        .build();\n\n    p.cargo(\"check\")\n        .build_std_arg(\"std,panic_abort\")\n        .env(\"RUSTFLAGS\", \"-C panic=abort\")\n        .arg(\"-Zbuild-std-features=optimize_for_size\")\n        .run();\n}\n\npub trait CargoProjectExt {\n    /// Creates a `ProcessBuilder` to run cargo.\n    ///\n    /// Arguments can be separated by spaces.\n    ///\n    /// For `cargo run`, see [`Project::rename_run`].\n    ///\n    /// # Example:\n    ///\n    /// ```no_run\n    /// # let p = cargo_test_support::project().build();\n    /// p.cargo(\"build --bin foo\").run();\n    /// ```\n    fn cargo(&self, cmd: &str) -> Execs;\n}\n\nimpl CargoProjectExt for Project {\n    fn cargo(&self, cmd: &str) -> Execs {\n        let cargo = cargo_exe();\n        let mut execs = self.process(&cargo);\n        execs.env(\"CARGO\", cargo);\n        execs.arg_line(cmd);\n        execs\n    }\n}\n\n/// Path to the cargo binary\npub fn cargo_exe() -> PathBuf {\n    snapbox::cmd::cargo_bin!(\"cargo\").to_path_buf()\n}\n"
  },
  {
    "path": "tests/testsuite/advanced_env.rs",
    "content": "//! -Zadvanced-env tests\n\nuse crate::prelude::*;\nuse cargo_test_support::{paths, project, registry::Package};\n\n#[cargo_test]\nfn source_config_env() {\n    // Try to define [source] with environment variables.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            somedep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"somedep\", \"1.0.0\")\n        .local(true)\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let path = paths::root().join(\"registry\");\n\n    p.cargo(\"check -Zadvanced-env\")\n        .masquerade_as_nightly_cargo(&[\"advanced-env\"])\n        .env(\"CARGO_SOURCE_crates-io_REPLACE_WITH\", \"my-local-source\")\n        .env(\"CARGO_SOURCE_my-local-source_LOCAL_REGISTRY\", path)\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/alt_registry.rs",
    "content": "//! Tests for alternative registries.\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::publish::validate_alt_upload;\nuse cargo_test_support::registry::{self, Package, RegistryBuilder};\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_manifest, paths, project};\n\n#[cargo_test]\nfn depend_on_alt_registry() {\n    registry::alt_init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n                registry = \"alternative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").alternative(true).publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `alternative`)\n[CHECKING] bar v0.0.1 (registry `alternative`)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"clean\").run();\n\n    // Don't download a second time\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.0.1 (registry `alternative`)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn depend_on_alt_registry_depends_on_same_registry_no_index() {\n    registry::alt_init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n                registry = \"alternative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"baz\", \"0.0.1\").alternative(true).publish();\n    Package::new(\"bar\", \"0.0.1\")\n        .registry_dep(\"baz\", \"0.0.1\")\n        .alternative(true)\n        .publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.0.1 (registry `alternative`)\n[DOWNLOADED] bar v0.0.1 (registry `alternative`)\n[CHECKING] baz v0.0.1 (registry `alternative`)\n[CHECKING] bar v0.0.1 (registry `alternative`)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn depend_on_alt_registry_depends_on_same_registry() {\n    registry::alt_init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n                registry = \"alternative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"baz\", \"0.0.1\").alternative(true).publish();\n    Package::new(\"bar\", \"0.0.1\")\n        .registry_dep(\"baz\", \"0.0.1\")\n        .alternative(true)\n        .publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.0.1 (registry `alternative`)\n[DOWNLOADED] bar v0.0.1 (registry `alternative`)\n[CHECKING] baz v0.0.1 (registry `alternative`)\n[CHECKING] bar v0.0.1 (registry `alternative`)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn depend_on_alt_registry_depends_on_crates_io() {\n    registry::alt_init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n                registry = \"alternative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"baz\", \"0.0.1\").publish();\n    Package::new(\"bar\", \"0.0.1\")\n        .dep(\"baz\", \"0.0.1\")\n        .alternative(true)\n        .publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `alternative` index\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] bar v0.0.1 (registry `alternative`)\n[CHECKING] baz v0.0.1\n[CHECKING] bar v0.0.1 (registry `alternative`)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn registry_and_path_dep_works() {\n    registry::alt_init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies.bar]\n                path = \"bar\"\n                registry = \"alternative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn registry_incompatible_with_git() {\n    registry::alt_init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies.bar]\n                git = \"\"\n                registry = \"alternative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  dependency (bar) specification is ambiguous. Only one of `git` or `registry` is allowed.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cannot_publish_to_crates_io_with_registry_dependency() {\n    let crates_io = registry::init();\n    let _alternative = RegistryBuilder::new().alternative().build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n                [dependencies.bar]\n                version = \"0.0.1\"\n                registry = \"alternative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").alternative(true).publish();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(crates_io.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] failed to verify manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  crates cannot be published to crates.io with dependencies sourced from other\n  registries. `bar` needs to be published to crates.io before publishing this crate.\n  (crate `bar` is pulled from registry `alternative`)\n\n\"#]])\n        .run();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(crates_io.index_url())\n        .arg(\"--token\")\n        .arg(crates_io.token())\n        .arg(\"--index\")\n        .arg(crates_io.index_url().as_str())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] `cargo publish --token` is deprecated in favor of using `cargo login` and environment variables\n[UPDATING] crates.io index\n[ERROR] failed to verify manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  crates cannot be published to crates.io with dependencies sourced from other\n  registries. `bar` needs to be published to crates.io before publishing this crate.\n  (crate `bar` is pulled from registry `alternative`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_with_registry_dependency() {\n    let _reg = RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n                registry = \"alternative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").alternative(true).publish();\n\n    p.cargo(\"publish --registry alternative\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[UPDATING] `alternative` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `alternative`)\n[COMPILING] bar v0.0.1 (registry `alternative`)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `alternative`\n[NOTE] waiting for foo v0.0.1 to be available at registry `alternative`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `alternative`\n\n\"#]])\n        .run();\n\n    validate_alt_upload(\n        r#\"{\n            \"authors\": [],\n            \"badges\": {},\n            \"categories\": [],\n            \"deps\": [\n              {\n                \"default_features\": true,\n                \"features\": [],\n                \"kind\": \"normal\",\n                \"name\": \"bar\",\n                \"optional\": false,\n                \"target\": null,\n                \"version_req\": \"^0.0.1\"\n              }\n            ],\n            \"description\": null,\n            \"documentation\": null,\n            \"features\": {},\n            \"homepage\": null,\n            \"keywords\": [],\n            \"license\": null,\n            \"license_file\": null,\n            \"links\": null,\n            \"name\": \"foo\",\n            \"readme\": null,\n            \"readme_file\": null,\n            \"repository\": null,\n            \"homepage\": null,\n            \"documentation\": null,\n            \"rust_version\": null,\n            \"vers\": \"0.0.1\"\n        }\"#,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n    );\n}\n\n#[cargo_test]\nfn alt_registry_and_crates_io_deps() {\n    registry::alt_init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies]\n                crates_io_dep = \"0.0.1\"\n\n                [dependencies.alt_reg_dep]\n                version = \"0.1.0\"\n                registry = \"alternative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"crates_io_dep\", \"0.0.1\").publish();\n    Package::new(\"alt_reg_dep\", \"0.1.0\")\n        .alternative(true)\n        .publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `alternative` index\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] crates_io_dep v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] alt_reg_dep v0.1.0 (registry `alternative`)\n[CHECKING] crates_io_dep v0.0.1\n[CHECKING] alt_reg_dep v0.1.0 (registry `alternative`)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn block_publish_due_to_no_token() {\n    registry::alt_init();\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    fs::remove_file(paths::home().join(\".cargo/credentials.toml\")).unwrap();\n\n    // Now perform the actual publish\n    p.cargo(\"publish --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] no token found for `alternative`, please run `cargo login --registry alternative`\nor use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_registries_crates_io_protocol() {\n    let _ = RegistryBuilder::new()\n        .no_configure_token()\n        .alternative()\n        .build();\n    // Should not produce a warning due to the registries.crates-io.protocol = 'sparse' configuration\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            \"[registries.crates-io]\n            protocol = 'sparse'\",\n        )\n        .build();\n\n    p.cargo(\"publish --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] no token found for `alternative`, please run `cargo login --registry alternative`\nor use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_to_alt_registry() {\n    let _reg = RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    // Now perform the actual publish\n    p.cargo(\"publish --registry alternative\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `alternative`\n[NOTE] waiting for foo v0.0.1 to be available at registry `alternative`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `alternative`\n\n\"#]])\n        .run();\n\n    validate_alt_upload(\n        r#\"{\n            \"authors\": [],\n            \"badges\": {},\n            \"categories\": [],\n            \"deps\": [],\n            \"description\": null,\n            \"documentation\": null,\n            \"features\": {},\n            \"homepage\": null,\n            \"keywords\": [],\n            \"license\": null,\n            \"license_file\": null,\n            \"links\": null,\n            \"name\": \"foo\",\n            \"readme\": null,\n            \"readme_file\": null,\n            \"repository\": null,\n            \"homepage\": null,\n            \"documentation\": null,\n            \"rust_version\": null,\n            \"vers\": \"0.0.1\"\n        }\"#,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n    );\n}\n\n#[cargo_test]\nfn publish_with_crates_io_dep() {\n    // crates.io registry.\n    let _dummy_reg = registry::init();\n    // Alternative registry.\n    let _alt_reg = RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = [\"me\"]\n                edition = \"2015\"\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    p.cargo(\"publish --registry alternative\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[UPDATING] `dummy-registry` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[COMPILING] bar v0.0.1\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `alternative`\n[NOTE] waiting for foo v0.0.1 to be available at registry `alternative`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `alternative`\n\n\"#]])\n        .run();\n\n    validate_alt_upload(\n        r#\"{\n            \"authors\": [\"me\"],\n            \"badges\": {},\n            \"categories\": [],\n            \"deps\": [\n              {\n                \"default_features\": true,\n                \"features\": [],\n                \"kind\": \"normal\",\n                \"name\": \"bar\",\n                \"optional\": false,\n                \"registry\": \"https://github.com/rust-lang/crates.io-index\",\n                \"target\": null,\n                \"version_req\": \"^0.0.1\"\n              }\n            ],\n            \"description\": \"foo\",\n            \"documentation\": null,\n            \"features\": {},\n            \"homepage\": null,\n            \"keywords\": [],\n            \"license\": \"MIT\",\n            \"license_file\": null,\n            \"links\": null,\n            \"name\": \"foo\",\n            \"readme\": null,\n            \"readme_file\": null,\n            \"repository\": null,\n            \"homepage\": null,\n            \"documentation\": null,\n            \"rust_version\": null,\n            \"vers\": \"0.0.1\"\n        }\"#,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n    );\n}\n\n#[cargo_test]\nfn passwords_in_registries_index_url_forbidden() {\n    registry::alt_init();\n\n    let config = paths::home().join(\".cargo/config.toml\");\n\n    fs::write(\n        config,\n        r#\"\n        [registries.alternative]\n        index = \"ssh://git:secret@foobar.com\"\n        \"#,\n    )\n    .unwrap();\n\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"publish --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid index URL for registry `alternative` defined in [ROOT]/home/.cargo/config.toml\n\nCaused by:\n  registry URLs may not contain passwords\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patch_alt_reg() {\n    registry::alt_init();\n    Package::new(\"bar\", \"0.1.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"0.1.0\", registry = \"alternative\" }\n\n                [patch.alternative]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate bar;\n            pub fn f() { bar::bar(); }\n            \",\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_registry_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n                registry = \"bad name\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid character ` ` in registry name: `bad name`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)\n       \n       \n --> Cargo.toml:8:17\n  |\n8 |                 [dependencies.bar]\n  |                 ^^^^^^^^^^^^^^^^^^\n\n\"#]])\n        .run();\n\n    for cmd in &[\n        \"init\",\n        \"install foo\",\n        \"login\",\n        \"owner\",\n        \"publish\",\n        \"search\",\n        \"yank --version 0.0.1\",\n    ] {\n        p.cargo(cmd)\n            .arg(\"--registry\")\n            .arg(\"bad name\")\n            .with_status(101)\n            .with_stderr_data(str![[r#\"\n[ERROR] invalid character ` ` in registry name: `bad name`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)\n\n\"#]])\n            .run();\n    }\n}\n\n#[cargo_test]\nfn no_api() {\n    let _registry = RegistryBuilder::new().alternative().no_api().build();\n    Package::new(\"bar\", \"0.0.1\").alternative(true).publish();\n\n    // First check that a dependency works.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n                registry = \"alternative\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `alternative`)\n[CHECKING] bar v0.0.1 (registry `alternative`)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"login --registry alternative\")\n        .with_stdin(\"TOKEN\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] registry `alternative` does not support API commands\n\n\"#]])\n        .run();\n\n    p.cargo(\"publish --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] registry `alternative` does not support API commands\n\n\"#]])\n        .run();\n\n    p.cargo(\"search --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] registry `alternative` does not support API commands\n\n\"#]])\n        .run();\n\n    p.cargo(\"owner --registry alternative --list\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] registry `alternative` does not support API commands\n\n\"#]])\n        .run();\n\n    p.cargo(\"yank --registry alternative --version=0.0.1 bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] registry `alternative` does not support API commands\n\n\"#]])\n        .run();\n\n    p.cargo(\"yank --registry alternative --version=0.0.1 bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] registry `alternative` does not support API commands\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn alt_reg_metadata() {\n    // Check for \"registry\" entries in `cargo metadata` with alternative registries.\n    registry::alt_init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                altdep = { version = \"0.0.1\", registry = \"alternative\" }\n                iodep = { version = \"0.0.1\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n    Package::new(\"altdep\", \"0.0.1\")\n        .dep(\"bar\", \"0.0.1\")\n        .alternative(true)\n        .publish();\n    Package::new(\"altdep2\", \"0.0.1\").alternative(true).publish();\n    Package::new(\"iodep\", \"0.0.1\")\n        .registry_dep(\"altdep2\", \"0.0.1\")\n        .publish();\n\n    // The important thing to check here is the \"registry\" value in `deps`.\n    // They should be:\n    // foo -> altdep: alternative-registry\n    // foo -> iodep: null (because it is in crates.io)\n    // altdep -> bar: null (because it is in crates.io)\n    // iodep -> altdep2: alternative-registry\n    p.cargo(\"metadata --format-version=1 --no-deps\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"altdep\",\n          \"optional\": false,\n          \"registry\": \"[ROOTURL]/alternative-registry\",\n          \"rename\": null,\n          \"req\": \"^0.0.1\",\n          \"source\": \"registry+[ROOTURL]/alternative-registry\",\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"iodep\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"^0.0.1\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    }\n  ],\n  \"resolve\": null,\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.0.1\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.0.1\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n\n    // --no-deps uses a different code path, make sure both work.\n    p.cargo(\"metadata --format-version=1\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"bar\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"^0.0.1\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+[ROOTURL]/alternative-registry#altdep@0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/altdep-0.0.1/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"altdep\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+[ROOTURL]/alternative-registry\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"altdep\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/altdep-0.0.1/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+[ROOTURL]/alternative-registry#altdep2@0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/altdep2-0.0.1/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"altdep2\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+[ROOTURL]/alternative-registry\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"altdep2\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/altdep2-0.0.1/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"bar\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"altdep\",\n          \"optional\": false,\n          \"registry\": \"[ROOTURL]/alternative-registry\",\n          \"rename\": null,\n          \"req\": \"^0.0.1\",\n          \"source\": \"registry+[ROOTURL]/alternative-registry\",\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"iodep\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"^0.0.1\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"altdep2\",\n          \"optional\": false,\n          \"registry\": \"[ROOTURL]/alternative-registry\",\n          \"rename\": null,\n          \"req\": \"^0.0.1\",\n          \"source\": \"registry+[ROOTURL]/alternative-registry\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/iodep-0.0.1/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"iodep\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"iodep\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/iodep-0.0.1/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [\n          \"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"bar\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"registry+[ROOTURL]/alternative-registry#altdep@0.0.1\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+[ROOTURL]/alternative-registry#altdep2@0.0.1\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1\"\n      },\n      {\n        \"dependencies\": [\n          \"registry+[ROOTURL]/alternative-registry#altdep@0.0.1\",\n          \"registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"altdep\",\n            \"pkg\": \"registry+[ROOTURL]/alternative-registry#altdep@0.0.1\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"iodep\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.0.1\"\n      },\n      {\n        \"dependencies\": [\n          \"registry+[ROOTURL]/alternative-registry#altdep2@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"altdep2\",\n            \"pkg\": \"registry+[ROOTURL]/alternative-registry#altdep2@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.0.1\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.0.1\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.0.1\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn unknown_registry() {\n    // A known registry refers to an unknown registry.\n    // foo -> bar(crates.io) -> baz(alt)\n    registry::alt_init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"baz\", \"0.0.1\").alternative(true).publish();\n    Package::new(\"bar\", \"0.0.1\")\n        .registry_dep(\"baz\", \"0.0.1\")\n        .publish();\n\n    // Remove \"alternative\" from config.\n    let cfg_path = paths::home().join(\".cargo/config.toml\");\n    let mut config = fs::read_to_string(&cfg_path).unwrap();\n    let start = config.find(\"[registries.alternative]\").unwrap();\n    config.insert(start, '#');\n    let start_index = &config[start..].find(\"index =\").unwrap();\n    config.insert(start + start_index, '#');\n    fs::write(&cfg_path, config).unwrap();\n\n    p.cargo(\"check\").run();\n\n    // Important parts:\n    // foo -> bar registry = null\n    // bar -> baz registry = alternate\n    p.cargo(\"metadata --format-version=1\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"baz\",\n          \"optional\": false,\n          \"registry\": \"[ROOTURL]/alternative-registry\",\n          \"rename\": null,\n          \"req\": \"^0.0.1\",\n          \"source\": \"registry+[ROOTURL]/alternative-registry\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"bar\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+[ROOTURL]/alternative-registry#baz@0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/baz-0.0.1/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"baz\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+[ROOTURL]/alternative-registry\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"baz\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/baz-0.0.1/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"bar\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"^0.0.1\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/main.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [\n          \"registry+[ROOTURL]/alternative-registry#baz@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"baz\",\n            \"pkg\": \"registry+[ROOTURL]/alternative-registry#baz@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+[ROOTURL]/alternative-registry#baz@0.0.1\"\n      },\n      {\n        \"dependencies\": [\n          \"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"bar\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.0.1\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.0.1\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.0.1\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.0.1\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn registries_index_relative_url() {\n    registry::alt_init();\n    let config = paths::root().join(\".cargo/config.toml\");\n    fs::create_dir_all(config.parent().unwrap()).unwrap();\n    fs::write(\n        &config,\n        r#\"\n            [registries.relative]\n            index = \"file:alternative-registry\"\n        \"#,\n    )\n    .unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n                registry = \"relative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").alternative(true).publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `relative` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `relative`)\n[CHECKING] bar v0.0.1 (registry `relative`)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn registries_index_relative_path_not_allowed() {\n    registry::alt_init();\n    let config = paths::root().join(\".cargo/config.toml\");\n    fs::create_dir_all(config.parent().unwrap()).unwrap();\n    fs::write(\n        &config,\n        r#\"\n            [registries.relative]\n            index = \"alternative-registry\"\n        \"#,\n    )\n    .unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n                registry = \"relative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").alternative(true).publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  invalid index URL for registry `relative` defined in [ROOT]/.cargo/config.toml\n\nCaused by:\n  invalid url `alternative-registry`: relative URL without a base\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn both_index_and_registry() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    for cmd in &[\"publish\", \"owner\", \"search\", \"yank --version 1.0.0\"] {\n        p.cargo(cmd)\n            .arg(\"--registry=foo\")\n            .arg(\"--index=foo\")\n            .with_status(1)\n            .with_stderr_data(str![[r#\"\n[ERROR] the argument '--registry <REGISTRY>' cannot be used with '--index <INDEX>'\n\nUsage: [..]\n\nFor more information, try '--help'.\n\n\"#]])\n            .run();\n    }\n}\n\n#[cargo_test]\nfn both_index_and_default() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    for cmd in &[\n        \"publish\",\n        \"owner\",\n        \"search\",\n        \"yank --version 1.0.0\",\n        \"install foo\",\n    ] {\n        p.cargo(cmd)\n            .env(\"CARGO_REGISTRY_DEFAULT\", \"undefined\")\n            .arg(format!(\"--index=index_url\"))\n            .with_status(101)\n            .with_stderr_data(str![[r#\"\n[ERROR] invalid url `index_url`: relative URL without a base\n\n\"#]])\n            .run();\n    }\n}\n\n#[cargo_test]\nfn sparse_lockfile() {\n    let _registry = registry::RegistryBuilder::new()\n        .http_index()\n        .alternative()\n        .build();\n    Package::new(\"foo\", \"0.1.0\").alternative(true).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [project]\n                name = \"a\"\n                version = \"0.5.0\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies]\n                foo = { registry = 'alternative', version = '0.1.0'}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n    assert_e2e().eq(\n        &p.read_lockfile(),\n        str![[r##\"\n# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"a\"\nversion = \"0.5.0\"\ndependencies = [\n \"foo\",\n]\n\n[[package]]\nname = \"foo\"\nversion = \"0.1.0\"\nsource = \"sparse+http://127.0.0.1:[..]/index/\"\nchecksum = \"458c1addb23fde7dfbca0410afdbcc0086f96197281ec304d9e0e10def3cb899\"\n\n\"##]],\n    );\n}\n\n#[cargo_test]\nfn publish_with_transitive_dep() {\n    let _alt1 = RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative_named(\"Alt-1\")\n        .build();\n    let _alt2 = RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative_named(\"Alt-2\")\n        .build();\n\n    let p1 = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p1.cargo(\"publish --registry Alt-1\").run();\n\n    let p2 = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.6.0\"\n                publish = [\"Alt-2\"]\n                edition = \"2015\"\n\n                [dependencies]\n                a = { version = \"0.5.0\", registry = \"Alt-1\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p2.cargo(\"publish\").run();\n}\n\n#[cargo_test]\nfn warn_for_unused_fields() {\n    let _ = RegistryBuilder::new()\n        .no_configure_token()\n        .alternative()\n        .build();\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            \"[registry]\n            unexpected-field = 'foo'\n            [registries.alternative]\n            unexpected-field = 'foo'\n            \",\n        )\n        .build();\n\n    p.cargo(\"publish --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[WARNING] unused config key `registries.alternative.unexpected-field` in `[ROOT]/foo/.cargo/config.toml`\n[ERROR] no token found for `alternative`, please run `cargo login --registry alternative`\nor use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN\n\n\"#]])\n        .run();\n\n    let crates_io = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .build();\n    p.cargo(\"publish --registry crates-io\")\n        .replace_crates_io(crates_io.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] unused config key `registry.unexpected-field` in `[ROOT]/foo/.cargo/config.toml`\n[ERROR] no token found, please run `cargo login`\nor use environment variable CARGO_REGISTRY_TOKEN\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn config_empty_registry_name() {\n    let _ = RegistryBuilder::new()\n        .no_configure_token()\n        .alternative()\n        .build();\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            \"[registry.'']\n            \",\n        )\n        .build();\n\n    p.cargo(\"publish\")\n        .arg(\"--registry\")\n        .arg(\"\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] registry name cannot be empty\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn empty_registry_flag() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"publish\")\n        .arg(\"--registry\")\n        .arg(\"\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] registry name cannot be empty\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn empty_dependency_registry() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"0.1.0\", registry = \"\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate bar;\n            pub fn f() { bar::bar(); }\n            \",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] registry name cannot be empty\n       \n       \n --> Cargo.toml:8:23\n  |\n8 |                 bar = { version = \"0.1.0\", registry = \"\" }\n  |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/artifact_dep.rs",
    "content": "//! Tests specific to artifact dependencies, designated using\n//! the new `dep = { artifact = \"bin\", … }` syntax in manifests.\n\nuse crate::prelude::*;\nuse crate::utils::cross_compile::{\n    can_run_on_host as cross_compile_can_run_on_host, disabled as cross_compile_disabled,\n};\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::registry::{Package, RegistryBuilder};\nuse cargo_test_support::str;\nuse cargo_test_support::{\n    Project, basic_bin_manifest, basic_manifest, cross_compile, project, publish, registry,\n    rustc_host,\n};\n\n#[cargo_test]\nfn check_with_invalid_artifact_dependency() {\n    // invalid name\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"unknown\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\") // this would fail but we don't get there, artifacts are no libs\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  'unknown' is not a valid artifact specifier\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    fn run_cargo_with_and_without_bindeps_feature(\n        p: &Project,\n        cmd: &str,\n        assert: &dyn Fn(&mut cargo_test_support::Execs),\n    ) {\n        assert(\n            p.cargo(&format!(\"{} -Z bindeps\", cmd))\n                .masquerade_as_nightly_cargo(&[\"bindeps\"]),\n        );\n        assert(&mut p.cargo(cmd));\n    }\n\n    // lib specified without artifact\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar/\", lib = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n    run_cargo_with_and_without_bindeps_feature(&p, \"check\", &|cargo| {\n        cargo\n            .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  'lib' specifier cannot be used without an 'artifact = …' value (bar)\n\n\"#]])\n            .with_status(101)\n            .run();\n    });\n\n    // target specified without artifact\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar/\", target = \"target\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n    run_cargo_with_and_without_bindeps_feature(&p, \"check\", &|cargo| {\n        cargo\n            .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  'target' specifier cannot be used without an 'artifact = …' value (bar)\n\n\"#]])\n            .with_status(101)\n            .run();\n    })\n}\n\n#[cargo_test]\nfn check_with_invalid_target_triple() {\n    // invalid name\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\", target = \"unknown-target-triple\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  process didn't exit successfully: `rustc - --crate-name ___ --print=file-names --target unknown-target-triple [..]` ([EXIT_STATUS]: 1)\n  --- stderr\n...\n\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn build_without_nightly_aborts_with_error() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `artifact = …` requires `-Z bindeps` (bar)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn disallow_artifact_and_no_artifact_dep_to_same_package_within_the_same_dep_category() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\" }\n                bar_stable = { path = \"bar/\", package = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[WARNING] foo v0.0.0 ([ROOT]/foo) ignoring invalid dependency `bar_stable` which is missing a lib target\n[ERROR] the crate `foo v0.0.0 ([ROOT]/foo)` depends on crate `bar v0.5.0 ([ROOT]/foo/bar)` multiple times with different names\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn features_are_unified_among_lib_and_bin_dep_of_same_target() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies.d1]\n                path = \"d1\"\n                features = [\"d1f1\"]\n                artifact = \"bin\"\n                lib = true\n\n                [dependencies.d2]\n                path = \"d2\"\n                features = [\"d2f2\"]\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    d1::f1();\n                    d1::f2();\n                    d2::f1();\n                    d2::f2();\n                }\n            \"#,\n        )\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                d1f1 = [\"d2\"]\n\n                [dependencies.d2]\n                path = \"../d2\"\n                features = [\"d2f1\"]\n                optional = true\n            \"#,\n        )\n        .file(\n            \"d1/src/main.rs\",\n            r#\"fn main() {\n                #[cfg(feature = \"d1f1\")]\n                d2::f1();\n\n                // Using f2 is only possible as features are unififed across the same target.\n                // Our own manifest would only enable f1, and f2 comes in because a parent crate\n                // enables the feature in its manifest.\n                #[cfg(feature = \"d1f1\")]\n                d2::f2();\n            }\"#,\n        )\n        .file(\n            \"d1/src/lib.rs\",\n            r#\"\n            #[cfg(feature = \"d2\")]\n            extern crate d2;\n            /// Importing f2 here shouldn't be possible as unless features are unified.\n            #[cfg(feature = \"d1f1\")]\n            pub use d2::{f1, f2};\n        \"#,\n        )\n        .file(\n            \"d2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                d2f1 = []\n                d2f2 = []\n            \"#,\n        )\n        .file(\n            \"d2/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"d2f1\")] pub fn f1() {}\n                #[cfg(feature = \"d2f2\")] pub fn f2() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] d2 v0.0.1 ([ROOT]/foo/d2)\n[COMPILING] d1 v0.0.1 ([ROOT]/foo/d1)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn features_are_not_unified_among_lib_and_bin_dep_of_different_target() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies.d1]\n                path = \"d1\"\n                features = [\"d1f1\"]\n                artifact = \"bin\"\n                lib = true\n                target = \"$TARGET\"\n\n                [dependencies.d2]\n                path = \"d2\"\n                features = [\"d2f2\"]\n            \"#\n            .replace(\"$TARGET\", target),\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    // the lib = true part always builds for our current target, unifying dependencies\n                    d1::d2::f1();\n                    d1::d2::f2();\n                    d2::f1();\n                    d2::f2();\n                }\n            \"#,\n        )\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                d1f1 = [\"d2\"]\n\n                [dependencies.d2]\n                path = \"../d2\"\n                features = [\"d2f1\"]\n                optional = true\n            \"#,\n        )\n        .file(\"d1/src/main.rs\", r#\"fn main() {\n            // f1 we set ourselves\n            d2::f1();\n            // As 'main' is only compiled as part of the artifact dependency and since that is not unified\n            // if the target differs, trying to access f2 is a compile time error as the feature isn't enabled in our dependency tree.\n            d2::f2();\n        }\"#)\n        .file(\n            \"d1/src/lib.rs\",\n            r#\"\n            #[cfg(feature = \"d2\")]\n            pub extern crate d2;\n        \"#,\n        )\n        .file(\n            \"d2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                d2f1 = []\n                d2f2 = []\n            \"#,\n        )\n        .file(\n            \"d2/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"d2f1\")] pub fn f1() {}\n                #[cfg(feature = \"d2f2\")] pub fn f2() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] d2 v0.0.1 ([ROOT]/foo/d2)\n[COMPILING] d1 v0.0.1 ([ROOT]/foo/d1)\nerror[E0425]: cannot find function `f2` in crate `d2`\n...\n\nFor more information about this error, try `rustc --explain E0425`.\n[ERROR] could not compile `d1` (bin \"d1\") due to 1 previous error\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn feature_resolution_works_for_cfg_target_specification() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies.d1]\n                path = \"d1\"\n                artifact = \"bin\"\n                target = \"$TARGET\"\n            \"#\n            .replace(\"$TARGET\", target),\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_D1\"));\n                }\n            \"#,\n        )\n        .file(\n            \"d1/Cargo.toml\",\n            &r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'$TARGET'.dependencies]\n                d2 = { path = \"../d2\" }\n            \"#\n            .replace(\"$TARGET\", target),\n        )\n        .file(\n            \"d1/src/main.rs\",\n            r#\"fn main() {\n                d1::f();\n            }\"#,\n        )\n        .file(\"d1/build.rs\", r#\"fn main() { }\"#)\n        .file(\n            \"d1/src/lib.rs\",\n            &r#\"pub fn f() {\n                #[cfg(target = \"$TARGET\")]\n                d2::f();\n            }\n            \"#\n            .replace(\"$TARGET\", target),\n        )\n        .file(\n            \"d2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"d2/build.rs\", r#\"fn main() { }\"#)\n        .file(\"d2/src/lib.rs\", \"pub fn f() {}\")\n        .build();\n\n    p.cargo(\"test -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .run();\n}\n\n#[cargo_test]\nfn build_script_with_bin_artifacts() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [build-dependencies]\n                bar = { path = \"bar/\", artifact = [\"bin\", \"staticlib\", \"cdylib\"] }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", r#\"\n            fn main() {\n                let baz: std::path::PathBuf = std::env::var(\"CARGO_BIN_FILE_BAR_baz\").expect(\"CARGO_BIN_FILE_BAR_baz\").into();\n                println!(\"{}\", baz.display());\n                assert!(&baz.is_file());\n\n                let lib: std::path::PathBuf = std::env::var(\"CARGO_STATICLIB_FILE_BAR_bar\").expect(\"CARGO_STATICLIB_FILE_BAR_bar\").into();\n                println!(\"{}\", lib.display());\n                assert!(&lib.is_file());\n\n                let lib: std::path::PathBuf = std::env::var(\"CARGO_CDYLIB_FILE_BAR_bar\").expect(\"CARGO_CDYLIB_FILE_BAR_bar\").into();\n                println!(\"{}\", lib.display());\n                assert!(&lib.is_file());\n\n                let dir: std::path::PathBuf = std::env::var(\"CARGO_BIN_DIR_BAR\").expect(\"CARGO_BIN_DIR_BAR\").into();\n                println!(\"{}\", dir.display());\n                assert!(dir.is_dir());\n\n                let bar: std::path::PathBuf = std::env::var(\"CARGO_BIN_FILE_BAR\").expect(\"CARGO_BIN_FILE_BAR\").into();\n                println!(\"{}\", bar.display());\n                assert!(&bar.is_file());\n\n                let bar2: std::path::PathBuf = std::env::var(\"CARGO_BIN_FILE_BAR_bar\").expect(\"CARGO_BIN_FILE_BAR_bar\").into();\n                println!(\"{}\", bar2.display());\n                assert_eq!(bar, bar2);\n            }\n        \"#)\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                crate-type = [\"staticlib\", \"cdylib\"]\n            \"#,\n        )\n        // compilation target is native for build scripts unless overridden\n        .file(\"bar/src/bin/bar.rs\", &format!(r#\"fn main() {{ assert_eq!(std::env::var(\"TARGET\").unwrap(), \"{}\"); }}\"#, cross_compile::native()))\n        .file(\"bar/src/bin/baz.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    let build_script_output = build_script_output_string(&p, \"foo\");\n    // we need the binary directory for this artifact along with all binary paths\n    if cfg!(target_env = \"msvc\") {\n        assert_e2e().eq(\n            &build_script_output,\n            str![[r#\"\n[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin/baz[EXE]\n[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/staticlib/bar-[HASH].lib\n[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/cdylib/bar.dll\n[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin\n[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin/bar[EXE]\n[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin/bar[EXE]\n\n\"#]],\n        );\n    } else {\n        assert_e2e().eq(\n            &build_script_output,\n            str![[r#\"\n[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin/baz-[HASH][EXE]\n[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/staticlib/libbar-[HASH].a\n[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/cdylib/[..]bar.[..]\n[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin\n[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin/bar-[HASH][EXE]\n[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin/bar-[HASH][EXE]\n\n\"#]],\n        );\n    }\n\n    assert!(\n        !p.bin(\"bar\").is_file(),\n        \"artifacts are located in their own directory, exclusively, and won't be lifted up\"\n    );\n    assert!(!p.bin(\"baz\").is_file(),);\n    assert_artifact_executable_output(&p, \"debug\", \"bar\", \"bar\");\n}\n\n#[cargo_test]\nfn build_script_with_bin_artifact_and_lib_false() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [build-dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n               bar::doit()\n            }\n        \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() { bar::doit(); }\")\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n            pub fn doit() {\n               panic!(\"sentinel\");\n            }\n        \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_status(101)\n        .with_stderr_does_not_contain(\"[..]sentinel[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn lib_with_bin_artifact_and_lib_false() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn foo() {\n               bar::doit()\n            }\"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() { bar::doit(); }\")\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n            pub fn doit() {\n               panic!(\"sentinel\");\n            }\n        \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_status(101)\n        .with_stderr_does_not_contain(\"[..]sentinel[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn build_script_with_selected_dashed_bin_artifact_and_lib_true() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [build-dependencies]\n                bar-baz = { path = \"bar/\", artifact = \"bin:baz-suffix\", lib = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", r#\"\n            fn main() {\n               bar_baz::print_env()\n            }\n        \"#)\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar-baz\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"bar\"\n\n                [[bin]]\n                name = \"baz-suffix\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", r#\"\n            pub fn print_env() {\n                let dir: std::path::PathBuf = std::env::var(\"CARGO_BIN_DIR_BAR_BAZ\").expect(\"CARGO_BIN_DIR_BAR_BAZ\").into();\n                let bin: std::path::PathBuf = std::env::var(\"CARGO_BIN_FILE_BAR_BAZ_baz-suffix\").expect(\"CARGO_BIN_FILE_BAR_BAZ_baz-suffix\").into();\n                println!(\"{}\", dir.display());\n                println!(\"{}\", bin.display());\n                assert!(dir.is_dir());\n                assert!(&bin.is_file());\n                assert!(std::env::var(\"CARGO_BIN_FILE_BAR_BAZ\").is_err(), \"CARGO_BIN_FILE_BAR_BAZ isn't set due to name mismatch\");\n                assert!(std::env::var(\"CARGO_BIN_FILE_BAR_BAZ_bar\").is_err(), \"CARGO_BIN_FILE_BAR_BAZ_bar isn't set as binary isn't selected\");\n            }\n        \"#)\n        .build();\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar-baz v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let build_script_output = build_script_output_string(&p, \"foo\");\n    // we need the binary directory for this artifact and the binary itself\n    if cfg!(target_env = \"msvc\") {\n        assert_e2e().eq(\n            &build_script_output,\n            str![[r#\"\n[ROOT]/foo/target/debug/deps/artifact/bar-baz-[HASH]/bin\n[ROOT]/foo/target/debug/deps/artifact/bar-baz-[HASH]/bin/baz_suffix[EXE]\n\n\"#]],\n        );\n    } else {\n        assert_e2e().eq(\n            &build_script_output,\n            str![[r#\"\n[ROOT]/foo/target/debug/deps/artifact/bar-baz-[HASH]/bin\n[ROOT]/foo/target/debug/deps/artifact/bar-baz-[HASH]/bin/baz_suffix-[HASH][EXE]\n\n\"#]],\n        );\n    }\n\n    assert!(\n        !p.bin(\"bar\").is_file(),\n        \"artifacts are located in their own directory, exclusively, and won't be lifted up\"\n    );\n    assert_artifact_executable_output(&p, \"debug\", \"bar\", \"baz_suffix\");\n}\n\n#[cargo_test]\nfn lib_with_selected_dashed_bin_artifact_and_lib_true() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar-baz = { path = \"bar/\", artifact = [\"bin:baz-suffix\", \"staticlib\", \"cdylib\"], lib = true }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn foo() {\n                bar_baz::exists();\n\n                env!(\"CARGO_BIN_DIR_BAR_BAZ\");\n                let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR_BAZ_baz-suffix\"));\n                let _b = include_bytes!(env!(\"CARGO_STATICLIB_FILE_BAR_BAZ\"));\n                let _b = include_bytes!(env!(\"CARGO_STATICLIB_FILE_BAR_BAZ_bar-baz\"));\n                let _b = include_bytes!(env!(\"CARGO_STATICLIB_FILE_BAR_BAZ_bar_baz\"));\n                let _b = include_bytes!(env!(\"CARGO_CDYLIB_FILE_BAR_BAZ\"));\n                let _b = include_bytes!(env!(\"CARGO_CDYLIB_FILE_BAR_BAZ_bar-baz\"));\n                let _b = include_bytes!(env!(\"CARGO_CDYLIB_FILE_BAR_BAZ_bar_baz\"));\n            }\n        \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar-baz\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                crate-type = [\"rlib\", \"staticlib\", \"cdylib\"]\n\n                [[bin]]\n                name = \"bar\"\n\n                [[bin]]\n                name = \"baz-suffix\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"pub fn exists() {}\")\n        .build();\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar-baz v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(\n        !p.bin(\"bar\").is_file(),\n        \"artifacts are located in their own directory, exclusively, and won't be lifted up\"\n    );\n    assert_artifact_executable_output(&p, \"debug\", \"bar\", \"baz_suffix\");\n}\n\n#[cargo_test]\nfn allow_artifact_and_no_artifact_dep_to_same_package_within_different_dep_categories() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\" }\n\n                [dev-dependencies]\n                bar = { path = \"bar/\", package = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            #[cfg(test)] extern crate bar;\n            pub fn foo() {\n                env!(\"CARGO_BIN_DIR_BAR\");\n                let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR\"));\n            }\"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"test -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn normal_build_deps_are_picked_up_in_presence_of_an_artifact_build_dep_to_the_same_package() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar\", artifact = \"bin:bar\" }\n\n                [build-dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() { bar::f(); }\")\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn foo() {\n                env!(\"CARGO_BIN_DIR_BAR\");\n                let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR\"));\n            }\"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"pub fn f() {}\")\n        .build();\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .run();\n}\n\n#[cargo_test]\nfn disallow_using_example_binaries_as_artifacts() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"bin:one-example\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/examples/one-example.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ERROR] dependency `bar` in package `foo` requires a `bin:one-example` artifact to be present.\n\n\"#]])\n        .run();\n}\n\n/// From RFC 3028\n///\n/// > You may also specify separate dependencies with different artifact values, as well as\n/// dependencies on the same crate without artifact specified; for instance, you may have a\n/// build dependency on the binary of a crate and a normal dependency on the Rust library of the same crate.\n#[cargo_test]\nfn allow_artifact_and_non_artifact_dependency_to_same_crate() {\n    let p = project()\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [build-dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\" }\n\n                [dependencies]\n                bar = { path = \"bar/\" }\n            \"#,\n            )\n            .file(\"src/lib.rs\", r#\"\n                    pub fn foo() {\n                         bar::doit();\n                         assert!(option_env!(\"CARGO_BIN_FILE_BAR\").is_none());\n                    }\"#)\n            .file(\n                \"build.rs\",\n                r#\"\n                fn main() {\n                     assert!(option_env!(\"CARGO_BIN_FILE_BAR\").is_none(), \"no environment variables at build time\");\n                     std::process::Command::new(std::env::var(\"CARGO_BIN_FILE_BAR\").expect(\"BAR present\")).status().unwrap();\n                }\"#,\n            )\n            .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n            .file(\"bar/src/main.rs\", \"fn main() {}\")\n            .file(\"bar/src/lib.rs\", \"pub fn doit() {}\")\n        .build();\n\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_script_deps_adopt_specified_target_unconditionally() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [build-dependencies.bar]\n                path = \"bar/\"\n                artifact = \"bin\"\n                target = \"{}\"\n            \"#,\n                target\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", r#\"\n                fn main() {\n                    let bar: std::path::PathBuf = std::env::var(\"CARGO_BIN_FILE_BAR\").expect(\"CARGO_BIN_FILE_BAR\").into();\n                    assert!(&bar.is_file());\n                }\"#)\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"pub fn doit() {}\")\n        .build();\n\n    p.cargo(\"check -v -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_does_not_contain(\n            \"[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--target [ALT_TARGET] [..]\",\n        )\n        .with_stderr_contains(\"[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]\")\n        .with_stderr_contains(\n            \"[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--target [ALT_TARGET] [..]\",\n        )\n        .with_stderr_contains(\n            \"[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..]--target [ALT_TARGET] [..]\",\n        )\n        .with_stderr_does_not_contain(\n            \"[RUNNING] `rustc --crate-name foo [..]--target [ALT_TARGET] [..]\",\n        )\n        .with_stderr_contains(\"[RUNNING] `rustc --crate-name foo [..]\")\n        .run();\n}\n\n/// inverse RFC-3176\n#[cargo_test]\nfn build_script_deps_adopt_do_not_allow_multiple_targets_under_different_name_and_same_version() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let alternate = cross_compile::alternate();\n    let native = cross_compile::native();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [build-dependencies.bar]\n                path = \"bar/\"\n                artifact = \"bin\"\n                target = \"{}\"\n\n                [build-dependencies.bar-native]\n                package = \"bar\"\n                path = \"bar/\"\n                artifact = \"bin\"\n                target = \"{}\"\n            \"#,\n                alternate,\n                native\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", r#\"\n                fn main() {\n                    let bar: std::path::PathBuf = std::env::var(\"CARGO_BIN_FILE_BAR\").expect(\"CARGO_BIN_FILE_BAR\").into();\n                    assert!(&bar.is_file());\n                    let bar_native: std::path::PathBuf = std::env::var(\"CARGO_BIN_FILE_BAR_NATIVE_bar\").expect(\"CARGO_BIN_FILE_BAR_NATIVE_bar\").into();\n                    assert!(&bar_native.is_file());\n                    assert_ne!(bar_native, bar, \"should build different binaries due to different targets\");\n                }\"#)\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ERROR] the crate `foo v0.0.0 ([ROOT]/foo)` depends on crate `bar v0.5.0 ([ROOT]/foo/bar)` multiple times with different names\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn non_build_script_deps_adopt_specified_target_unconditionally() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies.bar]\n                path = \"bar/\"\n                artifact = \"bin\"\n                target = \"{}\"\n            \"#,\n                target\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"pub fn foo() { let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR\")); }\"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"pub fn doit() {}\")\n        .build();\n\n    p.cargo(\"check -v -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_contains(\n            \"[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--target [ALT_TARGET] [..]\",\n        )\n        .with_stderr_contains(\n            \"[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..]--target [ALT_TARGET] [..]\",\n        )\n        .with_stderr_does_not_contain(\n            \"[RUNNING] `rustc --crate-name foo [..]--target [ALT_TARGET] [..]\",\n        )\n        .with_stderr_contains(\"[RUNNING] `rustc --crate-name foo [..]\")\n        .run();\n}\n\n#[cargo_test]\nfn cross_doctests_works_with_artifacts() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\", lib = true }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! ```\n                //! env!(\"CARGO_BIN_DIR_BAR\");\n                //! let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR\"));\n                //! ```\n                pub fn foo() {\n                    env!(\"CARGO_BIN_DIR_BAR\");\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR\"));\n                }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", r#\"pub extern \"C\" fn c() {}\"#)\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    let target = rustc_host();\n    p.cargo(\"test -Z bindeps --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/[HOST_TARGET]/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .run();\n\n    println!(\"c\");\n    let target = cross_compile::alternate();\n\n    if !cross_compile_can_run_on_host() {\n        return;\n    }\n\n    p.cargo(\"test -Z bindeps -v --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--target [ALT_TARGET] [..]\n[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..]--target [ALT_TARGET] [..]\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[RUNNING] `rustc --crate-name foo [..]\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `rustdoc [..]--test src/lib.rs --test-run-directory [ROOT]/foo --target [ALT_TARGET] [..]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_script_deps_adopts_target_platform_if_target_equals_target() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [build-dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\", target = \"target\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", r#\"\n                fn main() {\n                    let bar: std::path::PathBuf = std::env::var(\"CARGO_BIN_FILE_BAR\").expect(\"CARGO_BIN_FILE_BAR\").into();\n                    assert!(&bar.is_file());\n                }\"#)\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"pub fn doit() {}\")\n        .build();\n\n    let alternate_target = cross_compile::alternate();\n    p.cargo(\"check -v -Z bindeps --target\")\n        .arg(alternate_target)\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_does_not_contain(\n            \"[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--target [ALT_TARGET] [..]\",\n        )\n        .with_stderr_contains(\"[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]\")\n        .with_stderr_contains(\n            \"[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--target [ALT_TARGET] [..]\",\n        )\n        .with_stderr_contains(\n            \"[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..]--target [ALT_TARGET] [..]\",\n        )\n        .with_stderr_contains(\n            \"[RUNNING] `rustc --crate-name foo [..]--target [ALT_TARGET] [..]\",\n        )\n        .run();\n}\n\n#[cargo_test]\n// TODO(ST): rename bar (dependency) to something else and un-ignore this with RFC-3176\n#[cfg_attr(target_env = \"msvc\", ignore = \"msvc not working\")]\nfn profile_override_basic() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [build-dependencies]\n                bar = { path = \"bar\", artifact = \"bin\" }\n\n                [dependencies]\n                bar = { path = \"bar\", artifact = \"bin\" }\n\n                [profile.dev.build-override]\n                opt-level = 1\n\n                [profile.dev]\n                opt-level = 3\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"build -v -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name build_script_build [..] -C opt-level=1 [..]`\n[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..] -C opt-level=3 [..]`\n[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..] -C opt-level=1 [..]`\n[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..] -C opt-level=1 [..]`\n[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..] -C opt-level=3 [..]`\n[RUNNING] `rustc --crate-name foo [..] -C opt-level=3 [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[FINISHED] `dev` profile [optimized + debuginfo] target(s) in [ELAPSED]s\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn dependencies_of_dependencies_work_in_artifacts() {\n    Package::new(\"baz\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"pub fn baz() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [build-dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                std::process::Command::new(std::env::var(\"CARGO_BIN_FILE_BAR\").expect(\"BAR present\")).status().unwrap();\n            }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"1.0.0\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", r#\"pub fn bar() {baz::baz()}\"#)\n        .file(\"bar/src/main.rs\", r#\"fn main() {bar::bar()}\"#)\n        .build();\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .run();\n\n    // cargo tree sees artifacts as the dependency kind they are in and doesn't do anything special with it.\n    p.cargo(\"tree -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stdout_data(str![[r#\"\nfoo v0.0.0 ([ROOT]/foo)\n[build-dependencies]\n└── bar v0.5.0 ([ROOT]/foo/bar)\n    └── baz v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn artifact_dep_target_specified() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let target = cross_compile::alternate();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                authors = []\n                resolver = \"2\"\n                edition = \"2015\"\n\n                [dependencies]\n                bindep = { path = \"bindep\", artifact = \"bin\", target = \"$TARGET\" }\n            \"#\n            .replace(\"$TARGET\", target),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bindep/Cargo.toml\", &basic_manifest(\"bindep\", \"0.0.0\"))\n        .file(\"bindep/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bindep v0.0.0 ([ROOT]/foo/bindep)\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_status(0)\n        .run();\n\n    p.cargo(\"tree -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stdout_data(str![[r#\"\nfoo v0.0.0 ([ROOT]/foo)\n└── bindep v0.0.0 ([ROOT]/foo/bindep)\n\n\"#]])\n        .with_status(0)\n        .run();\n}\n\n/// From issue #10593\n/// The case where:\n/// *   artifact dep is { target = <specified> }\n/// *   dependency of that artifact dependency specifies the same target\n/// *   the target is not activated.\n#[cargo_test]\nfn dep_of_artifact_dep_same_target_specified() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n                    resolver = \"2\"\n\n                    [dependencies]\n                    bar = {{ path = \"bar\", artifact = \"bin\", target = \"{target}\" }}\n                \"#,\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"bar\"\n                    version = \"0.1.0\"\n\n                    [target.{target}.dependencies]\n                    baz = {{ path = \"../baz\" }}\n                \"#,\n            ),\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.0\"\n\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] baz v0.1.0 ([ROOT]/foo/baz)\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_status(0)\n        .run();\n\n    p.cargo(\"tree -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stdout_data(\n            r#\"...\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v0.1.0 ([ROOT]/foo/bar)\n    └── baz v0.1.0 ([ROOT]/foo/baz)\n\"#,\n        )\n        .with_status(0)\n        .run();\n}\n\n#[cargo_test]\nfn targets_are_picked_up_from_non_workspace_artifact_deps() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let target = cross_compile::alternate();\n    Package::new(\"artifact\", \"1.0.0\")\n        .file(\"src/main.rs\", r#\"fn main() {}\"#)\n        .file(\"src/lib.rs\", r#\"pub fn lib() {}\"#)\n        .publish();\n\n    let mut dep = registry::Dependency::new(\"artifact\", \"1.0.0\");\n    Package::new(\"uses-artifact\", \"1.0.0\")\n        .schema_version(3)\n        .file(\n            \"src/lib.rs\",\n            r#\"pub fn uses_artifact() { let _b = include_bytes!(env!(\"CARGO_BIN_FILE_ARTIFACT\")); }\"#,\n        )\n        .add_dep(dep.artifact(\"bin\", Some(target.to_string())))\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                uses-artifact = { version = \"1.0.0\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"pub fn foo() { uses_artifact::uses_artifact(); }\"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .run();\n}\n\n#[cargo_test]\nfn index_version_filtering() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let target = cross_compile::alternate();\n\n    Package::new(\"artifact\", \"1.0.0\")\n        .file(\"src/main.rs\", r#\"fn main() {}\"#)\n        .file(\"src/lib.rs\", r#\"pub fn lib() {}\"#)\n        .publish();\n\n    let mut dep = registry::Dependency::new(\"artifact\", \"1.0.0\");\n\n    Package::new(\"bar\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.1\")\n        .schema_version(3)\n        .add_dep(dep.artifact(\"bin\", Some(target.to_string())))\n        .publish();\n\n    // Verify that without `-Zbindeps` that it does not use 1.0.1.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v1.0.0\n\n\"#]])\n        .run();\n\n    // And with -Zbindeps it can use 1.0.1.\n    p.cargo(\"update -Zbindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[ADDING] artifact v1.0.0\n[UPDATING] bar v1.0.0 -> v1.0.1\n\n\"#]])\n        .run();\n\n    // And without -Zbindeps, now that 1.0.1 is in Cargo.lock, it should fail.\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `bar = \"^1.0\"` (locked to 1.0.1)\n  version 1.0.1 requires a Cargo version that supports index version 3\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.1.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn proc_macro_in_artifact_dep() {\n    // Forcing FeatureResolver to check a proc-macro for a dependency behind a\n    // target dependency.\n    if cross_compile_disabled() {\n        return;\n    }\n    Package::new(\"pm\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pm\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n\n                [lib]\n                proc-macro = true\n\n            \"#,\n        )\n        .publish();\n    let alternate = cross_compile::alternate();\n    Package::new(\"bin-uses-pm\", \"1.0.0\")\n        .target_dep(\"pm\", \"1.0\", alternate)\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .publish();\n    // Simulate a network error downloading the proc-macro.\n    std::fs::remove_file(cargo_test_support::paths::root().join(\"dl/pm/1.0.0/download\")).unwrap();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                bin-uses-pm = {{ version = \"1.0\", artifact = \"bin\", target = \"{alternate}\"}}\n            \"#\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(\n            r#\"...\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[ERROR] failed to download from `[ROOTURL]/dl/pm/1.0.0/download`\n\nCaused by:\n  [37] Could[..]t read a file:// file (Could[..]t open file [ROOT]/dl/pm/1.0.0/download)\n\"#,\n        )\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn allow_dep_renames_with_multiple_versions() {\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/main.rs\", r#\"fn main() {println!(\"1.0.0\")}\"#)\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [build-dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\" }\n                bar_stable = { package = \"bar\", version = \"1.0.0\", artifact = \"bin\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                std::process::Command::new(std::env::var(\"CARGO_BIN_FILE_BAR\").expect(\"BAR present\")).status().unwrap();\n                std::process::Command::new(std::env::var(\"CARGO_BIN_FILE_BAR_STABLE_bar\").expect(\"BAR STABLE present\")).status().unwrap();\n            }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", r#\"fn main() {println!(\"0.5.0\")}\"#)\n        .build();\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[COMPILING] bar v1.0.0\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    let build_script_output = build_script_output_string(&p, \"foo\");\n    assert_e2e().eq(\n        &build_script_output,\n        str![[r#\"\n0.5.0\n1.0.0\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn allow_artifact_and_non_artifact_dependency_to_same_crate_if_these_are_not_the_same_dep_kind() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [build-dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\", lib = false }\n\n                [dependencies]\n                bar = { path = \"bar/\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\"\n            pub fn foo() {\n                bar::doit();\n                assert!(option_env!(\"CARGO_BIN_FILE_BAR\").is_none());\n            }\"#)\n        .file(\n            \"build.rs\",\n            r#\"fn main() {\n               println!(\"{}\", std::env::var(\"CARGO_BIN_FILE_BAR\").expect(\"CARGO_BIN_FILE_BAR\"));\n               println!(\"{}\", std::env::var(\"CARGO_BIN_FILE_BAR_bar\").expect(\"CARGO_BIN_FILE_BAR_bar\"));\n           }\"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn doit() {}\")\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn prevent_no_lib_warning_with_artifact_dependencies() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"pub fn foo() { let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR\")); }\"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn show_no_lib_warning_with_artifact_dependencies_that_have_no_lib_but_lib_true() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [build-dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\" }\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\", lib = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/build.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[WARNING] foo v0.0.0 ([ROOT]/foo) ignoring invalid dependency `bar` which is missing a lib target\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn resolver_2_build_dep_without_lib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                authors = []\n                edition = \"2021\"\n\n                [build-dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", r#\"\n                fn main() {\n                    let bar: std::path::PathBuf = std::env::var(\"CARGO_BIN_FILE_BAR\").expect(\"CARGO_BIN_FILE_BAR\").into();\n                    assert!(&bar.is_file());\n                }\"#)\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .run();\n}\n\n#[cargo_test]\nfn check_missing_crate_type_in_package_fails() {\n    for crate_type in &[\"cdylib\", \"staticlib\", \"bin\"] {\n        let p = project()\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n                        [package]\n                        name = \"foo\"\n                        version = \"0.0.0\"\n                        edition = \"2015\"\n                        authors = []\n\n                        [dependencies]\n                        bar = {{ path = \"bar/\", artifact = \"{}\" }}\n                    \"#,\n                    crate_type\n                ),\n            )\n            .file(\"src/lib.rs\", \"\")\n            .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\")) //no bin, just rlib\n            .file(\"bar/src/lib.rs\", \"\")\n            .build();\n        p.cargo(\"check -Z bindeps\")\n            .masquerade_as_nightly_cargo(&[\"bindeps\"])\n            .with_status(101)\n            .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ERROR] dependency `bar` in package `foo` requires a [..] artifact to be present.\n\n\"#]])\n            .run();\n    }\n}\n\n#[cargo_test]\nfn check_target_equals_target_in_non_build_dependency_errors() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\", target = \"target\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `target = \"target\"` in normal- or dev-dependencies has no effect (bar)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_vars_and_build_products_for_various_build_targets() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [lib]\n                doctest = true\n\n                [build-dependencies]\n                bar = { path = \"bar/\", artifact = [\"cdylib\", \"staticlib\"] }\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\", lib = true }\n\n                [dev-dependencies]\n                bar = { path = \"bar/\", artifact = \"bin:baz\" }\n            \"#,\n        )\n        .file(\"build.rs\", r#\"\n            fn main() {\n                let file: std::path::PathBuf = std::env::var(\"CARGO_CDYLIB_FILE_BAR\").expect(\"CARGO_CDYLIB_FILE_BAR\").into();\n                assert!(&file.is_file());\n\n                let file: std::path::PathBuf = std::env::var(\"CARGO_STATICLIB_FILE_BAR\").expect(\"CARGO_STATICLIB_FILE_BAR\").into();\n                assert!(&file.is_file());\n\n                assert!(std::env::var(\"CARGO_BIN_FILE_BAR\").is_err());\n                assert!(std::env::var(\"CARGO_BIN_FILE_BAR_baz\").is_err());\n            }\n        \"#)\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! ```\n                //! bar::c();\n                //! env!(\"CARGO_BIN_DIR_BAR\");\n                //! let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR\"));\n                //! let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR_bar\"));\n                //! let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR_baz\"));\n                //! assert!(option_env!(\"CARGO_STATICLIB_FILE_BAR\").is_none());\n                //! assert!(option_env!(\"CARGO_CDYLIB_FILE_BAR\").is_none());\n                //! ```\n                pub fn foo() {\n                    bar::c();\n                    env!(\"CARGO_BIN_DIR_BAR\");\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR\"));\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR_bar\"));\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR_baz\"));\n                    assert!(option_env!(\"CARGO_STATICLIB_FILE_BAR\").is_none());\n                    assert!(option_env!(\"CARGO_CDYLIB_FILE_BAR\").is_none());\n                }\n\n                #[cfg(test)]\n                #[test]\n                fn env_unit() {\n                    env!(\"CARGO_BIN_DIR_BAR\");\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR\"));\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR_bar\"));\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR_baz\"));\n                    assert!(option_env!(\"CARGO_STATICLIB_FILE_BAR\").is_none());\n                    assert!(option_env!(\"CARGO_CDYLIB_FILE_BAR\").is_none());\n                }\n               \"#,\n        )\n        .file(\n            \"tests/main.rs\",\n            r#\"\n                #[test]\n                fn env_integration() {\n                    env!(\"CARGO_BIN_DIR_BAR\");\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR\"));\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR_bar\"));\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR_baz\"));\n                }\"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                crate-type = [\"staticlib\", \"cdylib\", \"rlib\"]\n\n                [[bin]]\n                name = \"bar\"\n\n                [[bin]]\n                name = \"baz\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", r#\"pub extern \"C\" fn c() {}\"#)\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"test -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[RUNNING] tests/main.rs (target/debug/deps/main-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_artifact_dep() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    Package::new(\"bar\", \"1.0.0\").publish();\n    Package::new(\"baz\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"foo\"\n            documentation = \"foo\"\n            homepage = \"foo\"\n            repository = \"foo\"\n            resolver = \"2\"\n\n            [dependencies]\n            bar = { version = \"1.0\", artifact = \"bin\", lib = true }\n\n            [build-dependencies]\n            baz = { version = \"1.0\", artifact = [\"bin:a\", \"cdylib\", \"staticlib\"], target = \"target\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish -Z bindeps --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] foo v0.1.0 ([ROOT]/foo)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.1.0 ([ROOT]/foo)\n[UPLOADED] foo v0.1.0 to registry `crates-io`\n[NOTE] waiting for foo v0.1.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.1.0 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    publish::validate_upload_with_contents(\n        r#\"\n        {\n          \"authors\": [],\n          \"badges\": {},\n          \"categories\": [],\n          \"deps\": [{\n              \"artifact\": [\"bin\"],\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"normal\",\n              \"lib\": true,\n              \"name\": \"bar\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"artifact\": [\n                \"bin:a\",\n                \"cdylib\",\n                \"staticlib\"\n              ],\n              \"bindep_target\": \"target\",\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"build\",\n              \"name\": \"baz\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            }\n          ],\n          \"description\": \"foo\",\n          \"documentation\": \"foo\",\n          \"features\": {},\n          \"homepage\": \"foo\",\n          \"keywords\": [],\n          \"license\": \"MIT\",\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"foo\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": \"foo\",\n          \"rust_version\": null,\n          \"vers\": \"0.1.0\"\n        }\n        \"#,\n        \"foo-0.1.0.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\", \"Cargo.lock\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.1.0\"\nauthors = []\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\nhomepage = \"foo\"\ndocumentation = \"foo\"\nreadme = false\nlicense = \"MIT\"\nrepository = \"foo\"\nresolver = \"2\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n[dependencies.bar]\nversion = \"1.0\"\nartifact = [\"bin\"]\nlib = true\n\n[build-dependencies.baz]\nversion = \"1.0\"\nartifact = [\n    \"bin:a\",\n    \"cdylib\",\n    \"staticlib\",\n]\ntarget = \"target\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn doc_lib_true() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies.bar]\n                path = \"bar\"\n                artifact = \"bin\"\n                lib = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar; pub fn foo() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"doc -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    assert!(p.root().join(\"target/doc\").is_dir());\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/bar/index.html\").is_file());\n\n    // Verify that it emits rmeta for the bin and lib dependency.\n    assert_eq!(p.glob(\"target/debug/artifact/*.rlib\").count(), 0);\n    assert_eq!(p.glob(\"target/debug/deps/libbar-*.rmeta\").count(), 2);\n\n    p.cargo(\"doc -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    assert!(p.root().join(\"target/doc\").is_dir());\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/bar/index.html\").is_file());\n}\n\n#[cargo_test]\nfn rustdoc_works_on_libs_with_artifacts_and_lib_false() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies.bar]\n                path = \"bar\"\n                artifact = [\"bin\", \"staticlib\", \"cdylib\"]\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn foo() {\n                env!(\"CARGO_BIN_DIR_BAR\");\n                let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR\"));\n                let _b = include_bytes!(env!(\"CARGO_CDYLIB_FILE_BAR\"));\n                let _b = include_bytes!(env!(\"CARGO_CDYLIB_FILE_BAR_bar\"));\n                let _b = include_bytes!(env!(\"CARGO_STATICLIB_FILE_BAR\"));\n                let _b = include_bytes!(env!(\"CARGO_STATICLIB_FILE_BAR_bar\"));\n            }\"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                crate-type = [\"staticlib\", \"cdylib\"]\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"doc -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    assert!(p.root().join(\"target/doc\").is_dir());\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(\n        !p.root().join(\"target/doc/bar/index.html\").is_file(),\n        \"bar is not a lib dependency and thus remains undocumented\"\n    );\n}\n\nfn assert_artifact_executable_output(\n    p: &Project,\n    target_name: &str,\n    dep_name: &str,\n    bin_name: &str,\n) {\n    if cfg!(target_env = \"msvc\") {\n        assert_eq!(\n            p.glob(format!(\n                \"target/{}/deps/artifact/{}-*/bin/{}{}\",\n                target_name,\n                dep_name,\n                bin_name,\n                std::env::consts::EXE_SUFFIX\n            ))\n            .count(),\n            1,\n            \"artifacts are placed into their own output directory to not possibly clash\"\n        );\n    } else {\n        assert_eq!(\n            p.glob(format!(\n                \"target/{}/deps/artifact/{}-*/bin/{}-*{}\",\n                target_name,\n                dep_name,\n                bin_name,\n                std::env::consts::EXE_SUFFIX\n            ))\n            .filter_map(Result::ok)\n            .filter(|f| f.extension().map_or(true, |ext| ext != \"o\" && ext != \"d\"))\n            .count(),\n            1,\n            \"artifacts are placed into their own output directory to not possibly clash\"\n        );\n    }\n}\n\nfn build_script_output_string(p: &Project, package_name: &str) -> String {\n    let paths = p\n        .glob(format!(\"target/debug/build/{}-*/output\", package_name))\n        .collect::<Result<Vec<_>, _>>()\n        .unwrap();\n    assert_eq!(paths.len(), 1);\n    std::fs::read_to_string(&paths[0]).unwrap()\n}\n\n#[cargo_test]\nfn build_script_features_for_shared_dependency() {\n    // When a build script is built and run, its features should match. Here:\n    //\n    // foo\n    //   -> artifact on d1 with target\n    //   -> common with features f1\n    //\n    // d1\n    //   -> common with features f2\n    //\n    // common has features f1 and f2, with a build script.\n    //\n    // When common is built as a dependency of d1, it should have features\n    // `f2` (for the library and the build script).\n    //\n    // When common is built as a dependency of foo, it should have features\n    // `f1` (for the library and the build script).\n    if cross_compile_disabled() {\n        return;\n    }\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                resolver = \"2\"\n\n                [dependencies]\n                d1 = { path = \"d1\", artifact = \"bin\", target = \"$TARGET\" }\n                common = { path = \"common\", features = [\"f1\"] }\n            \"#\n            .replace(\"$TARGET\", target),\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_D1\"));\n                    common::f1();\n                }\n            \"#,\n        )\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                common = { path = \"../common\", features = [\"f2\"] }\n            \"#,\n        )\n        .file(\n            \"d1/src/main.rs\",\n            r#\"fn main() {\n                common::f2();\n            }\"#,\n        )\n        .file(\n            \"common/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"common\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                f1 = []\n                f2 = []\n            \"#,\n        )\n        .file(\n            \"common/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"f1\")]\n                pub fn f1() {}\n\n                #[cfg(feature = \"f2\")]\n                pub fn f2() {}\n            \"#,\n        )\n        .file(\n            \"common/build.rs\",\n            &r#\"\n                use std::env::var_os;\n                fn main() {\n                    assert_eq!(var_os(\"CARGO_FEATURE_F1\").is_some(), cfg!(feature=\"f1\"));\n                    assert_eq!(var_os(\"CARGO_FEATURE_F2\").is_some(), cfg!(feature=\"f2\"));\n                    if std::env::var(\"TARGET\").unwrap() == \"$TARGET\" {\n                        assert!(var_os(\"CARGO_FEATURE_F1\").is_none());\n                        assert!(var_os(\"CARGO_FEATURE_F2\").is_some());\n                    } else {\n                        assert!(var_os(\"CARGO_FEATURE_F1\").is_some());\n                        assert!(var_os(\"CARGO_FEATURE_F2\").is_none());\n                    }\n                }\n            \"#\n            .replace(\"$TARGET\", target),\n        )\n        .build();\n\n    p.cargo(\"build -Z bindeps -v\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .run();\n}\n\n#[cargo_test]\nfn calc_bin_artifact_fingerprint() {\n    // See rust-lang/cargo#10527\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = \"bin\" }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_BAR\"));\n                }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/main.rs\", r#\"fn main() { println!(\"foo\") }\"#)\n        .build();\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\"bar/src/main.rs\", r#\"fn main() { println!(\"bar\") }\"#);\n    // Change in artifact bin dep `bar` propagates to `foo`, triggering recompile.\n    p.cargo(\"check -v -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] bar v0.5.0 ([ROOT]/foo/bar): the file `bar/src/main.rs` has changed ([..])\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..]`\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the dependency `bar` was rebuilt\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // All units are fresh. No recompile.\n    p.cargo(\"check -v -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] bar v0.5.0 ([ROOT]/foo/bar)\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn with_target_and_optional() {\n    // See rust-lang/cargo#10526\n    if cross_compile_disabled() {\n        return;\n    }\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                [dependencies]\n                d1 = { path = \"d1\", artifact = \"bin\", optional = true, target = \"$TARGET\" }\n            \"#\n            .replace(\"$TARGET\", target),\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    let _b = include_bytes!(env!(\"CARGO_BIN_FILE_D1\"));\n                }\n            \"#,\n        )\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"d1/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Z bindeps -F d1 -v\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] d1 v0.0.1 ([ROOT]/foo/d1)\n[RUNNING] `rustc --crate-name d1 [..]--crate-type bin[..]\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]--cfg[..]d1[..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn with_assumed_host_target_and_optional_build_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                [build-dependencies]\n                d1 = { path = \"d1\", artifact = \"bin\", optional = true, target = \"target\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    std::env::var(\"CARGO_BIN_FILE_D1\").unwrap();\n                }\n            \"#,\n        )\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"d1/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Z bindeps -F d1 -v\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] d1 v0.0.1 ([ROOT]/foo/d1)\n[RUNNING] `rustc --crate-name build_script_build --edition=2021 [..]--crate-type bin[..]\n[RUNNING] `rustc --crate-name d1 --edition=2021 [..]--crate-type bin[..]\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo --edition=2021 [..]--cfg[..]d1[..]\n[FINISHED] `dev` profile [..]\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn decouple_same_target_transitive_dep_from_artifact_dep() {\n    // See https://github.com/rust-lang/cargo/issues/11463\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                a = {{ path = \"a\" }}\n                bar = {{ path = \"bar\", artifact = \"bin\", target = \"{target}\" }}\n            \"#\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {}\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                a = { path = \"../a\", features = [\"feature\"] }\n            \"#,\n        )\n        .file(\n            \"bar/src/main.rs\",\n            r#\"\n                fn main() {}\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                b = { path = \"../b\" }\n                c = { path = \"../c\" }\n\n                [features]\n                feature = [\"c/feature\"]\n            \"#,\n        )\n        .file(\n            \"a/src/lib.rs\",\n            r#\"\n                use b::Trait as _;\n\n                pub fn use_b_trait(x: &impl c::Trait) {\n                    x.b();\n                }\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                c = { path = \"../c\" }\n            \"#,\n        )\n        .file(\n            \"b/src/lib.rs\",\n            r#\"\n                pub trait Trait {\n                    fn b(&self) {}\n                }\n\n                impl<T: c::Trait> Trait for T {}\n            \"#,\n        )\n        .file(\n            \"c/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"c\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                feature = []\n            \"#,\n        )\n        .file(\n            \"c/src/lib.rs\",\n            r#\"\n                pub trait Trait {}\n            \"#,\n        )\n        .build();\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 4 packages to latest compatible versions\n[COMPILING] c v0.1.0 ([ROOT]/foo/c)\n[COMPILING] b v0.1.0 ([ROOT]/foo/b)\n[COMPILING] a v0.1.0 ([ROOT]/foo/a)\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn decouple_same_target_transitive_dep_from_artifact_dep_lib() {\n    // See https://github.com/rust-lang/cargo/issues/10837\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                a = {{ path = \"a\" }}\n                b = {{ path = \"b\", features = [\"feature\"] }}\n                bar = {{ path = \"bar\", artifact = \"bin\", lib = true, target = \"{target}\" }}\n            \"#\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                a = { path = \"../a\", features = [\"b\"] }\n                b = { path = \"../b\" }\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"bar/src/main.rs\",\n            r#\"\n                use b::Trait;\n\n                fn main() {\n                    a::A.b()\n                }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                b = { path = \"../b\", optional = true }\n            \"#,\n        )\n        .file(\n            \"a/src/lib.rs\",\n            r#\"\n                pub struct A;\n\n                #[cfg(feature = \"b\")]\n                impl b::Trait for A {}\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                feature = []\n            \"#,\n        )\n        .file(\n            \"b/src/lib.rs\",\n            r#\"\n                pub trait Trait {\n                    fn b(&self) {}\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 3 packages to latest compatible versions\n[COMPILING] b v0.1.0 ([ROOT]/foo/b)\n[COMPILING] a v0.1.0 ([ROOT]/foo/a)\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn decouple_same_target_transitive_dep_from_artifact_dep_and_proc_macro() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                c = {{ path = \"c\" }}\n                bar = {{ path = \"bar\", artifact = \"bin\", target = \"{target}\" }}\n            \"#\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            b = { path = \"../b\" }\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.1.0\"\n            edition = \"2021\"\n\n            [dependencies]\n            a = { path = \"../a\" }\n\n            [lib]\n            proc-macro = true\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"c/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"c\"\n            version = \"0.1.0\"\n            edition = \"2021\"\n\n            [dependencies]\n            d = { path = \"../d\", features = [\"feature\"] }\n            a = { path = \"../a\" }\n\n            [lib]\n            proc-macro = true\n            \"#,\n        )\n        .file(\n            \"c/src/lib.rs\",\n            r#\"\n            use a::Trait;\n\n            fn _c() {\n                d::D.a()\n            }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            d = { path = \"../d\" }\n            \"#,\n        )\n        .file(\n            \"a/src/lib.rs\",\n            r#\"\n            pub trait Trait {\n                fn a(&self) {}\n            }\n\n            impl Trait for d::D {}\n            \"#,\n        )\n        .file(\n            \"d/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"d\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            feature = []\n            \"#,\n        )\n        .file(\"d/src/lib.rs\", \"pub struct D;\")\n        .build();\n\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 5 packages to latest compatible versions\n[COMPILING] d v0.1.0 ([ROOT]/foo/d)\n[COMPILING] a v0.1.0 ([ROOT]/foo/a)\n[COMPILING] b v0.1.0 ([ROOT]/foo/b)\n[COMPILING] c v0.1.0 ([ROOT]/foo/c)\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn same_target_artifact_dep_sharing() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                a = {{ path = \"a\" }}\n                bar = {{ path = \"bar\", artifact = \"bin\", target = \"{target}\" }}\n            \"#\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                a = { path = \"../a\" }\n            \"#,\n        )\n        .file(\n            \"bar/src/main.rs\",\n            r#\"\n                fn main() {}\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n    p.cargo(&format!(\"build -Z bindeps --target {target}\"))\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] a v0.1.0 ([ROOT]/foo/a)\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_transitive_artifact_dependency_with_different_target() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar/\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                baz = { path = \"baz/\", artifact = \"bin\", target = \"custom-target\" }\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"bar/baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n            \"#,\n        )\n        .file(\"bar/baz/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[ERROR] failed to determine target information for target `custom-target`.\n  Artifact dependency `baz` in package `bar v0.0.0 ([ROOT]/foo/bar)` requires building for `custom-target`\n\nCaused by:\n  failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  process didn't exit successfully: `rustc [..] ([EXIT_STATUS]: 1)\n  --- stderr\n...\n\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn build_only_specified_artifact_library() {\n    // Create a project with:\n    // - A crate `bar` with both `staticlib` and `cdylib` as crate-types.\n    // - A crate `foo` which depends on either the `staticlib` or `cdylib` artifact of bar,\n    //   whose build-script simply checks which library artifacts are present.\n    let create_project = |artifact_lib| {\n        project()\n            .file(\n                \"bar/Cargo.toml\",\n                r#\"\n                [package]\n                name = \"bar\"\n                version = \"1.0.0\"\n\n                [lib]\n                crate-type = [\"staticlib\", \"cdylib\"]\n                \"#,\n            )\n            .file(\"bar/src/lib.rs\", \"\")\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n\n                [build-dependencies]\n                bar = {{ path = \"bar\", artifact = \"{artifact_lib}\" }}\n            \"#),\n            )\n            .file(\"src/lib.rs\", \"\")\n            .file(\n                \"build.rs\",\n                r#\"\n                fn main() {\n                    println!(\"cdylib present: {}\", std::env::var_os(\"CARGO_CDYLIB_FILE_BAR\").is_some());\n                    println!(\"staticlib present: {}\", std::env::var_os(\"CARGO_STATICLIB_FILE_BAR\").is_some());\n                }\n            \"#,\n            )\n            .build()\n    };\n\n    let cdylib = create_project(\"cdylib\");\n    cdylib\n        .cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .run();\n    assert_e2e().eq(\n        &build_script_output_string(&cdylib, \"foo\"),\n        str![[r#\"\ncdylib present: true\nstaticlib present: false\n\n\"#]],\n    );\n\n    let staticlib = create_project(\"staticlib\");\n    staticlib\n        .cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .run();\n    assert_e2e().eq(\n        &build_script_output_string(&staticlib, \"foo\"),\n        str![[r#\"\ncdylib present: false\nstaticlib present: true\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn artifact_dep_target_does_not_propagate_to_deps_of_build_script() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let bindeps_target = cross_compile::alternate();\n    let native_target = cross_compile::native();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            resolver = \"2\"\n\n            [dependencies.artifact]\n            path = \"artifact\"\n            artifact = \"bin\"\n            target = \"$TARGET\"\n        \"#\n            .replace(\"$TARGET\", bindeps_target),\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                let _b = include_bytes!(env!(\"CARGO_BIN_FILE_ARTIFACT\"));\n            }\n        \"#,\n        )\n        .file(\n            \"artifact/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"artifact\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [build-dependencies]\n            builder = { path = \"../builder\" }\n            \"#,\n        )\n        .file(\"artifact/src/main.rs\", \"fn main() { }\")\n        .file(\n            \"artifact/build.rs\",\n            r#\"\n            extern crate builder;\n            fn main() {\n                let _ = builder::add(1, 2);\n            }\n            \"#,\n        )\n        .file(\n            \"builder/Cargo.toml\",\n            &r#\"\n            [package]\n            name = \"builder\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [target.'$TARGET'.dependencies]\n            arch = { path = \"../arch\" }\n            \"#\n            .replace(\"$TARGET\", native_target),\n        )\n        .file(\n            \"builder/src/lib.rs\",\n            r#\"\n            extern crate arch;\n            pub fn add(a: i32, b: i32) -> i32 { arch::add(a, b) }\n            \"#,\n        )\n        .file(\n            \"arch/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"arch\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"arch/src/lib.rs\",\n            r#\"pub fn add(a: i32, b: i32) -> i32 { a + b }\"#,\n        )\n        .build();\n    p.cargo(\"test -Z bindeps\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 3 packages to latest compatible versions\n[COMPILING] arch v0.0.1 ([ROOT]/foo/arch)\n[COMPILING] builder v0.0.1 ([ROOT]/foo/builder)\n[COMPILING] artifact v0.0.1 ([ROOT]/foo/artifact)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .run();\n}\n\n#[cargo_test]\nfn artifact_dep_target_does_not_propagate_to_proc_macro() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let bindeps_target = cross_compile::alternate();\n    let native_target = cross_compile::native();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            resolver = \"2\"\n\n            [dependencies.artifact]\n            path = \"artifact\"\n            artifact = \"bin\"\n            target = \"$TARGET\"\n        \"#\n            .replace(\"$TARGET\", bindeps_target),\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                let _b = include_bytes!(env!(\"CARGO_BIN_FILE_ARTIFACT\"));\n            }\n        \"#,\n        )\n        .file(\n            \"artifact/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"artifact\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            macro = { path = \"../macro\" }\n            \"#,\n        )\n        .file(\"artifact/src/main.rs\", \"fn main() { }\")\n        .file(\n            \"macro/Cargo.toml\",\n            &r#\"\n            [package]\n            name = \"macro\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [lib]\n            proc-macro = true\n\n            [target.'$TARGET'.dependencies]\n            arch = { path = \"../arch\" }\n            \"#\n            .replace(\"$TARGET\", native_target),\n        )\n        .file(\"macro/src/lib.rs\", \"\")\n        .file(\n            \"arch/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"arch\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"arch/src/lib.rs\",\n            \"pub fn add(a: i32, b: i32) -> i32 { a + b }\",\n        )\n        .build();\n    p.cargo(\"test -Z bindeps\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 3 packages to latest compatible versions\n[COMPILING] arch v0.0.1 ([ROOT]/foo/arch)\n[COMPILING] macro v0.0.1 ([ROOT]/foo/macro)\n[COMPILING] artifact v0.0.1 ([ROOT]/foo/artifact)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/artifact_dir.rs",
    "content": "//! Tests for --artifact-dir flag.\n\nuse std::env;\nuse std::fs;\nuse std::path::Path;\n\nuse crate::prelude::*;\nuse cargo_test_support::sleep_ms;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_manifest, project};\n\n#[cargo_test]\nfn binary_with_debug() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .build();\n\n    p.cargo(\"build -Z unstable-options --artifact-dir out\")\n        .masquerade_as_nightly_cargo(&[\"artifact-dir\"])\n        .enable_mac_dsym()\n        .run();\n    check_dir_contents(\n        &p.root().join(\"out\"),\n        &[\"foo\"],\n        &[\"foo\", \"foo.dSYM\"],\n        &[\"foo.exe\", \"foo.pdb\"],\n        &[\"foo.exe\"],\n    );\n}\n\n#[cargo_test]\nfn static_library_with_debug() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [lib]\n                crate-type = [\"staticlib\"]\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[no_mangle]\n                pub extern \"C\" fn foo() { println!(\"Hello, World!\") }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z unstable-options --artifact-dir out\")\n        .masquerade_as_nightly_cargo(&[\"artifact-dir\"])\n        .run();\n    check_dir_contents(\n        &p.root().join(\"out\"),\n        &[\"libfoo.a\"],\n        &[\"libfoo.a\"],\n        &[\"foo.lib\"],\n        &[\"libfoo.a\"],\n    );\n}\n\n#[cargo_test]\nfn dynamic_library_with_debug() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [lib]\n                crate-type = [\"cdylib\"]\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[no_mangle]\n                pub extern \"C\" fn foo() { println!(\"Hello, World!\") }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z unstable-options --artifact-dir out\")\n        .masquerade_as_nightly_cargo(&[\"artifact-dir\"])\n        .enable_mac_dsym()\n        .run();\n    check_dir_contents(\n        &p.root().join(\"out\"),\n        &[\"libfoo.so\"],\n        &[\"libfoo.dylib\", \"libfoo.dylib.dSYM\"],\n        &[\"foo.dll\", \"foo.dll.exp\", \"foo.dll.lib\", \"foo.pdb\"],\n        &[\"foo.dll\", \"libfoo.dll.a\"],\n    );\n}\n\n#[cargo_test]\nfn rlib_with_debug() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [lib]\n                crate-type = [\"rlib\"]\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() { println!(\"Hello, World!\") }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z unstable-options --artifact-dir out\")\n        .masquerade_as_nightly_cargo(&[\"artifact-dir\"])\n        .run();\n    check_dir_contents(\n        &p.root().join(\"out\"),\n        &[\"libfoo.rlib\"],\n        &[\"libfoo.rlib\"],\n        &[\"libfoo.rlib\"],\n        &[\"libfoo.rlib\"],\n    );\n}\n\n#[cargo_test]\nfn include_only_the_binary_from_the_current_package() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [workspace]\n\n                [dependencies]\n                utils = { path = \"./utils\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate utils;\")\n        .file(\n            \"src/main.rs\",\n            r#\"\n                extern crate foo;\n                extern crate utils;\n                fn main() {\n                    println!(\"Hello, World!\")\n                }\n            \"#,\n        )\n        .file(\"utils/Cargo.toml\", &basic_manifest(\"utils\", \"0.0.1\"))\n        .file(\"utils/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Z unstable-options --bin foo --artifact-dir out\")\n        .masquerade_as_nightly_cargo(&[\"artifact-dir\"])\n        .enable_mac_dsym()\n        .run();\n    check_dir_contents(\n        &p.root().join(\"out\"),\n        &[\"foo\"],\n        &[\"foo\", \"foo.dSYM\"],\n        &[\"foo.exe\", \"foo.pdb\"],\n        &[\"foo.exe\"],\n    );\n}\n\n#[cargo_test]\nfn artifact_dir_is_a_file() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\"out\", \"\")\n        .build();\n\n    p.cargo(\"build -Z unstable-options --artifact-dir out\")\n        .masquerade_as_nightly_cargo(&[\"artifact-dir\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to create directory `[ROOT]/foo/out`\n\nCaused by:\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn replaces_artifacts() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"foo\") }\"#)\n        .build();\n\n    p.cargo(\"build -Z unstable-options --artifact-dir out\")\n        .masquerade_as_nightly_cargo(&[\"artifact-dir\"])\n        .run();\n    p.process(\n        &p.root()\n            .join(&format!(\"out/foo{}\", env::consts::EXE_SUFFIX)),\n    )\n    .with_stdout_data(str![[r#\"\nfoo\n\n\"#]])\n    .run();\n\n    sleep_ms(1000);\n    p.change_file(\"src/main.rs\", r#\"fn main() { println!(\"bar\") }\"#);\n\n    p.cargo(\"build -Z unstable-options --artifact-dir out\")\n        .masquerade_as_nightly_cargo(&[\"artifact-dir\"])\n        .run();\n    p.process(\n        &p.root()\n            .join(&format!(\"out/foo{}\", env::consts::EXE_SUFFIX)),\n    )\n    .with_stdout_data(str![[r#\"\nbar\n\n\"#]])\n    .run();\n}\n\n#[cargo_test]\nfn avoid_build_scripts() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/main.rs\", \"fn main() {}\")\n        .file(\"a/build.rs\", r#\"fn main() { println!(\"hello-build-a\"); }\"#)\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/main.rs\", \"fn main() {}\")\n        .file(\"b/build.rs\", r#\"fn main() { println!(\"hello-build-b\"); }\"#)\n        .build();\n\n    p.cargo(\"build -Z unstable-options --artifact-dir out -vv\")\n        .masquerade_as_nightly_cargo(&[\"artifact-dir\"])\n        .enable_mac_dsym()\n        .with_stdout_data(\n            str![[r#\"\n[a 0.0.1] hello-build-a\n[b 0.0.1] hello-build-b\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    check_dir_contents(\n        &p.root().join(\"out\"),\n        &[\"a\", \"b\"],\n        &[\"a\", \"a.dSYM\", \"b\", \"b.dSYM\"],\n        &[\"a.exe\", \"a.pdb\", \"b.exe\", \"b.pdb\"],\n        &[\"a.exe\", \"b.exe\"],\n    );\n}\n\n#[cargo_test]\nfn cargo_build_artifact_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            artifact-dir = \"out\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z unstable-options\")\n        .masquerade_as_nightly_cargo(&[\"artifact-dir\"])\n        .enable_mac_dsym()\n        .run();\n    check_dir_contents(\n        &p.root().join(\"out\"),\n        &[\"foo\"],\n        &[\"foo\", \"foo.dSYM\"],\n        &[\"foo.exe\", \"foo.pdb\"],\n        &[\"foo.exe\"],\n    );\n}\n\n#[cargo_test]\nfn unsupported_short_artifact_dir_flag() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .build();\n\n    p.cargo(\"build -Z unstable-options -O\")\n        .masquerade_as_nightly_cargo(&[\"artifact-dir\"])\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '-O' found\n\n  tip: a similar argument exists: '--artifact-dir'\n\nUsage: cargo[EXE] build [OPTIONS]\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn removed_out_dir_flag() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .build();\n\n    p.cargo(\"build -Z unstable-options --out-dir out\")\n        .masquerade_as_nightly_cargo(&[\"out-dir\"])\n        .with_status(1)\n        .enable_mac_dsym()\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '--out-dir' found\n\n  tip: a similar argument exists: '--artifact-dir'\n\nUsage: cargo[EXE] build [OPTIONS]\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn artifact_dir_rejected_on_stable() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"build --artifact-dir out\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"[ERROR] the `--artifact-dir` flag is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel\nSee https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels.\nSee https://github.com/rust-lang/cargo/issues/6790 for more information about the `--artifact-dir` flag.\n\n\"#]])\n        .run();\n}\n\nfn check_dir_contents(\n    artifact_dir: &Path,\n    expected_linux: &[&str],\n    expected_mac: &[&str],\n    expected_win_msvc: &[&str],\n    expected_win_gnu: &[&str],\n) {\n    let expected = if cfg!(target_os = \"windows\") {\n        if cfg!(target_env = \"msvc\") {\n            expected_win_msvc\n        } else {\n            expected_win_gnu\n        }\n    } else if cfg!(target_os = \"macos\") {\n        expected_mac\n    } else {\n        expected_linux\n    };\n\n    let actual = list_dir(artifact_dir);\n    let mut expected = expected.iter().map(|s| s.to_string()).collect::<Vec<_>>();\n    expected.sort_unstable();\n    assert_eq!(actual, expected);\n}\n\nfn list_dir(dir: &Path) -> Vec<String> {\n    let mut res = Vec::new();\n    for entry in fs::read_dir(dir).unwrap() {\n        let entry = entry.unwrap();\n        res.push(entry.file_name().into_string().unwrap());\n    }\n    res.sort_unstable();\n    res\n}\n"
  },
  {
    "path": "tests/testsuite/bad_config.rs",
    "content": "//! Tests for some invalid .cargo/config files.\n\nuse crate::prelude::*;\nuse cargo_test_support::git::cargo_uses_gitoxide;\nuse cargo_test_support::registry::{self, Package};\nuse cargo_test_support::{Project, basic_bin_manifest, basic_manifest, project, rustc_host, str};\n\n#[cargo_test]\nfn bad1() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                  [target]\n                  nonexistent-target = \"foo\"\n            \"#,\n        )\n        .build();\n    p.cargo(\"check -v --target=nonexistent-target\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] expected table for configuration key `target.nonexistent-target`, but found string in [ROOT]/foo/.cargo/config.toml\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unsupported_float() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                  [http]\n                    proxy = 3.0\n            \"#,\n        )\n        .build();\n    p.cargo(\"publish -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not load Cargo configuration\n\nCaused by:\n  failed to load TOML configuration from `[ROOT]/foo/.cargo/config.toml`\n\nCaused by:\n  failed to parse config at `http.proxy`\n\nCaused by:\n  unsupported TOML configuration type `float`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unsupported_datetime() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [http]\n                proxy = 1979-05-27T07:32:00Z\n            \"#,\n        )\n        .build();\n    p.cargo(\"publish -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not load Cargo configuration\n\nCaused by:\n  failed to load TOML configuration from `[ROOT]/foo/.cargo/config.toml`\n\nCaused by:\n  failed to parse config at `http.proxy`\n\nCaused by:\n  unsupported TOML configuration type `datetime`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unsupported_float_array() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [alias]\n                floats = [2.71828, 3.14159]\n            \"#,\n        )\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not load Cargo configuration\n\nCaused by:\n  failed to load TOML configuration from `[ROOT]/foo/.cargo/config.toml`\n\nCaused by:\n  failed to parse config at `alias.floats[0]`\n\nCaused by:\n  unsupported TOML configuration type `float`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unsupported_datetime_array() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [alias]\n                datetimes = [07:32:00, 1979-05-27T07:32:00Z]\n            \"#,\n        )\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not load Cargo configuration\n\nCaused by:\n  failed to load TOML configuration from `[ROOT]/foo/.cargo/config.toml`\n\nCaused by:\n  failed to parse config at `alias.datetimes[0]`\n\nCaused by:\n  unsupported TOML configuration type `datetime`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad3() {\n    let registry = registry::init();\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [http]\n                  proxy = true\n            \"#,\n        )\n        .build();\n    Package::new(\"foo\", \"1.0.0\").publish();\n\n    p.cargo(\"publish -v\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to update registry `crates-io`\n\nCaused by:\n  error in [ROOT]/foo/.cargo/config.toml: `http.proxy` expected a string, but found a boolean\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad4() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [cargo-new]\n                  vcs = false\n            \"#,\n        )\n        .build();\n    p.cargo(\"new -v foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `foo` package\n[ERROR] failed to create package `foo` at `[ROOT]/foo/foo`\n\nCaused by:\n  error in [ROOT]/foo/.cargo/config.toml: `cargo-new.vcs` expected a string, but found a boolean\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad6() {\n    let registry = registry::init();\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [http]\n                  user-agent = true\n            \"#,\n        )\n        .build();\n    Package::new(\"foo\", \"1.0.0\").publish();\n\n    p.cargo(\"publish -v\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to update registry `crates-io`\n\nCaused by:\n  error in [ROOT]/foo/.cargo/config.toml: `http.user-agent` expected a string, but found a boolean\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_global_config() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"0.1.0\"\n            \"#,\n        )\n        .file(\".cargo/config.toml\", \"4\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  could not load Cargo configuration\n\nCaused by:\n  could not parse TOML configuration in `[ROOT]/foo/.cargo/config.toml`\n\nCaused by:\n  TOML parse error at line 1, column 2\n    |\n  1 | 4\n    |  ^\n  key with no value, expected `=`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_cargo_lock() {\n    let p = project()\n        .file(\"Cargo.lock\", \"[[package]]\\nfoo = 92\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock\n\nCaused by:\n  TOML parse error at line 1, column 1\n    |\n  1 | [[package]]\n    | ^^^^^^^^^^^\n  missing field `name`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn duplicate_packages_in_cargo_lock() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.lock\",\n            r#\"\n                [[package]]\n                name = \"foo\"\n                version = \"0.0.1\"\n                dependencies = [\n                 \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n                ]\n\n                [[package]]\n                name = \"bar\"\n                version = \"0.1.0\"\n                source = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n                [[package]]\n                name = \"bar\"\n                version = \"0.1.0\"\n                source = \"registry+https://github.com/rust-lang/crates.io-index\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock\n\nCaused by:\n  package `bar` is specified twice in the lockfile\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_source_in_cargo_lock() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.lock\",\n            r#\"\n                [[package]]\n                name = \"foo\"\n                version = \"0.0.1\"\n                dependencies = [\n                 \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n                ]\n\n                [[package]]\n                name = \"bar\"\n                version = \"0.1.0\"\n                source = \"You shall not parse\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check --verbose\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock\n\nCaused by:\n  TOML parse error at line 12, column 26\n     |\n  12 |                 source = \"You shall not parse\"\n     |                          ^^^^^^^^^^^^^^^^^^^^^\n  invalid source `You shall not parse`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_dependency_in_lockfile() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.lock\",\n            r#\"\n                [[package]]\n                name = \"foo\"\n                version = \"0.0.1\"\n                dependencies = [\n                 \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n                ]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn bad_git_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = {{ git = \"{url}\" }}\n            \"#,\n                url = if cargo_uses_gitoxide() {\n                    \"git://host.xz\"\n                } else {\n                    \"file:..\"\n                }\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    if cargo_uses_gitoxide() {\n        p.cargo(\"check -v\")\n            .with_status(101)\n            .with_stderr_data(str![[r#\"\n[UPDATING] git repository `git://host.xz`\n[ERROR] failed to get `foo` as a dependency of package `foo v0.0.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `foo`\n\nCaused by:\n  unable to update git://host.xz\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/_empty-[HASH]\n\nCaused by:\n  URL \"git://host.xz\" does not specify a path to a repository\n\n\"#]])\n            .run();\n    } else {\n        p.cargo(\"check -v\")\n            .with_status(101)\n            .with_stderr_data(str![[r#\"\n[UPDATING] git repository `file:///`\n[ERROR] failed to get `foo` as a dependency of package `foo v0.0.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `foo`\n\nCaused by:\n  unable to update file:///\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/_empty-[HASH]\n\nCaused by:\n  'file:///' is not a valid local file URI; class=Config (7)\n\n\"#]])\n            .run();\n    };\n}\n\n#[cargo_test]\nfn bad_crate_type() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                crate-type = [\"bad_type\", \"rlib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[ERROR] unknown crate type: `bad_type`, expected one of: `lib`, `rlib`, `staticlib`, `dylib`, `cdylib`, `bin`, `proc-macro`\n\n[ERROR] could not compile `foo` (lib) due to 1 previous error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn malformed_override() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [target.x86_64-apple-darwin.freetype]\n                native = {\n                  foo: \"bar\"\n                }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] missing assignment between key-value pairs, expected `=`\n  --> Cargo.toml:10:24\n   |\n10 |                   foo: \"bar\"\n   |                        ^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_toml_missing_package_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n               [package]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  missing field `package.name`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn duplicate_binary_names() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n               [package]\n               name = \"qqq\"\n               version = \"0.1.0\"\n               edition = \"2015\"\n               authors = [\"A <a@a.a>\"]\n\n               [[bin]]\n               name = \"e\"\n               path = \"a.rs\"\n\n               [[bin]]\n               name = \"e\"\n               path = \"b.rs\"\n            \"#,\n        )\n        .file(\"a.rs\", r#\"fn main() -> () {}\"#)\n        .file(\"b.rs\", r#\"fn main() -> () {}\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  found duplicate binary name e, but all binary targets must have a unique name\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn duplicate_example_names() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n               [package]\n               name = \"qqq\"\n               version = \"0.1.0\"\n               edition = \"2015\"\n               authors = [\"A <a@a.a>\"]\n\n               [[example]]\n               name = \"ex\"\n               path = \"examples/ex.rs\"\n\n               [[example]]\n               name = \"ex\"\n               path = \"examples/ex2.rs\"\n            \"#,\n        )\n        .file(\"examples/ex.rs\", r#\"fn main () -> () {}\"#)\n        .file(\"examples/ex2.rs\", r#\"fn main () -> () {}\"#)\n        .build();\n\n    p.cargo(\"check --example ex\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  found duplicate example name ex, but all example targets must have a unique name\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn duplicate_bench_names() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n               [package]\n               name = \"qqq\"\n               version = \"0.1.0\"\n               edition = \"2015\"\n               authors = [\"A <a@a.a>\"]\n\n               [[bench]]\n               name = \"ex\"\n               path = \"benches/ex.rs\"\n\n               [[bench]]\n               name = \"ex\"\n               path = \"benches/ex2.rs\"\n            \"#,\n        )\n        .file(\"benches/ex.rs\", r#\"fn main () {}\"#)\n        .file(\"benches/ex2.rs\", r#\"fn main () {}\"#)\n        .build();\n\n    p.cargo(\"bench\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  found duplicate bench name ex, but all bench targets must have a unique name\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn duplicate_deps() {\n    let p = project()\n        .file(\"shim-bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"shim-bar/src/lib.rs\", \"pub fn a() {}\")\n        .file(\"linux-bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"linux-bar/src/lib.rs\", \"pub fn a() {}\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n               [package]\n               name = \"qqq\"\n               version = \"0.0.1\"\n               edition = \"2015\"\n               authors = []\n\n               [dependencies]\n               bar = { path = \"shim-bar\" }\n\n               [target.x86_64-unknown-linux-gnu.dependencies]\n               bar = { path = \"linux-bar\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main () {}\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  Dependency 'bar' has different source paths depending on the build target. Each dependency must have a single canonical source path irrespective of build target.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn duplicate_deps_diff_sources() {\n    let p = project()\n        .file(\"shim-bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"shim-bar/src/lib.rs\", \"pub fn a() {}\")\n        .file(\"linux-bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"linux-bar/src/lib.rs\", \"pub fn a() {}\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n               [package]\n               name = \"qqq\"\n               version = \"0.0.1\"\n               edition = \"2015\"\n               authors = []\n\n               [target.i686-unknown-linux-gnu.dependencies]\n               bar = { path = \"shim-bar\" }\n\n               [target.x86_64-unknown-linux-gnu.dependencies]\n               bar = { path = \"linux-bar\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main () {}\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  Dependency 'bar' has different source paths depending on the build target. Each dependency must have a single canonical source path irrespective of build target.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unused_keys() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\npaths = [\"/path/to/override\"]\n\n[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2015\"\nauthors = []\nunused = \"foo\"\n\n[target.foo]\nbar = \"3\"\n\n[lib]\nbuild = \"foo\"\n\n## Config fields\n\n[alias]\nb = \"build\"\n\n[build]\njobs = 1\n\n[credential-alias]\nmy-alias = [\"/usr/bin/cargo-credential-example\", \"--argument\", \"value\", \"--flag\"]\n\n[doc]\nbrowser = \"chromium\"\n\n[env]\nENV_VAR_NAME = \"value\"\n\n[future-incompat-report]\nfrequency = 'always'\n\n[cache]\nauto-clean-frequency = \"1 day\"\n\n[cargo-new]\nvcs = \"none\"\n\n[http]\ndebug = false\n\n[install]\nroot = \"/some/path\"\n\n[net]\nretry = 3\n\n[net.ssh]\nknown-hosts = [\"...\"]\n\n[resolver]\nincompatible-rust-versions = \"allow\"\n\n[registries.alternative]\nindex = \"…\"\n\n[registries.crates-io]\nprotocol = \"sparse\"\n\n[registry]\ndefault = \"…\"\n\n[source.alternative]\nreplace-with = \"…\"\n\n[target.'cfg(unix)']\nlinker = \"…\"\n\n[term]\nquiet = false\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused manifest key: alias\n[HELP] alias is a valid .cargo/config.toml key\n[WARNING] unused manifest key: build\n[HELP] build is a valid .cargo/config.toml key\n[WARNING] unused manifest key: cache\n[HELP] cache is a valid .cargo/config.toml key\n[WARNING] unused manifest key: cargo-new\n[HELP] cargo-new is a valid .cargo/config.toml key\n[WARNING] unused manifest key: credential-alias\n[HELP] credential-alias is a valid .cargo/config.toml key\n[WARNING] unused manifest key: doc\n[HELP] doc is a valid .cargo/config.toml key\n[WARNING] unused manifest key: env\n[HELP] env is a valid .cargo/config.toml key\n[WARNING] unused manifest key: future-incompat-report\n[HELP] future-incompat-report is a valid .cargo/config.toml key\n[WARNING] unused manifest key: http\n[HELP] http is a valid .cargo/config.toml key\n[WARNING] unused manifest key: install\n[HELP] install is a valid .cargo/config.toml key\n[WARNING] unused manifest key: lib.build\n[WARNING] unused manifest key: net\n[HELP] net is a valid .cargo/config.toml key\n[WARNING] unused manifest key: package.unused\n[WARNING] unused manifest key: paths\n[HELP] paths is a valid .cargo/config.toml key\n[WARNING] unused manifest key: registries\n[HELP] registries is a valid .cargo/config.toml key\n[WARNING] unused manifest key: registry\n[HELP] registry is a valid .cargo/config.toml key\n[WARNING] unused manifest key: resolver\n[HELP] resolver is a valid .cargo/config.toml key\n[WARNING] unused manifest key: source\n[HELP] source is a valid .cargo/config.toml key\n[WARNING] unused manifest key: target.cfg(unix).linker\n[WARNING] unused manifest key: target.foo.bar\n[WARNING] unused manifest key: term\n[HELP] term is a valid .cargo/config.toml key\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unused_keys_in_virtual_manifest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n                unused = \"foo\"\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check --workspace\")\n        .with_stderr_data(str![[r#\"\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: workspace.unused\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn empty_dependencies() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = {}\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  dependency (bar) specified without providing a local path, Git repository, version, or workspace dependency to use\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dev_dependencies2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dev_dependencies]\n                a = {path = \"a\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] `dev_dependencies` is deprecated in favor of `dev-dependencies` and will not work in the 2024 edition\n(in the `foo` package)\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn dev_dependencies2_2024() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n\n                [dev_dependencies]\n                a = {path = \"a\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `dev_dependencies` is unsupported as of the 2024 edition; instead use `dev-dependencies`\n  (in the `foo` package)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dev_dependencies2_conflict() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dev-dependencies]\n                a = {path = \"a\"}\n                [dev_dependencies]\n                a = {path = \"a\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] `dev_dependencies` is redundant with `dev-dependencies`, preferring `dev-dependencies` in the `foo` package\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn build_dependencies2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [build_dependencies]\n                a = {path = \"a\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] `build_dependencies` is deprecated in favor of `build-dependencies` and will not work in the 2024 edition\n(in the `foo` package)\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn build_dependencies2_2024() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n\n                [build_dependencies]\n                a = {path = \"a\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `build_dependencies` is unsupported as of the 2024 edition; instead use `build-dependencies`\n  (in the `foo` package)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_dependencies2_conflict() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [build-dependencies]\n                a = {path = \"a\"}\n                [build_dependencies]\n                a = {path = \"a\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] `build_dependencies` is redundant with `build-dependencies`, preferring `build-dependencies` in the `foo` package\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn lib_crate_type2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [lib]\n                name = \"foo\"\n                crate_type = [\"staticlib\", \"dylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition\n(in the `foo` library target)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn lib_crate_type2_2024() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2024\"\n                authors = [\"wycats@example.com\"]\n\n                [lib]\n                name = \"foo\"\n                crate_type = [\"staticlib\", \"dylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `crate_type` is unsupported as of the 2024 edition; instead use `crate-type`\n  (in the `foo` library target)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn lib_crate_type2_conflict() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [lib]\n                name = \"foo\"\n                crate-type = [\"rlib\", \"dylib\"]\n                crate_type = [\"staticlib\", \"dylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] `crate_type` is redundant with `crate-type`, preferring `crate-type` in the `foo` library target\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn bin_crate_type2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [[bin]]\n                name = \"foo\"\n                path = \"src/main.rs\"\n                crate_type = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition\n(in the `foo` binary target)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bin_crate_type2_2024() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2024\"\n                authors = [\"wycats@example.com\"]\n\n                [[bin]]\n                name = \"foo\"\n                path = \"src/main.rs\"\n                crate_type = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `crate_type` is unsupported as of the 2024 edition; instead use `crate-type`\n  (in the `foo` binary target)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bin_crate_type2_conflict() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [[bin]]\n                name = \"foo\"\n                path = \"src/main.rs\"\n                crate_type = []\n                crate-type = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] `crate_type` is redundant with `crate-type`, preferring `crate-type` in the `foo` binary target\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn examples_crate_type2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [[example]]\n                name = \"ex\"\n                path = \"examples/ex.rs\"\n                crate_type = [\"proc_macro\"]\n                [[example]]\n                name = \"goodbye\"\n                path = \"examples/ex-goodbye.rs\"\n                crate_type = [\"rlib\", \"staticlib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"examples/ex.rs\",\n            r#\"\n                fn main() { println!(\"ex\"); }\n            \"#,\n        )\n        .file(\n            \"examples/ex-goodbye.rs\",\n            r#\"\n                fn main() { println!(\"goodbye\"); }\n            \"#,\n        )\n        .build();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition\n(in the `ex` example target)\n[WARNING] `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition\n(in the `goodbye` example target)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn examples_crate_type2_2024() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2024\"\n                authors = [\"wycats@example.com\"]\n\n                [[example]]\n                name = \"ex\"\n                path = \"examples/ex.rs\"\n                crate_type = [\"proc_macro\"]\n                [[example]]\n                name = \"goodbye\"\n                path = \"examples/ex-goodbye.rs\"\n                crate_type = [\"rlib\", \"staticlib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"examples/ex.rs\",\n            r#\"\n                fn main() { println!(\"ex\"); }\n            \"#,\n        )\n        .file(\n            \"examples/ex-goodbye.rs\",\n            r#\"\n                fn main() { println!(\"goodbye\"); }\n            \"#,\n        )\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `crate_type` is unsupported as of the 2024 edition; instead use `crate-type`\n  (in the `ex` example target)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn examples_crate_type2_conflict() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [[example]]\n                name = \"ex\"\n                path = \"examples/ex.rs\"\n                crate-type = [\"rlib\", \"dylib\"]\n                crate_type = [\"proc_macro\"]\n                [[example]]\n                name = \"goodbye\"\n                path = \"examples/ex-goodbye.rs\"\n                crate-type = [\"rlib\", \"dylib\"]\n                crate_type = [\"rlib\", \"staticlib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"examples/ex.rs\",\n            r#\"\n                fn main() { println!(\"ex\"); }\n            \"#,\n        )\n        .file(\n            \"examples/ex-goodbye.rs\",\n            r#\"\n                fn main() { println!(\"goodbye\"); }\n            \"#,\n        )\n        .build();\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] `crate_type` is redundant with `crate-type`, preferring `crate-type` in the `ex` example target\n[WARNING] `crate_type` is redundant with `crate-type`, preferring `crate-type` in the `goodbye` example target\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn cargo_platform_build_dependencies2() {\n    let host = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n                    build = \"build.rs\"\n\n                    [target.{host}.build_dependencies]\n                    build = {{ path = \"build\" }}\n                \"#,\n                host = host\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() { }\")\n        .file(\n            \"build.rs\",\n            \"extern crate build; fn main() { build::build(); }\",\n        )\n        .file(\"build/Cargo.toml\", &basic_manifest(\"build\", \"0.5.0\"))\n        .file(\"build/src/lib.rs\", \"pub fn build() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `build_dependencies` is deprecated in favor of `build-dependencies` and will not work in the 2024 edition\n(in the `[HOST_TARGET]` platform target)\n[LOCKING] 1 package to latest compatible version\n[COMPILING] build v0.5.0 ([ROOT]/foo/build)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_platform_build_dependencies2_2024() {\n    let host = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2024\"\n                    authors = [\"wycats@example.com\"]\n                    build = \"build.rs\"\n\n                    [target.{host}.build_dependencies]\n                    build = {{ path = \"build\" }}\n                \"#,\n                host = host\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() { }\")\n        .file(\n            \"build.rs\",\n            \"extern crate build; fn main() { build::build(); }\",\n        )\n        .file(\"build/Cargo.toml\", &basic_manifest(\"build\", \"0.5.0\"))\n        .file(\"build/src/lib.rs\", \"pub fn build() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `build_dependencies` is unsupported as of the 2024 edition; instead use `build-dependencies`\n  (in the `[HOST_TARGET]` platform target)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_platform_build_dependencies2_conflict() {\n    let host = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n                    build = \"build.rs\"\n\n                    [target.{host}.build-dependencies]\n                    build = {{ path = \"build\" }}\n                    [target.{host}.build_dependencies]\n                    build = {{ path = \"build\" }}\n                \"#,\n                host = host\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() { }\")\n        .file(\n            \"build.rs\",\n            \"extern crate build; fn main() { build::build(); }\",\n        )\n        .file(\"build/Cargo.toml\", &basic_manifest(\"build\", \"0.5.0\"))\n        .file(\"build/src/lib.rs\", \"pub fn build() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `build_dependencies` is redundant with `build-dependencies`, preferring `build-dependencies` in the `[HOST_TARGET]` platform target\n[LOCKING] 1 package to latest compatible version\n[COMPILING] build v0.5.0 ([ROOT]/foo/build)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n\n        .run();\n}\n\n#[cargo_test]\nfn cargo_platform_dev_dependencies2() {\n    let host = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [target.{host}.dev_dependencies]\n                    dev = {{ path = \"dev\" }}\n                \"#,\n                host = host\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() { }\")\n        .file(\n            \"tests/foo.rs\",\n            \"extern crate dev; #[test] fn foo() { dev::dev() }\",\n        )\n        .file(\"dev/Cargo.toml\", &basic_manifest(\"dev\", \"0.5.0\"))\n        .file(\"dev/src/lib.rs\", \"pub fn dev() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `dev_dependencies` is deprecated in favor of `dev-dependencies` and will not work in the 2024 edition\n(in the `[HOST_TARGET]` platform target)\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_platform_dev_dependencies2_2024() {\n    let host = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2024\"\n                    authors = [\"wycats@example.com\"]\n\n                    [target.{host}.dev_dependencies]\n                    dev = {{ path = \"dev\" }}\n                \"#,\n                host = host\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() { }\")\n        .file(\n            \"tests/foo.rs\",\n            \"extern crate dev; #[test] fn foo() { dev::dev() }\",\n        )\n        .file(\"dev/Cargo.toml\", &basic_manifest(\"dev\", \"0.5.0\"))\n        .file(\"dev/src/lib.rs\", \"pub fn dev() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `dev_dependencies` is unsupported as of the 2024 edition; instead use `dev-dependencies`\n  (in the `[HOST_TARGET]` platform target)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_platform_dev_dependencies2_conflict() {\n    let host = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [target.{host}.dev-dependencies]\n                    dev = {{ path = \"dev\" }}\n                    [target.{host}.dev_dependencies]\n                    dev = {{ path = \"dev\" }}\n                \"#,\n                host = host\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() { }\")\n        .file(\n            \"tests/foo.rs\",\n            \"extern crate dev; #[test] fn foo() { dev::dev() }\",\n        )\n        .file(\"dev/Cargo.toml\", &basic_manifest(\"dev\", \"0.5.0\"))\n        .file(\"dev/src/lib.rs\", \"pub fn dev() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `dev_dependencies` is redundant with `dev-dependencies`, preferring `dev-dependencies` in the `[HOST_TARGET]` platform target\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn default_features2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\", features = [\"f1\"], default_features = false }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"f1\"]\n                f1 = []\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] `default_features` is deprecated in favor of `default-features` and will not work in the 2024 edition\n(in the `a` dependency)\n[LOCKING] 1 package to latest compatible version\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn default_features2_2024() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\", features = [\"f1\"], default_features = false }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"f1\"]\n                f1 = []\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `default_features` is unsupported as of the 2024 edition; instead use `default-features`\n  (in the `a` dependency)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn default_features2_conflict() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\", features = [\"f1\"], default-features = false, default_features = false }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"f1\"]\n                f1 = []\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] `default_features` is redundant with `default-features`, preferring `default-features` in the `a` dependency\n[LOCKING] 1 package to latest compatible version\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn workspace_default_features2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"workspace_only\", \"dep_workspace_only\", \"package_only\", \"dep_package_only\"]\n\n                [workspace.dependencies]\n                dep_workspace_only = { path = \"dep_workspace_only\", default_features = true }\n                dep_package_only = { path = \"dep_package_only\" }\n            \"#,\n        )\n        .file(\n            \"workspace_only/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"workspace_only\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                dep_workspace_only.workspace = true\n            \"#,\n        )\n        .file(\"workspace_only/src/lib.rs\", \"\")\n        .file(\n            \"dep_workspace_only/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep_workspace_only\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"dep_workspace_only/src/lib.rs\", \"\")\n        .file(\n            \"package_only/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"package_only\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                dep_package_only = { workspace = true, default_features = true }\n            \"#,\n        )\n        .file(\"package_only/src/lib.rs\", \"\")\n        .file(\n            \"dep_package_only/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep_package_only\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"dep_package_only/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] dep_package_only v0.1.0 ([ROOT]/foo/dep_package_only)\n[CHECKING] dep_workspace_only v0.1.0 ([ROOT]/foo/dep_workspace_only)\n[CHECKING] package_only v0.1.0 ([ROOT]/foo/package_only)\n[CHECKING] workspace_only v0.1.0 ([ROOT]/foo/workspace_only)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[WARNING] [ROOT]/foo/workspace_only/Cargo.toml: `default_features` is deprecated in favor of `default-features` and will not work in the 2024 edition\n(in the `dep_workspace_only` dependency)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_default_features2_2024() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"workspace_only\", \"dep_workspace_only\", \"package_only\", \"dep_package_only\"]\n\n                [workspace.dependencies]\n                dep_workspace_only = { path = \"dep_workspace_only\", default_features = true }\n                dep_package_only = { path = \"dep_package_only\" }\n            \"#,\n        )\n        .file(\n            \"workspace_only/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"workspace_only\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                authors = []\n\n                [dependencies]\n                dep_workspace_only.workspace = true\n            \"#,\n        )\n        .file(\"workspace_only/src/lib.rs\", \"\")\n        .file(\n            \"dep_workspace_only/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep_workspace_only\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                authors = []\n            \"#,\n        )\n        .file(\"dep_workspace_only/src/lib.rs\", \"\")\n        .file(\n            \"package_only/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"package_only\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                authors = []\n\n                [dependencies]\n                dep_package_only = { workspace = true, default_features = true }\n            \"#,\n        )\n        .file(\"package_only/src/lib.rs\", \"\")\n        .file(\n            \"dep_package_only/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep_package_only\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                authors = []\n            \"#,\n        )\n        .file(\"dep_package_only/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to load manifest for workspace member `[ROOT]/foo/workspace_only`\nreferenced by workspace at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  failed to parse manifest at `[ROOT]/foo/workspace_only/Cargo.toml`\n\nCaused by:\n  `default_features` is unsupported as of the 2024 edition; instead use `default-features`\n  (in the `dep_workspace_only` dependency)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn lib_proc_macro2() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                proc_macro = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `proc_macro` is deprecated in favor of `proc-macro` and will not work in the 2024 edition\n(in the `foo` library target)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn lib_proc_macro2_2024() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                [lib]\n                proc_macro = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `proc_macro` is unsupported as of the 2024 edition; instead use `proc-macro`\n  (in the `foo` library target)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn lib_proc_macro2_conflict() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                proc-macro = false\n                proc_macro = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] `proc_macro` is redundant with `proc-macro`, preferring `proc-macro` in the `foo` library target\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn bin_proc_macro2() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [[bin]]\n                name = \"foo\"\n                path = \"src/main.rs\"\n                proc_macro = false\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `proc_macro` is deprecated in favor of `proc-macro` and will not work in the 2024 edition\n(in the `foo` binary target)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bin_proc_macro2_2024() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2024\"\n                authors = [\"wycats@example.com\"]\n\n                [[bin]]\n                name = \"foo\"\n                path = \"src/main.rs\"\n                proc_macro = false\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `proc_macro` is unsupported as of the 2024 edition; instead use `proc-macro`\n  (in the `foo` binary target)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bin_proc_macro2_conflict() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [[bin]]\n                name = \"foo\"\n                path = \"src/main.rs\"\n                proc-macro = false\n                proc_macro = false\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    foo.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] `proc_macro` is redundant with `proc-macro`, preferring `proc-macro` in the `foo` binary target\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn invalid_toml_historically_allowed_fails() {\n    let p = project()\n        .file(\".cargo/config.toml\", \"[bar] baz = 2\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not load Cargo configuration\n\nCaused by:\n  could not parse TOML configuration in `[ROOT]/foo/.cargo/config.toml`\n\nCaused by:\n  TOML parse error at line 1, column 7\n    |\n  1 | [bar] baz = 2\n    |       ^\n  unexpected key or value, expected newline, `#`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ambiguous_git_reference() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                git = \"http://127.0.0.1\"\n                branch = \"master\"\n                tag = \"some-tag\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  dependency (bar) specification is ambiguous. Only one of `branch`, `tag` or `rev` is allowed.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(public_network_test)]\nfn github_pull_request_url() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                git = \"https://github.com/rust-lang/does-not-exist/pull/123\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `https://github.com/rust-lang/does-not-exist/pull/123`\n...\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update https://github.com/rust-lang/does-not-exist/pull/123\n...\n  [NOTE] GitHub url https://github.com/rust-lang/does-not-exist/pull/123 is not a repository. \n  [HELP] Replace the dependency with \n         `git = \"https://github.com/rust-lang/does-not-exist.git\" rev = \"refs/pull/123/head\"` \n     to specify pull requests as dependencies' revision.\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fragment_in_git_url() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                git = \"http://127.0.0.1#foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        // the following is needed as gitoxide has a different error message\n        // ...\n        // [..]127.0.0.1[..]\n        .with_stderr_data(str![[r#\"\n[WARNING] URL fragment `#foo` in git URL is ignored for dependency (bar). If you were trying to specify a specific git revision, use `rev = \"foo\"` in the dependency declaration.\n[UPDATING] git repository `http://127.0.0.1/#foo`\n...\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update http://127.0.0.1/#foo\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/_empty-[HASH]\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_source_config1() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\".cargo/config.toml\", \"[source.foo]\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no source location specified for `source.foo`, need `registry`, `local-registry`, `directory`, or `git` defined\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_source_config2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [source.crates-io]\n                registry = 'http://example.com'\n                replace-with = 'bar'\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update registry `crates-io`\n\nCaused by:\n  could not find a configured source with the name `bar` when attempting to lookup `crates-io` (configuration in `[ROOT]/foo/.cargo/config.toml`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_source_config3() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [source.crates-io]\n                registry = 'https://example.com'\n                replace-with = 'crates-io'\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update registry `crates-io`\n\nCaused by:\n  detected a cycle of `replace-with` sources, the source `crates-io` is eventually replaced with itself (configuration in `[ROOT]/foo/.cargo/config.toml`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_source_config4() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [source.crates-io]\n                replace-with = 'bar'\n\n                [source.bar]\n                registry = 'https://example.com'\n                replace-with = 'crates-io'\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update registry `crates-io`\n\nCaused by:\n  detected a cycle of `replace-with` sources, the source `crates-io` is eventually replaced with itself (configuration in `[ROOT]/foo/.cargo/config.toml`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_source_config5() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [source.crates-io]\n                registry = 'https://example.com'\n                replace-with = 'bar'\n\n                [source.bar]\n                registry = 'not a url'\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] configuration key `source.bar.registry` specified an invalid URL (in [ROOT]/foo/.cargo/config.toml)\n\nCaused by:\n  invalid url `not a url`: relative URL without a base\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn both_git_and_path_specified() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                git = \"http://127.0.0.1\"\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  dependency (bar) specification is ambiguous. Only one of `git` or `path` is allowed.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_source_config6() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [source.crates-io]\n                registry = 'https://example.com'\n                replace-with = ['not', 'a', 'string']\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `source.crates-io.replace-with`\n\nCaused by:\n  error in [ROOT]/foo/.cargo/config.toml: `source.crates-io.replace-with` expected a string, but found a array\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ignored_git_revision() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n                branch = \"spam\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  key `branch` is ignored for dependency (bar).\n\n\"#]])\n        .run();\n\n    // #11540, check that [target] dependencies fail the same way.\n    foo.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.0\"\n            edition = \"2015\"\n\n            [target.some-target.dependencies]\n            bar = { path = \"bar\", branch = \"spam\" }\n        \"#,\n    );\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  key `branch` is ignored for dependency (bar).\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_source_config7() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [source.foo]\n                registry = 'https://example.com'\n                local-registry = 'file:///another/file'\n            \"#,\n        )\n        .build();\n\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] more than one source location specified for `source.foo`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_source_config8() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [source.foo]\n                branch = \"somebranch\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] source definition `source.foo` specifies `branch`, but that requires a `git` key to be specified (in [ROOT]/foo/.cargo/config.toml)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = 3\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid type: integer `3`, expected a version string like \"0.9.8\" or a detailed dependency like { version = \"0.9.8\" }\n --> Cargo.toml:9:23\n  |\n9 |                 bar = 3\n  |                       ^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_dependency_true_literal() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid type: boolean `true`, expected a version string like \"0.9.8\" or a detailed dependency like { version = \"0.9.8\" }\n       [NOTE] if you meant to use a workspace member, you can write\n        dep.workspace = true\n --> Cargo.toml:9:23\n  |\n9 |                 bar = true\n  |                       ^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_debuginfo() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.dev]\n                debug = 'a'\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid value: string \"a\", expected a boolean, 0, 1, 2, \"none\", \"limited\", \"full\", \"line-tables-only\", or \"line-directives-only\"\n --> Cargo.toml:9:25\n  |\n9 |                 debug = 'a'\n  |                         ^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_debuginfo2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.dev]\n                debug = 3.6\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid type: floating point `3.6`, expected a boolean, 0, 1, 2, \"none\", \"limited\", \"full\", \"line-tables-only\", or \"line-directives-only\"\n --> Cargo.toml:9:25\n  |\n9 |                 debug = 3.6\n  |                         ^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_opt_level() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = 3\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid type: integer `3`, expected a boolean, string or array\n --> Cargo.toml:7:25\n  |\n7 |                 build = 3\n  |                         ^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warn_semver_metadata() {\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"1.0.0+1234\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] version requirement `1.0.0+1234` for dependency `bar` includes semver metadata which will be ignored, removing the metadata is recommended to avoid confusion\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] bar v1.0.0\n[CHECKING] foo v1.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn bad_http_ssl_version() {\n    // Invalid type in SslVersionConfig.\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [http]\n            ssl-version = [\"tlsv1.2\", \"tlsv1.3\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `http.ssl-version`\n\nCaused by:\n  invalid type: sequence, expected a string or map\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_http_ssl_version_range() {\n    // Invalid type in SslVersionConfigRange.\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [http]\n            ssl-version.min = false\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `http.ssl-version`\n\nCaused by:\n  error in [ROOT]/foo/.cargo/config.toml: `http.ssl-version.min` expected a string, but found a boolean\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_build_jobs() {\n    // Invalid type in JobsConfig.\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            jobs = { default = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `build.jobs`\n\nCaused by:\n  invalid type: map, expected an integer or string\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_build_target() {\n    // Invalid type in BuildTargetConfig.\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target.'cfg(unix)' = \"x86_64\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `build.target`\n\nCaused by:\n  error in [ROOT]/foo/.cargo/config.toml: could not load config key `build.target`\n\nCaused by:\n  invalid type: map, expected a string or array\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_target_cfg() {\n    // Invalid type in a StringList.\n    //\n    // The error message is a bit unfortunate here. The type here ends up\n    // being essentially Value<Value<StringList>>, and each layer of \"Value\"\n    // adds some context to the error message. Also, untagged enums provide\n    // strange error messages. Hopefully most users will be able to untangle\n    // the message.\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [target.'cfg(not(target_os = \"none\"))']\n            runner = false\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `target.'cfg(not(target_os = \"none\"))'.runner`\n\nCaused by:\n  error in [ROOT]/foo/.cargo/config.toml: could not load config key `target.'cfg(not(target_os = \"none\"))'.runner`\n\nCaused by:\n  invalid configuration for key `target.'cfg(not(target_os = \"none\"))'.runner`\n  expected a string or array of strings, but found a boolean for `target.'cfg(not(target_os = \"none\"))'.runner` in [ROOT]/foo/.cargo/config.toml\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_target_links_overrides() {\n    // Invalid parsing of links overrides.\n    //\n    // This error message is terrible. Nothing in the deserialization path is\n    // using config::Value<>, so nothing is able to report the location. I\n    // think this illustrates how the way things break down with how it\n    // currently is designed with serde.\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [target.{}.somelib]\n                rustc-flags = 'foo'\n                \"#,\n                rustc_host()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] only `-l` and `-L` flags are allowed in target config `target.[HOST_TARGET].rustc-flags` (in [ROOT]/foo/.cargo/config.toml): `foo`\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \".cargo/config.toml\",\n        &format!(\n            \"[target.{}.somelib]\n            warning = \\\"foo\\\"\n            \",\n            rustc_host(),\n        ),\n    );\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `warning` is not supported in build script overrides\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn redefined_sources() {\n    // Cannot define a source multiple times.\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [source.foo]\n            registry = \"https://github.com/rust-lang/crates.io-index\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] source `foo` defines source registry `crates-io`, but that source is already defined by `crates-io`\n[NOTE] Sources are not allowed to be defined multiple times.\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n        [source.one]\n        directory = \"index\"\n\n        [source.two]\n        directory = \"index\"\n        \"#,\n    );\n\n    // Name is `[..]` because we can't guarantee the order.\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] source `[..]` defines source dir [ROOT]/foo/index, but that source is already defined by `[..]`\n[NOTE] Sources are not allowed to be defined multiple times.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_trim_paths() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [profile.dev]\n                trim-paths = \"split-debuginfo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"trim-paths\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] expected a boolean, \"none\", \"diagnostics\", \"macro\", \"object\", \"all\", or an array with these options\n --> Cargo.toml:8:30\n  |\n8 |                 trim-paths = \"split-debuginfo\"\n  |                              ^^^^^^^^^^^^^^^^^\n\n\"#]])\n        .run();\n}\n\nfn bad_target_name_project(target: &str, path: &str, name: &str) -> Project {\n    project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n[package]\nname = \"bad-{target}-name\"\nedition = \"2024\"\n\n[[{target}]]\nname = \"{name}\"\n\"#\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(format!(\"{path}/{name}\"), \"\")\n        .build()\n}\n\n#[cargo_test]\nfn bad_bin_name() {\n    bad_target_name_project(\"bin\", \"src/bin\", \"bin.rs\")\n        .cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `bin.rs` bin at `src/bin/bin.rs.rs` or `src/bin/bin.rs/main.rs`. Please specify bin.path if you want to use a non-default path.\n\n  [HELP] a bin with a similar name exists: `bin`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_example_name() {\n    bad_target_name_project(\"example\", \"examples\", \"example.rs\")\n        .cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `example.rs` example at `examples/example.rs.rs` or `examples/example.rs/main.rs`. Please specify example.path if you want to use a non-default path.\n\n  [HELP] a example with a similar name exists: `example`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_test_name() {\n    bad_target_name_project(\"test\", \"tests\", \"test.rs\")\n        .cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `test.rs` test at `tests/test.rs.rs` or `tests/test.rs/main.rs`. Please specify test.path if you want to use a non-default path.\n\n  [HELP] a test with a similar name exists: `test`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_bench_name() {\n    bad_target_name_project(\"bench\", \"benches\", \"bench.rs\")\n        .cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `bench.rs` bench at `benches/bench.rs.rs` or `benches/bench.rs/main.rs`. Please specify bench.path if you want to use a non-default path.\n\n  [HELP] a bench with a similar name exists: `bench`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn non_existing_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n\n                [lib]\n                name = \"foo\"\n                path = \"src/lib.rs\"\n\n                [[test]]\n                name = \"hello\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --tests -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `hello` test at `tests/hello.rs` or `tests/hello/main.rs`. Please specify test.path if you want to use a non-default path.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn non_existing_example() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n\n                [lib]\n                name = \"foo\"\n                path = \"src/lib.rs\"\n\n                [[example]]\n                name = \"hello\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --examples -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `hello` example at `examples/hello.rs` or `examples/hello/main.rs`. Please specify example.path if you want to use a non-default path.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn non_existing_benchmark() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n\n                [lib]\n                name = \"foo\"\n                path = \"src/lib.rs\"\n\n                [[bench]]\n                name = \"hello\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --benches -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `hello` bench at `benches/hello.rs` or `benches/hello/main.rs`. Please specify bench.path if you want to use a non-default path.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn non_existing_binary() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/ehlo.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `foo` bin at `src/bin/foo.rs` or `src/bin/foo/main.rs`. Please specify bin.path if you want to use a non-default path.\n\n  [HELP] a bin with a similar name exists: `ehlo`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn commonly_wrong_path_of_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n\n                [lib]\n                name = \"foo\"\n                path = \"src/lib.rs\"\n\n                [[test]]\n                name = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"test/foo.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --tests -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `foo` test at default paths, but found a file at `test/foo.rs`.\n  Perhaps rename the file to `tests/foo.rs` for target auto-discovery, or specify test.path if you want to use a non-default path.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn commonly_wrong_path_of_example() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n\n                [lib]\n                name = \"foo\"\n                path = \"src/lib.rs\"\n\n                [[example]]\n                name = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"example/foo.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --examples -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `foo` example at default paths, but found a file at `example/foo.rs`.\n  Perhaps rename the file to `examples/foo.rs` for target auto-discovery, or specify example.path if you want to use a non-default path.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn commonly_wrong_path_of_benchmark() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n\n                [lib]\n                name = \"foo\"\n                path = \"src/lib.rs\"\n\n                [[bench]]\n                name = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bench/foo.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --benches -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `foo` bench at default paths, but found a file at `bench/foo.rs`.\n  Perhaps rename the file to `benches/foo.rs` for target auto-discovery, or specify bench.path if you want to use a non-default path.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn commonly_wrong_path_binary() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bins/foo.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `foo` bin at default paths, but found a file at `src/bins/foo.rs`.\n  Perhaps rename the file to `src/bin/foo.rs` for target auto-discovery, or specify bin.path if you want to use a non-default path.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn commonly_wrong_path_subdir_binary() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bins/foo/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `foo` bin at default paths, but found a file at `src/bins/foo/main.rs`.\n  Perhaps rename the file to `src/bin/foo/main.rs` for target auto-discovery, or specify bin.path if you want to use a non-default path.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn found_multiple_target_files() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/foo.rs\", \"\")\n        .file(\"src/bin/foo/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        // Don't assert the inferred paths since the order is non-deterministic.\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  cannot infer path for `foo` bin\n  Cargo doesn't know which to use because multiple target files found at `src/bin/foo[..]rs` and `src/bin/foo[..].rs`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn legacy_binary_paths_warnings() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[WARNING] An explicit [[bin]] section is specified in Cargo.toml which currently\ndisables Cargo from automatically inferring other binary targets.\nThis inference behavior will change in the Rust 2018 edition and the following\nfiles will be included as a binary target:\n\n* src/main.rs\n\nThis is likely to break cargo build or cargo test as these files may not be\nready to be compiled as a binary target today. You can future-proof yourself\nand disable this warning by adding `autobins = false` to your [package]\nsection. You may also move the files to a location where Cargo would not\nautomatically infer them to be a target, such as in subfolders.\n\nFor more information on this warning you can consult\nhttps://github.com/rust-lang/cargo/issues/5330\n[WARNING] path `src/main.rs` was erroneously implicitly accepted for binary `bar`,\nplease set bin.path in Cargo.toml\n[CHECKING] foo v1.0.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[RUNNING] `rustc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[WARNING] An explicit [[bin]] section is specified in Cargo.toml which currently\ndisables Cargo from automatically inferring other binary targets.\nThis inference behavior will change in the Rust 2018 edition and the following\nfiles will be included as a binary target:\n\n* src/bin/main.rs\n\nThis is likely to break cargo build or cargo test as these files may not be\nready to be compiled as a binary target today. You can future-proof yourself\nand disable this warning by adding `autobins = false` to your [package]\nsection. You may also move the files to a location where Cargo would not\nautomatically infer them to be a target, such as in subfolders.\n\nFor more information on this warning you can consult\nhttps://github.com/rust-lang/cargo/issues/5330\n[WARNING] path `src/bin/main.rs` was erroneously implicitly accepted for binary `bar`,\nplease set bin.path in Cargo.toml\n[CHECKING] foo v1.0.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[RUNNING] `rustc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"bar\"\n            \"#,\n        )\n        .file(\"src/bar.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[WARNING] path `src/bar.rs` was erroneously implicitly accepted for binary `bar`,\nplease set bin.path in Cargo.toml\n[CHECKING] foo v1.0.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn nonexistent_example_target_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [[example]]\n                name = \"bar\"\n                path = \"examples/null.rs\"\n            \"#,\n        )\n        .build();\n    p.cargo(\"check --examples\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] can't find example `bar` at path `[ROOT]/foo/examples/null.rs`\n --> [ROOT]/foo/Cargo.toml\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn nonexistent_library_target_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [lib]\n                path = \"src/null.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"fn bar() {}\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] can't find lib `foo` at path `[ROOT]/foo/src/null.rs`\n --> [ROOT]/foo/Cargo.toml\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn nonexistent_binary_target_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [[bin]]\n                name = \"null\"\n                path = \"src/null.rs\"\n            \"#,\n        )\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] can't find bin `null` at path `[ROOT]/foo/src/null.rs`\n --> [ROOT]/foo/Cargo.toml\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn nonexistent_test_target_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [[test]]\n                name = \"null\"\n                path = \"src/null.rs\"\n            \"#,\n        )\n        .build();\n    p.cargo(\"test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] can't find integration-test `null` at path `[ROOT]/foo/src/null.rs`\n --> [ROOT]/foo/Cargo.toml\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn nonexistent_bench_target_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [[bench]]\n                name = \"null\"\n                path = \"src/null.rs\"\n            \"#,\n        )\n        .build();\n    p.cargo(\"bench\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] can't find bench `null` at path `[ROOT]/foo/src/null.rs`\n --> [ROOT]/foo/Cargo.toml\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn directory_as_example_target_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [[example]]\n                name = \"bar\"\n                path = \"examples/bar\"\n            \"#,\n        )\n        .file(\"examples/bar/.temp\", \"\")\n        .build();\n    p.cargo(\"check --example bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] path `[ROOT]/foo/examples/bar` for example `bar` is a directory, but a source file was expected.\n --> [ROOT]/foo/Cargo.toml\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn directory_as_library_target_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [lib]\n                path = \"src/null\"\n            \"#,\n        )\n        .file(\"src/null/.temp\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] path `[ROOT]/foo/src/null` for lib `foo` is a directory, but a source file was expected.\n --> [ROOT]/foo/Cargo.toml\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn directory_as_binary_target_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [[bin]]\n                name = \"null\"\n                path = \"src/null\"\n            \"#,\n        )\n        .file(\"src/null/.temp\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] path `[ROOT]/foo/src/null` for bin `null` is a directory, but a source file was expected.\n --> [ROOT]/foo/Cargo.toml\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn directory_as_test_target_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [[test]]\n                name = \"null\"\n                path = \"src/null\"\n            \"#,\n        )\n        .file(\"src/null/.temp\", \"\")\n        .build();\n    p.cargo(\"test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] path `[ROOT]/foo/src/null` for integration-test `null` is a directory, but a source file was expected.\n --> [ROOT]/foo/Cargo.toml\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn directory_as_bench_target_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [[bench]]\n                name = \"null\"\n                path = \"src/null\"\n            \"#,\n        )\n        .file(\"src/null/.temp\", \"\")\n        .build();\n    p.cargo(\"bench\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] path `[ROOT]/foo/src/null` for bench `null` is a directory, but a source file was expected.\n --> [ROOT]/foo/Cargo.toml\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn directory_as_example_target_path_with_entrypoint() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [[example]]\n                name = \"bar\"\n                path = \"examples/bar\"\n            \"#,\n        )\n        .file(\"examples/bar/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check --example bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] path `[ROOT]/foo/examples/bar` for example `bar` is a directory, but a source file was expected.\n --> [ROOT]/foo/Cargo.toml\n  = [HELP] an entry point exists at `[ROOT]/foo/examples/bar/main.rs`\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn directory_as_library_target_path_with_entrypoint() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [lib]\n                path = \"src/null\"\n            \"#,\n        )\n        .file(\"src/null/lib.rs\", \"fn foo() {}\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] path `[ROOT]/foo/src/null` for lib `foo` is a directory, but a source file was expected.\n --> [ROOT]/foo/Cargo.toml\n  = [HELP] an entry point exists at `[ROOT]/foo/src/null/lib.rs`\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn directory_as_binary_target_path_with_entrypoint() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [[bin]]\n                name = \"null\"\n                path = \"src/null\"\n            \"#,\n        )\n        .file(\"src/null/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] path `[ROOT]/foo/src/null` for bin `null` is a directory, but a source file was expected.\n --> [ROOT]/foo/Cargo.toml\n  = [HELP] an entry point exists at `[ROOT]/foo/src/null/main.rs`\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn directory_as_test_target_path_with_entrypoint() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [[test]]\n                name = \"null\"\n                path = \"src/null\"\n            \"#,\n        )\n        .file(\"src/null/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] path `[ROOT]/foo/src/null` for integration-test `null` is a directory, but a source file was expected.\n --> [ROOT]/foo/Cargo.toml\n  = [HELP] an entry point exists at `[ROOT]/foo/src/null/main.rs`\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn directory_as_bench_target_path_with_entrypoint() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2024\"\n\n                [[bench]]\n                name = \"null\"\n                path = \"src/null\"\n            \"#,\n        )\n        .file(\"src/null/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"bench\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] path `[ROOT]/foo/src/null` for bench `null` is a directory, but a source file was expected.\n --> [ROOT]/foo/Cargo.toml\n  = [HELP] an entry point exists at `[ROOT]/foo/src/null/main.rs`\n[ERROR] could not compile due to 1 previous target resolution error\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/bad_manifest_path.rs",
    "content": "//! Tests for invalid --manifest-path arguments.\n\nuse crate::prelude::*;\nuse cargo_test_support::{basic_bin_manifest, main_file, project, str};\n\n#[track_caller]\nfn assert_bad_manifest_path(command: &str, manifest_path_argument: &str, stderr: impl IntoData) {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(command)\n        .arg(\"--manifest-path\")\n        .arg(manifest_path_argument)\n        .cwd(p.root().parent().unwrap())\n        .with_status(101)\n        .with_stderr_data(stderr)\n        .run();\n}\n\n#[cargo_test]\nfn bench_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"bench\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn bench_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"bench\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn bench_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"bench\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn bench_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"bench\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn build_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"check\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn build_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"bench\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn build_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"bench\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn build_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"check\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn clean_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"clean\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn clean_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"clean\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn clean_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"clean\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn clean_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"clean\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn doc_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"doc\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn doc_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"doc\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn doc_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"doc\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn doc_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"doc\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn fetch_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"fetch\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn fetch_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"fetch\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn fetch_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"fetch\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn fetch_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"fetch\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn generate_lockfile_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"generate-lockfile\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn generate_lockfile_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"generate-lockfile\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn generate_lockfile_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"generate-lockfile\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn generate_lockfile_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"generate-lockfile\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn package_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"package\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn package_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"package\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn package_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"package\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn package_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"package\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn pkgid_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"pkgid\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn pkgid_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"pkgid\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn pkgid_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"pkgid\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn pkgid_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"pkgid\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn publish_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"publish\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn publish_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"publish\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn publish_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"publish\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn publish_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"publish\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn read_manifest_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"read-manifest\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn read_manifest_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"read-manifest\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn read_manifest_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"read-manifest\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn read_manifest_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"read-manifest\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn run_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"run\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn run_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"run\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn run_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"run\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn run_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"run\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn rustc_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"rustc\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn rustc_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"rustc\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn rustc_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"rustc\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn rustc_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"rustc\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn test_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"test\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn test_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"test\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn test_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"test\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn test_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"test\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn update_dir_containing_cargo_toml() {\n    assert_bad_manifest_path(\n        \"update\",\n        \"foo\",\n        str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn update_dir_plus_file() {\n    assert_bad_manifest_path(\n        \"update\",\n        \"foo/bar\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn update_dir_plus_path() {\n    assert_bad_manifest_path(\n        \"update\",\n        \"foo/bar/baz\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn update_dir_to_nonexistent_cargo_toml() {\n    assert_bad_manifest_path(\n        \"update\",\n        \"foo/bar/baz/Cargo.toml\",\n        str![[r#\"\n[ERROR] manifest path `foo/bar/baz/Cargo.toml` does not exist\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn verify_project_dir_containing_cargo_toml() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"verify-project --manifest-path foo\")\n        .cwd(p.root().parent().unwrap())\n        .with_status(1)\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"invalid\": \"manifest path `foo` is a directory but expected a file\\n[HELP] [ROOT]/foo/Cargo.toml exists\"\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn verify_project_dir_plus_file() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"verify-project --manifest-path foo/bar\")\n        .cwd(p.root().parent().unwrap())\n        .with_status(1)\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"invalid\": \"manifest path `foo/bar` does not exist\"\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn verify_project_dir_plus_path() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"verify-project --manifest-path foo/bar/baz\")\n        .cwd(p.root().parent().unwrap())\n        .with_status(1)\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"invalid\": \"manifest path `foo/bar/baz` does not exist\"\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn verify_project_dir_to_nonexistent_cargo_toml() {\n    let p = project().build();\n    p.cargo(\"verify-project --manifest-path foo/bar/baz/Cargo.toml\")\n        .cwd(p.root().parent().unwrap())\n        .with_status(1)\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"invalid\": \"manifest path `foo/bar/baz/Cargo.toml` does not exist\"\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/bench.rs",
    "content": "//! Tests for the `cargo bench` command.\n\nuse crate::prelude::*;\nuse cargo_test_support::{basic_bin_manifest, basic_lib_manifest, basic_manifest, project, str};\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn cargo_bench_simple() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n\n            fn hello() -> &'static str {\n                \"hello\"\n            }\n\n            pub fn main() {\n                println!(\"{}\", hello())\n            }\n\n            #[bench]\n            fn bench_hello(_b: &mut test::Bencher) {\n                assert_eq!(hello(), \"hello\")\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bench_hello ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_bench_implicit() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n            #[bench] fn run1(_ben: &mut test::Bencher) { }\n            fn main() { println!(\"Hello main!\"); }\n            \"#,\n        )\n        .file(\n            \"tests/other.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run3(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .file(\n            \"benches/mybench.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run2(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench --benches\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n[RUNNING] [..] (target/release/deps/mybench-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest run1 ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest run2 ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_bin_implicit() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n            #[bench] fn run1(_ben: &mut test::Bencher) { }\n            fn main() { println!(\"Hello main!\"); }\n            \"#,\n        )\n        .file(\n            \"tests/other.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run3(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .file(\n            \"benches/mybench.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run2(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench --bins\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest run1 ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_tarname() {\n    let p = project()\n        .file(\n            \"benches/bin1.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run1(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .file(\n            \"benches/bin2.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run2(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench --bench bin2\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/bin2-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest run2 ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_multiple_targets() {\n    let p = project()\n        .file(\n            \"benches/bin1.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run1(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .file(\n            \"benches/bin2.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run2(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .file(\n            \"benches/bin3.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run3(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .build();\n\n    // This should not have anything about `run3` in it.\n    p.cargo(\"bench --bench bin1 --bench bin2\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] benches/bin1.rs (target/release/deps/bin1-[HASH][EXE])\n[RUNNING] benches/bin2.rs (target/release/deps/bin2-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn cargo_bench_verbose() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #![feature(test)]\n                #[cfg(test)]\n                extern crate test;\n                fn main() {}\n                #[bench] fn bench_hello(_b: &mut test::Bencher) {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench -v hello\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] src/main.rs [..]`\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[..]target/release/deps/foo-[HASH][EXE] hello --bench`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bench_hello ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn many_similar_names() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n            pub fn foo() {}\n            #[bench] fn lib_bench(_b: &mut test::Bencher) {}\n        \",\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate foo;\n            #[cfg(test)]\n            extern crate test;\n            fn main() {}\n            #[bench] fn bin_bench(_b: &mut test::Bencher) { foo::foo() }\n        \",\n        )\n        .file(\n            \"benches/foo.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate foo;\n                extern crate test;\n                #[bench] fn bench_bench(_b: &mut test::Bencher) { foo::foo() }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench\")\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest lib_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bin_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bench_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn cargo_bench_failing_test() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n            fn hello() -> &'static str {\n                \"hello\"\n            }\n\n            pub fn main() {\n                println!(\"{}\", hello())\n            }\n\n            #[bench]\n            fn bench_hello(_b: &mut test::Bencher) {\n                assert_eq!(hello(), \"nope\", \"NOPE!\")\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n\n    // Force libtest into serial execution so that the test header will be printed.\n    p.cargo(\"bench -- --test-threads=1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n[ERROR] bench failed, to rerun pass `--bin foo`\n\n\"#]])\n        .with_stdout_data(\"...\\n[..]NOPE![..]\\n...\")\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_with_lib_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"baz\"\n                path = \"src/main.rs\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![feature(test)]\n                #[cfg(test)]\n                extern crate test;\n                ///\n                /// ```rust\n                /// extern crate foo;\n                /// fn main() {\n                ///     println!(\"{}\", foo::foo());\n                /// }\n                /// ```\n                ///\n                pub fn foo(){}\n                #[bench] fn lib_bench(_b: &mut test::Bencher) {}\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n            #![feature(test)]\n            #[allow(unused_extern_crates)]\n            extern crate foo;\n            #[cfg(test)]\n            extern crate test;\n\n            fn main() {}\n\n            #[bench]\n            fn bin_bench(_b: &mut test::Bencher) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n[RUNNING] [..] (target/release/deps/baz-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest lib_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bin_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_with_deep_lib_dep() {\n    let p = project()\n        .at(\"bar\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.foo]\n                path = \"../foo\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate foo;\n            #[cfg(test)]\n            extern crate test;\n            #[bench]\n            fn bar_bench(_b: &mut test::Bencher) {\n                foo::foo();\n            }\n        \",\n        )\n        .build();\n    let _p2 = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n\n            pub fn foo() {}\n\n            #[bench]\n            fn foo_bench(_b: &mut test::Bencher) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] bar v0.0.1 ([ROOT]/bar)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/bar-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bar_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn external_bench_explicit() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bench]]\n                name = \"bench\"\n                path = \"src/bench.rs\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![feature(test)]\n                #[cfg(test)]\n                extern crate test;\n                pub fn get_hello() -> &'static str { \"Hello\" }\n\n                #[bench]\n                fn internal_bench(_b: &mut test::Bencher) {}\n            \"#,\n        )\n        .file(\n            \"src/bench.rs\",\n            r#\"\n                #![feature(test)]\n                #[allow(unused_extern_crates)]\n                extern crate foo;\n                extern crate test;\n\n                #[bench]\n                fn external_bench(_b: &mut test::Bencher) {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n[RUNNING] [..] (target/release/deps/bench-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest internal_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest external_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn external_bench_implicit() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![feature(test)]\n                #[cfg(test)]\n                extern crate test;\n\n                pub fn get_hello() -> &'static str { \"Hello\" }\n\n                #[bench]\n                fn internal_bench(_b: &mut test::Bencher) {}\n            \"#,\n        )\n        .file(\n            \"benches/external.rs\",\n            r#\"\n                #![feature(test)]\n                #[allow(unused_extern_crates)]\n                extern crate foo;\n                extern crate test;\n\n                #[bench]\n                fn external_bench(_b: &mut test::Bencher) {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n[RUNNING] [..] (target/release/deps/external-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest internal_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest external_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_autodiscover_2015() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2015\"\n\n                [features]\n                magic = []\n\n                [[bench]]\n                name = \"bench_magic\"\n                required-features = [\"magic\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"benches/bench_basic.rs\",\n            r#\"\n                #![feature(test)]\n                #[allow(unused_extern_crates)]\n                extern crate foo;\n                extern crate test;\n\n                #[bench]\n                fn bench_basic(_b: &mut test::Bencher) {}\n            \"#,\n        )\n        .file(\n            \"benches/bench_magic.rs\",\n            r#\"\n                #![feature(test)]\n                #[allow(unused_extern_crates)]\n                extern crate foo;\n                extern crate test;\n\n                #[bench]\n                fn bench_magic(_b: &mut test::Bencher) {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench bench_basic\")\n        .with_stderr_data(str![[r#\"\n[WARNING] An explicit [[bench]] section is specified in Cargo.toml which currently\ndisables Cargo from automatically inferring other benchmark targets.\nThis inference behavior will change in the Rust 2018 edition and the following\nfiles will be included as a benchmark target:\n\n* [..]bench_basic.rs\n\nThis is likely to break cargo build or cargo test as these files may not be\nready to be compiled as a benchmark target today. You can future-proof yourself\nand disable this warning by adding `autobenches = false` to your [package]\nsection. You may also move the files to a location where Cargo would not\nautomatically infer them to be a target, such as in subfolders.\n\nFor more information on this warning you can consult\nhttps://github.com/rust-lang/cargo/issues/5330\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn dont_run_examples() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"examples/dont-run-me-i-will-fail.rs\",\n            r#\"fn main() { panic!(\"Examples should not be run by 'cargo test'\"); }\"#,\n        )\n        .build();\n    p.cargo(\"bench\").run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn pass_through_command_line() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n\n            #[bench] fn foo(_b: &mut test::Bencher) {}\n            #[bench] fn bar(_b: &mut test::Bencher) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"bench bar\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bar ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 1 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"bench foo\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest foo ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 1 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n// Regression test for running cargo-bench twice with\n// tests in an rlib\n#[cargo_test(nightly, reason = \"bench\")]\nfn cargo_bench_twice() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\n            \"src/foo.rs\",\n            r#\"\n            #![crate_type = \"rlib\"]\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n\n            #[bench]\n            fn dummy_bench(b: &mut test::Bencher) { }\n            \"#,\n        )\n        .build();\n\n    for _ in 0..2 {\n        p.cargo(\"bench\").run();\n    }\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn lib_bin_same_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo\"\n                [[bin]]\n                name = \"foo\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n            #[bench] fn lib_bench(_b: &mut test::Bencher) {}\n        \",\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n            #![feature(test)]\n            #[allow(unused_extern_crates)]\n            extern crate foo;\n            #[cfg(test)]\n            extern crate test;\n\n            #[bench]\n            fn bin_bench(_b: &mut test::Bencher) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest lib_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bin_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn lib_with_standard_name() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"syntax\", \"0.0.1\"))\n        .file(\n            \"src/lib.rs\",\n            \"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n\n            /// ```\n            /// syntax::foo();\n            /// ```\n            pub fn foo() {}\n\n            #[bench]\n            fn foo_bench(_b: &mut test::Bencher) {}\n        \",\n        )\n        .file(\n            \"benches/bench.rs\",\n            \"\n            #![feature(test)]\n            extern crate syntax;\n            extern crate test;\n\n            #[bench]\n            fn bench(_b: &mut test::Bencher) { syntax::foo() }\n        \",\n        )\n        .build();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] syntax v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/syntax-[HASH][EXE])\n[RUNNING] [..] (target/release/deps/bench-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest foo_bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn lib_with_standard_name2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"syntax\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"syntax\"\n                bench = false\n                doctest = false\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"src/main.rs\",\n            \"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate syntax;\n            #[cfg(test)]\n            extern crate test;\n\n            fn main() {}\n\n            #[bench]\n            fn bench(_b: &mut test::Bencher) { syntax::foo() }\n        \",\n        )\n        .build();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] syntax v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/syntax-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_dylib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo\"\n                crate-type = [\"dylib\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate bar as the_bar;\n                #[cfg(test)]\n                extern crate test;\n\n                pub fn bar() { the_bar::baz(); }\n\n                #[bench]\n                fn foo(_b: &mut test::Bencher) {}\n            \"#,\n        )\n        .file(\n            \"benches/bench.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate foo as the_foo;\n                extern crate test;\n\n                #[bench]\n                fn foo(_b: &mut test::Bencher) { the_foo::bar(); }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"bar\"\n                crate-type = [\"dylib\"]\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"bench -v\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] [..] -C opt-level=3 [..]\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] [..] -C opt-level=3 [..]\n[RUNNING] [..] -C opt-level=3 [..]\n[RUNNING] [..] -C opt-level=3 [..]\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[..]target/release/deps/foo-[HASH][EXE] --bench`\n[RUNNING] `[..]target/release/deps/bench-[HASH][EXE] --bench`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest foo ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest foo ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.root().move_into_the_past();\n    p.cargo(\"bench -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] bar v0.0.1 ([ROOT]/foo/bar)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[..]target/release/deps/foo-[HASH][EXE] --bench`\n[RUNNING] `[..]target/release/deps/bench-[HASH][EXE] --bench`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest foo ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest foo ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_twice_with_build_cmd() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\n            \"src/lib.rs\",\n            \"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n            #[bench]\n            fn foo(_b: &mut test::Bencher) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest foo ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `bench` profile [optimized] target(s) in [..]\n[RUNNING] [..] (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest foo ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_with_examples() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"6.6.6\"\n                edition = \"2015\"\n                authors = []\n\n                [[example]]\n                name = \"teste1\"\n\n                [[bench]]\n                name = \"testb1\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![feature(test)]\n                #[cfg(test)]\n                extern crate test;\n                #[cfg(test)]\n                use test::Bencher;\n\n                pub fn f1() {\n                    println!(\"f1\");\n                }\n\n                pub fn f2() {}\n\n                #[bench]\n                fn bench_bench1(_b: &mut Bencher) {\n                    f2();\n                }\n            \"#,\n        )\n        .file(\n            \"benches/testb1.rs\",\n            \"\n            #![feature(test)]\n            extern crate foo;\n            extern crate test;\n\n            use test::Bencher;\n\n            #[bench]\n            fn bench_bench2(_b: &mut Bencher) {\n                foo::f2();\n            }\n        \",\n        )\n        .file(\n            \"examples/teste1.rs\",\n            r#\"\n                extern crate foo;\n\n                fn main() {\n                    println!(\"example1\");\n                    foo::f1();\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v6.6.6 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[RUNNING] `rustc [..]`\n[RUNNING] `rustc [..]`\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE] --bench`\n[RUNNING] `[ROOT]/foo/target/release/deps/testb1-[HASH][EXE] --bench`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bench_bench1 ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bench_bench2 ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn test_a_bench() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                name = \"foo\"\n                test = false\n                doctest = false\n\n                [[bench]]\n                name = \"b\"\n                test = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"benches/b.rs\", \"#[test] fn foo() {}\")\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] [..] (target/debug/deps/b-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest foo ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn test_bench_no_run() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"benches/bbaz.rs\",\n            r#\"\n                #![feature(test)]\n\n                extern crate test;\n\n                use test::Bencher;\n\n                #[bench]\n                fn bench_baz(_: &mut Bencher) {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench --no-run\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[EXECUTABLE] benches src/lib.rs (target/release/deps/foo-[HASH][EXE])\n[EXECUTABLE] benches/bbaz.rs (target/release/deps/bbaz-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn test_bench_no_run_emit_json() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"benches/bbaz.rs\",\n            r#\"\n                #![feature(test)]\n\n                extern crate test;\n\n                use test::Bencher;\n\n                #[bench]\n                fn bench_baz(_: &mut Bencher) {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench --no-run --message-format json\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn test_bench_no_fail_fast() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n            fn hello() -> &'static str {\n                \"hello\"\n            }\n\n            pub fn main() {\n                println!(\"{}\", hello())\n            }\n\n            #[bench]\n            fn bench_hello(_b: &mut test::Bencher) {\n                assert_eq!(hello(), \"hello\")\n            }\n\n            #[bench]\n            fn bench_nope(_b: &mut test::Bencher) {\n                assert_eq!(\"nope\", hello(), \"NOPE!\")\n            }\n            \"#,\n        )\n        .file(\n            \"benches/b1.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n                #[bench]\n                fn b1_fail(_b: &mut test::Bencher) { assert_eq!(1, 2, \"ONE=TWO\"); }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench --no-fail-fast -- --test-threads=1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/release/deps/foo-[HASH][EXE])\n[ERROR] bench failed, to rerun pass `--bin foo`\n[RUNNING] benches/b1.rs (target/release/deps/b1-[HASH][EXE])\n[ERROR] bench failed, to rerun pass `--bench b1`\n[ERROR] 2 targets failed:\n    `--bin foo`\n    `--bench b1`\n\n\"#]])\n        .with_stdout_data(\n            r#\"\n...\n[..]NOPE![..]\n...\n[..]ONE=TWO[..]\n...\n\"#,\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn test_bench_multiple_packages() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies.bar]\n                path = \"../bar\"\n\n                [dependencies.baz]\n                path = \"../baz\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let _bar = project()\n        .at(\"bar\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                authors = []\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [[bench]]\n                name = \"bbar\"\n                test = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"benches/bbar.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n\n                use test::Bencher;\n\n                #[bench]\n                fn bench_bar(_b: &mut Bencher) {}\n            \"#,\n        )\n        .build();\n\n    let _baz = project()\n        .at(\"baz\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                authors = []\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [[bench]]\n                name = \"bbaz\"\n                test = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"benches/bbaz.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n\n                use test::Bencher;\n\n                #[bench]\n                fn bench_baz(_b: &mut Bencher) {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench -p bar -p baz\")\n        .with_stderr_data(str![[r#\"\n[RUNNING] [..] (target/release/deps/bbaz-[HASH][EXE])\n[RUNNING] [..] (target/release/deps/bbar-[HASH][EXE])\n\n\"#]])\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.1.0 ([ROOT]/bar)\n[COMPILING] baz v0.1.0 ([ROOT]/baz)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/release/deps/bar-[HASH][EXE])\n[RUNNING] benches/bbar.rs (target/release/deps/bbar-[HASH][EXE])\n[RUNNING] unittests src/lib.rs (target/release/deps/baz-[HASH][EXE])\n[RUNNING] benches/bbaz.rs (target/release/deps/bbaz-[HASH][EXE])\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_all_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"benches/foo.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n\n                use test::Bencher;\n\n                #[bench]\n                fn bench_foo(_: &mut Bencher) -> () { () }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\n            \"bar/benches/bar.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n\n                use test::Bencher;\n\n                #[bench]\n                fn bench_bar(_: &mut Bencher) -> () { () }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench --workspace\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/release/deps/bar-[HASH][EXE])\n[RUNNING] benches/bar.rs (target/release/deps/bar-[HASH][EXE])\n[RUNNING] unittests src/main.rs (target/release/deps/foo-[HASH][EXE])\n[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bench_bar ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bench_foo ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_all_exclude() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                #![feature(test)]\n                #[cfg(test)]\n                extern crate test;\n\n                #[bench]\n                pub fn bar(b: &mut test::Bencher) {\n                    b.iter(|| {});\n                }\n            \"#,\n        )\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\n            \"baz/src/lib.rs\",\n            \"#[test] pub fn baz() { break_the_build(); }\",\n        )\n        .build();\n\n    p.cargo(\"bench --workspace --exclude baz\")\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bar ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_all_exclude_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                #![feature(test)]\n                #[cfg(test)]\n                extern crate test;\n\n                #[bench]\n                pub fn bar(b: &mut test::Bencher) {\n                    b.iter(|| {});\n                }\n            \"#,\n        )\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\n            \"baz/src/lib.rs\",\n            \"#[test] pub fn baz() { break_the_build(); }\",\n        )\n        .build();\n\n    p.cargo(\"bench --workspace --exclude '*z'\")\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bar ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_all_virtual_manifest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\n            \"bar/benches/bar.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n\n                use test::Bencher;\n\n                #[bench]\n                fn bench_bar(_: &mut Bencher) -> () { () }\n            \"#,\n        )\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .file(\n            \"baz/benches/baz.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n\n                use test::Bencher;\n\n                #[bench]\n                fn bench_baz(_: &mut Bencher) -> () { () }\n            \"#,\n        )\n        .build();\n\n    // The order in which bar and baz are built is not guaranteed\n    p.cargo(\"bench --workspace\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] baz v0.1.0 ([ROOT]/foo/baz)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/release/deps/bar-[HASH][EXE])\n[RUNNING] benches/bar.rs (target/release/deps/bar-[HASH][EXE])\n[RUNNING] unittests src/lib.rs (target/release/deps/baz-[HASH][EXE])\n[RUNNING] benches/baz.rs (target/release/deps/baz-[HASH][EXE])\n\n\"#]]\n            .unordered(),\n        )\n        .with_stdout_data(str![[r#\"\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bench_bar ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bench_baz ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_virtual_manifest_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() { break_the_build(); }\")\n        .file(\n            \"bar/benches/bar.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n\n                use test::Bencher;\n\n                #[bench]\n                fn bench_bar(_: &mut Bencher) -> () { break_the_build(); }\n            \"#,\n        )\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .file(\n            \"baz/benches/baz.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n\n                use test::Bencher;\n\n                #[bench]\n                fn bench_baz(_: &mut Bencher) -> () { () }\n            \"#,\n        )\n        .build();\n\n    // This should not have `bar` built or benched\n    p.cargo(\"bench -p '*z'\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] baz v0.1.0 ([ROOT]/foo/baz)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/release/deps/baz-[HASH][EXE])\n[RUNNING] benches/baz.rs (target/release/deps/baz-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bench_baz ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n// https://github.com/rust-lang/cargo/issues/4287\n#[cargo_test(nightly, reason = \"bench\")]\nfn legacy_bench_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [[bench]]\n                name = \"bench\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"src/bench.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n\n                use test::Bencher;\n\n                #[bench]\n                fn bench_foo(_: &mut Bencher) -> () { () }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[WARNING] path `src/bench.rs` was erroneously implicitly accepted for benchmark `bench`,\nplease set bench.path in Cargo.toml\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/release/deps/foo-[HASH][EXE])\n[RUNNING] src/bench.rs (target/release/deps/bench-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_virtual_manifest_all_implied() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"bar/benches/bar.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n                use test::Bencher;\n                #[bench]\n                fn bench_bar(_: &mut Bencher) -> () { () }\n            \"#,\n        )\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .file(\n            \"baz/benches/baz.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n                use test::Bencher;\n                #[bench]\n                fn bench_baz(_: &mut Bencher) -> () { () }\n            \"#,\n        )\n        .build();\n\n    // The order in which bar and baz are built is not guaranteed\n\n    p.cargo(\"bench\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] baz v0.1.0 ([ROOT]/foo/baz)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/release/deps/bar-[HASH][EXE])\n[RUNNING] benches/bar.rs (target/release/deps/bar-[HASH][EXE])\n[RUNNING] unittests src/lib.rs (target/release/deps/baz-[HASH][EXE])\n[RUNNING] benches/baz.rs (target/release/deps/baz-[HASH][EXE])\n\n\"#]]\n            .unordered(),\n        )\n        .with_stdout_data(str![[r#\"\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bench_bar ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bench_baz ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn json_artifact_includes_executable_for_benchmark() {\n    let p = project()\n        .file(\n            \"benches/benchmark.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n\n                use test::Bencher;\n\n                #[bench]\n                fn bench_foo(_: &mut Bencher) -> () { () }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench --no-run --message-format=json\")\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"executable\": \"[..]\",\n    \"features\": [],\n    \"filenames\": \"{...}\",\n    \"fresh\": false,\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.1\",\n    \"profile\": \"{...}\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": false,\n      \"doctest\": false,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"bench\"\n      ],\n      \"name\": \"benchmark\",\n      \"src_path\": \"[ROOT]/foo/benches/benchmark.rs\",\n      \"test\": false\n    }\n  },\n  {\n    \"reason\": \"build-finished\",\n    \"success\": true\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn cargo_bench_print_env_verbose() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.1\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n\n            fn hello() -> &'static str {\n                \"hello\"\n            }\n\n            pub fn main() {\n                println!(\"{}\", hello())\n            }\n\n            #[bench]\n            fn bench_hello(_b: &mut test::Bencher) {\n                assert_eq!(hello(), \"hello\")\n            }\n            \"#,\n        )\n        .build();\n    p.cargo(\"bench -vv\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] rustc[..]`\n[FINISHED] `bench` profile [optimized] target(s) in [..]\n[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] [ROOT]/foo/target/release/deps/foo-[HASH][EXE] --bench`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/binary_name.rs",
    "content": "//! Tests for `cargo-features = [\"different-binary-name\"]`.\n\nuse crate::prelude::*;\nuse cargo_test_support::install::assert_has_installed_exe;\nuse cargo_test_support::install::assert_has_not_installed_exe;\nuse cargo_test_support::is_nightly;\nuse cargo_test_support::paths;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn gated() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name =  \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"foo\"\n                filename = \"007bar\"\n                path = \"src/main.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() { assert!(true) }\")\n        .build();\n\n    // Run cargo build.\n    p.cargo(\"build\")\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `different-binary-name` is required\n\n  The package requires the Cargo feature called `different-binary-name`, but that feature is not stabilized in this version of Cargo ([..]).\n  Consider adding `cargo-features = [\"different-binary-name\"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#different-binary-name for more information about the status of this feature.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n// This test checks if:\n// 1. The correct binary is produced\n// 2. The deps file has the correct content\n// 3. Fingerprinting works\n// 4. `cargo clean` command works\nfn binary_name1() {\n    // Create the project.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"different-binary-name\"]\n\n                [package]\n                name =  \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"foo\"\n                filename = \"007bar\"\n                path = \"src/main.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() { assert!(true) }\")\n        .build();\n\n    // Run cargo build.\n    p.cargo(\"build\")\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .run();\n\n    // Check the name of the binary that cargo has generated.\n    // A binary with the name of the crate should NOT be created.\n    let foo_path = p.bin(\"foo\");\n    assert!(!foo_path.is_file());\n    // A binary with the name provided in `filename` parameter should be created.\n    let bar_path = p.bin(\"007bar\");\n    assert!(bar_path.is_file());\n\n    // Check if deps file exists.\n    let deps_path = p.bin(\"007bar\").with_extension(\"d\");\n    assert!(deps_path.is_file(), \"{:?}\", bar_path);\n\n    let depinfo = p.read_file(&deps_path);\n\n    // Prepare what content we expect to be present in deps file.\n    let deps_exp = format!(\n        \"{}: {}\",\n        p.bin(\"007bar\").to_str().unwrap(),\n        p.root().join(\"src\").join(\"main.rs\").to_str().unwrap()\n    );\n\n    // Compare actual deps content with expected deps content.\n    assert!(\n        depinfo.lines().any(|line| line == deps_exp),\n        \"Content of `{}` is incorrect\",\n        deps_path.to_string_lossy()\n    );\n\n    // Run cargo second time, to verify fingerprint.\n    p.cargo(\"build -p foo -v\")\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Run cargo clean.\n    p.cargo(\"clean -p foo\")\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .run();\n\n    // Check if the appropriate file was removed.\n    assert!(\n        !bar_path.is_file(),\n        \"`cargo clean` did not remove the correct files\"\n    );\n}\n\n#[cargo_test]\n// This test checks if:\n// 1. Check `cargo run`\n// 2. Check `cargo test`\n// 3. Check `cargo install/uninstall`\nfn binary_name2() {\n    // Create the project.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"different-binary-name\"]\n\n                [package]\n                name =  \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"foo\"\n                filename = \"007bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn hello(name: &str) -> String {\n                    format!(\"Hello, {}!\", name)\n                }\n\n                fn main() {\n                    println!(\"{}\", hello(\"crabs\"));\n                }\n\n                #[cfg(test)]\n                mod tests {\n                    use super::*;\n\n                    #[test]\n                    fn check_crabs() {\n                        assert_eq!(hello(\"crabs\"), \"Hello, crabs!\");\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    // Run cargo build.\n    p.cargo(\"build\")\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .run();\n\n    // Check the name of the binary that cargo has generated.\n    // A binary with the name of the crate should NOT be created.\n    let foo_path = p.bin(\"foo\");\n    assert!(!foo_path.is_file());\n    // A binary with the name provided in `filename` parameter should be created.\n    let bar_path = p.bin(\"007bar\");\n    assert!(bar_path.is_file());\n\n    // Check if `cargo test` works\n    p.cargo(\"test\")\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/debug/deps/foo-[..][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest tests::check_crabs ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    // Check if `cargo run` is able to execute the binary\n    p.cargo(\"run\")\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .with_stdout_data(str![[r#\"\nHello, crabs!\n\n\"#]])\n        .run();\n\n    p.cargo(\"install\")\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .run();\n\n    assert_has_installed_exe(paths::cargo_home(), \"007bar\");\n\n    p.cargo(\"uninstall\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/007bar[EXE]\n\n\"#]])\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .run();\n\n    assert_has_not_installed_exe(paths::cargo_home(), \"007bar\");\n}\n\n#[cargo_test]\nfn check_env_vars() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"different-binary-name\"]\n\n                [package]\n                name =  \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"foo\"\n                filename = \"007bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    println!(\"{}\", option_env!(\"CARGO_BIN_NAME\").unwrap());\n                }\n            \"#,\n        )\n        .file(\n            \"tests/integration.rs\",\n            r#\"\n                #[test]\n                fn check_env_vars2() {\n                    let value = option_env!(\"CARGO_BIN_EXE_007bar\").expect(\"Could not find environment variable.\");\n                    assert!(value.contains(\"007bar\"));\n                }\n            \"#\n        )\n        .build();\n\n    // Run cargo build.\n    p.cargo(\"build\")\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .run();\n    p.cargo(\"run\")\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .with_stdout_data(str![[r#\"\n007bar\n\n\"#]])\n        .run();\n    p.cargo(\"test\")\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .with_status(0)\n        .run();\n}\n\n#[cargo_test]\nfn check_msg_format_json() {\n    // Create the project.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"different-binary-name\"]\n\n                [package]\n                name =  \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"foo\"\n                filename = \"007bar\"\n                path = \"src/main.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() { assert!(true) }\")\n        .build();\n\n    // Run cargo build.\n    p.cargo(\"build --message-format=json\")\n        .masquerade_as_nightly_cargo(&[\"different-binary-name\"])\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"executable\": \"[ROOT]/foo/target/debug/007bar[EXE]\",\n    \"features\": [],\n    \"filenames\": \"{...}\",\n    \"fresh\": false,\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.1\",\n    \"profile\": \"{...}\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": \"{...}\"\n  },\n  {\n    \"reason\": \"build-finished\",\n    \"success\": true\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn targets_with_relative_path_in_workspace_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"relative-bar\"]\n            resolver = \"2\"\n        \"#,\n        )\n        .file(\n            \"relative-bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"relative-bar\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                build = \"./build.rs\"\n\n                [[bin]]\n                name = \"bar\"\n                path = \"./src/main.rs\"\n\n                [lib]\n                name = \"lib\"\n                path = \"./src/lib.rs\"\n\n                [[example]]\n                name = \"example\"\n                path = \"./example.rs\"\n\n                [[test]]\n                name = \"test\"\n                path = \"./test.rs\"\n\n                [[bench]]\n                name = \"bench\"\n                path = \"./bench.rs\"\n            \"#,\n        )\n        .file(\"relative-bar/build.rs\", \"fn main() { let a = 1; }\")\n        .file(\"relative-bar/src/main.rs\", \"fn main() { let a = 1; }\")\n        .file(\"relative-bar/src/lib.rs\", \"fn a() {}\")\n        .file(\"relative-bar/example.rs\", \"fn main() { let a = 1; }\")\n        .file(\n            \"relative-bar/test.rs\",\n            r#\"\n                fn main() {}\n\n                #[test]\n                fn test_a() { let a = 1; } \n            \"#,\n        )\n        .file(\n            \"relative-bar/bench.rs\",\n            r#\"  \n                #![feature(test)]\n                #[cfg(test)]\n                extern crate test;\n\n                #[bench]\n                fn bench_a(_b: &mut test::Bencher) { let a = 1; }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n...\n --> relative-bar/build.rs:1:17\n...\n --> relative-bar/src/lib.rs:1:4\n...\n --> relative-bar/src/main.rs:1:17\n...\n\"#]])\n        .run();\n\n    p.cargo(\"check --example example\")\n        .with_stderr_data(str![[r#\"\n...\n --> relative-bar/example.rs:1:17\n...\n\"#]])\n        .run();\n\n    p.cargo(\"check --test test\")\n        .with_stderr_data(str![[r#\"\n...\n --> relative-bar/test.rs:5:35\n...\n\"#]])\n        .run();\n\n    if is_nightly() {\n        p.cargo(\"check --bench bench\")\n            .with_stderr_data(str![[r#\"\n...\n --> relative-bar/bench.rs:7:58\n...\n\"#]])\n            .run();\n    }\n\n    // Disable Cargo target auto-discovery.\n    p.change_file(\n        \"relative-bar/Cargo.toml\",\n        r#\"\n            [package]\n            name = \"relative-bar\"\n            version = \"0.1.0\"\n            edition = \"2021\"\n\n            autolib = false\n            autobins = false\n            autoexamples = false\n            autotests = false\n            autobenches = false\n\n            build = \"./build.rs\"\n\n            [[bin]]\n            name = \"bar\"\n            path = \"./src/main.rs\"\n\n            [lib]\n            name = \"lib\"\n            path = \"./src/lib.rs\"\n\n            [[example]]\n            name = \"example\"\n            path = \"./example.rs\"\n\n            [[test]]\n            name = \"test\"\n            path = \"./test.rs\"\n\n            [[bench]]\n            name = \"bench\"\n            path = \"./bench.rs\"\n        \"#,\n    );\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n...\n --> relative-bar/build.rs:1:17\n...\n --> relative-bar/src/lib.rs:1:4\n...\n --> relative-bar/src/main.rs:1:17\n...\n\"#]])\n        .run();\n\n    p.cargo(\"check --example example\")\n        .with_stderr_data(str![[r#\"\n...\n --> relative-bar/example.rs:1:17\n...\n\"#]])\n        .run();\n\n    p.cargo(\"check --test test\")\n        .with_stderr_data(str![[r#\"\n...\n --> relative-bar/test.rs:5:35\n...\n\"#]])\n        .run();\n\n    if is_nightly() {\n        p.cargo(\"check --bench bench\")\n            .with_stderr_data(str![[r#\"\n...\n --> relative-bar/bench.rs:7:58\n...\n\"#]])\n            .run();\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/build.rs",
    "content": "//! Tests for the `cargo build` command.\n\nuse std::env;\nuse std::fs;\nuse std::io::Read;\nuse std::process::Stdio;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_exe;\nuse crate::utils::cargo_process;\nuse crate::utils::tools;\nuse cargo::GlobalContext;\nuse cargo::core::Shell;\nuse cargo::core::Workspace;\nuse cargo::core::compiler::UserIntent;\nuse cargo::ops::CompileOptions;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::paths::root;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{\n    Execs, ProjectBuilder, basic_bin_manifest, basic_lib_manifest, basic_manifest, git, is_nightly,\n    main_file, paths, process, project, rustc_host, sleep_ms, symlink_supported, t,\n};\nuse cargo_util::paths::dylib_path_envvar;\n\n#[cargo_test]\nfn cargo_compile_simple() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\ni am foo\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_with_symlink_to_path_dependency_with_build_script_in_git() {\n    if !symlink_supported() {\n        return;\n    }\n\n    let root = paths::root();\n    git::repo(&root)\n        .nocommit_file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n               [dependencies]\n               # the path leads through a symlink, 'symlink-to-original' is a worktree root,\n               # and symlink-to-dir/ is a symlink to a sub-directory to be stepped through.\n               lib = { version = \"0.1.0\", path = \"symlink-to-original/symlink-to-dir/lib\" }\n            \"#,\n        )\n        .nocommit_file(\"src/main.rs\", \"fn main() { }\")\n        .nocommit_file(\"original/dir/lib/build.rs\", \"fn main() {}\")\n        .nocommit_file(\n            \"original/dir/lib/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"lib\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n              \"#,\n        )\n        .nocommit_file(\"original/dir/lib/src/lib.rs\", \"\")\n        .nocommit_symlink_dir(\"original\", \"symlink-to-original\")\n        .nocommit_symlink_dir(\"original/dir\", \"original/symlink-to-dir\")\n        .build();\n\n    // It is necessary to have a sub-repository and to add files so there is an index.\n    let repo = git::init(&root.join(\"original\"));\n    git::add(&repo);\n    cargo_process(\"build\").run();\n}\n\n#[cargo_test]\nfn cargo_fail_with_no_stderr() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", &String::from(\"refusal\"))\n        .build();\n    p.cargo(\"build --message-format=json\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n\n\"#]])\n        .run();\n}\n\n/// Checks that the `CARGO_INCREMENTAL` environment variable results in\n/// `rustc` getting `-C incremental` passed to it.\n#[cargo_test]\nfn cargo_compile_incremental() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build -v\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] -C incremental=[ROOT]/foo/target/debug/incremental[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"test -v\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] -C incremental=[ROOT]/foo/target/debug/incremental[..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn incremental_profile() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.dev]\n                incremental = false\n\n                [profile.release]\n                incremental = true\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .env_remove(\"CARGO_INCREMENTAL\")\n        .with_stderr_does_not_contain(\"[..]C incremental=[..]\")\n        .run();\n\n    p.cargo(\"build -v\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_contains(\"[..]C incremental=[..]\")\n        .run();\n\n    p.cargo(\"build --release -v\")\n        .env_remove(\"CARGO_INCREMENTAL\")\n        .with_stderr_contains(\"[..]C incremental=[..]\")\n        .run();\n\n    p.cargo(\"build --release -v\")\n        .env(\"CARGO_INCREMENTAL\", \"0\")\n        .with_stderr_does_not_contain(\"[..]C incremental=[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn incremental_config() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                incremental = false\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .env_remove(\"CARGO_INCREMENTAL\")\n        .with_stderr_does_not_contain(\"[..]C incremental=[..]\")\n        .run();\n\n    p.cargo(\"build -v\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_contains(\"[..]C incremental=[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_redundant_default_mode() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build --debug\")\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '--debug' found\n\n  tip: `--debug` is the default for `cargo build`; instead `--release` is supported\n\nUsage: cargo[EXE] build [OPTIONS]\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_unsupported_short_config_flag() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build -c net.git-fetch-with-cli=true\")\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '-c' found\n\n  tip: a similar argument exists: '--config'\n\nUsage: cargo[EXE] build [OPTIONS]\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_workspace_excluded() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"build --workspace --exclude foo\")\n        .with_stderr_data(str![[r#\"\n[ERROR] no packages to compile\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_manifest_path() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build --manifest-path foo/Cargo.toml\")\n        .cwd(p.root().parent().unwrap())\n        .run();\n    assert!(p.bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn cargo_compile_with_wrong_manifest_path_flag() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build --path foo/Cargo.toml\")\n        .cwd(p.root().parent().unwrap())\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '--path' found\n\n  tip: a similar argument exists: '--manifest-path'\n\nUsage: cargo[EXE] build [OPTIONS]\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn chdir_gated() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .build();\n    p.cargo(\"-C foo build\")\n        .cwd(p.root().parent().unwrap())\n        .with_stderr_data(str![[r#\"\n[ERROR] the `-C` flag is unstable, pass `-Z unstable-options` on the nightly channel to enable it\n\n\"#]])\n        .with_status(101)\n        .run();\n    // No masquerade should also fail.\n    p.cargo(\"-C foo -Z unstable-options build\")\n        .cwd(p.root().parent().unwrap())\n        .with_stderr_data(str![[r#\"\n[ERROR] the `-C` flag is unstable, pass `-Z unstable-options` on the nightly channel to enable it\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_directory_not_cwd() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .file(\".cargo/config.toml\", &\"\")\n        .build();\n\n    p.cargo(\"-Zunstable-options -C foo build\")\n        .masquerade_as_nightly_cargo(&[\"chdir\"])\n        .cwd(p.root().parent().unwrap())\n        .run();\n    assert!(p.bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn cargo_compile_with_unsupported_short_unstable_feature_flag() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .file(\".cargo/config.toml\", &\"\")\n        .build();\n\n    p.cargo(\"-zunstable-options -C foo build\")\n        .masquerade_as_nightly_cargo(&[\"chdir\"])\n        .cwd(p.root().parent().unwrap())\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '-z' found\n\n  tip: a similar argument exists: '-Z'\n\nUsage: cargo [..][OPTIONS] [COMMAND]\n       cargo [..][OPTIONS] -Zscript <MANIFEST_RS> [ARGS]...\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_directory_not_cwd_with_invalid_config() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .file(\".cargo/config.toml\", &\"!\")\n        .build();\n\n    p.cargo(\"-Zunstable-options -C foo build\")\n        .masquerade_as_nightly_cargo(&[\"chdir\"])\n        .cwd(p.root().parent().unwrap())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not load Cargo configuration\n\nCaused by:\n  could not parse TOML configuration in `[ROOT]/foo/.cargo/config.toml`\n\nCaused by:\n  TOML parse error at line 1, column 2\n    |\n  1 | !\n    |  ^\n  key with no value, expected `=`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_invalid_manifest() {\n    let p = project().file(\"Cargo.toml\", \"\").build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  manifest is missing either a `[package]` or a `[workspace]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_invalid_manifest2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            \"\n                [package]\n                foo = bar\n            \",\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] string values must be quoted, expected literal string\n --> Cargo.toml:3:23\n  |\n3 |                 foo = bar\n  |                       ^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_invalid_manifest3() {\n    let p = project().file(\"src/Cargo.toml\", \"a = bar\").build();\n\n    p.cargo(\"build --manifest-path src/Cargo.toml\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] string values must be quoted, expected literal string\n --> src/Cargo.toml:1:5\n  |\n1 | a = bar\n  |     ^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_duplicate_build_targets() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"main\"\n                path = \"src/main.rs\"\n                crate-type = [\"dylib\"]\n\n                [dependencies]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"#![allow(warnings)] fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[WARNING] file `[ROOT]/foo/src/main.rs` found to be present in multiple build targets:\n  * `lib` target `main`\n  * `bin` target `foo`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_invalid_version() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0\"))\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected end of input while parsing minor version number\n --> Cargo.toml:4:19\n  |\n4 |         version = \"1.0\"\n  |                   ^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_empty_package_name() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"\", \"0.0.0\"))\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package name cannot be empty\n --> Cargo.toml:3:16\n  |\n3 |         name = \"\"\n  |                ^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_invalid_package_name() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo@bar\", \"0.0.0\"))\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid character `@` in package name: `foo@bar`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)\n --> Cargo.toml:3:16\n  |\n3 |         name = \"foo@bar\"\n  |                ^^^^^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_invalid_bin_target_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  binary target names cannot be empty\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_forbidden_bin_target_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"build\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the binary target name `build` is forbidden, it conflicts with cargo's build directory names\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_bin_and_crate_type() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"the_foo_bin\"\n                path = \"src/foo.rs\"\n                crate-type = [\"cdylib\", \"rlib\"]\n            \"#,\n        )\n        .file(\"src/foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the target `the_foo_bin` is a binary and can't have any crate-types set (currently \"cdylib, rlib\")\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_api_exposes_artifact_paths() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"the_foo_bin\"\n                path = \"src/bin.rs\"\n\n                [lib]\n                name = \"the_foo_lib\"\n                path = \"src/foo.rs\"\n                crate-type = [\"cdylib\", \"rlib\"]\n            \"#,\n        )\n        .file(\"src/foo.rs\", \"pub fn bar() {}\")\n        .file(\"src/bin.rs\", \"pub fn main() {}\")\n        .build();\n\n    let shell = Shell::from_write(Box::new(Vec::new()));\n    let gctx = GlobalContext::new(shell, env::current_dir().unwrap(), paths::home());\n    let ws = Workspace::new(&p.root().join(\"Cargo.toml\"), &gctx).unwrap();\n    let compile_options = CompileOptions::new(ws.gctx(), UserIntent::Build).unwrap();\n\n    let result = cargo::ops::compile(&ws, &compile_options).unwrap();\n\n    assert_eq!(1, result.binaries.len());\n    assert!(result.binaries[0].path.exists());\n    assert!(\n        result.binaries[0]\n            .path\n            .to_str()\n            .unwrap()\n            .contains(\"the_foo_bin\")\n    );\n\n    assert_eq!(1, result.cdylibs.len());\n    // The exact library path varies by platform, but should certainly exist at least\n    assert!(result.cdylibs[0].path.exists());\n    assert!(\n        result.cdylibs[0]\n            .path\n            .to_str()\n            .unwrap()\n            .contains(\"the_foo_lib\")\n    );\n}\n\n#[cargo_test]\nfn cargo_compile_with_bin_and_proc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"the_foo_bin\"\n                path = \"src/foo.rs\"\n                proc-macro = true\n            \"#,\n        )\n        .file(\"src/foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the target `the_foo_bin` is a binary and can't have `proc-macro` set `true`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_invalid_lib_target_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [lib]\n                name = \"\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  library target names cannot be empty\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_invalid_non_numeric_dep_version() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                crossbeam = \"y\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  failed to parse the version requirement `y` for dependency `crossbeam`\n\nCaused by:\n  unexpected character 'y' while parsing major version number\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_without_manifest() {\n    let p = project().no_manifest().build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not find `Cargo.toml` in `[ROOT]/foo` or any parent directory\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[cfg(target_os = \"linux\")]\nfn cargo_compile_with_lowercase_cargo_toml() {\n    let p = project()\n        .no_manifest()\n        .file(\"cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/lib.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not find `Cargo.toml` in `[ROOT]/foo` or any parent directory, but found cargo.toml please try to rename it to Cargo.toml\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_invalid_code() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"invalid rust code!\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[ERROR] [..]\n...\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n\n\"#]])\n        .run();\n    assert!(p.root().join(\"Cargo.lock\").is_file());\n}\n\n#[cargo_test]\nfn cargo_compile_with_invalid_code_in_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n                [dependencies.baz]\n                path = \"../baz\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"invalid rust code!\")\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"invalid rust code!\")\n        .build();\n    let _baz = project()\n        .at(\"baz\")\n        .file(\"Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"invalid rust code!\")\n        .build();\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] bar v0.1.0 ([ROOT]/bar)\n[COMPILING] baz v0.1.0 ([ROOT]/baz)\n[ERROR] could not compile `bar` (lib) due to 1 previous error\n[ERROR] could not compile `baz` (lib) due to 1 previous error\n...\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_warnings_in_the_root_package() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {} fn dead() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[WARNING] [..]dead[..]\n...\n[WARNING] `foo` (bin \"foo\") generated 1 warning\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_warnings_in_a_dep_package() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n\n                [[bin]]\n\n                name = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\n            \"bar/src/bar.rs\",\n            r#\"\n                pub fn gimme() -> &'static str {\n                    \"test passed\"\n                }\n\n                fn dead() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[WARNING] [..]dead[..]\n...\n[WARNING] `bar` (lib) generated 1 warning\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\ntest passed\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_nested_deps_inferred() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n                path = 'bar'\n\n                [[bin]]\n                name = \"foo\"\n            \"#,\n        )\n        .file(\"src/foo.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.baz]\n                path = \"../baz\"\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                extern crate baz;\n\n                pub fn gimme() -> String {\n                    baz::gimme()\n                }\n            \"#,\n        )\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.5.0\"))\n        .file(\n            \"baz/src/lib.rs\",\n            r#\"\n                pub fn gimme() -> String {\n                    \"test passed\".to_string()\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!p.bin(\"libbar.rlib\").is_file());\n    assert!(!p.bin(\"libbaz.rlib\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\ntest passed\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_nested_deps_correct_bin() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n\n                [[bin]]\n                name = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.baz]\n                path = \"../baz\"\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                extern crate baz;\n\n                pub fn gimme() -> String {\n                    baz::gimme()\n                }\n            \"#,\n        )\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.5.0\"))\n        .file(\n            \"baz/src/lib.rs\",\n            r#\"\n                pub fn gimme() -> String {\n                    \"test passed\".to_string()\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!p.bin(\"libbar.rlib\").is_file());\n    assert!(!p.bin(\"libbaz.rlib\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\ntest passed\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_nested_deps_shorthand() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.baz]\n                path = \"../baz\"\n\n                [lib]\n\n                name = \"bar\"\n            \"#,\n        )\n        .file(\n            \"bar/src/bar.rs\",\n            r#\"\n                extern crate baz;\n\n                pub fn gimme() -> String {\n                    baz::gimme()\n                }\n            \"#,\n        )\n        .file(\"baz/Cargo.toml\", &basic_lib_manifest(\"baz\"))\n        .file(\n            \"baz/src/baz.rs\",\n            r#\"\n                pub fn gimme() -> String {\n                    \"test passed\".to_string()\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!p.bin(\"libbar.rlib\").is_file());\n    assert!(!p.bin(\"libbaz.rlib\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\ntest passed\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_nested_deps_longhand() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n\n                [[bin]]\n\n                name = \"foo\"\n            \"#,\n        )\n        .file(\"src/foo.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.baz]\n                path = \"../baz\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n\n                [lib]\n\n                name = \"bar\"\n            \"#,\n        )\n        .file(\n            \"bar/src/bar.rs\",\n            r#\"\n                extern crate baz;\n\n                pub fn gimme() -> String {\n                    baz::gimme()\n                }\n            \"#,\n        )\n        .file(\"baz/Cargo.toml\", &basic_lib_manifest(\"baz\"))\n        .file(\n            \"baz/src/baz.rs\",\n            r#\"\n                pub fn gimme() -> String {\n                    \"test passed\".to_string()\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!p.bin(\"libbar.rlib\").is_file());\n    assert!(!p.bin(\"libbaz.rlib\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\ntest passed\n\n\"#]])\n        .run();\n}\n\n// Check that Cargo gives a sensible error if a dependency can't be found\n// because of a name mismatch.\n#[cargo_test]\nfn cargo_compile_with_dep_name_mismatch() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [[bin]]\n\n                name = \"foo\"\n\n                [dependencies.notquitebar]\n\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/bin/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[\"bar\"]))\n        .file(\"bar/Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\"bar/src/bar.rs\", &main_file(r#\"\"i am bar\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no matching package named `notquitebar` found\nlocation searched: [ROOT]/foo/bar\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n}\n\n// Ensure that renamed deps have a valid name\n#[cargo_test]\nfn cargo_compile_with_invalid_dep_rename() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"buggin\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                \"haha this isn't a valid name 🐛\" = { package = \"libc\", version = \"0.1\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"What's good?\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)\n --> Cargo.toml:8:17\n  |\n8 |                 \"haha this isn't a valid name 🐛\" = { package = \"libc\", version = \"0.1\" }\n  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_filename() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"src/bin/a.rs\",\n            r#\"\n                extern crate foo;\n                fn main() { println!(\"hello a.rs\"); }\n            \"#,\n        )\n        .file(\"examples/a.rs\", r#\"fn main() { println!(\"example\"); }\"#)\n        .build();\n\n    p.cargo(\"build --bin bin.rs\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no bin target named `bin.rs` in default-run packages\n[HELP] available bin targets:\n    a\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --bin a.rs\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no bin target named `a.rs` in default-run packages\n\n[HELP] a target with a similar name exists: `a`\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --example example.rs\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no example target named `example.rs` in default-run packages\n[HELP] available example targets:\n    a\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --example a.rs\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no example target named `a.rs` in default-run packages\n\n[HELP] a target with a similar name exists: `a`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn incompatible_dependencies() {\n    Package::new(\"bad\", \"0.1.0\").publish();\n    Package::new(\"bad\", \"1.0.0\").publish();\n    Package::new(\"bad\", \"1.0.1\").publish();\n    Package::new(\"bad\", \"1.0.2\").publish();\n    Package::new(\"bar\", \"0.1.0\").dep(\"bad\", \"0.1.0\").publish();\n    Package::new(\"baz\", \"0.1.1\").dep(\"bad\", \"=1.0.0\").publish();\n    Package::new(\"baz\", \"0.1.0\").dep(\"bad\", \"=1.0.0\").publish();\n    Package::new(\"qux\", \"0.1.2\").dep(\"bad\", \">=1.0.1\").publish();\n    Package::new(\"qux\", \"0.1.1\").dep(\"bad\", \">=1.0.1\").publish();\n    Package::new(\"qux\", \"0.1.0\").dep(\"bad\", \">=1.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1.0\"\n                baz = \"0.1.0\"\n                qux = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for `bad`.\n    ... required by package `qux v0.1.0`\n    ... which satisfies dependency `qux = \"^0.1.0\"` of package `foo v0.0.1 ([ROOT]/foo)`\nversions that meet the requirements `>=1.0.1` are: 1.0.2, 1.0.1\n\nall possible versions conflict with previously selected packages.\n\n  previously selected package `bad v1.0.0`\n    ... which satisfies dependency `bad = \"=1.0.0\"` of package `baz v0.1.0`\n    ... which satisfies dependency `baz = \"^0.1.0\"` of package `foo v0.0.1 ([ROOT]/foo)`\n\nfailed to select a version for `bad` which could resolve this conflict\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn incompatible_dependencies_with_multi_semver() {\n    Package::new(\"bad\", \"1.0.0\").publish();\n    Package::new(\"bad\", \"1.0.1\").publish();\n    Package::new(\"bad\", \"2.0.0\").publish();\n    Package::new(\"bad\", \"2.0.1\").publish();\n    Package::new(\"bar\", \"0.1.0\").dep(\"bad\", \"=1.0.0\").publish();\n    Package::new(\"baz\", \"0.1.0\").dep(\"bad\", \">=2.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1.0\"\n                baz = \"0.1.0\"\n                bad = \">=1.0.1, <=2.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for `bad`.\n    ... required by package `foo v0.0.1 ([ROOT]/foo)`\nversions that meet the requirements `>=1.0.1, <=2.0.0` are: 2.0.0, 1.0.1\n\nall possible versions conflict with previously selected packages.\n\n  previously selected package `bad v2.0.1`\n    ... which satisfies dependency `bad = \">=2.0.1\"` of package `baz v0.1.0`\n    ... which satisfies dependency `baz = \"^0.1.0\"` of package `foo v0.0.1 ([ROOT]/foo)`\n\n  previously selected package `bad v1.0.0`\n    ... which satisfies dependency `bad = \"=1.0.0\"` of package `bar v0.1.0`\n    ... which satisfies dependency `bar = \"^0.1.0\"` of package `foo v0.0.1 ([ROOT]/foo)`\n\nfailed to select a version for `bad` which could resolve this conflict\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn compile_path_dep_then_change_version() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    p.change_file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.2\"));\n\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn ignores_carriage_return_in_lockfile() {\n    let p = project()\n        .file(\"src/main.rs\", \"mod a; fn main() {}\")\n        .file(\"src/a.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    let lock = p.read_lockfile();\n    p.change_file(\"Cargo.lock\", &lock.replace(\"\\n\", \"\\r\\n\"));\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn cargo_default_env_metadata_env_var() {\n    // Ensure that path dep + dylib + env_var get metadata\n    // (even though path_dep + dylib should not)\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"// hi\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"bar\"\n                crate-type = [\"dylib\"]\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"// hello\")\n        .build();\n\n    let dll_prefix = env::consts::DLL_PREFIX;\n    let dll_suffix = env::consts::DLL_SUFFIX;\n\n    // No metadata on libbar since it's a dylib path dependency\n    p.cargo(\"build -v\")\n        .with_stderr_data(format!(\n            \"\\\n...\n[RUNNING] `rustc --crate-name foo [..]--extern bar=[ROOT]/foo/target/debug/deps/{dll_prefix}bar{dll_suffix}`\n...\n\"))\n        .run();\n\n    p.cargo(\"clean\").run();\n\n    // If you set the env-var, then we expect metadata on libbar\n    p.cargo(\"build -v\")\n        .env(\"__CARGO_DEFAULT_LIB_METADATA\", \"stable\")\n        .with_stderr_data(format!(\n            \"\\\n...\n[RUNNING] `rustc --crate-name foo [..]--extern bar=[ROOT]/foo/target/debug/deps/{dll_prefix}bar-[..]{dll_suffix}`\n...\n\"))\n        .run();\n}\n\n#[cargo_test]\nfn crate_env_vars() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.5.1-alpha.1\"\n            edition = \"2015\"\n            description = \"This is foo\"\n            homepage = \"https://example.com\"\n            repository = \"https://example.com/repo.git\"\n            authors = [\"wycats@example.com\"]\n            license = \"MIT OR Apache-2.0\"\n            license-file = \"license.txt\"\n            rust-version = \"1.61.0\"\n            readme = \"../../README.md\"\n\n            [[bin]]\n            name = \"foo-bar\"\n            path = \"src/main.rs\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                extern crate foo;\n\n\n                static VERSION_MAJOR: &'static str = env!(\"CARGO_PKG_VERSION_MAJOR\");\n                static VERSION_MINOR: &'static str = env!(\"CARGO_PKG_VERSION_MINOR\");\n                static VERSION_PATCH: &'static str = env!(\"CARGO_PKG_VERSION_PATCH\");\n                static VERSION_PRE: &'static str = env!(\"CARGO_PKG_VERSION_PRE\");\n                static VERSION: &'static str = env!(\"CARGO_PKG_VERSION\");\n                static CARGO_MANIFEST_DIR: &'static str = env!(\"CARGO_MANIFEST_DIR\");\n                static CARGO_MANIFEST_PATH: &'static str = env!(\"CARGO_MANIFEST_PATH\");\n                static PKG_NAME: &'static str = env!(\"CARGO_PKG_NAME\");\n                static HOMEPAGE: &'static str = env!(\"CARGO_PKG_HOMEPAGE\");\n                static REPOSITORY: &'static str = env!(\"CARGO_PKG_REPOSITORY\");\n                static LICENSE: &'static str = env!(\"CARGO_PKG_LICENSE\");\n                static LICENSE_FILE: &'static str = env!(\"CARGO_PKG_LICENSE_FILE\");\n                static DESCRIPTION: &'static str = env!(\"CARGO_PKG_DESCRIPTION\");\n                static RUST_VERSION: &'static str = env!(\"CARGO_PKG_RUST_VERSION\");\n                static README: &'static str = env!(\"CARGO_PKG_README\");\n                static BIN_NAME: &'static str = env!(\"CARGO_BIN_NAME\");\n                static CRATE_NAME: &'static str = env!(\"CARGO_CRATE_NAME\");\n\n\n                fn main() {\n                    let s = format!(\"{}-{}-{} @ {} in {} file {}\", VERSION_MAJOR,\n                                    VERSION_MINOR, VERSION_PATCH, VERSION_PRE,\n                                    CARGO_MANIFEST_DIR, CARGO_MANIFEST_PATH);\n                     assert_eq!(s, foo::version());\n                     println!(\"{}\", s);\n                     assert_eq!(\"foo\", PKG_NAME);\n                     assert_eq!(\"foo-bar\", BIN_NAME);\n                     assert_eq!(\"foo_bar\", CRATE_NAME);\n                     assert_eq!(\"https://example.com\", HOMEPAGE);\n                     assert_eq!(\"https://example.com/repo.git\", REPOSITORY);\n                     assert_eq!(\"MIT OR Apache-2.0\", LICENSE);\n                     assert_eq!(\"license.txt\", LICENSE_FILE);\n                     assert_eq!(\"This is foo\", DESCRIPTION);\n                     assert_eq!(\"1.61.0\", RUST_VERSION);\n                     assert_eq!(\"../../README.md\", README);\n                    let s = format!(\"{}.{}.{}-{}\", VERSION_MAJOR,\n                                    VERSION_MINOR, VERSION_PATCH, VERSION_PRE);\n                    assert_eq!(s, VERSION);\n\n                    // Verify CARGO_TARGET_TMPDIR isn't set for bins\n                    assert!(option_env!(\"CARGO_TARGET_TMPDIR\").is_none());\n                }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                use std::env;\n                use std::path::PathBuf;\n\n                pub fn version() -> String {\n                    format!(\"{}-{}-{} @ {} in {} file {}\",\n                            env!(\"CARGO_PKG_VERSION_MAJOR\"),\n                            env!(\"CARGO_PKG_VERSION_MINOR\"),\n                            env!(\"CARGO_PKG_VERSION_PATCH\"),\n                            env!(\"CARGO_PKG_VERSION_PRE\"),\n                            env!(\"CARGO_MANIFEST_DIR\"),\n                            env!(\"CARGO_MANIFEST_PATH\"))\n                }\n\n                pub fn check_no_int_test_env() {\n                    env::var(\"CARGO_TARGET_DIR\").unwrap_err();\n                }\n\n                pub fn check_tmpdir(tmp: Option<&'static str>) {\n                    let tmpdir: PathBuf = tmp.unwrap().into();\n\n                    let exe: PathBuf = env::current_exe().unwrap().into();\n                    let mut expected: PathBuf = exe.parent().unwrap()\n                        .parent().unwrap()\n                        .parent().unwrap()\n                        .into();\n                    expected.push(\"tmp\");\n                    assert_eq!(tmpdir, expected);\n\n                    // Check that CARGO_TARGET_TMPDIR isn't set for lib code\n                    assert!(option_env!(\"CARGO_TARGET_TMPDIR\").is_none());\n                    env::var(\"CARGO_TARGET_TMPDIR\").unwrap_err();\n                }\n\n                #[test]\n                fn unit_env_cargo_target_tmpdir() {\n                    // Check that CARGO_TARGET_TMPDIR isn't set for unit tests\n                    assert!(option_env!(\"CARGO_TARGET_TMPDIR\").is_none());\n                    env::var(\"CARGO_TARGET_TMPDIR\").unwrap_err();\n                }\n            \"#,\n        )\n        .file(\n            \"examples/ex-env-vars.rs\",\n            r#\"\n                static PKG_NAME: &'static str = env!(\"CARGO_PKG_NAME\");\n                static BIN_NAME: &'static str = env!(\"CARGO_BIN_NAME\");\n                static CRATE_NAME: &'static str = env!(\"CARGO_CRATE_NAME\");\n\n                fn main() {\n                    assert_eq!(\"foo\", PKG_NAME);\n                    assert_eq!(\"ex-env-vars\", BIN_NAME);\n                    assert_eq!(\"ex_env_vars\", CRATE_NAME);\n\n                    // Verify CARGO_TARGET_TMPDIR isn't set for examples\n                    assert!(option_env!(\"CARGO_TARGET_TMPDIR\").is_none());\n                }\n            \"#,\n        )\n        .file(\n            \"tests/env.rs\",\n            r#\"\n                #[test]\n                fn integration_env_cargo_target_tmpdir() {\n                    foo::check_tmpdir(option_env!(\"CARGO_TARGET_TMPDIR\"));\n                }\n            \"#,\n        );\n\n    let p = if is_nightly() {\n        p.file(\n            \"benches/env.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n                use test::Bencher;\n\n                #[bench]\n                fn bench_env_cargo_target_tmpdir(_: &mut Bencher) {\n                    foo::check_tmpdir(option_env!(\"CARGO_TARGET_TMPDIR\"));\n                }\n            \"#,\n        )\n        .build()\n    } else {\n        p.build()\n    };\n\n    println!(\"build\");\n    p.cargo(\"build -v\").run();\n\n    println!(\"bin\");\n    p.process(&p.bin(\"foo-bar\"))\n        .with_stdout_data(str![[r#\"\n0-5-1 @ alpha.1 in [ROOT]/foo file [ROOT]/foo/Cargo.toml\n\n\"#]])\n        .run();\n\n    println!(\"example\");\n    p.cargo(\"run --example ex-env-vars -v\").run();\n\n    println!(\"test\");\n    p.cargo(\"test -v\").run();\n\n    if is_nightly() {\n        println!(\"bench\");\n        p.cargo(\"bench -v\").run();\n    }\n}\n\n#[cargo_test]\nfn crate_authors_env_vars() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.1-alpha.1\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\", \"neikos@example.com\"]\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                extern crate foo;\n\n                static AUTHORS: &'static str = env!(\"CARGO_PKG_AUTHORS\");\n\n                fn main() {\n                    let s = \"wycats@example.com:neikos@example.com\";\n                    assert_eq!(AUTHORS, foo::authors());\n                    println!(\"{}\", AUTHORS);\n                    assert_eq!(s, AUTHORS);\n                }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn authors() -> String {\n                    format!(\"{}\", env!(\"CARGO_PKG_AUTHORS\"))\n                }\n            \"#,\n        )\n        .build();\n\n    println!(\"build\");\n    p.cargo(\"build -v\").run();\n\n    println!(\"bin\");\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nwycats@example.com:neikos@example.com\n\n\"#]])\n        .run();\n\n    println!(\"test\");\n    p.cargo(\"test -v\").run();\n}\n\n#[cargo_test]\nfn vv_prints_rustc_env_vars() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = [\"escape='\\\"@example.com\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    let mut b = p.cargo(\"build -vv\");\n\n    #[cfg(windows)]\n    {\n        b.with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] CARGO_PKG_AUTHORS=\"escape='/\"@example.com\"&& [..] set CARGO_PKG_NAME=foo&& [..] rustc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    }\n\n    #[cfg(not(windows))]\n    {\n        b.with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] CARGO_PKG_AUTHORS='escape='/''\"@example.com' [..] CARGO_PKG_NAME=foo [..] rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    }\n\n    b.run();\n}\n\n// The tester may already have LD_LIBRARY_PATH=::/foo/bar which leads to a false positive error\nfn setenv_for_removing_empty_component(mut execs: Execs) -> Execs {\n    let v = dylib_path_envvar();\n    if let Ok(search_path) = env::var(v) {\n        let new_search_path =\n            env::join_paths(env::split_paths(&search_path).filter(|e| !e.as_os_str().is_empty()))\n                .expect(\"join_paths\");\n        execs.env(v, new_search_path); // build_command() will override LD_LIBRARY_PATH accordingly\n    }\n    execs\n}\n\n// Regression test for #4277\n#[cargo_test]\nfn crate_library_path_env_var() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            &format!(\n                r#\"\n                    fn main() {{\n                        let search_path = env!(\"{}\");\n                        let paths = std::env::split_paths(&search_path).collect::<Vec<_>>();\n                        assert!(!paths.contains(&\"\".into()));\n                    }}\n                \"#,\n                dylib_path_envvar()\n            ),\n        )\n        .build();\n\n    setenv_for_removing_empty_component(p.cargo(\"run\")).run();\n}\n\n// See https://github.com/rust-lang/cargo/issues/14194\n#[cargo_test]\nfn issue_14194_deduplicate_library_path_env_var() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            &format!(\n                r#\"\n                    use std::process::Command;\n                    fn main() {{\n                        let level: i32 = std::env::args().nth(1).unwrap().parse().unwrap();\n                        let txt = \"var.txt\";\n                        let lib_path = std::env::var(\"{}\").unwrap();\n\n                        // Make sure we really have something in dylib search path.\n                        let count = std::env::split_paths(&lib_path).count();\n                        assert!(count > 0);\n\n                        if level >= 3 {{\n                            std::fs::write(txt, &lib_path).unwrap();\n                        }} else {{\n                            let prev_lib_path = std::fs::read_to_string(txt).unwrap();\n                            // Ensure no duplicate insertion to dylib search paths\n                            // when calling `cargo run` recursively.\n                            assert_eq!(lib_path, prev_lib_path);\n                        }}\n\n                        if level == 0 {{\n                            return;\n                        }}\n                        \n                        let _  = Command::new(std::env!(\"CARGO\"))\n                        .arg(\"run\")\n                        .arg(\"--\")\n                        .arg((level - 1).to_string())\n                        .status()\n                        .unwrap();\n                    }}\n                \"#,\n                dylib_path_envvar(),\n            ),\n        )\n        .build();\n\n    setenv_for_removing_empty_component(p.cargo(\"run -- 3\"))\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE] 3`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE] 2`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE] 1`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE] 0`\n\n\"#]])\n        .run();\n}\n\n// Regression test for #4277\n#[cargo_test]\nfn build_with_fake_libc_not_loading() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", r#\" \"#)\n        .file(\"libc.so.6\", r#\"\"#)\n        .build();\n\n    setenv_for_removing_empty_component(p.cargo(\"build\")).run();\n}\n\n// this is testing that src/<pkg-name>.rs still works (for now)\n#[cargo_test]\nfn many_crate_types_old_style_lib_location() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [lib]\n\n                name = \"foo\"\n                crate-type = [\"rlib\", \"dylib\"]\n            \"#,\n        )\n        .file(\"src/foo.rs\", \"pub fn foo() {}\")\n        .build();\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[WARNING] path `src/foo.rs` was erroneously implicitly accepted for library `foo`,\nplease rename the file to `src/lib.rs` or set lib.path in Cargo.toml\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(p.root().join(\"target/debug/libfoo.rlib\").is_file());\n    let fname = format!(\"{}foo{}\", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX);\n    assert!(p.root().join(\"target/debug\").join(&fname).is_file());\n}\n\n#[cargo_test]\nfn many_crate_types_correct() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [lib]\n\n                name = \"foo\"\n                crate-type = [\"rlib\", \"dylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n    p.cargo(\"build\").run();\n\n    assert!(p.root().join(\"target/debug/libfoo.rlib\").is_file());\n    let fname = format!(\"{}foo{}\", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX);\n    assert!(p.root().join(\"target/debug\").join(&fname).is_file());\n}\n\n#[cargo_test]\nfn set_both_dylib_and_cdylib_crate_types() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [lib]\n\n                name = \"foo\"\n                crate-type = [\"cdylib\", \"dylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  library `foo` cannot set the crate type of both `dylib` and `cdylib`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn self_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.test]\n\n                path = \".\"\n\n                [lib]\n                name = \"test\"\n                path = \"src/test.rs\"\n            \"#,\n        )\n        .file(\"src/test.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cyclic package dependency: package `test v0.0.0 ([ROOT]/foo)` depends on itself. Cycle:\npackage `test v0.0.0 ([ROOT]/foo)`\n    ... which satisfies path dependency `test` of package `test v0.0.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n/// Make sure broken and loop symlinks don't break the build\n///\n/// This test requires you to be able to make symlinks.\n/// For windows, this may require you to enable developer mode.\nfn ignore_broken_symlinks() {\n    if !symlink_supported() {\n        return;\n    }\n\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .symlink(\"Notafile\", \"bar\")\n        // To hit the symlink directory, we need a build script\n        // to trigger a full scan of package files.\n        .file(\"build.rs\", &main_file(r#\"\"build script\"\"#, &[]))\n        .symlink_dir(\"a/b\", \"a/b/c/d/foo\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[WARNING] File system loop found: [ROOT]/foo/a/b/c/d/foo points to an ancestor [ROOT]/foo/a/b\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\ni am foo\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn missing_lib_and_bin() {\n    let p = project().build();\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  no targets specified in the manifest\n  either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn lto_build() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.release]\n                lto = true\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"build -v --release\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] test v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name test --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C lto [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn explicit_examples() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo\"\n                path = \"src/lib.rs\"\n\n                [[example]]\n                name = \"hello\"\n                path = \"examples/ex-hello.rs\"\n\n                [[example]]\n                name = \"goodbye\"\n                path = \"examples/ex-goodbye.rs\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn get_hello() -> &'static str { \"Hello\" }\n                pub fn get_goodbye() -> &'static str { \"Goodbye\" }\n                pub fn get_world() -> &'static str { \"World\" }\n            \"#,\n        )\n        .file(\n            \"examples/ex-hello.rs\",\n            r#\"\n                extern crate foo;\n                fn main() { println!(\"{}, {}!\", foo::get_hello(), foo::get_world()); }\n            \"#,\n        )\n        .file(\n            \"examples/ex-goodbye.rs\",\n            r#\"\n                extern crate foo;\n                fn main() { println!(\"{}, {}!\", foo::get_goodbye(), foo::get_world()); }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --examples\").run();\n    p.process(&p.bin(\"examples/hello\"))\n        .with_stdout_data(str![[r#\"\nHello, World!\n\n\"#]])\n        .run();\n    p.process(&p.bin(\"examples/goodbye\"))\n        .with_stdout_data(str![[r#\"\nGoodbye, World!\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn implicit_examples() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn get_hello() -> &'static str { \"Hello\" }\n                pub fn get_goodbye() -> &'static str { \"Goodbye\" }\n                pub fn get_world() -> &'static str { \"World\" }\n            \"#,\n        )\n        .file(\n            \"examples/hello.rs\",\n            r#\"\n                extern crate foo;\n                fn main() {\n                    println!(\"{}, {}!\", foo::get_hello(), foo::get_world());\n                }\n            \"#,\n        )\n        .file(\n            \"examples/goodbye.rs\",\n            r#\"\n                extern crate foo;\n                fn main() {\n                    println!(\"{}, {}!\", foo::get_goodbye(), foo::get_world());\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --examples\").run();\n    p.process(&p.bin(\"examples/hello\"))\n        .with_stdout_data(str![[r#\"\nHello, World!\n\n\"#]])\n        .run();\n    p.process(&p.bin(\"examples/goodbye\"))\n        .with_stdout_data(str![[r#\"\nGoodbye, World!\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn standard_build_no_ndebug() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/foo.rs\",\n            r#\"\n                fn main() {\n                    if cfg!(debug_assertions) {\n                        println!(\"slow\")\n                    } else {\n                        println!(\"fast\")\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nslow\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn release_build_ndebug() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/foo.rs\",\n            r#\"\n                fn main() {\n                    if cfg!(debug_assertions) {\n                        println!(\"slow\")\n                    } else {\n                        println!(\"fast\")\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --release\").run();\n    p.process(&p.release_bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nfast\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inferred_main_bin() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"build\").run();\n    p.process(&p.bin(\"foo\")).run();\n}\n\n#[cargo_test]\nfn deletion_causes_failure() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.change_file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.1\"));\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\nerror[E0463]: can't find crate for `bar`\n...\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_cargo_toml_in_target_dir() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"target/Cargo.toml\", \"bad-toml\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.process(&p.bin(\"foo\")).run();\n}\n\n#[cargo_test]\nfn lib_with_standard_name() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"syntax\", \"0.0.1\"))\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"src/main.rs\",\n            \"extern crate syntax; fn main() { syntax::foo() }\",\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] syntax v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_staticlib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                  [package]\n                  name = \"foo\"\n                  authors = []\n                  version = \"0.0.1\"\n                  edition = \"2015\"\n\n                  [lib]\n                  name = \"foo\"\n                  crate-type = [\"staticlib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    // env var is a test for #1381\n    p.cargo(\"build\").env(\"CARGO_LOG\", \"nekoneko=trace\").run();\n}\n\n#[cargo_test]\nfn staticlib_rlib_and_bin() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                  [package]\n                  name = \"foo\"\n                  authors = []\n                  version = \"0.0.1\"\n                  edition = \"2015\"\n\n                  [lib]\n                  name = \"foo\"\n                  crate-type = [\"staticlib\", \"rlib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\"src/main.rs\", \"extern crate foo; fn main() { foo::foo(); }\")\n        .build();\n\n    p.cargo(\"build -v\").run();\n}\n\n#[cargo_test]\nfn opt_out_of_bin() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                  bin = []\n\n                  [package]\n                  name = \"foo\"\n                  authors = []\n                  version = \"0.0.1\"\n                  edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"bad syntax\")\n        .build();\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn single_lib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                  [package]\n                  name = \"foo\"\n                  authors = []\n                  version = \"0.0.1\"\n                  edition = \"2015\"\n\n                  [lib]\n                  name = \"foo\"\n                  path = \"src/bar.rs\"\n            \"#,\n        )\n        .file(\"src/bar.rs\", \"\")\n        .build();\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn freshness_ignores_excluded() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n                exclude = [\"src/b*.rs\"]\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"pub fn bar() -> i32 { 1 }\")\n        .build();\n    foo.root().move_into_the_past();\n\n    foo.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Smoke test to make sure it doesn't compile again\n    println!(\"first pass\");\n    foo.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Modify an ignored file and make sure we don't rebuild\n    println!(\"second pass\");\n    foo.change_file(\"src/bar.rs\", \"\");\n    foo.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rebuild_preserves_out_dir() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = 'build.rs'\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                use std::fs::File;\n                use std::path::Path;\n\n                fn main() {\n                    let path = Path::new(&env::var(\"OUT_DIR\").unwrap()).join(\"foo\");\n                    if env::var_os(\"FIRST\").is_some() {\n                        File::create(&path).unwrap();\n                    } else {\n                        File::create(&path).unwrap();\n                    }\n                }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn bar() -> i32 { 1 }\")\n        .build();\n    foo.root().move_into_the_past();\n\n    foo.cargo(\"build\")\n        .env(\"FIRST\", \"1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    foo.change_file(\"src/bar.rs\", \"\");\n    foo.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dep_no_libs() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn bar() -> i32 { 1 }\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"bar/src/main.rs\", \"\")\n        .build();\n    foo.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn recompile_space_in_name() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo\"\n                path = \"src/my lib.rs\"\n            \"#,\n        )\n        .file(\"src/my lib.rs\", \"\")\n        .build();\n    foo.cargo(\"build\").run();\n    foo.root().move_into_the_past();\n    foo.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cfg(unix)]\n#[cargo_test]\nfn credentials_is_unreadable() {\n    use cargo_test_support::paths::home;\n    use std::os::unix::prelude::*;\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let credentials = home().join(\".cargo/credentials.toml\");\n    t!(fs::create_dir_all(credentials.parent().unwrap()));\n    t!(fs::write(\n        &credentials,\n        r#\"\n            [registry]\n            token = \"api-token\"\n        \"#\n    ));\n    let stat = fs::metadata(credentials.as_path()).unwrap();\n    let mut perms = stat.permissions();\n    perms.set_mode(0o000);\n    fs::set_permissions(credentials, perms).unwrap();\n\n    p.cargo(\"build\").run();\n}\n\n#[cfg(unix)]\n#[cargo_test]\nfn ignore_bad_directories() {\n    use std::os::unix::prelude::*;\n    let foo = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    let dir = foo.root().join(\"tmp\");\n    fs::create_dir(&dir).unwrap();\n    let stat = fs::metadata(&dir).unwrap();\n    let mut perms = stat.permissions();\n    perms.set_mode(0o644);\n    fs::set_permissions(&dir, perms.clone()).unwrap();\n    foo.cargo(\"build\").run();\n    perms.set_mode(0o755);\n    fs::set_permissions(&dir, perms).unwrap();\n}\n\n#[cargo_test]\nfn bad_cargo_config() {\n    let foo = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\".cargo/config.toml\", \"this is not valid toml\")\n        .build();\n    foo.cargo(\"build -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not load Cargo configuration\n\nCaused by:\n  could not parse TOML configuration in `[ROOT]/foo/.cargo/config.toml`\n\nCaused by:\n  TOML parse error at line 1, column 6\n    |\n  1 | this is not valid toml\n    |      ^\n  key with no value, expected `=`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_platform_specific_dependency() {\n    let host = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n                    build = \"build.rs\"\n\n                    [target.{host}.dependencies]\n                    dep = {{ path = \"dep\" }}\n                    [target.{host}.build-dependencies]\n                    build = {{ path = \"build\" }}\n                    [target.{host}.dev-dependencies]\n                    dev = {{ path = \"dev\" }}\n                \"#,\n                host = host\n            ),\n        )\n        .file(\"src/main.rs\", \"extern crate dep; fn main() { dep::dep() }\")\n        .file(\n            \"tests/foo.rs\",\n            \"extern crate dev; #[test] fn foo() { dev::dev() }\",\n        )\n        .file(\n            \"build.rs\",\n            \"extern crate build; fn main() { build::build(); }\",\n        )\n        .file(\"dep/Cargo.toml\", &basic_manifest(\"dep\", \"0.5.0\"))\n        .file(\"dep/src/lib.rs\", \"pub fn dep() {}\")\n        .file(\"build/Cargo.toml\", &basic_manifest(\"build\", \"0.5.0\"))\n        .file(\"build/src/lib.rs\", \"pub fn build() {}\")\n        .file(\"dev/Cargo.toml\", &basic_manifest(\"dev\", \"0.5.0\"))\n        .file(\"dev/src/lib.rs\", \"pub fn dev() {}\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.bin(\"foo\").is_file());\n    p.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn bad_platform_specific_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [target.wrong-target.dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"pub fn gimme() -> String { format!(\"\") }\"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\nerror[E0463]: can't find crate for `bar`\n...\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_platform_specific_dependency_wrong_platform() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [target.non-existing-triplet.dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\n            \"bar/src/lib.rs\",\n            \"invalid rust file, should not be compiled\",\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.bin(\"foo\").is_file());\n    p.process(&p.bin(\"foo\")).run();\n\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"bar\"));\n}\n\n#[cargo_test]\nfn example_as_lib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[example]]\n                name = \"ex\"\n                crate-type = [\"lib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --example=ex\").run();\n    assert!(p.example_lib(\"ex\", \"lib\").is_file());\n}\n\n#[cargo_test]\nfn example_as_rlib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[example]]\n                name = \"ex\"\n                crate-type = [\"rlib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --example=ex\").run();\n    assert!(p.example_lib(\"ex\", \"rlib\").is_file());\n}\n\n#[cargo_test]\nfn example_as_dylib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[example]]\n                name = \"ex\"\n                crate-type = [\"dylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --example=ex\").run();\n    assert!(p.example_lib(\"ex\", \"dylib\").is_file());\n}\n\n#[cargo_test]\nfn example_as_proc_macro() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[example]]\n                name = \"ex\"\n                crate-type = [\"proc-macro\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"examples/ex.rs\",\n            r#\"\n            extern crate proc_macro;\n            use proc_macro::TokenStream;\n\n            #[proc_macro]\n            pub fn eat(_item: TokenStream) -> TokenStream {\n                \"\".parse().unwrap()\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --example=ex\").run();\n    assert!(p.example_lib(\"ex\", \"proc-macro\").is_file());\n}\n\n#[cargo_test]\nfn example_bin_same_name() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"examples/foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --examples\").run();\n\n    assert!(!p.bin(\"foo\").is_file());\n    // We expect a file of the form bin/foo-{metadata_hash}\n    assert!(p.bin(\"examples/foo\").is_file());\n\n    p.cargo(\"build --examples\").run();\n\n    assert!(!p.bin(\"foo\").is_file());\n    // We expect a file of the form bin/foo-{metadata_hash}\n    assert!(p.bin(\"examples/foo\").is_file());\n}\n\n#[cargo_test]\nfn compile_then_delete() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"run -v\").run();\n    assert!(p.bin(\"foo\").is_file());\n    if cfg!(windows) {\n        // On windows unlinking immediately after running often fails, so sleep\n        sleep_ms(100);\n    }\n    fs::remove_file(&p.bin(\"foo\")).unwrap();\n    p.cargo(\"run -v\").run();\n}\n\n#[cargo_test]\nfn transitive_dependencies_not_available() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.aaaaa]\n                path = \"a\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"extern crate bbbbb; extern crate aaaaa; fn main() {}\",\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"aaaaa\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bbbbb]\n                path = \"../b\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"extern crate bbbbb;\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"bbbbb\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bbbbb v0.0.1 ([ROOT]/foo/b)\n[RUNNING] `rustc [..]\n[COMPILING] aaaaa v0.0.1 ([ROOT]/foo/a)\n[RUNNING] `rustc [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\nerror[E0463]: can't find crate for `bbbbb`\n...\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n\nCaused by:\n  process didn't exit successfully: `rustc [..]` ([EXIT_STATUS]: 1)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cyclic_deps_rejected() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.foo]\n                path = \"..\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cyclic package dependency: package `a v0.0.1 ([ROOT]/foo/a)` depends on itself. Cycle:\npackage `a v0.0.1 ([ROOT]/foo/a)`\n    ... which satisfies path dependency `a` of package `foo v0.0.1 ([ROOT]/foo)`\n    ... which satisfies path dependency `foo` of package `a v0.0.1 ([ROOT]/foo/a)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn predictable_filenames() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo\"\n                crate-type = [\"dylib\", \"rlib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\").run();\n    assert!(p.root().join(\"target/debug/libfoo.rlib\").is_file());\n    let dylib_name = format!(\"{}foo{}\", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX);\n    assert!(p.root().join(\"target/debug\").join(dylib_name).is_file());\n}\n\n#[cargo_test]\nfn dashes_to_underscores() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo-bar\", \"0.0.1\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"extern crate foo_bar; fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\").run();\n    assert!(p.bin(\"foo-bar\").is_file());\n}\n\n#[cargo_test]\nfn dashes_in_crate_name_bad() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo-bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"extern crate foo_bar; fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  library target names cannot contain hyphens: foo-bar\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustc_env_var() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"build -v\")\n        .env(\"RUSTC\", \"rustc-that-does-not-exist\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not execute process `rustc-that-does-not-exist -vV` (never executed)\n\nCaused by:\n  [..]\n\n\"#]])\n        .run();\n    assert!(!p.bin(\"a\").is_file());\n}\n\n#[cargo_test]\nfn filtering() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\"src/bin/b.rs\", \"fn main() {}\")\n        .file(\"examples/a.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --lib\").run();\n    assert!(!p.bin(\"a\").is_file());\n\n    p.cargo(\"build --bin=a --example=a\").run();\n    assert!(p.bin(\"a\").is_file());\n    assert!(!p.bin(\"b\").is_file());\n    assert!(p.bin(\"examples/a\").is_file());\n    assert!(!p.bin(\"examples/b\").is_file());\n}\n\n#[cargo_test]\nfn filtering_implicit_bins() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\"src/bin/b.rs\", \"fn main() {}\")\n        .file(\"examples/a.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --bins\").run();\n    assert!(p.bin(\"a\").is_file());\n    assert!(p.bin(\"b\").is_file());\n    assert!(!p.bin(\"examples/a\").is_file());\n    assert!(!p.bin(\"examples/b\").is_file());\n}\n\n#[cargo_test]\nfn filtering_implicit_examples() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\"src/bin/b.rs\", \"fn main() {}\")\n        .file(\"examples/a.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --examples\").run();\n    assert!(!p.bin(\"a\").is_file());\n    assert!(!p.bin(\"b\").is_file());\n    assert!(p.bin(\"examples/a\").is_file());\n    assert!(p.bin(\"examples/b\").is_file());\n}\n\n#[cargo_test]\nfn ignore_dotfile() {\n    let p = project()\n        .file(\"src/bin/.a.rs\", \"\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn ignore_dotdirs() {\n    let p = project()\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\".git/Cargo.toml\", \"\")\n        .file(\".pc/dummy-fix.patch/Cargo.toml\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn dotdir_root() {\n    let p = ProjectBuilder::new(root().join(\".foo\"))\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn custom_target_dir_env() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    let exe_name = format!(\"foo{}\", env::consts::EXE_SUFFIX);\n\n    p.cargo(\"build\").env(\"CARGO_TARGET_DIR\", \"foo/target\").run();\n    assert!(p.root().join(\"foo/target/debug\").join(&exe_name).is_file());\n    assert!(!p.root().join(\"target/debug\").join(&exe_name).is_file());\n\n    p.cargo(\"build\").run();\n    assert!(p.root().join(\"foo/target/debug\").join(&exe_name).is_file());\n    assert!(p.root().join(\"target/debug\").join(&exe_name).is_file());\n\n    p.cargo(\"build\")\n        .env(\"CARGO_BUILD_TARGET_DIR\", \"foo2/target\")\n        .run();\n    assert!(p.root().join(\"foo2/target/debug\").join(&exe_name).is_file());\n\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n            [build]\n            target-dir = \"foo/target\"\n        \"#,\n    );\n    p.cargo(\"build\").env(\"CARGO_TARGET_DIR\", \"bar/target\").run();\n    assert!(p.root().join(\"bar/target/debug\").join(&exe_name).is_file());\n    assert!(p.root().join(\"foo/target/debug\").join(&exe_name).is_file());\n    assert!(p.root().join(\"target/debug\").join(&exe_name).is_file());\n}\n\n#[cargo_test]\nfn custom_target_dir_line_parameter() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    let exe_name = format!(\"foo{}\", env::consts::EXE_SUFFIX);\n\n    p.cargo(\"build --target-dir foo/target\").run();\n    assert!(p.root().join(\"foo/target/debug\").join(&exe_name).is_file());\n    assert!(!p.root().join(\"target/debug\").join(&exe_name).is_file());\n\n    p.cargo(\"build\").run();\n    assert!(p.root().join(\"foo/target/debug\").join(&exe_name).is_file());\n    assert!(p.root().join(\"target/debug\").join(&exe_name).is_file());\n\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n            [build]\n            target-dir = \"foo/target\"\n        \"#,\n    );\n    p.cargo(\"build --target-dir bar/target\").run();\n    assert!(p.root().join(\"bar/target/debug\").join(&exe_name).is_file());\n    assert!(p.root().join(\"foo/target/debug\").join(&exe_name).is_file());\n    assert!(p.root().join(\"target/debug\").join(&exe_name).is_file());\n\n    p.cargo(\"build --target-dir foobar/target\")\n        .env(\"CARGO_TARGET_DIR\", \"bar/target\")\n        .run();\n    assert!(\n        p.root()\n            .join(\"foobar/target/debug\")\n            .join(&exe_name)\n            .is_file()\n    );\n    assert!(p.root().join(\"bar/target/debug\").join(&exe_name).is_file());\n    assert!(p.root().join(\"foo/target/debug\").join(&exe_name).is_file());\n    assert!(p.root().join(\"target/debug\").join(&exe_name).is_file());\n}\n\n#[cargo_test]\nfn build_multiple_packages() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.d1]\n                    path = \"d1\"\n                [dependencies.d2]\n                    path = \"d2\"\n\n                [[bin]]\n                    name = \"foo\"\n            \"#,\n        )\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .file(\"d1/Cargo.toml\", &basic_bin_manifest(\"d1\"))\n        .file(\"d1/src/lib.rs\", \"\")\n        .file(\"d1/src/main.rs\", \"fn main() { println!(\\\"d1\\\"); }\")\n        .file(\n            \"d2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                    name = \"d2\"\n                    doctest = false\n            \"#,\n        )\n        .file(\"d2/src/main.rs\", \"fn main() { println!(\\\"d2\\\"); }\")\n        .build();\n\n    p.cargo(\"build -p d1 -p d2 -p foo\").run();\n\n    assert!(p.bin(\"foo\").is_file());\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\ni am foo\n\n\"#]])\n        .run();\n\n    let d1_path = &p\n        .build_dir()\n        .join(\"debug\")\n        .join(format!(\"d1{}\", env::consts::EXE_SUFFIX));\n    let d2_path = &p\n        .build_dir()\n        .join(\"debug\")\n        .join(format!(\"d2{}\", env::consts::EXE_SUFFIX));\n\n    assert!(d1_path.is_file());\n    p.process(d1_path)\n        .with_stdout_data(str![[r#\"\nd1\n\n\"#]])\n        .run();\n\n    assert!(d2_path.is_file());\n    p.process(d2_path)\n        .with_stdout_data(str![[r#\"\nd2\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_spec() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.d1]\n                    path = \"d1\"\n\n                [[bin]]\n                    name = \"foo\"\n            \"#,\n        )\n        .file(\"src/bin/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .file(\"d1/Cargo.toml\", &basic_bin_manifest(\"d1\"))\n        .file(\"d1/src/lib.rs\", \"\")\n        .file(\"d1/src/main.rs\", \"fn main() { println!(\\\"d1\\\"); }\")\n        .build();\n\n    p.cargo(\"build -p notAValidDep\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ERROR] package ID specification `notAValidDep` did not match any packages\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -p d1 -p notAValidDep\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `notAValidDep` did not match any packages\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn manifest_with_bom_is_ok() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            \"\\u{FEFF}\n            [package]\n            name = \\\"foo\\\"\n            version = \\\"0.0.1\\\"\n            edition = \\\"2015\\\"\n            authors = []\n        \",\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build -v\").run();\n}\n\n#[cargo_test]\nfn panic_abort_compiles_with_panic_abort() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.dev]\n                panic = 'abort'\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] -C panic=abort [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn compiler_json_error_format() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            \"fn main() { println!(\\\"cargo::rustc-cfg=xyz\\\") }\",\n        )\n        .file(\"src/main.rs\", \"fn main() { let unused = 92; }\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"bar/src/lib.rs\", r#\"fn dead() {}\"#)\n        .build();\n\n    let output = |fresh| {\n        r#\"\n[\n  {\n    \"executable\": null,\n    \"features\": [],\n    \"fresh\": $FRESH,\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.5.0\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"kind\": [\"custom-build\"],\n      \"...\": \"{...}\"\n    },\n    \"...\": \"{...}\"\n  },\n  {\n    \"manifest_path\": \"[ROOT]/foo/bar/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo/bar#0.5.0\",\n    \"reason\": \"compiler-message\",\n    \"target\": {\n      \"kind\": [\"lib\"],\n      \"...\": \"{...}\"\n    },\n    \"...\": \"{...}\"\n  },\n  {\n    \"executable\": null,\n    \"features\": [],\n    \"fresh\": $FRESH,\n    \"manifest_path\": \"[ROOT]/foo/bar/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo/bar#0.5.0\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"kind\": [\"lib\"],\n      \"...\": \"{...}\"\n    },\n    \"...\": \"{...}\"\n  },\n  {\n    \"cfgs\": [\n      \"xyz\"\n    ],\n    \"env\": [],\n    \"linked_libs\": [],\n    \"linked_paths\": [],\n    \"out_dir\": \"[ROOT]/foo/target/debug/build/foo-[HASH]/out\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.5.0\",\n    \"reason\": \"build-script-executed\"\n  },\n  {\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.5.0\",\n    \"reason\": \"compiler-message\",\n    \"target\": {\n      \"kind\": [\"bin\"],\n      \"...\": \"{...}\"\n    },\n    \"...\": \"{...}\"\n  },\n  {\n    \"features\": [],\n    \"fresh\": $FRESH,\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.5.0\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"kind\": [\"bin\"],\n      \"...\": \"{...}\"\n    },\n    \"...\": \"{...}\"\n  },\n  {\n    \"reason\": \"build-finished\",\n    \"success\": true\n  },\n  \"{...}\"\n]\n\"#\n        .replace(\"$FRESH\", fresh)\n        .is_json()\n        .against_jsonlines()\n        .unordered()\n    };\n\n    // Use `jobs=1` to ensure that the order of messages is consistent.\n    p.cargo(\"build -v --message-format=json --jobs=1\")\n        .with_stdout_data(output(\"false\"))\n        .run();\n\n    // With fresh build, we should repeat the artifacts,\n    // and replay the cached compiler warnings.\n    p.cargo(\"build -v --message-format=json --jobs=1\")\n        .with_stdout_data(output(\"true\"))\n        .run();\n}\n\n#[cargo_test]\nfn wrong_message_format_option() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --message-format XML\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid value 'XML' for '--message-format <FMT>'\n  [possible values: human, short, json, json-diagnostic-short, json-diagnostic-rendered-ansi, json-render-diagnostics]\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn message_format_json_forward_stderr() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() { let unused = 0; }\")\n        .build();\n\n    p.cargo(\"rustc --release --bin foo --message-format JSON\")\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"message\": \"{...}\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.5.0\",\n    \"reason\": \"compiler-message\",\n    \"target\": {\n      \"kind\": [\"bin\"],\n      \"...\": \"{...}\"\n    },\n    \"...\": \"{...}\"\n  },\n  {\n    \"features\": [],\n    \"fresh\": false,\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.5.0\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"kind\": [\"bin\"],\n      \"...\": \"{...}\"\n    },\n    \"...\": \"{...}\"\n  },\n  {\n    \"reason\": \"build-finished\",\n    \"success\": true\n  },\n  \"{...}\"\n]\n\"#]]\n            .is_json()\n            .against_jsonlines()\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn no_warn_about_package_metadata() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [package.metadata]\n                foo = \"bar\"\n                a = true\n                b = 3\n\n                [package.metadata.another]\n                bar = 3\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_warn_about_workspace_metadata() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"foo\"]\n\n            [workspace.metadata]\n            something = \"something_else\"\n            x = 1\n            y = 2\n\n            [workspace.metadata.another]\n            bar = 12\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_build_empty_target() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --target\")\n        .arg(\"\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] target was empty\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_build_with_unsupported_short_target_flag() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -t\")\n        .arg(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '-t' found\n\n  tip: a similar argument exists: '--target'\n\nUsage: cargo[EXE] build [OPTIONS]\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn build_all_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"build --workspace\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_all_exclude() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() { break_the_build(); }\")\n        .build();\n\n    p.cargo(\"build --workspace --exclude baz\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_build_with_unsupported_short_exclude_flag() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() { break_the_build(); }\")\n        .build();\n\n    p.cargo(\"build --workspace -x baz\")\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '-x' found\n\n  tip: a similar argument exists: '--exclude'\n\nUsage: cargo[EXE] build [OPTIONS]\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn build_all_exclude_not_found() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"build --workspace --exclude baz\")\n        .with_stderr_data(\n            str![[r#\"\n[WARNING] excluded package(s) `baz` not found in workspace `[ROOT]/foo`\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_all_exclude_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() { break_the_build(); }\")\n        .build();\n\n    p.cargo(\"build --workspace --exclude '*z'\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_all_exclude_glob_not_found() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"build --workspace --exclude '*z'\")\n        .with_stderr_data(\n            str![[r#\"\n[WARNING] excluded package pattern(s) `*z` not found in workspace `[ROOT]/foo`\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_all_exclude_broken_glob() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"build --workspace --exclude '[*z'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot build glob pattern from `[*z`\n\nCaused by:\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_all_workspace_implicit_examples() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\"src/bin/b.rs\", \"fn main() {}\")\n        .file(\"examples/c.rs\", \"fn main() {}\")\n        .file(\"examples/d.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"bar/src/bin/e.rs\", \"fn main() {}\")\n        .file(\"bar/src/bin/f.rs\", \"fn main() {}\")\n        .file(\"bar/examples/g.rs\", \"fn main() {}\")\n        .file(\"bar/examples/h.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --workspace --examples\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(!p.bin(\"a\").is_file());\n    assert!(!p.bin(\"b\").is_file());\n    assert!(p.bin(\"examples/c\").is_file());\n    assert!(p.bin(\"examples/d\").is_file());\n    assert!(!p.bin(\"e\").is_file());\n    assert!(!p.bin(\"f\").is_file());\n    assert!(p.bin(\"examples/g\").is_file());\n    assert!(p.bin(\"examples/h\").is_file());\n}\n\n#[cargo_test]\nfn build_all_virtual_manifest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    // The order in which bar and baz are built is not guaranteed\n    p.cargo(\"build --workspace\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] baz v0.1.0 ([ROOT]/foo/baz)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_virtual_manifest_all_implied() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    // The order in which `bar` and `baz` are built is not guaranteed.\n    p.cargo(\"build\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] baz v0.1.0 ([ROOT]/foo/baz)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_virtual_manifest_one_project() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() { break_the_build(); }\")\n        .build();\n\n    p.cargo(\"build -p bar\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_virtual_manifest_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() { break_the_build(); }\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"build -p '*z'\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] baz v0.1.0 ([ROOT]/foo/baz)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_virtual_manifest_glob_not_found() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"build -p bar -p '*z'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package pattern(s) `*z` not found in workspace `[ROOT]/foo`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_virtual_manifest_broken_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"build -p '[*z'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot build glob pattern from `[*z`\n\nCaused by:\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_all_virtual_manifest_implicit_examples() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"bar/src/bin/a.rs\", \"fn main() {}\")\n        .file(\"bar/src/bin/b.rs\", \"fn main() {}\")\n        .file(\"bar/examples/c.rs\", \"fn main() {}\")\n        .file(\"bar/examples/d.rs\", \"fn main() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"\")\n        .file(\"baz/src/bin/e.rs\", \"fn main() {}\")\n        .file(\"baz/src/bin/f.rs\", \"fn main() {}\")\n        .file(\"baz/examples/g.rs\", \"fn main() {}\")\n        .file(\"baz/examples/h.rs\", \"fn main() {}\")\n        .build();\n\n    // The order in which bar and baz are built is not guaranteed\n    p.cargo(\"build --workspace --examples\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] baz v0.1.0 ([ROOT]/foo/baz)\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    assert!(!p.bin(\"a\").is_file());\n    assert!(!p.bin(\"b\").is_file());\n    assert!(p.bin(\"examples/c\").is_file());\n    assert!(p.bin(\"examples/d\").is_file());\n    assert!(!p.bin(\"e\").is_file());\n    assert!(!p.bin(\"f\").is_file());\n    assert!(p.bin(\"examples/g\").is_file());\n    assert!(p.bin(\"examples/h\").is_file());\n}\n\n#[cargo_test]\nfn build_all_member_dependency_same_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                a = \"0.1.0\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"pub fn a() {}\")\n        .build();\n\n    Package::new(\"a\", \"0.1.0\").publish();\n\n    p.cargo(\"build --workspace\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] a v0.1.0 (registry `dummy-registry`)\n[COMPILING] a v0.1.0\n[COMPILING] a v0.1.0 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_proper_binary() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                edition = \"2015\"\n                [[bin]]\n                name = \"main\"\n                [[bin]]\n                name = \"other\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"src/bin/main.rs\",\n            r#\"fn main() { panic!(\"This should never be run.\"); }\"#,\n        )\n        .file(\"src/bin/other.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"run --bin other\").run();\n}\n\n#[cargo_test]\nfn run_proper_binary_main_rs() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"run --bin foo\").run();\n}\n\n#[cargo_test]\nfn run_proper_alias_binary_from_src() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                edition = \"2015\"\n                [[bin]]\n                name = \"foo\"\n                [[bin]]\n                name = \"bar\"\n            \"#,\n        )\n        .file(\"src/foo.rs\", r#\"fn main() { println!(\"foo\"); }\"#)\n        .file(\"src/bar.rs\", r#\"fn main() { println!(\"bar\"); }\"#)\n        .build();\n\n    p.cargo(\"build --workspace\").run();\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nfoo\n\n\"#]])\n        .run();\n    p.process(&p.bin(\"bar\"))\n        .with_stdout_data(str![[r#\"\nbar\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_proper_alias_binary_main_rs() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                edition = \"2015\"\n                [[bin]]\n                name = \"foo\"\n                [[bin]]\n                name = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"main\"); }\"#)\n        .build();\n\n    p.cargo(\"build --workspace\").run();\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nmain\n\n\"#]])\n        .run();\n    p.process(&p.bin(\"bar\"))\n        .with_stdout_data(str![[r#\"\nmain\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_proper_binary_main_rs_as_foo() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/foo.rs\",\n            r#\" fn main() { panic!(\"This should never be run.\"); }\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"run --bin foo\").run();\n}\n\n#[cargo_test]\nfn rustc_wrapper() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    let wrapper = tools::echo_wrapper();\n    p.cargo(\"build -v\")\n        .env(\"RUSTC_WRAPPER\", &wrapper)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..]/rustc-echo-wrapper[EXE] rustc --crate-name foo [..]`\nWRAPPER CALLED: rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.build_dir().rm_rf();\n    p.cargo(\"build -v\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", &wrapper)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..]/rustc-echo-wrapper[EXE] rustc --crate-name foo [..]`\nWRAPPER CALLED: rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n/// Checks what happens when both rust-wrapper and rustc-workspace-wrapper are set.\n#[cargo_test]\nfn rustc_wrapper_precedence() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    let rustc_wrapper = tools::echo_wrapper();\n    let ws_wrapper = rustc_wrapper.with_file_name(\"rustc-ws-wrapper\");\n    assert_ne!(rustc_wrapper, ws_wrapper);\n    std::fs::hard_link(&rustc_wrapper, &ws_wrapper).unwrap();\n\n    p.cargo(\"build -v\")\n        .env(\"RUSTC_WRAPPER\", &rustc_wrapper)\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", &ws_wrapper)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..]/rustc-echo-wrapper[EXE] [..]/rustc-ws-wrapper rustc --crate-name foo [..]`\nWRAPPER CALLED: [..]/rustc-ws-wrapper rustc --crate-name foo [..]\nWRAPPER CALLED: rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustc_wrapper_queries() {\n    // Check that the invocations querying rustc for information are done with the wrapper.\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    let wrapper = tools::echo_wrapper();\n    p.cargo(\"build\")\n        .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n        .env(\"RUSTC_WRAPPER\", &wrapper)\n        .with_stderr_contains(\"[..]running [..]rustc-echo-wrapper[EXE] rustc -vV[..]\")\n        .with_stderr_contains(\n            \"[..]running [..]rustc-echo-wrapper[EXE] rustc - --crate-name ___ --print[..]\",\n        )\n        .run();\n    p.build_dir().rm_rf();\n    p.cargo(\"build\")\n        .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", &wrapper)\n        .with_stderr_contains(\"[..]running [..]rustc-echo-wrapper[EXE] rustc -vV[..]\")\n        .with_stderr_contains(\n            \"[..]running [..]rustc-echo-wrapper[EXE] rustc - --crate-name ___ --print[..]\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn rustc_wrapper_relative() {\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    let wrapper = tools::echo_wrapper();\n    let exe_name = wrapper.file_name().unwrap().to_str().unwrap();\n    let relative_path = format!(\"./{}\", exe_name);\n    fs::hard_link(&wrapper, p.root().join(exe_name)).unwrap();\n    p.cargo(\"build -v\")\n        .env(\"RUSTC_WRAPPER\", &relative_path)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[COMPILING] bar v1.0.0\n[RUNNING] `[ROOT]/foo/./rustc-echo-wrapper[EXE] rustc --crate-name bar [..]`\nWRAPPER CALLED: rustc --crate-name bar [..]\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/./rustc-echo-wrapper[EXE] rustc --crate-name foo [..]`\nWRAPPER CALLED: rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.build_dir().rm_rf();\n    p.cargo(\"build -v\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", &relative_path)\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v1.0.0\n[RUNNING] `rustc --crate-name bar [..]`\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/./rustc-echo-wrapper[EXE] rustc --crate-name foo [..]`\nWRAPPER CALLED: rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.build_dir().rm_rf();\n    p.change_file(\n        \".cargo/config.toml\",\n        &format!(\n            r#\"\n                build.rustc-wrapper = \"./{}\"\n            \"#,\n            exe_name\n        ),\n    );\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v1.0.0\n[RUNNING] `[ROOT]/foo/./rustc-echo-wrapper[EXE] rustc --crate-name bar [..]`\nWRAPPER CALLED: rustc --crate-name bar [..]\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/./rustc-echo-wrapper[EXE] rustc --crate-name foo [..]`\nWRAPPER CALLED: rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustc_wrapper_from_path() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.cargo(\"build -v\")\n        .env(\"RUSTC_WRAPPER\", \"wannabe_sccache\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not execute process `wannabe_sccache rustc -vV` (never executed)\n\nCaused by:\n  [..]\n\n\"#]])\n        .run();\n    p.build_dir().rm_rf();\n    p.cargo(\"build -v\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", \"wannabe_sccache\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not execute process `wannabe_sccache rustc -vV` (never executed)\n\nCaused by:\n  [..]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cdylib_not_lifted() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"cdylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    let files = if cfg!(windows) {\n        if cfg!(target_env = \"msvc\") {\n            vec![\"foo.dll.lib\", \"foo.dll.exp\", \"foo.dll\"]\n        } else {\n            vec![\"libfoo.dll.a\", \"foo.dll\"]\n        }\n    } else if cfg!(target_os = \"macos\") {\n        vec![\"libfoo.dylib\"]\n    } else {\n        vec![\"libfoo.so\"]\n    };\n\n    for file in files {\n        println!(\"checking: {}\", file);\n        assert!(p.root().join(\"target/debug/deps\").join(&file).is_file());\n    }\n}\n\n#[cargo_test]\nfn cdylib_final_outputs() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo-bar\"\n                authors = []\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"cdylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    let files = if cfg!(windows) {\n        if cfg!(target_env = \"msvc\") {\n            vec![\"foo_bar.dll.lib\", \"foo_bar.dll\"]\n        } else {\n            vec![\"foo_bar.dll\", \"libfoo_bar.dll.a\"]\n        }\n    } else if cfg!(target_os = \"macos\") {\n        vec![\"libfoo_bar.dylib\"]\n    } else {\n        vec![\"libfoo_bar.so\"]\n    };\n\n    for file in files {\n        println!(\"checking: {}\", file);\n        assert!(p.root().join(\"target/debug\").join(&file).is_file());\n    }\n}\n\n#[cargo_test]\n// NOTE: Windows MSVC and wasm32-unknown-emscripten do not use metadata. Skip them.\n// See <https://github.com/rust-lang/cargo/issues/9325#issuecomment-1030662699>\n#[cfg(not(all(target_os = \"windows\", target_env = \"msvc\")))]\nfn no_dep_info_collision_when_cdylib_and_bin_coexist() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n\n            [lib]\n            crate-type = [\"cdylib\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v1.0.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] --crate-type bin [..] -C metadata=[..]`\n[RUNNING] `rustc [..] --crate-type cdylib [..] -C metadata=[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    let deps_dir = p.target_debug_dir().join(\"deps\");\n    assert!(deps_dir.join(\"foo.d\").exists());\n    let dep_info_count = deps_dir\n        .read_dir()\n        .unwrap()\n        .filter(|e| {\n            let filename = e.as_ref().unwrap().file_name();\n            let filename = filename.to_str().unwrap();\n            filename.starts_with(\"foo\") && filename.ends_with(\".d\")\n        })\n        .count();\n    // cdylib -> foo.d\n    // bin -> foo-<meta>.d\n    assert_eq!(dep_info_count, 2);\n}\n\n#[cargo_test]\nfn deterministic_cfg_flags() {\n    // This bug is non-deterministic.\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [features]\n                default = [\"f_a\", \"f_b\", \"f_c\", \"f_d\"]\n                f_a = []\n                f_b = []\n                f_c = []\n                f_d = []\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-cfg=cfg_a\");\n                    println!(\"cargo::rustc-cfg=cfg_b\");\n                    println!(\"cargo::rustc-cfg=cfg_c\");\n                    println!(\"cargo::rustc-cfg=cfg_d\");\n                    println!(\"cargo::rustc-cfg=cfg_e\");\n                }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..] --cfg[..]default[..]--cfg[..]f_a[..]--cfg[..]f_b[..] --cfg[..]f_c[..]--cfg[..]f_d[..] --cfg cfg_a --cfg cfg_b --cfg cfg_c --cfg cfg_d --cfg cfg_e`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn explicit_bins_without_paths() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"foo\"\n\n                [[bin]]\n                name = \"bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/bin/bar.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn no_bin_in_src_with_lib() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  can't find `foo` bin at `src/bin/foo.rs` or `src/bin/foo/main.rs`. Please specify bin.path if you want to use a non-default path.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inferred_bins() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/bin/bar.rs\", \"fn main() {}\")\n        .file(\"src/bin/baz/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(p.bin(\"bar\").is_file());\n    assert!(p.bin(\"baz\").is_file());\n}\n\n#[cargo_test]\nfn inferred_bins_duplicate_name() {\n    // this should fail, because we have two binaries with the same name\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/bin/bar.rs\", \"fn main() {}\")\n        .file(\"src/bin/bar/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  found duplicate binary name bar, but all binary targets must have a unique name\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inferred_bin_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n\n            [[bin]]\n            name = \"bar\"\n            # Note, no `path` key!\n            \"#,\n        )\n        .file(\"src/bin/bar/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"bar\").is_file());\n}\n\n#[cargo_test]\nfn inferred_examples() {\n    let p = project()\n        .file(\"src/lib.rs\", \"fn main() {}\")\n        .file(\"examples/bar.rs\", \"fn main() {}\")\n        .file(\"examples/baz/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --examples\").run();\n    assert!(p.bin(\"examples/bar\").is_file());\n    assert!(p.bin(\"examples/baz\").is_file());\n}\n\n#[cargo_test]\nfn inferred_tests() {\n    let p = project()\n        .file(\"src/lib.rs\", \"fn main() {}\")\n        .file(\"tests/bar.rs\", \"fn main() {}\")\n        .file(\"tests/baz/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"test --test=bar --test=baz\").run();\n}\n\n#[cargo_test]\nfn inferred_benchmarks() {\n    let p = project()\n        .file(\"src/lib.rs\", \"fn main() {}\")\n        .file(\"benches/bar.rs\", \"fn main() {}\")\n        .file(\"benches/baz/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"bench --bench=bar --bench=baz\").run();\n}\n\n#[cargo_test]\nfn no_infer_dirs() {\n    let p = project()\n        .file(\"src/lib.rs\", \"fn main() {}\")\n        .file(\"examples/dir.rs/dummy\", \"\")\n        .file(\"benches/dir.rs/dummy\", \"\")\n        .file(\"tests/dir.rs/dummy\", \"\")\n        .build();\n\n    p.cargo(\"build --examples --benches --tests\").run(); // should not fail with \"is a directory\"\n}\n\n#[cargo_test]\nfn target_edition() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [lib]\n                edition = \"2018\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `edition` is set on library `foo` which is deprecated\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]--edition=2018 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_edition_override() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2018\"\n\n                [lib]\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n                pub fn async() {}\n                pub fn try() {}\n                pub fn await() {}\n            \",\n        )\n        .build();\n\n    p.cargo(\"build -v\").run();\n}\n\n#[cargo_test]\nfn same_metadata_different_directory() {\n    // A top-level crate built in two different workspaces should have the\n    // same metadata hash.\n    let p = project()\n        .at(\"foo1\")\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n    let output = t!(String::from_utf8(p.cargo(\"build -v\").run().stderr,));\n    let metadata = output\n        .split_whitespace()\n        .find(|arg| arg.starts_with(\"metadata=\"))\n        .unwrap();\n\n    let p = project()\n        .at(\"foo2\")\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(format!(\"...\\n[..]{metadata}[..]\\n...\"))\n        .run();\n}\n\n#[cargo_test]\nfn building_a_dependent_crate_without_bin_should_fail() {\n    Package::new(\"testless\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"testless\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"a_bin\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                testless = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] testless v0.1.0 (registry `dummy-registry`)\n[ERROR] failed to download replaced source registry `crates-io`\n\nCaused by:\n  failed to parse manifest at `[ROOT]/home/.cargo/registry/src/-[HASH]/testless-0.1.0/Cargo.toml`\n\nCaused by:\n  can't find `a_bin` bin at `src/bin/a_bin.rs` or `src/bin/a_bin/main.rs`. Please specify bin.path if you want to use a non-default path.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[cfg(any(target_os = \"macos\", target_os = \"ios\"))]\nfn uplift_dsym_of_bin_on_mac() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() { panic!(); }\")\n        .file(\"src/bin/b.rs\", \"fn main() { panic!(); }\")\n        .file(\"examples/c.rs\", \"fn main() { panic!(); }\")\n        .file(\"tests/d.rs\", \"fn main() { panic!(); }\")\n        .build();\n\n    p.cargo(\"build --bins --examples --tests\")\n        .enable_mac_dsym()\n        .run();\n    assert!(p.target_debug_dir().join(\"foo.dSYM\").is_dir());\n    assert!(p.target_debug_dir().join(\"b.dSYM\").is_dir());\n    assert!(p.target_debug_dir().join(\"b.dSYM\").is_symlink());\n    assert!(p.target_debug_dir().join(\"examples/c.dSYM\").is_dir());\n    assert!(!p.target_debug_dir().join(\"c.dSYM\").exists());\n    assert!(!p.target_debug_dir().join(\"d.dSYM\").exists());\n}\n\n#[cargo_test]\n#[cfg(any(target_os = \"macos\", target_os = \"ios\"))]\nfn uplift_dsym_of_bin_on_mac_when_broken_link_exists() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() { panic!(); }\")\n        .build();\n    let dsym = p.target_debug_dir().join(\"foo.dSYM\");\n\n    p.cargo(\"build\").enable_mac_dsym().run();\n    assert!(dsym.is_dir());\n\n    // Simulate the situation where the underlying dSYM bundle goes missing\n    // but the uplifted symlink to it remains. This would previously cause\n    // builds to permanently fail until the bad symlink was manually removed.\n    dsym.rm_rf();\n    p.symlink(\n        p.target_debug_dir()\n            .join(\"deps\")\n            .join(\"foo-baaaaaadbaaaaaad.dSYM\"),\n        &dsym,\n    );\n    assert!(dsym.is_symlink());\n    assert!(!dsym.exists());\n\n    p.cargo(\"build\").enable_mac_dsym().run();\n    assert!(dsym.is_dir());\n}\n\n#[cargo_test]\n#[cfg(all(target_os = \"windows\", target_env = \"msvc\"))]\nfn uplift_pdb_of_bin_on_windows() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() { panic!(); }\")\n        .file(\"src/bin/b.rs\", \"fn main() { panic!(); }\")\n        .file(\"src/bin/foo-bar.rs\", \"fn main() { panic!(); }\")\n        .file(\"examples/c.rs\", \"fn main() { panic!(); }\")\n        .file(\"tests/d.rs\", \"fn main() { panic!(); }\")\n        .build();\n\n    p.cargo(\"build --bins --examples --tests\").run();\n    assert!(p.target_debug_dir().join(\"foo.pdb\").is_file());\n    assert!(p.target_debug_dir().join(\"b.pdb\").is_file());\n    assert!(p.target_debug_dir().join(\"examples/c.pdb\").exists());\n    assert!(p.target_debug_dir().join(\"foo-bar.exe\").is_file());\n    assert!(p.target_debug_dir().join(\"foo_bar.pdb\").is_file());\n    assert!(!p.target_debug_dir().join(\"c.pdb\").exists());\n    assert!(!p.target_debug_dir().join(\"d.pdb\").exists());\n}\n\n#[cargo_test]\n#[cfg(target_os = \"linux\")]\nfn uplift_dwp_of_bin_on_linux() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() { panic!(); }\")\n        .file(\"src/bin/b.rs\", \"fn main() { panic!(); }\")\n        .file(\"src/bin/foo-bar.rs\", \"fn main() { panic!(); }\")\n        .file(\"examples/c.rs\", \"fn main() { panic!(); }\")\n        .file(\"tests/d.rs\", \"fn main() { panic!(); }\")\n        .build();\n\n    p.cargo(\"build --bins --examples --tests\")\n        .enable_split_debuginfo_packed()\n        .run();\n    assert!(p.target_debug_dir().join(\"foo.dwp\").is_file());\n    assert!(p.target_debug_dir().join(\"b.dwp\").is_file());\n    assert!(p.target_debug_dir().join(\"examples/c.dwp\").exists());\n    assert!(p.target_debug_dir().join(\"foo-bar\").is_file());\n    assert!(p.target_debug_dir().join(\"foo-bar.dwp\").is_file());\n    assert!(!p.target_debug_dir().join(\"c.dwp\").exists());\n    assert!(!p.target_debug_dir().join(\"d.dwp\").exists());\n}\n\n// Ensure that `cargo build` chooses the correct profile for building\n// targets based on filters (assuming `--profile` is not specified).\n#[cargo_test]\nfn build_filter_infer_profile() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"tests/t1.rs\", \"\")\n        .file(\"benches/b1.rs\", \"\")\n        .file(\"examples/ex1.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n\n    p.root().join(\"target\").rm_rf();\n    p.cargo(\"build -v --test=t1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..] -C debuginfo=2 [..]`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link[..] -C debuginfo=2 [..]`\n[RUNNING] `rustc --crate-name t1 --edition=2015 tests/t1.rs [..]--emit=[..]link[..] -C debuginfo=2 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n\n    p.root().join(\"target\").rm_rf();\n    // Bench uses test profile without `--release`.\n    p.cargo(\"build -v --bench=b1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link [..]-C debuginfo=2 [..]`\n[RUNNING] `rustc --crate-name b1 --edition=2015 benches/b1.rs [..]--emit=[..]link[..] -C embed-bitcode=no -C debuginfo=2 [..]--test [..]`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link [..]-C debuginfo=2 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn targets_selected_default() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"build -v\")\n        // Binaries.\n        .with_stderr_contains(\n            \"[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin \\\n             --emit=[..]link[..]\",\n        )\n        // Benchmarks.\n        .with_stderr_does_not_contain(\n            \"[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link \\\n             -C opt-level=3 --test [..]\",\n        )\n        // Unit tests.\n        .with_stderr_does_not_contain(\n            \"[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link[..]\\\n             -C debuginfo=2 --test [..]\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn targets_selected_all() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    // The first RUNNING is for unit tests\n    // The second RUNNING is for binaries\n    p.cargo(\"build -v --all-targets\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link [..]-C debuginfo=2 -[..]-test[..]`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn all_targets_no_lib() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    // The first RUNNING is for unit tests\n    // The second RUNNING is for binaries\n    p.cargo(\"build -v --all-targets\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link[..] -C debuginfo=2 [..]--test [..]`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn no_linkable_target() {\n    // Issue 3169: this is currently not an error as per discussion in PR #4797.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                the_lib = { path = \"the_lib\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"the_lib/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"the_lib\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                name = \"the_lib\"\n                crate-type = [\"staticlib\"]\n            \"#,\n        )\n        .file(\"the_lib/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[WARNING] the package `the_lib` provides no linkable target\n  |\n  = [NOTE] this might cause `foo` to fail compilation\n  = [NOTE] this warning might turn into a hard error in the future\n  = [HELP] consider adding 'dylib' or 'rlib' to key 'crate-type' in `the_lib`'s Cargo.toml\n[COMPILING] the_lib v0.1.0 ([ROOT]/foo/the_lib)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn avoid_dev_deps() {\n    Package::new(\"foo\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dev-dependencies]\n                baz = \"1.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package named `baz` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `bar v0.1.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zavoid-dev-deps\")\n        .masquerade_as_nightly_cargo(&[\"avoid-dev-deps\"])\n        .run();\n}\n\n#[cargo_test]\nfn default_cargo_config_jobs() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                jobs = 1\n            \"#,\n        )\n        .build();\n    p.cargo(\"build -v\").run();\n}\n\n#[cargo_test]\nfn good_cargo_config_jobs() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                jobs = 4\n            \"#,\n        )\n        .build();\n    p.cargo(\"build -v\").run();\n}\n\n#[cargo_test]\nfn good_jobs() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build --jobs 1\").run();\n\n    p.cargo(\"build --jobs -1\").run();\n\n    p.cargo(\"build --jobs default\").run();\n}\n\n#[cargo_test]\nfn invalid_cargo_config_jobs() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                jobs = 0\n            \"#,\n        )\n        .build();\n    p.cargo(\"build -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] jobs may not be 0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_jobs() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build --jobs 0\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] jobs may not be 0\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --jobs over9000\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not parse `over9000`. Number of parallel jobs should be `default` or a number.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_filters_workspace() {\n    let ws = project()\n        .at(\"ws\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_lib_manifest(\"a\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\"a/examples/ex1.rs\", \"fn main() {}\")\n        .file(\"b/Cargo.toml\", &basic_bin_manifest(\"b\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\"b/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    ws.cargo(\"build -v --example ex\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no example target named `ex` in default-run packages\n\n[HELP] a target with a similar name exists: `ex1`\n\n\"#]])\n        .run();\n\n    ws.cargo(\"build -v --example 'ex??'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no example target matches pattern `ex??` in default-run packages\n\n[HELP] a target with a similar name exists: `ex1`\n\n\"#]])\n        .run();\n\n    ws.cargo(\"build -v --lib\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] a v0.5.0 ([ROOT]/ws/a)\n[COMPILING] b v0.5.0 ([ROOT]/ws/b)\n[RUNNING] `rustc [..]a/src/lib.rs[..]`\n[RUNNING] `rustc [..]b/src/lib.rs[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    ws.cargo(\"build -v --example ex1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] a v0.5.0 ([ROOT]/ws/a)\n[RUNNING] `rustc [..]a/examples/ex1.rs[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_filters_workspace_not_found() {\n    let ws = project()\n        .at(\"ws\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_bin_manifest(\"a\"))\n        .file(\"a/src/main.rs\", \"fn main() {}\")\n        .file(\"b/Cargo.toml\", &basic_bin_manifest(\"b\"))\n        .file(\"b/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    ws.cargo(\"build -v --lib\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no library targets found in packages: a, b\n\n\"#]])\n        .run();\n}\n\n#[cfg(unix)]\n#[cargo_test]\nfn signal_display() {\n    // Cause the compiler to crash with a signal.\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [dependencies]\n                pm = { path = \"pm\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[macro_use]\n                extern crate pm;\n\n                #[derive(Foo)]\n                pub struct S;\n            \"#,\n        )\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pm\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"pm/src/lib.rs\",\n            r#\"\n                extern crate proc_macro;\n                use proc_macro::TokenStream;\n\n                #[proc_macro_derive(Foo)]\n                pub fn derive(_input: TokenStream) -> TokenStream {\n                    std::process::abort()\n                }\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] pm v0.1.0 ([ROOT]/foo/pm)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[ERROR] could not compile `foo` (lib)\n\nCaused by:\n  process didn't exit successfully: `rustc [..]` (signal: 6, SIGABRT: process abort signal)\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn tricky_pipelining() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"build -p bar\").run();\n    foo.cargo(\"build -p foo\").run();\n}\n\n#[cargo_test]\nfn pipelining_works() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"build\")\n        .with_stdout_data(str![])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn pipelining_big_graph() {\n    // Create a crate graph of the form {a,b}{0..29}, where {a,b}(n) depend on {a,b}(n+1)\n    // Then have `foo`, a binary crate, depend on the whole thing.\n    let mut project = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [dependencies]\n                a1 = { path = \"a1\" }\n                b1 = { path = \"b1\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\");\n\n    for n in 0..30 {\n        for x in &[\"a\", \"b\"] {\n            project = project\n                .file(\n                    &format!(\"{x}{n}/Cargo.toml\", x = x, n = n),\n                    &format!(\n                        r#\"\n                            [package]\n                            name = \"{x}{n}\"\n                            version = \"0.1.0\"\n                            edition = \"2015\"\n                            [dependencies]\n                            a{np1} = {{ path = \"../a{np1}\" }}\n                            b{np1} = {{ path = \"../b{np1}\" }}\n                        \"#,\n                        x = x,\n                        n = n,\n                        np1 = n + 1\n                    ),\n                )\n                .file(&format!(\"{x}{n}/src/lib.rs\", x = x, n = n), \"\");\n        }\n    }\n\n    let foo = project\n        .file(\"a30/Cargo.toml\", &basic_lib_manifest(\"a30\"))\n        .file(\n            \"a30/src/lib.rs\",\n            r#\"compile_error!(\"don't actually build me\");\"#,\n        )\n        .file(\"b30/Cargo.toml\", &basic_lib_manifest(\"b30\"))\n        .file(\"b30/src/lib.rs\", \"\")\n        .build();\n    foo.cargo(\"build -p foo\")\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] a30 v0.5.0 ([ROOT]/foo/a30)\n[ERROR] don't actually build me\n...\n[ERROR] could not compile `a30` (lib) due to 1 previous error\n...\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn forward_rustc_output() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = '2018'\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"bar::foo!();\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                extern crate proc_macro;\n                use proc_macro::*;\n\n                #[proc_macro]\n                pub fn foo(input: TokenStream) -> TokenStream {\n                    println!(\"a\");\n                    println!(\"b\");\n                    println!(\"{{}}\");\n                    eprintln!(\"c\");\n                    eprintln!(\"d\");\n                    eprintln!(\"{{a\"); // \"malformed json\"\n                    input\n                }\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"build\")\n        .with_stdout_data(str![[r#\"\na\nb\n{}\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\nc\nd\n{a\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_lib_only() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", r#\" \"#)\n        .build();\n\n    p.cargo(\"build --lib -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..] -L dependency=[ROOT]/foo/target/debug/deps`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_with_no_lib() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --lib\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no library targets found in package `foo`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_with_relative_cargo_home_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies]\n\n                \"test-dependency\" = { path = \"src/test_dependency\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/test_dependency/src/lib.rs\", r#\" \"#)\n        .file(\n            \"src/test_dependency/Cargo.toml\",\n            &basic_manifest(\"test-dependency\", \"0.0.1\"),\n        )\n        .build();\n\n    p.cargo(\"build\").env(\"CARGO_HOME\", \"./cargo_home/\").run();\n}\n\n#[cargo_test]\nfn user_specific_cfgs_are_filtered_out() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", r#\"fn main() {}\"#)\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                assert!(std::env::var_os(\"CARGO_CFG_PROC_MACRO\").is_none());\n                assert!(std::env::var_os(\"CARGO_CFG_DEBUG_ASSERTIONS\").is_some());\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"rustc -- --cfg debug_assertions --cfg proc_macro -Aunknown_lints -Aexplicit_builtin_cfgs_in_flags\")\n        .run();\n    p.process(&p.bin(\"foo\")).run();\n}\n\n#[cargo_test]\nfn close_output() {\n    // What happens when stdout or stderr is closed during a build.\n\n    // Server to know when rustc has spawned.\n    let listener = std::net::TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let addr = listener.local_addr().unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [lib]\n                proc-macro = true\n\n                [[bin]]\n                name = \"foobar\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            &r#\"\n                use proc_macro::TokenStream;\n                use std::io::Read;\n\n                #[proc_macro]\n                pub fn repro(_input: TokenStream) -> TokenStream {\n                    println!(\"hello stdout!\");\n                    eprintln!(\"hello stderr!\");\n                    // Tell the test we have started.\n                    let mut socket = std::net::TcpStream::connect(\"__ADDR__\").unwrap();\n                    // Wait for the test to tell us to start printing.\n                    let mut buf = [0];\n                    drop(socket.read_exact(&mut buf));\n                    let use_stderr = std::env::var(\"__CARGO_REPRO_STDERR\").is_ok();\n                    // Emit at least 1MB of data.\n                    // Linux pipes can buffer up to 64KB.\n                    // This test seems to be sensitive to having other threads\n                    // calling fork. My hypothesis is that the stdout/stderr\n                    // file descriptors are duplicated into the child process,\n                    // and during the short window between fork and exec, the\n                    // file descriptor is kept alive long enough for the\n                    // build to finish. It's a half-baked theory, but this\n                    // seems to prevent the spurious errors in CI.\n                    // An alternative solution is to run this test in\n                    // a single-threaded environment.\n                    for i in 0..100000 {\n                        if use_stderr {\n                            eprintln!(\"0123456789{}\", i);\n                        } else {\n                            println!(\"0123456789{}\", i);\n                        }\n                    }\n                    TokenStream::new()\n                }\n            \"#\n            .replace(\"__ADDR__\", &addr.to_string()),\n        )\n        .file(\n            \"src/bin/foobar.rs\",\n            r#\"\n                foo::repro!();\n\n                fn main() {}\n            \"#,\n        )\n        .build();\n\n    // The `stderr` flag here indicates if this should forcefully close stderr or stdout.\n    let spawn = |stderr: bool| {\n        let mut cmd = p.cargo(\"build\").build_command();\n        cmd.stdout(Stdio::piped()).stderr(Stdio::piped());\n        if stderr {\n            cmd.env(\"__CARGO_REPRO_STDERR\", \"1\");\n        }\n        let mut child = cmd.spawn().unwrap();\n        // Wait for proc macro to start.\n        let pm_conn = listener.accept().unwrap().0;\n        // Close stderr or stdout.\n        if stderr {\n            drop(child.stderr.take());\n        } else {\n            drop(child.stdout.take());\n        }\n        // Tell the proc-macro to continue;\n        drop(pm_conn);\n        // Read the output from the other channel.\n        let out: &mut dyn Read = if stderr {\n            child.stdout.as_mut().unwrap()\n        } else {\n            child.stderr.as_mut().unwrap()\n        };\n        let mut result = String::new();\n        out.read_to_string(&mut result).unwrap();\n        let status = child.wait().unwrap();\n        assert!(!status.success());\n        result\n    };\n\n    let stderr = spawn(false);\n    assert_e2e().eq(\n        &stderr,\n        str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\nhello stderr!\n[ERROR] [BROKEN_PIPE]\n[WARNING] build failed, waiting for other jobs to finish...\n\n\"#]]\n        .unordered(),\n    );\n\n    // Try again with stderr.\n    p.build_dir().rm_rf();\n    let stdout = spawn(true);\n    assert_eq!(stdout, \"hello stdout!\\n\");\n}\n\n#[cargo_test]\nfn close_output_during_drain() {\n    // Test to close the output during the build phase (drain_the_queue).\n    // There was a bug where it would hang.\n\n    // Server to know when rustc has spawned.\n    let listener = std::net::TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let addr = listener.local_addr().unwrap();\n\n    // Create a wrapper so the test can know when compiling has started.\n    let rustc_wrapper = {\n        let p = project()\n            .at(\"compiler\")\n            .file(\"Cargo.toml\", &basic_manifest(\"compiler\", \"1.0.0\"))\n            .file(\n                \"src/main.rs\",\n                &r#\"\n                    use std::process::Command;\n                    use std::env;\n                    use std::io::Read;\n\n                    fn main() {\n                        // Only wait on the first dependency.\n                        if matches!(env::var(\"CARGO_PKG_NAME\").as_deref(), Ok(\"dep\")) {\n                            let mut socket = std::net::TcpStream::connect(\"__ADDR__\").unwrap();\n                            // Wait for the test to tell us to start printing.\n                            let mut buf = [0];\n                            drop(socket.read_exact(&mut buf));\n                        }\n                        let mut cmd = Command::new(\"rustc\");\n                        for arg in env::args_os().skip(1) {\n                            cmd.arg(arg);\n                        }\n                        std::process::exit(cmd.status().unwrap().code().unwrap());\n                    }\n                \"#\n                .replace(\"__ADDR__\", &addr.to_string()),\n            )\n            .build();\n        p.cargo(\"build\").run();\n        p.bin(\"compiler\")\n    };\n\n    Package::new(\"dep\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                dep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Spawn cargo, wait for the first rustc to start, and then close stderr.\n    let mut cmd = process(&cargo_exe())\n        .arg(\"check\")\n        .cwd(p.root())\n        .env(\"RUSTC\", rustc_wrapper)\n        .build_command();\n    cmd.stdout(Stdio::piped()).stderr(Stdio::piped());\n    let mut child = cmd.spawn().expect(\"cargo should spawn\");\n    // Wait for the rustc wrapper to start.\n    let rustc_conn = listener.accept().unwrap().0;\n    // Close stderr to force an error.\n    drop(child.stderr.take());\n    // Tell the wrapper to continue.\n    drop(rustc_conn);\n    match child.wait() {\n        Ok(status) => assert!(!status.success()),\n        Err(e) => panic!(\"child wait failed: {}\", e),\n    }\n}\n\nuse cargo_test_support::registry::Dependency;\n\n#[cargo_test]\nfn reduced_reproduction_8249() {\n    // https://github.com/rust-lang/cargo/issues/8249\n    Package::new(\"a-src\", \"0.1.0\").links(\"a\").publish();\n    Package::new(\"a-src\", \"0.2.0\").links(\"a\").publish();\n\n    Package::new(\"b\", \"0.1.0\")\n        .add_dep(Dependency::new(\"a-src\", \"0.1\").optional(true))\n        .publish();\n    Package::new(\"b\", \"0.2.0\")\n        .add_dep(Dependency::new(\"a-src\", \"0.2\").optional(true))\n        .publish();\n\n    Package::new(\"c\", \"1.0.0\")\n        .add_dep(&Dependency::new(\"b\", \"0.1.0\"))\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                b = { version = \"*\", features = [\"a-src\"] }\n                a-src = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n    cargo_util::paths::append(&p.root().join(\"Cargo.toml\"), b\"c = \\\"*\\\"\").unwrap();\n    p.cargo(\"check\").run();\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn target_directory_backup_exclusion() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    // Newly created target/ should have CACHEDIR.TAG inside...\n    p.cargo(\"build\").run();\n    let cachedir_tag = p.build_dir().join(\"CACHEDIR.TAG\");\n    assert!(cachedir_tag.is_file());\n    assert!(\n        fs::read_to_string(&cachedir_tag)\n            .unwrap()\n            .starts_with(\"Signature: 8a477f597d28d172789f06886806bc55\")\n    );\n    // ...but if target/ already exists CACHEDIR.TAG should not be created in it.\n    fs::remove_file(&cachedir_tag).unwrap();\n    p.cargo(\"build\").run();\n    assert!(!&cachedir_tag.is_file());\n}\n\n#[cargo_test]\nfn simple_terminal_width() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() {\n                    let _: () = 42;\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .env(\"__CARGO_TEST_TTY_WIDTH_DO_NOT_USE_THIS\", \"20\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]--diagnostic-width=20[..]\nerror[E0308][..]\n...\n[ERROR] could not compile `foo` (lib) due to 1 previous error\n\nCaused by:\n  process didn't exit successfully: `rustc [..]` ([EXIT_STATUS]: 1)\n\n\"#]])\n        .run();\n\n    p.cargo(\"doc -v\")\n        .env(\"__CARGO_TEST_TTY_WIDTH_DO_NOT_USE_THIS\", \"20\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]--diagnostic-width=20[..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_script_o0_default() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v --release\")\n        .with_stderr_does_not_contain(\"[..]build_script_build[..]opt-level[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn build_script_o0_default_even_with_release() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [profile.release]\n                opt-level = 1\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v --release\")\n        .with_stderr_does_not_contain(\"[..]build_script_build[..]opt-level[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn primary_package_env_var() {\n    // Test that CARGO_PRIMARY_PACKAGE is enabled only for \"foo\" and not for any dependency.\n\n    let is_primary_package = r#\"\n        pub fn is_primary_package() -> bool {{\n            option_env!(\"CARGO_PRIMARY_PACKAGE\").is_some()\n        }}\n    \"#;\n\n    Package::new(\"qux\", \"0.1.0\")\n        .file(\"src/lib.rs\", is_primary_package)\n        .publish();\n\n    let baz = git::new(\"baz\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n            .file(\"src/lib.rs\", is_primary_package)\n    });\n\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    bar = {{ path = \"bar\" }}\n                    baz = {{ git = '{}' }}\n                    qux = \"0.1\"\n                \"#,\n                baz.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            &format!(\n                r#\"\n                    extern crate bar;\n                    extern crate baz;\n                    extern crate qux;\n\n                    {}\n\n                    #[test]\n                    fn verify_primary_package() {{\n                        assert!(!bar::is_primary_package());\n                        assert!(!baz::is_primary_package());\n                        assert!(!qux::is_primary_package());\n                        assert!(is_primary_package());\n                    }}\n                \"#,\n                is_primary_package\n            ),\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", is_primary_package)\n        .build();\n\n    foo.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn renamed_uplifted_artifact_remains_unmodified_after_rebuild() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    let bin = p.bin(\"foo\");\n    let renamed_bin = p.bin(\"foo-renamed\");\n\n    fs::rename(&bin, &renamed_bin).unwrap();\n\n    p.change_file(\"src/main.rs\", \"fn main() { eprintln!(\\\"hello, world\\\"); }\");\n    p.cargo(\"build\").run();\n\n    let not_the_same = !same_file::is_same_file(bin, renamed_bin).unwrap();\n    assert!(not_the_same, \"renamed uplifted artifact must be unmodified\");\n}\n\n#[cargo_test(nightly, reason = \"-Zno-embed-metadata is nightly only\")]\nfn no_embed_metadata() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[]))\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\n            \"bar/src/bar.rs\",\n            r#\"\n                pub fn gimme() -> &'static str {\n                    \"test passed\"\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z no-embed-metadata\")\n        .masquerade_as_nightly_cargo(&[\"-Z no-embed-metadata\"])\n        .arg(\"-v\")\n        .with_stderr_contains(\"[RUNNING] `[..]-Z embed-metadata=no[..]`\")\n        .with_stderr_contains(\n            \"[RUNNING] `[..]--extern bar=[ROOT]/foo/target/debug/deps/libbar-[HASH].rmeta[..]`\",\n        )\n        .run();\n}\n\n// Make sure that cargo passes --extern=<dep>.rmeta even if <dep>\n// is compiled as a dylib.\n#[cargo_test(nightly, reason = \"-Zno-embed-metadata is nightly only\")]\nfn no_embed_metadata_dylib_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[]))\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"dylib\"]\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                pub fn gimme() -> &'static str {\n                    \"test passed\"\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z no-embed-metadata\")\n        .masquerade_as_nightly_cargo(&[\"-Z no-embed-metadata\"])\n        .arg(\"-v\")\n        .with_stderr_contains(\"[RUNNING] `[..]-Z embed-metadata=no[..]`\")\n        .with_stderr_contains(\n            \"[RUNNING] `[..]--extern bar=[ROOT]/foo/target/debug/deps/libbar.rmeta[..]`\",\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zno-embed-metadata is nightly only\")]\nfn no_embed_metadata_invalidate() {\n    // Invalidate all deps when -Zno-embed-metadata is toggled\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[]))\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\n            \"bar/src/bar.rs\",\n            r#\"\n                pub fn gimme() -> &'static str {\n                    \"test passed\"\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z no-embed-metadata\")\n        .masquerade_as_nightly_cargo(&[\"-Z no-embed-metadata\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build\")\n        .masquerade_as_nightly_cargo(&[\"-Z no-embed-metadata\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/build_analysis.rs",
    "content": "//! Tests for `-Zbuild-analysis`.\n\nuse crate::prelude::*;\n\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::paths::log_file;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn gated() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] ignoring 'build.analysis' config, pass `-Zbuild-analysis` to enable it\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn one_logfile_per_invocation() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // First invocation\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let _ = get_log(0);\n\n    // Second invocation\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let _ = get_log(1);\n}\n\n#[cargo_test]\nfn log_msg_build_started() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    assert_e2e().eq(\n        &get_log(0),\n        str![[r#\"\n[\n  {\n    \"command\": \"{...}\",\n    \"cwd\": \"[ROOT]/foo\",\n    \"host\": \"[HOST_TARGET]\",\n    \"jobs\": \"{...}\",\n    \"num_cpus\": \"{...}\",\n    \"profile\": \"dev\",\n    \"reason\": \"build-started\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"rustc_version\": \"1.[..]\",\n    \"rustc_version_verbose\": \"{...}\",\n    \"target_dir\": \"[ROOT]/foo/target\",\n    \"timestamp\": \"[..]T[..]Z\",\n    \"workspace_root\": \"[ROOT]/foo\"\n  },\n  \"{...}\"\n]\n\"#]]\n        .is_json()\n        .against_jsonlines(),\n    );\n}\n\n#[cargo_test]\nfn log_msg_timing_info() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    assert_e2e().eq(\n        &get_log(0),\n        str![[r#\"\n[\n  \"{...}\",\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 0,\n    \"reason\": \"unit-started\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 0,\n    \"reason\": \"unit-rmeta-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 0,\n    \"reason\": \"unit-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\",\n    \"unblocked\": [\n      1\n    ]\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 1,\n    \"reason\": \"unit-started\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 1,\n    \"reason\": \"unit-rmeta-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 1,\n    \"reason\": \"unit-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  }\n]\n\"#]]\n        .is_json()\n        .against_jsonlines(),\n    );\n}\n\n#[cargo_test(nightly, reason = \"rustc --json=timings is unstable\")]\nfn log_msg_timing_info_section_timings() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis -Zsection-timings\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\", \"section-timings\"])\n        .run();\n\n    assert_e2e().eq(\n        &get_log(0),\n        str![[r#\"\n[\n  \"{...}\",\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 0,\n    \"reason\": \"unit-started\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 0,\n    \"reason\": \"unit-section-started\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"section\": \"codegen\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 0,\n    \"reason\": \"unit-rmeta-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 0,\n    \"reason\": \"unit-section-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"section\": \"codegen\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 0,\n    \"reason\": \"unit-section-started\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"section\": \"link\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 0,\n    \"reason\": \"unit-section-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"section\": \"link\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 0,\n    \"reason\": \"unit-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\",\n    \"unblocked\": [\n      1\n    ]\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 1,\n    \"reason\": \"unit-started\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 1,\n    \"reason\": \"unit-section-started\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"section\": \"codegen\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 1,\n    \"reason\": \"unit-rmeta-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 1,\n    \"reason\": \"unit-section-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"section\": \"codegen\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 1,\n    \"reason\": \"unit-section-started\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"section\": \"link\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 1,\n    \"reason\": \"unit-section-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"section\": \"link\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"index\": 1,\n    \"reason\": \"unit-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  }\n]\n\"#]]\n        .is_json()\n        .against_jsonlines(),\n    );\n}\n\n#[cargo_test]\nfn log_rebuild_reason_fresh_build() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert_e2e().eq(\n        &get_log(0),\n        str![[r#\"\n[\n  \"{...}\",\n  {\n    \"...\": \"{...}\",\n    \"reason\": \"unit-graph-finished\"\n  },\n  {\n    \"index\": 0,\n    \"reason\": \"unit-fingerprint\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"status\": \"new\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"...\": \"{...}\",\n    \"reason\": \"unit-started\"\n  },\n  \"{...}\"\n]\n\"#]]\n        .is_json()\n        .against_jsonlines(),\n    );\n}\n\n#[cargo_test]\nfn log_rebuild_reason_file_changed() {\n    // Test that changing a file logs the appropriate rebuild reason\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    assert_e2e().eq(\n        &get_log(0),\n        str![[r#\"\n[\n  \"{...}\",\n  {\n    \"...\": \"{...}\",\n    \"reason\": \"unit-graph-finished\"\n  },\n  {\n    \"index\": 0,\n    \"reason\": \"unit-fingerprint\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"status\": \"new\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"...\": \"{...}\",\n    \"reason\": \"unit-started\"\n  },\n  \"{...}\"\n]\n\"#]]\n        .is_json()\n        .against_jsonlines(),\n    );\n\n    // Change source file\n    p.change_file(\"src/lib.rs\", \"//! comment\");\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // File changes SHOULD log rebuild-reason\n    assert_e2e().eq(\n        &get_log(1),\n        str![[r#\"\n[\n  \"{...}\",\n  {\n    \"...\": \"{...}\",\n    \"reason\": \"unit-graph-finished\"\n  },\n  {\n    \"cause\": {\n      \"dirty_reason\": \"fs-status-outdated\",\n      \"fs_status\": \"stale-item\",\n      \"reference\": \"[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/dep-lib-foo\",\n      \"reference_mtime\": \"{...}\",\n      \"stale\": \"[ROOT]/foo/src/lib.rs\",\n      \"stale_item\": \"changed-file\",\n      \"stale_mtime\": \"{...}\"\n    },\n    \"index\": 0,\n    \"reason\": \"unit-fingerprint\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"status\": \"dirty\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"...\": \"{...}\",\n    \"reason\": \"unit-started\"\n  },\n  \"{...}\"\n]\n\"#]]\n        .is_json()\n        .against_jsonlines(),\n    );\n}\n\n#[cargo_test]\nfn log_rebuild_reason_no_rebuild() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // First build\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    assert_e2e().eq(\n        &get_log(0),\n        str![[r#\"\n[\n  \"{...}\",\n  {\n    \"...\": \"{...}\",\n    \"reason\": \"unit-graph-finished\"\n  },\n  {\n    \"index\": 0,\n    \"reason\": \"unit-fingerprint\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"status\": \"new\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"...\": \"{...}\",\n    \"reason\": \"unit-started\"\n  },\n  \"{...}\"\n]\n\"#]]\n        .is_json()\n        .against_jsonlines(),\n    );\n\n    // Second build without changes\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Should NOT contain any rebuild-reason messages since nothing rebuilt\n    assert_e2e().eq(\n        &get_log(1),\n        str![[r#\"\n[\n  \"{...}\",\n  {\n    \"...\": \"{...}\",\n    \"reason\": \"unit-graph-finished\"\n  },\n  {\n    \"index\": 0,\n    \"reason\": \"unit-fingerprint\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"status\": \"fresh\",\n    \"timestamp\": \"[..]T[..]Z\"\n  }\n]\n\"#]]\n        .is_json()\n        .against_jsonlines(),\n    );\n}\n\n#[cargo_test]\nfn log_msg_unit_graph() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    // `cargo doc` generates more units than `cargo check`\n    // * check bar\n    // * build foo build.rs\n    // * run foo build.rs\n    // * doc foo\n    // * doc bar\n    p.cargo(\"doc -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\", \"section-timings\"])\n        .run();\n\n    assert_e2e().eq(\n        &get_log(0),\n        str![[r#\"\n[\n  \"{...}\",\n  {\n    \"elapsed\": \"{...}\",\n    \"reason\": \"unit-graph-started\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"index\": 0,\n    \"mode\": \"check\",\n    \"package_id\": \"path+[ROOTURL]/foo/bar#0.0.0\",\n    \"platform\": \"[HOST_TARGET]\",\n    \"reason\": \"unit-registered\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"target\": {\n      \"kind\": \"lib\",\n      \"name\": \"bar\"\n    },\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"index\": 1,\n    \"mode\": \"doc\",\n    \"package_id\": \"path+[ROOTURL]/foo/bar#0.0.0\",\n    \"platform\": \"[HOST_TARGET]\",\n    \"reason\": \"unit-registered\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"target\": {\n      \"kind\": \"lib\",\n      \"name\": \"bar\"\n    },\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"dependencies\": [\n      0,\n      1,\n      4\n    ],\n    \"index\": 2,\n    \"mode\": \"doc\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.0\",\n    \"platform\": \"[HOST_TARGET]\",\n    \"reason\": \"unit-registered\",\n    \"requested\": true,\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"target\": {\n      \"kind\": \"lib\",\n      \"name\": \"foo\"\n    },\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"index\": 3,\n    \"mode\": \"build\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.0\",\n    \"platform\": \"[HOST_TARGET]\",\n    \"reason\": \"unit-registered\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"target\": {\n      \"kind\": \"build-script\",\n      \"name\": \"build-script-build\"\n    },\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"dependencies\": [\n      3\n    ],\n    \"index\": 4,\n    \"mode\": \"run-custom-build\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.0\",\n    \"platform\": \"[HOST_TARGET]\",\n    \"reason\": \"unit-registered\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"target\": {\n      \"kind\": \"build-script\",\n      \"name\": \"build-script-build\"\n    },\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"reason\": \"unit-graph-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  \"{...}\"\n]\n\"#]]\n        .is_json()\n        .against_jsonlines(),\n    );\n}\n\n#[cargo_test]\nfn log_msg_resolution_events() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\", \"section-timings\"])\n        .run();\n\n    assert_e2e().eq(\n        &get_log(0),\n        str![[r#\"\n[\n  \"{...}\",\n  {\n    \"elapsed\": \"{...}\",\n    \"reason\": \"resolution-started\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  {\n    \"elapsed\": \"{...}\",\n    \"reason\": \"resolution-finished\",\n    \"run_id\": \"[..]T[..]Z-[..]\",\n    \"timestamp\": \"[..]T[..]Z\"\n  },\n  \"{...}\"\n]\n\"#]]\n        .is_json()\n        .against_jsonlines(),\n    );\n}\n\nfn get_log(idx: usize) -> String {\n    std::fs::read_to_string(log_file(idx)).unwrap()\n}\n"
  },
  {
    "path": "tests/testsuite/build_dir.rs",
    "content": "//! Tests for `build.build-dir` config property.\n//!\n//! The testing strategy for build-dir functionality is primarily checking if directories / files\n//! are in the expected locations.\n//! The rational is that other tests will verify each individual feature, while the tests in this\n//! file verify the files saved to disk are in the correct locations according to the `build-dir`\n//! configuration.\n//!\n//! Tests check if directories match some \"layout\" by using [`CargoPathExt::assert_file_layout`]\n\nuse std::path::PathBuf;\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::{Package, RegistryBuilder};\nuse cargo_test_support::{paths, prelude::*, project, str};\nuse std::env::consts::{DLL_PREFIX, DLL_SUFFIX, EXE_SUFFIX};\n\n#[cargo_test]\nfn binary_with_debug() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    assert_not_exists(&p.root().join(\"target\"));\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n[ROOT]/foo/target-dir/debug/foo.d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn binary_with_release() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build --release\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    assert_exists_patterns_with_base_dir(\n        &p.root(),\n        &[\n            // Check the pre-uplifted binary in the build-dir\n            &format!(\"build-dir/release/build/foo/*/out/foo*{EXE_SUFFIX}\"),\n            \"build-dir/release/build/foo/*/out/foo*.d\",\n            // Verify the binary was copied to the target-dir\n            &format!(\"target-dir/release/foo{EXE_SUFFIX}\"),\n            \"target-dir/release/foo.d\",\n        ],\n    );\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/release/.cargo-build-lock\n[ROOT]/foo/build-dir/release/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/build-dir/release/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/build-dir/release/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/build-dir/release/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/release/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/release/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/build-dir/release/build/foo/[HASH]/.lock\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/release/.cargo-lock\n[ROOT]/foo/target-dir/release/foo[EXE]\n[ROOT]/foo/target-dir/release/foo.d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn libs() {\n    // https://doc.rust-lang.org/reference/linkage.html#r-link.staticlib\n    let (staticlib_prefix, staticlib_suffix) =\n        if cfg!(target_os = \"windows\") && cfg!(target_env = \"msvc\") {\n            (\"\", \".lib\")\n        } else {\n            (\"lib\", \".a\")\n        };\n\n    // (crate-type, list of final artifacts)\n    let lib_types = [\n        (\"lib\", [\"libfoo.rlib\", \"libfoo.d\"]),\n        (\n            \"dylib\",\n            [\n                &format!(\"{DLL_PREFIX}foo{DLL_SUFFIX}\"),\n                &format!(\"{DLL_PREFIX}foo.d\"),\n            ],\n        ),\n        (\n            \"cdylib\",\n            [\n                &format!(\"{DLL_PREFIX}foo{DLL_SUFFIX}\"),\n                &format!(\"{DLL_PREFIX}foo.d\"),\n            ],\n        ),\n        (\n            \"staticlib\",\n            [\n                &format!(\"{staticlib_prefix}foo{staticlib_suffix}\"),\n                &format!(\"{staticlib_prefix}foo.d\"),\n            ],\n        ),\n    ];\n\n    for (lib_type, expected_files) in lib_types {\n        let p = project()\n            .file(\"src/lib.rs\", r#\"fn foo() { println!(\"Hello, World!\") }\"#)\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            authors = []\n            edition = \"2015\"\n\n            [lib]\n            crate-type = [\"{lib_type}\"]\n            \"#\n                ),\n            )\n            .file(\n                \".cargo/config.toml\",\n                r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n            )\n            .build();\n\n        p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n            .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n            .enable_mac_dsym()\n            .run();\n\n        // Verify lib artifacts were copied into the artifact dir\n        assert_exists_patterns_with_base_dir(&p.root().join(\"target-dir/debug\"), &expected_files);\n    }\n}\n\n#[cargo_test]\nfn should_default_to_target() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    p.root().join(\"target\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target/.rustc_info.json\n[ROOT]/foo/target/CACHEDIR.TAG\n[ROOT]/foo/target/debug/.cargo-lock\n[ROOT]/foo/target/debug/.cargo-build-lock\n[ROOT]/foo/target/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/target/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/target/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/target/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/target/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/target/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/target/debug/foo[EXE]\n[ROOT]/foo/target/debug/foo.d\n[ROOT]/foo/target/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n}\n\n#[cargo_test]\nfn should_respect_env_var() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .env(\"CARGO_BUILD_BUILD_DIR\", \"build-dir\")\n        .enable_mac_dsym()\n        .run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n}\n\n#[cargo_test]\nfn build_script_should_output_to_build_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                std::fs::write(\n                    format!(\"{}/foo.txt\", std::env::var(\"OUT_DIR\").unwrap()),\n                    \"Hello, world!\",\n                )\n                .unwrap();\n            }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo.txt\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/build_script_build[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/build_script_build[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/build-script-build[EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/run-build-script-build-script-build\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/run-build-script-build-script-build.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-build-script-build-script-build\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/build-script-build-script-build\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/build-script-build-script-build.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/run/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/run/stdout\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/run/root-output\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/run/stderr\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n}\n\n#[cargo_test]\nfn cargo_tmpdir_should_output_to_build_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \"tests/foo.rs\",\n            r#\"\n            #[test]\n            fn test() {\n                std::fs::write(\n                    format!(\"{}/foo.txt\", env!(\"CARGO_TARGET_TMPDIR\")),\n                    \"Hello, world!\",\n                )\n                .unwrap();\n            }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking test\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo-[HASH].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo.d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo-[HASH][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-test-bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/test-bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/test-bin-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-test-integration-test-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/test-integration-test-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/test-integration-test-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n[ROOT]/foo/build-dir/tmp/foo.txt\n[ROOT]/foo/build-dir/.rustc_info.json\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n\n\"#]]);\n}\n\n#[cargo_test]\nfn examples_should_output_to_build_dir_and_uplift_to_target_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\"examples/foo.rs\", r#\"fn main() { }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build --examples\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-example-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/example-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/example-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n\n    assert!(!p.root().join(\"build-dir/debug/examples\").exists());\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/examples/foo[EXE]\n[ROOT]/foo/target-dir/debug/examples/foo.d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn benches_should_output_to_build_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\"benches/foo.rs\", r#\"fn main() { }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build --bench=foo\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo-[HASH].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo-[HASH][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-test-bench-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/test-bench-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/test-bench-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n[ROOT]/foo/build-dir/.rustc_info.json\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n\n\"#]]);\n}\n\n#[cargo_test]\nfn cargo_doc_should_output_to_target_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking doc\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    let docs_dir = p.root().join(\"target-dir/doc\");\n\n    assert_exists(&docs_dir);\n    assert_exists(&docs_dir.join(\"foo/index.html\"));\n}\n\n#[cargo_test]\nfn cargo_package_should_build_in_build_dir_and_output_to_target_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking package\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    let package_artifact_dir = p.root().join(\"target-dir/package\");\n    assert_exists(&package_artifact_dir);\n    assert_exists(&package_artifact_dir.join(\"foo-0.0.1.crate\"));\n    assert!(package_artifact_dir.join(\"foo-0.0.1.crate\").is_file());\n    // FIXME: The `.cargo-lock` file should be in target-dir not build-dir. See #16707\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/debug/.cargo-lock\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n[ROOT]/foo/build-dir/debug/foo[EXE]\n[ROOT]/foo/build-dir/debug/foo.d\n[ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.lock\n[ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.toml\n[ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.toml.orig\n[ROOT]/foo/build-dir/package/foo-0.0.1/src/main.rs\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/package/tmp-crate/foo-0.0.1.crate\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/package/foo-0.0.1.crate\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n\n\"#]]);\n}\n\n#[cargo_test]\nfn cargo_publish_should_only_touch_build_dir() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking publish\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .replace_crates_io(registry.index_url())\n        .enable_mac_dsym()\n        .run();\n\n    let package_artifact_dir = p.root().join(\"target-dir/package\");\n    assert!(!package_artifact_dir.exists());\n\n    let package_build_dir = p.root().join(\"build-dir/package\");\n    assert_exists(&package_build_dir);\n    assert_exists(&package_build_dir.join(\"foo-0.0.1\"));\n    assert!(package_build_dir.join(\"foo-0.0.1\").is_dir());\n}\n\n#[cargo_test]\nfn cargo_clean_should_clean_the_target_dir_and_build_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n[ROOT]/foo/target-dir/debug/foo.d\n\n\"#]]);\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking clean\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    assert_not_exists(&p.root().join(\"build-dir\"));\n    assert_not_exists(&p.root().join(\"target-dir\"));\n}\n\n#[cargo_test]\nfn cargo_clean_should_remove_correct_files() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                exclude = [\"*.txt\"]\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\"); }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/out/bar-[HASH].d\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/out/libbar-[HASH].rlib\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/out/libbar-[HASH].rmeta\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/fingerprint/dep-lib-bar\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/fingerprint/lib-bar\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/fingerprint/lib-bar.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/.lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking clean -p bar\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n}\n\n#[cargo_test]\nfn timings_report_should_output_to_target_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build --timings\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    assert_exists(&p.root().join(\"target-dir/cargo-timings/cargo-timing.html\"));\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"-Zfuture-incompat-test requires nightly (permanently)\"\n)]\nfn future_incompat_should_output_to_build_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { let x = 1; }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .arg(\"--future-incompat-report\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .run();\n\n    assert_exists(&p.root().join(\"build-dir/.future-incompat-report.json\"));\n}\n\n#[cargo_test]\nfn template_should_error_for_invalid_variables() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"{fake}/build-dir\"\n            target-dir = \"target-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected variable `fake` in build.build-dir path `{fake}/build-dir`\n\n[HELP] available template variables are `{workspace-root}`, `{cargo-cache-home}`, `{workspace-path-hash}`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn template_should_suggest_nearest_variable() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"{workspace-ro}/build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected variable `workspace-ro` in build.build-dir path `{workspace-ro}/build-dir`\n\n[HELP] a template variable with a similar name exists: `workspace-root`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn template_workspace_root() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"{workspace-root}/build-dir\"\n            target-dir = \"target-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    // Verify the binary was uplifted to the target-dir\n    assert_exists(&p.root().join(&format!(\"target-dir/debug/foo{EXE_SUFFIX}\")));\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n[ROOT]/foo/target-dir/debug/foo.d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn template_cargo_cache_home() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"{cargo-cache-home}/build-dir\"\n            target-dir = \"target-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    // Verify the binary was uplifted to the target-dir\n    assert_exists(&p.root().join(&format!(\"target-dir/debug/foo{EXE_SUFFIX}\")));\n    paths::cargo_home()\n        .join(\"build-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/home/.cargo/build-dir/.rustc_info.json\n[ROOT]/home/.cargo/build-dir/CACHEDIR.TAG\n[ROOT]/home/.cargo/build-dir/debug/.cargo-build-lock\n[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/home/.cargo/build-dir/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n[ROOT]/foo/target-dir/debug/foo.d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn template_workspace_path_hash() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            authors = []\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"foo/{workspace-path-hash}/build-dir\"\n            target-dir = \"target-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    let foo_dir = p.root().join(\"foo\");\n    assert_exists(&foo_dir);\n    let hash_dir = parse_workspace_manifest_path_hash(&foo_dir);\n\n    let build_dir = hash_dir.as_path().join(\"build-dir\");\n\n    // Verify the binary was uplifted to the target-dir\n    assert_exists(&p.root().join(&format!(\"target-dir/debug/foo{EXE_SUFFIX}\")));\n    build_dir.assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json\n[ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n[ROOT]/foo/target-dir/debug/foo.d\n\n\"#]]);\n}\n\n/// Verify that the {workspace-path-hash} does not changes if cargo is run from inside of\n/// a symlinked directory.\n/// The test approach is to build a project twice from the non-symlinked directory and a symlinked\n/// directory and then compare the build-dir paths.\n#[cargo_test]\nfn template_workspace_path_hash_should_handle_symlink() {\n    #[cfg(unix)]\n    use std::os::unix::fs::symlink;\n    #[cfg(windows)]\n    use std::os::windows::fs::symlink_dir as symlink;\n\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n             [package]\n             name = \"foo\"\n             version = \"1.0.0\"\n             authors = []\n             edition = \"2015\"\n             \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n             [build]\n             build-dir = \"foo/{workspace-path-hash}/build-dir\"\n             \"#,\n        )\n        .build();\n\n    // Build from the non-symlinked directory\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking check\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .run();\n\n    // Parse and verify the hash dir created from the non-symlinked dir\n    let foo_dir = p.root().join(\"foo\");\n    assert_exists(&foo_dir);\n    let original_hash_dir = parse_workspace_manifest_path_hash(&foo_dir);\n\n    original_hash_dir.assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json\n[ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/dep-lib-foo\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/lib-foo\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/lib-foo.json\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/out/foo-[HASH].d\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/out/libfoo-[HASH].rmeta\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n\n    p.root().join(\"target\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target/CACHEDIR.TAG\n\n\"#]]);\n\n    // Create a symlink of the project root.\n    let mut symlinked_dir = p.root().clone();\n    symlinked_dir.pop();\n    symlinked_dir = symlinked_dir.join(\"symlink-dir\");\n    symlink(p.root(), &symlinked_dir).unwrap();\n\n    // Remove the foo dir (which contains the build-dir) before we rebuild from a symlinked dir.\n    foo_dir.rm_rf();\n\n    // Run cargo from the symlinked dir\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking check\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .enable_mac_dsym()\n        .cwd(&symlinked_dir)\n        .run();\n\n    // Parse and verify the hash created from the symlinked dir\n    assert_exists(&foo_dir);\n    let symlink_hash_dir = parse_workspace_manifest_path_hash(&foo_dir);\n\n    symlink_hash_dir.assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json\n[ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/dep-lib-foo\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/lib-foo\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/fingerprint/lib-foo.json\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/out/foo-[HASH].d\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/out/libfoo-[HASH].rmeta\n[ROOT]/foo/foo/[HASH]/build-dir/debug/build/foo/[HASH]/.lock\n\n\"#]]);\n\n    p.root().join(\"target\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target/CACHEDIR.TAG\n\n\"#]]);\n\n    // Verify the hash dir created from the symlinked and non-symlinked dirs are the same.\n    assert_eq!(original_hash_dir, symlink_hash_dir);\n}\n\n#[cargo_test]\nfn template_should_handle_reject_unmatched_brackets() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"foo/{bar\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout -Zfine-grain-locking build\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected opening bracket `{` in build.build-dir path `foo/{bar`\n\n\"#]])\n        .run();\n\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"foo/}bar\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected closing bracket `}` in build.build-dir path `foo/}bar`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn artifact_deps() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = [\"bin:bar\"] }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                 println!(\"CARGO_BIN_DIR_BAR={}\", env!(\"CARGO_BIN_DIR_BAR\"));\n                 println!(\"CARGO_BIN_FILE_BAR_bar={}\", env!(\"CARGO_BIN_FILE_BAR_bar\"));\n            }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"bar\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"run -Zbuild-dir-new-layout -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\", \"build-dir-new-layout\"])\n        .enable_mac_dsym()\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target-dir/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nCARGO_BIN_DIR_BAR=[ROOT]/foo/build-dir/debug/build/bar/[HASH]/artifact/bin\nCARGO_BIN_FILE_BAR_bar=[ROOT]/foo/build-dir/debug/build/bar/[HASH]/artifact/bin/bar[..][EXE]\n\n\"#]])\n        .run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/fingerprint/bin-bar\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/fingerprint/bin-bar.json\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/fingerprint/dep-bin-bar\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/bin-foo.json\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/fingerprint/dep-bin-foo\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/artifact/bin/bar[..][EXE]\n[ROOT]/foo/build-dir/debug/build/bar/[HASH]/artifact/bin/bar[..].d\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo/[HASH]/out/foo[..].d\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n[ROOT]/foo/target-dir/debug/foo.d\n\n\"#]]);\n}\n\nfn parse_workspace_manifest_path_hash(hash_dir: &PathBuf) -> PathBuf {\n    // Since the hash will change between test runs simply find the first directories and assume\n    // that is the hash dir. The format is a 2 char directory followed by the remaining hash in the\n    // inner directory (ie. `34/f9d02eb8411c05`)\n    let mut dirs = std::fs::read_dir(hash_dir).unwrap().into_iter();\n    let outer_hash_dir = dirs.next().unwrap().unwrap();\n    // Validate there are no other directories in `hash_dir`\n    assert!(\n        dirs.next().is_none(),\n        \"Found multiple dir entries in {hash_dir:?}\"\n    );\n    // Validate the outer hash dir hash is a directory and has the correct hash length\n    assert!(\n        outer_hash_dir.path().is_dir(),\n        \"{outer_hash_dir:?} was not a directory\"\n    );\n    assert_eq!(\n        outer_hash_dir.path().file_name().unwrap().len(),\n        2,\n        \"Path {:?} should have been 2 chars\",\n        outer_hash_dir.path().file_name()\n    );\n\n    let mut dirs = std::fs::read_dir(outer_hash_dir.path())\n        .unwrap()\n        .into_iter();\n    let inner_hash_dir = dirs.next().unwrap().unwrap();\n    // Validate there are no other directories in first hash dir\n    assert!(\n        dirs.next().is_none(),\n        \"Found multiple dir entries in {outer_hash_dir:?}\"\n    );\n    // Validate the outer hash dir hash is a directory and has the correct hash length\n    assert!(\n        inner_hash_dir.path().is_dir(),\n        \"{inner_hash_dir:?} was not a directory\"\n    );\n    assert_eq!(\n        inner_hash_dir.path().file_name().unwrap().len(),\n        14,\n        \"Path {:?} should have been 2 chars\",\n        inner_hash_dir.path().file_name()\n    );\n    return inner_hash_dir.path();\n}\n\n#[track_caller]\nfn assert_exists(path: &PathBuf) {\n    assert!(\n        path.exists(),\n        \"Expected `{}` to exist but was not found.\",\n        path.display()\n    );\n}\n\n#[track_caller]\nfn assert_not_exists(path: &PathBuf) {\n    assert!(\n        !path.exists(),\n        \"Expected `{}` to NOT exist but was found.\",\n        path.display()\n    );\n}\n\n#[track_caller]\nfn assert_exists_patterns_with_base_dir(base: &PathBuf, patterns: &[&str]) {\n    let root = base.to_str().unwrap();\n    let p: Vec<_> = patterns.iter().map(|p| format!(\"{root}/{p}\")).collect();\n    let p: Vec<&str> = p.iter().map(|v| v.as_str()).collect();\n    assert_exists_patterns(&p);\n}\n\n#[track_caller]\nfn assert_exists_patterns(patterns: &[&str]) {\n    for p in patterns {\n        assert_exists_pattern(p);\n    }\n}\n\n#[track_caller]\nfn assert_exists_pattern(pattern: &str) {\n    use glob::glob;\n\n    let mut z = glob(pattern).unwrap();\n\n    assert!(\n        z.next().is_some(),\n        \"Expected `{pattern}` to match existing file but was not found.\",\n    )\n}\n"
  },
  {
    "path": "tests/testsuite/build_dir_legacy.rs",
    "content": "//! Tests for `build.build-dir` config property.\n//!\n//! The testing strategy for build-dir functionality is primarily checking if directories / files\n//! are in the expected locations.\n//! The rational is that other tests will verify each individual feature, while the tests in this\n//! file verify the files saved to disk are in the correct locations according to the `build-dir`\n//! configuration.\n//!\n//! Tests check if directories match some \"layout\" by using [`CargoPathExt::assert_file_layout`]\n\nuse std::path::PathBuf;\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::{Package, RegistryBuilder};\nuse cargo_test_support::{paths, prelude::*, project, str};\nuse std::env::consts::{DLL_PREFIX, DLL_SUFFIX, EXE_SUFFIX};\n\n#[cargo_test]\nfn binary_with_debug() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").enable_mac_dsym().run();\n\n    assert_not_exists(&p.root().join(\"target\"));\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/deps/foo[..].d\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n[ROOT]/foo/target-dir/debug/foo.d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn binary_with_release() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --release\").enable_mac_dsym().run();\n\n    assert_exists_patterns_with_base_dir(\n        &p.root(),\n        &[\n            // Check the pre-uplifted binary in the build-dir\n            &format!(\"build-dir/release/deps/foo*{EXE_SUFFIX}\"),\n            \"build-dir/release/deps/foo*.d\",\n            // Verify the binary was copied to the target-dir\n            &format!(\"target-dir/release/foo{EXE_SUFFIX}\"),\n            \"target-dir/release/foo.d\",\n        ],\n    );\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/release/.cargo-build-lock\n[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/release/deps/foo[..][EXE]\n[ROOT]/foo/build-dir/release/deps/foo[..].d\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/release/.cargo-lock\n[ROOT]/foo/target-dir/release/foo[EXE]\n[ROOT]/foo/target-dir/release/foo.d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn libs() {\n    // https://doc.rust-lang.org/reference/linkage.html#r-link.staticlib\n    let (staticlib_prefix, staticlib_suffix) =\n        if cfg!(target_os = \"windows\") && cfg!(target_env = \"msvc\") {\n            (\"\", \".lib\")\n        } else {\n            (\"lib\", \".a\")\n        };\n\n    // (crate-type, list of final artifacts)\n    let lib_types = [\n        (\"lib\", [\"libfoo.rlib\", \"libfoo.d\"]),\n        (\n            \"dylib\",\n            [\n                &format!(\"{DLL_PREFIX}foo{DLL_SUFFIX}\"),\n                &format!(\"{DLL_PREFIX}foo.d\"),\n            ],\n        ),\n        (\n            \"cdylib\",\n            [\n                &format!(\"{DLL_PREFIX}foo{DLL_SUFFIX}\"),\n                &format!(\"{DLL_PREFIX}foo.d\"),\n            ],\n        ),\n        (\n            \"staticlib\",\n            [\n                &format!(\"{staticlib_prefix}foo{staticlib_suffix}\"),\n                &format!(\"{staticlib_prefix}foo.d\"),\n            ],\n        ),\n    ];\n\n    for (lib_type, expected_files) in lib_types {\n        let p = project()\n            .file(\"src/lib.rs\", r#\"fn foo() { println!(\"Hello, World!\") }\"#)\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            authors = []\n            edition = \"2015\"\n\n            [lib]\n            crate-type = [\"{lib_type}\"]\n            \"#\n                ),\n            )\n            .file(\n                \".cargo/config.toml\",\n                r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n            )\n            .build();\n\n        p.cargo(\"build\").enable_mac_dsym().run();\n\n        // Verify lib artifacts were copied into the artifact dir\n        assert_exists_patterns_with_base_dir(&p.root().join(\"target-dir/debug\"), &expected_files);\n    }\n}\n\n#[cargo_test]\nfn should_default_to_target() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .build();\n\n    p.cargo(\"build\").enable_mac_dsym().run();\n\n    p.root().join(\"target\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target/.rustc_info.json\n[ROOT]/foo/target/CACHEDIR.TAG\n[ROOT]/foo/target/debug/.cargo-lock\n[ROOT]/foo/target/debug/.cargo-build-lock\n[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/target/debug/deps/foo[..][EXE]\n[ROOT]/foo/target/debug/deps/foo[..].d\n[ROOT]/foo/target/debug/foo[EXE]\n[ROOT]/foo/target/debug/foo.d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn should_respect_env_var() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .build();\n\n    p.cargo(\"build\")\n        .env(\"CARGO_BUILD_BUILD_DIR\", \"build-dir\")\n        .enable_mac_dsym()\n        .run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/deps/foo[..].d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn build_script_should_output_to_build_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                std::fs::write(\n                    format!(\"{}/foo.txt\", std::env::var(\"OUT_DIR\").unwrap()),\n                    \"Hello, world!\",\n                )\n                .unwrap();\n            }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").enable_mac_dsym().run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/deps/foo[..].d\n[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/run-build-script-build-script-build\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/run-build-script-build-script-build.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-build-script-build-script-build\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/build-script-build-script-build\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/build-script-build-script-build.json\n[ROOT]/foo/build-dir/debug/build/foo-[HASH]/build_script_build[..].d\n[ROOT]/foo/build-dir/debug/build/foo-[HASH]/build_script_build[..][EXE]\n[ROOT]/foo/build-dir/debug/build/foo-[HASH]/build-script-build[EXE]\n[ROOT]/foo/build-dir/debug/build/foo-[HASH]/out/foo.txt\n[ROOT]/foo/build-dir/debug/build/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/build/foo-[HASH]/output\n[ROOT]/foo/build-dir/debug/build/foo-[HASH]/stderr\n[ROOT]/foo/build-dir/debug/build/foo-[HASH]/root-output\n\n\"#]]);\n}\n\n#[cargo_test]\nfn cargo_tmpdir_should_output_to_build_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \"tests/foo.rs\",\n            r#\"\n            #[test]\n            fn test() {\n                std::fs::write(\n                    format!(\"{}/foo.txt\", env!(\"CARGO_TARGET_TMPDIR\")),\n                    \"Hello, world!\",\n                )\n                .unwrap();\n            }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test\").enable_mac_dsym().run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/deps/foo-[HASH].d\n[ROOT]/foo/build-dir/debug/deps/foo-[HASH].d\n[ROOT]/foo/build-dir/debug/deps/foo[..].d\n[ROOT]/foo/build-dir/debug/deps/foo-[HASH][EXE]\n[ROOT]/foo/build-dir/debug/deps/foo-[HASH][EXE]\n[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-test-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bin-foo.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-test-integration-test-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-integration-test-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-integration-test-foo.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/build-dir/tmp/foo.txt\n[ROOT]/foo/build-dir/.rustc_info.json\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n\n\"#]]);\n}\n\n#[cargo_test]\nfn examples_should_output_to_build_dir_and_uplift_to_target_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\"examples/foo.rs\", r#\"fn main() { }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --examples\").enable_mac_dsym().run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-example-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/example-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/example-foo.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/examples/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/examples/foo[..].d\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/examples/foo[EXE]\n[ROOT]/foo/target-dir/debug/examples/foo.d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn benches_should_output_to_build_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\"benches/foo.rs\", r#\"fn main() { }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --bench=foo\").enable_mac_dsym().run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/deps/foo-[HASH].d\n[ROOT]/foo/build-dir/debug/deps/foo[..].d\n[ROOT]/foo/build-dir/debug/deps/foo-[HASH][EXE]\n[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-test-bench-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bench-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bench-foo.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/build-dir/.rustc_info.json\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n\n\"#]]);\n}\n\n#[cargo_test]\nfn cargo_doc_should_output_to_target_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"doc\").enable_mac_dsym().run();\n\n    let docs_dir = p.root().join(\"target-dir/doc\");\n\n    assert_exists(&docs_dir);\n    assert_exists(&docs_dir.join(\"foo/index.html\"));\n}\n\n#[cargo_test]\nfn cargo_package_should_build_in_build_dir_and_output_to_target_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"package\").enable_mac_dsym().run();\n\n    let package_artifact_dir = p.root().join(\"target-dir/package\");\n    assert_exists(&package_artifact_dir);\n    assert_exists(&package_artifact_dir.join(\"foo-0.0.1.crate\"));\n    assert!(package_artifact_dir.join(\"foo-0.0.1.crate\").is_file());\n    // FIXME: The `.cargo-lock` file should be in target-dir not build-dir. See #16707\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/debug/.cargo-lock\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/deps/foo[..].d\n[ROOT]/foo/build-dir/debug/foo[EXE]\n[ROOT]/foo/build-dir/debug/foo.d\n[ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.lock\n[ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.toml\n[ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.toml.orig\n[ROOT]/foo/build-dir/package/foo-0.0.1/src/main.rs\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/package/tmp-crate/foo-0.0.1.crate\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/package/foo-0.0.1.crate\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n\n\"#]]);\n}\n\n#[cargo_test]\nfn cargo_publish_should_only_touch_build_dir() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .enable_mac_dsym()\n        .run();\n\n    let package_artifact_dir = p.root().join(\"target-dir/package\");\n    assert!(!package_artifact_dir.exists());\n\n    let package_build_dir = p.root().join(\"build-dir/package\");\n    assert_exists(&package_build_dir);\n    assert_exists(&package_build_dir.join(\"foo-0.0.1\"));\n    assert!(package_build_dir.join(\"foo-0.0.1\").is_dir());\n}\n\n#[cargo_test]\nfn cargo_clean_should_clean_the_target_dir_and_build_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").enable_mac_dsym().run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/deps/foo[..].d\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n[ROOT]/foo/target-dir/debug/foo.d\n\n\"#]]);\n\n    p.cargo(\"clean\").enable_mac_dsym().run();\n\n    assert_not_exists(&p.root().join(\"build-dir\"));\n    assert_not_exists(&p.root().join(\"target-dir\"));\n}\n\n#[cargo_test]\nfn cargo_clean_should_remove_correct_files() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                exclude = [\"*.txt\"]\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\"); }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").enable_mac_dsym().run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/deps/foo[..].d\n[ROOT]/foo/build-dir/debug/.fingerprint/bar-[HASH]/lib-bar\n[ROOT]/foo/build-dir/debug/.fingerprint/bar-[HASH]/lib-bar.json\n[ROOT]/foo/build-dir/debug/.fingerprint/bar-[HASH]/dep-lib-bar\n[ROOT]/foo/build-dir/debug/.fingerprint/bar-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/deps/bar[..].d\n[ROOT]/foo/build-dir/debug/deps/libbar[..].rlib\n[ROOT]/foo/build-dir/debug/deps/libbar[..].rmeta\n\n\"#]]);\n\n    p.cargo(\"clean -p bar\").enable_mac_dsym().run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/deps/foo[..].d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn timings_report_should_output_to_target_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --timings\").enable_mac_dsym().run();\n\n    assert_exists(&p.root().join(\"target-dir/cargo-timings/cargo-timing.html\"));\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"-Zfuture-incompat-test requires nightly (permanently)\"\n)]\nfn future_incompat_should_output_to_build_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { let x = 1; }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .arg(\"--future-incompat-report\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .run();\n\n    assert_exists(&p.root().join(\"build-dir/.future-incompat-report.json\"));\n}\n\n#[cargo_test]\nfn template_should_error_for_invalid_variables() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"{fake}/build-dir\"\n            target-dir = \"target-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .enable_mac_dsym()\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected variable `fake` in build.build-dir path `{fake}/build-dir`\n\n[HELP] available template variables are `{workspace-root}`, `{cargo-cache-home}`, `{workspace-path-hash}`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn template_should_suggest_nearest_variable() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"{workspace-ro}/build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected variable `workspace-ro` in build.build-dir path `{workspace-ro}/build-dir`\n\n[HELP] a template variable with a similar name exists: `workspace-root`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn template_workspace_root() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"{workspace-root}/build-dir\"\n            target-dir = \"target-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").enable_mac_dsym().run();\n\n    // Verify the binary was uplifted to the target-dir\n    assert_exists(&p.root().join(&format!(\"target-dir/debug/foo{EXE_SUFFIX}\")));\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/deps/foo[..].d\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n[ROOT]/foo/target-dir/debug/foo.d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn template_cargo_cache_home() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"{cargo-cache-home}/build-dir\"\n            target-dir = \"target-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").enable_mac_dsym().run();\n\n    // Verify the binary was uplifted to the target-dir\n    assert_exists(&p.root().join(&format!(\"target-dir/debug/foo{EXE_SUFFIX}\")));\n    paths::cargo_home()\n        .join(\"build-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/home/.cargo/build-dir/.rustc_info.json\n[ROOT]/home/.cargo/build-dir/CACHEDIR.TAG\n[ROOT]/home/.cargo/build-dir/debug/.cargo-build-lock\n[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/home/.cargo/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/home/.cargo/build-dir/debug/deps/foo[..].d\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n[ROOT]/foo/target-dir/debug/foo.d\n\n\"#]]);\n}\n\n#[cargo_test]\nfn template_workspace_path_hash() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            authors = []\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"foo/{workspace-path-hash}/build-dir\"\n            target-dir = \"target-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").enable_mac_dsym().run();\n\n    let foo_dir = p.root().join(\"foo\");\n    assert_exists(&foo_dir);\n    let hash_dir = parse_workspace_manifest_path_hash(&foo_dir);\n\n    let build_dir = hash_dir.as_path().join(\"build-dir\");\n\n    // Verify the binary was uplifted to the target-dir\n    assert_exists(&p.root().join(&format!(\"target-dir/debug/foo{EXE_SUFFIX}\")));\n    build_dir.assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json\n[ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo[..].d\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n[ROOT]/foo/target-dir/debug/foo.d\n\n\"#]]);\n}\n\n/// Verify that the {workspace-path-hash} does not changes if cargo is run from inside of\n/// a symlinked directory.\n/// The test approach is to build a project twice from the non-symlinked directory and a symlinked\n/// directory and then compare the build-dir paths.\n#[cargo_test]\nfn template_workspace_path_hash_should_handle_symlink() {\n    #[cfg(unix)]\n    use std::os::unix::fs::symlink;\n    #[cfg(windows)]\n    use std::os::windows::fs::symlink_dir as symlink;\n\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n             [package]\n             name = \"foo\"\n             version = \"1.0.0\"\n             authors = []\n             edition = \"2015\"\n             \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n             [build]\n             build-dir = \"foo/{workspace-path-hash}/build-dir\"\n             \"#,\n        )\n        .build();\n\n    // Build from the non-symlinked directory\n    p.cargo(\"check\").enable_mac_dsym().run();\n\n    // Parse and verify the hash dir created from the non-symlinked dir\n    let foo_dir = p.root().join(\"foo\");\n    assert_exists(&foo_dir);\n    let original_hash_dir = parse_workspace_manifest_path_hash(&foo_dir);\n\n    original_hash_dir.assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json\n[ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/dep-lib-foo\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo.json\n[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo-[HASH].d\n[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/libfoo-[HASH].rmeta\n\n\"#]]);\n\n    p.root().join(\"target\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target/CACHEDIR.TAG\n\n\"#]]);\n\n    // Create a symlink of the project root.\n    let mut symlinked_dir = p.root().clone();\n    symlinked_dir.pop();\n    symlinked_dir = symlinked_dir.join(\"symlink-dir\");\n    symlink(p.root(), &symlinked_dir).unwrap();\n\n    // Remove the foo dir (which contains the build-dir) before we rebuild from a symlinked dir.\n    foo_dir.rm_rf();\n\n    // Run cargo from the symlinked dir\n    p.cargo(\"check\").cwd(&symlinked_dir).enable_mac_dsym().run();\n\n    // Parse and verify the hash created from the symlinked dir\n    assert_exists(&foo_dir);\n    let symlink_hash_dir = parse_workspace_manifest_path_hash(&foo_dir);\n\n    symlink_hash_dir.assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json\n[ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/dep-lib-foo\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo\n[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo.json\n[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo-[HASH].d\n[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/libfoo-[HASH].rmeta\n\n\"#]]);\n\n    p.root().join(\"target\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target/CACHEDIR.TAG\n\n\"#]]);\n\n    // Verify the hash dir created from the symlinked and non-symlinked dirs are the same.\n    assert_eq!(original_hash_dir, symlink_hash_dir);\n}\n\n#[cargo_test]\nfn template_should_handle_reject_unmatched_brackets() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"foo/{bar\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected opening bracket `{` in build.build-dir path `foo/{bar`\n\n\"#]])\n        .run();\n\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"foo/}bar\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected closing bracket `}` in build.build-dir path `foo/}bar`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn artifact_deps() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                resolver = \"2\"\n\n                [dependencies]\n                bar = { path = \"bar/\", artifact = [\"bin:bar\"] }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                 println!(\"CARGO_BIN_DIR_BAR={}\", env!(\"CARGO_BIN_DIR_BAR\"));\n                 println!(\"CARGO_BIN_FILE_BAR_bar={}\", env!(\"CARGO_BIN_FILE_BAR_bar\"));\n            }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"bar\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"run -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .enable_mac_dsym()\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target-dir/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nCARGO_BIN_DIR_BAR=[ROOT]/foo/build-dir/debug/deps/artifact/bar-[HASH]/bin\nCARGO_BIN_FILE_BAR_bar=[ROOT]/foo/build-dir/debug/deps/artifact/bar-[HASH]/bin/bar[..][EXE]\n\n\"#]])\n        .run();\n\n    p.root().join(\"build-dir\").assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/build-dir/.rustc_info.json\n[ROOT]/foo/build-dir/CACHEDIR.TAG\n[ROOT]/foo/build-dir/debug/.cargo-build-lock\n[ROOT]/foo/build-dir/debug/.fingerprint/bar-[HASH]/bin-bar\n[ROOT]/foo/build-dir/debug/.fingerprint/bar-[HASH]/bin-bar.json\n[ROOT]/foo/build-dir/debug/.fingerprint/bar-[HASH]/dep-bin-bar\n[ROOT]/foo/build-dir/debug/.fingerprint/bar-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo\n[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp\n[ROOT]/foo/build-dir/debug/deps/artifact/bar-[HASH]/bin/bar[..][EXE]\n[ROOT]/foo/build-dir/debug/deps/artifact/bar-[HASH]/bin/bar[..].d\n[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]\n[ROOT]/foo/build-dir/debug/deps/foo[..].d\n\n\"#]]);\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n[ROOT]/foo/target-dir/debug/.cargo-lock\n[ROOT]/foo/target-dir/debug/foo[EXE]\n[ROOT]/foo/target-dir/debug/foo.d\n\n\"#]]);\n}\n\nfn parse_workspace_manifest_path_hash(hash_dir: &PathBuf) -> PathBuf {\n    // Since the hash will change between test runs simply find the first directories and assume\n    // that is the hash dir. The format is a 2 char directory followed by the remaining hash in the\n    // inner directory (ie. `34/f9d02eb8411c05`)\n    let mut dirs = std::fs::read_dir(hash_dir).unwrap().into_iter();\n    let outer_hash_dir = dirs.next().unwrap().unwrap();\n    // Validate there are no other directories in `hash_dir`\n    assert!(\n        dirs.next().is_none(),\n        \"Found multiple dir entries in {hash_dir:?}\"\n    );\n    // Validate the outer hash dir hash is a directory and has the correct hash length\n    assert!(\n        outer_hash_dir.path().is_dir(),\n        \"{outer_hash_dir:?} was not a directory\"\n    );\n    assert_eq!(\n        outer_hash_dir.path().file_name().unwrap().len(),\n        2,\n        \"Path {:?} should have been 2 chars\",\n        outer_hash_dir.path().file_name()\n    );\n\n    let mut dirs = std::fs::read_dir(outer_hash_dir.path())\n        .unwrap()\n        .into_iter();\n    let inner_hash_dir = dirs.next().unwrap().unwrap();\n    // Validate there are no other directories in first hash dir\n    assert!(\n        dirs.next().is_none(),\n        \"Found multiple dir entries in {outer_hash_dir:?}\"\n    );\n    // Validate the outer hash dir hash is a directory and has the correct hash length\n    assert!(\n        inner_hash_dir.path().is_dir(),\n        \"{inner_hash_dir:?} was not a directory\"\n    );\n    assert_eq!(\n        inner_hash_dir.path().file_name().unwrap().len(),\n        14,\n        \"Path {:?} should have been 2 chars\",\n        inner_hash_dir.path().file_name()\n    );\n    return inner_hash_dir.path();\n}\n\n#[track_caller]\nfn assert_exists(path: &PathBuf) {\n    assert!(\n        path.exists(),\n        \"Expected `{}` to exist but was not found.\",\n        path.display()\n    );\n}\n\n#[track_caller]\nfn assert_not_exists(path: &PathBuf) {\n    assert!(\n        !path.exists(),\n        \"Expected `{}` to NOT exist but was found.\",\n        path.display()\n    );\n}\n\n#[track_caller]\nfn assert_exists_patterns_with_base_dir(base: &PathBuf, patterns: &[&str]) {\n    let root = base.to_str().unwrap();\n    let p: Vec<_> = patterns.iter().map(|p| format!(\"{root}/{p}\")).collect();\n    let p: Vec<&str> = p.iter().map(|v| v.as_str()).collect();\n    assert_exists_patterns(&p);\n}\n\n#[track_caller]\nfn assert_exists_patterns(patterns: &[&str]) {\n    for p in patterns {\n        assert_exists_pattern(p);\n    }\n}\n\n#[track_caller]\nfn assert_exists_pattern(pattern: &str) {\n    use glob::glob;\n\n    let mut z = glob(pattern).unwrap();\n\n    assert!(\n        z.next().is_some(),\n        \"Expected `{pattern}` to match existing file but was not found.\",\n    )\n}\n"
  },
  {
    "path": "tests/testsuite/build_script.rs",
    "content": "//! Tests for build.rs scripts.\n\nuse std::env;\nuse std::fs;\nuse std::io;\nuse std::thread;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_exe;\nuse crate::utils::cross_compile::{\n    can_run_on_host as cross_compile_can_run_on_host, disabled as cross_compile_disabled,\n};\nuse crate::utils::tools;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::paths::cargo_home;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_manifest, cross_compile, is_coarse_mtime, project, project_in};\nuse cargo_test_support::{git, rustc_host, sleep_ms, slow_cpu_multiplier, symlink_supported};\nuse cargo_util::paths::{self, remove_dir_all};\n\n#[cargo_test]\nfn custom_build_script_failed() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build.rs\", \"fn main() { std::process::exit(101); }\")\n        .build();\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[ERROR] failed to run custom build command for `foo v0.5.0 ([ROOT]/foo)`\n\nCaused by:\n  process didn't exit successfully: `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` ([EXIT_STATUS]: 101)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_script_failed_backtraces_message() {\n    // In this situation (no dependency sharing), debuginfo is turned off in\n    // `dev.build-override`. However, if an error occurs running e.g. a build\n    // script, and backtraces are opted into: a message explaining how to\n    // improve backtraces is also displayed.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build.rs\", \"fn main() { std::process::exit(101); }\")\n        .build();\n    p.cargo(\"check -v\")\n        .env(\"RUST_BACKTRACE\", \"1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[ERROR] failed to run custom build command for `foo v0.5.0 ([ROOT]/foo)`\n[NOTE] To improve backtraces for build dependencies, set the CARGO_PROFILE_DEV_BUILD_OVERRIDE_DEBUG=true environment variable to enable debug information generation.\n\nCaused by:\n  process didn't exit successfully: `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` ([EXIT_STATUS]: 101)\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -v\")\n        .env(\"RUST_BACKTRACE\", \"1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[ERROR] failed to run custom build command for `foo v0.5.0 ([ROOT]/foo)`\n[NOTE] To improve backtraces for build dependencies, set the CARGO_PROFILE_DEV_BUILD_OVERRIDE_DEBUG=true environment variable to enable debug information generation.\n\nCaused by:\n  process didn't exit successfully: `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` ([EXIT_STATUS]: 101)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_script_failed_backtraces_message_with_debuginfo() {\n    // This is the same test as `custom_build_script_failed_backtraces_message` above, this time\n    // ensuring that the message dedicated to improving backtraces by requesting debuginfo is not\n    // shown when debuginfo is already turned on.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build.rs\", \"fn main() { std::process::exit(101); }\")\n        .build();\n    p.cargo(\"check -v\")\n        .env(\"RUST_BACKTRACE\", \"1\")\n        .env(\"CARGO_PROFILE_DEV_BUILD_OVERRIDE_DEBUG\", \"true\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[ERROR] failed to run custom build command for `foo v0.5.0 ([ROOT]/foo)`\n\nCaused by:\n  process didn't exit successfully: `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` ([EXIT_STATUS]: 101)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_env_vars() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [features]\n                bar_feat = [\"bar/foo\", \"bar/other-feature\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n                build = \"build.rs\"\n\n                [features]\n                foo = []\n                other-feature = []\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"pub fn hello() {}\");\n\n    let cargo = cargo_exe();\n    let cargo = cargo.to_str().unwrap();\n    let rustc = paths::resolve_executable(\"rustc\".as_ref()).unwrap();\n    let rustc = rustc.to_str().unwrap();\n    let file_content = format!(\n        r##\"\n            use std::env;\n            use std::path::Path;\n\n            fn main() {{\n                let _target = env::var(\"TARGET\").unwrap();\n                let _ncpus = env::var(\"NUM_JOBS\").unwrap();\n                let _dir = env::var(\"CARGO_MANIFEST_DIR\").unwrap();\n\n                let opt = env::var(\"OPT_LEVEL\").unwrap();\n                assert_eq!(opt, \"0\");\n\n                let opt = env::var(\"PROFILE\").unwrap();\n                assert_eq!(opt, \"debug\");\n\n                let debug = env::var(\"DEBUG\").unwrap();\n                assert_eq!(debug, \"true\");\n\n                let out = env::var(\"OUT_DIR\").unwrap();\n                assert!(out.starts_with(r\"{0}\"));\n                assert!(Path::new(&out).is_dir());\n\n                let _host = env::var(\"HOST\").unwrap();\n\n                let _feat = env::var(\"CARGO_FEATURE_FOO\").unwrap();\n                let feat = env::var(\"CARGO_CFG_FEATURE\").unwrap();\n                assert_eq!(feat, \"foo,other-feature\");\n\n                let cargo = env::var(\"CARGO\").unwrap();\n                if env::var_os(\"CHECK_CARGO_IS_RUSTC\").is_some() {{\n                    assert_eq!(cargo, r#\"{rustc}\"#);\n                }} else {{\n                    assert_eq!(cargo, r#\"{cargo}\"#);\n                }}\n\n                let rustc = env::var(\"RUSTC\").unwrap();\n                assert_eq!(rustc, \"rustc\");\n\n                let rustdoc = env::var(\"RUSTDOC\").unwrap();\n                assert_eq!(rustdoc, \"rustdoc\");\n\n                assert!(env::var(\"RUSTC_WRAPPER\").is_err());\n                assert!(env::var(\"RUSTC_WORKSPACE_WRAPPER\").is_err());\n\n                assert!(env::var(\"RUSTC_LINKER\").is_err());\n\n                assert!(env::var(\"RUSTFLAGS\").is_err());\n                let rustflags = env::var(\"CARGO_ENCODED_RUSTFLAGS\").unwrap();\n                assert_eq!(rustflags, \"\");\n            }}\n        \"##,\n        p.root()\n            .join(\"target\")\n            .join(\"debug\")\n            .join(\"build\")\n            .display(),\n    );\n\n    let p = p.file(\"bar/build.rs\", &file_content).build();\n\n    p.cargo(\"check --features bar_feat\").run();\n    p.cargo(\"check --features bar_feat\")\n        // we use rustc since $CARGO is only used if it points to a path that exists\n        .env(\"CHECK_CARGO_IS_RUSTC\", \"1\")\n        .env(cargo::CARGO_ENV, rustc)\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_env_var_rustflags() {\n    let rustflags = \"--cfg=special\";\n    let rustflags_alt = \"--cfg=notspecial\";\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [build]\n                rustflags = [\"{}\"]\n                \"#,\n                rustflags\n            ),\n        )\n        .file(\n            \"build.rs\",\n            &format!(\n                r#\"\n                use std::env;\n\n                fn main() {{\n                    // Static assertion that exactly one of the cfg paths is always taken.\n                    assert!(env::var(\"RUSTFLAGS\").is_err());\n                    let x;\n                    #[cfg(special)]\n                    {{ assert_eq!(env::var(\"CARGO_ENCODED_RUSTFLAGS\").unwrap(), \"{}\"); x = String::new(); }}\n                    #[cfg(notspecial)]\n                    {{ assert_eq!(env::var(\"CARGO_ENCODED_RUSTFLAGS\").unwrap(), \"{}\"); x = String::new(); }}\n                    let _ = x;\n                }}\n                \"#,\n                rustflags, rustflags_alt,\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    // RUSTFLAGS overrides build.rustflags, so --cfg=special shouldn't be passed\n    p.cargo(\"check\").env(\"RUSTFLAGS\", rustflags_alt).run();\n}\n\n#[cargo_test]\nfn custom_build_env_var_encoded_rustflags() {\n    // NOTE: We use \"-Clink-arg=-B nope\" here rather than, say, \"-A missing_docs\", since for the\n    // latter it won't matter if the whitespace accidentally gets split, as rustc will do the right\n    // thing either way.\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            rustflags = [\"-Clink-arg=-B nope\", \"--cfg=foo\"]\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n\n                fn main() {{\n                    assert_eq!(env::var(\"CARGO_ENCODED_RUSTFLAGS\").unwrap(), \"-Clink-arg=-B nope\\x1f--cfg=foo\");\n                }}\n                \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn custom_build_env_var_rustc_wrapper() {\n    let wrapper = tools::echo_wrapper();\n    let p = project()\n        .file(\n            \"build.rs\",\n            r#\"\n            use std::env;\n\n            fn main() {{\n                assert_eq!(\n                    env::var(\"RUSTC_WRAPPER\").unwrap(),\n                    env::var(\"CARGO_RUSTC_WRAPPER_CHECK\").unwrap()\n                );\n            }}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .env(\"CARGO_BUILD_RUSTC_WRAPPER\", &wrapper)\n        .env(\"CARGO_RUSTC_WRAPPER_CHECK\", &wrapper)\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_env_var_rustc_workspace_wrapper() {\n    let wrapper = tools::echo_wrapper();\n\n    // Workspace wrapper should be set for any crate we're operating directly on.\n    let p = project()\n        .file(\n            \"build.rs\",\n            r#\"\n            use std::env;\n\n            fn main() {{\n                assert_eq!(\n                    env::var(\"RUSTC_WORKSPACE_WRAPPER\").unwrap(),\n                    env::var(\"CARGO_RUSTC_WORKSPACE_WRAPPER_CHECK\").unwrap()\n                );\n            }}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .env(\"CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER\", &wrapper)\n        .env(\"CARGO_RUSTC_WORKSPACE_WRAPPER_CHECK\", &wrapper)\n        .run();\n\n    // But should not be set for a crate from the registry, as then it's not in a workspace.\n    Package::new(\"bar\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            links = \"a\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n            use std::env;\n\n            fn main() {{\n                assert!(env::var(\"RUSTC_WORKSPACE_WRAPPER\").is_err());\n            }}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .env(\"CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER\", &wrapper)\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_env_var_rustc_linker() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [target.{}]\n                linker = \"/path/to/linker\"\n                \"#,\n                target\n            ),\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n            use std::env;\n\n            fn main() {\n                assert!(env::var(\"RUSTC_LINKER\").unwrap().ends_with(\"/path/to/linker\"));\n            }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // no crate type set => linker never called => build succeeds if and\n    // only if build.rs succeeds, despite linker binary not existing.\n    p.cargo(\"build --target\").arg(&target).run();\n}\n\n// Only run this test on linux, since it's difficult to construct\n// a case suitable for all platforms.\n// See:https://github.com/rust-lang/cargo/pull/12535#discussion_r1306618264\n#[cargo_test]\n#[cfg(target_os = \"linux\")]\nfn custom_build_env_var_rustc_linker_with_target_cfg() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [target.'cfg(target_pointer_width = \"32\")']\n            linker = \"/path/to/linker\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n            use std::env;\n\n            fn main() {\n                assert!(env::var(\"RUSTC_LINKER\").unwrap().ends_with(\"/path/to/linker\"));\n            }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // no crate type set => linker never called => build succeeds if and\n    // only if build.rs succeeds, despite linker binary not existing.\n    p.cargo(\"build --target\").arg(&target).run();\n}\n\n#[cargo_test]\nfn custom_build_env_var_rustc_linker_bad_host_target() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [target.{}]\n                linker = \"/path/to/linker\"\n                \"#,\n                target\n            ),\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // build.rs should fail since host == target when no target is set\n    p.cargo(\"build --verbose\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]-C linker=[..]/path/to/linker [..]`\n[ERROR] linker `[..]/path/to/linker` not found\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_env_var_rustc_linker_host_target() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                target-applies-to-host = false\n                [target.{}]\n                linker = \"/path/to/linker\"\n                \"#,\n                target\n            ),\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n            use std::env;\n\n            fn main() {\n                assert!(env::var(\"RUSTC_LINKER\").unwrap().ends_with(\"/path/to/linker\"));\n            }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // no crate type set => linker never called => build succeeds if and\n    // only if build.rs succeeds, despite linker binary not existing.\n    p.cargo(\"build -Z target-applies-to-host --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_env_var_rustc_linker_host_target_env() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [target.{}]\n                linker = \"/path/to/linker\"\n                \"#,\n                target\n            ),\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n            use std::env;\n\n            fn main() {\n                assert!(env::var(\"RUSTC_LINKER\").unwrap().ends_with(\"/path/to/linker\"));\n            }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // no crate type set => linker never called => build succeeds if and\n    // only if build.rs succeeds, despite linker binary not existing.\n    p.cargo(\"build -Z target-applies-to-host --target\")\n        .env(\"CARGO_TARGET_APPLIES_TO_HOST\", \"false\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_invalid_host_config_feature_flag() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [target.{}]\n                linker = \"/path/to/linker\"\n                \"#,\n                target\n            ),\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // build.rs should fail due to -Zhost-config being set without -Ztarget-applies-to-host\n    p.cargo(\"build -Z host-config --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"host-config\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the -Zhost-config flag requires the -Ztarget-applies-to-host flag to be set\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_linker_host_target_with_bad_host_config() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [host]\n                linker = \"/path/to/host/linker\"\n                [target.{}]\n                linker = \"/path/to/target/linker\"\n                \"#,\n                target\n            ),\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // build.rs should fail due to bad host linker being set\n    p.cargo(\"build -Z target-applies-to-host -Z host-config --verbose --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]-C linker=[..]/path/to/host/linker [..]`\n[ERROR] linker `[..]/path/to/host/linker` not found\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_linker_bad_host() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [host]\n                linker = \"/path/to/host/linker\"\n                [target.{}]\n                linker = \"/path/to/target/linker\"\n                \"#,\n                target\n            ),\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // build.rs should fail due to bad host linker being set\n    p.cargo(\"build -Z target-applies-to-host -Z host-config --verbose --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]-C linker=[..]/path/to/host/linker [..]`\n[ERROR] linker `[..]/path/to/host/linker` not found\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_linker_bad_host_with_arch() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [host]\n                linker = \"/path/to/host/linker\"\n                [host.{}]\n                linker = \"/path/to/host/arch/linker\"\n                [target.{}]\n                linker = \"/path/to/target/linker\"\n                \"#,\n                target, target\n            ),\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // build.rs should fail due to bad host linker being set\n    p.cargo(\"build -Z target-applies-to-host -Z host-config --verbose --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]-C linker=[..]/path/to/host/arch/linker [..]`\n[ERROR] linker `[..]/path/to/host/arch/linker` not found\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_env_var_rustc_linker_cross_arch_host() {\n    let target = rustc_host();\n    let cross_target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [host.{}]\n                linker = \"/path/to/host/arch/linker\"\n                [target.{}]\n                linker = \"/path/to/target/linker\"\n                \"#,\n                cross_target, target\n            ),\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n            use std::env;\n\n            fn main() {\n                assert!(env::var(\"RUSTC_LINKER\").unwrap().ends_with(\"/path/to/target/linker\"));\n            }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // build.rs should be built fine since cross target != host target.\n    // assertion should succeed since it's still passed the target linker\n    p.cargo(\"build -Z target-applies-to-host -Z host-config --verbose --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_linker_bad_cross_arch_host() {\n    let target = rustc_host();\n    let cross_target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [host]\n                linker = \"/path/to/host/linker\"\n                [host.{}]\n                linker = \"/path/to/host/arch/linker\"\n                [target.{}]\n                linker = \"/path/to/target/linker\"\n                \"#,\n                cross_target, target\n            ),\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // build.rs should fail due to bad host linker being set\n    p.cargo(\"build -Z target-applies-to-host -Z host-config --verbose --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..] -C linker=[..]/path/to/host/linker [..]`\n[ERROR] linker `[..]/path/to/host/linker` not found\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn host_runner_wraps_build_script() {\n    let target = rustc_host();\n    let wrapper = tools::echo_wrapper();\n    let p = project()\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Build should succeed with the host runner wrapping the build script\n    p.cargo(\"build -Z target-applies-to-host -Z host-config -v --target\")\n        .arg(&target)\n        .env(\"CARGO_HOST_RUNNER\", &wrapper)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]build.rs [..]`\n[RUNNING] `[..]/rustc-echo-wrapper[EXE] [ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..]--crate-name foo [..]`\n[FINISHED] [..]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn host_runner_does_not_apply_to_target() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [host]\n                runner = \"nonexistent-runner\"\n                [target.{target}]\n                runner = \"nonexistent-target-runner\"\n                \"#,\n            ),\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // build.rs execution should fail due to the host runner, not the target runner\n    p.cargo(\"build -Z target-applies-to-host -Z host-config --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to run custom build command for `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  could not execute process `nonexistent-runner [ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` (never executed)\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn host_runner_arch_takes_precedence() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [host]\n                runner = \"nonexistent-generic-runner\"\n                [host.{target}]\n                runner = \"nonexistent-arch-runner\"\n                \"#,\n            ),\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // host.<triple>.runner should take precedence over host.runner\n    p.cargo(\"build -Z target-applies-to-host -Z host-config --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to run custom build command for `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  could not execute process `nonexistent-arch-runner [ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` (never executed)\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn host_runner_ignored_without_flag() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [host]\n            runner = \"nonexistent-runner\"\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Without -Zhost-config, host.runner should be ignored and build succeeds\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn host_runner_with_args() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [host]\n            runner = [\"nonexistent-runner\", \"--flag\", \"arg1\"]\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Runner args should be passed correctly before the build script path\n    p.cargo(\"build -Z target-applies-to-host -Z host-config --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to run custom build command for `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  could not execute process `nonexistent-runner --flag arg1 [ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` (never executed)\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn host_runner_does_not_apply_to_cargo_run() {\n    // `host.runner` should only wrap build scripts, not `cargo run`.\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [host]\n            runner = \"nonexistent-host-runner\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() { println!(\\\"hello\\\"); }\")\n        .build();\n\n    // with --target\n    p.cargo(\"run -Z target-applies-to-host -Z host-config --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/[HOST_TARGET]/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n\n    // without --target\n    p.cargo(\"run -Z target-applies-to-host -Z host-config\")\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_runner_does_not_apply_to_build_script() {\n    // Regression test for https://github.com/rust-lang/miri/issues/4855\n    // `target.<host>.runner` should not wrap build scripts.\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [target.{target}]\n                runner = \"nonexistent-runner\"\n                \"#,\n            ),\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_script_wrong_rustc_flags() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-flags=-aaa -bbb\"); }\"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[ERROR] only `-l` and `-L` flags are allowed in build script of `foo v0.5.0 ([ROOT]/foo)`: `-aaa -bbb`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_script_rustc_flags() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.foo]\n                path = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\n            \"foo/build.rs\",\n            r#\"\n                fn main() {\n                    let root = std::env::current_dir().unwrap();\n                    let root = root.parent().unwrap();\n                    println!(\"cargo::rustc-flags=-l nonexistinglib \\\n                        -L {R}/dummy-path1 -L {R}/dummy-path2\", R=root.display());\n                }\n            \"#,\n        )\n        .build();\n    p.root().join(\"dummy-path1\").mkdir_p();\n    p.root().join(\"dummy-path2\").mkdir_p();\n\n    p.cargo(\"build --verbose\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] foo v0.5.0 ([ROOT]/foo/foo)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 foo/build.rs [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo --edition=2015 foo/src/lib.rs [..]-L dependency=[ROOT]/foo/target/debug/deps -L [ROOT]/foo/dummy-path1 -L [ROOT]/foo/dummy-path2 -l nonexistinglib`\n[COMPILING] bar v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bar --edition=2015 src/main.rs [..]-L dependency=[ROOT]/foo/target/debug/deps --extern foo=[ROOT]/foo/target/debug/deps/libfoo-[HASH].rlib -L [ROOT]/foo/dummy-path1 -L [ROOT]/foo/dummy-path2`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn custom_build_script_rustc_flags_no_space() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.foo]\n                path = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\n            \"foo/build.rs\",\n            r#\"\n                fn main() {\n                    let root = std::env::current_dir().unwrap();\n                    let root = root.parent().unwrap();\n                    println!(\"cargo::rustc-flags=-lnonexistinglib \\\n                        -L {R}/dummy-path1 -L {R}/dummy-path2\", R=root.display());\n                }\n            \"#,\n        )\n        .build();\n    p.root().join(\"dummy-path1\").mkdir_p();\n    p.root().join(\"dummy-path2\").mkdir_p();\n\n    p.cargo(\"build --verbose\").with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] foo v0.5.0 ([ROOT]/foo/foo)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 foo/build.rs [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo --edition=2015 foo/src/lib.rs [..]-L dependency=[ROOT]/foo/target/debug/deps -L [ROOT]/foo/dummy-path1 -L [ROOT]/foo/dummy-path2 -l nonexistinglib`\n[COMPILING] bar v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bar --edition=2015 src/main.rs [..]-L dependency=[ROOT]/foo/target/debug/deps --extern foo=[ROOT]/foo/target/debug/deps/libfoo-[HASH].rlib -L [ROOT]/foo/dummy-path1 -L [ROOT]/foo/dummy-path2`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn links_no_build_cmd() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  package specifies that it links to `a` but does not have a custom build script\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn links_duplicates() {\n    // this tests that the links_duplicates are caught at resolver time\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"a\"\n                build = \"build.rs\"\n\n                [dependencies.a-sys]\n                path = \"a-sys\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"\")\n        .file(\n            \"a-sys/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a-sys\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"a\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a-sys/src/lib.rs\", \"\")\n        .file(\"a-sys/build.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to select a version for `a-sys`.\n    ... required by package `foo v0.5.0 ([ROOT]/foo)`\nversions that meet the requirements `*` are: 0.5.0\n\npackage `a-sys` links to the native library `a`, but it conflicts with a previous package which links to `a` as well:\npackage `foo v0.5.0 ([ROOT]/foo)`\nOnly one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the `links = \"a\"` value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.\n\nfailed to select a version for `a-sys` which could resolve this conflict\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn links_duplicates_old_registry() {\n    // Test old links validator. See `validate_links`.\n    Package::new(\"bar\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            links = \"a\"\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            links = \"a\"\n\n            [dependencies]\n            bar = \"0.1\"\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[ERROR] multiple packages link to native library `a`, but a native library can be linked only once\n\npackage `bar v0.1.0`\n    ... which satisfies dependency `bar = \"^0.1\"` (locked to 0.1.0) of package `foo v0.1.0 ([ROOT]/foo)`\nlinks to native library `a`\n\npackage `foo v0.1.0 ([ROOT]/foo)`\nalso links to native library `a`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn links_duplicates_deep_dependency() {\n    // this tests that the links_duplicates are caught at resolver time\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"a\"\n                build = \"build.rs\"\n\n                [dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies.a-sys]\n                path = \"a-sys\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\"a/build.rs\", \"\")\n        .file(\n            \"a/a-sys/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a-sys\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"a\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/a-sys/src/lib.rs\", \"\")\n        .file(\"a/a-sys/build.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to select a version for `a-sys`.\n    ... required by package `a v0.5.0 ([ROOT]/foo/a)`\n    ... which satisfies path dependency `a` of package `foo v0.5.0 ([ROOT]/foo)`\nversions that meet the requirements `*` are: 0.5.0\n\npackage `a-sys` links to the native library `a`, but it conflicts with a previous package which links to `a` as well:\npackage `foo v0.5.0 ([ROOT]/foo)`\nOnly one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the `links = \"a\"` value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.\n\nfailed to select a version for `a-sys` which could resolve this conflict\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn overrides_and_links() {\n    let target = rustc_host();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                fn main() {\n                    assert_eq!(env::var(\"DEP_FOO_FOO\").ok().expect(\"FOO missing\"),\n                               \"bar\");\n                    assert_eq!(env::var(\"DEP_FOO_BAR\").ok().expect(\"BAR missing\"),\n                               \"baz\");\n                }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}.foo]\n                    rustc-flags = \"-L foo -L bar\"\n                    foo = \"bar\"\n                    bar = \"baz\"\n                \"#,\n                target\n            ),\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"foo\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\"a/build.rs\", \"not valid rust code\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] a v0.5.0 ([ROOT]/foo/a)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..]`\n[RUNNING] `rustc --crate-name a [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..] -L foo -L bar`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn unused_overrides() {\n    let target = rustc_host();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}.foo]\n                    rustc-flags = \"-L foo -L bar\"\n                    foo = \"bar\"\n                    bar = \"baz\"\n                \"#,\n                target\n            ),\n        )\n        .build();\n\n    p.cargo(\"build -v\").run();\n}\n\n#[cargo_test]\nfn links_passes_env_vars() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                fn main() {\n                    assert_eq!(env::var(\"DEP_FOO_FOO\").unwrap(), \"bar\");\n                    assert_eq!(env::var(\"DEP_FOO_BAR\").unwrap(), \"baz\");\n                }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"foo\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            r#\"\n                use std::env;\n                fn main() {\n                    let lib = env::var(\"CARGO_MANIFEST_LINKS\").unwrap();\n                    assert_eq!(lib, \"foo\");\n\n                    println!(\"cargo::metadata=foo=bar\");\n                    println!(\"cargo::metadata=bar=baz\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\").run();\n}\n\n#[cargo_test]\nfn metadata_from_dep_kinds() {\n    let set_metadata = r#\"\nfn main() {\n    println!(\"cargo::metadata=key=value\");\n}\n\"#;\n\n    let get_metadata = r#\"\nfn warn_print_env_var(key: &str) {\n    println!(\"cargo::warning={key}={:?}\", std::env::var(key));\n}\nfn main() {\n    warn_print_env_var(\"DEP_FOO_KEY\");\n    warn_print_env_var(\"CARGO_DEP_LINKS_KEY\");\n}\n\"#;\n\n    // Create a project with a crate with `links` and 3 test crates that imports this crate as a\n    // normal dependency (n), dev-dependency (d), and build-dependency (b).\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                resolver = \"3\"\n                members = [\"links\", \"n\", \"b\", \"d\"]\n            \"#,\n        )\n        .file(\n            \"links/Cargo.toml\",\n            r#\"\n[package]\nname = \"links\"\nedition = \"2024\"\nlinks = \"foo\"\n\"#,\n        )\n        .file(\"links/src/lib.rs\", \"\")\n        .file(\"links/build.rs\", set_metadata)\n        .file(\n            \"n/Cargo.toml\",\n            r#\"\n[package]\nname = \"n\"\nedition = \"2024\"\n\n[dependencies]\nlinks.path = \"../links\"\n\"#,\n        )\n        .file(\"n/src/lib.rs\", \"\")\n        .file(\"n/build.rs\", get_metadata)\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n[package]\nname = \"b\"\nedition = \"2024\"\n\n[build-dependencies]\nlinks.path = \"../links\"\n\"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\"b/build.rs\", get_metadata)\n        .file(\n            \"d/Cargo.toml\",\n            r#\"\n[package]\nname = \"d\"\nedition = \"2024\"\n\n[dev-dependencies]\nlinks.path = \"../links\"\n\"#,\n        )\n        .file(\"d/src/lib.rs\", \"\")\n        .file(\"d/build.rs\", get_metadata)\n        .build();\n\n    p.cargo(\"check --all-targets -Zany-build-script-metadata\")\n        .masquerade_as_nightly_cargo(&[\"any-build-script-metadata\"])\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] links v0.0.0 ([ROOT]/foo/links)\n[COMPILING] n v0.0.0 ([ROOT]/foo/n)\n[COMPILING] b v0.0.0 ([ROOT]/foo/b)\n[COMPILING] d v0.0.0 ([ROOT]/foo/d)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[WARNING] n@0.0.0: DEP_FOO_KEY=Ok(\"value\")\n[WARNING] n@0.0.0: CARGO_DEP_LINKS_KEY=Ok(\"value\")\n[WARNING] d@0.0.0: DEP_FOO_KEY=Err(NotPresent)\n[WARNING] d@0.0.0: CARGO_DEP_LINKS_KEY=Err(NotPresent)\n[WARNING] b@0.0.0: DEP_FOO_KEY=Err(NotPresent)\n[WARNING] b@0.0.0: CARGO_DEP_LINKS_KEY=Err(NotPresent)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn links_passes_env_vars_with_any_build_script_unstable_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                fn main() {\n                    assert_eq!(env::var(\"DEP_FOO_FOO\").unwrap(), \"bar\");\n                    assert_eq!(env::var(\"DEP_FOO_BAR\").unwrap(), \"baz\");\n                    assert_eq!(env::var(\"CARGO_DEP_A_FOO\").unwrap(), \"bar\");\n                    assert_eq!(env::var(\"CARGO_DEP_A_BAR\").unwrap(), \"baz\");\n                }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"foo\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            r#\"\n                use std::env;\n                fn main() {\n                    let lib = env::var(\"CARGO_MANIFEST_LINKS\").unwrap();\n                    assert_eq!(lib, \"foo\");\n\n                    println!(\"cargo::metadata=foo=bar\");\n                    println!(\"cargo::metadata=bar=baz\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -v -Zany-build-script-metadata\")\n        .masquerade_as_nightly_cargo(&[\"any-build-script-metadata\"])\n        .run();\n}\n\n#[cargo_test]\nfn non_links_can_pass_env_vars() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                fn main() {\n                    // DEP_<links>_<key> is only allowed for `links` crates\n                    assert!(env::var(\"DEP_FOO_FOO\").is_err());\n                    assert!(env::var(\"DEP_FOO_BAR\").is_err());\n                    // Make sure DEP_<name-in-toml>_<key> is not present.\n                    // This is not a valid scenario but verify these are not present just incase.\n                    assert!(env::var(\"DEP_A_FOO\").is_err());\n                    assert!(env::var(\"DEP_A_BAR\").is_err());\n\n                    assert_eq!(env::var(\"CARGO_DEP_A_FOO\").unwrap(), \"bar\");\n                    assert_eq!(env::var(\"CARGO_DEP_A_BAR\").unwrap(), \"baz\");\n                }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::metadata=foo=bar\");\n                    println!(\"cargo::metadata=bar=baz\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -v -Zany-build-script-metadata\")\n        .masquerade_as_nightly_cargo(&[\"any-build-script-metadata\"])\n        .run();\n}\n\n#[cargo_test]\nfn non_links_can_pass_env_vars_with_dep_renamed() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies]\n                my-renamed-package = { package = \"a\", path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                fn main() {\n                    assert!(env::var(\"DEP_A_FOO\").is_err());\n                    assert!(env::var(\"DEP_A_BAR\").is_err());\n                    assert!(env::var(\"DEP_MY_RENAMED_PACKAGE_FOO\").is_err());\n                    assert!(env::var(\"DEP_MY_RENAMED_PACKAGE_BAR\").is_err());\n\n                    // If dep was renamed, we should not add env vars with the original name\n                    // and env vars with the renamed package should be added\n                    assert!(env::var(\"CARGO_DEP_A_FOO\").is_err());\n                    assert!(env::var(\"CARGO_DEP_A_BAR\").is_err());\n                    assert_eq!(env::var(\"CARGO_DEP_MY_RENAMED_PACKAGE_FOO\").unwrap(), \"bar\");\n                    assert_eq!(env::var(\"CARGO_DEP_MY_RENAMED_PACKAGE_BAR\").unwrap(), \"baz\");\n                }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::metadata=foo=bar\");\n                    println!(\"cargo::metadata=bar=baz\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -v -Zany-build-script-metadata\")\n        .masquerade_as_nightly_cargo(&[\"any-build-script-metadata\"])\n        .run();\n}\n\n#[cargo_test]\nfn non_links_can_pass_env_vars_direct_deps_only() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies]\n                direct = { path = \"direct\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                fn main() {\n                    assert!(env::var(\"DEP_DIRECT_FOO\").is_err());\n                    assert!(env::var(\"DEP_TRANSITIVE_FOO\").is_err());\n\n                    assert_eq!(env::var(\"CARGO_DEP_DIRECT_FOO\").unwrap(), \"direct\");\n                    assert!(env::var(\"CARGO_DEP_TRANSITIVE_FOO\").is_err());\n                }\n            \"#,\n        )\n        .file(\n            \"direct/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"direct\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies]\n                transitive = { path = \"../transitive\" }\n            \"#,\n        )\n        .file(\"direct/src/lib.rs\", \"\")\n        .file(\n            \"direct/build.rs\",\n            r#\"\n                use std::env;\n                fn main() {\n                    println!(\"cargo::metadata=foo=direct\");\n\n                    assert_eq!(env::var(\"CARGO_DEP_TRANSITIVE_FOO\").unwrap(), \"transitive\");\n                }\n            \"#,\n        )\n        .file(\n            \"transitive/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"transitive\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"transitive/src/lib.rs\", \"\")\n        .file(\n            \"transitive/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::metadata=foo=transitive\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -v -Zany-build-script-metadata\")\n        .masquerade_as_nightly_cargo(&[\"any-build-script-metadata\"])\n        .run();\n}\n\n/// Regression test for https://github.com/rust-lang/cargo/issues/16493\n#[cargo_test]\nfn with_patch() {\n    Package::new(\"cxx\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            edition = \"2021\"\n\n            [dependencies]\n            cxx = \"1.0.0\"\n\n            [patch.crates-io]\n            cxx = { path = \"cxx\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\n            \"cxx/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"cxx\"\n            version = \"1.0.0\"\n            edition = \"2021\"\n            links = \"cxx\"\n            \"#,\n        )\n        .file(\"cxx/src/lib.rs\", \"\")\n        .file(\"cxx/build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[COMPILING] cxx v1.0.0 ([ROOT]/foo/cxx)\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn only_rerun_build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\").run();\n    p.root().move_into_the_past();\n\n    p.change_file(\"some-new-file\", \"\");\n    p.root().move_into_the_past();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/foo): the precalculated components changed\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rebuild_continues_to_pass_env_vars() {\n    let a = project()\n        .at(\"a\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"foo\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::time::Duration;\n                fn main() {\n                    println!(\"cargo::metadata=foo=bar\");\n                    println!(\"cargo::metadata=bar=baz\");\n                    std::thread::sleep(Duration::from_millis(500));\n                }\n            \"#,\n        )\n        .build();\n    a.root().move_into_the_past();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    build = \"build.rs\"\n\n                    [dependencies.a]\n                    path = '{}'\n                \"#,\n                a.root().display()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                fn main() {\n                    assert_eq!(env::var(\"DEP_FOO_FOO\").unwrap(), \"bar\");\n                    assert_eq!(env::var(\"DEP_FOO_BAR\").unwrap(), \"baz\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -v\").run();\n    p.root().move_into_the_past();\n\n    p.change_file(\"some-new-file\", \"\");\n    p.root().move_into_the_past();\n\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn testing_and_such() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    println!(\"build\");\n    p.cargo(\"build -v\").run();\n    p.root().move_into_the_past();\n\n    p.change_file(\"src/lib.rs\", \"\");\n    p.root().move_into_the_past();\n\n    println!(\"test\");\n    p.cargo(\"test -vj1\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/foo): the precalculated components changed\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `rustdoc [..]--test [..]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    println!(\"doc\");\n    p.cargo(\"doc -v\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    p.change_file(\"src/main.rs\", \"fn main() {}\");\n    println!(\"run\");\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn propagation_of_l_flags() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"bar\"\n                build = \"build.rs\"\n\n                [dependencies.b]\n                path = \"../b\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-flags=-L bar\"); }\"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"foo\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\"b/build.rs\", \"bad file\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}.foo]\n                    rustc-flags = \"-L foo\"\n                \"#,\n                target\n            ),\n        )\n        .build();\n\n    p.cargo(\"build -v -j1\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustc --crate-name a [..] -L bar -L foo`\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -L bar -L foo`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn propagation_of_l_flags_new() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"bar\"\n                build = \"build.rs\"\n\n                [dependencies.b]\n                path = \"../b\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-search=bar\");\n                }\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"foo\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\"b/build.rs\", \"bad file\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}.foo]\n                    rustc-link-search = [\"foo\"]\n                \"#,\n                target\n            ),\n        )\n        .build();\n\n    p.cargo(\"build -v -j1\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustc --crate-name a [..] -L bar -L foo`\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -L bar -L foo`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_deps_simple() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n                [build-dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            \"\n            #[allow(unused_extern_crates)]\n            extern crate a;\n            fn main() {}\n        \",\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.5.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\").with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] a v0.5.0 ([ROOT]/foo/a)\n[RUNNING] `rustc --crate-name a [..]`\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..] build.rs [..] --extern a=[ROOT]/foo/target/debug/deps/liba-[HASH].rlib`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn build_deps_not_for_normal() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n                [build-dependencies.aaaaa]\n                path = \"a\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"#[allow(unused_extern_crates)] extern crate aaaaa;\",\n        )\n        .file(\n            \"build.rs\",\n            \"\n            #[allow(unused_extern_crates)]\n            extern crate aaaaa;\n            fn main() {}\n        \",\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"aaaaa\", \"0.5.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v --target\")\n        .arg(&target)\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n...\nerror[E0463]: can't find crate for `aaaaa`\n[ERROR] could not compile `foo` (lib) due to 1 previous error\n\nCaused by:\n  process didn't exit successfully: `rustc --crate-name foo[..]` ([EXIT_STATUS]: 1)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_cmd_with_a_build_cmd() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [build-dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            \"\n            #[allow(unused_extern_crates)]\n            extern crate a;\n            fn main() {}\n        \",\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [build-dependencies.b]\n                path = \"../b\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            \"#[allow(unused_extern_crates)] extern crate b; fn main() {}\",\n        )\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.5.0\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\").with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] b v0.5.0 ([ROOT]/foo/b)\n[RUNNING] `rustc --crate-name b [..]`\n[COMPILING] a v0.5.0 ([ROOT]/foo/a)\n[RUNNING] `rustc --crate-name build_script_build [..] a/build.rs [..] --extern b=[ROOT]/foo/target/debug/deps/libb-[HASH].rlib`\n[RUNNING] `[ROOT]/foo/target/debug/build/a-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name a [..]a/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps`\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/build/foo-[HASH] -L dependency=[ROOT]/foo/target/debug/deps --extern a=[ROOT]/foo/target/debug/deps/liba-[HASH].rlib`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]src/lib.rs [..]--crate-type lib --emit=[..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn out_dir_is_preserved() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                use std::fs::File;\n                use std::path::Path;\n                fn main() {\n                    let out = env::var(\"OUT_DIR\").unwrap();\n                    File::create(Path::new(&out).join(\"foo\")).unwrap();\n                }\n            \"#,\n        )\n        .build();\n\n    // Make the file\n    p.cargo(\"check -v\").run();\n\n    // Change to asserting that it's there\n    p.change_file(\n        \"build.rs\",\n        r#\"\n            use std::env;\n            use std::fs::File;\n            use std::path::Path;\n            fn main() {\n                let out = env::var(\"OUT_DIR\").unwrap();\n                File::open(&Path::new(&out).join(\"foo\")).unwrap();\n            }\n        \"#,\n    );\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/foo): the file `build.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Run a fresh build where file should be preserved\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // One last time to make sure it's still there.\n    p.change_file(\"foo\", \"\");\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/foo): the precalculated components changed\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn output_separate_lines() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-flags=-L foo\");\n                    println!(\"cargo::rustc-flags=-l static=foo\");\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"build -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..] -L foo -l static=foo`\n[ERROR] could not find native static library `foo`, perhaps an -L flag is missing?\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn output_separate_lines_new() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-search=foo\");\n                    println!(\"cargo::rustc-link-lib=static=foo\");\n                    println!(\"cargo::rustc-link-lib=bar\");\n                    println!(\"cargo::rustc-link-search=bar\");\n                }\n            \"#,\n        )\n        .build();\n    // The order of the arguments passed to rustc is important.\n    p.cargo(\"build -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..] -L foo -L bar -l static=foo -l bar`\n[ERROR] could not find native static library `foo`, perhaps an -L flag is missing?\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn code_generation() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                include!(concat!(env!(\"OUT_DIR\"), \"/hello.rs\"));\n\n                fn main() {\n                    println!(\"{}\", message());\n                }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                use std::fs;\n                use std::path::PathBuf;\n\n                fn main() {\n                    let dst = PathBuf::from(env::var(\"OUT_DIR\").unwrap());\n                    fs::write(dst.join(\"hello.rs\"),\n                        \"\n                        pub fn message() -> &'static str {\n                            \\\"Hello, World!\\\"\n                        }\n                        \")\n                    .unwrap();\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn release_with_build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -v --release\").run();\n}\n\n#[cargo_test]\nfn build_script_only() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                  [package]\n                  name = \"foo\"\n                  version = \"0.0.0\"\n                  edition = \"2015\"\n                  authors = []\n                  build = \"build.rs\"\n            \"#,\n        )\n        .file(\"build.rs\", r#\"fn main() {}\"#)\n        .build();\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  no targets specified in the manifest\n  either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn shared_dep_with_a_build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies.a]\n                path = \"a\"\n\n                [build-dependencies.b]\n                path = \"b\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/build.rs\", \"fn main() {}\")\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.a]\n                path = \"../a\"\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn test_a_lib_with_a_build_command() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                include!(concat!(env!(\"OUT_DIR\"), \"/foo.rs\"));\n\n                /// ```\n                /// foo::bar();\n                /// ```\n                pub fn bar() {\n                    assert_eq!(foo(), 1);\n                }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                use std::fs;\n                use std::path::PathBuf;\n\n                fn main() {\n                    let out = PathBuf::from(env::var(\"OUT_DIR\").unwrap());\n                    fs::write(out.join(\"foo.rs\"), \"fn foo() -> i32 { 1 }\").unwrap();\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn test_dev_dep_build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dev-dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/build.rs\", \"fn main() {}\")\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn build_script_with_dynamic_native_dependency() {\n    let build = project()\n        .at(\"builder\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"builder\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"builder\"\n                crate-type = [\"dylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\"#[no_mangle] pub extern \"C\" fn foo() {}\"#)\n        .build();\n\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [build-dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"build.rs\", \"extern crate bar; fn main() { bar::bar() }\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"bar/build.rs\",\n            r#\"\n                use std::env;\n                use std::fs;\n                use std::path::PathBuf;\n\n                fn main() {\n                    let out_dir = PathBuf::from(env::var(\"OUT_DIR\").unwrap());\n                    let root = PathBuf::from(env::var(\"BUILDER_ROOT\").unwrap());\n                    let file = format!(\"{}builder{}\",\n                        env::consts::DLL_PREFIX,\n                        env::consts::DLL_SUFFIX);\n                    let src = root.join(&file);\n                    let dst = out_dir.join(&file);\n                    fs::copy(src, dst).unwrap();\n                    if cfg!(target_env = \"msvc\") {\n                        fs::copy(root.join(\"builder.dll.lib\"),\n                                 out_dir.join(\"builder.dll.lib\")).unwrap();\n                    }\n                    println!(\"cargo::rustc-link-search=native={}\", out_dir.display());\n                }\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                pub fn bar() {\n                    #[cfg_attr(not(target_env = \"msvc\"), link(name = \"builder\"))]\n                    #[cfg_attr(target_env = \"msvc\", link(name = \"builder.dll\"))]\n                    extern \"C\" { fn foo(); }\n                    unsafe { foo() }\n                }\n            \"#,\n        )\n        .build();\n\n    build\n        .cargo(\"build -v\")\n        .env(\"CARGO_LOG\", \"cargo::ops::cargo_rustc\")\n        .run();\n\n    let root = build.root().join(\"target\").join(\"debug\");\n    foo.cargo(\"build -v\")\n        .env(\"BUILDER_ROOT\", root)\n        .env(\"CARGO_LOG\", \"cargo::ops::cargo_rustc\")\n        .run();\n}\n\n#[cargo_test]\nfn profile_and_opt_level_set_correctly() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                  use std::env;\n\n                  fn main() {\n                      assert_eq!(env::var(\"OPT_LEVEL\").unwrap(), \"3\");\n                      assert_eq!(env::var(\"PROFILE\").unwrap(), \"release\");\n                      assert_eq!(env::var(\"DEBUG\").unwrap(), \"false\");\n                  }\n            \"#,\n        )\n        .build();\n    p.cargo(\"bench\").run();\n}\n\n#[cargo_test]\nfn profile_debug_0() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                debug = 0\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                  use std::env;\n\n                  fn main() {\n                      assert_eq!(env::var(\"OPT_LEVEL\").unwrap(), \"0\");\n                      assert_eq!(env::var(\"PROFILE\").unwrap(), \"debug\");\n                      assert_eq!(env::var(\"DEBUG\").unwrap(), \"false\");\n                  }\n            \"#,\n        )\n        .build();\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn build_script_with_lto() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [profile.dev]\n                lto = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn test_duplicate_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies.bar]\n                path = \"bar\"\n\n                [build-dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                extern crate bar;\n                fn main() { bar::do_nothing() }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                extern crate bar;\n                fn main() { bar::do_nothing() }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn do_nothing() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn cfg_feedback() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"#[cfg(foo)] fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-cfg=foo\"); }\"#,\n        )\n        .build();\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn cfg_override() {\n    let target = rustc_host();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"a\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"#[cfg(foo)] fn main() {}\")\n        .file(\"build.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}.a]\n                    rustc-cfg = [\"foo\"]\n                \"#,\n                target\n            ),\n        )\n        .build();\n\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn cfg_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"fn main() {\n                println!(\"cargo::rustc-cfg=foo\");\n                println!(\"cargo::rustc-check-cfg=cfg(foo)\");\n            }\"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                ///\n                /// ```\n                /// extern crate foo;\n                ///\n                /// fn main() {\n                ///     foo::foo()\n                /// }\n                /// ```\n                ///\n                #[cfg(foo)]\n                pub fn foo() {}\n\n                #[cfg(foo)]\n                #[test]\n                fn test_foo() {\n                    foo()\n                }\n            \"#,\n        )\n        .file(\"tests/test.rs\", \"#[cfg(foo)] #[test] fn test_bar() {}\")\n        .build();\n    p.cargo(\"test -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..] --cfg foo[..]`\n[RUNNING] `rustc --crate-name foo [..] --cfg foo[..]`\n[RUNNING] `rustc --crate-name test [..] --cfg foo[..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[RUNNING] `[ROOT]/foo/target/debug/deps/test-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `rustdoc [..]--cfg foo[..]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest test_foo ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest test_bar ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest src/lib.rs - foo (line 3) ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cfg_doc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-cfg=foo\"); }\"#,\n        )\n        .file(\"src/lib.rs\", \"#[cfg(foo)] pub fn foo() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"bar/build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-cfg=bar\"); }\"#,\n        )\n        .file(\"bar/src/lib.rs\", \"#[cfg(bar)] pub fn bar() {}\")\n        .build();\n    p.cargo(\"doc\").run();\n    assert!(p.root().join(\"target/doc\").is_dir());\n    assert!(p.root().join(\"target/doc/foo/fn.foo.html\").is_file());\n    assert!(p.root().join(\"target/doc/bar/fn.bar.html\").is_file());\n}\n\n#[cargo_test]\nfn cfg_override_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n                links = \"a\"\n\n                [lints.rust]\n                unexpected_cfgs = \"allow\" # bc of override, stable/nightly, tests\n            \"#,\n        )\n        .file(\"build.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}.a]\n                    rustc-cfg = [\"foo\"]\n                \"#,\n                rustc_host()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                ///\n                /// ```\n                /// extern crate foo;\n                ///\n                /// fn main() {\n                ///     foo::foo()\n                /// }\n                /// ```\n                ///\n                #[cfg(foo)]\n                pub fn foo() {}\n\n                #[cfg(foo)]\n                #[test]\n                fn test_foo() {\n                    foo()\n                }\n            \"#,\n        )\n        .file(\"tests/test.rs\", \"#[cfg(foo)] #[test] fn test_bar() {}\")\n        .build();\n    p.cargo(\"test -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo[..]`\n[RUNNING] `rustc --crate-name foo[..]`\n[RUNNING] `rustc --crate-name test[..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[RUNNING] `[ROOT]/foo/target/debug/deps/test-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `rustdoc [..] --cfg foo[..]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest test_foo ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest test_bar ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest src/lib.rs - foo (line 3) ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cfg_override_doc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n                links = \"a\"\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{target}.a]\n                    rustc-cfg = [\"foo\"]\n                    [target.{target}.b]\n                    rustc-cfg = [\"bar\"]\n                \"#,\n                target = rustc_host()\n            ),\n        )\n        .file(\"build.rs\", \"\")\n        .file(\"src/lib.rs\", \"#[cfg(foo)] pub fn foo() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n                links = \"b\"\n            \"#,\n        )\n        .file(\"bar/build.rs\", \"\")\n        .file(\"bar/src/lib.rs\", \"#[cfg(bar)] pub fn bar() {}\")\n        .build();\n    p.cargo(\"doc\").run();\n    assert!(p.root().join(\"target/doc\").is_dir());\n    assert!(p.root().join(\"target/doc/foo/fn.foo.html\").is_file());\n    assert!(p.root().join(\"target/doc/bar/fn.bar.html\").is_file());\n}\n\n#[cargo_test]\nfn env_build() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                const FOO: &'static str = env!(\"FOO\");\n                fn main() {\n                    println!(\"{}\", FOO);\n                }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-env=FOO=foo\"); }\"#,\n        )\n        .build();\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn env_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-env=FOO=foo\"); }\"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"pub const FOO: &'static str = env!(\"FOO\"); \"#,\n        )\n        .file(\n            \"tests/test.rs\",\n            r#\"\n                extern crate foo;\n\n                #[test]\n                fn test_foo() {\n                    assert_eq!(\"foo\", foo::FOO);\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"test -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build[..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo[..]`\n[RUNNING] `rustc --crate-name foo[..]`\n[RUNNING] `rustc --crate-name test[..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[RUNNING] `[ROOT]/foo/target/debug/deps/test-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `rustdoc --edition=2015 --crate-type lib --color auto --crate-name foo[..]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest test_foo ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_doc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                const FOO: &'static str = env!(\"FOO\");\n                fn main() {}\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-env=FOO=foo\"); }\"#,\n        )\n        .build();\n    p.cargo(\"doc -v\").run();\n}\n\n#[cargo_test]\nfn flags_go_into_tests() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"tests/foo.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                a = { path = \"../a\" }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            r#\"\n                fn main() {\n                    let path = std::env::current_dir().unwrap().parent().unwrap().join(\"link-dir\");\n                    println!(\"cargo::rustc-link-search={}\", path.display());\n                }\n            \"#,\n        )\n        .build();\n    p.root().join(\"link-dir\").mkdir_p();\n\n    p.cargo(\"test -v --test=foo\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] a v0.5.0 ([ROOT]/foo/a)\n[RUNNING] `rustc [..] a/build.rs [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/a-[HASH]/build-script-build`\n[RUNNING] `rustc [..] a/src/lib.rs [..] -L [ROOT]/foo/link-dir`\n[COMPILING] b v0.5.0 ([ROOT]/foo/b)\n[RUNNING] `rustc [..] b/src/lib.rs [..] -L [ROOT]/foo/link-dir`\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] src/lib.rs [..] -L [ROOT]/foo/link-dir`\n[RUNNING] `rustc [..] tests/foo.rs [..] -L [ROOT]/foo/link-dir`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"test -v -pb --lib\")\n        .with_stderr_data(str![[r#\"\n[FRESH] a v0.5.0 ([ROOT]/foo/a)\n[COMPILING] b v0.5.0 ([ROOT]/foo/b)\n[RUNNING] `rustc --crate-name b [..] -L [ROOT]/foo/link-dir`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/b-[HASH][EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn diamond_passes_args_only_once() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"tests/foo.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                b = { path = \"../b\" }\n                c = { path = \"../c\" }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                c = { path = \"../c\" }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"c/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"c\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"c/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-search=native=test\");\n                }\n            \"#,\n        )\n        .file(\"c/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 3 packages to latest compatible versions\n[COMPILING] c v0.5.0 ([ROOT]/foo/c)\n[RUNNING] `rustc --crate-name build_script_build [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/c-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name c [..] -L native=test`\n[COMPILING] b v0.5.0 ([ROOT]/foo/b)\n[RUNNING] `rustc --crate-name b [..] -L native=test`\n[COMPILING] a v0.5.0 ([ROOT]/foo/a)\n[RUNNING] `rustc --crate-name a [..] -L native=test`\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -L native=test`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn adding_an_override_invalidates() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"foo\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\".cargo/config.toml\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-search=native=foo\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..] -L native=foo`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \".cargo/config.toml\",\n        &format!(\n            \"\n                [target.{}.foo]\n                rustc-link-search = [\\\"native=bar\\\"]\n            \",\n            target\n        ),\n    );\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -L native=bar`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn changing_an_override_invalidates() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"foo\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                \"\n            [target.{}.foo]\n            rustc-link-search = [\\\"native=foo\\\"]\n        \",\n                target\n            ),\n        )\n        .file(\"build.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -L native=foo`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \".cargo/config.toml\",\n        &format!(\n            \"\n                [target.{}.foo]\n                rustc-link-search = [\\\"native=bar\\\"]\n            \",\n            target\n        ),\n    );\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/foo): the precalculated components changed\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -L native=bar`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fresh_builds_possible_with_link_libs() {\n    // The bug is non-deterministic. Sometimes you can get a fresh build\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"nativefoo\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                \"\n            [target.{}.nativefoo]\n            rustc-link-lib = [\\\"a\\\"]\n            rustc-link-search = [\\\"./b\\\"]\n            rustc-flags = \\\"-l z -L ./\\\"\n        \",\n                target\n            ),\n        )\n        .file(\"build.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] src/lib.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fresh_builds_possible_with_multiple_metadata_overrides() {\n    // The bug is non-deterministic. Sometimes you can get a fresh build\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"foo\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                \"\n            [target.{}.foo]\n            a = \\\"\\\"\n            b = \\\"\\\"\n            c = \\\"\\\"\n            d = \\\"\\\"\n            e = \\\"\\\"\n        \",\n                target\n            ),\n        )\n        .file(\"build.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] src/lib.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn generate_good_d_files() {\n    // this is here to stop regression on an issue where build.rs rerun-if-changed paths aren't\n    // made absolute properly, which in turn interacts poorly with the dep-info-basedir setting,\n    // and the dep-info files have other-crate-relative paths spat out in them\n    let p = project()\n        .file(\n            \"awoo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"awoo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"awoo/src/lib.rs\", \"\")\n        .file(\n            \"awoo/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rerun-if-changed=build.rs\");\n                    println!(\"cargo::rerun-if-changed=barkbarkbark\");\n                }\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"meow\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                [dependencies]\n                awoo = { path = \"awoo\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\").run();\n\n    let dot_d_path = p.bin(\"meow\").with_extension(\"d\");\n    println!(\"*meow at* {:?}\", dot_d_path);\n    let dot_d = fs::read_to_string(&dot_d_path).unwrap();\n\n    println!(\"*.d file content*: {}\", &dot_d);\n\n    assert_e2e().eq(\n        &dot_d,\n        str![[r#\"\n[ROOT]/foo/target/debug/meow[EXE]: [ROOT]/foo/awoo/barkbarkbark [ROOT]/foo/awoo/build.rs [ROOT]/foo/awoo/src/lib.rs [ROOT]/foo/src/main.rs\n\n\"#]],\n    );\n\n    // paths relative to dependency roots should not be allowed\n    assert!(\n        !dot_d\n            .split_whitespace()\n            .any(|v| v == \"barkbarkbark\" || v == \"build.rs\")\n    );\n\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n        [build]\n        dep-info-basedir=\".\"\n    \"#,\n    );\n    p.cargo(\"build -v\").run();\n\n    let dot_d = fs::read_to_string(&dot_d_path).unwrap();\n\n    println!(\"*.d file content with dep-info-basedir*: {}\", &dot_d);\n\n    assert_e2e().eq(\n        &dot_d,\n        str![[r#\"\ntarget/debug/meow[EXE]: awoo/barkbarkbark awoo/build.rs awoo/src/lib.rs src/main.rs\n\n\"#]],\n    );\n\n    // paths relative to dependency roots should not be allowed\n    assert!(\n        !dot_d\n            .split_whitespace()\n            .any(|v| v == \"barkbarkbark\" || v == \"build.rs\")\n    );\n}\n\n#[cargo_test]\nfn generate_good_d_files_for_external_tools() {\n    // This tests having a relative paths going out of the\n    // project root in config's dep-info-basedir\n    let p = project_in(\"rust_things\")\n        .file(\n            \"awoo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"awoo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"awoo/src/lib.rs\", \"\")\n        .file(\n            \"awoo/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rerun-if-changed=build.rs\");\n                    println!(\"cargo::rerun-if-changed=barkbarkbark\");\n                }\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"meow\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                [dependencies]\n                awoo = { path = \"awoo\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                dep-info-basedir=\"../..\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\").run();\n\n    let dot_d_path = p.bin(\"meow\").with_extension(\"d\");\n    let dot_d = fs::read_to_string(&dot_d_path).unwrap();\n\n    println!(\"*.d file content with dep-info-basedir*: {}\", &dot_d);\n\n    assert_e2e().eq(&dot_d, str![[r#\"\nrust_things/foo/target/debug/meow[EXE]: rust_things/foo/awoo/barkbarkbark rust_things/foo/awoo/build.rs rust_things/foo/awoo/src/lib.rs rust_things/foo/src/main.rs\n\n\"#]]);\n}\n\n#[cargo_test]\nfn rebuild_only_on_explicit_paths() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rerun-if-changed=foo\");\n                    println!(\"cargo::rerun-if-changed=bar\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -v\").run();\n\n    // files don't exist, so should always rerun if they don't exist\n    println!(\"run without\");\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/foo): the file `foo` is missing\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..] src/lib.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    sleep_ms(1000);\n    p.change_file(\"foo\", \"\");\n    p.change_file(\"bar\", \"\");\n    sleep_ms(1000); // make sure the to-be-created outfile has a timestamp distinct from the infiles\n\n    // now the exist, so run once, catch the mtime, then shouldn't run again\n    println!(\"run with\");\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/foo): the file `foo` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..] src/lib.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    println!(\"run with2\");\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    sleep_ms(1000);\n\n    // random other files do not affect freshness\n    println!(\"run baz\");\n    p.change_file(\"baz\", \"// modified\");\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // but changing dependent files does\n    println!(\"run foo change\");\n    p.change_file(\"foo\", \"// modified\");\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/foo): the file `foo` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..] src/lib.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // .. as does deleting a file\n    println!(\"run bar delete\");\n    fs::remove_file(p.root().join(\"bar\")).unwrap();\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/foo): the file `bar` is missing\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..] src/lib.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doctest_receives_build_link_args() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"bar\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-search=native=bar\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test -v\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--crate-name foo --test [..]-L native=bar[..]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn please_respect_the_dag() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies]\n                a = { path = 'a' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-search=native=foo\");\n                }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"bar\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-search=native=bar\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustc --crate-name foo [..] -L native=foo -L native=bar`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn non_utf8_output() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::io::prelude::*;\n\n                fn main() {\n                    let mut out = std::io::stdout();\n                    // print something that's not utf8\n                    out.write_all(b\"\\xff\\xff\\n\").unwrap();\n\n                    // now print some cargo metadata that's utf8\n                    println!(\"cargo::rustc-cfg=foo\");\n\n                    // now print more non-utf8\n                    out.write_all(b\"\\xff\\xff\\n\").unwrap();\n                }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"#[cfg(foo)] fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn custom_target_dir() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                target-dir = 'test'\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/build.rs\", \"fn main() {}\")\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn panic_abort_with_build_scripts() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.release]\n                panic = 'abort'\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"#[allow(unused_extern_crates)] extern crate a;\",\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [build-dependencies]\n                b = { path = \"../b\" }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            \"#[allow(unused_extern_crates)] extern crate b; fn main() {}\",\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v --release\").run();\n\n    p.root().join(\"target\").rm_rf();\n\n    p.cargo(\"test --release -v\")\n        .with_stderr_does_not_contain(\"[..]panic=abort[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn warnings_emitted() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::warning=foo\");\n                    println!(\"cargo::warning=bar\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[WARNING] foo@0.5.0: foo\n[WARNING] foo@0.5.0: bar\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn errors_and_warnings_emitted_and_build_failed() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::warning=foo\");\n                    println!(\"cargo::warning=bar\");\n                    println!(\"cargo::error=foo err\");\n                    println!(\"cargo::error=bar err\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[WARNING] foo@0.5.0: foo\n[WARNING] foo@0.5.0: bar\n[ERROR] foo@0.5.0: foo err\n[ERROR] foo@0.5.0: bar err\n[ERROR] build script logged errors\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warnings_emitted_from_path_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::warning=foo\");\n                    println!(\"cargo::warning=bar\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] a v0.5.0 ([ROOT]/foo/a)\n[WARNING] a@0.5.0: foo\n[WARNING] a@0.5.0: bar\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warnings_emitted_when_build_script_panics() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::warning=foo\");\n                    println!(\"cargo::warning=bar\");\n                    panic!(\"our crate panicked\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[WARNING] foo@0.5.0: foo\n[WARNING] foo@0.5.0: bar\n[ERROR] failed to run custom build command for `foo v0.5.0 ([ROOT]/foo)`\n\nCaused by:\n  process didn't exit successfully: `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` ([EXIT_STATUS]: 101)\n  --- stdout\n  cargo::warning=foo\n  cargo::warning=bar\n\n  --- stderr\n...\n[..]our crate panicked[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warnings_emitted_when_dependency_panics() {\n    Package::new(\"published\", \"0.1.0\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::warning=foo\");\n                    println!(\"cargo::warning=bar\");\n                    panic!(\"dependency panicked\");\n                }\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"published\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                published = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n    .with_status(101)\n    .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] published v0.1.0 (registry `dummy-registry`)\n[COMPILING] published v0.1.0\n[WARNING] published@0.1.0: foo\n[WARNING] published@0.1.0: bar\n[ERROR] failed to run custom build command for `published v0.1.0`\n\nCaused by:\n  process didn't exit successfully: `[ROOT]/foo/target/debug/build/published-[HASH]/build-script-build` ([EXIT_STATUS]: 101)\n  --- stdout\n  cargo::warning=foo\n  cargo::warning=bar\n\n  --- stderr\n...\n[..]dependency panicked[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn log_messages_emitted_when_dependency_logs_errors() {\n    Package::new(\"published\", \"0.1.0\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::warning=foo\");\n                    println!(\"cargo::warning=bar\");\n                    println!(\"cargo::error=foo err\");\n                    println!(\"cargo::error=bar err\");\n                }\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"published\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                published = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] published v0.1.0 (registry `dummy-registry`)\n[COMPILING] published v0.1.0\n[WARNING] published@0.1.0: foo\n[WARNING] published@0.1.0: bar\n[ERROR] published@0.1.0: foo err\n[ERROR] published@0.1.0: bar err\n[ERROR] build script logged errors\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warnings_hidden_for_upstream() {\n    Package::new(\"bar\", \"0.1.0\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::warning=foo\");\n                    println!(\"cargo::warning=bar\");\n                }\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[COMPILING] bar v0.1.0\n[RUNNING] `rustc --crate-name build_script_build [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/bar-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name bar [..]`\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warnings_printed_on_vv() {\n    Package::new(\"bar\", \"0.1.0\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::warning=foo\");\n                    println!(\"cargo::warning=bar\");\n                }\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -vv\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[COMPILING] bar v0.1.0\n[RUNNING] `[..] rustc --crate-name build_script_build [..]`\n[RUNNING] `[..] [ROOT]/foo/target/debug/build/bar-[HASH]/build-script-build`\n[WARNING] bar@0.1.0: foo\n[WARNING] bar@0.1.0: bar\n[RUNNING] `[..] rustc --crate-name bar [..]`\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn output_shows_on_vv() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::io::prelude::*;\n\n                fn main() {\n                    std::io::stderr().write_all(b\"stderr\\n\").unwrap();\n                    std::io::stdout().write_all(b\"stdout\\n\").unwrap();\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -vv\")\n        .with_stdout_data(str![[r#\"\n[foo 0.5.0] stdout\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build [..]`\n[RUNNING] `[..] [ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[foo 0.5.0] stderr\n[RUNNING] `[..] rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn links_with_dots() {\n    let target = rustc_host();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n                links = \"a.b\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-search=bar\")\n                }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}.'a.b']\n                    rustc-link-search = [\"foo\"]\n                \"#,\n                target\n            ),\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -L foo`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustc_and_rustdoc_set_correctly() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                  use std::env;\n\n                  fn main() {\n                      assert_eq!(env::var(\"RUSTC\").unwrap(), \"rustc\");\n                      assert_eq!(env::var(\"RUSTDOC\").unwrap(), \"rustdoc\");\n                  }\n            \"#,\n        )\n        .build();\n    p.cargo(\"bench\").run();\n}\n\n#[cargo_test]\nfn cfg_env_vars_available() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n\n                fn main() {\n                    let fam = env::var(\"CARGO_CFG_TARGET_FAMILY\").unwrap();\n                    if cfg!(unix) {\n                        assert!(fam.contains(\"unix\"));\n                    } else if cfg!(windows) {\n                        assert!(fam.contains(\"windows\"));\n                    }\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"bench\").run();\n}\n\n#[cargo_test]\nfn switch_features_rerun() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [features]\n                foo = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    println!(include_str!(concat!(env!(\"OUT_DIR\"), \"/output\")));\n                }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                use std::fs;\n                use std::path::Path;\n\n                fn main() {\n                    let out_dir = env::var_os(\"OUT_DIR\").unwrap();\n                    let output = Path::new(&out_dir).join(\"output\");\n\n                    if env::var_os(\"CARGO_FEATURE_FOO\").is_some() {\n                        fs::write(output, \"foo\").unwrap();\n                    } else {\n                        fs::write(output, \"bar\").unwrap();\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v --features=foo\").run();\n    p.rename_run(\"foo\", \"with_foo\")\n        .with_stdout_data(str![[r#\"\nfoo\n\n\"#]])\n        .run();\n    p.cargo(\"build -v\").run();\n    p.rename_run(\"foo\", \"without_foo\")\n        .with_stdout_data(str![[r#\"\nbar\n\n\"#]])\n        .run();\n    p.cargo(\"build -v --features=foo\").run();\n    p.rename_run(\"foo\", \"with_foo2\")\n        .with_stdout_data(str![[r#\"\nfoo\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn assume_build_script_when_build_rs_present() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    if ! cfg!(foo) {\n                        panic!(\"the build script was not run\");\n                    }\n                }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-cfg=foo\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run -v\").run();\n}\n\n#[cargo_test]\nfn if_build_set_to_false_dont_treat_build_rs_as_build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = false\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    if cfg!(foo) {\n                        panic!(\"the build script was run\");\n                    }\n                }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-cfg=foo\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run -v\").run();\n}\n\n#[cargo_test]\nfn deterministic_rustc_dependency_flags() {\n    // This bug is non-deterministic hence the large number of dependencies\n    // in the hopes it will have a much higher chance of triggering it.\n\n    Package::new(\"dep1\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep1\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-flags=-L native=test1\");\n                }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    Package::new(\"dep2\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep2\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-flags=-L native=test2\");\n                }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    Package::new(\"dep3\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep3\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-flags=-L native=test3\");\n                }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    Package::new(\"dep4\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep4\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-flags=-L native=test4\");\n                }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                dep1 = \"*\"\n                dep2 = \"*\"\n                dep3 = \"*\"\n                dep4 = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\").with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustc --crate-name foo [..] -L native=test1 -L native=test2 -L native=test3 -L native=test4`\n...\n\"#]]).run();\n}\n\n#[cargo_test]\nfn links_duplicates_with_cycle() {\n    // this tests that the links_duplicates are caught at resolver time\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"a\"\n                build = \"build.rs\"\n\n                [dependencies.a]\n                path = \"a\"\n\n                [dev-dependencies]\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"a\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\"a/build.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = { path = \"..\" }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to select a version for `a`.\n    ... required by package `foo v0.5.0 ([ROOT]/foo)`\nversions that meet the requirements `*` are: 0.5.0\n\npackage `a` links to the native library `a`, but it conflicts with a previous package which links to `a` as well:\npackage `foo v0.5.0 ([ROOT]/foo)`\nOnly one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the `links = \"a\"` value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.\n\nfailed to select a version for `a` which could resolve this conflict\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rename_with_link_search_path() {\n    _rename_with_link_search_path(\n        false,\n        str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/bar[EXE]`\n\n\"#]],\n    );\n}\n\n#[cargo_test]\n#[cfg_attr(\n    target_os = \"macos\",\n    ignore = \"don't have a cdylib cross target on macos\"\n)]\nfn rename_with_link_search_path_cross() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    _rename_with_link_search_path(\n        true,\n        str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/[ALT_TARGET]/debug/bar[EXE]`\n\n\"#]],\n    );\n}\n\nfn _rename_with_link_search_path(cross: bool, expected: impl IntoData) {\n    let target_arg = if cross {\n        format!(\" --target={}\", cross_compile::alternate())\n    } else {\n        \"\".to_string()\n    };\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                crate-type = [\"cdylib\"]\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"#[no_mangle] pub extern \"C\" fn cargo_test_foo() {}\"#,\n        );\n    let p = p.build();\n\n    p.cargo(&format!(\"build{}\", target_arg)).run();\n\n    let p2 = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                use std::fs;\n                use std::path::PathBuf;\n\n                fn main() {\n                    // Move the `libfoo.so` from the root of our project into the\n                    // build directory. This way Cargo should automatically manage\n                    // `LD_LIBRARY_PATH` and such.\n                    let root = PathBuf::from(env::var_os(\"CARGO_MANIFEST_DIR\").unwrap());\n                    let file = format!(\"{}foo{}\", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX);\n                    let src = root.join(&file);\n\n                    let dst_dir = PathBuf::from(env::var_os(\"OUT_DIR\").unwrap());\n                    let dst = dst_dir.join(&file);\n\n                    fs::copy(&src, &dst).unwrap();\n                    // handle windows, like below\n                    drop(fs::copy(root.join(\"foo.dll.lib\"), dst_dir.join(\"foo.dll.lib\")));\n\n                    println!(\"cargo::rerun-if-changed=build.rs\");\n                    if cfg!(target_env = \"msvc\") {\n                        println!(\"cargo::rustc-link-lib=foo.dll\");\n                    } else {\n                        println!(\"cargo::rustc-link-lib=foo\");\n                    }\n                    println!(\"cargo::rustc-link-search=all={}\",\n                             dst.parent().unwrap().display());\n                }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                extern \"C\" {\n                    #[link_name = \"cargo_test_foo\"]\n                    fn foo();\n                }\n\n                fn main() {\n                    unsafe { foo(); }\n                }\n            \"#,\n        );\n    let p2 = p2.build();\n\n    // Move the output `libfoo.so` into the directory of `p2`, and then delete\n    // the `p` project. On macOS, the `libfoo.dylib` artifact references the\n    // original path in `p` so we want to make sure that it can't find it (hence\n    // the deletion).\n    let root = if cross {\n        p.root()\n            .join(\"target\")\n            .join(cross_compile::alternate())\n            .join(\"debug\")\n            .join(\"deps\")\n    } else {\n        p.root().join(\"target\").join(\"debug\").join(\"deps\")\n    };\n    let file = format!(\"{}foo{}\", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX);\n    let src = root.join(&file);\n\n    let dst = p2.root().join(&file);\n\n    fs::copy(&src, &dst).unwrap();\n    // copy the import library for windows, if it exists\n    drop(fs::copy(\n        &root.join(\"foo.dll.lib\"),\n        p2.root().join(\"foo.dll.lib\"),\n    ));\n    remove_dir_all(p.root()).unwrap();\n\n    // Everything should work the first time\n    p2.cargo(&format!(\"run{}\", target_arg)).run();\n\n    // Now rename the root directory and rerun `cargo run`. Not only should we\n    // not build anything but we also shouldn't crash.\n    let mut new = p2.root();\n    new.pop();\n    new.push(\"bar2\");\n\n    // For whatever reason on Windows right after we execute a binary it's very\n    // unlikely that we're able to successfully delete or rename that binary.\n    // It's not really clear why this is the case or if it's a bug in Cargo\n    // holding a handle open too long. In an effort to reduce the flakiness of\n    // this test though we throw this in a loop\n    //\n    // For some more information see #5481 and rust-lang/rust#48775\n    let mut i = 0;\n    loop {\n        let error = match fs::rename(p2.root(), &new) {\n            Ok(()) => break,\n            Err(e) => e,\n        };\n        i += 1;\n        if !cfg!(windows) || error.kind() != io::ErrorKind::PermissionDenied || i > 10 {\n            panic!(\"failed to rename: {}\", error);\n        }\n        println!(\"assuming {} is spurious, waiting to try again\", error);\n        thread::sleep(slow_cpu_multiplier(100));\n    }\n\n    p2.cargo(&format!(\"run{}\", target_arg))\n        .cwd(&new)\n        .with_stderr_data(expected)\n        .run();\n}\n\n#[cargo_test]\nfn optional_build_script_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\", optional = true }\n\n                [build-dependencies]\n                bar = { path = \"bar\", optional = true }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                #[cfg(feature = \"bar\")]\n                extern crate bar;\n\n                fn main() {\n                    #[cfg(feature = \"bar\")] {\n                        println!(\"cargo::rustc-env=FOO={}\", bar::bar());\n                        return\n                    }\n                    println!(\"cargo::rustc-env=FOO=0\");\n                }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[cfg(feature = \"bar\")]\n                extern crate bar;\n\n                fn main() {\n                    println!(\"{}\", env!(\"FOO\"));\n                }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() -> u32 { 1 }\");\n    let p = p.build();\n\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\n0\n\n\"#]])\n        .run();\n    p.cargo(\"run --features bar\")\n        .with_stdout_data(str![[r#\"\n1\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn optional_build_dep_and_required_normal_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            bar = { path = \"./bar\", optional = true }\n\n            [build-dependencies]\n            bar = { path = \"./bar\" }\n            \"#,\n        )\n        .file(\"build.rs\", \"extern crate bar; fn main() { bar::bar(); }\")\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[cfg(feature = \"bar\")]\n                extern crate bar;\n\n                fn main() {\n                    #[cfg(feature = \"bar\")] {\n                        println!(\"{}\", bar::bar());\n                    }\n                    #[cfg(not(feature = \"bar\"))] {\n                        println!(\"0\");\n                    }\n                }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() -> u32 { 1 }\");\n    let p = p.build();\n\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\n0\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --all-features\")\n        .with_stdout_data(str![[r#\"\n1\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn using_rerun_if_changed_does_not_rebuild() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rerun-if-changed=build.rs\");\n                }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn links_interrupted_can_restart() {\n    // Test for a `links` dependent build script getting canceled and then\n    // restarted. Steps:\n    // 1. Build to establish fingerprints.\n    // 2. Change something (an env var in this case) that triggers the\n    //    dependent build script to run again. Kill the top-level build script\n    //    while it is running (such as hitting Ctrl-C).\n    // 3. Run the build again, it should re-run the build script.\n    let bar = project()\n        .at(\"bar\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.5.0\"\n            edition = \"2015\"\n            authors = []\n            links = \"foo\"\n            build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                println!(\"cargo::rerun-if-env-changed=SOMEVAR\");\n            }\n            \"#,\n        )\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies.bar]\n                path = '{}'\n                \"#,\n                bar.root().display()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n            use std::env;\n            fn main() {\n                println!(\"cargo::metadata=rebuild-if-changed=build.rs\");\n                if std::path::Path::new(\"abort\").exists() {\n                    panic!(\"Crash!\");\n                }\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    // Simulate the user hitting Ctrl-C during a build.\n    p.change_file(\"abort\", \"\");\n    // Set SOMEVAR to trigger a rebuild.\n    p.cargo(\"build\")\n        .env(\"SOMEVAR\", \"1\")\n        .with_stderr_data(str![[r#\"\n...\n  Crash!\n...\n\"#]])\n        .with_status(101)\n        .run();\n    fs::remove_file(p.root().join(\"abort\")).unwrap();\n    // Try again without aborting the script.\n    // ***This is currently broken, the script does not re-run.\n    p.cargo(\"build -v\")\n        .env(\"SOMEVAR\", \"1\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dev_dep_with_links() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"x\"\n\n                [dev-dependencies]\n                bar = { path = \"./bar\" }\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"y\"\n\n                [dependencies]\n                foo = { path = \"..\" }\n            \"#,\n        )\n        .file(\"bar/build.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check --tests\").run();\n}\n\n#[cargo_test]\nfn rerun_if_directory() {\n    if !symlink_supported() {\n        return;\n    }\n\n    // rerun-if-changed of a directory should rerun if any file in the directory changes.\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rerun-if-changed=somedir\");\n                }\n            \"#,\n        )\n        .build();\n\n    let dirty = |expected| {\n        p.cargo(\"check -v\").with_stderr_data(expected).run();\n    };\n\n    let fresh = || {\n        p.cargo(\"check\")\n            .with_stderr_data(\n                \"\\\n[FINISHED] [..]\n\",\n            )\n            .run();\n    };\n\n    // Start with a missing directory.\n    dirty(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build[..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    // Because the directory doesn't exist, it will trigger a rebuild every time.\n    // https://github.com/rust-lang/cargo/issues/6003\n    dirty(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `somedir` is missing\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n\n    // Empty directory.\n    fs::create_dir(p.root().join(\"somedir\")).unwrap();\n    dirty(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `somedir` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    fresh();\n\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n\n    // Add a file.\n    p.change_file(\"somedir/foo\", \"\");\n    p.change_file(\"somedir/bar\", \"\");\n    dirty(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `somedir` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    fresh();\n\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n\n    // Add a symlink.\n    p.symlink(\"foo\", \"somedir/link\");\n    dirty(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `somedir` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    fresh();\n\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n\n    // Move the symlink.\n    fs::remove_file(p.root().join(\"somedir/link\")).unwrap();\n    p.symlink(\"bar\", \"somedir/link\");\n    dirty(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `somedir` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    fresh();\n\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n\n    // Remove a file.\n    fs::remove_file(p.root().join(\"somedir/foo\")).unwrap();\n    dirty(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `somedir` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    fresh();\n}\n\n#[cargo_test]\nfn rerun_if_published_directory() {\n    // build script of a dependency contains a `rerun-if-changed` pointing to a directory\n    Package::new(\"mylib-sys\", \"1.0.0\")\n        .file(\"mylib/balrog.c\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    // Changing to mylib/balrog.c will not trigger a rebuild\n                    println!(\"cargo::rerun-if-changed=mylib\");\n                }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                mylib-sys = \"1.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    // Delete registry src to make directories being recreated with the latest timestamp.\n    cargo_home().join(\"registry/src\").rm_rf();\n\n    p.cargo(\"check --verbose\")\n        .with_stderr_data(str![[r#\"\n[FRESH] mylib-sys v1.0.0\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Upgrade of a package should still trigger a rebuild\n    Package::new(\"mylib-sys\", \"1.0.1\")\n        .file(\"mylib/balrog.c\", \"\")\n        .file(\"mylib/balrog.h\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                    fn main() {\n                        println!(\"cargo::rerun-if-changed=mylib\");\n                    }\n                \"#,\n        )\n        .publish();\n    p.cargo(\"update\").run();\n    p.cargo(\"fetch\").run();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] mylib-sys v1.0.1\n[RUNNING] `rustc --crate-name build_script_build [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/mylib-sys-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name mylib_sys [..]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_with_dep_metadata() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    assert_eq!(std::env::var(\"DEP_BAR_FOO\").unwrap(), \"bar\");\n                }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                links = 'bar'\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"bar/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::metadata=foo=bar\");\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"test --lib\").run();\n}\n\n#[cargo_test]\nfn duplicate_script_with_extra_env() {\n    // Test where a build script is run twice, that emits different rustc-env\n    // and rustc-cfg values. In this case, one is run for host, the other for\n    // target.\n    if !cross_compile_can_run_on_host() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"pm\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                pm = { path = \"../pm\" }\n            \"#,\n        )\n        .file(\n            \"foo/src/lib.rs\",\n            &r#\"\n                //! ```rust\n                //! #[cfg(not(mycfg=\"{target}\"))]\n                //! compile_error!{\"expected mycfg set\"}\n                //! assert_eq!(env!(\"CRATE_TARGET\"), \"{target}\");\n                //! assert_eq!(std::env::var(\"CRATE_TARGET\").unwrap(), \"{target}\");\n                //! ```\n\n                #[test]\n                fn check_target() {\n                    #[cfg(not(mycfg=\"{target}\"))]\n                    compile_error!{\"expected mycfg set\"}\n                    // Compile-time assertion.\n                    assert_eq!(env!(\"CRATE_TARGET\"), \"{target}\");\n                    // Run-time assertion.\n                    assert_eq!(std::env::var(\"CRATE_TARGET\").unwrap(), \"{target}\");\n                }\n            \"#\n            .replace(\"{target}\", target),\n        )\n        .file(\n            \"foo/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-env=CRATE_TARGET={}\", std::env::var(\"TARGET\").unwrap());\n                    println!(\"cargo::rustc-cfg=mycfg=\\\"{}\\\"\", std::env::var(\"TARGET\").unwrap());\n                }\n            \"#,\n        )\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pm\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                proc-macro = true\n                # This is just here to speed things up.\n                doctest = false\n\n                [dev-dependencies]\n                foo = { path = \"../foo\" }\n            \"#,\n        )\n        .file(\"pm/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test --workspace --target\")\n        .arg(&target)\n        .with_stdout_data(str![[r#\"\n...\ntest check_target ... ok\n...\n\"#]])\n        .run();\n\n    p.cargo(\"test --workspace --doc --target\")\n        .arg(&target)\n        .with_stdout_data(str![[r#\"\n...\ntest foo/src/lib.rs - (line 2) ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn wrong_output() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::example\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] invalid output in build script of `foo v0.0.1 ([ROOT]/foo)`: `cargo::example`\nExpected a line with `cargo::KEY=VALUE` with an `=` character, but none was found.\nSee https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_closes_stdin() {\n    // Ensure stdin is closed to prevent deadlock.\n    // See https://github.com/rust-lang/cargo/issues/11196\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"fn main() {\n                let mut line = String::new();\n                std::io::stdin().read_line(&mut line).unwrap();\n            }\"#,\n        )\n        .build();\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn test_old_syntax() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                const FOO: &'static str = env!(\"FOO\");\n                fn main() {\n                    println!(\"{}\", FOO);\n                }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"fn main() {\n                println!(\"cargo:rustc-env=FOO=foo\");\n                println!(\"cargo:foo=foo\");\n            }\"#,\n        )\n        .build();\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn test_invalid_old_syntax() {\n    // Unexpected metadata value.\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo:foo\");\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] invalid output in build script of `foo v0.0.1 ([ROOT]/foo)`: `cargo:foo`\nExpected a line with `cargo:KEY=VALUE` with an `=` character, but none was found.\nSee https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_invalid_new_syntax() {\n    // Unexpected metadata value.\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::metadata=foo\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] invalid output in build script of `foo v0.0.1 ([ROOT]/foo)`: `cargo::metadata=foo`\nExpected a line with `cargo::metadata=KEY=VALUE` with an `=` character, but none was found.\nSee https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs.\n\n\"#]])\n        .run();\n    // `cargo::` can not be used with the unknown key.\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::foo=bar\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] invalid output in build script of `foo v0.0.1 ([ROOT]/foo)`: `cargo::foo=bar`\nUnknown key: `foo`.\nSee https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_new_syntax_with_old_msrv() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n                rust-version = \"1.60.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::metadata=foo=bar\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[ERROR] the `cargo::` syntax for build script output instructions was added in Rust 1.77.0, but the minimum supported Rust version of `foo v0.5.0 ([ROOT]/foo)` is 1.60.0.\nSwitch to the old `cargo:foo=bar` syntax instead of `cargo::metadata=foo=bar` (note the single colon).\nSee https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_new_syntax_with_old_msrv_and_reserved_prefix() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n                rust-version = \"1.60.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-check-cfg=cfg(foo)\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[ERROR] the `cargo::` syntax for build script output instructions was added in Rust 1.77.0, but the minimum supported Rust version of `foo v0.5.0 ([ROOT]/foo)` is 1.60.0.\nSwitch to the old `cargo:rustc-check-cfg=cfg(foo)` syntax (note the single colon).\nSee https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_new_syntax_with_old_msrv_and_unknown_prefix() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n                rust-version = \"1.60.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::foo=bar\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[ERROR] the `cargo::` syntax for build script output instructions was added in Rust 1.77.0, but the minimum supported Rust version of `foo v0.5.0 ([ROOT]/foo)` is 1.60.0.\nSee https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_new_syntax_with_compatible_partial_msrv() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n                build = \"build.rs\"\n                rust-version = \"1.77\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::metadata=foo=bar\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_old_syntax_with_old_msrv() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n                rust-version = \"1.60.0\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                const FOO: &'static str = env!(\"FOO\");\n                fn main() {\n                    println!(\"{}\", FOO);\n                }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"fn main() {\n                println!(\"cargo:rustc-env=FOO=foo\");\n                println!(\"cargo:foo=foo\");\n            }\"#,\n        )\n        .build();\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn build_script_rerun_when_target_rustflags_change() {\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                #[cfg(enable)]\n                println!(\"hello\");\n            }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n            use std::env;\n\n            fn main() {\n                println!(\"cargo::rustc-check-cfg=cfg(enable)\");\n                if let Ok(rustflags) = env::var(\"CARGO_ENCODED_RUSTFLAGS\") {\n                    if !rustflags.is_empty() {\n                        println!(\"cargo::rustc-cfg=enable\");\n                    }\n                }\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run --target\")\n        .arg(&target)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/[HOST_TARGET]/debug/foo[EXE]`\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --target\")\n        .arg(&target)\n        .env(\"RUSTFLAGS\", \"-C opt-level=3\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/[HOST_TARGET]/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn links_overrides_with_target_applies_to_host() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"mylib-sys\"\n                edition = \"2021\"\n                version = \"0.0.1\"\n                authors = []\n                links = \"mylib\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"bad file\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .args(&[\n            \"-Ztarget-applies-to-host\",\n            \"--config\",\n            \"target-applies-to-host=false\",\n        ])\n        .args(&[\n            \"--config\",\n            &format!(r#\"target.{}.mylib.rustc-link-search=[\"foo\"]\"#, rustc_host()),\n        ])\n        .with_stderr_data(str![[r#\"\n[COMPILING] mylib-sys v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name mylib_sys [..] -L foo`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn directory_with_leading_underscore() {\n    let p: cargo_test_support::Project = git::new(\"foo\", |p| {\n        p.no_manifest()\n            .file(\n                \"_foo/foo/Cargo.toml\",\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n                build = \"build.rs\"\n            \"#,\n            )\n            .file(\"_foo/foo/src/main.rs\", \"fn main() {}\")\n            .file(\"_foo/foo/build.rs\", \"fn main() { }\")\n    });\n    p.cargo(\"check --manifest-path=_foo/foo/Cargo.toml -v\")\n        .with_status(0)\n        .run();\n}\n\n#[cargo_test]\nfn linker_search_path_preference() {\n    // This isn't strictly the exact scenario that causes the issue, but it's the shortest demonstration\n    // of the issue.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                build = \"build.rs\"\n\n                [dependencies]\n                a = { path = \"a\" }\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    let out_dir = std::env::var(\"OUT_DIR\").unwrap();\n                    println!(\"cargo::rustc-link-search=/usr/lib\");\n                    println!(\"cargo::rustc-link-search={}/libs2\", out_dir);\n                    println!(\"cargo::rustc-link-search=/lib\");\n                    println!(\"cargo::rustc-link-search={}/libs1\", out_dir);\n                }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/build.rs\",\n            r#\"\n                fn main() {\n                    let out_dir = std::env::var(\"OUT_DIR\").unwrap();\n                    println!(\"cargo::rustc-link-search=/usr/lib3\");\n                    println!(\"cargo::rustc-link-search={}/libsA.2\", out_dir);\n                    println!(\"cargo::rustc-link-search=/lib3\");\n                    println!(\"cargo::rustc-link-search={}/libsA.1\", out_dir);\n                }\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"b/build.rs\",\n            r#\"\n                fn main() {\n                    let out_dir = std::env::var(\"OUT_DIR\").unwrap();\n                    println!(\"cargo::rustc-link-search=/usr/lib2\");\n                    println!(\"cargo::rustc-link-search={}/libsB.1\", out_dir);\n                    println!(\"cargo::rustc-link-search=/lib2\");\n                    println!(\"cargo::rustc-link-search={}/libsB.2\", out_dir);\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\").with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustc --crate-name foo [..] -L [ROOT]/foo/target/debug/build/foo-[HASH]/out/libs2 -L [ROOT]/foo/target/debug/build/foo-[HASH]/out/libs1 -L [ROOT]/foo/target/debug/build/a-[HASH]/out/libsA.2 -L [ROOT]/foo/target/debug/build/a-[HASH]/out/libsA.1 -L [ROOT]/foo/target/debug/build/b-[HASH]/out/libsB.1 -L [ROOT]/foo/target/debug/build/b-[HASH]/out/libsB.2 -L /usr/lib -L /lib -L /usr/lib3 -L /lib3 -L /usr/lib2 -L /lib2`\n...\n\"#]]).run();\n}\n"
  },
  {
    "path": "tests/testsuite/build_script_env.rs",
    "content": "//! Tests for build.rs rerun-if-env-changed and rustc-env\n\nuse crate::prelude::*;\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::project;\nuse cargo_test_support::sleep_ms;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn rerun_if_env_changes() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rerun-if-env-changed=FOO\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .env(\"FOO\", \"bar\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .env(\"FOO\", \"baz\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .env(\"FOO\", \"baz\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rerun_if_env_or_file_changes() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rerun-if-env-changed=FOO\");\n                    println!(\"cargo::rerun-if-changed=foo\");\n                }\n            \"#,\n        )\n        .file(\"foo\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .env(\"FOO\", \"bar\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .env(\"FOO\", \"bar\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    sleep_ms(1000);\n    p.change_file(\"foo\", \"// modified\");\n    p.cargo(\"check\")\n        .env(\"FOO\", \"bar\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustc_bootstrap() {\n    let build_rs = r#\"\n        fn main() {\n            println!(\"cargo::rustc-env=RUSTC_BOOTSTRAP=1\");\n        }\n    \"#;\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"has-dashes\", \"0.0.1\"))\n        .file(\n            \"src/lib.rs\",\n            \"#![allow(internal_features)] #![feature(rustc_attrs)]\",\n        )\n        .file(\"build.rs\", build_rs)\n        .build();\n    // RUSTC_BOOTSTRAP unset on stable should error\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] has-dashes v0.0.1 ([ROOT]/foo)\n[ERROR] cannot set `RUSTC_BOOTSTRAP=1` from build script of `has-dashes v0.0.1 ([ROOT]/foo)`.\n[NOTE] crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.\n[HELP] If you're sure you want to do this in your project, set the environment variable `RUSTC_BOOTSTRAP=has_dashes` before running cargo instead.\n\n\"#]])\n        .with_status(101)\n        .run();\n    // nightly should warn whether or not RUSTC_BOOTSTRAP is set\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"RUSTC_BOOTSTRAP\"])\n        // NOTE: uses RUSTC_BOOTSTRAP so it will be propagated to rustc\n        // (this matters when tests are being run with a beta or stable cargo)\n        .env(\"RUSTC_BOOTSTRAP\", \"1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] has-dashes v0.0.1 ([ROOT]/foo)\n[WARNING] has-dashes@0.0.1: cannot set `RUSTC_BOOTSTRAP=1` from build script of `has-dashes v0.0.1 ([ROOT]/foo)`.\n[NOTE] crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // RUSTC_BOOTSTRAP set to the name of the library should warn\n    p.cargo(\"check\")\n        .env(\"RUSTC_BOOTSTRAP\", \"has_dashes\")\n        .with_stderr_data(str![[r#\"\n[WARNING] has-dashes@0.0.1: cannot set `RUSTC_BOOTSTRAP=1` from build script of `has-dashes v0.0.1 ([ROOT]/foo)`.\n[NOTE] crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // RUSTC_BOOTSTRAP set to some random value should error\n    p.cargo(\"check\")\n        .env(\"RUSTC_BOOTSTRAP\", \"bar\")\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot set `RUSTC_BOOTSTRAP=1` from build script of `has-dashes v0.0.1 ([ROOT]/foo)`.\n[NOTE] crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.\n[HELP] If you're sure you want to do this in your project, set the environment variable `RUSTC_BOOTSTRAP=has_dashes` before running cargo instead.\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    // Tests for binaries instead of libraries\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.1\"))\n        .file(\n            \"src/main.rs\",\n            \"#![allow(internal_features)] #![feature(rustc_attrs)] fn main() {}\",\n        )\n        .file(\"build.rs\", build_rs)\n        .build();\n    // nightly should warn when there's no library whether or not RUSTC_BOOTSTRAP is set\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"RUSTC_BOOTSTRAP\"])\n        // NOTE: uses RUSTC_BOOTSTRAP so it will be propagated to rustc\n        // (this matters when tests are being run with a beta or stable cargo)\n        .env(\"RUSTC_BOOTSTRAP\", \"1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] foo@0.0.1: cannot set `RUSTC_BOOTSTRAP=1` from build script of `foo v0.0.1 ([ROOT]/foo)`.\n[NOTE] crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // RUSTC_BOOTSTRAP conditionally set when there's no library should error (regardless of the value)\n    p.cargo(\"check\")\n        .env(\"RUSTC_BOOTSTRAP\", \"foo\")\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot set `RUSTC_BOOTSTRAP=1` from build script of `foo v0.0.1 ([ROOT]/foo)`.\n[NOTE] crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.\n[HELP] If you're sure you want to do this in your project, set the environment variable `RUSTC_BOOTSTRAP=1` before running cargo instead.\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn build_script_env_verbose() {\n    let build_rs = r#\"\n        fn main() {}\n    \"#;\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"verbose-build\", \"0.0.1\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", build_rs)\n        .build();\n\n    p.cargo(\"check -vv\")\n        .with_stderr_data(\n            \"\\\n...\n[RUNNING] `[..]CARGO=[..]build-script-build`\n...\",\n        )\n        .run();\n}\n\n#[cargo_test]\n#[cfg(target_arch = \"x86_64\")]\nfn build_script_sees_cfg_target_feature() {\n    let build_rs = r#\"\n        fn main() {\n            let cfg = std::env::var(\"CARGO_CFG_TARGET_FEATURE\").unwrap();\n            eprintln!(\"CARGO_CFG_TARGET_FEATURE={cfg}\");\n        }\n    \"#;\n\n    let configs = [\n        r#\"\n            [build]\n            rustflags = [\"-Ctarget-feature=+sse4.1,+sse4.2\"]\n        \"#,\n        r#\"\n            [target.'cfg(target_arch = \"x86_64\")']\n            rustflags = [\"-Ctarget-feature=+sse4.1,+sse4.2\"]\n        \"#,\n    ];\n\n    for config in configs {\n        let p = project()\n            .file(\".cargo/config.toml\", config)\n            .file(\"src/lib.rs\", r#\"\"#)\n            .file(\"build.rs\", build_rs)\n            .build();\n\n        p.cargo(\"check -vv\")\n            .with_stderr_data(\n                \"\\\n...\n[foo 0.0.1] CARGO_CFG_TARGET_FEATURE=[..]sse4.2[..]\n...\n[..]-Ctarget-feature=[..]+sse4.2[..]\n...\",\n            )\n            .run();\n    }\n}\n\n/// In this test, the cfg is self-contradictory. There's no *right* answer as to\n/// what the value of `RUSTFLAGS` should be in this case. We chose to give a\n/// warning. However, no matter what we do, it's important that build scripts\n/// and rustc see a consistent picture\n#[cargo_test]\nfn cfg_paradox() {\n    let build_rs = r#\"\n        fn main() {\n            let cfg = std::env::var(\"CARGO_CFG_BERTRAND\").is_ok();\n            eprintln!(\"cfg!(bertrand)={cfg}\");\n        }\n    \"#;\n\n    let config = r#\"\n        [target.'cfg(not(bertrand))']\n        rustflags = [\"--cfg=bertrand\"]\n    \"#;\n\n    let p = project()\n        .file(\".cargo/config.toml\", config)\n        .file(\"src/lib.rs\", r#\"\"#)\n        .file(\"build.rs\", build_rs)\n        .build();\n\n    p.cargo(\"check -vv\")\n        .with_stderr_data(\n            \"\\\n[WARNING] non-trivial mutual dependency between target-specific configuration and RUSTFLAGS\n...\n[foo 0.0.1] cfg!(bertrand)=true\n...\n[..]--cfg=bertrand[..]\n...\",\n        )\n        .run();\n}\n\n/// This test checks how Cargo handles rustc cfgs which are defined both with\n/// and without a value. The expected behavior is that the environment variable\n/// is going to contain all the values.\n///\n/// For example, this configuration:\n/// ```\n/// target_has_atomic\n/// target_has_atomic=\"16\"\n/// target_has_atomic=\"32\"\n/// target_has_atomic=\"64\"\n/// target_has_atomic=\"8\"\n/// target_has_atomic=\"ptr\"\n/// ```\n///\n/// Should result in the following environment variable:\n///\n/// ```\n/// CARGO_CFG_TARGET_HAS_ATOMIC=16,32,64,8,ptr\n/// ```\n///\n/// On the other hand, configuration symbols without any value should result in\n/// an empty string.\n///\n/// For example, this configuration:\n///\n/// ```\n/// target_thread_local\n/// ```\n///\n/// Should result in the following environment variable:\n///\n/// ```\n/// CARGO_CFG_TARGET_THREAD_LOCAL=\n/// ```\n#[cargo_test(nightly, reason = \"affected rustc cfg is unstable\")]\n#[cfg(target_arch = \"x86_64\")]\nfn rustc_cfg_with_and_without_value() {\n    let build_rs = r#\"\n        fn main() {\n            let cfg = std::env::var(\"CARGO_CFG_TARGET_HAS_ATOMIC\");\n            eprintln!(\"CARGO_CFG_TARGET_HAS_ATOMIC={cfg:?}\");\n            let cfg = std::env::var(\"CARGO_CFG_WINDOWS\");\n            eprintln!(\"CARGO_CFG_WINDOWS={cfg:?}\");\n            let cfg = std::env::var(\"CARGO_CFG_UNIX\");\n            eprintln!(\"CARGO_CFG_UNIX={cfg:?}\");\n        }\n    \"#;\n    let p = project()\n        .file(\"src/lib.rs\", r#\"\"#)\n        .file(\"build.rs\", build_rs)\n        .build();\n\n    let mut check = p.cargo(\"check -vv\");\n    #[cfg(target_has_atomic = \"64\")]\n    check.with_stderr_data(\n        \"\\\n...\n[foo 0.0.1] CARGO_CFG_TARGET_HAS_ATOMIC=Ok(\\\"[..]64[..]\\\")\n...\",\n    );\n    #[cfg(windows)]\n    check.with_stderr_data(\n        \"\\\n...\n[foo 0.0.1] CARGO_CFG_WINDOWS=Ok(\\\"\\\")\n...\",\n    );\n    #[cfg(unix)]\n    check.with_stderr_data(\n        \"\\\n...\n[foo 0.0.1] CARGO_CFG_UNIX=Ok(\\\"\\\")\n...\",\n    );\n    check.run();\n}\n\n#[cargo_test]\nfn rerun_if_env_exists_in_config() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                println!(\"cargo::rerun-if-env-changed=FOO\");\n            }\n        \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [env]\n            FOO = \"foo\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(r#\"check --config 'env.FOO=\"bar\"'\"#)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rerun_if_env_newly_added_in_config() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                println!(\"cargo::rerun-if-env-changed=FOO\");\n            }\n        \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(r#\"check --config 'env.FOO=\"foo\"'\"#)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_script_debug_assertions_dev() {\n    // Test that CARGO_CFG_DEBUG_ASSERTIONS is set in dev profile (default)\n    let build_rs = r#\"\n        fn main() {\n            let has_debug_assertions = std::env::var_os(\"CARGO_CFG_DEBUG_ASSERTIONS\").is_some();\n            assert!(has_debug_assertions, \"CARGO_CFG_DEBUG_ASSERTIONS should be set in dev profile\");\n        }\n    \"#;\n\n    let p = project()\n        .file(\"src/lib.rs\", r#\"\"#)\n        .file(\"build.rs\", build_rs)\n        .build();\n\n    // Default dev profile has debug-assertions enabled\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn build_script_debug_assertions_release() {\n    // Test that CARGO_CFG_DEBUG_ASSERTIONS is NOT set in release profile (default)\n    let build_rs = r#\"\n        fn main() {\n            let has_debug_assertions = std::env::var_os(\"CARGO_CFG_DEBUG_ASSERTIONS\").is_some();\n            assert!(!has_debug_assertions, \"CARGO_CFG_DEBUG_ASSERTIONS should NOT be set in release profile\");\n        }\n    \"#;\n\n    let p = project()\n        .file(\"src/lib.rs\", r#\"\"#)\n        .file(\"build.rs\", build_rs)\n        .build();\n\n    // Release profile has debug-assertions disabled by default\n    p.cargo(\"check --release\").run();\n}\n\n#[cargo_test]\nfn build_script_debug_assertions_override_dev() {\n    // Test that CARGO_CFG_DEBUG_ASSERTIONS respects profile overrides\n    // Dev profile with debug-assertions explicitly DISABLED\n    let build_rs = r#\"\n        fn main() {\n            let has_debug_assertions = std::env::var_os(\"CARGO_CFG_DEBUG_ASSERTIONS\").is_some();\n            assert!(!has_debug_assertions, \"CARGO_CFG_DEBUG_ASSERTIONS should NOT be set when dev profile disables it\");\n        }\n    \"#;\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n\n                [profile.dev]\n                debug-assertions = false\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\"\"#)\n        .file(\"build.rs\", build_rs)\n        .build();\n\n    // Dev profile with debug-assertions explicitly disabled\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn build_script_debug_assertions_override_release() {\n    // Test that CARGO_CFG_DEBUG_ASSERTIONS respects profile overrides\n    // Release profile with debug-assertions explicitly ENABLED\n    let build_rs = r#\"\n        fn main() {\n            let has_debug_assertions = std::env::var_os(\"CARGO_CFG_DEBUG_ASSERTIONS\").is_some();\n            assert!(has_debug_assertions, \"CARGO_CFG_DEBUG_ASSERTIONS should be set when release profile enables it\");\n        }\n    \"#;\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n\n                [profile.release]\n                debug-assertions = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\"\"#)\n        .file(\"build.rs\", build_rs)\n        .build();\n\n    // Release profile with debug-assertions explicitly enabled\n    p.cargo(\"check --release\").run();\n}\n\n#[cargo_test]\nfn build_script_debug_assertions_build_override() {\n    let build_rs = r#\"\n        fn main() {\n            let profile = std::env::var(\"PROFILE\").unwrap();\n            if profile == \"debug\" {\n                assert!(!cfg!(debug_assertions));\n            } else if profile == \"release\" {\n                assert!(cfg!(debug_assertions));\n            }\n        }\n    \"#;\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n\n                [profile.dev.build-override]\n                debug-assertions = false\n\n                [profile.release.build-override]\n                debug-assertions = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\"\"#)\n        .file(\"build.rs\", build_rs)\n        .build();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"check --release\").run();\n}\n"
  },
  {
    "path": "tests/testsuite/build_script_extra_link_arg.rs",
    "content": "//! Tests for additional link arguments.\n\n// NOTE: Many of these tests use `without_status()` when passing bogus flags\n// because MSVC link.exe just gives a warning on unknown flags (how helpful!),\n// and other linkers will return an error.\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_bin_manifest, basic_lib_manifest, basic_manifest, project};\n\n#[cargo_test]\nfn build_script_extra_link_arg_bin() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-arg-bins=--this-is-a-bogus-flag\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .without_status()\n        .with_stderr_data(\n            \"\\\n...\n[RUNNING] `rustc --crate-name foo [..]-C link-arg=--this-is-a-bogus-flag[..]\n...\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_script_extra_link_arg_bin_single() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foobar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [[bin]]\n                name = \"foo\"\n                [[bin]]\n                name = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-arg-bins=--bogus-flag-all\");\n                    println!(\"cargo::rustc-link-arg-bin=foo=--bogus-flag-foo\");\n                    println!(\"cargo::rustc-link-arg-bin=bar=--bogus-flag-bar\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .without_status()\n        .with_stderr_data(\n            \"\\\n...\n[RUNNING] `rustc --crate-name foo [..]-C link-arg=--bogus-flag-all -C link-arg=--bogus-flag-foo[..]\n...\",\n        )\n        .with_stderr_data(\n            \"\\\n...\n[RUNNING] `rustc --crate-name bar [..]-C link-arg=--bogus-flag-all -C link-arg=--bogus-flag-bar[..]\n...\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_script_extra_link_arg() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-arg=--this-is-a-bogus-flag\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .without_status()\n        .with_stderr_data(\n            \"\\\n...\n[RUNNING] `rustc --crate-name foo [..]-C link-arg=--this-is-a-bogus-flag[..]\n...\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn link_arg_missing_target() {\n    // Errors when a given target doesn't exist.\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-link-arg-cdylib=--bogus\"); }\"#,\n        )\n        .build();\n\n    // TODO: Uncomment this if cdylib restriction is re-added (see\n    // cdylib_link_arg_transitive below).\n    //     p.cargo(\"check\")\n    //         .with_status(101)\n    //         .with_stderr(\"\\\n    // [COMPILING] foo [..]\n    // error: invalid instruction `cargo::rustc-link-arg-cdylib` from build script of `foo v0.0.1 ([ROOT]/foo)`\n    // The package foo v0.0.1 ([ROOT]/foo) does not have a cdylib target.\n    // \")\n    //         .run();\n\n    p.change_file(\n        \"build.rs\",\n        r#\"fn main() { println!(\"cargo::rustc-link-arg-bins=--bogus\"); }\"#,\n    );\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] invalid instruction `cargo::rustc-link-arg-bins` from build script of `foo v0.0.1 ([ROOT]/foo)`\nThe package foo v0.0.1 ([ROOT]/foo) does not have a bin target.\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"build.rs\",\n        r#\"fn main() { println!(\"cargo::rustc-link-arg-bin=abc=--bogus\"); }\"#,\n    );\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] invalid instruction `cargo::rustc-link-arg-bin` from build script of `foo v0.0.1 ([ROOT]/foo)`\nThe package foo v0.0.1 ([ROOT]/foo) does not have a bin target with the name `abc`.\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"build.rs\",\n        r#\"fn main() { println!(\"cargo::rustc-link-arg-bin=abc\"); }\"#,\n    );\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] invalid instruction `cargo::rustc-link-arg-bin=abc` from build script of `foo v0.0.1 ([ROOT]/foo)`\nThe instruction should have the form cargo::rustc-link-arg-bin=BIN=ARG\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cdylib_link_arg_transitive() {\n    // There was an unintended regression in 1.50 where rustc-link-arg-cdylib\n    // arguments from dependencies were being applied in the parent package.\n    // Previously it was silently ignored.\n    // See https://github.com/rust-lang/cargo/issues/9562\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"cdylib\"]\n\n                [dependencies]\n                bar = {path=\"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"bar/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-arg-cdylib=--bogus\");\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"build -v\")\n        .without_status()\n        .with_stderr_data(\n            \"\\\n...\n[COMPILING] bar v1.0.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 bar/build.rs [..]\n[RUNNING] `[ROOT]/foo/target/debug/build/bar-[HASH]/build-script-build`\n[WARNING] bar@1.0.0: cargo::rustc-link-arg-cdylib was specified in the build script of bar v1.0.0 \\\n([ROOT]/foo/bar), but that package does not contain a cdylib target\n\nAllowing this was an unintended change in the 1.50 release, and may become an error in \\\nthe future. For more information, see <https://github.com/rust-lang/cargo/issues/9562>.\n[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]-C link-arg=--bogus[..]`\n...\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn link_arg_transitive_not_allowed() {\n    // Verify that transitive dependencies don't pass link args.\n    //\n    // Note that rustc-link-arg doesn't have any errors or warnings when it is\n    // unused. Perhaps that could be more aggressive, but it is difficult\n    // since it could be used for test binaries.\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-arg=--bogus\");\n                }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"cdylib\"]\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[COMPILING] bar v1.0.0\n[RUNNING] `rustc --crate-name build_script_build [..]\n[RUNNING] `[ROOT]/foo/target/debug/build/bar-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name bar [..]\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stderr_does_not_contain(\"--bogus\")\n        .run();\n}\n\n#[cargo_test]\nfn link_arg_with_doctest() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! ```\n                //! let x = 5;\n                //! assert_eq!(x, 5);\n                //! ```\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-arg=--this-is-a-bogus-flag\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test --doc -v\")\n        .without_status()\n        .with_stderr_data(\n            \"\\\n...\n[RUNNING] `rustdoc [..]--crate-name foo [..]-C link-arg=--this-is-a-bogus-flag[..]\n...\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_script_extra_link_arg_tests() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"tests/test_foo.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-arg-tests=--this-is-a-bogus-flag\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test -v\")\n        .without_status()\n        .with_stderr_data(\n            \"\\\n...\n[RUNNING] `rustc --crate-name test_foo [..]-C link-arg=--this-is-a-bogus-flag[..]\n...\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_script_extra_link_arg_benches() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"benches/bench_foo.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-arg-benches=--this-is-a-bogus-flag\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench -v\")\n        .without_status()\n        .with_stderr_data(\n            \"\\\n...\n[RUNNING] `rustc --crate-name bench_foo [..]-C link-arg=--this-is-a-bogus-flag[..]\n...\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_script_extra_link_arg_examples() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/example_foo.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-link-arg-examples=--this-is-a-bogus-flag\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v --examples\")\n        .without_status()\n        .with_stderr_data(\n            \"\\\n...\n[RUNNING] `rustc --crate-name example_foo [..]-C link-arg=--this-is-a-bogus-flag[..]\n...\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cdylib_both_forms() {\n    // Cargo accepts two different forms for the cdylib link instruction,\n    // which have the same meaning.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"cdylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-cdylib-link-arg=--bogus-flag-one\");\n                    println!(\"cargo::rustc-link-arg-cdylib=--bogus-flag-two\");\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"build -v\")\n        .without_status()\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..]\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]--crate-type cdylib [..]-C link-arg=--bogus-flag-one -C link-arg=--bogus-flag-two[..]\n...\n\"#]])\n        .run();\n}\n\n// https://github.com/rust-lang/cargo/issues/12663\n#[cargo_test]\nfn cdylib_extra_link_args_should_not_apply_to_unit_tests() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"lib\", \"cdylib\"]\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[test]\n                fn noop() {}\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    // This would fail if cargo passed `-lhack` to building the test because `hack` doesn't exist.\n                    println!(\"cargo::rustc-link-arg-cdylib=-lhack\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test --lib\").run();\n}\n"
  },
  {
    "path": "tests/testsuite/build_scripts_multiple.rs",
    "content": "//! Tests for multiple build scripts feature.\n\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::git;\nuse cargo_test_support::publish::validate_crate_contents;\nuse cargo_test_support::str;\nuse cargo_test_support::{Project, project};\nuse std::fs::File;\n\n#[cargo_test]\nfn build_without_feature_enabled_aborts_with_error() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                build = [\"build1.rs\", \"build2.rs\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build1.rs\", \"fn main() {}\")\n        .file(\"build2.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `multiple-build-scripts` is required\n\n  The package requires the Cargo feature called `multiple-build-scripts`, but that feature is not stabilized in this version of Cargo ([..]).\n  Consider adding `cargo-features = [\"multiple-build-scripts\"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#multiple-build-scripts for more information about the status of this feature.\n\n\"#]])\n        .run();\n}\n\nfn basic_empty_project() -> Project {\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"multiple-build-scripts\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                build = [\"build1.rs\", \"build2.rs\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build1.rs\", \"fn main() {}\")\n        .file(\"build2.rs\", \"fn main() {}\")\n        .build()\n}\n\n#[cargo_test]\nfn empty_multiple_build_script_project() {\n    let p = basic_empty_project();\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_status(0)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_build_scripts_metadata() {\n    let p = basic_empty_project();\n    p.cargo(\"metadata --format-version=1\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_status(0)\n        .with_stderr_data(\"\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2024\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.1.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2024\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/main.rs\",\n          \"test\": true\n        },\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": false,\n          \"doctest\": false,\n          \"edition\": \"2024\",\n          \"kind\": [\n            \"custom-build\"\n          ],\n          \"name\": \"build-script-build1\",\n          \"src_path\": \"[ROOT]/foo/build1.rs\",\n          \"test\": false\n        },\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": false,\n          \"doctest\": false,\n          \"edition\": \"2024\",\n          \"kind\": [\n            \"custom-build\"\n          ],\n          \"name\": \"build-script-build2\",\n          \"src_path\": \"[ROOT]/foo/build2.rs\",\n          \"test\": false\n        }\n      ],\n      \"version\": \"0.1.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.1.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.1.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn verify_package_multiple_build_scripts() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"multiple-build-scripts\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"docs.rs/foo\"\n                authors = []\n\n                build = [\"build1.rs\", \"build2.rs\"]\n                include = [ \"src/main.rs\", \"build1.rs\" ]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build1.rs\", \"fn main() {}\")\n        .file(\"build2.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_status(0)\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.1.0 ([ROOT]/foo)\n[WARNING] ignoring `package.build` entry `build2.rs` as it is not included in the published package\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.1.0 ([ROOT]/foo)\n[COMPILING] foo v0.1.0 ([ROOT]/foo/target/package/foo-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.1.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.1.0.crate\",\n        &[\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/main.rs\",\n            \"build1.rs\",\n            \"Cargo.lock\",\n        ],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\ncargo-features = [\"multiple-build-scripts\"]\n\n[package]\nedition = \"2024\"\nname = \"foo\"\nversion = \"0.1.0\"\nauthors = []\nbuild = \"build1.rs\"\ninclude = [\n    \"src/main.rs\",\n    \"build1.rs\",\n]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\n\"##]],\n        )],\n    );\n}\n\nfn add_git_vendor_config(p: &Project, git_project: &Project) {\n    p.change_file(\n        \".cargo/config.toml\",\n        &format!(\n            r#\"\n            [source.\"git+{url}\"]\n            git = \"{url}\"\n            replace-with = 'vendor'\n\n            [source.vendor]\n            directory = 'vendor'\n        \"#,\n            url = git_project.url()\n        ),\n    );\n}\n\n#[cargo_test]\nfn verify_vendor_multiple_build_scripts() {\n    let git_project = git::new(\"dep\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                cargo-features = [\"multiple-build-scripts\"]\n\n                [package]\n                name = \"dep\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                license = \"MIT\"\n                description = \"dependency of foo\"\n                documentation = \"docs.rs/dep\"\n                authors = []\n\n                build = [\"build1.rs\", \"build2.rs\"]\n                include = [ \"src/main.rs\", \"build1.rs\" ]\n            \"#,\n            )\n            .file(\"src/main.rs\", \"fn main() {}\")\n            .file(\"build1.rs\", \"fn main() {}\")\n            .file(\"build2.rs\", \"fn main() {}\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    cargo-features = [\"multiple-build-scripts\"]\n\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2024\"\n\n                    [dependencies.dep]\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_status(0)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep`\n[LOCKING] 1 package to latest [..] compatible version\n   Vendoring dep v0.1.0 ([ROOTURL]/dep#[..]) ([ROOT]/home/.cargo/git/checkouts/dep-[HASH]/[..]) to vendor/dep\n[WARNING] ignoring `package.build` entry `build2.rs` as it is not included in the published package\nTo use vendored sources, add this to your .cargo/config.toml for this project:\n\n\n\"#]])\n        .run();\n    add_git_vendor_config(&p, &git_project);\n\n    assert_e2e().eq(\n        p.read_file(\"vendor/dep/Cargo.toml\"),\n        str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\ncargo-features = [\"multiple-build-scripts\"]\n\n[package]\nedition = \"2024\"\nname = \"dep\"\nversion = \"0.1.0\"\nauthors = []\nbuild = \"build1.rs\"\ninclude = [\n    \"src/main.rs\",\n    \"build1.rs\",\n]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"dependency of foo\"\ndocumentation = \"docs.rs/dep\"\nreadme = false\nlicense = \"MIT\"\n\n[[bin]]\nname = \"dep\"\npath = \"src/main.rs\"\n\n\"##]],\n    );\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_script_first_index_script_failed() {\n    // In this, the script that is at first index in the build script array fails\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"multiple-build-scripts\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n\n                build = [\"build1.rs\", \"build2.rs\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build1.rs\", \"fn main() { std::process::exit(101); }\")\n        .file(\"build2.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n...\n[ERROR] failed to run custom build command for `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  process didn't exit successfully: `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build1` ([EXIT_STATUS]: 101)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_build_script_second_index_script_failed() {\n    // In this, the script that is at second index in the build script array fails\n    // This test was necessary because earlier, the program failed only if first script failed.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"multiple-build-scripts\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n\n                build = [\"build1.rs\", \"build2.rs\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build1.rs\", \"fn main() {}\")\n        .file(\"build2.rs\", \"fn main() { std::process::exit(101); }\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n...\n[ERROR] failed to run custom build command for `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  process didn't exit successfully: `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build2` ([EXIT_STATUS]: 101)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_script_with_conflicting_environment_variables() {\n    // In this, multiple scripts set different values to same environment variables\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"multiple-build-scripts\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n\n                build = [\"build1.rs\", \"build2.rs\"]\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                const FOO: &'static str = env!(\"FOO\");\n                fn main() {\n                    println!(\"{}\", FOO);\n                }\n            \"#,\n        )\n        .file(\n            \"build1.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-env=FOO=bar1\"); }\"#,\n        )\n        .file(\n            \"build2.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-env=FOO=bar2\"); }\"#,\n        )\n        .build();\n\n    p.cargo(\"run -v\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_status(0)\n        .with_stdout_data(str![[r#\"\nbar2\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_script_with_conflicting_out_dirs() {\n    // In this, multiple scripts create file with same name in their respective OUT_DIR.\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"multiple-build-scripts\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n\n                build = [\"build1.rs\", \"build2.rs\"]\n            \"#,\n        )\n        // By default, OUT_DIR is set to that of the first build script in the array\n        .file(\n            \"src/main.rs\",\n            r#\"\n                include!(concat!(env!(\"OUT_DIR\"), \"/foo.rs\"));\n                fn main() {\n                    println!(\"{}\", message());\n                }\n            \"#,\n        )\n        .file(\n            \"build1.rs\",\n            r#\"\n            use std::env;\n            use std::fs;\n            use std::path::Path;\n\n            fn main() {\n                let out_dir = env::var_os(\"OUT_DIR\").unwrap();\n                let dest_path = Path::new(&out_dir).join(\"foo.rs\");\n                fs::write(\n                    &dest_path,\n                    \"pub fn message() -> &'static str {\n                        \\\"Hello, from Build Script 1!\\\"\n                    }\n                    \"\n                ).unwrap();\n             }\"#,\n        )\n        .file(\n            \"build2.rs\",\n            r#\"\n            use std::env;\n            use std::fs;\n            use std::path::Path;\n\n            fn main() {\n                let out_dir = env::var_os(\"OUT_DIR\").unwrap();\n                let dest_path = Path::new(&out_dir).join(\"foo.rs\");\n                fs::write(\n                    &dest_path,\n                    \"pub fn message() -> &'static str {\n                        \\\"Hello, from Build Script 2!\\\"\n                    }\n                    \"\n                ).unwrap();\n             }\"#,\n        )\n        .build();\n\n    p.cargo(\"run -v\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_status(0)\n        .with_stdout_data(str![[r#\"\nHello, from Build Script 1!\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_script_with_conflicts_reverse_sorted() {\n    // In this, multiple scripts create file with same name in their respective OUT_DIR.\n    // It is different from above because `package.build` is not sorted in this.\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"multiple-build-scripts\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n\n                build = [\"build2.rs\", \"build1.rs\"]\n            \"#,\n        )\n        // By default, OUT_DIR is set to that of the first build script in the array\n        .file(\n            \"src/main.rs\",\n            r#\"\n                include!(concat!(env!(\"OUT_DIR\"), \"/foo.rs\"));\n                fn main() {\n                    println!(\"{}\", message());\n                }\n            \"#,\n        )\n        .file(\n            \"build1.rs\",\n            r#\"\n            use std::env;\n            use std::fs;\n            use std::path::Path;\n\n            fn main() {\n                let out_dir = env::var_os(\"OUT_DIR\").unwrap();\n                let dest_path = Path::new(&out_dir).join(\"foo.rs\");\n                fs::write(\n                    &dest_path,\n                    \"pub fn message() -> &'static str {\n                        \\\"Hello, from Build Script 1!\\\"\n                    }\n                    \"\n                ).unwrap();\n             }\"#,\n        )\n        .file(\n            \"build2.rs\",\n            r#\"\n            use std::env;\n            use std::fs;\n            use std::path::Path;\n\n            fn main() {\n                let out_dir = env::var_os(\"OUT_DIR\").unwrap();\n                let dest_path = Path::new(&out_dir).join(\"foo.rs\");\n                fs::write(\n                    &dest_path,\n                    \"pub fn message() -> &'static str {\n                        \\\"Hello, from Build Script 2!\\\"\n                    }\n                    \"\n                ).unwrap();\n             }\"#,\n        )\n        .build();\n\n    p.cargo(\"run -v\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_status(0)\n        .with_stdout_data(str![[r#\"\nHello, from Build Script 2!\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rerun_untracks_other_files() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"multiple-build-scripts\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                build = [\"build1.rs\", \"build2.rs\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build1.rs\",\n            r#\"\nfn main() {\n    foo();\n}\nfn foo() {\n    let _path = \"assets/foo.txt\";\n}\n\"#,\n        )\n        .file(\n            \"build2.rs\",\n            r#\"\nfn main() {\n    bar();\n}\n\nfn bar() {\n    let path = \"assets/bar.txt\";\n    println!(\"cargo::rerun-if-changed={path}\");\n}\"#,\n        )\n        .file(\"assets/foo.txt\", \"foo\")\n        .file(\"assets/bar.txt\", \"bar\")\n        .build();\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .run();\n\n    // Editing foo.txt will also recompile now since they are separate build scripts\n    p.change_file(\"assets/foo.txt\", \"foo updated\");\n    p.cargo(\"check -v\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the [..]\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build1`\n[RUNNING] `rustc --crate-name foo --edition=2024 src/main.rs [..] --crate-type bin [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Editing bar.txt will also recompile now since they are separate build scripts\n\n    p.change_file(\"assets/bar.txt\", \"bar updated\");\n    p.cargo(\"check -v\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the [..]\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build[..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build[..]`\n[RUNNING] `rustc --crate-name foo --edition=2024 src/main.rs [..] --crate-type bin [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_out_dirs() {\n    // Test to verify access to the `OUT_DIR` of the respective build scripts.\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"multiple-build-scripts\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                build = [\"build1.rs\", \"build2.rs\"]\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                include!(concat!(env!(\"build1_OUT_DIR\"), \"/foo.rs\"));\n                include!(concat!(env!(\"build2_OUT_DIR\"), \"/foo.rs\"));\n                fn main() {\n                    println!(\"{}\", message1());\n                    println!(\"{}\", message2());\n                }\n            \"#,\n        )\n        .file(\n            \"build1.rs\",\n            r#\"\n            use std::env;\n            use std::fs;\n            use std::path::Path;\n\n            fn main() {\n                let out_dir = env::var_os(\"OUT_DIR\").unwrap();\n                let dest_path = Path::new(&out_dir).join(\"foo.rs\");\n                fs::write(\n                    &dest_path,\n                    \"pub fn message1() -> &'static str {\n                        \\\"Hello, from Build Script 1!\\\"\n                    }\n                    \"\n                ).unwrap();\n             }\"#,\n        )\n        .file(\n            \"build2.rs\",\n            r#\"\n            use std::env;\n            use std::fs;\n            use std::path::Path;\n\n            fn main() {\n                let out_dir = env::var_os(\"OUT_DIR\").unwrap();\n                let dest_path = Path::new(&out_dir).join(\"foo.rs\");\n                fs::write(\n                    &dest_path,\n                    \"pub fn message2() -> &'static str {\n                        \\\"Hello, from Build Script 2!\\\"\n                    }\n                    \"\n                ).unwrap();\n             }\"#,\n        )\n        .build();\n\n    p.cargo(\"run -v\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_status(0)\n        .with_stdout_data(str![[r#\"\nHello, from Build Script 1!\nHello, from Build Script 2!\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn duplicate_build_script_stems() {\n    // Test to verify that duplicate build script file stems throws error.\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"multiple-build-scripts\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n                build = [\"build1.rs\", \"foo/build1.rs\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build1.rs\", \"fn main() {}\")\n        .file(\"foo/build1.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .masquerade_as_nightly_cargo(&[\"multiple-build-scripts\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  found build scripts with duplicate file stems, but all build scripts must have a unique file stem\n    for stem `build1`: build1.rs, foo/build1.rs\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cache_lock.rs",
    "content": "//! Tests for `CacheLock`.\n\nuse std::thread::JoinHandle;\n\nuse crate::prelude::*;\nuse cargo::util::cache_lock::{CacheLockMode, CacheLocker};\nuse cargo_test_support::paths;\nuse cargo_test_support::{retry, thread_wait_timeout, threaded_timeout};\n\nuse crate::config::GlobalContextBuilder;\n\n/// Helper to verify that it is OK to acquire the given lock (it shouldn't block).\nfn verify_lock_is_ok(mode: CacheLockMode) {\n    let root = paths::root();\n    threaded_timeout(100, move || {\n        let gctx = GlobalContextBuilder::new().root(root).build();\n        let locker = CacheLocker::new();\n        // This would block if it is held.\n        let _lock = locker.lock(&gctx, mode).unwrap();\n        assert!(locker.is_locked(mode));\n    });\n}\n\n/// Helper to acquire two locks from the same locker.\nfn a_b_nested(a: CacheLockMode, b: CacheLockMode) {\n    let gctx = GlobalContextBuilder::new().build();\n    let locker = CacheLocker::new();\n    let lock1 = locker.lock(&gctx, a).unwrap();\n    assert!(locker.is_locked(a));\n    let lock2 = locker.lock(&gctx, b).unwrap();\n    assert!(locker.is_locked(b));\n    drop(lock2);\n    drop(lock1);\n    // Verify locks were unlocked.\n    verify_lock_is_ok(CacheLockMode::Shared);\n    verify_lock_is_ok(CacheLockMode::DownloadExclusive);\n    verify_lock_is_ok(CacheLockMode::MutateExclusive);\n}\n\n/// Helper to acquire two locks from separate lockers, verifying that they\n/// don't block each other.\nfn a_then_b_separate_not_blocked(a: CacheLockMode, b: CacheLockMode, verify: CacheLockMode) {\n    let gctx = GlobalContextBuilder::new().build();\n    let locker1 = CacheLocker::new();\n    let lock1 = locker1.lock(&gctx, a).unwrap();\n    assert!(locker1.is_locked(a));\n    let locker2 = CacheLocker::new();\n    let lock2 = locker2.lock(&gctx, b).unwrap();\n    assert!(locker2.is_locked(b));\n    let thread = verify_lock_would_block(verify);\n    // Unblock the thread.\n    drop(lock1);\n    drop(lock2);\n    // Verify the thread is unblocked.\n    thread_wait_timeout::<()>(100, thread);\n}\n\n/// Helper to acquire two locks from separate lockers, verifying that the\n/// second one blocks.\nfn a_then_b_separate_blocked(a: CacheLockMode, b: CacheLockMode) {\n    let gctx = GlobalContextBuilder::new().build();\n    let locker = CacheLocker::new();\n    let lock = locker.lock(&gctx, a).unwrap();\n    assert!(locker.is_locked(a));\n    let thread = verify_lock_would_block(b);\n    // Unblock the thread.\n    drop(lock);\n    // Verify the thread is unblocked.\n    thread_wait_timeout::<()>(100, thread);\n}\n\n/// Helper to verify that acquiring the given mode would block.\n///\n/// Always call `thread_wait_timeout` on the result.\n#[must_use]\nfn verify_lock_would_block(mode: CacheLockMode) -> JoinHandle<()> {\n    let root = paths::root();\n    // Spawn a thread that will block on the lock.\n    let thread = std::thread::spawn(move || {\n        let gctx = GlobalContextBuilder::new().root(root).build();\n        let locker2 = CacheLocker::new();\n        let lock2 = locker2.lock(&gctx, mode).unwrap();\n        assert!(locker2.is_locked(mode));\n        drop(lock2);\n    });\n    // Verify that it blocked.\n    retry(100, || {\n        if let Ok(s) = std::fs::read_to_string(paths::root().join(\"shell.out\")) {\n            if s.trim().starts_with(\"Blocking waiting for file lock on\") {\n                return Some(());\n            } else {\n                eprintln!(\"unexpected output: {s}\");\n                // Try again, it might have been partially written.\n            }\n        }\n        None\n    });\n    thread\n}\n\n#[test]\nfn new_is_unlocked() {\n    let locker = CacheLocker::new();\n    assert!(!locker.is_locked(CacheLockMode::Shared));\n    assert!(!locker.is_locked(CacheLockMode::DownloadExclusive));\n    assert!(!locker.is_locked(CacheLockMode::MutateExclusive));\n}\n\n#[cargo_test]\nfn multiple_shared() {\n    // Test that two nested shared locks from the same locker are safe to acquire.\n    a_b_nested(CacheLockMode::Shared, CacheLockMode::Shared);\n}\n\n#[cfg_attr(\n    target_os = \"aix\",\n    ignore = \"Test fails on AIX due to unsupported flock behaviour\"\n)]\n#[cargo_test]\nfn multiple_shared_separate() {\n    // Test that two independent shared locks are safe to acquire at the same time.\n    a_then_b_separate_not_blocked(\n        CacheLockMode::Shared,\n        CacheLockMode::Shared,\n        CacheLockMode::MutateExclusive,\n    );\n}\n\n#[cargo_test]\nfn multiple_download() {\n    // That that two nested download locks from the same locker are safe to acquire.\n    a_b_nested(\n        CacheLockMode::DownloadExclusive,\n        CacheLockMode::DownloadExclusive,\n    );\n}\n\n#[cargo_test]\nfn multiple_mutate() {\n    // That that two nested mutate locks from the same locker are safe to acquire.\n    a_b_nested(\n        CacheLockMode::MutateExclusive,\n        CacheLockMode::MutateExclusive,\n    );\n}\n\n#[cargo_test]\n#[should_panic(expected = \"lock is not allowed\")]\nfn download_then_shared() {\n    // This sequence is not supported.\n    a_b_nested(CacheLockMode::DownloadExclusive, CacheLockMode::Shared);\n}\n\n#[cargo_test]\n#[should_panic(expected = \"lock upgrade from shared to exclusive not supported\")]\nfn shared_then_mutate() {\n    // This sequence is not supported.\n    a_b_nested(CacheLockMode::Shared, CacheLockMode::MutateExclusive);\n}\n\n#[cargo_test]\nfn shared_then_download() {\n    a_b_nested(CacheLockMode::Shared, CacheLockMode::DownloadExclusive);\n    // Verify drop actually unlocked.\n    verify_lock_is_ok(CacheLockMode::DownloadExclusive);\n    verify_lock_is_ok(CacheLockMode::MutateExclusive);\n}\n\n#[cargo_test]\nfn mutate_then_shared() {\n    a_b_nested(CacheLockMode::MutateExclusive, CacheLockMode::Shared);\n    // Verify drop actually unlocked.\n    verify_lock_is_ok(CacheLockMode::MutateExclusive);\n}\n\n#[cargo_test]\nfn download_then_mutate() {\n    a_b_nested(\n        CacheLockMode::DownloadExclusive,\n        CacheLockMode::MutateExclusive,\n    );\n    // Verify drop actually unlocked.\n    verify_lock_is_ok(CacheLockMode::DownloadExclusive);\n    verify_lock_is_ok(CacheLockMode::MutateExclusive);\n}\n\n#[cargo_test]\nfn mutate_then_download() {\n    a_b_nested(\n        CacheLockMode::MutateExclusive,\n        CacheLockMode::DownloadExclusive,\n    );\n    // Verify drop actually unlocked.\n    verify_lock_is_ok(CacheLockMode::MutateExclusive);\n    verify_lock_is_ok(CacheLockMode::DownloadExclusive);\n}\n\n#[cargo_test]\nfn readonly() {\n    // In a permission denied situation, it should still allow a lock. It just\n    // silently behaves as-if it was locked.\n    let cargo_home = paths::home().join(\".cargo\");\n    std::fs::create_dir_all(&cargo_home).unwrap();\n    let mut perms = std::fs::metadata(&cargo_home).unwrap().permissions();\n    perms.set_readonly(true);\n    std::fs::set_permissions(&cargo_home, perms).unwrap();\n    let gctx = GlobalContextBuilder::new().build();\n    let locker = CacheLocker::new();\n    for mode in [\n        CacheLockMode::Shared,\n        CacheLockMode::DownloadExclusive,\n        CacheLockMode::MutateExclusive,\n    ] {\n        let _lock1 = locker.lock(&gctx, mode).unwrap();\n        // Make sure it can recursively acquire the lock, too.\n        let _lock2 = locker.lock(&gctx, mode).unwrap();\n    }\n}\n\n#[cfg_attr(\n    target_os = \"aix\",\n    ignore = \"Test fails on AIX due to unsupported flock behaviour\"\n)]\n#[cargo_test]\nfn download_then_shared_separate() {\n    a_then_b_separate_not_blocked(\n        CacheLockMode::DownloadExclusive,\n        CacheLockMode::Shared,\n        CacheLockMode::MutateExclusive,\n    );\n}\n\n#[cfg_attr(\n    target_os = \"aix\",\n    ignore = \"Test fails on AIX due to unsupported flock behaviour\"\n)]\n#[cargo_test]\nfn shared_then_download_separate() {\n    a_then_b_separate_not_blocked(\n        CacheLockMode::Shared,\n        CacheLockMode::DownloadExclusive,\n        CacheLockMode::MutateExclusive,\n    );\n}\n\n#[cfg_attr(\n    target_os = \"aix\",\n    ignore = \"Test fails on AIX due to unsupported flock behaviour\"\n)]\n#[cargo_test]\nfn multiple_download_separate() {\n    // Test that with two independent download locks, the second blocks until\n    // the first is released.\n    a_then_b_separate_blocked(\n        CacheLockMode::DownloadExclusive,\n        CacheLockMode::DownloadExclusive,\n    );\n}\n\n#[cfg_attr(\n    target_os = \"aix\",\n    ignore = \"Test fails on AIX due to unsupported flock behaviour\"\n)]\n#[cargo_test]\nfn multiple_mutate_separate() {\n    // Test that with two independent mutate locks, the second blocks until\n    // the first is released.\n    a_then_b_separate_blocked(\n        CacheLockMode::MutateExclusive,\n        CacheLockMode::MutateExclusive,\n    );\n}\n\n#[cfg_attr(\n    target_os = \"aix\",\n    ignore = \"Test fails on AIX due to unsupported flock behaviour\"\n)]\n#[cargo_test]\nfn shared_then_mutate_separate() {\n    a_then_b_separate_blocked(CacheLockMode::Shared, CacheLockMode::MutateExclusive);\n}\n\n#[cfg_attr(\n    target_os = \"aix\",\n    ignore = \"Test fails on AIX due to unsupported flock behaviour\"\n)]\n#[cargo_test]\nfn download_then_mutate_separate() {\n    a_then_b_separate_blocked(\n        CacheLockMode::DownloadExclusive,\n        CacheLockMode::MutateExclusive,\n    );\n}\n\n#[cfg_attr(\n    target_os = \"aix\",\n    ignore = \"Test fails on AIX due to unsupported flock behaviour\"\n)]\n#[cargo_test]\nfn mutate_then_download_separate() {\n    a_then_b_separate_blocked(\n        CacheLockMode::MutateExclusive,\n        CacheLockMode::DownloadExclusive,\n    );\n}\n\n#[cfg_attr(\n    target_os = \"aix\",\n    ignore = \"Test fails on AIX due to unsupported flock behaviour\"\n)]\n#[cargo_test]\nfn mutate_then_shared_separate() {\n    a_then_b_separate_blocked(CacheLockMode::MutateExclusive, CacheLockMode::Shared);\n}\n\n#[cargo_test(ignore_windows = \"no method to prevent creating or locking a file\")]\nfn mutate_err_is_atomic() {\n    // Verifies that when getting a mutate lock, that if the first lock\n    // succeeds, but the second one fails, that the first lock is released.\n    let gctx = GlobalContextBuilder::new().build();\n    let locker = CacheLocker::new();\n    let cargo_home = gctx.home().as_path_unlocked();\n    let cache_path = cargo_home.join(\".package-cache\");\n    // This is a hacky way to force an error acquiring the download lock. By\n    // making it a directory, it is unable to open it.\n    // TODO: Unfortunately this doesn't work on Windows. I don't have any\n    // ideas on how to simulate an error on Windows.\n    cache_path.mkdir_p();\n    match locker.lock(&gctx, CacheLockMode::MutateExclusive) {\n        Ok(_) => panic!(\"did not expect lock to succeed\"),\n        Err(e) => {\n            let msg = format!(\"{e:?}\");\n            assert!(msg.contains(\"failed to open:\"), \"{msg}\");\n        }\n    }\n    assert!(!locker.is_locked(CacheLockMode::MutateExclusive));\n    assert!(!locker.is_locked(CacheLockMode::DownloadExclusive));\n    assert!(!locker.is_locked(CacheLockMode::Shared));\n    cache_path.rm_rf();\n    verify_lock_is_ok(CacheLockMode::DownloadExclusive);\n    verify_lock_is_ok(CacheLockMode::Shared);\n    verify_lock_is_ok(CacheLockMode::MutateExclusive);\n}\n"
  },
  {
    "path": "tests/testsuite/cache_messages.rs",
    "content": "//! Tests for caching compiler diagnostics.\n\nuse crate::prelude::*;\nuse crate::utils::tools;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_manifest, is_coarse_mtime, project, registry::Package, sleep_ms};\n\nuse super::messages::raw_rustc_output;\n\nfn as_str(bytes: &[u8]) -> &str {\n    std::str::from_utf8(bytes).expect(\"valid utf-8\")\n}\n\n#[cargo_test]\nfn simple() {\n    // A simple example that generates two warnings (unused functions).\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n            fn a() {}\n            fn b() {}\n            \",\n        )\n        .build();\n\n    // Capture what rustc actually emits. This is done to avoid relying on the\n    // exact message formatting in rustc.\n    let rustc_output = raw_rustc_output(&p, \"src/lib.rs\", &[]);\n\n    // -q so the output is the same as rustc (no \"Compiling\" or \"Finished\").\n    let cargo_output1 = p.cargo(\"check -q --color=never\").run();\n    assert_eq!(rustc_output, as_str(&cargo_output1.stderr));\n    assert!(cargo_output1.stdout.is_empty());\n    // Check that the cached version is exactly the same.\n    let cargo_output2 = p.cargo(\"check -q\").run();\n    assert_eq!(rustc_output, as_str(&cargo_output2.stderr));\n    assert!(cargo_output2.stdout.is_empty());\n}\n\n// same as `simple`, except everything is using the short format\n#[cargo_test]\nfn simple_short() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n                fn a() {}\n                fn b() {}\n            \",\n        )\n        .build();\n\n    let rustc_output = raw_rustc_output(&p, \"src/lib.rs\", &[\"--error-format=short\"]);\n\n    let cargo_output1 = p\n        .cargo(\"check -q --color=never --message-format=short\")\n        .run();\n    assert_eq!(rustc_output, as_str(&cargo_output1.stderr));\n    // assert!(cargo_output1.stdout.is_empty());\n    let cargo_output2 = p.cargo(\"check -q --message-format=short\").run();\n    println!(\"{}\", String::from_utf8_lossy(&cargo_output2.stdout));\n    assert_eq!(rustc_output, as_str(&cargo_output2.stderr));\n    assert!(cargo_output2.stdout.is_empty());\n}\n\n#[cargo_test]\nfn color() {\n    // Check enabling/disabling color.\n    let p = project().file(\"src/lib.rs\", \"fn a() {}\").build();\n\n    // Hack for issue in fwdansi 1.1. It is squashing multiple resets\n    // into a single reset.\n    // https://github.com/kennytm/fwdansi/issues/2\n    fn normalize(s: &str) -> String {\n        #[cfg(windows)]\n        return s.replace(\"\\x1b[0m\\x1b[0m\", \"\\x1b[0m\");\n        #[cfg(not(windows))]\n        return s.to_string();\n    }\n\n    let compare = |a, b| {\n        assert_eq!(normalize(a), normalize(b));\n    };\n\n    // Capture the original color output.\n    let rustc_color = raw_rustc_output(&p, \"src/lib.rs\", &[\"--color=always\"]);\n    assert!(rustc_color.contains(\"\\x1b[\"));\n\n    // Capture the original non-color output.\n    let rustc_nocolor = raw_rustc_output(&p, \"src/lib.rs\", &[]);\n    assert!(!rustc_nocolor.contains(\"\\x1b[\"));\n\n    // First pass, non-cached, with color, should be the same.\n    let cargo_output1 = p.cargo(\"check -q --color=always\").run();\n    compare(&rustc_color, as_str(&cargo_output1.stderr));\n\n    // Replay cached, with color.\n    let cargo_output2 = p.cargo(\"check -q --color=always\").run();\n    compare(&rustc_color, as_str(&cargo_output2.stderr));\n\n    // Replay cached, no color.\n    let cargo_output_nocolor = p.cargo(\"check -q --color=never\").run();\n    compare(&rustc_nocolor, as_str(&cargo_output_nocolor.stderr));\n}\n\n#[cargo_test]\nfn cached_as_json() {\n    // Check that cached JSON output is the same.\n    let p = project().file(\"src/lib.rs\", \"fn a() {}\").build();\n\n    // Grab the non-cached output, feature disabled.\n    // NOTE: When stabilizing, this will need to be redone.\n    let cargo_output = p.cargo(\"check --message-format=json\").run();\n    let orig_cargo_out = as_str(&cargo_output.stdout);\n    assert!(orig_cargo_out.contains(\"compiler-message\"));\n    p.cargo(\"clean\").run();\n\n    // Check JSON output, not fresh.\n    let cargo_output1 = p.cargo(\"check --message-format=json\").run();\n    assert_eq!(as_str(&cargo_output1.stdout), orig_cargo_out);\n\n    // Check JSON output, fresh.\n    let cargo_output2 = p.cargo(\"check --message-format=json\").run();\n    // The only difference should be this field.\n    let fix_fresh = as_str(&cargo_output2.stdout).replace(\"\\\"fresh\\\":true\", \"\\\"fresh\\\":false\");\n    assert_eq!(fix_fresh, orig_cargo_out);\n}\n\n#[cargo_test]\nfn clears_cache_after_fix() {\n    // Make sure the cache is invalidated when there is no output.\n    let p = project().file(\"src/lib.rs\", \"fn asdf() {}\").build();\n    // Fill the cache.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] function `asdf` is never used\n...\n[WARNING] `foo` (lib) generated 1 warning\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    let cpath = p\n        .glob(\"target/debug/.fingerprint/foo-*/output-*\")\n        .next()\n        .unwrap()\n        .unwrap();\n    assert!(std::fs::read_to_string(cpath).unwrap().contains(\"asdf\"));\n\n    // Fix it.\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n    p.change_file(\"src/lib.rs\", \"\");\n\n    p.cargo(\"check\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert_eq!(\n        p.glob(\"target/debug/.fingerprint/foo-*/output-*\").count(),\n        0\n    );\n\n    // And again, check the cache is correct.\n    p.cargo(\"check\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc() {\n    // Create a warning in rustdoc.\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n            #![warn(missing_docs)]\n            pub fn f() {}\n            \",\n        )\n        .build();\n\n    let rustdoc_output = p.cargo(\"doc -q --color=always\").run();\n    let rustdoc_stderr = as_str(&rustdoc_output.stderr);\n    assert!(rustdoc_stderr.contains(\"missing\"));\n    assert!(rustdoc_stderr.contains(\"\\x1b[\"));\n    assert_eq!(\n        p.glob(\"target/debug/.fingerprint/foo-*/output-*\").count(),\n        1\n    );\n\n    // Check the cached output.\n    let rustdoc_output = p.cargo(\"doc -q --color=always\").run();\n    assert_eq!(as_str(&rustdoc_output.stderr), rustdoc_stderr);\n}\n\n#[cargo_test]\nfn fix() {\n    // Make sure `fix` is not broken by caching.\n    let p = project().file(\"src/lib.rs\", \"pub fn try() {}\").build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\").run();\n\n    assert_eq!(p.read_file(\"src/lib.rs\"), \"pub fn r#try() {}\");\n}\n\n#[cargo_test]\nfn very_verbose() {\n    // Handle cap-lints in dependencies.\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"fn not_used() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -vv\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] bar v1.0.0\n[RUNNING] [..]\n[WARNING] function `not_used` is never used\n...\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -vv\")\n        .with_stderr_data(str![[r#\"\n[FRESH] bar v1.0.0\n[WARNING] function `not_used` is never used\n...\n[WARNING] `bar` (lib) generated 1 warning\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doesnt_create_extra_files() {\n    // Ensure it doesn't create `output` files when not needed.\n    Package::new(\"dep\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"fn unused() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                dep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    assert_eq!(\n        p.glob(\"target/debug/.fingerprint/foo-*/output-*\").count(),\n        0\n    );\n    assert_eq!(\n        p.glob(\"target/debug/.fingerprint/dep-*/output-*\").count(),\n        0\n    );\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n    p.change_file(\"src/lib.rs\", \"fn unused() {}\");\n    p.cargo(\"check\").run();\n    assert_eq!(\n        p.glob(\"target/debug/.fingerprint/foo-*/output-*\").count(),\n        1\n    );\n}\n\n#[cargo_test]\nfn replay_non_json() {\n    // Handles non-json output.\n    let rustc = project()\n        .at(\"rustc\")\n        .file(\"Cargo.toml\", &basic_manifest(\"rustc_alt\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                eprintln!(\"line 1\");\n                eprintln!(\"line 2\");\n                let r = std::process::Command::new(\"rustc\")\n                    .args(std::env::args_os().skip(1))\n                    .status();\n                std::process::exit(r.unwrap().code().unwrap_or(2));\n            }\n            \"#,\n        )\n        .build();\n    rustc.cargo(\"build\").run();\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.cargo(\"check\")\n        .env(\"RUSTC\", rustc.bin(\"rustc_alt\"))\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\nline 1\nline 2\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .env(\"RUSTC\", rustc.bin(\"rustc_alt\"))\n        .with_stderr_data(str![[r#\"\nline 1\nline 2\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn caching_large_output() {\n    // Handles large number of messages.\n    // This is an arbitrary amount that is greater than the 100 used in\n    // job_queue. This is here to check for deadlocks or any other problems.\n    const COUNT: usize = 250;\n    let rustc = project()\n        .at(\"rustc\")\n        .file(\"Cargo.toml\", &basic_manifest(\"rustc_alt\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            &format!(\n                r#\"\n                fn main() {{\n                    for i in 0..{} {{\n                        eprintln!(\"{{{{\\\"message\\\": \\\"test message {{}}\\\", \\\"level\\\": \\\"warning\\\", \\\n                            \\\"spans\\\": [], \\\"children\\\": [], \\\"rendered\\\": \\\"test message {{}}\\\"}}}}\",\n                            i, i);\n                    }}\n                    let r = std::process::Command::new(\"rustc\")\n                        .args(std::env::args_os().skip(1))\n                        .status();\n                    std::process::exit(r.unwrap().code().unwrap_or(2));\n                }}\n                \"#,\n                COUNT\n            ),\n        )\n        .build();\n\n    let mut expected = String::new();\n    for i in 0..COUNT {\n        expected.push_str(&format!(\"test message {}\\n\", i));\n    }\n\n    rustc.cargo(\"build\").run();\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.cargo(\"check\")\n        .env(\"RUSTC\", rustc.bin(\"rustc_alt\"))\n        .with_stderr_data(&format!(\n            \"\\\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n{}[WARNING] `foo` (lib) generated 250 warnings\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\",\n            expected\n        ))\n        .run();\n\n    p.cargo(\"check\")\n        .env(\"RUSTC\", rustc.bin(\"rustc_alt\"))\n        .with_stderr_data(&format!(\n            \"\\\n{}[WARNING] `foo` (lib) generated 250 warnings\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\",\n            expected\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn rustc_workspace_wrapper() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"pub fn f() { assert!(true); }\\n\\\n             fn unused_func() {}\",\n        )\n        .build();\n\n    p.cargo(\"check -v\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", tools::echo_wrapper())\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] [..]/rustc-echo-wrapper[EXE] rustc --crate-name foo [..]\nWRAPPER CALLED: rustc --crate-name foo --edition=2015 src/lib.rs [..]\n[WARNING] function `unused_func` is never used\n...\n[WARNING] `foo` (lib) generated 1 warning\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Check without a wrapper should rebuild\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc[..]`\n[WARNING] function `unused_func` is never used\n...\n[WARNING] `foo` (lib) generated 1 warning\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n\n    // Again, reading from the cache.\n    p.cargo(\"check -v\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", tools::echo_wrapper())\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\nWRAPPER CALLED: rustc [..]\n...\n[WARNING] `foo` (lib) generated 1 warning\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n\n    // And `check` should also be fresh, reading from cache.\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[WARNING] function `unused_func` is never used\n...\n[WARNING] `foo` (lib) generated 1 warning\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn wacky_hashless_fingerprint() {\n    // On Windows, executables don't have hashes. This checks for a bad\n    // assumption that caused bad caching.\n    let p = project()\n        .file(\"src/bin/a.rs\", \"fn main() { let unused = 1; }\")\n        .file(\"src/bin/b.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check --bin b\")\n        .with_stderr_does_not_contain(\"[..]unused[..]\")\n        .run();\n    p.cargo(\"check --bin a\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] unused variable: `unused`\n...\n[WARNING] `foo` (bin \"a\") generated 1 warning[..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // This should not pick up the cache from `a`.\n    p.cargo(\"check --bin b\")\n        .with_stderr_does_not_contain(\"[..]unused[..]\")\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"--help\")\n        .env_remove(\"RUSTUP_HOME\") // consistent behavior with/without\n        .env_remove(\"RUSTUP_TOOLCHAIN\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo/mod.rs",
    "content": "mod help;\nmod z_help;\n"
  },
  {
    "path": "tests/testsuite/cargo/z_help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .masquerade_as_nightly_cargo(&[\"-Z help\"])\n        .args([\"-Z\", \"help\"])\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/add-basic.in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/add-basic.in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/add_basic/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/add_basic/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/add_multiple/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 my-package2\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/add_multiple/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package1 = \"99999.0.0\"\nmy-package2 = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/in/.cargo/config.toml",
    "content": "[source.crates-io]\nreplace-with = \"vendored-sources\"\n\n[source.vendored-sources]\ndirectory = \"./vendor\""
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\""
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/in/vendor/aa/.cargo-checksum.json",
    "content": "{\"files\":{}}"
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/in/vendor/aa/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"aa\"\nversion = \"0.0.0\""
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/in/vendor/aa/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::alt_init();\n    cargo_test_support::registry::Package::new(\"linked-hash-map\", \"0.5.4\")\n        .feature(\"clippy\", &[])\n        .feature(\"heapsize\", &[])\n        .feature(\"heapsize_impl\", &[])\n        .feature(\"nightly\", &[])\n        .feature(\"serde\", &[])\n        .feature(\"serde_impl\", &[])\n        .feature(\"serde_test\", &[])\n        .alternative(true)\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"linked_hash_map --registry alternative\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nlinked-hash-map = { version = \"0.5.4\", registry = \"alternative\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/in/.cargo/config.toml",
    "content": "[source.crates-io]\nreplace-with = \"vendored-sources\"\n\n[source.vendored-sources]\ndirectory = \"./vendor\""
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/in/vendor/aa/.cargo-checksum.json",
    "content": "{\"files\":{}}"
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/in/vendor/aa/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"aa\"\nversion = \"0.0.0\""
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/in/vendor/aa/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cbindgen\")\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/add_toolchain/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"+nightly\")\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/add_toolchain/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/build/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-build-package1\", \"my-build-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"--build my-build-package1 my-build-package2\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/build/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[build-dependencies]\nmy-build-package1 = \"99999.0.0\"\nmy-build-package2 = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/build_prefer_existing_version/in/Cargo.toml",
    "content": "[workspace]\nexclude = [\"dependency\"]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", path = \"dependency\", optional = true, default-features = false, features = [\"one\", \"two\"], registry = \"alternative\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/build_prefer_existing_version/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\none = []\ntwo = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/build_prefer_existing_version/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/build_prefer_existing_version/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/build_prefer_existing_version/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::alt_init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .alternative(true)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency --build\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/build_prefer_existing_version/out/Cargo.toml",
    "content": "[workspace]\nexclude = [\"dependency\"]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", path = \"dependency\", optional = true, default-features = false, features = [\"one\", \"two\"], registry = \"alternative\" }\n\n[build-dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", path = \"dependency\", registry = \"alternative\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/build_prefer_existing_version/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\none = []\ntwo = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/change_rename_target/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nsome-package = { package = \"my-package1\", version = \"0.1.1\", optional = true }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/change_rename_target/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/change_rename_target/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package2 --rename some-package\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/change_rename_target/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nsome-package = { package = \"my-package2\", version = \"99999.0.0\", optional = true }\n\n[features]\nsome-package = [\"dep:some-package\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/cyclic_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"test_cyclic_features\", \"0.1.1\")\n        .feature(\"default\", &[\"feature-one\", \"feature-two\"])\n        .feature(\"feature-one\", &[\"feature-two\"])\n        .feature(\"feature-two\", &[\"feature-one\"])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"test_cyclic_features\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/cyclic_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ntest_cyclic_features = \"0.1.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/default_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 my-package2@0.4.1 --default-features\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/default_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package1 = \"99999.0.0\"\nmy-package2 = \"0.4.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/deprecated_default_features/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = { version = \"99999.0.0\", default_features = false }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/deprecated_default_features/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/deprecated_default_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package\")\n        .current_dir(&cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/deprecated_default_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = { version = \"99999.0.0\", default_features = false }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/deprecated_section/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dev_dependencies]\nmy-package = \"99999.0.0\"\n\n[build_dependencies]\nmy-package = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/deprecated_section/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/deprecated_section/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package\")\n        .current_dir(&cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/deprecated_section/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dev_dependencies]\nmy-package = \"99999.0.0\"\n\n[build_dependencies]\nmy-package = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo.workspace = true\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_features/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\", features = [\"merge\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_features/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\ndefault-base = []\ndefault-test-base = []\ndefault-merge-base = []\ndefault = [\"default-base\", \"default-test-base\", \"default-merge-base\"]\ntest-base = []\ntest = [\"test-base\", \"default-test-base\"]\nmerge-base = []\nmerge = [\"merge-base\", \"default-merge-base\"]\nunrelated = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_features/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_features/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_features/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"-p\", \"bar\", \"--features\", \"test\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_features/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\", features = [\"merge\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_features/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\ndefault-base = []\ndefault-test-base = []\ndefault-merge-base = []\ndefault = [\"default-base\", \"default-test-base\", \"default-merge-base\"]\ntest-base = []\ntest = [\"test-base\", \"default-test-base\"]\nmerge-base = []\nmerge = [\"merge-base\", \"default-merge-base\"]\nunrelated = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_features/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { workspace = true, features = [\"test\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_optional/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_optional/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_optional/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_optional/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_optional/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_optional/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"-p\", \"bar\", \"--optional\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_optional/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_optional/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_optional/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { workspace = true, optional = true }\n\n[features]\nfoo = [\"dep:foo\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_path_base/in/.cargo/config.toml",
    "content": "[path-bases]\nmy_base = \"deps\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_path_base/in/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[workspace]\nmembers = [\"primary\", \"deps/dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", base = \"my_base\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_path_base/in/deps/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_path_base/in/deps/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_path_base/in/primary/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_path_base/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_path_base/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .masquerade_as_nightly_cargo(&[\"path-base\"])\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_path_base/out/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[workspace]\nmembers = [\"primary\", \"deps/dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", base = \"my_base\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_path_base/out/deps/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_path_base/out/primary/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo.workspace = true\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_public/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_public/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_public/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_public/in/primary/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_public/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_public/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"-p\", \"bar\", \"--public\"])\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_public/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_public/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/detect_workspace_inherit_public/out/primary/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { workspace = true, public = true }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-dev-package1\", \"my-dev-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"--dev my-dev-package1 my-dev-package2\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dev-dependencies]\nmy-dev-package1 = \"99999.0.0\"\nmy-dev-package2 = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_build_conflict/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --dev --build\")\n        .current_dir(cwd)\n        .assert()\n        .code(1)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_build_conflict/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_existing_path_base/in/.cargo/config.toml",
    "content": "[path-bases]\nmy_base = \".\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_existing_path_base/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_existing_path_base/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/dev_existing_path_base/in/primary/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", base = \"my_base\", path = \"dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_existing_path_base/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/dev_existing_path_base/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency --dev\")\n        .current_dir(&cwd)\n        .masquerade_as_nightly_cargo(&[\"path-base\"])\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_existing_path_base/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_existing_path_base/out/primary/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", base = \"my_base\", path = \"dependency\" }\n\n[dev-dependencies]\ncargo-list-test-fixture-dependency = { base = \"my_base\", path = \"dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_prefer_existing_version/in/Cargo.toml",
    "content": "[workspace]\nexclude = [\"dependency\"]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", path = \"dependency\", optional = true, default-features = false, features = [\"one\", \"two\"], registry = \"alternative\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_prefer_existing_version/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\none = []\ntwo = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_prefer_existing_version/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/dev_prefer_existing_version/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/dev_prefer_existing_version/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::alt_init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .alternative(true)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency --dev\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_prefer_existing_version/out/Cargo.toml",
    "content": "[workspace]\nexclude = [\"dependency\"]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", path = \"dependency\", optional = true, default-features = false, features = [\"one\", \"two\"], registry = \"alternative\" }\n\n[dev-dependencies]\ncargo-list-test-fixture-dependency = { path = \"dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dev_prefer_existing_version/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\none = []\ntwo = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dry_run/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --dry-run\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/dry_run/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/empty_dep_name/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"@1.2.3\")\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/empty_dep_name/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/feature_suggestion_multiple/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2024\"\n\n"
  },
  {
    "path": "tests/testsuite/cargo_add/feature_suggestion_multiple/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/feature_suggestion_multiple/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0+my-package\")\n        .feature(\"bar\", &[])\n        .feature(\"foo\", &[])\n        .publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --features baz --features feo\")\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/feature_suggestion_none/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2024\"\n\n"
  },
  {
    "path": "tests/testsuite/cargo_add/feature_suggestion_none/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/feature_suggestion_none/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0+my-package\")\n        .feature(\"bar\", &[])\n        .feature(\"foo\", &[])\n        .publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --features none_existent\")\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/feature_suggestion_single/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2024\"\n\n"
  },
  {
    "path": "tests/testsuite/cargo_add/feature_suggestion_single/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/feature_suggestion_single/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0+my-package\")\n        .feature(\"bar\", &[])\n        .publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --features baz\")\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --features eyes\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour-face = { version = \"99999.0.0\", features = [\"eyes\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_activated_over_limit/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_activated_over_limit/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/features_activated_over_limit/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\nuse itertools::Itertools;\n\n#[cargo_test]\nfn case() {\n    const MANY_FEATURES_COUNT: usize = 200;\n    const ACTIVATED_FEATURES_COUNT: usize = 100;\n\n    cargo_test_support::registry::init();\n    let mut test_package =\n        cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\");\n    for i in 0..MANY_FEATURES_COUNT {\n        test_package.feature(format!(\"eyes{i:03}\").as_str(), &[]);\n    }\n    test_package.publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    let features = (0..ACTIVATED_FEATURES_COUNT)\n        .map(|i| format!(\"eyes{i:03}\"))\n        .join(\",\");\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(format!(\"your-face --features {features}\").as_str())\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_activated_over_limit/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour-face = { version = \"99999.0.0\", features = [\"eyes000\", \"eyes001\", \"eyes002\", \"eyes003\", \"eyes004\", \"eyes005\", \"eyes006\", \"eyes007\", \"eyes008\", \"eyes009\", \"eyes010\", \"eyes011\", \"eyes012\", \"eyes013\", \"eyes014\", \"eyes015\", \"eyes016\", \"eyes017\", \"eyes018\", \"eyes019\", \"eyes020\", \"eyes021\", \"eyes022\", \"eyes023\", \"eyes024\", \"eyes025\", \"eyes026\", \"eyes027\", \"eyes028\", \"eyes029\", \"eyes030\", \"eyes031\", \"eyes032\", \"eyes033\", \"eyes034\", \"eyes035\", \"eyes036\", \"eyes037\", \"eyes038\", \"eyes039\", \"eyes040\", \"eyes041\", \"eyes042\", \"eyes043\", \"eyes044\", \"eyes045\", \"eyes046\", \"eyes047\", \"eyes048\", \"eyes049\", \"eyes050\", \"eyes051\", \"eyes052\", \"eyes053\", \"eyes054\", \"eyes055\", \"eyes056\", \"eyes057\", \"eyes058\", \"eyes059\", \"eyes060\", \"eyes061\", \"eyes062\", \"eyes063\", \"eyes064\", \"eyes065\", \"eyes066\", \"eyes067\", \"eyes068\", \"eyes069\", \"eyes070\", \"eyes071\", \"eyes072\", \"eyes073\", \"eyes074\", \"eyes075\", \"eyes076\", \"eyes077\", \"eyes078\", \"eyes079\", \"eyes080\", \"eyes081\", \"eyes082\", \"eyes083\", \"eyes084\", \"eyes085\", \"eyes086\", \"eyes087\", \"eyes088\", \"eyes089\", \"eyes090\", \"eyes091\", \"eyes092\", \"eyes093\", \"eyes094\", \"eyes095\", \"eyes096\", \"eyes097\", \"eyes098\", \"eyes099\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_deactivated_over_limit/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_deactivated_over_limit/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/features_deactivated_over_limit/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\nuse itertools::Itertools;\n\n#[cargo_test]\nfn case() {\n    const MANY_FEATURES_COUNT: usize = 200;\n    const ACTIVATED_FEATURES_COUNT: usize = 30;\n\n    cargo_test_support::registry::init();\n    let mut test_package =\n        cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\");\n    for i in 0..MANY_FEATURES_COUNT {\n        test_package.feature(format!(\"eyes{i:03}\").as_str(), &[]);\n    }\n    test_package.publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    let features = (0..ACTIVATED_FEATURES_COUNT)\n        .map(|i| format!(\"eyes{i:03}\"))\n        .join(\",\");\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(format!(\"your-face --features {features}\").as_str())\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_deactivated_over_limit/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour-face = { version = \"99999.0.0\", features = [\"eyes000\", \"eyes001\", \"eyes002\", \"eyes003\", \"eyes004\", \"eyes005\", \"eyes006\", \"eyes007\", \"eyes008\", \"eyes009\", \"eyes010\", \"eyes011\", \"eyes012\", \"eyes013\", \"eyes014\", \"eyes015\", \"eyes016\", \"eyes017\", \"eyes018\", \"eyes019\", \"eyes020\", \"eyes021\", \"eyes022\", \"eyes023\", \"eyes024\", \"eyes025\", \"eyes026\", \"eyes027\", \"eyes028\", \"eyes029\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_empty/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --features ''\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_empty/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour-face = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_error_activated_over_limit/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies.your-face]\nversion = \"99999.0.0\"\nfeatures = [\n  \"eyes000\",\n  \"eyes001\",\n  \"eyes002\",\n  \"eyes003\",\n  \"eyes004\",\n  \"eyes005\",\n  \"eyes006\",\n  \"eyes007\",\n  \"eyes008\",\n  \"eyes009\",\n  \"eyes010\",\n  \"eyes011\",\n  \"eyes012\",\n  \"eyes013\",\n  \"eyes014\",\n  \"eyes015\",\n  \"eyes016\",\n  \"eyes017\",\n  \"eyes018\",\n  \"eyes019\",\n  \"eyes020\",\n  \"eyes021\",\n  \"eyes022\",\n  \"eyes023\",\n  \"eyes024\",\n  \"eyes025\",\n  \"eyes026\",\n  \"eyes027\",\n  \"eyes028\",\n  \"eyes029\",\n  \"eyes030\",\n  \"eyes031\",\n  \"eyes032\",\n  \"eyes033\",\n  \"eyes034\",\n  \"eyes035\",\n  \"eyes036\",\n  \"eyes037\",\n  \"eyes038\",\n  \"eyes039\",\n]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_error_activated_over_limit/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/features_error_activated_over_limit/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    const MANY_FEATURES_COUNT: usize = 50;\n\n    cargo_test_support::registry::init();\n    let mut test_package =\n        cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\");\n    for i in 0..MANY_FEATURES_COUNT {\n        test_package.feature(format!(\"eyes{i:03}\").as_str(), &[]);\n    }\n    test_package.publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    let features = \"eees100,eees101\";\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(format!(\"your-face --features {features}\").as_str())\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_error_activated_over_limit/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies.your-face]\nversion = \"99999.0.0\"\nfeatures = [\n  \"eyes000\",\n  \"eyes001\",\n  \"eyes002\",\n  \"eyes003\",\n  \"eyes004\",\n  \"eyes005\",\n  \"eyes006\",\n  \"eyes007\",\n  \"eyes008\",\n  \"eyes009\",\n  \"eyes010\",\n  \"eyes011\",\n  \"eyes012\",\n  \"eyes013\",\n  \"eyes014\",\n  \"eyes015\",\n  \"eyes016\",\n  \"eyes017\",\n  \"eyes018\",\n  \"eyes019\",\n  \"eyes020\",\n  \"eyes021\",\n  \"eyes022\",\n  \"eyes023\",\n  \"eyes024\",\n  \"eyes025\",\n  \"eyes026\",\n  \"eyes027\",\n  \"eyes028\",\n  \"eyes029\",\n  \"eyes030\",\n  \"eyes031\",\n  \"eyes032\",\n  \"eyes033\",\n  \"eyes034\",\n  \"eyes035\",\n  \"eyes036\",\n  \"eyes037\",\n  \"eyes038\",\n  \"eyes039\",\n]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_error_deactivated_over_limit/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies.your-face]\nversion = \"99999.0.0\"\nfeatures = [\n  \"eyes000\",\n]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_error_deactivated_over_limit/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/features_error_deactivated_over_limit/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    const MANY_FEATURES_COUNT: usize = 200;\n\n    cargo_test_support::registry::init();\n    let mut test_package =\n        cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\");\n    for i in 0..MANY_FEATURES_COUNT {\n        test_package.feature(format!(\"eyes{i:03}\").as_str(), &[]);\n    }\n    test_package.publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    let features = \"eees100,eees101\";\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(format!(\"your-face --features {features}\").as_str())\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_error_deactivated_over_limit/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies.your-face]\nversion = \"99999.0.0\"\nfeatures = [\n  \"eyes000\",\n]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_multiple_occurrences/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --features eyes --features nose\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_multiple_occurrences/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour-face = { version = \"99999.0.0\", features = [\"eyes\", \"nose\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_preserve/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour-face = { version = \"99999.0.0\", features = [\"eyes\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_preserve/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/features_preserve/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_preserve/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour-face = { version = \"99999.0.0\", features = [\"eyes\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_spaced_values/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --features eyes,nose\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_spaced_values/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour-face = { version = \"99999.0.0\", features = [\"eyes\", \"nose\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_unknown/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --features noze\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_unknown/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_unknown_no_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --features noze\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/features_unknown_no_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let git_dep = cargo_test_support::git::new(\"git-package\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"git-package\", \"0.3.0+git-package\"),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"git-package\", \"--git\", &git_url])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ngit-package = { git = \"[ROOTURL]/git-package\", version = \"0.3.0\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_branch/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let (git_dep, git_repo) = cargo_test_support::git::new_repo(\"git-package\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"git-package\", \"0.3.0+git-package\"),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n    let branch = \"dev\";\n    let find_head = || git_repo.head().unwrap().peel_to_commit().unwrap();\n    git_repo.branch(branch, &find_head(), false).unwrap();\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"git-package\", \"--git\", &git_url, \"--branch\", branch])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_branch/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ngit-package = { git = \"[ROOTURL]/git-package\", branch = \"dev\", version = \"0.3.0\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_conflicts_namever/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\n            \"my-package@0.4.3\",\n            \"--git\",\n            \"https://github.com/dcjanus/invalid\",\n        ])\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_conflicts_namever/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_dev/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let git_dep = cargo_test_support::git::new(\"git-package\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"git-package\", \"0.3.0+git-package\"),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"git-package\", \"--git\", &git_url, \"--dev\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_dev/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dev-dependencies]\ngit-package = { git = \"[ROOTURL]/git-package\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_inferred_name/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let git_dep = cargo_test_support::git::new(\"git-package\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"git-package\", \"0.3.0+git-package\"),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"--git\", &git_url])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_inferred_name/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ngit-package = { git = \"[ROOTURL]/git-package\", version = \"0.3.0\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_inferred_name_multiple/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let git_dep = cargo_test_support::git::new(\"git-package\", |project| {\n        project\n            .file(\n                \"p1/Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"my-package1\", \"0.3.0+my-package1\"),\n            )\n            .file(\"p1/src/lib.rs\", \"\")\n            .file(\n                \"p2/Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"my-package2\", \"0.3.0+my-package2\"),\n            )\n            .file(\"p2/src/lib.rs\", \"\")\n            .file(\n                \"p3/Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"my-package3\", \"0.3.0+my-package2\"),\n            )\n            .file(\"p3/src/lib.rs\", \"\")\n            .file(\n                \"p4/Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"my-package4\", \"0.3.0+my-package2\"),\n            )\n            .file(\"p4/src/lib.rs\", \"\")\n            .file(\n                \"p5/Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"my-package5\", \"0.3.0+my-package2\"),\n            )\n            .file(\"p5/src/lib.rs\", \"\")\n            .file(\n                \"p6/Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"my-package6\", \"0.3.0+my-package2\"),\n            )\n            .file(\"p6/src/lib.rs\", \"\")\n            .file(\n                \"p7/Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"my-package7\", \"0.3.0+my-package2\"),\n            )\n            .file(\"p7/src/lib.rs\", \"\")\n            .file(\n                \"p8/Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"my-package8\", \"0.3.0+my-package2\"),\n            )\n            .file(\"p8/src/lib.rs\", \"\")\n            .file(\n                \"p9/Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"my-package9\", \"0.3.0+my-package2\"),\n            )\n            .file(\"p9/src/lib.rs\", \"\")\n    });\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"--git\", &git_url])\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_inferred_name_multiple/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_multiple_names/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let git_dep = cargo_test_support::git::new(\"git-package\", |project| {\n        project\n            .file(\n                \"p1/Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"my-package1\", \"0.3.0+my-package1\"),\n            )\n            .file(\"p1/src/lib.rs\", \"\")\n            .file(\n                \"p2/Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"my-package2\", \"0.3.0+my-package2\"),\n            )\n            .file(\"p2/src/lib.rs\", \"\")\n    });\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"my-package1\", \"my-package2\", \"--git\", &git_url])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_multiple_names/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package1 = { git = \"[ROOTURL]/git-package\", version = \"0.3.0\" }\nmy-package2 = { git = \"[ROOTURL]/git-package\", version = \"0.3.0\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_multiple_packages_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let main_manifest = r#\"\n    [package]\n    name = \"main-package\"\n    version = \"0.1.1+main-package\"\n    authors = []\n\n    [workspace]\n    members = [\"package-wo-feature\", \"package-with-feature\"]\n    \"#;\n\n    let manifest_feature = r#\"\n    [package]\n    name = \"package-with-feature\"\n    version = \"0.1.3+package-with-feature\"\n    [features]\n    target_feature = []\n    \"#;\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let git_dep = cargo_test_support::git::new(\"git-package\", |project| {\n        project\n            .file(\"Cargo.toml\", &main_manifest)\n            .file(\n                \"package-wo-feature/Cargo.toml\",\n                &cargo_test_support::basic_manifest(\n                    \"package-wo-feature\",\n                    \"0.1.1+package-wo-feature\",\n                ),\n            )\n            .file(\"package-wo-feature/src/lib.rs\", \"\")\n            .file(\"package-with-feature/Cargo.toml\", &manifest_feature)\n            .file(\"package-with-feature/src/lib.rs\", \"\")\n    });\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\n            \"--git\",\n            &git_url,\n            \"package-with-feature\",\n            \"--features=target_feature\",\n        ])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_multiple_packages_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\npackage-with-feature = { git = \"[ROOTURL]/git-package\", version = \"0.1.3\", features = [\"target_feature\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_registry/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_registry/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/git_registry/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::alt_init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"versioned-package\", ver)\n            .alternative(true)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let git_dep = cargo_test_support::git::new(\"versioned-package\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"versioned-package\", \"0.3.0+versioned-package\"),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\n            \"versioned-package\",\n            \"--git\",\n            &git_url,\n            \"--registry\",\n            \"alternative\",\n        ])\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_registry/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nversioned-package = { git = \"[ROOTURL]/versioned-package\", version = \"0.3.0\", registry = \"alternative\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_rev/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let (git_dep, git_repo) = cargo_test_support::git::new_repo(\"git-package\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"git-package\", \"0.3.0+git-package\"),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n    let find_head = || git_repo.head().unwrap().peel_to_commit().unwrap();\n    let head = find_head().id().to_string();\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"git-package\", \"--git\", &git_url, \"--rev\", &head])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_rev/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ngit-package = { git = \"[ROOTURL]/git-package\", rev = \"[..]\", version = \"0.3.0\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_tag/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let (git_dep, git_repo) = cargo_test_support::git::new_repo(\"git-package\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"git-package\", \"0.3.0+git-package\"),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n    let tag = \"v1.0.0\";\n    cargo_test_support::git::tag(&git_repo, tag);\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"git-package\", \"--git\", &git_url, \"--tag\", tag])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/git_tag/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ngit-package = { git = \"[ROOTURL]/git-package\", tag = \"v1.0.0\", version = \"0.3.0\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/infer_prerelease/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"prerelease_only\", \"0.2.0-alpha.1\").publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"prerelease_only\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/infer_prerelease/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nprerelease_only = \"0.2.0-alpha.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_arg/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --flag\")\n        .current_dir(cwd)\n        .assert()\n        .code(1)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_arg/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_git_name/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let git_dep = cargo_test_support::git::new(\"git-package\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"git-package\", \"0.3.0+git-package\"),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"not-in-git\", \"--git\", &git_url])\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_git_name/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_inherited_dependency/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo.workspace = true\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_inherited_dependency/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_inherited_dependency/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_inherited_dependency/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_inherited_dependency/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_inherited_dependency/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_inherited_dependency/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo.workspace = true\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_inherited_dependency/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_inherited_dependency/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_inherit_dependency/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_inherit_dependency/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_inherit_dependency/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_inherit_dependency/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_inherit_dependency/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_inherit_dependency/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"--default-features\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_inherit_dependency/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_inherit_dependency/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_inherit_dependency/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo.workspace = true\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"--default-features\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo.workspace = true\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\", \"dependency-alt\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/in/dependency-alt/Cargo.toml",
    "content": "[package]\nname = \"foo-alt\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/in/dependency-alt/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"--rename\", \"foo\", \"foo-alt\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\", \"dependency-alt\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/out/dependency-alt/Cargo.toml",
    "content": "[package]\nname = \"foo-alt\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_manifest/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"manifest-invalid-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[invalid-section]\nkey = invalid-value\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_manifest/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_manifest/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_manifest/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"manifest-invalid-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[invalid-section]\nkey = invalid-value\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_name_external/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"lets_hope_nobody_ever_publishes_this_crate\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_name_external/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_path/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture --path ./tests/fixtures/local\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_path/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_path_name/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_path_name/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_path_name/in/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_path_name/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_path_name/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"not-at-path --path ../dependency\")\n        .current_dir(&cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_path_name/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_path_name/out/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_path_self/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture --path .\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_path_self/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_target_empty/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --target ''\")\n        .current_dir(cwd)\n        .assert()\n        .code(1)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_target_empty/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_vers/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package@invalid-version-string\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/invalid_vers/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"your-face\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour-face = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\", \"optional\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"your-face\"\nversion = \"0.1.3\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"0.1.1\"\noptional-dependency = { path = \"../optional\", optional = true }\n\n[features]\ndefault = [\"mouth\"]\nnose = []\nmouth = [\"nose\"]\neyes = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path/in/optional/Cargo.toml",
    "content": "[package]\nname = \"optional-dependency\"\nversion = \"0.1.3\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"0.1.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path/in/optional/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path/in/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --path ../dependency\")\n        .current_dir(&cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\", \"optional\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"your-face\"\nversion = \"0.1.3\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"0.1.1\"\noptional-dependency = { path = \"../optional\", optional = true }\n\n[features]\ndefault = [\"mouth\"]\nnose = []\nmouth = [\"nose\"]\neyes = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path/out/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour-face = { version = \"0.1.3\", path = \"../dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path_no_default/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\", \"optional\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path_no_default/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"your-face\"\nversion = \"0.1.3\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"0.1.1\"\noptional-dependency = { path = \"../optional\", optional = true }\n\n[features]\ndefault = [\"mouth\"]\nnose = []\nmouth = [\"nose\"]\neyes = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path_no_default/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path_no_default/in/optional/Cargo.toml",
    "content": "[package]\nname = \"optional-dependency\"\nversion = \"0.1.3\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"0.1.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path_no_default/in/optional/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path_no_default/in/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path_no_default/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path_no_default/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\n            \"your-face\",\n            \"--path\",\n            \"../dependency\",\n            \"--no-default-features\",\n        ])\n        .current_dir(&cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path_no_default/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\", \"optional\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path_no_default/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"your-face\"\nversion = \"0.1.3\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"0.1.1\"\noptional-dependency = { path = \"../optional\", optional = true }\n\n[features]\ndefault = [\"mouth\"]\nnose = []\nmouth = [\"nose\"]\neyes = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/list_features_path_no_default/out/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour-face = { version = \"0.1.3\", path = \"../dependency\", default-features = false }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/locked_changed/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --locked\")\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/locked_changed/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/locked_unchanged/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/locked_unchanged/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/locked_unchanged/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --locked\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/locked_unchanged/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/lockfile_updated/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nunrelateed-crate = \"0.2.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/lockfile_updated/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/lockfile_updated/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package\", \"unrelateed-crate\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/lockfile_updated/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"99999.0.0\"\nunrelateed-crate = \"0.2.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/manifest_path_package/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/manifest_path_package/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/manifest_path_package/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/manifest_path_package/in/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/manifest_path_package/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/manifest_path_package/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\n            \"--manifest-path\",\n            \"Cargo.toml\",\n            \"--package\",\n            \"cargo-list-test-fixture\",\n            \"cargo-list-test-fixture-dependency\",\n        ])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/manifest_path_package/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/manifest_path_package/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/manifest_path_package/out/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", path = \"../dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/merge_activated_features/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\", features = [\"merge\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/merge_activated_features/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\ndefault-base = []\ndefault-test-base = []\ndefault-merge-base = []\ndefault = [\"default-base\", \"default-test-base\", \"default-merge-base\"]\ntest-base = []\ntest = [\"test-base\", \"default-test-base\"]\nmerge-base = []\nmerge = [\"merge-base\", \"default-merge-base\"]\nunrelated = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/merge_activated_features/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/merge_activated_features/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { workspace = true, features = [\"test\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/merge_activated_features/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/merge_activated_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/merge_activated_features/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\", features = [\"merge\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/merge_activated_features/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\ndefault-base = []\ndefault-test-base = []\ndefault-merge-base = []\ndefault = [\"default-base\", \"default-test-base\", \"default-merge-base\"]\ntest-base = []\ntest = [\"test-base\", \"default-test-base\"]\nmerge-base = []\nmerge = [\"merge-base\", \"default-merge-base\"]\nunrelated = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/merge_activated_features/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { workspace = true, features = [\"test\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/missing_at_in_crate_spec/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package=1.0.0\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/missing_at_in_crate_spec/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/mod.rs",
    "content": "mod add_basic;\nmod add_multiple;\nmod add_no_vendored_package_with_alter_registry;\nmod add_no_vendored_package_with_vendor;\nmod add_toolchain;\nmod build;\nmod build_prefer_existing_version;\nmod change_rename_target;\nmod cyclic_features;\nmod default_features;\nmod deprecated_default_features;\nmod deprecated_section;\nmod detect_workspace_inherit;\nmod detect_workspace_inherit_features;\nmod detect_workspace_inherit_optional;\nmod detect_workspace_inherit_path_base;\nmod detect_workspace_inherit_public;\nmod dev;\nmod dev_build_conflict;\nmod dev_existing_path_base;\nmod dev_prefer_existing_version;\nmod dry_run;\nmod empty_dep_name;\nmod feature_suggestion_multiple;\nmod feature_suggestion_none;\nmod feature_suggestion_single;\nmod features;\nmod features_activated_over_limit;\nmod features_deactivated_over_limit;\nmod features_empty;\nmod features_error_activated_over_limit;\nmod features_error_deactivated_over_limit;\nmod features_multiple_occurrences;\nmod features_preserve;\nmod features_spaced_values;\nmod features_unknown;\nmod features_unknown_no_features;\nmod git;\nmod git_branch;\nmod git_conflicts_namever;\nmod git_dev;\nmod git_inferred_name;\nmod git_inferred_name_multiple;\nmod git_multiple_names;\nmod git_multiple_packages_features;\nmod git_registry;\nmod git_rev;\nmod git_tag;\nmod help;\nmod infer_prerelease;\nmod invalid_arg;\nmod invalid_git_name;\nmod invalid_inherited_dependency;\nmod invalid_key_inherit_dependency;\nmod invalid_key_overwrite_inherit_dependency;\nmod invalid_key_rename_inherit_dependency;\nmod invalid_manifest;\nmod invalid_name_external;\nmod invalid_path;\nmod invalid_path_name;\nmod invalid_path_self;\nmod invalid_target_empty;\nmod invalid_vers;\nmod list_features;\nmod list_features_path;\nmod list_features_path_no_default;\nmod locked_changed;\nmod locked_unchanged;\nmod lockfile_updated;\nmod manifest_path_package;\nmod merge_activated_features;\nmod missing_at_in_crate_spec;\nmod multiple_conflicts_with_features;\nmod multiple_conflicts_with_rename;\nmod namever;\nmod no_args;\nmod no_default_features;\nmod no_optional;\nmod no_public;\nmod normalize_name_git;\nmod normalize_name_path;\nmod normalize_name_path_existing;\nmod normalize_name_registry;\nmod normalize_name_registry_existing;\nmod normalize_name_registry_yanked;\nmod normalize_name_workspace_dep;\nmod offline_empty_cache;\nmod optional;\nmod overwrite_default_features;\nmod overwrite_default_features_with_no_default_features;\nmod overwrite_features;\nmod overwrite_git_with_path;\nmod overwrite_inherit_features_noop;\nmod overwrite_inherit_noop;\nmod overwrite_inherit_optional_noop;\nmod overwrite_inline_features;\nmod overwrite_name_dev_noop;\nmod overwrite_name_noop;\nmod overwrite_no_default_features;\nmod overwrite_no_default_features_with_default_features;\nmod overwrite_no_optional;\nmod overwrite_no_optional_with_optional;\nmod overwrite_no_public;\nmod overwrite_no_public_with_public;\nmod overwrite_optional;\nmod overwrite_optional_with_no_optional;\nmod overwrite_optional_with_optional;\nmod overwrite_path_base_with_version;\nmod overwrite_path_noop;\nmod overwrite_path_with_version;\nmod overwrite_preserves_inline_table;\nmod overwrite_public;\nmod overwrite_public_with_no_public;\nmod overwrite_rename_with_no_rename;\nmod overwrite_rename_with_rename;\nmod overwrite_rename_with_rename_noop;\nmod overwrite_version_with_git;\nmod overwrite_version_with_path;\nmod overwrite_with_rename;\nmod overwrite_workspace_dep;\nmod overwrite_workspace_dep_features;\nmod path;\nmod path_base;\nmod path_base_inferred_name;\nmod path_base_missing_base_path;\nmod path_base_unstable;\nmod path_dev;\nmod path_inferred_name;\nmod path_inferred_name_conflicts_full_feature;\nmod prefixed_v_in_version;\nmod preserve_dep_std_table;\nmod preserve_features_sorted;\nmod preserve_features_table;\nmod preserve_features_unsorted;\nmod preserve_sorted;\nmod preserve_unsorted;\nmod public;\nmod public_common_version;\nmod quiet;\nmod registry;\nmod rename;\nmod require_weak;\nmod rust_version_ignore;\nmod rust_version_incompatible;\nmod rust_version_latest;\nmod rust_version_older;\nmod rustc_ignore;\nmod rustc_incompatible;\nmod rustc_latest;\nmod rustc_older;\nmod script_bare;\nmod script_escape;\nmod script_frontmatter;\nmod script_frontmatter_empty;\nmod script_shebang;\nmod sorted_table_with_dotted_item;\nmod symlink;\nmod target;\nmod target_cfg;\nmod unknown_inherited_feature;\nmod vers;\nmod workspace_name;\nmod workspace_path;\nmod workspace_path_dev;\nmod yanked;\n"
  },
  {
    "path": "tests/testsuite/cargo_add/multiple_conflicts_with_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package1\", ver).publish();\n    }\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 your-face --features nose\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/multiple_conflicts_with_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/multiple_conflicts_with_rename/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 my-package2 --rename renamed\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/multiple_conflicts_with_rename/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/namever/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package\", \"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1@>=0.1.1 my-package2@0.2.3 my-package\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/namever/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"99999.0.0\"\nmy-package1 = \">=0.1.1\"\nmy-package2 = \"0.2.3\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/no_args/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .current_dir(cwd)\n        .assert()\n        .code(1)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/no_args/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/no_default_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 my-package2@0.4.1 --no-default-features\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/no_default_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package1 = { version = \"99999.0.0\", default-features = false }\nmy-package2 = { version = \"0.4.1\", default-features = false }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/no_optional/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --no-optional\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/no_optional/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"0.1.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/no_public/in/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/no_public/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/no_public/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --no-public\")\n        .current_dir(cwd)\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/no_public/out/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"0.1.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_git/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let git_dep = cargo_test_support::git::new(\"git-package\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"git-package\", \"0.3.0+git-package\"),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"git_package\", \"--git\", &git_url])\n        .current_dir(cwd)\n        .assert()\n        .failure() // Fuzzy searching for paths isn't supported at this time\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_git/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path/in/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo_list_test_fixture_dependency --path ../dependency\")\n        .current_dir(&cwd)\n        .assert()\n        .failure() // Fuzzy searching for paths isn't supported at this time\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path/out/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path_existing/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"fuzzy_name\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path_existing/in/fuzzy_name/Cargo.toml",
    "content": "[package]\nname = \"fuzzy_name\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path_existing/in/fuzzy_name/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path_existing/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfuzzy_name = { path = \"../fuzzy_name\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path_existing/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path_existing/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"fuzzy-name\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path_existing/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"fuzzy_name\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path_existing/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfuzzy_name = { path = \"../fuzzy_name\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_path_existing/out/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_registry/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"linked-hash-map\", \"0.5.4\")\n        .feature(\"clippy\", &[])\n        .feature(\"heapsize\", &[])\n        .feature(\"heapsize_impl\", &[])\n        .feature(\"nightly\", &[])\n        .feature(\"serde\", &[])\n        .feature(\"serde_impl\", &[])\n        .feature(\"serde_test\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"inflector\", \"0.11.4\")\n        .feature(\"default\", &[\"heavyweight\", \"lazy_static\", \"regex\"])\n        .feature(\"heavyweight\", &[])\n        .feature(\"lazy_static\", &[])\n        .feature(\"regex\", &[])\n        .feature(\"unstable\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"linked_hash_map Inflector\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_registry/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ninflector = \"0.11.4\"\nlinked-hash-map = \"0.5.4\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_registry_existing/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour_face = { version = \"99999.0.0\", features = [\"eyes\"] }"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_registry_existing/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_registry_existing/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your_face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_registry_existing/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour_face = { version = \"99999.0.0\", features = [\"eyes\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_registry_yanked/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"linked-hash-map\", \"0.5.0\").publish();\n    cargo_test_support::registry::Package::new(\"linked-hash-map\", \"0.5.4\").publish();\n    cargo_test_support::registry::Package::new(\"linked-hash-map\", \"0.6.0\")\n        .yanked(true)\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"linked_hash_map\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_registry_yanked/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nlinked-hash-map = \"0.5.4\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_workspace_dep/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\"]\n\n[workspace.dependencies]\nfuzzy_dependency = \"1.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_workspace_dep/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_workspace_dep/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_workspace_dep/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    Package::new(\"fuzzy_dependency\", \"1.0.0\").publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"fuzzy-dependency\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_workspace_dep/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\"]\n\n[workspace.dependencies]\nfuzzy_dependency = \"1.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_workspace_dep/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfuzzy_dependency.workspace = true\n"
  },
  {
    "path": "tests/testsuite/cargo_add/normalize_name_workspace_dep/out/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/offline_empty_cache/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"--offline my-package\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/offline_empty_cache/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/optional/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --optional\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/optional/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = { version = \"0.1.0\", optional = true }\n\n[features]\nmy-package = [\"dep:my-package\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_default_features/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nmy-package1 = \"99999.0.0\"  # After my-package1\n# Before my-package2\nmy-package2 = \"0.4.1\"  # After my-package2\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_default_features/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_default_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 my-package2@0.4.1 --default-features\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_default_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nmy-package1 = \"99999.0.0\"  # After my-package1\n# Before my-package2\nmy-package2 = \"0.4.1\"  # After my-package2\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_default_features_with_no_default_features/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nmy-package1 = { version = \"99999.0.0\", default-features = true }  # After my-package1\n# Before my-package2\nmy-package2 = { version = \"0.4.1\", default-features = true }  # After my-package2\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_default_features_with_no_default_features/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_default_features_with_no_default_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 my-package2@0.4.1 --no-default-features\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_default_features_with_no_default_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nmy-package1 = { version = \"99999.0.0\", default-features = false }  # After my-package1\n# Before my-package2\nmy-package2 = { version = \"0.4.1\", default-features = false }  # After my-package2\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_features/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before your-face\nyour-face = { version = \"99999.0.0\", features = [\"eyes\"] }  # After your-face\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_features/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --features nose\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before your-face\nyour-face = { version = \"99999.0.0\", features = [\"eyes\", \"nose\"] }  # After your-face\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_git_with_path/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_git_with_path/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_git_with_path/in/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { git = \"git://git.git\", branch = \"main\", optional = true }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_git_with_path/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_git_with_path/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency --path ../dependency\")\n        .current_dir(&cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_git_with_path/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_git_with_path/out/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { optional = true, path = \"../dependency\", version = \"0.0.0\" }\n\n[features]\ncargo-list-test-fixture-dependency = [\"dep:cargo-list-test-fixture-dependency\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_features_noop/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_features_noop/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\ntest = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_features_noop/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_features_noop/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { workspace = true, features = [\"test\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_features_noop/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_features_noop/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_features_noop/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_features_noop/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\ntest = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_features_noop/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { workspace = true, features = [\"test\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_noop/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_noop/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_noop/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_noop/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo.workspace = true\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_noop/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_noop/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_noop/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_noop/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_noop/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo.workspace = true\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_optional_noop/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_optional_noop/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_optional_noop/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_optional_noop/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { workspace = true, optional = true }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_optional_noop/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_optional_noop/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_optional_noop/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\"}"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_optional_noop/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inherit_optional_noop/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { workspace = true, optional = true }\n\n[features]\nfoo = [\"dep:foo\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inline_features/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before your-face\nyour-face = { version = \"99999.0.0\", features = [\"eyes\"] }  # After your-face\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inline_features/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inline_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"unrelateed-crate\", ver).publish();\n    }\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\n            \"unrelateed-crate your-face --features your-face/nose,your-face/mouth -Fyour-face/ears\",\n        )\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_inline_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nunrelateed-crate = \"99999.0.0\"\n# Before your-face\nyour-face = { version = \"99999.0.0\", features = [\"ears\", \"eyes\", \"mouth\", \"nose\"] }  # After your-face\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_dev_noop/in/Cargo.toml",
    "content": "[workspace]\nexclude = [\"dependency\"]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dev-dependencies]\n# Before your-face\nyour-face = { version = \"0.0.0\", path = \"dependency\", default-features = false, features = [\"nose\", \"mouth\"], registry = \"alternative\" }  # After your-face\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_dev_noop/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"your-face\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\nmouth = []\nnose = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_dev_noop/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_dev_noop/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_dev_noop/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::alt_init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .alternative(true)\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --dev\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_dev_noop/out/Cargo.toml",
    "content": "[workspace]\nexclude = [\"dependency\"]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dev-dependencies]\n# Before your-face\nyour-face = { version = \"0.0.0\", path = \"dependency\", default-features = false, features = [\"nose\", \"mouth\"], registry = \"alternative\" }  # After your-face\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_dev_noop/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"your-face\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\nmouth = []\nnose = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_noop/in/Cargo.toml",
    "content": "[workspace]\nexclude = [\"dependency\"]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before your-face\nyour-face = { version = \"0.0.0\", path = \"dependency\", optional = true, default-features = false, features = [\"nose\", \"mouth\"], registry = \"alternative\" }  # After your-face\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_noop/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"your-face\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\nmouth = []\nnose = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_noop/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_noop/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_noop/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::alt_init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .alternative(true)\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_noop/out/Cargo.toml",
    "content": "[workspace]\nexclude = [\"dependency\"]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before your-face\nyour-face = { version = \"0.0.0\", path = \"dependency\", optional = true, default-features = false, features = [\"nose\", \"mouth\"], registry = \"alternative\" }  # After your-face\n\n[features]\nyour-face = [\"dep:your-face\"]\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_name_noop/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"your-face\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\nmouth = []\nnose = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_default_features/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nmy-package1 = \"99999.0.0\"  # After my-package1\n# Before my-package2\nmy-package2 = \"0.4.1\"  # After my-package2\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_default_features/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_default_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 my-package2@0.4.1 --no-default-features\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_default_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nmy-package1 = { version = \"99999.0.0\", default-features = false }  # After my-package1\n# Before my-package2\nmy-package2 = { version = \"0.4.1\", default-features = false }  # After my-package2\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_default_features_with_default_features/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nmy-package1 = { version = \"99999.0.0\", default-features = false }  # After my-package1\n# Before my-package2\nmy-package2 = { version = \"0.4.1\", default-features = false }  # After my-package2\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_default_features_with_default_features/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_default_features_with_default_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 my-package2@0.4.1 --default-features\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_default_features_with_default_features/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nmy-package1 = { version = \"99999.0.0\" }  # After my-package1\n# Before my-package2\nmy-package2 = { version = \"0.4.1\" }  # After my-package2\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_optional/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = \"0.1.0\"  # After my-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_optional/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_optional/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --no-optional\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_optional/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = \"0.1.0\"  # After my-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_optional_with_optional/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = { version = \"0.1.0\", optional = false }  # After my-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_optional_with_optional/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_optional_with_optional/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --optional\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_optional_with_optional/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = { version = \"0.1.0\", optional = true }  # After my-package\n\n[features]\nmy-package = [\"dep:my-package\"]\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_public/in/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = \"0.1.0\"  # After my-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_public/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_public/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --no-public\")\n        .current_dir(cwd)\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_public/out/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = \"0.1.0\"  # After my-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_public_with_public/in/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = { version = \"0.1.0\", public = false }  # After my-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_public_with_public/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_public_with_public/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --public\")\n        .current_dir(cwd)\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_no_public_with_public/out/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = { version = \"0.1.0\", public = true }  # After my-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_optional/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = \"0.1.0\"  # After my-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_optional/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_optional/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --optional\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_optional/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = { version = \"0.1.0\", optional = true }  # After my-package\n\n[features]\nmy-package = [\"dep:my-package\"]\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_optional_with_no_optional/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\ndefault = [\"your-face\"]\nother = [\"your-face/nose\"]\n\n[dependencies]\n# Before your-face\nyour-face = { version = \"99999.0.0\", optional = true }  # After your-face\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_optional_with_no_optional/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_optional_with_no_optional/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --no-optional\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_optional_with_no_optional/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\ndefault = []\nother = [\"your-face/nose\"]\n\n[dependencies]\n# Before your-face\nyour-face = { version = \"99999.0.0\" }  # After your-face\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_optional_with_optional/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nmy-package1 = { version = \"99999.0.0\", optional = true }  # After my-package1\n# End\n\n[features]\ndefault = [\"dep:my-package1\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_optional_with_optional/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_optional_with_optional/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package1\", \"99999.0.0\").publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 --optional\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_optional_with_optional/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nmy-package1 = { version = \"99999.0.0\", optional = true }  # After my-package1\n# End\n\n[features]\ndefault = [\"dep:my-package1\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_base_with_version/in/.cargo/config.toml",
    "content": "[path-bases]\nmy_base = \".\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_base_with_version/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_base_with_version/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_base_with_version/in/primary/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { optional = true, path = \"dependency\", base = \"my_base\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_base_with_version/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_base_with_version/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", \"20.0.0\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency@20.0\")\n        .current_dir(&cwd)\n        .masquerade_as_nightly_cargo(&[\"path-base\"])\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_base_with_version/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_base_with_version/out/primary/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { optional = true, version = \"20.0\" }\n\n[features]\ncargo-list-test-fixture-dependency = [\"dep:cargo-list-test-fixture-dependency\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_noop/in/Cargo.toml",
    "content": "[workspace]\nexclude = [\"dependency\"]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nyour-face = { version = \"0.0.0\", path = \"dependency\", optional = true, default-features = false, features = [\"nose\", \"mouth\"], registry = \"alternative\" }  # After my-package1\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_noop/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"your-face\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\nmouth = []\nnose = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_noop/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_noop/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_noop/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::alt_init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .alternative(true)\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --path ./dependency\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_noop/out/Cargo.toml",
    "content": "[workspace]\nexclude = [\"dependency\"]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nyour-face = { version = \"0.0.0\", path = \"dependency\", optional = true, default-features = false, features = [\"nose\", \"mouth\"], registry = \"alternative\" }  # After my-package1\n\n[features]\nyour-face = [\"dep:your-face\"]\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_noop/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"your-face\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\nmouth = []\nnose = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_with_version/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_with_version/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_with_version/in/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { optional = true, path = \"../dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_with_version/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_with_version/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency@20.0\")\n        .current_dir(&cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_with_version/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_path_with_version/out/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { optional = true, version = \"20.0\" }\n\n[features]\ncargo-list-test-fixture-dependency = [\"dep:cargo-list-test-fixture-dependency\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_preserves_inline_table/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nyour-face={version=\"99999.0.0\",features=[\"eyes\"]}  # After my-package1\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_preserves_inline_table/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_preserves_inline_table/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --features nose\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_preserves_inline_table/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package1\nyour-face={ version = \"99999.0.0\", features = [\"eyes\", \"nose\"] }  # After my-package1\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_public/in/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = \"0.1.0\"  # After my-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_public/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_public/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --public\")\n        .current_dir(cwd)\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_public/out/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = { version = \"0.1.0\", public = true }  # After my-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_public_with_no_public/in/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = { version = \"0.1.0\", public = true }  # After my-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_public_with_no_public/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_public_with_no_public/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --no-public\")\n        .current_dir(cwd)\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_public_with_no_public/out/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before my-package\nmy-package = { version = \"0.1.0\" }  # After my-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_rename_with_no_rename/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before a1\na1 = { package = \"versioned-package\", version = \"0.1.1\", optional = true }  # After a1\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_rename_with_no_rename/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_rename_with_no_rename/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"versioned-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"versioned-package\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_rename_with_no_rename/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before a1\na1 = { package = \"versioned-package\", version = \"0.1.1\", optional = true }  # After a1\nversioned-package = \"99999.0.0\"\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_rename_with_rename/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before a1\na1 = { package = \"versioned-package\", version = \"0.1.1\", optional = true }  # After a1\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_rename_with_rename/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_rename_with_rename/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"versioned-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"versioned-package --rename a2\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_rename_with_rename/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before a1\na1 = { package = \"versioned-package\", version = \"0.1.1\", optional = true }  # After a1\na2 = { version = \"99999.0.0\", package = \"versioned-package\" }\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before a1\na1 = { package = \"versioned-package\", version = \"0.1.1\", optional = true }  # After a1\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"versioned-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"versioned-package --rename a1\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before a1\na1 = { package = \"versioned-package\", version = \"0.1.1\", optional = true }  # After a1\n\n[features]\na1 = [\"dep:a1\"]\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_version_with_git/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before versioned-package\nversioned-package = { version = \"0.1.1\", optional = true }  # After versioned-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_version_with_git/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_version_with_git/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"versioned-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let git_dep = cargo_test_support::git::new(\"versioned-package\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &cargo_test_support::basic_manifest(\"versioned-package\", \"0.3.0+versioned-package\"),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n    let git_url = git_dep.url().to_string();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"versioned-package\", \"--git\", &git_url])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_version_with_git/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before versioned-package\nversioned-package = { version = \"0.3.0\", optional = true, git = \"[ROOTURL]/versioned-package\" }  # After versioned-package\n\n[features]\nversioned-package = [\"dep:versioned-package\"]\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_version_with_path/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_version_with_path/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_version_with_path/in/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.1.1\", optional = true }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_version_with_path/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_version_with_path/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency --path ../dependency\")\n        .current_dir(&cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_version_with_path/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_version_with_path/out/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", optional = true, path = \"../dependency\" }\n\n[features]\ncargo-list-test-fixture-dependency = [\"dep:cargo-list-test-fixture-dependency\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_with_rename/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\n# Before versioned-package\nversioned-package = { version = \"0.1.1\", optional = true }  # After versioned-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_with_rename/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_with_rename/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"versioned-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"versioned-package --rename renamed\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_with_rename/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nrenamed = { version = \"99999.0.0\", package = \"versioned-package\" }\n# Before versioned-package\nversioned-package = { version = \"0.1.1\", optional = true }  # After versioned-package\n# End\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\" }"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo.workspace = true\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"--path\", \"./dependency\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\" }"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { version = \"0.0.0\", path = \"../dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep_features/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\" }"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep_features/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\ndefault-base = []\ndefault-test-base = []\ndefault-merge-base = []\ndefault = [\"default-base\", \"default-test-base\", \"default-merge-base\"]\ntest-base = []\ntest = [\"test-base\", \"default-test-base\"]\nmerge-base = []\nmerge = [\"merge-base\", \"default-merge-base\"]\nunrelated = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep_features/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep_features/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { workspace = true, features = [\"test\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep_features/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep_features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"--path\", \"./dependency\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep_features/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\" }"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep_features/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\ndefault-base = []\ndefault-test-base = []\ndefault-merge-base = []\ndefault = [\"default-base\", \"default-test-base\", \"default-merge-base\"]\ntest-base = []\ntest = [\"test-base\", \"default-test-base\"]\nmerge-base = []\nmerge = [\"merge-base\", \"default-merge-base\"]\nunrelated = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/overwrite_workspace_dep_features/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { features = [\"test\"], path = \"../dependency\", version = \"0.0.0\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path/in/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency --path ../dependency\")\n        .current_dir(&cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path/out/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", path = \"../dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base/in/.cargo/config.toml",
    "content": "[path-bases]\nmy_base = \".\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_base/in/primary/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_base/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency --path ../dependency --base my_base\")\n        .current_dir(&cwd)\n        .masquerade_as_nightly_cargo(&[\"path-base\"])\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base/out/primary/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", base = \"my_base\", path = \"dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_inferred_name/in/.cargo/config.toml",
    "content": "[path-bases]\nmy_base = \".\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_inferred_name/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_inferred_name/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_inferred_name/in/primary/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_inferred_name/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_inferred_name/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"--path ../dependency --base my_base\")\n        .current_dir(&cwd)\n        .masquerade_as_nightly_cargo(&[\"path-base\"])\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_inferred_name/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_inferred_name/out/primary/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", base = \"my_base\", path = \"dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_missing_base_path/in/primary/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_missing_base_path/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_missing_base_path/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"--path dependency --base bad_base\")\n        .current_dir(&cwd)\n        .masquerade_as_nightly_cargo(&[\"path-base\"])\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_missing_base_path/out/primary/Cargo.toml",
    "content": "cargo-features = [\"path-bases\"]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_unstable/in/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_unstable/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_unstable/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"--path dependency --base mybase\")\n        .current_dir(&cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_base_unstable/out/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_dev/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_dev/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_dev/in/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_dev/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_dev/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency --path ../dependency --dev\")\n        .current_dir(&cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_dev/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_dev/out/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dev-dependencies]\ncargo-list-test-fixture-dependency = { path = \"../dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name/in/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name/in/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"--path ../dependency\")\n        .current_dir(&cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name/out/dependency/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name/out/primary/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", path = \"../dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\", \"optional\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"your-face\"\nversion = \"0.1.3\"\nedition = \"2015\"\n\n[dependencies]\ntoml_edit = \"0.1.5\"\natty = \"0.2.13\"\noptional-dependency = { path = \"../optional\", optional = true }\n\n[features]\ndefault = [\"mouth\"]\nnose = []\nmouth = [\"nose\"]\neyes = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/in/optional/Cargo.toml",
    "content": "[package]\nname = \"optional-dep\"\nversion = \"0.1.3\"\nedition = \"2015\"\n\n[dependencies]\ntoml_edit = \"0.1.5\"\natty = \"0.2.13\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/in/optional/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/in/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"--path ../dependency --features your-face/nose\")\n        .current_dir(&cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\", \"optional\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"your-face\"\nversion = \"0.1.3\"\nedition = \"2015\"\n\n[dependencies]\ntoml_edit = \"0.1.5\"\natty = \"0.2.13\"\noptional-dependency = { path = \"../optional\", optional = true }\n\n[features]\ndefault = [\"mouth\"]\nnose = []\nmouth = [\"nose\"]\neyes = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/out/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/prefixed_v_in_version/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"foo@v0.0.1\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/prefixed_v_in_version/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_dep_std_table/in/Cargo.toml",
    "content": "[package]\nname = \"xxx\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies.your-face]\n# Leading version\nversion = \"99999.0.0\"  # Trailing version\n# Leading optional\noptional = true  # Trailing optional\n# Leading features\nfeatures = []  # Trailing features\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_dep_std_table/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_dep_std_table/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --no-optional\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_dep_std_table/out/Cargo.toml",
    "content": "[package]\nname = \"xxx\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies.your-face]\n# Leading version\nversion = \"99999.0.0\"  # Trailing version\n# Leading features\nfeatures = []  # Trailing features\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_features_sorted/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = { version = \"99999.0.0\", features = [\"a\", \"b\", \"c\", \"e\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_features_sorted/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_features_sorted/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"99999.0.0+my-package\")\n        .feature(\"a\", &[])\n        .feature(\"b\", &[])\n        .feature(\"c\", &[])\n        .feature(\"d\", &[])\n        .feature(\"e\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package -F d\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_features_sorted/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = { version = \"99999.0.0\", features = [\"a\", \"b\", \"c\", \"d\", \"e\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_features_table/in/Cargo.toml",
    "content": "[package]\nname = \"xxx\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\nyour-face = { version = \"99999.0.0\", optional = true }\n\n[features]\ndefault = [\n  \"a\",\n  \"b\",\n  \"c\",\n]\na = [\n  \"your-face?/nose\",  # but not the mouth and nose\n]\nb = []\nc = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_features_table/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_features_table/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --no-optional\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_features_table/out/Cargo.toml",
    "content": "[package]\nname = \"xxx\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\nyour-face = { version = \"99999.0.0\" }\n\n[features]\ndefault = [\n  \"a\",\n  \"b\",\n  \"c\",\n]\na = [\n  \"your-face/nose\",  # but not the mouth and nose\n]\nb = []\nc = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_features_unsorted/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = { version = \"99999.0.0\", features = [\"b\", \"a\", \"d\", \"c\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_features_unsorted/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_features_unsorted/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"99999.0.0+my-package\")\n        .feature(\"a\", &[])\n        .feature(\"b\", &[])\n        .feature(\"c\", &[])\n        .feature(\"d\", &[])\n        .feature(\"e\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package -F e\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_features_unsorted/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = { version = \"99999.0.0\", features = [\"b\", \"a\", \"d\", \"c\", \"e\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_sorted/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"0.1.1\"\nversioned-package = \"0.1.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_sorted/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_sorted/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package\", \"versioned-package\", \"toml\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"toml\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_sorted/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"0.1.1\"\ntoml = \"99999.0.0\"\nversioned-package = \"0.1.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_unsorted/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nversioned-package = \"0.1.1\"\nmy-package = \"0.1.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_unsorted/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_unsorted/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package\", \"versioned-package\", \"toml\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"toml\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/preserve_unsorted/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nversioned-package = \"0.1.1\"\nmy-package = \"0.1.1\"\ntoml = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/public/in/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/public/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/public/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --public\")\n        .current_dir(cwd)\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/public/out/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = { version = \"0.1.0\", public = true }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/public_common_version/in/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"0.1.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/public_common_version/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/public_common_version/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::registry::Dependency;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"my-package-dep\", \"0.1.0\").publish();\n    cargo_test_support::registry::Package::new(\"my-package-dep\", \"0.2.0\").publish();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\")\n        .add_dep(Dependency::new(\"my-package-dep\", \"0.1.0\").public(true))\n        .publish();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.2.0\")\n        .add_dep(Dependency::new(\"my-package-dep\", \"0.2.0\").public(true))\n        .publish();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package-dep\")\n        .current_dir(cwd)\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/public_common_version/out/Cargo.toml",
    "content": "cargo-features = [\"public-dependency\"]\n[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"0.1.0\"\nmy-package-dep = \"^0.1.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/quiet/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"--quiet your-face\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(str![\"\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/quiet/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nyour-face = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/registry/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/registry/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/registry/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::alt_init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver)\n                .alternative(true)\n                .publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 my-package2 --registry alternative\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/registry/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package1 = { version = \"99999.0.0\", registry = \"alternative\" }\nmy-package2 = { version = \"99999.0.0\", registry = \"alternative\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rename/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package --rename renamed\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rename/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nrenamed = { version = \"99999.0.0\", package = \"my-package\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/require_weak/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\neyes = [\"your-face?/eyes\"]\n\n[dependencies]\nyour-face = { version = \"99999.0.0\", optional = true }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/require_weak/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/require_weak/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\")\n        .feature(\"nose\", &[])\n        .feature(\"mouth\", &[])\n        .feature(\"eyes\", &[])\n        .feature(\"ears\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"your-face --no-optional\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/require_weak/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\neyes = [\"your-face/eyes\"]\n\n[dependencies]\nyour-face = { version = \"99999.0.0\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_ignore/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\nrust-version = \"1.68\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_ignore/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_ignore/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.1.0\")\n        .rust_version(\"1.66\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.2.1\")\n        .rust_version(\"1.72\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg(\"--ignore-rust-version\")\n        .arg_line(\"rust-version-user\")\n        .current_dir(cwd)\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .assert()\n        .code(0)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_ignore/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\nrust-version = \"1.68\"\n\n[dependencies]\nrust-version-user = \"0.2.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_ignore/out/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_incompatible/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\nrust-version = \"1.56\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_incompatible/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_incompatible/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.1.0\")\n        .rust_version(\"1.66\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.1.1\")\n        .rust_version(\"1.66\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.2.1\")\n        .rust_version(\"1.72\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"rust-version-user\")\n        .current_dir(cwd)\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_incompatible/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\nrust-version = \"1.56\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_incompatible/out/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_latest/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\nrust-version = \"1.72\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_latest/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_latest/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.1.0\")\n        .rust_version(\"1.66\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.2.1\")\n        .rust_version(\"1.72\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"rust-version-user\")\n        .current_dir(cwd)\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_latest/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\nrust-version = \"1.72\"\n\n[dependencies]\nrust-version-user = \"0.2.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_latest/out/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_older/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\nrust-version = \"1.70\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_older/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_older/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.1.0\")\n        .rust_version(\"1.66\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.2.1\")\n        .rust_version(\"1.72\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"rust-version-user\")\n        .current_dir(cwd)\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_older/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\nrust-version = \"1.70\"\n\n[dependencies]\nrust-version-user = \"0.1.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rust_version_older/out/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_ignore/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_ignore/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_ignore/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.1.0\")\n        .rust_version(\"1.30\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.1.1\")\n        .rust_version(\"1.30\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.2.1\")\n        .rust_version(\"1.2345\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg(\"--ignore-rust-version\")\n        .arg_line(\"rust-version-user\")\n        .current_dir(cwd)\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .assert()\n        .code(0)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_ignore/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nrust-version-user = \"0.2.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_ignore/out/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_incompatible/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_incompatible/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_incompatible/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.2.1\")\n        .rust_version(\"1.2345\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"rust-version-user\")\n        .current_dir(cwd)\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_incompatible/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_incompatible/out/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_latest/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_latest/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_latest/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.1.0\")\n        .rust_version(\"1.30\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.1.1\")\n        .rust_version(\"1.30\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.2.1\")\n        .rust_version(\"1.2345\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"rust-version-user\")\n        .current_dir(cwd)\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_latest/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nrust-version-user = \"0.1.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_latest/out/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_older/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_older/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_older/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.1.0\")\n        .rust_version(\"1.30\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.1.1\")\n        .rust_version(\"1.30\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"rust-version-user\", \"0.2.1\")\n        .rust_version(\"1.2345\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"rust-version-user\")\n        .current_dir(cwd)\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_older/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nrust-version-user = \"0.1.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/rustc_older/out/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/script_bare/in/cargo-test-fixture.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_bare/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .arg(\"-Zscript\")\n        .arg(\"add\")\n        .arg_line(\"--manifest-path cargo-test-fixture.rs my-package\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_bare/out/cargo-test-fixture.rs",
    "content": "---\n[dependencies]\nmy-package = \"99999.0.0\"\n---\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_escape/in/cargo-test-fixture.rs",
    "content": "---------\n[package]\nedition = \"2015\"\ndescription = \"\"\"\nHeader\n------\n\nBody\n\"\"\"\n---------\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_escape/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .arg(\"-Zscript\")\n        .arg(\"add\")\n        .arg_line(\"--manifest-path cargo-test-fixture.rs my-package\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_escape/out/cargo-test-fixture.rs",
    "content": "---------\n[package]\nedition = \"2015\"\ndescription = \"\"\"\nHeader\n------\n\nBody\n\"\"\"\n\n[dependencies]\nmy-package = \"99999.0.0\"\n---------\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_frontmatter/in/cargo-test-fixture.rs",
    "content": "---\n[package]\nedition = \"2015\"\n---\n\nfn main() {\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_frontmatter/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .arg(\"-Zscript\")\n        .arg(\"add\")\n        .arg_line(\"--manifest-path cargo-test-fixture.rs my-package\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_frontmatter/out/cargo-test-fixture.rs",
    "content": "---\n[package]\nedition = \"2015\"\n\n[dependencies]\nmy-package = \"99999.0.0\"\n---\n\nfn main() {\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_frontmatter_empty/in/cargo-test-fixture.rs",
    "content": "---\n---\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_frontmatter_empty/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .arg(\"-Zscript\")\n        .arg(\"add\")\n        .arg_line(\"--manifest-path cargo-test-fixture.rs my-package\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_frontmatter_empty/out/cargo-test-fixture.rs",
    "content": "---\n[dependencies]\nmy-package = \"99999.0.0\"\n---\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_shebang/in/cargo-test-fixture.rs",
    "content": "#!/usr/bin/env cargo\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_shebang/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .arg(\"-Zscript\")\n        .arg(\"add\")\n        .arg_line(\"--manifest-path cargo-test-fixture.rs my-package\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/script_shebang/out/cargo-test-fixture.rs",
    "content": "#!/usr/bin/env cargo\n---\n[dependencies]\nmy-package = \"99999.0.0\"\n---\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/sorted_table_with_dotted_item/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ntoml = \"0.1.1\"\nversioned-package = \"0.1.1\"\n\n[dependencies.my-build-package1]\nversion = \"0.1.1\"\nedition = \"2015\"\n\n"
  },
  {
    "path": "tests/testsuite/cargo_add/sorted_table_with_dotted_item/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/sorted_table_with_dotted_item/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\n        \"unrelateed-crate\",\n        \"versioned-package\",\n        \"toml\",\n        \"my-build-package1\",\n    ] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"unrelateed-crate\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/sorted_table_with_dotted_item/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ntoml = \"0.1.1\"\nunrelateed-crate = \"99999.0.0\"\nversioned-package = \"0.1.1\"\n\n[dependencies.my-build-package1]\nversion = \"0.1.1\"\nedition = \"2015\"\n\n"
  },
  {
    "path": "tests/testsuite/cargo_add/symlink.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry;\nuse std::fs;\n\n#[cargo_test]\nfn symlink_case() {\n    if !cargo_test_support::symlink_supported() {\n        return;\n    }\n\n    registry::init();\n    registry::Package::new(\"test-dep\", \"1.0.0\").publish();\n\n    let project = project().file(\"src/lib.rs\", \"\").build();\n\n    let target_dir = project.root().join(\"target_dir\");\n    fs::create_dir_all(&target_dir).unwrap();\n\n    fs::copy(\n        project.root().join(\"Cargo.toml\"),\n        target_dir.join(\"Cargo.toml\"),\n    )\n    .unwrap();\n\n    fs::remove_file(project.root().join(\"Cargo.toml\")).unwrap();\n\n    #[cfg(unix)]\n    {\n        use std::os::unix::fs::symlink;\n        symlink(\n            target_dir.join(\"Cargo.toml\"),\n            project.root().join(\"Cargo.toml\"),\n        )\n        .unwrap();\n    }\n\n    #[cfg(windows)]\n    {\n        use std::os::windows::fs::symlink_file;\n        symlink_file(\n            target_dir.join(\"Cargo.toml\"),\n            project.root().join(\"Cargo.toml\"),\n        )\n        .unwrap();\n    }\n\n    project.cargo(\"add test-dep\").run();\n\n    assert!(project.root().join(\"Cargo.toml\").is_symlink());\n\n    let target_content = fs::read_to_string(target_dir.join(\"Cargo.toml\")).unwrap();\n    assert!(target_content.contains(\"test-dep\"));\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/target/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 my-package2 --target wasm32-unknown-unknown\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/target/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[target.wasm32-unknown-unknown.dependencies]\nmy-package1 = \"99999.0.0\"\nmy-package2 = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/target_cfg/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for name in [\"my-package1\", \"my-package2\"] {\n        for ver in [\n            \"0.1.1+my-package\",\n            \"0.2.0+my-package\",\n            \"0.2.3+my-package\",\n            \"0.4.1+my-package\",\n            \"20.0.0+my-package\",\n            \"99999.0.0+my-package\",\n            \"99999.0.0-alpha.1+my-package\",\n        ] {\n            cargo_test_support::registry::Package::new(name, ver).publish();\n        }\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package1 my-package2 --target 'cfg(target_os=\\\"linux\\\")'\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/target_cfg/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[target.'cfg(target_os=\"linux\")'.dependencies]\nmy-package1 = \"99999.0.0\"\nmy-package2 = \"99999.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/unknown_inherited_feature/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\", features = [\"not_recognized\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/unknown_inherited_feature/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\ndefault-base = []\ndefault-test-base = []\ndefault-merge-base = []\nlong-feature-name-because-of-formatting-reasons = []\ndefault = [\n    \"default-base\",\n    \"default-test-base\",\n    \"default-merge-base\",\n    \"long-feature-name-because-of-formatting-reasons\",\n]\ntest-base = []\ntest = [\"test-base\", \"default-test-base\"]\nmerge-base = []\nmerge = [\"merge-base\", \"default-merge-base\"]\nunrelated = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/unknown_inherited_feature/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/unknown_inherited_feature/in/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { workspace = true, features = [\"test\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/unknown_inherited_feature/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/unknown_inherited_feature/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .args([\"foo\", \"-p\", \"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/unknown_inherited_feature/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n\n[workspace.dependencies]\nfoo = { version = \"0.0.0\", path = \"./dependency\", features = [\"not_recognized\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/unknown_inherited_feature/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[features]\ndefault-base = []\ndefault-test-base = []\ndefault-merge-base = []\nlong-feature-name-because-of-formatting-reasons = []\ndefault = [\n    \"default-base\",\n    \"default-test-base\",\n    \"default-merge-base\",\n    \"long-feature-name-because-of-formatting-reasons\",\n]\ntest-base = []\ntest = [\"test-base\", \"default-test-base\"]\nmerge-base = []\nmerge = [\"merge-base\", \"default-merge-base\"]\nunrelated = []\n"
  },
  {
    "path": "tests/testsuite/cargo_add/unknown_inherited_feature/out/primary/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nfoo = { workspace = true, features = [\"test\"] }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/vers/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"my-package@>=0.1.1\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/vers/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nmy-package = \">=0.1.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_name/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_name/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_name/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_name/in/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_name/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_name/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency\")\n        .current_dir(&cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_name/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_name/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_name/out/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", path = \"../dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path/in/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency --path ../dependency\")\n        .current_dir(&cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path/out/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\ncargo-list-test-fixture-dependency = { version = \"0.0.0\", path = \"../dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path_dev/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path_dev/in/dependency/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path_dev/in/dependency/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path_dev/in/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path_dev/in/primary/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path_dev/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"cargo-list-test-fixture-dependency\", ver)\n            .publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = project_root.join(\"primary\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"cargo-list-test-fixture-dependency --path ../dependency --dev\")\n        .current_dir(&cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path_dev/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"primary\", \"dependency\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path_dev/out/dependency/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture-dependency\"\nversion = \"0.0.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_add/workspace_path_dev/out/primary/Cargo.toml",
    "content": "[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dev-dependencies]\ncargo-list-test-fixture-dependency = { path = \"../dependency\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_add/yanked/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"linked-hash-map\", \"0.5.0\").publish();\n    cargo_test_support::registry::Package::new(\"linked-hash-map\", \"0.5.4\").publish();\n    cargo_test_support::registry::Package::new(\"linked-hash-map\", \"0.6.0\")\n        .yanked(true)\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"add\")\n        .arg_line(\"linked-hash-map\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_add/yanked/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\nedition = \"2015\"\n\n[dependencies]\nlinked-hash-map = \"0.5.4\"\n"
  },
  {
    "path": "tests/testsuite/cargo_alias_config.rs",
    "content": "//! Tests for `[alias]` config command aliases.\n\nuse std::env;\n\nuse crate::prelude::*;\nuse crate::utils::tools::echo_subcommand;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_bin_manifest, project};\n\n#[cargo_test]\nfn alias_incorrect_config_type() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [alias]\n                b-cargo-test = 5\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"b-cargo-test -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid configuration for key `alias.b-cargo-test`\nexpected a list, but found a integer for `alias.b-cargo-test` in [ROOT]/foo/.cargo/config.toml\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn alias_malformed_config_string() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [alias]\n                b-cargo-test = `\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"b-cargo-test -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not load Cargo configuration\n\nCaused by:\n  could not parse TOML configuration in `[ROOT]/foo/.cargo/config.toml`\n\nCaused by:\n  TOML parse error at line 3, column 32\n    |\n  3 |                 b-cargo-test = `\n    |                                ^\n  string values must be quoted, expected literal string\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn alias_malformed_config_list() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [alias]\n                b-cargo-test = [1, 2]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"b-cargo-test -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] error in [ROOT]/foo/.cargo/config.toml: failed to parse config at `alias.b-cargo-test[0]`\n\nCaused by:\n  invalid type: integer `1`, expected a string\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn alias_config() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [alias]\n                b-cargo-test = \"build\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"b-cargo-test -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dependent_alias() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [alias]\n                b-cargo-test = \"build\"\n                a-cargo-test = [\"b-cargo-test\", \"-v\"]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"a-cargo-test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn builtin_alias_shadowing_external_subcommand() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .executable(\"cargo-t\", \"\")\n        .build();\n\n    let mut paths: Vec<_> = env::split_paths(&env::var_os(\"PATH\").unwrap_or_default()).collect();\n    paths.push(p.root());\n    let path = env::join_paths(paths).unwrap();\n\n    p.cargo(\"t\")\n        .env(\"PATH\", &path)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn alias_shadowing_external_subcommand() {\n    let echo = echo_subcommand();\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [alias]\n                echo = \"build\"\n            \"#,\n        )\n        .build();\n\n    let mut paths: Vec<_> = env::split_paths(&env::var_os(\"PATH\").unwrap_or_default()).collect();\n    paths.push(echo.target_debug_dir());\n    let path = env::join_paths(paths).unwrap();\n\n    p.cargo(\"echo\")\n        .env(\"PATH\", &path)\n        .with_stderr_data(str![[r#\"\n[WARNING] user-defined alias `echo` is shadowing an external subcommand found at `[ROOT]/cargo-echo/target/debug/cargo-echo[EXE]`\n  |\n  = [NOTE] this was previously accepted but will become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/10049>\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn default_args_alias() {\n    let echo = echo_subcommand();\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [alias]\n                echo = \"echo --flag1 --flag2\"\n                test-1 = \"echo\"\n                build = \"build --verbose\"\n            \"#,\n        )\n        .build();\n\n    let mut paths: Vec<_> = env::split_paths(&env::var_os(\"PATH\").unwrap_or_default()).collect();\n    paths.push(echo.target_debug_dir());\n    let path = env::join_paths(paths).unwrap();\n\n    p.cargo(\"echo\")\n        .env(\"PATH\", &path)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] user-defined alias `echo` is shadowing an external subcommand found at `[ROOT]/cargo-echo/target/debug/cargo-echo[EXE]`\n  |\n  = [NOTE] this was previously accepted but will become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/10049>\n[ERROR] alias echo has unresolvable recursive definition: echo -> echo\n\n\"#]])\n        .run();\n\n    p.cargo(\"test-1\")\n        .env(\"PATH\", &path)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] user-defined alias `echo` is shadowing an external subcommand found at `[ROOT]/cargo-echo/target/debug/cargo-echo[EXE]`\n  |\n  = [NOTE] this was previously accepted but will become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/10049>\n[ERROR] alias test-1 has unresolvable recursive definition: test-1 -> echo -> echo\n\n\"#]])\n        .run();\n\n    // Builtins are not expanded by rule\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[WARNING] user-defined alias `build` is ignored, because it is shadowed by a built-in command\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn corecursive_alias() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [alias]\n                test-1 = \"test-2 --flag1\"\n                test-2 = \"test-3 --flag2\"\n                test-3 = \"test-1 --flag3\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test-1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] alias test-1 has unresolvable recursive definition: test-1 -> test-2 -> test-3 -> test-1\n\n\"#]])\n        .run();\n\n    p.cargo(\"test-2\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] alias test-2 has unresolvable recursive definition: test-2 -> test-3 -> test-1 -> test-2\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn alias_list_test() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n               [alias]\n               b-cargo-test = [\"build\", \"--release\"]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"b-cargo-test -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn alias_with_flags_config() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n               [alias]\n               b-cargo-test = \"build --release\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"b-cargo-test -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn alias_cannot_shadow_builtin_command() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n               [alias]\n               build = \"fetch\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[WARNING] user-defined alias `build` is ignored, because it is shadowed by a built-in command\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn alias_override_builtin_alias() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n               [alias]\n               b = \"run\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"b\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn builtin_alias_takes_options() {\n    // #6381\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"examples/ex1.rs\",\n            r#\"fn main() { println!(\"{}\", std::env::args().skip(1).next().unwrap()) }\"#,\n        )\n        .build();\n\n    p.cargo(\"r --example ex1 -- asdf\")\n        .with_stdout_data(str![[r#\"\nasdf\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn global_options_with_alias() {\n    // Check that global options are passed through.\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"-v c\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn weird_check() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"-- check --invalid_argument -some-other-argument\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] trailing arguments after built-in command `check` are unsupported: `--invalid_argument -some-other-argument`\n\nTo pass the arguments to the subcommand, remove `--`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn empty_alias() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n               [alias]\n               string = \"\"\n               array = []\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"string\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] subcommand is required, but `alias.string` is empty\n\n\"#]])\n        .run();\n\n    p.cargo(\"array\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] subcommand is required, but `alias.array` is empty\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn alias_no_subcommand() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n               [alias]\n               a = \"--locked\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"a\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] subcommand is required, add a subcommand to the command alias `alias.a`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_bench/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"bench\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_bench/mod.rs",
    "content": "mod help;\nmod no_keep_going;\n"
  },
  {
    "path": "tests/testsuite/cargo_bench/no_keep_going/in/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_bench/no_keep_going/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_bench/no_keep_going/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"bench\")\n        .arg(\"--keep-going\")\n        .current_dir(cwd)\n        .assert()\n        .code(1)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_build/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"build\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_build/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_check/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"check\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_check/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_clean/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"clean\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_clean/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_command.rs",
    "content": "//! Tests for custom cargo commands and other global command features.\n\nuse std::env;\nuse std::fs;\nuse std::io::Read;\nuse std::path::{Path, PathBuf};\nuse std::process::Stdio;\nuse std::str;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_exe;\nuse crate::utils::cargo_process;\nuse crate::utils::tools::echo_subcommand;\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::rustc_host;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_bin_manifest, paths, project, project_in_home};\nuse cargo_util::paths::join_paths;\n\nfn path() -> Vec<PathBuf> {\n    env::split_paths(&env::var_os(\"PATH\").unwrap_or_default()).collect()\n}\n\n#[cargo_test]\nfn list_commands_with_descriptions() {\n    let p = project().build();\n    p.cargo(\"--list\")\n        .with_stdout_data(\n            \"\\\n...\n    b                    alias: build\n...\n    build                Compile a local package and all of its dependencies\n...\n    c                    alias: check\n...\n    r                    alias: run\n...\n    read-manifest        DEPRECATED: Print a JSON representation of a Cargo.toml manifest.\n...\n    t                    alias: test\n...\n\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn list_custom_aliases_with_descriptions() {\n    let p = project_in_home(\"proj\")\n        .file(\n            &paths::home().join(\".cargo\").join(\"config\"),\n            r#\"\n            [alias]\n            myaliasstr = \"foo --bar\"\n            myaliasvec = [\"foo\", \"--bar\"]\n        \"#,\n        )\n        .build();\n\n    p.cargo(\"--list\")\n        .with_stdout_data(str![[r#\"\n...\n    myaliasstr           alias: foo --bar\n    myaliasvec           alias: foo --bar\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn list_dedupe() {\n    let p = project()\n        .executable(Path::new(\"path-test-1\").join(\"cargo-dupe\"), \"\")\n        .executable(Path::new(\"path-test-2\").join(\"cargo-dupe\"), \"\")\n        .build();\n\n    let mut path = path();\n    path.push(p.root().join(\"path-test-1\"));\n    path.push(p.root().join(\"path-test-2\"));\n    let path = env::join_paths(path.iter()).unwrap();\n\n    p.cargo(\"--list\")\n        .env(\"PATH\", &path)\n        .with_stdout_data(str![[r#\"\n...\n    dupe\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn list_command_looks_at_path() {\n    let proj = project()\n        .executable(Path::new(\"path-test\").join(\"cargo-1\"), \"\")\n        .build();\n\n    let mut path = path();\n    path.push(proj.root().join(\"path-test\"));\n    let path = env::join_paths(path.iter()).unwrap();\n    let output = cargo_process(\"-v --list\").env(\"PATH\", &path).run();\n    let output = str::from_utf8(&output.stdout).unwrap();\n    assert!(\n        output.contains(\"\\n    1                   \"),\n        \"missing 1: {}\",\n        output\n    );\n}\n\n#[cfg(windows)]\n#[cargo_test]\nfn list_command_looks_at_path_case_mismatch() {\n    let proj = project()\n        .executable(Path::new(\"path-test\").join(\"cargo-1\"), \"\")\n        .build();\n\n    let mut path = path();\n    path.push(proj.root().join(\"path-test\"));\n    let path = env::join_paths(path.iter()).unwrap();\n\n    // See issue #11814: Environment variable names are case-insensitive on Windows.\n    // We need to check that having \"Path\" instead of \"PATH\" is okay.\n    let output = cargo_process(\"-v --list\")\n        .env(\"Path\", &path)\n        .env_remove(\"PATH\")\n        .run();\n    let output = str::from_utf8(&output.stdout).unwrap();\n    assert!(\n        output.contains(\"\\n    1                   \"),\n        \"missing 1: {}\",\n        output\n    );\n}\n\n#[cargo_test]\nfn list_command_handles_known_external_commands() {\n    let p = project()\n        .executable(Path::new(\"path-test\").join(\"cargo-fmt\"), \"\")\n        .build();\n\n    let fmt_desc = \"    fmt                  Formats all bin and lib files of the current crate using rustfmt.\";\n\n    // Without path - fmt isn't there\n    p.cargo(\"--list\")\n        .env(\"PATH\", \"\")\n        .with_stdout_does_not_contain(fmt_desc)\n        .run();\n\n    // With path - fmt is there with known description\n    let mut path = path();\n    path.push(p.root().join(\"path-test\"));\n    let path = env::join_paths(path.iter()).unwrap();\n\n    p.cargo(\"--list\")\n        .env(\"PATH\", &path)\n        .with_stdout_data(str![[r#\"\n...\n    fmt                  Formats all bin and lib files of the current crate using rustfmt.\n...\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn list_command_resolves_symlinks() {\n    let proj = project()\n        .symlink(cargo_exe(), Path::new(\"path-test\").join(\"cargo-2\"))\n        .build();\n\n    let mut path = path();\n    path.push(proj.root().join(\"path-test\"));\n    let path = env::join_paths(path.iter()).unwrap();\n    let output = cargo_process(\"-v --list\").env(\"PATH\", &path).run();\n    let output = str::from_utf8(&output.stdout).unwrap();\n    assert!(\n        output.contains(\"\\n    2                   \"),\n        \"missing 2: {}\",\n        output\n    );\n}\n\n#[cargo_test]\nfn find_closest_capital_c_to_c() {\n    cargo_process(\"C\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no such command: `C`\n\n[HELP] a command with a similar name exists: `c`\n\n[HELP] view all installed commands with `cargo --list`\n[HELP] find a package to install `C` with `cargo search cargo-C`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn find_closest_capital_b_to_b() {\n    cargo_process(\"B\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no such command: `B`\n\n[HELP] a command with a similar name exists: `b`\n\n[HELP] view all installed commands with `cargo --list`\n[HELP] find a package to install `B` with `cargo search cargo-B`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn find_closest_biuld_to_build() {\n    cargo_process(\"biuld\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no such command: `biuld`\n\n[HELP] a command with a similar name exists: `build`\n\n[HELP] view all installed commands with `cargo --list`\n[HELP] find a package to install `biuld` with `cargo search cargo-biuld`\n\n\"#]])\n        .run();\n\n    // But, if we actually have `biuld`, it must work!\n    // https://github.com/rust-lang/cargo/issues/5201\n    Package::new(\"cargo-biuld\", \"1.0.0\")\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    println!(\"Similar, but not identical to, build\");\n                }\n            \"#,\n        )\n        .publish();\n\n    cargo_process(\"install cargo-biuld\").run();\n    cargo_process(\"biuld\")\n        .with_stdout_data(str![[r#\"\nSimilar, but not identical to, build\n\n\"#]])\n        .run();\n    cargo_process(\"--list\")\n        .with_stdout_data(str![[r#\"\n...\n    biuld\n...\n    build                Compile a local package and all of its dependencies\n...\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn find_closest_alias() {\n    let root = paths::root();\n    let my_home = root.join(\"my_home\");\n    fs::create_dir(&my_home).unwrap();\n    fs::write(\n        &my_home.join(\"config.toml\"),\n        r#\"\n            [alias]\n            myalias = \"build\"\n        \"#,\n    )\n    .unwrap();\n\n    cargo_process(\"myalais\")\n        .env(\"CARGO_HOME\", &my_home)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no such command: `myalais`\n\n[HELP] a command with a similar name exists: `myalias`\n\n[HELP] view all installed commands with `cargo --list`\n[HELP] find a package to install `myalais` with `cargo search cargo-myalais`\n\n\"#]])\n        .run();\n\n    // But, if no alias is defined, it must not suggest one!\n    cargo_process(\"myalais\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no such command: `myalais`\n\n[HELP] view all installed commands with `cargo --list`\n[HELP] find a package to install `myalais` with `cargo search cargo-myalais`\n\n\"#]])\n        .run();\n}\n\n// If a subcommand is more than an edit distance of 3 away, we don't make a suggestion.\n#[cargo_test]\nfn find_closest_dont_correct_nonsense() {\n    cargo_process(\"there-is-no-way-that-there-is-a-command-close-to-this\")\n\t\t.cwd(&paths::root())\n\t\t.with_status(101)\n\t\t.with_stderr_data(str![[r#\"\n[ERROR] no such command: `there-is-no-way-that-there-is-a-command-close-to-this`\n\n[HELP] view all installed commands with `cargo --list`\n[HELP] find a package to install `there-is-no-way-that-there-is-a-command-close-to-this` with `cargo search cargo-there-is-no-way-that-there-is-a-command-close-to-this`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn displays_subcommand_on_error() {\n    cargo_process(\"invalid-command\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no such command: `invalid-command`\n\n[HELP] view all installed commands with `cargo --list`\n[HELP] find a package to install `invalid-command` with `cargo search cargo-invalid-command`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn override_cargo_home() {\n    let root = paths::root();\n    let my_home = root.join(\"my_home\");\n    fs::create_dir(&my_home).unwrap();\n    fs::write(\n        &my_home.join(\"config\"),\n        r#\"\n            [cargo-new]\n            vcs = \"none\"\n        \"#,\n    )\n    .unwrap();\n\n    cargo_process(\"new foo\").env(\"CARGO_HOME\", &my_home).run();\n\n    assert!(!paths::root().join(\"foo/.git\").is_dir());\n\n    cargo_process(\"new foo2\").run();\n\n    assert!(paths::root().join(\"foo2/.git\").is_dir());\n}\n\n#[cargo_test]\nfn cargo_subcommand_env() {\n    let src = format!(\n        r#\"\n        use std::env;\n\n        fn main() {{\n            println!(\"{{}}\", env::var(\"{}\").unwrap());\n        }}\n        \"#,\n        cargo::CARGO_ENV\n    );\n\n    let p = project()\n        .at(\"cargo-envtest\")\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"cargo-envtest\"))\n        .file(\"src/main.rs\", &src)\n        .build();\n\n    let target_dir = p.target_debug_dir();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"cargo-envtest\").is_file());\n\n    let cargo = cargo_exe();\n    let mut path = path();\n    path.push(target_dir.clone());\n    let path = env::join_paths(path.iter()).unwrap();\n\n    cargo_process(\"envtest\")\n        .env(\"PATH\", &path)\n        .with_stdout_data(format!(\"{}\\n\", cargo.to_str().unwrap()).raw())\n        .run();\n\n    // Check that subcommands inherit an overridden $CARGO\n    let envtest_bin = target_dir\n        .join(\"cargo-envtest\")\n        .with_extension(std::env::consts::EXE_EXTENSION);\n    let envtest_bin = envtest_bin.to_str().unwrap();\n    // Previously, `$CARGO` would be left at `envtest_bin`. However, with the\n    // fix for #15099, `$CARGO` is now overwritten with the path to the current\n    // exe when it is detected to be a cargo binary.\n    cargo_process(\"envtest\")\n        .env(\"PATH\", &path)\n        .env(cargo::CARGO_ENV, &envtest_bin)\n        .with_stdout_data(format!(\"{}\\n\", cargo.display()).raw())\n        .run();\n}\n\n#[cargo_test]\nfn cargo_cmd_bins_vs_explicit_path() {\n    // Set up `cargo-foo` binary in two places: inside `$HOME/.cargo/bin` and outside of it\n    //\n    // Return paths to both places\n    fn set_up_cargo_foo() -> (PathBuf, PathBuf) {\n        let p = project()\n            .at(\"cargo-foo\")\n            .file(\"Cargo.toml\", &basic_manifest(\"cargo-foo\", \"1.0.0\"))\n            .file(\n                \"src/bin/cargo-foo.rs\",\n                r#\"fn main() { println!(\"INSIDE\"); }\"#,\n            )\n            .file(\n                \"src/bin/cargo-foo2.rs\",\n                r#\"fn main() { println!(\"OUTSIDE\"); }\"#,\n            )\n            .build();\n        p.cargo(\"build\").run();\n        let cargo_bin_dir = paths::home().join(\".cargo/bin\");\n        cargo_bin_dir.mkdir_p();\n        let root_bin_dir = paths::root().join(\"bin\");\n        root_bin_dir.mkdir_p();\n        let exe_name = format!(\"cargo-foo{}\", env::consts::EXE_SUFFIX);\n        fs::rename(p.bin(\"cargo-foo\"), cargo_bin_dir.join(&exe_name)).unwrap();\n        fs::rename(p.bin(\"cargo-foo2\"), root_bin_dir.join(&exe_name)).unwrap();\n\n        (root_bin_dir, cargo_bin_dir)\n    }\n\n    let (outside_dir, inside_dir) = set_up_cargo_foo();\n\n    // If `$CARGO_HOME/bin` is not in a path, prefer it over anything in `$PATH`.\n    //\n    // This is the historical behavior we don't want to break.\n    cargo_process(\"foo\")\n        .with_stdout_data(str![[r#\"\nINSIDE\n\n\"#]])\n        .run();\n\n    // When `$CARGO_HOME/bin` is in the `$PATH`\n    // use only `$PATH` so the user-defined ordering is respected.\n    {\n        cargo_process(\"foo\")\n            .env(\n                \"PATH\",\n                join_paths(&[&inside_dir, &outside_dir], \"PATH\").unwrap(),\n            )\n            .with_stdout_data(str![[r#\"\nINSIDE\n\n\"#]])\n            .run();\n\n        cargo_process(\"foo\")\n            // Note: trailing slash\n            .env(\n                \"PATH\",\n                join_paths(&[inside_dir.join(\"\"), outside_dir.join(\"\")], \"PATH\").unwrap(),\n            )\n            .with_stdout_data(str![[r#\"\nINSIDE\n\n\"#]])\n            .run();\n\n        cargo_process(\"foo\")\n            .env(\n                \"PATH\",\n                join_paths(&[&outside_dir, &inside_dir], \"PATH\").unwrap(),\n            )\n            .with_stdout_data(str![[r#\"\nOUTSIDE\n\n\"#]])\n            .run();\n\n        cargo_process(\"foo\")\n            // Note: trailing slash\n            .env(\n                \"PATH\",\n                join_paths(&[outside_dir.join(\"\"), inside_dir.join(\"\")], \"PATH\").unwrap(),\n            )\n            .with_stdout_data(str![[r#\"\nOUTSIDE\n\n\"#]])\n            .run();\n    }\n}\n\n#[cargo_test]\nfn cargo_subcommand_args() {\n    let p = echo_subcommand();\n    let cargo_foo_bin = p.bin(\"cargo-echo\");\n    assert!(cargo_foo_bin.is_file());\n\n    let mut path = path();\n    path.push(p.target_debug_dir());\n    let path = env::join_paths(path.iter()).unwrap();\n\n    cargo_process(\"echo bar -v --help\")\n        .env(\"PATH\", &path)\n        .with_stdout_data(str![[r#\"\necho bar -v --help\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn explain() {\n    cargo_process(\"--explain E0001\")\n        .with_stdout_data(str![[r#\"\n...\nThis error suggests that the expression arm corresponding to the noted pattern[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn closed_output_ok() {\n    // Checks that closed output doesn't cause an error.\n    let mut p = cargo_process(\"--list\").build_command();\n    p.stdout(Stdio::piped()).stderr(Stdio::piped());\n    let mut child = p.spawn().unwrap();\n    // Close stdout\n    drop(child.stdout.take());\n    // Read stderr\n    let mut s = String::new();\n    child\n        .stderr\n        .as_mut()\n        .unwrap()\n        .read_to_string(&mut s)\n        .unwrap();\n    let status = child.wait().unwrap();\n    assert!(status.success());\n    assert!(s.is_empty(), \"{}\", s);\n}\n\n#[cargo_test]\nfn subcommand_leading_plus_output_contains() {\n    cargo_process(\"+nightly\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no such command: `+nightly`\n\n[HELP] invoke `cargo` through `rustup` to handle `+toolchain` directives\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn full_did_you_mean() {\n    cargo_process(\"bluid\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no such command: `bluid`\n\n[HELP] a command with a similar name exists: `build`\n\n[HELP] view all installed commands with `cargo --list`\n[HELP] find a package to install `bluid` with `cargo search cargo-bluid`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn overwrite_cargo_environment_variable() {\n    let rustc_host = rustc_host();\n    // If passed arguments `arg1 arg2 ...`, this program runs them as a command.\n    // If passed no arguments, this program simply prints `$CARGO`.\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    let mut args = std::env::args().skip(1);\n                    if let Some(arg1) = args.next() {\n                        let status = std::process::Command::new(arg1)\n                            .args(args)\n                            .status()\n                            .unwrap();\n                        assert!(status.success());\n                    } else {\n                        eprintln!(\"{}\", std::env::var(\"CARGO\").unwrap());\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    // Create two other cargo binaries in the project root, one with the wrong\n    // name and one with the right name.\n    let cargo_exe = crate::utils::cargo_exe();\n    let wrong_name_path = p\n        .root()\n        .join(format!(\"wrong_name{}\", env::consts::EXE_SUFFIX));\n    let other_cargo_path = p.root().join(cargo_exe.file_name().unwrap());\n    std::fs::hard_link(&cargo_exe, &wrong_name_path).unwrap();\n    std::fs::hard_link(&cargo_exe, &other_cargo_path).unwrap();\n\n    // The output of each of the following commands should be `path-to-cargo`:\n    // ```\n    // cargo run\n    // cargo run -- cargo run\n    // cargo run -- wrong_name run\n    // ```\n\n    let cargo = cargo_exe.display().to_string();\n    let wrong_name = wrong_name_path.display().to_string();\n    let stderr_cargo = format!(\n        \"{}[EXE]\\n\",\n        cargo_exe\n            .with_extension(\"\")\n            .to_str()\n            .unwrap()\n            .replace(rustc_host, \"[HOST_TARGET]\")\n    );\n\n    for cmd in [\n        \"run\",\n        &format!(\"run -- {cargo} run\"),\n        &format!(\"run -- {wrong_name} run\"),\n    ] {\n        p.cargo(cmd).with_stderr_contains(&stderr_cargo).run();\n    }\n\n    // The output of the following command should be `path-to-other-cargo`:\n    // ```\n    // cargo run -- other_cargo run\n    // ```\n\n    let other_cargo = other_cargo_path.display().to_string();\n    let stderr_other_cargo = format!(\n        \"{}[EXE]\\n\",\n        other_cargo_path\n            .with_extension(\"\")\n            .to_str()\n            .unwrap()\n            .replace(p.root().parent().unwrap().to_str().unwrap(), \"[ROOT]\")\n    );\n\n    p.cargo(&format!(\"run -- {other_cargo} run\"))\n        .with_stderr_contains(stderr_other_cargo)\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_config/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"config\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_config/mod.rs",
    "content": "//! Tests for the `cargo config` command.\n\nuse super::config::write_config_at;\nuse crate::prelude::*;\nuse cargo_test_support::paths;\nuse cargo_test_support::str;\nuse std::fs;\nuse std::path::PathBuf;\n\nmod help;\n\nfn cargo_process(s: &str) -> cargo_test_support::Execs {\n    let mut p = crate::utils::cargo_process(s);\n    // Clear out some of the environment added by the default cargo_process so\n    // the tests don't need to deal with it.\n    p.env_remove(\"CARGO_PROFILE_DEV_SPLIT_DEBUGINFO\")\n        .env_remove(\"CARGO_PROFILE_TEST_SPLIT_DEBUGINFO\")\n        .env_remove(\"CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO\")\n        .env_remove(\"CARGO_PROFILE_BENCH_SPLIT_DEBUGINFO\")\n        .env_remove(\"CARGO_INCREMENTAL\");\n    p\n}\n\n#[cargo_test]\nfn gated() {\n    cargo_process(\"config get\")\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `cargo config` command is unstable, pass `-Z unstable-options` to enable it\nSee https://github.com/rust-lang/cargo/issues/9301 for more information about the `cargo config` command.\n\n\"#]])\n        .run();\n}\n\nfn common_setup() -> PathBuf {\n    write_config_at(\n        paths::home().join(\".cargo/config.toml\"),\n        \"\n        [alias]\n        foo = \\\"abc --xyz\\\"\n        [build]\n        jobs = 99\n        rustflags = [\\\"--flag-global\\\"]\n        [profile.dev]\n        opt-level = 3\n        [profile.dev.package.foo]\n        opt-level = 1\n        [target.'cfg(target_os = \\\"linux\\\")']\n        runner = \\\"runme\\\"\n\n        # How unknown keys are handled.\n        [extra-table]\n        somekey = \\\"somevalue\\\"\n        \",\n    );\n    let sub_folder = paths::root().join(\"foo/.cargo\");\n    write_config_at(\n        sub_folder.join(\"config.toml\"),\n        \"\n        [alias]\n        sub-example = [\\\"sub\\\", \\\"example\\\"]\n        [build]\n        rustflags = [\\\"--flag-directory\\\"]\n        \",\n    );\n    sub_folder\n}\n\nfn array_setup() -> PathBuf {\n    let home = paths::home();\n    write_config_at(\n        home.join(\".cargo/config.toml\"),\n        r#\"\n        ints = [1, 2, 3]\n\n        bools = [true, false, true]\n\n        strings = [\"hello\", \"world\", \"test\"]\n\n        nested_ints = [[1, 2], [3, 4]]\n        nested_bools = [[true], [false, true]]\n        nested_strings = [[\"a\", \"b\"], [\"3\", \"4\"]]\n        nested_tables = [\n            [\n                { x = \"a\" },\n                { x = \"b\" },\n            ],\n            [\n                { x = \"c\" },\n                { x = \"d\" },\n            ],\n        ]\n        deeply_nested = [[\n            { x = [[[ { x = [], y = 2  } ]]], y = 1 },\n        ]]\n\n        mixed = [{ x = 1 }, true, [false], \"hello\", 123]\n\n        [[tables]]\n        name = \"first\"\n        value = 1\n        [[tables]]\n        name = \"second\"\n        value = 2\n\n        \"#,\n    );\n    home\n}\n\n#[cargo_test]\nfn get_toml() {\n    // Notes:\n    // - The \"extra-table\" is shown without a warning. I'm not sure how that\n    //   should be handled, since displaying warnings could cause problems\n    //   with ingesting the output.\n    // - Environment variables aren't loaded. :(\n    let sub_folder = common_setup();\n    cargo_process(\"config get -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .env(\"CARGO_ALIAS_BAR\", \"cat dog\")\n        .env(\"CARGO_BUILD_JOBS\", \"100\")\n        // The weird forward slash in the linux line is due to testsuite normalization.\n        .with_stdout_data(str![[r#\"\nalias.foo = \"abc --xyz\"\nalias.sub-example = [\"sub\", \"example\"]\nbuild.jobs = 99\nbuild.rustflags = [\"--flag-global\", \"--flag-directory\"]\nextra-table.somekey = \"somevalue\"\nprofile.dev.opt-level = 3\nprofile.dev.package.foo.opt-level = 1\ntarget.'cfg(target_os = \"linux\")'.runner = \"runme\"\n# The following environment variables may affect the loaded values.\n# CARGO_ALIAS_BAR=[..]cat dog[..]\n# CARGO_BUILD_JOBS=100\n# CARGO_HOME=[ROOT]/home/.cargo\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    // Env keys work if they are specific.\n    cargo_process(\"config get build.jobs -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .env(\"CARGO_BUILD_JOBS\", \"100\")\n        .with_stdout_data(str![[r#\"\nbuild.jobs = 100\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    // Array value.\n    cargo_process(\"config get build.rustflags -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r#\"\nbuild.rustflags = [\"--flag-global\", \"--flag-directory\"]\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    // Sub-table\n    cargo_process(\"config get profile -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r#\"\nprofile.dev.opt-level = 3\nprofile.dev.package.foo.opt-level = 1\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    // Specific profile entry.\n    cargo_process(\"config get profile.dev.opt-level -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r#\"\nprofile.dev.opt-level = 3\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    // A key that isn't set.\n    cargo_process(\"config get build.rustc -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_status(101)\n        .with_stdout_data(str![[r#\"\"#]])\n        .with_stderr_data(str![[r#\"\n[ERROR] config value `build.rustc` is not set\n\n\"#]])\n        .run();\n\n    // A key that is not part of Cargo's config schema.\n    cargo_process(\"config get not.set -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_status(101)\n        .with_stdout_data(str![[r#\"\"#]])\n        .with_stderr_data(str![[r#\"\n[ERROR] config value `not.set` is not set\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn get_toml_with_array_any_types() {\n    let cwd = &array_setup();\n    cargo_process(\"config get -Zunstable-options\")\n        .cwd(cwd)\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r#\"\nbools = [true, false, true]\ndeeply_nested = [[{ x = [[[{ x = [], y = 2 }]]], y = 1 }]]\nints = [1, 2, 3]\nmixed = [{ x = 1 }, true, [false], \"hello\", 123]\nnested_bools = [[true], [false, true]]\nnested_ints = [[1, 2], [3, 4]]\nnested_strings = [[\"a\", \"b\"], [\"3\", \"4\"]]\nnested_tables = [[{ x = \"a\" }, { x = \"b\" }], [{ x = \"c\" }, { x = \"d\" }]]\nstrings = [\"hello\", \"world\", \"test\"]\ntables = [{ name = \"first\", value = 1 }, { name = \"second\", value = 2 }]\n# The following environment variables may affect the loaded values.\n# CARGO_HOME=[ROOT]/home/.cargo\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    // Unfortunately there is no TOML syntax to index an array item.\n    cargo_process(\"config get tables -Zunstable-options\")\n        .cwd(cwd)\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r#\"\ntables = [{ name = \"first\", value = 1 }, { name = \"second\", value = 2 }]\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn get_json() {\n    let sub_folder = common_setup();\n    cargo_process(\"config get --format=json -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .env(\"CARGO_ALIAS_BAR\", \"cat dog\")\n        .env(\"CARGO_BUILD_JOBS\", \"100\")\n        .with_stdout_data(\n            r#\"\n{\n  \"alias\": {\n    \"foo\": \"abc --xyz\",\n    \"sub-example\": [\n      \"sub\",\n      \"example\"\n    ]\n  },\n  \"build\": {\n    \"jobs\": 99,\n    \"rustflags\": [\n      \"--flag-global\",\n      \"--flag-directory\"\n    ]\n  },\n  \"extra-table\": {\n    \"somekey\": \"somevalue\"\n  },\n  \"profile\": {\n    \"dev\": {\n      \"opt-level\": 3,\n      \"package\": {\n        \"foo\": {\n          \"opt-level\": 1\n        }\n      }\n    }\n  },\n  \"target\": {\n    \"cfg(target_os = \\\"linux\\\")\": {\n      \"runner\": \"runme\"\n    }\n  }\n}\n\n\"#\n            .is_json(),\n        )\n        .with_stderr_data(str![[r#\"\n[NOTE] The following environment variables may affect the loaded values.\nCARGO_ALIAS_BAR=[..]cat dog[..]\nCARGO_BUILD_JOBS=100\nCARGO_HOME=[ROOT]/home/.cargo\n\n\"#]])\n        .run();\n\n    // json-value is the same for the entire root table\n    cargo_process(\"config get --format=json-value -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(\n            r#\"\n{\n  \"alias\": {\n    \"foo\": \"abc --xyz\",\n    \"sub-example\": [\n      \"sub\",\n      \"example\"\n    ]\n  },\n  \"build\": {\n    \"jobs\": 99,\n    \"rustflags\": [\n      \"--flag-global\",\n      \"--flag-directory\"\n    ]\n  },\n  \"extra-table\": {\n    \"somekey\": \"somevalue\"\n  },\n  \"profile\": {\n    \"dev\": {\n      \"opt-level\": 3,\n      \"package\": {\n        \"foo\": {\n          \"opt-level\": 1\n        }\n      }\n    }\n  },\n  \"target\": {\n    \"cfg(target_os = \\\"linux\\\")\": {\n      \"runner\": \"runme\"\n    }\n  }\n}\n  \n\"#\n            .is_json(),\n        )\n        .with_stderr_data(str![[r#\"\n[NOTE] The following environment variables may affect the loaded values.\nCARGO_HOME=[ROOT]/home/.cargo\n\n\"#]])\n        .run();\n\n    cargo_process(\"config get --format=json build.jobs -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r#\"\n{\"build\":{\"jobs\":99}}\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    cargo_process(\"config get --format=json-value build.jobs -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r#\"\n99\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn get_json_with_array_any_types() {\n    let cwd = &array_setup();\n    cargo_process(\"config get --format=json -Zunstable-options\")\n        .cwd(cwd)\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"bools\": [\n    true,\n    false,\n    true\n  ],\n  \"deeply_nested\": [\n    [\n      {\n        \"x\": [\n          [\n            [\n              {\n                \"x\": [],\n                \"y\": 2\n              }\n            ]\n          ]\n        ],\n        \"y\": 1\n      }\n    ]\n  ],\n  \"ints\": [\n    1,\n    2,\n    3\n  ],\n  \"mixed\": [\n    {\n      \"x\": 1\n    },\n    true,\n    [\n      false\n    ],\n    \"hello\",\n    123\n  ],\n  \"nested_bools\": [\n    [\n      true\n    ],\n    [\n      false,\n      true\n    ]\n  ],\n  \"nested_ints\": [\n    [\n      1,\n      2\n    ],\n    [\n      3,\n      4\n    ]\n  ],\n  \"nested_strings\": [\n    [\n      \"a\",\n      \"b\"\n    ],\n    [\n      \"3\",\n      \"4\"\n    ]\n  ],\n  \"nested_tables\": [\n    [\n      {\n        \"x\": \"a\"\n      },\n      {\n        \"x\": \"b\"\n      }\n    ],\n    [\n      {\n        \"x\": \"c\"\n      },\n      {\n        \"x\": \"d\"\n      }\n    ]\n  ],\n  \"strings\": [\n    \"hello\",\n    \"world\",\n    \"test\"\n  ],\n  \"tables\": [\n    {\n      \"name\": \"first\",\n      \"value\": 1\n    },\n    {\n      \"name\": \"second\",\n      \"value\": 2\n    }\n  ]\n}\n\"#]]\n            .is_json(),\n        )\n        .with_stderr_data(str![[r#\"\n[NOTE] The following environment variables may affect the loaded values.\nCARGO_HOME=[ROOT]/home/.cargo\n\n\"#]])\n        .run();\n\n    // Unfortunately there is no TOML syntax to index an array item.\n    cargo_process(\"config get tables --format=json -Zunstable-options\")\n        .cwd(cwd)\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"tables\": [\n    {\n      \"name\": \"first\",\n      \"value\": 1\n    },\n    {\n      \"name\": \"second\",\n      \"value\": 2\n    }\n  ]\n}\n\"#]]\n            .is_json(),\n        )\n        .with_stderr_data(str![\"\"])\n        .run();\n}\n\n#[cargo_test]\nfn show_origin_toml() {\n    let sub_folder = common_setup();\n    cargo_process(\"config get --show-origin -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r#\"\nalias.foo = \"abc --xyz\" # [ROOT]/home/.cargo/config.toml\nalias.sub-example = [\n    \"sub\", # [ROOT]/foo/.cargo/config.toml\n    \"example\", # [ROOT]/foo/.cargo/config.toml\n]\nbuild.jobs = 99 # [ROOT]/home/.cargo/config.toml\nbuild.rustflags = [\n    \"--flag-global\", # [ROOT]/home/.cargo/config.toml\n    \"--flag-directory\", # [ROOT]/foo/.cargo/config.toml\n]\nextra-table.somekey = \"somevalue\" # [ROOT]/home/.cargo/config.toml\nprofile.dev.opt-level = 3 # [ROOT]/home/.cargo/config.toml\nprofile.dev.package.foo.opt-level = 1 # [ROOT]/home/.cargo/config.toml\ntarget.'cfg(target_os = \"linux\")'.runner = \"runme\" # [ROOT]/home/.cargo/config.toml\n# The following environment variables may affect the loaded values.\n# CARGO_HOME=[ROOT]/home/.cargo\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    cargo_process(\"config get --show-origin build.rustflags -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .env(\"CARGO_BUILD_RUSTFLAGS\", \"env1 env2\")\n        .with_stdout_data(str![[r#\"\nbuild.rustflags = [\n    \"--flag-global\", # [ROOT]/home/.cargo/config.toml\n    \"--flag-directory\", # [ROOT]/foo/.cargo/config.toml\n    \"env1\", # environment variable `CARGO_BUILD_RUSTFLAGS`\n    \"env2\", # environment variable `CARGO_BUILD_RUSTFLAGS`\n]\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn show_origin_toml_with_array_any_types() {\n    let cwd = &array_setup();\n    cargo_process(\"config get --show-origin -Zunstable-options\")\n        .cwd(cwd)\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r#\"\nbools = [\n    true, # [ROOT]/home/.cargo/config.toml\n    false, # [ROOT]/home/.cargo/config.toml\n    true, # [ROOT]/home/.cargo/config.toml\n]\ndeeply_nested = [\n    [{ x = [[[{ x = [], y = 2 }]]], y = 1 }], # [ROOT]/home/.cargo/config.toml\n]\nints = [\n    1, # [ROOT]/home/.cargo/config.toml\n    2, # [ROOT]/home/.cargo/config.toml\n    3, # [ROOT]/home/.cargo/config.toml\n]\nmixed = [\n    { x = 1 }, # [ROOT]/home/.cargo/config.toml\n    true, # [ROOT]/home/.cargo/config.toml\n    [false], # [ROOT]/home/.cargo/config.toml\n    \"hello\", # [ROOT]/home/.cargo/config.toml\n    123, # [ROOT]/home/.cargo/config.toml\n]\nnested_bools = [\n    [true], # [ROOT]/home/.cargo/config.toml\n    [false, true], # [ROOT]/home/.cargo/config.toml\n]\nnested_ints = [\n    [1, 2], # [ROOT]/home/.cargo/config.toml\n    [3, 4], # [ROOT]/home/.cargo/config.toml\n]\nnested_strings = [\n    [\"a\", \"b\"], # [ROOT]/home/.cargo/config.toml\n    [\"3\", \"4\"], # [ROOT]/home/.cargo/config.toml\n]\nnested_tables = [\n    [{ x = \"a\" }, { x = \"b\" }], # [ROOT]/home/.cargo/config.toml\n    [{ x = \"c\" }, { x = \"d\" }], # [ROOT]/home/.cargo/config.toml\n]\nstrings = [\n    \"hello\", # [ROOT]/home/.cargo/config.toml\n    \"world\", # [ROOT]/home/.cargo/config.toml\n    \"test\", # [ROOT]/home/.cargo/config.toml\n]\ntables = [\n    { name = \"first\", value = 1 }, # [ROOT]/home/.cargo/config.toml\n    { name = \"second\", value = 2 }, # [ROOT]/home/.cargo/config.toml\n]\n# The following environment variables may affect the loaded values.\n# CARGO_HOME=[ROOT]/home/.cargo\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    // Unfortunately there is no TOML syntax to index an array item.\n    cargo_process(\"config get tables --show-origin -Zunstable-options\")\n        .cwd(cwd)\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r#\"\ntables = [\n    { name = \"first\", value = 1 }, # [ROOT]/home/.cargo/config.toml\n    { name = \"second\", value = 2 }, # [ROOT]/home/.cargo/config.toml\n]\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn show_origin_toml_cli() {\n    let sub_folder = common_setup();\n    cargo_process(\"config get --show-origin build.jobs -Zunstable-options --config build.jobs=123\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .env(\"CARGO_BUILD_JOBS\", \"1\")\n        .with_stdout_data(str![[r#\"\nbuild.jobs = 123 # --config cli option\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    cargo_process(\"config get --show-origin build.rustflags -Zunstable-options --config\")\n        .arg(\"build.rustflags=[\\\"cli1\\\",\\\"cli2\\\"]\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .env(\"CARGO_BUILD_RUSTFLAGS\", \"env1 env2\")\n        .with_stdout_data(str![[r#\"\nbuild.rustflags = [\n    \"--flag-global\", # [ROOT]/home/.cargo/config.toml\n    \"--flag-directory\", # [ROOT]/foo/.cargo/config.toml\n    \"env1\", # environment variable `CARGO_BUILD_RUSTFLAGS`\n    \"env2\", # environment variable `CARGO_BUILD_RUSTFLAGS`\n    \"cli1\", # --config cli option\n    \"cli2\", # --config cli option\n]\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn show_origin_json() {\n    let sub_folder = common_setup();\n    cargo_process(\"config get --show-origin --format=json -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `json` format does not support --show-origin, try the `toml` format instead\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unmerged_toml() {\n    let sub_folder = common_setup();\n    cargo_process(\"config get --merged=no -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .env(\"CARGO_ALIAS_BAR\", \"cat dog\")\n        .env(\"CARGO_BUILD_JOBS\", \"100\")\n        .with_stdout_data(str![[r##\"\n# Environment variables\n# CARGO=[..]\n# CARGO_ALIAS_BAR=[..]cat dog[..]\n# CARGO_BUILD_JOBS=100\n# CARGO_HOME=[ROOT]/home/.cargo\n\n# [ROOT]/foo/.cargo/config.toml\nalias.sub-example = [\"sub\", \"example\"]\nbuild.rustflags = [\"--flag-directory\"]\n\n# [ROOT]/home/.cargo/config.toml\nalias.foo = \"abc --xyz\"\nbuild.jobs = 99\nbuild.rustflags = [\"--flag-global\"]\nextra-table.somekey = \"somevalue\"\nprofile.dev.opt-level = 3\nprofile.dev.package.foo.opt-level = 1\ntarget.'cfg(target_os = \"linux\")'.runner = \"runme\"\n\n\n\"##]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    cargo_process(\"config get --merged=no build.rustflags -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .env(\"CARGO_BUILD_RUSTFLAGS\", \"env1 env2\")\n        .with_stdout_data(str![[r#\"\n# Environment variables\n# CARGO_BUILD_RUSTFLAGS=[..]env1 env2[..]\n\n# [ROOT]/foo/.cargo/config.toml\nbuild.rustflags = [\"--flag-directory\"]\n\n# [ROOT]/home/.cargo/config.toml\nbuild.rustflags = [\"--flag-global\"]\n\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    cargo_process(\"config get --merged=no does.not.exist -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stderr_data(str![[r#\"\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    cargo_process(\"config get --merged=no build.rustflags.extra -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] expected table for configuration key `build.rustflags`, but found array in [ROOT]/foo/.cargo/config.toml\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unmerged_toml_cli() {\n    let sub_folder = common_setup();\n    cargo_process(\"config get --merged=no build.rustflags -Zunstable-options --config\")\n        .arg(\"build.rustflags=[\\\"cli1\\\",\\\"cli2\\\"]\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .env(\"CARGO_BUILD_RUSTFLAGS\", \"env1 env2\")\n        .with_stdout_data(str![[r#\"\n# --config cli option\nbuild.rustflags = [\"cli1\", \"cli2\"]\n\n# Environment variables\n# CARGO_BUILD_RUSTFLAGS=[..]env1 env2[..]\n\n# [ROOT]/foo/.cargo/config.toml\nbuild.rustflags = [\"--flag-directory\"]\n\n# [ROOT]/home/.cargo/config.toml\nbuild.rustflags = [\"--flag-global\"]\n\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unmerged_json() {\n    let sub_folder = common_setup();\n    cargo_process(\"config get --merged=no --format=json -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `json` format does not support --merged=no, try the `toml` format instead\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn includes() {\n    let sub_folder = common_setup();\n    fs::write(\n        sub_folder.join(\"config.toml\"),\n        \"\n        include = ['other.toml']\n        [build]\n        rustflags = [\\\"--flag-directory\\\"]\n        \",\n    )\n    .unwrap();\n    fs::write(\n        sub_folder.join(\"other.toml\"),\n        \"\n        [build]\n        rustflags = [\\\"--flag-other\\\"]\n        \",\n    )\n    .unwrap();\n\n    cargo_process(\"config get build.rustflags -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r#\"\nbuild.rustflags = [\"--flag-global\", \"--flag-other\", \"--flag-directory\"]\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    cargo_process(\"config get build.rustflags --show-origin -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r#\"\nbuild.rustflags = [\n    \"--flag-global\", # [ROOT]/home/.cargo/config.toml\n    \"--flag-other\", # [ROOT]/foo/.cargo/other.toml\n    \"--flag-directory\", # [ROOT]/foo/.cargo/config.toml\n]\n\n\"#]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n\n    cargo_process(\"config get --merged=no -Zunstable-options\")\n        .cwd(&sub_folder.parent().unwrap())\n        .masquerade_as_nightly_cargo(&[\"cargo-config\"])\n        .with_stdout_data(str![[r##\"\n# Environment variables\n# CARGO=[..]\n# CARGO_HOME=[ROOT]/home/.cargo\n\n# [ROOT]/foo/.cargo/other.toml\nbuild.rustflags = [\"--flag-other\"]\n\n# [ROOT]/foo/.cargo/config.toml\nbuild.rustflags = [\"--flag-directory\"]\ninclude = [\"other.toml\"]\n\n# [ROOT]/home/.cargo/config.toml\nalias.foo = \"abc --xyz\"\nbuild.jobs = 99\nbuild.rustflags = [\"--flag-global\"]\nextra-table.somekey = \"somevalue\"\nprofile.dev.opt-level = 3\nprofile.dev.package.foo.opt-level = 1\ntarget.'cfg(target_os = \"linux\")'.runner = \"runme\"\n\n\n\"##]])\n        .with_stderr_data(str![[r#\"\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_doc/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"doc\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_doc/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_env_config.rs",
    "content": "//! Tests for `[env]` config.\n\nuse crate::prelude::*;\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_bin_manifest, project};\n\n#[cargo_test]\nfn env_basic() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n        use std::env;\n        fn main() {\n            println!( \"compile-time:{}\", env!(\"ENV_TEST_1233\") );\n            println!( \"run-time:{}\", env::var(\"ENV_TEST_1233\").unwrap());\n        }\n        \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [env]\n                ENV_TEST_1233 = \"Hello\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\ncompile-time:Hello\nrun-time:Hello\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_invalid() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n        fn main() {\n        }\n        \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [env]\n                ENV_TEST_BOOL = false\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `env.ENV_TEST_BOOL`\n\nCaused by:\n  error in [ROOT]/foo/.cargo/config.toml: could not load config key `env.ENV_TEST_BOOL`\n\nCaused by:\n  invalid type: boolean `false`, expected a string or map\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_no_disallowed() {\n    // Checks for keys that are not allowed in the [env] table.\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    for disallowed in &[\"CARGO_HOME\", \"RUSTUP_HOME\", \"RUSTUP_TOOLCHAIN\"] {\n        p.change_file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [env]\n                    {disallowed} = \"foo\"\n                \"#\n            ),\n        );\n        p.cargo(\"check\")\n            .with_status(101)\n            .with_stderr_data(format!(\n                \"\\\n[ERROR] setting the `{disallowed}` environment variable \\\nis not supported in the `[env]` configuration table\n\"\n            ))\n            .run();\n    }\n}\n\n#[cargo_test]\nfn env_force() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n        use std::env;\n        fn main() {\n            println!( \"ENV_TEST_FORCED:{}\", env!(\"ENV_TEST_FORCED\") );\n            println!( \"ENV_TEST_UNFORCED:{}\", env!(\"ENV_TEST_UNFORCED\") );\n            println!( \"ENV_TEST_UNFORCED_DEFAULT:{}\", env!(\"ENV_TEST_UNFORCED_DEFAULT\") );\n        }\n        \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [env]\n                ENV_TEST_UNFORCED_DEFAULT = \"from-config\"\n                ENV_TEST_UNFORCED = { value = \"from-config\", force = false }\n                ENV_TEST_FORCED = { value = \"from-config\", force = true }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .env(\"ENV_TEST_FORCED\", \"from-env\")\n        .env(\"ENV_TEST_UNFORCED\", \"from-env\")\n        .env(\"ENV_TEST_UNFORCED_DEFAULT\", \"from-env\")\n        .with_stdout_data(str![[r#\"\nENV_TEST_FORCED:from-config\nENV_TEST_UNFORCED:from-env\nENV_TEST_UNFORCED_DEFAULT:from-env\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_relative() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo2\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n        use std::env;\n        use std::path::Path;\n        fn main() {\n            println!( \"ENV_TEST_REGULAR:{}\", env!(\"ENV_TEST_REGULAR\") );\n            println!( \"ENV_TEST_REGULAR_DEFAULT:{}\", env!(\"ENV_TEST_REGULAR_DEFAULT\") );\n            println!( \"ENV_TEST_RELATIVE:{}\", env!(\"ENV_TEST_RELATIVE\") );\n\n            assert!( Path::new(env!(\"ENV_TEST_RELATIVE\")).is_absolute() );\n            assert!( !Path::new(env!(\"ENV_TEST_REGULAR\")).is_absolute() );\n            assert!( !Path::new(env!(\"ENV_TEST_REGULAR_DEFAULT\")).is_absolute() );\n        }\n        \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [env]\n                ENV_TEST_REGULAR = { value = \"Cargo.toml\", relative = false }\n                ENV_TEST_REGULAR_DEFAULT = \"Cargo.toml\"\n                ENV_TEST_RELATIVE = { value = \"Cargo.toml\", relative = true }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\").run();\n}\n\n#[cargo_test]\nfn env_no_override() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"unchanged\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n        use std::env;\n        fn main() {\n            println!( \"CARGO_PKG_NAME:{}\", env!(\"CARGO_PKG_NAME\") );\n        }\n        \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [env]\n                CARGO_PKG_NAME = { value = \"from-config\", force = true }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\nCARGO_PKG_NAME:unchanged\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_applied_to_target_info_discovery_rustc() {\n    let wrapper = project()\n        .at(\"wrapper\")\n        .file(\"Cargo.toml\", &basic_manifest(\"wrapper\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                let mut cmd = std::env::args().skip(1).collect::<Vec<_>>();\n                // This will be invoked twice (with `-vV` and with all the `--print`),\n                // make sure the environment variable exists each time.\n                let env_test = std::env::var(\"ENV_TEST\").unwrap();\n                eprintln!(\"WRAPPER ENV_TEST:{env_test}\");\n                let (prog, args) = cmd.split_first().unwrap();\n                let status = std::process::Command::new(prog)\n                    .args(args).status().unwrap();\n                std::process::exit(status.code().unwrap_or(1));\n            }\n            \"#,\n        )\n        .build();\n    wrapper.cargo(\"build\").run();\n    let wrapper = &wrapper.bin(\"wrapper\");\n\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                eprintln!( \"MAIN ENV_TEST:{}\", std::env!(\"ENV_TEST\") );\n            }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [env]\n                ENV_TEST = \"from-config\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", wrapper)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\nWRAPPER ENV_TEST:from-config\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\nMAIN ENV_TEST:from-config\n\n\"#]])\n        .run();\n\n    // Ensure wrapper also maintains the same overridden priority for envs.\n    p.cargo(\"clean\").run();\n    p.cargo(\"run\")\n        .env(\"ENV_TEST\", \"from-env\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", wrapper)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\nWRAPPER ENV_TEST:from-env\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\nMAIN ENV_TEST:from-env\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_changed_defined_in_config_toml() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n        use std::env;\n        fn main() {\n            println!( \"{}\", env!(\"ENV_TEST\") );\n        }\n        \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [env]\n                ENV_TEST = \"from-config\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\nfrom-config\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n\n    p.cargo(\"run\")\n        .env(\"ENV_TEST\", \"from-env\")\n        .with_stdout_data(str![[r#\"\nfrom-env\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n    // This identical cargo invocation is to ensure no rebuild happen.\n    p.cargo(\"run\")\n        .env(\"ENV_TEST\", \"from-env\")\n        .with_stdout_data(str![[r#\"\nfrom-env\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn forced_env_changed_defined_in_config_toml() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n        use std::env;\n        fn main() {\n            println!( \"{}\", env!(\"ENV_TEST\") );\n        }\n        \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [env]\n                ENV_TEST = {value = \"from-config\", force = true}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\nfrom-config\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n\n    p.cargo(\"run\")\n        .env(\"ENV_TEST\", \"from-env\")\n        .with_stdout_data(str![[r#\"\nfrom-config\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_changed_defined_in_config_args() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n        use std::env;\n        fn main() {\n            println!( \"{}\", env!(\"ENV_TEST\") );\n        }\n        \"#,\n        )\n        .build();\n    p.cargo(r#\"run --config 'env.ENV_TEST=\"one\"'\"#)\n        .with_stdout_data(str![[r#\"\none\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n\n    p.cargo(r#\"run --config 'env.ENV_TEST=\"two\"'\"#)\n        .with_stdout_data(str![[r#\"\ntwo\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n    // This identical cargo invocation is to ensure no rebuild happen.\n    p.cargo(r#\"run --config 'env.ENV_TEST=\"two\"'\"#)\n        .with_stdout_data(str![[r#\"\ntwo\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_features.rs",
    "content": "//! Tests for `cargo-features` definitions.\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{project, registry};\n\n#[cargo_test]\nfn feature_required() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                im-a-teapot = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"test-dummy-unstable\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the `im-a-teapot` manifest key is unstable and may not work properly in England\n\nCaused by:\n  feature `test-dummy-unstable` is required\n\n  The package requires the Cargo feature called `test-dummy-unstable`, but that feature is not stabilized in this version of Cargo (1.[..]).\n  Consider adding `cargo-features = [\"test-dummy-unstable\"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information about the status of this feature.\n\n\"#]])\n        .run();\n\n    // Same, but stable.\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the `im-a-teapot` manifest key is unstable and may not work properly in England\n\nCaused by:\n  feature `test-dummy-unstable` is required\n\n  The package requires the Cargo feature called `test-dummy-unstable`, but that feature is not stabilized in this version of Cargo (1.[..]).\n  Consider trying a newer version of Cargo (this may require the nightly release).\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information about the status of this feature.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn feature_required_dependency() {\n    // The feature has been stabilized by a future version of Cargo, and\n    // someone published something uses it, but this version of Cargo has not\n    // yet stabilized it. Don't suggest editing Cargo.toml, since published\n    // packages shouldn't be edited.\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                im-a-teapot = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"test-dummy-unstable\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[ERROR] failed to download replaced source registry `crates-io`\n\nCaused by:\n  failed to parse manifest at `[ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/Cargo.toml`\n\nCaused by:\n  the `im-a-teapot` manifest key is unstable and may not work properly in England\n\nCaused by:\n  feature `test-dummy-unstable` is required\n\n  The package requires the Cargo feature called `test-dummy-unstable`, but that feature is not stabilized in this version of Cargo (1.[..]).\n  Consider trying a more recent nightly release.\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information about the status of this feature.\n\n\"#]])\n        .run();\n\n    // Same, but stable.\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to download `bar v1.0.0`\n\nCaused by:\n  unable to get packages from source\n\nCaused by:\n  failed to download replaced source registry `crates-io`\n\nCaused by:\n  failed to parse manifest at `[ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/Cargo.toml`\n\nCaused by:\n  the `im-a-teapot` manifest key is unstable and may not work properly in England\n\nCaused by:\n  feature `test-dummy-unstable` is required\n\n  The package requires the Cargo feature called `test-dummy-unstable`, but that feature is not stabilized in this version of Cargo (1.[..]).\n  Consider trying a newer version of Cargo (this may require the nightly release).\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information about the status of this feature.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unknown_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"foo\"]\n\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  unknown Cargo.toml feature `foo`\n\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn wrong_kind_of_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"build-dir\"]\n\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  unknown Cargo.toml feature `build-dir`\n\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn feature_syntax() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"bad_feature\"]\n\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  unknown Cargo.toml feature `bad_feature`\n\n  Feature names must use '-' instead of '_'.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn stable_feature_warns() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"test-dummy-stable\"]\n\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] the cargo feature `test-dummy-stable` has been stabilized in the 1.0 release and is no longer necessary to be listed in the manifest\n  See https://doc.rust-lang.org/cargo/ for more information about using this feature.\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zallow-features is unstable\")]\nfn allow_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"test-dummy-unstable\"]\n\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                im-a-teapot = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"-Zallow-features=test-dummy-unstable check\")\n        .masquerade_as_nightly_cargo(&[\"allow-features\", \"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"-Zallow-features=test-dummy-unstable,print-im-a-teapot -Zprint-im-a-teapot check\")\n        .masquerade_as_nightly_cargo(&[\n            \"allow-features\",\n            \"test-dummy-unstable\",\n            \"print-im-a-teapot\",\n        ])\n        .with_stdout_data(str![[r#\"\nim-a-teapot = true\n\n\"#]])\n        .run();\n\n    p.cargo(\"-Zallow-features=test-dummy-unstable -Zprint-im-a-teapot check\")\n        .masquerade_as_nightly_cargo(&[\n            \"allow-features\",\n            \"test-dummy-unstable\",\n            \"print-im-a-teapot\",\n        ])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the feature `print-im-a-teapot` is not in the list of allowed features: [test-dummy-unstable]\n\n\"#]])\n        .run();\n\n    p.cargo(\"-Zallow-features= check\")\n        .masquerade_as_nightly_cargo(&[\"allow-features\", \"test-dummy-unstable\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the feature `test-dummy-unstable` is not in the list of allowed features: []\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zallow-features is unstable\")]\nfn allow_features_to_rustc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![allow(internal_features)]\n                #![feature(rustc_attrs)]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zallow-features= check\")\n        .masquerade_as_nightly_cargo(&[\"allow-features\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CHECKING] a v0.0.1 ([ROOT]/foo)\nerror[E0725]: the feature `rustc_attrs` is not in the list of allowed features\n...\n\"#]])\n        .run();\n\n    p.cargo(\"-Zallow-features=rustc_attrs check\")\n        .masquerade_as_nightly_cargo(&[\"allow-features\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zallow-features is unstable\")]\nfn allow_features_in_cfg() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"test-dummy-unstable\"]\n\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                im-a-teapot = true\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [unstable]\n                allow-features = [\"test-dummy-unstable\", \"print-im-a-teapot\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\n            \"allow-features\",\n            \"test-dummy-unstable\",\n            \"print-im-a-teapot\",\n        ])\n        .with_stderr_data(str![[r#\"\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"-Zprint-im-a-teapot check\")\n        .masquerade_as_nightly_cargo(&[\n            \"allow-features\",\n            \"test-dummy-unstable\",\n            \"print-im-a-teapot\",\n        ])\n        .with_stdout_data(str![[r#\"\nim-a-teapot = true\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"-Zunstable-options check\")\n        .masquerade_as_nightly_cargo(&[\"allow-features\", \"test-dummy-unstable\", \"print-im-a-teapot\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the feature `unstable-options` is not in the list of allowed features: [print-im-a-teapot, test-dummy-unstable]\n\n\"#]])\n        .run();\n\n    // -Zallow-features overrides .cargo/config.toml\n    p.cargo(\"-Zallow-features=test-dummy-unstable -Zprint-im-a-teapot check\")\n        .masquerade_as_nightly_cargo(&[\n            \"allow-features\",\n            \"test-dummy-unstable\",\n            \"print-im-a-teapot\",\n        ])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the feature `print-im-a-teapot` is not in the list of allowed features: [test-dummy-unstable]\n\n\"#]])\n        .run();\n\n    p.cargo(\"-Zallow-features= check\")\n        .masquerade_as_nightly_cargo(&[\n            \"allow-features\",\n            \"test-dummy-unstable\",\n            \"print-im-a-teapot\",\n        ])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the feature `test-dummy-unstable` is not in the list of allowed features: []\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn nightly_feature_requires_nightly() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"test-dummy-unstable\"]\n\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                im-a-teapot = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the cargo feature `test-dummy-unstable` requires a nightly version of Cargo, but this is the `stable` channel\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn nightly_feature_requires_nightly_in_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                cargo-features = [\"test-dummy-unstable\"]\n\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                im-a-teapot = true\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] a v0.0.1 ([ROOT]/foo/a)\n[CHECKING] b v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to get `a` as a dependency of package `b v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `a`\n\nCaused by:\n  unable to update [ROOT]/foo/a\n\nCaused by:\n  failed to parse manifest at `[ROOT]/foo/a/Cargo.toml`\n\nCaused by:\n  the cargo feature `test-dummy-unstable` requires a nightly version of Cargo, but this is the `stable` channel\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cant_publish() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"test-dummy-unstable\"]\n\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                im-a-teapot = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the cargo feature `test-dummy-unstable` requires a nightly version of Cargo, but this is the `stable` channel\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn z_flags_rejected() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"test-dummy-unstable\"]\n\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                im-a-teapot = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check -Zprint-im-a-teapot\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `-Z` flag is only accepted on the nightly channel of Cargo, but this is the `stable` channel\nSee [..]\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -Zarg\")\n        .masquerade_as_nightly_cargo(&[\"test-dummy-unstable\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unknown `-Z` flag specified: arg\n\nFor available unstable features, see https://doc.rust-lang.org/nightly/cargo/reference/unstable.html\nIf you intended to use an unstable rustc feature, try setting `RUSTFLAGS=\"-Zarg\"`\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -Zprint-im-a-teapot\")\n        .masquerade_as_nightly_cargo(&[\"test-dummy-unstable\"])\n        .with_stdout_data(str![[r#\"\nim-a-teapot = true\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_allowed() {\n    let registry = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"test-dummy-unstable\"]\n\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .masquerade_as_nightly_cargo(&[\"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] a v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] a v0.0.1 ([ROOT]/foo)\n[COMPILING] a v0.0.1 ([ROOT]/foo/target/package/a-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] a v0.0.1 ([ROOT]/foo)\n[UPLOADED] a v0.0.1 to registry `crates-io`\n[NOTE] waiting for a v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] a v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn wrong_position() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                cargo-features = [\"test-dummy-unstable\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"test-dummy-unstable\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the field `cargo-features` should be set at the top of Cargo.toml before any tables\n --> Cargo.toml:6:34\n  |\n6 |                 cargo-features = [\"test-dummy-unstable\"]\n  |                                  ^^^^^^^^^^^^^^^^^^^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn z_stabilized() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"check -Z cache-messages\")\n        .masquerade_as_nightly_cargo(&[\"always_nightly\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] flag `-Z cache-messages` has been stabilized in the 1.40 release, and is no longer necessary\n  Message caching is now always enabled.\n\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -Z offline\")\n        .masquerade_as_nightly_cargo(&[\"always_nightly\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] flag `-Z offline` has been stabilized in the 1.36 release\n  Offline mode is now available via the --offline CLI option\n\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_fetch/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"fetch\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_fetch/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_fix/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"fix\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_fix/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_generate_lockfile/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"generate-lockfile\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_generate_lockfile/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_git_checkout/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"git-checkout\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_git_checkout/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_help/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"help\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_help/mod.rs",
    "content": "mod help;\nmod nested_alias_dash_joined;\nmod nested_cmd;\nmod nested_cmd_dash_joined;\nmod nested_cmd_suggestion;\nmod nested_cmd_with_extra_flags;\nmod nested_subcommand_suggestion;\nmod single_alias;\nmod single_cmd;\nmod single_cmd_space_joined;\nmod single_cmd_suggestion;\nmod single_cmd_with_extra_flags;\n"
  },
  {
    "path": "tests/testsuite/cargo_help/nested_alias_dash_joined/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .env(\"__CARGO_TEST_FORCE_HELP_TXT\", \"1\")\n        .arg(\"help\")\n        .arg(\"report-future-incompat\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.txt\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_help/nested_alias_dash_joined/stdout.term.txt",
    "content": "CARGO-REPORT-FUTURE-INCOMPATIBILITIES(1)\n\nNAME\n       cargo-report-future-incompatibilities — Reports any crates which will\n       eventually stop compiling\n\nSYNOPSIS\n       cargo report future-incompatibilities [options]\n\nDESCRIPTION\n       Displays a report of future-incompatible warnings that were emitted\n       during previous builds. These are warnings for changes that may become\n       hard errors in the future, causing dependencies to stop building in a\n       future version of rustc.\n\n       For more, see the chapter on Future incompat report\n       <https://doc.rust-lang.org/cargo/reference/future-incompat-report.html>.\n\nOPTIONS\n       --id id\n           Show the report with the specified Cargo-generated id. If not\n           specified, shows the most recent report.\n\n   Package Selection\n       By default, the package in the current working directory is selected.\n       The -p flag can be used to choose a different package in a workspace.\n\n       -p spec, --package spec\n           The package to display a report for. See cargo-pkgid(1) for the SPEC\n           format.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Display the latest future-incompat report:\n\n              cargo report future-incompat\n\n       2. Display the latest future-incompat report for a specific package:\n\n              cargo report future-incompat --package my-dep@0.0.1\n\nSEE ALSO\n       cargo(1), cargo-report(1), cargo-build(1)\n\n"
  },
  {
    "path": "tests/testsuite/cargo_help/nested_cmd/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .env(\"__CARGO_TEST_FORCE_HELP_TXT\", \"1\")\n        .arg(\"help\")\n        .arg(\"report\")\n        .arg(\"future-incompatibilities\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.txt\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_help/nested_cmd/stdout.term.txt",
    "content": "CARGO-REPORT-FUTURE-INCOMPATIBILITIES(1)\n\nNAME\n       cargo-report-future-incompatibilities — Reports any crates which will\n       eventually stop compiling\n\nSYNOPSIS\n       cargo report future-incompatibilities [options]\n\nDESCRIPTION\n       Displays a report of future-incompatible warnings that were emitted\n       during previous builds. These are warnings for changes that may become\n       hard errors in the future, causing dependencies to stop building in a\n       future version of rustc.\n\n       For more, see the chapter on Future incompat report\n       <https://doc.rust-lang.org/cargo/reference/future-incompat-report.html>.\n\nOPTIONS\n       --id id\n           Show the report with the specified Cargo-generated id. If not\n           specified, shows the most recent report.\n\n   Package Selection\n       By default, the package in the current working directory is selected.\n       The -p flag can be used to choose a different package in a workspace.\n\n       -p spec, --package spec\n           The package to display a report for. See cargo-pkgid(1) for the SPEC\n           format.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Display the latest future-incompat report:\n\n              cargo report future-incompat\n\n       2. Display the latest future-incompat report for a specific package:\n\n              cargo report future-incompat --package my-dep@0.0.1\n\nSEE ALSO\n       cargo(1), cargo-report(1), cargo-build(1)\n\n"
  },
  {
    "path": "tests/testsuite/cargo_help/nested_cmd_dash_joined/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .env(\"__CARGO_TEST_FORCE_HELP_TXT\", \"1\")\n        .arg(\"help\")\n        .arg(\"report-future-incompatibilities\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.txt\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_help/nested_cmd_dash_joined/stdout.term.txt",
    "content": "CARGO-REPORT-FUTURE-INCOMPATIBILITIES(1)\n\nNAME\n       cargo-report-future-incompatibilities — Reports any crates which will\n       eventually stop compiling\n\nSYNOPSIS\n       cargo report future-incompatibilities [options]\n\nDESCRIPTION\n       Displays a report of future-incompatible warnings that were emitted\n       during previous builds. These are warnings for changes that may become\n       hard errors in the future, causing dependencies to stop building in a\n       future version of rustc.\n\n       For more, see the chapter on Future incompat report\n       <https://doc.rust-lang.org/cargo/reference/future-incompat-report.html>.\n\nOPTIONS\n       --id id\n           Show the report with the specified Cargo-generated id. If not\n           specified, shows the most recent report.\n\n   Package Selection\n       By default, the package in the current working directory is selected.\n       The -p flag can be used to choose a different package in a workspace.\n\n       -p spec, --package spec\n           The package to display a report for. See cargo-pkgid(1) for the SPEC\n           format.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Display the latest future-incompat report:\n\n              cargo report future-incompat\n\n       2. Display the latest future-incompat report for a specific package:\n\n              cargo report future-incompat --package my-dep@0.0.1\n\nSEE ALSO\n       cargo(1), cargo-report(1), cargo-build(1)\n\n"
  },
  {
    "path": "tests/testsuite/cargo_help/nested_cmd_suggestion/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .env(\"__CARGO_TEST_FORCE_HELP_TXT\", \"1\")\n        .arg(\"help\")\n        .arg(\"report-future-incomp\")\n        .assert()\n        .code(101)\n        .stdout_eq(file![\"stdout.term.txt\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_help/nested_cmd_suggestion/stdout.term.txt",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_help/nested_cmd_with_extra_flags/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .env(\"__CARGO_TEST_FORCE_HELP_TXT\", \"1\")\n        .arg(\"help\")\n        .arg(\"report\")\n        .arg(\"future-incompatibilities\")\n        .arg(\"--id\")\n        .assert()\n        .code(1)\n        .stdout_eq(file![\"stdout.term.txt\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_help/nested_cmd_with_extra_flags/stdout.term.txt",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_help/nested_subcommand_suggestion/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    // Valid parent command `report`, but invalid subcommand `foo`\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"help\")\n        .arg(\"report\")\n        .arg(\"foo\")\n        .assert()\n        .code(101)\n        .stdout_eq(file![\"stdout.term.txt\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_help/nested_subcommand_suggestion/stdout.term.txt",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_help/single_alias/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .env(\"__CARGO_TEST_FORCE_HELP_TXT\", \"1\")\n        .arg(\"help\")\n        .arg(\"rm\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.txt\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_help/single_alias/stdout.term.txt",
    "content": "CARGO-REMOVE(1)\n\nNAME\n       cargo-remove — Remove dependencies from a Cargo.toml manifest file\n\nSYNOPSIS\n       cargo remove [options] dependency…\n\nDESCRIPTION\n       Remove one or more dependencies from a Cargo.toml manifest.\n\nOPTIONS\n   Section options\n       --dev\n           Remove as a development dependency\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#development-dependencies>.\n\n       --build\n           Remove as a build dependency\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#build-dependencies>.\n\n       --target target\n           Remove as a dependency to the given target platform\n           <https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies>.\n\n           To avoid unexpected shell expansions, you may use quotes around each\n           target, e.g., --target 'cfg(unix)'.\n\n   Miscellaneous Options\n       --dry-run\n           Don’t actually write to the manifest.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Package Selection\n       -p spec…, --package spec…\n           Package to remove from.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Remove regex as a dependency\n\n              cargo remove regex\n\n       2. Remove trybuild as a dev-dependency\n\n              cargo remove --dev trybuild\n\n       3. Remove nom from the wasm32-unknown-unknown dependencies table\n\n              cargo remove --target wasm32-unknown-unknown nom\n\nSEE ALSO\n       cargo(1), cargo-add(1)\n\n"
  },
  {
    "path": "tests/testsuite/cargo_help/single_cmd/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .env(\"__CARGO_TEST_FORCE_HELP_TXT\", \"1\")\n        .arg(\"help\")\n        .arg(\"build\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.txt\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_help/single_cmd/stdout.term.txt",
    "content": "CARGO-BUILD(1)\n\nNAME\n       cargo-build — Compile the current package\n\nSYNOPSIS\n       cargo build [options]\n\nDESCRIPTION\n       Compile local packages and all of their dependencies.\n\nOPTIONS\n   Package Selection\n       By default, when no package selection options are given, the packages\n       selected depend on the selected manifest file (based on the current\n       working directory if --manifest-path is not given). If the manifest is\n       the root of a workspace then the workspaces default members are\n       selected, otherwise only the package defined by the manifest will be\n       selected.\n\n       The default members of a workspace can be set explicitly with the\n       workspace.default-members key in the root manifest. If this is not set,\n       a virtual workspace will include all workspace members (equivalent to\n       passing --workspace), and a non-virtual workspace will include only the\n       root crate itself.\n\n       -p spec…, --package spec…\n           Build only the specified packages. See cargo-pkgid(1) for the SPEC\n           format. This flag may be specified multiple times and supports\n           common Unix glob patterns like *, ? and []. However, to avoid your\n           shell accidentally expanding glob patterns before Cargo handles\n           them, you must use single quotes or double quotes around each\n           pattern.\n\n       --workspace\n           Build all members in the workspace.\n\n       --all\n           Deprecated alias for --workspace.\n\n       --exclude SPEC…\n           Exclude the specified packages. Must be used in conjunction with the\n           --workspace flag. This flag may be specified multiple times and\n           supports common Unix glob patterns like *, ? and []. However, to\n           avoid your shell accidentally expanding glob patterns before Cargo\n           handles them, you must use single quotes or double quotes around\n           each pattern.\n\n   Target Selection\n       When no target selection options are given, cargo build will build all\n       binary and library targets of the selected packages. Binaries are\n       skipped if they have required-features that are missing.\n\n       Binary targets are automatically built if there is an integration test\n       or benchmark being selected to build. This allows an integration test to\n       execute the binary to exercise and test its behavior. The\n       CARGO_BIN_EXE_<name> environment variable\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates>\n       is set when the integration test is built and run so that it can use the\n       env macro <https://doc.rust-lang.org/std/macro.env.html> or the var\n       function <https://doc.rust-lang.org/std/env/fn.var.html> to locate the\n       executable.\n\n       Passing target selection flags will build only the specified targets.\n\n       Note that --bin, --example, --test and --bench flags also support common\n       Unix glob patterns like *, ? and []. However, to avoid your shell\n       accidentally expanding glob patterns before Cargo handles them, you must\n       use single quotes or double quotes around each glob pattern.\n\n       --lib\n           Build the package’s library.\n\n       --bin name…\n           Build the specified binary. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --bins\n           Build all binary targets.\n\n       --example name…\n           Build the specified example. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --examples\n           Build all example targets.\n\n       --test name…\n           Build the specified integration test. This flag may be specified\n           multiple times and supports common Unix glob patterns.\n\n       --tests\n           Build all targets that have the test = true manifest flag set. By\n           default this includes the library and binaries built as unittests,\n           and integration tests. Be aware that this will also build any\n           required dependencies, so the lib target may be built twice (once as\n           a unittest, and once as a dependency for binaries, integration\n           tests, etc.). Targets may be enabled or disabled by setting the test\n           flag in the manifest settings for the target.\n\n       --bench name…\n           Build the specified benchmark. This flag may be specified multiple\n           times and supports common Unix glob patterns.\n\n       --benches\n           Build all targets that have the bench = true manifest flag set. By\n           default this includes the library and binaries built as benchmarks,\n           and bench targets. Be aware that this will also build any required\n           dependencies, so the lib target may be built twice (once as a\n           benchmark, and once as a dependency for binaries, benchmarks, etc.).\n           Targets may be enabled or disabled by setting the bench flag in the\n           manifest settings for the target.\n\n       --all-targets\n           Build all targets. This is equivalent to specifying --lib --bins\n           --tests --benches --examples.\n\n   Feature Selection\n       The feature flags allow you to control which features are enabled. When\n       no feature options are given, the default feature is activated for every\n       selected package.\n\n       See the features documentation\n       <https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options>\n       for more details.\n\n       -F features, --features features\n           Space or comma separated list of features to activate. Features of\n           workspace members may be enabled with package-name/feature-name\n           syntax. This flag may be specified multiple times, which enables all\n           specified features.\n\n       --all-features\n           Activate all available features of all selected packages.\n\n       --no-default-features\n           Do not activate the default feature of the selected packages.\n\n   Compilation Options\n       --target triple\n           Build for the specified target architecture. Flag may be specified\n           multiple times. The default is the host architecture. The general\n           format of the triple is <arch><sub>-<vendor>-<sys>-<abi>.\n\n           Possible values:\n\n           o  Any supported target in rustc --print target-list.\n\n           o  \"host-tuple\", which will internally be substituted by the\n              host’s target. This can be particularly useful if you’re\n              cross-compiling some crates, and don’t want to specify your\n              host’s machine as a target (for instance, an xtask in a shared\n              project that may be worked on by many hosts).\n\n           o  A path to a custom target specification. See Custom Target Lookup\n              Path\n              <https://doc.rust-lang.org/rustc/targets/custom.html#custom-target-lookup-path>\n              for more information.\n\n           This may also be specified with the build.target config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n           Note that specifying this flag makes Cargo run in a different mode\n           where the target artifacts are placed in a separate directory. See\n           the build cache\n           <https://doc.rust-lang.org/cargo/reference/build-cache.html>\n           documentation for more details.\n\n       -r, --release\n           Build optimized artifacts with the release profile. See also the\n           --profile option for choosing a specific profile by name.\n\n       --profile name\n           Build with the given profile. See the reference\n           <https://doc.rust-lang.org/cargo/reference/profiles.html> for more\n           details on profiles.\n\n       --timings\n           Output information how long each compilation takes, and track\n           concurrency information over time.\n\n           A file cargo-timing.html will be written to the target/cargo-timings\n           directory at the end of the build. An additional report with a\n           timestamp in its filename is also written if you want to look at a\n           previous run. These reports are suitable for human consumption only,\n           and do not provide machine-readable timing data.\n\n   Output Options\n       --target-dir directory\n           Directory for all generated artifacts and intermediate files. May\n           also be specified with the CARGO_TARGET_DIR environment variable, or\n           the build.target-dir config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           target in the root of the workspace.\n\n       --artifact-dir directory\n           Copy final artifacts to this directory.\n\n           This option is unstable and available only on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable. See\n           <https://github.com/rust-lang/cargo/issues/6790> for more\n           information.\n\n   Display Options\n       -v, --verbose\n           Use verbose output. May be specified twice for “very verbose”\n           output which includes extra output such as dependency warnings and\n           build script output. May also be specified with the term.verbose\n           config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       -q, --quiet\n           Do not print cargo log messages. May also be specified with the\n           term.quiet config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --color when\n           Control when colored output is used. Valid values:\n\n           o  auto (default): Automatically detect if color support is\n              available on the terminal.\n\n           o  always: Always display colors.\n\n           o  never: Never display colors.\n\n           May also be specified with the term.color config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --message-format fmt\n           The output format for diagnostic messages. Can be specified multiple\n           times and consists of comma-separated values. Valid values:\n\n           o  human (default): Display in a human-readable text format.\n              Conflicts with short and json.\n\n           o  short: Emit shorter, human-readable text messages. Conflicts with\n              human and json.\n\n           o  json: Emit JSON messages to stdout. See the reference\n              <https://doc.rust-lang.org/cargo/reference/external-tools.html#json-messages>\n              for more details. Conflicts with human and short.\n\n           o  json-diagnostic-short: Ensure the rendered field of JSON messages\n              contains the “short” rendering from rustc. Cannot be used\n              with human or short.\n\n           o  json-diagnostic-rendered-ansi: Ensure the rendered field of JSON\n              messages contains embedded ANSI color codes for respecting\n              rustc’s default color scheme. Cannot be used with human or\n              short.\n\n           o  json-render-diagnostics: Instruct Cargo to not include rustc\n              diagnostics in JSON messages printed, but instead Cargo itself\n              should render the JSON diagnostics coming from rustc. Cargo’s\n              own JSON diagnostics and others coming from rustc are still\n              emitted. Cannot be used with human or short.\n\n   Manifest Options\n       --manifest-path path\n           Path to the Cargo.toml file. By default, Cargo searches for the\n           Cargo.toml file in the current directory or any parent directory.\n\n       --ignore-rust-version\n           Ignore rust-version specification in packages.\n\n       --locked\n           Asserts that the exact same dependencies and versions are used as\n           when the existing Cargo.lock file was originally generated. Cargo\n           will exit with an error when either of the following scenarios\n           arises:\n\n           o  The lock file is missing.\n\n           o  Cargo attempted to change the lock file due to a different\n              dependency resolution.\n\n           It may be used in environments where deterministic builds are\n           desired, such as in CI pipelines.\n\n       --offline\n           Prevents Cargo from accessing the network for any reason. Without\n           this flag, Cargo will stop with an error if it needs to access the\n           network and the network is not available. With this flag, Cargo will\n           attempt to proceed without the network if possible.\n\n           Beware that this may result in different dependency resolution than\n           online mode. Cargo will restrict itself to crates that are\n           downloaded locally, even if there might be a newer version as\n           indicated in the local copy of the index. See the cargo-fetch(1)\n           command to download dependencies before going offline.\n\n           May also be specified with the net.offline config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>.\n\n       --frozen\n           Equivalent to specifying both --locked and --offline.\n\n   Common Options\n       +toolchain\n           If Cargo has been installed with rustup, and the first argument to\n           cargo begins with +, it will be interpreted as a rustup toolchain\n           name (such as +stable or +nightly). See the rustup documentation\n           <https://rust-lang.github.io/rustup/overrides.html> for more\n           information about how toolchain overrides work.\n\n       --config KEY=VALUE or PATH\n           Overrides a Cargo configuration value. The argument should be in\n           TOML syntax of KEY=VALUE, or provided as a path to an extra\n           configuration file. This flag may be specified multiple times. See\n           the command-line overrides section\n           <https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides>\n           for more information.\n\n       -C PATH\n           Changes the current working directory before executing any specified\n           operations. This affects things like where cargo looks by default\n           for the project manifest (Cargo.toml), as well as the directories\n           searched for discovering .cargo/config.toml, for example. This\n           option must appear before the command name, for example cargo -C\n           path/to/my-project build.\n\n           This option is only available on the nightly channel\n           <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html> and\n           requires the -Z unstable-options flag to enable (see #10098\n           <https://github.com/rust-lang/cargo/issues/10098>).\n\n       -h, --help\n           Prints help information.\n\n       -Z flag\n           Unstable (nightly-only) flags to Cargo. Run cargo -Z help for\n           details.\n\n   Miscellaneous Options\n       -j N, --jobs N\n           Number of parallel jobs to run. May also be specified with the\n           build.jobs config value\n           <https://doc.rust-lang.org/cargo/reference/config.html>. Defaults to\n           the number of logical CPUs. If negative, it sets the maximum number\n           of parallel jobs to the number of logical CPUs plus provided value.\n           If a string default is provided, it sets the value back to defaults.\n           Should not be 0.\n\n       --keep-going\n           Build as many crates in the dependency graph as possible, rather\n           than aborting the build on the first one that fails to build.\n\n           For example if the current package depends on dependencies fails and\n           works, one of which fails to build, cargo build -j1 may or may not\n           build the one that succeeds (depending on which one of the two\n           builds Cargo picked to run first), whereas cargo build -j1\n           --keep-going would definitely run both builds, even if the one run\n           first fails.\n\n       --future-incompat-report\n           Displays a future-incompat report for any future-incompatible\n           warnings produced during execution of this command\n\n           See cargo-report(1)\n\nENVIRONMENT\n       See the reference\n       <https://doc.rust-lang.org/cargo/reference/environment-variables.html>\n       for details on environment variables that Cargo reads.\n\nEXIT STATUS\n       o  0: Cargo succeeded.\n\n       o  101: Cargo failed to complete.\n\nEXAMPLES\n       1. Build the local package and all of its dependencies:\n\n              cargo build\n\n       2. Build with optimizations:\n\n              cargo build --release\n\nSEE ALSO\n       cargo(1), cargo-rustc(1)\n\n"
  },
  {
    "path": "tests/testsuite/cargo_help/single_cmd_space_joined/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    // Should be `generate-lockfile` but typed wrong as two commands.\n    snapbox::cmd::Command::cargo_ui()\n        .env(\"__CARGO_TEST_FORCE_HELP_TXT\", \"1\")\n        .arg(\"help\")\n        .arg(\"generate\")\n        .arg(\"lockfile\")\n        .assert()\n        .code(101)\n        .stdout_eq(file![\"stdout.term.txt\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_help/single_cmd_space_joined/stdout.term.txt",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_help/single_cmd_suggestion/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .env(\"__CARGO_TEST_FORCE_HELP_TXT\", \"1\")\n        .arg(\"help\")\n        .arg(\"built\")\n        .assert()\n        .code(101)\n        .stdout_eq(file![\"stdout.term.txt\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_help/single_cmd_suggestion/stdout.term.txt",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_help/single_cmd_with_extra_flags/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .env(\"__CARGO_TEST_FORCE_HELP_TXT\", \"1\")\n        .arg(\"help\")\n        .arg(\"build\")\n        .arg(\"--release\")\n        .assert()\n        .code(1)\n        .stdout_eq(file![\"stdout.term.txt\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_help/single_cmd_with_extra_flags/stdout.term.txt",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/basic/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"my-package\"\n            version = \"0.1.0\"\n            description = \"A package for testing\"\n            repository = \"https://github.com/hi-rustin/cargo-infromation\"\n            documentation = \"https://docs.rs/my-package/0.1.0\"\n            license = \"MIT\"\n            edition = \"2018\"\n            rust-version = \"1.50.0\"\n            keywords = [\"foo\", \"bar\", \"baz\"]\n\n            [features]\n            default = [\"feature1\"]\n            feature1 = []\n            feature2 = []\n\n            [dependencies]\n            foo = \"0.1.0\"\n            bar = \"0.2.0\"\n            baz = { version = \"0.3.0\", optional = true }\n\n            [[bin]]\n            name = \"my_bin\"\n\n            [lib]\n            name = \"my_lib\"\n            \"#,\n        )\n        .file(\"src/bin/my_bin.rs\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/crate_name_normalization_from_hyphen_to_underscore/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    cargo_test_support::registry::Package::new(\"my_crate\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"my_crate\"\n            version = \"0.1.0\"\n            description = \"A package for testing\"\n            repository = \"https://github.com/hi-rustin/cargo-infromation\"\n            documentation = \"https://docs.rs/my-package/0.1.0\"\n            license = \"MIT\"\n            edition = \"2018\"\n            rust-version = \"1.50.0\"\n            keywords = [\"foo\", \"bar\", \"baz\"]\n\n            [features]\n            default = [\"feature1\"]\n            feature1 = []\n            feature2 = []\n\n            [dependencies]\n            foo = \"0.1.0\"\n            bar = \"0.2.0\"\n            baz = { version = \"0.3.0\", optional = true }\n\n            [[bin]]\n            name = \"my_bin\"\n\n            [lib]\n            name = \"my_lib\"\n            \"#,\n        )\n        .file(\"src/bin/my_bin.rs\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-crate\") //hyphen on purpose to show the error\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/crate_name_normalization_from_underscore_to_hyphen/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"my-package\"\n            version = \"0.1.0\"\n            description = \"A package for testing\"\n            repository = \"https://github.com/hi-rustin/cargo-infromation\"\n            documentation = \"https://docs.rs/my-package/0.1.0\"\n            license = \"MIT\"\n            edition = \"2018\"\n            rust-version = \"1.50.0\"\n            keywords = [\"foo\", \"bar\", \"baz\"]\n\n            [features]\n            default = [\"feature1\"]\n            feature1 = []\n            feature2 = []\n\n            [dependencies]\n            foo = \"0.1.0\"\n            bar = \"0.2.0\"\n            baz = { version = \"0.3.0\", optional = true }\n\n            [[bin]]\n            name = \"my_bin\"\n\n            [lib]\n            name = \"my_lib\"\n            \"#,\n        )\n        .file(\"src/bin/my_bin.rs\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my_package\") //underscore on purpose to show the error\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/features/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.1\")\n        .feature(\"default\", &[\"feature1\", \"feature2\"])\n        .feature(\"feature1\", &[])\n        .feature(\"feature2\", &[])\n        .publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/features_activated_over_limit/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    const MANY_FEATURES_COUNT: usize = 200;\n    const DEFAULT_FEATURES_COUNT: usize = 100;\n\n    init_registry_without_token();\n    let mut test_package =\n        cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\");\n    let features = (0..MANY_FEATURES_COUNT)\n        .map(|i| format!(\"eyes{i:03}\"))\n        .collect::<Vec<_>>();\n    for name in &features {\n        test_package.feature(name.as_str(), &[]);\n    }\n    let default_features = features\n        .iter()\n        .take(DEFAULT_FEATURES_COUNT)\n        .map(|s| s.as_str())\n        .collect::<Vec<_>>();\n    test_package.feature(\"default\", &default_features);\n    test_package.publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"your-face\")\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/features_activated_over_limit_verbose/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    const MANY_FEATURES_COUNT: usize = 200;\n    const DEFAULT_FEATURES_COUNT: usize = 100;\n\n    init_registry_without_token();\n    let mut test_package =\n        cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\");\n    let features = (0..MANY_FEATURES_COUNT)\n        .map(|i| format!(\"eyes{i:03}\"))\n        .collect::<Vec<_>>();\n    for name in &features {\n        test_package.feature(name.as_str(), &[]);\n    }\n    let default_features = features\n        .iter()\n        .take(DEFAULT_FEATURES_COUNT)\n        .map(|s| s.as_str())\n        .collect::<Vec<_>>();\n    test_package.feature(\"default\", &default_features);\n    test_package.publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"your-face\")\n        .arg(\"--verbose\")\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/features_deactivated_over_limit/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    const MANY_FEATURES_COUNT: usize = 200;\n    const DEFAULT_FEATURES_COUNT: usize = 20;\n\n    init_registry_without_token();\n    let mut test_package =\n        cargo_test_support::registry::Package::new(\"your-face\", \"99999.0.0+my-package\");\n    let features = (0..MANY_FEATURES_COUNT)\n        .map(|i| format!(\"eyes{i:03}\"))\n        .collect::<Vec<_>>();\n    for name in &features {\n        test_package.feature(name.as_str(), &[]);\n    }\n    let default_features = features\n        .iter()\n        .take(DEFAULT_FEATURES_COUNT)\n        .map(|s| s.as_str())\n        .collect::<Vec<_>>();\n    test_package.feature(\"default\", &default_features);\n    test_package.publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"your-face\")\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/git_dependency/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{basic_manifest, file, git, project};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    let baz = git::new(\"baz\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    baz = {{ git = '{}' }}\n                \"#,\n                baz.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let project_root = foo.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg_line(\"--verbose foo\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(\"\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(\"\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/mod.rs",
    "content": "mod basic;\nmod crate_name_normalization_from_hyphen_to_underscore;\nmod crate_name_normalization_from_underscore_to_hyphen;\nmod features;\nmod features_activated_over_limit;\nmod features_activated_over_limit_verbose;\nmod features_deactivated_over_limit;\nmod git_dependency;\nmod help;\nmod not_found;\nmod path_dependency;\nmod pick_msrv_compatible_package;\nmod pick_msrv_compatible_package_within_ws;\nmod pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws;\nmod specify_empty_version_with_url;\nmod specify_version_outside_ws;\nmod specify_version_with_url_but_registry_is_not_matched;\nmod specify_version_within_ws_and_conflict_with_lockfile;\nmod specify_version_within_ws_and_match_with_lockfile;\nmod transitive_dependency_within_ws;\nmod verbose;\nmod with_default_registry_configured;\nmod with_default_registry_configured_and_specified;\nmod with_frozen_outside_ws;\nmod with_frozen_within_ws;\nmod with_locked_outside_ws;\nmod with_locked_within_ws;\nmod with_locked_within_ws_and_pick_the_package;\nmod with_offline;\nmod with_quiet;\nmod within_ws;\nmod within_ws_and_pick_ws_package;\nmod within_ws_with_alternative_registry;\nmod within_ws_without_lockfile;\nmod without_requiring_registry_auth;\n\n// Initialize the registry without a token.\n// Otherwise, it will try to list owners of the crate and fail.\npub(crate) fn init_registry_without_token() {\n    let _reg = cargo_test_support::registry::RegistryBuilder::new()\n        .no_configure_token()\n        .build();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/not_found/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"unknown\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(\"\")\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/not_found/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/not_found/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/path_dependency/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"crates/*\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.0\"\n\n[dependencies]\ncrate1 = { path = \"./crates/crate1\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_info/path_dependency/in/crates/crate1/Cargo.toml",
    "content": "[package]\nname = \"crate1\"\nversion = \"0.0.0\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/path_dependency/in/crates/crate1/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/path_dependency/in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/path_dependency/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg_line(\"--verbose foo\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(\"\");\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/path_dependency/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"crates/*\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.0\"\n\n[dependencies]\ncrate1 = { path = \"./crates/crate1\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_info/path_dependency/out/crates/crate1/Cargo.toml",
    "content": "[package]\nname = \"crate1\"\nversion = \"0.0.0\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/path_dependency/out/crates/crate1/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/path_dependency/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.1+my-package\")\n        .rust_version(\"1.0.0\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.2.0+my-package\")\n        .rust_version(\"1.9876.0\")\n        .publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"crate*\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/in/crate1/Cargo.toml",
    "content": "[package]\nname = \"crate1\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/in/crate1/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/in/crate2/Cargo.toml",
    "content": "[package]\nname = \"crate2\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/in/crate2/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.2.0\")\n        .rust_version(\"1.0.0\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.2.1\")\n        .rust_version(\"1.9876.0\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root.join(\"crate1\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"crate*\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/out/crate1/Cargo.toml",
    "content": "[package]\nname = \"crate1\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/out/crate1/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/out/crate2/Cargo.toml",
    "content": "[package]\nname = \"crate2\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/out/crate2/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"crate*\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/in/crate1/Cargo.toml",
    "content": "[package]\nname = \"crate1\"\nversion = \"0.0.0\"\n\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/in/crate1/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/in/crate2/Cargo.toml",
    "content": "[package]\nname = \"crate2\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/in/crate2/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\").publish();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.2.0\")\n        .rust_version(\"1.0.0\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.2.1\")\n        .rust_version(\"1.70.0\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root.join(\"crate1\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"crate*\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/out/crate1/Cargo.toml",
    "content": "[package]\nname = \"crate1\"\nversion = \"0.0.0\"\n\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/out/crate1/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/out/crate2/Cargo.toml",
    "content": "[package]\nname = \"crate2\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/out/crate2/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/specify_empty_version_with_url/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{file, registry::RegistryBuilder};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    let _ = RegistryBuilder::new()\n        .alternative()\n        .no_configure_token()\n        .build();\n    cargo_test_support::registry::Package::new(\"my-package\", \"99999.0.0-alpha.1+my-package\")\n        .alternative(true)\n        .publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"https://crates.io\")\n        .arg(\"--registry=alternative\")\n        .assert()\n        .failure()\n        .stdout_eq(\"\")\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/specify_version_outside_ws/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    for ver in [\"0.1.1+my-package\", \"0.2.0+my-package\", \"0.2.3+my-package\"] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package@0.2\")\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/specify_version_with_url_but_registry_is_not_matched/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{file, registry::RegistryBuilder};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    let _ = RegistryBuilder::new()\n        .alternative()\n        .no_configure_token()\n        .build();\n    cargo_test_support::registry::Package::new(\"my-package\", \"99999.0.0-alpha.1+my-package\")\n        .alternative(true)\n        .publish();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"https://crates.io/my-package\")\n        .arg(\"--registry=alternative\")\n        .assert()\n        .failure()\n        .stdout_eq(\"\")\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package@0.4\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package@0.1\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"crates/*\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/in/crates/direct1/Cargo.toml",
    "content": "[package]\nname = \"direct1\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n\n[dependencies]\nmy-package = \"1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/in/crates/direct1/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/in/crates/direct2/Cargo.toml",
    "content": "[package]\nname = \"direct2\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n\n[dependencies]\nmy-package = \"2\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/in/crates/direct2/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/in/crates/transitive1/Cargo.toml",
    "content": "[package]\nname = \"transitive1\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n\n[dependencies]\ndep1 = \"1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/in/crates/transitive1/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/in/crates/transitive123/Cargo.toml",
    "content": "[package]\nname = \"transitive123\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n[dependencies]\ndep1 = \"1\"\ndep2 = \"1\"\ndep3 = \"1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/in/crates/transitive123/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/in/crates/transitive2/Cargo.toml",
    "content": "[package]\nname = \"transitive2\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n\n[dependencies]\ndep2 = \"1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/in/crates/transitive2/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    // 99.0.0 is unused\n    for ver in [\"1.0.0\", \"2.0.0\", \"3.0.0\", \"99.0.0\"] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n    // Dep1 depends on 3.0.0, Dep2 depends on 2.0.0, Dep3 depends on 1.0.0\n    cargo_test_support::registry::Package::new(\"dep1\", \"1.0.0\")\n        .dep(\"my-package\", \"1.0.0\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"dep2\", \"1.0.0\")\n        .dep(\"my-package\", \"2.0.0\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"dep3\", \"1.0.0\")\n        .dep(\"my-package\", \"3.0.0\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let transitive1_root = project_root.join(\"crates/transitive1\");\n    let transitive2_root = project_root.join(\"crates/transitive2\");\n    let direct1_root = project_root.join(\"crates/direct1\");\n    let direct2_root = project_root.join(\"crates/direct2\");\n    let ws_directory = &project_root;\n    let transitive1_directory = &transitive1_root;\n    let transitive2_directory = &transitive2_root;\n    let direct1_directory = &direct1_root;\n    let direct2_directory = &direct2_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(ws_directory)\n        .assert()\n        .stdout_eq(file![\"ws-stdout.term.svg\"])\n        .stderr_eq(file![\"ws-stderr.term.svg\"]);\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(transitive1_directory)\n        .assert()\n        .stdout_eq(file![\"transitive1-stdout.term.svg\"])\n        .stderr_eq(file![\"transitive1-stderr.term.svg\"]);\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(transitive2_directory)\n        .assert()\n        .stdout_eq(file![\"transitive2-stdout.term.svg\"])\n        .stderr_eq(file![\"transitive2-stderr.term.svg\"]);\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(direct1_directory)\n        .assert()\n        .stdout_eq(file![\"direct1-stdout.term.svg\"])\n        .stderr_eq(file![\"direct1-stderr.term.svg\"]);\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(direct2_directory)\n        .assert()\n        .stdout_eq(file![\"direct2-stdout.term.svg\"])\n        .stderr_eq(file![\"direct2-stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"crates/*\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/out/crates/direct1/Cargo.toml",
    "content": "[package]\nname = \"direct1\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n\n[dependencies]\nmy-package = \"1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/out/crates/direct1/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/out/crates/direct2/Cargo.toml",
    "content": "[package]\nname = \"direct2\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n\n[dependencies]\nmy-package = \"2\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/out/crates/direct2/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/out/crates/transitive1/Cargo.toml",
    "content": "[package]\nname = \"transitive1\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n\n[dependencies]\ndep1 = \"1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/out/crates/transitive1/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/out/crates/transitive123/Cargo.toml",
    "content": "[package]\nname = \"transitive123\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n[dependencies]\ndep1 = \"1\"\ndep2 = \"1\"\ndep3 = \"1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/out/crates/transitive123/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/out/crates/transitive2/Cargo.toml",
    "content": "[package]\nname = \"transitive2\"\nversion = \"0.0.0\"\nrust-version = \"1.0.0\"\n\n\n[dependencies]\ndep2 = \"1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/out/crates/transitive2/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/transitive_dependency_within_ws/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/verbose/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"my-package\"\n            version = \"0.1.0\"\n            description = \"A package for testing\"\n            repository = \"https://github.com/hi-rustin/cargo-infromation\"\n            documentation = \"https://docs.rs/my-package/0.1.0\"\n            license = \"MIT\"\n            edition = \"2018\"\n            rust-version = \"1.50.0\"\n            keywords = [\"foo\", \"bar\", \"baz\"]\n\n            [features]\n            default = [\"feature1\"]\n            feature1 = []\n            feature2 = []\n\n            [dependencies]\n            foo = \"0.1.0\"\n            bar = \"0.2.0\"\n            baz = { version = \"0.3.0\", optional = true }\n\n            [[bin]]\n            name = \"my_bin\"\n\n            [lib]\n            name = \"my_lib\"\n            \"#,\n        )\n        .file(\"src/bin/my_bin.rs\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--verbose\")\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured/in/.cargo/config.toml",
    "content": "[registry]\ndefault = \"crates-io\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"crates/*\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.0\"\n\n[dependencies]\ncrate1 = { path = \"./crates/crate1\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured/in/crates/crate1/Cargo.toml",
    "content": "[package]\nname = \"crate1\"\nversion = \"0.0.0\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured/in/crates/crate1/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured/in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg_line(\"--verbose foo\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(\"\");\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured/out/.cargo/config.toml",
    "content": "[registry]\ndefault = \"crates-io\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"crates/*\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.0\"\n\n[dependencies]\ncrate1 = { path = \"./crates/crate1\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured/out/crates/crate1/Cargo.toml",
    "content": "[package]\nname = \"crate1\"\nversion = \"0.0.0\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured/out/crates/crate1/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured_and_specified/in/.cargo/config.toml",
    "content": "[registry]\ndefault = \"crates-io\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured_and_specified/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\"crates/*\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.0\"\n\n[dependencies]\ncrate1 = { path = \"./crates/crate1\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured_and_specified/in/crates/crate1/Cargo.toml",
    "content": "[package]\nname = \"crate1\"\nversion = \"0.0.0\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured_and_specified/in/crates/crate1/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured_and_specified/in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured_and_specified/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n\n    for ver in [\"0.1.1+foo\", \"0.2.0+foo\"] {\n        cargo_test_support::registry::Package::new(\"foo\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg_line(\"--verbose foo\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured_and_specified/out/.cargo/config.toml",
    "content": "[registry]\ndefault = \"crates-io\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured_and_specified/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"crates/*\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.0\"\n\n[dependencies]\ncrate1 = { path = \"./crates/crate1\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured_and_specified/out/crates/crate1/Cargo.toml",
    "content": "[package]\nname = \"crate1\"\nversion = \"0.0.0\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured_and_specified/out/crates/crate1/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_default_registry_configured_and_specified/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_frozen_outside_ws/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--frozen\")\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .failure()\n        .stdout_eq(\"\")\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_frozen_within_ws/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"unknown\")\n        .arg(\"--frozen\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(\"\")\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_frozen_within_ws/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_frozen_within_ws/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_locked_outside_ws/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--locked\")\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .failure()\n        .stdout_eq(\"\")\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_locked_within_ws/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"unknown\")\n        .arg(\"--locked\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(\"\")\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_locked_within_ws/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_locked_within_ws/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--locked\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_offline/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--offline\")\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .failure()\n        .stdout_eq(\"\")\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/with_quiet/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--quiet\")\n        .arg(\"--registry=dummy-registry\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(\"\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_workspace.in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_workspace.in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n        \"20.0.0+my-package\",\n        \"99999.0.0+my-package\",\n        \"99999.0.0-alpha.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_and_pick_ws_package/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.2.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_and_pick_ws_package/in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_and_pick_ws_package/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"cargo-list-test-fixture\", \"0.1.1+my-package\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"cargo-list-test-fixture\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(\"\");\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_and_pick_ws_package/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.2.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_and_pick_ws_package/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_with_alternative_registry/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, registry::RegistryBuilder};\nuse cargo_test_support::{current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    let _ = RegistryBuilder::new()\n        .alternative()\n        .no_configure_token()\n        .build();\n    cargo_test_support::registry::Package::new(\"my-package\", \"99999.0.0-alpha.1+my-package\")\n        .alternative(true)\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=alternative\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_with_alternative_registry/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_with_alternative_registry/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_without_lockfile/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.2\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_without_lockfile/in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_without_lockfile/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    for ver in [\n        \"0.1.1+my-package\",\n        \"0.2.0+my-package\",\n        \"0.2.3+my-package\",\n        \"0.4.1+my-package\",\n    ] {\n        cargo_test_support::registry::Package::new(\"my-package\", ver).publish();\n    }\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_without_lockfile/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.2\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/within_ws_without_lockfile/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_info/without_requiring_registry_auth/in/.cargo/config.toml",
    "content": "[registry]\nglobal-credential-providers = [\"false\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/without_requiring_registry_auth/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/without_requiring_registry_auth/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_info/without_requiring_registry_auth/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{Project, compare::assert_ui, current_dir, file};\n\nuse super::init_registry_without_token;\n\n#[cargo_test]\nfn case() {\n    init_registry_without_token();\n    cargo_test_support::registry::Package::new(\"my-package\", \"0.1.1+my-package\").publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"info\")\n        .arg(\"my-package\")\n        .arg(\"--registry=dummy-registry\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_info/without_requiring_registry_auth/out/.cargo/config.toml",
    "content": "[registry]\nglobal-credential-providers = [\"false\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_info/without_requiring_registry_auth/out/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"cargo-list-test-fixture\"\nversion = \"0.0.0\"\n\n[dependencies]\nmy-package = \"0.1\"\n"
  },
  {
    "path": "tests/testsuite/cargo_info/without_requiring_registry_auth/out/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_init/auto_git/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n    assert!(project_root.join(\".git\").is_dir());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/auto_git/out/.gitignore",
    "content": "/target\n"
  },
  {
    "path": "tests/testsuite/cargo_init/auto_git/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/auto_git/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_explicit/in/src/main.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_explicit/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --bin --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_explicit/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_explicit/out/src/main.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/in/main.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --bin --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\"src\").is_dir());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n\n[[bin]]\nname = \"case\"\npath = \"main.rs\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/out/main.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit/in/src/main.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit/out/src/main.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/in/case.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\"src\").is_dir());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n\n[[bin]]\nname = \"case\"\npath = \"case.rs\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/out/case.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/in/src/case.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\"src/main.rs\").is_file());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n\n[[bin]]\nname = \"case\"\npath = \"src/case.rs\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/out/src/case.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/in/main.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\"src\").is_dir());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n\n[[bin]]\nname = \"case\"\npath = \"main.rs\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/out/main.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n\n"
  },
  {
    "path": "tests/testsuite/cargo_init/both_lib_and_bin/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::paths;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let cwd = paths::root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib --bin\")\n        .current_dir(&cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert!(!cwd.join(\"Cargo.toml\").is_file());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/in/case.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/in/lib.rs",
    "content": "fn f() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib\")\n        .current_dir(project_root)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/confused_by_multiple_lib_files/in/lib.rs",
    "content": "fn f() { println!(\"lib.rs\"); }\n"
  },
  {
    "path": "tests/testsuite/cargo_init/confused_by_multiple_lib_files/in/src/lib.rs",
    "content": "fn f() { println!(\"src/lib.rs\"); }\n"
  },
  {
    "path": "tests/testsuite/cargo_init/confused_by_multiple_lib_files/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\"Cargo.toml\").is_file());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/confused_by_multiple_lib_files/out/lib.rs",
    "content": "fn f() { println!(\"lib.rs\"); }\n"
  },
  {
    "path": "tests/testsuite/cargo_init/confused_by_multiple_lib_files/out/src/lib.rs",
    "content": "fn f() { println!(\"src/lib.rs\"); }\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/in/case.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/in/lib.rs",
    "content": "fn f() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --bin --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n\n[[bin]]\nname = \"case\"\npath = \"case.rs\"\n\n[lib]\npath = \"lib.rs\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/out/case.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/out/lib.rs",
    "content": "fn f() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/in/case.rs",
    "content": "fn f() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --bin --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n\n[[bin]]\nname = \"case\"\npath = \"case.rs\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/out/case.rs",
    "content": "fn f() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/in/case.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n\n[lib]\npath = \"case.rs\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/out/case.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/empty_dir/mod.rs",
    "content": "use cargo_test_support::compare::assert_ui;\nuse crate::prelude::*;\nuse cargo_test_support::{command_is_available, paths, Project};\nuse std::fs;\nuse std::process::Command;\n\nuse crate::test_root;\n"
  },
  {
    "path": "tests/testsuite/cargo_init/error_on_existing_package.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::paths;\nuse cargo_test_support::str;\nuse std::fs;\n\n#[cargo_test]\nfn init_error_on_existing_package() {\n    let project_root = paths::root().join(\"foo\");\n    fs::create_dir_all(&project_root).unwrap();\n    fs::write(project_root.join(\"Cargo.toml\"), \"\").unwrap();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --color=never\")\n        .current_dir(&project_root)\n        .assert()\n        .code(101)\n        .stderr_eq(str![[r#\"\n    Creating binary (application) package\nerror: `cargo init` cannot be run on existing Cargo packages\nhelp: use `cargo new` to create a package in a new subdirectory\n\n\"#]]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/explicit_bin_with_git/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --vcs git --bin\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/explicit_bin_with_git/out/.gitignore",
    "content": "/target\n"
  },
  {
    "path": "tests/testsuite/cargo_init/explicit_bin_with_git/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/explicit_bin_with_git/out/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/formats_source/in/rustfmt.toml",
    "content": "tab_spaces = 2\n"
  },
  {
    "path": "tests/testsuite/cargo_init/formats_source/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\nuse cargo_test_support::{Project, process};\n\n#[cargo_test]\nfn case() {\n    // This cannot use `requires_rustfmt` because rustfmt is not available in\n    // the rust-lang/rust environment. Additionally, if running cargo without\n    // rustup (but with rustup installed), this test also fails due to HOME\n    // preventing the proxy from choosing a toolchain.\n    if let Err(e) = process(\"rustfmt\").arg(\"-V\").exec_with_output() {\n        eprintln!(\"skipping test, rustfmt not available:\\n{e:?}\");\n        return;\n    }\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/formats_source/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/formats_source/out/rustfmt.toml",
    "content": "tab_spaces = 2\n"
  },
  {
    "path": "tests/testsuite/cargo_init/formats_source/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n  left + right\n}\n\n#[cfg(test)]\nmod tests {\n  use super::*;\n\n  #[test]\n  fn it_works() {\n    let result = add(2, 2);\n    assert_eq!(result, 4);\n  }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/fossil_autodetect/in/.fossil/.keep",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_init/fossil_autodetect/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\".git\").is_dir());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/clean-glob",
    "content": "target\n"
  },
  {
    "path": "tests/testsuite/cargo_init/fossil_autodetect/out/.fossil-settings/ignore-glob",
    "content": "target\n"
  },
  {
    "path": "tests/testsuite/cargo_init/fossil_autodetect/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/fossil_autodetect/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/git_autodetect/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::paths;\nuse cargo_test_support::str;\nuse std::fs;\n\n#[cargo_test]\nfn case() {\n    let project_root = &paths::root().join(\"foo\");\n    // Need to create `.git` dir manually because it cannot be tracked under a git repo\n    fs::create_dir_all(project_root.join(\".git\")).unwrap();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(project_root.join(\".git\").is_dir());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/git_autodetect/out/.gitignore",
    "content": "/target\n"
  },
  {
    "path": "tests/testsuite/cargo_init/git_autodetect/out/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/git_autodetect/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/in/.gitignore",
    "content": "**/some.file"
  },
  {
    "path": "tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib --edition 2015\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(project_root.join(\".git\").is_dir());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/out/.gitignore",
    "content": "**/some.file\n\n# Added by cargo\n\n/target\n"
  },
  {
    "path": "tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"init\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/ignores_failure_to_format_source/in/rustfmt.toml",
    "content": "tab_spaces = 2\n"
  },
  {
    "path": "tests/testsuite/cargo_init/ignores_failure_to_format_source/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib --vcs none\")\n        .env(\"PATH\", \"\") // pretend that `rustfmt` is missing\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/ignores_failure_to_format_source/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/ignores_failure_to_format_source/out/rustfmt.toml",
    "content": "tab_spaces = 2\n"
  },
  {
    "path": "tests/testsuite/cargo_init/ignores_failure_to_format_source/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/in_home_directory/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::paths;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init\")\n        .current_dir(paths::home())\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inferred_bin_with_git/in/main.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inferred_bin_with_git/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --vcs git\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inferred_bin_with_git/out/.gitignore",
    "content": "/target\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inferred_bin_with_git/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n\n[[bin]]\nname = \"case\"\npath = \"main.rs\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inferred_bin_with_git/out/main.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inferred_lib_with_git/in/lib.rs",
    "content": "fn f() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inferred_lib_with_git/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --vcs git\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inferred_lib_with_git/out/.gitignore",
    "content": "/target\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inferred_lib_with_git/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n\n[lib]\npath = \"lib.rs\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inferred_lib_with_git/out/lib.rs",
    "content": "fn f() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inherit_workspace_package_table/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\n  \"crates/*\",\n]\n\n[workspace.package]\nauthors = [\"Rustaceans\"]\ndescription = \"foo\"\nedition = \"2018\"\nhomepage = \"foo\"\nkeywords = [\"foo\", \"bar\"]\nreadme = \"README.md\"\nrust-version = \"1.67.0\"\ncategories = [\"algorithms\"]\ndocumentation = \"foo\"\nexclude = [\"foo\"]\ninclude = [\"foo\"]\nlicense = \"MIT OR Apache-2.0\"\npublish = false\nrepository = \"foo\"\nversion = \"1.2.3\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inherit_workspace_package_table/in/README.md",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_init/inherit_workspace_package_table/in/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inherit_workspace_package_table/in/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inherit_workspace_package_table/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"init\")\n        .args([\"crates/foo\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inherit_workspace_package_table/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\n  \"crates/*\",\n]\n\n[workspace.package]\nauthors = [\"Rustaceans\"]\ndescription = \"foo\"\nedition = \"2018\"\nhomepage = \"foo\"\nkeywords = [\"foo\", \"bar\"]\nreadme = \"README.md\"\nrust-version = \"1.67.0\"\ncategories = [\"algorithms\"]\ndocumentation = \"foo\"\nexclude = [\"foo\"]\ninclude = [\"foo\"]\nlicense = \"MIT OR Apache-2.0\"\npublish = false\nrepository = \"foo\"\nversion = \"1.2.3\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inherit_workspace_package_table/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nauthors.workspace = true\ndescription.workspace = true\nedition.workspace = true\nhomepage.workspace = true\nkeywords.workspace = true\nreadme.workspace = true\nrust-version.workspace = true\ncategories.workspace = true\ndocumentation.workspace = true\nexclude.workspace = true\ninclude.workspace = true\nlicense.workspace = true\npublish.workspace = true\nrepository.workspace = true\nversion.workspace = true\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inherit_workspace_package_table/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Check that our file is not overwritten\")\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/inherit_workspace_package_table/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/invalid_dir_name/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::paths;\nuse cargo_test_support::str;\nuse std::fs;\n\n#[cargo_test]\nfn case() {\n    let foo = &paths::root().join(\"foo.bar\");\n    fs::create_dir_all(foo).unwrap();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init\")\n        .current_dir(foo)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert!(!foo.join(\"Cargo.toml\").is_file());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/lib_already_exists_nosrc/in/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_init/lib_already_exists_nosrc/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\"src/main.rs\").is_file());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/lib_already_exists_nosrc/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n\n[lib]\npath = \"lib.rs\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/lib_already_exists_nosrc/out/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_init/lib_already_exists_src/in/src/lib.rs",
    "content": "fn f() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/lib_already_exists_src/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\"src/main.rs\").is_file());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/lib_already_exists_src/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/lib_already_exists_src/out/src/lib.rs",
    "content": "fn f() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/mercurial_autodetect/in/.hg/.keep",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_init/mercurial_autodetect/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\".git\").is_dir());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/mercurial_autodetect/out/.hgignore",
    "content": "^target$\n"
  },
  {
    "path": "tests/testsuite/cargo_init/mercurial_autodetect/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/mercurial_autodetect/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/mod.rs",
    "content": "//! Tests for the `cargo init` command.\n\nmod auto_git;\nmod bin_already_exists_explicit;\nmod bin_already_exists_explicit_nosrc;\nmod bin_already_exists_implicit;\nmod bin_already_exists_implicit_namenosrc;\nmod bin_already_exists_implicit_namesrc;\nmod bin_already_exists_implicit_nosrc;\nmod both_lib_and_bin;\nmod cant_create_library_when_both_binlib_present;\nmod confused_by_multiple_lib_files;\nmod creates_binary_when_both_binlib_present;\nmod creates_binary_when_instructed_and_has_lib_file;\nmod creates_library_when_instructed_and_has_bin_file;\nmod error_on_existing_package;\nmod explicit_bin_with_git;\nmod formats_source;\nmod fossil_autodetect;\nmod git_autodetect;\nmod git_ignore_exists_no_conflicting_entries;\nmod help;\nmod ignores_failure_to_format_source;\nmod in_home_directory;\nmod inferred_bin_with_git;\nmod inferred_lib_with_git;\nmod inherit_workspace_package_table;\nmod invalid_dir_name;\nmod lib_already_exists_nosrc;\nmod lib_already_exists_src;\nmod mercurial_autodetect;\nmod multibin_project_name_clash;\n#[cfg(not(windows))]\nmod no_filename;\n#[cfg(unix)]\nmod path_contains_separator;\nmod pijul_autodetect;\nmod reserved_name;\nmod reserved_name_core;\nmod simple_bin;\nmod simple_git;\nmod simple_git_ignore_exists;\nmod simple_hg;\nmod simple_hg_ignore_exists;\nmod simple_lib;\nmod unknown_flags;\nmod with_argument;\nmod workspace_add_member;\n"
  },
  {
    "path": "tests/testsuite/cargo_init/multibin_project_name_clash/in/case.rs",
    "content": "fn main() { println!(\"foo.rs\"); }\n"
  },
  {
    "path": "tests/testsuite/cargo_init/multibin_project_name_clash/in/main.rs",
    "content": "fn main() { println!(\"main.rs\"); }\n"
  },
  {
    "path": "tests/testsuite/cargo_init/multibin_project_name_clash/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\"Cargo.toml\").is_file());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/multibin_project_name_clash/out/case.rs",
    "content": "fn main() { println!(\"foo.rs\"); }\n"
  },
  {
    "path": "tests/testsuite/cargo_init/multibin_project_name_clash/out/main.rs",
    "content": "fn main() { println!(\"main.rs\"); }\n"
  },
  {
    "path": "tests/testsuite/cargo_init/no_filename/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::paths;\nuse cargo_test_support::str;\n\n#[cfg(not(windows))]\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init /\")\n        .current_dir(paths::root())\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/path_contains_separator/in/.keep",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_init/path_contains_separator/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\nuse cargo_test_support::{Project, t};\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root().join(\"test:ing\");\n\n    if !project_root.exists() {\n        t!(std::fs::create_dir(&project_root));\n    }\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --bin --vcs none --edition 2015 --name testing\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\".gitignore\").is_file());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/path_contains_separator/out/Cargo.toml",
    "content": "[package]\nname = \"testing\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/path_contains_separator/out/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/pijul_autodetect/in/.pijul/.keep",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_init/pijul_autodetect/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\".git\").is_dir());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/pijul_autodetect/out/.ignore",
    "content": "/target\n"
  },
  {
    "path": "tests/testsuite/cargo_init/pijul_autodetect/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/pijul_autodetect/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/reserved_name/mod.rs",
    "content": "use std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::paths;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project_root = &paths::root().join(\"test\");\n    fs::create_dir_all(project_root).unwrap();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init\")\n        .current_dir(project_root)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert!(!project_root.join(\"Cargo.toml\").is_file());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/reserved_name_core.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::paths;\nuse cargo_test_support::str;\nuse std::fs;\n\n#[cargo_test]\nfn init_with_reserved_name_core() {\n    let project_root = paths::root().join(\"core\");\n    fs::create_dir_all(&project_root).unwrap();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --color=never\")\n        .current_dir(&project_root)\n        .assert()\n        .stderr_eq(str![[r#\"\n    Creating binary (application) package\nwarning: package name `core` may be confused with the package with that name in Rust's standard library\nIt is recommended to use a different name to avoid problems.\nnote: the directory name is used as the package name\nhelp: to override the package name, pass `--name <pkgname>`\nhelp: to name the binary \"core\", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/core.rs` or change the name in Cargo.toml with:\n\n    [[bin]]\n    name = \"core\"\n    path = \"src/main.rs\"\n\nnote: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_bin/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --bin --vcs none --edition 2015\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\".gitignore\").is_file());\n\n    snapbox::cmd::Command::cargo_ui()\n        .current_dir(project_root)\n        .arg(\"build\")\n        .assert()\n        .success();\n    assert!(project.bin(\"case\").is_file());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_bin/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_bin/out/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_git/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib --vcs git\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(project_root.join(\".git\").is_dir());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_git/out/.gitignore",
    "content": "/target\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_git/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_git/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_git_ignore_exists/in/.gitignore",
    "content": "/target\n**/some.file"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_git_ignore_exists/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib --edition 2015\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(project_root.join(\".git\").is_dir());\n\n    snapbox::cmd::Command::cargo_ui()\n        .current_dir(project_root)\n        .arg(\"build\")\n        .assert()\n        .success();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_git_ignore_exists/out/.gitignore",
    "content": "/target\n**/some.file\n\n# Added by cargo\n#\n# already existing elements were commented out\n\n#/target\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_git_ignore_exists/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_git_ignore_exists/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_hg/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test(requires = \"hg\")]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib --vcs hg\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\".git\").is_dir());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_hg/out/.hgignore",
    "content": "^target$\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_hg/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_hg/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_hg_ignore_exists/in/.hg/.keep",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_init/simple_hg_ignore_exists/in/.hgignore",
    "content": "^/somefile"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_hg_ignore_exists/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\".git\").is_dir());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_hg_ignore_exists/out/.hgignore",
    "content": "^/somefile\n\n# Added by cargo\n\n^target$\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_hg_ignore_exists/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_hg_ignore_exists/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_lib/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --lib --vcs none --edition 2015\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n    assert!(!project_root.join(\".gitignore\").is_file());\n\n    snapbox::cmd::Command::cargo_ui()\n        .current_dir(project_root)\n        .arg(\"build\")\n        .assert()\n        .success();\n    assert!(!project.bin(\"foo\").is_file());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_lib/out/Cargo.toml",
    "content": "[package]\nname = \"case\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/simple_lib/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/unknown_flags/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::paths;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init foo --flag\")\n        .current_dir(paths::root())\n        .assert()\n        .code(1)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/with_argument/in/foo/.keep",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_init/with_argument/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init foo --vcs none\")\n        .current_dir(project_root)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/with_argument/out/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/with_argument/out/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/workspace_add_member/in/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\n"
  },
  {
    "path": "tests/testsuite/cargo_init/workspace_add_member/in/crates/foo/.keep",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_init/workspace_add_member/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = &project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg_line(\"init --bin --vcs none\")\n        .current_dir(project_root.join(\"crates\").join(\"foo\"))\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_init/workspace_add_member/out/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\"crates/foo\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/workspace_add_member/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_init/workspace_add_member/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_install/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"install\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_install/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_locate_project/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"locate-project\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_locate_project/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_login/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"login\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_login/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_logout/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"logout\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_logout/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_metadata/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"metadata\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_metadata/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_non_workspace/in/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_non_workspace/in/src/main.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_non_workspace/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"bar\", \"--lib\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_non_workspace/out/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_non_workspace/out/bar/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_non_workspace/out/bar/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_non_workspace/out/src/main.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/in/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\n\n[workspace.package]\nauthors = [\"Rustaceans\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"crates/foo\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/out/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\"crates/foo\"]\n\n[workspace.package]\nauthors = [\"Rustaceans\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2024\"\nauthors.workspace = true\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/in/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\"crates/bar\", \"crates/qux\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/in/crates/bar/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/in/crates/bar/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/in/crates/qux/Cargo.toml",
    "content": "[package]\nname = \"qux\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/in/crates/qux/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"crates/foo\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/out/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\"crates/bar\", \"crates/foo\", \"crates/qux\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/in/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = []\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n    let package_path = cwd.join(\"crates\").join(\"foo\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([package_path])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/out/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\"crates/foo\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/in/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = []\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"crates/foo\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/out/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\"crates/foo\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/in/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = []\nexclude = [\"crates/foo\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/in/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"crates/foo\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/out/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = []\nexclude = [\"crates/foo\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/in/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\"crates/*\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"crates/foo\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/out/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\"crates/*\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_without_members/in/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_without_members/in/src/main.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_without_members/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"bar\", \"--lib\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_without_members/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\"bar\"]\n\n[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_without_members/out/bar/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_without_members/out/bar/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/add_members_to_workspace_without_members/out/src/main.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/empty_name/in/.keep",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_new/empty_name/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"foo\", \"--name\", \"\"])\n        .current_dir(cwd)\n        .assert()\n        .failure()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/empty_name/out/.keep",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_new/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/ignore_current_dir_workspace/in/workspace/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/ignore_current_dir_workspace/in/workspace/src/main.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/ignore_current_dir_workspace/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root.join(\"workspace\");\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"../out-of-workspace\", \"--lib\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/ignore_current_dir_workspace/out/out-of-workspace/Cargo.toml",
    "content": "[package]\nname = \"out-of-workspace\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/ignore_current_dir_workspace/out/out-of-workspace/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/ignore_current_dir_workspace/out/workspace/Cargo.toml",
    "content": "[workspace]\n\n[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/ignore_current_dir_workspace/out/workspace/src/main.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_lints/in/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\"crates/*\"]\n\n[workspace.lints.rust]\nunsafe_code = \"forbid\"\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_lints/in/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_lints/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"crates/foo\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_lints/out/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\"crates/*\"]\n\n[workspace.lints.rust]\nunsafe_code = \"forbid\"\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_lints/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_lints/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_lints/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"crates/foo\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table/out/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\n  \"crates/*\",\n]\n\n[workspace.package]\nauthors = [\"Rustaceans\"]\ndescription = \"foo\"\nedition = \"2018\"\nhomepage = \"foo\"\nkeywords = [\"foo\", \"bar\"]\nreadme = \"README.md\"\nrust-version = \"1.67.0\"\ncategories = [\"algorithms\"]\ndocumentation = \"foo\"\nexclude = [\"foo\"]\ninclude = [\"foo\"]\nlicense = \"MIT OR Apache-2.0\"\npublish = false\nrepository = \"foo\"\nversion = \"1.2.3\"\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nauthors.workspace = true\ndescription.workspace = true\nedition.workspace = true\nhomepage.workspace = true\nkeywords.workspace = true\nreadme.workspace = true\nrust-version.workspace = true\ncategories.workspace = true\ndocumentation.workspace = true\nexclude.workspace = true\ninclude.workspace = true\nlicense.workspace = true\npublish.workspace = true\nrepository.workspace = true\nversion.workspace = true\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table.in/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\n  \"crates/*\",\n]\n\n[workspace.package]\nauthors = [\"Rustaceans\"]\ndescription = \"foo\"\nedition = \"2018\"\nhomepage = \"foo\"\nkeywords = [\"foo\", \"bar\"]\nreadme = \"README.md\"\nrust-version = \"1.67.0\"\ncategories = [\"algorithms\"]\ndocumentation = \"foo\"\nexclude = [\"foo\"]\ninclude = [\"foo\"]\nlicense = \"MIT OR Apache-2.0\"\npublish = false\nrepository = \"foo\"\nversion = \"1.2.3\"\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table.in/README.md",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table.in/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"crates/foo\", \"--edition\", \"2021\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\n  \"crates/*\",\n]\n\n[workspace.package]\nauthors = [\"Rustaceans\"]\ndescription = \"foo\"\nedition = \"2018\"\nhomepage = \"foo\"\nkeywords = [\"foo\", \"bar\"]\nreadme = \"README.md\"\nrust-version = \"1.67.0\"\ncategories = [\"algorithms\"]\ndocumentation = \"foo\"\nexclude = [\"foo\"]\ninclude = [\"foo\"]\nlicense = \"MIT OR Apache-2.0\"\npublish = false\nrepository = \"foo\"\nversion = \"1.2.3\"\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nedition = \"2021\"\nauthors.workspace = true\ndescription.workspace = true\nhomepage.workspace = true\nkeywords.workspace = true\nreadme.workspace = true\nrust-version.workspace = true\ncategories.workspace = true\ndocumentation.workspace = true\nexclude.workspace = true\ninclude.workspace = true\nlicense.workspace = true\npublish.workspace = true\nrepository.workspace = true\nversion.workspace = true\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"crates/foo\", \"--registry\", \"foo\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\n  \"crates/*\",\n]\n\n[workspace.package]\nauthors = [\"Rustaceans\"]\ndescription = \"foo\"\nedition = \"2018\"\nhomepage = \"foo\"\nkeywords = [\"foo\", \"bar\"]\nreadme = \"README.md\"\nrust-version = \"1.67.0\"\ncategories = [\"algorithms\"]\ndocumentation = \"foo\"\nexclude = [\"foo\"]\ninclude = [\"foo\"]\nlicense = \"MIT OR Apache-2.0\"\npublish = false\nrepository = \"foo\"\nversion = \"1.2.3\"\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\npublish = [\"foo\"]\nauthors.workspace = true\ndescription.workspace = true\nedition.workspace = true\nhomepage.workspace = true\nkeywords.workspace = true\nreadme.workspace = true\nrust-version.workspace = true\ncategories.workspace = true\ndocumentation.workspace = true\nexclude.workspace = true\ninclude.workspace = true\nlicense.workspace = true\nrepository.workspace = true\nversion.workspace = true\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/Cargo.toml",
    "content": "[workspace]\nmembers = [\n  \"crates/*\",\n]\n\n[workspace.package]\nauthors = [\"Rustaceans\"]\ndescription = \"foo\"\nedition = \"2018\"\nhomepage = \"foo\"\nkeywords = [\"foo\", \"bar\"]\nreadme = \"README.md\"\nrust-version = \"1.67.0\"\ncategories = [\"algorithms\"]\ndocumentation = \"foo\"\nexclude = [\"foo\"]\ninclude = [\"foo\"]\nlicense = \"MIT OR Apache-2.0\"\npublish = false\nrepository = \"foo\"\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/README.md",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/in/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"crates/foo\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\n  \"crates/*\",\n]\n\n[workspace.package]\nauthors = [\"Rustaceans\"]\ndescription = \"foo\"\nedition = \"2018\"\nhomepage = \"foo\"\nkeywords = [\"foo\", \"bar\"]\nreadme = \"README.md\"\nrust-version = \"1.67.0\"\ncategories = [\"algorithms\"]\ndocumentation = \"foo\"\nexclude = [\"foo\"]\ninclude = [\"foo\"]\nlicense = \"MIT OR Apache-2.0\"\npublish = false\nrepository = \"foo\"\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nauthors.workspace = true\ndescription.workspace = true\nedition.workspace = true\nhomepage.workspace = true\nkeywords.workspace = true\nreadme.workspace = true\nrust-version.workspace = true\ncategories.workspace = true\ndocumentation.workspace = true\nexclude.workspace = true\ninclude.workspace = true\nlicense.workspace = true\npublish.workspace = true\nrepository.workspace = true\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/crates/foo/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/mod.rs",
    "content": "mod add_members_to_non_workspace;\nmod add_members_to_workspace_format_previous_items;\nmod add_members_to_workspace_format_sorted;\nmod add_members_to_workspace_with_absolute_package_path;\nmod add_members_to_workspace_with_empty_members;\nmod add_members_to_workspace_with_exclude_list;\nmod add_members_to_workspace_with_members_glob;\nmod add_members_to_workspace_without_members;\nmod empty_name;\nmod help;\nmod ignore_current_dir_workspace;\nmod inherit_workspace_lints;\nmod inherit_workspace_package_table;\nmod inherit_workspace_package_table_with_edition;\nmod inherit_workspace_package_table_with_registry;\nmod inherit_workspace_package_table_without_version;\nmod not_inherit_workspace_package_table_if_not_members;\n"
  },
  {
    "path": "tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/Cargo.toml",
    "content": "[workspace]\nexclude = [\"bar\"]\n[workspace.package]\nauthors = [\"Rustaceans\"]\ndescription = \"foo\"\nedition = \"2018\"\nhomepage = \"foo\"\nkeywords = [\"foo\", \"bar\"]\nreadme = \"README.md\"\nrust-version = \"1.67.0\"\ncategories = [\"algorithms\"]\ndocumentation = \"foo\"\nexclude = [\"foo\"]\ninclude = [\"foo\"]\nlicense = \"MIT OR Apache-2.0\"\npublish = false\nrepository = \"foo\"\n[workspace.lints.rust]\nunsafe_code = \"forbid\"\n\n[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2018\"\n"
  },
  {
    "path": "tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/README.md",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/in/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"new\")\n        .args([\"bar\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/Cargo.toml",
    "content": "[workspace]\nexclude = [\"bar\"]\n[workspace.package]\nauthors = [\"Rustaceans\"]\ndescription = \"foo\"\nedition = \"2018\"\nhomepage = \"foo\"\nkeywords = [\"foo\", \"bar\"]\nreadme = \"README.md\"\nrust-version = \"1.67.0\"\ncategories = [\"algorithms\"]\ndocumentation = \"foo\"\nexclude = [\"foo\"]\ninclude = [\"foo\"]\nlicense = \"MIT OR Apache-2.0\"\npublish = false\nrepository = \"foo\"\n[workspace.lints.rust]\nunsafe_code = \"forbid\"\n\n[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2018\"\n"
  },
  {
    "path": "tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/bar/Cargo.toml",
    "content": "[package]\nname = \"bar\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/bar/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/out/src/lib.rs",
    "content": "pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_owner/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"owner\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_owner/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_package/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"package\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_package/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_pkgid/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"pkgid\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_pkgid/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_publish/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"publish\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_publish/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_read_manifest/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"read-manifest\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_read_manifest/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/avoid_empty_tables/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"clippy\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/avoid_empty_tables/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/build/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--build\", \"semver\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/build/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/dev/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--dev\", \"regex\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/dev/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/dry_run/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"semver\", \"--dry-run\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/dry_run/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/dry_run/out/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_keep_used_patch/in/Cargo.toml",
    "content": "# Cargo.toml\n\n[workspace]\nmembers = [\"serde\", \"serde_derive\"]\n\n[patch.crates-io]\nserde = { path = \"serde\" }\n\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_keep_used_patch/in/serde/Cargo.toml",
    "content": "# serde/Cargo.toml\n\n[package]\nname = \"serde\"\nversion = \"1.0.0\"\nedition = \"2015\"\n\n[dependencies]\nserde_derive = { path = \"../serde_derive\" }\n\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_keep_used_patch/in/serde/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_keep_used_patch/in/serde_derive/Cargo.toml",
    "content": "# serde_derive/Cargo.toml\n\n[package]\nname = \"serde_derive\"\nversion = \"1.0.0\"\nedition = \"2015\"\n\n[dev-dependencies]\nserde_json = \"1.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_keep_used_patch/in/serde_derive/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_keep_used_patch/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.0\").publish();\n    cargo_test_support::registry::Package::new(\"serde_json\", \"1.0.0\")\n        .dep(\"serde\", \"1.0.0\")\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n\n    snapbox::cmd::Command::cargo_ui()\n        .current_dir(&project_root)\n        .arg(\"remove\")\n        .args([\"--package\", \"serde\", \"serde_derive\"])\n        .assert()\n        .code(0)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_keep_used_patch/out/Cargo.toml",
    "content": "# Cargo.toml\n\n[workspace]\nmembers = [\"serde\", \"serde_derive\"]\n\n[patch.crates-io]\nserde = { path = \"serde\" }\n\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_keep_used_patch/out/serde/Cargo.toml",
    "content": "# serde/Cargo.toml\n\n[package]\nname = \"serde\"\nversion = \"1.0.0\"\nedition = \"2015\"\n\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_keep_used_patch/out/serde/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_keep_used_patch/out/serde_derive/Cargo.toml",
    "content": "# serde_derive/Cargo.toml\n\n[package]\nname = \"serde_derive\"\nversion = \"1.0.0\"\nedition = \"2015\"\n\n[dev-dependencies]\nserde_json = \"1.0.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_keep_used_patch/out/serde_derive/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_patch/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::git;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n\n    let git_project1 = git::new(\"bar1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n            .file(\"src/lib.rs\", \"\")\n    })\n    .url();\n\n    let git_project2 = git::new(\"bar2\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n            .file(\"src/lib.rs\", \"\")\n    })\n    .url();\n\n    let git_project3 = git::new(\"bar3\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n            .file(\"src/lib.rs\", \"\")\n    })\n    .url();\n\n    let in_project = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                \"[workspace]\\n\\\n                 members = [ \\\"my-member\\\" ]\\n\\\n                 \\n\\\n                 [package]\\n\\\n                 name = \\\"my-project\\\"\\n\\\n                 version = \\\"0.1.0\\\"\\n\\\n                 edition = \\\"2015\\\"\\n\\\n                 \\n\\\n                 [dependencies]\\n\\\n                 bar = {{ git = \\\"{git_project1}\\\" }}\\n\\\n                 \\n\\\n                 [patch.\\\"{git_project1}\\\"]\\n\\\n                 bar = {{ git = \\\"{git_project3}\\\" }}\\n\\\n                 \\n\\\n                 [patch.crates-io]\\n\\\n                 bar = {{ git = \\\"{git_project2}\\\" }}\\n\",\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"my-member/Cargo.toml\",\n            \"[package]\\n\\\n               name = \\\"my-member\\\"\\n\\\n               version = \\\"0.1.0\\\"\\n\\\n               \\n\\\n               [dependencies]\\n\\\n               bar = \\\"0.1.0\\\"\\n\",\n        )\n        .file(\"my-member/src/lib.rs\", \"\")\n        .build();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"bar\"])\n        .current_dir(&in_project.root())\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &in_project.root());\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_patch/out/Cargo.toml",
    "content": "[workspace]\nmembers = [ \"my-member\" ]\n\n[package]\nname = \"my-project\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[patch.crates-io]\nbar = { git = \"[ROOTURL]/bar2\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_patch/out/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_profile/in/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\ntoml = \"0.2.3\"\ndocopt = \"0.6\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n\n[profile.dev.package.docopt]\nopt-level = 3\n\n[profile.dev.package.\"toml@0.1.0\"]\nopt-level = 3\n\n[profile.release.package.toml]\nopt-level = 1\noverflow-checks = false\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_profile/in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_profile/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.2.3+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"toml\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_profile/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\ntoml = \"0.2.3\"\ndocopt = \"0.6\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n\n[profile.dev.package.docopt]\nopt-level = 3\n\n[profile.release.package.toml]\nopt-level = 1\noverflow-checks = false\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_replace/in/Cargo.toml",
    "content": "[workspace]\nmembers = [ \"my-package\" ]\n\n[replace]\n\"toml:0.1.0\" = { path = \"../toml\" }\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_replace/in/my-package/Cargo.toml",
    "content": "[package]\nname = \"my-package\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\ntoml = \"0.2.3\"\ndocopt = \"0.6\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_replace/in/my-package/src/main.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_replace/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.2.3+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--package\", \"my-package\", \"toml\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_replace/out/Cargo.toml",
    "content": "[workspace]\nmembers = [ \"my-package\" ]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_replace/out/my-package/Cargo.toml",
    "content": "[package]\nname = \"my-package\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\ntoml = \"0.2.3\"\ndocopt = \"0.6\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/gc_replace/out/my-package/src/main.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_arg/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"foo\", \"--flag\"])\n        .current_dir(cwd)\n        .assert()\n        .code(1)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_arg/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_dep/in/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ninvalid-dependency-name = \"0.6\"\ndocopt = \"0.6\"\nsemver = \"0.1\"\n\n[dev-dependencies]\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_dep/in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_dep/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"invalid-dependency-name\", \"0.6.2+my-package\")\n        .publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"invalid_dependency_name\"])\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_dep/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ninvalid-dependency-name = \"0.6\"\ndocopt = \"0.6\"\nsemver = \"0.1\"\n\n[dev-dependencies]\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_package/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"dbus\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"ncurses\", \"20.0.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"docopt\", \"--package\", \"dep-c\"])\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_package/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\n    \"dep-a\",\n    \"dep-b\"\n]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_package/out/dep-a/Cargo.toml",
    "content": "[package]\nname = \"dep-a\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_package/out/dep-a/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_package/out/dep-b/Cargo.toml",
    "content": "[package]\nname = \"dep-b\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_package/out/dep-b/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_package_multiple/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"dbus\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"ncurses\", \"20.0.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"docopt\"])\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_package_multiple/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\n    \"dep-a\",\n    \"dep-b\"\n]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_package_multiple/out/dep-a/Cargo.toml",
    "content": "[package]\nname = \"dep-a\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_package_multiple/out/dep-a/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_package_multiple/out/dep-b/Cargo.toml",
    "content": "[package]\nname = \"dep-b\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_package_multiple/out/dep-b/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_section/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--build\", \"docopt\"])\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_section/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_section_dep/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--dev\", \"semver\", \"regex\"])\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_section_dep/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_section_missing_flags/in/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-target-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[target.x86_64-unknown-freebsd.build-dependencies]\nsemver = \"0.1.0\"\n\n[target.wasm32-unknown-unknown.build-dependencies]\nsemver = \"0.1.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_section_missing_flags/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"semver\"])\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_section_missing_flags/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-target-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[target.x86_64-unknown-freebsd.build-dependencies]\nsemver = \"0.1.0\"\n\n[target.wasm32-unknown-unknown.build-dependencies]\nsemver = \"0.1.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_target/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"dbus\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"ncurses\", \"20.0.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--target\", \"powerpc-unknown-linux-gnu\", \"dbus\"])\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_target/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-target-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[target.x86_64-unknown-freebsd.build-dependencies]\nsemver = \"0.1.0\"\n\n[target.wasm32-unknown-unknown.build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[target.wasm32-unknown-unknown.dependencies]\ndbus = \"0.6.2\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[target.wasm32-unknown-unknown.dev-dependencies]\nncurses = \"20.0\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_target_dep/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"dbus\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"ncurses\", \"20.0.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--target\", \"wasm32-unknown-unknown\", \"toml\"])\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/invalid_target_dep/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-target-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[target.x86_64-unknown-freebsd.build-dependencies]\nsemver = \"0.1.0\"\n\n[target.wasm32-unknown-unknown.build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[target.wasm32-unknown-unknown.dependencies]\ndbus = \"0.6.2\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[target.wasm32-unknown-unknown.dev-dependencies]\nncurses = \"20.0\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/last_dep/in/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[dependencies]\ndocopt = \"0.6\"\n\n[features]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/last_dep/in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/last_dep/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"docopt\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/last_dep/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[features]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/mod.rs",
    "content": "mod avoid_empty_tables;\nmod build;\nmod dev;\nmod dry_run;\nmod gc_keep_used_patch;\nmod gc_patch;\nmod gc_profile;\nmod gc_replace;\nmod help;\nmod invalid_arg;\nmod invalid_dep;\nmod invalid_package;\nmod invalid_package_multiple;\nmod invalid_section;\nmod invalid_section_dep;\nmod invalid_section_missing_flags;\nmod invalid_target;\nmod invalid_target_dep;\nmod last_dep;\nmod multiple_deps;\nmod multiple_dev;\nmod no_arg;\nmod offline;\nmod optional_dep_feature;\nmod optional_dep_feature_formatting;\nmod optional_feature;\nmod package;\nmod remove_basic;\nmod script;\nmod script_last;\nmod skip_gc_glob_profile;\nmod target;\nmod target_build;\nmod target_dev;\nmod update_lock_file;\nmod workspace;\nmod workspace_non_virtual;\nmod workspace_preserved;\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/multiple_deps/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"docopt\", \"semver\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/multiple_deps/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\nrustc-serialize = \"0.4\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/multiple_dev/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--dev\", \"regex\", \"serde\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/multiple_dev/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[features]\nstd = [ \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/no_arg/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .current_dir(cwd)\n        .assert()\n        .code(1)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/no_arg/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/offline/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    // run the metadata command to populate the cache\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"metadata\")\n        .current_dir(cwd)\n        .assert()\n        .success();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"docopt\", \"--offline\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/offline/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/optional_dep_feature/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--dev\", \"serde\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/optional_dep_feature/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\n\n[features]\nstd = [ \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/optional_dep_feature_formatting/in/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = { version = \"0.6\", optional = true }\nrustc-serialize = { version = \"0.4\", optional = true }\nsemver = \"0.1\"\ntoml = { version = \"0.1\", optional = true }\nclippy = { version = \"0.4\", optional = true }\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\n  # Leading clippy\n  \"dep:clippy\",  # trailing clippy\n\n  # Leading docopt\n  \"dep:docopt\",  # trailing docopt\n\n  # Leading rustc-serialize\n  \"dep:rustc-serialize\",  # trailing rustc-serialize\n\n  # Leading serde/std\n  \"serde/std\",  # trailing serde/std\n\n  # Leading semver/std\n  \"semver/std\",  # trailing semver/std\n\n  # Leading toml\n  \"dep:toml\",  # trailing toml\n]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/optional_dep_feature_formatting/in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/optional_dep_feature_formatting/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"docopt\", \"toml\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/optional_dep_feature_formatting/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\nrustc-serialize = { version = \"0.4\", optional = true }\nsemver = \"0.1\"\nclippy = { version = \"0.4\", optional = true }\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\n  # Leading clippy\n  \"dep:clippy\",  # trailing clippy\n\n  # Leading docopt\n  # trailing docopt\n\n  # Leading rustc-serialize\n  \"dep:rustc-serialize\",  # trailing rustc-serialize\n\n  # Leading serde/std\n  \"serde/std\",  # trailing serde/std\n\n  # Leading semver/std\n  \"semver/std\",  # trailing semver/std\n\n  # Leading toml\n  # trailing toml\n]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/optional_feature/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"semver\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/optional_feature/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/package/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"dbus\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"ncurses\", \"20.0.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"docopt\", \"--package\", \"dep-a\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/package/out/Cargo.toml",
    "content": "[workspace]\nmembers = [\n    \"dep-a\",\n    \"dep-b\"\n]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/package/out/dep-a/Cargo.toml",
    "content": "[package]\nname = \"dep-a\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/package/out/dep-a/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/package/out/dep-b/Cargo.toml",
    "content": "[package]\nname = \"dep-b\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/package/out/dep-b/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/remove-basic.in/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/remove-basic.in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/remove-package.in/Cargo.toml",
    "content": "[workspace]\nmembers = [\n    \"dep-a\",\n    \"dep-b\"\n]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/remove-package.in/dep-a/Cargo.toml",
    "content": "[package]\nname = \"dep-a\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/remove-package.in/dep-a/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/remove-package.in/dep-b/Cargo.toml",
    "content": "[package]\nname = \"dep-b\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/remove-package.in/dep-b/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/remove-target.in/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-target-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[target.x86_64-unknown-freebsd.build-dependencies]\nsemver = \"0.1.0\"\n\n[target.wasm32-unknown-unknown.build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[target.wasm32-unknown-unknown.dependencies]\ndbus = \"0.6.2\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[target.wasm32-unknown-unknown.dev-dependencies]\nncurses = \"20.0\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/remove_basic/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"docopt\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/remove_basic/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/script/in/cargo-remove-test-fixture.rs",
    "content": "---\nedition = \"2015\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n---\n\nfn main() {\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/script/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .arg(\"-Zscript\")\n        .arg(\"remove\")\n        .arg_line(\"--manifest-path cargo-remove-test-fixture.rs docopt\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/script/out/cargo-remove-test-fixture.rs",
    "content": "---\nedition = \"2015\"\n\n[dependencies]\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n---\n\nfn main() {\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/script_last/in/cargo-remove-test-fixture.rs",
    "content": "---\n[dependencies]\ndocopt = \"0.6\"\n---\n\nfn main() {\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/script_last/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .arg(\"-Zscript\")\n        .arg(\"remove\")\n        .arg_line(\"--manifest-path cargo-remove-test-fixture.rs docopt\")\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/script_last/out/cargo-remove-test-fixture.rs",
    "content": "---\n\n---\n\nfn main() {\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/skip_gc_glob_profile/in/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[dependencies]\ntoml = \"0.1\"\n\n[profile.dev.package.\"*\"]\nopt-level = 3\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/skip_gc_glob_profile/in/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/skip_gc_glob_profile/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"toml\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/skip_gc_glob_profile/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[profile.dev.package.\"*\"]\nopt-level = 3\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/target/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"dbus\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"ncurses\", \"20.0.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--target\", \"wasm32-unknown-unknown\", \"dbus\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/target/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-target-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[target.x86_64-unknown-freebsd.build-dependencies]\nsemver = \"0.1.0\"\n\n[target.wasm32-unknown-unknown.build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[target.wasm32-unknown-unknown.dev-dependencies]\nncurses = \"20.0\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/target_build/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"dbus\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"ncurses\", \"20.0.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--build\", \"--target\", \"wasm32-unknown-unknown\", \"semver\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/target_build/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-target-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[target.x86_64-unknown-freebsd.build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[target.wasm32-unknown-unknown.dependencies]\ndbus = \"0.6.2\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[target.wasm32-unknown-unknown.dev-dependencies]\nncurses = \"20.0\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/target_dev/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"dbus\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"ncurses\", \"20.0.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--dev\", \"--target\", \"wasm32-unknown-unknown\", \"ncurses\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/target_dev/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-target-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[target.x86_64-unknown-freebsd.build-dependencies]\nsemver = \"0.1.0\"\n\n[target.wasm32-unknown-unknown.build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[target.wasm32-unknown-unknown.dependencies]\ndbus = \"0.6.2\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/update_lock_file/in/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/update_lock_file/in/src/main.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/update_lock_file/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"rustc-serialize\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/update_lock_file/out/Cargo.toml",
    "content": "[package]\nname = \"cargo-remove-test-fixture\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = \"0.1.0\"\n\n[dependencies]\ndocopt = \"0.6\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/update_lock_file/out/src/main.rs",
    "content": "fn main() {}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace/in/Cargo.toml",
    "content": "[workspace]\nmembers = [ \"my-package\" ]\n\n[workspace.dependencies]\nsemver = \"0.1.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace/in/my-package/Cargo.toml",
    "content": "[package]\nname = \"my-package\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = { workspace = true }\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace/in/my-package/src/main.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--package\", \"my-package\", \"--build\", \"semver\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace/out/Cargo.toml",
    "content": "[workspace]\nmembers = [ \"my-package\" ]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace/out/my-package/Cargo.toml",
    "content": "[package]\nname = \"my-package\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace/out/my-package/src/main.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_non_virtual/in/Cargo.toml",
    "content": "[workspace]\nmembers = [ \"my-member\" ]\n\n[workspace.dependencies]\nsemver = \"0.1.0\"\n\n[package]\nname = \"my-package\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = { workspace = true }\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_non_virtual/in/my-member/Cargo.toml",
    "content": "[package]\nname = \"my-member\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_non_virtual/in/my-member/src/main.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_non_virtual/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--package\", \"my-package\", \"--build\", \"semver\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_non_virtual/out/Cargo.toml",
    "content": "[workspace]\nmembers = [ \"my-member\" ]\n\n[package]\nname = \"my-package\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_non_virtual/out/my-member/Cargo.toml",
    "content": "[package]\nname = \"my-member\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_non_virtual/out/my-member/src/main.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_preserved/in/Cargo.toml",
    "content": "[workspace]\nmembers = [ \"my-package\", \"my-other-package\" ]\n\n[workspace.dependencies]\nsemver = \"0.1.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_preserved/in/my-other-package/Cargo.toml",
    "content": "[package]\nname = \"my-other-package\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nsemver = { workspace = true }\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_preserved/in/my-other-package/src/main.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_preserved/in/my-package/Cargo.toml",
    "content": "[package]\nname = \"my-package\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[build-dependencies]\nsemver = { workspace = true }\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_preserved/in/my-package/src/main.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_preserved/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::compare::assert_ui;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    cargo_test_support::registry::init();\n    cargo_test_support::registry::Package::new(\"clippy\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"docopt\", \"0.6.2+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"regex\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"rustc-serialize\", \"0.4.0+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"toml\", \"0.1.1+my-package\").publish();\n    cargo_test_support::registry::Package::new(\"semver\", \"0.1.1\")\n        .feature(\"std\", &[])\n        .publish();\n    cargo_test_support::registry::Package::new(\"serde\", \"1.0.90\")\n        .feature(\"std\", &[])\n        .publish();\n\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"remove\")\n        .args([\"--package\", \"my-package\", \"--build\", \"semver\"])\n        .current_dir(cwd)\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n\n    assert_ui().subset_matches(current_dir!().join(\"out\"), &project_root);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_preserved/out/Cargo.toml",
    "content": "[workspace]\nmembers = [ \"my-package\", \"my-other-package\" ]\n\n[workspace.dependencies]\nsemver = \"0.1.0\"\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_preserved/out/my-other-package/Cargo.toml",
    "content": "[package]\nname = \"my-other-package\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nsemver = { workspace = true }\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_preserved/out/my-other-package/src/main.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_preserved/out/my-package/Cargo.toml",
    "content": "[package]\nname = \"my-package\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[[bin]]\nname = \"main\"\npath = \"src/main.rs\"\n\n[dependencies]\ndocopt = \"0.6\"\nrustc-serialize = \"0.4\"\nsemver = \"0.1\"\ntoml = \"0.1\"\nclippy = \"0.4\"\n\n[dev-dependencies]\nregex = \"0.1.1\"\nserde = \"1.0.90\"\n\n[features]\nstd = [\"serde/std\", \"semver/std\"]\n"
  },
  {
    "path": "tests/testsuite/cargo_remove/workspace_preserved/out/my-package/src/main.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/cargo_report/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"report\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_report/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_report_future_incompat/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .args([\"report\", \"future-incompat\"])\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_report_future_incompat/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_report_rebuilds/mod.rs",
    "content": "//! Tests for `cargo report rebuilds`.\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\n\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::paths;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn gated_stable_channel() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"report rebuilds\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `cargo report rebuilds` command is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel\nSee https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels.\nSee https://github.com/rust-lang/cargo/issues/15844 for more information about the `cargo report rebuilds` command.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn gated_unstable_options() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"report rebuilds\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `cargo report rebuilds` command is unstable, pass `-Z build-analysis` to enable it\nSee https://github.com/rust-lang/cargo/issues/15844 for more information about the `cargo report rebuilds` command.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_log() {\n    cargo_process(\"report rebuilds -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no sessions found\n  |\n  = [NOTE] run command with `-Z build-analysis` to generate log files\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_log_for_the_current_workspace() {\n    let foo = project()\n        .at(\"foo\")\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    // one log file got generated.\n    let _ = paths::log_file(0);\n\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    bar.cargo(\"report rebuilds -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no sessions found for workspace at `[ROOT]/bar`\n  |\n  = [NOTE] run command with `-Z build-analysis` to generate log files\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_rebuild_data() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.cargo(\"report rebuilds -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession: [..]\nStatus: 0 units rebuilt, 0 cached, 1 new\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn basic_rebuild() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.change_file(\"src/lib.rs\", \"// touched\");\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.cargo(\"report rebuilds -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession: [..]\nStatus: 1 unit rebuilt, 0 cached, 0 new\n\nRebuild impact:\n  root rebuilds: 1 unit\n  cascading:     0 units\n\nRoot rebuilds:\n  0. foo@0.0.0 (check): file modified: src/lib.rs\n     impact: no cascading rebuilds\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn all_fresh() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    // Second build without changes\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.cargo(\"report rebuilds -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession: [..]\nStatus: 0 units rebuilt, 1 cached, 0 new\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn with_dependencies() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            edition = \"2021\"\n\n            [dependencies]\n            dep = { path = \"dep\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            edition = \"2021\"\n\n            [dependencies]\n            nested = { path = \"../nested\" }\n            \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .file(\n            \"nested/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"nested\"\n            edition = \"2021\"\n\n            [dependencies]\n            deep = { path = \"../deep\" }\n            \"#,\n        )\n        .file(\"nested/src/lib.rs\", \"\")\n        .file(\n            \"deep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"deep\"\n            edition = \"2021\"\n\n            [dependencies]\n            deeper = { path = \"../deeper\" }\n            \"#,\n        )\n        .file(\"deep/src/lib.rs\", \"\")\n        .file(\"deeper/Cargo.toml\", &basic_manifest(\"deeper\", \"0.0.0\"))\n        .file(\"deeper/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.change_file(\"deeper/src/lib.rs\", \"// touched\");\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.cargo(\"report rebuilds -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession: [..]\nStatus: 5 units rebuilt, 0 cached, 0 new\n\nRebuild impact:\n  root rebuilds: 1 unit\n  cascading:     4 units\n\nRoot rebuilds:\n  0. deeper@0.0.0 (check): file modified: deeper/src/lib.rs\n     impact: 4 dependent units rebuilt\n\n[NOTE] pass `-vv` to show all affected rebuilt unit lists\n\n\"#]])\n        .run();\n\n    p.cargo(\"report rebuilds -Zbuild-analysis -vv\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession: [..]\nStatus: 5 units rebuilt, 0 cached, 0 new\n\nRebuild impact:\n  root rebuilds: 1 unit\n  cascading:     4 units\n\nRoot rebuilds:\n  0. deeper@0.0.0 (check): file modified: deeper/src/lib.rs\n     impact: 4 dependent units rebuilt\n       - deep@0.0.0 (check)\n       - dep@0.0.0 (check)\n       - foo@0.0.0 (check)\n       - nested@0.0.0 (check)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_root_causes() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"pkg1\", \"pkg2\", \"pkg3\", \"pkg4\", \"pkg5\", \"pkg6\"]\n            resolver = \"2\"\n            \"#,\n        )\n        .file(\"pkg1/Cargo.toml\", &basic_manifest(\"pkg1\", \"0.0.0\"))\n        .file(\"pkg1/src/lib.rs\", \"\")\n        .file(\"pkg2/Cargo.toml\", &basic_manifest(\"pkg2\", \"0.0.0\"))\n        .file(\"pkg2/src/lib.rs\", \"\")\n        .file(\"pkg3/Cargo.toml\", &basic_manifest(\"pkg3\", \"0.0.0\"))\n        .file(\"pkg3/src/lib.rs\", \"\")\n        .file(\"pkg4/Cargo.toml\", &basic_manifest(\"pkg4\", \"0.0.0\"))\n        .file(\n            \"pkg4/src/lib.rs\",\n            \"fn f() { let _ = option_env!(\\\"__CARGO_TEST_MY_FOO\\\");}\",\n        )\n        .file(\"pkg5/Cargo.toml\", &basic_manifest(\"pkg5\", \"0.0.0\"))\n        .file(\"pkg5/src/lib.rs\", \"\")\n        .file(\"pkg6/Cargo.toml\", &basic_manifest(\"pkg6\", \"0.0.0\"))\n        .file(\"pkg6/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.change_file(\n        \"pkg1/Cargo.toml\",\n        r#\"\n        [package]\n        name = \"pkg1\"\n        edition = \"2021\"\n\n        [features]\n        feat = []\n        \"#,\n    );\n    p.change_file(\"pkg2/src/lib.rs\", \"// touched\");\n    p.change_file(\n        \"pkg3/Cargo.toml\",\n        r#\"\n        [package]\n        name = \"pkg3\"\n        edition = \"2024\"\n        \"#,\n    );\n    p.change_file(\"pkg5/src/lib.rs\", \"// touched\");\n    p.change_file(\"pkg6/src/lib.rs\", \"// touched\");\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .env(\"__CARGO_TEST_MY_FOO\", \"1\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.cargo(\"report rebuilds -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession: [..]\nStatus: 6 units rebuilt, 0 cached, 0 new\n\nRebuild impact:\n  root rebuilds: 6 units\n  cascading:     0 units\n\nRoot rebuilds: (top 5 of 6 by impact)\n  0. pkg1@0.0.0 (check): declared features changed: [] -> [\"feat\"]\n     impact: no cascading rebuilds\n  1. pkg2@0.0.0 (check): file modified: pkg2/src/lib.rs\n     impact: no cascading rebuilds\n  2. pkg3@0.0.0 (check): target configuration changed\n     impact: no cascading rebuilds\n  3. pkg4@0.0.0 (check): environment variable changed (__CARGO_TEST_MY_FOO): <unset> -> 1\n     impact: no cascading rebuilds\n  4. pkg5@0.0.0 (check): file modified: pkg5/src/lib.rs\n     impact: no cascading rebuilds\n\n[NOTE] pass `--verbose` to show all root rebuilds\n\n\"#]])\n        .run();\n\n    p.cargo(\"report rebuilds -Zbuild-analysis --verbose\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession: [..]\nStatus: 6 units rebuilt, 0 cached, 0 new\n\nRebuild impact:\n  root rebuilds: 6 units\n  cascading:     0 units\n\nRoot rebuilds:\n  0. pkg1@0.0.0 (check): declared features changed: [] -> [\"feat\"]\n     impact: no cascading rebuilds\n  1. pkg2@0.0.0 (check): file modified: pkg2/src/lib.rs\n     impact: no cascading rebuilds\n  2. pkg3@0.0.0 (check): target configuration changed\n     impact: no cascading rebuilds\n  3. pkg4@0.0.0 (check): environment variable changed (__CARGO_TEST_MY_FOO): <unset> -> 1\n     impact: no cascading rebuilds\n  4. pkg5@0.0.0 (check): file modified: pkg5/src/lib.rs\n     impact: no cascading rebuilds\n  5. pkg6@0.0.0 (check): file modified: pkg6/src/lib.rs\n     impact: no cascading rebuilds\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn shared_dep_cascading() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"foo\", \"bar\"]\n            resolver = \"2\"\n\n            [workspace.dependencies]\n            common = { path = \"common\" }\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            edition = \"2021\"\n\n            [dependencies]\n            common = { workspace = true }\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            edition = \"2021\"\n\n            [dependencies]\n            common = { workspace = true }\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"common/Cargo.toml\", &basic_manifest(\"common\", \"0.0.0\"))\n        .file(\"common/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.change_file(\"common/src/lib.rs\", \"// touched\");\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.cargo(\"report rebuilds -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession: [..]\nStatus: 3 units rebuilt, 0 cached, 0 new\n\nRebuild impact:\n  root rebuilds: 1 unit\n  cascading:     2 units\n\nRoot rebuilds:\n  0. common@0.0.0 (check): file modified: common/src/lib.rs\n     impact: 2 dependent units rebuilt\n\n[NOTE] pass `-vv` to show all affected rebuilt unit lists\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn outside_workspace() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.change_file(\"src/lib.rs\", \"// touched\");\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    cargo_process(\"report rebuilds -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession: [..]\nStatus: 1 unit rebuilt, 0 cached, 0 new\n\nRebuild impact:\n  root rebuilds: 1 unit\n  cascading:     0 units\n\nRoot rebuilds:\n  0. foo@0.0.0 (check): file modified: foo/src/lib.rs\n     impact: no cascading rebuilds\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn with_manifest_path() {\n    let foo = project()\n        .at(\"foo\")\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    bar.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    bar.change_file(\"src/lib.rs\", \"// touched\");\n    bar.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    foo.cargo(\"report rebuilds --manifest-path ../bar/Cargo.toml -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession: [..]\nStatus: 1 unit rebuilt, 0 cached, 0 new\n\nRebuild impact:\n  root rebuilds: 1 unit\n  cascading:     0 units\n\nRoot rebuilds:\n  0. bar@0.0.0 (check): file modified: src/lib.rs\n     impact: no cascading rebuilds\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn with_session_id() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // First session: fresh build (1 new unit)\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    let first_log = paths::log_file(0);\n    let first_session_id = first_log.file_stem().unwrap().to_str().unwrap();\n\n    p.change_file(\"src/lib.rs\", \"// touched\");\n\n    // Second session: rebuild (1 unit rebuilt)\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    let _ = paths::log_file(1);\n\n    // With --id, should use the first session (not the most recent second)\n    p.cargo(&format!(\n        \"report rebuilds --id {first_session_id} -Zbuild-analysis\"\n    ))\n    .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n    .with_stderr_data(str![[r#\"\nSession: [..]\nStatus: 0 units rebuilt, 0 cached, 1 new\n\n\n\"#]])\n    .run();\n}\n\n#[cargo_test]\nfn session_id_not_found() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.cargo(\"report rebuilds --id 20260101T000000000Z-0000000000000000 -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] session `20260101T000000000Z-0000000000000000` not found for workspace at `[ROOT]/foo`\n  |\n  = [NOTE] run `cargo report sessions` to list available sessions\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_session_id_format() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"report rebuilds --id invalid-session-id -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] expect run ID in format `20060724T012128000Z-<16-char-hex>`, got `invalid-session-id`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_report_sessions/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .args([\"report\", \"sessions\"])\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_report_sessions/mod.rs",
    "content": "//! Tests for `cargo report sessions`.\n\nmod help;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\n\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn gated_stable_channel() {\n    cargo_process(\"report sessions\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `cargo report sessions` command is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel\nSee https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels.\nSee https://github.com/rust-lang/cargo/issues/15844 for more information about the `cargo report sessions` command.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn gated_unstable_options() {\n    cargo_process(\"report sessions\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `cargo report sessions` command is unstable, pass `-Z build-analysis` to enable it\nSee https://github.com/rust-lang/cargo/issues/15844 for more information about the `cargo report sessions` command.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_logs() {\n    cargo_process(\"report sessions -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no sessions found\n  |\n  = [NOTE] run build commands with `-Z build-analysis` to generate log files\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_logs_in_workspace() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"report sessions -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no sessions found for workspace at `[ROOT]/foo`\n  |\n  = [NOTE] run build commands with `-Z build-analysis` to generate log files\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn in_workspace() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.cargo(\"report sessions -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession IDs for `[ROOT]/foo` (most recent first):\n\n - [..]T[..]Z-[..]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn outside_workspace() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    // cd to outside the workspace, should show all sessions\n    cargo_process(\"report sessions -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession IDs (most recent first):\n\n - [..]T[..]Z-[..]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn with_limit_1_and_extra_logs() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Generate 3 sessions\n    for i in 0..3 {\n        p.change_file(\"src/lib.rs\", &format!(\"pub fn foo{i}() {{}}\"));\n        p.cargo(\"check -Zbuild-analysis\")\n            .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n            .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n            .run();\n    }\n\n    p.cargo(\"report sessions --limit 1 -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession IDs for `[ROOT]/foo` (most recent first):\n\n - [..]T[..]Z-[..]\n\n... and more (use --limit N to see more)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn with_limit_5_but_not_enough_logs() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Generate 2 sessions\n    for i in 0..2 {\n        p.change_file(\"src/lib.rs\", &format!(\"pub fn foo{i}() {{}}\"));\n        p.cargo(\"check -Zbuild-analysis\")\n            .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n            .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n            .run();\n    }\n\n    p.cargo(\"report sessions --limit 5 -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession IDs for `[ROOT]/foo` (most recent first):\n\n - [..]T[..]Z-[..]\n - [..]T[..]Z-[..]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn existing_logs_from_other_workspaces() {\n    let foo = project()\n        .at(\"foo\")\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    bar.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    // In foo workspace, should only show foo sessions by default\n    foo.cargo(\"report sessions -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession IDs for `[ROOT]/foo` (most recent first):\n\n - [..]T[..]Z-[..]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn with_manifest_path() {\n    let foo = project()\n        .at(\"foo\")\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    bar.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    foo.cargo(\"report sessions --manifest-path ../bar/Cargo.toml -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\nSession IDs for `[ROOT]/bar` (most recent first):\n\n - [..]T[..]Z-[..]\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_report_timings/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .args([\"report\", \"timings\"])\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_report_timings/mod.rs",
    "content": "//! Tests for `cargo report timings`.\n\nmod help;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\n\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::paths;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn gated_stable_channel() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"report timings\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `cargo report timings` command is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel\nSee https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels.\nSee https://github.com/rust-lang/cargo/issues/15844 for more information about the `cargo report timings` command.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn gated_unstable_options() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"report timings\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `cargo report timings` command is unstable, pass `-Z build-analysis` to enable it\nSee https://github.com/rust-lang/cargo/issues/15844 for more information about the `cargo report timings` command.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_log() {\n    cargo_process(\"report timings -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no sessions found\n  |\n  = [NOTE] run command with `-Z build-analysis` to generate log files\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_log_for_the_current_workspace() {\n    let foo = project()\n        .at(\"foo\")\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    // one log file got generated.\n    let _ = paths::log_file(0);\n\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    bar.cargo(\"report timings -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no sessions found for workspace at `[ROOT]/bar`\n  |\n  = [NOTE] run command with `-Z build-analysis` to generate log files\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_log() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    // Put some junks in the log file.\n    std::fs::write(paths::log_file(0), \"}|x| hello world\").unwrap();\n\n    p.cargo(\"report timings -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to analyze log at `[ROOT]/home/.cargo/log/[..]T[..]Z-[..].jsonl`\n\nCaused by:\n  no timing data found in log\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn empty_log() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    // Truncate the log file.\n    std::fs::File::create(paths::log_file(0)).unwrap();\n\n    // If the make-up log file was picked, the command would have failed.\n    p.cargo(\"report timings -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to analyze log at `[ROOT]/home/.cargo/log/[..]T[..]Z-[..].jsonl`\n\nCaused by:\n  no timing data found in log\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn prefer_latest() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    // Put some junks in the first log file.\n    std::fs::write(paths::log_file(0), \"}|x| hello world\").unwrap();\n\n    p.change_file(\"src/lib.rs\", \"pub fn foo() {}\");\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    // the second log file got generated.\n    let _ = paths::log_file(1);\n\n    // if it had picked the corrupted first log file, it would have failed.\n    p.cargo(\"report timings -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\n      Timing report saved to [ROOT]/foo/target/cargo-timings/cargo-timing-[..]T[..]Z-[..].html\n\n\"#]])\n        .run();\n\n    assert_eq!(p.glob(\"**/cargo-timing-*.html\").count(), 1);\n}\n\n#[cargo_test]\nfn prefer_workspace() {\n    let foo = project()\n        .at(\"foo\")\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    // one log file got generated.\n    let _ = paths::log_file(0);\n\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    bar.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    // Put some junks in the newest log file.\n    std::fs::write(paths::log_file(1), \"}|x| hello world\").unwrap();\n\n    // Back to foo, if it had picked the corrupted log file, it would have failed.\n    foo.cargo(\"report timings -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\n      Timing report saved to [ROOT]/foo/target/cargo-timings/cargo-timing-[..]T[..]Z-[..].html\n\n\"#]])\n        .run();\n\n    assert_eq!(foo.glob(\"**/cargo-timing-*.html\").count(), 1);\n}\n\n#[cargo_test]\nfn outside_workspace() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    // cd to outside the workspace, it should\n    // * retrieve the latest log\n    // * save the report in a temp directory\n    cargo_process(\"report timings -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\n      Timing report saved to [..]/cargo-timing-[..]T[..]Z-[..].html\n\n\"#]])\n        .run();\n\n    // Have no timing HTML under target directory\n    assert_eq!(p.glob(\"**/cargo-timing-*.html\").count(), 0);\n}\n\n#[cargo_test]\nfn with_manifest_path() {\n    let foo = project()\n        .at(\"foo\")\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    bar.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    foo.cargo(\"report timings --manifest-path ../bar/Cargo.toml -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\n      Timing report saved to [ROOT]/bar/target/cargo-timings/cargo-timing-[..]T[..]-[..].html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"rustc --json=timings is unstable\")]\nfn with_section_timings() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis -Zsection-timings\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\", \"section-timings\"])\n        .run();\n\n    p.cargo(\"report timings -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\n      Timing report saved to [ROOT]/foo/target/cargo-timings/cargo-timing-[..]T[..]Z-[..].html\n\n\"#]])\n        .run();\n\n    assert_eq!(p.glob(\"**/cargo-timing-*.html\").count(), 1);\n}\n\n#[cargo_test]\nfn with_multiple_targets() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            edition = \"2021\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn lib_fn() {}\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/bin/extra.rs\", \"fn main() {}\")\n        .file(\"examples/ex1.rs\", \"fn main() {}\")\n        .file(\"tests/t1.rs\", \"#[test] fn test1() {}\")\n        .build();\n\n    p.cargo(\"check --all-targets -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.cargo(\"report timings -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_stderr_data(str![[r#\"\n      Timing report saved to [ROOT]/foo/target/cargo-timings/cargo-timing-[..]T[..]Z-[..].html\n\n\"#]])\n        .run();\n\n    assert_eq!(p.glob(\"**/cargo-timing-*.html\").count(), 1);\n}\n\n#[cargo_test]\nfn with_session_id() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    let first_log = paths::log_file(0);\n    let first_session_id = first_log.file_stem().unwrap().to_str().unwrap();\n\n    p.change_file(\"src/lib.rs\", \"pub fn foo() {}\");\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    let second_log = paths::log_file(1);\n    let second_session_id = second_log.file_stem().unwrap().to_str().unwrap();\n\n    // With --id, should use the first session (not the most recent second)\n    p.cargo(&format!(\n        \"report timings --id {first_session_id} -Zbuild-analysis\"\n    ))\n    .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n    .with_stderr_data(str![[r#\"\n      Timing report saved to [ROOT]/foo/target/cargo-timings/cargo-timing-[..]T[..]Z-[..].html\n\n\"#]])\n    .run();\n\n    let timing_files: Vec<_> = p.glob(\"**/cargo-timing-*.html\").collect();\n    assert_eq!(timing_files.len(), 1);\n    let timing_file = timing_files[0].as_ref().unwrap();\n    let filename = timing_file.file_name().unwrap().to_str().unwrap();\n    assert!(\n        filename.contains(first_session_id),\n        \"Expected timing file to contain first session ID {first_session_id}, got {filename}\"\n    );\n    assert!(\n        !filename.contains(second_session_id),\n        \"Should not contain second session ID {second_session_id}, got {filename}\"\n    );\n}\n\n#[cargo_test]\nfn session_id_not_found() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zbuild-analysis\")\n        .env(\"CARGO_BUILD_ANALYSIS_ENABLED\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .run();\n\n    p.cargo(\"report timings --id 20260101T000000000Z-0000000000000000 -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] session `20260101T000000000Z-0000000000000000` not found for workspace at `[ROOT]/foo`\n  |\n  = [NOTE] run `cargo report sessions` to list available sessions\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_session_id_format() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"report timings --id invalid-session-id -Zbuild-analysis\")\n        .masquerade_as_nightly_cargo(&[\"build-analysis\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] expect run ID in format `20060724T012128000Z-<16-char-hex>`, got `invalid-session-id`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_run/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"run\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_run/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_rustc/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"rustc\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_rustc/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_rustdoc/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"rustdoc\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_rustdoc/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_search/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"search\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_search/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_targets.rs",
    "content": "//! Tests specifically related to target handling (lib, bins, examples, tests, benches).\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn warn_unmatched_target_filters() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n        [package]\n        name = \"foo\"\n        version = \"0.1.0\"\n        edition = \"2015\"\n\n        [lib]\n        test = false\n        bench = false\n        \"#,\n        )\n        .file(\"src/lib.rs\", r#\"fn main() {}\"#)\n        .build();\n\n    p.cargo(\"check --tests --bins --examples --benches\")\n        .with_stderr_data(str![[r#\"\n[WARNING] target filters `bins`, `tests`, `examples`, `benches` specified, but no targets matched; this is a no-op\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn reserved_windows_target_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [[bin]]\n            name = \"con\"\n            path = \"src/main.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    if cfg!(windows) {\n        p.cargo(\"check\")\n            .with_stderr_data(str![[r#\"\n[WARNING] binary target `con` is a reserved Windows filename, this target will not work on Windows platforms\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n            .run();\n    } else {\n        p.cargo(\"check\")\n            .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n            .run();\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_test/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"test\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_test/mod.rs",
    "content": "mod help;\nmod no_keep_going;\n"
  },
  {
    "path": "tests/testsuite/cargo_test/no_keep_going/in/Cargo.toml",
    "content": "[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2015\"\n"
  },
  {
    "path": "tests/testsuite/cargo_test/no_keep_going/in/src/lib.rs",
    "content": ""
  },
  {
    "path": "tests/testsuite/cargo_test/no_keep_going/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"test\")\n        .arg(\"--keep-going\")\n        .current_dir(cwd)\n        .assert()\n        .code(1)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_tree/deps.rs",
    "content": "//! Tests for the `cargo tree` command.\n\nuse crate::prelude::*;\nuse crate::utils::cross_compile::disabled as cross_compile_disabled;\nuse cargo_test_support::cross_compile::alternate;\nuse cargo_test_support::registry::{Dependency, Package};\nuse cargo_test_support::str;\nuse cargo_test_support::{Project, basic_manifest, git, project, rustc_host};\n\nuse crate::features2::switch_to_resolver_2;\n\nfn make_simple_proj() -> Project {\n    Package::new(\"c\", \"1.0.0\").publish();\n    Package::new(\"b\", \"1.0.0\").dep(\"c\", \"1.0\").publish();\n    Package::new(\"a\", \"1.0.0\").dep(\"b\", \"1.0\").publish();\n    Package::new(\"bdep\", \"1.0.0\").dep(\"b\", \"1.0\").publish();\n    Package::new(\"devdep\", \"1.0.0\").dep(\"b\", \"1.0.0\").publish();\n\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            a = \"1.0\"\n            c = \"1.0\"\n\n            [build-dependencies]\n            bdep = \"1.0\"\n\n            [dev-dependencies]\n            devdep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build()\n}\n\n#[cargo_test]\nfn simple() {\n    // A simple test with a few different dependencies.\n    let p = make_simple_proj();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── a v1.0.0\n│   └── b v1.0.0\n│       └── c v1.0.0\n└── c v1.0.0\n[build-dependencies]\n└── bdep v1.0.0\n    └── b v1.0.0 (*)\n[dev-dependencies]\n└── devdep v1.0.0\n    └── b v1.0.0 (*)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -p bdep\")\n        .with_stdout_data(str![[r#\"\nbdep v1.0.0\n└── b v1.0.0\n    └── c v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn virtual_workspace() {\n    // Multiple packages in a virtual workspace.\n    Package::new(\"somedep\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"baz\", \"c\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"1.0.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"baz\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            c = { path = \"../c\" }\n            somedep = \"1.0\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .file(\"c/Cargo.toml\", &basic_manifest(\"c\", \"1.0.0\"))\n        .file(\"c/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\na v1.0.0 ([ROOT]/foo/a)\n\nbaz v0.1.0 ([ROOT]/foo/baz)\n├── c v1.0.0 ([ROOT]/foo/c)\n└── somedep v1.0.0\n\nc v1.0.0 ([ROOT]/foo/c)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -p a\")\n        .with_stdout_data(str![[r#\"\na v1.0.0 ([ROOT]/foo/a)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree\")\n        .cwd(\"baz\")\n        .with_stdout_data(str![[r#\"\nbaz v0.1.0 ([ROOT]/foo/baz)\n├── c v1.0.0 ([ROOT]/foo/c)\n└── somedep v1.0.0\n\n\"#]])\n        .run();\n\n    // exclude baz\n    p.cargo(\"tree --workspace --exclude baz\")\n        .with_stdout_data(str![[r#\"\na v1.0.0 ([ROOT]/foo/a)\n\nc v1.0.0 ([ROOT]/foo/c)\n\n\"#]])\n        .run();\n\n    // exclude glob '*z'\n    p.cargo(\"tree --workspace --exclude '*z'\")\n        .with_stdout_data(str![[r#\"\na v1.0.0 ([ROOT]/foo/a)\n\nc v1.0.0 ([ROOT]/foo/c)\n\n\"#]])\n        .run();\n\n    // include glob '*z'\n    p.cargo(\"tree -p '*z'\")\n        .with_stdout_data(str![[r#\"\nbaz v0.1.0 ([ROOT]/foo/baz)\n├── c v1.0.0 ([ROOT]/foo/c)\n└── somedep v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dedupe_edges() {\n    // Works around https://github.com/rust-lang/cargo/issues/7985\n    Package::new(\"bitflags\", \"1.0.0\").publish();\n    Package::new(\"manyfeat\", \"1.0.0\")\n        .feature(\"f1\", &[])\n        .feature(\"f2\", &[])\n        .feature(\"f3\", &[])\n        .dep(\"bitflags\", \"1.0\")\n        .publish();\n    Package::new(\"a\", \"1.0.0\")\n        .feature_dep(\"manyfeat\", \"1.0\", &[\"f1\"])\n        .publish();\n    Package::new(\"b\", \"1.0.0\")\n        .feature_dep(\"manyfeat\", \"1.0\", &[\"f2\"])\n        .publish();\n    Package::new(\"c\", \"1.0.0\")\n        .feature_dep(\"manyfeat\", \"1.0\", &[\"f3\"])\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            a = \"1.0\"\n            b = \"1.0\"\n            c = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── a v1.0.0\n│   └── manyfeat v1.0.0\n│       └── bitflags v1.0.0\n├── b v1.0.0\n│   └── manyfeat v1.0.0 (*)\n└── c v1.0.0\n    └── manyfeat v1.0.0 (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn renamed_deps() {\n    // Handles renamed dependencies.\n    Package::new(\"one\", \"1.0.0\").publish();\n    Package::new(\"two\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\").dep(\"one\", \"1.0\").publish();\n    Package::new(\"bar\", \"2.0.0\").dep(\"two\", \"1.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n\n            [dependencies]\n            bar1 = {version = \"1.0\", package=\"bar\"}\n            bar2 = {version = \"2.0\", package=\"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n├── bar v1.0.0\n│   └── one v1.0.0\n└── bar v2.0.0\n    └── two v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn source_kinds() {\n    // Handles git and path sources.\n    Package::new(\"regdep\", \"1.0.0\").publish();\n    let git_project = git::new(\"gitdep\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"gitdep\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                regdep = \"1.0\"\n                pathdep = {{ path = \"pathdep\" }}\n                gitdep = {{ git = \"{}\" }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"pathdep/Cargo.toml\", &basic_manifest(\"pathdep\", \"1.0.0\"))\n        .file(\"pathdep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── gitdep v1.0.0 ([ROOTURL]/gitdep#[..])\n├── pathdep v1.0.0 ([ROOT]/foo/pathdep)\n└── regdep v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn features() {\n    // Exercises a variety of feature behaviors.\n    Package::new(\"optdep_default\", \"1.0.0\").publish();\n    Package::new(\"optdep\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            optdep_default = { version = \"1.0\", optional = true }\n            optdep = { version = \"1.0\", optional = true }\n\n            [features]\n            default = [\"optdep_default\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\na v0.1.0 ([ROOT]/foo)\n└── optdep_default v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --no-default-features\")\n        .with_stdout_data(str![[r#\"\na v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --all-features\")\n        .with_stdout_data(str![[r#\"\na v0.1.0 ([ROOT]/foo)\n├── optdep v1.0.0\n└── optdep_default v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --features optdep\")\n        .with_stdout_data(str![[r#\"\na v0.1.0 ([ROOT]/foo)\n├── optdep v1.0.0\n└── optdep_default v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn filters_target() {\n    // --target flag\n    if cross_compile_disabled() {\n        return;\n    }\n    Package::new(\"targetdep\", \"1.0.0\").publish();\n    Package::new(\"hostdep\", \"1.0.0\").publish();\n    Package::new(\"devdep\", \"1.0.0\").publish();\n    Package::new(\"build_target_dep\", \"1.0.0\").publish();\n    Package::new(\"build_host_dep\", \"1.0.0\")\n        .target_dep(\"targetdep\", \"1.0\", alternate())\n        .target_dep(\"hostdep\", \"1.0\", rustc_host())\n        .publish();\n    Package::new(\"pm_target\", \"1.0.0\")\n        .proc_macro(true)\n        .publish();\n    Package::new(\"pm_host\", \"1.0.0\").proc_macro(true).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [target.'{alt}'.dependencies]\n                targetdep = \"1.0\"\n                pm_target = \"1.0\"\n\n                [target.'{host}'.dependencies]\n                hostdep = \"1.0\"\n                pm_host = \"1.0\"\n\n                [target.'{alt}'.dev-dependencies]\n                devdep = \"1.0\"\n\n                [target.'{alt}'.build-dependencies]\n                build_target_dep = \"1.0\"\n\n                [target.'{host}'.build-dependencies]\n                build_host_dep = \"1.0\"\n                \"#,\n                alt = alternate(),\n                host = rustc_host()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── hostdep v1.0.0\n└── pm_host v1.0.0 (proc-macro)\n[build-dependencies]\n└── build_host_dep v1.0.0\n    └── hostdep v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --target\")\n        .arg(alternate())\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── pm_target v1.0.0 (proc-macro)\n└── targetdep v1.0.0\n[build-dependencies]\n└── build_host_dep v1.0.0\n    └── hostdep v1.0.0\n[dev-dependencies]\n└── devdep v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --target\")\n        .arg(rustc_host())\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── hostdep v1.0.0\n└── pm_host v1.0.0 (proc-macro)\n[build-dependencies]\n└── build_host_dep v1.0.0\n    └── hostdep v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --target=all\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── hostdep v1.0.0\n├── pm_host v1.0.0 (proc-macro)\n├── pm_target v1.0.0 (proc-macro)\n└── targetdep v1.0.0\n[build-dependencies]\n├── build_host_dep v1.0.0\n│   ├── hostdep v1.0.0\n│   └── targetdep v1.0.0\n└── build_target_dep v1.0.0\n[dev-dependencies]\n└── devdep v1.0.0\n\n\"#]])\n        .run();\n\n    // no-proc-macro\n    p.cargo(\"tree --target=all -e no-proc-macro\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── hostdep v1.0.0\n└── targetdep v1.0.0\n[build-dependencies]\n├── build_host_dep v1.0.0\n│   ├── hostdep v1.0.0\n│   └── targetdep v1.0.0\n└── build_target_dep v1.0.0\n[dev-dependencies]\n└── devdep v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_selected_target_dependency() {\n    // --target flag\n    if cross_compile_disabled() {\n        return;\n    }\n    Package::new(\"targetdep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [target.'{alt}'.dependencies]\n                targetdep = \"1.0\"\n\n                \"#,\n                alt = alternate(),\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -i targetdep\")\n        .with_stderr_data(str![[r#\"\n[WARNING] nothing to print.\n\nTo find dependencies that require specific target platforms, try to use option `--target all` first, and then narrow your search scope accordingly.\n\n\"#]])\n        .run();\n    p.cargo(\"tree -i targetdep --target all\")\n        .with_stdout_data(str![[r#\"\ntargetdep v1.0.0\n└── foo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dep_kinds() {\n    Package::new(\"inner-devdep\", \"1.0.0\").publish();\n    Package::new(\"inner-builddep\", \"1.0.0\").publish();\n    Package::new(\"inner-normal\", \"1.0.0\").publish();\n    Package::new(\"inner-pm\", \"1.0.0\").proc_macro(true).publish();\n    Package::new(\"inner-buildpm\", \"1.0.0\")\n        .proc_macro(true)\n        .publish();\n    Package::new(\"normaldep\", \"1.0.0\")\n        .dep(\"inner-normal\", \"1.0\")\n        .dev_dep(\"inner-devdep\", \"1.0\")\n        .build_dep(\"inner-builddep\", \"1.0\")\n        .publish();\n    Package::new(\"devdep\", \"1.0.0\")\n        .dep(\"inner-normal\", \"1.0\")\n        .dep(\"inner-pm\", \"1.0\")\n        .dev_dep(\"inner-devdep\", \"1.0\")\n        .build_dep(\"inner-builddep\", \"1.0\")\n        .build_dep(\"inner-buildpm\", \"1.0\")\n        .publish();\n    Package::new(\"builddep\", \"1.0.0\")\n        .dep(\"inner-normal\", \"1.0\")\n        .dev_dep(\"inner-devdep\", \"1.0\")\n        .build_dep(\"inner-builddep\", \"1.0\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            normaldep = \"1.0\"\n\n            [dev-dependencies]\n            devdep = \"1.0\"\n\n            [build-dependencies]\n            builddep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── normaldep v1.0.0\n    └── inner-normal v1.0.0\n    [build-dependencies]\n    └── inner-builddep v1.0.0\n[build-dependencies]\n└── builddep v1.0.0\n    └── inner-normal v1.0.0\n    [build-dependencies]\n    └── inner-builddep v1.0.0\n[dev-dependencies]\n└── devdep v1.0.0\n    ├── inner-normal v1.0.0\n    └── inner-pm v1.0.0 (proc-macro)\n    [build-dependencies]\n    ├── inner-builddep v1.0.0\n    └── inner-buildpm v1.0.0 (proc-macro)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e no-dev\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── normaldep v1.0.0\n    └── inner-normal v1.0.0\n    [build-dependencies]\n    └── inner-builddep v1.0.0\n[build-dependencies]\n└── builddep v1.0.0\n    └── inner-normal v1.0.0\n    [build-dependencies]\n    └── inner-builddep v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e normal\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── normaldep v1.0.0\n    └── inner-normal v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e dev,build\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n[build-dependencies]\n└── builddep v1.0.0\n    [build-dependencies]\n    └── inner-builddep v1.0.0\n[dev-dependencies]\n└── devdep v1.0.0\n    [build-dependencies]\n    ├── inner-builddep v1.0.0\n    └── inner-buildpm v1.0.0 (proc-macro)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e dev,build,no-proc-macro\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n[build-dependencies]\n└── builddep v1.0.0\n    [build-dependencies]\n    └── inner-builddep v1.0.0\n[dev-dependencies]\n└── devdep v1.0.0\n    [build-dependencies]\n    └── inner-builddep v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cyclic_dev_dep() {\n    // Cyclical dev-dependency and inverse flag.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dev-dependencies]\n            dev-dep = { path = \"dev-dep\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"dev-dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dev-dep\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            foo = { path=\"..\" }\n            \"#,\n        )\n        .file(\"dev-dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n[dev-dependencies]\n└── dev-dep v0.1.0 ([ROOT]/foo/dev-dep)\n    └── foo v0.1.0 ([ROOT]/foo) (*)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --invert foo\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── dev-dep v0.1.0 ([ROOT]/foo/dev-dep)\n    [dev-dependencies]\n    └── foo v0.1.0 ([ROOT]/foo) (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invert() {\n    Package::new(\"b1\", \"1.0.0\").dep(\"c\", \"1.0\").publish();\n    Package::new(\"b2\", \"1.0.0\").dep(\"d\", \"1.0\").publish();\n    Package::new(\"c\", \"1.0.0\").publish();\n    Package::new(\"d\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            b1 = \"1.0\"\n            b2 = \"1.0\"\n            c = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── b1 v1.0.0\n│   └── c v1.0.0\n├── b2 v1.0.0\n│   └── d v1.0.0\n└── c v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --invert c\")\n        .with_stdout_data(str![[r#\"\nc v1.0.0\n├── b1 v1.0.0\n│   └── foo v0.1.0 ([ROOT]/foo)\n└── foo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invert_with_build_dep() {\n    // -i for a common dependency between normal and build deps.\n    Package::new(\"common\", \"1.0.0\").publish();\n    Package::new(\"bdep\", \"1.0.0\").dep(\"common\", \"1.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            common = \"1.0\"\n\n            [build-dependencies]\n            bdep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── common v1.0.0\n[build-dependencies]\n└── bdep v1.0.0\n    └── common v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -i common\")\n        .with_stdout_data(str![[r#\"\ncommon v1.0.0\n├── bdep v1.0.0\n│   [build-dependencies]\n│   └── foo v0.1.0 ([ROOT]/foo)\n└── foo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_indent() {\n    let p = make_simple_proj();\n\n    p.cargo(\"tree --prefix=none\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\na v1.0.0\nb v1.0.0\nc v1.0.0\nc v1.0.0\nbdep v1.0.0\nb v1.0.0 (*)\ndevdep v1.0.0\nb v1.0.0 (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn prefix_depth() {\n    let p = make_simple_proj();\n\n    p.cargo(\"tree --prefix=depth\")\n        .with_stdout_data(str![[r#\"\n0foo v0.1.0 ([ROOT]/foo)\n1a v1.0.0\n2b v1.0.0\n3c v1.0.0\n1c v1.0.0\n1bdep v1.0.0\n2b v1.0.0 (*)\n1devdep v1.0.0\n2b v1.0.0 (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_dedupe() {\n    let p = make_simple_proj();\n\n    p.cargo(\"tree --no-dedupe\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── a v1.0.0\n│   └── b v1.0.0\n│       └── c v1.0.0\n└── c v1.0.0\n[build-dependencies]\n└── bdep v1.0.0\n    └── b v1.0.0\n        └── c v1.0.0\n[dev-dependencies]\n└── devdep v1.0.0\n    └── b v1.0.0\n        └── c v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_dedupe_cycle() {\n    // --no-dedupe with a dependency cycle\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dev-dependencies]\n            bar = {path = \"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            foo = {path=\"..\"}\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n[dev-dependencies]\n└── bar v0.1.0 ([ROOT]/foo/bar)\n    └── foo v0.1.0 ([ROOT]/foo) (*)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --no-dedupe\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n[dev-dependencies]\n└── bar v0.1.0 ([ROOT]/foo/bar)\n    └── foo v0.1.0 ([ROOT]/foo) (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn duplicates() {\n    Package::new(\"dog\", \"1.0.0\").publish();\n    Package::new(\"dog\", \"2.0.0\").publish();\n    Package::new(\"cat\", \"1.0.0\").publish();\n    Package::new(\"cat\", \"2.0.0\").publish();\n    Package::new(\"dep\", \"1.0.0\")\n        .dep(\"dog\", \"1.0\")\n        .dep(\"cat\", \"1.0\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            dog1 = { version = \"1.0\", package = \"dog\" }\n            dog2 = { version = \"2.0\", package = \"dog\" }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            dep = \"1.0\"\n            cat = \"2.0\"\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -p a\")\n        .with_stdout_data(str![[r#\"\na v0.1.0 ([ROOT]/foo/a)\n├── dog v1.0.0\n└── dog v2.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -p b\")\n        .with_stdout_data(str![[r#\"\nb v0.1.0 ([ROOT]/foo/b)\n├── cat v2.0.0\n└── dep v1.0.0\n    ├── cat v1.0.0\n    └── dog v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -p a -d\")\n        .with_stdout_data(str![[r#\"\ndog v1.0.0\n└── a v0.1.0 ([ROOT]/foo/a)\n\ndog v2.0.0\n└── a v0.1.0 ([ROOT]/foo/a)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -p b -d\")\n        .with_stdout_data(str![[r#\"\ncat v1.0.0\n└── dep v1.0.0\n    └── b v0.1.0 ([ROOT]/foo/b)\n\ncat v2.0.0\n└── b v0.1.0 ([ROOT]/foo/b)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn duplicates_with_target() {\n    // --target flag\n    if cross_compile_disabled() {\n        return;\n    }\n    Package::new(\"a\", \"1.0.0\").publish();\n    Package::new(\"dog\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            a = \"1.0\"\n            dog = \"1.0\"\n\n            [build-dependencies]\n            a = \"1.0\"\n            dog = \"1.0\"\n\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"tree -d\").with_stdout_data(str![\"\"]).run();\n\n    p.cargo(\"tree -d --target\")\n        .arg(alternate())\n        .with_stdout_data(str![\"\"])\n        .run();\n\n    p.cargo(\"tree -d --target\")\n        .arg(rustc_host())\n        .with_stdout_data(str![\"\"])\n        .run();\n\n    p.cargo(\"tree -d --target=all\")\n        .with_stdout_data(str![\"\"])\n        .run();\n}\n\n#[cargo_test]\nfn duplicates_with_proc_macro() {\n    Package::new(\"dupe-dep\", \"1.0.0\").publish();\n    Package::new(\"dupe-dep\", \"2.0.0\").publish();\n    Package::new(\"proc\", \"1.0.0\")\n        .proc_macro(true)\n        .dep(\"dupe-dep\", \"1.0\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            proc = \"1.0\"\n            dupe-dep = \"2.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── dupe-dep v2.0.0\n└── proc v1.0.0 (proc-macro)\n    └── dupe-dep v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --duplicates\")\n        .with_stdout_data(str![[r#\"\ndupe-dep v1.0.0\n└── proc v1.0.0 (proc-macro)\n    └── foo v0.1.0 ([ROOT]/foo)\n\ndupe-dep v2.0.0\n└── foo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --duplicates --edges no-proc-macro\")\n        .with_stdout_data(str![\"\"])\n        .run();\n}\n\n#[cargo_test]\nfn charset() {\n    let p = make_simple_proj();\n    p.cargo(\"tree --charset ascii\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n|-- a v1.0.0\n|   `-- b v1.0.0\n|       `-- c v1.0.0\n`-- c v1.0.0\n[build-dependencies]\n`-- bdep v1.0.0\n    `-- b v1.0.0 (*)\n[dev-dependencies]\n`-- devdep v1.0.0\n    `-- b v1.0.0 (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn format() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n    Package::new(\"other-dep\", \"1.0.0\").publish();\n\n    Package::new(\"dep_that_is_awesome\", \"1.0.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep_that_is_awesome\"\n                version = \"1.0.0\"\n\n                [lib]\n                name = \"awesome_dep\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub struct Straw;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            license = \"MIT\"\n            repository = \"https://github.com/rust-lang/cargo\"\n\n            [dependencies]\n            dep = {version=\"1.0\", optional=true}\n            other-dep = {version=\"1.0\", optional=true}\n            dep_that_is_awesome = {version=\"1.0\", optional=true}\n\n\n            [features]\n            default = [\"foo\"]\n            foo = [\"bar\"]\n            bar = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree --format <<<{p}>>>\")\n        .with_stdout_data(str![[r#\"\n<<<foo v0.1.0 ([ROOT]/foo)>>>\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --format {}\")\n        .with_stderr_data(str![[r#\"\n[ERROR] tree format `{}` not valid\n\nCaused by:\n  unsupported pattern ``\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    p.cargo(\"tree --format {p}-{{hello}}\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)-{hello}\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --format\")\n        .arg(\"{p} {l} {r}\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo) MIT https://github.com/rust-lang/cargo\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --format\")\n        .arg(\"{p} {f}\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo) bar,default,foo\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --all-features --format\")\n        .arg(\"{p} [{f}]\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo) [bar,default,dep,dep_that_is_awesome,foo,other-dep]\n├── dep v1.0.0 []\n├── dep_that_is_awesome v1.0.0 []\n└── other-dep v1.0.0 []\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree\")\n        .arg(\"--features=other-dep,dep_that_is_awesome\")\n        .arg(\"--format={lib}\")\n        .with_stdout_data(str![[r#\"\n\n├── awesome_dep\n└── other_dep\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dev_dep_feature() {\n    // New feature resolver with optional dep\n    Package::new(\"optdep\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(Dependency::new(\"optdep\", \"1.0\").optional(true))\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dev-dependencies]\n            bar = { version = \"1.0\", features = [\"optdep\"] }\n\n            [dependencies]\n            bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Old behavior.\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v1.0.0\n    └── optdep v1.0.0\n[dev-dependencies]\n└── bar v1.0.0 (*)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e normal\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v1.0.0\n    └── optdep v1.0.0\n\n\"#]])\n        .run();\n\n    // New behavior.\n    switch_to_resolver_2(&p);\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v1.0.0\n    └── optdep v1.0.0\n[dev-dependencies]\n└── bar v1.0.0 (*)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e normal\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn host_dep_feature() {\n    // New feature resolver with optional build dep\n    Package::new(\"optdep\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(Dependency::new(\"optdep\", \"1.0\").optional(true))\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [build-dependencies]\n            bar = { version = \"1.0\", features = [\"optdep\"] }\n\n            [dependencies]\n            bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    // Old behavior\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v1.0.0\n    └── optdep v1.0.0\n[build-dependencies]\n└── bar v1.0.0 (*)\n\n\"#]])\n        .run();\n\n    // -p\n    p.cargo(\"tree -p bar\")\n        .with_stdout_data(str![[r#\"\nbar v1.0.0\n└── optdep v1.0.0\n\n\"#]])\n        .run();\n\n    // invert\n    p.cargo(\"tree -i optdep\")\n        .with_stdout_data(str![[r#\"\noptdep v1.0.0\n└── bar v1.0.0\n    └── foo v0.1.0 ([ROOT]/foo)\n    [build-dependencies]\n    └── foo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    // New behavior.\n    switch_to_resolver_2(&p);\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v1.0.0\n[build-dependencies]\n└── bar v1.0.0\n    └── optdep v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -p bar\")\n        .with_stdout_data(str![[r#\"\nbar v1.0.0\n\nbar v1.0.0\n└── optdep v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -i optdep\")\n        .with_stdout_data(str![[r#\"\noptdep v1.0.0\n└── bar v1.0.0\n    [build-dependencies]\n    └── foo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    // Check that -d handles duplicates with features.\n    p.cargo(\"tree -d\")\n        .with_stdout_data(str![[r#\"\nbar v1.0.0\n└── foo v0.1.0 ([ROOT]/foo)\n\nbar v1.0.0\n[build-dependencies]\n└── foo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn proc_macro_features() {\n    // New feature resolver with a proc-macro\n    Package::new(\"optdep\", \"1.0.0\").publish();\n    Package::new(\"somedep\", \"1.0.0\")\n        .add_dep(Dependency::new(\"optdep\", \"1.0\").optional(true))\n        .publish();\n    Package::new(\"pm\", \"1.0.0\")\n        .proc_macro(true)\n        .feature_dep(\"somedep\", \"1.0\", &[\"optdep\"])\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            pm = \"1.0\"\n            somedep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Old behavior\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── pm v1.0.0 (proc-macro)\n│   └── somedep v1.0.0\n│       └── optdep v1.0.0\n└── somedep v1.0.0 (*)\n\n\"#]])\n        .run();\n\n    // Old behavior + no-proc-macro\n    p.cargo(\"tree -e no-proc-macro\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── somedep v1.0.0\n    └── optdep v1.0.0\n\n\"#]])\n        .run();\n\n    // -p\n    p.cargo(\"tree -p somedep\")\n        .with_stdout_data(str![[r#\"\nsomedep v1.0.0\n└── optdep v1.0.0\n\n\"#]])\n        .run();\n\n    // -p -e no-proc-macro\n    p.cargo(\"tree -p somedep -e no-proc-macro\")\n        .with_stdout_data(str![[r#\"\nsomedep v1.0.0\n└── optdep v1.0.0\n\n\"#]])\n        .run();\n\n    // invert\n    p.cargo(\"tree -i somedep\")\n        .with_stdout_data(str![[r#\"\nsomedep v1.0.0\n├── foo v0.1.0 ([ROOT]/foo)\n└── pm v1.0.0 (proc-macro)\n    └── foo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    // invert + no-proc-macro\n    p.cargo(\"tree -i somedep -e no-proc-macro\")\n        .with_stdout_data(str![[r#\"\nsomedep v1.0.0\n└── foo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    // New behavior.\n    switch_to_resolver_2(&p);\n\n    // Note the missing (*)\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── pm v1.0.0 (proc-macro)\n│   └── somedep v1.0.0\n│       └── optdep v1.0.0\n└── somedep v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e no-proc-macro\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── somedep v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -p somedep\")\n        .with_stdout_data(str![[r#\"\nsomedep v1.0.0\n\nsomedep v1.0.0\n└── optdep v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -i somedep\")\n        .with_stdout_data(str![[r#\"\nsomedep v1.0.0\n└── foo v0.1.0 ([ROOT]/foo)\n\nsomedep v1.0.0\n└── pm v1.0.0 (proc-macro)\n    └── foo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -i somedep -e no-proc-macro\")\n        .with_stdout_data(str![[r#\"\nsomedep v1.0.0\n└── foo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn itarget_opt_dep() {\n    // New feature resolver with optional target dep\n    Package::new(\"optdep\", \"1.0.0\").publish();\n    Package::new(\"common\", \"1.0.0\")\n        .add_dep(Dependency::new(\"optdep\", \"1.0\").optional(true))\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n\n            [dependencies]\n            common = \"1.0\"\n\n            [target.'cfg(whatever)'.dependencies]\n            common = { version = \"1.0\", features = [\"optdep\"] }\n\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Old behavior\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n└── common v1.0.0\n    └── optdep v1.0.0\n\n\"#]])\n        .run();\n\n    // New behavior.\n    switch_to_resolver_2(&p);\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n└── common v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ambiguous_name() {\n    // -p that is ambiguous.\n    Package::new(\"dep\", \"1.0.0\").publish();\n    Package::new(\"dep\", \"2.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\").dep(\"dep\", \"2.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            dep = \"1.0\"\n            bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -p dep\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[ADDING] dep v1.0.0 (available: v2.0.0)\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v2.0.0 (registry `dummy-registry`)\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[ERROR] specification `dep` is ambiguous\n[HELP] re-run this command with one of the following specifications\n  dep@1.0.0\n  dep@2.0.0\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn workspace_features_are_local() {\n    // The features for workspace packages should be the same as `cargo build`\n    // (i.e., the features selected depend on the \"current\" package).\n    Package::new(\"optdep\", \"1.0.0\").publish();\n    Package::new(\"somedep\", \"1.0.0\")\n        .add_dep(Dependency::new(\"optdep\", \"1.0\").optional(true))\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            somedep = {version=\"1.0\", features=[\"optdep\"]}\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            somedep = \"1.0\"\n\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\na v0.1.0 ([ROOT]/foo/a)\n└── somedep v1.0.0\n    └── optdep v1.0.0\n\nb v0.1.0 ([ROOT]/foo/b)\n└── somedep v1.0.0 (*)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -p a\")\n        .with_stdout_data(str![[r#\"\na v0.1.0 ([ROOT]/foo/a)\n└── somedep v1.0.0\n    └── optdep v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -p b\")\n        .with_stdout_data(str![[r#\"\nb v0.1.0 ([ROOT]/foo/b)\n└── somedep v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unknown_edge_kind() {\n    let p = project()\n        .file(\"Cargo.toml\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e unknown\")\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid value 'unknown' for '--edges <KINDS>'\n  [possible values: all, normal, build, dev, features, public, no-normal, no-build, no-dev, no-proc-macro]\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn mixed_no_edge_kinds() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e no-build,normal\")\n        .with_stderr_data(str![[r#\"\n[ERROR] `normal` dependency kind cannot be mixed with \"no-normal\", \"no-build\", or \"no-dev\" dependency kinds\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    // `no-proc-macro` can be mixed with others\n    p.cargo(\"tree -e no-proc-macro,normal\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn depth_limit() {\n    let p = make_simple_proj();\n\n    p.cargo(\"tree --depth 0\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n[build-dependencies]\n[dev-dependencies]\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --depth 1\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── a v1.0.0\n└── c v1.0.0\n[build-dependencies]\n└── bdep v1.0.0\n[dev-dependencies]\n└── devdep v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --depth 2\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── a v1.0.0\n│   └── b v1.0.0\n└── c v1.0.0\n[build-dependencies]\n└── bdep v1.0.0\n    └── b v1.0.0 (*)\n[dev-dependencies]\n└── devdep v1.0.0\n    └── b v1.0.0 (*)\n\n\"#]])\n        .run();\n\n    // specify a package\n    p.cargo(\"tree -p bdep --depth 1\")\n        .with_stdout_data(str![[r#\"\nbdep v1.0.0\n└── b v1.0.0\n\n\"#]])\n        .run();\n\n    // different prefix\n    p.cargo(\"tree --depth 1 --prefix depth\")\n        .with_stdout_data(str![[r#\"\n0foo v0.1.0 ([ROOT]/foo)\n1a v1.0.0\n1c v1.0.0\n1bdep v1.0.0\n1devdep v1.0.0\n\n\"#]])\n        .run();\n\n    // with edge-kinds\n    p.cargo(\"tree --depth 1 -e no-dev\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── a v1.0.0\n└── c v1.0.0\n[build-dependencies]\n└── bdep v1.0.0\n\n\"#]])\n        .run();\n\n    // invert\n    p.cargo(\"tree --depth 1 --invert c\")\n        .with_stdout_data(str![[r#\"\nc v1.0.0\n├── b v1.0.0\n└── foo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn depth_workspace() {\n    Package::new(\"somedep\", \"1.0.0\").publish();\n    Package::new(\"otherdep\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\", \"c\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"1.0.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            c = { path = \"../c\" }\n            somedep = \"1\"\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"c/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"c\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            somedep = \"1\"\n            otherdep = \"1\"\n            \"#,\n        )\n        .file(\"c/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree --depth workspace\")\n        .with_stdout_data(str![[r#\"\na v1.0.0 ([ROOT]/foo/a)\n\nb v0.1.0 ([ROOT]/foo/b)\n└── c v0.1.0 ([ROOT]/foo/c)\n\nc v0.1.0 ([ROOT]/foo/c) (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn edge_public() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"diamond\", \"left-pub\", \"right-priv\", \"dep\"]\n            \"#,\n        )\n        .file(\n            \"diamond/Cargo.toml\",\n            r#\"\n            cargo-features = [\"public-dependency\"]\n\n            [package]\n            name = \"diamond\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            left-pub = { path = \"../left-pub\", public = true }\n            right-priv = { path = \"../right-priv\", public = true }\n            \"#,\n        )\n        .file(\"diamond/src/lib.rs\", \"\")\n        .file(\n            \"left-pub/Cargo.toml\",\n            r#\"\n            cargo-features = [\"public-dependency\"]\n\n            [package]\n            name = \"left-pub\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            dep = { path = \"../dep\", public = true }\n            \"#,\n        )\n        .file(\"left-pub/src/lib.rs\", \"\")\n        .file(\n            \"right-priv/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"right-priv\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            dep = { path = \"../dep\" }\n            \"#,\n        )\n        .file(\"right-priv/src/lib.rs\", \"\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree --edges public\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\", \"edge-public\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `--edges public` requires `-Zunstable-options`\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --edges public -p left-pub\")\n        .arg(\"-Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\", \"edge-public\"])\n        .with_stdout_data(str![[r#\"\nleft-pub v0.1.0 ([ROOT]/foo/left-pub)\n└── dep v0.1.0 ([ROOT]/foo/dep)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --edges public -p right-priv\")\n        .arg(\"-Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\", \"edge-public\"])\n        .with_stdout_data(str![[r#\"\nright-priv v0.1.0 ([ROOT]/foo/right-priv)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --edges public -p diamond\")\n        .arg(\"-Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\", \"edge-public\"])\n        .with_stdout_data(str![[r#\"\ndiamond v0.1.0 ([ROOT]/foo/diamond)\n├── left-pub v0.1.0 ([ROOT]/foo/left-pub)\n│   └── dep v0.1.0 ([ROOT]/foo/dep)\n└── right-priv v0.1.0 ([ROOT]/foo/right-priv)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --edges public\")\n        .arg(\"-Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\", \"edge-public\"])\n        .with_stdout_data(str![[r#\"\ndep v0.1.0 ([ROOT]/foo/dep)\n\ndiamond v0.1.0 ([ROOT]/foo/diamond)\n├── left-pub v0.1.0 ([ROOT]/foo/left-pub)\n│   └── dep v0.1.0 ([ROOT]/foo/dep)\n└── right-priv v0.1.0 ([ROOT]/foo/right-priv)\n\nleft-pub v0.1.0 ([ROOT]/foo/left-pub) (*)\n\nright-priv v0.1.0 ([ROOT]/foo/right-priv)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --edges public --invert dep\")\n        .arg(\"-Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\", \"edge-public\"])\n        .with_stdout_data(str![[r#\"\ndep v0.1.0 ([ROOT]/foo/dep)\n└── left-pub v0.1.0 ([ROOT]/foo/left-pub)\n    └── diamond v0.1.0 ([ROOT]/foo/diamond)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn prune() {\n    let p = make_simple_proj();\n\n    p.cargo(\"tree --prune c\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── a v1.0.0\n    └── b v1.0.0\n[build-dependencies]\n└── bdep v1.0.0\n    └── b v1.0.0 (*)\n[dev-dependencies]\n└── devdep v1.0.0\n    └── b v1.0.0 (*)\n\n\"#]])\n        .run();\n\n    // multiple prune\n    p.cargo(\"tree --prune c --prune bdep\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── a v1.0.0\n    └── b v1.0.0\n[build-dependencies]\n[dev-dependencies]\n└── devdep v1.0.0\n    └── b v1.0.0 (*)\n\n\"#]])\n        .run();\n\n    // with edge-kinds\n    p.cargo(\"tree --prune c -e normal\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── a v1.0.0\n    └── b v1.0.0\n\n\"#]])\n        .run();\n\n    // pruning self does not works\n    p.cargo(\"tree --prune foo\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── a v1.0.0\n│   └── b v1.0.0\n│       └── c v1.0.0\n└── c v1.0.0\n[build-dependencies]\n└── bdep v1.0.0\n    └── b v1.0.0 (*)\n[dev-dependencies]\n└── devdep v1.0.0\n    └── b v1.0.0 (*)\n\n\"#]])\n        .run();\n\n    // dep not exist\n    p.cargo(\"tree --prune no-dep\")\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `no-dep` did not match any packages\n\n[HELP] a package with a similar name exists: `bdep`\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn cyclic_features() {\n    // Check for stack overflow with cyclic features (oops!).\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n\n                [features]\n                a = [\"b\"]\n                b = [\"a\"]\n                default = [\"a\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e features\")\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features -i foo\")\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n├── foo feature \"a\"\n│   ├── foo feature \"b\"\n│   │   └── foo feature \"a\" (*)\n│   └── foo feature \"default\" (command-line)\n├── foo feature \"b\" (*)\n└── foo feature \"default\" (command-line)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dev_dep_cycle_with_feature() {\n    // Cycle with features and a dev-dependency.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n\n                [dev-dependencies]\n                bar = { path = \"bar\" }\n\n                [features]\n                a = [\"bar/feat1\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"1.0.0\"\n\n                [dependencies]\n                foo = { path = \"..\" }\n\n                [features]\n                feat1 = [\"foo/a\"]\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e features --features a\")\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n[dev-dependencies]\n└── bar feature \"default\"\n    └── bar v1.0.0 ([ROOT]/foo/bar)\n        └── foo feature \"default\" (command-line)\n            └── foo v1.0.0 ([ROOT]/foo) (*)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --features a -i foo\")\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n├── foo feature \"a\" (command-line)\n│   └── bar feature \"feat1\"\n│       └── foo feature \"a\" (command-line) (*)\n└── foo feature \"default\" (command-line)\n    └── bar v1.0.0 ([ROOT]/foo/bar)\n        ├── bar feature \"default\"\n        │   [dev-dependencies]\n        │   └── foo v1.0.0 ([ROOT]/foo) (*)\n        └── bar feature \"feat1\" (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dev_dep_cycle_with_feature_nested() {\n    // Checks for an issue where a cyclic dev dependency tries to activate a\n    // feature on its parent that tries to activate the feature back on the\n    // dev-dependency.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n\n                [dev-dependencies]\n                bar = { path = \"bar\" }\n\n                [features]\n                a = [\"bar/feat1\"]\n                b = [\"a\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"1.0.0\"\n\n                [dependencies]\n                foo = { path = \"..\" }\n\n                [features]\n                feat1 = [\"foo/b\"]\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e features\")\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n[dev-dependencies]\n└── bar feature \"default\"\n    └── bar v1.0.0 ([ROOT]/foo/bar)\n        └── foo feature \"default\" (command-line)\n            └── foo v1.0.0 ([ROOT]/foo) (*)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --features a -i foo\")\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n├── foo feature \"a\" (command-line)\n│   └── foo feature \"b\"\n│       └── bar feature \"feat1\"\n│           └── foo feature \"a\" (command-line) (*)\n├── foo feature \"b\" (*)\n└── foo feature \"default\" (command-line)\n    └── bar v1.0.0 ([ROOT]/foo/bar)\n        ├── bar feature \"default\"\n        │   [dev-dependencies]\n        │   └── foo v1.0.0 ([ROOT]/foo) (*)\n        └── bar feature \"feat1\" (*)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --features b -i foo\")\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n├── foo feature \"a\"\n│   └── foo feature \"b\" (command-line)\n│       └── bar feature \"feat1\"\n│           └── foo feature \"a\" (*)\n├── foo feature \"b\" (command-line) (*)\n└── foo feature \"default\" (command-line)\n    └── bar v1.0.0 ([ROOT]/foo/bar)\n        ├── bar feature \"default\"\n        │   [dev-dependencies]\n        │   └── foo v1.0.0 ([ROOT]/foo) (*)\n        └── bar feature \"feat1\" (*)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --features bar/feat1 -i foo\")\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n├── foo feature \"a\"\n│   └── foo feature \"b\"\n│       └── bar feature \"feat1\" (command-line)\n│           └── foo feature \"a\" (*)\n├── foo feature \"b\" (*)\n└── foo feature \"default\" (command-line)\n    └── bar v1.0.0 ([ROOT]/foo/bar)\n        ├── bar feature \"default\"\n        │   [dev-dependencies]\n        │   └── foo v1.0.0 ([ROOT]/foo) (*)\n        └── bar feature \"feat1\" (command-line) (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_proc_macro_order() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n    Package::new(\"pm\", \"1.0.0\").proc_macro(true).publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            pm = \"1.0\"\n            dep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── dep v1.0.0\n└── pm v1.0.0 (proc-macro)\n\n\"#]])\n        .run();\n\n    // no-proc-macro combined with other edge kinds\n    p.cargo(\"tree -e normal,no-proc-macro\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── dep v1.0.0\n\n\"#]])\n        .run();\n\n    // change flag order, expecting the same output\n    p.cargo(\"tree -e no-proc-macro,normal\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── dep v1.0.0\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_tree/dupe/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    Package::new(\"a\", \"1.0.0\").dep(\"b\", \"1.0\").publish();\n    Package::new(\"b\", \"1.0.0\").dep(\"c\", \"1.0\").publish();\n    Package::new(\"c\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            a = \"1.0\"\n            b = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"tree\")\n        .current_dir(p.root())\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n\n#[cargo_test]\nfn all_flag() {\n    Package::new(\"a\", \"1.0.0\").dep(\"b\", \"1.0\").publish();\n    Package::new(\"b\", \"1.0.0\").dep(\"c\", \"1.0\").publish();\n    Package::new(\"c\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            a = \"1.0\"\n            b = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"tree --all\").with_stderr_data(str![[r#\"\n[WARNING] the `cargo tree` --all flag has been changed to --no-dedupe, and may be removed in a future version\n  |\n  = [HELP] if you are looking to display all workspace members, use the --workspace flag\n...\n\"#]]).run();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_tree/edge_kind/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\n\n#[cargo_test]\nfn case() {\n    Package::new(\"normal_a\", \"1.0.0\")\n        .dep(\"normal_b\", \"1.0\")\n        .publish();\n    Package::new(\"normal_b\", \"1.0.0\")\n        .dep(\"normal_c\", \"1.0\")\n        .build_dep(\"normal_b_build_a\", \"1.0.0\")\n        .dev_dep(\"normal_b_dev_a\", \"1.0.0\")\n        .publish();\n    Package::new(\"normal_c\", \"1.0.0\").publish();\n    Package::new(\"normal_b_build_a\", \"1.0.0\")\n        .dep(\"normal_b_build_a_normal_a\", \"1.0.0\")\n        .publish();\n    Package::new(\"normal_b_build_a_normal_a\", \"1.0.0\").publish();\n    Package::new(\"normal_b_dev_a\", \"1.0.0\")\n        .dep(\"normal_b_dev_a_normal_a\", \"1.0.0\")\n        .publish();\n    Package::new(\"normal_b_dev_a_normal_a\", \"1.0.0\").publish();\n    Package::new(\"normal_d\", \"1.0.0\").publish();\n\n    Package::new(\"build_a\", \"1.0.0\")\n        .dep(\"build_b\", \"1.0\")\n        .publish();\n    Package::new(\"build_b\", \"1.0.0\")\n        .dep(\"build_c\", \"1.0\")\n        .build_dep(\"build_b_build_a\", \"1.0.0\")\n        .dev_dep(\"build_b_dev_a\", \"1.0.0\")\n        .publish();\n    Package::new(\"build_c\", \"1.0.0\").publish();\n    Package::new(\"build_b_build_a\", \"1.0.0\")\n        .dep(\"build_b_build_a_normal_a\", \"1.0.0\")\n        .publish();\n    Package::new(\"build_b_build_a_normal_a\", \"1.0.0\").publish();\n    Package::new(\"build_b_dev_a\", \"1.0.0\")\n        .dep(\"build_b_dev_a_normal_a\", \"1.0.0\")\n        .publish();\n    Package::new(\"build_b_dev_a_normal_a\", \"1.0.0\").publish();\n    Package::new(\"build_d\", \"1.0.0\").publish();\n\n    Package::new(\"dev_a\", \"1.0.0\").dep(\"dev_b\", \"1.0\").publish();\n    Package::new(\"dev_b\", \"1.0.0\")\n        .dep(\"dev_c\", \"1.0\")\n        .build_dep(\"dev_b_build_a\", \"1.0.0\")\n        .dev_dep(\"dev_b_dev_a\", \"1.0.0\")\n        .publish();\n    Package::new(\"dev_c\", \"1.0.0\").publish();\n    Package::new(\"dev_b_build_a\", \"1.0.0\")\n        .dep(\"dev_b_build_a_normal_a\", \"1.0.0\")\n        .publish();\n    Package::new(\"dev_b_build_a_normal_a\", \"1.0.0\").publish();\n    Package::new(\"dev_b_dev_a\", \"1.0.0\")\n        .dep(\"dev_b_dev_a_normal_a\", \"1.0.0\")\n        .publish();\n    Package::new(\"dev_b_dev_a_normal_a\", \"1.0.0\").publish();\n    Package::new(\"dev_d\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [features]\n            default = [\"foo\"]\n            foo = [\"dep:normal_a\"]\n\n            [dependencies]\n            normal_a = { version = \"1.0\", optional = true }\n            normal_d = \"1.0\"\n\n            [build-dependencies]\n            build_a = \"1.0\"\n            build_d = \"1.0\"\n\n            [dev-dependencies]\n            dev_a = \"1.0\"\n            dev_d = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"tree\")\n        .arg(\"--edges=features\")\n        .current_dir(p.root())\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_tree/features.rs",
    "content": "//! Tests for the `cargo tree` command with -e features option.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::{Dependency, Package};\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn dep_feature_various() {\n    // Checks different ways of setting features via dependencies.\n    Package::new(\"optdep\", \"1.0.0\")\n        .feature(\"default\", &[\"cat\"])\n        .feature(\"cat\", &[])\n        .publish();\n    Package::new(\"defaultdep\", \"1.0.0\")\n        .feature(\"default\", &[\"f1\"])\n        .feature(\"f1\", &[\"optdep\"])\n        .add_dep(Dependency::new(\"optdep\", \"1.0\").optional(true))\n        .publish();\n    Package::new(\"nodefaultdep\", \"1.0.0\")\n        .feature(\"default\", &[\"f1\"])\n        .feature(\"f1\", &[])\n        .publish();\n    Package::new(\"nameddep\", \"1.0.0\")\n        .add_dep(Dependency::new(\"serde\", \"1.0\").optional(true))\n        .feature(\"default\", &[\"serde-stuff\"])\n        .feature(\"serde-stuff\", &[\"serde/derive\"])\n        .feature(\"vehicle\", &[\"car\"])\n        .feature(\"car\", &[])\n        .publish();\n    Package::new(\"serde_derive\", \"1.0.0\").publish();\n    Package::new(\"serde\", \"1.0.0\")\n        .feature(\"derive\", &[\"serde_derive\"])\n        .add_dep(Dependency::new(\"serde_derive\", \"1.0\").optional(true))\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            defaultdep = \"1.0\"\n            nodefaultdep = {version=\"1.0\", default-features = false}\n            nameddep = {version=\"1.0\", features = [\"vehicle\", \"serde\"]}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e features\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── nodefaultdep v1.0.0\n├── defaultdep feature \"default\"\n│   ├── defaultdep v1.0.0\n│   │   └── optdep feature \"default\"\n│   │       ├── optdep v1.0.0\n│   │       └── optdep feature \"cat\"\n│   │           └── optdep v1.0.0\n│   └── defaultdep feature \"f1\"\n│       ├── defaultdep v1.0.0 (*)\n│       └── defaultdep feature \"optdep\"\n│           └── defaultdep v1.0.0 (*)\n├── nameddep feature \"default\"\n│   ├── nameddep v1.0.0\n│   │   └── serde feature \"default\"\n│   │       └── serde v1.0.0\n│   │           └── serde_derive feature \"default\"\n│   │               └── serde_derive v1.0.0\n│   └── nameddep feature \"serde-stuff\"\n│       ├── nameddep v1.0.0 (*)\n│       ├── nameddep feature \"serde\"\n│       │   └── nameddep v1.0.0 (*)\n│       └── serde feature \"derive\"\n│           ├── serde v1.0.0 (*)\n│           └── serde feature \"serde_derive\"\n│               └── serde v1.0.0 (*)\n├── nameddep feature \"serde\" (*)\n└── nameddep feature \"vehicle\"\n    ├── nameddep v1.0.0 (*)\n    └── nameddep feature \"car\"\n        └── nameddep v1.0.0 (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn graph_features_ws_interdependent() {\n    // A workspace with interdependent crates.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            b = {path=\"../b\", features=[\"feat2\"]}\n\n            [features]\n            default = [\"a1\"]\n            a1 = []\n            a2 = []\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.1.0\"\n\n            [features]\n            default = [\"feat1\"]\n            feat1 = []\n            feat2 = []\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e features\")\n        .with_stdout_data(str![[r#\"\na v0.1.0 ([ROOT]/foo/a)\n├── b feature \"default\" (command-line)\n│   ├── b v0.1.0 ([ROOT]/foo/b)\n│   └── b feature \"feat1\"\n│       └── b v0.1.0 ([ROOT]/foo/b)\n└── b feature \"feat2\"\n    └── b v0.1.0 ([ROOT]/foo/b)\n\nb v0.1.0 ([ROOT]/foo/b)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features -i a -i b\")\n        .with_stdout_data(str![[r#\"\na v0.1.0 ([ROOT]/foo/a)\n├── a feature \"a1\"\n│   └── a feature \"default\" (command-line)\n└── a feature \"default\" (command-line)\n\nb v0.1.0 ([ROOT]/foo/b)\n├── b feature \"default\" (command-line)\n│   └── a v0.1.0 ([ROOT]/foo/a) (*)\n├── b feature \"feat1\"\n│   └── b feature \"default\" (command-line) (*)\n└── b feature \"feat2\"\n    └── a v0.1.0 ([ROOT]/foo/a) (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn slash_feature_name() {\n    // dep_name/feat_name syntax\n    Package::new(\"opt\", \"1.0.0\").feature(\"feat1\", &[]).publish();\n    Package::new(\"notopt\", \"1.0.0\")\n        .feature(\"cat\", &[])\n        .feature(\"animal\", &[\"cat\"])\n        .publish();\n    Package::new(\"opt2\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            opt = {version = \"1.0\", optional=true}\n            opt2 = {version = \"1.0\", optional=true}\n            notopt = \"1.0\"\n\n            [features]\n            f1 = [\"opt/feat1\", \"notopt/animal\"]\n            f2 = [\"f1\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e features --features f1\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── notopt feature \"default\"\n│   └── notopt v1.0.0\n└── opt feature \"default\"\n    └── opt v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --features f1 -i foo\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── foo feature \"default\" (command-line)\n├── foo feature \"f1\" (command-line)\n└── foo feature \"opt\"\n    └── foo feature \"f1\" (command-line)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --features f1 -i notopt\")\n        .with_stdout_data(str![[r#\"\nnotopt v1.0.0\n├── notopt feature \"animal\"\n│   └── foo feature \"f1\" (command-line)\n├── notopt feature \"cat\"\n│   └── notopt feature \"animal\" (*)\n└── notopt feature \"default\"\n    └── foo v0.1.0 ([ROOT]/foo)\n        ├── foo feature \"default\" (command-line)\n        ├── foo feature \"f1\" (command-line)\n        └── foo feature \"opt\"\n            └── foo feature \"f1\" (command-line)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --features notopt/animal -i notopt\")\n        .with_stdout_data(str![[r#\"\nnotopt v1.0.0\n├── notopt feature \"animal\" (command-line)\n├── notopt feature \"cat\"\n│   └── notopt feature \"animal\" (command-line)\n└── notopt feature \"default\"\n    └── foo v0.1.0 ([ROOT]/foo)\n        └── foo feature \"default\" (command-line)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --all-features\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── notopt feature \"default\"\n│   └── notopt v1.0.0\n├── opt feature \"default\"\n│   └── opt v1.0.0\n└── opt2 feature \"default\"\n    └── opt2 v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --all-features -i opt2\")\n        .with_stdout_data(str![[r#\"\nopt2 v1.0.0\n└── opt2 feature \"default\"\n    └── foo v0.1.0 ([ROOT]/foo)\n        ├── foo feature \"default\" (command-line)\n        ├── foo feature \"f1\" (command-line)\n        │   └── foo feature \"f2\" (command-line)\n        ├── foo feature \"f2\" (command-line)\n        ├── foo feature \"opt\" (command-line)\n        │   └── foo feature \"f1\" (command-line) (*)\n        └── foo feature \"opt2\" (command-line)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn features_enables_inactive_target() {\n    // Features that enable things on targets that are not enabled.\n    Package::new(\"optdep\", \"1.0.0\")\n        .feature(\"feat1\", &[])\n        .publish();\n    Package::new(\"dep1\", \"1.0.0\")\n        .feature(\"somefeat\", &[])\n        .publish();\n    Package::new(\"dep2\", \"1.0.0\")\n        .add_dep(\n            Dependency::new(\"optdep\", \"1.0.0\")\n                .optional(true)\n                .target(\"cfg(whatever)\"),\n        )\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [target.'cfg(whatever)'.dependencies]\n            optdep = {version=\"1.0\", optional=true}\n            dep1 = \"1.0\"\n\n            [dependencies]\n            dep2 = \"1.0\"\n\n            [features]\n            f1 = [\"optdep\"]\n            f2 = [\"optdep/feat1\"]\n            f3 = [\"dep1/somefeat\"]\n            f4 = [\"dep2/optdep\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"tree -e features\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── dep2 feature \"default\"\n    └── dep2 v1.0.0\n\n\"#]])\n        .run();\n    p.cargo(\"tree -e features --all-features\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── dep2 feature \"default\"\n    └── dep2 v1.0.0\n\n\"#]])\n        .run();\n    p.cargo(\"tree -e features --all-features --target=all\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── dep1 feature \"default\"\n│   └── dep1 v1.0.0\n├── dep2 feature \"default\"\n│   └── dep2 v1.0.0\n│       └── optdep feature \"default\"\n│           └── optdep v1.0.0\n└── optdep feature \"default\" (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn edge_public_no_features() {\n    Package::new(\"pub-defaultdep\", \"1.0.0\").publish();\n    Package::new(\"priv-defaultdep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            cargo-features = [\"public-dependency\"]\n\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            pub-defaultdep = { version = \"1.0.0\", public = true }\n            priv-defaultdep = \"1.0.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e features --edges public\")\n        .arg(\"-Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\", \"edge-public\"])\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── pub-defaultdep feature \"default\"\n    └── pub-defaultdep v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn edge_public_transitive_features() {\n    Package::new(\"pub-defaultdep\", \"1.0.0\")\n        .feature(\"default\", &[\"f1\"])\n        .feature(\"f1\", &[\"f2\"])\n        .feature(\"f2\", &[\"optdep\"])\n        .add_dep(Dependency::new(\"optdep\", \"1.0\").optional(true).public(true))\n        .publish();\n    Package::new(\"priv-defaultdep\", \"1.0.0\")\n        .feature(\"default\", &[\"f1\"])\n        .feature(\"f1\", &[\"f2\"])\n        .feature(\"f2\", &[\"optdep\"])\n        .add_dep(Dependency::new(\"optdep\", \"1.0\").optional(true))\n        .publish();\n    Package::new(\"optdep\", \"1.0.0\")\n        .feature(\"default\", &[\"f\"])\n        .feature(\"f\", &[])\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            cargo-features = [\"public-dependency\"]\n\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            pub-defaultdep = { version = \"1.0.0\", public = true }\n            priv-defaultdep = { version = \"1.0.0\", public = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e features --edges public\")\n        .arg(\"-Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\", \"edge-public\"])\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── priv-defaultdep feature \"default\"\n│   ├── priv-defaultdep v1.0.0\n│   └── priv-defaultdep feature \"f1\"\n│       ├── priv-defaultdep v1.0.0\n│       └── priv-defaultdep feature \"f2\"\n│           ├── priv-defaultdep v1.0.0\n│           └── priv-defaultdep feature \"optdep\"\n│               └── priv-defaultdep v1.0.0\n└── pub-defaultdep feature \"default\"\n    ├── pub-defaultdep v1.0.0\n    │   └── optdep feature \"default\"\n    │       ├── optdep v1.0.0\n    │       └── optdep feature \"f\"\n    │           └── optdep v1.0.0\n    └── pub-defaultdep feature \"f1\"\n        ├── pub-defaultdep v1.0.0 (*)\n        └── pub-defaultdep feature \"f2\"\n            ├── pub-defaultdep v1.0.0 (*)\n            └── pub-defaultdep feature \"optdep\"\n                └── pub-defaultdep v1.0.0 (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn edge_public_cli() {\n    Package::new(\"priv\", \"1.0.0\").feature(\"f\", &[]).publish();\n    Package::new(\"pub\", \"1.0.0\").feature(\"f\", &[]).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            cargo-features = [\"public-dependency\"]\n\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [features]\n            priv-indirect = [\"priv\"]\n            priv = [\"dep:priv\", \"priv?/f\"]\n            pub-indirect = [\"pub\"]\n            pub = [\"dep:pub\", \"priv?/f\"]\n\n            [dependencies]\n            priv = { version = \"1.0.0\", optional = true }\n            pub = { version = \"1.0.0\", optional = true, public = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e features --edges public\")\n        .arg(\"-Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\", \"edge-public\"])\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --edges public --features pub-indirect\")\n        .arg(\"-Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\", \"edge-public\"])\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── pub feature \"default\"\n    └── pub v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --edges public --features priv-indirect\")\n        .arg(\"-Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\", \"edge-public\"])\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_tree/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"tree\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_tree/mod.rs",
    "content": "mod deps;\nmod dupe;\nmod edge_kind;\nmod features;\nmod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_uninstall/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"uninstall\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_uninstall/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_update/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"update\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_update/mod.rs",
    "content": "mod help;\nmod toolchain_pkgname;\n"
  },
  {
    "path": "tests/testsuite/cargo_update/toolchain_pkgname/in/Cargo.toml",
    "content": "[package]\nname = \"test\"\nversion = \"0.1.0\"\nedition = \"2015\"\n\n[dependencies]\n"
  },
  {
    "path": "tests/testsuite/cargo_update/toolchain_pkgname/in/src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_update/toolchain_pkgname/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::Project;\nuse cargo_test_support::current_dir;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    let project = Project::from_template(current_dir!().join(\"in\"));\n    let project_root = project.root();\n    let cwd = &project_root;\n\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"update\")\n        .arg(\"+stable\")\n        .current_dir(cwd)\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_vendor/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"vendor\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_vendor/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_verify_project/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"verify-project\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_verify_project/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_version/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"version\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_version/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cargo_yank/help/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::file;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn case() {\n    snapbox::cmd::Command::cargo_ui()\n        .arg(\"yank\")\n        .arg(\"--help\")\n        .assert()\n        .success()\n        .stdout_eq(file![\"stdout.term.svg\"])\n        .stderr_eq(str![\"\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/cargo_yank/mod.rs",
    "content": "mod help;\n"
  },
  {
    "path": "tests/testsuite/cfg.rs",
    "content": "//! Tests for `cfg()` expressions.\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::rustc_host;\nuse cargo_test_support::{basic_manifest, project, str};\n\n#[cargo_test]\nfn cfg_easy() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'cfg(unix)'.dependencies]\n                b = { path = 'b' }\n                [target.\"cfg(windows)\".dependencies]\n                b = { path = 'b' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate b;\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn dont_include() {\n    let other_family = if cfg!(unix) { \"windows\" } else { \"unix\" };\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"a\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [target.'cfg({})'.dependencies]\n                    b = {{ path = 'b' }}\n                \"#,\n                other_family\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn works_through_the_registry() {\n    Package::new(\"baz\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.0\")\n        .target_dep(\"baz\", \"0.1.0\", \"cfg(unix)\")\n        .target_dep(\"baz\", \"0.1.0\", \"cfg(windows)\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"#[allow(unused_extern_crates)] extern crate bar;\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] baz v0.1.0\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ignore_version_from_other_platform() {\n    let this_family = if cfg!(unix) { \"unix\" } else { \"windows\" };\n    let other_family = if cfg!(unix) { \"windows\" } else { \"unix\" };\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [target.'cfg({})'.dependencies]\n                    bar = \"0.1.0\"\n\n                    [target.'cfg({})'.dependencies]\n                    bar = \"0.2.0\"\n                \"#,\n                this_family, other_family\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"#[allow(unused_extern_crates)] extern crate bar;\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[ADDING] bar v0.1.0 (available: v0.2.0)\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_target_spec() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'cfg(4)'.dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  failed to parse `4` as a cfg expression: unexpected character `4` in cfg, expected parens, a comma, an identifier, or a string\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_target_spec2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'cfg(bar =)'.dependencies]\n                baz = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  failed to parse `bar =` as a cfg expression: expected a string, but cfg expression ended\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_match_ok() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"a\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [target.'cfg(unix)'.dependencies]\n                    b = {{ path = 'b' }}\n                    [target.'cfg(target_family = \"unix\")'.dependencies]\n                    b = {{ path = 'b' }}\n                    [target.\"cfg(windows)\".dependencies]\n                    b = {{ path = 'b' }}\n                    [target.'cfg(target_family = \"windows\")'.dependencies]\n                    b = {{ path = 'b' }}\n                    [target.\"cfg(any(windows, unix))\".dependencies]\n                    b = {{ path = 'b' }}\n\n                    [target.{}.dependencies]\n                    b = {{ path = 'b' }}\n                \"#,\n                rustc_host()\n            ),\n        )\n        .file(\"src/lib.rs\", \"extern crate b;\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn any_ok() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.\"cfg(any(windows, unix))\".dependencies]\n                b = { path = 'b' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate b;\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check -v\").run();\n}\n\n// https://github.com/rust-lang/cargo/issues/5313\n#[cargo_test]\n#[cfg(all(target_arch = \"x86_64\", target_os = \"linux\", target_env = \"gnu\"))]\nfn cfg_looks_at_rustflags_for_target() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'cfg(with_b)'.dependencies]\n                b = { path = 'b' }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[cfg(with_b)]\n                extern crate b;\n\n                fn main() { b::foo(); }\n            \"#,\n        )\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"check --target x86_64-unknown-linux-gnu\")\n        .env(\"RUSTFLAGS\", \"--cfg with_b\")\n        .run();\n}\n\n#[cargo_test]\nfn bad_cfg_discovery() {\n    // Check error messages when `rustc -v` and `rustc --print=*` parsing fails.\n    //\n    // This is a `rustc` replacement which behaves differently based on an\n    // environment variable.\n    let p = project()\n        .at(\"compiler\")\n        .file(\"Cargo.toml\", &basic_manifest(\"compiler\", \"0.1.0\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn run_rustc() -> String {\n                let mut cmd = std::process::Command::new(\"rustc\");\n                for arg in std::env::args_os().skip(1) {\n                    cmd.arg(arg);\n                }\n                String::from_utf8(cmd.output().unwrap().stdout).unwrap()\n            }\n\n            fn main() {\n                let mode = std::env::var(\"FUNKY_MODE\").unwrap();\n                if mode == \"bad-version\" {\n                    println!(\"foo\");\n                    return;\n                }\n                if std::env::args_os().any(|a| a == \"-vV\") {\n                    print!(\"{}\", run_rustc());\n                    return;\n                }\n                if mode == \"no-crate-types\" {\n                    return;\n                }\n                if mode == \"bad-crate-type\" {\n                    println!(\"foo\");\n                    return;\n                }\n                let output = run_rustc();\n                let mut lines = output.lines();\n                let sysroot = loop {\n                    let line = lines.next().unwrap();\n                    if line.contains(\"___\") {\n                        println!(\"{}\", line);\n                    } else {\n                        break line;\n                    }\n                };\n                if mode == \"no-sysroot\" {\n                    return;\n                }\n                println!(\"{}\", sysroot);\n\n                if mode == \"no-split-debuginfo\" {\n                    return;\n                }\n                loop {\n                    let line = lines.next().unwrap();\n                    if line == \"___\" {\n                        println!(\"\\n{line}\");\n                        break;\n                    } else {\n                        // As the number split-debuginfo options varies,\n                        // concat them into one line.\n                        print!(\"{line},\");\n                    }\n                };\n\n                if mode != \"bad-cfg\" {\n                    panic!(\"unexpected\");\n                }\n                println!(\"123\");\n            }\n            \"#,\n        )\n        .build();\n    p.cargo(\"build\").run();\n    let funky_rustc = p.bin(\"compiler\");\n\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"check\")\n        .env(\"RUSTC\", &funky_rustc)\n        .env(\"FUNKY_MODE\", \"bad-version\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `rustc -vV` didn't have a line for `host:`, got:\nfoo\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .env(\"RUSTC\", &funky_rustc)\n        .env(\"FUNKY_MODE\", \"no-crate-types\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] malformed output when learning about crate-type bin information\ncommand was: `[ROOT]/compiler/target/debug/compiler[..] --crate-name ___ [..]`\n(no output received)\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .env(\"RUSTC\", &funky_rustc)\n        .env(\"FUNKY_MODE\", \"no-sysroot\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] output of --print=sysroot missing when learning about target-specific information from rustc\ncommand was: `[ROOT]/compiler/target/debug/compiler[..]--crate-type [..]`\n\n--- stdout\n___[EXE]\nlib___.rlib\n[..]___.[..]\n[..]___.[..]\n[..]___.[..]\n[..]___.[..]\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .env(\"RUSTC\", &funky_rustc)\n        .env(\"FUNKY_MODE\", \"no-split-debuginfo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] output of --print=split-debuginfo missing when learning about target-specific information from rustc\ncommand was: `[ROOT]/compiler/target/debug/compiler[..]--crate-type [..]`\n\n--- stdout\n___[EXE]\nlib___.rlib\n[..]___.[..]\n[..]___.[..]\n[..]___.[..]\n[..]___.[..]\n[..]\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .env(\"RUSTC\", &funky_rustc)\n        .env(\"FUNKY_MODE\", \"bad-cfg\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse the cfg from `rustc --print=cfg`, got:\n___[EXE]\nlib___.rlib\n[..]___.[..]\n[..]___.[..]\n[..]___.[..]\n[..]___.[..]\n[..]\n[..],[..]\n___\n123\n\n\nCaused by:\n  failed to parse `123` as a cfg expression: unexpected character `1` in cfg, expected parens, a comma, an identifier, or a string\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn exclusive_dep_kinds() {\n    // Checks for a bug where the same package with different cfg expressions\n    // was not being filtered correctly.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [target.'cfg(abc)'.dependencies]\n                bar = \"1.0\"\n\n                [target.'cfg(not(abc))'.build-dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"extern crate bar; fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n    p.change_file(\"src/lib.rs\", \"extern crate bar;\");\n    p.cargo(\"check\")\n        .with_status(101)\n        // can't find crate for `bar`\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\nerror[E0463]: can't find crate for `bar`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cfg_raw_idents() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [target.'cfg(any(r#true, r#all, r#target_os = \"<>\"))'.dependencies]\n                b = { path = \"b/\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] b v0.0.1 ([ROOT]/foo/b)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cfg_raw_idents_empty() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [target.'cfg(r#))'.dependencies]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  failed to parse `r#)` as a cfg expression: unexpected character `)` in cfg, expected parens, a comma, an identifier, or a string\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cfg_raw_idents_not_really() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [target.'cfg(r#11))'.dependencies]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  failed to parse `r#11)` as a cfg expression: unexpected character `1` in cfg, expected parens, a comma, an identifier, or a string\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cfg_keywords() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [target.'cfg(any(async, fn, const, return, true))'.dependencies]\n                b = { path = \"b/\" }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [target.\"cfg(any(for, match, extern, crate, false))\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] b v0.0.1 ([ROOT]/foo/b)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cfg_booleans() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'cfg(true)'.dependencies]\n                b = { path = 'b' }\n\n                [target.'cfg(false)'.dependencies]\n                c = { path = 'c' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\"c/Cargo.toml\", &basic_manifest(\"c\", \"0.0.1\"))\n        .file(\"c/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] b v0.0.1 ([ROOT]/foo/b)\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cfg_booleans_config() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [target.'cfg(true)']\n                rustflags = []\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cfg_booleans_not() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'cfg(not(false))'.dependencies]\n                b = { path = 'b' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] b v0.0.1 ([ROOT]/foo/b)\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cfg_booleans_combinators() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'cfg(all(any(true), not(false), true))'.dependencies]\n                b = { path = 'b' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] b v0.0.1 ([ROOT]/foo/b)\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cfg_booleans_rustflags_no_effect() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'cfg(true)'.dependencies]\n                b = { path = 'b' }\n\n                [target.'cfg(false)'.dependencies]\n                c = { path = 'c' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\"c/Cargo.toml\", &basic_manifest(\"c\", \"0.0.1\"))\n        .file(\"c/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .env(\"RUSTFLAGS\", \"--cfg r#false\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] b v0.0.1 ([ROOT]/foo/b)\n[CHECKING] a v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/check.rs",
    "content": "//! Tests for the `cargo check` command.\n\nuse std::fmt::{self, Write};\n\nuse crate::prelude::*;\nuse crate::utils::tools;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::install::exe;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_bin_manifest, basic_manifest, git, project};\n\n#[cargo_test]\nfn check_success() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"extern crate bar; fn main() { ::bar::baz(); }\",\n        )\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    foo.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn check_fail() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"extern crate bar; fn main() { ::bar::baz(42); }\",\n        )\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\nerror[E0061]: this function takes 0 arguments but 1 argument was supplied\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_derive() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            #[macro_use]\n            extern crate bar;\n\n            trait B {\n                fn b(&self);\n            }\n\n            #[derive(B)]\n            struct A;\n\n            fn main() {\n                let a = A;\n                a.b();\n            }\n            \"#,\n        )\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            extern crate proc_macro;\n\n            use proc_macro::TokenStream;\n\n            #[proc_macro_derive(B)]\n            pub fn derive(_input: TokenStream) -> TokenStream {\n                format!(\"impl B for A {{ fn b(&self) {{}} }}\").parse().unwrap()\n            }\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn check_build() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"extern crate bar; fn main() { ::bar::baz(); }\",\n        )\n        .build();\n\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    foo.cargo(\"check\").run();\n    foo.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn build_check() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"extern crate bar; fn main() { ::bar::baz(); }\",\n        )\n        .build();\n\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    foo.cargo(\"build -v\").run();\n    foo.cargo(\"check -v\").run();\n}\n\n// Checks that where a project has both a lib and a bin, the lib is only checked\n// not built.\n#[cargo_test]\nfn issue_3418() {\n    let foo = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    foo.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]--emit=[..]metadata [..]`\n[RUNNING] `rustc --crate-name foo [..] src/main.rs [..]--emit=[..]metadata [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n// Check on a dylib should have a different metadata hash than build.\n#[cargo_test]\nfn dylib_check_preserves_build_cache() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                crate-type = [\"dylib\"]\n\n                [dependencies]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\").run();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n// test `cargo rustc --profile check`\n#[cargo_test]\nfn rustc_check() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"extern crate bar; fn main() { ::bar::baz(); }\",\n        )\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    foo.cargo(\"rustc --profile check -- --emit=metadata\").run();\n\n    // Verify compatible usage of --profile with --release, issue #7488\n    foo.cargo(\"rustc --profile check --release -- --emit=metadata\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] the argument '--profile <PROFILE-NAME>' cannot be used with '--release'\n\nUsage: cargo[EXE] rustc --profile <PROFILE-NAME> [ARGS]...\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n\n    foo.cargo(\"rustc --profile test --release -- --emit=metadata\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] the argument '--profile <PROFILE-NAME>' cannot be used with '--release'\n\nUsage: cargo[EXE] rustc --profile <PROFILE-NAME> [ARGS]...\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustc_check_err() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"extern crate bar; fn main() { ::bar::qux(); }\",\n        )\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    foo.cargo(\"rustc --profile check -- --emit=metadata\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\nerror[E0425]: [..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_all() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                [dependencies]\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"examples/a.rs\", \"fn main() {}\")\n        .file(\"tests/a.rs\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/main.rs\", \"fn main() {}\")\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --workspace -v\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] b v0.0.1 ([ROOT]/foo/b)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]`\n[RUNNING] `rustc --crate-name foo [..] src/main.rs [..]`\n[RUNNING] `rustc --crate-name b [..] b/src/lib.rs [..]`\n[RUNNING] `rustc --crate-name b [..] b/src/main.rs [..]`\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn check_all_exclude() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() { break_the_build(); }\")\n        .build();\n\n    p.cargo(\"check --workspace --exclude baz\")\n        .with_stderr_does_not_contain(\"[CHECKING] baz v0.1.0 [..]\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_all_exclude_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() { break_the_build(); }\")\n        .build();\n\n    p.cargo(\"check --workspace --exclude '*z'\")\n        .with_stderr_does_not_contain(\"[CHECKING] baz v0.1.0 [..]\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_virtual_all_implied() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] baz v0.1.0 ([ROOT]/foo/baz)\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name baz [..] baz/src/lib.rs [..]`\n[RUNNING] `rustc --crate-name bar [..] bar/src/lib.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn check_virtual_manifest_one_project() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() { break_the_build(); }\")\n        .build();\n\n    p.cargo(\"check -p bar\")\n        .with_stderr_does_not_contain(\"[CHECKING] baz v0.1.0 [..]\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_virtual_manifest_one_bin_project_not_in_default_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n                default-members = []\n                resolver = \"3\"\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() { let _ = (1); }\")\n        .build();\n\n    p.cargo(\"check -p bar\")\n        .with_stderr_contains(\"[..]run `cargo fix --bin \\\"bar\\\" -p bar` to apply[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn check_virtual_manifest_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {  break_the_build(); }\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check -p '*z'\")\n        .with_stderr_does_not_contain(\"[CHECKING] bar v0.1.0 [..]\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] baz v0.1.0 ([ROOT]/foo/baz)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn exclude_warns_on_non_existing_package() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.cargo(\"check --workspace --exclude bar\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[WARNING] excluded package(s) `bar` not found in workspace `[ROOT]/foo`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn targets_selected_default() {\n    let foo = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"pub fn smth() {}\")\n        .file(\"examples/example1.rs\", \"fn main() {}\")\n        .file(\"tests/test2.rs\", \"#[test] fn t() {}\")\n        .file(\"benches/bench3.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -v\")\n        .with_stderr_contains(\"[..] --crate-name foo [..] src/lib.rs [..]\")\n        .with_stderr_contains(\"[..] --crate-name foo [..] src/main.rs [..]\")\n        .with_stderr_does_not_contain(\"[..] --crate-name example1 [..] examples/example1.rs [..]\")\n        .with_stderr_does_not_contain(\"[..] --crate-name test2 [..] tests/test2.rs [..]\")\n        .with_stderr_does_not_contain(\"[..] --crate-name bench3 [..] benches/bench3.rs [..]\")\n        .run();\n}\n\n#[cargo_test]\nfn targets_selected_all() {\n    let foo = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"pub fn smth() {}\")\n        .file(\"examples/example1.rs\", \"fn main() {}\")\n        .file(\"tests/test2.rs\", \"#[test] fn t() {}\")\n        .file(\"benches/bench3.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check --all-targets -v\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]`\n[RUNNING] `rustc --crate-name foo [..] src/main.rs [..]`\n[RUNNING] `rustc --crate-name example1 [..] examples/example1.rs [..]`\n[RUNNING] `rustc --crate-name test2 [..] tests/test2.rs [..]`\n[RUNNING] `rustc --crate-name bench3 [..] benches/bench3.rs [..]`\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn check_unit_test_profile() {\n    let foo = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(test)]\n                mod tests {\n                    #[test]\n                    fn it_works() {\n                        badtext\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"check\").run();\n    foo.cargo(\"check --profile test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\nerror[E0425]: cannot find value `badtext` in this scope\n...\n\"#]])\n        .run();\n}\n\n// Verify what is checked with various command-line filters.\n#[cargo_test]\nfn check_filters() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                fn unused_normal_lib() {}\n                #[cfg(test)]\n                mod tests {\n                    fn unused_unit_lib() {}\n                }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {}\n                fn unused_normal_bin() {}\n                #[cfg(test)]\n                mod tests {\n                    fn unused_unit_bin() {}\n                }\n            \"#,\n        )\n        .file(\n            \"tests/t1.rs\",\n            r#\"\n                fn unused_normal_t1() {}\n                #[cfg(test)]\n                mod tests {\n                    fn unused_unit_t1() {}\n                }\n            \"#,\n        )\n        .file(\n            \"examples/ex1.rs\",\n            r#\"\n                fn main() {}\n                fn unused_normal_ex1() {}\n                #[cfg(test)]\n                mod tests {\n                    fn unused_unit_ex1() {}\n                }\n            \"#,\n        )\n        .file(\n            \"benches/b1.rs\",\n            r#\"\n                fn unused_normal_b1() {}\n                #[cfg(test)]\n                mod tests {\n                    fn unused_unit_b1() {}\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_contains(\"[..]unused_normal_lib[..]\")\n        .with_stderr_contains(\"[..]unused_normal_bin[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_normal_t1[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_normal_ex1[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_normal_b1[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_unit_[..]\")\n        .run();\n    p.root().join(\"target\").rm_rf();\n    p.cargo(\"check --tests -v\")\n        .with_stderr_contains(\"[..] --crate-name foo [..] src/lib.rs [..] --test [..]\")\n        .with_stderr_contains(\"[..] --crate-name foo [..] src/lib.rs [..] --crate-type lib [..]\")\n        .with_stderr_contains(\"[..] --crate-name foo [..] src/main.rs [..] --test [..]\")\n        .with_stderr_contains(\"[..]unused_unit_lib[..]\")\n        .with_stderr_contains(\"[..]unused_unit_bin[..]\")\n        .with_stderr_contains(\"[..]unused_normal_lib[..]\")\n        .with_stderr_contains(\"[..]unused_normal_bin[..]\")\n        .with_stderr_contains(\"[..]unused_unit_t1[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_normal_ex1[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_unit_ex1[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_normal_b1[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_unit_b1[..]\")\n        .with_stderr_does_not_contain(\"[..]--crate-type bin[..]\")\n        .run();\n    p.root().join(\"target\").rm_rf();\n    p.cargo(\"check --test t1 -v\")\n        .with_stderr_contains(\"[..]unused_normal_lib[..]\")\n        .with_stderr_contains(\"[..]unused_unit_t1[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_unit_lib[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_normal_bin[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_unit_bin[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_normal_ex1[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_normal_b1[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_unit_ex1[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_unit_b1[..]\")\n        .run();\n    p.root().join(\"target\").rm_rf();\n    p.cargo(\"check --all-targets -v\")\n        .with_stderr_contains(\"[..]unused_normal_lib[..]\")\n        .with_stderr_contains(\"[..]unused_normal_bin[..]\")\n        .with_stderr_contains(\"[..]unused_normal_t1[..]\")\n        .with_stderr_contains(\"[..]unused_normal_ex1[..]\")\n        .with_stderr_contains(\"[..]unused_normal_b1[..]\")\n        .with_stderr_contains(\"[..]unused_unit_b1[..]\")\n        .with_stderr_contains(\"[..]unused_unit_t1[..]\")\n        .with_stderr_contains(\"[..]unused_unit_lib[..]\")\n        .with_stderr_contains(\"[..]unused_unit_bin[..]\")\n        .with_stderr_does_not_contain(\"[..]unused_unit_ex1[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn check_artifacts() {\n    // Verify which artifacts are created when running check (#4059).\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"tests/t1.rs\", \"\")\n        .file(\"examples/ex1.rs\", \"fn main() {}\")\n        .file(\"benches/b1.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n    assert!(!p.root().join(\"target/debug/libfoo.rmeta\").is_file());\n    assert!(!p.root().join(\"target/debug/libfoo.rlib\").is_file());\n    assert!(!p.root().join(\"target/debug\").join(exe(\"foo\")).is_file());\n    assert_eq!(p.glob(\"target/debug/deps/libfoo-*.rmeta\").count(), 2);\n\n    p.root().join(\"target\").rm_rf();\n    p.cargo(\"check --lib\").run();\n    assert!(!p.root().join(\"target/debug/libfoo.rmeta\").is_file());\n    assert!(!p.root().join(\"target/debug/libfoo.rlib\").is_file());\n    assert!(!p.root().join(\"target/debug\").join(exe(\"foo\")).is_file());\n    assert_eq!(p.glob(\"target/debug/deps/libfoo-*.rmeta\").count(), 1);\n\n    p.root().join(\"target\").rm_rf();\n    p.cargo(\"check --bin foo\").run();\n    assert!(!p.root().join(\"target/debug/libfoo.rmeta\").is_file());\n    assert!(!p.root().join(\"target/debug/libfoo.rlib\").is_file());\n    assert!(!p.root().join(\"target/debug\").join(exe(\"foo\")).is_file());\n    assert_eq!(p.glob(\"target/debug/deps/libfoo-*.rmeta\").count(), 2);\n\n    p.root().join(\"target\").rm_rf();\n    p.cargo(\"check --test t1\").run();\n    assert!(!p.root().join(\"target/debug/libfoo.rmeta\").is_file());\n    assert!(!p.root().join(\"target/debug/libfoo.rlib\").is_file());\n    assert!(!p.root().join(\"target/debug\").join(exe(\"foo\")).is_file());\n    assert_eq!(p.glob(\"target/debug/t1-*\").count(), 0);\n    assert_eq!(p.glob(\"target/debug/deps/libfoo-*.rmeta\").count(), 1);\n    assert_eq!(p.glob(\"target/debug/deps/libt1-*.rmeta\").count(), 1);\n\n    p.root().join(\"target\").rm_rf();\n    p.cargo(\"check --example ex1\").run();\n    assert!(!p.root().join(\"target/debug/libfoo.rmeta\").is_file());\n    assert!(!p.root().join(\"target/debug/libfoo.rlib\").is_file());\n    assert!(\n        !p.root()\n            .join(\"target/debug/examples\")\n            .join(exe(\"ex1\"))\n            .is_file()\n    );\n    assert_eq!(p.glob(\"target/debug/deps/libfoo-*.rmeta\").count(), 1);\n    assert_eq!(p.glob(\"target/debug/examples/libex1-*.rmeta\").count(), 1);\n\n    p.root().join(\"target\").rm_rf();\n    p.cargo(\"check --bench b1\").run();\n    assert!(!p.root().join(\"target/debug/libfoo.rmeta\").is_file());\n    assert!(!p.root().join(\"target/debug/libfoo.rlib\").is_file());\n    assert!(!p.root().join(\"target/debug\").join(exe(\"foo\")).is_file());\n    assert_eq!(p.glob(\"target/debug/b1-*\").count(), 0);\n    assert_eq!(p.glob(\"target/debug/deps/libfoo-*.rmeta\").count(), 1);\n    assert_eq!(p.glob(\"target/debug/deps/libb1-*.rmeta\").count(), 1);\n}\n\n#[cargo_test]\nfn short_message_format() {\n    let foo = project()\n        .file(\"src/lib.rs\", \"fn foo() { let _x: bool = 'a'; }\")\n        .build();\n    foo.cargo(\"check --message-format=short\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\nsrc/lib.rs:1:27: error[E0308]: mismatched types[..]\n[ERROR] could not compile `foo` (lib) due to 1 previous error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn proc_macro() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"demo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate proc_macro;\n\n                use proc_macro::TokenStream;\n\n                #[proc_macro_derive(Foo)]\n                pub fn demo(_input: TokenStream) -> TokenStream {\n                    \"\".parse().unwrap()\n                }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[macro_use]\n                extern crate demo;\n\n                #[derive(Foo)]\n                struct A;\n\n                fn main() {}\n            \"#,\n        )\n        .build();\n    p.cargo(\"check -v\").env(\"CARGO_LOG\", \"cargo=trace\").run();\n}\n\n#[cargo_test]\nfn check_keep_going() {\n    let foo = project()\n        .file(\"src/bin/one.rs\", \"compile_error!(\\\"ONE\\\"); fn main() {}\")\n        .file(\"src/bin/two.rs\", \"compile_error!(\\\"TWO\\\"); fn main() {}\")\n        .build();\n\n    // Due to -j1, without --keep-going only one of the two bins would be built.\n    foo.cargo(\"check -j1 --keep-going\")\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n[ERROR] ONE\n[ERROR] TWO\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn does_not_use_empty_rustc_wrapper() {\n    // An empty RUSTC_WRAPPER environment variable won't be used.\n    // The env var will also override the config, essentially unsetting it.\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                rustc-wrapper = \"do-not-execute-me\"\n            \"#,\n        )\n        .build();\n    p.cargo(\"check\").env(\"RUSTC_WRAPPER\", \"\").run();\n}\n\n#[cargo_test]\nfn does_not_use_empty_rustc_workspace_wrapper() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.cargo(\"check\").env(\"RUSTC_WORKSPACE_WRAPPER\", \"\").run();\n}\n\n#[cargo_test]\nfn error_from_deep_recursion() -> Result<(), fmt::Error> {\n    let mut big_macro = String::new();\n    writeln!(big_macro, \"macro_rules! m {{\")?;\n    for i in 0..130 {\n        writeln!(big_macro, \"({}) => {{ m!({}); }};\", i, i + 1)?;\n    }\n    writeln!(big_macro, \"}}\")?;\n    writeln!(big_macro, \"m!(0);\")?;\n\n    let p = project().file(\"src/lib.rs\", &big_macro).build();\n    p.cargo(\"check --message-format=json\")\n        .with_status(101)\n        .with_stdout_data(str![[r#\"\n{\"reason\":\"compiler-message\",[..]\"message\":\"recursion limit reached while expanding `m!`\",[..]rendered\":\"[..]recursion limit reached while expanding `m!`[..]\"}}\n...\n\"#]])\n        .run();\n\n    Ok(())\n}\n\n#[cargo_test]\nfn rustc_workspace_wrapper_affects_all_workspace_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", tools::echo_wrapper())\n        .with_stderr_data(\n            str![[r#\"\nWRAPPER CALLED: rustc --crate-name bar [..]\nWRAPPER CALLED: rustc --crate-name baz [..]\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn rustc_workspace_wrapper_includes_path_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"bar\"]\n\n                [dependencies]\n                baz = { path = \"baz\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check --workspace\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", tools::echo_wrapper())\n        .with_stderr_data(\n            str![[r#\"\nWRAPPER CALLED: rustc --crate-name bar [..]\nWRAPPER CALLED: rustc --crate-name baz [..]\nWRAPPER CALLED: rustc --crate-name foo [..]\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn rustc_workspace_wrapper_respects_primary_units() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check -p bar\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", tools::echo_wrapper())\n        .with_stderr_contains(\"WRAPPER CALLED: rustc --crate-name bar [..]\")\n        .with_stdout_does_not_contain(\"WRAPPER CALLED: rustc --crate-name baz [..]\")\n        .run();\n}\n\n#[cargo_test]\nfn rustc_workspace_wrapper_excludes_published_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"bar\"]\n\n                [dependencies]\n                baz = \"1.0.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    Package::new(\"baz\", \"1.0.0\").publish();\n\n    p.cargo(\"check --workspace -v\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", tools::echo_wrapper())\n        .with_stderr_contains(\"WRAPPER CALLED: rustc --crate-name foo [..]\")\n        .with_stderr_contains(\"WRAPPER CALLED: rustc --crate-name bar [..]\")\n        .with_stderr_contains(\"[CHECKING] baz [..]\")\n        .with_stdout_does_not_contain(\"WRAPPER CALLED: rustc --crate-name baz [..]\")\n        .run();\n}\n\n#[cargo_test]\nfn warn_manifest_with_project() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [project]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `[project]` is deprecated in favor of `[package]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn error_manifest_with_project_on_2024() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [project]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2024\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `[project]` is not supported as of the 2024 Edition, please use `[package]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warn_manifest_package_and_project() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [project]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `[project]` is deprecated in favor of `[package]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_manifest_package_and_project() {\n    let p = project();\n    let git_project = git::new(\"bar\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [project]\n            name = \"bar\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = p\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n                git  = '{}'\n\n            \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.0.1 ([ROOTURL]/bar#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_manifest_with_project() {\n    let p = project();\n    let git_project = git::new(\"bar\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n            [project]\n            name = \"bar\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = p\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n                git  = '{}'\n\n            \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.0.1 ([ROOTURL]/bar#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_fixable_warning() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"use std::io;\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply 1 suggestion)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_fixable_test_warning() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\\\nmod tests {\n    #[test]\n    fn t1() {\n        use std::io;\n    }\n}\n            \",\n        )\n        .build();\n\n    foo.cargo(\"check --all-targets\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] `foo` (lib test) generated 1 warning (run `cargo fix --lib -p foo --tests` to apply 1 suggestion)\n...\n\"#]])\n        .run();\n    foo.cargo(\"fix --lib -p foo --tests --allow-no-vcs\").run();\n    assert!(!foo.read_file(\"src/lib.rs\").contains(\"use std::io;\"));\n}\n\n#[cargo_test]\nfn check_fixable_error_no_fix() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"use std::io;\\n#[derive(Debug(x))]\\nstruct Foo;\",\n        )\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] traits in `#[derive(...)]` don't accept arguments\n[WARNING] unused import: `std::io`\n[WARNING] `foo` (lib) generated 1 warning\n[ERROR] could not compile `foo` (lib) due to 1 previous error; 1 warning emitted\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn check_fixable_warning_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"use std::io;\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                foo = { path = \"../foo\" }\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"use std::io;\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[WARNING] `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply 1 suggestion)\n[WARNING] `bar` (lib) generated 1 warning (run `cargo fix --lib -p bar` to apply 1 suggestion)\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn check_fixable_example() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn hello() -> &'static str {\n                \"hello\"\n            }\n\n            pub fn main() {\n                println!(\"{}\", hello())\n            }\n            \"#,\n        )\n        .file(\"examples/ex1.rs\", \"use std::fmt; fn main() {}\")\n        .build();\n    p.cargo(\"check --all-targets\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] `foo` (example \"ex1\") generated 1 warning (run `cargo fix --example \"ex1\" -p foo` to apply 1 suggestion)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn check_fixable_bench() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n\n            fn hello() -> &'static str {\n                \"hello\"\n            }\n\n            pub fn main() {\n                println!(\"{}\", hello())\n            }\n\n            #[bench]\n            fn bench_hello(_b: &mut test::Bencher) {\n                use std::io;\n                assert_eq!(hello(), \"hello\")\n            }\n            \"#,\n        )\n        .file(\n            \"benches/bench.rs\",\n            \"\n            #![feature(test)]\n            extern crate test;\n\n            #[bench]\n            fn bench(_b: &mut test::Bencher) { use std::fmt; }\n        \",\n        )\n        .build();\n    p.cargo(\"check --all-targets\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] `foo` (bench \"bench\") generated 1 warning (run `cargo fix --bench \"bench\" -p foo` to apply 1 suggestion)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn check_fixable_mixed() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            #![feature(test)]\n            #[cfg(test)]\n            extern crate test;\n\n            fn hello() -> &'static str {\n                \"hello\"\n            }\n\n            pub fn main() {\n                println!(\"{}\", hello())\n            }\n\n            #[bench]\n            fn bench_hello(_b: &mut test::Bencher) {\n                use std::io;\n                assert_eq!(hello(), \"hello\")\n            }\n            #[test]\n            fn t1() {\n                use std::fmt;\n            }\n            \"#,\n        )\n        .file(\"examples/ex1.rs\", \"use std::fmt; fn main() {}\")\n        .file(\n            \"benches/bench.rs\",\n            \"\n            #![feature(test)]\n            extern crate test;\n\n            #[bench]\n            fn bench(_b: &mut test::Bencher) { use std::fmt; }\n        \",\n        )\n        .build();\n    p.cargo(\"check --all-targets\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `foo` (example \"ex1\") generated 1 warning (run `cargo fix --example \"ex1\" -p foo` to apply 1 suggestion)\n[WARNING] `foo` (bench \"bench\") generated 1 warning (run `cargo fix --bench \"bench\" -p foo` to apply 1 suggestion)\n[WARNING] `foo` (bin \"foo\" test) generated 2 warnings (run `cargo fix --bin \"foo\" -p foo --tests` to apply 2 suggestions)\n...\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn check_fixable_warning_for_clippy() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        // We don't want to show a warning that is `clippy`\n        // specific since we are using a `rustc` wrapper\n        // inplace of `clippy`\n        .file(\"src/lib.rs\", \"use std::io;\")\n        .build();\n\n    foo.cargo(\"check\")\n        // We can't use `clippy` so we use a `rustc` workspace wrapper instead\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", tools::wrapped_clippy_driver())\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] `foo` (lib) generated 1 warning (run `cargo clippy --fix --lib -p foo` to apply 1 suggestion)\n...\n\"#]])\n        .run();\n\n    foo.cargo(\"check\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", tools::wrapped_clippy_driver())\n        .env(\"CLIPPY_ARGS\", \"-Wclippy::pedantic__CLIPPY_HACKERY__-Aclippy::allow_attributes__CLIPPY_HACKERY__\") // Set -Wclippy::pedantic\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] `foo` (lib) generated 1 warning (run `cargo clippy --fix --lib -p foo -- -Wclippy::pedantic -Aclippy::allow_attributes` to apply 1 suggestion)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_unused_manifest_keys() {\n    Package::new(\"dep\", \"0.1.0\").publish();\n    Package::new(\"foo\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            dep = { version = \"0.1.0\", wxz = \"wxz\" }\n            foo = { version = \"0.1.0\", abc = \"abc\" }\n\n            [dev-dependencies]\n            foo = { version = \"0.1.0\", wxz = \"wxz\" }\n\n            [build-dependencies]\n            foo = { version = \"0.1.0\", wxz = \"wxz\" }\n\n            [target.'cfg(windows)'.dependencies]\n            foo = { version = \"0.1.0\", wxz = \"wxz\" }\n\n            [target.wasm32-wasip1.dev-dependencies]\n            foo = { version = \"0.1.0\", wxz = \"wxz\" }\n\n            [target.bar.build-dependencies]\n            foo = { version = \"0.1.0\", wxz = \"wxz\" }\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[WARNING] unused manifest key: dependencies.dep.wxz\n[WARNING] unused manifest key: dependencies.foo.abc\n[WARNING] unused manifest key: dev-dependencies.foo.wxz\n[WARNING] unused manifest key: build-dependencies.foo.wxz\n[WARNING] unused manifest key: target.bar.build-dependencies.foo.wxz\n[WARNING] unused manifest key: target.cfg(windows).dependencies.foo.wxz\n[WARNING] unused manifest key: target.wasm32-wasip1.dev-dependencies.foo.wxz\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.1.0 (registry `dummy-registry`)\n[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`)\n[CHECKING] foo v0.1.0\n[CHECKING] dep v0.1.0\n[CHECKING] bar v0.2.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn versionless_package() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                description = \"foo\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn pkgid_querystring_works() {\n    let git_project = git::new(\"gitdep\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"gitdep\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n\n                [dependencies]\n                gitdep = {{ git = \"{}\", branch = \"master\" }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    let output = p.cargo(\"pkgid\").arg(\"gitdep\").run();\n    let gitdep_pkgid = String::from_utf8(output.stdout).unwrap();\n    let gitdep_pkgid = gitdep_pkgid.trim();\n    assert_e2e().eq(\n        gitdep_pkgid,\n        str![\"git+[ROOTURL]/gitdep?branch=master#1.0.0\"],\n    );\n\n    p.cargo(\"build -p\")\n        .arg(gitdep_pkgid)\n        .with_stderr_data(str![[r#\"\n[COMPILING] gitdep v1.0.0 ([ROOTURL]/gitdep?branch=master#[..])\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_build_should_not_output_files_to_artifact_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\").enable_mac_dsym().run();\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n\n\"#]]);\n}\n\n#[cargo_test]\nfn check_build_should_lock_target_dir_when_artifact_dir_is_same_as_build_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .build();\n\n    p.cargo(\"check\").enable_mac_dsym().run();\n    assert!(p.root().join(\"target/debug/.cargo-build-lock\").exists());\n}\n\n#[cargo_test]\nfn check_build_should_not_lock_artifact_dir_when_build_dir_is_not_same_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\").enable_mac_dsym().run();\n\n    // Verify we did NOT take the build-dir lock\n    assert!(!p.root().join(\"target-dir/debug/.cargo-lock\").exists());\n    // Verify we did take the build-dir lock\n    assert!(p.root().join(\"build-dir/debug/.cargo-build-lock\").exists());\n}\n\n// Regression test for #16305\n#[cargo_test]\nfn check_build_should_not_uplift_proc_macro_dylib_deps() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target-dir = \"target-dir\"\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\", \"baz\"]\n            \"#,\n        )\n        // Bin\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"../bar\" }\n            \"#,\n        )\n        .file(\"foo/src/main.rs\", \"fn main() {}\")\n        // Proc macro\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                baz = { path = \"../baz\" }\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n            extern crate proc_macro;\n\n            use proc_macro::TokenStream;\n\n            #[proc_macro_derive(B)]\n            pub fn derive(input: TokenStream) -> TokenStream {\n                input\n            }\n            \"#,\n        )\n        // Dylib\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                crate-type = [\"dylib\"]\n\n                [dependencies]\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"pub fn baz() { }\")\n        .build();\n\n    p.cargo(\"check\").enable_mac_dsym().run();\n\n    p.root()\n        .join(\"target-dir\")\n        .assert_build_dir_layout(str![[r#\"\n[ROOT]/foo/target-dir/CACHEDIR.TAG\n\n\"#]]);\n}\n"
  },
  {
    "path": "tests/testsuite/check_cfg.rs",
    "content": "//! Tests for Cargo usage of rustc `--check-cfg`.\n\nuse crate::prelude::*;\nuse cargo_test_support::{basic_manifest, project, str};\n\nmacro_rules! x {\n    ($tool:tt => $what:tt $(of $who:tt)?) => {{\n        #[cfg(windows)]\n        {\n            concat!(\"[RUNNING] [..]\", $tool, \"[..] --check-cfg \",\n                    $what, '(', $($who,)* ')', \"[..]\")\n        }\n        #[cfg(not(windows))]\n        {\n            concat!(\"[RUNNING] [..]\", $tool, \"[..] --check-cfg '\",\n                    $what, '(', $($who,)* ')', \"'\", \"[..]\")\n        }\n    }};\n    ($tool:tt => $what:tt of $who:tt with $($first_value:tt $($other_values:tt)*)?) => {{\n        #[cfg(windows)]\n        {\n            concat!(\"[RUNNING] [..]\", $tool, \"[..] --check-cfg \\\"\",\n                    $what, '(', $who, \", values(\", $(\"/\\\"\", $first_value, \"/\\\"\", $(\", \", \"/\\\"\", $other_values, \"/\\\"\",)*)* \"))\", '\"', \"[..]\")\n        }\n        #[cfg(not(windows))]\n        {\n            concat!(\"[RUNNING] [..]\", $tool, \"[..] --check-cfg '\",\n                    $what, '(', $who, \", values(\", $(\"\\\"\", $first_value, \"\\\"\", $(\", \", \"\\\"\", $other_values, \"\\\"\",)*)* \"))\", \"'\", \"[..]\")\n        }\n    }};\n}\n\n#[cargo_test]\nfn features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                f_a = []\n                f_b = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with \"f_a\" \"f_b\"))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"docsrs,test\"))\n        .run();\n}\n\n#[cargo_test]\nfn features_with_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar/\" }\n\n                [features]\n                f_a = []\n                f_b = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"#[allow(dead_code)] fn bar() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with \"f_a\" \"f_b\"))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"docsrs,test\"))\n        .run();\n}\n\n#[cargo_test]\nfn features_with_opt_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar/\", optional = true }\n\n                [features]\n                default = [\"bar\"]\n                f_a = []\n                f_b = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"#[allow(dead_code)] fn bar() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with \"bar\" \"default\" \"f_a\" \"f_b\"))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"docsrs,test\"))\n        .run();\n}\n\n#[cargo_test]\nfn features_with_namespaced_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar/\", optional = true }\n\n                [features]\n                f_a = [\"dep:bar\"]\n                f_b = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"#[allow(dead_code)] fn bar() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with \"f_a\" \"f_b\"))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"docsrs,test\"))\n        .run();\n}\n\n#[cargo_test]\nfn features_fingerprint() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                f_a = []\n                f_b = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"#[cfg(feature = \\\"f_b\\\")] fn entry() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with \"f_a\" \"f_b\"))\n        .with_stderr_does_not_contain(\"[..]unexpected_cfgs[..]\")\n        .run();\n\n    p.cargo(\"check -v\")\n        .with_stderr_does_not_contain(\"[..]rustc[..]\")\n        .run();\n\n    // checking that re-ordering the features does not invalid the fingerprint\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            f_b = []\n            f_a = []\n        \"#,\n    );\n\n    p.cargo(\"check -v\")\n        .with_stderr_does_not_contain(\"[..]rustc[..]\")\n        .run();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            f_a = []\n        \"#,\n    );\n\n    p.cargo(\"check -v\")\n        // we check that the fingerprint is indeed dirty\n        // that is cause rustc to be called again with the new check-cfg args\n        // and that we indeed found a new warning from the unexpected_cfgs lint\n        .with_stderr_data(format!(\n            \"\\\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the list of declared features changed\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n{running_rustc}\n[WARNING] unexpected `cfg` condition value: `f_b`\n...\n\",\n            running_rustc = x!(\"rustc\" => \"cfg\" of \"feature\" with \"f_a\")\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn well_known_names_values() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"docsrs,test\"))\n        .run();\n}\n\n#[cargo_test]\nfn features_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                f_a = []\n                f_b = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"test -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with \"f_a\" \"f_b\"))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"docsrs,test\"))\n        .run();\n}\n\n#[cargo_test]\nfn features_doctest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                default = [\"f_a\"]\n                f_a = []\n                f_b = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"#[allow(dead_code)] fn foo() {}\")\n        .build();\n\n    p.cargo(\"test -v --doc\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with \"default\" \"f_a\" \"f_b\"))\n        .with_stderr_contains(x!(\"rustdoc\" => \"cfg\" of \"feature\" with \"default\" \"f_a\" \"f_b\"))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"docsrs,test\"))\n        .with_stderr_contains(x!(\"rustdoc\" => \"cfg\" of \"docsrs,test\"))\n        .run();\n}\n\n#[cargo_test]\nfn well_known_names_values_test() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"test -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"docsrs,test\"))\n        .run();\n}\n\n#[cargo_test]\nfn well_known_names_values_doctest() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"#[allow(dead_code)] fn foo() {}\")\n        .build();\n\n    p.cargo(\"test -v --doc\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with))\n        .with_stderr_contains(x!(\"rustdoc\" => \"cfg\" of \"feature\" with))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"docsrs,test\"))\n        .with_stderr_contains(x!(\"rustdoc\" => \"cfg\" of \"docsrs,test\"))\n        .run();\n}\n\n#[cargo_test]\nfn features_doc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                default = [\"f_a\"]\n                f_a = []\n                f_b = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"#[allow(dead_code)] fn foo() {}\")\n        .build();\n\n    p.cargo(\"doc -v\")\n        .with_stderr_contains(x!(\"rustdoc\" => \"cfg\" of \"feature\" with \"default\" \"f_a\" \"f_b\"))\n        .with_stderr_contains(x!(\"rustdoc\" => \"cfg\" of \"docsrs,test\"))\n        .run();\n}\n\n#[cargo_test]\nfn build_script_feedback() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-check-cfg=cfg(foo)\"); }\"#,\n        )\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"foo\"))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"docsrs,test\"))\n        .run();\n}\n\n#[cargo_test]\nfn build_script_doc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-check-cfg=cfg(foo)\"); }\"#,\n        )\n        .build();\n\n    p.cargo(\"doc -v\")\n        .with_stderr_does_not_contain(\"rustc [..] --check-cfg [..]\")\n        .with_stderr_data(format!(\n            \"\\\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] build.rs [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n{running_rustdoc}\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\",\n            running_rustdoc = x!(\"rustdoc\" => \"cfg\" of \"foo\")\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn build_script_override() {\n    let target = cargo_test_support::rustc_host();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"a\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}.a]\n                    rustc-check-cfg = [\"cfg(foo)\"]\n                \"#,\n                target\n            ),\n        )\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"foo\"))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"docsrs,test\"))\n        .run();\n}\n\n#[cargo_test]\nfn build_script_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"fn main() {\n                println!(\"cargo::rustc-check-cfg=cfg(foo)\");\n                println!(\"cargo::rustc-cfg=foo\");\n            }\"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                ///\n                /// ```\n                /// extern crate foo;\n                ///\n                /// fn main() {\n                ///     foo::foo()\n                /// }\n                /// ```\n                ///\n                #[cfg(foo)]\n                pub fn foo() {}\n\n                #[cfg(foo)]\n                #[test]\n                fn test_foo() {\n                    foo()\n                }\n            \"#,\n        )\n        .file(\"tests/test.rs\", \"#[cfg(foo)] #[test] fn test_bar() {}\")\n        .build();\n\n    p.cargo(\"test -v\")\n        .with_stderr_data(\n            format!(\n                \"\\\n{running_rustc}\n{running_rustdoc}\n...\n\",\n                running_rustc = x!(\"rustc\" => \"cfg\" of \"foo\"),\n                running_rustdoc = x!(\"rustdoc\" => \"cfg\" of \"foo\")\n            )\n            .unordered(),\n        )\n        .with_stdout_data(\n            str![[r#\"\ntest test_foo ... ok\ntest test_bar ... ok\ntest [..] ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn config_simple() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lints.rust]\n                unexpected_cfgs = { level = \"warn\", check-cfg = [\"cfg(has_foo)\", \"cfg(has_bar, values(\\\"yes\\\", \\\"no\\\"))\"] }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"has_foo\"))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"has_bar\" with \"yes\" \"no\"))\n        .with_stderr_does_not_contain(\"[..]unused manifest key[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn config_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo/\"]\n\n                [workspace.lints.rust]\n                unexpected_cfgs = { level = \"warn\", check-cfg = [\"cfg(has_foo)\"] }\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lints]\n                workspace = true\n            \"#,\n        )\n        .file(\"foo/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(format!(\n            \"\\\n...\n{running_rustc}\n...\n\",\n            running_rustc = x!(\"rustc\" => \"cfg\" of \"has_foo\")\n        ))\n        .with_stderr_does_not_contain(\"unexpected_cfgs\")\n        .run();\n}\n\n#[cargo_test]\nfn config_workspace_not_inherited() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo/\"]\n\n                [workspace.lints.rust]\n                unexpected_cfgs = { level = \"warn\", check-cfg = [\"cfg(has_foo)\"] }\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"foo/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_does_not_contain(x!(\"rustc\" => \"cfg\" of \"has_foo\"))\n        .with_stderr_does_not_contain(\"unexpected_cfgs\")\n        .run();\n}\n\n#[cargo_test]\nfn config_invalid_position() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lints.rust]\n                use_bracket = { level = \"warn\", check-cfg = [\"cfg(has_foo)\"] }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused manifest key: `lints.rust.use_bracket.check-cfg`\n...\n\"#]])\n        .with_stderr_does_not_contain(x!(\"rustc\" => \"cfg\" of \"has_foo\"))\n        .run();\n}\n\n#[cargo_test]\nfn config_invalid_empty() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lints.rust]\n                unexpected_cfgs = { }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] missing field `level`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn config_invalid_not_list() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lints.rust]\n                unexpected_cfgs = { level = \"warn\", check-cfg = \"cfg()\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `lints.rust.unexpected_cfgs.check-cfg` must be a list of string\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn config_invalid_not_list_string() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lints.rust]\n                unexpected_cfgs = { level = \"warn\", check-cfg = [12] }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `lints.rust.unexpected_cfgs.check-cfg` must be a list of string\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn config_and_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                my_feature = []\n                alloc = []\n\n                [lints.rust]\n                unexpected_cfgs = { level = \"warn\", check-cfg = [\"cfg(has_foo)\", \"cfg(has_bar, values(\\\"yes\\\", \\\"no\\\"))\"] }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"has_foo\"))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"has_bar\" with \"yes\" \"no\"))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with \"alloc\" \"my_feature\"))\n        .run();\n}\n\n#[cargo_test]\nfn config_with_cargo_doc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lints.rust]\n                unexpected_cfgs = { level = \"warn\", check-cfg = [\"cfg(has_foo)\"] }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"doc -v\")\n        .with_stderr_data(format!(\n            \"\\\n...\n{running_rustdoc}\n...\n\",\n            running_rustdoc = x!(\"rustdoc\" => \"cfg\" of \"has_foo\")\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn config_with_cargo_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lints.rust]\n                unexpected_cfgs = { level = \"warn\", check-cfg = [\"cfg(has_foo)\"] }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"test -v\")\n        .with_stderr_data(format!(\n            \"\\\n...\n{running_rustc}\n...\n\",\n            running_rustc = x!(\"rustc\" => \"cfg\" of \"has_foo\")\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn config_and_build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                build = \"build.rs\"\n\n                [lints.rust]\n                unexpected_cfgs = { level = \"warn\", check-cfg = [\"cfg(bar)\"] }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-check-cfg=cfg(foo)\"); }\"#,\n        )\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"foo\")) // from build.rs\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"bar\")) // from config\n        .run();\n}\n\n#[cargo_test]\nfn config_features_and_build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                build = \"build.rs\"\n\n                [features]\n                serde = []\n                json = []\n\n                [lints.rust]\n                unexpected_cfgs = { level = \"warn\", check-cfg = [\"cfg(bar)\"] }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rustc-check-cfg=cfg(foo)\"); }\"#,\n        )\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"foo\")) // from build.rs\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"bar\")) // from config\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"feature\" with \"json\" \"serde\")) // features\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"docsrs,test\")) // Cargo well known\n        .run();\n}\n\n#[cargo_test]\nfn config_fingerprint() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lints.rust]\n                unexpected_cfgs = { level = \"warn\", check-cfg = [\"cfg(bar)\"] }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"fn entry() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"bar\"))\n        .run();\n\n    p.cargo(\"check -v\")\n        .with_stderr_does_not_contain(\"[..]rustc[..]\")\n        .run();\n\n    // checking that changing the `check-cfg` config does invalid the fingerprint\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [lints.rust]\n            unexpected_cfgs = { level = \"warn\", check-cfg = [\"cfg(bar)\", \"cfg(foo)\"] }\n        \"#,\n    );\n\n    p.cargo(\"check -v\")\n        // we check that the fingerprint is indeed dirty\n        .with_stderr_contains(\"[..][DIRTY][..]the profile configuration changed\")\n        // that cause rustc to be called again with the new check-cfg args\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"bar\"))\n        .with_stderr_contains(x!(\"rustc\" => \"cfg\" of \"foo\"))\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/clean.rs",
    "content": "//! Tests for the `cargo clean` command.\n\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{\n    basic_bin_manifest, basic_manifest, git, main_file, project, project_in, rustc_host,\n};\nuse glob::GlobError;\nuse std::env;\nuse std::path::{Path, PathBuf};\n\n#[cargo_test]\nfn cargo_clean_simple() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build\").run();\n    assert!(p.build_dir().is_dir());\n\n    p.cargo(\"clean\").run();\n    assert!(!p.build_dir().is_dir());\n}\n\n#[cargo_test]\nfn different_dir() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .file(\"src/bar/a.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    assert!(p.build_dir().is_dir());\n\n    p.cargo(\"clean\")\n        .cwd(\"src\")\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    assert!(!p.build_dir().is_dir());\n}\n\n#[cargo_test]\nfn clean_multiple_packages() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.d1]\n                    path = \"d1\"\n                [dependencies.d2]\n                    path = \"d2\"\n\n                [[bin]]\n                    name = \"foo\"\n            \"#,\n        )\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .file(\"d1/Cargo.toml\", &basic_bin_manifest(\"d1\"))\n        .file(\"d1/src/main.rs\", \"fn main() { println!(\\\"d1\\\"); }\")\n        .file(\"d2/Cargo.toml\", &basic_bin_manifest(\"d2\"))\n        .file(\"d2/src/main.rs\", \"fn main() { println!(\\\"d2\\\"); }\")\n        .build();\n\n    p.cargo(\"build -p d1 -p d2 -p foo\").run();\n\n    let d1_path = &p\n        .build_dir()\n        .join(\"debug\")\n        .join(format!(\"d1{}\", env::consts::EXE_SUFFIX));\n    let d2_path = &p\n        .build_dir()\n        .join(\"debug\")\n        .join(format!(\"d2{}\", env::consts::EXE_SUFFIX));\n\n    assert!(p.bin(\"foo\").is_file());\n    assert!(d1_path.is_file());\n    assert!(d2_path.is_file());\n\n    p.cargo(\"clean -p d1 -p d2\")\n        .cwd(\"src\")\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!d1_path.is_file());\n    assert!(!d2_path.is_file());\n}\n\n#[cargo_test]\nfn clean_multiple_packages_in_glob_char_path() {\n    let p = project_in(\"[d1]\")\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n    let foo_path = &p.build_dir().join(\"debug\").join(\"deps\");\n\n    #[cfg(not(target_env = \"msvc\"))]\n    let file_glob = \"foo-*\";\n\n    #[cfg(target_env = \"msvc\")]\n    let file_glob = \"foo.pdb\";\n\n    // Assert that build artifacts are produced\n    p.cargo(\"build\").run();\n    assert_ne!(get_build_artifacts(foo_path, file_glob).len(), 0);\n\n    // Assert that build artifacts are destroyed\n    p.cargo(\"clean -p foo\").run();\n    assert_eq!(get_build_artifacts(foo_path, file_glob).len(), 0);\n}\n\nfn get_build_artifacts(path: &PathBuf, file_glob: &str) -> Vec<Result<PathBuf, GlobError>> {\n    let pattern = path.to_str().expect(\"expected utf-8 path\");\n    let pattern = glob::Pattern::escape(pattern);\n\n    let path = PathBuf::from(pattern).join(file_glob);\n    let path = path.to_str().expect(\"expected utf-8 path\");\n    glob::glob(path)\n        .expect(\"expected glob to run\")\n        .into_iter()\n        .collect::<Vec<Result<PathBuf, GlobError>>>()\n}\n\n#[cargo_test]\nfn clean_p_only_cleans_specified_package() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\n                    \"foo\",\n                    \"foo_core\",\n                    \"foo-base\",\n                ]\n            \"#,\n        )\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"//! foo\")\n        .file(\"foo_core/Cargo.toml\", &basic_manifest(\"foo_core\", \"0.1.0\"))\n        .file(\"foo_core/src/lib.rs\", \"//! foo_core\")\n        .file(\"foo-base/Cargo.toml\", &basic_manifest(\"foo-base\", \"0.1.0\"))\n        .file(\"foo-base/src/lib.rs\", \"//! foo-base\")\n        .build();\n\n    let fingerprint_path = &p.build_dir().join(\"debug\").join(\".fingerprint\");\n\n    p.cargo(\"build -p foo -p foo_core -p foo-base\").run();\n\n    let mut fingerprint_names = get_fingerprints_without_hashes(fingerprint_path);\n\n    // Artifacts present for all after building\n    assert!(fingerprint_names.iter().any(|e| e == \"foo\"));\n    let num_foo_core_artifacts = fingerprint_names\n        .iter()\n        .filter(|&e| e == \"foo_core\")\n        .count();\n    assert_ne!(num_foo_core_artifacts, 0);\n    let num_foo_base_artifacts = fingerprint_names\n        .iter()\n        .filter(|&e| e == \"foo-base\")\n        .count();\n    assert_ne!(num_foo_base_artifacts, 0);\n\n    p.cargo(\"clean -p foo\").run();\n\n    fingerprint_names = get_fingerprints_without_hashes(fingerprint_path);\n\n    // Cleaning `foo` leaves artifacts for the others\n    assert!(!fingerprint_names.iter().any(|e| e == \"foo\"));\n    assert_eq!(\n        fingerprint_names\n            .iter()\n            .filter(|&e| e == \"foo_core\")\n            .count(),\n        num_foo_core_artifacts,\n    );\n    assert_eq!(\n        fingerprint_names\n            .iter()\n            .filter(|&e| e == \"foo-base\")\n            .count(),\n        num_foo_core_artifacts,\n    );\n}\n\n#[cargo_test]\nfn clean_workspace_does_not_touch_non_workspace_packages() {\n    Package::new(\"external_dependency\", \"0.1.0\").publish();\n    let foo_manifest = r#\"\n        [package]\n        name = \"foo\"\n        version = \"0.1.0\"\n        edition = \"2015\"\n\n        [dependencies]\n        external_dependency = \"0.1.0\"\n        \"#;\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\n                    \"foo\",\n                    \"foo_core\",\n                    \"foo-base\",\n                ]\n            \"#,\n        )\n        .file(\"foo/Cargo.toml\", foo_manifest)\n        .file(\"foo/src/lib.rs\", \"//! foo\")\n        .file(\"foo_core/Cargo.toml\", &basic_manifest(\"foo_core\", \"0.1.0\"))\n        .file(\"foo_core/src/lib.rs\", \"//! foo_core\")\n        .file(\"foo-base/Cargo.toml\", &basic_manifest(\"foo-base\", \"0.1.0\"))\n        .file(\"foo-base/src/lib.rs\", \"//! foo-base\")\n        .build();\n\n    let fingerprint_path = &p.build_dir().join(\"debug\").join(\".fingerprint\");\n\n    p.cargo(\"check -p foo -p foo_core -p foo-base\").run();\n\n    let mut fingerprint_names = get_fingerprints_without_hashes(fingerprint_path);\n\n    // Artifacts present for all after building\n    assert!(fingerprint_names.iter().any(|e| e == \"foo\"));\n    assert!(fingerprint_names.iter().any(|e| e == \"foo_core\"));\n    assert!(fingerprint_names.iter().any(|e| e == \"foo-base\"));\n\n    let num_external_dependency_artifacts = fingerprint_names\n        .iter()\n        .filter(|&e| e == \"external_dependency\")\n        .count();\n    assert_ne!(num_external_dependency_artifacts, 0);\n\n    p.cargo(\"clean --workspace\").run();\n\n    fingerprint_names = get_fingerprints_without_hashes(fingerprint_path);\n\n    // Cleaning workspace members leaves artifacts for the external dependency\n    assert!(\n        !fingerprint_names\n            .iter()\n            .any(|e| e == \"foo\" || e == \"foo_core\" || e == \"foo-base\")\n    );\n    assert_eq!(\n        fingerprint_names\n            .iter()\n            .filter(|&e| e == \"external_dependency\")\n            .count(),\n        num_external_dependency_artifacts,\n    );\n}\n\n#[cargo_test]\nfn clean_workspace_with_extra_package_specifiers() {\n    Package::new(\"external_dependency_1\", \"0.1.0\").publish();\n    Package::new(\"external_dependency_2\", \"0.1.0\").publish();\n    let foo_manifest = r#\"\n        [package]\n        name = \"foo\"\n        version = \"0.1.0\"\n        edition = \"2015\"\n\n        [dependencies]\n        external_dependency_1 = \"0.1.0\"\n        external_dependency_2 = \"0.1.0\"\n        \"#;\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\n                    \"foo\",\n                    \"foo_core\",\n                    \"foo-base\",\n                ]\n            \"#,\n        )\n        .file(\"foo/Cargo.toml\", foo_manifest)\n        .file(\"foo/src/lib.rs\", \"//! foo\")\n        .file(\"foo_core/Cargo.toml\", &basic_manifest(\"foo_core\", \"0.1.0\"))\n        .file(\"foo_core/src/lib.rs\", \"//! foo_core\")\n        .file(\"foo-base/Cargo.toml\", &basic_manifest(\"foo-base\", \"0.1.0\"))\n        .file(\"foo-base/src/lib.rs\", \"//! foo-base\")\n        .build();\n\n    let fingerprint_path = &p.build_dir().join(\"debug\").join(\".fingerprint\");\n\n    p.cargo(\"check -p foo -p foo_core -p foo-base\").run();\n\n    let mut fingerprint_names = get_fingerprints_without_hashes(fingerprint_path);\n\n    // Artifacts present for all after building\n    assert!(fingerprint_names.iter().any(|e| e == \"foo\"));\n    assert!(fingerprint_names.iter().any(|e| e == \"foo_core\"));\n    assert!(fingerprint_names.iter().any(|e| e == \"foo-base\"));\n\n    let num_external_dependency_2_artifacts = fingerprint_names\n        .iter()\n        .filter(|&e| e == \"external_dependency_2\")\n        .count();\n    assert_ne!(num_external_dependency_2_artifacts, 0);\n\n    p.cargo(\"clean --workspace -p external_dependency_1\").run();\n\n    fingerprint_names = get_fingerprints_without_hashes(fingerprint_path);\n\n    // Cleaning workspace members and external_dependency_1 leaves artifacts for the external_dependency_2\n    assert!(\n        !fingerprint_names.iter().any(|e| e == \"foo\"\n            || e == \"foo_core\"\n            || e == \"foo-base\"\n            || e == \"external_dependency_1\")\n    );\n    assert_eq!(\n        fingerprint_names\n            .iter()\n            .filter(|&e| e == \"external_dependency_2\")\n            .count(),\n        num_external_dependency_2_artifacts,\n    );\n}\n\nfn get_fingerprints_without_hashes(fingerprint_path: &Path) -> Vec<String> {\n    std::fs::read_dir(fingerprint_path)\n        .expect(\"Build dir should be readable\")\n        .filter_map(|entry| entry.ok())\n        .map(|entry| {\n            let name = entry.file_name();\n            let name = name\n                .into_string()\n                .expect(\"fingerprint name should be UTF-8\");\n            name.rsplit_once('-')\n                .expect(\"Name should contain at least one hyphen\")\n                .0\n                .to_owned()\n        })\n        .collect()\n}\n\n#[cargo_test]\nfn clean_release() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --release\").run();\n\n    p.cargo(\"clean -p foo\").run();\n    p.cargo(\"build --release\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"clean -p foo --release\").run();\n    p.cargo(\"build --release\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build\").run();\n\n    p.cargo(\"clean\").arg(\"--release\").run();\n    assert!(p.build_dir().is_dir());\n    assert!(p.build_dir().join(\"debug\").is_dir());\n    assert!(!p.build_dir().join(\"release\").is_dir());\n}\n\n#[cargo_test]\nfn clean_doc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc\").run();\n\n    let doc_path = &p.build_dir().join(\"doc\");\n\n    assert!(doc_path.is_dir());\n\n    p.cargo(\"clean --doc\")\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n\n    assert!(!doc_path.is_dir());\n    assert!(p.build_dir().is_dir());\n}\n\n#[cargo_test]\nfn build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::path::PathBuf;\n                use std::env;\n\n                fn main() {\n                    let out = PathBuf::from(env::var_os(\"OUT_DIR\").unwrap());\n                    if env::var(\"FIRST\").is_ok() {\n                        std::fs::File::create(out.join(\"out\")).unwrap();\n                    } else {\n                        assert!(!out.join(\"out\").exists());\n                    }\n                }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").env(\"FIRST\", \"1\").run();\n    p.cargo(\"clean -p foo\").run();\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] build.rs [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..] src/main.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn clean_git() {\n    let git = git::new(\"dep\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    dep = {{ git = '{}' }}\n                \"#,\n                git.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"clean -p dep\")\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn registry() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"clean -p bar\")\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn clean_verbose() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    p.cargo(\"build\").run();\n    let mut expected = String::from(\n        \"\\\n[REMOVING] [ROOT]/foo/target/debug/.fingerprint/bar-[HASH]\n[REMOVING] [ROOT]/foo/target/debug/deps/libbar-[HASH].rlib\n[REMOVING] [ROOT]/foo/target/debug/deps/bar-[HASH].d\n[REMOVING] [ROOT]/foo/target/debug/deps/libbar-[HASH].rmeta\n\",\n    );\n    if cfg!(target_os = \"macos\") {\n        // Rust 1.69 has changed so that split-debuginfo=unpacked includes unpacked for rlibs.\n        for _ in p.glob(\"target/debug/deps/bar-*.o\") {\n            expected.push_str(\"[REMOVING] [ROOT]/foo/target/debug/deps/bar-[HASH][..].o\\n\");\n        }\n    }\n    expected.push_str(\"[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\\n\");\n    p.cargo(\"clean -p bar --verbose\")\n        .with_stderr_data(&expected.unordered())\n        .run();\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn clean_remove_rlib_rmeta() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    assert!(p.target_debug_dir().join(\"libfoo.rlib\").exists());\n    let rmeta = p.glob(\"target/debug/deps/*.rmeta\").next().unwrap().unwrap();\n    assert!(rmeta.exists());\n    p.cargo(\"clean -p foo\").run();\n    assert!(!p.target_debug_dir().join(\"libfoo.rlib\").exists());\n    assert!(!rmeta.exists());\n}\n\n#[cargo_test]\nfn package_cleans_all_the_things() {\n    // -p cleans everything\n    // Use dashes everywhere to make sure dash/underscore stuff is handled.\n    for crate_type in &[\"rlib\", \"dylib\", \"cdylib\", \"staticlib\", \"proc-macro\"] {\n        // Try each crate type individually since the behavior changes when\n        // they are combined.\n        let p = project()\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n                    [package]\n                    name = \"foo-bar\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [lib]\n                    crate-type = [\"{}\"]\n                    \"#,\n                    crate_type\n                ),\n            )\n            .file(\"src/lib.rs\", \"\")\n            .build();\n        p.cargo(\"build\").run();\n        p.cargo(\"clean -p foo-bar\").run();\n        assert_all_clean(&p.build_dir());\n    }\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo-bar\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [lib]\n            crate-type = [\"rlib\", \"dylib\", \"staticlib\"]\n\n            [[example]]\n            name = \"foo-ex-rlib\"\n            crate-type = [\"rlib\"]\n            test = true\n\n            [[example]]\n            name = \"foo-ex-cdylib\"\n            crate-type = [\"cdylib\"]\n            test = true\n\n            [[example]]\n            name = \"foo-ex-bin\"\n            test = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/lib/some-main.rs\", \"fn main() {}\")\n        .file(\"src/bin/other-main.rs\", \"fn main() {}\")\n        .file(\"examples/foo-ex-rlib.rs\", \"\")\n        .file(\"examples/foo-ex-cdylib.rs\", \"\")\n        .file(\"examples/foo-ex-bin.rs\", \"fn main() {}\")\n        .file(\"tests/foo-test.rs\", \"\")\n        .file(\"benches/foo-bench.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --all-targets\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .run();\n    p.cargo(\"test --all-targets\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .run();\n    p.cargo(\"check --all-targets\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .run();\n    p.cargo(\"clean -p foo-bar\").run();\n    assert_all_clean(&p.build_dir());\n\n    // Try some targets.\n    p.cargo(\"build --all-targets --target\")\n        .arg(rustc_host())\n        .run();\n    p.cargo(\"clean -p foo-bar --target\").arg(rustc_host()).run();\n    assert_all_clean(&p.build_dir());\n}\n\n// Ensures that all files for the package have been deleted.\n#[track_caller]\nfn assert_all_clean(build_dir: &Path) {\n    let walker = walkdir::WalkDir::new(build_dir).into_iter();\n    for entry in walker.filter_entry(|e| {\n        let path = e.path();\n        // This is a known limitation, clean can't differentiate between\n        // the different build scripts from different packages.\n        !(path\n            .file_name()\n            .unwrap()\n            .to_str()\n            .unwrap()\n            .starts_with(\"build_script_build\")\n            && path\n                .parent()\n                .unwrap()\n                .file_name()\n                .unwrap()\n                .to_str()\n                .unwrap()\n                == \"incremental\")\n    }) {\n        let entry = entry.unwrap();\n        let path = entry.path();\n        if let \".rustc_info.json\" | \".cargo-lock\" | \".cargo-build-lock\" | \"CACHEDIR.TAG\" =\n            path.file_name().unwrap().to_str().unwrap()\n        {\n            continue;\n        }\n        if path.is_symlink() || path.is_file() {\n            panic!(\"{:?} was not cleaned\", path);\n        }\n    }\n}\n\n#[cargo_test]\nfn clean_spec_version() {\n    // clean -p foo where foo matches multiple versions\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar1 = {version=\"0.1\", package=\"bar\"}\n            bar2 = {version=\"0.2\", package=\"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    // Check suggestion for bad pkgid.\n    p.cargo(\"clean -p baz\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `baz` did not match any packages\n\n[HELP] a package with a similar name exists: `bar`\n\n\"#]])\n        .run();\n\n    p.cargo(\"clean -p bar:0.1.0\")\n        .with_stderr_data(str![[r#\"\n[WARNING] version qualifier in `-p bar:0.1.0` is ignored, cleaning all versions of `bar` found\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    let mut walker = walkdir::WalkDir::new(p.build_dir())\n        .into_iter()\n        .filter_map(|e| e.ok())\n        .filter(|e| {\n            let n = e.file_name().to_str().unwrap();\n            n.starts_with(\"bar\") || n.starts_with(\"libbar\")\n        });\n    if let Some(e) = walker.next() {\n        panic!(\"{:?} was not cleaned\", e.path());\n    }\n}\n\n#[cargo_test]\nfn clean_spec_partial_version() {\n    // clean -p foo where foo matches multiple versions\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar1 = {version=\"0.1\", package=\"bar\"}\n            bar2 = {version=\"0.2\", package=\"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    // Check suggestion for bad pkgid.\n    p.cargo(\"clean -p baz\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `baz` did not match any packages\n\n[HELP] a package with a similar name exists: `bar`\n\n\"#]])\n        .run();\n\n    p.cargo(\"clean -p bar:0.1\")\n        .with_stderr_data(str![[r#\"\n[WARNING] version qualifier in `-p bar:0.1` is ignored, cleaning all versions of `bar` found\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    let mut walker = walkdir::WalkDir::new(p.build_dir())\n        .into_iter()\n        .filter_map(|e| e.ok())\n        .filter(|e| {\n            let n = e.file_name().to_str().unwrap();\n            n.starts_with(\"bar\") || n.starts_with(\"libbar\")\n        });\n    if let Some(e) = walker.next() {\n        panic!(\"{:?} was not cleaned\", e.path());\n    }\n}\n\n#[cargo_test]\nfn clean_spec_partial_version_ambiguous() {\n    // clean -p foo where foo matches multiple versions\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar1 = {version=\"0.1\", package=\"bar\"}\n            bar2 = {version=\"0.2\", package=\"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    // Check suggestion for bad pkgid.\n    p.cargo(\"clean -p baz\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `baz` did not match any packages\n\n[HELP] a package with a similar name exists: `bar`\n\n\"#]])\n        .run();\n\n    p.cargo(\"clean -p bar:0\")\n        .with_stderr_data(str![[r#\"\n[WARNING] version qualifier in `-p bar:0` is ignored, cleaning all versions of `bar` found\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    let mut walker = walkdir::WalkDir::new(p.build_dir())\n        .into_iter()\n        .filter_map(|e| e.ok())\n        .filter(|e| {\n            let n = e.file_name().to_str().unwrap();\n            n.starts_with(\"bar\") || n.starts_with(\"libbar\")\n        });\n    if let Some(e) = walker.next() {\n        panic!(\"{:?} was not cleaned\", e.path());\n    }\n}\n\n#[cargo_test]\nfn clean_spec_reserved() {\n    // Clean when a target (like a test) has a reserved name. In this case,\n    // make sure `clean -p` doesn't delete the reserved directory `build` when\n    // there is a test named `build`.\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"tests/build.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --all-targets\").run();\n    assert!(p.target_debug_dir().join(\"build\").is_dir());\n    let build_test = p.glob(\"target/debug/deps/build-*\").next().unwrap().unwrap();\n    assert!(build_test.exists());\n    // Tests are never \"uplifted\".\n    assert!(p.glob(\"target/debug/build-*\").next().is_none());\n\n    p.cargo(\"clean -p foo\").run();\n    // Should not delete this.\n    assert!(p.target_debug_dir().join(\"build\").is_dir());\n\n    // This should not rebuild bar.\n    p.cargo(\"build -v --all-targets\")\n        .with_stderr_data(str![[r#\"\n[FRESH] bar v1.0.0\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[RUNNING] `rustc [..]`\n[RUNNING] `rustc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn clean_dry_run() {\n    // Basic `clean --dry-run` test.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Start with no files.\n    p.cargo(\"clean --dry-run\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[SUMMARY] 0 files\n[WARNING] no files deleted due to --dry-run\n\n\"#]])\n        .run();\n    p.cargo(\"check\").run();\n    let before = p.build_dir().ls_r();\n    p.cargo(\"clean --dry-run\")\n        .with_stderr_data(str![[r#\"\n[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total\n[WARNING] no files deleted due to --dry-run\n\n\"#]])\n        .run();\n    // Verify it didn't delete anything.\n    let after = p.build_dir().ls_r();\n    assert_eq!(before, after);\n    let mut expected = itertools::join(before.iter().map(|p| p.to_str().unwrap()), \"\\n\");\n    expected.push_str(\"\\n\");\n    let expected = snapbox::filter::normalize_paths(&expected);\n    let expected = assert_e2e().redactions().redact(&expected);\n    eprintln!(\"{expected}\");\n    // Verify the verbose output.\n    p.cargo(\"clean --dry-run -v\")\n        .with_stdout_data(expected.unordered())\n        .with_stderr_data(str![[r#\"\n[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total\n[WARNING] no files deleted due to --dry-run\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_with_package_selection() {\n    // --doc with -p\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.cargo(\"clean --doc -p foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] --doc cannot be used with -p\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn quiet_does_not_show_summary() {\n    // Checks that --quiet works with `cargo clean`, since there was a\n    // subtle issue with how the flag is defined as a global flag.\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"clean --quiet --dry-run\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(\"\")\n        .run();\n    // Verify exact same command without -q would actually display something.\n    p.cargo(\"clean --dry-run\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total\n[WARNING] no files deleted due to --dry-run\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/clean_new_layout.rs",
    "content": "//! Tests for the `cargo clean` command.\n\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{\n    basic_bin_manifest, basic_manifest, git, main_file, project, project_in, rustc_host,\n};\nuse glob::GlobError;\nuse std::env;\nuse std::path::{Path, PathBuf};\n\n#[cargo_test]\nfn cargo_clean_simple() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    assert!(p.build_dir().is_dir());\n\n    p.cargo(\"clean\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    assert!(!p.build_dir().is_dir());\n}\n\n#[cargo_test]\nfn different_dir() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .file(\"src/bar/a.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    assert!(p.build_dir().is_dir());\n\n    p.cargo(\"clean\")\n        .cwd(\"src\")\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    assert!(!p.build_dir().is_dir());\n}\n\n#[cargo_test]\nfn clean_multiple_packages() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.d1]\n                    path = \"d1\"\n                [dependencies.d2]\n                    path = \"d2\"\n\n                [[bin]]\n                    name = \"foo\"\n            \"#,\n        )\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .file(\"d1/Cargo.toml\", &basic_bin_manifest(\"d1\"))\n        .file(\"d1/src/main.rs\", \"fn main() { println!(\\\"d1\\\"); }\")\n        .file(\"d2/Cargo.toml\", &basic_bin_manifest(\"d2\"))\n        .file(\"d2/src/main.rs\", \"fn main() { println!(\\\"d2\\\"); }\")\n        .build();\n\n    p.cargo(\"build -p d1 -p d2 -p foo\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    let d1_path = &p\n        .build_dir()\n        .join(\"debug\")\n        .join(format!(\"d1{}\", env::consts::EXE_SUFFIX));\n    let d2_path = &p\n        .build_dir()\n        .join(\"debug\")\n        .join(format!(\"d2{}\", env::consts::EXE_SUFFIX));\n\n    assert!(p.bin(\"foo\").is_file());\n    assert!(d1_path.is_file());\n    assert!(d2_path.is_file());\n\n    p.cargo(\"clean -p d1 -p d2\")\n        .cwd(\"src\")\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!d1_path.is_file());\n    assert!(!d2_path.is_file());\n}\n\n#[cargo_test]\nfn clean_multiple_packages_in_glob_char_path() {\n    let p = project_in(\"[d1]\")\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n    let foo_path = &p.build_dir().join(\"debug\").join(\"build\");\n\n    #[cfg(not(target_env = \"msvc\"))]\n    let file_glob = \"foo/*/out/foo*\";\n\n    #[cfg(target_env = \"msvc\")]\n    let file_glob = \"foo/*/out/foo.pdb\";\n\n    // Assert that build artifacts are produced\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    assert_ne!(get_build_artifacts(foo_path, file_glob).len(), 0);\n\n    // Assert that build artifacts are destroyed\n    p.cargo(\"clean -p foo\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    assert_eq!(get_build_artifacts(foo_path, file_glob).len(), 0);\n}\n\nfn get_build_artifacts(path: &PathBuf, file_glob: &str) -> Vec<Result<PathBuf, GlobError>> {\n    let pattern = path.to_str().expect(\"expected utf-8 path\");\n    let pattern = glob::Pattern::escape(pattern);\n\n    let path = PathBuf::from(pattern).join(file_glob);\n    let path = path.to_str().expect(\"expected utf-8 path\");\n    glob::glob(path)\n        .expect(\"expected glob to run\")\n        .into_iter()\n        .collect::<Vec<Result<PathBuf, GlobError>>>()\n}\n\n#[cargo_test]\nfn clean_p_only_cleans_specified_package() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\n                    \"foo\",\n                    \"foo_core\",\n                    \"foo-base\",\n                ]\n            \"#,\n        )\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"//! foo\")\n        .file(\"foo_core/Cargo.toml\", &basic_manifest(\"foo_core\", \"0.1.0\"))\n        .file(\"foo_core/src/lib.rs\", \"//! foo_core\")\n        .file(\"foo-base/Cargo.toml\", &basic_manifest(\"foo-base\", \"0.1.0\"))\n        .file(\"foo-base/src/lib.rs\", \"//! foo-base\")\n        .build();\n\n    let units_path = &p.build_dir().join(\"debug\").join(\"build\");\n\n    p.cargo(\"build -p foo -p foo_core -p foo-base\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    let mut fingerprint_names = get_fingerprints_without_hashes(units_path);\n\n    // Artifacts present for all after building\n    assert!(fingerprint_names.iter().any(|e| e == \"foo\"));\n    let num_foo_core_artifacts = fingerprint_names\n        .iter()\n        .filter(|&e| e == \"foo_core\")\n        .count();\n    assert_ne!(num_foo_core_artifacts, 0);\n    let num_foo_base_artifacts = fingerprint_names\n        .iter()\n        .filter(|&e| e == \"foo-base\")\n        .count();\n    assert_ne!(num_foo_base_artifacts, 0);\n\n    p.cargo(\"clean -p foo\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    fingerprint_names = get_fingerprints_without_hashes(units_path);\n\n    // Cleaning `foo` leaves artifacts for the others\n    assert!(!fingerprint_names.iter().any(|e| e == \"foo\"));\n    assert_eq!(\n        fingerprint_names\n            .iter()\n            .filter(|&e| e == \"foo_core\")\n            .count(),\n        num_foo_core_artifacts,\n    );\n    assert_eq!(\n        fingerprint_names\n            .iter()\n            .filter(|&e| e == \"foo-base\")\n            .count(),\n        num_foo_core_artifacts,\n    );\n}\n\nfn get_fingerprints_without_hashes(fingerprint_path: &Path) -> Vec<String> {\n    std::fs::read_dir(fingerprint_path)\n        .expect(\"Build dir should be readable\")\n        .filter_map(|entry| entry.ok())\n        .map(|entry| {\n            let name = entry.file_name();\n            name.into_string()\n                .expect(\"fingerprint name should be UTF-8\")\n        })\n        .collect()\n}\n\n#[cargo_test]\nfn clean_release() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --release\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    p.cargo(\"clean -p foo\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"build --release\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    p.cargo(\"clean -p foo --release\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"build --release\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    p.cargo(\"clean\")\n        .arg(\"--release\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    assert!(p.build_dir().is_dir());\n    assert!(p.build_dir().join(\"debug\").is_dir());\n    assert!(!p.build_dir().join(\"release\").is_dir());\n}\n\n#[cargo_test]\nfn clean_doc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    let doc_path = &p.build_dir().join(\"doc\");\n\n    assert!(doc_path.is_dir());\n\n    p.cargo(\"clean --doc\")\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    assert!(!doc_path.is_dir());\n    assert!(p.build_dir().is_dir());\n}\n\n#[cargo_test]\nfn build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::path::PathBuf;\n                use std::env;\n\n                fn main() {\n                    let out = PathBuf::from(env::var_os(\"OUT_DIR\").unwrap());\n                    if env::var(\"FIRST\").is_ok() {\n                        std::fs::File::create(out.join(\"out\")).unwrap();\n                    } else {\n                        assert!(!out.join(\"out\").exists());\n                    }\n                }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .env(\"FIRST\", \"1\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"clean -p foo\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] build.rs [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo/[HASH]/out/build-script-build`\n[RUNNING] `rustc [..] src/main.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n}\n\n#[cargo_test]\nfn clean_git() {\n    let git = git::new(\"dep\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    dep = {{ git = '{}' }}\n                \"#,\n                git.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"clean -p dep\")\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n}\n\n#[cargo_test]\nfn registry() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"clean -p bar\")\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n}\n\n#[cargo_test]\nfn clean_verbose() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"clean -p bar --verbose\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/foo/target/debug/build/bar\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n}\n\n#[cargo_test]\nfn clean_remove_rlib_rmeta() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    assert!(p.target_debug_dir().join(\"libfoo.rlib\").exists());\n    let rmeta = p\n        .glob(\"target/debug/build/*/*/out/*.rmeta\")\n        .next()\n        .unwrap()\n        .unwrap();\n    assert!(rmeta.exists());\n    p.cargo(\"clean -p foo\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    assert!(!p.target_debug_dir().join(\"libfoo.rlib\").exists());\n    assert!(!rmeta.exists());\n}\n\n#[cargo_test]\nfn package_cleans_all_the_things() {\n    // -p cleans everything\n    // Use dashes everywhere to make sure dash/underscore stuff is handled.\n    for crate_type in &[\"rlib\", \"dylib\", \"cdylib\", \"staticlib\", \"proc-macro\"] {\n        // Try each crate type individually since the behavior changes when\n        // they are combined.\n        let p = project()\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n                    [package]\n                    name = \"foo-bar\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [lib]\n                    crate-type = [\"{}\"]\n                    \"#,\n                    crate_type\n                ),\n            )\n            .file(\"src/lib.rs\", \"\")\n            .build();\n        p.cargo(\"build\")\n            .arg(\"-Zbuild-dir-new-layout\")\n            .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n            .run();\n        p.cargo(\"clean -p foo-bar\")\n            .arg(\"-Zbuild-dir-new-layout\")\n            .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n            .run();\n        assert_all_clean(&p.build_dir());\n    }\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo-bar\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [lib]\n            crate-type = [\"rlib\", \"dylib\", \"staticlib\"]\n\n            [[example]]\n            name = \"foo-ex-rlib\"\n            crate-type = [\"rlib\"]\n            test = true\n\n            [[example]]\n            name = \"foo-ex-cdylib\"\n            crate-type = [\"cdylib\"]\n            test = true\n\n            [[example]]\n            name = \"foo-ex-bin\"\n            test = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/lib/some-main.rs\", \"fn main() {}\")\n        .file(\"src/bin/other-main.rs\", \"fn main() {}\")\n        .file(\"examples/foo-ex-rlib.rs\", \"\")\n        .file(\"examples/foo-ex-cdylib.rs\", \"\")\n        .file(\"examples/foo-ex-bin.rs\", \"fn main() {}\")\n        .file(\"tests/foo-test.rs\", \"\")\n        .file(\"benches/foo-bench.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --all-targets\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"test --all-targets\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"check --all-targets\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"clean -p foo-bar\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    assert_all_clean(&p.build_dir());\n\n    // Try some targets.\n    p.cargo(\"build --all-targets --target\")\n        .arg(rustc_host())\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"clean -p foo-bar --target\")\n        .arg(rustc_host())\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    assert_all_clean(&p.build_dir());\n}\n\n// Ensures that all files for the package have been deleted.\n#[track_caller]\nfn assert_all_clean(build_dir: &Path) {\n    let walker = walkdir::WalkDir::new(build_dir).into_iter();\n    for entry in walker.filter_entry(|e| {\n        let path = e.path();\n        // This is a known limitation, clean can't differentiate between\n        // the different build scripts from different packages.\n        !(path\n            .file_name()\n            .unwrap()\n            .to_str()\n            .unwrap()\n            .starts_with(\"build_script_build\")\n            && path\n                .parent()\n                .unwrap()\n                .file_name()\n                .unwrap()\n                .to_str()\n                .unwrap()\n                == \"incremental\")\n    }) {\n        let entry = entry.unwrap();\n        let path = entry.path();\n        if let \".rustc_info.json\" | \".cargo-lock\" | \".cargo-build-lock\" | \"CACHEDIR.TAG\" =\n            path.file_name().unwrap().to_str().unwrap()\n        {\n            continue;\n        }\n        if path.is_symlink() || path.is_file() {\n            panic!(\"{:?} was not cleaned\", path);\n        }\n    }\n}\n\n#[cargo_test]\nfn clean_spec_version() {\n    // clean -p foo where foo matches multiple versions\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar1 = {version=\"0.1\", package=\"bar\"}\n            bar2 = {version=\"0.2\", package=\"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    // Check suggestion for bad pkgid.\n    p.cargo(\"clean -p baz\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `baz` did not match any packages\n\n[HELP] a package with a similar name exists: `bar`\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    p.cargo(\"clean -p bar:0.1.0\")\n        .with_stderr_data(str![[r#\"\n[WARNING] version qualifier in `-p bar:0.1.0` is ignored, cleaning all versions of `bar` found\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    let mut walker = walkdir::WalkDir::new(p.build_dir())\n        .into_iter()\n        .filter_map(|e| e.ok())\n        .filter(|e| {\n            let n = e.file_name().to_str().unwrap();\n            n.starts_with(\"bar\") || n.starts_with(\"libbar\")\n        });\n    if let Some(e) = walker.next() {\n        panic!(\"{:?} was not cleaned\", e.path());\n    }\n}\n\n#[cargo_test]\nfn clean_spec_partial_version() {\n    // clean -p foo where foo matches multiple versions\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar1 = {version=\"0.1\", package=\"bar\"}\n            bar2 = {version=\"0.2\", package=\"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    // Check suggestion for bad pkgid.\n    p.cargo(\"clean -p baz\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `baz` did not match any packages\n\n[HELP] a package with a similar name exists: `bar`\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    p.cargo(\"clean -p bar:0.1\")\n        .with_stderr_data(str![[r#\"\n[WARNING] version qualifier in `-p bar:0.1` is ignored, cleaning all versions of `bar` found\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    let mut walker = walkdir::WalkDir::new(p.build_dir())\n        .into_iter()\n        .filter_map(|e| e.ok())\n        .filter(|e| {\n            let n = e.file_name().to_str().unwrap();\n            n.starts_with(\"bar\") || n.starts_with(\"libbar\")\n        });\n    if let Some(e) = walker.next() {\n        panic!(\"{:?} was not cleaned\", e.path());\n    }\n}\n\n#[cargo_test]\nfn clean_spec_partial_version_ambiguous() {\n    // clean -p foo where foo matches multiple versions\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar1 = {version=\"0.1\", package=\"bar\"}\n            bar2 = {version=\"0.2\", package=\"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    // Check suggestion for bad pkgid.\n    p.cargo(\"clean -p baz\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `baz` did not match any packages\n\n[HELP] a package with a similar name exists: `bar`\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n\n    p.cargo(\"clean -p bar:0\")\n        .with_stderr_data(str![[r#\"\n[WARNING] version qualifier in `-p bar:0` is ignored, cleaning all versions of `bar` found\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    let mut walker = walkdir::WalkDir::new(p.build_dir())\n        .into_iter()\n        .filter_map(|e| e.ok())\n        .filter(|e| {\n            let n = e.file_name().to_str().unwrap();\n            n.starts_with(\"bar\") || n.starts_with(\"libbar\")\n        });\n    if let Some(e) = walker.next() {\n        panic!(\"{:?} was not cleaned\", e.path());\n    }\n}\n\n#[cargo_test]\nfn clean_spec_reserved() {\n    // Clean when a target (like a test) has a reserved name. In this case,\n    // make sure `clean -p` doesn't delete the reserved directory `build` when\n    // there is a test named `build`.\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"tests/build.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --all-targets\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    assert!(p.target_debug_dir().join(\"build\").is_dir());\n    let build_test = p\n        .glob(\"target/debug/build/*/*/out/build-*\")\n        .next()\n        .unwrap()\n        .unwrap();\n    assert!(build_test.exists());\n    // Tests are never \"uplifted\".\n    assert!(p.glob(\"target/debug/build-*\").next().is_none());\n\n    p.cargo(\"clean -p foo\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    // Should not delete this.\n    assert!(p.target_debug_dir().join(\"build\").is_dir());\n\n    // This should not rebuild bar.\n    p.cargo(\"build -v --all-targets\")\n        .with_stderr_data(str![[r#\"\n[FRESH] bar v1.0.0\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[RUNNING] `rustc [..]`\n[RUNNING] `rustc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n}\n\n#[cargo_test]\nfn clean_dry_run() {\n    // Basic `clean --dry-run` test.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Start with no files.\n    p.cargo(\"clean --dry-run\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[SUMMARY] 0 files\n[WARNING] no files deleted due to --dry-run\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"check\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    let before = p.build_dir().ls_r();\n    p.cargo(\"clean --dry-run\")\n        .with_stderr_data(str![[r#\"\n[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total\n[WARNING] no files deleted due to --dry-run\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    // Verify it didn't delete anything.\n    let after = p.build_dir().ls_r();\n    assert_eq!(before, after);\n    let mut expected = itertools::join(before.iter().map(|p| p.to_str().unwrap()), \"\\n\");\n    expected.push_str(\"\\n\");\n    let expected = snapbox::filter::normalize_paths(&expected);\n    let expected = assert_e2e().redactions().redact(&expected);\n    eprintln!(\"{expected}\");\n    // Verify the verbose output.\n    p.cargo(\"clean --dry-run -v\")\n        .with_stdout_data(expected.unordered())\n        .with_stderr_data(str![[r#\"\n[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total\n[WARNING] no files deleted due to --dry-run\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n}\n\n#[cargo_test]\nfn doc_with_package_selection() {\n    // --doc with -p\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.cargo(\"clean --doc -p foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] --doc cannot be used with -p\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n}\n\n#[cargo_test]\nfn quiet_does_not_show_summary() {\n    // Checks that --quiet works with `cargo clean`, since there was a\n    // subtle issue with how the flag is defined as a global flag.\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    p.cargo(\"clean --quiet --dry-run\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(\"\")\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n    // Verify exact same command without -q would actually display something.\n    p.cargo(\"clean --dry-run\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total\n[WARNING] no files deleted due to --dry-run\n\n\"#]])\n        .arg(\"-Zbuild-dir-new-layout\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/collisions.rs",
    "content": "//! Tests for when multiple artifacts have the same output filename.\n//! See <https://github.com/rust-lang/cargo/issues/6313> for more details.\n//! Ideally these should never happen, but I don't think we'll ever be able to\n//! prevent all collisions.\n\nuse crate::prelude::*;\nuse crate::utils::cross_compile::disabled as cross_compile_disabled;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_manifest, cross_compile, project};\nuse std::env;\n\n#[cargo_test]\nfn collision_dylib() {\n    // Path dependencies don't include metadata hash in filename for dylibs.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n\n            [lib]\n            crate-type = [\"dylib\"]\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n\n            [lib]\n            crate-type = [\"dylib\"]\n            name = \"a\"\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    // `j=1` is required because on Windows you'll get an error due to\n    // two processes writing to the file at the same time.\n    p.cargo(\"build -j=1\")\n        .with_stderr_data(&format!(\"\\\n...\n[WARNING] output filename collision at [ROOT]/foo/target/debug/deps/{}a{}\n  |\n  = [NOTE] the lib target `a` in package `b v1.0.0 ([ROOT]/foo/b)` has the same output filename as the lib target `a` in package `a v1.0.0 ([ROOT]/foo/a)`\n  = [NOTE] this may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>\n  = [HELP] consider changing their names to be unique or compiling them separately\n...\n\", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX))\n        .run();\n}\n\n#[cargo_test]\nfn collision_example() {\n    // Examples in a workspace can easily collide.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"1.0.0\"))\n        .file(\"a/examples/ex1.rs\", \"fn main() {}\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"1.0.0\"))\n        .file(\"b/examples/ex1.rs\", \"fn main() {}\")\n        .build();\n\n    // `j=1` is required because on Windows you'll get an error due to\n    // two processes writing to the file at the same time.\n    p.cargo(\"build --examples -j=1\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] output filename collision at [ROOT]/foo/target/debug/examples/ex1[EXE]\n  |\n  = [NOTE] the example target `ex1` in package `b v1.0.0 ([ROOT]/foo/b)` has the same output filename as the example target `ex1` in package `a v1.0.0 ([ROOT]/foo/a)`\n  = [NOTE] this may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>\n  = [HELP] consider changing their names to be unique or compiling them separately\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n// See https://github.com/rust-lang/cargo/issues/7493\n#[cfg_attr(\n    any(target_env = \"msvc\", target_vendor = \"apple\"),\n    ignore = \"--artifact-dir and examples are currently broken on MSVC and apple\"\n)]\nfn collision_export() {\n    // `--artifact-dir` combines some things which can cause conflicts.\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"examples/foo.rs\", \"fn main() {}\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // -j1 to avoid issues with two processes writing to the same file at the\n    // same time.\n    p.cargo(\"build -j1 --artifact-dir=out -Z unstable-options --bins --examples\")\n        .masquerade_as_nightly_cargo(&[\"artifact-dir\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `--artifact-dir` filename collision at [ROOT]/foo/out/foo[EXE]\n  |\n  = [NOTE] the example target `foo` in package `foo v1.0.0 ([ROOT]/foo)` has the same output filename as the bin target `foo` in package `foo v1.0.0 ([ROOT]/foo)`\n  = [NOTE] this may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>\n  = [HELP] consider changing their names to be unique or compiling them separately\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn collision_doc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            foo2 = { path = \"foo2\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"foo2/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo2\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [lib]\n            name = \"foo\"\n            \"#,\n        )\n        .file(\"foo2/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -j=1\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] output filename collision at [ROOT]/foo/target/doc/foo/index.html\n  |\n  = [NOTE] the lib target `foo` in package `foo2 v0.1.0 ([ROOT]/foo/foo2)` has the same output filename as the lib target `foo` in package `foo v0.1.0 ([ROOT]/foo)`\n  = [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn collision_doc_multiple_versions() {\n    // Multiple versions of the same package.\n    Package::new(\"old-dep\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\").dep(\"old-dep\", \"1.0\").publish();\n    // Note that this removes \"old-dep\". Just checking what happens when there\n    // are orphans.\n    Package::new(\"bar\", \"2.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n                bar2 = { package=\"bar\", version=\"2.0\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Should only document bar 2.0, should not document old-dep.\n    p.cargo(\"doc\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[ADDING] bar v1.0.0 (available: v2.0.0)\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v2.0.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] old-dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] old-dep v1.0.0\n[CHECKING] bar v2.0.0\n[CHECKING] bar v1.0.0\n[DOCUMENTING] bar v2.0.0\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo)\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn collision_doc_host_target_feature_split() {\n    // Same dependency built twice due to different features.\n    //\n    // foo v0.1.0\n    // ├── common v1.0.0\n    // │   └── common-dep v1.0.0\n    // └── pm v0.1.0 (proc-macro)\n    //     └── common v1.0.0\n    //         └── common-dep v1.0.0\n    // [build-dependencies]\n    // └── common-dep v1.0.0\n    //\n    // Here `common` and `common-dep` are built twice. `common-dep` has\n    // different features for host versus target.\n    Package::new(\"common-dep\", \"1.0.0\")\n        .feature(\"bdep-feat\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// Some doc\n                pub fn f() {}\n\n                /// Another doc\n                #[cfg(feature = \"bdep-feat\")]\n                pub fn bdep_func() {}\n            \"#,\n        )\n        .publish();\n    Package::new(\"common\", \"1.0.0\")\n        .dep(\"common-dep\", \"1.0\")\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// Some doc\n                pub fn f() {}\n            \"#,\n        )\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                resolver = \"2\"\n\n                [dependencies]\n                pm = { path = \"pm\" }\n                common = \"1.0\"\n\n                [build-dependencies]\n                common-dep = { version = \"1.0\", features = [\"bdep-feat\"] }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// Some doc\n                pub fn f() {}\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pm\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                common = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"pm/src/lib.rs\",\n            r#\"\n                use proc_macro::TokenStream;\n\n                /// Some doc\n                #[proc_macro]\n                pub fn pm(_input: TokenStream) -> TokenStream {\n                    \"\".parse().unwrap()\n                }\n            \"#,\n        )\n        .build();\n\n    // No warnings, no duplicates, common and common-dep only documented once.\n    p.cargo(\"doc\")\n        // Cannot check full output due to https://github.com/rust-lang/cargo/issues/9076\n        .with_stderr_does_not_contain(\"[WARNING][..]\")\n        .run();\n\n    assert!(p.build_dir().join(\"doc/common_dep/fn.f.html\").exists());\n    assert!(\n        !p.build_dir()\n            .join(\"doc/common_dep/fn.bdep_func.html\")\n            .exists()\n    );\n    assert!(p.build_dir().join(\"doc/common/fn.f.html\").exists());\n    assert!(p.build_dir().join(\"doc/pm/macro.pm.html\").exists());\n    assert!(p.build_dir().join(\"doc/foo/fn.f.html\").exists());\n}\n\n#[cargo_test]\nfn collision_doc_profile_split() {\n    // Same dependency built twice due to different profile settings.\n    Package::new(\"common\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                pm = { path = \"pm\" }\n                common = \"1.0\"\n\n                [profile.dev]\n                opt-level = 2\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pm\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                common = \"1.0\"\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\"pm/src/lib.rs\", \"\")\n        .build();\n\n    // Just to verify that common is normally built twice.\n    // This is unordered because in rare cases `pm` may start\n    // building in-between the two `common`.\n    p.cargo(\"build -v\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] common v1.0.0 (registry `dummy-registry`)\n[COMPILING] common v1.0.0\n[RUNNING] `rustc --crate-name common [..]\n[RUNNING] `rustc --crate-name common [..]\n[COMPILING] pm v0.1.0 ([ROOT]/foo/pm)\n[RUNNING] `rustc --crate-name pm [..]\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[FINISHED] `dev` profile [optimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    // Should only document common once, no warnings.\n    p.cargo(\"doc\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] common v1.0.0\n[DOCUMENTING] common v1.0.0\n[DOCUMENTING] pm v0.1.0 ([ROOT]/foo/pm)\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [optimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn collision_doc_sources() {\n    // Different sources with the same package.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n                bar2 = { path = \"bar\", package = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -j=1\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[WARNING] output filename collision at [ROOT]/foo/target/doc/bar/index.html\n  |\n  = [NOTE] the lib target `bar` in package `bar v1.0.0` has the same output filename as the lib target `bar` in package `bar v1.0.0 ([ROOT]/foo/bar)`\n  = [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>\n[CHECKING] bar v1.0.0 ([ROOT]/foo/bar)\n[DOCUMENTING] bar v1.0.0 ([ROOT]/foo/bar)\n[DOCUMENTING] bar v1.0.0\n[CHECKING] bar v1.0.0\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn collision_doc_target() {\n    // collision in doc with --target, doesn't fail due to orphans\n    if cross_compile_disabled() {\n        return;\n    }\n\n    Package::new(\"orphaned\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\")\n        .dep(\"orphaned\", \"1.0\")\n        .publish();\n    Package::new(\"bar\", \"2.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar2 = { version = \"2.0\", package=\"bar\" }\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc --target\")\n        .arg(cross_compile::alternate())\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[ADDING] bar v1.0.0 (available: v2.0.0)\n[DOWNLOADING] crates ...\n[DOWNLOADED] orphaned v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v2.0.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] orphaned v1.0.0\n[DOCUMENTING] bar v2.0.0\n[CHECKING] bar v2.0.0\n[CHECKING] bar v1.0.0\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/[ALT_TARGET]/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn collision_with_root() {\n    // Check for a doc collision between a root package and a dependency.\n    // In this case, `foo-macro` comes from both the workspace and crates.io.\n    // This checks that the duplicate correction code doesn't choke on this\n    // by removing the root unit.\n    Package::new(\"foo-macro\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"abc\", \"foo-macro\"]\n            \"#,\n        )\n        .file(\n            \"abc/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"abc\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                foo-macro = \"1.0\"\n            \"#,\n        )\n        .file(\"abc/src/lib.rs\", \"\")\n        .file(\n            \"foo-macro/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo-macro\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                abc = {path=\"../abc\"}\n            \"#,\n        )\n        .file(\"foo-macro/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -j=1\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo-macro v1.0.0 (registry `dummy-registry`)\n[WARNING] output filename collision at [ROOT]/foo/target/doc/foo_macro/index.html\n  |\n  = [NOTE] the lib target `foo_macro` in package `foo-macro v1.0.0` has the same output filename as the lib target `foo_macro` in package `foo-macro v1.0.0 ([ROOT]/foo/foo-macro)`\n  = [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>\n[CHECKING] foo-macro v1.0.0\n[DOCUMENTING] foo-macro v1.0.0\n[CHECKING] abc v1.0.0 ([ROOT]/foo/abc)\n[DOCUMENTING] foo-macro v1.0.0 ([ROOT]/foo/foo-macro)\n[DOCUMENTING] abc v1.0.0 ([ROOT]/foo/abc)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/abc/index.html and 1 other file\n\n\"#]].unordered())\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/compile_time_deps.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::{project, str};\n\n#[cargo_test]\nfn gated_by_unstable_opts() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .build();\n\n    p.cargo(\"check --compile-time-deps\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `--compile-time-deps` flag is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel\nSee https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels.\nSee https://github.com/rust-lang/cargo/issues/14434 for more information about the `--compile-time-deps` flag.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn non_comp_time_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [dependencies]\n                bar.path = \"bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    bar::bar();\n                }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", r#\"pub fn bar() {}\"#)\n        .build();\n\n    p.cargo(\"-Zunstable-options check --compile-time-deps\")\n        .masquerade_as_nightly_cargo(&[\"compile-time-deps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn proc_macro_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                resolver = \"2\"\n                members = [\"foo\", \"bar\", \"baz\"]\n\n                [workspace.dependencies]\n                bar.path = \"bar\"\n                baz.path = \"baz\"\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [dependencies]\n                bar.workspace = true\n            \"#,\n        )\n        .file(\n            \"foo/src/main.rs\",\n            r#\"\n                fn main() {\n                    bar::bar!();\n                }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                baz.workspace = true\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                extern crate proc_macro;\n\n                use proc_macro::TokenStream;\n\n                #[proc_macro]\n                pub fn bar(input: TokenStream) -> TokenStream {\n                    baz::baz();\n                    input\n                }\n            \"#,\n        )\n        .file(\n            \"bar/tests/simple.rs\",\n            r#\"\n                #[test]\n                fn test_bar() {\n                    let _x: bool = bar::bar!(true);\n                }\n            \"#,\n        )\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", r#\"pub fn baz() {}\"#)\n        .build();\n\n    p.cargo(\"-Zunstable-options check --package foo --compile-time-deps\")\n        .masquerade_as_nightly_cargo(&[\"compile-time-deps\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] baz v0.0.1 ([ROOT]/foo/baz)\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"clean\").run();\n\n    p.cargo(\"-Zunstable-options check --package bar --compile-time-deps\")\n        .masquerade_as_nightly_cargo(&[\"compile-time-deps\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"clean\").run();\n\n    p.cargo(\"-Zunstable-options check --package bar --all-targets --compile-time-deps\")\n        .masquerade_as_nightly_cargo(&[\"compile-time-deps\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] baz v0.0.1 ([ROOT]/foo/baz)\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [build-dependencies]\n                bar.path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() {}\"#)\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    bar::bar();\n                    std::fs::write(\"check-script-output\", \"build script run\").unwrap();\n                }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [dependencies]\n                baz.path = \"baz\"\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                pub fn bar() {\n                    baz::baz();\n                }\n            \"#,\n        )\n        .file(\n            \"bar/baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"bar/baz/src/lib.rs\", r#\"pub fn baz() {}\"#)\n        .build();\n\n    p.cargo(\"-Zunstable-options check --compile-time-deps\")\n        .masquerade_as_nightly_cargo(&[\"compile-time-deps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] baz v0.0.1 ([ROOT]/foo/bar/baz)\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert_eq!(p.read_file(\"check-script-output\"), \"build script run\");\n}\n\n#[cargo_test]\nfn indirect_comp_time_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [dependencies]\n                bar.path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() {}\"#)\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [build-dependencies]\n                baz.path = \"baz\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", r#\"pub fn bar() {}\"#)\n        .file(\n            \"bar/build.rs\",\n            r#\"\n                fn main() {\n                    baz::baz();\n                }\n            \"#,\n        )\n        .file(\n            \"bar/baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", r#\"pub fn baz() {}\"#)\n        .file(\n            \"bar/baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"bar/baz/src/lib.rs\", r#\"pub fn baz() {}\"#)\n        .build();\n\n    p.cargo(\"-Zunstable-options check --compile-time-deps\")\n        .masquerade_as_nightly_cargo(&[\"compile-time-deps\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] baz v0.0.1 ([ROOT]/foo/bar/baz)\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn tests_target() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [dev-dependencies]\n                bar.path = \"bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {}\n\n                #[test]\n                fn foo() {\n                    bar::bar!();\n                }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                extern crate proc_macro;\n\n                use proc_macro::TokenStream;\n\n                #[proc_macro]\n                pub fn bar(input: TokenStream) -> TokenStream {\n                    input\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"-Zunstable-options check --tests --compile-time-deps\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .masquerade_as_nightly_cargo(&[\"compile-time-deps\"])\n        .run();\n\n    p.cargo(\"clean\").run();\n\n    p.cargo(\"-Zunstable-options check --compile-time-deps\")\n        .masquerade_as_nightly_cargo(&[\"compile-time-deps\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/concurrent.rs",
    "content": "//! Tests for running multiple `cargo` processes at the same time.\n\nuse std::fs;\nuse std::net::TcpListener;\nuse std::process::Stdio;\nuse std::sync::mpsc::channel;\nuse std::thread;\nuse std::{env, str};\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::git;\nuse cargo_test_support::install::assert_has_installed_exe;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_manifest, execs, project, retry, sleep_ms, slow_cpu_multiplier};\n\nfn pkg(name: &str, vers: &str) {\n    Package::new(name, vers)\n        .file(\"src/main.rs\", \"fn main() {{}}\")\n        .publish();\n}\n\n#[cargo_test]\nfn multiple_installs() {\n    let p = project()\n        .no_manifest()\n        .file(\"a/Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"a/src/main.rs\", \"fn main() {}\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"b/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    let mut a = p.cargo(\"install\").cwd(\"a\").build_command();\n    let mut b = p.cargo(\"install\").cwd(\"b\").build_command();\n\n    a.stdout(Stdio::piped()).stderr(Stdio::piped());\n    b.stdout(Stdio::piped()).stderr(Stdio::piped());\n\n    let a = a.spawn().unwrap();\n    let b = b.spawn().unwrap();\n    let a = thread::spawn(move || a.wait_with_output().unwrap());\n    let b = b.wait_with_output().unwrap();\n    let a = a.join().unwrap();\n\n    execs().run_output(&a);\n    execs().run_output(&b);\n\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    assert_has_installed_exe(paths::cargo_home(), \"bar\");\n}\n\n#[cargo_test]\nfn concurrent_installs() {\n    const LOCKED_BUILD: &str = \"waiting for file lock on build directory\";\n\n    pkg(\"foo\", \"0.0.1\");\n    pkg(\"bar\", \"0.0.1\");\n\n    let mut a = cargo_process(\"install foo\").build_command();\n    let mut b = cargo_process(\"install bar\").build_command();\n\n    a.stdout(Stdio::piped()).stderr(Stdio::piped());\n    b.stdout(Stdio::piped()).stderr(Stdio::piped());\n\n    let a = a.spawn().unwrap();\n    let b = b.spawn().unwrap();\n    let a = thread::spawn(move || a.wait_with_output().unwrap());\n    let b = b.wait_with_output().unwrap();\n    let a = a.join().unwrap();\n\n    assert!(!str::from_utf8(&a.stderr).unwrap().contains(LOCKED_BUILD));\n    assert!(!str::from_utf8(&b.stderr).unwrap().contains(LOCKED_BUILD));\n\n    execs().run_output(&a);\n    execs().run_output(&b);\n\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    assert_has_installed_exe(paths::cargo_home(), \"bar\");\n}\n\n#[cargo_test]\nfn one_install_should_be_bad() {\n    let p = project()\n        .no_manifest()\n        .file(\"a/Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"a/src/main.rs\", \"fn main() {}\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"b/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    let mut a = p.cargo(\"install\").cwd(\"a\").build_command();\n    let mut b = p.cargo(\"install\").cwd(\"b\").build_command();\n\n    a.stdout(Stdio::piped()).stderr(Stdio::piped());\n    b.stdout(Stdio::piped()).stderr(Stdio::piped());\n\n    let a = a.spawn().unwrap();\n    let b = b.spawn().unwrap();\n    let a = thread::spawn(move || a.wait_with_output().unwrap());\n    let b = b.wait_with_output().unwrap();\n    let a = a.join().unwrap();\n\n    execs().run_output(&a);\n    execs().run_output(&b);\n\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn multiple_registry_fetches() {\n    let mut pkg = Package::new(\"bar\", \"1.0.2\");\n    for i in 0..10 {\n        let name = format!(\"foo{}\", i);\n        Package::new(&name, \"1.0.0\").publish();\n        pkg.dep(&name, \"*\");\n    }\n    pkg.publish();\n\n    let p = project()\n        .no_manifest()\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"a/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                authors = []\n                version = \"0.0.0\"\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"b/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    let mut a = p.cargo(\"build\").cwd(\"a\").build_command();\n    let mut b = p.cargo(\"build\").cwd(\"b\").build_command();\n\n    a.stdout(Stdio::piped()).stderr(Stdio::piped());\n    b.stdout(Stdio::piped()).stderr(Stdio::piped());\n\n    let a = a.spawn().unwrap();\n    let b = b.spawn().unwrap();\n    let a = thread::spawn(move || a.wait_with_output().unwrap());\n    let b = b.wait_with_output().unwrap();\n    let a = a.join().unwrap();\n\n    execs().run_output(&a);\n    execs().run_output(&b);\n\n    let suffix = env::consts::EXE_SUFFIX;\n    assert!(\n        p.root()\n            .join(\"a/target/debug\")\n            .join(format!(\"foo{}\", suffix))\n            .is_file()\n    );\n    assert!(\n        p.root()\n            .join(\"b/target/debug\")\n            .join(format!(\"bar{}\", suffix))\n            .is_file()\n    );\n}\n\n#[cargo_test]\nfn git_same_repo_different_tags() {\n    let a = git::new(\"dep\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"pub fn tag1() {}\")\n    });\n\n    let repo = git2::Repository::open(&a.root()).unwrap();\n    git::tag(&repo, \"tag1\");\n\n    a.change_file(\"src/lib.rs\", \"pub fn tag2() {}\");\n    git::add(&repo);\n    git::commit(&repo);\n    git::tag(&repo, \"tag2\");\n\n    let p = project()\n        .no_manifest()\n        .file(\n            \"a/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    authors = []\n                    version = \"0.0.0\"\n\n                    [dependencies]\n                    dep = {{ git = '{}', tag = 'tag1' }}\n                \"#,\n                a.url()\n            ),\n        )\n        .file(\n            \"a/src/main.rs\",\n            \"extern crate dep; fn main() { dep::tag1(); }\",\n        )\n        .file(\n            \"b/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"bar\"\n                    authors = []\n                    version = \"0.0.0\"\n\n                    [dependencies]\n                    dep = {{ git = '{}', tag = 'tag2' }}\n                \"#,\n                a.url()\n            ),\n        )\n        .file(\n            \"b/src/main.rs\",\n            \"extern crate dep; fn main() { dep::tag2(); }\",\n        );\n    let p = p.build();\n\n    let mut a = p.cargo(\"build -v\").cwd(\"a\").build_command();\n    let mut b = p.cargo(\"build -v\").cwd(\"b\").build_command();\n\n    a.stdout(Stdio::piped()).stderr(Stdio::piped());\n    b.stdout(Stdio::piped()).stderr(Stdio::piped());\n\n    let a = a.spawn().unwrap();\n    let b = b.spawn().unwrap();\n    let a = thread::spawn(move || a.wait_with_output().unwrap());\n    let b = b.wait_with_output().unwrap();\n    let a = a.join().unwrap();\n\n    execs().run_output(&a);\n    execs().run_output(&b);\n}\n\n#[cargo_test]\nfn git_same_branch_different_revs() {\n    let a = git::new(\"dep\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"pub fn f1() {}\")\n    });\n\n    let p = project()\n        .no_manifest()\n        .file(\n            \"a/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    authors = []\n                    version = \"0.0.0\"\n\n                    [dependencies]\n                    dep = {{ git = '{}' }}\n                \"#,\n                a.url()\n            ),\n        )\n        .file(\n            \"a/src/main.rs\",\n            \"extern crate dep; fn main() { dep::f1(); }\",\n        )\n        .file(\n            \"b/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"bar\"\n                    authors = []\n                    version = \"0.0.0\"\n\n                    [dependencies]\n                    dep = {{ git = '{}' }}\n                \"#,\n                a.url()\n            ),\n        )\n        .file(\n            \"b/src/main.rs\",\n            \"extern crate dep; fn main() { dep::f2(); }\",\n        );\n    let p = p.build();\n\n    // Generate a Cargo.lock pointing at the current rev, then clear out the\n    // target directory\n    p.cargo(\"build\").cwd(\"a\").run();\n    fs::remove_dir_all(p.root().join(\"a/target\")).unwrap();\n\n    // Make a new commit on the master branch\n    let repo = git2::Repository::open(&a.root()).unwrap();\n    a.change_file(\"src/lib.rs\", \"pub fn f2() {}\");\n    git::add(&repo);\n    git::commit(&repo);\n\n    // Now run both builds in parallel. The build of `b` should pick up the\n    // newest commit while the build of `a` should use the locked old commit.\n    let mut a = p.cargo(\"build\").cwd(\"a\").build_command();\n    let mut b = p.cargo(\"build\").cwd(\"b\").build_command();\n\n    a.stdout(Stdio::piped()).stderr(Stdio::piped());\n    b.stdout(Stdio::piped()).stderr(Stdio::piped());\n\n    let a = a.spawn().unwrap();\n    let b = b.spawn().unwrap();\n    let a = thread::spawn(move || a.wait_with_output().unwrap());\n    let b = b.wait_with_output().unwrap();\n    let a = a.join().unwrap();\n\n    execs().run_output(&a);\n    execs().run_output(&b);\n}\n\n#[cargo_test]\nfn same_project() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\");\n    let p = p.build();\n\n    let mut a = p.cargo(\"build\").build_command();\n    let mut b = p.cargo(\"build\").build_command();\n\n    a.stdout(Stdio::piped()).stderr(Stdio::piped());\n    b.stdout(Stdio::piped()).stderr(Stdio::piped());\n\n    let a = a.spawn().unwrap();\n    let b = b.spawn().unwrap();\n    let a = thread::spawn(move || a.wait_with_output().unwrap());\n    let b = b.wait_with_output().unwrap();\n    let a = a.join().unwrap();\n\n    execs().run_output(&a);\n    execs().run_output(&b);\n}\n\n// Make sure that if Cargo dies while holding a lock that it's released and the\n// next Cargo to come in will take over cleanly.\n#[cargo_test]\nfn killing_cargo_releases_the_lock() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::net::TcpStream;\n\n                fn main() {\n                    if std::env::var(\"A\").is_ok() {\n                        TcpStream::connect(&std::env::var(\"ADDR\").unwrap()[..])\n                                  .unwrap();\n                        std::thread::sleep(std::time::Duration::new(10, 0));\n                    }\n                }\n            \"#,\n        );\n    let p = p.build();\n\n    // Our build script will connect to our local TCP socket to inform us that\n    // it's started  and that's how we know that `a` will have the lock\n    // when we kill it.\n    let l = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let mut a = p.cargo(\"build\").build_command();\n    let mut b = p.cargo(\"build\").build_command();\n    a.stdout(Stdio::piped()).stderr(Stdio::piped());\n    b.stdout(Stdio::piped()).stderr(Stdio::piped());\n    a.env(\"ADDR\", l.local_addr().unwrap().to_string())\n        .env(\"A\", \"a\");\n    b.env(\"ADDR\", l.local_addr().unwrap().to_string())\n        .env_remove(\"A\");\n\n    // Spawn `a`, wait for it to get to the build script (at which point the\n    // lock is held), then kill it.\n    let mut a = a.spawn().unwrap();\n    l.accept().unwrap();\n    a.kill().unwrap();\n\n    // Spawn `b`, then just finish the output of a/b the same way the above\n    // tests does.\n    let b = b.spawn().unwrap();\n    let a = thread::spawn(move || a.wait_with_output().unwrap());\n    let b = b.wait_with_output().unwrap();\n    let a = a.join().unwrap();\n\n    // We killed `a`, so it shouldn't succeed, but `b` should have succeeded.\n    assert!(!a.status.success());\n    execs().run_output(&b);\n}\n\n#[cargo_test]\nfn debug_release_ok() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"build\").run();\n    fs::remove_dir_all(p.root().join(\"target\")).unwrap();\n\n    let mut a = p.cargo(\"build\").build_command();\n    let mut b = p.cargo(\"build --release\").build_command();\n    a.stdout(Stdio::piped()).stderr(Stdio::piped());\n    b.stdout(Stdio::piped()).stderr(Stdio::piped());\n    let a = a.spawn().unwrap();\n    let b = b.spawn().unwrap();\n    let a = thread::spawn(move || a.wait_with_output().unwrap());\n    let b = b.wait_with_output().unwrap();\n    let a = a.join().unwrap();\n\n    execs()\n        .with_stderr_data(str![[r#\"\n...\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run_output(&a);\n    execs()\n        .with_stderr_data(str![[r#\"\n...\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run_output(&b);\n}\n\n#[cargo_test]\nfn no_deadlock_with_git_dependencies() {\n    let dep1 = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let dep2 = git::new(\"dep2\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep2\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    authors = []\n                    version = \"0.0.0\"\n\n                    [dependencies]\n                    dep1 = {{ git = '{}' }}\n                    dep2 = {{ git = '{}' }}\n                \"#,\n                dep1.url(),\n                dep2.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() { }\");\n    let p = p.build();\n\n    let n_concurrent_builds = 5;\n\n    let (tx, rx) = channel();\n    for _ in 0..n_concurrent_builds {\n        let cmd = p\n            .cargo(\"build\")\n            .build_command()\n            .stdout(Stdio::piped())\n            .stderr(Stdio::piped())\n            .spawn();\n        let tx = tx.clone();\n        thread::spawn(move || {\n            let result = cmd.unwrap().wait_with_output().unwrap();\n            tx.send(result).unwrap()\n        });\n    }\n\n    for _ in 0..n_concurrent_builds {\n        let result = rx.recv_timeout(slow_cpu_multiplier(30)).expect(\"Deadlock!\");\n        execs().run_output(&result);\n    }\n}\n\n#[cargo_test]\nfn verbose_file_lock_blocking() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2024\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    let blocking = std::env::var(\"BLOCKING\").unwrap_or_default();\n                    if blocking == \"1\" {\n                        std::fs::write(\"blocking\", \"\").unwrap();\n                        let path = std::path::Path::new(\"ready\");\n                        loop {\n                            if path.exists() {\n                                break;\n                            } else {\n                                std::thread::sleep(std::time::Duration::from_millis(100))\n                            }\n                        }\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    // start a build that will hold the lock on the build directory\n    let mut a = p\n        .cargo(\"check\")\n        .build_command()\n        .stdout(Stdio::piped())\n        .stderr(Stdio::piped())\n        .env(\"BLOCKING\", \"1\")\n        .spawn()\n        .unwrap();\n\n    // wait for the build script to start\n    retry(100, || p.root().join(\"blocking\").exists().then_some(()));\n\n    let blocked_p = p\n        .cargo(\"check -vv\")\n        .build_command()\n        .stdout(Stdio::piped())\n        .stderr(Stdio::piped())\n        .env(\"BLOCKING\", \"0\")\n        .spawn()\n        .unwrap();\n\n    sleep_ms(500);\n\n    // release the lock on the build directory\n    std::fs::write(p.root().join(\"ready\"), \"\").unwrap();\n\n    let blocked_p_otpt = blocked_p.wait_with_output().unwrap();\n\n    assert!(a.wait().unwrap().success());\n    execs()\n        .with_stderr_contains(\"[BLOCKING] waiting for file lock on build directory ([ROOT]/foo/target/debug/.cargo-build-lock)\")\n        .run_output(&blocked_p_otpt);\n}\n"
  },
  {
    "path": "tests/testsuite/config.rs",
    "content": "//! Tests for config settings.\n\nuse std::borrow::Borrow;\nuse std::collections::{BTreeMap, HashMap};\nuse std::fs;\nuse std::io;\nuse std::os;\nuse std::path::{Path, PathBuf};\n\nuse crate::prelude::*;\nuse cargo::CargoResult;\nuse cargo::core::features::{GitFeatures, GitoxideFeatures};\nuse cargo::core::{PackageIdSpec, Shell};\nuse cargo::util::auth::RegistryConfig;\nuse cargo::util::context::Value;\nuse cargo::util::context::{\n    self, Definition, GlobalContext, JobsConfig, SslVersionConfig, StringList,\n};\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::str;\nuse cargo_test_support::{paths, project, project_in_home, symlink_supported, t};\nuse cargo_util_schemas::manifest::TomlTrimPaths;\nuse cargo_util_schemas::manifest::TomlTrimPathsValue;\nuse cargo_util_schemas::manifest::{self as cargo_toml, TomlDebugInfo, VecStringOrBool as VSOB};\nuse serde::Deserialize;\n\n/// Helper for constructing a `GlobalContext` object.\npub struct GlobalContextBuilder {\n    env: HashMap<String, String>,\n    unstable: Vec<String>,\n    config_args: Vec<String>,\n    cwd: Option<PathBuf>,\n    root: Option<PathBuf>,\n    enable_nightly_features: bool,\n}\n\nimpl GlobalContextBuilder {\n    pub fn new() -> GlobalContextBuilder {\n        GlobalContextBuilder {\n            env: HashMap::new(),\n            unstable: Vec::new(),\n            config_args: Vec::new(),\n            root: None,\n            cwd: None,\n            enable_nightly_features: false,\n        }\n    }\n\n    /// Passes a `-Z` flag.\n    pub fn unstable_flag(&mut self, s: impl Into<String>) -> &mut Self {\n        self.unstable.push(s.into());\n        self\n    }\n\n    /// Sets an environment variable.\n    pub fn env(&mut self, key: impl Into<String>, val: impl Into<String>) -> &mut Self {\n        self.env.insert(key.into(), val.into());\n        self\n    }\n\n    /// Unconditionally enable nightly features, even on stable channels.\n    pub fn nightly_features_allowed(&mut self, allowed: bool) -> &mut Self {\n        self.enable_nightly_features = allowed;\n        self\n    }\n\n    /// Passes a `--config` flag.\n    pub fn config_arg(&mut self, arg: impl Into<String>) -> &mut Self {\n        self.config_args.push(arg.into());\n        self\n    }\n\n    /// Sets the current working directory where config files will be loaded.\n    ///\n    /// Default is the root from [`GlobalContextBuilder::root`] or [`paths::root`].\n    pub fn cwd(&mut self, path: impl AsRef<Path>) -> &mut Self {\n        let path = path.as_ref();\n        let cwd = self\n            .root\n            .as_ref()\n            .map_or_else(|| paths::root().join(path), |r| r.join(path));\n        self.cwd = Some(cwd);\n        self\n    }\n\n    /// Sets the test root directory.\n    ///\n    /// This generally should not be necessary. It is only useful if you want\n    /// to create a [`GlobalContext`] from within a thread. Since Cargo's\n    /// testsuite uses thread-local storage, this can be used to avoid accessing\n    /// that thread-local storage.\n    ///\n    /// Default is [`paths::root`].\n    pub fn root(&mut self, path: impl Into<PathBuf>) -> &mut Self {\n        self.root = Some(path.into());\n        self\n    }\n\n    /// Creates the [`GlobalContext`].\n    pub fn build(&self) -> GlobalContext {\n        self.build_err().unwrap()\n    }\n\n    /// Creates the [`GlobalContext`], returning a Result.\n    pub fn build_err(&self) -> CargoResult<GlobalContext> {\n        let root = self.root.clone().unwrap_or_else(|| paths::root());\n        let output = Box::new(fs::File::create(root.join(\"shell.out\")).unwrap());\n        let shell = Shell::from_write(output);\n        let cwd = self.cwd.clone().unwrap_or_else(|| root.clone());\n        let homedir = root.join(\"home\").join(\".cargo\");\n        let mut gctx = GlobalContext::new(shell, cwd, homedir);\n        gctx.nightly_features_allowed = self.enable_nightly_features || !self.unstable.is_empty();\n        gctx.set_env(self.env.clone());\n        gctx.set_search_stop_path(&root);\n        gctx.configure(\n            0,\n            false,\n            None,\n            false,\n            false,\n            false,\n            &None,\n            &self.unstable,\n            &self.config_args,\n        )?;\n        Ok(gctx)\n    }\n}\n\nfn new_gctx() -> GlobalContext {\n    GlobalContextBuilder::new().build()\n}\n\n/// Read the output from Config.\npub fn read_output(gctx: GlobalContext) -> String {\n    drop(gctx); // Paranoid about flushing the file.\n    let path = paths::root().join(\"shell.out\");\n    fs::read_to_string(path).unwrap()\n}\n\n#[cargo_test]\nfn read_env_vars_for_config() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                fn main() {\n                    assert_eq!(env::var(\"NUM_JOBS\").unwrap(), \"100\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\").env(\"CARGO_BUILD_JOBS\", \"100\").run();\n}\n\npub fn write_config_extless(config: &str) {\n    write_config_at(paths::root().join(\".cargo/config\"), config);\n}\n\npub fn write_config_at(path: impl AsRef<Path>, contents: &str) {\n    let path = paths::root().join(path.as_ref());\n    fs::create_dir_all(path.parent().unwrap()).unwrap();\n    fs::write(path, contents).unwrap();\n}\n\npub fn write_config_toml(config: &str) {\n    write_config_at(paths::root().join(\".cargo/config.toml\"), config);\n}\n\n#[cfg(unix)]\nfn symlink_file(target: &Path, link: &Path) -> io::Result<()> {\n    os::unix::fs::symlink(target, link)\n}\n\n#[cfg(windows)]\nfn symlink_file(target: &Path, link: &Path) -> io::Result<()> {\n    os::windows::fs::symlink_file(target, link)\n}\n\nfn make_config_symlink_to_config_toml_absolute() {\n    let toml_path = paths::root().join(\".cargo/config.toml\");\n    let symlink_path = paths::root().join(\".cargo/config\");\n    t!(symlink_file(&toml_path, &symlink_path));\n}\n\nfn make_config_symlink_to_config_toml_relative() {\n    let symlink_path = paths::root().join(\".cargo/config\");\n    t!(symlink_file(Path::new(\"config.toml\"), &symlink_path));\n}\n\nfn rename_config_toml_to_config_replacing_with_symlink() {\n    let root = paths::root();\n    t!(fs::rename(\n        root.join(\".cargo/config.toml\"),\n        root.join(\".cargo/config\")\n    ));\n    t!(symlink_file(\n        Path::new(\"config\"),\n        &root.join(\".cargo/config.toml\")\n    ));\n}\n\n#[track_caller]\npub fn assert_error<E: Borrow<anyhow::Error>>(error: E, msgs: impl IntoData) {\n    let causes = error\n        .borrow()\n        .chain()\n        .enumerate()\n        .map(|(i, e)| {\n            if i == 0 {\n                e.to_string()\n            } else {\n                format!(\"Caused by:\\n  {}\", e)\n            }\n        })\n        .collect::<Vec<_>>()\n        .join(\"\\n\\n\");\n    assert_e2e().eq(&causes, msgs);\n}\n\n#[cargo_test]\nfn get_config() {\n    write_config_toml(\n        \"\\\n[S]\nf1 = 123\n\",\n    );\n\n    let gctx = new_gctx();\n\n    #[derive(Debug, Deserialize, Eq, PartialEq)]\n    struct S {\n        f1: Option<i64>,\n    }\n    let s: S = gctx.get(\"S\").unwrap();\n    assert_eq!(s, S { f1: Some(123) });\n    let gctx = GlobalContextBuilder::new().env(\"CARGO_S_F1\", \"456\").build();\n    let s: S = gctx.get(\"S\").unwrap();\n    assert_eq!(s, S { f1: Some(456) });\n}\n\n#[cfg(windows)]\n#[cargo_test]\nfn environment_variable_casing() {\n    // Issue #11814: Environment variable names are case-insensitive on Windows.\n    let gctx = GlobalContextBuilder::new()\n        .env(\"Path\", \"abc\")\n        .env(\"Two-Words\", \"abc\")\n        .env(\"two_words\", \"def\")\n        .build();\n\n    let var = gctx.get_env(\"PATH\").unwrap();\n    assert_eq!(var, String::from(\"abc\"));\n\n    let var = gctx.get_env(\"path\").unwrap();\n    assert_eq!(var, String::from(\"abc\"));\n\n    let var = gctx.get_env(\"TWO-WORDS\").unwrap();\n    assert_eq!(var, String::from(\"abc\"));\n\n    // Make sure that we can still distinguish between dashes and underscores\n    // in variable names.\n    let var = gctx.get_env(\"Two_Words\").unwrap();\n    assert_eq!(var, String::from(\"def\"));\n}\n\n#[cargo_test]\nfn config_works_without_extension() {\n    write_config_extless(\n        \"\\\n[foo]\nf1 = 1\n\",\n    );\n\n    let gctx = new_gctx();\n\n    assert_eq!(gctx.get::<Option<i32>>(\"foo.f1\").unwrap(), Some(1));\n\n    // It should NOT have warned for the symlink.\n    let output = read_output(gctx);\n    let expected = str![[r#\"\n[WARNING] `[ROOT]/.cargo/config` is deprecated in favor of `config.toml`\n  |\n  = [HELP] if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`\n\n\"#]];\n    assert_e2e().eq(&output, expected);\n}\n\n#[cargo_test]\nfn home_config_works_without_extension() {\n    write_config_at(\n        paths::cargo_home().join(\"config\"),\n        \"\\\n[foo]\nf1 = 1\n\",\n    );\n    let p = project_in_home(\"foo\").file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"-vV\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `[ROOT]/home/.cargo/config` is deprecated in favor of `config.toml`\n  |\n  = [HELP] if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn config_ambiguous_filename_symlink_doesnt_warn() {\n    // Windows requires special permissions to create symlinks.\n    // If we don't have permission, just skip this test.\n    if !symlink_supported() {\n        return;\n    };\n\n    write_config_toml(\n        \"\\\n[foo]\nf1 = 1\n\",\n    );\n\n    make_config_symlink_to_config_toml_absolute();\n\n    let gctx = new_gctx();\n\n    assert_eq!(gctx.get::<Option<i32>>(\"foo.f1\").unwrap(), Some(1));\n\n    // It should NOT have warned for the symlink.\n    let output = read_output(gctx);\n    assert_e2e().eq(&output, str![[\"\"]]);\n}\n\n#[cargo_test]\nfn config_ambiguous_filename_symlink_doesnt_warn_relative() {\n    // Windows requires special permissions to create symlinks.\n    // If we don't have permission, just skip this test.\n    if !symlink_supported() {\n        return;\n    };\n\n    write_config_toml(\n        \"\\\n[foo]\nf1 = 1\n\",\n    );\n\n    make_config_symlink_to_config_toml_relative();\n\n    let gctx = new_gctx();\n\n    assert_eq!(gctx.get::<Option<i32>>(\"foo.f1\").unwrap(), Some(1));\n\n    // It should NOT have warned for the symlink.\n    let output = read_output(gctx);\n    assert_e2e().eq(&output, str![[\"\"]]);\n}\n\n#[cargo_test]\nfn config_ambiguous_filename_symlink_doesnt_warn_backward() {\n    // Windows requires special permissions to create symlinks.\n    // If we don't have permission, just skip this test.\n    if !symlink_supported() {\n        return;\n    };\n\n    write_config_toml(\n        \"\\\n[foo]\nf1 = 1\n\",\n    );\n\n    rename_config_toml_to_config_replacing_with_symlink();\n\n    let gctx = new_gctx();\n\n    assert_eq!(gctx.get::<Option<i32>>(\"foo.f1\").unwrap(), Some(1));\n\n    // It should NOT have warned for this situation.\n    let output = read_output(gctx);\n    assert_e2e().eq(&output, str![[\"\"]]);\n}\n\n#[cargo_test]\nfn config_ambiguous_filename() {\n    write_config_extless(\n        \"\\\n[foo]\nf1 = 1\n\",\n    );\n\n    write_config_toml(\n        \"\\\n[foo]\nf1 = 2\n\",\n    );\n\n    let gctx = new_gctx();\n\n    // It should use the value from the one without the extension for\n    // backwards compatibility.\n    assert_eq!(gctx.get::<Option<i32>>(\"foo.f1\").unwrap(), Some(1));\n\n    // But it also should have warned.\n    let output = read_output(gctx);\n    let expected = str![[r#\"\n[WARNING] both `[ROOT]/.cargo/config` and `[ROOT]/.cargo/config.toml` exist. Using `[ROOT]/.cargo/config`\n\n\"#]];\n    assert_e2e().eq(&output, expected);\n}\n\n#[cargo_test]\nfn config_unused_fields() {\n    write_config_toml(\n        \"\\\n[S]\nunused = 456\n\",\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_S_UNUSED2\", \"1\")\n        .env(\"CARGO_S2_UNUSED\", \"2\")\n        .build();\n\n    #[derive(Debug, Deserialize, Eq, PartialEq)]\n    struct S {\n        f1: Option<i64>,\n    }\n    // This prints a warning (verified below).\n    let s: S = gctx.get(\"S\").unwrap();\n    assert_eq!(s, S { f1: None });\n    // This does not print anything, we cannot easily/reliably warn for\n    // environment variables.\n    let s: S = gctx.get(\"S2\").unwrap();\n    assert_eq!(s, S { f1: None });\n\n    // Verify the warnings.\n    let output = read_output(gctx);\n    let expected = str![[r#\"\n[WARNING] unused config key `S.unused` in `[ROOT]/.cargo/config.toml`\n\n\"#]];\n    assert_e2e().eq(&output, expected);\n}\n\n#[cargo_test]\nfn config_load_toml_profile() {\n    write_config_toml(\n        \"\\\n[profile.dev]\nopt-level = 's'\nlto = true\ncodegen-units=4\ndebug = true\ndebug-assertions = true\nrpath = true\npanic = 'abort'\noverflow-checks = true\nincremental = true\n\n[profile.dev.build-override]\nopt-level = 1\n\n[profile.dev.package.bar]\ncodegen-units = 9\n\n[profile.no-lto]\ninherits = 'dev'\ndir-name = 'without-lto'\nlto = false\n\",\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .unstable_flag(\"advanced-env\")\n        .env(\"CARGO_PROFILE_DEV_CODEGEN_UNITS\", \"5\")\n        .env(\"CARGO_PROFILE_DEV_BUILD_OVERRIDE_CODEGEN_UNITS\", \"11\")\n        .env(\"CARGO_PROFILE_DEV_PACKAGE_env_CODEGEN_UNITS\", \"13\")\n        .env(\"CARGO_PROFILE_DEV_PACKAGE_bar_OPT_LEVEL\", \"2\")\n        .build();\n\n    // TODO: don't use actual `tomlprofile`.\n    let p: cargo_toml::TomlProfile = gctx.get(\"profile.dev\").unwrap();\n    let mut packages = BTreeMap::new();\n    let key =\n        cargo_toml::ProfilePackageSpec::Spec(::cargo::core::PackageIdSpec::parse(\"bar\").unwrap());\n    let o_profile = cargo_toml::TomlProfile {\n        opt_level: Some(cargo_toml::TomlOptLevel(\"2\".to_string())),\n        codegen_units: Some(9),\n        ..Default::default()\n    };\n    packages.insert(key, o_profile);\n    let key =\n        cargo_toml::ProfilePackageSpec::Spec(::cargo::core::PackageIdSpec::parse(\"env\").unwrap());\n    let o_profile = cargo_toml::TomlProfile {\n        codegen_units: Some(13),\n        ..Default::default()\n    };\n    packages.insert(key, o_profile);\n\n    assert_eq!(\n        p,\n        cargo_toml::TomlProfile {\n            opt_level: Some(cargo_toml::TomlOptLevel(\"s\".to_string())),\n            lto: Some(cargo_toml::StringOrBool::Bool(true)),\n            codegen_units: Some(5),\n            debug: Some(cargo_toml::TomlDebugInfo::Full),\n            debug_assertions: Some(true),\n            rpath: Some(true),\n            panic: Some(\"abort\".to_string()),\n            overflow_checks: Some(true),\n            incremental: Some(true),\n            package: Some(packages),\n            build_override: Some(Box::new(cargo_toml::TomlProfile {\n                opt_level: Some(cargo_toml::TomlOptLevel(\"1\".to_string())),\n                codegen_units: Some(11),\n                ..Default::default()\n            })),\n            ..Default::default()\n        }\n    );\n\n    let p: cargo_toml::TomlProfile = gctx.get(\"profile.no-lto\").unwrap();\n    assert_eq!(\n        p,\n        cargo_toml::TomlProfile {\n            lto: Some(cargo_toml::StringOrBool::Bool(false)),\n            dir_name: Some(String::from(\"without-lto\")),\n            inherits: Some(String::from(\"dev\")),\n            ..Default::default()\n        }\n    );\n}\n\n#[cargo_test]\nfn profile_env_var_prefix() {\n    // Check for a bug with collision on DEBUG vs DEBUG_ASSERTIONS.\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_PROFILE_DEV_DEBUG_ASSERTIONS\", \"false\")\n        .build();\n    let p: cargo_toml::TomlProfile = gctx.get(\"profile.dev\").unwrap();\n    assert_eq!(p.debug_assertions, Some(false));\n    assert_eq!(p.debug, None);\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_PROFILE_DEV_DEBUG\", \"1\")\n        .build();\n    let p: cargo_toml::TomlProfile = gctx.get(\"profile.dev\").unwrap();\n    assert_eq!(p.debug_assertions, None);\n    assert_eq!(p.debug, Some(cargo_toml::TomlDebugInfo::Limited));\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_PROFILE_DEV_DEBUG_ASSERTIONS\", \"false\")\n        .env(\"CARGO_PROFILE_DEV_DEBUG\", \"1\")\n        .build();\n    let p: cargo_toml::TomlProfile = gctx.get(\"profile.dev\").unwrap();\n    assert_eq!(p.debug_assertions, Some(false));\n    assert_eq!(p.debug, Some(cargo_toml::TomlDebugInfo::Limited));\n}\n\n#[cargo_test]\nfn config_deserialize_any() {\n    // Some tests to exercise deserialize_any for deserializers that need to\n    // be told the format.\n    write_config_toml(\n        \"\\\na = true\nb = ['b']\nc = ['c']\n\",\n    );\n\n    // advanced-env\n    let gctx = GlobalContextBuilder::new()\n        .unstable_flag(\"advanced-env\")\n        .env(\"CARGO_ENVB\", \"false\")\n        .env(\"CARGO_C\", \"['d']\")\n        .env(\"CARGO_ENVL\", \"['a', 'b']\")\n        .build();\n    assert_eq!(gctx.get::<VSOB>(\"a\").unwrap(), VSOB::Bool(true));\n    assert_eq!(\n        gctx.get::<VSOB>(\"b\").unwrap(),\n        VSOB::VecString(vec![\"b\".to_string()])\n    );\n    assert_eq!(\n        gctx.get::<VSOB>(\"c\").unwrap(),\n        VSOB::VecString(vec![\"c\".to_string(), \"d\".to_string()])\n    );\n    assert_eq!(gctx.get::<VSOB>(\"envb\").unwrap(), VSOB::Bool(false));\n    assert_eq!(\n        gctx.get::<VSOB>(\"envl\").unwrap(),\n        VSOB::VecString(vec![\"a\".to_string(), \"b\".to_string()])\n    );\n\n    // Demonstrate where merging logic isn't very smart. This could be improved.\n    let gctx = GlobalContextBuilder::new().env(\"CARGO_A\", \"x y\").build();\n    assert_error(\n        gctx.get::<VSOB>(\"a\").unwrap_err(),\n        str![[r#\"\nerror in environment variable `CARGO_A`: could not load config key `a`\n\nCaused by:\n  invalid type: string \"x y\", expected a boolean or vector of strings\n\"#]],\n    );\n\n    // Normal env.\n    let gctx = GlobalContextBuilder::new()\n        .unstable_flag(\"advanced-env\")\n        .env(\"CARGO_B\", \"d e\")\n        .env(\"CARGO_C\", \"f g\")\n        .build();\n    assert_eq!(\n        gctx.get::<VSOB>(\"b\").unwrap(),\n        VSOB::VecString(vec![\"b\".to_string(), \"d\".to_string(), \"e\".to_string()])\n    );\n    assert_eq!(\n        gctx.get::<VSOB>(\"c\").unwrap(),\n        VSOB::VecString(vec![\"c\".to_string(), \"f\".to_string(), \"g\".to_string()])\n    );\n\n    // config-cli\n    // This test demonstrates that ConfigValue::merge isn't very smart.\n    // It would be nice if it was smarter.\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"a = ['a']\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![[r#\"\nfailed to merge key `a` between [ROOT]/.cargo/config.toml and --config cli option\n\nCaused by:\n  failed to merge config value from `--config cli option` into `[ROOT]/.cargo/config.toml`: expected boolean, but found array\n\"#]],\n    );\n\n    // config-cli and advanced-env\n    let gctx = GlobalContextBuilder::new()\n        .unstable_flag(\"advanced-env\")\n        .config_arg(\"b=['clib']\")\n        .config_arg(\"c=['clic']\")\n        .env(\"CARGO_B\", \"env1 env2\")\n        .env(\"CARGO_C\", \"['e1', 'e2']\")\n        .build();\n    assert_eq!(\n        gctx.get::<VSOB>(\"b\").unwrap(),\n        VSOB::VecString(vec![\n            \"b\".to_string(),\n            \"env1\".to_string(),\n            \"env2\".to_string(),\n            \"clib\".to_string(),\n        ])\n    );\n    assert_eq!(\n        gctx.get::<VSOB>(\"c\").unwrap(),\n        VSOB::VecString(vec![\n            \"c\".to_string(),\n            \"e1\".to_string(),\n            \"e2\".to_string(),\n            \"clic\".to_string(),\n        ])\n    );\n}\n\n#[cargo_test]\nfn config_toml_errors() {\n    write_config_toml(\n        \"\\\n[profile.dev]\nopt-level = 'foo'\n\",\n    );\n\n    let gctx = new_gctx();\n\n    assert_error(\n        gctx.get::<cargo_toml::TomlProfile>(\"profile.dev\")\n            .unwrap_err(),\n        str![[r#\"\nerror in [ROOT]/.cargo/config.toml: could not load config key `profile.dev.opt-level`\n\nCaused by:\n  must be `0`, `1`, `2`, `3`, `s` or `z`, but found the string: \"foo\"\n\"#]],\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_PROFILE_DEV_OPT_LEVEL\", \"asdf\")\n        .build();\n\n    assert_error(\n        gctx.get::<cargo_toml::TomlProfile>(\"profile.dev\")\n            .unwrap_err(),\n        str![[r#\"\nerror in environment variable `CARGO_PROFILE_DEV_OPT_LEVEL`: could not load config key `profile.dev.opt-level`\n\nCaused by:\n  must be `0`, `1`, `2`, `3`, `s` or `z`, but found the string: \"asdf\"\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn load_nested() {\n    write_config_toml(\n        \"\\\n[nest.foo]\nf1 = 1\nf2 = 2\n[nest.bar]\nasdf = 3\n\",\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .unstable_flag(\"advanced-env\")\n        .env(\"CARGO_NEST_foo_f2\", \"3\")\n        .env(\"CARGO_NESTE_foo_f1\", \"1\")\n        .env(\"CARGO_NESTE_foo_f2\", \"3\")\n        .env(\"CARGO_NESTE_bar_asdf\", \"3\")\n        .build();\n\n    type Nested = HashMap<String, HashMap<String, u8>>;\n\n    let n: Nested = gctx.get(\"nest\").unwrap();\n    let mut expected = HashMap::new();\n    let mut foo = HashMap::new();\n    foo.insert(\"f1\".to_string(), 1);\n    foo.insert(\"f2\".to_string(), 3);\n    expected.insert(\"foo\".to_string(), foo);\n    let mut bar = HashMap::new();\n    bar.insert(\"asdf\".to_string(), 3);\n    expected.insert(\"bar\".to_string(), bar);\n    assert_eq!(n, expected);\n\n    let n: Nested = gctx.get(\"neste\").unwrap();\n    assert_eq!(n, expected);\n}\n\n#[cargo_test]\nfn get_errors() {\n    write_config_toml(\n        \"\\\n[S]\nf1 = 123\nf2 = 'asdf'\nbig = 123456789\n\",\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_E_S\", \"asdf\")\n        .env(\"CARGO_E_BIG\", \"123456789\")\n        .build();\n    assert_error(\n        gctx.get::<i64>(\"foo\").unwrap_err(),\n        str![\"missing config key `foo`\"],\n    );\n    assert_error(\n        gctx.get::<i64>(\"foo.bar\").unwrap_err(),\n        str![\"missing config key `foo.bar`\"],\n    );\n    assert_error(\n        gctx.get::<i64>(\"S.f2\").unwrap_err(),\n        str![\"error in [ROOT]/.cargo/config.toml: `S.f2` expected an integer, but found a string\"],\n    );\n    assert_error(\n        gctx.get::<u8>(\"S.big\").unwrap_err(),\n        str![[r#\"\nerror in [ROOT]/.cargo/config.toml: could not load config key `S.big`\n\nCaused by:\n  invalid value: integer `123456789`, expected u8\n\"#]],\n    );\n\n    // Environment variable type errors.\n    assert_error(\n        gctx.get::<i64>(\"e.s\").unwrap_err(),\n        str![\"error in environment variable `CARGO_E_S`: invalid digit found in string\"],\n    );\n    assert_error(\n        gctx.get::<i8>(\"e.big\").unwrap_err(),\n        str![[r#\"\nerror in environment variable `CARGO_E_BIG`: could not load config key `e.big`\n\nCaused by:\n  invalid value: integer `123456789`, expected i8\n\"#]],\n    );\n\n    #[derive(Debug, Deserialize)]\n    #[allow(dead_code)]\n    struct S {\n        f1: i64,\n        f2: String,\n        f3: i64,\n        big: i64,\n    }\n    assert_error(gctx.get::<S>(\"S\").unwrap_err(), str![\"missing field `f3`\"]);\n}\n\n#[cargo_test]\nfn config_get_option() {\n    write_config_toml(\n        \"\\\n[foo]\nf1 = 1\n\",\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_BAR_ASDF\", \"3\")\n        .build();\n\n    assert_eq!(gctx.get::<Option<i32>>(\"a\").unwrap(), None);\n    assert_eq!(gctx.get::<Option<i32>>(\"a.b\").unwrap(), None);\n    assert_eq!(gctx.get::<Option<i32>>(\"foo.f1\").unwrap(), Some(1));\n    assert_eq!(gctx.get::<Option<i32>>(\"bar.asdf\").unwrap(), Some(3));\n    assert_eq!(gctx.get::<Option<i32>>(\"bar.zzzz\").unwrap(), None);\n}\n\n#[cargo_test]\nfn config_bad_toml() {\n    write_config_toml(\"asdf\");\n    let gctx = new_gctx();\n    assert_error(\n        gctx.get::<i32>(\"foo\").unwrap_err(),\n        str![[r#\"\ncould not load Cargo configuration\n\nCaused by:\n  could not parse TOML configuration in `[ROOT]/.cargo/config.toml`\n\nCaused by:\n  TOML parse error at line 1, column 5\n  |\n1 | asdf\n  |     ^\nkey with no value, expected `=`\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn config_get_list() {\n    write_config_toml(\n        \"\\\nl1 = []\nl2 = ['one', 'two']\nl3 = 123\nl4 = ['one', 'two']\n\n[nested]\nl = ['x']\n\n[nested2]\nl = ['y']\n\n[nested-empty]\n\",\n    );\n\n    type L = Vec<String>;\n\n    let gctx = GlobalContextBuilder::new()\n        .unstable_flag(\"advanced-env\")\n        .env(\"CARGO_L4\", \"['three', 'four']\")\n        .env(\"CARGO_L5\", \"['a']\")\n        .env(\"CARGO_ENV_EMPTY\", \"[]\")\n        .env(\"CARGO_ENV_BLANK\", \"\")\n        .env(\"CARGO_ENV_NUM\", \"1\")\n        .env(\"CARGO_ENV_NUM_LIST\", \"[1]\")\n        .env(\"CARGO_ENV_TEXT\", \"asdf\")\n        .env(\"CARGO_LEPAIR\", \"['a', 'b']\")\n        .env(\"CARGO_NESTED2_L\", \"['z']\")\n        .env(\"CARGO_NESTEDE_L\", \"['env']\")\n        .env(\"CARGO_BAD_ENV\", \"[zzz]\")\n        .build();\n\n    assert_eq!(gctx.get::<L>(\"unset\").unwrap(), vec![] as Vec<String>);\n    assert_eq!(gctx.get::<L>(\"l1\").unwrap(), vec![] as Vec<String>);\n    assert_eq!(gctx.get::<L>(\"l2\").unwrap(), vec![\"one\", \"two\"]);\n    assert_error(\n        gctx.get::<L>(\"l3\").unwrap_err(),\n        str![[r#\"\ninvalid configuration for key `l3`\nexpected a list, but found a integer for `l3` in [ROOT]/.cargo/config.toml\n\"#]],\n    );\n    assert_eq!(\n        gctx.get::<L>(\"l4\").unwrap(),\n        vec![\"one\", \"two\", \"three\", \"four\"]\n    );\n    assert_eq!(gctx.get::<L>(\"l5\").unwrap(), vec![\"a\"]);\n    assert_eq!(gctx.get::<L>(\"env-empty\").unwrap(), vec![] as Vec<String>);\n    assert_eq!(gctx.get::<L>(\"env-blank\").unwrap(), vec![] as Vec<String>);\n    assert_eq!(gctx.get::<L>(\"env-num\").unwrap(), vec![\"1\".to_string()]);\n    assert_error(\n        gctx.get::<L>(\"env-num-list\").unwrap_err(),\n        str![\"error in environment variable `CARGO_ENV_NUM_LIST`: expected string, found integer\"],\n    );\n    assert_eq!(gctx.get::<L>(\"env-text\").unwrap(), vec![\"asdf\".to_string()]);\n    // \"invalid number\" here isn't the best error, but I think it's just toml.rs.\n    assert_error(\n        gctx.get::<L>(\"bad-env\").unwrap_err(),\n        str![[r#\"\nerror in environment variable `CARGO_BAD_ENV`: could not parse TOML list: TOML parse error at line 1, column 2\n  |\n1 | [zzz]\n  |  ^^^\nstring values must be quoted, expected literal string\n\n\"#]],\n    );\n\n    // Try some other sequence-like types.\n    assert_eq!(\n        gctx.get::<(String, String, String, String)>(\"l4\").unwrap(),\n        (\n            \"one\".to_string(),\n            \"two\".to_string(),\n            \"three\".to_string(),\n            \"four\".to_string()\n        )\n    );\n    assert_eq!(gctx.get::<(String,)>(\"l5\").unwrap(), (\"a\".to_string(),));\n\n    // Tuple struct\n    #[derive(Debug, Deserialize, Eq, PartialEq)]\n    struct TupS(String, String);\n    assert_eq!(\n        gctx.get::<TupS>(\"lepair\").unwrap(),\n        TupS(\"a\".to_string(), \"b\".to_string())\n    );\n\n    // Nested with an option.\n    #[derive(Debug, Deserialize, Eq, PartialEq)]\n    struct S {\n        l: Option<Vec<String>>,\n    }\n    assert_eq!(gctx.get::<S>(\"nested-empty\").unwrap(), S { l: None });\n    assert_eq!(\n        gctx.get::<S>(\"nested\").unwrap(),\n        S {\n            l: Some(vec![\"x\".to_string()]),\n        }\n    );\n    assert_eq!(\n        gctx.get::<S>(\"nested2\").unwrap(),\n        S {\n            l: Some(vec![\"y\".to_string(), \"z\".to_string()]),\n        }\n    );\n    assert_eq!(\n        gctx.get::<S>(\"nestede\").unwrap(),\n        S {\n            l: Some(vec![\"env\".to_string()]),\n        }\n    );\n}\n\n#[cargo_test]\nfn config_get_other_types() {\n    write_config_toml(\n        \"\\\nns = 123\nns2 = 456\n\",\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_NSE\", \"987\")\n        .env(\"CARGO_NS2\", \"654\")\n        .build();\n\n    #[derive(Debug, Deserialize, Eq, PartialEq)]\n    #[serde(transparent)]\n    struct NewS(i32);\n    assert_eq!(gctx.get::<NewS>(\"ns\").unwrap(), NewS(123));\n    assert_eq!(gctx.get::<NewS>(\"ns2\").unwrap(), NewS(654));\n    assert_eq!(gctx.get::<NewS>(\"nse\").unwrap(), NewS(987));\n    assert_error(\n        gctx.get::<NewS>(\"unset\").unwrap_err(),\n        str![\"missing config key `unset`\"],\n    );\n}\n\n#[cargo_test]\nfn config_relative_path() {\n    write_config_toml(&format!(\n        \"\\\np1 = 'foo/bar'\np2 = '../abc'\np3 = 'b/c'\nabs = '{}'\n\",\n        paths::home().display(),\n    ));\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_EPATH\", \"a/b\")\n        .env(\"CARGO_P3\", \"d/e\")\n        .build();\n\n    assert_eq!(\n        gctx.get::<context::ConfigRelativePath>(\"p1\")\n            .unwrap()\n            .resolve_path(&gctx),\n        paths::root().join(\"foo/bar\")\n    );\n    assert_eq!(\n        gctx.get::<context::ConfigRelativePath>(\"p2\")\n            .unwrap()\n            .resolve_path(&gctx),\n        paths::root().join(\"../abc\")\n    );\n    assert_eq!(\n        gctx.get::<context::ConfigRelativePath>(\"p3\")\n            .unwrap()\n            .resolve_path(&gctx),\n        paths::root().join(\"d/e\")\n    );\n    assert_eq!(\n        gctx.get::<context::ConfigRelativePath>(\"abs\")\n            .unwrap()\n            .resolve_path(&gctx),\n        paths::home()\n    );\n    assert_eq!(\n        gctx.get::<context::ConfigRelativePath>(\"epath\")\n            .unwrap()\n            .resolve_path(&gctx),\n        paths::root().join(\"a/b\")\n    );\n}\n\n#[cargo_test]\nfn config_get_integers() {\n    write_config_toml(\n        \"\\\nnpos = 123456789\nnneg = -123456789\ni64max = 9223372036854775807\n\",\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_EPOS\", \"123456789\")\n        .env(\"CARGO_ENEG\", \"-1\")\n        .env(\"CARGO_EI64MAX\", \"9223372036854775807\")\n        .build();\n\n    assert_eq!(\n        gctx.get::<u64>(\"i64max\").unwrap(),\n        9_223_372_036_854_775_807\n    );\n    assert_eq!(\n        gctx.get::<i64>(\"i64max\").unwrap(),\n        9_223_372_036_854_775_807\n    );\n    assert_eq!(\n        gctx.get::<u64>(\"ei64max\").unwrap(),\n        9_223_372_036_854_775_807\n    );\n    assert_eq!(\n        gctx.get::<i64>(\"ei64max\").unwrap(),\n        9_223_372_036_854_775_807\n    );\n\n    assert_error(\n        gctx.get::<u32>(\"nneg\").unwrap_err(),\n        str![[r#\"\nerror in [ROOT]/.cargo/config.toml: could not load config key `nneg`\n\nCaused by:\n  invalid value: integer `-123456789`, expected u32\n\"#]],\n    );\n    assert_error(\n        gctx.get::<u32>(\"eneg\").unwrap_err(),\n        str![[r#\"\nerror in environment variable `CARGO_ENEG`: could not load config key `eneg`\n\nCaused by:\n  invalid value: integer `-1`, expected u32\n\"#]],\n    );\n    assert_error(\n        gctx.get::<i8>(\"npos\").unwrap_err(),\n        str![[r#\"\nerror in [ROOT]/.cargo/config.toml: could not load config key `npos`\n\nCaused by:\n  invalid value: integer `123456789`, expected i8\n\"#]],\n    );\n    assert_error(\n        gctx.get::<i8>(\"epos\").unwrap_err(),\n        str![[r#\"\nerror in environment variable `CARGO_EPOS`: could not load config key `epos`\n\nCaused by:\n  invalid value: integer `123456789`, expected i8\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn config_get_ssl_version_missing() {\n    write_config_toml(\n        \"\\\n[http]\nhello = 'world'\n\",\n    );\n\n    let gctx = new_gctx();\n\n    assert!(\n        gctx.get::<Option<SslVersionConfig>>(\"http.ssl-version\")\n            .unwrap()\n            .is_none()\n    );\n}\n\n#[cargo_test]\nfn config_get_ssl_version_single() {\n    write_config_toml(\n        \"\\\n[http]\nssl-version = 'tlsv1.2'\n\",\n    );\n\n    let gctx = new_gctx();\n\n    let a = gctx\n        .get::<Option<SslVersionConfig>>(\"http.ssl-version\")\n        .unwrap()\n        .unwrap();\n    match a {\n        SslVersionConfig::Single(v) => assert_eq!(&v, \"tlsv1.2\"),\n        SslVersionConfig::Range(_) => panic!(\"Did not expect ssl version min/max.\"),\n    };\n}\n\n#[cargo_test]\nfn config_get_ssl_version_min_max() {\n    write_config_toml(\n        \"\\\n[http]\nssl-version.min = 'tlsv1.2'\nssl-version.max = 'tlsv1.3'\n\",\n    );\n\n    let gctx = new_gctx();\n\n    let a = gctx\n        .get::<Option<SslVersionConfig>>(\"http.ssl-version\")\n        .unwrap()\n        .unwrap();\n    match a {\n        SslVersionConfig::Single(_) => panic!(\"Did not expect exact ssl version.\"),\n        SslVersionConfig::Range(range) => {\n            assert_eq!(range.min, Some(String::from(\"tlsv1.2\")));\n            assert_eq!(range.max, Some(String::from(\"tlsv1.3\")));\n        }\n    };\n}\n\n#[cargo_test]\nfn config_get_ssl_version_both_forms_configured() {\n    // this is not allowed\n    write_config_toml(\n        \"\\\n[http]\nssl-version = 'tlsv1.1'\nssl-version.min = 'tlsv1.2'\nssl-version.max = 'tlsv1.3'\n\",\n    );\n\n    let gctx = new_gctx();\n\n    assert_error(\n        gctx.get::<SslVersionConfig>(\"http.ssl-version\")\n            .unwrap_err(),\n        str![[r#\"\ncould not load Cargo configuration\n\nCaused by:\n  could not parse TOML configuration in `[ROOT]/.cargo/config.toml`\n\nCaused by:\n  TOML parse error at line 3, column 1\n  |\n3 | ssl-version.min = 'tlsv1.2'\n  | ^^^^^^^^^^^\ncannot extend value of type string with a dotted key\n\n\"#]],\n    );\n}\n\n#[cargo_test]\n/// Assert that unstable options can be configured with the `unstable` table in\n/// cargo config files\nfn unstable_table_notation() {\n    write_config_toml(\n        \"\\\n[unstable]\nprint-im-a-teapot = true\n\",\n    );\n    let gctx = GlobalContextBuilder::new()\n        .nightly_features_allowed(true)\n        .build();\n    assert_eq!(gctx.cli_unstable().print_im_a_teapot, true);\n}\n\n#[cargo_test]\n/// Assert that dotted notation works for configuring unstable options\nfn unstable_dotted_notation() {\n    write_config_toml(\n        \"\\\nunstable.print-im-a-teapot = true\n\",\n    );\n    let gctx = GlobalContextBuilder::new()\n        .nightly_features_allowed(true)\n        .build();\n    assert_eq!(gctx.cli_unstable().print_im_a_teapot, true);\n}\n\n#[cargo_test]\n/// Assert that Zflags on the CLI take precedence over those from config\nfn unstable_cli_precedence() {\n    write_config_toml(\n        \"\\\nunstable.print-im-a-teapot = true\n\",\n    );\n    let gctx = GlobalContextBuilder::new()\n        .nightly_features_allowed(true)\n        .build();\n    assert_eq!(gctx.cli_unstable().print_im_a_teapot, true);\n\n    let gctx = GlobalContextBuilder::new()\n        .unstable_flag(\"print-im-a-teapot=no\")\n        .build();\n    assert_eq!(gctx.cli_unstable().print_im_a_teapot, false);\n}\n\n#[cargo_test]\n/// Assert that attempting to set an unstable flag that doesn't exist via config\n/// is ignored on stable\nfn unstable_invalid_flag_ignored_on_stable() {\n    write_config_toml(\n        \"\\\nunstable.an-invalid-flag = 'yes'\n\",\n    );\n    assert!(GlobalContextBuilder::new().build_err().is_ok());\n}\n\n#[cargo_test]\n/// Assert that unstable options can be configured with the `unstable` table in\n/// cargo config files\nfn unstable_flags_ignored_on_stable() {\n    write_config_toml(\n        \"\\\n[unstable]\nprint-im-a-teapot = true\n\",\n    );\n    // Enforce stable channel even when testing on nightly.\n    let gctx = GlobalContextBuilder::new()\n        .nightly_features_allowed(false)\n        .build();\n    assert_eq!(gctx.cli_unstable().print_im_a_teapot, false);\n}\n\n#[cargo_test]\nfn table_merge_failure() {\n    // Config::merge fails to merge entries in two tables.\n    write_config_at(\n        \"foo/.cargo/config.toml\",\n        \"\n        [table]\n        key = ['foo']\n        \",\n    );\n    write_config_at(\n        \".cargo/config.toml\",\n        \"\n        [table]\n        key = 'bar'\n        \",\n    );\n\n    #[derive(Debug, Deserialize)]\n    #[allow(dead_code)]\n    struct Table {\n        key: StringList,\n    }\n    let gctx = GlobalContextBuilder::new().cwd(\"foo\").build();\n    assert_error(\n        gctx.get::<Table>(\"table\").unwrap_err(),\n        str![[r#\"\ncould not load Cargo configuration\n\nCaused by:\n  failed to merge configuration at `[ROOT]/.cargo/config.toml`\n\nCaused by:\n  failed to merge key `table` between [ROOT]/foo/.cargo/config.toml and [ROOT]/.cargo/config.toml\n\nCaused by:\n  failed to merge key `key` between [ROOT]/foo/.cargo/config.toml and [ROOT]/.cargo/config.toml\n\nCaused by:\n  failed to merge config value from `[ROOT]/.cargo/config.toml` into `[ROOT]/foo/.cargo/config.toml`: expected array, but found string\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn struct_with_opt_inner_struct() {\n    // Struct with a key that is Option of another struct.\n    // Check that can be defined with environment variable.\n    #[derive(Deserialize)]\n    struct Inner {\n        value: Option<i32>,\n    }\n    #[derive(Deserialize)]\n    struct Foo {\n        inner: Option<Inner>,\n    }\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_FOO_INNER_VALUE\", \"12\")\n        .build();\n    let f: Foo = gctx.get(\"foo\").unwrap();\n    assert_eq!(f.inner.unwrap().value.unwrap(), 12);\n}\n\n#[cargo_test]\nfn struct_with_default_inner_struct() {\n    // Struct with serde defaults.\n    // Check that can be defined with environment variable.\n    #[derive(Deserialize, Default)]\n    #[serde(default)]\n    struct Inner {\n        value: i32,\n    }\n    #[derive(Deserialize, Default)]\n    #[serde(default)]\n    struct Foo {\n        inner: Inner,\n    }\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_FOO_INNER_VALUE\", \"12\")\n        .build();\n    let f: Foo = gctx.get(\"foo\").unwrap();\n    assert_eq!(f.inner.value, 12);\n}\n\n#[cargo_test]\nfn overlapping_env_config() {\n    // Issue where one key is a prefix of another.\n    #[derive(Deserialize)]\n    #[serde(rename_all = \"kebab-case\")]\n    struct Ambig {\n        debug: Option<u32>,\n        debug_assertions: Option<bool>,\n    }\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_AMBIG_DEBUG_ASSERTIONS\", \"true\")\n        .build();\n\n    let s: Ambig = gctx.get(\"ambig\").unwrap();\n    assert_eq!(s.debug_assertions, Some(true));\n    assert_eq!(s.debug, None);\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_AMBIG_DEBUG\", \"0\")\n        .build();\n    let s: Ambig = gctx.get(\"ambig\").unwrap();\n    assert_eq!(s.debug_assertions, None);\n    assert_eq!(s.debug, Some(0));\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_AMBIG_DEBUG\", \"1\")\n        .env(\"CARGO_AMBIG_DEBUG_ASSERTIONS\", \"true\")\n        .build();\n    let s: Ambig = gctx.get(\"ambig\").unwrap();\n    assert_eq!(s.debug_assertions, Some(true));\n    assert_eq!(s.debug, Some(1));\n}\n\n#[cargo_test]\nfn overlapping_env_with_defaults_errors_out() {\n    // Issue where one key is a prefix of another.\n    // This is a limitation of mapping environment variables on to a hierarchy.\n    // Check that we error out when we hit ambiguity in this way, rather than\n    // the more-surprising defaulting through.\n    // If, in the future, we can handle this more correctly, feel free to delete\n    // this test.\n    #[derive(Deserialize, Default)]\n    #[serde(default, rename_all = \"kebab-case\")]\n    struct Ambig {\n        debug: u32,\n        debug_assertions: bool,\n    }\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_AMBIG_DEBUG_ASSERTIONS\", \"true\")\n        .build();\n    let err = gctx.get::<Ambig>(\"ambig\").err().unwrap();\n    assert!(format!(\"{}\", err).contains(\"missing config key `ambig.debug`\"));\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_AMBIG_DEBUG\", \"5\")\n        .build();\n    let s: Ambig = gctx.get(\"ambig\").unwrap();\n    assert_eq!(s.debug_assertions, bool::default());\n    assert_eq!(s.debug, 5);\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_AMBIG_DEBUG\", \"1\")\n        .env(\"CARGO_AMBIG_DEBUG_ASSERTIONS\", \"true\")\n        .build();\n    let s: Ambig = gctx.get(\"ambig\").unwrap();\n    assert_eq!(s.debug_assertions, true);\n    assert_eq!(s.debug, 1);\n}\n\n#[cargo_test]\nfn struct_with_overlapping_inner_struct_and_defaults() {\n    // Struct with serde defaults.\n    // Check that can be defined with environment variable.\n    #[derive(Deserialize, Default)]\n    #[serde(default)]\n    struct Inner {\n        value: i32,\n    }\n\n    // Containing struct with a prefix of inner\n    //\n    // This is a limitation of mapping environment variables on to a hierarchy.\n    // Check that we error out when we hit ambiguity in this way, rather than\n    // the more-surprising defaulting through.\n    // If, in the future, we can handle this more correctly, feel free to delete\n    // this case.\n    #[derive(Deserialize, Default)]\n    struct PrefixContainer {\n        inn: bool,\n        inner: Inner,\n    }\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_PREFIXCONTAINER_INNER_VALUE\", \"12\")\n        .build();\n    let err = gctx\n        .get::<PrefixContainer>(\"prefixcontainer\")\n        .err()\n        .unwrap();\n    assert!(format!(\"{}\", err).contains(\"missing field `inn`\"));\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_PREFIXCONTAINER_INNER_VALUE\", \"12\")\n        .env(\"CARGO_PREFIXCONTAINER_INN\", \"true\")\n        .build();\n    let f: PrefixContainer = gctx.get(\"prefixcontainer\").unwrap();\n    assert_eq!(f.inner.value, 12);\n    assert_eq!(f.inn, true);\n\n    // Use default attribute of serde, then we can skip setting the inn field\n    #[derive(Deserialize, Default)]\n    #[serde(default)]\n    struct PrefixContainerFieldDefault {\n        inn: bool,\n        inner: Inner,\n    }\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_PREFIXCONTAINER_INNER_VALUE\", \"12\")\n        .build();\n    let f = gctx\n        .get::<PrefixContainerFieldDefault>(\"prefixcontainer\")\n        .unwrap();\n    assert_eq!(f.inner.value, 12);\n    assert_eq!(f.inn, false);\n\n    // Containing struct where the inner value's field is a prefix of another\n    //\n    // This is a limitation of mapping environment variables on to a hierarchy.\n    // Check that we error out when we hit ambiguity in this way, rather than\n    // the more-surprising defaulting through.\n    // If, in the future, we can handle this more correctly, feel free to delete\n    // this case.\n    #[derive(Deserialize, Default)]\n    #[serde(default)]\n    struct InversePrefixContainer {\n        inner_field: bool,\n        inner: Inner,\n    }\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_INVERSEPREFIXCONTAINER_INNER_VALUE\", \"12\")\n        .build();\n    let f: InversePrefixContainer = gctx.get(\"inverseprefixcontainer\").unwrap();\n    assert_eq!(f.inner_field, bool::default());\n    assert_eq!(f.inner.value, 12);\n}\n\n#[cargo_test]\nfn string_list_tricky_env() {\n    // Make sure StringList handles typed env values.\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_KEY1\", \"123\")\n        .env(\"CARGO_KEY2\", \"true\")\n        .env(\"CARGO_KEY3\", \"1 2\")\n        .build();\n    let x = gctx.get::<StringList>(\"key1\").unwrap();\n    assert_eq!(x.as_slice(), &[\"123\".to_string()]);\n    let x = gctx.get::<StringList>(\"key2\").unwrap();\n    assert_eq!(x.as_slice(), &[\"true\".to_string()]);\n    let x = gctx.get::<StringList>(\"key3\").unwrap();\n    assert_eq!(x.as_slice(), &[\"1\".to_string(), \"2\".to_string()]);\n}\n\n#[cargo_test]\nfn string_list_wrong_type() {\n    // What happens if StringList is given then wrong type.\n    write_config_toml(\"some_list = 123\");\n    let gctx = GlobalContextBuilder::new().build();\n    assert_error(\n        gctx.get::<StringList>(\"some_list\").unwrap_err(),\n        str![[r#\"\ninvalid configuration for key `some_list`\nexpected a string or array of strings, but found a integer for `some_list` in [ROOT]/.cargo/config.toml\n\"#]],\n    );\n\n    write_config_toml(\"some_list = \\\"1 2\\\"\");\n    let gctx = GlobalContextBuilder::new().build();\n    let x = gctx.get::<StringList>(\"some_list\").unwrap();\n    assert_eq!(x.as_slice(), &[\"1\".to_string(), \"2\".to_string()]);\n}\n\n#[cargo_test]\nfn string_list_advanced_env() {\n    // StringList with advanced env.\n    let gctx = GlobalContextBuilder::new()\n        .unstable_flag(\"advanced-env\")\n        .env(\"CARGO_KEY1\", \"[]\")\n        .env(\"CARGO_KEY2\", \"['1 2', '3']\")\n        .env(\"CARGO_KEY3\", \"[123]\")\n        .build();\n    let x = gctx.get::<StringList>(\"key1\").unwrap();\n    assert_eq!(x.as_slice(), &[] as &[String]);\n    let x = gctx.get::<StringList>(\"key2\").unwrap();\n    assert_eq!(x.as_slice(), &[\"1 2\".to_string(), \"3\".to_string()]);\n    assert_error(\n        gctx.get::<StringList>(\"key3\").unwrap_err(),\n        str![\"error in environment variable `CARGO_KEY3`: expected string, found integer\"],\n    );\n}\n\n#[cargo_test]\nfn parse_strip_with_string() {\n    write_config_toml(\n        \"\\\n[profile.release]\nstrip = 'debuginfo'\n\",\n    );\n\n    let gctx = new_gctx();\n\n    let p: cargo_toml::TomlProfile = gctx.get(\"profile.release\").unwrap();\n    let strip = p.strip.unwrap();\n    assert_eq!(\n        strip,\n        cargo_toml::StringOrBool::String(\"debuginfo\".to_string())\n    );\n}\n\n#[cargo_test]\nfn cargo_target_empty_cfg() {\n    write_config_toml(\n        \"\\\n[build]\ntarget-dir = ''\n\",\n    );\n\n    let gctx = new_gctx();\n\n    assert_error(\n        gctx.target_dir().unwrap_err(),\n        str![\"the target directory is set to an empty string in [ROOT]/.cargo/config.toml\"],\n    );\n}\n\n#[cargo_test]\nfn cargo_target_empty_env() {\n    let project = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    project.cargo(\"check\")\n        .env(\"CARGO_TARGET_DIR\", \"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] the target directory is set to an empty string in the `CARGO_TARGET_DIR` environment variable\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn all_profile_options() {\n    // Check that all profile options can be serialized/deserialized.\n    let base_settings = cargo_toml::TomlProfile {\n        opt_level: Some(cargo_toml::TomlOptLevel(\"0\".to_string())),\n        lto: Some(cargo_toml::StringOrBool::String(\"thin\".to_string())),\n        codegen_backend: Some(String::from(\"example\")),\n        codegen_units: Some(123),\n        debug: Some(cargo_toml::TomlDebugInfo::Limited),\n        split_debuginfo: Some(\"packed\".to_string()),\n        debug_assertions: Some(true),\n        rpath: Some(true),\n        panic: Some(\"abort\".to_string()),\n        overflow_checks: Some(true),\n        incremental: Some(true),\n        dir_name: Some(String::from(\"dir_name\")),\n        inherits: Some(String::from(\"debug\")),\n        strip: Some(cargo_toml::StringOrBool::String(\"symbols\".to_string())),\n        package: None,\n        build_override: None,\n        rustflags: None,\n        trim_paths: None,\n        hint_mostly_unused: None,\n    };\n    let mut overrides = BTreeMap::new();\n    let key = cargo_toml::ProfilePackageSpec::Spec(PackageIdSpec::parse(\"foo\").unwrap());\n    overrides.insert(key, base_settings.clone());\n    let profile = cargo_toml::TomlProfile {\n        build_override: Some(Box::new(base_settings.clone())),\n        package: Some(overrides),\n        ..base_settings\n    };\n    let profile_toml = toml::to_string(&profile).unwrap();\n    let roundtrip: cargo_toml::TomlProfile = toml::from_str(&profile_toml).unwrap();\n    let roundtrip_toml = toml::to_string(&roundtrip).unwrap();\n    assert_e2e().eq(&roundtrip_toml, &profile_toml);\n}\n\n#[cargo_test]\nfn value_in_array() {\n    // Value<String> in an array should work\n    let root_path = paths::root().join(\".cargo/config.toml\");\n    write_config_at(\n        &root_path,\n        \"\\\n[net.ssh]\nknown-hosts = [\n    \\\"example.com ...\\\",\n    \\\"example.net ...\\\",\n]\n\",\n    );\n\n    let foo_path = paths::root().join(\"foo/.cargo/config.toml\");\n    write_config_at(\n        &foo_path,\n        \"\\\n[net.ssh]\nknown-hosts = [\n    \\\"example.org ...\\\",\n]\n\",\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .cwd(\"foo\")\n        // environment variables don't actually work for known-hosts due to\n        // space splitting, but this is included here just to validate that\n        // they work (particularly if other Vec<Value> config vars are added\n        // in the future).\n        .env(\"CARGO_NET_SSH_KNOWN_HOSTS\", \"env-example\")\n        .build();\n    let net_config = gctx.net_config().unwrap();\n    let kh = net_config\n        .ssh\n        .as_ref()\n        .unwrap()\n        .known_hosts\n        .as_ref()\n        .unwrap();\n    assert_eq!(kh.len(), 4);\n    assert_eq!(kh[0].val, \"example.com ...\");\n    assert_eq!(kh[0].definition, Definition::Path(root_path.clone()));\n    assert_eq!(kh[1].val, \"example.net ...\");\n    assert_eq!(kh[1].definition, Definition::Path(root_path.clone()));\n    assert_eq!(kh[2].val, \"example.org ...\");\n    assert_eq!(kh[2].definition, Definition::Path(foo_path.clone()));\n    assert_eq!(kh[3].val, \"env-example\");\n    assert_eq!(\n        kh[3].definition,\n        Definition::Environment(\"CARGO_NET_SSH_KNOWN_HOSTS\".to_string())\n    );\n}\n\n#[cargo_test]\nfn debuginfo_parsing() {\n    let gctx = GlobalContextBuilder::new().build();\n    let p: cargo_toml::TomlProfile = gctx.get(\"profile.dev\").unwrap();\n    assert_eq!(p.debug, None);\n\n    let env_test_cases = [\n        (TomlDebugInfo::None, [\"false\", \"0\", \"none\"].as_slice()),\n        (TomlDebugInfo::LineDirectivesOnly, &[\"line-directives-only\"]),\n        (TomlDebugInfo::LineTablesOnly, &[\"line-tables-only\"]),\n        (TomlDebugInfo::Limited, &[\"1\", \"limited\"]),\n        (TomlDebugInfo::Full, &[\"true\", \"2\", \"full\"]),\n    ];\n    for (expected, config_strs) in env_test_cases {\n        for &val in config_strs {\n            let gctx = GlobalContextBuilder::new()\n                .env(\"CARGO_PROFILE_DEV_DEBUG\", val)\n                .build();\n            let debug: TomlDebugInfo = gctx.get(\"profile.dev.debug\").unwrap();\n            assert_eq!(debug, expected, \"failed to parse {val}\");\n        }\n    }\n\n    let toml_test_cases = [\n        (TomlDebugInfo::None, [\"false\", \"0\", \"\\\"none\\\"\"].as_slice()),\n        (\n            TomlDebugInfo::LineDirectivesOnly,\n            &[\"\\\"line-directives-only\\\"\"],\n        ),\n        (TomlDebugInfo::LineTablesOnly, &[\"\\\"line-tables-only\\\"\"]),\n        (TomlDebugInfo::Limited, &[\"1\", \"\\\"limited\\\"\"]),\n        (TomlDebugInfo::Full, &[\"true\", \"2\", \"\\\"full\\\"\"]),\n    ];\n    for (expected, config_strs) in toml_test_cases {\n        for &val in config_strs {\n            let gctx = GlobalContextBuilder::new()\n                .config_arg(format!(\"profile.dev.debug={val}\"))\n                .build();\n            let debug: TomlDebugInfo = gctx.get(\"profile.dev.debug\").unwrap();\n            assert_eq!(debug, expected, \"failed to parse {val}\");\n        }\n    }\n\n    let toml_err_cases = [\"\\\"\\\"\", \"\\\"unrecognized\\\"\", \"3\"];\n    for err_val in toml_err_cases {\n        let gctx = GlobalContextBuilder::new()\n            .config_arg(format!(\"profile.dev.debug={err_val}\"))\n            .build();\n        let err = gctx.get::<TomlDebugInfo>(\"profile.dev.debug\").unwrap_err();\n        assert!(\n            err.to_string()\n                .ends_with(\"could not load config key `profile.dev.debug`\")\n        );\n    }\n}\n\n#[cargo_test]\nfn build_jobs_missing() {\n    write_config_toml(\n        \"\\\n[build]\n\",\n    );\n\n    let gctx = new_gctx();\n\n    assert!(\n        gctx.get::<Option<JobsConfig>>(\"build.jobs\")\n            .unwrap()\n            .is_none()\n    );\n}\n\n#[cargo_test]\nfn build_jobs_default() {\n    write_config_toml(\n        \"\\\n[build]\njobs = \\\"default\\\"\n\",\n    );\n\n    let gctx = new_gctx();\n\n    let a = gctx\n        .get::<Option<JobsConfig>>(\"build.jobs\")\n        .unwrap()\n        .unwrap();\n\n    match a {\n        JobsConfig::String(v) => assert_eq!(&v, \"default\"),\n        JobsConfig::Integer(_) => panic!(\"Did not except an integer.\"),\n    }\n}\n\n#[cargo_test]\nfn build_jobs_integer() {\n    write_config_toml(\n        \"\\\n[build]\njobs = 2\n\",\n    );\n\n    let gctx = new_gctx();\n\n    let a = gctx\n        .get::<Option<JobsConfig>>(\"build.jobs\")\n        .unwrap()\n        .unwrap();\n\n    match a {\n        JobsConfig::String(_) => panic!(\"Did not except an integer.\"),\n        JobsConfig::Integer(v) => assert_eq!(v, 2),\n    }\n}\n\n#[cargo_test]\nfn trim_paths_parsing() {\n    let gctx = GlobalContextBuilder::new().build();\n    let p: cargo_toml::TomlProfile = gctx.get(\"profile.dev\").unwrap();\n    assert_eq!(p.trim_paths, None);\n\n    let test_cases = [\n        (TomlTrimPathsValue::Diagnostics.into(), \"diagnostics\"),\n        (TomlTrimPathsValue::Macro.into(), \"macro\"),\n        (TomlTrimPathsValue::Object.into(), \"object\"),\n    ];\n    for (expected, val) in test_cases {\n        // env\n        let gctx = GlobalContextBuilder::new()\n            .env(\"CARGO_PROFILE_DEV_TRIM_PATHS\", val)\n            .build();\n        let trim_paths: TomlTrimPaths = gctx.get(\"profile.dev.trim-paths\").unwrap();\n        assert_eq!(trim_paths, expected, \"failed to parse {val}\");\n\n        // config.toml\n        let gctx = GlobalContextBuilder::new()\n            .config_arg(format!(\"profile.dev.trim-paths='{val}'\"))\n            .build();\n        let trim_paths: TomlTrimPaths = gctx.get(\"profile.dev.trim-paths\").unwrap();\n        assert_eq!(trim_paths, expected, \"failed to parse {val}\");\n    }\n\n    let test_cases = [(TomlTrimPaths::none(), false), (TomlTrimPaths::All, true)];\n\n    for (expected, val) in test_cases {\n        // env\n        let gctx = GlobalContextBuilder::new()\n            .env(\"CARGO_PROFILE_DEV_TRIM_PATHS\", format!(\"{val}\"))\n            .build();\n        let trim_paths: TomlTrimPaths = gctx.get(\"profile.dev.trim-paths\").unwrap();\n        assert_eq!(trim_paths, expected, \"failed to parse {val}\");\n\n        // config.toml\n        let gctx = GlobalContextBuilder::new()\n            .config_arg(format!(\"profile.dev.trim-paths={val}\"))\n            .build();\n        let trim_paths: TomlTrimPaths = gctx.get(\"profile.dev.trim-paths\").unwrap();\n        assert_eq!(trim_paths, expected, \"failed to parse {val}\");\n    }\n\n    let expected = vec![\n        TomlTrimPathsValue::Diagnostics,\n        TomlTrimPathsValue::Macro,\n        TomlTrimPathsValue::Object,\n    ]\n    .into();\n    let val = r#\"[\"diagnostics\", \"macro\", \"object\"]\"#;\n    // config.toml\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(format!(\"profile.dev.trim-paths={val}\"))\n        .build();\n    let trim_paths: TomlTrimPaths = gctx.get(\"profile.dev.trim-paths\").unwrap();\n    assert_eq!(trim_paths, expected, \"failed to parse {val}\");\n}\n\n#[cargo_test]\nfn missing_fields() {\n    #[derive(Deserialize, Default, Debug)]\n    struct Foo {\n        bar: Bar,\n    }\n\n    #[derive(Deserialize, Default, Debug)]\n    struct Bar {\n        bax: bool,\n        baz: bool,\n    }\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_FOO_BAR_BAZ\", \"true\")\n        .build();\n    assert_error(\n        gctx.get::<Foo>(\"foo\").unwrap_err(),\n        str![[r#\"\ncould not load config key `foo.bar`\n\nCaused by:\n  missing field `bax`\n\"#]],\n    );\n    let gctx: GlobalContext = GlobalContextBuilder::new()\n        .env(\"CARGO_FOO_BAR_BAZ\", \"true\")\n        .env(\"CARGO_FOO_BAR_BAX\", \"true\")\n        .build();\n    let foo = gctx.get::<Foo>(\"foo\").unwrap();\n    assert_eq!(foo.bar.bax, true);\n    assert_eq!(foo.bar.baz, true);\n\n    let gctx: GlobalContext = GlobalContextBuilder::new()\n        .config_arg(\"foo.bar.baz=true\")\n        .build();\n    assert_error(\n        gctx.get::<Foo>(\"foo\").unwrap_err(),\n        str![[r#\"\nerror in --config cli option: could not load config key `foo.bar`\n\nCaused by:\n  missing field `bax`\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn git_features() {\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_UNSTABLE_GIT\", \"shallow-index\")\n        .build();\n    assert!(do_check(\n        gctx,\n        Some(GitFeatures {\n            shallow_index: true,\n            ..GitFeatures::default()\n        }),\n    ));\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_UNSTABLE_GIT\", \"shallow-index,abc\")\n        .build();\n    assert_error(\n        gctx.get::<Option<cargo::core::CliUnstable>>(\"unstable\")\n            .unwrap_err(),\n        str![[r#\"\nerror in environment variable `CARGO_UNSTABLE_GIT`: could not load config key `unstable.git`\n\nCaused by:\n  unstable 'git' only takes `shallow-index` and `shallow-deps` as valid inputs\n\"#]],\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_UNSTABLE_GIT\", \"shallow-deps\")\n        .build();\n    assert!(do_check(\n        gctx,\n        Some(GitFeatures {\n            shallow_index: false,\n            shallow_deps: true,\n        }),\n    ));\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_UNSTABLE_GIT\", \"true\")\n        .build();\n    assert!(do_check(gctx, Some(GitFeatures::all())));\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_UNSTABLE_GIT_SHALLOW_INDEX\", \"true\")\n        .build();\n    assert!(do_check(\n        gctx,\n        Some(GitFeatures {\n            shallow_index: true,\n            ..Default::default()\n        }),\n    ));\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_UNSTABLE_GIT_SHALLOW_INDEX\", \"true\")\n        .env(\"CARGO_UNSTABLE_GIT_SHALLOW_DEPS\", \"true\")\n        .build();\n    assert!(do_check(\n        gctx,\n        Some(GitFeatures {\n            shallow_index: true,\n            shallow_deps: true,\n            ..Default::default()\n        }),\n    ));\n\n    write_config_toml(\n        \"\\\n[unstable]\ngit = 'shallow-index'\n\",\n    );\n    let gctx = GlobalContextBuilder::new().build();\n    assert!(do_check(\n        gctx,\n        Some(GitFeatures {\n            shallow_index: true,\n            shallow_deps: false,\n        }),\n    ));\n\n    write_config_toml(\n        \"\\\n    [unstable.git]\n    shallow_deps = false\n    shallow_index = true\n    \",\n    );\n    let gctx = GlobalContextBuilder::new().build();\n    assert!(do_check(\n        gctx,\n        Some(GitFeatures {\n            shallow_index: true,\n            shallow_deps: false,\n            ..Default::default()\n        }),\n    ));\n\n    write_config_toml(\n        \"\\\n    [unstable.git]\n    \",\n    );\n    let gctx = GlobalContextBuilder::new().build();\n    assert!(do_check(gctx, Some(Default::default())));\n\n    fn do_check(gctx: GlobalContext, expect: Option<GitFeatures>) -> bool {\n        let unstable_flags = gctx\n            .get::<Option<cargo::core::CliUnstable>>(\"unstable\")\n            .unwrap()\n            .unwrap();\n        unstable_flags.git == expect\n    }\n}\n\n#[cargo_test]\nfn gitoxide_features() {\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_UNSTABLE_GITOXIDE\", \"fetch\")\n        .build();\n    assert!(do_check(\n        gctx,\n        Some(GitoxideFeatures {\n            fetch: true,\n            ..GitoxideFeatures::default()\n        }),\n    ));\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_UNSTABLE_GITOXIDE\", \"fetch,abc\")\n        .build();\n\n    assert_error(\n        gctx.get::<Option<cargo::core::CliUnstable>>(\"unstable\")\n            .unwrap_err(),\n        str![[r#\"\nerror in environment variable `CARGO_UNSTABLE_GITOXIDE`: could not load config key `unstable.gitoxide`\n\nCaused by:\n  unstable 'gitoxide' only takes `fetch` and `checkout` and `internal-use-git2` as valid inputs, for shallow fetches see `-Zgit=shallow-index,shallow-deps`\n\"#]],\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_UNSTABLE_GITOXIDE\", \"true\")\n        .build();\n    assert!(do_check(gctx, Some(GitoxideFeatures::all())));\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_UNSTABLE_GITOXIDE_FETCH\", \"true\")\n        .build();\n    assert!(do_check(\n        gctx,\n        Some(GitoxideFeatures {\n            fetch: true,\n            ..Default::default()\n        }),\n    ));\n\n    write_config_toml(\n        \"\\\n[unstable]\ngitoxide = \\\"fetch\\\"\n\",\n    );\n    let gctx = GlobalContextBuilder::new().build();\n    assert!(do_check(\n        gctx,\n        Some(GitoxideFeatures {\n            fetch: true,\n            ..GitoxideFeatures::default()\n        }),\n    ));\n\n    write_config_toml(\n        \"\\\n    [unstable.gitoxide]\n    fetch = true\n    checkout = false\n    internal_use_git2 = false\n    \",\n    );\n    let gctx = GlobalContextBuilder::new().build();\n    assert!(do_check(\n        gctx,\n        Some(GitoxideFeatures {\n            fetch: true,\n            checkout: false,\n            internal_use_git2: false,\n        }),\n    ));\n\n    write_config_toml(\n        \"\\\n    [unstable.gitoxide]\n    \",\n    );\n    let gctx = GlobalContextBuilder::new().build();\n    assert!(do_check(gctx, Some(Default::default())));\n\n    fn do_check(gctx: GlobalContext, expect: Option<GitoxideFeatures>) -> bool {\n        let unstable_flags = gctx\n            .get::<Option<cargo::core::CliUnstable>>(\"unstable\")\n            .unwrap()\n            .unwrap();\n        unstable_flags.gitoxide == expect\n    }\n}\n\n#[cargo_test]\nfn nonmergeable_lists() {\n    let root_path = paths::root().join(\".cargo/config.toml\");\n    write_config_at(\n        &root_path,\n        \"\\\n[registries.example]\ncredential-provider = ['a', 'b']\n\",\n    );\n\n    let foo_path = paths::root().join(\"foo/.cargo/config.toml\");\n    write_config_at(\n        &foo_path,\n        \"\\\n[registries.example]\ncredential-provider = ['c', 'd']\n\",\n    );\n\n    let gctx = GlobalContextBuilder::new().cwd(\"foo\").build();\n    let provider = gctx\n        .get::<Option<RegistryConfig>>(&format!(\"registries.example\"))\n        .unwrap()\n        .unwrap()\n        .credential_provider\n        .unwrap();\n    assert_eq!(provider.path.raw_value(), \"c\");\n    assert_eq!(provider.args, [\"d\"]);\n\n    let cli_arg = \"registries.example.credential-provider=['cli', 'cli-arg']\";\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(cli_arg)\n        .cwd(\"foo\")\n        .build();\n    let provider = gctx\n        .get::<Option<RegistryConfig>>(&format!(\"registries.example\"))\n        .unwrap()\n        .unwrap()\n        .credential_provider\n        .unwrap();\n    // expect: no merge happens; config CLI takes precedence\n    assert_eq!(provider.path.raw_value(), \"cli\");\n    assert_eq!(provider.args, [\"cli-arg\"]);\n\n    let env = \"CARGO_REGISTRIES_EXAMPLE_CREDENTIAL_PROVIDER\";\n    let gctx = GlobalContextBuilder::new()\n        .env(env, \"env env-arg\")\n        .cwd(\"foo\")\n        .build();\n    let provider = gctx\n        .get::<Option<RegistryConfig>>(&format!(\"registries.example\"))\n        .unwrap()\n        .unwrap()\n        .credential_provider\n        .unwrap();\n    // expect: no merge happens; env takes precedence over files\n    assert_eq!(provider.path.raw_value(), \"env\");\n    assert_eq!(provider.args, [\"env-arg\"]);\n\n    let gctx = GlobalContextBuilder::new()\n        .env(env, \"env env-arg\")\n        .config_arg(cli_arg)\n        .cwd(\"foo\")\n        .build();\n    let provider = gctx\n        .get::<Option<RegistryConfig>>(&format!(\"registries.example\"))\n        .unwrap()\n        .unwrap()\n        .credential_provider\n        .unwrap();\n    // expect: no merge happens; cli takes precedence over files and env\n    assert_eq!(provider.path.raw_value(), \"cli\");\n    assert_eq!(provider.args, [\"cli-arg\"]);\n}\n\n#[cargo_test]\nfn build_std() {\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_UNSTABLE_BUILD_STD\", \"core,std,panic_abort\")\n        .build();\n    let value = gctx\n        .get::<Option<cargo::core::CliUnstable>>(\"unstable\")\n        .unwrap()\n        .unwrap()\n        .build_std\n        .unwrap();\n    assert_eq!(\n        value,\n        vec![\n            \"core\".to_string(),\n            \"std\".to_string(),\n            \"panic_abort\".to_string(),\n        ],\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"unstable.build-std=['core', 'std,panic_abort']\")\n        .build();\n    let value = gctx\n        .get::<Option<cargo::core::CliUnstable>>(\"unstable\")\n        .unwrap()\n        .unwrap()\n        .build_std\n        .unwrap();\n    assert_eq!(\n        value,\n        vec![\n            \"core\".to_string(),\n            \"std\".to_string(),\n            \"panic_abort\".to_string(),\n        ]\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\n            \"CARGO_UNSTABLE_BUILD_STD_FEATURES\",\n            \"backtrace,panic-unwind,windows_raw_dylib\",\n        )\n        .build();\n    let value = gctx\n        .get::<Option<cargo::core::CliUnstable>>(\"unstable\")\n        .unwrap()\n        .unwrap()\n        .build_std_features\n        .unwrap();\n    assert_eq!(\n        value,\n        vec![\n            \"backtrace\".to_string(),\n            \"panic-unwind\".to_string(),\n            \"windows_raw_dylib\".to_string(),\n        ]\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"unstable.build-std-features=['backtrace', 'panic-unwind,windows_raw_dylib']\")\n        .build();\n    let value = gctx\n        .get::<Option<cargo::core::CliUnstable>>(\"unstable\")\n        .unwrap()\n        .unwrap()\n        .build_std_features\n        .unwrap();\n    assert_eq!(\n        value,\n        vec![\n            \"backtrace\".to_string(),\n            \"panic-unwind\".to_string(),\n            \"windows_raw_dylib\".to_string(),\n        ]\n    );\n}\n\n#[cargo_test]\nfn array_of_any_types() {\n    write_config_toml(\n        r#\"\n        ints = [1, 2, 3]\n\n        bools = [true, false, true]\n\n        strings = [\"hello\", \"world\", \"test\"]\n\n        [[tables]]\n        name = \"first\"\n        value = 1\n        [[tables]]\n        name = \"second\"\n        value = 2\n        \"#,\n    );\n\n    let gctx = new_gctx();\n\n    // Test integer array\n    let ints: Vec<i32> = gctx.get(\"ints\").unwrap();\n    assert_eq!(ints, vec![1, 2, 3]);\n\n    let bools: Vec<bool> = gctx.get(\"bools\").unwrap();\n    assert_eq!(bools, vec![true, false, true]);\n\n    #[derive(Deserialize, Debug, PartialEq)]\n    struct T {\n        name: String,\n        value: i32,\n    }\n    let tables: Vec<T> = gctx.get(\"tables\").unwrap();\n    assert_eq!(\n        tables,\n        vec![\n            T {\n                name: \"first\".into(),\n                value: 1,\n            },\n            T {\n                name: \"second\".into(),\n                value: 2,\n            },\n        ]\n    );\n}\n\n#[cargo_test]\nfn array_env() {\n    // for environment, only strings are supported.\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_INTS\", \"3 4 5\")\n        .env(\"CARGO_BOOLS\", \"false true false\")\n        .env(\"CARGO_STRINGS\", \"env1 env2 env3\")\n        .build();\n\n    assert_error(\n        gctx.get::<Vec<i32>>(\"ints\").unwrap_err(),\n        str![[r#\"\nerror in environment variable `CARGO_INTS`: failed to parse config at `ints[0]`\n\nCaused by:\n  invalid type: string \"3\", expected i32\n\"#]],\n    );\n\n    assert_error(\n        gctx.get::<Vec<bool>>(\"bools\").unwrap_err(),\n        str![[r#\"\nerror in environment variable `CARGO_BOOLS`: failed to parse config at `bools[0]`\n\nCaused by:\n  invalid type: string \"false\", expected a boolean\n\"#]],\n    );\n\n    assert_eq!(\n        gctx.get::<Vec<String>>(\"strings\").unwrap(),\n        vec![\"env1\".to_string(), \"env2\".to_string(), \"env3\".to_string()],\n    );\n}\n\n#[cargo_test]\nfn nested_array() {\n    let root_path = paths::root().join(\".cargo/config.toml\");\n    write_config_at(\n        &root_path,\n        r#\"\n        nested_ints = [[1, 2], [3, 4]]\n        nested_bools = [[true], [false, true]]\n        nested_strings = [[\"a\", \"b\"], [\"3\", \"4\"]]\n        nested_tables = [\n            [\n                { x = \"a\" },\n                { x = \"b\" },\n            ],\n            [\n                { x = \"c\" },\n                { x = \"d\" },\n            ],\n        ]\n        deeply_nested = [[\n            { x = [[[ { x = [], y = 2  } ]]], y = 1 },\n        ]]\n        \"#,\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"nested_ints = [[5]]\")\n        .build();\n\n    let nested = gctx.get::<Vec<Vec<i32>>>(\"nested_ints\").unwrap();\n    assert_eq!(nested, vec![vec![1, 2], vec![3, 4], vec![5]]);\n\n    // exercising Value and Definition\n    let nested = gctx\n        .get::<Vec<Value<Vec<Value<i32>>>>>(\"nested_ints\")\n        .unwrap();\n    let def = Definition::Path(root_path);\n    assert_eq!(\n        nested,\n        vec![\n            Value {\n                val: vec![\n                    Value {\n                        val: 1,\n                        definition: def.clone(),\n                    },\n                    Value {\n                        val: 2,\n                        definition: def.clone(),\n                    },\n                ],\n                definition: def.clone()\n            },\n            Value {\n                val: vec![\n                    Value {\n                        val: 3,\n                        definition: def.clone(),\n                    },\n                    Value {\n                        val: 4,\n                        definition: def.clone(),\n                    },\n                ],\n                definition: def.clone(),\n            },\n            Value {\n                val: vec![Value {\n                    val: 5,\n                    definition: Definition::Cli(None),\n                },],\n                definition: Definition::Cli(None),\n            },\n        ]\n    );\n\n    let nested = gctx.get::<Vec<Vec<bool>>>(\"nested_bools\").unwrap();\n    assert_eq!(nested, vec![vec![true], vec![false, true]]);\n\n    let nested = gctx.get::<Vec<Vec<String>>>(\"nested_strings\").unwrap();\n    assert_eq!(\n        nested,\n        vec![\n            vec![\"a\".to_string(), \"b\".to_string()],\n            vec![\"3\".to_string(), \"4\".to_string()]\n        ]\n    );\n\n    #[derive(Deserialize, Debug, PartialEq)]\n    struct S {\n        x: Vec<Vec<Vec<S>>>,\n        y: i32,\n    }\n    let nested = gctx.get::<Vec<Vec<S>>>(\"deeply_nested\").unwrap();\n    assert_eq!(\n        nested,\n        vec![vec![S {\n            x: vec![vec![vec![S { x: vec![], y: 2 }]]],\n            y: 1,\n        }]],\n    );\n}\n\n#[cargo_test]\nfn mixed_type_array() {\n    let root_path = paths::root().join(\".cargo/config.toml\");\n    write_config_at(&root_path, r#\"a = [{ x = 1 }]\"#);\n\n    let foo_path = paths::root().join(\"foo/.cargo/config.toml\");\n    write_config_at(&foo_path, r#\"a = [true, [false]]\"#);\n\n    let gctx = GlobalContextBuilder::new()\n        .cwd(\"foo\")\n        .env(\"CARGO_A\", \"hello\")\n        .config_arg(\"a = [123]\")\n        .build();\n\n    #[derive(Deserialize, Debug, PartialEq)]\n    #[serde(untagged)]\n    enum Item {\n        B(bool),\n        I(i32),\n        S(String),\n        T { x: i32 },\n        L(Vec<bool>),\n    }\n\n    use Item::*;\n\n    // Simple vector works\n    assert_eq!(\n        gctx.get::<Vec<Item>>(\"a\").unwrap(),\n        vec![\n            T { x: 1 },\n            B(true),\n            L(vec![false]),\n            S(\"hello\".into()),\n            I(123)\n        ],\n    );\n\n    // Value and Definition works\n    assert_eq!(\n        gctx.get::<Value<Vec<Value<Item>>>>(\"a\").unwrap(),\n        Value {\n            val: vec![\n                Value {\n                    val: T { x: 1 },\n                    definition: Definition::Path(root_path.clone()),\n                },\n                Value {\n                    val: B(true),\n                    definition: Definition::Path(foo_path.clone()),\n                },\n                Value {\n                    val: L(vec![false]),\n                    definition: Definition::Path(foo_path.clone()),\n                },\n                Value {\n                    val: S(\"hello\".into()),\n                    definition: Definition::Environment(\"CARGO_A\".into()),\n                },\n                Value {\n                    val: I(123),\n                    definition: Definition::Cli(None),\n                },\n            ],\n            definition: Definition::Environment(\"CARGO_A\".into()),\n        }\n    );\n}\n\n#[cargo_test]\nfn config_symlink_home_duplicate_load() {\n    // Test that when CARGO_HOME is accessed via a symlink that points to a directory\n    // already in the config search path, the config file is not loaded twice.\n\n    use cargo_test_support::basic_manifest;\n\n    #[cfg(unix)]\n    use std::os::unix::fs::symlink;\n\n    #[cfg(windows)]\n    use std::os::windows::fs::symlink_dir as symlink;\n\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Create directory structure a/b/ and symlink c -> a\n    let a_dir = p.root().join(\"a\");\n    let b_dir = a_dir.join(\"b\");\n    let c_symlink = p.root().join(\"c\");\n\n    fs::create_dir_all(&b_dir).unwrap();\n    symlink(&a_dir, &c_symlink).unwrap();\n\n    // Create config file in a/.cargo/\n    let cargo_config_dir = a_dir.join(\".cargo\");\n    fs::create_dir(&cargo_config_dir).unwrap();\n    let config_path = cargo_config_dir.join(\"config.toml\");\n    fs::write(\n        &config_path,\n        r#\"\n[build]\nrustdocflags = [\"--default-theme=dark\"]\n\"#,\n    )\n    .unwrap();\n\n    // Move the project into a/b/\n    let project_in_b = b_dir.join(\"foo\");\n    fs::create_dir(&project_in_b).unwrap();\n    fs::write(\n        project_in_b.join(\"Cargo.toml\"),\n        &basic_manifest(\"foo\", \"0.1.0\"),\n    )\n    .unwrap();\n    fs::create_dir(project_in_b.join(\"src\")).unwrap();\n    fs::write(project_in_b.join(\"src/lib.rs\"), \"\").unwrap();\n\n    // Set CARGO_HOME to ../../c/.cargo (which is really a/.cargo via symlink)\n    let cargo_home = c_symlink.join(\".cargo\");\n\n    // If config is loaded twice, rustdocflags will be duplicated and cause an error\n    p.cargo(\"doc\")\n        .cwd(&project_in_b)\n        .env(\"CARGO_HOME\", &cargo_home)\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/config_cli.rs",
    "content": "//! Tests for the --config CLI option.\n\nuse std::{collections::HashMap, fs};\n\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::paths;\nuse cargo_test_support::str;\n\nuse super::config::{\n    GlobalContextBuilder, assert_error, read_output, write_config_at, write_config_toml,\n};\n\n#[cargo_test]\nfn basic() {\n    // Simple example.\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"foo='bar'\")\n        .config_arg(\"net.git-fetch-with-cli=true\")\n        .build();\n    assert_eq!(gctx.get::<String>(\"foo\").unwrap(), \"bar\");\n    assert_eq!(gctx.net_config().unwrap().git_fetch_with_cli, Some(true));\n}\n\n#[cargo_test]\nfn cli_priority() {\n    // Command line takes priority over files and env vars.\n    write_config_toml(\n        \"\n        demo_list = ['a']\n        [build]\n        jobs = 3\n        rustc = 'file'\n        [term]\n        quiet = false\n        verbose = false\n        \",\n    );\n    let gctx = GlobalContextBuilder::new().build();\n    assert_eq!(gctx.get::<i32>(\"build.jobs\").unwrap(), 3);\n    assert_eq!(gctx.get::<String>(\"build.rustc\").unwrap(), \"file\");\n    assert_eq!(gctx.get::<bool>(\"term.quiet\").unwrap(), false);\n    assert_eq!(gctx.get::<bool>(\"term.verbose\").unwrap(), false);\n\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_BUILD_JOBS\", \"2\")\n        .env(\"CARGO_BUILD_RUSTC\", \"env\")\n        .env(\"CARGO_TERM_VERBOSE\", \"false\")\n        .env(\"CARGO_NET_GIT_FETCH_WITH_CLI\", \"false\")\n        .config_arg(\"build.jobs=1\")\n        .config_arg(\"build.rustc='cli'\")\n        .config_arg(\"term.verbose=true\")\n        .config_arg(\"net.git-fetch-with-cli=true\")\n        .build();\n    assert_eq!(gctx.get::<i32>(\"build.jobs\").unwrap(), 1);\n    assert_eq!(gctx.get::<String>(\"build.rustc\").unwrap(), \"cli\");\n    assert_eq!(gctx.get::<bool>(\"term.verbose\").unwrap(), true);\n    assert_eq!(gctx.net_config().unwrap().git_fetch_with_cli, Some(true));\n\n    // Setting both term.verbose and term.quiet is invalid and is tested\n    // in the run test suite.\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_TERM_QUIET\", \"false\")\n        .config_arg(\"term.quiet=true\")\n        .build();\n    assert_eq!(gctx.get::<bool>(\"term.quiet\").unwrap(), true);\n}\n\n#[cargo_test]\nfn merge_primitives_for_multiple_cli_occurrences() {\n    let config_path0 = \".cargo/file0.toml\";\n    write_config_at(config_path0, \"k = 'file0'\");\n    let config_path1 = \".cargo/file1.toml\";\n    write_config_at(config_path1, \"k = 'file1'\");\n\n    // k=env0\n    let gctx = GlobalContextBuilder::new().env(\"CARGO_K\", \"env0\").build();\n    assert_eq!(gctx.get::<String>(\"k\").unwrap(), \"env0\");\n\n    // k=env0\n    // --config k='cli0'\n    // --config k='cli1'\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_K\", \"env0\")\n        .config_arg(\"k='cli0'\")\n        .config_arg(\"k='cli1'\")\n        .build();\n    assert_eq!(gctx.get::<String>(\"k\").unwrap(), \"cli1\");\n\n    // Env has a lower priority when comparing with file from CLI arg.\n    //\n    // k=env0\n    // --config k='cli0'\n    // --config k='cli1'\n    // --config .cargo/file0.toml\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_K\", \"env0\")\n        .config_arg(\"k='cli0'\")\n        .config_arg(\"k='cli1'\")\n        .config_arg(config_path0)\n        .build();\n    assert_eq!(gctx.get::<String>(\"k\").unwrap(), \"file0\");\n\n    // k=env0\n    // --config k='cli0'\n    // --config k='cli1'\n    // --config .cargo/file0.toml\n    // --config k='cli2'\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_K\", \"env0\")\n        .config_arg(\"k='cli0'\")\n        .config_arg(\"k='cli1'\")\n        .config_arg(config_path0)\n        .config_arg(\"k='cli2'\")\n        .build();\n    assert_eq!(gctx.get::<String>(\"k\").unwrap(), \"cli2\");\n\n    // k=env0\n    // --config k='cli0'\n    // --config k='cli1'\n    // --config .cargo/file0.toml\n    // --config k='cli2'\n    // --config .cargo/file1.toml\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_K\", \"env0\")\n        .config_arg(\"k='cli0'\")\n        .config_arg(\"k='cli1'\")\n        .config_arg(config_path0)\n        .config_arg(\"k='cli2'\")\n        .config_arg(config_path1)\n        .build();\n    assert_eq!(gctx.get::<String>(\"k\").unwrap(), \"file1\");\n}\n\n#[cargo_test]\nfn merges_array() {\n    // Array entries are appended.\n    write_config_toml(\n        \"\n        [build]\n        rustflags = ['--file']\n        \",\n    );\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"build.rustflags = ['--cli']\")\n        .build();\n    assert_eq!(\n        gctx.get::<Vec<String>>(\"build.rustflags\").unwrap(),\n        [\"--file\", \"--cli\"]\n    );\n\n    // With normal env.\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_BUILD_RUSTFLAGS\", \"--env1 --env2\")\n        .config_arg(\"build.rustflags = ['--cli']\")\n        .build();\n    assert_eq!(\n        gctx.get::<Vec<String>>(\"build.rustflags\").unwrap(),\n        [\"--file\", \"--env1\", \"--env2\", \"--cli\"]\n    );\n\n    // With advanced-env.\n    let gctx = GlobalContextBuilder::new()\n        .unstable_flag(\"advanced-env\")\n        .env(\"CARGO_BUILD_RUSTFLAGS\", \"--env\")\n        .config_arg(\"build.rustflags = ['--cli']\")\n        .build();\n    assert_eq!(\n        gctx.get::<Vec<String>>(\"build.rustflags\").unwrap(),\n        [\"--file\", \"--env\", \"--cli\"]\n    );\n\n    // Merges multiple instances.\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"build.rustflags=['--one']\")\n        .config_arg(\"build.rustflags=['--two']\")\n        .build();\n    assert_eq!(\n        gctx.get::<Vec<String>>(\"build.rustflags\").unwrap(),\n        [\"--file\", \"--one\", \"--two\"]\n    );\n}\n\n#[cargo_test]\nfn string_list_array() {\n    // Using the StringList type.\n    write_config_toml(\n        \"\n        [build]\n        rustflags = ['--file']\n        \",\n    );\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"build.rustflags = ['--cli']\")\n        .build();\n    assert_eq!(\n        gctx.get::<cargo::util::context::StringList>(\"build.rustflags\")\n            .unwrap()\n            .as_slice(),\n        [\"--file\", \"--cli\"]\n    );\n\n    // With normal env.\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_BUILD_RUSTFLAGS\", \"--env1 --env2\")\n        .config_arg(\"build.rustflags = ['--cli']\")\n        .build();\n    assert_eq!(\n        gctx.get::<cargo::util::context::StringList>(\"build.rustflags\")\n            .unwrap()\n            .as_slice(),\n        [\"--file\", \"--env1\", \"--env2\", \"--cli\"]\n    );\n\n    // With advanced-env.\n    let gctx = GlobalContextBuilder::new()\n        .unstable_flag(\"advanced-env\")\n        .env(\"CARGO_BUILD_RUSTFLAGS\", \"['--env']\")\n        .config_arg(\"build.rustflags = ['--cli']\")\n        .build();\n    assert_eq!(\n        gctx.get::<cargo::util::context::StringList>(\"build.rustflags\")\n            .unwrap()\n            .as_slice(),\n        [\"--file\", \"--env\", \"--cli\"]\n    );\n}\n\n#[cargo_test]\nfn merges_table() {\n    // Tables are merged.\n    write_config_toml(\n        \"\n        [foo]\n        key1 = 1\n        key2 = 2\n        key3 = 3\n        \",\n    );\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"foo.key2 = 4\")\n        .config_arg(\"foo.key3 = 5\")\n        .config_arg(\"foo.key4 = 6\")\n        .build();\n    assert_eq!(gctx.get::<i32>(\"foo.key1\").unwrap(), 1);\n    assert_eq!(gctx.get::<i32>(\"foo.key2\").unwrap(), 4);\n    assert_eq!(gctx.get::<i32>(\"foo.key3\").unwrap(), 5);\n    assert_eq!(gctx.get::<i32>(\"foo.key4\").unwrap(), 6);\n\n    // With env.\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_FOO_KEY3\", \"7\")\n        .env(\"CARGO_FOO_KEY4\", \"8\")\n        .env(\"CARGO_FOO_KEY5\", \"9\")\n        .config_arg(\"foo.key2 = 4\")\n        .config_arg(\"foo.key3 = 5\")\n        .config_arg(\"foo.key4 = 6\")\n        .build();\n    assert_eq!(gctx.get::<i32>(\"foo.key1\").unwrap(), 1);\n    assert_eq!(gctx.get::<i32>(\"foo.key2\").unwrap(), 4);\n    assert_eq!(gctx.get::<i32>(\"foo.key3\").unwrap(), 5);\n    assert_eq!(gctx.get::<i32>(\"foo.key4\").unwrap(), 6);\n    assert_eq!(gctx.get::<i32>(\"foo.key5\").unwrap(), 9);\n}\n\n#[cargo_test]\nfn enforces_format() {\n    // These dotted key expressions should all be fine.\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"a=true\")\n        .config_arg(\" b.a = true \")\n        .config_arg(\"c.\\\"b\\\".'a'=true\")\n        .config_arg(\"d.\\\"=\\\".'='=true\")\n        .config_arg(\"e.\\\"'\\\".'\\\"'=true\")\n        .build();\n    assert_eq!(gctx.get::<bool>(\"a\").unwrap(), true);\n    assert_eq!(\n        gctx.get::<HashMap<String, bool>>(\"b\").unwrap(),\n        HashMap::from([(\"a\".to_string(), true)])\n    );\n    assert_eq!(\n        gctx.get::<HashMap<String, HashMap<String, bool>>>(\"c\")\n            .unwrap(),\n        HashMap::from([(\"b\".to_string(), HashMap::from([(\"a\".to_string(), true)]))])\n    );\n    assert_eq!(\n        gctx.get::<HashMap<String, HashMap<String, bool>>>(\"d\")\n            .unwrap(),\n        HashMap::from([(\"=\".to_string(), HashMap::from([(\"=\".to_string(), true)]))])\n    );\n    assert_eq!(\n        gctx.get::<HashMap<String, HashMap<String, bool>>>(\"e\")\n            .unwrap(),\n        HashMap::from([(\"'\".to_string(), HashMap::from([(\"\\\"\".to_string(), true)]))])\n    );\n\n    // But anything that's not a dotted key expression should be disallowed.\n    let _ = GlobalContextBuilder::new()\n        .config_arg(\"[a] foo=true\")\n        .build_err()\n        .unwrap_err();\n    let _ = GlobalContextBuilder::new()\n        .config_arg(\"a = true\\nb = true\")\n        .build_err()\n        .unwrap_err();\n\n    // We also disallow overwriting with tables since it makes merging unclear.\n    let _ = GlobalContextBuilder::new()\n        .config_arg(\"a = { first = true, second = false }\")\n        .build_err()\n        .unwrap_err();\n    let _ = GlobalContextBuilder::new()\n        .config_arg(\"a = { first = true }\")\n        .build_err()\n        .unwrap_err();\n}\n\n#[cargo_test]\nfn unused_key() {\n    // Unused key passed on command line.\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"build.unused = 2\")\n        .build();\n\n    gctx.build_config().unwrap();\n    let output = read_output(gctx);\n    let expected = str![[r#\"\n[WARNING] unused config key `build.unused` in `--config cli option`\n\n\"#]];\n    assert_e2e().eq(&output, expected);\n}\n\n#[cargo_test]\nfn rerooted_remains() {\n    // Re-rooting keeps cli args.\n    let somedir = paths::root().join(\"somedir\");\n    fs::create_dir_all(somedir.join(\".cargo\")).unwrap();\n    fs::write(\n        somedir.join(\".cargo\").join(\"config\"),\n        \"\n        a = 'file1'\n        b = 'file2'\n        \",\n    )\n    .unwrap();\n    let mut gctx = GlobalContextBuilder::new()\n        .cwd(&somedir)\n        .config_arg(\"b='cli1'\")\n        .config_arg(\"c='cli2'\")\n        .build();\n    assert_eq!(gctx.get::<String>(\"a\").unwrap(), \"file1\");\n    assert_eq!(gctx.get::<String>(\"b\").unwrap(), \"cli1\");\n    assert_eq!(gctx.get::<String>(\"c\").unwrap(), \"cli2\");\n\n    gctx.reload_rooted_at(paths::root()).unwrap();\n\n    assert_eq!(gctx.get::<Option<String>>(\"a\").unwrap(), None);\n    assert_eq!(gctx.get::<String>(\"b\").unwrap(), \"cli1\");\n    assert_eq!(gctx.get::<String>(\"c\").unwrap(), \"cli2\");\n}\n\n#[cargo_test]\nfn bad_parse() {\n    // Fail to TOML parse.\n    let gctx = GlobalContextBuilder::new().config_arg(\"abc\").build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![[r#\"\nfailed to parse value from --config argument `abc` as a dotted key expression\n\nCaused by:\n  TOML parse error at line 1, column 4\n  |\n1 | abc\n  |    ^\nkey with no value, expected `=`\n\n\"#]],\n    );\n\n    let gctx = GlobalContextBuilder::new().config_arg(\"\").build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![\n            \"--config argument `` was not a TOML dotted key expression (such as `build.jobs = 2`)\"\n        ],\n    );\n}\n\n#[cargo_test]\nfn too_many_values() {\n    // Currently restricted to only 1 value.\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"a=1\\nb=2\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![[r#\"\n--config argument `a=1\nb=2` was not a TOML dotted key expression (such as `build.jobs = 2`)\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn no_disallowed_values() {\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"registry.token=\\\"hello\\\"\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![\"registry.token cannot be set through --config for security reasons\"],\n    );\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"registries.crates-io.token=\\\"hello\\\"\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![\"registries.crates-io.token cannot be set through --config for security reasons\"],\n    );\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"registry.secret-key=\\\"hello\\\"\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![\"registry.secret-key cannot be set through --config for security reasons\"],\n    );\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"registries.crates-io.secret-key=\\\"hello\\\"\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![\"registries.crates-io.secret-key cannot be set through --config for security reasons\"],\n    );\n}\n\n#[cargo_test]\nfn no_inline_table_value() {\n    // Disallow inline tables\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"a.b={c = \\\"d\\\"}\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![[\n            r#\"--config argument `a.b={c = \"d\"}` sets a value to an inline table, which is not accepted\"#\n        ]],\n    );\n}\n\n#[cargo_test]\nfn no_array_of_tables_values() {\n    // Disallow array-of-tables when not in dotted form\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"[[a.b]]\\nc = \\\"d\\\"\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![[r#\"\n--config argument `[[a.b]]\nc = \"d\"` was not a TOML dotted key expression (such as `build.jobs = 2`)\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn no_comments() {\n    // Disallow comments in dotted form.\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"a.b = \\\"c\\\" # exactly\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![[r#\"--config argument `a.b = \"c\" # exactly` includes non-whitespace decoration\"#]],\n    );\n\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"# exactly\\na.b = \\\"c\\\"\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![[r#\"\n--config argument `# exactly\na.b = \"c\"` includes non-whitespace decoration\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn bad_cv_convert() {\n    // ConfigValue does not support all TOML types.\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"a=2019-12-01\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![[r#\"\nfailed to convert --config argument `a=2019-12-01`\n\nCaused by:\n  failed to parse config at `a`\n\nCaused by:\n  unsupported TOML configuration type `datetime`\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn fail_to_merge_multiple_args() {\n    // Error message when multiple args fail to merge.\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"foo='a'\")\n        .config_arg(\"foo=['a']\")\n        .build_err();\n    // This is a little repetitive, but hopefully the user can figure it out.\n    assert_error(\n        gctx.unwrap_err(),\n        str![[r#\"\nfailed to merge --config argument `foo=['a']`\n\nCaused by:\n  failed to merge key `foo` between --config cli option and --config cli option\n\nCaused by:\n  failed to merge config value from `--config cli option` into `--config cli option`: expected string, but found array\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn cli_path() {\n    // --config path_to_file\n    fs::write(paths::root().join(\"myconfig.toml\"), \"key = 123\").unwrap();\n    let gctx = GlobalContextBuilder::new()\n        .cwd(paths::root())\n        .config_arg(\"myconfig.toml\")\n        .build();\n    assert_eq!(gctx.get::<u32>(\"key\").unwrap(), 123);\n\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"missing.toml\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![[r#\"\nfailed to parse value from --config argument `missing.toml` as a dotted key expression\n\nCaused by:\n  TOML parse error at line 1, column 13\n  |\n1 | missing.toml\n  |             ^\nkey with no value, expected `=`\n\n\"#]],\n    );\n}\n"
  },
  {
    "path": "tests/testsuite/config_include.rs",
    "content": "//! Tests for `include` config field.\n\nuse crate::prelude::*;\nuse cargo_test_support::str;\n\nuse super::config::GlobalContextBuilder;\nuse super::config::assert_error;\nuse super::config::write_config_at;\nuse super::config::write_config_toml;\n\n#[cargo_test]\nfn simple() {\n    // Simple test.\n    write_config_at(\n        \".cargo/config.toml\",\n        \"\n        include = ['other.toml']\n        key1 = 1\n        key2 = 2\n        \",\n    );\n    write_config_at(\n        \".cargo/other.toml\",\n        \"\n        key2 = 3\n        key3 = 4\n        \",\n    );\n    let gctx = GlobalContextBuilder::new().build();\n    assert_eq!(gctx.get::<i32>(\"key1\").unwrap(), 1);\n    assert_eq!(gctx.get::<i32>(\"key2\").unwrap(), 2);\n    assert_eq!(gctx.get::<i32>(\"key3\").unwrap(), 4);\n}\n\n#[cargo_test]\nfn mix_of_hierarchy_and_include() {\n    write_config_at(\n        \"foo/.cargo/config.toml\",\n        \"\n        include = ['other.toml']\n        key1 = 1\n\n        # also make sure unstable flags merge in the correct order\n        [unstable]\n        features = ['1']\n        \",\n    );\n    write_config_at(\n        \"foo/.cargo/other.toml\",\n        \"\n        key1 = 2\n        key2 = 2\n\n        [unstable]\n        features = ['2']\n        \",\n    );\n    write_config_at(\n        \".cargo/config.toml\",\n        \"\n        include = ['other.toml']\n        key1 = 3\n        key2 = 3\n        key3 = 3\n\n        [unstable]\n        features = ['3']\n        \",\n    );\n    write_config_at(\n        \".cargo/other.toml\",\n        \"\n        key1 = 4\n        key2 = 4\n        key3 = 4\n        key4 = 4\n\n        [unstable]\n        features = ['4']\n        \",\n    );\n    let gctx = GlobalContextBuilder::new()\n        .cwd(\"foo\")\n        .nightly_features_allowed(true)\n        .build();\n    assert_eq!(gctx.get::<i32>(\"key1\").unwrap(), 1);\n    assert_eq!(gctx.get::<i32>(\"key2\").unwrap(), 2);\n    assert_eq!(gctx.get::<i32>(\"key3\").unwrap(), 3);\n    assert_eq!(gctx.get::<i32>(\"key4\").unwrap(), 4);\n    assert_eq!(\n        gctx.get::<Vec<String>>(\"unstable.features\").unwrap(),\n        vec![\n            \"4\".to_string(),\n            \"3\".to_string(),\n            \"2\".to_string(),\n            \"1\".to_string()\n        ]\n    );\n}\n\n#[cargo_test]\nfn left_to_right_bottom_to_top() {\n    // How it merges multiple nested includes.\n    write_config_at(\n        \".cargo/config.toml\",\n        \"\n        include = ['left-middle.toml', 'right-middle.toml']\n        top = 1\n        \",\n    );\n    write_config_at(\n        \".cargo/right-middle.toml\",\n        \"\n        include = ['right-bottom.toml']\n        top = 0\n        right-middle = 0\n        \",\n    );\n    write_config_at(\n        \".cargo/right-bottom.toml\",\n        \"\n        top = -1\n        right-middle = -1\n        right-bottom = -1\n        \",\n    );\n    write_config_at(\n        \".cargo/left-middle.toml\",\n        \"\n        include = ['left-bottom.toml']\n        top = -2\n        right-middle = -2\n        right-bottom = -2\n        left-middle = -2\n        \",\n    );\n    write_config_at(\n        \".cargo/left-bottom.toml\",\n        \"\n        top = -3\n        right-middle = -3\n        right-bottom = -3\n        left-middle = -3\n        left-bottom = -3\n        \",\n    );\n    let gctx = GlobalContextBuilder::new().build();\n    assert_eq!(gctx.get::<i32>(\"top\").unwrap(), 1);\n    assert_eq!(gctx.get::<i32>(\"right-middle\").unwrap(), 0);\n    assert_eq!(gctx.get::<i32>(\"right-bottom\").unwrap(), -1);\n    assert_eq!(gctx.get::<i32>(\"left-middle\").unwrap(), -2);\n    assert_eq!(gctx.get::<i32>(\"left-bottom\").unwrap(), -3);\n}\n\n#[cargo_test]\nfn nested_include_resolves_relative_to_including_file() {\n    write_config_at(\n        \".cargo/config.toml\",\n        \"\n        include = ['../config/cargo.toml']\n        \",\n    );\n    write_config_at(\n        \"config/cargo.toml\",\n        \"\n        include = ['other.toml']\n        middle = 10\n        \",\n    );\n    write_config_at(\n        \"config/other.toml\",\n        \"\n        nested = 42\n        \",\n    );\n\n    // This should not be included,\n    // because `include` path is resolved relative to the including config\n    // (where the `include` is defined)\n    write_config_at(\n        \".cargo/other.toml\",\n        \"\n        INVALID = SYNTAX\n        \",\n    );\n\n    let gctx = GlobalContextBuilder::new().build();\n\n    assert_eq!(gctx.get::<i32>(\"nested\").unwrap(), 42);\n    assert_eq!(gctx.get::<i32>(\"middle\").unwrap(), 10);\n}\n\n#[cargo_test]\nfn missing_file() {\n    // Error when there's a missing file.\n    write_config_toml(\"include=['missing.toml']\");\n    // Config values are lazy loaded and fail at first retrieval.\n    // This ensures simple commands like `cargo --version` working even when\n    let gctx = GlobalContextBuilder::new().build();\n    assert_error(\n        gctx.get::<bool>(\"foo\").unwrap_err(),\n        str![[r#\"\ncould not load Cargo configuration\n\nCaused by:\n  failed to load config include `missing.toml` from `[ROOT]/.cargo/config.toml`\n\nCaused by:\n  failed to read configuration file `[ROOT]/.cargo/missing.toml`\n\nCaused by:\n  [NOT_FOUND]\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn wrong_file_extension() {\n    // Error when it doesn't end with `.toml`.\n    write_config_toml(\"include=['config.png']\");\n    // Config values are lazy loaded and fail at first retrieval.\n    // This ensures simple commands like `cargo --version` working even when\n    let gctx = GlobalContextBuilder::new().build();\n    assert_error(\n        gctx.get::<bool>(\"foo\").unwrap_err(),\n        str![[r#\"\ncould not load Cargo configuration\n\nCaused by:\n  expected a config include path ending with `.toml`, but found `config.png` from `[ROOT]/.cargo/config.toml`\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn cycle() {\n    // Detects a cycle.\n    write_config_at(\".cargo/config.toml\", \"include=['one.toml']\");\n    write_config_at(\".cargo/one.toml\", \"include=['two.toml']\");\n    write_config_at(\".cargo/two.toml\", \"include=['config.toml']\");\n    let gctx = GlobalContextBuilder::new().build();\n    assert_error(\n        gctx.get::<bool>(\"foo\").unwrap_err(),\n        str![[r#\"\ncould not load Cargo configuration\n\nCaused by:\n  failed to load config include `one.toml` from `[ROOT]/.cargo/config.toml`\n\nCaused by:\n  failed to load config include `two.toml` from `[ROOT]/.cargo/one.toml`\n\nCaused by:\n  failed to load config include `config.toml` from `[ROOT]/.cargo/two.toml`\n\nCaused by:\n  config `include` cycle detected with path `[ROOT]/.cargo/config.toml`\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn cli_include() {\n    // Using --config with include.\n    // CLI takes priority over files.\n    write_config_at(\n        \".cargo/config.toml\",\n        \"\n        foo = 1\n        bar = 2\n        \",\n    );\n    write_config_at(\".cargo/config-foo.toml\", \"foo = 2\");\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"include=['.cargo/config-foo.toml']\")\n        .build();\n    assert_eq!(gctx.get::<i32>(\"foo\").unwrap(), 2);\n    assert_eq!(gctx.get::<i32>(\"bar\").unwrap(), 2);\n}\n\n#[cargo_test]\nfn bad_format() {\n    // Not a valid format.\n    write_config_toml(\"include = 1\");\n    // Config values are lazy loaded and fail at first retrieval.\n    // This ensures simple commands like `cargo --version` working even when\n    let gctx = GlobalContextBuilder::new().build();\n    assert_error(\n        gctx.get::<bool>(\"foo\").unwrap_err(),\n        str![[r#\"\ncould not load Cargo configuration\n\nCaused by:\n  expected a list of strings or a list of tables, but found integer at `include` in `[ROOT]/.cargo/config.toml\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn cli_include_failed() {\n    // Error message when CLI include fails to load.\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"include=['foobar.toml']\")\n        .build_err();\n    assert_error(\n        gctx.unwrap_err(),\n        str![[r#\"\nfailed to load --config include\n\nCaused by:\n  failed to load config include `foobar.toml` from `--config cli option`\n\nCaused by:\n  failed to read configuration file `[ROOT]/foobar.toml`\n\nCaused by:\n  [NOT_FOUND]\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn cli_merge_failed() {\n    // Error message when CLI include merge fails.\n    write_config_toml(\"foo = ['a']\");\n    write_config_at(\n        \".cargo/other.toml\",\n        \"\n        foo = 'b'\n        \",\n    );\n    let gctx = GlobalContextBuilder::new()\n        .config_arg(\"include=['.cargo/other.toml']\")\n        .build_err();\n    // Maybe this error message should mention it was from an include file?\n    assert_error(\n        gctx.unwrap_err(),\n        str![[r#\"\nfailed to merge key `foo` between [ROOT]/.cargo/config.toml and [ROOT]/.cargo/other.toml\n\nCaused by:\n  failed to merge config value from `[ROOT]/.cargo/other.toml` into `[ROOT]/.cargo/config.toml`: expected array, but found string\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn cli_include_take_priority_over_env() {\n    write_config_at(\".cargo/include.toml\", \"k='include'\");\n\n    // k=env\n    let gctx = GlobalContextBuilder::new().env(\"CARGO_K\", \"env\").build();\n    assert_eq!(gctx.get::<String>(\"k\").unwrap(), \"env\");\n\n    // k=env\n    // --config 'include=\".cargo/include.toml\"'\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_K\", \"env\")\n        .config_arg(\"include=['.cargo/include.toml']\")\n        .build();\n    assert_eq!(gctx.get::<String>(\"k\").unwrap(), \"include\");\n\n    // k=env\n    // --config '.cargo/foo.toml'\n    write_config_at(\".cargo/foo.toml\", \"include=['include.toml']\");\n    let gctx = GlobalContextBuilder::new()\n        .env(\"CARGO_K\", \"env\")\n        .config_arg(\".cargo/foo.toml\")\n        .build();\n    assert_eq!(gctx.get::<String>(\"k\").unwrap(), \"include\");\n}\n\n#[cargo_test]\nfn inline_table_style() {\n    write_config_at(\n        \".cargo/config.toml\",\n        \"\n        include = ['simple.toml', { path = 'other.toml' }]\n        key1 = 1\n        key2 = 2\n        \",\n    );\n    write_config_at(\n        \".cargo/simple.toml\",\n        \"\n        key2 = 3\n        key3 = 4\n        \",\n    );\n    write_config_at(\n        \".cargo/other.toml\",\n        \"\n        key3 = 5\n        key4 = 6\n        \",\n    );\n\n    let gctx = GlobalContextBuilder::new().build();\n    assert_eq!(gctx.get::<i32>(\"key1\").unwrap(), 1);\n    assert_eq!(gctx.get::<i32>(\"key2\").unwrap(), 2);\n    assert_eq!(gctx.get::<i32>(\"key3\").unwrap(), 5);\n    assert_eq!(gctx.get::<i32>(\"key4\").unwrap(), 6);\n}\n\n#[cargo_test]\nfn array_of_tables_style() {\n    write_config_at(\n        \".cargo/config.toml\",\n        \"\n        key1 = 1\n        key2 = 2\n\n        [[include]]\n        path = 'other1.toml'\n\n        [[include]]\n        path = 'other2.toml'\n        \",\n    );\n    write_config_at(\n        \".cargo/other1.toml\",\n        \"\n        key2 = 3\n        key3 = 4\n        \",\n    );\n    write_config_at(\n        \".cargo/other2.toml\",\n        \"\n        key3 = 5\n        key4 = 6\n        \",\n    );\n\n    let gctx = GlobalContextBuilder::new().build();\n    assert_eq!(gctx.get::<i32>(\"key1\").unwrap(), 1);\n    assert_eq!(gctx.get::<i32>(\"key2\").unwrap(), 2);\n    assert_eq!(gctx.get::<i32>(\"key3\").unwrap(), 5);\n    assert_eq!(gctx.get::<i32>(\"key4\").unwrap(), 6);\n}\n\n#[cargo_test]\nfn table_with_unknown_fields() {\n    // Unknown fields should be ignored for forward compatibility\n    write_config_at(\n        \".cargo/config.toml\",\n        \"\n        key1 = 1\n\n        [[include]]\n        path = 'other.toml'\n        unknown_foo = true\n        unknown_bar = 123\n        \",\n    );\n    write_config_at(\n        \".cargo/other.toml\",\n        \"\n        key2 = 2\n        \",\n    );\n\n    let gctx = GlobalContextBuilder::new().build();\n    assert_eq!(gctx.get::<i32>(\"key1\").unwrap(), 1);\n    assert_eq!(gctx.get::<i32>(\"key2\").unwrap(), 2);\n}\n\n#[cargo_test]\nfn table_missing_required_field() {\n    // Missing required field should fail\n    write_config_at(\n        \".cargo/config.toml\",\n        \"\n        key1 = 1\n        [[include]]\n        random_field = true\n        \",\n    );\n\n    // Config values are lazy loaded and fail at first retrieval.\n    // This ensures simple commands like `cargo --version` working even when\n    let gctx = GlobalContextBuilder::new().build();\n    assert_error(\n        gctx.get::<bool>(\"foo\").unwrap_err(),\n        str![[r#\"\ncould not load Cargo configuration\n\nCaused by:\n  missing field `path` at `include[0]` in `[ROOT]/.cargo/config.toml`\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn optional_include_missing_and_existing() {\n    write_config_at(\n        \".cargo/config.toml\",\n        \"\n        key1 = 1\n\n        [[include]]\n        path = 'missing.toml'\n        optional = true\n\n        [[include]]\n        path = 'other.toml'\n        optional = true\n        \",\n    );\n    write_config_at(\n        \".cargo/other.toml\",\n        \"\n        key2 = 2\n        \",\n    );\n\n    let gctx = GlobalContextBuilder::new().build();\n    assert_eq!(gctx.get::<i32>(\"key1\").unwrap(), 1);\n    assert_eq!(gctx.get::<i32>(\"key2\").unwrap(), 2);\n}\n\n#[cargo_test]\nfn optional_false_missing_file() {\n    write_config_at(\n        \".cargo/config.toml\",\n        \"\n        key1 = 1\n\n        [[include]]\n        path = 'missing.toml'\n        optional = false\n        \",\n    );\n\n    // Config values are lazy loaded and fail at first retrieval.\n    // This ensures simple commands like `cargo --version` working even when\n    let gctx = GlobalContextBuilder::new().build();\n    assert_error(\n        gctx.get::<bool>(\"foo\").unwrap_err(),\n        str![[r#\"\ncould not load Cargo configuration\n\nCaused by:\n  failed to load config include `missing.toml` from `[ROOT]/.cargo/config.toml`\n\nCaused by:\n  failed to read configuration file `[ROOT]/.cargo/missing.toml`\n\nCaused by:\n  [NOT_FOUND]\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn disallow_glob_syntax() {\n    // Reserved for future extension\n    write_config_toml(\"include = ['config-*.toml']\");\n    // Config values are lazy loaded and fail at first retrieval.\n    // This ensures simple commands like `cargo --version` working even when\n    let gctx = GlobalContextBuilder::new().build();\n    assert_error(\n        gctx.get::<bool>(\"foo\").unwrap_err(),\n        str![[r#\"\ncould not load Cargo configuration\n\nCaused by:\n  expected a config include path without glob patterns, but found `config-*.toml` from `[ROOT]/.cargo/config.toml`\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn disallow_template_syntax() {\n    // Reserved for future extension\n    write_config_toml(\"include = ['{workspace-root}/config.toml']\");\n    // Config values are lazy loaded and fail at first retrieval.\n    // This ensures simple commands like `cargo --version` working even when\n    let gctx = GlobalContextBuilder::new().build();\n    assert_error(\n        gctx.get::<bool>(\"foo\").unwrap_err(),\n        str![[r#\"\ncould not load Cargo configuration\n\nCaused by:\n  expected a config include path without template braces, but found `{workspace-root}/config.toml` from `[ROOT]/.cargo/config.toml`\n\"#]],\n    );\n}\n"
  },
  {
    "path": "tests/testsuite/corrupt_git.rs",
    "content": "//! Tests for corrupt git repos.\n\nuse std::fs;\nuse std::path::{Path, PathBuf};\n\nuse crate::prelude::*;\nuse cargo_test_support::paths;\nuse cargo_test_support::{basic_manifest, git, project};\nuse cargo_util::paths as cargopaths;\n\n#[cargo_test]\nfn deleting_database_files() {\n    let project = project();\n    let git_project = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    authors = []\n\n                    [dependencies]\n                    bar = {{ git = '{}' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    project.cargo(\"check\").run();\n\n    let mut files = Vec::new();\n    find_files(&paths::home().join(\".cargo/git/db\"), &mut files);\n    assert!(!files.is_empty());\n\n    let log = \"cargo::sources::git=trace\";\n    for file in files {\n        if !file.exists() {\n            continue;\n        }\n        println!(\"deleting {}\", file.display());\n        cargopaths::remove_file(&file).unwrap();\n        project.cargo(\"check -v\").env(\"CARGO_LOG\", log).run();\n\n        if !file.exists() {\n            continue;\n        }\n        println!(\"truncating {}\", file.display());\n        make_writable(&file);\n        fs::OpenOptions::new()\n            .write(true)\n            .open(&file)\n            .unwrap()\n            .set_len(2)\n            .unwrap();\n        project.cargo(\"check -v\").env(\"CARGO_LOG\", log).run();\n    }\n}\n\n#[cargo_test]\nfn deleting_checkout_files() {\n    let project = project();\n    let git_project = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    authors = []\n\n                    [dependencies]\n                    bar = {{ git = '{}' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    project.cargo(\"check\").run();\n\n    let dir = paths::home()\n        .join(\".cargo/git/checkouts\")\n        // get the first entry in the checkouts dir for the package's location\n        .read_dir()\n        .unwrap()\n        .next()\n        .unwrap()\n        .unwrap()\n        .path()\n        // get the first child of that checkout dir for our checkout\n        .read_dir()\n        .unwrap()\n        .next()\n        .unwrap()\n        .unwrap()\n        .path()\n        // and throw on .git to corrupt things\n        .join(\".git\");\n    let mut files = Vec::new();\n    find_files(&dir, &mut files);\n    assert!(!files.is_empty());\n\n    let log = \"cargo::sources::git=trace\";\n    for file in files {\n        if !file.exists() {\n            continue;\n        }\n        println!(\"deleting {}\", file.display());\n        cargopaths::remove_file(&file).unwrap();\n        project.cargo(\"check -v\").env(\"CARGO_LOG\", log).run();\n\n        if !file.exists() {\n            continue;\n        }\n        println!(\"truncating {}\", file.display());\n        make_writable(&file);\n        fs::OpenOptions::new()\n            .write(true)\n            .open(&file)\n            .unwrap()\n            .set_len(2)\n            .unwrap();\n        project.cargo(\"check -v\").env(\"CARGO_LOG\", log).run();\n    }\n}\n\nfn make_writable(path: &Path) {\n    let mut p = path.metadata().unwrap().permissions();\n    p.set_readonly(false);\n    fs::set_permissions(path, p).unwrap();\n}\n\nfn find_files(path: &Path, dst: &mut Vec<PathBuf>) {\n    for e in path.read_dir().unwrap() {\n        let e = e.unwrap();\n        let path = e.path();\n        if e.file_type().unwrap().is_dir() {\n            find_files(&path, dst);\n        } else {\n            dst.push(path);\n        }\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/credential_process.rs",
    "content": "//! Tests for credential-process.\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::registry::{Package, TestRegistry};\nuse cargo_test_support::{Project, basic_manifest, paths, project, registry, str};\n\nfn toml_bin(proj: &Project, name: &str) -> String {\n    proj.bin(name).display().to_string().replace('\\\\', \"\\\\\\\\\")\n}\n\n/// Setup for a test that will issue a command that needs to fetch a token.\n///\n/// This does the following:\n///\n/// * Spawn a thread that will act as an API server.\n/// * Create a simple credential-process that will generate a fake token.\n/// * Create a simple `foo` project to run the test against.\n/// * Configure the credential-process config.\n///\n/// Returns the simple `foo` project to test against and the API server handle.\nfn get_token_test() -> (Project, TestRegistry) {\n    // API server that checks that the token is included correctly.\n    let server = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .token(cargo_test_support::registry::Token::Plaintext(\n            \"sekrit\".to_string(),\n        ))\n        .alternative()\n        .http_api()\n        .http_index()\n        .auth_required()\n        .build();\n\n    let provider = build_provider(\n        \"test-cred\",\n        r#\"{\"Ok\":{\"kind\":\"get\",\"token\":\"sekrit\",\"cache\":\"session\",\"operation_independent\":false}}\"#,\n    );\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [registries.alternative]\n                    index = \"{}\"\n                    credential-provider = [\"{provider}\"]\n                \"#,\n                server.index_url(),\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                description = \"foo\"\n                license = \"MIT\"\n                homepage = \"https://example.com/\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    (p, server)\n}\n\n#[cargo_test]\nfn publish() {\n    // Checks that credential-process is used for `cargo publish`.\n    let (p, _t) = get_token_test();\n\n    p.cargo(\"publish --no-verify --registry alternative\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n{\"v\":1,\"registry\":{\"index-url\":\"[..]\",\"name\":\"alternative\",\"headers\":[..]},\"kind\":\"get\",\"operation\":\"read\"}\n[PACKAGING] foo v0.1.0 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.1.0 ([ROOT]/foo)\n{\"v\":1,\"registry\":{\"index-url\":\"[..]\",\"name\":\"alternative\"},\"kind\":\"get\",\"operation\":\"publish\",\"name\":\"foo\",\"vers\":\"0.1.0\",\"cksum\":\"[..]\"}\n[UPLOADED] foo v0.1.0 to registry `alternative`\n[NOTE] waiting for foo v0.1.0 to be available at registry `alternative`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.1.0 at registry `alternative`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn credential_provider_auth_failure() {\n    let _reg = registry::RegistryBuilder::new()\n        .http_index()\n        .auth_required()\n        .alternative()\n        .no_configure_token()\n        .credential_provider(&[\"cargo:token-from-stdout\", \"true\"])\n        .build();\n\n    cargo_process(\"install libc --registry=alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] token rejected for `alternative`\nYou may need to log in using this registry's credential provider\n\nCaused by:\n  failed to get successful HTTP response from [..]\n  body:\n  [..]\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn basic_unsupported() {\n    // Non-action commands don't support login/logout.\n    let registry = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .credential_provider(&[\"cargo:token-from-stdout\", \"false\"])\n        .build();\n\n    cargo_process(\"login\")\n        .with_stdin(\"abcdefg\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] credential provider `cargo:token-from-stdout false` failed action `login`\n\nCaused by:\n  requested operation not supported\n\n\"#]])\n        .run();\n\n    cargo_process(\"logout\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] credential provider `cargo:token-from-stdout false` failed action `logout`\n\nCaused by:\n  requested operation not supported\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn login() {\n    let registry = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .credential_provider(&[\n            &build_provider(\"test-cred\", r#\"{\"Ok\": {\"kind\": \"login\"}}\"#),\n            \"cfg1\",\n            \"--cfg2\",\n        ])\n        .build();\n\n    cargo_process(\"login -- cmd3 --cmd4\")\n        .with_stdin(\"abcdefg\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n{\"v\":1,\"registry\":{\"index-url\":\"https://github.com/rust-lang/crates.io-index\",\"name\":\"crates-io\"},\"kind\":\"login\",\"token\":\"abcdefg\",\"login-url\":\"[ROOTURL]/api/me\",\"args\":[\"cfg1\",\"--cfg2\",\"cmd3\",\"--cmd4\"]}\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn logout() {\n    let server = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .credential_provider(&[&build_provider(\n            \"test-cred\",\n            r#\"{\"Ok\": {\"kind\": \"logout\"}}\"#,\n        )])\n        .build();\n\n    cargo_process(\"logout\")\n        .replace_crates_io(server.index_url())\n        .with_stderr_data(str![[r#\"\n{\"v\":1,\"registry\":{\"index-url\":\"https://github.com/rust-lang/crates.io-index\",\"name\":\"crates-io\"},\"kind\":\"logout\"}\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn yank() {\n    let (p, _t) = get_token_test();\n\n    p.cargo(\"yank --version 0.1.0 --registry alternative\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n{\"v\":1,\"registry\":{\"index-url\":\"[..]\",\"name\":\"alternative\",\"headers\":[..]},\"kind\":\"get\",\"operation\":\"read\"}\n{\"v\":1,\"registry\":{\"index-url\":\"[..]\",\"name\":\"alternative\"},\"kind\":\"get\",\"operation\":\"yank\",\"name\":\"foo\",\"vers\":\"0.1.0\"}\n[YANK] foo@0.1.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn owner() {\n    let (p, _t) = get_token_test();\n\n    p.cargo(\"owner --add username --registry alternative\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n{\"v\":1,\"registry\":{\"index-url\":\"[..]\",\"name\":\"alternative\",\"headers\":[..]},\"kind\":\"get\",\"operation\":\"read\"}\n{\"v\":1,\"registry\":{\"index-url\":\"[..]\",\"name\":\"alternative\"},\"kind\":\"get\",\"operation\":\"owners\",\"name\":\"foo\"}\n[OWNER] completed!\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_token_output() {\n    // Error when credential process does not output the expected format for a token.\n    let cred_proj = project()\n        .at(\"cred_proj\")\n        .file(\"Cargo.toml\", &basic_manifest(\"test-cred\", \"1.0.0\"))\n        .file(\"src/main.rs\", r#\"fn main() { print!(\"a\\nb\\n\"); } \"#)\n        .build();\n    cred_proj.cargo(\"build\").run();\n    let _server = registry::RegistryBuilder::new()\n        .alternative()\n        .credential_provider(&[\n            \"cargo:token-from-stdout\",\n            &toml_bin(&cred_proj, \"test-cred\"),\n        ])\n        .no_configure_token()\n        .build();\n\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] credential provider `[..]test-cred[EXE]` failed action `get`\n\nCaused by:\n  process `[..]` returned more than one line of output; expected a single token\n\n\"#]])\n        .run();\n}\n\n/// Builds a credential provider that echos the request from cargo to stderr,\n/// and prints the `response` to stdout.\nfn build_provider(name: &str, response: &str) -> String {\n    // The credential process to use.\n    let cred_proj = project()\n        .at(name)\n        .file(\"Cargo.toml\", &basic_manifest(name, \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            &r####\"\n                fn main() {\n                    println!(r#\"{{\"v\":[1]}}\"#);\n                    assert_eq!(std::env::args().skip(1).next().unwrap(), \"--cargo-plugin\");\n                    let mut buffer = String::new();\n                    std::io::stdin().read_line(&mut buffer).unwrap();\n                    eprint!(\"{}\", buffer);\n                    use std::io::Write;\n                    std::io::stdout().write_all(r###\"[RESPONSE]\"###.as_bytes()).unwrap();\n                    println!();\n                } \"####\n                .replace(\"[RESPONSE]\", response),\n        )\n        .build();\n    cred_proj.cargo(\"build\").run();\n    toml_bin(&cred_proj, name)\n}\n\n#[cargo_test]\nfn not_found() {\n    let registry = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .http_index()\n        .auth_required()\n        .credential_provider(&[&build_provider(\n            \"not_found\",\n            r#\"{\"Err\": {\"kind\": \"not-found\"}}\"#,\n        )])\n        .build();\n\n    // should not suggest a _TOKEN environment variable since the cargo:token provider isn't available.\n    cargo_process(\"install -v foo\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[CREDENTIAL] [..]not_found[..] get crates-io\n{\"v\":1[..]\n[ERROR] no token found, please run `cargo login`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn all_not_found() {\n    let server = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .auth_required()\n        .http_index()\n        .build();\n    let not_found = build_provider(\"not_found\", r#\"{\"Err\": {\"kind\": \"not-found\"}}\"#);\n    cargo_util::paths::append(\n        &paths::home().join(\".cargo/config.toml\"),\n        format!(\n            r#\"\n                [registry]\n                global-credential-providers = [\"not_found\"]\n                [credential-alias]\n                not_found = [\"{not_found}\"]\n            \"#,\n        )\n        .as_bytes(),\n    )\n    .unwrap();\n\n    // should not suggest a _TOKEN environment variable since the cargo:token provider isn't available.\n    cargo_process(\"install -v foo\")\n        .replace_crates_io(server.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[CREDENTIAL] [..]not_found[..] get crates-io\n{\"v\":1,\"registry\":{\"index-url\":\"[..]\",\"name\":\"crates-io\",\"headers\":[[..]\"www-authenticate: Cargo login_url=/\"https://test-registry-login/me/\"\"[..]]},\"kind\":\"get\",\"operation\":\"read\"}\n[ERROR] no token found, please run `cargo login`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn all_not_supported() {\n    let server = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .auth_required()\n        .http_index()\n        .build();\n    let not_supported =\n        build_provider(\"not_supported\", r#\"{\"Err\": {\"kind\": \"url-not-supported\"}}\"#);\n    cargo_util::paths::append(\n        &paths::home().join(\".cargo/config.toml\"),\n        format!(\n            r#\"\n                [registry]\n                global-credential-providers = [\"not_supported\"]\n                [credential-alias]\n                not_supported = [\"{not_supported}\"]\n            \"#,\n        )\n        .as_bytes(),\n    )\n    .unwrap();\n\n    cargo_process(\"install -v foo\")\n        .replace_crates_io(server.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[CREDENTIAL] [..]not_supported[..] get crates-io\n{\"v\":1,\"registry\":{\"index-url\":\"[..]\",\"name\":\"crates-io\",\"headers\":[[..]\"www-authenticate: Cargo login_url=/\"https://test-registry-login/me/\"\"[..]]},\"kind\":\"get\",\"operation\":\"read\"}\n[ERROR] no credential providers could handle the request\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_providers() {\n    let server = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .build();\n\n    // Set up two credential providers: the first will fail with \"UrlNotSupported\"\n    // and Cargo should skip it. The second should succeed.\n    let url_not_supported = build_provider(\n        \"url_not_supported\",\n        r#\"{\"Err\": {\"kind\": \"url-not-supported\"}}\"#,\n    );\n\n    let success_provider = build_provider(\"success_provider\", r#\"{\"Ok\": {\"kind\": \"login\"}}\"#);\n\n    cargo_util::paths::append(\n        &paths::home().join(\".cargo/config.toml\"),\n        format!(\n            r#\"\n                [registry]\n                global-credential-providers = [\"success_provider\", \"url_not_supported\"]\n\n                [credential-alias]\n                success_provider = [\"{success_provider}\"]\n                url_not_supported = [\"{url_not_supported}\"]\n            \"#,\n        )\n        .as_bytes(),\n    )\n    .unwrap();\n\n    cargo_process(\"login -v\")\n    .with_stdin(\"abcdefg\")\n        .replace_crates_io(server.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[CREDENTIAL] [..]url_not_supported[..] login crates-io\n{\"v\":1,\"registry\":{\"index-url\":\"https://github.com/rust-lang/crates.io-index\",\"name\":\"crates-io\"},\"kind\":\"login\",\"token\":\"abcdefg\",\"login-url\":\"[ROOTURL]/api/me\"}\n[CREDENTIAL] [..]success_provider[..] login crates-io\n{\"v\":1,\"registry\":{\"index-url\":\"https://github.com/rust-lang/crates.io-index\",\"name\":\"crates-io\"},\"kind\":\"login\",\"token\":\"abcdefg\",\"login-url\":\"[ROOTURL]/api/me\"}\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn both_token_and_provider() {\n    let server = registry::RegistryBuilder::new()\n        .credential_provider(&[\"cargo:paseto\"])\n        .build();\n\n    cargo_process(\"login -Z asymmetric-token\")\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .replace_crates_io(server.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] registry `crates-io` has a token configured in [ROOT]/home/.cargo/credentials.toml that will be ignored because this registry is configured to use credential-provider `cargo:paseto`\nk3.public[..]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn registry_provider_overrides_global() {\n    let server = registry::RegistryBuilder::new().build();\n    cargo_util::paths::append(\n        &paths::home().join(\".cargo/config.toml\"),\n        format!(\n            r#\"\n                [registry]\n                global-credential-providers = [\"should-not-be-called\"]\n            \"#,\n        )\n        .as_bytes(),\n    )\n    .unwrap();\n\n    cargo_process(\"login -v\")\n        .with_stdin(\"abcdefg\")\n        .env(\"CARGO_REGISTRY_CREDENTIAL_PROVIDER\", \"cargo:token\")\n        .replace_crates_io(server.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[CREDENTIAL] cargo:token login crates-io\n[LOGIN] token for `crates-io` saved\n\n\"#]])\n        .run();\n    let credentials =\n        std::fs::read_to_string(paths::home().join(\".cargo/credentials.toml\")).unwrap();\n    assert_eq!(credentials, \"[registry]\\ntoken = \\\"abcdefg\\\"\\n\");\n}\n\n#[cargo_test]\nfn both_asymmetric_and_token() {\n    let server = registry::RegistryBuilder::new().build();\n    cargo_util::paths::append(\n        &paths::home().join(\".cargo/config.toml\"),\n        format!(\n            r#\"\n                [registry]\n                token = \"foo\"\n                secret-key = \"bar\"\n            \"#,\n        )\n        .as_bytes(),\n    )\n    .unwrap();\n\n    cargo_process(\"login -Zasymmetric-token -v\").with_stdin(\"abcdefg\")\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .replace_crates_io(server.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] registry `crates-io` has a `secret_key` configured in [..]config.toml that will be ignored because a `token` is also configured, and the `cargo:token` provider is configured with higher precedence\n[CREDENTIAL] cargo:token login crates-io\n[LOGIN] token for `crates-io` saved\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn token_caching() {\n    let server = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .no_configure_registry()\n        .token(cargo_test_support::registry::Token::Plaintext(\n            \"sekrit\".to_string(),\n        ))\n        .alternative()\n        .http_api()\n        .http_index()\n        .build();\n\n    // Token should not be re-used if it is expired\n    let expired_provider = build_provider(\n        \"expired_provider\",\n        r#\"{\"Ok\":{\"kind\":\"get\",\"token\":\"sekrit\",\"cache\":\"expires\",\"expiration\":0,\"operation_independent\":true}}\"#,\n    );\n\n    // Token should not be re-used for a different operation if it is not operation_independent\n    let non_independent_provider = build_provider(\n        \"non_independent_provider\",\n        r#\"{\"Ok\":{\"kind\":\"get\",\"token\":\"sekrit\",\"cache\":\"session\",\"operation_independent\":false}}\"#,\n    );\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [registries.alternative]\n                    index = \"{}\"\n                    credential-provider = [\"{expired_provider}\"]\n                \"#,\n                server.index_url(),\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                description = \"foo\"\n                license = \"MIT\"\n                homepage = \"https://example.com/\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let output = str![[r#\"\n[UPDATING] `alternative` index\n{\"v\":1,\"registry\":{\"index-url\":\"[..]\",\"name\":\"alternative\"},\"kind\":\"get\",\"operation\":\"read\"}\n[PACKAGING] foo v0.1.0 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.1.0 ([ROOT]/foo)\n{\"v\":1,\"registry\":{\"index-url\":\"[..]\",\"name\":\"alternative\"},\"kind\":\"get\",\"operation\":\"publish\",\"name\":\"foo\",\"vers\":\"0.1.0\",\"cksum\":\"[..]\"}\n[UPLOADED] foo v0.1.0 to registry `alternative`\n[NOTE] waiting [..]\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.1.0 at registry `alternative`\n\n\"#]];\n\n    // The output should contain two JSON messages from the provider in both cases:\n    // The first because the credential is expired, the second because the provider\n    // indicated that the token was non-operation-independent.\n    p.cargo(\"publish --registry alternative --no-verify\")\n        .with_stderr_data(output)\n        .run();\n\n    let output_non_independent = str![[r#\"\n[UPDATING] `alternative` index\n{\"v\":1,\"registry\":{\"index-url\":\"[..]\",\"name\":\"alternative\"},\"kind\":\"get\",\"operation\":\"read\"}\n[PACKAGING] foo v0.1.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.1.1 ([ROOT]/foo)\n{\"v\":1,\"registry\":{\"index-url\":\"[..]\",\"name\":\"alternative\"},\"kind\":\"get\",\"operation\":\"publish\",\"name\":\"foo\",\"vers\":\"0.1.1\",\"cksum\":\"[..]\"}\n[UPLOADED] foo v0.1.1 to registry `alternative`\n[NOTE] waiting [..]\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.1.1 at registry `alternative`\n\n\"#]];\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n        [package]\n        name = \"foo\"\n        version = \"0.1.1\"\n        edition = \"2015\"\n        description = \"foo\"\n        license = \"MIT\"\n        homepage = \"https://example.com/\"\n    \"#,\n    );\n\n    p.change_file(\n        \".cargo/config.toml\",\n        &format!(\n            r#\"\n                [registries.alternative]\n                index = \"{}\"\n                credential-provider = [\"{non_independent_provider}\"]\n            \"#,\n            server.index_url(),\n        ),\n    );\n\n    p.cargo(\"publish --registry alternative --no-verify\")\n        .with_stderr_data(output_non_independent)\n        .run();\n}\n\n#[cargo_test]\nfn basic_provider() {\n    let cred_proj = project()\n        .at(\"cred_proj\")\n        .file(\"Cargo.toml\", &basic_manifest(\"test-cred\", \"1.0.0\"))\n        .file(\"src/main.rs\", r#\"fn main() {\n            eprintln!(\"CARGO={:?}\", std::env::var(\"CARGO\").ok());\n            eprintln!(\"CARGO_REGISTRY_NAME_OPT={:?}\", std::env::var(\"CARGO_REGISTRY_NAME_OPT\").ok());\n            eprintln!(\"CARGO_REGISTRY_INDEX_URL={:?}\", std::env::var(\"CARGO_REGISTRY_INDEX_URL\").ok());\n            print!(\"sekrit\"); \n        }\"#)\n        .build();\n    cred_proj.cargo(\"build\").run();\n\n    let _server = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .credential_provider(&[\n            \"cargo:token-from-stdout\",\n            &toml_bin(&cred_proj, \"test-cred\"),\n        ])\n        .token(cargo_test_support::registry::Token::Plaintext(\n            \"sekrit\".to_string(),\n        ))\n        .alternative()\n        .http_api()\n        .auth_required()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies.bar]\n                version = \"0.0.1\"\n                registry = \"alternative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    Package::new(\"bar\", \"0.0.1\").alternative(true).publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\nCARGO=Some([..])\nCARGO_REGISTRY_NAME_OPT=Some(\"alternative\")\nCARGO_REGISTRY_INDEX_URL=Some(\"[ROOTURL]/alternative-registry\")\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `alternative`)\n[CHECKING] bar v0.0.1 (registry `alternative`)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unsupported_version() {\n    let cred_proj = project()\n        .at(\"new-vers\")\n        .file(\"Cargo.toml\", &basic_manifest(\"new-vers\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            &r####\"\n                fn main() {\n                    println!(r#\"{{\"v\":[998, 999]}}\"#);\n                    assert_eq!(std::env::args().skip(1).next().unwrap(), \"--cargo-plugin\");\n                    let mut buffer = String::new();\n                    std::io::stdin().read_line(&mut buffer).unwrap();\n                    std::thread::sleep(std::time::Duration::from_secs(1));\n                    panic!(\"child process should have been killed before getting here\");\n                } \"####,\n        )\n        .build();\n    cred_proj.cargo(\"build\").run();\n    let provider = toml_bin(&cred_proj, \"new-vers\");\n\n    let registry = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .credential_provider(&[&provider])\n        .build();\n\n    cargo_process(\"login\")\n        .with_stdin(\"abcdefg\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] credential provider `[..]` failed action `login`\n\nCaused by:\n  credential provider supports protocol versions [998, 999], while Cargo supports [1]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn alias_builtin_warning() {\n    let registry = registry::RegistryBuilder::new()\n        .credential_provider(&[&\"cargo:token\"])\n        .build();\n\n    cargo_util::paths::append(\n        &paths::home().join(\".cargo/config.toml\"),\n        format!(\n            r#\"\n                [credential-alias]\n                \"cargo:token\" = [\"ignored\"]\n            \"#,\n        )\n        .as_bytes(),\n    )\n    .unwrap();\n\n    cargo_process(\"login\")\n        .with_stdin(\"abcdefg\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] credential-alias `cargo:token` (defined in `[ROOT]/home/.cargo/config.toml`) will be ignored because it would shadow a built-in credential-provider\n[LOGIN] token for `crates-io` saved\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn login_token_from_stdin() {\n    // Test reading a token from stdin, ensuring newlines are trimmed.\n    let registry = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .credential_provider(&[&build_provider(\"test-cred\", r#\"{\"Ok\": {\"kind\": \"login\"}}\"#)])\n        .build();\n\n    cargo_process(\"login\")\n        .replace_crates_io(registry.index_url())\n        .with_stdin(\"abcdefg\\n\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n{\"v\":1,\"registry\":{\"index-url\":\"https://github.com/rust-lang/crates.io-index\",\"name\":\"crates-io\"},\"kind\":\"login\",\"token\":\"abcdefg\",\"login-url\":\"[ROOTURL]/api/me\"}\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cross_compile.rs",
    "content": "//! Tests for cross compiling with --target.\n//!\n//! See `cargo_test_support::cross_compile` for more detail.\n\nuse crate::prelude::*;\nuse cargo_test_support::rustc_host;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_bin_manifest, basic_manifest, cross_compile, project};\n\nuse crate::utils::cross_compile::{\n    can_run_on_host as cross_compile_can_run_on_host, disabled as cross_compile_disabled,\n};\n\n#[cargo_test]\nfn simple_cross() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            &format!(\n                r#\"\n                    fn main() {{\n                        assert_eq!(std::env::var(\"TARGET\").unwrap(), \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            &format!(\n                r#\"\n                    use std::env;\n                    fn main() {{\n                        assert_eq!(env::consts::ARCH, \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .build();\n\n    let target = cross_compile::alternate();\n    p.cargo(\"build -v --target\").arg(&target).run();\n    assert!(p.target_bin(target, \"foo\").is_file());\n\n    if cross_compile_can_run_on_host() {\n        p.process(&p.target_bin(target, \"foo\")).run();\n    }\n}\n\n#[cargo_test]\nfn simple_cross_config() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [build]\n                    target = \"{}\"\n                \"#,\n                cross_compile::alternate()\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            &format!(\n                r#\"\n                    fn main() {{\n                        assert_eq!(std::env::var(\"TARGET\").unwrap(), \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            &format!(\n                r#\"\n                    use std::env;\n                    fn main() {{\n                        assert_eq!(env::consts::ARCH, \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .build();\n\n    let target = cross_compile::alternate();\n    p.cargo(\"build -v\").run();\n    assert!(p.target_bin(target, \"foo\").is_file());\n\n    if cross_compile_can_run_on_host() {\n        p.process(&p.target_bin(target, \"foo\")).run();\n    }\n}\n\n#[cargo_test]\nfn target_host_arg() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            &format!(\n                r#\"\n                    fn main() {{\n                        assert_eq!(std::env::var(\"TARGET\").unwrap(), \"{}\");\n                    }}\n                \"#,\n                rustc_host()\n            ),\n        )\n        .file(\"src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"build -v --target host-tuple\")\n        .with_stderr_contains(\"[RUNNING] `rustc [..] --target [HOST_TARGET] [..]`\")\n        .run();\n}\n\n#[cargo_test]\nfn target_host_config() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [build]\n                    target = \"host-tuple\"\n                \"#,\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            &format!(\n                r#\"\n                    fn main() {{\n                        assert_eq!(std::env::var(\"TARGET\").unwrap(), \"{}\");\n                    }}\n                \"#,\n                rustc_host()\n            ),\n        )\n        .file(\"src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_contains(\"[RUNNING] `rustc [..] --target [HOST_TARGET] [..]`\")\n        .run();\n}\n\n#[cargo_test]\nfn simple_deps() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() { bar::bar(); }\")\n        .build();\n    let _p2 = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let target = cross_compile::alternate();\n    p.cargo(\"build --target\").arg(&target).run();\n    assert!(p.target_bin(target, \"foo\").is_file());\n\n    if cross_compile_can_run_on_host() {\n        p.process(&p.target_bin(target, \"foo\")).run();\n    }\n}\n\n/// Always take care of setting these so that\n/// `cross_compile::alternate()` is the actually-picked target\nfn per_crate_target_test(\n    default_target: Option<&'static str>,\n    forced_target: Option<&'static str>,\n    arg_target: Option<&'static str>,\n) {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    cargo-features = [\"per-package-target\"]\n\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.0\"\n                    edition = \"2015\"\n                    authors = []\n                    build = \"build.rs\"\n                    {}\n                    {}\n                \"#,\n                default_target\n                    .map(|t| format!(r#\"default-target = \"{}\"\"#, t))\n                    .unwrap_or(String::new()),\n                forced_target\n                    .map(|t| format!(r#\"forced-target = \"{}\"\"#, t))\n                    .unwrap_or(String::new()),\n            ),\n        )\n        .file(\n            \"build.rs\",\n            &format!(\n                r#\"\n                    fn main() {{\n                        assert_eq!(std::env::var(\"TARGET\").unwrap(), \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            &format!(\n                r#\"\n                    use std::env;\n                    fn main() {{\n                        assert_eq!(env::consts::ARCH, \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .build();\n\n    let mut cmd = p.cargo(\"build -v\");\n    if let Some(t) = arg_target {\n        cmd.arg(\"--target\").arg(&t);\n    }\n    cmd.masquerade_as_nightly_cargo(&[\"per-package-target\"])\n        .run();\n    assert!(p.target_bin(cross_compile::alternate(), \"foo\").is_file());\n\n    if cross_compile_can_run_on_host() {\n        p.process(&p.target_bin(cross_compile::alternate(), \"foo\"))\n            .run();\n    }\n}\n\n#[cargo_test]\nfn per_crate_default_target_is_default() {\n    per_crate_target_test(Some(cross_compile::alternate()), None, None);\n}\n\n#[cargo_test]\nfn per_crate_default_target_gets_overridden() {\n    per_crate_target_test(\n        Some(cross_compile::unused()),\n        None,\n        Some(cross_compile::alternate()),\n    );\n}\n\n#[cargo_test]\nfn per_crate_forced_target_is_default() {\n    per_crate_target_test(None, Some(cross_compile::alternate()), None);\n}\n\n#[cargo_test]\nfn per_crate_forced_target_does_not_get_overridden() {\n    per_crate_target_test(\n        None,\n        Some(cross_compile::alternate()),\n        Some(cross_compile::unused()),\n    );\n}\n\n#[cargo_test]\nfn workspace_with_multiple_targets() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"native\", \"cross\"]\n            \"#,\n        )\n        .file(\n            \"native/Cargo.toml\",\n            r#\"\n                cargo-features = [\"per-package-target\"]\n\n                [package]\n                name = \"native\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"native/build.rs\",\n            &format!(\n                r#\"\n                    fn main() {{\n                        assert_eq!(std::env::var(\"TARGET\").unwrap(), \"{}\");\n                    }}\n                \"#,\n                cross_compile::native()\n            ),\n        )\n        .file(\n            \"native/src/main.rs\",\n            &format!(\n                r#\"\n                    use std::env;\n                    fn main() {{\n                        assert_eq!(env::consts::ARCH, \"{}\");\n                    }}\n                \"#,\n                cross_compile::native_arch()\n            ),\n        )\n        .file(\n            \"cross/Cargo.toml\",\n            &format!(\n                r#\"\n                    cargo-features = [\"per-package-target\"]\n\n                    [package]\n                    name = \"cross\"\n                    version = \"0.0.0\"\n                    edition = \"2015\"\n                    authors = []\n                    build = \"build.rs\"\n                    default-target = \"{}\"\n                \"#,\n                cross_compile::alternate(),\n            ),\n        )\n        .file(\n            \"cross/build.rs\",\n            &format!(\n                r#\"\n                    fn main() {{\n                        assert_eq!(std::env::var(\"TARGET\").unwrap(), \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate()\n            ),\n        )\n        .file(\n            \"cross/src/main.rs\",\n            &format!(\n                r#\"\n                    use std::env;\n                    fn main() {{\n                        assert_eq!(env::consts::ARCH, \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .build();\n\n    let mut cmd = p.cargo(\"build -v\");\n    cmd.masquerade_as_nightly_cargo(&[\"per-package-target\"])\n        .run();\n\n    assert!(p.bin(\"native\").is_file());\n    assert!(p.target_bin(cross_compile::alternate(), \"cross\").is_file());\n\n    p.process(&p.bin(\"native\")).run();\n    if cross_compile_can_run_on_host() {\n        p.process(&p.target_bin(cross_compile::alternate(), \"cross\"))\n            .run();\n    }\n}\n\n#[cargo_test]\nfn linker() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}]\n                    linker = \"my-linker-tool\"\n                \"#,\n                target\n            ),\n        )\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/foo.rs\",\n            &format!(\n                r#\"\n                    use std::env;\n                    fn main() {{\n                        assert_eq!(env::consts::ARCH, \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .build();\n\n    p.cargo(\"build -v --target\")\n        .arg(&target)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] path `src/foo.rs` was erroneously implicitly accepted for binary `foo`,\nplease set bin.path in Cargo.toml\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/foo.rs [..]--crate-type bin --emit=[..]link[..]-C debuginfo=2 [..] -C metadata=[..] --out-dir [ROOT]/foo/target/[ALT_TARGET]/debug/deps --target [ALT_TARGET] -C linker=my-linker-tool -L dependency=[ROOT]/foo/target/[ALT_TARGET]/debug/deps -L dependency=[ROOT]/foo/target/debug/deps`\n[ERROR] linker `my-linker-tool` not found\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cross_tests() {\n    if !cross_compile_can_run_on_host() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"bar\"\n            \"#,\n        )\n        .file(\n            \"src/bin/bar.rs\",\n            &format!(\n                r#\"\n                    #[allow(unused_extern_crates)]\n                    extern crate foo;\n                    use std::env;\n                    fn main() {{\n                        assert_eq!(env::consts::ARCH, \"{}\");\n                    }}\n                    #[test] fn test() {{ main() }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            &format!(\n                r#\"\n                    //! ```\n                    //! extern crate foo;\n                    //! assert!(true);\n                    //! ```\n\n                    use std::env;\n                    pub fn foo() {{ assert_eq!(env::consts::ARCH, \"{}\"); }}\n                    #[test] fn test_foo() {{ foo() }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .build();\n\n    let target = cross_compile::alternate();\n    p.cargo(\"test --target\")\n        .arg(&target)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE])\n[RUNNING] unittests src/bin/bar.rs (target/[ALT_TARGET]/debug/deps/bar-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest test_foo ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest test ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest src/lib.rs - (line 2) ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_cargo_run() {\n    if !cross_compile_can_run_on_host() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            &format!(\n                r#\"\n                    use std::env;\n                    fn main() {{\n                        assert_eq!(env::consts::ARCH, \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .build();\n\n    let target = cross_compile::alternate();\n    p.cargo(\"run --target\").arg(&target).run();\n}\n\n#[cargo_test]\nfn cross_with_a_build_script() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = 'build.rs'\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            &format!(\n                r#\"\n                    use std::env;\n                    use std::path::PathBuf;\n                    fn main() {{\n                        assert_eq!(env::var(\"TARGET\").unwrap(), \"{0}\");\n                        let mut path = PathBuf::from(env::var_os(\"OUT_DIR\").unwrap());\n                        assert_eq!(path.file_name().unwrap().to_str().unwrap(), \"out\");\n                        path.pop();\n                        assert!(path.file_name().unwrap().to_str().unwrap()\n                                    .starts_with(\"foo-\"));\n                        path.pop();\n                        assert_eq!(path.file_name().unwrap().to_str().unwrap(), \"build\");\n                        path.pop();\n                        assert_eq!(path.file_name().unwrap().to_str().unwrap(), \"debug\");\n                        path.pop();\n                        assert_eq!(path.file_name().unwrap().to_str().unwrap(), \"{0}\");\n                        path.pop();\n                        assert_eq!(path.file_name().unwrap().to_str().unwrap(), \"target\");\n                    }}\n                \"#,\n                target\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v --target\")\n        .arg(&target)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] build.rs [..] --out-dir [ROOT]/foo/target/debug/build/foo-[HASH] [..]\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..] src/main.rs [..] --target [ALT_TARGET] [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_script_needed_for_host_and_target() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = 'build.rs'\n\n                [dependencies.d1]\n                path = \"d1\"\n                [build-dependencies.d2]\n                path = \"d2\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                #[allow(unused_extern_crates)]\n                extern crate d2;\n                fn main() { d2::d2(); }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n            #[allow(unused_extern_crates)]\n            extern crate d1;\n            fn main() { d1::d1(); }\n        \",\n        )\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = 'build.rs'\n            \"#,\n        )\n        .file(\"d1/src/lib.rs\", \"pub fn d1() {}\")\n        .file(\n            \"d1/build.rs\",\n            r#\"\n                use std::env;\n                fn main() {\n                    let target = env::var(\"TARGET\").unwrap();\n                    let root = std::env::current_dir().unwrap();\n                    let root = root.parent().unwrap().join(format!(\"link-{target}\"));\n                    println!(\"cargo::rustc-flags=-L {}\", root.display());\n                }\n            \"#,\n        )\n        .file(\n            \"d2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d2\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.d1]\n                path = \"../d1\"\n            \"#,\n        )\n        .file(\n            \"d2/src/lib.rs\",\n            \"\n            #[allow(unused_extern_crates)]\n            extern crate d1;\n            pub fn d2() { d1::d1(); }\n        \",\n        )\n        .build();\n    p.root().join(format!(\"link-{target}\")).mkdir_p();\n    p.root().join(format!(\"link-{}\", rustc_host())).mkdir_p();\n\n    p.cargo(\"build -v --target\")\n        .arg(&target)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] d1 v0.0.0 ([ROOT]/foo/d1)\n[RUNNING] `rustc [..] d1/build.rs [..] --out-dir [ROOT]/foo/target/debug/build/d1-[HASH] [..]\n[RUNNING] `[ROOT]/foo/target/debug/build/d1-[HASH]/build-script-build`\n[RUNNING] `[ROOT]/foo/target/debug/build/d1-[HASH]/build-script-build`\n[RUNNING] `rustc [..] d1/src/lib.rs [..] --out-dir [ROOT]/foo/target/debug/deps [..]\n[RUNNING] `rustc [..] d1/src/lib.rs [..] --out-dir [ROOT]/foo/target/[ALT_TARGET]/debug/deps [..]\n[COMPILING] d2 v0.0.0 ([ROOT]/foo/d2)\n[RUNNING] `rustc [..] d2/src/lib.rs [..] --out-dir [ROOT]/foo/target/debug/deps [..]-L [ROOT]/foo/link-[HOST_TARGET]`\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] build.rs [..] --out-dir [ROOT]/foo/target/debug/build/foo-[HASH] [..]-L [ROOT]/foo/link-[HOST_TARGET]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..] src/main.rs [..] --out-dir [ROOT]/foo/target/[ALT_TARGET]/debug/deps --target [ALT_TARGET] [..]-L [ROOT]/foo/link-[ALT_TARGET]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn build_deps_for_the_right_arch() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.d2]\n                path = \"d2\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate d2; fn main() {}\")\n        .file(\"d1/Cargo.toml\", &basic_manifest(\"d1\", \"0.0.0\"))\n        .file(\"d1/src/lib.rs\", \"pub fn d1() {}\")\n        .file(\n            \"d2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d2\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [build-dependencies.d1]\n                path = \"../d1\"\n            \"#,\n        )\n        .file(\"d2/build.rs\", \"extern crate d1; fn main() {}\")\n        .file(\"d2/src/lib.rs\", \"\")\n        .build();\n\n    let target = cross_compile::alternate();\n    p.cargo(\"build -v --target\").arg(&target).run();\n}\n\n#[cargo_test]\nfn build_script_only_host() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [build-dependencies.d1]\n                path = \"d1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build.rs\", \"extern crate d1; fn main() {}\")\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"d1/src/lib.rs\", \"pub fn d1() {}\")\n        .file(\n            \"d1/build.rs\",\n            r#\"\n                use std::env;\n\n                fn main() {\n                    assert!(env::var(\"OUT_DIR\").unwrap().replace(\"\\\\\", \"/\")\n                                               .contains(\"target/debug/build/d1-\"),\n                            \"bad: {:?}\", env::var(\"OUT_DIR\"));\n                }\n            \"#,\n        )\n        .build();\n\n    let target = cross_compile::alternate();\n    p.cargo(\"build -v --target\").arg(&target).run();\n}\n\n#[cargo_test]\nfn build_script_with_platform_specific_dependencies() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n    let host = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [build-dependencies.d1]\n                path = \"d1\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            \"\n            #[allow(unused_extern_crates)]\n            extern crate d1;\n            fn main() {}\n        \",\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"d1/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"d1\"\n                    version = \"0.0.0\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [target.{}.dependencies]\n                    d2 = {{ path = \"../d2\" }}\n                \"#,\n                host\n            ),\n        )\n        .file(\n            \"d1/src/lib.rs\",\n            \"#[allow(unused_extern_crates)] extern crate d2;\",\n        )\n        .file(\"d2/Cargo.toml\", &basic_manifest(\"d2\", \"0.0.0\"))\n        .file(\"d2/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v --target\")\n        .arg(&target)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] d2 v0.0.0 ([ROOT]/foo/d2)\n[RUNNING] `rustc [..] d2/src/lib.rs [..]`\n[COMPILING] d1 v0.0.0 ([ROOT]/foo/d1)\n[RUNNING] `rustc [..] d1/src/lib.rs [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] build.rs [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..] src/lib.rs [..] --target [ALT_TARGET] [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn platform_specific_dependencies_do_not_leak() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n    let host = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n\n                [dependencies.d1]\n                path = \"d1\"\n\n                [build-dependencies.d1]\n                path = \"d1\"\n            \"#,\n        )\n        .file(\"build.rs\", \"extern crate d1; fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"d1/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"d1\"\n                    version = \"0.0.0\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [target.{}.dependencies]\n                    d2 = {{ path = \"../d2\" }}\n                \"#,\n                host\n            ),\n        )\n        .file(\"d1/src/lib.rs\", \"extern crate d2;\")\n        .file(\"d1/Cargo.toml\", &basic_manifest(\"d1\", \"0.0.0\"))\n        .file(\"d2/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v --target\")\n        .arg(&target)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\nerror[E0463]: can't find crate for `d2`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn platform_specific_variables_reflected_in_build_scripts() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n    let host = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n                    build = \"build.rs\"\n\n                    [target.{host}.dependencies]\n                    d1 = {{ path = \"d1\" }}\n\n                    [target.{target}.dependencies]\n                    d2 = {{ path = \"d2\" }}\n                \"#,\n                host = host,\n                target = target\n            ),\n        )\n        .file(\n            \"build.rs\",\n            &format!(\n                r#\"\n                    use std::env;\n\n                    fn main() {{\n                        let platform = env::var(\"TARGET\").unwrap();\n                        let (expected, not_expected) = match &platform[..] {{\n                            \"{host}\" => (\"DEP_D1_VAL\", \"DEP_D2_VAL\"),\n                            \"{target}\" => (\"DEP_D2_VAL\", \"DEP_D1_VAL\"),\n                            _ => panic!(\"unknown platform\")\n                        }};\n\n                        env::var(expected).ok()\n                            .expect(&format!(\"missing {{}}\", expected));\n                        env::var(not_expected).err()\n                            .expect(&format!(\"found {{}}\", not_expected));\n                    }}\n                \"#,\n                host = host,\n                target = target\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"d1\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"d1/build.rs\",\n            r#\"fn main() { println!(\"cargo::metadata=val=1\") }\"#,\n        )\n        .file(\"d1/src/lib.rs\", \"\")\n        .file(\n            \"d2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d2\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                links = \"d2\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"d2/build.rs\",\n            r#\"fn main() { println!(\"cargo::metadata=val=1\") }\"#,\n        )\n        .file(\"d2/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\").run();\n    p.cargo(\"build -v --target\").arg(&target).run();\n}\n\n#[cargo_test]\n#[cfg_attr(\n    target_os = \"macos\",\n    ignore = \"don't have a dylib cross target on macos\"\n)]\nfn cross_test_dylib() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo\"\n                crate-type = [\"dylib\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate bar as the_bar;\n\n                pub fn bar() { the_bar::baz(); }\n\n                #[test]\n                fn foo() { bar(); }\n            \"#,\n        )\n        .file(\n            \"tests/test.rs\",\n            r#\"\n                extern crate foo as the_foo;\n\n                #[test]\n                fn foo() { the_foo::bar(); }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"bar\"\n                crate-type = [\"dylib\"]\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            &format!(\n                r#\"\n                     use std::env;\n                     pub fn baz() {{\n                        assert_eq!(env::consts::ARCH, \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .build();\n\n    p.cargo(\"test --target\")\n        .arg(&target)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE])\n[RUNNING] tests/test.rs (target/[ALT_TARGET]/debug/deps/test-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest foo ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest foo ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doctest_xcompile_linker() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}]\n                    linker = \"my-linker-tool\"\n                \"#,\n                target\n            ),\n        )\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// assert_eq!(1, 1);\n                /// ```\n                pub fn foo() {}\n            \"#,\n        )\n        .build();\n\n    // Fails because `my-linker-tool` doesn't actually exist.\n    p.cargo(\"test --doc -v --target\")\n        .arg(&target)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] --out-dir [ROOT]/foo/target/[ALT_TARGET]/debug/deps --target [ALT_TARGET] [..]\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[DOCTEST] foo\n[RUNNING] `rustdoc [..] src/lib.rs [..]\n[ERROR] doctest failed, to rerun pass `--doc`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn always_emit_warnings_as_warnings_when_learning_target_info() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = \"wasm32-unknown-unknown\";\n    if !cross_compile::requires_target_installed(target) {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v --target\")\n        .env(\"RUSTFLAGS\", \"-Awarnings\")\n        .arg(target)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]-Awarnings[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn host_linker_does_not_apply_to_binary_build() {\n    // `host.linker` should only apply to build scripts, not to normal binary builds.\n    let target = rustc_host();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [host]\n                linker = \"nonexistent-host-linker\"\n                [target.{target}]\n                linker = \"nonexistent-target-linker\"\n                \"#,\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -Z target-applies-to-host -Z host-config --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .with_status(101)\n        // Need to omit some MSVC-specific diagnostics\n        // because rustc prints extra stuff when linker was not found.\n        // https://github.com/rust-lang/rust/blob/7ad4e69ad585d8ff214f7b42d01f1959eda08f40/compiler/rustc_codegen_ssa/src/back/link.rs?plain=1#L971-L975\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] linker `nonexistent-target-linker` not found\n  |\n  = [NOTE] [NOT_FOUND]\n...\n\"#]])\n        .run();\n\n    // with target-applies-to-host=false,\n    // host.linker should not be applied but target.linker\n    p.cargo(\"build -Z target-applies-to-host -Z host-config\")\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .env(\"CARGO_TARGET_APPLIES_TO_HOST\", \"false\")\n        .with_status(101)\n        // Need to omit some MSVC-specific diagnostics\n        // because rustc prints extra stuff when linker was not found.\n        // https://github.com/rust-lang/rust/blob/7ad4e69ad585d8ff214f7b42d01f1959eda08f40/compiler/rustc_codegen_ssa/src/back/link.rs?plain=1#L971-L975\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] linker `nonexistent-target-linker` not found\n  |\n  = [NOTE] [NOT_FOUND]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cross_with_host_config() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"build -Z target-applies-to-host -Z host-config --target\")\n        .arg(&target)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .with_status(0)\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/cross_publish.rs",
    "content": "//! Tests for publishing using the `--target` flag.\n\nuse std::fs::File;\n\nuse crate::prelude::*;\nuse crate::utils::cross_compile::disabled as cross_compile_disabled;\nuse cargo_test_support::{cross_compile, project, publish, registry, str};\n\n#[cargo_test]\nfn simple_cross_package() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                repository = \"bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            &format!(\n                r#\"\n                    use std::env;\n                    fn main() {{\n                        assert_eq!(env::consts::ARCH, \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .build();\n\n    let target = cross_compile::alternate();\n\n    p.cargo(\"package --target\")\n        .arg(&target)\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.0 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.0 ([ROOT]/foo)\n[COMPILING] foo v0.0.0 ([ROOT]/foo/target/package/foo-0.0.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Check that the tarball contains the files\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.0.crate\")).unwrap();\n    publish::validate_crate_contents(\n        f,\n        \"foo-0.0.0.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        (),\n    );\n}\n\n#[cargo_test]\nfn publish_with_target() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    // `publish` generally requires a remote registry\n    let registry = registry::RegistryBuilder::new().http_api().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                repository = \"bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            &format!(\n                r#\"\n                    use std::env;\n                    fn main() {{\n                        assert_eq!(env::consts::ARCH, \"{}\");\n                    }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .build();\n\n    let target = cross_compile::alternate();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .arg(\"--target\")\n        .arg(&target)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] foo v0.0.0 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.0 ([ROOT]/foo)\n[COMPILING] foo v0.0.0 ([ROOT]/foo/target/package/foo-0.0.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.0 ([ROOT]/foo)\n[UPLOADED] foo v0.0.0 to registry `crates-io`\n[NOTE] waiting for foo v0.0.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.0 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/custom_target.rs",
    "content": "//! Tests for custom json target specifications.\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\nuse cargo_test_support::target_spec_json;\n\nconst MINIMAL_LIB: &str = r#\"\n#![allow(internal_features)]\n#![feature(no_core)]\n#![feature(lang_items)]\n#![no_core]\n\n#[lang = \"pointee_sized\"]\npub trait PointeeSized {\n    // Empty.\n}\n\n#[lang = \"meta_sized\"]\npub trait MetaSized: PointeeSized {\n    // Empty.\n}\n\n#[lang = \"sized\"]\npub trait Sized: MetaSized {\n    // Empty.\n}\n#[lang = \"copy\"]\npub trait Copy {\n    // Empty.\n}\n\"#;\n\n#[cargo_test]\nfn custom_target_gated() {\n    // Checks that .json targets require the -Z option.\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"build --target custom-target.json\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `.json` target specs require -Zjson-target-spec\n\n\"#]])\n        .run();\n\n    // Same with config settings.\n    p.cargo(\"build\")\n        .env(\"CARGO_BUILD_TARGET\", \"custom-target.json\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `.json` target specs require -Zjson-target-spec\n\n\"#]])\n        .run();\n\n    // And artifact dependencies.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = { path = \"bar/\", artifact = \"bin\", target = \"custom-target.json\" }\n        \"#,\n    );\n    p.cargo(\"build -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `.json` target specs require -Zjson-target-spec\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires features no_core, lang_items\")]\nfn custom_target_minimal() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            &\"\n                __MINIMAL_LIB__\n\n                pub fn foo() -> u32 {\n                    42\n                }\n            \"\n            .replace(\"__MINIMAL_LIB__\", MINIMAL_LIB),\n        )\n        .file(\"custom-target.json\", target_spec_json())\n        .build();\n\n    p.cargo(\"build --lib --target custom-target.json -v -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .run();\n    p.cargo(\"build --lib --target src/../custom-target.json -v -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .run();\n\n    // Ensure that the correct style of flag is passed to --target with doc tests.\n    p.cargo(\"test --doc --target src/../custom-target.json -v -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"no_core\", \"lang_items\", \"json-target-spec\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[DOCTEST] foo\n[RUNNING] `rustdoc [..]--target [..]foo/custom-target.json[..]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires features no_core, lang_items, auto_traits\")]\nfn custom_target_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = [\"author@example.com\"]\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![allow(internal_features)]\n                #![feature(no_core)]\n                #![feature(lang_items)]\n                #![feature(auto_traits)]\n                #![no_core]\n\n                extern crate bar;\n\n                pub fn foo() -> u32 {\n                    bar::bar()\n                }\n\n                #[lang = \"freeze\"]\n                unsafe auto trait Freeze {}\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\n            \"bar/src/lib.rs\",\n            &\"\n                __MINIMAL_LIB__\n\n                pub fn bar() -> u32 {\n                    42\n                }\n            \"\n            .replace(\"__MINIMAL_LIB__\", MINIMAL_LIB),\n        )\n        .file(\"custom-target.json\", target_spec_json())\n        .build();\n\n    p.cargo(\"build --lib --target custom-target.json -v -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires features no_core, lang_items\")]\n// This is randomly crashing in lld. See https://github.com/rust-lang/rust/issues/115985\n#[cfg_attr(all(windows, target_env = \"gnu\"), ignore = \"windows-gnu lld crashing\")]\nfn custom_bin_target() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            &\"\n                #![no_main]\n                __MINIMAL_LIB__\n            \"\n            .replace(\"__MINIMAL_LIB__\", MINIMAL_LIB),\n        )\n        .file(\"custom-bin-target.json\", target_spec_json())\n        .build();\n\n    p.cargo(\"build --target custom-bin-target.json -v -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires features no_core, lang_items\")]\nfn changing_spec_rebuilds() {\n    // Changing the .json file will trigger a rebuild.\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            &\"\n                __MINIMAL_LIB__\n\n                pub fn foo() -> u32 {\n                    42\n                }\n            \"\n            .replace(\"__MINIMAL_LIB__\", MINIMAL_LIB),\n        )\n        .file(\"custom-target.json\", target_spec_json())\n        .build();\n\n    p.cargo(\"build --lib --target custom-target.json -v -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .run();\n    p.cargo(\"build --lib --target custom-target.json -v -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    let spec_path = p.root().join(\"custom-target.json\");\n    let spec = fs::read_to_string(&spec_path).unwrap();\n    // Some arbitrary change that I hope is safe.\n    let spec = spec.replace('{', \"{\\n\\\"vendor\\\": \\\"unknown\\\",\\n\");\n    fs::write(&spec_path, spec).unwrap();\n    p.cargo(\"build --lib --target custom-target.json -v -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires features no_core, lang_items\")]\n// This is randomly crashing in lld. See https://github.com/rust-lang/rust/issues/115985\n#[cfg_attr(all(windows, target_env = \"gnu\"), ignore = \"windows-gnu lld crashing\")]\nfn changing_spec_relearns_crate_types() {\n    // Changing the .json file will invalidate the cache of crate types.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"cdylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", MINIMAL_LIB)\n        .file(\"custom-target.json\", target_spec_json())\n        .build();\n\n    p.cargo(\"build --lib --target custom-target.json -v -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot produce cdylib for `foo v0.1.0 ([ROOT]/foo)` [..]\n\n\"#]])\n        .run();\n\n    // Enable dynamic linking.\n    let spec_path = p.root().join(\"custom-target.json\");\n    let spec = fs::read_to_string(&spec_path).unwrap();\n    let spec = spec.replace('{', \"{\\n\\\"dynamic-linking\\\": true,\\n\");\n    fs::write(&spec_path, spec).unwrap();\n\n    p.cargo(\"build --lib --target custom-target.json -v -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires features no_core, lang_items\")]\nfn custom_target_ignores_filepath() {\n    // Changing the path of the .json file will not trigger a rebuild.\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            &\"\n                __MINIMAL_LIB__\n\n                pub fn foo() -> u32 {\n                    42\n                }\n            \"\n            .replace(\"__MINIMAL_LIB__\", MINIMAL_LIB),\n        )\n        .file(\"b/custom-target.json\", target_spec_json())\n        .file(\"a/custom-target.json\", target_spec_json())\n        .build();\n\n    // Should build the library the first time.\n    p.cargo(\"build --lib --target a/custom-target.json -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // But not the second time, even though the path to the custom target is different.\n    p.cargo(\"build --lib --target b/custom-target.json -Zjson-target-spec\")\n        .masquerade_as_nightly_cargo(&[\"json_target_spec\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/death.rs",
    "content": "//! Tests for ctrl-C handling.\n\nuse std::fs;\nuse std::io::{self, Read};\nuse std::net::TcpListener;\nuse std::process::{Child, Stdio};\nuse std::thread;\n\nuse crate::prelude::*;\nuse cargo_test_support::{project, slow_cpu_multiplier};\n\n#[cargo_test]\nfn ctrl_c_kills_everyone() {\n    let listener = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let addr = listener.local_addr().unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            &format!(\n                r#\"\n                    use std::net::TcpStream;\n                    use std::io::Read;\n\n                    fn main() {{\n                        let mut socket = TcpStream::connect(\"{}\").unwrap();\n                        let _ = socket.read(&mut [0; 10]);\n                        panic!(\"that read should never return\");\n                    }}\n                \"#,\n                addr\n            ),\n        )\n        .build();\n\n    let mut cargo = p.cargo(\"check\").build_command();\n    cargo\n        .stdin(Stdio::piped())\n        .stdout(Stdio::piped())\n        .stderr(Stdio::piped())\n        .env(\"__CARGO_TEST_SETSID_PLEASE_DONT_USE_ELSEWHERE\", \"1\");\n    let mut child = cargo.spawn().unwrap();\n\n    let mut sock = listener.accept().unwrap().0;\n    ctrl_c(&mut child);\n\n    assert!(!child.wait().unwrap().success());\n    match sock.read(&mut [0; 10]) {\n        Ok(n) => assert_eq!(n, 0),\n        Err(e) => assert_eq!(e.kind(), io::ErrorKind::ConnectionReset),\n    }\n\n    // Ok so what we just did was spawn cargo that spawned a build script, then\n    // we killed cargo in hopes of it killing the build script as well. If all\n    // went well the build script is now dead. On Windows, however, this is\n    // enforced with job objects which means that it may actually be in the\n    // *process* of being torn down at this point.\n    //\n    // Now on Windows we can't completely remove a file until all handles to it\n    // have been closed. Including those that represent running processes. So if\n    // we were to return here then there may still be an open reference to some\n    // file in the build directory. What we want to actually do is wait for the\n    // build script to *complete* exit. Take care of that by blowing away the\n    // build directory here, and panicking if we eventually spin too long\n    // without being able to.\n    for i in 0..10 {\n        match fs::remove_dir_all(&p.root().join(\"target\")) {\n            Ok(()) => return,\n            Err(e) => println!(\"attempt {}: {}\", i, e),\n        }\n        thread::sleep(slow_cpu_multiplier(100));\n    }\n\n    panic!(\n        \"couldn't remove build directory after a few tries, seems like \\\n         we won't be able to!\"\n    );\n}\n\n#[cfg(unix)]\npub fn ctrl_c(child: &mut Child) {\n    let r = unsafe { libc::kill(-(child.id() as i32), libc::SIGINT) };\n    if r < 0 {\n        panic!(\"failed to kill: {}\", io::Error::last_os_error());\n    }\n}\n\n#[cfg(windows)]\npub fn ctrl_c(child: &mut Child) {\n    child.kill().unwrap();\n}\n"
  },
  {
    "path": "tests/testsuite/dep_info.rs",
    "content": "//! Tests for dep-info files. This includes the dep-info file Cargo creates in\n//! the output directory, and the ones stored in the fingerprint.\n\nuse std::path::Path;\n\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{assert_deps, assert_deps_contains};\nuse cargo_test_support::{basic_bin_manifest, basic_manifest, main_file, project, rustc_host};\nuse filetime::FileTime;\n\n#[cargo_test]\nfn build_dep_info() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"build\").run();\n\n    let depinfo_bin_path = &p.bin(\"foo\").with_extension(\"d\");\n\n    assert!(depinfo_bin_path.is_file());\n\n    let depinfo = p.read_file(depinfo_bin_path);\n\n    let bin_path = p.bin(\"foo\");\n    let src_path = p.root().join(\"src\").join(\"foo.rs\");\n    if !depinfo.lines().any(|line| {\n        line.starts_with(&format!(\"{}:\", bin_path.display()))\n            && line.contains(src_path.to_str().unwrap())\n    }) {\n        panic!(\n            \"Could not find {:?}: {:?} in {:?}\",\n            bin_path, src_path, depinfo_bin_path\n        );\n    }\n}\n\n#[cargo_test]\nfn build_dep_info_lib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [[example]]\n                name = \"ex\"\n                crate-type = [\"lib\"]\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --example=ex\").run();\n    assert!(p.example_lib(\"ex\", \"lib\").with_extension(\"d\").is_file());\n}\n\n#[cargo_test]\nfn build_dep_info_rlib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [[example]]\n                name = \"ex\"\n                crate-type = [\"rlib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --example=ex\").run();\n    assert!(p.example_lib(\"ex\", \"rlib\").with_extension(\"d\").is_file());\n}\n\n#[cargo_test]\nfn build_dep_info_dylib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [[example]]\n                name = \"ex\"\n                crate-type = [\"dylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --example=ex\").run();\n    assert!(p.example_lib(\"ex\", \"dylib\").with_extension(\"d\").is_file());\n}\n\n#[cargo_test]\nfn dep_path_inside_target_has_correct_path() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"a\"))\n        .file(\"target/debug/blah\", \"\")\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    let x = include_bytes!(concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/target/debug/blah\"));\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n\n    let depinfo_path = &p.bin(\"a\").with_extension(\"d\");\n\n    assert!(depinfo_path.is_file(), \"{:?}\", depinfo_path);\n\n    let depinfo = p.read_file(depinfo_path);\n\n    let bin_path = p.bin(\"a\");\n    let target_debug_blah = Path::new(\"target\").join(\"debug\").join(\"blah\");\n    if !depinfo.lines().any(|line| {\n        line.starts_with(&format!(\"{}:\", bin_path.display()))\n            && line.contains(target_debug_blah.to_str().unwrap())\n    }) {\n        panic!(\n            \"Could not find {:?}: {:?} in {:?}\",\n            bin_path, target_debug_blah, depinfo_path\n        );\n    }\n}\n\n#[cargo_test]\nfn no_rewrite_if_no_change() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"build\").run();\n    let dep_info = p.root().join(\"target/debug/libfoo.d\");\n    let metadata1 = dep_info.metadata().unwrap();\n    p.cargo(\"build\").run();\n    let metadata2 = dep_info.metadata().unwrap();\n\n    assert_eq!(\n        FileTime::from_last_modification_time(&metadata1),\n        FileTime::from_last_modification_time(&metadata2),\n    );\n}\n\n#[cargo_test(nightly, reason = \"-Z binary-dep-depinfo is unstable\")]\nfn relative_depinfo_paths_ws() {\n    // Test relative dep-info paths in a workspace with --target with\n    // proc-macros and other dependency kinds.\n    Package::new(\"regdep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn f() {}\")\n        .publish();\n    Package::new(\"pmdep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn f() {}\")\n        .publish();\n    Package::new(\"bdep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn f() {}\")\n        .publish();\n\n    let p = project()\n        /*********** Workspace ***********/\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"foo\"]\n            \"#,\n        )\n        /*********** Main Project ***********/\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [dependencies]\n            pm = {path = \"../pm\"}\n            bar = {path = \"../bar\"}\n            regdep = \"0.1\"\n\n            [build-dependencies]\n            bdep = \"0.1\"\n            bar = {path = \"../bar\"}\n            \"#,\n        )\n        .file(\n            \"foo/src/main.rs\",\n            r#\"\n            pm::noop!{}\n\n            fn main() {\n                bar::f();\n                regdep::f();\n            }\n            \"#,\n        )\n        .file(\"foo/build.rs\", \"fn main() { bdep::f(); }\")\n        /*********** Proc Macro ***********/\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"pm\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [lib]\n            proc-macro = true\n\n            [dependencies]\n            pmdep = \"0.1\"\n            \"#,\n        )\n        .file(\n            \"pm/src/lib.rs\",\n            r#\"\n            extern crate proc_macro;\n            use proc_macro::TokenStream;\n\n            #[proc_macro]\n            pub fn noop(_item: TokenStream) -> TokenStream {\n                pmdep::f();\n                \"\".parse().unwrap()\n            }\n            \"#,\n        )\n        /*********** Path Dependency `bar` ***********/\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn f() {}\")\n        .build();\n\n    let host = rustc_host();\n    p.cargo(\"build -Z binary-dep-depinfo --target\")\n        .arg(&host)\n        .masquerade_as_nightly_cargo(&[\"binary-dep-depinfo\"])\n        .with_stderr_data(str![[r#\"\n...\n[COMPILING] foo v0.1.0 ([ROOT]/foo/foo)\n...\n\"#]])\n        .run();\n\n    assert_deps_contains(\n        &p,\n        \"target/debug/.fingerprint/pm-*/dep-lib-pm\",\n        &[(0, \"src/lib.rs\"), (1, \"debug/deps/libpmdep-*.rlib\")],\n    );\n\n    assert_deps_contains(\n        &p,\n        &format!(\"target/{}/debug/.fingerprint/foo-*/dep-bin-foo\", host),\n        &[\n            (0, \"src/main.rs\"),\n            (\n                1,\n                &format!(\n                    \"debug/deps/{}pm-*.{}\",\n                    paths::get_lib_prefix(\"proc-macro\"),\n                    paths::get_lib_extension(\"proc-macro\")\n                ),\n            ),\n            (1, &format!(\"{}/debug/deps/libbar-*.rlib\", host)),\n            (1, &format!(\"{}/debug/deps/libregdep-*.rlib\", host)),\n        ],\n    );\n\n    assert_deps_contains(\n        &p,\n        \"target/debug/.fingerprint/foo-*/dep-build-script-build-script-build\",\n        &[(0, \"build.rs\"), (1, \"debug/deps/libbdep-*.rlib\")],\n    );\n\n    // Make sure it stays fresh.\n    p.cargo(\"build -Z binary-dep-depinfo --target\")\n        .arg(&host)\n        .masquerade_as_nightly_cargo(&[\"binary-dep-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Z binary-dep-depinfo is unstable\")]\nfn relative_depinfo_paths_no_ws() {\n    // Test relative dep-info paths without a workspace with proc-macros and\n    // other dependency kinds.\n    Package::new(\"regdep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn f() {}\")\n        .publish();\n    Package::new(\"pmdep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn f() {}\")\n        .publish();\n    Package::new(\"bdep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn f() {}\")\n        .publish();\n\n    let p = project()\n        /*********** Main Project ***********/\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [dependencies]\n            pm = {path = \"pm\"}\n            bar = {path = \"bar\"}\n            regdep = \"0.1\"\n\n            [build-dependencies]\n            bdep = \"0.1\"\n            bar = {path = \"bar\"}\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            pm::noop!{}\n\n            fn main() {\n                bar::f();\n                regdep::f();\n            }\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() { bdep::f(); }\")\n        /*********** Proc Macro ***********/\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"pm\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [lib]\n            proc-macro = true\n\n            [dependencies]\n            pmdep = \"0.1\"\n            \"#,\n        )\n        .file(\n            \"pm/src/lib.rs\",\n            r#\"\n            extern crate proc_macro;\n            use proc_macro::TokenStream;\n\n            #[proc_macro]\n            pub fn noop(_item: TokenStream) -> TokenStream {\n                pmdep::f();\n                \"\".parse().unwrap()\n            }\n            \"#,\n        )\n        /*********** Path Dependency `bar` ***********/\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn f() {}\")\n        .build();\n\n    p.cargo(\"build -Z binary-dep-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"binary-dep-depinfo\"])\n        .with_stderr_data(str![[r#\"\n...\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n...\n\"#]])\n        .run();\n\n    assert_deps_contains(\n        &p,\n        \"target/debug/.fingerprint/pm-*/dep-lib-pm\",\n        &[(0, \"src/lib.rs\"), (1, \"debug/deps/libpmdep-*.rlib\")],\n    );\n\n    assert_deps_contains(\n        &p,\n        \"target/debug/.fingerprint/foo-*/dep-bin-foo\",\n        &[\n            (0, \"src/main.rs\"),\n            (\n                1,\n                &format!(\n                    \"debug/deps/{}pm-*.{}\",\n                    paths::get_lib_prefix(\"proc-macro\"),\n                    paths::get_lib_extension(\"proc-macro\")\n                ),\n            ),\n            (1, \"debug/deps/libbar-*.rlib\"),\n            (1, \"debug/deps/libregdep-*.rlib\"),\n        ],\n    );\n\n    assert_deps_contains(\n        &p,\n        \"target/debug/.fingerprint/foo-*/dep-build-script-build-script-build\",\n        &[(0, \"build.rs\"), (1, \"debug/deps/libbdep-*.rlib\")],\n    );\n\n    // Make sure it stays fresh.\n    p.cargo(\"build -Z binary-dep-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"binary-dep-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn reg_dep_source_not_tracked() {\n    // Make sure source files in dep-info file are not tracked for registry dependencies.\n    Package::new(\"regdep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn f() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            regdep = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn f() { regdep::f(); }\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    assert_deps(\n        &p,\n        \"target/debug/.fingerprint/regdep-*/dep-lib-regdep\",\n        |info_path, entries| {\n            for (kind, path) in entries {\n                if *kind == 1 {\n                    panic!(\n                        \"Did not expect package root relative path type: {:?} in {:?}\",\n                        path, info_path\n                    );\n                }\n            }\n        },\n    );\n}\n\n#[cargo_test(nightly, reason = \"-Z binary-dep-depinfo is unstable\")]\nfn canonical_path() {\n    if !cargo_test_support::symlink_supported() {\n        return;\n    }\n    Package::new(\"regdep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn f() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            regdep = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn f() { regdep::f(); }\")\n        .build();\n\n    let real = p.root().join(\"real_target\");\n    real.mkdir_p();\n    p.symlink(real, \"target\");\n\n    p.cargo(\"check -Z binary-dep-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"binary-dep-depinfo\"])\n        .run();\n\n    assert_deps_contains(\n        &p,\n        \"target/debug/.fingerprint/foo-*/dep-lib-foo\",\n        &[(0, \"src/lib.rs\"), (1, \"debug/deps/libregdep-*.rmeta\")],\n    );\n}\n\n#[cargo_test]\nfn non_local_build_script() {\n    // Non-local build script information is not included.\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rerun-if-changed=build.rs\");\n                }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\").run();\n    let contents = p.read_file(\"target/debug/foo.d\");\n    assert_e2e().eq(\n        &contents,\n        str![[r#\"\n[ROOT]/foo/target/debug/foo[EXE]: [ROOT]/foo/src/main.rs\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn no_trailing_separator_after_package_root_build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            authors = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                println!(\"cargo::rerun-if-changed=\");\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    let contents = p.read_file(\"target/debug/foo.d\");\n\n    assert_e2e().eq(\n        &contents,\n        str![[r#\"\n[ROOT]/foo/target/debug/foo[EXE]: [ROOT]/foo [ROOT]/foo/build.rs [ROOT]/foo/src/main.rs\n\n\"#]],\n    );\n}\n\n#[cargo_test(nightly, reason = \"proc_macro::tracked::path is unstable\")]\nfn no_trailing_separator_after_package_root_proc_macro() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            authors = []\n            edition = \"2018\"\n\n            [dependencies]\n            pm = { path = \"pm\" }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n            pm::noop!{}\n            fn main() {}\n            \",\n        )\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"pm\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [lib]\n            proc-macro = true\n            \"#,\n        )\n        .file(\n            \"pm/src/lib.rs\",\n            r#\"\n            #![feature(proc_macro_tracked_path)]\n            extern crate proc_macro;\n            use proc_macro::TokenStream;\n\n            #[proc_macro]\n            pub fn noop(_item: TokenStream) -> TokenStream {\n                proc_macro::tracked::path(\n                    std::env::current_dir().unwrap().to_str().unwrap()\n                );\n                \"\".parse().unwrap()\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    let contents = p.read_file(\"target/debug/foo.d\");\n\n    assert_e2e().eq(\n        &contents,\n        str![[r#\"\n[ROOT]/foo/target/debug/foo[EXE]: [ROOT]/foo [ROOT]/foo/pm/src/lib.rs [ROOT]/foo/src/main.rs\n\n\"#]],\n    );\n}\n"
  },
  {
    "path": "tests/testsuite/diagnostics.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn dont_panic_on_render() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n[[bench.foo]]\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid type: map, expected a sequence\n --> Cargo.toml:6:3\n  |\n6 | [[bench.foo]]\n  |   ^^^^^\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/direct_minimal_versions.rs",
    "content": "//! Tests for minimal-version resolution.\n//!\n//! Note: Some tests are located in the resolver-tests package.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn simple() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n    Package::new(\"dep\", \"1.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n\n                [dependencies]\n                dep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile -Zdirect-minimal-versions\")\n        .masquerade_as_nightly_cargo(&[\"direct-minimal-versions\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package\n[ADDING] dep v1.0.0 (available: v1.1.0)\n\n\"#]])\n        .run();\n\n    let lock = p.read_lockfile();\n\n    assert!(\n        lock.contains(\"1.0.0\"),\n        \"dep minimal version must be present\"\n    );\n    assert!(\n        !lock.contains(\"1.1.0\"),\n        \"dep maximal version cannot be present\"\n    );\n}\n\n#[cargo_test]\nfn mixed_dependencies() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n    Package::new(\"dep\", \"1.1.0\").publish();\n    Package::new(\"dep\", \"1.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n\n                [dependencies]\n                dep = \"1.0\"\n\n                [dev-dependencies]\n                dep = \"1.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile -Zdirect-minimal-versions\")\n        .masquerade_as_nightly_cargo(&[\"direct-minimal-versions\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for `dep`.\n    ... required by package `foo v0.0.1 ([ROOT]/foo)`\nversions that meet the requirements `^1.1` are: 1.1.0\n\nall possible versions conflict with previously selected packages.\n\n  previously selected package `dep v1.0.0`\n    ... which satisfies dependency `dep = \"^1.0\"` of package `foo v0.0.1 ([ROOT]/foo)`\n\nfailed to select a version for `dep` which could resolve this conflict\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn yanked() {\n    Package::new(\"dep\", \"1.0.0\").yanked(true).publish();\n    Package::new(\"dep\", \"1.1.0\").publish();\n    Package::new(\"dep\", \"1.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n\n                [dependencies]\n                dep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile -Zdirect-minimal-versions\")\n        .masquerade_as_nightly_cargo(&[\"direct-minimal-versions\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package\n[ADDING] dep v1.1.0 (available: v1.2.0)\n\n\"#]])\n        .run();\n\n    let lock = p.read_lockfile();\n\n    assert!(\n        lock.contains(\"1.1.0\"),\n        \"dep minimal version must be present\"\n    );\n    assert!(\n        !lock.contains(\"1.0.0\"),\n        \"yanked minimal version must be skipped\"\n    );\n    assert!(\n        !lock.contains(\"1.2.0\"),\n        \"dep maximal version cannot be present\"\n    );\n}\n\n#[cargo_test]\nfn indirect() {\n    Package::new(\"indirect\", \"2.0.0\").publish();\n    Package::new(\"indirect\", \"2.1.0\").publish();\n    Package::new(\"indirect\", \"2.2.0\").publish();\n    Package::new(\"direct\", \"1.0.0\")\n        .dep(\"indirect\", \"2.1\")\n        .publish();\n    Package::new(\"direct\", \"1.1.0\")\n        .dep(\"indirect\", \"2.1\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n\n                [dependencies]\n                direct = \"1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile -Zdirect-minimal-versions\")\n        .masquerade_as_nightly_cargo(&[\"direct-minimal-versions\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages\n[ADDING] direct v1.0.0 (available: v1.1.0)\n\n\"#]])\n        .run();\n\n    let lock = p.read_lockfile();\n\n    assert!(\n        lock.contains(\"1.0.0\"),\n        \"direct minimal version must be present\"\n    );\n    assert!(\n        !lock.contains(\"1.1.0\"),\n        \"direct maximal version cannot be present\"\n    );\n    assert!(\n        !lock.contains(\"2.0.0\"),\n        \"indirect minimal version cannot be present\"\n    );\n    assert!(\n        !lock.contains(\"2.1.0\"),\n        \"indirect minimal version cannot be present\"\n    );\n    assert!(\n        lock.contains(\"2.2.0\"),\n        \"indirect maximal version must be present\"\n    );\n}\n\n#[cargo_test]\nfn indirect_conflict() {\n    Package::new(\"indirect\", \"2.0.0\").publish();\n    Package::new(\"indirect\", \"2.1.0\").publish();\n    Package::new(\"indirect\", \"2.2.0\").publish();\n    Package::new(\"direct\", \"1.0.0\")\n        .dep(\"indirect\", \"2.1\")\n        .publish();\n    Package::new(\"direct\", \"1.1.0\")\n        .dep(\"indirect\", \"2.1\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n\n                [dependencies]\n                direct = \"1.0\"\n                indirect = \"2.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile -Zdirect-minimal-versions\")\n        .masquerade_as_nightly_cargo(&[\"direct-minimal-versions\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for `indirect`.\n    ... required by package `direct v1.0.0`\n    ... which satisfies dependency `direct = \"^1.0\"` of package `foo v0.0.1 ([ROOT]/foo)`\nversions that meet the requirements `^2.1` are: 2.2.0, 2.1.0\n\nall possible versions conflict with previously selected packages.\n\n  previously selected package `indirect v2.0.0`\n    ... which satisfies dependency `indirect = \"^2.0\"` of package `foo v0.0.1 ([ROOT]/foo)`\n\nfailed to select a version for `indirect` which could resolve this conflict\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/directory.rs",
    "content": "//! Tests for directory sources.\n\nuse std::collections::HashMap;\nuse std::fs;\nuse std::str;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::git;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::{Package, cksum};\nuse cargo_test_support::str;\nuse cargo_test_support::{ProjectBuilder, basic_manifest, project, t};\nuse serde::Serialize;\n\nfn setup() {\n    let root = paths::root();\n    t!(fs::create_dir(&root.join(\".cargo\")));\n    t!(fs::write(\n        root.join(\".cargo/config.toml\"),\n        r#\"\n            [source.crates-io]\n            replace-with = 'my-awesome-local-registry'\n\n            [source.my-awesome-local-registry]\n            directory = 'index'\n        \"#\n    ));\n}\n\nstruct VendorPackage {\n    p: Option<ProjectBuilder>,\n    cksum: Checksum,\n}\n\n#[derive(Serialize)]\nstruct Checksum {\n    package: Option<String>,\n    files: HashMap<String, String>,\n}\n\nimpl VendorPackage {\n    fn new(name: &str) -> VendorPackage {\n        VendorPackage {\n            p: Some(project().at(&format!(\"index/{}\", name))),\n            cksum: Checksum {\n                package: Some(String::new()),\n                files: HashMap::new(),\n            },\n        }\n    }\n\n    fn file(&mut self, name: &str, contents: &str) -> &mut VendorPackage {\n        self.p = Some(self.p.take().unwrap().file(name, contents));\n        self.cksum\n            .files\n            .insert(name.to_string(), cksum(contents.as_bytes()));\n        self\n    }\n\n    fn disable_checksum(&mut self) -> &mut VendorPackage {\n        self.cksum.package = None;\n        self\n    }\n\n    fn no_manifest(mut self) -> Self {\n        self.p = self.p.map(|pb| pb.no_manifest());\n        self\n    }\n\n    fn build(&mut self) {\n        let p = self.p.take().unwrap();\n        let json = serde_json::to_string(&self.cksum).unwrap();\n        let p = p.file(\".cargo-checksum.json\", &json);\n        let _ = p.build();\n    }\n}\n\n#[cargo_test]\nfn simple() {\n    setup();\n\n    VendorPackage::new(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_install() {\n    setup();\n\n    VendorPackage::new(\"foo\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    VendorPackage::new(\"bar\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"0.0.1\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"extern crate foo; pub fn main() { foo::foo(); }\",\n        )\n        .build();\n\n    cargo_process(\"install bar\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] bar v0.1.0\n[LOCKING] 1 package to latest compatible version\n[COMPILING] foo v0.0.1\n[COMPILING] bar v0.1.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [..]bar[..]\n[INSTALLED] package `bar v0.1.0` (executable `bar[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_install_fail() {\n    setup();\n\n    VendorPackage::new(\"foo\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    VendorPackage::new(\"bar\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"0.1.0\"\n                baz = \"9.8.7\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"extern crate foo; pub fn main() { foo::foo(); }\",\n        )\n        .build();\n\n    cargo_process(\"install bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[INSTALLING] bar v0.1.0\n[ERROR] failed to compile `bar v0.1.0`, intermediate artifacts can be found at `[..]`.\nTo reuse those artifacts with a future compilation, set the environment variable `CARGO_BUILD_BUILD_DIR` to that path.\n\nCaused by:\n  no matching package found\n  searched package name: `baz`\n  perhaps you meant:      bar or foo\n  location searched: directory source `[ROOT]/index` (which is replacing registry `crates-io`)\n  required by package `bar v0.1.0`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn install_without_feature_dep() {\n    setup();\n\n    VendorPackage::new(\"foo\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    VendorPackage::new(\"bar\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"0.0.1\"\n                baz = { version = \"9.8.7\", optional = true }\n\n                [features]\n                wantbaz = [\"baz\"]\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"extern crate foo; pub fn main() { foo::foo(); }\",\n        )\n        .build();\n\n    cargo_process(\"install bar\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] bar v0.1.0\n[LOCKING] 1 package to latest compatible version\n[COMPILING] foo v0.0.1\n[COMPILING] bar v0.1.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [..]bar[..]\n[INSTALLED] package `bar v0.1.0` (executable `bar[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn not_there() {\n    setup();\n\n    let _ = project().at(\"index\").build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no matching package named `bar` found\nlocation searched: directory source `[ROOT]/index` (which is replacing registry `crates-io`)\nrequired by package `foo v0.1.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple() {\n    setup();\n\n    VendorPackage::new(\"bar-0.1.0\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .file(\".cargo-checksum\", \"\")\n        .build();\n\n    VendorPackage::new(\"bar-0.2.0\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.2.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .file(\".cargo-checksum\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ADDING] bar v0.1.0 (available: v0.2.0)\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn crates_io_then_directory() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    let cksum = Package::new(\"bar\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn bar() -> u32 { 0 }\")\n        .publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    setup();\n\n    let mut v = VendorPackage::new(\"bar\");\n    v.file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"));\n    v.file(\"src/lib.rs\", \"pub fn bar() -> u32 { 1 }\");\n    v.cksum.package = Some(cksum);\n    v.build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn crates_io_then_bad_checksum() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    p.cargo(\"check\").run();\n    setup();\n\n    VendorPackage::new(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] checksum for `bar v0.1.0` changed between lock files\n\nthis could be indicative of a few possible errors:\n\n    * the lock file is corrupt\n    * a replacement source in use (e.g., a mirror) returned a different checksum\n    * the source itself may be corrupt in one way or another\n\nunable to verify that `bar v0.1.0` is the same as when the lockfile was generated\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_file_checksum() {\n    setup();\n\n    VendorPackage::new(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    t!(fs::write(\n        paths::root().join(\"index/bar/src/lib.rs\"),\n        \"fn bar() -> u32 { 0 }\"\n    ));\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ERROR] the listed checksum of `[ROOT]/index/bar/src/lib.rs` has changed:\nexpected: [..]\nactual:   [..]\n\ndirectory sources are not intended to be edited, if modifications are required then it is recommended that `[patch]` is used with a forked copy of the source\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn only_dot_files_ok() {\n    setup();\n\n    VendorPackage::new(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    VendorPackage::new(\"foo\")\n        .no_manifest()\n        .file(\".bar\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn random_files_ok() {\n    setup();\n\n    VendorPackage::new(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    VendorPackage::new(\"foo\")\n        .no_manifest()\n        .file(\"bar\", \"\")\n        .file(\"../test\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn git_lock_file_doesnt_change() {\n    let git = git::new(\"git\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"git\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    VendorPackage::new(\"git\")\n        .file(\"Cargo.toml\", &basic_manifest(\"git\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .disable_checksum()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    git = {{ git = '{0}' }}\n                \"#,\n                git.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    let lock1 = p.read_lockfile();\n\n    let root = paths::root();\n    t!(fs::create_dir(&root.join(\".cargo\")));\n    t!(fs::write(\n        root.join(\".cargo/config.toml\"),\n        format!(\n            r#\"\n                [source.my-git-repo]\n                git = '{}'\n                replace-with = 'my-awesome-local-registry'\n\n                [source.my-awesome-local-registry]\n                directory = 'index'\n            \"#,\n            git.url()\n        )\n    ));\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] git v0.5.0 ([..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let lock2 = p.read_lockfile();\n    assert_eq!(lock1, lock2, \"lock files changed\");\n}\n\n#[cargo_test]\nfn git_override_requires_lockfile() {\n    VendorPackage::new(\"git\")\n        .file(\"Cargo.toml\", &basic_manifest(\"git\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .disable_checksum()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                git = { git = 'https://example.com/' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let root = paths::root();\n    t!(fs::create_dir(&root.join(\".cargo\")));\n    t!(fs::write(\n        root.join(\".cargo/config.toml\"),\n        r#\"\n            [source.my-git-repo]\n            git = 'https://example.com/'\n            replace-with = 'my-awesome-local-registry'\n\n            [source.my-awesome-local-registry]\n            directory = 'index'\n        \"#\n    ));\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to get `git` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `git`\n\nCaused by:\n  unable to update https://example.com/\n\nCaused by:\n  the source my-git-repo requires a lock file to be present first before it can be\n  used against vendored source code\n\n  remove the source replacement configuration, generate a lock file, and then\n  restore the source replacement configuration to continue the build\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_different_locations() {\n    let p = project()\n        .no_manifest()\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                edition = \"2015\"\n\n                [dependencies]\n                baz = \"*\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\"foo/vendor/baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"foo/vendor/baz/src/lib.rs\", \"\")\n        .file(\"foo/vendor/baz/.cargo-checksum.json\", \"{\\\"files\\\":{}}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = 'bar'\n                version = '0.1.0'\n                edition = \"2015\"\n\n                [dependencies]\n                baz = \"*\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                target-dir = './target'\n\n                [source.crates-io]\n                replace-with = 'my-awesome-local-registry'\n\n                [source.my-awesome-local-registry]\n                directory = 'foo/vendor'\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\").cwd(\"foo\").run();\n    p.cargo(\"check\")\n        .cwd(\"bar\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn version_missing() {\n    setup();\n\n    VendorPackage::new(\"foo\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    VendorPackage::new(\"bar\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"2\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install bar\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] bar v0.1.0\n[ERROR] failed to compile [..], intermediate artifacts can be found at `[..]`.\nTo reuse those artifacts with a future compilation, set the environment variable `CARGO_BUILD_BUILD_DIR` to that path.\n\nCaused by:\n  failed to select a version for the requirement `foo = \"^2\"`\n  candidate versions found which didn't match: 0.0.1\n  location searched: directory source `[..] (which is replacing registry `[..]`)\n  required by package `bar v0.1.0`\n  perhaps a crate was updated and forgotten to be re-vendored?\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn root_dir_diagnostics() {\n    let p = ProjectBuilder::new(paths::root())\n        .no_manifest() // we are placing it in a different dir\n        .file(\n            \"ws_root/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"ws_root/src/lib.rs\", \"invalid;\")\n        .build();\n\n    // Crucially, the rustc error message below says `ws_root/...`, i.e.\n    // it is relative to our fake home, not to the workspace root.\n    p.cargo(\"check\")\n        .arg(\"-Zroot-dir=.\")\n        .arg(\"--manifest-path=ws_root/Cargo.toml\")\n        .masquerade_as_nightly_cargo(&[\"-Zroot-dir\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/ws_root)\n[ERROR] [..]\n --> ws_root/src/lib.rs:1:8\n  |\n1 | invalid;\n  | [..]\n\n[ERROR] could not compile `foo` (lib) due to 1 previous error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn root_dir_file_macro() {\n    let p = ProjectBuilder::new(paths::root())\n        .no_manifest() // we are placing it in a different dir\n        .file(\n            \"ws_root/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\n            \"ws_root/src/main.rs\",\n            r#\"fn main() { println!(\"{}\", file!()); }\"#,\n        )\n        .build();\n\n    // Crucially, the path is relative to our fake home, not to the workspace root.\n    p.cargo(\"run\")\n        .arg(\"-Zroot-dir=.\")\n        .arg(\"--manifest-path=ws_root/Cargo.toml\")\n        .masquerade_as_nightly_cargo(&[\"-Zroot-dir\"])\n        .with_stdout_data(str![[r#\"\nws_root/src/main.rs\n\n\"#]])\n        .run();\n    // Try again with an absolute path for `root-dir`.\n    p.cargo(\"run\")\n        .arg(format!(\"-Zroot-dir={}\", p.root().display()))\n        .arg(\"--manifest-path=ws_root/Cargo.toml\")\n        .masquerade_as_nightly_cargo(&[\"-Zroot-dir\"])\n        .with_stdout_data(str![[r#\"\nws_root/src/main.rs\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/doc.rs",
    "content": "//! Tests for the `cargo doc` command.\n\nuse std::fs;\nuse std::str;\n\nuse crate::prelude::*;\nuse crate::utils::cross_compile::disabled as cross_compile_disabled;\nuse crate::utils::tools;\n\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::cross_compile;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_lib_manifest, basic_manifest, git, project};\nuse cargo_test_support::{rustc_host, symlink_supported};\n\n#[derive(serde::Serialize, serde::Deserialize)]\nstruct RustdocFingerprint {\n    rustc_vv: String,\n}\n\n#[cargo_test]\nfn simple() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n    assert!(p.root().join(\"target/doc\").is_dir());\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n}\n\n#[cargo_test]\nfn doc_no_libs() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"foo\"\n                doc = false\n            \"#,\n        )\n        .file(\"src/main.rs\", \"bad code\")\n        .build();\n\n    p.cargo(\"doc\").run();\n}\n\n#[cargo_test]\nfn doc_twice() {\n    let p = project().file(\"src/lib.rs\", \"pub fn foo() {}\").build();\n\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar; pub fn foo() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"doc\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar)\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    assert!(p.root().join(\"target/doc\").is_dir());\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/bar/index.html\").is_file());\n\n    // Verify that it only emits rmeta for the dependency.\n    assert_eq!(p.glob(\"target/debug/**/*.rlib\").count(), 0);\n    assert_eq!(p.glob(\"target/debug/deps/libbar-*.rmeta\").count(), 1);\n\n    // Make sure it doesn't recompile.\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    assert!(p.root().join(\"target/doc\").is_dir());\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/bar/index.html\").is_file());\n}\n\n#[cargo_test]\nfn doc_no_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar; pub fn foo() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"doc --no-deps\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    assert!(p.root().join(\"target/doc\").is_dir());\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(!p.root().join(\"target/doc/bar/index.html\").is_file());\n}\n\n#[cargo_test]\nfn doc_only_bin() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; pub fn foo() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"doc -v\").run();\n\n    assert!(p.root().join(\"target/doc\").is_dir());\n    assert!(p.root().join(\"target/doc/bar/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n}\n\n#[cargo_test]\nfn doc_multiple_targets_same_name_lib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                name = \"foo_lib\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                name = \"foo_lib\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc --workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] document output filename collision\nThe lib `foo_lib` in package `foo v0.1.0 ([ROOT]/foo/foo)` has the same name as the lib `foo_lib` in package `bar v0.1.0 ([ROOT]/foo/bar)`.\nOnly one may be documented at once since they output to the same path.\nConsider documenting only one, renaming one, or marking one with `doc = false` in Cargo.toml.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_multiple_targets_same_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [[bin]]\n                name = \"foo_lib\"\n                path = \"src/foo_lib.rs\"\n            \"#,\n        )\n        .file(\"foo/src/foo_lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                name = \"foo_lib\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc --workspace\")\n        .with_stderr_data(str![[r#\"\n[WARNING] output filename collision at [ROOT]/foo/target/doc/foo_lib/index.html\n  |\n  = [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>\n  = [NOTE] the bin target `foo_lib` in package `foo v0.1.0 ([ROOT]/foo/foo)` has the same output filename as the lib target `foo_lib` in package `bar v0.1.0 ([ROOT]/foo/bar)`\n[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar)\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo_lib/index.html and 1 other file\n\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn doc_multiple_targets_same_name_bin() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"foo/src/bin/foo-cli.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"bar/src/bin/foo-cli.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc --workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] document output filename collision\nThe bin `foo-cli` in package `foo v0.1.0 ([ROOT]/foo/foo)` has the same name as the bin `foo-cli` in package `bar v0.1.0 ([ROOT]/foo/bar)`.\nOnly one may be documented at once since they output to the same path.\nConsider documenting only one, renaming one, or marking one with `doc = false` in Cargo.toml.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_multiple_targets_same_name_undoced() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [[bin]]\n                name = \"foo-cli\"\n            \"#,\n        )\n        .file(\"foo/src/foo-cli.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [[bin]]\n                name = \"foo-cli\"\n                doc = false\n            \"#,\n        )\n        .file(\"bar/src/foo-cli.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc --workspace\").run();\n}\n\n#[cargo_test]\nfn doc_lib_bin_same_name_documents_lib() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                //! Binary documentation\n                extern crate foo;\n                fn main() {\n                    foo::foo();\n                }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! Library documentation\n                pub fn foo() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(doc_html.contains(\"Library\"));\n    assert!(!doc_html.contains(\"Binary\"));\n}\n\n#[cargo_test]\nfn doc_lib_bin_same_name_documents_lib_when_requested() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                //! Binary documentation\n                extern crate foo;\n                fn main() {\n                    foo::foo();\n                }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! Library documentation\n                pub fn foo() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"doc --lib\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(doc_html.contains(\"Library\"));\n    assert!(!doc_html.contains(\"Binary\"));\n}\n\n#[cargo_test]\nfn doc_lib_bin_same_name_with_dash() {\n    // Checks `doc` behavior when there is a dash in the package name, and\n    // there is a lib and bin, and the lib name is inferred.\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo-bar\", \"1.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo-bar v1.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo_bar/index.html\n\n\"#]])\n        .run();\n    assert!(p.build_dir().join(\"doc/foo_bar/index.html\").exists());\n    assert!(!p.build_dir().join(\"doc/foo_bar/fn.main.html\").exists());\n}\n\n#[cargo_test]\nfn doc_lib_bin_same_name_documents_named_bin_when_requested() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                //! Binary documentation\n                extern crate foo;\n                fn main() {\n                    foo::foo();\n                }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! Library documentation\n                pub fn foo() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"doc --bin foo\")\n        // The checking/documenting lines are sometimes swapped since they run\n        // concurrently.\n        .with_stderr_data(str![[r#\"\n[WARNING] output filename collision at [ROOT]/foo/target/doc/foo/index.html\n  |\n  = [NOTE] the bin target `foo` in package `foo v0.0.1 ([ROOT]/foo)` has the same output filename as the lib target `foo` in package `foo v0.0.1 ([ROOT]/foo)`\n  = [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]].unordered())\n        .run();\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(!doc_html.contains(\"Library\"));\n    assert!(doc_html.contains(\"Binary\"));\n}\n\n#[cargo_test]\nfn doc_lib_bin_same_name_documents_bins_when_requested() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                //! Binary documentation\n                extern crate foo;\n                fn main() {\n                    foo::foo();\n                }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! Library documentation\n                pub fn foo() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"doc --bins\")\n        // The checking/documenting lines are sometimes swapped since they run\n        // concurrently.\n        .with_stderr_data(str![[r#\"\n[WARNING] output filename collision at [ROOT]/foo/target/doc/foo/index.html\n  |\n  = [NOTE] the bin target `foo` in package `foo v0.0.1 ([ROOT]/foo)` has the same output filename as the lib target `foo` in package `foo v0.0.1 ([ROOT]/foo)`\n  = [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]].unordered())\n        .run();\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(!doc_html.contains(\"Library\"));\n    assert!(doc_html.contains(\"Binary\"));\n}\n\n#[cargo_test]\nfn doc_lib_bin_example_same_name_documents_named_example_when_requested() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                //! Binary documentation\n                extern crate foo;\n                fn main() {\n                    foo::foo();\n                }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! Library documentation\n                pub fn foo() {}\n            \"#,\n        )\n        .file(\n            \"examples/ex1.rs\",\n            r#\"\n                //! Example1 documentation\n                pub fn x() { f(); }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"doc --example ex1\")\n        // The checking/documenting lines are sometimes swapped since they run\n        // concurrently.\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/ex1/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/ex1/index.html\");\n    assert!(!doc_html.contains(\"Library\"));\n    assert!(!doc_html.contains(\"Binary\"));\n    assert!(doc_html.contains(\"Example1\"));\n}\n\n#[cargo_test]\nfn doc_lib_bin_example_same_name_documents_examples_when_requested() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                //! Binary documentation\n                extern crate foo;\n                fn main() {\n                    foo::foo();\n                }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! Library documentation\n                pub fn foo() {}\n            \"#,\n        )\n        .file(\n            \"examples/ex1.rs\",\n            r#\"\n                //! Example1 documentation\n                pub fn example1() { f(); }\n            \"#,\n        )\n        .file(\n            \"examples/ex2.rs\",\n            r#\"\n                //! Example2 documentation\n                pub fn example2() { f(); }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"doc --examples\")\n        // The checking/documenting lines are sometimes swapped since they run\n        // concurrently.\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/ex1/index.html and 1 other file\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    let example_doc_html_1 = p.read_file(\"target/doc/ex1/index.html\");\n    let example_doc_html_2 = p.read_file(\"target/doc/ex2/index.html\");\n\n    assert!(!example_doc_html_1.contains(\"Library\"));\n    assert!(!example_doc_html_1.contains(\"Binary\"));\n\n    assert!(!example_doc_html_2.contains(\"Library\"));\n    assert!(!example_doc_html_2.contains(\"Binary\"));\n\n    assert!(example_doc_html_1.contains(\"Example1\"));\n    assert!(example_doc_html_2.contains(\"Example2\"));\n}\n\n#[cargo_test]\nfn doc_dash_p() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate a;\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.b]\n                path = \"../b\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"extern crate b;\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -p a\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[DOCUMENTING] b v0.0.1 ([ROOT]/foo/b)\n[CHECKING] b v0.0.1 ([ROOT]/foo/b)\n[DOCUMENTING] a v0.0.1 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/a/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn doc_all_exclude() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() { break_the_build(); }\")\n        .build();\n\n    p.cargo(\"doc --workspace --exclude baz\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bar/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_all_exclude_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() { break_the_build(); }\")\n        .build();\n\n    p.cargo(\"doc --workspace --exclude '*z'\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bar/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_same_name() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/main.rs\", \"fn main() {}\")\n        .file(\"examples/main.rs\", \"fn main() {}\")\n        .file(\"tests/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"doc\").run();\n}\n\n#[cargo_test(nightly, reason = \"no_core, lang_items requires nightly\")]\nfn doc_target() {\n    const TARGET: &str = \"arm-unknown-linux-gnueabihf\";\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![allow(internal_features)]\n                #![feature(no_core, lang_items)]\n                #![no_core]\n\n                #[lang = \"pointee_sized\"]\n                trait PointeeSized {}\n\n                #[lang = \"meta_sized\"]\n                trait MetaSized: PointeeSized {}\n\n                #[lang = \"sized\"]\n                trait Sized: MetaSized {}\n\n                extern {\n                    pub static A: u32;\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"doc --verbose --target\").arg(TARGET).run();\n    assert!(p.root().join(&format!(\"target/{}/doc\", TARGET)).is_dir());\n    assert!(\n        p.root()\n            .join(&format!(\"target/{}/doc/foo/index.html\", TARGET))\n            .is_file()\n    );\n}\n\n#[cargo_test]\nfn target_specific_not_documented() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.foo.dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"not rust\")\n        .build();\n\n    p.cargo(\"doc\").run();\n}\n\n#[cargo_test]\nfn output_not_captured() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\n            \"a/src/lib.rs\",\n            \"\n            /// ```\n            /// `\n            /// ```\n            pub fn foo() {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n...\n[..]unknown start of token: `\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_specific_documented() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [target.foo.dependencies]\n                    a = {{ path = \"a\" }}\n                    [target.{}.dependencies]\n                    a = {{ path = \"a\" }}\n                \"#,\n                rustc_host()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate a;\n\n            /// test\n            pub fn foo() {}\n        \",\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\n            \"a/src/lib.rs\",\n            \"\n            /// test\n            pub fn foo() {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"doc\").run();\n}\n\n#[cargo_test]\nfn no_document_build_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [build-dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\n            \"a/src/lib.rs\",\n            \"\n            /// ```\n            /// ☃\n            /// ```\n            pub fn foo() {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"doc\").run();\n}\n\n#[cargo_test]\nfn doc_release() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"check --release\").run();\n    p.cargo(\"doc --release -v\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc [..] src/lib.rs [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_multiple_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n\n                [dependencies.baz]\n                path = \"baz\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar; pub fn foo() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.0.1\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"doc -p bar -p baz -v\").run();\n\n    assert!(p.root().join(\"target/doc\").is_dir());\n    assert!(p.root().join(\"target/doc/bar/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/baz/index.html\").is_file());\n}\n\n#[cargo_test]\nfn features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n\n                [features]\n                foo = [\"bar/bar\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\"#[cfg(feature = \"foo\")] pub fn foo() {}\"#)\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                bar = []\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"#[cfg(feature = \"bar\")] pub fn bar() {}\"#,\n        )\n        .build();\n    p.cargo(\"doc --features foo\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    assert!(p.root().join(\"target/doc\").is_dir());\n    assert!(p.root().join(\"target/doc/foo/fn.foo.html\").is_file());\n    assert!(p.root().join(\"target/doc/bar/fn.bar.html\").is_file());\n    // Check that turning the feature off will remove the files.\n    p.cargo(\"doc\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    assert!(!p.root().join(\"target/doc/foo/fn.foo.html\").is_file());\n    assert!(!p.root().join(\"target/doc/bar/fn.bar.html\").is_file());\n    // And switching back will rebuild and bring them back.\n    p.cargo(\"doc --features foo\")\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    assert!(p.root().join(\"target/doc/foo/fn.foo.html\").is_file());\n    assert!(p.root().join(\"target/doc/bar/fn.bar.html\").is_file());\n}\n\n#[cargo_test]\nfn rerun_when_dir_removed() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// dox\n                pub fn foo() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"doc\").run();\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n\n    fs::remove_dir_all(p.root().join(\"target/doc/foo\")).unwrap();\n\n    p.cargo(\"doc\").run();\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n}\n\n#[cargo_test]\nfn document_only_lib() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// dox\n                pub fn foo() {}\n            \"#,\n        )\n        .file(\n            \"src/bin/bar.rs\",\n            r#\"\n                /// ```\n                /// ☃\n                /// ```\n                pub fn foo() {}\n                fn main() { foo(); }\n            \"#,\n        )\n        .build();\n    p.cargo(\"doc --lib\").run();\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n}\n\n#[cargo_test]\nfn plugins_no_use_target() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"doc --target=x86_64-unknown-openbsd -v\").run();\n}\n\n#[cargo_test]\nfn doc_all_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    // The order in which bar is compiled or documented is not deterministic\n    p.cargo(\"doc --workspace\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar)\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bar/index.html and 1 other file\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn doc_all_workspace_verbose() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    // The order in which bar is compiled or documented is not deterministic\n    p.cargo(\"doc --workspace -v\")\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar)\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc [..]\n[RUNNING] `rustdoc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bar/index.html\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn doc_all_virtual_manifest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    // The order in which bar and baz are documented is not guaranteed\n    p.cargo(\"doc --workspace\")\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] baz v0.1.0 ([ROOT]/foo/baz)\n[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bar/index.html and 1 other file\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn doc_virtual_manifest_all_implied() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    // The order in which bar and baz are documented is not guaranteed\n    p.cargo(\"doc\")\n        .with_stderr_data(\n            str![[r#\"\n[GENERATED] [ROOT]/foo/target/doc/bar/index.html and 1 other file\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar)\n[DOCUMENTING] baz v0.1.0 ([ROOT]/foo/baz)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn doc_virtual_manifest_one_project() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() { break_the_build(); }\")\n        .build();\n\n    p.cargo(\"doc -p bar\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bar/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_virtual_manifest_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {  break_the_build(); }\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"doc -p '*z'\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] baz v0.1.0 ([ROOT]/foo/baz)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/baz/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_all_member_dependency_same_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    p.cargo(\"doc --workspace\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[WARNING] output filename collision at [ROOT]/foo/target/doc/bar/index.html\n  |\n  = [NOTE] the lib target `bar` in package `bar v0.1.0` has the same output filename as the lib target `bar` in package `bar v0.1.0 ([ROOT]/foo/bar)`\n  = [NOTE] this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>\n[DOCUMENTING] bar v0.1.0\n[CHECKING] bar v0.1.0\n[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bar/index.html\n\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn doc_workspace_open_help_message() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n            \"#,\n        )\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    // The order in which bar is compiled or documented is not deterministic\n    p.cargo(\"doc --workspace --open\")\n        .env(\"BROWSER\", tools::echo())\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo/foo)\n[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[OPENING] [ROOT]/foo/target/doc/bar/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zextern-html-root-url is unstable\")]\nfn doc_extern_map_local() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\".cargo/config.toml\", \"doc.extern-map.std = 'local'\")\n        .build();\n\n    p.cargo(\"doc -v --no-deps -Zrustdoc-map --open\")\n        .env(\"BROWSER\", tools::echo())\n        .masquerade_as_nightly_cargo(&[\"rustdoc-map\"])\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustdoc --edition=2015 --crate-type lib --crate-name foo src/lib.rs [..]--crate-version 0.1.0`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[OPENING] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn open_no_doc_crate() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [lib]\n            doc = false\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"#[cfg(feature)] pub fn f();\")\n        .build();\n\n    p.cargo(\"doc --open\")\n        .env(\"BROWSER\", \"do_not_run_me\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[ERROR] cannot open specified crate's documentation: no documentation generated\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_workspace_open_different_library_and_package_names() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                name = \"foolib\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc --open\")\n        .env(\"BROWSER\", tools::echo())\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[OPENING] [ROOT]/foo/target/doc/foolib/index.html\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n[ROOT]/foo/target/doc/foolib/index.html\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \".cargo/config.toml\",\n        &format!(\n            r#\"\n                [doc]\n                browser = [\"{}\", \"a\"]\n            \"#,\n            tools::echo().display().to_string().replace('\\\\', \"\\\\\\\\\")\n        ),\n    );\n\n    // check that the cargo config overrides the browser env var\n    p.cargo(\"doc --open\")\n        .env(\"BROWSER\", \"do_not_run_me\")\n        .with_stdout_data(str![[r#\"\na [ROOT]/foo/target/doc/foolib/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_workspace_open_binary() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [[bin]]\n                name = \"foobin\"\n                path = \"src/main.rs\"\n            \"#,\n        )\n        .file(\"foo/src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc --open\")\n        .env(\"BROWSER\", tools::echo())\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[OPENING] [ROOT]/foo/target/doc/foobin/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_workspace_open_binary_and_library() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                name = \"foolib\"\n                [[bin]]\n                name = \"foobin\"\n                path = \"src/main.rs\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\"foo/src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc --open\")\n        .env(\"BROWSER\", tools::echo())\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo/foo)\n[CHECKING] foo v0.1.0 ([ROOT]/foo/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[OPENING] [ROOT]/foo/target/doc/foolib/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn doc_edition() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2018\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -v\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--edition=2018[..]\n...\n\"#]])\n        .run();\n\n    p.cargo(\"test -v\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--edition=2018[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_target_edition() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                edition = \"2018\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -v\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--edition=2018[..]\n...\n\"#]])\n        .run();\n\n    p.cargo(\"test -v\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--edition=2018[..]\n...\n\"#]])\n        .run();\n}\n\n// Tests an issue where depending on different versions of the same crate depending on `cfg`s\n// caused `cargo doc` to fail.\n#[cargo_test]\nfn issue_5345() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'cfg(all(windows, target_arch = \"x86\"))'.dependencies]\n                bar = \"0.1\"\n\n                [target.'cfg(not(all(windows, target_arch = \"x86\")))'.dependencies]\n                bar = \"0.2\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .build();\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    foo.cargo(\"check\").run();\n    foo.cargo(\"doc\").run();\n}\n\n#[cargo_test]\nfn doc_private_items() {\n    let foo = project()\n        .file(\"src/lib.rs\", \"mod private { fn private_item() {} }\")\n        .build();\n    foo.cargo(\"doc --document-private-items\").run();\n\n    assert!(foo.root().join(\"target/doc\").is_dir());\n    assert!(\n        foo.root()\n            .join(\"target/doc/foo/private/index.html\")\n            .is_file()\n    );\n}\n\n#[cargo_test]\nfn doc_private_ws() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"fn p() {}\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"fn p2() {}\")\n        .file(\"b/src/bin/b-cli.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"doc --workspace --bins --lib --document-private-items -v\")\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] b v0.0.1 ([ROOT]/foo/b)\n[CHECKING] b v0.0.1 ([ROOT]/foo/b)\n[DOCUMENTING] a v0.0.1 ([ROOT]/foo/a)\n[RUNNING] `rustdoc [..] a/src/lib.rs [..]--document-private-items[..]\n[RUNNING] `rustc [..]\n[WARNING] function `p2` is never used\n...\n[RUNNING] `rustdoc [..] b/src/lib.rs [..]--document-private-items[..]\n[WARNING] `b` (lib) generated 1 warning\n[RUNNING] `rustdoc [..] b/src/bin/b-cli.rs [..]--document-private-items[..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/a/index.html\n[GENERATED] [ROOT]/foo/target/doc/b/index.html\n[GENERATED] [ROOT]/foo/target/doc/b_cli/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\nconst BAD_INTRA_LINK_LIB: &str = r#\"\n#![deny(rustdoc::broken_intra_doc_links)]\n\n/// [bad_link]\npub fn foo() {}\n\"#;\n\n#[cargo_test]\nfn doc_cap_lints() {\n    let a = git::new(\"a\", |p| {\n        p.file(\"Cargo.toml\", &basic_lib_manifest(\"a\"))\n            .file(\"src/lib.rs\", BAD_INTRA_LINK_LIB)\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    a = {{ git = '{}' }}\n                \"#,\n                a.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[UPDATING] git repository `[..]`\n[DOCUMENTING] a v0.5.0 ([..])\n[CHECKING] a v0.5.0 ([..])\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.root().join(\"target\").rm_rf();\n\n    p.cargo(\"doc -vv\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] [..]`bad_link`[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_message_format() {\n    let p = project().file(\"src/lib.rs\", BAD_INTRA_LINK_LIB).build();\n\n    p.cargo(\"doc --message-format=json\")\n        .with_status(101)\n        .with_stdout_data(\n            str![[r##\"\n[\n  {\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"message\": {\n      \"$message_type\": \"diagnostic\",\n      \"level\": \"error\",\n      \"...\": \"{...}\"\n    },\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.1\",\n    \"reason\": \"compiler-message\",\n    \"target\": \"{...}\"\n  },\n  \"{...}\"\n]\n\"##]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn doc_json_artifacts() {\n    // Checks the output of json artifact messages.\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/somebin.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"doc --message-format=json\")\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"executable\": null,\n    \"features\": [],\n    \"filenames\": [\n      \"[ROOT]/foo/target/debug/deps/libfoo-[HASH].rmeta\"\n    ],\n    \"fresh\": false,\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.1\",\n    \"profile\": \"{...}\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"crate_types\": [\n        \"lib\"\n      ],\n      \"doc\": true,\n      \"doctest\": true,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"lib\"\n      ],\n      \"name\": \"foo\",\n      \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n      \"test\": true\n    }\n  },\n  {\n    \"executable\": null,\n    \"features\": [],\n    \"filenames\": [\n      \"[ROOT]/foo/target/doc/foo/index.html\"\n    ],\n    \"fresh\": false,\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.1\",\n    \"profile\": \"{...}\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"crate_types\": [\n        \"lib\"\n      ],\n      \"doc\": true,\n      \"doctest\": true,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"lib\"\n      ],\n      \"name\": \"foo\",\n      \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n      \"test\": true\n    }\n  },\n  {\n    \"executable\": null,\n    \"features\": [],\n    \"filenames\": [\n      \"[ROOT]/foo/target/doc/somebin/index.html\"\n    ],\n    \"fresh\": false,\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.1\",\n    \"profile\": \"{...}\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"somebin\",\n      \"src_path\": \"[ROOT]/foo/src/bin/somebin.rs\",\n      \"test\": true\n    }\n  },\n  {\n    \"reason\": \"build-finished\",\n    \"success\": true\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines()\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn short_message_format() {\n    let p = project().file(\"src/lib.rs\", BAD_INTRA_LINK_LIB).build();\n    p.cargo(\"doc --message-format=short\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\nsrc/lib.rs:4:6: [ERROR] [..]`bad_link`[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_example() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [[example]]\n            crate-type = [\"lib\"]\n            name = \"ex1\"\n            doc = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn f() {}\")\n        .file(\n            \"examples/ex1.rs\",\n            r#\"\n            use foo::f;\n\n            /// Example\n            pub fn x() { f(); }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"doc\").run();\n    assert!(\n        p.build_dir()\n            .join(\"doc\")\n            .join(\"ex1\")\n            .join(\"fn.x.html\")\n            .exists()\n    );\n}\n\n#[cargo_test]\nfn doc_example_with_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [[example]]\n            crate-type = [\"lib\"]\n            name = \"ex\"\n            doc = true\n\n            [dev-dependencies]\n            a = {path = \"a\"}\n            b = {path = \"b\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"examples/ex.rs\",\n            r#\"\n            use a::fun;\n\n            /// Example\n            pub fn x() { fun(); }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            b = {path = \"../b\"}\n            \"#,\n        )\n        .file(\"a/src/fun.rs\", \"pub fn fun() {}\")\n        .file(\"a/src/lib.rs\", \"pub mod fun;\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc --examples\").run();\n    assert!(\n        p.build_dir()\n            .join(\"doc\")\n            .join(\"ex\")\n            .join(\"fn.x.html\")\n            .exists()\n    );\n}\n\n#[cargo_test]\nfn bin_private_items() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n            pub fn foo_pub() {}\n            fn foo_priv() {}\n            struct FooStruct;\n            enum FooEnum {}\n            trait FooTrait {}\n            type FooType = u32;\n            mod foo_mod {}\n\n        \",\n        )\n        .build();\n\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/foo/fn.foo_pub.html\").is_file());\n    assert!(p.root().join(\"target/doc/foo/fn.foo_priv.html\").is_file());\n    assert!(\n        p.root()\n            .join(\"target/doc/foo/struct.FooStruct.html\")\n            .is_file()\n    );\n    assert!(p.root().join(\"target/doc/foo/enum.FooEnum.html\").is_file());\n    assert!(\n        p.root()\n            .join(\"target/doc/foo/trait.FooTrait.html\")\n            .is_file()\n    );\n    assert!(p.root().join(\"target/doc/foo/type.FooType.html\").is_file());\n    assert!(p.root().join(\"target/doc/foo/foo_mod/index.html\").is_file());\n}\n\n#[cargo_test]\nfn bin_private_items_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n            fn foo_priv() {}\n            pub fn foo_pub() {}\n        \",\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\n            \"bar/src/lib.rs\",\n            \"\n            #[allow(dead_code)]\n            fn bar_priv() {}\n            pub fn bar_pub() {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"doc\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar)\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/foo/fn.foo_pub.html\").is_file());\n    assert!(p.root().join(\"target/doc/foo/fn.foo_priv.html\").is_file());\n\n    assert!(p.root().join(\"target/doc/bar/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/bar/fn.bar_pub.html\").is_file());\n    assert!(!p.root().join(\"target/doc/bar/fn.bar_priv.html\").exists());\n}\n\n#[cargo_test]\nfn crate_versions() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.2.4\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -v\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v1.2.4 ([ROOT]/foo)\n[RUNNING] `rustdoc --edition=2015 --crate-type lib --crate-name foo src/lib.rs [..]--crate-version 1.2.4`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    let output_path = p.root().join(\"target/doc/foo/index.html\");\n    let output_documentation = fs::read_to_string(&output_path).unwrap();\n\n    assert!(output_documentation.contains(\"1.2.4\"));\n}\n\n#[cargo_test]\nfn crate_versions_flag_is_overridden() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.2.4\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let output_documentation = || {\n        let output_path = p.root().join(\"target/doc/foo/index.html\");\n        fs::read_to_string(&output_path).unwrap()\n    };\n    let asserts = |html: String| {\n        assert!(!html.contains(\"1.2.4\"));\n        assert!(html.contains(\"2.0.3\"));\n    };\n\n    p.cargo(\"doc\")\n        .env(\"RUSTDOCFLAGS\", \"--crate-version 2.0.3\")\n        .run();\n    asserts(output_documentation());\n\n    p.build_dir().rm_rf();\n\n    p.cargo(\"rustdoc -- --crate-version 2.0.3\").run();\n    asserts(output_documentation());\n}\n\n#[cargo_test]\nfn doc_test_in_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\n                    \"crate-a\",\n                    \"crate-b\",\n                ]\n            \"#,\n        )\n        .file(\n            \"crate-a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"crate-a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"crate-a/src/lib.rs\",\n            \"\\\n                //! ```\n                //! assert_eq!(1, 1);\n                //! ```\n            \",\n        )\n        .file(\n            \"crate-b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"crate-b\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"crate-b/src/lib.rs\",\n            \"\\\n                //! ```\n                //! assert_eq!(1, 1);\n                //! ```\n            \",\n        )\n        .build();\n    p.cargo(\"test --doc -vv\")\n        .with_stderr_data(str![[r#\"\n...\n[DOCTEST] crate_a\n...\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest crate-a/src/lib.rs - (line 1) ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest crate-b/src/lib.rs - (line 1) ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n/// This is a test for <https://github.com/rust-lang/rust/issues/46372>.\n/// The `file!()` macro inside of an `include!()` should output\n/// workspace-relative paths, just like it does in other cases.\n#[cargo_test]\nfn doc_test_include_file() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\n                    \"child\",\n                ]\n                [package]\n                name = \"root\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// assert_eq!(\"src/lib.rs\", file!().replace(\"\\\\\", \"/\"))\n                /// ```\n                pub mod included {\n                    include!(concat!(\"../\", file!(), \".included.rs\"));\n                }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs.included.rs\",\n            r#\"\n                /// ```\n                /// assert_eq!(1, 1)\n                /// ```\n                pub fn foo() {}\n            \"#,\n        )\n        .file(\n            \"child/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"child\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"child/src/lib.rs\",\n            r#\"\n                /// ```\n                /// assert_eq!(\"child/src/lib.rs\", file!().replace(\"\\\\\", \"/\"))\n                /// ```\n                pub mod included {\n                    include!(concat!(\"../../\", file!(), \".included.rs\"));\n                }\n            \"#,\n        )\n        .file(\n            \"child/src/lib.rs.included.rs\",\n            r#\"\n                /// ```\n                /// assert_eq!(1, 1)\n                /// ```\n                pub fn foo() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test --workspace --doc -vv -- --test-threads=1\")\n        .with_stderr_data(str![[r#\"\n...\n[DOCTEST] child\n...\n[DOCTEST] root\n...\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 2 tests\ntest child/src/../../child/src/lib.rs.included.rs - included::foo (line 2) ... ok\ntest child/src/lib.rs - included (line 2) ... ok\n\ntest result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 2 tests\ntest src/../src/lib.rs.included.rs - included::foo (line 2) ... ok\ntest src/lib.rs - included (line 2) ... ok\n\ntest result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_fingerprint_is_versioning_consistent() {\n    // Random rustc verbose version\n    let old_rustc_verbose_version = format!(\n        \"\\\nrustc 1.41.1 (f3e1a954d 2020-02-24)\nbinary: rustc\ncommit-hash: f3e1a954d2ead4e2fc197c7da7d71e6c61bad196\ncommit-date: 2020-02-24\nhost: {}\nrelease: 1.41.1\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    // Create the dummy project.\n    let dummy_project = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.2.4\"\n            edition = \"2015\"\n            authors = []\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"//! These are the docs!\")\n        .build();\n\n    dummy_project.cargo(\"doc\").run();\n\n    let fingerprint: RustdocFingerprint =\n        serde_json::from_str(&dummy_project.read_file(\"target/.rustdoc_fingerprint.json\"))\n            .expect(\"JSON Serde fail\");\n\n    // Check that the fingerprint contains the actual rustc version\n    // which has been used to compile the docs.\n    let output = std::process::Command::new(\"rustc\")\n        .arg(\"-vV\")\n        .output()\n        .expect(\"Failed to get actual rustc verbose version\");\n    assert_eq!(\n        fingerprint.rustc_vv,\n        (String::from_utf8_lossy(&output.stdout).as_ref())\n    );\n\n    // As the test shows above. Now we have generated the `doc/` folder and inside\n    // the rustdoc fingerprint file is located with the correct rustc version.\n    // So we will remove it and create a new fingerprint with an old rustc version\n    // inside it. We will also place a bogus file inside of the `doc/` folder to ensure\n    // it gets removed as we expect on the next doc compilation.\n    dummy_project.change_file(\n        \"target/.rustdoc_fingerprint.json\",\n        &old_rustc_verbose_version,\n    );\n\n    fs::write(\n        dummy_project.build_dir().join(\"doc/bogus_file\"),\n        String::from(\"This is a bogus file and should be removed!\"),\n    )\n    .expect(\"Error writing test bogus file\");\n\n    // Now if we trigger another compilation, since the fingerprint contains an old version\n    // of rustc, cargo should remove the entire `/doc` folder (including the fingerprint)\n    // and generating another one with the actual version.\n    // It should also remove the bogus file we created above.\n    dummy_project.cargo(\"doc\").run();\n\n    assert!(!dummy_project.build_dir().join(\"doc/bogus_file\").exists());\n\n    let fingerprint: RustdocFingerprint =\n        serde_json::from_str(&dummy_project.read_file(\"target/.rustdoc_fingerprint.json\"))\n            .expect(\"JSON Serde fail\");\n\n    // Check that the fingerprint contains the actual rustc version\n    // which has been used to compile the docs.\n    assert_eq!(\n        fingerprint.rustc_vv,\n        (String::from_utf8_lossy(&output.stdout).as_ref())\n    );\n}\n\n#[cargo_test]\nfn doc_fingerprint_respects_target_paths() {\n    let host = rustc_host();\n    // Random rustc verbose version\n    let old_rustc_verbose_version = format!(\n        \"\\\nrustc 1.41.1 (f3e1a954d 2020-02-24)\nbinary: rustc\ncommit-hash: f3e1a954d2ead4e2fc197c7da7d71e6c61bad196\ncommit-date: 2020-02-24\nhost: {host}\nrelease: 1.41.1\nLLVM version: 9.0\n\",\n    );\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            edition = \"2021\"\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"//! These are the docs!\")\n        .build();\n\n    // generate `target/doc` and `target/<host>/doc\n    p.cargo(\"doc --target\").arg(host).run();\n    p.cargo(\"doc\").run();\n\n    let host_fingerprint_path = p.build_dir().join(\".rustdoc_fingerprint.json\");\n\n    let target_fingerprint_path = p.build_dir().join(host).join(\".rustdoc_fingerprint.json\");\n\n    let host_fingerprint: RustdocFingerprint =\n        serde_json::from_str(&fs::read_to_string(&host_fingerprint_path).unwrap())\n            .expect(\"JSON Serde fail\");\n\n    let target_fingerprint: RustdocFingerprint =\n        serde_json::from_str(&fs::read_to_string(&target_fingerprint_path).unwrap())\n            .expect(\"JSON Serde fail\");\n\n    assert_eq!(host_fingerprint.rustc_vv, target_fingerprint.rustc_vv);\n\n    // Check that the fingerprint contains the actual rustc version\n    // which has been used to compile the docs.\n    let current_rustc_version = String::from_utf8(\n        std::process::Command::new(\"rustc\")\n            .arg(\"-vV\")\n            .output()\n            .unwrap()\n            .stdout,\n    )\n    .unwrap();\n    assert_eq!(&host_fingerprint.rustc_vv, &current_rustc_version);\n\n    // Write random `rustc -vV` output and bogus file for both host and target\n    fs::write(&host_fingerprint_path, &old_rustc_verbose_version).unwrap();\n    fs::write(&target_fingerprint_path, &old_rustc_verbose_version).unwrap();\n    fs::write(\n        p.build_dir().join(host).join(\"doc/bogus_file\"),\n        \"This is a bogus file and should be removed!\",\n    )\n    .unwrap();\n    fs::write(\n        p.build_dir().join(\"doc/bogus_file\"),\n        \"This is a bogus file and should be removed!\",\n    )\n    .unwrap();\n\n    // ...but run only target\n    p.cargo(\"doc --target\").arg(host).run();\n\n    // host doc dir stays the same, and the fingerprint is still the old random one\n    assert!(p.build_dir().join(\"doc/bogus_file\").exists());\n    assert_eq!(\n        &fs::read_to_string(&host_fingerprint_path).unwrap(),\n        &old_rustc_verbose_version,\n    );\n\n    // target doc dir got cleaned\n    assert!(!p.build_dir().join(host).join(\"doc/bogus_file\").exists());\n    let fingerprint: RustdocFingerprint =\n        serde_json::from_str(&fs::read_to_string(&target_fingerprint_path).unwrap()).unwrap();\n    assert_eq!(&fingerprint.rustc_vv, &current_rustc_version);\n}\n\n#[cargo_test]\nfn doc_fingerprint_unusual_behavior() {\n    // Checks for some unusual circumstances with clearing the doc directory.\n    if !symlink_supported() {\n        return;\n    }\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.build_dir().mkdir_p();\n    let real_doc = p.root().join(\"doc\");\n    real_doc.mkdir_p();\n    let build_doc = p.build_dir().join(\"doc\");\n    p.symlink(&real_doc, &build_doc);\n    fs::write(real_doc.join(\"somefile\"), \"test\").unwrap();\n    fs::write(real_doc.join(\".hidden\"), \"test\").unwrap();\n    p.cargo(\"doc\").run();\n    // Make sure for the first run, it does not delete any files and does not\n    // break the symlink.\n    assert!(build_doc.join(\"somefile\").exists());\n    assert!(real_doc.join(\"somefile\").exists());\n    assert!(real_doc.join(\".hidden\").exists());\n    assert!(real_doc.join(\"foo/index.html\").exists());\n    // Pretend that the last build was generated by an older version.\n    p.change_file(\n        \"target/.rustdoc_fingerprint.json\",\n        \"{\\\"rustc_vv\\\": \\\"I am old\\\"}\",\n    );\n    // Change file to trigger a new build.\n    p.change_file(\"src/lib.rs\", \"// changed\");\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n    // This will delete somefile, but not .hidden.\n    assert!(!real_doc.join(\"somefile\").exists());\n    assert!(real_doc.join(\".hidden\").exists());\n    assert!(real_doc.join(\"foo/index.html\").exists());\n    // And also check the -Z flag behavior.\n    p.change_file(\n        \"target/.rustdoc_fingerprint.json\",\n        \"{\\\"rustc_vv\\\": \\\"I am old\\\"}\",\n    );\n    // Change file to trigger a new build.\n    p.change_file(\"src/lib.rs\", \"// changed2\");\n    fs::write(real_doc.join(\"somefile\"), \"test\").unwrap();\n    p.cargo(\"doc -Z skip-rustdoc-fingerprint\")\n        .masquerade_as_nightly_cargo(&[\"skip-rustdoc-fingerprint\"])\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n    // Should not have deleted anything.\n    assert!(build_doc.join(\"somefile\").exists());\n    assert!(real_doc.join(\"somefile\").exists());\n}\n\n#[cargo_test]\nfn lib_before_bin() {\n    // Checks that the library is documented before the binary.\n    // Previously they were built concurrently, which can cause issues\n    // if the bin has intra-doc links to the lib.\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// Hi\n                pub fn abc() {}\n            \"#,\n        )\n        .file(\n            \"src/bin/somebin.rs\",\n            r#\"\n                //! See [`foo::abc`]\n                fn main() {}\n            \"#,\n        )\n        .build();\n\n    // Run check first. This just helps ensure that the test clearly shows the\n    // order of the rustdoc commands.\n    p.cargo(\"check\").run();\n\n    // The order of output here should be deterministic.\n    p.cargo(\"doc -v\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc --edition=2015 --crate-type lib --crate-name foo src/lib.rs [..]\n[RUNNING] `rustdoc --edition=2015 --crate-type bin --crate-name somebin src/bin/somebin.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n[GENERATED] [ROOT]/foo/target/doc/somebin/index.html\n\n\"#]])\n        .run();\n\n    // And the link should exist.\n    let bin_html = p.read_file(\"target/doc/somebin/index.html\");\n    assert!(bin_html.contains(\"../foo/fn.abc.html\"));\n}\n\n#[cargo_test]\nfn doc_lib_false() {\n    // doc = false for a library\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                doc = false\n\n                [dependencies]\n                bar = {path = \"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .file(\"src/bin/some-bin.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                doc = false\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/some_bin/index.html\n\n\"#]])\n        .run();\n\n    assert!(!p.build_dir().join(\"doc/foo\").exists());\n    assert!(!p.build_dir().join(\"doc/bar\").exists());\n    assert!(p.build_dir().join(\"doc/some_bin\").exists());\n}\n\n#[cargo_test]\nfn doc_lib_false_dep() {\n    // doc = false for a dependency\n    // Ensures that the rmeta gets produced\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                doc = false\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    assert!(p.build_dir().join(\"doc/foo\").exists());\n    assert!(!p.build_dir().join(\"doc/bar\").exists());\n}\n\n#[cargo_test]\nfn link_to_private_item() {\n    let main = r#\"\n    //! [bar]\n    #[allow(dead_code)]\n    fn bar() {}\n    \"#;\n    let p = project().file(\"src/lib.rs\", main).build();\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n...\n[..]documentation for `foo` links to private item `bar`\n...\n\"#]])\n        .run();\n    // Check that binaries don't emit a private_intra_doc_links warning.\n    fs::rename(p.root().join(\"src/lib.rs\"), p.root().join(\"src/main.rs\")).unwrap();\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_failure_hides_command_line_by_default() {\n    let p = project().file(\"src/lib.rs\", \"invalid rust code\").build();\n\n    // `cargo doc` doesn't print the full command line on failures by default\n    p.cargo(\"doc\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] expected one of `!` or `::`, found `rust`\n --> src/lib.rs:1:9\n  |\n1 | invalid rust code\n  |         ^^^^ expected one of `!` or `::`\n\n[ERROR] could not document `foo`\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    // ... but it still does so if requested with `--verbose`.\n    p.cargo(\"doc --verbose\")\n        .with_stderr_data(str![[r#\"\n...\nCaused by:\n  process didn't exit successfully[..]rustdoc[..]\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"`rustdoc --emit` is unstable\")]\nfn rustdoc_depinfo_gated() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -Zrustdoc-depinfo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `-Z` flag is only accepted on the nightly channel of Cargo, but this is the `stable` channel\nSee https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"`rustdoc --emit` is unstable\")]\nfn rebuild_tracks_target_src_outside_package_root() {\n    let p = cargo_test_support::project_in(\"parent\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n                [lib]\n                path = \"../lib.rs\"\n            \"#,\n        )\n        .file(\"../lib.rs\", \"//! # depinfo-before\")\n        .build();\n\n    p.cargo(\"doc -Zrustdoc-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.0 ([ROOT]/parent/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/parent/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(doc_html.contains(\"depinfo-before\"));\n\n    p.change_file(\"../lib.rs\", \"//! # depinfo-after\");\n\n    p.cargo(\"doc --verbose -Zrustdoc-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.0 ([ROOT]/parent/foo): the file `../lib.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[DOCUMENTING] foo v0.0.0 ([ROOT]/parent/foo)\n[RUNNING] `rustdoc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/parent/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(doc_html.contains(\"depinfo-after\"));\n}\n\n#[cargo_test(nightly, reason = \"`rustdoc --emit` is unstable\")]\nfn rebuild_tracks_include_str() {\n    let p = cargo_test_support::project_in(\"parent\")\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", r#\"#![doc = include_str!(\"../../README\")]\"#)\n        .file(\"../README\", \"# depinfo-before\")\n        .build();\n\n    p.cargo(\"doc -Zrustdoc-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.5.0 ([ROOT]/parent/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/parent/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(doc_html.contains(\"depinfo-before\"));\n\n    p.change_file(\"../README\", \"# depinfo-after\");\n\n    p.cargo(\"doc --verbose -Zrustdoc-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/parent/foo): the file `src/../../README` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[DOCUMENTING] foo v0.5.0 ([ROOT]/parent/foo)\n[RUNNING] `rustdoc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/parent/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(doc_html.contains(\"depinfo-after\"));\n}\n\n#[cargo_test(nightly, reason = \"`rustdoc --emit` is unstable\")]\nfn rebuild_tracks_path_attr() {\n    let p = cargo_test_support::project_in(\"parent\")\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", r#\"#[path = \"../../bar.rs\"] pub mod bar;\"#)\n        .file(\"../bar.rs\", \"//! # depinfo-before\")\n        .build();\n\n    p.cargo(\"doc -Zrustdoc-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.5.0 ([ROOT]/parent/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/parent/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(doc_html.contains(\"depinfo-before\"));\n\n    p.change_file(\"../bar.rs\", \"//! # depinfo-after\");\n\n    p.cargo(\"doc --verbose -Zrustdoc-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/parent/foo): the file `src/../../bar.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[DOCUMENTING] foo v0.5.0 ([ROOT]/parent/foo)\n[RUNNING] `rustdoc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/parent/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(doc_html.contains(\"depinfo-after\"));\n}\n\n#[cargo_test(nightly, reason = \"`rustdoc --emit` is unstable\")]\nfn rebuild_tracks_env() {\n    let env = \"__RUSTDOC_INJECTED\";\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", &format!(r#\"#![doc = env!(\"{env}\")]\"#))\n        .build();\n\n    p.cargo(\"doc -Zrustdoc-depinfo\")\n        .env(env, \"# depinfo-before\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(doc_html.contains(\"depinfo-before\"));\n\n    p.cargo(\"doc --verbose -Zrustdoc-depinfo\")\n        .env(env, \"# depinfo-after\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/foo): the environment variable __RUSTDOC_INJECTED changed\n[DOCUMENTING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(doc_html.contains(\"depinfo-after\"));\n}\n\n#[cargo_test(nightly, reason = \"`rustdoc --emit` is unstable\")]\nfn rebuild_tracks_env_in_dep() {\n    let env = \"__RUSTDOC_INJECTED\";\n    Package::new(\"bar\", \"0.1.0\")\n        .file(\"src/lib.rs\", &format!(r#\"#![doc = env!(\"{env}\")]\"#))\n        .publish();\n\n    let env = \"__RUSTDOC_INJECTED\";\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -Zrustdoc-depinfo\")\n        .env(env, \"# depinfo-before\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-depinfo\"])\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[DOCUMENTING] bar v0.1.0\n[DOCUMENTING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/bar/index.html\");\n    assert!(doc_html.contains(\"depinfo-before\"));\n\n    p.cargo(\"doc --verbose -Zrustdoc-depinfo\")\n        .env(env, \"# depinfo-after\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-depinfo\"])\n        .with_stderr_data(\n            str![[r#\"\n[DIRTY] bar v0.1.0: the environment variable __RUSTDOC_INJECTED changed\n[DOCUMENTING] bar v0.1.0\n[DIRTY] bar v0.1.0: the environment variable __RUSTDOC_INJECTED changed\n[CHECKING] bar v0.1.0\n[RUNNING] `rustc --crate-name bar [..]`\n[RUNNING] `rustdoc [..]--crate-name bar [..]`\n[DIRTY] foo v0.0.0 ([ROOT]/foo): the dependency `bar` was rebuilt\n[DOCUMENTING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]--crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/bar/index.html\");\n    assert!(doc_html.contains(\"depinfo-after\"));\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"`rustdoc --emit` is unstable; requires -Zchecksum-hash-algorithm\"\n)]\nfn rebuild_tracks_checksum() {\n    let p = cargo_test_support::project_in(\"parent\")\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", r#\"#![doc = include_str!(\"../../README\")]\"#)\n        .file(\"../README\", \"# depinfo-before\")\n        .build();\n\n    p.cargo(\"doc -Zrustdoc-depinfo -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-depinfo\", \"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.5.0 ([ROOT]/parent/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/parent/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(doc_html.contains(\"depinfo-before\"));\n\n    p.change_file(\"../README\", \"# depinfo-after\");\n    // Change mtime into the future\n    p.root().move_into_the_future();\n\n    p.cargo(\"doc --verbose -Zrustdoc-depinfo -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/parent/foo): file size changed (16 != 15) for `src/../../README`\n[DOCUMENTING] foo v0.5.0 ([ROOT]/parent/foo)\n[RUNNING] `rustdoc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/parent/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/index.html\");\n    assert!(doc_html.contains(\"depinfo-after\"));\n}\n\n#[cargo_test(nightly, reason = \"rustdoc mergeable crate info is unstable\")]\nfn mergeable_info_gated() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -Zrustdoc-mergeable-info\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `-Z` flag is only accepted on the nightly channel of Cargo, but this is the `stable` channel\nSee https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"rustdoc mergeable crate info is unstable\")]\nfn mergeable_info_with_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n\n                [dependencies.dep]\n                path = \"dep\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate dep; pub fn foo() {}\")\n        .file(\"dep/Cargo.toml\", &basic_manifest(\"dep\", \"0.0.0\"))\n        .file(\"dep/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[DOCUMENTING] dep v0.0.0 ([ROOT]/foo/dep)\n[CHECKING] dep v0.0.0 ([ROOT]/foo/dep)\n[RUNNING] `rustdoc [..]--crate-name dep [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/dep-[HASH]/out [..]`\n[RUNNING] `rustc --crate-name dep [..]`\n[DOCUMENTING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]--crate-name foo [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 2 docs for host\n[RUNNING] `rustdoc -o [ROOT]/foo/target/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/debug/build/dep-[HASH]/out --include-parts-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]].unordered()\n        )\n        .run();\n\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/dep/index.html\").is_file());\n    assert_eq!(p.glob(\"target/debug/build/foo-*/out/foo.json\").count(), 1);\n    assert_eq!(p.glob(\"target/debug/build/dep-*/out/dep.json\").count(), 1);\n\n    assert_e2e().eq(\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap(),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/dep-[HASH]/out/dep.json\",\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test(nightly, reason = \"rustdoc mergeable crate info is unstable\")]\nfn mergeable_info_no_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n\n                [dependencies.dep]\n                path = \"dep\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate dep; pub fn foo() {}\")\n        .file(\"dep/Cargo.toml\", &basic_manifest(\"dep\", \"0.0.0\"))\n        .file(\"dep/src/lib.rs\", \"pub fn dep() {}\")\n        .build();\n\n    p.cargo(\"doc -v --no-deps -Zrustdoc-mergeable-info\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] dep v0.0.0 ([ROOT]/foo/dep)\n[RUNNING] `rustc --crate-name dep --edition=2015 [..]`\n[DOCUMENTING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]--crate-name foo [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 1 doc for host\n[RUNNING] `rustdoc -o [ROOT]/foo/target/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n        )\n        .run();\n\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(!p.root().join(\"target/doc/dep/index.html\").is_file());\n    assert_eq!(p.glob(\"target/debug/build/foo-*/out/foo.json\").count(), 1);\n    assert_eq!(p.glob(\"target/debug/build/dep-*/out/dep.json\").count(), 0);\n\n    assert_e2e().eq(\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap(),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test(nightly, reason = \"rustdoc mergeable crate info is unstable\")]\nfn mergeable_info_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n                resolver = \"3\"\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n\n                [dependencies.dep]\n                path = \"../dep\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"extern crate dep; pub fn foo() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"dep/Cargo.toml\", &basic_manifest(\"dep\", \"0.0.0\"))\n        .file(\"dep/src/lib.rs\", \"pub fn dep() {}\")\n        .build();\n\n    p.cargo(\"doc -v --workspace -Zrustdoc-mergeable-info\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] dep v0.0.0 ([ROOT]/foo/dep)\n[CHECKING] dep v0.0.0 ([ROOT]/foo/dep)\n[DOCUMENTING] bar v0.0.0 ([ROOT]/foo/bar)\n[RUNNING] `rustdoc [..]--crate-name dep [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/dep-[HASH]/out [..]`\n[RUNNING] `rustdoc [..]--crate-name bar [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/bar-[HASH]/out [..]`\n[RUNNING] `rustc --crate-name dep [..]`\n[DOCUMENTING] foo v0.0.0 ([ROOT]/foo/foo)\n[RUNNING] `rustdoc [..]--crate-name foo [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 3 docs for host\n[RUNNING] `rustdoc -o [ROOT]/foo/target/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/debug/build/bar-[HASH]/out --include-parts-dir=[ROOT]/foo/target/debug/build/dep-[HASH]/out --include-parts-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bar/index.html\n[GENERATED] [ROOT]/foo/target/doc/dep/index.html\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]].unordered()\n        )\n        .run();\n\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/bar/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/dep/index.html\").is_file());\n    assert_eq!(p.glob(\"target/debug/build/foo-*/out/foo.json\").count(), 1);\n    assert_eq!(p.glob(\"target/debug/build/bar-*/out/bar.json\").count(), 1);\n    assert_eq!(p.glob(\"target/debug/build/dep-*/out/dep.json\").count(), 1);\n\n    assert_e2e().eq(\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap(),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/bar-[HASH]/out/bar.json\",\n    \"debug/build/dep-[HASH]/out/dep.json\",\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test(nightly, reason = \"rustdoc mergeable crate info is unstable\")]\nfn mergeable_info_multi_targets() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let target = cross_compile::alternate();\n    let host = rustc_host();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"doc -v --target host-tuple -Zrustdoc-mergeable-info\")\n        .args(&[\"--target\", target])\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs --target [HOST_TARGET] [..]--merge=none --parts-out-dir=[ROOT]/foo/target/[HOST_TARGET]/debug/build/foo-[HASH]/out [..]`\n[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs --target [ALT_TARGET] [..]--merge=none --parts-out-dir=[ROOT]/foo/target/[ALT_TARGET]/debug/build/foo-[HASH]/out [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 1 doc for [ALT_TARGET]\n[RUNNING] `rustdoc -o [ROOT]/foo/target/[ALT_TARGET]/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/[ALT_TARGET]/debug/build/foo-[HASH]/out`\n[MERGING] 1 doc for [HOST_TARGET]\n[RUNNING] `rustdoc -o [ROOT]/foo/target/[HOST_TARGET]/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/[HOST_TARGET]/debug/build/foo-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/[HOST_TARGET]/doc/foo/index.html\n[GENERATED] [ROOT]/foo/target/[ALT_TARGET]/doc/foo/index.html\n[GENERATED] [ROOT]/foo/target/[HOST_TARGET]/doc/foo/index.html\n[GENERATED] [ROOT]/foo/target/[ALT_TARGET]/doc/foo/index.html\n\n\"#]].unordered(),\n        )\n        .run();\n\n    let path = format!(\"target/{host}/doc/foo/index.html\");\n    assert!(p.root().join(path).is_file());\n    let path = format!(\"target/{target}/doc/foo/index.html\");\n    assert!(p.root().join(path).is_file());\n    let path = format!(\"target/{host}/debug/build/foo-*/out/foo.json\");\n    assert_eq!(p.glob(path).count(), 1);\n    let path = format!(\"target/{target}/debug/build/foo-*/out/foo.json\");\n    assert_eq!(p.glob(path).count(), 1);\n\n    assert_e2e().eq(\n        p.read_file(format!(\"target/{host}/.rustdoc_fingerprint.json\")),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n\n    assert_e2e().eq(\n        p.read_file(format!(\"target/{target}/.rustdoc_fingerprint.json\")),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test(nightly, reason = \"rustdoc mergeable crate info is unstable\")]\nfn mergeable_info_rebuild_detection() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]--crate-name foo [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 1 doc for host\n[RUNNING] `rustdoc -o [ROOT]/foo/target/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n        )\n        .run();\n\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert_eq!(p.glob(\"target/debug/build/foo-*/out/foo.json\").count(), 1);\n\n    assert_e2e().eq(\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap(),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n\n    // Make sure it doesn't recompile.\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[FRESH] doc-merge for host\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    // Still there\n    assert_e2e().eq(\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap(),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n\n    // Changing source code trigger re-merge\n    p.change_file(\"src/lib.rs\", \"pub fn foo2() {}\");\n\n    // Make sure it recompiles\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(\n            str![[r#\"\n[DIRTY] foo v0.0.0 ([ROOT]/foo): the precalculated components changed\n[DOCUMENTING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]--crate-name foo [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 1 doc for host\n[RUNNING] `rustdoc -o [ROOT]/foo/target/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n        )\n        .run();\n\n    // Make sure it doesn't recompile.\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[FRESH] doc-merge for host\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    // Make sure it doesn't recompile after previous no-op build.\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[FRESH] doc-merge for host\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    // Stay the same\n    assert_e2e().eq(\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap(),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"rustdoc mergeable crate info is unstable; `rustdoc --emit` is unstable\"\n)]\nfn mergeable_info_rebuild_with_depinfo() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info -Zrustdoc-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\", \"-Zrustdoc-depinfo\"])\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]--crate-name foo [..]--emit=html-non-static-files,dep-info=[..] --merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 1 doc for host\n[RUNNING] `rustdoc -o [ROOT]/foo/target/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n        )\n        .run();\n\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert_eq!(p.glob(\"target/debug/build/foo-*/out/foo.json\").count(), 1);\n\n    assert_e2e().eq(\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap(),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n\n    // Make sure it doesn't recompile.\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info -Zrustdoc-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\", \"-Zrustdoc-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[FRESH] doc-merge for host\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    // Still there\n    assert_e2e().eq(\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap(),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n\n    // Changing source code trigger re-merge\n    p.change_file(\"src/lib.rs\", \"pub fn foo2() {}\");\n\n    // Make sure it recompiles\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info -Zrustdoc-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\", \"-Zrustdoc-depinfo\"])\n        .with_stderr_data(\n            str![[r#\"\n[DIRTY] foo v0.0.0 ([ROOT]/foo): the file `src/lib.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[DOCUMENTING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]--crate-name foo [..]--emit=html-non-static-files,dep-info=[..] --merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 1 doc for host\n[RUNNING] `rustdoc -o [ROOT]/foo/target/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n        )\n        .run();\n\n    // Make sure it doesn't recompile.\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info -Zrustdoc-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\", \"-Zrustdoc-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[FRESH] doc-merge for host\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    // Make sure it doesn't recompile after previous no-op build\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info -Zrustdoc-depinfo\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\", \"-Zrustdoc-depinfo\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[FRESH] doc-merge for host\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    // Still there\n    assert_e2e().eq(\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap(),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test(nightly, reason = \"rustdoc mergeable crate info is unstable\")]\nfn mergeable_info_additive() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n                resolver = \"3\"\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n\n                [dependencies.dep]\n                path = \"../dep\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"extern crate dep; pub fn foo() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"dep/Cargo.toml\", &basic_manifest(\"dep\", \"0.0.0\"))\n        .file(\"dep/src/lib.rs\", \"pub fn dep() {}\")\n        .build();\n\n    p.cargo(\"doc -v -p foo --no-deps -Zrustdoc-mergeable-info\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] dep v0.0.0 ([ROOT]/foo/dep)\n[RUNNING] `rustc --crate-name dep [..]`\n[DOCUMENTING] foo v0.0.0 ([ROOT]/foo/foo)\n[RUNNING] `rustdoc [..]--crate-name foo [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 1 doc for host\n[RUNNING] `rustdoc -o [ROOT]/foo/target/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n        )\n        .run();\n\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(!p.root().join(\"target/doc/bar/index.html\").is_file());\n    assert!(!p.root().join(\"target/doc/dep/index.html\").is_file());\n    assert_eq!(p.glob(\"target/debug/build/foo-*/out/foo.json\").count(), 1);\n    assert_eq!(p.glob(\"target/debug/build/bar-*/out/bar.json\").count(), 0);\n    assert_eq!(p.glob(\"target/debug/build/dep-*/out/dep.json\").count(), 0);\n\n    assert_e2e().eq(\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap(),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n\n    p.cargo(\"doc -v -p dep --no-deps -Zrustdoc-mergeable-info\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] dep v0.0.0 ([ROOT]/foo/dep)\n[RUNNING] `rustdoc [..]--crate-name dep [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/dep-[HASH]/out [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 2 docs for host\n[RUNNING] `rustdoc -o [ROOT]/foo/target/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/debug/build/dep-[HASH]/out --include-parts-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/dep/index.html\n\n\"#]]\n        )\n        .run();\n\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(!p.root().join(\"target/doc/bar/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/dep/index.html\").is_file());\n    assert_eq!(p.glob(\"target/debug/build/foo-*/out/foo.json\").count(), 1);\n    assert_eq!(p.glob(\"target/debug/build/bar-*/out/bar.json\").count(), 0);\n    assert_eq!(p.glob(\"target/debug/build/dep-*/out/dep.json\").count(), 1);\n\n    assert_e2e().eq(\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap(),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/dep-[HASH]/out/dep.json\",\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n\n    p.cargo(\"doc -v -p bar --no-deps -Zrustdoc-mergeable-info\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] bar v0.0.0 ([ROOT]/foo/bar)\n[RUNNING] `rustdoc [..]--crate-name bar [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/bar-[HASH]/out [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 3 docs for host\n[RUNNING] `rustdoc -o [ROOT]/foo/target/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/debug/build/bar-[HASH]/out --include-parts-dir=[ROOT]/foo/target/debug/build/dep-[HASH]/out --include-parts-dir=[ROOT]/foo/target/debug/build/foo-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bar/index.html\n\n\"#]]\n        )\n        .run();\n\n    assert!(p.root().join(\"target/doc/foo/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/bar/index.html\").is_file());\n    assert!(p.root().join(\"target/doc/dep/index.html\").is_file());\n    assert_eq!(p.glob(\"target/debug/build/foo-*/out/foo.json\").count(), 1);\n    assert_eq!(p.glob(\"target/debug/build/bar-*/out/bar.json\").count(), 1);\n    assert_eq!(p.glob(\"target/debug/build/dep-*/out/dep.json\").count(), 1);\n\n    assert_e2e().eq(\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap(),\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/bar-[HASH]/out/bar.json\",\n    \"debug/build/dep-[HASH]/out/dep.json\",\n    \"debug/build/foo-[HASH]/out/foo.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test(nightly, reason = \"rustdoc mergeable crate info is unstable\")]\nfn mergeable_info_dep_collision() {\n    Package::new(\"dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn dep010() {}\")\n        .publish();\n\n    Package::new(\"dep\", \"0.2.0\")\n        .file(\"src/lib.rs\", \"pub fn dep020() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2021\"\n\n                [dependencies.dep1]\n                version = \"0.1.0\"\n                package = \"dep\"\n\n                [dependencies.dep2]\n                version = \"0.2.0\"\n                package = \"dep\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    // First document dep@0.1.0\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info -p dep@0.1.0\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[ADDING] dep v0.1.0 (available: v0.2.0)\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v0.2.0 (registry `dummy-registry`)\n[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`)\n[DOCUMENTING] dep v0.1.0\n[RUNNING] `rustdoc [..]--crate-name dep [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/dep-[HASH]/out [..]--crate-version 0.1.0`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 1 doc for host\n[RUNNING] `rustdoc -o [ROOT]/foo/target/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/debug/build/dep-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/dep/index.html\n\n\"#]]\n        )\n        .run();\n\n    assert!(p.root().join(\"target/doc/dep/index.html\").is_file());\n    assert_eq!(p.glob(\"target/debug/build/dep-*/out/dep.json\").count(), 1);\n\n    // See `fn dep010()`\n    assert!(p.build_dir().join(\"doc/dep/fn.dep010.html\").exists());\n    assert!(!p.build_dir().join(\"doc/dep/fn.dep020.html\").exists());\n\n    let first_fingerprint =\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap();\n    assert_e2e().eq(\n        &first_fingerprint,\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/dep-[HASH]/out/dep.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n\n    // Now selectively document dep@0.2.0\n    p.cargo(\"doc -v -Zrustdoc-mergeable-info -p dep@0.2.0\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-mergeable-info\"])\n        .with_stderr_data(\n            str![[r#\"\n[DOCUMENTING] dep v0.2.0\n[RUNNING] `rustdoc [..]--crate-name dep [..]--merge=none --parts-out-dir=[ROOT]/foo/target/debug/build/dep-[HASH]/out [..]--crate-version 0.2.0`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[MERGING] 1 doc for host\n[RUNNING] `rustdoc -o [ROOT]/foo/target/doc -Zunstable-options --merge=finalize --include-parts-dir=[ROOT]/foo/target/debug/build/dep-[HASH]/out`\n[FINISHED] documentation merge in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/dep/index.html\n\n\"#]]\n        )\n        .run();\n\n    assert!(p.root().join(\"target/doc/dep/index.html\").is_file());\n    // We'll have two dep.json\n    assert_eq!(p.glob(\"target/debug/build/dep-*/out/dep.json\").count(), 2);\n\n    // ...but only the selected dep@0.2.0 would be merged\n    assert!(!p.build_dir().join(\"doc/dep/fn.dep010.html\").exists());\n    assert!(p.build_dir().join(\"doc/dep/fn.dep020.html\").exists());\n\n    let second_fingerprint =\n        fs::read_to_string(p.build_dir().join(\".rustdoc_fingerprint.json\")).unwrap();\n    assert_e2e().eq(\n        &second_fingerprint,\n        str![[r#\"\n{\n  \"doc_parts\": [\n    \"debug/build/dep-[HASH]/out/dep.json\"\n  ],\n  \"rustc_vv\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n    // ...and the fingerprint content are different (path to dep.json different)\n    assert_ne!(first_fingerprint, second_fingerprint);\n}\n"
  },
  {
    "path": "tests/testsuite/docscrape.rs",
    "content": "//! Tests for the `cargo doc` command with `-Zrustdoc-scrape-examples`.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn basic() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"examples/ex.rs\", \"fn main() { foo::foo(); }\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\\npub fn bar() { foo(); }\")\n        .build();\n\n    p.cargo(\"doc -Zunstable-options -Zrustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[SCRAPING] foo v0.0.1 ([ROOT]/foo)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    p.cargo(\"doc -Zunstable-options -Z rustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/fn.foo.html\");\n    assert!(doc_html.contains(\"Examples found in repository\"));\n    assert!(!doc_html.contains(\"More examples\"));\n\n    // Ensure that the reverse-dependency has its sources generated\n    assert!(p.build_dir().join(\"doc/src/ex/ex.rs.html\").exists());\n}\n\n// This test ensures that even if there is no `[workspace]` in the top-level `Cargo.toml` file, the\n// dependencies will get their examples scraped and that they appear in the generated documentation.\n#[cargo_test(nightly, reason = \"-Zrustdoc-scrape-examples is unstable\")]\nfn scrape_examples_for_non_workspace_reexports() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"crates/a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub use a::*;\")\n        // Example\n        .file(\n            \"examples/one.rs\",\n            r#\"use foo::*;\nfn main() {\n    let foo = Foo::new(\"yes\".into());\n    foo.maybe();\n}\"#,\n        )\n        // `a` crate\n        .file(\n            \"crates/a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n        \"#,\n        )\n        .file(\n            \"crates/a/src/lib.rs\",\n            r#\"\n#[derive(Debug)]\npub struct Foo {\n    foo: String,\n    yes: bool,\n}\n\nimpl Foo {\n    pub fn new(foo: String) -> Self {\n        Self { foo, yes: true }\n    }\n\n    pub fn maybe(&self) {\n        if self.yes {\n            println!(\"{}\", self.foo)\n        }\n    }\n}\"#,\n        )\n        .build();\n\n    p.cargo(\"doc -Zunstable-options -Zrustdoc-scrape-examples --no-deps\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] a v0.0.1 ([ROOT]/foo/crates/a)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[SCRAPING] foo v0.0.1 ([ROOT]/foo)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/struct.Foo.html\");\n    assert!(doc_html.contains(\"Examples found in repository\"));\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn avoid_build_script_cycle() {\n    let p = project()\n        // package with build dependency\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                links = \"foo\"\n\n                [workspace]\n                members = [\"bar\"]\n\n                [build-dependencies]\n                bar = {path = \"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main(){}\")\n        // dependency\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                links = \"bar\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"bar/build.rs\", \"fn main(){}\")\n        .build();\n\n    p.cargo(\"doc --workspace -Zunstable-options -Zrustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn complex_reverse_dependencies() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dev-dependencies]\n                a = {path = \"a\", features = [\"feature\"]}\n                b = {path = \"b\"}\n\n                [workspace]\n                members = [\"b\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"fn main() {}\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                b = {path = \"../b\"}\n\n                [features]\n                feature = []\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc --workspace --examples -Zunstable-options -Zrustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn crate_with_dash() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"da-sh\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\"examples/a.rs\", \"fn main() { da_sh::foo(); }\")\n        .build();\n\n    p.cargo(\"doc -Zunstable-options -Zrustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/da_sh/fn.foo.html\");\n    assert!(doc_html.contains(\"Examples found in repository\"));\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn configure_target() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                doc-scrape-examples = true\n\n                [[bin]]\n                name = \"a_bin\"\n                doc-scrape-examples = true\n\n                [[example]]\n                name = \"a\"\n                doc-scrape-examples = false\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"pub fn foo() {} fn lib_must_appear() { foo(); }\",\n        )\n        .file(\n            \"examples/a.rs\",\n            \"fn example_must_not_appear() { foo::foo(); }\",\n        )\n        .file(\n            \"src/bin/a_bin.rs\",\n            \"fn bin_must_appear() { foo::foo(); } fn main(){}\",\n        )\n        .build();\n\n    p.cargo(\"doc -Zunstable-options -Zrustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/fn.foo.html\");\n    assert!(doc_html.contains(\"lib_must_appear\"));\n    assert!(doc_html.contains(\"bin_must_appear\"));\n    assert!(!doc_html.contains(\"example_must_not_appear\"));\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn configure_profile_issue_10500() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.dev]\n                panic = \"abort\"\n            \"#,\n        )\n        .file(\"examples/ex.rs\", \"fn main() { foo::foo(); }\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\\npub fn bar() { foo(); }\")\n        .build();\n\n    p.cargo(\"doc -Zunstable-options -Zrustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/fn.foo.html\");\n    assert!(doc_html.contains(\"Examples found in repository\"));\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn issue_10545() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                resolver = \"2\"\n                members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.0.1\"\n            authors = []\n            edition = \"2021\"\n\n            [features]\n            default = [\"foo\"]\n            foo = []\n        \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2021\"\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc --workspace -Zunstable-options -Zrustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn cache() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"examples/ex.rs\", \"fn main() { foo::foo(); }\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\\npub fn bar() { foo(); }\")\n        .build();\n\n    p.cargo(\"doc -Zunstable-options -Zrustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[SCRAPING] foo v0.0.1 ([ROOT]/foo)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    p.cargo(\"doc -Zunstable-options -Zrustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn no_fail_bad_lib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() { CRASH_THE_BUILD() }\")\n        .file(\"examples/ex.rs\", \"fn main() { foo::foo(); }\")\n        .file(\"examples/ex2.rs\", \"fn main() { foo::foo(); }\")\n        .build();\n\n    p.cargo(\"doc -Zunstable-options -Z rustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[SCRAPING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] failed to check lib in package `foo` as a prerequisite for scraping examples from: example \"ex\", example \"ex2\"\n    Try running with `--verbose` to see the error message.\n    If an example should not be scanned, then consider adding `doc-scrape-examples = false` to its `[[example]]` definition in Cargo.toml\n[WARNING] `foo` (lib) generated 1 warning\n[WARNING] failed to scan example \"ex\" in package `foo` for example code usage\n    Try running with `--verbose` to see the error message.\n    If an example should not be scanned, then consider adding `doc-scrape-examples = false` to its `[[example]]` definition in Cargo.toml\n[WARNING] `foo` (example \"ex\") generated 1 warning\n[WARNING] failed to scan example \"ex2\" in package `foo` for example code usage\n    Try running with `--verbose` to see the error message.\n    If an example should not be scanned, then consider adding `doc-scrape-examples = false` to its `[[example]]` definition in Cargo.toml\n[WARNING] `foo` (example \"ex2\") generated 1 warning\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn fail_bad_build_script() {\n    // See rust-lang/cargo#11623\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() { panic!(\\\"You shall not pass\\\")}\")\n        .file(\"examples/ex.rs\", \"fn main() {}\")\n        .build();\n\n    // `cargo doc` fails\n    p.cargo(\"doc\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[..]You shall not pass[..]\n...\n\"#]])\n        .run();\n\n    // scrape examples should fail whenever `cargo doc` fails.\n    p.cargo(\"doc -Zunstable-options -Z rustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[..]You shall not pass[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn no_fail_bad_example() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"examples/ex1.rs\", \"DOES NOT COMPILE\")\n        .file(\"examples/ex2.rs\", \"fn main() { foo::foo(); }\")\n        .file(\"src/lib.rs\", \"pub fn foo(){}\")\n        .build();\n\n    p.cargo(\"doc -Zunstable-options -Z rustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[SCRAPING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] failed to scan example \"ex1\" in package `foo` for example code usage\n    Try running with `--verbose` to see the error message.\n    If an example should not be scanned, then consider adding `doc-scrape-examples = false` to its `[[example]]` definition in Cargo.toml\n[WARNING] `foo` (example \"ex1\") generated 1 warning\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    p.cargo(\"clean\").run();\n\n    p.cargo(\"doc -v -Zunstable-options -Z rustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo[..]\n[SCRAPING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc[..] --crate-name ex1[..]\n[RUNNING] `rustdoc[..] --crate-name ex2[..]\n[RUNNING] `rustdoc[..] --crate-name foo[..]\n[ERROR] expected one of `!` or `::`, found `NOT`\n --> examples/ex1.rs:1:6\n  |\n1 | DOES NOT COMPILE\n  |      ^^^ expected one of `!` or `::`\n\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/fn.foo.html\");\n    assert!(doc_html.contains(\"Examples found in repository\"));\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn no_scrape_with_dev_deps() {\n    // Tests that a crate with dev-dependencies does not have its examples\n    // scraped unless explicitly prompted to check them. See\n    // `UnitGenerator::create_docscrape_proposals` for details on why.\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [dev-dependencies]\n            a = {path = \"a\"}\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"fn main() { a::f(); }\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n        \"#,\n        )\n        .file(\"a/src/lib.rs\", \"pub fn f() {}\")\n        .build();\n\n    // If --examples is not provided, then the example is not scanned, and a warning\n    // should be raised.\n    p.cargo(\"doc -Zunstable-options -Z rustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[WARNING] Rustdoc did not scrape the following examples because they require dev-dependencies: ex\n    If you want Rustdoc to scrape these examples, then add `doc-scrape-examples = true`\n    to the [[example]] target configuration of at least one example.\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    // If --examples is provided, then the example is scanned.\n    p.cargo(\"doc --examples -Zunstable-options -Z rustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] a v0.0.1 ([ROOT]/foo/a)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[DOCUMENTING] a v0.0.1 ([ROOT]/foo/a)\n[SCRAPING] foo v0.0.1 ([ROOT]/foo)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/ex/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn use_dev_deps_if_explicitly_enabled() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [[example]]\n            name = \"ex\"\n            doc-scrape-examples = true\n\n            [dev-dependencies]\n            a = {path = \"a\"}\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"fn main() { a::f(); }\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n        \"#,\n        )\n        .file(\"a/src/lib.rs\", \"pub fn f() {}\")\n        .build();\n\n    // If --examples is not provided, then the example is never scanned.\n    p.cargo(\"doc -Zunstable-options -Z rustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] a v0.0.1 ([ROOT]/foo/a)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[SCRAPING] foo v0.0.1 ([ROOT]/foo)\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn only_scrape_documented_targets() {\n    // package bar has doc = false and should not be eligible for documentation.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []            \n\n            [lib]\n            doc = false\n\n            [workspace]\n            members = [\"foo\"]\n\n            [dependencies]\n            foo = {{ path = \"foo\" }}\n        \"#\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"pub fn main() { foo::foo(); }\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []      \n        \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"doc --workspace -Zunstable-options -Zrustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .run();\n\n    let doc_html = p.read_file(\"target/doc/foo/fn.foo.html\");\n    let example_found = doc_html.contains(\"Examples found in repository\");\n    assert!(!example_found);\n}\n\n#[cargo_test(nightly, reason = \"rustdoc scrape examples flags are unstable\")]\nfn issue_11496() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"repro\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n                \n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"fn main(){}\")\n        .build();\n\n    p.cargo(\"doc -Zunstable-options -Zrustdoc-scrape-examples\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-scrape-examples\"])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/edition.rs",
    "content": "//! Tests for edition setting.\n\nuse crate::prelude::*;\nuse cargo::core::Edition;\nuse cargo_test_support::{basic_lib_manifest, project, str};\n\n#[cargo_test]\nfn edition_works_for_build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                edition = '2018'\n\n                [build-dependencies]\n                a = { path = 'a' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    a::foo();\n                }\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_lib_manifest(\"a\"))\n        .file(\"a/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn edition_unstable_gated() {\n    // During the period where a new edition is coming up, but not yet stable,\n    // this test will verify that it cannot be used on stable. If there is no\n    // next edition, it does nothing.\n    let next = match Edition::LATEST_UNSTABLE {\n        Some(next) => next,\n        None => {\n            eprintln!(\"Next edition is currently not available, skipping test.\");\n            return;\n        }\n    };\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"{}\"\n            \"#,\n                next\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(format!(\n            \"\\\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `edition{next}` is required\n\n  The package requires the Cargo feature called `edition{next}`, but that feature is not stabilized in this version of Cargo (1.[..]).\n  Consider trying a newer version of Cargo (this may require the nightly release).\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#edition-{next} for more information about the status of this feature.\n\"))\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"fundamentally always nightly\")]\nfn edition_unstable() {\n    // During the period where a new edition is coming up, but not yet stable,\n    // this test will verify that it can be used with `cargo-features`. If\n    // there is no next edition, it does nothing.\n    let next = match Edition::LATEST_UNSTABLE {\n        Some(next) => next,\n        None => {\n            eprintln!(\"Next edition is currently not available, skipping test.\");\n            return;\n        }\n    };\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                cargo-features = [\"edition{next}\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"{next}\"\n            \"#,\n                next = next\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"always_nightly\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unset_edition_with_unset_rust_version() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to `2015` while the latest is `[..]`\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] --edition=2015 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unset_edition_works_with_no_newer_compatible_edition() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                rust-version = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] --edition=2015 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unset_edition_works_on_old_msrv() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                rust-version = \"1.50\"  # contains 2018 edition\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to `2015` while 2018 is compatible with `rust-version`\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] --edition=2015 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn future_edition_is_gated() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"future\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `unstable-editions` is required\n\n  The package requires the Cargo feature called `unstable-editions`, but that feature is not stabilized in this version of Cargo ([..]).\n  Consider trying a newer version of Cargo (this may require the nightly release).\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#unstable-editions for more information about the status of this feature.\n\n\"#]])\n        .run();\n\n    // Repeat on nightly.\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"unstable-editions\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `unstable-editions` is required\n\n  The package requires the Cargo feature called `unstable-editions`, but that feature is not stabilized in this version of Cargo ([..]).\n  Consider adding `cargo-features = [\"unstable-editions\"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#unstable-editions for more information about the status of this feature.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn future_edition_with_rust_version_hint() {\n    // When an unstable edition is used and the package has `rust-version` set,\n    // the error message should include a `help:` line pointing the user at the\n    // required Rust toolchain version, matching the format used elsewhere in\n    // Cargo (e.g. `{name}@{version} requires rust {msrv}`).\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"future\"\n                rust-version = \"1.90\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `unstable-editions` is required\n\n  The package requires the Cargo feature called `unstable-editions`, but that feature is not stabilized in this version of Cargo ([..]).\n  Consider trying a newer version of Cargo (this may require the nightly release).\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#unstable-editions for more information about the status of this feature.\n  [HELP] foo@0.1.0 requires rust 1.90\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"future edition is always unstable\")]\nfn future_edition_works() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"unstable-editions\"]\n\n                [package]\n                name = \"foo\"\n                edition = \"future\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"unstable-editions\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/error.rs",
    "content": "//! General error tests that don't belong anywhere else.\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\n\n#[cargo_test]\nfn internal_error() {\n    cargo_process(\"init\")\n        .env(\"__CARGO_TEST_INTERNAL_ERROR\", \"1\")\n        .with_status(101)\n        .with_stderr_data(format!(\n            \"\\\n[ERROR] internal error test\n[NOTE] this is an unexpected cargo internal error\n[NOTE] we would appreciate a bug report: https://github.com/rust-lang/cargo/issues/\n[NOTE] cargo {}\n\",\n            cargo::version()\n        ))\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/feature_unification.rs",
    "content": "//! Tests for workspace feature unification.\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::{\n    basic_manifest,\n    compare::assert_e2e,\n    project,\n    registry::{Dependency, Package},\n    str,\n};\n\n#[cargo_test]\nfn workspace_feature_unification() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [resolver]\n                feature-unification = \"workspace\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                resolver = \"2\"\n                members = [\"common\", \"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"common/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"common\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [features]\n                a = []\n                b = []\n            \"#,\n        )\n        .file(\n            \"common/src/lib.rs\",\n            r#\"\n                #[cfg(not(all(feature = \"a\", feature = \"b\")))]\n                compile_error!(\"features were not unified\");\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\", features = [\"a\"] }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\", features = [\"b\"] }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -p common\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] common v0.1.0 ([ROOT]/foo/common)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check -p a\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check -p b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] b v0.1.0 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn package_feature_unification() {\n    Package::new(\"outside\", \"0.1.0\")\n        .feature(\"a\", &[])\n        .feature(\"b\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(all(feature = \"a\", feature = \"b\"))]\n                compile_error!(\"features were unified\");\n                #[cfg(feature = \"a\")]\n                pub fn a() {}\n                #[cfg(feature = \"b\")]\n                pub fn b() {}\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [resolver]\n                feature-unification = \"package\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                resolver = \"2\"\n                members = [\"common\", \"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"common/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"common\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [features]\n                a = []\n                b = []\n            \"#,\n        )\n        .file(\n            \"common/src/lib.rs\",\n            r#\"\n                #[cfg(all(feature = \"a\", feature = \"b\"))]\n                compile_error!(\"features were unified\");\n                #[cfg(feature = \"a\")]\n                pub fn a() {}\n                #[cfg(feature = \"b\")]\n                pub fn b() {}\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\", features = [\"a\"] }\n                outside = { version = \"0.1.0\", features = [\"a\"] }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"pub use common::a;\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\", features = [\"b\"] }\n                outside = { version = \"0.1.0\", features = [\"b\"] }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"pub use common::b;\")\n        .build();\n\n    p.cargo(\"check -p common\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] common v0.1.0 ([ROOT]/foo/common)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check -p a\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(\n            str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] outside v0.1.0 (registry `dummy-registry`)\n[CHECKING] outside v0.1.0\n[CHECKING] common v0.1.0 ([ROOT]/foo/common)\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    p.cargo(\"check -p b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] outside v0.1.0\n[CHECKING] common v0.1.0 ([ROOT]/foo/common)\n[CHECKING] b v0.1.0 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    p.cargo(\"check -p a -p b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(\n            str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    p.cargo(\"check\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // Sanity check that compilation without package feature unification does not work\n    p.cargo(\"check -p a -p b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"selected\")\n        .with_status(101)\n        .with_stderr_contains(\"[ERROR] features were unified\")\n        .run();\n}\n\n#[cargo_test]\nfn package_feature_unification_default_features() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [resolver]\n                feature-unification = \"package\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                resolver = \"2\"\n                members = [\"common\", \"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"common/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"common\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [features]\n                default = [\"a\"]\n                a = []\n                b = []\n            \"#,\n        )\n        .file(\n            \"common/src/lib.rs\",\n            r#\"\n                #[cfg(all(feature = \"a\", feature = \"b\"))]\n                compile_error!(\"features were unified\");\n                #[cfg(feature = \"a\")]\n                pub fn a() {}\n                #[cfg(feature = \"b\")]\n                pub fn b() {}\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\" }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"pub use common::a;\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\", features = [\"b\"], default-features = false }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"pub use common::b;\")\n        .build();\n\n    p.cargo(\"check -p common\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] common v0.1.0 ([ROOT]/foo/common)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check -p a\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check -p b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] common v0.1.0 ([ROOT]/foo/common)\n[CHECKING] b v0.1.0 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(\n            str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn package_feature_unification_cli_features() {\n    Package::new(\"outside\", \"0.1.0\")\n        .feature(\"a\", &[])\n        .feature(\"b\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(all(feature = \"a\", feature = \"b\"))]\n                compile_error!(\"features were unified\");\n                #[cfg(feature = \"a\")]\n                pub fn a() {}\n                #[cfg(feature = \"b\")]\n                pub fn b() {}\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [resolver]\n                feature-unification = \"package\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                resolver = \"2\"\n                members = [\"common\", \"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"common/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"common\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [features]\n                a = []\n                b = []\n            \"#,\n        )\n        .file(\n            \"common/src/lib.rs\",\n            r#\"\n                #[cfg(all(feature = \"a\", feature = \"b\"))]\n                compile_error!(\"features were unified\");\n                #[cfg(feature = \"a\")]\n                pub fn a() {}\n                #[cfg(feature = \"b\")]\n                pub fn b() {}\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\" }\n                outside = \"0.1.0\"\n\n                [features]\n                a = [\"common/a\", \"outside/a\"]\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"pub use common::a;\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\", features = [\"b\"] }\n                outside = \"0.1.0\"\n\n                [features]\n                b = [\"common/b\", \"outside/b\"]\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"pub use common::b;\")\n        .build();\n\n    p.cargo(\"check -p a -p b -F a,b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(\n            str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[CHECKING] common v0.1.0 ([ROOT]/foo/common)\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] outside v0.1.0 (registry `dummy-registry`)\n[CHECKING] outside v0.1.0\n[CHECKING] b v0.1.0 ([ROOT]/foo/b)\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    p.cargo(\"check --workspace --exclude common -F a,b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(\n            str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"check -p a -p b -F a/a,b/b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(\n            str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    p.cargo(\"check -p a -p b -F a,b,c\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] none of the selected packages contains this feature: c\nselected packages: a, b\n\n\"#]])\n        .run();\n    p.cargo(\"check -p a -F b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the package 'a' does not contain this feature: b\n[HELP] packages with the missing feature: common, b\n\n\"#]])\n        .run();\n    p.cargo(\"check -p a -F a/a,common/b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_status(101)\n        .with_stderr_contains(\"[ERROR] features were unified\")\n        .run();\n\n    p.cargo(\"check -p a -F a/a,outside/b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_status(101)\n        .with_stderr_contains(\"[ERROR] features were unified\")\n        .run();\n\n    // Sanity check that compilation without package feature unification does not work\n    p.cargo(\"check -p a -p b -F a,b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"selected\")\n        .with_status(101)\n        .with_stderr_contains(\"[ERROR] features were unified\")\n        .run();\n}\n\n#[cargo_test]\nfn package_feature_unification_weak_dependencies() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [resolver]\n                feature-unification = \"package\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                resolver = \"2\"\n                members = [\"common\", \"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"common/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"common\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [features]\n                a = []\n                b = []\n            \"#,\n        )\n        .file(\n            \"common/src/lib.rs\",\n            r#\"\n                #[cfg(all(feature = \"a\", feature = \"b\"))]\n                compile_error!(\"features were unified\");\n                #[cfg(feature = \"a\")]\n                pub fn a() {}\n                #[cfg(feature = \"b\")]\n                pub fn b() {}\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\", optional = true }\n\n                [features]\n                default = [\"dep:common\", \"common?/a\"]\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"pub use common::a;\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\", optional = true }\n\n                [features]\n                default = [\"dep:common\", \"common?/b\"]\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"pub use common::b;\")\n        .build();\n\n    p.cargo(\"check -p a -p b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] common v0.1.0 ([ROOT]/foo/common)\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[CHECKING] b v0.1.0 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    p.cargo(\"check\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] common v0.1.0 ([ROOT]/foo/common)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Sanity check that compilation without package feature unification does not work\n    p.cargo(\"check -p a -p b\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"selected\")\n        .with_status(101)\n        .with_stderr_contains(\"[ERROR] features were unified\")\n        .run();\n}\n\n#[cargo_test]\nfn feature_unification_cargo_tree() {\n    Package::new(\"outside\", \"0.1.0\")\n        .feature(\"a\", &[])\n        .feature(\"b\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(all(feature = \"a\", feature = \"b\"))]\n                compile_error!(\"features were unified\");\n                #[cfg(feature = \"a\")]\n                pub fn a() {}\n                #[cfg(feature = \"b\")]\n                pub fn b() {}\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                resolver = \"2\"\n                members = [\"common\", \"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"common/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"common\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [features]\n                a = []\n                b = []\n            \"#,\n        )\n        .file(\n            \"common/src/lib.rs\",\n            r#\"\n                #[cfg(all(feature = \"a\", feature = \"b\"))]\n                compile_error!(\"features were unified\");\n                #[cfg(feature = \"a\")]\n                pub fn a() {}\n                #[cfg(feature = \"b\")]\n                pub fn b() {}\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\", features = [\"a\"] }\n                outside = { version = \"0.1.0\", features = [\"a\"] }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"pub use common::a;\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\", features = [\"b\"] }\n                outside = { version = \"0.1.0\", features = [\"b\"] }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"pub use common::b;\")\n        .build();\n\n    p.cargo(\"tree -e features\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"selected\")\n        .with_stdout_data(str![[r#\"\na v0.1.0 ([ROOT]/foo/a)\n├── common feature \"a\"\n│   └── common v0.1.0 ([ROOT]/foo/common)\n├── common feature \"default\" (command-line)\n│   └── common v0.1.0 ([ROOT]/foo/common)\n├── outside feature \"a\"\n│   └── outside v0.1.0\n└── outside feature \"default\"\n    └── outside v0.1.0\n\nb v0.1.0 ([ROOT]/foo/b)\n├── common feature \"b\"\n│   └── common v0.1.0 ([ROOT]/foo/common)\n├── common feature \"default\" (command-line) (*)\n├── outside feature \"b\"\n│   └── outside v0.1.0\n└── outside feature \"default\" (*)\n\ncommon v0.1.0 ([ROOT]/foo/common)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"workspace\")\n        .with_stdout_data(str![[r#\"\na v0.1.0 ([ROOT]/foo/a)\n├── common feature \"a\"\n│   └── common v0.1.0 ([ROOT]/foo/common)\n├── common feature \"default\" (command-line)\n│   └── common v0.1.0 ([ROOT]/foo/common)\n├── outside feature \"a\"\n│   └── outside v0.1.0\n└── outside feature \"default\"\n    └── outside v0.1.0\n\nb v0.1.0 ([ROOT]/foo/b)\n├── common feature \"b\"\n│   └── common v0.1.0 ([ROOT]/foo/common)\n├── common feature \"default\" (command-line) (*)\n├── outside feature \"b\"\n│   └── outside v0.1.0\n└── outside feature \"default\" (*)\n\ncommon v0.1.0 ([ROOT]/foo/common)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"package\")\n        .with_stdout_data(str![[r#\"\ncommon v0.1.0 ([ROOT]/foo/common)\na v0.1.0 ([ROOT]/foo/a)\n├── common feature \"a\"\n│   └── common v0.1.0 ([ROOT]/foo/common)\n├── common feature \"default\"\n│   └── common v0.1.0 ([ROOT]/foo/common)\n├── outside feature \"a\"\n│   └── outside v0.1.0\n└── outside feature \"default\"\n    └── outside v0.1.0\nb v0.1.0 ([ROOT]/foo/b)\n├── common feature \"b\"\n│   └── common v0.1.0 ([ROOT]/foo/common)\n├── common feature \"default\"\n│   └── common v0.1.0 ([ROOT]/foo/common)\n├── outside feature \"b\"\n│   └── outside v0.1.0\n└── outside feature \"default\"\n    └── outside v0.1.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_install_ignores_config() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"common\", features = [\"a\"] }\n\n                [workspace]\n                members = [\"common\", \"b\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"common/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"common\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [features]\n                a = []\n                b = []\n            \"#,\n        )\n        .file(\n            \"common/src/lib.rs\",\n            r#\"\n                #[cfg(all(feature = \"a\", feature = \"b\"))]\n                compile_error!(\"features should not be unified\");\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                common = { path = \"../common\", features = [\"b\"] }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    cargo_process(\"install --path\")\n        .arg(p.root())\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"workspace\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] a v0.1.0 ([ROOT]/foo)\n[COMPILING] common v0.1.0 ([ROOT]/foo/common)\n[COMPILING] a v0.1.0 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/a[EXE]\n[INSTALLED] package `a v0.1.0 ([ROOT]/foo)` (executable `a[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    cargo_process(\"install --path\")\n        .arg(p.root())\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"package\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] a v0.1.0 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[REPLACING] [ROOT]/home/.cargo/bin/a[EXE]\n[REPLACED] package `a v0.1.0 ([ROOT]/foo)` with `a v0.1.0 ([ROOT]/foo)` (executable `a[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unstable_config_on_stable() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                resolver = \"2\"\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"workspace\")\n        .with_stderr_data(str![[r#\"\n[WARNING] ignoring `resolver.feature-unification` without `-Zfeature-unification`\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_fix_works() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n# Before project\n[ project ] # After project header\n# After project header line\nname = \"foo\"\nedition = \"2021\"\n# After project table\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"package\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2021 edition to 2024\n[FIXED] Cargo.toml (1 fix)\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2021 edition to 2024\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert_e2e().eq(\n        p.read_file(\"Cargo.toml\"),\n        str![[r#\"\n\n# Before project\n[ package ] # After project header\n# After project header line\nname = \"foo\"\nedition = \"2021\"\n# After project table\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn edition_v2_resolver_report() {\n    // Show a report if the V2 resolver shows differences.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"f1\", &[])\n        .feature(\"dev-feat\", &[])\n        .add_dep(Dependency::new(\"opt_dep\", \"1.0\").optional(true))\n        .publish();\n    Package::new(\"opt_dep\", \"1.0.0\").publish();\n\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(\n            Dependency::new(\"common\", \"1.0\")\n                .target(\"cfg(whatever)\")\n                .enable_features(&[\"f1\"]),\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                common = \"1.0\"\n                bar = \"1.0\"\n\n                [build-dependencies]\n                common = { version = \"1.0\", features = [\"opt_dep\"] }\n\n                [dev-dependencies]\n                common = { version=\"1.0\", features=[\"dev-feat\"] }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs --workspace\")\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"package\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n[MIGRATING] Cargo.toml from 2018 edition to 2021\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] common v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] opt_dep v1.0.0 (registry `dummy-registry`)\n[MIGRATING] bar/Cargo.toml from 2018 edition to 2021\n[ERROR] cannot fix edition when using `feature-unification = \"package\"`.\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn feature_unification_of_cli_features_within_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                resolver = \"2\"\n                members = [\"parent\", \"child\", \"grandchild\"]\n            \"#,\n        )\n        .file(\n            \"grandchild/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"grandchild\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [features]\n                a = []\n            \"#,\n        )\n        .file(\n            \"grandchild/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"a\")]\n                pub fn a() {}\n            \"#,\n        )\n        .file(\n            \"child/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"child\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                grandchild = { path = \"../grandchild\" }\n            \"#,\n        )\n        .file(\"child/src/lib.rs\", \"pub use grandchild::*;\")\n        .file(\n            \"parent/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"parent\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                child = { path = \"../child\" }\n            \"#,\n        )\n        .file(\"parent/src/lib.rs\", \"pub use child::a;\")\n        .build();\n\n    p.cargo(\"check -p parent -F grandchild/a\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the package 'parent' does not contain this feature: grandchild/a\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -p parent -F grandchild/a\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the package 'parent' does not contain this feature: grandchild/a\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -p parent -F grandchild/a\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"selected\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the package 'parent' does not contain this feature: grandchild/a\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -p child -F grandchild/a\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"package\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] grandchild v0.1.0 ([ROOT]/foo/grandchild)\n[CHECKING] child v0.1.0 ([ROOT]/foo/child)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -p child -F grandchild/a\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"workspace\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -p child -F grandchild/a\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"selected\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -F grandchild/a\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"package\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] parent v0.1.0 ([ROOT]/foo/parent)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -F grandchild/a\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"workspace\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -F grandchild/a\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"selected\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -F grandchild/a --workspace --exclude grandchild\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"package\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -F grandchild/a --workspace --exclude grandchild\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"workspace\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -F grandchild/a --workspace --exclude grandchild\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"selected\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -F grandchild/a --workspace --exclude grandchild --exclude child\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the package 'parent' does not contain this feature: grandchild/a\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -F grandchild/a --workspace --exclude grandchild --exclude child\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the package 'parent' does not contain this feature: grandchild/a\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -F grandchild/a --workspace --exclude grandchild --exclude child\")\n        .arg(\"-Zfeature-unification\")\n        .masquerade_as_nightly_cargo(&[\"feature-unification\"])\n        .env(\"CARGO_RESOLVER_FEATURE_UNIFICATION\", \"selected\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the package 'parent' does not contain this feature: grandchild/a\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/features.rs",
    "content": "//! Tests for `[features]` table.\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::{Dependency, Package};\nuse cargo_test_support::{basic_manifest, project};\nuse cargo_test_support::{rustc_host, str};\n\n#[cargo_test]\nfn feature_activates_missing_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                bar = [\"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `bar` includes `baz` which is neither a dependency nor another feature\n\n  [HELP] a feature with a similar name exists: `bar`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn feature_activates_typoed_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                bar = [\"baz\"]\n                jaz = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `bar` includes `baz` which is neither a dependency nor another feature\n\n  [HELP] a feature with a similar name exists: `bar`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn empty_feature_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                \"\" = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] feature name cannot be empty\n --> Cargo.toml:9:17\n  |\n9 |                 \"\" = []\n  |                 ^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn same_name() {\n    // Feature with the same name as a dependency.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                bar = [\"baz\"]\n                baz = []\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -f\")\n        .arg(\"{p} [{f}]\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo) []\n└── bar v1.0.0 ([ROOT]/foo/bar) []\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --features bar -f\")\n        .arg(\"{p} [{f}]\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo) [bar,baz]\n└── bar v1.0.0 ([ROOT]/foo/bar) []\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn feature_activates_required_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                bar = [\"baz\"]\n\n                [dependencies.baz]\n                path = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `bar` includes `baz`, but `baz` is not an optional dependency\n  A non-optional dependency of the same name is defined; consider adding `optional = true` to its definition.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dependency_activates_missing_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n                features = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to select a version for `bar`.\n    ... required by package `foo v0.0.1 ([ROOT]/foo)`\nversions that meet the requirements `*` are: 0.0.1\n\npackage `foo` depends on `bar` with feature `bar` but `bar` does not have that feature.\n\n\nfailed to select a version for `bar` which could resolve this conflict\n\n\"#]])\n        .run();\n\n    p.change_file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.1\"));\n\n    p.cargo(\"check --features test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package `foo v0.0.1 ([ROOT]/foo)` does not have the feature `test`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dependency_activates_typoed_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n                features = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                baz = []\n\"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to select a version for `bar`.\n    ... required by package `foo v0.0.1 ([ROOT]/foo)`\nversions that meet the requirements `*` are: 0.0.1\n\npackage `foo` depends on `bar` with feature `bar` but `bar` does not have that feature.\n package `bar` does have feature `baz`\n\n\nfailed to select a version for `bar` which could resolve this conflict\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dependency_activates_feature_with_no_close_match() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies.bar]\n                path = \"bar\"\n                features = [\"serde\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                json = []\n                tls = []\n                cookies = []\n\"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to select a version for `bar`.\n    ... required by package `foo v0.0.1 ([ROOT]/foo)`\nversions that meet the requirements `*` are: 0.0.1\n\npackage `foo` depends on `bar` with feature `serde` but `bar` does not have that feature.\n available features: cookies, json, tls\n\n\nfailed to select a version for `bar` which could resolve this conflict\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn optional_dev_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dev-dependencies.bar]\n                path = \"bar\"\n                optional = true\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  dev-dependencies are not allowed to be optional: `bar`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn feature_activates_missing_dep_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                foo = [\"bar/baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --features foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] feature `foo` includes `bar/baz`, but `bar` is not a dependency\n --> Cargo.toml:9:23\n  |\n9 |                 foo = [\"bar/baz\"]\n  |                       ^^^^^^^^^^^\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn feature_activates_feature_inside_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                foo = [\"bar/baz\"]\n                bar = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --features foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] feature `foo` includes `bar/baz`, but `bar` is not a dependency\n --> Cargo.toml:9:23\n  |\n9 |                 foo = [\"bar/baz\"]\n  |                       ^^^^^^^^^^^\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dependency_activates_dep_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n                features = [\"foo/bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --features foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `foo/bar` in dependency `bar` is not allowed to contain slashes\n  If you want to enable features [..]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cli_activates_required_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --features bar\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ERROR] package `foo v0.0.1 ([ROOT]/foo)` does not have feature `bar`\n\n[HELP] a dependency with that name exists but it is required dependency and only optional dependencies can be used as features.\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn dependency_activates_required_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n                features = [\"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.baz]\n                path = \"baz\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"bar/baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.0.1\"))\n        .file(\"bar/baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to select a version for `bar`.\n    ... required by package `foo v0.0.1 ([ROOT]/foo)`\nversions that meet the requirements `*` are: 0.0.1\n\npackage `foo` depends on `bar` with feature `baz` but `bar` does not have that feature.\n A required dependency with that name exists, but only optional dependencies can be used as features.\n\n\nfailed to select a version for `bar` which could resolve this conflict\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn no_transitive_dep_feature_requirement() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.derived]\n                path = \"derived\"\n\n                [features]\n                default = [\"derived/bar/qux\"]\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                extern crate derived;\n                fn main() { derived::test(); }\n            \"#,\n        )\n        .file(\n            \"derived/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"derived\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\"derived/src/lib.rs\", \"extern crate bar; pub use bar::test;\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                qux = []\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"qux\")]\n                pub fn test() { print!(\"test\"); }\n            \"#,\n        )\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  multiple slashes in feature `derived/bar/qux` (included by feature `default`) are not allowed\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_feature_doesnt_build() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n                optional = true\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[cfg(feature = \"bar\")]\n                extern crate bar;\n                #[cfg(feature = \"bar\")]\n                fn main() { bar::bar(); println!(\"bar\") }\n                #[cfg(not(feature = \"bar\"))]\n                fn main() {}\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.process(&p.bin(\"foo\")).with_stdout_data(\"\").run();\n\n    let expected = if cfg!(target_os = \"windows\") && cfg!(target_env = \"msvc\") {\n        str![[r#\"\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..]`\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the list of features changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n    } else {\n        str![[r#\"\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n    };\n    p.cargo(\"build --features bar -v\")\n        .with_stderr_data(expected)\n        .run();\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nbar\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn default_feature_pulled_in() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"bar\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n                optional = true\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[cfg(feature = \"bar\")]\n                extern crate bar;\n                #[cfg(feature = \"bar\")]\n                fn main() { bar::bar(); println!(\"bar\") }\n                #[cfg(not(feature = \"bar\"))]\n                fn main() {}\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nbar\n\n\"#]])\n        .run();\n\n    let expected = if cfg!(target_os = \"windows\") && cfg!(target_env = \"msvc\") {\n        str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the list of features changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n    } else {\n        str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n    };\n    p.cargo(\"build --no-default-features -v\")\n        .with_stderr_data(expected)\n        .run();\n    p.process(&p.bin(\"foo\")).with_stdout_data(\"\").run();\n}\n\n#[cargo_test]\nfn cyclic_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"default\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cyclic feature dependency: feature `default` depends on itself\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cyclic_feature2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                foo = [\"bar\"]\n                bar = [\"foo\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn groups_on_groups_on_groups() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"f1\"]\n                f1 = [\"f2\", \"bar\"]\n                f2 = [\"f3\", \"f4\"]\n                f3 = [\"f5\", \"f6\", \"baz\"]\n                f4 = [\"f5\", \"f7\"]\n                f5 = [\"f6\"]\n                f6 = [\"f7\"]\n                f7 = [\"bar\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n                optional = true\n\n                [dependencies.baz]\n                path = \"baz\"\n                optional = true\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[allow(unused_extern_crates)]\n                extern crate bar;\n                #[allow(unused_extern_crates)]\n                extern crate baz;\n                fn main() {}\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.0.1\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[CHECKING] baz v0.0.1 ([ROOT]/foo/baz)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn many_cli_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n                optional = true\n\n                [dependencies.baz]\n                path = \"baz\"\n                optional = true\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[allow(unused_extern_crates)]\n                extern crate bar;\n                #[allow(unused_extern_crates)]\n                extern crate baz;\n                fn main() {}\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.0.1\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check --features\")\n        .arg(\"bar baz\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[CHECKING] baz v0.0.1 ([ROOT]/foo/baz)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn union_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.d1]\n                path = \"d1\"\n                features = [\"f1\"]\n                [dependencies.d2]\n                path = \"d2\"\n                features = [\"f2\"]\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[allow(unused_extern_crates)]\n                extern crate d1;\n                extern crate d2;\n                fn main() {\n                    d2::f1();\n                    d2::f2();\n                }\n            \"#,\n        )\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                f1 = [\"d2\"]\n\n                [dependencies.d2]\n                path = \"../d2\"\n                features = [\"f1\"]\n                optional = true\n            \"#,\n        )\n        .file(\"d1/src/lib.rs\", \"\")\n        .file(\n            \"d2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                f1 = []\n                f2 = []\n            \"#,\n        )\n        .file(\n            \"d2/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"f1\")] pub fn f1() {}\n                #[cfg(feature = \"f2\")] pub fn f2() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] d2 v0.0.1 ([ROOT]/foo/d2)\n[CHECKING] d1 v0.0.1 ([ROOT]/foo/d1)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn many_features_no_rebuilds() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name    = \"b\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.a]\n                path = \"a\"\n                features = [\"fall\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name    = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                ftest  = []\n                ftest2 = []\n                fall   = [\"ftest\", \"ftest2\"]\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[CHECKING] b v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.root().move_into_the_past();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] a v0.1.0 ([ROOT]/foo/a)\n[FRESH] b v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n// Tests that all cmd lines work with `--features \"\"`\n#[cargo_test]\nfn empty_features() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"check --features\").arg(\"\").run();\n}\n\n// Tests that all cmd lines work with `--features \"\"`\n#[cargo_test]\nfn transitive_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                foo = [\"bar/baz\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() { bar::baz(); }\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                baz = []\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"#[cfg(feature = \"baz\")] pub fn baz() {}\"#,\n        )\n        .build();\n\n    p.cargo(\"check --features foo\").run();\n}\n\n#[cargo_test]\nfn everything_in_the_lockfile() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                f1 = [\"d1/f1\"]\n                f2 = [\"d2\"]\n\n                [dependencies.d1]\n                path = \"d1\"\n                [dependencies.d2]\n                path = \"d2\"\n                optional = true\n                [dependencies.d3]\n                path = \"d3\"\n                optional = true\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                f1 = []\n            \"#,\n        )\n        .file(\"d1/src/lib.rs\", \"\")\n        .file(\"d2/Cargo.toml\", &basic_manifest(\"d2\", \"0.0.2\"))\n        .file(\"d2/src/lib.rs\", \"\")\n        .file(\n            \"d3/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d3\"\n                version = \"0.0.3\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                f3 = []\n            \"#,\n        )\n        .file(\"d3/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch\").run();\n    let lockfile = p.read_lockfile();\n    assert!(\n        lockfile.contains(r#\"name = \"d1\"\"#),\n        \"d1 not found\\n{}\",\n        lockfile\n    );\n    assert!(\n        lockfile.contains(r#\"name = \"d2\"\"#),\n        \"d2 not found\\n{}\",\n        lockfile\n    );\n    assert!(\n        lockfile.contains(r#\"name = \"d3\"\"#),\n        \"d3 not found\\n{}\",\n        lockfile\n    );\n}\n\n#[cargo_test]\nfn no_rebuild_when_frobbing_default_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"../a\", features = [\"f1\"], default-features = false }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"f1\"]\n                f1 = []\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unions_work_with_no_default_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate a; pub fn foo() { a::a(); }\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"../a\", features = [], default-features = false }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"f1\"]\n                f1 = []\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", r#\"#[cfg(feature = \"f1\")] pub fn a() {}\"#)\n        .build();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn optional_and_dev_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name    = \"test\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = { path = \"foo\", optional = true }\n                [dev-dependencies]\n                foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] test v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn activating_feature_activates_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name    = \"test\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = { path = \"foo\", optional = true }\n\n                [features]\n                a = [\"foo/a\"]\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate foo; pub fn bar() { foo::bar(); }\",\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", r#\"#[cfg(feature = \"a\")] pub fn bar() {}\"#)\n        .build();\n\n    p.cargo(\"check --features a -v\").run();\n}\n\n#[cargo_test]\nfn activating_feature_does_not_activate_transitive_dev_dependency() {\n    let p = project()\n        .no_manifest()\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.0\"\n                edition = \"2021\"\n\n                [features]\n                f = [\"b/f\"]\n\n                [dependencies]\n                b = { path = \"../b\" }\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.0.0\"\n                edition = \"2021\"\n\n                [features]\n                f = [\"c/f\"]\n\n                [dev-dependencies]\n                c = { path = \"../c\" }\n            \"#,\n        )\n        .file(\n            \"c/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"c\"\n                version = \"0.0.0\"\n                edition = \"2021\"\n\n                [features]\n                f = []\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\"c/src/lib.rs\", \"compile_error!\")\n        .build();\n\n    p.cargo(\"check --manifest-path a/Cargo.toml --features f\")\n        .run();\n}\n\n#[cargo_test]\nfn dep_feature_in_cmd_line() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.derived]\n                path = \"derived\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                extern crate derived;\n                fn main() { derived::test(); }\n            \"#,\n        )\n        .file(\n            \"derived/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"derived\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n\n                [features]\n                default = []\n                derived-feat = [\"bar/some-feat\"]\n            \"#,\n        )\n        .file(\"derived/src/lib.rs\", \"extern crate bar; pub use bar::test;\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                some-feat = []\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"some-feat\")]\n                pub fn test() { print!(\"test\"); }\n            \"#,\n        )\n        .build();\n\n    // The foo project requires that feature \"some-feat\" in \"bar\" is enabled.\n    // Building without any features enabled should fail:\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\nerror[E0432]: unresolved import `bar::test`\n...\n\"#]])\n        .run();\n\n    // We should be able to enable the feature \"derived-feat\", which enables \"some-feat\",\n    // on the command line. The feature is enabled, thus building should be successful:\n    p.cargo(\"check --features derived/derived-feat\").run();\n\n    // Trying to enable features of transitive dependencies is an error\n    p.cargo(\"check --features bar/some-feat\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package `foo v0.0.1 ([ROOT]/foo)` does not have a dependency named `bar`\n\n\"#]])\n        .run();\n\n    // Hierarchical feature specification should still be disallowed\n    p.cargo(\"check --features derived/bar/some-feat\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] multiple slashes in feature `derived/bar/some-feat` is not allowed\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn all_features_flag_enables_all_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                foo = []\n                bar = []\n\n                [dependencies.baz]\n                path = \"baz\"\n                optional = true\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[cfg(feature = \"foo\")]\n                pub fn foo() {}\n\n                #[cfg(feature = \"bar\")]\n                pub fn bar() {\n                    extern crate baz;\n                    baz::baz();\n                }\n\n                fn main() {\n                    foo();\n                    bar();\n                }\n            \"#,\n        )\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.0.1\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check --all-features\").run();\n}\n\n#[cargo_test]\nfn many_cli_features_comma_delimited() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n                optional = true\n\n                [dependencies.baz]\n                path = \"baz\"\n                optional = true\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[allow(unused_extern_crates)]\n                extern crate bar;\n                #[allow(unused_extern_crates)]\n                extern crate baz;\n                fn main() {}\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.0.1\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check --features bar,baz\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[CHECKING] baz v0.0.1 ([ROOT]/foo/baz)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn many_cli_features_comma_and_space_delimited() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n                optional = true\n\n                [dependencies.baz]\n                path = \"baz\"\n                optional = true\n\n                [dependencies.bam]\n                path = \"bam\"\n                optional = true\n\n                [dependencies.bap]\n                path = \"bap\"\n                optional = true\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[allow(unused_extern_crates)]\n                extern crate bar;\n                #[allow(unused_extern_crates)]\n                extern crate baz;\n                #[allow(unused_extern_crates)]\n                extern crate bam;\n                #[allow(unused_extern_crates)]\n                extern crate bap;\n                fn main() {}\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.0.1\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .file(\"bam/Cargo.toml\", &basic_manifest(\"bam\", \"0.0.1\"))\n        .file(\"bam/src/lib.rs\", \"pub fn bam() {}\")\n        .file(\"bap/Cargo.toml\", &basic_manifest(\"bap\", \"0.0.1\"))\n        .file(\"bap/src/lib.rs\", \"pub fn bap() {}\")\n        .build();\n\n    p.cargo(\"check --features\")\n        .arg(\"bar,baz bam bap\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 4 packages to latest compatible versions\n[CHECKING] bam v0.0.1 ([ROOT]/foo/bam)\n[CHECKING] bap v0.0.1 ([ROOT]/foo/bap)\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[CHECKING] baz v0.0.1 ([ROOT]/foo/baz)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn only_dep_is_optional() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                foo = ['bar']\n\n                [dependencies]\n                bar = { version = \"0.1\", optional = true }\n\n                [dev-dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn all_features_all_crates() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = ['bar']\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                foo = []\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"#[cfg(feature = \\\"foo\\\")] fn main() {}\")\n        .build();\n\n    p.cargo(\"check --all-features --workspace\").run();\n}\n\n#[cargo_test]\nfn feature_off_dylib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"dylib\"]\n\n                [features]\n                f1 = []\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn hello() -> &'static str {\n                    if cfg!(feature = \"f1\") {\n                        \"f1\"\n                    } else {\n                        \"no f1\"\n                    }\n                }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                foo = { path = \"..\" }\n            \"#,\n        )\n        .file(\n            \"bar/src/main.rs\",\n            r#\"\n                extern crate foo;\n\n                fn main() {\n                    assert_eq!(foo::hello(), \"no f1\");\n                }\n            \"#,\n        )\n        .build();\n\n    // Build the dylib with `f1` feature.\n    p.cargo(\"check --features f1\").run();\n    // Check that building without `f1` uses a dylib without `f1`.\n    p.cargo(\"run -p bar\").run();\n}\n\n#[cargo_test]\nfn warn_if_default_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n               [package]\n               name = \"foo\"\n               version = \"0.0.1\"\n               edition = \"2015\"\n               authors = []\n\n               [dependencies.bar]\n               path = \"bar\"\n               optional = true\n\n               [features]\n               default-features = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `[features]` defines a feature named `default-features`\n[NOTE] only a feature named `default` will be enabled by default\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_feature_for_non_optional_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[cfg(not(feature = \"bar\"))]\n                fn main() {\n                }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"check --features bar/a\").run();\n}\n\n#[cargo_test]\nfn features_option_given_twice() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n                b = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[cfg(all(feature = \"a\", feature = \"b\"))]\n                fn main() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check --features a --features b\").run();\n}\n\n#[cargo_test]\nfn multi_multi_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n                b = []\n                c = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n               #[cfg(all(feature = \"a\", feature = \"b\", feature = \"c\"))]\n               fn main() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check --features a --features\").arg(\"b c\").run();\n}\n\n#[cargo_test]\nfn cli_parse_ok() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n               #[cfg(feature = \"a\")]\n               fn main() {\n                    assert_eq!(std::env::args().nth(1).unwrap(), \"b\");\n               }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run --features a b\").run();\n}\n\n#[cargo_test]\nfn all_features_virtual_ws() {\n    // What happens with `--all-features` in the root of a virtual workspace.\n    // Some of this behavior is a little strange (member dependencies also\n    // have all features enabled, one might expect `f4` to be disabled).\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                b = {path=\"../b\", optional=true}\n\n                [features]\n                default = [\"f1\"]\n                f1 = []\n                f2 = []\n            \"#,\n        )\n        .file(\n            \"a/src/main.rs\",\n            r#\"\n                fn main() {\n                    if cfg!(feature=\"f1\") {\n                        println!(\"f1\");\n                    }\n                    if cfg!(feature=\"f2\") {\n                        println!(\"f2\");\n                    }\n                    #[cfg(feature=\"b\")]\n                    b::f();\n                }\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                default = [\"f3\"]\n                f3 = []\n                f4 = []\n            \"#,\n        )\n        .file(\n            \"b/src/lib.rs\",\n            r#\"\n                pub fn f() {\n                    if cfg!(feature=\"f3\") {\n                        println!(\"f3\");\n                    }\n                    if cfg!(feature=\"f4\") {\n                        println!(\"f4\");\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\nf1\n\n\"#]])\n        .run();\n    p.cargo(\"run --all-features\")\n        .with_stdout_data(str![[r#\"\nf1\nf2\nf3\nf4\n\n\"#]])\n        .run();\n    // In `a`, it behaves differently. :(\n    p.cargo(\"run --all-features\")\n        .cwd(\"a\")\n        .with_stdout_data(str![[r#\"\nf1\nf2\nf3\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn slash_optional_enables() {\n    // --features dep/feat will enable `dep` and set its feature.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n                edition = \"2015\"\n\n            [dependencies]\n            dep = {path=\"dep\", optional=true}\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            #[cfg(not(feature=\"dep\"))]\n            compile_error!(\"dep not set\");\n            \"#,\n        )\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            feat = []\n            \"#,\n        )\n        .file(\n            \"dep/src/lib.rs\",\n            r#\"\n            #[cfg(not(feature=\"feat\"))]\n            compile_error!(\"feat not set\");\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] dep not set\n...\n\"#]])\n        .run();\n\n    p.cargo(\"check --features dep/feat\").run();\n}\n\n#[cargo_test]\nfn registry_summary_order_doesnt_matter() {\n    // Checks for an issue where the resolver depended on the order of entries\n    // in the registry summary. If there was a non-optional dev-dependency\n    // that appeared before an optional normal dependency, then the resolver\n    // would not activate the optional dependency with a pkg/featname feature\n    // syntax.\n    Package::new(\"dep\", \"0.1.0\")\n        .feature(\"feat1\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(feature=\"feat1\")]\n                pub fn work() {\n                    println!(\"it works\");\n                }\n            \"#,\n        )\n        .publish();\n    Package::new(\"bar\", \"0.1.0\")\n        .feature(\"bar_feat\", &[\"dep/feat1\"])\n        .add_dep(Dependency::new(\"dep\", \"0.1.0\").dev())\n        .add_dep(Dependency::new(\"dep\", \"0.1.0\").optional(true))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                // This will fail to compile without `dep` optional dep activated.\n                extern crate dep;\n\n                pub fn doit() {\n                    dep::work();\n                }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                bar = { version=\"0.1\", features = [\"bar_feat\"] }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    bar::doit();\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[COMPILING] dep v0.1.0\n[COMPILING] bar v0.1.0\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nit works\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn nonexistent_required_features() {\n    Package::new(\"required_dependency\", \"0.1.0\")\n        .feature(\"simple\", &[])\n        .publish();\n    Package::new(\"optional_dependency\", \"0.2.0\")\n        .feature(\"optional\", &[])\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            [features]\n            existing = []\n            fancy = [\"optional_dependency\"]\n            [dependencies]\n            required_dependency = { version = \"0.1\", optional = false}\n            optional_dependency = { version = \"0.2\", optional = true}\n            [[example]]\n            name = \"ololo\"\n            required-features = [\"not_present\",\n                                 \"existing\",\n                                 \"fancy\",\n                                 \"required_dependency/not_existing\",\n                                 \"required_dependency/simple\",\n                                 \"optional_dependency/optional\",\n                                 \"not_specified_dependency/some_feature\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"examples/ololo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check --examples\").with_stderr_data(str![[r#\"\n...\n[WARNING] invalid feature `not_present` in required-features of target `ololo`: `not_present` is not present in [features] section\n[WARNING] invalid feature `required_dependency/not_existing` in required-features of target `ololo`: feature `not_existing` does not exist in package `required_dependency v0.1.0`\n[WARNING] invalid feature `not_specified_dependency/some_feature` in required-features of target `ololo`: dependency `not_specified_dependency` does not exist\n...\n\"#]]).run();\n}\n\n#[cargo_test]\nfn invalid_feature_names_error() {\n    // Errors for more restricted feature syntax.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                # Invalid start character.\n                \"+foo\" = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid character `+` in feature name: `+foo`, the first character must be a Unicode XID start character or digit (most letters or `_` or `0` to `9`)\n --> Cargo.toml:9:17\n  |\n9 |                 \"+foo\" = []\n  |                 ^^^^^^\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            # Invalid continue character.\n            \"a&b\" = []\n        \"#,\n    );\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid character `&` in feature name: `a&b`, characters must be Unicode XID characters, '-', `+`, or `.` (numbers, `+`, `-`, `_`, `.`, or most letters)\n --> Cargo.toml:9:13\n  |\n9 |             \"a&b\" = []\n  |             ^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_feature_name_slash_error() {\n    // Errors for more restricted feature syntax.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                \"foo/bar\" = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid character `/` in feature name: `foo/bar`, feature name is not allowed to contain slashes\n --> Cargo.toml:8:17\n  |\n8 |                 \"foo/bar\" = []\n  |                 ^^^^^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dont_demand_not_required_dep() {\n    Package::new(\"not-required\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"sample\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[features]\ndefault = [\"feat\"]\nfeat = [\"dep:not-required\"]\n\n[target.'cfg(false)'.dependencies]\nnot-required = { version = \"1.0\", optional = true }\n\n[[example]]\nname = \"demo\"\nrequired-features = [\"feat\"]\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"examples/demo.rs\", \"fn main() {}\")\n        .build();\n\n    let host = rustc_host();\n    p.cargo(&format!(\"fetch --target={host}\")).run();\n    p.cargo(&format!(\"check --target={host} --examples --frozen\"))\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/features2.rs",
    "content": "//! Tests for the new feature resolver.\n\nuse std::fs::File;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse crate::utils::cross_compile::disabled as cross_compile_disabled;\nuse cargo_test_support::cross_compile::alternate;\nuse cargo_test_support::paths;\nuse cargo_test_support::publish::validate_crate_contents;\nuse cargo_test_support::registry::{Dependency, Package};\nuse cargo_test_support::str;\nuse cargo_test_support::{Project, basic_manifest, project, rustc_host};\n\n/// Switches Cargo.toml to use `resolver = \"2\"`.\npub fn switch_to_resolver_2(p: &Project) {\n    let mut manifest = p.read_file(\"Cargo.toml\");\n    if manifest.contains(\"resolver =\") {\n        panic!(\"did not expect manifest to already contain a resolver setting\");\n    }\n    if let Some(index) = manifest.find(\"[workspace]\\n\") {\n        manifest.insert_str(index + 12, \"resolver = \\\"2\\\"\\n\");\n    } else if let Some(index) = manifest.find(\"[package]\\n\") {\n        manifest.insert_str(index + 10, \"resolver = \\\"2\\\"\\n\");\n    } else {\n        panic!(\"expected [package] or [workspace] in manifest\");\n    }\n    p.change_file(\"Cargo.toml\", &manifest);\n}\n\n#[cargo_test]\nfn inactivate_targets() {\n    // Basic test of `itarget`. A shared dependency where an inactive [target]\n    // changes the features.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"f1\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            #[cfg(feature = \"f1\")]\n            compile_error!(\"f1 should not activate\");\n            \"#,\n        )\n        .publish();\n\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(\n            Dependency::new(\"common\", \"1.0\")\n                .target(\"cfg(whatever)\")\n                .enable_features(&[\"f1\"]),\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            common = \"1.0\"\n            bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n...\n[ERROR] f1 should not activate\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    switch_to_resolver_2(&p);\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn inactive_target_optional() {\n    // Activating optional [target] dependencies for inactivate target.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"f1\", &[])\n        .feature(\"f2\", &[])\n        .feature(\"f3\", &[])\n        .feature(\"f4\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn f() {\n                if cfg!(feature=\"f1\") { println!(\"f1\"); }\n                if cfg!(feature=\"f2\") { println!(\"f2\"); }\n                if cfg!(feature=\"f3\") { println!(\"f3\"); }\n                if cfg!(feature=\"f4\") { println!(\"f4\"); }\n            }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [dependencies]\n            common = \"1.0\"\n\n            [target.'cfg(whatever)'.dependencies]\n            dep1 = {path='dep1', optional=true}\n            dep2 = {path='dep2', optional=true, features=[\"f3\"]}\n            common = {version=\"1.0\", optional=true, features=[\"f4\"]}\n\n            [features]\n            foo1 = [\"dep1/f2\"]\n            foo2 = [\"dep2\"]\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                if cfg!(feature=\"foo1\") { println!(\"foo1\"); }\n                if cfg!(feature=\"foo2\") { println!(\"foo2\"); }\n                if cfg!(feature=\"dep1\") { println!(\"dep1\"); }\n                if cfg!(feature=\"dep2\") { println!(\"dep2\"); }\n                if cfg!(feature=\"common\") { println!(\"common\"); }\n                common::f();\n            }\n            \"#,\n        )\n        .file(\n            \"dep1/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep1\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            common = {version=\"1.0\", features=[\"f1\"]}\n\n            [features]\n            f2 = [\"common/f2\"]\n            \"#,\n        )\n        .file(\n            \"dep1/src/lib.rs\",\n            r#\"compile_error!(\"dep1 should not build\");\"#,\n        )\n        .file(\n            \"dep2/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep2\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            common = \"1.0\"\n\n            [features]\n            f3 = [\"common/f3\"]\n            \"#,\n        )\n        .file(\n            \"dep2/src/lib.rs\",\n            r#\"compile_error!(\"dep2 should not build\");\"#,\n        )\n        .build();\n\n    p.cargo(\"run --all-features\")\n        .with_stdout_data(str![[r#\"\nfoo1\nfoo2\ndep1\ndep2\ncommon\nf1\nf2\nf3\nf4\n\n\"#]])\n        .run();\n    p.cargo(\"run --features dep1\")\n        .with_stdout_data(str![[r#\"\ndep1\nf1\n\n\"#]])\n        .run();\n    p.cargo(\"run --features foo1\")\n        .with_stdout_data(str![[r#\"\nfoo1\ndep1\nf1\nf2\n\n\"#]])\n        .run();\n    p.cargo(\"run --features dep2\")\n        .with_stdout_data(str![[r#\"\ndep2\nf3\n\n\"#]])\n        .run();\n    p.cargo(\"run --features common\")\n        .with_stdout_data(str![[r#\"\ncommon\nf4\n\n\"#]])\n        .run();\n\n    switch_to_resolver_2(&p);\n    p.cargo(\"run --all-features\")\n        .with_stdout_data(str![[r#\"\nfoo1\nfoo2\ndep1\ndep2\ncommon\n\n\"#]])\n        .run();\n    p.cargo(\"run --features dep1\")\n        .with_stdout_data(str![[r#\"\ndep1\n\n\"#]])\n        .run();\n    p.cargo(\"run --features foo1\")\n        .with_stdout_data(str![[r#\"\nfoo1\n\n\"#]])\n        .run();\n    p.cargo(\"run --features dep2\")\n        .with_stdout_data(str![[r#\"\ndep2\n\n\"#]])\n        .run();\n    p.cargo(\"run --features common\")\n        .with_stdout_data(str![[r#\"\ncommon\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn itarget_proc_macro() {\n    // itarget inside a proc-macro while cross-compiling\n    if cross_compile_disabled() {\n        return;\n    }\n    Package::new(\"hostdep\", \"1.0.0\").publish();\n    Package::new(\"pm\", \"1.0.0\")\n        .proc_macro(true)\n        .target_dep(\"hostdep\", \"1.0\", rustc_host())\n        .file(\"src/lib.rs\", \"extern crate hostdep;\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            pm = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Old behavior\n    p.cargo(\"check\").run();\n    p.cargo(\"check --target\").arg(alternate()).run();\n\n    // New behavior\n    switch_to_resolver_2(&p);\n    p.cargo(\"check\").run();\n    p.cargo(\"check --target\").arg(alternate()).run();\n    // For good measure, just make sure things don't break.\n    p.cargo(\"check --target\").arg(alternate()).run();\n}\n\n#[cargo_test]\nfn decouple_host_deps() {\n    // Basic test for `host_dep` decouple.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"f1\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            #[cfg(feature = \"f1\")]\n            pub fn foo() {}\n            #[cfg(not(feature = \"f1\"))]\n            pub fn bar() {}\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [build-dependencies]\n            common = {version=\"1.0\", features=[\"f1\"]}\n\n            [dependencies]\n            common = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n            use common::foo;\n            fn main() {}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"use common::bar;\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\nerror[E0432]: unresolved import `common::bar`\n...\n\"#]])\n        .run();\n\n    switch_to_resolver_2(&p);\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn decouple_host_deps_nested() {\n    // `host_dep` decouple of transitive dependencies.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"f1\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            #[cfg(feature = \"f1\")]\n            pub fn foo() {}\n            #[cfg(not(feature = \"f1\"))]\n            pub fn bar() {}\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [build-dependencies]\n            bdep = {path=\"bdep\"}\n\n            [dependencies]\n            common = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n            use bdep::foo;\n            fn main() {}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"use common::bar;\")\n        .file(\n            \"bdep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bdep\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [dependencies]\n            common = {version=\"1.0\", features=[\"f1\"]}\n            \"#,\n        )\n        .file(\"bdep/src/lib.rs\", \"pub use common::foo;\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\nerror[E0432]: unresolved import `common::bar`\n...\n\"#]])\n        .run();\n\n    switch_to_resolver_2(&p);\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn decouple_dev_deps() {\n    // Basic test for `dev_dep` decouple.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"f1\", &[])\n        .feature(\"f2\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            // const ensures it uses the correct dependency at *build time*\n            // compared to *link time*.\n            #[cfg(all(feature=\"f1\", not(feature=\"f2\")))]\n            pub const X: u32 = 1;\n\n            #[cfg(all(feature=\"f1\", feature=\"f2\"))]\n            pub const X: u32 = 3;\n\n            pub fn foo() -> u32 {\n                let mut res = 0;\n                if cfg!(feature = \"f1\") {\n                    res |= 1;\n                }\n                if cfg!(feature = \"f2\") {\n                    res |= 2;\n                }\n                res\n            }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [dependencies]\n            common = {version=\"1.0\", features=[\"f1\"]}\n\n            [dev-dependencies]\n            common = {version=\"1.0\", features=[\"f2\"]}\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                let expected: u32 = std::env::args().skip(1).next().unwrap().parse().unwrap();\n                assert_eq!(foo::foo(), expected);\n                assert_eq!(foo::build_time(), expected);\n                assert_eq!(common::foo(), expected);\n                assert_eq!(common::X, expected);\n            }\n\n            #[test]\n            fn test_bin() {\n                assert_eq!(foo::foo(), 3);\n                assert_eq!(common::foo(), 3);\n                assert_eq!(common::X, 3);\n                assert_eq!(foo::build_time(), 3);\n            }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn foo() -> u32 {\n                common::foo()\n            }\n\n            pub fn build_time() -> u32 {\n                common::X\n            }\n\n            #[test]\n            fn test_lib() {\n                assert_eq!(foo(), 3);\n                assert_eq!(common::foo(), 3);\n                assert_eq!(common::X, 3);\n            }\n            \"#,\n        )\n        .file(\n            \"tests/t1.rs\",\n            r#\"\n            #[test]\n            fn test_t1() {\n                assert_eq!(foo::foo(), 3);\n                assert_eq!(common::foo(), 3);\n                assert_eq!(common::X, 3);\n                assert_eq!(foo::build_time(), 3);\n            }\n\n            #[test]\n            fn test_main() {\n                // Features are unified for main when run with `cargo test`,\n                // even with the new resolver.\n                let s = std::process::Command::new(\"target/debug/foo\")\n                    .arg(\"3\")\n                    .status().unwrap();\n                assert!(s.success());\n            }\n            \"#,\n        )\n        .build();\n\n    // Old behavior\n    p.cargo(\"run 3\").run();\n    p.cargo(\"test\").run();\n\n    // New behavior\n    switch_to_resolver_2(&p);\n    p.cargo(\"run 1\").run();\n    p.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn build_script_runtime_features() {\n    // Check that the CARGO_FEATURE_* environment variable is set correctly.\n    //\n    // This has a common dependency between build/normal/dev-deps, and it\n    // queries which features it was built with in different circumstances.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"normal\", &[])\n        .feature(\"dev\", &[])\n        .feature(\"build\", &[])\n        .file(\n            \"build.rs\",\n            r#\"\n            fn is_set(name: &str) -> bool {\n                std::env::var(name) == Ok(\"1\".to_string())\n            }\n\n            fn main() {\n                let mut res = 0;\n                if is_set(\"CARGO_FEATURE_NORMAL\") {\n                    res |= 1;\n                }\n                if is_set(\"CARGO_FEATURE_DEV\") {\n                    res |= 2;\n                }\n                if is_set(\"CARGO_FEATURE_BUILD\") {\n                    res |= 4;\n                }\n                println!(\"cargo::rustc-cfg=RunCustomBuild=\\\"{}\\\"\", res);\n\n                let mut res = 0;\n                if cfg!(feature = \"normal\") {\n                    res |= 1;\n                }\n                if cfg!(feature = \"dev\") {\n                    res |= 2;\n                }\n                if cfg!(feature = \"build\") {\n                    res |= 4;\n                }\n                println!(\"cargo::rustc-cfg=CustomBuild=\\\"{}\\\"\", res);\n            }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn foo() -> u32 {\n                let mut res = 0;\n                if cfg!(feature = \"normal\") {\n                    res |= 1;\n                }\n                if cfg!(feature = \"dev\") {\n                    res |= 2;\n                }\n                if cfg!(feature = \"build\") {\n                    res |= 4;\n                }\n                res\n            }\n\n            pub fn build_time() -> u32 {\n                #[cfg(RunCustomBuild=\"1\")] return 1;\n                #[cfg(RunCustomBuild=\"3\")] return 3;\n                #[cfg(RunCustomBuild=\"4\")] return 4;\n                #[cfg(RunCustomBuild=\"5\")] return 5;\n                #[cfg(RunCustomBuild=\"7\")] return 7;\n            }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [build-dependencies]\n            common = {version=\"1.0\", features=[\"build\"]}\n\n            [dependencies]\n            common = {version=\"1.0\", features=[\"normal\"]}\n\n            [dev-dependencies]\n            common = {version=\"1.0\", features=[\"dev\"]}\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                assert_eq!(common::foo(), common::build_time());\n                println!(\"cargo::rustc-cfg=from_build=\\\"{}\\\"\", common::foo());\n            }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn foo() -> u32 {\n                common::foo()\n            }\n\n            pub fn build_time() -> u32 {\n                common::build_time()\n            }\n\n            #[test]\n            fn test_lib() {\n                assert_eq!(common::foo(), common::build_time());\n                assert_eq!(common::foo(),\n                    std::env::var(\"CARGO_FEATURE_EXPECT\").unwrap().parse().unwrap());\n            }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                assert_eq!(common::foo(), common::build_time());\n                assert_eq!(common::foo(),\n                    std::env::var(\"CARGO_FEATURE_EXPECT\").unwrap().parse().unwrap());\n            }\n\n            #[test]\n            fn test_bin() {\n                assert_eq!(common::foo(), common::build_time());\n                assert_eq!(common::foo(),\n                    std::env::var(\"CARGO_FEATURE_EXPECT\").unwrap().parse().unwrap());\n            }\n            \"#,\n        )\n        .file(\n            \"tests/t1.rs\",\n            r#\"\n            #[test]\n            fn test_t1() {\n                assert_eq!(common::foo(), common::build_time());\n                assert_eq!(common::foo(),\n                    std::env::var(\"CARGO_FEATURE_EXPECT\").unwrap().parse().unwrap());\n            }\n\n            #[test]\n            fn test_main() {\n                // Features are unified for main when run with `cargo test`,\n                // even with the new resolver.\n                let s = std::process::Command::new(\"target/debug/foo\")\n                    .status().unwrap();\n                assert!(s.success());\n            }\n            \"#,\n        )\n        .build();\n\n    // Old way, unifies all 3.\n    p.cargo(\"run\").env(\"CARGO_FEATURE_EXPECT\", \"7\").run();\n    p.cargo(\"test\").env(\"CARGO_FEATURE_EXPECT\", \"7\").run();\n\n    // New behavior.\n    switch_to_resolver_2(&p);\n\n    // normal + build unify\n    p.cargo(\"run\").env(\"CARGO_FEATURE_EXPECT\", \"1\").run();\n\n    // dev_deps are still unified with `cargo test`\n    p.cargo(\"test\").env(\"CARGO_FEATURE_EXPECT\", \"3\").run();\n}\n\n#[cargo_test]\nfn cyclical_dev_dep() {\n    // Check how a cyclical dev-dependency will work.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [features]\n            dev = []\n\n            [dev-dependencies]\n            foo = { path = '.', features = [\"dev\"] }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn assert_dev(enabled: bool) {\n                assert_eq!(enabled, cfg!(feature=\"dev\"));\n            }\n\n            #[test]\n            fn test_in_lib() {\n                assert_dev(true);\n            }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                let expected: bool = std::env::args().skip(1).next().unwrap().parse().unwrap();\n                foo::assert_dev(expected);\n            }\n            \"#,\n        )\n        .file(\n            \"tests/t1.rs\",\n            r#\"\n            #[test]\n            fn integration_links() {\n                foo::assert_dev(true);\n                // The lib linked with main.rs will also be unified.\n                let s = std::process::Command::new(\"target/debug/foo\")\n                    .arg(\"true\")\n                    .status().unwrap();\n                assert!(s.success());\n            }\n            \"#,\n        )\n        .build();\n\n    // Old way unifies features.\n    p.cargo(\"run true\").run();\n    // dev feature should always be enabled in tests.\n    p.cargo(\"test\").run();\n\n    // New behavior.\n    switch_to_resolver_2(&p);\n    // Should decouple main.\n    p.cargo(\"run false\").run();\n\n    // And this should be no different.\n    p.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn all_feature_opts() {\n    // All feature options at once.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"normal\", &[])\n        .feature(\"build\", &[])\n        .feature(\"dev\", &[])\n        .feature(\"itarget\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn feats() -> u32 {\n                let mut res = 0;\n                if cfg!(feature=\"normal\") { res |= 1; }\n                if cfg!(feature=\"build\") { res |= 2; }\n                if cfg!(feature=\"dev\") { res |= 4; }\n                if cfg!(feature=\"itarget\") { res |= 8; }\n                res\n            }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [dependencies]\n            common = {version = \"1.0\", features=[\"normal\"]}\n\n            [dev-dependencies]\n            common = {version = \"1.0\", features=[\"dev\"]}\n\n            [build-dependencies]\n            common = {version = \"1.0\", features=[\"build\"]}\n\n            [target.'cfg(whatever)'.dependencies]\n            common = {version = \"1.0\", features=[\"itarget\"]}\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                expect();\n            }\n\n            fn expect() {\n                let expected: u32 = std::env::var(\"EXPECTED_FEATS\").unwrap().parse().unwrap();\n                assert_eq!(expected, common::feats());\n            }\n\n            #[test]\n            fn from_test() {\n                expect();\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\").env(\"EXPECTED_FEATS\", \"15\").run();\n    p.cargo(\"test\").env(\"EXPECTED_FEATS\", \"15\").run();\n\n    // New behavior.\n    switch_to_resolver_2(&p);\n    // Only normal feature.\n    p.cargo(\"run\").env(\"EXPECTED_FEATS\", \"1\").run();\n\n    // only normal+dev\n    p.cargo(\"test\").env(\"EXPECTED_FEATS\", \"5\").run();\n}\n\n#[cargo_test]\nfn required_features_host_dep() {\n    // Check that required-features handles build-dependencies correctly.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [[bin]]\n            name = \"x\"\n            required-features = [\"bdep/f1\"]\n\n            [build-dependencies]\n            bdep = {path=\"bdep\"}\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\n            \"src/bin/x.rs\",\n            r#\"\n            fn main() {}\n            \"#,\n        )\n        .file(\n            \"bdep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bdep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            f1 = []\n            \"#,\n        )\n        .file(\"bdep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"run\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ERROR] target `x` in package `foo` requires the features: `bdep/f1`\nConsider enabling them by passing, e.g., `--features=\"bdep/f1\"`\n\n\"#]])\n        .run();\n\n    // New behavior.\n    switch_to_resolver_2(&p);\n    p.cargo(\"run --features bdep/f1\").run();\n}\n\n#[cargo_test]\nfn disabled_shared_host_dep() {\n    // Check for situation where an optional dep of a shared dep is enabled in\n    // a normal dependency, but disabled in an optional one. The unit tree is:\n    // foo\n    // ├── foo build.rs\n    // |   └── common (BUILD dependency, NO FEATURES)\n    // └── common (Normal dependency, default features)\n    //     └── somedep\n    Package::new(\"somedep\", \"1.0.0\")\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn f() { println!(\"hello from somedep\"); }\n            \"#,\n        )\n        .publish();\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"default\", &[\"somedep\"])\n        .add_dep(Dependency::new(\"somedep\", \"1.0\").optional(true))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn check_somedep() -> bool {\n                #[cfg(feature=\"somedep\")]\n                {\n                    extern crate somedep;\n                    somedep::f();\n                    true\n                }\n                #[cfg(not(feature=\"somedep\"))]\n                {\n                    println!(\"no somedep\");\n                    false\n                }\n            }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2018\"\n            resolver = \"2\"\n\n            [dependencies]\n            common = \"1.0\"\n\n            [build-dependencies]\n            common = {version = \"1.0\", default-features = false}\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"fn main() { assert!(common::check_somedep()); }\",\n        )\n        .file(\n            \"build.rs\",\n            \"fn main() { assert!(!common::check_somedep()); }\",\n        )\n        .build();\n\n    p.cargo(\"run -v\")\n        .with_stdout_data(str![[r#\"\nhello from somedep\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn required_features_inactive_dep() {\n    // required-features with an inactivated dep.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            resolver = \"2\"\n\n            [target.'cfg(whatever)'.dependencies]\n            bar = {path=\"bar\"}\n\n            [[bin]]\n            name = \"foo\"\n            required-features = [\"feat1\"]\n\n            [features]\n            feat1 = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check --features=feat1\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn decouple_proc_macro() {\n    // proc macro features are not shared\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"somefeat\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub const fn foo() -> bool { cfg!(feature=\"somefeat\") }\n            #[cfg(feature=\"somefeat\")]\n            pub const FEAT_ONLY_CONST: bool = true;\n            \"#,\n        )\n        .publish();\n    Package::new(\"pm\", \"1.0.0\")\n        .proc_macro(true)\n        .feature_dep(\"common\", \"1.0\", &[\"somefeat\"])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            extern crate proc_macro;\n            extern crate common;\n            #[proc_macro]\n            pub fn foo(input: proc_macro::TokenStream) -> proc_macro::TokenStream {\n                assert!(common::foo());\n                \"\".parse().unwrap()\n            }\n            \"#,\n        )\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2018\"\n\n            [dependencies]\n            pm = \"1.0\"\n            common = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            //! Test with docs.\n            //!\n            //! ```rust\n            //! pm::foo!{}\n            //! fn main() {\n            //!   let expected = std::env::var_os(\"TEST_EXPECTS_ENABLED\").is_some();\n            //!   assert_eq!(expected, common::foo(), \"common is wrong\");\n            //! }\n            //! ```\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            pm::foo!{}\n            fn main() {\n                println!(\"it is {}\", common::foo());\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .env(\"TEST_EXPECTS_ENABLED\", \"1\")\n        .with_stdout_data(str![[r#\"\nit is true\n\n\"#]])\n        .run();\n    // Make sure the test is fallible.\n    p.cargo(\"test --doc\")\n        .with_status(101)\n        .with_stdout_data(\"...\\n[..]common is wrong[..]\\n...\")\n        .run();\n    p.cargo(\"test --doc\").env(\"TEST_EXPECTS_ENABLED\", \"1\").run();\n    p.cargo(\"doc\").run();\n    assert!(\n        p.build_dir()\n            .join(\"doc/common/constant.FEAT_ONLY_CONST.html\")\n            .exists()\n    );\n    // cargo doc should clean in-between runs, but it doesn't, and leaves stale files.\n    // https://github.com/rust-lang/cargo/issues/6783 (same for removed items)\n    p.build_dir().join(\"doc\").rm_rf();\n\n    // New behavior.\n    switch_to_resolver_2(&p);\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\nit is false\n\n\"#]])\n        .run();\n\n    p.cargo(\"test --doc\").run();\n    p.cargo(\"doc\").run();\n    assert!(\n        !p.build_dir()\n            .join(\"doc/common/constant.FEAT_ONLY_CONST.html\")\n            .exists()\n    );\n}\n\n#[cargo_test]\nfn proc_macro_ws() {\n    // Checks for bug with proc-macro in a workspace with dependency (shouldn't panic).\n    //\n    // Note, debuginfo is explicitly requested here to preserve the intent of this non-regression\n    // test: that will disable the debuginfo build dependencies optimization. Otherwise, it would\n    // initially trigger when the crates are built independently, but rebuild them with debuginfo\n    // when it sees the shared build/runtime dependency when checking the complete workspace.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"foo\", \"pm\"]\n            resolver = \"2\"\n\n            [profile.dev.build-override]\n            debug = true\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            feat1 = []\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"pm\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [lib]\n            proc-macro = true\n\n            [dependencies]\n            foo = { path = \"../foo\", features=[\"feat1\"] }\n            \"#,\n        )\n        .file(\"pm/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -p pm -v\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustc --crate-name foo [..]--cfg[..]feat1[..]`\n...\n\"#]])\n        .run();\n    // This may be surprising that `foo` doesn't get built separately. It is\n    // because pm might have other units (binaries, tests, etc.), and so the\n    // feature resolver must assume that normal deps get unified with it. This\n    // is related to the bigger issue where the features selected in a\n    // workspace depend on which packages are selected.\n    p.cargo(\"check --workspace -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.1.0 ([ROOT]/foo/foo)\n[FRESH] pm v0.1.0 ([ROOT]/foo/pm)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // Selecting just foo will build without unification.\n    p.cargo(\"check -p foo -v\")\n        // Make sure `foo` is built without feat1\n        .with_stderr_line_without(\n            &[\"[RUNNING] `rustc --crate-name foo --edition=2015\"],\n            &[\"--cfg[..]feat1\"],\n        )\n        .run();\n}\n\n#[cargo_test]\nfn has_dev_dep_for_test() {\n    // Check for a bug where the decision on whether or not \"dev dependencies\"\n    // should be used did not consider `check --profile=test`.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dev-dependencies]\n            dep = { path = 'dep', features = ['f1'] }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            #[test]\n            fn t1() {\n                dep::f();\n            }\n            \"#,\n        )\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            f1 = []\n            \"#,\n        )\n        .file(\n            \"dep/src/lib.rs\",\n            r#\"\n            #[cfg(feature = \"f1\")]\n            pub fn f() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check -v --profile=test\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] dep v0.1.0 ([ROOT]/foo/dep)\n[RUNNING] `rustc --crate-name dep [..]`\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // New resolver should not be any different.\n    switch_to_resolver_2(&p);\n    p.cargo(\"check -v --profile=test\")\n        .with_stderr_data(str![[r#\"\n[FRESH] dep v0.1.0 ([ROOT]/foo/dep)\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_dep_activated() {\n    // Build dependencies always match the host for [target.*.build-dependencies].\n    if cross_compile_disabled() {\n        return;\n    }\n    Package::new(\"somedep\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    Package::new(\"targetdep\", \"1.0.0\").publish();\n    Package::new(\"hostdep\", \"1.0.0\")\n        // Check that \"for_host\" is sticky.\n        .target_dep(\"somedep\", \"1.0\", rustc_host())\n        .feature(\"feat1\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            extern crate somedep;\n\n            #[cfg(not(feature=\"feat1\"))]\n            compile_error!{\"feat1 missing\"}\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                # This should never be selected.\n                [target.'{}'.build-dependencies]\n                targetdep = \"1.0\"\n\n                [target.'{}'.build-dependencies]\n                hostdep = {{version=\"1.0\", features=[\"feat1\"]}}\n                \"#,\n                alternate(),\n                rustc_host()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"check --target\").arg(alternate()).run();\n\n    // New behavior.\n    switch_to_resolver_2(&p);\n    p.cargo(\"check\").run();\n    p.cargo(\"check --target\").arg(alternate()).run();\n}\n\n#[cargo_test]\nfn resolver_bad_setting() {\n    // Unknown setting in `resolver`\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            resolver = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `resolver` setting `foo` is not valid, valid options are \"1\", \"2\" or \"3\"\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn resolver_original() {\n    // resolver=\"1\" uses old unification behavior.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"f1\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            #[cfg(feature = \"f1\")]\n            compile_error!(\"f1 should not activate\");\n            \"#,\n        )\n        .publish();\n\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(\n            Dependency::new(\"common\", \"1.0\")\n                .target(\"cfg(whatever)\")\n                .enable_features(&[\"f1\"]),\n        )\n        .publish();\n\n    let manifest = |resolver| {\n        format!(\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                resolver = \"{}\"\n\n                [dependencies]\n                common = \"1.0\"\n                bar = \"1.0\"\n            \"#,\n            resolver\n        )\n    };\n\n    let p = project()\n        .file(\"Cargo.toml\", &manifest(\"1\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n...\n[ERROR] f1 should not activate\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.change_file(\"Cargo.toml\", &manifest(\"2\"));\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn resolver_not_both() {\n    // Can't specify resolver in both workspace and package.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            resolver = \"2\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            resolver = \"2\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  cannot specify `resolver` field in both `[workspace]` and `[package]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn resolver_ws_member() {\n    // Can't specify `resolver` in a ws member.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            resolver = \"2\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] resolver for the non root package will be ignored, specify resolver at the workspace root:\npackage:   [ROOT]/foo/a/Cargo.toml\nworkspace: [ROOT]/foo/Cargo.toml\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn edition_2021_workspace_member() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2021\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] virtual workspace defaulting to `resolver = \"1\"` despite one or more workspace members being on edition 2021 which implies `resolver = \"2\"`\n  |\n  = [NOTE] to keep the current resolver, specify `workspace.resolver = \"1\"` in the workspace root's manifest\n  = [NOTE] to use the edition 2021 resolver, specify `workspace.resolver = \"2\"` in the workspace root's manifest\n  = [NOTE] for more details see https://doc.rust-lang.org/cargo/reference/resolver.html#resolver-versions\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn resolver_ws_root_and_member() {\n    // Check when specified in both ws root and member.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\"]\n            resolver = \"2\"\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            resolver = \"2\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    // Ignores if they are the same.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn resolver_enables_new_features() {\n    // resolver=\"2\" enables all the things.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"normal\", &[])\n        .feature(\"build\", &[])\n        .feature(\"dev\", &[])\n        .feature(\"itarget\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn feats() -> u32 {\n                let mut res = 0;\n                if cfg!(feature=\"normal\") { res |= 1; }\n                if cfg!(feature=\"build\") { res |= 2; }\n                if cfg!(feature=\"dev\") { res |= 4; }\n                if cfg!(feature=\"itarget\") { res |= 8; }\n                res\n            }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            resolver = \"2\"\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [dependencies]\n            common = {version = \"1.0\", features=[\"normal\"]}\n\n            [dev-dependencies]\n            common = {version = \"1.0\", features=[\"dev\"]}\n\n            [build-dependencies]\n            common = {version = \"1.0\", features=[\"build\"]}\n\n            [target.'cfg(whatever)'.dependencies]\n            common = {version = \"1.0\", features=[\"itarget\"]}\n            \"#,\n        )\n        .file(\n            \"a/src/main.rs\",\n            r#\"\n            fn main() {\n                expect();\n            }\n\n            fn expect() {\n                let expected: u32 = std::env::var(\"EXPECTED_FEATS\").unwrap().parse().unwrap();\n                assert_eq!(expected, common::feats());\n            }\n\n            #[test]\n            fn from_test() {\n                expect();\n            }\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            ping = []\n            \"#,\n        )\n        .file(\n            \"b/src/main.rs\",\n            r#\"\n            fn main() {\n                if cfg!(feature=\"ping\") {\n                    println!(\"pong\");\n                }\n            }\n            \"#,\n        )\n        .build();\n\n    // Only normal.\n    p.cargo(\"run --bin a\")\n        .env(\"EXPECTED_FEATS\", \"1\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] common v1.0.0 (registry `dummy-registry`)\n[COMPILING] common v1.0.0\n[COMPILING] a v0.1.0 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/a[EXE]`\n\n\"#]])\n        .run();\n\n    // only normal+dev\n    p.cargo(\"test\").cwd(\"a\").env(\"EXPECTED_FEATS\", \"5\").run();\n\n    // Can specify features of packages from a different directory.\n    p.cargo(\"run -p b --features=ping\")\n        .cwd(\"a\")\n        .with_stdout_data(str![[r#\"\npong\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn install_resolve_behavior() {\n    // install honors the resolver behavior.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"f1\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            #[cfg(feature = \"f1\")]\n            compile_error!(\"f1 should not activate\");\n            \"#,\n        )\n        .publish();\n\n    Package::new(\"bar\", \"1.0.0\").dep(\"common\", \"1.0\").publish();\n\n    Package::new(\"foo\", \"1.0.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n            resolver = \"2\"\n\n            [target.'cfg(whatever)'.dependencies]\n            common = {version=\"1.0\", features=[\"f1\"]}\n\n            [dependencies]\n            bar = \"1.0\"\n\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .publish();\n\n    cargo_process(\"install foo\").run();\n}\n\n#[cargo_test]\nfn package_includes_resolve_behavior() {\n    // `cargo package` will inherit the correct resolve behavior.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\"]\n            resolver = \"2\"\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = [\"Zzz\"]\n            description = \"foo\"\n            license = \"MIT\"\n            homepage = \"https://example.com/\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\").cwd(\"a\").run();\n\n    let rewritten_toml = str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"a\"\nversion = \"0.1.0\"\nauthors = [\"Zzz\"]\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\nhomepage = \"https://example.com/\"\nreadme = false\nlicense = \"MIT\"\nresolver = \"2\"\n\n[lib]\nname = \"a\"\npath = \"src/lib.rs\"\n\n\"##]];\n\n    let f = File::open(&p.root().join(\"target/package/a-0.1.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"a-0.1.0.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\", \"Cargo.lock\"],\n        [(\"Cargo.toml\", rewritten_toml)],\n    );\n}\n\n#[cargo_test]\nfn tree_all() {\n    // `cargo tree` with the new feature resolver.\n    Package::new(\"log\", \"0.4.8\").feature(\"serde\", &[]).publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                resolver = \"2\"\n\n                [target.'cfg(whatever)'.dependencies]\n                log = {version=\"*\", features=[\"serde\"]}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"tree --target=all\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── log v0.4.8\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn shared_dep_same_but_dependencies() {\n    // Checks for a bug of nondeterminism. This scenario creates a shared\n    // dependency `dep` which needs to be built twice (once as normal, and\n    // once as a build dep). However, in both cases the flags to `dep` are the\n    // same, the only difference is what it links to. The normal dependency\n    // should link to `subdep` with the feature disabled, and the build\n    // dependency should link to it with it enabled. Crucially, the `--target`\n    // flag should not be specified, otherwise Unit.kind would be different\n    // and avoid the collision, and this bug won't manifest.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bin1\", \"bin2\"]\n                resolver = \"2\"\n            \"#,\n        )\n        .file(\n            \"bin1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bin1\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                dep = { path = \"../dep\" }\n            \"#,\n        )\n        .file(\"bin1/src/main.rs\", \"fn main() { dep::feat_func(); }\")\n        .file(\n            \"bin2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bin2\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [build-dependencies]\n                dep = { path = \"../dep\" }\n                subdep = { path = \"../subdep\", features = [\"feat\"] }\n            \"#,\n        )\n        .file(\"bin2/build.rs\", \"fn main() { dep::feat_func(); }\")\n        .file(\"bin2/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                subdep = { path = \"../subdep\" }\n            \"#,\n        )\n        .file(\n            \"dep/src/lib.rs\",\n            \"pub fn feat_func() { subdep::feat_func(); }\",\n        )\n        .file(\n            \"subdep/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"subdep\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                feat = []\n            \"#,\n        )\n        .file(\n            \"subdep/src/lib.rs\",\n            r#\"\n                pub fn feat_func() {\n                    #[cfg(feature = \"feat\")] println!(\"cargo::warning=feat: enabled\");\n                    #[cfg(not(feature = \"feat\"))] println!(\"cargo::warning=feat: not enabled\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --bin bin1 --bin bin2\")\n        // unordered because bin1 and bin2 build at the same time\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] subdep v0.1.0 ([ROOT]/foo/subdep)\n[COMPILING] dep v0.1.0 ([ROOT]/foo/dep)\n[COMPILING] bin1 v0.1.0 ([ROOT]/foo/bin1)\n[COMPILING] bin2 v0.1.0 ([ROOT]/foo/bin2)\n[WARNING] bin2@0.1.0: feat: enabled\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    p.process(p.bin(\"bin1\"))\n        .with_stdout_data(str![[r#\"\ncargo::warning=feat: not enabled\n\n\"#]])\n        .run();\n\n    // Make sure everything stays cached.\n    p.cargo(\"build -v --bin bin1 --bin bin2\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] subdep v0.1.0 ([ROOT]/foo/subdep)\n[FRESH] dep v0.1.0 ([ROOT]/foo/dep)\n[FRESH] bin1 v0.1.0 ([ROOT]/foo/bin1)\n[WARNING] bin2@0.1.0: feat: enabled\n[FRESH] bin2 v0.1.0 ([ROOT]/foo/bin2)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn test_proc_macro() {\n    // Running `cargo test` on a proc-macro, with a shared dependency that has\n    // different features.\n    //\n    // There was a bug where `shared` was built twice (once with feature \"B\"\n    // and once without), and both copies linked into the unit test. This\n    // would cause a type failure when used in an intermediate dependency\n    // (the-macro-support).\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"runtime\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                resolver = \"2\"\n\n                [dependencies]\n                the-macro = { path = \"the-macro\", features = ['a'] }\n                [build-dependencies]\n                shared = { path = \"shared\", features = ['b'] }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"the-macro/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"the-macro\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                proc-macro = true\n                test = false\n                [dependencies]\n                the-macro-support = { path = \"../the-macro-support\" }\n                shared = { path = \"../shared\" }\n                [dev-dependencies]\n                runtime = { path = \"..\" }\n                [features]\n                a = []\n            \"#,\n        )\n        .file(\n            \"the-macro/src/lib.rs\",\n            \"\n                fn _test() {\n                    the_macro_support::foo(shared::Foo);\n                }\n            \",\n        )\n        .file(\n            \"the-macro-support/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"the-macro-support\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [dependencies]\n                shared = { path = \"../shared\" }\n            \"#,\n        )\n        .file(\n            \"the-macro-support/src/lib.rs\",\n            \"\n                pub fn foo(_: shared::Foo) {}\n            \",\n        )\n        .file(\n            \"shared/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"shared\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [features]\n                b = []\n            \"#,\n        )\n        .file(\"shared/src/lib.rs\", \"pub struct Foo;\")\n        .build();\n    p.cargo(\"test --manifest-path the-macro/Cargo.toml\").run();\n}\n\n#[cargo_test]\nfn doc_optional() {\n    // Checks for a bug where `cargo doc` was failing with an inactive target\n    // that enables a shared optional dependency.\n    Package::new(\"spin\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(Dependency::new(\"spin\", \"1.0\").optional(true))\n        .publish();\n    // The enabler package enables the `spin` feature, which we don't want.\n    Package::new(\"enabler\", \"1.0.0\")\n        .feature_dep(\"bar\", \"1.0\", &[\"spin\"])\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                resolver = \"2\"\n\n                [target.'cfg(whatever)'.dependencies]\n                enabler = \"1.0\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] spin v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[DOCUMENTING] bar v1.0.0\n[CHECKING] bar v1.0.0\n[DOCUMENTING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn minimal_download() {\n    // Various checks that it only downloads the minimum set of dependencies\n    // needed in various situations.\n    //\n    // This checks several permutations of the different\n    // host_dep/dev_dep/itarget settings. These 3 are planned to be stabilized\n    // together, so there isn't much need to be concerned about how the behave\n    // independently. However, there are some cases where they do behave\n    // independently. Specifically:\n    //\n    // * `cargo test` forces dev_dep decoupling to be disabled.\n    // * `cargo tree --target=all` forces ignore_inactive_targets off and decouple_dev_deps off.\n    // * `cargo tree --target=all -e normal` forces ignore_inactive_targets off.\n    //\n    // However, `cargo tree` is a little weird because it downloads everything\n    // anyways.\n    //\n    // So to summarize the different permutations:\n    //\n    // dev_dep | host_dep | itarget | Notes\n    // --------|----------|---------|----------------------------\n    //         |          |         | -Zfeatures=compare (new resolver should behave same as old)\n    //         |          |    ✓    | This scenario should not happen.\n    //         |     ✓    |         | `cargo tree --target=all -Zfeatures=all`†\n    //         |     ✓    |    ✓    | `cargo test`\n    //    ✓    |          |         | This scenario should not happen.\n    //    ✓    |          |    ✓    | This scenario should not happen.\n    //    ✓    |     ✓    |         | `cargo tree --target=all -e normal -Z features=all`†\n    //    ✓    |     ✓    |    ✓    | A normal build.\n    //\n    // † — However, `cargo tree` downloads everything.\n    Package::new(\"normal\", \"1.0.0\").publish();\n    Package::new(\"normal_pm\", \"1.0.0\").publish();\n    Package::new(\"normal_opt\", \"1.0.0\").publish();\n    Package::new(\"dev_dep\", \"1.0.0\").publish();\n    Package::new(\"dev_dep_pm\", \"1.0.0\").publish();\n    Package::new(\"build_dep\", \"1.0.0\").publish();\n    Package::new(\"build_dep_pm\", \"1.0.0\").publish();\n    Package::new(\"build_dep_opt\", \"1.0.0\").publish();\n\n    Package::new(\"itarget_normal\", \"1.0.0\").publish();\n    Package::new(\"itarget_normal_pm\", \"1.0.0\").publish();\n    Package::new(\"itarget_dev_dep\", \"1.0.0\").publish();\n    Package::new(\"itarget_dev_dep_pm\", \"1.0.0\").publish();\n    Package::new(\"itarget_build_dep\", \"1.0.0\").publish();\n    Package::new(\"itarget_build_dep_pm\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                normal = \"1.0\"\n                normal_pm = \"1.0\"\n                normal_opt = { version = \"1.0\", optional = true }\n\n                [dev-dependencies]\n                dev_dep = \"1.0\"\n                dev_dep_pm = \"1.0\"\n\n                [build-dependencies]\n                build_dep = \"1.0\"\n                build_dep_pm = \"1.0\"\n                build_dep_opt = { version = \"1.0\", optional = true }\n\n                [target.'cfg(whatever)'.dependencies]\n                itarget_normal = \"1.0\"\n                itarget_normal_pm = \"1.0\"\n\n                [target.'cfg(whatever)'.dev-dependencies]\n                itarget_dev_dep = \"1.0\"\n                itarget_dev_dep_pm = \"1.0\"\n\n                [target.'cfg(whatever)'.build-dependencies]\n                itarget_build_dep = \"1.0\"\n                itarget_build_dep_pm = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    let clear = || {\n        paths::cargo_home().join(\"registry/cache\").rm_rf();\n        paths::cargo_home().join(\"registry/src\").rm_rf();\n        p.build_dir().rm_rf();\n    };\n\n    // none\n    // Should be the same as `-Zfeatures=all`\n    p.cargo(\"check -Zfeatures=compare\")\n        .masquerade_as_nightly_cargo(&[\"features=compare\"])\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 14 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] normal_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] normal v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] build_dep_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] build_dep v1.0.0 (registry `dummy-registry`)\n[COMPILING] build_dep v1.0.0\n[COMPILING] build_dep_pm v1.0.0\n[CHECKING] normal_pm v1.0.0\n[CHECKING] normal v1.0.0\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    clear();\n\n    // New behavior\n    switch_to_resolver_2(&p);\n\n    // all\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] normal_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] normal v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] build_dep_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] build_dep v1.0.0 (registry `dummy-registry`)\n[COMPILING] build_dep_pm v1.0.0\n[COMPILING] build_dep v1.0.0\n[CHECKING] normal_pm v1.0.0\n[CHECKING] normal v1.0.0\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    clear();\n\n    // This disables decouple_dev_deps.\n    p.cargo(\"test --no-run\")\n        .with_stderr_data(\n            str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] normal_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] normal v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] dev_dep_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] dev_dep v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] build_dep_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] build_dep v1.0.0 (registry `dummy-registry`)\n[COMPILING] build_dep_pm v1.0.0\n[COMPILING] build_dep v1.0.0\n[COMPILING] normal_pm v1.0.0\n[COMPILING] normal v1.0.0\n[COMPILING] dev_dep v1.0.0\n[COMPILING] dev_dep_pm v1.0.0\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    clear();\n\n    // This disables itarget, but leaves decouple_dev_deps enabled.\n    p.cargo(\"tree -e normal --target=all\")\n        .with_stderr_data(\n            str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] normal_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] normal v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] itarget_normal_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] itarget_normal v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] itarget_build_dep_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] itarget_build_dep v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] build_dep_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] build_dep v1.0.0 (registry `dummy-registry`)\n\n\"#]]\n            .unordered(),\n        )\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── itarget_normal v1.0.0\n├── itarget_normal_pm v1.0.0\n├── normal v1.0.0\n└── normal_pm v1.0.0\n\n\"#]])\n        .run();\n    clear();\n\n    // This disables itarget and decouple_dev_deps.\n    p.cargo(\"tree --target=all\")\n        .with_stderr_data(\n            str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] normal_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] normal v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] itarget_normal_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] itarget_normal v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] itarget_dev_dep_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] itarget_dev_dep v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] itarget_build_dep_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] itarget_build_dep v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] dev_dep_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] dev_dep v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] build_dep_pm v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] build_dep v1.0.0 (registry `dummy-registry`)\n\n\"#]]\n            .unordered(),\n        )\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── itarget_normal v1.0.0\n├── itarget_normal_pm v1.0.0\n├── normal v1.0.0\n└── normal_pm v1.0.0\n[build-dependencies]\n├── build_dep v1.0.0\n├── build_dep_pm v1.0.0\n├── itarget_build_dep v1.0.0\n└── itarget_build_dep_pm v1.0.0\n[dev-dependencies]\n├── dev_dep v1.0.0\n├── dev_dep_pm v1.0.0\n├── itarget_dev_dep v1.0.0\n└── itarget_dev_dep_pm v1.0.0\n\n\"#]])\n        .run();\n    clear();\n}\n\n#[cargo_test]\nfn pm_with_int_shared() {\n    // This is a somewhat complex scenario of a proc-macro in a workspace with\n    // an integration test where the proc-macro is used for other things, and\n    // *everything* is built at once (`--workspace --all-targets\n    // --all-features`). There was a bug where the UnitFor settings were being\n    // incorrectly computed based on the order that the graph was traversed.\n    //\n    // There are some uncertainties about exactly how proc-macros should behave\n    // with `--workspace`, see https://github.com/rust-lang/cargo/issues/8312.\n    //\n    // This uses a const-eval hack to do compile-time feature checking.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"pm\", \"shared\"]\n                resolver = \"2\"\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                pm = { path = \"../pm\" }\n                shared = { path = \"../shared\", features = [\"norm-feat\"] }\n            \"#,\n        )\n        .file(\n            \"foo/src/lib.rs\",\n            r#\"\n                // foo->shared always has both features set\n                const _CHECK: [(); 0] = [(); 0-!(shared::FEATS==3) as usize];\n            \"#,\n        )\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pm\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                shared = { path = \"../shared\", features = [\"host-feat\"] }\n            \"#,\n        )\n        .file(\n            \"pm/src/lib.rs\",\n            r#\"\n                // pm->shared always has just host\n                const _CHECK: [(); 0] = [(); 0-!(shared::FEATS==1) as usize];\n            \"#,\n        )\n        .file(\n            \"pm/tests/pm_test.rs\",\n            r#\"\n                // integration test gets both set\n                const _CHECK: [(); 0] = [(); 0-!(shared::FEATS==3) as usize];\n            \"#,\n        )\n        .file(\n            \"shared/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"shared\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                norm-feat = []\n                host-feat = []\n            \"#,\n        )\n        .file(\n            \"shared/src/lib.rs\",\n            r#\"\n                pub const FEATS: u32 = {\n                    if cfg!(feature=\"norm-feat\") && cfg!(feature=\"host-feat\") {\n                        3\n                    } else if cfg!(feature=\"norm-feat\") {\n                        2\n                    } else if cfg!(feature=\"host-feat\") {\n                        1\n                    } else {\n                        0\n                    }\n                };\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --workspace --all-targets --all-features -v\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] shared v0.1.0 ([ROOT]/foo/shared)\n[RUNNING] `rustc --crate-name shared [..]--crate-type lib [..]`\n[RUNNING] `rustc --crate-name shared [..]--crate-type lib [..]`\n[RUNNING] `rustc --crate-name shared [..]--test[..]`\n[COMPILING] pm v0.1.0 ([ROOT]/foo/pm)\n[RUNNING] `rustc --crate-name pm [..]--crate-type proc-macro[..]`\n[RUNNING] `rustc --crate-name pm [..]--test[..]`\n[COMPILING] foo v0.1.0 ([ROOT]/foo/foo)\n[RUNNING] `rustc --crate-name foo [..]--crate-type lib [..]`\n[RUNNING] `rustc --crate-name foo [..]--test[..]`\n[RUNNING] `rustc --crate-name pm_test [..]--test[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    // And again, should stay fresh.\n    p.cargo(\"build --workspace --all-targets --all-features -v\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] pm v0.1.0 ([ROOT]/foo/pm)\n[FRESH] foo v0.1.0 ([ROOT]/foo/foo)\n[FRESH] shared v0.1.0 ([ROOT]/foo/shared)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn doc_proc_macro() {\n    // Checks for a bug when documenting a proc-macro with a dependency. The\n    // doc unit builder was not carrying the \"for host\" setting through the\n    // dependencies, and the `pm-dep` dependency was causing a panic because\n    // it was looking for target features instead of host features.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                resolver = \"2\"\n\n                [dependencies]\n                pm = { path = \"pm\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pm\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                pm-dep = { path = \"../pm-dep\" }\n            \"#,\n        )\n        .file(\"pm/src/lib.rs\", \"\")\n        .file(\"pm-dep/Cargo.toml\", &basic_manifest(\"pm-dep\", \"0.1.0\"))\n        .file(\"pm-dep/src/lib.rs\", \"\")\n        .build();\n\n    // Unfortunately this cannot check the output because what it prints is\n    // nondeterministic. Sometimes it says \"Compiling pm-dep\" and sometimes\n    // \"Checking pm-dep\". This is because it is both building it and checking\n    // it in parallel (building so it can build the proc-macro, and checking\n    // so rustdoc can load it).\n    p.cargo(\"doc\").run();\n}\n\n#[cargo_test]\nfn edition_2021_default_2() {\n    // edition = 2021 defaults to v2 resolver.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"f1\", &[])\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(\n            Dependency::new(\"common\", \"1.0\")\n                .target(\"cfg(whatever)\")\n                .enable_features(&[\"f1\"]),\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                common = \"1.0\"\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // First without edition.\n    p.cargo(\"tree -f\")\n        .arg(\"{p} feats:{f}\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo) feats:\n├── bar v1.0.0 feats:\n└── common v1.0.0 feats:f1\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            cargo-features = [\"edition2021\"]\n\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2021\"\n\n            [dependencies]\n            common = \"1.0\"\n            bar = \"1.0\"\n        \"#,\n    );\n\n    // Importantly, this does not include `f1` on `common`.\n    p.cargo(\"tree -f\")\n        .arg(\"{p} feats:{f}\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo) feats:\n├── bar v1.0.0 feats:\n└── common v1.0.0 feats:\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn all_features_merges_with_features() {\n    Package::new(\"dep\", \"0.1.0\")\n        .feature(\"feat1\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(feature=\"feat1\")]\n                pub fn work() {\n                    println!(\"it works\");\n                }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [features]\n                a = []\n\n                [dependencies]\n                dep = \"0.1\"\n\n                [[example]]\n                name = \"ex\"\n                required-features = [\"a\", \"dep/feat1\"]\n            \"#,\n        )\n        .file(\n            \"examples/ex.rs\",\n            r#\"\n            fn main() {\n                dep::work();\n            }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"run --example ex --all-features --features dep/feat1\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`)\n[COMPILING] dep v0.1.0\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/examples/ex[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nit works\n\n\"#]])\n        .run();\n\n    switch_to_resolver_2(&p);\n\n    p.cargo(\"run --example ex --all-features --features dep/feat1\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/examples/ex[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nit works\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dep_with_optional_host_deps_activated() {\n    // To prevent regression like rust-lang/cargo#11330\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                serde = { path = \"serde\", features = [\"derive\", \"build\"] }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"serde/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"serde\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                serde_derive = { path = \"../serde_derive\", optional = true }\n\n                [build-dependencies]\n                serde_build = { path = \"../serde_build\", optional = true }\n\n                [features]\n                derive = [\"dep:serde_derive\"]\n                build = [\"dep:serde_build\"]\n            \"#,\n        )\n        .file(\"serde/src/lib.rs\", \"\")\n        .file(\"serde/build.rs\", \"fn main() {}\")\n        .file(\n            \"serde_derive/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"serde_derive\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\"serde_derive/src/lib.rs\", \"\")\n        .file(\n            \"serde_build/Cargo.toml\",\n            &basic_manifest(\"serde_build\", \"0.1.0\"),\n        )\n        .file(\"serde_build/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 3 packages to latest compatible versions\n[COMPILING] serde_build v0.1.0 ([ROOT]/foo/serde_build)\n[COMPILING] serde_derive v0.1.0 ([ROOT]/foo/serde_derive)\n[COMPILING] serde v0.1.0 ([ROOT]/foo/serde)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dont_unify_proc_macro_example_from_dependency() {\n    // See https://github.com/rust-lang/cargo/issues/13726\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2021\"\n\n                [dependencies]\n                pm_helper = { path = \"pm_helper\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"pm_helper/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pm_helper\"\n\n                [[example]]\n                name = \"pm\"\n                proc-macro = true\n                crate-type = [\"proc-macro\"]\n            \"#,\n        )\n        .file(\"pm_helper/src/lib.rs\", \"\")\n        .file(\"pm_helper/examples/pm.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] pm_helper v0.0.0 ([ROOT]/foo/pm_helper)\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/features_namespaced.rs",
    "content": "//! Tests for namespaced features.\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::{Dependency, Package, RegistryBuilder};\nuse cargo_test_support::str;\nuse cargo_test_support::{project, publish};\n\nuse super::features2::switch_to_resolver_2;\n\n#[cargo_test]\nfn dependency_with_crate_syntax() {\n    // Registry dependency uses dep: syntax.\n    Package::new(\"baz\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(Dependency::new(\"baz\", \"1.0\").optional(true))\n        .feature(\"feat\", &[\"dep:baz\"])\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = {version=\"1.0\", features=[\"feat\"]}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] baz v1.0.0\n[CHECKING] bar v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn namespaced_invalid_feature() {\n    // Specifies a feature that doesn't exist.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                bar = [\"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `bar` includes `baz` which is neither a dependency nor another feature\n\n  [HELP] a feature with a similar name exists: `bar`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn namespaced_invalid_dependency() {\n    // Specifies a dep:name that doesn't exist.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                bar = [\"dep:baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `bar` includes `dep:baz`, but `baz` is not listed as a dependency\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn namespaced_non_optional_dependency() {\n    // Specifies a dep:name for a dependency that is not optional.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                bar = [\"dep:baz\"]\n\n                [dependencies]\n                baz = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `bar` includes `dep:baz`, but `baz` is not an optional dependency\n  A non-optional dependency of the same name is defined; consider adding `optional = true` to its definition.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn namespaced_implicit_feature() {\n    // Backwards-compatible with old syntax.\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                bar = [\"baz\"]\n\n                [dependencies]\n                baz = { version = \"0.1\", optional = true }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check --features baz\")\n        .with_stderr_data(str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`)\n[CHECKING] baz v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn namespaced_shadowed_dep() {\n    // An optional dependency is not listed in the features table, and its\n    // implicit feature is overridden.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                baz = []\n\n                [dependencies]\n                baz = { version = \"0.1\", optional = true }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  optional dependency `baz` is not included in any feature\n  Make sure that `dep:baz` is included in one of features in the [features] table.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn namespaced_shadowed_non_optional() {\n    // Able to specify a feature with the same name as a required dependency.\n    Package::new(\"baz\", \"0.1.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                baz = []\n\n                [dependencies]\n                baz = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn namespaced_implicit_non_optional() {\n    // Includes a non-optional dependency in [features] table.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                bar = [\"baz\"]\n\n                [dependencies]\n                baz = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `bar` includes `baz`, but `baz` is not an optional dependency\n  A non-optional dependency of the same name is defined; consider adding `optional = true` to its definition.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn namespaced_same_name() {\n    // Explicitly listing an optional dependency in the [features] table.\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                baz = [\"dep:baz\"]\n\n                [dependencies]\n                baz = { version = \"0.1\", optional = true }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    if cfg!(feature=\"baz\") { println!(\"baz\"); }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n\n    p.cargo(\"run --features baz\")\n        .with_stderr_data(str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`)\n[COMPILING] baz v0.1.0\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nbaz\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_implicit_feature() {\n    // Using `dep:` will not create an implicit feature.\n    Package::new(\"regex\", \"1.0.0\").publish();\n    Package::new(\"lazy_static\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                regex = { version = \"1.0\", optional = true }\n                lazy_static = { version = \"1.0\", optional = true }\n\n                [features]\n                regex = [\"dep:regex\", \"dep:lazy_static\"]\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    if cfg!(feature = \"regex\") { println!(\"regex\"); }\n                    #[allow(unexpected_cfgs)]\n                    if cfg!(feature = \"lazy_static\") { println!(\"lazy_static\"); }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n\n    p.cargo(\"run --features regex\")\n        .with_stderr_data(\n            str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] regex v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] lazy_static v1.0.0 (registry `dummy-registry`)\n[COMPILING] regex v1.0.0\n[COMPILING] lazy_static v1.0.0\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]]\n            .unordered(),\n        )\n        .with_stdout_data(str![[r#\"\nregex\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --features lazy_static\")\n        .with_stderr_data(str![[r#\"\n[ERROR] package `foo v0.1.0 ([ROOT]/foo)` does not have feature `lazy_static`\n\n[HELP] an optional dependency with that name exists, but the `features` table includes it with the \"dep:\" syntax so it does not have an implicit feature with that name\nDependency `lazy_static` would be enabled by these features:\n\t- `regex`\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn crate_syntax_bad_name() {\n    // \"dep:bar\" = []\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version=\"1.0\", optional=true }\n\n                [features]\n                \"dep:bar\" = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --features dep:bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] feature named `dep:bar` is not allowed to start with `dep:`\n  --> Cargo.toml:11:17\n   |\n11 |                 \"dep:bar\" = []\n   |                 ^^^^^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn crate_syntax_in_dep() {\n    // features = [\"dep:baz\"]\n    Package::new(\"baz\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(Dependency::new(\"baz\", \"1.0\").optional(true))\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"1.0\", features = [\"dep:baz\"] }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `dep:baz` in dependency `bar` is not allowed to use explicit `dep:` syntax\n  If you want to enable an optional dependency, specify the name of the optional dependency without the `dep:` prefix, or specify a feature from the dependency's `[features]` table that enables the optional dependency.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn crate_syntax_cli() {\n    // --features dep:bar\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"1.0\", optional=true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --features dep:bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] feature `dep:bar` is not allowed to use explicit `dep:` syntax\n\n\"#]])\n        .run();\n\n    switch_to_resolver_2(&p);\n    p.cargo(\"check --features dep:bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] feature `dep:bar` is not allowed to use explicit `dep:` syntax\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn crate_required_features() {\n    // required-features = [\"dep:bar\"]\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"1.0\", optional=true }\n\n                [[bin]]\n                name = \"foo\"\n                required-features = [\"dep:bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ERROR] invalid feature `dep:bar` in required-features of target `foo`: `dep:` prefixed feature values are not allowed in required-features\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn json_exposed() {\n    // Checks that the implicit dep: values are exposed in JSON.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"1.0\", optional=true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"metadata --no-deps\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": \"{...}\",\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {\n        \"bar\": [\n          \"dep:bar\"\n        ]\n      },\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.1.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": \"{...}\",\n      \"version\": \"0.1.0\"\n    }\n  ],\n  \"resolve\": null,\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn crate_feature_with_explicit() {\n    // crate_name/feat_name syntax where crate_name already has a feature defined.\n    // NOTE: I don't know if this is actually ideal behavior.\n    Package::new(\"bar\", \"1.0.0\")\n        .feature(\"bar_feat\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(not(feature=\"bar_feat\"))]\n                compile_error!(\"bar_feat is not enabled\");\n            \"#,\n        )\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version=\"1.0\", optional = true }\n\n                [features]\n                f1 = [\"bar/bar_feat\"]\n                bar = [\"dep:bar\", \"f2\"]\n                f2 = []\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(not(feature=\"bar\"))]\n                compile_error!(\"bar should be enabled\");\n\n                #[cfg(not(feature=\"f2\"))]\n                compile_error!(\"f2 should be enabled\");\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check --features f1\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] bar v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn optional_explicit_without_crate() {\n    // \"feat\" syntax when there is no implicit \"feat\" feature because it is\n    // explicitly listed elsewhere.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"1.0\", optional = true }\n\n                [features]\n                feat1 = [\"dep:bar\"]\n                feat2 = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `feat2` includes `bar`, but `bar` is an optional dependency without an implicit feature\n  Use `dep:bar` to enable the dependency.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn tree() {\n    Package::new(\"baz\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(Dependency::new(\"baz\", \"1.0\").optional(true))\n        .feature(\"feat1\", &[\"dep:baz\"])\n        .feature(\"feat2\", &[])\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"1.0\", features = [\"feat1\"], optional=true }\n\n                [features]\n                a = [\"bar/feat2\"]\n                bar = [\"dep:bar\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e features\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --features a\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── bar feature \"default\"\n│   └── bar v1.0.0\n│       └── baz feature \"default\"\n│           └── baz v1.0.0\n└── bar feature \"feat1\"\n    └── bar v1.0.0 (*)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --features a -i bar\")\n        .with_stdout_data(str![[r#\"\nbar v1.0.0\n├── bar feature \"default\"\n│   └── foo v0.1.0 ([ROOT]/foo)\n│       ├── foo feature \"a\" (command-line)\n│       ├── foo feature \"bar\"\n│       │   └── foo feature \"a\" (command-line)\n│       └── foo feature \"default\" (command-line)\n├── bar feature \"feat1\"\n│   └── foo v0.1.0 ([ROOT]/foo) (*)\n└── bar feature \"feat2\"\n    └── foo feature \"a\" (command-line)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --features bar\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n├── bar feature \"default\"\n│   └── bar v1.0.0\n│       └── baz feature \"default\"\n│           └── baz v1.0.0\n└── bar feature \"feat1\"\n    └── bar v1.0.0 (*)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --features bar -i bar\")\n        .with_stdout_data(str![[r#\"\nbar v1.0.0\n├── bar feature \"default\"\n│   └── foo v0.1.0 ([ROOT]/foo)\n│       ├── foo feature \"bar\" (command-line)\n│       └── foo feature \"default\" (command-line)\n└── bar feature \"feat1\"\n    └── foo v0.1.0 ([ROOT]/foo) (*)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn tree_no_implicit() {\n    // tree without an implicit feature\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"1.0\", optional=true }\n\n                [features]\n                a = [\"dep:bar\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -e features\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --all-features\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar feature \"default\"\n    └── bar v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features -i bar --all-features\")\n        .with_stdout_data(str![[r#\"\nbar v1.0.0\n└── bar feature \"default\"\n    └── foo v0.1.0 ([ROOT]/foo)\n        ├── foo feature \"a\" (command-line)\n        └── foo feature \"default\" (command-line)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_no_implicit() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    // Does not include implicit features or dep: syntax on publish.\n    Package::new(\"opt-dep1\", \"1.0.0\").publish();\n    Package::new(\"opt-dep2\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                description = \"foo\"\n                license = \"MIT\"\n                homepage = \"https://example.com/\"\n\n                [dependencies]\n                opt-dep1 = { version = \"1.0\", optional = true }\n                opt-dep2 = { version = \"1.0\", optional = true }\n\n                [features]\n                feat = [\"opt-dep1\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] foo v0.1.0 ([ROOT]/foo)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.1.0 ([ROOT]/foo)\n[UPLOADED] foo v0.1.0 to registry `crates-io`\n[NOTE] waiting for foo v0.1.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.1.0 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    publish::validate_upload_with_contents(\n        r#\"\n        {\n          \"authors\": [],\n          \"badges\": {},\n          \"categories\": [],\n          \"deps\": [\n            {\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"normal\",\n              \"name\": \"opt-dep1\",\n              \"optional\": true,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"normal\",\n              \"name\": \"opt-dep2\",\n              \"optional\": true,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            }\n          ],\n          \"description\": \"foo\",\n          \"documentation\": null,\n          \"features\": {\n            \"feat\": [\"opt-dep1\"]\n          },\n          \"homepage\": \"https://example.com/\",\n          \"keywords\": [],\n          \"license\": \"MIT\",\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"foo\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": null,\n          \"rust_version\": null,\n          \"vers\": \"0.1.0\"\n          }\n        \"#,\n        \"foo-0.1.0.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\", \"Cargo.lock\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.1.0\"\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\nhomepage = \"https://example.com/\"\nreadme = false\nlicense = \"MIT\"\n\n[features]\nfeat = [\"opt-dep1\"]\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n[dependencies.opt-dep1]\nversion = \"1.0\"\noptional = true\n\n[dependencies.opt-dep2]\nversion = \"1.0\"\noptional = true\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn publish() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    // Publish behavior with explicit dep: syntax.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                description = \"foo\"\n                license = \"MIT\"\n                homepage = \"https://example.com/\"\n\n                [dependencies]\n                bar = { version = \"1.0\", optional = true }\n\n                [features]\n                feat1 = []\n                feat2 = [\"dep:bar\"]\n                feat3 = [\"feat2\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] foo v0.1.0 ([ROOT]/foo)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.1.0 ([ROOT]/foo)\n[COMPILING] foo v0.1.0 ([ROOT]/foo/target/package/foo-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.1.0 ([ROOT]/foo)\n[UPLOADED] foo v0.1.0 to registry `crates-io`\n[NOTE] waiting for foo v0.1.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.1.0 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    publish::validate_upload_with_contents(\n        r#\"\n        {\n          \"authors\": [],\n          \"badges\": {},\n          \"categories\": [],\n          \"deps\": [\n            {\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"normal\",\n              \"name\": \"bar\",\n              \"optional\": true,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            }\n          ],\n          \"description\": \"foo\",\n          \"documentation\": null,\n          \"features\": {\n            \"feat1\": [],\n            \"feat2\": [\"dep:bar\"],\n            \"feat3\": [\"feat2\"]\n          },\n          \"homepage\": \"https://example.com/\",\n          \"keywords\": [],\n          \"license\": \"MIT\",\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"foo\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": null,\n          \"rust_version\": null,\n          \"vers\": \"0.1.0\"\n          }\n        \"#,\n        \"foo-0.1.0.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\", \"Cargo.lock\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.1.0\"\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\nhomepage = \"https://example.com/\"\nreadme = false\nlicense = \"MIT\"\n\n[features]\nfeat1 = []\nfeat2 = [\"dep:bar\"]\nfeat3 = [\"feat2\"]\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n[dependencies.bar]\nversion = \"1.0\"\noptional = true\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn namespaced_feature_together() {\n    // Check for an error when `dep:` is used with `/`\n    Package::new(\"bar\", \"1.0.0\")\n        .feature(\"bar-feat\", &[])\n        .publish();\n\n    // Non-optional shouldn't have extra err.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n\n                [features]\n                f1 = [\"dep:bar/bar-feat\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `f1` includes `dep:bar/bar-feat` with both `dep:` and `/`\n  To fix this, remove the `dep:` prefix.\n\n\"#]])\n        .run();\n\n    // Weak dependency shouldn't have extra err.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = {version = \"1.0\", optional = true }\n\n            [features]\n            f1 = [\"dep:bar?/bar-feat\"]\n        \"#,\n    );\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `f1` includes `dep:bar?/bar-feat` with both `dep:` and `/`\n  To fix this, remove the `dep:` prefix.\n\n\"#]])\n        .run();\n\n    // If dep: is already specified, shouldn't have extra err.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = {version = \"1.0\", optional = true }\n\n            [features]\n            f1 = [\"dep:bar\", \"dep:bar/bar-feat\"]\n        \"#,\n    );\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `f1` includes `dep:bar/bar-feat` with both `dep:` and `/`\n  To fix this, remove the `dep:` prefix.\n\n\"#]])\n        .run();\n\n    // Only when the other 3 cases aren't true should it give some extra help.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = {version = \"1.0\", optional = true }\n\n            [features]\n            f1 = [\"dep:bar/bar-feat\"]\n        \"#,\n    );\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `f1` includes `dep:bar/bar-feat` with both `dep:` and `/`\n  To fix this, remove the `dep:` prefix.\n  If the intent is to avoid creating an implicit feature `bar` for an optional dependency, then consider replacing this with two values:\n      \"dep:bar\", \"bar/bar-feat\"\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dep_feature_when_hidden() {\n    // Checks for behavior with dep:bar and bar/feat syntax when there is no\n    // `bar` feature.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\", optional = true }\n\n                [features]\n                f1 = [\"dep:bar\"]\n                f2 = [\"bar/bar_feat\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                bar_feat = []\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree -f\")\n        .arg(\"{p} features={f}\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo) features=\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -F f1 -f\")\n        .arg(\"{p} features={f}\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo) features=f1\n└── bar v0.1.0 ([ROOT]/foo/bar) features=\n\n\"#]])\n        .with_stderr_data(\"\")\n        .run();\n\n    p.cargo(\"tree -F f2 -f\")\n        .arg(\"{p} features={f}\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo) features=f2\n└── bar v0.1.0 ([ROOT]/foo/bar) features=bar_feat\n\n\"#]])\n        .with_stderr_data(\"\")\n        .run();\n\n    p.cargo(\"tree --all-features -f\")\n        .arg(\"{p} features={f}\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo) features=f1,f2\n└── bar v0.1.0 ([ROOT]/foo/bar) features=bar_feat\n\n\"#]])\n        .with_stderr_data(\"\")\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/fetch.rs",
    "content": "//! Tests for the `cargo fetch` command.\n\nuse crate::prelude::*;\nuse crate::utils::cross_compile::disabled as cross_compile_disabled;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::rustc_host;\nuse cargo_test_support::{basic_manifest, cross_compile, project, str};\n\n#[cargo_test]\nfn no_deps() {\n    let p = project()\n        .file(\"src/main.rs\", \"mod a; fn main() {}\")\n        .file(\"src/a.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch\").with_stderr_data(\"\").run();\n}\n\n#[cargo_test]\nfn fetch_all_platform_dependencies_when_no_target_is_given() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    Package::new(\"d1\", \"1.2.3\")\n        .file(\"Cargo.toml\", &basic_manifest(\"d1\", \"1.2.3\"))\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    Package::new(\"d2\", \"0.1.2\")\n        .file(\"Cargo.toml\", &basic_manifest(\"d2\", \"0.1.2\"))\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let target = cross_compile::alternate();\n    let host = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [target.{host}.dependencies]\n                    d1 = \"1.2.3\"\n\n                    [target.{target}.dependencies]\n                    d2 = \"0.1.2\"\n                \"#,\n                host = host,\n                target = target\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch\")\n        .with_stderr_data(str![[r#\"\n...\n[DOWNLOADED] d1 v1.2.3 (registry `dummy-registry`)\n[DOWNLOADED] d2 v0.1.2 (registry `dummy-registry`)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fetch_platform_specific_dependencies() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    Package::new(\"d1\", \"1.2.3\")\n        .file(\"Cargo.toml\", &basic_manifest(\"d1\", \"1.2.3\"))\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    Package::new(\"d2\", \"0.1.2\")\n        .file(\"Cargo.toml\", &basic_manifest(\"d2\", \"0.1.2\"))\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let target = cross_compile::alternate();\n    let host = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [target.{host}.dependencies]\n                    d1 = \"1.2.3\"\n\n                    [target.{target}.dependencies]\n                    d2 = \"0.1.2\"\n                \"#,\n                host = host,\n                target = target\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch --target\")\n        .arg(&host)\n        .with_stderr_contains(\"[DOWNLOADED] d1 v1.2.3 [..]\")\n        .with_stderr_does_not_contain(\"[DOWNLOADED] d2 v0.1.2 [..]\")\n        .run();\n\n    p.cargo(\"fetch --target\")\n        .arg(&target)\n        .with_stderr_contains(\"[DOWNLOADED] d2 v0.1.2[..]\")\n        .with_stderr_does_not_contain(\"[DOWNLOADED] d1 v1.2.3 [..]\")\n        .run();\n}\n\n#[cargo_test]\nfn fetch_warning() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n            misspelled = \"wut\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused manifest key: package.misspelled\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/fix.rs",
    "content": "//! Tests for the `cargo fix` command.\n\nuse crate::prelude::*;\nuse crate::utils::tools;\nuse cargo::core::Edition;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::git::{self, init};\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::{Dependency, Package};\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_manifest, is_nightly, project};\n\n#[cargo_test]\nfn do_not_fix_broken_builds() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() {\n                    let mut x = 3;\n                    let _ = x;\n                }\n\n                pub fn foo2() {\n                    let _x: u32 = \"a\";\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] could not compile `foo` (lib) due to 1 previous error; 1 warning emitted\n...\n\"#]])\n        .run();\n    assert!(p.read_file(\"src/lib.rs\").contains(\"let mut x = 3;\"));\n}\n\n#[cargo_test]\nfn fix_broken_if_requested() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                fn foo(a: &u32) -> u32 { a + 1 }\n                pub fn bar() {\n                    foo(1);\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs --broken-code\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .run();\n}\n\n#[cargo_test]\nfn fix_path_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = 'bar' }\n\n                [workspace]\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate bar;\n\n                pub fn foo() -> u32 {\n                    let mut x = 3;\n                    x\n                }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                pub fn foo() -> u32 {\n                    let mut x = 3;\n                    x\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs -p foo -p bar\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[FIXED] bar/src/lib.rs (1 fix)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FIXED] src/lib.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn do_not_fix_non_relevant_deps() {\n    let p = project()\n        .no_manifest()\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = '../bar' }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                pub fn foo() -> u32 {\n                    let mut x = 3;\n                    x\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .cwd(\"foo\")\n        .run();\n\n    assert!(p.read_file(\"bar/src/lib.rs\").contains(\"mut\"));\n}\n\n#[cargo_test]\nfn prepare_for_2018() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![allow(unused)]\n\n                mod foo {\n                    pub const FOO: &str = \"fooo\";\n                }\n\n                mod bar {\n                    use ::foo::FOO;\n                }\n\n                fn main() {\n                    let x = ::foo::FOO;\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2015 edition to 2018\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2015 edition to 2018\n[FIXED] src/lib.rs (2 fixes)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n\n    println!(\"{}\", p.read_file(\"src/lib.rs\"));\n    assert!(p.read_file(\"src/lib.rs\").contains(\"use crate::foo::FOO;\"));\n    assert!(\n        p.read_file(\"src/lib.rs\")\n            .contains(\"let x = crate::foo::FOO;\")\n    );\n}\n\n#[cargo_test]\nfn fix_tests_with_edition() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![allow(ellipsis_inclusive_range_patterns)]\n                pub fn foo() {}\n\n                #[cfg(test)]\n                mod tests {\n                    #[test]\n                    fn it_works() {\n                        f();\n                    }\n                    fn f() -> bool {\n                        let x = 123;\n                        match x {\n                            0...100 => true,\n                            _ => false,\n                        }\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2018 edition to 2021\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2018 edition to 2021\n[FIXED] src/lib.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n    // Check that the test is fixed.\n    assert!(p.read_file(\"src/lib.rs\").contains(r#\"0..=100 => true,\"#));\n}\n\n#[cargo_test]\nfn fix_tests_with_edition_idioms() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                edition = '2018'\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() {}\n\n                #[cfg(test)]\n                mod tests {\n                    #[test]\n                    fn it_works() {\n                        f();\n                    }\n\n                    use std::any::Any;\n                    pub fn f() {\n                        let _x: Box<Any> = Box::new(3);\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --edition-idioms --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FIXED] src/lib.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n    // Check that the test is fixed.\n    assert!(p.read_file(\"src/lib.rs\").contains(\"Box<dyn Any>\"));\n}\n\n#[cargo_test]\nfn local_paths() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                use test::foo;\n\n                mod test {\n                    pub fn foo() {}\n                }\n\n                pub fn f() {\n                    foo();\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2015 edition to 2018\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2015 edition to 2018\n[FIXED] src/lib.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n\n    println!(\"{}\", p.read_file(\"src/lib.rs\"));\n    assert!(p.read_file(\"src/lib.rs\").contains(\"use crate::test::foo;\"));\n}\n\n#[cargo_test]\nfn upgrade_extern_crate() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = '2018'\n\n                [workspace]\n\n                [dependencies]\n                bar = { path = 'bar' }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![warn(rust_2018_idioms)]\n                extern crate bar;\n\n                use bar::bar;\n\n                pub fn foo() {\n                    ::bar::bar();\n                    bar();\n                }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FIXED] src/lib.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n    println!(\"{}\", p.read_file(\"src/lib.rs\"));\n    assert!(!p.read_file(\"src/lib.rs\").contains(\"extern crate\"));\n}\n\n#[cargo_test]\nfn specify_rustflags() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![allow(unused)]\n\n                mod foo {\n                    pub const FOO: &str = \"fooo\";\n                }\n\n                fn main() {\n                    let x = ::foo::FOO;\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .env(\"RUSTFLAGS\", \"-C linker=cc\")\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2015 edition to 2018\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2015 edition to 2018\n[FIXED] src/lib.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn no_changes_necessary() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn fixes_extra_mut() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() -> u32 {\n                    let mut x = 3;\n                    x\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FIXED] src/lib.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn fixes_two_missing_ampersands() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() -> u32 {\n                    let mut x = 3;\n                    let mut y = 3;\n                    x + y\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FIXED] src/lib.rs (2 fixes)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn tricky() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() -> u32 {\n                    let mut x = 3; let mut y = 3;\n                    x + y\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FIXED] src/lib.rs (2 fixes)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn preserve_line_endings() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"fn add(a: &u32) -> u32 { a + 1 }\\r\\n\\\n             pub fn foo() -> u32 { let mut x = 3; add(&x) }\\r\\n\\\n             \",\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .run();\n    assert!(p.read_file(\"src/lib.rs\").contains(\"\\r\\n\"));\n}\n\n#[cargo_test]\nfn fix_deny_warnings() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"#![deny(warnings)]\n             pub fn foo() { let mut x = 3; let _ = x; }\n            \",\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .run();\n}\n\n#[cargo_test]\nfn fix_deny_warnings_but_not_others() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n                #![deny(unused_mut)]\n\n                pub fn foo() -> u32 {\n                    let mut x = 3;\n                    x\n                }\n\n                pub fn bar() {\n                    #[allow(unused_mut)]\n                    let mut _y = 4;\n                }\n            \",\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .run();\n    assert!(!p.read_file(\"src/lib.rs\").contains(\"let mut x = 3;\"));\n    assert!(p.read_file(\"src/lib.rs\").contains(\"let mut _y = 4;\"));\n}\n\n#[cargo_test]\nfn fix_two_files() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n                pub mod bar;\n\n                pub fn foo() -> u32 {\n                    let mut x = 3;\n                    x\n                }\n            \",\n        )\n        .file(\n            \"src/bar.rs\",\n            \"\n                pub fn foo() -> u32 {\n                    let mut x = 3;\n                    x\n                }\n\n            \",\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FIXED] src/bar.rs (1 fix)\n[FIXED] src/lib.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    assert!(!p.read_file(\"src/lib.rs\").contains(\"let mut x = 3;\"));\n    assert!(!p.read_file(\"src/bar.rs\").contains(\"let mut x = 3;\"));\n}\n\n#[cargo_test]\nfn fixes_missing_ampersand() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() { let mut x = 3; let _ = x; }\")\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() { let mut x = 3; let _ = x; }\n\n                #[test]\n                pub fn foo2() { let mut x = 3; let _ = x; }\n            \"#,\n        )\n        .file(\n            \"tests/a.rs\",\n            r#\"\n                #[test]\n                pub fn foo() { let mut x = 3; let _ = x; }\n            \"#,\n        )\n        .file(\"examples/foo.rs\", \"fn main() { let mut x = 3; let _ = x; }\")\n        .file(\"build.rs\", \"fn main() { let mut x = 3; let _ = x; }\")\n        .build();\n\n    p.cargo(\"fix --all-targets --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .with_stdout_data(\"\")\n        // Don't assert number of fixes for `src/lib.rs`, as we don't know if we're\n        // fixing it once or twice! We run this all concurrently, and if we\n        // compile (and fix) in `--test` mode first, we get two fixes. Otherwise\n        // we'll fix one non-test thing, and then fix another one later in\n        // test mode.\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FIXED] build.rs (1 fix)\n[FIXED] src/lib.rs ([..]fix[..])\n[FIXED] src/main.rs (1 fix)\n[FIXED] examples/foo.rs (1 fix)\n[FIXED] tests/a.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n    p.cargo(\"check\").run();\n    p.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn fix_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                bar = []\n\n                [workspace]\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"bar\")]\n                pub fn foo() -> u32 { let mut x = 3; x }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\").run();\n    p.cargo(\"check\").run();\n    p.cargo(\"fix --features bar --allow-no-vcs\").run();\n    p.cargo(\"check --features bar\").run();\n}\n\n#[cargo_test]\nfn shows_warnings() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"#[deprecated] fn bar() {} pub fn foo() { let _ = bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] use of deprecated function `bar`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warns_if_no_vcs_detected() {\n    let p = project().file(\"src/lib.rs\", \"pub fn foo() {}\").build();\n\n    p.cargo(\"fix\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no VCS found for this package and `cargo fix` can potentially perform destructive changes; if you'd like to suppress this error pass `--allow-no-vcs`\n\n\"#]])\n        .run();\n    p.cargo(\"fix --allow-no-vcs\").run();\n}\n\n#[cargo_test]\nfn warns_about_dirty_working_directory() {\n    let p = git::new(\"foo\", |p| p.file(\"src/lib.rs\", \"pub fn foo() {}\"));\n\n    p.change_file(\"src/lib.rs\", \"\");\n\n    p.cargo(\"fix\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the working directory of this package has uncommitted changes, and `cargo fix` can potentially perform destructive changes; if you'd like to suppress this error pass `--allow-dirty`, or commit the changes to these files:\n\n  * src/lib.rs (dirty)\n\n\n\n\"#]])\n        .run();\n    p.cargo(\"fix --allow-dirty\").run();\n}\n\n#[cargo_test]\nfn warns_about_staged_working_directory() {\n    let (p, repo) = git::new_repo(\"foo\", |p| p.file(\"src/lib.rs\", \"pub fn foo() {}\"));\n\n    p.change_file(\"src/lib.rs\", \"pub fn bar() {}\");\n    git::add(&repo);\n\n    p.cargo(\"fix\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the working directory of this package has uncommitted changes, and `cargo fix` can potentially perform destructive changes; if you'd like to suppress this error pass `--allow-dirty`, or commit the changes to these files:\n\n  * src/lib.rs (staged)\n\n\n\n\"#]])\n        .run();\n    p.cargo(\"fix --allow-staged\").run();\n}\n\n#[cargo_test]\nfn errors_about_untracked_files() {\n    let mut git_project = project().at(\"foo\");\n    git_project = git_project.file(\"src/lib.rs\", \"pub fn foo() {}\");\n    let p = git_project.build();\n    let _ = init(&p.root());\n\n    p.cargo(\"fix\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the working directory of this package has uncommitted changes, and `cargo fix` can potentially perform destructive changes; if you'd like to suppress this error pass `--allow-dirty`, or commit the changes to these files:\n\n  * Cargo.toml (dirty)\n  * src/ (dirty)\n\n\n\n\"#]])\n        .run();\n    p.cargo(\"fix --allow-dirty\").run();\n}\n\n#[cargo_test]\nfn does_not_warn_about_clean_working_directory() {\n    let p = git::new(\"foo\", |p| p.file(\"src/lib.rs\", \"pub fn foo() {}\"));\n    p.cargo(\"fix\").run();\n}\n\n#[cargo_test]\nfn does_not_warn_about_dirty_ignored_files() {\n    let p = git::new(\"foo\", |p| {\n        p.file(\"src/lib.rs\", \"pub fn foo() {}\")\n            .file(\".gitignore\", \"bar\\n\")\n    });\n\n    p.change_file(\"bar\", \"\");\n\n    p.cargo(\"fix\").run();\n}\n\n#[cargo_test]\nfn do_not_fix_tests_by_default() {\n    let p = project()\n        .file(\"src/lib.rs\", \"pub fn foo() { let mut x = 3; let _ = x; }\")\n        .file(\"tests/foo.rs\", \"pub fn foo() { let mut x = 3; let _ = x; }\")\n        .build();\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .run();\n    assert!(!p.read_file(\"src/lib.rs\").contains(\"let mut x\"));\n    assert!(p.read_file(\"tests/foo.rs\").contains(\"let mut x\"));\n}\n\n#[cargo_test]\nfn prepare_for_unstable() {\n    // During the period where a new edition is coming up, but not yet stable,\n    // this test will verify that it cannot be migrated to on stable. If there\n    // is no next edition, it does nothing.\n    let next = match Edition::LATEST_UNSTABLE {\n        Some(next) => next,\n        None => {\n            eprintln!(\"Next edition is currently not available, skipping test.\");\n            return;\n        }\n    };\n    let latest_stable = Edition::LATEST_STABLE;\n    let prev = latest_stable.previous().unwrap();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"{}\"\n            \"#,\n                latest_stable\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // -j1 to make the error more deterministic (otherwise there can be\n    // multiple errors since they run in parallel).\n    p.cargo(\"fix --edition --allow-no-vcs -j1\")\n        .with_stderr_data(&format!(\"\\\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[WARNING] `src/lib.rs` is on the latest edition, but trying to migrate to edition {next}.\nEdition {next} is unstable and not allowed in this release, consider trying the nightly release channel.\n\nIf you are trying to migrate from the previous edition ({prev}), the\nprocess requires following these steps:\n\n1. Start with `edition = \\\"{prev}\\\"` in `Cargo.toml`\n2. Run `cargo fix --edition`\n3. Modify `Cargo.toml` to set `edition = \\\"{latest_stable}\\\"`\n4. Run `cargo build` or `cargo test` to verify the fixes worked\n\nMore details may be found at\nhttps://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html\n\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\", next=next, latest_stable=latest_stable, prev=prev))\n        .run();\n\n    if !is_nightly() {\n        // The rest of this test is fundamentally always nightly.\n        return;\n    }\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .masquerade_as_nightly_cargo(&[\"always_nightly\"])\n        .with_stderr_data(&format!(\n            \"\\\n[MIGRATING] Cargo.toml from {latest_stable} edition to {next}\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from {latest_stable} edition to {next}\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\",\n            latest_stable = latest_stable,\n            next = next,\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn prepare_for_latest_stable() {\n    // This is the stable counterpart of prepare_for_unstable.\n    let latest_stable = Edition::LATEST_STABLE;\n    let previous = latest_stable.previous().unwrap();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                edition = '{}'\n            \"#,\n                previous\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .with_stderr_data(&format!(\n            \"\\\n[MIGRATING] Cargo.toml from {previous} edition to {latest_stable}\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from {previous} edition to {latest_stable}\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\",\n        ))\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"fundamentally always nightly\")]\nfn prepare_for_already_on_latest_unstable() {\n    // During the period where a new edition is coming up, but not yet stable,\n    // this test will check what happens if you are already on the latest. If\n    // there is no next edition, it does nothing.\n    let next_edition = match Edition::LATEST_UNSTABLE {\n        Some(next) => next,\n        None => {\n            eprintln!(\"Next edition is currently not available, skipping test.\");\n            return;\n        }\n    };\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                cargo-features = [\"edition{}\"]\n\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                edition = '{}'\n            \"#,\n                next_edition, next_edition\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .masquerade_as_nightly_cargo(&[\"always_nightly\"])\n        .with_stderr_data(&format!(\n            \"\\\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[WARNING] `src/lib.rs` is already on the latest edition ({next_edition}), unable to migrate further\n...\n\",\n            next_edition = next_edition\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn prepare_for_already_on_latest_stable() {\n    // Stable counterpart of prepare_for_already_on_latest_unstable.\n    if Edition::LATEST_UNSTABLE.is_some() {\n        eprintln!(\"This test cannot run while the latest edition is unstable, skipping.\");\n        return;\n    }\n    let latest_stable = Edition::LATEST_STABLE;\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                edition = '{}'\n            \"#,\n                latest_stable\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .with_stderr_contains(\"[CHECKING] foo [..]\")\n        .with_stderr_contains(&format!(\n            \"\\\n[WARNING] `src/lib.rs` is already on the latest edition ({latest_stable}), unable to migrate further\n\",\n            latest_stable = latest_stable\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn fix_overlapping() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo<T>() {}\n                pub struct A;\n\n                pub mod bar {\n                    pub fn baz() {\n                        ::foo::<::A>();\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs --edition --lib\")\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2015 edition to 2018\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2015 edition to 2018\n[FIXED] src/lib.rs (2 fixes)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let contents = p.read_file(\"src/lib.rs\");\n    println!(\"{}\", contents);\n    assert!(contents.contains(\"crate::foo::<crate::A>()\"));\n}\n\n#[cargo_test]\nfn fix_idioms() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                edition = '2018'\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                use std::any::Any;\n                pub fn foo() {\n                    let _x: Box<Any> = Box::new(3);\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --edition-idioms --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FIXED] src/lib.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(p.read_file(\"src/lib.rs\").contains(\"Box<dyn Any>\"));\n}\n\n#[cargo_test]\nfn idioms_2015_ok() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"fix --edition-idioms --allow-no-vcs\").run();\n}\n\n#[cargo_test]\nfn shows_warnings_on_second_run_without_changes() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[deprecated]\n                fn bar() {}\n\n                pub fn foo() {\n                    let _ = bar();\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] use of deprecated function `bar`\n...\n\"#]])\n        .run();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] use of deprecated function `bar`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn shows_warnings_on_second_run_without_changes_on_multiple_targets() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[deprecated]\n                fn bar() {}\n\n                pub fn foo() {\n                    let _ = bar();\n                }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[deprecated]\n                fn bar() {}\n\n                fn main() {\n                    let _ = bar();\n                }\n            \"#,\n        )\n        .file(\n            \"tests/foo.rs\",\n            r#\"\n                #[deprecated]\n                fn bar() {}\n\n                #[test]\n                fn foo_test() {\n                    let _ = bar();\n                }\n            \"#,\n        )\n        .file(\n            \"tests/bar.rs\",\n            r#\"\n                #[deprecated]\n                fn bar() {}\n\n                #[test]\n                fn foo_test() {\n                    let _ = bar();\n                }\n            \"#,\n        )\n        .file(\n            \"examples/fooxample.rs\",\n            r#\"\n                #[deprecated]\n                fn bar() {}\n\n                fn main() {\n                    let _ = bar();\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs --all-targets\")\n        .with_stderr_data(\n            str![[r#\"\n...\n --> src/lib.rs:6:29\n...\n --> src/main.rs:6:29\n...\n --> examples/fooxample.rs:6:29\n...\n --> tests/foo.rs:7:29\n...\n --> tests/bar.rs:7:29\n...\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"fix --allow-no-vcs --all-targets\")\n        .with_stderr_data(\n            str![[r#\"\n...\n --> src/lib.rs:6:29\n...\n --> src/main.rs:6:29\n...\n --> examples/fooxample.rs:6:29\n...\n --> tests/bar.rs:7:29\n...\n --> tests/foo.rs:7:29\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn doesnt_rebuild_dependencies() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = 'bar' }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs -p foo\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"fix --allow-no-vcs -p foo\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn does_not_crash_with_rustc_wrapper() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"RUSTC_WRAPPER\", tools::echo_wrapper())\n        .run();\n    p.build_dir().rm_rf();\n    p.cargo(\"fix --allow-no-vcs --verbose\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", tools::echo_wrapper())\n        .run();\n}\n\n#[cargo_test]\nfn uses_workspace_wrapper_and_primary_wrapper_override() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs --verbose\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", tools::echo_wrapper())\n        .with_stderr_data(str![[r#\"\n...\nWRAPPER CALLED: rustc src/lib.rs --crate-name foo [..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn only_warn_for_relevant_crates() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                a = { path = 'a' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"a/src/lib.rs\",\n            \"\n                pub fn foo() {}\n                pub mod bar {\n                    use foo;\n                    pub fn baz() { foo() }\n                }\n            \",\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs --edition\")\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2015 edition to 2018\n[LOCKING] 1 package to latest compatible version\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2015 edition to 2018\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fix_to_broken_code() {\n    let p = project()\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                edition = \"2015\"\n                [workspace]\n            \"#,\n        )\n        .file(\n            \"foo/src/main.rs\",\n            r#\"\n                use std::env;\n                use std::fs;\n                use std::io::Write;\n                use std::path::{Path, PathBuf};\n                use std::process::{self, Command};\n\n                fn main() {\n                    // Ignore calls to things like --print=file-names and compiling build.rs.\n                    // Also compatible for rustc invocations with `@path` argfile.\n                    let is_lib_rs = env::args_os()\n                        .map(PathBuf::from)\n                        .flat_map(|p| if let Some(p) = p.to_str().unwrap_or_default().strip_prefix(\"@\") {\n                            fs::read_to_string(p).unwrap().lines().map(PathBuf::from).collect()\n                        } else {\n                            vec![p]\n                        })\n                        .any(|l| l == Path::new(\"src/lib.rs\"));\n                    if is_lib_rs {\n                        let path = PathBuf::from(env::var_os(\"OUT_DIR\").unwrap());\n                        let path = path.join(\"foo\");\n                        if path.exists() {\n                            panic!()\n                        } else {\n                            fs::File::create(&path).unwrap();\n                        }\n                    }\n\n                    let status = Command::new(\"rustc\")\n                        .args(env::args().skip(1))\n                        .status()\n                        .expect(\"failed to run rustc\");\n                    process::exit(status.code().unwrap_or(2));\n                }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = 'bar'\n                version = '0.1.0'\n                edition = \"2015\"\n                [workspace]\n            \"#,\n        )\n        .file(\"bar/build.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"pub fn foo() { let mut x = 3; let _ = x; }\")\n        .build();\n\n    // Build our rustc shim\n    p.cargo(\"build\").cwd(\"foo\").run();\n\n    // Attempt to fix code, but our shim will always fail the second compile\n    p.cargo(\"fix --allow-no-vcs --broken-code\")\n        .cwd(\"bar\")\n        .env(\"RUSTC\", p.root().join(\"foo/target/debug/foo\"))\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[ERROR] errors present after applying fixes to crate `bar`\n  |\n  = cause: thread 'main' ([..]) panicked at src/main.rs:23:29:\n           explicit panic\n           [NOTE] run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n[HELP] to report this as a bug, open an issue at https://github.com/rust-lang/rust/issues, quoting the full output of this command\n[HELP] to possibly apply more fixes, pass in the `--broken-code` flag\n[NOTE] original diagnostics will follow:\n...\n\n\"#]])\n        .run();\n\n    assert_e2e().eq(\n        p.read_file(\"bar/src/lib.rs\"),\n        str![\"pub fn foo() { let x = 3; let _ = x; }\"],\n    );\n}\n\n#[cargo_test]\nfn fix_with_common() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"tests/t1.rs\",\n            \"mod common; #[test] fn t1() { common::try(); }\",\n        )\n        .file(\n            \"tests/t2.rs\",\n            \"mod common; #[test] fn t2() { common::try(); }\",\n        )\n        .file(\"tests/common/mod.rs\", \"pub fn try() {}\")\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\").run();\n\n    assert_e2e().eq(\n        p.read_file(\"tests/common/mod.rs\"),\n        str![\"pub fn r#try() {}\"],\n    );\n}\n\n#[cargo_test]\nfn fix_in_existing_repo_weird_ignore() {\n    // Check that ignore doesn't ignore the repo itself.\n    let p = git::new(\"foo\", |project| {\n        project\n            .file(\"src/lib.rs\", \"\")\n            .file(\".gitignore\", \"foo\\ninner\\nCargo.lock\\ntarget\\n\")\n            .file(\"inner/file\", \"\")\n    });\n\n    p.cargo(\"fix\").run();\n    // This is questionable about whether it is the right behavior. It should\n    // probably be checking if any source file for the current project is\n    // ignored.\n    p.cargo(\"fix\")\n        .cwd(\"inner\")\n        .with_stderr_data(str![[r#\"\n[ERROR] no VCS found for this package and `cargo fix` can potentially perform destructive changes; if you'd like to suppress this error pass `--allow-no-vcs`\n\n\"#]])\n        .with_status(101)\n        .run();\n    p.cargo(\"fix\").cwd(\"src\").run();\n}\n\n#[cargo_test]\nfn fix_color_message() {\n    // Check that color appears in diagnostics.\n    let p = project()\n        .file(\"src/lib.rs\", \"std::compile_error!{\\\"color test\\\"}\")\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs --color=always\")\n        .with_stderr_data(\n            \"\\\n...\n[..]\\x1b[[..]\n...\n\",\n        )\n        .with_status(101)\n        .run();\n\n    p.cargo(\"fix --allow-no-vcs --color=never\")\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] color test\n...\n\"#]])\n        .with_stderr_does_not_contain(\"[..]\\x1b[[..]\")\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn edition_v2_resolver_report() {\n    // Show a report if the V2 resolver shows differences.\n    Package::new(\"common\", \"1.0.0\")\n        .feature(\"f1\", &[])\n        .feature(\"dev-feat\", &[])\n        .add_dep(Dependency::new(\"opt_dep\", \"1.0\").optional(true))\n        .publish();\n    Package::new(\"opt_dep\", \"1.0.0\").publish();\n\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(\n            Dependency::new(\"common\", \"1.0\")\n                .target(\"cfg(whatever)\")\n                .enable_features(&[\"f1\"]),\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                common = \"1.0\"\n                bar = \"1.0\"\n\n                [build-dependencies]\n                common = { version = \"1.0\", features = [\"opt_dep\"] }\n\n                [dev-dependencies]\n                common = { version=\"1.0\", features=[\"dev-feat\"] }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2018 edition to 2021\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] common v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] opt_dep v1.0.0 (registry `dummy-registry`)\n[NOTE] Switching to Edition 2021 will enable the use of the version 2 feature resolver in Cargo.\nThis may cause some dependencies to be built with fewer features enabled than previously.\nMore information about the resolver changes may be found at https://doc.rust-lang.org/nightly/edition-guide/rust-2021/default-cargo-resolver.html\nWhen building the following dependencies, the given features will no longer be used:\n\n  common v1.0.0 removed features: dev-feat, f1, opt_dep\n  common v1.0.0 (as host dependency) removed features: dev-feat, f1\n\nThe following differences only apply when building with dev-dependencies:\n\n  common v1.0.0 removed features: f1, opt_dep\n\n[CHECKING] opt_dep v1.0.0\n[CHECKING] common v1.0.0\n[CHECKING] bar v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2018 edition to 2021\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn rustfix_handles_multi_spans() {\n    // Checks that rustfix handles a single diagnostic with multiple\n    // suggestion spans (non_fmt_panic in this case).\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() {\n                    panic!(format!(\"hey\"));\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\").run();\n    assert!(p.read_file(\"src/lib.rs\").contains(r#\"panic!(\"hey\");\"#));\n}\n\n#[cargo_test]\nfn fix_edition_2021() {\n    // Can migrate 2021, even when lints are allowed.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![allow(ellipsis_inclusive_range_patterns)]\n\n                pub fn f() -> bool {\n                    let x = 123;\n                    match x {\n                        0...100 => true,\n                        _ => false,\n                    }\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2018 edition to 2021\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2018 edition to 2021\n[FIXED] src/lib.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(p.read_file(\"src/lib.rs\").contains(r#\"0..=100 => true,\"#));\n}\n\n#[cargo_test]\nfn fix_shared_cross_workspace() {\n    // Fixing a file that is shared between multiple packages in the same workspace.\n    // Make sure two processes don't try to fix the same file at the same time.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n            \"#,\n        )\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"pub mod shared;\")\n        // This will fix both unused and bare trait.\n        .file(\"foo/src/shared.rs\", \"pub fn fixme(x: Box<&Fn() -> ()>) {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                #[path=\"../../foo/src/shared.rs\"]\n                pub mod shared;\n            \"#,\n        )\n        .build();\n\n    // The output here can be either of these two, depending on who runs first:\n    //     [FIXED] bar/src/../../foo/src/shared.rs (2 fixes)\n    //     [FIXED] foo/src/shared.rs (2 fixes)\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo/foo)\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[FIXED] [..]foo/src/shared.rs (2 fixes)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    assert_e2e().eq(\n        &p.read_file(\"foo/src/shared.rs\"),\n        str![\"pub fn fixme(_x: Box<&dyn Fn() -> ()>) {}\"],\n    );\n}\n\n#[cargo_test]\nfn abnormal_exit() {\n    // rustc fails unexpectedly after applying fixes, should show some error information.\n    //\n    // This works with a proc-macro that runs twice:\n    // - First run (collect diagnostics pass): writes a file, exits normally.\n    // - Second run (verify diagnostics work): it detects the presence of the\n    //   file, removes the file, and aborts the process.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                pm = {path=\"pm\"}\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn f() {\n                    let mut x = 1;\n                    pm::crashme!();\n                }\n            \"#,\n        )\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pm\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"pm/src/lib.rs\",\n            r#\"\n                use proc_macro::TokenStream;\n                #[proc_macro]\n                pub fn crashme(_input: TokenStream) -> TokenStream {\n                    // Use a file to succeed on the first pass, and fail on the second.\n                    let p = std::env::var_os(\"ONCE_PATH\").unwrap();\n                    let check_path = std::path::Path::new(&p);\n                    if check_path.exists() {\n                        eprintln!(\"I'm not a diagnostic.\");\n                        std::fs::remove_file(check_path).unwrap();\n                        std::process::abort();\n                    } else {\n                        std::fs::write(check_path, \"\").unwrap();\n                        \"\".parse().unwrap()\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"fix --lib --allow-no-vcs\")\n        .env(\n            \"ONCE_PATH\",\n            paths::root().join(\"proc-macro-run-once\").to_str().unwrap(),\n        )\n        // \"signal: 6, SIGABRT: process abort signal\" on some platforms\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] pm v0.1.0 ([ROOT]/foo/pm)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[ERROR] errors present after applying fixes to crate `foo`\n  |\n  = cause: I'm not a diagnostic.\n  = cause: rustc exited abnormally: [..]\n[HELP] to report this as a bug, open an issue at https://github.com/rust-lang/rust/issues, quoting the full output of this command\n[HELP] to possibly apply more fixes, pass in the `--broken-code` flag\n[NOTE] original diagnostics will follow:\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fix_with_run_cargo_in_proc_macros() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                use proc_macro::*;\n\n                #[proc_macro]\n                pub fn foo(_input: TokenStream) -> TokenStream {\n                    let output = std::process::Command::new(env!(\"CARGO\"))\n                        .args(&[\"metadata\", \"--format-version=1\"])\n                        .output()\n                        .unwrap();\n                    eprintln!(\"{}\", std::str::from_utf8(&output.stderr).unwrap());\n                    println!(\"{}\", std::str::from_utf8(&output.stdout).unwrap());\n                    \"\".parse().unwrap()\n                }\n            \"#,\n        )\n        .file(\n            \"src/bin/main.rs\",\n            r#\"\n                use foo::foo;\n\n                fn main() {\n                    foo!(\"bar\")\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"fix --allow-no-vcs\")\n        .with_stderr_does_not_contain(\"error: could not find .rs file in rustc args\")\n        .run();\n}\n\n#[cargo_test]\nfn non_edition_lint_migration() {\n    // Migrating to a new edition where a non-edition lint causes problems.\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                // This is only used in a test.\n                // To be correct, this should be gated on #[cfg(test)], but\n                // sometimes people don't do that. If the unused_imports\n                // lint removes this, then the unittest will fail to compile.\n                use std::str::from_utf8;\n\n                pub mod foo {\n                    pub const FOO: &[u8] = &[102, 111, 111];\n                }\n\n                #[test]\n                fn example() {\n                    assert_eq!(\n                        from_utf8(::foo::FOO), Ok(\"foo\")\n                    );\n                }\n            \"#,\n        )\n        .build();\n    // Check that it complains about an unused import.\n    p.cargo(\"check --lib\")\n        .with_stderr_data(str![[r#\"\n...\n[..]use std::str::from_utf8;\n...\n  = [NOTE] `#[warn(unused_imports)]` [..]on by default\n...\n\"#]])\n        .run();\n    p.cargo(\"fix --edition --allow-no-vcs\").run();\n    let contents = p.read_file(\"src/lib.rs\");\n    // Check it does not remove the \"unused\" import.\n    assert!(contents.contains(\"use std::str::from_utf8;\"));\n    // Check that it made the edition migration.\n    assert!(contents.contains(\"from_utf8(crate::foo::FOO)\"));\n}\n\n#[cargo_test]\nfn fix_in_dependency() {\n    // Tests what happens if rustc emits a suggestion to modify a file from a\n    // dependency in cargo's home directory. This should never happen, and\n    // indicates a bug in rustc. However, there are several known bugs in\n    // rustc where it does this (often involving macros), so `cargo fix` has a\n    // guard that says if the suggestion points to some location in CARGO_HOME\n    // to not apply it.\n    //\n    // See https://github.com/rust-lang/cargo/issues/9857 for some other\n    // examples.\n    //\n    // This test uses a simulated rustc which replays a suggestion via a JSON\n    // message that points into CARGO_HOME. This does not use the real rustc\n    // because as the bugs are fixed in the real rustc, that would cause this\n    // test to stop working.\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[macro_export]\n                macro_rules! m {\n                    ($i:tt) => {\n                        let $i = 1;\n                    };\n                }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() {\n                    bar::m!(abc);\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"fetch\").run();\n\n    // The path in CARGO_HOME.\n    let bar_path = std::fs::read_dir(paths::home().join(\".cargo/registry/src\"))\n        .unwrap()\n        .next()\n        .unwrap()\n        .unwrap()\n        .path();\n    // Since this is a substitution into a Rust string (representing a JSON\n    // string), deal with backslashes like on Windows.\n    let bar_path_str = bar_path.to_str().unwrap().replace(\"\\\\\", \"/\");\n\n    // This is a fake rustc that will emit a JSON message when the `foo` crate\n    // builds that tells cargo to modify a file it shouldn't.\n    let rustc = project()\n        .at(\"rustc-replay\")\n        .file(\"Cargo.toml\", &basic_manifest(\"rustc-replay\", \"1.0.0\"))\n        .file(\"src/main.rs\",\n            &r##\"\n                fn main() {\n                    let pkg_name = match std::env::var(\"CARGO_PKG_NAME\") {\n                        Ok(pkg_name) => pkg_name,\n                        Err(_) => {\n                            let r = std::process::Command::new(\"rustc\")\n                                .args(std::env::args_os().skip(1))\n                                .status();\n                            std::process::exit(r.unwrap().code().unwrap_or(2));\n                        }\n                    };\n                    if pkg_name == \"foo\" {\n                        eprintln!(\"{}\", r#\"{\n                          \"$message_type\": \"diagnostic\",\n                          \"message\": \"unused variable: `abc`\",\n                          \"code\":\n                          {\n                            \"code\": \"unused_variables\",\n                            \"explanation\": null\n                          },\n                          \"level\": \"warning\",\n                          \"spans\":\n                          [\n                            {\n                              \"file_name\": \"__BAR_PATH__/bar-1.0.0/src/lib.rs\",\n                              \"byte_start\": 127,\n                              \"byte_end\": 129,\n                              \"line_start\": 5,\n                              \"line_end\": 5,\n                              \"column_start\": 29,\n                              \"column_end\": 31,\n                              \"is_primary\": true,\n                              \"text\":\n                              [\n                                {\n                                  \"text\": \"                        let $i = 1;\",\n                                  \"highlight_start\": 29,\n                                  \"highlight_end\": 31\n                                }\n                              ],\n                              \"label\": null,\n                              \"suggested_replacement\": null,\n                              \"suggestion_applicability\": null,\n                              \"expansion\": null\n                            }\n                          ],\n                          \"children\":\n                          [\n                            {\n                              \"message\": \"`#[warn(unused_variables)]` on by default\",\n                              \"code\": null,\n                              \"level\": \"note\",\n                              \"spans\":\n                              [],\n                              \"children\":\n                              [],\n                              \"rendered\": null\n                            },\n                            {\n                              \"message\": \"if this is intentional, prefix it with an underscore\",\n                              \"code\": null,\n                              \"level\": \"help\",\n                              \"spans\":\n                              [\n                                {\n                                  \"file_name\": \"__BAR_PATH__/bar-1.0.0/src/lib.rs\",\n                                  \"byte_start\": 127,\n                                  \"byte_end\": 129,\n                                  \"line_start\": 5,\n                                  \"line_end\": 5,\n                                  \"column_start\": 29,\n                                  \"column_end\": 31,\n                                  \"is_primary\": true,\n                                  \"text\":\n                                  [\n                                    {\n                                      \"text\": \"                        let $i = 1;\",\n                                      \"highlight_start\": 29,\n                                      \"highlight_end\": 31\n                                    }\n                                  ],\n                                  \"label\": null,\n                                  \"suggested_replacement\": \"_abc\",\n                                  \"suggestion_applicability\": \"MachineApplicable\",\n                                  \"expansion\": null\n                                }\n                              ],\n                              \"children\":\n                              [],\n                              \"rendered\": null\n                            }\n                          ],\n                          \"rendered\": \"warning: unused variable: `abc`\\n --> __BAR_PATH__/bar-1.0.0/src/lib.rs:5:29\\n  |\\n5 |                         let $i = 1;\\n  |                             ^^ help: if this is intentional, prefix it with an underscore: `_abc`\\n  |\\n  = note: `#[warn(unused_variables)]` on by default\\n\\n\"\n                        }\"#.replace(\"\\n\", \"\"));\n                    }\n                }\n            \"##.replace(\"__BAR_PATH__\", &bar_path_str))\n        .build();\n    rustc.cargo(\"build\").run();\n    let rustc_bin = rustc.bin(\"rustc-replay\");\n\n    // The output here should not say `Fixed`.\n    //\n    // It is OK to compare the full diagnostic output here because the text is\n    // hard-coded in rustc-replay. Normally tests should not be checking the\n    // compiler output.\n    p.cargo(\"fix --lib --allow-no-vcs\")\n        .env(\"RUSTC\", &rustc_bin)\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[WARNING] unused variable: `abc`\n --> [ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/src/lib.rs:5:29\n  |\n5 |                         let $i = 1;\n  |                             ^^ [HELP] if this is intentional, prefix it with an underscore: `_abc`\n  |\n  = [NOTE] `#[warn(unused_variables)]` on by default\n\n[WARNING] `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply 1 suggestion)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fix_in_rust_src() {\n    // Tests what happens if rustc emits a suggestion to modify the standard\n    // library in rust source. This should never happen, and indicates a bug in\n    // rustc. However, there are several known bugs in rustc where it does this\n    // (often involving macros), so `cargo fix` has a guard that says if the\n    // suggestion points to rust source under sysroot to not apply it.\n    //\n    // See https://github.com/rust-lang/cargo/issues/9857 for some other\n    // examples.\n    //\n    // This test uses a simulated rustc which replays a suggestion via a JSON\n    // message that points into rust-src. This does not use the real rustc\n    // because as the bugs are fixed in the real rustc, that would cause this\n    // test to stop working.\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {\n                    if true {\n                        writeln!(w, \"`;?` here ->\")?;\n                    } else {\n                        writeln!(w, \"but not here\")\n                    }\n                    Ok(())\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"fetch\").run();\n\n    // Since this is a substitution into a Rust string (representing a JSON\n    // string), deal with backslashes like on Windows.\n    let sysroot = paths::sysroot().replace(\"\\\\\", \"/\");\n\n    // This is a fake rustc that will emit a JSON message when the `foo` crate\n    // builds that tells cargo to modify a file it shouldn't.\n    let rustc = project()\n        .at(\"rustc-replay\")\n        .file(\"Cargo.toml\", &basic_manifest(\"rustc-replay\", \"1.0.0\"))\n        .file(\"src/main.rs\",\n            &r##\"\n                fn main() {\n                    let pkg_name = match std::env::var(\"CARGO_PKG_NAME\") {\n                        Ok(pkg_name) => pkg_name,\n                        Err(_) => {\n                            let r = std::process::Command::new(\"rustc\")\n                                .args(std::env::args_os().skip(1))\n                                .status();\n                            std::process::exit(r.unwrap().code().unwrap_or(2));\n                        }\n                    };\n                    if pkg_name == \"foo\" {\n                        eprintln!(\"{}\", r#\"{\n    \"$message_type\": \"diagnostic\",\n    \"message\": \"mismatched types\",\n    \"code\":\n    {\n        \"code\": \"E0308\",\n        \"explanation\": \"Expected type did not match the received type.\\n\\nErroneous code examples:\\n\\n```compile_fail,E0308\\nfn plus_one(x: i32) -> i32 {\\n    x + 1\\n}\\n\\nplus_one(\\\"Not a number\\\");\\n//       ^^^^^^^^^^^^^^ expected `i32`, found `&str`\\n\\nif \\\"Not a bool\\\" {\\n// ^^^^^^^^^^^^ expected `bool`, found `&str`\\n}\\n\\nlet x: f32 = \\\"Not a float\\\";\\n//     ---   ^^^^^^^^^^^^^ expected `f32`, found `&str`\\n//     |\\n//     expected due to this\\n```\\n\\nThis error occurs when an expression was used in a place where the compiler\\nexpected an expression of a different type. It can occur in several cases, the\\nmost common being when calling a function and passing an argument which has a\\ndifferent type than the matching type in the function declaration.\\n\"\n    },\n    \"level\": \"error\",\n    \"spans\":\n    [\n        {\n            \"file_name\": \"__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs\",\n            \"byte_start\": 23568,\n            \"byte_end\": 23617,\n            \"line_start\": 670,\n            \"line_end\": 670,\n            \"column_start\": 9,\n            \"column_end\": 58,\n            \"is_primary\": true,\n            \"text\":\n            [\n                {\n                    \"text\": \"        $dst.write_fmt($crate::format_args_nl!($($arg)*))\",\n                    \"highlight_start\": 9,\n                    \"highlight_end\": 58\n                }\n            ],\n            \"label\": \"expected `()`, found `Result<(), Error>`\",\n            \"suggested_replacement\": null,\n            \"suggestion_applicability\": null,\n            \"expansion\":\n            {\n                \"span\":\n                {\n                    \"file_name\": \"lib.rs\",\n                    \"byte_start\": 144,\n                    \"byte_end\": 171,\n                    \"line_start\": 5,\n                    \"line_end\": 5,\n                    \"column_start\": 9,\n                    \"column_end\": 36,\n                    \"is_primary\": false,\n                    \"text\":\n                    [\n                        {\n                            \"text\": \"        writeln!(w, \\\"but not here\\\")\",\n                            \"highlight_start\": 9,\n                            \"highlight_end\": 36\n                        }\n                    ],\n                    \"label\": null,\n                    \"suggested_replacement\": null,\n                    \"suggestion_applicability\": null,\n                    \"expansion\": null\n                },\n                \"macro_decl_name\": \"writeln!\",\n                \"def_site_span\":\n                {\n                    \"file_name\": \"__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs\",\n                    \"byte_start\": 23434,\n                    \"byte_end\": 23454,\n                    \"line_start\": 665,\n                    \"line_end\": 665,\n                    \"column_start\": 1,\n                    \"column_end\": 21,\n                    \"is_primary\": false,\n                    \"text\":\n                    [\n                        {\n                            \"text\": \"macro_rules! writeln {\",\n                            \"highlight_start\": 1,\n                            \"highlight_end\": 21\n                        }\n                    ],\n                    \"label\": null,\n                    \"suggested_replacement\": null,\n                    \"suggestion_applicability\": null,\n                    \"expansion\": null\n                }\n            }\n        },\n        {\n            \"file_name\": \"lib.rs\",\n            \"byte_start\": 75,\n            \"byte_end\": 177,\n            \"line_start\": 2,\n            \"line_end\": 6,\n            \"column_start\": 5,\n            \"column_end\": 6,\n            \"is_primary\": false,\n            \"text\":\n            [\n                {\n                    \"text\": \"    if true {\",\n                    \"highlight_start\": 5,\n                    \"highlight_end\": 14\n                },\n                {\n                    \"text\": \"        writeln!(w, \\\"`;?` here ->\\\")?;\",\n                    \"highlight_start\": 1,\n                    \"highlight_end\": 38\n                },\n                {\n                    \"text\": \"    } else {\",\n                    \"highlight_start\": 1,\n                    \"highlight_end\": 13\n                },\n                {\n                    \"text\": \"        writeln!(w, \\\"but not here\\\")\",\n                    \"highlight_start\": 1,\n                    \"highlight_end\": 36\n                },\n                {\n                    \"text\": \"    }\",\n                    \"highlight_start\": 1,\n                    \"highlight_end\": 6\n                }\n            ],\n            \"label\": \"expected this to be `()`\",\n            \"suggested_replacement\": null,\n            \"suggestion_applicability\": null,\n            \"expansion\": null\n        }\n    ],\n    \"children\":\n    [\n        {\n            \"message\": \"use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller\",\n            \"code\": null,\n            \"level\": \"help\",\n            \"spans\":\n            [\n                {\n                    \"file_name\": \"__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs\",\n                    \"byte_start\": 23617,\n                    \"byte_end\": 23617,\n                    \"line_start\": 670,\n                    \"line_end\": 670,\n                    \"column_start\": 58,\n                    \"column_end\": 58,\n                    \"is_primary\": true,\n                    \"text\":\n                    [\n                        {\n                            \"text\": \"        $dst.write_fmt($crate::format_args_nl!($($arg)*))\",\n                            \"highlight_start\": 58,\n                            \"highlight_end\": 58\n                        }\n                    ],\n                    \"label\": null,\n                    \"suggested_replacement\": \"?\",\n                    \"suggestion_applicability\": \"HasPlaceholders\",\n                    \"expansion\":\n                    {\n                        \"span\":\n                        {\n                            \"file_name\": \"lib.rs\",\n                            \"byte_start\": 144,\n                            \"byte_end\": 171,\n                            \"line_start\": 5,\n                            \"line_end\": 5,\n                            \"column_start\": 9,\n                            \"column_end\": 36,\n                            \"is_primary\": false,\n                            \"text\":\n                            [\n                                {\n                                    \"text\": \"        writeln!(w, \\\"but not here\\\")\",\n                                    \"highlight_start\": 9,\n                                    \"highlight_end\": 36\n                                }\n                            ],\n                            \"label\": null,\n                            \"suggested_replacement\": null,\n                            \"suggestion_applicability\": null,\n                            \"expansion\": null\n                        },\n                        \"macro_decl_name\": \"writeln!\",\n                        \"def_site_span\":\n                        {\n                            \"file_name\": \"__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs\",\n                            \"byte_start\": 23434,\n                            \"byte_end\": 23454,\n                            \"line_start\": 665,\n                            \"line_end\": 665,\n                            \"column_start\": 1,\n                            \"column_end\": 21,\n                            \"is_primary\": false,\n                            \"text\":\n                            [\n                                {\n                                    \"text\": \"macro_rules! writeln {\",\n                                    \"highlight_start\": 1,\n                                    \"highlight_end\": 21\n                                }\n                            ],\n                            \"label\": null,\n                            \"suggested_replacement\": null,\n                            \"suggestion_applicability\": null,\n                            \"expansion\": null\n                        }\n                    }\n                }\n            ],\n            \"children\":\n            [],\n            \"rendered\": null\n        }\n    ],\n    \"rendered\": \"error[E0308]: mismatched types\\n --> lib.rs:5:9\\n  |\\n2 | /     if true {\\n3 | |         writeln!(w, \\\"`;?` here ->\\\")?;\\n4 | |     } else {\\n5 | |         writeln!(w, \\\"but not here\\\")\\n  | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>`\\n6 | |     }\\n  | |_____- expected this to be `()`\\n  |\\n  = note: expected unit type `()`\\n                  found enum `Result<(), std::fmt::Error>`\\n  = note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)\\nhelp: consider using a semicolon here\\n  |\\n6 |     };\\n  |      +\\nhelp: you might have meant to return this value\\n  |\\n5 |         return writeln!(w, \\\"but not here\\\");\\n  |         ++++++                            +\\nhelp: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller\\n --> __SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs:670:58\\n  |\\n67|         $dst.write_fmt($crate::format_args_nl!($($arg)*))?\\n  |                                                          +\\n\\n\"\n}\"#.replace(\"\\n\", \"\"));\n\n                        std::process::exit(2);\n                    }\n                }\n            \"##.replace(\"__SYSROOT__\", &sysroot))\n        .build();\n    rustc.cargo(\"build\").run();\n    let rustc_bin = rustc.bin(\"rustc-replay\");\n\n    // The output here should not say `Fixed`.\n    //\n    // It is OK to compare the full diagnostic output here because the text is\n    // hard-coded in rustc-replay. Normally tests should not be checking the\n    // compiler output.\n    p.cargo(\"fix --lib --allow-no-vcs --broken-code\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .env(\"RUSTC\", &rustc_bin)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\nerror[E0308]: mismatched types\n --> lib.rs:5:9\n  |\n2 | /     if true {\n3 | |         writeln!(w, \"`;?` here ->\")?;\n4 | |     } else {\n5 | |         writeln!(w, \"but not here\")\n  | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>`\n6 | |     }\n  | |_____- expected this to be `()`\n  |\n  = [NOTE] expected unit type `()`\n                  found enum `Result<(), std::fmt::Error>`\n  = [NOTE] this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)\n[HELP] consider using a semicolon here\n  |\n6 |     };\n  |      +\n[HELP] you might have meant to return this value\n  |\n5 |         return writeln!(w, \"but not here\");\n  |         ++++++                            +\n[HELP] use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller\n --> [..]/lib/rustlib/src/rust/library/core/src/macros/mod.rs:670:58\n  |\n67|         $dst.write_fmt($crate::format_args_nl!($($arg)*))?\n  |                                                          +\n\n[ERROR] could not compile `foo` (lib) due to 1 previous error\n\n\"#]])\n        .run();\n}\n\n// See <https://github.com/rust-lang/cargo/issues/13027>\n#[cargo_test]\nfn fix_only_once_for_duplicates() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\nmacro_rules! foo {\n    () => {\n        let x = Box::new(1);\n        std::mem::forget(&x);\n    };\n}\n\nfn main() {\n    foo!();\n    foo!();\n}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"fix --allow-no-vcs\")\n        .env(\"__CARGO_FIX_YOLO\", \"1\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FIXED] src/main.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert_e2e().eq(\n        p.read_file(\"src/main.rs\"),\n        str![[r#\"\n\nmacro_rules! foo {\n    () => {\n        let x = Box::new(1);\n        let _ = &x;\n    };\n}\n\nfn main() {\n    foo!();\n    foo!();\n}\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn migrate_project_to_package() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n# Before project\n[ project ] # After project header\n# After project header line\nname = \"foo\"\nedition = \"2021\"\n# After project table\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2021 edition to 2024\n[FIXED] Cargo.toml (1 fix)\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2021 edition to 2024\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert_e2e().eq(\n        p.read_file(\"Cargo.toml\"),\n        str![[r#\"\n\n# Before project\n[ package ] # After project header\n# After project header line\nname = \"foo\"\nedition = \"2021\"\n# After project table\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn migrate_removes_project() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n# Before package\n[ package ] # After package header\n# After package header line\nname = \"foo\"\nedition = \"2021\"\n# After package table\n\n# Before project\n[ project ] # After project header\n# After project header line\nname = \"foo\"\nedition = \"2021\"\n# After project table\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2021 edition to 2024\n[FIXED] Cargo.toml (1 fix)\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2021 edition to 2024\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert_e2e().eq(\n        p.read_file(\"Cargo.toml\"),\n        str![[r#\"\n\n# Before package\n[ package ] # After package header\n# After package header line\nname = \"foo\"\nedition = \"2021\"\n# After project table\n\n\"#]],\n    );\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn migrate_removes_project_for_script() {\n    let p = project()\n        .file(\n            \"foo.rs\",\n            r#\"\n---\n# Before package\n[ package ] # After package header\n# After package header line\nname = \"foo\"\nedition = \"2021\"\n# After package table\n\n# Before project\n[ project ] # After project header\n# After project header line\nname = \"foo\"\nedition = \"2021\"\n# After project table\n---\n\nfn main() {\n}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript fix --edition --allow-no-vcs --manifest-path foo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stderr_data(str![[r#\"\n[MIGRATING] foo.rs from 2021 edition to 2024\n[FIXED] foo.rs (1 fix)\n[CHECKING] foo v0.0.0 ([ROOT]/foo/foo.rs)\n[MIGRATING] foo.rs from 2021 edition to 2024\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert_e2e().eq(\n        p.read_file(\"foo.rs\"),\n        str![[r#\"\n\n---\n# Before package\n[ package ] # After package header\n# After package header line\nname = \"foo\"\nedition = \"2021\"\n# After project table\n---\n\nfn main() {\n}\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn migrate_rename_underscore_fields() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace.dependencies]\n# Before default_features\na = {path = \"a\", default_features = false}  # After default_features value\n# After default_features line\n\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[lib]\nname = \"foo\"\n# Before crate_type\ncrate_type = [\"staticlib\", \"dylib\"]  # After crate_type value\n# After crate_type line\n\n[[example]]\nname = \"ex\"\npath = \"examples/ex.rs\"\n# Before crate_type\ncrate_type = [\"proc-macro\"]  # After crate_type value\n# After crate_type line\n\n# Before dev_dependencies\n[ dev_dependencies ] # After dev_dependencies header\n# After dev_dependencies line\na = {path = \"a\", default_features = false}\n# After dev_dependencies table\n\n# Before build_dependencies\n[ build_dependencies ] # After build_dependencies header\n# After build_dependencies line\na = {path = \"a\", default_features = false}\n# After build_dependencies table\n\n# Before dev_dependencies\n[ target.'cfg(any())'.dev_dependencies ] # After dev_dependencies header\n# After dev_dependencies line\na = {path = \"a\", default_features = false}\n# After dev_dependencies table\n\n# Before build_dependencies\n[ target.'cfg(any())'.build_dependencies ] # After build_dependencies header\n# After build_dependencies line\na = {path = \"a\", default_features = false}\n# After build_dependencies table\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"examples/ex.rs\",\n            r#\"\n                fn main() { println!(\"ex\"); }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2021 edition to 2024\n[FIXED] Cargo.toml (11 fixes)\n[CHECKING] a v0.0.1 ([ROOT]/foo/a)\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2021 edition to 2024\n[MIGRATING] examples/ex.rs from 2021 edition to 2024\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert_e2e().eq(\n        p.read_file(\"Cargo.toml\"),\n        str![[r#\"\n\n[workspace.dependencies]\n# Before default_features\na = {path = \"a\", default-features = false}  # After default_features value\n# After default_features line\n\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[lib]\nname = \"foo\"\n# Before crate_type\ncrate-type = [\"staticlib\", \"dylib\"]  # After crate_type value\n# After crate_type line\n\n[[example]]\nname = \"ex\"\npath = \"examples/ex.rs\"\n# Before crate_type\ncrate-type = [\"proc-macro\"]  # After crate_type value\n# After crate_type line\n\n# Before dev_dependencies\n[ dev-dependencies ] # After dev_dependencies header\n# After dev_dependencies line\na = {path = \"a\", default-features = false}\n# After dev_dependencies table\n\n# Before build_dependencies\n[ build-dependencies ] # After build_dependencies header\n# After build_dependencies line\na = {path = \"a\", default-features = false}\n# After build_dependencies table\n\n# Before dev_dependencies\n[ target.'cfg(any())'.dev-dependencies ] # After dev_dependencies header\n# After dev_dependencies line\na = {path = \"a\", default-features = false}\n# After dev_dependencies table\n\n# Before build_dependencies\n[ target.'cfg(any())'.build-dependencies ] # After build_dependencies header\n# After build_dependencies line\na = {path = \"a\", default-features = false}\n# After build_dependencies table\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn migrate_rename_underscore_fields_in_virtual_manifest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"foo\"]\nresolver = \"2\"\n\n[workspace.dependencies]\n# Before default_features\na = {path = \"a\", default_features = false}  # After default_features value\n# After default_features line\n\"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --edition --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2021 edition to 2024\n[FIXED] Cargo.toml (1 fix)\n[MIGRATING] foo/Cargo.toml from 2021 edition to 2024\n[CHECKING] foo v0.0.0 ([ROOT]/foo/foo)\n[MIGRATING] foo/src/lib.rs from 2021 edition to 2024\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert_e2e().eq(\n        p.read_file(\"Cargo.toml\"),\n        str![[r#\"\n\n[workspace]\nmembers = [\"foo\"]\nresolver = \"2\"\n\n[workspace.dependencies]\n# Before default_features\na = {path = \"a\", default-features = false}  # After default_features value\n# After default_features line\n\n\"#]],\n    );\n    assert_e2e().eq(\n        p.read_file(\"foo/Cargo.toml\"),\n        str![[r#\"\n\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn remove_ignored_default_features() {\n    Package::new(\"dep_simple\", \"0.1.0\").publish();\n    Package::new(\"dep_df_true\", \"0.1.0\").publish();\n    Package::new(\"dep_df_false\", \"0.1.0\").publish();\n\n    let pkg_default = r#\"\n[package]\nname = \"pkg_default\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\ndep_simple = { workspace = true }\ndep_df_true = { workspace = true }\ndep_df_false = { workspace = true }\n\n[build-dependencies]\ndep_simple = { workspace = true }\ndep_df_true = { workspace = true }\ndep_df_false = { workspace = true }\n\n[target.'cfg(target_os = \"linux\")'.dependencies]\ndep_simple = { workspace = true }\ndep_df_true = { workspace = true }\ndep_df_false = { workspace = true }\n\"#;\n    let pkg_df_true = r#\"\n[package]\nname = \"pkg_df_true\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\ndep_simple = { workspace = true, default-features = true }\ndep_df_true = { workspace = true, default-features = true }\ndep_df_false = { workspace = true, default-features = true }\n\n[build-dependencies]\ndep_simple = { workspace = true, default-features = true }\ndep_df_true = { workspace = true, default-features = true }\ndep_df_false = { workspace = true, default-features = true }\n\n[target.'cfg(target_os = \"linux\")'.dependencies]\ndep_simple = { workspace = true, default-features = true }\ndep_df_true = { workspace = true, default-features = true }\ndep_df_false = { workspace = true, default-features = true }\n\"#;\n    let pkg_df_false = r#\"\n[package]\nname = \"pkg_df_false\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\ndep_simple = { workspace = true, default-features = false }\ndep_df_true = { workspace = true, default-features = false }\ndep_df_false = { workspace = true, default-features = false }\n\n[build-dependencies]\ndep_simple = { workspace = true, default-features = false }\ndep_df_true = { workspace = true, default-features = false }\ndep_df_false = { workspace = true, default-features = false }\n\n[target.'cfg(target_os = \"linux\")'.dependencies]\ndep_simple = { workspace = true, default-features = false }\ndep_df_true = { workspace = true, default-features = false }\ndep_df_false = { workspace = true, default-features = false }\n\"#;\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"pkg_default\", \"pkg_df_true\", \"pkg_df_false\"]\nresolver = \"2\"\n\n[workspace.dependencies]\ndep_simple = \"0.1.0\"\ndep_df_true = { version = \"0.1.0\", default-features = true }\ndep_df_false = { version = \"0.1.0\", default-features = false }\n\"#,\n        )\n        .file(\"pkg_default/Cargo.toml\", pkg_default)\n        .file(\"pkg_default/src/lib.rs\", \"\")\n        .file(\"pkg_df_true/Cargo.toml\", pkg_df_true)\n        .file(\"pkg_df_true/src/lib.rs\", \"\")\n        .file(\"pkg_df_false/Cargo.toml\", pkg_df_false)\n        .file(\"pkg_df_false/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix --all --edition --allow-no-vcs\")\n        .with_stderr_data(\n            str![[r#\"\n[MIGRATING] pkg_default/Cargo.toml from 2021 edition to 2024\n[MIGRATING] pkg_df_true/Cargo.toml from 2021 edition to 2024\n[MIGRATING] pkg_df_false/Cargo.toml from 2021 edition to 2024\n[FIXED] pkg_df_false/Cargo.toml (6 fixes)\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep_simple v0.1.0 (registry `dummy-registry`)\n[DOWNLOADED] dep_df_true v0.1.0 (registry `dummy-registry`)\n[DOWNLOADED] dep_df_false v0.1.0 (registry `dummy-registry`)\n[CHECKING] dep_df_true v0.1.0\n[CHECKING] dep_df_false v0.1.0\n[CHECKING] dep_simple v0.1.0\n[CHECKING] pkg_df_true v0.1.0 ([ROOT]/foo/pkg_df_true)\n[CHECKING] pkg_df_false v0.1.0 ([ROOT]/foo/pkg_df_false)\n[CHECKING] pkg_default v0.1.0 ([ROOT]/foo/pkg_default)\n[MIGRATING] pkg_df_false/src/lib.rs from 2021 edition to 2024\n[MIGRATING] pkg_df_true/src/lib.rs from 2021 edition to 2024\n[MIGRATING] pkg_default/src/lib.rs from 2021 edition to 2024\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    assert_e2e().eq(p.read_file(\"pkg_default/Cargo.toml\"), pkg_default);\n    assert_e2e().eq(p.read_file(\"pkg_df_true/Cargo.toml\"), pkg_df_true);\n    assert_e2e().eq(\n        p.read_file(\"pkg_df_false/Cargo.toml\"),\n        str![[r#\"\n\n[package]\nname = \"pkg_df_false\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\ndep_simple = { workspace = true}\ndep_df_true = { workspace = true}\ndep_df_false = { workspace = true, default-features = false }\n\n[build-dependencies]\ndep_simple = { workspace = true}\ndep_df_true = { workspace = true}\ndep_df_false = { workspace = true, default-features = false }\n\n[target.'cfg(target_os = \"linux\")'.dependencies]\ndep_simple = { workspace = true}\ndep_df_true = { workspace = true}\ndep_df_false = { workspace = true, default-features = false }\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn fix_edition_skips_old_editions() {\n    // Checks that -Zfix-edition will skip things that are not 2024.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"[workspace]\n            members = [\"e2021\", \"e2024\"]\n            resolver = \"3\"\n            \"#,\n        )\n        .file(\n            \"e2021/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"e2021\"\n            edition = \"2021\"\n            \"#,\n        )\n        .file(\"e2021/src/lib.rs\", \"\")\n        .file(\n            \"e2024/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"e2024\"\n                edition = \"2024\"\n            \"#,\n        )\n        .file(\"e2024/src/lib.rs\", \"\")\n        .build();\n\n    // Doing the whole workspace should skip since there is a 2021 in the mix.\n    p.cargo(\"fix -Zfix-edition=start=2024 -v\")\n        .masquerade_as_nightly_cargo(&[\"fix-edition\"])\n        .with_stderr_data(str![[r#\"\n[SKIPPING] not all packages are at edition 2024\n\n\"#]])\n        .run();\n\n    // Same with `end`.\n    p.cargo(\"fix -Zfix-edition=end=2024,future -v\")\n        .masquerade_as_nightly_cargo(&[\"fix-edition\"])\n        .with_stderr_data(str![[r#\"\n[SKIPPING] not all packages are at edition 2024\n\n\"#]])\n        .run();\n\n    // Doing an individual package at the correct edition should check it.\n    p.cargo(\"fix -Zfix-edition=start=2024 -p e2024\")\n        .masquerade_as_nightly_cargo(&[\"fix-edition\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] e2024 v0.0.0 ([ROOT]/foo/e2024)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"future edition is always unstable\")]\nfn fix_edition_future() {\n    // Checks that the -Zfix-edition can work for the future.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            edition = \"2024\"\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fix -Zfix-edition=end=2024,future\")\n        .masquerade_as_nightly_cargo(&[\"fix-edition\"])\n        .with_stderr_data(str![[r#\"\n[MIGRATING] Cargo.toml from 2024 edition to future\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[MIGRATING] src/lib.rs from 2024 edition to future\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n     Updated edition to future\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert_e2e().eq(\n        p.read_file(\"Cargo.toml\"),\n        str![[r#\"\ncargo-features = [\"unstable-editions\"]\n\n            [package]\n            name = \"foo\"\nedition = \"future\"\n\n\"#]],\n    );\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn script_without_frontmatter() {\n    let p = cargo_test_support::project()\n        .file(\"echo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"fix -Zscript --allow-no-vcs --manifest-path echo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![\"\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[FIXED] echo.rs (1 fix)\n[CHECKING] echo v0.0.0 ([ROOT]/foo/echo.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert_e2e().eq(\n        p.read_file(\"echo.rs\"),\n        str![[r#\"\n---\n[package]\nedition = \"2024\"\n---\n\nfn main() {}\n\"#]],\n    );\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn script_with_frontmatter() {\n    let p = cargo_test_support::project()\n        .file(\n            \"echo.rs\",\n            \"#!/usr/bin/env cargo\n---\n[dependencies]\n---\nfn main() {}\",\n        )\n        .build();\n\n    p.cargo(\"fix -Zscript --allow-no-vcs --manifest-path echo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![\"\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[FIXED] echo.rs (1 fix)\n[CHECKING] echo v0.0.0 ([ROOT]/foo/echo.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert_e2e().eq(\n        p.read_file(\"echo.rs\"),\n        str![[r##\"\n#!/usr/bin/env cargo\n---\n[package]\nedition = \"2024\"\n[dependencies]\n---\nfn main() {}\n\"##]],\n    );\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn script_with_package_table() {\n    let p = cargo_test_support::project()\n        .file(\n            \"echo.rs\",\n            r#\"#!/usr/bin/env cargo\n---\n[package]\nname = \"foo\"\n---\nfn main() {}\"#,\n        )\n        .build();\n\n    p.cargo(\"fix -Zscript --allow-no-vcs --manifest-path echo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![\"\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[FIXED] echo.rs (1 fix)\n[CHECKING] foo v0.0.0 ([ROOT]/foo/echo.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert_e2e().eq(\n        p.read_file(\"echo.rs\"),\n        str![[r##\"\n#!/usr/bin/env cargo\n---\n[package]\nname = \"foo\"\nedition = \"2024\"\n---\nfn main() {}\n\"##]],\n    );\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn script_with_package_dotted() {\n    let p = cargo_test_support::project()\n        .file(\n            \"echo.rs\",\n            r#\"#!/usr/bin/env cargo\n---\npackage.name = \"foo\"\n---\nfn main() {}\"#,\n        )\n        .build();\n\n    p.cargo(\"fix -Zscript --allow-no-vcs --manifest-path echo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![\"\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[FIXED] echo.rs (1 fix)\n[CHECKING] foo v0.0.0 ([ROOT]/foo/echo.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert_e2e().eq(\n        p.read_file(\"echo.rs\"),\n        str![[r##\"\n#!/usr/bin/env cargo\n---\npackage.name = \"foo\"\npackage.edition = \"2024\"\n---\nfn main() {}\n\"##]],\n    );\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn script_with_edition() {\n    let p = cargo_test_support::project()\n        .file(\n            \"echo.rs\",\n            r#\"#!/usr/bin/env cargo\n---\npackage.edition = \"2015\"\n---\nfn main() {}\"#,\n        )\n        .build();\n\n    p.cargo(\"fix -Zscript --allow-no-vcs --manifest-path echo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![\"\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] echo v0.0.0 ([ROOT]/foo/echo.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert_e2e().eq(\n        p.read_file(\"echo.rs\"),\n        str![[r##\"\n#!/usr/bin/env cargo\n---\npackage.edition = \"2015\"\n---\nfn main() {}\n\"##]],\n    );\n}\n"
  },
  {
    "path": "tests/testsuite/fix_n_times.rs",
    "content": "//! Tests for the `cargo fix` command, specifically targeting the logic around\n//! running rustc multiple times to apply and verify fixes.\n//!\n//! These tests use a replacement of rustc (\"rustc-fix-shim\") which emits JSON\n//! messages based on what the test is exercising. It uses an environment\n//! variable `RUSTC_FIX_SHIM_SEQUENCE` which determines how it should behave\n//! based on how many times `rustc` has run. It keeps track of how many times\n//! rustc has run in a local file.\n//!\n//! For example, a sequence of `[Step::OneFix, Step::Error]` will emit one\n//! suggested fix the first time `rustc` is run, and then the next time it is\n//! run it will generate an error.\n//!\n//! The [`expect_fix_runs_rustc_n_times`] function handles setting everything\n//! up, and verifying the results.\n\nuse std::path::PathBuf;\nuse std::sync::{Mutex, OnceLock};\n\nuse crate::prelude::*;\nuse crate::utils::tools;\nuse cargo_test_support::{Execs, basic_manifest, paths, project, str};\n\n/// The action that the `rustc` shim should take in the current sequence of\n/// events.\n#[derive(Clone, Copy, PartialEq)]\n#[repr(u8)]\nenum Step {\n    /// Exits with success with no messages.\n    SuccessNoOutput = b'0',\n    /// Emits one suggested fix.\n    ///\n    /// The suggested fix involves updating the number of the first line\n    /// comment which starts as `// fix-count 0`.\n    OneFix = b'1',\n    /// Emits two suggested fixes which overlap, which rustfix can only apply\n    /// one of them, and fails for the other.\n    ///\n    /// The suggested fix is the same as `Step::OneFix`, it just shows up\n    /// twice.\n    TwoFixOverlapping = b'2',\n    /// Generates a warning without a suggestion.\n    Warning = b'w',\n    /// Generates an error message with no suggestion.\n    Error = b'e',\n    /// Emits one suggested fix and an error.\n    OneFixError = b'f',\n    /// Emits one diagnostic with two exclusive, overlapping suggestions.\n    TwoFixExclusive = b'x',\n}\n\n/// Verifies `cargo fix` behavior based on the given sequence of behaviors for\n/// `rustc`.\n///\n/// - `sequence` is the sequence of behaviors for each call to `rustc`.\n///   If rustc is called more often than the number of steps, then it will panic.\n/// - `extra_execs` a callback that allows extra customization of the [`Execs`].\n/// - `expected_stderr` is the expected output from cargo.\n/// - `expected_lib_rs` is the expected contents of `src/lib.rs` after the\n///   fixes have been applied. The file starts out with the content `//\n///   fix-count 0`, and the number increases based on which suggestions are\n///   applied.\nfn expect_fix_runs_rustc_n_times(\n    sequence: &[Step],\n    extra_execs: impl FnOnce(&mut Execs),\n    expected_stderr: impl IntoData,\n    expected_lib_rs: &str,\n) {\n    let rustc = rustc_for_cargo_fix();\n    let p = project().file(\"src/lib.rs\", \"// fix-count 0\").build();\n\n    let sequence_vec: Vec<_> = sequence.iter().map(|x| *x as u8).collect();\n    let sequence_str = std::str::from_utf8(&sequence_vec).unwrap();\n\n    let mut execs = p.cargo(\"fix --allow-no-vcs --lib\");\n    execs\n        .env(\"RUSTC\", &rustc)\n        .env(\"RUSTC_FIX_SHIM_SEQUENCE\", sequence_str)\n        .with_stderr_data(expected_stderr);\n    extra_execs(&mut execs);\n    execs.run();\n    let lib_rs = p.read_file(\"src/lib.rs\");\n    assert_eq!(expected_lib_rs, lib_rs);\n    let count: usize = p.read_file(\"rustc-fix-shim-count\").parse().unwrap();\n    assert_eq!(sequence.len(), count);\n}\n\n/// Returns the path to the rustc replacement executable.\nfn rustc_for_cargo_fix() -> PathBuf {\n    static FIX_SHIM: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new();\n\n    let mut lock = FIX_SHIM.get_or_init(|| Default::default()).lock().unwrap();\n    if let Some(path) = &*lock {\n        return path.clone();\n    }\n\n    let p = project()\n        .at(paths::global_root().join(\"rustc-fix-shim\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"rustc-fix-shim\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            r##\"\nfn main() {\n    if std::env::var_os(\"CARGO_PKG_NAME\").is_none() {\n        // Handle things like rustc -Vv\n        let r = std::process::Command::new(\"rustc\")\n            .args(std::env::args_os().skip(1))\n            .status();\n        std::process::exit(r.unwrap().code().unwrap_or(2));\n    }\n\n    // Keep track of which step in the sequence that needs to run.\n    let successful_count = std::fs::read_to_string(\"rustc-fix-shim-count\")\n        .map(|c| c.parse().unwrap())\n        .unwrap_or(0);\n    std::fs::write(\"rustc-fix-shim-count\", format!(\"{}\", successful_count + 1)).unwrap();\n    // The sequence tells us which behavior we should have.\n    let seq = std::env::var(\"RUSTC_FIX_SHIM_SEQUENCE\").unwrap();\n    if successful_count >= seq.len() {\n        panic!(\"rustc called too many times count={}, \\\n                make sure to update the Step sequence\", successful_count);\n    }\n    match seq.as_bytes()[successful_count] {\n        b'0' => return,\n        b'1' => {\n            output_suggestion(successful_count + 1);\n        }\n        b'2' => {\n            output_suggestion(successful_count + 1);\n            output_suggestion(successful_count + 2);\n        }\n        b'w' => {\n            output_message(\"warning\", successful_count + 1);\n        }\n        b'e' => {\n            output_message(\"error\", successful_count + 1);\n            std::process::exit(1);\n        }\n        b'f' => {\n            output_suggestion(successful_count + 1);\n            output_message(\"error\", successful_count + 2);\n            std::process::exit(1);\n        }\n        b'x' => {\n            output_exclusive_suggestions(successful_count + 1);\n        }\n        _ => panic!(\"unexpected sequence\"),\n    }\n}\n\nfn output_suggestion(count: usize) {\n    let json = format!(\n        r#\"{{\n            \"$message_type\": \"diagnostic\",\n            \"message\": \"rustc fix shim comment {count}\",\n            \"code\": null,\n            \"level\": \"warning\",\n            \"spans\":\n            [\n                {{\n                    \"file_name\": \"src/lib.rs\",\n                    \"byte_start\": 13,\n                    \"byte_end\": 14,\n                    \"line_start\": 1,\n                    \"line_end\": 1,\n                    \"column_start\": 14,\n                    \"column_end\": 15,\n                    \"is_primary\": true,\n                    \"text\":\n                    [\n                        {{\n                            \"text\": \"// fix-count 0\",\n                            \"highlight_start\": 14,\n                            \"highlight_end\": 15\n                        }}\n                    ],\n                    \"label\": \"increase this number\",\n                    \"suggested_replacement\": null,\n                    \"suggestion_applicability\": null,\n                    \"expansion\": null\n                }}\n            ],\n            \"children\":\n            [\n                {{\n                    \"message\": \"update the number here\",\n                    \"code\": null,\n                    \"level\": \"help\",\n                    \"spans\":\n                    [\n                        {{\n                            \"file_name\": \"src/lib.rs\",\n                            \"byte_start\": 13,\n                            \"byte_end\": 14,\n                            \"line_start\": 1,\n                            \"line_end\": 1,\n                            \"column_start\": 14,\n                            \"column_end\": 15,\n                            \"is_primary\": true,\n                            \"text\":\n                            [\n                                {{\n                                    \"text\": \"// fix-count 0\",\n                                    \"highlight_start\": 14,\n                                    \"highlight_end\": 15\n                                }}\n                            ],\n                            \"label\": null,\n                            \"suggested_replacement\": \"{count}\",\n                            \"suggestion_applicability\": \"MachineApplicable\",\n                            \"expansion\": null\n                        }}\n                    ],\n                    \"children\": [],\n                    \"rendered\": null\n                }}\n            ],\n            \"rendered\": \"rustc fix shim comment {count}\"\n        }}\"#,\n    )\n    .replace(\"\\n\", \"\");\n    eprintln!(\"{json}\");\n}\n\nfn output_message(level: &str, count: usize) {\n    let json = format!(\n        r#\"{{\n    \"$message_type\": \"diagnostic\",\n    \"message\": \"rustc fix shim {level} count={count}\",\n    \"code\": null,\n    \"level\": \"{level}\",\n    \"spans\":\n    [\n        {{\n            \"file_name\": \"src/lib.rs\",\n            \"byte_start\": 0,\n            \"byte_end\": 0,\n            \"line_start\": 1,\n            \"line_end\": 1,\n            \"column_start\": 1,\n            \"column_end\": 1,\n            \"is_primary\": true,\n            \"text\":\n            [\n                {{\n                    \"text\": \"// fix-count 0\",\n                    \"highlight_start\": 1,\n                    \"highlight_end\": 4\n                }}\n            ],\n            \"label\": \"forced error\",\n            \"suggested_replacement\": null,\n            \"suggestion_applicability\": null,\n            \"expansion\": null\n        }}\n    ],\n    \"children\": [],\n    \"rendered\": \"rustc fix shim {level} count={count}\"\n}}\"#,\n    )\n    .replace(\"\\n\", \"\");\n    eprintln!(\"{json}\");\n}\n\nfn output_exclusive_suggestions(count: usize) {\n    let json = format!(\n        r#\"{{\n            \"$message_type\": \"diagnostic\",\n            \"message\": \"rustc fix shim exclusive comment {count}\",\n            \"code\": null,\n            \"level\": \"warning\",\n            \"spans\":\n            [\n                {{\n                    \"file_name\": \"src/lib.rs\",\n                    \"byte_start\": 13,\n                    \"byte_end\": 14,\n                    \"line_start\": 1,\n                    \"line_end\": 1,\n                    \"column_start\": 14,\n                    \"column_end\": 15,\n                    \"is_primary\": true,\n                    \"text\":\n                    [\n                        {{\n                            \"text\": \"// fix-count 0\",\n                            \"highlight_start\": 14,\n                            \"highlight_end\": 15\n                        }}\n                    ],\n                    \"label\": \"increase this number\",\n                    \"suggested_replacement\": null,\n                    \"suggestion_applicability\": null,\n                    \"expansion\": null\n                }}\n            ],\n            \"children\":\n            [\n                {{\n                    \"message\": \"try this\",\n                    \"code\": null,\n                    \"level\": \"help\",\n                    \"spans\":\n                    [\n                        {{\n                            \"file_name\": \"src/lib.rs\",\n                            \"byte_start\": 13,\n                            \"byte_end\": 14,\n                            \"line_start\": 1,\n                            \"line_end\": 1,\n                            \"column_start\": 14,\n                            \"column_end\": 15,\n                            \"is_primary\": true,\n                            \"text\":\n                            [\n                                {{\n                                    \"text\": \"// fix-count 0\",\n                                    \"highlight_start\": 14,\n                                    \"highlight_end\": 15\n                                }}\n                            ],\n                            \"label\": null,\n                            \"suggested_replacement\": \"{count}a\",\n                            \"suggestion_applicability\": \"MachineApplicable\",\n                            \"expansion\": null\n                        }}\n                    ],\n                    \"children\": [],\n                    \"rendered\": null\n                }},\n                {{\n                    \"message\": \"or try this\",\n                    \"code\": null,\n                    \"level\": \"help\",\n                    \"spans\":\n                    [\n                        {{\n                            \"file_name\": \"src/lib.rs\",\n                            \"byte_start\": 13,\n                            \"byte_end\": 14,\n                            \"line_start\": 1,\n                            \"line_end\": 1,\n                            \"column_start\": 14,\n                            \"column_end\": 15,\n                            \"is_primary\": true,\n                            \"text\":\n                            [\n                                {{\n                                    \"text\": \"// fix-count 0\",\n                                    \"highlight_start\": 14,\n                                    \"highlight_end\": 15\n                                }}\n                            ],\n                            \"label\": null,\n                            \"suggested_replacement\": \"{count}b\",\n                            \"suggestion_applicability\": \"MachineApplicable\",\n                            \"expansion\": null\n                        }}\n                    ],\n                    \"children\": [],\n                    \"rendered\": null\n                }}\n            ],\n            \"rendered\": \"rustc fix shim exclusive comment {count}\"\n        }}\"#,\n    )\n    .replace(\"\\n\", \"\");\n    eprintln!(\"{json}\");\n}\n            \"##,\n        )\n        .build();\n    p.cargo(\"build\").run();\n    let path = p.bin(\"rustc-fix-shim\");\n    *lock = Some(path.clone());\n    path\n}\n\n#[cargo_test]\nfn fix_no_suggestions() {\n    // No suggested fixes.\n    expect_fix_runs_rustc_n_times(\n        &[Step::SuccessNoOutput],\n        |_execs| {},\n        str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        \"// fix-count 0\",\n    );\n}\n\n#[cargo_test]\nfn fix_one_suggestion() {\n    // One suggested fix, with a successful verification, no output.\n    expect_fix_runs_rustc_n_times(\n        &[Step::OneFix, Step::SuccessNoOutput],\n        |_execs| {},\n        str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FIXED] src/lib.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        \"// fix-count 1\",\n    );\n}\n\n#[cargo_test]\nfn fix_one_overlapping() {\n    // Two suggested fixes, where one fails, then the next step returns no suggestions.\n    expect_fix_runs_rustc_n_times(\n        &[Step::TwoFixOverlapping, Step::SuccessNoOutput],\n        |_execs| {},\n        str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FIXED] src/lib.rs (1 fix)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        \"// fix-count 2\",\n    );\n}\n\n#[cargo_test]\nfn fix_overlapping_max() {\n    // Rustc repeatedly spits out suggestions that overlap, which should hit\n    // the limit of 4 attempts. It should show the output from the 5th attempt.\n    expect_fix_runs_rustc_n_times(\n        &[\n            Step::TwoFixOverlapping,\n            Step::TwoFixOverlapping,\n            Step::TwoFixOverlapping,\n            Step::TwoFixOverlapping,\n            Step::TwoFixOverlapping,\n        ],\n        |_execs| {},\n        str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] error applying suggestions\n --> src/lib.rs\n  = cause: cannot replace slice of data that was already replaced\n[HELP] to report this as a bug, open an issue at https://github.com/rust-lang/rust/issues, quoting the full output of this command\n[HELP] to possibly apply more fixes, pass in the `--broken-code` flag\n[FIXED] src/lib.rs (4 fixes)\nrustc fix shim comment 5\nrustc fix shim comment 6\n[WARNING] `foo` (lib) generated 2 warnings (run `cargo fix --lib -p foo` to apply 2 suggestions)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        \"// fix-count 5\",\n    );\n}\n\n#[cargo_test]\nfn fix_verification_failed() {\n    // One suggested fix, with an error in the verification step.\n    // This should cause `cargo fix` to back out the changes.\n    expect_fix_runs_rustc_n_times(\n        &[Step::OneFix, Step::Error],\n        |_execs| {},\n        str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] errors present after applying fixes to crate `foo`\n --> src/lib.rs\n  = cause: rustc fix shim error count=2\n[HELP] to report this as a bug, open an issue at https://github.com/rust-lang/rust/issues, quoting the full output of this command\n[HELP] to possibly apply more fixes, pass in the `--broken-code` flag\n[NOTE] original diagnostics will follow:\nrustc fix shim comment 1\n[WARNING] `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply 1 suggestion)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        \"// fix-count 0\",\n    );\n}\n\n#[cargo_test]\nfn fix_verification_failed_clippy() {\n    // This is the same as `fix_verification_failed_clippy`, except it checks\n    // the error message has the customization for the clippy URL and\n    // subcommand.\n    expect_fix_runs_rustc_n_times(\n        &[Step::OneFix, Step::Error],\n        |execs| {\n            execs.env(\"RUSTC_WORKSPACE_WRAPPER\", tools::wrapped_clippy_driver());\n        },\n        str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] errors present after applying fixes to crate `foo`\n --> src/lib.rs\n  = cause: rustc fix shim error count=2\n[HELP] to report this as a bug, open an issue at https://github.com/rust-lang/rust-clippy/issues, quoting the full output of this command\n[HELP] to possibly apply more fixes, pass in the `--broken-code` flag\n[NOTE] original diagnostics will follow:\nrustc fix shim comment 1\n[WARNING] `foo` (lib) generated 1 warning (run `cargo clippy --fix --lib -p foo` to apply 1 suggestion)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        \"// fix-count 0\",\n    );\n}\n\n#[cargo_test]\nfn warnings() {\n    // Only emits warnings.\n    expect_fix_runs_rustc_n_times(\n        &[Step::Warning],\n        |_execs| {},\n        str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\nrustc fix shim warning count=1\n[WARNING] `foo` (lib) generated 1 warning\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        \"// fix-count 0\",\n    );\n}\n\n#[cargo_test]\nfn starts_with_error() {\n    // The source code doesn't compile to start with.\n    expect_fix_runs_rustc_n_times(\n        &[Step::Error],\n        |execs| {\n            execs.with_status(101);\n        },\n        str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\nrustc fix shim error count=1\n[ERROR] could not compile `foo` (lib) due to 1 previous error\n\n\"#]],\n        \"// fix-count 0\",\n    );\n}\n\n#[cargo_test]\nfn broken_code_no_suggestions() {\n    // --broken-code with no suggestions\n    expect_fix_runs_rustc_n_times(\n        &[Step::Error],\n        |execs| {\n            execs.arg(\"--broken-code\").with_status(101);\n        },\n        str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\nrustc fix shim error count=1\n[ERROR] could not compile `foo` (lib) due to 1 previous error\n\n\"#]],\n        \"// fix-count 0\",\n    );\n}\n\n#[cargo_test]\nfn broken_code_one_suggestion() {\n    // --broken-code where there is an error and a suggestion.\n    expect_fix_runs_rustc_n_times(\n        &[Step::OneFixError, Step::Error],\n        |execs| {\n            execs.arg(\"--broken-code\").with_status(101);\n        },\n        str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] errors present after applying fixes to crate `foo`\n --> src/lib.rs\n  = cause: rustc fix shim error count=2\n[HELP] to report this as a bug, open an issue at https://github.com/rust-lang/rust/issues, quoting the full output of this command\n[HELP] to possibly apply more fixes, pass in the `--broken-code` flag\n[NOTE] original diagnostics will follow:\nrustc fix shim comment 1\nrustc fix shim error count=2\n[WARNING] `foo` (lib) generated 1 warning\n[ERROR] could not compile `foo` (lib) due to 1 previous error; 1 warning emitted\n\n\"#]],\n        \"// fix-count 1\",\n    );\n}\n\n#[cargo_test]\nfn fix_exclusive_suggestions() {\n    // One diagnostic with two exclusive suggestions for the same span.\n    // Currently, rustfix fails with a generic `AlreadyReplaced` error\n    // (\"cannot replace slice of data that was already replaced\") when it\n    // encounters this.\n    expect_fix_runs_rustc_n_times(\n        &[Step::TwoFixExclusive],\n        |execs| {\n            execs.with_status(0);\n        },\n        str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] error applying suggestions\n --> src/lib.rs\n  = cause: cannot replace slice of data that was already replaced\n[HELP] to report this as a bug, open an issue at https://github.com/rust-lang/rust/issues, quoting the full output of this command\n[HELP] to possibly apply more fixes, pass in the `--broken-code` flag\n[FIXED] src/lib.rs (0 fixes)\n[..]\n[WARNING] `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply 1 suggestion)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        \"// fix-count 0\",\n    );\n}\n"
  },
  {
    "path": "tests/testsuite/freshness.rs",
    "content": "//! Tests for fingerprinting (rebuild detection).\n\nuse std::fs::{self, OpenOptions};\nuse std::io;\nuse std::io::prelude::*;\nuse std::net::TcpListener;\nuse std::path::{Path, PathBuf};\nuse std::process::Stdio;\nuse std::thread;\nuse std::time::SystemTime;\n\nuse crate::prelude::*;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{\n    basic_lib_manifest, basic_manifest, is_coarse_mtime, project, rustc_host, rustc_host_env,\n    sleep_ms, str,\n};\nuse filetime::FileTime;\n\nuse super::death;\n\n#[cargo_test]\nfn modifying_and_moving() {\n    let p = project()\n        .file(\"src/main.rs\", \"mod a; fn main() {}\")\n        .file(\"src/a.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.root().move_into_the_past();\n    p.root().join(\"target\").move_into_the_past();\n\n    p.change_file(\"src/a.rs\", \"#[allow(unused)]fn main() {}\");\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the file `src/a.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    fs::rename(&p.root().join(\"src/a.rs\"), &p.root().join(\"src/b.rs\")).unwrap();\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\nerror[E0583]: file not found for module `a`\n...\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn modify_only_some_files() {\n    let p = project()\n        .file(\"src/lib.rs\", \"mod a;\")\n        .file(\"src/a.rs\", \"\")\n        .file(\"src/main.rs\", \"mod b; fn main() {}\")\n        .file(\"src/b.rs\", \"\")\n        .file(\"tests/test.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"test\").run();\n    sleep_ms(1000);\n\n    assert!(p.bin(\"foo\").is_file());\n\n    let lib = p.root().join(\"src/lib.rs\");\n    p.change_file(\"src/lib.rs\", \"invalid rust code\");\n    p.change_file(\"src/b.rs\", \"#[allow(unused)]fn foo() {}\");\n    lib.move_into_the_past();\n\n    // Make sure the binary is rebuilt, not the lib\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the file `src/b.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(p.bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn rebuild_sub_package_then_while_package() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies.a]\n                path = \"a\"\n                [dependencies.b]\n                path = \"b\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate a; extern crate b;\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                authors = []\n                version = \"0.0.1\"\n                edition = \"2015\"\n                [dependencies.b]\n                path = \"../b\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"extern crate b;\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n    p.change_file(\"b/src/lib.rs\", \"pub fn b() {}\");\n\n    p.cargo(\"build -pb -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] b v0.0.1 ([ROOT]/foo/b): the file `b/src/lib.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[RUNNING] `rustc --crate-name b [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"src/lib.rs\",\n        \"extern crate a; extern crate b; pub fn toplevel() {}\",\n    );\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] b v0.0.1 ([ROOT]/foo/b)\n[DIRTY] a v0.0.1 ([ROOT]/foo/a): the dependency `b` was rebuilt ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[RUNNING] `rustc --crate-name a [..]\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the dependency `b` was rebuilt ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn changing_lib_features_caches_targets() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                foo = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --features foo\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    /* Targets should be cached from the first build */\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --features foo\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn changing_profiles_caches_targets() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                panic = \"abort\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .run();\n\n    /* Targets should be cached from the first build */\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"test foo\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn changing_bin_paths_common_target_features_caches_targets() {\n    // Make sure dep_cache crate is built once per feature\n    let p = project()\n        .no_manifest()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                target-dir = \"./target\"\n            \"#,\n        )\n        .file(\n            \"dep_crate/Cargo.toml\",\n            r#\"\n                [package]\n                name    = \"dep_crate\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                ftest  = []\n            \"#,\n        )\n        .file(\n            \"dep_crate/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"ftest\")]\n                pub fn yo() {\n                    println!(\"ftest on\")\n                }\n                #[cfg(not(feature = \"ftest\"))]\n                pub fn yo() {\n                    println!(\"ftest off\")\n                }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name    = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                dep_crate = {path = \"../dep_crate\", features = []}\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/src/main.rs\",\n            r#\"\n                extern crate dep_crate;\n                use dep_crate::yo;\n                fn main() {\n                    yo();\n                }\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name    = \"b\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                dep_crate = {path = \"../dep_crate\", features = [\"ftest\"]}\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"b/src/main.rs\",\n            r#\"\n                extern crate dep_crate;\n                use dep_crate::yo;\n                fn main() {\n                    yo();\n                }\n            \"#,\n        )\n        .build();\n\n    /* Build and rebuild a/. Ensure dep_crate only builds once */\n    p.cargo(\"run\")\n        .cwd(\"a\")\n        .with_stdout_data(str![[r#\"\nftest off\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] dep_crate v0.0.1 ([ROOT]/foo/dep_crate)\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/./target/debug/a[EXE]`\n\n\"#]])\n        .run();\n    p.cargo(\"clean -p a\").cwd(\"a\").run();\n    p.cargo(\"run\")\n        .cwd(\"a\")\n        .with_stdout_data(str![[r#\"\nftest off\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/./target/debug/a[EXE]`\n\n\"#]])\n        .run();\n\n    /* Build and rebuild b/. Ensure dep_crate only builds once */\n    p.cargo(\"run\")\n        .cwd(\"b\")\n        .with_stdout_data(str![[r#\"\nftest on\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] dep_crate v0.0.1 ([ROOT]/foo/dep_crate)\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/./target/debug/b[EXE]`\n\n\"#]])\n        .run();\n    p.cargo(\"clean -p b\").cwd(\"b\").run();\n    p.cargo(\"run\")\n        .cwd(\"b\")\n        .with_stdout_data(str![[r#\"\nftest on\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/./target/debug/b[EXE]`\n\n\"#]])\n        .run();\n\n    /* Build a/ package again. If we cache different feature dep builds correctly,\n     * this should not cause a rebuild of dep_crate */\n    p.cargo(\"clean -p a\").cwd(\"a\").run();\n    p.cargo(\"run\")\n        .cwd(\"a\")\n        .with_stdout_data(str![[r#\"\nftest off\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/./target/debug/a[EXE]`\n\n\"#]])\n        .run();\n\n    /* Build b/ package again. If we cache different feature dep builds correctly,\n     * this should not cause a rebuild */\n    p.cargo(\"clean -p b\").cwd(\"b\").run();\n    p.cargo(\"run\")\n        .cwd(\"b\")\n        .with_stdout_data(str![[r#\"\nftest on\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/./target/debug/b[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn changing_bin_features_caches_targets() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                foo = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    let msg = if cfg!(feature = \"foo\") { \"feature on\" } else { \"feature off\" };\n                    println!(\"{}\", msg);\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.rename_run(\"foo\", \"off1\")\n        .with_stdout_data(str![[r#\"\nfeature off\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --features foo\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.rename_run(\"foo\", \"on1\")\n        .with_stdout_data(str![[r#\"\nfeature on\n\n\"#]])\n        .run();\n\n    /* Targets should be cached from the first build */\n\n    let mut e = p.cargo(\"build -v\");\n\n    // MSVC does not include hash in binary filename, so it gets recompiled.\n    if cfg!(target_env = \"msvc\") {\n        e.with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the list of features changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    } else {\n        e.with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    }\n    e.run();\n    p.rename_run(\"foo\", \"off2\")\n        .with_stdout_data(str![[r#\"\nfeature off\n\n\"#]])\n        .run();\n\n    let mut e = p.cargo(\"build --features foo -v\");\n    if cfg!(target_env = \"msvc\") {\n        e.with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the list of features changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    } else {\n        e.with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    }\n    e.run();\n    p.rename_run(\"foo\", \"on2\")\n        .with_stdout_data(str![[r#\"\nfeature on\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rebuild_tests_if_lib_changes() {\n    let p = project()\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\"tests/foo-test.rs\", \"extern crate foo;\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"test\").run();\n\n    sleep_ms(1000);\n    p.change_file(\"src/lib.rs\", \"\");\n\n    p.cargo(\"build\").run();\n    p.cargo(\"test -v --test foo-test\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the dependency `foo` was rebuilt ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo_test [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/foo_test-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_rebuild_transitive_target_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n                [dev-dependencies]\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"tests/foo.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.foo.dependencies]\n                c = { path = \"../c\" }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                c = { path = \"../c\" }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\"c/Cargo.toml\", &basic_manifest(\"c\", \"0.0.1\"))\n        .file(\"c/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"test --no-run\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] c v0.0.1 ([ROOT]/foo/c)\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[EXECUTABLE] tests/foo.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rerun_if_changed_in_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"a/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rerun-if-changed=build.rs\");\n                }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn same_build_dir_cached_packages() {\n    let p = project()\n        .no_manifest()\n        .file(\n            \"a1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                b = { path = \"../b\" }\n            \"#,\n        )\n        .file(\"a1/src/lib.rs\", \"\")\n        .file(\n            \"a2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                b = { path = \"../b\" }\n            \"#,\n        )\n        .file(\"a2/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                c = { path = \"../c\" }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"c/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"c\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                d = { path = \"../d\" }\n            \"#,\n        )\n        .file(\"c/src/lib.rs\", \"\")\n        .file(\"d/Cargo.toml\", &basic_manifest(\"d\", \"0.0.1\"))\n        .file(\"d/src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                target-dir = \"./target\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .cwd(\"a1\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 3 packages to latest compatible versions\n[COMPILING] d v0.0.1 ([ROOT]/foo/d)\n[COMPILING] c v0.0.1 ([ROOT]/foo/c)\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[COMPILING] a1 v0.0.1 ([ROOT]/foo/a1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build\")\n        .cwd(\"a2\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 3 packages to latest compatible versions\n[COMPILING] a2 v0.0.1 ([ROOT]/foo/a2)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_rebuild_if_build_artifacts_move_backwards_in_time() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    p.root().move_into_the_past();\n\n    p.cargo(\"build\")\n        .with_stdout_data(str![])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rebuild_if_build_artifacts_move_forward_in_time() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    p.root().move_into_the_future();\n\n    p.cargo(\"build\")\n        .env(\"CARGO_LOG\", \"\")\n        .with_stdout_data(str![])\n        .with_stderr_data(str![[r#\"\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rebuild_if_environment_changes() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                description = \"old desc\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    println!(\"{}\", env!(\"CARGO_PKG_DESCRIPTION\"));\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\nold desc\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            description = \"new desc\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n        \"#,\n    );\n\n    p.cargo(\"run -v\")\n        .with_stdout_data(str![[r#\"\nnew desc\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the environment variable CARGO_PKG_DESCRIPTION changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_rebuild_when_rename_dir() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n\n                [dependencies]\n                foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\"src/_unused.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.0.1\"))\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\"foo/build.rs\", \"fn main() {}\")\n        .build();\n\n    // make sure the most recently modified file is `src/lib.rs`, not\n    // `Cargo.toml`, to expose a historical bug where we forgot to strip the\n    // `Cargo.toml` path from looking for the package root.\n    cargo_test_support::sleep_ms(100);\n    fs::write(p.root().join(\"src/lib.rs\"), \"\").unwrap();\n\n    p.cargo(\"build\").run();\n    let mut new = p.root();\n    new.pop();\n    new.push(\"bar\");\n    fs::rename(p.root(), &new).unwrap();\n\n    p.cargo(\"build\")\n        .cwd(&new)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unused_optional_dep() {\n    Package::new(\"registry1\", \"0.1.0\").publish();\n    Package::new(\"registry2\", \"0.1.0\").publish();\n    Package::new(\"registry3\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"p\"\n                authors = []\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n                baz = { path = \"baz\" }\n                registry1 = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dev-dependencies]\n                registry2 = \"*\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                registry3 = { version = \"*\", optional = true }\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn path_dev_dep_registry_updates() {\n    Package::new(\"registry1\", \"0.1.0\").publish();\n    Package::new(\"registry2\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"p\"\n                authors = []\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                registry1 = \"*\"\n\n                [dev-dependencies]\n                baz = { path = \"../baz\"}\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                registry2 = \"*\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn change_panic_mode() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = ['bar', 'baz']\n                [profile.dev]\n                panic = 'abort'\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                bar = { path = '../bar' }\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"extern crate bar;\")\n        .build();\n\n    p.cargo(\"build -p bar\").run();\n    p.cargo(\"build -p baz\").run();\n}\n\n#[cargo_test]\nfn dont_rebuild_based_on_plugins() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n\n                [workspace]\n                members = ['baz']\n\n                [dependencies]\n                proc-macro-thing = { path = 'proc-macro-thing' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"proc-macro-thing/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"proc-macro-thing\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                qux = { path = '../qux' }\n            \"#,\n        )\n        .file(\"proc-macro-thing/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                qux = { path = '../qux' }\n            \"#,\n        )\n        .file(\"baz/src/main.rs\", \"fn main() {}\")\n        .file(\"qux/Cargo.toml\", &basic_manifest(\"qux\", \"0.1.1\"))\n        .file(\"qux/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"build -p baz\").run();\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -p bar\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn reuse_workspace_lib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n\n                [workspace]\n\n                [dependencies]\n                baz = { path = 'baz' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.1\"))\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"test -p baz -v --no-run\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] baz v0.1.1 ([ROOT]/foo/baz)\n[RUNNING] `rustc --crate-name baz [..]\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/baz-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn reuse_shared_build_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                shared = {path = \"shared\"}\n\n                [workspace]\n                members = [\"shared\", \"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"shared/Cargo.toml\", &basic_manifest(\"shared\", \"0.0.1\"))\n        .file(\"shared/src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [build-dependencies]\n                shared = { path = \"../shared\" }\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"bar/build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --workspace\").run();\n    // This should not recompile!\n    p.cargo(\"build -p foo -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] shared v0.0.1 ([ROOT]/foo/shared)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn changing_rustflags_is_cached() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    // This isn't ever cached, we always have to recompile\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -v\")\n        .env(\"RUSTFLAGS\", \"-C linker=cc\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -v\")\n        .env(\"RUSTFLAGS\", \"-C linker=cc\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn changing_rustc_extra_flags_is_cached() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    // This isn't ever cached, we always have to recompile\n    p.cargo(\"rustc\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"rustc -v -- -C linker=cc\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"rustc -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"rustc -v -- -C linker=cc\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_dependency_mtime_does_not_rebuild() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Z mtime-on-use\")\n        .masquerade_as_nightly_cargo(&[\"mtime-on-use\"])\n        .env(\"RUSTFLAGS\", \"-C linker=cc\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // This does not make new files, but it does update the mtime of the dependency.\n    p.cargo(\"build -p bar -Z mtime-on-use\")\n        .masquerade_as_nightly_cargo(&[\"mtime-on-use\"])\n        .env(\"RUSTFLAGS\", \"-C linker=cc\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // This should not recompile!\n    p.cargo(\"build -Z mtime-on-use\")\n        .masquerade_as_nightly_cargo(&[\"mtime-on-use\"])\n        .env(\"RUSTFLAGS\", \"-C linker=cc\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\nfn fingerprint_cleaner(mut dir: PathBuf, timestamp: filetime::FileTime) {\n    // Cargo is experimenting with letting outside projects develop some\n    // limited forms of GC for target_dir. This is one of the forms.\n    // Specifically, Cargo is updating the mtime of a file in\n    // target/profile/.fingerprint each time it uses the fingerprint.\n    // So a cleaner can remove files associated with a fingerprint\n    // if all the files in the fingerprint's folder are older then a time stamp without\n    // effecting any builds that happened since that time stamp.\n    let mut cleaned = false;\n    dir.push(\".fingerprint\");\n    for fingerprint in fs::read_dir(&dir).unwrap() {\n        let fingerprint = fingerprint.unwrap();\n\n        let outdated = |f: io::Result<fs::DirEntry>| {\n            filetime::FileTime::from_last_modification_time(&f.unwrap().metadata().unwrap())\n                <= timestamp\n        };\n        if fs::read_dir(fingerprint.path()).unwrap().all(outdated) {\n            fs::remove_dir_all(fingerprint.path()).unwrap();\n            println!(\"remove: {:?}\", fingerprint.path());\n            // a real cleaner would remove the big files in deps and build as well\n            // but fingerprint is sufficient for our tests\n            cleaned = true;\n        } else {\n        }\n    }\n    assert!(\n        cleaned,\n        \"called fingerprint_cleaner, but there was nothing to remove\"\n    );\n}\n\n#[cargo_test]\nfn fingerprint_cleaner_does_not_rebuild() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [features]\n                a = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Z mtime-on-use\")\n        .masquerade_as_nightly_cargo(&[\"mtime-on-use\"])\n        .run();\n    p.cargo(\"build -Z mtime-on-use --features a\")\n        .masquerade_as_nightly_cargo(&[\"mtime-on-use\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n    let timestamp = filetime::FileTime::from_system_time(SystemTime::now());\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n    // This does not make new files, but it does update the mtime.\n    p.cargo(\"build -Z mtime-on-use --features a\")\n        .masquerade_as_nightly_cargo(&[\"mtime-on-use\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    fingerprint_cleaner(p.target_debug_dir(), timestamp);\n    // This should not recompile!\n    p.cargo(\"build -Z mtime-on-use --features a\")\n        .masquerade_as_nightly_cargo(&[\"mtime-on-use\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // But this should be cleaned and so need a rebuild\n    p.cargo(\"build -Z mtime-on-use\")\n        .masquerade_as_nightly_cargo(&[\"mtime-on-use\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn reuse_panic_build_dep_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [build-dependencies]\n                bar = { path = \"bar\" }\n\n                [dev-dependencies]\n                bar = { path = \"bar\" }\n\n                [profile.dev]\n                panic = \"abort\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    // Check that `bar` is not built twice. It is only needed once (without `panic`).\n    p.cargo(\"test --lib --no-run -v\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..]\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..]\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]--test[..]\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn reuse_panic_pm() {\n    // foo(panic) -> bar(panic)\n    // somepm(nopanic) -> bar(nopanic)\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n                somepm = { path = \"somepm\" }\n\n                [profile.dev]\n                panic = \"abort\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"somepm/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"somepm\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                bar = { path = \"../bar\" }\n            \"#,\n        )\n        .file(\"somepm/src/lib.rs\", \"extern crate bar;\")\n        .build();\n\n    // bar is built once without panic (for proc-macro) and once with (for the\n    // normal dependency).\n    p.cargo(\"build -v\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..] -C panic=abort [..]\n[RUNNING] `rustc --crate-name bar [..]\n[COMPILING] somepm v0.0.1 ([ROOT]/foo/somepm)\n[RUNNING] `rustc --crate-name somepm [..]\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -C panic=abort [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn bust_patched_dep() {\n    Package::new(\"registry1\", \"0.1.0\").publish();\n    Package::new(\"registry2\", \"0.1.0\")\n        .dep(\"registry1\", \"0.1.0\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                registry2 = \"0.1.0\"\n\n                [patch.crates-io]\n                registry1 = { path = \"reg1new\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"reg1new/Cargo.toml\", &basic_manifest(\"registry1\", \"0.1.0\"))\n        .file(\"reg1new/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n\n    p.change_file(\"reg1new/src/lib.rs\", \"// modified\");\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n\n    p.cargo(\"build -v\").with_stderr_data(str![[r#\"\n[DIRTY] registry1 v0.1.0 ([ROOT]/foo/reg1new): the file `reg1new/src/lib.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] registry1 v0.1.0 ([ROOT]/foo/reg1new)\n[RUNNING] `rustc --crate-name registry1 [..]\n[DIRTY] registry2 v0.1.0: the dependency `registry1` was rebuilt\n[COMPILING] registry2 v0.1.0\n[RUNNING] `rustc --crate-name registry2 [..]\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the dependency `registry2` was rebuilt\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] registry1 v0.1.0 ([ROOT]/foo/reg1new)\n[FRESH] registry2 v0.1.0\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rebuild_on_mid_build_file_modification() {\n    let server = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let addr = server.local_addr().unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"root\", \"proc_macro_dep\"]\n            \"#,\n        )\n        .file(\n            \"root/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"root\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                proc_macro_dep = { path = \"../proc_macro_dep\" }\n            \"#,\n        )\n        .file(\n            \"root/src/lib.rs\",\n            r#\"\n                #[macro_use]\n                extern crate proc_macro_dep;\n\n                #[derive(Noop)]\n                pub struct X;\n            \"#,\n        )\n        .file(\n            \"proc_macro_dep/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"proc_macro_dep\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"proc_macro_dep/src/lib.rs\",\n            &format!(\n                r#\"\n                    extern crate proc_macro;\n\n                    use std::io::Read;\n                    use std::net::TcpStream;\n                    use proc_macro::TokenStream;\n\n                    #[proc_macro_derive(Noop)]\n                    pub fn noop(_input: TokenStream) -> TokenStream {{\n                        let mut stream = TcpStream::connect(\"{}\").unwrap();\n                        let mut v = Vec::new();\n                        stream.read_to_end(&mut v).unwrap();\n                        \"\".parse().unwrap()\n                    }}\n                \"#,\n                addr\n            ),\n        )\n        .build();\n    let root = p.root();\n\n    let t = thread::spawn(move || {\n        let socket = server.accept().unwrap().0;\n        sleep_ms(1000);\n        let mut file = OpenOptions::new()\n            .write(true)\n            .append(true)\n            .open(root.join(\"root/src/lib.rs\"))\n            .unwrap();\n        writeln!(file, \"// modified\").expect(\"Failed to append to root sources\");\n        drop(file);\n        drop(socket);\n        drop(server.accept().unwrap());\n    });\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] proc_macro_dep v0.1.0 ([ROOT]/foo/proc_macro_dep)\n[COMPILING] root v0.1.0 ([ROOT]/foo/root)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -v\").with_stderr_data(str![[r#\"\n[FRESH] proc_macro_dep v0.1.0 ([ROOT]/foo/proc_macro_dep)\n[DIRTY] root v0.1.0 ([ROOT]/foo/root): the file `root/src/lib.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] root v0.1.0 ([ROOT]/foo/root)\n[RUNNING] `rustc --crate-name root [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n\n    t.join().ok().unwrap();\n}\n\n#[cargo_test]\nfn dirty_both_lib_and_test() {\n    // This tests that all artifacts that depend on the results of a build\n    // script will get rebuilt when the build script reruns, even for separate\n    // commands. It does the following:\n    //\n    // 1. Project \"foo\" has a build script which will compile a small\n    //    staticlib to link against. Normally this would use the `cc` crate,\n    //    but here we just use rustc to avoid the `cc` dependency.\n    // 2. Build the library.\n    // 3. Build the unit test. The staticlib intentionally has a bad value.\n    // 4. Rewrite the staticlib with the correct value.\n    // 5. Build the library again.\n    // 6. Build the unit test. This should recompile.\n\n    let slib = |n| {\n        format!(\n            r#\"\n                #[no_mangle]\n                pub extern \"C\" fn doit() -> i32 {{\n                    return {};\n                }}\n            \"#,\n            n\n        )\n    };\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern \"C\" {\n                    fn doit() -> i32;\n                }\n\n                #[test]\n                fn t1() {\n                    assert_eq!(unsafe { doit() }, 1, \"doit assert failure\");\n                }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                use std::path::PathBuf;\n                use std::process::Command;\n\n                fn main() {\n                    let rustc = env::var_os(\"RUSTC\").unwrap();\n                    let out_dir = PathBuf::from(env::var(\"OUT_DIR\").unwrap());\n                    assert!(\n                        Command::new(rustc)\n                            .args(&[\n                                \"--crate-type=staticlib\",\n                                \"--out-dir\",\n                                out_dir.to_str().unwrap(),\n                                \"slib.rs\"\n                            ])\n                            .status()\n                            .unwrap()\n                            .success(),\n                        \"slib build failed\"\n                    );\n                    println!(\"cargo::rustc-link-lib=slib\");\n                    println!(\"cargo::rustc-link-search={}\", out_dir.display());\n                }\n            \"#,\n        )\n        .file(\"slib.rs\", &slib(2))\n        .build();\n\n    p.cargo(\"build\").run();\n\n    // 2 != 1\n    p.cargo(\"test --lib\")\n        .with_status(101)\n        .with_stdout_data(\"...\\n[..]doit assert failure[..]\\n...\")\n        .run();\n\n    if is_coarse_mtime() {\n        // #5918\n        sleep_ms(1000);\n    }\n    // Fix the mistake.\n    p.change_file(\"slib.rs\", &slib(1));\n\n    p.cargo(\"build\").run();\n    // This should recompile with the new static lib, and the test should pass.\n    p.cargo(\"test --lib\").run();\n}\n\n#[cargo_test]\nfn script_fails_stay_dirty() {\n    // Check if a script is aborted (such as hitting Ctrl-C) that it will re-run.\n    // Steps:\n    // 1. Build to establish fingerprints.\n    // 2. Make a change that triggers the build script to re-run. Abort the\n    //    script while it is running.\n    // 3. Run the build again and make sure it re-runs the script.\n    let p = project()\n        .file(\n            \"build.rs\",\n            r#\"\n                mod helper;\n                fn main() {\n                    println!(\"cargo::rerun-if-changed=build.rs\");\n                    helper::doit();\n                }\n            \"#,\n        )\n        .file(\"helper.rs\", \"pub fn doit() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n    p.change_file(\"helper.rs\", r#\"pub fn doit() {panic!(\"Crash!\");}\"#);\n    p.cargo(\"build\")\n        .with_stderr_data(\"...\\n[..]Crash![..]\\n...\")\n        .with_status(101)\n        .run();\n    // There was a bug where this second call would be \"fresh\".\n    p.cargo(\"build\")\n        .with_stderr_data(\"...\\n[..]Crash![..]\\n...\")\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn simulated_docker_deps_stay_cached() {\n    // Test what happens in docker where the nanoseconds are zeroed out.\n    Package::new(\"regdep\", \"1.0.0\").publish();\n    Package::new(\"regdep_old_style\", \"1.0.0\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    Package::new(\"regdep_env\", \"1.0.0\")\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                println!(\"cargo::rerun-if-env-changed=SOMEVAR\");\n            }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    Package::new(\"regdep_rerun\", \"1.0.0\")\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                println!(\"cargo::rerun-if-changed=build.rs\");\n            }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            pathdep = { path = \"pathdep\" }\n            regdep = \"1.0\"\n            regdep_old_style = \"1.0\"\n            regdep_env = \"1.0\"\n            regdep_rerun = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate pathdep;\n            extern crate regdep;\n            extern crate regdep_old_style;\n            extern crate regdep_env;\n            extern crate regdep_rerun;\n            \",\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"pathdep/Cargo.toml\", &basic_manifest(\"pathdep\", \"1.0.0\"))\n        .file(\"pathdep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    let already_zero = {\n        // This happens on HFS with 1-second timestamp resolution,\n        // or other filesystems where it just so happens to write exactly on a\n        // 1-second boundary.\n        let metadata = fs::metadata(p.root().join(\"src/lib.rs\")).unwrap();\n        let mtime = FileTime::from_last_modification_time(&metadata);\n        mtime.nanoseconds() == 0\n    };\n\n    // Recursively remove `nanoseconds` from every path.\n    fn zeropath(path: &Path) {\n        for entry in walkdir::WalkDir::new(path)\n            .into_iter()\n            .filter_map(|e| e.ok())\n        {\n            let metadata = fs::metadata(entry.path()).unwrap();\n            let mtime = metadata.modified().unwrap();\n            let mtime_duration = mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap();\n            let trunc_mtime = FileTime::from_unix_time(mtime_duration.as_secs() as i64, 0);\n            let atime = metadata.accessed().unwrap();\n            let atime_duration = atime.duration_since(SystemTime::UNIX_EPOCH).unwrap();\n            let trunc_atime = FileTime::from_unix_time(atime_duration.as_secs() as i64, 0);\n            if let Err(e) = filetime::set_file_times(entry.path(), trunc_atime, trunc_mtime) {\n                // Windows doesn't allow changing filetimes on some things\n                // (directories, other random things I'm not sure why). Just\n                // ignore them.\n                if e.kind() == std::io::ErrorKind::PermissionDenied {\n                    println!(\"PermissionDenied filetime on {:?}\", entry.path());\n                } else {\n                    panic!(\"FileTime error on {:?}: {:?}\", entry.path(), e);\n                }\n            }\n        }\n    }\n    zeropath(&p.root());\n    zeropath(&paths::home());\n\n    if already_zero {\n        println!(\"already zero\");\n        // If it was already truncated, then everything stays fresh.\n        p.cargo(\"build -v\")\n            .with_stderr_data(\n                str![[r#\"\n[FRESH] pathdep [..]\n[FRESH] regdep [..]\n[FRESH] regdep_env [..]\n[FRESH] regdep_old_style [..]\n[FRESH] regdep_rerun [..]\n[FRESH] foo [..]\n[FINISHED] [..]\n\n\"#]]\n                .unordered(),\n            )\n            .run();\n    } else {\n        println!(\"not already zero\");\n        // It is not ideal that `foo` gets recompiled, but that is the current\n        // behavior. Currently mtimes are ignored for registry deps.\n        //\n        // Note that this behavior is due to the fact that `foo` has a build\n        // script in \"old\" mode where it doesn't print `rerun-if-*`. In this\n        // mode we use `Precalculated` to fingerprint a path dependency, where\n        // `Precalculated` is an opaque string which has the most recent mtime\n        // in it. It differs between builds because one has nsec=0 and the other\n        // likely has a nonzero nsec. Hence, the rebuild.\n        p.cargo(\"build -v\")\n            .with_stderr_data(\n                str![[r#\"\n[FRESH] regdep [..]\n[FRESH] pathdep [..]\n[FRESH] regdep_env [..]\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the precalculated components changed\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FRESH] regdep_rerun [..]\n[FRESH] regdep_old_style [..]\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n                .unordered(),\n            )\n            .run();\n    }\n}\n\n#[cargo_test]\nfn metadata_change_invalidates() {\n    // (key, value, value-updated, env-var-name)\n    let scenarios = [\n        (\n            \"description\",\n            r#\"\"foo\"\"#,\n            r#\"\"foo_updated\"\"#,\n            \"CARGO_PKG_DESCRIPTION\",\n        ),\n        (\n            \"homepage\",\n            r#\"\"foo\"\"#,\n            r#\"\"foo_updated\"\"#,\n            \"CARGO_PKG_HOMEPAGE\",\n        ),\n        (\n            \"repository\",\n            r#\"\"foo\"\"#,\n            r#\"\"foo_updated\"\"#,\n            \"CARGO_PKG_REPOSITORY\",\n        ),\n        (\n            \"license\",\n            r#\"\"foo\"\"#,\n            r#\"\"foo_updated\"\"#,\n            \"CARGO_PKG_LICENSE\",\n        ),\n        (\n            \"license-file\",\n            r#\"\"foo\"\"#,\n            r#\"\"foo_updated\"\"#,\n            \"CARGO_PKG_LICENSE_FILE\",\n        ),\n        (\n            \"authors\",\n            r#\"[\"foo\"]\"#,\n            r#\"[\"foo_updated\"]\"#,\n            \"CARGO_PKG_AUTHORS\",\n        ),\n        (\n            \"rust-version\",\n            r#\"\"1.0.0\"\"#,\n            r#\"\"1.0.1\"\"#,\n            \"CARGO_PKG_RUST_VERSION\",\n        ),\n        (\"readme\", r#\"\"foo\"\"#, r#\"\"foo_updated\"\"#, \"CARGO_PKG_README\"),\n    ];\n    let base_cargo_toml = r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                \"#;\n\n    let p = project().build();\n    for (key, value, value_updated, env_var) in scenarios {\n        p.change_file(\"Cargo.toml\", base_cargo_toml);\n        p.change_file(\n            \"src/main.rs\",\n            &format!(\n                r#\"\n            fn main() {{\n                let output = env!(\"{env_var}\");\n                println!(\"{{output}}\");\n            }}\n            \"#\n            ),\n        );\n\n        // Compile the first time\n        p.cargo(\"build\").run();\n\n        // Update the manifest, rebuild, and verify the build was invalided\n        p.change_file(\"Cargo.toml\", &format!(\"{base_cargo_toml}\\n{key} = {value}\"));\n        p.cargo(\"build -v\")\n            .with_stderr_data(format!(\n                r#\"[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable {env_var} changed\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\"#\n            ))\n            .run();\n\n        // Remove references to the metadata and rebuild\n        p.change_file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                println!(\"foo\");\n            }\n            \"#,\n        );\n        p.cargo(\"build\").run();\n\n        // Update the manifest value and verify the build is NOT invalidated.\n        p.change_file(\n            \"Cargo.toml\",\n            &format!(\"{base_cargo_toml}\\n{key} = {value_updated}\"),\n        );\n\n        p.cargo(\"build -v\")\n            .with_stderr_data(str![[r#\"\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n            .run();\n    }\n}\n\n#[cargo_test]\nfn edition_change_invalidates() {\n    const MANIFEST: &str = r#\"\n        [package]\n        name = \"foo\"\n        version = \"0.1.0\"\n    \"#;\n    let p = project()\n        .file(\"Cargo.toml\", MANIFEST)\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build\").run();\n    p.change_file(\"Cargo.toml\", &format!(\"{}edition = \\\"2018\\\"\", MANIFEST));\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.change_file(\n        \"Cargo.toml\",\n        &format!(\n            r#\"{}edition = \"2018\"\n            [lib]\n            edition = \"2015\"\n            \"#,\n            MANIFEST\n        ),\n    );\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `edition` is set on library `foo` which is deprecated\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `edition` is set on library `foo` which is deprecated\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert_eq!(p.glob(\"target/debug/deps/libfoo-*.rlib\").count(), 1);\n}\n\n#[cargo_test]\nfn rename_with_path_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = 'a' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate a; pub fn foo() { a::foo(); }\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                b = { path = 'b' }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"extern crate b; pub fn foo() { b::foo() }\")\n        .file(\n            \"a/b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"a/b/src/lib.rs\", \"pub fn foo() { }\");\n    let p = p.build();\n\n    p.cargo(\"build\").run();\n\n    // Now rename the root directory and rerun `cargo run`. Not only should we\n    // not build anything but we also shouldn't crash.\n    let mut new = p.root();\n    new.pop();\n    new.push(\"foo2\");\n\n    fs::rename(p.root(), &new).unwrap();\n\n    p.cargo(\"build\")\n        .cwd(&new)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn move_target_directory_with_path_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate a; pub use a::print_msg;\")\n        .file(\n            \"a/build.rs\",\n            r###\"\n                use std::env;\n                use std::fs;\n                use std::path::Path;\n\n                fn main() {\n                    println!(\"cargo::rerun-if-changed=build.rs\");\n                    let out_dir = env::var(\"OUT_DIR\").unwrap();\n                    let dest_path = Path::new(&out_dir).join(\"hello.rs\");\n                    fs::write(&dest_path, r#\"\n                        pub fn message() -> &'static str {\n                            \"Hello, World!\"\n                        }\n                    \"#).unwrap();\n                }\n            \"###,\n        )\n        .file(\n            \"a/src/lib.rs\",\n            r#\"\n            include!(concat!(env!(\"OUT_DIR\"), \"/hello.rs\"));\n            pub fn print_msg() { message(); }\n            \"#,\n        );\n    let p = p.build();\n\n    let mut parent = p.root();\n    parent.pop();\n\n    p.cargo(\"build\").run();\n\n    let new_target = p.root().join(\"target2\");\n    fs::rename(p.root().join(\"target\"), &new_target).unwrap();\n\n    p.cargo(\"build\")\n        .env(\"CARGO_TARGET_DIR\", &new_target)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rerun_if_changes() {\n    let p = project()\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rerun-if-env-changed=FOO\");\n                    if std::env::var(\"FOO\").is_ok() {\n                        println!(\"cargo::rerun-if-env-changed=BAR\");\n                    }\n                }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -v\")\n        .env(\"FOO\", \"1\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the env variable FOO changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build\")\n        .env(\"FOO\", \"1\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -v\")\n        .env(\"FOO\", \"1\")\n        .env(\"BAR\", \"1\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the env variable BAR changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build\")\n        .env(\"FOO\", \"1\")\n        .env(\"BAR\", \"1\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -v\")\n        .env(\"BAR\", \"2\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the env variable FOO changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build\")\n        .env(\"BAR\", \"2\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn channel_shares_filenames() {\n    // Test that different \"nightly\" releases use the same output filename.\n\n    // Create separate rustc binaries to emulate running different toolchains.\n    let nightly1 = format!(\n        \"\\\nrustc 1.44.0-nightly (38114ff16 2020-03-21)\nbinary: rustc\ncommit-hash: 38114ff16e7856f98b2b4be7ab4cd29b38bed59a\ncommit-date: 2020-03-21\nhost: {}\nrelease: 1.44.0-nightly\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    let nightly2 = format!(\n        \"\\\nrustc 1.44.0-nightly (a5b09d354 2020-03-31)\nbinary: rustc\ncommit-hash: a5b09d35473615e7142f5570f5c5fad0caf68bd2\ncommit-date: 2020-03-31\nhost: {}\nrelease: 1.44.0-nightly\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    let beta1 = format!(\n        \"\\\nrustc 1.43.0-beta.3 (4c587bbda 2020-03-25)\nbinary: rustc\ncommit-hash: 4c587bbda04ab55aaf56feab11dfdfe387a85d7a\ncommit-date: 2020-03-25\nhost: {}\nrelease: 1.43.0-beta.3\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    let beta2 = format!(\n        \"\\\nrustc 1.42.0-beta.5 (4e1c5f0e9 2020-02-28)\nbinary: rustc\ncommit-hash: 4e1c5f0e9769a588b91c977e3d81e140209ef3a2\ncommit-date: 2020-02-28\nhost: {}\nrelease: 1.42.0-beta.5\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    let stable1 = format!(\n        \"\\\nrustc 1.42.0 (b8cedc004 2020-03-09)\nbinary: rustc\ncommit-hash: b8cedc00407a4c56a3bda1ed605c6fc166655447\ncommit-date: 2020-03-09\nhost: {}\nrelease: 1.42.0\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    let stable2 = format!(\n        \"\\\nrustc 1.41.1 (f3e1a954d 2020-02-24)\nbinary: rustc\ncommit-hash: f3e1a954d2ead4e2fc197c7da7d71e6c61bad196\ncommit-date: 2020-02-24\nhost: {}\nrelease: 1.41.1\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    let compiler = project()\n        .at(\"compiler\")\n        .file(\"Cargo.toml\", &basic_manifest(\"compiler\", \"0.1.0\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                if std::env::args_os().any(|a| a == \"-vV\") {\n                    print!(\"{}\", env!(\"FUNKY_VERSION_TEST\"));\n                    return;\n                }\n                let mut cmd = std::process::Command::new(\"rustc\");\n                cmd.args(std::env::args_os().skip(1));\n                assert!(cmd.status().unwrap().success());\n            }\n            \"#,\n        )\n        .build();\n\n    let makeit = |version, vv| {\n        // Force a rebuild.\n        compiler.target_debug_dir().join(\"deps\").rm_rf();\n        compiler.cargo(\"build\").env(\"FUNKY_VERSION_TEST\", vv).run();\n        fs::rename(compiler.bin(\"compiler\"), compiler.bin(version)).unwrap();\n    };\n    makeit(\"nightly1\", nightly1);\n    makeit(\"nightly2\", nightly2);\n    makeit(\"beta1\", beta1);\n    makeit(\"beta2\", beta2);\n    makeit(\"stable1\", stable1);\n    makeit(\"stable2\", stable2);\n\n    // Run `cargo check` with different rustc versions to observe its behavior.\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    // Runs `cargo check` and returns the rmeta filename created.\n    // Checks that the freshness matches the given value.\n    let check = |version, fresh| -> String {\n        let output = p\n            .cargo(\"check --message-format=json\")\n            .env(\"RUSTC\", compiler.bin(version))\n            .run();\n        // Collect the filenames generated.\n        let mut artifacts: Vec<_> = std::str::from_utf8(&output.stdout)\n            .unwrap()\n            .lines()\n            .filter_map(|line| {\n                let value: serde_json::Value = serde_json::from_str(line).unwrap();\n                if value[\"reason\"].as_str().unwrap() == \"compiler-artifact\" {\n                    assert_eq!(value[\"fresh\"].as_bool().unwrap(), fresh);\n                    let filenames = value[\"filenames\"].as_array().unwrap();\n                    assert_eq!(filenames.len(), 1);\n                    Some(filenames[0].to_string())\n                } else {\n                    None\n                }\n            })\n            .collect();\n        // Should only generate one rmeta file.\n        assert_eq!(artifacts.len(), 1);\n        artifacts.pop().unwrap()\n    };\n\n    let nightly1_name = check(\"nightly1\", false);\n    assert_eq!(check(\"nightly1\", true), nightly1_name);\n    assert_eq!(check(\"nightly2\", false), nightly1_name); // same as before\n    assert_eq!(check(\"nightly2\", true), nightly1_name);\n    // Should rebuild going back to nightly1.\n    assert_eq!(check(\"nightly1\", false), nightly1_name);\n\n    let beta1_name = check(\"beta1\", false);\n    assert_ne!(beta1_name, nightly1_name);\n    assert_eq!(check(\"beta1\", true), beta1_name);\n    assert_eq!(check(\"beta2\", false), beta1_name); // same as before\n    assert_eq!(check(\"beta2\", true), beta1_name);\n    // Should rebuild going back to beta1.\n    assert_eq!(check(\"beta1\", false), beta1_name);\n\n    let stable1_name = check(\"stable1\", false);\n    assert_ne!(stable1_name, nightly1_name);\n    assert_ne!(stable1_name, beta1_name);\n    let stable2_name = check(\"stable2\", false);\n    assert_ne!(stable1_name, stable2_name);\n    // Check everything is fresh.\n    assert_eq!(check(\"stable1\", true), stable1_name);\n    assert_eq!(check(\"stable2\", true), stable2_name);\n    assert_eq!(check(\"beta1\", true), beta1_name);\n    assert_eq!(check(\"nightly1\", true), nightly1_name);\n}\n\n#[cargo_test]\nfn linking_interrupted() {\n    // Interrupt during the linking phase shouldn't leave test executable as \"fresh\".\n\n    // This is used to detect when linking starts, then to pause the linker so\n    // that the test can kill cargo.\n    let link_listener = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let link_addr = link_listener.local_addr().unwrap();\n\n    // This is used to detect when rustc exits.\n    let rustc_listener = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let rustc_addr = rustc_listener.local_addr().unwrap();\n\n    // Create a linker that we can interrupt.\n    let linker = project()\n        .at(\"linker\")\n        .file(\"Cargo.toml\", &basic_manifest(\"linker\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            &r#\"\n            fn main() {\n                // Figure out the output filename.\n                let output = match std::env::args().find(|a| a.starts_with(\"/OUT:\")) {\n                    Some(s) => s[5..].to_string(),\n                    None => {\n                        let mut args = std::env::args();\n                        loop {\n                            if args.next().unwrap() == \"-o\" {\n                                break;\n                            }\n                        }\n                        args.next().unwrap()\n                    }\n                };\n                std::fs::remove_file(&output).unwrap();\n                std::fs::write(&output, \"\").unwrap();\n                // Tell the test that we are ready to be interrupted.\n                let mut socket = std::net::TcpStream::connect(\"__ADDR__\").unwrap();\n                // Wait for the test to kill us.\n                std::thread::sleep(std::time::Duration::new(60, 0));\n            }\n            \"#\n            .replace(\"__ADDR__\", &link_addr.to_string()),\n        )\n        .build();\n    linker.cargo(\"build\").run();\n\n    // Create a wrapper around rustc that will tell us when rustc is finished.\n    let rustc = project()\n        .at(\"rustc-waiter\")\n        .file(\"Cargo.toml\", &basic_manifest(\"rustc-waiter\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            &r#\"\n            fn main() {\n                let mut conn = None;\n                // Check for a normal build (not -vV or --print).\n                if std::env::args().any(|arg| arg == \"t1\") {\n                    // Tell the test that rustc has started.\n                    conn = Some(std::net::TcpStream::connect(\"__ADDR__\").unwrap());\n                }\n                let status = std::process::Command::new(\"rustc\")\n                    .args(std::env::args().skip(1))\n                    .status()\n                    .expect(\"rustc to run\");\n                std::process::exit(status.code().unwrap_or(1));\n            }\n            \"#\n            .replace(\"__ADDR__\", &rustc_addr.to_string()),\n        )\n        .build();\n    rustc.cargo(\"build\").run();\n\n    // Build it once so that the fingerprint gets saved to disk.\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"tests/t1.rs\", \"\")\n        .build();\n    p.cargo(\"test --test t1 --no-run\").run();\n\n    // Make a change, start a build, then interrupt it.\n    p.change_file(\"src/lib.rs\", \"// modified\");\n    let linker_env = format!(\"CARGO_TARGET_{}_LINKER\", rustc_host_env());\n    // NOTE: This assumes that the paths to the linker or rustc are not in the\n    // fingerprint. But maybe they should be?\n    let mut cmd = p\n        .cargo(\"test --test t1 --no-run\")\n        .env(&linker_env, linker.bin(\"linker\"))\n        .env(\"RUSTC\", rustc.bin(\"rustc-waiter\"))\n        .build_command();\n    let mut child = cmd\n        .stdout(Stdio::null())\n        .stderr(Stdio::null())\n        .env(\"__CARGO_TEST_SETSID_PLEASE_DONT_USE_ELSEWHERE\", \"1\")\n        .spawn()\n        .unwrap();\n    // Wait for rustc to start.\n    let mut rustc_conn = rustc_listener.accept().unwrap().0;\n    // Wait for linking to start.\n    drop(link_listener.accept().unwrap());\n\n    // Interrupt the child.\n    death::ctrl_c(&mut child);\n    assert!(!child.wait().unwrap().success());\n    // Wait for rustc to exit. If we don't wait, then the command below could\n    // start while rustc is still being torn down.\n    let mut buf = [0];\n    drop(rustc_conn.read_exact(&mut buf));\n\n    // Build again, shouldn't be fresh.\n    p.cargo(\"test --test t1 -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the config settings changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[RUNNING] `rustc --crate-name t1 [..]\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/t1-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[cfg_attr(\n    not(all(target_arch = \"x86_64\", target_os = \"windows\", target_env = \"msvc\")),\n    ignore\n)]\nfn lld_is_fresh() {\n    // Check for bug when using lld linker that it remains fresh with dylib.\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [target.x86_64-pc-windows-msvc]\n                linker = \"rust-lld\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"dylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_in_code_causes_rebuild() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    println!(\"{:?}\", option_env!(\"FOO\"));\n                    println!(\"{:?}\", option_env!(\"FOO\\nBAR\"));\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").env_remove(\"FOO\").run();\n    p.cargo(\"build\")\n        .env_remove(\"FOO\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -v\")\n        .env(\"FOO\", \"bar\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable FOO changed\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build\")\n        .env(\"FOO\", \"bar\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -v\")\n        .env(\"FOO\", \"baz\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable FOO changed\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build\")\n        .env(\"FOO\", \"baz\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -v\")\n        .env_remove(\"FOO\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable FOO changed\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build\")\n        .env_remove(\"FOO\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let interesting = \" #!$\\nabc\\r\\\\\\t\\u{8}\\r\\n\";\n    p.cargo(\"build\").env(\"FOO\", interesting).run();\n    p.cargo(\"build\")\n        .env(\"FOO\", interesting)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build\").env(\"FOO\\nBAR\", interesting).run();\n    p.cargo(\"build\")\n        .env(\"FOO\\nBAR\", interesting)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_build_script_no_rebuild() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-env=FOO=bar\");\n                }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    println!(\"{:?}\", env!(\"FOO\"));\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_env_changes() {\n    // Checks that changes to the env var CARGO in the dep-info file triggers\n    // a rebuild.\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    println!(\"{:?}\", env!(\"CARGO\"));\n                }\n            \"#,\n        )\n        .build();\n\n    let cargo_exe = crate::utils::cargo_exe();\n    let other_cargo_path = p.root().join(cargo_exe.file_name().unwrap());\n    std::fs::hard_link(&cargo_exe, &other_cargo_path).unwrap();\n    let other_cargo = || {\n        let mut pb = cargo_test_support::process(&other_cargo_path);\n        pb.cwd(p.root());\n        cargo_test_support::execs().with_process_builder(pb)\n    };\n\n    p.cargo(\"check\").run();\n    other_cargo()\n        .arg(\"check\")\n        .arg(\"-v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v1.0.0 ([ROOT]/foo): the environment variable CARGO changed\n[CHECKING] foo v1.0.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // And just to confirm that without using env! it doesn't rebuild.\n    p.change_file(\"src/main.rs\", \"fn main() {}\");\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v1.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    other_cargo()\n        .arg(\"check\")\n        .arg(\"-v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v1.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn changing_linker() {\n    // Changing linker should rebuild.\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"build\").run();\n    let linker_env = format!(\"CARGO_TARGET_{}_LINKER\", rustc_host_env());\n    p.cargo(\"build --verbose\")\n        .env(&linker_env, \"nonexistent-linker\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the config settings changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -C linker=nonexistent-linker [..]`\n[ERROR] linker `nonexistent-linker` not found\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn verify_source_before_recompile() {\n    Package::new(\"bar\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n            [source.crates-io]\n            replace-with = 'vendor'\n\n            [source.vendor]\n            directory = 'vendor'\n        \"#,\n    );\n    // Sanity check: vendoring works correctly.\n    p.cargo(\"check --verbose\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.0\n[RUNNING] `rustc --crate-name bar [..] [ROOT]/foo/vendor/bar/src/lib.rs [..]\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // Now modify vendored crate.\n    p.change_file(\n        \"vendor/bar/src/lib.rs\",\n        r#\"compile_error!(\"You shall not pass!\");\"#,\n    );\n    // Should ignore modified sources without any recompile.\n    p.cargo(\"check --verbose\")\n        .with_stderr_data(str![[r#\"\n[FRESH] bar v0.1.0\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Add a `RUSTFLAGS` to trigger a recompile.\n    //\n    // Cargo should refuse to build because of checksum verification failure.\n    // Cargo shouldn't recompile dependency `bar`.\n    p.cargo(\"check --verbose\")\n        .env(\"RUSTFLAGS\", \"-W warnings\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the listed checksum of `[ROOT]/foo/vendor/bar/src/lib.rs` has changed:\nexpected: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\nactual:   66e843918c1d4ea8231af814f9f958958808249d4407de01114acb730ecd9bdf\n\ndirectory sources are not intended to be edited, if modifications are required then it is recommended that `[patch]` is used with a forked copy of the source\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn skip_mtime_check_in_selected_cargo_home_subdirs() {\n    let p = project()\n        .at(\"cargo_home/registry/foo\")\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    let project_root = p.root();\n    let cargo_home = project_root.parent().unwrap().parent().unwrap();\n    p.cargo(\"check -v\")\n        .env(\"CARGO_HOME\", &cargo_home)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.5.0 ([ROOT]/cargo_home/registry/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.change_file(\"src/lib.rs\", \"illegal syntax\");\n    p.cargo(\"check -v\")\n        .env(\"CARGO_HOME\", &cargo_home)\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.5.0 ([ROOT]/cargo_home/registry/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn use_mtime_cache_in_cargo_home() {\n    let p = project()\n        .at(\"cargo_home/foo\")\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    let project_root = p.root();\n    let cargo_home = project_root.parent().unwrap();\n    p.cargo(\"check -v\")\n        .env(\"CARGO_HOME\", &cargo_home)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.5.0 ([ROOT]/cargo_home/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..] src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.change_file(\"src/lib.rs\", \"illegal syntax\");\n    p.cargo(\"check -v\")\n        .env(\"CARGO_HOME\", &cargo_home)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/cargo_home/foo): the file `src/lib.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[CHECKING] foo v0.5.0 ([ROOT]/cargo_home/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]\n...\n[ERROR] could not compile `foo` (lib) due to 1 previous error\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn incremental_build_script_execution_got_new_mtime_and_cargo_check() {\n    // See https://github.com/rust-lang/cargo/issues/16104\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"touch-me\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rerun-if-changed=touch-me\") }\"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    if is_coarse_mtime() {\n        sleep_ms(1000);\n    }\n\n    p.change_file(\"touch-me\", \"oops\");\n\n    // The first one is expected to rerun build script\n    p.cargo(\"check -v\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the file `touch-me` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // subsequent cargo check gets stuck...\n    p.cargo(\"check -v\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -v\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn symlink_to_package() {\n    // Illustrates what happens when the path is a symlink, and the symlink\n    // target changes.\n    if !cargo_test_support::symlink_supported() {\n        return;\n    }\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    bar::bar();\n                }\n            \"#,\n        )\n        .file(\"bar1/Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n        .file(\n            \"bar1/src/lib.rs\",\n            r#\"\n                pub fn bar() {\n                    println!(\"one\");\n                }\n            \"#,\n        )\n        .file(\"bar2/Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n        .file(\n            \"bar2/src/lib.rs\",\n            r#\"\n                pub fn bar() {\n                    println!(\"two\");\n                }\n            \"#,\n        )\n        .symlink_dir(\"bar1\", \"bar\")\n        .build();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v1.0.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    let bar_path = p.root().join(\"bar\");\n    cargo_util::paths::remove_file(&bar_path).unwrap();\n    p.symlink(\"bar2\", \"bar\");\n    // FIXME: This is not rebuilding when it should.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/freshness_checksum.rs",
    "content": "//! Tests for checksum-based fingerprinting (rebuild detection).\n\nuse std::fs::{self, OpenOptions};\nuse std::io::prelude::*;\nuse std::net::TcpListener;\nuse std::process::Stdio;\nuse std::thread;\n\nuse crate::prelude::*;\nuse cargo_test_support::assert_deps_contains;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{\n    basic_lib_manifest, basic_manifest, project, rustc_host, rustc_host_env, str,\n};\n\nuse super::death;\n\n#[cargo_test]\nfn non_nightly_fails() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .with_stderr_data(str![[r#\"\n[ERROR] the `-Z` flag is only accepted on the nightly channel of Cargo, but this is the `stable` channel\nSee https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels.\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn checksum_actually_uses_checksum() {\n    let p = project()\n        .file(\"src/main.rs\", \"mod a; fn main() {}\")\n        .file(\"src/a.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.root().move_into_the_future();\n\n    p.cargo(\"check -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn checksum_build_compatible_with_mtime_build() {\n    let p = project()\n        .file(\"src/main.rs\", \"mod a; fn main() {}\")\n        .file(\"src/a.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn same_size_different_content() {\n    let p = project()\n        .file(\"src/main.rs\", \"mod a; fn main() {}\")\n        .file(\"src/a.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.change_file(\"src/main.rs\", \"mod a;fn main() { }\");\n\n    p.cargo(\"check -v -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the file `src/main.rs` has changed (checksum didn't match, blake3=26aa07e1adab787246f9d333be65d2eb78dd5fd0fee834ba7a769098b4b651bc != blake3=fc1a42e376d9c148227c13de41b77143f6b5b8132d2b204b63cdbc9326848894)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"-Zbinary-dep-depinfo is unstable, also requires -Zchecksum-hash-algorithm\"\n)]\nfn binary_depinfo_correctly_encoded() {\n    Package::new(\"regdep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn f() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [dependencies]\n            regdep = \"0.1\"\n            bar = {path = \"./bar\"}\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                regdep::f();\n                bar::f();\n            }\n            \"#,\n        )\n        /*********** Path Dependency `bar` ***********/\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn f() {}\")\n        .build();\n\n    let host = rustc_host();\n    p.cargo(\"build -Zbinary-dep-depinfo -Zchecksum-freshness --target\")\n        .arg(&host)\n        .masquerade_as_nightly_cargo(&[\"binary-dep-depinfo\", \"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n...\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n...\n\n\"#]])\n        .run();\n\n    assert_deps_contains(\n        &p,\n        &format!(\"target/{}/debug/.fingerprint/foo-*/dep-bin-foo\", host),\n        &[\n            (0, \"src/main.rs\"),\n            (1, &format!(\"{}/debug/deps/libbar-*.rlib\", host)),\n            (1, &format!(\"{}/debug/deps/libregdep-*.rlib\", host)),\n        ],\n    );\n\n    // Make sure it stays fresh.\n    p.cargo(\"build -Zbinary-dep-depinfo -Zchecksum-freshness --target\")\n        .arg(&host)\n        .masquerade_as_nightly_cargo(&[\"binary-dep-depinfo\", \"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn modifying_and_moving() {\n    let p = project()\n        .file(\"src/main.rs\", \"mod a; fn main() {}\")\n        .file(\"src/a.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.root().move_into_the_past();\n    p.root().join(\"target\").move_into_the_past();\n\n    p.change_file(\"src/a.rs\", \"#[allow(unused)]fn main() {}\");\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): file size changed (0 != 28) for `src/a.rs`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    fs::rename(&p.root().join(\"src/a.rs\"), &p.root().join(\"src/b.rs\")).unwrap();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\nerror[E0583]: file not found for module `a`\n...\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn rebuild_sub_package_then_while_package() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies.a]\n                path = \"a\"\n                [dependencies.b]\n                path = \"b\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate a; extern crate b;\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                authors = []\n                version = \"0.0.1\"\n                edition = \"2015\"\n                [dependencies.b]\n                path = \"../b\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"extern crate b;\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\"b/src/lib.rs\", \"pub fn b() {}\");\n\n    p.cargo(\"build -Zchecksum-freshness -pb -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] b v0.0.1 ([ROOT]/foo/b): file size changed (0 != 13) for `b/src/lib.rs`\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[RUNNING] `rustc --crate-name b [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"src/lib.rs\",\n        \"extern crate a; extern crate b; pub fn toplevel() {}\",\n    );\n\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] b v0.0.1 ([ROOT]/foo/b)\n[DIRTY] a v0.0.1 ([ROOT]/foo/a): the dependency `b` was rebuilt ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[RUNNING] `rustc --crate-name a [..]\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the dependency `b` was rebuilt ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn changing_lib_features_caches_targets() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                foo = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -Zchecksum-freshness --features foo\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    /* Targets should be cached from the first build */\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -Zchecksum-freshness --features foo\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn changing_profiles_caches_targets() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                panic = \"abort\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"test -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .run();\n\n    /* Targets should be cached from the first build */\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"test -Zchecksum-freshness foo\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn changing_bin_paths_common_target_features_caches_targets() {\n    // Make sure dep_cache crate is built once per feature\n    let p = project()\n        .no_manifest()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                target-dir = \"./target\"\n            \"#,\n        )\n        .file(\n            \"dep_crate/Cargo.toml\",\n            r#\"\n                [package]\n                name    = \"dep_crate\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                ftest  = []\n            \"#,\n        )\n        .file(\n            \"dep_crate/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"ftest\")]\n                pub fn yo() {\n                    println!(\"ftest on\")\n                }\n                #[cfg(not(feature = \"ftest\"))]\n                pub fn yo() {\n                    println!(\"ftest off\")\n                }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name    = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                dep_crate = {path = \"../dep_crate\", features = []}\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"a/src/main.rs\",\n            r#\"\n                extern crate dep_crate;\n                use dep_crate::yo;\n                fn main() {\n                    yo();\n                }\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name    = \"b\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                dep_crate = {path = \"../dep_crate\", features = [\"ftest\"]}\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"b/src/main.rs\",\n            r#\"\n                extern crate dep_crate;\n                use dep_crate::yo;\n                fn main() {\n                    yo();\n                }\n            \"#,\n        )\n        .build();\n\n    /* Build and rebuild a/. Ensure dep_crate only builds once */\n    p.cargo(\"run -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .cwd(\"a\")\n        .with_stdout_data(str![[r#\"\nftest off\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] dep_crate v0.0.1 ([ROOT]/foo/dep_crate)\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/./target/debug/a[EXE]`\n\n\"#]])\n        .run();\n    p.cargo(\"clean -p a\").cwd(\"a\").run();\n    p.cargo(\"run -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .cwd(\"a\")\n        .with_stdout_data(str![[r#\"\nftest off\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/./target/debug/a[EXE]`\n\n\"#]])\n        .run();\n\n    /* Build and rebuild b/. Ensure dep_crate only builds once */\n    p.cargo(\"run -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .cwd(\"b\")\n        .with_stdout_data(str![[r#\"\nftest on\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] dep_crate v0.0.1 ([ROOT]/foo/dep_crate)\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/./target/debug/b[EXE]`\n\n\"#]])\n        .run();\n    p.cargo(\"clean -p b\").cwd(\"b\").run();\n    p.cargo(\"run -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .cwd(\"b\")\n        .with_stdout_data(str![[r#\"\nftest on\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/./target/debug/b[EXE]`\n\n\"#]])\n        .run();\n\n    /* Build a/ package again. If we cache different feature dep builds correctly,\n     * this should not cause a rebuild of dep_crate */\n    p.cargo(\"clean -p a\").cwd(\"a\").run();\n    p.cargo(\"run -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .cwd(\"a\")\n        .with_stdout_data(str![[r#\"\nftest off\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/./target/debug/a[EXE]`\n\n\"#]])\n        .run();\n\n    /* Build b/ package again. If we cache different feature dep builds correctly,\n     * this should not cause a rebuild */\n    p.cargo(\"clean -p b\").cwd(\"b\").run();\n    p.cargo(\"run -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .cwd(\"b\")\n        .with_stdout_data(str![[r#\"\nftest on\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/./target/debug/b[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn changing_bin_features_caches_targets() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [features]\n                foo = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    let msg = if cfg!(feature = \"foo\") { \"feature on\" } else { \"feature off\" };\n                    println!(\"{}\", msg);\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.rename_run(\"foo\", \"off1\")\n        .with_stdout_data(str![[r#\"\nfeature off\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -Zchecksum-freshness --features foo\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.rename_run(\"foo\", \"on1\")\n        .with_stdout_data(str![[r#\"\nfeature on\n\n\"#]])\n        .run();\n\n    /* Targets should be cached from the first build */\n\n    let mut e = p.cargo(\"build -Zchecksum-freshness -v\");\n    e.masquerade_as_nightly_cargo(&[\"checksum-freshness\"]);\n\n    // MSVC does not include hash in binary filename, so it gets recompiled.\n    if cfg!(target_env = \"msvc\") {\n        e.with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the list of features changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    } else {\n        e.with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    }\n    e.run();\n    p.rename_run(\"foo\", \"off2\")\n        .with_stdout_data(str![[r#\"\nfeature off\n\n\"#]])\n        .run();\n\n    let mut e = p.cargo(\"build -Zchecksum-freshness --features foo -v\");\n    e.masquerade_as_nightly_cargo(&[\"checksum-freshness\"]);\n    if cfg!(target_env = \"msvc\") {\n        e.with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the list of features changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    } else {\n        e.with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n    }\n    e.run();\n    p.rename_run(\"foo\", \"on2\")\n        .with_stdout_data(str![[r#\"\nfeature on\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn rebuild_tests_if_lib_changes() {\n    let p = project()\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\"tests/foo-test.rs\", \"extern crate foo;\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"test -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n\n    p.change_file(\"src/lib.rs\", \"\");\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"test -Zchecksum-freshness -v --test foo-test\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the dependency `foo` was rebuilt ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo_test [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/foo_test-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn no_rebuild_transitive_target_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n                [dev-dependencies]\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"tests/foo.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.foo.dependencies]\n                c = { path = \"../c\" }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                c = { path = \"../c\" }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\"c/Cargo.toml\", &basic_manifest(\"c\", \"0.0.1\"))\n        .file(\"c/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"test -Zchecksum-freshness --no-run\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] c v0.0.1 ([ROOT]/foo/c)\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[EXECUTABLE] tests/foo.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn rerun_if_changed_in_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"a/build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rerun-if-changed=build.rs\");\n                }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn same_build_dir_cached_packages() {\n    let p = project()\n        .no_manifest()\n        .file(\n            \"a1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                b = { path = \"../b\" }\n            \"#,\n        )\n        .file(\"a1/src/lib.rs\", \"\")\n        .file(\n            \"a2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                b = { path = \"../b\" }\n            \"#,\n        )\n        .file(\"a2/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                c = { path = \"../c\" }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"c/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"c\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                d = { path = \"../d\" }\n            \"#,\n        )\n        .file(\"c/src/lib.rs\", \"\")\n        .file(\"d/Cargo.toml\", &basic_manifest(\"d\", \"0.0.1\"))\n        .file(\"d/src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                target-dir = \"./target\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .cwd(\"a1\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 3 packages to latest compatible versions\n[COMPILING] d v0.0.1 ([ROOT]/foo/d)\n[COMPILING] c v0.0.1 ([ROOT]/foo/c)\n[COMPILING] b v0.0.1 ([ROOT]/foo/b)\n[COMPILING] a1 v0.0.1 ([ROOT]/foo/a1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .cwd(\"a2\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 3 packages to latest compatible versions\n[COMPILING] a2 v0.0.1 ([ROOT]/foo/a2)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn no_rebuild_if_build_artifacts_move_backwards_in_time() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n\n    p.root().move_into_the_past();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stdout_data(str![])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn rebuild_if_environment_changes() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                description = \"old desc\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    println!(\"{}\", env!(\"CARGO_PKG_DESCRIPTION\"));\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stdout_data(str![[r#\"\nold desc\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            description = \"new desc\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n        \"#,\n    );\n\n    p.cargo(\"run -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stdout_data(str![[r#\"\nnew desc\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the environment variable CARGO_PKG_DESCRIPTION changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn no_rebuild_when_rename_dir() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n\n                [dependencies]\n                foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\"src/_unused.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.0.1\"))\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\"foo/build.rs\", \"fn main() {}\")\n        .build();\n\n    // make sure the most recently modified file is `src/lib.rs`, not\n    // `Cargo.toml`, to expose a historical bug where we forgot to strip the\n    // `Cargo.toml` path from looking for the package root.\n    fs::write(p.root().join(\"src/lib.rs\"), \"\").unwrap();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    let mut new = p.root();\n    new.pop();\n    new.push(\"bar\");\n    fs::rename(p.root(), &new).unwrap();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .cwd(&new)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn unused_optional_dep() {\n    Package::new(\"registry1\", \"0.1.0\").publish();\n    Package::new(\"registry2\", \"0.1.0\").publish();\n    Package::new(\"registry3\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"p\"\n                authors = []\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n                baz = { path = \"baz\" }\n                registry1 = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dev-dependencies]\n                registry2 = \"*\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                registry3 = { version = \"*\", optional = true }\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn path_dev_dep_registry_updates() {\n    Package::new(\"registry1\", \"0.1.0\").publish();\n    Package::new(\"registry2\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"p\"\n                authors = []\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                registry1 = \"*\"\n\n                [dev-dependencies]\n                baz = { path = \"../baz\"}\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                registry2 = \"*\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn change_panic_mode() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = ['bar', 'baz']\n                [profile.dev]\n                panic = 'abort'\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                bar = { path = '../bar' }\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"extern crate bar;\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness -p bar\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness -p baz\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn dont_rebuild_based_on_plugins() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n\n                [workspace]\n                members = ['baz']\n\n                [dependencies]\n                proc-macro-thing = { path = 'proc-macro-thing' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"proc-macro-thing/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"proc-macro-thing\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                qux = { path = '../qux' }\n            \"#,\n        )\n        .file(\"proc-macro-thing/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                qux = { path = '../qux' }\n            \"#,\n        )\n        .file(\"baz/src/main.rs\", \"fn main() {}\")\n        .file(\"qux/Cargo.toml\", &basic_manifest(\"qux\", \"0.1.1\"))\n        .file(\"qux/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness -p baz\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness -p bar\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn reuse_workspace_lib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n\n                [workspace]\n\n                [dependencies]\n                baz = { path = 'baz' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.1\"))\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"test -Zchecksum-freshness -p baz -v --no-run\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] baz v0.1.1 ([ROOT]/foo/baz)\n[RUNNING] `rustc --crate-name baz [..]\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/baz-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn reuse_shared_build_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                shared = {path = \"shared\"}\n\n                [workspace]\n                members = [\"shared\", \"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"shared/Cargo.toml\", &basic_manifest(\"shared\", \"0.0.1\"))\n        .file(\"shared/src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [build-dependencies]\n                shared = { path = \"../shared\" }\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"bar/build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness --workspace\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    // This should not recompile!\n    p.cargo(\"build -Zchecksum-freshness -p foo -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] shared v0.0.1 ([ROOT]/foo/shared)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn changing_rustflags_is_cached() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    // This isn't ever cached, we always have to recompile\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"RUSTFLAGS\", \"-C linker=cc\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"RUSTFLAGS\", \"-C linker=cc\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn changing_rustc_extra_flags_is_cached() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    // This isn't ever cached, we always have to recompile\n    p.cargo(\"rustc -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"rustc -Zchecksum-freshness -v -- -C linker=cc\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"rustc -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"rustc -Zchecksum-freshness -v -- -C linker=cc\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn reuse_panic_build_dep_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [build-dependencies]\n                bar = { path = \"bar\" }\n\n                [dev-dependencies]\n                bar = { path = \"bar\" }\n\n                [profile.dev]\n                panic = \"abort\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    // Check that `bar` is not built twice. It is only needed once (without `panic`).\n    p.cargo(\"test -Zchecksum-freshness --lib --no-run -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..]\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..]\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]--test[..]\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn reuse_panic_pm() {\n    // foo(panic) -> bar(panic)\n    // somepm(nopanic) -> bar(nopanic)\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n                somepm = { path = \"somepm\" }\n\n                [profile.dev]\n                panic = \"abort\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"somepm/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"somepm\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                bar = { path = \"../bar\" }\n            \"#,\n        )\n        .file(\"somepm/src/lib.rs\", \"extern crate bar;\")\n        .build();\n\n    // bar is built once without panic (for proc-macro) and once with (for the\n    // normal dependency).\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..] -C panic=abort [..]\n[RUNNING] `rustc --crate-name bar [..]\n[COMPILING] somepm v0.0.1 ([ROOT]/foo/somepm)\n[RUNNING] `rustc --crate-name somepm [..]\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -C panic=abort [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn bust_patched_dep() {\n    Package::new(\"registry1\", \"0.1.0\").publish();\n    Package::new(\"registry2\", \"0.1.0\")\n        .dep(\"registry1\", \"0.1.0\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                registry2 = \"0.1.0\"\n\n                [patch.crates-io]\n                registry1 = { path = \"reg1new\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"reg1new/Cargo.toml\", &basic_manifest(\"registry1\", \"0.1.0\"))\n        .file(\"reg1new/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n\n    p.change_file(\"reg1new/src/lib.rs\", \"// modified\");\n\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] registry1 v0.1.0 ([ROOT]/foo/reg1new): file size changed (0 != 11) for `reg1new/src/lib.rs`\n[COMPILING] registry1 v0.1.0 ([ROOT]/foo/reg1new)\n[RUNNING] `rustc --crate-name registry1 [..]\n[DIRTY] registry2 v0.1.0: the dependency `registry1` was rebuilt\n[COMPILING] registry2 v0.1.0\n[RUNNING] `rustc --crate-name registry2 [..]\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the dependency `registry2` was rebuilt\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] registry1 v0.1.0 ([ROOT]/foo/reg1new)\n[FRESH] registry2 v0.1.0\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn rebuild_on_mid_build_file_modification() {\n    let server = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let addr = server.local_addr().unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"root\", \"proc_macro_dep\"]\n            \"#,\n        )\n        .file(\n            \"root/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"root\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                proc_macro_dep = { path = \"../proc_macro_dep\" }\n            \"#,\n        )\n        .file(\n            \"root/src/lib.rs\",\n            r#\"\n                #[macro_use]\n                extern crate proc_macro_dep;\n\n                #[derive(Noop)]\n                pub struct X;\n            \"#,\n        )\n        .file(\n            \"proc_macro_dep/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"proc_macro_dep\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"proc_macro_dep/src/lib.rs\",\n            &format!(\n                r#\"\n                    extern crate proc_macro;\n\n                    use std::io::Read;\n                    use std::net::TcpStream;\n                    use proc_macro::TokenStream;\n\n                    #[proc_macro_derive(Noop)]\n                    pub fn noop(_input: TokenStream) -> TokenStream {{\n                        let mut stream = TcpStream::connect(\"{}\").unwrap();\n                        let mut v = Vec::new();\n                        stream.read_to_end(&mut v).unwrap();\n                        \"\".parse().unwrap()\n                    }}\n                \"#,\n                addr\n            ),\n        )\n        .build();\n    let root = p.root();\n\n    let t = thread::spawn(move || {\n        let socket = server.accept().unwrap().0;\n        let mut file = OpenOptions::new()\n            .write(true)\n            .append(true)\n            .open(root.join(\"root/src/lib.rs\"))\n            .unwrap();\n        writeln!(file, \"// modified\").expect(\"Failed to append to root sources\");\n        drop(file);\n        drop(socket);\n        drop(server.accept().unwrap());\n    });\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] proc_macro_dep v0.1.0 ([ROOT]/foo/proc_macro_dep)\n[COMPILING] root v0.1.0 ([ROOT]/foo/root)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] proc_macro_dep v0.1.0 ([ROOT]/foo/proc_macro_dep)\n[DIRTY] root v0.1.0 ([ROOT]/foo/root): file size changed (150 != 162) for `root/src/lib.rs`\n[COMPILING] root v0.1.0 ([ROOT]/foo/root)\n[RUNNING] `rustc --crate-name root [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    t.join().ok().unwrap();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn dirty_both_lib_and_test() {\n    // This tests that all artifacts that depend on the results of a build\n    // script will get rebuilt when the build script reruns, even for separate\n    // commands. It does the following:\n    //\n    // 1. Project \"foo\" has a build script which will compile a small\n    //    staticlib to link against. Normally this would use the `cc` crate,\n    //    but here we just use rustc to avoid the `cc` dependency.\n    // 2. Build the library.\n    // 3. Build the unit test. The staticlib intentionally has a bad value.\n    // 4. Rewrite the staticlib with the correct value.\n    // 5. Build the library again.\n    // 6. Build the unit test. This should recompile.\n\n    let slib = |n| {\n        format!(\n            r#\"\n                #[no_mangle]\n                pub extern \"C\" fn doit() -> i32 {{\n                    return {};\n                }}\n            \"#,\n            n\n        )\n    };\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern \"C\" {\n                    fn doit() -> i32;\n                }\n\n                #[test]\n                fn t1() {\n                    assert_eq!(unsafe { doit() }, 1, \"doit assert failure\");\n                }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::env;\n                use std::path::PathBuf;\n                use std::process::Command;\n\n                fn main() {\n                    let rustc = env::var_os(\"RUSTC\").unwrap();\n                    let out_dir = PathBuf::from(env::var(\"OUT_DIR\").unwrap());\n                    assert!(\n                        Command::new(rustc)\n                            .args(&[\n                                \"--crate-type=staticlib\",\n                                \"--out-dir\",\n                                out_dir.to_str().unwrap(),\n                                \"slib.rs\"\n                            ])\n                            .status()\n                            .unwrap()\n                            .success(),\n                        \"slib build failed\"\n                    );\n                    println!(\"cargo::rustc-link-lib=slib\");\n                    println!(\"cargo::rustc-link-search={}\", out_dir.display());\n                }\n            \"#,\n        )\n        .file(\"slib.rs\", &slib(2))\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n\n    // 2 != 1\n    p.cargo(\"test -Zchecksum-freshness --lib\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_status(101)\n        .with_stdout_data(\"...\\n[..]doit assert failure[..]\\n...\")\n        .run();\n\n    // Fix the mistake.\n    p.change_file(\"slib.rs\", &slib(1));\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    // This should recompile with the new static lib, and the test should pass.\n    p.cargo(\"test -Zchecksum-freshness --lib\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn script_fails_stay_dirty() {\n    // Check if a script is aborted (such as hitting Ctrl-C) that it will re-run.\n    // Steps:\n    // 1. Build to establish fingerprints.\n    // 2. Make a change that triggers the build script to re-run. Abort the\n    //    script while it is running.\n    // 3. Run the build again and make sure it re-runs the script.\n    let p = project()\n        .file(\n            \"build.rs\",\n            r#\"\n                mod helper;\n                fn main() {\n                    println!(\"cargo::rerun-if-changed=build.rs\");\n                    helper::doit();\n                }\n            \"#,\n        )\n        .file(\"helper.rs\", \"pub fn doit() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.change_file(\"helper.rs\", r#\"pub fn doit() {panic!(\"Crash!\");}\"#);\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(\"...\\n[..]Crash![..]\\n...\")\n        .with_status(101)\n        .run();\n    // There was a bug where this second call would be \"fresh\".\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(\"...\\n[..]Crash![..]\\n...\")\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn edition_change_invalidates() {\n    const MANIFEST: &str = r#\"\n        [package]\n        name = \"foo\"\n        version = \"0.1.0\"\n    \"#;\n    let p = project()\n        .file(\"Cargo.toml\", MANIFEST)\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.change_file(\"Cargo.toml\", &format!(\"{}edition = \\\"2018\\\"\", MANIFEST));\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.change_file(\n        \"Cargo.toml\",\n        &format!(\n            r#\"{}edition = \"2018\"\n            [lib]\n            edition = \"2015\"\n            \"#,\n            MANIFEST\n        ),\n    );\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `edition` is set on library `foo` which is deprecated\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `edition` is set on library `foo` which is deprecated\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert_eq!(p.glob(\"target/debug/deps/libfoo-*.rlib\").count(), 1);\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn rename_with_path_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = 'a' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate a; pub fn foo() { a::foo(); }\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                b = { path = 'b' }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"extern crate b; pub fn foo() { b::foo() }\")\n        .file(\n            \"a/b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"a/b/src/lib.rs\", \"pub fn foo() { }\");\n    let p = p.build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n\n    // Now rename the root directory and rerun `cargo run`. Not only should we\n    // not build anything but we also shouldn't crash.\n    let mut new = p.root();\n    new.pop();\n    new.push(\"foo2\");\n\n    fs::rename(p.root(), &new).unwrap();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .cwd(&new)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn move_target_directory_with_path_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate a; pub use a::print_msg;\")\n        .file(\n            \"a/build.rs\",\n            r###\"\n                use std::env;\n                use std::fs;\n                use std::path::Path;\n\n                fn main() {\n                    println!(\"cargo::rerun-if-changed=build.rs\");\n                    let out_dir = env::var(\"OUT_DIR\").unwrap();\n                    let dest_path = Path::new(&out_dir).join(\"hello.rs\");\n                    fs::write(&dest_path, r#\"\n                        pub fn message() -> &'static str {\n                            \"Hello, World!\"\n                        }\n                    \"#).unwrap();\n                }\n            \"###,\n        )\n        .file(\n            \"a/src/lib.rs\",\n            r#\"\n            include!(concat!(env!(\"OUT_DIR\"), \"/hello.rs\"));\n            pub fn print_msg() { message(); }\n            \"#,\n        );\n    let p = p.build();\n\n    let mut parent = p.root();\n    parent.pop();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n\n    let new_target = p.root().join(\"target2\");\n    fs::rename(p.root().join(\"target\"), &new_target).unwrap();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"CARGO_TARGET_DIR\", &new_target)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn rerun_if_changes() {\n    let p = project()\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rerun-if-env-changed=FOO\");\n                    if std::env::var(\"FOO\").is_ok() {\n                        println!(\"cargo::rerun-if-env-changed=BAR\");\n                    }\n                }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"FOO\", \"1\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the env variable FOO changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"FOO\", \"1\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"FOO\", \"1\")\n        .env(\"BAR\", \"1\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the env variable BAR changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"FOO\", \"1\")\n        .env(\"BAR\", \"1\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"BAR\", \"2\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the env variable FOO changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"BAR\", \"2\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn channel_shares_filenames() {\n    // Test that different \"nightly\" releases use the same output filename.\n\n    // Create separate rustc binaries to emulate running different toolchains.\n    let nightly1 = format!(\n        \"\\\nrustc 1.44.0-nightly (38114ff16 2020-03-21)\nbinary: rustc\ncommit-hash: 38114ff16e7856f98b2b4be7ab4cd29b38bed59a\ncommit-date: 2020-03-21\nhost: {}\nrelease: 1.44.0-nightly\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    let nightly2 = format!(\n        \"\\\nrustc 1.44.0-nightly (a5b09d354 2020-03-31)\nbinary: rustc\ncommit-hash: a5b09d35473615e7142f5570f5c5fad0caf68bd2\ncommit-date: 2020-03-31\nhost: {}\nrelease: 1.44.0-nightly\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    let beta1 = format!(\n        \"\\\nrustc 1.43.0-beta.3 (4c587bbda 2020-03-25)\nbinary: rustc\ncommit-hash: 4c587bbda04ab55aaf56feab11dfdfe387a85d7a\ncommit-date: 2020-03-25\nhost: {}\nrelease: 1.43.0-beta.3\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    let beta2 = format!(\n        \"\\\nrustc 1.42.0-beta.5 (4e1c5f0e9 2020-02-28)\nbinary: rustc\ncommit-hash: 4e1c5f0e9769a588b91c977e3d81e140209ef3a2\ncommit-date: 2020-02-28\nhost: {}\nrelease: 1.42.0-beta.5\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    let stable1 = format!(\n        \"\\\nrustc 1.42.0 (b8cedc004 2020-03-09)\nbinary: rustc\ncommit-hash: b8cedc00407a4c56a3bda1ed605c6fc166655447\ncommit-date: 2020-03-09\nhost: {}\nrelease: 1.42.0\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    let stable2 = format!(\n        \"\\\nrustc 1.41.1 (f3e1a954d 2020-02-24)\nbinary: rustc\ncommit-hash: f3e1a954d2ead4e2fc197c7da7d71e6c61bad196\ncommit-date: 2020-02-24\nhost: {}\nrelease: 1.41.1\nLLVM version: 9.0\n\",\n        rustc_host()\n    );\n\n    let compiler = project()\n        .at(\"compiler\")\n        .file(\"Cargo.toml\", &basic_manifest(\"compiler\", \"0.1.0\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                if std::env::args_os().any(|a| a == \"-vV\") {\n                    print!(\"{}\", env!(\"FUNKY_VERSION_TEST\"));\n                    return;\n                }\n                let mut cmd = std::process::Command::new(\"rustc\");\n                cmd.args(std::env::args_os().skip(1));\n                assert!(cmd.status().unwrap().success());\n            }\n            \"#,\n        )\n        .build();\n\n    let makeit = |version, vv| {\n        // Force a rebuild.\n        compiler.target_debug_dir().join(\"deps\").rm_rf();\n        compiler\n            .cargo(\"build -Zchecksum-freshness\")\n            .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n            .env(\"FUNKY_VERSION_TEST\", vv)\n            .run();\n        fs::rename(compiler.bin(\"compiler\"), compiler.bin(version)).unwrap();\n    };\n    makeit(\"nightly1\", nightly1);\n    makeit(\"nightly2\", nightly2);\n    makeit(\"beta1\", beta1);\n    makeit(\"beta2\", beta2);\n    makeit(\"stable1\", stable1);\n    makeit(\"stable2\", stable2);\n\n    // Run `cargo check` with different rustc versions to observe its behavior.\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    // Runs `cargo check` and returns the rmeta filename created.\n    // Checks that the freshness matches the given value.\n    let check = |version, fresh| -> String {\n        let output = p\n            .cargo(\"check -Zchecksum-freshness --message-format=json\")\n            .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n            .env(\"RUSTC\", compiler.bin(version))\n            .run();\n        // Collect the filenames generated.\n        let mut artifacts: Vec<_> = std::str::from_utf8(&output.stdout)\n            .unwrap()\n            .lines()\n            .filter_map(|line| {\n                let value: serde_json::Value = serde_json::from_str(line).unwrap();\n                if value[\"reason\"].as_str().unwrap() == \"compiler-artifact\" {\n                    assert_eq!(value[\"fresh\"].as_bool().unwrap(), fresh);\n                    let filenames = value[\"filenames\"].as_array().unwrap();\n                    assert_eq!(filenames.len(), 1);\n                    Some(filenames[0].to_string())\n                } else {\n                    None\n                }\n            })\n            .collect();\n        // Should only generate one rmeta file.\n        assert_eq!(artifacts.len(), 1);\n        artifacts.pop().unwrap()\n    };\n\n    let nightly1_name = check(\"nightly1\", false);\n    assert_eq!(check(\"nightly1\", true), nightly1_name);\n    assert_eq!(check(\"nightly2\", false), nightly1_name); // same as before\n    assert_eq!(check(\"nightly2\", true), nightly1_name);\n    // Should rebuild going back to nightly1.\n    assert_eq!(check(\"nightly1\", false), nightly1_name);\n\n    let beta1_name = check(\"beta1\", false);\n    assert_ne!(beta1_name, nightly1_name);\n    assert_eq!(check(\"beta1\", true), beta1_name);\n    assert_eq!(check(\"beta2\", false), beta1_name); // same as before\n    assert_eq!(check(\"beta2\", true), beta1_name);\n    // Should rebuild going back to beta1.\n    assert_eq!(check(\"beta1\", false), beta1_name);\n\n    let stable1_name = check(\"stable1\", false);\n    assert_ne!(stable1_name, nightly1_name);\n    assert_ne!(stable1_name, beta1_name);\n    let stable2_name = check(\"stable2\", false);\n    assert_ne!(stable1_name, stable2_name);\n    // Check everything is fresh.\n    assert_eq!(check(\"stable1\", true), stable1_name);\n    assert_eq!(check(\"stable2\", true), stable2_name);\n    assert_eq!(check(\"beta1\", true), beta1_name);\n    assert_eq!(check(\"nightly1\", true), nightly1_name);\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn linking_interrupted() {\n    // Interrupt during the linking phase shouldn't leave test executable as \"fresh\".\n\n    // This is used to detect when linking starts, then to pause the linker so\n    // that the test can kill cargo.\n    let link_listener = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let link_addr = link_listener.local_addr().unwrap();\n\n    // This is used to detect when rustc exits.\n    let rustc_listener = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let rustc_addr = rustc_listener.local_addr().unwrap();\n\n    // Create a linker that we can interrupt.\n    let linker = project()\n        .at(\"linker\")\n        .file(\"Cargo.toml\", &basic_manifest(\"linker\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            &r#\"\n            fn main() {\n                // Figure out the output filename.\n                let output = match std::env::args().find(|a| a.starts_with(\"/OUT:\")) {\n                    Some(s) => s[5..].to_string(),\n                    None => {\n                        let mut args = std::env::args();\n                        loop {\n                            if args.next().unwrap() == \"-o\" {\n                                break;\n                            }\n                        }\n                        args.next().unwrap()\n                    }\n                };\n                std::fs::remove_file(&output).unwrap();\n                std::fs::write(&output, \"\").unwrap();\n                // Tell the test that we are ready to be interrupted.\n                let mut socket = std::net::TcpStream::connect(\"__ADDR__\").unwrap();\n                // Wait for the test to kill us.\n                std::thread::sleep(std::time::Duration::new(60, 0));\n            }\n            \"#\n            .replace(\"__ADDR__\", &link_addr.to_string()),\n        )\n        .build();\n    linker\n        .cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n\n    // Create a wrapper around rustc that will tell us when rustc is finished.\n    let rustc = project()\n        .at(\"rustc-waiter\")\n        .file(\"Cargo.toml\", &basic_manifest(\"rustc-waiter\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            &r#\"\n            fn main() {\n                let mut conn = None;\n                // Check for a normal build (not -vV or --print).\n                if std::env::args().any(|arg| arg == \"t1\") {\n                    // Tell the test that rustc has started.\n                    conn = Some(std::net::TcpStream::connect(\"__ADDR__\").unwrap());\n                }\n                let status = std::process::Command::new(\"rustc\")\n                    .args(std::env::args().skip(1))\n                    .status()\n                    .expect(\"rustc to run\");\n                std::process::exit(status.code().unwrap_or(1));\n            }\n            \"#\n            .replace(\"__ADDR__\", &rustc_addr.to_string()),\n        )\n        .build();\n    rustc\n        .cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n\n    // Build it once so that the fingerprint gets saved to disk.\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"tests/t1.rs\", \"\")\n        .build();\n    p.cargo(\"test -Zchecksum-freshness --test t1 --no-run\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n\n    // Make a change, start a build, then interrupt it.\n    p.change_file(\"src/lib.rs\", \"// modified\");\n    let linker_env = format!(\"CARGO_TARGET_{}_LINKER\", rustc_host_env());\n    // NOTE: This assumes that the paths to the linker or rustc are not in the\n    // fingerprint. But maybe they should be?\n    let mut cmd = p\n        .cargo(\"test -Zchecksum-freshness --test t1 --no-run\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(&linker_env, linker.bin(\"linker\"))\n        .env(\"RUSTC\", rustc.bin(\"rustc-waiter\"))\n        .build_command();\n    let mut child = cmd\n        .stdout(Stdio::null())\n        .stderr(Stdio::null())\n        .env(\"__CARGO_TEST_SETSID_PLEASE_DONT_USE_ELSEWHERE\", \"1\")\n        .spawn()\n        .unwrap();\n    // Wait for rustc to start.\n    let mut rustc_conn = rustc_listener.accept().unwrap().0;\n    // Wait for linking to start.\n    drop(link_listener.accept().unwrap());\n\n    // Interrupt the child.\n    death::ctrl_c(&mut child);\n    assert!(!child.wait().unwrap().success());\n    // Wait for rustc to exit. If we don't wait, then the command below could\n    // start while rustc is still being torn down.\n    let mut buf = [0];\n    drop(rustc_conn.read_exact(&mut buf));\n\n    // Build again, shouldn't be fresh.\n    p.cargo(\"test -Zchecksum-freshness --test t1 -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the config settings changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]\n[RUNNING] `rustc --crate-name t1 [..]\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/t1-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\n#[cfg(all(target_arch = \"x86_64\", target_os = \"windows\", target_env = \"msvc\"))]\nfn lld_is_fresh() {\n    // Check for bug when using lld linker that it remains fresh with dylib.\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [target.x86_64-pc-windows-msvc]\n                linker = \"rust-lld\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"dylib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn env_in_code_causes_rebuild() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    println!(\"{:?}\", option_env!(\"FOO\"));\n                    println!(\"{:?}\", option_env!(\"FOO\\nBAR\"));\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env_remove(\"FOO\")\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env_remove(\"FOO\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"FOO\", \"bar\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable FOO changed\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"FOO\", \"bar\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"FOO\", \"baz\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable FOO changed\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"FOO\", \"baz\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env_remove(\"FOO\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable FOO changed\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env_remove(\"FOO\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let interesting = \" #!$\\nabc\\r\\\\\\t\\u{8}\\r\\n\";\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"FOO\", interesting)\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"FOO\", interesting)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"FOO\\nBAR\", interesting)\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"FOO\\nBAR\", interesting)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn env_build_script_no_rebuild() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    println!(\"cargo::rustc-env=FOO=bar\");\n                }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    println!(\"{:?}\", env!(\"FOO\"));\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn changing_linker() {\n    // Changing linker should rebuild.\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"build -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .run();\n    let linker_env = format!(\"CARGO_TARGET_{}_LINKER\", rustc_host_env());\n    p.cargo(\"build -Zchecksum-freshness --verbose\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(&linker_env, \"nonexistent-linker\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the config settings changed\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -C linker=nonexistent-linker [..]`\n[ERROR] linker `nonexistent-linker` not found\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn verify_source_before_recompile() {\n    Package::new(\"bar\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n            [source.crates-io]\n            replace-with = 'vendor'\n\n            [source.vendor]\n            directory = 'vendor'\n        \"#,\n    );\n    // Sanity check: vendoring works correctly.\n    p.cargo(\"check -Zchecksum-freshness --verbose\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.0\n[RUNNING] `rustc --crate-name bar [..] [ROOT]/foo/vendor/bar/src/lib.rs [..]\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // Now modify vendored crate.\n    p.change_file(\n        \"vendor/bar/src/lib.rs\",\n        r#\"compile_error!(\"You shall not pass!\");\"#,\n    );\n    // Should ignore modified sources without any recompile.\n    p.cargo(\"check -Zchecksum-freshness --verbose\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] bar v0.1.0\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Add a `RUSTFLAGS` to trigger a recompile.\n    //\n    // Cargo should refuse to build because of checksum verification failure.\n    // Cargo shouldn't recompile dependency `bar`.\n    p.cargo(\"check -Zchecksum-freshness --verbose\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"RUSTFLAGS\", \"-W warnings\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the listed checksum of `[ROOT]/foo/vendor/bar/src/lib.rs` has changed:\nexpected: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\nactual:   66e843918c1d4ea8231af814f9f958958808249d4407de01114acb730ecd9bdf\n\ndirectory sources are not intended to be edited, if modifications are required then it is recommended that `[patch]` is used with a forked copy of the source\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn skip_checksum_check_in_selected_cargo_home_subdirs() {\n    let p = project()\n        .at(\"cargo_home/registry/foo\")\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    let project_root = p.root();\n    let cargo_home = project_root.parent().unwrap().parent().unwrap();\n    p.cargo(\"check -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"CARGO_HOME\", &cargo_home)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.5.0 ([ROOT]/cargo_home/registry/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.change_file(\"src/lib.rs\", \"illegal syntax\");\n    p.cargo(\"check -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"CARGO_HOME\", &cargo_home)\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.5.0 ([ROOT]/cargo_home/registry/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn use_checksum_cache_in_cargo_home() {\n    let p = project()\n        .at(\"cargo_home/foo\")\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    let project_root = p.root();\n    let cargo_home = project_root.parent().unwrap();\n    p.cargo(\"check -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"CARGO_HOME\", &cargo_home)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.5.0 ([ROOT]/cargo_home/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..] src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.change_file(\"src/lib.rs\", \"illegal syntax\");\n    p.cargo(\"check -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"CARGO_HOME\", &cargo_home)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/cargo_home/foo): file size changed (0 != 14) for `src/lib.rs`\n[CHECKING] foo v0.5.0 ([ROOT]/cargo_home/foo)\n[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]\n...\n[ERROR] could not compile `foo` (lib) due to 1 previous error\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"requires -Zchecksum-hash-algorithm\")]\nfn incremental_build_script_execution_got_new_mtime_and_cargo_check() {\n    // See https://github.com/rust-lang/cargo/issues/16104\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"touch-me\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"fn main() { println!(\"cargo::rerun-if-changed=touch-me\") }\"#,\n        )\n        .build();\n\n    p.cargo(\"check -Zchecksum-freshness\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\"touch-me\", \"oops\");\n\n    // The first one is expected to rerun build script\n    p.cargo(\"check -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the file `touch-me` has changed ([TIME_DIFF_AFTER_LAST_BUILD])\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // subsequent cargo check gets stuck...\n    p.cargo(\"check -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -Zchecksum-freshness -v\")\n        .masquerade_as_nightly_cargo(&[\"checksum-freshness\"])\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/future_incompat_report.rs",
    "content": "//! Tests for future-incompat-report messages\n//!\n//! Note that these tests use the -Zfuture-incompat-test for rustc.\n//! This causes rustc to treat *every* lint as future-incompatible.\n//! This is done because future-incompatible lints are inherently\n//! ephemeral, but we don't want to continually update these tests.\n//! So we pick some random lint that will likely always be the same\n//! over time.\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{Project, basic_manifest, project, str};\n\nuse super::config::write_config_toml;\n\n// An arbitrary lint (unused_variables) that triggers a lint.\n// We use a special flag to force it to generate a report.\nconst FUTURE_EXAMPLE: &'static str = \"pub fn foo() { let x = 1; }\";\n// Some text that will be displayed when the lint fires.\nconst FUTURE_OUTPUT: &'static str = \"[..]unused variable[..]\";\n\n/// A project with a future-incompat error in the local package.\nfn local_project() -> Project {\n    project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/lib.rs\", FUTURE_EXAMPLE)\n        .build()\n}\n\n/// A project with a future-incompat error in a dependency.\nfn dependency_project() -> Project {\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n                repository = \"https://example.com/\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", FUTURE_EXAMPLE)\n        .publish();\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build()\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"-Zfuture-incompat-test requires nightly (permanently)\"\n)]\nfn incompat_in_local_crate() {\n    // A simple example where a local crate triggers a future-incompatibility warning.\n    let p = local_project();\n\n    p.cargo(\"check\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[WARNING] unused variable: `x`\n...\n\n[WARNING] `foo` (lib) generated 1 warning[..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[WARNING] the following packages contain code that will be rejected by a future version of Rust: foo v0.0.0 ([ROOT]/foo)\n[NOTE] to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`\n\n\"#]])\n        .run();\n\n    p.cargo(\"check --future-incompat-report\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused variable: `x`\n...\n\n[WARNING] `foo` (lib) generated 1 warning[..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[WARNING] the following packages contain code that will be rejected by a future version of Rust: foo v0.0.0 ([ROOT]/foo)\n[NOTE] this report can be shown with `cargo report future-incompatibilities --id 1`\n\n\"#]])\n    .run();\n\n    p.cargo(\"report future-incompatibilities --id 1\")\n        .with_stdout_data(str![[r#\"\nThe following warnings were discovered during the build. These warnings are an\nindication that the packages contain code that will become an error in a\nfuture release of Rust. These warnings typically cover changes to close\nsoundness problems, unintended or undocumented behavior, or critical problems\nthat cannot be fixed in a backwards-compatible fashion, and are not expected\nto be in wide use.\n\nEach warning should contain a link for more information on what the warning\nmeans and how to resolve it.\n\n\nThe package `foo v0.0.0 ([ROOT]/foo)` currently triggers the following future incompatibility lints:\n> [WARNING] unused variable: `x`\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"-Zfuture-incompat-test requires nightly (permanently)\"\n)]\nfn incompat_in_dependency() {\n    // A simple example where a remote dependency triggers a future-incompatibility warning.\n    let p = dependency_project();\n\n    p.cargo(\"check\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] bar v1.0.0\n[CHECKING] foo v1.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[WARNING] the following packages contain code that will be rejected by a future version of Rust: bar v1.0.0\n[NOTE] to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`\n\n\"#]])\n        .run();\n\n    p.cargo(\"check --future-incompat-report\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[WARNING] the following packages contain code that will be rejected by a future version of Rust: bar v1.0.0\n[HELP] ensure the maintainers know of this problem (e.g. creating a bug report if needed)\n      or even helping with a fix (e.g. by creating a pull request)\n        - bar@1.0.0\n        - repository: https://example.com/\n        - detailed warning command: `cargo report future-incompatibilities --id 1 --package bar@1.0.0`\n[HELP] use your own version of the dependency with the `[patch]` section in `Cargo.toml`\n      For more information, see:\n      https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section\n[NOTE] this report can be shown with `cargo report future-incompatibilities --id 1`\n\n\"#]])\n        .run();\n\n    p.cargo(\"report future-incompatibilities --id 1\")\n        .with_stdout_data(str![[r#\"\nThe following warnings were discovered during the build. These warnings are an\nindication that the packages contain code that will become an error in a\nfuture release of Rust. These warnings typically cover changes to close\nsoundness problems, unintended or undocumented behavior, or critical problems\nthat cannot be fixed in a backwards-compatible fashion, and are not expected\nto be in wide use.\n\nEach warning should contain a link for more information on what the warning\nmeans and how to resolve it.\n\nto solve this problem, you can try the following approaches:\n\n- ensure the maintainers know of this problem (e.g. creating a bug report if needed)\nor even helping with a fix (e.g. by creating a pull request)\n  - bar@1.0.0\n  - repository: https://example.com/\n  - detailed warning command: `cargo report future-incompatibilities --id 1 --package bar@1.0.0`\n\n- use your own version of the dependency with the `[patch]` section in `Cargo.toml`\nFor more information, see:\nhttps://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section\n\nThe package `bar v1.0.0` currently triggers the following future incompatibility lints:\n> [WARNING] unused variable: `x`\n...\n\n\"#]])\n        .run();\n}\n\n// This feature is stable, and should not be gated\n#[cargo_test]\nfn no_gate_future_incompat_report() {\n    let p = local_project();\n\n    p.cargo(\"check --future-incompat-report\")\n        .with_status(0)\n        .run();\n\n    p.cargo(\"report future-incompatibilities --id foo\")\n        .with_stderr_data(str![[r#\"\n[ERROR] no reports are currently available\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"-Zfuture-incompat-test requires nightly (permanently)\"\n)]\nfn test_zero_future_incompat() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // No note if --future-incompat-report is not specified.\n    p.cargo(\"check\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check --future-incompat-report\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[NOTE] 0 dependencies had future-incompatible warnings\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"-Zfuture-incompat-test requires nightly (permanently)\"\n)]\nfn test_single_crate() {\n    let p = local_project();\n\n    for command in &[\"build\", \"check\", \"rustc\", \"test\"] {\n        let check_has_future_compat = || {\n            p.cargo(command)\n                .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n                .with_stderr_data(\"\\\n...\n[WARNING] unused variable: `x`\n...\n[WARNING] the following packages contain code that will be rejected by a future version of Rust: foo v0.0.0 ([ROOT]/foo)\n...\n\")\n                .with_stderr_does_not_contain(\"[..]incompatibility[..]\")\n                .run();\n        };\n\n        // Check that we show a message with no [future-incompat-report] config section\n        write_config_toml(\"\");\n        check_has_future_compat();\n\n        // Check that we show a message with `frequency = \"always\"`\n        write_config_toml(\n            \"\\\n[future-incompat-report]\nfrequency = 'always'\n\",\n        );\n        check_has_future_compat();\n\n        // Check that we do not show a message with `frequency = \"never\"`\n        write_config_toml(\n            \"\\\n[future-incompat-report]\nfrequency = 'never'\n\",\n        );\n        p.cargo(command)\n            .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n            .with_stderr_data(\n                \"\\\n[WARNING] unused variable: `x`\n...\n\",\n            )\n            .with_stderr_does_not_contain(\"[..]rejected[..]\")\n            .with_stderr_does_not_contain(\"[..]incompatibility[..]\")\n            .run();\n\n        // Check that passing `--future-incompat-report` overrides `frequency = 'never'`\n        p.cargo(command).arg(\"--future-incompat-report\")\n            .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n            .with_stderr_data(\"\\\n[WARNING] unused variable: `x`\n...\n[WARNING] the following packages contain code that will be rejected by a future version of Rust: foo v0.0.0 ([ROOT]/foo)\n...\n[NOTE] this report can be shown with `cargo report future-incompatibilities --id [..]`\n...\n\")\n            .run();\n    }\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"-Zfuture-incompat-test requires nightly (permanently)\"\n)]\nfn test_multi_crate() {\n    Package::new(\"first-dep\", \"0.0.1\")\n        .file(\"src/lib.rs\", FUTURE_EXAMPLE)\n        .publish();\n    Package::new(\"second-dep\", \"0.0.2\")\n        .file(\"src/lib.rs\", FUTURE_EXAMPLE)\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n\n                [dependencies]\n                first-dep = \"*\"\n                second-dep = \"*\"\n              \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    for command in &[\"build\", \"check\", \"rustc\", \"test\"] {\n        p.cargo(command)\n            .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n            .with_stderr_does_not_contain(FUTURE_OUTPUT)\n            .with_stderr_data(\"\\\n...\n[WARNING] the following packages contain code that will be rejected by a future version of Rust: first-dep v0.0.1, second-dep v0.0.2\n...\n\")\n            // Check that we don't have the 'triggers' message shown at the bottom of this loop,\n            // and that we don't explain how to show a per-package report\n            .with_stderr_does_not_contain(\"[..]triggers[..]\")\n            .with_stderr_does_not_contain(\"[..]--package[..]\")\n            .with_stderr_does_not_contain(\"[..]-p[..]\")\n            .run();\n\n        p.cargo(command).arg(\"--future-incompat-report\")\n            .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n            .with_stderr_data(\"\\\n...\n[WARNING] the following packages contain code that will be rejected by a future version of Rust: first-dep v0.0.1, second-dep v0.0.2\n...\n        - first-dep@0.0.1\n...\n        - second-dep@0.0.2\n...\n\")\n            .run();\n\n        p.cargo(\"report future-incompatibilities\")\n            .arg(\"--package\")\n            .arg(\"first-dep@0.0.1\")\n            .with_stdout_data(\n                \"\\\n...\nThe package `first-dep v0.0.1` currently triggers the following future incompatibility lints:\n> [WARNING] unused variable: `x`\n...\n\",\n            )\n            .with_stdout_does_not_contain(\"[..]second-dep-0.0.2/src[..]\")\n            .run();\n\n        p.cargo(\"report future-incompatibilities\")\n            .arg(\"--package\")\n            .arg(\"second-dep@0.0.2\")\n            .with_stdout_data(\n                \"\\\n...\nThe package `second-dep v0.0.2` currently triggers the following future incompatibility lints:\n> [WARNING] unused variable: `x`\n...\n\",\n            )\n            .with_stdout_does_not_contain(\"[..]first-dep-0.0.1/src[..]\")\n            .run();\n    }\n\n    // Test that passing the correct id via '--id' doesn't generate a warning message\n    let output = p\n        .cargo(\"check\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .run();\n\n    // Extract the 'id' from the stdout. We are looking\n    // for the id in a line of the form \"run `cargo report future-incompatibilities --id yZ7S`\"\n    // which is generated by Cargo to tell the user what command to run\n    // This is just to test that passing the id suppresses the warning message. Any users needing\n    // access to the report from a shell script should use the `--future-incompat-report` flag\n    let stderr = std::str::from_utf8(&output.stderr).unwrap();\n\n    // Find '--id <ID>' in the output\n    let mut iter = stderr.split(' ');\n    iter.find(|w| *w == \"--id\").unwrap();\n    let id = iter\n        .next()\n        .unwrap_or_else(|| panic!(\"Unexpected output:\\n{}\", stderr));\n    // Strip off the trailing '`' included in the output\n    let id: String = id.chars().take_while(|c| *c != '`').collect();\n\n    p.cargo(&format!(\"report future-incompatibilities --id {}\", id))\n        .with_stdout_data(str![[r#\"\n...\nThe package `first-dep v0.0.1` currently triggers the following future incompatibility lints:\n...\nThe package `second-dep v0.0.2` currently triggers the following future incompatibility lints:\n...\n\"#]])\n        .run();\n\n    // Test without --id, and also the full output of the report.\n    let output = p.cargo(\"report future-incompat\").run();\n    let output = std::str::from_utf8(&output.stdout).unwrap();\n    assert!(output.starts_with(\"The following warnings were discovered\"));\n    let mut lines = output\n        .lines()\n        // Skip the beginning of the per-package information.\n        .skip_while(|line| !line.starts_with(\"The package\"));\n    for expected in &[\"first-dep v0.0.1\", \"second-dep v0.0.2\"] {\n        assert_eq!(\n            &format!(\n                \"The package `{}` currently triggers the following future incompatibility lints:\",\n                expected\n            ),\n            lines.next().unwrap(),\n            \"Bad output:\\n{}\",\n            output\n        );\n        let mut count = 0;\n        while let Some(line) = lines.next() {\n            if line.is_empty() {\n                break;\n            }\n            count += 1;\n        }\n        assert!(count > 0);\n    }\n    assert_eq!(lines.next(), None);\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"-Zfuture-incompat-test requires nightly (permanently)\"\n)]\nfn color() {\n    let p = local_project();\n\n    p.cargo(\"check\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .masquerade_as_nightly_cargo(&[\"future-incompat-test\"])\n        .run();\n\n    p.cargo(\"report future-incompatibilities\")\n        .with_stdout_does_not_contain(\"[..]\\x1b[[..]\")\n        .run();\n\n    p.cargo(\"report future-incompatibilities\")\n        .env(\"CARGO_TERM_COLOR\", \"always\")\n        .with_stdout_contains(\"[..]\\x1b[[..]\")\n        .run();\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"-Zfuture-incompat-test requires nightly (permanently)\"\n)]\nfn bad_ids() {\n    let p = local_project();\n\n    p.cargo(\"report future-incompatibilities --id 1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no reports are currently available\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .masquerade_as_nightly_cargo(&[\"future-incompat-test\"])\n        .run();\n\n    p.cargo(\"report future-incompatibilities --id foo\")\n        .with_status(1)\n        .with_stderr_data(str![\n            \"[ERROR] invalid value: could not parse `foo` as a number\"\n        ])\n        .run();\n\n    p.cargo(\"report future-incompatibilities --id 7\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not find report with ID 7\nAvailable IDs are: 1\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"-Zfuture-incompat-test requires nightly (permanently)\"\n)]\nfn suggestions_for_updates() {\n    Package::new(\"with_updates\", \"1.0.0\")\n        .file(\"src/lib.rs\", FUTURE_EXAMPLE)\n        .publish();\n    Package::new(\"big_update\", \"1.0.0\")\n        .file(\"src/lib.rs\", FUTURE_EXAMPLE)\n        .dep(\"with_updates\", \"1.0.0\")\n        .publish();\n    Package::new(\"without_updates\", \"1.0.0\")\n        .file(\"src/lib.rs\", FUTURE_EXAMPLE)\n        .dep(\"big_update\", \"1.0.0\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                with_updates = \"1\"\n                big_update = \"1\"\n                without_updates = \"1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    Package::new(\"with_updates\", \"1.0.1\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    Package::new(\"with_updates\", \"1.0.2\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    Package::new(\"with_updates\", \"3.0.1\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    Package::new(\"big_update\", \"2.0.0\")\n        .file(\"src/lib.rs\", \"\")\n        .dep(\"with_updates\", \"1.0.0\")\n        .publish();\n\n    // This is a hack to force cargo to update the index. Cargo can't do this\n    // automatically because doing a network update on every build would be a\n    // bad idea. Under normal circumstances, we'll hope the user has done\n    // something else along the way to trigger an update (building some other\n    // project or something). This could use some more consideration of how to\n    // handle this better (maybe only trigger an update if it hasn't updated\n    // in a long while?).\n    p.cargo(\"update without_updates\").run();\n\n    p.cargo(\"check --future-incompat-report\")\n        .masquerade_as_nightly_cargo(&[\"future-incompat-test\"])\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .with_stderr_data(str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] without_updates v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] with_updates v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] big_update v1.0.0 (registry `dummy-registry`)\n[CHECKING] with_updates v1.0.0\n[CHECKING] big_update v1.0.0\n[CHECKING] without_updates v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[WARNING] the following packages contain code that will be rejected by a future version of Rust: big_update v1.0.0, with_updates v1.0.0, without_updates v1.0.0\n[HELP] update to a newer version to see if the issue has been fixed\n        - big_update v1.0.0 has the following newer versions available: 2.0.0\n        - with_updates v1.0.0 has the following newer versions available: 1.0.1, 1.0.2, 3.0.1\n[HELP] ensure the maintainers know of this problem (e.g. creating a bug report if needed)\n      or even helping with a fix (e.g. by creating a pull request)\n        - big_update@1.0.0\n        - repository: <not found>\n        - detailed warning command: `cargo report future-incompatibilities --id 1 --package big_update@1.0.0`\n      \n        - with_updates@1.0.0\n        - repository: <not found>\n        - detailed warning command: `cargo report future-incompatibilities --id 1 --package with_updates@1.0.0`\n      \n        - without_updates@1.0.0\n        - repository: <not found>\n        - detailed warning command: `cargo report future-incompatibilities --id 1 --package without_updates@1.0.0`\n[HELP] use your own version of the dependency with the `[patch]` section in `Cargo.toml`\n      For more information, see:\n      https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section\n[NOTE] this report can be shown with `cargo report future-incompatibilities --id 1`\n\n\"#]])\n        .run();\n\n    p.cargo(\"report future-incompatibilities\")\n        .with_stdout_data(str![[r#\"\nThe following warnings were discovered during the build. These warnings are an\nindication that the packages contain code that will become an error in a\nfuture release of Rust. These warnings typically cover changes to close\nsoundness problems, unintended or undocumented behavior, or critical problems\nthat cannot be fixed in a backwards-compatible fashion, and are not expected\nto be in wide use.\n\nEach warning should contain a link for more information on what the warning\nmeans and how to resolve it.\n\nto solve this problem, you can try the following approaches:\n\n- update to a newer version to see if the issue has been fixed\n  - big_update v1.0.0 has the following newer versions available: 2.0.0\n  - with_updates v1.0.0 has the following newer versions available: 1.0.1, 1.0.2, 3.0.1\n\n- ensure the maintainers know of this problem (e.g. creating a bug report if needed)\nor even helping with a fix (e.g. by creating a pull request)\n  - big_update@1.0.0\n  - repository: <not found>\n  - detailed warning command: `cargo report future-incompatibilities --id 1 --package big_update@1.0.0`\n\n  - with_updates@1.0.0\n  - repository: <not found>\n  - detailed warning command: `cargo report future-incompatibilities --id 1 --package with_updates@1.0.0`\n\n  - without_updates@1.0.0\n  - repository: <not found>\n  - detailed warning command: `cargo report future-incompatibilities --id 1 --package without_updates@1.0.0`\n\n- use your own version of the dependency with the `[patch]` section in `Cargo.toml`\nFor more information, see:\nhttps://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section\n\nThe package `big_update v1.0.0` currently triggers the following future incompatibility lints:\n> [WARNING] unused variable: `x`\n...\n\nThe package `with_updates v1.0.0` currently triggers the following future incompatibility lints:\n> [WARNING] unused variable: `x`\n...\n\nThe package `without_updates v1.0.0` currently triggers the following future incompatibility lints:\n> [WARNING] unused variable: `x`\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(\n    nightly,\n    reason = \"-Zfuture-incompat-test requires nightly (permanently)\"\n)]\nfn correct_report_id_when_cached() {\n    // Checks for a bug where the `--id` value was off-by-one when the report\n    // is already cached.\n    let p = dependency_project();\n\n    p.cargo(\"check --future-incompat-report\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] bar v1.0.0\n[CHECKING] foo v1.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[WARNING] the following packages contain code that will be rejected by a future version of Rust: bar v1.0.0\n[HELP] ensure the maintainers know of this problem (e.g. creating a bug report if needed)\n      or even helping with a fix (e.g. by creating a pull request)\n        - bar@1.0.0\n        - repository: https://example.com/\n        - detailed warning command: `cargo report future-incompatibilities --id 1 --package bar@1.0.0`\n[HELP] use your own version of the dependency with the `[patch]` section in `Cargo.toml`\n      For more information, see:\n      https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section\n[NOTE] this report can be shown with `cargo report future-incompatibilities --id 1`\n\n\"#]])\n        .run();\n\n    p.cargo(\"check --future-incompat-report\")\n        .env(\"RUSTFLAGS\", \"-Zfuture-incompat-test\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[WARNING] the following packages contain code that will be rejected by a future version of Rust: bar v1.0.0\n[HELP] ensure the maintainers know of this problem (e.g. creating a bug report if needed)\n      or even helping with a fix (e.g. by creating a pull request)\n        - bar@1.0.0\n        - repository: https://example.com/\n        - detailed warning command: `cargo report future-incompatibilities --id 1 --package bar@1.0.0`\n[HELP] use your own version of the dependency with the `[patch]` section in `Cargo.toml`\n      For more information, see:\n      https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section\n[NOTE] this report can be shown with `cargo report future-incompatibilities --id 1`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/generate_lockfile.rs",
    "content": "//! Tests for the `cargo generate-lockfile` command.\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::registry::{Package, RegistryBuilder};\nuse cargo_test_support::{ProjectBuilder, basic_manifest, paths, project, str};\n\n#[cargo_test]\nfn adding_and_removing_packages() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    let lock1 = p.read_lockfile();\n\n    // add a dep\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            authors = []\n            version = \"0.0.1\"\n\n            [dependencies.bar]\n            path = \"bar\"\n        \"#,\n    );\n    p.cargo(\"generate-lockfile\").run();\n    let lock2 = p.read_lockfile();\n    assert_ne!(lock1, lock2);\n\n    // change the dep\n    p.change_file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.2\"));\n    p.cargo(\"generate-lockfile\").run();\n    let lock3 = p.read_lockfile();\n    assert_ne!(lock1, lock3);\n    assert_ne!(lock2, lock3);\n\n    // remove the dep\n    println!(\"lock4\");\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            authors = []\n            version = \"0.0.1\"\n        \"#,\n    );\n    p.cargo(\"generate-lockfile\").run();\n    let lock4 = p.read_lockfile();\n    assert_eq!(lock1, lock4);\n}\n\n#[cargo_test]\nfn no_index_update_sparse() {\n    let _registry = RegistryBuilder::new().http_index().build();\n    no_index_update(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n\n\"#]],\n        str![[r#\"\n[LOCKING] 1 package to latest compatible version\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn no_index_update_git() {\n    no_index_update(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n\n\"#]],\n        str![[r#\"\n[LOCKING] 1 package to latest compatible version\n\n\"#]],\n    );\n}\n\nfn no_index_update(expected: impl IntoData, expected_unstable_option: impl IntoData) {\n    Package::new(\"serde\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n\n                [dependencies]\n                serde = \"1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile\")\n        .with_stderr_data(expected)\n        .run();\n\n    p.cargo(\"generate-lockfile -Zno-index-update\")\n        .masquerade_as_nightly_cargo(&[\"no-index-update\"])\n        .with_stdout_data(\"\")\n        .with_stderr_data(expected_unstable_option)\n        .run();\n}\n\n#[cargo_test]\nfn preserve_metadata() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    let metadata = r#\"\n[metadata]\nbar = \"baz\"\nfoo = \"bar\"\n\"#;\n    let lock = p.read_lockfile();\n    let data = lock + metadata;\n    p.change_file(\"Cargo.lock\", &data);\n\n    // Build and make sure the metadata is still there\n    p.cargo(\"build\").run();\n    let lock = p.read_lockfile();\n    assert!(lock.contains(metadata.trim()), \"{}\", lock);\n\n    // Update and make sure the metadata is still there\n    p.cargo(\"update\").run();\n    let lock = p.read_lockfile();\n    assert!(lock.contains(metadata.trim()), \"{}\", lock);\n}\n\n#[cargo_test]\nfn preserve_line_endings_issue_2076() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    let lockfile = p.root().join(\"Cargo.lock\");\n    p.cargo(\"generate-lockfile\").run();\n    assert!(lockfile.is_file());\n    p.cargo(\"generate-lockfile\").run();\n\n    let lock0 = p.read_lockfile();\n\n    assert!(lock0.starts_with(\"# This file is automatically @generated by Cargo.\\n# It is not intended for manual editing.\\n\"));\n\n    let lock1 = lock0.replace(\"\\n\", \"\\r\\n\");\n    p.change_file(\"Cargo.lock\", &lock1);\n\n    p.cargo(\"generate-lockfile\").run();\n\n    let lock2 = p.read_lockfile();\n\n    assert!(lock2.starts_with(\"# This file is automatically @generated by Cargo.\\r\\n# It is not intended for manual editing.\\r\\n\"));\n    assert_eq!(lock1, lock2);\n}\n\n#[cargo_test]\nfn cargo_update_generate_lockfile() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    let lockfile = p.root().join(\"Cargo.lock\");\n    assert!(!lockfile.is_file());\n    p.cargo(\"update\").with_stderr_data(\"\").run();\n    assert!(lockfile.is_file());\n\n    fs::remove_file(p.root().join(\"Cargo.lock\")).unwrap();\n\n    assert!(!lockfile.is_file());\n    p.cargo(\"update\").with_stderr_data(\"\").run();\n    assert!(lockfile.is_file());\n}\n\n#[cargo_test]\nfn duplicate_entries_in_lockfile() {\n    let _a = ProjectBuilder::new(paths::root().join(\"a\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            authors = []\n            version = \"0.0.1\"\n\n            [dependencies]\n            common = {path=\"common\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let common_toml = &basic_manifest(\"common\", \"0.0.1\");\n\n    let _common_in_a = ProjectBuilder::new(paths::root().join(\"a/common\"))\n        .file(\"Cargo.toml\", common_toml)\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let b = ProjectBuilder::new(paths::root().join(\"b\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            authors = []\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            common = {path=\"common\"}\n            a = {path=\"../a\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let _common_in_b = ProjectBuilder::new(paths::root().join(\"b/common\"))\n        .file(\"Cargo.toml\", common_toml)\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // should fail due to a duplicate package `common` in the lock file\n    b.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package collision in the lockfile: packages common v0.0.1 ([ROOT]/a/common) and common v0.0.1 ([ROOT]/b/common) are different, but only one can be written to lockfile unambiguously\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn generate_lockfile_holds_lock_and_offline() {\n    Package::new(\"syn\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n\n                [dependencies]\n                syn = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n\n    p.cargo(\"generate-lockfile --offline\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_time_feature_gated() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n\n                [dependencies]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile --publish-time 2025-03-01T06:00:00Z\")\n        .masquerade_as_nightly_cargo(&[\"publish-time\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `--publish-time` flag is unstable, pass `-Z unstable-options` to enable it\nSee https://github.com/rust-lang/cargo/issues/5221 for more information about the `--publish-time` flag.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_time() {\n    Package::new(\"has_time\", \"2025.1.1\")\n        .pubtime(\"2025-01-01T06:00:00Z\")\n        .publish();\n    Package::new(\"has_time\", \"2025.6.1\")\n        .pubtime(\"2025-06-01T06:00:00Z\")\n        .publish();\n    Package::new(\"no_time\", \"2025.1.1\").publish();\n    Package::new(\"no_time\", \"2025.6.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n\n                [dependencies]\n                has_time = \"2025.0\"\n                no_time = \"2025.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile --publish-time 2025-03-01T06:00:00Z -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"publish-time\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions as of 2025-03-01T06:00:00Z\n[ADDING] has_time v2025.1.1 (available: v2025.6.1)\n\n\"#]])\n        .run();\n\n    let lock = p.read_lockfile();\n    assert_e2e().eq(\n        lock,\n        str![[r##\"\n# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.0\"\ndependencies = [\n \"has_time\",\n \"no_time\",\n]\n\n[[package]]\nname = \"has_time\"\nversion = \"2025.1.1\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"105ca3acbc796da3e728ff310cafc6961cebc48d0106285edb8341015b5cc2d7\"\n\n[[package]]\nname = \"no_time\"\nversion = \"2025.6.1\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"01e688c07975f1e85f526c033322273181a4d8fe97800543d813d0a0adc134e3\"\n\n\"##]],\n    );\n}\n\n#[cargo_test]\nfn publish_time_no_candidates() {\n    Package::new(\"has_time\", \"2025.6.1\")\n        .pubtime(\"2025-06-01T06:00:00Z\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n\n                [dependencies]\n                has_time = \"2025.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile --publish-time 2025-03-01T06:00:00Z -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"publish-time\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `has_time = \"^2025.0\"`\n  version 2025.6.1 is unavailable\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_time_invalid() {\n    Package::new(\"has_time\", \"2025.6.1\")\n        .pubtime(\"2025-06-01T06:00:00\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n\n                [dependencies]\n                has_time = \"2025.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile --publish-time 2025-03-01T06:00:00Z -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"publish-time\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `has_time = \"^2025.0\"`\n  version 2025.6.1's index entry is invalid\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/git.rs",
    "content": "//! Tests for git support.\n\nuse std::fs;\nuse std::io::prelude::*;\nuse std::net::{TcpListener, TcpStream};\nuse std::path::Path;\nuse std::str;\nuse std::sync::Arc;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::thread;\n\nuse crate::prelude::*;\nuse cargo_test_support::git::{add_submodule, cargo_uses_gitoxide};\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{Project, sleep_ms, str, t};\nuse cargo_test_support::{basic_lib_manifest, basic_manifest, git, main_file, project};\n\n#[cargo_test]\nfn cargo_compile_simple_git_dep() {\n    let project = project();\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\n                \"src/dep1.rs\",\n                r#\"\n                    pub fn hello() -> &'static str {\n                        \"hello world\"\n                    }\n                \"#,\n            )\n    });\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.dep1]\n\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            &main_file(r#\"\"{}\", dep1::hello()\"#, &[\"dep1\"]),\n        )\n        .build();\n\n    project\n        .cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[LOCKING] 1 package to latest compatible version\n[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1#[..])\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(project.bin(\"foo\").is_file());\n\n    project\n        .process(&project.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nhello world\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_git_dep_branch() {\n    let project = project();\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\n                \"src/dep1.rs\",\n                r#\"\n                    pub fn hello() -> &'static str {\n                        \"hello world\"\n                    }\n                \"#,\n            )\n    });\n\n    // Make a new branch based on the current HEAD commit\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    let head = repo.head().unwrap().target().unwrap();\n    let head = repo.find_commit(head).unwrap();\n    repo.branch(\"branchy\", &head, true).unwrap();\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.dep1]\n\n                    git = '{}'\n                    branch = \"branchy\"\n\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            &main_file(r#\"\"{}\", dep1::hello()\"#, &[\"dep1\"]),\n        )\n        .build();\n\n    project\n        .cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[LOCKING] 1 package to latest compatible version\n[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1?branch=branchy#[..])\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(project.bin(\"foo\").is_file());\n\n    project\n        .process(&project.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nhello world\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_git_dep_tag() {\n    let project = project();\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\n                \"src/dep1.rs\",\n                r#\"\n                    pub fn hello() -> &'static str {\n                        \"hello world\"\n                    }\n                \"#,\n            )\n    });\n\n    // Make a tag corresponding to the current HEAD\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    let head = repo.head().unwrap().target().unwrap();\n    repo.tag(\n        \"v0.1.0\",\n        &repo.find_object(head, None).unwrap(),\n        &repo.signature().unwrap(),\n        \"make a new tag\",\n        false,\n    )\n    .unwrap();\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.dep1]\n\n                    git = '{}'\n                    tag = \"v0.1.0\"\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            &main_file(r#\"\"{}\", dep1::hello()\"#, &[\"dep1\"]),\n        )\n        .build();\n\n    project\n        .cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[LOCKING] 1 package to latest compatible version\n[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1?tag=v0.1.0#[..])\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(project.bin(\"foo\").is_file());\n\n    project\n        .process(&project.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nhello world\n\n\"#]])\n        .run();\n\n    project.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn cargo_compile_git_dep_pull_request() {\n    let project = project();\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\n                \"src/dep1.rs\",\n                r#\"\n                    pub fn hello() -> &'static str {\n                        \"hello world\"\n                    }\n                \"#,\n            )\n    });\n\n    // Make a reference in GitHub's pull request ref naming convention.\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    let log_message = \"open pull request\";\n    let parent = repo.head().unwrap().peel_to_commit().unwrap();\n    let author = repo.signature().unwrap();\n    let oid = repo\n        .commit(\n            None,\n            &author,\n            &author,\n            log_message,\n            &parent.tree().unwrap(),\n            &[&parent],\n        )\n        .unwrap();\n    repo.reference(\"refs/pull/330/head\", oid, false, log_message)\n        .unwrap();\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    dep1 = {{ git = \"{}\", rev = \"refs/pull/330/head\" }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            &main_file(r#\"\"{}\", dep1::hello()\"#, &[\"dep1\"]),\n        )\n        .build();\n\n    project\n        .cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[LOCKING] 1 package to latest compatible version\n[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1?rev=refs%2Fpull%2F330%2Fhead#[..])\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(project.bin(\"foo\").is_file());\n\n    // Delete the local cache, but keep the Cargo.lock to prevent regression\n    // of <https://github.com/rust-lang/cargo/issues/16767>\n    // This ensures we fetch the refs/pull/330/head spec explicitly, even\n    // if we have a locked commit.\n    paths::cargo_home().join(\"git\").rm_rf();\n\n    project\n        .cargo(\"check\")\n        .env(\"CARGO_NET_GIT_FETCH_WITH_CLI\", \"true\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n...\n[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1?rev=refs%2Fpull%2F330%2Fhead#[..])\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_nested_paths() {\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                    [package]\n\n                    name = \"dep1\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"carlhuda@example.com\"]\n\n                    [dependencies.dep2]\n\n                    version = \"0.5.0\"\n                    path = \"vendor/dep2\"\n\n                    [lib]\n\n                    name = \"dep1\"\n                \"#,\n            )\n            .file(\n                \"src/dep1.rs\",\n                r#\"\n                    extern crate dep2;\n\n                    pub fn hello() -> &'static str {\n                        dep2::hello()\n                    }\n                \"#,\n            )\n            .file(\"vendor/dep2/Cargo.toml\", &basic_lib_manifest(\"dep2\"))\n            .file(\n                \"vendor/dep2/src/dep2.rs\",\n                r#\"\n                    pub fn hello() -> &'static str {\n                        \"hello world\"\n                    }\n                \"#,\n            )\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.dep1]\n\n                    version = \"0.5.0\"\n                    git = '{}'\n\n                    [[bin]]\n\n                    name = \"foo\"\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/foo.rs\",\n            &main_file(r#\"\"{}\", dep1::hello()\"#, &[\"dep1\"]),\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nhello world\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_malformed_nested_paths() {\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\n                \"src/dep1.rs\",\n                r#\"\n                    pub fn hello() -> &'static str {\n                        \"hello world\"\n                    }\n                \"#,\n            )\n            .file(\"vendor/dep2/Cargo.toml\", \"!INVALID!\")\n            .file(\n                \"vendor/dep3/Cargo.toml\",\n                r#\"\n                [package]\n                name = \"dep3\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                [dependencies]\n                subdep1 = { path = \"../require-extra-build-step\" }\n                \"#,\n            )\n            .file(\"vendor/dep3/src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.dep1]\n\n                    version = \"0.5.0\"\n                    git = '{}'\n\n                    [[bin]]\n\n                    name = \"foo\"\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/foo.rs\",\n            &main_file(r#\"\"{}\", dep1::hello()\"#, &[\"dep1\"]),\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nhello world\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_meta_package() {\n    let git_project = git::new(\"meta-dep\", |project| {\n        project\n            .file(\"dep1/Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\n                \"dep1/src/dep1.rs\",\n                r#\"\n                    pub fn hello() -> &'static str {\n                        \"this is dep1\"\n                    }\n                \"#,\n            )\n            .file(\"dep2/Cargo.toml\", &basic_lib_manifest(\"dep2\"))\n            .file(\n                \"dep2/src/dep2.rs\",\n                r#\"\n                    pub fn hello() -> &'static str {\n                        \"this is dep2\"\n                    }\n                \"#,\n            )\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.dep1]\n\n                    version = \"0.5.0\"\n                    git = '{}'\n\n                    [dependencies.dep2]\n\n                    version = \"0.5.0\"\n                    git = '{}'\n\n                    [[bin]]\n\n                    name = \"foo\"\n                \"#,\n                git_project.url(),\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/foo.rs\",\n            &main_file(\n                r#\"\"{} {}\", dep1::hello(), dep2::hello()\"#,\n                &[\"dep1\", \"dep2\"],\n            ),\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nthis is dep1 this is dep2\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_short_ssh_git() {\n    let url = \"git@github.com:a/dep\";\n    let well_formed_url = \"ssh://git@github.com/a/dep\";\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.dep]\n\n                    git = \"{}\"\n\n                    [[bin]]\n\n                    name = \"foo\"\n                \"#,\n                url\n            ),\n        )\n        .file(\n            \"src/foo.rs\",\n            &main_file(r#\"\"{}\", dep1::hello()\"#, &[\"dep1\"]),\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(&format!(\n            \"\\\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  invalid url `{}`: relative URL without a base; try using `{}` instead\n\",\n            url, well_formed_url\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn recompilation() {\n    let git_project = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"bar\"))\n            .file(\"src/bar.rs\", \"pub fn bar() {}\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.bar]\n\n                    version = \"0.5.0\"\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{:?}\", bar::bar()\"#, &[\"bar\"]))\n        .build();\n\n    // First time around we should compile both foo and bar\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..])\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Don't recompile the second time\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Modify a file manually, shouldn't trigger a recompile\n    git_project.change_file(\"src/bar.rs\", r#\"pub fn bar() { println!(\"hello!\"); }\"#);\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"update\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 0 packages to latest compatible versions\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Commit the changes and make sure we don't trigger a recompile because the\n    // lock file says not to change\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    git::add(&repo);\n    git::commit(&repo);\n\n    println!(\"compile after commit\");\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.root().move_into_the_past();\n\n    // Update the dependency and carry on!\n    p.cargo(\"update\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.5.0 ([ROOTURL]/bar#[..]) -> #[..]\n\n\"#]])\n        .run();\n    println!(\"going for the last compile\");\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..])\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Make sure clean only cleans one dep\n    p.cargo(\"clean -p foo\")\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_with_shared_deps() {\n    let git_project = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"bar\"))\n            .file(\"src/bar.rs\", \"pub fn bar() {}\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.dep1]\n                path = \"dep1\"\n                [dependencies.dep2]\n                path = \"dep2\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[allow(unused_extern_crates)]\n                extern crate dep1;\n                #[allow(unused_extern_crates)]\n                extern crate dep2;\n                fn main() {}\n            \"#,\n        )\n        .file(\n            \"dep1/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"dep1\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.bar]\n                    version = \"0.5.0\"\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"dep1/src/lib.rs\", \"\")\n        .file(\n            \"dep2/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"dep2\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.bar]\n                    version = \"0.5.0\"\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"dep2/src/lib.rs\", \"\")\n        .build();\n\n    // First time around we should compile both foo and bar\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 3 packages to latest compatible versions\n[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..])\n[CHECKING] dep1 v0.5.0 ([ROOT]/foo/dep1)\n[CHECKING] dep2 v0.5.0 ([ROOT]/foo/dep2)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    // Modify a file manually, and commit it\n    git_project.change_file(\"src/bar.rs\", r#\"pub fn bar() { println!(\"hello!\"); }\"#);\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    let old_head = repo.head().unwrap().target().unwrap();\n    git::add(&repo);\n    git::commit(&repo);\n\n    sleep_ms(1000);\n\n    // By default, not transitive updates\n    println!(\"dep1 update\");\n    p.cargo(\"update dep1\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.5.0 ([ROOTURL]/bar#[..]) -> #[..]\n\n\"#]])\n        .run();\n\n    // Don't do anything bad on a weird --precise argument\n    println!(\"bar bad precise update\");\n    p.cargo(\"update bar --precise 0.1.2\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[ERROR] unable to update [ROOTURL]/bar#0.1.2\n\nCaused by:\n  revspec '0.1.2' not found; class=Reference (4); code=NotFound (-3)\n\n\"#]])\n        .run();\n\n    // Specifying a precise rev to the old rev shouldn't actually update\n    // anything because we already have the rev in the db.\n    println!(\"bar precise update\");\n    p.cargo(\"update bar --precise\")\n        .arg(&old_head.to_string())\n        .with_stderr_data(str![[r#\"\n[UPDATING] bar v0.5.0 ([ROOTURL]/bar#[..]) -> #[..]\n\n\"#]])\n        .run();\n\n    // Updating recursively should, however, update the repo.\n    println!(\"dep1 recursive update\");\n    p.cargo(\"update dep1 --recursive\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.5.0 ([ROOTURL]/bar#[..]) -> #[..]\n\n\"#]])\n        .run();\n\n    // Make sure we still only compile one version of the git repo\n    println!(\"build\");\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..])\n[CHECKING] dep1 v0.5.0 ([ROOT]/foo/dep1)\n[CHECKING] dep2 v0.5.0 ([ROOT]/foo/dep2)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    // We should be able to update transitive deps\n    p.cargo(\"update bar\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 0 packages to latest compatible versions\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dep_with_submodule() {\n    let project = project();\n    let git_project = git::new(\"dep1\", |project| {\n        project.file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n    });\n    let git_project2 = git::new(\"dep2\", |project| project.file(\"lib.rs\", \"pub fn dep() {}\"));\n\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    let url = git_project2.root().to_url().to_string();\n    git::add_submodule(&repo, &url, Path::new(\"src\"));\n    git::commit(&repo);\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.dep1]\n\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate dep1; pub fn foo() { dep1::dep() }\",\n        )\n        .build();\n\n    project\n        .cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[UPDATING] git submodule `[ROOTURL]/dep2`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1#[..])\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let db_paths = glob::glob(paths::cargo_home().join(\"git/db/dep2-*\").to_str().unwrap())\n        .unwrap()\n        .map(Result::unwrap)\n        .collect::<Vec<_>>();\n    assert_eq!(db_paths.len(), 1, \"submodule db created once\");\n}\n\n#[cargo_test]\nfn dep_with_relative_submodule() {\n    let foo = project();\n    let base = git::new(\"base\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n            [package]\n            name = \"base\"\n            version = \"0.5.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            deployment.path = \"deployment\"\n        \"#,\n            )\n            .file(\n                \"src/lib.rs\",\n                r#\"\n            pub fn dep() {\n                deployment::deployment_func();\n            }\n            \"#,\n            )\n    });\n    let _deployment = git::new(\"deployment\", |project| {\n        project\n            .file(\"src/lib.rs\", \"pub fn deployment_func() {}\")\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"deployment\"))\n    });\n\n    let base_repo = git2::Repository::open(&base.root()).unwrap();\n    git::add_submodule(&base_repo, \"../deployment\", Path::new(\"deployment\"));\n    git::commit(&base_repo);\n\n    let project = foo\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n\n                    [dependencies.base]\n                    git = '{}'\n                \"#,\n                base.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {  }\")\n        .build();\n\n    project\n        .cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/base`\n[UPDATING] git submodule `[ROOTURL]/deployment`\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] deployment v0.5.0 ([ROOTURL]/base#[..])\n[CHECKING] base v0.5.0 ([ROOTURL]/base#[..])\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let db_paths = glob::glob(\n        paths::cargo_home()\n            .join(\"git/db/deployment-*\")\n            .to_str()\n            .unwrap(),\n    )\n    .unwrap()\n    .map(Result::unwrap)\n    .collect::<Vec<_>>();\n    assert_eq!(db_paths.len(), 1, \"submodule db created once\");\n}\n\n#[cargo_test]\nfn dep_with_bad_submodule() {\n    let project = project();\n    let git_project = git::new(\"dep1\", |project| {\n        project.file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n    });\n    let git_project2 = git::new(\"dep2\", |project| project.file(\"lib.rs\", \"pub fn dep() {}\"));\n\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    let url = git_project2.root().to_url().to_string();\n    git::add_submodule(&repo, &url, Path::new(\"src\"));\n    git::commit(&repo);\n\n    // now amend the first commit on git_project2 to make submodule ref point to not-found\n    // commit\n    let repo = git2::Repository::open(&git_project2.root()).unwrap();\n    let original_submodule_ref = repo.refname_to_id(\"refs/heads/master\").unwrap();\n    let commit = repo.find_commit(original_submodule_ref).unwrap();\n    commit\n        .amend(\n            Some(\"refs/heads/master\"),\n            None,\n            None,\n            None,\n            Some(\"something something\"),\n            None,\n        )\n        .unwrap();\n\n    let p = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.dep1]\n\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate dep1; pub fn foo() { dep1::dep() }\",\n        )\n        .build();\n\n    let expected = str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[UPDATING] git submodule `[ROOTURL]/dep2`\n[ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `dep1`\n\nCaused by:\n  unable to update [ROOTURL]/dep1\n\nCaused by:\n  failed to update submodule `src`\n\nCaused by:\n  failed to fetch submodule `src` from [ROOTURL]/dep2\n\nCaused by:\n  revspec '[..]' not found; class=Reference (4); code=NotFound (-3)\n\n\"#]];\n\n    p.cargo(\"check\")\n        .with_stderr_data(expected)\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn dep_with_skipped_submodule() {\n    // Ensure we skip dependency submodules if their update strategy is `none`.\n    let qux = git::new(\"qux\", |project| {\n        project.no_manifest().file(\"README\", \"skip me\")\n    });\n\n    let bar = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    // `qux` is a submodule of `bar`, but we don't want to update it.\n    let repo = git2::Repository::open(&bar.root()).unwrap();\n    git::add_submodule(&repo, qux.url().as_str(), Path::new(\"qux\"));\n\n    let mut conf = git2::Config::open(&bar.root().join(\".gitmodules\")).unwrap();\n    conf.set_str(\"submodule.qux.update\", \"none\").unwrap();\n\n    git::add(&repo);\n    git::commit(&repo);\n\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.0\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies.bar]\n                    git = \"{}\"\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[SKIPPING] git submodule `[ROOTURL]/qux` due to update strategy in .gitmodules\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.0.0 ([ROOTURL]/bar#[..])\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ambiguous_published_deps() {\n    let project = project();\n    let git_project = git::new(\"dep\", |project| {\n        project\n            .file(\n                \"duplicate1/Cargo.toml\",\n                &format!(\n                    r#\"\n                    [package]\n                    name = \"duplicate\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    publish = true\n                \"#\n                ),\n            )\n            .file(\"duplicate1/src/lib.rs\", \"\")\n            .file(\n                \"duplicate2/Cargo.toml\",\n                &format!(\n                    r#\"\n                    [package]\n                    name = \"duplicate\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    publish = true\n                \"#\n                ),\n            )\n            .file(\"duplicate2/src/lib.rs\", \"\")\n    });\n\n    let p = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.duplicate]\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {  }\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[WARNING] skipping duplicate package `duplicate v0.5.0 ([ROOTURL]/dep#[..])`:\n  [ROOT]/home/.cargo/git/checkouts/dep-[HASH]/[..]/duplicate2/Cargo.toml\nin favor of [ROOT]/home/.cargo/git/checkouts/dep-[HASH]/[..]/duplicate1/Cargo.toml\n\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unused_ambiguous_published_deps() {\n    let project = project();\n    let git_project = git::new(\"dep\", |project| {\n        project\n            .file(\n                \"unique/Cargo.toml\",\n                &format!(\n                    r#\"\n                    [package]\n                    name = \"unique\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    publish = true\n                \"#\n                ),\n            )\n            .file(\"unique/src/lib.rs\", \"\")\n            .file(\n                \"duplicate1/Cargo.toml\",\n                &format!(\n                    r#\"\n                    [package]\n                    name = \"duplicate\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    publish = true\n                \"#\n                ),\n            )\n            .file(\"duplicate1/src/lib.rs\", \"\")\n            .file(\n                \"duplicate2/Cargo.toml\",\n                &format!(\n                    r#\"\n                    [package]\n                    name = \"duplicate\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    publish = true\n                \"#\n                ),\n            )\n            .file(\"duplicate2/src/lib.rs\", \"\")\n            .file(\n                \"invalid/Cargo.toml\",\n                &format!(\n                    r#\"\n                    [package\n                    name = \"bar\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    publish = true\n                \"#\n                ),\n            )\n            .file(\"invalid/src/lib.rs\", \"\")\n    });\n\n    let p = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.unique]\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {  }\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[ERROR] unclosed table, expected `]`\n --> ../home/.cargo/git/checkouts/dep-[HASH]/[..]/invalid/Cargo.toml:2:29\n  |\n2 |                     [package\n  |                             ^\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn two_deps_only_update_one() {\n    let project = project();\n    let git1 = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let git2 = git::new(\"dep2\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep2\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.dep1]\n                    git = '{}'\n                    [dependencies.dep2]\n                    git = '{}'\n                \"#,\n                git1.url(),\n                git2.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    fn oid_to_short_sha(oid: git2::Oid) -> String {\n        oid.to_string()[..8].to_string()\n    }\n    fn git_repo_head_sha(p: &Project) -> String {\n        let repo = git2::Repository::open(p.root()).unwrap();\n        let head = repo.head().unwrap().target().unwrap();\n        oid_to_short_sha(head)\n    }\n\n    println!(\"dep1 head sha: {}\", git_repo_head_sha(&git1));\n    println!(\"dep2 head sha: {}\", git_repo_head_sha(&git2));\n\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[UPDATING] git repository `[ROOTURL]/dep2`\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1#[..])\n[CHECKING] dep2 v0.5.0 ([ROOTURL]/dep2#[..])\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    git1.change_file(\"src/lib.rs\", \"pub fn foo() {}\");\n    let repo = git2::Repository::open(&git1.root()).unwrap();\n    git::add(&repo);\n    let oid = git::commit(&repo);\n    println!(\"dep1 head sha: {}\", oid_to_short_sha(oid));\n\n    p.cargo(\"update dep1\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[LOCKING] 1 package to latest compatible version\n[UPDATING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) -> #[..]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn stale_cached_version() {\n    let bar = git::new(\"meta-dep\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n            .file(\"src/lib.rs\", \"pub fn bar() -> i32 { 1 }\")\n    });\n\n    // Update the git database in the cache with the current state of the git\n    // repo\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.0\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies.bar]\n                    git = '{}'\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                extern crate bar;\n\n                fn main() { assert_eq!(bar::bar(), 1) }\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"build\").run();\n    foo.process(&foo.bin(\"foo\")).run();\n\n    // Update the repo, and simulate someone else updating the lock file and then\n    // us pulling it down.\n    bar.change_file(\"src/lib.rs\", \"pub fn bar() -> i32 { 1 + 0 }\");\n    let repo = git2::Repository::open(&bar.root()).unwrap();\n    git::add(&repo);\n    git::commit(&repo);\n\n    sleep_ms(1000);\n\n    let rev = repo.revparse_single(\"HEAD\").unwrap().id();\n\n    foo.change_file(\n        \"Cargo.lock\",\n        &format!(\n            r#\"\n                [[package]]\n                name = \"foo\"\n                version = \"0.0.0\"\n                dependencies = [\n                 'bar 0.0.0 (git+{url}#{hash})'\n                ]\n\n                [[package]]\n                name = \"bar\"\n                version = \"0.0.0\"\n                source = 'git+{url}#{hash}'\n            \"#,\n            url = bar.url(),\n            hash = rev\n        ),\n    );\n\n    // Now build!\n    foo.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/meta-dep`\n[COMPILING] bar v0.0.0 ([ROOTURL]/meta-dep#[..])\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    foo.process(&foo.bin(\"foo\")).run();\n}\n\n#[cargo_test]\nfn dep_with_changed_submodule() {\n    let project = project();\n    let git_project = git::new(\"dep1\", |project| {\n        project.file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n    });\n\n    let git_project2 = git::new(\"dep2\", |project| {\n        project.file(\"lib.rs\", \"pub fn dep() -> &'static str { \\\"project2\\\" }\")\n    });\n\n    let git_project3 = git::new(\"dep3\", |project| {\n        project.file(\"lib.rs\", \"pub fn dep() -> &'static str { \\\"project3\\\" }\")\n    });\n\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    let mut sub = git::add_submodule(&repo, git_project2.url().as_ref(), Path::new(\"src\"));\n    git::commit(&repo);\n\n    let p = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n                    [dependencies.dep1]\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n            extern crate dep1;\n            pub fn main() { println!(\\\"{}\\\", dep1::dep()) }\n        \",\n        )\n        .build();\n\n    println!(\"first run\");\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[UPDATING] git submodule `[ROOTURL]/dep2`\n[LOCKING] 1 package to latest compatible version\n[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1#[..])\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nproject2\n\n\"#]])\n        .run();\n\n    let db_paths = glob::glob(paths::cargo_home().join(\"git/db/dep2-*\").to_str().unwrap())\n        .unwrap()\n        .map(Result::unwrap)\n        .collect::<Vec<_>>();\n    assert_eq!(db_paths.len(), 1, \"submodule db created once\");\n\n    git_project.change_file(\n        \".gitmodules\",\n        &format!(\n            \"[submodule \\\"src\\\"]\\n\\tpath = src\\n\\turl={}\",\n            git_project3.url()\n        ),\n    );\n\n    // Sync the submodule and reset it to the new remote.\n    sub.sync().unwrap();\n    {\n        let subrepo = sub.open().unwrap();\n        subrepo\n            .remote_add_fetch(\"origin\", \"refs/heads/*:refs/heads/*\")\n            .unwrap();\n        subrepo\n            .remote_set_url(\"origin\", git_project3.url().as_ref())\n            .unwrap();\n        let mut origin = subrepo.find_remote(\"origin\").unwrap();\n        origin.fetch(&Vec::<String>::new(), None, None).unwrap();\n        let id = subrepo.refname_to_id(\"refs/remotes/origin/master\").unwrap();\n        let obj = subrepo.find_object(id, None).unwrap();\n        subrepo.reset(&obj, git2::ResetType::Hard, None).unwrap();\n    }\n    sub.add_to_index(true).unwrap();\n    git::add(&repo);\n    git::commit(&repo);\n\n    sleep_ms(1000);\n    // Update the dependency and carry on!\n    println!(\"update\");\n    p.cargo(\"update\")\n        .with_stdout_data(str![])\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[UPDATING] git submodule `[ROOTURL]/dep3`\n[LOCKING] 1 package to latest compatible version\n[UPDATING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) -> #[..]\n\n\"#]])\n        .run();\n\n    let db_paths = glob::glob(paths::cargo_home().join(\"git/db/dep3-*\").to_str().unwrap())\n        .unwrap()\n        .map(Result::unwrap)\n        .collect::<Vec<_>>();\n    assert_eq!(db_paths.len(), 1, \"submodule db created once\");\n\n    println!(\"last run\");\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1#[..])\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nproject3\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dev_deps_with_testing() {\n    let p2 = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n            .file(\n                \"src/lib.rs\",\n                r#\"\n                    pub fn gimme() -> &'static str { \"zoidberg\" }\n                \"#,\n            )\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dev-dependencies.bar]\n                    version = \"0.5.0\"\n                    git = '{}'\n                \"#,\n                p2.url()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {}\n\n                #[cfg(test)]\n                mod tests {\n                    extern crate bar;\n                    #[test] fn foo() { bar::gimme(); }\n                }\n            \"#,\n        )\n        .build();\n\n    // Generate a lock file which did not use `bar` to compile, but had to update\n    // `bar` to generate the lock file\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Make sure we use the previous resolution of `bar` instead of updating it\n    // a second time.\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.5.0 ([ROOTURL]/bar#[..])\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest tests::foo ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_build_cmd_freshness() {\n    let foo = git::new(\"foo\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.0\"\n                    edition = \"2015\"\n                    authors = []\n                    build = \"build.rs\"\n                \"#,\n            )\n            .file(\"build.rs\", \"fn main() {}\")\n            .file(\"src/lib.rs\", \"pub fn bar() -> i32 { 1 }\")\n            .file(\".gitignore\", \"src/bar.rs\")\n    });\n    foo.root().move_into_the_past();\n\n    sleep_ms(1000);\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Smoke test to make sure it doesn't compile again\n    println!(\"first pass\");\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Modify an ignored file and make sure we don't rebuild\n    println!(\"second pass\");\n    foo.change_file(\"src/bar.rs\", \"\");\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_name_not_always_needed() {\n    let p2 = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n            .file(\n                \"src/lib.rs\",\n                r#\"\n                    pub fn gimme() -> &'static str { \"zoidberg\" }\n                \"#,\n            )\n    });\n\n    let repo = git2::Repository::open(&p2.root()).unwrap();\n    let mut cfg = repo.config().unwrap();\n    let _ = cfg.remove(\"user.name\");\n    let _ = cfg.remove(\"user.email\");\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dev-dependencies.bar]\n                    git = '{}'\n                \"#,\n                p2.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // Generate a lock file which did not use `bar` to compile, but had to update\n    // `bar` to generate the lock file\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_repo_changing_no_rebuild() {\n    let bar = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"pub fn bar() -> i32 { 1 }\")\n    });\n\n    // Lock p1 to the first rev in the git repo\n    let p1 = project()\n        .at(\"p1\")\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"p1\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    build = 'build.rs'\n                    [dependencies.bar]\n                    git = '{}'\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n    p1.root().move_into_the_past();\n    p1.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[COMPILING] p1 v0.5.0 ([ROOT]/p1)\n[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..])\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Make a commit to lock p2 to a different rev\n    bar.change_file(\"src/lib.rs\", \"pub fn bar() -> i32 { 2 }\");\n    let repo = git2::Repository::open(&bar.root()).unwrap();\n    git::add(&repo);\n    git::commit(&repo);\n\n    // Lock p2 to the second rev\n    let p2 = project()\n        .at(\"p2\")\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"p2\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    [dependencies.bar]\n                    git = '{}'\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p2.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..])\n[CHECKING] p2 v0.5.0 ([ROOT]/p2)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // And now for the real test! Make sure that p1 doesn't get rebuilt\n    // even though the git repo has changed.\n    p1.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_dep_build_cmd() {\n    let p = git::new(\"foo\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.bar]\n\n                    version = \"0.5.0\"\n                    path = \"bar\"\n\n                    [[bin]]\n\n                    name = \"foo\"\n                \"#,\n            )\n            .file(\"src/foo.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n            .file(\n                \"bar/Cargo.toml\",\n                r#\"\n                    [package]\n\n                    name = \"bar\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n                    build = \"build.rs\"\n\n                    [lib]\n                    name = \"bar\"\n                    path = \"src/bar.rs\"\n                \"#,\n            )\n            .file(\n                \"bar/src/bar.rs.in\",\n                r#\"\n                    pub fn gimme() -> i32 { 0 }\n                \"#,\n            )\n            .file(\n                \"bar/build.rs\",\n                r#\"\n                    use std::fs;\n                    fn main() {\n                        fs::copy(\"src/bar.rs.in\", \"src/bar.rs\").unwrap();\n                    }\n                \"#,\n            )\n    });\n\n    p.root().join(\"bar\").move_into_the_past();\n\n    p.cargo(\"build\").run();\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\n0\n\n\"#]])\n        .run();\n\n    // Touching bar.rs.in should cause the `build` command to run again.\n    p.change_file(\"bar/src/bar.rs.in\", \"pub fn gimme() -> i32 { 1 }\");\n\n    p.cargo(\"build\").run();\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\n1\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fetch_downloads() {\n    let bar = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"pub fn bar() -> i32 { 1 }\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    [dependencies.bar]\n                    git = '{}'\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"fetch\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n\n    p.cargo(\"fetch\").with_stderr_data(str![]).run();\n}\n\n#[cargo_test]\nfn fetch_downloads_with_git2_first_then_with_gitoxide_and_vice_versa() {\n    let bar = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"pub fn bar() -> i32 { 1 }\")\n    });\n    let feature_configuration = if cargo_uses_gitoxide() {\n        // When we are always using `gitoxide` by default, create the registry with git2 as well as the download…\n        \"-Zgitoxide=internal-use-git2\"\n    } else {\n        // …otherwise create the registry and the git download with `gitoxide`.\n        \"-Zgitoxide=fetch\"\n    };\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    [dependencies.bar]\n                    git = '{url}'\n                \"#,\n                url = bar.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"fetch\")\n        .arg(feature_configuration)\n        .masquerade_as_nightly_cargo(&[\"unstable features must be available for -Z gitoxide\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n\n    Package::new(\"bar\", \"1.0.0\").publish(); // trigger a crates-index change.\n    p.cargo(\"fetch\").with_stderr_data(str![]).run();\n}\n\n#[cargo_test]\nfn warnings_in_git_dep() {\n    let bar = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"fn unused() {}\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    [dependencies.bar]\n                    git = '{}'\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..])\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_ambiguous() {\n    let bar1 = git::new(\"bar1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let bar2 = git::new(\"bar2\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.6.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let baz = git::new(\"baz\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n                        [package]\n                        name = \"baz\"\n                        version = \"0.5.0\"\n                        edition = \"2015\"\n                        authors = [\"wycats@example.com\"]\n\n                        [dependencies.bar]\n                        git = '{}'\n                    \"#,\n                    bar2.url()\n                ),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    [dependencies.bar]\n                    git = '{}'\n                    [dependencies.baz]\n                    git = '{}'\n                \"#,\n                bar1.url(),\n                baz.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n    p.cargo(\"update bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] specification `bar` is ambiguous\n[HELP] re-run this command with one of the following specifications\n  bar@0.5.0\n  bar@0.6.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_one_dep_in_repo_with_many_deps() {\n    let bar = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n            .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.5.0\"))\n            .file(\"a/src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    [dependencies.bar]\n                    git = '{}'\n                    [dependencies.a]\n                    git = '{}'\n                \"#,\n                bar.url(),\n                bar.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n    p.cargo(\"update bar\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 0 packages to latest compatible versions\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn switch_deps_does_not_update_transitive() {\n    let transitive = git::new(\"transitive\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"transitive\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let dep1 = git::new(\"dep1\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n                        [package]\n                        name = \"dep\"\n                        version = \"0.5.0\"\n                        edition = \"2015\"\n                        authors = [\"wycats@example.com\"]\n\n                        [dependencies.transitive]\n                        git = '{}'\n                    \"#,\n                    transitive.url()\n                ),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n    let dep2 = git::new(\"dep2\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n                        [package]\n                        name = \"dep\"\n                        version = \"0.5.0\"\n                        edition = \"2015\"\n                        authors = [\"wycats@example.com\"]\n\n                        [dependencies.transitive]\n                        git = '{}'\n                    \"#,\n                    transitive.url()\n                ),\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    [dependencies.dep]\n                    git = '{}'\n                \"#,\n                dep1.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[UPDATING] git repository `[ROOTURL]/transitive`\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] transitive v0.5.0 ([ROOTURL]/transitive#[..])\n[CHECKING] dep v0.5.0 ([ROOTURL]/dep1#[..])\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Update the dependency to point to the second repository, but this\n    // shouldn't update the transitive dependency which is the same.\n    p.change_file(\n        \"Cargo.toml\",\n        &format!(\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies.dep]\n                git = '{}'\n            \"#,\n            dep2.url()\n        ),\n    );\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep2`\n[LOCKING] 1 package to latest compatible version\n[ADDING] dep v0.5.0 ([ROOTURL]/dep2#[..])\n[CHECKING] dep v0.5.0 ([ROOTURL]/dep2#[..])\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_one_source_updates_all_packages_in_that_git_source() {\n    let dep = git::new(\"dep\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                    [package]\n                    name = \"dep\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies.a]\n                    path = \"a\"\n                \"#,\n            )\n            .file(\"src/lib.rs\", \"\")\n            .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.5.0\"))\n            .file(\"a/src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    [dependencies.dep]\n                    git = '{}'\n                \"#,\n                dep.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    let repo = git2::Repository::open(&dep.root()).unwrap();\n    let rev1 = repo.revparse_single(\"HEAD\").unwrap().id();\n\n    // Just be sure to change a file\n    dep.change_file(\"src/lib.rs\", \"pub fn bar() -> i32 { 2 }\");\n    git::add(&repo);\n    git::commit(&repo);\n\n    p.cargo(\"update dep\").run();\n    let lockfile = p.read_lockfile();\n    assert!(\n        !lockfile.contains(&rev1.to_string()),\n        \"{} in {}\",\n        rev1,\n        lockfile\n    );\n}\n\n#[cargo_test]\nfn switch_sources() {\n    let a1 = git::new(\"a1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"a\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let a2 = git::new(\"a2\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"a\", \"0.5.1\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies.b]\n                path = \"b\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"b/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"b\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    [dependencies.a]\n                    git = '{}'\n                \"#,\n                a1.url()\n            ),\n        )\n        .file(\"b/src/lib.rs\", \"pub fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/a1`\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] a v0.5.0 ([ROOTURL]/a1#[..])\n[CHECKING] b v0.5.0 ([ROOT]/foo/b)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"b/Cargo.toml\",\n        &format!(\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies.a]\n                git = '{}'\n            \"#,\n            a2.url()\n        ),\n    );\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/a2`\n[LOCKING] 1 package to latest compatible version\n[ADDING] a v0.5.1 ([ROOTURL]/a2#[..])\n[CHECKING] a v0.5.1 ([ROOTURL]/a2#[..])\n[CHECKING] b v0.5.0 ([ROOT]/foo/b)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dont_require_submodules_are_checked_out() {\n    let p = project().build();\n    let git1 = git::new(\"dep1\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/foo\", \"\")\n    });\n    let git2 = git::new(\"dep2\", |p| p);\n\n    let repo = git2::Repository::open(&git1.root()).unwrap();\n    let url = git2.root().to_url().to_string();\n    git::add_submodule(&repo, &url, Path::new(\"a/submodule\"));\n    git::commit(&repo);\n\n    git2::Repository::init(&p.root()).unwrap();\n    let url = git1.root().to_url().to_string();\n    let dst = paths::home().join(\"foo\");\n    git2::Repository::clone(&url, &dst).unwrap();\n\n    git1.cargo(\"check -v\").cwd(&dst).run();\n}\n\n#[cargo_test]\nfn doctest_same_name() {\n    let a2 = git::new(\"a2\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"a\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"pub fn a2() {}\")\n    });\n\n    let a1 = git::new(\"a1\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"a\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    [dependencies]\n                    a = {{ git = '{}' }}\n                \"#,\n                a2.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"extern crate a; pub fn a1() {}\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    a = {{ git = '{}' }}\n                \"#,\n                a1.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[macro_use]\n                extern crate a;\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test -v\").run();\n}\n\n#[cargo_test]\nfn lints_are_suppressed() {\n    let a = git::new(\"a\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"a\", \"0.5.0\")).file(\n            \"src/lib.rs\",\n            \"\n            use std::option;\n        \",\n        )\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    a = {{ git = '{}' }}\n                \"#,\n                a.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/a`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] a v0.5.0 ([ROOTURL]/a#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn denied_lints_are_allowed() {\n    let a = git::new(\"a\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"a\", \"0.5.0\")).file(\n            \"src/lib.rs\",\n            \"\n            #![deny(warnings)]\n            use std::option;\n        \",\n        )\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    a = {{ git = '{}' }}\n                \"#,\n                a.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/a`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] a v0.5.0 ([ROOTURL]/a#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn add_a_git_dep() {\n    let git = git::new(\"git\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"git\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    a = {{ path = 'a' }}\n                    git = {{ git = '{}' }}\n                \"#,\n                git.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    assert!(paths::home().join(\".cargo/git/CACHEDIR.TAG\").is_file());\n\n    p.change_file(\n        \"a/Cargo.toml\",\n        &format!(\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                git = {{ git = '{}' }}\n            \"#,\n            git.url()\n        ),\n    );\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn two_at_rev_instead_of_tag() {\n    let git = git::new(\"git\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"git1\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n            .file(\"a/Cargo.toml\", &basic_manifest(\"git2\", \"0.5.0\"))\n            .file(\"a/src/lib.rs\", \"\")\n    });\n\n    // Make a tag corresponding to the current HEAD\n    let repo = git2::Repository::open(&git.root()).unwrap();\n    let head = repo.head().unwrap().target().unwrap();\n    repo.tag(\n        \"v0.1.0\",\n        &repo.find_object(head, None).unwrap(),\n        &repo.signature().unwrap(),\n        \"make a new tag\",\n        false,\n    )\n    .unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    git1 = {{ git = '{0}', rev = 'v0.1.0' }}\n                    git2 = {{ git = '{0}', rev = 'v0.1.0' }}\n                \"#,\n                git.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn include_overrides_gitignore() {\n    // Make sure that `package.include` takes precedence over .gitignore.\n    let p = git::new(\"foo\", |repo| {\n        repo.file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                include = [\"src/lib.rs\", \"ignored.txt\", \"Cargo.toml\"]\n            \"#,\n        )\n        .file(\n            \".gitignore\",\n            r#\"\n                /target\n                Cargo.lock\n                ignored.txt\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"ignored.txt\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n    });\n\n    p.cargo(\"check\").run();\n    p.change_file(\"ignored.txt\", \"Trigger rebuild.\");\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.5.0 ([ROOT]/foo): the precalculated components changed\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"package --list --allow-dirty\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nignored.txt\nsrc/lib.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_git_dependency_manifest() {\n    let project = project();\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                    [package]\n\n                    name = \"dep1\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"carlhuda@example.com\"]\n                    categories = [\"algorithms\"]\n                    categories = [\"algorithms\"]\n\n                    [lib]\n\n                    name = \"dep1\"\n                \"#,\n            )\n            .file(\n                \"src/dep1.rs\",\n                r#\"\n                    pub fn hello() -> &'static str {\n                        \"hello world\"\n                    }\n                \"#,\n            )\n    });\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.dep1]\n\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            &main_file(r#\"\"{}\", dep1::hello()\"#, &[\"dep1\"]),\n        )\n        .build();\n\n    project\n        .cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[ERROR] duplicate key\n --> ../home/.cargo/git/checkouts/dep1-[HASH]/[..]/Cargo.toml:9:21\n  |\n9 |                     categories = [\"algorithms\"]\n  |                     ^^^^^^^^^^\n[ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `dep1`\n\nCaused by:\n  unable to update [ROOTURL]/dep1\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn failed_submodule_checkout() {\n    let project = project();\n    let git_project = git::new(\"dep1\", |project| {\n        project.file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n    });\n\n    let git_project2 = git::new(\"dep2\", |project| project.file(\"lib.rs\", \"\"));\n\n    let listener = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let addr = listener.local_addr().unwrap();\n    let done = Arc::new(AtomicBool::new(false));\n    let done2 = done.clone();\n\n    let t = thread::spawn(move || {\n        while !done2.load(Ordering::SeqCst) {\n            if let Ok((mut socket, _)) = listener.accept() {\n                drop(socket.write_all(b\"foo\\r\\n\"));\n            }\n        }\n    });\n\n    let repo = git2::Repository::open(&git_project2.root()).unwrap();\n    let url = format!(\"https://{}:{}/\", addr.ip(), addr.port());\n    {\n        let mut s = repo.submodule(&url, Path::new(\"bar\"), false).unwrap();\n        let subrepo = s.open().unwrap();\n        let mut cfg = subrepo.config().unwrap();\n        cfg.set_str(\"user.email\", \"foo@bar.com\").unwrap();\n        cfg.set_str(\"user.name\", \"Foo Bar\").unwrap();\n        git::commit(&subrepo);\n        s.add_finalize().unwrap();\n    }\n    git::commit(&repo);\n    drop((repo, url));\n\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    let url = git_project2.root().to_url().to_string();\n    git::add_submodule(&repo, &url, Path::new(\"src\"));\n    git::commit(&repo);\n    drop(repo);\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    dep1 = {{ git = '{}' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    project\n        .cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n  failed to update submodule `src`\n...\n  failed to update submodule `bar`\n...\n\"#]])\n        .run();\n    project\n        .cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n  failed to update submodule `src`\n...\n  failed to update submodule `bar`\n...\n\"#]])\n        .run();\n\n    done.store(true, Ordering::SeqCst);\n    drop(TcpStream::connect(&addr));\n    t.join().unwrap();\n}\n\n#[cargo_test(requires = \"git\")]\nfn use_the_cli() {\n    let project = project();\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    dep1 = {{ git = '{}' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            \"\n                [net]\n                git-fetch-with-cli = true\n            \",\n        )\n        .build();\n\n    let stderr = str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[RUNNING] `git fetch --no-tags --verbose --force --update-head-ok [..][ROOTURL]/dep1[..] [..]+HEAD:refs/remotes/origin/HEAD[..]`\nFrom [ROOTURL]/dep1\n * [new ref] [..] -> origin/HEAD[..]\n[LOCKING] 1 package to latest compatible version\n[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1#[..])\n[RUNNING] `rustc --crate-name dep1 [..]`\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]];\n\n    project\n        .cargo(\"check -v\")\n        .env(\"LC_ALL\", \"C\")\n        .with_stderr_data(stderr)\n        .run();\n    assert!(paths::home().join(\".cargo/git/CACHEDIR.TAG\").is_file());\n}\n\n#[cargo_test]\nfn templatedir_doesnt_cause_problems() {\n    let git_project2 = git::new(\"dep2\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep2\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    dep1 = {{ git = '{}' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    fs::write(\n        paths::home().join(\".gitconfig\"),\n        format!(\n            r#\"\n                [init]\n                templatedir = {}\n            \"#,\n            git_project2\n                .url()\n                .to_file_path()\n                .unwrap()\n                .to_str()\n                .unwrap()\n                .replace(\"\\\\\", \"/\")\n        ),\n    )\n    .unwrap();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test(requires = \"git\")]\nfn git_with_cli_force() {\n    // Supports a force-pushed repo.\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\"src/lib.rs\", r#\"pub fn f() { println!(\"one\"); }\"#)\n    });\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2018\"\n\n                [dependencies]\n                dep1 = {{ git = \"{}\" }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() { dep1::f(); }\")\n        .file(\n            \".cargo/config.toml\",\n            \"\n            [net]\n            git-fetch-with-cli = true\n            \",\n        )\n        .build();\n    p.cargo(\"build\").run();\n    p.rename_run(\"foo\", \"foo1\")\n        .with_stdout_data(str![[r#\"\none\n\n\"#]])\n        .run();\n\n    // commit --amend a change that will require a force fetch.\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    git_project.change_file(\"src/lib.rs\", r#\"pub fn f() { println!(\"two\"); }\"#);\n    git::add(&repo);\n    let id = repo.refname_to_id(\"HEAD\").unwrap();\n    let commit = repo.find_commit(id).unwrap();\n    let tree_id = t!(t!(repo.index()).write_tree());\n    t!(commit.amend(\n        Some(\"HEAD\"),\n        None,\n        None,\n        None,\n        None,\n        Some(&t!(repo.find_tree(tree_id)))\n    ));\n    // Perform the fetch.\n    p.cargo(\"update\").run();\n    p.cargo(\"build\").run();\n    p.rename_run(\"foo\", \"foo2\")\n        .with_stdout_data(str![[r#\"\ntwo\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(requires = \"git\")]\nfn git_fetch_cli_env_clean() {\n    // This tests that git-fetch-with-cli works when GIT_DIR environment\n    // variable is set (for whatever reason).\n    let git_dep = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let git_proj = git::new(\"foo\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n                    [dependencies]\n                    dep1 = {{ git = '{}' }}\n                    \"#,\n                    git_dep.url()\n                ),\n            )\n            .file(\"src/lib.rs\", \"pub extern crate dep1;\")\n            .file(\n                \".cargo/config.toml\",\n                \"\n                [net]\n                git-fetch-with-cli = true\n                \",\n            )\n    });\n\n    // The directory set here isn't too important. Pointing to our own git\n    // directory causes git to be confused and fail. Can also point to an\n    // empty directory, or a nonexistent one.\n    git_proj\n        .cargo(\"fetch\")\n        .env(\"GIT_DIR\", git_proj.root().join(\".git\"))\n        .run();\n}\n\n#[cargo_test]\nfn dirty_submodule() {\n    // `cargo package` warns for dirty file in submodule.\n    let (git_project, repo) = git::new_repo(\"foo\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.5.0\"))\n            // This is necessary because `git::add` is too eager.\n            .file(\".gitignore\", \"/target\")\n    });\n    let git_project2 = git::new(\"src\", |project| {\n        project.no_manifest().file(\"lib.rs\", \"pub fn f() {}\")\n    });\n\n    let url = git_project2.root().to_url().to_string();\n    git::add_submodule(&repo, &url, Path::new(\"src\"));\n\n    // Submodule added, but not committed.\n    git_project\n        .cargo(\"package --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[ERROR] 2 files in the working directory contain changes that were not yet committed into git:\n\n.gitmodules\nsrc/lib.rs\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n\n    git::commit(&repo);\n    git_project.cargo(\"package --no-verify\").run();\n\n    // Modify file, check for warning.\n    git_project.change_file(\"src/lib.rs\", \"\");\n    git_project\n        .cargo(\"package --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[ERROR] 1 files in the working directory contain changes that were not yet committed into git:\n\nsrc/lib.rs\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n    // Commit the change.\n    let sub_repo = git2::Repository::open(git_project.root().join(\"src\")).unwrap();\n    git::add(&sub_repo);\n    git::commit(&sub_repo);\n    git::add(&repo);\n    git::commit(&repo);\n    git_project.cargo(\"package --no-verify\").run();\n\n    // Try with a nested submodule.\n    let git_project3 = git::new(\"bar\", |project| project.no_manifest().file(\"mod.rs\", \"\"));\n    let url = git_project3.root().to_url().to_string();\n    git::add_submodule(&sub_repo, &url, Path::new(\"bar\"));\n    git_project\n        .cargo(\"package --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[ERROR] 2 files in the working directory contain changes that were not yet committed into git:\n\nsrc/.gitmodules\nsrc/bar/mod.rs\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n\n    // Commit the submodule addition.\n    git::commit(&sub_repo);\n    git::add(&repo);\n    git::commit(&repo);\n    git_project.cargo(\"package --no-verify\").run();\n    // Modify within nested submodule.\n    git_project.change_file(\"src/bar/new_file.rs\", \"//test\");\n    git_project\n        .cargo(\"package --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[ERROR] 1 files in the working directory contain changes that were not yet committed into git:\n\nsrc/bar/new_file.rs\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n    // And commit the change.\n    let sub_sub_repo = git2::Repository::open(git_project.root().join(\"src/bar\")).unwrap();\n    git::add(&sub_sub_repo);\n    git::commit(&sub_sub_repo);\n    git::add(&sub_repo);\n    git::commit(&sub_repo);\n    git::add(&repo);\n    git::commit(&repo);\n    git_project.cargo(\"package --no-verify\").run();\n}\n\n#[cargo_test]\nfn default_not_master() {\n    let project = project();\n\n    // Create a repository with a `master` branch, but switch the head to a\n    // branch called `main` at the same time.\n    let (git_project, repo) = git::new_repo(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\"src/lib.rs\", \"pub fn foo() {}\")\n    });\n    let head_id = repo.head().unwrap().target().unwrap();\n    let head = repo.find_commit(head_id).unwrap();\n    repo.branch(\"main\", &head, false).unwrap();\n    repo.set_head(\"refs/heads/main\").unwrap();\n\n    // Then create a commit on the new `main` branch so `master` and `main`\n    // differ.\n    git_project.change_file(\"src/lib.rs\", \"pub fn bar() {}\");\n    git::add(&repo);\n    git::commit(&repo);\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    [dependencies]\n                    dep1 = {{ git = '{}' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() { dep1::bar() }\")\n        .build();\n\n    project\n        .cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1#[..])\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn historical_lockfile_works() {\n    let project = project();\n\n    let (git_project, repo) = git::new_repo(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let head_id = repo.head().unwrap().target().unwrap();\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    dep1 = {{ git = '{}', branch = 'master' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    project.cargo(\"check\").run();\n    project.change_file(\n        \"Cargo.lock\",\n        &format!(\n            r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\n[[package]]\nname = \"dep1\"\nversion = \"0.5.0\"\nsource = \"git+{}#{}\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.5.0\"\ndependencies = [\n \"dep1\",\n]\n\"#,\n            git_project.url(),\n            head_id\n        ),\n    );\n    project\n        .cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ADDING] dep1 v0.5.0 ([ROOTURL]/dep1?branch=master#[..])\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn historical_lockfile_works_with_vendor() {\n    let project = project();\n\n    let (git_project, repo) = git::new_repo(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let head_id = repo.head().unwrap().target().unwrap();\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    dep1 = {{ git = '{}', branch = 'master' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let output = project.cargo(\"vendor\").run();\n    project.change_file(\n        \".cargo/config.toml\",\n        str::from_utf8(&output.stdout).unwrap(),\n    );\n    project.change_file(\n        \"Cargo.lock\",\n        &format!(\n            r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\n[[package]]\nname = \"dep1\"\nversion = \"0.5.0\"\nsource = \"git+{}#{}\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.5.0\"\ndependencies = [\n \"dep1\",\n]\n\"#,\n            git_project.url(),\n            head_id\n        ),\n    );\n    project.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn two_dep_forms() {\n    let project = project();\n\n    let (git_project, _repo) = git::new_repo(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    [dependencies]\n                    dep1 = {{ git = '{}', branch = 'master' }}\n                    a = {{ path = 'a' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"a\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    [dependencies]\n                    dep1 = {{ git = '{}' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    // This will download the git repository twice, one with HEAD and once with\n    // the master branch. Then it'll compile 4 crates, the 2 git deps, then\n    // the two local deps.\n    project\n        .cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[UPDATING] git repository `[ROOTURL]/dep1`\n[LOCKING] 3 packages to latest compatible versions\n[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1#[..])\n[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1?branch=master#[..])\n[CHECKING] a v0.5.0 ([ROOT]/foo/a)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn metadata_master_consistency() {\n    // SourceId consistency in the `cargo metadata` output when `master` is\n    // explicit or implicit, using new or old Cargo.lock.\n    let (git_project, git_repo) = git::new_repo(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let bar_hash = git_repo.head().unwrap().target().unwrap().to_string();\n\n    // Explicit branch=\"master\" with a lock file created before 1.47 (does not contain ?branch=master).\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = {{ git = \"{}\", branch = \"master\" }}\n            \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"Cargo.lock\",\n            &format!(\n                r#\"\n                    [[package]]\n                    name = \"bar\"\n                    version = \"1.0.0\"\n                    source = \"git+{}#{}\"\n\n                    [[package]]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    dependencies = [\n                     \"bar\",\n                    ]\n                \"#,\n                git_project.url(),\n                bar_hash,\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let metadata = |bar_source| -> String {\n        r#\"\n            {\n              \"packages\": [\n                {\n                  \"name\": \"bar\",\n                  \"version\": \"1.0.0\",\n                  \"id\": \"__BAR_SOURCE__#1.0.0\",\n                  \"license\": null,\n                  \"license_file\": null,\n                  \"description\": null,\n                  \"source\": \"__BAR_SOURCE__#__BAR_HASH__\",\n                  \"dependencies\": [],\n                  \"targets\": \"{...}\",\n                  \"features\": {},\n                  \"manifest_path\": \"[..]\",\n                  \"metadata\": null,\n                  \"publish\": null,\n                  \"authors\": [],\n                  \"categories\": [],\n                  \"default_run\": null,\n                  \"keywords\": [],\n                  \"readme\": null,\n                  \"repository\": null,\n                  \"rust_version\": null,\n                  \"homepage\": null,\n                  \"documentation\": null,\n                  \"edition\": \"2015\",\n                  \"links\": null\n                },\n                {\n                  \"name\": \"foo\",\n                  \"version\": \"0.1.0\",\n                  \"id\": \"[..]foo#0.1.0\",\n                  \"license\": null,\n                  \"license_file\": null,\n                  \"description\": null,\n                  \"source\": null,\n                  \"dependencies\": [\n                    {\n                      \"name\": \"bar\",\n                      \"source\": \"__BAR_SOURCE__\",\n                      \"req\": \"*\",\n                      \"kind\": null,\n                      \"rename\": null,\n                      \"optional\": false,\n                      \"uses_default_features\": true,\n                      \"features\": [],\n                      \"target\": null,\n                      \"registry\": null\n                    }\n                  ],\n                  \"targets\": \"{...}\",\n                  \"features\": {},\n                  \"manifest_path\": \"[..]\",\n                  \"metadata\": null,\n                  \"publish\": null,\n                  \"authors\": [],\n                  \"categories\": [],\n                  \"default_run\": null,\n                  \"keywords\": [],\n                  \"readme\": null,\n                  \"repository\": null,\n                  \"rust_version\": null,\n                  \"homepage\": null,\n                  \"documentation\": null,\n                  \"edition\": \"2015\",\n                  \"links\": null\n                }\n              ],\n              \"workspace_members\": [\n                \"[..]foo#0.1.0\"\n              ],\n              \"workspace_default_members\": [\n                \"[..]foo#0.1.0\"\n              ],\n              \"resolve\": {\n                \"nodes\": [\n                  {\n                    \"id\": \"__BAR_SOURCE__#1.0.0\",\n                    \"dependencies\": [],\n                    \"deps\": [],\n                    \"features\": []\n                  },\n                  {\n                    \"id\": \"[..]foo#0.1.0\",\n                    \"dependencies\": [\n                      \"__BAR_SOURCE__#1.0.0\"\n                    ],\n                    \"deps\": [\n                      {\n                        \"name\": \"bar\",\n                        \"pkg\": \"__BAR_SOURCE__#1.0.0\",\n                        \"dep_kinds\": [\n                          {\n                            \"kind\": null,\n                            \"target\": null\n                          }\n                        ]\n                      }\n                    ],\n                    \"features\": []\n                  }\n                ],\n                \"root\": \"[..]foo#0.1.0\"\n              },\n              \"target_directory\": \"[..]\",\n              \"build_directory\": \"[..]\",\n              \"version\": 1,\n              \"workspace_root\": \"[..]\",\n              \"metadata\": null\n            }\n        \"#\n        .replace(\"__BAR_SOURCE__\", bar_source)\n        .replace(\"__BAR_HASH__\", &bar_hash)\n    };\n\n    let bar_source = \"git+[ROOTURL]/bar?branch=master\";\n    p.cargo(\"metadata\")\n        .with_stdout_data(&metadata(&bar_source).is_json())\n        .run();\n\n    // Conversely, remove branch=\"master\" from Cargo.toml, but use a new Cargo.lock that has ?branch=master.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = {{ git = \"{}\" }}\n            \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"Cargo.lock\",\n            &format!(\n                r#\"\n                    [[package]]\n                    name = \"bar\"\n                    version = \"1.0.0\"\n                    source = \"git+{}?branch=master#{}\"\n\n                    [[package]]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    dependencies = [\n                     \"bar\",\n                    ]\n                \"#,\n                git_project.url(),\n                bar_hash\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // No ?branch=master!\n    let bar_source = \"git+[ROOTURL]/bar\";\n    p.cargo(\"metadata\")\n        .with_stdout_data(&metadata(&bar_source).is_json())\n        .run();\n}\n\n#[cargo_test]\nfn git_with_force_push() {\n    // Checks that cargo can handle force-pushes to git repos.\n    // This works by having a git dependency that is updated with an amend\n    // commit, and tries with various forms (default branch, branch, rev,\n    // tag).\n    let main = |text| format!(r#\"pub fn f() {{ println!(\"{}\"); }}\"#, text);\n    let (git_project, repo) = git::new_repo(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\"src/lib.rs\", &main(\"one\"))\n    });\n    let manifest = |extra| {\n        format!(\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2018\"\n\n                [dependencies]\n                dep1 = {{ git = \"{}\"{} }}\n            \"#,\n            git_project.url(),\n            extra\n        )\n    };\n    let p = project()\n        .file(\"Cargo.toml\", &manifest(\"\"))\n        .file(\"src/main.rs\", \"fn main() { dep1::f(); }\")\n        .build();\n    // Download the original and make sure it is OK.\n    p.cargo(\"build\").run();\n    p.rename_run(\"foo\", \"foo1\")\n        .with_stdout_data(str![[r#\"\none\n\n\"#]])\n        .run();\n\n    let find_head = || t!(t!(repo.head()).peel_to_commit());\n\n    let amend_commit = |text| {\n        // commit --amend a change that will require a force fetch.\n        git_project.change_file(\"src/lib.rs\", &main(text));\n        git::add(&repo);\n        let commit = find_head();\n        let tree_id = t!(t!(repo.index()).write_tree());\n        t!(commit.amend(\n            Some(\"HEAD\"),\n            None,\n            None,\n            None,\n            None,\n            Some(&t!(repo.find_tree(tree_id)))\n        ));\n    };\n\n    let mut rename_annoyance = 1;\n\n    let mut verify = |text| {\n        // Perform the fetch.\n        p.cargo(\"update\").run();\n        p.cargo(\"build\").run();\n        rename_annoyance += 1;\n        p.rename_run(\"foo\", &format!(\"foo{}\", rename_annoyance))\n            .with_stdout_data(text)\n            .run();\n    };\n\n    amend_commit(\"two\");\n    verify(str![[r#\"\ntwo\n\n\"#]]);\n\n    // Try with a rev.\n    let head1 = find_head().id().to_string();\n    let extra = format!(\", rev = \\\"{}\\\"\", head1);\n    p.change_file(\"Cargo.toml\", &manifest(&extra));\n    verify(str![[r#\"\ntwo\n\n\"#]]);\n    amend_commit(\"three\");\n    let head2 = find_head().id().to_string();\n    assert_ne!(&head1, &head2);\n    let extra = format!(\", rev = \\\"{}\\\"\", head2);\n    p.change_file(\"Cargo.toml\", &manifest(&extra));\n    verify(str![[r#\"\nthree\n\n\"#]]);\n\n    // Try with a tag.\n    git::tag(&repo, \"my-tag\");\n    p.change_file(\"Cargo.toml\", &manifest(\", tag = \\\"my-tag\\\"\"));\n    verify(str![[r#\"\nthree\n\n\"#]]);\n    amend_commit(\"tag-three\");\n    let head = t!(t!(repo.head()).peel(git2::ObjectType::Commit));\n    t!(repo.tag(\"my-tag\", &head, &t!(repo.signature()), \"move tag\", true));\n    verify(str![[r#\"\ntag-three\n\n\"#]]);\n\n    // Try with a branch.\n    let br = t!(repo.branch(\"awesome-stuff\", &find_head(), false));\n    t!(repo.checkout_tree(&t!(br.get().peel(git2::ObjectType::Tree)), None));\n    t!(repo.set_head(\"refs/heads/awesome-stuff\"));\n    git_project.change_file(\"src/lib.rs\", &main(\"awesome-three\"));\n    git::add(&repo);\n    git::commit(&repo);\n    p.change_file(\"Cargo.toml\", &manifest(\", branch = \\\"awesome-stuff\\\"\"));\n    verify(str![[r#\"\nawesome-three\n\n\"#]]);\n    amend_commit(\"awesome-four\");\n    verify(str![[r#\"\nawesome-four\n\n\"#]]);\n}\n\n#[cargo_test]\nfn corrupted_checkout() {\n    // Test what happens if the checkout is corrupted somehow.\n    _corrupted_checkout(false);\n}\n\n#[cargo_test]\nfn corrupted_checkout_with_cli() {\n    // Test what happens if the checkout is corrupted somehow with git cli.\n    _corrupted_checkout(true);\n}\n\nfn _corrupted_checkout(with_cli: bool) {\n    let (git_project, repository) = git::new_repo(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let project2 = git::new(\"dep2\", |project| {\n        project.no_manifest().file(\"README.md\", \"\")\n    });\n    let url = project2.root().to_url().to_string();\n    add_submodule(&repository, &url, Path::new(\"dep2\"));\n    git::commit(&repository);\n    drop(repository);\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    dep1 = {{ git = \"{}\" }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch\").run();\n\n    let mut dep1_co_paths = t!(glob::glob(\n        paths::home()\n            .join(\".cargo/git/checkouts/dep1-*/*\")\n            .to_str()\n            .unwrap()\n    ));\n    let dep1_co_path = dep1_co_paths.next().unwrap().unwrap();\n    let dep1_ok = dep1_co_path.join(\".cargo-ok\");\n    let dep1_manifest = dep1_co_path.join(\"Cargo.toml\");\n    let dep2_readme = dep1_co_path.join(\"dep2/README.md\");\n\n    // Deleting this file simulates an interrupted checkout.\n    t!(fs::remove_file(&dep1_ok));\n    t!(fs::remove_file(&dep1_manifest));\n    t!(fs::remove_file(&dep2_readme));\n\n    // This should refresh the checkout.\n    let mut e = p.cargo(\"fetch\");\n    if with_cli {\n        e.env(\"CARGO_NET_GIT_FETCH_WITH_CLI\", \"true\");\n    }\n    e.run();\n    assert!(dep1_ok.exists());\n    assert!(dep1_manifest.exists());\n    assert!(dep2_readme.exists());\n}\n\n#[cargo_test]\nfn cleans_temp_pack_files() {\n    // Checks that cargo removes temp files left by libgit2 when it is\n    // interrupted (see clean_repo_temp_files).\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\").run();\n    // Simulate what happens when libgit2 is interrupted while indexing a pack file.\n    let tmp_path = super::git_gc::find_index().join(\".git/objects/pack/pack_git2_91ab40da04fdc2e7\");\n    fs::write(&tmp_path, \"test\").unwrap();\n    let mut perms = fs::metadata(&tmp_path).unwrap().permissions();\n    perms.set_readonly(true);\n    fs::set_permissions(&tmp_path, perms).unwrap();\n\n    // Trigger an index update.\n    p.cargo(\"generate-lockfile\").run();\n    assert!(!tmp_path.exists());\n}\n\n#[cargo_test]\nfn different_user_relative_submodules() {\n    let user1_git_project = git::new(\"user1/dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let user2_git_project = git::new(\"user2/dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let _user2_git_project2 = git::new(\"user2/dep2\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let user2_repo = git2::Repository::open(&user2_git_project.root()).unwrap();\n    let url = \"../dep2\";\n    git::add_submodule(&user2_repo, url, Path::new(\"dep2\"));\n    git::commit(&user2_repo);\n\n    let user1_repo = git2::Repository::open(&user1_git_project.root()).unwrap();\n    let url = user2_git_project.url();\n    git::add_submodule(&user1_repo, url.as_str(), Path::new(\"user2/dep1\"));\n    git::commit(&user1_repo);\n\n    let project = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\" \n                    version = \"0.5.0\"\n                    edition = \"2015\"\n\n                    [dependencies.dep1]\n                    git = '{}'\n                \"#,\n                user1_git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"hello\"\"#, &[]))\n        .build();\n\n    project\n        .cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/user1/dep1`\n[UPDATING] git submodule `[ROOTURL]/user2/dep1`\n[UPDATING] git submodule `[ROOTURL]/user2/dep2`\n[LOCKING] 1 package to latest compatible version\n[COMPILING] dep1 v0.5.0 ([ROOTURL]/user1/dep1#[..])\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(project.bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn git_worktree_with_original_repo_renamed() {\n    let project = project().build();\n    let git_project = git::new(\"foo\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    license = \"MIR OR Apache-2.0\"\n                    description = \"A test!\"\n                    homepage = \"https://example.org\"\n                    documentation = \"\"\n                    repository = \"https://example.org\"\n                    readme = \"./README.md\"\n                \"#,\n            )\n            .file(\"src/lib.rs\", \"\")\n            .file(\"README.md\", \"\")\n    });\n\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    let repo_root = repo.workdir().unwrap().parent().unwrap();\n    let opts = git2::WorktreeAddOptions::new();\n    let _ = repo\n        .worktree(\"bar\", &repo_root.join(\"bar\"), Some(&opts))\n        .unwrap();\n\n    // Rename the original repository\n    let new = repo_root.join(\"foo2\");\n    fs::rename(&git_project.root(), &new).unwrap();\n\n    project\n        .cargo(\"package --list\")\n        .cwd(&new)\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nREADME.md\nsrc/lib.rs\n\n\"#]])\n        .run();\n\n    project\n        .cargo(\"check\")\n        .cwd(&new)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.5.0 ([ROOT]/foo2)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(public_network_test, requires = \"git\")]\nfn github_fastpath_error_message() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bitflags = { git = \"https://github.com/rust-lang/bitflags.git\", rev=\"11111b376b93484341c68fbca3ca110ae5cd2790\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .env(\"CARGO_NET_GIT_FETCH_WITH_CLI\", \"true\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `https://github.com/rust-lang/bitflags.git`\nfatal: remote [ERROR] upload-pack: not our ref 11111b376b93484341c68fbca3ca110ae5cd2790\n[WARNING] spurious network error (3 tries remaining): process didn't exit successfully: `git fetch --no-tags --force --update-head-ok [..]\nfatal: remote [ERROR] upload-pack: not our ref 11111b376b93484341c68fbca3ca110ae5cd2790\n[WARNING] spurious network error (2 tries remaining): process didn't exit successfully: `git fetch --no-tags --force --update-head-ok [..]\nfatal: remote [ERROR] upload-pack: not our ref 11111b376b93484341c68fbca3ca110ae5cd2790\n[WARNING] spurious network error (1 try remaining): process didn't exit successfully: `git fetch --no-tags --force --update-head-ok [..]\nfatal: remote [ERROR] upload-pack: not our ref 11111b376b93484341c68fbca3ca110ae5cd2790\n[ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bitflags`\n\nCaused by:\n  unable to update https://github.com/rust-lang/bitflags.git?rev=11111b376b93484341c68fbca3ca110ae5cd2790\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bitflags-[HASH]\n\nCaused by:\n  revision 11111b376b93484341c68fbca3ca110ae5cd2790 not found\n\nCaused by:\n  process didn't exit successfully: `git fetch --no-tags --force --update-head-ok [..]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(public_network_test)]\nfn git_fetch_libgit2_error_message() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bitflags = { git = \"https://github.com/rust-lang/bitflags.git\", rev=\"11111b376b93484341c68fbca3ca110ae5cd2790\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `https://github.com/rust-lang/bitflags.git`\n...\n[ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bitflags`\n\nCaused by:\n  unable to update https://github.com/rust-lang/bitflags.git?rev=11111b376b93484341c68fbca3ca110ae5cd2790\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bitflags-[HASH]\n\nCaused by:\n  revision 11111b376b93484341c68fbca3ca110ae5cd2790 not found\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_worktree_with_bare_original_repo() {\n    let project = project().build();\n    let git_project = git::new(\"foo\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n                    license = \"MIR OR Apache-2.0\"\n                    description = \"A test!\"\n                    homepage = \"https://example.org\"\n                    documentation = \"\"\n                    repository = \"https://example.org\"\n                    readme = \"./README.md\"\n                \"#,\n            )\n            .file(\"src/lib.rs\", \"\")\n            .file(\"README.md\", \"\")\n    });\n\n    // Create a \"bare\" Git repository.\n    // Keep the `.git` folder and delete the others.\n    let repo = {\n        let mut repo_builder = git2::build::RepoBuilder::new();\n        repo_builder\n            .bare(true)\n            .clone_local(git2::build::CloneLocal::Local)\n            .clone(\n                git_project.root().to_url().as_str(),\n                &paths::root().join(\"foo-bare\"),\n            )\n            .unwrap()\n    };\n    assert!(repo.is_bare());\n    let opts = git2::WorktreeAddOptions::new();\n    let wt = repo\n        .worktree(\"bar\", &paths::root().join(\"bar\"), Some(&opts))\n        .unwrap();\n\n    project\n        .cargo(\"package --list\")\n        .cwd(wt.path())\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nREADME.md\nsrc/lib.rs\n\n\"#]])\n        .run();\n\n    project\n        .cargo(\"check\")\n        .cwd(wt.path())\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.5.0 ([ROOT]/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[cfg(unix)]\nfn simple_with_fifo() {\n    let git_project = git::new(\"foo\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n            )\n            .file(\"src/main.rs\", \"fn main() {}\")\n    });\n\n    std::process::Command::new(\"mkfifo\")\n        .current_dir(git_project.root())\n        .arg(git_project.root().join(\"blocks-when-read\"))\n        .status()\n        .expect(\"a FIFO can be created\");\n\n    // Avoid actual blocking even in case of failure, assuming that what it lists here\n    // would also be read eventually.\n    git_project\n        .cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dep_with_cached_submodule() {\n    let project = project();\n    let git_project = git::new(\"dep1\", |project| {\n        project.file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n    });\n    let git_project2 = git::new(\"dep2\", |project| {\n        project.file(\"Cargo.toml\", &basic_manifest(\"dep2\", \"0.5.0\"))\n    });\n    let git_project3 = git::new(\"dep3\", |project| project.file(\"lib.rs\", \"pub fn dep() {}\"));\n\n    let url = git_project3.root().to_url().to_string();\n\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    git::add_submodule(&repo, &url, Path::new(\"src\"));\n    git::commit(&repo);\n\n    let repo2 = git2::Repository::open(&git_project2.root()).unwrap();\n    git::add_submodule(&repo2, &url, Path::new(\"src\"));\n    git::commit(&repo2);\n\n    let project = project\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.dep1]\n                    git = '{}'\n\n                    [dependencies.dep2]\n                    git = '{}'\n\n                \"#,\n                git_project.url(),\n                git_project2.url(),\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate dep1; pub fn foo() { dep1::dep() }\n                extern crate dep2; pub fn bar() { dep2::dep() }\n            \"#,\n        )\n        .build();\n\n    project\n        .cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[UPDATING] git submodule `[ROOTURL]/dep3`\n[UPDATING] git repository `[ROOTURL]/dep2`\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] dep[..] v0.5.0 ([ROOTURL]/dep[..]#[..])\n[CHECKING] dep[..] v0.5.0 ([ROOTURL]/dep[..]#[..])\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let db_paths = glob::glob(paths::cargo_home().join(\"git/db/dep3-*\").to_str().unwrap())\n        .unwrap()\n        .map(Result::unwrap)\n        .collect::<Vec<_>>();\n    assert_eq!(db_paths.len(), 1, \"submodule db created once\");\n}\n\n#[cargo_test]\nfn dep_with_scp_like_submodule_url() {\n    // Regression test for https://github.com/rust-lang/cargo/pull/16727\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n            .file(\"src/lib.rs\", \"pub fn dep() {}\")\n    });\n    let git_project2 = git::new(\"dep2\", |project| project.file(\"lib.rs\", \"pub fn dep2() {}\"));\n\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    let url = git_project2.root().to_url().to_string();\n    git::add_submodule(&repo, &url, Path::new(\"submod\"));\n    git::commit(&repo);\n\n    git_project.change_file(\n        \".gitmodules\",\n        \"[submodule \\\"submod\\\"]\\n\\tpath = submod\\n\\turl = git@github.com:foo/bar.git\",\n    );\n    git::add(&repo);\n    git::commit(&repo);\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n\n                    [dependencies.dep1]\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"extern crate dep1;\")\n        .build();\n\n    // With the SCP-like URL fix, Cargo preserves the original SCP-like URL\n    // for the actual fetch, while using the ssh:// form internally for caching.\n    // The fetch fails because the SSH server is not reachable, but the URL\n    // shown in messages is the original SCP-like form.\n    p.cargo(\"fetch\")\n        .env(\n            \"GIT_SSH_COMMAND\",\n            \"ssh -o StrictHostKeyChecking=no -o LogLevel=ERROR\",\n        )\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/dep1`\n[UPDATING] git submodule `git@github.com:foo/bar.git`\n[ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `dep1`\n\nCaused by:\n  unable to update [ROOTURL]/dep1\n\nCaused by:\n  failed to update submodule `submod`\n\nCaused by:\n  failed to fetch submodule `submod` from git@github.com:foo/bar.git\n...\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/git_auth.rs",
    "content": "//! Tests for git authentication.\n\nuse std::collections::HashSet;\nuse std::io::BufReader;\nuse std::io::prelude::*;\nuse std::net::{SocketAddr, TcpListener};\nuse std::sync::Arc;\nuse std::sync::atomic::{AtomicUsize, Ordering::SeqCst};\nuse std::thread::{self, JoinHandle};\n\nuse crate::prelude::*;\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::git::cargo_uses_gitoxide;\nuse cargo_test_support::paths;\nuse cargo_test_support::project;\n\nfn setup_failed_auth_test() -> (SocketAddr, JoinHandle<()>, Arc<AtomicUsize>) {\n    let server = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let addr = server.local_addr().unwrap();\n\n    fn headers(rdr: &mut dyn BufRead) -> HashSet<String> {\n        let valid = [\"GET\", \"Authorization\", \"Accept\"];\n        rdr.lines()\n            .map(|s| s.unwrap())\n            .take_while(|s| s.len() > 2)\n            .map(|s| s.trim().to_string())\n            .filter(|s| valid.iter().any(|prefix| s.starts_with(*prefix)))\n            .collect()\n    }\n\n    let connections = Arc::new(AtomicUsize::new(0));\n    let connections2 = connections.clone();\n    let t = thread::spawn(move || {\n        let mut conn = BufReader::new(server.accept().unwrap().0);\n        let req = headers(&mut conn);\n        connections2.fetch_add(1, SeqCst);\n        conn.get_mut()\n            .write_all(\n                b\"HTTP/1.1 401 Unauthorized\\r\\n\\\n              WWW-Authenticate: Basic realm=\\\"wheee\\\"\\r\\n\\\n              Content-Length: 0\\r\\n\\\n              \\r\\n\",\n            )\n            .unwrap();\n        assert_eq!(\n            req,\n            vec![\n                \"GET /foo/bar/info/refs?service=git-upload-pack HTTP/1.1\",\n                \"Accept: */*\",\n            ]\n            .into_iter()\n            .map(|s| s.to_string())\n            .collect()\n        );\n\n        let req = headers(&mut conn);\n        connections2.fetch_add(1, SeqCst);\n        conn.get_mut()\n            .write_all(\n                b\"HTTP/1.1 401 Unauthorized\\r\\n\\\n              WWW-Authenticate: Basic realm=\\\"wheee\\\"\\r\\n\\\n              \\r\\n\",\n            )\n            .unwrap();\n        assert_eq!(\n            req,\n            vec![\n                \"GET /foo/bar/info/refs?service=git-upload-pack HTTP/1.1\",\n                \"Authorization: Basic Zm9vOmJhcg==\",\n                \"Accept: */*\",\n            ]\n            .into_iter()\n            .map(|s| s.to_string())\n            .collect()\n        );\n    });\n\n    let script = project()\n        .at(\"script\")\n        .file(\"Cargo.toml\", &basic_manifest(\"script\", \"0.1.0\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    println!(\"username=foo\");\n                    println!(\"password=bar\");\n                }\n            \"#,\n        )\n        .build();\n\n    script.cargo(\"build -v\").run();\n    let script = script.bin(\"script\");\n\n    let config = paths::home().join(\".gitconfig\");\n    let mut config = git2::Config::open(&config).unwrap();\n    config\n        .set_str(\n            \"credential.helper\",\n            // This is a bash script so replace `\\` with `/` for Windows\n            &script.display().to_string().replace(\"\\\\\", \"/\"),\n        )\n        .unwrap();\n    (addr, t, connections)\n}\n\n// Tests that HTTP auth is offered from `credential.helper`.\n#[cargo_test]\nfn http_auth_offered() {\n    let (addr, t, connections) = setup_failed_auth_test();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies.bar]\n                    git = \"http://127.0.0.1:{}/foo/bar\"\n                \"#,\n                addr.port()\n            ),\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            \"[net]\n             retry = 0\n            \",\n        )\n        .build();\n\n    // This is a \"contains\" check because the last error differs by platform,\n    // may span multiple lines, and isn't relevant to this test.\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(&format!(\n            \"\\\n[UPDATING] git repository `http://{addr}/foo/bar`\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update http://{addr}/foo/bar\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH]\n\nCaused by:\n  failed to authenticate when downloading repository\n\n  * attempted to find username/password via `credential.helper`, but maybe the found credentials were incorrect\n\n  if the git CLI succeeds then `net.git-fetch-with-cli` may help here\n  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\n\nCaused by:\n{trailer}\n\",\n            trailer = if cargo_uses_gitoxide() {\n              format!(r#\"[CREDENTIAL]s provided for \"http://{addr}/foo/bar\" were not accepted by the remote\n\nCaused by:\n  Received HTTP status 401\"#)\n            } else {\n              \"  no authentication methods succeeded\".to_string()\n            }\n        ))\n        .run();\n    assert_eq!(connections.load(SeqCst), 2);\n    t.join().ok().unwrap();\n}\n\n// Boy, sure would be nice to have a TLS implementation in rust!\n#[cargo_test]\nfn https_something_happens() {\n    let server = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let addr = server.local_addr().unwrap();\n    let t = thread::spawn(move || {\n        let mut conn = server.accept().unwrap().0;\n        drop(conn.write(b\"1234\"));\n        drop(conn.shutdown(std::net::Shutdown::Write));\n        drop(conn.read(&mut [0; 16]));\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies.bar]\n                    git = \"https://127.0.0.1:{}/foo/bar\"\n                \"#,\n                addr.port()\n            ),\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            \"[net]\n             retry = 0\n            \",\n        )\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(&format!(\n            \"\\\n[UPDATING] git repository `https://{addr}/foo/bar`\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update https://{addr}/foo/bar\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH]\n\nCaused by:\n{errmsg}\n\",\n            errmsg = if cargo_uses_gitoxide() {\n                r\"  network failure seems to have happened\n  if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\n  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\n\nCaused by:\n  An IO error occurred when talking to the server\n\nCaused by:\n  [35] SSL connect error ([..])\"\n            } else if cfg!(windows) {\n                \"[..]failed to send request: [..]\\n...\"\n            } else if cfg!(target_os = \"macos\") {\n                // macOS is difficult to tests as some builds may use Security.framework,\n                // while others may use OpenSSL. In that case, let's just not verify the error\n                // message here.\n                \"...\"\n            } else {\n                \"[..]SSL [ERROR][..]\"\n            }\n        ))\n        .run();\n\n    t.join().ok().unwrap();\n}\n\n// It would sure be nice to have an SSH implementation in Rust!\n#[cargo_test]\nfn ssh_something_happens() {\n    let server = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let addr = server.local_addr().unwrap();\n    let t = thread::spawn(move || {\n        drop(server.accept().unwrap());\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies.bar]\n                    git = \"ssh://127.0.0.1:{}/foo/bar\"\n                \"#,\n                addr.port()\n            ),\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    let expected = if cargo_uses_gitoxide() {\n        // Due to the usage of `ssh` and `ssh.exe` respectively, the messages change.\n        // This will be adjusted to use `ssh2` to get rid of this dependency and have uniform messaging.\n        let message = if cfg!(windows) {\n            // The order of multiple possible messages isn't deterministic within `ssh`, and `gitoxide` detects both\n            // but gets to report only the first. Thus this test can flip-flop from one version of the error to the other\n            // and we can't test for that.\n            // We'd want to test for:\n            // \"[..]ssh: connect to host 127.0.0.1 [..]\"\n            //   ssh: connect to host example.org port 22: No route to host\n            // \"[..]banner exchange: Connection to 127.0.0.1 [..]\"\n            //   banner exchange: Connection to 127.0.0.1 port 62250: Software caused connection abort\n            // But since there is no common meaningful sequence or word, we can only match a small telling sequence of characters.\n            \"[..]onnect[..]\"\n        } else {\n            \"[..]Connection [..] by [..]\"\n        };\n        format!(\n            \"\\\n[UPDATING] git repository `ssh://{addr}/foo/bar`\n...\n{message}\n...\n\"\n        )\n    } else {\n        format!(\n            \"\\\n[UPDATING] git repository `ssh://{addr}/foo/bar`\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update ssh://{addr}/foo/bar\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH]\n\nCaused by:\n  network failure seems to have happened\n  if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\n  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\n\nCaused by:\n  failed to start SSH session: Failed getting banner; class=Ssh (23)\n\"\n        )\n    };\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(expected)\n        .run();\n    t.join().ok().unwrap();\n}\n\n#[cargo_test]\nfn net_err_suggests_fetch_with_cli() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = { git = \"ssh://needs-proxy.invalid/git\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(format!(\n            \"\\\n[UPDATING] git repository `ssh://needs-proxy.invalid/git`\n[WARNING] spurious network error (3 tries remaining): [..] resolve [..] needs-proxy.invalid: [..] known[..]\n[WARNING] spurious network error (2 tries remaining): [..] resolve [..] needs-proxy.invalid: [..] known[..]\n[WARNING] spurious network error (1 try remaining): [..] resolve [..] needs-proxy.invalid: [..] known[..]\n[ERROR] failed to get `foo` as a dependency of package `foo v0.0.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `foo`\n\nCaused by:\n  unable to update ssh://needs-proxy.invalid/git\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/git-[HASH]\n\nCaused by:\n  network failure seems to have happened\n  if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\n  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\n\nCaused by:\n{trailer}\n\",\n            trailer = if cargo_uses_gitoxide() {\n                r\"  An IO error occurred when talking to the server\n\nCaused by:\n  ssh: Could not resolve hostname needs-proxy.invalid[..]\"\n            } else {\n                \"  failed to resolve address for needs-proxy.invalid: [..] known[..]; class=Net (12)\"\n            }\n        ))\n        .run();\n\n    p.change_file(\n        \".cargo/config.toml\",\n        \"\n            [net]\n            git-fetch-with-cli = true\n            \",\n    );\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_contains(\"[..]unable to update[..]\")\n        .with_stderr_does_not_contain(\"[..]try enabling `git-fetch-with-cli`[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn instead_of_url_printed() {\n    let (addr, t, _connections) = setup_failed_auth_test();\n    let config = paths::home().join(\".gitconfig\");\n    let mut config = git2::Config::open(&config).unwrap();\n    config\n        .set_str(\n            &format!(\"url.http://{}/.insteadOf\", addr),\n            \"https://foo.bar/\",\n        )\n        .unwrap();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                git = \"https://foo.bar/foo/bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(&format!(\n            \"\\\n[UPDATING] git repository `https://foo.bar/foo/bar`\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update https://foo.bar/foo/bar\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH]\n\nCaused by:\n  failed to authenticate when downloading repository: http://{addr}/foo/bar\n\n  * attempted to find username/password via `credential.helper`, but maybe the found credentials were incorrect\n\n  if the git CLI succeeds then `net.git-fetch-with-cli` may help here\n  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\n\nCaused by:\n...\n\"\n        ))\n        .run();\n\n    t.join().ok().unwrap();\n}\n"
  },
  {
    "path": "tests/testsuite/git_gc.rs",
    "content": "//! Tests for git garbage collection.\n\nuse std::env;\nuse std::ffi::OsStr;\nuse std::path::PathBuf;\n\nuse crate::prelude::*;\nuse cargo_test_support::git;\nuse cargo_test_support::git::cargo_uses_gitoxide;\nuse cargo_test_support::paths;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse url::Url;\n\npub fn find_index() -> PathBuf {\n    let dir = paths::home().join(\".cargo/registry/index\");\n    dir.read_dir().unwrap().next().unwrap().unwrap().path()\n}\n\nfn run_test(path_env: Option<&OsStr>) {\n    const N: usize = 50;\n\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    foo.cargo(\"check\").run();\n\n    let index = find_index();\n    let path = paths::home().join(\"tmp\");\n    let url = Url::from_file_path(&path).unwrap().to_string();\n    let repo = git2::Repository::init(&path).unwrap();\n    let index = git2::Repository::open(&index).unwrap();\n    let mut cfg = repo.config().unwrap();\n    cfg.set_str(\"user.email\", \"foo@bar.com\").unwrap();\n    cfg.set_str(\"user.name\", \"Foo Bar\").unwrap();\n    let mut cfg = index.config().unwrap();\n    cfg.set_str(\"user.email\", \"foo@bar.com\").unwrap();\n    cfg.set_str(\"user.name\", \"Foo Bar\").unwrap();\n\n    for _ in 0..N {\n        git::commit(&repo);\n        index\n            .remote_anonymous(&url)\n            .unwrap()\n            .fetch(&[\"refs/heads/master:refs/remotes/foo/master\"], None, None)\n            .unwrap();\n    }\n    drop((repo, index));\n    Package::new(\"bar\", \"0.1.1\").publish();\n\n    // Each fetch above creates a new pack file in the index. Count them before\n    // running cargo update so we can verify gc actually consolidates them.\n    let before = find_index()\n        .join(\".git/objects/pack\")\n        .read_dir()\n        .unwrap()\n        .count();\n    assert!(before > N);\n\n    // Set __CARGO_PACKFILE_LIMIT=10 so gc.autoPackLimit=10 is passed to\n    // `git gc --auto`. This forces consolidation at a low threshold rather\n    // than relying on git's default (which is much higher).\n    let mut cmd = foo.cargo(\"update\");\n    cmd.env(\"__CARGO_PACKFILE_LIMIT\", \"10\");\n    if let Some(path) = path_env {\n        cmd.env(\"PATH\", path);\n    }\n    cmd.env(\"CARGO_LOG\", \"trace\");\n    cmd.run();\n\n    let after = find_index()\n        .join(\".git/objects/pack\")\n        .read_dir()\n        .unwrap()\n        .count();\n    assert!(\n        after < before,\n        \"packfiles before: {}\\n\\\n         packfiles after:  {}\",\n        before,\n        after\n    );\n}\n\n#[cargo_test(requires = \"git\")]\nfn use_git_gc() {\n    run_test(None);\n}\n\n#[cargo_test]\nfn avoid_using_git() {\n    if cargo_uses_gitoxide() {\n        // file protocol without git binary is currently not possible - needs built-in upload-pack.\n        // See https://github.com/Byron/gitoxide/issues/734 (support for the file protocol) progress updates.\n        return;\n    }\n    let path = env::var_os(\"PATH\").unwrap_or_default();\n    let mut paths = env::split_paths(&path).collect::<Vec<_>>();\n    let idx = paths\n        .iter()\n        .position(|p| p.join(\"git\").exists() || p.join(\"git.exe\").exists());\n    match idx {\n        Some(i) => {\n            paths.remove(i);\n        }\n        None => return,\n    }\n    run_test(Some(&env::join_paths(&paths).unwrap()));\n}\n"
  },
  {
    "path": "tests/testsuite/git_shallow.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{basic_manifest, git, paths, project};\n\nuse crate::git_gc::find_index;\n\n#[derive(Copy, Clone, Debug)]\nenum Backend {\n    Git2,\n    Gitoxide,\n    GitCli,\n}\n\nimpl Backend {\n    fn to_arg(&self) -> &'static str {\n        match self {\n            Backend::Git2 => \"\",\n            Backend::Gitoxide => \"-Zgitoxide=fetch\",\n            Backend::GitCli => \"--config=net.git-fetch-with-cli=true\",\n        }\n    }\n\n    fn to_trace_log(&self) -> &str {\n        match self {\n            Backend::Git2 => r#\"[..]git-fetch: backend=\"libgit2\"[..]\"#,\n            Backend::Gitoxide => r#\"[..]git-fetch: backend=\"gitoxide\"[..]\"#,\n            Backend::GitCli => r#\"[..]git-fetch: backend=\"git-cli\"[..]\"#,\n        }\n    }\n}\n\n#[derive(Copy, Clone, Debug)]\nenum RepoMode {\n    Shallow,\n    Complete,\n}\n\nimpl RepoMode {\n    fn to_deps_arg(&self) -> &'static str {\n        match self {\n            RepoMode::Complete => \"\",\n            RepoMode::Shallow => \"-Zgit=shallow-deps\",\n        }\n    }\n\n    fn to_index_arg(&self) -> &'static str {\n        match self {\n            RepoMode::Complete => \"\",\n            RepoMode::Shallow => \"-Zgit=shallow-index\",\n        }\n    }\n\n    #[track_caller]\n    fn assert_index(self, repo: &gix::Repository, shallow_depth: usize, complete_depth: usize) {\n        let commit_count = repo\n            .rev_parse_single(\"origin/HEAD\")\n            .unwrap()\n            .ancestors()\n            .all()\n            .unwrap()\n            .count();\n        match self {\n            RepoMode::Shallow => {\n                assert_eq!(commit_count, shallow_depth,);\n                assert!(repo.is_shallow());\n            }\n            RepoMode::Complete => {\n                assert_eq!(commit_count, complete_depth,);\n                assert!(!repo.is_shallow());\n            }\n        }\n    }\n}\n\n#[cargo_test]\nfn gitoxide_fetch_shallow_dep_two_revs() {\n    fetch_dep_two_revs(Backend::Gitoxide)\n}\n\n#[cargo_test]\nfn git_cli_fetch_shallow_dep_two_revs() {\n    fetch_dep_two_revs(Backend::GitCli)\n}\n\nfn fetch_dep_two_revs(backend: Backend) {\n    let bar = git::new(\"meta-dep\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.0\"))\n            .file(\"src/lib.rs\", \"pub fn bar() -> i32 { 1 }\")\n    });\n\n    let repo = git2::Repository::open(&bar.root()).unwrap();\n    let rev1 = repo.revparse_single(\"HEAD\").unwrap().id();\n\n    // Commit the changes and make sure we trigger a recompile\n    bar.change_file(\"src/lib.rs\", \"pub fn bar() -> i32 { 2 }\");\n    git::add(&repo);\n    let rev2 = git::commit(&repo);\n\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.0\"\n                    authors = []\n\n                    [dependencies.bar]\n                    git = '{}'\n                    rev = \"{}\"\n\n                    [dependencies.baz]\n                    path = \"../baz\"\n                \"#,\n                bar.url(),\n                rev1\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                extern crate bar;\n                extern crate baz;\n\n                fn main() {\n                    assert_eq!(bar::bar(), 1);\n                    assert_eq!(baz::baz(), 2);\n                }\n            \"#,\n        )\n        .build();\n\n    let _baz = project()\n        .at(\"baz\")\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"baz\"\n                    version = \"0.0.0\"\n                    authors = []\n\n                    [dependencies.bar]\n                    git = '{}'\n                    rev = \"{}\"\n                \"#,\n                bar.url(),\n                rev2\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate bar;\n                pub fn baz() -> i32 { bar::bar() }\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"check -v\")\n        .arg_line(backend.to_arg())\n        .arg_line(RepoMode::Shallow.to_deps_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\") // respect `backend`\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-deps\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n}\n\n#[cargo_test]\nfn gitoxide_fetch_shallow_dep_branch_and_rev() -> anyhow::Result<()> {\n    fetch_shallow_dep_branch_and_rev(Backend::Gitoxide)\n}\n\n#[cargo_test]\nfn git_cli_fetch_shallow_dep_branch_and_rev() -> anyhow::Result<()> {\n    fetch_shallow_dep_branch_and_rev(Backend::GitCli)\n}\n\nfn fetch_shallow_dep_branch_and_rev(backend: Backend) -> anyhow::Result<()> {\n    let (bar, bar_repo) = git::new_repo(\"bar\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    // this commit would not be available in a shallow fetch.\n    let first_commit_pre_change = bar_repo.head().unwrap().target().unwrap();\n\n    bar.change_file(\"src/lib.rs\", \"// change\");\n    git::add(&bar_repo);\n    git::commit(&bar_repo);\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    bar-renamed = {{ package = \"bar\", git = \"{}\", rev = \"{}\" }}\n                    bar = {{ git = \"{}\", branch = \"master\" }}\n                \"#,\n                bar.url(),\n                first_commit_pre_change,\n                bar.url(),\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .arg_line(backend.to_arg())\n        .arg_line(RepoMode::Shallow.to_deps_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-deps\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n\n    let db_paths = glob::glob(paths::home().join(\".cargo/git/db/bar-*\").to_str().unwrap())?\n        .map(Result::unwrap)\n        .collect::<Vec<_>>();\n    assert_eq!(\n        db_paths.len(),\n        1,\n        \"only one db checkout source is used per dependency\"\n    );\n    let db_clone = gix::open_opts(&db_paths[0], gix::open::Options::isolated())?;\n    assert!(\n        db_clone.is_shallow(),\n        \"the repo is shallow while having all data it needs\"\n    );\n\n    Ok(())\n}\n\n#[cargo_test]\nfn gitoxide_fetch_shallow_dep_branch_to_rev() -> anyhow::Result<()> {\n    fetch_shallow_dep_branch_to_rev(Backend::Gitoxide)\n}\n\n#[cargo_test]\nfn git_cli_fetch_shallow_dep_branch_to_rev() -> anyhow::Result<()> {\n    fetch_shallow_dep_branch_to_rev(Backend::GitCli)\n}\n\nfn fetch_shallow_dep_branch_to_rev(backend: Backend) -> anyhow::Result<()> {\n    // db exists from previous build, then dependency changes to refer to revision that isn't\n    // available in the shallow fetch.\n\n    let (bar, bar_repo) = git::new_repo(\"bar\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    // this commit would not be available in a shallow fetch.\n    let first_commit_pre_change = bar_repo.head().unwrap().target().unwrap();\n\n    bar.change_file(\"src/lib.rs\", \"// change\");\n    git::add(&bar_repo);\n    git::commit(&bar_repo);\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    bar = {{ git = \"{}\", branch = \"master\" }}\n                \"#,\n                bar.url(),\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .arg_line(backend.to_arg())\n        .arg_line(RepoMode::Shallow.to_deps_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-deps\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n\n    let db_clone = gix::open_opts(\n        find_bar_db(RepoMode::Shallow),\n        gix::open::Options::isolated(),\n    )?;\n    assert!(db_clone.is_shallow());\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    bar = {{ git = \"{}\", rev = \"{}\" }}\n                \"#,\n                bar.url(),\n                first_commit_pre_change\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .arg_line(backend.to_arg())\n        .arg_line(RepoMode::Shallow.to_deps_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-deps\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n\n    assert!(\n        db_clone.is_shallow(),\n        \"we maintain shallowness and never unshallow\"\n    );\n\n    Ok(())\n}\n\n#[cargo_test]\nfn gitoxide_fetch_shallow_index_then_git2_fetch_complete() -> anyhow::Result<()> {\n    fetch_index_then_fetch(\n        Backend::Gitoxide,\n        RepoMode::Shallow,\n        Backend::Git2,\n        RepoMode::Complete,\n    )\n}\n\n#[cargo_test]\nfn gitoxide_fetch_shallow_index_then_git_cli_fetch_shallow() -> anyhow::Result<()> {\n    fetch_index_then_fetch(\n        Backend::Gitoxide,\n        RepoMode::Shallow,\n        Backend::GitCli,\n        RepoMode::Shallow,\n    )\n}\n\n#[cargo_test]\nfn gitoxide_fetch_complete_index_then_git_cli_fetch_shallow() -> anyhow::Result<()> {\n    fetch_index_then_fetch(\n        Backend::Gitoxide,\n        RepoMode::Complete,\n        Backend::GitCli,\n        RepoMode::Shallow,\n    )\n}\n\n#[cargo_test]\nfn gitoxide_fetch_shallow_index_then_git_cli_fetch_complete() -> anyhow::Result<()> {\n    fetch_index_then_fetch(\n        Backend::Gitoxide,\n        RepoMode::Shallow,\n        Backend::GitCli,\n        RepoMode::Complete,\n    )\n}\n\n#[cargo_test]\nfn git_cli_fetch_shallow_index_then_git2_fetch_complete() -> anyhow::Result<()> {\n    fetch_index_then_fetch(\n        Backend::GitCli,\n        RepoMode::Shallow,\n        Backend::Git2,\n        RepoMode::Complete,\n    )\n}\n\n#[cargo_test]\nfn git_cli_fetch_shallow_index_then_gitoxide_fetch_shallow() -> anyhow::Result<()> {\n    fetch_index_then_fetch(\n        Backend::GitCli,\n        RepoMode::Shallow,\n        Backend::Gitoxide,\n        RepoMode::Shallow,\n    )\n}\n\n#[cargo_test]\nfn git_cli_fetch_shallow_complete_then_gitoxide_fetch_complete() -> anyhow::Result<()> {\n    fetch_index_then_fetch(\n        Backend::GitCli,\n        RepoMode::Complete,\n        Backend::Gitoxide,\n        RepoMode::Shallow,\n    )\n}\n\n#[cargo_test]\nfn git_cli_fetch_shallow_index_then_gitoxide_fetch_complete() -> anyhow::Result<()> {\n    fetch_index_then_fetch(\n        Backend::GitCli,\n        RepoMode::Shallow,\n        Backend::Gitoxide,\n        RepoMode::Complete,\n    )\n}\n\nfn fetch_index_then_fetch(\n    backend_1st: Backend,\n    mode_1st: RepoMode,\n    backend_2nd: Backend,\n    mode_2nd: RepoMode,\n) -> anyhow::Result<()> {\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .arg_line(backend_1st.to_arg())\n        .arg_line(mode_1st.to_index_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-index\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend_1st.to_trace_log())\n        .run();\n\n    let repo = gix::open_opts(find_remote_index(mode_1st), gix::open::Options::isolated())?;\n    let complete_depth = 2; // initial commit, bar@1.0.0\n    mode_1st.assert_index(&repo, 1, complete_depth);\n\n    Package::new(\"bar\", \"1.1.0\").publish();\n    p.cargo(\"update\")\n        .arg_line(backend_2nd.to_arg())\n        .arg_line(mode_2nd.to_index_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-index\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend_2nd.to_trace_log())\n        .run();\n\n    let repo = gix::open_opts(find_remote_index(mode_2nd), gix::open::Options::isolated())?;\n    let complete_depth = 3; // initial commit, bar@1.0.0, and bar@1.1.0\n    mode_2nd.assert_index(&repo, 1, complete_depth);\n\n    Ok(())\n}\n\n#[cargo_test]\nfn gitoxide_fetch_shallow_dep_then_git2_fetch_complete() -> anyhow::Result<()> {\n    fetch_shallow_dep_then_fetch_complete(Backend::Gitoxide, Backend::Git2)\n}\n\n#[cargo_test]\nfn git_cli_fetch_shallow_dep_then_git2_fetch_complete() -> anyhow::Result<()> {\n    fetch_shallow_dep_then_fetch_complete(Backend::GitCli, Backend::Git2)\n}\n\n#[cargo_test]\nfn gitoxide_fetch_shallow_dep_then_gitoxide_fetch_complete() -> anyhow::Result<()> {\n    fetch_shallow_dep_then_fetch_complete(Backend::Gitoxide, Backend::Gitoxide)\n}\n\n#[cargo_test]\nfn git_cli_fetch_shallow_dep_then_gitoxide_fetch_complete() -> anyhow::Result<()> {\n    fetch_shallow_dep_then_fetch_complete(Backend::GitCli, Backend::Gitoxide)\n}\n\n#[cargo_test]\nfn gitoxide_fetch_shallow_dep_then_git_cli_fetch_complete() -> anyhow::Result<()> {\n    fetch_shallow_dep_then_fetch_complete(Backend::Gitoxide, Backend::GitCli)\n}\n\n#[cargo_test]\nfn git_cli_fetch_shallow_dep_then_git_cli_fetch_complete() -> anyhow::Result<()> {\n    fetch_shallow_dep_then_fetch_complete(Backend::GitCli, Backend::GitCli)\n}\n\nfn fetch_shallow_dep_then_fetch_complete(\n    backend_1st: Backend,\n    backend_2nd: Backend,\n) -> anyhow::Result<()> {\n    // Example where an old lockfile with an explicit branch=\"master\" in Cargo.toml.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let (bar, bar_repo) = git::new_repo(\"bar\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    bar.change_file(\"src/lib.rs\", \"// change\");\n    git::add(&bar_repo);\n    git::commit(&bar_repo);\n\n    {\n        let mut walk = bar_repo.revwalk()?;\n        walk.push_head()?;\n        assert_eq!(\n            walk.count(),\n            2,\n            \"original repo has initial commit and change commit\"\n        );\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    bar = {{ version = \"1.0\", git = \"{}\", branch = \"master\" }}\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"update\")\n        .arg_line(backend_1st.to_arg())\n        .arg_line(RepoMode::Shallow.to_deps_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-deps\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend_1st.to_trace_log())\n        .run();\n\n    let db_clone = gix::open_opts(\n        find_bar_db(RepoMode::Shallow),\n        gix::open::Options::isolated(),\n    )?;\n    assert!(db_clone.is_shallow());\n    assert_eq!(\n        db_clone\n            .rev_parse_single(\"origin/master\")?\n            .ancestors()\n            .all()?\n            .count(),\n        1,\n        \"db fetch are shallow and have a shortened history\"\n    );\n\n    let dep_checkout = gix::open_opts(\n        find_lexicographically_first_bar_checkout(),\n        gix::open::Options::isolated(),\n    )?;\n    assert!(dep_checkout.is_shallow());\n    assert_eq!(\n        dep_checkout.head_id()?.ancestors().all()?.count(),\n        1,\n        \"db checkouts are hard-linked fetches with the shallow file copied separately.\"\n    );\n\n    bar.change_file(\"src/lib.rs\", \"// another change\");\n    git::add(&bar_repo);\n    git::commit(&bar_repo);\n    {\n        let mut walk = bar_repo.revwalk()?;\n        walk.push_head()?;\n        assert_eq!(\n            walk.count(),\n            3,\n            \"original repo has initial commit and change commit, and another change\"\n        );\n    }\n\n    p.cargo(\"update\")\n        .arg_line(backend_2nd.to_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend_2nd.to_trace_log())\n        .run();\n\n    let db_clone = gix::open_opts(\n        find_bar_db(RepoMode::Complete),\n        gix::open::Options::isolated(),\n    )?;\n    assert_eq!(\n        db_clone\n            .rev_parse_single(\"origin/master\")?\n            .ancestors()\n            .all()?\n            .count(),\n        3,\n        \"the db clone was re-initialized and has all commits\"\n    );\n    assert!(\n        !db_clone.is_shallow(),\n        \"shallow-ness was removed as git2 does not support it\"\n    );\n    assert_eq!(\n        dep_checkout.head_id()?.ancestors().all()?.count(),\n        1,\n        \"the original dep checkout didn't change - there is a new one for each update we get locally\"\n    );\n\n    let max_history_depth = glob::glob(\n        paths::home()\n            .join(\".cargo/git/checkouts/bar-*/*/.git\")\n            .to_str()\n            .unwrap(),\n    )?\n        .map(|path| -> anyhow::Result<usize> {\n            let dep_checkout = gix::open_opts(path?, gix::open::Options::isolated())?;\n            let depth = dep_checkout.head_id()?.ancestors().all()?.count();\n            assert_eq!(dep_checkout.is_shallow(), depth == 1, \"the first checkout is done with gitoxide and shallow, the second one is git2 non-shallow\");\n            Ok(depth)\n        })\n        .map(Result::unwrap)\n        .max()\n        .expect(\"two checkout repos\");\n\n    assert_eq!(\n        max_history_depth, 3,\n        \"the new checkout sees all commits of the non-shallow DB repository\"\n    );\n\n    Ok(())\n}\n\n#[cargo_test]\nfn gitoxide_fetch_shallow_index_then_preserve_shallow() -> anyhow::Result<()> {\n    fetch_shallow_index_then_preserve_shallow(Backend::Gitoxide)\n}\n\n#[cargo_test]\nfn git_cli_fetch_shallow_index_then_preserve_shallow() -> anyhow::Result<()> {\n    fetch_shallow_index_then_preserve_shallow(Backend::GitCli)\n}\n\nfn fetch_shallow_index_then_preserve_shallow(backend: Backend) -> anyhow::Result<()> {\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .arg_line(backend.to_arg())\n        .arg(RepoMode::Shallow.to_index_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-index\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n\n    let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?;\n    assert_eq!(\n        repo.rev_parse_single(\"origin/HEAD\")?\n            .ancestors()\n            .all()?\n            .count(),\n        1,\n        \"shallow fetches always start at depth of 1 to minimize download size\"\n    );\n    assert!(repo.is_shallow());\n\n    Package::new(\"bar\", \"1.1.0\").publish();\n    p.cargo(\"update\")\n        .arg_line(backend.to_arg())\n        .arg(RepoMode::Shallow.to_index_arg()) // NOTE: the flag needs to be consistent or else a different index is created\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-index\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n\n    assert_eq!(\n        repo.rev_parse_single(\"origin/HEAD\")?\n            .ancestors()\n            .all()?\n            .count(),\n        1,\n        \"subsequent shallow fetches wont' fetch what's inbetween, only the single commit that we need while leveraging existing commits\"\n    );\n    assert!(repo.is_shallow());\n\n    Package::new(\"bar\", \"1.2.0\").publish();\n    Package::new(\"bar\", \"1.3.0\").publish();\n    p.cargo(\"update\")\n        .arg_line(backend.to_arg())\n        .arg(RepoMode::Shallow.to_index_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-index\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n\n    assert_eq!(\n        repo.rev_parse_single(\"origin/HEAD\")?\n            .ancestors()\n            .all()?\n            .count(),\n        1,\n        \"shallow boundaries are moved with each fetch to maintain only a single commit of history\"\n    );\n    assert!(repo.is_shallow());\n\n    Ok(())\n}\n\n/// If there is shallow *and* non-shallow fetches, non-shallow will naturally be returned due to sort order.\n#[cargo_test]\nfn gitoxide_fetch_complete_index_then_shallow() -> anyhow::Result<()> {\n    fetch_complete_index_then_shallow(Backend::Gitoxide)\n}\n\n#[cargo_test]\nfn git_cli_fetch_complete_index_then_shallow() -> anyhow::Result<()> {\n    fetch_complete_index_then_shallow(Backend::GitCli)\n}\n\nfn fetch_complete_index_then_shallow(backend: Backend) -> anyhow::Result<()> {\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .arg_line(backend.to_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n\n    let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?;\n    assert_eq!(\n        repo.rev_parse_single(\"origin/HEAD\")?\n            .ancestors()\n            .all()?\n            .count(),\n        2,\n        \"initial commit and the first crate\"\n    );\n    assert!(!repo.is_shallow());\n\n    Package::new(\"bar\", \"1.1.0\").publish();\n    p.cargo(\"update\")\n        .arg_line(backend.to_arg())\n        .arg(RepoMode::Shallow.to_index_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-index\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n\n    let shallow_repo = gix::open_opts(\n        find_remote_index(RepoMode::Shallow),\n        gix::open::Options::isolated(),\n    )?;\n    assert_eq!(\n        shallow_repo\n            .rev_parse_single(\"origin/HEAD\")?\n            .ancestors()\n            .all()?\n            .count(),\n        1,\n        \"the follow up fetch an entirely new index which is now shallow and which is in its own location\"\n    );\n    assert!(shallow_repo.is_shallow());\n\n    Package::new(\"bar\", \"1.2.0\").publish();\n    Package::new(\"bar\", \"1.3.0\").publish();\n    p.cargo(\"update\")\n        .arg_line(backend.to_arg())\n        .arg(RepoMode::Shallow.to_index_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-index\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n\n    assert_eq!(\n        shallow_repo\n            .rev_parse_single(\"origin/HEAD\")?\n            .ancestors()\n            .all()?\n            .count(),\n        1,\n        \"subsequent shallow fetches wont' fetch what's inbetween, only the single commit that we need while leveraging existing commits\"\n    );\n    assert!(shallow_repo.is_shallow());\n\n    p.cargo(\"update\")\n        .arg_line(backend.to_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n\n    assert_eq!(\n        repo.rev_parse_single(\"origin/HEAD\")?\n            .ancestors()\n            .all()?\n            .count(),\n        5,\n        \"we can separately fetch the non-shallow index as well and it sees all commits\"\n    );\n\n    Ok(())\n}\n\n#[cargo_test]\nfn gitoxide_fetch_shallow_index_then_abort_and_update() -> anyhow::Result<()> {\n    fetch_shallow_index_then_abort_and_update(Backend::Gitoxide)\n}\n\n// Git CLI cannot recover from stale lock files like Gitoxide can.\n// This test simulates an aborted fetch by creating a stale shallow.lock file.\n// Gitoxide can detect and recover from this, but Git CLI will fail with:\n//\n// ```text\n// fatal: Unable to create \\'/path/to/.git/shallow.lock\\': File exists.\n//\n// Another git process seems to be running in this repository, e.g.\n// an editor opened by \\'git commit\\'. Please make sure all processes\n// are terminated then try again. If it still fails, a git process\n// may have crashed in this repository earlier:\n// remove the file manually to continue.\n// ```\n#[cargo_test]\n#[ignore = \"Git CLI cannot recover from stale lock files\"]\nfn git_cli_fetch_shallow_index_then_abort_and_update() -> anyhow::Result<()> {\n    fetch_shallow_index_then_abort_and_update(Backend::GitCli)\n}\n\nfn fetch_shallow_index_then_abort_and_update(backend: Backend) -> anyhow::Result<()> {\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .arg_line(backend.to_arg())\n        .arg(RepoMode::Shallow.to_index_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-index\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n\n    let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?;\n    assert_eq!(\n        repo.rev_parse_single(\"origin/HEAD\")?\n            .ancestors()\n            .all()?\n            .count(),\n        1,\n        \"shallow fetches always start at depth of 1 to minimize download size\"\n    );\n    assert!(repo.is_shallow());\n    let shallow_lock = repo.shallow_file().with_extension(\"lock\");\n    // adding a lock file and deleting the original simulates a left-over fetch that was aborted, leaving a lock file\n    // in place without ever having moved it to the right location.\n    std::fs::write(&shallow_lock, &[])?;\n    std::fs::remove_file(repo.shallow_file())?;\n\n    Package::new(\"bar\", \"1.1.0\").publish();\n    p.cargo(\"update\")\n        .arg_line(backend.to_arg())\n        .arg(RepoMode::Shallow.to_index_arg())\n        .env(\"__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2\", \"0\")\n        .masquerade_as_nightly_cargo(&[\"gitoxide=fetch\", \"git=shallow-index\"])\n        .env(\"CARGO_LOG\", \"git-fetch=debug\")\n        .with_stderr_contains(backend.to_trace_log())\n        .run();\n\n    assert!(!shallow_lock.is_file(), \"the repository was re-initialized\");\n    assert!(repo.is_shallow());\n    assert_eq!(\n        repo.rev_parse_single(\"origin/HEAD\")?\n            .ancestors()\n            .all()?\n            .count(),\n        1,\n        \"it's a fresh shallow fetch - otherwise it would have 2 commits if the previous shallow fetch would still be present\"\n    );\n\n    Ok(())\n}\n\nfn find_lexicographically_first_bar_checkout() -> std::path::PathBuf {\n    glob::glob(\n        paths::home()\n            .join(\".cargo/git/checkouts/bar-*/*/.git\")\n            .to_str()\n            .unwrap(),\n    )\n    .unwrap()\n    .next()\n    .unwrap()\n    .unwrap()\n    .to_owned()\n}\n\nfn find_remote_index(mode: RepoMode) -> std::path::PathBuf {\n    glob::glob(\n        paths::home()\n            .join(\".cargo/registry/index/*\")\n            .to_str()\n            .unwrap(),\n    )\n    .unwrap()\n    .map(Result::unwrap)\n    .filter(|p| p.to_string_lossy().ends_with(\"-shallow\") == matches!(mode, RepoMode::Shallow))\n    .next()\n    .unwrap()\n}\n\n/// Find a checkout directory for bar, `shallow` or not.\nfn find_bar_db(mode: RepoMode) -> std::path::PathBuf {\n    glob::glob(paths::home().join(\".cargo/git/db/bar-*\").to_str().unwrap())\n        .unwrap()\n        .map(Result::unwrap)\n        .filter(|p| p.to_string_lossy().ends_with(\"-shallow\") == matches!(mode, RepoMode::Shallow))\n        .next()\n        .unwrap()\n        .to_owned()\n}\n"
  },
  {
    "path": "tests/testsuite/glob_targets.rs",
    "content": "//! Tests for target filter flags with glob patterns.\n\nuse crate::prelude::*;\nuse cargo_test_support::{Project, project, str};\n\n#[cargo_test]\nfn build_example() {\n    full_project()\n        .cargo(\"build -v --example 'ex*1'\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name example1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_bin() {\n    full_project()\n        .cargo(\"build -v --bin 'bi*1'\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bin1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_bench() {\n    full_project()\n        .cargo(\"build -v --bench 'be*1'\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[RUNNING] `rustc --crate-name bench1 [..]`\n[RUNNING] `rustc --crate-name bin2 [..]`\n[RUNNING] `rustc --crate-name bin1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_test() {\n    full_project()\n        .cargo(\"build -v --test 'te*1'\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bin1 [..]`\n[RUNNING] `rustc --crate-name foo [..]`\n[RUNNING] `rustc --crate-name bin2 [..]`\n[RUNNING] `rustc --crate-name test1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn check_example() {\n    full_project()\n        .cargo(\"check -v --example 'ex*1'\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name example1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_bin() {\n    full_project()\n        .cargo(\"check -v --bin 'bi*1'\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bin1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_bench() {\n    full_project()\n        .cargo(\"check -v --bench 'be*1'\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bench1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_test() {\n    full_project()\n        .cargo(\"check -v --test 'te*1'\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name test1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doc_bin() {\n    full_project()\n        .cargo(\"doc -v --bin 'bi*1'\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc --edition=2015 --crate-type bin --crate-name bin1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bin1/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fix_example() {\n    full_project()\n        .cargo(\"fix -v --example 'ex*1' --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name example1 [..]`\n[FIXING] examples/example1.rs\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fix_bin() {\n    full_project()\n        .cargo(\"fix -v --bin 'bi*1' --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name bin1 [..]`\n[FIXING] src/bin/bin1.rs\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fix_bench() {\n    full_project()\n        .cargo(\"fix -v --bench 'be*1' --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name bench1 [..]`\n[FIXING] benches/bench1.rs\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fix_test() {\n    full_project()\n        .cargo(\"fix -v --test 'te*1' --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name test1 [..]`\n[FIXING] tests/test1.rs\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_example_and_bin() {\n    let p = full_project();\n    p.cargo(\"run -v --bin 'bi*1'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `cargo run` does not support glob patterns on target selection\n\n\"#]])\n        .run();\n\n    p.cargo(\"run -v --example 'ex*1'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `cargo run` does not support glob patterns on target selection\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_example() {\n    full_project()\n        .cargo(\"test -v --example 'ex*1'\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name example1 [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/examples/example1-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_bin() {\n    full_project()\n        .cargo(\"test -v --bin 'bi*1'\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bin1 [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/bin1-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_bench() {\n    full_project()\n        .cargo(\"test -v --bench 'be*1'\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bin2 [..]`\n[RUNNING] `rustc --crate-name foo [..]`\n[RUNNING] `rustc --crate-name bench1 [..]`\n[RUNNING] `rustc --crate-name bin1 [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/bench1-[HASH][EXE]`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn test_test() {\n    full_project()\n        .cargo(\"test -v --test 'te*1'\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name test1 [..]`\n[RUNNING] `rustc --crate-name bin1 [..]`\n[RUNNING] `rustc --crate-name foo [..]`\n[RUNNING] `rustc --crate-name bin2 [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/test1-[HASH][EXE]`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn bench_example() {\n    full_project()\n        .cargo(\"bench -v --example 'ex*1'\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name example1 [..]`\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/examples/example1-[HASH][EXE] --bench`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bench_bin() {\n    full_project()\n        .cargo(\"bench -v --bin 'bi*1'\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bin1 [..]`\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/deps/bin1-[HASH][EXE] --bench`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bench_bench() {\n    full_project()\n        .cargo(\"bench -v --bench 'be*1'\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bin1 [..]`\n[RUNNING] `rustc --crate-name bin2 [..]`\n[RUNNING] `rustc --crate-name foo [..]`\n[RUNNING] `rustc --crate-name bench1 [..]`\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/deps/bench1-[HASH][EXE] --bench`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn bench_test() {\n    full_project()\n        .cargo(\"bench -v --test 'te*1'\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bin2 [..]`\n[RUNNING] `rustc --crate-name foo [..]`\n[RUNNING] `rustc --crate-name test1 [..]`\n[RUNNING] `rustc --crate-name bin1 [..]`\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/deps/test1-[HASH][EXE] --bench`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn install_example() {\n    full_project()\n        .cargo(\"install --path . --example 'ex*1'\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/example1[EXE]\n[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `example1[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn install_bin() {\n    full_project()\n        .cargo(\"install --path . --bin 'bi*1'\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/bin1[EXE]\n[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `bin1[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_example() {\n    full_project()\n        .cargo(\"rustdoc -v --example 'ex*1'\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc --edition=2015 --crate-type bin --crate-name example1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/example1/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_bin() {\n    full_project()\n        .cargo(\"rustdoc -v --bin 'bi*1'\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc --edition=2015 --crate-type bin --crate-name bin1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bin1/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_bench() {\n    full_project()\n        .cargo(\"rustdoc -v --bench 'be*1'\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc --edition=2015 --crate-type bin --crate-name bench1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bench1/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_test() {\n    full_project()\n        .cargo(\"rustdoc -v --test 'te*1'\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc --edition=2015 --crate-type bin --crate-name test1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/test1/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustc_example() {\n    full_project()\n        .cargo(\"rustc -v --example 'ex*1'\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name example1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustc_bin() {\n    full_project()\n        .cargo(\"rustc -v --bin 'bi*1'\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bin1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustc_bench() {\n    full_project()\n        .cargo(\"rustc -v --bench 'be*1'\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bin1 [..]`\n[RUNNING] `rustc --crate-name bench1 [..]`\n[RUNNING] `rustc --crate-name bin2 [..]`\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn rustc_test() {\n    full_project()\n        .cargo(\"rustc -v --test 'te*1'\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name bin1 [..]`\n[RUNNING] `rustc --crate-name bin2 [..]`\n[RUNNING] `rustc --crate-name foo [..]`\n[RUNNING] `rustc --crate-name test1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\nfn full_project() -> Project {\n    project()\n        .file(\"examples/example1.rs\", \"fn main() { }\")\n        .file(\"examples/example2.rs\", \"fn main() { }\")\n        .file(\"benches/bench1.rs\", \"\")\n        .file(\"benches/bench2.rs\", \"\")\n        .file(\"tests/test1.rs\", \"\")\n        .file(\"tests/test2.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() { }\")\n        .file(\"src/bin/bin1.rs\", \"fn main() { }\")\n        .file(\"src/bin/bin2.rs\", \"fn main() { }\")\n        .build()\n}\n"
  },
  {
    "path": "tests/testsuite/global_cache_tracker.rs",
    "content": "//! Tests for last-use tracking and auto-gc.\n//!\n//! Cargo supports an environment variable called `__CARGO_TEST_LAST_USE_NOW`\n//! to have cargo pretend that the current time is the given time (in seconds\n//! since the unix epoch). This is used throughout these tests to simulate\n//! what happens when time passes. The [`days_ago_unix`] and\n//! [`months_ago_unix`] functions help with setting this value.\n\nuse std::env;\nuse std::fmt::Write;\nuse std::path::Path;\nuse std::path::PathBuf;\nuse std::process::Stdio;\nuse std::sync::OnceLock;\nuse std::time::{Duration, SystemTime};\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo::GlobalContext;\nuse cargo::core::global_cache_tracker::{self, DeferredGlobalLastUse, GlobalCacheTracker};\nuse cargo::util::cache_lock::CacheLockMode;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::{Package, RegistryBuilder};\nuse cargo_test_support::{\n    Execs, Project, basic_manifest, execs, git, process, project, retry, sleep_ms, str,\n    thread_wait_timeout,\n};\nuse itertools::Itertools;\n\nuse super::config::GlobalContextBuilder;\n\n/// Helper to create a simple `foo` project which depends on a registry\n/// dependency called `bar`.\nfn basic_foo_bar_project() -> Project {\n    Package::new(\"bar\", \"1.0.0\").publish();\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build()\n}\n\n/// Helper to get the names of files in a directory as strings.\nfn get_names(glob: &str) -> Vec<String> {\n    let mut names: Vec<_> = glob::glob(paths::home().join(glob).to_str().unwrap())\n        .unwrap()\n        .map(|p| p.unwrap().file_name().unwrap().to_str().unwrap().to_owned())\n        .collect();\n    names.sort();\n    names\n}\n\nfn get_registry_names(which: &str) -> Vec<String> {\n    get_names(&format!(\".cargo/registry/{which}/*/*\"))\n}\n\nfn get_index_names() -> Vec<String> {\n    get_names(&format!(\".cargo/registry/index/*\"))\n}\n\nfn get_git_db_names() -> Vec<String> {\n    get_names(&format!(\".cargo/git/db/*\"))\n}\n\nfn get_git_checkout_names(db_name: &str) -> Vec<String> {\n    get_names(&format!(\".cargo/git/checkouts/{db_name}/*\"))\n}\n\nfn days_ago(n: u64) -> SystemTime {\n    now() - Duration::from_secs(60 * 60 * 24 * n)\n}\n\nfn now() -> SystemTime {\n    // This captures the time once to avoid potential time boundaries or\n    // inconsistencies affecting a test. For example, on a fast system\n    // `days_ago(1)` called twice in a row will return the same answer.\n    // However, on a slower system, or if the clock happens to flip over from\n    // one second to the next, then it would return different answers. This\n    // ensures that it always returns the same answer.\n    static START: OnceLock<SystemTime> = OnceLock::new();\n    *START.get_or_init(|| SystemTime::now())\n}\n\n/// Helper for simulating running cargo in the past. Use with the\n/// `__CARGO_TEST_LAST_USE_NOW` environment variable.\nfn days_ago_unix(n: u64) -> String {\n    days_ago(n)\n        .duration_since(SystemTime::UNIX_EPOCH)\n        .unwrap()\n        .as_secs()\n        .to_string()\n}\n\n/// Helper for simulating running cargo in the past. Use with the\n/// `__CARGO_TEST_LAST_USE_NOW` environment variable.\nfn months_ago_unix(n: u64) -> String {\n    days_ago_unix(n * 30)\n}\n\n/// Populates last-use database and the cache files.\n///\n/// This makes it easier to more accurately specify exact sizes. Creating\n/// specific sizes with `Package` is too difficult.\nfn populate_cache(\n    gctx: &GlobalContext,\n    test_crates: &[(&str, u64, u64, u64)],\n) -> (PathBuf, PathBuf) {\n    let cache_dir = paths::home().join(\".cargo/registry/cache/example.com-a6c4a5adcb232b9a\");\n    let src_dir = paths::home().join(\".cargo/registry/src/example.com-a6c4a5adcb232b9a\");\n\n    GlobalCacheTracker::db_path(&gctx)\n        .into_path_unlocked()\n        .rm_rf();\n\n    let _lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n        .unwrap();\n    let mut tracker = GlobalCacheTracker::new(&gctx).unwrap();\n    let mut deferred = DeferredGlobalLastUse::new();\n\n    cache_dir.rm_rf();\n    cache_dir.mkdir_p();\n    src_dir.rm_rf();\n    src_dir.mkdir_p();\n    paths::home()\n        .join(\".cargo/registry/index/example.com-a6c4a5adcb232b9a\")\n        .mkdir_p();\n    let mut create = |name: &str, age, crate_size: u64, src_size: u64| {\n        let crate_filename = format!(\"{name}.crate\").into();\n        deferred.mark_registry_crate_used_stamp(\n            global_cache_tracker::RegistryCrate {\n                encoded_registry_name: \"example.com-a6c4a5adcb232b9a\".into(),\n                crate_filename,\n                size: crate_size,\n            },\n            Some(&days_ago(age)),\n        );\n        deferred.mark_registry_src_used_stamp(\n            global_cache_tracker::RegistrySrc {\n                encoded_registry_name: \"example.com-a6c4a5adcb232b9a\".into(),\n                package_dir: name.into(),\n                size: Some(src_size),\n            },\n            Some(&days_ago(age)),\n        );\n        std::fs::write(\n            cache_dir.join(crate_filename),\n            \"x\".repeat(crate_size as usize),\n        )\n        .unwrap();\n        let path = src_dir.join(name);\n        path.mkdir_p();\n        std::fs::write(path.join(\"data\"), \"x\".repeat(src_size as usize)).unwrap()\n    };\n\n    for (name, age, crate_size, src_size) in test_crates {\n        create(name, *age, *crate_size, *src_size);\n    }\n    deferred.save(&mut tracker).unwrap();\n\n    (cache_dir, src_dir)\n}\n\n/// Returns an `Execs` that will run the rustup `cargo` proxy from the global\n/// system's cargo home directory.\nfn rustup_cargo() -> Execs {\n    // Modify the PATH to ensure that `cargo` and `rustc` comes from\n    // CARGO_HOME. This is necessary because cargo adds the \"deps\" directory\n    // into PATH on Windows, which points to the wrong cargo.\n    let real_cargo_home_bin = Path::new(&std::env::var_os(\"CARGO_HOME\").unwrap()).join(\"bin\");\n    let mut paths = vec![real_cargo_home_bin];\n    paths.extend(env::split_paths(&env::var_os(\"PATH\").unwrap_or_default()));\n    let path = env::join_paths(paths).unwrap();\n    let mut e = execs().with_process_builder(process(\"cargo\"));\n    e.env(\"PATH\", path);\n    e\n}\n\n#[cargo_test]\nfn clean_gc_gated() {\n    cargo_process(\"clean gc\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `cargo clean gc` command is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel\nSee https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels.\nSee https://github.com/rust-lang/cargo/issues/12633 for more information about the `cargo clean gc` command.\n\n\"#]]\n        )\n        .run();\n}\n\n#[cargo_test]\nfn implies_source() {\n    // Checks that when a src, crate, or checkout is marked as used, the\n    // corresponding index or git db also gets marked as used.\n    let gctx = GlobalContextBuilder::new().build();\n    let _lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n        .unwrap();\n    let mut deferred = DeferredGlobalLastUse::new();\n    let mut tracker = GlobalCacheTracker::new(&gctx).unwrap();\n\n    deferred.mark_registry_crate_used(global_cache_tracker::RegistryCrate {\n        encoded_registry_name: \"example.com-a6c4a5adcb232b9a\".into(),\n        crate_filename: \"regex-1.8.4.crate\".into(),\n        size: 123,\n    });\n    deferred.mark_registry_src_used(global_cache_tracker::RegistrySrc {\n        encoded_registry_name: \"index.crates.io-6f17d22bba15001f\".into(),\n        package_dir: \"rand-0.8.5\".into(),\n        size: None,\n    });\n    deferred.mark_git_checkout_used(global_cache_tracker::GitCheckout {\n        encoded_git_name: \"cargo-e7ff1db891893a9e\".into(),\n        short_name: \"f0a4ee0\".into(),\n        size: None,\n    });\n    deferred.save(&mut tracker).unwrap();\n\n    let mut indexes = tracker.registry_index_all().unwrap();\n    assert_eq!(indexes.len(), 2);\n    indexes.sort_by(|a, b| a.0.encoded_registry_name.cmp(&b.0.encoded_registry_name));\n    assert_eq!(\n        indexes[0].0.encoded_registry_name,\n        \"example.com-a6c4a5adcb232b9a\"\n    );\n    assert_eq!(\n        indexes[1].0.encoded_registry_name,\n        \"index.crates.io-6f17d22bba15001f\"\n    );\n\n    let dbs = tracker.git_db_all().unwrap();\n    assert_eq!(dbs.len(), 1);\n    assert_eq!(dbs[0].0.encoded_git_name, \"cargo-e7ff1db891893a9e\");\n}\n\n#[cargo_test]\nfn auto_gc_defaults() {\n    // Checks that the auto-gc deletes old entries, and leaves new ones intact.\n    Package::new(\"old\", \"1.0.0\").publish();\n    Package::new(\"new\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                old = \"1.0\"\n                new = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    // Populate the last-use data.\n    p.cargo(\"check\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n    assert_eq!(get_registry_names(\"src\"), [\"new-1.0.0\", \"old-1.0.0\"]);\n    assert_eq!(\n        get_registry_names(\"cache\"),\n        [\"new-1.0.0.crate\", \"old-1.0.0.crate\"]\n    );\n\n    // Run again with just one package. Make sure the old src gets deleted,\n    // but .crate does not.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            new = \"1.0\"\n        \"#,\n    );\n    p.cargo(\"check\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(2))\n        .run();\n    assert_eq!(get_registry_names(\"src\"), [\"new-1.0.0\"]);\n    assert_eq!(\n        get_registry_names(\"cache\"),\n        [\"new-1.0.0.crate\", \"old-1.0.0.crate\"]\n    );\n\n    // Run again after the .crate should have aged out.\n    p.cargo(\"check\").run();\n    assert_eq!(get_registry_names(\"src\"), [\"new-1.0.0\"]);\n    assert_eq!(get_registry_names(\"cache\"), [\"new-1.0.0.crate\"]);\n}\n\n#[cargo_test]\nfn auto_gc_config_gated() {\n    // gc.auto config options should be ignored without -Zgc\n    Package::new(\"old\", \"1.0.0\").publish();\n    Package::new(\"new\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [gc.auto]\n                frequency = \"always\"\n                max-src-age = \"1 day\"\n                max-crate-age = \"3 days\"\n                max-index-age = \"3 days\"\n                max-git-co-age = \"1 day\"\n                max-git-db-age = \"3 days\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                old = \"1.0\"\n                new = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    // Populate the last-use data.\n    p.cargo(\"check\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", days_ago_unix(4))\n        .run();\n    assert_eq!(get_registry_names(\"src\"), [\"new-1.0.0\", \"old-1.0.0\"]);\n    assert_eq!(\n        get_registry_names(\"cache\"),\n        [\"new-1.0.0.crate\", \"old-1.0.0.crate\"]\n    );\n\n    // Run again with just one package. Without -Zgc, it should use the\n    // defaults and ignore the config. Nothing should get deleted since the\n    // defaults are much greater than 4 days.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            new = \"1.0\"\n        \"#,\n    );\n\n    p.cargo(\"check\").run();\n    assert_eq!(get_registry_names(\"src\"), [\"new-1.0.0\", \"old-1.0.0\"]);\n    assert_eq!(\n        get_registry_names(\"cache\"),\n        [\"new-1.0.0.crate\", \"old-1.0.0.crate\"]\n    );\n}\n\n#[cargo_test]\nfn auto_gc_config() {\n    // Can configure auto gc settings.\n    Package::new(\"old\", \"1.0.0\").publish();\n    Package::new(\"new\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [cache]\n                auto-clean-frequency = \"always\"\n                [cache.global-clean]\n                max-src-age = \"1 day\"\n                max-crate-age = \"3 days\"\n                max-index-age = \"3 days\"\n                max-git-co-age = \"1 day\"\n                max-git-db-age = \"3 days\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                old = \"1.0\"\n                new = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    // Populate the last-use data.\n    p.cargo(\"check\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", days_ago_unix(4))\n        .run();\n    assert_eq!(get_registry_names(\"src\"), [\"new-1.0.0\", \"old-1.0.0\"]);\n    assert_eq!(\n        get_registry_names(\"cache\"),\n        [\"new-1.0.0.crate\", \"old-1.0.0.crate\"]\n    );\n\n    // Run again with just one package. Make sure the old src gets deleted,\n    // but .crate does not.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            new = \"1.0\"\n        \"#,\n    );\n    p.cargo(\"check -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", days_ago_unix(2))\n        .run();\n    assert_eq!(get_registry_names(\"src\"), [\"new-1.0.0\"]);\n    assert_eq!(\n        get_registry_names(\"cache\"),\n        [\"new-1.0.0.crate\", \"old-1.0.0.crate\"]\n    );\n\n    // Run again after the .crate should have aged out.\n    p.cargo(\"check -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .run();\n    assert_eq!(get_registry_names(\"src\"), [\"new-1.0.0\"]);\n    assert_eq!(get_registry_names(\"cache\"), [\"new-1.0.0.crate\"]);\n}\n\n#[cargo_test]\nfn frequency() {\n    // cache.auto-clean-frequency settings\n    let p = basic_foo_bar_project();\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n            [cache]\n            auto-clean-frequency = \"never\"\n        \"#,\n    );\n    // Populate data in the past.\n    p.cargo(\"check\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n    assert_eq!(get_index_names().len(), 1);\n    assert_eq!(get_registry_names(\"src\"), [\"bar-1.0.0\"]);\n    assert_eq!(get_registry_names(\"cache\"), [\"bar-1.0.0.crate\"]);\n\n    p.change_file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.2.0\"));\n\n    // Try after the default expiration time, with \"never\" it shouldn't gc.\n    p.cargo(\"check\").run();\n    assert_eq!(get_index_names().len(), 1);\n    assert_eq!(get_registry_names(\"src\"), [\"bar-1.0.0\"]);\n    assert_eq!(get_registry_names(\"cache\"), [\"bar-1.0.0.crate\"]);\n\n    // Try again with a setting that allows it to run.\n    p.cargo(\"check\")\n        .env(\"CARGO_CACHE_AUTO_CLEAN_FREQUENCY\", \"1 day\")\n        .run();\n    assert_eq!(get_index_names().len(), 0);\n    assert_eq!(get_registry_names(\"src\").len(), 0);\n    assert_eq!(get_registry_names(\"cache\").len(), 0);\n}\n\n#[cargo_test]\nfn auto_gc_index() {\n    // Deletes the index if it hasn't been used in a while.\n    let p = basic_foo_bar_project();\n    p.cargo(\"check\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n    assert_eq!(get_index_names().len(), 1);\n\n    // Make sure it stays within the time frame.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n        \"#,\n    );\n    p.cargo(\"check\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(2))\n        .run();\n    assert_eq!(get_index_names().len(), 1);\n\n    // After it expires, it should be deleted.\n    p.cargo(\"check\").run();\n    assert_eq!(get_index_names().len(), 0);\n}\n\n#[cargo_test]\nfn auto_gc_git() {\n    // auto-gc should delete git checkouts and dbs.\n\n    // Returns the short git name of a checkout.\n    let short_id = |repo: &git2::Repository| -> String {\n        let head = repo.revparse_single(\"HEAD\").unwrap();\n        let short_id = head.short_id().unwrap();\n        short_id.as_str().unwrap().to_owned()\n    };\n\n    // Set up a git dependency and fetch it and populate the database,\n    // 6 months in the past.\n    let (git_project, git_repo) = git::new_repo(\"bar\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = {{ git = '{}' }}\n            \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(6))\n        .run();\n    let db_names = get_git_db_names();\n    assert_eq!(db_names.len(), 1);\n    let first_short_oid = short_id(&git_repo);\n    assert_eq!(\n        get_git_checkout_names(&db_names[0]),\n        [first_short_oid.clone()]\n    );\n\n    // Use a new git checkout, should keep both.\n    git_project.change_file(\"src/lib.rs\", \"// modified\");\n    git::add(&git_repo);\n    git::commit(&git_repo);\n    p.cargo(\"update\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(6))\n        .run();\n    assert_eq!(get_git_db_names().len(), 1);\n    let second_short_oid = short_id(&git_repo);\n    let mut both = vec![first_short_oid, second_short_oid.clone()];\n    both.sort();\n    assert_eq!(get_git_checkout_names(&db_names[0]), both);\n\n    // In the future, using the second checkout should delete the first.\n    p.cargo(\"check\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n    assert_eq!(get_git_db_names().len(), 1);\n    assert_eq!(\n        get_git_checkout_names(&db_names[0]),\n        [second_short_oid.clone()]\n    );\n\n    // After three months, the db should get deleted.\n    p.change_file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.2.0\"));\n    p.cargo(\"check\").run();\n    assert_eq!(get_git_db_names().len(), 0);\n    assert_eq!(get_git_checkout_names(&db_names[0]).len(), 0);\n}\n\n#[cargo_test]\nfn auto_gc_various_commands() {\n    // Checks that auto gc works with a variety of commands.\n    //\n    // Auto-gc is only run on a subset of commands. Generally it is run on\n    // commands that are already doing a lot of work, or heavily involve the\n    // use of the registry.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let cmds = [\"check\", \"fetch\"];\n    for cmd in cmds {\n        eprintln!(\"checking command {cmd}\");\n        let p = project()\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    bar = \"1.0\"\n                \"#,\n            )\n            .file(\"src/lib.rs\", \"\")\n            .build();\n        // Populate the last-use data.\n        p.cargo(cmd)\n            .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n            .run();\n        let gctx = GlobalContextBuilder::new().build();\n        let lock = gctx\n            .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n            .unwrap();\n        let tracker = GlobalCacheTracker::new(&gctx).unwrap();\n        let indexes = tracker.registry_index_all().unwrap();\n        assert_eq!(indexes.len(), 1);\n        let crates = tracker.registry_crate_all().unwrap();\n        assert_eq!(crates.len(), 1);\n        let srcs = tracker.registry_src_all().unwrap();\n        assert_eq!(srcs.len(), 1);\n        drop(lock);\n\n        // After everything is aged out, it should all be deleted.\n        p.change_file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.2.0\"));\n        p.cargo(cmd).run();\n        let lock = gctx\n            .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n            .unwrap();\n        let indexes = tracker.registry_index_all().unwrap();\n        assert_eq!(indexes.len(), 0);\n        let crates = tracker.registry_crate_all().unwrap();\n        assert_eq!(crates.len(), 0);\n        let srcs = tracker.registry_src_all().unwrap();\n        assert_eq!(srcs.len(), 0);\n        drop(tracker);\n        drop(lock);\n        paths::home().join(\".cargo/registry\").rm_rf();\n        GlobalCacheTracker::db_path(&gctx)\n            .into_path_unlocked()\n            .rm_rf();\n    }\n}\n\n#[cargo_test]\nfn updates_last_use_various_commands() {\n    // Checks that last-use tracking is updated by various commands.\n    //\n    // Not *all* commands update the index tracking, even though they\n    // technically involve reading the index. There isn't a convenient place\n    // to ensure it gets saved while avoiding saving too often in other\n    // commands. For the most part, this should be fine, since these commands\n    // usually aren't run without running one of the commands that does save\n    // the tracking. Some of the commands are:\n    //\n    // - login, owner, yank, search\n    // - report future-incompatibilities\n    // - package --no-verify\n    // - fetch --locked\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let cmds = [\n        // name, expected_crates (0=doesn't download)\n        (\"check\", 1),\n        (\"fetch\", 1),\n        (\"tree\", 1),\n        (\"generate-lockfile\", 0),\n        (\"update\", 0),\n        (\"metadata\", 1),\n        (\"vendor --respect-source-config\", 1),\n    ];\n    for (cmd, expected_crates) in cmds {\n        eprintln!(\"checking command {cmd}\");\n        let p = project()\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    bar = \"1.0\"\n                \"#,\n            )\n            .file(\"src/lib.rs\", \"\")\n            .build();\n        // Populate the last-use data.\n        p.cargo(cmd).run();\n        let gctx = GlobalContextBuilder::new().build();\n        let lock = gctx\n            .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n            .unwrap();\n        let tracker = GlobalCacheTracker::new(&gctx).unwrap();\n        let indexes = tracker.registry_index_all().unwrap();\n        assert_eq!(indexes.len(), 1);\n        let crates = tracker.registry_crate_all().unwrap();\n        assert_eq!(crates.len(), expected_crates);\n        let srcs = tracker.registry_src_all().unwrap();\n        assert_eq!(srcs.len(), expected_crates);\n        drop(tracker);\n        drop(lock);\n        paths::home().join(\".cargo/registry\").rm_rf();\n        GlobalCacheTracker::db_path(&gctx)\n            .into_path_unlocked()\n            .rm_rf();\n    }\n}\n\n#[cargo_test]\nfn both_git_and_http_index_cleans() {\n    // Checks that either the git or http index cache gets cleaned.\n    let _crates_io = RegistryBuilder::new().build();\n    let _alternative = RegistryBuilder::new().alternative().http_index().build();\n    Package::new(\"from_git\", \"1.0.0\").publish();\n    Package::new(\"from_http\", \"1.0.0\")\n        .alternative(true)\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                from_git = \"1.0\"\n                from_http = { version = \"1.0\", registry = \"alternative\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"update\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n    let gctx = GlobalContextBuilder::new().build();\n    let lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n        .unwrap();\n    let tracker = GlobalCacheTracker::new(&gctx).unwrap();\n    let indexes = tracker.registry_index_all().unwrap();\n    assert_eq!(indexes.len(), 2);\n    assert_eq!(get_index_names().len(), 2);\n    drop(lock);\n\n    // Running in the future without these indexes should delete them.\n    p.change_file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.2.0\"));\n    p.cargo(\"clean gc -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .run();\n    let lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n        .unwrap();\n    let indexes = tracker.registry_index_all().unwrap();\n    assert_eq!(indexes.len(), 0);\n    assert_eq!(get_index_names().len(), 0);\n    drop(lock);\n}\n\n#[cargo_test]\nfn clean_gc_dry_run() {\n    // Basic `clean --gc --dry-run` test.\n    let p = basic_foo_bar_project();\n    // Populate the last-use data.\n    p.cargo(\"fetch\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n\n    let registry_root = paths::home().join(\".cargo/registry\");\n    let glob_registry = |name| -> PathBuf {\n        let mut paths: Vec<_> = glob::glob(registry_root.join(name).join(\"*\").to_str().unwrap())\n            .unwrap()\n            .map(|p| p.unwrap())\n            .collect();\n        assert_eq!(paths.len(), 1);\n        paths.pop().unwrap()\n    };\n    let index = glob_registry(\"index\").ls_r();\n    let src = glob_registry(\"src\").ls_r();\n    let cache = glob_registry(\"cache\").ls_r();\n    let mut expected_files = index\n        .iter()\n        .chain(src.iter())\n        .chain(cache.iter())\n        .map(|p| p.to_str().unwrap())\n        .join(\"\\n\");\n    expected_files.push_str(\"\\n\");\n    let expected_files = snapbox::filter::normalize_paths(&expected_files);\n    let expected_files = assert_e2e().redactions().redact(&expected_files);\n\n    p.cargo(\"clean gc --dry-run -v -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stdout_data(expected_files.as_str().unordered())\n        .with_stderr_data(str![[r#\"\n[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total\n[WARNING] no files deleted due to --dry-run\n\n\"#]])\n        .run();\n\n    // Again, make sure the information is still tracked.\n    p.cargo(\"clean gc --dry-run -v -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stdout_data(expected_files.as_str().unordered())\n        .with_stderr_data(str![[r#\"\n[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total\n[WARNING] no files deleted due to --dry-run\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn clean_default_gc() {\n    // `clean gc` without options should also gc\n    let p = basic_foo_bar_project();\n    // Populate the last-use data.\n    p.cargo(\"fetch\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n    p.cargo(\"clean gc -v -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(\n            str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/registry/index/-[HASH]\n[REMOVING] [ROOT]/home/.cargo/registry/src/-[HASH]\n[REMOVING] [ROOT]/home/.cargo/registry/cache/-[HASH]\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn tracks_sizes() {\n    // Checks that sizes are properly tracked in the db.\n    Package::new(\"dep1\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    Package::new(\"dep2\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\"data\", &\"abcdefghijklmnopqrstuvwxyz\".repeat(1000))\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                dep1 = \"1.0\"\n                dep2 = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\").run();\n\n    // Check that the crate sizes are the same as on disk.\n    let gctx = GlobalContextBuilder::new().build();\n    let _lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n        .unwrap();\n    let tracker = GlobalCacheTracker::new(&gctx).unwrap();\n    let mut crates = tracker.registry_crate_all().unwrap();\n    crates.sort_by(|a, b| a.0.crate_filename.cmp(&b.0.crate_filename));\n    let db_sizes: Vec<_> = crates.iter().map(|c| c.0.size).collect();\n\n    let mut actual: Vec<_> = p\n        .glob(paths::home().join(\".cargo/registry/cache/*/*\"))\n        .map(|p| p.unwrap())\n        .collect();\n    actual.sort();\n    let actual_sizes: Vec<_> = actual\n        .iter()\n        .map(|path| std::fs::metadata(path).unwrap().len())\n        .collect();\n    assert_eq!(db_sizes, actual_sizes);\n\n    // Also check the src sizes are computed.\n    let mut srcs = tracker.registry_src_all().unwrap();\n    srcs.sort_by(|a, b| a.0.package_dir.cmp(&b.0.package_dir));\n    let db_sizes: Vec<_> = srcs.iter().map(|c| c.0.size.unwrap()).collect();\n    let mut actual: Vec<_> = p\n        .glob(paths::home().join(\".cargo/registry/src/*/*\"))\n        .map(|p| p.unwrap())\n        .collect();\n    actual.sort();\n    // .cargo-ok is not tracked in the size.\n    actual.iter().for_each(|p| p.join(\".cargo-ok\").rm_rf());\n    let actual_sizes: Vec<_> = actual\n        .iter()\n        .map(|path| cargo_util::du(path, &[]).unwrap())\n        .collect();\n    assert_eq!(db_sizes, actual_sizes);\n    assert!(db_sizes[1] > 26000);\n}\n\n#[cargo_test]\nfn max_size() {\n    // Checks --max-crate-size and --max-src-size with various cleaning thresholds.\n    let gctx = GlobalContextBuilder::new().build();\n\n    let test_crates = [\n        // name, age, crate_size, src_size\n        (\"a-1.0.0\", 5, 1, 1),\n        (\"b-1.0.0\", 6, 2, 2),\n        (\"c-1.0.0\", 3, 3, 3),\n        (\"d-1.0.0\", 2, 4, 4),\n        (\"e-1.0.0\", 2, 5, 5),\n        (\"f-1.0.0\", 9, 6, 6),\n        (\"g-1.0.0\", 1, 1, 1),\n    ];\n\n    // Determine the order things get deleted so they can be verified.\n    let mut names_by_timestamp: Vec<_> = test_crates\n        .iter()\n        .map(|(name, age, _, _)| (days_ago_unix(*age), name))\n        .collect();\n    names_by_timestamp.sort();\n    let names_by_timestamp: Vec<_> = names_by_timestamp\n        .into_iter()\n        .map(|(_, name)| name)\n        .collect();\n\n    // This exercises the different boundary conditions.\n    for (clean_size, files) in [\n        (22, 0),\n        (21, 1),\n        (16, 1),\n        (15, 2),\n        (14, 2),\n        (13, 3),\n        (12, 4),\n        (10, 4),\n        (9, 5),\n        (6, 5),\n        (5, 6),\n        (1, 6),\n        (0, 7),\n    ] {\n        let (removed, kept) = names_by_timestamp.split_at(files);\n        // --max-crate-size\n        let (cache_dir, src_dir) = populate_cache(&gctx, &test_crates);\n        let mut stderr = String::new();\n        for name in removed {\n            writeln!(stderr, \"[REMOVING] [..]{name}.crate\").unwrap();\n        }\n        let total_display = if removed.is_empty() {\n            \"\"\n        } else {\n            \", [FILE_SIZE]B total\"\n        };\n        let files_display = if files == 0 {\n            \"0 files\"\n        } else if files == 1 {\n            \"1 file\"\n        } else {\n            \"[FILE_NUM] files\"\n        };\n        writeln!(stderr, \"[REMOVED] {files_display}{total_display}\").unwrap();\n        cargo_process(&format!(\"clean gc -Zgc -v --max-crate-size={clean_size}\"))\n            .masquerade_as_nightly_cargo(&[\"gc\"])\n            .with_stderr_data(stderr.unordered())\n            .run();\n        for name in kept {\n            assert!(cache_dir.join(format!(\"{name}.crate\")).exists());\n        }\n        for name in removed {\n            assert!(!cache_dir.join(format!(\"{name}.crate\")).exists());\n        }\n\n        // --max-src-size\n        populate_cache(&gctx, &test_crates);\n        let mut stderr = String::new();\n        for name in removed {\n            writeln!(stderr, \"[REMOVING] [..]{name}\").unwrap();\n        }\n        let total_display = if removed.is_empty() {\n            \"\"\n        } else {\n            \", [FILE_SIZE]B total\"\n        };\n        writeln!(stderr, \"[REMOVED] {files_display}{total_display}\").unwrap();\n        cargo_process(&format!(\"clean gc -Zgc -v --max-src-size={clean_size}\"))\n            .masquerade_as_nightly_cargo(&[\"gc\"])\n            .with_stderr_data(stderr.unordered())\n            .run();\n        for name in kept {\n            assert!(src_dir.join(name).exists());\n        }\n        for name in removed {\n            assert!(!src_dir.join(name).exists());\n        }\n    }\n}\n\n#[cargo_test]\nfn max_size_untracked_crate() {\n    // When a .crate file exists from an older version of cargo that did not\n    // track sizes, `clean --max-crate-size` should populate the db with the\n    // sizes.\n    let gctx = GlobalContextBuilder::new().build();\n    let cache = paths::home().join(\".cargo/registry/cache/example.com-a6c4a5adcb232b9a\");\n    cache.mkdir_p();\n    paths::home()\n        .join(\".cargo/registry/index/example.com-a6c4a5adcb232b9a\")\n        .mkdir_p();\n    // Create the `.crate files.\n    let test_crates = [\n        // name, size\n        (\"a-1.0.0.crate\", 1234),\n        (\"b-1.0.0.crate\", 42),\n        (\"c-1.0.0.crate\", 0),\n    ];\n    for (name, size) in test_crates {\n        std::fs::write(cache.join(name), \"x\".repeat(size as usize)).unwrap()\n    }\n    // This should scan the directory and populate the db with the size information.\n    cargo_process(\"clean gc -Zgc -v --max-crate-size=100000\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVED] 0 files\n\n\"#]])\n        .run();\n    // Check that it stored the size data.\n    let _lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n        .unwrap();\n    let tracker = GlobalCacheTracker::new(&gctx).unwrap();\n    let crates = tracker.registry_crate_all().unwrap();\n    let mut actual: Vec<_> = crates\n        .iter()\n        .map(|(rc, _time)| (rc.crate_filename.as_str(), rc.size))\n        .collect();\n    actual.sort();\n    assert_eq!(test_crates, actual.as_slice());\n}\n\n/// Helper to prepare the max-size test.\nfn max_size_untracked_prepare() -> (GlobalContext, Project) {\n    // First, publish and download a dependency.\n    let p = basic_foo_bar_project();\n    p.cargo(\"fetch\").run();\n    // Pretend it was an older version that did not track last-use.\n    let gctx = GlobalContextBuilder::new().build();\n    GlobalCacheTracker::db_path(&gctx)\n        .into_path_unlocked()\n        .rm_rf();\n    (gctx, p)\n}\n\n/// Helper to verify the max-size test.\nfn max_size_untracked_verify(gctx: &GlobalContext) {\n    let actual: Vec<_> = glob::glob(\n        paths::home()\n            .join(\".cargo/registry/src/*/*\")\n            .to_str()\n            .unwrap(),\n    )\n    .unwrap()\n    .map(|p| p.unwrap())\n    .collect();\n    assert_eq!(actual.len(), 1);\n    let actual_size = cargo_util::du(&actual[0], &[]).unwrap();\n    let lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n        .unwrap();\n    let tracker = GlobalCacheTracker::new(&gctx).unwrap();\n    let srcs = tracker.registry_src_all().unwrap();\n    assert_eq!(srcs.len(), 1);\n    assert_eq!(srcs[0].0.size, Some(actual_size));\n    drop(lock);\n}\n\n#[cargo_test]\nfn max_size_untracked_src_from_use() {\n    // When a src directory exists from an older version of cargo that did not\n    // track sizes, doing a build should populate the db with an entry with an\n    // unknown size. `clean --max-src-size` should then fix the size.\n    let (gctx, p) = max_size_untracked_prepare();\n\n    // Run a command that will update the db with an unknown src size.\n    p.cargo(\"tree\").run();\n    // Check that it is None.\n    let lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n        .unwrap();\n    let tracker = GlobalCacheTracker::new(&gctx).unwrap();\n    let srcs = tracker.registry_src_all().unwrap();\n    assert_eq!(srcs.len(), 1);\n    assert_eq!(srcs[0].0.size, None);\n    drop(lock);\n\n    // Fix the size.\n    p.cargo(\"clean gc -v --max-src-size=10000 -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVED] 0 files\n\n\"#]])\n        .run();\n    max_size_untracked_verify(&gctx);\n}\n\n#[cargo_test]\nfn max_size_untracked_src_from_clean() {\n    // When a src directory exists from an older version of cargo that did not\n    // track sizes, `clean --max-src-size` should populate the db with the\n    // sizes.\n    let (gctx, p) = max_size_untracked_prepare();\n\n    // Clean should scan the src and update the db.\n    p.cargo(\"clean gc -v --max-src-size=10000 -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVED] 0 files\n\n\"#]])\n        .run();\n    max_size_untracked_verify(&gctx);\n}\n\n#[cargo_test]\nfn max_download_size() {\n    // --max-download-size\n    //\n    // This creates some sample crates of specific sizes, and then tries\n    // deleting at various specific size thresholds that exercise different\n    // edge conditions.\n    let gctx = GlobalContextBuilder::new().build();\n\n    let test_crates = [\n        // name, age, crate_size, src_size\n        (\"d-1.0.0\", 4, 4, 5),\n        (\"c-1.0.0\", 3, 3, 3),\n        (\"a-1.0.0\", 1, 2, 5),\n        (\"b-1.0.0\", 1, 1, 7),\n    ];\n\n    for (max_size, num_deleted, files_deleted) in [\n        (30, 0, 0),\n        (29, 1, 1),\n        (24, 2, 2),\n        (20, 3, 3),\n        (1, 7, 7),\n        (0, 8, 8),\n    ] {\n        populate_cache(&gctx, &test_crates);\n        // Determine the order things will be deleted.\n        let delete_order: Vec<String> = test_crates\n            .iter()\n            .flat_map(|(name, _, _, _)| [name.to_string(), format!(\"{name}.crate\")])\n            .collect();\n        let (removed, _kept) = delete_order.split_at(num_deleted);\n        let mut stderr = String::new();\n        for name in removed {\n            writeln!(stderr, \"[REMOVING] [..]{name}\").unwrap();\n        }\n        let files_display = if files_deleted == 0 {\n            \"0 files\"\n        } else if files_deleted == 1 {\n            \"1 file\"\n        } else {\n            \"[FILE_NUM] files\"\n        };\n        let total_display = if removed.is_empty() {\n            \"\"\n        } else {\n            \", [FILE_SIZE]B total\"\n        };\n        writeln!(stderr, \"[REMOVED] {files_display}{total_display}\",).unwrap();\n        cargo_process(&format!(\"clean gc -Zgc -v --max-download-size={max_size}\"))\n            .masquerade_as_nightly_cargo(&[\"gc\"])\n            .with_stderr_data(stderr.unordered())\n            .run();\n    }\n}\n\n#[cargo_test]\nfn package_cache_lock_during_build() {\n    // Verifies that a shared lock is held during a build. Resolution and\n    // downloads should be OK while that is held, but mutation should block.\n    //\n    // This works by launching a build with a build script that will pause.\n    // Then it performs other cargo commands and verifies their behavior.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p_foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    std::fs::write(\"blocking\", \"\").unwrap();\n                    let path = std::path::Path::new(\"ready\");\n                    loop {\n                        if path.exists() {\n                            break;\n                        } else {\n                            std::thread::sleep(std::time::Duration::from_millis(100))\n                        }\n                    }\n                }\n            \"#,\n        )\n        .build();\n    let p_foo2 = project()\n        .at(\"foo2\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo2\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Start a build that will pause once the build starts.\n    let mut foo_child = p_foo\n        .cargo(\"check\")\n        .build_command()\n        .stdout(Stdio::piped())\n        .stderr(Stdio::piped())\n        .spawn()\n        .unwrap();\n\n    // Wait for it to enter build script.\n    retry(100, || p_foo.root().join(\"blocking\").exists().then_some(()));\n\n    // Start a build with a different target directory. It should not block,\n    // even though it gets a download lock, and then a shared lock.\n    //\n    // Also verify that auto-gc gets disabled.\n    p_foo2\n        .cargo(\"check\")\n        .env(\"CARGO_CACHE_AUTO_CLEAN_FREQUENCY\", \"always\")\n        .env(\"CARGO_LOG\", \"gc=debug\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n   [..]s DEBUG gc: unable to acquire mutate lock, auto gc disabled\n[CHECKING] bar v1.0.0\n[CHECKING] foo2 v0.1.0 ([ROOT]/foo2)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Ensure that the first build really blocked.\n    assert!(matches!(foo_child.try_wait(), Ok(None)));\n\n    // Cleaning while a command is running should block.\n    let mut clean_cmd = p_foo2\n        .cargo(\"clean gc --max-download-size=0 -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .build_command();\n    clean_cmd.stderr(Stdio::piped());\n    let mut clean_child = clean_cmd.spawn().unwrap();\n\n    // Give the clean command a chance to finish (it shouldn't).\n    sleep_ms(500);\n    // They should both still be running.\n    assert!(matches!(foo_child.try_wait(), Ok(None)));\n    assert!(matches!(clean_child.try_wait(), Ok(None)));\n\n    // Let the original build finish.\n    p_foo.change_file(\"ready\", \"\");\n\n    // Wait for clean to finish.\n    let thread = std::thread::spawn(|| clean_child.wait_with_output().unwrap());\n    let output = thread_wait_timeout(100, thread);\n    assert!(output.status.success());\n    // Validate the output of the clean.\n    execs()\n        .with_stderr_data(str![[r#\"\n[BLOCKING] waiting for file lock on package cache mutation\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run_output(&output);\n}\n\n#[cargo_test]\nfn read_only_locking_auto_gc() {\n    // Tests the behavior for auto-gc on a read-only directory.\n    let p = basic_foo_bar_project();\n    // Populate cache.\n    p.cargo(\"fetch\").run();\n    let cargo_home = paths::home().join(\".cargo\");\n    let mut perms = std::fs::metadata(&cargo_home).unwrap().permissions();\n    // Test when it can't update auto-gc db.\n    perms.set_readonly(true);\n    std::fs::set_permissions(&cargo_home, perms.clone()).unwrap();\n    p.cargo(\"check -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // Try again without the last-use existing (such as if the cache was\n    // populated by an older version of cargo).\n    perms.set_readonly(false);\n    std::fs::set_permissions(&cargo_home, perms.clone()).unwrap();\n    let gctx = GlobalContextBuilder::new().build();\n    GlobalCacheTracker::db_path(&gctx)\n        .into_path_unlocked()\n        .rm_rf();\n    perms.set_readonly(true);\n    std::fs::set_permissions(&cargo_home, perms.clone()).unwrap();\n    p.cargo(\"check -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    perms.set_readonly(false);\n    std::fs::set_permissions(&cargo_home, perms).unwrap();\n}\n\n#[cargo_test]\nfn delete_index_also_deletes_crates() {\n    // Checks that when an index is delete that src and cache directories also get deleted.\n    let p = basic_foo_bar_project();\n    p.cargo(\"fetch\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n\n    assert_eq!(get_registry_names(\"src\"), [\"bar-1.0.0\"]);\n    assert_eq!(get_registry_names(\"cache\"), [\"bar-1.0.0.crate\"]);\n\n    p.cargo(\"clean gc\")\n        .arg(\"--max-index-age=0 days\")\n        .arg(\"-Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n\n    assert_eq!(get_registry_names(\"src\").len(), 0);\n    assert_eq!(get_registry_names(\"cache\").len(), 0);\n}\n\n#[cargo_test]\nfn clean_syncs_missing_files() {\n    // When files go missing in the cache, clean operations that need to track\n    // the size should also remove them from the database.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    Package::new(\"baz\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n                baz = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\").run();\n\n    // Verify things are tracked.\n    let gctx = GlobalContextBuilder::new().build();\n    let lock = gctx\n        .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n        .unwrap();\n    let tracker = GlobalCacheTracker::new(&gctx).unwrap();\n    let crates = tracker.registry_crate_all().unwrap();\n    assert_eq!(crates.len(), 2);\n    let srcs = tracker.registry_src_all().unwrap();\n    assert_eq!(srcs.len(), 2);\n    drop(lock);\n\n    // Remove the files.\n    for pattern in [\n        \".cargo/registry/cache/*/bar-1.0.0.crate\",\n        \".cargo/registry/src/*/bar-1.0.0\",\n    ] {\n        p.glob(paths::home().join(pattern))\n            .map(|p| p.unwrap())\n            .next()\n            .unwrap()\n            .rm_rf();\n    }\n\n    // Clean should update the db.\n    p.cargo(\"clean gc -v --max-download-size=1GB -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVED] 0 files\n\n\"#]])\n        .run();\n\n    // Verify\n    let crates = tracker.registry_crate_all().unwrap();\n    assert_eq!(crates.len(), 1);\n    let srcs = tracker.registry_src_all().unwrap();\n    assert_eq!(srcs.len(), 1);\n}\n\n#[cargo_test]\nfn offline_doesnt_auto_gc() {\n    // When running offline, auto-gc shouldn't run.\n    let p = basic_foo_bar_project();\n    p.cargo(\"fetch\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n    // Remove the dependency.\n    p.change_file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"));\n    // Run offline, make sure it doesn't delete anything\n    p.cargo(\"check --offline\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert_eq!(get_registry_names(\"src\"), [\"bar-1.0.0\"]);\n    assert_eq!(get_registry_names(\"cache\"), [\"bar-1.0.0.crate\"]);\n    // Run online, make sure auto-gc runs.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert_eq!(get_registry_names(\"src\"), &[] as &[String]);\n    assert_eq!(get_registry_names(\"cache\"), &[] as &[String]);\n}\n\n#[cargo_test]\nfn can_handle_future_schema() -> anyhow::Result<()> {\n    // It should work when a future version of cargo has made schema changes\n    // to the database.\n    let p = basic_foo_bar_project();\n    p.cargo(\"fetch\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n    // Modify the schema to pretend this is done by a future version of cargo.\n    let gctx = GlobalContextBuilder::new().build();\n    let db_path = GlobalCacheTracker::db_path(&gctx).into_path_unlocked();\n    let conn = rusqlite::Connection::open(&db_path)?;\n    let user_version: u32 =\n        conn.query_row(\"SELECT user_version FROM pragma_user_version\", [], |row| {\n            row.get(0)\n        })?;\n    conn.execute(\"ALTER TABLE global_data ADD COLUMN foo DEFAULT 123\", [])?;\n    conn.pragma_update(None, \"user_version\", &(user_version + 1))?;\n    drop(conn);\n    // Verify it doesn't blow up.\n    p.cargo(\"clean gc --max-download-size=0 -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    Ok(())\n}\n\n#[cargo_test]\nfn clean_max_git_age() {\n    // --max-git-*-age flags\n    let (git_a, git_a_repo) = git::new_repo(\"git_a\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"git_a\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                git_a = {{ git = '{}' }}\n            \"#,\n                git_a.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    // Populate last-use tracking.\n    p.cargo(\"fetch\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", days_ago_unix(4))\n        .run();\n    // Update git_a to create a separate checkout.\n    git_a.change_file(\"src/lib.rs\", \"// test\");\n    git::add(&git_a_repo);\n    git::commit(&git_a_repo);\n    // Update last-use tracking, where the first git checkout will stay \"old\".\n    p.cargo(\"update -p git_a\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", days_ago_unix(2))\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/git_a`\n[LOCKING] 1 package to latest compatible version\n[UPDATING] git_a v1.0.0 ([ROOTURL]/git_a#[..]) -> #[..]\n\n\"#]])\n        .run();\n\n    let db_names = get_git_db_names();\n    assert_eq!(db_names.len(), 1);\n    let db_name = &db_names[0];\n    let co_names = get_git_checkout_names(&db_name);\n    assert_eq!(co_names.len(), 2);\n\n    // Delete the first checkout\n    p.cargo(\"clean gc -v -Zgc\")\n        .arg(\"--max-git-co-age=3 days\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/git/checkouts/git_a-[HASH]/[..]\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n\n    let db_names = get_git_db_names();\n    assert_eq!(db_names.len(), 1);\n    let co_names = get_git_checkout_names(&db_name);\n    assert_eq!(co_names.len(), 1);\n\n    // delete the second checkout\n    p.cargo(\"clean gc -v -Zgc\")\n        .arg(\"--max-git-co-age=0 days\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/git/checkouts/git_a-[HASH]/[..]\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n\n    let db_names = get_git_db_names();\n    assert_eq!(db_names.len(), 1);\n    let co_names = get_git_checkout_names(&db_name);\n    assert_eq!(co_names.len(), 0);\n\n    // delete the db\n    p.cargo(\"clean gc -v -Zgc\")\n        .arg(\"--max-git-db-age=1 days\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/git/db/git_a-[HASH]\n[REMOVING] [ROOT]/home/.cargo/git/checkouts/git_a-[HASH]\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n\n    let db_names = get_git_db_names();\n    assert_eq!(db_names.len(), 0);\n    let co_names = get_git_checkout_names(&db_name);\n    assert_eq!(co_names.len(), 0);\n}\n\n#[cargo_test]\nfn clean_max_src_crate_age() {\n    // --max-src-age and --max-crate-age flags\n    let p = basic_foo_bar_project();\n    // Populate last-use tracking.\n    p.cargo(\"fetch\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", days_ago_unix(4))\n        .run();\n    // Update bar to create a separate copy with a different timestamp.\n    Package::new(\"bar\", \"1.0.1\").publish();\n    p.cargo(\"update -p bar\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", days_ago_unix(2))\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v1.0.0 -> v1.0.1\n\n\"#]])\n        .run();\n    p.cargo(\"fetch\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", days_ago_unix(2))\n        .with_stderr_data(str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.1 (registry `dummy-registry`)\n\n\"#]])\n        .run();\n\n    assert_eq!(get_registry_names(\"src\"), [\"bar-1.0.0\", \"bar-1.0.1\"]);\n    assert_eq!(\n        get_registry_names(\"cache\"),\n        [\"bar-1.0.0.crate\", \"bar-1.0.1.crate\"]\n    );\n\n    // Delete the old src.\n    p.cargo(\"clean gc -v -Zgc\")\n        .arg(\"--max-src-age=3 days\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n\n    // delete the second src\n    p.cargo(\"clean gc -v -Zgc\")\n        .arg(\"--max-src-age=0 days\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.1\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n\n    // delete the old crate\n    p.cargo(\"clean gc -v -Zgc\")\n        .arg(\"--max-crate-age=3 days\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/registry/cache/-[HASH]/bar-1.0.0.crate\n[REMOVED] 1 file, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n\n    // delete the seecond crate\n    p.cargo(\"clean gc -v -Zgc\")\n        .arg(\"--max-crate-age=0 days\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/registry/cache/-[HASH]/bar-1.0.1.crate\n[REMOVED] 1 file, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn clean_max_git_size() {\n    // clean --max-git-size\n    //\n    // Creates two checkouts. The sets a size threshold to delete one. And\n    // then with 0 max size to delete everything.\n    let (git_project, git_repo) = git::new_repo(\"bar\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = {{ git = '{}' }}\n            \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    // Fetch and populate db.\n    p.cargo(\"fetch\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", days_ago_unix(3))\n        .run();\n\n    // Figure out the name of the first checkout.\n    let git_root = paths::home().join(\".cargo/git\");\n    let db_names = get_git_db_names();\n    assert_eq!(db_names.len(), 1);\n    let db_name = &db_names[0];\n    let co_names = get_git_checkout_names(&db_name);\n    assert_eq!(co_names.len(), 1);\n    let first_co_name = &co_names[0];\n\n    // Make an update and create a new checkout.\n    git_project.change_file(\"src/lib.rs\", \"// modified\");\n    git::add(&git_repo);\n    git::commit(&git_repo);\n    p.cargo(\"update\")\n        // Use a different time so that the first checkout timestamp is less\n        // than the second.\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", days_ago_unix(2))\n        .run();\n\n    // Figure out the threshold to use.\n    let mut co_names = get_git_checkout_names(&db_name);\n    assert_eq!(co_names.len(), 2);\n    co_names.retain(|name| name != first_co_name);\n    assert_eq!(co_names.len(), 1);\n    let second_co_name = &co_names[0];\n    let second_co_path = git_root\n        .join(\"checkouts\")\n        .join(db_name)\n        .join(second_co_name);\n    let second_co_size = cargo_util::du(&second_co_path, &[\"!.git\"]).unwrap();\n\n    let db_size = cargo_util::du(&git_root.join(\"db\").join(db_name), &[]).unwrap();\n\n    let threshold = db_size + second_co_size;\n\n    p.cargo(&format!(\"clean gc --max-git-size={threshold} -Zgc -v\"))\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(&format!(\n            \"\\\n[REMOVING] [ROOT]/home/.cargo/git/checkouts/bar-[HASH]/{first_co_name}\n[REMOVED] [..]\n\"\n        ))\n        .run();\n\n    // And then try cleaning everything.\n    p.cargo(\"clean gc --max-git-size=0 -Zgc -v\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(\n            format!(\n                \"\\\n[REMOVING] [ROOT]/home/.cargo/git/checkouts/bar-[HASH]/{second_co_name}\n[REMOVING] [ROOT]/home/.cargo/git/db/bar-[HASH]\n[REMOVED] [..]\n\"\n            )\n            .unordered(),\n        )\n        .run();\n}\n\n// Helper for setting up fake git sizes for git size cleaning.\nfn setup_fake_git_sizes(db_name: &str, db_size: usize, co_sizes: &[usize]) {\n    let base_git = paths::home().join(\".cargo/git\");\n    let db_path = base_git.join(\"db\").join(db_name);\n    db_path.mkdir_p();\n    std::fs::write(db_path.join(\"test\"), \"x\".repeat(db_size)).unwrap();\n    let base_co = base_git.join(\"checkouts\").join(db_name);\n    for (i, size) in co_sizes.iter().enumerate() {\n        let co_name = format!(\"co{i}\");\n        let co_path = base_co.join(co_name);\n        co_path.mkdir_p();\n        std::fs::write(co_path.join(\"test\"), \"x\".repeat(*size)).unwrap();\n    }\n}\n\n#[cargo_test]\nfn clean_max_git_size_untracked() {\n    // If there are git directories that aren't tracked in the database,\n    // `--max-git-size` should pick it up.\n    //\n    // The db_name of \"example\" depends on the sorting order of the names (\"e\"\n    // should be after \"c\"), so that the db comes after the checkouts.\n    setup_fake_git_sizes(\"example\", 5000, &[1000, 2000]);\n    cargo_process(&format!(\"clean gc -Zgc -v --max-git-size=7000\"))\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/git/checkouts/example/co0\n[REMOVED] 1 file, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    cargo_process(&format!(\"clean gc -Zgc -v --max-git-size=5000\"))\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/git/checkouts/example/co1\n[REMOVED] 1 file, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    cargo_process(&format!(\"clean gc -Zgc -v --max-git-size=0\"))\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/git/db/example\n[REMOVED] 1 file, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn clean_max_git_size_deletes_co_from_db() {\n    // In the scenario where it thinks it needs to delete the db, it should\n    // also delete all the checkouts.\n    //\n    // The db_name of \"abc\" depends on the sorting order of the names (\"a\"\n    // should be before \"c\"), so that the db comes before the checkouts.\n    setup_fake_git_sizes(\"abc\", 5000, &[1000, 2000]);\n    // This deletes everything because it tries to delete the db, which then\n    // deletes all checkouts.\n    cargo_process(&format!(\"clean gc -Zgc -v --max-git-size=3000\"))\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/git/db/abc\n[REMOVING] [ROOT]/home/.cargo/git/checkouts/abc/co1\n[REMOVING] [ROOT]/home/.cargo/git/checkouts/abc/co0\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn handles_missing_index() {\n    // Checks behavior when index is missing.\n    let p = basic_foo_bar_project();\n    p.cargo(\"fetch\").run();\n    paths::home().join(\".cargo/registry/index\").rm_rf();\n    cargo_process(\"clean gc -v --max-download-size=0 -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(\n            str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/registry/cache/-[HASH]\n[REMOVING] [ROOT]/home/.cargo/registry/src/-[HASH]\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn handles_missing_git_db() {\n    // Checks behavior when git db is missing.\n    let git_project = git::new(\"bar\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = {{ git = '{}' }}\n            \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\").run();\n    paths::home().join(\".cargo/git/db\").rm_rf();\n    cargo_process(\"clean gc -v --max-git-size=0 -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/git/checkouts/bar-[HASH]\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn clean_gc_quiet_is_quiet() {\n    // Checks that --quiet works with `cargo clean gc`, since there was a\n    // subtle issue with how the flag is defined as a global flag.\n    let p = basic_foo_bar_project();\n    p.cargo(\"fetch\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n    p.cargo(\"clean gc --quiet -Zgc --dry-run\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stdout_data(\"\")\n        .with_stderr_data(\"\")\n        .run();\n    // Verify exact same command without -q would actually display something.\n    p.cargo(\"clean gc -Zgc --dry-run\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total\n[WARNING] no files deleted due to --dry-run\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(requires_rustup_stable)]\nfn compatible_with_older_cargo() {\n    // Ensures that db stays backwards compatible across versions.\n\n    // T-4 months: Current version, build the database.\n    Package::new(\"old\", \"1.0.0\").publish();\n    Package::new(\"middle\", \"1.0.0\").publish();\n    Package::new(\"new\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                old = \"1.0\"\n                middle = \"1.0\"\n                new = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    // Populate the last-use data.\n    p.cargo(\"check\")\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n    assert_eq!(\n        get_registry_names(\"src\"),\n        [\"middle-1.0.0\", \"new-1.0.0\", \"old-1.0.0\"]\n    );\n    assert_eq!(\n        get_registry_names(\"cache\"),\n        [\"middle-1.0.0.crate\", \"new-1.0.0.crate\", \"old-1.0.0.crate\"]\n    );\n\n    // T-2 months: Stable version, make sure it reads and deletes old src.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            new = \"1.0\"\n            middle = \"1.0\"\n        \"#,\n    );\n    rustup_cargo()\n        .args(&[\"+stable\", \"check\"])\n        .cwd(p.root())\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(2))\n        .run();\n    assert_eq!(get_registry_names(\"src\"), [\"middle-1.0.0\", \"new-1.0.0\"]);\n    assert_eq!(\n        get_registry_names(\"cache\"),\n        [\"middle-1.0.0.crate\", \"new-1.0.0.crate\", \"old-1.0.0.crate\"]\n    );\n\n    // T-0 months: Current version, make sure it can read data from stable,\n    // deletes old crate and middle src.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            new = \"1.0\"\n        \"#,\n    );\n    p.cargo(\"check\").run();\n    assert_eq!(get_registry_names(\"src\"), [\"new-1.0.0\"]);\n    assert_eq!(\n        get_registry_names(\"cache\"),\n        [\"middle-1.0.0.crate\", \"new-1.0.0.crate\"]\n    );\n}\n\n#[cargo_test(requires_rustup_stable)]\nfn forward_compatible() {\n    // Checks that db created in an older version can be read in a newer version.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let git_project = git::new(\"from_git\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"from_git\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n\n                    [dependencies]\n                    bar = \"1.0.0\"\n                    from_git = {{ git = '{}' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    rustup_cargo()\n        .args(&[\"+stable\", \"check\"])\n        .cwd(p.root())\n        .run();\n\n    let config = GlobalContextBuilder::new().build();\n    let lock = config\n        .acquire_package_cache_lock(CacheLockMode::MutateExclusive)\n        .unwrap();\n    let tracker = GlobalCacheTracker::new(&config).unwrap();\n    // Don't want to check the actual index name here, since although the\n    // names are semi-stable, they might change over long periods of time.\n    let indexes = tracker.registry_index_all().unwrap();\n    assert_eq!(indexes.len(), 1);\n    let crates = tracker.registry_crate_all().unwrap();\n    let names: Vec<_> = crates\n        .iter()\n        .map(|(krate, _timestamp)| krate.crate_filename)\n        .collect();\n    assert_eq!(names, &[\"bar-1.0.0.crate\"]);\n    let srcs = tracker.registry_src_all().unwrap();\n    let names: Vec<_> = srcs\n        .iter()\n        .map(|(src, _timestamp)| src.package_dir)\n        .collect();\n    assert_eq!(names, &[\"bar-1.0.0\"]);\n    let dbs: Vec<_> = tracker.git_db_all().unwrap();\n    assert_eq!(dbs.len(), 1);\n    let cos: Vec<_> = tracker.git_checkout_all().unwrap();\n    assert_eq!(cos.len(), 1);\n    drop(lock);\n}\n\n#[cargo_test]\nfn resilient_to_unexpected_files() {\n    // Tests that it doesn't choke on unexpected files.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let git_project = git::new(\"from_git\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"from_git\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n\n                    [dependencies]\n                    bar = \"1.0.0\"\n                    from_git = {{ git = '{}' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .env(\"__CARGO_TEST_LAST_USE_NOW\", months_ago_unix(4))\n        .run();\n\n    let root = paths::home().join(\".cargo\");\n    std::fs::write(root.join(\"registry/index/foo\"), \"\").unwrap();\n    std::fs::write(root.join(\"registry/cache/foo\"), \"\").unwrap();\n    std::fs::write(root.join(\"registry/src/foo\"), \"\").unwrap();\n    std::fs::write(root.join(\"git/db/foo\"), \"\").unwrap();\n    std::fs::write(root.join(\"git/checkouts/foo\"), \"\").unwrap();\n\n    p.cargo(\"clean gc -Zgc\")\n        .masquerade_as_nightly_cargo(&[\"gc\"])\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/help.rs",
    "content": "//! Tests for cargo's help output.\n\nuse std::fs;\nuse std::path::Path;\nuse std::str::from_utf8;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_manifest, paths, project};\n\n#[cargo_test]\nfn help() {\n    cargo_process(\"\").run();\n    cargo_process(\"help\").run();\n    cargo_process(\"-h\").run();\n    cargo_process(\"help build\").run();\n    cargo_process(\"build -h\").run();\n    cargo_process(\"help help\").run();\n}\n\n#[cargo_test]\nfn help_external_subcommand() {\n    // Check that `help external-subcommand` forwards the --help flag to the\n    // given subcommand.\n    Package::new(\"cargo-fake-help\", \"1.0.0\")\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                if ::std::env::args().nth(2) == Some(String::from(\"--help\")) {\n                    println!(\"fancy help output\");\n                }\n            }\n            \"#,\n        )\n        .publish();\n    cargo_process(\"install cargo-fake-help\").run();\n    cargo_process(\"help fake-help\")\n        .with_stdout_data(str![[r#\"\nfancy help output\n\n\"#]])\n        .run();\n}\n\nfn help_with_man(display_command: &str) {\n    // Build a \"man\" process that just echoes the contents.\n    let p = project()\n        .at(display_command)\n        .file(\"Cargo.toml\", &basic_manifest(display_command, \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            &r#\"\n                fn main() {\n                    eprintln!(\"custom __COMMAND__\");\n                    let path = std::env::args().skip(1).next().unwrap();\n                    let mut f = std::fs::File::open(path).unwrap();\n                    std::io::copy(&mut f, &mut std::io::stdout()).unwrap();\n                }\n            \"#\n            .replace(\"__COMMAND__\", display_command),\n        )\n        .build();\n    p.cargo(\"build\").run();\n\n    help_with_man_and_path(display_command, \"build\", \"build\", &p.target_debug_dir());\n}\n\nfn help_with_man_and_path(\n    display_command: &str,\n    subcommand: &str,\n    actual_subcommand: &str,\n    path: &Path,\n) {\n    let contents = if display_command == \"man\" {\n        fs::read_to_string(format!(\"src/etc/man/cargo-{}.1\", actual_subcommand)).unwrap()\n    } else {\n        fs::read_to_string(format!(\n            \"src/doc/man/generated_txt/cargo-{}.txt\",\n            actual_subcommand\n        ))\n        .unwrap()\n    };\n\n    let output = cargo_process(&format!(\"help {subcommand}\"))\n        .env(\"PATH\", path)\n        .run();\n    let stderr = from_utf8(&output.stderr).unwrap();\n    if display_command.is_empty() {\n        assert_eq!(stderr, \"\");\n    } else {\n        assert_eq!(stderr, format!(\"custom {}\\n\", display_command));\n    }\n    let stdout = from_utf8(&output.stdout).unwrap();\n    assert_eq!(stdout, contents);\n}\n\nfn help_with_stdout_and_path(subcommand: &str, path: &Path) -> String {\n    let output = cargo_process(&format!(\"help {subcommand}\"))\n        .env(\"PATH\", path)\n        .run();\n    let stderr = from_utf8(&output.stderr).unwrap();\n    assert_eq!(stderr, \"\");\n    let stdout = from_utf8(&output.stdout).unwrap();\n    stdout.to_string()\n}\n\n#[cargo_test]\nfn help_man() {\n    // Checks that `help command` displays the man page using the given command.\n    help_with_man(\"man\");\n    help_with_man(\"less\");\n    help_with_man(\"more\");\n\n    // Check with no commands in PATH.\n    help_with_man_and_path(\"\", \"build\", \"build\", Path::new(\"\"));\n}\n\n#[cargo_test]\nfn help_alias() {\n    // Check that `help some_alias` will resolve.\n    help_with_man_and_path(\"\", \"b\", \"build\", Path::new(\"\"));\n\n    let config = paths::root().join(\".cargo/config.toml\");\n    fs::create_dir_all(config.parent().unwrap()).unwrap();\n    fs::write(\n        config,\n        r#\"\n            [alias]\n            empty-alias   = \"\"\n            simple-alias  = \"build\"\n            complex-alias = [\"build\", \"--release\"]\n        \"#,\n    )\n    .unwrap();\n\n    // The `empty-alias` returns an error.\n    cargo_process(\"help empty-alias\")\n        .env(\"PATH\", Path::new(\"\"))\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no such command: `empty-alias`\n\n[HELP] a command with a similar name exists: `empty-alias`\n\n[HELP] view all installed commands with `cargo --list`\n[HELP] find a package to install `empty-alias` with `cargo search cargo-empty-alias`\n\n\"#]])\n        .run();\n\n    // Because `simple-alias` aliases a subcommand with no arguments, help shows the manpage.\n    help_with_man_and_path(\"\", \"simple-alias\", \"build\", Path::new(\"\"));\n\n    // Help for `complex-alias` displays the full alias command.\n    let out = help_with_stdout_and_path(\"complex-alias\", Path::new(\"\"));\n    assert_eq!(out, \"`complex-alias` is aliased to `build --release`\\n\");\n}\n"
  },
  {
    "path": "tests/testsuite/hints.rs",
    "content": "//! Tests for hints.\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{project, str};\n\n#[cargo_test]\nfn empty_hints_no_warn() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [hints]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unknown_hints_warn() {\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n\n            [hints]\n            this-is-an-unknown-hint = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"1.0\"\n\n            [hints]\n            this-is-an-unknown-hint = true\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused manifest key: hints.this-is-an-unknown-hint\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] bar v1.0.0\n[RUNNING] `rustc --crate-name bar [..]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn hint_unknown_type_warn() {\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n\n            [hints]\n            mostly-unused = 1\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"1.0\"\n\n            [hints]\n            mostly-unused = \"string\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[WARNING] foo@0.0.1: ignoring unsupported value type (string) for 'hints.mostly-unused', which expects a boolean\n[CHECKING] bar v1.0.0\n[RUNNING] `rustc --crate-name bar [..]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stderr_does_not_contain(\"-Zhint-mostly-unused\")\n        .run();\n}\n\n#[cargo_test]\nfn hints_mostly_unused_warn_without_gate() {\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n\n            [hints]\n            mostly-unused = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"1.0\"\n\n            [hints]\n            mostly-unused = true\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[WARNING] foo@0.0.1: ignoring 'hints.mostly-unused', pass `-Zprofile-hint-mostly-unused` to enable it\n[CHECKING] bar v1.0.0\n[RUNNING] `rustc --crate-name bar [..]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stderr_does_not_contain(\"-Zhint-mostly-unused\")\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zhint-mostly-unused is unstable\")]\nfn hints_mostly_unused_nightly() {\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n\n            [hints]\n            mostly-unused = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Zprofile-hint-mostly-unused -v\")\n        .masquerade_as_nightly_cargo(&[\"profile-hint-mostly-unused\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] bar v1.0.0\n[RUNNING] `rustc --crate-name bar [..] -Zhint-mostly-unused [..]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stderr_does_not_contain(\n            \"[RUNNING] `rustc --crate-name foo [..] -Zhint-mostly-unused [..]\",\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zhint-mostly-unused is unstable\")]\nfn mostly_unused_profile_overrides_hints_nightly() {\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n\n            [hints]\n            mostly-unused = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"1.0\"\n\n            [profile.dev.package.bar]\n            hint-mostly-unused = false\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Zprofile-hint-mostly-unused -v\")\n        .masquerade_as_nightly_cargo(&[\"profile-hint-mostly-unused\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] bar v1.0.0\n[RUNNING] `rustc --crate-name bar [..]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stderr_does_not_contain(\"-Zhint-mostly-unused\")\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zhint-mostly-unused is unstable\")]\nfn mostly_unused_profile_overrides_hints_on_self_nightly() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [hints]\n            mostly-unused = true\n\n            [profile.dev]\n            hint-mostly-unused = false\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stderr_does_not_contain(\"-Zhint-mostly-unused\")\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/https.rs",
    "content": "//! Network tests for https transport.\n//!\n//! Note that these tests will generally require setting `CARGO_CONTAINER_TESTS`\n//! or `CARGO_PUBLIC_NETWORK_TESTS`.\n\nuse crate::prelude::*;\nuse cargo_test_support::containers::Container;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test(container_test)]\nfn self_signed_should_fail() {\n    // Cargo should not allow a connection to a self-signed certificate.\n    let apache = Container::new(\"apache\").launch();\n    let port = apache.port_mappings[&443];\n    let url = format!(\"https://127.0.0.1:{port}/repos/bar.git\");\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    bar = {{ git = \"{url}\" }}\n                \"#\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    // I think the text here depends on the curl backend.\n    let err_msg = if cfg!(target_os = \"macos\") {\n        \"untrusted connection error; class=Ssl (16)[..]\"\n    } else if cfg!(unix) {\n        \"the SSL certificate is invalid; class=Ssl (16)[..]\"\n    } else if cfg!(windows) {\n        \"user cancelled certificate check; class=Http (34); code=Certificate (-17)\"\n    } else {\n        panic!(\"target not supported\");\n    };\n    p.cargo(\"fetch\")\n        .with_status(101)\n        .with_stderr_data(&format!(\n            \"\\\n[UPDATING] git repository `https://127.0.0.1:[..]/repos/bar.git`\n[ERROR] failed to get `bar` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update https://127.0.0.1:[..]/repos/bar.git\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH]\n\nCaused by:\n  network failure seems to have happened\n  if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\n  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\n\nCaused by:\n  {err_msg}\n\"\n        ))\n        .run();\n}\n\n#[cargo_test(container_test)]\nfn self_signed_with_cacert() {\n    // When using cainfo, that should allow a connection to a self-signed cert.\n\n    if cfg!(target_os = \"macos\") {\n        // This test only seems to work with the\n        // curl-sys/force-system-lib-on-osx feature enabled. For some reason\n        // SecureTransport doesn't seem to like the self-signed certificate.\n        // It works if the certificate is manually approved via Keychain\n        // Access. The system libcurl is built with a LibreSSL fallback which\n        // is used when CAINFO is set, which seems to work correctly. This\n        // could use some more investigation. The official Rust binaries use\n        // curl-sys/force-system-lib-on-osx so it is mostly an issue for local\n        // testing.\n        //\n        // The error is:\n        // [60] SSL peer certificate or SSH remote key was not OK (SSL:\n        // certificate verification failed (result: 5)); class=Net (12)\n        let curl_v = curl::Version::get();\n        if curl_v.vendored() {\n            eprintln!(\n                \"vendored curl not supported on macOS, \\\n                set curl-sys/force-system-lib-on-osx to enable\"\n            );\n            return;\n        }\n    }\n\n    let apache = Container::new(\"apache\").launch();\n    let port = apache.port_mappings[&443];\n    let url = format!(\"https://127.0.0.1:{port}/repos/bar.git\");\n    let server_crt = apache.read_file(\"/usr/local/apache2/conf/server.crt\");\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    bar = {{ git = \"{url}\" }}\n                \"#\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [http]\n                    cainfo = \"server.crt\"\n                \"#\n            ),\n        )\n        .file(\"server.crt\", &server_crt)\n        .build();\n    p.cargo(\"fetch\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `https://127.0.0.1:[..]/repos/bar.git`\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(public_network_test)]\nfn github_works() {\n    // Check that an https connection to github.com works.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bitflags = { git = \"https://github.com/rust-lang/bitflags.git\", tag=\"1.3.2\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `https://github.com/rust-lang/bitflags.git`\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/inheritable_workspace_fields.rs",
    "content": "//! Tests for inheriting Cargo.toml fields with field.workspace = true\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::{Dependency, Package, RegistryBuilder};\nuse cargo_test_support::{\n    basic_lib_manifest, basic_manifest, git, paths, project, publish, registry, str,\n};\n\n#[cargo_test]\nfn permit_additional_workspace_fields() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"bar\"]\n            [workspace.package]\n            version = \"1.2.3\"\n            authors = [\"Rustaceans\"]\n            description = \"This is a crate\"\n            documentation = \"https://www.rust-lang.org/learn\"\n            readme = \"README.md\"\n            homepage = \"https://www.rust-lang.org\"\n            repository = \"https://github.com/example/example\"\n            license = \"MIT\"\n            license-file = \"LICENSE\"\n            keywords = [\"cli\"]\n            categories = [\"development-tools\"]\n            publish = false\n            edition = \"2018\"\n            rust-version = \"1.60\"\n            exclude = [\"foo.txt\"]\n            include = [\"bar.txt\", \"**/*.rs\", \"Cargo.toml\", \"LICENSE\", \"README.md\"]\n\n            [workspace.dependencies]\n            dep = \"0.1\"\n        \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n              [package]\n              name = \"bar\"\n              version = \"0.1.0\"\n              edition = \"2015\"\n              authors = []\n              workspace = \"..\"\n              \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        // Should not warn about unused fields.\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\").run();\n    let lockfile = p.read_lockfile();\n    assert!(!lockfile.contains(\"dep\"));\n}\n\n#[cargo_test]\nfn deny_optional_dependencies() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"bar\"]\n\n            [workspace.dependencies]\n            dep1 = { version = \"0.1\", optional = true }\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n              [package]\n              name = \"bar\"\n              version = \"0.1.0\"\n              edition = \"2015\"\n              authors = []\n              workspace = \"..\"\n              \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  dep1 is optional, but workspace dependencies cannot be optional\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inherit_own_workspace_fields() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project().build();\n\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version.workspace = true\n            authors.workspace = true\n            description.workspace = true\n            documentation.workspace = true\n            homepage.workspace = true\n            repository.workspace = true\n            license.workspace = true\n            keywords.workspace = true\n            categories.workspace = true\n            publish.workspace = true\n            edition.workspace = true\n            rust-version.workspace = true\n            exclude.workspace = true\n            include.workspace = true\n\n            [workspace]\n            members = []\n            [workspace.package]\n            version = \"1.2.3\"\n            authors = [\"Rustaceans\"]\n            description = \"This is a crate\"\n            documentation = \"https://www.rust-lang.org/learn\"\n            homepage = \"https://www.rust-lang.org\"\n            repository = \"https://github.com/example/example\"\n            license = \"MIT\"\n            keywords = [\"cli\"]\n            categories = [\"development-tools\"]\n            publish = true\n            edition = \"2018\"\n            rust-version = \"1.60\"\n            exclude = [\"foo.txt\"]\n            include = [\"bar.txt\", \"**/*.rs\", \"Cargo.toml\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"foo.txt\", \"\") // should be ignored when packaging\n        .file(\"bar.txt\", \"\") // should be included when packaging\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] both package.include and package.exclude are specified; the exclude list will be ignored\n[PACKAGING] foo v1.2.3 ([ROOT]/foo)\n[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v1.2.3 ([ROOT]/foo)\n[COMPILING] foo v1.2.3 ([ROOT]/foo/target/package/foo-1.2.3)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v1.2.3 ([ROOT]/foo)\n[UPLOADED] foo v1.2.3 to registry `crates-io`\n[NOTE] waiting for foo v1.2.3 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v1.2.3 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    publish::validate_upload_with_contents(\n        r#\"\n        {\n          \"authors\": [\"Rustaceans\"],\n          \"badges\": {},\n          \"categories\": [\"development-tools\"],\n          \"deps\": [],\n          \"description\": \"This is a crate\",\n          \"documentation\": \"https://www.rust-lang.org/learn\",\n          \"features\": {},\n          \"homepage\": \"https://www.rust-lang.org\",\n          \"keywords\": [\"cli\"],\n          \"license\": \"MIT\",\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"foo\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": \"https://github.com/example/example\",\n          \"rust_version\": \"1.60\",\n          \"vers\": \"1.2.3\"\n          }\n        \"#,\n        \"foo-1.2.3.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/main.rs\",\n            \".cargo_vcs_info.json\",\n            \"bar.txt\",\n        ],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2018\"\nrust-version = \"1.60\"\nname = \"foo\"\nversion = \"1.2.3\"\nauthors = [\"Rustaceans\"]\nbuild = false\nexclude = [\"foo.txt\"]\ninclude = [\n    \"bar.txt\",\n    \"**/*.rs\",\n    \"Cargo.toml\",\n]\npublish = true\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"This is a crate\"\nhomepage = \"https://www.rust-lang.org\"\ndocumentation = \"https://www.rust-lang.org/learn\"\nreadme = false\nkeywords = [\"cli\"]\ncategories = [\"development-tools\"]\nlicense = \"MIT\"\nrepository = \"https://github.com/example/example\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn inherit_own_dependencies() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            dep.workspace = true\n\n            [build-dependencies]\n            dep-build.workspace = true\n\n            [dev-dependencies]\n            dep-dev.workspace = true\n\n            [workspace]\n            members = []\n\n            [workspace.dependencies]\n            dep = \"0.1\"\n            dep-build = \"0.8\"\n            dep-dev = \"0.5.2\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"dep\", \"0.1.2\").publish();\n    Package::new(\"dep-build\", \"0.8.2\").publish();\n    Package::new(\"dep-dev\", \"0.5.2\").publish();\n\n    p.cargo(\"check\")\n        // Unordered because the download order is nondeterministic.\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v0.1.2 (registry `dummy-registry`)\n[DOWNLOADED] dep-build v0.8.2 (registry `dummy-registry`)\n[CHECKING] dep v0.1.2\n[CHECKING] bar v0.2.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"check\").run();\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"dep\"));\n    assert!(lockfile.contains(\"dep-dev\"));\n    assert!(lockfile.contains(\"dep-build\"));\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] bar v0.2.0 ([ROOT]/foo)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] bar v0.2.0 ([ROOT]/foo)\n[COMPILING] dep v0.1.2\n[COMPILING] bar v0.2.0 ([ROOT]/foo/target/package/bar-0.2.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] bar v0.2.0 ([ROOT]/foo)\n[UPLOADED] bar v0.2.0 to registry `crates-io`\n[NOTE] waiting for bar v0.2.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] bar v0.2.0 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    publish::validate_upload_with_contents(\n        r#\"\n        {\n          \"authors\": [],\n          \"badges\": {},\n          \"categories\": [],\n          \"deps\": [\n            {\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"normal\",\n              \"name\": \"dep\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^0.1\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"dev\",\n              \"name\": \"dep-dev\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^0.5.2\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"build\",\n              \"name\": \"dep-build\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^0.8\"\n            }\n          ],\n          \"description\": null,\n          \"documentation\": null,\n          \"features\": {},\n          \"homepage\": null,\n          \"keywords\": [],\n          \"license\": null,\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"bar\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": null,\n          \"rust_version\": null,\n          \"vers\": \"0.2.0\"\n          }\n        \"#,\n        \"bar-0.2.0.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"Cargo.lock\", \"src/main.rs\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"bar\"\nversion = \"0.2.0\"\nauthors = []\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\nreadme = false\n\n[[bin]]\nname = \"bar\"\npath = \"src/main.rs\"\n\n[dependencies.dep]\nversion = \"0.1\"\n\n[dev-dependencies.dep-dev]\nversion = \"0.5.2\"\n\n[build-dependencies.dep-build]\nversion = \"0.8\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn inherit_own_detailed_dependencies() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            dep.workspace = true\n\n            [workspace]\n            members = []\n\n            [workspace.dependencies]\n            dep = { version = \"0.1.2\", features = [\"testing\"] }\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"dep\", \"0.1.2\")\n        .feature(\"testing\", &[])\n        .publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v0.1.2 (registry `dummy-registry`)\n[CHECKING] dep v0.1.2\n[CHECKING] bar v0.2.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\").run();\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"dep\"));\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] bar v0.2.0 ([ROOT]/foo)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] bar v0.2.0 ([ROOT]/foo)\n[COMPILING] dep v0.1.2\n[COMPILING] bar v0.2.0 ([ROOT]/foo/target/package/bar-0.2.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] bar v0.2.0 ([ROOT]/foo)\n[UPLOADED] bar v0.2.0 to registry `crates-io`\n[NOTE] waiting for bar v0.2.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] bar v0.2.0 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    publish::validate_upload_with_contents(\n        r#\"\n        {\n          \"authors\": [],\n          \"badges\": {},\n          \"categories\": [],\n          \"deps\": [\n            {\n              \"default_features\": true,\n              \"features\": [\"testing\"],\n              \"kind\": \"normal\",\n              \"name\": \"dep\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^0.1.2\"\n            }\n          ],\n          \"description\": null,\n          \"documentation\": null,\n          \"features\": {},\n          \"homepage\": null,\n          \"keywords\": [],\n          \"license\": null,\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"bar\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": null,\n          \"rust_version\": null,\n          \"vers\": \"0.2.0\"\n          }\n        \"#,\n        \"bar-0.2.0.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"Cargo.lock\", \"src/main.rs\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"bar\"\nversion = \"0.2.0\"\nauthors = []\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\nreadme = false\n\n[[bin]]\nname = \"bar\"\npath = \"src/main.rs\"\n\n[dependencies.dep]\nversion = \"0.1.2\"\nfeatures = [\"testing\"]\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn inherit_from_own_undefined_field() {\n    registry::init();\n\n    let p = project().build();\n\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.2.5\"\n            edition = \"2015\"\n            authors = [\"rustaceans\"]\n            description.workspace = true\n\n            [workspace]\n            members = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  error inheriting `description` from workspace root manifest's `workspace.package.description`\n\nCaused by:\n  `workspace.package.description` was not defined\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inherited_dependencies_union_features() {\n    Package::new(\"dep\", \"0.1.0\")\n        .feature(\"fancy\", &[\"fancy_dep\"])\n        .feature(\"dancy\", &[\"dancy_dep\"])\n        .add_dep(Dependency::new(\"fancy_dep\", \"0.2\").optional(true))\n        .add_dep(Dependency::new(\"dancy_dep\", \"0.6\").optional(true))\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    Package::new(\"fancy_dep\", \"0.2.4\").publish();\n    Package::new(\"dancy_dep\", \"0.6.8\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n            [dependencies]\n            dep = { workspace = true, features = [\"dancy\"] }\n\n            [workspace]\n            members = []\n            [workspace.dependencies]\n            dep = { version = \"0.1\", features = [\"fancy\"] }\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`)\n[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`)\n[DOWNLOADED] dancy_dep v0.6.8 (registry `dummy-registry`)\n[CHECKING] fancy_dep v0.2.4\n[CHECKING] dancy_dep v0.6.8\n[CHECKING] dep v0.1.0\n[CHECKING] bar v0.2.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"dep\"));\n    assert!(lockfile.contains(\"fancy_dep\"));\n    assert!(lockfile.contains(\"dancy_dep\"));\n}\n\n#[cargo_test]\nfn inherit_workspace_fields() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project().build();\n\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"bar\"]\n            [workspace.package]\n            version = \"1.2.3\"\n            authors = [\"Rustaceans\"]\n            description = \"This is a crate\"\n            documentation = \"https://www.rust-lang.org/learn\"\n            readme = \"README.md\"\n            homepage = \"https://www.rust-lang.org\"\n            repository = \"https://github.com/example/example\"\n            license = \"MIT\"\n            license-file = \"LICENSE\"\n            keywords = [\"cli\"]\n            categories = [\"development-tools\"]\n            publish = true\n            edition = \"2018\"\n            rust-version = \"1.60\"\n            exclude = [\"foo.txt\"]\n            include = [\"bar.txt\", \"**/*.rs\", \"Cargo.toml\", \"LICENSE\", \"README.md\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            workspace = \"..\"\n            version.workspace = true\n            authors.workspace = true\n            description.workspace = true\n            documentation.workspace = true\n            readme.workspace = true\n            homepage.workspace = true\n            repository.workspace = true\n            license.workspace = true\n            license-file.workspace = true\n            keywords.workspace = true\n            categories.workspace = true\n            publish.workspace = true\n            edition.workspace = true\n            rust-version.workspace = true\n            exclude.workspace = true\n            include.workspace = true\n        \"#,\n        )\n        .file(\"LICENSE\", \"license\")\n        .file(\"README.md\", \"README.md\")\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/foo.txt\", \"\") // should be ignored when packaging\n        .file(\"bar/bar.txt\", \"\") // should be included when packaging\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .cwd(\"bar\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] both package.include and package.exclude are specified; the exclude list will be ignored\n[PACKAGING] bar v1.2.3 ([ROOT]/foo/bar)\n[PACKAGED] 8 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] bar v1.2.3 ([ROOT]/foo/bar)\n[WARNING] only one of `license` or `license-file` is necessary\n`license` should be used if the package license can be expressed with a standard SPDX expression.\n`license-file` should be used if the package uses a non-standard license.\nSee https://doc.rust-lang.org/cargo/reference/manifest.html#the-license-and-license-file-fields for more information.\n[COMPILING] bar v1.2.3 ([ROOT]/foo/target/package/bar-1.2.3)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] bar v1.2.3 ([ROOT]/foo/bar)\n[UPLOADED] bar v1.2.3 to registry `crates-io`\n[NOTE] waiting for bar v1.2.3 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] bar v1.2.3 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    publish::validate_upload_with_contents(\n        r#\"\n        {\n          \"authors\": [\"Rustaceans\"],\n          \"badges\": {},\n          \"categories\": [\"development-tools\"],\n          \"deps\": [],\n          \"description\": \"This is a crate\",\n          \"documentation\": \"https://www.rust-lang.org/learn\",\n          \"features\": {},\n          \"homepage\": \"https://www.rust-lang.org\",\n          \"keywords\": [\"cli\"],\n          \"license\": \"MIT\",\n          \"license_file\": \"LICENSE\",\n          \"links\": null,\n          \"name\": \"bar\",\n          \"readme\": \"README.md\",\n          \"readme_file\": \"README.md\",\n          \"repository\": \"https://github.com/example/example\",\n          \"rust_version\": \"1.60\",\n          \"vers\": \"1.2.3\"\n          }\n        \"#,\n        \"bar-1.2.3.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/main.rs\",\n            \"README.md\",\n            \"LICENSE\",\n            \".cargo_vcs_info.json\",\n            \"bar.txt\",\n        ],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2018\"\nrust-version = \"1.60\"\nname = \"bar\"\nversion = \"1.2.3\"\nauthors = [\"Rustaceans\"]\nbuild = false\nexclude = [\"foo.txt\"]\ninclude = [\n    \"bar.txt\",\n    \"**/*.rs\",\n    \"Cargo.toml\",\n    \"LICENSE\",\n    \"README.md\",\n]\npublish = true\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"This is a crate\"\nhomepage = \"https://www.rust-lang.org\"\ndocumentation = \"https://www.rust-lang.org/learn\"\nreadme = \"README.md\"\nkeywords = [\"cli\"]\ncategories = [\"development-tools\"]\nlicense = \"MIT\"\nlicense-file = \"LICENSE\"\nrepository = \"https://github.com/example/example\"\n\n[[bin]]\nname = \"bar\"\npath = \"src/main.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn inherit_dependencies() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"bar\"]\n            [workspace.dependencies]\n            dep = \"0.1\"\n            dep-build = \"0.8\"\n            dep-dev = \"0.5.2\"\n        \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            workspace = \"..\"\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n            [dependencies]\n            dep.workspace = true\n            [build-dependencies]\n            dep-build.workspace = true\n            [dev-dependencies]\n            dep-dev.workspace = true\n        \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"dep\", \"0.1.2\").publish();\n    Package::new(\"dep-build\", \"0.8.2\").publish();\n    Package::new(\"dep-dev\", \"0.5.2\").publish();\n\n    p.cargo(\"check\")\n        // Unordered because the download order is nondeterministic.\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v0.1.2 (registry `dummy-registry`)\n[DOWNLOADED] dep-build v0.8.2 (registry `dummy-registry`)\n[CHECKING] dep v0.1.2\n[CHECKING] bar v0.2.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"check\").run();\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"dep\"));\n    assert!(lockfile.contains(\"dep-dev\"));\n    assert!(lockfile.contains(\"dep-build\"));\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .cwd(\"bar\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] bar v0.2.0 ([ROOT]/foo/bar)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] bar v0.2.0 ([ROOT]/foo/bar)\n[COMPILING] dep v0.1.2\n[COMPILING] bar v0.2.0 ([ROOT]/foo/target/package/bar-0.2.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] bar v0.2.0 ([ROOT]/foo/bar)\n[UPLOADED] bar v0.2.0 to registry `crates-io`\n[NOTE] waiting for bar v0.2.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] bar v0.2.0 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    publish::validate_upload_with_contents(\n        r#\"\n        {\n          \"authors\": [],\n          \"badges\": {},\n          \"categories\": [],\n          \"deps\": [\n            {\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"normal\",\n              \"name\": \"dep\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^0.1\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"dev\",\n              \"name\": \"dep-dev\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^0.5.2\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"build\",\n              \"name\": \"dep-build\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^0.8\"\n            }\n          ],\n          \"description\": null,\n          \"documentation\": null,\n          \"features\": {},\n          \"homepage\": null,\n          \"keywords\": [],\n          \"license\": null,\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"bar\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": null,\n          \"rust_version\": null,\n          \"vers\": \"0.2.0\"\n          }\n        \"#,\n        \"bar-0.2.0.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"Cargo.lock\", \"src/main.rs\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"bar\"\nversion = \"0.2.0\"\nauthors = []\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\nreadme = false\n\n[[bin]]\nname = \"bar\"\npath = \"src/main.rs\"\n\n[dependencies.dep]\nversion = \"0.1\"\n\n[dev-dependencies.dep-dev]\nversion = \"0.5.2\"\n\n[build-dependencies.dep-build]\nversion = \"0.8\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn inherit_target_dependencies() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"bar\"]\n            [workspace.dependencies]\n            dep = \"0.1\"\n        \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            workspace = \"..\"\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n            [target.'cfg(unix)'.dependencies]\n            dep.workspace = true\n            [target.'cfg(windows)'.dependencies]\n            dep.workspace = true\n        \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"dep\", \"0.1.2\").publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v0.1.2 (registry `dummy-registry`)\n[CHECKING] dep v0.1.2\n[CHECKING] bar v0.2.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"dep\"));\n}\n\n#[cargo_test]\nfn inherit_dependency_override_optional() {\n    Package::new(\"dep\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"bar\"]\n            [workspace.dependencies]\n            dep = \"0.1.0\"\n        \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            workspace = \"..\"\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n            [dependencies]\n            dep = { workspace = true, optional = true }\n        \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.2.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inherit_dependency_features() {\n    Package::new(\"dep\", \"0.1.0\")\n        .feature(\"fancy\", &[\"fancy_dep\"])\n        .add_dep(Dependency::new(\"fancy_dep\", \"0.2\").optional(true))\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    Package::new(\"fancy_dep\", \"0.2.4\").publish();\n    Package::new(\"dancy_dep\", \"0.6.8\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n            [dependencies]\n            dep = { workspace = true, features = [\"fancy\"] }\n\n            [workspace]\n            members = []\n            [workspace.dependencies]\n            dep = \"0.1\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`)\n[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`)\n[CHECKING] fancy_dep v0.2.4\n[CHECKING] dep v0.1.0\n[CHECKING] bar v0.2.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"dep\"));\n    assert!(lockfile.contains(\"fancy_dep\"));\n}\n\n#[cargo_test]\nfn inherit_detailed_dependencies() {\n    let git_project = git::new(\"detailed\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"detailed\"))\n            .file(\n                \"src/detailed.rs\",\n                r#\"\n                pub fn hello() -> &'static str {\n                    \"hello world\"\n                }\n            \"#,\n            )\n    });\n\n    // Make a new branch based on the current HEAD commit\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    let head = repo.head().unwrap().target().unwrap();\n    let head = repo.find_commit(head).unwrap();\n    repo.branch(\"branchy\", &head, true).unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n            [workspace]\n            members = [\"bar\"]\n            [workspace.dependencies]\n            detailed = {{ git = '{}', branch = \"branchy\" }}\n        \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            workspace = \"..\"\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n            [dependencies]\n            detailed.workspace = true\n        \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/detailed`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] detailed v0.5.0 ([ROOTURL]/detailed?branch=branchy#[..])\n[CHECKING] bar v0.2.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inherit_path_dependencies() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"bar\"]\n            [workspace.dependencies]\n            dep = { path = \"dep\" }\n        \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            workspace = \"..\"\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n            [dependencies]\n            dep.workspace = true\n        \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"dep/Cargo.toml\", &basic_manifest(\"dep\", \"0.9.0\"))\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] dep v0.9.0 ([ROOT]/foo/dep)\n[CHECKING] bar v0.2.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"dep\"));\n}\n\n#[cargo_test]\nfn error_workspace_false() {\n    registry::init();\n\n    let p = project().build();\n\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            workspace = \"..\"\n            version = \"1.2.3\"\n            edition = \"2015\"\n            authors = [\"rustaceans\"]\n            description = { workspace = false }\n        \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .cwd(\"bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `workspace` cannot be false\n --> Cargo.toml:8:41\n  |\n8 |             description = { workspace = false }\n  |                                         ^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn error_workspace_dependency_looked_for_workspace_itself() {\n    registry::init();\n\n    let p = project().build();\n\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"1.2.3\"\n            edition = \"2015\"\n\n            [dependencies]\n            dep.workspace = true\n\n            [workspace]\n            members = []\n\n            [workspace.dependencies]\n            dep.workspace = true\n\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  dependency (dep) specified without providing a local path, Git repository, version, or workspace dependency to use\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn error_malformed_workspace_root() {\n    registry::init();\n\n    let p = project().build();\n\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [invalid toml\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            workspace = \"..\"\n            version = \"1.2.3\"\n            edition = \"2015\"\n            authors = [\"rustaceans\"]\n        \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .cwd(\"bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unclosed array, expected `]`\n --> ../Cargo.toml:3:36\n  |\n3 |             members = [invalid toml\n  |                                    ^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn error_no_root_workspace() {\n    registry::init();\n\n    let p = project().build();\n\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            workspace = \"..\"\n            version = \"1.2.3\"\n            edition = \"2015\"\n            authors = [\"rustaceans\"]\n            description.workspace = true\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .cwd(\"bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/bar/Cargo.toml`\n\nCaused by:\n  error inheriting `description` from workspace root manifest's `workspace.package.description`\n\nCaused by:\n  root of a workspace inferred but wasn't a root: [ROOT]/foo/Cargo.toml\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn error_inherit_unspecified_dependency() {\n    let p = project().build();\n\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            workspace = \"..\"\n            version = \"1.2.3\"\n            edition = \"2015\"\n            authors = [\"rustaceans\"]\n            [dependencies]\n            foo.workspace = true\n        \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .cwd(\"bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/bar/Cargo.toml`\n\nCaused by:\n  error inheriting `foo` from workspace root manifest's `workspace.dependencies.foo`\n\nCaused by:\n  `workspace.dependencies` was not defined\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warn_inherit_def_feat_true_member_def_feat_false() {\n    Package::new(\"dep\", \"0.1.0\")\n        .feature(\"default\", &[\"fancy_dep\"])\n        .add_dep(Dependency::new(\"fancy_dep\", \"0.2\").optional(true))\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    Package::new(\"fancy_dep\", \"0.2.4\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n            [dependencies]\n            dep = { workspace = true, default-features = false }\n\n            [workspace]\n            members = []\n            [workspace.dependencies]\n            dep = { version = \"0.1.0\", default-features = true }\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] [ROOT]/foo/Cargo.toml: `default-features` is ignored for dep, since `default-features` was true for `workspace.dependencies.dep`, this could become a hard error in the future\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`)\n[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`)\n[CHECKING] fancy_dep v0.2.4\n[CHECKING] dep v0.1.0\n[CHECKING] bar v0.2.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn warn_inherit_def_feat_true_member_def_feat_false_2024_edition() {\n    Package::new(\"dep\", \"0.1.0\")\n        .feature(\"default\", &[\"fancy_dep\"])\n        .add_dep(Dependency::new(\"fancy_dep\", \"0.2\").optional(true))\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    Package::new(\"fancy_dep\", \"0.2.4\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2024\"\n            authors = []\n            [dependencies]\n            dep = { workspace = true, default-features = false }\n\n            [workspace]\n            members = []\n            [workspace.dependencies]\n            dep = { version = \"0.1.0\", default-features = true }\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  error inheriting `dep` from workspace root manifest's `workspace.dependencies.dep`\n\nCaused by:\n  `default-features = false` cannot override workspace's `default-features`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warn_inherit_simple_member_def_feat_false() {\n    Package::new(\"dep\", \"0.1.0\")\n        .feature(\"default\", &[\"fancy_dep\"])\n        .add_dep(Dependency::new(\"fancy_dep\", \"0.2\").optional(true))\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    Package::new(\"fancy_dep\", \"0.2.4\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n            [dependencies]\n            dep = { workspace = true, default-features = false }\n\n            [workspace]\n            members = []\n            [workspace.dependencies]\n            dep = \"0.1.0\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] [ROOT]/foo/Cargo.toml: `default-features` is ignored for dep, since `default-features` was not specified for `workspace.dependencies.dep`, this could become a hard error in the future\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`)\n[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`)\n[CHECKING] fancy_dep v0.2.4\n[CHECKING] dep v0.1.0\n[CHECKING] bar v0.2.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn warn_inherit_simple_member_def_feat_false_2024_edition() {\n    Package::new(\"dep\", \"0.1.0\")\n        .feature(\"default\", &[\"fancy_dep\"])\n        .add_dep(Dependency::new(\"fancy_dep\", \"0.2\").optional(true))\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    Package::new(\"fancy_dep\", \"0.2.4\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2024\"\n            authors = []\n            [dependencies]\n            dep = { workspace = true, default-features = false }\n\n            [workspace]\n            members = []\n            [workspace.dependencies]\n            dep = \"0.1.0\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  error inheriting `dep` from workspace root manifest's `workspace.dependencies.dep`\n\nCaused by:\n  `default-features = false` cannot override workspace's `default-features`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inherit_def_feat_false_member_def_feat_true() {\n    Package::new(\"dep\", \"0.1.0\")\n        .feature(\"default\", &[\"fancy_dep\"])\n        .add_dep(Dependency::new(\"fancy_dep\", \"0.2\").optional(true))\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    Package::new(\"fancy_dep\", \"0.2.4\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n            [dependencies]\n            dep = { workspace = true, default-features = true }\n\n            [workspace]\n            members = []\n            [workspace.dependencies]\n            dep = { version = \"0.1.0\", default-features = false }\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`)\n[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`)\n[CHECKING] fancy_dep v0.2.4\n[CHECKING] dep v0.1.0\n[CHECKING] bar v0.2.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cannot_inherit_in_patch() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = []\n\n            [workspace.dependencies]\n            bar = { path = \"bar\" }\n\n            [package]\n            name = \"foo\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n\n            [patch.crates-io]\n            bar.workspace = true\n\n            [dependencies]\n            bar = \"0.1.0\"\n\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  dependency (bar) specified without providing a local path, Git repository, version, or workspace dependency to use\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warn_inherit_unused_manifest_key_dep() {\n    Package::new(\"dep\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = []\n            [workspace.dependencies]\n            dep = { version = \"0.1\", wxz = \"wxz\" }\n\n            [package]\n            name = \"bar\"\n            version = \"0.2.0\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            dep = { workspace = true, wxz = \"wxz\" }\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: workspace.dependencies.dep.wxz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: dependencies.dep.wxz\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`)\n[CHECKING] dep v0.1.0\n[CHECKING] bar v0.2.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warn_unused_workspace_package_field() {\n    Package::new(\"dep\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = []\n            [workspace.package]\n            name = \"unused\"\n\n            [package]\n            name = \"foo\"\n            edition = \"2015\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: workspace.package.name\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warn_inherit_unused_manifest_key_package() {\n    Package::new(\"dep\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = []\n            [workspace.package]\n            version = \"1.2.3\"\n            authors = [\"Rustaceans\"]\n            description = \"This is a crate\"\n            documentation = \"https://www.rust-lang.org/learn\"\n            homepage = \"https://www.rust-lang.org\"\n            repository = \"https://github.com/example/example\"\n            license = \"MIT\"\n            keywords = [\"cli\"]\n            categories = [\"development-tools\"]\n            publish = true\n            edition = \"2018\"\n            rust-version = \"1.60\"\n            exclude = [\"foo.txt\"]\n            include = [\"bar.txt\", \"**/*.rs\", \"Cargo.toml\"]\n\n            [package]\n            name = \"bar\"\n            version = { workspace = true, xyz = \"abc\"}\n            authors = { workspace = true, xyz = \"abc\"}\n            description = { workspace = true, xyz = \"abc\"}\n            documentation = { workspace = true, xyz = \"abc\"}\n            homepage = { workspace = true, xyz = \"abc\"}\n            repository = { workspace = true, xyz = \"abc\"}\n            license = { workspace = true, xyz = \"abc\"}\n            keywords = { workspace = true, xyz = \"abc\"}\n            categories = { workspace = true, xyz = \"abc\"}\n            publish = { workspace = true, xyz = \"abc\"}\n            edition = { workspace = true, xyz = \"abc\"}\n            rust-version = { workspace = true, xyz = \"abc\"}\n            exclude = { workspace = true, xyz = \"abc\"}\n            include = { workspace = true, xyz = \"abc\"}\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.authors.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.categories.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.description.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.documentation.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.edition.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.exclude.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.homepage.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.include.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.keywords.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.license.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.publish.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.repository.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.rust-version.xyz\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.version.xyz\n[CHECKING] bar v1.2.3 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/install.rs",
    "content": "//! Tests for the `cargo install` command.\n\nuse std::env;\nuse std::fs::{self, OpenOptions};\nuse std::io::prelude::*;\nuse std::path::Path;\nuse std::path::PathBuf;\nuse std::thread;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::cross_compile;\nuse cargo_test_support::git;\nuse cargo_test_support::registry::{self, Package};\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_manifest, project, project_in, symlink_supported, t};\nuse cargo_util::{ProcessBuilder, ProcessError};\n\nuse crate::utils::cross_compile::disabled as cross_compile_disabled;\nuse cargo_test_support::install::{assert_has_installed_exe, assert_has_not_installed_exe, exe};\nuse cargo_test_support::paths::{self, cargo_home};\n\nfn pkg(name: &str, vers: &str) {\n    Package::new(name, vers)\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"src/main.rs\",\n            &format!(\"extern crate {}; fn main() {{}}\", name),\n        )\n        .publish();\n}\n\n#[cargo_test]\nfn simple() {\n    pkg(\"foo\", \"0.0.1\");\n\n    cargo_process(\"install foo\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[INSTALLING] foo v0.0.1\n[COMPILING] foo v0.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]]).run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n\n    cargo_process(\"uninstall foo\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE]\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn install_the_same_version_twice() {\n    pkg(\"foo\", \"0.0.1\");\n\n    cargo_process(\"install foo foo\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[INSTALLING] foo v0.0.1\n[COMPILING] foo v0.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn toolchain() {\n    pkg(\"foo\", \"0.0.1\");\n\n    cargo_process(\"install +nightly\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid character `+` in package name: `+nightly`\n    Use `cargo +nightly install` if you meant to use the `nightly` toolchain.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn url() {\n    pkg(\"foo\", \"0.0.1\");\n    cargo_process(\"install https://github.com/bar/foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid package name: `https://github.com/bar/foo`\n    Use `cargo install --git https://github.com/bar/foo` if you meant to install from a git repository.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_with_message_format() {\n    pkg(\"foo\", \"0.0.1\");\n\n    cargo_process(\"install foo --message-format=json\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[INSTALLING] foo v0.0.1\n[COMPILING] foo v0.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)\n[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"executable\": null,\n    \"features\": [],\n    \"filenames\": \"{...}\",\n    \"fresh\": false,\n    \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/foo-0.0.1/Cargo.toml\",\n    \"package_id\": \"registry+https://github.com/rust-lang/crates.io-index#foo@0.0.1\",\n    \"profile\": \"{...}\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"crate_types\": [\n        \"lib\"\n      ],\n      \"doc\": true,\n      \"doctest\": true,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"lib\"\n      ],\n      \"name\": \"foo\",\n      \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/foo-0.0.1/src/lib.rs\",\n      \"test\": true\n    }\n  },\n  {\n    \"executable\": \"[..]\",\n    \"features\": [],\n    \"filenames\": \"{...}\",\n    \"fresh\": false,\n    \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/foo-0.0.1/Cargo.toml\",\n    \"package_id\": \"registry+https://github.com/rust-lang/crates.io-index#foo@0.0.1\",\n    \"profile\": \"{...}\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"foo\",\n      \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/foo-0.0.1/src/main.rs\",\n      \"test\": true\n    }\n  },\n  {\n    \"reason\": \"build-finished\",\n    \"success\": true\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn with_index() {\n    let registry = registry::init();\n    pkg(\"foo\", \"0.0.1\");\n\n    cargo_process(\"install foo --index\")\n        .arg(registry.index_url().as_str())\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[ROOT]/registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `[ROOT]/registry`)\n[INSTALLING] foo v0.0.1 (registry `[ROOT]/registry`)\n[COMPILING] foo v0.0.1 (registry `[ROOT]/registry`)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1 (registry `[ROOT]/registry`)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n\n    cargo_process(\"uninstall foo\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE]\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn multiple_pkgs() {\n    pkg(\"foo\", \"0.0.1\");\n    pkg(\"bar\", \"0.0.2\");\n\n    cargo_process(\"install foo bar baz\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.2 (registry `dummy-registry`)\n[ERROR] could not find `baz` in registry `crates-io` with version `*`\n[INSTALLING] foo v0.0.1\n[COMPILING] foo v0.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)\n[INSTALLING] bar v0.0.2\n[COMPILING] bar v0.0.2\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/bar[EXE]\n[INSTALLED] package `bar v0.0.2` (executable `bar[EXE]`)\n[SUMMARY] Successfully installed foo, bar! Failed to install baz (see error(s) above).\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n[ERROR] some crates failed to install\n\n\"#]])\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    assert_has_installed_exe(paths::cargo_home(), \"bar\");\n\n    cargo_process(\"uninstall foo bar\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE]\n[REMOVING] [ROOT]/home/.cargo/bin/bar[EXE]\n[SUMMARY] Successfully uninstalled foo, bar!\n\n\"#]])\n        .run();\n\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"bar\");\n}\n\nfn path() -> Vec<PathBuf> {\n    env::split_paths(&env::var_os(\"PATH\").unwrap_or_default()).collect()\n}\n\n#[cargo_test]\nfn multiple_pkgs_path_set() {\n    // confirm partial failure results in 101 status code and does not have the\n    //      '[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries'\n    //  even if CARGO_HOME/bin is in the PATH\n    pkg(\"foo\", \"0.0.1\");\n    pkg(\"bar\", \"0.0.2\");\n\n    // add CARGO_HOME/bin to path\n    let mut path = path();\n    path.push(paths::cargo_home().join(\"bin\"));\n    let new_path = env::join_paths(path).unwrap();\n    cargo_process(\"install foo bar baz\")\n        .env(\"PATH\", new_path)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.2 (registry `dummy-registry`)\n[ERROR] could not find `baz` in registry `crates-io` with version `*`\n[INSTALLING] foo v0.0.1\n[COMPILING] foo v0.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)\n[INSTALLING] bar v0.0.2\n[COMPILING] bar v0.0.2\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/bar[EXE]\n[INSTALLED] package `bar v0.0.2` (executable `bar[EXE]`)\n[SUMMARY] Successfully installed foo, bar! Failed to install baz (see error(s) above).\n[ERROR] some crates failed to install\n\n\"#]])\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    assert_has_installed_exe(paths::cargo_home(), \"bar\");\n\n    cargo_process(\"uninstall foo bar\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE]\n[REMOVING] [ROOT]/home/.cargo/bin/bar[EXE]\n[SUMMARY] Successfully uninstalled foo, bar!\n\n\"#]])\n        .run();\n\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"bar\");\n}\n\n#[cargo_test]\nfn pick_max_version() {\n    pkg(\"foo\", \"0.1.0\");\n    pkg(\"foo\", \"0.2.0\");\n    pkg(\"foo\", \"0.2.1\");\n    pkg(\"foo\", \"0.2.1-pre.1\");\n    pkg(\"foo\", \"0.3.0-pre.2\");\n\n    cargo_process(\"install foo\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.2.1 (registry `dummy-registry`)\n[INSTALLING] foo v0.2.1\n[COMPILING] foo v0.2.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.2.1` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]]).run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn installs_beta_version_by_explicit_name_from_git() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.3.0-beta.1\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --git\")\n        .arg(p.url().to_string())\n        .arg(\"foo\")\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn missing() {\n    pkg(\"foo\", \"0.0.1\");\n    cargo_process(\"install bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] could not find `bar` in registry `crates-io` with version `*`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn missing_current_working_directory() {\n    cargo_process(\"install .\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] to install the binaries for the package in current working directory use `cargo install --path .`. \nuse `cargo build` if you want to simply build the package.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_version() {\n    pkg(\"foo\", \"0.0.1\");\n    cargo_process(\"install foo --version=0.2.0\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] could not find `foo` in registry `crates-io` with version `=0.2.0`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn missing_at_symbol_before_version() {\n    pkg(\"foo\", \"0.0.1\");\n    cargo_process(\"install foo=0.2.0\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid character `=` in package name: `foo=0.2.0`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)\n\n[HELP] if this is meant to be a package name followed by a version, insert an `@` like `foo@=0.2.0`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_paths() {\n    cargo_process(\"install\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `[ROOT]` is not a crate root; specify a crate to install from crates.io, or use --path or --git to specify an alternate source\n\n\"#]])\n        .run();\n\n    cargo_process(\"install --path .\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `[ROOT]` does not contain a Cargo.toml file. --path must point to a directory containing a Cargo.toml file.\n\n\"#]])\n        .run();\n\n    let toml = paths::root().join(\"Cargo.toml\");\n    fs::write(toml, \"\").unwrap();\n    cargo_process(\"install --path Cargo.toml\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `[ROOT]/Cargo.toml` is not a directory. --path must point to a directory containing a Cargo.toml file.\n\n\"#]])\n        .run();\n\n    cargo_process(\"install --path .\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/Cargo.toml`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn install_location_precedence() {\n    pkg(\"foo\", \"0.0.1\");\n\n    let root = paths::root();\n    let t1 = root.join(\"t1\");\n    let t2 = root.join(\"t2\");\n    let t3 = root.join(\"t3\");\n    let t4 = paths::cargo_home();\n\n    fs::create_dir(root.join(\".cargo\")).unwrap();\n    fs::write(\n        root.join(\".cargo/config.toml\"),\n        &format!(\n            \"[install]\n             root = '{}'\n            \",\n            t3.display()\n        ),\n    )\n    .unwrap();\n\n    println!(\"install --root\");\n\n    cargo_process(\"install foo --root\")\n        .arg(&t1)\n        .env(\"CARGO_INSTALL_ROOT\", &t2)\n        .run();\n    assert_has_installed_exe(&t1, \"foo\");\n    assert_has_not_installed_exe(&t2, \"foo\");\n\n    println!(\"install CARGO_INSTALL_ROOT\");\n\n    cargo_process(\"install foo\")\n        .env(\"CARGO_INSTALL_ROOT\", &t2)\n        .run();\n    assert_has_installed_exe(&t2, \"foo\");\n    assert_has_not_installed_exe(&t3, \"foo\");\n\n    println!(\"install install.root\");\n\n    cargo_process(\"install foo\").run();\n    assert_has_installed_exe(&t3, \"foo\");\n    assert_has_not_installed_exe(&t4, \"foo\");\n\n    fs::remove_file(root.join(\".cargo/config.toml\")).unwrap();\n\n    println!(\"install cargo home\");\n\n    cargo_process(\"install foo\").run();\n    assert_has_installed_exe(&t4, \"foo\");\n}\n\n#[cargo_test]\nfn relative_install_location_without_trailing_slash() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    let root = paths::root();\n    let root_t1 = root.join(\"t1\");\n    let p_path = p.root().to_path_buf();\n    let project_t1 = p_path.join(\"t1\");\n\n    fs::create_dir(root.join(\".cargo\")).unwrap();\n    fs::write(\n        root.join(\".cargo/config.toml\"),\n        r#\"\n            [install]\n            root = \"t1\"\n        \"#,\n    )\n    .unwrap();\n\n    let mut cmd = cargo_process(\"install --path .\");\n    cmd.cwd(p.root());\n    cmd.with_stderr_data(str![[r#\"\n[WARNING] the `install.root` value `t1` defined in [ROOT]/.cargo/config.toml without a trailing slash is deprecated\n  |\n  = [NOTE] a future version of Cargo will treat it as relative to the configuration directory\n  = [HELP] add a trailing slash (`t1/`) to adopt the correct behavior and silence this warning\n  = [NOTE] see more at https://doc.rust-lang.org/cargo/reference/config.html#config-relative-paths\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/foo/t1/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/foo/t1/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n\n    // NOTE: the install location is relative to the CWD, not the config file\n    assert_has_not_installed_exe(&root_t1, \"foo\");\n    assert_has_installed_exe(&project_t1, \"foo\");\n}\n\n#[cargo_test]\nfn cli_root_argument_without_deprecation_warning() {\n    // Verify that using the --root CLI argument does not produce the deprecation warning.\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    let root = paths::root();\n    let root_t1 = root.join(\"t1\");\n    let p_path = p.root().to_path_buf();\n    let project_t1 = p_path.join(\"t1\");\n\n    cargo_process(\"install --path . --root\")\n        .arg(\"t1\")\n        .cwd(p.root())\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/foo/t1/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/foo/t1/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(&root_t1, \"foo\");\n    assert_has_installed_exe(&project_t1, \"foo\");\n}\n\n#[cargo_test]\nfn relative_install_location_with_trailing_slash() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    let root = paths::root();\n    let root_t1 = root.join(\"t1\");\n    let p_path = p.root().to_path_buf();\n    let project_t1 = p_path.join(\"t1\");\n\n    fs::create_dir(root.join(\".cargo\")).unwrap();\n    fs::write(\n        root.join(\".cargo/config.toml\"),\n        r#\"\n            [install]\n            root = \"t1/\"\n        \"#,\n    )\n    .unwrap();\n\n    let mut cmd = cargo_process(\"install --path .\");\n    cmd.cwd(p.root());\n    cmd.with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/t1/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/t1/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n\n    assert_has_installed_exe(&root_t1, \"foo\");\n    assert_has_not_installed_exe(&project_t1, \"foo\");\n}\n\n#[cargo_test]\nfn relative_install_location_with_path_set() {\n    // Test that when the absolute install path is in PATH, no warning is shown\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    let root = paths::root();\n    let p_path = p.root().to_path_buf();\n    let project_t1 = p_path.join(\"t1\");\n\n    fs::create_dir(root.join(\".cargo\")).unwrap();\n    fs::write(\n        root.join(\".cargo/config.toml\"),\n        r#\"\n            [install]\n            root = \"t1\"\n        \"#,\n    )\n    .unwrap();\n\n    // Add the absolute path to PATH environment variable\n    let install_bin_path = project_t1.join(\"bin\");\n    let mut path = path();\n    path.push(install_bin_path);\n    let new_path = env::join_paths(path).unwrap();\n\n    let mut cmd = cargo_process(\"install --path .\");\n    cmd.cwd(p.root());\n    cmd.env(\"PATH\", new_path);\n    cmd.with_stderr_data(str![[r#\"\n[WARNING] the `install.root` value `t1` defined in [ROOT]/.cargo/config.toml without a trailing slash is deprecated\n  |\n  = [NOTE] a future version of Cargo will treat it as relative to the configuration directory\n  = [HELP] add a trailing slash (`t1/`) to adopt the correct behavior and silence this warning\n  = [NOTE] see more at https://doc.rust-lang.org/cargo/reference/config.html#config-relative-paths\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/foo/t1/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `foo[EXE]`)\n\n\"#]])\n        .run();\n\n    assert_has_installed_exe(&project_t1, \"foo\");\n}\n\n#[cargo_test]\nfn install_path() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    cargo_process(\"install --path\").arg(p.root()).run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    // path-style installs force a reinstall\n    p.cargo(\"install --path .\").with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n[REPLACED] package `foo v0.0.1 ([ROOT]/foo)` with `foo v0.0.1 ([ROOT]/foo)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn install_target_dir() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"install --target-dir td_test\")\n        .with_stderr_data(str![[r#\"\n[WARNING] using `cargo install` to install the binaries from the package in current working directory is deprecated, use `cargo install --path .` instead. [NOTE] use `cargo build` if you want to simply build the package.\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n\n    let mut path = p.root();\n    path.push(\"td_test\");\n    assert!(path.exists());\n\n    #[cfg(not(windows))]\n    path.push(\"release/foo\");\n    #[cfg(windows)]\n    path.push(\"release/foo.exe\");\n    assert!(path.exists());\n}\n\n#[cargo_test]\n#[cfg(target_os = \"linux\")]\nfn install_path_with_lowercase_cargo_toml() {\n    let toml = paths::root().join(\"cargo.toml\");\n    fs::write(toml, \"\").unwrap();\n\n    cargo_process(\"install --path .\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `[ROOT]` does not contain a Cargo.toml file, but found cargo.toml please try to rename it to Cargo.toml. --path must point to a directory containing a Cargo.toml file.\n\n\"#]]\n        )\n        .run();\n}\n\n#[cargo_test]\nfn install_relative_path_outside_current_ws() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                authors = []\n\n                [workspace]\n                members = [\"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.0\"\n                authors = []\n                edition = \"2021\"\n\n                [dependencies]\n                foo = \"1\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    let _bin_project = project_in(\"bar\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"install --path ../bar/foo\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/bar/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/bar/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1 ([ROOT]/bar/foo)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n\n    // Validate the workspace error message to display available targets.\n    p.cargo(\"install --path ../bar/foo --bin\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nAvailable binaries:\n    foo\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_packages_containing_binaries() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"a/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --git\")\n        .arg(p.url().to_string())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/foo`\n[ERROR] multiple packages with binaries found: bar, foo. When installing a git repository, cargo will always search the entire repo for any Cargo.toml.\nPlease specify a package, e.g. `cargo install --git [ROOTURL]/foo bar`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_packages_matching_example() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex1.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"bar/examples/ex1.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --example ex1 --git\")\n        .arg(p.url().to_string())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/foo`\n[ERROR] multiple packages with examples found: bar, foo. When installing a git repository, cargo will always search the entire repo for any Cargo.toml.\nPlease specify a package, e.g. `cargo install --git [ROOTURL]/foo bar`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_binaries_deep_select_uses_package_name() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"bar/baz/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --git\")\n        .arg(p.url().to_string())\n        .arg(\"baz\")\n        .run();\n}\n\n#[cargo_test]\nfn multiple_binaries_in_selected_package_installs_all() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/bin/bin1.rs\", \"fn main() {}\")\n        .file(\"bar/src/bin/bin2.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --git\")\n        .arg(p.url().to_string())\n        .arg(\"bar\")\n        .run();\n\n    let cargo_home = paths::cargo_home();\n    assert_has_installed_exe(&cargo_home, \"bin1\");\n    assert_has_installed_exe(&cargo_home, \"bin2\");\n}\n\n#[cargo_test]\nfn multiple_binaries_in_selected_package_with_bin_option_installs_only_one() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/bin/bin1.rs\", \"fn main() {}\")\n        .file(\"bar/src/bin/bin2.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --bin bin1 --git\")\n        .arg(p.url().to_string())\n        .arg(\"bar\")\n        .run();\n\n    let cargo_home = paths::cargo_home();\n    assert_has_installed_exe(&cargo_home, \"bin1\");\n    assert_has_not_installed_exe(&cargo_home, \"bin2\");\n}\n\n#[cargo_test]\nfn multiple_crates_select() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"a/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --git\")\n        .arg(p.url().to_string())\n        .arg(\"foo\")\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"bar\");\n\n    cargo_process(\"install --git\")\n        .arg(p.url().to_string())\n        .arg(\"bar\")\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"bar\");\n}\n\n#[cargo_test]\nfn multiple_crates_git_all() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"bin1\", \"bin2\"]\n            \"#,\n        )\n        .file(\"bin1/Cargo.toml\", &basic_manifest(\"bin1\", \"0.1.0\"))\n        .file(\"bin2/Cargo.toml\", &basic_manifest(\"bin2\", \"0.1.0\"))\n        .file(\n            \"bin1/src/main.rs\",\n            r#\"fn main() { println!(\"Hello, world!\"); }\"#,\n        )\n        .file(\n            \"bin2/src/main.rs\",\n            r#\"fn main() { println!(\"Hello, world!\"); }\"#,\n        )\n        .build();\n\n    cargo_process(&format!(\"install --git {} bin1 bin2\", p.url())).run();\n}\n\n#[cargo_test]\nfn multiple_crates_auto_binaries() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() {}\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    cargo_process(\"install --path\").arg(p.root()).run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn multiple_crates_auto_examples() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .file(\n            \"examples/foo.rs\",\n            \"\n            extern crate bar;\n            extern crate foo;\n            fn main() {}\n        \",\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    cargo_process(\"install --path\")\n        .arg(p.root())\n        .arg(\"--example=foo\")\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn no_binaries_or_examples() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    cargo_process(\"install --path\")\n        .arg(p.root())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no packages found with binaries or examples\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_binaries() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/foo.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --path\")\n        .arg(p.root())\n        .arg(\"foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] there is nothing to install in `foo v0.0.1 ([ROOT]/foo)`, because it has no binaries\n`cargo install` is only for installing programs, and can't be used with libraries.\nTo use a library crate, add it as a dependency to a Cargo project with `cargo add`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn examples() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/foo.rs\", \"extern crate foo; fn main() {}\")\n        .build();\n\n    cargo_process(\"install --path\")\n        .arg(p.root())\n        .arg(\"--example=foo\")\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn install_force() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    cargo_process(\"install --path\").arg(p.root()).run();\n\n    let p = project()\n        .at(\"foo2\")\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.2.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --force --path\")\n        .arg(p.root())\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.2.0 ([ROOT]/foo2)\n[COMPILING] foo v0.2.0 ([ROOT]/foo2)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n[REPLACED] package `foo v0.0.1 ([ROOT]/foo)` with `foo v0.2.0 ([ROOT]/foo2)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n\n    cargo_process(\"install --list\")\n        .with_stdout_data(str![[r#\"\nfoo v0.2.0 ([ROOT]/foo2):\n    foo[EXE]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn install_force_partial_overlap() {\n    let p = project()\n        .file(\"src/bin/foo-bin1.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo-bin2.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --path\").arg(p.root()).run();\n\n    let p = project()\n        .at(\"foo2\")\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.2.0\"))\n        .file(\"src/bin/foo-bin2.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo-bin3.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --force --path\")\n        .arg(p.root())\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.2.0 ([ROOT]/foo2)\n[COMPILING] foo v0.2.0 ([ROOT]/foo2)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo-bin3[EXE]\n[REPLACING] [ROOT]/home/.cargo/bin/foo-bin2[EXE]\n[REMOVING] executable `[ROOT]/home/.cargo/bin/foo-bin1[EXE]` from previous version foo v0.0.1 ([ROOT]/foo)\n[INSTALLED] package `foo v0.2.0 ([ROOT]/foo2)` (executable `foo-bin3[EXE]`)\n[REPLACED] package `foo v0.0.1 ([ROOT]/foo)` with `foo v0.2.0 ([ROOT]/foo2)` (executable `foo-bin2[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n\n    cargo_process(\"install --list\")\n        .with_stdout_data(str![[r#\"\nfoo v0.2.0 ([ROOT]/foo2):\n    foo-bin2[EXE]\n    foo-bin3[EXE]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn install_force_bin() {\n    let p = project()\n        .file(\"src/bin/foo-bin1.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo-bin2.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --path\").arg(p.root()).run();\n\n    let p = project()\n        .at(\"foo2\")\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.2.0\"))\n        .file(\"src/bin/foo-bin1.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo-bin2.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --force --bin foo-bin2 --path\")\n        .arg(p.root())\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.2.0 ([ROOT]/foo2)\n[COMPILING] foo v0.2.0 ([ROOT]/foo2)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[REPLACING] [ROOT]/home/.cargo/bin/foo-bin2[EXE]\n[REPLACED] package `foo v0.0.1 ([ROOT]/foo)` with `foo v0.2.0 ([ROOT]/foo2)` (executable `foo-bin2[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n\n    cargo_process(\"install --list\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo):\n    foo-bin1[EXE]\nfoo v0.2.0 ([ROOT]/foo2):\n    foo-bin2[EXE]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn compile_failure() {\n    let p = project().file(\"src/main.rs\", \"\").build();\n\n    cargo_process(\"install --path\")\n        .arg(p.root())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n[ERROR] failed to compile `foo v0.0.1 ([ROOT]/foo)`, intermediate artifacts can be found at `[ROOT]/foo/target`.\nTo reuse those artifacts with a future compilation, set the environment variable `CARGO_BUILD_BUILD_DIR` to that path.\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_repo() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // Use `--locked` to test that we don't even try to write a lock file.\n    cargo_process(\"install --locked --git\")\n        .arg(p.url().to_string())\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/foo`\n[WARNING] no Cargo.lock file published in foo v0.1.0 ([ROOTURL]/foo#[..])\n[INSTALLING] foo v0.1.0 ([ROOTURL]/foo#[..])\n[COMPILING] foo v0.1.0 ([ROOT]/home/.cargo/git/checkouts/foo-[HASH]/[..])\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.1.0 ([ROOTURL]/foo#[..])` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\n#[cfg(target_os = \"linux\")]\nfn git_repo_with_lowercase_cargo_toml() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\"cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --git\")\n        .arg(p.url().to_string())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository [..]\n[ERROR] could not find `Cargo.toml` in `[..]`\n[HELP] found `cargo.toml`, consider renaming it to `Cargo.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn list() {\n    pkg(\"foo\", \"0.0.1\");\n    pkg(\"bar\", \"0.2.1\");\n    pkg(\"bar\", \"0.2.2\");\n\n    cargo_process(\"install --list\").with_stdout_data(\"\").run();\n\n    cargo_process(\"install bar --version =0.2.1\").run();\n    cargo_process(\"install foo\").run();\n    cargo_process(\"install --list\")\n        .with_stdout_data(str![[r#\"\nbar v0.2.1:\n    bar[EXE]\nfoo v0.0.1:\n    foo[EXE]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn list_error() {\n    pkg(\"foo\", \"0.0.1\");\n    cargo_process(\"install foo\").run();\n    cargo_process(\"install --list\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1:\n    foo[EXE]\n\n\"#]])\n        .run();\n    let mut worldfile_path = paths::cargo_home();\n    worldfile_path.push(\".crates.toml\");\n    let mut worldfile = OpenOptions::new()\n        .write(true)\n        .open(worldfile_path)\n        .expect(\".crates.toml should be there\");\n    worldfile.write_all(b\"\\x00\").unwrap();\n    drop(worldfile);\n    cargo_process(\"install --list --verbose\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse crate metadata at `[ROOT]/home/.cargo/.crates.toml`\n\nCaused by:\n  invalid TOML found for metadata\n\nCaused by:\n  TOML parse error at line 1, column 4\n    |\n  1 | v1]\n    |    ^\n  key with no value, expected `=`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn uninstall_pkg_does_not_exist() {\n    cargo_process(\"uninstall foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `foo` did not match any packages\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn uninstall_bin_does_not_exist() {\n    pkg(\"foo\", \"0.0.1\");\n\n    cargo_process(\"install foo\").run();\n    cargo_process(\"uninstall foo --bin=bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] binary `bar[EXE]` not installed as part of `foo v0.0.1`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn uninstall_piecemeal() {\n    let p = project()\n        .file(\"src/bin/foo.rs\", \"fn main() {}\")\n        .file(\"src/bin/bar.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --path\").arg(p.root()).run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    assert_has_installed_exe(paths::cargo_home(), \"bar\");\n\n    cargo_process(\"uninstall foo --bin=bar\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/bar[EXE]\n\n\"#]])\n        .run();\n\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"bar\");\n\n    cargo_process(\"uninstall foo --bin=foo\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE]\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n\n    cargo_process(\"uninstall foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `foo` did not match any packages\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn subcommand_works_out_of_the_box() {\n    Package::new(\"cargo-foo\", \"1.0.0\")\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"bar\"); }\"#)\n        .publish();\n    cargo_process(\"install cargo-foo\").run();\n    cargo_process(\"foo\")\n        .with_stdout_data(str![[r#\"\nbar\n\n\"#]])\n        .run();\n    cargo_process(\"--list\")\n        .with_stdout_data(str![[r#\"\n...\n    foo\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn installs_from_cwd_by_default() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"install\").with_stderr_data(str![[r#\"\n[WARNING] using `cargo install` to install the binaries from the package in current working directory is deprecated, use `cargo install --path .` instead. [NOTE] use `cargo build` if you want to simply build the package.\n...\n\"#]]).run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn installs_from_cwd_with_2018_warnings() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n                edition = \"2018\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"install\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] using `cargo install` to install the binaries from the package in current working directory is no longer supported, use `cargo install --path .` instead. [NOTE] use `cargo build` if you want to simply build the package.\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn uninstall_cwd() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"install --path .\").with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]]).run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n\n    p.cargo(\"uninstall\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE]\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn uninstall_cwd_not_installed() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"uninstall\")\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] package `foo v0.0.1 ([ROOT]/foo)` is not installed\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn uninstall_cwd_no_project() {\n    cargo_process(\"uninstall\")\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to read `[ROOT]/Cargo.toml`\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn do_not_rebuilds_on_local_install() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"build --release\").run();\n    cargo_process(\"install --path\")\n        .arg(p.root())\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n\n    assert!(p.build_dir().exists());\n    assert!(p.release_bin(\"foo\").exists());\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn reports_unsuccessful_subcommand_result() {\n    Package::new(\"cargo-fail\", \"1.0.0\")\n        .file(\"src/main.rs\", r#\"fn main() { panic!(\"EXPLICIT PANIC!\"); }\"#)\n        .publish();\n    cargo_process(\"install cargo-fail\").run();\n    cargo_process(\"--list\")\n        .with_stdout_data(str![[r#\"\n...\n    fail\n...\n\"#]])\n        .run();\n    cargo_process(\"fail\")\n        .with_status(101)\n        .with_stderr_data(\"...\\n[..]EXPLICIT PANIC![..]\\n...\")\n        .run();\n}\n\n#[cargo_test]\nfn git_with_lockfile() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"fn main() {}\")\n        .file(\n            \"Cargo.lock\",\n            r#\"\n                [[package]]\n                name = \"foo\"\n                version = \"0.1.0\"\n                dependencies = [ \"bar 0.1.0\" ]\n\n                [[package]]\n                name = \"bar\"\n                version = \"0.1.0\"\n            \"#,\n        )\n        .build();\n\n    cargo_process(\"install --git\")\n        .arg(p.url().to_string())\n        .run();\n}\n\n#[cargo_test]\nfn q_silences_warnings() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    cargo_process(\"install -q --path\")\n        .arg(p.root())\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn readonly_dir() {\n    pkg(\"foo\", \"0.0.1\");\n\n    let root = paths::root();\n    let dir = &root.join(\"readonly\");\n    fs::create_dir(root.join(\"readonly\")).unwrap();\n    let mut perms = fs::metadata(dir).unwrap().permissions();\n    perms.set_readonly(true);\n    fs::set_permissions(dir, perms).unwrap();\n\n    cargo_process(\"install foo\").cwd(dir).run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn use_path_workspace() {\n    Package::new(\"foo\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                authors = []\n\n                [workspace]\n                members = [\"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                foo = \"1\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    let lock = p.read_lockfile();\n    p.cargo(\"install\").run();\n    let lock2 = p.read_lockfile();\n    assert_eq!(lock, lock2, \"different lockfiles\");\n}\n\n#[cargo_test]\nfn path_install_workspace_root_despite_default_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"ws-root\"\n                version = \"0.1.0\"\n                authors = []\n\n                [workspace]\n                members = [\"ws-member\"]\n                default-members = [\"ws-member\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"ws-member/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"ws-member\"\n                version = \"0.1.0\"\n                authors = []\n            \"#,\n        )\n        .file(\"ws-member/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"install --path\")\n        .arg(p.root())\n        .arg(\"ws-root\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] ws-root v0.1.0 ([ROOT]/foo)\n[COMPILING] ws-root v0.1.0 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/ws-root[EXE]\n[INSTALLED] package `ws-root v0.1.0 ([ROOT]/foo)` (executable `ws-root[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        // Particularly avoid \"Installed package `ws-root v0.1.0 ([..]])` (executable `ws-member`)\":\n        .with_stderr_does_not_contain(\"ws-member\")\n        .run();\n}\n\n#[cargo_test]\nfn git_install_workspace_root_despite_default_members() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"ws-root\"\n                version = \"0.1.0\"\n                authors = []\n\n                [workspace]\n                members = [\"ws-member\"]\n                default-members = [\"ws-member\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"ws-member/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"ws-member\"\n                version = \"0.1.0\"\n                authors = []\n            \"#,\n        )\n        .file(\"ws-member/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --git\")\n        .arg(p.url().to_string())\n        .arg(\"ws-root\")\n        .with_stderr_data(str![[r#\"\n...\n[INSTALLED] package `ws-root v0.1.0 ([ROOTURL]/foo#[..])` (executable `ws-root[EXE]`)\n...\n\"#]])\n        // Particularly avoid \"Installed package `ws-root v0.1.0 ([..]])` (executable `ws-member`)\":\n        .with_stderr_does_not_contain(\"ws-member\")\n        .run();\n}\n\n#[cargo_test]\nfn dev_dependencies_no_check() {\n    Package::new(\"foo\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dev-dependencies]\n                baz = \"1.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] no matching package named `baz` found\n...\n\"#]])\n        .run();\n    p.cargo(\"install\").run();\n}\n\n#[cargo_test]\nfn dev_dependencies_lock_file_untouched() {\n    Package::new(\"foo\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dev-dependencies]\n                bar = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    let lock = p.read_lockfile();\n    p.cargo(\"install\").run();\n    let lock2 = p.read_lockfile();\n    assert!(lock == lock2, \"different lockfiles\");\n}\n\n#[cargo_test]\nfn install_target_native() {\n    pkg(\"foo\", \"0.1.0\");\n\n    cargo_process(\"install foo --target\")\n        .arg(cargo_test_support::rustc_host())\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn install_target_foreign() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    pkg(\"foo\", \"0.1.0\");\n\n    cargo_process(\"install foo --target\")\n        .arg(cross_compile::alternate())\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn vers_precise() {\n    pkg(\"foo\", \"0.1.1\");\n    pkg(\"foo\", \"0.1.2\");\n\n    cargo_process(\"install foo --vers 0.1.1\")\n        .with_stderr_data(str![[r#\"\n...\n[DOWNLOADED] foo v0.1.1 (registry `dummy-registry`)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn version_precise() {\n    pkg(\"foo\", \"0.1.1\");\n    pkg(\"foo\", \"0.1.2\");\n\n    cargo_process(\"install foo --version 0.1.1\")\n        .with_stderr_data(str![[r#\"\n...\n[DOWNLOADED] foo v0.1.1 (registry `dummy-registry`)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inline_version_precise() {\n    pkg(\"foo\", \"0.1.1\");\n    pkg(\"foo\", \"0.1.2\");\n\n    cargo_process(\"install foo@0.1.1\")\n        .with_stderr_data(str![[r#\"\n...\n[DOWNLOADED] foo v0.1.1 (registry `dummy-registry`)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inline_version_multiple() {\n    pkg(\"foo\", \"0.1.0\");\n    pkg(\"foo\", \"0.1.1\");\n    pkg(\"foo\", \"0.1.2\");\n    pkg(\"bar\", \"0.2.0\");\n    pkg(\"bar\", \"0.2.1\");\n    pkg(\"bar\", \"0.2.2\");\n\n    cargo_process(\"install foo@0.1.1 bar@0.2.1\")\n        .with_stderr_data(str![[r#\"\n...\n[DOWNLOADED] foo v0.1.1 (registry `dummy-registry`)\n...\n[DOWNLOADED] bar v0.2.1 (registry `dummy-registry`)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inline_version_without_name() {\n    pkg(\"foo\", \"0.1.1\");\n    pkg(\"foo\", \"0.1.2\");\n\n    cargo_process(\"install @0.1.1\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid value '@0.1.1' for '[CRATE[@<VER>]]...': missing crate name before '@'\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inline_and_explicit_version() {\n    pkg(\"foo\", \"0.1.1\");\n    pkg(\"foo\", \"0.1.2\");\n\n    cargo_process(\"install foo@0.1.1 --version 0.1.1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot specify both `@<VERSION>` and `--version <VERSION>`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn not_both_vers_and_version() {\n    pkg(\"foo\", \"0.1.1\");\n    pkg(\"foo\", \"0.1.2\");\n\n    cargo_process(\"install foo --version 0.1.1 --vers 0.1.2\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] the argument '--version <VERSION>' cannot be used multiple times\n\nUsage: cargo[EXE] install [OPTIONS] [CRATE[@<VER>]]...\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_install_git_cannot_be_a_base_url() {\n    cargo_process(\"install --git github.com:rust-lang/rustfmt.git\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid url `github.com:rust-lang/rustfmt.git`: cannot-be-a-base-URLs are not supported\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn uninstall_multiple_and_specifying_bin() {\n    cargo_process(\"uninstall foo bar --bin baz\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] A binary can only be associated with a single installed package, specifying multiple specs with --bin is redundant.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn uninstall_with_empty_package_option() {\n    cargo_process(\"uninstall -p\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value.\nRun `cargo help pkgid` for more information about SPEC format.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn uninstall_multiple_and_some_pkg_does_not_exist() {\n    pkg(\"foo\", \"0.0.1\");\n\n    cargo_process(\"install foo\").run();\n\n    cargo_process(\"uninstall foo bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE]\n[ERROR] package ID specification `bar` did not match any packages\n[SUMMARY] Successfully uninstalled foo! Failed to uninstall bar (see error(s) above).\n[ERROR] some packages failed to uninstall\n\n\"#]])\n        .run();\n\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"bar\");\n}\n\n#[cargo_test]\nfn custom_target_dir_for_git_source() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    cargo_process(\"install --git\")\n        .arg(p.url().to_string())\n        .run();\n    assert!(!paths::root().join(\"target/release\").is_dir());\n\n    cargo_process(\"install --force --git\")\n        .arg(p.url().to_string())\n        .env(\"CARGO_TARGET_DIR\", \"target\")\n        .run();\n    assert!(paths::root().join(\"target/release\").is_dir());\n}\n\n#[cargo_test]\nfn install_respects_lock_file() {\n    // `cargo install` now requires --locked to use a Cargo.lock.\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.1\")\n        .file(\"src/lib.rs\", \"not rust\")\n        .publish();\n    Package::new(\"foo\", \"0.1.0\")\n        .dep(\"bar\", \"0.1\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"src/main.rs\",\n            \"extern crate foo; extern crate bar; fn main() {}\",\n        )\n        .file(\n            \"Cargo.lock\",\n            r#\"\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.1.0\"\ndependencies = [\n \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n\"#,\n        )\n        .publish();\n\n    cargo_process(\"install foo\")\n        .with_stderr_data(str![[r#\"\n...\n[..]not rust[..]\n...\n\"#]])\n        .with_status(101)\n        .run();\n    cargo_process(\"install --locked foo\").run();\n}\n\n#[cargo_test]\nfn install_path_respects_lock_file() {\n    // --path version of install_path_respects_lock_file, --locked is required\n    // to use Cargo.lock.\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.1\")\n        .file(\"src/lib.rs\", \"not rust\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() {}\")\n        .file(\n            \"Cargo.lock\",\n            r#\"\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.1.0\"\ndependencies = [\n \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n\"#,\n        )\n        .build();\n\n    p.cargo(\"install --path .\")\n        .with_stderr_data(str![[r#\"\n...\n[..]not rust[..]\n...\n\"#]])\n        .with_status(101)\n        .run();\n    p.cargo(\"install --path . --locked\").run();\n}\n\n#[cargo_test]\nfn lock_file_path_deps_ok() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    Package::new(\"foo\", \"0.1.0\")\n        .dep(\"bar\", \"0.1\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"src/main.rs\",\n            \"extern crate foo; extern crate bar; fn main() {}\",\n        )\n        .file(\n            \"Cargo.lock\",\n            r#\"\n            [[package]]\n            name = \"bar\"\n            version = \"0.1.0\"\n\n            [[package]]\n            name = \"foo\"\n            version = \"0.1.0\"\n            dependencies = [\n             \"bar 0.1.0\",\n            ]\n            \"#,\n        )\n        .publish();\n\n    cargo_process(\"install foo\").run();\n}\n\n#[cargo_test]\nfn install_empty_argument() {\n    // Bug 5229\n    cargo_process(\"install\")\n        .arg(\"\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid value '' for '[CRATE[@<VER>]]...': crate name is empty\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_repo_replace() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    let repo = git2::Repository::open(&p.root()).unwrap();\n    let old_rev = repo.revparse_single(\"HEAD\").unwrap().id();\n    cargo_process(\"install --git\")\n        .arg(p.url().to_string())\n        .run();\n    git::commit(&repo);\n    let new_rev = repo.revparse_single(\"HEAD\").unwrap().id();\n    let mut path = paths::home();\n    path.push(\".cargo/.crates.toml\");\n\n    assert_ne!(old_rev, new_rev);\n    assert!(\n        fs::read_to_string(path.clone())\n            .unwrap()\n            .contains(&format!(\"{}\", old_rev))\n    );\n    cargo_process(\"install --force --git\")\n        .arg(p.url().to_string())\n        .run();\n    assert!(\n        fs::read_to_string(path)\n            .unwrap()\n            .contains(&format!(\"{}\", new_rev))\n    );\n}\n\n#[cargo_test]\nfn workspace_uses_workspace_target_dir() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n\n                [workspace]\n\n                [dependencies]\n                bar = { path = 'bar' }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --release\").cwd(\"bar\").run();\n    cargo_process(\"install --path\")\n        .arg(p.root().join(\"bar\"))\n        .with_stderr_data(str![[r#\"\n[INSTALLING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/bar[EXE]\n[INSTALLED] package `bar v0.1.0 ([ROOT]/foo/bar)` (executable `bar[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn install_ignores_local_cargo_config() {\n    pkg(\"bar\", \"0.0.1\");\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                target = \"non-existing-target\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"install bar\").run();\n    assert_has_installed_exe(paths::cargo_home(), \"bar\");\n}\n\n#[cargo_test]\nfn install_ignores_unstable_table_in_local_cargo_config() {\n    pkg(\"bar\", \"0.0.1\");\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [unstable]\n                build-std = [\"core\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"install bar\")\n        .masquerade_as_nightly_cargo(&[\"build-std\"])\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"bar\");\n}\n\n#[cargo_test]\nfn install_global_cargo_config() {\n    pkg(\"bar\", \"0.0.1\");\n\n    let config = paths::cargo_home().join(\"config.toml\");\n    let mut toml = fs::read_to_string(&config).unwrap_or_default();\n\n    toml.push_str(\n        r#\"\n            [build]\n            target = 'nonexistent'\n        \"#,\n    );\n    fs::write(&config, toml).unwrap();\n\n    cargo_process(\"install bar\")\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n[INSTALLING] bar v0.0.1\nCaused by:\n  process didn't exit successfully: `rustc [..]--target nonexistent[..]` ([EXIT_STATUS]: 1)\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn install_path_config() {\n    project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            target = 'nonexistent'\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    cargo_process(\"install --path foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n  process didn't exit successfully: `rustc [..]--target nonexistent[..]` ([EXIT_STATUS]: 1)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn install_version_req() {\n    // Try using a few versionreq styles.\n    pkg(\"foo\", \"0.0.3\");\n    pkg(\"foo\", \"1.0.4\");\n    pkg(\"foo\", \"1.0.5\");\n    cargo_process(\"install foo --version=*\")\n        .with_stderr_does_not_contain(\"[WARNING][..]is not a valid semver[..]\")\n        .with_stderr_data(str![[r#\"\n...\n[INSTALLING] foo v1.0.5\n...\n\"#]])\n        .run();\n    cargo_process(\"uninstall foo\").run();\n    cargo_process(\"install foo --version=^1.0\")\n        .with_stderr_does_not_contain(\"[WARNING][..]is not a valid semver[..]\")\n        .with_stderr_data(str![[r#\"\n...\n[INSTALLING] foo v1.0.5\n...\n\"#]])\n        .run();\n    cargo_process(\"uninstall foo\").run();\n    cargo_process(\"install foo --version=0.0.*\")\n        .with_stderr_does_not_contain(\"[WARNING][..]is not a valid semver[..]\")\n        .with_stderr_data(str![[r#\"\n...\n[INSTALLING] foo v0.0.3\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_install_reads_workspace_manifest() {\n    let p = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"bin1\"]\n\n            [profile.release]\n            incremental = 3\n            \"#,\n        )\n        .file(\"bin1/Cargo.toml\", &basic_manifest(\"bin1\", \"0.1.0\"))\n        .file(\n            \"bin1/src/main.rs\",\n            r#\"fn main() { println!(\"Hello, world!\"); }\"#,\n        )\n        .build();\n\n    cargo_process(&format!(\"install --git {}\", p.url()))\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/foo`\n[ERROR] invalid type: integer `3`, expected a boolean\n --> home/.cargo/git/checkouts/foo-[HASH]/[..]/Cargo.toml:6:27\n  |\n6 |             incremental = 3\n  |                           ^\n[ERROR] invalid type: integer `3`, expected a boolean\n --> home/.cargo/git/checkouts/foo-[HASH]/[..]/Cargo.toml:6:27\n  |\n6 |             incremental = 3\n  |                           ^\n[ERROR] failed searching for potential workspace\npackage manifest: `[ROOT]/home/.cargo/git/checkouts/foo-[HASH]/[..]/bin1/Cargo.toml`\ninvalid potential workspace manifest: `[ROOT]/home/.cargo/git/checkouts/foo-[HASH]/[..]/Cargo.toml`\n\n[HELP] to avoid searching for a non-existent workspace, add `[workspace]` to the package manifest\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn install_git_with_symlink_home() {\n    // Ensure that `cargo install` with a git repo is OK when CARGO_HOME is a\n    // symlink, and uses an build script.\n    if !symlink_supported() {\n        return;\n    }\n    let p = git::new(\"foo\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n            .file(\"src/main.rs\", \"fn main() {}\")\n            // This triggers discover_git_and_list_files for detecting changed files.\n            .file(\"build.rs\", \"fn main() {}\")\n    });\n    #[cfg(unix)]\n    use std::os::unix::fs::symlink;\n    #[cfg(windows)]\n    use std::os::windows::fs::symlink_dir as symlink;\n\n    let actual = paths::root().join(\"actual-home\");\n    t!(std::fs::create_dir(&actual));\n    t!(symlink(&actual, paths::home().join(\".cargo\")));\n    cargo_process(\"install --git\")\n        .arg(p.url().to_string())\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/foo`\n[INSTALLING] foo v1.0.0 ([ROOTURL]/foo#[..])\n[COMPILING] foo v1.0.0 ([ROOT]/home/.cargo/git/checkouts/foo-[HASH]/[..])\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v1.0.0 ([ROOTURL]/foo#[..])` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn install_yanked_cargo_package() {\n    Package::new(\"baz\", \"0.0.1\").yanked(true).publish();\n    cargo_process(\"install baz --version 0.0.1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] cannot install package `baz`, it has been yanked from registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn install_cargo_package_in_a_patched_workspace() {\n    pkg(\"foo\", \"0.1.0\");\n    pkg(\"fizz\", \"1.0.0\");\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                authors = []\n\n                [workspace]\n                members = [\"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                fizz = \"1\"\n\n                [patch.crates-io]\n                fizz = { version = \"=1.0.0\" }\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] patch for the non root package will be ignored, specify patch at the workspace root:\npackage:   [ROOT]/foo/baz/Cargo.toml\nworkspace: [ROOT]/foo/Cargo.toml\n...\n\"#]])\n        .run();\n\n    // A crate installation must not emit any message from a workspace under\n    // current working directory.\n    // See https://github.com/rust-lang/cargo/issues/8619\n    p.cargo(\"install foo\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.1.0 (registry `dummy-registry`)\n[INSTALLING] foo v0.1.0\n[COMPILING] foo v0.1.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.1.0` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]]).run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn locked_install_without_published_lockfile() {\n    Package::new(\"foo\", \"0.1.0\")\n        .file(\"src/main.rs\", \"//! Some docs\\nfn main() {}\")\n        .publish();\n\n    cargo_process(\"install foo --locked\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] no Cargo.lock file published in foo v0.1.0\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn install_semver_metadata() {\n    // Check trying to install a package that uses semver metadata.\n    // This uses alt registry because the bug this is exercising doesn't\n    // trigger with a replaced source.\n    registry::alt_init();\n    Package::new(\"foo\", \"1.0.0+abc\")\n        .alternative(true)\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .publish();\n\n    cargo_process(\"install foo --registry alternative --version 1.0.0+abc\").run();\n    cargo_process(\"install foo --registry alternative\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[IGNORED] package `foo v1.0.0+abc (registry `alternative`)` is already installed, use --force to override\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    // \"Updating\" is not displayed here due to the --version fast-path.\n    cargo_process(\"install foo --registry alternative --version 1.0.0+abc\")\n        .with_stderr_data(str![[r#\"\n[IGNORED] package `foo v1.0.0+abc (registry `alternative`)` is already installed, use --force to override\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    cargo_process(\"install foo --registry alternative --version 1.0.0 --force\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[INSTALLING] foo v1.0.0+abc (registry `alternative`)\n[COMPILING] foo v1.0.0+abc (registry `alternative`)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n[REPLACED] package `foo v1.0.0+abc (registry `alternative`)` with `foo v1.0.0+abc (registry `alternative`)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    // Check that from a fresh cache will work without metadata, too.\n    paths::home().join(\".cargo/registry\").rm_rf();\n    paths::home().join(\".cargo/bin\").rm_rf();\n    cargo_process(\"install foo --registry alternative --version 1.0.0\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v1.0.0+abc (registry `alternative`)\n[INSTALLING] foo v1.0.0+abc (registry `alternative`)\n[COMPILING] foo v1.0.0+abc (registry `alternative`)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v1.0.0+abc (registry `alternative`)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_auto_fix_note() {\n    Package::new(\"auto_fix\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"use std::io;\")\n        .file(\n            \"src/main.rs\",\n            &format!(\"extern crate {}; use std::io; fn main() {{}}\", \"auto_fix\"),\n        )\n        .publish();\n\n    // This should not contain a suggestion to run `cargo fix`\n    //\n    // This is checked by matching the full output as `with_stderr_does_not_contain`\n    // can be brittle\n    cargo_process(\"install auto_fix\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] auto_fix v0.0.1 (registry `dummy-registry`)\n[INSTALLING] auto_fix v0.0.1\n[COMPILING] auto_fix v0.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/auto_fix[EXE]\n[INSTALLED] package `auto_fix v0.0.1` (executable `auto_fix[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"auto_fix\");\n\n    cargo_process(\"uninstall auto_fix\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/auto_fix[EXE]\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"auto_fix\");\n}\n\n#[cargo_test]\nfn failed_install_retains_temp_directory() {\n    // Verifies that the temporary directory persists after a build failure.\n    Package::new(\"foo\", \"0.0.1\")\n        .file(\"src/main.rs\", \"x\")\n        .publish();\n    let err = cargo_process(\"install foo\").exec_with_output().unwrap_err();\n    let err = err.downcast::<ProcessError>().unwrap();\n    let stderr = String::from_utf8(err.stderr.unwrap()).unwrap();\n    assert_e2e().eq(&stderr, str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[INSTALLING] foo v0.0.1\n[COMPILING] foo v0.0.1\n[ERROR] expected one of `!` or `::`, found `<eof>`\n --> [ROOT]/home/.cargo/registry/src/-[..]/foo-0.0.1/src/main.rs:1:1\n  |\n1 | x\n  | ^ expected one of `!` or `::`\n\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n[ERROR] failed to compile `foo v0.0.1`, intermediate artifacts can be found at `[..]`.\nTo reuse those artifacts with a future compilation, set the environment variable `CARGO_BUILD_BUILD_DIR` to that path.\n\n\"#]]);\n\n    // Find the path in the output.\n    let stderr = stderr.split_once(\"found at `\").unwrap().1;\n    let end = stderr.find('.').unwrap() - 1;\n    let path = Path::new(&stderr[..end]);\n    assert!(path.exists());\n    assert!(path.join(\"release/deps\").exists());\n}\n\n#[cargo_test]\nfn failed_install_points_to_build_dir_for_intermediate_artifacts() {\n    let custom_build_dir = cargo_home().join(\"build-artifacts\");\n\n    let p = project()\n        .file(\"src/main.rs\", \"x\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n        [package]\n        name = \"foo\"\n        version = \"0.0.1\"\n        authors = []\n        edition = \"2021\"\n\n        [dependencies]\n    \"#,\n        )\n        .build();\n\n    let err = cargo_process(\"install --path\")\n        .env(\"CARGO_BUILD_BUILD_DIR\", &custom_build_dir)\n        .arg(p.root())\n        .exec_with_output()\n        .unwrap_err();\n    let err = err.downcast::<ProcessError>().unwrap();\n    let stderr = String::from_utf8(err.stderr.unwrap()).unwrap();\n    assert_e2e().eq(&stderr, str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] expected one of `!` or `::`, found `<eof>`\n --> src/main.rs:1:1\n  |\n1 | x\n  | ^ expected one of `!` or `::`\n\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n[ERROR] failed to compile `foo v0.0.1 ([ROOT]/foo)`, intermediate artifacts can be found at `[ROOT]/home/.cargo/build-artifacts`.\nTo reuse those artifacts with a future compilation, set the environment variable `CARGO_BUILD_BUILD_DIR` to that path.\n\n\"#]]);\n}\n\n#[cargo_test]\nfn sparse_install() {\n    // Checks for an issue where uninstalling something corrupted\n    // the SourceIds of sparse registries.\n    // See https://github.com/rust-lang/cargo/issues/11751\n    let _registry = registry::RegistryBuilder::new().http_index().build();\n\n    pkg(\"foo\", \"0.0.1\");\n    pkg(\"bar\", \"0.0.1\");\n\n    cargo_process(\"install foo --registry dummy-registry\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[INSTALLING] foo v0.0.1 (registry `dummy-registry`)\n[UPDATING] `dummy-registry` index\n[COMPILING] foo v0.0.1 (registry `dummy-registry`)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1 (registry `dummy-registry`)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    let assert_v1 = |expected| {\n        let v1 = fs::read_to_string(paths::home().join(\".cargo/.crates.toml\")).unwrap();\n        assert_e2e().eq(&v1, expected);\n    };\n    assert_v1(str![[r#\"\n[v1]\n\"foo 0.0.1 (sparse+http://127.0.0.1:[..]/index/)\" = [\"foo[EXE]\"]\n\n\"#]]);\n    cargo_process(\"install bar\").run();\n    assert_has_installed_exe(paths::cargo_home(), \"bar\");\n    assert_v1(str![[r#\"\n[v1]\n\"bar 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)\" = [\"bar[EXE]\"]\n\"foo 0.0.1 (sparse+http://127.0.0.1:[..]/index/)\" = [\"foo[EXE]\"]\n\n\"#]]);\n\n    cargo_process(\"uninstall bar\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/bar[EXE]\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"bar\");\n    assert_v1(str![[r#\"\n[v1]\n\"foo 0.0.1 (sparse+http://127.0.0.1:[..]/index/)\" = [\"foo[EXE]\"]\n\n\"#]]);\n    cargo_process(\"uninstall foo\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE]\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n    assert_v1(str![[r#\"\n[v1]\n\n\"#]]);\n}\n\n#[cargo_test]\nfn self_referential() {\n    // Some packages build-dep on prior versions of themselves.\n    Package::new(\"foo\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"fn hello() {}\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .publish();\n    Package::new(\"foo\", \"0.0.2\")\n        .file(\"src/lib.rs\", \"fn hello() {}\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build_dep(\"foo\", \"0.0.1\")\n        .publish();\n\n    cargo_process(\"install foo\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.2 (registry `dummy-registry`)\n[INSTALLING] foo v0.0.2\n[LOCKING] 1 package to latest compatible version\n[ADDING] foo v0.0.1 (available: v0.0.2)\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[COMPILING] foo v0.0.1\n[COMPILING] foo v0.0.2\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.2` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]]).run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn ambiguous_registry_vs_local_package() {\n    // Correctly install 'foo' from a local package, even if that package also\n    // depends on a registry dependency named 'foo'.\n    Package::new(\"foo\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"fn hello() {}\")\n        .publish();\n\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n        [package]\n        name = \"foo\"\n        version = \"0.1.0\"\n        authors = []\n        edition = \"2021\"\n\n        [dependencies]\n        foo = \"0.0.1\"\n    \"#,\n        )\n        .build();\n\n    cargo_process(\"install --path\")\n        .arg(p.root())\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.1.0 ([ROOT]/foo)\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[COMPILING] foo v0.0.1\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.1.0 ([ROOT]/foo)` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn install_with_redundant_default_mode() {\n    pkg(\"foo\", \"0.0.1\");\n\n    cargo_process(\"install foo --release\")\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '--release' found\n\n  tip: `--release` is the default for `cargo install`; instead `--debug` is supported\n\nUsage: cargo[EXE] install [OPTIONS] [CRATE[@<VER>]]...\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn install_incompat_msrv() {\n    Package::new(\"foo\", \"0.1.0\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .rust_version(\"1.30\")\n        .publish();\n    Package::new(\"foo\", \"0.2.0\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .rust_version(\"1.9876.0\")\n        .publish();\n\n    cargo_process(\"install foo\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] cannot install package `foo 0.2.0`, it requires rustc 1.9876.0 or newer, while the currently active rustc version is [..]\n`foo 0.1.0` supports rustc 1.30\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\nfn assert_tracker_noexistence(key: &str) {\n    let v1_data: toml::Value =\n        toml::from_str(&fs::read_to_string(paths::cargo_home().join(\".crates.toml\")).unwrap())\n            .unwrap();\n    let v2_data: serde_json::Value = serde_json::from_str(\n        &fs::read_to_string(paths::cargo_home().join(\".crates2.json\")).unwrap(),\n    )\n    .unwrap();\n\n    assert!(v1_data[\"v1\"].get(key).is_none());\n    assert!(v2_data[\"installs\"][key].is_null());\n}\n\n#[cargo_test]\nfn uninstall_running_binary() {\n    use std::io::Write;\n\n    Package::new(\"foo\", \"0.0.1\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                use std::net::TcpStream;\n                use std::env::var;\n                use std::io::Read;\n                fn main() {\n                    for i in 0..2 {\n                        TcpStream::connect(&var(\"__ADDR__\").unwrap()[..])\n                            .unwrap()\n                            .read_to_end(&mut Vec::new())\n                            .unwrap();\n                    }\n                }\n            \"#,\n        )\n        .publish();\n\n    cargo_process(\"install foo\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[INSTALLING] foo v0.0.1\n[COMPILING] foo v0.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]]).run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n\n    let foo_bin = paths::cargo_home().join(\"bin\").join(exe(\"foo\"));\n    let l = std::net::TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let addr = l.local_addr().unwrap().to_string();\n    let t = thread::spawn(move || {\n        ProcessBuilder::new(foo_bin)\n            .env(\"__ADDR__\", addr)\n            .exec()\n            .unwrap();\n    });\n    let key = \"foo 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)\";\n\n    #[cfg(windows)]\n    {\n        // Ensure foo is running before the first `cargo uninstall` call\n        l.accept().unwrap().0.write_all(&[1]).unwrap();\n        cargo_process(\"uninstall foo\")\n            .with_status(101)\n            .with_stderr_data(str![[r#\"\n...\n[ERROR] failed to remove file `[ROOT]/home/.cargo/bin/foo[EXE]`\n...\n\"#]])\n            .run();\n        // Ensure foo is stopped before the second `cargo uninstall` call\n        l.accept().unwrap().0.write_all(&[1]).unwrap();\n        t.join().unwrap();\n        cargo_process(\"uninstall foo\")\n            .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE]\n\n\"#]])\n            .run();\n    };\n\n    #[cfg(not(windows))]\n    {\n        // Ensure foo is running before the first `cargo uninstall` call\n        l.accept().unwrap().0.write_all(&[1]).unwrap();\n        cargo_process(\"uninstall foo\")\n            .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE]\n\n\"#]])\n            .run();\n        l.accept().unwrap().0.write_all(&[1]).unwrap();\n        t.join().unwrap();\n    };\n\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n    assert_tracker_noexistence(key);\n\n    cargo_process(\"install foo\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[INSTALLING] foo v0.0.1\n[COMPILING] foo v0.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn dry_run() {\n    pkg(\"foo\", \"0.0.1\");\n\n    cargo_process(\"-Z unstable-options install --dry-run foo\")\n        .masquerade_as_nightly_cargo(&[\"install::dry-run\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[INSTALLING] foo v0.0.1\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[WARNING] aborting install due to dry run\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn dry_run_incompatible_package() {\n    Package::new(\"some-package-from-the-distant-future\", \"0.0.1\")\n        .rust_version(\"1.2345.0\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .publish();\n\n    cargo_process(\"-Z unstable-options install --dry-run some-package-from-the-distant-future\")\n        .masquerade_as_nightly_cargo(&[\"install::dry-run\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] cannot install package `some-package-from-the-distant-future 0.0.1`, it requires rustc 1.2345.0 or newer, while the currently active rustc version is [..]\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"some-package-from-the-distant-future\");\n}\n\n#[cargo_test]\nfn dry_run_incompatible_package_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                some-package-from-the-distant-future = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"some-package-from-the-distant-future\"\n                version = \"0.1.0\"\n                authors = []\n                rust-version = \"1.2345.0\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    cargo_process(\"-Z unstable-options install --dry-run --path\")\n        .arg(p.root())\n        .arg(\"foo\")\n        .masquerade_as_nightly_cargo(&[\"install::dry-run\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.1.0 ([ROOT]/foo)\n[LOCKING] 1 package to latest compatible version\n[ERROR] failed to compile `foo v0.1.0 ([ROOT]/foo)`, intermediate artifacts can be found at `[ROOT]/foo/target`.\nTo reuse those artifacts with a future compilation, set the environment variable `CARGO_BUILD_BUILD_DIR` to that path.\n\nCaused by:\n  rustc [..] is not supported by the following package:\n    some-package-from-the-distant-future@0.1.0 requires rustc 1.2345.0\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn dry_run_upgrade() {\n    pkg(\"foo\", \"0.0.1\");\n    cargo_process(\"install foo\").run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n\n    pkg(\"foo\", \"0.0.2\");\n    cargo_process(\"-Z unstable-options install --dry-run foo\")\n        .masquerade_as_nightly_cargo(&[\"install::dry-run\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.2 (registry `dummy-registry`)\n[INSTALLING] foo v0.0.2\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n[WARNING] aborting install due to dry run\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn dry_run_remove_orphan() {\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/bin/client.rs\", \"fn main() {}\")\n        .file(\"src/bin/server.rs\", \"fn main() {}\")\n        .publish();\n\n    cargo_process(\"install bar\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[INSTALLING] bar v1.0.0\n[COMPILING] bar v1.0.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/client[EXE]\n[INSTALLING] [ROOT]/home/.cargo/bin/server[EXE]\n[INSTALLED] package `bar v1.0.0` (executables `client[EXE]`, `server[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"client\");\n    assert_has_installed_exe(paths::cargo_home(), \"server\");\n\n    Package::new(\"bar\", \"2.0.0\")\n        .file(\"src/bin/client.rs\", \"fn main() {}\")\n        .publish();\n\n    cargo_process(\"-Z unstable-options install --dry-run bar\")\n        .masquerade_as_nightly_cargo(&[\"install::dry-run\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v2.0.0 (registry `dummy-registry`)\n[INSTALLING] bar v2.0.0\n[REPLACING] [ROOT]/home/.cargo/bin/client[EXE]\n[REMOVING] executable `[ROOT]/home/.cargo/bin/server[EXE]` from previous version bar v1.0.0\n[WARNING] aborting install due to dry run\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"client\");\n    // Ensure server is still installed after the dry run\n    assert_has_installed_exe(paths::cargo_home(), \"server\");\n}\n\n#[cargo_test]\nfn prefixed_v_in_version() {\n    pkg(\"foo\", \"0.0.1\");\n    cargo_process(\"install foo@v0.0.1\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid value 'foo@v0.0.1' for '[CRATE[@<VER>]]...': the version provided, `v0.0.1` is not a valid SemVer requirement\n\n[HELP] try changing the version to `0.0.1`\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn emoji_name() {\n    pkg(\"foo\", \"0.0.1\");\n    cargo_process(\"install 🦀\")\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid character `🦀` in package name: `🦀`, the first character must be a Unicode XID start character (most letters or `_`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn starts_with_number_case() {\n    pkg(\"foo\", \"0.0.1\");\n    cargo_process(\"install 23898932983\")\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid character `2` in package name: `23898932983`, the name cannot start with a digit\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn mistaken_flag_case() {\n    pkg(\"foo\", \"0.0.1\");\n    cargo_process(\"install ––path .\") // en dashes\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid character `–` in package name: `––path`, the first character must be a Unicode XID start character (most letters or `_`)\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/install_upgrade.rs",
    "content": "//! Tests for `cargo install` where it upgrades a package if it is out-of-date.\n\nuse std::collections::BTreeSet;\nuse std::env;\nuse std::fs;\nuse std::path::PathBuf;\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse crate::utils::cross_compile::disabled as cross_compile_disabled;\nuse cargo::core::PackageId;\nuse cargo_test_support::install::exe;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::{self, Package};\nuse cargo_test_support::{Execs, basic_manifest, cross_compile, execs, git, process, project, str};\n\nfn pkg_maybe_yanked(name: &str, vers: &str, yanked: bool) {\n    Package::new(name, vers)\n        .yanked(yanked)\n        .file(\n            \"src/main.rs\",\n            r#\"fn main() { println!(\"{}\", env!(\"CARGO_PKG_VERSION\")) }\"#,\n        )\n        .publish();\n}\n\n// Helper for publishing a package.\nfn pkg(name: &str, vers: &str) {\n    pkg_maybe_yanked(name, vers, false)\n}\n\nfn v1_path() -> PathBuf {\n    paths::cargo_home().join(\".crates.toml\")\n}\n\nfn v2_path() -> PathBuf {\n    paths::cargo_home().join(\".crates2.json\")\n}\n\nfn load_crates1() -> toml::Value {\n    toml::from_str(&fs::read_to_string(v1_path()).unwrap()).unwrap()\n}\n\nfn load_crates2() -> serde_json::Value {\n    serde_json::from_str(&fs::read_to_string(v2_path()).unwrap()).unwrap()\n}\n\nfn installed_exe(name: &str) -> PathBuf {\n    paths::cargo_home().join(\"bin\").join(exe(name))\n}\n\n/// Helper for executing binaries installed by cargo.\nfn installed_process(name: &str) -> Execs {\n    static NEXT_ID: AtomicUsize = AtomicUsize::new(0);\n    thread_local!(static UNIQUE_ID: usize = NEXT_ID.fetch_add(1, Ordering::SeqCst));\n\n    // This copies the executable to a unique name so that it may be safely\n    // replaced on Windows.  See Project::rename_run for details.\n    let src = installed_exe(name);\n    let dst = installed_exe(&UNIQUE_ID.with(|my_id| format!(\"{}-{}\", name, my_id)));\n    // Note: Cannot use copy. On Linux, file descriptors may be left open to\n    // the executable as other tests in other threads are constantly spawning\n    // new processes (see https://github.com/rust-lang/cargo/pull/5557 for\n    // more).\n    fs::rename(&src, &dst)\n        .unwrap_or_else(|e| panic!(\"Failed to rename `{:?}` to `{:?}`: {}\", src, dst, e));\n    // Leave behind a fake file so that reinstall duplicate check works.\n    fs::write(src, \"\").unwrap();\n    let p = process(dst);\n    execs().with_process_builder(p)\n}\n\n/// Check that the given package name/version has the following bins listed in\n/// the trackers. Also verifies that both trackers are in sync and valid.\n/// Pass in an empty `bins` list to assert that the package is *not* installed.\nfn validate_trackers(name: &str, version: &str, bins: &[&str]) {\n    let v1 = load_crates1();\n    let v1_table = v1.get(\"v1\").unwrap().as_table().unwrap();\n    let v2 = load_crates2();\n    let v2_table = v2[\"installs\"].as_object().unwrap();\n    assert_eq!(v1_table.len(), v2_table.len());\n    // Convert `bins` to a BTreeSet.\n    let bins: BTreeSet<String> = bins\n        .iter()\n        .map(|b| format!(\"{}{}\", b, env::consts::EXE_SUFFIX))\n        .collect();\n    // Check every entry matches between v1 and v2.\n    for (pkg_id_str, v1_bins) in v1_table {\n        let pkg_id: PackageId = toml::Value::from(pkg_id_str.to_string())\n            .try_into()\n            .unwrap();\n        let v1_bins: BTreeSet<String> = v1_bins\n            .as_array()\n            .unwrap()\n            .iter()\n            .map(|b| b.as_str().unwrap().to_string())\n            .collect();\n        if pkg_id.name().as_str() == name && pkg_id.version().to_string() == version {\n            if bins.is_empty() {\n                panic!(\n                    \"Expected {} to not be installed, but found: {:?}\",\n                    name, v1_bins\n                );\n            } else {\n                assert_eq!(bins, v1_bins);\n            }\n        }\n        let pkg_id_value = serde_json::to_value(&pkg_id).unwrap();\n        let pkg_id_str = pkg_id_value.as_str().unwrap();\n        let v2_info = v2_table\n            .get(pkg_id_str)\n            .expect(\"v2 missing v1 pkg\")\n            .as_object()\n            .unwrap();\n        let v2_bins = v2_info[\"bins\"].as_array().unwrap();\n        let v2_bins: BTreeSet<String> = v2_bins\n            .iter()\n            .map(|b| b.as_str().unwrap().to_string())\n            .collect();\n        assert_eq!(v1_bins, v2_bins);\n    }\n}\n\n#[cargo_test]\nfn registry_upgrade() {\n    // Installing and upgrading from a registry.\n    pkg(\"foo\", \"1.0.0\");\n    cargo_process(\"install foo\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v1.0.0 (registry `dummy-registry`)\n[INSTALLING] foo v1.0.0\n[COMPILING] foo v1.0.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v1.0.0` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]]).run();\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\n1.0.0\n\n\"#]])\n        .run();\n    validate_trackers(\"foo\", \"1.0.0\", &[\"foo\"]);\n\n    cargo_process(\"install foo\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[IGNORED] package `foo v1.0.0` is already installed, use --force to override\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]]).run();\n\n    pkg(\"foo\", \"1.0.1\");\n\n    cargo_process(\"install foo\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v1.0.1 (registry `dummy-registry`)\n[INSTALLING] foo v1.0.1\n[COMPILING] foo v1.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n[REPLACED] package `foo v1.0.0` with `foo v1.0.1` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]]).run();\n\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\n1.0.1\n\n\"#]])\n        .run();\n    validate_trackers(\"foo\", \"1.0.1\", &[\"foo\"]);\n\n    cargo_process(\"install foo --version=1.0.0\")\n        .with_stderr_data(str![[r#\"\n...\n[COMPILING] foo v1.0.0\n...\n\"#]])\n        .run();\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\n1.0.0\n\n\"#]])\n        .run();\n    validate_trackers(\"foo\", \"1.0.0\", &[\"foo\"]);\n\n    cargo_process(\"install foo --version=^1.0\")\n        .with_stderr_data(str![[r#\"\n...\n[COMPILING] foo v1.0.1\n...\n\"#]])\n        .run();\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\n1.0.1\n\n\"#]])\n        .run();\n    validate_trackers(\"foo\", \"1.0.1\", &[\"foo\"]);\n\n    cargo_process(\"install foo --version=^1.0\")\n        .with_stderr_data(str![[r#\"\n...\n[IGNORED] package `foo v1.0.1` is already installed, use --force to override\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn uninstall() {\n    // Basic uninstall test.\n    pkg(\"foo\", \"1.0.0\");\n    cargo_process(\"install foo\").run();\n    cargo_process(\"uninstall foo\").run();\n    let data = load_crates2();\n    assert_eq!(data[\"installs\"].as_object().unwrap().len(), 0);\n    let v1_table = load_crates1();\n    assert_eq!(v1_table.get(\"v1\").unwrap().as_table().unwrap().len(), 0);\n}\n\n#[cargo_test]\nfn upgrade_force() {\n    pkg(\"foo\", \"1.0.0\");\n    cargo_process(\"install foo\").run();\n    cargo_process(\"install foo --force\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[INSTALLING] foo v1.0.0\n[COMPILING] foo v1.0.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n[REPLACED] package `foo v1.0.0` with `foo v1.0.0` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    validate_trackers(\"foo\", \"1.0.0\", &[\"foo\"]);\n}\n\n#[cargo_test]\nfn ambiguous_version_no_longer_allowed() {\n    // Non-semver-requirement is not allowed for `--version`.\n    pkg(\"foo\", \"1.0.0\");\n    cargo_process(\"install foo --version=1.0\")\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid value '1.0' for '--version <VERSION>': unexpected end of input while parsing minor version number\n\n  tip: if you want to specify SemVer range, add an explicit qualifier, like '^1.0'\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn path_is_always_dirty() {\n    // --path should always reinstall.\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"install --path .\").run();\n    p.cargo(\"install --path .\")\n        .with_stderr_data(str![[r#\"\n...\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fails_for_conflicts_unknown() {\n    // If an untracked file is in the way, it should fail.\n    pkg(\"foo\", \"1.0.0\");\n    let exe = installed_exe(\"foo\");\n    exe.parent().unwrap().mkdir_p();\n    fs::write(exe, \"\").unwrap();\n    cargo_process(\"install foo\")\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] binary `foo[EXE]` already exists in destination\n...\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn fails_for_conflicts_known() {\n    // If the same binary exists in another package, it should fail.\n    pkg(\"foo\", \"1.0.0\");\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/bin/foo.rs\", \"fn main() {}\")\n        .publish();\n    cargo_process(\"install foo\").run();\n    cargo_process(\"install bar\")\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] binary `foo[EXE]` already exists in destination as part of `foo v1.0.0`\n...\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn supports_multiple_binary_names() {\n    // Can individually install with --bin or --example\n    Package::new(\"foo\", \"1.0.0\")\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"foo\"); }\"#)\n        .file(\"src/bin/a.rs\", r#\"fn main() { println!(\"a\"); }\"#)\n        .file(\"examples/ex1.rs\", r#\"fn main() { println!(\"ex1\"); }\"#)\n        .publish();\n    cargo_process(\"install foo --bin foo\").run();\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\nfoo\n\n\"#]])\n        .run();\n    assert!(!installed_exe(\"a\").exists());\n    assert!(!installed_exe(\"ex1\").exists());\n    validate_trackers(\"foo\", \"1.0.0\", &[\"foo\"]);\n    cargo_process(\"install foo --bin a\").run();\n    installed_process(\"a\")\n        .with_stdout_data(str![[r#\"\na\n\n\"#]])\n        .run();\n    assert!(!installed_exe(\"ex1\").exists());\n    validate_trackers(\"foo\", \"1.0.0\", &[\"a\", \"foo\"]);\n    cargo_process(\"install foo --example ex1\").run();\n    installed_process(\"ex1\")\n        .with_stdout_data(str![[r#\"\nex1\n\n\"#]])\n        .run();\n    validate_trackers(\"foo\", \"1.0.0\", &[\"a\", \"ex1\", \"foo\"]);\n    cargo_process(\"uninstall foo --bin foo\").run();\n    assert!(!installed_exe(\"foo\").exists());\n    assert!(installed_exe(\"ex1\").exists());\n    validate_trackers(\"foo\", \"1.0.0\", &[\"a\", \"ex1\"]);\n    cargo_process(\"uninstall foo\").run();\n    assert!(!installed_exe(\"ex1\").exists());\n    assert!(!installed_exe(\"a\").exists());\n}\n\n#[cargo_test]\nfn v1_already_installed_fresh() {\n    // Install with v1, then try to install again with v2.\n    pkg(\"foo\", \"1.0.0\");\n    cargo_process(\"install foo\").run();\n    cargo_process(\"install foo\")\n        .with_stderr_data(str![[r#\"\n...\n[IGNORED] package `foo v1.0.0` is already installed, use --force to override\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn v1_already_installed_dirty() {\n    // Install with v1, then install a new version with v2.\n    pkg(\"foo\", \"1.0.0\");\n    cargo_process(\"install foo\").run();\n    pkg(\"foo\", \"1.0.1\");\n    cargo_process(\"install foo\")\n        .with_stderr_data(str![[r#\"\n...\n[COMPILING] foo v1.0.1\n...\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n...\n\"#]])\n        .run();\n    validate_trackers(\"foo\", \"1.0.1\", &[\"foo\"]);\n}\n\n#[cargo_test]\nfn change_features_rebuilds() {\n    Package::new(\"foo\", \"1.0.0\")\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                if cfg!(feature = \"f1\") {\n                    println!(\"f1\");\n                }\n                if cfg!(feature = \"f2\") {\n                    println!(\"f2\");\n                }\n            }\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n\n            [features]\n            f1 = []\n            f2 = []\n            default = [\"f1\"]\n            \"#,\n        )\n        .publish();\n    cargo_process(\"install foo\").run();\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\nf1\n\n\"#]])\n        .run();\n    cargo_process(\"install foo --no-default-features\").run();\n    installed_process(\"foo\").with_stdout_data(\"\").run();\n    cargo_process(\"install foo --all-features\").run();\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\nf1\nf2\n\n\"#]])\n        .run();\n    cargo_process(\"install foo --no-default-features --features=f1\").run();\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\nf1\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn change_profile_rebuilds() {\n    pkg(\"foo\", \"1.0.0\");\n    cargo_process(\"install foo\").run();\n    cargo_process(\"install foo --debug\")\n        .with_stderr_data(str![[r#\"\n...\n[COMPILING] foo v1.0.0\n...\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n...\n\"#]])\n        .run();\n    cargo_process(\"install foo --debug\")\n        .with_stderr_data(str![[r#\"\n...\n[IGNORED] package `foo v1.0.0` is already installed, use --force to override\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn change_target_rebuilds() {\n    if cross_compile_disabled() {\n        return;\n    }\n    pkg(\"foo\", \"1.0.0\");\n    cargo_process(\"install foo\").run();\n    let target = cross_compile::alternate();\n    cargo_process(\"install foo -v --target\")\n        .arg(&target)\n        .with_stderr_data(str![[r#\"\n...\n[COMPILING] foo v1.0.0\n[RUNNING] `rustc [..]--target [ALT_TARGET][..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn change_bin_sets_rebuilds() {\n    // Changing which bins in a multi-bin project should reinstall.\n    Package::new(\"foo\", \"1.0.0\")\n        .file(\"src/main.rs\", \"fn main() { }\")\n        .file(\"src/bin/x.rs\", \"fn main() { }\")\n        .file(\"src/bin/y.rs\", \"fn main() { }\")\n        .publish();\n    cargo_process(\"install foo --bin x\").run();\n    assert!(installed_exe(\"x\").exists());\n    assert!(!installed_exe(\"y\").exists());\n    assert!(!installed_exe(\"foo\").exists());\n    validate_trackers(\"foo\", \"1.0.0\", &[\"x\"]);\n    cargo_process(\"install foo --bin y\")\n        .with_stderr_data(str![[r#\"\n...\n[INSTALLED] package `foo v1.0.0` (executable `y[EXE]`)\n...\n\"#]])\n        .run();\n    assert!(installed_exe(\"x\").exists());\n    assert!(installed_exe(\"y\").exists());\n    assert!(!installed_exe(\"foo\").exists());\n    validate_trackers(\"foo\", \"1.0.0\", &[\"x\", \"y\"]);\n    cargo_process(\"install foo\")\n        .with_stderr_data(str![[r#\"\n...\n[INSTALLED] package `foo v1.0.0` (executable `foo[EXE]`)\n[REPLACED] package `foo v1.0.0` with `foo v1.0.0` (executables `x[EXE]`, `y[EXE]`)\n...\n\"#]])\n        .run();\n    assert!(installed_exe(\"x\").exists());\n    assert!(installed_exe(\"y\").exists());\n    assert!(installed_exe(\"foo\").exists());\n    validate_trackers(\"foo\", \"1.0.0\", &[\"foo\", \"x\", \"y\"]);\n}\n\n#[cargo_test]\nfn forwards_compatible() {\n    // Unknown fields should be preserved.\n    pkg(\"foo\", \"1.0.0\");\n    pkg(\"bar\", \"1.0.0\");\n    cargo_process(\"install foo\").run();\n    let key = \"foo 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)\";\n    let v2 = paths::cargo_home().join(\".crates2.json\");\n    let mut data = load_crates2();\n    data[\"newfield\"] = serde_json::Value::Bool(true);\n    data[\"installs\"][key][\"moreinfo\"] = serde_json::Value::String(\"shazam\".to_string());\n    fs::write(&v2, serde_json::to_string(&data).unwrap()).unwrap();\n    cargo_process(\"install bar\").run();\n    let data: serde_json::Value = serde_json::from_str(&fs::read_to_string(&v2).unwrap()).unwrap();\n    assert_eq!(data[\"newfield\"].as_bool().unwrap(), true);\n    assert_eq!(\n        data[\"installs\"][key][\"moreinfo\"].as_str().unwrap(),\n        \"shazam\"\n    );\n}\n\n#[cargo_test]\nfn v2_syncs() {\n    // V2 inherits the installs from V1.\n    pkg(\"one\", \"1.0.0\");\n    pkg(\"two\", \"1.0.0\");\n    pkg(\"three\", \"1.0.0\");\n    let p = project()\n        .file(\"src/bin/x.rs\", \"fn main() {}\")\n        .file(\"src/bin/y.rs\", \"fn main() {}\")\n        .build();\n    cargo_process(\"install one\").run();\n    validate_trackers(\"one\", \"1.0.0\", &[\"one\"]);\n    p.cargo(\"install --path .\").run();\n    validate_trackers(\"foo\", \"1.0.0\", &[\"x\", \"y\"]);\n    // v1 add/remove\n    cargo_process(\"install two\").run();\n    cargo_process(\"uninstall one\").run();\n    // This should pick up that `two` was added, `one` was removed.\n    cargo_process(\"install three\").run();\n    validate_trackers(\"three\", \"1.0.0\", &[\"three\"]);\n    cargo_process(\"install --list\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo):\n    x[EXE]\n    y[EXE]\nthree v1.0.0:\n    three[EXE]\ntwo v1.0.0:\n    two[EXE]\n\n\"#]])\n        .run();\n    cargo_process(\"install one\").run();\n    installed_process(\"one\")\n        .with_stdout_data(str![[r#\"\n1.0.0\n\n\"#]])\n        .run();\n    validate_trackers(\"one\", \"1.0.0\", &[\"one\"]);\n    cargo_process(\"install two\")\n        .with_stderr_data(str![[r#\"\n...\n[IGNORED] package `two v1.0.0` is already installed, use --force to override\n...\n\"#]])\n        .run();\n    // v1 remove\n    p.cargo(\"uninstall --bin x\").run();\n    pkg(\"x\", \"1.0.0\");\n    pkg(\"y\", \"1.0.0\");\n    // This should succeed because `x` was removed in V1.\n    cargo_process(\"install x\").run();\n    validate_trackers(\"x\", \"1.0.0\", &[\"x\"]);\n    // This should fail because `y` still exists in a different package.\n    cargo_process(\"install y\")\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] binary `y[EXE]` already exists in destination as part of `foo v0.0.1 ([ROOT]/foo)`\n...\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn upgrade_git() {\n    let git_project = git::new(\"foo\", |project| project.file(\"src/main.rs\", \"fn main() {}\"));\n    // install\n    cargo_process(\"install --git\")\n        .arg(git_project.url().to_string())\n        .run();\n    // Check install stays fresh.\n    cargo_process(\"install --git\")\n        .arg(git_project.url().to_string())\n        .with_stderr_data(str![[r#\"\n...\n[IGNORED] package `foo v0.0.1 ([ROOTURL]/foo#[..])` is already installed, use --force to override\n...\n\"#]])\n        .run();\n    // Modify a file.\n    let repo = git2::Repository::open(git_project.root()).unwrap();\n    git_project.change_file(\"src/main.rs\", r#\"fn main() {println!(\"onomatopoeia\");}\"#);\n    git::add(&repo);\n    git::commit(&repo);\n    // Install should reinstall.\n    cargo_process(\"install --git\")\n        .arg(git_project.url().to_string())\n        .with_stderr_data(str![[r#\"\n...\n[COMPILING] foo v0.0.1 ([ROOT]/home/.cargo/git/checkouts/foo-[HASH]/[..])\n...\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n...\n\"#]])\n        .run();\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\nonomatopoeia\n\n\"#]])\n        .run();\n    // Check install stays fresh.\n    cargo_process(\"install --git\")\n        .arg(git_project.url().to_string())\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/foo`\n[IGNORED] package `foo v0.0.1 ([ROOTURL]/foo#[..])` is already installed, use --force to override\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn switch_sources() {\n    // Installing what appears to be the same thing, but from different\n    // sources should reinstall.\n    registry::alt_init();\n    pkg(\"foo\", \"1.0.0\");\n    Package::new(\"foo\", \"1.0.0\")\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"alt\"); }\"#)\n        .alternative(true)\n        .publish();\n    let p = project()\n        .at(\"foo-local\") // so it doesn't use the same directory as the git project\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"local\"); }\"#)\n        .build();\n    let git_project = git::new(\"foo\", |project| {\n        project.file(\"src/main.rs\", r#\"fn main() { println!(\"git\"); }\"#)\n    });\n\n    cargo_process(\"install foo\").run();\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\n1.0.0\n\n\"#]])\n        .run();\n    cargo_process(\"install foo --registry alternative\").run();\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\nalt\n\n\"#]])\n        .run();\n    p.cargo(\"install --path .\").run();\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\nlocal\n\n\"#]])\n        .run();\n    cargo_process(\"install --git\")\n        .arg(git_project.url().to_string())\n        .run();\n    installed_process(\"foo\")\n        .with_stdout_data(str![[r#\"\ngit\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_report() {\n    // Testing the full output that indicates installed/ignored/replaced/summary.\n    pkg(\"one\", \"1.0.0\");\n    pkg(\"two\", \"1.0.0\");\n    fn three(vers: &str) {\n        Package::new(\"three\", vers)\n            .file(\"src/main.rs\", \"fn main() { }\")\n            .file(\"src/bin/x.rs\", \"fn main() { }\")\n            .file(\"src/bin/y.rs\", \"fn main() { }\")\n            .publish();\n    }\n    three(\"1.0.0\");\n    cargo_process(\"install one two three\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] one v1.0.0 (registry `dummy-registry`)\n[DOWNLOADING] crates ...\n[DOWNLOADED] two v1.0.0 (registry `dummy-registry`)\n[DOWNLOADING] crates ...\n[DOWNLOADED] three v1.0.0 (registry `dummy-registry`)\n[INSTALLING] one v1.0.0\n[COMPILING] one v1.0.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/one[EXE]\n[INSTALLED] package `one v1.0.0` (executable `one[EXE]`)\n[INSTALLING] two v1.0.0\n[COMPILING] two v1.0.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/two[EXE]\n[INSTALLED] package `two v1.0.0` (executable `two[EXE]`)\n[INSTALLING] three v1.0.0\n[COMPILING] three v1.0.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/three[EXE]\n[INSTALLING] [ROOT]/home/.cargo/bin/x[EXE]\n[INSTALLING] [ROOT]/home/.cargo/bin/y[EXE]\n[INSTALLED] package `three v1.0.0` (executables `three[EXE]`, `x[EXE]`, `y[EXE]`)\n[SUMMARY] Successfully installed one, two, three!\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    pkg(\"foo\", \"1.0.1\");\n    pkg(\"bar\", \"1.0.1\");\n    three(\"1.0.1\");\n    cargo_process(\"install one two three\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[IGNORED] package `one v1.0.0` is already installed, use --force to override\n[IGNORED] package `two v1.0.0` is already installed, use --force to override\n[DOWNLOADING] crates ...\n[DOWNLOADED] three v1.0.1 (registry `dummy-registry`)\n[INSTALLING] three v1.0.1\n[COMPILING] three v1.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[REPLACING] [ROOT]/home/.cargo/bin/three[EXE]\n[REPLACING] [ROOT]/home/.cargo/bin/x[EXE]\n[REPLACING] [ROOT]/home/.cargo/bin/y[EXE]\n[REPLACED] package `three v1.0.0` with `three v1.0.1` (executables `three[EXE]`, `x[EXE]`, `y[EXE]`)\n[SUMMARY] Successfully installed one, two, three!\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    cargo_process(\"uninstall three\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/home/.cargo/bin/three[EXE]\n[REMOVING] [ROOT]/home/.cargo/bin/x[EXE]\n[REMOVING] [ROOT]/home/.cargo/bin/y[EXE]\n\n\"#]])\n        .run();\n    cargo_process(\"install three --bin x\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[INSTALLING] three v1.0.1\n[COMPILING] three v1.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/x[EXE]\n[INSTALLED] package `three v1.0.1` (executable `x[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    cargo_process(\"install three\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[INSTALLING] three v1.0.1\n[COMPILING] three v1.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/three[EXE]\n[INSTALLING] [ROOT]/home/.cargo/bin/y[EXE]\n[REPLACING] [ROOT]/home/.cargo/bin/x[EXE]\n[INSTALLED] package `three v1.0.1` (executables `three[EXE]`, `y[EXE]`)\n[REPLACED] package `three v1.0.1` with `three v1.0.1` (executable `x[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_track() {\n    pkg(\"foo\", \"1.0.0\");\n    cargo_process(\"install --no-track foo\").run();\n    assert!(!v1_path().exists());\n    assert!(!v2_path().exists());\n    cargo_process(\"install --no-track foo\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] binary `foo[EXE]` already exists in destination `[ROOT]/home/.cargo/bin/foo[EXE]`\nAdd --force to overwrite\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn deletes_orphaned() {\n    // When an executable is removed from a project, upgrading should remove it.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/bin/other.rs\", \"fn main() {}\")\n        .file(\"examples/ex1.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"install --path . --bins --examples\").run();\n    assert!(installed_exe(\"other\").exists());\n\n    // Remove a binary, add a new one, and bump the version.\n    fs::remove_file(p.root().join(\"src/bin/other.rs\")).unwrap();\n    p.change_file(\"examples/ex2.rs\", \"fn main() {}\");\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n        [package]\n        name = \"foo\"\n        version = \"0.2.0\"\n        \"#,\n    );\n    p.cargo(\"install --path . --bins --examples\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.2.0 ([ROOT]/foo)\n[COMPILING] foo v0.2.0 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/ex2[EXE]\n[REPLACING] [ROOT]/home/.cargo/bin/ex1[EXE]\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n[REMOVING] executable `[ROOT]/home/.cargo/bin/other[EXE]` from previous version foo v0.1.0 ([ROOT]/foo)\n[INSTALLED] package `foo v0.2.0 ([ROOT]/foo)` (executable `ex2[EXE]`)\n[REPLACED] package `foo v0.1.0 ([ROOT]/foo)` with `foo v0.2.0 ([ROOT]/foo)` (executables `ex1[EXE]`, `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    assert!(!installed_exe(\"other\").exists());\n    validate_trackers(\"foo\", \"0.2.0\", &[\"foo\", \"ex1\", \"ex2\"]);\n    // 0.1.0 should not have any entries.\n    validate_trackers(\"foo\", \"0.1.0\", &[]);\n}\n\n#[cargo_test]\nfn already_installed_exact_does_not_update() {\n    pkg(\"foo\", \"1.0.0\");\n    cargo_process(\"install foo  --version=1.0.0\").run();\n    cargo_process(\"install foo --version=1.0.0\")\n        .with_stderr_data(str![[r#\"\n[IGNORED] package `foo v1.0.0` is already installed, use --force to override\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n\n    cargo_process(\"install foo --version=>=1.0.0\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[IGNORED] package `foo v1.0.0` is already installed, use --force to override\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n    pkg(\"foo\", \"1.0.1\");\n    cargo_process(\"install foo --version=>=1.0.0\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v1.0.1 (registry `dummy-registry`)\n[INSTALLING] foo v1.0.1\n[COMPILING] foo v1.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n[REPLACED] package `foo v1.0.0` with `foo v1.0.1` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn already_installed_updates_yank_status_on_upgrade() {\n    pkg(\"foo\", \"1.0.0\");\n    pkg_maybe_yanked(\"foo\", \"1.0.1\", true);\n    cargo_process(\"install foo  --version=1.0.0\").run();\n\n    cargo_process(\"install foo --version=1.0.1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] cannot install package `foo`, it has been yanked from registry `crates-io`\n\n\"#]])\n        .run();\n\n    pkg_maybe_yanked(\"foo\", \"1.0.1\", false);\n\n    pkg(\"foo\", \"1.0.1\");\n    cargo_process(\"install foo --version=1.0.1\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v1.0.1 (registry `dummy-registry`)\n[INSTALLING] foo v1.0.1\n[COMPILING] foo v1.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n[REPLACED] package `foo v1.0.0` with `foo v1.0.1` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn partially_already_installed_does_one_update() {\n    pkg(\"foo\", \"1.0.0\");\n    cargo_process(\"install foo  --version=1.0.0\").run();\n    pkg(\"bar\", \"1.0.0\");\n    pkg(\"baz\", \"1.0.0\");\n    cargo_process(\"install foo bar baz --version=1.0.0\")\n        .with_stderr_data(str![[r#\"\n[IGNORED] package `foo v1.0.0` is already installed, use --force to override\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v1.0.0 (registry `dummy-registry`)\n[INSTALLING] bar v1.0.0\n[COMPILING] bar v1.0.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/bar[EXE]\n[INSTALLED] package `bar v1.0.0` (executable `bar[EXE]`)\n[INSTALLING] baz v1.0.0\n[COMPILING] baz v1.0.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/baz[EXE]\n[INSTALLED] package `baz v1.0.0` (executable `baz[EXE]`)\n[SUMMARY] Successfully installed foo, bar, baz!\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/jobserver.rs",
    "content": "//! Tests for the jobserver protocol.\n\nuse std::env;\nuse std::net::TcpListener;\nuse std::process::Command;\nuse std::thread;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_exe;\nuse cargo_test_support::basic_bin_manifest;\nuse cargo_test_support::install::assert_has_installed_exe;\nuse cargo_test_support::paths;\nuse cargo_test_support::{project, rustc_host, str};\nuse cargo_util::is_ci;\n\nconst EXE_CONTENT: &str = r#\"\nuse std::env;\n\nfn main() {\n    let var = env::var(\"CARGO_MAKEFLAGS\").expect(\"no jobserver from env\");\n    let arg = var.split(' ')\n                 .find(|p| p.starts_with(\"--jobserver\"))\n                .unwrap();\n    let val = &arg[arg.find('=').unwrap() + 1..];\n    validate(val);\n}\n\n#[cfg(unix)]\nfn validate(s: &str) {\n    use std::fs::{self, File};\n    use std::io::*;\n    use std::os::unix::prelude::*;\n\n    if let Some((r, w)) = s.split_once(',') {\n        // `--jobserver-auth=R,W`\n        unsafe {\n            let mut read = File::from_raw_fd(r.parse().unwrap());\n            let mut write = File::from_raw_fd(w.parse().unwrap());\n\n            let mut buf = [0];\n            assert_eq!(read.read(&mut buf).unwrap(), 1);\n            assert_eq!(write.write(&buf).unwrap(), 1);\n        }\n    } else {\n        // `--jobserver-auth=fifo:PATH` is the default since GNU Make 4.4\n        let (_, path) = s.split_once(':').expect(\"fifo:PATH\");\n        assert!(fs::metadata(path).unwrap().file_type().is_fifo());\n    }\n}\n\n#[cfg(windows)]\nfn validate(_: &str) {\n    // a little too complicated for a test...\n}\n\"#;\n\nfn make_exe() -> &'static str {\n    if cfg!(windows) {\n        \"mingw32-make\"\n    } else if cfg!(target_os = \"aix\") {\n        \"gmake\"\n    } else {\n        \"make\"\n    }\n}\n\n#[cargo_test]\nfn jobserver_exists() {\n    let p = project()\n        .file(\"build.rs\", EXE_CONTENT)\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Explicitly use `-j2` to ensure that there's eventually going to be a\n    // token to read from `validate` above, since running the build script\n    // itself consumes a token.\n    p.cargo(\"check -j2\").run();\n}\n\n#[cargo_test]\nfn external_subcommand_inherits_jobserver() {\n    let make = make_exe();\n    if Command::new(make).arg(\"--version\").output().is_err() {\n        return;\n    }\n\n    let name = \"cargo-jobserver-check\";\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"{name}\"\n                    version = \"0.0.1\"\n                \"#\n            ),\n        )\n        .file(\"src/main.rs\", EXE_CONTENT)\n        .file(\n            \"Makefile\",\n            \"\\\nall:\n\\t+$(CARGO) jobserver-check\n\",\n        )\n        .build();\n\n    p.cargo(\"install --path .\").run();\n    assert_has_installed_exe(paths::cargo_home(), name);\n\n    p.process(make).env(\"CARGO\", cargo_exe()).arg(\"-j2\").run();\n}\n\n#[cargo_test]\nfn runner_inherits_jobserver() {\n    let make = make_exe();\n    if Command::new(make).arg(\"--version\").output().is_err() {\n        return;\n    }\n\n    let runner = \"runner\";\n    project()\n        .at(runner)\n        .file(\"Cargo.toml\", &basic_bin_manifest(runner))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            pub fn main() {\n                eprintln!(\"this is a runner\");\n                let args: Vec<String> = std::env::args().collect();\n                let status = std::process::Command::new(&args[1]).status().unwrap();\n                assert!(status.success());\n            }\n            \"#,\n        )\n        .build()\n        .cargo(\"install --path .\")\n        .run();\n\n    // Add .cargo/bin to PATH\n    let mut path: Vec<_> = env::split_paths(&env::var_os(\"PATH\").unwrap_or_default()).collect();\n    path.push(paths::cargo_home().join(\"bin\"));\n    let path = &env::join_paths(path).unwrap();\n    assert_has_installed_exe(paths::cargo_home(), runner);\n\n    let host = rustc_host();\n    let config_value = &format!(\"target.{host}.runner = \\\"{runner}\\\"\");\n\n    let name = \"cargo-jobserver-check\";\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"{name}\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                \"#\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n#[test]\nfn test() {\n    _ = std::env::var(\"CARGO_MAKEFLAGS\").expect(\"no jobserver from env\");\n}\n        \"#,\n        )\n        .file(\"src/main.rs\", EXE_CONTENT)\n        .file(\n            \"Makefile\",\n            &format!(\n                \"\\\nrun:\n\\t+$(CARGO) run\n\nrun-runner:\n\\t+$(CARGO) run --config '{config_value}'\n\ntest:\n\\t+$(CARGO) test --lib\n\ntest-runner:\n\\t+$(CARGO) test --lib --config '{config_value}'\n\",\n            ),\n        )\n        .build();\n\n    // jobserver can be inherited from env\n    p.process(make)\n        .env(\"CARGO\", cargo_exe())\n        .arg(\"run\")\n        .arg(\"-j2\")\n        .run();\n    p.process(make)\n        .env(\"PATH\", path)\n        .env(\"CARGO\", cargo_exe())\n        .arg(\"run-runner\")\n        .arg(\"-j2\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `runner target/debug/cargo-jobserver-check[EXE]`\nthis is a runner\n\n\"#]])\n        .run();\n    p.process(make)\n        .env(\"CARGO\", cargo_exe())\n        .arg(\"test\")\n        .arg(\"-j2\")\n        .run();\n    p.process(make)\n        .env(\"PATH\", path)\n        .env(\"CARGO\", cargo_exe())\n        .arg(\"test-runner\")\n        .arg(\"-j2\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/cargo_jobserver_check-[HASH][EXE])\nthis is a runner\n\n\"#]])\n        .run();\n\n    // but not from `-j` flag\n    p.cargo(\"run -j2\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/cargo-jobserver-check[EXE]`\n...\n[..]no jobserver from env[..]\n...\n\n\"#]])\n        .run();\n    p.cargo(\"run -j2\")\n        .env(\"PATH\", path)\n        .arg(\"--config\")\n        .arg(config_value)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `runner target/debug/cargo-jobserver-check[EXE]`\nthis is a runner\n...\n[..]no jobserver from env[..]\n...\n\n\"#]])\n        .run();\n    p.cargo(\"test -j2\")\n        .with_status(101)\n        .with_stdout_data(\"...\\n[..]no jobserver from env[..]\\n...\")\n        .run();\n    p.cargo(\"test -j2\")\n        .env(\"PATH\", path)\n        .arg(\"--config\")\n        .arg(config_value)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/cargo_jobserver_check-[HASH][EXE])\nthis is a runner\n...\n\n\"#]])\n        .with_stdout_data(\"...\\n[..]no jobserver from env[..]\\n...\")\n        .run();\n}\n\n#[cargo_test]\nfn makes_jobserver_used() {\n    let make = make_exe();\n    if !is_ci() && Command::new(make).arg(\"--version\").output().is_err() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [dependencies]\n                d1 = { path = \"d1\" }\n                d2 = { path = \"d2\" }\n                d3 = { path = \"d3\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.1\"\n                authors = []\n                build = \"../dbuild.rs\"\n            \"#,\n        )\n        .file(\"d1/src/lib.rs\", \"\")\n        .file(\n            \"d2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d2\"\n                version = \"0.0.1\"\n                authors = []\n                build = \"../dbuild.rs\"\n            \"#,\n        )\n        .file(\"d2/src/lib.rs\", \"\")\n        .file(\n            \"d3/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d3\"\n                version = \"0.0.1\"\n                authors = []\n                build = \"../dbuild.rs\"\n            \"#,\n        )\n        .file(\"d3/src/lib.rs\", \"\")\n        .file(\n            \"dbuild.rs\",\n            r#\"\n                use std::net::TcpStream;\n                use std::env;\n                use std::io::Read;\n\n                fn main() {\n                    let addr = env::var(\"ADDR\").unwrap();\n                    let mut stream = TcpStream::connect(addr).unwrap();\n                    let mut v = Vec::new();\n                    stream.read_to_end(&mut v).unwrap();\n                }\n            \"#,\n        )\n        .file(\n            \"Makefile\",\n            \"\\\nall:\n\\t+$(CARGO) build\n\",\n        )\n        .build();\n\n    let l = TcpListener::bind(\"127.0.0.1:0\").unwrap();\n    let addr = l.local_addr().unwrap();\n\n    let child = thread::spawn(move || {\n        let a1 = l.accept().unwrap();\n        let a2 = l.accept().unwrap();\n        l.set_nonblocking(true).unwrap();\n\n        for _ in 0..1000 {\n            assert!(l.accept().is_err());\n            thread::yield_now();\n        }\n\n        drop(a1);\n        l.set_nonblocking(false).unwrap();\n        let a3 = l.accept().unwrap();\n\n        drop((a2, a3));\n    });\n\n    p.process(make)\n        .env(\"CARGO\", cargo_exe())\n        .env(\"ADDR\", addr.to_string())\n        .arg(\"-j2\")\n        .run();\n    child.join().unwrap();\n}\n\n#[cargo_test]\nfn jobserver_and_j() {\n    let make = make_exe();\n    if !is_ci() && Command::new(make).arg(\"--version\").output().is_err() {\n        return;\n    }\n\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Makefile\",\n            \"\\\nall:\n\\t+$(CARGO) build -j2\n\",\n        )\n        .build();\n\n    p.process(make)\n        .env(\"CARGO\", cargo_exe())\n        .arg(\"-j2\")\n        .with_stderr_data(str![[r#\"\n[WARNING] a `-j` argument was passed to Cargo but Cargo is also configured with an external jobserver in its environment, ignoring the `-j` parameter\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/blanket_hint_mostly_unused.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test(nightly, reason = \"-Zhint-mostly-unused is unstable\")]\nfn named_profile_blanket() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\n\n[profile.dev]\nhint-mostly-unused = true\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Zprofile-hint-mostly-unused -v\")\n        .masquerade_as_nightly_cargo(&[\"profile-hint-mostly-unused\", \"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `hint-mostly-unused` is being blanket applied to all dependencies\n --> Cargo.toml:7:10\n  |\n7 | [profile.dev]\n  |          ^^^\n8 | hint-mostly-unused = true\n  | -------------------------\n  |\n  = [NOTE] `cargo::blanket_hint_mostly_unused` is set to `warn` by default\n[HELP] scope `hint-mostly-unused` to specific packages with a lot of unused object code\n  |\n7 | [profile.dev.package.<pkg_name>]\n  |             +++++++++++++++++++\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zhint-mostly-unused is unstable\")]\nfn profile_package_wildcard() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\n\n[profile.dev.package.\"*\"]\nhint-mostly-unused = true\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Zprofile-hint-mostly-unused -v\")\n        .masquerade_as_nightly_cargo(&[\"profile-hint-mostly-unused\", \"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `hint-mostly-unused` is being blanket applied to all dependencies\n --> Cargo.toml:7:22\n  |\n7 | [profile.dev.package.\"*\"]\n  |                      ^^^\n8 | hint-mostly-unused = true\n  | -------------------------\n  |\n  = [HELP] scope `hint-mostly-unused` to specific packages with a lot of unused object code\n  = [NOTE] `cargo::blanket_hint_mostly_unused` is set to `warn` by default\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zhint-mostly-unused is unstable\")]\nfn profile_build_override() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\n\n[profile.dev.build-override]\nhint-mostly-unused = true\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Zprofile-hint-mostly-unused -v\")\n        .masquerade_as_nightly_cargo(&[\"profile-hint-mostly-unused\", \"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `hint-mostly-unused` is being blanket applied to all dependencies\n --> Cargo.toml:7:14\n  |\n7 | [profile.dev.build-override]\n  |              ^^^^^^^^^^^^^^\n8 | hint-mostly-unused = true\n  | -------------------------\n  |\n  = [HELP] scope `hint-mostly-unused` to specific packages with a lot of unused object code\n  = [NOTE] `cargo::blanket_hint_mostly_unused` is set to `warn` by default\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zhint-mostly-unused is unstable\")]\nfn workspace_profile_package_wildcard() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"foo\"]\n\n[profile.dev.package.\"*\"]\nhint-mostly-unused = true\n\"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zprofile-hint-mostly-unused -v\")\n        .masquerade_as_nightly_cargo(&[\"profile-hint-mostly-unused\", \"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `hint-mostly-unused` is being blanket applied to all dependencies\n --> Cargo.toml:5:22\n  |\n5 | [profile.dev.package.\"*\"]\n  |                      ^^^\n6 | hint-mostly-unused = true\n  | -------------------------\n  |\n  = [HELP] scope `hint-mostly-unused` to specific packages with a lot of unused object code\n  = [NOTE] `cargo::blanket_hint_mostly_unused` is set to `warn` by default\n[CHECKING] foo v0.0.1 ([ROOT]/foo/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zhint-mostly-unused is unstable\")]\nfn deny() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\n\n[profile.dev]\nhint-mostly-unused = true\n\n[lints.cargo]\nblanket_hint_mostly_unused = \"deny\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Zprofile-hint-mostly-unused -v -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"profile-hint-mostly-unused\", \"cargo-lints\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `hint-mostly-unused` is being blanket applied to all dependencies\n --> Cargo.toml:7:10\n  |\n7 | [profile.dev]\n  |          ^^^\n8 | hint-mostly-unused = true\n  | -------------------------\n  |\n  = [NOTE] `cargo::blanket_hint_mostly_unused` is set to `deny` in `[lints]`\n[HELP] scope `hint-mostly-unused` to specific packages with a lot of unused object code\n  |\n7 | [profile.dev.package.<pkg_name>]\n  |             +++++++++++++++++++\n[ERROR] encountered 1 error while running lints\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/error/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::str;\nuse cargo_test_support::{file, project};\n\n#[cargo_test]\nfn case() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\ncargo-features = [\"test-dummy-unstable\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nim-a-teapot = true\n\n[lints.cargo]\nim_a_teapot = \"deny\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    snapbox::cmd::Command::cargo_ui()\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .current_dir(p.root())\n        .arg(\"check\")\n        .arg(\"-Zcargo-lints\")\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/lints/implicit_minimum_version_req.rs",
    "content": "//! Tests for the `implicit_minimum_version_req` lint.\n\nuse crate::prelude::*;\n\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::git;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn major_only() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \"1\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:7\n  |\n7 | dep = \"1\"\n  |       ^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = \"1.0.0\"\n  |         ++++\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn major_minor() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \"1.0\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:7\n  |\n7 | dep = \"1.0\"\n  |       ^^^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = \"1.0.0\"\n  |           ++\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fully_specified_should_not_warn() {\n    Package::new(\"dep\", \"1.2.3\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \"1.0.0\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.2.3 (registry `dummy-registry`)\n[CHECKING] dep v1.2.3\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn detailed_dep_major_only() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = { version = \"1\" }\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:19\n  |\n7 | dep = { version = \"1\" }\n  |                   ^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = { version = \"1.0.0\" }\n  |                     ++++\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn greater_eq() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \">=1.0\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:7\n  |\n7 | dep = \">=1.0\"\n  |       ^^^^^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = \">=1.0.0\"\n  |             ++\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn less_should_not_warn() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \"<2.0\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn wildcard_should_not_warn() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \"1.*\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn wildcard_minor_should_not_warn() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \"1.0.*\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn greater_should_not_warn() {\n    Package::new(\"dep\", \"1.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \">1.0\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.1.0 (registry `dummy-registry`)\n[CHECKING] dep v1.1.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn less_eq_should_not_warn() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \"<=2.0\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_requirements() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \">=1.0, <2.0\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:7\n  |\n7 | dep = \">=1.0, <2.0\"\n  |       ^^^^^^^^^^^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = \">=1.0.0, <2.0\"\n  |             ++\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn tilde_requirement_should_not_warn() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \"~1.0\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn exact_requirement_should_not_warn() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \"=1\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn path_dep_should_not_warn() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\nbar = { path = \"bar\" }\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n[package]\nname = \"bar\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn path_dep_with_registry_version() {\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\nbar = { path = \"bar\", version = \"0.1\" }\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n[package]\nname = \"bar\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:33\n  |\n7 | bar = { path = \"bar\", version = \"0.1\" }\n  |                                 ^^^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | bar = { path = \"bar\", version = \"0.1.0\" }\n  |                                     ++\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_dep_should_not_warn() {\n    let git_project = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\nbar = {{ git = '{}' }}\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOTURL]/bar#[..])\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_dep_with_registry_version() {\n    let git_project = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\nbar = {{ git = '{}', version = \"0.1\" }}\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:[..]\n  |\n7 | bar = { git = '[ROOTURL]/bar', version = \"0.1\" }\n  |                                      [..]^^^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | bar = { git = '[ROOTURL]/bar', version = \"0.1.0\" }\n  |                                          [..]++\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOTURL]/bar#[..])\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dev_dep() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dev-dependencies]\ndep = \"1\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:7\n  |\n7 | dep = \"1\"\n  |       ^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = \"1.0.0\"\n  |         ++++\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_dep() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[build-dependencies]\ndep = \"1.0\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:7\n  |\n7 | dep = \"1.0\"\n  |       ^^^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = \"1.0.0\"\n  |           ++\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[COMPILING] dep v1.0.0\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_dep() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n# Spaces are critical here to check Cargo tolerates them\n[target.'cfg(      all(  )   )'.dependencies]\ndep = \"1\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:8:7\n  |\n8 | dep = \"1\"\n  |       ^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n8 | dep = \"1.0.0\"\n  |         ++++\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_dev_dep() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n# Spaces are critical here to check Cargo tolerates them\n[target.'cfg(      all(  )   )'.dev-dependencies]\ndep = \"1\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:8:7\n  |\n8 | dep = \"1\"\n  |       ^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n8 | dep = \"1.0.0\"\n  |         ++++\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_implicit_deps() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n    Package::new(\"regex\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \"1\"\nregex = \"1.0\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints --quiet\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:7\n  |\n7 | dep = \"1\"\n  |       ^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = \"1.0.0\"\n  |         ++++\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:8:9\n  |\n8 | regex = \"1.0\"\n  |         ^^^^^ missing full version components\n  |\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n8 | regex = \"1.0.0\"\n  |             ++\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_inherited() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"member\"]\nresolver = \"2\"\n\n[workspace.dependencies]\ndep = \"1\"\n\n[workspace.lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\n            \"member/Cargo.toml\",\n            r#\"\n[package]\nname = \"member\"\nedition = \"2021\"\n\n[dependencies]\ndep.workspace = true\n\n[lints]\nworkspace = true\n\"#,\n        )\n        .file(\"member/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:7\n  |\n7 | dep = \"1\"\n  |       ^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = \"1.0.0\"\n  |         ++++\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] member v0.0.0 ([ROOT]/foo/member)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unused_workspace_dep() {\n    // Should still warn for workspace dep\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"member\"]\nresolver = \"2\"\n\n[workspace.dependencies]\ndep = \"1\"\n\n[workspace.lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\n            \"member/Cargo.toml\",\n            r#\"\n[package]\nname = \"member\"\nedition = \"2021\"\n\n[lints]\n\"#,\n        )\n        .file(\"member/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] unused workspace dependency\n --> Cargo.toml:7:1\n  |\n7 | dep = \"1\"\n  | ^^^\n  |\n  = [NOTE] `cargo::unused_workspace_dependencies` is set to `warn` by default\n[HELP] consider removing the unused dependency\n  |\n7 - dep = \"1\"\n  |\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:7\n  |\n7 | dep = \"1\"\n  |       ^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = \"1.0.0\"\n  |         ++++\n[CHECKING] member v0.0.0 ([ROOT]/foo/member)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unused_workspace_dep_and_package_implicit_req() {\n    // Should warn package and workspace separately\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"member\"]\nresolver = \"2\"\n\n[workspace.dependencies]\ndep = \"1\"\n\n[workspace.lints.cargo]\nimplicit_minimum_version_req = \"warn\"\n\"#,\n        )\n        .file(\n            \"member/Cargo.toml\",\n            r#\"\n[package]\nname = \"member\"\nedition = \"2021\"\n\n[dependencies]\ndep = \"1.0\"\n\n[lints]\nworkspace = true\n\"#,\n        )\n        .file(\"member/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] unused workspace dependency\n --> Cargo.toml:7:1\n  |\n7 | dep = \"1\"\n  | ^^^\n  |\n  = [NOTE] `cargo::unused_workspace_dependencies` is set to `warn` by default\n[HELP] consider removing the unused dependency\n  |\n7 - dep = \"1\"\n  |\n[WARNING] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:7\n  |\n7 | dep = \"1\"\n  |       ^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = \"1.0.0\"\n  |         ++++\n[WARNING] dependency version requirement without an explicit minimum version\n --> member/Cargo.toml:7:7\n  |\n7 | dep = \"1.0\"\n  |       ^^^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = \"1.0.0\"\n  |           ++\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[CHECKING] member v0.0.0 ([ROOT]/foo/member)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn deny() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nedition = \"2021\"\n\n[dependencies]\ndep = \"1\"\n\n[lints.cargo]\nimplicit_minimum_version_req = \"deny\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] dependency version requirement without an explicit minimum version\n --> Cargo.toml:7:7\n  |\n7 | dep = \"1\"\n  |       ^^^ missing full version components\n  |\n  = [NOTE] `cargo::implicit_minimum_version_req` is set to `deny` in `[lints]`\n[HELP] consider specifying full `major.minor.patch` version components\n  |\n7 | dep = \"1.0.0\"\n  |         ++++\n[ERROR] encountered 1 error while running lints\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/inherited/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::str;\nuse cargo_test_support::{file, project};\n\n#[cargo_test]\nfn case() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"foo\"]\n\n[workspace.lints.cargo]\nim_a_teapot = { level = \"warn\", priority = 10 }\n\"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[lints]\nworkspace = true\n\"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    snapbox::cmd::Command::cargo_ui()\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .current_dir(p.root())\n        .arg(\"check\")\n        .arg(\"-Zcargo-lints\")\n        .assert()\n        .code(101)\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/lints/missing_lints_inheritance.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn no_lints() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"bar\"]\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n[package]\nname = \"bar\"\nversion = \"0.0.1\"\nedition = \"2015\"\n\"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ws_lints() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"bar\"]\n\n[workspace.lints.cargo]\nmissing_lints_inheritance = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n[package]\nname = \"bar\"\nversion = \"0.0.1\"\nedition = \"2015\"\n\"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] missing `[lints]` to inherit `[workspace.lints]`\n --> bar/Cargo.toml\n  = [NOTE] `cargo::missing_lints_inheritance` is set to `warn` by default\n[HELP] to inherit `workspace.lints, add:\n  |\n5 ~ edition = \"2015\"\n6 + [lints]\n7 + workspace = true\n  |\n[HELP] to clarify your intent to not inherit, add:\n  |\n5 ~ edition = \"2015\"\n6 + [lints]\n  |\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn empty_pkg_lints() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"bar\"]\n\n[workspace.lints.cargo]\nmissing_lints_inheritance = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n[package]\nname = \"bar\"\nversion = \"0.0.1\"\nedition = \"2015\"\n\n[lints]\n\"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inherit_lints() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"bar\"]\n\n[workspace.lints.cargo]\nmissing_lints_inheritance = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n[package]\nname = \"bar\"\nversion = \"0.0.1\"\nedition = \"2015\"\n\n[lints]\nworkspace = true\n\"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.0.1 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\nmod blanket_hint_mostly_unused;\nmod error;\nmod implicit_minimum_version_req;\nmod inherited;\nmod missing_lints_inheritance;\nmod non_kebab_case_bins;\nmod non_kebab_case_features;\nmod non_kebab_case_packages;\nmod non_snake_case_features;\nmod non_snake_case_packages;\nmod redundant_homepage;\nmod redundant_readme;\nmod unknown_lints;\nmod unused_workspace_dependencies;\nmod unused_workspace_package_fields;\nmod warning;\n\n#[cargo_test]\nfn dashes_dont_get_rewritten() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\ncargo-features = [\"test-dummy-unstable\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nim-a-teapot = true\n\n[lints.cargo]\nim-a-teapot = \"warn\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] unknown lint: `im-a-teapot`\n  --> Cargo.toml:12:1\n   |\n12 | im-a-teapot = \"warn\"\n   | ^^^^^^^^^^^\n   |\n   = [NOTE] `cargo::unknown_lints` is set to `warn` by default\n   = [HELP] there is a lint with a similar name: `im_a_teapot`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn forbid_not_overridden() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\ncargo-features = [\"test-dummy-unstable\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nim-a-teapot = true\n\n[lints.cargo]\nim_a_teapot = { level = \"warn\", priority = 10 }\ntest_dummy_unstable = { level = \"forbid\", priority = -1 }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `im_a_teapot` is specified\n --> Cargo.toml:9:1\n  |\n9 | im-a-teapot = true\n  | ^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `cargo::im_a_teapot` is set to `forbid` in `[lints]`\n[ERROR] encountered 1 error while running lints\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_lints() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\ncargo-features = [\"test-dummy-unstable\"]\n\n[workspace.lints.cargo]\nim_a_teapot = { level = \"warn\", priority = 10 }\ntest_dummy_unstable = { level = \"forbid\", priority = -1 }\n\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nim-a-teapot = true\n\n[lints]\nworkspace = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `im_a_teapot` is specified\n  --> Cargo.toml:13:1\n   |\n13 | im-a-teapot = true\n   | ^^^^^^^^^^^^^^^^^^\n   |\n   = [NOTE] `cargo::im_a_teapot` is set to `forbid` in `[lints]`\n[ERROR] encountered 1 error while running lints\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dont_always_inherit_workspace_lints() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\ncargo-features = [\"test-dummy-unstable\"]\n\n[workspace]\nmembers = [\"foo\"]\n\n[workspace.lints.cargo]\nim_a_teapot = \"warn\"\n\"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\ncargo-features = [\"test-dummy-unstable\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nim-a-teapot = true\n\"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] missing `[lints]` to inherit `[workspace.lints]`\n  --> foo/Cargo.toml\n   = [NOTE] `cargo::missing_lints_inheritance` is set to `warn` by default\n[HELP] to inherit `workspace.lints, add:\n   |\n 9 ~ im-a-teapot = true\n10 + [lints]\n11 + workspace = true\n   |\n[HELP] to clarify your intent to not inherit, add:\n   |\n 9 ~ im-a-teapot = true\n10 + [lints]\n   |\n[CHECKING] foo v0.0.1 ([ROOT]/foo/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cap_lints() {\n    Package::new(\"baz\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\ncargo-features = [\"test-dummy-unstable\"]\n\n[package]\nname = \"bar\"\nversion = \"0.1.0\"\nedition = \"2021\"\nim-a-teapot = true\n\n[dependencies]\nbaz = { version = \"0.1.0\", optional = true }\n\n[lints.cargo]\nim_a_teapot = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\nbar = \"0.1.0\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_feature_gated() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[lints.cargo]\nim_a_teapot = \"warn\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] use of unstable lint `im_a_teapot`\n --> Cargo.toml:9:1\n  |\n9 | im_a_teapot = \"warn\"\n  | ^^^^^^^^^^^ this is behind `test-dummy-unstable`, which is not enabled\n  |\n  = [HELP] consider adding `cargo-features = [\"test-dummy-unstable\"]` to the top of the manifest\n[ERROR] encountered 1 error while verifying lints\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_feature_gated_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"foo\"]\n\n[workspace.lints.cargo]\nim_a_teapot = { level = \"warn\", priority = 10 }\ntest_dummy_unstable = { level = \"forbid\", priority = -1 }\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[lints]\nworkspace = true\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] use of unstable lint `im_a_teapot`\n --> Cargo.toml:6:1\n  |\n6 | im_a_teapot = { level = \"warn\", priority = 10 }\n  | ^^^^^^^^^^^ this is behind `test-dummy-unstable`, which is not enabled\n  |\n  = [HELP] consider adding `cargo-features = [\"test-dummy-unstable\"]` to the top of the manifest\n[ERROR] use of unstable lint `test_dummy_unstable`\n --> Cargo.toml:7:1\n  |\n7 | test_dummy_unstable = { level = \"forbid\", priority = -1 }\n  | ^^^^^^^^^^^^^^^^^^^ this is behind `test-dummy-unstable`, which is not enabled\n  |\n  = [HELP] consider adding `cargo-features = [\"test-dummy-unstable\"]` to the top of the manifest\n[ERROR] encountered 2 errors while verifying lints\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_feature_gated_workspace_not_inherited() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"foo\"]\n\n[workspace.lints.cargo]\nim_a_teapot = { level = \"warn\", priority = 10 }\ntest_dummy_unstable = { level = \"forbid\", priority = -1 }\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] use of unstable lint `im_a_teapot`\n --> Cargo.toml:6:1\n  |\n6 | im_a_teapot = { level = \"warn\", priority = 10 }\n  | ^^^^^^^^^^^ this is behind `test-dummy-unstable`, which is not enabled\n  |\n  = [HELP] consider adding `cargo-features = [\"test-dummy-unstable\"]` to the top of the manifest\n[ERROR] use of unstable lint `test_dummy_unstable`\n --> Cargo.toml:7:1\n  |\n7 | test_dummy_unstable = { level = \"forbid\", priority = -1 }\n  | ^^^^^^^^^^^^^^^^^^^ this is behind `test-dummy-unstable`, which is not enabled\n  |\n  = [HELP] consider adding `cargo-features = [\"test-dummy-unstable\"]` to the top of the manifest\n[WARNING] missing `[lints]` to inherit `[workspace.lints]`\n --> foo/Cargo.toml\n  = [NOTE] `cargo::missing_lints_inheritance` is set to `warn` by default\n[HELP] to inherit `workspace.lints, add:\n  |\n7 ~             \n8 + [lints]\n9 + workspace = true\n  |\n[HELP] to clarify your intent to not inherit, add:\n  |\n7 ~             \n8 + [lints]\n  |\n[ERROR] encountered 2 errors while verifying lints\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zrustc-unicode is unstable\")]\nfn unicode_report() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\ncargo-features = [\"test-dummy-unstable\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nim-a-teapot = true\n\n[lints.cargo]\nim_a_teapot = { level = \"warn\", priority = 10 }\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints -Zrustc-unicode\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"rustc-unicode\", \"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `im_a_teapot` is specified\n  ╭▸ Cargo.toml:9:1\n  │\n9 │ im-a-teapot = true\n  │ ━━━━━━━━━━━━━━━━━━\n  │\n  ╰ [NOTE] `cargo::im_a_teapot` is set to `warn` in `[lints]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/non_kebab_case_bins.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn bin_name_explicit() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[[bin]]\nname = \"foo_bar\"\npath = \"src/main.rs\"\n\n[lints.cargo]\nnon_kebab_case_bins = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] binaries should have a kebab-case name\n  |\n1 | [ROOT]/foo/target/.../foo_bar[EXE]\n  |                   [..]^^^^^^^\n  |\n  = [NOTE] `cargo::non_kebab_case_bins` is set to `warn` in `[lints]`\n[HELP] to change the binary name to kebab case, convert `bin.name`\n --> Cargo.toml:9:8\n  |\n9 - name = \"foo_bar\"\n9 + name = \"foo-bar\"\n  |\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bin_name_from_package() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo_bar\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[lints.cargo]\nnon_kebab_case_bins = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] binaries should have a kebab-case name\n   |\n 1 | [ROOT]/foo/target/.../foo_bar[EXE]\n   |                   [..]^^^^^^^\n   |\n   = [NOTE] `cargo::non_kebab_case_bins` is set to `warn` in `[lints]`\n[HELP] to change the binary name to kebab case, convert `package.name`\n  --> Cargo.toml:3:8\n   |\n 3 - name = \"foo_bar\"\n 3 + name = \"foo-bar\"\n   |\n[HELP] to change the binary name to kebab case, specify `bin.name`\n  --> Cargo.toml:9:30\n   |\n 9 ~ non_kebab_case_bins = \"warn\"\n10 + [[bin]]\n11 + name = \"foo-bar\"\n12 + path = \"src/main.rs\"\n   |\n[CHECKING] foo_bar v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bin_name_from_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[lints.cargo]\nnon_kebab_case_bins = \"warn\"\n\"#,\n        )\n        .file(\"src/bin/foo_bar.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] binaries should have a kebab-case name\n  |\n1 | [ROOT]/foo/target/.../foo_bar[EXE]\n  |                   [..]^^^^^^^\n  |\n  = [NOTE] `cargo::non_kebab_case_bins` is set to `warn` in `[lints]`\n[HELP] to change the binary name to kebab case, convert the file stem\n  |\n1 - src/bin/foo_bar.rs\n1 + src/bin/foo-bar.rs\n  |\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn bin_name_from_script_name() {\n    let p = cargo_test_support::project()\n        .file(\n            \"foo_bar\",\n            r#\"\n---\n[lints.cargo]\nnon_kebab_case_bins = \"warn\"\n---\nfn main() {}\"#,\n        )\n        .build();\n\n    p.cargo(\"check -Zcargo-lints -Zscript --manifest-path foo_bar\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"script\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[WARNING] binaries should have a kebab-case name\n  |\n1 | [ROOT]/home/.cargo/build/[HASH]/target/.../foo_bar[EXE]\n  |                                        [..]^^^^^^^\n  |\n  = [NOTE] `cargo::non_kebab_case_bins` is set to `warn` in `[lints]`\n[HELP] to change the binary name to kebab case, convert the file stem\n  |\n1 - foo_bar\n1 + foo-bar\n  |\n[CHECKING] foo_bar v0.0.0 ([ROOT]/foo/foo_bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/non_kebab_case_features.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn feature_name_explicit() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[features]\nfoo_bar = []\n\n[lints.cargo]\nnon_kebab_case_features = \"warn\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] features should have a kebab-case name\n --> Cargo.toml:9:1\n  |\n9 | foo_bar = []\n  | ^^^^^^^\n  |\n  = [NOTE] `cargo::non_kebab_case_features` is set to `warn` in `[lints]`\n[HELP] to change the feature name to kebab case, convert the `features` key\n  |\n9 - foo_bar = []\n9 + foo-bar = []\n  |\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn feature_name_implicit() {\n    Package::new(\"foo_bar\", \"0.0.1\").publish();\n\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[dependencies]\nfoo_bar = { version = \"0.0.1\", optional = true }\n\n[lints.cargo]\nnon_kebab_case_features = \"warn\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] features should have a kebab-case name\n --> Cargo.toml:9:1\n  |\n9 | foo_bar = { version = \"0.0.1\", optional = true }\n  | ^^^^^^^ source of feature name --------------- cause of feature\n  |\n  = [NOTE] see also <https://doc.rust-lang.org/cargo/reference/features.html#optional-dependencies>\n  = [NOTE] `cargo::non_kebab_case_features` is set to `warn` in `[lints]`\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/non_kebab_case_packages.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn package_name_explicit() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo_bar\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[lints.cargo]\nnon_kebab_case_packages = \"warn\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] packages should have a kebab-case name\n --> Cargo.toml:3:8\n  |\n3 | name = \"foo_bar\"\n  |        ^^^^^^^^^\n  |\n  = [NOTE] `cargo::non_kebab_case_packages` is set to `warn` in `[lints]`\n[HELP] to change the package name to kebab case, convert `package.name`\n  |\n3 - name = \"foo_bar\"\n3 + name = \"foo-bar\"\n  |\n[CHECKING] foo_bar v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn package_name_from_script_name() {\n    let p = cargo_test_support::project()\n        .file(\n            \"foo_bar\",\n            r#\"\n---\n[lints.cargo]\nnon_kebab_case_packages = \"warn\"\n---\nfn main() {}\"#,\n        )\n        .build();\n\n    p.cargo(\"check -Zcargo-lints -Zscript --manifest-path foo_bar\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"script\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[WARNING] packages should have a kebab-case name\n --> foo_bar\n  = [NOTE] `cargo::non_kebab_case_packages` is set to `warn` in `[lints]`\n[HELP] to change the package name to kebab case, convert the file stem\n  |\n1 - [ROOT]/foo/foo_bar\n1 + [ROOT]/foo/foo-bar\n  |\n[WARNING] binaries should have a kebab-case name\n  |\n1 | [ROOT]/home/.cargo/build/[HASH]/target/.../foo_bar[EXE]\n  |                                        [..]^^^^^^^\n  |\n  = [NOTE] `cargo::non_kebab_case_bins` is set to `warn` by default\n[HELP] to change the binary name to kebab case, convert the file stem\n  |\n1 - foo_bar\n1 + foo-bar\n  |\n[CHECKING] foo_bar v0.0.0 ([ROOT]/foo/foo_bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/non_snake_case_features.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn feature_name_explicit() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[features]\nfoo-bar = []\n\n[lints.cargo]\nnon_snake_case_features = \"warn\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] features should have a snake-case name\n --> Cargo.toml:9:1\n  |\n9 | foo-bar = []\n  | ^^^^^^^\n  |\n  = [NOTE] `cargo::non_snake_case_features` is set to `warn` in `[lints]`\n[HELP] to change the feature name to snake case, convert the `features` key\n  |\n9 - foo-bar = []\n9 + foo_bar = []\n  |\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn feature_name_implicit() {\n    Package::new(\"foo-bar\", \"0.0.1\").publish();\n\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[dependencies]\nfoo-bar = { version = \"0.0.1\", optional = true }\n\n[lints.cargo]\nnon_snake_case_features = \"warn\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] features should have a snake-case name\n --> Cargo.toml:9:1\n  |\n9 | foo-bar = { version = \"0.0.1\", optional = true }\n  | ^^^^^^^ source of feature name --------------- cause of feature\n  |\n  = [NOTE] see also <https://doc.rust-lang.org/cargo/reference/features.html#optional-dependencies>\n  = [NOTE] `cargo::non_snake_case_features` is set to `warn` in `[lints]`\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/non_snake_case_packages.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn package_name_explicit() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo-bar\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[lints.cargo]\nnon_snake_case_packages = \"warn\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] packages should have a snake-case name\n --> Cargo.toml:3:8\n  |\n3 | name = \"foo-bar\"\n  |        ^^^^^^^^^\n  |\n  = [NOTE] `cargo::non_snake_case_packages` is set to `warn` in `[lints]`\n[HELP] to change the package name to snake case, convert `package.name`\n  |\n3 - name = \"foo-bar\"\n3 + name = \"foo_bar\"\n  |\n[CHECKING] foo-bar v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn package_name_from_script_name() {\n    let p = cargo_test_support::project()\n        .file(\n            \"foo-bar\",\n            r#\"\n---\n[lints.cargo]\nnon_snake_case_packages = \"warn\"\n---\nfn main() {}\"#,\n        )\n        .build();\n\n    p.cargo(\"check -Zcargo-lints -Zscript --manifest-path foo-bar\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"script\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[WARNING] packages should have a snake-case name\n --> foo-bar\n  = [NOTE] `cargo::non_snake_case_packages` is set to `warn` in `[lints]`\n[HELP] to change the package name to snake case, convert the file stem\n  |\n1 - [ROOT]/foo/foo-bar\n1 + [ROOT]/foo/foo_bar\n  |\n[CHECKING] foo-bar v0.0.0 ([ROOT]/foo/foo-bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/redundant_homepage.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn with_repo() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"cargo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nrepository = \"https://github.com/rust-lang/cargo/\"\nhomepage = \"https://github.com/rust-lang/cargo/\"\n\n[lints.cargo]\nredundant_homepage = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"README.md\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.homepage` is redundant with another manifest field\n --> Cargo.toml:7:12\n  |\n6 | repository = \"https://github.com/rust-lang/cargo/\"\n  |              -------------------------------------\n7 | homepage = \"https://github.com/rust-lang/cargo/\"\n  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `cargo::redundant_homepage` is set to `warn` in `[lints]`\n[HELP] consider removing `package.homepage`\n  |\n7 - homepage = \"https://github.com/rust-lang/cargo/\"\n  |\n[CHECKING] cargo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn with_docs() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"cargo\"\nversion = \"0.0.1\"\nedition = \"2015\"\ndocumentation = \"https://docs.rs/cargo/latest/cargo/\"\nhomepage = \"https://docs.rs/cargo/latest/cargo/\"\n\n[lints.cargo]\nredundant_homepage = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"README.md\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.homepage` is redundant with another manifest field\n --> Cargo.toml:7:12\n  |\n6 | documentation = \"https://docs.rs/cargo/latest/cargo/\"\n  |                 -------------------------------------\n7 | homepage = \"https://docs.rs/cargo/latest/cargo/\"\n  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `cargo::redundant_homepage` is set to `warn` in `[lints]`\n[HELP] consider removing `package.homepage`\n  |\n7 - homepage = \"https://docs.rs/cargo/latest/cargo/\"\n  |\n[CHECKING] cargo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inherited() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace.package]\ndocumentation = \"https://docs.rs/cargo/latest/cargo/\"\nhomepage = \"https://docs.rs/cargo/latest/cargo/\"\n\n[package]\nname = \"cargo\"\nversion = \"0.0.1\"\nedition = \"2015\"\ndocumentation.workspace = true\nhomepage.workspace = true\n\n[lints.cargo]\nredundant_homepage = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"README.md\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.homepage` is redundant with another manifest field\n  --> Cargo.toml:11:1\n   |\n10 | documentation.workspace = true\n   | -------------\n11 | homepage.workspace = true\n   | ^^^^^^^^\n   |\n   = [NOTE] `cargo::redundant_homepage` is set to `warn` in `[lints]`\n[HELP] consider removing `package.homepage`\n   |\n11 - homepage.workspace = true\n   |\n[CHECKING] cargo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/redundant_readme.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn explicit_readme() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nreadme = \"README.md\"\n\n[lints.cargo]\nredundant_readme = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"README.md\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] explicit `package.readme` can be inferred\n --> Cargo.toml:7:1\n  |\n7 | readme = \"README.md\"\n  | ^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `cargo::redundant_readme` is set to `warn` in `[lints]`\n[HELP] consider removing `package.readme`\n  |\n7 - readme = \"README.md\"\n  |\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn implicit_readme() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[lints.cargo]\nredundant_readme = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"README.md\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nreadme = \"FOO.md\"\n\n[lints.cargo]\nredundant_readme = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"FOO.md\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_location() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nreadme = \"src/README.md\"\n\n[lints.cargo]\nredundant_readme = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/README.md\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inherited() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace.package]\nreadme = \"README.md\"\n\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nreadme.workspace = true\n\n[lints.cargo]\nredundant_readme = \"warn\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"README.md\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/unknown_lints.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn default() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[lints.cargo]\nthis-lint-does-not-exist = \"warn\"\n\"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] unknown lint: `this-lint-does-not-exist`\n --> Cargo.toml:9:1\n  |\n9 | this-lint-does-not-exist = \"warn\"\n  | ^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `cargo::unknown_lints` is set to `warn` by default\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inherited() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"foo\"]\n\n[workspace.lints.cargo]\nthis-lint-does-not-exist = \"warn\"\n\"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[lints]\nworkspace = true\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] unknown lint: `this-lint-does-not-exist`\n --> Cargo.toml:6:1\n  |\n6 | this-lint-does-not-exist = \"warn\"\n  | ^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `cargo::unknown_lints` is set to `warn` by default\n[CHECKING] foo v0.0.1 ([ROOT]/foo/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn not_inherited() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"foo\"]\n\n[workspace.lints.cargo]\nthis-lint-does-not-exist = \"warn\"\n\"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] unknown lint: `this-lint-does-not-exist`\n --> Cargo.toml:6:1\n  |\n6 | this-lint-does-not-exist = \"warn\"\n  | ^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `cargo::unknown_lints` is set to `warn` by default\n[WARNING] missing `[lints]` to inherit `[workspace.lints]`\n --> foo/Cargo.toml\n  = [NOTE] `cargo::missing_lints_inheritance` is set to `warn` by default\n[HELP] to inherit `workspace.lints, add:\n  |\n7 ~             \n8 + [lints]\n9 + workspace = true\n  |\n[HELP] to clarify your intent to not inherit, add:\n  |\n7 ~             \n8 + [lints]\n  |\n[CHECKING] foo v0.0.1 ([ROOT]/foo/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/unused_workspace_dependencies.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn unused() {\n    Package::new(\"in-package\", \"1.0.0\").publish();\n    Package::new(\"build-dep\", \"1.0.0\").publish();\n    Package::new(\"dep\", \"1.0.0\").publish();\n    Package::new(\"dev-dep\", \"1.0.0\").publish();\n    Package::new(\"target-dep\", \"1.0.0\").publish();\n    Package::new(\"unused\", \"1.0.0\").publish();\n    Package::new(\"not-inherited\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"bar\"]\n\n[workspace.dependencies]\nin-package = \"1\"\nbuild-dep = \"1\"\ndep = \"1\"\ndev-dep = \"1\"\ntarget-dep = \"1\"\nunused = \"1\"\nnot-inherited = \"1\"\n\n[workspace.lints.cargo]\nunused_workspace_dependencies = \"warn\"\n\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[dependencies]\nin-package.workspace = true\n\n[lints]\nworkspace = true\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n[package]\nname = \"bar\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[build-dependencies]\nbuild-dep.workspace = true\n\n[dependencies]\ndep.workspace = true\nnot-inherited = \"1\"\n\n[dev-dependencies]\ndev-dep.workspace = true\n\n[target.'cfg(false)'.dependencies]\ntarget-dep.workspace = true\n\n[lints]\nworkspace = true\n\"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] unused workspace dependency\n  --> Cargo.toml:12:1\n   |\n12 | not-inherited = \"1\"\n   | ^^^^^^^^^^^^^\n   |\n   = [NOTE] `cargo::unused_workspace_dependencies` is set to `warn` by default\n[HELP] consider removing the unused dependency\n   |\n12 - not-inherited = \"1\"\n   |\n[WARNING] unused workspace dependency\n  --> Cargo.toml:11:1\n   |\n11 | unused = \"1\"\n   | ^^^^^^\n   |\n[HELP] consider removing the unused dependency\n   |\n11 - unused = \"1\"\n   |\n[UPDATING] `dummy-registry` index\n[LOCKING] 6 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] in-package v1.0.0 (registry `dummy-registry`)\n[CHECKING] in-package v1.0.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/unused_workspace_package_fields.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn unused() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"bar\"]\n\n[workspace.package]\ndocumentation = \"docs.rs/foo\"\nhomepage = \"bar.rs\"\nrust-version = \"1.0\"\nunknown = \"foo\"\n\n[workspace.lints.cargo]\nunused_workspace_package_fields = \"warn\"\n\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\ndocumentation.workspace = true\n\n[lints]\nworkspace = true\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n[package]\nname = \"bar\"\nversion = \"0.0.1\"\nedition = \"2015\"\nhomepage.workspace = true\n\n[lints]\nworkspace = true\n\"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] unused field in `workspace.package`\n --> Cargo.toml:8:1\n  |\n8 | rust-version = \"1.0\"\n  | ^^^^^^^^^^^^\n  |\n  = [NOTE] `cargo::unused_workspace_package_fields` is set to `warn` by default\n[HELP] consider removing the unused field\n  |\n8 - rust-version = \"1.0\"\n  |\n[WARNING] unused field in `workspace.package`\n --> Cargo.toml:9:1\n  |\n9 | unknown = \"foo\"\n  | ^^^^^^^\n  |\n[HELP] consider removing the unused field\n  |\n9 - unknown = \"foo\"\n  |\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: workspace.package.unknown\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lints/warning/mod.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::str;\nuse cargo_test_support::{file, project};\n\n#[cargo_test]\nfn case() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\ncargo-features = [\"test-dummy-unstable\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nim-a-teapot = true\n\n[lints.cargo]\nim_a_teapot = \"warn\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    snapbox::cmd::Command::cargo_ui()\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .current_dir(p.root())\n        .arg(\"check\")\n        .arg(\"-Zcargo-lints\")\n        .assert()\n        .success()\n        .stdout_eq(str![\"\"])\n        .stderr_eq(file![\"stderr.term.svg\"]);\n}\n"
  },
  {
    "path": "tests/testsuite/lints_table.rs",
    "content": "//! Tests for `[lints]`\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn dependency_warning_ignored() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar.path = \"../bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let _bar = project()\n        .at(\"bar\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lints.rust]\n                unsafe_code = \"forbid\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.0.1 ([ROOT]/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn malformed_on_stable() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                lints = 20\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid type: integer `20`, expected a lints table\n --> Cargo.toml:2:25\n  |\n2 |                 lints = 20\n  |                         ^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fail_on_invalid_tool() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace.lints.super-awesome-linter]\n                unsafe_code = \"forbid\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] [ROOT]/foo/Cargo.toml: unrecognized lint tool `lints.super-awesome-linter`, specifying unrecognized tools may break in the future.\nsupported tools: cargo, clippy, rust, rustdoc\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn invalid_type_in_lint_value() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [workspace.lints.rust]\n                rust-2018-idioms = -1\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid type: integer `-1`, expected a string or map\n --> Cargo.toml:8:36\n  |\n8 |                 rust-2018-idioms = -1\n  |                                    ^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warn_on_unused_key() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [workspace.lints.rust]\n                rust-2018-idioms = { level = \"allow\", unused = true }\n                [lints.rust]\n                rust-2018-idioms = { level = \"allow\", unused = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: `lints.rust.rust-2018-idioms.unused`\n[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: `lints.rust.rust-2018-idioms.unused`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fail_on_tool_injection() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace.lints.rust]\n                \"clippy::cyclomatic_complexity\" = \"warn\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `lints.rust.clippy::cyclomatic_complexity` is not valid lint name; try `lints.clippy.cyclomatic_complexity`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fail_on_redundant_tool() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace.lints.rust]\n                \"rust::unsafe_code\" = \"forbid\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `lints.rust.rust::unsafe_code` is not valid lint name; try `lints.rust.unsafe_code`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fail_on_conflicting_tool() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace.lints.rust]\n                \"super-awesome-tool::unsafe_code\" = \"forbid\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `lints.rust.super-awesome-tool::unsafe_code` is not a valid lint name\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn package_lint_deny() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lints.rust]\n                \"unsafe_code\" = \"deny\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\npub fn foo(num: i32) -> u32 {\n    unsafe { std::mem::transmute(num) }\n}\n\",\n        )\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] usage of an `unsafe` block\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_cant_be_false() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lints]\n                workspace = false\n\n                [workspace.lints.rust]\n                \"unsafe_code\" = \"deny\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\npub fn foo(num: i32) -> u32 {\n    unsafe { std::mem::transmute(num) }\n}\n\",\n        )\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `workspace` cannot be false\n --> Cargo.toml:9:29\n  |\n9 |                 workspace = false\n  |                             ^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_lint_deny() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lints]\n                workspace = true\n\n                [workspace.lints.rust]\n                \"unsafe_code\" = \"deny\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\npub fn foo(num: i32) -> u32 {\n    unsafe { std::mem::transmute(num) }\n}\n\",\n        )\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] usage of an `unsafe` block\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_and_package_lints() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lints]\n                workspace = true\n                [lints.rust]\n                \"unsafe_code\" = \"allow\"\n\n                [workspace.lints.rust]\n                \"unsafe_code\" = \"deny\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\npub fn foo(num: i32) -> u32 {\n    unsafe { std::mem::transmute(num) }\n}\n\",\n        )\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  cannot override `workspace.lints` in `lints`, either remove the overrides or `lints.workspace = true` and manually specify the lints\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn attribute_has_precedence() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lints.rust]\n                \"unsafe_code\" = \"deny\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n#![allow(unsafe_code)]\n\npub fn foo(num: i32) -> u32 {\n    unsafe { std::mem::transmute(num) }\n}\n\",\n        )\n        .build();\n\n    foo.cargo(\"check\")\n        .arg(\"-v\") // Show order of rustflags on failure\n        .run();\n}\n\n#[cargo_test]\nfn rustflags_has_precedence() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lints.rust]\n                \"unsafe_code\" = \"deny\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\npub fn foo(num: i32) -> u32 {\n    unsafe { std::mem::transmute(num) }\n}\n\",\n        )\n        .build();\n\n    foo.cargo(\"check\")\n        .arg(\"-v\") // Show order of rustflags on failure\n        .env(\"RUSTFLAGS\", \"-Aunsafe_code\")\n        .run();\n}\n\n#[cargo_test]\nfn profile_rustflags_has_precedence() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"profile-rustflags\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [lints.rust]\n                \"unsafe_code\" = \"deny\"\n\n                [profile.dev]\n                rustflags = [\"-A\", \"unsafe_code\"]\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\npub fn foo(num: i32) -> u32 {\n    unsafe { std::mem::transmute(num) }\n}\n\",\n        )\n        .build();\n\n    foo.cargo(\"check\")\n        .arg(\"-v\") // Show order of rustflags on failure\n        .masquerade_as_nightly_cargo(&[\"profile-rustflags\"])\n        .run();\n}\n\n#[cargo_test]\nfn build_rustflags_has_precedence() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [lints.rust]\n                \"unsafe_code\" = \"deny\"\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                rustflags = [\"-A\", \"unsafe_code\"]\n\"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\npub fn foo(num: i32) -> u32 {\n    unsafe { std::mem::transmute(num) }\n}\n\",\n        )\n        .build();\n\n    foo.cargo(\"check\")\n        .arg(\"-v\") // Show order of rustflags on failure\n        .run();\n}\n\n#[cargo_test]\nfn without_priority() {\n    Package::new(\"reg-dep\", \"1.0.0\").publish();\n\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2018\"\n                authors = []\n\n                [dependencies]\n                reg-dep = \"1.0.0\"\n\n                [lints.rust]\n                \"rust-2018-idioms\" = \"deny\"\n                \"unused-extern-crates\" = \"allow\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\nextern crate reg_dep;\n\npub fn foo() -> u32 {\n    2\n}\n\",\n        )\n        .build();\n\n    foo.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] unused extern crate\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn with_priority() {\n    Package::new(\"reg-dep\", \"1.0.0\").publish();\n\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2018\"\n                authors = []\n\n                [dependencies]\n                reg-dep = \"1.0.0\"\n\n                [lints.rust]\n                \"rust-2018-idioms\" = { level = \"deny\", priority = -1 }\n                \"unused-extern-crates\" = \"allow\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\nextern crate reg_dep;\n\npub fn foo() -> u32 {\n    2\n}\n\",\n        )\n        .build();\n\n    foo.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn rustdoc_lint() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lints.rustdoc]\n                broken_intra_doc_links = \"deny\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n/// [`bar`] doesn't exist\npub fn foo() -> u32 {\n}\n\",\n        )\n        .build();\n\n    foo.cargo(\"doc\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] unresolved link to `bar`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doctest_respects_lints() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lints.rust]\n                confusable-idents = 'allow'\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n/// Test\n///\n/// [`Foo`]\n///\n/// ```\n/// let s = \"rust\";\n/// let ｓ_ｓ = \"rust2\";\n/// ```\npub fn f() {}\npub const Ě: i32 = 1;\npub const Ĕ: i32 = 2;\n\"#,\n        )\n        .build();\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    foo.cargo(\"test --doc\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[DOCTEST] foo\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_lints_nightly_required() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\n\n[lints.cargo]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused manifest key `lints.cargo` (may be supported in a future version)\n\nthis Cargo does not support nightly features, but if you\nswitch to nightly channel you can pass\n`-Zcargo-lints` to enable this feature.\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_lints_no_z_flag() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\ncargo-features = [\"test-dummy-unstable\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nim-a-teapot = true\n\n[lints.cargo]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] unused manifest key `lints.cargo` (may be supported in a future version)\n\nconsider passing `-Zcargo-lints` to enable this feature.\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_lints_success() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\ncargo-features = [\"test-dummy-unstable\"]\n\n[package]\nname = \"foo\"\nversion = \"0.0.1\"\nedition = \"2015\"\nauthors = []\nim-a-teapot = true\n\n[lints.cargo]\nim_a_teapot = \"warn\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -Zcargo-lints\")\n        .masquerade_as_nightly_cargo(&[\"cargo-lints\", \"test-dummy-unstable\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `im_a_teapot` is specified\n --> Cargo.toml:9:1\n  |\n9 | im-a-teapot = true\n  | ^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `cargo::im_a_teapot` is set to `warn` in `[lints]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/list_availables.rs",
    "content": "//! Tests for packages/target filter flags giving suggestions on which\n//! packages/targets are available.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\nuse snapbox::IntoData;\n\nfn list_availables_test(command: &str, expected: ExpectedSnapshots<impl IntoData>) {\n    let full_project = project()\n        .file(\"examples/a.rs\", \"fn main() { }\")\n        .file(\"examples/b.rs\", \"fn main() { }\")\n        .file(\"benches/bench1.rs\", \"\")\n        .file(\"benches/bench2.rs\", \"\")\n        .file(\"tests/test1.rs\", \"\")\n        .file(\"tests/test2.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() { }\")\n        .file(\"Cargo.lock\", \"\") // for `cargo pkgid`\n        .build();\n\n    if let ExpectedSnapshots {\n        example: ProjectExpected {\n            full: Some(example),\n            ..\n        },\n        ..\n    } = expected\n    {\n        full_project\n            .cargo(&format!(\"{} --example\", command))\n            .with_stderr_data(example)\n            .with_status(101)\n            .run();\n    }\n\n    if let ExpectedSnapshots {\n        bin: ProjectExpected {\n            full: Some(bin), ..\n        },\n        ..\n    } = expected\n    {\n        full_project\n            .cargo(&format!(\"{} --bin\", command))\n            .with_stderr_data(bin)\n            .with_status(101)\n            .run();\n    }\n\n    if let ExpectedSnapshots {\n        bench: ProjectExpected {\n            full: Some(bench), ..\n        },\n        ..\n    } = expected\n    {\n        full_project\n            .cargo(&format!(\"{} --bench\", command))\n            .with_stderr_data(bench)\n            .with_status(101)\n            .run();\n    }\n\n    if let ExpectedSnapshots {\n        test: ProjectExpected {\n            full: Some(test), ..\n        },\n        ..\n    } = expected\n    {\n        full_project\n            .cargo(&format!(\"{} --test\", command))\n            .with_stderr_data(test)\n            .with_status(101)\n            .run();\n    }\n\n    if let ExpectedSnapshots {\n        package: ProjectExpected {\n            full: Some(package),\n            ..\n        },\n        ..\n    } = expected\n    {\n        full_project\n            .cargo(&format!(\"{} -p\", command))\n            .with_stderr_data(package)\n            .with_status(101)\n            .run();\n    }\n\n    let empty_project = project().file(\"src/lib.rs\", \"\").build();\n\n    if let ExpectedSnapshots {\n        example: ProjectExpected {\n            empty: Some(example),\n            ..\n        },\n        ..\n    } = expected\n    {\n        empty_project\n            .cargo(&format!(\"{} --example\", command))\n            .with_stderr_data(example)\n            .with_status(101)\n            .run();\n    }\n\n    if let ExpectedSnapshots {\n        bin: ProjectExpected {\n            empty: Some(bin), ..\n        },\n        ..\n    } = expected\n    {\n        empty_project\n            .cargo(&format!(\"{} --bin\", command))\n            .with_stderr_data(bin)\n            .with_status(101)\n            .run();\n    }\n\n    if let ExpectedSnapshots {\n        bench: ProjectExpected {\n            empty: Some(bench), ..\n        },\n        ..\n    } = expected\n    {\n        empty_project\n            .cargo(&format!(\"{} --bench\", command))\n            .with_stderr_data(bench)\n            .with_status(101)\n            .run();\n    }\n\n    if let ExpectedSnapshots {\n        test: ProjectExpected {\n            empty: Some(test), ..\n        },\n        ..\n    } = expected\n    {\n        empty_project\n            .cargo(&format!(\"{} --test\", command))\n            .with_stderr_data(test)\n            .with_status(101)\n            .run();\n    }\n\n    if let ExpectedSnapshots {\n        target: ProjectExpected {\n            empty: Some(target),\n            ..\n        },\n        ..\n    } = expected\n    {\n        empty_project\n            .cargo(&format!(\"{} --target\", command))\n            .with_stderr_data(target)\n            .with_status(101)\n            .run();\n    }\n}\n\n#[cargo_test]\nfn build_list_availables() {\n    list_availables_test(\n        \"build\",\n        SnapshotsBuilder::new()\n            .with_example(str![[r#\"\n[ERROR] \"--example\" takes one argument.\nAvailable examples:\n    a\n    b\n\n\n\"#]], str![[r#\"\n[ERROR] \"--example\" takes one argument.\nNo examples available.\n\n\n\"#]])\n            .with_bin(str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nAvailable binaries:\n    foo\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nNo binaries available.\n\n\n\"#]])\n            .with_test(str![[r#\"\n[ERROR] \"--test\" takes one argument.\nAvailable test targets:\n    test1\n    test2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--test\" takes one argument.\nNo test targets available.\n\n\n\"#]])\n            .with_bench(str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nAvailable bench targets:\n    bench1\n    bench2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nNo bench targets available.\n\n\n\"#]])\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .with_target(str![[r#\"\n[ERROR] \"--target\" takes a target architecture as an argument.\n\nRun `[..]` to see possible targets.\n\n\"#]])\n            .build(),\n    );\n}\n\n#[cargo_test]\nfn check_list_availables() {\n    list_availables_test(\n        \"check\",\n        SnapshotsBuilder::new()\n            .with_example(str![[r#\"\n[ERROR] \"--example\" takes one argument.\nAvailable examples:\n    a\n    b\n\n\n\"#]], str![[r#\"\n[ERROR] \"--example\" takes one argument.\nNo examples available.\n\n\n\"#]])\n            .with_bin(str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nAvailable binaries:\n    foo\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nNo binaries available.\n\n\n\"#]])\n            .with_test(str![[r#\"\n[ERROR] \"--test\" takes one argument.\nAvailable test targets:\n    test1\n    test2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--test\" takes one argument.\nNo test targets available.\n\n\n\"#]])\n            .with_bench(str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nAvailable bench targets:\n    bench1\n    bench2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nNo bench targets available.\n\n\n\"#]])\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .with_target(str![[r#\"\n[ERROR] \"--target\" takes a target architecture as an argument.\n\nRun `[..]` to see possible targets.\n\n\"#]])\n            .build(),\n    );\n}\n\n#[cargo_test]\nfn doc_list_availables() {\n    list_availables_test(\n        \"doc\",\n        SnapshotsBuilder::new()\n            .with_bin(str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nAvailable binaries:\n    foo\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nNo binaries available.\n\n\n\"#]])\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .with_target(str![[r#\"\n[ERROR] \"--target\" takes a target architecture as an argument.\n\nRun `[..]` to see possible targets.\n\n\"#]])\n            .build(),\n    );\n}\n\n#[cargo_test]\nfn fix_list_availables() {\n    list_availables_test(\n        \"fix\",\n        SnapshotsBuilder::new()\n            .with_example(str![[r#\"\n[ERROR] \"--example\" takes one argument.\nAvailable examples:\n    a\n    b\n\n\n\"#]], str![[r#\"\n[ERROR] \"--example\" takes one argument.\nNo examples available.\n\n\n\"#]])\n            .with_bin(str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nAvailable binaries:\n    foo\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nNo binaries available.\n\n\n\"#]])\n            .with_test(str![[r#\"\n[ERROR] \"--test\" takes one argument.\nAvailable test targets:\n    test1\n    test2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--test\" takes one argument.\nNo test targets available.\n\n\n\"#]])\n            .with_bench(str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nAvailable bench targets:\n    bench1\n    bench2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nNo bench targets available.\n\n\n\"#]])\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .with_target(str![[r#\"\n[ERROR] \"--target\" takes a target architecture as an argument.\n\nRun `[..]` to see possible targets.\n\n\"#]])\n            .build(),\n    );\n}\n\n#[cargo_test]\nfn run_list_availables() {\n    list_availables_test(\n        \"run\",\n        SnapshotsBuilder::new()\n            .with_example(str![[r#\"\n[ERROR] \"--example\" takes one argument.\nAvailable examples:\n    a\n    b\n\n\n\"#]], str![[r#\"\n[ERROR] \"--example\" takes one argument.\nNo examples available.\n\n\n\"#]])\n            .with_bin(str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nAvailable binaries:\n    foo\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nNo binaries available.\n\n\n\"#]])\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .with_target(str![[r#\"\n[ERROR] \"--target\" takes a target architecture as an argument.\n\nRun `[..]` to see possible targets.\n\n\"#]])\n            .build(),\n    );\n}\n\n#[cargo_test]\nfn test_list_availables() {\n    list_availables_test(\n        \"test\",\n        SnapshotsBuilder::new()\n            .with_example(str![[r#\"\n[ERROR] \"--example\" takes one argument.\nAvailable examples:\n    a\n    b\n\n\n\"#]], str![[r#\"\n[ERROR] \"--example\" takes one argument.\nNo examples available.\n\n\n\"#]])\n            .with_bin(str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nAvailable binaries:\n    foo\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nNo binaries available.\n\n\n\"#]])\n            .with_test(str![[r#\"\n[ERROR] \"--test\" takes one argument.\nAvailable test targets:\n    test1\n    test2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--test\" takes one argument.\nNo test targets available.\n\n\n\"#]])\n            .with_bench(str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nAvailable bench targets:\n    bench1\n    bench2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nNo bench targets available.\n\n\n\"#]])\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .with_target(str![[r#\"\n[ERROR] \"--target\" takes a target architecture as an argument.\n\nRun `[..]` to see possible targets.\n\n\"#]])\n            .build(),\n    );\n}\n\n#[cargo_test]\nfn bench_list_availables() {\n    list_availables_test(\n        \"bench\",\n        SnapshotsBuilder::new()\n            .with_example(str![[r#\"\n[ERROR] \"--example\" takes one argument.\nAvailable examples:\n    a\n    b\n\n\n\"#]], str![[r#\"\n[ERROR] \"--example\" takes one argument.\nNo examples available.\n\n\n\"#]])\n            .with_bin(str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nAvailable binaries:\n    foo\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nNo binaries available.\n\n\n\"#]])\n            .with_test(str![[r#\"\n[ERROR] \"--test\" takes one argument.\nAvailable test targets:\n    test1\n    test2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--test\" takes one argument.\nNo test targets available.\n\n\n\"#]])\n            .with_bench(str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nAvailable bench targets:\n    bench1\n    bench2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nNo bench targets available.\n\n\n\"#]])\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .with_target(str![[r#\"\n[ERROR] \"--target\" takes a target architecture as an argument.\n\nRun `[..]` to see possible targets.\n\n\"#]])\n            .build(),\n    );\n}\n\n#[cargo_test]\nfn install_list_availables() {\n    list_availables_test(\n        \"install\",\n        SnapshotsBuilder::new()\n            .with_example(\n                str![[r#\"\n[ERROR] \"--example\" takes one argument.\nAvailable examples:\n    a\n    b\n\n\n\"#]],\n                str![[r#\"\n[ERROR] \"--example\" takes one argument.\nNo examples available.\n\n\n\"#]],\n            )\n            .with_bin(\n                str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nAvailable binaries:\n    foo\n\n\n\"#]],\n                str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nNo binaries available.\n\n\n\"#]],\n            )\n            .with_target(str![[r#\"\n[ERROR] \"--target\" takes a target architecture as an argument.\n\nRun `[..]` to see possible targets.\n\n\"#]])\n            .build(),\n    );\n}\n\n#[cargo_test]\nfn rustdoc_list_availables() {\n    list_availables_test(\n        \"rustdoc\",\n        SnapshotsBuilder::new()\n            .with_example(str![[r#\"\n[ERROR] \"--example\" takes one argument.\nAvailable examples:\n    a\n    b\n\n\n\"#]], str![[r#\"\n[ERROR] \"--example\" takes one argument.\nNo examples available.\n\n\n\"#]])\n            .with_bin(str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nAvailable binaries:\n    foo\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nNo binaries available.\n\n\n\"#]])\n            .with_test(str![[r#\"\n[ERROR] \"--test\" takes one argument.\nAvailable test targets:\n    test1\n    test2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--test\" takes one argument.\nNo test targets available.\n\n\n\"#]])\n            .with_bench(str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nAvailable bench targets:\n    bench1\n    bench2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nNo bench targets available.\n\n\n\"#]])\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .with_target(str![[r#\"\n[ERROR] \"--target\" takes a target architecture as an argument.\n\nRun `[..]` to see possible targets.\n\n\"#]])\n            .build(),\n    );\n}\n\n#[cargo_test]\nfn rustc_list_availables() {\n    list_availables_test(\n        \"rustc\",\n        SnapshotsBuilder::new()\n            .with_example(str![[r#\"\n[ERROR] \"--example\" takes one argument.\nAvailable examples:\n    a\n    b\n\n\n\"#]], str![[r#\"\n[ERROR] \"--example\" takes one argument.\nNo examples available.\n\n\n\"#]])\n            .with_bin(str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nAvailable binaries:\n    foo\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nNo binaries available.\n\n\n\"#]])\n            .with_test(str![[r#\"\n[ERROR] \"--test\" takes one argument.\nAvailable test targets:\n    test1\n    test2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--test\" takes one argument.\nNo test targets available.\n\n\n\"#]])\n            .with_bench(str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nAvailable bench targets:\n    bench1\n    bench2\n\n\n\"#]], str![[r#\"\n[ERROR] \"--bench\" takes one argument.\nNo bench targets available.\n\n\n\"#]])\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .with_target(str![[r#\"\n[ERROR] \"--target\" takes a target architecture as an argument.\n\nRun `[..]` to see possible targets.\n\n\"#]])\n            .build(),\n    );\n}\n\n#[cargo_test]\nfn pkgid_list_availables() {\n    list_availables_test(\n        \"pkgid\",\n        SnapshotsBuilder::new()\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .build(),\n    );\n}\n\n#[cargo_test]\nfn tree_list_availables() {\n    list_availables_test(\n        \"tree\",\n        SnapshotsBuilder::new()\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .with_target(str![[r#\"\n[ERROR] \"--target\" takes a target architecture as an argument.\n\nRun `[..]` to see possible targets.\n\n\"#]])\n            .build(),\n    )\n}\n\n#[cargo_test]\nfn clean_list_availables() {\n    list_availables_test(\n        \"clean\",\n        SnapshotsBuilder::new()\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .with_target(str![[r#\"\n[ERROR] \"--target\" takes a target architecture as an argument.\n\nRun `[..]` to see possible targets.\n\n\"#]])\n            .build(),\n    );\n}\n\n#[cargo_test]\nfn update_list_availables() {\n    list_availables_test(\n        \"update\",\n        SnapshotsBuilder::new()\n            .with_package(str![[r#\"\n[ERROR] \"--package <SPEC>\" requires a SPEC format value, which can be any package ID specifier in the dependency graph.\nRun `cargo help pkgid` for more information about SPEC format.\n\nPossible packages/workspace members:\n    foo\n\n\n\"#]])\n            .build(),\n    );\n}\n\nstruct ExpectedSnapshots<T: IntoData> {\n    example: ProjectExpected<T>,\n    bin: ProjectExpected<T>,\n    test: ProjectExpected<T>,\n    bench: ProjectExpected<T>,\n    package: ProjectExpected<T>,\n    target: ProjectExpected<T>,\n}\n\nstruct ProjectExpected<T: IntoData> {\n    full: Option<T>,\n    empty: Option<T>,\n}\n\nstruct SnapshotsBuilder<T: IntoData> {\n    example: ProjectExpected<T>,\n    bin: ProjectExpected<T>,\n    test: ProjectExpected<T>,\n    bench: ProjectExpected<T>,\n    package: ProjectExpected<T>,\n    target: ProjectExpected<T>,\n}\n\nimpl<T: IntoData> SnapshotsBuilder<T> {\n    pub fn new() -> Self {\n        Self {\n            example: ProjectExpected {\n                full: None,\n                empty: None,\n            },\n            bin: ProjectExpected {\n                full: None,\n                empty: None,\n            },\n            test: ProjectExpected {\n                full: None,\n                empty: None,\n            },\n            bench: ProjectExpected {\n                full: None,\n                empty: None,\n            },\n            package: ProjectExpected {\n                full: None,\n                empty: None,\n            },\n            target: ProjectExpected {\n                full: None,\n                empty: None,\n            },\n        }\n    }\n\n    fn with_example(mut self, full: T, empty: T) -> Self {\n        self.example.full = Some(full);\n        self.example.empty = Some(empty);\n        self\n    }\n\n    fn with_bin(mut self, full: T, empty: T) -> Self {\n        self.bin.full = Some(full);\n        self.bin.empty = Some(empty);\n        self\n    }\n\n    fn with_test(mut self, full: T, empty: T) -> Self {\n        self.test.full = Some(full);\n        self.test.empty = Some(empty);\n        self\n    }\n\n    fn with_bench(mut self, full: T, empty: T) -> Self {\n        self.bench.full = Some(full);\n        self.bench.empty = Some(empty);\n        self\n    }\n\n    fn with_package(mut self, full: T) -> Self {\n        self.package.full = Some(full);\n        self\n    }\n\n    fn with_target(mut self, empty: T) -> Self {\n        self.target.empty = Some(empty);\n        self\n    }\n\n    fn build(self) -> ExpectedSnapshots<T> {\n        ExpectedSnapshots {\n            example: self.example,\n            bin: self.bin,\n            test: self.test,\n            bench: self.bench,\n            package: self.package,\n            target: self.target,\n        }\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/local_registry.rs",
    "content": "//! Tests for local-registry sources.\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::{Package, registry_path};\nuse cargo_test_support::{basic_manifest, project, str, t};\n\nfn setup() {\n    let root = paths::root();\n    t!(fs::create_dir(&root.join(\".cargo\")));\n    t!(fs::write(\n        root.join(\".cargo/config.toml\"),\n        r#\"\n            [source.crates-io]\n            registry = 'https://wut'\n            replace-with = 'my-awesome-local-registry'\n\n            [source.my-awesome-local-registry]\n            local-registry = 'registry'\n        \"#\n    ));\n}\n\n#[cargo_test]\nfn simple() {\n    setup();\n    Package::new(\"bar\", \"0.0.1\")\n        .local(true)\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.0.1\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[UNPACKING] bar v0.0.1 (registry `[ROOT]/registry`)\n[COMPILING] bar v0.0.1\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn not_found() {\n    setup();\n    // Publish a package so that the directory hierarchy is created.\n    // Note, however, that we declare a dependency on baz.\n    Package::new(\"bar\", \"0.0.1\").local(true).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"0.0.1\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate baz; pub fn foo() { baz::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no matching package named `baz` found\nlocation searched: `[ROOT]/registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn depend_on_yanked() {\n    setup();\n    Package::new(\"bar\", \"0.0.1\").local(true).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Run cargo to create lock file.\n    p.cargo(\"check\").run();\n\n    registry_path().join(\"index\").join(\"3\").rm_rf();\n    Package::new(\"bar\", \"0.0.1\")\n        .local(true)\n        .yanked(true)\n        .publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_versions() {\n    setup();\n    Package::new(\"bar\", \"0.0.1\").local(true).publish();\n    Package::new(\"bar\", \"0.1.0\")\n        .local(true)\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[UNPACKING] bar v0.1.0 (registry `[ROOT]/registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    Package::new(\"bar\", \"0.2.0\")\n        .local(true)\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .publish();\n\n    p.cargo(\"update\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.1.0 -> v0.2.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_names() {\n    setup();\n    Package::new(\"bar\", \"0.0.1\")\n        .local(true)\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .publish();\n    Package::new(\"baz\", \"0.1.0\")\n        .local(true)\n        .file(\"src/lib.rs\", \"pub fn baz() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n                baz = \"*\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate bar;\n                extern crate baz;\n                pub fn foo() {\n                    bar::bar();\n                    baz::baz();\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[UNPACKING] bar v0.0.1 (registry `[ROOT]/registry`)\n[UNPACKING] baz v0.1.0 (registry `[ROOT]/registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] baz v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn interdependent() {\n    setup();\n    Package::new(\"bar\", \"0.0.1\")\n        .local(true)\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .publish();\n    Package::new(\"baz\", \"0.1.0\")\n        .local(true)\n        .dep(\"bar\", \"*\")\n        .file(\"src/lib.rs\", \"extern crate bar; pub fn baz() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n                baz = \"*\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate bar;\n                extern crate baz;\n                pub fn foo() {\n                    bar::bar();\n                    baz::baz();\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[UNPACKING] bar v0.0.1 (registry `[ROOT]/registry`)\n[UNPACKING] baz v0.1.0 (registry `[ROOT]/registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] baz v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn path_dep_rewritten() {\n    setup();\n    Package::new(\"bar\", \"0.0.1\")\n        .local(true)\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .publish();\n    Package::new(\"baz\", \"0.1.0\")\n        .local(true)\n        .dep(\"bar\", \"*\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\", version = \"*\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar; pub fn baz() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n                baz = \"*\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate bar;\n                extern crate baz;\n                pub fn foo() {\n                    bar::bar();\n                    baz::baz();\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[UNPACKING] bar v0.0.1 (registry `[ROOT]/registry`)\n[UNPACKING] baz v0.1.0 (registry `[ROOT]/registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] baz v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_dir_bad() {\n    setup();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [source.crates-io]\n                registry = 'https://wut'\n                replace-with = 'my-awesome-local-directory'\n\n                [source.my-awesome-local-directory]\n                local-registry = '/path/to/nowhere'\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update registry `crates-io`\n\nCaused by:\n  failed to update replaced source registry `crates-io`\n\nCaused by:\n  local registry path is not a directory: [..]path[..]to[..]nowhere\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn different_directory_replacing_the_registry_is_bad() {\n    setup();\n\n    // Move our test's .cargo/config to a temporary location and publish a\n    // registry package we're going to use first.\n    let config = paths::root().join(\".cargo\");\n    let config_tmp = paths::root().join(\".cargo-old\");\n    t!(fs::rename(&config, &config_tmp));\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Generate a lock file against the crates.io registry\n    Package::new(\"bar\", \"0.0.1\").publish();\n    p.cargo(\"check\").run();\n\n    // Switch back to our directory source, and now that we're replacing\n    // crates.io make sure that this fails because we're replacing with a\n    // different checksum\n    config.rm_rf();\n    t!(fs::rename(&config_tmp, &config));\n    Package::new(\"bar\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"invalid\")\n        .local(true)\n        .publish();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] checksum for `bar v0.0.1` changed between lock files\n\nthis could be indicative of a few possible errors:\n\n    * the lock file is corrupt\n    * a replacement source in use (e.g., a mirror) returned a different checksum\n    * the source itself may be corrupt in one way or another\n\nunable to verify that `bar v0.0.1` is the same as when the lockfile was generated\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn crates_io_registry_url_is_optional() {\n    let root = paths::root();\n    t!(fs::create_dir(&root.join(\".cargo\")));\n    t!(fs::write(\n        root.join(\".cargo/config.toml\"),\n        r#\"\n            [source.crates-io]\n            replace-with = 'my-awesome-local-registry'\n\n            [source.my-awesome-local-registry]\n            local-registry = 'registry'\n        \"#\n    ));\n\n    Package::new(\"bar\", \"0.0.1\")\n        .local(true)\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.0.1\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[UNPACKING] bar v0.0.1 (registry `[ROOT]/registry`)\n[COMPILING] bar v0.0.1\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"test\").run();\n}\n"
  },
  {
    "path": "tests/testsuite/locate_project.rs",
    "content": "//! Tests for the `cargo locate-project` command.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn simple() {\n    let p = project().build();\n\n    p.cargo(\"locate-project\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn message_format() {\n    let p = project().build();\n\n    p.cargo(\"locate-project --message-format plain\")\n        .with_stdout_data(str![[r#\"\n[ROOT]/foo/Cargo.toml\n\n\"#]])\n        .run();\n\n    p.cargo(\"locate-project --message-format json\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n\n    p.cargo(\"locate-project --message-format cryptic\")\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid value 'cryptic' for '--message-format <FMT>'\n  [possible values: json, plain]\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"outer\"\n                version = \"0.0.0\"\n\n                [workspace]\n                members = [\"inner\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"inner/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"inner\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"inner/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n\n    p.cargo(\"locate-project\")\n        .cwd(\"inner\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/inner/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n\n    p.cargo(\"locate-project --workspace\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"inner\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_missing_member() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"root\"\n                version = \"0.0.0\"\n\n                [workspace]\n                members = [\"missing_member\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_nested_with_explicit_pointer() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"root\"\n                version = \"0.0.0\"\n\n                [workspace]\n                members = [\"nested\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"nested/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"nested\"\n                version = \"0.0.0\"\n                workspace = \"..\"\n            \"#,\n        )\n        .file(\"nested/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"nested\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_not_a_member() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"member\"]\n            \"#,\n        )\n        .file(\n            \"member/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"member\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"member/src/lib.rs\", \"\")\n        .file(\n            \"not-member/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"not-member\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"not-member/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"not-member\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] current package believes it's in a workspace when it's not:\ncurrent:   [ROOT]/foo/not-member/Cargo.toml\nworkspace: [ROOT]/foo/Cargo.toml\n\nthis may be fixable by adding `not-member` to the `workspace.members` array of the manifest located at: [ROOT]/foo/Cargo.toml\nAlternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest.\n\n\"#]])\n        .run();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"not-member/src\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] current package believes it's in a workspace when it's not:\ncurrent:   [ROOT]/foo/not-member/Cargo.toml\nworkspace: [ROOT]/foo/Cargo.toml\n\nthis may be fixable by adding `not-member` to the `workspace.members` array of the manifest located at: [ROOT]/foo/Cargo.toml\nAlternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_pointer_to_sibling_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"outer-member\"]\n            \"#,\n        )\n        .file(\n            \"outer-member/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"outer-member\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"outer-member/src/lib.rs\", \"\")\n        .file(\n            \"sibling-workspace/Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"../pkg\"]\n            \"#,\n        )\n        .file(\n            \"pkg/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pkg\"\n                version = \"0.0.0\"\n                workspace = \"../sibling-workspace\"\n            \"#,\n        )\n        .file(\"pkg/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"pkg\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/sibling-workspace/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_member_in_both_members_and_exclude() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"pkg\"]\n                exclude = [\"pkg\"]\n            \"#,\n        )\n        .file(\n            \"pkg/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pkg\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"pkg/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"pkg\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_default_members_not_in_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = []\n                default-members = [\"pkg\"]\n            \"#,\n        )\n        .file(\n            \"pkg/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pkg\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"pkg/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package `[ROOT]/foo/pkg` is listed in default-members but is not a member\nfor workspace at `[ROOT]/foo/Cargo.toml`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_default_members_and_exclude() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"pkg\", \"other\"]\n                default-members = [\"pkg\"]\n                exclude = [\"pkg\"]\n            \"#,\n        )\n        .file(\n            \"pkg/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pkg\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"pkg/src/lib.rs\", \"\")\n        .file(\n            \"other/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"other\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"other/src/lib.rs\", \"\")\n        .build();\n\n    // pkg is in members, default-members, and exclude.\n    // Since it's in members, it's still a workspace member (member wins over exclude).\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"pkg\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_member_with_own_workspace_invalid_default_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"pkg\"]\n            \"#,\n        )\n        .file(\n            \"pkg/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pkg\"\n                version = \"0.0.0\"\n\n                [workspace]\n                default-members = [\"nonexistent\"]\n            \"#,\n        )\n        .file(\"pkg/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"pkg\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package `[ROOT]/foo/pkg/nonexistent` is listed in default-members but is not a member\nfor workspace at `[ROOT]/foo/pkg/Cargo.toml`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_default_member_and_exclude_but_not_member() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"pkg-a\"]\n                default-members = [\"pkg-b\"]\n                exclude = [\"pkg-b\"]\n            \"#,\n        )\n        .file(\n            \"pkg-a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pkg-a\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"pkg-a/src/lib.rs\", \"\")\n        .file(\n            \"pkg-b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pkg-b\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"pkg-b/src/lib.rs\", \"\")\n        .build();\n\n    // Should error because pkg-b is in default-members but not in members\n    // The exclude doesn't help since it's not in members either\n    p.cargo(\"locate-project --workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package `[ROOT]/foo/pkg-b` is listed in default-members but is not a member\nfor workspace at `[ROOT]/foo/Cargo.toml`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_only_in_exclude() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"other\"]\n                exclude = [\"pkg\"]\n            \"#,\n        )\n        .file(\n            \"other/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"other\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"other/src/lib.rs\", \"\")\n        .file(\n            \"pkg/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pkg\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"pkg/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"pkg\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/pkg/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_only_exclude_no_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                exclude = [\"pkg\"]\n            \"#,\n        )\n        .file(\n            \"pkg/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pkg\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"pkg/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"pkg\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/pkg/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_glob_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"crates/*\"]\n            \"#,\n        )\n        .file(\n            \"crates/foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"crates/foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"crates/foo\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_glob_members_parent_path() {\n    let p = project()\n        .file(\n            \"workspace/Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"../crates/*\"]\n            \"#,\n        )\n        .file(\n            \"crates/foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                workspace = \"../../workspace\"\n            \"#,\n        )\n        .file(\"crates/foo/src/lib.rs\", \"\")\n        .file(\n            \"crates/bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.0\"\n                workspace = \"../../workspace\"\n            \"#,\n        )\n        .file(\"crates/bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"crates/foo\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/workspace/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"crates/bar\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/workspace/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_path_dependency_member() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"root\"\n                version = \"0.0.0\"\n\n                [workspace]\n\n                [dependencies]\n                path-dep = { path = \"path-dep\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"path-dep/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"path-dep\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"path-dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"path-dep\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_nested_subdirectory_not_member() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"crate-a\"]\n            \"#,\n        )\n        .file(\n            \"crate-a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"crate-a\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"crate-a/src/lib.rs\", \"\")\n        .file(\n            \"crate-a/subcrate/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"subcrate\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"crate-a/subcrate/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"crate-a/subcrate\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] current package believes it's in a workspace when it's not:\ncurrent:   [ROOT]/foo/crate-a/subcrate/Cargo.toml\nworkspace: [ROOT]/foo/Cargo.toml\n\nthis may be fixable by adding `crate-a/subcrate` to the `workspace.members` array of the manifest located at: [ROOT]/foo/Cargo.toml\nAlternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn nested_independent_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"member\"]\n            \"#,\n        )\n        .file(\n            \"member/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"member\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"member/src/lib.rs\", \"\")\n        .file(\n            \"nested-ws/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"nested-ws\"\n                version = \"0.0.0\"\n\n                [workspace]\n            \"#,\n        )\n        .file(\"nested-ws/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"locate-project --workspace\")\n        .cwd(\"nested-ws/src\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"root\": \"[ROOT]/foo/nested-ws/Cargo.toml\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lockfile_compat.rs",
    "content": "//! Tests for supporting older versions of the Cargo.lock file format.\n\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::git;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_lib_manifest, basic_manifest, project};\n\n#[cargo_test]\nfn oldest_lockfile_still_works() {\n    let cargo_commands = vec![\"build\", \"update\"];\n    for cargo_command in cargo_commands {\n        oldest_lockfile_still_works_with_command(cargo_command);\n    }\n}\n\nfn oldest_lockfile_still_works_with_command(cargo_command: &str) {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let expected_lockfile = str![[r##\"\n# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"[..]\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar\",\n]\n\n\"##]];\n\n    let old_lockfile = r#\"\n[root]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\"#;\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"Cargo.lock\", old_lockfile)\n        .build();\n\n    p.cargo(cargo_command).run();\n\n    let lock = p.read_lockfile();\n    assert_e2e().eq(&lock, expected_lockfile);\n}\n\n#[cargo_test]\nfn frozen_flag_preserves_old_lockfile() {\n    let cksum = Package::new(\"bar\", \"0.1.0\").publish();\n\n    let old_lockfile = format!(\n        r#\"[root]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n[metadata]\n\"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\" = \"{}\"\n\"#,\n        cksum,\n    );\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"Cargo.lock\", &old_lockfile)\n        .build();\n\n    p.cargo(\"check --locked\").run();\n\n    let lock = p.read_lockfile();\n    assert_e2e().eq(&lock, &old_lockfile);\n}\n\n#[cargo_test]\nfn totally_wild_checksums_works() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.lock\",\n            r#\"\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n[metadata]\n\"checksum baz 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)\" = \"checksum\"\n\"checksum bar 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)\" = \"checksum\"\n\"#,\n        );\n\n    let p = p.build();\n\n    p.cargo(\"check\").run();\n\n    let lock = p.read_lockfile();\n    assert_e2e().eq(\n        &lock,\n        str![[r##\"\n# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"[..]\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar\",\n]\n\n\"##]],\n    );\n}\n\n#[cargo_test]\nfn wrong_checksum_is_an_error() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.lock\",\n            r#\"\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n[metadata]\n\"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\" = \"checksum\"\n\"#,\n        );\n\n    let p = p.build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] checksum for `bar v0.1.0` changed between lock files\n\nthis could be indicative of a few possible errors:\n\n    * the lock file is corrupt\n    * a replacement source in use (e.g., a mirror) returned a different checksum\n    * the source itself may be corrupt in one way or another\n\nunable to verify that `bar v0.1.0` is the same as when the lockfile was generated\n\n\n\"#]])\n        .run();\n}\n\n// If the checksum is unlisted in the lock file (e.g., <none>) yet we can\n// calculate it (e.g., it's a registry dep), then we should in theory just fill\n// it in.\n#[cargo_test]\nfn unlisted_checksum_is_bad_if_we_calculate() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.lock\",\n            r#\"\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n[metadata]\n\"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\" = \"<none>\"\n\"#,\n        );\n    let p = p.build();\n\n    p.cargo(\"fetch\").with_status(101).with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] checksum for `bar v0.1.0` was not previously calculated, but a checksum could now be calculated\n\nthis could be indicative of a few possible situations:\n\n    * the source `registry `crates-io`` did not previously support checksums,\n      but was replaced with one that does\n    * newer Cargo implementations know how to checksum this source, but this\n      older implementation does not\n    * the lock file is corrupt\n\n\n\"#]]).run();\n}\n\n// If the checksum is listed in the lock file yet we cannot calculate it (e.g.,\n// Git dependencies as of today), then make sure we choke.\n#[cargo_test]\nfn listed_checksum_bad_if_we_cannot_compute() {\n    let git = git::new(\"bar\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = {{ git = '{}' }}\n                \"#,\n                git.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.lock\",\n            &format!(\n                r#\"\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar 0.1.0 (git+{0})\"\n]\n\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"git+{0}\"\n\n[metadata]\n\"checksum bar 0.1.0 (git+{0})\" = \"checksum\"\n\"#,\n                git.url()\n            ),\n        );\n\n    let p = p.build();\n\n    p.cargo(\"fetch\").with_status(101).with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[ERROR] checksum for `bar v0.1.0 ([ROOTURL]/bar)` could not be calculated, but a checksum is listed in the existing lock file\n\nthis could be indicative of a few possible situations:\n\n    * the source `[ROOTURL]/bar` supports checksums,\n      but was replaced with one that doesn't\n    * the lock file is corrupt\n\nunable to verify that `bar v0.1.0 ([ROOTURL]/bar)` is the same as when the lockfile was generated\n\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn current_lockfile_format() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"check\").run();\n\n    let actual = p.read_lockfile();\n\n    let expected = str![[r##\"\n# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"[..]\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar\",\n]\n\n\"##]];\n    assert_e2e().eq(&actual, expected);\n}\n\n#[cargo_test]\nfn lockfile_without_root() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let lockfile = r#\"\n# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar\",\n]\n\"#;\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"Cargo.lock\", lockfile);\n\n    let p = p.build();\n\n    p.cargo(\"check\").run();\n\n    let lock = p.read_lockfile();\n    assert_e2e().eq(\n        &lock,\n        str![[r##\"\n# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"[..]\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar\",\n]\n\n\"##]],\n    );\n}\n\n#[cargo_test]\nfn locked_correct_error() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"check --locked\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] cannot create the lock file [ROOT]/foo/Cargo.lock because --locked was passed to prevent this\n[HELP] to generate the lock file without accessing the network, remove the --locked flag and use --offline instead.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn v2_format_preserved() {\n    let cksum = Package::new(\"bar\", \"0.1.0\").publish();\n\n    let lockfile = format!(\n        r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"{}\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar\",\n]\n\"#,\n        cksum\n    );\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"Cargo.lock\", &lockfile)\n        .build();\n\n    p.cargo(\"fetch\").run();\n\n    let lock = p.read_lockfile();\n    assert_e2e().eq(&lock, &lockfile);\n}\n\n#[cargo_test]\nfn v2_path_and_crates_io() {\n    let cksum010 = Package::new(\"a\", \"0.1.0\").publish();\n    let cksum020 = Package::new(\"a\", \"0.2.0\").publish();\n\n    let lockfile = format!(\n        r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\n[[package]]\nname = \"a\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"{}\"\n\n[[package]]\nname = \"a\"\nversion = \"0.2.0\"\n\n[[package]]\nname = \"a\"\nversion = \"0.2.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"{}\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"a 0.1.0\",\n \"a 0.2.0\",\n \"a 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n\"#,\n        cksum010, cksum020,\n    );\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = 'a' }\n                b = { version = \"0.1\", package = 'a' }\n                c = { version = \"0.2\", package = 'a' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.2.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\"Cargo.lock\", &lockfile)\n        .build();\n\n    p.cargo(\"fetch\").run();\n    p.cargo(\"fetch\").run();\n\n    let lock = p.read_lockfile();\n    assert_e2e().eq(&lock, &lockfile);\n}\n\n#[cargo_test]\nfn v3_and_git() {\n    let (git_project, repo) = git::new_repo(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let head_id = repo.head().unwrap().target().unwrap();\n\n    let lockfile = format!(\n        r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 3\n\n[[package]]\nname = \"dep1\"\nversion = \"0.5.0\"\nsource = \"git+[ROOTURL]/dep1?branch=master#{}\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"dep1\",\n]\n\"#,\n        head_id,\n    );\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    rust-version = \"1.81\" # ensure it stays in lockfile v3\n\n                    [dependencies]\n                    dep1 = {{ git = '{}', branch = 'master' }}\n                \"#,\n                git_project.url(),\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"Cargo.lock\", \"version = 3\")\n        .build();\n\n    p.cargo(\"fetch\").run();\n\n    let lock = p.read_lockfile();\n    assert_e2e().eq(&lock, &lockfile);\n}\n\n#[cargo_test]\nfn lock_from_the_future() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"Cargo.lock\", \"version = 10000000\")\n        .build();\n\n    p.cargo(\"fetch\").with_stderr_data(str![[r#\"\n[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock\n\nCaused by:\n  lock file version `10000000` was found, but this version of Cargo does not understand this lock file, perhaps Cargo needs to be updated?\n\n\"#]]).with_status(101).run();\n}\n\n#[cargo_test]\nfn preserve_old_format_if_no_update_needed() {\n    let cksum = Package::new(\"bar\", \"0.1.0\").publish();\n    let lockfile = format!(\n        r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n\n[metadata]\n\"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\" = \"{}\"\n\"#,\n        cksum\n    );\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"Cargo.lock\", &lockfile)\n        .build();\n\n    p.cargo(\"check --locked\").run();\n}\n\n#[cargo_test]\nfn same_name_version_different_sources() {\n    let cksum = Package::new(\"foo\", \"0.1.0\").publish();\n    let (git_project, repo) = git::new_repo(\"dep1\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n                \"#,\n            )\n            .file(\"src/lib.rs\", \"\")\n    });\n    let head_id = repo.head().unwrap().target().unwrap();\n\n    // Lockfile was generated with Rust 1.51\n    let lockfile = format!(\n        r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 3\n\n[[package]]\nname = \"foo\"\nversion = \"0.1.0\"\ndependencies = [\n \"foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n \"foo 0.1.0 (git+{url})\",\n]\n\n[[package]]\nname = \"foo\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"{cksum}\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.1.0\"\nsource = \"git+{url}#{sha}\"\n\"#,\n        sha = head_id,\n        url = git_project.url(),\n        cksum = cksum\n    );\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    foo = \"0.1.0\"\n                    foo2 = {{ git = '{}', package = 'foo' }}\n                \"#,\n                git_project.url(),\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"Cargo.lock\", &lockfile)\n        .build();\n\n    p.cargo(\"check\").run();\n\n    assert_eq!(p.read_file(\"Cargo.lock\"), lockfile);\n}\n\n#[cargo_test]\nfn bad_data_in_lockfile_error_meg() {\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"Cargo.lock\",\n            r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 3\n\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"8e1b9346248cf3391ead604c4407258d327c28e37209f6d56127598165165dda\"\n\n[[package]]\nname = \"test\"\nversion = \"0.0.0\"\ndependencies = [\n \"bar\",\n]\"#,\n        )\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `bar = \"*\"` (locked to 0.1.0)\ncandidate versions found which didn't match: 0.0.1\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `test v0.0.0 ([ROOT]/foo)`\nperhaps a crate was updated and forgotten to be re-vendored?\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn next_version_is_always_unstable() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                \"#,\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"Cargo.lock\", \"version = 5\")\n        .build();\n\n    p.cargo(\"fetch\").with_status(101).with_stderr_data(str![[r#\"\n[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock\n\nCaused by:\n  lock file version `5` was found, but this version of Cargo does not understand this lock file, perhaps Cargo needs to be updated?\n\n\"#]]).run();\n\n    // On nightly, let the user know about the `-Z` flag.\n    p.cargo(\"fetch\")\n        .masquerade_as_nightly_cargo(&[\"-Znext-lockfile-bump\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock\n\nCaused by:\n  lock file version `5` requires `-Znext-lockfile-bump`\n\n\"#]])\n        .run();\n}\n\nfn create_branch(repo: &git2::Repository, branch: &str, head_id: git2::Oid) {\n    repo.branch(branch, &repo.find_commit(head_id).unwrap(), true)\n        .unwrap();\n}\n\nfn create_tag(repo: &git2::Repository, tag: &str, head_id: git2::Oid) {\n    repo.tag(\n        tag,\n        &repo.find_object(head_id, None).unwrap(),\n        &repo.signature().unwrap(),\n        \"make a new tag\",\n        false,\n    )\n    .unwrap();\n}\n\nfn v3_and_git_url_encoded(ref_kind: &str, f: impl FnOnce(&git2::Repository, &str, git2::Oid)) {\n    let (git_project, repo) = git::new_repo(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let url = git_project.url();\n    let head_id = repo.head().unwrap().target().unwrap();\n    // Ref name with special characters\n    let git_ref = \"a-_+#$)\";\n    let encoded_ref = \"a-_%2B%23%24%29\";\n    f(&repo, git_ref, head_id);\n\n    let lockfile = format!(\n        r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 3\n\n[[package]]\nname = \"dep1\"\nversion = \"0.5.0\"\nsource = \"git+[ROOTURL]/dep1?{ref_kind}={git_ref}#{head_id}\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"dep1\",\n]\n\"#,\n    );\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    rust-version = \"1.81\" # ensure it stays in lockfile v3\n\n                    [dependencies]\n                    dep1 = {{ git = '{url}', {ref_kind} = '{git_ref}' }}\n                \"#,\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"Cargo.lock\", \"version = 3\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(format!(\n            \"\\\n[UPDATING] git repository `[ROOTURL]/dep1`\n[LOCKING] 1 package to latest compatible version\n[ADDING] dep1 v0.5.0 ([ROOTURL]/dep1?{ref_kind}={encoded_ref}#[..])\n[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1?{ref_kind}={encoded_ref}#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\"\n        ))\n        .run();\n\n    let lock = p.read_lockfile();\n    assert_e2e().eq(&lock, &lockfile);\n\n    // v3 doesn't URL-encode URL parameters, but `url` crate does decode as it\n    // was URL-encoded. Therefore Cargo thinks they are from different source\n    // and clones the repository again.\n    p.cargo(\"check\")\n        .with_stderr_data(format!(\n            \"\\\n[UPDATING] git repository `[ROOTURL]/dep1`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\"\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn v3_and_git_url_encoded_branch() {\n    v3_and_git_url_encoded(\"branch\", create_branch);\n}\n\n#[cargo_test]\nfn v3_and_git_url_encoded_tag() {\n    v3_and_git_url_encoded(\"tag\", create_tag);\n}\n\n#[cargo_test]\nfn v3_and_git_url_encoded_rev() {\n    v3_and_git_url_encoded(\"rev\", create_tag);\n}\n\nfn v4_and_git_url_encoded(ref_kind: &str, f: impl FnOnce(&git2::Repository, &str, git2::Oid)) {\n    let (git_project, repo) = git::new_repo(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"dep1\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let url = git_project.url();\n    let head_id = repo.head().unwrap().target().unwrap();\n    // Ref name with special characters\n    let git_ref = \"a-_+#$)\";\n    let encoded_ref = \"a-_%2B%23%24%29\";\n    f(&repo, git_ref, head_id);\n\n    let lockfile = format!(\n        r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"dep1\"\nversion = \"0.5.0\"\nsource = \"git+[ROOTURL]/dep1?{ref_kind}={encoded_ref}#{head_id}\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"dep1\",\n]\n\"#,\n    );\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    dep1 = {{ git = '{url}', {ref_kind} = '{git_ref}' }}\n                \"#,\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"Cargo.lock\", \"version = 4\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(format!(\n            \"\\\n[UPDATING] git repository `[ROOTURL]/dep1`\n[LOCKING] 1 package to latest compatible version\n[ADDING] dep1 v0.5.0 ([ROOTURL]/dep1?{ref_kind}={encoded_ref}#[..])\n[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1?{ref_kind}={encoded_ref}#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\"\n        ))\n        .run();\n\n    let lock = p.read_lockfile();\n    assert_e2e().eq(&lock, &lockfile);\n\n    // Unlike v3_and_git_url_encoded, v4 encodes URL parameters so no git\n    // repository re-clone happen.\n    p.cargo(\"check\")\n        .with_stderr_data(\n            \"\\\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn v4_and_git_url_encoded_branch() {\n    v4_and_git_url_encoded(\"branch\", create_branch);\n}\n\n#[cargo_test]\nfn v4_and_git_url_encoded_tag() {\n    v4_and_git_url_encoded(\"tag\", create_tag);\n}\n\n#[cargo_test]\nfn v4_and_git_url_encoded_rev() {\n    v4_and_git_url_encoded(\"rev\", create_tag)\n}\n\n#[cargo_test]\nfn with_msrv() {\n    let cksum = Package::new(\"bar\", \"0.1.0\").publish();\n\n    let v3_lockfile = format!(\n        r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 3\n\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"{cksum}\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar\",\n]\n\"#\n    );\n    let v2_lockfile = format!(\n        r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"{cksum}\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar\",\n]\n\"#\n    );\n\n    let v1_lockfile = format!(\n        r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\ndependencies = [\n \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n\n[metadata]\n\"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\" = \"{cksum}\"\n\"#\n    );\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let cases = [\n        // v1 is the default\n        (\"1.37\", None, 1),\n        (\"1.37\", Some(1), 1),\n        (\"1.37\", Some(2), 2),\n        (\"1.37\", Some(3), 3),\n        (\"1.37\", Some(4), 4),\n        // v2 introduced\n        (\"1.38\", None, 1),\n        // last version of v1 as the default\n        (\"1.40\", None, 1),\n        // v2 is the default\n        (\"1.41\", None, 2),\n        (\"1.41\", Some(1), 1),\n        (\"1.41\", Some(2), 2),\n        (\"1.41\", Some(3), 3),\n        (\"1.41\", Some(4), 4),\n        // v3 introduced\n        (\"1.47\", None, 2),\n        // last version of v2 as the default\n        (\"1.48\", None, 2),\n        // v3 is the default\n        (\"1.53\", None, 3),\n        (\"1.53\", Some(1), 1),\n        (\"1.53\", Some(2), 2),\n        (\"1.53\", Some(3), 3),\n        (\"1.53\", Some(4), 4),\n        // v4 introduced\n        (\"1.78\", None, 3),\n        // last version of v3 as the default\n        (\"1.82\", None, 3),\n        // v4 is the default\n        (\"1.83\", None, 4),\n        (\"1.83\", Some(1), 1),\n        (\"1.83\", Some(2), 2),\n        (\"1.83\", Some(3), 3),\n        (\"1.83\", Some(4), 4),\n    ];\n\n    for (msrv, existing_lockfile, expected_version) in cases {\n        // Clean previous lockfile.\n        _ = std::fs::remove_file(p.root().join(\"Cargo.lock\"));\n\n        p.change_file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                rust-version = \"{msrv}\"\n\n                [dependencies]\n                bar = \"0.1.0\"\n                \"#,\n            ),\n        );\n\n        if let Some(existing_lockfile) = existing_lockfile {\n            let existing_lockfile = match existing_lockfile {\n                1 => v1_lockfile.as_str().into(),\n                2 => v2_lockfile.as_str().into(),\n                3 => v3_lockfile.as_str().into(),\n                v => std::borrow::Cow::from(format!(\"version = {v}\")),\n            };\n            p.change_file(\"Cargo.lock\", &existing_lockfile);\n        }\n\n        p.cargo(\"fetch\").run();\n\n        let lock = p.read_lockfile();\n        let toml = lock.parse::<toml::Table>().unwrap();\n        // get `version = <n>` from Cargo.lock\n        let version_field = toml.get(\"version\").and_then(|v| v.as_integer());\n\n        let actual_version = if let Some(ver) = version_field {\n            ver\n        } else if lock.find(\"\\nchecksum = \").is_some() {\n            2\n        } else {\n            1\n        };\n\n        assert_eq!(\n            expected_version, actual_version,\n            \"msrv: {msrv}, existing lockfile: {existing_lockfile:?}\"\n        );\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/lockfile_path.rs",
    "content": "//! Tests for `lockfile-path` flag\n\nuse std::fs;\n\nuse snapbox::str;\n\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::install::assert_has_installed_exe;\nuse cargo_test_support::registry::{Package, RegistryBuilder};\nuse cargo_test_support::{\n    ProjectBuilder, basic_bin_manifest, cargo_test, paths, project, symlink_supported,\n};\n\n#[cargo_test]\nfn config_lockfile_path_without_z_flag() {\n    let p = make_project().build();\n\n    p.cargo(\"generate-lockfile\")\n        .arg(\"--config\")\n        .arg(\"resolver.lockfile-path='my/Cargo.lock'\")\n        .with_stderr_data(str![[r#\"\n[WARNING] ignoring `resolver.lockfile-path`, pass `-Zlockfile-path` to enable it\n\n\"#]])\n        .run();\n\n    assert!(p.root().join(\"Cargo.lock\").exists());\n    assert!(!p.root().join(\"my/Cargo.lock\").exists());\n}\n\n#[cargo_test]\nfn config_lockfile_created() {\n    let lockfile_path = \"mylockfile/Cargo.lock\";\n    let p = make_project().build();\n\n    p.cargo(\"generate-lockfile -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .with_stderr_data(str![\"\"])\n        .run();\n\n    assert!(!p.root().join(\"Cargo.lock\").exists());\n    assert!(p.root().join(lockfile_path).exists());\n}\n\n#[cargo_test]\nfn config_basic_lockfile_read() {\n    let lockfile_path = \"mylockfile/Cargo.lock\";\n    let p = make_project().file(lockfile_path, VALID_LOCKFILE).build();\n\n    p.cargo(\"generate-lockfile -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .run();\n\n    assert!(!p.root().join(\"Cargo.lock\").exists());\n    assert!(p.root().join(lockfile_path).is_file());\n}\n\n#[cargo_test]\nfn config_basic_lockfile_override() {\n    let lockfile_path = \"mylockfile/Cargo.lock\";\n    let p = make_project()\n        .file(\"Cargo.lock\", \"This is an invalid lock file!\")\n        .build();\n\n    p.cargo(\"generate-lockfile -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .run();\n\n    assert!(p.root().join(lockfile_path).is_file());\n}\n\n#[cargo_test]\nfn config_symlink_in_path() {\n    if !symlink_supported() {\n        return;\n    }\n\n    let dst = \"dst\";\n    let src = \"somedir/link\";\n    let lockfile_path = format!(\"{src}/Cargo.lock\");\n\n    let p = make_project().symlink_dir(dst, src).build();\n\n    fs::create_dir(p.root().join(\"dst\")).unwrap();\n    assert!(p.root().join(src).is_dir());\n\n    p.cargo(\"generate-lockfile -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .run();\n\n    assert!(p.root().join(lockfile_path).is_file());\n    assert!(p.root().join(dst).join(\"Cargo.lock\").is_file());\n}\n\n#[cargo_test]\nfn config_symlink_lockfile() {\n    if !symlink_supported() {\n        return;\n    }\n\n    let lockfile_path = \"dst/Cargo.lock\";\n    let src = \"somedir/link\";\n    let lock_body = VALID_LOCKFILE;\n\n    let p = make_project()\n        .file(lockfile_path, lock_body)\n        .symlink(lockfile_path, src)\n        .build();\n\n    assert!(p.root().join(src).is_file());\n\n    p.cargo(\"generate-lockfile -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .run();\n\n    assert!(!p.root().join(\"Cargo.lock\").exists());\n}\n\n#[cargo_test]\nfn config_broken_symlink() {\n    if !symlink_supported() {\n        return;\n    }\n\n    let invalid_dst = \"invalid_path\";\n    let src = \"somedir/link\";\n    let lockfile_path = format!(\"{src}/Cargo.lock\");\n\n    let p = make_project().symlink_dir(invalid_dst, src).build();\n    assert!(!p.root().join(src).is_dir());\n\n    p.cargo(\"generate-lockfile -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to create directory `[ROOT]/foo/somedir/link`\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn config_loop_symlink() {\n    if !symlink_supported() {\n        return;\n    }\n\n    let loop_link = \"loop\";\n    let src = \"somedir/link\";\n    let lockfile_path = format!(\"{src}/Cargo.lock\");\n\n    let p = make_project()\n        .symlink_dir(loop_link, src)\n        .symlink_dir(src, loop_link)\n        .build();\n    assert!(!p.root().join(src).is_dir());\n\n    p.cargo(\"generate-lockfile -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to create directory `[ROOT]/foo/somedir/link`\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn config_add_lockfile_override() {\n    let lockfile_path = \"mylockfile/Cargo.lock\";\n    project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", LIB_TOML)\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    let p = make_project()\n        .file(\"Cargo.lock\", \"This is an invalid lock file!\")\n        .build();\n    p.cargo(\"add -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .arg(\"--path\")\n        .arg(\"../bar\")\n        .run();\n\n    assert!(p.root().join(lockfile_path).is_file());\n}\n\n#[cargo_test]\nfn config_clean_lockfile_override() {\n    let lockfile_path = \"mylockfile/Cargo.lock\";\n    let p = make_project()\n        .file(\"Cargo.lock\", \"This is an invalid lock file!\")\n        .build();\n    p.cargo(\"clean -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .arg(\"--package\")\n        .arg(\"test_foo\")\n        .run();\n\n    assert!(p.root().join(lockfile_path).is_file());\n}\n\n#[cargo_test]\nfn config_fix_lockfile_override() {\n    let lockfile_path = \"mylockfile/Cargo.lock\";\n    let p = make_project()\n        .file(\"Cargo.lock\", \"This is an invalid lock file!\")\n        .build();\n    p.cargo(\"fix -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .arg(\"--package\")\n        .arg(\"test_foo\")\n        .arg(\"--allow-no-vcs\")\n        .run();\n\n    assert!(p.root().join(lockfile_path).is_file());\n}\n\n#[cargo_test]\nfn config_publish_lockfile_read() {\n    let lockfile_path = \"mylockfile/Cargo.lock\";\n    let p = make_project().file(lockfile_path, VALID_LOCKFILE).build();\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    p.cargo(\"publish -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .replace_crates_io(registry.index_url())\n        .run();\n\n    assert!(!p.root().join(\"Cargo.lock\").exists());\n    assert!(p.root().join(lockfile_path).is_file());\n}\n\n#[cargo_test]\nfn config_remove_lockfile_override() {\n    let lockfile_path = \"mylockfile/Cargo.lock\";\n    let manifest = r#\"\n        [package]\n\n        name = \"foo\"\n        version = \"0.5.0\"\n        authors = [\"wycats@example.com\"]\n        edition = \"2015\"\n\n        [[bin]]\n\n        name = \"foo\"\n\n        [dependencies]\n        test_bar = { version = \"0.1.0\", path = \"../bar\" }\n    \"#;\n\n    project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", LIB_TOML)\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    let p = project()\n        .file(\"Cargo.toml\", &manifest)\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"Cargo.lock\", \"This is an invalid lock file!\")\n        .build();\n    p.cargo(\"remove -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .arg(\"test_bar\")\n        .run();\n\n    assert!(p.root().join(lockfile_path).is_file());\n}\n\n#[cargo_test]\nfn config_assert_respect_pinned_version_from_lockfile_path() {\n    let lockfile_path = \"mylockfile/Cargo.lock\";\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"#\n[package]\n\nname = \"test_foo\"\nversion = \"0.5.0\"\nauthors = [\"wycats@example.com\"]\nedition = \"2015\"\n\n[[bin]]\n\nname = \"test_foo\"\n\n[dependencies]\nbar = \"0.1.0\"\n\"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.1.0\").publish();\n    p.cargo(\"generate-lockfile -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .run();\n\n    assert!(!p.root().join(\"Cargo.lock\").exists());\n    assert!(p.root().join(lockfile_path).is_file());\n\n    let lockfile_original = fs::read_to_string(p.root().join(lockfile_path)).unwrap();\n\n    Package::new(\"bar\", \"0.1.1\").publish();\n    p.cargo(\"package -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .run();\n\n    assert!(\n        p.root()\n            .join(\"target/package/test_foo-0.5.0/Cargo.lock\")\n            .is_file()\n    );\n\n    let path = p.root().join(\"target/package/test_foo-0.5.0/Cargo.lock\");\n    let contents = fs::read_to_string(path).unwrap();\n\n    assert_e2e().eq(contents, lockfile_original);\n}\n\n#[cargo_test]\nfn config_install_respects_lock_file_path() {\n    // `cargo install` will imply --locked when lockfile path is provided\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.1\")\n        .file(\"src/lib.rs\", \"not rust\")\n        .publish();\n    // Publish with lockfile containing bad version of `bar` (0.1.1)\n    Package::new(\"foo\", \"0.1.0\")\n        .dep(\"bar\", \"0.1\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"src/main.rs\",\n            \"extern crate foo; extern crate bar; fn main() {}\",\n        )\n        .file(\n            \"Cargo.lock\",\n            r#\"\n[[package]]\nname = \"bar\"\nversion = \"0.1.1\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.1.0\"\ndependencies = [\n \"bar 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n\"#,\n        )\n        .publish();\n\n    let p = project().at(\"install\").build();\n\n    p.cargo(\"install foo --locked\")\n        .with_stderr_data(str![[r#\"\n...\n[..]not rust[..]\n...\n\"#]])\n        .with_status(101)\n        .run();\n\n    // Create lockfile with the good `bar` version (0.1.0) and use it for install\n    project()\n        .file(\n            \"Cargo.lock\",\n            r#\"\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.1.0\"\ndependencies = [\n \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n\"#,\n        )\n        .build();\n    p.cargo(\"install foo --locked -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(\"resolver.lockfile-path='../foo/Cargo.lock'\")\n        .run();\n\n    assert!(paths::root().join(\"foo/Cargo.lock\").is_file());\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn config_install_lock_file_path_must_present() {\n    // `cargo install` will imply --locked when lockfile path is provided\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"foo\", \"0.1.0\")\n        .dep(\"bar\", \"0.1\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"src/main.rs\",\n            \"extern crate foo; extern crate bar; fn main() {}\",\n        )\n        .publish();\n\n    let p = project().at(\"install\").build();\n\n    p.cargo(\"install foo --locked -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(\"resolver.lockfile-path='../lockfile_dir/Cargo.lock'\")\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] no Cargo.lock file found in the requested path [ROOT]/install/../lockfile_dir/Cargo.lock\n...\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn config_run_embed() {\n    let lockfile_path = \"mylockfile/Cargo.lock\";\n    let invalid_lockfile = \"Cargo.lock\";\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"Cargo.lock\", \"This is an invalid lock file!\")\n        .build();\n\n    p.cargo(\"run -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"-Zscript\")\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{lockfile_path}'\"))\n        .arg(\"--manifest-path\")\n        .arg(\"src/main.rs\")\n        .run();\n\n    assert!(p.root().join(lockfile_path).is_file());\n\n    p.cargo(\"run -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"-Zunstable-options\")\n        .arg(\"-Zscript\")\n        .arg(\"--config\")\n        .arg(&format!(\"resolver.lockfile-path='{invalid_lockfile}'\"))\n        .arg(\"--manifest-path\")\n        .arg(\"src/main.rs\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn config_lockfile_path_rejects_templates() {\n    let p = make_project().build();\n\n    p.cargo(\"generate-lockfile -Zlockfile-path\")\n        .masquerade_as_nightly_cargo(&[\"lockfile-path\"])\n        .arg(\"--config\")\n        .arg(\"resolver.lockfile-path='{var}/Cargo.lock'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected variable `var` in resolver.lockfile-path `{var}/Cargo.lock`\n\n\"#]])\n        .run();\n}\n\nconst VALID_LOCKFILE: &str = r#\"# Test lockfile\nversion = 4\n\n[[package]]\nname = \"test_foo\"\nversion = \"0.5.0\"\n\"#;\n\nconst LIB_TOML: &str = r#\"\n        [package]\n        name = \"test_bar\"\n        version = \"0.1.0\"\n        edition = \"2021\"\n    \"#;\n\nfn make_project() -> ProjectBuilder {\n    project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"test_foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n}\n"
  },
  {
    "path": "tests/testsuite/login.rs",
    "content": "//! Tests for the `cargo login` command.\n\nuse std::fs;\nuse std::path::PathBuf;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::{self, RegistryBuilder};\nuse cargo_test_support::str;\nuse cargo_test_support::t;\n\nconst TOKEN: &str = \"test-token\";\nconst TOKEN2: &str = \"test-token2\";\nconst ORIGINAL_TOKEN: &str = \"api-token\";\n\nfn credentials_toml() -> PathBuf {\n    paths::home().join(\".cargo/credentials.toml\")\n}\n\nfn setup_new_credentials() {\n    setup_new_credentials_at(credentials_toml());\n}\n\nfn setup_new_credentials_at(config: PathBuf) {\n    t!(fs::create_dir_all(config.parent().unwrap()));\n    t!(fs::write(\n        &config,\n        format!(r#\"token = \"{token}\"\"#, token = ORIGINAL_TOKEN)\n    ));\n}\n\n/// Asserts whether or not the token is set to the given value for the given registry.\npub fn check_token(expected_token: Option<&str>, registry: Option<&str>) {\n    let credentials = credentials_toml();\n    assert!(credentials.is_file());\n\n    let contents = fs::read_to_string(&credentials).unwrap();\n    let toml: toml::Table = contents.parse().unwrap();\n\n    let actual_token = match registry {\n        // A registry has been provided, so check that the token exists in a\n        // table for the registry.\n        Some(registry) => toml\n            .get(\"registries\")\n            .and_then(|registries_table| registries_table.get(registry))\n            .and_then(|registry_table| match registry_table.get(\"token\") {\n                Some(&toml::Value::String(ref token)) => Some(token.as_str().to_string()),\n                _ => None,\n            }),\n        // There is no registry provided, so check the global token instead.\n        None => toml\n            .get(\"registry\")\n            .and_then(|registry_table| registry_table.get(\"token\"))\n            .and_then(|v| match v {\n                toml::Value::String(token) => Some(token.as_str().to_string()),\n                _ => None,\n            }),\n    };\n\n    match (actual_token, expected_token) {\n        (None, None) => {}\n        (Some(actual), Some(expected)) => assert_eq!(actual, expected),\n        (None, Some(expected)) => {\n            panic!(\"expected `{registry:?}` to be `{expected}`, but was not set\")\n        }\n        (Some(actual), None) => {\n            panic!(\"expected `{registry:?}` to be unset, but was set to `{actual}`\")\n        }\n    }\n}\n\n#[cargo_test]\nfn registry_credentials() {\n    let _alternative = RegistryBuilder::new().alternative().build();\n    let _alternative2 = RegistryBuilder::new()\n        .alternative_named(\"alternative2\")\n        .build();\n\n    setup_new_credentials();\n\n    let reg = \"alternative\";\n\n    cargo_process(\"login --registry\")\n        .arg(reg)\n        .with_stdin(TOKEN)\n        .run();\n\n    // Ensure that we have not updated the default token\n    check_token(Some(ORIGINAL_TOKEN), None);\n\n    // Also ensure that we get the new token for the registry\n    check_token(Some(TOKEN), Some(reg));\n\n    let reg2 = \"alternative2\";\n    cargo_process(\"login --registry\")\n        .arg(reg2)\n        .with_stdin(TOKEN2)\n        .run();\n\n    // Ensure not overwriting 1st alternate registry token with\n    // 2nd alternate registry token (see rust-lang/cargo#7701).\n    check_token(Some(ORIGINAL_TOKEN), None);\n    check_token(Some(TOKEN), Some(reg));\n    check_token(Some(TOKEN2), Some(reg2));\n}\n\n#[cargo_test]\nfn empty_login_token() {\n    let registry = RegistryBuilder::new()\n        .no_configure_registry()\n        .no_configure_token()\n        .build();\n    setup_new_credentials();\n\n    cargo_process(\"login\")\n        .replace_crates_io(registry.index_url())\n        .with_stdin(\"\\t\\n\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\nplease paste the token found on [ROOTURL]/api/me below\n[ERROR] credential provider `cargo:token` failed action `login`\n\nCaused by:\n  please provide a non-empty token\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    cargo_process(\"login\")\n        .replace_crates_io(registry.index_url())\n        .with_stdin(\"\")\n        .with_stderr_data(str![[r#\"\nplease paste the token found on [ROOTURL]/api/me below\n[ERROR] credential provider `cargo:token` failed action `login`\n\nCaused by:\n  please provide a non-empty token\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    cargo_process(\"login\")\n        .replace_crates_io(registry.index_url())\n        .arg(\"\")\n        .with_stdin(\"\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `cargo login <token>` is deprecated in favor of reading `<token>` from stdin\n[ERROR] credential provider `cargo:token` failed action `login`\n\nCaused by:\n  please provide a non-empty token\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn invalid_login_token() {\n    let registry = RegistryBuilder::new()\n        .no_configure_registry()\n        .no_configure_token()\n        .build();\n    setup_new_credentials();\n\n    let check = |stdin: &str, stderr: &str, status: i32| {\n        cargo_process(\"login\")\n            .replace_crates_io(registry.index_url())\n            .with_stdin(stdin)\n            .with_stderr_data(stderr)\n            .with_status(status)\n            .run();\n    };\n\n    let invalid = |stdin: &str| {\n        check(\n            stdin,\n            \"[ERROR] credential provider `cargo:token` failed action `login`\n\nCaused by:\n  token contains invalid characters.\n  Only printable ISO-8859-1 characters are allowed as it is sent in a HTTPS header.\n\",\n            101,\n        )\n    };\n    let valid = |stdin: &str| {\n        check(\n            stdin,\n            \"\\\n[LOGIN] token for `crates-io` saved\n\",\n            0,\n        )\n    };\n\n    // Update config.json so that the rest of the tests don't need to care\n    // whether or not `Updating` is printed.\n    check(\n        \"test\",\n        \"\\\n[UPDATING] crates.io index\n[LOGIN] token for `crates-io` saved\n\",\n        0,\n    );\n\n    invalid(\"😄\");\n    invalid(\"\\u{0016}\");\n    invalid(\"\\u{0000}\");\n    invalid(\"你好\");\n    valid(\"foo\\tbar\");\n    valid(\"foo bar\");\n    valid(\n        r##\"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"##,\n    );\n}\n\n#[cargo_test]\nfn bad_asymmetric_token_args() {\n    let registry = RegistryBuilder::new()\n        .credential_provider(&[\"cargo:paseto\"])\n        .no_configure_token()\n        .build();\n\n    // These cases are kept brief as the implementation is covered by clap, so this is only smoke testing that we have clap configured correctly.\n    cargo_process(\"login -Zasymmetric-token -- --key-subject\")\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] credential provider `cargo:paseto --key-subject` failed action `login`\n\nCaused by:\n  [ERROR] a value is required for '--key-subject <SUBJECT>' but none was supplied\n\n  For more information, try '--help'.\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn login_with_no_cargo_dir() {\n    // Create a config in the root directory because `login` requires the\n    // index to be updated, and we don't want to hit crates.io.\n    let registry = registry::init();\n    fs::rename(paths::home().join(\".cargo\"), paths::root().join(\".cargo\")).unwrap();\n    paths::home().rm_rf();\n    cargo_process(\"login foo -v\")\n        .replace_crates_io(registry.index_url())\n        .run();\n    let credentials = fs::read_to_string(credentials_toml()).unwrap();\n    assert_eq!(credentials, \"[registry]\\ntoken = \\\"foo\\\"\\n\");\n}\n\n#[cargo_test]\nfn login_with_asymmetric_token_and_subject_on_stdin() {\n    let registry = RegistryBuilder::new()\n        .credential_provider(&[\"cargo:paseto\"])\n        .no_configure_token()\n        .build();\n    let credentials = credentials_toml();\n    cargo_process(\"login -v -Z asymmetric-token -- --key-subject=foo\")\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[CREDENTIAL] cargo:paseto --key-subject=foo login crates-io\nk3.public.AmDwjlyf8jAV3gm5Z7Kz9xAOcsKslt_Vwp5v-emjFzBHLCtcANzTaVEghTNEMj9PkQ\n\n\"#]])\n        .with_stdin(\"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\")\n        .run();\n    let credentials = fs::read_to_string(&credentials).unwrap();\n    assert!(credentials.starts_with(\"[registry]\\n\"));\n    assert!(credentials.contains(\"secret-key-subject = \\\"foo\\\"\\n\"));\n    assert!(credentials.contains(\"secret-key = \\\"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\\\"\\n\"));\n}\n\n#[cargo_test]\nfn login_with_differently_sized_token() {\n    // Verify that the configuration file gets properly truncated.\n    let registry = registry::init();\n    let credentials = credentials_toml();\n    fs::remove_file(&credentials).unwrap();\n    cargo_process(\"login lmaolmaolmao -v\")\n        .replace_crates_io(registry.index_url())\n        .run();\n    cargo_process(\"login lmao -v\")\n        .replace_crates_io(registry.index_url())\n        .run();\n    cargo_process(\"login lmaolmaolmao -v\")\n        .replace_crates_io(registry.index_url())\n        .run();\n    let credentials = fs::read_to_string(&credentials).unwrap();\n    assert_eq!(credentials, \"[registry]\\ntoken = \\\"lmaolmaolmao\\\"\\n\");\n}\n\n#[cargo_test]\nfn login_with_token_on_stdin() {\n    let registry = registry::init();\n    let credentials = credentials_toml();\n    fs::remove_file(&credentials).unwrap();\n    cargo_process(\"login lmao -v\")\n        .replace_crates_io(registry.index_url())\n        .run();\n    cargo_process(\"login\")\n        .replace_crates_io(registry.index_url())\n        .with_stdin(\"some token\")\n        .run();\n    let credentials = fs::read_to_string(&credentials).unwrap();\n    assert_eq!(credentials, \"[registry]\\ntoken = \\\"some token\\\"\\n\");\n}\n\n#[cargo_test]\nfn login_with_asymmetric_token_on_stdin() {\n    let _registry = RegistryBuilder::new()\n        .credential_provider(&[\"cargo:paseto\"])\n        .alternative()\n        .no_configure_token()\n        .build();\n    let credentials = credentials_toml();\n    cargo_process(\"login -v -Z asymmetric-token --registry alternative\")\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[CREDENTIAL] cargo:paseto login alternative\nk3.public.AmDwjlyf8jAV3gm5Z7Kz9xAOcsKslt_Vwp5v-emjFzBHLCtcANzTaVEghTNEMj9PkQ\n\n\"#]])\n        .with_stdin(\"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\")\n        .run();\n    let credentials = fs::read_to_string(&credentials).unwrap();\n    assert_eq!(\n        credentials,\n        \"[registries.alternative]\\nsecret-key = \\\"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\\\"\\n\"\n    );\n}\n\n#[cargo_test]\nfn login_with_generate_asymmetric_token() {\n    let _registry = RegistryBuilder::new()\n        .credential_provider(&[\"cargo:paseto\"])\n        .alternative()\n        .no_configure_token()\n        .build();\n    let credentials = credentials_toml();\n    cargo_process(\"login -Z asymmetric-token --registry alternative\")\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\nk3.public.[..]\n\n\"#]])\n        .run();\n    let credentials = fs::read_to_string(&credentials).unwrap();\n    assert!(credentials.contains(\"secret-key = \\\"k3.secret.\"));\n}\n\n#[cargo_test]\nfn default_registry_configured() {\n    // When registry.default is set, login should use that one when\n    // --registry is not used.\n    let _alternative = RegistryBuilder::new().alternative().build();\n    let cargo_home = paths::home().join(\".cargo\");\n    cargo_util::paths::append(\n        &cargo_home.join(\"config.toml\"),\n        br#\"\n            [registry]\n            default = \"alternative\"\n        \"#,\n    )\n    .unwrap();\n\n    cargo_process(\"login\")\n        .with_stdin(\"a-new-token\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOGIN] token for `alternative` saved\n\n\"#]])\n        .run();\n\n    check_token(None, None);\n    check_token(Some(\"a-new-token\"), Some(\"alternative\"));\n}\n"
  },
  {
    "path": "tests/testsuite/logout.rs",
    "content": "//! Tests for the `cargo logout` command.\n\nuse super::login::check_token;\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::TestRegistry;\nuse cargo_test_support::{registry, str};\n\nfn simple_logout_test(registry: &TestRegistry, reg: Option<&str>, flag: &str, note: &str) {\n    let msg = reg.unwrap_or(\"crates-io\");\n    check_token(Some(registry.token()), reg);\n    let mut cargo = cargo_process(&format!(\"logout {}\", flag));\n    if reg.is_none() {\n        cargo.replace_crates_io(registry.index_url());\n    }\n    cargo\n        .with_stderr_data(&format!(\n            \"\\\n[LOGOUT] token for `{msg}` has been removed from local storage\n[NOTE] This does not revoke the token on the registry server.\n    If you need to revoke the token, visit {note} and follow the instructions there.\n\"\n        ))\n        .run();\n    check_token(None, reg);\n\n    let mut cargo = cargo_process(&format!(\"logout {}\", flag));\n    if reg.is_none() {\n        cargo.replace_crates_io(registry.index_url());\n    }\n    cargo\n        .with_stderr_data(&format!(\n            \"\\\n[LOGOUT] not currently logged in to `{msg}`\n\"\n        ))\n        .run();\n    check_token(None, reg);\n}\n\n#[cargo_test]\nfn default_registry_unconfigured() {\n    let registry = registry::init();\n    simple_logout_test(&registry, None, \"\", \"<https://crates.io/me>\");\n}\n\n#[cargo_test]\nfn other_registry() {\n    let registry = registry::alt_init();\n    simple_logout_test(\n        &registry,\n        Some(\"alternative\"),\n        \"--registry alternative\",\n        \"the `alternative` website\",\n    );\n    // It should not touch crates.io.\n    check_token(Some(\"sekrit\"), None);\n}\n\n#[cargo_test]\nfn default_registry_configured() {\n    // When registry.default is set, logout should use that one when\n    // --registry is not used.\n    let cargo_home = paths::home().join(\".cargo\");\n    cargo_home.mkdir_p();\n    cargo_util::paths::write(\n        &cargo_home.join(\"config.toml\"),\n        r#\"\n            [registry]\n            default = \"dummy-registry\"\n\n            [registries.dummy-registry]\n            index = \"https://127.0.0.1/index\"\n        \"#,\n    )\n    .unwrap();\n    cargo_util::paths::write(\n        &cargo_home.join(\"credentials.toml\"),\n        r#\"\n        [registry]\n        token = \"crates-io-token\"\n\n        [registries.dummy-registry]\n        token = \"dummy-token\"\n        \"#,\n    )\n    .unwrap();\n    check_token(Some(\"dummy-token\"), Some(\"dummy-registry\"));\n    check_token(Some(\"crates-io-token\"), None);\n\n    cargo_process(\"logout\").with_stderr_data(str![[r#\"\n[LOGOUT] token for `dummy-registry` has been removed from local storage\n[NOTE] This does not revoke the token on the registry server.\n    If you need to revoke the token, visit the `dummy-registry` website and follow the instructions there.\n\n\"#]]).run();\n    check_token(None, Some(\"dummy-registry\"));\n    check_token(Some(\"crates-io-token\"), None);\n\n    cargo_process(\"logout\")\n        .with_stderr_data(str![[r#\"\n[LOGOUT] not currently logged in to `dummy-registry`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn logout_asymmetric() {\n    let _registry = registry::RegistryBuilder::new()\n        .token(cargo_test_support::registry::Token::rfc_key())\n        .build();\n\n    cargo_process(\"logout --registry crates-io -Zasymmetric-token\")\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .with_stderr_data(str![[r#\"\n[LOGOUT] secret-key for `crates-io` has been removed from local storage\n\n\"#]])\n        .run();\n\n    cargo_process(\"logout --registry crates-io -Zasymmetric-token\")\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .with_stderr_data(str![[r#\"\n[LOGOUT] not currently logged in to `crates-io`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/lto.rs",
    "content": "use crate::prelude::*;\nuse cargo::core::compiler::Lto;\nuse cargo_test_support::RawOutput;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{Project, basic_manifest, project, str};\n\n#[cargo_test]\nfn with_deps() {\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"*\"\n\n                [profile.release]\n                lto = true\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() {}\")\n        .build();\n    p.cargo(\"build -v --release\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[COMPILING] bar v0.0.1\n[RUNNING] `rustc --crate-name bar [..]-C linker-plugin-lto [..]`\n[COMPILING] test v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name test [..]-C lto [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn shared_deps() {\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"*\"\n\n                [build-dependencies]\n                bar = \"*\"\n\n                [profile.release]\n                lto = true\n            \"#,\n        )\n        .file(\"build.rs\", \"extern crate bar; fn main() {}\")\n        .file(\"src/main.rs\", \"extern crate bar; fn main() {}\")\n        .build();\n    p.cargo(\"build -v --release\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[COMPILING] bar v0.0.1\n[RUNNING] `rustc --crate-name bar [..]-C linker-plugin-lto [..]`\n[RUNNING] `rustc --crate-name bar [..]-C embed-bitcode=no [..]`\n[COMPILING] test v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..]`\n[RUNNING] `[ROOT]/foo/target/release/build/test-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name test [..]-C lto [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_dep_not_ltod() {\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [build-dependencies]\n                bar = \"*\"\n\n                [profile.release]\n                lto = true\n            \"#,\n        )\n        .file(\"build.rs\", \"extern crate bar; fn main() {}\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"build -v --release\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[COMPILING] bar v0.0.1\n[RUNNING] `rustc --crate-name bar [..]-C embed-bitcode=no [..]`\n[COMPILING] test v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..]`\n[RUNNING] `[ROOT]/foo/target/release/build/test-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name test [..]-C lto [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn complicated() {\n    Package::new(\"dep-shared\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .publish();\n    Package::new(\"dep-normal2\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .publish();\n    Package::new(\"dep-normal\", \"0.0.1\")\n        .dep(\"dep-shared\", \"*\")\n        .dep(\"dep-normal2\", \"*\")\n        .file(\n            \"src/lib.rs\",\n            \"\n                pub fn foo() {\n                    dep_shared::foo();\n                    dep_normal2::foo();\n                }\n            \",\n        )\n        .publish();\n    Package::new(\"dep-build2\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .publish();\n    Package::new(\"dep-build\", \"0.0.1\")\n        .dep(\"dep-shared\", \"*\")\n        .dep(\"dep-build2\", \"*\")\n        .file(\n            \"src/lib.rs\",\n            \"\n                pub fn foo() {\n                    dep_shared::foo();\n                    dep_build2::foo();\n                }\n            \",\n        )\n        .publish();\n    Package::new(\"dep-proc-macro2\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .publish();\n    Package::new(\"dep-proc-macro\", \"0.0.1\")\n        .proc_macro(true)\n        .dep(\"dep-shared\", \"*\")\n        .dep(\"dep-proc-macro2\", \"*\")\n        .file(\n            \"src/lib.rs\",\n            \"\n                extern crate proc_macro;\n                use proc_macro::TokenStream;\n\n                #[proc_macro_attribute]\n                pub fn foo(_: TokenStream, a: TokenStream) -> TokenStream {\n                    dep_shared::foo();\n                    dep_proc_macro2::foo();\n                    a\n                }\n            \",\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = ['cdylib', 'staticlib']\n\n                [dependencies]\n                dep-normal = \"*\"\n                dep-proc-macro = \"*\"\n\n                [build-dependencies]\n                dep-build = \"*\"\n\n                [profile.release]\n                lto = true\n\n                # force build deps to share an opt-level with the rest of the\n                # graph so they only get built once.\n                [profile.release.build-override]\n                opt-level = 3\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() { dep_build::foo() }\")\n        .file(\n            \"src/bin/foo-bin.rs\",\n            \"#[dep_proc_macro::foo] fn main() { dep_normal::foo() }\",\n        )\n        .file(\n            \"src/lib.rs\",\n            \"#[dep_proc_macro::foo] pub fn foo() { dep_normal::foo() }\",\n        )\n        .build();\n    p.cargo(\"build -v --release\")\n        // normal deps and their transitive dependencies do not need object\n        // code, so they should have linker-plugin-lto specified\n        .with_stderr_contains(\n            \"[..]`rustc[..]--crate-name dep_normal2 [..]-C linker-plugin-lto[..]`\",\n        )\n        .with_stderr_contains(\"[..]`rustc[..]--crate-name dep_normal [..]-C linker-plugin-lto[..]`\")\n        // build dependencies and their transitive deps don't need any bitcode,\n        // so embedding should be turned off\n        .with_stderr_contains(\"[..]`rustc[..]--crate-name dep_build2 [..]-C embed-bitcode=no[..]`\")\n        .with_stderr_contains(\"[..]`rustc[..]--crate-name dep_build [..]-C embed-bitcode=no[..]`\")\n        .with_stderr_contains(\n            \"[..]`rustc[..]--crate-name build_script_build [..]-C embed-bitcode=no[..]`\",\n        )\n        // proc macro deps are the same as build deps here\n        .with_stderr_contains(\n            \"[..]`rustc[..]--crate-name dep_proc_macro2 [..]-C embed-bitcode=no[..]`\",\n        )\n        .with_stderr_contains(\n            \"[..]`rustc[..]--crate-name dep_proc_macro [..]-C embed-bitcode=no[..]`\",\n        )\n        .with_stderr_contains(\n            \"[..]`rustc[..]--crate-name foo_bin [..]--crate-type bin[..]-C lto[..]`\",\n        )\n        .with_stderr_contains(\n            \"[..]`rustc[..]--crate-name test [..]--crate-type cdylib[..]-C lto[..]`\",\n        )\n        .with_stderr_contains(\"[..]`rustc[..]--crate-name dep_shared [..]`\")\n        .with_stderr_does_not_contain(\"[..]--crate-name dep_shared[..]-C lto[..]\")\n        .with_stderr_does_not_contain(\"[..]--crate-name dep_shared[..]-C linker-plugin-lto[..]\")\n        .with_stderr_does_not_contain(\"[..]--crate-name dep_shared[..]-C embed-bitcode[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn off_in_manifest_works() {\n    Package::new(\"bar\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"*\"\n\n                [profile.release]\n                lto = \"off\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"src/main.rs\",\n            \"fn main() {\n            test::foo();\n            bar::foo();\n        }\",\n        )\n        .build();\n    p.cargo(\"build -v --release\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[COMPILING] bar v0.0.1\n[RUNNING] `rustc --crate-name bar [..]--crate-type lib [..]-C lto=off [..]-C embed-bitcode=no [..]`\n[COMPILING] test v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name test [..]--crate-type lib [..]-C lto=off [..]-C embed-bitcode=no [..]`\n[RUNNING] `rustc --crate-name test --edition=2015 src/main.rs [..]--crate-type bin [..]-C lto=off [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn between_builds() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [profile.release]\n                lto = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\"src/main.rs\", \"fn main() { test::foo() }\")\n        .build();\n    p.cargo(\"build -v --release --lib\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] test v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]--crate-type lib [..]-C linker-plugin-lto [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build -v --release\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] test v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]--crate-type bin [..]-C lto [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_all() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [profile.release]\n                lto = true\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"tests/a.rs\", \"\")\n        .file(\"tests/b.rs\", \"\")\n        .build();\n    p.cargo(\"test --release -v\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name a [..]-C lto [..]`\n[RUNNING] `rustc --crate-name b [..]-C lto [..]`\n[RUNNING] `rustc --crate-name foo [..]-C lto [..]--test [..]`\n[RUNNING] `rustc --crate-name foo [..]--crate-type bin [..]-C lto [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n[RUNNING] `[ROOT]/foo/target/release/deps/a-[HASH][EXE]`\n[RUNNING] `[ROOT]/foo/target/release/deps/b-[HASH][EXE]`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn test_all_and_bench() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [profile.release]\n                lto = true\n                [profile.bench]\n                lto = true\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"tests/a.rs\", \"\")\n        .file(\"tests/b.rs\", \"\")\n        .build();\n    p.cargo(\"test --release -v\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name a [..]-C lto [..]`\n[RUNNING] `rustc --crate-name b [..]-C lto [..]`\n[RUNNING] `rustc --crate-name foo [..]-C lto [..]--test [..]`\n[RUNNING] `rustc --crate-name foo [..]--crate-type bin [..]-C lto [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n[RUNNING] `[ROOT]/foo/target/release/deps/a-[HASH][EXE]`\n[RUNNING] `[ROOT]/foo/target/release/deps/b-[HASH][EXE]`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n/// Basic setup:\n///\n/// foo v0.0.0\n/// ├── bar v0.0.0\n/// │   ├── registry v0.0.1\n/// │   └── registry-shared v0.0.1\n/// └── registry-shared v0.0.1\n///\n/// Where `bar` will have the given crate types.\nfn project_with_dep(crate_types: &str) -> Project {\n    Package::new(\"registry\", \"0.0.1\")\n        .file(\"src/lib.rs\", r#\"pub fn foo() { println!(\"registry\"); }\"#)\n        .publish();\n    Package::new(\"registry-shared\", \"0.0.1\")\n        .file(\"src/lib.rs\", r#\"pub fn foo() { println!(\"shared\"); }\"#)\n        .publish();\n\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [workspace]\n\n                [dependencies]\n                bar = { path = 'bar' }\n                registry-shared = \"*\"\n\n                [profile.release]\n                lto = true\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n                fn main() {\n                    bar::foo();\n                    registry_shared::foo();\n                }\n            \",\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"bar\"\n                    version = \"0.0.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    registry = \"*\"\n                    registry-shared = \"*\"\n\n                    [lib]\n                    crate-type = [{}]\n                \"#,\n                crate_types\n            ),\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                pub fn foo() {\n                    println!(\"bar\");\n                    registry::foo();\n                    registry_shared::foo();\n                }\n            \"#,\n        )\n        .file(\"tests/a.rs\", \"\")\n        .file(\"bar/tests/b.rs\", \"\")\n        .build()\n}\n\n/// Helper for checking which LTO behavior is used for a specific crate.\n///\n/// `krate_info` is extra compiler flags used to distinguish this if the same\n/// crate name is being built multiple times.\nfn verify_lto(output: &RawOutput, krate: &str, krate_info: &str, expected_lto: Lto) {\n    let stderr = std::str::from_utf8(&output.stderr).unwrap();\n    let mut matches = stderr.lines().filter(|line| {\n        line.contains(\"Running\")\n            && line.contains(&format!(\"--crate-name {} \", krate))\n            && line.contains(krate_info)\n    });\n    let line = matches.next().unwrap_or_else(|| {\n        panic!(\n            \"expected to find crate `{}` info: `{}`, not found in output:\\n{}\",\n            krate, krate_info, stderr\n        );\n    });\n    if let Some(line2) = matches.next() {\n        panic!(\n            \"found multiple lines matching crate `{}` info: `{}`:\\nline1:{}\\nline2:{}\\noutput:\\n{}\",\n            krate, krate_info, line, line2, stderr\n        );\n    }\n    let actual_lto = if let Some((_, line)) = line.split_once(\"-C lto=\") {\n        let mode = line.splitn(2, ' ').next().unwrap();\n        if mode == \"off\" {\n            Lto::Off\n        } else {\n            Lto::Run(Some(mode.into()))\n        }\n    } else if line.contains(\"-C lto\") {\n        Lto::Run(None)\n    } else if line.contains(\"-C linker-plugin-lto\") {\n        Lto::OnlyBitcode\n    } else if line.contains(\"-C embed-bitcode=no\") {\n        Lto::OnlyObject\n    } else {\n        Lto::ObjectAndBitcode\n    };\n    assert_eq!(\n        actual_lto, expected_lto,\n        \"did not find expected LTO in line: {}\",\n        line\n    );\n}\n\n#[cargo_test]\nfn cdylib_and_rlib() {\n    let p = project_with_dep(\"'cdylib', 'rlib'\");\n    let output = p.cargo(\"build --release -v\").run();\n    // `registry` is ObjectAndBitcode because it needs Object for the\n    // rlib, and Bitcode for the cdylib (which doesn't support LTO).\n    verify_lto(\n        &output,\n        \"registry\",\n        \"--crate-type lib\",\n        Lto::ObjectAndBitcode,\n    );\n    // Same as `registry`\n    verify_lto(\n        &output,\n        \"registry_shared\",\n        \"--crate-type lib\",\n        Lto::ObjectAndBitcode,\n    );\n    // Same as `registry`\n    verify_lto(\n        &output,\n        \"bar\",\n        \"--crate-type cdylib --crate-type rlib\",\n        Lto::ObjectAndBitcode,\n    );\n    verify_lto(&output, \"foo\", \"--crate-type bin\", Lto::Run(None));\n    p.cargo(\"test --release -v\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] registry v0.0.1\n[FRESH] registry-shared v0.0.1\n[FRESH] bar v0.0.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]-C lto [..]--test [..]`\n[RUNNING] `rustc --crate-name a [..]-C lto [..]--test [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n[RUNNING] `[ROOT]/foo/target/release/deps/a-[HASH][EXE]`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    p.cargo(\"build --release -v --manifest-path bar/Cargo.toml\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] registry-shared v0.0.1\n[FRESH] registry v0.0.1\n[FRESH] bar v0.0.0 ([ROOT]/foo/bar)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    p.cargo(\"test --release -v --manifest-path bar/Cargo.toml\")\n        .with_stderr_data(str![[r#\"\n[FRESH] registry-shared v0.0.1\n[FRESH] registry v0.0.1\n[COMPILING] bar v0.0.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..]-C lto [..]--test [..]`\n[RUNNING] `rustc --crate-name b [..]-C lto [..]--test [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/deps/bar-[HASH][EXE]`\n[RUNNING] `[ROOT]/foo/target/release/deps/b-[HASH][EXE]`\n[DOCTEST] bar\n[RUNNING] `rustdoc --edition=2015 --crate-type cdylib --crate-type rlib --color auto --crate-name bar --test [..]-C lto [..]\n\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn dylib() {\n    let p = project_with_dep(\"'dylib'\");\n    let output = p.cargo(\"build --release -v\").run();\n    // `registry` is OnlyObject because rustc doesn't support LTO with dylibs.\n    verify_lto(&output, \"registry\", \"--crate-type lib\", Lto::OnlyObject);\n    // `registry_shared` is both because it is needed by both bar (Object) and\n    // foo (Bitcode for LTO).\n    verify_lto(\n        &output,\n        \"registry_shared\",\n        \"--crate-type lib\",\n        Lto::ObjectAndBitcode,\n    );\n    // `bar` is OnlyObject because rustc doesn't support LTO with dylibs.\n    verify_lto(&output, \"bar\", \"--crate-type dylib\", Lto::OnlyObject);\n    // `foo` is LTO because it is a binary, and the profile specifies `lto=true`.\n    verify_lto(&output, \"foo\", \"--crate-type bin\", Lto::Run(None));\n    // `cargo test` should not rebuild dependencies. It builds the test\n    // executables with `lto=true` because the tests are built with the\n    // `--release` flag.\n    p.cargo(\"test --release -v\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] registry v0.0.1\n[FRESH] registry-shared v0.0.1\n[FRESH] bar v0.0.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]-C lto [..]--test [..]`\n[RUNNING] `rustc --crate-name a [..]-C lto [..]--test [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n[RUNNING] `[ROOT]/foo/target/release/deps/a-[HASH][EXE]`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    // Building just `bar` causes `registry-shared` to get rebuilt because it\n    // switches to OnlyObject because it is now only being used with a dylib\n    // which does not support LTO.\n    //\n    // `bar` gets rebuilt because `registry_shared` got rebuilt.\n    p.cargo(\"build --release -v --manifest-path bar/Cargo.toml\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] registry-shared v0.0.1\n[FRESH] registry v0.0.1\n[RUNNING] `rustc --crate-name registry_shared [..]-C embed-bitcode=no [..]`\n[DIRTY] bar v0.0.0 ([ROOT]/foo/bar): info of dependency `registry-shared` changed\n[COMPILING] bar v0.0.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..]--crate-type dylib [..]-C embed-bitcode=no [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    // Testing just `bar` causes `registry` to get rebuilt because it switches\n    // to needing both Object (for the `bar` dylib) and Bitcode (for the test\n    // built with LTO).\n    //\n    // `bar` the dylib gets rebuilt because `registry` got rebuilt.\n    p.cargo(\"test --release -v --manifest-path bar/Cargo.toml\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] registry-shared v0.0.1\n[COMPILING] registry v0.0.1\n[RUNNING] `rustc --crate-name registry [..]`\n[DIRTY] bar v0.0.0 ([ROOT]/foo/bar): info of dependency `registry` changed\n[COMPILING] bar v0.0.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..]--crate-type dylib [..]-C embed-bitcode=no [..]`\n[RUNNING] `rustc --crate-name bar [..]-C lto [..]--test [..]`\n[RUNNING] `rustc --crate-name b [..]-C lto [..]--test [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/deps/bar-[HASH][EXE]`\n[RUNNING] `[ROOT]/foo/target/release/deps/b-[HASH][EXE]`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\n// This is currently broken on windows-gnu, see https://github.com/rust-lang/rust/issues/109797\n#[cfg_attr(\n    all(target_os = \"windows\", target_env = \"gnu\"),\n    ignore = \"windows-gnu not working\"\n)]\nfn test_profile() {\n    Package::new(\"bar\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"pub fn foo() -> i32 { 123 } \")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [profile.test]\n                lto = 'thin'\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[test]\n                fn t1() {\n                    assert_eq!(123, bar::foo());\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test -v\")\n        // unordered because the two `foo` builds start in parallel\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[COMPILING] bar v0.0.1\n[RUNNING] `rustc --crate-name bar [..]--crate-type lib [..]`\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C linker-plugin-lto [..]`\n[RUNNING] `rustc --crate-name foo [..]--emit=dep-info,link -C lto=thin [..]--test [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `rustdoc [..]\n\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn doctest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [profile.release]\n                lto = true\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// Foo!\n                ///\n                /// ```\n                /// foo::foo();\n                /// ```\n                pub fn foo() { bar::bar(); }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                pub fn bar() { println!(\"hi!\"); }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test --doc --release -v\")\n        // embed-bitcode should be harmless here\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..]--crate-type lib [..]-C linker-plugin-lto [..]`\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]--crate-type lib [..]-C linker-plugin-lto [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[DOCTEST] foo\n[RUNNING] `rustdoc [..]`\n\n\"#]])\n        .run();\n\n    // Try with bench profile.\n    p.cargo(\"test --doc --release -v\")\n        .env(\"CARGO_PROFILE_BENCH_LTO\", \"true\")\n        .with_stderr_data(\n            str![[r#\"\n[DOCTEST] foo\n[RUNNING] `rustdoc [..]-C lto [..]`\n[FRESH] bar v0.1.0 ([ROOT]/foo/bar)\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn dylib_rlib_bin() {\n    // dylib+rlib linked with a binary\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"dylib\", \"rlib\"]\n\n                [profile.release]\n                lto = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() { println!(\\\"hi!\\\"); }\")\n        .file(\"src/bin/ferret.rs\", \"fn main() { foo::foo(); }\")\n        .build();\n\n    let output = p.cargo(\"build --release -v\").run();\n    verify_lto(\n        &output,\n        \"foo\",\n        \"--crate-type dylib --crate-type rlib\",\n        Lto::ObjectAndBitcode,\n    );\n    verify_lto(&output, \"ferret\", \"--crate-type bin\", Lto::Run(None));\n}\n\n#[cargo_test]\nfn fresh_swapping_commands() {\n    // In some rare cases, different commands end up building dependencies\n    // with different LTO settings. This checks that it doesn't cause the\n    // cache to thrash in that scenario.\n    Package::new(\"bar\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n\n                [profile.release]\n                lto = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() { println!(\\\"hi!\\\"); }\")\n        .build();\n\n    p.cargo(\"build --release -v\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[COMPILING] bar v1.0.0\n[RUNNING] `rustc --crate-name bar [..]-C linker-plugin-lto [..]`\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]-C linker-plugin-lto [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"test --release -v\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] bar v1.0.0\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]-C lto [..]--test [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `rustdoc [..]-C lto [..]`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"build --release -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] bar v1.0.0\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"test --release -v --no-run -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] bar v1.0.0\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/main.rs",
    "content": "#![allow(clippy::disallowed_methods)]\n#![allow(clippy::print_stderr)]\n#![allow(clippy::print_stdout)]\n\nmod advanced_env;\nmod alt_registry;\nmod artifact_dep;\nmod artifact_dir;\nmod bad_config;\nmod bad_manifest_path;\nmod bench;\nmod binary_name;\nmod build;\nmod build_analysis;\nmod build_dir;\nmod build_dir_legacy;\nmod build_script;\nmod build_script_env;\nmod build_script_extra_link_arg;\nmod build_scripts_multiple;\nmod cache_lock;\nmod cache_messages;\nmod cargo;\nmod cargo_add;\nmod cargo_alias_config;\nmod cargo_bench;\nmod cargo_build;\nmod cargo_check;\nmod cargo_clean;\nmod cargo_command;\nmod cargo_config;\nmod cargo_doc;\nmod cargo_env_config;\nmod cargo_features;\nmod cargo_fetch;\nmod cargo_fix;\nmod cargo_generate_lockfile;\nmod cargo_git_checkout;\nmod cargo_help;\nmod cargo_info;\nmod cargo_init;\nmod cargo_install;\nmod cargo_locate_project;\nmod cargo_login;\nmod cargo_logout;\nmod cargo_metadata;\nmod cargo_new;\nmod cargo_owner;\nmod cargo_package;\nmod cargo_pkgid;\nmod cargo_publish;\nmod cargo_read_manifest;\nmod cargo_remove;\nmod cargo_report;\nmod cargo_report_future_incompat;\nmod cargo_report_rebuilds;\nmod cargo_report_sessions;\nmod cargo_report_timings;\nmod cargo_run;\nmod cargo_rustc;\nmod cargo_rustdoc;\nmod cargo_search;\nmod cargo_targets;\nmod cargo_test;\nmod cargo_tree;\nmod cargo_uninstall;\nmod cargo_update;\nmod cargo_vendor;\nmod cargo_verify_project;\nmod cargo_version;\nmod cargo_yank;\nmod cfg;\nmod check;\nmod check_cfg;\nmod clean;\nmod clean_new_layout;\nmod collisions;\nmod compile_time_deps;\nmod concurrent;\nmod config;\nmod config_cli;\nmod config_include;\nmod corrupt_git;\nmod credential_process;\nmod cross_compile;\nmod cross_publish;\nmod custom_target;\nmod death;\nmod dep_info;\nmod diagnostics;\nmod direct_minimal_versions;\nmod directory;\nmod doc;\nmod docscrape;\nmod edition;\nmod error;\nmod feature_unification;\nmod features;\nmod features2;\nmod features_namespaced;\nmod fetch;\nmod fix;\nmod fix_n_times;\nmod freshness;\nmod freshness_checksum;\nmod future_incompat_report;\nmod generate_lockfile;\nmod git;\nmod git_auth;\nmod git_gc;\nmod git_shallow;\nmod glob_targets;\nmod global_cache_tracker;\nmod help;\nmod hints;\nmod https;\nmod inheritable_workspace_fields;\nmod install;\nmod install_upgrade;\nmod jobserver;\nmod lints;\nmod lints_table;\nmod list_availables;\nmod local_registry;\nmod locate_project;\nmod lockfile_compat;\nmod lockfile_path;\nmod login;\nmod logout;\nmod lto;\nmod member_discovery;\nmod member_errors;\nmod message_format;\nmod messages;\nmod metabuild;\nmod metadata;\nmod minimal_versions;\nmod multitarget;\nmod net_config;\nmod new;\nmod offline;\nmod old_cargos;\nmod open_namespaces;\nmod owner;\nmod package;\nmod package_features;\nmod package_message_format;\nmod patch;\nmod path;\nmod paths;\nmod pgo;\nmod pkgid;\nmod precise_pre_release;\nmod proc_macro;\nmod profile_config;\nmod profile_custom;\nmod profile_overrides;\nmod profile_panic_immediate_abort;\nmod profile_targets;\nmod profile_trim_paths;\nmod profiles;\nmod progress;\nmod pub_priv;\nmod publish;\nmod publish_lockfile;\nmod read_manifest;\nmod registry;\nmod registry_auth;\nmod registry_overlay;\nmod rename_deps;\nmod replace;\nmod required_features;\nmod run;\nmod rust_version;\nmod rustc;\nmod rustc_info_cache;\nmod rustdoc;\nmod rustdoc_extern_html;\nmod rustdocflags;\nmod rustflags;\nmod rustup;\nmod sbom;\nmod script;\nmod search;\nmod shell_quoting;\nmod source_replacement;\nmod ssh;\nmod standard_lib;\nmod test;\nmod timings;\nmod tool_paths;\nmod unit_graph;\nmod update;\nmod utils;\nmod vendor;\nmod verify_project;\nmod version;\nmod warn_on_failure;\nmod warning_override;\nmod weak_dep_features;\nmod workspaces;\nmod yank;\n\nuse crate::prelude::*;\n\npub mod prelude {\n    pub use crate::utils::ext::CargoCommandExt;\n    pub use crate::utils::ext::CargoProjectExt;\n    pub use cargo_test_support::prelude::*;\n}\n\n#[cargo_test]\nfn aaa_trigger_cross_compile_disabled_check() {\n    // This triggers the cross compile disabled check to run ASAP, see #5141\n    crate::utils::cross_compile::disabled();\n}\n\n// This is placed here as running tests in `cargo-test-support` would rebuild it\n#[cargo_test]\n#[cfg(not(windows))]\nfn check_test_dir() {\n    let tests = vec![\n        (\n            \"tests/testsuite/workspaces.rs\",\n            \"workspace_in_git\",\n            \"testsuite/workspaces/workspace_in_git\",\n        ),\n        (\n            \"tests/testsuite/cargo_remove/invalid_arg/mod.rs\",\n            \"case\",\n            \"testsuite/cargo_remove/invalid_arg/case\",\n        ),\n        (\n            \"tests/build-std/main.rs\",\n            \"cross_custom\",\n            \"build-std/main/cross_custom\",\n        ),\n        (\n            \"src/tools/cargo/tests/testsuite/build.rs\",\n            \"cargo_compile_simple\",\n            \"src/tools/cargo/testsuite/build/cargo_compile_simple\",\n        ),\n        (\n            \"src/tools/cargo/tests/testsuite/cargo_add/add_basic/mod.rs\",\n            \"case\",\n            \"src/tools/cargo/testsuite/cargo_add/add_basic/case\",\n        ),\n        (\n            \"src/tools/cargo/tests/build-std/main.rs\",\n            \"cross_custom\",\n            \"src/tools/cargo/build-std/main/cross_custom\",\n        ),\n        (\n            \"workspace/more/src/tools/cargo/tests/testsuite/build.rs\",\n            \"cargo_compile_simple\",\n            \"src/tools/cargo/testsuite/build/cargo_compile_simple\",\n        ),\n    ];\n    for (path, name, expected) in tests {\n        assert_eq!(\n            cargo_test_support::paths::test_dir(path, name),\n            std::path::PathBuf::from(expected)\n        );\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/member_discovery.rs",
    "content": "//! Tests for workspace member discovery.\n\nuse crate::prelude::*;\nuse cargo::core::{Shell, Workspace};\nuse cargo::util::context::GlobalContext;\nuse cargo_test_support::paths;\nuse cargo_test_support::project;\nuse cargo_test_support::registry;\n\n/// Tests exclusion of non-directory files from workspace member discovery using glob `*`.\n#[cargo_test]\nfn bad_file_member_exclusion() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [ \"crates/*\" ]\n            \"#,\n        )\n        .file(\"crates/.DS_Store\", \"PLACEHOLDER\")\n        .file(\n            \"crates/bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                authors = []\n            \"#,\n        )\n        .file(\"crates/bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // Prevent this test from accessing the network by setting up .cargo/config.\n    registry::init();\n    let gctx = GlobalContext::new(\n        Shell::from_write(Box::new(Vec::new())),\n        paths::cargo_home(),\n        paths::cargo_home(),\n    );\n    let ws = Workspace::new(&p.root().join(\"Cargo.toml\"), &gctx).unwrap();\n    assert_eq!(ws.members().count(), 1);\n    assert_eq!(ws.members().next().unwrap().name(), \"bar\");\n}\n"
  },
  {
    "path": "tests/testsuite/member_errors.rs",
    "content": "//! Tests for workspace member errors.\n\nuse crate::prelude::*;\nuse cargo::core::Shell;\nuse cargo::core::Workspace;\nuse cargo::core::compiler::UserIntent;\nuse cargo::core::resolver::ResolveError;\nuse cargo::ops::{self, CompileOptions};\nuse cargo::util::{context::GlobalContext, errors::ManifestError};\nuse cargo_test_support::paths;\nuse cargo_test_support::project;\nuse cargo_test_support::registry;\nuse cargo_test_support::str;\n\n/// Tests inclusion of a `ManifestError` pointing to a member manifest\n/// when that manifest fails to deserialize.\n#[cargo_test]\nfn toml_deserialize_manifest_error() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                foobar == \"0.55\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] extra `=`, expected nothing\n --> bar/Cargo.toml:8:25\n  |\n8 |                 foobar == \"0.55\"\n  |                         ^\n[ERROR] failed to load manifest for dependency `bar`\n\n\"#]])\n        .run();\n}\n\n/// Tests inclusion of a `ManifestError` pointing to a member manifest\n/// when that manifest has an invalid dependency path.\n#[cargo_test]\nfn member_manifest_path_io_error() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                foobar = { path = \"nosuch\" }\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    let root_manifest_path = p.root().join(\"Cargo.toml\");\n    let member_manifest_path = p.root().join(\"bar\").join(\"Cargo.toml\");\n    let missing_manifest_path = p.root().join(\"bar\").join(\"nosuch\").join(\"Cargo.toml\");\n\n    let error =\n        Workspace::new(&root_manifest_path, &GlobalContext::default().unwrap()).unwrap_err();\n    eprintln!(\"{:?}\", error);\n\n    let manifest_err: &ManifestError = error.downcast_ref().expect(\"Not a ManifestError\");\n    assert_eq!(manifest_err.manifest_path(), &root_manifest_path);\n\n    let causes: Vec<_> = manifest_err.manifest_causes().collect();\n    assert_eq!(causes.len(), 2, \"{:?}\", causes);\n    assert_eq!(causes[0].manifest_path(), &member_manifest_path);\n    assert_eq!(causes[1].manifest_path(), &missing_manifest_path);\n}\n\n/// Tests dependency version errors provide which package failed via a `ResolveError`.\n#[cargo_test]\nfn member_manifest_version_error() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                i-dont-exist = \"0.55\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // Prevent this test from accessing the network by setting up .cargo/config.\n    registry::init();\n    let gctx = GlobalContext::new(\n        Shell::from_write(Box::new(Vec::new())),\n        paths::cargo_home(),\n        paths::cargo_home(),\n    );\n    let ws = Workspace::new(&p.root().join(\"Cargo.toml\"), &gctx).unwrap();\n    let compile_options = CompileOptions::new(&gctx, UserIntent::Build).unwrap();\n    let member_bar = ws.members().find(|m| &*m.name() == \"bar\").unwrap();\n\n    let error = ops::compile(&ws, &compile_options).map(|_| ()).unwrap_err();\n    eprintln!(\"{:?}\", error);\n\n    let resolve_err: &ResolveError = error.downcast_ref().expect(\"Not a ResolveError\");\n    let package_path = resolve_err.package_path();\n    assert_eq!(package_path.len(), 1, \"package_path: {:?}\", package_path);\n    assert_eq!(package_path[0], member_bar.package_id());\n}\n"
  },
  {
    "path": "tests/testsuite/message_format.rs",
    "content": "//! Tests for --message-format flag.\n\nuse crate::prelude::*;\nuse cargo_test_support::{basic_lib_manifest, basic_manifest, project, str};\n\n#[cargo_test]\nfn cannot_specify_two() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    let formats = [\"human\", \"json\", \"short\"];\n\n    for a in formats.iter() {\n        for b in formats.iter() {\n            p.cargo(&format!(\"build --message-format {},{}\", a, b))\n                .with_status(101)\n                .with_stderr_data(str![[r#\"\n[ERROR] cannot specify two kinds of `message-format` arguments\n\n\"#]])\n                .run();\n        }\n    }\n}\n\n#[cargo_test]\nfn double_json_works() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check --message-format json,json-render-diagnostics\")\n        .run();\n    p.cargo(\"check --message-format json,json-diagnostic-short\")\n        .run();\n    p.cargo(\"check --message-format json,json-diagnostic-rendered-ansi\")\n        .run();\n    p.cargo(\"check --message-format json --message-format json-diagnostic-rendered-ansi\")\n        .run();\n    p.cargo(\"check --message-format json-diagnostic-rendered-ansi\")\n        .run();\n    p.cargo(\"check --message-format json-diagnostic-short,json-diagnostic-rendered-ansi\")\n        .run();\n}\n\n#[cargo_test]\nfn cargo_renders() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n\n                [dependencies]\n                bar = { path = 'bar' }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --message-format json-render-diagnostics\")\n        .with_status(101)\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"reason\": \"compiler-artifact\",\n    \"...\": \"{...}\"\n  },\n  {\n    \"reason\": \"build-finished\",\n    \"success\": false\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .with_stderr_contains(\n            \"\\\n[CHECKING] bar [..]\n[CHECKING] foo [..]\nerror[..]`main`[..]\n\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_renders_short() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --message-format json-render-diagnostics,json-diagnostic-short\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\nerror[E0601]: `main` function not found in crate `foo`\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_renders_ansi() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --message-format json-diagnostic-rendered-ansi\")\n        .with_status(101)\n        // Because 1b is the start of an ANSI escape sequence, checking for it\n        // allows us to verify that ANSI colors are being emitted without\n        // looking for specific color codes, that may change over time.\n        .with_stdout_contains(\"[..]\\\\u001b[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn cargo_renders_doctests() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\n            \"src/lib.rs\",\n            \"\\\n            /// ```rust\n            /// bar()\n            /// ```\n            pub fn bar() {}\n            \",\n        )\n        .build();\n\n    p.cargo(\"test --doc --message-format short\")\n        .with_status(101)\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest src/lib.rs - bar (line 1) ... FAILED\n\nfailures:\n\n---- src/lib.rs - bar (line 1) stdout ----\nsrc/lib.rs:2:1: error[E0425]: cannot find function `bar`[..]\n[ERROR] aborting due to 1 previous error\nCouldn't compile the test.\n\nfailures:\n    src/lib.rs - bar (line 1)\n\ntest result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zrustc-unicode is unstable\")]\nfn cargo_passes_unicode_output() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\\\nmod tests {\n    #[test]\n    fn t1() {\n        use std::io;\n    }\n}\n            \",\n        )\n        .build();\n\n    foo.cargo(\"check -v -Zrustc-unicode\")\n        .masquerade_as_nightly_cargo(&[\"rustc-unicode\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] --json=diagnostic-rendered-ansi,artifacts,future-incompat,diagnostic-unicode [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/messages.rs",
    "content": "//! General tests specifically about diagnostics and other messages.\n//!\n//! Tests for message caching can be found in `cache_messages`.\n\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::{Project, process, project};\nuse cargo_util::ProcessError;\n\n/// Captures the actual diagnostics displayed by rustc. This is done to avoid\n/// relying on the exact message formatting in rustc.\npub fn raw_rustc_output(project: &Project, path: &str, extra: &[&str]) -> String {\n    let mut proc = process(\"rustc\");\n    if cfg!(windows) {\n        // Sanitize in case the caller wants to do direct string comparison with Cargo's output.\n        proc.arg(path.replace('/', \"\\\\\"));\n    } else {\n        proc.arg(path);\n    }\n    let rustc_output = match proc\n        .arg(\"--crate-type=lib\")\n        .args(extra)\n        .cwd(project.root())\n        .exec_with_output()\n    {\n        Ok(output) => output.stderr,\n        Err(e) => e.downcast::<ProcessError>().unwrap().stderr.unwrap(),\n    };\n    // Do a little dance to remove rustc's \"warnings emitted\" message and the subsequent newline.\n    let stderr = std::str::from_utf8(&rustc_output).expect(\"utf8\");\n    let mut lines = stderr.lines();\n    let mut result = String::new();\n    while let Some(line) = lines.next() {\n        if line.contains(\"warning emitted\")\n            || line.contains(\"warnings emitted\")\n            || line.contains(\"aborting due to\")\n        {\n            // Eat blank line.\n            match lines.next() {\n                None | Some(\"\") => continue,\n                Some(s) => panic!(\"unexpected str {}\", s),\n            }\n        }\n        result.push_str(line);\n        result.push('\\n');\n    }\n    result\n}\n\nfn redact_rustc_message(msg: &str) -> impl IntoData {\n    use snapbox::filter::{Filter, FilterPaths};\n    let assert = assert_e2e();\n    let redactions = assert.redactions();\n    let msg = redactions.redact(msg);\n    FilterPaths.filter(msg.into())\n}\n\n#[cargo_test]\nfn deduplicate_messages_basic() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() {\n                    let x = 1;\n                }\n            \"#,\n        )\n        .build();\n    let rustc_message = raw_rustc_output(&p, \"src/lib.rs\", &[]);\n    let expected_output = format!(\n        \"{}\\\n[WARNING] `foo` (lib) generated 1 warning[..]\n[WARNING] `foo` (lib test) generated 1 warning (1 duplicate)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\",\n        rustc_message\n    );\n    p.cargo(\"test --no-run -j1\")\n        .with_stderr_data(redact_rustc_message(&format!(\n            \"\\\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n{}\",\n            expected_output\n        )))\n        .run();\n    // Run again, to check for caching behavior.\n    p.cargo(\"test --no-run -j1\")\n        .with_stderr_data(redact_rustc_message(&expected_output))\n        .run();\n}\n\n#[cargo_test]\nfn deduplicate_messages_mismatched_warnings() {\n    // One execution prints 1 warning, the other prints 2 where there is an overlap.\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() {\n                    let x = 1;\n                }\n\n                #[test]\n                fn t1() {\n                    let MY_VALUE = 1;\n                    assert_eq!(MY_VALUE, 1);\n                }\n            \"#,\n        )\n        .build();\n    let lib_output = raw_rustc_output(&p, \"src/lib.rs\", &[]);\n    let mut lib_test_output = raw_rustc_output(&p, \"src/lib.rs\", &[\"--test\"]);\n    // Remove the duplicate warning.\n    let start = lib_test_output.find(&lib_output).expect(\"same warning\");\n    lib_test_output.replace_range(start..start + lib_output.len(), \"\");\n    let expected_output = format!(\n        \"\\\n{}\\\n[WARNING] `foo` (lib) generated 1 warning[..]\n{}\\\n[WARNING] `foo` (lib test) generated 2 warnings (1 duplicate)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\",\n        lib_output, lib_test_output\n    );\n    p.cargo(\"test --no-run -j1\")\n        .with_stderr_data(redact_rustc_message(&format!(\n            \"\\\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n{}\",\n            expected_output\n        )))\n        .run();\n    // Run again, to check for caching behavior.\n    p.cargo(\"test --no-run -j1\")\n        .with_stderr_data(redact_rustc_message(&expected_output))\n        .run();\n}\n\n#[cargo_test]\nfn deduplicate_errors() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                this should not compile\n            \"#,\n        )\n        .build();\n    let rustc_message = raw_rustc_output(&p, \"src/lib.rs\", &[]);\n    p.cargo(\"test -j1\")\n        .with_status(101)\n        .with_stderr_data(redact_rustc_message(&format!(\n            \"\\\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n{}[ERROR] could not compile `foo` (lib) due to 1 previous error\n\",\n            rustc_message\n        )))\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/metabuild.rs",
    "content": "//! Tests for the metabuild feature (declarative build scripts).\n\nuse std::str;\n\nuse crate::prelude::*;\nuse cargo_test_support::{\n    Project, basic_lib_manifest, basic_manifest, is_coarse_mtime, project, registry::Package,\n    rustc_host, str,\n};\n\n#[cargo_test]\nfn metabuild_gated() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                metabuild = [\"mb\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `metabuild` is required\n\n  The package requires the Cargo feature called `metabuild`, but that feature is not stabilized in this version of Cargo ([..]).\n  Consider adding `cargo-features = [\"metabuild\"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#metabuild for more information about the status of this feature.\n\n\"#]])\n        .run();\n}\n\nfn basic_project() -> Project {\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                metabuild = [\"mb\", \"mb-other\"]\n\n                [build-dependencies]\n                mb = {path=\"mb\"}\n                mb-other = {path=\"mb-other\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"mb/Cargo.toml\", &basic_lib_manifest(\"mb\"))\n        .file(\n            \"mb/src/lib.rs\",\n            r#\"pub fn metabuild() { println!(\"Hello mb\"); }\"#,\n        )\n        .file(\n            \"mb-other/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"mb-other\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\n            \"mb-other/src/lib.rs\",\n            r#\"pub fn metabuild() { println!(\"Hello mb-other\"); }\"#,\n        )\n        .build()\n}\n\n#[cargo_test]\nfn metabuild_basic() {\n    let p = basic_project();\n    p.cargo(\"check -vv\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_stdout_data(str![[r#\"\n[foo 0.0.1] Hello mb\n[foo 0.0.1] Hello mb-other\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn metabuild_error_both() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                metabuild = \"mb\"\n\n                [build-dependencies]\n                mb = {path=\"mb\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", r#\"fn main() {}\"#)\n        .file(\"mb/Cargo.toml\", &basic_lib_manifest(\"mb\"))\n        .file(\n            \"mb/src/lib.rs\",\n            r#\"pub fn metabuild() { println!(\"Hello mb\"); }\"#,\n        )\n        .build();\n\n    p.cargo(\"check -vv\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  cannot specify both `metabuild` and `build`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn metabuild_missing_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                metabuild = \"mb\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -vv\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  metabuild package `mb` must be specified in `build-dependencies`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn metabuild_optional_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                metabuild = \"mb\"\n\n                [build-dependencies]\n                mb = {path=\"mb\", optional=true}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"mb/Cargo.toml\", &basic_lib_manifest(\"mb\"))\n        .file(\n            \"mb/src/lib.rs\",\n            r#\"pub fn metabuild() { println!(\"Hello mb\"); }\"#,\n        )\n        .build();\n\n    p.cargo(\"check -vv\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_stdout_does_not_contain(\"[foo 0.0.1] Hello mb\")\n        .run();\n\n    p.cargo(\"check -vv --features mb\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_stdout_contains(\"[foo 0.0.1] Hello mb\")\n        .run();\n}\n\n#[cargo_test]\nfn metabuild_lib_name() {\n    // Test when setting `name` on [lib].\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                metabuild = \"mb\"\n\n                [build-dependencies]\n                mb = {path=\"mb\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"mb/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"mb\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                [lib]\n                name = \"other\"\n            \"#,\n        )\n        .file(\n            \"mb/src/lib.rs\",\n            r#\"pub fn metabuild() { println!(\"Hello mb\"); }\"#,\n        )\n        .build();\n\n    p.cargo(\"check -vv\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_stdout_data(str![[r#\"\n[foo 0.0.1] Hello mb\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn metabuild_fresh() {\n    if is_coarse_mtime() {\n        // This test doesn't work on coarse mtimes very well. Because the\n        // metabuild script is created at build time, its mtime is almost\n        // always equal to the mtime of the output. The second call to `build`\n        // will then think it needs to be rebuilt when it should be fresh.\n        return;\n    }\n\n    // Check that rebuild is fresh.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                metabuild = \"mb\"\n\n                [build-dependencies]\n                mb = {path=\"mb\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"mb/Cargo.toml\", &basic_lib_manifest(\"mb\"))\n        .file(\n            \"mb/src/lib.rs\",\n            r#\"pub fn metabuild() { println!(\"Hello mb\"); }\"#,\n        )\n        .build();\n\n    p.cargo(\"check -vv\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_stdout_contains(\"[foo 0.0.1] Hello mb\")\n        .run();\n\n    p.cargo(\"check -vv\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_stdout_does_not_contain(\"[foo 0.0.1] Hello mb\")\n        .with_stderr_data(str![[r#\"\n[FRESH] mb v0.5.0 ([ROOT]/foo/mb)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn metabuild_links() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                links = \"cat\"\n                metabuild = \"mb\"\n\n                [build-dependencies]\n                mb = {path=\"mb\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"mb/Cargo.toml\", &basic_lib_manifest(\"mb\"))\n        .file(\n            \"mb/src/lib.rs\",\n            r#\"\n                pub fn metabuild() {\n                    assert_eq!(std::env::var(\"CARGO_MANIFEST_LINKS\"),\n                        Ok(\"cat\".to_string()));\n                    println!(\"Hello mb\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -vv\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_stdout_data(str![[r#\"\n[foo 0.0.1] Hello mb\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn metabuild_override() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                links = \"cat\"\n                metabuild = \"mb\"\n\n                [build-dependencies]\n                mb = {path=\"mb\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"mb/Cargo.toml\", &basic_lib_manifest(\"mb\"))\n        .file(\n            \"mb/src/lib.rs\",\n            r#\"pub fn metabuild() { panic!(\"should not run\"); }\"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}.cat]\n                    rustc-link-lib = [\"a\"]\n                \"#,\n                rustc_host()\n            ),\n        )\n        .build();\n\n    p.cargo(\"check -vv\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .run();\n}\n\n#[cargo_test]\nfn metabuild_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"member1\", \"member2\"]\n            \"#,\n        )\n        .file(\n            \"member1/Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"member1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                metabuild = [\"mb1\", \"mb2\"]\n\n                [build-dependencies]\n                mb1 = {path=\"../../mb1\"}\n                mb2 = {path=\"../../mb2\"}\n            \"#,\n        )\n        .file(\"member1/src/lib.rs\", \"\")\n        .file(\n            \"member2/Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"member2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                metabuild = [\"mb1\"]\n\n                [build-dependencies]\n                mb1 = {path=\"../../mb1\"}\n            \"#,\n        )\n        .file(\"member2/src/lib.rs\", \"\")\n        .build();\n\n    project()\n        .at(\"mb1\")\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"mb1\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"pub fn metabuild() { println!(\"Hello mb1 {}\", std::env::var(\"CARGO_MANIFEST_DIR\").unwrap()); }\"#,\n        )\n        .build();\n\n    project()\n        .at(\"mb2\")\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"mb2\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"pub fn metabuild() { println!(\"Hello mb2 {}\", std::env::var(\"CARGO_MANIFEST_DIR\").unwrap()); }\"#,\n        )\n        .build();\n\n    p.cargo(\"check -vv --workspace\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_stdout_contains(\"[member1 0.0.1] Hello mb1 [..]member1\")\n        .with_stdout_contains(\"[member1 0.0.1] Hello mb2 [..]member1\")\n        .with_stdout_contains(\"[member2 0.0.1] Hello mb1 [..]member2\")\n        .with_stdout_does_not_contain(\"[member2 0.0.1] Hello mb2 [..]member2\")\n        .run();\n}\n\n#[cargo_test]\nfn metabuild_metadata() {\n    // The metabuild Target is filtered out of the `metadata` results.\n    let p = basic_project();\n\n    let meta = p\n        .cargo(\"metadata --format-version=1\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .run_json();\n    let mb_info: Vec<&str> = meta[\"packages\"]\n        .as_array()\n        .unwrap()\n        .iter()\n        .find(|p| p[\"name\"].as_str().unwrap() == \"foo\")\n        .unwrap()[\"metabuild\"]\n        .as_array()\n        .unwrap()\n        .iter()\n        .map(|s| s.as_str().unwrap())\n        .collect();\n    assert_eq!(mb_info, [\"mb\", \"mb-other\"]);\n}\n\n#[cargo_test]\nfn metabuild_two_versions() {\n    // Two versions of a metabuild dep with the same name.\n    let p = project()\n        .at(\"ws\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"member1\", \"member2\"]\n            \"#,\n        )\n        .file(\n            \"member1/Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"member1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                metabuild = [\"mb\"]\n\n                [build-dependencies]\n                mb = {path=\"../../mb1\"}\n            \"#,\n        )\n        .file(\"member1/src/lib.rs\", \"\")\n        .file(\n            \"member2/Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"member2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                metabuild = [\"mb\"]\n\n                [build-dependencies]\n                mb = {path=\"../../mb2\"}\n            \"#,\n        )\n        .file(\"member2/src/lib.rs\", \"\")\n        .build();\n\n    project().at(\"mb1\")\n        .file(\"Cargo.toml\", r#\"\n            [package]\n            name = \"mb\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n        \"#)\n        .file(\n            \"src/lib.rs\",\n            r#\"pub fn metabuild() { println!(\"Hello mb1 {}\", std::env::var(\"CARGO_MANIFEST_DIR\").unwrap()); }\"#,\n        )\n        .build();\n\n    project().at(\"mb2\")\n        .file(\"Cargo.toml\", r#\"\n            [package]\n            name = \"mb\"\n            version = \"0.0.2\"\n            edition = \"2015\"\n        \"#)\n        .file(\n            \"src/lib.rs\",\n            r#\"pub fn metabuild() { println!(\"Hello mb2 {}\", std::env::var(\"CARGO_MANIFEST_DIR\").unwrap()); }\"#,\n        )\n        .build();\n\n    p.cargo(\"check -vv --workspace\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_stdout_data(\n            str![[r#\"\n[member2 0.0.1] Hello mb2 [ROOT]/ws/member2\n[member1 0.0.1] Hello mb1 [ROOT]/ws/member1\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    assert_eq!(\n        p.glob(\"target/.metabuild/metabuild-member?-*.rs\").count(),\n        2\n    );\n}\n\n#[cargo_test]\nfn metabuild_external_dependency() {\n    Package::new(\"mb\", \"1.0.0\")\n        .file(\"Cargo.toml\", &basic_manifest(\"mb\", \"1.0.0\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"pub fn metabuild() { println!(\"Hello mb\"); }\"#,\n        )\n        .publish();\n    Package::new(\"dep\", \"1.0.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"metabuild\"]\n                [package]\n                name = \"dep\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n                metabuild = [\"mb\"]\n\n                [build-dependencies]\n                mb = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build_dep(\"mb\", \"1.0.0\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            [dependencies]\n            dep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate dep;\")\n        .build();\n\n    p.cargo(\"check -vv\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_stdout_data(str![[r#\"\n[dep 1.0.0] Hello mb\n\n\"#]])\n        .run();\n\n    assert_eq!(p.glob(\"target/.metabuild/metabuild-dep-*.rs\").count(), 1);\n}\n\n#[cargo_test]\nfn metabuild_json_artifact() {\n    let p = basic_project();\n    p.cargo(\"check --message-format=json\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_stdout_data(\n            str![[r#\"\n[\n  \"{...}\",\n  {\n    \"executable\": null,\n    \"features\": [],\n    \"filenames\": \"{...}\",\n    \"fresh\": false,\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.1\",\n    \"profile\": \"{...}\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": false,\n      \"doctest\": false,\n      \"edition\": \"2018\",\n      \"kind\": [\n        \"custom-build\"\n      ],\n      \"name\": \"metabuild-foo\",\n      \"src_path\": \"[ROOT]/foo/target/.metabuild/metabuild-foo-[HASH].rs\",\n      \"test\": false\n    }\n  },\n  {\n    \"cfgs\": [],\n    \"env\": [],\n    \"linked_libs\": [],\n    \"linked_paths\": [],\n    \"out_dir\": \"[ROOT]/foo/target/debug/build/foo-[HASH]/out\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.1\",\n    \"reason\": \"build-script-executed\"\n  },\n  \"{...}\"\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn metabuild_failed_build_json() {\n    let p = basic_project();\n    // Modify the metabuild dep so that it fails to compile.\n    p.change_file(\"mb/src/lib.rs\", \"\");\n    p.cargo(\"check --message-format=json\")\n        .masquerade_as_nightly_cargo(&[\"metabuild\"])\n        .with_status(101)\n        .with_stdout_data(\n            str![[r#\"\n[\n  \"{...}\",\n  {\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"message\": {\n      \"level\": \"error\",\n      \"message\": \"cannot find function `metabuild` in crate `mb`\",\n      \"...\": \"{...}\"\n    },\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.1\",\n    \"reason\": \"compiler-message\",\n    \"target\": {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": false,\n      \"doctest\": false,\n      \"edition\": \"2018\",\n      \"kind\": [\n        \"custom-build\"\n      ],\n      \"name\": \"metabuild-foo\",\n      \"src_path\": null,\n      \"test\": false\n    }\n  },\n  \"{...}\"\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/metadata.rs",
    "content": "//! Tests for the `cargo metadata` command.\n\nuse crate::prelude::*;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{\n    basic_bin_manifest, basic_lib_manifest, main_file, project, rustc_host, str,\n};\nuse serde_json::json;\n\n#[cargo_test]\nfn cargo_metadata_simple() {\n    let p = project()\n        .file(\"src/foo.rs\", \"\")\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/foo.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.5.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.5.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_warns_on_implicit_version() {\n    let p = project()\n        .file(\"src/foo.rs\", \"\")\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stderr_data(str![[r#\"\n[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems\n\n\"#]])\n        .run();\n\n    p.cargo(\"metadata --format-version 1\")\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn library_with_several_crate_types() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.5.0\"\n\n[lib]\ncrate-type = [\"lib\", \"staticlib\"]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\",\n            \"staticlib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\",\n            \"staticlib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.5.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.5.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn library_with_features() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.5.0\"\n\n[features]\ndefault = [\"default_feat\"]\ndefault_feat = []\noptional_feat = []\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {\n        \"default\": [\n          \"default_feat\"\n        ],\n        \"default_feat\": [],\n        \"optional_feat\": []\n      },\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [\n          \"default\",\n          \"default_feat\"\n        ],\n        \"id\": \"path+[ROOTURL]/foo#0.5.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.5.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_with_deps_and_version() {\n    let p = project()\n        .file(\"src/foo.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [[bin]]\n                name = \"foo\"\n\n                [dependencies]\n                bar = \"*\"\n                [dev-dependencies]\n                foobar = \"*\"\n            \"#,\n        )\n        .build();\n    Package::new(\"baz\", \"0.0.1\").publish();\n    Package::new(\"foobar\", \"0.0.1\").publish();\n    Package::new(\"bar\", \"0.0.1\").dep(\"baz\", \"0.0.1\").publish();\n\n    p.cargo(\"metadata -q --format-version 1\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"baz\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"^0.0.1\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"bar\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#baz@0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/baz-0.0.1/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"baz\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"baz\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/baz-0.0.1/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"bar\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": \"dev\",\n          \"name\": \"foobar\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": \"foo\",\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"keywords\": [],\n      \"license\": \"MIT\",\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/foo.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/foobar-0.0.1/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foobar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foobar\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/foobar-0.0.1/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [\n          \"registry+https://github.com/rust-lang/crates.io-index#baz@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"baz\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#baz@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#baz@0.0.1\"\n      },\n      {\n        \"dependencies\": [\n          \"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1\",\n          \"registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"bar\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": \"dev\",\n                \"target\": null\n              }\n            ],\n            \"name\": \"foobar\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.5.0\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.5.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n/// The `public` field should not show up in `cargo metadata` output if `-Zpublic-dependency`\n/// is not enabled\n#[cargo_test]\nfn cargo_metadata_public_private_dependencies_disabled() {\n    let p = project()\n        .file(\"src/foo.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [[bin]]\n                name = \"foo\"\n\n                [dependencies]\n                bar = { version = \"*\", public = false }\n                foobar = { version = \"*\", public = true }\n                baz = \"*\"\n            \"#,\n        )\n        .build();\n    Package::new(\"bar\", \"0.0.1\").publish();\n    Package::new(\"foobar\", \"0.0.2\").publish();\n    Package::new(\"baz\", \"0.0.3\").publish();\n\n    p.cargo(\"metadata -q --format-version 1\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"name\": \"bar\",\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"baz\",\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"foo\",\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"bar\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"baz\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"foobar\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"foobar\",\n      \"...\": \"{...}\"\n    }\n  ],\n  \"...\": \"{...}\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_public_private_dependencies_enabled() {\n    let p = project()\n        .file(\"src/foo.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [[bin]]\n                name = \"foo\"\n\n                [dependencies]\n                bar = { version = \"*\", public = false }\n                foobar = { version = \"*\", public = true }\n                baz = \"*\"\n            \"#,\n        )\n        .build();\n    Package::new(\"bar\", \"0.0.1\").publish();\n    Package::new(\"foobar\", \"0.0.2\").publish();\n    Package::new(\"baz\", \"0.0.3\").publish();\n\n    p.cargo(\"metadata -q --format-version 1 -Zpublic-dependency\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"name\": \"bar\",\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"baz\",\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"foo\",\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"bar\",\n          \"optional\": false,\n          \"public\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"baz\",\n          \"optional\": false,\n          \"public\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"foobar\",\n          \"optional\": false,\n          \"public\": true,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"foobar\",\n      \"...\": \"{...}\"\n    }\n  ],\n  \"...\": \"{...}\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn example() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.1.0\"\n\n[[example]]\nname = \"ex\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.1.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        },\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": false,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"example\"\n          ],\n          \"name\": \"ex\",\n          \"src_path\": \"[ROOT]/foo/examples/ex.rs\",\n          \"test\": false\n        }\n      ],\n      \"version\": \"0.1.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.1.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.1.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn example_lib() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.1.0\"\n\n[[example]]\nname = \"ex\"\ncrate-type = [\"rlib\", \"dylib\"]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.1.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        },\n        {\n          \"crate_types\": [\n            \"rlib\",\n            \"dylib\"\n          ],\n          \"doc\": false,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"example\"\n          ],\n          \"name\": \"ex\",\n          \"src_path\": \"[ROOT]/foo/examples/ex.rs\",\n          \"test\": false\n        }\n      ],\n      \"version\": \"0.1.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.1.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.1.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_metadata() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n\n                [workspace.metadata]\n                tool1 = \"hello\"\n                tool2 = [1, 2, 3]\n\n                [workspace.metadata.foo]\n                bar = 3\n\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"baz/Cargo.toml\", &basic_lib_manifest(\"baz\"))\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": {\n    \"foo\": {\n      \"bar\": 3\n    },\n    \"tool1\": \"hello\",\n    \"tool2\": [\n      1,\n      2,\n      3\n    ]\n  },\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/bar#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/bar/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"bar\",\n          \"src_path\": \"[ROOT]/foo/bar/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    },\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/baz#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/baz/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"baz\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"baz\",\n          \"src_path\": \"[ROOT]/foo/baz/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo/bar#0.5.0\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo/baz#0.5.0\"\n      }\n    ],\n    \"root\": null\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo/bar#0.5.0\",\n    \"path+[ROOTURL]/foo/baz#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo/bar#0.5.0\",\n    \"path+[ROOTURL]/foo/baz#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_metadata_with_dependencies_no_deps() {\n    let p = project()\n        // NOTE that 'artifact' isn't mentioned in the workspace here, yet it shows up as member.\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies]\n                baz = { path = \"../baz/\" }\n                artifact = { path = \"../artifact/\", artifact = \"bin\" }\n           \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"baz/Cargo.toml\", &basic_lib_manifest(\"baz\"))\n        .file(\"baz/src/lib.rs\", \"\")\n        .file(\"artifact/Cargo.toml\", &basic_bin_manifest(\"artifact\"))\n        .file(\"artifact/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"metadata --no-deps -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"artifact\": {\n            \"kinds\": [\n              \"bin\"\n            ],\n            \"lib\": false,\n            \"target\": null\n          },\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"artifact\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/artifact\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"baz\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/baz\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/bar#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/bar/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"bar\",\n          \"src_path\": \"[ROOT]/foo/bar/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    },\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/artifact#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/artifact/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"artifact\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"artifact\",\n          \"src_path\": \"[ROOT]/foo/artifact/src/main.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    },\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/baz#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/baz/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"baz\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"baz\",\n          \"src_path\": \"[ROOT]/foo/baz/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": null,\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo/bar#0.5.0\",\n    \"path+[ROOTURL]/foo/artifact#0.5.0\",\n    \"path+[ROOTURL]/foo/baz#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo/bar#0.5.0\",\n    \"path+[ROOTURL]/foo/artifact#0.5.0\",\n    \"path+[ROOTURL]/foo/baz#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_metadata_with_dependencies_and_resolve() {\n    let alt_target = \"wasm32-unknown-unknown\";\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"artifact\", \"non-artifact\", \"bin-only-artifact\"]\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            &r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                authors = []\n\n                [build-dependencies]\n                artifact = { path = \"../artifact/\", artifact = \"bin\", target = \"target\" }\n                bin-only-artifact = { path = \"../bin-only-artifact/\", artifact = \"bin\", target = \"$ALT_TARGET\" }\n                non-artifact = { path = \"../non-artifact\" }\n\n                [dependencies]\n                artifact = { path = \"../artifact/\", artifact = [\"cdylib\", \"staticlib\", \"bin:baz-name\"], lib = true, target = \"$ALT_TARGET\" }\n                bin-only-artifact = { path = \"../bin-only-artifact/\", artifact = \"bin:a-name\" }\n                non-artifact = { path = \"../non-artifact\" }\n\n                [dev-dependencies]\n                artifact = { path = \"../artifact/\" }\n                non-artifact = { path = \"../non-artifact\" }\n                bin-only-artifact = { path = \"../bin-only-artifact/\", artifact = \"bin:b-name\" }\n           \"#.replace(\"$ALT_TARGET\", alt_target),\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"bar/build.rs\", \"fn main() {}\")\n        .file(\n            \"artifact/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"artifact\"\n                version = \"0.5.0\"\n                authors = []\n\n                [lib]\n                crate-type = [\"staticlib\", \"cdylib\", \"rlib\"]\n\n                [[bin]]\n                name = \"bar-name\"\n\n                [[bin]]\n                name = \"baz-name\"\n            \"#,\n        )\n        .file(\"artifact/src/main.rs\", \"fn main() {}\")\n        .file(\"artifact/src/lib.rs\", \"\")\n        .file(\n            \"bin-only-artifact/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bin-only-artifact\"\n                version = \"0.5.0\"\n                authors = []\n\n                [[bin]]\n                name = \"a-name\"\n\n                [[bin]]\n                name = \"b-name\"\n            \"#,\n        )\n        .file(\"bin-only-artifact/src/main.rs\", \"fn main() {}\")\n        .file(\"non-artifact/Cargo.toml\",\n              r#\"\n                [package]\n\n                name = \"non-artifact\"\n                version = \"0.5.0\"\n                authors = []\n            \"#,\n        )\n        .file(\"non-artifact/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"metadata -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/artifact#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/artifact/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"artifact\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"staticlib\",\n            \"cdylib\",\n            \"rlib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"staticlib\",\n            \"cdylib\",\n            \"rlib\"\n          ],\n          \"name\": \"artifact\",\n          \"src_path\": \"[ROOT]/foo/artifact/src/lib.rs\",\n          \"test\": true\n        },\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"bar-name\",\n          \"src_path\": \"[ROOT]/foo/artifact/src/main.rs\",\n          \"test\": true\n        },\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"baz-name\",\n          \"src_path\": \"[ROOT]/foo/artifact/src/main.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"artifact\": {\n            \"kinds\": [\n              \"cdylib\",\n              \"staticlib\",\n              \"bin:baz-name\"\n            ],\n            \"lib\": true,\n            \"target\": \"wasm32-unknown-unknown\"\n          },\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"artifact\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/artifact\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"artifact\": {\n            \"kinds\": [\n              \"bin:a-name\"\n            ],\n            \"lib\": false,\n            \"target\": null\n          },\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"bin-only-artifact\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/bin-only-artifact\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"non-artifact\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/non-artifact\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": \"dev\",\n          \"name\": \"artifact\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/artifact\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"artifact\": {\n            \"kinds\": [\n              \"bin:b-name\"\n            ],\n            \"lib\": false,\n            \"target\": null\n          },\n          \"features\": [],\n          \"kind\": \"dev\",\n          \"name\": \"bin-only-artifact\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/bin-only-artifact\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": \"dev\",\n          \"name\": \"non-artifact\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/non-artifact\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"artifact\": {\n            \"kinds\": [\n              \"bin\"\n            ],\n            \"lib\": false,\n            \"target\": \"target\"\n          },\n          \"features\": [],\n          \"kind\": \"build\",\n          \"name\": \"artifact\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/artifact\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"artifact\": {\n            \"kinds\": [\n              \"bin\"\n            ],\n            \"lib\": false,\n            \"target\": \"wasm32-unknown-unknown\"\n          },\n          \"features\": [],\n          \"kind\": \"build\",\n          \"name\": \"bin-only-artifact\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/bin-only-artifact\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": \"build\",\n          \"name\": \"non-artifact\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/non-artifact\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/bar#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/bar/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"bar\",\n          \"src_path\": \"[ROOT]/foo/bar/src/lib.rs\",\n          \"test\": true\n        },\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": false,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"custom-build\"\n          ],\n          \"name\": \"build-script-build\",\n          \"src_path\": \"[ROOT]/foo/bar/build.rs\",\n          \"test\": false\n        }\n      ],\n      \"version\": \"0.5.0\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/bin-only-artifact#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/bin-only-artifact/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bin-only-artifact\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"a-name\",\n          \"src_path\": \"[ROOT]/foo/bin-only-artifact/src/main.rs\",\n          \"test\": true\n        },\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"b-name\",\n          \"src_path\": \"[ROOT]/foo/bin-only-artifact/src/main.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/non-artifact#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/non-artifact/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"non-artifact\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"non_artifact\",\n          \"src_path\": \"[ROOT]/foo/non-artifact/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo/artifact#0.5.0\"\n      },\n      {\n        \"dependencies\": [\n          \"path+[ROOTURL]/foo/artifact#0.5.0\",\n          \"path+[ROOTURL]/foo/bin-only-artifact#0.5.0\",\n          \"path+[ROOTURL]/foo/non-artifact#0.5.0\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"extern_name\": \"artifact\",\n                \"kind\": null,\n                \"target\": null\n              },\n              {\n                \"artifact\": \"cdylib\",\n                \"compile_target\": \"wasm32-unknown-unknown\",\n                \"extern_name\": \"artifact\",\n                \"kind\": null,\n                \"target\": null\n              },\n              {\n                \"artifact\": \"staticlib\",\n                \"compile_target\": \"wasm32-unknown-unknown\",\n                \"extern_name\": \"artifact\",\n                \"kind\": null,\n                \"target\": null\n              },\n              {\n                \"artifact\": \"bin\",\n                \"bin_name\": \"baz-name\",\n                \"compile_target\": \"wasm32-unknown-unknown\",\n                \"extern_name\": \"baz_name\",\n                \"kind\": null,\n                \"target\": null\n              },\n              {\n                \"kind\": \"dev\",\n                \"target\": null\n              },\n              {\n                \"artifact\": \"bin\",\n                \"bin_name\": \"bar-name\",\n                \"compile_target\": \"<target>\",\n                \"extern_name\": \"bar_name\",\n                \"kind\": \"build\",\n                \"target\": null\n              },\n              {\n                \"artifact\": \"bin\",\n                \"bin_name\": \"baz-name\",\n                \"compile_target\": \"<target>\",\n                \"extern_name\": \"baz_name\",\n                \"kind\": \"build\",\n                \"target\": null\n              }\n            ],\n            \"name\": \"artifact\",\n            \"pkg\": \"path+[ROOTURL]/foo/artifact#0.5.0\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"artifact\": \"bin\",\n                \"bin_name\": \"a-name\",\n                \"extern_name\": \"a_name\",\n                \"kind\": null,\n                \"target\": null\n              },\n              {\n                \"artifact\": \"bin\",\n                \"bin_name\": \"b-name\",\n                \"extern_name\": \"b_name\",\n                \"kind\": \"dev\",\n                \"target\": null\n              },\n              {\n                \"artifact\": \"bin\",\n                \"bin_name\": \"a-name\",\n                \"compile_target\": \"wasm32-unknown-unknown\",\n                \"extern_name\": \"a_name\",\n                \"kind\": \"build\",\n                \"target\": null\n              },\n              {\n                \"artifact\": \"bin\",\n                \"bin_name\": \"b-name\",\n                \"compile_target\": \"wasm32-unknown-unknown\",\n                \"extern_name\": \"b_name\",\n                \"kind\": \"build\",\n                \"target\": null\n              }\n            ],\n            \"name\": \"\",\n            \"pkg\": \"path+[ROOTURL]/foo/bin-only-artifact#0.5.0\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              },\n              {\n                \"kind\": \"dev\",\n                \"target\": null\n              },\n              {\n                \"kind\": \"build\",\n                \"target\": null\n              }\n            ],\n            \"name\": \"non_artifact\",\n            \"pkg\": \"path+[ROOTURL]/foo/non-artifact#0.5.0\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo/bar#0.5.0\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo/bin-only-artifact#0.5.0\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo/non-artifact#0.5.0\"\n      }\n    ],\n    \"root\": null\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo/bar#0.5.0\",\n    \"path+[ROOTURL]/foo/artifact#0.5.0\",\n    \"path+[ROOTURL]/foo/bin-only-artifact#0.5.0\",\n    \"path+[ROOTURL]/foo/non-artifact#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo/bar#0.5.0\",\n    \"path+[ROOTURL]/foo/artifact#0.5.0\",\n    \"path+[ROOTURL]/foo/bin-only-artifact#0.5.0\",\n    \"path+[ROOTURL]/foo/non-artifact#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_with_invalid_manifest() {\n    let p = project().file(\"Cargo.toml\", \"\").build();\n\n    p.cargo(\"metadata --format-version 1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  manifest is missing either a `[package]` or a `[workspace]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_with_invalid_authors_field() {\n    let p = project()\n        .file(\"src/foo.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                authors = \"\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid type: string \"\", expected a vector of strings or workspace\n --> Cargo.toml:3:27\n  |\n3 |                 authors = \"\"\n  |                           ^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_with_invalid_version_field() {\n    let p = project()\n        .file(\"src/foo.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                version = 1\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid type: integer `1`, expected SemVer version\n --> Cargo.toml:3:27\n  |\n3 |                 version = 1\n  |                           ^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_with_invalid_publish_field() {\n    let p = project()\n        .file(\"src/foo.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                publish = \"foo\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid type: string \"foo\", expected a boolean, a vector of strings, or workspace\n --> Cargo.toml:3:27\n  |\n3 |                 publish = \"foo\"\n  |                           ^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_with_invalid_artifact_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n\n                [dependencies]\n                artifact = { path = \"artifact\", artifact = \"bin:notfound\" }\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"artifact/Cargo.toml\", &basic_bin_manifest(\"artifact\"))\n        .file(\"artifact/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"metadata -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems\n[LOCKING] 1 package to latest compatible version\n[ERROR] dependency `artifact` in package `foo` requires a `bin:notfound` artifact to be present.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_with_invalid_duplicate_renamed_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n                baz = { path = \"bar\", package = \"bar\" }\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems\n[LOCKING] 1 package to latest compatible version\n[ERROR] the crate `foo v0.5.0 ([ROOT]/foo)` depends on crate `bar v0.5.0 ([ROOT]/foo/bar)` multiple times with different names\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_no_deps_path_to_cargo_toml_relative() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"metadata --no-deps --manifest-path foo/Cargo.toml\")\n        .cwd(p.root().parent().unwrap())\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/foo.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": null,\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_no_deps_path_to_cargo_toml_absolute() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"metadata --no-deps --manifest-path\")\n        .arg(p.root().join(\"Cargo.toml\"))\n        .cwd(p.root().parent().unwrap())\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/foo.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": null,\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_no_deps_path_to_cargo_toml_parent_relative() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"metadata --no-deps --manifest-path foo\")\n        .cwd(p.root().parent().unwrap())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_no_deps_path_to_cargo_toml_parent_absolute() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"metadata --no-deps --manifest-path\")\n        .arg(p.root())\n        .cwd(p.root().parent().unwrap())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] manifest path `[ROOT]/foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_no_deps_cwd() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"metadata --no-deps\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/foo.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": null,\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_bad_version() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"metadata --no-deps --format-version 2\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid value '2' for '--format-version <VERSION>'\n  [possible values: 1]\n\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n\n                [features]\n                a = []\n                b = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"metadata --features\").arg(\"a b\").run();\n}\n\n#[cargo_test]\nfn package_metadata() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = [\"wycats@example.com\"]\n                categories = [\"database\"]\n                keywords = [\"database\"]\n                readme = \"README.md\"\n                repository = \"https://github.com/rust-lang/cargo\"\n                homepage = \"https://rust-lang.org\"\n                documentation = \"https://doc.rust-lang.org/stable/std/\"\n\n                [package.metadata.bar]\n                baz = \"quux\"\n            \"#,\n        )\n        .file(\"README.md\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"metadata --no-deps\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [\n        \"database\"\n      ],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": \"https://doc.rust-lang.org/stable/std/\",\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": \"https://rust-lang.org\",\n      \"id\": \"path+[ROOTURL]/foo#0.1.0\",\n      \"keywords\": [\n        \"database\"\n      ],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": {\n        \"bar\": {\n          \"baz\": \"quux\"\n        }\n      },\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": \"README.md\",\n      \"repository\": \"https://github.com/rust-lang/cargo\",\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.1.0\"\n    }\n  ],\n  \"resolve\": null,\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn package_publish() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = [\"wycats@example.com\"]\n                categories = [\"database\"]\n                keywords = [\"database\"]\n                readme = \"README.md\"\n                repository = \"https://github.com/rust-lang/cargo\"\n                publish = [\"my-registry\"]\n            \"#,\n        )\n        .file(\"README.md\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"metadata --no-deps\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [\n        \"database\"\n      ],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.1.0\",\n      \"keywords\": [\n        \"database\"\n      ],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": [\n        \"my-registry\"\n      ],\n      \"readme\": \"README.md\",\n      \"repository\": \"https://github.com/rust-lang/cargo\",\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.1.0\"\n    }\n  ],\n  \"resolve\": null,\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_metadata_path_to_cargo_toml_project() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --manifest-path\")\n        .arg(p.root().join(\"bar/Cargo.toml\"))\n        .cwd(p.root().parent().unwrap())\n        .run();\n\n    p.cargo(\"metadata --manifest-path\")\n        .arg(p.root().join(\"target/package/bar-0.5.0/Cargo.toml\"))\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/target/package/bar-0.5.0#bar@0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/target/package/bar-0.5.0/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"bar\",\n          \"src_path\": \"[ROOT]/foo/target/package/bar-0.5.0/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo/target/package/bar-0.5.0#bar@0.5.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo/target/package/bar-0.5.0#bar@0.5.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target/package/bar-0.5.0/target\",\n  \"build_directory\": \"[ROOT]/foo/target/package/bar-0.5.0/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo/target/package/bar-0.5.0#bar@0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo/target/package/bar-0.5.0#bar@0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo/target/package/bar-0.5.0\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn package_edition_2018() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = [\"wycats@example.com\"]\n                edition = \"2018\"\n            \"#,\n        )\n        .build();\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2018\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.1.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2018\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.1.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.1.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.1.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn package_default_run() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", r#\"fn main() { println!(\"hello A\"); }\"#)\n        .file(\"src/bin/b.rs\", r#\"fn main() { println!(\"hello B\"); }\"#)\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = [\"wycats@example.com\"]\n                edition = \"2018\"\n                default-run = \"a\"\n            \"#,\n        )\n        .build();\n    let json = p.cargo(\"metadata\").run_json();\n    assert_eq!(json[\"packages\"][0][\"default_run\"], json!(\"a\"));\n}\n\n#[cargo_test]\nfn package_rust_version() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = [\"wycats@example.com\"]\n                edition = \"2018\"\n                rust-version = \"1.56\"\n            \"#,\n        )\n        .build();\n    let json = p.cargo(\"metadata\").run_json();\n    assert_eq!(json[\"packages\"][0][\"rust_version\"], json!(\"1.56\"));\n}\n\n#[cargo_test]\nfn target_edition_2018() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = [\"wycats@example.com\"]\n                edition = \"2015\"\n\n                [lib]\n                edition = \"2018\"\n            \"#,\n        )\n        .build();\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.1.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2018\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        },\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/main.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.1.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.1.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.1.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn rename_dependency() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [dependencies]\n                bar = { version = \"0.1.0\" }\n                baz = { version = \"0.2.0\", package = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar; extern crate baz;\")\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.1.0/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"bar\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.1.0/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.1.0\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.2.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.2.0/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"bar\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.2.0/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.2.0\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"bar\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"^0.1.0\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"bar\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": \"baz\",\n          \"req\": \"^0.2.0\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.2.0\"\n      },\n      {\n        \"dependencies\": [\n          \"registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0\",\n          \"registry+https://github.com/rust-lang/crates.io-index#bar@0.2.0\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"bar\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"baz\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.2.0\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.0.1\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.0.1\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.0.1\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.0.1\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn metadata_links() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.5.0\"\n            links = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": \"a\",\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        },\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": false,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"custom-build\"\n          ],\n          \"name\": \"build-script-build\",\n          \"src_path\": \"[ROOT]/foo/build.rs\",\n          \"test\": false\n        }\n      ],\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.5.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.5.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn deps_with_bin_only() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                [dependencies]\n                bdep = { path = \"bdep\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bdep/Cargo.toml\", &basic_bin_manifest(\"bdep\"))\n        .file(\"bdep/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"bdep\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/bdep\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.1.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.1.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.1.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.1.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn filter_platform() {\n    // Testing the --filter-platform flag.\n    Package::new(\"normal-dep\", \"0.0.1\").publish();\n    Package::new(\"host-dep\", \"0.0.1\").publish();\n    Package::new(\"alt-dep\", \"0.0.1\").publish();\n    Package::new(\"cfg-dep\", \"0.0.1\").publish();\n    // Just needs to be a valid target that is different from host.\n    // Presumably nobody runs these tests on wasm. 🙃\n    let alt_target = \"wasm32-unknown-unknown\";\n    let host_target = rustc_host();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                normal-dep = \"0.0.1\"\n\n                [target.{}.dependencies]\n                host-dep = \"0.0.1\"\n\n                [target.{}.dependencies]\n                alt-dep = \"0.0.1\"\n\n                [target.'cfg(foobar)'.dependencies]\n                cfg-dep = \"0.0.1\"\n                \"#,\n                host_target, alt_target\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // We're going to be checking that we don't download excessively,\n    // so we need to ensure that downloads will happen.\n    let clear = || {\n        paths::cargo_home().join(\"registry/cache\").rm_rf();\n        paths::cargo_home().join(\"registry/src\").rm_rf();\n        p.build_dir().rm_rf();\n    };\n\n    // Normal metadata, no filtering, returns *everything*.\n    p.cargo(\"metadata\")\n        .with_stderr_data(\n            str![[r#\"\n[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems\n[UPDATING] `dummy-registry` index\n[LOCKING] 4 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] normal-dep v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] host-dep v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] cfg-dep v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] alt-dep v0.0.1 (registry `dummy-registry`)\n\n\"#]]\n            .unordered(),\n        )\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"packages\": [\n    {\n      \"name\": \"alt-dep\",\n      \"dependencies\": [],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"cfg-dep\",\n      \"dependencies\": [],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"foo\",\n      \"dependencies\": [\n        {\n          \"name\": \"normal-dep\",\n          \"target\": null,\n          \"...\": \"{...}\"\n        },\n        {\n          \"name\": \"cfg-dep\",\n          \"target\": \"cfg(foobar)\",\n          \"...\": \"{...}\"\n        },\n        {\n          \"name\": \"alt-dep\",\n          \"target\": \"wasm32-unknown-unknown\",\n          \"...\": \"{...}\"\n        },\n        {\n          \"name\": \"host-dep\",\n          \"target\": \"[HOST_TARGET]\",\n          \"...\": \"{...}\"\n        }\n      ],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"host-dep\",\n      \"dependencies\": [],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"normal-dep\",\n      \"dependencies\": [],\n      \"...\": \"{...}\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1\"\n      },\n      {\n        \"dependencies\": [\n          \"registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1\",\n          \"registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1\",\n          \"registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1\",\n          \"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": \"wasm32-unknown-unknown\"\n              }\n            ],\n            \"name\": \"alt_dep\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": \"cfg(foobar)\"\n              }\n            ],\n            \"name\": \"cfg_dep\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": \"[HOST_TARGET]\"\n              }\n            ],\n            \"name\": \"host_dep\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"normal_dep\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.1.0\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.1.0\"\n  },\n  \"...\": \"{...}\"\n}\n\"#]]\n            .is_json()\n            .unordered(),\n        )\n        .run();\n    clear();\n\n    // Filter on alternate, removes cfg and host.\n    p.cargo(\"metadata --filter-platform\")\n        .arg(alt_target)\n        .with_stderr_data(\n            str![[r#\"\n[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems\n[DOWNLOADING] crates ...\n[DOWNLOADED] normal-dep v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] host-dep v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] alt-dep v0.0.1 (registry `dummy-registry`)\n\n\"#]]\n            .unordered(),\n        )\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"packages\": [\n    {\n      \"name\": \"alt-dep\",\n      \"dependencies\": [],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"foo\",\n      \"dependencies\": [\n        {\n          \"name\": \"normal-dep\",\n          \"target\": null,\n          \"...\": \"{...}\"\n        },\n        {\n          \"name\": \"cfg-dep\",\n          \"target\": \"cfg(foobar)\",\n          \"...\": \"{...}\"\n        },\n        {\n          \"name\": \"alt-dep\",\n          \"target\": \"wasm32-unknown-unknown\",\n          \"...\": \"{...}\"\n        },\n        {\n          \"name\": \"host-dep\",\n          \"target\": \"[HOST_TARGET]\",\n          \"...\": \"{...}\"\n        }\n      ],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"normal-dep\",\n      \"dependencies\": [],\n      \"...\": \"{...}\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1\"\n      },\n      {\n        \"dependencies\": [\n          \"registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1\",\n          \"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": \"wasm32-unknown-unknown\"\n              }\n            ],\n            \"name\": \"alt_dep\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"normal_dep\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.1.0\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.1.0\"\n  },\n  \"...\": \"{...}\"\n}\n\"#]]\n            .is_json()\n            .unordered(),\n        )\n        .run();\n    clear();\n\n    let host_filtered_stderr = str![[r#\"\n[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems\n[DOWNLOADING] crates ...\n[DOWNLOADED] normal-dep v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] host-dep v0.0.1 (registry `dummy-registry`)\n\n\"#]];\n\n    let host_filtered_stdout = str![[r#\"\n{\n  \"packages\": [\n    {\n      \"name\": \"foo\",\n      \"dependencies\": [\n        {\n          \"name\": \"normal-dep\",\n          \"target\": null,\n          \"...\": \"{...}\"\n        },\n        {\n          \"name\": \"cfg-dep\",\n          \"target\": \"cfg(foobar)\",\n          \"...\": \"{...}\"\n        },\n        {\n          \"name\": \"alt-dep\",\n          \"target\": \"wasm32-unknown-unknown\",\n          \"...\": \"{...}\"\n        },\n        {\n          \"name\": \"host-dep\",\n          \"target\": \"[HOST_TARGET]\",\n          \"...\": \"{...}\"\n        }\n      ],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"host-dep\",\n      \"dependencies\": [],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"normal-dep\",\n      \"dependencies\": [],\n      \"...\": \"{...}\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [\n          \"registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1\",\n          \"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": \"[HOST_TARGET]\"\n              }\n            ],\n            \"name\": \"host_dep\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"normal_dep\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.1.0\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.1.0\"\n  },\n  \"...\": \"{...}\"\n}\n\"#]];\n\n    // Filter on host, removes alt and cfg.\n    p.cargo(\"metadata --filter-platform\")\n        .arg(&host_target)\n        .with_stderr_data(host_filtered_stderr.clone().unordered())\n        .with_stdout_data(host_filtered_stdout.clone().is_json().unordered())\n        .run();\n    clear();\n\n    // Filter on host-tuple, should produce same result as explicit host target.\n    p.cargo(\"metadata --filter-platform\")\n        .arg(\"host-tuple\")\n        .with_stderr_data(host_filtered_stderr.unordered())\n        .with_stdout_data(host_filtered_stdout.is_json().unordered())\n        .run();\n    clear();\n\n    // Filter host with cfg, removes alt only\n    p.cargo(\"metadata --filter-platform\")\n        .arg(&host_target)\n        .env(\"RUSTFLAGS\", \"--cfg=foobar\")\n        .with_stderr_data(\n            str![[r#\"\n[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems\n[DOWNLOADING] crates ...\n[DOWNLOADED] normal-dep v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] host-dep v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] cfg-dep v0.0.1 (registry `dummy-registry`)\n\n\"#]]\n            .unordered(),\n        )\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"packages\": [\n    {\n      \"name\": \"cfg-dep\",\n      \"dependencies\": [],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"foo\",\n      \"dependencies\": [\n        {\n          \"name\": \"normal-dep\",\n          \"target\": null,\n          \"...\": \"{...}\"\n        },\n        {\n          \"name\": \"cfg-dep\",\n          \"target\": \"cfg(foobar)\",\n          \"...\": \"{...}\"\n        },\n        {\n          \"name\": \"alt-dep\",\n          \"target\": \"wasm32-unknown-unknown\",\n          \"...\": \"{...}\"\n        },\n        {\n          \"name\": \"host-dep\",\n          \"target\": \"[HOST_TARGET]\",\n          \"...\": \"{...}\"\n        }\n      ],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"host-dep\",\n      \"dependencies\": [],\n      \"...\": \"{...}\"\n    },\n    {\n      \"name\": \"normal-dep\",\n      \"dependencies\": [],\n      \"...\": \"{...}\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1\"\n      },\n      {\n        \"dependencies\": [\n          \"registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1\",\n          \"registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1\",\n          \"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": \"cfg(foobar)\"\n              }\n            ],\n            \"name\": \"cfg_dep\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": \"[HOST_TARGET]\"\n              }\n            ],\n            \"name\": \"host_dep\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"normal_dep\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.1.0\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.1.0\"\n  },\n  \"...\": \"{...}\"\n}\n\"#]]\n            .is_json()\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn dep_kinds() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"winapi\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            bar = \"0.1\"\n\n            [dev-dependencies]\n            bar = \"0.1\"\n\n            [build-dependencies]\n            bar = \"0.1\"\n\n            [target.'cfg(windows)'.dependencies]\n            winapi = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": \"{...}\",\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0\"\n      },\n      {\n        \"dependencies\": [\n          \"registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0\",\n          \"registry+https://github.com/rust-lang/crates.io-index#winapi@0.1.0\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              },\n              {\n                \"kind\": \"dev\",\n                \"target\": null\n              },\n              {\n                \"kind\": \"build\",\n                \"target\": null\n              }\n            ],\n            \"name\": \"bar\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": \"cfg(windows)\"\n              }\n            ],\n            \"name\": \"winapi\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#winapi@0.1.0\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.1.0\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#winapi@0.1.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.1.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn dep_kinds_workspace() {\n    // Check for bug with duplicate dep kinds in a workspace.\n    // If different members select different features for the same package,\n    // they show up multiple times in the resolver `deps`.\n    //\n    // Here:\n    //     foo -> dep\n    //     bar -> foo[feat1] -> dep\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [features]\n                feat1 = []\n\n                [dependencies]\n                dep = { path=\"dep\" }\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            foo = { path=\"..\", features=[\"feat1\"] }\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"dep/Cargo.toml\", &basic_lib_manifest(\"dep\"))\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": \"{...}\",\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [\n          \"path+[ROOTURL]/foo#0.1.0\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"foo\",\n            \"pkg\": \"path+[ROOTURL]/foo#0.1.0\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo/bar#0.1.0\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo/dep#0.5.0\"\n      },\n      {\n        \"dependencies\": [\n          \"path+[ROOTURL]/foo/dep#0.5.0\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"dep\",\n            \"pkg\": \"path+[ROOTURL]/foo/dep#0.5.0\"\n          }\n        ],\n        \"features\": [\n          \"feat1\"\n        ],\n        \"id\": \"path+[ROOTURL]/foo#0.1.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.1.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.1.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo/bar#0.1.0\",\n    \"path+[ROOTURL]/foo#0.1.0\",\n    \"path+[ROOTURL]/foo/dep#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn build_dir() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"Hello, World!\") }\"#)\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            build-dir = \"build-dir\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": \"{...}\",\n  \"resolve\": \"{...}\",\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/build-dir\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.0.1\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.0.1\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n// Creating non-utf8 path is an OS-specific pain, so let's run this only on\n// linux, where arbitrary bytes work.\n#[cfg(target_os = \"linux\")]\n#[cargo_test]\nfn cargo_metadata_non_utf8() {\n    use std::ffi::OsString;\n    use std::os::unix::ffi::OsStringExt;\n    use std::path::PathBuf;\n\n    let base = PathBuf::from(OsString::from_vec(vec![255]));\n\n    let p = project()\n        .no_manifest()\n        .file(base.join(\"./src/lib.rs\"), \"\")\n        .file(base.join(\"./Cargo.toml\"), &basic_lib_manifest(\"foo\"))\n        .build();\n\n    p.cargo(\"metadata\")\n        .cwd(p.root().join(base))\n        .arg(\"--format-version\")\n        .arg(\"1\")\n        .with_stderr_data(str![[r#\"\n[ERROR] path contains invalid UTF-8 characters\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n// TODO: Consider using this test instead of the version without the 'artifact' suffix or merge them because they should be pretty much the same.\n#[cargo_test]\nfn workspace_metadata_with_dependencies_no_deps_artifact() {\n    let p = project()\n        // NOTE that 'artifact' isn't mentioned in the workspace here, yet it shows up as member.\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies]\n                baz = { path = \"../baz/\" }\n                baz-renamed = { path = \"../baz/\" }\n                artifact = { path = \"../artifact/\", artifact = \"bin\" }\n           \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"baz/Cargo.toml\", &basic_lib_manifest(\"baz\"))\n        .file(\"baz/src/lib.rs\", \"\")\n        .file(\"artifact/Cargo.toml\", &basic_bin_manifest(\"artifact\"))\n        .file(\"artifact/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"metadata --no-deps -Z bindeps\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"artifact\": {\n            \"kinds\": [\n              \"bin\"\n            ],\n            \"lib\": false,\n            \"target\": null\n          },\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"artifact\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/artifact\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"baz\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/baz\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"baz-renamed\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/baz\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/bar#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/bar/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"bar\",\n          \"src_path\": \"[ROOT]/foo/bar/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    },\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/artifact#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/artifact/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"artifact\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"artifact\",\n          \"src_path\": \"[ROOT]/foo/artifact/src/main.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    },\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/baz#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/baz/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"baz\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"baz\",\n          \"src_path\": \"[ROOT]/foo/baz/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": null,\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo/bar#0.5.0\",\n    \"path+[ROOTURL]/foo/artifact#0.5.0\",\n    \"path+[ROOTURL]/foo/baz#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo/bar#0.5.0\",\n    \"path+[ROOTURL]/foo/artifact#0.5.0\",\n    \"path+[ROOTURL]/foo/baz#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn versionless_packages() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n\n                [dependencies]\n                foobar = \"0.0.1\"\n                baz = { path = \"../baz/\" }\n           \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n\n                [dependencies]\n                foobar = \"0.0.1\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n    Package::new(\"foobar\", \"0.0.1\").publish();\n\n    p.cargo(\"metadata -q --format-version 1\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"baz\",\n          \"optional\": false,\n          \"path\": \"[ROOT]/foo/baz\",\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"*\",\n          \"source\": null,\n          \"target\": null,\n          \"uses_default_features\": true\n        },\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"foobar\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"^0.0.1\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/bar#0.0.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/bar/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bar\",\n      \"publish\": [],\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"bar\",\n          \"src_path\": \"[ROOT]/foo/bar/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.0\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"foobar\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"^0.0.1\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/baz#0.0.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/baz/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"baz\",\n      \"publish\": [],\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"baz\",\n          \"src_path\": \"[ROOT]/foo/baz/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.0\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/foobar-0.0.1/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foobar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foobar\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/foobar-0.0.1/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [\n          \"path+[ROOTURL]/foo/baz#0.0.0\",\n          \"registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"baz\",\n            \"pkg\": \"path+[ROOTURL]/foo/baz#0.0.0\"\n          },\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"foobar\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo/bar#0.0.0\"\n      },\n      {\n        \"dependencies\": [\n          \"registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"foobar\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo/baz#0.0.0\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1\"\n      }\n    ],\n    \"root\": null\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo/bar#0.0.0\",\n    \"path+[ROOTURL]/foo/baz#0.0.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo/bar#0.0.0\",\n    \"path+[ROOTURL]/foo/baz#0.0.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n/// Record how TOML-specific types are deserialized by `toml` so we can make sure we know if these change and\n/// can have a conversation about what should be done.\n#[cargo_test]\nfn cargo_metadata_toml_types() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"Cargo.toml\",\n            \"\n[package]\nname = 'foo'\nedition = '2015'\n\n[package.metadata]\noffset-datetime = 1979-05-27T07:32:00Z\nlocal-datetime = 1979-05-27T07:32:00\nlocal-date = 1979-05-27\nlocal-time = 1979-05-27\n\",\n        )\n        .build();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.0.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": {\n        \"local-date\": {\n          \"$__toml_private_datetime\": \"1979-05-27\"\n        },\n        \"local-datetime\": {\n          \"$__toml_private_datetime\": \"1979-05-27T07:32:00\"\n        },\n        \"local-time\": {\n          \"$__toml_private_datetime\": \"1979-05-27\"\n        },\n        \"offset-datetime\": {\n          \"$__toml_private_datetime\": \"1979-05-27T07:32:00Z\"\n        }\n      },\n      \"name\": \"foo\",\n      \"publish\": [],\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"foo\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.0.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.0.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.0.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.0.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn metadata_ignores_build_target_configuration() -> anyhow::Result<()> {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n\n                [target.'cfg(something)'.dependencies]\n                foobar = \"0.0.1\"\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    Package::new(\"foobar\", \"0.0.1\").publish();\n\n    let output1 = p\n        .cargo(\"metadata -q --format-version 1\")\n        .exec_with_output()?;\n    let output2 = p\n        .cargo(\"metadata -q --format-version 1\")\n        .env(\"CARGO_BUILD_TARGET\", rustc_host())\n        .exec_with_output()?;\n    assert!(\n        output1.stdout == output2.stdout,\n        \"metadata should not change when `CARGO_BUILD_TARGET` is set\",\n    );\n    Ok(())\n}\n"
  },
  {
    "path": "tests/testsuite/minimal_versions.rs",
    "content": "//! Tests for minimal-version resolution.\n//!\n//! Note: Some tests are located in the resolver-tests package.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n// Ensure that the \"-Z minimal-versions\" CLI option works and the minimal\n// version of a dependency ends up in the lock file.\n#[cargo_test]\nfn minimal_version_cli() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n    Package::new(\"dep\", \"1.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.0.1\"\n\n                [dependencies]\n                dep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile -Zminimal-versions\")\n        .masquerade_as_nightly_cargo(&[\"minimal-versions\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to earliest compatible version\n[ADDING] dep v1.0.0 (available: v1.1.0)\n\n\"#]])\n        .run();\n\n    let lock = p.read_lockfile();\n\n    assert!(!lock.contains(\"1.1.0\"));\n}\n"
  },
  {
    "path": "tests/testsuite/mock-std/dep_test/Cargo.toml",
    "content": "[package]\nname = \"dep_test\"\nversion = \"0.1.0\"\nedition = \"2021\""
  },
  {
    "path": "tests/testsuite/mock-std/dep_test/src/lib.rs",
    "content": "\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/Cargo.toml",
    "content": "[workspace]\nresolver = \"1\"\nmembers = [\n  \"std\",\n  \"sysroot\",\n]\n\n[patch.crates-io]\nrustc-std-workspace-core = { path = 'rustc-std-workspace-core' }\nrustc-std-workspace-alloc = { path = 'rustc-std-workspace-alloc' }\nrustc-std-workspace-std = { path = 'rustc-std-workspace-std' }\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/alloc/Cargo.toml",
    "content": "[package]\nname = \"alloc\"\nversion = \"0.1.0\"\nauthors = [\"Alex Crichton <alex@alexcrichton.com>\"]\nedition = \"2018\"\n\n[dependencies]\nregistry-dep-using-core = { version = \"*\", features = ['mockbuild'] }\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/alloc/src/lib.rs",
    "content": "#![feature(staged_api)]\n#![stable(since = \"1.0.0\", feature = \"dummy\")]\n\nextern crate alloc;\n\n#[stable(since = \"1.0.0\", feature = \"dummy\")]\npub use alloc::*;\n\n#[stable(since = \"1.0.0\", feature = \"dummy\")]\npub fn custom_api() {\n}\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/compiler_builtins/Cargo.toml",
    "content": "[package]\nname = \"compiler_builtins\"\nversion = \"0.1.0\"\nauthors = [\"Alex Crichton <alex@alexcrichton.com>\"]\nedition = \"2018\"\nlinks = \"compiler-rt\"\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/compiler_builtins/build.rs",
    "content": "fn main() {\n    println!(\"cargo::metadata=compiler-rt=foo\");\n}\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/compiler_builtins/src/lib.rs",
    "content": "#![no_std]\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/core/Cargo.toml",
    "content": "[package]\nname = \"core\"\nversion = \"0.1.0\"\nauthors = [\"Alex Crichton <alex@alexcrichton.com>\"]\nedition = \"2018\"\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/core/src/lib.rs",
    "content": "#![no_std]\n#![feature(staged_api)]\n#![stable(since = \"1.0.0\", feature = \"dummy\")]\n\n#[stable(since = \"1.0.0\", feature = \"dummy\")]\npub use core::*;\n\n#[stable(since = \"1.0.0\", feature = \"dummy\")]\npub fn custom_api() {\n}\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/panic_unwind/Cargo.toml",
    "content": "[package]\nname = \"panic_unwind\"\nversion = \"0.1.0\"\nauthors = [\"Alex Crichton <alex@alexcrichton.com>\"]\nedition = \"2018\"\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/panic_unwind/src/lib.rs",
    "content": "#![feature(panic_unwind, panic_runtime)]\n#![panic_runtime]\n#![no_std]\n\nextern crate panic_unwind;\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/proc_macro/Cargo.toml",
    "content": "[package]\nname = \"proc_macro\"\nversion = \"0.1.0\"\nauthors = [\"Alex Crichton <alex@alexcrichton.com>\"]\nedition = \"2018\"\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/proc_macro/src/lib.rs",
    "content": "#![feature(staged_api)]\n#![stable(since = \"1.0.0\", feature = \"dummy\")]\n\nextern crate proc_macro;\n\n#[stable(since = \"1.0.0\", feature = \"dummy\")]\npub use proc_macro::*;\n\n#[stable(since = \"1.0.0\", feature = \"dummy\")]\npub fn custom_api() {\n}\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/rustc-std-workspace-alloc/Cargo.toml",
    "content": "[package]\nname = \"rustc-std-workspace-alloc\"\nversion = \"1.9.0\"\nauthors = [\"Alex Crichton <alex@alexcrichton.com>\"]\nedition = \"2018\"\n\n[lib]\npath = \"lib.rs\"\n\n[dependencies]\nalloc = { path = \"../alloc\" }\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/rustc-std-workspace-alloc/lib.rs",
    "content": "#![no_std]\n\npub use alloc::*;\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/rustc-std-workspace-core/Cargo.toml",
    "content": "[package]\nname = \"rustc-std-workspace-core\"\nversion = \"1.9.0\"\nauthors = [\"Alex Crichton <alex@alexcrichton.com>\"]\nedition = \"2018\"\n\n[lib]\npath = \"lib.rs\"\n\n[dependencies]\ncore = { path = \"../core\" }\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/rustc-std-workspace-core/lib.rs",
    "content": "#![no_std]\n\npub use core::*;\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/rustc-std-workspace-std/Cargo.toml",
    "content": "[package]\nname = \"rustc-std-workspace-std\"\nversion = \"1.9.0\"\nauthors = [\"Alex Crichton <alex@alexcrichton.com>\"]\nedition = \"2018\"\n\n[lib]\npath = \"lib.rs\"\n\n[dependencies]\nstd = { path = \"../std\" }\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/rustc-std-workspace-std/lib.rs",
    "content": "pub use std::*;\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/std/Cargo.toml",
    "content": "[package]\nname = \"std\"\nversion = \"0.1.0\"\nauthors = [\"Alex Crichton <alex@alexcrichton.com>\"]\nedition = \"2018\"\n\n[dependencies]\nregistry-dep-using-alloc = { version = \"*\", features = ['mockbuild'] }\ndep_test = { path = \"../../dep_test\" }\n\n[features]\nfeature1 = []\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/std/src/lib.rs",
    "content": "#![feature(staged_api)]\n#![stable(since = \"1.0.0\", feature = \"dummy\")]\n\n#[stable(since = \"1.0.0\", feature = \"dummy\")]\npub use std::*;\n\n#[stable(since = \"1.0.0\", feature = \"dummy\")]\npub fn custom_api() {}\n\n#[cfg(feature = \"feature1\")]\n#[stable(since = \"1.0.0\", feature = \"dummy\")]\npub fn conditional_function() {}\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/sysroot/Cargo.toml",
    "content": "[package]\nname = \"sysroot\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\nproc_macro = { path = \"../proc_macro\" }\nstd = { path = \"../std\" }\ntest = { path = \"../test\" }\n\n[features]\npanic-unwind = []\nbacktrace = []\nfeature1 = [\"std/feature1\"]\ndefault = []\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/sysroot/src/lib.rs",
    "content": "// Intentionally left blank.\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/test/Cargo.toml",
    "content": "[package]\nname = \"test\"\nversion = \"0.1.0\"\nauthors = [\"Alex Crichton <alex@alexcrichton.com>\"]\nedition = \"2018\"\n\n[dependencies]\nstd = { path = \"../std\" }\npanic_unwind = { path = \"../panic_unwind\" }\ncompiler_builtins = { path = \"../compiler_builtins\" }\nregistry-dep-using-std = { version = \"*\", features = ['mockbuild'] }\n"
  },
  {
    "path": "tests/testsuite/mock-std/library/test/src/lib.rs",
    "content": "#![feature(staged_api)]\n#![feature(test)]\n#![unstable(feature = \"test\", issue = \"none\")]\n\nextern crate test;\n\npub use test::*;\n\npub fn custom_api() {\n}\n"
  },
  {
    "path": "tests/testsuite/multitarget.rs",
    "content": "//! Tests for multiple `--target` flags to subcommands\n\nuse crate::prelude::*;\nuse crate::utils::cross_compile::{\n    can_run_on_host as cross_compile_can_run_on_host, disabled as cross_compile_disabled,\n};\nuse cargo_test_support::{basic_manifest, cross_compile, project, rustc_host, str};\n\n#[cargo_test]\nfn simple_build() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let t1 = cross_compile::alternate();\n    let t2 = rustc_host();\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .arg(\"--target\")\n        .arg(&t1)\n        .arg(\"--target\")\n        .arg(&t2)\n        .run();\n\n    assert!(p.target_bin(t1, \"foo\").is_file());\n    assert!(p.target_bin(t2, \"foo\").is_file());\n}\n\n#[cargo_test]\nfn simple_build_with_config() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let t1 = cross_compile::alternate();\n    let t2 = rustc_host();\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [build]\n                    target = [\"{t1}\", \"{t2}\"]\n                \"#\n            ),\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.target_bin(t1, \"foo\").is_file());\n    assert!(p.target_bin(t2, \"foo\").is_file());\n}\n\n#[cargo_test]\nfn simple_test() {\n    if !cross_compile_can_run_on_host() {\n        return;\n    }\n    let t1 = cross_compile::alternate();\n    let t2 = rustc_host();\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/lib.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"test\")\n        .arg(\"--target\")\n        .arg(&t1)\n        .arg(\"--target\")\n        .arg(&t2)\n        .with_stderr_data(\n            str![[r#\"\n[RUNNING] unittests src/lib.rs (target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE])\n[RUNNING] unittests src/lib.rs (target/[HOST_TARGET]/debug/deps/foo-[HASH][EXE])\n...\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn simple_run() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"run --target a --target b\")\n        .with_stderr_data(str![[r#\"\n[ERROR] only one `--target` argument is supported\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn simple_doc() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let t1 = cross_compile::alternate();\n    let t2 = rustc_host();\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/lib.rs\", \"//! empty lib\")\n        .build();\n\n    p.cargo(\"doc\")\n        .arg(\"--target\")\n        .arg(&t1)\n        .arg(\"--target\")\n        .arg(&t2)\n        .run();\n\n    assert!(p.build_dir().join(&t1).join(\"doc/foo/index.html\").is_file());\n    assert!(p.build_dir().join(&t2).join(\"doc/foo/index.html\").is_file());\n}\n\n#[cargo_test]\nfn simple_doc_open() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let t1 = cross_compile::alternate();\n    let t2 = rustc_host();\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/lib.rs\", \"//! empty lib\")\n        .build();\n\n    p.cargo(\"doc\")\n        .arg(\"--open\")\n        .arg(\"--target\")\n        .arg(&t1)\n        .arg(\"--target\")\n        .arg(&t2)\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v1.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[ERROR] only one `--target` argument is supported\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn simple_check() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let t1 = cross_compile::alternate();\n    let t2 = rustc_host();\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .arg(\"--target\")\n        .arg(&t1)\n        .arg(\"--target\")\n        .arg(&t2)\n        .run();\n}\n\n#[cargo_test]\nfn same_value_twice() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let t = rustc_host();\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .arg(\"--target\")\n        .arg(&t)\n        .arg(\"--target\")\n        .arg(&t)\n        .run();\n\n    assert!(p.target_bin(t, \"foo\").is_file());\n}\n\n#[cargo_test]\nfn same_value_twice_with_config() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let t = rustc_host();\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [build]\n                    target = [\"{t}\", \"{t}\"]\n                \"#\n            ),\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.target_bin(t, \"foo\").is_file());\n}\n\n#[cargo_test]\nfn works_with_config_in_both_string_or_list() {\n    if cross_compile_disabled() {\n        return;\n    }\n    let t = rustc_host();\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [build]\n                    target = \"{t}\"\n                \"#\n            ),\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.target_bin(t, \"foo\").is_file());\n\n    p.cargo(\"clean\").run();\n\n    p.change_file(\n        \".cargo/config.toml\",\n        &format!(\n            r#\"\n                [build]\n                target = [\"{t}\"]\n            \"#\n        ),\n    );\n\n    p.cargo(\"build\").run();\n\n    assert!(p.target_bin(t, \"foo\").is_file());\n}\n\n#[cargo_test]\nfn works_with_env() {\n    let t = rustc_host();\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\").env(\"CARGO_BUILD_TARGET\", t).run();\n\n    assert!(p.target_bin(t, \"foo\").is_file());\n}\n"
  },
  {
    "path": "tests/testsuite/net_config.rs",
    "content": "//! Tests for network configuration.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn net_retry_loads_from_config() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [dependencies.bar]\n                git = \"http://127.0.0.1:11/foo/bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n           [net]\n           retry=1\n           [http]\n           timeout=1\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] spurious network error (1 try remaining): [..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn net_retry_git_outputs_warning() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [dependencies.bar]\n                git = \"http://127.0.0.1:11/foo/bar\"\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n           [http]\n           timeout=1\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v -j 1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] spurious network error (2 tries remaining): [..]\n[WARNING] spurious network error (1 try remaining): [..]\n...\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/new.rs",
    "content": "//! Tests for the `cargo new` command.\n\nuse std::env;\nuse std::fs::{self, File};\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::paths;\nuse cargo_test_support::str;\n\nfn create_default_gitconfig() {\n    // This helps on Windows where libgit2 is very aggressive in attempting to\n    // find a git config file.\n    let gitconfig = paths::home().join(\".gitconfig\");\n    File::create(gitconfig).unwrap();\n\n    // If we're running this under a user account that has a different default branch set up\n    // then tests that assume the default branch is master will fail. We set the default branch\n    // to master explicitly so that tests that rely on this behavior still pass.\n    fs::write(\n        paths::home().join(\".gitconfig\"),\n        r#\"\n        [init]\n            defaultBranch = master\n        \"#,\n    )\n    .unwrap();\n}\n\n#[cargo_test]\nfn simple_lib() {\n    cargo_process(\"new --lib foo --vcs none --edition 2015\")\n        .with_stderr_data(str![[r#\"\n[CREATING] library `foo` package\n[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]])\n        .run();\n\n    assert!(paths::root().join(\"foo\").is_dir());\n    assert!(paths::root().join(\"foo/Cargo.toml\").is_file());\n    assert!(paths::root().join(\"foo/src/lib.rs\").is_file());\n    assert!(!paths::root().join(\"foo/.gitignore\").is_file());\n\n    let lib = paths::root().join(\"foo/src/lib.rs\");\n    let contents = fs::read_to_string(&lib).unwrap();\n    assert_eq!(\n        contents,\n        r#\"pub fn add(left: u64, right: u64) -> u64 {\n    left + right\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn it_works() {\n        let result = add(2, 2);\n        assert_eq!(result, 4);\n    }\n}\n\"#\n    );\n\n    cargo_process(\"build\").cwd(&paths::root().join(\"foo\")).run();\n}\n\n#[cargo_test]\nfn simple_bin() {\n    cargo_process(\"new --bin foo --edition 2015\")\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `foo` package\n[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]])\n        .run();\n\n    assert!(paths::root().join(\"foo\").is_dir());\n    assert!(paths::root().join(\"foo/Cargo.toml\").is_file());\n    assert!(paths::root().join(\"foo/src/main.rs\").is_file());\n\n    cargo_process(\"build\").cwd(&paths::root().join(\"foo\")).run();\n    assert!(\n        paths::root()\n            .join(&format!(\"foo/target/debug/foo{}\", env::consts::EXE_SUFFIX))\n            .is_file()\n    );\n}\n\n#[cargo_test]\nfn both_lib_and_bin() {\n    cargo_process(\"new --lib --bin foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] can't specify both lib and binary outputs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_git() {\n    cargo_process(\"new --lib foo --edition 2015\").run();\n\n    assert!(paths::root().is_dir());\n    assert!(paths::root().join(\"foo/Cargo.toml\").is_file());\n    assert!(paths::root().join(\"foo/src/lib.rs\").is_file());\n    assert!(paths::root().join(\"foo/.git\").is_dir());\n    assert!(paths::root().join(\"foo/.gitignore\").is_file());\n\n    let fp = paths::root().join(\"foo/.gitignore\");\n    let contents = fs::read_to_string(&fp).unwrap();\n    assert_eq!(contents, \"/target\\n\",);\n\n    cargo_process(\"build\").cwd(&paths::root().join(\"foo\")).run();\n}\n\n#[cargo_test(requires = \"hg\")]\nfn simple_hg() {\n    cargo_process(\"new --lib foo --edition 2015 --vcs hg\").run();\n\n    assert!(paths::root().is_dir());\n    assert!(paths::root().join(\"foo/Cargo.toml\").is_file());\n    assert!(paths::root().join(\"foo/src/lib.rs\").is_file());\n    assert!(paths::root().join(\"foo/.hg\").is_dir());\n    assert!(paths::root().join(\"foo/.hgignore\").is_file());\n\n    let fp = paths::root().join(\"foo/.hgignore\");\n    let contents = fs::read_to_string(&fp).unwrap();\n    assert_eq!(contents, \"^target$\\n\",);\n\n    cargo_process(\"build\").cwd(&paths::root().join(\"foo\")).run();\n}\n\n#[cargo_test]\nfn no_argument() {\n    cargo_process(\"new\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] the following required arguments were not provided:\n  <PATH>\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn existing() {\n    let dst = paths::root().join(\"foo\");\n    fs::create_dir(&dst).unwrap();\n    cargo_process(\"new foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `foo` package\n[ERROR] destination `[ROOT]/foo` already exists\n\nUse `cargo init` to initialize the directory\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_characters() {\n    cargo_process(\"new foo.rs\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `foo.rs` package\n[ERROR] invalid character `.` in package name: `foo.rs`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)\n[NOTE] the directory name is used as the package name\n[HELP] to override the package name, pass `--name <pkgname>`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn reserved_name() {\n    cargo_process(\"new test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `test` package\n[ERROR] invalid package name `test`: it conflicts with Rust's built-in test library\n[NOTE] the directory name is used as the package name\n[HELP] to override the package name, pass `--name <pkgname>`\n[HELP] to name the binary \"test\", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/test.rs` or change the name in Cargo.toml with:\n\n    [[bin]]\n    name = \"test\"\n    path = \"src/main.rs\"\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn reserved_binary_name() {\n    cargo_process(\"new --bin incremental\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `incremental` package\n[ERROR] invalid package name `incremental`: it conflicts with cargo's build directory names\n[NOTE] the directory name is used as the package name\n[HELP] to override the package name, pass `--name <pkgname>`\n\n\"#]])\n        .run();\n\n    cargo_process(\"new --lib incremental\")\n        .with_stderr_data(str![[r#\"\n[CREATING] library `incremental` package\n[WARNING] package `incremental` will not support binary executables with that name, it conflicts with cargo's build directory names\n[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn keyword_name() {\n    cargo_process(\"new pub\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `pub` package\n[ERROR] invalid package name `pub`: it is a Rust keyword\n[NOTE] the directory name is used as the package name\n[HELP] to override the package name, pass `--name <pkgname>`\n[HELP] to name the binary \"pub\", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/pub.rs` or change the name in Cargo.toml with:\n\n    [[bin]]\n    name = \"pub\"\n    path = \"src/main.rs\"\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn std_name() {\n    cargo_process(\"new core\").with_stderr_data(str![[r#\"\n[CREATING] binary (application) `core` package\n[WARNING] package name `core` may be confused with the package with that name in Rust's standard library\nIt is recommended to use a different name to avoid problems.\n[NOTE] the directory name is used as the package name\n[HELP] to override the package name, pass `--name <pkgname>`\n[HELP] to name the binary \"core\", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/core.rs` or change the name in Cargo.toml with:\n\n    [[bin]]\n    name = \"core\"\n    path = \"src/main.rs\"\n\n[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn git_prefers_command_line() {\n    let root = paths::root();\n    fs::create_dir(&root.join(\".cargo\")).unwrap();\n    fs::write(\n        &root.join(\".cargo/config.toml\"),\n        r#\"\n            [cargo-new]\n            vcs = \"none\"\n            name = \"foo\"\n            email = \"bar\"\n        \"#,\n    )\n    .unwrap();\n\n    cargo_process(\"new foo --vcs git\").run();\n    assert!(paths::root().join(\"foo/.gitignore\").exists());\n    assert!(\n        !fs::read_to_string(paths::root().join(\"foo/Cargo.toml\"))\n            .unwrap()\n            .contains(\"authors =\")\n    );\n}\n\n#[cargo_test]\nfn subpackage_no_git() {\n    cargo_process(\"new foo\").run();\n\n    assert!(paths::root().join(\"foo/.git\").is_dir());\n    assert!(paths::root().join(\"foo/.gitignore\").is_file());\n\n    let subpackage = paths::root().join(\"foo\").join(\"components\");\n    fs::create_dir(&subpackage).unwrap();\n    cargo_process(\"new foo/components/subcomponent\").run();\n\n    assert!(\n        !paths::root()\n            .join(\"foo/components/subcomponent/.git\")\n            .is_file()\n    );\n    assert!(\n        !paths::root()\n            .join(\"foo/components/subcomponent/.gitignore\")\n            .is_file()\n    );\n}\n\n#[cargo_test]\nfn subpackage_git_with_gitignore() {\n    cargo_process(\"new foo\").run();\n\n    assert!(paths::root().join(\"foo/.git\").is_dir());\n    assert!(paths::root().join(\"foo/.gitignore\").is_file());\n\n    let gitignore = paths::root().join(\"foo/.gitignore\");\n    fs::write(gitignore, b\"components\").unwrap();\n\n    let subpackage = paths::root().join(\"foo/components\");\n    fs::create_dir(&subpackage).unwrap();\n    cargo_process(\"new foo/components/subcomponent\").run();\n\n    assert!(\n        paths::root()\n            .join(\"foo/components/subcomponent/.git\")\n            .is_dir()\n    );\n    assert!(\n        paths::root()\n            .join(\"foo/components/subcomponent/.gitignore\")\n            .is_file()\n    );\n}\n\n#[cargo_test]\nfn subpackage_git_with_vcs_arg() {\n    cargo_process(\"new foo\").run();\n\n    let subpackage = paths::root().join(\"foo\").join(\"components\");\n    fs::create_dir(&subpackage).unwrap();\n    cargo_process(\"new foo/components/subcomponent --vcs git\").run();\n\n    assert!(\n        paths::root()\n            .join(\"foo/components/subcomponent/.git\")\n            .is_dir()\n    );\n    assert!(\n        paths::root()\n            .join(\"foo/components/subcomponent/.gitignore\")\n            .is_file()\n    );\n}\n\n#[cargo_test]\nfn unknown_flags() {\n    cargo_process(\"new foo --flag\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '--flag' found\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn explicit_invalid_name_not_suggested() {\n    cargo_process(\"new --name 10-invalid a\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `10-invalid` package\n[ERROR] invalid character `1` in package name: `10-invalid`, the name cannot start with a digit\n[HELP] to name the binary \"10-invalid\", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/10-invalid.rs` or change the name in Cargo.toml with:\n\n    [[bin]]\n    name = \"10-invalid\"\n    path = \"src/main.rs\"\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn explicit_project_name() {\n    cargo_process(\"new --lib foo --name bar\")\n        .with_stderr_data(str![[r#\"\n[CREATING] library `bar` package\n[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn new_with_edition_2015() {\n    cargo_process(\"new --edition 2015 foo\").run();\n    let manifest = fs::read_to_string(paths::root().join(\"foo/Cargo.toml\")).unwrap();\n    assert!(manifest.contains(\"edition = \\\"2015\\\"\"));\n}\n\n#[cargo_test]\nfn new_with_edition_2018() {\n    cargo_process(\"new --edition 2018 foo\").run();\n    let manifest = fs::read_to_string(paths::root().join(\"foo/Cargo.toml\")).unwrap();\n    assert!(manifest.contains(\"edition = \\\"2018\\\"\"));\n}\n\n#[cargo_test]\nfn new_default_edition() {\n    cargo_process(\"new foo\").run();\n    let manifest = fs::read_to_string(paths::root().join(\"foo/Cargo.toml\")).unwrap();\n    assert!(manifest.contains(\"edition = \\\"2024\\\"\"));\n}\n\n#[cargo_test]\nfn new_with_bad_edition() {\n    cargo_process(\"new --edition something_else foo\")\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid value 'something_else' for '--edition <YEAR>'\n...\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn lockfile_constant_during_new() {\n    cargo_process(\"new foo\").run();\n\n    cargo_process(\"build\").cwd(&paths::root().join(\"foo\")).run();\n    let before = fs::read_to_string(paths::root().join(\"foo/Cargo.lock\")).unwrap();\n    cargo_process(\"build\").cwd(&paths::root().join(\"foo\")).run();\n    let after = fs::read_to_string(paths::root().join(\"foo/Cargo.lock\")).unwrap();\n    assert_eq!(before, after);\n}\n\n#[cargo_test]\nfn restricted_windows_name() {\n    if cfg!(windows) {\n        cargo_process(\"new nul\")\n            .with_status(101)\n            .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `nul` package\n[ERROR] invalid package name `nul`: it is a reserved Windows filename\n[NOTE] the directory name is used as the package name\n[HELP] to override the package name, pass `--name <pkgname>`\n\n\"#]])\n            .run();\n    } else {\n        cargo_process(\"new nul\").with_stderr_data(str![[r#\"\n[CREATING] binary (application) `nul` package\n[WARNING] package name `nul` is a reserved Windows filename\nThis package will not work on Windows platforms.\n[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]]).run();\n    }\n}\n\n#[cargo_test]\nfn non_ascii_name() {\n    cargo_process(\"new Привет\").with_stderr_data(str![[r#\"\n[CREATING] binary (application) `Привет` package\n[WARNING] invalid package name `Привет`: contains non-ASCII characters\nNon-ASCII crate names are not supported by Rust.\n[WARNING] package name `Привет` is not snake_case or kebab-case which is recommended for package names, consider `привет`\n[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn non_ascii_name_invalid() {\n    // These are alphanumeric characters, but not Unicode XID.\n    cargo_process(\"new ⒶⒷⒸ\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `ⒶⒷⒸ` package\n[ERROR] invalid character `Ⓐ` in package name: `ⒶⒷⒸ`, the first character must be a Unicode XID start character (most letters or `_`)\n[NOTE] the directory name is used as the package name\n[HELP] to override the package name, pass `--name <pkgname>`\n[HELP] to name the binary \"ⒶⒷⒸ\", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/ⒶⒷⒸ.rs` or change the name in Cargo.toml with:\n\n    [[bin]]\n    name = \"ⒶⒷⒸ\"\n    path = \"src/main.rs\"\n\n\n\"#]])\n        .run();\n\n    cargo_process(\"new a¼\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `a¼` package\n[ERROR] invalid character `¼` in package name: `a¼`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters)\n[NOTE] the directory name is used as the package name\n[HELP] to override the package name, pass `--name <pkgname>`\n[HELP] to name the binary \"a¼\", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/a¼.rs` or change the name in Cargo.toml with:\n\n    [[bin]]\n    name = \"a¼\"\n    path = \"src/main.rs\"\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn non_snake_case_name() {\n    cargo_process(\"new UPPERcase_name\")\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `UPPERcase_name` package\n[WARNING] package name `UPPERcase_name` is not snake_case or kebab-case which is recommended for package names, consider `uppercase_name`\n[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn kebab_case_name_is_accepted() {\n    cargo_process(\"new kebab-case-is-valid\")\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `kebab-case-is-valid` package\n[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_default_branch() {\n    // Check for init.defaultBranch support.\n    create_default_gitconfig();\n\n    cargo_process(\"new foo\").run();\n    let repo = git2::Repository::open(paths::root().join(\"foo\")).unwrap();\n    let head = repo.find_reference(\"HEAD\").unwrap();\n    assert_eq!(head.symbolic_target().unwrap(), \"refs/heads/master\");\n\n    fs::write(\n        paths::home().join(\".gitconfig\"),\n        r#\"\n        [init]\n            defaultBranch = hello\n        \"#,\n    )\n    .unwrap();\n    cargo_process(\"new bar\").run();\n    let repo = git2::Repository::open(paths::root().join(\"bar\")).unwrap();\n    let head = repo.find_reference(\"HEAD\").unwrap();\n    assert_eq!(head.symbolic_target().unwrap(), \"refs/heads/hello\");\n}\n\n#[cargo_test]\nfn non_utf8_str_in_ignore_file() {\n    let dir = paths::home().join(\"foo\");\n    fs::create_dir(&dir).unwrap();\n    fs::write(dir.join(\".gitignore\"), &[0xFF, 0xFE]).unwrap();\n\n    cargo_process(&format!(\"init {} --vcs git\", dir.display()))\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) package\n[ERROR] failed to create package `foo` at `[ROOT]/home/foo`\n\nCaused by:\n  Character at line 0 is invalid. Cargo only supports UTF-8.\n\n\"#]])\n        .run();\n}\n\n#[cfg(unix)]\n#[cargo_test]\nfn path_with_invalid_character() {\n    cargo_process(\"new --name testing test:ing\")\n        .with_stderr_data(str![[r#\"\n[CREATING] binary (application) `testing` package\n[WARNING] the path `[ROOT]/test:ing` contains invalid PATH characters (usually `:`, `;`, or `\"`)\nIt is recommended to use a different name to avoid problems.\n[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/offline.rs",
    "content": "//! Tests for --offline flag.\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::{\n    Execs, basic_manifest, git, main_file, project,\n    registry::{Package, RegistryBuilder},\n    str,\n};\n\n#[cargo_test]\nfn offline_unused_target_dep() {\n    // --offline with a target dependency that is not used and not downloaded.\n    Package::new(\"unused_dep\", \"1.0.0\").publish();\n    Package::new(\"used_dep\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            [dependencies]\n            used_dep = \"1.0\"\n            [target.'cfg(unused)'.dependencies]\n            unused_dep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    // Do a build that downloads only what is necessary.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n...\n[DOWNLOADED] used_dep v1.0.0 (registry `dummy-registry`)\n...\n\"#]])\n        .with_stderr_does_not_contain(\"[DOWNLOADED] unused_dep [..]\")\n        .run();\n    p.cargo(\"clean\").run();\n    // Build offline, make sure it works.\n    p.cargo(\"check --offline\").run();\n}\n\n#[cargo_test]\nfn offline_missing_optional() {\n    Package::new(\"opt_dep\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            [dependencies]\n            opt_dep = { version = \"1.0\", optional = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    // Do a build that downloads only what is necessary.\n    p.cargo(\"check\")\n        .with_stderr_does_not_contain(\"[DOWNLOADED] opt_dep [..]\")\n        .run();\n    p.cargo(\"clean\").run();\n    // Build offline, make sure it works.\n    p.cargo(\"check --offline\").run();\n    p.cargo(\"check --offline --features=opt_dep\")\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to download `opt_dep v1.0.0`\n\nCaused by:\n  attempting to make an HTTP request, but --offline was specified\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_path_with_offline() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies.bar]\n            path = \"bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --offline\").run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_downloaded_dependency_with_offline() {\n    Package::new(\"present_dep\", \"1.2.3\")\n        .file(\"Cargo.toml\", &basic_manifest(\"present_dep\", \"1.2.3\"))\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    // make package downloaded\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            present_dep = \"1.2.3\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\").run();\n\n    let p2 = project()\n        .at(\"bar\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            present_dep = \"1.2.3\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p2.cargo(\"check --offline\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] present_dep v1.2.3\n[CHECKING] bar v0.1.0 ([ROOT]/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_offline_not_try_update() {\n    // When --offline needs to download the registry, provide a reasonable\n    // error hint to run without --offline.\n    let p = project()\n        .at(\"bar\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            not_cached_dep = \"1.2.5\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --offline\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no matching package named `not_cached_dep` found\nlocation searched: crates.io index\nrequired by package `bar v0.1.0 ([ROOT]/bar)`\nAs a reminder, you're using offline mode (--offline) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without `--offline`.\n\n\"#]])\n        .run();\n\n    // While we're here, also check the config works.\n    p.change_file(\".cargo/config.toml\", \"net.offline = true\");\n    p.cargo(\"check\").with_status(101).with_stderr_data(str![[r#\"\n[ERROR] no matching package named `not_cached_dep` found\nlocation searched: crates.io index\nrequired by package `bar v0.1.0 ([ROOT]/bar)`\nAs a reminder, you're using offline mode (--offline) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without `--offline`.\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn compile_offline_without_maxvers_cached() {\n    Package::new(\"present_dep\", \"1.2.1\").publish();\n    Package::new(\"present_dep\", \"1.2.2\").publish();\n\n    Package::new(\"present_dep\", \"1.2.3\")\n        .file(\"Cargo.toml\", &basic_manifest(\"present_dep\", \"1.2.3\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"pub fn get_version()->&'static str {\"1.2.3\"}\"#,\n        )\n        .publish();\n\n    Package::new(\"present_dep\", \"1.2.5\")\n        .file(\"Cargo.toml\", &basic_manifest(\"present_dep\", \"1.2.5\"))\n        .file(\"src/lib.rs\", r#\"pub fn get_version(){\"1.2.5\"}\"#)\n        .publish();\n\n    // make package cached\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            present_dep = \"=1.2.3\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build\").run();\n\n    let p2 = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            present_dep = \"1.2\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"\\\nextern crate present_dep;\nfn main(){\n    println!(\\\"{}\\\", present_dep::get_version());\n}\",\n        )\n        .build();\n\n    p2.cargo(\"run --offline\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] present_dep v1.2.3\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n1.2.3\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_forbird_git_httpsrepo_offline() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n\n            [package]\n            name = \"foo\"\n            version = \"0.5.0\"\n            edition = \"2015\"\n            authors = [\"chabapok@example.com\"]\n\n            [dependencies.dep1]\n            git = 'https://github.com/some_user/dep1.git'\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --offline\").with_status(101).with_stderr_data(str![[r#\"\n[ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `dep1`\n\nCaused by:\n  unable to update https://github.com/some_user/dep1.git\n\nCaused by:\n  can't checkout from 'https://github.com/some_user/dep1.git': you are in the offline mode (--offline)\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn compile_offline_while_transitive_dep_not_cached() {\n    let baz = Package::new(\"baz\", \"1.0.0\");\n    let baz_path = baz.archive_dst();\n    baz.publish();\n\n    let baz_content = fs::read(&baz_path).unwrap();\n    // Truncate the file to simulate a download failure.\n    fs::write(&baz_path, &[]).unwrap();\n\n    Package::new(\"bar\", \"0.1.0\").dep(\"baz\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n\n    // simulate download bar, but fail to download baz\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\nCaused by:\n  failed to verify the checksum of `baz v1.0.0 (registry `dummy-registry`)`\n\n\"#]])\n        .run();\n\n    // Restore the file contents.\n    fs::write(&baz_path, &baz_content).unwrap();\n\n    p.cargo(\"check --offline\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to download `bar v0.1.0`\n\nCaused by:\n  attempting to make an HTTP request, but --offline was specified\n\n\"#]])\n        .run();\n}\n\nfn update_offline_not_cached() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            bar = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"update --offline\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no matching package named `bar` found\nlocation searched: [..]\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\nAs a reminder, you're using offline mode (--offline) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without `--offline`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_offline_not_cached_sparse() {\n    let _registry = RegistryBuilder::new().http_index().build();\n    update_offline_not_cached()\n}\n\n#[cargo_test]\nfn update_offline_not_cached_git() {\n    update_offline_not_cached()\n}\n\n#[cargo_test]\nfn cargo_compile_offline_with_cached_git_dep() {\n    compile_offline_with_cached_git_dep(false)\n}\n\n#[cargo_test]\nfn gitoxide_cargo_compile_offline_with_cached_git_dep_shallow_dep() {\n    compile_offline_with_cached_git_dep(true)\n}\n\nfn compile_offline_with_cached_git_dep(shallow: bool) {\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"0.5.0\"))\n            .file(\n                \"src/lib.rs\",\n                r#\"\n                pub static COOL_STR:&str = \"cached git repo rev1\";\n                \"#,\n            )\n    });\n\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    let rev1 = repo.revparse_single(\"HEAD\").unwrap().id();\n\n    // Commit the changes and make sure we trigger a recompile\n    git_project.change_file(\n        \"src/lib.rs\",\n        r#\"pub static COOL_STR:&str = \"cached git repo rev2\";\"#,\n    );\n    git::add(&repo);\n    let rev2 = git::commit(&repo);\n\n    // cache to registry rev1 and rev2\n    let prj = project()\n        .at(\"cache_git_dep\")\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"cache_git_dep\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n\n                [dependencies.dep1]\n                git = '{}'\n                rev = \"{}\"\n                \"#,\n                git_project.url(),\n                rev1\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n    let maybe_use_shallow = |mut cargo: Execs| -> Execs {\n        if shallow {\n            cargo\n                .arg(\"-Zgitoxide=fetch\")\n                .arg(\"-Zgit=shallow-deps\")\n                .masquerade_as_nightly_cargo(&[\n                    \"unstable features must be available for -Z gitoxide and -Z git\",\n                ]);\n        }\n        cargo\n    };\n    maybe_use_shallow(prj.cargo(\"build\")).run();\n\n    prj.change_file(\n        \"Cargo.toml\",\n        &format!(\n            r#\"\n            [package]\n            name = \"cache_git_dep\"\n            version = \"0.5.0\"\n            edition = \"2015\"\n\n            [dependencies.dep1]\n            git = '{}'\n            rev = \"{}\"\n            \"#,\n            git_project.url(),\n            rev2\n        ),\n    );\n    maybe_use_shallow(prj.cargo(\"build\")).run();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n\n                [dependencies.dep1]\n                git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            &main_file(r#\"\"hello from {}\", dep1::COOL_STR\"#, &[\"dep1\"]),\n        )\n        .build();\n\n    let mut cargo = p.cargo(\"build --offline\");\n    cargo.with_stderr_data(format!(\n        \"\\\n[LOCKING] 1 package to latest compatible version\n[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1#[..])\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\",\n    ));\n    maybe_use_shallow(cargo).run();\n\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(\"hello from cached git repo rev2\\n\")\n        .run();\n\n    p.change_file(\n        \"Cargo.toml\",\n        &format!(\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.5.0\"\n            edition = \"2015\"\n\n            [dependencies.dep1]\n            git = '{}'\n            rev = \"{}\"\n            \"#,\n            git_project.url(),\n            rev1\n        ),\n    );\n\n    maybe_use_shallow(p.cargo(\"build --offline\")).run();\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(\"hello from cached git repo rev1\\n\")\n        .run();\n}\n\n#[cargo_test]\nfn offline_resolve_optional_fail() {\n    // Example where resolve fails offline.\n    //\n    // This happens if at least 1 version of an optional dependency is\n    // available, but none of them satisfy the requirements. The current logic\n    // that handles this is `RegistryIndex::query_inner`, and it doesn't know\n    // if the package being queried is an optional one. This is not ideal, it\n    // would be best if it just ignored optional (unselected) dependencies.\n    Package::new(\"dep\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            dep = { version = \"1.0\", optional = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch\").run();\n\n    // Change dep to 2.0.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            dep = { version = \"2.0\", optional = true }\n        \"#,\n    );\n\n    p.cargo(\"check --offline\")\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n[ERROR] failed to select a version for the requirement `dep = \"^2.0\"`\ncandidate versions found which didn't match: 1.0.0\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.1.0 ([ROOT]/foo)`\nperhaps a crate was updated and forgotten to be re-vendored?\nAs a reminder, you're using offline mode (--offline) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without `--offline`.\n\n\"#]]\n        )\n        .run();\n}\n\n#[cargo_test]\nfn offline_with_all_patched() {\n    // Offline works if everything is patched.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            dep = \"1.0\"\n\n            [patch.crates-io]\n            dep = {path = \"dep\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn f() { dep::foo(); }\")\n        .file(\"dep/Cargo.toml\", &basic_manifest(\"dep\", \"1.0.0\"))\n        .file(\"dep/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"check --offline\").run();\n}\n\n#[cargo_test]\nfn update_offline_cached() {\n    // Cache a few versions to update against\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    let versions = [\"1.2.3\", \"1.2.5\", \"1.2.9\"];\n    for vers in versions.iter() {\n        Package::new(\"present_dep\", vers)\n            .file(\"Cargo.toml\", &basic_manifest(\"present_dep\", vers))\n            .file(\n                \"src/lib.rs\",\n                format!(r#\"pub fn get_version()->&'static str {{ \"{}\" }}\"#, vers).as_str(),\n            )\n            .publish();\n        // make package cached\n        p.change_file(\n            \"Cargo.toml\",\n            format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                present_dep = \"={}\"\n                \"#,\n                vers\n            )\n            .as_str(),\n        );\n        p.cargo(\"build\").run();\n    }\n\n    let p2 = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            present_dep = \"1.2\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"\\\nextern crate present_dep;\nfn main(){\n    println!(\\\"{}\\\", present_dep::get_version());\n}\",\n        )\n        .build();\n\n    p2.cargo(\"build --offline\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] present_dep v1.2.9\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p2.rename_run(\"foo\", \"with_1_2_9\")\n        .with_stdout_data(str![[r#\"\n1.2.9\n\n\"#]])\n        .run();\n    // updates happen without updating the index\n    p2.cargo(\"update present_dep --precise 1.2.3 --offline\")\n        .with_status(0)\n        .with_stderr_data(str![[r#\"\n[DOWNGRADING] present_dep v1.2.9 -> v1.2.3\n\n\"#]])\n        .run();\n\n    p2.cargo(\"build --offline\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] present_dep v1.2.3\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p2.rename_run(\"foo\", \"with_1_2_3\")\n        .with_stdout_data(str![[r#\"\n1.2.3\n\n\"#]])\n        .run();\n\n    // Offline update should only print package details and not index updating\n    p2.cargo(\"update --offline\")\n        .with_status(0)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[UPDATING] present_dep v1.2.3 -> v1.2.9\n\n\"#]])\n        .run();\n\n    // No v1.2.8 loaded into the cache so expect failure.\n    p2.cargo(\"update present_dep --precise 1.2.8 --offline\")\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n[ERROR] no matching package named `present_dep` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.1.0 ([ROOT]/foo)`\nAs a reminder, you're using offline mode (--offline) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without `--offline`.\n\n\"#]]\n        )\n        .run();\n}\n\n#[cargo_test]\nfn offline_and_frozen_and_no_lock() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.cargo(\"check --frozen --offline\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot create the lock file [ROOT]/foo/Cargo.lock because --frozen was passed to prevent this\n[HELP] to generate the lock file without accessing the network, remove the --frozen flag and use --offline instead.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn offline_and_locked_and_no_frozen() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.cargo(\"check --locked --offline\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot create the lock file [ROOT]/foo/Cargo.lock because --locked was passed to prevent this\n[HELP] to generate the lock file without accessing the network, remove the --locked flag and use --offline instead.\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/old_cargos.rs",
    "content": "//! Tests for checking behavior of old cargos.\n//!\n//! These tests are ignored because it is intended to be run on a developer\n//! system with a bunch of toolchains installed. This requires `rustup` to be\n//! installed. It will iterate over installed toolchains, and run some tests\n//! over each one, producing a report at the end. As of this writing, I have\n//! tested 1.0 to 1.51. Run this with:\n//!\n//! ```console\n//! cargo test --test testsuite -- old_cargos --no-capture --ignored\n//! ```\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_exe;\nuse cargo::CargoResult;\nuse cargo_test_support::registry::{self, Dependency, Package};\nuse cargo_test_support::{execs, paths, process, project, rustc_host, str};\nuse cargo_util::{ProcessBuilder, ProcessError};\nuse semver::Version;\n\nfn tc_process(cmd: &str, toolchain: &str) -> ProcessBuilder {\n    let mut p = if toolchain == \"this\" {\n        if cmd == \"cargo\" {\n            process(&cargo_exe())\n        } else {\n            process(cmd)\n        }\n    } else {\n        let mut cmd = process(cmd);\n        cmd.arg(format!(\"+{}\", toolchain));\n        cmd\n    };\n    // Reset PATH since `process` modifies it to remove rustup.\n    p.env(\"PATH\", std::env::var_os(\"PATH\").unwrap());\n    p\n}\n\n/// Returns a sorted list of all toolchains.\n///\n/// The returned value includes the parsed version, and the rustup toolchain\n/// name as a string.\nfn collect_all_toolchains() -> Vec<(Version, String)> {\n    let rustc_version = |tc| {\n        let mut cmd = tc_process(\"rustc\", tc);\n        cmd.arg(\"-V\");\n        let output = cmd.exec_with_output().expect(\"rustc installed\");\n        let version = std::str::from_utf8(&output.stdout).unwrap();\n        let parts: Vec<_> = version.split_whitespace().collect();\n        assert_eq!(parts[0], \"rustc\");\n        assert!(parts[1].starts_with(\"1.\"));\n        Version::parse(parts[1]).expect(\"valid version\")\n    };\n\n    // Provide a way to override the list.\n    if let Ok(tcs) = std::env::var(\"OLD_CARGO\") {\n        return tcs\n            .split(',')\n            .map(|tc| (rustc_version(tc), tc.to_string()))\n            .collect();\n    }\n\n    let host = rustc_host();\n    // I tend to have lots of toolchains installed, but I don't want to test\n    // all of them (like dated nightlies, or toolchains for non-host targets).\n    let valid_names = &[\n        format!(\"stable-{}\", host),\n        format!(\"beta-{}\", host),\n        format!(\"nightly-{}\", host),\n    ];\n\n    let output = ProcessBuilder::new(\"rustup\")\n        .args(&[\"toolchain\", \"list\"])\n        .exec_with_output()\n        .expect(\"rustup should be installed\");\n    let stdout = std::str::from_utf8(&output.stdout).unwrap();\n    let mut toolchains: Vec<_> = stdout\n        .lines()\n        .map(|line| {\n            // Some lines say things like (default), just get the version.\n            line.split_whitespace().next().expect(\"non-empty line\")\n        })\n        .filter(|line| {\n            line.ends_with(&host)\n                && (line.starts_with(\"1.\") || valid_names.iter().any(|name| name == line))\n        })\n        .map(|line| (rustc_version(line), line.to_string()))\n        .collect();\n\n    toolchains.sort_by(|a, b| a.0.cmp(&b.0));\n    toolchains\n}\n\n/// Returns whether the default toolchain is the stable version.\nfn default_toolchain_is_stable() -> bool {\n    let default = tc_process(\"rustc\", \"this\").arg(\"-V\").exec_with_output();\n    let stable = tc_process(\"rustc\", \"stable\").arg(\"-V\").exec_with_output();\n    match (default, stable) {\n        (Ok(d), Ok(s)) => d.stdout == s.stdout,\n        _ => false,\n    }\n}\n\n// This is a test for exercising the behavior of older versions of cargo with\n// the new feature syntax.\n//\n// The test involves a few dependencies with different feature requirements:\n//\n// * `bar` 1.0.0 is the base version that does not use the new syntax.\n// * `bar` 1.0.1 has a feature with the new syntax, but the feature is unused.\n//   The optional dependency `new-baz-dep` should not be activated.\n// * `bar` 1.0.2 has a dependency on `baz` that *requires* the new feature\n//   syntax.\n#[ignore = \"must be run manually, requires old cargo installations\"]\n#[cargo_test]\nfn new_features() {\n    let registry = registry::init();\n    if std::process::Command::new(\"rustup\").output().is_err() {\n        panic!(\"old_cargos requires rustup to be installed\");\n    }\n    Package::new(\"new-baz-dep\", \"1.0.0\").publish();\n\n    Package::new(\"baz\", \"1.0.0\").publish();\n    let baz101_cksum = Package::new(\"baz\", \"1.0.1\")\n        .add_dep(Dependency::new(\"new-baz-dep\", \"1.0\").optional(true))\n        .feature(\"new-feat\", &[\"dep:new-baz-dep\"])\n        .publish();\n\n    let bar100_cksum = Package::new(\"bar\", \"1.0.0\")\n        .add_dep(Dependency::new(\"baz\", \"1.0\").optional(true))\n        .feature(\"feat\", &[\"baz\"])\n        .publish();\n    let bar101_cksum = Package::new(\"bar\", \"1.0.1\")\n        .add_dep(Dependency::new(\"baz\", \"1.0\").optional(true))\n        .feature(\"feat\", &[\"dep:baz\"])\n        .publish();\n    let bar102_cksum = Package::new(\"bar\", \"1.0.2\")\n        .add_dep(Dependency::new(\"baz\", \"1.0\").enable_features(&[\"new-feat\"]))\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let lock_bar_to = |toolchain_version: &Version, bar_version| {\n        let lock = if toolchain_version < &Version::new(1, 12, 0) {\n            let url = registry.index_url();\n            match bar_version {\n                100 => format!(\n                    r#\"\n                        [root]\n                        name = \"foo\"\n                        version = \"0.1.0\"\n                        dependencies = [\n                         \"bar 1.0.0 (registry+{url})\",\n                        ]\n\n                        [[package]]\n                        name = \"bar\"\n                        version = \"1.0.0\"\n                        source = \"registry+{url}\"\n                    \"#,\n                    url = url\n                ),\n                101 => format!(\n                    r#\"\n                        [root]\n                        name = \"foo\"\n                        version = \"0.1.0\"\n                        dependencies = [\n                         \"bar 1.0.1 (registry+{url})\",\n                        ]\n\n                        [[package]]\n                        name = \"bar\"\n                        version = \"1.0.1\"\n                        source = \"registry+{url}\"\n                    \"#,\n                    url = url\n                ),\n                102 => format!(\n                    r#\"\n                        [root]\n                        name = \"foo\"\n                        version = \"0.1.0\"\n                        dependencies = [\n                         \"bar 1.0.2 (registry+{url})\",\n                        ]\n\n                        [[package]]\n                        name = \"bar\"\n                        version = \"1.0.2\"\n                        source = \"registry+{url}\"\n                        dependencies = [\n                         \"baz 1.0.1 (registry+{url})\",\n                        ]\n\n                        [[package]]\n                        name = \"baz\"\n                        version = \"1.0.1\"\n                        source = \"registry+{url}\"\n                    \"#,\n                    url = url\n                ),\n                _ => panic!(\"unexpected version\"),\n            }\n        } else {\n            match bar_version {\n                100 => format!(\n                    r#\"\n                        [root]\n                        name = \"foo\"\n                        version = \"0.1.0\"\n                        dependencies = [\n                         \"bar 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n                        ]\n\n                        [[package]]\n                        name = \"bar\"\n                        version = \"1.0.0\"\n                        source = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n                        [metadata]\n                        \"checksum bar 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)\" = \"{}\"\n                    \"#,\n                    bar100_cksum\n                ),\n                101 => format!(\n                    r#\"\n                        [root]\n                        name = \"foo\"\n                        version = \"0.1.0\"\n                        dependencies = [\n                         \"bar 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)\",\n                        ]\n\n                        [[package]]\n                        name = \"bar\"\n                        version = \"1.0.1\"\n                        source = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n                        [metadata]\n                        \"checksum bar 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)\" = \"{}\"\n                    \"#,\n                    bar101_cksum\n                ),\n                102 => format!(\n                    r#\"\n                        [root]\n                        name = \"foo\"\n                        version = \"0.1.0\"\n                        dependencies = [\n                         \"bar 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)\",\n                        ]\n\n                        [[package]]\n                        name = \"bar\"\n                        version = \"1.0.2\"\n                        source = \"registry+https://github.com/rust-lang/crates.io-index\"\n                        dependencies = [\n                         \"baz 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)\",\n                        ]\n\n                        [[package]]\n                        name = \"baz\"\n                        version = \"1.0.1\"\n                        source = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n                        [metadata]\n                        \"checksum bar 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)\" = \"{bar102_cksum}\"\n                        \"checksum baz 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)\" = \"{baz101_cksum}\"\n                    \"#,\n                    bar102_cksum = bar102_cksum,\n                    baz101_cksum = baz101_cksum\n                ),\n                _ => panic!(\"unexpected version\"),\n            }\n        };\n        p.change_file(\"Cargo.lock\", &lock);\n    };\n\n    let toolchains = collect_all_toolchains();\n\n    let config_path = paths::home().join(\".cargo/config\");\n    let lock_path = p.root().join(\"Cargo.lock\");\n\n    struct ToolchainBehavior {\n        bar: Option<Version>,\n        baz: Option<Version>,\n        new_baz_dep: Option<Version>,\n    }\n\n    // Collect errors to print at the end. One entry per toolchain, a list of\n    // strings to print.\n    let mut unexpected_results: Vec<Vec<String>> = Vec::new();\n\n    for (version, toolchain) in &toolchains {\n        if version >= &Version::new(1, 15, 0) && version < &Version::new(1, 18, 0) {\n            // These versions do not stay within the sandbox, and chokes on\n            // Cargo's own `Cargo.toml`.\n            continue;\n        }\n        let mut tc_result = Vec::new();\n        // Write a config appropriate for this version.\n        if version < &Version::new(1, 12, 0) {\n            fs::write(\n                &config_path,\n                format!(\n                    r#\"\n                        [registry]\n                        index = \"{}\"\n                    \"#,\n                    registry.index_url()\n                ),\n            )\n            .unwrap();\n        } else {\n            fs::write(\n                &config_path,\n                format!(\n                    \"\n                        [source.crates-io]\n                        registry = 'https://wut'  # only needed by 1.12\n                        replace-with = 'dummy-registry'\n\n                        [source.dummy-registry]\n                        registry = '{}'\n                    \",\n                    registry.index_url()\n                ),\n            )\n            .unwrap();\n        }\n\n        // Fetches the version of a package in the lock file.\n        let pkg_version = |pkg| -> Option<Version> {\n            let output = tc_process(\"cargo\", toolchain)\n                .args(&[\"pkgid\", pkg])\n                .cwd(p.root())\n                .exec_with_output()\n                .ok()?;\n            let stdout = std::str::from_utf8(&output.stdout).unwrap();\n            let version = stdout\n                .trim()\n                .rsplitn(2, ['@', ':'])\n                .next()\n                .expect(\"version after colon\");\n            Some(Version::parse(version).expect(\"parseable version\"))\n        };\n\n        // Runs `cargo build` and returns the versions selected in the lock.\n        let run_cargo = || -> CargoResult<ToolchainBehavior> {\n            match tc_process(\"cargo\", toolchain)\n                .args(&[\"build\", \"--verbose\"])\n                .cwd(p.root())\n                .exec_with_output()\n            {\n                Ok(_output) => {\n                    eprintln!(\"{} ok\", toolchain);\n                    let bar = pkg_version(\"bar\");\n                    let baz = pkg_version(\"baz\");\n                    let new_baz_dep = pkg_version(\"new-baz-dep\");\n                    Ok(ToolchainBehavior {\n                        bar,\n                        baz,\n                        new_baz_dep,\n                    })\n                }\n                Err(e) => {\n                    eprintln!(\"{} err {}\", toolchain, e);\n                    Err(e)\n                }\n            }\n        };\n\n        macro_rules! check_lock {\n            ($tc_result:ident, $pkg:expr, $which:expr, $actual:expr, None) => {\n                check_lock!(= $tc_result, $pkg, $which, $actual, None);\n            };\n            ($tc_result:ident, $pkg:expr, $which:expr, $actual:expr, $expected:expr) => {\n                check_lock!(= $tc_result, $pkg, $which, $actual, Some(Version::parse($expected).unwrap()));\n            };\n            (= $tc_result:ident, $pkg:expr, $which:expr, $actual:expr, $expected:expr) => {\n                let exp: Option<Version> = $expected;\n                if $actual != $expected {\n                    $tc_result.push(format!(\n                        \"{} for {} saw {:?} but expected {:?}\",\n                        $which, $pkg, $actual, exp\n                    ));\n                }\n            };\n        }\n\n        let check_err_contains = |tc_result: &mut Vec<_>, err: anyhow::Error, contents| {\n            if let Some(ProcessError {\n                stderr: Some(stderr),\n                ..\n            }) = err.downcast_ref::<ProcessError>()\n            {\n                let stderr = std::str::from_utf8(stderr).unwrap();\n                if !stderr.contains(contents) {\n                    tc_result.push(format!(\n                        \"{} expected to see error contents:\\n{}\\nbut saw:\\n{}\",\n                        toolchain, contents, stderr\n                    ));\n                }\n            } else {\n                panic!(\"{} unexpected error {}\", toolchain, err);\n            }\n        };\n\n        // Unlocked behavior.\n        let which = \"unlocked\";\n        lock_path.rm_rf();\n        p.build_dir().rm_rf();\n        match run_cargo() {\n            Ok(behavior) => {\n                if version < &Version::new(1, 51, 0) {\n                    check_lock!(tc_result, \"bar\", which, behavior.bar, \"1.0.2\");\n                    check_lock!(tc_result, \"baz\", which, behavior.baz, \"1.0.1\");\n                    check_lock!(tc_result, \"new-baz-dep\", which, behavior.new_baz_dep, None);\n                } else if version >= &Version::new(1, 51, 0) && version <= &Version::new(1, 59, 0) {\n                    check_lock!(tc_result, \"bar\", which, behavior.bar, \"1.0.0\");\n                    check_lock!(tc_result, \"baz\", which, behavior.baz, None);\n                    check_lock!(tc_result, \"new-baz-dep\", which, behavior.new_baz_dep, None);\n                }\n                // Starting with 1.60, namespaced-features has been stabilized.\n                else {\n                    check_lock!(tc_result, \"bar\", which, behavior.bar, \"1.0.2\");\n                    check_lock!(tc_result, \"baz\", which, behavior.baz, \"1.0.1\");\n                    check_lock!(\n                        tc_result,\n                        \"new-baz-dep\",\n                        which,\n                        behavior.new_baz_dep,\n                        \"1.0.0\"\n                    );\n                }\n            }\n            Err(e) => {\n                if version < &Version::new(1, 49, 0) {\n                    // Old versions don't like the dep: syntax.\n                    check_err_contains(\n                        &mut tc_result,\n                        e,\n                        \"which is neither a dependency nor another feature\",\n                    );\n                } else if version >= &Version::new(1, 49, 0) && version < &Version::new(1, 51, 0) {\n                    check_err_contains(\n                        &mut tc_result,\n                        e,\n                        \"requires the `-Z namespaced-features` flag\",\n                    );\n                } else {\n                    tc_result.push(format!(\"unlocked build failed: {}\", e));\n                }\n            }\n        }\n\n        let which = \"locked bar 1.0.0\";\n        lock_bar_to(version, 100);\n        match run_cargo() {\n            Ok(behavior) => {\n                check_lock!(tc_result, \"bar\", which, behavior.bar, \"1.0.0\");\n                check_lock!(tc_result, \"baz\", which, behavior.baz, None);\n                check_lock!(tc_result, \"new-baz-dep\", which, behavior.new_baz_dep, None);\n            }\n            Err(e) => {\n                tc_result.push(format!(\"bar 1.0.0 locked build failed: {}\", e));\n            }\n        }\n\n        let which = \"locked bar 1.0.1\";\n        lock_bar_to(version, 101);\n        match run_cargo() {\n            Ok(behavior) => {\n                check_lock!(tc_result, \"bar\", which, behavior.bar, \"1.0.1\");\n                check_lock!(tc_result, \"baz\", which, behavior.baz, None);\n                check_lock!(tc_result, \"new-baz-dep\", which, behavior.new_baz_dep, None);\n            }\n            Err(e) => {\n                if version < &Version::new(1, 49, 0) {\n                    // Old versions don't like the dep: syntax.\n                    check_err_contains(\n                        &mut tc_result,\n                        e,\n                        \"which is neither a dependency nor another feature\",\n                    );\n                } else if version >= &Version::new(1, 49, 0) && version < &Version::new(1, 51, 0) {\n                    check_err_contains(\n                        &mut tc_result,\n                        e,\n                        \"requires the `-Z namespaced-features` flag\",\n                    );\n                } else {\n                    // When version >= 1.51 and <= 1.59,\n                    // 1.0.1 can't be used without -Znamespaced-features\n                    // It gets filtered out of the index.\n                    check_err_contains(\n                        &mut tc_result,\n                        e,\n                        \"candidate versions found which didn't match: 1.0.2, 1.0.0\",\n                    );\n                }\n            }\n        }\n\n        let which = \"locked bar 1.0.2\";\n        lock_bar_to(version, 102);\n        match run_cargo() {\n            Ok(behavior) => {\n                if version <= &Version::new(1, 59, 0) {\n                    check_lock!(tc_result, \"bar\", which, behavior.bar, \"1.0.2\");\n                    check_lock!(tc_result, \"baz\", which, behavior.baz, \"1.0.1\");\n                    check_lock!(tc_result, \"new-baz-dep\", which, behavior.new_baz_dep, None);\n                }\n                // Starting with 1.60, namespaced-features has been stabilized.\n                else {\n                    check_lock!(tc_result, \"bar\", which, behavior.bar, \"1.0.2\");\n                    check_lock!(tc_result, \"baz\", which, behavior.baz, \"1.0.1\");\n                    check_lock!(\n                        tc_result,\n                        \"new-baz-dep\",\n                        which,\n                        behavior.new_baz_dep,\n                        \"1.0.0\"\n                    );\n                }\n            }\n            Err(e) => {\n                if version < &Version::new(1, 49, 0) {\n                    // Old versions don't like the dep: syntax.\n                    check_err_contains(\n                        &mut tc_result,\n                        e,\n                        \"which is neither a dependency nor another feature\",\n                    );\n                } else if version >= &Version::new(1, 49, 0) && version < &Version::new(1, 51, 0) {\n                    check_err_contains(\n                        &mut tc_result,\n                        e,\n                        \"requires the `-Z namespaced-features` flag\",\n                    );\n                } else {\n                    // When version >= 1.51 and <= 1.59,\n                    // baz can't lock to 1.0.1, it requires -Znamespaced-features\n                    check_err_contains(\n                        &mut tc_result,\n                        e,\n                        \"candidate versions found which didn't match: 1.0.0\",\n                    );\n                }\n            }\n        }\n\n        unexpected_results.push(tc_result);\n    }\n\n    // Generate a report.\n    let mut has_err = false;\n    for ((tc_vers, tc_name), errs) in toolchains.iter().zip(unexpected_results) {\n        if errs.is_empty() {\n            continue;\n        }\n        eprintln!(\"error: toolchain {} (version {}):\", tc_name, tc_vers);\n        for err in errs {\n            eprintln!(\"  {}\", err);\n        }\n        has_err = true;\n    }\n    if has_err {\n        panic!(\"at least one toolchain did not run as expected\");\n    }\n}\n\n#[cargo_test]\n#[ignore = \"must be run manually, requires old cargo installations\"]\nfn index_cache_rebuild() {\n    // Checks that the index cache gets rebuilt.\n    //\n    // 1.48 will not cache entries with features with the same name as a\n    // dependency. If the cache does not get rebuilt, then running with\n    // `-Znamespaced-features` would prevent the new cargo from seeing those\n    // entries. The index cache version was changed to prevent this from\n    // happening, and switching between versions should work correctly\n    // (although it will thrash the cash, that's better than not working\n    // correctly.\n    let registry = registry::init();\n    Package::new(\"baz\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.1\")\n        .add_dep(Dependency::new(\"baz\", \"1.0\").optional(true))\n        .feature(\"baz\", &[\"dep:baz\"])\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [source.crates-io]\n                    replace-with = 'dummy-registry'\n\n                    [source.dummy-registry]\n                    registry = '{}'\n                \"#,\n                registry.index_url()\n            ),\n        )\n        .build();\n\n    // This version of Cargo errors on index entries that have overlapping\n    // feature names, so 1.0.1 will be missing.\n    execs()\n        .with_process_builder(tc_process(\"cargo\", \"1.48.0\"))\n        .arg(\"check\")\n        .cwd(p.root())\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[ROOT]/registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `[ROOT]/registry`)\n[CHECKING] bar v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] dev [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    fs::remove_file(p.root().join(\"Cargo.lock\")).unwrap();\n\n    // This should rebuild the cache and use 1.0.1.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] no edition set: defaulting to the 2015 edition while the latest is [..]\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.1 (registry `dummy-registry`)\n[CHECKING] bar v1.0.1\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    fs::remove_file(p.root().join(\"Cargo.lock\")).unwrap();\n\n    // Verify 1.48 can still resolve, and is at 1.0.0.\n    execs()\n        .with_process_builder(tc_process(\"cargo\", \"1.48.0\"))\n        .arg(\"tree\")\n        .cwd(p.root())\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v1.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[ignore = \"must be run manually, requires old cargo installations\"]\nfn avoids_split_debuginfo_collision() {\n    // Test needs two different toolchains.\n    // If the default toolchain is stable, then it won't work.\n    if default_toolchain_is_stable() {\n        return;\n    }\n    // Checks for a bug where .o files were being incorrectly shared between\n    // different toolchains using incremental and split-debuginfo on macOS.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [profile.dev]\n                split-debuginfo = \"unpacked\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    execs()\n        .with_process_builder(tc_process(\"cargo\", \"stable\"))\n        .arg(\"build\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .cwd(p.root())\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .with_stderr_data(str![[r#\"\n[WARNING] no edition set: defaulting to the 2015 edition while the latest is [..]\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    execs()\n        .with_process_builder(tc_process(\"cargo\", \"stable\"))\n        .arg(\"build\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .cwd(p.root())\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/open_namespaces.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn within_namespace_requires_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo::bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"read-manifest\")\n        .masquerade_as_nightly_cargo(&[\"open-namespaces\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `open-namespaces` is required\n\n  The package requires the Cargo feature called `open-namespaces`, but that feature is not stabilized in this version of Cargo ([..]).\n  Consider adding `cargo-features = [\"open-namespaces\"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#open-namespaces for more information about the status of this feature.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn implicit_lib_within_namespace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"open-namespaces\"]\n\n                [package]\n                name = \"foo::bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"read-manifest\")\n        .masquerade_as_nightly_cargo(&[\"open-namespaces\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2015\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo#foo::bar@0.0.1\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n  \"metadata\": null,\n  \"name\": \"foo::bar\",\n  \"publish\": null,\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"lib\"\n      ],\n      \"doc\": true,\n      \"doctest\": true,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"lib\"\n      ],\n      \"name\": \"foo::bar\",\n      \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.1\"\n}\n\"#]]\n            .is_json(),\n        )\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn implicit_bin_within_namespace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"open-namespaces\"]\n\n                [package]\n                name = \"foo::bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"read-manifest\")\n        .masquerade_as_nightly_cargo(&[\"open-namespaces\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2015\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo#foo::bar@0.0.1\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n  \"metadata\": null,\n  \"name\": \"foo::bar\",\n  \"publish\": null,\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"foo::bar\",\n      \"src_path\": \"[ROOT]/foo/src/main.rs\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.1\"\n}\n\"#]]\n            .is_json(),\n        )\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn explicit_bin_within_namespace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"open-namespaces\"]\n\n                [package]\n                name = \"foo::bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [[bin]]\n                name = \"foo-bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/foo-bar/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"read-manifest\")\n        .masquerade_as_nightly_cargo(&[\"open-namespaces\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2015\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo#foo::bar@0.0.1\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n  \"metadata\": null,\n  \"name\": \"foo::bar\",\n  \"publish\": null,\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"lib\"\n      ],\n      \"doc\": true,\n      \"doctest\": true,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"lib\"\n      ],\n      \"name\": \"foo::bar\",\n      \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n      \"test\": true\n    },\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"foo-bar\",\n      \"src_path\": \"[ROOT]/foo/src/bin/foo-bar/main.rs\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.1\"\n}\n\"#]]\n            .is_json(),\n        )\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[cfg(unix)]\nfn namespaced_script_name() {\n    let p = cargo_test_support::project()\n        .file(\n            \"foo::bar.rs\",\n            r#\"---\ncargo-features = [\"open-namespaces\"]\npackage.edition = \"2021\"\n---\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"read-manifest -Zscript --manifest-path foo::bar.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\", \"open-namespaces\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2021\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/foo::bar.rs#foo::bar@0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/foo::bar.rs\",\n  \"metadata\": null,\n  \"name\": \"foo::bar\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2021\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"foo::bar\",\n      \"src_path\": \"[ROOT]/foo/foo::bar.rs\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}\n\"#]]\n            .is_json(),\n        )\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn generate_pkgid_with_namespace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"open-namespaces\"]\n\n                [package]\n                name = \"foo::bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\")\n        .masquerade_as_nightly_cargo(&[\"open-namespaces\"])\n        .run();\n    p.cargo(\"pkgid\")\n        .masquerade_as_nightly_cargo(&[\"open-namespaces\"])\n        .with_stdout_data(str![[r#\"\npath+[ROOTURL]/foo#foo::bar@0.0.1\n\n\"#]])\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn update_spec_accepts_namespaced_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"open-namespaces\"]\n\n                [package]\n                name = \"foo::bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\")\n        .masquerade_as_nightly_cargo(&[\"open-namespaces\"])\n        .run();\n    p.cargo(\"update foo::bar\")\n        .masquerade_as_nightly_cargo(&[\"open-namespaces\"])\n        .with_stdout_data(str![\"\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 0 packages to latest compatible versions\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_spec_accepts_namespaced_pkgid() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"open-namespaces\"]\n\n                [package]\n                name = \"foo::bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\")\n        .masquerade_as_nightly_cargo(&[\"open-namespaces\"])\n        .run();\n    p.cargo(&format!(\"update path+{}#foo::bar@0.0.1\", p.url()))\n        .masquerade_as_nightly_cargo(&[\"open-namespaces\"])\n        .with_stdout_data(str![\"\"])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 0 packages to latest compatible versions\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[cfg(unix)] // until we get proper packaging support\nfn publish_namespaced() {\n    use cargo_test_support::registry::RegistryBuilder;\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"open-namespaces\"]\n\n                [package]\n                name = \"foo::bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish\")\n        .masquerade_as_nightly_cargo(&[\"script\", \"open-namespaces\"])\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo::bar v0.0.1 ([ROOT]/foo)\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  cannot publish with `open-namespaces`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/owner.rs",
    "content": "//! Tests for the `cargo owner` command.\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::{self, api_path};\nuse cargo_test_support::str;\n\nfn setup(name: &str, content: Option<&str>) {\n    let dir = api_path().join(format!(\"api/v1/crates/{}\", name));\n    dir.mkdir_p();\n    if let Some(body) = content {\n        fs::write(dir.join(\"owners\"), body).unwrap();\n    }\n}\n\n#[cargo_test]\nfn simple_list() {\n    let registry = registry::init();\n    let content = r#\"{\n        \"users\": [\n            {\n                \"id\": 70,\n                \"login\": \"github:rust-lang:core\",\n                \"name\": \"Core\"\n            },\n            {\n                \"id\": 123,\n                \"login\": \"octocat\"\n            }\n        ]\n    }\"#;\n    setup(\"foo\", Some(content));\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"owner -l\")\n        .replace_crates_io(registry.index_url())\n        .with_stdout_data(str![[r#\"\ngithub:rust-lang:core (Core)\noctocat\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_add() {\n    let registry = registry::init();\n    setup(\"foo\", None);\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"owner -a username\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] failed to invite owners to crate `foo` on registry at [ROOTURL]/api\n\nCaused by:\n  EOF while parsing a value at line 1 column 0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_add_with_asymmetric() {\n    let registry = registry::RegistryBuilder::new()\n        .http_api()\n        .token(cargo_test_support::registry::Token::rfc_key())\n        .build();\n    setup(\"foo\", None);\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [project]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // The http_api server will check that the authorization is correct.\n    // If the authorization was not sent then we would get an unauthorized error.\n    p.cargo(\"owner -a username\")\n        .arg(\"-Zasymmetric-token\")\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .replace_crates_io(registry.index_url())\n        .with_status(0)\n        .run();\n}\n\n#[cargo_test]\nfn simple_remove() {\n    let registry = registry::init();\n    setup(\"foo\", None);\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"owner -r username\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[OWNER] removing [\"username\"] from crate foo\n[ERROR] failed to remove owners from crate `foo` on registry at [ROOTURL]/api\n\nCaused by:\n  EOF while parsing a value at line 1 column 0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_remove_with_asymmetric() {\n    let registry = registry::RegistryBuilder::new()\n        .http_api()\n        .token(cargo_test_support::registry::Token::rfc_key())\n        .build();\n    setup(\"foo\", None);\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [project]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // The http_api server will check that the authorization is correct.\n    // If the authorization was not sent then we would get an unauthorized error.\n    p.cargo(\"owner -r username\")\n        .arg(\"-Zasymmetric-token\")\n        .replace_crates_io(registry.index_url())\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .with_status(0)\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/package.rs",
    "content": "//! Tests for the `cargo package` command.\n\nuse std::fs::{self, File, read_to_string};\nuse std::path::Path;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::publish::validate_crate_contents;\nuse cargo_test_support::registry::{self, Package};\nuse cargo_test_support::{\n    Project, ProjectBuilder, basic_manifest, git, paths, project, rustc_host, str,\n    symlink_supported, t,\n};\nuse flate2::read::GzDecoder;\nuse tar::Archive;\n\n#[cargo_test]\nfn simple() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                exclude = [\"*.txt\"]\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\"src/bar.txt\", \"\") // should be ignored when packaging\n        .build();\n\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(p.root().join(\"target/package/foo-0.0.1.crate\").is_file());\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/main.rs\",\n            \"Cargo.lock\",\n        ],\n        (),\n    );\n}\n\n#[cargo_test]\nfn metadata_warning() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                repository = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn package_verbose() {\n    let root = paths::root().join(\"all\");\n    let repo = git::repo(&root)\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.1\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"a/a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/a/src/lib.rs\", \"\")\n        .build();\n    cargo_process(\"build\").cwd(repo.root()).run();\n\n    println!(\"package main repo\");\n    cargo_process(\"package -v --no-verify\")\n        .cwd(repo.root())\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/all)\n[ARCHIVING] .cargo_vcs_info.json\n[ARCHIVING] Cargo.lock\n[ARCHIVING] Cargo.toml\n[ARCHIVING] Cargo.toml.orig\n[ARCHIVING] src/main.rs\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n\n    let f = File::open(&repo.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    let vcs_contents = format!(\n        r#\"{{\n  \"git\": {{\n    \"sha1\": \"{}\"\n  }},\n  \"path_in_vcs\": \"\"\n}}\"#,\n        repo.revparse_head()\n    );\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/main.rs\",\n            \".cargo_vcs_info.json\",\n        ],\n        [(\".cargo_vcs_info.json\", &vcs_contents)],\n    );\n\n    println!(\"package sub-repo\");\n    cargo_process(\"package -v --no-verify\")\n        .cwd(repo.root().join(\"a/a\"))\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] a v0.0.1 ([ROOT]/all/a/a)\n[ARCHIVING] .cargo_vcs_info.json\n[ARCHIVING] Cargo.lock\n[ARCHIVING] Cargo.toml\n[ARCHIVING] Cargo.toml.orig\n[ARCHIVING] src/lib.rs\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n\n    let f = File::open(&repo.root().join(\"a/a/target/package/a-0.0.1.crate\")).unwrap();\n    let vcs_contents = format!(\n        r#\"{{\n  \"git\": {{\n    \"sha1\": \"{}\"\n  }},\n  \"path_in_vcs\": \"a/a\"\n}}\"#,\n        repo.revparse_head()\n    );\n    validate_crate_contents(\n        f,\n        \"a-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            \".cargo_vcs_info.json\",\n        ],\n        [(\".cargo_vcs_info.json\", &vcs_contents)],\n    );\n}\n\n#[cargo_test]\nfn package_verification() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"build\").run();\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn vcs_file_collision() {\n    let p = project().build();\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                description = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n                exclude = [\"*.no-existe\"]\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {}\n            \"#,\n        )\n        .file(\".cargo_vcs_info.json\", \"foo\")\n        .build();\n    p.cargo(\"package\")\n        .arg(\"--no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid inclusion of reserved file name .cargo_vcs_info.json in package source\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn orig_file_collision() {\n    let p = project().build();\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                description = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n                exclude = [\"*.no-existe\"]\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {}\n            \"#,\n        )\n        .file(\"Cargo.toml.orig\", \"oops\")\n        .build();\n    p.cargo(\"package\")\n        .arg(\"--no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid inclusion of reserved file name Cargo.toml.orig in package source\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn path_dependency_no_version() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[ERROR] failed to verify manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  all dependencies must have a version requirement specified when packaging.\n  dependency `bar` does not specify a version\n  Note: The packaged dependency will use the version from crates.io,\n  the `path` specification will be removed from the dependency declaration.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_dependency_no_version() {\n    registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies.foo]\n                git = \"git://path/to/nowhere\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[ERROR] failed to verify manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  all dependencies must have a version requirement specified when packaging.\n  dependency `foo` does not specify a version\n  Note: The packaged dependency will use the version from crates.io,\n  the `git` specification will be removed from the dependency declaration.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn exclude() {\n    let root = paths::root().join(\"exclude\");\n    let repo = git::repo(&root)\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                exclude = [\n                    \"*.txt\",\n                    # file in root\n                    \"file_root_1\",       # NO_CHANGE (ignored)\n                    \"/file_root_2\",      # CHANGING (packaged -> ignored)\n                    \"file_root_3/\",      # NO_CHANGE (packaged)\n                    \"file_root_4/*\",     # NO_CHANGE (packaged)\n                    \"file_root_5/**\",    # NO_CHANGE (packaged)\n                    # file in sub-dir\n                    \"file_deep_1\",       # CHANGING (packaged -> ignored)\n                    \"/file_deep_2\",      # NO_CHANGE (packaged)\n                    \"file_deep_3/\",      # NO_CHANGE (packaged)\n                    \"file_deep_4/*\",     # NO_CHANGE (packaged)\n                    \"file_deep_5/**\",    # NO_CHANGE (packaged)\n                    # dir in root\n                    \"dir_root_1\",        # CHANGING (packaged -> ignored)\n                    \"/dir_root_2\",       # CHANGING (packaged -> ignored)\n                    \"dir_root_3/\",       # CHANGING (packaged -> ignored)\n                    \"dir_root_4/*\",      # NO_CHANGE (ignored)\n                    \"dir_root_5/**\",     # NO_CHANGE (ignored)\n                    # dir in sub-dir\n                    \"dir_deep_1\",        # CHANGING (packaged -> ignored)\n                    \"/dir_deep_2\",       # NO_CHANGE\n                    \"dir_deep_3/\",       # CHANGING (packaged -> ignored)\n                    \"dir_deep_4/*\",      # CHANGING (packaged -> ignored)\n                    \"dir_deep_5/**\",     # CHANGING (packaged -> ignored)\n                ]\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\"bar.txt\", \"\")\n        .file(\"src/bar.txt\", \"\")\n        // File in root.\n        .file(\"file_root_1\", \"\")\n        .file(\"file_root_2\", \"\")\n        .file(\"file_root_3\", \"\")\n        .file(\"file_root_4\", \"\")\n        .file(\"file_root_5\", \"\")\n        // File in sub-dir.\n        .file(\"some_dir/file_deep_1\", \"\")\n        .file(\"some_dir/file_deep_2\", \"\")\n        .file(\"some_dir/file_deep_3\", \"\")\n        .file(\"some_dir/file_deep_4\", \"\")\n        .file(\"some_dir/file_deep_5\", \"\")\n        // Dir in root.\n        .file(\"dir_root_1/some_dir/file\", \"\")\n        .file(\"dir_root_2/some_dir/file\", \"\")\n        .file(\"dir_root_3/some_dir/file\", \"\")\n        .file(\"dir_root_4/some_dir/file\", \"\")\n        .file(\"dir_root_5/some_dir/file\", \"\")\n        // Dir in sub-dir.\n        .file(\"some_dir/dir_deep_1/some_dir/file\", \"\")\n        .file(\"some_dir/dir_deep_2/some_dir/file\", \"\")\n        .file(\"some_dir/dir_deep_3/some_dir/file\", \"\")\n        .file(\"some_dir/dir_deep_4/some_dir/file\", \"\")\n        .file(\"some_dir/dir_deep_5/some_dir/file\", \"\")\n        .build();\n\n    cargo_process(\"package --no-verify -v\")\n        .cwd(repo.root())\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/exclude)\n[ARCHIVING] .cargo_vcs_info.json\n[ARCHIVING] Cargo.lock\n[ARCHIVING] Cargo.toml\n[ARCHIVING] Cargo.toml.orig\n[ARCHIVING] file_root_3\n[ARCHIVING] file_root_4\n[ARCHIVING] file_root_5\n[ARCHIVING] some_dir/dir_deep_2/some_dir/file\n[ARCHIVING] some_dir/dir_deep_4/some_dir/file\n[ARCHIVING] some_dir/dir_deep_5/some_dir/file\n[ARCHIVING] some_dir/file_deep_2\n[ARCHIVING] some_dir/file_deep_3\n[ARCHIVING] some_dir/file_deep_4\n[ARCHIVING] some_dir/file_deep_5\n[ARCHIVING] src/main.rs\n[PACKAGED] 15 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n\n    assert!(repo.root().join(\"target/package/foo-0.0.1.crate\").is_file());\n\n    cargo_process(\"package -l\")\n        .cwd(repo.root())\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nfile_root_3\nfile_root_4\nfile_root_5\nsome_dir/dir_deep_2/some_dir/file\nsome_dir/dir_deep_4/some_dir/file\nsome_dir/dir_deep_5/some_dir/file\nsome_dir/file_deep_2\nsome_dir/file_deep_3\nsome_dir/file_deep_4\nsome_dir/file_deep_5\nsrc/main.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn include() {\n    let root = paths::root().join(\"include\");\n    let repo = git::repo(&root)\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                exclude = [\"*.txt\"]\n                include = [\"foo.txt\", \"**/*.rs\", \"Cargo.toml\", \".dotfile\"]\n            \"#,\n        )\n        .file(\"foo.txt\", \"\")\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\".dotfile\", \"\")\n        // Should be ignored when packaging.\n        .file(\"src/bar.txt\", \"\")\n        .build();\n\n    cargo_process(\"package --no-verify -v\")\n        .cwd(repo.root())\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[WARNING] both package.include and package.exclude are specified; the exclude list will be ignored\n[PACKAGING] foo v0.0.1 ([ROOT]/include)\n[ARCHIVING] .cargo_vcs_info.json\n[ARCHIVING] .dotfile\n[ARCHIVING] Cargo.lock\n[ARCHIVING] Cargo.toml\n[ARCHIVING] Cargo.toml.orig\n[ARCHIVING] foo.txt\n[ARCHIVING] src/main.rs\n[PACKAGED] 7 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn package_lib_with_bin() {\n    let p = project()\n        .file(\"src/main.rs\", \"extern crate foo; fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package -v\").run();\n}\n\n#[cargo_test]\nfn package_git_submodule() {\n    let project = git::new(\"foo\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                edition = \"2015\"\n                    authors = [\"foo@example.com\"]\n                    license = \"MIT\"\n                    description = \"foo\"\n                    repository = \"foo\"\n                \"#,\n            )\n            .file(\"src/lib.rs\", \"pub fn foo() {}\")\n    });\n    let library = git::new(\"bar\", |library| {\n        library.no_manifest().file(\"Makefile\", \"all:\")\n    });\n\n    let repository = git2::Repository::open(&project.root()).unwrap();\n    let url = library.root().to_url().to_string();\n    git::add_submodule(&repository, &url, Path::new(\"bar\"));\n    git::commit(&repository);\n\n    let repository = git2::Repository::open(&project.root().join(\"bar\")).unwrap();\n    repository\n        .reset(\n            &repository.revparse_single(\"HEAD\").unwrap(),\n            git2::ResetType::Hard,\n            None,\n        )\n        .unwrap();\n\n    project\n        .cargo(\"package --no-verify -v\")\n        .with_stderr_data(str![[r#\"\n...\n[ARCHIVING] bar/Makefile\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n/// Tests if a symlink to a git submodule is properly handled.\n///\n/// This test requires you to be able to make symlinks.\n/// For windows, this may require you to enable developer mode.\nfn package_symlink_to_submodule() {\n    #[cfg(unix)]\n    use std::os::unix::fs::symlink;\n    #[cfg(windows)]\n    use std::os::windows::fs::symlink_dir as symlink;\n\n    if !symlink_supported() {\n        return;\n    }\n\n    let project = git::new(\"foo\", |project| {\n        project.file(\"src/lib.rs\", \"pub fn foo() {}\")\n    });\n\n    let library = git::new(\"submodule\", |library| {\n        library.no_manifest().file(\"Makefile\", \"all:\")\n    });\n\n    let repository = git2::Repository::open(&project.root()).unwrap();\n    let url = library.root().to_url().to_string();\n    git::add_submodule(&repository, &url, Path::new(\"submodule\"));\n    t!(symlink(\n        &project.root().join(\"submodule\"),\n        &project.root().join(\"submodule-link\")\n    ));\n    git::add(&repository);\n    git::commit(&repository);\n\n    let repository = git2::Repository::open(&project.root().join(\"submodule\")).unwrap();\n    repository\n        .reset(\n            &repository.revparse_single(\"HEAD\").unwrap(),\n            git2::ResetType::Hard,\n            None,\n        )\n        .unwrap();\n\n    project\n        .cargo(\"package --no-verify -v\")\n        .with_stderr_contains(\"[ARCHIVING] submodule/Makefile\")\n        .with_stderr_does_not_contain(\"[ARCHIVING] submodule-link/.git/config\")\n        .run();\n}\n\n#[cargo_test]\nfn no_duplicates_from_modified_tracked_files() {\n    let p = git::new(\"all\", |p| p.file(\"src/main.rs\", \"fn main() {}\"));\n    p.change_file(\"src/main.rs\", r#\"fn main() { println!(\"A change!\"); }\"#);\n    p.cargo(\"build\").run();\n    p.cargo(\"package --list --allow-dirty\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ignore_nested() {\n    let cargo_toml = r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"foo\"\n            homepage = \"https://example.com/\"\n        \"#;\n    let main_rs = r#\"\n            fn main() { println!(\"hello\"); }\n        \"#;\n    let p = project()\n        .file(\"Cargo.toml\", cargo_toml)\n        .file(\"src/main.rs\", main_rs)\n        // If a project happens to contain a copy of itself, we should\n        // ignore it.\n        .file(\"a_dir/foo/Cargo.toml\", cargo_toml)\n        .file(\"a_dir/foo/src/main.rs\", main_rs)\n        .build();\n\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(p.root().join(\"target/package/foo-0.0.1.crate\").is_file());\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        (),\n    );\n}\n\n// Windows doesn't allow these characters in filenames.\n#[cfg(unix)]\n#[cargo_test]\nfn package_weird_characters() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\"src/:foo\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[ERROR] cannot package a filename with a special character `:`: src/:foo\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn repackage_on_source_change() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"package\").run();\n\n    // Add another source file\n    p.change_file(\"src/foo.rs\", r#\"fn main() { println!(\"foo\"); }\"#);\n\n    // Check that cargo rebuilds the tarball\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Check that the tarball contains the added file\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/main.rs\",\n            \"src/foo.rs\",\n        ],\n        (),\n    );\n}\n\n#[cargo_test]\n/// Tests if a broken symlink is properly handled when packaging.\n///\n/// This test requires you to be able to make symlinks.\n/// For windows, this may require you to enable developer mode.\nfn broken_symlink() {\n    #[cfg(unix)]\n    use std::os::unix::fs::symlink;\n    #[cfg(windows)]\n    use std::os::windows::fs::symlink_dir as symlink;\n\n    if !symlink_supported() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = 'foo'\n                documentation = 'foo'\n                homepage = 'foo'\n                repository = 'foo'\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n    t!(symlink(\"nowhere\", &p.root().join(\"src/foo.rs\")));\n\n    p.cargo(\"package -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  failed to open for archiving: `[ROOT]/foo/src/foo.rs`\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n/// Tests if a broken but excluded symlink is ignored.\n/// See issue rust-lang/cargo#10917\n///\n/// This test requires you to be able to make symlinks.\n/// For windows, this may require you to enable developer mode.\nfn broken_but_excluded_symlink() {\n    #[cfg(unix)]\n    use std::os::unix::fs::symlink;\n    #[cfg(windows)]\n    use std::os::windows::fs::symlink_dir as symlink;\n\n    if !symlink_supported() {\n        return;\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = 'foo'\n                documentation = 'foo'\n                homepage = 'foo'\n                repository = 'foo'\n                exclude = [\"src/foo.rs\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n    t!(symlink(\"nowhere\", &p.root().join(\"src/foo.rs\")));\n\n    p.cargo(\"package -v --list\")\n        // `src/foo.rs` is excluded.\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[cfg(not(windows))] // https://github.com/libgit2/libgit2/issues/6250\n/// Test that /dir and /dir/ matches symlinks to directories.\nfn gitignore_symlink_dir() {\n    if !symlink_supported() {\n        return;\n    }\n\n    let (p, _repo) = git::new_repo(\"foo\", |p| {\n        p.file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n            .symlink_dir(\"src\", \"src1\")\n            .symlink_dir(\"src\", \"src2\")\n            .symlink_dir(\"src\", \"src3\")\n            .symlink_dir(\"src\", \"src4\")\n            .file(\".gitignore\", \"/src1\\n/src2/\\nsrc3\\nsrc4/\")\n    });\n\n    p.cargo(\"package -l --no-metadata\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\n.gitignore\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[cfg(not(windows))] // https://github.com/libgit2/libgit2/issues/6250\n/// Test that /dir and /dir/ matches symlinks to directories in dirty working directory.\nfn gitignore_symlink_dir_dirty() {\n    if !symlink_supported() {\n        return;\n    }\n\n    let (p, _repo) = git::new_repo(\"foo\", |p| {\n        p.file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n            .file(\".gitignore\", \"/src1\\n/src2/\\nsrc3\\nsrc4/\")\n    });\n\n    p.symlink(\"src\", \"src1\");\n    p.symlink(\"src\", \"src2\");\n    p.symlink(\"src\", \"src3\");\n    p.symlink(\"src\", \"src4\");\n\n    p.cargo(\"package -l --no-metadata\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\n.gitignore\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n\n    p.cargo(\"package -l --no-metadata --allow-dirty\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\n.gitignore\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n/// Tests if a symlink to a directory is properly included.\n///\n/// This test requires you to be able to make symlinks.\n/// For windows, this may require you to enable developer mode.\nfn package_symlink_to_dir() {\n    if !symlink_supported() {\n        return;\n    }\n\n    project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\"bla/Makefile\", \"all:\")\n        .symlink_dir(\"bla\", \"foo\")\n        .build()\n        .cargo(\"package -v\")\n        .with_stderr_data(str![[r#\"\n...\n[ARCHIVING] foo/Makefile\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n/// Tests if a symlink to ancestor causes filesystem loop error.\n///\n/// This test requires you to be able to make symlinks.\n/// For windows, this may require you to enable developer mode.\nfn filesystem_loop() {\n    if !symlink_supported() {\n        return;\n    }\n\n    project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .symlink_dir(\"a/b\", \"a/b/c/d/foo\")\n        .build()\n        .cargo(\"package -v\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] File system loop found: [ROOT]/foo/a/b/c/d/foo points to an ancestor [ROOT]/foo/a/b\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn do_not_package_if_repository_is_dirty() {\n    let p = project().build();\n\n    // Create a Git repository containing a minimal Rust project.\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // Modify Cargo.toml without committing the change.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            documentation = \"foo\"\n            homepage = \"foo\"\n            repository = \"foo\"\n            # change\n        \"#,\n    );\n\n    p.cargo(\"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] 1 files in the working directory contain changes that were not yet committed into git:\n\nCargo.toml\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n\n    // cd to `src` and cargo report relative paths.\n    p.cargo(\"package\")\n        .cwd(p.root().join(\"src\"))\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] 1 files in the working directory contain changes that were not yet committed into git:\n\n../Cargo.toml\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dirty_ignored() {\n    // Cargo warns about an ignored file that will be published.\n    let (p, repo) = git::new_repo(\"foo\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                description = \"foo\"\n                license = \"foo\"\n                documentation = \"foo\"\n                include = [\"src\", \"build\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\".gitignore\", \"build\")\n    });\n    // Example of adding a file that is confusingly ignored by an overzealous\n    // gitignore rule.\n    p.change_file(\"src/build/mod.rs\", \"\");\n    p.cargo(\"package --list\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] 1 files in the working directory contain changes that were not yet committed into git:\n\nsrc/build/mod.rs\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n    // Add the ignored file and make sure it is included.\n    let mut index = t!(repo.index());\n    t!(index.add_path(Path::new(\"src/build/mod.rs\")));\n    t!(index.write());\n    git::commit(&repo);\n    p.cargo(\"package --list\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/build/mod.rs\nsrc/lib.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn vcs_status_check_for_each_workspace_member() {\n    // Cargo checks VCS status separately for each workspace member.\n    // This ensure one file changed in a package won't affect the other.\n    // Since the dirty bit in .cargo_vcs_info.json is just for advisory purpose,\n    // We may change the meaning of it in the future.\n    let (p, repo) = git::new_repo(\"foo\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"isengard\", \"mordor\"]\n            \"#,\n        )\n        .file(\"hobbit\", \"...\")\n        .file(\n            \"isengard/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"isengard\"\n                edition = \"2015\"\n                homepage = \"saruman\"\n                description = \"saruman\"\n                license = \"MIT\"\n            \"#,\n        )\n        .file(\"isengard/src/lib.rs\", \"\")\n        .file(\n            \"mordor/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"mordor\"\n                edition = \"2015\"\n                homepage = \"sauron\"\n                description = \"sauron\"\n                license = \"MIT\"\n            \"#,\n        )\n        .file(\"mordor/src/lib.rs\", \"\")\n    });\n    git::commit(&repo);\n\n    // Dirty file outside won't affect packaging.\n    p.change_file(\"hobbit\", \"changed!\");\n    p.change_file(\"mordor/src/lib.rs\", \"changed!\");\n    p.change_file(\"mordor/src/main.rs\", \"fn main() {}\");\n\n    // Ensure dirty files be reported only for one affected package.\n    p.cargo(\"package --workspace --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[PACKAGING] isengard v0.0.0 ([ROOT]/foo/isengard)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[ERROR] 2 files in the working directory contain changes that were not yet committed into git:\n\nmordor/src/lib.rs\nmordor/src/main.rs\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n\n    // Ensure only dirty package be recorded as dirty.\n    p.cargo(\"package --workspace --no-verify --allow-dirty\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] isengard v0.0.0 ([ROOT]/foo/isengard)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] mordor v0.0.0 ([ROOT]/foo/mordor)\n[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/isengard-0.0.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"isengard-0.0.0.crate\",\n        &[\n            \".cargo_vcs_info.json\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            \"Cargo.lock\",\n        ],\n        [(\n            \".cargo_vcs_info.json\",\n            // No change within `isengard/`, so not dirty at all.\n            str![[r#\"\n{\n  \"git\": {\n    \"sha1\": \"[..]\"\n  },\n  \"path_in_vcs\": \"isengard\"\n}\n\"#]]\n            .is_json(),\n        )],\n    );\n\n    let f = File::open(&p.root().join(\"target/package/mordor-0.0.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"mordor-0.0.0.crate\",\n        &[\n            \".cargo_vcs_info.json\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            \"src/main.rs\",\n            \"Cargo.lock\",\n        ],\n        [(\n            \".cargo_vcs_info.json\",\n            // Dirty bit is recorded.\n            str![[r#\"\n{\n  \"git\": {\n    \"dirty\": true,\n    \"sha1\": \"[..]\"\n  },\n  \"path_in_vcs\": \"mordor\"\n}\n\"#]]\n            .is_json(),\n        )],\n    );\n}\n\n/// Regression test for https://github.com/rust-lang/cargo/issues/16478\n#[cargo_test]\nfn dirty_untracked_file_when_packaged_from_workspace_member() {\n    let (p, repo) = git::new_repo(\"foo\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"inner\"]\n                resolver = \"2\"\n            \"#,\n        )\n        .file(\n            \"inner/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"inner\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"inner/src/lib.rs\", \"\")\n    });\n    git::commit(&repo);\n\n    p.change_file(\"inner/untracked\", \"untracked\");\n\n    p.cargo(\"package --list --no-metadata\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] 1 files in the working directory contain changes that were not yet committed into git:\n\ninner/untracked\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n\n    // Running from workspace member directory should also detect the untracked file.\n    p.cargo(\"package --list --no-metadata\")\n        .cwd(\"inner\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] 1 files in the working directory contain changes that were not yet committed into git:\n\nuntracked\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dirty_file_outside_pkg_root_considered_dirty() {\n    if !symlink_supported() {\n        return;\n    }\n    let main_outside_pkg_root = paths::root().join(\"main.rs\");\n    let (p, repo) = git::new_repo(\"foo\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"isengard\"]\n                resolver = \"2\"\n                [workspace.package]\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"lib.rs\", r#\"compile_error!(\"you shall not pass\")\"#)\n        .file(\"LICENSE\", \"before\")\n        .file(\"README.md\", \"before\")\n        .file(\n            \"isengard/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"isengard\"\n                edition.workspace = true\n                homepage = \"saruman\"\n                description = \"saruman\"\n                license-file = \"../LICENSE\"\n            \"#,\n        )\n        .file(\"original-dir/file\", \"before\")\n        .symlink(\"lib.rs\", \"isengard/src/lib.rs\")\n        .symlink(\"README.md\", \"isengard/README.md\")\n        .file(&main_outside_pkg_root, \"fn main() {}\")\n        .symlink(&main_outside_pkg_root, \"isengard/src/main.rs\")\n        .symlink_dir(\"original-dir\", \"isengard/symlink-dir\")\n    });\n    git::commit(&repo);\n\n    // Changing files outside pkg root under situations below should be treated\n    // as dirty. `cargo package` is expected to fail on VCS status check.\n    //\n    // * Changes in files outside package root that source files symlink to\n    p.change_file(\"README.md\", \"after\");\n    p.change_file(\"lib.rs\", \"pub fn after() {}\");\n    p.change_file(\"original-dir/file\", \"after\");\n    // * Changes in files outside pkg root that `license-file`/`readme` point to\n    p.change_file(\"LICENSE\", \"after\");\n    // * When workspace root manifest has changed,\n    //   no matter whether workspace inheritance is involved.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [workspace]\n            members = [\"isengard\"]\n            resolver = \"2\"\n            [workspace.package]\n            edition = \"2021\"\n        \"#,\n    );\n    // Changes in files outside git workdir won't affect VCS status check\n    p.change_file(\n        &main_outside_pkg_root,\n        r#\"fn main() { eprintln!(\"after\"); }\"#,\n    );\n\n    // Ensure dirty files be reported.\n    p.cargo(\"package --workspace --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] 5 files in the working directory contain changes that were not yet committed into git:\n\nCargo.toml\nLICENSE\nREADME.md\nlib.rs\noriginal-dir/file\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --workspace --no-verify --allow-dirty\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] isengard v0.0.0 ([ROOT]/foo/isengard)\n[PACKAGED] 9 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n\n    let cargo_toml = str![[r##\"\n...\n[package]\nedition = \"2021\"\n...\n\n\"##]];\n\n    let f = File::open(&p.root().join(\"target/package/isengard-0.0.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"isengard-0.0.0.crate\",\n        &[\n            \".cargo_vcs_info.json\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            \"src/main.rs\",\n            \"symlink-dir/file\",\n            \"Cargo.lock\",\n            \"LICENSE\",\n            \"README.md\",\n        ],\n        [\n            (\"src/lib.rs\", str![\"pub fn after() {}\"]),\n            (\"src/main.rs\", str![r#\"fn main() { eprintln!(\"after\"); }\"#]),\n            (\"symlink-dir/file\", str![\"after\"]),\n            (\"README.md\", str![\"after\"]),\n            (\"LICENSE\", str![\"after\"]),\n            (\"Cargo.toml\", cargo_toml),\n        ],\n    );\n}\n\n#[cargo_test]\nfn dirty_file_outside_pkg_root_inside_submodule() {\n    if !symlink_supported() {\n        return;\n    }\n    let (p, repo) = git::new_repo(\"foo\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"isengard\"]\n                resolver = \"2\"\n            \"#,\n        )\n        .file(\n            \"isengard/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"isengard\"\n                edition = \"2015\"\n                homepage = \"saruman\"\n                description = \"saruman\"\n                license = \"ISC\"\n            \"#,\n        )\n        .file(\"isengard/src/lib.rs\", \"\")\n    });\n    let submodule = git::new(\"submodule\", |p| {\n        p.no_manifest().file(\"file.txt\", \"from-submodule\")\n    });\n    git::add_submodule(\n        &repo,\n        submodule.root().to_url().as_ref(),\n        Path::new(\"submodule\"),\n    );\n    p.symlink(\"submodule/file.txt\", \"isengard/src/file.txt\");\n    git::add(&repo);\n    git::commit(&repo);\n    p.change_file(\"submodule/file.txt\", \"changed\");\n\n    p.cargo(\"package --workspace --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] 1 files in the working directory contain changes that were not yet committed into git:\n\nisengard/src/file.txt\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn issue_13695_allow_dirty_vcs_info() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            description = \"foo\"\n            license = \"foo\"\n            documentation = \"foo\"\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let repo = git::init(&p.root());\n    // Initial commit, with no files added.\n    git::commit(&repo);\n\n    // Allowing a dirty worktree results in the vcs file still being included.\n    p.cargo(\"package --allow-dirty\").run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.1.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.1.0.crate\",\n        &[\n            \".cargo_vcs_info.json\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            \"Cargo.lock\",\n        ],\n        [(\n            \".cargo_vcs_info.json\",\n            str![[r#\"\n{\n  \"git\": {\n    \"dirty\": true,\n    \"sha1\": \"[..]\"\n  },\n  \"path_in_vcs\": \"\"\n}\n\"#]]\n            .is_json(),\n        )],\n    );\n\n    // Listing provides a consistent result.\n    p.cargo(\"package --list --allow-dirty\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/lib.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn issue_13695_allowing_dirty_vcs_info_but_clean() {\n    let p = project().build();\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            description = \"foo\"\n            license = \"foo\"\n            documentation = \"foo\"\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Allowing a dirty worktree despite it being clean.\n    p.cargo(\"package --allow-dirty\").run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.1.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.1.0.crate\",\n        &[\n            \".cargo_vcs_info.json\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            \"Cargo.lock\",\n        ],\n        [(\n            \".cargo_vcs_info.json\",\n            str![[r#\"\n{\n  \"git\": {\n    \"sha1\": \"[..]\"\n  },\n  \"path_in_vcs\": \"\"\n}\n\"#]]\n            .is_json(),\n        )],\n    );\n}\n\n#[cargo_test]\nfn issue_14354_allowing_dirty_bare_commit() {\n    let p = project().build();\n    // Init a bare commit git repo\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            description = \"foo\"\n            license = \"foo\"\n            documentation = \"foo\"\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\");\n\n    p.cargo(\"package --allow-dirty\").run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.1.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.1.0.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\", \"Cargo.lock\"],\n        (),\n    );\n}\n\n#[cargo_test]\nfn generated_manifest() {\n    registry::alt_init();\n    Package::new(\"abc\", \"1.0.0\").publish();\n    Package::new(\"def\", \"1.0.0\").alternative(true).publish();\n    Package::new(\"ghi\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                exclude = [\"*.txt\"]\n                license = \"MIT\"\n                description = \"foo\"\n\n                [package.metadata]\n                foo = 'bar'\n\n                [workspace]\n\n                [dependencies]\n                bar = { path = \"bar\", version = \"0.1\" }\n                def = { version = \"1.0\", registry = \"alternative\" }\n                ghi = \"1.0\"\n                abc = \"1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --no-verify\").run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    let rewritten_toml = str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\nexclude = [\"*.txt\"]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\nreadme = false\nlicense = \"MIT\"\n\n[package.metadata]\nfoo = \"bar\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\n[dependencies.abc]\nversion = \"1.0\"\n\n[dependencies.bar]\nversion = \"0.1\"\n\n[dependencies.def]\nversion = \"1.0\"\nregistry-index = \"[ROOTURL]/alternative-registry\"\n\n[dependencies.ghi]\nversion = \"1.0\"\n\n\"##]];\n\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        [(\"Cargo.toml\", rewritten_toml)],\n    );\n}\n\n#[cargo_test]\nfn ignore_workspace_specifier() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                authors = []\n\n                [workspace]\n\n                [dependencies]\n                bar = { path = \"bar\", version = \"0.1\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"..\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --no-verify\").cwd(\"bar\").run();\n\n    let f = File::open(&p.root().join(\"target/package/bar-0.1.0.crate\")).unwrap();\n    let rewritten_toml = str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"bar\"\nversion = \"0.1.0\"\nauthors = []\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\nreadme = false\n\n[lib]\nname = \"bar\"\npath = \"src/lib.rs\"\n\n\"##]];\n    validate_crate_contents(\n        f,\n        \"bar-0.1.0.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\", \"Cargo.lock\"],\n        [(\"Cargo.toml\", rewritten_toml)],\n    );\n}\n\n#[cargo_test]\nfn package_two_kinds_of_deps() {\n    Package::new(\"other\", \"1.0.0\").publish();\n    Package::new(\"other1\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                other = \"1.0\"\n                other1 = { version = \"1.0\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --no-verify\").run();\n}\n\n#[cargo_test]\nfn package_should_use_build_cache() {\n    Package::new(\"other\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                other = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Build once so that the build cache is populated\n    p.cargo(\"build\").run();\n\n    // Run package and verify we do not rebuild the `other` crate\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[UPDATING] `dummy-registry` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn package_public_dep() {\n    Package::new(\"bar\", \"1.0.0\").publish();\n    Package::new(\"baz\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format! {\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = {{ version = \"1.0.0\", public = true }}\n\n                [target.{host}.dependencies]\n                baz = {{ version = \"1.0.0\", public = true }}\n            \"#,\n                host = rustc_host()\n            },\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    let rewritten_toml = str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\nreadme = false\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\n[dependencies.bar]\nversion = \"1.0.0\"\n\n[target.[HOST_TARGET].dependencies.baz]\nversion = \"1.0.0\"\n\n\"##]];\n    verify(&p, \"package\", rewritten_toml);\n\n    let rewritten_toml = str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\nreadme = false\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\n[dependencies.bar]\nversion = \"1.0.0\"\npublic = true\n\n[target.[HOST_TARGET].dependencies.baz]\nversion = \"1.0.0\"\npublic = true\n\n\"##]];\n    verify(&p, \"package -Zpublic-dependency\", rewritten_toml);\n\n    fn verify(p: &cargo_test_support::Project, cmd: &str, rewritten_toml: impl IntoData) {\n        p.cargo(cmd)\n            .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n            .run();\n        let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n        validate_crate_contents(\n            f,\n            \"foo-0.0.1.crate\",\n            &[\"Cargo.toml\", \"Cargo.toml.orig\", \"Cargo.lock\", \"src/main.rs\"],\n            [(\"Cargo.toml\", rewritten_toml)],\n        );\n    }\n}\n\n#[cargo_test]\nfn test_edition() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"edition\"]\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2018\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\" \"#)\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n...\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]--edition=2018 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn edition_with_metadata() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"2018\"\n\n                [package.metadata.docs.rs]\n                features = [\"foobar\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\").run();\n}\n\n#[cargo_test]\nfn test_edition_malformed() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                edition = \"chicken\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\" \"#)\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  failed to parse the `edition` key\n\nCaused by:\n  supported edition values are `2015`, `2018`, `2021`, or `2024`, but `chicken` is unknown\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_edition_from_the_future() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"[package]\n                edition = \"2038\"\n                name = \"foo\"\n                version = \"99.99.99\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  failed to parse the `edition` key\n\nCaused by:\n  this version of Cargo is older than the `2038` edition, and only supports `2015`, `2018`, `2021`, and `2024` editions.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn do_not_package_if_src_was_modified() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\"dir/foo.txt\", \"\")\n        .file(\"bar.txt\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                use std::fs;\n\n                fn main() {\n                    fs::write(\"src/generated.txt\",\n                        \"Hello, world of generated files.\"\n                    ).expect(\"failed to create file\");\n                    fs::remove_file(\"dir/foo.txt\").expect(\"failed to remove file\");\n                    fs::remove_dir(\"dir\").expect(\"failed to remove dir\");\n                    fs::write(\"bar.txt\", \"updated content\").expect(\"failed to update\");\n                    fs::create_dir(\"new-dir\").expect(\"failed to create dir\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] failed to verify package tarball\n\nCaused by:\n  Source directory was modified by build.rs during cargo publish. Build scripts should not modify anything outside of OUT_DIR.\n  Changed: [ROOT]/foo/target/package/foo-0.0.1/bar.txt\n  Added: [ROOT]/foo/target/package/foo-0.0.1/new-dir\n  \t[ROOT]/foo/target/package/foo-0.0.1/src/generated.txt\n  Removed: [ROOT]/foo/target/package/foo-0.0.1/dir\n  \t[ROOT]/foo/target/package/foo-0.0.1/dir/foo.txt\n\n  To proceed despite this, pass the `--no-verify` flag.\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --no-verify\").run();\n}\n\n#[cargo_test]\nfn package_with_select_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [features]\n                required = []\n                optional = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"#[cfg(not(feature = \\\"required\\\"))]\n             compile_error!(\\\"This crate requires `required` feature!\\\");\n             fn main() {}\",\n        )\n        .build();\n\n    p.cargo(\"package --features required\").run();\n}\n\n#[cargo_test]\nfn package_with_all_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [features]\n                required = []\n                optional = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"#[cfg(not(feature = \\\"required\\\"))]\n             compile_error!(\\\"This crate requires `required` feature!\\\");\n             fn main() {}\",\n        )\n        .build();\n\n    p.cargo(\"package --all-features\").run();\n}\n\n#[cargo_test]\nfn package_no_default_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [features]\n                default = [\"required\"]\n                required = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"#[cfg(not(feature = \\\"required\\\"))]\n             compile_error!(\\\"This crate requires `required` feature!\\\");\n             fn main() {}\",\n        )\n        .build();\n\n    p.cargo(\"package --no-default-features\")\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] This crate requires `required` feature!\n...\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn include_cargo_toml_implicit() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            include = [\"src/lib.rs\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --list\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/lib.rs\n\n\"#]])\n        .run();\n}\n\nfn include_exclude_test(include: &str, exclude: &str, files: &[&str], expected: &str) {\n    let mut pb = project().file(\n        \"Cargo.toml\",\n        &format!(\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"foo\"\n            documentation = \"foo\"\n            homepage = \"foo\"\n            repository = \"foo\"\n            include = {}\n            exclude = {}\n            \"#,\n            include, exclude\n        ),\n    );\n    for file in files {\n        pb = pb.file(file, \"\");\n    }\n    let p = pb.build();\n\n    p.cargo(\"package --list\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(expected)\n        .run();\n    p.root().rm_rf();\n}\n\n#[cargo_test]\nfn package_include_ignore_only() {\n    // Test with a gitignore pattern that fails to parse with glob.\n    // This is a somewhat nonsense pattern, but is an example of something git\n    // allows and glob does not.\n    assert!(glob::Pattern::new(\"src/abc**\").is_err());\n\n    include_exclude_test(\n        r#\"[\"Cargo.toml\", \"src/abc**\", \"src/lib.rs\"]\"#,\n        \"[]\",\n        &[\"src/lib.rs\", \"src/abc1.rs\", \"src/abc2.rs\", \"src/abc/mod.rs\"],\n        \"Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         src/abc/mod.rs\\n\\\n         src/abc1.rs\\n\\\n         src/abc2.rs\\n\\\n         src/lib.rs\\n\\\n         \",\n    )\n}\n\n#[cargo_test]\nfn gitignore_patterns() {\n    include_exclude_test(\n        r#\"[\"Cargo.toml\", \"foo\"]\"#, // include\n        \"[]\",\n        &[\"src/lib.rs\", \"foo\", \"a/foo\", \"a/b/foo\", \"x/foo/y\", \"bar\"],\n        \"Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         a/b/foo\\n\\\n         a/foo\\n\\\n         foo\\n\\\n         x/foo/y\\n\\\n         \",\n    );\n\n    include_exclude_test(\n        r#\"[\"Cargo.toml\", \"/foo\"]\"#, // include\n        \"[]\",\n        &[\"src/lib.rs\", \"foo\", \"a/foo\", \"a/b/foo\", \"x/foo/y\", \"bar\"],\n        \"Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         foo\\n\\\n         \",\n    );\n\n    include_exclude_test(\n        \"[]\",\n        r#\"[\"foo/\"]\"#, // exclude\n        &[\"src/lib.rs\", \"foo\", \"a/foo\", \"x/foo/y\", \"bar\"],\n        \"Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         a/foo\\n\\\n         bar\\n\\\n         foo\\n\\\n         src/lib.rs\\n\\\n         \",\n    );\n\n    include_exclude_test(\n        \"[]\",\n        r#\"[\"*.txt\", \"[ab]\", \"[x-z]\"]\"#, // exclude\n        &[\n            \"src/lib.rs\",\n            \"foo.txt\",\n            \"bar/foo.txt\",\n            \"other\",\n            \"a\",\n            \"b\",\n            \"c\",\n            \"x\",\n            \"y\",\n            \"z\",\n        ],\n        \"Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         c\\n\\\n         other\\n\\\n         src/lib.rs\\n\\\n         \",\n    );\n\n    include_exclude_test(\n        r#\"[\"Cargo.toml\", \"**/foo/bar\"]\"#, // include\n        \"[]\",\n        &[\"src/lib.rs\", \"a/foo/bar\", \"foo\", \"bar\"],\n        \"Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         a/foo/bar\\n\\\n         \",\n    );\n\n    include_exclude_test(\n        r#\"[\"Cargo.toml\", \"foo/**\"]\"#, // include\n        \"[]\",\n        &[\"src/lib.rs\", \"a/foo/bar\", \"foo/x/y/z\"],\n        \"Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         foo/x/y/z\\n\\\n         \",\n    );\n\n    include_exclude_test(\n        r#\"[\"Cargo.toml\", \"a/**/b\"]\"#, // include\n        \"[]\",\n        &[\"src/lib.rs\", \"a/b\", \"a/x/b\", \"a/x/y/b\"],\n        \"Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         a/b\\n\\\n         a/x/b\\n\\\n         a/x/y/b\\n\\\n         \",\n    );\n}\n\n#[cargo_test]\nfn gitignore_negate() {\n    include_exclude_test(\n        r#\"[\"Cargo.toml\", \"*.rs\", \"!foo.rs\", \"\\\\!important\"]\"#, // include\n        \"[]\",\n        &[\"src/lib.rs\", \"foo.rs\", \"!important\"],\n        \"!important\\n\\\n         Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         src/lib.rs\\n\\\n         \",\n    );\n\n    // NOTE: This is unusual compared to git. Git treats `src/` as a\n    // short-circuit which means rules like `!src/foo.rs` would never run.\n    // However, because Cargo only works by iterating over *files*, it doesn't\n    // short-circuit.\n    include_exclude_test(\n        r#\"[\"Cargo.toml\", \"src/\", \"!src/foo.rs\"]\"#, // include\n        \"[]\",\n        &[\"src/lib.rs\", \"src/foo.rs\"],\n        \"Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         src/lib.rs\\n\\\n         \",\n    );\n\n    include_exclude_test(\n        r#\"[\"Cargo.toml\", \"src/*.rs\", \"!foo.rs\"]\"#, // include\n        \"[]\",\n        &[\"src/lib.rs\", \"foo.rs\", \"src/foo.rs\", \"src/bar/foo.rs\"],\n        \"Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         src/lib.rs\\n\\\n         \",\n    );\n\n    include_exclude_test(\n        \"[]\",\n        r#\"[\"*.rs\", \"!foo.rs\", \"\\\\!important\"]\"#, // exclude\n        &[\"src/lib.rs\", \"foo.rs\", \"!important\"],\n        \"Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         foo.rs\\n\\\n         \",\n    );\n}\n\n#[cargo_test]\nfn exclude_dot_files_and_directories_by_default() {\n    include_exclude_test(\n        \"[]\",\n        \"[]\",\n        &[\"src/lib.rs\", \".dotfile\", \".dotdir/file\"],\n        \"Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         src/lib.rs\\n\\\n         \",\n    );\n\n    include_exclude_test(\n        r#\"[\"Cargo.toml\", \"src/lib.rs\", \".dotfile\", \".dotdir/file\"]\"#,\n        \"[]\",\n        &[\"src/lib.rs\", \".dotfile\", \".dotdir/file\"],\n        \".dotdir/file\\n\\\n         .dotfile\\n\\\n         Cargo.lock\\n\\\n         Cargo.toml\\n\\\n         Cargo.toml.orig\\n\\\n         src/lib.rs\\n\\\n         \",\n    );\n}\n\n#[cargo_test]\nfn empty_readme_path() {\n    // fail if `readme` is empty.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n            readme = \"\"\n            license = \"MIT\"\n            description = \"foo\"\n            homepage = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] readme `` does not appear to exist (relative to `[ROOT]/foo`).\nPlease update the readme setting in the manifest at `[ROOT]/foo/Cargo.toml`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_readme_path() {\n    // fail if `readme` path is invalid.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n            readme = \"DOES-NOT-EXIST\"\n            license = \"MIT\"\n            description = \"foo\"\n            homepage = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] readme `DOES-NOT-EXIST` does not appear to exist (relative to `[ROOT]/foo`).\nPlease update the readme setting in the manifest at `[ROOT]/foo/Cargo.toml`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn readme_or_license_file_is_dir() {\n    // Test error when `readme` or `license-file` is a directory, not a file.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n            readme = \"./src\"\n            license-file = \"./src\"\n            description = \"foo\"\n            homepage = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] license-file `./src` does not appear to exist (relative to `[ROOT]/foo`).\nPlease update the license-file setting in the manifest at `[ROOT]/foo/Cargo.toml`.\nreadme `./src` does not appear to exist (relative to `[ROOT]/foo`).\nPlease update the readme setting in the manifest at `[ROOT]/foo/Cargo.toml`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn empty_license_file_path() {\n    // fail if license-file is empty.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n            license-file = \"\"\n            description = \"foo\"\n            homepage = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no license or license-file\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[ERROR] license-file `` does not appear to exist (relative to `[ROOT]/foo`).\nPlease update the license-file setting in the manifest at `[ROOT]/foo/Cargo.toml`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_license_file_path() {\n    // Test warning when license-file points to a non-existent file.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n            license-file = \"does-not-exist\"\n            description = \"foo\"\n            homepage = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] license-file `does-not-exist` does not appear to exist (relative to `[ROOT]/foo`).\nPlease update the license-file setting in the manifest at `[ROOT]/foo/Cargo.toml`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn license_file_implicit_include() {\n    // license-file should be automatically included even if not listed.\n    let p = git::new(\"foo\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n            license-file = \"subdir/LICENSE\"\n            description = \"foo\"\n            homepage = \"foo\"\n            include = [\"src\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"subdir/LICENSE\", \"license text\")\n    });\n\n    p.cargo(\"package --list\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/lib.rs\nsubdir/LICENSE\n\n\"#]])\n        .with_stderr_data(\"\")\n        .run();\n\n    p.cargo(\"package --no-verify -v\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v1.0.0 ([ROOT]/foo)\n[ARCHIVING] .cargo_vcs_info.json\n[ARCHIVING] Cargo.lock\n[ARCHIVING] Cargo.toml\n[ARCHIVING] Cargo.toml.orig\n[ARCHIVING] src/lib.rs\n[ARCHIVING] subdir/LICENSE\n[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n    let f = File::open(&p.root().join(\"target/package/foo-1.0.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-1.0.0.crate\",\n        &[\n            \".cargo_vcs_info.json\",\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"subdir/LICENSE\",\n            \"src/lib.rs\",\n        ],\n        [(\"subdir/LICENSE\", \"license text\")],\n    );\n}\n\n#[cargo_test]\nfn relative_license_included() {\n    // license-file path outside of package will copy into root.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n            license-file = \"../LICENSE\"\n            description = \"foo\"\n            homepage = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"../LICENSE\", \"license text\")\n        .build();\n\n    p.cargo(\"package --list\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nLICENSE\nsrc/lib.rs\n\n\"#]])\n        .with_stderr_data(\"\")\n        .run();\n\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v1.0.0 ([ROOT]/foo)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v1.0.0 ([ROOT]/foo)\n[COMPILING] foo v1.0.0 ([ROOT]/foo/target/package/foo-1.0.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    let f = File::open(&p.root().join(\"target/package/foo-1.0.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-1.0.0.crate\",\n        &[\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"LICENSE\",\n            \"src/lib.rs\",\n            \"Cargo.lock\",\n        ],\n        [(\"LICENSE\", \"license text\")],\n    );\n    let manifest =\n        std::fs::read_to_string(p.root().join(\"target/package/foo-1.0.0/Cargo.toml\")).unwrap();\n    assert!(manifest.contains(\"license-file = \\\"LICENSE\\\"\"));\n    let orig =\n        std::fs::read_to_string(p.root().join(\"target/package/foo-1.0.0/Cargo.toml.orig\")).unwrap();\n    assert!(orig.contains(\"license-file = \\\"../LICENSE\\\"\"));\n}\n\n#[cargo_test]\nfn relative_license_include_collision() {\n    // Can't copy a relative license-file if there is a file with that name already.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            edition = \"2015\"\n            license-file = \"../LICENSE\"\n            description = \"foo\"\n            homepage = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"../LICENSE\", \"outer license\")\n        .file(\"LICENSE\", \"inner license\")\n        .build();\n\n    p.cargo(\"package --list\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nLICENSE\nsrc/lib.rs\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] license-file `../LICENSE` appears to be a path outside of the package, but there is already a file named `LICENSE` in the root of the package. The archived crate will contain the copy in the root of the package. Update the license-file to point to the path relative to the root of the package to remove this warning.\n\n\"#]])\n        .run();\n\n    p.cargo(\"package\").with_stderr_data(str![[r#\"\n[WARNING] license-file `../LICENSE` appears to be a path outside of the package, but there is already a file named `LICENSE` in the root of the package. The archived crate will contain the copy in the root of the package. Update the license-file to point to the path relative to the root of the package to remove this warning.\n[PACKAGING] foo v1.0.0 ([ROOT]/foo)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v1.0.0 ([ROOT]/foo)\n[COMPILING] foo v1.0.0 ([ROOT]/foo/target/package/foo-1.0.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n    let f = File::open(&p.root().join(\"target/package/foo-1.0.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-1.0.0.crate\",\n        &[\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"LICENSE\",\n            \"src/lib.rs\",\n            \"Cargo.lock\",\n        ],\n        [(\"LICENSE\", \"inner license\")],\n    );\n    let manifest = read_to_string(p.root().join(\"target/package/foo-1.0.0/Cargo.toml\")).unwrap();\n    assert!(manifest.contains(\"license-file = \\\"LICENSE\\\"\"));\n    let orig = read_to_string(p.root().join(\"target/package/foo-1.0.0/Cargo.toml.orig\")).unwrap();\n    assert!(orig.contains(\"license-file = \\\"../LICENSE\\\"\"));\n}\n\n#[cargo_test]\n#[cfg(not(windows))] // Don't want to create invalid files on Windows.\nfn package_restricted_windows() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            homepage = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub mod con;\\npub mod aux;\")\n        .file(\"src/con.rs\", \"pub fn f() {}\")\n        .file(\"src/aux/mod.rs\", \"pub fn f() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        // use unordered here because the order of the warning is different on each platform.\n        .with_stderr_data(\n            str![[r#\"\n[WARNING] file src/con.rs is a reserved Windows filename, it will not work on Windows platforms\n[WARNING] file src/aux/mod.rs is a reserved Windows filename, it will not work on Windows platforms\n[PACKAGING] foo v0.1.0 ([ROOT]/foo)\n[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.1.0 ([ROOT]/foo)\n[COMPILING] foo v0.1.0 ([ROOT]/foo/target/package/foo-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn finds_git_in_parent() {\n    // Test where `Cargo.toml` is not in the root of the git repo.\n    let repo_path = paths::root().join(\"repo\");\n    fs::create_dir(&repo_path).unwrap();\n    let p = project()\n        .at(\"repo/foo\")\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    let repo = git::init(&repo_path);\n    git::add(&repo);\n    git::commit(&repo);\n    p.change_file(\"ignoreme\", \"\");\n    p.change_file(\"ignoreme2\", \"\");\n    p.cargo(\"package --list --allow-dirty\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nignoreme\nignoreme2\nsrc/lib.rs\n\n\"#]])\n        .run();\n\n    p.change_file(\".gitignore\", \"ignoreme\");\n    p.cargo(\"package --list --allow-dirty\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\n.gitignore\nCargo.lock\nCargo.toml\nCargo.toml.orig\nignoreme2\nsrc/lib.rs\n\n\"#]])\n        .run();\n\n    fs::write(repo_path.join(\".gitignore\"), \"ignoreme2\").unwrap();\n    p.cargo(\"package --list --allow-dirty\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\n.gitignore\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/lib.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[cfg(windows)]\nfn reserved_windows_name() {\n    // If we are running on a version of Windows that allows these reserved filenames,\n    // skip this test.\n    if paths::windows_reserved_names_are_allowed() {\n        return;\n    }\n\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"pub mod aux;\")\n        .file(\"src/aux.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies]\n                bar = \"1.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar;\\nfn main() {  }\")\n        .build();\n    p.cargo(\"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] failed to verify package tarball\n\nCaused by:\n  failed to download replaced source registry `crates-io`\n\nCaused by:\n  failed to unpack package `bar v1.0.0 (registry `dummy-registry`)`\n\nCaused by:\n  failed to unpack entry at `bar-1.0.0/src/aux.rs`\n\nCaused by:\n  `bar-1.0.0/src/aux.rs` appears to contain a reserved Windows path, it cannot be extracted on Windows\n\nCaused by:\n  failed to unpack `[ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/src/aux.rs`\n\nCaused by:\n  failed to unpack `bar-1.0.0/src/aux.rs` into `[ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/src/aux.rs`\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn list_with_path_and_lock() {\n    // Allow --list even for something that isn't packageable.\n\n    // Init an empty registry because a versionless path dep will search for\n    // the package on crates.io.\n    registry::init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            homepage = \"foo\"\n\n            [dependencies]\n            bar = {path=\"bar\"}\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --list\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n\n    p.cargo(\"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to verify manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  all dependencies must have a version requirement specified when packaging.\n  dependency `bar` does not specify a version\n  Note: The packaged dependency will use the version from crates.io,\n  the `path` specification will be removed from the dependency declaration.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn long_file_names() {\n    // Filenames over 100 characters require a GNU extension tarfile.\n    // See #8453.\n\n    registry::init();\n    let long_name = concat!(\n        \"012345678901234567890123456789012345678901234567890123456789\",\n        \"012345678901234567890123456789012345678901234567890123456789\",\n        \"012345678901234567890123456789012345678901234567890123456789\"\n    );\n    if cfg!(windows) {\n        // Long paths on Windows require a special registry entry that is\n        // disabled by default (even on Windows 10).\n        // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file\n        // If the directory where Cargo runs happens to be more than 80 characters\n        // long, then it will bump into this limit.\n        //\n        // First create a directory to account for various paths Cargo will\n        // be using in the target directory (such as \"target/package/foo-0.1.0\").\n        let test_path = paths::root().join(\"test-dir-probe-long-path-support\");\n        test_path.mkdir_p();\n        let test_path = test_path.join(long_name);\n        if let Err(e) = File::create(&test_path) {\n            // write to stderr directly to avoid output from being captured\n            // and always display text, even without --no-capture\n            use std::io::Write;\n            writeln!(\n                std::io::stderr(),\n                \"\\nSkipping long_file_names test, this OS or filesystem does not \\\n                appear to support long file paths: {:?}\\n{:?}\",\n                e,\n                test_path\n            )\n            .unwrap();\n            return;\n        }\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            homepage = \"foo\"\n\n            [dependencies]\n            \"#,\n        )\n        .file(long_name, \"something\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\").run();\n    p.cargo(\"package --list\").with_stdout_data(str![[r#\"\n012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn reproducible_output() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                exclude = [\"*.txt\"]\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"package\").run();\n    assert!(p.root().join(\"target/package/foo-0.0.1.crate\").is_file());\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    let decoder = GzDecoder::new(f);\n    let mut archive = Archive::new(decoder);\n\n    // Hardcoded value be removed once alexcrichton/tar-rs#420 is merged and released.\n    // See also rust-lang/cargo#16237\n    const DETERMINISTIC_TIMESTAMP: u64 = 1153704088;\n    for ent in archive.entries().unwrap() {\n        let ent = ent.unwrap();\n        println!(\"checking {:?}\", ent.path());\n        let header = ent.header();\n        assert_eq!(header.mode().unwrap(), 0o644);\n        assert!(header.mtime().unwrap() == DETERMINISTIC_TIMESTAMP);\n        assert_eq!(header.username().unwrap().unwrap(), \"\");\n        assert_eq!(header.groupname().unwrap().unwrap(), \"\");\n    }\n}\n\n#[cargo_test]\nfn package_with_resolver_and_metadata() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                resolver = '2'\n\n                [package.metadata.docs.rs]\n                all-features = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\").run();\n}\n\n#[cargo_test]\nfn deleted_git_working_tree() {\n    // When deleting a file, but not staged, cargo should ignore the file.\n    let (p, repo) = git::new_repo(\"foo\", |p| {\n        p.file(\"src/lib.rs\", \"\").file(\"src/main.rs\", \"fn main() {}\")\n    });\n    p.root().join(\"src/lib.rs\").rm_rf();\n    p.cargo(\"package --allow-dirty --list\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n    p.cargo(\"package --allow-dirty\").run();\n    let mut index = t!(repo.index());\n    t!(index.remove(Path::new(\"src/lib.rs\"), 0));\n    t!(index.write());\n    p.cargo(\"package --allow-dirty --list\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n    p.cargo(\"package --allow-dirty\").run();\n}\n\n#[cargo_test]\nfn package_in_workspace_not_found() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"bar\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"baz\"\n            \"#,\n        )\n        .file(\"baz/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package -p doesnt-exist\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `doesnt-exist` did not match any packages\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn in_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"bar\"\n                workspace = \"..\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package --workspace\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] bar v0.0.1 ([ROOT]/foo/bar)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] bar v0.0.1 ([ROOT]/foo/target/package/bar-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(p.root().join(\"target/package/foo-0.0.1.crate\").is_file());\n    assert!(p.root().join(\"target/package/bar-0.0.1.crate\").is_file());\n}\n\n#[cargo_test]\nfn workspace_noconflict_readme() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"README.md\", \"workspace readme\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                repository = \"https://github.com/bar/bar\"\n                authors = []\n                license = \"MIT\"\n                description = \"bar\"\n                readme = \"../README.md\"\n                workspace = \"..\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/example/README.md\", \"# example readmdBar\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] bar v0.0.1 ([ROOT]/foo/bar)\n[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] bar v0.0.1 ([ROOT]/foo/target/package/bar-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_conflict_readme() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"README.md\", \"workspace readme\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                repository = \"https://github.com/bar/bar\"\n                authors = []\n                license = \"MIT\"\n                description = \"bar\"\n                readme = \"../README.md\"\n                workspace = \"..\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/README.md\", \"# workspace member: Bar\")\n        .build();\n\n    p.cargo(\"package\").with_stderr_data(str![[r#\"\n[WARNING] readme `../README.md` appears to be a path outside of the package, but there is already a file named `README.md` in the root of the package. The archived crate will contain the copy in the root of the package. Update the readme to point to the path relative to the root of the package to remove this warning.\n[PACKAGING] bar v0.0.1 ([ROOT]/foo/bar)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] bar v0.0.1 ([ROOT]/foo/target/package/bar-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn workspace_overrides_resolver() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --no-verify -p bar -p baz\").run();\n\n    let f = File::open(&p.root().join(\"target/package/bar-0.1.0.crate\")).unwrap();\n    let rewritten_toml = str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2021\"\nname = \"bar\"\nversion = \"0.1.0\"\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\nreadme = false\nresolver = \"1\"\n\n[lib]\nname = \"bar\"\npath = \"src/lib.rs\"\n\n\"##]];\n    validate_crate_contents(\n        f,\n        \"bar-0.1.0.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\", \"Cargo.lock\"],\n        [(\"Cargo.toml\", rewritten_toml)],\n    );\n\n    // When the crate has the same implicit resolver as the workspace it is not overridden\n    let f = File::open(&p.root().join(\"target/package/baz-0.1.0.crate\")).unwrap();\n    let rewritten_toml = str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"baz\"\nversion = \"0.1.0\"\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\nreadme = false\n\n[lib]\nname = \"baz\"\npath = \"src/lib.rs\"\n\n\"##]];\n    validate_crate_contents(\n        f,\n        \"baz-0.1.0.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\", \"Cargo.lock\"],\n        [(\"Cargo.toml\", rewritten_toml)],\n    );\n}\n\nfn verify_packaged_status_line(\n    output: cargo_test_support::RawOutput,\n    num_files: usize,\n    uncompressed_size: u64,\n    compressed_size: u64,\n) {\n    use cargo::util::HumanBytes;\n\n    let stderr = String::from_utf8(output.stderr).unwrap();\n    let mut packaged_lines = stderr\n        .lines()\n        .filter(|line| line.trim().starts_with(\"Packaged\"));\n    let packaged_line = packaged_lines\n        .next()\n        .expect(\"`Packaged` status line should appear in stderr\");\n    assert!(\n        packaged_lines.next().is_none(),\n        \"Only one `Packaged` status line should appear in stderr\"\n    );\n    let size_info = packaged_line.trim().trim_start_matches(\"Packaged\").trim();\n    let uncompressed = HumanBytes(uncompressed_size);\n    let compressed = HumanBytes(compressed_size);\n    let expected = format!(\"{num_files} files, {uncompressed:.1} ({compressed:.1} compressed)\");\n    assert_eq!(size_info, expected);\n}\n\n#[cargo_test]\nfn basic_filesizes() {\n    let cargo_toml_orig_contents = r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                exclude = [\"*.txt\"]\n                license = \"MIT\"\n                description = \"foo\"\n                homepage = \"https://example.com/\"\n            \"#;\n    let main_rs_contents = r#\"fn main() { println!(\"🦀\"); }\"#;\n    let cargo_toml_contents = format!(\n        r#\"{}\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\nexclude = [\"*.txt\"]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\nhomepage = \"https://example.com/\"\nreadme = false\nlicense = \"MIT\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\"#,\n        cargo::core::manifest::MANIFEST_PREAMBLE\n    );\n    let cargo_lock_contents = r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\n\"#;\n    let p = project()\n        .file(\"Cargo.toml\", cargo_toml_orig_contents)\n        .file(\"src/main.rs\", main_rs_contents)\n        .file(\"src/bar.txt\", \"Ignored text file contents\") // should be ignored when packaging\n        .build();\n\n    let uncompressed_size = (cargo_toml_orig_contents.len()\n        + main_rs_contents.len()\n        + cargo_toml_contents.len()\n        + cargo_lock_contents.len()) as u64;\n    let output = p.cargo(\"package\").run();\n\n    assert!(p.root().join(\"target/package/foo-0.0.1.crate\").is_file());\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    let compressed_size = f.metadata().unwrap().len();\n    verify_packaged_status_line(output, 4, uncompressed_size, compressed_size);\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        [\n            (\"Cargo.lock\", cargo_lock_contents),\n            (\"Cargo.toml\", &cargo_toml_contents),\n            (\"Cargo.toml.orig\", cargo_toml_orig_contents),\n            (\"src/main.rs\", main_rs_contents),\n        ],\n    );\n}\n\n#[cargo_test]\nfn larger_filesizes() {\n    let cargo_toml_orig_contents = r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"https://example.com/\"\n            \"#;\n    let lots_of_crabs = \"🦀\".repeat(1337);\n    let main_rs_contents = format!(r#\"fn main() {{ println!(\"{}\"); }}\"#, lots_of_crabs);\n    let bar_txt_contents = \"This file is relatively incompressible, to increase the compressed\n        package size beyond 1KiB.\n        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt\n        ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation\n        ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in\n        reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur\n        sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est\n        laborum.\";\n    let cargo_toml_contents = format!(\n        r#\"{}\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"https://example.com/\"\nreadme = false\nlicense = \"MIT\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\"#,\n        cargo::core::manifest::MANIFEST_PREAMBLE\n    );\n    let cargo_lock_contents = r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\n\"#;\n    let p = project()\n        .file(\"Cargo.toml\", cargo_toml_orig_contents)\n        .file(\"src/main.rs\", &main_rs_contents)\n        .file(\"src/bar.txt\", bar_txt_contents)\n        .build();\n\n    let uncompressed_size = (cargo_toml_orig_contents.len()\n        + main_rs_contents.len()\n        + cargo_toml_contents.len()\n        + cargo_lock_contents.len()\n        + bar_txt_contents.len()) as u64;\n\n    let output = p.cargo(\"package\").run();\n    assert!(p.root().join(\"target/package/foo-0.0.1.crate\").is_file());\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/bar.txt\nsrc/main.rs\n\n\"#]])\n        .run();\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    let compressed_size = f.metadata().unwrap().len();\n    verify_packaged_status_line(output, 5, uncompressed_size, compressed_size);\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/bar.txt\",\n            \"src/main.rs\",\n        ],\n        [\n            (\"Cargo.lock\", cargo_lock_contents),\n            (\"Cargo.toml\", &cargo_toml_contents),\n            (\"Cargo.toml.orig\", cargo_toml_orig_contents),\n            (\"src/bar.txt\", bar_txt_contents),\n            (\"src/main.rs\", &main_rs_contents),\n        ],\n    );\n}\n\n#[cargo_test]\nfn symlink_filesizes() {\n    if !symlink_supported() {\n        return;\n    }\n\n    let cargo_toml_orig_contents = r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                homepage = \"https://example.com/\"\n            \"#;\n    let lots_of_crabs = \"🦀\".repeat(1337);\n    let main_rs_contents = format!(r#\"fn main() {{ println!(\"{}\"); }}\"#, lots_of_crabs);\n    let bar_txt_contents = \"This file is relatively incompressible, to increase the compressed\n        package size beyond 1KiB.\n        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt\n        ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation\n        ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in\n        reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur\n        sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est\n        laborum.\";\n    let cargo_toml_contents = format!(\n        r#\"{}\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\nhomepage = \"https://example.com/\"\nreadme = false\nlicense = \"MIT\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\"#,\n        cargo::core::manifest::MANIFEST_PREAMBLE\n    );\n    let cargo_lock_contents = r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"foo\"\nversion = \"0.0.1\"\n\"#;\n\n    let p = project()\n        .file(\"Cargo.toml\", cargo_toml_orig_contents)\n        .file(\"src/main.rs\", &main_rs_contents)\n        .file(\"bla/bar.txt\", bar_txt_contents)\n        .symlink(\"src/main.rs\", \"src/main.rs.bak\")\n        .symlink_dir(\"bla\", \"foo\")\n        .build();\n\n    let uncompressed_size = (cargo_toml_orig_contents.len()\n        + main_rs_contents.len() * 2\n        + cargo_toml_contents.len()\n        + cargo_lock_contents.len()\n        + bar_txt_contents.len() * 2) as u64;\n\n    let output = p.cargo(\"package\").run();\n    assert!(p.root().join(\"target/package/foo-0.0.1.crate\").is_file());\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nbla/bar.txt\nfoo/bar.txt\nsrc/main.rs\nsrc/main.rs.bak\n\n\"#]])\n        .run();\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 7 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    let compressed_size = f.metadata().unwrap().len();\n    verify_packaged_status_line(output, 7, uncompressed_size, compressed_size);\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"bla/bar.txt\",\n            \"foo/bar.txt\",\n            \"src/main.rs\",\n            \"src/main.rs.bak\",\n        ],\n        [\n            (\"Cargo.lock\", cargo_lock_contents),\n            (\"Cargo.toml\", &cargo_toml_contents),\n            (\"Cargo.toml.orig\", cargo_toml_orig_contents),\n            (\"bla/bar.txt\", bar_txt_contents),\n            (\"foo/bar.txt\", bar_txt_contents),\n            (\"src/main.rs\", &main_rs_contents),\n            (\"src/main.rs.bak\", &main_rs_contents),\n        ],\n    );\n}\n\n#[cargo_test]\n#[cfg(windows)] // windows is the platform that is most consistently configured for case insensitive filesystems\nfn normalize_case() {\n    let p = project()\n        .file(\"Build.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\"src/Main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bar.txt\", \"\") // should be ignored when packaging\n        .file(\"Examples/ExampleFoo.rs\", \"\")\n        .file(\"Tests/ExplicitPath.rs\", \"\")\n        .build();\n    // Workaround `project()` making a `Cargo.toml` on our behalf\n    std::fs::remove_file(p.root().join(\"Cargo.toml\")).unwrap();\n    std::fs::write(\n        p.root().join(\"cargo.toml\"),\n        r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2018\"\n                authors = []\n                exclude = [\"*.txt\"]\n                license = \"MIT\"\n                description = \"foo\"\n\n                [[test]]\n                name = \"explicitpath\"\n                path = \"tests/explicitpath.rs\"\n            \"#,\n    )\n    .unwrap();\n\n    p.cargo(\"package\").with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] ignoring `package.build` entry `build.rs` as it is not included in the published package\n[WARNING] ignoring binary `foo` as `src/main.rs` is not included in the published package\n[WARNING] ignoring example `ExampleFoo` as `examples/ExampleFoo.rs` is not included in the published package\n[WARNING] ignoring test `ExplicitPath` as `tests/ExplicitPath.rs` is not included in the published package\n[WARNING] ignoring test `explicitpath` as `tests/explicitpath.rs` is not included in the published package\n[PACKAGED] 8 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n    assert!(p.root().join(\"target/package/foo-0.0.1.crate\").is_file());\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\nBuild.rs\nCargo.lock\nCargo.toml\nCargo.toml.orig\nExamples/ExampleFoo.rs\nTests/ExplicitPath.rs\nsrc/Main.rs\nsrc/lib.rs\n\n\"#]])\n        .run();\n    p.cargo(\"package\").with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] ignoring `package.build` entry `build.rs` as it is not included in the published package\n[WARNING] ignoring binary `foo` as `src/main.rs` is not included in the published package\n[WARNING] ignoring example `ExampleFoo` as `examples/ExampleFoo.rs` is not included in the published package\n[WARNING] ignoring test `ExplicitPath` as `tests/ExplicitPath.rs` is not included in the published package\n[WARNING] ignoring test `explicitpath` as `tests/explicitpath.rs` is not included in the published package\n[PACKAGED] 8 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"Build.rs\",\n            \"src/Main.rs\",\n            \"src/lib.rs\",\n            \"Examples/ExampleFoo.rs\",\n            \"Tests/ExplicitPath.rs\",\n        ],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2018\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\nexclude = [\"*.txt\"]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\n#[cfg(target_os = \"linux\")] // linux is generally configured to be case sensitive\nfn mixed_case() {\n    let manifest = r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                exclude = [\"*.txt\"]\n                license = \"MIT\"\n                description = \"foo\"\n            \"#;\n    let p = project()\n        .file(\"Cargo.toml\", manifest)\n        .file(\"cargo.toml\", manifest)\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\"src/bar.txt\", \"\") // should be ignored when packaging\n        .build();\n\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(p.root().join(\"target/package/foo-0.0.1.crate\").is_file());\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        (),\n    );\n}\n\n#[cargo_test]\nfn versionless_package() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                description = \"foo\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.0 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.0 ([ROOT]/foo)\n[COMPILING] foo v0.0.0 ([ROOT]/foo/target/package/foo-0.0.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.0.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        (),\n    );\n}\n\n#[cargo_test]\nfn include_files_called_target_project() {\n    // https://github.com/rust-lang/cargo/issues/12790\n    // files and folders called \"target\" should be included, unless they're the actual target directory\n    let p = init_and_add_inner_target(project())\n        .file(\"target/foo.txt\", \"\")\n        .build();\n\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\ndata/not_target\ndata/target\nderp/not_target/foo.txt\nderp/target/foo.txt\nsrc/main.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn include_files_called_target_git() {\n    // https://github.com/rust-lang/cargo/issues/12790\n    // files and folders called \"target\" should be included, unless they're the actual target directory\n    let (p, repo) = git::new_repo(\"foo\", |p| init_and_add_inner_target(p));\n    // add target folder but not committed.\n    _ = fs::create_dir(p.build_dir()).unwrap();\n    _ = fs::write(p.build_dir().join(\"foo.txt\"), \"\").unwrap();\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\ndata/not_target\ndata/target\nderp/not_target/foo.txt\nderp/target/foo.txt\nsrc/main.rs\n\n\"#]])\n        .run();\n\n    // if target is committed, it should be included.\n    git::add(&repo);\n    git::commit(&repo);\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\ndata/not_target\ndata/target\nderp/not_target/foo.txt\nderp/target/foo.txt\nsrc/main.rs\ntarget/foo.txt\n\n\"#]])\n        .run();\n\n    // Untracked files shouldn't be included, if they are also ignored.\n    _ = fs::write(repo.workdir().unwrap().join(\".gitignore\"), \"target/\").unwrap();\n    git::add(&repo);\n    git::commit(&repo);\n    _ = fs::write(p.build_dir().join(\"untracked.txt\"), \"\").unwrap();\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\n.gitignore\nCargo.lock\nCargo.toml\nCargo.toml.orig\ndata/not_target\ndata/target\nderp/not_target/foo.txt\nderp/target/foo.txt\nsrc/main.rs\ntarget/foo.txt\n\n\"#]])\n        .run();\n}\n\nfn init_and_add_inner_target(p: ProjectBuilder) -> ProjectBuilder {\n    p.file(\n        \"Cargo.toml\",\n        r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n    )\n    .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n    // file called target, should be included\n    .file(\"data/target\", \"\")\n    .file(\"data/not_target\", \"\")\n    // folder called target, should be included\n    .file(\"derp/target/foo.txt\", \"\")\n    .file(\"derp/not_target/foo.txt\", \"\")\n}\n\n#[cargo_test]\nfn build_script_outside_pkg_root() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    authors = []\n    build = \"../t_custom_build/custom_build.rs\"\n    \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    // custom_build.rs does not exist\n    p.cargo(\"package -l\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[ERROR] the source file of build script doesn't appear to exist.\nThis may cause issue during packaging, as modules resolution and resources included via macros are often relative to the path of source files.\nPlease update the `build` setting in the manifest at `[ROOT]/foo/Cargo.toml` and point to a path inside the root of the package.\n\n\"#]])\n        .run();\n\n    // custom_build.rs outside the package root\n    let custom_build_root = paths::root().join(\"t_custom_build\");\n    _ = fs::create_dir(&custom_build_root).unwrap();\n    _ = fs::write(&custom_build_root.join(\"custom_build.rs\"), \"fn main() {}\");\n    p.cargo(\"package -l\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[ERROR] the source file of build script doesn't appear to be a path inside of the package.\nIt is at `[ROOT]/t_custom_build/custom_build.rs`, whereas the root the package is `[ROOT]/foo`.\nThis may cause issue during packaging, as modules resolution and resources included via macros are often relative to the path of source files.\nPlease update the `build` setting in the manifest at `[ROOT]/foo/Cargo.toml` and point to a path inside the root of the package.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn symlink_manifest_path() {\n    // Test `cargo install --manifest-path` pointing through a symlink.\n    if !symlink_supported() {\n        return;\n    }\n    let p = git::new(\"foo\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"foo\", \"1.0.0\"))\n            .file(\"src/main.rs\", \"fn main() {}\")\n            // Triggers discover_git_and_list_files for detecting changed files.\n            .file(\"build.rs\", \"fn main() {}\")\n    });\n    #[cfg(unix)]\n    use std::os::unix::fs::symlink;\n    #[cfg(windows)]\n    use std::os::windows::fs::symlink_dir as symlink;\n\n    let foo_symlink = paths::root().join(\"foo-symlink\");\n    t!(symlink(p.root(), &foo_symlink));\n\n    cargo_process(\"package --no-verify --manifest-path\")\n        .arg(foo_symlink.join(\"Cargo.toml\"))\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v1.0.0 ([ROOT]/foo-symlink)\n[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[cfg(windows)]\nfn normalize_paths() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    readme = \".\\\\docs\\\\README.md\"\n    license-file = \".\\\\docs\\\\LICENSE\"\n    build = \".\\\\src\\\\build.rs\"\n\n    [lib]\n    path = \".\\\\src\\\\lib.rs\"\n\n    [[bin]]\n    name = \"foo\"\n    path = \".\\\\src\\\\bin\\\\foo\\\\main.rs\"\n\n    [[example]]\n    name = \"example_foo\"\n    path = \".\\\\examples\\\\example_foo.rs\"\n\n    [[test]]\n    name = \"test_foo\"\n    path = \".\\\\tests\\\\test_foo.rs\"\n\n    [[bench]]\n    name = \"bench_foo\"\n    path = \".\\\\benches\\\\bench_foo.rs\"\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"docs/README.md\", \"\")\n        .file(\"docs/LICENSE\", \"\")\n        .file(\"src/build.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo/main.rs\", \"fn main() {}\")\n        .file(\"examples/example_foo.rs\", \"fn main() {}\")\n        .file(\"tests/test_foo.rs\", \"fn main() {}\")\n        .file(\"benches/bench_foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 11 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            \"docs/README.md\",\n            \"docs/LICENSE\",\n            \"src/build.rs\",\n            \"src/bin/foo/main.rs\",\n            \"examples/example_foo.rs\",\n            \"tests/test_foo.rs\",\n            \"benches/bench_foo.rs\",\n        ],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = \"src/build.rs\"\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = \"docs/README.md\"\nlicense-file = \"docs/LICENSE\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/bin/foo/main.rs\"\n\n[[example]]\nname = \"example_foo\"\npath = \"examples/example_foo.rs\"\n\n[[test]]\nname = \"test_foo\"\npath = \"tests/test_foo.rs\"\n\n[[bench]]\nname = \"bench_foo\"\npath = \"benches/bench_foo.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn discovery_inferred_build_rs_included() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/lib.rs\", \"build.rs\"]\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            \"build.rs\",\n            \"Cargo.lock\",\n        ],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = \"build.rs\"\ninclude = [\n    \"src/lib.rs\",\n    \"build.rs\",\n]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn discovery_inferred_build_rs_excluded() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/lib.rs\"]\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] ignoring `package.build` entry `build.rs` as it is not included in the published package\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\", \"Cargo.lock\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\"src/lib.rs\"]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn discovery_explicit_build_rs_included() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/lib.rs\", \"build.rs\"]\n    build = \"build.rs\"\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            \"build.rs\",\n            \"Cargo.lock\",\n        ],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = \"build.rs\"\ninclude = [\n    \"src/lib.rs\",\n    \"build.rs\",\n]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn discovery_explicit_build_rs_excluded() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/lib.rs\"]\n    build = \"build.rs\"\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] ignoring `package.build` entry `build.rs` as it is not included in the published package\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\", \"Cargo.lock\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\"src/lib.rs\"]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn discovery_inferred_lib_included() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/main.rs\", \"src/lib.rs\"]\n    \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/main.rs\",\n            \"src/lib.rs\",\n        ],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\n    \"src/main.rs\",\n    \"src/lib.rs\",\n]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn discovery_inferred_lib_excluded() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/main.rs\"]\n    \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] ignoring library `foo` as `src/lib.rs` is not included in the published package\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\"src/main.rs\"]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn discovery_explicit_lib_included() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/main.rs\", \"src/lib.rs\"]\n\n    [lib]\n    path = \"src/lib.rs\"\n    \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/main.rs\",\n            \"src/lib.rs\",\n        ],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\n    \"src/main.rs\",\n    \"src/lib.rs\",\n]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn discovery_explicit_lib_excluded() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/main.rs\"]\n\n    [lib]\n    path = \"src/lib.rs\"\n    \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] ignoring library `foo` as `src/lib.rs` is not included in the published package\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\"src/main.rs\"]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn discovery_inferred_other_included() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/lib.rs\", \"src/bin/foo/main.rs\", \"examples/example_foo.rs\", \"tests/test_foo.rs\", \"benches/bench_foo.rs\"]\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/foo/main.rs\", \"fn main() {}\")\n        .file(\"examples/example_foo.rs\", \"fn main() {}\")\n        .file(\"tests/test_foo.rs\", \"fn main() {}\")\n        .file(\"benches/bench_foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 8 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            \"src/bin/foo/main.rs\",\n            \"examples/example_foo.rs\",\n            \"tests/test_foo.rs\",\n            \"benches/bench_foo.rs\",\n        ],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\n    \"src/lib.rs\",\n    \"src/bin/foo/main.rs\",\n    \"examples/example_foo.rs\",\n    \"tests/test_foo.rs\",\n    \"benches/bench_foo.rs\",\n]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/bin/foo/main.rs\"\n\n[[example]]\nname = \"example_foo\"\npath = \"examples/example_foo.rs\"\n\n[[test]]\nname = \"test_foo\"\npath = \"tests/test_foo.rs\"\n\n[[bench]]\nname = \"bench_foo\"\npath = \"benches/bench_foo.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn discovery_inferred_other_excluded() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/lib.rs\"]\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/foo/main.rs\", \"fn main() {}\")\n        .file(\"examples/example_foo.rs\", \"fn main() {}\")\n        .file(\"tests/test_foo.rs\", \"fn main() {}\")\n        .file(\"benches/bench_foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] ignoring binary `foo` as `src/bin/foo/main.rs` is not included in the published package\n[WARNING] ignoring example `example_foo` as `examples/example_foo.rs` is not included in the published package\n[WARNING] ignoring test `test_foo` as `tests/test_foo.rs` is not included in the published package\n[WARNING] ignoring benchmark `bench_foo` as `benches/bench_foo.rs` is not included in the published package\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\"src/lib.rs\"]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn discovery_explicit_other_included() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/lib.rs\", \"src/bin/foo/main.rs\", \"examples/example_foo.rs\", \"tests/test_foo.rs\", \"benches/bench_foo.rs\"]\n\n    [[bin]]\n    name = \"foo\"\n\n    [[example]]\n    name = \"example_foo\"\n\n    [[test]]\n    name = \"test_foo\"\n\n    [[bench]]\n    name = \"bench_foo\"\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/foo/main.rs\", \"fn main() {}\")\n        .file(\"examples/example_foo.rs\", \"fn main() {}\")\n        .file(\"tests/test_foo.rs\", \"fn main() {}\")\n        .file(\"benches/bench_foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 8 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            \"src/bin/foo/main.rs\",\n            \"examples/example_foo.rs\",\n            \"tests/test_foo.rs\",\n            \"benches/bench_foo.rs\",\n        ],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\n    \"src/lib.rs\",\n    \"src/bin/foo/main.rs\",\n    \"examples/example_foo.rs\",\n    \"tests/test_foo.rs\",\n    \"benches/bench_foo.rs\",\n]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/bin/foo/main.rs\"\n\n[[example]]\nname = \"example_foo\"\npath = \"examples/example_foo.rs\"\n\n[[test]]\nname = \"test_foo\"\npath = \"tests/test_foo.rs\"\n\n[[bench]]\nname = \"bench_foo\"\npath = \"benches/bench_foo.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn discovery_explicit_other_excluded() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/lib.rs\"]\n\n    [[main]]\n    name = \"foo\"\n\n    [[example]]\n    name = \"example_foo\"\n\n    [[test]]\n    name = \"test_foo\"\n\n    [[bench]]\n    name = \"bench_foo\"\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/foo/main.rs\", \"fn main() {}\")\n        .file(\"examples/example_foo.rs\", \"fn main() {}\")\n        .file(\"tests/test_foo.rs\", \"fn main() {}\")\n        .file(\"benches/bench_foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] ignoring binary `foo` as `src/bin/foo/main.rs` is not included in the published package\n[WARNING] ignoring example `example_foo` as `examples/example_foo.rs` is not included in the published package\n[WARNING] ignoring test `test_foo` as `tests/test_foo.rs` is not included in the published package\n[WARNING] ignoring benchmark `bench_foo` as `benches/bench_foo.rs` is not included in the published package\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\"src/lib.rs\"]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn deterministic_build_targets() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.0.1\"\n    edition = \"2021\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n\n    [[example]]\n    name = \"c\"\n\n    [[example]]\n    name = \"b\"\n\n    [[example]]\n    name = \"a\"\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/z.rs\", \"fn main() {}\")\n        .file(\"examples/y.rs\", \"fn main() {}\")\n        .file(\"examples/x.rs\", \"fn main() {}\")\n        .file(\"examples/c.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .file(\"examples/a.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 10 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            \"examples/a.rs\",\n            \"examples/b.rs\",\n            \"examples/c.rs\",\n            \"examples/x.rs\",\n            \"examples/y.rs\",\n            \"examples/z.rs\",\n        ],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2021\"\nname = \"foo\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n[[example]]\nname = \"a\"\npath = \"examples/a.rs\"\n\n[[example]]\nname = \"b\"\npath = \"examples/b.rs\"\n\n[[example]]\nname = \"c\"\npath = \"examples/c.rs\"\n\n[[example]]\nname = \"x\"\npath = \"examples/x.rs\"\n\n[[example]]\nname = \"y\"\npath = \"examples/y.rs\"\n\n[[example]]\nname = \"z\"\npath = \"examples/z.rs\"\n\n\"##]],\n        )],\n    );\n}\n\n// A workspace with three projects that depend on one another (level1 -> level2 -> level3).\n// level1 is a binary package, to test lockfile generation.\nfn workspace_with_local_deps_project() -> Project {\n    project()\n            .file(\n                \"Cargo.toml\",\n                r#\"\n            [workspace]\n            members = [\"level1\", \"level2\", \"level3\"]\n\n            [workspace.dependencies]\n            level2 = { path = \"level2\", version = \"0.0.1\" }\n        \"#\n            )\n            .file(\n                \"level1/Cargo.toml\",\n                r#\"\n            [package]\n            name = \"level1\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level1\"\n            repository = \"bar\"\n\n            [dependencies]\n            # Let one dependency also specify features, for the added test coverage when generating package files.\n            level2 = { workspace = true, features = [\"foo\"] }\n        \"#,\n            )\n            .file(\"level1/src/main.rs\", \"fn main() {}\")\n            .file(\n                \"level2/Cargo.toml\",\n                r#\"\n            [package]\n            name = \"level2\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level2\"\n            repository = \"bar\"\n\n            [features]\n            foo = []\n\n            [dependencies]\n            level3 = { path = \"../level3\", version = \"0.0.1\" }\n        \"#\n            )\n            .file(\"level2/src/lib.rs\", \"\")\n            .file(\n                \"level3/Cargo.toml\",\n                r#\"\n            [package]\n            name = \"level3\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level3\"\n            repository = \"bar\"\n        \"#,\n            )\n            .file(\"level3/src/lib.rs\", \"\")\n            .build()\n}\n\n#[cargo_test]\nfn workspace_with_local_deps() {\n    let crates_io = registry::init();\n    let p = workspace_with_local_deps_project();\n\n    p.cargo(\"package\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] level3 v0.0.1 ([ROOT]/foo/level3)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] level2 v0.0.1 ([ROOT]/foo/level2)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] level3 v0.0.1 ([ROOT]/foo/level3)\n[COMPILING] level3 v0.0.1 ([ROOT]/foo/target/package/level3-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] level2 v0.0.1 ([ROOT]/foo/level2)\n[UNPACKING] level3 v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] level3 v0.0.1\n[COMPILING] level2 v0.0.1 ([ROOT]/foo/target/package/level2-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] level1 v0.0.1 ([ROOT]/foo/level1)\n[UNPACKING] level2 v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] level2 v0.0.1\n[COMPILING] level1 v0.0.1 ([ROOT]/foo/target/package/level1-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let generated_lock = str![[r##\"\n# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"level1\"\nversion = \"0.0.1\"\ndependencies = [\n \"level2\",\n]\n\n[[package]]\nname = \"level2\"\nversion = \"0.0.1\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"[..]\"\ndependencies = [\n \"level3\",\n]\n\n[[package]]\nname = \"level3\"\nversion = \"0.0.1\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"[..]\"\n\n\"##]];\n\n    let generated_manifest = str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"level1\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"level1\"\nreadme = false\nlicense = \"MIT\"\nrepository = \"bar\"\n\n[[bin]]\nname = \"level1\"\npath = \"src/main.rs\"\n\n[dependencies.level2]\nversion = \"0.0.1\"\nfeatures = [\"foo\"]\n\n\"##]];\n\n    let mut f = File::open(&p.root().join(\"target/package/level1-0.0.1.crate\")).unwrap();\n\n    validate_crate_contents(\n        &mut f,\n        \"level1-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        [\n            (\"Cargo.lock\", generated_lock),\n            (\"Cargo.toml\", generated_manifest),\n        ],\n    );\n}\n\n#[cargo_test]\nfn workspace_with_local_dev_deps() {\n    let crates_io = registry::init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"main\", \"dev_dep\"]\n            resolver = \"3\"\n\n            [workspace.dependencies]\n            dev_dep = { path = \"dev_dep\", version = \"0.0.1\" }\n        \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2024\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n\n            [dev-dependencies]\n            dev_dep.workspace = true\n        \"#,\n        )\n        .file(\n            \"dev_dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dev_dep\"\n            version = \"0.0.1\"\n            edition = \"2024\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n        \"#,\n        )\n        .file(\"main/src/lib.rs\", \"\")\n        .file(\"dev_dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] dev_dep v0.0.1 ([ROOT]/foo/dev_dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] dev_dep v0.0.1 ([ROOT]/foo/dev_dep)\n[COMPILING] dev_dep v0.0.1 ([ROOT]/foo/target/package/dev_dep-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] main v0.0.1 ([ROOT]/foo/main)\n[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\nfn workspace_with_local_deps_packaging_one_fails_project() -> Project {\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"level1\", \"level2\"]\n        \"#,\n        )\n        .file(\n            \"level1/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level1\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level1\"\n            repository = \"bar\"\n\n            [dependencies]\n            level2 = { path = \"../level2\", version = \"0.0.1\" }\n        \"#,\n        )\n        .file(\"level1/src/lib.rs\", \"\")\n        .file(\n            \"level2/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level2\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level2\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"level2/src/lib.rs\", \"\")\n        .build()\n}\n\n#[cargo_test]\nfn workspace_with_local_deps_packaging_one_fails() {\n    let crates_io = registry::init();\n    let p = workspace_with_local_deps_packaging_one_fails_project();\n\n    // We can't package just level1, because there's a dependency on level2.\n    p.cargo(\"package -p level1\")\n        .replace_crates_io(crates_io.index_url())\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1)\n[UPDATING] crates.io index\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  no matching package named `level2` found\n  location searched: crates.io index\n  required by package `level1 v0.0.1 ([ROOT]/foo/level1)`\n\n\"#]])\n        .run();\n}\n\n// Same as workspace_with_local_deps_packaging_one_fails except that we're\n// packaging a bin. This fails during lock-file generation instead of during verification.\n#[cargo_test]\nfn workspace_with_local_deps_packaging_one_bin_fails() {\n    let crates_io = registry::init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"level1\", \"level2\"]\n        \"#,\n        )\n        .file(\n            \"level1/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level1\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level1\"\n            repository = \"bar\"\n\n            [dependencies]\n            level2 = { path = \"../level2\", version = \"0.0.1\" }\n        \"#,\n        )\n        .file(\"level1/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"level2/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level2\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level2\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"level2/src/lib.rs\", \"\")\n        .build();\n\n    // We can't package just level1, because there's a dependency on level2.\n    p.cargo(\"package -p level1\")\n        .replace_crates_io(crates_io.index_url())\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1)\n[UPDATING] crates.io index\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  no matching package named `level2` found\n  location searched: crates.io index\n  required by package `level1 v0.0.1 ([ROOT]/foo/level1)`\n\n\"#]])\n        .run();\n}\n\n// Here we don't package the whole workspace, but it succeeds because we package a\n// dependency-closed subset.\n#[cargo_test]\nfn workspace_with_local_deps_packaging_one_with_needed_deps() {\n    let crates_io = registry::init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"level1\", \"level2\", \"level3\"]\n        \"#,\n        )\n        .file(\n            \"level1/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level1\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level1\"\n            repository = \"bar\"\n\n            [dependencies]\n            level2 = { path = \"../level2\", version = \"0.0.1\" }\n        \"#,\n        )\n        .file(\"level1/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"level2/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level2\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level2\"\n            repository = \"bar\"\n\n            [dependencies]\n            level3 = { path = \"../level3\", version = \"0.0.1\" }\n        \"#,\n        )\n        .file(\"level2/src/lib.rs\", \"\")\n        .file(\n            \"level3/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level3\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level3\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"level3/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package -p level2 -p level3\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] level3 v0.0.1 ([ROOT]/foo/level3)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] level2 v0.0.1 ([ROOT]/foo/level2)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] level3 v0.0.1 ([ROOT]/foo/level3)\n[COMPILING] level3 v0.0.1 ([ROOT]/foo/target/package/level3-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] level2 v0.0.1 ([ROOT]/foo/level2)\n[UNPACKING] level3 v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] level3 v0.0.1\n[COMPILING] level2 v0.0.1 ([ROOT]/foo/target/package/level2-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n// package --list in a workspace lists all the files in all the packages.\n// The output is not very good, though. See https://github.com/rust-lang/cargo/issues/13953\n#[cargo_test]\nfn workspace_with_local_deps_list() {\n    let crates_io = registry::init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"level1\", \"level2\"]\n        \"#,\n        )\n        .file(\n            \"level1/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level1\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level1\"\n            repository = \"bar\"\n\n            [dependencies]\n            level2 = { path = \"../level2\", version = \"0.0.1\" }\n        \"#,\n        )\n        .file(\"level1/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"level2/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level2\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level2\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"level2/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --list\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/lib.rs\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn workspace_with_local_deps_index_mismatch() {\n    registry::init();\n    let alt_reg = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n    // We're publishing to an alternate index, but the manifests don't specify it.\n    // The intra-workspace deps won't be found.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"level1\", \"level2\"]\n        \"#,\n        )\n        .file(\n            \"level1/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level1\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level1\"\n            repository = \"bar\"\n\n            [dependencies]\n            level2 = { path = \"../level2\", version = \"0.0.1\" }\n        \"#,\n        )\n        .file(\"level1/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"level2/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level2\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level2\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"level2/src/lib.rs\", \"\")\n        .build();\n    p.cargo(&format!(\"package --index {}\", alt_reg.index_url()))\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] level2 v0.0.1 ([ROOT]/foo/level2)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1)\n[UPDATING] `dummy-registry` index\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  no matching package named `level2` found\n  location searched: `dummy-registry` index (which is replacing registry `crates-io`)\n  required by package `level1 v0.0.1 ([ROOT]/foo/level1)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_with_local_deps_alternative_index() {\n    let alt_reg = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"level1\", \"level2\"]\n        \"#,\n        )\n        .file(\n            \"level1/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level1\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level1\"\n            repository = \"bar\"\n\n            [dependencies]\n            level2 = { path = \"../level2\", version = \"0.0.1\", registry = \"alternative\" }\n        \"#,\n        )\n        .file(\"level1/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"level2/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"level2\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level2\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"level2/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(&format!(\"package --index {}\", alt_reg.index_url()))\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] level2 v0.0.1 ([ROOT]/foo/level2)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1)\n[UPDATING] `alternative` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] level2 v0.0.1 ([ROOT]/foo/level2)\n[COMPILING] level2 v0.0.1 ([ROOT]/foo/target/package/level2-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] level1 v0.0.1 ([ROOT]/foo/level1)\n[UPDATING] `alternative` index\n[UNPACKING] level2 v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] level2 v0.0.1 (registry `alternative`)\n[COMPILING] level1 v0.0.1 ([ROOT]/foo/target/package/level1-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let index = alt_reg.index_url();\n    let generated_lock = format!(\n        r#\"# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"level1\"\nversion = \"0.0.1\"\ndependencies = [\n \"level2\",\n]\n\n[[package]]\nname = \"level2\"\nversion = \"0.0.1\"\nsource = \"{index}\"\nchecksum = \"[..]\"\n\"#\n    );\n\n    let mut f = File::open(&p.root().join(\"target/package/level1-0.0.1.crate\")).unwrap();\n\n    validate_crate_contents(\n        &mut f,\n        \"level1-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        [(\"Cargo.lock\", generated_lock)],\n    );\n}\n\nfn workspace_with_local_dep_already_published_project() -> Project {\n    Package::new(\"dep\", \"0.1.0\").publish();\n\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"dep\", \"main\"]\n            \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n\n            [dependencies]\n            dep = { path = \"../dep\", version = \"0.1.0\" }\n        \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"dep\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build()\n}\n\n#[cargo_test]\nfn workspace_with_local_dep_already_published() {\n    let reg = registry::init();\n    let p = workspace_with_local_dep_already_published_project();\n\n    p.cargo(\"package\")\n        .replace_crates_io(reg.index_url())\n        .with_stderr_data(\n            str![[r#\"\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep)\n[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] main v0.0.1 ([ROOT]/foo/main)\n[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] dep v0.1.0\n[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_with_local_and_remote_deps() {\n    let reg = registry::init();\n\n    Package::new(\"dep\", \"0.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"dep\", \"main\"]\n            \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n\n            [dependencies]\n            dep = { path = \"../dep\", version = \"0.1.0\" }\n            old_dep = { package = \"dep\", version = \"0.0.1\" }\n        \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"dep\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .replace_crates_io(reg.index_url())\n        .with_stderr_data(\n            str![[r#\"\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep)\n[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] main v0.0.1 ([ROOT]/foo/main)\n[DOWNLOADING] crates ...\n[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[DOWNLOADED] dep v0.0.1\n[COMPILING] dep v0.0.1\n[COMPILING] dep v0.1.0\n[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_with_capitalized_member() {\n    let reg = registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"dep\", \"main\"]\n            \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n\n            [dependencies]\n            DEP = { path = \"../dep\", version = \"0.1.0\" }\n        \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"DEP\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"dep\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --no-verify\")\n        .replace_crates_io(reg.index_url())\n        .with_stderr_data(\n            str![[r#\"\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] DEP v0.1.0 ([ROOT]/foo/dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_with_renamed_member() {\n    let reg = registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"crates/*\"]\n            \"#,\n        )\n        .file(\n            \"crates/val-json/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"obeli-sk-val-json\"\n            version = \"0.16.2\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n\n            [dependencies]\n        \"#,\n        )\n        .file(\"crates/val-json/src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"crates/concepts/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"obeli-sk-concepts\"\n            version = \"0.16.2\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n\n            [dependencies]\n            val-json = { package = \"obeli-sk-val-json\", path = \"../val-json\", version = \"0.16.2\" }\n        \"#,\n        )\n        .file(\n            \"crates/concepts/src/lib.rs\",\n            \"pub fn foo() { val_json::foo() }\",\n        )\n        .file(\n            \"crates/utils/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"obeli-sk-utils\"\n            version = \"0.16.2\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n\n            [dependencies]\n            concepts = { package = \"obeli-sk-concepts\", path = \"../concepts\", version = \"0.16.2\" }\n            val-json = { package = \"obeli-sk-val-json\", path = \"../val-json\", version = \"0.16.2\" }\n        \"#,\n        )\n        .file(\n            \"crates/utils/src/lib.rs\",\n            \"pub fn foo() { val_json::foo(); concepts::foo(); }\",\n        )\n        .build();\n\n    p.cargo(\"package\")\n        .replace_crates_io(reg.index_url())\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] obeli-sk-val-json v0.16.2 ([ROOT]/foo/crates/val-json)\n[PACKAGING] obeli-sk-concepts v0.16.2 ([ROOT]/foo/crates/concepts)\n[PACKAGING] obeli-sk-utils v0.16.2 ([ROOT]/foo/crates/utils)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] obeli-sk-val-json v0.16.2 ([ROOT]/foo/crates/val-json)\n[COMPILING] obeli-sk-val-json v0.16.2 ([ROOT]/foo/target/package/obeli-sk-val-json-0.16.2)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] obeli-sk-concepts v0.16.2 ([ROOT]/foo/crates/concepts)\n[UNPACKING] obeli-sk-val-json v0.16.2 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] obeli-sk-val-json v0.16.2\n[COMPILING] obeli-sk-concepts v0.16.2 ([ROOT]/foo/target/package/obeli-sk-concepts-0.16.2)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] obeli-sk-utils v0.16.2 ([ROOT]/foo/crates/utils)\n[UNPACKING] obeli-sk-concepts v0.16.2 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] obeli-sk-concepts v0.16.2\n[COMPILING] obeli-sk-utils v0.16.2 ([ROOT]/foo/target/package/obeli-sk-utils-0.16.2)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_with_dot_rs_dir() {\n    let reg = registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"crates/*\"]\n            \"#,\n        )\n        .file(\n            \"crates/foo.rs/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.16.2\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n\n            [dependencies]\n        \"#,\n        )\n        .file(\"crates/foo.rs/src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"crates/bar.rs/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.16.2\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n\n            [dependencies]\n            foo = { path = \"../foo.rs\", version = \"0.16.2\" }\n        \"#,\n        )\n        .file(\"crates/bar.rs/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .replace_crates_io(reg.index_url())\n        .with_stderr_data(\n            str![[r#\"\n[PACKAGING] foo v0.16.2 ([ROOT]/foo/crates/foo.rs)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] bar v0.16.2 ([ROOT]/foo/crates/bar.rs)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.16.2 ([ROOT]/foo/crates/foo.rs)\n[COMPILING] foo v0.16.2 ([ROOT]/foo/target/package/foo-0.16.2)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] bar v0.16.2 ([ROOT]/foo/crates/bar.rs)\n[UNPACKING] foo v0.16.2 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] foo v0.16.2\n[COMPILING] bar v0.16.2 ([ROOT]/foo/target/package/bar-0.16.2)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn registry_not_in_publish_list() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                publish = [\n                    \"test\"\n                ]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `foo` cannot be packaged.\nThe registry `alternative` is not listed in the `package.publish` value in Cargo.toml.\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --registry alternative --list\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn registry_inferred_from_unique_option() {\n    let _registry = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"dep\", \"main\"]\n            \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n            publish = [\"alternative\"]\n\n            [dependencies]\n            dep = { path = \"../dep\", version = \"0.1.0\", registry = \"alternative\" }\n        \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"dep\"\n            repository = \"bar\"\n            publish = [\"alternative\"]\n        \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep)\n[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] dep v0.1.0 (registry `alternative`)\n[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn registry_not_inferred_because_of_conflict() {\n    let alt_reg = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"dep\", \"main\"]\n            \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n            publish = [\"alternative\"]\n\n            [dependencies]\n            dep = { path = \"../dep\", version = \"0.1.0\", registry = \"alternative\" }\n        \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"dep\"\n            repository = \"bar\"\n            publish = [\"alternative2\"]\n        \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] conflicts between `package.publish` fields in the selected packages\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --exclude-lockfile\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] conflicts between `package.publish` fields in the selected packages\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] conflicts between `package.publish` fields in the selected packages\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --exclude-lockfile --no-verify\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --registry=alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `dep` cannot be packaged.\nThe registry `alternative` is not listed in the `package.publish` value in Cargo.toml.\n\n\"#]])\n        .run();\n\n    p.cargo(&format!(\"package --index {}\", alt_reg.index_url()))\n        .with_stderr_data(str![[r#\"\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep)\n[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] dep v0.1.0 (registry `alternative`)\n[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn registry_inference_ignores_unpublishable() {\n    let _alt_reg = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"dep\", \"main\"]\n            \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n            publish = false\n\n            [dependencies]\n            dep = { path = \"../dep\", version = \"0.1.0\", registry = \"alternative\" }\n        \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"dep\"\n            repository = \"bar\"\n            publish = [\"alternative\"]\n        \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep)\n[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] dep v0.1.0 (registry `alternative`)\n[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --registry=alternative\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep)\n[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn registry_not_inferred_because_of_multiple_options() {\n    let _alt_reg = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"dep\", \"main\"]\n            \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n            publish = [\"alternative\", \"alternative2\"]\n\n            [dependencies]\n            dep = { path = \"../dep\", version = \"0.1.0\", registry = \"alternative\" }\n        \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"dep\"\n            repository = \"bar\"\n            publish = [\"alternative\", \"alternative2\"]\n        \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] --registry is required to disambiguate between \"alternative\" or \"alternative2\" registries\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --exclude-lockfile\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] --registry is required to disambiguate between \"alternative\" or \"alternative2\" registries\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] --registry is required to disambiguate between \"alternative\" or \"alternative2\" registries\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --exclude-lockfile --no-verify\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --registry=alternative\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep)\n[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] dep v0.1.0 (registry `alternative`)\n[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn registry_not_inferred_because_of_mismatch() {\n    let _alt_reg = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"dep\", \"main\"]\n            \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n            publish = [\"alternative\"]\n\n            [dependencies]\n            dep = { path = \"../dep\", version = \"0.1.0\", registry = \"alternative\" }\n        \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        // No `publish` field means \"any registry\", but the presence of this package\n        // will stop us from inferring a registry.\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"dep\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] --registry is required because not all `package.publish` settings agree\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --exclude-lockfile\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] --registry is required because not all `package.publish` settings agree\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] --registry is required because not all `package.publish` settings agree\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --exclude-lockfile --no-verify\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --registry=alternative\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep)\n[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] dep v0.1.0 (registry `alternative`)\n[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unpublishable_dependency() {\n    let _alt_reg = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"dep\", \"main\"]\n            \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n\n            [dependencies]\n            dep = { path = \"../dep\", version = \"0.1.0\", registry = \"alternative\" }\n        \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"dep\"\n            repository = \"bar\"\n            publish = false\n        \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] `alternative` index\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  no matching package named `dep` found\n  location searched: `alternative` index\n  required by package `main v0.0.1 ([ROOT]/foo/main)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn in_package_workspace_with_members_with_features_old() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [workspace]\n                members = [\"li\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"li/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"li\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                rust-version = \"1.69\"\n                description = \"li\"\n                license = \"MIT\"\n            \"#,\n        )\n        .file(\"li/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package -p li --no-verify\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] li v0.0.1 ([ROOT]/foo/li)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[cfg(unix)]\nfn simple_with_fifo() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    std::process::Command::new(\"mkfifo\")\n        .current_dir(p.root())\n        .arg(p.root().join(\"blocks-when-read\"))\n        .status()\n        .expect(\"a FIFO can be created\");\n\n    // Avoid actual blocking even in case of failure, assuming that what it lists here\n    // would also be read eventually.\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_core_symlinks_false() {\n    if !symlink_supported() {\n        return;\n    }\n\n    let git_project = git::new(\"bar\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                description = \"bar\"\n                license = \"MIT\"\n                edition = \"2021\"\n                documentation = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"//! This is a module\")\n        .symlink(\"src/lib.rs\", \"symlink-lib.rs\")\n        .symlink_dir(\"src\", \"symlink-dir\")\n    });\n\n    let url = git_project.root().to_url().to_string();\n\n    let p = project().build();\n    let root = p.root();\n    // Remove the default project layout,\n    // so we can git-fetch from git_project under the same directory\n    fs::remove_dir_all(&root).unwrap();\n    fs::create_dir_all(&root).unwrap();\n    let repo = git::init(&root);\n\n    let mut cfg = repo.config().unwrap();\n    cfg.set_bool(\"core.symlinks\", false).unwrap();\n\n    // let's fetch from git_project so it respects our core.symlinks=false config.\n    repo.remote_anonymous(&url)\n        .unwrap()\n        .fetch(&[\"HEAD\"], None, None)\n        .unwrap();\n    let rev = repo\n        .find_reference(\"FETCH_HEAD\")\n        .unwrap()\n        .peel_to_commit()\n        .unwrap();\n    repo.reset(rev.as_object(), git2::ResetType::Hard, None)\n        .unwrap();\n\n    p.cargo(\"package --allow-dirty\")\n        .with_stderr_data(str![[r#\"\n[WARNING] found symbolic links that may be checked out as regular files for git repo at `[ROOT]/foo/`\n  |\n  = [NOTE] this might cause the `.crate` file to include incorrect or incomplete files\n  = [HELP] to avoid this, set the Git config `core.symlinks` to `true`\n...\n[PACKAGING] bar v0.0.0 ([ROOT]/foo)\n[PACKAGED] 7 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] bar v0.0.0 ([ROOT]/foo)\n[COMPILING] bar v0.0.0 ([ROOT]/foo/target/package/bar-0.0.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/bar-0.0.0.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"bar-0.0.0.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/lib.rs\",\n            // We're missing symlink-dir/lib.rs in the `.crate` file.\n            \"symlink-dir\",\n            \"symlink-lib.rs\",\n            \".cargo_vcs_info.json\",\n        ],\n        [\n            // And their contents are incorrect.\n            (\"symlink-dir\", str![\"[ROOT]/bar/src\"]),\n            (\"symlink-lib.rs\", str![\"[ROOT]/bar/src/lib.rs\"]),\n        ],\n    );\n}\n\n#[cargo_test]\nfn exclude_lockfile() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --list --exclude-lockfile\")\n        .with_stdout_data(str![[r#\"\nCargo.toml\nCargo.toml.orig\nsrc/lib.rs\n\n\"#]])\n        .with_stderr_data(\"\")\n        .run();\n\n    p.cargo(\"package --exclude-lockfile\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\"],\n        (),\n    );\n}\n\n// A failing case from <https://github.com/rust-lang/cargo/issues/15059>\n#[cargo_test]\nfn unpublished_cyclic_dev_dependencies() {\n    registry::init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n\n                [dev-dependencies]\n                foo = { path = \".\", version = \"0.0.1\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --no-verify --exclude-lockfile\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        // no Cargo.lock\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\"],\n        (),\n    );\n}\n\n// A failing case from <https://github.com/rust-lang/cargo/issues/15059>\n#[cargo_test]\nfn unpublished_dependency() {\n    registry::init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n\n                [dependencies]\n                dep = { path = \"./dep\", version = \"0.0.1\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --no-verify -p foo --exclude-lockfile\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        // no Cargo.lock\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\"],\n        (),\n    );\n}\n\n// This is a companion to `publish::checksum_changed`, but because this one\n// is packaging without dry-run, it should fail.\n#[cargo_test]\nfn checksum_changed() {\n    let registry = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .build();\n\n    Package::new(\"dep\", \"1.0.0\").publish();\n    Package::new(\"transitive\", \"1.0.0\")\n        .dep(\"dep\", \"1.0.0\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"dep\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n\n                [dependencies]\n                dep = { path = \"./dep\", version = \"1.0.0\" }\n                transitive = \"1.0.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    p.cargo(\"package --workspace\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] dep v1.0.0 ([ROOT]/foo/dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  checksum for `dep v1.0.0` changed between lock files\n\n  this could be indicative of a few possible errors:\n\n      * the lock file is corrupt\n      * a replacement source in use (e.g., a mirror) returned a different checksum\n      * the source itself may be corrupt in one way or another\n\n  unable to verify that `dep v1.0.0` is the same as when the lockfile was generated\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_to_crates_io_warns() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                description = \"foo\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(&format!(\"publish --dry-run\"))\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.1.0 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.1.0 ([ROOT]/foo)\n[COMPILING] foo v0.1.0 ([ROOT]/foo/target/package/foo-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.1.0 ([ROOT]/foo)\n[WARNING] aborting upload due to dry run\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_to_alt_registry_warns() {\n    let _alt_reg = registry::RegistryBuilder::new().alternative().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                description = \"foo\"\n                edition = \"2015\"\n                publish = [\"alternative\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --dry-run --registry alternative\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[PACKAGING] foo v0.1.0 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.1.0 ([ROOT]/foo)\n[COMPILING] foo v0.1.0 ([ROOT]/foo/target/package/foo-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.1.0 ([ROOT]/foo)\n[WARNING] aborting upload due to dry run\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn package_dir_not_excluded_from_backups() {\n    // This test documents the current behavior where target directory is NOT excluded from backups.\n    // After the fix, this test will be updated to verify that CACHEDIR.TAG exists.\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"package --allow-dirty\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Verify CACHEDIR.TAG exists in target (which excludes target/ and all subdirectories)\n    let cachedir_tag = p.root().join(\"target/CACHEDIR.TAG\");\n    assert!(\n        cachedir_tag.exists(),\n        \"CACHEDIR.TAG should exist in target directory to exclude it from backups\"\n    );\n}\n\n#[cargo_test]\nfn repackage_smaller_crate_has_trailing_garbage() {\n    // When a package is re-packaged and the new .crate file is smaller than\n    // the previous one, the artifact on disk should be smaller without trailing garbage bytes.\n    let big_file_contents = \"x\".repeat(100_000);\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                include = [\"src/**\", \"Cargo.toml\", \"big.txt\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"big.txt\", &big_file_contents)\n        .build();\n\n    // First package run: includes big.txt, so the .crate file is large.\n    p.cargo(\"package --no-verify\").run();\n\n    let crate_path = p.root().join(\"target/package/foo-0.0.1.crate\");\n    let first_size = fs::metadata(&crate_path).unwrap().len();\n\n    // Remove big.txt from the project so the next package will be smaller.\n    fs::remove_file(p.root().join(\"big.txt\")).unwrap();\n\n    // Update the manifest to no longer include big.txt.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2021\"\n            include = [\"src/**\", \"Cargo.toml\"]\n        \"#,\n    );\n\n    // Second package run: no big.txt, so the .crate file should be much smaller.\n    p.cargo(\"package --no-verify\").run();\n\n    let second_size = fs::metadata(&crate_path).unwrap().len();\n\n    // The target .crate file *is* smaller.\n    assert!(\n        first_size > second_size,\n        \"the .crate file should be smaller after removing big.txt\"\n    );\n}\n\n#[cargo_test]\nfn repackage_smaller_local_dep_tmp_registry_checksum_match() {\n    let reg = registry::init();\n    let big_file_contents = \"x\".repeat(100_000);\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n                resolver = \"2\"\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [dependencies]\n                bar = { path = \"../bar\", version = \"0.0.1\" }\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"pub fn foo() { bar::bar(); }\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                include = [\"src/**\", \"Cargo.toml\", \"big.txt\"]\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"bar/big.txt\", &big_file_contents)\n        .build();\n\n    p.cargo(\"package --workspace --no-verify\")\n        .replace_crates_io(reg.index_url())\n        .run();\n\n    fs::remove_file(p.root().join(\"bar/big.txt\")).unwrap();\n    p.change_file(\n        \"bar/Cargo.toml\",\n        r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.0.1\"\n            edition = \"2021\"\n            include = [\"src/**\", \"Cargo.toml\"]\n        \"#,\n    );\n    p.cargo(\"package --workspace --no-verify\")\n        .replace_crates_io(reg.index_url())\n        .run();\n\n    let index_line = read_to_string(p.root().join(\"target/package/tmp-registry/index/3/b/bar\"))\n        .unwrap()\n        .lines()\n        .last()\n        .unwrap()\n        .to_owned();\n    let expected_cksum = serde_json::from_str::<serde_json::Value>(&index_line)\n        .unwrap()\n        .get(\"cksum\")\n        .and_then(|value| value.as_str())\n        .unwrap()\n        .to_owned();\n\n    let crate_contents =\n        fs::read(p.root().join(\"target/package/tmp-registry/bar-0.0.1.crate\")).unwrap();\n    let actual_cksum = registry::cksum(&crate_contents);\n\n    assert_eq!(\n        expected_cksum, actual_cksum,\n        \"tmp-registry crate checksum should match index entry\"\n    );\n}\n"
  },
  {
    "path": "tests/testsuite/package_features.rs",
    "content": "//! Tests for feature selection on the command-line.\n\nuse std::fmt::Write;\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::{Dependency, Package};\nuse cargo_test_support::{basic_manifest, project, str};\n\nuse super::features2::switch_to_resolver_2;\n\n#[cargo_test]\nfn virtual_no_default_features() {\n    // --no-default-features in root of virtual workspace.\n    Package::new(\"dep1\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            dep1 = {version = \"1.0\", optional = true}\n\n            [features]\n            default = [\"dep1\"]\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            default = [\"f1\"]\n            f1 = []\n            \"#,\n        )\n        .file(\n            \"b/src/lib.rs\",\n            r#\"\n            #[cfg(feature = \"f1\")]\n            compile_error!{\"expected f1 off\"}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check --no-default-features\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[CHECKING] b v0.1.0 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"check --features foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] none of the selected packages contains this feature: foo\nselected packages: a, b\n[HELP] there is a similarly named feature: f1\n\n\"#]])\n        .run();\n\n    p.cargo(\"check --features a/dep1,b/f1,b/f2,f2\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] none of the selected packages contains these features: b/f2, f2\nselected packages: a, b\n[HELP] there is a similarly named feature: f1\n\n\"#]])\n        .run();\n\n    p.cargo(\"check --features a/dep,b/f1,b/f2,f2\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] none of the selected packages contains these features: a/dep, b/f2, f2\nselected packages: a, b\n[HELP] there are similarly named features: a/dep1, f1\n\n\"#]])\n        .run();\n\n    p.cargo(\"check --features a/dep,a/dep1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] none of the selected packages contains this feature: a/dep\nselected packages: a, b\n[HELP] there is a similarly named feature: b/f1\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -p b --features=dep1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the package 'b' does not contain this feature: dep1\n[HELP] package with the missing feature: a\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn virtual_typo_member_feature() {\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            resolver = \"2\"\n\n            [features]\n            deny-warnings = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build()\n        .cargo(\"check --features a/deny-warning\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the package 'a' does not contain this feature: a/deny-warning\n[HELP] there is a similarly named feature: a/deny-warnings\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn virtual_features() {\n    // --features in root of virtual workspace.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            f1 = []\n            \"#,\n        )\n        .file(\n            \"a/src/lib.rs\",\n            r#\"\n            #[cfg(not(feature = \"f1\"))]\n            compile_error!{\"f1 is missing\"}\n            \"#,\n        )\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.1.0\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --features f1\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[CHECKING] b v0.1.0 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn virtual_with_specific() {\n    // -p flags with --features in root of virtual.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            f1 = []\n            f2 = []\n            \"#,\n        )\n        .file(\n            \"a/src/lib.rs\",\n            r#\"\n            #[cfg(not(feature = \"f1\"))]\n            compile_error!{\"f1 is missing\"}\n            #[cfg(not(feature = \"f2\"))]\n            compile_error!{\"f2 is missing\"}\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            f2 = []\n            f3 = []\n            \"#,\n        )\n        .file(\n            \"b/src/lib.rs\",\n            r#\"\n            #[cfg(not(feature = \"f2\"))]\n            compile_error!{\"f2 is missing\"}\n            #[cfg(not(feature = \"f3\"))]\n            compile_error!{\"f3 is missing\"}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -p a -p b --features f1,f2,f3\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[CHECKING] b v0.1.0 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn other_member_from_current() {\n    // -p for another member while in the current directory.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"bar\"]\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = { path=\"bar\", features=[\"f3\"] }\n\n            [features]\n            f1 = [\"bar/f4\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            f1 = []\n            f2 = []\n            f3 = []\n            f4 = []\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"bar/src/main.rs\",\n            r#\"\n            fn main() {\n                if cfg!(feature = \"f1\") {\n                    print!(\"f1\");\n                }\n                if cfg!(feature = \"f2\") {\n                    print!(\"f2\");\n                }\n                if cfg!(feature = \"f3\") {\n                    print!(\"f3\");\n                }\n                if cfg!(feature = \"f4\") {\n                    print!(\"f4\");\n                }\n                println!();\n            }\n            \"#,\n        )\n        .build();\n\n    // Old behavior.\n    p.cargo(\"run -p bar --features f1\")\n        .with_stdout_data(str![[r#\"\nf3f4\n\n\"#]])\n        .run();\n\n    p.cargo(\"run -p bar --features f1,f2\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package `foo v0.1.0 ([ROOT]/foo)` does not have the feature `f2`\n\n[HELP] a feature with a similar name exists: `f1`\n\n\"#]])\n        .run();\n\n    p.cargo(\"run -p bar --features bar/f1\")\n        .with_stdout_data(str![[r#\"\nf1f3\n\n\"#]])\n        .run();\n\n    // New behavior.\n    switch_to_resolver_2(&p);\n    p.cargo(\"run -p bar --features f1\")\n        .with_stdout_data(str![[r#\"\nf1\n\n\"#]])\n        .run();\n\n    p.cargo(\"run -p bar --features f1,f2\")\n        .with_stdout_data(str![[r#\"\nf1f2\n\n\"#]])\n        .run();\n\n    p.cargo(\"run -p bar --features bar/f1\")\n        .with_stdout_data(str![[r#\"\nf1\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn feature_default_resolver() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            test = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    if cfg!(feature = \"test\") {\n                        println!(\"feature set\");\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check --features testt\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package `a v0.1.0 ([ROOT]/foo)` does not have the feature `testt`\n\n[HELP] a feature with a similar name exists: `test`\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --features test\")\n        .with_status(0)\n        .with_stdout_data(str![[r#\"\nfeature set\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --features a/test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package `a v0.1.0 ([ROOT]/foo)` does not have a dependency named `a`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn command_line_optional_dep() {\n    // Enabling a dependency used as a `dep:` errors helpfully\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            foo = [\"dep:bar\"]\n\n            [dependencies]\n            bar = { version = \"1.0.0\", optional = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check --features bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ERROR] package `a v0.1.0 ([ROOT]/foo)` does not have feature `bar`\n\n[HELP] an optional dependency with that name exists, but the `features` table includes it with the \"dep:\" syntax so it does not have an implicit feature with that name\nDependency `bar` would be enabled by these features:\n\t- `foo`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn command_line_optional_dep_three_options() {\n    // Trying to enable an optional dependency used as a `dep:` errors helpfully, when there are three features which would enable the dependency\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            f1 = [\"dep:bar\"]\n            f2 = [\"dep:bar\"]\n            f3 = [\"dep:bar\"]\n\n            [dependencies]\n            bar = { version = \"1.0.0\", optional = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check --features bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ERROR] package `a v0.1.0 ([ROOT]/foo)` does not have feature `bar`\n\n[HELP] an optional dependency with that name exists, but the `features` table includes it with the \"dep:\" syntax so it does not have an implicit feature with that name\nDependency `bar` would be enabled by these features:\n\t- `f1`\n\t- `f2`\n\t- `f3`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn command_line_optional_dep_many_options() {\n    // Trying to enable an optional dependency used as a `dep:` errors helpfully, when there are many features which would enable the dependency\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            f1 = [\"dep:bar\"]\n            f2 = [\"dep:bar\"]\n            f3 = [\"dep:bar\"]\n            f4 = [\"dep:bar\"]\n\n            [dependencies]\n            bar = { version = \"1.0.0\", optional = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check --features bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ERROR] package `a v0.1.0 ([ROOT]/foo)` does not have feature `bar`\n\n[HELP] an optional dependency with that name exists, but the `features` table includes it with the \"dep:\" syntax so it does not have an implicit feature with that name\nDependency `bar` would be enabled by these features:\n\t- `f1`\n\t- `f2`\n\t- `f3`\n\t  ...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn command_line_optional_dep_many_paths() {\n    // Trying to enable an optional dependency used as a `dep:` errors helpfully, when a features would enable the dependency in multiple ways\n    Package::new(\"bar\", \"1.0.0\")\n        .feature(\"a\", &[])\n        .feature(\"b\", &[])\n        .feature(\"c\", &[])\n        .feature(\"d\", &[])\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            f1 = [\"dep:bar\", \"bar/a\", \"bar/b\"] # Remove the implicit feature\n            f2 = [\"bar/b\", \"bar/c\"] # Overlaps with previous\n            f3 = [\"bar/d\"] # No overlap with previous\n\n            [dependencies]\n            bar = { version = \"1.0.0\", optional = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check --features bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ERROR] package `a v0.1.0 ([ROOT]/foo)` does not have feature `bar`\n\n[HELP] an optional dependency with that name exists, but the `features` table includes it with the \"dep:\" syntax so it does not have an implicit feature with that name\nDependency `bar` would be enabled by these features:\n\t- `f1`\n\t- `f2`\n\t- `f3`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn virtual_member_slash() {\n    // member slash feature syntax\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            b = {path=\"../b\", optional=true}\n\n            [features]\n            default = [\"f1\"]\n            f1 = []\n            f2 = []\n            \"#,\n        )\n        .file(\n            \"a/src/lib.rs\",\n            r#\"\n            #[cfg(feature = \"f1\")]\n            compile_error!{\"f1 is set\"}\n\n            #[cfg(feature = \"f2\")]\n            compile_error!{\"f2 is set\"}\n\n            #[cfg(feature = \"b\")]\n            compile_error!{\"b is set\"}\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [features]\n            bfeat = []\n            \"#,\n        )\n        .file(\n            \"b/src/lib.rs\",\n            r#\"\n            #[cfg(feature = \"bfeat\")]\n            compile_error!{\"bfeat is set\"}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -p a\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] f1 is set\n...\n\"#]])\n        .with_stderr_does_not_contain(\"[..]f2 is set[..]\")\n        .with_stderr_does_not_contain(\"[..]b is set[..]\")\n        .run();\n\n    p.cargo(\"check -p a --features a/f1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] f1 is set\n...\n\"#]])\n        .with_stderr_does_not_contain(\"[..]f2 is set[..]\")\n        .with_stderr_does_not_contain(\"[..]b is set[..]\")\n        .run();\n\n    p.cargo(\"check -p a --features a/f2\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] f1 is set\n...\n[ERROR] f2 is set\n...\n\"#]])\n        .with_stderr_does_not_contain(\"[..]b is set[..]\")\n        .run();\n\n    p.cargo(\"check -p a --features b/bfeat\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] bfeat is set\n...\n\"#]])\n        .run();\n\n    p.cargo(\"check -p a --no-default-features\").run();\n\n    p.cargo(\"check -p a --no-default-features --features b\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] b is set\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn non_member() {\n    // -p for a non-member\n    Package::new(\"dep\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            resolver = \"2\"\n\n            [dependencies]\n            dep = \"1.0\"\n\n            [features]\n            f1 = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -p dep --features f1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot specify features for packages outside of workspace\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -p dep --all-features\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot specify features for packages outside of workspace\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -p dep --no-default-features\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot specify features for packages outside of workspace\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -p dep\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[CHECKING] dep v1.0.0\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn resolver1_member_features() {\n    // --features member-name/feature-name with resolver=\"1\"\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"member1\", \"member2\"]\n            \"#,\n        )\n        .file(\n            \"member1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"member1\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [features]\n                m1-feature = []\n            \"#,\n        )\n        .file(\n            \"member1/src/main.rs\",\n            r#\"\n                fn main() {\n                    if cfg!(feature = \"m1-feature\") {\n                        println!(\"m1-feature set\");\n                    }\n                }\n            \"#,\n        )\n        .file(\"member2/Cargo.toml\", &basic_manifest(\"member2\", \"0.1.0\"))\n        .file(\"member2/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"run -p member1 --features member1/m1-feature\")\n        .cwd(\"member2\")\n        .with_stdout_data(str![[r#\"\nm1-feature set\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -p member1 --features member1/m2-feature\")\n        .cwd(\"member2\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package `member1 v0.1.0 ([ROOT]/foo/member1)` does not have the feature `m2-feature`\n\n[HELP] a feature with a similar name exists: `m1-feature`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn non_member_feature() {\n    // --features for a non-member\n    Package::new(\"jazz\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(Dependency::new(\"jazz\", \"1.0\").optional(true))\n        .publish();\n    let make_toml = |resolver, optional| {\n        let mut s = String::new();\n        write!(\n            s,\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                resolver = \"{}\"\n\n                [dependencies]\n            \"#,\n            resolver\n        )\n        .unwrap();\n        if optional {\n            s.push_str(r#\"bar = { version = \"1.0\", optional = true } \"#);\n        } else {\n            s.push_str(r#\"bar = \"1.0\"\"#)\n        }\n        s.push('\\n');\n        s\n    };\n    let p = project()\n        .file(\"Cargo.toml\", &make_toml(\"1\", false))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\").run();\n    ///////////////////////// V1 non-optional\n    eprintln!(\"V1 non-optional\");\n    p.cargo(\"check -p bar\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v1.0.0\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // TODO: This should not be allowed (future warning?)\n    p.cargo(\"check --features bar/jazz\")\n        .with_stderr_data(str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] jazz v1.0.0 (registry `dummy-registry`)\n[CHECKING] jazz v1.0.0\n[CHECKING] bar v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // TODO: This should not be allowed (future warning?)\n    p.cargo(\"check -p bar --features bar/jazz -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] jazz v1.0.0\n[FRESH] bar v1.0.0\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    ///////////////////////// V1 optional\n    eprintln!(\"V1 optional\");\n    p.change_file(\"Cargo.toml\", &make_toml(\"1\", true));\n\n    // This error isn't great, but is probably unlikely to be common in\n    // practice, so I'm not going to put much effort into improving it.\n    p.cargo(\"check -p bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `bar` did not match any packages\n\n[HELP] a package with a similar name exists: `foo`\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -p bar --features bar -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] bar v1.0.0\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // TODO: This should not be allowed (future warning?)\n    p.cargo(\"check -p bar --features bar/jazz -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] jazz v1.0.0\n[FRESH] bar v1.0.0\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    ///////////////////////// V2 non-optional\n    eprintln!(\"V2 non-optional\");\n    p.change_file(\"Cargo.toml\", &make_toml(\"2\", false));\n    // TODO: This should not be allowed (future warning?)\n    p.cargo(\"check --features bar/jazz -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] jazz v1.0.0\n[FRESH] bar v1.0.0\n[FRESH] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check -p bar -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] bar v1.0.0\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check -p bar --features bar/jazz\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot specify features for packages outside of workspace\n\n\"#]])\n        .run();\n\n    ///////////////////////// V2 optional\n    eprintln!(\"V2 optional\");\n    p.change_file(\"Cargo.toml\", &make_toml(\"2\", true));\n    p.cargo(\"check -p bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `bar` did not match any packages\n\n[HELP] a package with a similar name exists: `foo`\n\n\"#]])\n        .run();\n    // New --features behavior does not look at cwd.\n    p.cargo(\"check -p bar --features bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot specify features for packages outside of workspace\n\n\"#]])\n        .run();\n    p.cargo(\"check -p bar --features bar/jazz\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot specify features for packages outside of workspace\n\n\"#]])\n        .run();\n    p.cargo(\"check -p bar --features foo/bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot specify features for packages outside of workspace\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/package_message_format.rs",
    "content": "//! Tests for the `--message-format` flag for `cargo package`.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn gated() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --list --message-format json\")\n        .masquerade_as_nightly_cargo(&[\"package --message-format\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `--message-format` flag is unstable, pass `-Z unstable-options` to enable it\nSee https://github.com/rust-lang/cargo/issues/15353 for more information about the `--message-format` flag.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn requires_list() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --message-format json -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"package --message-format\"])\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] the following required arguments were not provided:\n  --list\n\nUsage: cargo[EXE] package --list --message-format <FMT> -Z <FLAG>\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn human() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            documentation = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --list --message-format human -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"package --message-format\"])\n        .with_stderr_data(str![\"\"])\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/lib.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn single_package() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            documentation = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --list --message-format json -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"package --message-format\"])\n        .with_stderr_data(str![\"\"])\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"files\": {\n      \"Cargo.lock\": {\n        \"kind\": \"generate\"\n      },\n      \"Cargo.toml\": {\n        \"kind\": \"generate\",\n        \"path\": \"[ROOT]/foo/Cargo.toml\"\n      },\n      \"Cargo.toml.orig\": {\n        \"kind\": \"copy\",\n        \"path\": \"[ROOT]/foo/Cargo.toml\"\n      },\n      \"src/lib.rs\": {\n        \"kind\": \"copy\",\n        \"path\": \"[ROOT]/foo/src/lib.rs\"\n      }\n    },\n    \"id\": \"path+[ROOTURL]/foo#0.0.0\"\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n\n    // has existing lockfile\n    p.cargo(\"generate-lockfile\").run();\n    p.cargo(\"package --list --message-format json -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"package --message-format\"])\n        .with_stderr_data(str![\"\"])\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"files\": {\n      \"Cargo.lock\": {\n        \"kind\": \"generate\",\n        \"path\": \"[ROOT]/foo/Cargo.lock\"\n      },\n      \"Cargo.toml\": {\n        \"kind\": \"generate\",\n        \"path\": \"[ROOT]/foo/Cargo.toml\"\n      },\n      \"Cargo.toml.orig\": {\n        \"kind\": \"copy\",\n        \"path\": \"[ROOT]/foo/Cargo.toml\"\n      },\n      \"src/lib.rs\": {\n        \"kind\": \"copy\",\n        \"path\": \"[ROOT]/foo/src/lib.rs\"\n      }\n    },\n    \"id\": \"path+[ROOTURL]/foo#0.0.0\"\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"gondor\", \"rohan\"]\n            \"#,\n        )\n        .file(\n            \"gondor/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"gondor\"\n                edition = \"2015\"\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n            \"#,\n        )\n        .file(\"gondor/src/lib.rs\", \"\")\n        .file(\n            \"rohan/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"rohan\"\n                edition = \"2015\"\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n            \"#,\n        )\n        .file(\"rohan/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package --list --message-format json -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"package --message-format\"])\n        .with_stderr_data(str![\"\"])\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"files\": {\n      \"Cargo.lock\": {\n        \"kind\": \"generate\"\n      },\n      \"Cargo.toml\": {\n        \"kind\": \"generate\",\n        \"path\": \"[ROOT]/foo/gondor/Cargo.toml\"\n      },\n      \"Cargo.toml.orig\": {\n        \"kind\": \"copy\",\n        \"path\": \"[ROOT]/foo/gondor/Cargo.toml\"\n      },\n      \"src/lib.rs\": {\n        \"kind\": \"copy\",\n        \"path\": \"[ROOT]/foo/gondor/src/lib.rs\"\n      }\n    },\n    \"id\": \"path+[ROOTURL]/foo/gondor#0.0.0\"\n  },\n  {\n    \"files\": {\n      \"Cargo.lock\": {\n        \"kind\": \"generate\"\n      },\n      \"Cargo.toml\": {\n        \"kind\": \"generate\",\n        \"path\": \"[ROOT]/foo/rohan/Cargo.toml\"\n      },\n      \"Cargo.toml.orig\": {\n        \"kind\": \"copy\",\n        \"path\": \"[ROOT]/foo/rohan/Cargo.toml\"\n      },\n      \"src/lib.rs\": {\n        \"kind\": \"copy\",\n        \"path\": \"[ROOT]/foo/rohan/src/lib.rs\"\n      }\n    },\n    \"id\": \"path+[ROOTURL]/foo/rohan#0.0.0\"\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n\n    // has existing lockfile\n    p.cargo(\"generate-lockfile\").run();\n    p.cargo(\"package --list --message-format json -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"package --message-format\"])\n        .with_stderr_data(str![\"\"])\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"files\": {\n      \"Cargo.lock\": {\n        \"kind\": \"generate\",\n        \"path\": \"[ROOT]/foo/Cargo.lock\"\n      },\n      \"Cargo.toml\": {\n        \"kind\": \"generate\",\n        \"path\": \"[ROOT]/foo/gondor/Cargo.toml\"\n      },\n      \"Cargo.toml.orig\": {\n        \"kind\": \"copy\",\n        \"path\": \"[ROOT]/foo/gondor/Cargo.toml\"\n      },\n      \"src/lib.rs\": {\n        \"kind\": \"copy\",\n        \"path\": \"[ROOT]/foo/gondor/src/lib.rs\"\n      }\n    },\n    \"id\": \"path+[ROOTURL]/foo/gondor#0.0.0\"\n  },\n  {\n    \"files\": {\n      \"Cargo.lock\": {\n        \"kind\": \"generate\",\n        \"path\": \"[ROOT]/foo/Cargo.lock\"\n      },\n      \"Cargo.toml\": {\n        \"kind\": \"generate\",\n        \"path\": \"[ROOT]/foo/rohan/Cargo.toml\"\n      },\n      \"Cargo.toml.orig\": {\n        \"kind\": \"copy\",\n        \"path\": \"[ROOT]/foo/rohan/Cargo.toml\"\n      },\n      \"src/lib.rs\": {\n        \"kind\": \"copy\",\n        \"path\": \"[ROOT]/foo/rohan/src/lib.rs\"\n      }\n    },\n    \"id\": \"path+[ROOTURL]/foo/rohan#0.0.0\"\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/patch.rs",
    "content": "//! Tests for `[patch]` table source replacement.\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::git;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::{self, Package};\nuse cargo_test_support::{basic_manifest, project, str};\n\n#[cargo_test]\nfn replace() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"baz\", \"0.1.0\")\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn baz() { bar::bar(); }\",\n        )\n        .dep(\"bar\", \"0.1.0\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n                baz = \"0.1.0\"\n\n                [patch.crates-io]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate bar;\n            extern crate baz;\n            pub fn bar() {\n                bar::bar();\n                baz::baz();\n            }\n        \",\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] baz v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn from_config() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [patch.crates-io]\n                bar = { path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.1 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn from_config_relative() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \"../.cargo/config.toml\",\n            r#\"\n                [patch.crates-io]\n                bar = { path = 'foo/bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.1 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn from_config_precedence() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n\n                [patch.crates-io]\n                bar = { path = 'no-such-path' }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [patch.crates-io]\n                bar = { path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.1 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn nonexistent() {\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n\n                [patch.crates-io]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patch_git() {\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = {{ git = '{}' }}\n\n                    [patch.'{0}']\n                    bar = {{ path = \"bar\" }}\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/override`\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patch_to_git() {\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1\"\n\n                    [patch.crates-io]\n                    bar = {{ git = '{}' }}\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/override`\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(public_network_test)]\nfn patch_to_git_pull_request() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1\"\n\n                [patch.crates-io]\n                bar = { git = 'https://github.com/rust-lang/does-not-exist/pull/123' }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `https://github.com/rust-lang/does-not-exist/pull/123`\n...\n[ERROR] failed to load source for dependency `bar`\n\nCaused by:\n  unable to update https://github.com/rust-lang/does-not-exist/pull/123\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/123-[HASH]\n\nCaused by:\n  network failure seems to have happened\n  if a proxy or similar is necessary `net.git-fetch-with-cli` may help here\n  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\n\n  [NOTE] GitHub url https://github.com/rust-lang/does-not-exist/pull/123 is not a repository. \n  [HELP] Replace the dependency with \n         `git = \"https://github.com/rust-lang/does-not-exist.git\" rev = \"refs/pull/123/head\"` \n     to specify pull requests as dependencies' revision.\n\nCaused by:\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unused() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n\n                [patch.crates-io]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.2.0\"))\n        .file(\"bar/src/lib.rs\", \"not rust code\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[WARNING] patch `bar v0.2.0 ([ROOT]/foo/bar)` was not used in the crate graph\n[HELP] Check that the patched package version and available features are compatible\n      with the dependency requirements. If the patch has a different version from\n      what is locked in the Cargo.lock file, run `cargo update` to use the new\n      version. This may also occur with an optional dependency that is not enabled.\n[LOCKING] 1 package to latest compatible version\n[ADDING] bar v0.1.0 (available: v0.2.0)\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] patch `bar v0.2.0 ([ROOT]/foo/bar)` was not used in the crate graph\n[HELP] Check that the patched package version and available features are compatible\n      with the dependency requirements. If the patch has a different version from\n      what is locked in the Cargo.lock file, run `cargo update` to use the new\n      version. This may also occur with an optional dependency that is not enabled.\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // unused patch should be in the lock file\n    let lock = p.read_lockfile();\n    let toml: toml::Table = toml::from_str(&lock).unwrap();\n    assert_eq!(toml[\"patch\"][\"unused\"].as_array().unwrap().len(), 1);\n    assert_eq!(toml[\"patch\"][\"unused\"][0][\"name\"].as_str(), Some(\"bar\"));\n    assert_eq!(\n        toml[\"patch\"][\"unused\"][0][\"version\"].as_str(),\n        Some(\"0.2.0\")\n    );\n}\n\n#[cargo_test]\nfn unused_with_mismatch_source_being_patched() {\n    registry::alt_init();\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n\n                [patch.alternative]\n                bar = { path = \"bar\" }\n\n                [patch.crates-io]\n                bar = { path = \"baz\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.2.0\"))\n        .file(\"bar/src/lib.rs\", \"not rust code\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"bar\", \"0.3.0\"))\n        .file(\"baz/src/lib.rs\", \"not rust code\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[WARNING] patch `bar v0.2.0 ([ROOT]/foo/bar)` was not used in the crate graph\n  |\n  = [HELP] perhaps you meant one of the following:\n          \tcrates-io\n[WARNING] patch `bar v0.3.0 ([ROOT]/foo/baz)` was not used in the crate graph\n[HELP] Check that the patched package version and available features are compatible\n      with the dependency requirements. If the patch has a different version from\n      what is locked in the Cargo.lock file, run `cargo update` to use the new\n      version. This may also occur with an optional dependency that is not enabled.\n[LOCKING] 1 package to latest compatible version\n[ADDING] bar v0.1.0 (available: v0.3.0)\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn prefer_patch_version() {\n    Package::new(\"bar\", \"0.1.2\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n\n                [patch.crates-io]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.1 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // there should be no patch.unused in the toml file\n    let lock = p.read_lockfile();\n    let toml: toml::Table = toml::from_str(&lock).unwrap();\n    assert!(toml.get(\"patch\").is_none());\n}\n\n#[cargo_test]\nfn unused_from_config() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [patch.crates-io]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.2.0\"))\n        .file(\"bar/src/lib.rs\", \"not rust code\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[WARNING] patch `bar v0.2.0 ([ROOT]/foo/bar)` was not used in the crate graph\n[HELP] Check that the patched package version and available features are compatible\n      with the dependency requirements. If the patch has a different version from\n      what is locked in the Cargo.lock file, run `cargo update` to use the new\n      version. This may also occur with an optional dependency that is not enabled.\n[LOCKING] 1 package to latest compatible version\n[ADDING] bar v0.1.0 (available: v0.2.0)\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] patch `bar v0.2.0 ([ROOT]/foo/bar)` was not used in the crate graph\n[HELP] Check that the patched package version and available features are compatible\n      with the dependency requirements. If the patch has a different version from\n      what is locked in the Cargo.lock file, run `cargo update` to use the new\n      version. This may also occur with an optional dependency that is not enabled.\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // unused patch should be in the lock file\n    let lock = p.read_lockfile();\n    let toml: toml::Table = toml::from_str(&lock).unwrap();\n    assert_eq!(toml[\"patch\"][\"unused\"].as_array().unwrap().len(), 1);\n    assert_eq!(toml[\"patch\"][\"unused\"][0][\"name\"].as_str(), Some(\"bar\"));\n    assert_eq!(\n        toml[\"patch\"][\"unused\"][0][\"version\"].as_str(),\n        Some(\"0.2.0\")\n    );\n}\n\n#[cargo_test]\nfn unused_git() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let foo = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.2.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1\"\n\n                    [patch.crates-io]\n                    bar = {{ git = '{}' }}\n                \"#,\n                foo.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/override`\n[UPDATING] `dummy-registry` index\n[WARNING] patch `bar v0.2.0 ([ROOTURL]/override#[..])` was not used in the crate graph\n[HELP] Check that the patched package version and available features are compatible\n      with the dependency requirements. If the patch has a different version from\n      what is locked in the Cargo.lock file, run `cargo update` to use the new\n      version. This may also occur with an optional dependency that is not enabled.\n[LOCKING] 1 package to latest compatible version\n[ADDING] bar v0.1.0 (available: v0.2.0)\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] patch `bar v0.2.0 ([ROOTURL]/override#[..])` was not used in the crate graph\n[HELP] Check that the patched package version and available features are compatible\n      with the dependency requirements. If the patch has a different version from\n      what is locked in the Cargo.lock file, run `cargo update` to use the new\n      version. This may also occur with an optional dependency that is not enabled.\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn add_patch() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            bar = \"0.1.0\"\n\n            [patch.crates-io]\n            bar = { path = 'bar' }\n        \"#,\n    );\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ADDING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn add_patch_from_config() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n            [patch.crates-io]\n            bar = { path = 'bar' }\n        \"#,\n    );\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ADDING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn add_ignored_patch() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            bar = \"0.1.0\"\n\n            [patch.crates-io]\n            bar = { path = 'bar' }\n        \"#,\n    );\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] patch `bar v0.1.1 ([ROOT]/foo/bar)` was not used in the crate graph\n[HELP] Check that the patched package version and available features are compatible\n      with the dependency requirements. If the patch has a different version from\n      what is locked in the Cargo.lock file, run `cargo update` to use the new\n      version. This may also occur with an optional dependency that is not enabled.\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] patch `bar v0.1.1 ([ROOT]/foo/bar)` was not used in the crate graph\n[HELP] Check that the patched package version and available features are compatible\n      with the dependency requirements. If the patch has a different version from\n      what is locked in the Cargo.lock file, run `cargo update` to use the new\n      version. This may also occur with an optional dependency that is not enabled.\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"update\").run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.1 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn add_patch_with_features() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            bar = \"0.1.0\"\n\n            [patch.crates-io]\n            bar = { path = 'bar', features = [\"some_feature\"] }\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused field in patch for `bar`: `features`\n  |\n  = [HELP] configure `features` in the `dependencies` entry\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused field in patch for `bar`: `features`\n  |\n  = [HELP] configure `features` in the `dependencies` entry\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn add_patch_with_setting_default_features() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            bar = \"0.1.0\"\n\n            [patch.crates-io]\n            bar = { path = 'bar', default-features = false, features = [\"none_default_feature\"] }\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused field in patch for `bar`: `features`, `default-features`\n  |\n  = [HELP] configure `features`, `default-features` in the `dependencies` entry\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused field in patch for `bar`: `features`, `default-features`\n  |\n  = [HELP] configure `features`, `default-features` in the `dependencies` entry\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_warn_ws_patch() {\n    Package::new(\"c\", \"0.1.0\").publish();\n\n    // Don't issue an unused patch warning when the patch isn't used when\n    // partially building a workspace.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\", \"b\", \"c\"]\n\n                [patch.crates-io]\n                c = { path = \"c\" }\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [dependencies]\n                c = \"0.1.0\"\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\"c/Cargo.toml\", &basic_manifest(\"c\", \"0.1.0\"))\n        .file(\"c/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -p a\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn new_minor() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n\n                [patch.crates-io]\n                bar = { path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.1 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn transitive_new_minor() {\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = 'bar' }\n\n                [patch.crates-io]\n                baz = { path = 'baz' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = '0.1.0'\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.1\"))\n        .file(\"baz/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] baz v0.1.1 ([ROOT]/foo/baz)\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn new_major() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.2.0\"\n\n                [patch.crates-io]\n                bar = { path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.2.0\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.2.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    Package::new(\"bar\", \"0.2.0\").publish();\n    p.cargo(\"update\").run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            bar = \"0.2.0\"\n        \"#,\n    );\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ADDING] bar v0.2.0\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.2.0 (registry `dummy-registry`)\n[CHECKING] bar v0.2.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn transitive_new_major() {\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = 'bar' }\n\n                [patch.crates-io]\n                baz = { path = 'baz' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = '0.2.0'\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.2.0\"))\n        .file(\"baz/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] baz v0.2.0 ([ROOT]/foo/baz)\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn shared_by_transitive() {\n    Package::new(\"baz\", \"0.1.1\").publish();\n\n    let baz = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"baz\", \"0.1.2\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \" 0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    bar = {{ path = \"bar\" }}\n                    baz = \"0.1\"\n\n                    [patch.crates-io]\n                    baz = {{ git = \"{}\", version = \"0.1\" }}\n                \"#,\n                baz.url(),\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                baz = \"0.1.1\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/override`\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] baz v0.1.2 ([ROOTURL]/override#[..])\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn remove_patch() {\n    Package::new(\"foo\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1\"\n\n                [patch.crates-io]\n                foo = { path = 'foo' }\n                bar = { path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", r#\"\"#)\n        .build();\n\n    // Generate a lock file where `foo` is unused\n    p.cargo(\"check\").run();\n    let lock_file1 = p.read_lockfile();\n\n    // Remove `foo` and generate a new lock file form the old one\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            bar = \"0.1\"\n\n            [patch.crates-io]\n            bar = { path = 'bar' }\n        \"#,\n    );\n    p.cargo(\"check\").run();\n    let lock_file2 = p.read_lockfile();\n\n    // Remove the lock file and build from scratch\n    fs::remove_file(p.root().join(\"Cargo.lock\")).unwrap();\n    p.cargo(\"check\").run();\n    let lock_file3 = p.read_lockfile();\n\n    assert!(lock_file1.contains(\"foo\"));\n    assert_eq!(lock_file2, lock_file3);\n    assert_ne!(lock_file1, lock_file2);\n}\n\n#[cargo_test]\nfn non_crates_io() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [patch.some-other-source]\n                bar = { path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  [patch] entry `some-other-source` should be a URL or registry name\n\nCaused by:\n  invalid url `some-other-source`: relative URL without a base\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn replace_with_crates_io() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [patch.crates-io]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] patch for `bar` points to the same source, but patches must point to different sources\n[HELP] check `bar` patch definition for `https://github.com/rust-lang/crates.io-index` in `[ROOT]/foo/Cargo.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patch_in_virtual() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\"]\n\n                [patch.crates-io]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check -p foo\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check -p foo\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patch_depends_on_another_patch() {\n    Package::new(\"bar\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"broken code\")\n        .publish();\n\n    Package::new(\"baz\", \"0.1.0\")\n        .dep(\"bar\", \"0.1\")\n        .file(\"src/lib.rs\", \"broken code\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1\"\n                baz = \"0.1\"\n\n                [patch.crates-io]\n                bar = { path = \"bar\" }\n                baz = { path = \"baz\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\").run();\n\n    // Nothing should be rebuilt, no registry should be updated.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn replace_prerelease() {\n    Package::new(\"baz\", \"1.1.0-pre.1\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n\n                [patch.crates-io]\n                baz = { path = \"./baz\" }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"1.1.0-pre.1\"\n            \"#,\n        )\n        .file(\n            \"bar/src/main.rs\",\n            \"extern crate baz; fn main() { baz::baz() }\",\n        )\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"1.1.0-pre.1\"\n                edition = \"2015\"\n                authors = []\n                [workspace]\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn patch_older() {\n    Package::new(\"baz\", \"1.0.2\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = 'bar' }\n                baz = \"=1.0.1\"\n\n                [patch.crates-io]\n                baz = { path = \"./baz\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"1.0.0\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"1.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] baz v1.0.1 ([ROOT]/foo/baz)\n[CHECKING] bar v0.5.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cycle() {\n    Package::new(\"a\", \"1.0.0\").publish();\n    Package::new(\"b\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\", \"b\"]\n\n                [patch.crates-io]\n                a = {path=\"a\"}\n                b = {path=\"b\"}\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                b = \"1.0\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                a = \"1.0\"\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] cyclic package dependency: package `a v1.0.0 ([ROOT]/foo/a)` depends on itself. Cycle:\npackage `a v1.0.0 ([ROOT]/foo/a)`\n    ... which satisfies dependency `a = \"^1.0\"` of package `b v1.0.0 ([ROOT]/foo/b)`\n    ... which satisfies dependency `b = \"^1.0\"` of package `a v1.0.0 ([ROOT]/foo/a)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multipatch() {\n    Package::new(\"a\", \"1.0.0\").publish();\n    Package::new(\"a\", \"2.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                a1 = { version = \"1\", package = \"a\" }\n                a2 = { version = \"2\", package = \"a\" }\n\n                [patch.crates-io]\n                b1 = { path = \"a1\", package = \"a\" }\n                b2 = { path = \"a2\", package = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() { a1::f1(); a2::f2(); }\")\n        .file(\n            \"a1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"a1/src/lib.rs\", \"pub fn f1() {}\")\n        .file(\n            \"a2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"2.0.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"a2/src/lib.rs\", \"pub fn f2() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn patch_same_version() {\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    [dependencies]\n                    bar = \"0.1\"\n                    [patch.crates-io]\n                    bar = {{ path = \"bar\" }}\n                    bar2 = {{ git = '{}', package = 'bar' }}\n                \"#,\n                bar.url(),\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/override`\n[ERROR] several `[patch]` entries resolving to same version `bar v0.1.0`\n[HELP] check `bar` patch definitions for `https://github.com/rust-lang/crates.io-index` in `[ROOT]/foo/Cargo.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patch_same_version_different_patch_locations() {\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    [dependencies]\n                    bar = \"0.1\"\n                    [patch.crates-io]\n                    bar2 = {{ git = '{}', package = 'bar' }}\n                \"#,\n                bar.url(),\n            ),\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [patch.crates-io]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/override`\n[ERROR] several `[patch]` entries resolving to same version `bar v0.1.0`\n[HELP] check `bar` patch definitions for `https://github.com/rust-lang/crates.io-index` in `[ROOT]/foo/.cargo/config.toml`, `[ROOT]/foo/Cargo.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn two_semver_compatible() {\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    cargo_test_support::registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    [dependencies]\n                    bar = \"0.1\"\n                    [patch.crates-io]\n                    bar = {{ path = \"bar\" }}\n                    bar2 = {{ git = '{}', package = 'bar' }}\n                \"#,\n                bar.url(),\n            ),\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() { bar::foo() }\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.2\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    // assert the build succeeds and doesn't panic anywhere, and then afterwards\n    // assert that the build succeeds again without updating anything or\n    // building anything else.\n    p.cargo(\"check\").run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] patch `bar v0.1.1 ([ROOTURL]/override#[..])` was not used in the crate graph\n  |\n  = [HELP] perhaps you meant one of the following:\n          \t[ROOT]/foo/bar\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multipatch_select_big() {\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    cargo_test_support::registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    [dependencies]\n                    bar = \"*\"\n                    [patch.crates-io]\n                    bar = {{ path = \"bar\" }}\n                    bar2 = {{ git = '{}', package = 'bar' }}\n                \"#,\n                bar.url(),\n            ),\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() { bar::foo() }\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.2.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    // assert the build succeeds, which is only possible if 0.2.0 is selected\n    // since 0.1.0 is missing the function we need. Afterwards assert that the\n    // build succeeds again without updating anything or building anything else.\n    p.cargo(\"check\").run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] patch `bar v0.1.0 ([ROOTURL]/override#[..])` was not used in the crate graph\n  |\n  = [HELP] perhaps you meant one of the following:\n          \t[ROOT]/foo/bar\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn canonicalize_a_bunch() {\n    let base = git::repo(&paths::root().join(\"base\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"base\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let intermediate = git::repo(&paths::root().join(\"intermediate\"))\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"intermediate\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    # Note the lack of trailing slash\n                    base = {{ git = '{}' }}\n                \"#,\n                base.url(),\n            ),\n        )\n        .file(\"src/lib.rs\", \"pub fn f() { base::f() }\")\n        .build();\n\n    let newbase = git::repo(&paths::root().join(\"newbase\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"base\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn f() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    # Note the trailing slashes\n                    base = {{ git = '{base}/' }}\n                    intermediate = {{ git = '{intermediate}/' }}\n\n                    [patch.'{base}'] # Note the lack of trailing slash\n                    base = {{ git = '{newbase}' }}\n                \"#,\n                base = base.url(),\n                intermediate = intermediate.url(),\n                newbase = newbase.url(),\n            ),\n        )\n        .file(\"src/lib.rs\", \"pub fn a() { base::f(); intermediate::f() }\")\n        .build();\n\n    // Once to make sure it actually works\n    p.cargo(\"check\").run();\n\n    // Then a few more times for good measure to ensure no weird warnings about\n    // `[patch]` are printed.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_unused_new_version() {\n    // If there is an unused patch entry, and then you update the patch,\n    // make sure `cargo update` will be able to fix the lock file.\n    Package::new(\"bar\", \"0.1.5\").publish();\n\n    // Start with a lock file to 0.1.5, and an \"unused\" patch because the\n    // version is too old.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1.5\"\n\n                [patch.crates-io]\n                bar = { path = \"../bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Patch is too old.\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.4\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[WARNING] patch `bar v0.1.4 ([ROOT]/bar)` was not used in the crate graph\n...\n\"#]])\n        .run();\n    // unused patch should be in the lock file\n    let lock = p.read_lockfile();\n    let toml: toml::Table = toml::from_str(&lock).unwrap();\n    assert_eq!(toml[\"patch\"][\"unused\"].as_array().unwrap().len(), 1);\n    assert_eq!(toml[\"patch\"][\"unused\"][0][\"name\"].as_str(), Some(\"bar\"));\n    assert_eq!(\n        toml[\"patch\"][\"unused\"][0][\"version\"].as_str(),\n        Some(\"0.1.4\")\n    );\n\n    // Oh, OK, let's update to the latest version.\n    bar.change_file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.6\"));\n\n    // Create a backup so we can test it with different options.\n    fs::copy(p.root().join(\"Cargo.lock\"), p.root().join(\"Cargo.lock.bak\")).unwrap();\n\n    // Try to build again, this should automatically update Cargo.lock.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ADDING] bar v0.1.6 ([ROOT]/bar)\n[CHECKING] bar v0.1.6 ([ROOT]/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // This should not update any registry.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(!p.read_lockfile().contains(\"unused\"));\n\n    // Restore the lock file, and see if `update` will work, too.\n    fs::copy(p.root().join(\"Cargo.lock.bak\"), p.root().join(\"Cargo.lock\")).unwrap();\n\n    // Try `update <pkg>`.\n    p.cargo(\"update bar\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ADDING] bar v0.1.6 ([ROOT]/bar)\n[REMOVING] bar v0.1.5\n\n\"#]])\n        .run();\n\n    // Try with bare `cargo update`.\n    fs::copy(p.root().join(\"Cargo.lock.bak\"), p.root().join(\"Cargo.lock\")).unwrap();\n    p.cargo(\"update\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ADDING] bar v0.1.6 ([ROOT]/bar)\n[REMOVING] bar v0.1.5\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn too_many_matches() {\n    // The patch locations has multiple versions that match.\n    registry::alt_init();\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.0\").alternative(true).publish();\n    Package::new(\"bar\", \"0.1.1\").alternative(true).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1\"\n\n                [patch.crates-io]\n                bar = { version = \"0.1\", registry = \"alternative\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Picks 0.1.1, the most recent version.\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] patch for `bar` in `registry `alternative`` resolved to more than one candidate\n[NOTE] found versions: 0.1.0, 0.1.1\n[HELP] check `bar` patch definition for `https://github.com/rust-lang/crates.io-index` in `[ROOT]/foo/Cargo.toml`\n[HELP] select only one package using `version = \"=0.1.1\"`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn too_many_matches_in_git_repo() {\n    // The patch location has multiple versions that match.\n    Package::new(\"bar\", \"0.1.0\").publish();\n    let git_repo = git::repo(&paths::root().join(\"git-repo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n        [workspace]\n        members = [\"bar\", \"bar2\"]\n        \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"bar2/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar2/src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1\"\n\n                [patch.crates-io]\n                bar = {{ version = \"0.1\", git = '{}' }}\n            \"#,\n                git_repo.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"bar2/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar2/src/lib.rs\", \"\")\n        .build();\n\n    // Picks 0.1.1, the most recent version.\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/git-repo`\n[ERROR] patch for `bar` in `[ROOTURL]/git-repo` resolved to more than one candidate\n[NOTE] found versions: 0.1.0, 0.1.1\n[HELP] check `bar` patch definition for `https://github.com/rust-lang/crates.io-index` in `[ROOT]/foo/Cargo.toml`\n[HELP] select only one package using `version = \"=0.1.1\"`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_matches() {\n    // A patch to a location that does not contain the named package.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                 [package]\n                 name = \"foo\"\n                 version = \"0.1.0\"\n                 edition = \"2015\"\n\n                 [dependencies]\n                 bar = \"0.1\"\n\n                 [patch.crates-io]\n                 bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"abc\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] patch location `[ROOT]/foo/bar` does not contain packages matching `bar`\n[HELP] check `bar` patch definition for `https://github.com/rust-lang/crates.io-index` in `[ROOT]/foo/Cargo.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn mismatched_version() {\n    // A patch to a location that has an old version.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                 [package]\n                 name = \"foo\"\n                 version = \"0.1.0\"\n                 edition = \"2015\"\n\n                 [dependencies]\n                 bar = \"0.1.1\"\n\n                 [patch.crates-io]\n                 bar = { path = \"bar\", version = \"0.1.1\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] patch `bar` version mismatch\n[NOTE] patch location contains version `0.1.0`, but patch definition requires `^0.1.1`\n[HELP] check patch location `[ROOT]/foo/bar`\n[HELP] check `bar` patch definition for `https://github.com/rust-lang/crates.io-index` in `[ROOT]/foo/Cargo.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn mismatched_version_from_cli_config() {\n    // A patch to a location that has an old version.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                 [package]\n                 name = \"foo\"\n                 version = \"0.1.0\"\n                 edition = \"2015\"\n\n                 [dependencies]\n                 bar = \"0.1.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .arg_line(\"--config 'patch.crates-io.bar.path=\\\"bar\\\"'\")\n        .arg_line(\"--config 'patch.crates-io.bar.version=\\\"0.1.1\\\"'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] patch `bar` version mismatch\n[NOTE] patch location contains version `0.1.0`, but patch definition requires `^0.1.1`\n[HELP] check patch location `[ROOT]/foo/bar`\n[HELP] check `bar` patch definition for `https://github.com/rust-lang/crates.io-index` in `--config cli option`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn mismatched_version_from_config_file_provided_via_cli() {\n    Package::new(\"bar\", \"0.1.1\").publish(); // original dependency\n\n    // A patch to a location that has an old version.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                 [package]\n                 name = \"foo\"\n                 version = \"0.1.0\"\n                 edition = \"2015\"\n\n                 [dependencies]\n                 bar = \"0.1.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"tmp/my-config.toml\",\n            r#\"\n                [patch.crates-io]\n                bar = { path = 'bar', version = '0.1.1' }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .arg_line(\"--config tmp/my-config.toml\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] patch `bar` version mismatch\n[NOTE] patch location contains version `0.1.0`, but patch definition requires `^0.1.1`\n[HELP] check patch location `[ROOT]/foo/bar`\n[HELP] check `bar` patch definition for `https://github.com/rust-lang/crates.io-index` in `[ROOT]/foo/tmp/my-config.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patch_from_env_config_is_ignored() {\n    Package::new(\"bar\", \"1.0.0\").publish(); // original dependency\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                 [package]\n                 name = \"foo\"\n                 version = \"0.1.0\"\n                 edition = \"2015\"\n\n                 [dependencies]\n                 bar = \"1.0.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // copy of the [mismatched_version_from_cli_config] cli options using conversion to env\n    // described in https://doc.rust-lang.org/cargo/reference/config.html#environment-variables\n    p.cargo(\"check\")\n        .env(\"CARGO_PATCH_CRATES_IO_BAR_PATH\", \"bar\")\n        .env(\"CARGO_PATCH_CRATES_IO_BAR_VERSION\", \"0.1.1\")\n        .with_status(0)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] bar v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patch_walks_backwards() {\n    // Starting with a locked patch, change the patch so it points to an older version.\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"0.1\"\n\n            [patch.crates-io]\n            bar = {path=\"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.1 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Somehow the user changes the version backwards.\n    p.change_file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"));\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNGRADING] bar v0.1.1 ([ROOT]/foo/bar) -> v0.1.0\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patch_walks_backwards_restricted() {\n    // This is the same as `patch_walks_backwards`, but the patch contains a\n    // `version` qualifier. This is unusual, just checking a strange edge case.\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"0.1\"\n\n            [patch.crates-io]\n            bar = {path=\"bar\", version=\"0.1.1\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.1 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Somehow the user changes the version backwards.\n    p.change_file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"));\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] patch `bar` version mismatch\n[NOTE] patch location contains version `0.1.0`, but patch definition requires `^0.1.1`\n[HELP] check patch location `[ROOT]/foo/bar`\n[HELP] check `bar` patch definition for `https://github.com/rust-lang/crates.io-index` in `[ROOT]/foo/Cargo.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patched_dep_new_version() {\n    // What happens when a patch is locked, and then one of the patched\n    // dependencies needs to be updated. In this case, the baz requirement\n    // gets updated from 0.1.0 to 0.1.1.\n    Package::new(\"bar\", \"0.1.0\").dep(\"baz\", \"0.1.0\").publish();\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"0.1\"\n\n            [patch.crates-io]\n            bar = {path=\"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            baz = \"0.1\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    // Lock everything.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`)\n[CHECKING] baz v0.1.0\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    Package::new(\"baz\", \"0.1.1\").publish();\n\n    // Just the presence of the new version should not have changed anything.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Modify the patch so it requires the new version.\n    p.change_file(\n        \"bar/Cargo.toml\",\n        r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            baz = \"0.1.1\"\n        \"#,\n    );\n\n    // Should unlock and update cleanly.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] baz v0.1.0 -> v0.1.1\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.1.1 (registry `dummy-registry`)\n[CHECKING] baz v0.1.1\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patch_update_doesnt_update_other_sources() {\n    // Very extreme edge case, make sure a patch update doesn't update other\n    // sources.\n    registry::alt_init();\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.0\").alternative(true).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"0.1\"\n            bar_alt = { version = \"0.1\", registry = \"alternative\", package = \"bar\"  }\n\n            [patch.crates-io]\n            bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] `alternative` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `alternative`)\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[CHECKING] bar v0.1.0 (registry `alternative`)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    // Publish new versions in both sources.\n    Package::new(\"bar\", \"0.1.1\").publish();\n    Package::new(\"bar\", \"0.1.1\").alternative(true).publish();\n\n    // Since it is locked, nothing should change.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Require new version on crates.io.\n    p.change_file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"));\n\n    // This should not update bar_alt.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.1.0 ([ROOT]/foo/bar) -> v0.1.1\n[CHECKING] bar v0.1.1 ([ROOT]/foo/bar)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn can_update_with_alt_reg() {\n    // A patch to an alt reg can update.\n    registry::alt_init();\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.0\").alternative(true).publish();\n    Package::new(\"bar\", \"0.1.1\").alternative(true).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1\"\n\n                [patch.crates-io]\n                bar = { version = \"=0.1.1\", registry = \"alternative\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.1 (registry `alternative`)\n[CHECKING] bar v0.1.1 (registry `alternative`)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    Package::new(\"bar\", \"0.1.2\").alternative(true).publish();\n\n    // Should remain locked.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // This does nothing, due to `=` requirement.\n    p.cargo(\"update bar\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[UPDATING] `dummy-registry` index\n[LOCKING] 0 packages to latest compatible versions\n[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest\n\n\"#]])\n        .run();\n\n    // Bump to 0.1.2.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"0.1\"\n\n            [patch.crates-io]\n            bar = { version = \"=0.1.2\", registry = \"alternative\" }\n        \"#,\n    );\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.1.1 (registry `alternative`) -> v0.1.2\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.2 (registry `alternative`)\n[CHECKING] bar v0.1.2 (registry `alternative`)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn gitoxide_clones_shallow_old_git_patch() {\n    perform_old_git_patch(true)\n}\n\nfn perform_old_git_patch(shallow: bool) {\n    // Example where an old lockfile with an explicit branch=\"master\" in Cargo.toml.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let (bar, bar_repo) = git::new_repo(\"bar\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let bar_oid = bar_repo.head().unwrap().target().unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    bar = \"1.0\"\n\n                    [patch.crates-io]\n                    bar = {{ git = \"{}\", branch = \"master\" }}\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\n            \"Cargo.lock\",\n            &format!(\n                r#\"\n# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\n[[package]]\nname = \"bar\"\nversion = \"1.0.0\"\nsource = \"git+{}#{}\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.1.0\"\ndependencies = [\n \"bar\",\n]\n            \"#,\n                bar.url(),\n                bar_oid\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    bar.change_file(\"Cargo.toml\", &basic_manifest(\"bar\", \"2.0.0\"));\n    git::add(&bar_repo);\n    git::commit(&bar_repo);\n\n    // This *should* keep the old lock.\n    let mut cargo = p.cargo(\"tree\");\n    if shallow {\n        cargo\n            .arg(\"-Zgitoxide=fetch\")\n            .arg(\"-Zgit=shallow-deps\")\n            .masquerade_as_nightly_cargo(&[\n                \"unstable features must be available for -Z gitoxide and -Z git\",\n            ]);\n    }\n    cargo\n        // .env(\"CARGO_LOG\", \"trace\")\n        .with_stderr_data(\n            \"\\\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[ADDING] bar v1.0.0 ([ROOTURL]/bar?branch=master#[..])\n\",\n        )\n        // .with_status(1)\n        .with_stdout_data(format!(\n            \"\\\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v1.0.0 ([ROOTURL]/bar?branch=master#{})\n\",\n            &bar_oid.to_string()[..8]\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn old_git_patch() {\n    perform_old_git_patch(false)\n}\n\n// From https://github.com/rust-lang/cargo/issues/7463\n#[cargo_test]\nfn patch_eq_conflict_panic() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.1\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"=0.1.0\"\n\n                [dev-dependencies]\n                bar = \"=0.1.1\"\n\n                [patch.crates-io]\n                bar = {path=\"bar\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for `bar`.\n    ... required by package `foo v0.1.0 ([ROOT]/foo)`\nversions that meet the requirements `=0.1.1` are: 0.1.1\n\nall possible versions conflict with previously selected packages.\n\n  previously selected package `bar v0.1.0`\n    ... which satisfies dependency `bar = \"=0.1.0\"` of package `foo v0.1.0 ([ROOT]/foo)`\n\nfailed to select a version for `bar` which could resolve this conflict\n\n\"#]])\n        .run();\n}\n\n// From https://github.com/rust-lang/cargo/issues/11336\n#[cargo_test]\nfn mismatched_version2() {\n    Package::new(\"qux\", \"0.1.0-beta.1\").publish();\n    Package::new(\"qux\", \"0.1.0-beta.2\").publish();\n    Package::new(\"bar\", \"0.1.0\")\n        .dep(\"qux\", \"=0.1.0-beta.1\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                 [package]\n                 name = \"foo\"\n                 version = \"0.1.0\"\n                 edition = \"2015\"\n\n                 [dependencies]\n                 bar = \"0.1.0\"\n                 qux = \"0.1.0-beta.2\"\n\n                 [patch.crates-io]\n                 qux = { path = \"qux\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"qux/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"qux\"\n                version = \"0.1.0-beta.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"qux/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for `qux`.\n    ... required by package `bar v0.1.0`\n    ... which satisfies dependency `bar = \"^0.1.0\"` of package `foo v0.1.0 ([ROOT]/foo)`\nversions that meet the requirements `=0.1.0-beta.1` are: 0.1.0-beta.1\n\nall possible versions conflict with previously selected packages.\n\n  previously selected package `qux v0.1.0-beta.2`\n    ... which satisfies dependency `qux = \"^0.1.0-beta.2\"` of package `foo v0.1.0 ([ROOT]/foo)`\n\nfailed to select a version for `qux` which could resolve this conflict\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn mismatched_version_with_prerelease() {\n    Package::new(\"prerelease-deps\", \"0.0.1\").publish();\n    // A patch to a location that has an prerelease version\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                 [package]\n                 name = \"foo\"\n                 version = \"0.1.0\"\n                 edition = \"2015\"\n\n                 [dependencies]\n                 prerelease-deps = \"0.1.0\"\n\n                 [patch.crates-io]\n                 prerelease-deps = { path = \"./prerelease-deps\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"prerelease-deps/Cargo.toml\",\n            &basic_manifest(\"prerelease-deps\", \"0.1.1-pre1\"),\n        )\n        .file(\"prerelease-deps/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `prerelease-deps = \"^0.1.0\"`\ncandidate versions found which didn't match: 0.1.1-pre1, 0.0.1\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.1.0 ([ROOT]/foo)`\nif you are looking for the prerelease package it needs to be specified explicitly\n    prerelease-deps = { version = \"0.1.1-pre1\" }\nperhaps a crate was updated and forgotten to be re-vendored?\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn from_config_empty() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [patch.'']\n                bar = { path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] [patch] entry `` should be a URL or registry name\n\nCaused by:\n  invalid url ``: relative URL without a base\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn from_manifest_empty() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n\n                [patch.'']\n                bar = { path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.1\"))\n        .file(\"bar/src/lib.rs\", r#\"\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  [patch] entry `` should be a URL or registry name\n\nCaused by:\n  invalid url ``: relative URL without a base\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patched_reexport_stays_locked() {\n    // Patch example where you emulate a semver-incompatible patch via a re-export.\n    // Testing an issue where the lockfile does not stay locked after a new version is published.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"2.0.0\").publish();\n    Package::new(\"bar\", \"3.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n\n\n                [package]\n                name = \"foo\"\n\n                [dependencies]\n                bar1 = {package=\"bar\", version=\"1.0.0\"}\n                bar2 = {package=\"bar\", version=\"2.0.0\"}\n\n                [patch.crates-io]\n                bar1 = { package = \"bar\", path = \"bar-1-as-3\" }\n                bar2 = { package = \"bar\", path = \"bar-2-as-3\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar-1-as-3/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"1.0.999\"\n\n                [dependencies]\n                bar = \"3.0.0\"\n            \"#,\n        )\n        .file(\"bar-1-as-3/src/lib.rs\", \"\")\n        .file(\n            \"bar-2-as-3/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"2.0.999\"\n\n                [dependencies]\n                bar = \"3.0.0\"\n            \"#,\n        )\n        .file(\"bar-2-as-3/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.0 ([ROOT]/foo)\n├── bar v1.0.999 ([ROOT]/foo/bar-1-as-3)\n│   └── bar v3.0.0\n└── bar v2.0.999 ([ROOT]/foo/bar-2-as-3)\n    └── bar v3.0.0\n\n\"#]])\n        .run();\n\n    std::fs::copy(\n        p.root().join(\"Cargo.lock\"),\n        p.root().join(\"Cargo.lock.orig\"),\n    )\n    .unwrap();\n\n    Package::new(\"bar\", \"3.0.1\").publish();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.0 ([ROOT]/foo)\n├── bar v1.0.999 ([ROOT]/foo/bar-1-as-3)\n│   └── bar v3.0.0\n└── bar v2.0.999 ([ROOT]/foo/bar-2-as-3)\n    └── bar v3.0.0\n\n\"#]])\n        .run();\n\n    assert_eq!(p.read_file(\"Cargo.lock\"), p.read_file(\"Cargo.lock.orig\"));\n}\n\n#[cargo_test]\nfn patch_in_real_with_base() {\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"pub fn hello() {}\")\n        .build();\n    Package::new(\"bar\", \"0.5.0\").publish();\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [path-bases]\n                    test = '{}'\n                \"#,\n                bar.root().parent().unwrap().display()\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n                edition = \"2018\"\n\n                [dependencies]\n                bar = \"0.5.0\"\n\n                [patch.crates-io]\n                bar = { base = 'test', path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"use bar::hello as _;\")\n        .build();\n\n    p.cargo(\"tree\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .with_stdout_data(str![[r#\"\nfoo v0.5.0 ([ROOT]/foo)\n└── bar v0.5.0 ([ROOT]/bar)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn patch_in_virtual_with_base() {\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"pub fn hello() {}\")\n        .build();\n    Package::new(\"bar\", \"0.5.0\").publish();\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [path-bases]\n                    test = '{}'\n                \"#,\n                bar.root().parent().unwrap().display()\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [workspace]\n                members = [\"foo\"]\n\n                [patch.crates-io]\n                bar = { base = 'test', path = 'bar' }\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n                edition = \"2018\"\n\n                [dependencies]\n                bar = \"0.5.0\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"use bar::hello as _;\")\n        .build();\n\n    p.cargo(\"tree\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .with_stdout_data(str![[r#\"\nfoo v0.5.0 ([ROOT]/foo/foo)\n└── bar v0.5.0 ([ROOT]/bar)\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/path.rs",
    "content": "//! Tests for `path` dependencies.\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_lib_manifest, basic_manifest, main_file, project};\nuse cargo_test_support::{sleep_ms, t};\n\n#[cargo_test]\n// I have no idea why this is failing spuriously on Windows;\n// for more info, see #3466.\n#[cfg(not(windows))]\nfn cargo_compile_with_nested_deps_shorthand() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n\n                version = \"0.5.0\"\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.baz]\n\n                version = \"0.5.0\"\n                path = \"baz\"\n\n                [lib]\n\n                name = \"bar\"\n            \"#,\n        )\n        .file(\n            \"bar/src/bar.rs\",\n            r#\"\n                extern crate baz;\n\n                pub fn gimme() -> String {\n                    baz::gimme()\n                }\n            \"#,\n        )\n        .file(\"bar/baz/Cargo.toml\", &basic_lib_manifest(\"baz\"))\n        .file(\n            \"bar/baz/src/baz.rs\",\n            r#\"\n                pub fn gimme() -> String {\n                    \"test passed\".to_string()\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] baz v0.5.0 ([ROOT]/foo/bar/baz)\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\ntest passed\n\n\"#]])\n        .run();\n\n    println!(\"cleaning\");\n    p.cargo(\"clean -v\")\n        .with_stderr_data(str![[r#\"\n[REMOVING] [ROOT]/foo/target\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    println!(\"building baz\");\n    p.cargo(\"build -p baz\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] baz v0.5.0 ([ROOT]/foo/bar/baz)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    println!(\"building foo\");\n    p.cargo(\"build -p foo\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_root_dev_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dev-dependencies.bar]\n\n                version = \"0.5.0\"\n                path = \"../bar\"\n\n                [[bin]]\n                name = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n        .build();\n    let _p2 = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn gimme() -> &'static str {\n                    \"zoidberg\"\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\nerror[E0463]: can't find crate for `bar`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_root_dev_deps_with_testing() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dev-dependencies.bar]\n\n                version = \"0.5.0\"\n                path = \"../bar\"\n\n                [[bin]]\n                name = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n        .build();\n    let _p2 = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn gimme() -> &'static str {\n                    \"zoidberg\"\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/bar)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_compile_with_transitive_dev_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n\n                version = \"0.5.0\"\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dev-dependencies.baz]\n\n                git = \"git://example.com/path/to/nowhere\"\n\n                [lib]\n\n                name = \"bar\"\n            \"#,\n        )\n        .file(\n            \"bar/src/bar.rs\",\n            r#\"\n                pub fn gimme() -> &'static str {\n                    \"zoidberg\"\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nzoidberg\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_rebuild_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() { bar::bar() }\")\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/bar.rs\", \"pub fn bar() {}\")\n        .build();\n    // First time around we should compile both foo and bar\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.5.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    sleep_ms(1000);\n    p.change_file(\n        \"src/main.rs\",\n        r#\"\n            extern crate bar;\n            fn main() { bar::bar(); }\n        \"#,\n    );\n    // Don't compile bar, but do recompile foo.\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn deep_dependencies_trigger_rebuild() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() { bar::bar() }\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [lib]\n                name = \"bar\"\n                [dependencies.baz]\n                path = \"../baz\"\n            \"#,\n        )\n        .file(\n            \"bar/src/bar.rs\",\n            \"extern crate baz; pub fn bar() { baz::baz() }\",\n        )\n        .file(\"baz/Cargo.toml\", &basic_lib_manifest(\"baz\"))\n        .file(\"baz/src/baz.rs\", \"pub fn baz() {}\")\n        .build();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] baz v0.5.0 ([ROOT]/foo/baz)\n[CHECKING] bar v0.5.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Make sure an update to baz triggers a rebuild of bar\n    //\n    // We base recompilation off mtime, so sleep for at least a second to ensure\n    // that this write will change the mtime.\n    sleep_ms(1000);\n    p.change_file(\"baz/src/baz.rs\", r#\"pub fn baz() { println!(\"hello!\"); }\"#);\n    sleep_ms(1000);\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] baz v0.5.0 ([ROOT]/foo/baz)\n[CHECKING] bar v0.5.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Make sure an update to bar doesn't trigger baz\n    sleep_ms(1000);\n    p.change_file(\n        \"bar/src/bar.rs\",\n        r#\"\n            extern crate baz;\n            pub fn bar() { println!(\"hello!\"); baz::baz(); }\n        \"#,\n    );\n    sleep_ms(1000);\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.5.0 ([ROOT]/foo/bar)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_rebuild_two_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n                [dependencies.baz]\n                path = \"baz\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() { bar::bar() }\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [lib]\n                name = \"bar\"\n                [dependencies.baz]\n                path = \"../baz\"\n            \"#,\n        )\n        .file(\"bar/src/bar.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_lib_manifest(\"baz\"))\n        .file(\"baz/src/baz.rs\", \"pub fn baz() {}\")\n        .build();\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] baz v0.5.0 ([ROOT]/foo/baz)\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(p.bin(\"foo\").is_file());\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(p.bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn nested_deps_recompile() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n\n                version = \"0.5.0\"\n                path = \"src/bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n        .file(\"src/bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"src/bar/src/bar.rs\", \"pub fn gimme() -> i32 { 92 }\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.5.0 ([ROOT]/foo/src/bar)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    sleep_ms(1000);\n\n    p.change_file(\"src/main.rs\", r#\"fn main() {}\"#);\n\n    // This shouldn't recompile `bar`\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn error_message_for_missing_manifest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n\n                path = \"src/bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bar/not-a-manifest\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to get `bar` as a dependency of package `foo v0.5.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update [ROOT]/foo/src/bar\n\nCaused by:\n  failed to read `[ROOT]/foo/src/bar/Cargo.toml`\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn path_bases_not_stable() {\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [path-bases]\n                    test = '{}'\n                \"#,\n                bar.root().parent().unwrap().display()\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies]\n                bar = { base = 'test', path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(\n            \"\\\n[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml`\n\nCaused by:\n  resolving path dependency bar\n\nCaused by:\n  feature `path-bases` is required\n\n  The package requires the Cargo feature called `path-bases`, but that feature is not stabilized in this version of Cargo ([..]).\n  Consider trying a newer version of Cargo (this may require the nightly release).\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#path-bases for more information about the status of this feature.\n\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn path_with_base() {\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [path-bases]\n                    test = '{}'\n                \"#,\n                bar.root().parent().unwrap().display()\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies]\n                bar = { base = 'test', path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .run();\n}\n\n#[cargo_test]\nfn current_dir_with_base() {\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [path-bases]\n                    test = '{}'\n                \"#,\n                bar.root().display()\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies]\n                bar = { base = 'test', path = '.' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .run();\n}\n\n#[cargo_test]\nfn parent_dir_with_base() {\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [path-bases]\n                    test = '{}/subdir'\n                \"#,\n                bar.root().display()\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies]\n                bar = { base = 'test', path = '..' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .run();\n}\n\n#[cargo_test]\nfn inherit_dependency_using_base() {\n    let bar = project()\n        .at(\"dep_with_base\")\n        .file(\"Cargo.toml\", &basic_manifest(\"dep_with_base\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [path-bases]\n                    test = '{}'\n                \"#,\n                bar.root().parent().unwrap().display()\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"parent\"\n                version = \"0.1.0\"\n                authors = []\n\n                [workspace]\n                members = [\"child\"]\n\n                [workspace.dependencies]\n                dep_with_base = { base = 'test', path = 'dep_with_base' }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"child/Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"child\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                dep_with_base = { workspace = true }\n            \"#,\n        )\n        .file(\"child/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .run();\n}\n\n#[cargo_test]\nfn path_with_relative_base() {\n    project()\n        .at(\"shared_proj/bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"../.cargo/config.toml\",\n            r#\"\n                [path-bases]\n                test = 'shared_proj'\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies]\n                bar = { base = 'test', path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_builtin_base() {\n    project()\n        .at(\"dep_with_base\")\n        .file(\"Cargo.toml\", &basic_manifest(\"dep_with_base\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"parent\"\n                version = \"0.1.0\"\n                authors = []\n\n                [workspace]\n                members = [\"child\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"child/Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"child\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                dep_with_base = { base = 'workspace', path = '../dep_with_base' }\n            \"#,\n        )\n        .file(\"child/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_builtin_base_not_a_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                bar = { base = 'workspace', path = 'bar' }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .with_status(101)\n        .with_stderr_data(\n            \"\\\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  resolving path dependency bar\n\nCaused by:\n  failed to find a workspace root\n\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn shadow_workspace_builtin_base() {\n    let bar = project()\n        .at(\"dep_with_base\")\n        .file(\"Cargo.toml\", &basic_manifest(\"dep_with_base\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [path-bases]\n                    workspace = '{}/subdir/anotherdir'\n                \"#,\n                bar.root().parent().unwrap().display()\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"parent\"\n                version = \"0.1.0\"\n                authors = []\n\n                [workspace]\n                members = [\"child\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"child/Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"child\"\n                version = \"0.1.0\"\n                authors = []\n\n                [dependencies]\n                dep_with_base = { base = 'workspace', path = '../../dep_with_base' }\n            \"#,\n        )\n        .file(\"child/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .run();\n}\n\n#[cargo_test]\nfn unknown_base() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies]\n                bar = { base = 'test', path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .with_status(101)\n        .with_stderr_data(\n            \"\\\n[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml`\n\nCaused by:\n  resolving path dependency bar\n\nCaused by:\n  path base `test` is undefined. You must add an entry for `test` in the Cargo configuration [path-bases] table.\n\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn base_without_path() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies]\n                bar = { version = '1.0.0', base = 'test' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .with_status(101)\n        .with_stderr_data(\n            \"\\\n[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml`\n\nCaused by:\n  resolving path dependency bar\n\nCaused by:\n  `base` can only be used with path dependencies\n\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn invalid_base() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies]\n                bar = { base = '^^not-valid^^', path = 'bar' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .with_status(101)\n        .with_stderr_data(\n            \"\\\n[ERROR] invalid character `^` in path base name: `^^not-valid^^`, the first character must be a Unicode XID start character (most letters or `_`)\n       \n       \n  --> Cargo.toml:10:23\n   |\n10 |                 bar = { base = '^^not-valid^^', path = 'bar' }\n   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn invalid_path_with_base() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [path-bases]\n            test = 'shared_proj'\n        \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                authors = [\"wycats@example.com\"]\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { base = 'test', path = '\"' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to get `bar` as a dependency of package `foo v0.5.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update [ROOT]/foo/shared_proj/\"\n\nCaused by:\n  failed to read `[ROOT]/foo/shared_proj/\"/Cargo.toml`\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn self_dependency_using_base() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [path-bases]\n            test = '.'\n        \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"path-bases\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n                edition = \"2015\"\n\n                [dependencies]\n                foo = { base = 'test', path = '.' }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\")\n        .masquerade_as_nightly_cargo(&[\"path-bases\"])\n        .with_status(101)\n        .with_stderr_data(\n            \"\\\n[ERROR] cyclic package dependency: package `foo v0.1.0 ([ROOT]/foo)` depends on itself. Cycle:\npackage `foo v0.1.0 ([ROOT]/foo)`\n    ... which satisfies path dependency `foo` of package `foo v0.1.0 ([ROOT]/foo)`\n\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn override_relative() {\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    fs::create_dir(&paths::root().join(\".cargo\")).unwrap();\n    fs::write(\n        &paths::root().join(\".cargo/config.toml\"),\n        r#\"paths = [\"bar\"]\"#,\n    )\n    .unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.bar]\n                    path = '{}'\n                \"#,\n                bar.root().display()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn override_self() {\n    let bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project();\n    let root = p.root();\n    let p = p\n        .file(\n            \".cargo/config.toml\",\n            &format!(\"paths = ['{}']\", root.display()),\n        )\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.bar]\n                    path = '{}'\n\n                \"#,\n                bar.root().display()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn override_path_dep() {\n    let bar = project()\n        .at(\"bar\")\n        .file(\n            \"p1/Cargo.toml\",\n            r#\"\n                 [package]\n                 name = \"p1\"\n                 version = \"0.5.0\"\n                 edition = \"2015\"\n                 authors = []\n\n                 [dependencies.p2]\n                 path = \"../p2\"\n            \"#,\n        )\n        .file(\"p1/src/lib.rs\", \"\")\n        .file(\"p2/Cargo.toml\", &basic_manifest(\"p2\", \"0.5.0\"))\n        .file(\"p2/src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                \"paths = ['{}', '{}']\",\n                bar.root().join(\"p1\").display(),\n                bar.root().join(\"p2\").display()\n            ),\n        )\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = [\"wycats@example.com\"]\n\n                    [dependencies.p2]\n                    path = '{}'\n\n                \"#,\n                bar.root().join(\"p2\").display()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn path_dep_build_cmd() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n\n                [dependencies.bar]\n\n                version = \"0.5.0\"\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &main_file(r#\"\"{}\", bar::gimme()\"#, &[\"bar\"]))\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"wycats@example.com\"]\n                build = \"build.rs\"\n\n                [lib]\n                name = \"bar\"\n                path = \"src/bar.rs\"\n            \"#,\n        )\n        .file(\n            \"bar/build.rs\",\n            r#\"\n                use std::fs;\n                fn main() {\n                    fs::copy(\"src/bar.rs.in\", \"src/bar.rs\").unwrap();\n                }\n            \"#,\n        )\n        .file(\"bar/src/bar.rs.in\", \"pub fn gimme() -> i32 { 0 }\")\n        .build();\n    p.root().join(\"bar\").move_into_the_past();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\n0\n\n\"#]])\n        .run();\n\n    // Touching bar.rs.in should cause the `build` command to run again.\n    p.change_file(\"bar/src/bar.rs.in\", \"pub fn gimme() -> i32 { 1 }\");\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\n1\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dev_deps_no_rebuild_lib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n                    authors = []\n\n                [dev-dependencies.bar]\n                    path = \"bar\"\n\n                [lib]\n                    name = \"foo\"\n                    doctest = false\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(test)] #[allow(unused_extern_crates)] extern crate bar;\n                #[cfg(not(test))] pub fn foo() { env!(\"FOO\"); }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.5.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n    p.cargo(\"build\")\n        .env(\"FOO\", \"bar\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_target_no_rebuild() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                a = { path = \"a\" }\n                [workspace]\n                members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.5.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                a = { path = \"../a\" }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] a v0.5.0 ([ROOT]/foo/a)\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    t!(fs::rename(\n        p.root().join(\"target\"),\n        p.root().join(\"target_moved\")\n    ));\n    p.cargo(\"check --manifest-path=b/Cargo.toml\")\n        .env(\"CARGO_TARGET_DIR\", \"target_moved\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] b v0.5.0 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn override_and_depend() {\n    let p = project()\n        .no_manifest()\n        .file(\n            \"a/a1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a1\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                a2 = { path = \"../a2\" }\n            \"#,\n        )\n        .file(\"a/a1/src/lib.rs\", \"\")\n        .file(\"a/a2/Cargo.toml\", &basic_manifest(\"a2\", \"0.5.0\"))\n        .file(\"a/a2/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                a1 = { path = \"../a/a1\" }\n                a2 = { path = \"../a/a2\" }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\"b/.cargo/config.toml\", r#\"paths = [\"../a\"]\"#)\n        .build();\n    p.cargo(\"check\")\n        .cwd(\"b\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] a2 v0.5.0 ([ROOT]/foo/a)\n[CHECKING] a1 v0.5.0 ([ROOT]/foo/a)\n[CHECKING] b v0.5.0 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn missing_path_dependency() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"a\", \"0.5.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"paths = [\"../whoa-this-does-not-exist\"]\"#,\n        )\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to update path override `[ROOT]/whoa-this-does-not-exist` (defined in `[ROOT]/foo/.cargo/config.toml`)\n\nCaused by:\n  failed to read directory `[ROOT]/whoa-this-does-not-exist`\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_path_dep_in_workspace_with_lockfile() {\n    Package::new(\"bar\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"top\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n\n                [dependencies]\n                foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    // Generate a lock file\n    p.cargo(\"check\").run();\n\n    // Change the dependency on `bar` to an invalid path\n    p.change_file(\n        \"foo/Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.5.0\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            bar = { path = \"\" }\n        \"#,\n    );\n\n    // Make sure we get a nice error. In the past this actually stack\n    // overflowed!\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no matching package found\nsearched package name: `bar`\nperhaps you meant:      foo\nlocation searched: [ROOT]/foo/foo\nrequired by package `foo v0.5.0 ([ROOT]/foo/foo)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_produces_rlib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"top\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n\n                [dependencies]\n                foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.5.0\"))\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(p.root().join(\"target/debug/libtop.rlib\").is_file());\n    assert!(!p.root().join(\"target/debug/libfoo.rlib\").is_file());\n}\n\n#[cargo_test]\nfn deep_path_error() {\n    // Test for an error loading a path deep in the dependency graph.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            [dependencies]\n            a = {path=\"a\"}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n             [package]\n             name = \"a\"\n             version = \"0.1.0\"\n             edition = \"2015\"\n             [dependencies]\n             b = {path=\"../b\"}\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n             [package]\n             name = \"b\"\n             version = \"0.1.0\"\n             edition = \"2015\"\n             [dependencies]\n             c = {path=\"../c\"}\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to get `c` as a dependency of package `b v0.1.0 ([ROOT]/foo/b)`\n    ... which satisfies path dependency `b` of package `a v0.1.0 ([ROOT]/foo/a)`\n    ... which satisfies path dependency `a` of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `c`\n\nCaused by:\n  unable to update [ROOT]/foo/c\n\nCaused by:\n  failed to read `[ROOT]/foo/c/Cargo.toml`\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn catch_tricky_cycle() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"message\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dev-dependencies]\n                test = { path = \"test\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"tangle/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"tangle\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                message = { path = \"..\" }\n                snapshot = { path = \"../snapshot\" }\n            \"#,\n        )\n        .file(\"tangle/src/lib.rs\", \"\")\n        .file(\n            \"snapshot/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"snapshot\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                ledger = { path = \"../ledger\" }\n            \"#,\n        )\n        .file(\"snapshot/src/lib.rs\", \"\")\n        .file(\n            \"ledger/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"ledger\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                tangle = { path = \"../tangle\" }\n            \"#,\n        )\n        .file(\"ledger/src/lib.rs\", \"\")\n        .file(\n            \"test/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                snapshot = { path = \"../snapshot\" }\n            \"#,\n        )\n        .file(\"test/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[ERROR] cyclic package dependency: package `ledger v0.1.0 ([ROOT]/foo/ledger)` depends on itself. Cycle:\npackage `ledger v0.1.0 ([ROOT]/foo/ledger)`\n...\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn same_name_version_changed() {\n    // Illustrates having two path packages with the same name, but different versions.\n    // Verifies it works correctly when one of the versions is changed.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.0.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                foo2 = { path = \"foo2\", package = \"foo\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"foo2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"2.0.0\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"foo2/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n└── foo v2.0.0 ([ROOT]/foo/foo2)\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \"foo2/Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"2.0.1\"\n            edition = \"2021\"\n        \"#,\n    );\n    p.cargo(\"tree\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ADDING] foo v2.0.1 ([ROOT]/foo/foo2)\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nfoo v1.0.0 ([ROOT]/foo)\n└── foo v2.0.1 ([ROOT]/foo/foo2)\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/paths.rs",
    "content": "//! Tests for `paths` overrides.\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_manifest, project};\n\n#[cargo_test]\nfn broken_path_override_warns() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a1\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"a1/src/lib.rs\", \"\")\n        .file(\n            \"a2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.2\"\n            \"#,\n        )\n        .file(\"a2/src/lib.rs\", \"\")\n        .file(\".cargo/config.toml\", r#\"paths = [\"a2\"]\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[WARNING] path override for crate `a` has altered the original list of\ndependencies; the dependency on `bar` was either added or\nmodified to not match the previously resolved version\n\nThis is currently allowed but is known to produce buggy behavior with spurious\nrecompiles and changes to the crate graph. Path overrides unfortunately were\nnever intended to support this feature, so for now this message is just a\nwarning. In the future, however, this message will become a hard error.\n\nTo change the dependency graph via an override it's recommended to use the\n`[patch]` feature of Cargo instead of the path override feature. This is\ndocumented online at the url below for more information.\n\nhttps://doc.rust-lang.org/cargo/reference/overriding-dependencies.html\n\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.2.0 (registry `dummy-registry`)\n[CHECKING] bar v0.2.0\n[CHECKING] a v0.0.1 ([ROOT]/foo/a2)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn override_to_path_dep() {\n    Package::new(\"bar\", \"0.1.0\").dep(\"baz\", \"0.1\").publish();\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                authors = []\n\n                [dependencies]\n                baz = { path = \"baz\" }\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"bar/baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.0.1\"))\n        .file(\"bar/baz/src/lib.rs\", \"\")\n        .file(\".cargo/config.toml\", r#\"paths = [\"bar\"]\"#)\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn paths_ok_with_optional() {\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = { version = \"0.1\", optional = true }\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"bar2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = { version = \"0.1\", optional = true }\n            \"#,\n        )\n        .file(\"bar2/src/lib.rs\", \"\")\n        .file(\".cargo/config.toml\", r#\"paths = [\"bar2\"]\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar2)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn paths_add_optional_bad() {\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"bar2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n                authors = []\n\n                [dependencies]\n                baz = { version = \"0.1\", optional = true }\n            \"#,\n        )\n        .file(\"bar2/src/lib.rs\", \"\")\n        .file(\".cargo/config.toml\", r#\"paths = [\"bar2\"]\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[WARNING] path override for crate `bar` has altered the original list of\ndependencies; the dependency on `baz` was either added or\nmodified to not match the previously resolved version\n\nThis is currently allowed but is known to produce buggy behavior with spurious\nrecompiles and changes to the crate graph. Path overrides unfortunately were\nnever intended to support this feature, so for now this message is just a\nwarning. In the future, however, this message will become a hard error.\n\nTo change the dependency graph via an override it's recommended to use the\n`[patch]` feature of Cargo instead of the path override feature. This is\ndocumented online at the url below for more information.\n\nhttps://doc.rust-lang.org/cargo/reference/overriding-dependencies.html\n\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar2)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_paths_overrides_not_supported() {\n    Package::new(\"file\", \"0.1.0\").publish();\n    Package::new(\"cli\", \"0.1.0\").publish();\n    Package::new(\"env\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n\n                [dependencies]\n                file = \"0.1.0\"\n                cli = \"0.1.0\"\n                env = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"file/Cargo.toml\", &basic_manifest(\"file\", \"0.2.0\"))\n        .file(\"file/src/lib.rs\", \"\")\n        .file(\"cli/Cargo.toml\", &basic_manifest(\"cli\", \"0.2.0\"))\n        .file(\"cli/src/lib.rs\", \"\")\n        .file(\"env/Cargo.toml\", &basic_manifest(\"env\", \"0.2.0\"))\n        .file(\"env/src/lib.rs\", \"\")\n        .file(\".cargo/config.toml\", r#\"paths = [\"file\"]\"#)\n        .build();\n\n    p.cargo(\"check\")\n        .arg(\"--config\")\n        .arg(\"paths=['cli']\")\n        // paths overrides ignore env\n        .env(\"CARGO_PATHS\", \"env\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] env v0.1.0 (registry `dummy-registry`)\n[CHECKING] file v0.2.0 ([ROOT]/foo/file)\n[CHECKING] cli v0.2.0 ([ROOT]/foo/cli)\n[CHECKING] env v0.1.0\n[CHECKING] foo v0.0.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/pgo.rs",
    "content": "//! Test if PGO works.\n\nuse std::path::PathBuf;\nuse std::process::Command;\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\nfn llvm_profdata() -> Option<PathBuf> {\n    let output = Command::new(\"rustc\")\n        .arg(\"--print=target-libdir\")\n        .output()\n        .expect(\"rustc to run\");\n    assert!(output.status.success());\n    let mut libdir = PathBuf::from(String::from_utf8(output.stdout).unwrap());\n    assert!(libdir.pop());\n    let mut bin = libdir.join(\"bin\").join(\"llvm-profdata\");\n    bin.exists().then(|| bin.clone()).or_else(|| {\n        bin.set_extension(\"exe\");\n        bin.exists().then_some(bin)\n    })\n}\n\n// Rustc build may be without profiling support.\n// Mark it as nightly so it won't run on rust-lang/rust CI.\n#[cfg_attr(\n    target_os = \"linux\",\n    cargo_test(nightly, reason = \"rust-lang/rust#133675\")\n)]\n// macOS may emit different LLVM PGO warnings.\n// Windows LLVM has different requirements.\n#[cfg_attr(not(target_os = \"linux\"), cargo_test, ignore = \"linux only\")]\nfn pgo_works() {\n    let Some(llvm_profdata) = llvm_profdata() else {\n        return;\n    };\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            edition = \"2021\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn fibonacci(n: u64) -> u64 {\n                    match n {\n                        0 => 0,\n                        1 => 1,\n                        _ => fibonacci(n - 1) + fibonacci(n - 2),\n                    }\n                }\n\n                fn main() {\n                    for i in [15, 20, 25] {\n                        let _ = fibonacci(i);\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    let target_dir = p.build_dir();\n    let release_bin = target_dir.join(\"release\").join(\"foo\");\n    let pgo_data_dir = target_dir.join(\"pgo-data\");\n    let profdata_path = target_dir.join(\"merged.profdata\");\n\n    // Build the instrumented binary\n    p.cargo(\"build --release\")\n        .env(\n            \"RUSTFLAGS\",\n            format!(\"-Cprofile-generate={}\", pgo_data_dir.display()),\n        )\n        .run();\n    // Run the instrumented binary\n    cargo_test_support::execs()\n        .with_process_builder(cargo_test_support::process(release_bin))\n        .run();\n\n    cargo_test_support::process(llvm_profdata)\n        .arg(\"merge\")\n        .arg(\"-o\")\n        .arg(&profdata_path)\n        .arg(pgo_data_dir)\n        .status()\n        .unwrap();\n\n    // Use merged profdata during optimization.\n    //\n    // -Cllvm-args=-pgo-warn-missing-function is essential.\n    // If there are LLVM warnings, there might be something wrong.\n    p.cargo(\"build --release -v\")\n        .env(\n            \"RUSTFLAGS\",\n            format!(\n                \"-Cprofile-use={} -Cllvm-args=-pgo-warn-missing-function\",\n                profdata_path.display()\n            ),\n        )\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]-Cprofile-use=[ROOT]/foo/target/merged.profdata -Cllvm-args=-pgo-warn-missing-function`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/pkgid.rs",
    "content": "//! Tests for the `cargo pkgid` command.\n\nuse std::path::PathBuf;\n\nuse crate::prelude::*;\nuse cargo_test_support::basic_bin_manifest;\nuse cargo_test_support::basic_lib_manifest;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::git;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn local() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    p.cargo(\"pkgid foo\")\n        .with_stdout_data(str![[r#\"\npath+[ROOTURL]/foo#0.1.0\n\n\"#]])\n        .run();\n\n    // Bad file URL.\n    p.cargo(\"pkgid ./Cargo.toml\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid package ID specification: `./Cargo.toml`\n\nCaused by:\n  package ID specification `./Cargo.toml` looks like a file path, maybe try [ROOTURL]/foo/Cargo.toml\n\n\"#]])\n        .run();\n\n    // Bad file URL with similar name.\n    p.cargo(\"pkgid './bar'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid package ID specification: `./bar`\n\n[HELP] a package with a similar name exists: `bar`\n\nCaused by:\n  package ID specification `./bar` looks like a file path, maybe try [ROOTURL]/foo/bar\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn registry() {\n    Package::new(\"crates-io\", \"0.1.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                crates-io = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"cratesio\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    p.cargo(\"pkgid crates-io\")\n        .with_stdout_data(str![[r#\"\nregistry+https://github.com/rust-lang/crates.io-index#crates-io@0.1.0\n\n\"#]])\n        .run();\n\n    // Bad URL.\n    p.cargo(\"pkgid https://example.com/crates-io\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `https://example.com/crates-io` did not match any packages\n[HELP] there are similar package ID specifications:\n\n  crates-io@0.1.0\n\n\"#]])\n        .run();\n\n    // Bad name.\n    p.cargo(\"pkgid crates_io\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `crates_io` did not match any packages\n\n[HELP] a package with a similar name exists: `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_versions() {\n    Package::new(\"two-ver\", \"0.1.0\").publish();\n    Package::new(\"two-ver\", \"0.2.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                two-ver = \"0.1.0\"\n                two-ver2 = { package = \"two-ver\", version = \"0.2.0\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"cratesio\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    p.cargo(\"pkgid two-ver:0.2.0\")\n        .with_stdout_data(str![[r#\"\nregistry+https://github.com/rust-lang/crates.io-index#two-ver@0.2.0\n\n\"#]])\n        .run();\n\n    // Incomplete version.\n    p.cargo(\"pkgid two-ver@0\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] specification `two-ver@0` is ambiguous\n[HELP] re-run this command with one of the following specifications\n  two-ver@0.1.0\n  two-ver@0.2.0\n\n\"#]])\n        .run();\n\n    // Incomplete version.\n    p.cargo(\"pkgid two-ver@0.2\")\n        .with_stdout_data(str![[r#\"\nregistry+https://github.com/rust-lang/crates.io-index#two-ver@0.2.0\n\n\"#]])\n        .run();\n\n    // Ambiguous.\n    p.cargo(\"pkgid two-ver\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] specification `two-ver` is ambiguous\n[HELP] re-run this command with one of the following specifications\n  two-ver@0.1.0\n  two-ver@0.2.0\n\n\"#]])\n        .run();\n\n    // Bad version.\n    p.cargo(\"pkgid two-ver:0.3.0\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `two-ver@0.3.0` did not match any packages\n[HELP] there are similar package ID specifications:\n\n  two-ver@0.1.0\n  two-ver@0.2.0\n\n\"#]])\n        .run();\n}\n\n// Not for `cargo pkgid` but the `PackageIdSpec` format\n#[cargo_test]\nfn multiple_git_same_version() {\n    // Test what happens if different packages refer to the same git repo with\n    // different refs, and the package version is the same.\n    let (xyz_project, xyz_repo) = git::new_repo(\"xyz\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"xyz\"))\n            .file(\"src/lib.rs\", \"fn example() {}\")\n    });\n    let rev1 = xyz_repo.revparse_single(\"HEAD\").unwrap().id();\n    xyz_project.change_file(\"src/lib.rs\", \"pub fn example() {}\");\n    git::add(&xyz_repo);\n    let rev2 = git::commit(&xyz_repo);\n    // Both rev1 and rev2 point to version 0.1.0.\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    bar = {{ path = \"bar\" }}\n                    xyz = {{ git = \"{}\", rev = \"{}\" }}\n\n                \"#,\n                xyz_project.url(),\n                rev1\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"bar\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    xyz = {{ git = \"{}\", rev = \"{}\" }}\n                \"#,\n                xyz_project.url(),\n                rev2\n            ),\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"tree\")\n        .with_stdout_data(&format!(\n            \"\\\nfoo v0.1.0 ([ROOT]/foo)\n├── bar v0.1.0 ([ROOT]/foo/bar)\n│   └── xyz v0.5.0 ([ROOTURL]/xyz?rev={}#{})\n└── xyz v0.5.0 ([ROOTURL]/xyz?rev={}#{})\n\",\n            rev2,\n            &rev2.to_string()[..8],\n            rev1,\n            &rev1.to_string()[..8]\n        ))\n        .run();\n    // FIXME: This fails since xyz is ambiguous, but the\n    // possible pkgids are also ambiguous.\n    p.cargo(\"pkgid xyz\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] specification `xyz` is ambiguous\n[HELP] re-run this command with one of the following specifications\n  git+[ROOTURL]/xyz?rev=[..]#0.5.0\n  git+[ROOTURL]/xyz?rev=[..]#0.5.0\n\n\"#]])\n        .run();\n    // TODO, what should the `-p` value be here?\n    //p.cargo(\"update -p\")\n}\n\n// Keep Package ID format in sync among\n//\n// * Package ID specifications\n// * machine-readable message via `--message-format=json`\n// * `cargo metadata` output\n// * SBOMs\n#[cargo_test]\nfn pkgid_json_message_metadata_consistency() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    let output = p.cargo(\"pkgid\").arg(\"foo\").run();\n    let pkgid = String::from_utf8(output.stdout).unwrap();\n    let pkgid = pkgid.trim();\n    assert_e2e().eq(pkgid, str![\"path+[ROOTURL]/foo#0.5.0\"]);\n\n    p.cargo(\"check --message-format=json\")\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.5.0\",\n    \"reason\": \"compiler-artifact\",\n    \"...\": \"{...}\"\n  },\n  {\n    \"package_id\": \"path+[ROOTURL]/foo#0.5.0\",\n    \"reason\": \"build-script-executed\",\n    \"...\": \"{...}\"\n  },\n  {\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.5.0\",\n    \"reason\": \"compiler-artifact\",\n    \"...\": \"{...}\"\n  },\n  {\n    \"reason\": \"build-finished\",\n    \"success\": true\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [\n        \"wycats@example.com\"\n      ],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"foo\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": \"{...}\",\n      \"version\": \"0.5.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#0.5.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#0.5.0\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#0.5.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n\n    p.cargo(\"build -Zsbom\")\n        .env(\"CARGO_BUILD_SBOM\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"sbom\"])\n        .run();\n\n    let path = {\n        let mut path = p.bin(\"foo\").into_os_string();\n        path.push(\".cargo-sbom.json\");\n        PathBuf::from(path)\n    };\n\n    assert!(path.is_file());\n    let output = std::fs::read_to_string(&path).unwrap();\n    assert_e2e().eq(\n        output,\n        snapbox::str![[r#\"\n{\n  \"crates\": [\n    {\n      \"dependencies\": [\n        {\n          \"index\": 1,\n          \"kind\": \"build\"\n        }\n      ],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"kind\": [\n        \"bin\"\n      ]\n    },\n    {\n      \"dependencies\": [],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"kind\": [\n        \"custom-build\"\n      ]\n    }\n  ],\n  \"root\": 0,\n  \"rustc\": \"{...}\",\n  \"target\": \"[HOST_TARGET]\",\n  \"version\": 1\n}\n\"#]]\n        .is_json(),\n    );\n}\n"
  },
  {
    "path": "tests/testsuite/precise_pre_release.rs",
    "content": "//! Tests for selecting pre-release versions with `update --precise`.\n\nuse crate::prelude::*;\nuse cargo_test_support::{project, str};\n\n#[cargo_test]\nfn requires_nightly_cargo() {\n    cargo_test_support::registry::init();\n\n    for version in [\"0.1.1\", \"0.1.2-pre.0\"] {\n        cargo_test_support::registry::Package::new(\"my-dependency\", version).publish();\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"package\"\n            [dependencies]\n            my-dependency = \"0.1.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"update my-dependency --precise 0.1.2-pre.0\")\n        .with_status(101)\n        // This error is suffering from #12579 but still demonstrates that updating to\n        // a pre-release does not work on stable\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `my-dependency = \"^0.1.1\"`\ncandidate versions found which didn't match: 0.1.2-pre.0\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `package v0.0.0 ([ROOT]/foo)`\nif you are looking for the prerelease package it needs to be specified explicitly\n    my-dependency = { version = \"0.1.2-pre.0\" }\nperhaps a crate was updated and forgotten to be re-vendored?\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_pre_release() {\n    cargo_test_support::registry::init();\n\n    for version in [\"0.1.1\", \"0.1.2-pre.0\"] {\n        cargo_test_support::registry::Package::new(\"my-dependency\", version).publish();\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"package\"\n            [dependencies]\n            my-dependency = \"0.1.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"update my-dependency --precise 0.1.2-pre.0 -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"precise-pre-release\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] my-dependency v0.1.1 -> v0.1.2-pre.0\n\n\"#]])\n        .run();\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"\\nname = \\\"my-dependency\\\"\\nversion = \\\"0.1.2-pre.0\\\"\"));\n}\n\n#[cargo_test]\nfn pre_release_should_unmatched() {\n    cargo_test_support::registry::init();\n\n    cargo_test_support::registry::Package::new(\"my-dependency\", \"0.1.2\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"package\"\n            [dependencies]\n            my-dependency = \"0.1.2\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"generate-lockfile\").run();\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"\\nname = \\\"my-dependency\\\"\\nversion = \\\"0.1.2\\\"\"));\n\n    // 0.1.2-pre.0 < 0.1.2 so it doesn't match\n    cargo_test_support::registry::Package::new(\"my-dependency\", \"0.1.2-pre.0\").publish();\n    p.cargo(\"update -p my-dependency --precise 0.1.2-pre.0 -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"precise-pre-release\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `my-dependency = \"^0.1.2\"`\ncandidate versions found which didn't match: 0.1.2-pre.0\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `package v0.0.0 ([ROOT]/foo)`\nif you are looking for the prerelease package it needs to be specified explicitly\n    my-dependency = { version = \"0.1.2-pre.0\" }\nperhaps a crate was updated and forgotten to be re-vendored?\n\n\"#]])\n        .run();\n\n    cargo_test_support::registry::Package::new(\"my-dependency\", \"0.2.0-0\").publish();\n    // 0.2.0-0 is the upper bound we exclude, so it doesn't match\n    p.cargo(\"update -p my-dependency --precise 0.2.0-0 -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"precise-pre-release\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `my-dependency = \"^0.1.2\"`\ncandidate versions found which didn't match: 0.2.0-0\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `package v0.0.0 ([ROOT]/foo)`\nif you are looking for the prerelease package it needs to be specified explicitly\n    my-dependency = { version = \"0.2.0-0\" }\nperhaps a crate was updated and forgotten to be re-vendored?\n\n\"#]])\n        .run();\n\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"\\nname = \\\"my-dependency\\\"\\nversion = \\\"0.1.2\\\"\"));\n}\n\n#[cargo_test]\nfn pre_release_should_matched() {\n    cargo_test_support::registry::init();\n\n    cargo_test_support::registry::Package::new(\"my-dependency\", \"0.1.2\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"package\"\n            [dependencies]\n            my-dependency = \"0.1.2\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"generate-lockfile\").run();\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"\\nname = \\\"my-dependency\\\"\\nversion = \\\"0.1.2\\\"\"));\n\n    // Test upgrade\n    // 0.1.3 is in the range, so it match\n    cargo_test_support::registry::Package::new(\"my-dependency\", \"0.1.3\").publish();\n    p.cargo(\"update -p my-dependency --precise 0.1.3 -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"precise-pre-release\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] my-dependency v0.1.2 -> v0.1.3\n\n\"#]])\n        .run();\n\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"\\nname = \\\"my-dependency\\\"\\nversion = \\\"0.1.3\\\"\"));\n\n    // Test downgrade\n    // v0.1.3-pre.1 is in the range, so it match\n    cargo_test_support::registry::Package::new(\"my-dependency\", \"0.1.3-pre.1\").publish();\n    p.cargo(\"update -p my-dependency --precise 0.1.3-pre.1 -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"precise-pre-release\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNGRADING] my-dependency v0.1.3 -> v0.1.3-pre.1\n\n\"#]])\n        .run();\n\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"\\nname = \\\"my-dependency\\\"\\nversion = \\\"0.1.3-pre.1\\\"\"));\n}\n"
  },
  {
    "path": "tests/testsuite/proc_macro.rs",
    "content": "//! Tests for proc-macros.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn probe_cfg_before_crate_type_discovery() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'cfg(not(stage300))'.dependencies.noop]\n                path = \"../noop\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[macro_use]\n                extern crate noop;\n\n                #[derive(Noop)]\n                struct X;\n\n                fn main() {}\n            \"#,\n        )\n        .build();\n    let _noop = project()\n        .at(\"noop\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"noop\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate proc_macro;\n                use proc_macro::TokenStream;\n\n                #[proc_macro_derive(Noop)]\n                pub fn noop(_input: TokenStream) -> TokenStream {\n                    \"\".parse().unwrap()\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn noop() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.noop]\n                path = \"../noop\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[macro_use]\n                extern crate noop;\n\n                #[derive(Noop)]\n                struct X;\n\n                fn main() {}\n            \"#,\n        )\n        .build();\n    let _noop = project()\n        .at(\"noop\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"noop\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate proc_macro;\n                use proc_macro::TokenStream;\n\n                #[proc_macro_derive(Noop)]\n                pub fn noop(_input: TokenStream) -> TokenStream {\n                    \"\".parse().unwrap()\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn impl_and_derive() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.transmogrify]\n                path = \"../transmogrify\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[macro_use]\n                extern crate transmogrify;\n\n                trait ImplByTransmogrify {\n                    fn impl_by_transmogrify(&self) -> bool;\n                }\n\n                #[derive(Transmogrify, Debug)]\n                struct X { success: bool }\n\n                fn main() {\n                    let x = X::new();\n                    assert!(x.impl_by_transmogrify());\n                    println!(\"{:?}\", x);\n                }\n            \"#,\n        )\n        .build();\n    let _transmogrify = project()\n        .at(\"transmogrify\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"transmogrify\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate proc_macro;\n                use proc_macro::TokenStream;\n\n                #[proc_macro_derive(Transmogrify)]\n                #[doc(hidden)]\n                pub fn transmogrify(input: TokenStream) -> TokenStream {\n                    \"\n                        impl X {\n                            fn new() -> Self {\n                                X { success: true }\n                            }\n                        }\n\n                        impl ImplByTransmogrify for X {\n                            fn impl_by_transmogrify(&self) -> bool {\n                                true\n                            }\n                        }\n                    \".parse().unwrap()\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\nX { success: true }\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn proc_macro_doctest() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            #![crate_type = \"proc-macro\"]\n\n            extern crate proc_macro;\n\n            use proc_macro::TokenStream;\n\n            /// ```\n            /// assert!(true);\n            /// ```\n            #[proc_macro_derive(Bar)]\n            pub fn derive(_input: TokenStream) -> TokenStream {\n                \"\".parse().unwrap()\n            }\n\n            #[test]\n            fn a() {\n              assert!(true);\n            }\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"test\")\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest a ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest src/lib.rs - derive (line 8) ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn proc_macro_crate_type() {\n    // Verify that `crate-type = [\"proc-macro\"]` is the same as `proc-macro = true`\n    // and that everything, including rustdoc, works correctly.\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [dependencies]\n                pm = { path = \"pm\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! ```\n                //! use foo::THING;\n                //! assert_eq!(THING, 123);\n                //! ```\n                #[macro_use]\n                extern crate pm;\n                #[derive(MkItem)]\n                pub struct S;\n                #[cfg(test)]\n                mod tests {\n                    use super::THING;\n                    #[test]\n                    fn it_works() {\n                        assert_eq!(THING, 123);\n                    }\n                }\n            \"#,\n        )\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pm\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                crate-type = [\"proc-macro\"]\n            \"#,\n        )\n        .file(\n            \"pm/src/lib.rs\",\n            r#\"\n                extern crate proc_macro;\n                use proc_macro::TokenStream;\n\n                #[proc_macro_derive(MkItem)]\n                pub fn mk_item(_input: TokenStream) -> TokenStream {\n                    \"pub const THING: i32 = 123;\".parse().unwrap()\n                }\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"test\")\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest tests::it_works ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest src/lib.rs - (line 2) ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn proc_macro_crate_type_warning() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                crate-type = [\"proc-macro\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] library `foo` should only specify `proc-macro = true` instead of setting `crate-type`\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn lib_plugin_unused_key_warning() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                plugin = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused manifest key: lib.plugin\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn proc_macro_crate_type_warning_plugin() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                crate-type = [\"proc-macro\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] library `foo` should only specify `proc-macro = true` instead of setting `crate-type`\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn proc_macro_crate_type_multiple() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [lib]\n                crate-type = [\"proc-macro\", \"rlib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    foo.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  cannot mix `proc-macro` crate type with others\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn proc_macro_extern_prelude() {\n    // Check that proc_macro is in the extern prelude.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n            [lib]\n            proc-macro = true\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            use proc_macro::TokenStream;\n            #[proc_macro]\n            pub fn foo(input: TokenStream) -> TokenStream {\n                \"\".parse().unwrap()\n            }\n            \"#,\n        )\n        .build();\n    p.cargo(\"test\").run();\n    p.cargo(\"doc\").run();\n}\n\n#[cargo_test]\nfn proc_macro_built_once() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = ['a', 'b']\n                resolver = \"2\"\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [build-dependencies]\n                the-macro = { path = '../the-macro' }\n            \"#,\n        )\n        .file(\"a/build.rs\", \"fn main() {}\")\n        .file(\"a/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                the-macro = { path = '../the-macro', features = ['a'] }\n            \"#,\n        )\n        .file(\"b/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"the-macro/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"the-macro\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [lib]\n                proc-macro = true\n\n                [features]\n                a = []\n            \"#,\n        )\n        .file(\"the-macro/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build --verbose\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] the-macro v0.1.0 ([ROOT]/foo/the-macro)\n[RUNNING] `rustc --crate-name the_macro [..]`\n[COMPILING] b v0.1.0 ([ROOT]/foo/b)\n[RUNNING] `rustc --crate-name b [..]`\n[COMPILING] a v0.1.0 ([ROOT]/foo/a)\n[RUNNING] `rustc --crate-name build_script_build [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/a-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name a [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/profile_config.rs",
    "content": "//! Tests for profiles defined in config files.\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{basic_lib_manifest, paths, project, str};\nuse cargo_util_schemas::manifest::TomlDebugInfo;\n\n// TODO: this should be remove once -Zprofile-rustflags is stabilized\n#[cargo_test]\nfn rustflags_works_with_zflag() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [profile.dev]\n                rustflags = [\"-C\", \"link-dead-code=yes\"]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -v\")\n        .masquerade_as_nightly_cargo(&[\"profile-rustflags\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] config profile `dev` is not valid (defined in `[ROOT]/foo/.cargo/config.toml`)\n\nCaused by:\n  feature `profile-rustflags` is required\n...\n\"#]])\n        .run();\n\n    p.cargo(\"check -v -Zprofile-rustflags\")\n        .masquerade_as_nightly_cargo(&[\"profile-rustflags\"])\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -C link-dead-code=yes [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n            [unstable]\n            profile-rustflags = true\n\n            [profile.dev]\n            rustflags = [\"-C\", \"link-dead-code=yes\"]\n        \"#,\n    );\n\n    p.cargo(\"check -v\")\n        .masquerade_as_nightly_cargo(&[\"profile-rustflags\"])\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_config_validate_warnings() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [profile.test]\n                opt-level = 3\n\n                [profile.asdf]\n                opt-level = 3\n\n                [profile.dev]\n                bad-key = true\n\n                [profile.dev.build-override]\n                bad-key-bo = true\n\n                [profile.dev.package.bar]\n                bad-key-bar = true\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").with_stderr_data(str![[r#\"\n[WARNING] unused config key `profile.dev.bad-key` in `[ROOT]/foo/.cargo/config.toml`\n[WARNING] unused config key `profile.dev.build-override.bad-key-bo` in `[ROOT]/foo/.cargo/config.toml`\n[WARNING] unused config key `profile.dev.package.bar.bad-key-bar` in `[ROOT]/foo/.cargo/config.toml`\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered()).run();\n}\n\n#[cargo_test]\nfn profile_config_error_paths() {\n    // Errors in config show where the error is located.\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [profile.dev]\n                opt-level = 3\n            \"#,\n        )\n        .file(\n            paths::home().join(\".cargo/config.toml\"),\n            r#\"\n            [profile.dev]\n            rpath = \"foo\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `profile.dev`\n\nCaused by:\n  error in [ROOT]/home/.cargo/config.toml: `profile.dev.rpath` expected true/false, but found a string\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_config_validate_errors() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [profile.dev.package.foo]\n                panic = \"abort\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] config profile `dev` is not valid (defined in `[ROOT]/foo/.cargo/config.toml`)\n\nCaused by:\n  `panic` may not be specified in a `package` profile\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_config_syntax_errors() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [profile.dev]\n                codegen-units = \"foo\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `profile.dev`\n\nCaused by:\n  error in [ROOT]/foo/.cargo/config.toml: `profile.dev.codegen-units` expected an integer, but found a string\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_config_override_spec_multiple() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [profile.dev.package.bar]\n                opt-level = 3\n\n                [profile.dev.package.\"bar:0.5.0\"]\n                opt-level = 3\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    // Unfortunately this doesn't tell you which file, hopefully it's not too\n    // much of a problem.\n    p.cargo(\"build -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ERROR] multiple package overrides in profile `dev` match package `bar v0.5.0 ([ROOT]/foo/bar)`\nfound package specs: bar, bar@0.5.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_config_all_options() {\n    // Ensure all profile options are supported.\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [profile.release]\n            opt-level = 1\n            debug = true\n            debug-assertions = true\n            overflow-checks = false\n            rpath = true\n            lto = true\n            codegen-units = 2\n            panic = \"abort\"\n            incremental = true\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --release -v\")\n        .env_remove(\"CARGO_INCREMENTAL\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -C opt-level=1 -C panic=abort -C lto[..]-C codegen-units=2 -C debuginfo=2 [..]-C debug-assertions=on -C overflow-checks=off [..]-C rpath --out-dir [ROOT]/foo/target/release/deps -C incremental=[ROOT]/foo/target/release/incremental[..]`\n[FINISHED] `release` profile [optimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_config_override_precedence() {\n    // Config values take precedence over manifest values.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = {path = \"bar\"}\n\n                [profile.dev]\n                codegen-units = 2\n\n                [profile.dev.package.bar]\n                opt-level = 3\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [profile.dev.package.bar]\n                opt-level = 2\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..] -C opt-level=2[..]-C codegen-units=2 [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]-C codegen-units=2 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_config_no_warn_unknown_override() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [profile.dev.package.bar]\n                codegen-units = 4\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_does_not_contain(\"[..]warning[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn profile_config_mixed_types() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [profile.dev]\n                opt-level = 3\n            \"#,\n        )\n        .file(\n            paths::home().join(\".cargo/config.toml\"),\n            r#\"\n            [profile.dev]\n            opt-level = 's'\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]-C opt-level=3 [..]`\n[FINISHED] `dev` profile [optimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn named_config_profile() {\n    // Exercises config named profiles.\n    // foo -> middle -> bar -> dev\n    // middle exists in Cargo.toml, the others in .cargo/config.toml\n    use super::config::GlobalContextBuilder;\n    use cargo::core::compiler::CompileKind;\n    use cargo::core::profiles::{Profiles, UnitFor};\n    use cargo::core::{PackageId, Workspace};\n    use std::fs;\n    paths::root().join(\".cargo\").mkdir_p();\n    fs::write(\n        paths::root().join(\".cargo/config.toml\"),\n        r#\"\n            [profile.foo]\n            inherits = \"middle\"\n            codegen-units = 2\n            [profile.foo.build-override]\n            codegen-units = 6\n            [profile.foo.package.dep]\n            codegen-units = 7\n\n            [profile.middle]\n            inherits = \"bar\"\n            codegen-units = 3\n\n            [profile.bar]\n            inherits = \"dev\"\n            codegen-units = 4\n            debug = 1\n        \"#,\n    )\n    .unwrap();\n    fs::write(\n        paths::root().join(\"Cargo.toml\"),\n        r#\"\n            [workspace]\n\n            [profile.middle]\n            inherits = \"bar\"\n            codegen-units = 1\n            opt-level = 1\n            [profile.middle.package.dep]\n            overflow-checks = false\n\n            [profile.foo.build-override]\n            codegen-units = 5\n            debug-assertions = false\n            [profile.foo.package.dep]\n            codegen-units = 8\n        \"#,\n    )\n    .unwrap();\n    let gctx = GlobalContextBuilder::new().build();\n    let profile_name = \"foo\".into();\n    let ws = Workspace::new(&paths::root().join(\"Cargo.toml\"), &gctx).unwrap();\n    let profiles = Profiles::new(&ws, profile_name).unwrap();\n\n    let crates_io = cargo::core::SourceId::crates_io(&gctx).unwrap();\n    let a_pkg = PackageId::try_new(\"a\", \"0.1.0\", crates_io).unwrap();\n    let dep_pkg = PackageId::try_new(\"dep\", \"0.1.0\", crates_io).unwrap();\n\n    // normal package\n    let kind = CompileKind::Host;\n    let p = profiles.get_profile(a_pkg, true, true, UnitFor::new_normal(kind), kind);\n    assert_eq!(p.name, \"foo\");\n    assert_eq!(p.codegen_units, Some(2)); // \"foo\" from config\n    assert_eq!(p.opt_level, \"1\"); // \"middle\" from manifest\n    assert_eq!(p.debuginfo.into_inner(), TomlDebugInfo::Limited); // \"bar\" from config\n    assert_eq!(p.debug_assertions, true); // \"dev\" built-in (ignore build-override)\n    assert_eq!(p.overflow_checks, true); // \"dev\" built-in (ignore package override)\n\n    // build-override\n    let bo = profiles.get_profile(a_pkg, true, true, UnitFor::new_host(false, kind), kind);\n    assert_eq!(bo.name, \"foo\");\n    assert_eq!(bo.codegen_units, Some(6)); // \"foo\" build override from config\n    assert_eq!(bo.opt_level, \"0\"); // default to zero\n    assert_eq!(bo.debuginfo.into_inner(), TomlDebugInfo::Limited); // SAME as normal\n    assert_eq!(bo.debug_assertions, false); // \"foo\" build override from manifest\n    assert_eq!(bo.overflow_checks, true); // SAME as normal\n\n    // package overrides\n    let po = profiles.get_profile(dep_pkg, false, true, UnitFor::new_normal(kind), kind);\n    assert_eq!(po.name, \"foo\");\n    assert_eq!(po.codegen_units, Some(7)); // \"foo\" package override from config\n    assert_eq!(po.opt_level, \"1\"); // SAME as normal\n    assert_eq!(po.debuginfo.into_inner(), TomlDebugInfo::Limited); // SAME as normal\n    assert_eq!(po.debug_assertions, true); // SAME as normal\n    assert_eq!(po.overflow_checks, false); // \"middle\" package override from manifest\n}\n\n#[cargo_test]\nfn named_env_profile() {\n    // Environment variables used to define a named profile.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v --profile=other\")\n        .env(\"CARGO_PROFILE_OTHER_CODEGEN_UNITS\", \"1\")\n        .env(\"CARGO_PROFILE_OTHER_INHERITS\", \"dev\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]-C codegen-units=1 [..]`\n[FINISHED] `other` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_with_dev_profile() {\n    // The `test` profile inherits from `dev` for both local crates and\n    // dependencies.\n    Package::new(\"somedep\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            somedep = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"test --lib --no-run -v\")\n        .env(\"CARGO_PROFILE_DEV_DEBUG\", \"0\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] somedep v1.0.0 (registry `dummy-registry`)\n[COMPILING] somedep v1.0.0\n[RUNNING] `rustc --crate-name somedep [..]`\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `test` profile [unoptimized] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n\n\"#]])\n        .with_stdout_does_not_contain(\"[..] -C debuginfo=0[..]\")\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/profile_custom.rs",
    "content": "//! Tests for named profiles.\n\nuse crate::prelude::*;\nuse cargo_test_support::{basic_lib_manifest, project, str};\n\n#[cargo_test]\nfn inherits_on_release() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.release]\n                inherits = \"dev\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `inherits` must not be specified in root profile `release`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn missing_inherits() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.release-lto]\n                codegen-units = 7\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] profile `release-lto` is missing an `inherits` directive (`inherits` is required for all profiles except `dev` or `release`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_profile_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.'.release-lto']\n                inherits = \"release\"\n                codegen-units = 7\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid character `.` in profile name: `.release-lto`, allowed characters are letters, numbers, underscore, and hyphen\n --> Cargo.toml:8:26\n  |\n8 |                 [profile.'.release-lto']\n  |                          ^^^^^^^^^^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n// We are currently uncertain if dir-name will ever be exposed to the user.\n// The code for it still roughly exists, but only for the internal profiles.\n// This test was kept in case we ever want to enable support for it again.\n#[ignore = \"dir-name is disabled\"]\nfn invalid_dir_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.'release-lto']\n                inherits = \"release\"\n                dir-name = \".subdir\"\n                codegen-units = 7\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  Invalid character `.` in dir-name: `.subdir`\",\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dir_name_disabled() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [profile.release-lto]\n                inherits = \"release\"\n                dir-name = \"lto\"\n                lto = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  dir-name=\"lto\" in profile `release-lto` is not currently allowed, directory names are tied to the profile name for custom profiles\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_inherits() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.'release-lto']\n                inherits = \".release\"\n                codegen-units = 7\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] profile `release-lto` inherits from `.release`, but that profile is not defined\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn non_existent_inherits() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.release-lto]\n                codegen-units = 7\n                inherits = \"non-existent\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] profile `release-lto` inherits from `non-existent`, but that profile is not defined\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn self_inherits() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.release-lto]\n                codegen-units = 7\n                inherits = \"release-lto\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] profile inheritance loop detected with profile `release-lto` inheriting `release-lto`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inherits_loop() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.release-lto]\n                codegen-units = 7\n                inherits = \"release-lto2\"\n\n                [profile.release-lto2]\n                codegen-units = 7\n                inherits = \"release-lto\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] profile inheritance loop detected with profile `release-lto2` inheriting `release-lto`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn overrides_with_custom() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                xxx = {path = \"xxx\"}\n                yyy = {path = \"yyy\"}\n\n                [profile.dev]\n                codegen-units = 7\n\n                [profile.dev.package.xxx]\n                codegen-units = 5\n                [profile.dev.package.yyy]\n                codegen-units = 3\n\n                [profile.other]\n                inherits = \"dev\"\n                codegen-units = 2\n\n                [profile.other.package.yyy]\n                codegen-units = 6\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"xxx/Cargo.toml\", &basic_lib_manifest(\"xxx\"))\n        .file(\"xxx/src/lib.rs\", \"\")\n        .file(\"yyy/Cargo.toml\", &basic_lib_manifest(\"yyy\"))\n        .file(\"yyy/src/lib.rs\", \"\")\n        .build();\n\n    // profile overrides are inherited between profiles using inherits and have a\n    // higher priority than profile options provided by custom profiles\n    p.cargo(\"build -v\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] xxx v0.5.0 ([ROOT]/foo/xxx)\n[COMPILING] yyy v0.5.0 ([ROOT]/foo/yyy)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name xxx [..] -C codegen-units=5 [..]`\n[RUNNING] `rustc --crate-name yyy [..] -C codegen-units=3 [..]`\n[RUNNING] `rustc --crate-name foo [..] -C codegen-units=7 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    // This also verifies that the custom profile names appears in the finished line.\n    p.cargo(\"build --profile=other -v\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] xxx v0.5.0 ([ROOT]/foo/xxx)\n[COMPILING] yyy v0.5.0 ([ROOT]/foo/yyy)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name xxx [..] -C codegen-units=5 [..]`\n[RUNNING] `rustc --crate-name yyy [..] -C codegen-units=6 [..]`\n[RUNNING] `rustc --crate-name foo [..] -C codegen-units=2 [..]`\n[FINISHED] `other` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn conflicting_usage() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --profile=dev --release\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] the argument '--profile <PROFILE-NAME>' cannot be used with '--release'\n\nUsage: cargo[EXE] build --profile <PROFILE-NAME>\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n\n    p.cargo(\"install --profile=release --debug\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] the argument '--profile <PROFILE-NAME>' cannot be used with '--debug'\n\nUsage: cargo[EXE] install --profile <PROFILE-NAME> [CRATE[@<VER>]]...\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n\n    p.cargo(\"check --profile=dev --release\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] the argument '--profile <PROFILE-NAME>' cannot be used with '--release'\n\nUsage: cargo[EXE] check --profile <PROFILE-NAME>\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn clean_custom_dirname() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.other]\n                inherits = \"release\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --release\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"clean -p foo\").run();\n\n    p.cargo(\"build --release\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"clean -p foo --release\").run();\n\n    p.cargo(\"build --release\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --profile=other\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `other` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"clean\").arg(\"--release\").run();\n\n    // Make sure that 'other' was not cleaned\n    assert!(p.build_dir().is_dir());\n    assert!(p.build_dir().join(\"debug\").is_dir());\n    assert!(p.build_dir().join(\"other\").is_dir());\n    assert!(!p.build_dir().join(\"release\").is_dir());\n\n    // This should clean 'other'\n    p.cargo(\"clean --profile=other\")\n        .with_stderr_data(str![[r#\"\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n    assert!(p.build_dir().join(\"debug\").is_dir());\n    assert!(!p.build_dir().join(\"other\").is_dir());\n}\n\n#[cargo_test]\nfn unknown_profile() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --profile alpha\")\n        .with_stderr_data(str![[r#\"\n[ERROR] profile `alpha` is not defined\n\n\"#]])\n        .with_status(101)\n        .run();\n    // Clean has a separate code path, need to check it too.\n    p.cargo(\"clean --profile alpha\")\n        .with_stderr_data(str![[r#\"\n[ERROR] profile `alpha` is not defined\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn reserved_profile_names() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [profile.doc]\n                opt-level = 1\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --profile=doc\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] profile `doc` is reserved and not allowed to be explicitly specified\n\n\"#]])\n        .run();\n    // Not an exhaustive list, just a sample.\n    for name in [\"build\", \"cargo\", \"check\", \"rustc\", \"CaRgO_startswith\"] {\n        p.cargo(&format!(\"build --profile={}\", name))\n            .with_status(101)\n            .with_stderr_data(&format!(\n                \"\\\n[ERROR] profile name `{}` is reserved\nPlease choose a different name.\nSee https://doc.rust-lang.org/cargo/reference/profiles.html for more on configuring profiles.\n\",\n                name\n            ))\n            .run();\n    }\n    for name in [\"build\", \"check\", \"cargo\", \"rustc\", \"CaRgO_startswith\"] {\n        p.change_file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [profile.{}]\n                    opt-level = 1\n                \"#,\n                name\n            ),\n        );\n\n        let highlight = \"^\".repeat(name.len());\n        p.cargo(\"build\")\n            .with_status(101)\n            .with_stderr_data(&format!(\n                \"\\\n[ERROR] profile name `{name}` is reserved\n       Please choose a different name.\n       See https://doc.rust-lang.org/cargo/reference/profiles.html for more on configuring profiles.\n --> Cargo.toml:7:30\n  |\n7 |                     [profile.{name}]\n  |                              {highlight}\n\"\n            ))\n            .run();\n    }\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n               [package]\n               name = \"foo\"\n               version = \"0.1.0\"\n               edition = \"2015\"\n               authors = []\n\n               [profile.debug]\n               debug = 1\n               inherits = \"dev\"\n            \"#,\n    );\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] profile name `debug` is reserved\n       To configure the default development profile, use the name `dev` as in [profile.dev]\n       See https://doc.rust-lang.org/cargo/reference/profiles.html for more on configuring profiles.\n --> Cargo.toml:8:25\n  |\n8 |                [profile.debug]\n  |                         ^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn legacy_commands_support_custom() {\n    // These commands have had `--profile` before custom named profiles.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n               [package]\n               name = \"foo\"\n               version = \"0.1.0\"\n               edition = \"2015\"\n\n               [profile.super-dev]\n               codegen-units = 3\n               inherits = \"dev\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    for command in [\"rustc\", \"fix\", \"check\"] {\n        let mut pb = p.cargo(command);\n        if command == \"fix\" {\n            pb.arg(\"--allow-no-vcs\");\n        }\n        pb.arg(\"--profile=super-dev\")\n            .arg(\"-v\")\n            .with_stderr_data(str![\n                r#\"\n...\n[RUNNING] [..]codegen-units=3[..]\n...\n\"#\n            ])\n            .run();\n        p.build_dir().rm_rf();\n    }\n}\n\n#[cargo_test]\nfn legacy_rustc() {\n    // `cargo rustc` historically has supported dev/test/bench/check\n    // other profiles are covered in check::rustc_check\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [profile.dev]\n                codegen-units = 3\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"rustc --profile dev -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]-C codegen-units=3[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/profile_overrides.rs",
    "content": "//! Tests for profile overrides (build-override and per-package overrides).\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{basic_lib_manifest, basic_manifest, project, str};\n\n#[cargo_test]\nfn profile_override_basic() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = {path = \"bar\"}\n\n                [profile.dev]\n                opt-level = 1\n\n                [profile.dev.package.bar]\n                opt-level = 3\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.5.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar [..] -C opt-level=3 [..]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -C opt-level=1 [..]`\n[FINISHED] `dev` profile [optimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_override_warnings() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = {path = \"bar\"}\n\n                [profile.dev.package.bart]\n                opt-level = 3\n\n                [profile.dev.package.no-suggestion]\n                opt-level = 3\n\n                [profile.dev.package.\"bar:1.2.3\"]\n                opt-level = 3\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").with_stderr_data(str![[r#\"\n...\n[WARNING] profile package spec `bar@1.2.3` in profile `dev` has a version or URL that does not match any of the packages: bar v0.5.0 ([ROOT]/foo/bar)\n[WARNING] profile package spec `bart` in profile `dev` did not match any packages\n\n[HELP] a package with a similar name exists: `bar`\n[WARNING] profile package spec `no-suggestion` in profile `dev` did not match any packages\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn profile_override_bad_settings() {\n    let bad_values = [\n        (\n            \"panic = \\\"abort\\\"\",\n            \"`panic` may not be specified in a `package` profile\",\n        ),\n        (\n            \"lto = true\",\n            \"`lto` may not be specified in a `package` profile\",\n        ),\n        (\n            \"rpath = true\",\n            \"`rpath` may not be specified in a `package` profile\",\n        ),\n        (\"package = {}\", \"package-specific profiles cannot be nested\"),\n    ];\n    for &(snippet, expected) in bad_values.iter() {\n        let p = project()\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n                        [package]\n                        name = \"foo\"\n                        version = \"0.0.1\"\n                        edition = \"2015\"\n\n                        [dependencies]\n                        bar = {{path = \"bar\"}}\n\n                        [profile.dev.package.bar]\n                        {}\n                    \"#,\n                    snippet\n                ),\n            )\n            .file(\"src/lib.rs\", \"\")\n            .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n            .file(\"bar/src/lib.rs\", \"\")\n            .build();\n\n        p.cargo(\"check\")\n            .with_status(101)\n            .with_stderr_data(format!(\n                \"\\\n...\nCaused by:\\n  {}\n\",\n                expected\n            ))\n            .run();\n    }\n}\n\n#[cargo_test]\nfn profile_override_hierarchy() {\n    // Test that the precedence rules are correct for different types.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"m1\", \"m2\", \"m3\"]\n\n            [profile.dev]\n            codegen-units = 1\n\n            [profile.dev.package.m2]\n            codegen-units = 2\n\n            [profile.dev.package.\"*\"]\n            codegen-units = 3\n\n            [profile.dev.build-override]\n            codegen-units = 4\n            \"#,\n        )\n        // m1\n        .file(\n            \"m1/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"m1\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            m2 = { path = \"../m2\" }\n            dep = { path = \"../../dep\" }\n            \"#,\n        )\n        .file(\"m1/src/lib.rs\", \"extern crate m2; extern crate dep;\")\n        .file(\"m1/build.rs\", \"fn main() {}\")\n        // m2\n        .file(\n            \"m2/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"m2\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            m3 = { path = \"../m3\" }\n\n            [build-dependencies]\n            m3 = { path = \"../m3\" }\n            dep = { path = \"../../dep\" }\n            \"#,\n        )\n        .file(\"m2/src/lib.rs\", \"extern crate m3;\")\n        .file(\n            \"m2/build.rs\",\n            \"extern crate m3; extern crate dep; fn main() {}\",\n        )\n        // m3\n        .file(\"m3/Cargo.toml\", &basic_lib_manifest(\"m3\"))\n        .file(\"m3/src/lib.rs\", \"\")\n        .build();\n\n    // dep (outside of workspace)\n    let _dep = project()\n        .at(\"dep\")\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"dep\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Profiles should be:\n    // m3: 4 (as build.rs dependency)\n    // m3: 1 (as [profile.dev] as workspace member)\n    // dep: 3 (as [profile.dev.package.\"*\"] as non-workspace member)\n    // m1 build.rs: 4 (as [profile.dev.build-override])\n    // m2 build.rs: 2 (as [profile.dev.package.m2])\n    // m2: 2 (as [profile.dev.package.m2])\n    // m1: 1 (as [profile.dev])\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] m3 v0.5.0 ([ROOT]/foo/m3)\n[COMPILING] dep v0.5.0 ([ROOT]/dep)\n[RUNNING] `rustc --crate-name m3 --edition=2015 m3/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=4 [..]`\n[RUNNING] `rustc --crate-name dep [..][ROOT]/dep/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=3 [..]`\n[RUNNING] `rustc --crate-name m3 --edition=2015 m3/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=1 [..]`\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 m1/build.rs [..] --crate-type bin --emit=[..]link[..]-C codegen-units=4 [..]`\n[COMPILING] m2 v0.0.1 ([ROOT]/foo/m2)\n[RUNNING] `rustc --crate-name build_script_build --edition=2015 m2/build.rs [..] --crate-type bin --emit=[..]link[..]-C codegen-units=2 [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/m1-[HASH]/build-script-build`\n[RUNNING] `[ROOT]/foo/target/debug/build/m2-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name m2 --edition=2015 m2/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=2 [..]`\n[COMPILING] m1 v0.0.1 ([ROOT]/foo/m1)\n[RUNNING] `rustc --crate-name m1 --edition=2015 m1/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=1 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn profile_override_spec_multiple() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = { path = \"bar\" }\n\n            [profile.dev.package.bar]\n            opt-level = 3\n\n            [profile.dev.package.\"bar:0.5.0\"]\n            opt-level = 3\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] multiple package overrides in profile `dev` match package `bar v0.5.0 ([ROOT]/foo/bar)`\nfound package specs: bar, bar@0.5.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_override_spec_with_version() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = { path = \"bar\" }\n\n            [profile.dev.package.\"bar:0.5.0\"]\n            codegen-units = 2\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n...\n[CHECKING] bar v0.5.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc [..]bar/src/lib.rs [..] -C codegen-units=2 [..]`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_override_spec_with_partial_version() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = { path = \"bar\" }\n\n            [profile.dev.package.\"bar:0.5\"]\n            codegen-units = 2\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n...\n[CHECKING] bar v0.5.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc [..]bar/src/lib.rs [..] -C codegen-units=2 [..]`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_override_spec() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"m1\", \"m2\"]\n\n            [profile.dev.package.\"dep:1.0.0\"]\n            codegen-units = 1\n\n            [profile.dev.package.\"dep:2.0.0\"]\n            codegen-units = 2\n            \"#,\n        )\n        // m1\n        .file(\n            \"m1/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"m1\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            dep = { path = \"../../dep1\" }\n            \"#,\n        )\n        .file(\"m1/src/lib.rs\", \"extern crate dep;\")\n        // m2\n        .file(\n            \"m2/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"m2\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            dep = {path = \"../../dep2\" }\n            \"#,\n        )\n        .file(\"m2/src/lib.rs\", \"extern crate dep;\")\n        .build();\n\n    project()\n        .at(\"dep1\")\n        .file(\"Cargo.toml\", &basic_manifest(\"dep\", \"1.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    project()\n        .at(\"dep2\")\n        .file(\"Cargo.toml\", &basic_manifest(\"dep\", \"2.0.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(\n            str![[r#\"\n...\n[RUNNING] `rustc [..][ROOT]/dep1/src/lib.rs [..] -C codegen-units=1 [..]`\n[RUNNING] `rustc [..][ROOT]/dep2/src/lib.rs [..] -C codegen-units=2 [..]`\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn override_proc_macro() {\n    Package::new(\"shared\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [dependencies]\n            shared = \"1.0\"\n            pm = {path = \"pm\"}\n\n            [profile.dev.build-override]\n            codegen-units = 4\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\"pm::eat!{}\"#)\n        .file(\n            \"pm/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"pm\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [lib]\n            proc-macro = true\n\n            [dependencies]\n            shared = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"pm/src/lib.rs\",\n            r#\"\n            extern crate proc_macro;\n            use proc_macro::TokenStream;\n\n            #[proc_macro]\n            pub fn eat(_item: TokenStream) -> TokenStream {\n                \"\".parse().unwrap()\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -v\")\n        // Shared built for the proc-macro.\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustc [..]--crate-name shared [..] -C codegen-units=4[..]`\n...\n[RUNNING] `rustc [..]--crate-name pm [..] -C codegen-units=4[..]`\n...\n\"#]])\n        // Shared built for the library.\n        .with_stderr_line_without(\n            &[\"[RUNNING] `rustc --crate-name shared --edition=2015\"],\n            &[\"-C codegen-units\"],\n        )\n        .with_stderr_line_without(\n            &[\"[RUNNING] `rustc [..]--crate-name foo\"],\n            &[\"-C codegen-units\"],\n        )\n        .run();\n}\n\n#[cargo_test]\nfn no_warning_ws() {\n    // https://github.com/rust-lang/cargo/issues/7378, avoid warnings in a workspace.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n\n            [profile.dev.package.a]\n            codegen-units = 3\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.1.0\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -p b\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] b v0.1.0 ([ROOT]/foo/b)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_override_shared() {\n    // A dependency with a build script that is shared with a build\n    // dependency, using different profile settings. That is:\n    //\n    // foo DEBUG=2\n    // ├── common DEBUG=2\n    // │   └── common Run build.rs DEBUG=2\n    // │       └── common build.rs DEBUG=0 (build_override)\n    // └── foo Run build.rs DEBUG=2\n    //     └── foo build.rs DEBUG=0 (build_override)\n    //         └── common DEBUG=0 (build_override)\n    //             └── common Run build.rs DEBUG=0 (build_override)\n    //                 └── common build.rs DEBUG=0 (build_override)\n    //\n    // The key part here is that `common` RunCustomBuild is run twice, once\n    // with DEBUG=2 (as a dependency of foo) and once with DEBUG=0 (as a\n    // build-dependency of foo's build script).\n    Package::new(\"common\", \"1.0.0\")\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                if std::env::var(\"DEBUG\").unwrap() != \"false\" {\n                    println!(\"cargo::rustc-cfg=foo_debug\");\n                } else {\n                    println!(\"cargo::rustc-cfg=foo_release\");\n                }\n            }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn foo() -> u32 {\n                if cfg!(foo_debug) {\n                    assert!(cfg!(debug_assertions));\n                    1\n                } else if cfg!(foo_release) {\n                    assert!(!cfg!(debug_assertions));\n                    2\n                } else {\n                    panic!(\"not set\");\n                }\n            }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [build-dependencies]\n            common = \"1.0\"\n\n            [dependencies]\n            common = \"1.0\"\n\n            [profile.dev.build-override]\n            debug = 0\n            debug-assertions = false\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                assert_eq!(common::foo(), 2);\n            }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                assert_eq!(common::foo(), 1);\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\").run();\n}\n"
  },
  {
    "path": "tests/testsuite/profile_panic_immediate_abort.rs",
    "content": "//! Tests for `panic = \"immediate-abort\"`.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn gated_manifest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                panic = \"immediate-abort\"\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"panic-immediate-abort\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `panic-immediate-abort` is required\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn gated_config_toml() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [profile.dev]\n                panic = \"immediate-abort\"\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"panic-immediate-abort\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] config profile `dev` is not valid (defined in `[ROOT]/foo/.cargo/config.toml`)\n\nCaused by:\n  feature `panic-immediate-abort` is required\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Cpanic=immediate-abort is unstable\")]\nfn manifest_gate_works() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"panic-immediate-abort\"]\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                panic = \"immediate-abort\"\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --verbose\")\n        .masquerade_as_nightly_cargo(&[\"panic-immediate-abort\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]-C panic=immediate-abort -Z unstable-options[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Cpanic=immediate-abort is unstable\")]\nfn cli_gate_works() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                panic = \"immediate-abort\"\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --verbose -Z panic-immediate-abort\")\n        .masquerade_as_nightly_cargo(&[\"panic-immediate-abort\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]-C panic=immediate-abort -Z unstable-options[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/profile_targets.rs",
    "content": "//! Tests for checking exactly how profiles correspond with each unit. For\n//! example, the `test` profile applying to test targets, but not other\n//! targets, etc.\n\nuse crate::prelude::*;\nuse cargo_test_support::{Project, basic_manifest, project, str};\n\nfn all_target_project() -> Project {\n    // This abuses the `codegen-units` setting so that we can verify exactly\n    // which profile is used for each compiler invocation.\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [build-dependencies]\n                bdep = { path = \"bdep\" }\n\n                [profile.dev]\n                codegen-units = 1\n                panic = \"abort\"\n                [profile.release]\n                codegen-units = 2\n                panic = \"abort\"\n                [profile.test]\n                codegen-units = 3\n                [profile.bench]\n                codegen-units = 4\n                [profile.dev.build-override]\n                codegen-units = 5\n                [profile.release.build-override]\n                codegen-units = 6\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .file(\"src/main.rs\", \"extern crate foo; fn main() {}\")\n        .file(\"examples/ex1.rs\", \"extern crate foo; fn main() {}\")\n        .file(\"tests/test1.rs\", \"extern crate foo;\")\n        .file(\"benches/bench1.rs\", \"extern crate foo;\")\n        .file(\n            \"build.rs\",\n            r#\"\n                extern crate bdep;\n                fn main() {\n                    eprintln!(\"foo custom build PROFILE={} DEBUG={} OPT_LEVEL={}\",\n                        std::env::var(\"PROFILE\").unwrap(),\n                        std::env::var(\"DEBUG\").unwrap(),\n                        std::env::var(\"OPT_LEVEL\").unwrap(),\n                    );\n                }\n            \"#,\n        )\n        // `bar` package.\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        // `bdep` package.\n        .file(\n            \"bdep/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bdep\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"../bar\" }\n            \"#,\n        )\n        .file(\"bdep/src/lib.rs\", \"extern crate bar;\")\n        .build()\n}\n\n#[cargo_test]\nfn profile_selection_build() {\n    let p = all_target_project();\n\n    // `build`\n    // NOTES:\n    // - bdep `panic` is not set because it thinks `build.rs` is a plugin.\n    // - build_script_build is built without panic because it thinks `build.rs` is a plugin.\n    // - We make sure that the build dependencies bar, bdep, and build.rs\n    //   are built with debuginfo=0.\n    p.cargo(\"build -vv\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]\n[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep)\n[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]\n[RUNNING] `[..][ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .with_stderr_does_not_contain(\"[..] -C debuginfo=0[..]\")\n        .run();\n    p.cargo(\"build -vv\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep)\n[FRESH] bar v0.0.1 ([ROOT]/foo/bar)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn profile_selection_build_release() {\n    let p = all_target_project();\n\n    // `build --release`\n    p.cargo(\"build --release -vv\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..]\n[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep)\n[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..]\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=6 [..]\n[RUNNING] `[..][ROOT]/foo/target/release/build/foo-[HASH]/build-script-build`\n[foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n    p.cargo(\"build --release -vv\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] bar v0.0.1 ([ROOT]/foo/bar)\n[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn profile_selection_build_all_targets() {\n    let p = all_target_project();\n    // `build`\n    // NOTES:\n    // - bdep `panic` is not set because it thinks `build.rs` is a plugin.\n    // - build_script_build is built without panic because it thinks\n    //   `build.rs` is a plugin.\n    // - Benchmark dependencies are compiled in `dev` mode, which may be\n    //   surprising. See issue rust-lang/cargo#4929.\n    // - We make sure that the build dependencies bar, bdep, and build.rs are built with\n    //   debuginfo=0; but since we don't pass `-C debuginfo` when it's set to 0, we have to test\n    //   explicitly that there's no `-C debuginfo` flag.\n    //\n    // - Dependency profiles:\n    //   Pkg  Target  Profile     Reason\n    //   ---  ------  -------     ------\n    //   bar  lib     dev         For foo-bin\n    //   bar  lib     dev-panic   For tests/benches and bdep\n    //   bdep lib     dev-panic   For foo build.rs\n    //   foo  custom  dev-panic\n    //\n    // - `foo` target list is:\n    //   Target   Profile    Mode\n    //   ------   -------    ----\n    //   lib      dev+panic  build  (a normal lib target)\n    //   lib      dev-panic  build  (used by tests/benches)\n    //   lib      dev        dev\n    //   test     dev        dev\n    //   bench    dev        dev\n    //   bin      dev        dev\n    //   bin      dev        build\n    //   example  dev        build\n    p.cargo(\"build --all-targets -vv\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort -C embed-bitcode=[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=5 [..]`\n[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep)\n[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]`\n[RUNNING] `[..][ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]link[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]link[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name bench1 --edition=2015 benches/bench1.rs [..]--emit=[..]link[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type bin --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .with_stderr_does_not_contain(\"[..] -C debuginfo=0[..]\")\n        .run();\n    p.cargo(\"build -vv\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] bar v0.0.1 ([ROOT]/foo/bar)\n[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn profile_selection_build_all_targets_release() {\n    let p = all_target_project();\n    // `build --all-targets --release`\n    // NOTES:\n    // - bdep `panic` is not set because it thinks `build.rs` is a plugin.\n    // - bar compiled twice. It tries with and without panic, but the \"is a\n    //   plugin\" logic is forcing it to be cleared.\n    // - build_script_build is built without panic because it thinks\n    //   `build.rs` is a plugin.\n    // - build_script_build is being run two times. Once for the `dev` and\n    //   `test` targets, once for the `bench` targets.\n    //   TODO: \"PROFILE\" says debug both times, though!\n    //\n    // - Dependency profiles:\n    //   Pkg  Target  Profile        Reason\n    //   ---  ------  -------        ------\n    //   bar  lib     release        For foo-bin\n    //   bar  lib     release-panic  For tests/benches and bdep\n    //   bdep lib     release-panic  For foo build.rs\n    //   foo  custom  release-panic\n    //\n    // - `foo` target list is:\n    //   Target   Profile        Mode\n    //   ------   -------        ----\n    //   lib      release+panic  build  (a normal lib target)\n    //   lib      release-panic  build  (used by tests/benches)\n    //   lib      release        test   (bench/test de-duped)\n    //   test     release        test\n    //   bench    release        test\n    //   bin      release        test   (bench/test de-duped)\n    //   bin      release        build\n    //   example  release        build\n    p.cargo(\"build --all-targets --release -vv\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C embed-bitcode=[..]-C codegen-units=2 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort -C embed-bitcode=[..]-C codegen-units=2 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=6 [..]`\n[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep)\n[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=6 [..]`\n[RUNNING] `[..][ROOT]/foo/target/release/build/foo-[HASH]/build-script-build`\n[foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3[..]-C codegen-units=2 [..]`\n[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]`\n[RUNNING] `[..] rustc --crate-name bench1 --edition=2015 benches/bench1.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]`\n[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n    p.cargo(\"build --all-targets --release -vv\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] bar v0.0.1 ([ROOT]/foo/bar)\n[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn profile_selection_test() {\n    let p = all_target_project();\n    // `test`\n    // NOTES:\n    // - Dependency profiles:\n    //   Pkg  Target  Profile    Reason\n    //   ---  ------  -------    ------\n    //   bar  lib     test        For foo-bin\n    //   bar  lib     test-panic  For tests/benches and bdep\n    //   bdep lib     test-panic  For foo build.rs\n    //   foo  custom  test-panic\n    //\n    // - `foo` target list is:\n    //   Target   Profile        Mode\n    //   ------   -------        ----\n    //   lib      test-panic     build (for tests)\n    //   lib      test           build (for bins)\n    //   lib      test           test\n    //   test     test           test\n    //   example  test-panic     build\n    //   bin      test           test\n    //   bin      test           build\n    //\n    p.cargo(\"test -vv\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=3 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=5 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C embed-bitcode=[..]-C codegen-units=3 -C debuginfo=2 [..]`\n[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep)\n[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]`\n[RUNNING] `[..][ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C codegen-units=3 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=3 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]link[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]link[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=3 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C panic=abort[..]-C codegen-units=3 -C debuginfo=2 [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[..][ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[RUNNING] `[..][ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[RUNNING] `[..][ROOT]/foo/target/debug/deps/test1-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `[..] rustdoc [..]--test [..]\n\n\"#]].unordered())\n        .run();\n    p.cargo(\"test -vv\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep)\n[FRESH] bar v0.0.1 ([ROOT]/foo/bar)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[..][ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[RUNNING] `[..][ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[RUNNING] `[..][ROOT]/foo/target/debug/deps/test1-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `[..] rustdoc [..]--test [..]\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn profile_selection_test_release() {\n    let p = all_target_project();\n\n    // `test --release`\n    // NOTES:\n    // - Dependency profiles:\n    //   Pkg  Target  Profile        Reason\n    //   ---  ------  -------        ------\n    //   bar  lib     release        For foo-bin\n    //   bar  lib     release-panic  For tests/benches and bdep\n    //   bdep lib     release-panic  For foo build.rs\n    //   foo  custom  release-panic\n    //\n    // - `foo` target list is:\n    //   Target   Profile        Mode\n    //   ------   -------        ----\n    //   lib      release-panic  build  (for tests)\n    //   lib      release        build  (for bins)\n    //   lib      release        test\n    //   test     release        test\n    //   example  release-panic  build\n    //   bin      release        test\n    //   bin      release        build\n    //\n    p.cargo(\"test --release -vv\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C opt-level=3[..]-C codegen-units=2[..]`\n[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep)\n[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=6 [..]`\n[RUNNING] `[..][ROOT]/foo/target/release/build/foo-[HASH]/build-script-build`\n[foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3[..]-C codegen-units=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]`\n[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]`\n[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type bin --emit=[..]link -C opt-level=3[..]-C codegen-units=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n[RUNNING] `[..][ROOT]/foo/target/release/deps/test1-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `[..] rustdoc [..]--test [..]`\n\n\"#]].unordered())\n        .run();\n    p.cargo(\"test --release -vv\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep)\n[FRESH] bar v0.0.1 ([ROOT]/foo/bar)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n[RUNNING] `[..][ROOT]/foo/target/release/deps/test1-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `[..] rustdoc [..]--test [..]\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn profile_selection_bench() {\n    let p = all_target_project();\n\n    // `bench`\n    // NOTES:\n    // - Dependency profiles:\n    //   Pkg  Target  Profile        Reason\n    //   ---  ------  -------        ------\n    //   bar  lib     bench          For foo-bin\n    //   bar  lib     bench-panic    For tests/benches and bdep\n    //   bdep lib     bench-panic    For foo build.rs\n    //   foo  custom  bench-panic\n    //\n    // - `foo` target list is:\n    //   Target   Profile        Mode\n    //   ------   -------        ----\n    //   lib      bench-panic    build (for benches)\n    //   lib      bench          build (for bins)\n    //   lib      bench          test(bench)\n    //   bench    bench          test(bench)\n    //   bin      bench          test(bench)\n    //   bin      bench          build\n    //\n    p.cargo(\"bench -vv\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C embed-bitcode=[..]-C codegen-units=4 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort -C embed-bitcode=[..]-C codegen-units=4 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=6 [..]`\n[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep)\n[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=6 [..]`\n[RUNNING] `[..][ROOT]/foo/target/release/build/foo-[HASH]/build-script-build`\n[foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=4 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3[..]-C codegen-units=4 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=4 --test [..]`\n[RUNNING] `[..] rustc --crate-name bench1 --edition=2015 benches/bench1.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=4 --test [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=4 --test [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=4 [..]`\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE] --bench`\n[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE] --bench`\n[RUNNING] `[..][ROOT]/foo/target/release/deps/bench1-[HASH][EXE] --bench`\n\n\"#]].unordered())\n        .run();\n    p.cargo(\"bench -vv\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep)\n[FRESH] bar v0.0.1 ([ROOT]/foo/bar)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE] --bench`\n[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE] --bench`\n[RUNNING] `[..][ROOT]/foo/target/release/deps/bench1-[HASH][EXE] --bench`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn profile_selection_check_all_targets() {\n    let p = all_target_project();\n    // `check`\n    // NOTES:\n    // - Dependency profiles:\n    //   Pkg  Target  Profile    Action   Reason\n    //   ---  ------  -------    ------   ------\n    //   bar  lib     dev*       link     For bdep\n    //   bar  lib     dev-panic  metadata For tests/benches\n    //   bar  lib     dev        metadata For lib/bins\n    //   bdep lib     dev*       link     For foo build.rs\n    //   foo  custom  dev*       link     For build.rs\n    //\n    //   `*` = wants panic, but it is cleared when args are built.\n    //\n    // - foo target list is:\n    //   Target   Profile        Mode\n    //   ------   -------        ----\n    //   lib      dev            check\n    //   lib      dev-panic      check (for tests/benches)\n    //   lib      dev-panic      check-test (checking lib as a unittest)\n    //   example  dev            check\n    //   test     dev-panic      check-test\n    //   bench    dev-panic      check-test\n    //   bin      dev            check\n    //   bin      dev-panic      check-test (checking bin as a unittest)\n    //\n    p.cargo(\"check --all-targets -vv\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=5 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C embed-bitcode=[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C panic=abort -C embed-bitcode=[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep)\n[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]`\n[RUNNING] `[..][ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]metadata -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]metadata[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]metadata[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]metadata[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]metadata[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name bench1 --edition=2015 benches/bench1.rs [..]--emit=[..]metadata[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type bin --emit=[..]metadata -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]metadata -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n    // Starting with Rust 1.27, rustc emits `rmeta` files for bins, so\n    // everything should be completely fresh. Previously, bins were being\n    // rechecked.\n    // See PR rust-lang/rust#49289 and issue rust-lang/cargo#3624.\n    p.cargo(\"check --all-targets -vv\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep)\n[FRESH] bar v0.0.1 ([ROOT]/foo/bar)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn profile_selection_check_all_targets_release() {\n    let p = all_target_project();\n    // `check --release`\n    // See issue rust-lang/cargo#5218.\n    // This is a pretty straightforward variant of\n    // `profile_selection_check_all_targets` that uses `release` instead of\n    // `dev` for all targets.\n    p.cargo(\"check --all-targets --release -vv\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..]\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C opt-level=3[..]-C codegen-units=2 [..]\n[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep)\n[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link [..]-C codegen-units=6 [..]\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=6 [..]\n[RUNNING] `[..][ROOT]/foo/target/release/build/foo-[HASH]/build-script-build`\n[foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]metadata -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]metadata -C opt-level=3[..]-C codegen-units=2 [..]\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]metadata -C opt-level=3[..]-C codegen-units=2 --test [..]\n[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]metadata -C opt-level=3[..]-C codegen-units=2 --test [..]\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]metadata -C opt-level=3[..]-C codegen-units=2 --test [..]\n[RUNNING] `[..] rustc --crate-name bench1 --edition=2015 benches/bench1.rs [..]--emit=[..]metadata -C opt-level=3[..]-C codegen-units=2 --test [..]\n[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type bin --emit=[..]metadata -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]metadata -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n\n    p.cargo(\"check --all-targets --release -vv\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] bar v0.0.1 ([ROOT]/foo/bar)\n[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn profile_selection_check_all_targets_test() {\n    let p = all_target_project();\n\n    // `check --profile=test`\n    // - Dependency profiles:\n    //   Pkg  Target  Profile    Action   Reason\n    //   ---  ------  -------    ------   ------\n    //   bar  lib     test*       link     For bdep\n    //   bar  lib     test-panic  metadata  For tests/benches\n    //   bdep lib     test*       link     For foo build.rs\n    //   foo  custom  test*       link     For build.rs\n    //\n    //   `*` = wants panic, but it is cleared when args are built.\n    //\n    // - foo target list is:\n    //   Target   Profile     Mode\n    //   ------   -------     ----\n    //   lib      test-panic  check-test (for tests/benches)\n    //   lib      test-panic  check-test (checking lib as a unittest)\n    //   example  test-panic  check-test\n    //   test     test-panic  check-test\n    //   bench    test-panic  check-test\n    //   bin      test-panic  check-test\n    //\n    p.cargo(\"check --all-targets --profile=test -vv\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]`\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]`\n[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep)\n[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]`\n[RUNNING] `[..][ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name bench1 --edition=2015 benches/bench1.rs [..]--emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]`\n[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered())\n        .run();\n\n    p.cargo(\"check --all-targets --profile=test -vv\")\n        .with_stderr_data(\n            str![[r#\"\n[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep)\n[FRESH] bar v0.0.1 ([ROOT]/foo/bar)\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn profile_selection_doc() {\n    let p = all_target_project();\n    // `doc`\n    // NOTES:\n    // - Dependency profiles:\n    //   Pkg  Target  Profile    Action   Reason\n    //   ---  ------  -------    ------   ------\n    //   bar  lib     dev*       link     For bdep\n    //   bar  lib     dev        metadata For rustdoc\n    //   bdep lib     dev*       link     For foo build.rs\n    //   foo  custom  dev*       link     For build.rs\n    //\n    //   `*` = wants panic, but it is cleared when args are built.\n    p.cargo(\"doc -vv\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]`\n[RUNNING] `[..] rustdoc [..]--crate-name bar bar/src/lib.rs [..]\n[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]`\n[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep)\n[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]`\n[RUNNING] `[..][ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build`\n[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustdoc [..]--crate-name foo src/lib.rs [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]].unordered())\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/profile_trim_paths.rs",
    "content": "//! Tests for `-Ztrim-paths`.\n\nuse crate::prelude::*;\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::git;\nuse cargo_test_support::paths;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn gated_manifest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                trim-paths = \"macro\"\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `trim-paths` is required\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn gated_config_toml() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [profile.dev]\n                trim-paths = \"macro\"\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] config profile `dev` is not valid (defined in `[ROOT]/foo/.cargo/config.toml`)\n\nCaused by:\n  feature `trim-paths` is required\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--remap-path-scope will be stabilized in 1.95\")]\nfn release_profile_default_to_object() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --release --verbose -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--remap-path-scope will be stabilized in 1.95\")]\nfn one_option() {\n    let build = |option| {\n        let p = project()\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n\n                    [profile.dev]\n                    trim-paths = \"{option}\"\n                \"#\n                ),\n            )\n            .file(\"src/lib.rs\", \"\")\n            .build();\n\n        p.cargo(\"build -v -Ztrim-paths\")\n    };\n\n    for option in [\"macro\", \"diagnostics\", \"object\", \"all\"] {\n        build(option)\n            .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n            .with_stderr_data(&format!(\n                \"\\\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]\\\n    --remap-path-scope={option} \\\n    --remap-path-prefix=[ROOT]/foo=. \\\n    --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\",\n            ))\n            .run();\n    }\n    build(\"none\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stderr_does_not_contain(\"[..]--remap-path-scope=[..]\")\n        .with_stderr_does_not_contain(\"[..]--remap-path-prefix=[..]\")\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--remap-path-scope will be stabilized in 1.95\")]\nfn multiple_options() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                trim-paths = [\"diagnostics\", \"macro\", \"object\"]\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --verbose -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]--remap-path-scope=diagnostics,macro,object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--remap-path-scope will be stabilized in 1.95\")]\nfn profile_merge_works() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                trim-paths = [\"macro\"]\n\n                [profile.custom]\n                inherits = \"dev\"\n                trim-paths = [\"diagnostics\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v -Ztrim-paths --profile custom\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]--remap-path-scope=diagnostics --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[FINISHED] `custom` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--remap-path-scope will be stabilized in 1.95\")]\nfn registry_dependency() {\n    Package::new(\"bar\", \"0.0.1\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"src/lib.rs\", r#\"pub fn f() { println!(\"{}\", file!()); }\"#)\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.0.1\"\n\n                [profile.dev]\n                trim-paths = \"object\"\n           \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() { bar::f(); }\")\n        .build();\n\n    p.cargo(\"run --verbose -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stdout_data(str![[r#\"\n-[..]/bar-0.0.1/src/lib.rs\n\n\"#]]) // Omit the hash of Source URL\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[COMPILING] bar v0.0.1\n[RUNNING] `rustc [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/home/.cargo/registry/src= --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--remap-path-scope will be stabilized in 1.95\")]\nfn registry_dependency_with_build_script_codegen() {\n    Package::new(\"bar\", \"0.0.1\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                let out_dir = std::env::var(\"OUT_DIR\").unwrap();\n                let dest = std::path::PathBuf::from(out_dir);\n                std::fs::write(\n                    dest.join(\"bindings.rs\"),\n                    \"pub fn my_file() -> &'static str { file!() }\",\n                )\n                .unwrap();\n            }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            include!(concat!(env!(\"OUT_DIR\"), \"/bindings.rs\"));\n        \"#,\n        )\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.0.1\"\n\n                [profile.dev]\n                trim-paths = \"object\"\n           \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"fn main() { println!(\"{}\", bar::my_file()); }\"#,\n        )\n        .build();\n\n    p.cargo(\"run --verbose -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        // Macros should be sanitized\n        .with_stdout_data(str![[r#\"\n/cargo/build-dir/debug/build/bar-[HASH]/out/bindings.rs\n\n\"#]]) // Omit the hash of Source URL\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[COMPILING] bar v0.0.1\n[RUNNING] `rustc --crate-name build_script_build [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/home/.cargo/registry/src= --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/bar-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name bar [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/home/.cargo/registry/src= --remap-path-prefix=[ROOT]/foo/target=/cargo/build-dir --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--remap-path-scope will be stabilized in 1.95\")]\nfn git_dependency() {\n    let git_project = git::new(\"bar\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n            .file(\"src/lib.rs\", r#\"pub fn f() { println!(\"{}\", file!()); }\"#)\n    });\n    let url = git_project.url();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = {{ git = \"{url}\" }}\n\n                [profile.dev]\n                trim-paths = \"object\"\n           \"#\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() { bar::f(); }\")\n        .build();\n\n    p.cargo(\"run --verbose -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stdout_data(str![[r#\"\nbar-[..]/[..]/src/lib.rs\n\n\"#]]) // Omit the hash of Source URL and commit\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/bar`\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOTURL]/bar#[..])\n[RUNNING] `rustc [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/home/.cargo/git/checkouts= --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--remap-path-scope will be stabilized in 1.95\")]\nfn path_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"cocktail-bar\" }\n\n                [profile.dev]\n                trim-paths = \"object\"\n           \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() { bar::f(); }\")\n        .file(\"cocktail-bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\n            \"cocktail-bar/src/lib.rs\",\n            r#\"pub fn f() { println!(\"{}\", file!()); }\"#,\n        )\n        .build();\n\n    p.cargo(\"run --verbose -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stdout_data(str![[r#\"\ncocktail-bar/src/lib.rs\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/cocktail-bar)\n[RUNNING] `rustc [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--remap-path-scope will be stabilized in 1.95\")]\nfn path_dependency_outside_workspace() {\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"src/lib.rs\", r#\"pub fn f() { println!(\"{}\", file!()); }\"#)\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"../bar\" }\n\n                [profile.dev]\n                trim-paths = \"object\"\n           \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() { bar::f(); }\")\n        .build();\n\n    p.cargo(\"run --verbose -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stdout_data(str![[r#\"\nbar-0.0.1/src/lib.rs\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/bar)\n[RUNNING] `rustc [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/bar=bar-0.0.1 --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--remap-path-scope will be stabilized in 1.95\")]\nfn diagnostics_works() {\n    Package::new(\"bar\", \"0.0.1\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"src/lib.rs\", r#\"pub fn f() { let unused = 0; }\"#)\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.0.1\"\n\n                [profile.dev]\n                trim-paths = \"diagnostics\"\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let registry_src = paths::home().join(\".cargo/registry/src\");\n    let registry_src = registry_src.display();\n\n    p.cargo(\"build -vv -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stderr_line_without(\n            &[\"[..]bar-0.0.1/src/lib.rs:1[..]\"],\n            &[&format!(\"{registry_src}\")],\n        )\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `[..] rustc [..]--remap-path-scope=diagnostics --remap-path-prefix=[ROOT]/home/.cargo/registry/src= --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[WARNING] unused variable: `unused`\n...\n[RUNNING] `[..] rustc [..]--remap-path-scope=diagnostics --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n...\n\"#]])\n        .run();\n}\n\n#[cfg(target_os = \"macos\")]\nmod object_works {\n    use super::*;\n\n    fn inspect_debuginfo(path: &std::path::Path) -> Vec<u8> {\n        std::process::Command::new(\"nm\")\n            .arg(\"-pa\")\n            .arg(path)\n            .output()\n            .expect(\"nm works\")\n            .stdout\n    }\n\n    #[cargo_test(\n        requires = \"nm\",\n        nightly,\n        reason = \"--remap-path-scope will be stabilized in 1.95\"\n    )]\n    fn with_split_debuginfo_off() {\n        object_works_helper(\"off\", inspect_debuginfo);\n    }\n\n    #[cargo_test(\n        requires = \"nm\",\n        nightly,\n        reason = \"--remap-path-scope will be stabilized in 1.95\"\n    )]\n    fn with_split_debuginfo_packed() {\n        object_works_helper(\"packed\", inspect_debuginfo);\n    }\n\n    #[cargo_test(\n        requires = \"nm\",\n        nightly,\n        reason = \"--remap-path-scope will be stabilized in 1.95\"\n    )]\n    fn with_split_debuginfo_unpacked() {\n        object_works_helper(\"unpacked\", inspect_debuginfo);\n    }\n}\n\n#[cfg(target_os = \"linux\")]\nmod object_works {\n    use super::*;\n\n    fn inspect_debuginfo(path: &std::path::Path) -> Vec<u8> {\n        std::process::Command::new(\"readelf\")\n            .arg(\"--debug-dump=info\")\n            .arg(\"--debug-dump=no-follow-links\") // older version can't recognized but just a warning\n            .arg(path)\n            .output()\n            .expect(\"readelf works\")\n            .stdout\n    }\n\n    #[cargo_test(\n        requires = \"readelf\",\n        nightly,\n        reason = \"--remap-path-scope will be stabilized in 1.95\"\n    )]\n    fn with_split_debuginfo_off() {\n        object_works_helper(\"off\", inspect_debuginfo);\n    }\n\n    #[cargo_test(\n        requires = \"readelf\",\n        nightly,\n        reason = \"--remap-path-scope will be stabilized in 1.95\"\n    )]\n    fn with_split_debuginfo_packed() {\n        object_works_helper(\"packed\", inspect_debuginfo);\n    }\n\n    #[cargo_test(\n        requires = \"readelf\",\n        nightly,\n        reason = \"--remap-path-scope will be stabilized in 1.95\"\n    )]\n    fn with_split_debuginfo_unpacked() {\n        object_works_helper(\"unpacked\", inspect_debuginfo);\n    }\n}\n\n#[cfg(target_env = \"msvc\")]\nmod object_works {\n    use super::*;\n\n    fn inspect_debuginfo(path: &std::path::Path) -> Vec<u8> {\n        std::process::Command::new(\"strings\")\n            .arg(path)\n            .output()\n            .expect(\"strings works\")\n            .stdout\n    }\n\n    // windows-msvc supports split-debuginfo=packed only\n    #[cargo_test(\n        requires = \"strings\",\n        nightly,\n        reason = \"--remap-path-scope will be stabilized in 1.95\"\n    )]\n    fn with_split_debuginfo_packed() {\n        object_works_helper(\"packed\", inspect_debuginfo);\n    }\n}\n\nfn object_works_helper(split_debuginfo: &str, run: impl Fn(&std::path::Path) -> Vec<u8>) {\n    let registry_src = paths::home().join(\".cargo/registry/src\");\n    let registry_src_bytes = registry_src.as_os_str().as_encoded_bytes();\n    let rust_src = \"/lib/rustc/src/rust\".as_bytes();\n\n    Package::new(\"bar\", \"0.0.1\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"src/lib.rs\", r#\"pub fn f() { println!(\"{}\", file!()); }\"#)\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.0.1\"\n\n                [profile.dev]\n                split-debuginfo = \"{split_debuginfo}\"\n           \"#\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() { bar::f(); }\")\n        .build();\n\n    let pkg_root = p.root();\n    let pkg_root = pkg_root.as_os_str().as_encoded_bytes();\n\n    p.cargo(\"build\").run();\n\n    let bin_path = p.bin(\"foo\");\n    assert!(bin_path.is_file());\n    let stdout = run(&bin_path);\n    // On windows-msvc every debuginfo is in pdb file, so can't find anything here.\n    if cfg!(target_env = \"msvc\") {\n        // TODO: re-enable this check when rustc bootstrap disables remapping\n        // <https://github.com/rust-lang/cargo/pull/12625#discussion_r1371714791>\n        // assert!(memchr::memmem::find(&stdout, rust_src).is_some());\n        assert!(memchr::memmem::find(&stdout, registry_src_bytes).is_none());\n        assert!(memchr::memmem::find(&stdout, pkg_root).is_none());\n    } else {\n        // TODO: re-enable this check when rustc bootstrap disables remapping\n        // <https://github.com/rust-lang/cargo/pull/12625#discussion_r1371714791>\n        // assert!(memchr::memmem::find(&stdout, rust_src).is_some());\n        assert!(memchr::memmem::find(&stdout, registry_src_bytes).is_some());\n        assert!(memchr::memmem::find(&stdout, pkg_root).is_some());\n    }\n    p.cargo(\"clean\").run();\n\n    p.cargo(\"build --verbose -Ztrim-paths\")\n        .arg(\"--config\")\n        .arg(r#\"profile.dev.trim-paths=\"object\"\"#)\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stderr_data(&format!(\n            \"\\\n[COMPILING] bar v0.0.1\n[RUNNING] `rustc [..]-C split-debuginfo={split_debuginfo} [..]\\\n    --remap-path-scope=object \\\n    --remap-path-prefix=[ROOT]/home/.cargo/registry/src= \\\n    --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]-C split-debuginfo={split_debuginfo} [..]\\\n    --remap-path-scope=object \\\n    --remap-path-prefix=[ROOT]/foo=. \\\n    --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\",\n        ))\n        .run();\n\n    let bin_path = p.bin(\"foo\");\n    assert!(bin_path.is_file());\n    let stdout = run(&bin_path);\n    assert!(memchr::memmem::find(&stdout, rust_src).is_none());\n    for line in stdout.split(|c| c == &b'\\n') {\n        let registry = memchr::memmem::find(line, registry_src_bytes).is_none();\n        let local = memchr::memmem::find(line, pkg_root).is_none();\n        if registry && local {\n            continue;\n        }\n\n        #[cfg(target_os = \"macos\")]\n        {\n            // `OSO` symbols can't be trimmed at this moment.\n            // See <https://github.com/rust-lang/rust/issues/116948#issuecomment-1793617018>\n            if memchr::memmem::find(line, b\" OSO \").is_some() {\n                continue;\n            }\n        }\n\n        panic!(\n            \"unexpected untrimmed symbol: {}\",\n            String::from_utf8(line.into()).unwrap()\n        );\n    }\n}\n\n// TODO: might want to move to test/testsuite/build_script.rs once stabilized.\n#[cargo_test(nightly, reason = \"--remap-path-scope will be stabilized in 1.95\")]\nfn custom_build_env_var_trim_paths() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"\")\n        .build();\n\n    let test_cases = [\n        (\"[]\", \"none\"),\n        (\"\\\"all\\\"\", \"all\"),\n        (\"\\\"diagnostics\\\"\", \"diagnostics\"),\n        (\"\\\"macro\\\"\", \"macro\"),\n        (\"\\\"none\\\"\", \"none\"),\n        (\"\\\"object\\\"\", \"object\"),\n        (\"false\", \"none\"),\n        (\"true\", \"all\"),\n        (\n            r#\"[\"diagnostics\", \"macro\", \"object\"]\"#,\n            \"diagnostics,macro,object\",\n        ),\n    ];\n\n    for (opts, expected) in test_cases {\n        p.change_file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                trim-paths = {opts}\n                \"#\n            ),\n        );\n\n        p.change_file(\n            \"build.rs\",\n            &format!(\n                r#\"\n                fn main() {{\n                    assert_eq!(\n                        std::env::var(\"CARGO_TRIM_PATHS\").unwrap().as_str(),\n                        \"{expected}\",\n                    );\n                }}\n                \"#\n            ),\n        );\n\n        p.cargo(\"build -Ztrim-paths\")\n            .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n            .run();\n    }\n}\n\n// This test is disabled, as it currently doesn't work due to issues with lldb.\n#[cfg(any())]\n#[cfg(unix)]\n#[cargo_test(\n    requires = \"lldb\",\n    nightly,\n    reason = \"--remap-path-scope will be stabilized in 1.95\"\n)]\nfn lldb_works_after_trimmed() {\n    use cargo_test_support::compare::assert_e2e;\n    use cargo_util::is_ci;\n\n    if !is_ci() {\n        // On macOS lldb requires elevated privileges to run developer tools.\n        // See rust-lang/cargo#13413\n        return;\n    }\n\n    let run_lldb = |path| {\n        std::process::Command::new(\"lldb\")\n            .args([\"-o\", \"breakpoint set --file src/main.rs --line 4\"])\n            .args([\"-o\", \"run\"])\n            .args([\"-o\", \"continue\"])\n            .args([\"-o\", \"exit\"])\n            .arg(\"--no-use-colors\")\n            .arg(path)\n            .output()\n            .expect(\"lldb works\")\n    };\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                trim-paths = \"object\"\n           \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    let msg = \"Hello, Ferris!\";\n                    println!(\"{msg}\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --verbose -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let bin_path = p.bin(\"foo\");\n    assert!(bin_path.is_file());\n    let stdout = String::from_utf8(run_lldb(bin_path).stdout).unwrap();\n    assert_e2e().eq(\n        &stdout,\n        str![[r#\"\n...\n[..]stopped[..]\n[..]stop reason = breakpoint 1.1[..]\n...\n(lldb) continue\nHello, Ferris!\n...\n\n\"#]],\n    );\n}\n\n// This test is disabled, as it currently doesn't work.\n#[cfg(any())]\n#[cfg(target_env = \"msvc\")]\n#[cargo_test(\n    requires = \"cdb\",\n    nightly,\n    reason = \"--remap-path-scope will be stabilized in 1.95\"\n)]\nfn cdb_works_after_trimmed() {\n    use cargo_test_support::compare::assert_e2e;\n\n    let run_debugger = |path| {\n        std::process::Command::new(\"cdb\")\n            .args([\"-c\", \"bp `main.rs:4`;g;g;q\"])\n            .arg(path)\n            .output()\n            .expect(\"debugger works\")\n    };\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                trim-paths = \"object\"\n           \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    let msg = \"Hello, Ferris!\";\n                    println!(\"{msg}\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --verbose -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]--remap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let bin_path = p.bin(\"foo\");\n    assert!(bin_path.is_file());\n    let stdout = String::from_utf8(run_debugger(bin_path).stdout).unwrap();\n    assert_e2e().eq(\n        &stdout,\n        str![[r#\"\n...\nBreakpoint 0 hit\nHello, Ferris!\n...\n\n\"#]],\n    );\n}\n\n#[cargo_test(nightly, reason = \"rustdoc --remap-path-prefix is unstable\")]\nfn rustdoc_without_diagnostics_scope() {\n    Package::new(\"bar\", \"0.0.1\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            /// </script>\n            pub struct Bar;\n            \"#,\n        )\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.0.1\"\n\n                [profile.dev]\n                trim-paths = \"object\"\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -vv -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] unopened HTML tag `script`\n --> [ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/src/lib.rs:2:17\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"rustdoc --remap-path-prefix is unstable\")]\nfn rustdoc_diagnostics_works() {\n    // This is expected to work after rust-lang/rust#128736\n    Package::new(\"bar\", \"0.0.1\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            /// </script>\n            pub struct Bar;\n            \"#,\n        )\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.0.1\"\n\n                [profile.dev]\n                trim-paths = \"diagnostics\"\n           \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"doc -vv -Ztrim-paths\")\n        .masquerade_as_nightly_cargo(&[\"-Ztrim-paths\"])\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `[..]rustc [..]--remap-path-scope=diagnostics --remap-path-prefix=[ROOT]/home/.cargo/registry/src= --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]`\n...\n[WARNING] unopened HTML tag `script`\n --> -[..]/bar-0.0.1/src/lib.rs:2:17\n...\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/profiles.rs",
    "content": "//! Tests for profiles.\n\nuse std::env;\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{project, rustc_host, str};\n\n#[cargo_test]\nfn profile_overrides() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.dev]\n                opt-level = 1\n                debug = false\n                rpath = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build -v\").with_stderr_data(str![[r#\"\n[COMPILING] test v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name test --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..] -C opt-level=1[..] -C debug-assertions=on[..] -C metadata=[..] -C rpath --out-dir [ROOT]/foo/target/debug/deps [..] -L dependency=[ROOT]/foo/target/debug/deps`\n[FINISHED] `dev` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn opt_level_override_0() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.dev]\n                opt-level = 0\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build -v\").with_stderr_data(str![[r#\"\n[COMPILING] test v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name test --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..] -C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn debug_override_1() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.dev]\n                debug = 1\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build -v\").with_stderr_data(str![[r#\"\n[COMPILING] test v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name test --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=1 [..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\nfn check_opt_level_override(profile_level: &str, rustc_level: &str) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n\n                    name = \"test\"\n                    version = \"0.0.0\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [profile.dev]\n                    opt-level = {level}\n                \"#,\n                level = profile_level\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build -v\")\n        .with_stderr_data(&format!(\n            \"\\\n[COMPILING] test v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name test --edition=2015 src/lib.rs [..]--crate-type lib \\\n        --emit=[..]link \\\n        -C opt-level={level}[..]\\\n        -C debuginfo=2 [..]\\\n        -C debug-assertions=on[..] \\\n        -C metadata=[..] \\\n        --out-dir [..] \\\n        -L dependency=[ROOT]/foo/target/debug/deps`\n[FINISHED] `dev` profile [..]+ debuginfo] target(s) in [ELAPSED]s\n\",\n            level = rustc_level\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn opt_level_overrides() {\n    for &(profile_level, rustc_level) in &[\n        (\"1\", \"1\"),\n        (\"2\", \"2\"),\n        (\"3\", \"3\"),\n        (\"\\\"s\\\"\", \"s\"),\n        (\"\\\"z\\\"\", \"z\"),\n    ] {\n        check_opt_level_override(profile_level, rustc_level)\n    }\n}\n\n#[cargo_test]\nfn top_level_overrides_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"test\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.release]\n                opt-level = 1\n                debug = true\n\n                [dependencies.foo]\n                path = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.release]\n                opt-level = 0\n                debug = false\n\n                [lib]\n                name = \"foo\"\n                crate-type = [\"dylib\", \"rlib\"]\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build -v --release\")\n        .with_stderr_data(&format!(\n            \"\\\n[LOCKING] 1 package to latest compatible version\n[COMPILING] foo v0.0.0 ([ROOT]/foo/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 foo/src/lib.rs [..]\\\n        --crate-type dylib --crate-type rlib \\\n        --emit=[..]link \\\n        -C prefer-dynamic \\\n        -C opt-level=1[..]\\\n        -C debuginfo=2 [..]\\\n        -C metadata=[..] \\\n        --out-dir [ROOT]/foo/target/release/deps \\\n        -L dependency=[ROOT]/foo/target/release/deps`\n[COMPILING] test v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name test --edition=2015 src/lib.rs [..]--crate-type lib \\\n        --emit=[..]link \\\n        -C opt-level=1[..]\\\n        -C debuginfo=2 [..]\\\n        -C metadata=[..] \\\n        --out-dir [..] \\\n        -L dependency=[ROOT]/foo/target/release/deps \\\n        --extern foo=[ROOT]/foo/target/release/deps/\\\n                     {prefix}foo[..]{suffix} \\\n        --extern foo=[ROOT]/foo/target/release/deps/libfoo.rlib`\n[FINISHED] `release` profile [optimized + debuginfo] target(s) in [ELAPSED]s\n\",\n            prefix = env::consts::DLL_PREFIX,\n            suffix = env::consts::DLL_SUFFIX\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn profile_in_non_root_manifest_triggers_a_warning() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"bar\"]\n\n                [profile.dev]\n                debug = false\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"..\"\n\n                [profile.dev]\n                opt-level = 1\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .cwd(\"bar\")\n        .with_stderr_data(str![[r#\"\n[WARNING] profiles for the non root package will be ignored, specify profiles at the workspace root:\npackage:   [ROOT]/foo/bar/Cargo.toml\nworkspace: [ROOT]/foo/Cargo.toml\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc [..]`\n[FINISHED] `dev` profile [unoptimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_in_virtual_manifest_works() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n\n                [profile.dev]\n                opt-level = 1\n                debug = false\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"..\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .cwd(\"bar\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.1.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc [..]`\n[FINISHED] `dev` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_lto_string_bool_dev() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.dev]\n                lto = \"true\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  `lto` setting of string `\"true\"` for `dev` profile is not a valid setting, must be a boolean (`true`/`false`) or a string (`\"thin\"`/`\"fat\"`/`\"off\"`) or omitted.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_panic_test_bench() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.test]\n                panic = \"abort\"\n\n                [profile.bench]\n                panic = \"abort\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `panic` setting is ignored for `bench` profile\n[WARNING] `panic` setting is ignored for `test` profile\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn profile_doc_deprecated() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [profile.doc]\n                opt-level = 0\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[WARNING] profile `doc` is deprecated and has no effect\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn panic_unwind_does_not_build_twice() {\n    // Check for a bug where `lib` was built twice, once with panic set and\n    // once without. Since \"unwind\" is the default, they are the same and\n    // should only be built once.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [profile.dev]\n            panic = \"unwind\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"tests/t1.rs\", \"\")\n        .build();\n\n    p.cargo(\"test -v --tests --no-run\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib [..]`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] --test [..]`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin [..]`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..] --test [..]`\n[RUNNING] `rustc --crate-name t1 --edition=2015 tests/t1.rs [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/t1-[HASH][EXE]`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn debug_0_report() {\n    // The finished line handles 0 correctly.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [profile.dev]\n            debug = 0\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]`\n[FINISHED] `dev` profile [unoptimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stderr_does_not_contain(\"-C debuginfo\")\n        .run();\n}\n\n#[cargo_test]\nfn thin_lto_works() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"top\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.release]\n                lto = 'thin'\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --release -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] top v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] -C lto=thin [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn strip_works() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [profile.release]\n                strip = 'symbols'\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --release -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] -C strip=symbols [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn strip_passes_unknown_option_to_rustc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [profile.release]\n                strip = 'unknown'\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --release -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] -C strip=unknown [..]`\n[ERROR] incorrect value `unknown` for [..] `strip` [..] was expected\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn strip_accepts_true_to_strip_symbols() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [profile.release]\n                strip = true\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --release -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] -C strip=symbols [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn strip_accepts_false_to_disable_strip() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [profile.release]\n                strip = false\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --release -v\")\n        .with_stderr_does_not_contain(\"[RUNNING] `rustc [..] -C strip[..]`\")\n        .run();\n}\n\n#[cargo_test]\nfn strip_debuginfo_in_release() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --release -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] -C strip=debuginfo[..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build --release -v --target\")\n        .arg(rustc_host())\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] -C strip=debuginfo[..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn strip_debuginfo_without_debug() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                \n                [profile.dev]\n                debug = 0\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -C strip=debuginfo[..]`\n[FINISHED] `dev` profile [unoptimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn do_not_strip_debuginfo_with_requested_debug() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [profile.release.package.bar]\n                debug = 1\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n        \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --release -v\")\n        .with_stderr_does_not_contain(\"[RUNNING] `rustc [..] -C strip=debuginfo[..]`\")\n        .run();\n}\n\n#[cargo_test]\nfn rustflags_works() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            cargo-features = [\"profile-rustflags\"]\n\n            [profile.dev]\n            rustflags = [\"-C\", \"link-dead-code=yes\"]\n\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .masquerade_as_nightly_cargo(&[\"profile-rustflags\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -C link-dead-code=yes [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustflags_works_with_env() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            cargo-features = [\"profile-rustflags\"]\n\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .env(\"CARGO_PROFILE_DEV_RUSTFLAGS\", \"-C link-dead-code=yes\")\n        .masquerade_as_nightly_cargo(&[\"profile-rustflags\"])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -C link-dead-code=yes [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustflags_requires_cargo_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [profile.dev]\n                rustflags = [\"-C\", \"link-dead-code=yes\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .masquerade_as_nightly_cargo(&[\"profile-rustflags\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `profile-rustflags` is required\n\n  The package requires the Cargo feature called `profile-rustflags`, but that feature is not stabilized in this version of Cargo (1.[..]).\n  Consider adding `cargo-features = [\"profile-rustflags\"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-rustflags-option for more information about the status of this feature.\n\n\"#]])\n        .run();\n\n    Package::new(\"bar\", \"1.0.0\").publish();\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"1.0\"\n\n            [profile.dev.package.bar]\n            rustflags = [\"-C\", \"link-dead-code=yes\"]\n        \"#,\n    );\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"profile-rustflags\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `profile-rustflags` is required\n\n  The package requires the Cargo feature called `profile-rustflags`, but that feature is not stabilized in this version of Cargo (1.[..]).\n  Consider adding `cargo-features = [\"profile-rustflags\"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature.\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-rustflags-option for more information about the status of this feature.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn debug_options_valid() {\n    let build = |option| {\n        let p = project()\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n                    [package]\n                    name = \"foo\"\n                    authors = []\n                    version = \"0.0.0\"\n                    edition = \"2015\"\n\n                    [profile.dev]\n                    debug = \"{option}\"\n                \"#\n                ),\n            )\n            .file(\"src/main.rs\", \"fn main() {}\")\n            .build();\n\n        p.cargo(\"build -v\")\n    };\n\n    for (option, cli) in [\n        (\"line-directives-only\", \"line-directives-only\"),\n        (\"line-tables-only\", \"line-tables-only\"),\n        (\"limited\", \"1\"),\n        (\"full\", \"2\"),\n    ] {\n        build(option)\n            .with_stderr_data(&format!(\n                \"\\\n...\n[RUNNING] `rustc [..]-C debuginfo={cli} [..]`\n...\n\"\n            ))\n            .run();\n    }\n    build(\"none\")\n        .with_stderr_does_not_contain(\"[..]-C debuginfo[..]\")\n        .run();\n}\n\n#[cargo_test]\nfn profile_hint_mostly_unused_warn_without_gate() {\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"1.0\"\n\n            [profile.dev.package.bar]\n            hint-mostly-unused = true\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[WARNING] bar@1.0.0: ignoring 'hint-mostly-unused' profile option, pass `-Zprofile-hint-mostly-unused` to enable it\n[CHECKING] bar v1.0.0\n[RUNNING] `rustc --crate-name bar [..]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stderr_does_not_contain(\"-Zhint-mostly-unused\")\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zhint-mostly-unused is unstable\")]\nfn profile_hint_mostly_unused_nightly() {\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = \"1.0\"\n\n            [profile.dev.package.bar]\n            hint-mostly-unused = true\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"check -Zprofile-hint-mostly-unused -v\")\n        .masquerade_as_nightly_cargo(&[\"profile-hint-mostly-unused\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] bar v1.0.0\n[RUNNING] `rustc --crate-name bar [..] -Zhint-mostly-unused [..]`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stderr_does_not_contain(\n            \"[RUNNING] `rustc --crate-name foo [..] -Zhint-mostly-unused [..]\",\n        )\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/progress.rs",
    "content": "//! Tests for progress bar.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn bad_progress_config_unknown_when() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [term]\n            progress = { when = 'unknown' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `term.progress.when`\n\nCaused by:\n  unknown variant `unknown`, expected one of `auto`, `never`, `always`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_progress_config_missing_width() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [term]\n            progress = { when = 'always' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] \"always\" progress requires a `width` key\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn default_progress_is_auto() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [term]\n            progress = { width = 1000 }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn always_shows_progress() {\n    const N: usize = 3;\n    let mut deps = String::new();\n    for i in 1..=N {\n        Package::new(&format!(\"dep{}\", i), \"1.0.0\").publish();\n        deps.push_str(&format!(\"dep{} = \\\"1.0\\\"\\n\", i));\n    }\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [term]\n            progress = { when = 'always', width = 100 }\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                {}\n                \"#,\n                deps\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[DOWNLOADING] [..] crate [..]\n[DOWNLOADED] 3 crates ([..]) in [..]s\n[BUILDING] [..] [..]/4: [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn never_progress() {\n    const N: usize = 3;\n    let mut deps = String::new();\n    for i in 1..=N {\n        Package::new(&format!(\"dep{}\", i), \"1.0.0\").publish();\n        deps.push_str(&format!(\"dep{} = \\\"1.0\\\"\\n\", i));\n    }\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [term]\n            progress = { when = 'never' }\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                {}\n                \"#,\n                deps\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_does_not_contain(\"[DOWNLOADING] [..] crates [..]\")\n        .with_stderr_does_not_contain(\"[..][DOWNLOADED] 3 crates ([..]) in [..]\")\n        .with_stderr_does_not_contain(\"[BUILDING] [..] [..]/4: [..]\")\n        .run();\n}\n\n#[cargo_test]\nfn plain_string_when_doesnt_work() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [term]\n            progress = \"never\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid configuration for key `term.progress`\nexpected a table, but found a string for `term.progress` in [ROOT]/foo/.cargo/config.toml\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/pub_priv.rs",
    "content": "//! Tests for public/private dependencies.\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::{Dependency, Package};\nuse cargo_test_support::{git, str};\nuse cargo_test_support::{project, registry};\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn exported_priv_warning() {\n    Package::new(\"priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"public-dependency\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                priv_dep = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate priv_dep;\n            pub fn use_priv(_: priv_dep::FromPriv) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check --message-format=short\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(str![[r#\"\n...\nsrc/lib.rs:3:13: [WARNING] type `FromPriv` from private dependency 'priv_dep' in public interface\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn exported_pub_dep() {\n    Package::new(\"pub_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPub;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"public-dependency\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                pub_dep = {version = \"0.1.0\", public = true}\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate pub_dep;\n            pub fn use_pub(_: pub_dep::FromPub) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check --message-format=short\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] pub_dep v0.1.0 (registry `dummy-registry`)\n[CHECKING] pub_dep v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\npub fn requires_nightly_cargo() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"public-dependency\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --message-format=short\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the cargo feature `public-dependency` requires a nightly version of Cargo, but this is the `stable` channel\n  See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels.\n  See https://doc.rust-lang.org/[..]cargo/reference/unstable.html#public-dependency for more information about using this feature.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn requires_feature() {\n    Package::new(\"pub_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                pub_dep = { version = \"0.1.0\", public = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check --message-format=short\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] ignoring `public` on dependency pub_dep, pass `-Zpublic-dependency` to enable support for it\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] pub_dep v0.1.0 (registry `dummy-registry`)\n[CHECKING] pub_dep v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn pub_dev_dependency() {\n    Package::new(\"pub_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPub;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"public-dependency\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dev-dependencies]\n                pub_dep = {version = \"0.1.0\", public = true}\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate pub_dep;\n            pub fn use_pub(_: pub_dep::FromPub) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check --message-format=short\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  'public' specifier can only be used on regular dependencies, not dev-dependencies\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn pub_dev_dependency_without_feature() {\n    Package::new(\"pub_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPub;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dev-dependencies]\n                pub_dep = {version = \"0.1.0\", public = true}\n            \"#,\n        )\n        .file(\n            \"tests/mod.rs\",\n            \"\n            extern crate pub_dep;\n            pub fn use_pub(_: pub_dep::FromPub) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check --message-format=short\")\n        .with_stderr_data(str![[r#\"\n[WARNING] 'public' specifier can only be used on regular dependencies, not dev-dependencies\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn workspace_pub_disallowed() {\n    Package::new(\"foo1\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromFoo;\")\n        .publish();\n    Package::new(\"foo2\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromFoo;\")\n        .publish();\n    Package::new(\"foo3\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromFoo;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"public-dependency\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [workspace.dependencies]\n                foo1 = \"0.1.0\"\n                foo2 = { version = \"0.1.0\", public = true }\n                foo3 = { version = \"0.1.0\", public = false }\n\n                [dependencies]\n                foo1 = { workspace = true, public = true }\n                foo2 = { workspace = true }\n                foo3 = { workspace = true, public = true }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n                #![deny(exported_private_dependencies)]\n                pub fn use_priv1(_: foo1::FromFoo) {}\n                pub fn use_priv2(_: foo2::FromFoo) {}\n                pub fn use_priv3(_: foo3::FromFoo) {}\n            \",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  foo2 is public, but workspace dependencies cannot be public\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn allow_priv_in_tests() {\n    Package::new(\"priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"public-dependency\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                priv_dep = {version = \"0.1.0\", public = false}\n            \"#,\n        )\n        .file(\n            \"tests/mod.rs\",\n            \"\n            extern crate priv_dep;\n            pub fn use_priv(_: priv_dep::FromPriv) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check --tests --message-format=short\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] priv_dep v0.1.0 (registry `dummy-registry`)\n[CHECKING] priv_dep v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn allow_priv_in_benches() {\n    Package::new(\"priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"public-dependency\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                priv_dep = {version = \"0.1.0\", public = false}\n            \"#,\n        )\n        .file(\n            \"benches/mod.rs\",\n            \"\n            extern crate priv_dep;\n            pub fn use_priv(_: priv_dep::FromPriv) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check --benches --message-format=short\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] priv_dep v0.1.0 (registry `dummy-registry`)\n[CHECKING] priv_dep v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn allow_priv_in_bins() {\n    Package::new(\"priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"public-dependency\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                priv_dep = {version = \"0.1.0\", public = false}\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n            extern crate priv_dep;\n            pub fn use_priv(_: priv_dep::FromPriv) {}\n            fn main() {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check --bins --message-format=short\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] priv_dep v0.1.0 (registry `dummy-registry`)\n[CHECKING] priv_dep v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn allow_priv_in_examples() {\n    Package::new(\"priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"public-dependency\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                priv_dep = {version = \"0.1.0\", public = false}\n            \"#,\n        )\n        .file(\n            \"examples/lib.rs\",\n            \"\n            extern crate priv_dep;\n            pub fn use_priv(_: priv_dep::FromPriv) {}\n            fn main() {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check --examples --message-format=short\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] priv_dep v0.1.0 (registry `dummy-registry`)\n[CHECKING] priv_dep v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn allow_priv_in_custom_build() {\n    Package::new(\"priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"public-dependency\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [build-dependencies]\n                priv_dep = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"build.rs\",\n            \"\n            extern crate priv_dep;\n            pub fn use_priv(_: priv_dep::FromPriv) {}\n            fn main() {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check --all-targets --message-format=short\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] priv_dep v0.1.0 (registry `dummy-registry`)\n[COMPILING] priv_dep v0.1.0\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn publish_package_with_public_dependency() {\n    Package::new(\"pub_bar\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPub;\")\n        .publish();\n    Package::new(\"bar\", \"0.1.0\")\n        .cargo_feature(\"public-dependency\")\n        .add_dep(Dependency::new(\"pub_bar\", \"0.1.0\").public(true))\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate pub_bar;\n            pub use pub_bar::FromPub as BarFromPub;\n        \",\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            cargo-features = [\"public-dependency\"]\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            [dependencies]\n            bar = {version = \"0.1.0\", public = true}\n        \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate bar;\n            pub fn use_pub(_: bar::BarFromPub) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check --message-format=short\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] pub_bar v0.1.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] pub_bar v0.1.0\n[CHECKING] bar v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn verify_mix_cargo_feature_z() {\n    Package::new(\"dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromDep;\")\n        .publish();\n    Package::new(\"priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n    Package::new(\"pub_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPub;\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"public-dependency\"]\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                dep = \"0.1.0\"\n                priv_dep = {version = \"0.1.0\", public = false}\n                pub_dep = {version = \"0.1.0\", public = true}\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate dep;\n            extern crate priv_dep;\n            extern crate pub_dep;\n            pub fn use_dep(_: dep::FromDep) {}\n            pub fn use_priv(_: priv_dep::FromPriv) {}\n            pub fn use_pub(_: pub_dep::FromPub) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check -Zpublic-dependency --message-format=short\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(str![[r#\"\n...\nsrc/lib.rs:5:13: [WARNING] type `FromDep` from private dependency 'dep' in public interface\nsrc/lib.rs:6:13: [WARNING] type `FromPriv` from private dependency 'priv_dep' in public interface\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn verify_z_public_dependency() {\n    Package::new(\"dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromDep;\")\n        .publish();\n    Package::new(\"priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n    Package::new(\"pub_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPub;\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                dep = \"0.1.0\"\n                priv_dep = {version = \"0.1.0\", public = false}\n                pub_dep = {version = \"0.1.0\", public = true}\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate dep;\n            extern crate priv_dep;\n            extern crate pub_dep;\n            pub fn use_dep(_: dep::FromDep) {}\n            pub fn use_priv(_: priv_dep::FromPriv) {}\n            pub fn use_pub(_: pub_dep::FromPub) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check -Zpublic-dependency --message-format=short\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(\n            str![[r#\"\n...\nsrc/lib.rs:5:13: [WARNING] type `FromDep` from private dependency 'dep' in public interface\nsrc/lib.rs:6:13: [WARNING] type `FromPriv` from private dependency 'priv_dep' in public interface\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn manifest_location() {\n    Package::new(\"dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromDep;\")\n        .publish();\n    Package::new(\"priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                dep = \"0.1.0\"\n                priv_dep = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate dep;\n            extern crate priv_dep;\n            pub fn use_dep(_: dep::FromDep) {}\n            pub use priv_dep::FromPriv;\n        \",\n        )\n        .build();\n\n    p.cargo(\"check -Zpublic-dependency\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(\n            str![[r#\"\n...\n[WARNING] struct `FromPriv` from private dependency 'priv_dep' is re-exported\n --> src/lib.rs:5:21\n  |\n5 |             pub use priv_dep::FromPriv;\n  |                     ^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `#[warn(exported_private_dependencies)]` on by default\n[NOTE] dependency `priv_dep` declared here\n --> Cargo.toml:9:17\n  |\n9 |                 priv_dep = \"0.1.0\"\n  |                 --------\n\n[WARNING] type `FromDep` from private dependency 'dep' in public interface\n --> src/lib.rs:4:13\n  |\n4 |             pub fn use_dep(_: dep::FromDep) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n[NOTE] dependency `dep` declared here\n --> Cargo.toml:8:17\n  |\n8 |                 dep = \"0.1.0\"\n  |                 ---\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn renamed_dependency() {\n    Package::new(\"dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromDep;\")\n        .publish();\n    Package::new(\"priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                dep = { version = \"0.1.0\", package = \"dep\" }\n                renamed_dep = {version = \"0.1.0\", package = \"priv_dep\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate dep;\n            extern crate renamed_dep;\n            pub fn use_dep(_: dep::FromDep) {}\n            pub fn use_priv(_: renamed_dep::FromPriv) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check -Zpublic-dependency\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(\n            str![[r#\"\n...\n[WARNING] type `FromDep` from private dependency 'dep' in public interface\n --> src/lib.rs:4:13\n  |\n4 |             pub fn use_dep(_: dep::FromDep) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `#[warn(exported_private_dependencies)]` on by default\n[NOTE] dependency `dep` declared here\n --> Cargo.toml:8:54\n  |\n8 |                 dep = { version = \"0.1.0\", package = \"dep\" }\n  |                                                      -----\n\n[WARNING] type `FromPriv` from private dependency 'priv_dep' in public interface\n --> src/lib.rs:5:13\n  |\n5 |             pub fn use_priv(_: renamed_dep::FromPriv) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n[NOTE] dependency `priv_dep` declared here\n --> Cargo.toml:9:61\n  |\n9 |                 renamed_dep = {version = \"0.1.0\", package = \"priv_dep\" }\n  |                                                             ----------\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n// We don't point to the toml locations if the crate is ambiguous.\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn duplicate_renamed_dependency() {\n    registry::alt_init();\n    Package::new(\"dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromDep;\")\n        .publish();\n    Package::new(\"dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .alternative(true)\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                dep = { version = \"0.1.0\", package = \"dep\" }\n                renamed_dep = {version = \"0.1.0\", package = \"dep\", registry = \"alternative\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate dep;\n            extern crate renamed_dep;\n            pub fn use_dep(_: dep::FromDep) {}\n            pub fn use_priv(_: renamed_dep::FromPriv) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check -Zpublic-dependency\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(\n            str![[r#\"\n...\n[WARNING] type `FromDep` from private dependency 'dep' in public interface\n --> src/lib.rs:4:13\n  |\n4 |             pub fn use_dep(_: dep::FromDep) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `#[warn(exported_private_dependencies)]` on by default\n\n[WARNING] type `FromPriv` from private dependency 'dep' in public interface\n --> src/lib.rs:5:13\n  |\n5 |             pub fn use_priv(_: renamed_dep::FromPriv) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn dependency_location_in_target_table() {\n    if crate::utils::cross_compile::disabled() {\n        return;\n    }\n\n    let native = cargo_test_support::cross_compile::native();\n    let alt = cargo_test_support::cross_compile::alternate();\n\n    Package::new(\"dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromDep;\")\n        .publish();\n    Package::new(\"native_priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n    Package::new(\"alt_priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [target.{native}.dependencies]\n                dep = {{ version = \"0.1.0\" }}\n                renamed_dep = {{ version = \"0.1.0\", package = \"native_priv_dep\" }}\n\n                [target.{alt}.dependencies]\n                dep = {{ version = \"0.1.0\" }}\n                renamed_dep = {{ version = \"0.1.0\", package = \"alt_priv_dep\" }}\n            \"#\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate dep;\n            extern crate renamed_dep;\n            pub fn use_dep(_: dep::FromDep) {}\n            pub fn use_priv(_: renamed_dep::FromPriv) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check -Zpublic-dependency\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(\n            str![[r#\"\n...\n[WARNING] type `FromDep` from private dependency 'dep' in public interface\n --> src/lib.rs:4:13\n  |\n4 |             pub fn use_dep(_: dep::FromDep) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `#[warn(exported_private_dependencies)]` on by default\n[NOTE] dependency `dep` declared here\n --> Cargo.toml:8:17\n  |\n8 |                 dep = { version = \"0.1.0\" }\n  |                 ---\n\n[WARNING] type `FromPriv` from private dependency 'native_priv_dep' in public interface\n --> src/lib.rs:5:13\n  |\n5 |             pub fn use_priv(_: renamed_dep::FromPriv) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n[NOTE] dependency `native_priv_dep` declared here\n --> Cargo.toml:9:62\n  |\n9 |                 renamed_dep = { version = \"0.1.0\", package = \"native_priv_dep\" }\n  |                                                              -----------------\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(&format!(\"check -Zpublic-dependency --target={alt}\"))\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(\n            str![[r#\"\n...\n[WARNING] type `FromDep` from private dependency 'dep' in public interface\n --> src/lib.rs:4:13\n  |\n4 |             pub fn use_dep(_: dep::FromDep) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `#[warn(exported_private_dependencies)]` on by default\n[NOTE] dependency `dep` declared here\n  --> Cargo.toml:12:17\n   |\n12 |                 dep = { version = \"0.1.0\" }\n   |                 ---\n\n[WARNING] type `FromPriv` from private dependency 'alt_priv_dep' in public interface\n --> src/lib.rs:5:13\n  |\n5 |             pub fn use_priv(_: renamed_dep::FromPriv) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n[NOTE] dependency `alt_priv_dep` declared here\n  --> Cargo.toml:13:62\n   |\n13 |                 renamed_dep = { version = \"0.1.0\", package = \"alt_priv_dep\" }\n   |                                                              --------------\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn dependency_location_in_target_table_with_cfg() {\n    if crate::utils::cross_compile::disabled() {\n        return;\n    }\n\n    let native_arch = cargo_test_support::cross_compile::native_arch();\n    let alt = cargo_test_support::cross_compile::alternate();\n\n    Package::new(\"dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromDep;\")\n        .publish();\n    Package::new(\"native_priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n    Package::new(\"alt_priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [target.'cfg(target_arch = \"{native_arch}\")'.dependencies]\n                dep = {{ version = \"0.1.0\" }}\n                renamed_dep = {{ version = \"0.1.0\", package = \"native_priv_dep\" }}\n\n                [target.'cfg(not(target_arch = \"{native_arch}\"))'.dependencies]\n                dep = {{ version = \"0.1.0\" }}\n                renamed_dep = {{ version = \"0.1.0\", package = \"alt_priv_dep\" }}\n            \"#\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate dep;\n            extern crate renamed_dep;\n            pub fn use_dep(_: dep::FromDep) {}\n            pub fn use_priv(_: renamed_dep::FromPriv) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"check -Zpublic-dependency\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(\n            str![[r#\"\n...\n[WARNING] type `FromDep` from private dependency 'dep' in public interface\n --> src/lib.rs:4:13\n  |\n4 |             pub fn use_dep(_: dep::FromDep) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `#[warn(exported_private_dependencies)]` on by default\n[NOTE] dependency `dep` declared here\n --> Cargo.toml:8:17\n  |\n8 |                 dep = { version = \"0.1.0\" }\n  |                 ---\n\n[WARNING] type `FromPriv` from private dependency 'native_priv_dep' in public interface\n --> src/lib.rs:5:13\n  |\n5 |             pub fn use_priv(_: renamed_dep::FromPriv) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n[NOTE] dependency `native_priv_dep` declared here\n --> Cargo.toml:9:62\n  |\n9 |                 renamed_dep = { version = \"0.1.0\", package = \"native_priv_dep\" }\n  |                                                              -----------------\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(&format!(\"check -Zpublic-dependency --target={alt}\"))\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(\n            str![[r#\"\n...\n[WARNING] type `FromDep` from private dependency 'dep' in public interface\n --> src/lib.rs:4:13\n  |\n4 |             pub fn use_dep(_: dep::FromDep) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `#[warn(exported_private_dependencies)]` on by default\n[NOTE] dependency `dep` declared here\n  --> Cargo.toml:12:17\n   |\n12 |                 dep = { version = \"0.1.0\" }\n   |                 ---\n\n[WARNING] type `FromPriv` from private dependency 'alt_priv_dep' in public interface\n --> src/lib.rs:5:13\n  |\n5 |             pub fn use_priv(_: renamed_dep::FromPriv) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n[NOTE] dependency `alt_priv_dep` declared here\n  --> Cargo.toml:13:62\n   |\n13 |                 renamed_dep = { version = \"0.1.0\", package = \"alt_priv_dep\" }\n   |                                                              --------------\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn dependency_location_in_workspace() {\n    Package::new(\"dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromDep;\")\n        .publish();\n    let (p, repo) = git::new_repo(\"foo\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"pkg\"]\n                [workspace.package]\n                edition = \"2015\"\n                [workspace.dependencies]\n                dep = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \"pkg/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pkg\"\n                edition.workspace = true\n                [dependencies]\n                dep.workspace = true\n            \"#,\n        )\n        .file(\n            \"pkg/src/lib.rs\",\n            \"\n            extern crate dep;\n            pub fn use_dep(_: dep::FromDep) {}\n        \",\n        )\n    });\n    git::commit(&repo);\n    p.cargo(&format!(\"check -Zpublic-dependency\"))\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] type `FromDep` from private dependency 'dep' in public interface\n --> pkg/src/lib.rs:3:13\n  |\n3 |             pub fn use_dep(_: dep::FromDep) {}\n  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `#[warn(exported_private_dependencies)]` on by default\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"exported_private_dependencies lint is unstable\")]\nfn relative_display_path() {\n    Package::new(\"priv_dep\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub struct FromPriv;\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                priv_dep = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \"foo/src/lib.rs\",\n            \"\n            extern crate priv_dep;\n            pub use priv_dep::FromPriv;\n        \",\n        )\n        .build();\n    p.cargo(\"check -Zpublic-dependency\")\n        .cwd(\"foo\")\n        .masquerade_as_nightly_cargo(&[\"public-dependency\"])\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] struct `FromPriv` from private dependency 'priv_dep' is re-exported\n --> foo/src/lib.rs:3:21\n  |\n3 |             pub use priv_dep::FromPriv;\n  |                     ^^^^^^^^^^^^^^^^^^\n  |\n  = [NOTE] `#[warn(exported_private_dependencies)]` on by default\n[NOTE] dependency `priv_dep` declared here\n --> foo/Cargo.toml:8:17\n  |\n8 |                 priv_dep = \"0.1.0\"\n  |                 --------\n...\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/publish.rs",
    "content": "//! Tests for the `cargo publish` command.\n\nuse std::fs;\nuse std::sync::{Arc, Mutex};\n\nuse crate::prelude::*;\nuse cargo_test_support::git::{self, repo};\nuse cargo_test_support::registry::{self, Package, RegistryBuilder, Response};\nuse cargo_test_support::{Project, paths};\nuse cargo_test_support::{basic_manifest, project, publish, str};\n\nconst CLEAN_FOO_JSON: &str = r#\"\n    {\n        \"authors\": [],\n        \"badges\": {},\n        \"categories\": [],\n        \"deps\": [],\n        \"description\": \"foo\",\n        \"documentation\": \"foo\",\n        \"features\": {},\n        \"homepage\": \"foo\",\n        \"keywords\": [],\n        \"license\": \"MIT\",\n        \"license_file\": null,\n        \"links\": null,\n        \"name\": \"foo\",\n        \"readme\": null,\n        \"readme_file\": null,\n        \"repository\": \"foo\",\n        \"rust_version\": null,\n        \"vers\": \"0.0.1\"\n    }\n\"#;\n\nfn validate_upload_foo() {\n    publish::validate_upload(\n        r#\"\n        {\n          \"authors\": [],\n          \"badges\": {},\n          \"categories\": [],\n          \"deps\": [],\n          \"description\": \"foo\",\n          \"documentation\": null,\n          \"features\": {},\n          \"homepage\": null,\n          \"keywords\": [],\n          \"license\": \"MIT\",\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"foo\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": null,\n          \"rust_version\": null,\n          \"vers\": \"0.0.1\"\n          }\n        \"#,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n    );\n}\n\nfn validate_upload_li() {\n    publish::validate_upload(\n        r#\"\n        {\n          \"authors\": [],\n          \"badges\": {},\n          \"categories\": [],\n          \"deps\": [],\n          \"description\": \"li\",\n          \"documentation\": null,\n          \"features\": {},\n          \"homepage\": null,\n          \"keywords\": [],\n          \"license\": \"MIT\",\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"li\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": null,\n          \"rust_version\": \"1.69\",\n          \"vers\": \"0.0.1\"\n          }\n        \"#,\n        \"li-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n    );\n}\n\n#[cargo_test]\nfn simple() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    validate_upload_foo();\n}\n\n#[cargo_test]\nfn duplicate_version() {\n    let registry_dupl = RegistryBuilder::new().http_api().http_index().build();\n    Package::new(\"foo\", \"0.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --dry-run\")\n        .replace_crates_io(registry_dupl.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] crate foo@0.0.1 already exists on crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] aborting upload due to dry run\n\n\"#]])\n        .run();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry_dupl.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] crate foo@0.0.1 already exists on crates.io index\n\n\"#]])\n        .run();\n}\n\n// Check that the `token` key works at the root instead of under a\n// `[registry]` table.\n#[cargo_test]\nfn simple_publish_with_http() {\n    let _reg = registry::RegistryBuilder::new()\n        .http_api()\n        .token(registry::Token::Plaintext(\"sekrit\".to_string()))\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --no-verify --token sekrit --registry dummy-registry\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `cargo publish --token` is deprecated in favor of using `cargo login` and environment variables\n[UPDATING] `dummy-registry` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `dummy-registry`\n[NOTE] waiting for foo v0.0.1 to be available at registry `dummy-registry`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `dummy-registry`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_publish_with_asymmetric() {\n    let _reg = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative_named(\"dummy-registry\")\n        .token(registry::Token::rfc_key())\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --no-verify -Zasymmetric-token --registry dummy-registry\")\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `dummy-registry`\n[NOTE] waiting for foo v0.0.1 to be available at registry `dummy-registry`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `dummy-registry`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn old_token_location() {\n    // `publish` generally requires a remote registry\n    let registry = registry::RegistryBuilder::new().http_api().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    let credentials = paths::home().join(\".cargo/credentials.toml\");\n    fs::remove_file(&credentials).unwrap();\n\n    // Verify can't publish without a token.\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] no token found, please run `cargo login`\nor use environment variable CARGO_REGISTRY_TOKEN\n\n\"#]])\n        .run();\n\n    fs::write(&credentials, format!(r#\"token = \"{}\"\"#, registry.token())).unwrap();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    // Skip `validate_upload_foo` as we just cared we got far enough for verify the token behavior.\n    // Other tests will verify the endpoint gets the right payload.\n}\n\n#[cargo_test]\nfn simple_with_index() {\n    // `publish` generally requires a remote registry\n    let registry = registry::RegistryBuilder::new().http_api().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .arg(\"--token\")\n        .arg(registry.token())\n        .arg(\"--index\")\n        .arg(registry.index_url().as_str())\n        .with_stderr_data(str![[r#\"\n[WARNING] `cargo publish --token` is deprecated in favor of using `cargo login` and environment variables\n[UPDATING] `[ROOT]/registry` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `[ROOT]/registry`\n[NOTE] waiting for foo v0.0.1 to be available at registry `[ROOT]/registry`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `[ROOT]/registry`\n\n\"#]])\n        .run();\n\n    // Skip `validate_upload_foo` as we just cared we got far enough for verify the VCS behavior.\n    // Other tests will verify the endpoint gets the right payload.\n}\n\n#[cargo_test]\nfn git_deps() {\n    // Use local registry for faster test times since no publish will occur\n    let registry = registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies.foo]\n                git = \"git://path/to/nowhere\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] failed to verify manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  all dependencies must have a version requirement specified when publishing.\n  dependency `foo` does not specify a version\n  Note: The published dependency will use the version from crates.io,\n  the `git` specification will be removed from the dependency declaration.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn path_dependency_no_version() {\n    // Use local registry for faster test times since no publish will occur\n    let registry = registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] failed to verify manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  all dependencies must have a version requirement specified when publishing.\n  dependency `bar` does not specify a version\n  Note: The published dependency will use the version from crates.io,\n  the `path` specification will be removed from the dependency declaration.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unpublishable_crate() {\n    // Use local registry for faster test times since no publish will occur\n    let registry = registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                publish = false\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --index\")\n        .arg(registry.index_url().as_str())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `foo` cannot be published.\n`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dont_publish_dirty() {\n    // Use local registry for faster test times since no publish will occur\n    let registry = registry::init();\n\n    let p = project().file(\"bar\", \"\").build();\n\n    let _ = git::repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] 1 files in the working directory contain changes that were not yet committed into git:\n\nbar\n\nto proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_clean() {\n    // `publish` generally requires a remote registry\n    let registry = registry::RegistryBuilder::new().http_api().build();\n\n    let p = project().build();\n\n    let _ = repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    // Skip `validate_upload_foo_clean` as we just cared we got far enough for verify the VCS behavior.\n    // Other tests will verify the endpoint gets the right payload.\n}\n\n#[cargo_test]\nfn publish_in_sub_repo() {\n    // `publish` generally requires a remote registry\n    let registry = registry::RegistryBuilder::new().http_api().build();\n\n    let p = project().no_manifest().file(\"baz\", \"\").build();\n\n    let _ = repo(&paths::root().join(\"foo\"))\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .cwd(\"bar\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo/bar)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/bar/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo/bar)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    // Skip `validate_upload_foo_clean` as we just cared we got far enough for verify the VCS behavior.\n    // Other tests will verify the endpoint gets the right payload.\n}\n\n#[cargo_test]\nfn publish_when_ignored() {\n    // `publish` generally requires a remote registry\n    let registry = registry::RegistryBuilder::new().http_api().build();\n\n    let p = project().file(\"baz\", \"\").build();\n\n    let _ = repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\".gitignore\", \"baz\")\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    // Skip `validate_upload` as we just cared we got far enough for verify the VCS behavior.\n    // Other tests will verify the endpoint gets the right payload.\n}\n\n#[cargo_test]\nfn ignore_when_crate_ignored() {\n    // `publish` generally requires a remote registry\n    let registry = registry::RegistryBuilder::new().http_api().build();\n\n    let p = project().no_manifest().file(\"bar/baz\", \"\").build();\n\n    let _ = repo(&paths::root().join(\"foo\"))\n        .file(\".gitignore\", \"bar\")\n        .nocommit_file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n            \"#,\n        )\n        .nocommit_file(\"bar/src/main.rs\", \"fn main() {}\");\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .cwd(\"bar\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo/bar)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/bar/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo/bar)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    // Skip `validate_upload` as we just cared we got far enough for verify the VCS behavior.\n    // Other tests will verify the endpoint gets the right payload.\n}\n\n#[cargo_test]\nfn new_crate_rejected() {\n    // Use local registry for faster test times since no publish will occur\n    let registry = registry::init();\n\n    let p = project().file(\"baz\", \"\").build();\n\n    let _ = repo(&paths::root().join(\"foo\"))\n        .nocommit_file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n            \"#,\n        )\n        .nocommit_file(\"src/main.rs\", \"fn main() {}\");\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] 3 files in the working directory contain changes that were not yet committed into git:\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dry_run() {\n    // Use local registry for faster test times since no publish will occur\n    let registry = registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --dry-run --index\")\n        .arg(registry.index_url().as_str())\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[ROOT]/registry` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] aborting upload due to dry run\n\n\"#]])\n        .run();\n\n    // Ensure the API request wasn't actually made\n    assert!(registry::api_path().join(\"api/v1/crates\").exists());\n    assert!(!registry::api_path().join(\"api/v1/crates/new\").exists());\n}\n\n#[cargo_test]\nfn registry_not_in_publish_list() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                publish = [\n                    \"test\"\n                ]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish\")\n        .arg(\"--registry\")\n        .arg(\"alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `foo` cannot be published.\nThe registry `alternative` is not listed in the `package.publish` value in Cargo.toml.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_empty_list() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                publish = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `foo` cannot be published.\n`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_allowed_registry() {\n    let _registry = RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n\n    let p = project().build();\n\n    let _ = repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n                publish = [\"alternative\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --registry alternative\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `alternative`\n[NOTE] waiting for foo v0.0.1 to be available at registry `alternative`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `alternative`\n\n\"#]])\n        .run();\n\n    publish::validate_alt_upload(\n        CLEAN_FOO_JSON,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/main.rs\",\n            \".cargo_vcs_info.json\",\n        ],\n    );\n}\n\n#[cargo_test]\nfn publish_implicitly_to_only_allowed_registry() {\n    let _registry = RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n\n    let p = project().build();\n\n    let _ = repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n                publish = [\"alternative\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish\")\n        .with_stderr_data(str![[r#\"\n[NOTE] found `alternative` as only allowed registry. Publishing to it automatically.\n[UPDATING] `alternative` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `alternative`\n[NOTE] waiting for foo v0.0.1 to be available at registry `alternative`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `alternative`\n\n\"#]])\n        .run();\n\n    publish::validate_alt_upload(\n        CLEAN_FOO_JSON,\n        \"foo-0.0.1.crate\",\n        &[\n            \"Cargo.lock\",\n            \"Cargo.toml\",\n            \"Cargo.toml.orig\",\n            \"src/main.rs\",\n            \".cargo_vcs_info.json\",\n        ],\n    );\n}\n\n#[cargo_test]\nfn publish_when_both_publish_and_index_specified() {\n    let registry = RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n\n    let p = project().build();\n\n    let _ = repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n                publish = [\"registry\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish\")\n        .arg(\"--index\")\n        .arg(registry.index_url().as_str())\n        .arg(\"--token\")\n        .arg(registry.token())\n        .with_stderr_data(str![[r#\"\n[WARNING] `cargo publish --token` is deprecated in favor of using `cargo login` and environment variables\n[WARNING] `--index` will ignore registries set by `package.publish` in Cargo.toml, and may cause unexpected push to prohibited registry\n[HELP] use `--registry` instead or set `publish = true` in Cargo.toml to suppress this warning\n[UPDATING] [..] index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry [..]\n[NOTE] waiting for foo v0.0.1 to be available at registry [..]\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry [..]\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_failed_with_index_and_only_allowed_registry() {\n    let registry = RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .alternative()\n        .build();\n\n    let p = project().build();\n\n    let _ = repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n                publish = [\"alternative\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish\")\n        .arg(\"--index\")\n        .arg(registry.index_url().as_str())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] command-line argument --index requires --token to be specified\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_fail_with_no_registry_specified() {\n    let p = project().build();\n\n    let _ = repo(&paths::root().join(\"foo\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n                publish = [\"alternative\", \"test\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] --registry is required to disambiguate between \"alternative\" or \"test\" registries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn block_publish_no_registry() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                publish = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `foo` cannot be published.\n`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish.\n\n\"#]])\n        .run();\n}\n\n// Explicitly setting `crates-io` in the publish list.\n#[cargo_test]\nfn publish_with_crates_io_explicit() {\n    // `publish` generally requires a remote registry\n    let registry = registry::RegistryBuilder::new().http_api().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                publish = [\"crates-io\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `foo` cannot be published.\nThe registry `alternative` is not listed in the `package.publish` value in Cargo.toml.\n\n\"#]])\n        .run();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_with_select_features() {\n    // `publish` generally requires a remote registry\n    let registry = registry::RegistryBuilder::new().http_api().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [features]\n                required = []\n                optional = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"#[cfg(not(feature = \\\"required\\\"))]\n             compile_error!(\\\"This crate requires `required` feature!\\\");\n             fn main() {}\",\n        )\n        .build();\n\n    p.cargo(\"publish --features required\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_with_all_features() {\n    // `publish` generally requires a remote registry\n    let registry = registry::RegistryBuilder::new().http_api().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [features]\n                required = []\n                optional = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"#[cfg(not(feature = \\\"required\\\"))]\n             compile_error!(\\\"This crate requires `required` feature!\\\");\n             fn main() {}\",\n        )\n        .build();\n\n    p.cargo(\"publish --all-features\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_with_no_default_features() {\n    // Use local registry for faster test times since no publish will occur\n    let registry = registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [features]\n                default = [\"required\"]\n                required = []\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"#[cfg(not(feature = \\\"required\\\"))]\n             compile_error!(\\\"This crate requires `required` feature!\\\");\n             fn main() {}\",\n        )\n        .build();\n\n    p.cargo(\"publish --no-default-features\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] This crate requires `required` feature!\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_with_patch() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n    Package::new(\"bar\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                [dependencies]\n                bar = \"1.0\"\n                [patch.crates-io]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"extern crate bar;\n             fn main() {\n                 bar::newfunc();\n             }\",\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"1.0.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn newfunc() {}\")\n        .build();\n\n    // Check that it works with the patched crate.\n    p.cargo(\"build\").run();\n\n    // Check that verify fails with patched crate which has new functionality.\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\nerror[E0425]: cannot find function `newfunc` in crate `bar`\n...\n\"#]])\n        .run();\n\n    // Remove the usage of new functionality and try again.\n    p.change_file(\"src/main.rs\", \"extern crate bar; pub fn main() {}\");\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    publish::validate_upload(\n        r#\"\n        {\n          \"authors\": [],\n          \"badges\": {},\n          \"categories\": [],\n          \"deps\": [\n            {\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"normal\",\n              \"name\": \"bar\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            }\n          ],\n          \"description\": \"foo\",\n          \"documentation\": null,\n          \"features\": {},\n          \"homepage\": null,\n          \"keywords\": [],\n          \"license\": \"MIT\",\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"foo\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": null,\n          \"rust_version\": null,\n          \"vers\": \"0.0.1\"\n          }\n        \"#,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n    );\n}\n\n#[cargo_test]\nfn publish_checks_for_token_before_verify() {\n    let registry = registry::RegistryBuilder::new()\n        .no_configure_token()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // Assert upload token error before the package is verified\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] no token found, please run `cargo login`\nor use environment variable CARGO_REGISTRY_TOKEN\n\n\"#]])\n        .with_stderr_does_not_contain(\"[VERIFYING] foo v0.0.1 ([CWD])\")\n        .run();\n\n    // Assert package verified successfully on dry run\n    p.cargo(\"publish --dry-run\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] aborting upload due to dry run\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_with_bad_source() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [source.crates-io]\n            replace-with = 'local-registry'\n\n            [source.local-registry]\n            local-registry = 'registry'\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] crates-io is replaced with non-remote-registry source registry `[ROOT]/foo/registry`;\ninclude `--registry crates-io` to use crates.io\n\n\"#]])\n        .run();\n\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n        [source.crates-io]\n        replace-with = \"vendored-sources\"\n\n        [source.vendored-sources]\n        directory = \"vendor\"\n        \"#,\n    );\n\n    p.cargo(\"publish\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] crates-io is replaced with non-remote-registry source dir [ROOT]/foo/vendor;\ninclude `--registry crates-io` to use crates.io\n\n\"#]])\n        .run();\n}\n\n// A dependency with both `git` and `version`.\n#[cargo_test]\nfn publish_git_with_version() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    Package::new(\"dep1\", \"1.0.1\")\n        .file(\"src/lib.rs\", \"pub fn f() -> i32 {1}\")\n        .publish();\n\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep1\", \"1.0.0\"))\n            .file(\"src/lib.rs\", \"pub fn f() -> i32 {2}\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                authors = []\n                edition = \"2018\"\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies]\n                dep1 = {{version = \"1.0\", git=\"{}\"}}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            pub fn main() {\n                println!(\"{}\", dep1::f());\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\n2\n\n\"#]])\n        .run();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.1.0 ([ROOT]/foo)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.1.0 ([ROOT]/foo)\n[UPLOADED] foo v0.1.0 to registry `crates-io`\n[NOTE] waiting for foo v0.1.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.1.0 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    publish::validate_upload_with_contents(\n        r#\"\n        {\n          \"authors\": [],\n          \"badges\": {},\n          \"categories\": [],\n          \"deps\": [\n            {\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"normal\",\n              \"name\": \"dep1\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            }\n          ],\n          \"description\": \"foo\",\n          \"documentation\": null,\n          \"features\": {},\n          \"homepage\": null,\n          \"keywords\": [],\n          \"license\": \"MIT\",\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"foo\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": null,\n          \"rust_version\": null,\n          \"vers\": \"0.1.0\"\n          }\n        \"#,\n        \"foo-0.1.0.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        [\n            (\n                \"Cargo.toml\",\n                // Check that only `version` is included in Cargo.toml.\n                str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2018\"\nname = \"foo\"\nversion = \"0.1.0\"\nauthors = []\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\nreadme = false\nlicense = \"MIT\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\n[dependencies.dep1]\nversion = \"1.0\"\n\n\"##]],\n            ),\n            (\n                \"Cargo.lock\",\n                // The important check here is that it is 1.0.1 in the registry.\n                str![[r##\"\n# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 4\n\n[[package]]\nname = \"dep1\"\nversion = \"1.0.1\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"[..]\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.1.0\"\ndependencies = [\n \"dep1\",\n]\n\n\"##]],\n            ),\n        ],\n    );\n}\n\n#[cargo_test]\nfn publish_dev_dep_stripping() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n    Package::new(\"normal-only\", \"1.0.0\")\n        .feature(\"cat\", &[])\n        .publish();\n    Package::new(\"optional-dep-feature\", \"1.0.0\")\n        .feature(\"cat\", &[])\n        .publish();\n    Package::new(\"optional-namespaced\", \"1.0.0\")\n        .feature(\"cat\", &[])\n        .publish();\n    Package::new(\"optional-renamed-dep-feature\", \"1.0.0\")\n        .feature(\"cat\", &[])\n        .publish();\n    Package::new(\"optional-renamed-namespaced\", \"1.0.0\")\n        .feature(\"cat\", &[])\n        .publish();\n    Package::new(\"build-only\", \"1.0.0\")\n        .feature(\"cat\", &[])\n        .publish();\n    Package::new(\"normal-and-dev\", \"1.0.0\")\n        .feature(\"cat\", &[])\n        .publish();\n    Package::new(\"target-normal-only\", \"1.0.0\")\n        .feature(\"cat\", &[])\n        .publish();\n    Package::new(\"target-build-only\", \"1.0.0\")\n        .feature(\"cat\", &[])\n        .publish();\n    Package::new(\"target-normal-and-dev\", \"1.0.0\")\n        .feature(\"cat\", &[])\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"foo\"\n            documentation = \"foo\"\n            homepage = \"foo\"\n            repository = \"foo\"\n\n\n            [features]\n            foo_feature = [\n                \"normal-only/cat\",\n                \"build-only/cat\",\n                \"dev-only/cat\",\n                \"renamed-dev-only01/cat\",\n                \"normal-and-dev/cat\",\n                \"target-normal-only/cat\",\n                \"target-build-only/cat\",\n                \"target-dev-only/cat\",\n                \"target-normal-and-dev/cat\",\n                \"optional-dep-feature/cat\",\n                \"dep:optional-namespaced\",\n                \"optional-renamed-dep-feature10/cat\",\n                \"dep:optional-renamed-namespaced10\",\n            ]\n\n            [dependencies]\n            normal-only = { version = \"1.0\", features = [\"cat\"] }\n            normal-and-dev = { version = \"1.0\", features = [\"cat\"] }\n            optional-dep-feature = { version = \"1.0\", features = [\"cat\"], optional = true }\n            optional-namespaced = { version = \"1.0\", features = [\"cat\"], optional = true }\n            optional-renamed-dep-feature10 = { version = \"1.0\", features = [\"cat\"], optional = true, package = \"optional-renamed-dep-feature\" }\n            optional-renamed-namespaced10 = { version = \"1.0\", features = [\"cat\"], optional = true, package = \"optional-renamed-namespaced\" }\n\n            [build-dependencies]\n            build-only = { version = \"1.0\", features = [\"cat\"] }\n\n            [dev-dependencies]\n            dev-only = { path = \"../dev-only\", features = [\"cat\"] }\n            renamed-dev-only01 = { path = \"../renamed-dev-only\", features = [\"cat\"], package = \"renamed-dev-only\" }\n            normal-and-dev = { version = \"1.0\", features = [\"cat\"] }\n\n            [target.'cfg(unix)'.dependencies]\n            target-normal-only = { version = \"1.0\", features = [\"cat\"] }\n            target-normal-and-dev = { version = \"1.0\", features = [\"cat\"] }\n\n            [target.'cfg(unix)'.build-dependencies]\n            target-build-only = { version = \"1.0\", features = [\"cat\"] }\n\n            [target.'cfg(unix)'.dev-dependencies]\n            target-dev-only = { path = \"../dev-only\", features = [\"cat\"] }\n            target-normal-and-dev = { version = \"1.0\", features = [\"cat\"] }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\n            \"dev-only/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dev-only\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n\n            [features]\n            cat = []\n            \"#,\n        )\n        .file(\n            \"dev-only/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"cat\")]\n                pub fn cat() {}\n            \"#,\n        )\n        .file(\n            \"renamed-dev-only/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"renamed-dev-only\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n\n            [features]\n            cat = []\n            \"#,\n        )\n        .file(\n            \"renamed-dev-only/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"cat\")]\n                pub fn cat() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .env(\"RUSTFLAGS\", \"--cfg unix\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] foo v0.1.0 ([ROOT]/foo)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.1.0 ([ROOT]/foo)\n[UPLOADED] foo v0.1.0 to registry `crates-io`\n[NOTE] waiting for foo v0.1.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.1.0 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    publish::validate_upload_with_contents(\n        r#\"\n        {\n          \"authors\": [],\n          \"badges\": {},\n          \"categories\": [],\n          \"deps\": [\n            {\n              \"default_features\": true,\n              \"features\": [\n                \"cat\"\n              ],\n              \"kind\": \"normal\",\n              \"name\": \"normal-and-dev\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [\n                \"cat\"\n              ],\n              \"kind\": \"normal\",\n              \"name\": \"normal-only\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [\n                \"cat\"\n              ],\n              \"kind\": \"normal\",\n              \"name\": \"optional-dep-feature\",\n              \"optional\": true,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [\n                \"cat\"\n              ],\n              \"kind\": \"normal\",\n              \"name\": \"optional-namespaced\",\n              \"optional\": true,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"default_features\": true,\n              \"explicit_name_in_toml\": \"optional-renamed-dep-feature10\",\n              \"features\": [\n                \"cat\"\n              ],\n              \"kind\": \"normal\",\n              \"name\": \"optional-renamed-dep-feature\",\n              \"optional\": true,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"default_features\": true,\n              \"explicit_name_in_toml\": \"optional-renamed-namespaced10\",\n              \"features\": [\n                \"cat\"\n              ],\n              \"kind\": \"normal\",\n              \"name\": \"optional-renamed-namespaced\",\n              \"optional\": true,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [\n                \"cat\"\n              ],\n              \"kind\": \"dev\",\n              \"name\": \"normal-and-dev\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [\n                \"cat\"\n              ],\n              \"kind\": \"build\",\n              \"name\": \"build-only\",\n              \"optional\": false,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [\n                \"cat\"\n              ],\n              \"kind\": \"normal\",\n              \"name\": \"target-normal-and-dev\",\n              \"optional\": false,\n              \"target\": \"cfg(unix)\",\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [\n                \"cat\"\n              ],\n              \"kind\": \"normal\",\n              \"name\": \"target-normal-only\",\n              \"optional\": false,\n              \"target\": \"cfg(unix)\",\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [\n                \"cat\"\n              ],\n              \"kind\": \"build\",\n              \"name\": \"target-build-only\",\n              \"optional\": false,\n              \"target\": \"cfg(unix)\",\n              \"version_req\": \"^1.0\"\n            },\n            {\n              \"default_features\": true,\n              \"features\": [\n                \"cat\"\n              ],\n              \"kind\": \"dev\",\n              \"name\": \"target-normal-and-dev\",\n              \"optional\": false,\n              \"target\": \"cfg(unix)\",\n              \"version_req\": \"^1.0\"\n            }\n          ],\n          \"description\": \"foo\",\n          \"documentation\": \"foo\",\n          \"features\": {\n            \"foo_feature\": [\n              \"normal-only/cat\",\n              \"build-only/cat\",\n              \"normal-and-dev/cat\",\n              \"target-normal-only/cat\",\n              \"target-build-only/cat\",\n              \"target-normal-and-dev/cat\",\n              \"optional-dep-feature/cat\",\n              \"dep:optional-namespaced\",\n              \"optional-renamed-dep-feature10/cat\",\n              \"dep:optional-renamed-namespaced10\"\n            ]\n          },\n          \"homepage\": \"foo\",\n          \"keywords\": [],\n          \"license\": \"MIT\",\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"foo\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": \"foo\",\n          \"rust_version\": null,\n          \"vers\": \"0.1.0\"\n        }\n        \"#,\n        \"foo-0.1.0.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.1.0\"\nauthors = []\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\nhomepage = \"foo\"\ndocumentation = \"foo\"\nreadme = false\nlicense = \"MIT\"\nrepository = \"foo\"\n\n[features]\nfoo_feature = [\n    \"normal-only/cat\",\n    \"build-only/cat\",\n    \"normal-and-dev/cat\",\n    \"target-normal-only/cat\",\n    \"target-build-only/cat\",\n    \"target-normal-and-dev/cat\",\n    \"optional-dep-feature/cat\",\n    \"dep:optional-namespaced\",\n    \"optional-renamed-dep-feature10/cat\",\n    \"dep:optional-renamed-namespaced10\",\n]\n\n[[bin]]\nname = \"foo\"\npath = \"src/main.rs\"\n\n[dependencies.normal-and-dev]\nversion = \"1.0\"\nfeatures = [\"cat\"]\n\n[dependencies.normal-only]\nversion = \"1.0\"\nfeatures = [\"cat\"]\n\n[dependencies.optional-dep-feature]\nversion = \"1.0\"\nfeatures = [\"cat\"]\noptional = true\n\n[dependencies.optional-namespaced]\nversion = \"1.0\"\nfeatures = [\"cat\"]\noptional = true\n\n[dependencies.optional-renamed-dep-feature10]\nversion = \"1.0\"\nfeatures = [\"cat\"]\noptional = true\npackage = \"optional-renamed-dep-feature\"\n\n[dependencies.optional-renamed-namespaced10]\nversion = \"1.0\"\nfeatures = [\"cat\"]\noptional = true\npackage = \"optional-renamed-namespaced\"\n\n[dev-dependencies.normal-and-dev]\nversion = \"1.0\"\nfeatures = [\"cat\"]\n\n[build-dependencies.build-only]\nversion = \"1.0\"\nfeatures = [\"cat\"]\n\n[target.\"cfg(unix)\".dependencies.target-normal-and-dev]\nversion = \"1.0\"\nfeatures = [\"cat\"]\n\n[target.\"cfg(unix)\".dependencies.target-normal-only]\nversion = \"1.0\"\nfeatures = [\"cat\"]\n\n[target.\"cfg(unix)\".build-dependencies.target-build-only]\nversion = \"1.0\"\nfeatures = [\"cat\"]\n\n[target.\"cfg(unix)\".dev-dependencies.target-normal-and-dev]\nversion = \"1.0\"\nfeatures = [\"cat\"]\n\n\"##]],\n        )],\n    );\n}\n\n#[cargo_test]\nfn credentials_ambiguous_filename() {\n    // `publish` generally requires a remote registry\n    let registry = registry::RegistryBuilder::new().http_api().build();\n\n    // Make token in `credentials.toml` incorrect to ensure it is not read.\n    let credentials_toml = paths::home().join(\".cargo/credentials.toml\");\n    fs::write(credentials_toml, r#\"token = \"wrong-token\"\"#).unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n  Unauthorized message from server.\n\n\"#]])\n        .run();\n\n    // Favor `credentials` if exists.\n    let credentials = paths::home().join(\".cargo/credentials\");\n    fs::write(credentials, r#\"token = \"sekrit\"\"#).unwrap();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] both `[ROOT]/home/.cargo/credentials` and `[ROOT]/home/.cargo/credentials.toml` exist. Using `[ROOT]/home/.cargo/credentials`\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n// --index will not load registry.token to avoid possibly leaking\n// crates.io token to another server.\n#[cargo_test]\nfn index_requires_token() {\n    // Use local registry for faster test times since no publish will occur\n    let registry = registry::init();\n\n    let credentials = paths::home().join(\".cargo/credentials.toml\");\n    fs::remove_file(&credentials).unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify --index\")\n        .arg(registry.index_url().as_str())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] command-line argument --index requires --token to be specified\n\n\"#]])\n        .run();\n}\n\n// publish with source replacement without --registry\n#[cargo_test]\nfn cratesio_source_replacement() {\n    registry::init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] crates-io is replaced with remote registry dummy-registry;\ninclude `--registry dummy-registry` or `--registry crates-io`\n\n\"#]])\n        .run();\n}\n\n// Registry returns an API error.\n#[cargo_test]\nfn api_error_json() {\n    let _registry = registry::RegistryBuilder::new()\n        .alternative()\n        .http_api()\n        .add_responder(\"/api/v1/crates/new\", |_, _| Response {\n            body: br#\"{\"errors\": [{\"detail\": \"you must be logged in\"}]}\"#.to_vec(),\n            code: 403,\n            headers: vec![],\n        })\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to publish foo v0.0.1 to registry at http://127.0.0.1:[..]/\n\nCaused by:\n  the remote server responded with an error (status 403 Forbidden): you must be logged in\n\n\"#]])\n        .run();\n}\n\n// Registry returns an API error with a 200 status code.\n#[cargo_test]\nfn api_error_200() {\n    let _registry = registry::RegistryBuilder::new()\n        .alternative()\n        .http_api()\n        .add_responder(\"/api/v1/crates/new\", |_, _| Response {\n            body: br#\"{\"errors\": [{\"detail\": \"max upload size is 123\"}]}\"#.to_vec(),\n            code: 200,\n            headers: vec![],\n        })\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to publish foo v0.0.1 to registry at http://127.0.0.1:[..]/\n\nCaused by:\n  the remote server responded with an [ERROR] max upload size is 123\n\n\"#]])\n        .run();\n}\n\n// Registry returns an error code without a JSON message.\n#[cargo_test]\nfn api_error_code() {\n    let _registry = registry::RegistryBuilder::new()\n        .alternative()\n        .http_api()\n        .add_responder(\"/api/v1/crates/new\", |_, _| Response {\n            body: br#\"go away\"#.to_vec(),\n            code: 400,\n            headers: vec![],\n        })\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to publish foo v0.0.1 to registry at http://127.0.0.1:[..]/\n\nCaused by:\n  failed to get a 200 OK response, got 400\n  headers:\n  \tHTTP/1.1 400\n  \tContent-Length: 7\n  \tConnection: close\n  \t\n  body:\n  go away\n\n\"#]])\n        .run();\n}\n\n// Registry has a network error.\n#[cargo_test]\nfn api_curl_error() {\n    let _registry = registry::RegistryBuilder::new()\n        .alternative()\n        .http_api()\n        .add_responder(\"/api/v1/crates/new\", |_, _| {\n            panic!(\"broke\");\n        })\n        .build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // This doesn't check for the exact text of the error in the remote\n    // possibility that cargo is linked with a weird version of libcurl, or\n    // curl changes the text of the message. Currently the message 52\n    // (CURLE_GOT_NOTHING) is:\n    //    Server returned nothing (no headers, no data) (Empty reply from server)\n    p.cargo(\"publish --no-verify --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to publish foo v0.0.1 to registry at http://127.0.0.1:[..]/\n\nCaused by:\n  [52] Server returned nothing (no headers, no data) (Empty reply from server)\n\n\"#]])\n        .run();\n}\n\n// Registry returns an invalid response.\n#[cargo_test]\nfn api_other_error() {\n    let _registry = registry::RegistryBuilder::new()\n        .alternative()\n        .http_api()\n        .add_responder(\"/api/v1/crates/new\", |_, _| Response {\n            body: b\"\\xff\".to_vec(),\n            code: 200,\n            headers: vec![],\n        })\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n                homepage = \"foo\"\n                repository = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify --registry alternative\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to publish foo v0.0.1 to registry at http://127.0.0.1:[..]/\n\nCaused by:\n  invalid response body from server\n\nCaused by:\n  invalid utf-8 sequence of 1 bytes from index 0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn in_package_workspace() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n                [workspace]\n                members = [\"li\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"li/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"li\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                rust-version = \"1.69\"\n                description = \"li\"\n                license = \"MIT\"\n            \"#,\n        )\n        .file(\"li/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish -p li --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] li v0.0.1 ([ROOT]/foo/li)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] li v0.0.1 ([ROOT]/foo/li)\n[UPLOADED] li v0.0.1 to registry `crates-io`\n[NOTE] waiting for li v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] li v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    validate_upload_li();\n}\n\n#[cargo_test]\nfn with_duplicate_spec_in_members() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [workspace]\n                resolver = \"2\"\n                members = [\"li\",\"bar\"]\n                default-members = [\"li\",\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"li/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"li\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                description = \"li\"\n                license = \"MIT\"\n            \"#,\n        )\n        .file(\"li/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                description = \"bar\"\n                license = \"MIT\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] bar v0.0.1 ([ROOT]/foo/bar)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] li v0.0.1 ([ROOT]/foo/li)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] bar v0.0.1 ([ROOT]/foo/bar)\n[UPLOADED] bar v0.0.1 to registry `crates-io`\n[UPLOADING] li v0.0.1 ([ROOT]/foo/li)\n[UPLOADED] li v0.0.1 to registry `crates-io`\n[NOTE] waiting for bar v0.0.1 or li v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crates should be available shortly\n[PUBLISHED] bar v0.0.1 and li v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn in_package_workspace_with_members_with_features_old() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                [workspace]\n                members = [\"li\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"li/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"li\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                rust-version = \"1.69\"\n                description = \"li\"\n                license = \"MIT\"\n            \"#,\n        )\n        .file(\"li/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish -p li --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] li v0.0.1 ([ROOT]/foo/li)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] li v0.0.1 ([ROOT]/foo/li)\n[UPLOADED] li v0.0.1 to registry `crates-io`\n[NOTE] waiting for li v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] li v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    validate_upload_li();\n}\n\n#[cargo_test]\nfn in_virtual_workspace() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"foo/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn in_virtual_workspace_with_p() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\",\"li\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"foo/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"li/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"li\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                rust-version = \"1.69\"\n                description = \"li\"\n                license = \"MIT\"\n            \"#,\n        )\n        .file(\"li/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish -p li --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] li v0.0.1 ([ROOT]/foo/li)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] li v0.0.1 ([ROOT]/foo/li)\n[UPLOADED] li v0.0.1 to registry `crates-io`\n[NOTE] waiting for li v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] li v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn in_package_workspace_not_found() {\n    // Use local registry for faster test times since no publish will occur\n    let registry = registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"li/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"li\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                authors = []\n                license = \"MIT\"\n                description = \"li\"\n            \"#,\n        )\n        .file(\"li/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish -p li --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `li` did not match any packages\n\n[HELP] a package with a similar name exists: `foo`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn in_package_workspace_found_multiple() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n                [workspace]\n                members = [\"li\",\"lii\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"li/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"li\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                authors = []\n                license = \"MIT\"\n                description = \"li\"\n            \"#,\n        )\n        .file(\"li/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"lii/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"lii\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                authors = []\n                license = \"MIT\"\n                description = \"lii\"\n            \"#,\n        )\n        .file(\"lii/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish -p li* --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] li v0.0.1 ([ROOT]/foo/li)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] lii v0.0.1 ([ROOT]/foo/lii)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] li v0.0.1 ([ROOT]/foo/li)\n[UPLOADED] li v0.0.1 to registry `crates-io`\n[UPLOADING] lii v0.0.1 ([ROOT]/foo/lii)\n[UPLOADED] lii v0.0.1 to registry `crates-io`\n[NOTE] waiting for li v0.0.1 or lii v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crates should be available shortly\n[PUBLISHED] li v0.0.1 and lii v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_path_dependency_without_workspace() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                authors = []\n                license = \"MIT\"\n                description = \"bar\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish -p bar --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification `bar` did not match any packages\n\n[HELP] a package with a similar name exists: `foo`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn http_api_not_noop() {\n    let registry = registry::RegistryBuilder::new().http_api().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [project]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies]\n                foo = \"0.0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn wait_for_first_publish() {\n    // Counter for number of tries before the package is \"published\"\n    let arc: Arc<Mutex<u32>> = Arc::new(Mutex::new(0));\n    let arc2 = arc.clone();\n\n    // Registry returns an invalid response.\n    let registry = registry::RegistryBuilder::new()\n        .http_index()\n        .http_api()\n        .add_responder(\"/index/de/la/delay\", move |req, server| {\n            let mut lock = arc.lock().unwrap();\n            *lock += 1;\n            if *lock <= 1 {\n                server.not_found(req)\n            } else {\n                server.index(req)\n            }\n        })\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"delay\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_status(0)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] delay v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] delay v0.0.1 ([ROOT]/foo)\n[UPLOADED] delay v0.0.1 to registry `crates-io`\n[NOTE] waiting for delay v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] delay v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    // Verify the responder has been pinged\n    let lock = arc2.lock().unwrap();\n    assert_eq!(*lock, 2);\n    drop(lock);\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                delay = \"0.0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\").with_status(0).run();\n}\n\n/// A separate test is needed for package names with - or _ as they hit\n/// the responder twice per cargo invocation. If that ever gets changed\n/// this test will need to be changed accordingly.\n#[cargo_test]\nfn wait_for_first_publish_underscore() {\n    // Counter for number of tries before the package is \"published\"\n    let arc: Arc<Mutex<u32>> = Arc::new(Mutex::new(0));\n    let arc2 = arc.clone();\n    let misses = Arc::new(Mutex::new(Vec::new()));\n    let misses2 = misses.clone();\n\n    // Registry returns an invalid response.\n    let registry = registry::RegistryBuilder::new()\n        .http_index()\n        .http_api()\n        .add_responder(\"/index/de/la/delay_with_underscore\", move |req, server| {\n            let mut lock = arc.lock().unwrap();\n            *lock += 1;\n            if *lock <= 1 {\n                server.not_found(req)\n            } else {\n                server.index(req)\n            }\n        })\n        .not_found_handler(move |req, _| {\n            misses.lock().unwrap().push(req.url.to_string());\n            Response {\n                body: b\"not found\".to_vec(),\n                code: 404,\n                headers: vec![],\n            }\n        })\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"delay_with_underscore\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_status(0)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] delay_with_underscore v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] delay_with_underscore v0.0.1 ([ROOT]/foo)\n[UPLOADED] delay_with_underscore v0.0.1 to registry `crates-io`\n[NOTE] waiting for delay_with_underscore v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] delay_with_underscore v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    // Verify the repsponder has been pinged\n    let lock = arc2.lock().unwrap();\n    assert_eq!(*lock, 2);\n    drop(lock);\n    {\n        let misses = misses2.lock().unwrap();\n        assert!(\n            misses.len() == 1,\n            \"should only have 1 not found URL; instead found {misses:?}\"\n        );\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                delay_with_underscore = \"0.0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\").with_status(0).run();\n}\n\n#[cargo_test]\nfn wait_for_subsequent_publish() {\n    // Counter for number of tries before the package is \"published\"\n    let arc: Arc<Mutex<u32>> = Arc::new(Mutex::new(0));\n    let arc2 = arc.clone();\n    let publish_req = Arc::new(Mutex::new(None));\n    let publish_req2 = publish_req.clone();\n\n    let registry = registry::RegistryBuilder::new()\n        .http_index()\n        .http_api()\n        .add_responder(\"/api/v1/crates/new\", move |req, server| {\n            // Capture the publish request, but defer publishing\n            *publish_req.lock().unwrap() = Some(req.clone());\n            server.ok(req)\n        })\n        .add_responder(\"/index/de/la/delay\", move |req, server| {\n            let mut lock = arc.lock().unwrap();\n            *lock += 1;\n            if *lock == 3 {\n                // Run the publish on the 3rd attempt\n                let rep = server\n                    .check_authorized_publish(&publish_req2.lock().unwrap().as_ref().unwrap());\n                assert_eq!(rep.code, 200);\n            }\n            server.index(req)\n        })\n        .build();\n\n    // Publish an earlier version\n    Package::new(\"delay\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"delay\"\n                version = \"0.0.2\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_status(0)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] delay v0.0.2 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] delay v0.0.2 ([ROOT]/foo)\n[UPLOADED] delay v0.0.2 to registry `crates-io`\n[NOTE] waiting for delay v0.0.2 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] delay v0.0.2 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    // Verify the responder has been pinged\n    let lock = arc2.lock().unwrap();\n    assert_eq!(*lock, 3);\n    drop(lock);\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                delay = \"0.0.2\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").with_status(0).run();\n}\n\n#[cargo_test]\nfn skip_wait_for_publish() {\n    // Intentionally using local registry so the crate never makes it to the index\n    let registry = registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            \"\n                [publish]\n                timeout = 0\n                \",\n        )\n        .build();\n\n    p.cargo(\"publish --no-verify -Zpublish-timeout\")\n        .replace_crates_io(registry.index_url())\n        .masquerade_as_nightly_cargo(&[\"publish-timeout\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn timeout_waiting_for_publish() {\n    // Publish doesn't happen within the timeout window.\n    let registry = registry::RegistryBuilder::new()\n        .http_api()\n        .delayed_index_update(20)\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"delay\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [publish]\n                timeout = 2\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"publish --no-verify -Zpublish-timeout\")\n        .replace_crates_io(registry.index_url())\n        .masquerade_as_nightly_cargo(&[\"publish-timeout\"])\n        .with_status(0)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] delay v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] delay v0.0.1 ([ROOT]/foo)\n[UPLOADED] delay v0.0.1 to registry `crates-io`\n[NOTE] waiting for delay v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[WARNING] timed out waiting for delay v0.0.1 to be available in registry `crates-io`\n  |\n  = [NOTE] the registry may have a backlog that is delaying making the crate available. The crate should be available soon.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn timeout_waiting_for_dependency_publish() {\n    // Publish doesn't happen within the timeout window.\n    let registry = registry::RegistryBuilder::new()\n        .http_api()\n        .delayed_index_update(20)\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"main\", \"other\", \"dep\"]\n        \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"main\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies]\n                dep = { version = \"0.0.1\", path = \"../dep\" }\n            \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"other/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"other\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies]\n                dep = { version = \"0.0.1\", path = \"../dep\" }\n            \"#,\n        )\n        .file(\"other/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [publish]\n                timeout = 2\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"publish --no-verify -Zpublish-timeout\")\n        .replace_crates_io(registry.index_url())\n        .masquerade_as_nightly_cargo(&[\"publish-timeout\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] dep v0.0.1 ([ROOT]/foo/dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] other v0.0.1 ([ROOT]/foo/other)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] dep v0.0.1 ([ROOT]/foo/dep)\n[UPLOADED] dep v0.0.1 to registry `crates-io`\n[NOTE] waiting for dep v0.0.1 to be available at registry `crates-io`.\n      2 remaining crates to be published\n[WARNING] timed out waiting for dep v0.0.1 to be available in registry `crates-io`\n  |\n  = [NOTE] the registry may have a backlog that is delaying making the crate available. The crate should be available soon.\n[ERROR] unable to publish main v0.0.1 and other v0.0.1 due to a timeout while waiting for published dependencies to be available.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn package_selection() {\n    let registry = registry::RegistryBuilder::new().http_api().build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"#[test] fn a() {}\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.1.0\"))\n        .file(\"b/src/lib.rs\", \"#[test] fn b() {}\")\n        .build();\n\n    p.cargo(\"publish --no-verify --dry-run --workspace\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] a v0.1.0 ([ROOT]/foo/a)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] b v0.1.0 ([ROOT]/foo/b)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] a v0.1.0 ([ROOT]/foo/a)\n[WARNING] aborting upload due to dry run\n[UPLOADING] b v0.1.0 ([ROOT]/foo/b)\n[WARNING] aborting upload due to dry run\n\n\"#]])\n        .with_stdout_data(str![[r#\"\"#]])\n        .run();\n\n    p.cargo(\"publish --no-verify --dry-run --package a --package b\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] a v0.1.0 ([ROOT]/foo/a)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] b v0.1.0 ([ROOT]/foo/b)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] a v0.1.0 ([ROOT]/foo/a)\n[WARNING] aborting upload due to dry run\n[UPLOADING] b v0.1.0 ([ROOT]/foo/b)\n[WARNING] aborting upload due to dry run\n\n\"#]])\n        .with_stdout_data(str![[r#\"\"#]])\n        .run();\n\n    p.cargo(\"publish --no-verify --dry-run --workspace --exclude b\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] a v0.1.0 ([ROOT]/foo/a)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] a v0.1.0 ([ROOT]/foo/a)\n[WARNING] aborting upload due to dry run\n\n\"#]])\n        .with_stdout_data(str![[r#\"\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn wait_for_git_publish() {\n    // Slow publish to an index with a git index.\n    let registry = registry::RegistryBuilder::new()\n        .http_api()\n        .delayed_index_update(5)\n        .build();\n\n    // Publish an earlier version\n    Package::new(\"delay\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"delay\"\n                version = \"0.0.2\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_status(0)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] delay v0.0.2 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] delay v0.0.2 ([ROOT]/foo)\n[UPLOADED] delay v0.0.2 to registry `crates-io`\n[NOTE] waiting for delay v0.0.2 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] delay v0.0.2 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [dependencies]\n                delay = \"0.0.2\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").with_status(0).run();\n}\n\n#[cargo_test]\nfn invalid_token() {\n    // Checks publish behavior with an invalid token.\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .env(\"CARGO_REGISTRY_TOKEN\", \"\\x16\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to publish foo v0.0.1 to registry at http://127.0.0.1:[..]/\n\nCaused by:\n  token contains invalid characters.\n  Only printable ISO-8859-1 characters are allowed as it is sent in a HTTPS header.\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn versionless_package() {\n    // Use local registry for faster test times since no publish will occur\n    let registry = registry::init();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `foo` cannot be published.\n`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish.\n\n\"#]])\n        .run();\n}\n\n// A workspace with three projects that depend on one another (level1 -> level2 -> level3).\n// level1 is a binary package, to test lockfile generation.\nfn workspace_with_local_deps_project() -> Project {\n    project()\n            .file(\n                \"Cargo.toml\",\n                r#\"\n            [workspace]\n            members = [\"level1\", \"level2\", \"level3\"]\n\n            [workspace.dependencies]\n            level2 = { path = \"level2\", version = \"0.0.1\" }\n        \"#\n            )\n            .file(\n                \"level1/Cargo.toml\",\n                r#\"\n            [package]\n            name = \"level1\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level1\"\n            repository = \"bar\"\n\n            [dependencies]\n            # Let one dependency also specify features, for the added test coverage when generating package files.\n            level2 = { workspace = true, features = [\"foo\"] }\n        \"#,\n            )\n            .file(\"level1/src/main.rs\", \"fn main() {}\")\n            .file(\n                \"level2/Cargo.toml\",\n                r#\"\n            [package]\n            name = \"level2\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level2\"\n            repository = \"bar\"\n\n            [features]\n            foo = []\n\n            [dependencies]\n            level3 = { path = \"../level3\", version = \"0.0.1\" }\n        \"#\n            )\n            .file(\"level2/src/lib.rs\", \"\")\n            .file(\n                \"level3/Cargo.toml\",\n                r#\"\n            [package]\n            name = \"level3\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"level3\"\n            repository = \"bar\"\n        \"#,\n            )\n            .file(\"level3/src/lib.rs\", \"\")\n            .build()\n}\n\n#[cargo_test]\nfn workspace_with_local_deps() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n    let p = workspace_with_local_deps_project();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] level3 v0.0.1 ([ROOT]/foo/level3)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] level2 v0.0.1 ([ROOT]/foo/level2)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] level3 v0.0.1 ([ROOT]/foo/level3)\n[COMPILING] level3 v0.0.1 ([ROOT]/foo/target/package/level3-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] level2 v0.0.1 ([ROOT]/foo/level2)\n[UPDATING] crates.io index\n[UNPACKING] level3 v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] level3 v0.0.1\n[COMPILING] level2 v0.0.1 ([ROOT]/foo/target/package/level2-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] level1 v0.0.1 ([ROOT]/foo/level1)\n[UPDATING] crates.io index\n[UNPACKING] level2 v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] level2 v0.0.1\n[COMPILING] level1 v0.0.1 ([ROOT]/foo/target/package/level1-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] level3 v0.0.1 ([ROOT]/foo/level3)\n[UPLOADED] level3 v0.0.1 to registry `crates-io`\n[NOTE] waiting for level3 v0.0.1 to be available at registry `crates-io`.\n      2 remaining crates to be published\n[PUBLISHED] level3 v0.0.1 at registry `crates-io`\n[UPLOADING] level2 v0.0.1 ([ROOT]/foo/level2)\n[UPLOADED] level2 v0.0.1 to registry `crates-io`\n[NOTE] waiting for level2 v0.0.1 to be available at registry `crates-io`.\n      1 remaining crate to be published\n[PUBLISHED] level2 v0.0.1 at registry `crates-io`\n[UPLOADING] level1 v0.0.1 ([ROOT]/foo/level1)\n[UPLOADED] level1 v0.0.1 to registry `crates-io`\n[NOTE] waiting for level1 v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] level1 v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_parallel() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\", \"c\"]\n        \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"a\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"b\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"c/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"c\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"c\"\n            repository = \"bar\"\n\n            [dependencies]\n            a = { path = \"../a\", version = \"0.0.1\" }\n            b = { path = \"../b\", version = \"0.0.1\" }\n        \"#,\n        )\n        .file(\"c/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] a v0.0.1 ([ROOT]/foo/a)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] b v0.0.1 ([ROOT]/foo/b)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] c v0.0.1 ([ROOT]/foo/c)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] a v0.0.1 ([ROOT]/foo/a)\n[COMPILING] a v0.0.1 ([ROOT]/foo/target/package/a-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] b v0.0.1 ([ROOT]/foo/b)\n[COMPILING] b v0.0.1 ([ROOT]/foo/target/package/b-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] c v0.0.1 ([ROOT]/foo/c)\n[UPDATING] crates.io index\n[UNPACKING] a v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[UNPACKING] b v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] a v0.0.1\n[COMPILING] b v0.0.1\n[COMPILING] c v0.0.1 ([ROOT]/foo/target/package/c-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADED] b v0.0.1 to registry `crates-io`\n[UPLOADED] a v0.0.1 to registry `crates-io`\n[NOTE] waiting for a v0.0.1 or b v0.0.1 to be available at registry `crates-io`.\n      1 remaining crate to be published\n[PUBLISHED] a v0.0.1 and b v0.0.1 at registry `crates-io`\n[UPLOADING] c v0.0.1 ([ROOT]/foo/c)\n[UPLOADED] c v0.0.1 to registry `crates-io`\n[NOTE] waiting for c v0.0.1 to be available at registry `crates-io`\n[PUBLISHED] c v0.0.1 at registry `crates-io`\n[UPLOADING] a v0.0.1 ([ROOT]/foo/a)\n[UPLOADING] b v0.0.1 ([ROOT]/foo/b)\n[UPDATING] crates.io index\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn workspace_missing_dependency() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n        \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"a\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"b\"\n            repository = \"bar\"\n\n            [dependencies]\n            a = { path = \"../a\", version = \"0.0.1\" }\n        \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish -p b\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] b v0.0.1 ([ROOT]/foo/b)\n[UPDATING] crates.io index\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  no matching package named `a` found\n  location searched: crates.io index\n  required by package `b v0.0.1 ([ROOT]/foo/b)`\n\n\"#]])\n        .run();\n\n    p.cargo(\"publish -p a\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] a v0.0.1 ([ROOT]/foo/a)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] a v0.0.1 ([ROOT]/foo/a)\n[COMPILING] a v0.0.1 ([ROOT]/foo/target/package/a-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] a v0.0.1 ([ROOT]/foo/a)\n[UPLOADED] a v0.0.1 to registry `crates-io`\n[NOTE] waiting for a v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] a v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    // Publishing the whole workspace now will fail, as `a` is already published.\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] crate a@0.0.1 already exists on crates.io index\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn one_unpublishable_package() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"dep\", \"main\"]\n            \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n            publish = false\n\n            [dependencies]\n            dep = { path = \"../dep\", version = \"0.1.0\" }\n        \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"dep\"\n            repository = \"bar\"\n        \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep)\n[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] dep v0.1.0 ([ROOT]/foo/dep)\n[UPLOADED] dep v0.1.0 to registry `crates-io`\n[NOTE] waiting for dep v0.1.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] dep v0.1.0 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn virtual_ws_with_multiple_unpublishable_package() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"dep\", \"main\", \"publishable\"]\n            \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n            publish = false\n\n            [dependencies]\n            dep = { path = \"../dep\", version = \"0.1.0\" }\n        \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            license = \"MIT\"\n            description = \"dep\"\n            repository = \"bar\"\n            publish = false\n        \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .file(\n            \"publishable/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"publishable\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            repository = \"foo\"\n        \"#,\n        )\n        .file(\"publishable/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] publishable v0.1.0 ([ROOT]/foo/publishable)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] publishable v0.1.0 ([ROOT]/foo/publishable)\n[COMPILING] publishable v0.1.0 ([ROOT]/foo/target/package/publishable-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] publishable v0.1.0 ([ROOT]/foo/publishable)\n[UPLOADED] publishable v0.1.0 to registry `crates-io`\n[NOTE] waiting for publishable v0.1.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] publishable v0.1.0 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_flag_with_unpublishable_packages() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"publishable\", \"non-publishable\"]\n\n            [package]\n            name = \"cwd\"\n            version = \"0.0.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            repository = \"foo\"\n            publish = false\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"publishable/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"publishable\"\n            version = \"0.0.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            repository = \"foo\"\n            publish = true\n        \"#,\n        )\n        .file(\"publishable/src/lib.rs\", \"\")\n        .file(\n            \"non-publishable/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"non-publishable\"\n            version = \"0.0.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            repository = \"foo\"\n            publish = false\n        \"#,\n        )\n        .file(\"non-publishable/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --workspace\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] publishable v0.0.0 ([ROOT]/foo/publishable)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] publishable v0.0.0 ([ROOT]/foo/publishable)\n[COMPILING] publishable v0.0.0 ([ROOT]/foo/target/package/publishable-0.0.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] publishable v0.0.0 ([ROOT]/foo/publishable)\n[UPLOADED] publishable v0.0.0 to registry `crates-io`\n[NOTE] waiting for publishable v0.0.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] publishable v0.0.0 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unpublishable_package_as_versioned_dev_dep() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"dep\", \"main\"]\n            \"#,\n        )\n        .file(\n            \"main/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"main\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"main\"\n            repository = \"bar\"\n\n            [dev-dependencies]\n            dep = { path = \"../dep\", version = \"0.1.0\" }\n        \"#,\n        )\n        .file(\"main/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"dep\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"dep\"\n            repository = \"bar\"\n            publish = false\n        \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    // It is expected to find the versioned dev dep not being published,\n    // regardless with `--dry-run` or `--no-verify`.\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] crates.io index\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  no matching package named `dep` found\n  location searched: crates.io index\n  required by package `main v0.0.1 ([ROOT]/foo/main)`\n\n\"#]])\n        .run();\n\n    p.cargo(\"publish --dry-run\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] crates.io index\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  no matching package named `dep` found\n  location searched: crates.io index\n  required by package `main v0.0.1 ([ROOT]/foo/main)`\n\n\"#]])\n        .run();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] main v0.0.1 ([ROOT]/foo/main)\n[UPDATING] crates.io index\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  no matching package named `dep` found\n  location searched: crates.io index\n  required by package `main v0.0.1 ([ROOT]/foo/main)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn all_unpublishable_packages() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"non-publishable1\", \"non-publishable2\"]\n            \"#,\n        )\n        .file(\n            \"non-publishable1/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"non-publishable1\"\n            version = \"0.0.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            repository = \"foo\"\n            publish = false\n        \"#,\n        )\n        .file(\"non-publishable1/src/lib.rs\", \"\")\n        .file(\n            \"non-publishable2/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"non-publishable2\"\n            version = \"0.0.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            repository = \"foo\"\n            publish = false\n        \"#,\n        )\n        .file(\"non-publishable2/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --workspace\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[WARNING] nothing to publish, but found 2 unpublishable packages\n  |\n  = [HELP] to publish packages, set `package.publish` to `true` or a non-empty list\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn checksum_changed() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    Package::new(\"dep\", \"1.0.0\").publish();\n    Package::new(\"transitive\", \"1.0.0\")\n        .dep(\"dep\", \"1.0.0\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"dep\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                documentation = \"foo\"\n\n                [dependencies]\n                dep = { path = \"./dep\", version = \"1.0.0\" }\n                transitive = \"1.0.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"dep/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"dep\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"dep/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    p.cargo(\"publish --dry-run --workspace\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] crate dep@1.0.0 already exists on crates.io index\n[WARNING] manifest has no description, license, license-file, documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] dep v1.0.0 ([ROOT]/foo/dep)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] dep v1.0.0 ([ROOT]/foo/dep)\n[COMPILING] dep v1.0.0 ([ROOT]/foo/target/package/dep-1.0.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[UNPACKING] dep v1.0.0 (registry `[ROOT]/foo/target/package/tmp-registry`)\n[COMPILING] dep v1.0.0\n[COMPILING] transitive v1.0.0\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] dep v1.0.0 ([ROOT]/foo/dep)\n[WARNING] aborting upload due to dry run\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] aborting upload due to dry run\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_publish_rate_limit_error() {\n    let registry = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .add_responder(\"/api/v1/crates/new\", |_req, _| {\n            // For simplicity, let's just return rate limit error for all requests\n            // This simulates hitting rate limit during workspace publish\n            Response {\n                code: 429,\n                headers: vec![\"Retry-After: 3600\".to_string()],\n                body: format!(\n                    \"You have published too many new crates in a short period of time. Please try again after Fri, 18 Jul 2025 20:00:34 GMT or email help@crates.io to have your limit increased.\"\n                ).into_bytes(),\n            }\n        })\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"package_a\", \"package_b\", \"package_c\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"package_a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"package_a\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"package a\"\n            repository = \"https://github.com/test/package_a\"\n            \"#,\n        )\n        .file(\"package_a/src/lib.rs\", \"\")\n        .file(\n            \"package_b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"package_b\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"package b\"\n            repository = \"https://github.com/test/package_b\"\n            \"#,\n        )\n        .file(\"package_b/src/lib.rs\", \"\")\n        .file(\n            \"package_c/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"package_c\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"package c\"\n            repository = \"https://github.com/test/package_c\"\n\n            [dependencies]\n            package_a = { version = \"0.1.0\", path = \"../package_a\" }\n            \"#,\n        )\n        .file(\"package_c/src/lib.rs\", \"\")\n        .build();\n\n    // This demonstrates the improved error message after the fix\n    // The user now knows which package failed and what packages remain to be published\n    p.cargo(\"publish --workspace --no-verify\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] package_a v0.1.0 ([ROOT]/foo/package_a)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] package_b v0.1.0 ([ROOT]/foo/package_b)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] package_c v0.1.0 ([ROOT]/foo/package_c)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[UPLOADING] package_a v0.1.0 ([ROOT]/foo/package_a)\n[ERROR] failed to publish package_a v0.1.0 to registry at http://127.0.0.1:[..]/\n\n[NOTE] the following crates have not been published yet:\n  package_b v0.1.0 ([ROOT]/foo/package_b)\n  package_c v0.1.0 ([ROOT]/foo/package_c)\n\nCaused by:\n  failed to get a 200 OK response, got 429\n  headers:\n  \tHTTP/1.1 429\n  \tContent-Length: 172\n  \tConnection: close\n  \tRetry-After: 3600\n  \t\n  body:\n  You have published too many new crates in a short period of time. Please try again after Fri, 18 Jul 2025 20:00:34 GMT or email help@crates.io to have your limit increased.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_circular_publish_dependency() {\n    // Verify detection and reporting of workspace circular dependencies.\n    let registry = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .build();\n\n    cargo_test_support::registry::Package::new(\"foo\", \"0.1.0\").publish();\n    cargo_test_support::registry::Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"foo\", \"bar\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.1\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"foo\"\n            repository = \"foo\"\n\n            [dependencies]\n            bar = { version = \"0.1\", path = \"../bar\" }\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.1\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"bar\"\n            repository = \"bar\"\n\n            [dev-dependencies]\n            foo = { version = \"0.1\", path = \"../foo\" }\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    // Ensure the circular dependency is caught and reported clearly.\n    p.cargo(\"publish --workspace --no-verify -Zpublish-timeout --config publish.timeout=1\")\n        .masquerade_as_nightly_cargo(&[\"publish-timeout\"])\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] foo v0.1.1 ([ROOT]/foo/foo)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] bar v0.1.1 ([ROOT]/foo/bar)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[ERROR] circular dependency detected while publishing bar v0.1.1 and foo v0.1.1\n[HELP] to break a cycle between dev-dependencies and other dependencies, remove the version field on the dev-dependency so it will be implicitly stripped on publish\n\n\"#]])\n        .run();\n}\n#[cargo_test]\nfn workspace_circular_publish_dependency_with_non_cycle_package() {\n    // Verify that circular dependency errors only report packages actively involved in the cycle.\n    // Package 'c' is independent and should be excluded from the error message,\n    // even though the cycle between 'a' and 'b' blocks the overall workspace publish.\n    let registry = registry::RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .build();\n\n    cargo_test_support::registry::Package::new(\"a\", \"1.0.0\").publish();\n    cargo_test_support::registry::Package::new(\"b\", \"1.0.0\").publish();\n    cargo_test_support::registry::Package::new(\"c\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\", \"c\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"1.0.1\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"a\"\n            repository = \"a\"\n\n            [dependencies]\n            b = { version = \"1.0\", path = \"../b\" }\n            c = { version = \"1.0\", path = \"../c\" }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"1.0.1\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"b\"\n            repository = \"b\"\n\n            [dependencies]\n            c = { version = \"1.0\", path = \"../c\" }\n\n            [dev-dependencies]\n            a = { version = \"1.0\", path = \"../a\" }\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .file(\n            \"c/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"c\"\n            version = \"1.0.1\"\n            edition = \"2015\"\n            license = \"MIT\"\n            description = \"c\"\n            repository = \"c\"\n            \"#,\n        )\n        .file(\"c/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --workspace --no-verify -Zpublish-timeout --config publish.timeout=1\")\n        .masquerade_as_nightly_cargo(&[\"publish-timeout\"])\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] c v1.0.1 ([ROOT]/foo/c)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] b v1.0.1 ([ROOT]/foo/b)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[PACKAGING] a v1.0.1 ([ROOT]/foo/a)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[ERROR] circular dependency detected while publishing a v1.0.1 and b v1.0.1\n[HELP] to break a cycle between dev-dependencies and other dependencies, remove the version field on the dev-dependency so it will be implicitly stripped on publish\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/publish_lockfile.rs",
    "content": "//! Tests for including `Cargo.lock` when publishing/packaging.\n\nuse std::fs::File;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{\n    basic_manifest, git, paths, project, publish::validate_crate_contents, str,\n};\n\nfn pl_manifest(name: &str, version: &str, extra: &str) -> String {\n    format!(\n        r#\"\n        [package]\n        name = \"{}\"\n        version = \"{}\"\n        edition = \"2015\"\n        authors = []\n        license = \"MIT\"\n        description = \"foo\"\n        documentation = \"foo\"\n        homepage = \"foo\"\n        repository = \"foo\"\n\n        {}\n        \"#,\n        name, version, extra\n    )\n}\n\n#[cargo_test]\nfn removed() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            cargo-features = [\"publish-lockfile\"]\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            publish-lockfile = true\n            license = \"MIT\"\n            description = \"foo\"\n            documentation = \"foo\"\n            homepage = \"foo\"\n            repository = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"package\")\n        .masquerade_as_nightly_cargo(&[\"publish-lockfile\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the cargo feature `publish-lockfile` has been removed in the 1.37 release\n\n  Remove the feature from Cargo.toml to remove this error.\n  See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#publish-lockfile for more information about using this feature.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn package_lockfile() {\n    let p = project()\n        .file(\"Cargo.toml\", &pl_manifest(\"foo\", \"0.0.1\", \"\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(p.root().join(\"target/package/foo-0.0.1.crate\").is_file());\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n    p.cargo(\"package\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"Cargo.lock\", \"src/main.rs\"],\n        (),\n    );\n}\n\n#[cargo_test]\nfn package_lockfile_git_repo() {\n    // Create a Git repository containing a minimal Rust project.\n    let g = git::repo(&paths::root().join(\"foo\"))\n        .file(\"Cargo.toml\", &pl_manifest(\"foo\", \"0.0.1\", \"\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    cargo_process(\"package -l\")\n        .cwd(g.root())\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n    cargo_process(\"package -v\")\n        .cwd(g.root())\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[ARCHIVING] .cargo_vcs_info.json\n[ARCHIVING] Cargo.lock\n[ARCHIVING] Cargo.toml\n[ARCHIVING] Cargo.toml.orig\n[ARCHIVING] src/main.rs\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn lock_file_with_library() {\n    let p = project()\n        .file(\"Cargo.toml\", &pl_manifest(\"foo\", \"0.0.1\", \"\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\").run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\", \"Cargo.lock\"],\n        (),\n    );\n}\n\n#[cargo_test]\nfn lock_file_and_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\"]\n            \"#,\n        )\n        .file(\"foo/Cargo.toml\", &pl_manifest(\"foo\", \"0.0.1\", \"\"))\n        .file(\"foo/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"package\").cwd(\"foo\").run();\n\n    let f = File::open(&p.root().join(\"target/package/foo-0.0.1.crate\")).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\", \"Cargo.lock\"],\n        (),\n    );\n}\n\n#[cargo_test]\nfn note_resolve_changes() {\n    // `multi` has multiple sources (path and registry).\n    Package::new(\"multi\", \"0.1.0\").publish();\n    // `updated` is always from registry, but should not change.\n    Package::new(\"updated\", \"1.0.0\").publish();\n    // `patched` is [patch]ed.\n    Package::new(\"patched\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &pl_manifest(\n                \"foo\",\n                \"0.0.1\",\n                r#\"\n                [dependencies]\n                multi = { path = \"multi\", version = \"0.1\" }\n                updated = \"1.0\"\n                patched = \"1.0\"\n\n                [patch.crates-io]\n                patched = { path = \"patched\" }\n                \"#,\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"multi/Cargo.toml\", &basic_manifest(\"multi\", \"0.1.0\"))\n        .file(\"multi/src/lib.rs\", \"\")\n        .file(\"patched/Cargo.toml\", &basic_manifest(\"patched\", \"1.0.0\"))\n        .file(\"patched/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    // Make sure this does not change or warn.\n    Package::new(\"updated\", \"1.0.1\").publish();\n\n    p.cargo(\"package --no-verify -v --allow-dirty\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[ARCHIVING] Cargo.lock\n[UPDATING] `dummy-registry` index\n[NOTE] package `multi v0.1.0` added to the packaged Cargo.lock file, was originally sourced from `[ROOT]/foo/multi`\n[NOTE] package `patched v1.0.0` added to the packaged Cargo.lock file, was originally sourced from `[ROOT]/foo/patched`\n[ARCHIVING] Cargo.toml\n[ARCHIVING] Cargo.toml.orig\n[ARCHIVING] src/main.rs\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n...\n\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn outdated_lock_version_change_does_not_warn() {\n    // If the version of the package being packaged changes, but Cargo.lock is\n    // not updated, don't bother warning about it.\n    let p = project()\n        .file(\"Cargo.toml\", &pl_manifest(\"foo\", \"0.1.0\", \"\"))\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    p.change_file(\"Cargo.toml\", &pl_manifest(\"foo\", \"0.2.0\", \"\"));\n\n    p.cargo(\"package --no-verify\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.2.0 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_warn_workspace_extras() {\n    // Other entries in workspace lock file should be ignored.\n    Package::new(\"dep1\", \"1.0.0\").publish();\n    Package::new(\"dep2\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            &pl_manifest(\n                \"a\",\n                \"0.1.0\",\n                r#\"\n                [dependencies]\n                dep1 = \"1.0\"\n                \"#,\n            ),\n        )\n        .file(\"a/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"b/Cargo.toml\",\n            &pl_manifest(\n                \"b\",\n                \"0.1.0\",\n                r#\"\n                [dependencies]\n                dep2 = \"1.0\"\n                \"#,\n            ),\n        )\n        .file(\"b/src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"generate-lockfile\").run();\n    p.cargo(\"package --no-verify\")\n        .cwd(\"a\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] a v0.1.0 ([ROOT]/foo/a)\n[UPDATING] `dummy-registry` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warn_package_with_yanked() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &pl_manifest(\n                \"foo\",\n                \"0.0.1\",\n                r#\"\n                [dependencies]\n                bar = \"0.1\"\n                \"#,\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"generate-lockfile\").run();\n    Package::new(\"bar\", \"0.1.0\").yanked(true).publish();\n    // Make sure it sticks with the locked (yanked) version.\n    Package::new(\"bar\", \"0.1.1\").publish();\n    p.cargo(\"package --no-verify\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[UPDATING] `dummy-registry` index\n[WARNING] package `bar v0.1.0` in Cargo.lock is yanked in registry `crates-io`, consider updating to a version that is not yanked\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warn_install_with_yanked() {\n    Package::new(\"bar\", \"0.1.0\").yanked(true).publish();\n    Package::new(\"bar\", \"0.1.1\").publish();\n    Package::new(\"foo\", \"0.1.0\")\n        .dep(\"bar\", \"0.1\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"Cargo.lock\",\n            r#\"\n[[package]]\nname = \"bar\"\nversion = \"0.1.0\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n[[package]]\nname = \"foo\"\nversion = \"0.1.0\"\ndependencies = [\n \"bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n]\n            \"#,\n        )\n        .publish();\n\n    cargo_process(\"install --locked foo\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.1.0 (registry `dummy-registry`)\n[INSTALLING] foo v0.1.0\n[WARNING] package `bar v0.1.0` in Cargo.lock is yanked in registry `crates-io`, consider running without --locked\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[COMPILING] bar v0.1.0\n[COMPILING] foo v0.1.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.1.0` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n\n    // Try again without --locked, make sure it uses 0.1.1 and does not warn.\n    cargo_process(\"install --force foo\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[INSTALLING] foo v0.1.0\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.1 (registry `dummy-registry`)\n[COMPILING] bar v0.1.1\n[COMPILING] foo v0.1.0\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE]\n[REPLACED] package `foo v0.1.0` with `foo v0.1.0` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ignore_lockfile() {\n    // With an explicit `include` list, but Cargo.lock in .gitignore, don't\n    // complain about `Cargo.lock` being ignored. Note that it is still\n    // included in the packaged regardless.\n    let p = git::new(\"foo\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            &pl_manifest(\n                \"foo\",\n                \"0.0.1\",\n                r#\"\n                include = [\n                    \"src/main.rs\"\n                ]\n                \"#,\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\".gitignore\", \"Cargo.lock\")\n    });\n    p.cargo(\"package -l\")\n        .with_stdout_data(str![[r#\"\n.cargo_vcs_info.json\nCargo.lock\nCargo.toml\nCargo.toml.orig\nsrc/main.rs\n\n\"#]])\n        .run();\n    p.cargo(\"generate-lockfile\").run();\n    p.cargo(\"package -v\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[ARCHIVING] .cargo_vcs_info.json\n[ARCHIVING] Cargo.lock\n[ARCHIVING] Cargo.toml\n[ARCHIVING] Cargo.toml.orig\n[ARCHIVING] src/main.rs\n[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ignore_lockfile_inner() {\n    // Ignore `Cargo.lock` if in .gitignore in a git subdirectory.\n    let p = git::new(\"foo\", |p| {\n        p.no_manifest()\n            .file(\"bar/Cargo.toml\", &pl_manifest(\"bar\", \"0.0.1\", \"\"))\n            .file(\"bar/src/main.rs\", \"fn main() {}\")\n            .file(\"bar/.gitignore\", \"Cargo.lock\")\n    });\n    p.cargo(\"generate-lockfile\").cwd(\"bar\").run();\n    p.cargo(\"package -v --no-verify\")\n        .cwd(\"bar\")\n        .with_stderr_data(str![[r#\"\n[PACKAGING] bar v0.0.1 ([ROOT]/foo/bar)\n[ARCHIVING] .cargo_vcs_info.json\n[ARCHIVING] .gitignore\n[ARCHIVING] Cargo.lock\n[ARCHIVING] Cargo.toml\n[ARCHIVING] Cargo.toml.orig\n[ARCHIVING] src/main.rs\n[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn use_workspace_root_lockfile() {\n    // Issue #11148\n    // Workspace members should use `Cargo.lock` at workspace root\n\n    Package::new(\"serde\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies]\n                serde = \"0.2\"\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"bar\"\n                workspace = \"..\"\n\n                [dependencies]\n                serde = \"0.2\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // Create `Cargo.lock` in the workspace root.\n    p.cargo(\"generate-lockfile\").run();\n\n    // Now, add a newer version of `serde`.\n    Package::new(\"serde\", \"0.2.1\").publish();\n\n    // Expect: package `bar` uses `serde v0.2.0` as required by workspace `Cargo.lock`.\n    p.cargo(\"package --workspace\")\n        .with_stderr_data(str![[r#\"\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] bar v0.0.1 ([ROOT]/foo/bar)\n[UPDATING] `dummy-registry` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] bar v0.0.1 ([ROOT]/foo/bar)\n[DOWNLOADING] crates ...\n[DOWNLOADED] serde v0.2.0 (registry `dummy-registry`)\n[COMPILING] serde v0.2.0\n[COMPILING] bar v0.0.1 ([ROOT]/foo/target/package/bar-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let package_path = p.root().join(\"target/package/foo-0.0.1.crate\");\n    assert!(package_path.is_file());\n    let f = File::open(&package_path).unwrap();\n    validate_crate_contents(\n        f,\n        \"foo-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        (),\n    );\n\n    let package_path = p.root().join(\"target/package/bar-0.0.1.crate\");\n    assert!(package_path.is_file());\n    let f = File::open(&package_path).unwrap();\n    validate_crate_contents(\n        f,\n        \"bar-0.0.1.crate\",\n        &[\"Cargo.lock\", \"Cargo.toml\", \"Cargo.toml.orig\", \"src/main.rs\"],\n        (),\n    );\n}\n"
  },
  {
    "path": "tests/testsuite/read_manifest.rs",
    "content": "//! Tests for the `cargo read-manifest` command.\n\nuse crate::prelude::*;\nuse cargo_test_support::{basic_bin_manifest, main_file, project, str};\n\npub fn basic_bin_manifest_with_readme(name: &str, readme_filename: &str) -> String {\n    format!(\n        r#\"\n            [package]\n\n            name = \"{}\"\n            version = \"0.5.0\"\n            authors = [\"wycats@example.com\"]\n            readme = {}\n\n            [[bin]]\n\n            name = \"{}\"\n        \"#,\n        name, readme_filename, name\n    )\n}\n\n#[cargo_test]\nfn cargo_read_manifest_path_to_cargo_toml_relative() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"read-manifest --manifest-path foo/Cargo.toml\")\n        .cwd(p.root().parent().unwrap())\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"readme\": null,\n  \"...\": \"{...}\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_read_manifest_path_to_cargo_toml_absolute() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"read-manifest --manifest-path\")\n        .arg(p.root().join(\"Cargo.toml\"))\n        .cwd(p.root().parent().unwrap())\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"readme\": null,\n  \"...\": \"{...}\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_read_manifest_path_to_cargo_toml_parent_relative() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"read-manifest --manifest-path foo\")\n        .cwd(p.root().parent().unwrap())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] manifest path `foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_read_manifest_path_to_cargo_toml_parent_absolute() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"read-manifest --manifest-path\")\n        .arg(p.root())\n        .cwd(p.root().parent().unwrap())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] manifest path `[ROOT]/foo` is a directory but expected a file\n[HELP] [ROOT]/foo/Cargo.toml exists\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_read_manifest_cwd() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"read-manifest\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"readme\": null,\n  \"...\": \"{...}\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_read_manifest_with_specified_readme() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &basic_bin_manifest_with_readme(\"foo\", r#\"\"SomeReadme.txt\"\"#),\n        )\n        .file(\"SomeReadme.txt\", \"Sample Project\")\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"read-manifest\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"readme\": \"SomeReadme.txt\",\n  \"...\": \"{...}\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_read_manifest_default_readme() {\n    let assert_output = |readme, expected| {\n        let p = project()\n            .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n            .file(readme, \"Sample project\")\n            .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n            .build();\n\n        p.cargo(\"read-manifest\").with_stdout_data(expected).run();\n    };\n\n    assert_output(\n        \"README.md\",\n        str![[r#\"\n{\n  \"readme\": \"README.md\",\n  \"...\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n\n    assert_output(\n        \"README.txt\",\n        str![[r#\"\n{\n  \"readme\": \"README.txt\",\n  \"...\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n\n    assert_output(\n        \"README\",\n        str![[r#\"\n{\n  \"readme\": \"README\",\n  \"...\": \"{...}\"\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test]\nfn cargo_read_manifest_suppress_default_readme() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &basic_bin_manifest_with_readme(\"foo\", \"false\"),\n        )\n        .file(\"README.txt\", \"Sample project\")\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"read-manifest\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"readme\": null,\n  \"...\": \"{...}\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n\n// If a file named README.md exists, and `readme = true`, the value `README.md` should be defaulted in.\n#[cargo_test]\nfn cargo_read_manifest_defaults_readme_if_true() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest_with_readme(\"foo\", \"true\"))\n        .file(\"README.md\", \"Sample project\")\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"read-manifest\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"readme\": \"README.md\",\n  \"...\": \"{...}\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/registry.rs",
    "content": "//! Tests for normal registry dependencies.\n\nuse std::fmt::Write;\nuse std::fs::{self, File};\nuse std::path::{Path, PathBuf};\nuse std::sync::Arc;\nuse std::sync::Mutex;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo::core::SourceId;\nuse cargo_test_support::assert_deterministic_mtime;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::{\n    self, Dependency, Package, RegistryBuilder, Response, TestRegistry, registry_path,\n};\nuse cargo_test_support::{basic_manifest, project, str};\nuse cargo_test_support::{git, t};\nuse cargo_util::paths::remove_dir_all;\n\nfn setup_http() -> TestRegistry {\n    RegistryBuilder::new().http_index().build()\n}\n\n#[cargo_test]\nfn test_server_stops() {\n    let server = setup_http();\n    server.join(); // ensure the server fully shuts down\n}\n\n#[cargo_test]\nfn simple_http() {\n    let _server = setup_http();\n    simple(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn simple_git() {\n    simple(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\nfn simple(pre_clean_expected: impl IntoData, post_clean_expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    p.cargo(\"check\").with_stderr_data(pre_clean_expected).run();\n\n    p.cargo(\"clean\").run();\n\n    assert!(paths::home().join(\".cargo/registry/CACHEDIR.TAG\").is_file());\n\n    // Don't download a second time\n    p.cargo(\"check\").with_stderr_data(post_clean_expected).run();\n}\n\n#[cargo_test]\nfn deps_http() {\n    let _server = setup_http();\n    deps(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)\n[CHECKING] baz v0.0.1\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\n#[cargo_test]\nfn deps_git() {\n    deps(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)\n[CHECKING] baz v0.0.1\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\nfn deps(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"baz\", \"0.0.1\").publish();\n    Package::new(\"bar\", \"0.0.1\").dep(\"baz\", \"*\").publish();\n\n    p.cargo(\"check\").with_stderr_data(expected).run();\n\n    assert!(paths::home().join(\".cargo/registry/CACHEDIR.TAG\").is_file());\n}\n\n#[cargo_test]\nfn nonexistent_http() {\n    let _server = setup_http();\n    nonexistent(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package named `nonexistent` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]]);\n}\n\n#[cargo_test]\nfn nonexistent_git() {\n    nonexistent(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package named `nonexistent` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]]);\n}\n\nfn nonexistent(expected: impl IntoData) {\n    Package::new(\"init\", \"0.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                nonexistent = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(expected)\n        .run();\n}\n\n#[cargo_test]\nfn wrong_case_http() {\n    let _server = setup_http();\n    wrong_case(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package found\nsearched package name: `Init`\nperhaps you meant:      init\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]]);\n}\n\n#[cargo_test]\nfn wrong_case_git() {\n    wrong_case(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package found\nsearched package name: `Init`\nperhaps you meant:      init\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]]);\n}\n\nfn wrong_case(expected: impl IntoData) {\n    Package::new(\"init\", \"0.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                Init = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // #5678 to make this work\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(expected)\n        .run();\n}\n\n#[cargo_test]\nfn mis_hyphenated_http() {\n    let _server = setup_http();\n    mis_hyphenated(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package found\nsearched package name: `mis_hyphenated`\nperhaps you meant:      mis-hyphenated\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]]);\n}\n\n#[cargo_test]\nfn mis_hyphenated_git() {\n    mis_hyphenated(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package found\nsearched package name: `mis_hyphenated`\nperhaps you meant:      mis-hyphenated\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]]);\n}\n\nfn mis_hyphenated(expected: impl IntoData) {\n    Package::new(\"mis-hyphenated\", \"0.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                mis_hyphenated = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // #2775 to make this work\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(expected)\n        .run();\n}\n\n#[cargo_test]\nfn wrong_version_http() {\n    let _server = setup_http();\n    wrong_version(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `foo = \">=1.0.0\"`\ncandidate versions found which didn't match: 0.0.2, 0.0.1\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\nperhaps a crate was updated and forgotten to be re-vendored?\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `foo = \">=1.0.0\"`\ncandidate versions found which didn't match: 0.0.4, 0.0.3, 0.0.2, ...\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\nperhaps a crate was updated and forgotten to be re-vendored?\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn wrong_version_git() {\n    wrong_version(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `foo = \">=1.0.0\"`\ncandidate versions found which didn't match: 0.0.2, 0.0.1\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\nperhaps a crate was updated and forgotten to be re-vendored?\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `foo = \">=1.0.0\"`\ncandidate versions found which didn't match: 0.0.4, 0.0.3, 0.0.2, ...\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\nperhaps a crate was updated and forgotten to be re-vendored?\n\n\"#]],\n    );\n}\n\nfn wrong_version(pre_publish_expected: impl IntoData, post_publish_expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \">= 1.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"foo\", \"0.0.1\").publish();\n    Package::new(\"foo\", \"0.0.2\").publish();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(pre_publish_expected)\n        .run();\n\n    Package::new(\"foo\", \"0.0.3\").publish();\n    Package::new(\"foo\", \"0.0.4\").publish();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(post_publish_expected)\n        .run();\n}\n\n#[cargo_test]\nfn bad_cksum_http() {\n    let _server = setup_http();\n    bad_cksum(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bad-cksum v0.0.1 (registry `dummy-registry`)\n[ERROR] failed to download replaced source registry `crates-io`\n\nCaused by:\n  failed to verify the checksum of `bad-cksum v0.0.1 (registry `dummy-registry`)`\n\n\"#]]);\n}\n\n#[cargo_test]\nfn bad_cksum_git() {\n    bad_cksum(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bad-cksum v0.0.1 (registry `dummy-registry`)\n[ERROR] failed to download replaced source registry `crates-io`\n\nCaused by:\n  failed to verify the checksum of `bad-cksum v0.0.1 (registry `dummy-registry`)`\n\n\"#]]);\n}\n\nfn bad_cksum(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bad-cksum = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    let pkg = Package::new(\"bad-cksum\", \"0.0.1\");\n    pkg.publish();\n    t!(File::create(&pkg.archive_dst()));\n\n    p.cargo(\"check -v\")\n        .with_status(101)\n        .with_stderr_data(expected)\n        .run();\n}\n\n#[cargo_test]\nfn update_registry_http() {\n    let _server = setup_http();\n    update_registry(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package named `notyet` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] notyet v0.0.1 (registry `dummy-registry`)\n[CHECKING] notyet v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn update_registry_git() {\n    update_registry(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package named `notyet` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] notyet v0.0.1 (registry `dummy-registry`)\n[CHECKING] notyet v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\nfn update_registry(pre_publish_expected: impl IntoData, post_publish_expected: impl IntoData) {\n    Package::new(\"init\", \"0.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                notyet = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(pre_publish_expected)\n        .run();\n\n    Package::new(\"notyet\", \"0.0.1\").publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(post_publish_expected)\n        .run();\n}\n\n#[cargo_test]\nfn package_with_path_deps_http() {\n    let _server = setup_http();\n    package_with_path_deps(\n        str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[UPDATING] `dummy-registry` index\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  no matching package named `notyet` found\n  location searched: `dummy-registry` index (which is replacing registry `crates-io`)\n  required by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]],\n        str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[UPDATING] `dummy-registry` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[DOWNLOADING] crates ...\n[DOWNLOADED] notyet v0.0.1 (registry `dummy-registry`)\n[COMPILING] notyet v0.0.1\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn package_with_path_deps_git() {\n    package_with_path_deps(\n        str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[UPDATING] `dummy-registry` index\n[ERROR] failed to prepare local package for uploading\n\nCaused by:\n  no matching package named `notyet` found\n  location searched: `dummy-registry` index (which is replacing registry `crates-io`)\n  required by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]],\n        str![[r#\"\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[UPDATING] `dummy-registry` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[DOWNLOADING] crates ...\n[DOWNLOADED] notyet v0.0.1 (registry `dummy-registry`)\n[COMPILING] notyet v0.0.1\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\nfn package_with_path_deps(\n    pre_publish_expected: impl IntoData,\n    post_publish_expected: impl IntoData,\n) {\n    Package::new(\"init\", \"0.0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n                repository = \"bar\"\n\n                [dependencies.notyet]\n                version = \"0.0.1\"\n                path = \"notyet\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"notyet/Cargo.toml\", &basic_manifest(\"notyet\", \"0.0.1\"))\n        .file(\"notyet/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"package\")\n        .with_status(101)\n        .with_stderr_data(pre_publish_expected)\n        .run();\n\n    Package::new(\"notyet\", \"0.0.1\").publish();\n\n    p.cargo(\"package\")\n        .with_stderr_data(post_publish_expected)\n        .run();\n}\n\n#[cargo_test]\nfn lockfile_locks_http() {\n    let _server = setup_http();\n    lockfile_locks(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn lockfile_locks_git() {\n    lockfile_locks(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\nfn lockfile_locks(pre_publish_expected: impl IntoData, post_publish_expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(pre_publish_expected)\n        .run();\n\n    p.root().move_into_the_past();\n    Package::new(\"bar\", \"0.0.2\").publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(post_publish_expected)\n        .run();\n}\n\n#[cargo_test]\nfn lockfile_locks_transitively_http() {\n    let _server = setup_http();\n    lockfile_locks_transitively(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)\n[CHECKING] baz v0.0.1\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn lockfile_locks_transitively_git() {\n    lockfile_locks_transitively(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)\n[CHECKING] baz v0.0.1\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\nfn lockfile_locks_transitively(\n    pre_publish_expected: impl IntoData,\n    post_publish_expected: impl IntoData,\n) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"baz\", \"0.0.1\").publish();\n    Package::new(\"bar\", \"0.0.1\").dep(\"baz\", \"*\").publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(pre_publish_expected)\n        .run();\n\n    p.root().move_into_the_past();\n    Package::new(\"baz\", \"0.0.2\").publish();\n    Package::new(\"bar\", \"0.0.2\").dep(\"baz\", \"*\").publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(post_publish_expected)\n        .run();\n}\n\n#[cargo_test]\nfn yanks_are_not_used_http() {\n    let _server = setup_http();\n    yanks_are_not_used(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)\n[CHECKING] baz v0.0.1\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\n#[cargo_test]\nfn yanks_are_not_used_git() {\n    yanks_are_not_used(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`)\n[CHECKING] baz v0.0.1\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\nfn yanks_are_not_used(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"baz\", \"0.0.1\").publish();\n    Package::new(\"baz\", \"0.0.2\").yanked(true).publish();\n    Package::new(\"bar\", \"0.0.1\").dep(\"baz\", \"*\").publish();\n    Package::new(\"bar\", \"0.0.2\")\n        .dep(\"baz\", \"*\")\n        .yanked(true)\n        .publish();\n\n    p.cargo(\"check\").with_stderr_data(expected).run();\n}\n\n#[cargo_test]\nfn relying_on_a_yank_is_bad_http() {\n    let _server = setup_http();\n    relying_on_a_yank_is_bad(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `baz = \"=0.0.2\"`\n  version 0.0.2 is yanked\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `bar v0.0.1`\n    ... which satisfies dependency `bar = \"*\"` of package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]]);\n}\n\n#[cargo_test]\nfn relying_on_a_yank_is_bad_git() {\n    relying_on_a_yank_is_bad(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `baz = \"=0.0.2\"`\n  version 0.0.2 is yanked\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `bar v0.0.1`\n    ... which satisfies dependency `bar = \"*\"` of package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]]);\n}\n\nfn relying_on_a_yank_is_bad(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"baz\", \"0.0.1\").publish();\n    Package::new(\"baz\", \"0.0.2\").yanked(true).publish();\n    Package::new(\"bar\", \"0.0.1\").dep(\"baz\", \"=0.0.2\").publish();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(expected)\n        .run();\n}\n\n#[cargo_test]\nfn yanks_in_lockfiles_are_ok_http() {\n    let _server = setup_http();\n    yanks_in_lockfiles_are_ok(\n        str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `bar = \"*\"`\n  version 0.0.1 is yanked\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn yanks_in_lockfiles_are_ok_git() {\n    yanks_in_lockfiles_are_ok(\n        str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `bar = \"*\"`\n  version 0.0.1 is yanked\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]],\n    );\n}\n\nfn yanks_in_lockfiles_are_ok(expected_check: impl IntoData, expected_update: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    p.cargo(\"check\").run();\n\n    registry_path().join(\"3\").rm_rf();\n\n    Package::new(\"bar\", \"0.0.1\").yanked(true).publish();\n\n    p.cargo(\"check\").with_stderr_data(expected_check).run();\n\n    p.cargo(\"update\")\n        .with_status(101)\n        .with_stderr_data(expected_update)\n        .run();\n}\n\n#[cargo_test]\nfn yanks_in_lockfiles_are_ok_for_other_update_http() {\n    let _server = setup_http();\n    yanks_in_lockfiles_are_ok_for_other_update(\n        str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `bar = \"*\"`\n  version 0.0.1 is yanked\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] baz v0.0.1 -> v0.0.2\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn yanks_in_lockfiles_are_ok_for_other_update_git() {\n    yanks_in_lockfiles_are_ok_for_other_update(\n        str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `bar = \"*\"`\n  version 0.0.1 is yanked\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] baz v0.0.1 -> v0.0.2\n\n\"#]],\n    );\n}\n\nfn yanks_in_lockfiles_are_ok_for_other_update(\n    expected_check: impl IntoData,\n    expected_update: impl IntoData,\n    expected_other_update: impl IntoData,\n) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n                baz = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n    Package::new(\"baz\", \"0.0.1\").publish();\n\n    p.cargo(\"check\").run();\n\n    registry_path().join(\"3\").rm_rf();\n\n    Package::new(\"bar\", \"0.0.1\").yanked(true).publish();\n    Package::new(\"baz\", \"0.0.1\").publish();\n\n    p.cargo(\"check\").with_stderr_data(expected_check).run();\n\n    Package::new(\"baz\", \"0.0.2\").publish();\n\n    p.cargo(\"update\")\n        .with_status(101)\n        .with_stderr_data(expected_update)\n        .run();\n\n    p.cargo(\"update baz\")\n        .with_stderr_data(expected_other_update)\n        .run();\n}\n\n#[cargo_test]\nfn yanks_in_lockfiles_are_ok_with_new_dep_http() {\n    let _server = setup_http();\n    yanks_in_lockfiles_are_ok_with_new_dep(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ADDING] baz v0.0.1\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.0.1 (registry `dummy-registry`)\n[CHECKING] baz v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\n#[cargo_test]\nfn yanks_in_lockfiles_are_ok_with_new_dep_git() {\n    yanks_in_lockfiles_are_ok_with_new_dep(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ADDING] baz v0.0.1\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.0.1 (registry `dummy-registry`)\n[CHECKING] baz v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\nfn yanks_in_lockfiles_are_ok_with_new_dep(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    p.cargo(\"check\").run();\n\n    registry_path().join(\"3\").rm_rf();\n\n    Package::new(\"bar\", \"0.0.1\").yanked(true).publish();\n    Package::new(\"baz\", \"0.0.1\").publish();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            bar = \"*\"\n            baz = \"*\"\n        \"#,\n    );\n\n    p.cargo(\"check\").with_stderr_data(expected).run();\n}\n\n#[cargo_test]\nfn update_with_lockfile_if_packages_missing_http() {\n    let _server = setup_http();\n    update_with_lockfile_if_packages_missing(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\n#[cargo_test]\nfn update_with_lockfile_if_packages_missing_git() {\n    update_with_lockfile_if_packages_missing(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\nfn update_with_lockfile_if_packages_missing(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n    p.cargo(\"check\").run();\n    p.root().move_into_the_past();\n\n    paths::home().join(\".cargo/registry\").rm_rf();\n    p.cargo(\"check\").with_stderr_data(expected).run();\n}\n\n#[cargo_test]\nfn update_lockfile_http() {\n    let _server = setup_http();\n    update_lockfile(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] bar v0.0.1 -> v0.0.2\n\n\"#]],\n        str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.2 (registry `dummy-registry`)\n[CHECKING] bar v0.0.2\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.0.2 -> v0.0.3\n\n\"#]],\n        str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.3 (registry `dummy-registry`)\n[CHECKING] bar v0.0.3\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] bar v0.0.3 -> v0.0.4\n[ADDING] spam v0.2.5\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.0.4 -> v0.0.5\n[REMOVING] spam v0.2.5\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn update_lockfile_git() {\n    update_lockfile(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] bar v0.0.1 -> v0.0.2\n\n\"#]],\n        str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.2 (registry `dummy-registry`)\n[CHECKING] bar v0.0.2\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.0.2 -> v0.0.3\n\n\"#]],\n        str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.3 (registry `dummy-registry`)\n[CHECKING] bar v0.0.3\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] bar v0.0.3 -> v0.0.4\n[ADDING] spam v0.2.5\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.0.4 -> v0.0.5\n[REMOVING] spam v0.2.5\n\n\"#]],\n    );\n}\n\nfn update_lockfile(\n    expected_update: impl IntoData,\n    expected_check: impl IntoData,\n    expected_other_update: impl IntoData,\n    expected_other_check: impl IntoData,\n    expected_new_update: impl IntoData,\n    expected_new_check: impl IntoData,\n) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    println!(\"0.0.1\");\n    Package::new(\"bar\", \"0.0.1\").publish();\n    p.cargo(\"check\").run();\n\n    Package::new(\"bar\", \"0.0.2\").publish();\n    Package::new(\"bar\", \"0.0.3\").publish();\n    paths::home().join(\".cargo/registry\").rm_rf();\n    println!(\"0.0.2 update\");\n    p.cargo(\"update bar --precise 0.0.2\")\n        .with_stderr_data(expected_update)\n        .run();\n\n    println!(\"0.0.2 build\");\n    p.cargo(\"check\").with_stderr_data(expected_check).run();\n\n    println!(\"0.0.3 update\");\n    p.cargo(\"update bar\")\n        .with_stderr_data(expected_other_update)\n        .run();\n\n    println!(\"0.0.3 build\");\n    p.cargo(\"check\")\n        .with_stderr_data(expected_other_check)\n        .run();\n\n    println!(\"new dependencies update\");\n    Package::new(\"bar\", \"0.0.4\").dep(\"spam\", \"0.2.5\").publish();\n    Package::new(\"spam\", \"0.2.5\").publish();\n    p.cargo(\"update bar\")\n        .with_stderr_data(expected_new_update)\n        .run();\n\n    println!(\"new dependencies update\");\n    Package::new(\"bar\", \"0.0.5\").publish();\n    p.cargo(\"update bar\")\n        .with_stderr_data(expected_new_check)\n        .run();\n}\n\n#[cargo_test]\nfn dev_dependency_not_used_http() {\n    let _server = setup_http();\n    dev_dependency_not_used(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\n#[cargo_test]\nfn dev_dependency_not_used_git() {\n    dev_dependency_not_used(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\nfn dev_dependency_not_used(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"baz\", \"0.0.1\").publish();\n    Package::new(\"bar\", \"0.0.1\").dev_dep(\"baz\", \"*\").publish();\n\n    p.cargo(\"check\").with_stderr_data(expected).run();\n}\n\n#[cargo_test]\nfn bad_license_file_http() {\n    let registry = setup_http();\n    bad_license_file(\n        &registry,\n        str![[r#\"\n...\n[ERROR] license-file `foo` does not appear to exist (relative to `[ROOT]/foo`).\n...\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn bad_license_file_git() {\n    let registry = registry::init();\n    bad_license_file(\n        &registry,\n        str![[r#\"\n...\n[ERROR] license-file `foo` does not appear to exist (relative to `[ROOT]/foo`).\n...\n\"#]],\n    );\n}\n\nfn bad_license_file(registry: &TestRegistry, expected: impl IntoData) {\n    Package::new(\"foo\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license-file = \"foo\"\n                description = \"bar\"\n                repository = \"baz\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"publish -v\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(expected)\n        .run();\n}\n\n#[cargo_test]\nfn updating_a_dep_http() {\n    let _server = setup_http();\n    updating_a_dep(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] a v0.0.1 ([ROOT]/foo/a)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.0.1 -> v0.1.0\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] a v0.0.1 ([ROOT]/foo/a)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn updating_a_dep_git() {\n    updating_a_dep(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] a v0.0.1 ([ROOT]/foo/a)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.0.1 -> v0.1.0\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0\n[CHECKING] a v0.0.1 ([ROOT]/foo/a)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\nfn updating_a_dep(pre_update_expected: impl IntoData, post_update_expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    p.cargo(\"check\").with_stderr_data(pre_update_expected).run();\n    assert!(paths::home().join(\".cargo/registry/CACHEDIR.TAG\").is_file());\n\n    // Now delete the CACHEDIR.TAG file: this is the situation we'll be in after\n    // upgrading from a version of Cargo that doesn't mark this directory, to one that\n    // does. It should be recreated.\n    fs::remove_file(paths::home().join(\".cargo/registry/CACHEDIR.TAG\"))\n        .expect(\"remove CACHEDIR.TAG\");\n\n    p.change_file(\n        \"a/Cargo.toml\",\n        r#\"\n        [package]\n        name = \"a\"\n        version = \"0.0.1\"\n        edition = \"2015\"\n        authors = []\n\n        [dependencies]\n        bar = \"0.1.0\"\n        \"#,\n    );\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    println!(\"second\");\n    p.cargo(\"check\")\n        .with_stderr_data(post_update_expected)\n        .run();\n\n    assert!(\n        paths::home().join(\".cargo/registry/CACHEDIR.TAG\").is_file(),\n        \"CACHEDIR.TAG recreated in existing registry\"\n    );\n}\n\n#[cargo_test]\nfn git_and_registry_dep_http() {\n    let _server = setup_http();\n    git_and_registry_dep(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/b`\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] a v0.0.1 (registry `dummy-registry`)\n[CHECKING] a v0.0.1\n[CHECKING] b v0.0.1 ([ROOTURL]/b#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn git_and_registry_dep_git() {\n    git_and_registry_dep(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/b`\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] a v0.0.1 (registry `dummy-registry`)\n[CHECKING] a v0.0.1\n[CHECKING] b v0.0.1 ([ROOTURL]/b#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n        str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\nfn git_and_registry_dep(pre_move_expected: impl IntoData, post_move_expected: impl IntoData) {\n    let b = git::repo(&paths::root().join(\"b\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = \"0.0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    a = \"0.0.1\"\n\n                    [dependencies.b]\n                    git = '{}'\n                \"#,\n                b.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"a\", \"0.0.1\").publish();\n\n    p.root().move_into_the_past();\n    p.cargo(\"check\").with_stderr_data(pre_move_expected).run();\n    p.root().move_into_the_past();\n\n    println!(\"second\");\n    p.cargo(\"check\").with_stderr_data(post_move_expected).run();\n}\n\n#[cargo_test]\nfn update_publish_then_update_http() {\n    let _server = setup_http();\n    update_publish_then_update(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] a v0.1.1 (registry `dummy-registry`)\n[COMPILING] a v0.1.1\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\n#[cargo_test]\nfn update_publish_then_update_git() {\n    update_publish_then_update(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] a v0.1.1 (registry `dummy-registry`)\n[COMPILING] a v0.1.1\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\nfn update_publish_then_update(expected: impl IntoData) {\n    // First generate a Cargo.lock and a clone of the registry index at the\n    // \"head\" of the current registry.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    Package::new(\"a\", \"0.1.0\").publish();\n    p.cargo(\"build\").run();\n\n    // Next, publish a new package and back up the copy of the registry we just\n    // created.\n    Package::new(\"a\", \"0.1.1\").publish();\n    let registry = paths::home().join(\".cargo/registry\");\n    let backup = paths::root().join(\"registry-backup\");\n    t!(fs::rename(&registry, &backup));\n\n    // Generate a Cargo.lock with the newer version, and then move the old copy\n    // of the registry back into place.\n    let p2 = project()\n        .at(\"foo2\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = \"0.1.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p2.cargo(\"build\").run();\n    registry.rm_rf();\n    t!(fs::rename(&backup, &registry));\n    t!(fs::rename(\n        p2.root().join(\"Cargo.lock\"),\n        p.root().join(\"Cargo.lock\")\n    ));\n\n    // Finally, build the first project again (with our newer Cargo.lock) which\n    // should force an update of the old registry, download the new crate, and\n    // then build everything again.\n    p.cargo(\"build\").with_stderr_data(expected).run();\n}\n\n#[cargo_test]\nfn fetch_downloads_http() {\n    let _server = setup_http();\n    fetch_downloads(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] a v0.1.0 (registry `dummy-registry`)\n\n\"#]]);\n}\n\n#[cargo_test]\nfn fetch_downloads_git() {\n    fetch_downloads(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] a v0.1.0 (registry `dummy-registry`)\n\n\"#]]);\n}\n\nfn fetch_downloads(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"a\", \"0.1.0\").publish();\n\n    p.cargo(\"fetch\").with_stderr_data(expected).run();\n}\n\n#[cargo_test]\nfn update_transitive_dependency_http() {\n    let _server = setup_http();\n    update_transitive_dependency(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] b v0.1.0 -> v0.1.1\n\n\"#]],\n        str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] b v0.1.1 (registry `dummy-registry`)\n[CHECKING] b v0.1.1\n[CHECKING] a v0.1.0\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn update_transitive_dependency_git() {\n    update_transitive_dependency(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] b v0.1.0 -> v0.1.1\n\n\"#]],\n        str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] b v0.1.1 (registry `dummy-registry`)\n[CHECKING] b v0.1.1\n[CHECKING] a v0.1.0\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\nfn update_transitive_dependency(expected_update: impl IntoData, expected_check: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"a\", \"0.1.0\").dep(\"b\", \"*\").publish();\n    Package::new(\"b\", \"0.1.0\").publish();\n\n    p.cargo(\"fetch\").run();\n\n    Package::new(\"b\", \"0.1.1\").publish();\n\n    p.cargo(\"update b\").with_stderr_data(expected_update).run();\n\n    p.cargo(\"check\").with_stderr_data(expected_check).run();\n}\n\n#[cargo_test]\nfn update_backtracking_ok_http() {\n    let _server = setup_http();\n    update_backtracking_ok(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] hyper v0.6.5 -> v0.6.6\n[UPDATING] openssl v0.1.0 -> v0.1.1\n\n\"#]]);\n}\n\n#[cargo_test]\nfn update_backtracking_ok_git() {\n    update_backtracking_ok(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] hyper v0.6.5 -> v0.6.6\n[UPDATING] openssl v0.1.0 -> v0.1.1\n\n\"#]]);\n}\n\nfn update_backtracking_ok(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                webdriver = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"webdriver\", \"0.1.0\")\n        .dep(\"hyper\", \"0.6\")\n        .publish();\n    Package::new(\"hyper\", \"0.6.5\")\n        .dep(\"openssl\", \"0.1\")\n        .dep(\"cookie\", \"0.1\")\n        .publish();\n    Package::new(\"cookie\", \"0.1.0\")\n        .dep(\"openssl\", \"0.1\")\n        .publish();\n    Package::new(\"openssl\", \"0.1.0\").publish();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    Package::new(\"openssl\", \"0.1.1\").publish();\n    Package::new(\"hyper\", \"0.6.6\")\n        .dep(\"openssl\", \"0.1.1\")\n        .dep(\"cookie\", \"0.1.0\")\n        .publish();\n\n    p.cargo(\"update hyper\").with_stderr_data(expected).run();\n}\n\n#[cargo_test]\nfn update_multiple_packages_http() {\n    let _server = setup_http();\n    update_multiple_packages(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] a v0.1.0 -> v0.1.1\n[UPDATING] b v0.1.0 -> v0.1.1\n[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] c v0.1.0 -> v0.1.1\n\n\"#]],\n        str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] a v0.1.1 (registry `dummy-registry`)\n[DOWNLOADED] b v0.1.1 (registry `dummy-registry`)\n[DOWNLOADED] c v0.1.1 (registry `dummy-registry`)\n[CHECKING] a v0.1.1\n[CHECKING] c v0.1.1\n[CHECKING] b v0.1.1\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn update_multiple_packages_git() {\n    update_multiple_packages(\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] a v0.1.0 -> v0.1.1\n[UPDATING] b v0.1.0 -> v0.1.1\n[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest\n\n\"#]],\n        str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] c v0.1.0 -> v0.1.1\n\n\"#]],\n        str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] c v0.1.1 (registry `dummy-registry`)\n[DOWNLOADED] b v0.1.1 (registry `dummy-registry`)\n[DOWNLOADED] a v0.1.1 (registry `dummy-registry`)\n[CHECKING] b v0.1.1\n[CHECKING] a v0.1.1\n[CHECKING] c v0.1.1\n[CHECKING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]],\n    );\n}\n\nfn update_multiple_packages(\n    expected_update: impl IntoData,\n    expected_other_update: impl IntoData,\n    expected_check: impl IntoData,\n) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = \"*\"\n                b = \"*\"\n                c = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"a\", \"0.1.0\").publish();\n    Package::new(\"b\", \"0.1.0\").publish();\n    Package::new(\"c\", \"0.1.0\").publish();\n\n    p.cargo(\"fetch\").run();\n\n    Package::new(\"a\", \"0.1.1\").publish();\n    Package::new(\"b\", \"0.1.1\").publish();\n    Package::new(\"c\", \"0.1.1\").publish();\n\n    p.cargo(\"update a b\")\n        .with_stderr_data(expected_update)\n        .run();\n\n    p.cargo(\"update b c\")\n        .with_stderr_data(expected_other_update)\n        .run();\n\n    p.cargo(\"check\")\n        .with_stderr_data(IntoData::unordered(expected_check))\n        .run();\n}\n\n#[cargo_test]\nfn bundled_crate_in_registry_http() {\n    let _server = setup_http();\n    bundled_crate_in_registry();\n}\n\n#[cargo_test]\nfn bundled_crate_in_registry_git() {\n    bundled_crate_in_registry();\n}\n\nfn bundled_crate_in_registry() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1\"\n                baz = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"baz\", \"0.1.0\")\n        .dep(\"bar\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\", version = \"0.1.0\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .publish();\n\n    p.cargo(\"run\").run();\n}\n\n#[cargo_test]\nfn update_same_prefix_oh_my_how_was_this_a_bug_http() {\n    let _server = setup_http();\n    update_same_prefix_oh_my_how_was_this_a_bug();\n}\n\n#[cargo_test]\nfn update_same_prefix_oh_my_how_was_this_a_bug_git() {\n    update_same_prefix_oh_my_how_was_this_a_bug();\n}\n\nfn update_same_prefix_oh_my_how_was_this_a_bug() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"ugh\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"foobar\", \"0.2.0\").publish();\n    Package::new(\"foo\", \"0.1.0\")\n        .dep(\"foobar\", \"0.2.0\")\n        .publish();\n\n    p.cargo(\"generate-lockfile\").run();\n    p.cargo(\"update foobar --precise=0.2.0\").run();\n}\n\n#[cargo_test]\nfn use_semver_http() {\n    let _server = setup_http();\n    use_semver();\n}\n\n#[cargo_test]\nfn use_semver_git() {\n    use_semver();\n}\n\nfn use_semver() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"1.2.3-alpha.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"foo\", \"1.2.3-alpha.0\").publish();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn use_semver_package_incorrectly_http() {\n    let _server = setup_http();\n    use_semver_package_incorrectly(str![[r#\"\n[ERROR] failed to select a version for the requirement `a = \"^0.1\"`\ncandidate versions found which didn't match: 0.1.1-alpha.0\nlocation searched: [ROOT]/foo/a\nrequired by package `b v0.1.0 ([ROOT]/foo/b)`\nif you are looking for the prerelease package it needs to be specified explicitly\n    a = { version = \"0.1.1-alpha.0\" }\n\n\"#]]);\n}\n\n#[cargo_test]\nfn use_semver_package_incorrectly_git() {\n    use_semver_package_incorrectly(str![[r#\"\n[ERROR] failed to select a version for the requirement `a = \"^0.1\"`\ncandidate versions found which didn't match: 0.1.1-alpha.0\nlocation searched: [ROOT]/foo/a\nrequired by package `b v0.1.0 ([ROOT]/foo/b)`\nif you are looking for the prerelease package it needs to be specified explicitly\n    a = { version = \"0.1.1-alpha.0\" }\n\n\"#]]);\n}\n\nfn use_semver_package_incorrectly(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.1-alpha.0\"\n            edition = \"2015\"\n            authors = []\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"b\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            a = { version = \"^0.1\", path = \"../a\" }\n            \"#,\n        )\n        .file(\"a/src/main.rs\", \"fn main() {}\")\n        .file(\"b/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(expected)\n        .run();\n}\n\n#[cargo_test]\nfn only_download_relevant_http() {\n    let _server = setup_http();\n    only_download_relevant(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`)\n[CHECKING] baz v0.1.0\n[CHECKING] bar v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\n#[cargo_test]\nfn only_download_relevant_git() {\n    only_download_relevant(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`)\n[CHECKING] baz v0.1.0\n[CHECKING] bar v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\nfn only_download_relevant(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [target.foo.dependencies]\n                foo = \"*\"\n                [dev-dependencies]\n                bar = \"*\"\n                [dependencies]\n                baz = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"foo\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    p.cargo(\"check\").with_stderr_data(expected).run();\n}\n\n#[cargo_test]\nfn resolve_and_backtracking_http() {\n    let _server = setup_http();\n    resolve_and_backtracking();\n}\n\n#[cargo_test]\nfn resolve_and_backtracking_git() {\n    resolve_and_backtracking();\n}\n\nfn resolve_and_backtracking() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"foo\", \"0.1.1\")\n        .feature_dep(\"bar\", \"0.1\", &[\"a\", \"b\"])\n        .publish();\n    Package::new(\"foo\", \"0.1.0\").publish();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn upstream_warnings_on_extra_verbose_http() {\n    let _server = setup_http();\n    upstream_warnings_on_extra_verbose(str![[r#\"\n...\n[WARNING] function `unused` is never used\n...\n\"#]]);\n}\n\n#[cargo_test]\nfn upstream_warnings_on_extra_verbose_git() {\n    upstream_warnings_on_extra_verbose(str![[r#\"\n...\n[WARNING] function `unused` is never used\n...\n\"#]]);\n}\n\nfn upstream_warnings_on_extra_verbose(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"foo\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"fn unused() {}\")\n        .publish();\n\n    p.cargo(\"check -vv\").with_stderr_data(expected).run();\n}\n\n#[cargo_test]\nfn disallow_network_http() {\n    let _server = setup_http();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check --frozen\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no matching package named `foo` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `bar v0.5.0 ([ROOT]/foo)`\nAs a reminder, you're using offline mode (--frozen) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without `--frozen`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn disallow_network_git() {\n    let _server = RegistryBuilder::new().build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check --frozen\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no matching package named `foo` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `bar v0.5.0 ([ROOT]/foo)`\nAs a reminder, you're using offline mode (--frozen) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without `--frozen`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn add_dep_dont_update_registry_http() {\n    let _server = setup_http();\n    add_dep_dont_update_registry(str![[r#\"\n[CHECKING] bar v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\n#[cargo_test]\nfn add_dep_dont_update_registry_git() {\n    add_dep_dont_update_registry(str![[r#\"\n[CHECKING] bar v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\nfn add_dep_dont_update_registry(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = { path = \"baz\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                remote = \"0.3\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"remote\", \"0.3.4\").publish();\n\n    p.cargo(\"check\").run();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n        [package]\n        name = \"bar\"\n        version = \"0.5.0\"\n        edition = \"2015\"\n        authors = []\n\n        [dependencies]\n        baz = { path = \"baz\" }\n        remote = \"0.3\"\n        \"#,\n    );\n\n    p.cargo(\"check\").with_stderr_data(expected).run();\n}\n\n#[cargo_test]\nfn bump_version_dont_update_registry_http() {\n    let _server = setup_http();\n    bump_version_dont_update_registry(str![[r#\"\n[CHECKING] bar v0.6.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\n#[cargo_test]\nfn bump_version_dont_update_registry_git() {\n    bump_version_dont_update_registry(str![[r#\"\n[CHECKING] bar v0.6.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]);\n}\n\nfn bump_version_dont_update_registry(expected: impl IntoData) {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = { path = \"baz\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                remote = \"0.3\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"remote\", \"0.3.4\").publish();\n\n    p.cargo(\"check\").run();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n        [package]\n        name = \"bar\"\n        version = \"0.6.0\"\n        edition = \"2015\"\n        authors = []\n\n        [dependencies]\n        baz = { path = \"baz\" }\n        \"#,\n    );\n\n    p.cargo(\"check\").with_stderr_data(expected).run();\n}\n\n#[cargo_test]\nfn toml_lies_but_index_is_truth_http() {\n    let _server = setup_http();\n    toml_lies_but_index_is_truth();\n}\n\n#[cargo_test]\nfn toml_lies_but_index_is_truth_git() {\n    toml_lies_but_index_is_truth();\n}\n\nfn toml_lies_but_index_is_truth() {\n    Package::new(\"foo\", \"0.2.0\").publish();\n    Package::new(\"bar\", \"0.3.0\")\n        .dep(\"foo\", \"0.2.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.3.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate foo;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.3\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn vv_prints_warnings_http() {\n    let _server = setup_http();\n    vv_prints_warnings();\n}\n\n#[cargo_test]\nfn vv_prints_warnings_git() {\n    vv_prints_warnings();\n}\n\nfn vv_prints_warnings() {\n    Package::new(\"foo\", \"0.2.0\")\n        .file(\n            \"src/lib.rs\",\n            \"#![deny(warnings)] fn foo() {} // unused function\",\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"fo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"0.2\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -vv\").run();\n}\n\n#[cargo_test]\nfn bad_and_or_malicious_packages_rejected_http() {\n    let _server = setup_http();\n    bad_and_or_malicious_packages_rejected(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.2.0 (registry `dummy-registry`)\n[ERROR] failed to download replaced source registry `crates-io`\n\nCaused by:\n  failed to unpack package `foo v0.2.0 (registry `dummy-registry`)`\n\nCaused by:\n  invalid tarball downloaded, contains a file at \"foo-0.1.0/src/lib.rs\" which isn't under \"foo-0.2.0\"\n\n\"#]]);\n}\n\n#[cargo_test]\nfn bad_and_or_malicious_packages_rejected_git() {\n    bad_and_or_malicious_packages_rejected(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.2.0 (registry `dummy-registry`)\n[ERROR] failed to download replaced source registry `crates-io`\n\nCaused by:\n  failed to unpack package `foo v0.2.0 (registry `dummy-registry`)`\n\nCaused by:\n  invalid tarball downloaded, contains a file at \"foo-0.1.0/src/lib.rs\" which isn't under \"foo-0.2.0\"\n\n\"#]]);\n}\n\nfn bad_and_or_malicious_packages_rejected(expected: impl IntoData) {\n    Package::new(\"foo\", \"0.2.0\")\n        .extra_file(\"foo-0.1.0/src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"fo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"0.2\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -vv\")\n        .with_status(101)\n        .with_stderr_data(expected)\n        .run();\n}\n\n#[cargo_test]\nfn git_init_templatedir_missing_http() {\n    let _server = setup_http();\n    git_init_templatedir_missing();\n}\n\n#[cargo_test]\nfn git_init_templatedir_missing_git() {\n    git_init_templatedir_missing();\n}\n\nfn git_init_templatedir_missing() {\n    Package::new(\"foo\", \"0.2.0\").dep(\"bar\", \"*\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"fo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"0.2\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    remove_dir_all(paths::home().join(\".cargo/registry\")).unwrap();\n    fs::write(\n        paths::home().join(\".gitconfig\"),\n        r#\"\n            [init]\n            templatedir = nowhere\n        \"#,\n    )\n    .unwrap();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn rename_deps_and_features_http() {\n    let _server = setup_http();\n    rename_deps_and_features();\n}\n\n#[cargo_test]\nfn rename_deps_and_features_git() {\n    rename_deps_and_features();\n}\n\nfn rename_deps_and_features() {\n    Package::new(\"foo\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn f1() {}\")\n        .publish();\n    Package::new(\"foo\", \"0.2.0\")\n        .file(\"src/lib.rs\", \"pub fn f2() {}\")\n        .publish();\n    Package::new(\"bar\", \"0.2.0\")\n        .add_dep(\n            Dependency::new(\"foo01\", \"0.1.0\")\n                .package(\"foo\")\n                .optional(true),\n        )\n        .add_dep(Dependency::new(\"foo02\", \"0.2.0\").package(\"foo\"))\n        .feature(\"another\", &[\"foo01\"])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate foo02;\n                #[cfg(feature = \"foo01\")]\n                extern crate foo01;\n\n                pub fn foo() {\n                    foo02::f2();\n                    #[cfg(feature = \"foo01\")]\n                    foo01::f1();\n                }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.2\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n                extern crate bar;\n                fn main() { bar::foo(); }\n            \",\n        )\n        .build();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"check --features bar/foo01\").run();\n    p.cargo(\"check --features bar/another\").run();\n}\n\n#[cargo_test]\nfn ignore_invalid_json_lines_http() {\n    let _server = setup_http();\n    ignore_invalid_json_lines();\n}\n\n#[cargo_test]\nfn ignore_invalid_json_lines_git() {\n    ignore_invalid_json_lines();\n}\n\nfn ignore_invalid_json_lines() {\n    Package::new(\"foo\", \"0.1.0\").publish();\n    Package::new(\"foo\", \"0.1.1\")\n        .invalid_index_line(true)\n        .publish();\n    Package::new(\"foo\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = '0.1.0'\n                foo02 = { version = '0.2.0', package = 'foo' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn invalid_json_lines_error() {\n    Package::new(\"foo\", \"0.1.0\")\n        .rust_version(\"1.0\")\n        .schema_version(2)\n        .publish();\n    Package::new(\"foo\", \"0.1.1\")\n        // Bad name field, too corrupt to use\n        .invalid_index_line(true)\n        .publish();\n    Package::new(\"foo\", \"0.1.2\")\n        // Bad version field, too corrupt to use\n        .index_line(\n            r#\"{\"cksum\":\"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79\",\"deps\":[],\"features\":{},\"links\":null,\"name\":\"foo\",\"vers\":\"bad\",\"yanked\":false,\"rust_version\":\"1.2345\",\"v\":1000000000}\"#,\n        )\n        .publish();\n    Package::new(\"foo\", \"0.1.3\")\n        // Bad field, report rust version\n        .index_line(\n            r#\"{\"cksum\":\"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79\",\"deps\":[],\"features\":\"bad\",\"links\":null,\"name\":\"foo\",\"vers\":\"0.1.3\",\"yanked\":false,\"rust_version\":\"1.2345\",\"v\":1000000000}\"#,\n        )\n        .publish();\n    Package::new(\"foo\", \"0.1.4\")\n        // Bad field, report schema\n        .index_line(\n            r#\"{\"cksum\":\"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79\",\"deps\":[],\"features\":\"bad\",\"links\":null,\"name\":\"foo\",\"vers\":\"0.1.4\",\"yanked\":false,\"v\":1000000000}\"#,\n        )\n        .publish();\n    Package::new(\"foo\", \"0.1.5\")\n        // Bad field, report error\n        .index_line(\n            r#\"{\"cksum\":\"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79\",\"deps\":[],\"features\":\"bad\",\"links\":null,\"name\":\"foo\",\"vers\":\"0.1.5\",\"yanked\":false}\"#,\n        )\n        .publish();\n    Package::new(\"foo\", \"0.1.6\")\n        // Bad field with bad rust version, report schema\n        .index_line(\n            r#\"{\"cksum\":\"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79\",\"deps\":[],\"features\":\"bad\",\"links\":null,\"name\":\"foo\",\"vers\":\"0.1.6\",\"yanked\":false,\"rust_version\":\"bad\",\"v\":1000000000}\"#,\n        )\n        .publish();\n    Package::new(\"foo\", \"0.1.7\")\n        // Bad field with bad rust version and schema, report error\n        .index_line(\n            r#\"{\"cksum\":\"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79\",\"deps\":[],\"features\":\"bad\",\"links\":null,\"name\":\"foo\",\"vers\":\"0.1.7\",\"yanked\":false,\"rust_version\":\"bad\",\"v\":\"bad\"}\"#,\n        )\n        .publish();\n    Package::new(\"foo\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"0.1.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `foo = \"^0.1.1\"`\n  version 0.1.3 requires cargo 1.2345\n  version 0.1.4 requires a Cargo version that supports index version 1000000000\n  version 0.1.5's index entry is invalid\n  version 0.1.6 requires a Cargo version that supports index version 1000000000\n  version 0.1.7's index entry is invalid\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `a v0.5.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n    p.cargo(\"generate-lockfile\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `foo = \"^0.1.1\"`\n  version 0.1.3 requires cargo 1.2345\n  version 0.1.4 requires a Cargo version that supports index version 1000000000\n  version 0.1.5's index entry is invalid\n  version 0.1.6 requires a Cargo version that supports index version 1000000000\n  version 0.1.7's index entry is invalid\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `a v0.5.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn readonly_registry_still_works_http() {\n    let _server = setup_http();\n    readonly_registry_still_works();\n}\n\n#[cargo_test]\nfn readonly_registry_still_works_git() {\n    readonly_registry_still_works();\n}\n\nfn readonly_registry_still_works() {\n    Package::new(\"foo\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = '0.1.0'\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n    p.cargo(\"fetch --locked\").run();\n    chmod_readonly(&paths::home(), true);\n    p.cargo(\"check\").run();\n    // make sure we un-readonly the files afterwards so \"cargo clean\" can remove them (#6934)\n    chmod_readonly(&paths::home(), false);\n\n    fn chmod_readonly(path: &Path, readonly: bool) {\n        for entry in t!(path.read_dir()) {\n            let entry = t!(entry);\n            let path = entry.path();\n            if t!(entry.file_type()).is_dir() {\n                chmod_readonly(&path, readonly);\n            } else {\n                set_readonly(&path, readonly);\n            }\n        }\n        set_readonly(path, readonly);\n    }\n\n    fn set_readonly(path: &Path, readonly: bool) {\n        let mut perms = t!(path.metadata()).permissions();\n        perms.set_readonly(readonly);\n        t!(fs::set_permissions(path, perms));\n    }\n}\n\n#[cargo_test(ignore_windows = \"On Windows setting file attributes is a bit complicated\")]\nfn inaccessible_registry_cache_still_works() {\n    Package::new(\"foo\", \"0.1.0\").publish();\n    Package::new(\"fo2\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = '0.1.0'\n                fo2 = '0.1.0'\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n    p.cargo(\"fetch --locked\").run();\n\n    let cache_path = inner_dir(&paths::cargo_home().join(\"registry/index\")).join(\".cache\");\n    let f_cache_path = cache_path.join(\"3/f\");\n\n    // Remove the permissions from the cache path that contains the \"foo\" crate\n    set_permissions(&f_cache_path, 0o000);\n\n    // Now run a build and make sure we properly build and warn the user\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[WARNING] failed to write cache, path: [ROOT]/home/.cargo/registry/index/-[HASH]/.cache/3/f/fo[..], [ERROR] Permission denied (os error 13)\n[COMPILING] fo[..] v0.1.0\n[COMPILING] fo[..] v0.1.0\n[COMPILING] a v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    // make sure we add the permissions to the files afterwards so \"cargo clean\" can remove them (#6934)\n    set_permissions(&f_cache_path, 0o777);\n\n    #[cfg_attr(windows, allow(unused_variables))]\n    fn set_permissions(path: &Path, permissions: u32) {\n        #[cfg(not(windows))]\n        {\n            use std::os::unix::fs::PermissionsExt;\n            let mut perms = t!(path.metadata()).permissions();\n            perms.set_mode(permissions);\n            t!(fs::set_permissions(path, perms));\n        }\n\n        #[cfg(windows)]\n        panic!(\"This test is not supported on windows. See the reason in the #[cargo_test] macro\");\n    }\n\n    fn inner_dir(path: &Path) -> PathBuf {\n        for entry in t!(path.read_dir()) {\n            let path = t!(entry).path();\n\n            if path.is_dir() {\n                return path;\n            }\n        }\n\n        panic!(\"could not find inner directory of {path:?}\");\n    }\n}\n\n#[cargo_test]\nfn registry_index_rejected_http() {\n    let _server = setup_http();\n    registry_index_rejected(\n        str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the `registry.index` config value is no longer supported\n  Use `[source]` replacement to alter the default index for crates.io.\n\n\"#]],\n        str![[r#\"\n[ERROR] the `registry.index` config value is no longer supported\nUse `[source]` replacement to alter the default index for crates.io.\n\n\"#]],\n    );\n}\n\n#[cargo_test]\nfn registry_index_rejected_git() {\n    registry_index_rejected(\n        str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  the `registry.index` config value is no longer supported\n  Use `[source]` replacement to alter the default index for crates.io.\n\n\"#]],\n        str![[r#\"\n[ERROR] the `registry.index` config value is no longer supported\nUse `[source]` replacement to alter the default index for crates.io.\n\n\"#]],\n    );\n}\n\nfn registry_index_rejected(expected_check: impl IntoData, expected_login: impl IntoData) {\n    Package::new(\"dep\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [registry]\n            index = \"https://example.com/\"\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            dep = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(expected_check)\n        .run();\n\n    p.cargo(\"login\")\n        .with_status(101)\n        .with_stderr_data(expected_login)\n        .run();\n}\n\n#[cargo_test]\nfn package_lock_inside_package_is_overwritten() {\n    let registry = registry::init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\".cargo-ok\", \"\")\n        .publish();\n\n    p.cargo(\"check\").run();\n\n    let id = SourceId::for_registry(registry.index_url()).unwrap();\n    let hash = cargo::util::hex::short_hash(&id);\n    let ok = paths::cargo_home()\n        .join(\"registry\")\n        .join(\"src\")\n        .join(format!(\"-{}\", hash))\n        .join(\"bar-0.0.1\")\n        .join(\".cargo-ok\");\n\n    assert_eq!(ok.metadata().unwrap().len(), 7);\n}\n\n#[cargo_test]\nfn package_lock_as_a_symlink_inside_package_is_overwritten() {\n    let registry = registry::init();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\")\n        .file(\"src/lib.rs\", \"pub fn f() {}\")\n        .symlink(\".cargo-ok\", \"src/lib.rs\")\n        .publish();\n\n    p.cargo(\"check\").run();\n\n    let id = SourceId::for_registry(registry.index_url()).unwrap();\n    let hash = cargo::util::hex::short_hash(&id);\n    let pkg_root = paths::cargo_home()\n        .join(\"registry\")\n        .join(\"src\")\n        .join(format!(\"-{}\", hash))\n        .join(\"bar-0.0.1\");\n    let ok = pkg_root.join(\".cargo-ok\");\n    let librs = pkg_root.join(\"src/lib.rs\");\n\n    // Is correctly overwritten and doesn't affect the file linked to\n    assert_eq!(ok.metadata().unwrap().len(), 7);\n    assert_eq!(fs::read_to_string(librs).unwrap(), \"pub fn f() {}\");\n}\n\n#[cargo_test]\nfn ignores_unknown_index_version_http() {\n    let _server = setup_http();\n    ignores_unknown_index_version(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v1.0.0\n\n\"#]]);\n}\n\n#[cargo_test]\nfn ignores_unknown_index_version_git() {\n    ignores_unknown_index_version(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v1.0.0\n\n\"#]]);\n}\n\nfn ignores_unknown_index_version(expected: impl IntoData) {\n    // If the version field is not understood, it is ignored.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.1\")\n        .schema_version(u32::MAX)\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"tree\").with_stdout_data(expected).run();\n}\n\n#[cargo_test]\nfn unknown_index_version_error() {\n    Package::new(\"bar\", \"0.0.1\").publish();\n    // If the version field is not understood, it is ignored.\n    Package::new(\"bar\", \"1.0.1\")\n        .schema_version(u32::MAX)\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `bar = \"^1.0\"`\n  version 1.0.1 requires a Cargo version that supports index version 4294967295\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.1.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n    p.cargo(\"generate-lockfile\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `bar = \"^1.0\"`\n  version 1.0.1 requires a Cargo version that supports index version 4294967295\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.1.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unknown_index_version_with_msrv_error() {\n    Package::new(\"bar\", \"0.0.1\").publish();\n    // If the version field is not understood, it is ignored.\n    Package::new(\"bar\", \"1.0.1\")\n        .schema_version(u32::MAX)\n        .rust_version(\"1.2345\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `bar = \"^1.0\"`\n  version 1.0.1 requires cargo 1.2345\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.1.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn protocol() {\n    cargo_process(\"install bar\")\n        .with_status(101)\n        .env(\"CARGO_REGISTRIES_CRATES_IO_PROTOCOL\", \"invalid\")\n        .with_stderr_data(str![[r#\"\n[ERROR] unsupported registry protocol `invalid` (defined in environment variable `CARGO_REGISTRIES_CRATES_IO_PROTOCOL`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn http_requires_trailing_slash() {\n    cargo_process(\"install bar --index sparse+https://invalid.crates.io/test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] sparse registry url must end in a slash `/`: sparse+https://invalid.crates.io/test\n\n\"#]])\n        .run();\n}\n\n// Limit the test to debug builds so that `__CARGO_TEST_MAX_UNPACK_SIZE` will take affect.\n#[cfg(debug_assertions)]\n#[cargo_test]\nfn reach_max_unpack_size() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // Size of bar.crate is around 180 bytes.\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    p.cargo(\"check\")\n        .env(\"__CARGO_TEST_MAX_UNPACK_SIZE\", \"8\") // hit 8 bytes limit and boom!\n        .env(\"__CARGO_TEST_MAX_UNPACK_RATIO\", \"0\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[ERROR] failed to download replaced source registry `crates-io`\n\nCaused by:\n  failed to unpack package `bar v0.0.1 (registry `dummy-registry`)`\n\nCaused by:\n  failed to iterate over archive\n\nCaused by:\n  maximum limit reached when reading\n\n\"#]])\n        .run();\n\n    // Restore to the default ratio and it should compile.\n    p.cargo(\"check\")\n        .env(\"__CARGO_TEST_MAX_UNPACK_SIZE\", \"8\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn sparse_blocking_count() {\n    let fail_count = Mutex::new(0);\n    let _registry = RegistryBuilder::new()\n        .http_index()\n        .add_responder(\"/index/3/b/bar\", move |req, server| {\n            let mut fail_count = fail_count.lock().unwrap();\n            if *fail_count < 1 {\n                *fail_count += 1;\n                server.internal_server_error(req)\n            } else {\n                server.index(req)\n            }\n        })\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    // Ensure we have the expected number of `block_until_ready` calls.\n    // The 1st (0 transfers pending), is the deliberate extra call in `ensure_loaded` for a source.\n    // The 2nd (1 transfers pending), is the registry `config.json`.\n    // the 3rd (1 transfers pending), is the package metadata for `bar`.\n\n    p.cargo(\"check\")\n        .env(\"CARGO_LOG\", \"network::HttpRegistry::block_until_ready=trace\")\n        .with_stderr_data(str![[r#\"\n   [..] TRACE network::HttpRegistry::block_until_ready: 0 transfers pending\n[UPDATING] `dummy-registry` index\n   [..] TRACE network::HttpRegistry::block_until_ready: 1 transfers pending\n   [..] TRACE network::HttpRegistry::block_until_ready: 1 transfers pending\n[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `[..]/index/3/b/bar` ([..]), got 500\nbody:\ninternal server error\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn sparse_retry_single() {\n    let fail_count = Mutex::new(0);\n    let _registry = RegistryBuilder::new()\n        .http_index()\n        .add_responder(\"/index/3/b/bar\", move |req, server| {\n            let mut fail_count = fail_count.lock().unwrap();\n            if *fail_count < 2 {\n                *fail_count += 1;\n                server.internal_server_error(req)\n            } else {\n                server.index(req)\n            }\n        })\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 500\nbody:\ninternal server error\n[WARNING] spurious network error (2 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 500\nbody:\ninternal server error\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn sparse_retry_multiple() {\n    // Tests retry behavior of downloading lots of packages with various\n    // failure rates accessing the sparse index.\n\n    // The index is the number of retries, the value is the number of packages\n    // that retry that number of times. Thus 50 packages succeed on first try,\n    // 25 on second, etc.\n    const RETRIES: &[u32] = &[50, 25, 12, 6];\n\n    let pkgs: Vec<_> = RETRIES\n        .iter()\n        .enumerate()\n        .flat_map(|(retries, num)| {\n            (0..*num)\n                .into_iter()\n                .map(move |n| (retries as u32, format!(\"{}-{n}-{retries}\", rand_prefix())))\n        })\n        .collect();\n\n    let mut builder = RegistryBuilder::new().http_index();\n    let fail_counts: Arc<Mutex<Vec<u32>>> = Arc::new(Mutex::new(vec![0; pkgs.len()]));\n    let mut cargo_toml = r#\"\n        [package]\n        name = \"foo\"\n        version = \"0.1.0\"\n        edition = \"2015\"\n\n        [dependencies]\n        \"#\n    .to_string();\n    // The expected stderr output.\n    let mut expected = \"\\\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n\"\n    .to_string();\n    for (n, (retries, name)) in pkgs.iter().enumerate() {\n        let count_clone = fail_counts.clone();\n        let retries = *retries;\n        let ab = &name[..2];\n        let cd = &name[2..4];\n        builder = builder.add_responder(format!(\"/index/{ab}/{cd}/{name}\"), move |req, server| {\n            let mut fail_counts = count_clone.lock().unwrap();\n            if fail_counts[n] < retries {\n                fail_counts[n] += 1;\n                server.internal_server_error(req)\n            } else {\n                server.index(req)\n            }\n        });\n        write!(&mut cargo_toml, \"{name} = \\\"1.0.0\\\"\\n\").unwrap();\n        for retry in 0..retries {\n            let remain = 3 - retry;\n            write!(\n                &mut expected,\n                \"[WARNING] spurious network error ({remain} {} remaining): \\\n                failed to get successful HTTP response from \\\n                `http://127.0.0.1:[..]/{ab}/{cd}/{name}` (127.0.0.1), got 500\\n\\\n                body:\\n\\\n                internal server error\\n\",\n                if remain != 1 { \"tries\" } else { \"try\" }\n            )\n            .unwrap();\n        }\n        write!(\n            &mut expected,\n            \"\\\n[DOWNLOADED] {name} v1.0.0 (registry `dummy-registry`)\n\"\n        )\n        .unwrap();\n    }\n    write!(\n        &mut expected,\n        \"\\\n[LOCKING] 93 packages to latest compatible versions\n\"\n    )\n    .unwrap();\n    let _server = builder.build();\n    for (_, name) in &pkgs {\n        Package::new(name, \"1.0.0\").publish();\n    }\n    let p = project()\n        .file(\"Cargo.toml\", &cargo_toml)\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .with_stderr_data(IntoData::unordered(expected))\n        .run();\n}\n\n#[cargo_test]\nfn dl_retry_single() {\n    // Tests retry behavior of downloading a package.\n    // This tests a single package which exercises the code path that causes\n    // it to block.\n    let fail_count = Mutex::new(0);\n    let _server = RegistryBuilder::new()\n        .http_index()\n        .add_responder(\"/dl/bar/1.0.0/download\", move |req, server| {\n            let mut fail_count = fail_count.lock().unwrap();\n            if *fail_count < 2 {\n                *fail_count += 1;\n                server.internal_server_error(req)\n            } else {\n                server.dl(req)\n            }\n        })\n        .build();\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 500\nbody:\ninternal server error\n[WARNING] spurious network error (2 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 500\nbody:\ninternal server error\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n\n\"#]]).run();\n}\n\n/// Creates a random prefix to randomly spread out the package names\n/// to somewhat evenly distribute the different failures at different\n/// points.\nfn rand_prefix() -> String {\n    use rand::RngExt;\n    const CHARS: &[u8] = b\"abcdefghijklmnopqrstuvwxyz\";\n    let mut rng = rand::rng();\n    (0..5)\n        .map(|_| CHARS[rng.random_range(0..CHARS.len())] as char)\n        .collect()\n}\n\n#[cargo_test]\nfn dl_retry_multiple() {\n    // Tests retry behavior of downloading lots of packages with various\n    // failure rates.\n\n    // The index is the number of retries, the value is the number of packages\n    // that retry that number of times. Thus 50 packages succeed on first try,\n    // 25 on second, etc.\n    const RETRIES: &[u32] = &[50, 25, 12, 6];\n\n    let pkgs: Vec<_> = RETRIES\n        .iter()\n        .enumerate()\n        .flat_map(|(retries, num)| {\n            (0..*num)\n                .into_iter()\n                .map(move |n| (retries as u32, format!(\"{}-{n}-{retries}\", rand_prefix())))\n        })\n        .collect();\n\n    let mut builder = RegistryBuilder::new().http_index();\n    let fail_counts: Arc<Mutex<Vec<u32>>> = Arc::new(Mutex::new(vec![0; pkgs.len()]));\n    let mut cargo_toml = r#\"\n        [package]\n        name = \"foo\"\n        version = \"0.1.0\"\n        edition = \"2015\"\n\n        [dependencies]\n        \"#\n    .to_string();\n    // The expected stderr output.\n    let mut expected = \"\\\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n\"\n    .to_string();\n    for (n, (retries, name)) in pkgs.iter().enumerate() {\n        let count_clone = fail_counts.clone();\n        let retries = *retries;\n        builder =\n            builder.add_responder(format!(\"/dl/{name}/1.0.0/download\"), move |req, server| {\n                let mut fail_counts = count_clone.lock().unwrap();\n                if fail_counts[n] < retries {\n                    fail_counts[n] += 1;\n                    server.internal_server_error(req)\n                } else {\n                    server.dl(req)\n                }\n            });\n        write!(&mut cargo_toml, \"{name} = \\\"1.0.0\\\"\\n\").unwrap();\n        for retry in 0..retries {\n            let remain = 3 - retry;\n            write!(\n                &mut expected,\n                \"[WARNING] spurious network error ({remain} {} remaining): \\\n                failed to get successful HTTP response from \\\n                `http://127.0.0.1:[..]/dl/{name}/1.0.0/download` (127.0.0.1), got 500\\n\\\n                body:\\n\\\n                internal server error\\n\",\n                if remain != 1 { \"tries\" } else { \"try\" }\n            )\n            .unwrap();\n        }\n        write!(\n            &mut expected,\n            \"[DOWNLOADED] {name} v1.0.0 (registry `dummy-registry`)\\n\"\n        )\n        .unwrap();\n    }\n    write!(\n        &mut expected,\n        \"[LOCKING] 93 packages to latest compatible versions\\n\"\n    )\n    .unwrap();\n    let _server = builder.build();\n    for (_, name) in &pkgs {\n        Package::new(name, \"1.0.0\").publish();\n    }\n    let p = project()\n        .file(\"Cargo.toml\", &cargo_toml)\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .with_stderr_data(IntoData::unordered(expected))\n        .run();\n}\n\n#[cargo_test]\nfn retry_too_many_requests() {\n    let fail_count = Mutex::new(0);\n    let _registry = RegistryBuilder::new()\n        .http_index()\n        .add_responder(\"/index/3/b/bar\", move |req, server| {\n            let mut fail_count = fail_count.lock().unwrap();\n            if *fail_count < 1 {\n                *fail_count += 1;\n                server.too_many_requests(req, std::time::Duration::from_secs(1))\n            } else {\n                server.index(req)\n            }\n        })\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"bar\", \"0.0.1\").publish();\n\n    p.cargo(\"check\")\n    .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `[..]/index/3/b/bar` ([..]), got 429\nbody:\ntoo many requests, try again in 1 seconds\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn deleted_entry() {\n    // Checks the behavior when a package is removed from the index.\n    // This is done occasionally on crates.io to handle things like\n    // copyright takedowns.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // First, test removing a single version, but leaving an older version.\n    Package::new(\"bar\", \"0.1.0\").publish();\n    let bar_path = Path::new(\"3/b/bar\");\n    let bar_reg_path = registry_path().join(&bar_path);\n    let old_index = fs::read_to_string(&bar_reg_path).unwrap();\n    Package::new(\"bar\", \"0.1.1\").publish();\n    p.cargo(\"tree\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.1 (registry `dummy-registry`)\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v0.1.1\n\n\"#]])\n        .run();\n\n    // Remove 0.1.1\n    fs::remove_file(paths::root().join(\"dl/bar/0.1.1/download\")).unwrap();\n    let repo = git2::Repository::open(registry_path()).unwrap();\n    let mut index = repo.index().unwrap();\n    fs::write(&bar_reg_path, &old_index).unwrap();\n    index.add_path(&bar_path).unwrap();\n    index.write().unwrap();\n    git::commit(&repo);\n\n    // With `Cargo.lock` unchanged, it shouldn't have an impact.\n    p.cargo(\"tree\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v0.1.1\n\n\"#]])\n        .run();\n\n    // Regenerating Cargo.lock should switch to old version.\n    fs::remove_file(p.root().join(\"Cargo.lock\")).unwrap();\n    p.cargo(\"tree\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`)\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v0.1.0\n\n\"#]])\n        .run();\n\n    // Remove the package entirely.\n    fs::remove_file(paths::root().join(\"dl/bar/0.1.0/download\")).unwrap();\n    let mut index = repo.index().unwrap();\n    index.remove(&bar_path, 0).unwrap();\n    index.write().unwrap();\n    git::commit(&repo);\n    fs::remove_file(&bar_reg_path).unwrap();\n\n    // With `Cargo.lock` unchanged, it shouldn't have an impact.\n    p.cargo(\"tree\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v0.1.0\n\n\"#]])\n        .run();\n\n    // Regenerating Cargo.lock should fail.\n    fs::remove_file(p.root().join(\"Cargo.lock\")).unwrap();\n    p.cargo(\"tree\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package named `bar` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.1.0 ([ROOT]/foo)`\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn corrupted_ok_overwritten() {\n    // Checks what happens if .cargo-ok gets truncated, such as if the file is\n    // created, but the flush/close is interrupted.\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n\n\"#]])\n        .run();\n    let ok = glob::glob(\n        paths::home()\n            .join(\".cargo/registry/src/*/bar-1.0.0/.cargo-ok\")\n            .to_str()\n            .unwrap(),\n    )\n    .unwrap()\n    .next()\n    .unwrap()\n    .unwrap();\n    // Simulate cargo being interrupted, or filesystem corruption.\n    fs::write(&ok, \"\").unwrap();\n    assert_eq!(fs::read_to_string(&ok).unwrap(), \"\");\n    p.cargo(\"fetch\").with_stderr_data(\"\").run();\n    assert_eq!(fs::read_to_string(&ok).unwrap(), r#\"{\"v\":1}\"#);\n}\n\n#[cargo_test]\nfn not_found_permutations() {\n    // Test for querying permutations for a missing dependency.\n    let misses = Arc::new(Mutex::new(Vec::new()));\n    let misses2 = misses.clone();\n    let _registry = RegistryBuilder::new()\n        .http_index()\n        .not_found_handler(move |req, _server| {\n            let mut misses = misses2.lock().unwrap();\n            misses.push(req.url.path().to_string());\n            Response {\n                code: 404,\n                headers: vec![],\n                body: b\"not found\".to_vec(),\n            }\n        })\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a-b_c = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package named `a-b_c` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n    let mut misses = misses.lock().unwrap();\n    misses.sort();\n    assert_eq!(\n        &*misses,\n        &[\n            \"/index/a-/b-/a-b-c\",\n            \"/index/a-/b_/a-b_c\",\n            \"/index/a_/b_/a_b_c\"\n        ]\n    );\n}\n\n#[cargo_test]\nfn default_auth_error() {\n    // Check for the error message for an authentication error when default is set.\n    let crates_io = RegistryBuilder::new().http_api().build();\n    let _alternative = RegistryBuilder::new().http_api().alternative().build();\n\n    paths::home().join(\".cargo/credentials.toml\").rm_rf();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Test output before setting the default.\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] no token found, please run `cargo login`\nor use environment variable CARGO_REGISTRY_TOKEN\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    p.cargo(\"publish --no-verify --registry alternative\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] no token found for `alternative`, please run `cargo login --registry alternative`\nor use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    // Test the output with the default.\n    cargo_util::paths::append(\n        &paths::cargo_home().join(\"config.toml\"),\n        br#\"\n            [registry]\n            default = \"alternative\"\n        \"#,\n    )\n    .unwrap();\n\n    p.cargo(\"publish --no-verify\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] no token found for `alternative`, please run `cargo login --registry alternative`\nor use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    p.cargo(\"publish --no-verify --registry crates-io\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] no token found, please run `cargo login --registry crates-io`\nor use environment variable CARGO_REGISTRY_TOKEN\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\nconst SAMPLE_HEADERS: &[&str] = &[\n    \"x-amz-cf-pop: SFO53-P2\",\n    \"x-amz-cf-id: vEc3osJrCAXVaciNnF4Vev-hZFgnYwmNZtxMKRJ5bF6h9FTOtbTMnA==\",\n    \"x-cache: Hit from cloudfront\",\n    \"server: AmazonS3\",\n    \"x-amz-version-id: pvsJYY_JGsWiSETZvLJKb7DeEW5wWq1W\",\n    \"x-amz-server-side-encryption: AES256\",\n    \"content-type: text/plain\",\n    \"via: 1.1 bcbc5b46216015493e082cfbcf77ef10.cloudfront.net (CloudFront)\",\n];\n\n#[cargo_test]\nfn debug_header_message_index() {\n    // The error message should include some headers for debugging purposes.\n    let _server = RegistryBuilder::new()\n        .http_index()\n        .add_responder(\"/index/3/b/bar\", |_, _| Response {\n            code: 503,\n            headers: SAMPLE_HEADERS.iter().map(|s| s.to_string()).collect(),\n            body: b\"Please slow down\".to_vec(),\n        })\n        .build();\n    Package::new(\"bar\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 503\nbody:\nPlease slow down\n[WARNING] spurious network error (2 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 503\nbody:\nPlease slow down\n[WARNING] spurious network error (1 try remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 503\nbody:\nPlease slow down\n[ERROR] failed to get `bar` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to query replaced source registry `crates-io`\n\nCaused by:\n  download of 3/b/bar failed\n\nCaused by:\n  failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 503\n  debug headers:\n  x-amz-cf-pop: SFO53-P2\n  x-amz-cf-id: vEc3osJrCAXVaciNnF4Vev-hZFgnYwmNZtxMKRJ5bF6h9FTOtbTMnA==\n  x-cache: Hit from cloudfront\n  body:\n  Please slow down\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn debug_header_message_dl() {\n    // Same as debug_header_message_index, but for the dl endpoint which goes\n    // through a completely different code path.\n    let _server = RegistryBuilder::new()\n        .http_index()\n        .add_responder(\"/dl/bar/1.0.0/download\", |_, _| Response {\n            code: 503,\n            headers: SAMPLE_HEADERS.iter().map(|s| s.to_string()).collect(),\n            body: b\"Please slow down\".to_vec(),\n        })\n        .build();\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 503\nbody:\nPlease slow down\n[WARNING] spurious network error (2 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 503\nbody:\nPlease slow down\n[WARNING] spurious network error (1 try remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 503\nbody:\nPlease slow down\n[ERROR] failed to download from `http://127.0.0.1:[..]/dl/bar/1.0.0/download`\n\nCaused by:\n  failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 503\n  debug headers:\n  x-amz-cf-pop: SFO53-P2\n  x-amz-cf-id: vEc3osJrCAXVaciNnF4Vev-hZFgnYwmNZtxMKRJ5bF6h9FTOtbTMnA==\n  x-cache: Hit from cloudfront\n  body:\n  Please slow down\n\n\"#]])\n        .run();\n}\n\n#[cfg(unix)]\n#[cargo_test]\nfn set_mask_during_unpacking() {\n    use std::os::unix::fs::MetadataExt;\n\n    Package::new(\"bar\", \"1.0.0\")\n        .file_with_mode(\"example.sh\", 0o777, \"#!/bin/sh\")\n        .file_with_mode(\"src/lib.rs\", 0o666, \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n\n\"#]])\n        .run();\n    let src_file_path = |path: &str| {\n        glob::glob(\n            paths::home()\n                .join(\".cargo/registry/src/*/bar-1.0.0/\")\n                .join(path)\n                .to_str()\n                .unwrap(),\n        )\n        .unwrap()\n        .next()\n        .unwrap()\n        .unwrap()\n    };\n\n    let umask = cargo::util::get_umask();\n    let metadata = fs::metadata(src_file_path(\"src/lib.rs\")).unwrap();\n    assert_eq!(metadata.mode() & 0o777, 0o666 & !umask);\n    let metadata = fs::metadata(src_file_path(\"example.sh\")).unwrap();\n    assert_eq!(metadata.mode() & 0o777, 0o777 & !umask);\n}\n\n#[cargo_test]\nfn unpack_again_when_cargo_ok_is_unrecognized() {\n    Package::new(\"bar\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n\n\"#]])\n        .run();\n\n    let src_file_path = |path: &str| {\n        glob::glob(\n            paths::home()\n                .join(\".cargo/registry/src/*/bar-1.0.0/\")\n                .join(path)\n                .to_str()\n                .unwrap(),\n        )\n        .unwrap()\n        .next()\n        .unwrap()\n        .unwrap()\n    };\n\n    // Change permissions to simulate the old behavior not respecting umask.\n    let lib_rs = src_file_path(\"src/lib.rs\");\n    let cargo_ok = src_file_path(\".cargo-ok\");\n    let mut perms = fs::metadata(&lib_rs).unwrap().permissions();\n    assert!(!perms.readonly());\n    perms.set_readonly(true);\n    fs::set_permissions(&lib_rs, perms).unwrap();\n    let ok = fs::read_to_string(&cargo_ok).unwrap();\n    assert_eq!(&ok, r#\"{\"v\":1}\"#);\n\n    p.cargo(\"fetch\").with_stderr_data(\"\").run();\n\n    // Without changing `.cargo-ok`, a unpack won't be triggered.\n    let perms = fs::metadata(&lib_rs).unwrap().permissions();\n    assert!(perms.readonly());\n\n    // Write \"ok\" to simulate the old behavior and trigger the unpack again.\n    fs::write(&cargo_ok, \"ok\").unwrap();\n\n    p.cargo(\"fetch\").with_stderr_data(\"\").run();\n\n    // Permission has been restored and `.cargo-ok` is in the new format.\n    let perms = fs::metadata(lib_rs).unwrap().permissions();\n    assert!(!perms.readonly());\n    let ok = fs::read_to_string(&cargo_ok).unwrap();\n    assert_eq!(&ok, r#\"{\"v\":1}\"#);\n}\n\n#[cargo_test]\nfn differ_only_by_metadata() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"=0.0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"baz\", \"0.0.1+b\").publish();\n    Package::new(\"baz\", \"0.0.1+c\").yanked(true).publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.0.1+b (registry `dummy-registry`)\n[CHECKING] baz v0.0.1+b\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    Package::new(\"baz\", \"0.0.1+d\").publish();\n\n    p.cargo(\"clean\").run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] baz v0.0.1+b\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn differ_only_by_metadata_with_lockfile() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"=0.0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"baz\", \"0.0.1+a\").publish();\n    Package::new(\"baz\", \"0.0.1+b\").publish();\n    Package::new(\"baz\", \"0.0.1+c\").publish();\n\n    p.cargo(\"update --package baz --precise 0.0.1+b\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] baz v0.0.1+c -> v0.0.1+b\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.0.1+b (registry `dummy-registry`)\n[CHECKING] baz v0.0.1+b\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn builtin_source_replacement() {\n    // errors for builtin source replacement of crates.io\n    // should not include mention of source replacement in the error message.\n    let server = RegistryBuilder::new().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bad-cksum = \">= 0.0.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    let pkg = Package::new(\"bad-cksum\", \"0.0.1\");\n    pkg.publish();\n    t!(File::create(&pkg.archive_dst()));\n\n    p.cargo(\"check -v\")\n        .replace_crates_io(&server.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bad-cksum v0.0.1\n[ERROR] failed to verify the checksum of `bad-cksum v0.0.1`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn builtin_source_replacement_no_vendor_error() {\n    // errors for builtin source replacement of crates.io\n    // should not mention outdated vendor dependencies\n    let server = RegistryBuilder::new().build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [dependencies]\n                dep = \"0.2.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    let pkg = Package::new(\"dep\", \"0.1.0\");\n    pkg.publish();\n\n    p.cargo(\"check -v\")\n        .replace_crates_io(&server.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] failed to select a version for the requirement `dep = \"^0.2.0\"`\ncandidate versions found which didn't match: 0.1.0\nlocation searched: crates.io index\nrequired by package `foo v0.0.1 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn deterministic_mtime() {\n    let registry = registry::init();\n    Package::new(\"foo\", \"0.1.0\")\n        // content doesn't matter, we just want to check mtime\n        .file(\"Cargo.lock\", \"\")\n        .file(\".cargo_vcs_info.json\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                edition = \"2015\"\n\n                [dependencies]\n                foo = '0.1.0'\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch\").run();\n\n    let id = SourceId::for_registry(registry.index_url()).unwrap();\n    let hash = cargo::util::hex::short_hash(&id);\n    let pkg_root = paths::cargo_home()\n        .join(\"registry\")\n        .join(\"src\")\n        .join(format!(\"-{hash}\"))\n        .join(\"foo-0.1.0\");\n\n    // Generated files should have deterministic mtime after unpacking.\n    assert_deterministic_mtime(pkg_root.join(\"Cargo.lock\"));\n    assert_deterministic_mtime(pkg_root.join(\"Cargo.toml\"));\n    assert_deterministic_mtime(pkg_root.join(\".cargo_vcs_info.json\"));\n}\n\n#[cargo_test]\nfn symlink_and_directory() {\n    // Tests for symlink and directory entry in a tar file. The tar crate\n    // would incorrectly change the permissions of the symlink destination,\n    // which could be anywhere on the filesystem.\n    let victim = paths::root().join(\"victim\");\n    fs::create_dir(&victim).unwrap();\n    #[cfg(unix)]\n    {\n        use std::os::unix::fs::PermissionsExt;\n        let perm = fs::Permissions::from_mode(0o700);\n        fs::set_permissions(&victim, perm).unwrap();\n        assert_eq!(\n            victim.metadata().unwrap().permissions().mode() & 0o777,\n            0o700\n        );\n    }\n\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"\")\n        .symlink(\"smuggled\", victim.to_str().unwrap())\n        .directory(\"smuggled\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[ERROR] failed to download replaced source registry `crates-io`\n\nCaused by:\n  failed to unpack package `bar v1.0.0 (registry `dummy-registry`)`\n\nCaused by:\n  failed to unpack entry at `bar-1.0.0/smuggled`\n\nCaused by:\n  failed to unpack `[ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/smuggled`\n\nCaused by:\n  [..] when creating dir [ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/smuggled\n\n\"#]])\n        .run();\n\n    #[cfg(unix)]\n    {\n        // Permissions should not change.\n        use std::os::unix::fs::PermissionsExt;\n        assert_eq!(\n            victim.metadata().unwrap().permissions().mode() & 0o777,\n            0o700\n        );\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/registry_auth.rs",
    "content": "//! Tests for registry authentication.\n\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::registry::{Package, RegistryBuilder, Token};\nuse cargo_test_support::str;\nuse cargo_test_support::{Execs, Project, project};\n\nfn cargo(p: &Project, s: &str) -> Execs {\n    let mut e = p.cargo(s);\n    e.masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .arg(\"-Zasymmetric-token\");\n    e.env(\n        \"CARGO_REGISTRY_GLOBAL_CREDENTIAL_PROVIDERS\",\n        \"cargo:paseto cargo:token\",\n    );\n    e\n}\n\nfn make_project() -> Project {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                version = \"0.0.1\"\n                registry = \"alternative\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    Package::new(\"bar\", \"0.0.1\").alternative(true).publish();\n    p\n}\n\n#[cargo_test]\nfn requires_credential_provider() {\n    let _registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .http_api()\n        .build();\n\n    let p = make_project();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\n[ERROR] failed to download `bar v0.0.1 (registry `alternative`)`\n\nCaused by:\n  unable to get packages from source\n\nCaused by:\n  authenticated registries require a credential-provider to be configured\n  see https://doc.rust-lang.org/cargo/reference/registry-authentication.html for details\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple() {\n    let _registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .http_index()\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"build\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `alternative`)\n[COMPILING] bar v0.0.1 (registry `alternative`)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_with_asymmetric() {\n    let _registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .http_index()\n        .token(cargo_test_support::registry::Token::rfc_key())\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"build\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `alternative`)\n[COMPILING] bar v0.0.1 (registry `alternative`)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn environment_config() {\n    let registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .no_configure_registry()\n        .no_configure_token()\n        .http_index()\n        .build();\n    let p = make_project();\n    cargo(&p, \"build\")\n        .env(\n            \"CARGO_REGISTRIES_ALTERNATIVE_INDEX\",\n            registry.index_url().as_str(),\n        )\n        .env(\"CARGO_REGISTRIES_ALTERNATIVE_TOKEN\", registry.token())\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `alternative`)\n[COMPILING] bar v0.0.1 (registry `alternative`)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn environment_token() {\n    let registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .no_configure_token()\n        .http_index()\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"build\")\n        .env(\"CARGO_REGISTRIES_ALTERNATIVE_TOKEN\", registry.token())\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `alternative`)\n[COMPILING] bar v0.0.1 (registry `alternative`)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn environment_token_with_asymmetric() {\n    let registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .no_configure_token()\n        .http_index()\n        .token(cargo_test_support::registry::Token::Keys(\n            \"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\"\n                .to_string(),\n            None,\n        ))\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"build\")\n        .env(\"CARGO_REGISTRIES_ALTERNATIVE_SECRET_KEY\", registry.key())\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `alternative`)\n[COMPILING] bar v0.0.1 (registry `alternative`)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_environment_token_with_asymmetric_subject() {\n    let registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .no_configure_token()\n        .http_index()\n        .token(cargo_test_support::registry::Token::Keys(\n            \"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\"\n                .to_string(),\n            None,\n        ))\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"build\")\n        .env(\"CARGO_REGISTRIES_ALTERNATIVE_SECRET_KEY\", registry.key())\n        .env(\n            \"CARGO_REGISTRIES_ALTERNATIVE_SECRET_KEY_SUBJECT\",\n            \"incorrect\",\n        )\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  token rejected for `alternative`, please run `cargo login --registry alternative`\n  or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN\n\nCaused by:\n  failed to get successful HTTP response from `http://127.0.0.1:[..]/index/config.json`, got 401\n  body:\n  Unauthorized message from server.\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn bad_environment_token_with_asymmetric_incorrect_subject() {\n    let registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .no_configure_token()\n        .http_index()\n        .token(cargo_test_support::registry::Token::rfc_key())\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"build\")\n        .env(\"CARGO_REGISTRIES_ALTERNATIVE_SECRET_KEY\", registry.key())\n        .env(\n            \"CARGO_REGISTRIES_ALTERNATIVE_SECRET_KEY_SUBJECT\",\n            \"incorrect\",\n        )\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  token rejected for `alternative`, please run `cargo login --registry alternative`\n  or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN\n\nCaused by:\n  failed to get successful HTTP response from `http://127.0.0.1:[..]/index/config.json`, got 401\n  body:\n  Unauthorized message from server.\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn bad_environment_token_with_incorrect_asymmetric() {\n    let _registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .no_configure_token()\n        .http_index()\n        .token(cargo_test_support::registry::Token::Keys(\n            \"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\"\n                .to_string(),\n            None,\n        ))\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"build\")\n        .env(\n            \"CARGO_REGISTRIES_ALTERNATIVE_SECRET_KEY\",\n            \"k3.secret.9Vxr5hVlI_g_orBZN54vPz20bmB4O76wB_MVqUSuJJJqHFLwP8kdn_RY5g6J6pQG\",\n        )\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  token rejected for `alternative`, please run `cargo login --registry alternative`\n  or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN\n\nCaused by:\n  failed to get successful HTTP response from `http://127.0.0.1:[..]/index/config.json`, got 401\n  body:\n  Unauthorized message from server.\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn missing_token() {\n    let _registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .no_configure_token()\n        .http_index()\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  no token found for `alternative`, please run `cargo login --registry alternative`\n  or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn missing_token_git() {\n    let _registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .no_configure_token()\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\n[ERROR] failed to download `bar v0.0.1 (registry `alternative`)`\n\nCaused by:\n  unable to get packages from source\n\nCaused by:\n  no token found for `alternative`, please run `cargo login --registry alternative`\n  or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn incorrect_token() {\n    let _registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .no_configure_token()\n        .http_index()\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"build\")\n        .env(\"CARGO_REGISTRIES_ALTERNATIVE_TOKEN\", \"incorrect\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  token rejected for `alternative`, please run `cargo login --registry alternative`\n  or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN\n\nCaused by:\n  failed to get successful HTTP response from `http://127.0.0.1:[..]/index/config.json`, got 401\n  body:\n  Unauthorized message from server.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn incorrect_token_git() {\n    let _registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .no_configure_token()\n        .http_api()\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"build\")\n        .env(\"CARGO_REGISTRIES_ALTERNATIVE_TOKEN\", \"incorrect\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[ERROR] failed to download from `http://127.0.0.1:[..]/dl/bar/0.0.1/download`\n\nCaused by:\n  failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/0.0.1/download` (127.0.0.1), got 401\n  body:\n  Unauthorized message from server.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn anonymous_alt_registry() {\n    // An alternative registry that requires auth, but is not in the config.\n    let registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .no_configure_token()\n        .no_configure_registry()\n        .http_index()\n        .build();\n\n    let p = make_project();\n    cargo(&p, &format!(\"install --index {} bar\", registry.index_url()))\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index\n[ERROR] no token found for `sparse+http://127.0.0.1:[..]/index/`\nconsider setting up an alternate registry in Cargo's configuration\nas described by https://doc.rust-lang.org/cargo/reference/registries.html\n\n[registries]\nmy-registry = { index = \"sparse+http://127.0.0.1:[..]/index/\" }\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn login() {\n    let _registry = RegistryBuilder::new()\n        .alternative()\n        .no_configure_token()\n        .auth_required()\n        .http_index()\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"login --registry alternative\")\n        .with_stdin(\"sekrit\")\n        .run();\n}\n\n#[cargo_test]\nfn login_existing_token() {\n    let _registry = RegistryBuilder::new()\n        .alternative()\n        .auth_required()\n        .http_index()\n        .build();\n\n    let p = make_project();\n    cargo(&p, \"login --registry alternative\")\n        .with_stdin(\"sekrit\")\n        .run();\n}\n\n#[cargo_test]\nfn duplicate_index() {\n    let server = RegistryBuilder::new()\n        .alternative()\n        .no_configure_token()\n        .auth_required()\n        .build();\n    let p = make_project();\n\n    // Two alternative registries with the same index.\n    cargo(&p, \"build\")\n        .env(\n            \"CARGO_REGISTRIES_ALTERNATIVE1_INDEX\",\n            server.index_url().as_str(),\n        )\n        .env(\n            \"CARGO_REGISTRIES_ALTERNATIVE2_INDEX\",\n            server.index_url().as_str(),\n        )\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[LOCKING] 1 package to latest compatible version\n[ERROR] failed to download `bar v0.0.1 (registry `alternative`)`\n\nCaused by:\n  unable to get packages from source\n\nCaused by:\n  multiple registries are configured with the same index url 'registry+[ROOTURL]/alternative-registry': alternative1, alternative2\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn token_not_logged() {\n    // Checks that the token isn't displayed in debug output (for both HTTP\n    // index and registry API). Note that this doesn't fully verify the\n    // correct behavior since we don't have an HTTP2 server, and curl behaves\n    // significantly differently when using HTTP2.\n    let crates_io = RegistryBuilder::new()\n        .http_api()\n        .http_index()\n        .auth_required()\n        .token(Token::Plaintext(\"a-unique_token\".to_string()))\n        .build();\n    Package::new(\"bar\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    let output = cargo(&p, \"publish\")\n        .replace_crates_io(crates_io.index_url())\n        .env(\"CARGO_HTTP_DEBUG\", \"true\")\n        .env(\"CARGO_LOG\", \"trace\")\n        .run();\n    let log = String::from_utf8(output.stderr).unwrap();\n    assert_e2e().eq(\n        &log,\n        str![[r#\"\n...\n[PUBLISHED] foo v0.1.0 at registry `crates-io`\n\n\"#]],\n    );\n    let authorizations: Vec<_> = log\n        .lines()\n        .filter(|line| {\n            line.contains(\"http-debug:\") && line.to_lowercase().contains(\"authorization\")\n        })\n        .collect();\n    assert!(authorizations.iter().all(|line| line.contains(\"REDACTED\")));\n    // Total authorizations:\n    // 1. Initial config.json\n    // 2. /index/3/f/foo\n    // 3. config.json again for verification\n    // 4. /index/3/b/bar\n    // 5. config.json again for verification\n    // 6. /index/3/b/bar\n    // 7. /dl/bar/1.0.0/download\n    // 8. /api/v1/crates/new\n    // 9. config.json again for verification\n    // 10. /index/3/f/foo for the \"wait for publish\"\n    assert_eq!(authorizations.len(), 10);\n    assert!(!log.contains(\"a-unique_token\"));\n}\n"
  },
  {
    "path": "tests/testsuite/registry_overlay.rs",
    "content": "//! Tests for local-registry sources.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::{Package, RegistryBuilder, TestRegistry};\nuse cargo_test_support::str;\n\nfn setup() -> (TestRegistry, String) {\n    let alt = RegistryBuilder::new().alternative().build();\n    (\n        RegistryBuilder::new().http_index().build(),\n        alt.index_url()\n            .to_file_path()\n            .unwrap()\n            .into_os_string()\n            .into_string()\n            .unwrap(),\n    )\n}\n\n#[cargo_test]\nfn overlay_hit() {\n    let (reg, alt_path) = setup();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // baz is only in the local registry, but it gets found\n    Package::new(\"baz\", \"0.1.1\")\n        .alternative(true)\n        .local(true)\n        .publish();\n\n    p.cargo(\"check\")\n        .overlay_registry(&reg.index_url(), &alt_path)\n        .run();\n}\n\n#[cargo_test]\nfn registry_version_wins() {\n    let (reg, alt_path) = setup();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // The latest one is in the main registry, so it will get chosen.\n    Package::new(\"baz\", \"0.1.1\").publish();\n    Package::new(\"baz\", \"0.1.0\")\n        .alternative(true)\n        .local(true)\n        .publish();\n\n    p.cargo(\"check\")\n        .overlay_registry(&reg.index_url(), &alt_path)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.1.1 (registry `sparse+http://127.0.0.1:[..]/index/`)\n[CHECKING] baz v0.1.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn overlay_version_wins() {\n    let (reg, alt_path) = setup();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // The latest one is in the overlay registry, so it will get chosen.\n    Package::new(\"baz\", \"0.1.0\").publish();\n    Package::new(\"baz\", \"0.1.1\")\n        .alternative(true)\n        .local(true)\n        .publish();\n\n    p.cargo(\"check\")\n        .overlay_registry(&reg.index_url(), &alt_path)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index\n[LOCKING] 1 package to latest compatible version\n[UNPACKING] baz v0.1.1 (registry `[ROOT]/alternative-registry`)\n[CHECKING] baz v0.1.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn version_precedence() {\n    let (reg, alt_path) = setup();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // The one we want is in the main registry.\n    Package::new(\"baz\", \"0.1.1\").publish();\n    Package::new(\"baz\", \"0.1.1\")\n        .alternative(true)\n        .local(true)\n        .publish();\n\n    p.cargo(\"check\")\n        .overlay_registry(&reg.index_url(), &alt_path)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index\n[LOCKING] 1 package to latest compatible version\n[UNPACKING] baz v0.1.1 (registry `[ROOT]/alternative-registry`)\n[CHECKING] baz v0.1.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn local_depends_on_old_registry_package() {\n    let (reg, alt_path) = setup();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"baz\", \"0.0.1\").publish();\n    // A new local package can depend on an older version in the registry.\n    Package::new(\"baz\", \"0.1.1\")\n        .dep(\"baz\", \"=0.0.1\")\n        .alternative(true)\n        .local(true)\n        .publish();\n\n    p.cargo(\"check\")\n        .overlay_registry(&reg.index_url(), &alt_path)\n        .run();\n}\n\n#[cargo_test]\nfn registry_dep_depends_on_new_local_package() {\n    let (reg, alt_path) = setup();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                registry-package = \"0.1.0\"\n                workspace-package = \"0.0.1\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    Package::new(\"registry-package\", \"0.1.0\")\n        .dep(\"workspace-package\", \"0.1.0\")\n        .publish();\n    // The local overlay contains an updated version of workspace-package\n    Package::new(\"workspace-package\", \"0.1.1\")\n        .alternative(true)\n        .local(true)\n        .publish();\n\n    // The registry contains older versions of workspace-package (one of which\n    // we depend on directly).\n    Package::new(\"workspace-package\", \"0.1.0\").publish();\n    Package::new(\"workspace-package\", \"0.0.1\").publish();\n\n    p.cargo(\"check\")\n        .overlay_registry(&reg.index_url(), &alt_path)\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index\n[LOCKING] 3 packages to latest compatible versions\n[ADDING] workspace-package v0.0.1 (available: v0.1.1)\n[DOWNLOADING] crates ...\n[UNPACKING] workspace-package v0.1.1 (registry `[ROOT]/alternative-registry`)\n[DOWNLOADED] registry-package v0.1.0 (registry `sparse+http://127.0.0.1:[..]/index/`)\n[DOWNLOADED] workspace-package v0.0.1 (registry `sparse+http://127.0.0.1:[..]/index/`)\n[CHECKING] workspace-package v0.1.1\n[CHECKING] workspace-package v0.0.1\n[CHECKING] registry-package v0.1.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n// Test that we can overlay on top of alternate registries, not just crates-io.\n// Since the test framework only supports a single alternate registry, we repurpose\n// the dummy crates-io as the registry to overlay on top.\n#[cargo_test]\nfn alt_registry() {\n    let alt = RegistryBuilder::new().http_index().alternative().build();\n    let crates_io = RegistryBuilder::new().build();\n    let crates_io_path = crates_io\n        .index_url()\n        .to_file_path()\n        .unwrap()\n        .into_os_string()\n        .into_string()\n        .unwrap();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = { version = \"0.1.0\", registry = \"alternative\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // This package isn't used, but publishing it forces the creation of the registry index.\n    Package::new(\"bar\", \"0.0.1\").local(true).publish();\n    Package::new(\"baz\", \"0.1.1\").alternative(true).publish();\n\n    p.cargo(\"check\")\n        .overlay_registry(&alt.index_url(), &crates_io_path)\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/rename_deps.rs",
    "content": "//! Tests for renaming dependencies.\n\nuse crate::prelude::*;\nuse cargo_test_support::git;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::{self, Package};\nuse cargo_test_support::{basic_manifest, project, str};\n\n#[cargo_test]\nfn rename_dependency() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { version = \"0.1.0\" }\n                baz = { version = \"0.2.0\", package = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar; extern crate baz;\")\n        .build();\n\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn rename_with_different_names() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = { path = \"bar\", package = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate baz;\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"random_name\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n}\n\n#[cargo_test]\nfn lots_of_names() {\n    registry::alt_init();\n    Package::new(\"foo\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn foo1() {}\")\n        .publish();\n    Package::new(\"foo\", \"0.2.0\")\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .publish();\n    Package::new(\"foo\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn foo2() {}\")\n        .alternative(true)\n        .publish();\n\n    let g = git::repo(&paths::root().join(\"another\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn foo3() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"test\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    foo = \"0.2\"\n                    foo1 = {{ version = \"0.1\", package = \"foo\" }}\n                    foo2 = {{ version = \"0.1\", registry = \"alternative\", package = \"foo\" }}\n                    foo3 = {{ git = '{}', package = \"foo\" }}\n                    foo4 = {{ path = \"foo\", package = \"foo\" }}\n                \"#,\n                g.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n                extern crate foo;\n                extern crate foo1;\n                extern crate foo2;\n                extern crate foo3;\n                extern crate foo4;\n\n                pub fn foo() {\n                    foo::foo();\n                    foo1::foo1();\n                    foo2::foo2();\n                    foo3::foo3();\n                    foo4::foo4();\n                }\n            \",\n        )\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"pub fn foo4() {}\")\n        .build();\n\n    p.cargo(\"build -v\").run();\n}\n\n#[cargo_test]\nfn rename_and_patch() {\n    Package::new(\"foo\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { version = \"0.1\", package = \"foo\" }\n\n                [patch.crates-io]\n                foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::foo(); }\",\n        )\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"build -v\").run();\n}\n\n#[cargo_test]\nfn rename_twice() {\n    Package::new(\"foo\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { version = \"0.1\", package = \"foo\" }\n                [build-dependencies]\n                foo = { version = \"0.1\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.1.0 (registry `dummy-registry`)\n[ERROR] the crate `test v0.1.0 ([ROOT]/foo)` depends on crate `foo v0.1.0` multiple times with different names\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rename_affects_fingerprint() {\n    Package::new(\"foo\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = { version = \"0.1\", package = \"foo\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate foo;\")\n        .build();\n\n    p.cargo(\"build -v\").run();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n                [package]\n                name = \"test\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { version = \"0.1\", package = \"foo\" }\n        \"#,\n    );\n\n    p.cargo(\"build -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.1.0\n[DIRTY] test v0.1.0 ([ROOT]/foo): name of dependency changed (foo => bar)\n[COMPILING] test v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\nerror[E0463]: can't find crate for `foo`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn can_run_doc_tests() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.2.0\").publish();\n\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"0.1.0\" }\n                baz = { version = \"0.2.0\", package = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate bar;\n            extern crate baz;\n        \",\n        )\n        .build();\n\n    foo.cargo(\"test -v\").with_stderr_data(str![[r#\"\n...\n[DOCTEST] foo\n[RUNNING] `rustdoc [..]--test src/lib.rs [..] --extern bar=[ROOT]/foo/target/debug/deps/libbar-[HASH].rlib --extern baz=[ROOT]/foo/target/debug/deps/libbar-[HASH].rlib [..]`\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn features_still_work() {\n    Package::new(\"foo\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                p1 = { path = 'a', features = ['b'] }\n                p2 = { path = 'b' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"p1\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                b = { version = \"0.1\", package = \"foo\", optional = true }\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"extern crate b;\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"p2\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                b = { version = \"0.1\", package = \"bar\", optional = true }\n\n                [features]\n                default = ['b']\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"extern crate b;\")\n        .build();\n\n    p.cargo(\"build -v\").run();\n}\n\n#[cargo_test]\nfn features_not_working() {\n    Package::new(\"foo\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = 'a', package = 'p1', optional = true }\n\n                [features]\n                default = ['p1']\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"p1\", \"0.1.0\"))\n        .build();\n\n    p.cargo(\"build -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `default` includes `p1` which is neither a dependency nor another feature\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rename_with_dash() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"qwerty\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                foo-bar = { path = 'a', package = 'a' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate foo_bar;\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n}\n"
  },
  {
    "path": "tests/testsuite/replace.rs",
    "content": "//! Tests for `[replace]` table source replacement.\n\nuse crate::prelude::*;\nuse cargo_test_support::git;\nuse cargo_test_support::paths;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{basic_manifest, project, str};\n\n#[cargo_test]\nfn override_simple() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1.0\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{}' }}\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn override_with_features() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1.0\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{}', features = [\"some_feature\"] }}\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[LOCKING] 2 packages to latest compatible versions\n[WARNING] unused field in replacement for `bar`: `features`\n  |\n  = [NOTE] configure `features` in the `dependencies` entry\n[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn override_with_setting_default_features() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1.0\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{}', default-features = false, features = [\"none_default_feature\"] }}\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[LOCKING] 2 packages to latest compatible versions\n[WARNING] unused field in replacement for `bar`: `features`, `default-features`\n  |\n  = [NOTE] configure `features`, `default-features` in the `dependencies` entry\n[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn missing_version() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n\n                [replace]\n                bar = { git = 'https://example.com' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").with_status(101).with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  replacements must specify a version to replace, but `https://github.com/rust-lang/crates.io-index#bar` does not\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn invalid_semver_version() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n\n                [replace]\n                \"bar:*\" = { git = 'https://example.com' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  replacements must specify a valid semver version to replace, but `bar:*` does not\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn different_version() {\n    Package::new(\"bar\", \"0.2.0\").publish();\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n\n                [replace]\n                \"bar:0.1.0\" = \"0.2.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").with_status(101).with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  replacements cannot specify a version requirement, but found one for `https://github.com/rust-lang/crates.io-index#bar@0.1.0`\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn transitive() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"baz\", \"0.2.0\")\n        .dep(\"bar\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"extern crate bar; fn baz() { bar::bar(); }\")\n        .publish();\n\n    let foo = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    baz = \"0.2.0\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{}' }}\n                \"#,\n                foo.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.2.0 (registry `dummy-registry`)\n[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..])\n[CHECKING] baz v0.2.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn persists_across_rebuilds() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let foo = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1.0\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{}' }}\n                \"#,\n                foo.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn replace_registry_with_path() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let _ = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n\n                [replace]\n                \"bar:0.1.0\" = { path = \"../bar\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] bar v0.1.0 ([ROOT]/bar)\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn use_a_spec_to_select() {\n    Package::new(\"baz\", \"0.1.1\")\n        .file(\"src/lib.rs\", \"pub fn baz1() {}\")\n        .publish();\n    Package::new(\"baz\", \"0.2.0\").publish();\n    Package::new(\"bar\", \"0.1.1\")\n        .dep(\"baz\", \"0.2\")\n        .file(\n            \"src/lib.rs\",\n            \"extern crate baz; pub fn bar() { baz::baz3(); }\",\n        )\n        .publish();\n\n    let foo = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"baz\", \"0.2.0\"))\n        .file(\"src/lib.rs\", \"pub fn baz3() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1\"\n                    baz = \"0.1\"\n\n                    [replace]\n                    \"baz:0.2.0\" = {{ git = '{}' }}\n                \"#,\n                foo.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate bar;\n            extern crate baz;\n\n            pub fn local() {\n                baz::baz1();\n                bar::bar();\n            }\n        \",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[LOCKING] 4 packages to latest compatible versions\n[ADDING] baz v0.1.1 (available: v0.2.0)\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.1.1 (registry `dummy-registry`)\n[DOWNLOADED] bar v0.1.1 (registry `dummy-registry`)\n[CHECKING] baz v0.2.0 ([ROOTURL]/override#[..])\n[CHECKING] baz v0.1.1\n[CHECKING] bar v0.1.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn override_adds_some_deps() {\n    Package::new(\"baz\", \"0.1.1\").publish();\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let foo = git::repo(&paths::root().join(\"override\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{}' }}\n                \"#,\n                foo.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] baz v0.1.1 (registry `dummy-registry`)\n[CHECKING] baz v0.1.1\n[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    Package::new(\"baz\", \"0.1.2\").publish();\n    p.cargo(\"update\")\n        .arg(&format!(\"{}#bar\", foo.url()))\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/override`\n[UPDATING] `dummy-registry` index\n[LOCKING] 0 packages to latest compatible versions\n[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest\n\n\"#]])\n        .run();\n    p.cargo(\"update  https://github.com/rust-lang/crates.io-index#bar\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 0 packages to latest compatible versions\n[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn locked_means_locked_yes_no_seriously_i_mean_locked() {\n    // this in theory exercises #2041\n    Package::new(\"baz\", \"0.1.0\").publish();\n    Package::new(\"baz\", \"0.2.0\").publish();\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let foo = git::repo(&paths::root().join(\"override\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1\"\n                    baz = \"0.1\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{}' }}\n                \"#,\n                foo.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn override_wrong_name() {\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let foo = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    baz = \"0.1\"\n\n                    [replace]\n                    \"baz:0.1.0\" = {{ git = '{}' }}\n                \"#,\n                foo.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[ERROR] failed to get `baz` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  no matching package for override `https://github.com/rust-lang/crates.io-index#baz@0.1.0` found\n  location searched: [ROOTURL]/override\n  version required: =0.1.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn override_with_nothing() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let foo = git::repo(&paths::root().join(\"override\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{}' }}\n                \"#,\n                foo.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update [ROOTURL]/override\n\nCaused by:\n  could not find `Cargo.toml` in `[ROOT]/home/.cargo/git/checkouts/override-[HASH]/[..]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn override_wrong_version() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [replace]\n                \"bar:0.1.0\" = { git = 'https://example.com', version = '0.2.0' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").with_status(101).with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  replacements cannot specify a version requirement, but found one for `https://github.com/rust-lang/crates.io-index#bar@0.1.0`\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn multiple_specs() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1.0\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{0}' }}\n\n                    [replace.\"https://github.com/rust-lang/crates.io-index#bar:0.1.0\"]\n                    git = '{0}'\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  overlapping replacement specifications found:\n\n    * https://github.com/rust-lang/crates.io-index#bar@0.1.0\n    * https://github.com/rust-lang/crates.io-index#bar@0.1.0\n\n  both specifications match: bar v0.1.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_override_dep() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1.0\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{0}' }}\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test -p bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[LOCKING] 2 packages to latest compatible versions\n[ERROR] specification `bar` is ambiguous\n[HELP] re-run this command with one of the following specifications\n  registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0\n  git+[ROOTURL]/override#bar@0.1.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1.0\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{0}' }}\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n    p.cargo(\"update\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[LOCKING] 0 packages to latest compatible versions\n\n\"#]])\n        .run();\n}\n\n// foo -> near -> far\n// near is overridden with itself\n#[cargo_test]\nfn no_override_self() {\n    let deps = git::repo(&paths::root().join(\"override\"))\n        .file(\"far/Cargo.toml\", &basic_manifest(\"far\", \"0.1.0\"))\n        .file(\"far/src/lib.rs\", \"\")\n        .file(\n            \"near/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"near\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                far = { path = \"../far\" }\n            \"#,\n        )\n        .file(\"near/src/lib.rs\", \"#![no_std] pub extern crate far;\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    near = {{ git = '{0}' }}\n\n                    [replace]\n                    \"near:0.1.0\" = {{ git = '{0}' }}\n                \"#,\n                deps.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"#![no_std] pub extern crate near;\")\n        .build();\n\n    p.cargo(\"check --verbose\").run();\n}\n\n#[cargo_test]\nfn override_an_override() {\n    Package::new(\"chrono\", \"0.2.0\")\n        .dep(\"serde\", \"< 0.9\")\n        .publish();\n    Package::new(\"serde\", \"0.7.0\")\n        .file(\"src/lib.rs\", \"pub fn serde07() {}\")\n        .publish();\n    Package::new(\"serde\", \"0.8.0\")\n        .file(\"src/lib.rs\", \"pub fn serde08() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                chrono = \"0.2\"\n                serde = \"0.8\"\n\n                [replace]\n                \"chrono:0.2.0\" = { path = \"chrono\" }\n                \"serde:0.8.0\" = { path = \"serde\" }\n            \"#,\n        )\n        .file(\n            \"Cargo.lock\",\n            r#\"\n                [[package]]\n                name = \"foo\"\n                version = \"0.0.1\"\n                dependencies = [\n                 \"chrono 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n                 \"serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n                ]\n\n                [[package]]\n                name = \"chrono\"\n                version = \"0.2.0\"\n                source = \"registry+https://github.com/rust-lang/crates.io-index\"\n                replace = \"chrono 0.2.0\"\n\n                [[package]]\n                name = \"chrono\"\n                version = \"0.2.0\"\n                dependencies = [\n                 \"serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)\",\n                ]\n\n                [[package]]\n                name = \"serde\"\n                version = \"0.7.0\"\n                source = \"registry+https://github.com/rust-lang/crates.io-index\"\n\n                [[package]]\n                name = \"serde\"\n                version = \"0.8.0\"\n                source = \"registry+https://github.com/rust-lang/crates.io-index\"\n                replace = \"serde 0.8.0\"\n\n                [[package]]\n                name = \"serde\"\n                version = \"0.8.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            extern crate chrono;\n            extern crate serde;\n\n            pub fn foo() {\n                chrono::chrono();\n                serde::serde08_override();\n            }\n        \",\n        )\n        .file(\n            \"chrono/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"chrono\"\n                version = \"0.2.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"< 0.9\"\n            \"#,\n        )\n        .file(\n            \"chrono/src/lib.rs\",\n            \"\n            extern crate serde;\n            pub fn chrono() {\n                serde::serde07();\n            }\n        \",\n        )\n        .file(\"serde/Cargo.toml\", &basic_manifest(\"serde\", \"0.8.0\"))\n        .file(\"serde/src/lib.rs\", \"pub fn serde08_override() {}\")\n        .build();\n\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn overriding_nonexistent_no_spurious() {\n    Package::new(\"bar\", \"0.1.0\").dep(\"baz\", \"0.1\").publish();\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = { path = \"baz\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1.0\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{url}' }}\n                    \"baz:0.1.0\" = {{ git = '{url}' }}\n                \"#,\n                url = bar.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] package replacement is not used: https://github.com/rust-lang/crates.io-index#baz@0.1.0\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn no_warnings_when_replace_is_used_in_another_workspace_member() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [ \"first_crate\", \"second_crate\"]\n\n            [replace]\n            \"bar:0.1.0\" = { path = \"local_bar\" }\n            \"#,\n        )\n        .file(\n            \"first_crate/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"first_crate\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"first_crate/src/lib.rs\", \"\")\n        .file(\n            \"second_crate/Cargo.toml\",\n            &basic_manifest(\"second_crate\", \"0.1.0\"),\n        )\n        .file(\"second_crate/src/lib.rs\", \"\")\n        .file(\"local_bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"local_bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .cwd(\"first_crate\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] bar v0.1.0 ([ROOT]/foo/local_bar)\n[CHECKING] first_crate v0.1.0 ([ROOT]/foo/first_crate)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .cwd(\"second_crate\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] second_crate v0.1.0 ([ROOT]/foo/second_crate)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn replace_to_path_dep() {\n    Package::new(\"bar\", \"0.1.0\").dep(\"baz\", \"0.1\").publish();\n    Package::new(\"baz\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1.0\"\n\n                [replace]\n                \"bar:0.1.0\" = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = { path = \"baz\" }\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            \"extern crate baz; pub fn bar() { baz::baz(); }\",\n        )\n        .file(\"bar/baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"bar/baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn override_with_default_feature() {\n    Package::new(\"another\", \"0.1.0\").publish();\n    Package::new(\"another\", \"0.1.1\").dep(\"bar\", \"0.1\").publish();\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\", default-features = false }\n                another = \"0.1\"\n                another2 = { path = \"another2\" }\n\n                [replace]\n                'bar:0.1.0' = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() { bar::bar(); }\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = []\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"default\")]\n                pub fn bar() {}\n            \"#,\n        )\n        .file(\n            \"another2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"another2\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { version = \"0.1\", default-features = false }\n            \"#,\n        )\n        .file(\"another2/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"run\").run();\n}\n\n#[cargo_test]\nfn override_plus_dep() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"0.1\"\n\n                [replace]\n                'bar:0.1.0' = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = { path = \"..\" }\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] cyclic package dependency: package `bar v0.1.0 ([ROOT]/foo/bar)` depends on itself. Cycle:\npackage `bar v0.1.0 ([ROOT]/foo/bar)`\n    ... which satisfies dependency `bar = \"^0.1\"` of package `foo v0.0.1 ([ROOT]/foo)`\n    ... which satisfies path dependency `foo` of package `bar v0.1.0 ([ROOT]/foo/bar)`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn override_generic_matching_other_versions() {\n    Package::new(\"bar\", \"0.1.0+a\").publish();\n\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1.0\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{}' }}\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)`\n\nCaused by:\n  replacement specification `https://github.com/rust-lang/crates.io-index#bar@0.1.0` matched 0.1.0+a and tried to override it with 0.1.0\n  avoid matching unrelated packages by being more specific\n\n\"#]]).with_status(101).run();\n}\n\n#[cargo_test]\nfn override_respects_spec_metadata() {\n    Package::new(\"bar\", \"0.1.0+a\").publish();\n\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0+a\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1.0\"\n\n                    [replace]\n                    \"bar:0.1.0+notTheBuild\" = {{ git = '{}' }}\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[WARNING] package replacement is not used: https://github.com/rust-lang/crates.io-index#bar@0.1.0+notTheBuild\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.1.0+a (registry `dummy-registry`)\n[CHECKING] bar v0.1.0+a\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\nerror[E0425]: cannot find function `bar`[..]\n...\n[ERROR] could not compile `foo` (lib) due to 1 previous error\n\n\"#]]).with_status(101).run();\n}\n\n#[cargo_test]\nfn override_spec_metadata_is_optional() {\n    Package::new(\"bar\", \"0.1.0+a\").publish();\n\n    let bar = git::repo(&paths::root().join(\"override\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0+a\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    edition = \"2015\"\n                    authors = []\n\n                    [dependencies]\n                    bar = \"0.1.0\"\n\n                    [replace]\n                    \"bar:0.1.0\" = {{ git = '{}' }}\n                \"#,\n                bar.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            \"extern crate bar; pub fn foo() { bar::bar(); }\",\n        )\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] git repository `[ROOTURL]/override`\n[LOCKING] 2 packages to latest compatible versions\n[CHECKING] bar v0.1.0+a ([ROOTURL]/override#[..])\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/required_features.rs",
    "content": "//! Tests for targets with `required-features`.\n\nuse crate::prelude::*;\nuse cargo_test_support::install::{assert_has_installed_exe, assert_has_not_installed_exe};\nuse cargo_test_support::is_nightly;\nuse cargo_test_support::paths;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn build_bin_default_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"a\"]\n                a = []\n\n                [[bin]]\n                name = \"foo\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                extern crate foo;\n\n                #[cfg(feature = \"a\")]\n                fn test() {\n                    foo::foo();\n                }\n\n                fn main() {}\n            \"#,\n        )\n        .file(\"src/lib.rs\", r#\"#[cfg(feature = \"a\")] pub fn foo() {}\"#)\n        .build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n\n    p.cargo(\"build --no-default-features\").run();\n\n    p.cargo(\"build --bin=foo\").run();\n    assert!(p.bin(\"foo\").is_file());\n\n    p.cargo(\"build --bin=foo --no-default-features\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] target `foo` in package `foo` requires the features: `a`\nConsider enabling them by passing, e.g., `--features=\"a\"`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_bin_arg_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n\n                [[bin]]\n                name = \"foo\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --features a\").run();\n    assert!(p.bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn build_bin_multiple_required_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"a\", \"b\"]\n                a = []\n                b = [\"a\"]\n                c = []\n\n                [[bin]]\n                name = \"foo_1\"\n                path = \"src/foo_1.rs\"\n                required-features = [\"b\", \"c\"]\n\n                [[bin]]\n                name = \"foo_2\"\n                path = \"src/foo_2.rs\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"src/foo_1.rs\", \"fn main() {}\")\n        .file(\"src/foo_2.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    assert!(!p.bin(\"foo_1\").is_file());\n    assert!(p.bin(\"foo_2\").is_file());\n\n    p.cargo(\"build --features c\").run();\n\n    assert!(p.bin(\"foo_1\").is_file());\n    assert!(p.bin(\"foo_2\").is_file());\n\n    p.cargo(\"build --no-default-features\").run();\n}\n\n#[cargo_test]\nfn build_example_default_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"a\"]\n                a = []\n\n                [[example]]\n                name = \"foo\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"examples/foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --example=foo\").run();\n    assert!(p.bin(\"examples/foo\").is_file());\n\n    p.cargo(\"build --example=foo --no-default-features\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] target `foo` in package `foo` requires the features: `a`\nConsider enabling them by passing, e.g., `--features=\"a\"`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_example_arg_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n\n                [[example]]\n                name = \"foo\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"examples/foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --example=foo --features a\").run();\n    assert!(p.bin(\"examples/foo\").is_file());\n}\n\n#[cargo_test]\nfn build_example_multiple_required_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"a\", \"b\"]\n                a = []\n                b = [\"a\"]\n                c = []\n\n                [[example]]\n                name = \"foo_1\"\n                required-features = [\"b\", \"c\"]\n\n                [[example]]\n                name = \"foo_2\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"examples/foo_1.rs\", \"fn main() {}\")\n        .file(\"examples/foo_2.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --example=foo_1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] target `foo_1` in package `foo` requires the features: `b`, `c`\nConsider enabling them by passing, e.g., `--features=\"b c\"`\n\n\"#]])\n        .run();\n    p.cargo(\"build --example=foo_2\").run();\n\n    assert!(!p.bin(\"examples/foo_1\").is_file());\n    assert!(p.bin(\"examples/foo_2\").is_file());\n\n    p.cargo(\"build --example=foo_1 --features c\").run();\n    p.cargo(\"build --example=foo_2 --features c\").run();\n\n    assert!(p.bin(\"examples/foo_1\").is_file());\n    assert!(p.bin(\"examples/foo_2\").is_file());\n\n    p.cargo(\"build --example=foo_1 --no-default-features\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] target `foo_1` in package `foo` requires the features: `b`, `c`\nConsider enabling them by passing, e.g., `--features=\"b c\"`\n\n\"#]])\n        .run();\n    p.cargo(\"build --example=foo_2 --no-default-features\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] target `foo_2` in package `foo` requires the features: `a`\nConsider enabling them by passing, e.g., `--features=\"a\"`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_default_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"a\"]\n                a = []\n\n                [[test]]\n                name = \"foo\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"tests/foo.rs\", \"#[test]\\nfn test() {}\")\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest test ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"test --no-default-features\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n\n    p.cargo(\"test --test=foo\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest test ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"test --test=foo --no-default-features\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] target `foo` in package `foo` requires the features: `a`\nConsider enabling them by passing, e.g., `--features=\"a\"`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_arg_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n\n                [[test]]\n                name = \"foo\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"tests/foo.rs\", \"#[test]\\nfn test() {}\")\n        .build();\n\n    p.cargo(\"test --features a\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest test ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_multiple_required_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"a\", \"b\"]\n                a = []\n                b = [\"a\"]\n                c = []\n\n                [[test]]\n                name = \"foo_1\"\n                required-features = [\"b\", \"c\"]\n\n                [[test]]\n                name = \"foo_2\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"tests/foo_1.rs\", \"#[test]\\nfn test() {}\")\n        .file(\"tests/foo_2.rs\", \"#[test]\\nfn test() {}\")\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/foo_2.rs (target/debug/deps/foo_2-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest test ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"test --features c\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/foo_1.rs (target/debug/deps/foo_1-[HASH][EXE])\n[RUNNING] tests/foo_2.rs (target/debug/deps/foo_2-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest test ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest test ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"test --no-default-features\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_default_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"a\"]\n                a = []\n\n                [[bench]]\n                name = \"foo\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\n            \"benches/foo.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n\n            #[bench]\n            fn bench(_: &mut test::Bencher) {\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"bench --no-default-features\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n\n    p.cargo(\"bench --bench=foo\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"bench --bench=foo --no-default-features\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] target `foo` in package `foo` requires the features: `a`\nConsider enabling them by passing, e.g., `--features=\"a\"`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_arg_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n\n                [[bench]]\n                name = \"foo\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\n            \"benches/foo.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n\n            #[bench]\n            fn bench(_: &mut test::Bencher) {\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench --features a\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"bench\")]\nfn bench_multiple_required_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"a\", \"b\"]\n                a = []\n                b = [\"a\"]\n                c = []\n\n                [[bench]]\n                name = \"foo_1\"\n                required-features = [\"b\", \"c\"]\n\n                [[bench]]\n                name = \"foo_2\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\n            \"benches/foo_1.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n\n            #[bench]\n            fn bench(_: &mut test::Bencher) {\n            }\n            \"#,\n        )\n        .file(\n            \"benches/foo_2.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n\n            #[bench]\n            fn bench(_: &mut test::Bencher) {\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] benches/foo_2.rs (target/release/deps/foo_2-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"bench --features c\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] benches/foo_1.rs (target/release/deps/foo_1-[HASH][EXE])\n[RUNNING] benches/foo_2.rs (target/release/deps/foo_2-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"bench --no-default-features\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn install_default_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"a\"]\n                a = []\n\n                [[bin]]\n                name = \"foo\"\n                required-features = [\"a\"]\n\n                [[example]]\n                name = \"foo\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"examples/foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"install --path .\").run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    p.cargo(\"uninstall foo\").run();\n\n    p.cargo(\"install --path . --no-default-features\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[WARNING] none of the package's binaries are available for install using the selected features\n  bin \"foo\" requires the features: `a`\n  example \"foo\" requires the features: `a`\nConsider enabling some of the needed features by passing, e.g., `--features=\"a\"`\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n\n    p.cargo(\"install --path . --bin=foo\").run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    p.cargo(\"uninstall foo\").run();\n\n    p.cargo(\"install --path . --bin=foo --no-default-features\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to compile `foo v0.0.1 ([ROOT]/foo)`, intermediate artifacts can be found at `[ROOT]/foo/target`.\nTo reuse those artifacts with a future compilation, set the environment variable `CARGO_BUILD_BUILD_DIR` to that path.\n\nCaused by:\n  target `foo` in package `foo` requires the features: `a`\n  Consider enabling them by passing, e.g., `--features=\"a\"`\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n\n    p.cargo(\"install --path . --example=foo\").run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    p.cargo(\"uninstall foo\").run();\n\n    p.cargo(\"install --path . --example=foo --no-default-features\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] failed to compile `foo v0.0.1 ([ROOT]/foo)`, intermediate artifacts can be found at `[ROOT]/foo/target`.\nTo reuse those artifacts with a future compilation, set the environment variable `CARGO_BUILD_BUILD_DIR` to that path.\n\nCaused by:\n  target `foo` in package `foo` requires the features: `a`\n  Consider enabling them by passing, e.g., `--features=\"a\"`\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n}\n\n#[cargo_test]\nfn install_arg_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n\n                [[bin]]\n                name = \"foo\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"install --features a\").run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    p.cargo(\"uninstall foo\").run();\n}\n\n#[cargo_test]\nfn install_multiple_required_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"a\", \"b\"]\n                a = []\n                b = [\"a\"]\n                c = []\n\n                [[bin]]\n                name = \"foo_1\"\n                path = \"src/foo_1.rs\"\n                required-features = [\"b\", \"c\"]\n\n                [[bin]]\n                name = \"foo_2\"\n                path = \"src/foo_2.rs\"\n                required-features = [\"a\"]\n\n                [[example]]\n                name = \"foo_3\"\n                path = \"src/foo_3.rs\"\n                required-features = [\"b\", \"c\"]\n\n                [[example]]\n                name = \"foo_4\"\n                path = \"src/foo_4.rs\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"src/foo_1.rs\", \"fn main() {}\")\n        .file(\"src/foo_2.rs\", \"fn main() {}\")\n        .file(\"src/foo_3.rs\", \"fn main() {}\")\n        .file(\"src/foo_4.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"install --path .\").run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo_1\");\n    assert_has_installed_exe(paths::cargo_home(), \"foo_2\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo_3\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo_4\");\n    p.cargo(\"uninstall foo\").run();\n\n    p.cargo(\"install --path . --bins --examples\").run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo_1\");\n    assert_has_installed_exe(paths::cargo_home(), \"foo_2\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo_3\");\n    assert_has_installed_exe(paths::cargo_home(), \"foo_4\");\n    p.cargo(\"uninstall foo\").run();\n\n    p.cargo(\"install --path . --features c\").run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo_1\");\n    assert_has_installed_exe(paths::cargo_home(), \"foo_2\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo_3\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo_4\");\n    p.cargo(\"uninstall foo\").run();\n\n    p.cargo(\"install --path . --features c --bins --examples\")\n        .run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo_1\");\n    assert_has_installed_exe(paths::cargo_home(), \"foo_2\");\n    assert_has_installed_exe(paths::cargo_home(), \"foo_3\");\n    assert_has_installed_exe(paths::cargo_home(), \"foo_4\");\n    p.cargo(\"uninstall foo\").run();\n\n    p.cargo(\"install --path . --no-default-features\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[WARNING] none of the package's binaries are available for install using the selected features\n  bin \"foo_1\" requires the features: `b`, `c`\n  bin \"foo_2\" requires the features: `a`\n  example \"foo_3\" requires the features: `b`, `c`\n  example \"foo_4\" requires the features: `a`\nConsider enabling some of the needed features by passing, e.g., `--features=\"b c\"`\n\n\"#]])\n        .run();\n    p.cargo(\"install --path . --no-default-features --bins\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] target filter `bins` specified, but no targets matched; this is a no-op\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[WARNING] none of the package's binaries are available for install using the selected features\n  bin \"foo_1\" requires the features: `b`, `c`\n  bin \"foo_2\" requires the features: `a`\n  example \"foo_3\" requires the features: `b`, `c`\n  example \"foo_4\" requires the features: `a`\nConsider enabling some of the needed features by passing, e.g., `--features=\"b c\"`\n\n\"#]])\n        .run();\n    p.cargo(\"install --path . --no-default-features --examples\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] target filter `examples` specified, but no targets matched; this is a no-op\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[WARNING] none of the package's binaries are available for install using the selected features\n  bin \"foo_1\" requires the features: `b`, `c`\n  bin \"foo_2\" requires the features: `a`\n  example \"foo_3\" requires the features: `b`, `c`\n  example \"foo_4\" requires the features: `a`\nConsider enabling some of the needed features by passing, e.g., `--features=\"b c\"`\n\n\"#]])\n        .run();\n    p.cargo(\"install --path . --no-default-features --bins --examples\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] target filters `bins`, `examples` specified, but no targets matched; this is a no-op\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[WARNING] none of the package's binaries are available for install using the selected features\n  bin \"foo_1\" requires the features: `b`, `c`\n  bin \"foo_2\" requires the features: `a`\n  example \"foo_3\" requires the features: `b`, `c`\n  example \"foo_4\" requires the features: `a`\nConsider enabling some of the needed features by passing, e.g., `--features=\"b c\"`\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo_1\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo_2\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo_3\");\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo_4\");\n}\n\n#[cargo_test]\nfn dep_feature_in_toml() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\", features = [\"a\"] }\n\n                [[bin]]\n                name = \"foo\"\n                required-features = [\"bar/a\"]\n\n                [[example]]\n                name = \"foo\"\n                required-features = [\"bar/a\"]\n\n                [[test]]\n                name = \"foo\"\n                required-features = [\"bar/a\"]\n\n                [[bench]]\n                name = \"foo\"\n                required-features = [\"bar/a\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"examples/foo.rs\", \"fn main() {}\")\n        .file(\"tests/foo.rs\", \"#[test]\\nfn test() {}\")\n        .file(\n            \"benches/foo.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n\n            #[bench]\n            fn bench(_: &mut test::Bencher) {\n            }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n\n    // bin\n    p.cargo(\"build --bin=foo\").run();\n    assert!(p.bin(\"foo\").is_file());\n\n    // example\n    p.cargo(\"build --example=foo\").run();\n    assert!(p.bin(\"examples/foo\").is_file());\n\n    // test\n    p.cargo(\"test --test=foo\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest test ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    // bench\n    if is_nightly() {\n        p.cargo(\"bench --bench=foo\")\n            .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n            .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n            .run();\n    }\n\n    // install\n    p.cargo(\"install\").run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    p.cargo(\"uninstall foo\").run();\n}\n\n#[cargo_test]\nfn dep_feature_in_cmd_line() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [[bin]]\n                name = \"foo\"\n                required-features = [\"bar/a\"]\n\n                [[example]]\n                name = \"foo\"\n                required-features = [\"bar/a\"]\n\n                [[test]]\n                name = \"foo\"\n                required-features = [\"bar/a\"]\n\n                [[bench]]\n                name = \"foo\"\n                required-features = [\"bar/a\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"examples/foo.rs\", \"fn main() {}\")\n        .file(\n            \"tests/foo.rs\",\n            r#\"\n            #[test]\n            fn bin_is_built() {\n                let s = format!(\"target/debug/foo{}\", std::env::consts::EXE_SUFFIX);\n                let p = std::path::Path::new(&s);\n                assert!(p.exists(), \"foo does not exist\");\n            }\n            \"#,\n        )\n        .file(\n            \"benches/foo.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n\n            #[bench]\n            fn bench(_: &mut test::Bencher) {\n            }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    // This is a no-op\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(!p.bin(\"foo\").is_file());\n\n    // bin\n    p.cargo(\"build --bin=foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] target `foo` in package `foo` requires the features: `bar/a`\nConsider enabling them by passing, e.g., `--features=\"bar/a\"`\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --bin=foo --features bar/a\").run();\n    assert!(p.bin(\"foo\").is_file());\n\n    // example\n    p.cargo(\"build --example=foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] target `foo` in package `foo` requires the features: `bar/a`\nConsider enabling them by passing, e.g., `--features=\"bar/a\"`\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --example=foo --features bar/a\").run();\n    assert!(p.bin(\"examples/foo\").is_file());\n\n    // test\n    // This is a no-op, since no tests are enabled\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_stdout_data(\"\")\n        .run();\n\n    // Delete the target directory so this can check if the main.rs gets built.\n    p.build_dir().rm_rf();\n    p.cargo(\"test --test=foo --features bar/a\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bin_is_built ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    // bench\n    if is_nightly() {\n        p.cargo(\"bench\")\n            .with_stderr_data(str![[r#\"\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n            .with_stdout_data(\"\")\n            .run();\n\n        p.cargo(\"bench --bench=foo --features bar/a\")\n            .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n            .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest bench ... bench:           [AVG_ELAPSED] ns/iter (+/- [JITTER])\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n            .run();\n    }\n\n    // install\n    p.cargo(\"install --path .\")\n        .with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.0.1 ([ROOT]/foo)\n[LOCKING] 1 package to latest compatible version\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[WARNING] none of the package's binaries are available for install using the selected features\n  bin \"foo\" requires the features: `bar/a`\n  example \"foo\" requires the features: `bar/a`\nConsider enabling some of the needed features by passing, e.g., `--features=\"bar/a\"`\n\n\"#]])\n        .run();\n    assert_has_not_installed_exe(paths::cargo_home(), \"foo\");\n\n    p.cargo(\"install --features bar/a\").run();\n    assert_has_installed_exe(paths::cargo_home(), \"foo\");\n    p.cargo(\"uninstall foo\").run();\n}\n\n#[cargo_test]\nfn test_skips_compiling_bin_with_missing_required_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                a = []\n\n                [[bin]]\n                name = \"bin_foo\"\n                path = \"src/bin/foo.rs\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"src/bin/foo.rs\", \"extern crate bar; fn main() {}\")\n        .file(\"tests/foo.rs\", \"\")\n        .file(\"benches/foo.rs\", \"\")\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"test --features a -j 1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\nerror[E0463]: can't find crate for `bar`\n...\n\"#]])\n        .run();\n\n    if is_nightly() {\n        p.cargo(\"bench\")\n            .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE])\n\n\"#]])\n            .with_stdout_data(str![[r#\"\n\nrunning 0 tests\n\ntest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n            .run();\n\n        p.cargo(\"bench --features a -j 1\")\n            .with_status(101)\n            .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\nerror[E0463]: can't find crate for `bar`\n...\n\"#]])\n            .run();\n    }\n}\n\n#[cargo_test]\nfn run_default() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = []\n                a = []\n\n                [[bin]]\n                name = \"foo\"\n                required-features = [\"a\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"extern crate foo; fn main() {}\")\n        .build();\n\n    p.cargo(\"run\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] target `foo` in package `foo` requires the features: `a`\nConsider enabling them by passing, e.g., `--features=\"a\"`\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --features a\").run();\n}\n\n#[cargo_test]\nfn run_default_multiple_required_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"a\"]\n                a = []\n                b = []\n\n                [[bin]]\n                name = \"foo1\"\n                path = \"src/foo1.rs\"\n                required-features = [\"a\"]\n\n                [[bin]]\n                name = \"foo3\"\n                path = \"src/foo3.rs\"\n                required-features = [\"b\"]\n\n                [[bin]]\n                name = \"foo2\"\n                path = \"src/foo2.rs\"\n                required-features = [\"b\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/foo1.rs\", \"extern crate foo; fn main() {}\")\n        .file(\"src/foo3.rs\", \"extern crate foo; fn main() {}\")\n        .file(\"src/foo2.rs\", \"extern crate foo; fn main() {}\")\n        .build();\n\n    p.cargo(\"run\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `cargo run` could not determine which binary to run. Use the `--bin` option to specify a binary, or the `default-run` manifest key.\navailable binaries: foo1, foo2, foo3\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn renamed_required_features() {\n    // Test that required-features uses renamed package feature names.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2018\"\n\n            [[bin]]\n            name = \"x\"\n            required-features = [\"a1/f1\"]\n\n            [dependencies]\n            a1 = {path=\"a1\", package=\"a\"}\n            a2 = {path=\"a2\", package=\"a\"}\n            \"#,\n        )\n        .file(\n            \"src/bin/x.rs\",\n            r#\"\n            fn main() {\n                a1::f();\n                a2::f();\n            }\n            \"#,\n        )\n        .file(\n            \"a1/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"a\"\n            version = \"0.1.0\"\n\n            [features]\n            f1 = []\n            \"#,\n        )\n        .file(\n            \"a1/src/lib.rs\",\n            r#\"\n            pub fn f() {\n                if cfg!(feature=\"f1\") {\n                    println!(\"a1 f1\");\n                }\n            }\n            \"#,\n        )\n        .file(\n            \"a2/Cargo.toml\",\n            r#\"\n              [package]\n             name = \"a\"\n             version = \"0.2.0\"\n\n             [features]\n             f2 = []\n            \"#,\n        )\n        .file(\n            \"a2/src/lib.rs\",\n            r#\"\n            pub fn f() {\n                if cfg!(feature=\"f2\") {\n                    println!(\"a2 f2\");\n                }\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[ERROR] target `x` in package `foo` requires the features: `a1/f1`\nConsider enabling them by passing, e.g., `--features=\"a1/f1\"`\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --features a1/f1\").run();\n    p.rename_run(\"x\", \"x_with_f1\")\n        .with_stdout_data(str![[r#\"\na1 f1\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --features a1/f1,a2/f2\").run();\n    p.rename_run(\"x\", \"x_with_f1_f2\")\n        .with_stdout_data(str![[r#\"\na1 f1\na2 f2\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn truncated_install_warning_message() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"foo\"\n    version = \"0.1.0\"\n    edition = \"2021\"\n\n    [features]\n    feature1 = []\n    feature2 = []\n    feature3 = []\n    feature4 = []\n    feature5 = []\n\n    [[bin]]\n    name = \"foo1\"\n    required-features = [\"feature1\", \"feature2\", \"feature3\"]\n\n    [[bin]]\n    name = \"foo2\"\n    required-features = [\"feature2\"]\n\n    [[bin]]\n    name = \"foo3\"\n    required-features = [\"feature3\"]\n\n    [[bin]]\n    name = \"foo4\"\n    required-features = [\"feature4\", \"feature1\"]\n\n    [[bin]]\n    name = \"foo5\"\n    required-features = [\"feature1\", \"feature2\", \"feature3\", \"feature4\", \"feature5\"]\n\n    [[bin]]\n    name = \"foo6\"\n    required-features = [\"feature1\", \"feature2\", \"feature3\", \"feature4\", \"feature5\"]\n\n    [[bin]]\n    name = \"foo7\"\n    required-features = [\"feature1\", \"feature2\", \"feature3\", \"feature4\", \"feature5\"]\n\n    [[bin]]\n    name = \"foo8\"\n    required-features = [\"feature1\", \"feature2\", \"feature3\", \"feature4\", \"feature5\"]\n\n    [[bin]]\n    name = \"foo9\"\n    required-features = [\"feature1\", \"feature2\", \"feature3\", \"feature4\", \"feature5\"]\n\n    [[bin]]\n    name = \"foo10\"\n    required-features = [\"feature1\", \"feature2\", \"feature3\", \"feature4\", \"feature5\"]\n\n    [[example]]\n    name = \"example1\"\n    required-features = [\"feature1\", \"feature2\"]\n    \"#,\n        )\n        .file(\"src/bin/foo1.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo2.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo3.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo4.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo5.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo6.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo7.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo8.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo9.rs\", \"fn main() {}\")\n        .file(\"src/bin/foo10.rs\", \"fn main() {}\")\n        .file(\"examples/example1.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"install --path .\").with_stderr_data(str![[r#\"\n[INSTALLING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[WARNING] none of the package's binaries are available for install using the selected features\n  bin \"foo1\" requires the features: `feature1`, `feature2`, `feature3`\n  bin \"foo10\" requires the features: `feature1`, `feature2`, `feature3`, `feature4`, `feature5`\n  bin \"foo2\" requires the features: `feature2`\n  bin \"foo3\" requires the features: `feature3`\n  bin \"foo4\" requires the features: `feature4`, `feature1`\n  bin \"foo5\" requires the features: `feature1`, `feature2`, `feature3`, `feature4`, `feature5`\n  bin \"foo6\" requires the features: `feature1`, `feature2`, `feature3`, `feature4`, `feature5`\n4 more targets also requires features not enabled. See them in the Cargo.toml file.\nConsider enabling some of the needed features by passing, e.g., `--features=\"feature1 feature2 feature3\"`\n\n\"#]]).run();\n}\n"
  },
  {
    "path": "tests/testsuite/run.rs",
    "content": "//! Tests for the `cargo run` command.\n\nuse crate::prelude::*;\nuse cargo_test_support::{\n    Project, basic_bin_manifest, basic_lib_manifest, basic_manifest, project, str,\n};\nuse cargo_util::paths::dylib_path_envvar;\n\n#[cargo_test]\nfn simple() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n    assert!(p.bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn quiet_arg() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"run -q\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --quiet\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn unsupported_silent_arg() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"run -s\")\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '--silent' found\n\n  tip: a similar argument exists: '--quiet'\n\nUsage: cargo[EXE] run [OPTIONS] [ARGS]...\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n\n    p.cargo(\"run --silent\")\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '--silent' found\n\n  tip: a similar argument exists: '--quiet'\n\nUsage: cargo[EXE] run [OPTIONS] [ARGS]...\n\nFor more information, try '--help'.\n\n\"#]])\n        .with_status(1)\n        .run();\n}\n\n#[cargo_test]\nfn quiet_arg_and_verbose_arg() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"run -q -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot set both --verbose and --quiet\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn quiet_arg_and_verbose_config() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [term]\n                verbose = true\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"run -q\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn verbose_arg_and_quiet_config() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [term]\n                quiet = true\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"run -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn quiet_config_alone() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [term]\n                quiet = true\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"run\")\n        .with_stderr_data(\"\")\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn verbose_config_alone() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [term]\n                verbose = true\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn quiet_config_and_verbose_config() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [term]\n                verbose = true\n                quiet = true\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"run\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot set both `term.verbose` and `term.quiet`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_with_args() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    assert_eq!(std::env::args().nth(1).unwrap(), \"hello\");\n                    assert_eq!(std::env::args().nth(2).unwrap(), \"world\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run hello world\").run();\n}\n\n#[cfg(unix)]\n#[cargo_test]\nfn simple_with_non_utf8_args() {\n    use std::os::unix::ffi::OsStrExt;\n\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                use std::ffi::OsStr;\n                use std::os::unix::ffi::OsStrExt;\n\n                fn main() {\n                    assert_eq!(std::env::args_os().nth(1).unwrap(), OsStr::from_bytes(b\"hello\"));\n                    assert_eq!(std::env::args_os().nth(2).unwrap(), OsStr::from_bytes(b\"ab\\xffcd\"));\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .arg(\"hello\")\n        .arg(std::ffi::OsStr::from_bytes(b\"ab\\xFFcd\"))\n        .run();\n}\n\n#[cargo_test]\nfn exit_code() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() { std::process::exit(2); }\")\n        .build();\n\n    let expected = if !cfg!(unix) {\n        str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n[ERROR] process didn't exit successfully: `target/debug/foo[EXE]` ([EXIT_STATUS]: 2)\n\n\"#]]\n    } else {\n        str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo`\n\n\"#]]\n    };\n    p.cargo(\"run\")\n        .with_status(2)\n        .with_stderr_data(expected)\n        .run();\n}\n\n#[cargo_test]\nfn exit_code_verbose() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() { std::process::exit(2); }\")\n        .build();\n\n    let expected = if !cfg!(unix) {\n        str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n[ERROR] process didn't exit successfully: `target/debug/foo[EXE]` ([EXIT_STATUS]: 2)\n\n\"#]]\n    } else {\n        str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]]\n    };\n\n    p.cargo(\"run -v\")\n        .with_status(2)\n        .with_stderr_data(expected)\n        .run();\n}\n\n#[cargo_test]\nfn no_main_file() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"run\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] a bin target must be available for `cargo run`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn too_many_bins() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", \"\")\n        .file(\"src/bin/b.rs\", \"\")\n        .build();\n\n    // Using [..] here because the order is not stable\n    p.cargo(\"run\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `cargo run` could not determine which binary to run. Use the `--bin` option to specify a binary, or the `default-run` manifest key.\navailable binaries: a, b\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn specify_name() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"src/bin/a.rs\",\n            r#\"\n                #[allow(unused_extern_crates)]\n                extern crate foo;\n                fn main() { println!(\"hello a.rs\"); }\n            \"#,\n        )\n        .file(\n            \"src/bin/b.rs\",\n            r#\"\n                #[allow(unused_extern_crates)]\n                extern crate foo;\n                fn main() { println!(\"hello b.rs\"); }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run --bin a -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] src/lib.rs [..]`\n[RUNNING] `rustc [..] src/bin/a.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/a[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello a.rs\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --bin b -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] src/bin/b.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/b[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello b.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn specify_default_run() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                default-run = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", r#\"fn main() { println!(\"hello A\"); }\"#)\n        .file(\"src/bin/b.rs\", r#\"fn main() { println!(\"hello B\"); }\"#)\n        .build();\n\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\nhello A\n\n\"#]])\n        .run();\n    p.cargo(\"run --bin a\")\n        .with_stdout_data(str![[r#\"\nhello A\n\n\"#]])\n        .run();\n    p.cargo(\"run --bin b\")\n        .with_stdout_data(str![[r#\"\nhello B\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bogus_default_run() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                default-run = \"b\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", r#\"fn main() { println!(\"hello A\"); }\"#)\n        .build();\n\n    p.cargo(\"run\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  default-run target `b` not found\n\n  [HELP] a target with a similar name exists: `a`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_example() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/a.rs\", r#\"fn main() { println!(\"example\"); }\"#)\n        .file(\"src/bin/a.rs\", r#\"fn main() { println!(\"bin\"); }\"#)\n        .build();\n\n    p.cargo(\"run --example a\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/examples/a[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nexample\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_library_example() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [[example]]\n                name = \"bar\"\n                crate-type = [\"lib\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/bar.rs\", \"fn foo() {}\")\n        .build();\n\n    p.cargo(\"run --example bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] example target `bar` is a library and cannot be executed\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_bin_example() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                [[example]]\n                name = \"bar\"\n                crate-type = [\"bin\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/bar.rs\", r#\"fn main() { println!(\"example\"); }\"#)\n        .build();\n\n    p.cargo(\"run --example bar\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/examples/bar[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nexample\n\n\"#]])\n        .run();\n}\n\nfn autodiscover_examples_project(rust_edition: &str, autoexamples: Option<bool>) -> Project {\n    let autoexamples = match autoexamples {\n        None => \"\".to_string(),\n        Some(bool) => format!(\"autoexamples = {}\", bool),\n    };\n    project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.0.1\"\n                    authors = []\n                    edition = \"{rust_edition}\"\n                    {autoexamples}\n\n                    [features]\n                    magic = []\n\n                    [[example]]\n                    name = \"do_magic\"\n                    required-features = [\"magic\"]\n                \"#,\n                rust_edition = rust_edition,\n                autoexamples = autoexamples\n            ),\n        )\n        .file(\"examples/a.rs\", r#\"fn main() { println!(\"example\"); }\"#)\n        .file(\n            \"examples/do_magic.rs\",\n            r#\"\n                fn main() { println!(\"magic example\"); }\n            \"#,\n        )\n        .build()\n}\n\n#[cargo_test]\nfn run_example_autodiscover_2015() {\n    let p = autodiscover_examples_project(\"2015\", None);\n    p.cargo(\"run --example a\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] An explicit [[example]] section is specified in Cargo.toml which currently\ndisables Cargo from automatically inferring other example targets.\nThis inference behavior will change in the Rust 2018 edition and the following\nfiles will be included as a example target:\n\n* examples/a.rs\n\nThis is likely to break cargo build or cargo test as these files may not be\nready to be compiled as a example target today. You can future-proof yourself\nand disable this warning by adding `autoexamples = false` to your [package]\nsection. You may also move the files to a location where Cargo would not\nautomatically infer them to be a target, such as in subfolders.\n\nFor more information on this warning you can consult\nhttps://github.com/rust-lang/cargo/issues/5330\n[ERROR] no example target named `a` in default-run packages\n[HELP] available example targets:\n    do_magic\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_example_autodiscover_2015_with_autoexamples_enabled() {\n    let p = autodiscover_examples_project(\"2015\", Some(true));\n    p.cargo(\"run --example a\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/examples/a[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nexample\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_example_autodiscover_2015_with_autoexamples_disabled() {\n    let p = autodiscover_examples_project(\"2015\", Some(false));\n    p.cargo(\"run --example a\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no example target named `a` in default-run packages\n[HELP] available example targets:\n    do_magic\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_example_autodiscover_2018() {\n    let p = autodiscover_examples_project(\"2018\", None);\n    p.cargo(\"run --example a\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/examples/a[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nexample\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn autobins_disables() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            autobins = false\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub mod bin;\")\n        .file(\"src/bin/mod.rs\", \"// empty\")\n        .build();\n\n    p.cargo(\"run\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] a bin target must be available for `cargo run`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_bins() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/a.rs\", r#\"fn main() { println!(\"example\"); }\"#)\n        .file(\"src/bin/a.rs\", r#\"fn main() { println!(\"bin\"); }\"#)\n        .build();\n\n    p.cargo(\"run --bins\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument '--bins' found\n\n  tip: a similar argument exists: '--bin'\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_with_filename() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"src/bin/a.rs\",\n            r#\"\n                extern crate foo;\n                fn main() { println!(\"hello a.rs\"); }\n            \"#,\n        )\n        .file(\"examples/a.rs\", r#\"fn main() { println!(\"example\"); }\"#)\n        .build();\n\n    p.cargo(\"run --bin bin.rs\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no bin target named `bin.rs` in default-run packages\n[HELP] available bin targets:\n    a\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --bin a.rs\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no bin target named `a.rs` in default-run packages\n\n[HELP] a target with a similar name exists: `a`\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --example example.rs\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no example target named `example.rs` in default-run packages\n[HELP] available example targets:\n    a\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --example a.rs\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no example target named `a.rs` in default-run packages\n\n[HELP] a target with a similar name exists: `a`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ambiguous_bin_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n        [workspace]\n        resolver = \"3\"\n        members = [\"crate1\", \"crate2\", \"crate3\", \"crate4\"]\n        \"#,\n        )\n        .file(\"crate1/src/bin/ambiguous.rs\", \"fn main(){}\")\n        .file(\n            \"crate1/Cargo.toml\",\n            r#\"\n        [package]\n        name = \"crate1\"\n        version = \"0.1.0\"\n        edition = \"2024\"\n    \"#,\n        )\n        .file(\"crate2/src/bin/ambiguous.rs\", \"fn main(){}\")\n        .file(\n            \"crate2/Cargo.toml\",\n            r#\"\n        [package]\n        name = \"crate2\"\n        version = \"0.1.0\"\n        edition = \"2024\"\n    \"#,\n        )\n        .file(\"crate3/src/bin/ambiguous.rs\", \"fn main(){}\")\n        .file(\n            \"crate3/Cargo.toml\",\n            r#\"\n        [package]\n        name = \"crate3\"\n        version = \"0.1.0\"\n        edition = \"2024\"\n    \"#,\n        )\n        .file(\"crate4/src/bin/ambiguous.rs\", \"fn main(){}\")\n        .file(\n            \"crate4/Cargo.toml\",\n            r#\"\n        [package]\n        name = \"crate4\"\n        version = \"0.1.0\"\n        edition = \"2024\"\n    \"#,\n        );\n    let p = p.build();\n\n    p.cargo(\"run --bin ambiguous\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `cargo run` can run at most one executable, but multiple were specified\n[HELP] available targets:\n    bin `ambiguous` in package `crate1`\n    bin `ambiguous` in package `crate2`\n    bin `ambiguous` in package `crate3`\n    bin `ambiguous` in package `crate4`\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --bin crate1/ambiguous\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no bin target named `crate1/ambiguous` in default-run packages\n[HELP] available bin targets:\n    ambiguous in package crate1\n    ambiguous in package crate2\n    ambiguous in package crate3\n    ambiguous in package crate4\n\n\"#]])\n        .run();\n}\n\n// See rust-lang/cargo#14544\n#[cargo_test]\nfn print_available_targets_within_virtual_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n        [workspace]\n        resolver = \"3\"\n        members = [\"crate1\", \"crate2\", \"pattern1\", \"pattern2\"]\n\n        default-members = [\"crate1\"]\n        \"#,\n        )\n        .file(\"crate1/src/main.rs\", \"fn main(){}\")\n        .file(\n            \"crate1/Cargo.toml\",\n            r#\"\n        [package]\n        name = \"crate1\"\n        version = \"0.1.0\"\n        edition = \"2024\"\n    \"#,\n        )\n        .file(\"crate2/src/main.rs\", \"fn main(){}\")\n        .file(\n            \"crate2/Cargo.toml\",\n            r#\"\n        [package]\n        name = \"crate2\"\n        version = \"0.1.0\"\n        edition = \"2024\"\n    \"#,\n        )\n        .file(\"pattern1/src/main.rs\", \"fn main(){}\")\n        .file(\n            \"pattern1/Cargo.toml\",\n            r#\"\n        [package]\n        name = \"pattern1\"\n        version = \"0.1.0\"\n        edition = \"2024\"\n    \"#,\n        )\n        .file(\"pattern2/src/main.rs\", \"fn main(){}\")\n        .file(\n            \"pattern2/Cargo.toml\",\n            r#\"\n        [package]\n        name = \"pattern2\"\n        version = \"0.1.0\"\n        edition = \"2024\"\n    \"#,\n        )\n        .file(\"another/src/main.rs\", \"fn main(){}\")\n        .file(\n            \"another/Cargo.toml\",\n            r#\"\n        [package]\n        name = \"another\"\n        version = \"0.1.0\"\n        edition = \"2024\"\n    \"#,\n        );\n\n    let p = p.build();\n    p.cargo(\"run --bin\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] \"--bin\" takes one argument.\nAvailable binaries:\n    crate1\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"run -p crate1 --bin crate2\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no bin target named `crate2` in `crate1` package\n\n[HELP] a target with a similar name exists: `crate1`\n[HELP] available bin in `crate2` package:\n    crate2\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -p crate1 -p pattern1 -p pattern2 --bin crate2\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no bin target named `crate2` in `crate1`, ... packages\n\n[HELP] a target with a similar name exists: `crate1`\n[HELP] available bin in `crate2` package:\n    crate2\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --bin crate2\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no bin target named `crate2` in default-run packages\n\n[HELP] a target with a similar name exists: `crate1`\n[HELP] available bin in `crate2` package:\n    crate2\n\n\"#]])\n        .run();\n\n    p.cargo(\"check --bin pattern*\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no bin target matches pattern `pattern*` in default-run packages\n[HELP] available bin in `pattern1` package:\n    pattern1\n[HELP] available bin in `pattern2` package:\n    pattern2\n\n\"#]])\n        .run();\n\n    // This another branch that none of similar name exists, and print available targets in the\n    // default-members.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n        [workspace]\n        resolver = \"3\"\n        members = [\"crate1\", \"crate2\", \"another\"]\n\n        default-members = [\"another\"]\n        \"#,\n    );\n\n    p.cargo(\"run --bin crate2\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no bin target named `crate2` in default-run packages\n[HELP] available bin in `crate2` package:\n    crate2\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn either_name_or_example() {\n    let p = project()\n        .file(\"src/bin/a.rs\", r#\"fn main() { println!(\"hello a.rs\"); }\"#)\n        .file(\"examples/b.rs\", r#\"fn main() { println!(\"hello b.rs\"); }\"#)\n        .build();\n\n    p.cargo(\"run --bin a --example b\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `cargo run` can run at most one executable, but multiple were specified\n[HELP] available targets:\n    bin `a` in package `foo`\n    example `b` in package `foo`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn one_bin_multiple_examples() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"src/bin/main.rs\",\n            r#\"fn main() { println!(\"hello main.rs\"); }\"#,\n        )\n        .file(\"examples/a.rs\", r#\"fn main() { println!(\"hello a.rs\"); }\"#)\n        .file(\"examples/b.rs\", r#\"fn main() { println!(\"hello b.rs\"); }\"#)\n        .build();\n\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/main[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello main.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn example_with_release_flag() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                version = \"*\"\n                path = \"bar\"\n            \"#,\n        )\n        .file(\n            \"examples/a.rs\",\n            r#\"\n                extern crate bar;\n\n                fn main() {\n                    if cfg!(debug_assertions) {\n                        println!(\"slow1\")\n                    } else {\n                        println!(\"fast1\")\n                    }\n                    bar::baz();\n                }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\n            \"bar/src/bar.rs\",\n            r#\"\n                pub fn baz() {\n                    if cfg!(debug_assertions) {\n                        println!(\"slow2\")\n                    } else {\n                        println!(\"fast2\")\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run -v --release --example a\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/bar.rs [..]--crate-type lib --emit=[..]link -C opt-level=3[..] -C metadata=[..] --out-dir [ROOT]/foo/target/release/deps -C strip=debuginfo -L dependency=[ROOT]/foo/target/release/deps`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name a --edition=2015 examples/a.rs [..]--crate-type bin --emit=[..]link -C opt-level=3[..] -C metadata=[..] --out-dir [ROOT]/foo/target/release/examples -C strip=debuginfo -L dependency=[ROOT]/foo/target/release/deps --extern bar=[ROOT]/foo/target/release/deps/libbar-[HASH].rlib`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `target/release/examples/a[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nfast1\nfast2\n\n\"#]])\n        .run();\n\n    p.cargo(\"run -v --example a\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/bar.rs [..]--crate-type lib --emit=[..]link [..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name a --edition=2015 examples/a.rs [..]--crate-type bin --emit=[..]link [..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/examples -L dependency=[ROOT]/foo/target/debug/deps --extern bar=[ROOT]/foo/target/debug/deps/libbar-[HASH].rlib`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/examples/a[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nslow1\nslow2\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_dylib_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"extern crate bar; fn main() { bar::bar(); }\"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                authors = []\n\n                [lib]\n                name = \"bar\"\n                crate-type = [\"dylib\"]\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"run hello world\").run();\n}\n\n#[cargo_test]\nfn run_with_bin_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"bar\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", r#\"fn main() { println!(\"bar\"); }\"#)\n        .build();\n\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[WARNING] foo v0.0.1 ([ROOT]/foo) ignoring invalid dependency `bar` which is missing a lib target\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_with_bin_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies.bar1]\n                path = \"bar1\"\n                [dependencies.bar2]\n                path = \"bar2\"\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\n            \"bar1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"bar1\"\n            \"#,\n        )\n        .file(\"bar1/src/main.rs\", r#\"fn main() { println!(\"bar1\"); }\"#)\n        .file(\n            \"bar2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"bar2\"\n            \"#,\n        )\n        .file(\"bar2/src/main.rs\", r#\"fn main() { println!(\"bar2\"); }\"#)\n        .build();\n\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[WARNING] foo v0.0.1 ([ROOT]/foo) ignoring invalid dependency `bar1` which is missing a lib target\n[WARNING] foo v0.0.1 ([ROOT]/foo) ignoring invalid dependency `bar2` which is missing a lib target\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_with_bin_dep_in_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo1\", \"foo2\"]\n            \"#,\n        )\n        .file(\n            \"foo1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies.bar1]\n                path = \"bar1\"\n            \"#,\n        )\n        .file(\"foo1/src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\n            \"foo1/bar1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"bar1\"\n            \"#,\n        )\n        .file(\n            \"foo1/bar1/src/main.rs\",\n            r#\"fn main() { println!(\"bar1\"); }\"#,\n        )\n        .file(\n            \"foo2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies.bar2]\n                path = \"bar2\"\n            \"#,\n        )\n        .file(\"foo2/src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .file(\n            \"foo2/bar2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"bar2\"\n            \"#,\n        )\n        .file(\n            \"foo2/bar2/src/main.rs\",\n            r#\"fn main() { println!(\"bar2\"); }\"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `cargo run` could not determine which binary to run. Use the `--bin` option to specify a binary, or the `default-run` manifest key.\navailable binaries: bar1, bar2, foo1, foo2\n\n\"#]])\n        .run();\n\n    p.cargo(\"run --bin foo1\")\n        .with_stderr_data(str![[r#\"\n[WARNING] foo1 v0.0.1 ([ROOT]/foo/foo1) ignoring invalid dependency `bar1` which is missing a lib target\n[WARNING] foo2 v0.0.1 ([ROOT]/foo/foo2) ignoring invalid dependency `bar2` which is missing a lib target\n[COMPILING] foo1 v0.0.1 ([ROOT]/foo/foo1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo1[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn release_works() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() { if cfg!(debug_assertions) { panic!() } }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run --release\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `target/release/foo[EXE]`\n\n\"#]])\n        .run();\n    assert!(p.release_bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn release_short_works() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() { if cfg!(debug_assertions) { panic!() } }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run -r\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `target/release/foo[EXE]`\n\n\"#]])\n        .run();\n    assert!(p.release_bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn run_bin_different_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"bar\"\n            \"#,\n        )\n        .file(\"src/bar.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"run\").run();\n}\n\n#[cargo_test]\nfn dashes_are_forwarded() {\n    let p = project()\n        .file(\n            \"src/bin/bar.rs\",\n            r#\"\n                fn main() {\n                    let s: Vec<String> = std::env::args().collect();\n                    assert_eq!(s[1], \"--\");\n                    assert_eq!(s[2], \"a\");\n                    assert_eq!(s[3], \"--\");\n                    assert_eq!(s[4], \"b\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run -- -- a -- b\").run();\n}\n\n#[cargo_test]\nfn run_from_executable_folder() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    let cwd = p.root().join(\"target\").join(\"debug\");\n    p.cargo(\"build\").run();\n\n    p.cargo(\"run\")\n        .cwd(cwd)\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `./foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn run_with_library_paths() {\n    let p = project();\n\n    // Only link search directories within the target output directory are\n    // propagated through to dylib_path_envvar() (see #3366).\n    let mut dir1 = p.target_debug_dir();\n    dir1.push(\"foo\\\\backslash\");\n\n    let mut dir2 = p.target_debug_dir();\n    dir2.push(\"dir=containing=equal=signs\");\n\n    let p = p\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            &format!(\n                r##\"\n                    fn main() {{\n                        println!(r#\"cargo::rustc-link-search=native={}\"#);\n                        println!(r#\"cargo::rustc-link-search={}\"#);\n                    }}\n                \"##,\n                dir1.display(),\n                dir2.display()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            &format!(\n                r##\"\n                    fn main() {{\n                        let search_path = std::env::var_os(\"{}\").unwrap();\n                        let paths = std::env::split_paths(&search_path).collect::<Vec<_>>();\n                        println!(\"{{:#?}}\", paths);\n                        assert!(paths.contains(&r#\"{}\"#.into()));\n                        assert!(paths.contains(&r#\"{}\"#.into()));\n                    }}\n                \"##,\n                dylib_path_envvar(),\n                dir1.display(),\n                dir2.display()\n            ),\n        )\n        .build();\n\n    p.cargo(\"run\").run();\n}\n\n#[cargo_test]\nfn library_paths_sorted_alphabetically() {\n    let p = project();\n\n    let mut dir1 = p.target_debug_dir();\n    dir1.push(\"zzzzzzz\");\n\n    let mut dir2 = p.target_debug_dir();\n    dir2.push(\"BBBBBBB\");\n\n    let mut dir3 = p.target_debug_dir();\n    dir3.push(\"aaaaaaa\");\n\n    let p = p\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            &format!(\n                r##\"\n                    fn main() {{\n                        println!(r#\"cargo::rustc-link-search=native={}\"#);\n                        println!(r#\"cargo::rustc-link-search=native={}\"#);\n                        println!(r#\"cargo::rustc-link-search=native={}\"#);\n                    }}\n                \"##,\n                dir1.display(),\n                dir2.display(),\n                dir3.display()\n            ),\n        )\n        .file(\n            \"src/main.rs\",\n            &format!(\n                r##\"\n                    fn main() {{\n                        let search_path = std::env::var_os(\"{}\").unwrap();\n                        let paths = std::env::split_paths(&search_path).collect::<Vec<_>>();\n                        // ASCII case-sensitive sort\n                        assert_eq!(\"BBBBBBB\", paths[0].file_name().unwrap().to_string_lossy());\n                        assert_eq!(\"aaaaaaa\", paths[1].file_name().unwrap().to_string_lossy());\n                        assert_eq!(\"zzzzzzz\", paths[2].file_name().unwrap().to_string_lossy());\n                    }}\n                \"##,\n                dylib_path_envvar()\n            ),\n        )\n        .build();\n\n    p.cargo(\"run\").run();\n}\n\n#[cargo_test]\nfn fail_no_extra_verbose() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() { std::process::exit(1); }\")\n        .build();\n\n    p.cargo(\"run -q\")\n        .with_status(1)\n        .with_stdout_data(\"\")\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn run_multiple_packages() {\n    let p = project()\n        .no_manifest()\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n\n                [dependencies]\n                d1 = { path = \"d1\" }\n                d2 = { path = \"d2\" }\n                d3 = { path = \"../d3\" } # outside of the workspace\n\n                [[bin]]\n                name = \"foo\"\n            \"#,\n        )\n        .file(\"foo/src/foo.rs\", \"fn main() { println!(\\\"foo\\\"); }\")\n        .file(\"foo/d1/Cargo.toml\", &basic_bin_manifest(\"d1\"))\n        .file(\"foo/d1/src/lib.rs\", \"\")\n        .file(\"foo/d1/src/main.rs\", \"fn main() { println!(\\\"d1\\\"); }\")\n        .file(\"foo/d2/Cargo.toml\", &basic_bin_manifest(\"d2\"))\n        .file(\"foo/d2/src/main.rs\", \"fn main() { println!(\\\"d2\\\"); }\")\n        .file(\"d3/Cargo.toml\", &basic_bin_manifest(\"d3\"))\n        .file(\"d3/src/main.rs\", \"fn main() { println!(\\\"d2\\\"); }\")\n        .build();\n\n    let cargo = || {\n        let mut process_builder = p.cargo(\"run\");\n        process_builder.cwd(\"foo\");\n        process_builder\n    };\n\n    cargo()\n        .arg(\"-p\")\n        .arg(\"d1\")\n        .with_stdout_data(str![[r#\"\nd1\n\n\"#]])\n        .run();\n\n    cargo()\n        .arg(\"-p\")\n        .arg(\"d2\")\n        .arg(\"--bin\")\n        .arg(\"d2\")\n        .with_stdout_data(str![[r#\"\nd2\n\n\"#]])\n        .run();\n\n    cargo()\n        .with_stdout_data(str![[r#\"\nfoo\n\n\"#]])\n        .run();\n\n    cargo()\n        .arg(\"-p\")\n        .arg(\"d1\")\n        .arg(\"-p\")\n        .arg(\"d2\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] the argument '--package [<SPEC>]' cannot be used multiple times\n...\n\"#]])\n        .run();\n\n    cargo()\n        .arg(\"-p\")\n        .arg(\"d3\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package(s) `d3` not found in workspace `[ROOT]/foo/foo`\n\n\"#]])\n        .run();\n\n    cargo()\n        .arg(\"-p\")\n        .arg(\"d*\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `cargo run` does not support glob pattern `d*` on package selection\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn explicit_bin_with_args() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    assert_eq!(std::env::args().nth(1).unwrap(), \"hello\");\n                    assert_eq!(std::env::args().nth(2).unwrap(), \"world\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run --bin foo hello world\").run();\n}\n\n#[cargo_test]\nfn run_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_bin_manifest(\"a\"))\n        .file(\"a/src/main.rs\", r#\"fn main() {println!(\"run-a\");}\"#)\n        .file(\"b/Cargo.toml\", &basic_bin_manifest(\"b\"))\n        .file(\"b/src/main.rs\", r#\"fn main() {println!(\"run-b\");}\"#)\n        .build();\n\n    p.cargo(\"run\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `cargo run` could not determine which binary to run. Use the `--bin` option to specify a binary, or the `default-run` manifest key.\navailable binaries: a, b\n\n\"#]])\n        .run();\n    p.cargo(\"run --bin a\")\n        .with_stdout_data(str![[r#\"\nrun-a\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn default_run_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                default-run = \"a\"\n            \"#,\n        )\n        .file(\"a/src/main.rs\", r#\"fn main() {println!(\"run-a\");}\"#)\n        .file(\"b/Cargo.toml\", &basic_bin_manifest(\"b\"))\n        .file(\"b/src/main.rs\", r#\"fn main() {println!(\"run-b\");}\"#)\n        .build();\n\n    p.cargo(\"run\")\n        .with_stdout_data(str![[r#\"\nrun-a\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn print_env_verbose() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"src/main.rs\", r#\"fn main() {println!(\"run-a\");}\"#)\n        .build();\n\n    p.cargo(\"run -vv\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] a v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] rustc --crate-name a[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] target/debug/a[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[cfg(target_os = \"macos\")]\nfn run_link_system_path_macos() {\n    use cargo_test_support::paths;\n    use std::fs;\n    // Check that the default system library path is honored.\n    // First, build a shared library that will be accessed from\n    // DYLD_FALLBACK_LIBRARY_PATH.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            [lib]\n            crate-type = [\"cdylib\"]\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"#[no_mangle] pub extern fn something_shared() {}\",\n        )\n        .build();\n    p.cargo(\"build\").run();\n\n    // This is convoluted. Since this test can't modify things in /usr,\n    // this needs to dance around to check that things work.\n    //\n    // The default DYLD_FALLBACK_LIBRARY_PATH is:\n    //      $(HOME)/lib:/usr/local/lib:/lib:/usr/lib\n    //\n    // This will make use of ~/lib in the path, but the default cc link\n    // path is /usr/lib:/usr/local/lib. So first need to build in one\n    // location, and then move it to ~/lib.\n    //\n    // 1. Build with rustc-link-search pointing to libfoo so the initial\n    //    binary can be linked.\n    // 2. Move the library to ~/lib\n    // 3. Run `cargo run` to make sure it can still find the library in\n    //    ~/lib.\n    //\n    // This should be equivalent to having the library in /usr/local/lib.\n    let p2 = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            extern {\n                fn something_shared();\n            }\n            fn main() {\n                unsafe { something_shared(); }\n            }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            &format!(\n                r#\"\n                fn main() {{\n                    println!(\"cargo::rustc-link-lib=foo\");\n                    println!(\"cargo::rustc-link-search={}\");\n                }}\n                \"#,\n                p.target_debug_dir().display()\n            ),\n        )\n        .build();\n    p2.cargo(\"build\").run();\n    p2.cargo(\"test\").run();\n\n    let libdir = paths::home().join(\"lib\");\n    fs::create_dir(&libdir).unwrap();\n    fs::rename(\n        p.target_debug_dir().join(\"libfoo.dylib\"),\n        libdir.join(\"libfoo.dylib\"),\n    )\n    .unwrap();\n    p.root().rm_rf();\n    const VAR: &str = \"DYLD_FALLBACK_LIBRARY_PATH\";\n    // Reset DYLD_FALLBACK_LIBRARY_PATH so that we don't inherit anything that\n    // was set by the cargo that invoked the test.\n    p2.cargo(\"run\").env_remove(VAR).run();\n    p2.cargo(\"test\").env_remove(VAR).run();\n    // Ensure this still works when DYLD_FALLBACK_LIBRARY_PATH has\n    // a value set.\n    p2.cargo(\"run\").env(VAR, &libdir).run();\n    p2.cargo(\"test\").env(VAR, &libdir).run();\n}\n\n#[cargo_test]\nfn run_binary_with_same_name_as_dependency() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {}\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo\"\n                path = \"foo.rs\"\n            \"#,\n        )\n        .file(\"foo/foo.rs\", \"\")\n        .build();\n    p.cargo(\"run\").run();\n    p.cargo(\"check -p foo@0.5.0\").run();\n    p.cargo(\"run -p foo@0.5.0\").run();\n    p.cargo(\"run -p foo@0.5\").run();\n    p.cargo(\"run -p foo@0.4\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package(s) `foo@0.4` not found in workspace `[ROOT]/foo`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/rust_version.rs",
    "content": "//! Tests for targets with `rust-version`.\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::{project, registry::Package, str};\n\n#[cargo_test]\nfn rust_version_satisfied() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            rust-version = \"1.1.1\"\n            [[bin]]\n            name = \"foo\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"check --ignore-rust-version\").run();\n}\n\n#[cargo_test]\nfn rust_version_error() {\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            rust-version = \"^1.43\"\n            [[bin]]\n            name = \"foo\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build()\n        .cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected version requirement, expected a version like \"1.32\"\n --> Cargo.toml:7:28\n  |\n7 |             rust-version = \"^1.43\"\n  |                            ^^^^^^^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rust_version_older_than_edition() {\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            authors = []\n            rust-version = \"1.1\"\n            edition = \"2018\"\n            [[bin]]\n            name = \"foo\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build()\n        .cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  rust-version 1.1 is incompatible with the version (1.31.0) required by the specified edition (2018)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn lint_self_incompatible_with_rust_version() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            rust-version = \"1.9876.0\"\n            [[bin]]\n            name = \"foo\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] rustc [..] is not supported by the following package:\n  foo@0.0.1 requires rustc 1.9876.0\n\n\n\"#]])\n        .run();\n    p.cargo(\"check --ignore-rust-version\").run();\n}\n\n#[cargo_test]\nfn lint_dep_incompatible_with_rust_version() {\n    Package::new(\"too_new_parent\", \"0.0.1\")\n        .dep(\"too_new_child\", \"0.0.1\")\n        .rust_version(\"1.2345.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"too_new_child\", \"0.0.1\")\n        .rust_version(\"1.2345.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"rustc_compatible\", \"0.0.1\")\n        .rust_version(\"1.60.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            rust-version = \"1.50\"\n            authors = []\n            [dependencies]\n            too_new_parent = \"0.0.1\"\n            rustc_compatible = \"0.0.1\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n\n    p.cargo(\"generate-lockfile\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[ADDING] too_new_child v0.0.1 (requires Rust 1.2345.0)\n[ADDING] too_new_parent v0.0.1 (requires Rust 1.2345.0)\n\n\"#]])\n        .run();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] too_new_parent v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] too_new_child v0.0.1 (registry `dummy-registry`)\n[DOWNLOADED] rustc_compatible v0.0.1 (registry `dummy-registry`)\n[ERROR] rustc [..] is not supported by the following packages:\n  too_new_child@0.0.1 requires rustc 1.2345.0\n  too_new_parent@0.0.1 requires rustc 1.2345.0\nEither upgrade rustc or select compatible dependency versions with\n`cargo update <name>@<current-ver> --precise <compatible-ver>`\nwhere `<compatible-ver>` is the latest version supporting rustc [..]\n\n\n\"#]])\n        .run();\n    p.cargo(\"check --ignore-rust-version\").run();\n}\n\n#[cargo_test]\nfn resolve_with_rust_version() {\n    Package::new(\"only-newer\", \"1.6.0\")\n        .rust_version(\"1.65.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"newer-and-older\", \"1.5.0\")\n        .rust_version(\"1.55.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"newer-and-older\", \"1.6.0\")\n        .rust_version(\"1.65.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            rust-version = \"1.60.0\"\n\n            [dependencies]\n            only-newer = \"1.0.0\"\n            newer-and-older = \"1.0.0\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n\n    p.cargo(\"generate-lockfile --ignore-rust-version\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n├── newer-and-older v1.6.0\n└── only-newer v1.6.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"generate-lockfile\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest Rust 1.60.0 compatible versions\n[ADDING] newer-and-older v1.5.0 (available: v1.6.0, requires Rust 1.65.0)\n[ADDING] only-newer v1.6.0 (requires Rust 1.65.0)\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n├── newer-and-older v1.5.0\n└── only-newer v1.6.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn resolve_with_rustc() {\n    Package::new(\"only-newer\", \"1.6.0\")\n        .rust_version(\"1.2345\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"newer-and-older\", \"1.5.0\")\n        .rust_version(\"1.55.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"newer-and-older\", \"1.6.0\")\n        .rust_version(\"1.2345\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            rust-version = \"1.60.0\"\n\n            [dependencies]\n            only-newer = \"1.0.0\"\n            newer-and-older = \"1.0.0\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n\n    p.cargo(\"generate-lockfile --ignore-rust-version\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[ADDING] newer-and-older v1.6.0 (requires Rust 1.2345)\n[ADDING] only-newer v1.6.0 (requires Rust 1.2345)\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n├── newer-and-older v1.6.0\n└── only-newer v1.6.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"generate-lockfile\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest Rust 1.60.0 compatible versions\n[ADDING] newer-and-older v1.5.0 (available: v1.6.0, requires Rust 1.2345)\n[ADDING] only-newer v1.6.0 (requires Rust 1.2345)\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n├── newer-and-older v1.5.0\n└── only-newer v1.6.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn resolve_with_backtracking() {\n    Package::new(\"has-rust-version\", \"1.6.0\")\n        .rust_version(\"1.65.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"no-rust-version\", \"2.1.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"no-rust-version\", \"2.2.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .dep(\"has-rust-version\", \"1.6.0\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            rust-version = \"1.60.0\"\n\n            [dependencies]\n            no-rust-version = \"2\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n\n    p.cargo(\"generate-lockfile --ignore-rust-version\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n└── no-rust-version v2.2.0\n    └── has-rust-version v1.6.0\n\n\"#]])\n        .run();\n\n    // Ideally we'd pick `has-rust-version` 1.6.0 which requires backtracking\n    p.cargo(\"generate-lockfile\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest Rust 1.60.0 compatible versions\n[ADDING] has-rust-version v1.6.0 (requires Rust 1.65.0)\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n└── no-rust-version v2.2.0\n    └── has-rust-version v1.6.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn resolve_with_multiple_rust_versions() {\n    Package::new(&format!(\"shared-only-newer\"), \"1.65.0\")\n        .rust_version(\"1.65.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    for ver in [\"1.45.0\", \"1.55.0\", \"1.65.0\"] {\n        Package::new(&format!(\"shared-newer-and-older\"), ver)\n            .rust_version(ver)\n            .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n            .publish();\n    }\n    Package::new(&format!(\"lower-only-newer\"), \"1.65.0\")\n        .rust_version(\"1.65.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    for ver in [\"1.45.0\", \"1.55.0\"] {\n        Package::new(&format!(\"lower-newer-and-older\"), ver)\n            .rust_version(ver)\n            .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n            .publish();\n    }\n    Package::new(&format!(\"higher-only-newer\"), \"1.65.0\")\n        .rust_version(\"1.65.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    for ver in [\"1.55.0\", \"1.65.0\"] {\n        Package::new(&format!(\"higher-newer-and-older\"), ver)\n            .rust_version(ver)\n            .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n            .publish();\n    }\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"lower\"]\n\n            [package]\n            name = \"higher\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            rust-version = \"1.60.0\"\n\n            [dependencies]\n            higher-only-newer = \"1\"\n            higher-newer-and-older = \"1\"\n            shared-only-newer = \"1\"\n            shared-newer-and-older = \"1\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"lower/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"lower\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            rust-version = \"1.50.0\"\n\n            [dependencies]\n            lower-only-newer = \"1\"\n            lower-newer-and-older = \"1\"\n            shared-only-newer = \"1\"\n            shared-newer-and-older = \"1\"\n        \"#,\n        )\n        .file(\"lower/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"generate-lockfile --ignore-rust-version\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 6 packages to latest compatible versions\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nhigher v0.0.1 ([ROOT]/foo)\n├── higher-newer-and-older v1.65.0\n├── higher-only-newer v1.65.0\n├── shared-newer-and-older v1.65.0\n└── shared-only-newer v1.65.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"generate-lockfile\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 6 packages to latest Rust 1.50.0 compatible versions\n[ADDING] higher-newer-and-older v1.55.0 (available: v1.65.0, requires Rust 1.65.0)\n[ADDING] higher-only-newer v1.65.0 (requires Rust 1.65.0)\n[ADDING] lower-newer-and-older v1.45.0 (available: v1.55.0, requires Rust 1.55.0)\n[ADDING] lower-only-newer v1.65.0 (requires Rust 1.65.0)\n[ADDING] shared-newer-and-older v1.45.0 (available: v1.65.0, requires Rust 1.65.0)\n[ADDING] shared-only-newer v1.65.0 (requires Rust 1.65.0)\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nhigher v0.0.1 ([ROOT]/foo)\n├── higher-newer-and-older v1.55.0\n├── higher-only-newer v1.65.0\n├── shared-newer-and-older v1.45.0\n└── shared-only-newer v1.65.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn resolve_edition2024() {\n    Package::new(\"only-newer\", \"1.6.0\")\n        .rust_version(\"1.999.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"newer-and-older\", \"1.5.0\")\n        .rust_version(\"1.80.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"newer-and-older\", \"1.6.0\")\n        .rust_version(\"1.999.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2024\"\n            authors = []\n            rust-version = \"1.85.0\"\n\n            [dependencies]\n            only-newer = \"1.0.0\"\n            newer-and-older = \"1.0.0\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n\n    // Edition2024 should resolve for MSRV\n    p.cargo(\"generate-lockfile\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest Rust 1.85.0 compatible versions\n[ADDING] newer-and-older v1.5.0 (available: v1.6.0, requires Rust 1.999.0)\n[ADDING] only-newer v1.6.0 (requires Rust 1.999.0)\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n├── newer-and-older v1.5.0\n└── only-newer v1.6.0\n\n\"#]])\n        .run();\n\n    // `--ignore-rust-version` has precedence over Edition2024\n    p.cargo(\"generate-lockfile --ignore-rust-version\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[ADDING] newer-and-older v1.6.0 (requires Rust 1.999.0)\n[ADDING] only-newer v1.6.0 (requires Rust 1.999.0)\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n├── newer-and-older v1.6.0\n└── only-newer v1.6.0\n\n\"#]])\n        .run();\n\n    // config has precedence over Edition2024\n    p.cargo(\"generate-lockfile\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"allow\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[ADDING] newer-and-older v1.6.0 (requires Rust 1.999.0)\n[ADDING] only-newer v1.6.0 (requires Rust 1.999.0)\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n├── newer-and-older v1.6.0\n└── only-newer v1.6.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn resolve_v3() {\n    Package::new(\"only-newer\", \"1.6.0\")\n        .rust_version(\"1.999.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"newer-and-older\", \"1.5.0\")\n        .rust_version(\"1.80.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"newer-and-older\", \"1.6.0\")\n        .rust_version(\"1.999.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            rust-version = \"1.85.0\"\n            resolver = \"3\"\n\n            [dependencies]\n            only-newer = \"1.0.0\"\n            newer-and-older = \"1.0.0\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n\n    // v3 should resolve for MSRV\n    p.cargo(\"generate-lockfile\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest Rust 1.85.0 compatible versions\n[ADDING] newer-and-older v1.5.0 (available: v1.6.0, requires Rust 1.999.0)\n[ADDING] only-newer v1.6.0 (requires Rust 1.999.0)\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n├── newer-and-older v1.5.0\n└── only-newer v1.6.0\n\n\"#]])\n        .run();\n\n    // `--ignore-rust-version` has precedence over v3\n    p.cargo(\"generate-lockfile --ignore-rust-version\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[ADDING] newer-and-older v1.6.0 (requires Rust 1.999.0)\n[ADDING] only-newer v1.6.0 (requires Rust 1.999.0)\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n├── newer-and-older v1.6.0\n└── only-newer v1.6.0\n\n\"#]])\n        .run();\n\n    // config has precedence over v3\n    p.cargo(\"generate-lockfile\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"allow\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[ADDING] newer-and-older v1.6.0 (requires Rust 1.999.0)\n[ADDING] only-newer v1.6.0 (requires Rust 1.999.0)\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n├── newer-and-older v1.6.0\n└── only-newer v1.6.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_msrv_resolve() {\n    Package::new(\"bar\", \"1.5.0\")\n        .rust_version(\"1.55.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"bar\", \"1.6.0\")\n        .rust_version(\"1.65.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            rust-version = \"1.60.0\"\n            [dependencies]\n            bar = \"1.0.0\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n\n    p.cargo(\"update\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest Rust 1.60.0 compatible version\n[ADDING] bar v1.5.0 (available: v1.6.0, requires Rust 1.65.0)\n\n\"#]])\n        .run();\n    p.cargo(\"update --ignore-rust-version\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v1.5.0 -> v1.6.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_precise_overrides_msrv_resolver() {\n    Package::new(\"bar\", \"1.5.0\")\n        .rust_version(\"1.55.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"bar\", \"1.6.0\")\n        .rust_version(\"1.65.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            rust-version = \"1.60.0\"\n            [dependencies]\n            bar = \"1.0.0\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n\n    p.cargo(\"update\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest Rust 1.60.0 compatible version\n[ADDING] bar v1.5.0 (available: v1.6.0, requires Rust 1.65.0)\n\n\"#]])\n        .run();\n    p.cargo(\"update --precise 1.6.0 bar\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] bar v1.5.0 -> v1.6.0 (requires Rust 1.65.0)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn check_msrv_resolve() {\n    Package::new(\"only-newer\", \"1.6.0\")\n        .rust_version(\"1.65.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"newer-and-older\", \"1.5.0\")\n        .rust_version(\"1.55.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"newer-and-older\", \"1.6.0\")\n        .rust_version(\"1.65.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n            rust-version = \"1.60.0\"\n\n            [dependencies]\n            only-newer = \"1.0.0\"\n            newer-and-older = \"1.0.0\"\n        \"#,\n        )\n        .file(\"src/main.rs\", \"fn main(){}\")\n        .build();\n\n    p.cargo(\"check --ignore-rust-version\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] only-newer v1.6.0 (registry `dummy-registry`)\n[DOWNLOADED] newer-and-older v1.6.0 (registry `dummy-registry`)\n[CHECKING] only-newer v1.6.0\n[CHECKING] newer-and-older v1.6.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n├── newer-and-older v1.6.0\n└── only-newer v1.6.0\n\n\"#]])\n        .run();\n\n    std::fs::remove_file(p.root().join(\"Cargo.lock\")).unwrap();\n    p.cargo(\"check\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest Rust 1.60.0 compatible versions\n[ADDING] newer-and-older v1.5.0 (available: v1.6.0, requires Rust 1.65.0)\n[ADDING] only-newer v1.6.0 (requires Rust 1.65.0)\n[DOWNLOADING] crates ...\n[DOWNLOADED] newer-and-older v1.5.0 (registry `dummy-registry`)\n[CHECKING] newer-and-older v1.5.0\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"tree\")\n        .with_stdout_data(str![[r#\"\nfoo v0.0.1 ([ROOT]/foo)\n├── newer-and-older v1.5.0\n└── only-newer v1.6.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_install_ignores_msrv_config() {\n    Package::new(\"dep\", \"1.0.0\")\n        .rust_version(\"1.50\")\n        .file(\"src/lib.rs\", \"fn hello() {}\")\n        .publish();\n    Package::new(\"dep\", \"1.1.0\")\n        .rust_version(\"1.70\")\n        .file(\"src/lib.rs\", \"fn hello() {}\")\n        .publish();\n    Package::new(\"foo\", \"0.0.1\")\n        .rust_version(\"1.60\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .dep(\"dep\", \"1\")\n        .publish();\n\n    cargo_process(\"install foo\")\n        .env(\n            \"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\",\n            \"fallback\",\n        )\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[INSTALLING] foo v0.0.1\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.1.0 (registry `dummy-registry`)\n[COMPILING] dep v1.1.0\n[COMPILING] foo v0.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_install_ignores_resolver_v3_msrv_change() {\n    Package::new(\"dep\", \"1.0.0\")\n        .rust_version(\"1.50\")\n        .file(\"src/lib.rs\", \"fn hello() {}\")\n        .publish();\n    Package::new(\"dep\", \"1.1.0\")\n        .rust_version(\"1.70\")\n        .file(\"src/lib.rs\", \"fn hello() {}\")\n        .publish();\n    Package::new(\"foo\", \"0.0.1\")\n        .rust_version(\"1.60\")\n        .resolver(\"3\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .dep(\"dep\", \"1\")\n        .publish();\n\n    cargo_process(\"install foo\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)\n[INSTALLING] foo v0.0.1\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.1.0 (registry `dummy-registry`)\n[COMPILING] dep v1.1.0\n[COMPILING] foo v0.0.1\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE]\n[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`)\n[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn report_rust_versions() {\n    Package::new(\"dep-only-low-compatible\", \"1.55.0\")\n        .rust_version(\"1.55.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"dep-only-low-incompatible\", \"1.75.0\")\n        .rust_version(\"1.75.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"dep-only-high-compatible\", \"1.65.0\")\n        .rust_version(\"1.65.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"dep-only-high-incompatible\", \"1.75.0\")\n        .rust_version(\"1.75.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"dep-only-unset-unset\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"dep-only-unset-compatible\", \"1.75.0\")\n        .rust_version(\"1.75.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"dep-only-unset-incompatible\", \"1.2345.0\")\n        .rust_version(\"1.2345.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"dep-shared-compatible\", \"1.55.0\")\n        .rust_version(\"1.55.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n    Package::new(\"dep-shared-incompatible\", \"1.75.0\")\n        .rust_version(\"1.75.0\")\n        .file(\"src/lib.rs\", \"fn other_stuff() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"high\", \"low\", \"unset\"]\n            \"#,\n        )\n        .file(\n            \"high/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"high\"\n                edition = \"2015\"\n                rust-version = \"1.70.0\"\n\n                [dependencies]\n                dep-only-high-compatible = \"1\"\n                dep-only-high-incompatible = \"1\"\n                dep-shared-compatible = \"1\"\n                dep-shared-incompatible = \"1\"\n            \"#,\n        )\n        .file(\"high/src/main.rs\", \"fn main(){}\")\n        .file(\n            \"low/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"low\"\n                edition = \"2015\"\n                rust-version = \"1.60.0\"\n\n                [dependencies]\n                dep-only-low-compatible = \"1\"\n                dep-only-low-incompatible = \"1\"\n                dep-shared-compatible = \"1\"\n                dep-shared-incompatible = \"1\"\n            \"#,\n        )\n        .file(\"low/src/main.rs\", \"fn main(){}\")\n        .file(\n            \"unset/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"unset\"\n                edition = \"2015\"\n\n                [dependencies]\n                dep-only-unset-unset = \"1\"\n                dep-only-unset-compatible = \"1\"\n                dep-only-unset-incompatible = \"1\"\n                dep-shared-compatible = \"1\"\n                dep-shared-incompatible = \"1\"\n            \"#,\n        )\n        .file(\"unset/src/main.rs\", \"fn main(){}\")\n        .build();\n\n    p.cargo(\"update\")\n        .env(\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\", \"fallback\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 9 packages to latest Rust 1.60.0 compatible versions\n[ADDING] dep-only-high-incompatible v1.75.0 (requires Rust 1.75.0)\n[ADDING] dep-only-low-incompatible v1.75.0 (requires Rust 1.75.0)\n[ADDING] dep-only-unset-incompatible v1.2345.0 (requires Rust 1.2345.0)\n[ADDING] dep-shared-incompatible v1.75.0 (requires Rust 1.75.0)\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/rustc.rs",
    "content": "//! Tests for the `cargo rustc` command.\n\nuse crate::prelude::*;\nuse cargo_test_support::basic_bin_manifest;\nuse cargo_test_support::basic_lib_manifest;\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\nuse cargo_test_support::target_spec_json;\n\n#[cargo_test]\nfn build_lib_for_foo() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", r#\" \"#)\n        .build();\n\n    p.cargo(\"rustc --lib -v\").with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] [..]--out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn lib() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", r#\" \"#)\n        .build();\n\n    p.cargo(\"rustc --lib -v -- -C debug-assertions=off\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] [..]--out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps[..]-C debug-assertions=off[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_main_and_allow_unstable_options() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", r#\" \"#)\n        .build();\n\n    p.cargo(\"rustc -v --bin foo -- -C debug-assertions\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps --extern foo=[ROOT]/foo/target/debug/deps/libfoo-[HASH].rlib[..]-C debug-assertions[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fails_when_trying_to_build_main_and_lib_with_args() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", r#\" \"#)\n        .build();\n\n    p.cargo(\"rustc -v -- -C debug-assertions\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] extra arguments to `rustc` can only be passed to one target, consider filtering\nthe package by passing, e.g., `--lib` or `--bin NAME` to specify a single target\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_with_args_to_one_of_multiple_binaries() {\n    let p = project()\n        .file(\"src/bin/foo.rs\", \"fn main() {}\")\n        .file(\"src/bin/bar.rs\", \"fn main() {}\")\n        .file(\"src/bin/baz.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", r#\" \"#)\n        .build();\n\n    p.cargo(\"rustc -v --bin bar -- -C debug-assertions\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [..]`\n[RUNNING] `rustc --crate-name bar --edition=2015 src/bin/bar.rs [..]--crate-type bin --emit=[..]link[..]-C debuginfo=2 [..]-C debug-assertions[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fails_with_args_to_all_binaries() {\n    let p = project()\n        .file(\"src/bin/foo.rs\", \"fn main() {}\")\n        .file(\"src/bin/bar.rs\", \"fn main() {}\")\n        .file(\"src/bin/baz.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", r#\" \"#)\n        .build();\n\n    p.cargo(\"rustc -v -- -C debug-assertions\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] extra arguments to `rustc` can only be passed to one target, consider filtering\nthe package by passing, e.g., `--lib` or `--bin NAME` to specify a single target\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fails_with_crate_type_to_multi_binaries() {\n    let p = project()\n        .file(\"src/bin/foo.rs\", \"fn main() {}\")\n        .file(\"src/bin/bar.rs\", \"fn main() {}\")\n        .file(\"src/bin/baz.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", r#\" \"#)\n        .build();\n\n    p.cargo(\"rustc --crate-type lib\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] crate types to rustc can only be passed to one target, consider filtering\nthe package by passing, e.g., `--lib` or `--example` to specify a single target\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fails_with_crate_type_to_multi_examples() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [[example]]\n            name = \"ex1\"\n            crate-type = [\"rlib\"]\n            [[example]]\n            name = \"ex2\"\n            crate-type = [\"rlib\"]\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex1.rs\", \"\")\n        .file(\"examples/ex2.rs\", \"\")\n        .build();\n\n    p.cargo(\"rustc -v --example ex1 --example ex2 --crate-type lib,cdylib\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] crate types to rustc can only be passed to one target, consider filtering\nthe package by passing, e.g., `--lib` or `--example` to specify a single target\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fails_with_crate_type_to_binary() {\n    let p = project().file(\"src/bin/foo.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"rustc --crate-type lib\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] crate types can only be specified for libraries and example libraries.\nBinaries, tests, and benchmarks are always the `bin` crate type\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_with_crate_type_for_foo() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"rustc -v --crate-type cdylib\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type cdylib [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_with_crate_type_for_foo_with_deps() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            extern crate a;\n            pub fn foo() { a::hello(); }\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"pub fn hello() {}\")\n        .build();\n\n    p.cargo(\"rustc -v --crate-type cdylib\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] a v0.1.0 ([ROOT]/foo/a)\n[RUNNING] `rustc --crate-name a --edition=2015 a/src/lib.rs [..]--crate-type lib [..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type cdylib [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_with_crate_types_for_foo() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"rustc -v --crate-type lib,cdylib\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --crate-type cdylib [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_with_crate_type_to_example() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [[example]]\n            name = \"ex\"\n            crate-type = [\"rlib\"]\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"\")\n        .build();\n\n    p.cargo(\"rustc -v --example ex --crate-type cdylib\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib [..]`\n[RUNNING] `rustc --crate-name ex --edition=2015 examples/ex.rs [..]--crate-type cdylib [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_with_crate_types_to_example() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [[example]]\n            name = \"ex\"\n            crate-type = [\"rlib\"]\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex.rs\", \"\")\n        .build();\n\n    p.cargo(\"rustc -v --example ex --crate-type lib,cdylib\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib [..]`\n[RUNNING] `rustc --crate-name ex --edition=2015 examples/ex.rs [..]--crate-type lib --crate-type cdylib [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_with_crate_types_to_one_of_multi_examples() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [[example]]\n            name = \"ex1\"\n            crate-type = [\"rlib\"]\n            [[example]]\n            name = \"ex2\"\n            crate-type = [\"rlib\"]\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/ex1.rs\", \"\")\n        .file(\"examples/ex2.rs\", \"\")\n        .build();\n\n    p.cargo(\"rustc -v --example ex1 --crate-type lib,cdylib\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib [..]`\n[RUNNING] `rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type lib --crate-type cdylib [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_with_args_to_one_of_multiple_tests() {\n    let p = project()\n        .file(\"tests/foo.rs\", r#\" \"#)\n        .file(\"tests/bar.rs\", r#\" \"#)\n        .file(\"tests/baz.rs\", r#\" \"#)\n        .file(\"src/lib.rs\", r#\" \"#)\n        .build();\n\n    p.cargo(\"rustc -v --test bar -- -C debug-assertions\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [..]`\n[RUNNING] `rustc --crate-name bar --edition=2015 tests/bar.rs [..]--emit=[..]link[..]-C debuginfo=2 [..]--test[..]-C debug-assertions[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_foo_with_bar_dependency() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() { bar::baz() }\")\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    foo.cargo(\"rustc -v -- -C debug-assertions\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.1.0 ([ROOT]/bar)\n[RUNNING] `rustc --crate-name bar [..] -C debuginfo=2[..]`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] -C debuginfo=2 [..]-C debug-assertions[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_only_bar_dependency() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() { bar::baz() }\")\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    foo.cargo(\"rustc -v -p bar -- -C debug-assertions\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.1.0 ([ROOT]/bar)\n[RUNNING] `rustc --crate-name bar [..]--crate-type lib [..] -C debug-assertions[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn targets_selected_default() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"rustc -v\")\n        // bin\n        .with_stderr_contains(\n            \"[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin \\\n             --emit=[..]link[..]\",\n        )\n        // bench\n        .with_stderr_does_not_contain(\n            \"[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link \\\n             -C opt-level=3 --test [..]\",\n        )\n        // unit test\n        .with_stderr_does_not_contain(\n            \"[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link \\\n             -C debuginfo=2 [..]--test [..]\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn targets_selected_all() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"rustc -v --all-targets\")\n        // bin and unit test\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link[..]`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit[..]link[..] -C debuginfo=2 [..]--test [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]].unordered()\n        )\n        .run();\n}\n\n#[cargo_test]\nfn fail_with_multiple_packages() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                    path = \"../bar\"\n\n                [dependencies.baz]\n                    path = \"../baz\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    if cfg!(flag = \"1\") { println!(\"Yeah from bar!\"); }\n                }\n            \"#,\n        )\n        .build();\n\n    let _baz = project()\n        .at(\"baz\")\n        .file(\"Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    if cfg!(flag = \"1\") { println!(\"Yeah from baz!\"); }\n                }\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"rustc -v -p bar -p baz\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] the argument '--package [<SPEC>]' cannot be used multiple times\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fail_with_bad_bin_no_package() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() { println!(\"hello a.rs\"); }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"rustc --bin main\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no bin target named `main`\n[HELP] available bin targets:\n    foo\n...\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fail_with_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {  break_the_build(); }\")\n        .build();\n\n    p.cargo(\"rustc -p '*z'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] glob patterns on package selection are not supported.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustc_with_other_profile() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dev-dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[cfg(test)] extern crate a;\n\n                #[test]\n                fn foo() {}\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"rustc --profile test\").run();\n}\n\n#[cargo_test]\nfn rustc_fingerprint() {\n    // Verify that the fingerprint includes the rustc args.\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"rustc -v -- -C debug-assertions\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]-C debug-assertions[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"rustc -v -- -C debug-assertions\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"rustc -v\")\n        .with_stderr_does_not_contain(\"-C debug-assertions\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"rustc -v\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustc_test_with_implicit_bin() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[cfg(foo)]\n                fn f() { compile_fail!(\"Foo shouldn't be set.\"); }\n                fn main() {}\n            \"#,\n        )\n        .file(\n            \"tests/test1.rs\",\n            r#\"\n                #[cfg(not(foo))]\n                fn f() { compile_fail!(\"Foo should be set.\"); }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"rustc --test test1 -v -- --cfg foo\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name test1 --edition=2015 tests/test1.rs [..] --cfg foo[..]`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]`\n...\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn rustc_with_print_cfg_single_target() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", r#\"fn main() {} \"#)\n        .build();\n\n    p.cargo(\"rustc -Z unstable-options --target x86_64-pc-windows-msvc --print cfg\")\n        .masquerade_as_nightly_cargo(&[\"print\"])\n        .with_stdout_data(\n            str![[r#\"\ndebug_assertions\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"pc\"\nwindows\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn rustc_with_print_cfg_multiple_targets() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", r#\"fn main() {} \"#)\n        .build();\n\n    p.cargo(\"rustc -Z unstable-options --target x86_64-pc-windows-msvc --target i686-unknown-linux-gnu --print cfg\")\n        .masquerade_as_nightly_cargo(&[\"print\"])\n        .with_stdout_data(str![[r#\"\ndebug_assertions\ntarget_arch=\"x86\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"32\"\ntarget_vendor=\"unknown\"\nunix\ndebug_assertions\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"pc\"\nwindows\n...\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn rustc_with_print_cfg_rustflags_env_var() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", r#\"fn main() {} \"#)\n        .build();\n\n    p.cargo(\"rustc -Z unstable-options --target x86_64-pc-windows-msvc --print cfg\")\n        .masquerade_as_nightly_cargo(&[\"print\"])\n        .env(\"RUSTFLAGS\", \"-C target-feature=+crt-static\")\n        .with_stdout_data(\n            str![[r#\"\ndebug_assertions\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_feature=\"crt-static\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"pc\"\nwindows\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn rustc_with_print_cfg_config_toml() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n[target.x86_64-pc-windows-msvc]\nrustflags = [\"-C\", \"target-feature=+crt-static\"]\n\"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() {} \"#)\n        .build();\n\n    p.cargo(\"rustc -Z unstable-options --target x86_64-pc-windows-msvc --print cfg\")\n        .masquerade_as_nightly_cargo(&[\"print\"])\n        .env(\"RUSTFLAGS\", \"-C target-feature=+crt-static\")\n        .with_stdout_data(\n            str![[r#\"\ndebug_assertions\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_feature=\"crt-static\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"pc\"\nwindows\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"custom targets are unstable in rustc\")]\nfn rustc_with_print_cfg_config_toml_env() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"targets/best-target.json\", target_spec_json())\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n[build]\ntarget = \"best-target\"\n[env]\nRUST_TARGET_PATH = { value = \"./targets\", relative = true }\n\"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() {} \"#)\n        .build();\n\n    p.cargo(\"rustc -Z unstable-options --print cfg\")\n        .masquerade_as_nightly_cargo(&[\"print\"])\n        .with_stdout_data(str![\"...\"].unordered())\n        .env(\"RUSTFLAGS\", \"-Z unstable-options\")\n        .run();\n}\n\n#[cargo_test]\nfn precedence() {\n    // Ensure that the precedence of cargo-rustc is only lower than RUSTFLAGS,\n    // but higher than most flags set by cargo.\n    //\n    // See rust-lang/cargo#14346\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            edition = \"2021\"\n\n            [lints.rust]\n            unexpected_cfgs = \"allow\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"rustc --release -v -- --cfg cargo_rustc -C strip=symbols\")\n        .env(\"RUSTFLAGS\", \"--cfg from_rustflags\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]-C strip=debuginfo [..]--cfg cargo_rustc -C strip=symbols --cfg from_rustflags`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_with_duplicate_crate_types() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"rustc -v --crate-type staticlib --crate-type staticlib\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] --crate-type staticlib --emit[..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"rustc -v --crate-type staticlib --crate-type staticlib\")\n        .with_stderr_data(str![[r#\"\n[FRESH] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/rustc_info_cache.rs",
    "content": "//! Tests for the cache file for the rustc version info.\n\nuse std::env;\n\nuse crate::prelude::*;\nuse cargo_test_support::basic_bin_manifest;\nuse cargo_test_support::{basic_manifest, project};\n\nconst MISS: &str = \"[..] rustc info cache miss[..]\";\nconst HIT: &str = \"[..]rustc info cache hit[..]\";\nconst UPDATE: &str = \"[..]updated rustc info cache[..]\";\n\n#[cargo_test]\nfn rustc_info_cache() {\n    let p = project()\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    p.cargo(\"build\")\n        .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n        .with_stderr_contains(\"[..]failed to read rustc info cache[..]\")\n        .with_stderr_contains(MISS)\n        .with_stderr_does_not_contain(HIT)\n        .with_stderr_contains(UPDATE)\n        .run();\n\n    p.cargo(\"build\")\n        .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n        .with_stderr_contains(\"[..]reusing existing rustc info cache[..]\")\n        .with_stderr_contains(HIT)\n        .with_stderr_does_not_contain(MISS)\n        .with_stderr_does_not_contain(UPDATE)\n        .run();\n\n    p.cargo(\"build\")\n        .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n        .env(\"CARGO_CACHE_RUSTC_INFO\", \"0\")\n        .with_stderr_contains(\"[..]rustc info cache disabled[..]\")\n        .with_stderr_does_not_contain(UPDATE)\n        .run();\n\n    let other_rustc = {\n        let p = project()\n            .at(\"compiler\")\n            .file(\"Cargo.toml\", &basic_manifest(\"compiler\", \"0.1.0\"))\n            .file(\n                \"src/main.rs\",\n                r#\"\n                    use std::process::Command;\n                    use std::env;\n\n                    fn main() {\n                        let mut cmd = Command::new(\"rustc\");\n                        for arg in env::args_os().skip(1) {\n                            cmd.arg(arg);\n                        }\n                        std::process::exit(cmd.status().unwrap().code().unwrap());\n                    }\n                \"#,\n            )\n            .build();\n        p.cargo(\"build\").run();\n\n        p.root()\n            .join(\"target/debug/compiler\")\n            .with_extension(env::consts::EXE_EXTENSION)\n    };\n\n    p.cargo(\"build\")\n        .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n        .env(\"RUSTC\", other_rustc.display().to_string())\n        .with_stderr_contains(\"[..]different compiler, creating new rustc info cache[..]\")\n        .with_stderr_contains(MISS)\n        .with_stderr_does_not_contain(HIT)\n        .with_stderr_contains(UPDATE)\n        .run();\n\n    p.cargo(\"build\")\n        .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n        .env(\"RUSTC\", other_rustc.display().to_string())\n        .with_stderr_contains(\"[..]reusing existing rustc info cache[..]\")\n        .with_stderr_contains(HIT)\n        .with_stderr_does_not_contain(MISS)\n        .with_stderr_does_not_contain(UPDATE)\n        .run();\n\n    other_rustc.move_into_the_future();\n\n    p.cargo(\"build\")\n        .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n        .env(\"RUSTC\", other_rustc.display().to_string())\n        .with_stderr_contains(\"[..]different compiler, creating new rustc info cache[..]\")\n        .with_stderr_contains(MISS)\n        .with_stderr_does_not_contain(HIT)\n        .with_stderr_contains(UPDATE)\n        .run();\n\n    p.cargo(\"build\")\n        .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n        .env(\"RUSTC\", other_rustc.display().to_string())\n        .with_stderr_contains(\"[..]reusing existing rustc info cache[..]\")\n        .with_stderr_contains(HIT)\n        .with_stderr_does_not_contain(MISS)\n        .with_stderr_does_not_contain(UPDATE)\n        .run();\n}\n\n#[cargo_test]\nfn rustc_info_cache_with_wrappers() {\n    let wrapper_project = project()\n        .at(\"wrapper\")\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"wrapper\"))\n        .file(\"src/main.rs\", r#\"fn main() { }\"#)\n        .build();\n    let wrapper = wrapper_project.bin(\"wrapper\");\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"test\"\n                version = \"0.0.0\"\n                authors = []\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { println!(\"hello\"); }\"#)\n        .build();\n\n    for &wrapper_env in [\"RUSTC_WRAPPER\", \"RUSTC_WORKSPACE_WRAPPER\"].iter() {\n        p.cargo(\"clean\").with_status(0).run();\n        wrapper_project.change_file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                let mut args = std::env::args_os();\n                let _me = args.next().unwrap();\n                let rustc = args.next().unwrap();\n                let status = std::process::Command::new(rustc).args(args).status().unwrap();\n                std::process::exit(if status.success() { 0 } else { 1 })\n            }\n            \"#,\n        );\n        wrapper_project.cargo(\"build\").with_status(0).run();\n\n        p.cargo(\"build\")\n            .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n            .env(wrapper_env, &wrapper)\n            .with_stderr_contains(\"[..]failed to read rustc info cache[..]\")\n            .with_stderr_contains(MISS)\n            .with_stderr_contains(UPDATE)\n            .with_stderr_does_not_contain(HIT)\n            .with_status(0)\n            .run();\n        p.cargo(\"build\")\n            .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n            .env(wrapper_env, &wrapper)\n            .with_stderr_contains(\"[..]reusing existing rustc info cache[..]\")\n            .with_stderr_contains(HIT)\n            .with_stderr_does_not_contain(UPDATE)\n            .with_stderr_does_not_contain(MISS)\n            .with_status(0)\n            .run();\n\n        wrapper_project.change_file(\"src/main.rs\", r#\"fn main() { panic!() }\"#);\n        wrapper_project.cargo(\"build\").with_status(0).run();\n\n        p.cargo(\"build\")\n            .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n            .env(wrapper_env, &wrapper)\n            .with_stderr_contains(\"[..]different compiler, creating new rustc info cache[..]\")\n            .with_stderr_contains(MISS)\n            .with_stderr_contains(UPDATE)\n            .with_stderr_does_not_contain(HIT)\n            .with_status(101)\n            .run();\n        p.cargo(\"build\")\n            .env(\"CARGO_LOG\", \"cargo::util::rustc=debug\")\n            .env(wrapper_env, &wrapper)\n            .with_stderr_contains(\"[..]reusing existing rustc info cache[..]\")\n            .with_stderr_contains(HIT)\n            .with_stderr_does_not_contain(UPDATE)\n            .with_stderr_does_not_contain(MISS)\n            .with_status(101)\n            .run();\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/rustdoc.rs",
    "content": "//! Tests for the `cargo rustdoc` command.\n\nuse crate::prelude::*;\nuse cargo_test_support::str;\nuse cargo_test_support::{basic_manifest, cross_compile, project};\n\nuse crate::utils::cross_compile::disabled as cross_compile_disabled;\n\n#[cargo_test]\nfn rustdoc_simple() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"rustdoc -v\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc [..] --crate-name foo src/lib.rs -o [ROOT]/foo/target/doc [..] -L dependency=[ROOT]/foo/target/debug/deps [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_simple_html() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"rustdoc --output-format html --open -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `--output-format` flag is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel\nSee https://doc.rust-lang.org/book/[..].html for more information about Rust release channels.\nSee https://github.com/rust-lang/cargo/issues/12103 for more information about the `--output-format` flag.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--output-format is unstable\")]\nfn rustdoc_simple_json() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"rustdoc -Z unstable-options --output-format json -v\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-output-format\"])\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc [..] --crate-name foo [..]-o [ROOT]/foo/target/doc [..] --output-format=json[..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo.json\n\n\"#]])\n        .run();\n    assert!(p.root().join(\"target/doc/foo.json\").is_file());\n}\n\n#[cargo_test]\nfn rustdoc_invalid_output_format() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"rustdoc -Z unstable-options --output-format pdf -v\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-output-format\"])\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid value 'pdf' for '--output-format <FMT>'\n  [possible values: html, json]\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_json_stable() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"rustdoc -Z unstable-options --output-format json -v\")\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n[ERROR] the `-Z` flag is only accepted on the nightly channel of Cargo, but this is the `stable` channel\nSee https://doc.rust-lang.org/book/[..].html for more information about Rust release channels.\n\n\"#]]\n\t    )\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_json_without_unstable_options() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"rustdoc --output-format json -v\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-output-format\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `--output-format` flag is unstable, pass `-Z unstable-options` to enable it\nSee https://github.com/rust-lang/cargo/issues/12103 for more information about the `--output-format` flag.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_args() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"rustdoc -v -- --cfg=foo\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc [..] --crate-name foo src/lib.rs -o [ROOT]/foo/target/doc [..]-C metadata=[..] -L dependency=[ROOT]/foo/target/debug/deps [..]--cfg=foo[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_binary_args_passed() {\n    let p = project().file(\"src/main.rs\", \"\").build();\n\n    p.cargo(\"rustdoc -v\")\n        .arg(\"--\")\n        .arg(\"--markdown-no-toc\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..] --markdown-no-toc[..]`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_foo_with_bar_dependency() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"extern crate bar; pub fn foo() {}\")\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    foo.cargo(\"rustdoc -v -- --cfg=foo\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[CHECKING] bar v0.0.1 ([ROOT]/bar)\n[RUNNING] `rustc [..] [ROOT]/bar/src/lib.rs [..]`\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc [..] --crate-name foo src/lib.rs -o [ROOT]/foo/target/doc [..]-C metadata=[..] -L dependency=[ROOT]/foo/target/debug/deps --extern [..]--cfg=foo[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_only_bar_dependency() {\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"extern crate bar; fn main() { bar::baz() }\")\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    foo.cargo(\"rustdoc -v -p bar -- --cfg=foo\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[DOCUMENTING] bar v0.0.1 ([ROOT]/bar)\n[RUNNING] `rustdoc [..] --crate-name bar [ROOT]/bar/src/lib.rs -o [ROOT]/foo/target/doc [..]-C metadata=[..] -L dependency=[ROOT]/foo/target/debug/deps [..]--cfg=foo[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/bar/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_same_name_documents_lib() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", r#\" \"#)\n        .build();\n\n    p.cargo(\"rustdoc -v -- --cfg=foo\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc [..] --crate-name foo src/lib.rs -o [ROOT]/foo/target/doc [..]-C metadata=[..] -L dependency=[ROOT]/foo/target/debug/deps [..]--cfg=foo[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                quux = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"rustdoc --verbose --features quux\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]feature=[..]quux[..]`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn proc_macro_crate_type() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                proc-macro = true\n\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"rustdoc --verbose\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc --edition=2015 --crate-type proc-macro [..]`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdoc_target() {\n    if cross_compile_disabled() {\n        return;\n    }\n\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"rustdoc --verbose --target\")\n        .arg(cross_compile::alternate())\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs [..]--target [ALT_TARGET] -o [ROOT]/foo/target/[ALT_TARGET]/doc [..] -L dependency=[ROOT]/foo/target/[ALT_TARGET]/debug/deps -L dependency=[ROOT]/foo/target/debug/deps[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/[..]/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fail_with_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {  break_the_build(); }\")\n        .build();\n\n    p.cargo(\"rustdoc -p '*z'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] glob patterns on package selection are not supported.\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/rustdoc_extern_html.rs",
    "content": "//! Tests for the -Zrustdoc-map feature.\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::{self, Package};\nuse cargo_test_support::{Project, paths, project, str};\n\nfn basic_project() -> Project {\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"pub struct Straw;\")\n        .publish();\n\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn myfun() -> Option<bar::Straw> {\n                    None\n                }\n            \"#,\n        )\n        .build()\n}\n\n#[cargo_test]\nfn ignores_on_stable() {\n    // Requires -Zrustdoc-map to use.\n    let p = basic_project();\n    p.cargo(\"doc -v --no-deps\")\n        .with_stderr_does_not_contain(\"[..]--extern-html-root-url[..]\")\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--extern-html-root-url is unstable\")]\nfn simple() {\n    // Basic test that it works with crates.io.\n    let p = basic_project();\n    p.cargo(\"doc -v --no-deps -Zrustdoc-map\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-map\"])\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--crate-name foo [..]--extern-html-root-url [..]bar=https://docs.rs/bar/1.0.0/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n    let myfun = p.read_file(\"target/doc/foo/fn.myfun.html\");\n    assert!(myfun.contains(r#\"href=\"https://docs.rs/bar/1.0.0/bar/struct.Straw.html\"\"#));\n}\n\n#[ignore = \"Broken, temporarily disabled until https://github.com/rust-lang/rust/pull/82776 is resolved.\"]\n#[cargo_test]\n// #[cargo_test(nightly, reason = \"--extern-html-root-url is unstable\")]\nfn std_docs() {\n    // Mapping std docs somewhere else.\n    // For local developers, skip this test if docs aren't installed.\n    let docs = std::path::Path::new(&paths::sysroot()).join(\"share/doc/rust/html\");\n    if !docs.exists() {\n        if cargo_util::is_ci() {\n            panic!(\"std docs are not installed, check that the rust-docs component is installed\");\n        } else {\n            eprintln!(\n                \"documentation not found at {}, \\\n                skipping test (run `rustdoc component add rust-docs` to install\",\n                docs.display()\n            );\n            return;\n        }\n    }\n    let p = basic_project();\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n            [doc.extern-map]\n            std = \"local\"\n        \"#,\n    );\n    p.cargo(\"doc -v --no-deps -Zrustdoc-map\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-map\"])\n        .with_stderr_contains(\"[RUNNING] `rustdoc [..]--crate-name foo [..]std=file://[..]\")\n        .run();\n    let myfun = p.read_file(\"target/doc/foo/fn.myfun.html\");\n    assert!(myfun.contains(r#\"share/doc/rust/html/core/option/enum.Option.html\"\"#));\n\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n            [doc.extern-map]\n            std = \"https://example.com/rust/\"\n        \"#,\n    );\n    p.cargo(\"doc -v --no-deps -Zrustdoc-map\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-map\"])\n        .with_stderr_contains(\n            \"[RUNNING] `rustdoc [..]--crate-name foo [..]std=https://example.com/rust/[..]\",\n        )\n        .run();\n    let myfun = p.read_file(\"target/doc/foo/fn.myfun.html\");\n    assert!(myfun.contains(r#\"href=\"https://example.com/rust/core/option/enum.Option.html\"\"#));\n}\n\n#[cargo_test(nightly, reason = \"--extern-html-root-url is unstable\")]\nfn renamed_dep() {\n    // Handles renamed dependencies.\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"pub struct Straw;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                groovy = { version = \"1.0\", package = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn myfun() -> Option<groovy::Straw> {\n                    None\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"doc -v --no-deps -Zrustdoc-map\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-map\"])\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--crate-name foo [..]--extern-html-root-url [..]bar=https://docs.rs/bar/1.0.0/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n    let myfun = p.read_file(\"target/doc/foo/fn.myfun.html\");\n    assert!(myfun.contains(r#\"href=\"https://docs.rs/bar/1.0.0/bar/struct.Straw.html\"\"#));\n}\n\n#[cargo_test(nightly, reason = \"--extern-html-root-url is unstable\")]\nfn lib_name() {\n    // Handles lib name != package name.\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"1.0.0\"\n\n                [lib]\n                name = \"rumpelstiltskin\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub struct Straw;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn myfun() -> Option<rumpelstiltskin::Straw> {\n                    None\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"doc -v --no-deps -Zrustdoc-map\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-map\"])\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--crate-name foo [..]--extern-html-root-url [..]rumpelstiltskin=https://docs.rs/bar/1.0.0/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n    let myfun = p.read_file(\"target/doc/foo/fn.myfun.html\");\n    assert!(\n        myfun.contains(r#\"href=\"https://docs.rs/bar/1.0.0/rumpelstiltskin/struct.Straw.html\"\"#)\n    );\n}\n\n#[cargo_test(nightly, reason = \"--extern-html-root-url is unstable\")]\nfn alt_registry() {\n    // Supports other registry names.\n    registry::alt_init();\n    Package::new(\"bar\", \"1.0.0\")\n        .alternative(true)\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate baz;\n                pub struct Queen;\n                pub use baz::King;\n            \"#,\n        )\n        .registry_dep(\"baz\", \"1.0\")\n        .publish();\n    Package::new(\"baz\", \"1.0.0\")\n        .alternative(true)\n        .file(\"src/lib.rs\", \"pub struct King;\")\n        .publish();\n    Package::new(\"grimm\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"pub struct Gold;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                bar = { version = \"1.0\", registry=\"alternative\" }\n                grimm = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn queen() -> bar::Queen { bar::Queen }\n                pub fn king() -> bar::King { bar::King }\n                pub fn gold() -> grimm::Gold { grimm::Gold }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [doc.extern-map.registries]\n                alternative = \"https://example.com/{pkg_name}/{version}/\"\n                crates-io = \"https://docs.rs/\"\n            \"#,\n        )\n        .build();\n    p.cargo(\"doc -v --no-deps -Zrustdoc-map\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-map\"])\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--crate-name foo [..]--extern-html-root-url [..]bar=https://example.com/bar/1.0.0/[..] --extern-html-root-url [..]baz=https://example.com/baz/1.0.0/[..] --extern-html-root-url [..]grimm=https://docs.rs/grimm/1.0.0/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n    let queen = p.read_file(\"target/doc/foo/fn.queen.html\");\n    assert!(queen.contains(r#\"href=\"https://example.com/bar/1.0.0/bar/struct.Queen.html\"\"#));\n\n    let king = p.read_file(\"target/doc/foo/fn.king.html\");\n    assert!(king.contains(r#\"href=\"https://example.com/baz/1.0.0/baz/struct.King.html\"\"#));\n\n    let gold = p.read_file(\"target/doc/foo/fn.gold.html\");\n    assert!(gold.contains(r#\"href=\"https://docs.rs/grimm/1.0.0/grimm/struct.Gold.html\"\"#));\n}\n\n#[cargo_test(nightly, reason = \"--extern-html-root-url is unstable\")]\nfn multiple_versions() {\n    // What happens when there are multiple versions.\n    // NOTE: This is currently broken behavior. Rustdoc does not provide a way\n    // to match renamed dependencies.\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"pub struct Spin;\")\n        .publish();\n    Package::new(\"bar\", \"2.0.0\")\n        .file(\"src/lib.rs\", \"pub struct Straw;\")\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                bar = \"1.0\"\n                bar2 = {version=\"2.0\", package=\"bar\"}\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n                pub fn fn1() -> bar::Spin {bar::Spin}\n                pub fn fn2() -> bar2::Straw {bar2::Straw}\n            \",\n        )\n        .build();\n    p.cargo(\"doc -v --no-deps -Zrustdoc-map\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-map\"])\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--crate-name foo [..]--extern-html-root-url [..]bar=https://docs.rs/bar/1.0.0/[..] --extern-html-root-url [..]bar=https://docs.rs/bar/2.0.0/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n    let fn1 = p.read_file(\"target/doc/foo/fn.fn1.html\");\n    // This should be 1.0.0, rustdoc seems to use the last entry when there\n    // are duplicates.\n    assert!(fn1.contains(r#\"href=\"https://docs.rs/bar/2.0.0/bar/struct.Spin.html\"\"#));\n    let fn2 = p.read_file(\"target/doc/foo/fn.fn2.html\");\n    assert!(fn2.contains(r#\"href=\"https://docs.rs/bar/2.0.0/bar/struct.Straw.html\"\"#));\n}\n\n#[cargo_test(nightly, reason = \"--extern-html-root-url is unstable\")]\nfn rebuilds_when_changing() {\n    // Make sure it rebuilds if the map changes.\n    let p = basic_project();\n    p.cargo(\"doc -v --no-deps -Zrustdoc-map\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-map\"])\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--extern-html-root-url[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n\n    // This also tests that the map for docs.rs can be overridden.\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n            [doc.extern-map.registries]\n            crates-io = \"https://example.com/\"\n        \"#,\n    );\n    p.cargo(\"doc -v --no-deps -Zrustdoc-map\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-map\"])\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--extern-html-root-url [..]bar=https://example.com/bar/1.0.0/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"--extern-html-root-url is unstable\")]\nfn alt_sparse_registry() {\n    // Supports other registry names.\n\n    registry::init();\n    let _registry = registry::RegistryBuilder::new()\n        .http_index()\n        .alternative()\n        .build();\n\n    Package::new(\"bar\", \"1.0.0\")\n        .alternative(true)\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate baz;\n                pub struct Queen;\n                pub use baz::King;\n            \"#,\n        )\n        .registry_dep(\"baz\", \"1.0\")\n        .publish();\n    Package::new(\"baz\", \"1.0.0\")\n        .alternative(true)\n        .file(\"src/lib.rs\", \"pub struct King;\")\n        .publish();\n    Package::new(\"grimm\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"pub struct Gold;\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                bar = { version = \"1.0\", registry=\"alternative\" }\n                grimm = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn queen() -> bar::Queen { bar::Queen }\n                pub fn king() -> bar::King { bar::King }\n                pub fn gold() -> grimm::Gold { grimm::Gold }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [doc.extern-map.registries]\n                alternative = \"https://example.com/{pkg_name}/{version}/\"\n                crates-io = \"https://docs.rs/\"\n            \"#,\n        )\n        .build();\n    p.cargo(\"doc -v --no-deps -Zrustdoc-map\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-map\"])\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..]--crate-name foo [..]--extern-html-root-url [..]bar=https://example.com/bar/1.0.0/[..] --extern-html-root-url [..]baz=https://example.com/baz/1.0.0/[..] --extern-html-root-url [..]grimm=https://docs.rs/grimm/1.0.0/[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n    let queen = p.read_file(\"target/doc/foo/fn.queen.html\");\n    assert!(queen.contains(r#\"href=\"https://example.com/bar/1.0.0/bar/struct.Queen.html\"\"#));\n\n    let king = p.read_file(\"target/doc/foo/fn.king.html\");\n    assert!(king.contains(r#\"href=\"https://example.com/baz/1.0.0/baz/struct.King.html\"\"#));\n\n    let gold = p.read_file(\"target/doc/foo/fn.gold.html\");\n    assert!(gold.contains(r#\"href=\"https://docs.rs/grimm/1.0.0/grimm/struct.Gold.html\"\"#));\n}\n\n#[cargo_test(nightly, reason = \"--extern-html-root-url is unstable\")]\nfn same_deps_multi_occurrence_in_dep_tree() {\n    // rust-lang/cargo#13543\n    Package::new(\"baz\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n    Package::new(\"bar\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"\")\n        .dep(\"baz\", \"1.0\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2018\"\n\n                [dependencies]\n                bar = \"1.0\"\n                baz = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [doc.extern-map.registries]\n                crates-io = \"https://docs.rs/\"\n            \"#,\n        )\n        .build();\n    p.cargo(\"doc -v --no-deps -Zrustdoc-map\")\n        .masquerade_as_nightly_cargo(&[\"rustdoc-map\"])\n        .with_stderr_does_not_contain(\n            \"[..]--extern-html-root-url[..]bar=https://docs.rs\\\n             [..]--extern-html-root-url[..]baz=https://docs.rs\\\n             [..]--extern-html-root-url[..]baz=https://docs.rs[..]\",\n        )\n        .with_stderr_contains(\n            \"[..]--extern-html-root-url[..]bar=https://docs.rs\\\n             [..]--extern-html-root-url[..]baz=https://docs.rs[..]\",\n        )\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/rustdocflags.rs",
    "content": "//! Tests for setting custom rustdoc flags.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::rustc_host;\nuse cargo_test_support::rustc_host_env;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn parses_env() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"doc -v\")\n        .env(\"RUSTDOCFLAGS\", \"--cfg=foo\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..] --cfg=foo[..]`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn parses_config() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                rustdocflags = [\"--cfg\", \"foo\"]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"doc -v\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..] --cfg foo [..]`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_flags() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"doc\")\n        .env(\"RUSTDOCFLAGS\", \"--bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] Unrecognized option: 'bogus'\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rerun() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"doc\").env(\"RUSTDOCFLAGS\", \"--cfg=foo\").run();\n    p.cargo(\"doc\")\n        .env(\"RUSTDOCFLAGS\", \"--cfg=foo\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n    p.cargo(\"doc\")\n        .env(\"RUSTDOCFLAGS\", \"--cfg=bar\")\n        .with_stderr_data(str![[r#\"\n[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[GENERATED] [ROOT]/foo/target/doc/foo/index.html\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustdocflags_passed_to_rustdoc_through_cargo_test() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! ```\n                //! assert!(cfg!(do_not_choke));\n                //! ```\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test --doc\")\n        .env(\"RUSTDOCFLAGS\", \"--cfg do_not_choke\")\n        .run();\n}\n\n#[cargo_test]\nfn rustdocflags_passed_to_rustdoc_through_cargo_test_only_once() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"test --doc\")\n        .env(\"RUSTDOCFLAGS\", \"--markdown-no-toc\")\n        .run();\n}\n\n#[cargo_test]\nfn rustdocflags_misspelled() {\n    let p = project().file(\"src/main.rs\", \"fn main() { }\").build();\n\n    p.cargo(\"doc\")\n        .env(\"RUSTDOC_FLAGS\", \"foo\")\n        .with_stderr_data(str![[r#\"\n[WARNING] ignoring environment variable `RUSTDOC_FLAGS`\n  |\n  = [HELP] rustdoc flags are passed via `RUSTDOCFLAGS`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn whitespace() {\n    // Checks behavior of different whitespace characters.\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    // \"too many operands\"\n    p.cargo(\"doc\")\n        .env(\"RUSTDOCFLAGS\", \"--crate-version this has spaces\")\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] could not document `foo`\n...\n\"#]])\n        .with_status(101)\n        .run();\n\n    p.cargo(\"doc\")\n        .env_remove(\"__CARGO_TEST_FORCE_ARGFILE\") // Not applicable for argfile.\n        .env(\n            \"RUSTDOCFLAGS\",\n            \"--crate-version 1111\\n2222\\t3333\\u{00a0}4444\",\n        )\n        .run();\n\n    let contents = p.read_file(\"target/doc/foo/index.html\");\n    assert!(contents.contains(\"1111\"));\n    assert!(contents.contains(\"2222\"));\n    assert!(contents.contains(\"3333\"));\n    assert!(contents.contains(\"4444\"));\n}\n\n#[cargo_test]\nfn not_affected_by_target_rustflags() {\n    let cfg = if cfg!(windows) { \"windows\" } else { \"unix\" };\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.'cfg({cfg})']\n                    rustflags = [\"-D\", \"missing-docs\"]\n\n                    [build]\n                    rustdocflags = [\"--cfg\", \"foo\"]\n                \"#,\n            ),\n        )\n        .build();\n\n    // `cargo build` should fail due to missing docs.\n    p.cargo(\"build -v\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustc [..] -D missing-docs`\n...\n\"#]])\n        .run();\n\n    // `cargo doc` shouldn't fail.\n    p.cargo(\"doc -v\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..] --cfg foo[..]`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_triple_rustdocflags_works() {\n    let host = rustc_host();\n    let host_env = rustc_host_env();\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    // target.triple.rustdocflags in env works\n    p.cargo(\"doc -v\")\n        .env(\n            &format!(\"CARGO_TARGET_{host_env}_RUSTDOCFLAGS\"),\n            \"--cfg=foo\",\n        )\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc[..]--cfg[..]foo[..]`\n...\n\"#]])\n        .run();\n\n    // target.triple.rustdocflags in config works\n    p.cargo(\"doc -v\")\n        .arg(\"--config\")\n        .arg(format!(\"target.{host}.rustdocflags=['--cfg', 'foo']\"))\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc [..] --cfg foo [..]`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_triple_rustdocflags_works_through_cargo_test() {\n    let host = rustc_host();\n    let host_env = rustc_host_env();\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! ```\n                //! assert!(cfg!(foo));\n                //! ```\n            \"#,\n        )\n        .build();\n\n    // target.triple.rustdocflags in env works\n    p.cargo(\"test --doc -v\")\n        .env(\n            &format!(\"CARGO_TARGET_{host_env}_RUSTDOCFLAGS\"),\n            \"--cfg=foo\",\n        )\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc[..]--test[..]--cfg[..]foo[..]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest src/lib.rs - (line 2) ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    // target.triple.rustdocflags in config works\n    p.cargo(\"test --doc -v\")\n        .arg(\"--config\")\n        .arg(format!(\"target.{host}.rustdocflags=['--cfg', 'foo']\"))\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `rustdoc[..]--test[..]--cfg[..]foo[..]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest src/lib.rs - (line 2) ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/rustflags.rs",
    "content": "//! Tests for setting custom rustc flags.\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{\n    RawOutput, basic_manifest, paths, project, project_in_home, rustc_host, str,\n};\nuse snapbox::assert_data_eq;\n\n#[cargo_test]\nfn env_rustflags_normal_source() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .file(\"tests/c.rs\", \"#[test] fn f() { }\")\n        .file(\n            \"benches/d.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run1(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .build();\n\n    // Use RUSTFLAGS to pass an argument that will generate an error\n    p.cargo(\"check --lib\")\n        .env(\"RUSTFLAGS\", \"-Z bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"check --bin=a\")\n        .env(\"RUSTFLAGS\", \"-Z bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"check --example=b\")\n        .env(\"RUSTFLAGS\", \"-Z bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"test\")\n        .env(\"RUSTFLAGS\", \"-Z bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"bench\")\n        .env(\"RUSTFLAGS\", \"-Z bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_rustflags_build_script() {\n    // RUSTFLAGS should be passed to rustc for build scripts\n    // when --target is not specified.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() { assert!(cfg!(foo)); }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\").env(\"RUSTFLAGS\", \"--cfg foo\").run();\n}\n\n#[cargo_test]\nfn env_rustflags_build_script_dep() {\n    // RUSTFLAGS should be passed to rustc for build scripts\n    // when --target is not specified.\n    // In this test if --cfg foo is not passed the build will fail.\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                build = \"build.rs\"\n\n                [build-dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                fn bar() { }\n                #[cfg(not(foo))]\n                fn bar() { }\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"check\").env(\"RUSTFLAGS\", \"--cfg foo\").run();\n}\n\n#[cargo_test]\nfn env_rustflags_normal_source_with_target() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .file(\"tests/c.rs\", \"#[test] fn f() { }\")\n        .file(\n            \"benches/d.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run1(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .build();\n\n    let host = &rustc_host();\n\n    // Use RUSTFLAGS to pass an argument that will generate an error\n    p.cargo(\"check --lib --target\")\n        .arg(host)\n        .env(\"RUSTFLAGS\", \"-Z bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"check --bin=a --target\")\n        .arg(host)\n        .env(\"RUSTFLAGS\", \"-Z bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"check --example=b --target\")\n        .arg(host)\n        .env(\"RUSTFLAGS\", \"-Z bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"test --target\")\n        .arg(host)\n        .env(\"RUSTFLAGS\", \"-Z bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"bench --target\")\n        .arg(host)\n        .env(\"RUSTFLAGS\", \"-Z bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_rustflags_build_script_with_target() {\n    // RUSTFLAGS should not be passed to rustc for build scripts\n    // when --target is specified.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() { assert!(!cfg!(foo)); }\n            \"#,\n        )\n        .build();\n\n    let host = rustc_host();\n    p.cargo(\"check --target\")\n        .arg(host)\n        .env(\"RUSTFLAGS\", \"--cfg foo\")\n        .run();\n}\n\n#[cargo_test]\nfn env_rustflags_build_script_with_target_doesnt_apply_to_host_kind() {\n    // RUSTFLAGS should *not* be passed to rustc for build scripts when --target is specified as the\n    // host triple even if target-applies-to-host-kind is enabled, to match legacy Cargo behavior.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() { assert!(!cfg!(foo)); }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                target-applies-to-host = true\n            \"#,\n        )\n        .build();\n\n    let host = rustc_host();\n    p.cargo(\"check --target\")\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .arg(host)\n        .arg(\"-Ztarget-applies-to-host\")\n        .env(\"RUSTFLAGS\", \"--cfg foo\")\n        .run();\n}\n\n#[cargo_test]\nfn env_rustflags_build_script_dep_with_target() {\n    // RUSTFLAGS should not be passed to rustc for build scripts\n    // when --target is specified.\n    // In this test if --cfg foo is passed the build will fail.\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                build = \"build.rs\"\n\n                [build-dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                fn bar() { }\n                #[cfg(foo)]\n                fn bar() { }\n            \"#,\n        )\n        .build();\n\n    let host = rustc_host();\n    foo.cargo(\"check --target\")\n        .arg(host)\n        .env(\"RUSTFLAGS\", \"--cfg foo\")\n        .run();\n}\n\n#[cargo_test]\nfn env_rustflags_recompile() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"check\").run();\n    // Setting RUSTFLAGS forces a recompile\n    p.cargo(\"check\")\n        .env(\"RUSTFLAGS\", \"-Z bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_rustflags_recompile2() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"check\").env(\"RUSTFLAGS\", \"--cfg foo\").run();\n    // Setting RUSTFLAGS forces a recompile\n    p.cargo(\"check\")\n        .env(\"RUSTFLAGS\", \"-Z bogus\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_rustflags_no_recompile() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"check\").env(\"RUSTFLAGS\", \"--cfg foo\").run();\n    p.cargo(\"check\")\n        .env(\"RUSTFLAGS\", \"--cfg foo\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_rustflags_normal_source() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .file(\"tests/c.rs\", \"#[test] fn f() { }\")\n        .file(\n            \"benches/d.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run1(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            rustflags = [\"-Z\", \"bogus\"]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check --lib\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"check --bin=a\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"check --example=b\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"bench\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_rustflags_build_script() {\n    // RUSTFLAGS should be passed to rustc for build scripts\n    // when --target is not specified.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() { assert!(cfg!(foo)); }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            rustflags = [\"--cfg\", \"foo\"]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn build_rustflags_build_script_dep() {\n    // RUSTFLAGS should be passed to rustc for build scripts\n    // when --target is not specified.\n    // In this test if --cfg foo is not passed the build will fail.\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                build = \"build.rs\"\n\n                [build-dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            rustflags = [\"--cfg\", \"foo\"]\n            \"#,\n        )\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                fn bar() { }\n                #[cfg(not(foo))]\n                fn bar() { }\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn build_rustflags_normal_source_with_target() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .file(\"tests/c.rs\", \"#[test] fn f() { }\")\n        .file(\n            \"benches/d.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run1(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            rustflags = [\"-Z\", \"bogus\"]\n            \"#,\n        )\n        .build();\n\n    let host = &rustc_host();\n\n    // Use build.rustflags to pass an argument that will generate an error\n    p.cargo(\"check --lib --target\")\n        .arg(host)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"check --bin=a --target\")\n        .arg(host)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"check --example=b --target\")\n        .arg(host)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"test --target\")\n        .arg(host)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"bench --target\")\n        .arg(host)\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_rustflags_build_script_with_target() {\n    // RUSTFLAGS should not be passed to rustc for build scripts\n    // when --target is specified.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() { assert!(!cfg!(foo)); }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            rustflags = [\"--cfg\", \"foo\"]\n            \"#,\n        )\n        .build();\n\n    let host = rustc_host();\n    p.cargo(\"check --target\").arg(host).run();\n}\n\n#[cargo_test]\nfn build_rustflags_build_script_dep_with_target() {\n    // RUSTFLAGS should not be passed to rustc for build scripts\n    // when --target is specified.\n    // In this test if --cfg foo is passed the build will fail.\n    let foo = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                build = \"build.rs\"\n\n                [build-dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            rustflags = [\"--cfg\", \"foo\"]\n            \"#,\n        )\n        .build();\n    let _bar = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                fn bar() { }\n                #[cfg(foo)]\n                fn bar() { }\n            \"#,\n        )\n        .build();\n\n    let host = rustc_host();\n    foo.cargo(\"check --target\").arg(host).run();\n}\n\n#[cargo_test]\nfn build_rustflags_recompile() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"check\").run();\n\n    // Setting RUSTFLAGS forces a recompile\n    let config = r#\"\n        [build]\n        rustflags = [\"-Z\", \"bogus\"]\n        \"#;\n    let config_file = paths::root().join(\"foo/.cargo/config.toml\");\n    fs::create_dir_all(config_file.parent().unwrap()).unwrap();\n    fs::write(config_file, config).unwrap();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_rustflags_recompile2() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"check\").env(\"RUSTFLAGS\", \"--cfg foo\").run();\n\n    // Setting RUSTFLAGS forces a recompile\n    let config = r#\"\n        [build]\n        rustflags = [\"-Z\", \"bogus\"]\n        \"#;\n    let config_file = paths::root().join(\"foo/.cargo/config.toml\");\n    fs::create_dir_all(config_file.parent().unwrap()).unwrap();\n    fs::write(config_file, config).unwrap();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_rustflags_no_recompile() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            rustflags = [\"--cfg\", \"foo\"]\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\").env(\"RUSTFLAGS\", \"--cfg foo\").run();\n    p.cargo(\"check\")\n        .env(\"RUSTFLAGS\", \"--cfg foo\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn build_rustflags_with_home_config() {\n    // We need a config file inside the home directory\n    let home = paths::home();\n    let home_config = home.join(\".cargo\");\n    fs::create_dir(&home_config).unwrap();\n    fs::write(\n        &home_config.join(\"config\"),\n        r#\"\n            [build]\n            rustflags = [\"-Cllvm-args=-x86-asm-syntax=intel\"]\n        \"#,\n    )\n    .unwrap();\n\n    // And we need the project to be inside the home directory\n    // so the walking process finds the home project twice.\n    let p = project_in_home(\"foo\").file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"check -v\").run();\n}\n\n#[cargo_test]\nfn target_rustflags_normal_source() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .file(\"tests/c.rs\", \"#[test] fn f() { }\")\n        .file(\n            \"benches/d.rs\",\n            r#\"\n            #![feature(test)]\n            extern crate test;\n            #[bench] fn run1(_ben: &mut test::Bencher) { }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                \"\n            [target.{}]\n            rustflags = [\\\"-Z\\\", \\\"bogus\\\"]\n            \",\n                rustc_host()\n            ),\n        )\n        .build();\n\n    p.cargo(\"check --lib\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"check --bin=a\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"check --example=b\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"bench\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_rustflags_also_for_build_scripts() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() { assert!(cfg!(foo)); }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                \"\n            [target.{}]\n            rustflags = [\\\"--cfg=foo\\\"]\n            \",\n                rustc_host()\n            ),\n        )\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn target_rustflags_not_for_build_scripts_with_target() {\n    let host = rustc_host();\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() { assert!(!cfg!(foo)); }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                \"\n            [target.{}]\n            rustflags = [\\\"--cfg=foo\\\"]\n            \",\n                host\n            ),\n        )\n        .build();\n\n    p.cargo(\"check --target\").arg(host).run();\n\n    // Enabling -Ztarget-applies-to-host should not make a difference without the config setting\n    p.cargo(\"check --target\")\n        .arg(host)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .arg(\"-Ztarget-applies-to-host\")\n        .run();\n\n    // Even with the setting, the rustflags from `target.` should not apply, to match the legacy\n    // Cargo behavior.\n    p.change_file(\n        \".cargo/config.toml\",\n        &format!(\n            \"\n        target-applies-to-host = true\n\n        [target.{}]\n        rustflags = [\\\"--cfg=foo\\\"]\n        \",\n            host\n        ),\n    );\n    p.cargo(\"check --target\")\n        .arg(host)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .arg(\"-Ztarget-applies-to-host\")\n        .run();\n}\n\n#[cargo_test]\nfn build_rustflags_for_build_scripts() {\n    let host = rustc_host();\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() { assert!(cfg!(foo), \"CFG FOO!\"); }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            \"\n            [build]\n            rustflags = [\\\"--cfg=foo\\\"]\n            \",\n        )\n        .build();\n\n    // With \"legacy\" behavior, build.rustflags should apply to build scripts without --target\n    p.cargo(\"check\").run();\n\n    // But should _not_ apply _with_ --target\n    p.cargo(\"check --target\")\n        .arg(host)\n        .with_status(101)\n        .with_stderr_data(\"...\\n[..]CFG FOO![..]\\n...\")\n        .run();\n\n    // Enabling -Ztarget-applies-to-host should not make a difference without the config setting\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .arg(\"-Ztarget-applies-to-host\")\n        .run();\n    p.cargo(\"check --target\")\n        .arg(host)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .arg(\"-Ztarget-applies-to-host\")\n        .with_status(101)\n        .with_stderr_data(\"...\\n[..]CFG FOO![..]\\n...\")\n        .run();\n\n    // When set to false though, the \"proper\" behavior where host artifacts _only_ pick up on\n    // [host] should be applied.\n    p.change_file(\n        \".cargo/config.toml\",\n        \"\n        target-applies-to-host = false\n\n        [build]\n        rustflags = [\\\"--cfg=foo\\\"]\n        \",\n    );\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .arg(\"-Ztarget-applies-to-host\")\n        .with_status(101)\n        .with_stderr_data(\"...\\n[..]CFG FOO![..]\\n...\")\n        .run();\n    p.cargo(\"check --target\")\n        .arg(host)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .arg(\"-Ztarget-applies-to-host\")\n        .with_status(101)\n        .with_stderr_data(\"...\\n[..]CFG FOO![..]\\n...\")\n        .run();\n}\n\n#[cargo_test]\nfn host_rustflags_for_build_scripts() {\n    let host = rustc_host();\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n                // Ensure that --cfg=foo is passed.\n                fn main() { assert!(cfg!(foo)); }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                \"\n                target-applies-to-host = false\n\n                [host.{}]\n                rustflags = [\\\"--cfg=foo\\\"]\n                \",\n                host\n            ),\n        )\n        .build();\n\n    p.cargo(\"check --target\")\n        .arg(host)\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .arg(\"-Ztarget-applies-to-host\")\n        .arg(\"-Zhost-config\")\n        .run();\n}\n\n// target.{}.rustflags takes precedence over build.rustflags\n#[cargo_test]\nfn target_rustflags_precedence() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .file(\"tests/c.rs\", \"#[test] fn f() { }\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                \"\n            [build]\n            rustflags = [\\\"--cfg\\\", \\\"foo\\\"]\n\n            [target.{}]\n            rustflags = [\\\"-Z\\\", \\\"bogus\\\"]\n            \",\n                rustc_host()\n            ),\n        )\n        .build();\n\n    p.cargo(\"check --lib\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"check --bin=a\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"check --example=b\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n    p.cargo(\"bench\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to run `rustc` to learn about target-specific information\n\nCaused by:\n  [..]bogus[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cfg_rustflags_normal_source() {\n    let p = project()\n        .file(\"src/lib.rs\", \"pub fn t() {}\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .file(\"tests/c.rs\", \"#[test] fn f() { }\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [target.'cfg({})']\n                rustflags = [\"--cfg\", \"bar\"]\n                \"#,\n                if rustc_host().contains(\"-windows-\") {\n                    \"windows\"\n                } else {\n                    \"not(windows)\"\n                }\n            ),\n        )\n        .build();\n\n    p.cargo(\"build --lib -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] --cfg bar`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --bin=a -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name a [..] --cfg bar`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --example=b -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name b [..] --cfg bar`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"test --no-run -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] --cfg bar`\n[RUNNING] `rustc [..] --cfg bar`\n[RUNNING] `rustc [..] --cfg bar`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/a-[HASH][EXE]`\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/c-[HASH][EXE]`\n\n\"#]])\n        .run();\n\n    p.cargo(\"bench --no-run -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] --cfg bar`\n[RUNNING] `rustc [..] --cfg bar`\n[RUNNING] `rustc [..] --cfg bar`\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n[EXECUTABLE] `[ROOT]/foo/target/release/deps/a-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n// target.'cfg(...)'.rustflags takes precedence over build.rustflags\n#[cargo_test]\nfn cfg_rustflags_precedence() {\n    let p = project()\n        .file(\"src/lib.rs\", \"pub fn t() {}\")\n        .file(\"src/bin/a.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .file(\"tests/c.rs\", \"#[test] fn f() { }\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                [build]\n                rustflags = [\"--cfg\", \"foo\"]\n\n                [target.'cfg({})']\n                rustflags = [\"--cfg\", \"bar\"]\n                \"#,\n                if rustc_host().contains(\"-windows-\") {\n                    \"windows\"\n                } else {\n                    \"not(windows)\"\n                }\n            ),\n        )\n        .build();\n\n    p.cargo(\"build --lib -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] --cfg bar`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --bin=a -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name a [..] --cfg bar`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"build --example=b -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name b [..] --cfg bar`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"test --no-run -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] --cfg bar`\n[RUNNING] `rustc [..] --cfg bar`\n[RUNNING] `rustc [..] --cfg bar`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/a-[HASH][EXE]`\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/c-[HASH][EXE]`\n\n\"#]])\n        .run();\n\n    p.cargo(\"bench --no-run -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] --cfg bar`\n[RUNNING] `rustc [..] --cfg bar`\n[RUNNING] `rustc [..] --cfg bar`\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n[EXECUTABLE] `[ROOT]/foo/target/release/deps/a-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_rustflags_string_and_array_form1() {\n    let p1 = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            rustflags = [\"--cfg\", \"foo\"]\n            \"#,\n        )\n        .build();\n\n    p1.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] --cfg foo`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let p2 = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [build]\n            rustflags = \"--cfg foo\"\n            \"#,\n        )\n        .build();\n\n    p2.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] --cfg foo`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_rustflags_string_and_array_form2() {\n    let p1 = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}]\n                    rustflags = [\"--cfg\", \"foo\"]\n                \"#,\n                rustc_host()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p1.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] --cfg foo`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let p2 = project()\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}]\n                    rustflags = \"--cfg foo\"\n                \"#,\n                rustc_host()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p2.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo [..] --cfg foo`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn two_matching_in_config() {\n    let p1 = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [target.'cfg(unix)']\n                rustflags = [\"--cfg\", 'foo=\"a\"']\n                [target.'cfg(windows)']\n                rustflags = [\"--cfg\", 'foo=\"a\"']\n                [target.'cfg(target_pointer_width = \"32\")']\n                rustflags = [\"--cfg\", 'foo=\"b\"']\n                [target.'cfg(target_pointer_width = \"64\")']\n                rustflags = [\"--cfg\", 'foo=\"b\"']\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #![allow(unexpected_cfgs)]\n                fn main() {\n                    if cfg!(foo = \"a\") {\n                        println!(\"a\");\n                    } else if cfg!(foo = \"b\") {\n                        println!(\"b\");\n                    } else {\n                        panic!()\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p1.cargo(\"run\").run();\n    p1.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn env_rustflags_misspelled() {\n    let p = project().file(\"src/main.rs\", \"fn main() { }\").build();\n\n    for cmd in &[\"check\", \"build\", \"run\", \"test\", \"bench\"] {\n        p.cargo(cmd)\n            .env(\"RUST_FLAGS\", \"foo\")\n            .with_stderr_data(str![[r#\"\n[WARNING] ignoring environment variable `RUST_FLAGS`\n  |\n  = [HELP] rust flags are passed via `RUSTFLAGS`\n...\n\"#]])\n            .run();\n    }\n}\n\n#[cargo_test]\nfn env_rustflags_misspelled_build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() { }\")\n        .build();\n\n    p.cargo(\"check\")\n        .env(\"RUST_FLAGS\", \"foo\")\n        .with_stderr_data(str![[r#\"\n[WARNING] ignoring environment variable `RUST_FLAGS`\n  |\n  = [HELP] rust flags are passed via `RUSTFLAGS`\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn remap_path_prefix_works() {\n    // Check that remap-path-prefix works.\n    Package::new(\"bar\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"pub fn f() -> &'static str { file!() }\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            bar = \"0.1\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                println!(\"{}\", bar::f());\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .env(\n            \"RUSTFLAGS\",\n            format!(\"--remap-path-prefix={}=/foo\", paths::root().display()),\n        )\n        .with_stdout_data(str![[r#\"\n/foo/home/.cargo/registry/src/-[HASH]/bar-0.1.0/src/lib.rs\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn rustflags_remap_path_prefix_ignored_for_c_metadata() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    let build_output = p\n        .cargo(\"build -v\")\n        .env(\n            \"RUSTFLAGS\",\n            \"--remap-path-prefix=/abc=/zoo --remap-path-prefix /spaced=/zoo\",\n        )\n        .run();\n    let first_c_metadata = dbg!(get_c_metadata(build_output));\n\n    p.cargo(\"clean\").run();\n\n    let build_output = p\n        .cargo(\"build -v\")\n        .env(\n            \"RUSTFLAGS\",\n            \"--remap-path-prefix=/def=/zoo --remap-path-prefix /earth=/zoo\",\n        )\n        .run();\n    let second_c_metadata = dbg!(get_c_metadata(build_output));\n\n    assert_data_eq!(first_c_metadata, second_c_metadata);\n}\n\n#[cargo_test]\nfn rustc_remap_path_prefix_ignored_for_c_metadata() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    let build_output = p\n        .cargo(\"rustc -v -- --remap-path-prefix=/abc=/zoo --remap-path-prefix /spaced=/zoo\")\n        .run();\n    let first_c_metadata = dbg!(get_c_metadata(build_output));\n\n    p.cargo(\"clean\").run();\n\n    let build_output = p\n        .cargo(\"rustc -v -- --remap-path-prefix=/def=/zoo --remap-path-prefix /earth=/zoo\")\n        .run();\n    let second_c_metadata = dbg!(get_c_metadata(build_output));\n\n    assert_data_eq!(first_c_metadata, second_c_metadata);\n}\n\n// `--remap-path-prefix` is meant to take two different binaries and make them the same but the\n// rlib name, including `-Cextra-filename`, can still end up in the binary so it can't change\n#[cargo_test]\nfn rustflags_remap_path_prefix_ignored_for_c_extra_filename() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    let build_output = p\n        .cargo(\"build -v\")\n        .env(\n            \"RUSTFLAGS\",\n            \"--remap-path-prefix=/abc=/zoo --remap-path-prefix /spaced=/zoo\",\n        )\n        .run();\n    let first_c_extra_filename = dbg!(get_c_extra_filename(build_output));\n\n    p.cargo(\"clean\").run();\n\n    let build_output = p\n        .cargo(\"build -v\")\n        .env(\n            \"RUSTFLAGS\",\n            \"--remap-path-prefix=/def=/zoo --remap-path-prefix /earth=/zoo\",\n        )\n        .run();\n    let second_c_extra_filename = dbg!(get_c_extra_filename(build_output));\n\n    assert_data_eq!(first_c_extra_filename, second_c_extra_filename);\n}\n\n// `--remap-path-prefix` is meant to take two different binaries and make them the same but the\n// rlib name, including `-Cextra-filename`, can still end up in the binary so it can't change\n#[cargo_test]\nfn rustc_remap_path_prefix_ignored_for_c_extra_filename() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    let build_output = p\n        .cargo(\"rustc -v -- --remap-path-prefix=/abc=/zoo --remap-path-prefix /spaced=/zoo\")\n        .run();\n    let first_c_extra_filename = dbg!(get_c_extra_filename(build_output));\n\n    p.cargo(\"clean\").run();\n\n    let build_output = p\n        .cargo(\"rustc -v -- --remap-path-prefix=/def=/zoo --remap-path-prefix /earth=/zoo\")\n        .run();\n    let second_c_extra_filename = dbg!(get_c_extra_filename(build_output));\n\n    assert_data_eq!(first_c_extra_filename, second_c_extra_filename);\n}\n\nfn get_c_metadata(output: RawOutput) -> String {\n    let get_c_metadata_re =\n        regex::Regex::new(r\".* (--crate-name [^ ]+).* (-C ?metadata=[^ ]+).*\").unwrap();\n\n    let stderr = String::from_utf8(output.stderr).unwrap();\n    let mut c_metadata = get_c_metadata_re\n        .captures_iter(&stderr)\n        .map(|c| {\n            let (_, [name, c_metadata]) = c.extract();\n            format!(\"{name} {c_metadata}\")\n        })\n        .collect::<Vec<_>>();\n    assert!(\n        !c_metadata.is_empty(),\n        \"`{get_c_metadata_re:?}` did not match:\\n```\\n{stderr}\\n```\"\n    );\n    c_metadata.sort();\n    c_metadata.join(\"\\n\")\n}\n\nfn get_c_extra_filename(output: RawOutput) -> String {\n    let get_c_extra_filename_re =\n        regex::Regex::new(r\".* (--crate-name [^ ]+).* (-C ?extra-filename=[^ ]+).*\").unwrap();\n\n    let stderr = String::from_utf8(output.stderr).unwrap();\n    let mut c_extra_filename = get_c_extra_filename_re\n        .captures_iter(&stderr)\n        .map(|c| {\n            let (_, [name, c_extra_filename]) = c.extract();\n            format!(\"{name} {c_extra_filename}\")\n        })\n        .collect::<Vec<_>>();\n    assert!(\n        !c_extra_filename.is_empty(),\n        \"`{get_c_extra_filename_re:?}` did not match:\\n```\\n{stderr}\\n```\"\n    );\n    c_extra_filename.sort();\n    c_extra_filename.join(\"\\n\")\n}\n\n#[cargo_test]\nfn host_config_rustflags_with_target() {\n    // regression test for https://github.com/rust-lang/cargo/issues/10206\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() { assert!(cfg!(foo)); }\")\n        .file(\".cargo/config.toml\", \"target-applies-to-host = false\")\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\", \"host-config\"])\n        .arg(\"-Zhost-config\")\n        .arg(\"-Ztarget-applies-to-host\")\n        .arg(\"-Zunstable-options\")\n        .arg(\"--config\")\n        .arg(\"host.rustflags=[\\\"--cfg=foo\\\"]\")\n        .run();\n}\n\n#[cargo_test]\nfn target_applies_to_host_rustflags_works() {\n    // Ensures that rustflags are passed to the target when\n    // target_applies_to_host=false\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"#[cfg(feature = \"flag\")] compile_error!(\"flag passed\");\"#,\n        )\n        .build();\n\n    // Use RUSTFLAGS to pass an argument that will generate an error.\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .arg(\"-Ztarget-applies-to-host\")\n        .env(\"CARGO_TARGET_APPLIES_TO_HOST\", \"false\")\n        .env(\"RUSTFLAGS\", r#\"--cfg feature=\"flag\"\"#)\n        .with_status(101)\n        .with_stderr_data(\n            \"[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] flag passed\n...\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn target_applies_to_host_rustdocflags_works() {\n    // Ensures that rustflags are passed to the target when\n    // target_applies_to_host=false\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"#[cfg(feature = \"flag\")] compile_error!(\"flag passed\");\"#,\n        )\n        .build();\n\n    // Use RUSTFLAGS to pass an argument that would generate an error\n    // but it is ignored.\n    p.cargo(\"doc\")\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .arg(\"-Ztarget-applies-to-host\")\n        .env(\"CARGO_TARGET_APPLIES_TO_HOST\", \"false\")\n        .env(\"RUSTDOCFLAGS\", r#\"--cfg feature=\"flag\"\"#)\n        .with_status(101)\n        .with_stderr_data(\n            \"[DOCUMENTING] foo v0.0.1 ([ROOT]/foo)\n[ERROR] flag passed\n...\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn host_config_shared_build_dep() {\n    // rust-lang/cargo#14253\n    Package::new(\"cc\", \"1.0.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bootstrap\"\n            edition = \"2021\"\n\n            [dependencies]\n            cc = \"1.0.0\"\n\n            [build-dependencies]\n            cc = \"1.0.0\"\n\n            [profile.dev]\n            debug = 0\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            \"\n            target-applies-to-host=false\n\n            [host]\n            rustflags = ['--cfg', 'from_host']\n\n            [build]\n            rustflags = ['--cfg', 'from_target']\n            \",\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .arg(\"-Ztarget-applies-to-host\")\n        .arg(\"-Zhost-config\")\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] cc v1.0.0 (registry `dummy-registry`)\n[COMPILING] cc v1.0.0\n[RUNNING] `rustc --crate-name cc [..]--cfg from_host[..]`\n[RUNNING] `rustc --crate-name cc [..]--cfg from_target[..]`\n[COMPILING] bootstrap v0.0.0 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name build_script_build [..]--cfg from_host[..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/bootstrap-[HASH]/build-script-build`\n[RUNNING] `rustc --crate-name bootstrap[..]--cfg from_target[..]`\n[FINISHED] `dev` profile [unoptimized] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/rustup.rs",
    "content": "//! Tests for Cargo's behavior under Rustup.\n\nuse std::env;\nuse std::env::consts::EXE_EXTENSION;\nuse std::ffi::OsString;\nuse std::fs;\nuse std::path::{Path, PathBuf};\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::paths::{home, root};\nuse cargo_test_support::{process, project, str};\n\n/// Helper to generate an executable.\nfn make_exe(dest: &Path, name: &str, contents: &str, env: &[(&str, PathBuf)]) -> PathBuf {\n    let rs_name = format!(\"{name}.rs\");\n    fs::write(\n        root().join(&rs_name),\n        &format!(\"fn main() {{ {contents} }}\"),\n    )\n    .unwrap();\n    let mut pb = process(\"rustc\");\n    env.iter().for_each(|(key, value)| {\n        pb.env(key, value);\n    });\n    pb.arg(\"--edition=2021\")\n        .arg(root().join(&rs_name))\n        .exec()\n        .unwrap();\n    let exe = Path::new(name).with_extension(EXE_EXTENSION);\n    let output = dest.join(&exe);\n    fs::rename(root().join(&exe), &output).unwrap();\n    output\n}\n\nfn prepend_path(path: &Path) -> OsString {\n    let mut paths = vec![path.to_path_buf()];\n    paths.extend(env::split_paths(&env::var_os(\"PATH\").unwrap_or_default()));\n    env::join_paths(paths).unwrap()\n}\n\nstruct RustupEnvironment {\n    /// Path for ~/.cargo/bin\n    cargo_bin: PathBuf,\n    /// Path for ~/.rustup\n    rustup_home: PathBuf,\n    /// Path to the cargo executable in the toolchain directory\n    /// (~/.rustup/toolchain/test-toolchain/bin/cargo.exe).\n    cargo_toolchain_exe: PathBuf,\n}\n\n/// Creates an executable which prints a message and then runs the *real* rustc.\nfn real_rustc_wrapper(bin_dir: &Path, message: &str) -> PathBuf {\n    let real_rustc = cargo_util::paths::resolve_executable(\"rustc\".as_ref()).unwrap();\n    // The toolchain rustc needs to call the real rustc. In order to do that,\n    // it needs to restore or clear the RUSTUP environment variables so that\n    // if rustup is installed, it will call the correct rustc.\n    let rustup_toolchain_setup = match std::env::var_os(\"RUSTUP_TOOLCHAIN\") {\n        Some(t) => format!(\n            \".env(\\\"RUSTUP_TOOLCHAIN\\\", \\\"{}\\\")\",\n            t.into_string().unwrap()\n        ),\n        None => format!(\".env_remove(\\\"RUSTUP_TOOLCHAIN\\\")\"),\n    };\n    let mut env = vec![(\"CARGO_RUSTUP_TEST_real_rustc\", real_rustc)];\n    let rustup_home_setup = match std::env::var_os(\"RUSTUP_HOME\") {\n        Some(h) => {\n            env.push((\"CARGO_RUSTUP_TEST_RUSTUP_HOME\", h.into()));\n            format!(\".env(\\\"RUSTUP_HOME\\\", env!(\\\"CARGO_RUSTUP_TEST_RUSTUP_HOME\\\"))\")\n        }\n        None => format!(\".env_remove(\\\"RUSTUP_HOME\\\")\"),\n    };\n    make_exe(\n        bin_dir,\n        \"rustc\",\n        &format!(\n            r#\"\n                eprintln!(\"{message}\");\n                let r = std::process::Command::new(env!(\"CARGO_RUSTUP_TEST_real_rustc\"))\n                    .args(std::env::args_os().skip(1))\n                    {rustup_toolchain_setup}\n                    {rustup_home_setup}\n                    .status();\n                std::process::exit(r.unwrap().code().unwrap_or(2));\n            \"#\n        ),\n        &env,\n    )\n}\n\n/// Creates a simulation of a rustup environment with `~/.cargo/bin` and\n/// `~/.rustup` directories populated with some executables that simulate\n/// rustup.\nfn simulated_rustup_environment() -> RustupEnvironment {\n    // Set up ~/.rustup/toolchains/test-toolchain/bin with a custom rustc and cargo.\n    let rustup_home = home().join(\".rustup\");\n    let toolchain_bin = rustup_home\n        .join(\"toolchains\")\n        .join(\"test-toolchain\")\n        .join(\"bin\");\n    toolchain_bin.mkdir_p();\n    let rustc_toolchain_exe = real_rustc_wrapper(&toolchain_bin, \"real rustc running\");\n    let cargo_toolchain_exe = make_exe(\n        &toolchain_bin,\n        \"cargo\",\n        r#\"panic!(\"cargo toolchain should not be called\");\"#,\n        &[],\n    );\n\n    // Set up ~/.cargo/bin with a typical set of rustup proxies.\n    let cargo_bin = home().join(\".cargo\").join(\"bin\");\n    cargo_bin.mkdir_p();\n\n    let rustc_proxy = make_exe(\n        &cargo_bin,\n        \"rustc\",\n        &format!(\n            r#\"\n                match std::env::args().next().unwrap().as_ref() {{\n                    \"rustc\" => {{}}\n                    arg => panic!(\"proxy only supports rustc, got {{arg:?}}\"),\n                }}\n                eprintln!(\"rustc proxy running\");\n                let r = std::process::Command::new(env!(\"CARGO_RUSTUP_TEST_rustc_toolchain_exe\"))\n                    .args(std::env::args_os().skip(1))\n                    .status();\n                std::process::exit(r.unwrap().code().unwrap_or(2));\n            \"#\n        ),\n        &[(\"CARGO_RUSTUP_TEST_rustc_toolchain_exe\", rustc_toolchain_exe)],\n    );\n    fs::hard_link(\n        &rustc_proxy,\n        cargo_bin.join(\"cargo\").with_extension(EXE_EXTENSION),\n    )\n    .unwrap();\n    fs::hard_link(\n        &rustc_proxy,\n        cargo_bin.join(\"rustup\").with_extension(EXE_EXTENSION),\n    )\n    .unwrap();\n\n    RustupEnvironment {\n        cargo_bin,\n        rustup_home,\n        cargo_toolchain_exe,\n    }\n}\n\n#[cargo_test]\nfn typical_rustup() {\n    // Test behavior under a typical rustup setup with a normal toolchain.\n    let RustupEnvironment {\n        cargo_bin,\n        rustup_home,\n        cargo_toolchain_exe,\n    } = simulated_rustup_environment();\n\n    // Set up a project and run a normal cargo build.\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    // The path is modified so that cargo will call `rustc` from\n    // `~/.cargo/bin/rustc to use our custom rustup proxies.\n    let path = prepend_path(&cargo_bin);\n    p.cargo(\"check\")\n        .env(\"RUSTUP_TOOLCHAIN\", \"test-toolchain\")\n        .env(\"RUSTUP_HOME\", &rustup_home)\n        .env(\"PATH\", &path)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\nreal rustc running\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Do a similar test, but with a toolchain link that does not have cargo\n    // (which normally would do a fallback to nightly/beta/stable).\n    cargo_toolchain_exe.rm_rf();\n    p.build_dir().rm_rf();\n\n    p.cargo(\"check\")\n        .env(\"RUSTUP_TOOLCHAIN\", \"test-toolchain\")\n        .env(\"RUSTUP_HOME\", &rustup_home)\n        .env(\"PATH\", &path)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\nreal rustc running\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n// This doesn't work on Windows because Cargo forces the PATH to contain the\n// sysroot_libdir, which is actually `bin`, preventing the test from\n// overriding the bin directory.\n#[cargo_test(ignore_windows = \"PATH can't be overridden on Windows\")]\nfn custom_calls_other_cargo() {\n    // Test behavior when a custom subcommand tries to manipulate PATH to use\n    // a different toolchain.\n    let RustupEnvironment {\n        cargo_bin,\n        rustup_home,\n        cargo_toolchain_exe: _,\n    } = simulated_rustup_environment();\n\n    // Create a directory with a custom toolchain (outside of the rustup universe).\n    let custom_bin = root().join(\"custom-bin\");\n    custom_bin.mkdir_p();\n    // `cargo` points to the real cargo.\n    let cargo_exe = crate::utils::cargo_exe();\n    fs::hard_link(&cargo_exe, custom_bin.join(cargo_exe.file_name().unwrap())).unwrap();\n    // `rustc` executes the real rustc.\n    real_rustc_wrapper(&custom_bin, \"custom toolchain rustc running\");\n\n    // A project that cargo-custom will try to build.\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    // Create a custom cargo subcommand.\n    // This will modify PATH to a custom toolchain and call cargo from that.\n    make_exe(\n        &cargo_bin,\n        \"cargo-custom\",\n        r#\"\n            use std::env;\n            use std::process::Command;\n\n            eprintln!(\"custom command running\");\n\n            let mut paths = vec![std::path::PathBuf::from(env!(\"CARGO_RUSTUP_TEST_custom_bin\"))];\n            paths.extend(env::split_paths(&env::var_os(\"PATH\").unwrap_or_default()));\n            let path = env::join_paths(paths).unwrap();\n\n            let status = Command::new(\"cargo\")\n                .arg(\"check\")\n                .current_dir(env!(\"CARGO_RUSTUP_TEST_project_dir\"))\n                .env(\"PATH\", path)\n                .status()\n                .unwrap();\n            assert!(status.success());\n        \"#,\n        &[\n            (\"CARGO_RUSTUP_TEST_custom_bin\", custom_bin),\n            (\"CARGO_RUSTUP_TEST_project_dir\", p.root()),\n        ],\n    );\n\n    cargo_process(\"custom\")\n        // Set these to simulate what would happen when running under rustup.\n        // We want to make sure that cargo-custom does not try to use the\n        // rustup proxies.\n        .env(\"RUSTUP_TOOLCHAIN\", \"test-toolchain\")\n        .env(\"RUSTUP_HOME\", &rustup_home)\n        .with_stderr_data(str![[r#\"\ncustom command running\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\ncustom toolchain rustc running\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/sbom.rs",
    "content": "//! Tests for cargo-sbom precursor files.\n\nuse std::path::PathBuf;\n\nuse crate::prelude::*;\nuse cargo_test_support::basic_bin_manifest;\nuse cargo_test_support::cargo_test;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse snapbox::IntoData;\n\nconst SBOM_FILE_EXTENSION: &str = \".cargo-sbom.json\";\n\nfn append_sbom_suffix(link: &PathBuf) -> PathBuf {\n    let mut link_buf = link.clone().into_os_string();\n    link_buf.push(SBOM_FILE_EXTENSION);\n    PathBuf::from(link_buf)\n}\n\n#[cargo_test]\nfn warn_without_passing_unstable_flag() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"fn main() {\n    eprintln!(\"{:?}\", option_env!(\"CARGO_SBOM_PATH\"));\n}\"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .env(\"CARGO_BUILD_SBOM\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"sbom\"])\n        .with_stderr_data(snapbox::str![[r#\"\n[WARNING] ignoring 'sbom' config, pass `-Zsbom` to enable it\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\nNone\n\n\"#]])\n        .run();\n\n    let file = append_sbom_suffix(&p.bin(\"foo\"));\n    assert!(!file.exists());\n}\n\n#[cargo_test]\nfn simple() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", r#\"fn main() {}\"#)\n        .build();\n\n    p.cargo(\"build -Zsbom\")\n        .env(\"CARGO_BUILD_SBOM\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"sbom\"])\n        .run();\n\n    let file = append_sbom_suffix(&p.bin(\"foo\"));\n    let output = std::fs::read_to_string(file).unwrap();\n    // The expected test does contain the \"rustc\" section\n    // but other tests omit them for brevity.\n    assert_e2e().eq(\n        output,\n        snapbox::str![[r#\"\n{\n  \"crates\": [\n    {\n      \"dependencies\": [],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"kind\": [\n        \"bin\"\n      ]\n    }\n  ],\n  \"root\": 0,\n  \"rustc\": {\n    \"commit_hash\": \"{...}\",\n    \"host\": \"[HOST_TARGET]\",\n    \"verbose_version\": \"{...}\",\n    \"version\": \"{...}\",\n    \"workspace_wrapper\": null,\n    \"wrapper\": null\n  },\n  \"target\": \"[HOST_TARGET]\",\n  \"version\": 1\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test]\nfn with_multiple_crate_types() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"1.2.3\"\n\n                [lib]\n                crate-type = [\"dylib\", \"rlib\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() { let _i = foo::give_five(); }\"#)\n        .file(\"src/lib.rs\", r#\"pub fn give_five() -> i32 { 5 }\"#)\n        .build();\n\n    p.cargo(\"build -Zsbom\")\n        .env(\"CARGO_BUILD_SBOM\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"sbom\"])\n        .run();\n\n    assert_eq!(\n        3,\n        p.glob(p.target_debug_dir().join(\"*.cargo-sbom.json\"))\n            .count()\n    );\n\n    let sbom_path = append_sbom_suffix(&p.dylib(\"foo\"));\n    assert!(sbom_path.is_file());\n\n    let output = std::fs::read_to_string(sbom_path).unwrap();\n    assert_e2e().eq(\n        output,\n        snapbox::str![[r#\"\n{\n  \"crates\": [\n    {\n      \"dependencies\": [],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#1.2.3\",\n      \"kind\": [\n        \"dylib\",\n        \"rlib\"\n      ]\n    }\n  ],\n  \"root\": 0,\n  \"rustc\": \"{...}\",\n  \"target\": \"[HOST_TARGET]\",\n  \"version\": 1\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test]\nfn with_simple_build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"#[cfg(foo)] fn main() {}\")\n        .file(\n            \"build.rs\",\n            r#\"fn main() {\n                println!(\"cargo::rustc-check-cfg=cfg(foo)\");\n                println!(\"cargo::rustc-cfg=foo\");\n            }\"#,\n        )\n        .build();\n\n    p.cargo(\"build -Zsbom\")\n        .env(\"CARGO_BUILD_SBOM\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"sbom\"])\n        .run();\n\n    let path = append_sbom_suffix(&p.bin(\"foo\"));\n    assert!(path.is_file());\n\n    let output = std::fs::read_to_string(path).unwrap();\n    assert_e2e().eq(\n        output,\n        snapbox::str![[r#\"\n{\n  \"crates\": [\n    {\n      \"dependencies\": [\n        {\n          \"index\": 1,\n          \"kind\": \"build\"\n        }\n      ],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#0.0.1\",\n      \"kind\": [\n        \"bin\"\n      ]\n    },\n    {\n      \"dependencies\": [],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#0.0.1\",\n      \"kind\": [\n        \"custom-build\"\n      ]\n    }\n  ],\n  \"root\": 0,\n  \"rustc\": \"{...}\",\n  \"target\": \"[HOST_TARGET]\",\n  \"version\": 1\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test]\nfn with_build_dependencies() {\n    Package::new(\"baz\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.0\")\n        .build_dep(\"baz\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                build = \"build.rs\"\n\n                [build-dependencies]\n                baz = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn bar() -> i32 { 2 }\")\n        .file(\n            \"build.rs\",\n            r#\"fn main() {\n                println!(\"cargo::rustc-check-cfg=cfg(foo)\");\n                println!(\"cargo::rustc-cfg=foo\");\n            }\"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() { let _i = bar::bar(); }\")\n        .build();\n\n    p.cargo(\"build -Zsbom\")\n        .env(\"CARGO_BUILD_SBOM\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"sbom\"])\n        .run();\n\n    let path = append_sbom_suffix(&p.bin(\"foo\"));\n    let output = std::fs::read_to_string(path).unwrap();\n    assert_e2e().eq(\n        output,\n        snapbox::str![[r#\"\n{\n  \"crates\": [\n    {\n      \"dependencies\": [\n        {\n          \"index\": 1,\n          \"kind\": \"build\"\n        }\n      ],\n      \"features\": [],\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0\",\n      \"kind\": [\n        \"lib\"\n      ]\n    },\n    {\n      \"dependencies\": [\n        {\n          \"index\": 2,\n          \"kind\": \"normal\"\n        }\n      ],\n      \"features\": [],\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0\",\n      \"kind\": [\n        \"custom-build\"\n      ]\n    },\n    {\n      \"dependencies\": [],\n      \"features\": [],\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#baz@0.1.0\",\n      \"kind\": [\n        \"lib\"\n      ]\n    },\n    {\n      \"dependencies\": [\n        {\n          \"index\": 0,\n          \"kind\": \"normal\"\n        }\n      ],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#0.0.1\",\n      \"kind\": [\n        \"bin\"\n      ]\n    }\n  ],\n  \"root\": 3,\n  \"rustc\": \"{...}\",\n  \"target\": \"[HOST_TARGET]\",\n  \"version\": 1\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test]\nfn crate_uses_different_features_for_build_and_normal_dependencies() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                b = { path = \"b/\", features = [\"f1\"] }\n\n                [build-dependencies]\n                b = { path = \"b/\", features = [\"f2\"] }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() { b::f1(); }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() { b::f2(); }\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [features]\n                f1 = []\n                f2 = []\n            \"#,\n        )\n        .file(\n            \"b/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"f1\")]\n                pub fn f1() {}\n\n                #[cfg(feature = \"f2\")]\n                pub fn f2() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Zsbom\")\n        .env(\"CARGO_BUILD_SBOM\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"sbom\"])\n        .run();\n\n    let path = append_sbom_suffix(&p.bin(\"a\"));\n    assert!(path.is_file());\n    let output = std::fs::read_to_string(path).unwrap();\n    assert_e2e().eq(\n        output,\n        snapbox::str![[r#\"\n{\n  \"crates\": [\n    {\n      \"dependencies\": [\n        {\n          \"index\": 1,\n          \"kind\": \"build\"\n        },\n        {\n          \"index\": 3,\n          \"kind\": \"normal\"\n        }\n      ],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#a@0.1.0\",\n      \"kind\": [\n        \"bin\"\n      ]\n    },\n    {\n      \"dependencies\": [\n        {\n          \"index\": 2,\n          \"kind\": \"normal\"\n        }\n      ],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#a@0.1.0\",\n      \"kind\": [\n        \"custom-build\"\n      ]\n    },\n    {\n      \"dependencies\": [],\n      \"features\": [\n        \"f2\"\n      ],\n      \"id\": \"path+[ROOTURL]/foo/b#0.0.1\",\n      \"kind\": [\n        \"lib\"\n      ]\n    },\n    {\n      \"dependencies\": [],\n      \"features\": [\n        \"f1\"\n      ],\n      \"id\": \"path+[ROOTURL]/foo/b#0.0.1\",\n      \"kind\": [\n        \"lib\"\n      ]\n    }\n  ],\n  \"root\": 0,\n  \"rustc\": \"{...}\",\n  \"target\": \"[HOST_TARGET]\",\n  \"version\": 1\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test]\nfn artifact_dep() {\n    Package::new(\"bar\", \"0.5.0\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"bar\"))\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2021\"\n\n                [lib]\n                crate-type = [\"dylib\"] \n\n                [dependencies]\n                bar = { version = \"0.5.0\", artifact = \"bin\" }\n\n                [build-dependencies]\n                bar = { version = \"0.5.0\", artifact = \"bin\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"build.rs\", r#\"\n                fn main() {\n                    let bar: std::path::PathBuf = std::env::var(\"CARGO_BIN_FILE_BAR\").expect(\"CARGO_BIN_FILE_BAR\").into();\n                    assert!(&bar.is_file());\n                }\"#)\n        .build();\n    p.cargo(\"build -Z bindeps -Z sbom\")\n        .env(\"CARGO_BUILD_SBOM\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"bindeps\", \"sbom\"])\n        .run();\n\n    let output = std::fs::read_to_string(append_sbom_suffix(&p.dylib(\"foo\"))).unwrap();\n    assert_e2e().eq(\n        output,\n        snapbox::str![[r#\"\n{\n  \"crates\": [\n    {\n      \"dependencies\": [],\n      \"features\": [],\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#bar@0.5.0\",\n      \"kind\": [\n        \"bin\"\n      ]\n    },\n    {\n      \"dependencies\": [\n        {\n          \"index\": 0,\n          \"kind\": \"normal\"\n        },\n        {\n          \"index\": 0,\n          \"kind\": \"build\"\n        },\n        {\n          \"index\": 2,\n          \"kind\": \"build\"\n        }\n      ],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#0.0.0\",\n      \"kind\": [\n        \"dylib\"\n      ]\n    },\n    {\n      \"dependencies\": [],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#0.0.0\",\n      \"kind\": [\n        \"custom-build\"\n      ]\n    }\n  ],\n  \"root\": 1,\n  \"rustc\": \"{...}\",\n  \"target\": \"[HOST_TARGET]\",\n  \"version\": 1\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test]\nfn proc_macro() {\n    Package::new(\"noop\", \"0.0.1\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"noop\"\n            version = \"0.0.1\"\n            edition = \"2021\"\n\n            [lib]\n            proc-macro = true\n        \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            extern crate proc_macro;\n            use proc_macro::TokenStream;\n\n            #[proc_macro_derive(Noop)]\n            pub fn noop(_input: TokenStream) -> TokenStream {\n                \"\".parse().unwrap()\n            }\n        \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [dependencies]\n                noop = \"0.0.1\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[macro_use]\n                extern crate noop;\n\n                #[derive(Noop)]\n                struct X;\n\n                fn main() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -Z sbom\")\n        .env(\"CARGO_BUILD_SBOM\", \"true\")\n        .masquerade_as_nightly_cargo(&[\"sbom\"])\n        .run();\n\n    let output = std::fs::read_to_string(append_sbom_suffix(&p.bin(\"foo\"))).unwrap();\n    assert_e2e().eq(\n        output,\n        snapbox::str![[r#\"\n{\n  \"crates\": [\n    {\n      \"dependencies\": [\n        {\n          \"index\": 1,\n          \"kind\": \"build\"\n        }\n      ],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#0.0.1\",\n      \"kind\": [\n        \"bin\"\n      ]\n    },\n    {\n      \"dependencies\": [],\n      \"features\": [],\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#noop@0.0.1\",\n      \"kind\": [\n        \"proc-macro\"\n      ]\n    }\n  ],\n  \"root\": 0,\n  \"rustc\": \"{...}\",\n  \"target\": \"[HOST_TARGET]\",\n  \"version\": 1\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test]\nfn workspace_wrapper() {\n    let wrapper = project()\n        .at(\"wrapper\")\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"wrapper\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                let mut args = std::env::args().skip(1);\n                if let Some(sbom) = std::env::var_os(\"CARGO_SBOM_PATH\") {\n                    for sbom in std::env::split_paths(&sbom) {\n                        eprintln!(\"found sbom\");\n                        assert!(sbom.exists());\n                    }\n                }\n                let status = std::process::Command::new(&args.next().unwrap())\n                    .args(args).status().unwrap();\n                std::process::exit(status.code().unwrap_or(1));\n          }\n          \"#,\n        )\n        .build();\n    wrapper.cargo(\"build\").run();\n\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", r#\"fn main() {}\"#)\n        .build();\n    p.cargo(\"build -Zsbom\")\n        .env(\"CARGO_BUILD_SBOM\", \"true\")\n        .env(\"RUSTC_WRAPPER\", wrapper.bin(\"wrapper\"))\n        .masquerade_as_nightly_cargo(&[\"sbom\"])\n        .with_stderr_data(snapbox::str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\nfound sbom\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    let file = append_sbom_suffix(&p.bin(\"foo\"));\n    let output = std::fs::read_to_string(file).unwrap();\n    assert_e2e().eq(\n        output,\n        snapbox::str![[r#\"\n{\n  \"crates\": [\n    {\n      \"dependencies\": [],\n      \"features\": [],\n      \"id\": \"path+[ROOTURL]/foo#0.5.0\",\n      \"kind\": [\n        \"bin\"\n      ]\n    }\n  ],\n  \"root\": 0,\n  \"rustc\": \"{...}\",\n  \"target\": \"[HOST_TARGET]\",\n  \"version\": 1\n}\n\"#]]\n        .is_json(),\n    );\n}\n"
  },
  {
    "path": "tests/testsuite/script/cargo.rs",
    "content": "use crate::prelude::*;\nuse cargo_test_support::basic_manifest;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\nconst ECHO_SCRIPT: &str = r#\"#!/usr/bin/env cargo\n\nfn main() {\n    let current_exe = std::env::current_exe().unwrap().to_str().unwrap().to_owned();\n    let mut args = std::env::args_os();\n    let arg0 = args.next().unwrap().to_str().unwrap().to_owned();\n    let args = args.collect::<Vec<_>>();\n    println!(\"current_exe: {current_exe}\");\n    println!(\"arg0: {arg0}\");\n    println!(\"args: {args:?}\");\n}\n\n#[test]\nfn test () {}\n\"#;\n\n#[cfg(unix)]\nfn path() -> Vec<std::path::PathBuf> {\n    std::env::split_paths(&std::env::var_os(\"PATH\").unwrap_or_default()).collect()\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn basic_rs() {\n    let p = cargo_test_support::project()\n        .file(\"echo.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript -v echo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] echo v0.0.0 ([ROOT]/foo/echo.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cfg(unix)]\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn arg0() {\n    let p = cargo_test_support::project()\n        .file(\"echo.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript -v echo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]\narg0: [ROOT]/foo/echo.rs\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] echo v0.0.0 ([ROOT]/foo/echo.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cfg(windows)]\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn arg0() {\n    let p = cargo_test_support::project()\n        .file(\"echo.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript -v echo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]\narg0: [ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] echo v0.0.0 ([ROOT]/foo/echo.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn basic_path() {\n    let p = cargo_test_support::project()\n        .file(\"echo\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript -v ./echo\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] echo v0.0.0 ([ROOT]/foo/echo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn path_required() {\n    let p = cargo_test_support::project()\n        .file(\"echo\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript -v echo\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] no such command: `echo`\n\n[HELP] a command with a similar name exists: `bench`\n\n[HELP] view all installed commands with `cargo --list`\n[HELP] find a package to install `echo` with `cargo search cargo-echo`\n[HELP] to run the file `echo`, provide a relative path like `./echo`\n\n\"#]])\n        .run();\n}\n\n#[cfg(unix)]\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn manifest_precedence_over_plugins() {\n    let p = cargo_test_support::project()\n        .file(\"echo.rs\", ECHO_SCRIPT)\n        .executable(std::path::Path::new(\"path-test\").join(\"cargo-echo.rs\"), \"\")\n        .build();\n\n    // With path - fmt is there with known description\n    let mut path = path();\n    path.push(p.root().join(\"path-test\"));\n    let path = std::env::join_paths(path.iter()).unwrap();\n\n    p.cargo(\"-Zscript -v echo.rs\")\n        .env(\"PATH\", &path)\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] echo v0.0.0 ([ROOT]/foo/echo.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cfg(unix)]\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn warn_when_plugin_masks_manifest_on_stable() {\n    let p = cargo_test_support::project()\n        .file(\"echo.rs\", ECHO_SCRIPT)\n        .executable(std::path::Path::new(\"path-test\").join(\"cargo-echo.rs\"), \"\")\n        .build();\n\n    let mut path = path();\n    path.push(p.root().join(\"path-test\"));\n    let path = std::env::join_paths(path.iter()).unwrap();\n\n    p.cargo(\"-v echo.rs\")\n        .env(\"PATH\", &path)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[WARNING] external subcommand `echo.rs` has the appearance of a manifest-command\n  |\n  = [NOTE] this was previously accepted but will be phased out when `-Zscript` is stabilized; see <https://github.com/rust-lang/cargo/issues/12207>\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn requires_nightly() {\n    let p = cargo_test_support::project()\n        .file(\"echo.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-v echo.rs\")\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] running the file `echo.rs` requires `-Zscript`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn requires_z_flag() {\n    let p = cargo_test_support::project()\n        .file(\"echo.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-v echo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] running the file `echo.rs` requires `-Zscript`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn manifest_parse_error() {\n    // Exaggerate the newlines to make it more obvious if the error's line number is off\n    let script = r#\"#!/usr/bin/env cargo\n\n\n\n\n\n---\n[dependencies]\nbar = 3\n---\n\nfn main() {\n    println!(\"Hello world!\");\n}\"#;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(str![\"\"])\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid type: integer `3`, expected a version string like \"0.9.8\" or a detailed dependency like { version = \"0.9.8\" }\n --> script.rs:9:7\n  |\n9 | bar = 3\n  |       ^\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn clean_output_with_edition() {\n    let script = r#\"#!/usr/bin/env cargo\n---\n[package]\nedition = \"2018\"\n---\n\nfn main() {\n    println!(\"Hello world!\");\n}\"#;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nHello world!\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn warning_without_edition() {\n    let script = r#\"#!/usr/bin/env cargo\n---\n[package]\n---\n\nfn main() {\n    println!(\"Hello world!\");\n}\"#;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nHello world!\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn rebuild() {\n    let script = r#\"#!/usr/bin/env cargo-eval\n\nfn main() {\n    let msg = option_env!(\"_MESSAGE\").unwrap_or(\"undefined\");\n    println!(\"msg = {}\", msg);\n}\"#;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nmsg = undefined\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]`\n\n\"#]])\n        .run();\n\n    // Verify we don't rebuild\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nmsg = undefined\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]`\n\n\"#]])\n        .run();\n\n    // Verify we do rebuild\n    p.cargo(\"-Zscript -v script.rs\")\n        .env(\"_MESSAGE\", \"hello\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nmsg = hello\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn use_script_config() {\n    let script = ECHO_SCRIPT;\n    let _ = cargo_test_support::project()\n        .at(\"script\")\n        .file(\"script.rs\", script)\n        .build();\n\n    let p = cargo_test_support::project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n[build]\nrustc = \"non-existent-rustc\"\n\"#,\n        )\n        .file(\"script.rs\", script)\n        .build();\n\n    // Verify the config is bad\n    p.cargo(\"-Zscript script.rs -NotAnArg\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] could not execute process `non-existent-rustc -vV` (never executed)\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n\n    // Verify that the config isn't used\n    p.cargo(\"-Zscript ../script/script.rs -NotAnArg\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]\narg0: [..]\nargs: [\"-NotAnArg\"]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn default_programmatic_verbosity() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript script.rs -NotAnArg\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]\narg0: [..]\nargs: [\"-NotAnArg\"]\n\n\"#]])\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn quiet() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -q script.rs -NotAnArg\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]\narg0: [..]\nargs: [\"-NotAnArg\"]\n\n\"#]])\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_line_numbering_preserved() {\n    let script = r#\"#!/usr/bin/env cargo\n\nfn main() {\n    println!(\"line: {}\", line!());\n}\n\"#;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nline: 4\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_escaped_hyphen_arg() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v -- script.rs -NotAnArg\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]\narg0: [..]\nargs: [\"-NotAnArg\"]\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE] -NotAnArg`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_unescaped_hyphen_arg() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs -NotAnArg\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]\narg0: [..]\nargs: [\"-NotAnArg\"]\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE] -NotAnArg`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_same_flags() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs --help\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]\narg0: [..]\nargs: [\"--help\"]\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE] --help`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_name_has_weird_chars() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"s-h.w§c!.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v s-h.w§c!.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/s-h-w-c-[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] s-h-w-c- v0.0.0 ([ROOT]/foo/s-h.w§c!.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/s-h-w-c-[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_name_has_leading_number() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"42answer.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v 42answer.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/answer[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] answer v0.0.0 ([ROOT]/foo/42answer.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/answer[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_name_is_number() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project().file(\"42.rs\", script).build();\n\n    p.cargo(\"-Zscript -v 42.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/package[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] package v0.0.0 ([ROOT]/foo/42.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/package[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[cfg(not(windows))]\nfn test_name_is_windows_reserved_name() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project().file(\"con\", script).build();\n\n    p.cargo(\"-Zscript -v ./con\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/con[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] con v0.0.0 ([ROOT]/foo/con)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/con[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_name_is_sysroot_package_name() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project().file(\"test\", script).build();\n\n    p.cargo(\"-Zscript -v ./test\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/test[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] test v0.0.0 ([ROOT]/foo/test)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/test[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_name_is_keyword() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project().file(\"self\", script).build();\n\n    p.cargo(\"-Zscript -v ./self\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/self[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] self v0.0.0 ([ROOT]/foo/self)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/self[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_name_is_deps_dir_implicit() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"deps.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v deps.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(str![\"\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[ERROR] failed to parse manifest at `[ROOT]/foo/deps.rs`\n\nCaused by:\n  the binary target name `deps` is forbidden, it conflicts with cargo's build directory names\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_name_is_deps_dir_explicit() {\n    let script = r#\"#!/usr/bin/env cargo\n---\npackage.name = \"deps\"\n---\n\nfn main() {\n    let current_exe = std::env::current_exe().unwrap().to_str().unwrap().to_owned();\n    let mut args = std::env::args_os();\n    let arg0 = args.next().unwrap().to_str().unwrap().to_owned();\n    let args = args.collect::<Vec<_>>();\n    println!(\"current_exe: {current_exe}\");\n    println!(\"arg0: {arg0}\");\n    println!(\"args: {args:?}\");\n}\n\n#[test]\nfn test () {}\n\"#;\n    let p = cargo_test_support::project()\n        .file(\"deps.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v deps.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(str![\"\"])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[ERROR] failed to parse manifest at `[ROOT]/foo/deps.rs`\n\nCaused by:\n  the binary target name `deps` is forbidden, it conflicts with cargo's build directory names\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn script_like_dir() {\n    let p = cargo_test_support::project()\n        .file(\"foo.rs/foo\", \"something\")\n        .build();\n\n    p.cargo(\"-Zscript -v foo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no such file or subcommand `foo.rs`: `foo.rs` is a directory\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn non_existent_rs() {\n    let p = cargo_test_support::project().build();\n\n    p.cargo(\"-Zscript -v foo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no such file or subcommand `foo.rs`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn non_existent_rs_stable() {\n    let p = cargo_test_support::project().build();\n\n    p.cargo(\"-v foo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] no such subcommand `foo.rs`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn did_you_mean_file() {\n    let p = cargo_test_support::project()\n        .file(\"food.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript -v foo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] no such file or subcommand `foo.rs`\n[HELP] there is a script with a similar name: `./food.rs`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn did_you_mean_file_stable() {\n    let p = cargo_test_support::project()\n        .file(\"food.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-v foo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] no such subcommand `foo.rs`\n[HELP] there is a script with a similar name: `./food.rs` (requires `-Zscript`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn did_you_mean_command() {\n    let p = cargo_test_support::project().build();\n\n    p.cargo(\"-Zscript -v build--manifest-path=./Cargo.toml\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] no such file or subcommand `build--manifest-path=./Cargo.toml`\n[HELP] there is a command with a similar name: `build --manifest-path=./Cargo.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn did_you_mean_command_stable() {\n    let p = cargo_test_support::project().build();\n\n    p.cargo(\"-v build--manifest-path=./Cargo.toml\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] no such subcommand `build--manifest-path=./Cargo.toml`\n[HELP] there is a command with a similar name: `build --manifest-path=./Cargo.toml`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_name_same_as_dependency() {\n    Package::new(\"script\", \"1.0.0\").publish();\n    let script = r#\"#!/usr/bin/env cargo\n---\n[dependencies]\nscript = \"1.0.0\"\n---\n\nfn main() {\n    println!(\"Hello world!\");\n}\"#;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs --help\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nHello world!\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest Rust [..] compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] script v1.0.0 (registry `dummy-registry`)\n[COMPILING] script v1.0.0\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE] --help`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_path_dep() {\n    let script = r#\"#!/usr/bin/env cargo\n---\n[dependencies]\nbar.path = \"./bar\"\n---\n\nfn main() {\n    println!(\"Hello world!\");\n}\"#;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs --help\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nHello world!\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[LOCKING] 1 package to latest Rust [..] compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE] --help`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_no_build_rs() {\n    let script = r#\"#!/usr/bin/env cargo\n\nfn main() {\n    println!(\"Hello world!\");\n}\"#;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .file(\"build.rs\", \"broken\")\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs --help\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nHello world!\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE] --help`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_no_autobins() {\n    let script = r#\"#!/usr/bin/env cargo\n\nfn main() {\n    println!(\"Hello world!\");\n}\"#;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .file(\"src/bin/not-script/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs --help\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nHello world!\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE] --help`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn test_no_autolib() {\n    let script = r#\"#!/usr/bin/env cargo\n\nfn main() {\n    println!(\"Hello world!\");\n}\"#;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .file(\"src/lib.rs\", r#\"compile_error!{\"must not be built\"}\"#)\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs --help\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nHello world!\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE] --help`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_workspace() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\npackage.edition = \"2021\"\n\n[workspace]\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `workspace` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn workspace_members_mentions_script() {\n    let p = cargo_test_support::project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"scripts/nop.rs\"]\n\"#,\n        )\n        .file(\n            \"scripts/nop.rs\",\n            r#\"\n----\npackage.edition = \"2021\"\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript check\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] manifest path `[ROOT]/foo` contains no package: The manifest is virtual, and the workspace has no members.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn workspace_members_glob_matches_script() {\n    let p = cargo_test_support::project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"scripts/*\"]\n\"#,\n        )\n        .file(\n            \"scripts/nop.rs\",\n            r#\"\n----\npackage.edition = \"2021\"\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript check\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] manifest path `[ROOT]/foo` contains no package: The manifest is virtual, and the workspace has no members.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn package_workspace() {\n    let p = cargo_test_support::project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\"scripts/*\"]\n\n[package]\nname = \"foo\"\n\"#,\n        )\n        .file(\n            \"scripts/nop.rs\",\n            r#\"\n----\npackage.edition = \"2021\"\npackage.workspace = \"../\"\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript ./scripts/nop.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/scripts/nop.rs`\n\nCaused by:\n  `package.workspace` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_lib() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\npackage.edition = \"2021\"\n\n[lib]\nname = \"script\"\npath = \"script.rs\"\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `lib` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_bin() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\npackage.edition = \"2021\"\n\n[[bin]]\nname = \"script\"\npath = \"script.rs\"\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `bin` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_example() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\npackage.edition = \"2021\"\n\n[[example]]\nname = \"script\"\npath = \"script.rs\"\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `example` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_test() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\npackage.edition = \"2021\"\n\n[[test]]\nname = \"script\"\npath = \"script.rs\"\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `test` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_bench() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\npackage.edition = \"2021\"\n\n[[bench]]\nname = \"script\"\npath = \"script.rs\"\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `bench` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_package_build() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\n[package]\nedition = \"2021\"\nbuild = \"script.rs\"\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `package.build` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_package_links() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\n[package]\nedition = \"2021\"\nlinks = \"script\"\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `package.links` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_package_autolib() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\n[package]\nedition = \"2021\"\nautolib = true\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `package.autolib` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_package_autobins() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\n[package]\nedition = \"2021\"\nautobins = true\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `package.autobins` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_package_autoexamples() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\n[package]\nedition = \"2021\"\nautoexamples = true\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `package.autoexamples` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_package_autotests() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\n[package]\nedition = \"2021\"\nautotests = true\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `package.autotests` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn disallow_explicit_package_autobenches() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"\n----\n[package]\nedition = \"2021\"\nautobenches = true\n----\n\nfn main() {}\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs`\n\nCaused by:\n  `package.autobenches` is not allowed in embedded manifests\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn implicit_target_dir() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn no_local_lockfile() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n    let local_lockfile_path = p.root().join(\"Cargo.lock\");\n\n    assert!(!local_lockfile_path.exists());\n\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]`\n\n\"#]])\n        .run();\n\n    assert!(!local_lockfile_path.exists());\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_check_requires_nightly() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"check --manifest-path script.rs\")\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] embedded manifest `[ROOT]/foo/script.rs` requires `-Zscript`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_check_requires_z_flag() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"check --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] embedded manifest `[ROOT]/foo/script.rs` requires `-Zscript`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_check_with_embedded() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript check --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[CHECKING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_check_with_missing_script_rs() {\n    let p = cargo_test_support::project().build();\n\n    p.cargo(\"-Zscript check --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] manifest path `script.rs` does not exist\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_check_with_missing_script() {\n    let p = cargo_test_support::project().build();\n\n    p.cargo(\"-Zscript check --manifest-path script\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[ERROR] manifest path `script` does not exist\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_build_with_embedded() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript build --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_test_with_embedded() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript test --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest test ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests script.rs ([ROOT]/home/.cargo/build/[HASH]/debug/deps/script-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_clean_with_embedded() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    // Ensure there is something to clean\n    p.cargo(\"-Zscript script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .run();\n\n    p.cargo(\"-Zscript clean --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_generate_lockfile_with_embedded() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript generate-lockfile --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_metadata_with_embedded() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript metadata --manifest-path script.rs --format-version=1\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2024\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo/script.rs#script@0.0.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/script.rs\",\n      \"metadata\": null,\n      \"name\": \"script\",\n      \"publish\": [],\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"bin\"\n          ],\n          \"doc\": true,\n          \"doctest\": false,\n          \"edition\": \"2024\",\n          \"kind\": [\n            \"bin\"\n          ],\n          \"name\": \"script\",\n          \"src_path\": \"[ROOT]/foo/script.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo/script.rs#script@0.0.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo/script.rs#script@0.0.0\"\n  },\n  \"target_directory\": \"[ROOT]/home/.cargo/build/[HASH]/target\",\n  \"build_directory\": \"[ROOT]/home/.cargo/build/[HASH]\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo/script.rs#script@0.0.0\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo/script.rs#script@0.0.0\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_read_manifest_with_embedded() {\n    let script = ECHO_SCRIPT;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript read-manifest --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script.rs#script@0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script.rs\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script.rs\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}\n\"#]]\n            .is_json(),\n        )\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_run_with_embedded() {\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript run --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_tree_with_embedded() {\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript tree --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nscript v0.0.0 ([ROOT]/foo/script.rs)\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_update_with_embedded() {\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript update --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(\"\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_verify_project_with_embedded() {\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript verify-project --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"success\": \"true\"\n}\n\"#]]\n            .is_json(),\n        )\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_pkgid_with_embedded() {\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .run();\n\n    p.cargo(\"-Zscript pkgid --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\npath+[ROOTURL]/foo/script.rs#script@0.0.0\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_pkgid_with_embedded_no_lock_file() {\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript pkgid --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[ERROR] a Cargo.lock must exist for this command\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_pkgid_with_embedded_dep() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n    let script = r#\"#!/usr/bin/env cargo\n---\n[dependencies]\ndep = \"1.0.0\"\n---\n\nfn main() {\n    println!(\"Hello world!\");\n}\"#;\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", script)\n        .build();\n\n    p.cargo(\"-Zscript script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .run();\n\n    p.cargo(\"-Zscript pkgid --manifest-path script.rs -p dep\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nregistry+https://github.com/rust-lang/crates.io-index#dep@1.0.0\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn script_as_dep() {\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", ECHO_SCRIPT)\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"0.1.0\"\n\n[dependencies]\nscript.path = \"script.rs\"\n\"#,\n        )\n        .build();\n\n    p.cargo(\"build\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to `2015` while the latest is `[..]`\n[ERROR] failed to get `script` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `script`\n\nCaused by:\n  unable to update [ROOT]/foo/script.rs\n\nCaused by:\n  single file packages cannot be used as dependencies\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_install_with_embedded() {\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript install --path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `[ROOT]/foo/script.rs` is not a directory. --path must point to a directory containing a Cargo.toml file.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_package_with_embedded() {\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript package --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[ERROR] [ROOT]/foo/script.rs is unsupported by `cargo package`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn cmd_publish_with_embedded() {\n    let p = cargo_test_support::project()\n        .file(\"script.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(\"-Zscript publish --manifest-path script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[ERROR] [ROOT]/foo/script.rs is unsupported by `cargo publish`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn manifest_path_env() {\n    let p = cargo_test_support::project()\n        .file(\n            \"script.rs\",\n            r#\"#!/usr/bin/env cargo\n\nfn main() {\n    let path = env!(\"CARGO_MANIFEST_PATH\");\n    println!(\"CARGO_MANIFEST_PATH: {}\", path);\n}\n\"#,\n        )\n        .build();\n    p.cargo(\"-Zscript -v script.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\nCARGO_MANIFEST_PATH: [ROOT]/foo/script.rs\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/script[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\nfn ignore_surrounding_workspace() {\n    let p = cargo_test_support::project()\n        .file(\n            std::path::Path::new(\".cargo\").join(\"config.toml\"),\n            r#\"\n[registries.test-reg]\nindex = \"https://github.com/rust-lang/crates.io-index\"\n\"#,\n        )\n        .file(\n            std::path::Path::new(\"inner\").join(\"Cargo.toml\"),\n            r#\"\n[package]\nname = \"inner\"\nversion = \"0.1.0\"\n\n[dependencies]\nserde = { version = \"1.0\", registry = \"test-reg\" }\n\"#,\n        )\n        .file(std::path::Path::new(\"inner\").join(\"src\").join(\"lib.rs\"), \"\")\n        .file(std::path::Path::new(\"script\").join(\"echo.rs\"), ECHO_SCRIPT)\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[workspace]\nmembers = [\n    \"inner\",\n]\n\"#,\n        )\n        .build();\n\n    p.cargo(\"-Zscript -v script/echo.rs\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]\narg0: [..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] echo v0.0.0 ([ROOT]/foo/script/echo.rs)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/echo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[cfg(target_os = \"linux\")]\nfn memfd_script() {\n    use std::io::Write;\n    use std::os::fd::AsRawFd;\n\n    let fd = memfd::MemfdOptions::new()\n        .close_on_exec(false)\n        .create(\"otkeep-script\")\n        .unwrap();\n    let mut file = fd.into_file();\n    file.write_all(ECHO_SCRIPT.as_bytes()).unwrap();\n    file.flush().unwrap();\n\n    let raw_fd = file.as_raw_fd();\n\n    let p = cargo_test_support::project()\n        .file(\"echo.rs\", ECHO_SCRIPT)\n        .build();\n\n    p.cargo(&format!(\"-Zscript -v /proc/self/fd/{raw_fd}\"))\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(str![[r#\"\ncurrent_exe: [ROOT]/home/.cargo/build/[HASH]/target/debug/package\narg0: /proc/self/fd/[..]\nargs: []\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)\n[COMPILING] package v0.0.0 (/proc/self/fd/[..])\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/home/.cargo/build/[HASH]/target/debug/package`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/script/mod.rs",
    "content": "mod cargo;\nmod rustc;\n"
  },
  {
    "path": "tests/testsuite/script/rustc.rs",
    "content": "use std::collections::BTreeMap;\n\nuse snapbox::assert_data_eq;\n\nuse crate::prelude::*;\n\n#[test]\nfn ensure_all_fixtures_have_tests() {\n    let mut code_gen_divider = \"//\".to_owned();\n    code_gen_divider.push_str(\" START CODE GENERATION\");\n\n    let self_path = snapbox::utils::current_rs!();\n    let self_source = std::fs::read_to_string(&self_path).unwrap();\n\n    let (header, _) = self_source\n        .split_once(&code_gen_divider)\n        .expect(\"code-gen divider is present\");\n    let header = header.trim();\n\n    let fixture_root = snapbox::utils::current_dir!().join(\"rustc_fixtures\");\n    let mut fixtures = BTreeMap::new();\n    for entry in std::fs::read_dir(fixture_root).unwrap() {\n        let entry = entry.unwrap();\n        let path = entry.path();\n        let fn_name = file_to_fn(&path);\n        fixtures\n            .entry(fn_name.clone())\n            .or_insert_with(|| Fixture::new(fn_name))\n            .add_path(path);\n    }\n\n    let fixtures = fixtures\n        .into_values()\n        .filter(Fixture::is_valid)\n        .map(|f| f.to_string())\n        .collect::<String>();\n    let actual = format!(\n        \"{header}\n\n{code_gen_divider}\n{fixtures}\"\n    );\n    assert_data_eq!(actual, snapbox::Data::read_from(&self_path, None).raw());\n}\n\nfn file_to_fn(path: &std::path::Path) -> String {\n    let name = path.file_stem().unwrap().to_str().unwrap();\n    name.replace(\"-\", \"_\")\n}\n\nfn sanitize_path(path: &std::path::Path) -> String {\n    path.strip_prefix(env!(\"CARGO_MANIFEST_DIR\"))\n        .unwrap()\n        .as_os_str()\n        .to_string_lossy()\n        .replace(\"\\\\\", \"/\")\n}\n\nstruct Fixture {\n    fn_name: String,\n    input: std::path::PathBuf,\n    output: Option<std::path::PathBuf>,\n}\n\nimpl Fixture {\n    fn new(fn_name: String) -> Self {\n        Self {\n            fn_name,\n            input: Default::default(),\n            output: Default::default(),\n        }\n    }\n\n    fn is_valid(&self) -> bool {\n        !self.input.as_os_str().is_empty()\n    }\n\n    fn add_path(&mut self, path: std::path::PathBuf) {\n        if path.extension().map(|ext| ext.to_str().unwrap()) == Some(\"rs\") {\n            assert!(\n                self.input.as_os_str().is_empty(),\n                \"similarly named fixtures:/n{}/n{}\",\n                self.input.display(),\n                path.display()\n            );\n            self.input = path;\n        } else {\n            assert!(\n                self.output.is_none(),\n                \"conflicting assertions:/n{}/n{}\",\n                self.output.as_ref().unwrap().display(),\n                path.display()\n            );\n            self.output = Some(path);\n        }\n    }\n}\n\nimpl std::fmt::Display for Fixture {\n    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let fn_name = &self.fn_name;\n        let fixture_path = sanitize_path(&self.input);\n        match self\n            .output\n            .as_ref()\n            .map(|path| path.extension().unwrap().to_str().unwrap())\n        {\n            Some(\"stderr\") => {\n                let assertion_path = sanitize_path(self.output.as_ref().unwrap());\n                write!(\n                    fmt,\n                    r#\"\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn {fn_name}() {{\n    let fixture_path = {fixture_path:?};\n    let assertion_path = {assertion_path:?};\n    assert_failure(fixture_path, assertion_path);\n}}\n\"#\n                )\n            }\n            Some(\"stdout\") | None => {\n                let mut backup_path = self.input.clone();\n                backup_path.set_extension(\"stdout\");\n                let assertion_path = sanitize_path(self.output.as_ref().unwrap_or(&backup_path));\n                write!(\n                    fmt,\n                    r#\"\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn {fn_name}() {{\n    let fixture_path = {fixture_path:?};\n    let assertion_path = {assertion_path:?};\n    assert_success(fixture_path, assertion_path);\n}}\n\"#\n                )\n            }\n            Some(_) => {\n                panic!(\n                    \"unsupported assertiong: {}\",\n                    self.output.as_ref().unwrap().display()\n                )\n            }\n        }\n    }\n}\n\n#[track_caller]\nfn assert_success(fixture_path: &str, assertion_path: &str) {\n    let p = cargo_test_support::project()\n        .file(\"script\", &std::fs::read_to_string(fixture_path).unwrap())\n        .build();\n\n    // `read-manifest` to validate frontmatter content without processing deps, compiling\n    p.cargo(\"-Zscript read-manifest --manifest-path script\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_stdout_data(snapbox::Data::read_from(\n            std::path::Path::new(assertion_path),\n            Some(snapbox::data::DataFormat::Json),\n        ))\n        .run();\n}\n\n#[track_caller]\nfn assert_failure(fixture_path: &str, assertion_path: &str) {\n    let p = cargo_test_support::project()\n        .file(\"script\", &std::fs::read_to_string(fixture_path).unwrap())\n        .build();\n\n    // `read-manifest` to validate frontmatter content without processing deps, compiling\n    p.cargo(\"-Zscript read-manifest --manifest-path script\")\n        .masquerade_as_nightly_cargo(&[\"script\"])\n        .with_status(101)\n        .with_stderr_data(snapbox::Data::read_from(\n            std::path::Path::new(assertion_path),\n            None,\n        ))\n        .run();\n}\n\n// START CODE GENERATION\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn content_contains_whitespace() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/content-contains-whitespace.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/content-contains-whitespace.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn content_non_lexible_tokens() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/content-non-lexible-tokens.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/content-non-lexible-tokens.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn escape_hyphens_leading() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/escape-hyphens-leading.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/escape-hyphens-leading.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn escape_hyphens_nonleading_1() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-1.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-1.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn escape_hyphens_nonleading_2() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-2.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-2.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn escape_hyphens_nonleading_3() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-3.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-3.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_close_extra_after() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-close-extra-after.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-close-extra-after.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_indented() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-indented.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-indented.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_indented_mismatch() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-indented-mismatch.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-indented-mismatch.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_mismatch_1() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-mismatch-1.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-mismatch-1.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_mismatch_2() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-mismatch-2.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-mismatch-2.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_too_many_dashes() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-too-many-dashes.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-too-many-dashes.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_unclosed_1() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-unclosed-1.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-unclosed-1.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_unclosed_2() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-unclosed-2.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-unclosed-2.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_unclosed_3() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-unclosed-3.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-unclosed-3.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_unclosed_4() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-unclosed-4.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-unclosed-4.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_unclosed_5() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-unclosed-5.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-unclosed-5.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_unclosed_6() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-unclosed-6.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-unclosed-6.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_whitespace_trailing_1() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-whitespace-trailing-1.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-whitespace-trailing-1.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn fence_whitespace_trailing_2() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/fence-whitespace-trailing-2.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/fence-whitespace-trailing-2.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn frontmatter_crlf() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/frontmatter-crlf.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/frontmatter-crlf.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn infostring_comma() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/infostring-comma.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/infostring-comma.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn infostring_dot_leading() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/infostring-dot-leading.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/infostring-dot-leading.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn infostring_dot_nonleading() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/infostring-dot-nonleading.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/infostring-dot-nonleading.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn infostring_hyphen_leading() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/infostring-hyphen-leading.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/infostring-hyphen-leading.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn infostring_hyphen_nonleading() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/infostring-hyphen-nonleading.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/infostring-hyphen-nonleading.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn infostring_space() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/infostring-space.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/infostring-space.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn location_after_shebang() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/location-after-shebang.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/location-after-shebang.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn location_after_tokens() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/location-after-tokens.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/location-after-tokens.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn location_include_in_expr_ctxt() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/location-include-in-expr-ctxt.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/location-include-in-expr-ctxt.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn location_include_in_item_ctxt() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/location-include-in-item-ctxt.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/location-include-in-item-ctxt.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn location_proc_macro_observer() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/location-proc-macro-observer.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/location-proc-macro-observer.stdout\";\n    assert_success(fixture_path, assertion_path);\n}\n\n#[cargo_test(nightly, reason = \"-Zscript is unstable\")]\n#[rustfmt::skip]  // code-generated\nfn multifrontmatter() {\n    let fixture_path = \"tests/testsuite/script/rustc_fixtures/multifrontmatter.rs\";\n    let assertion_path = \"tests/testsuite/script/rustc_fixtures/multifrontmatter.stderr\";\n    assert_failure(fixture_path, assertion_path);\n}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/README.md",
    "content": "Canonical home for these tests is https://github.com/rust-lang/rust/tree/master/tests/ui/frontmatter\n\nTo update\n1. Sync changes to this directory\n2. Run `SNAPSHOTS=overwrite cargo test --test testsuite -- script::rustc` to register new test cases\n2. Run `SNAPSHOTS=overwrite cargo test --test testsuite -- script::rustc` to update snapshots for new test cases\n\nNote:\n- A `.stderr` file is assumed that the test fill fail\n- A `.stdout` file is assumed that the test fill succeed\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/auxiliary/expr.rs",
    "content": "---\n-\n---\n1\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/auxiliary/lib.rs",
    "content": "---something\n---\n\npub fn foo(x: i32) -> i32 {\n    -x\n}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/auxiliary/makro.rs",
    "content": "extern crate proc_macro;\nuse proc_macro::{Literal, TokenStream};\n\n#[proc_macro]\npub fn check(_: TokenStream) -> TokenStream {\n    // In the following test cases, the `---` may look like the start of frontmatter but it is not!\n    // That's because it would be backward incompatible to interpret them as such in the latest\n    // stable edition. That's not only the case due to the feature gate error but also due to the\n    // fact that we \"eagerly\" emit errors on malformed frontmatter.\n\n    // issue: <https://github.com/rust-lang/rust/issues/145520>\n    _ = \"---\".parse::<TokenStream>();\n    // Just a sequence of regular Rust punctuation tokens.\n    assert_eq!(6, \"---\\n---\".parse::<TokenStream>().unwrap().into_iter().count());\n\n    // issue: <https://github.com/rust-lang/rust/issues/146132>\n    assert!(\"---\".parse::<Literal>().is_err());\n\n    Default::default()\n}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/content-contains-whitespace.rs",
    "content": "#!/usr/bin/env -S cargo -Zscript\n---cargo\n# Beware editing: it has numerous whitespace characters which are important.\n# It contains one ranges from the 'PATTERN_WHITE_SPACE' property outlined in\n# https://unicode.org/Public/UNIDATA/PropList.txt\n#\n# The characters in the first expression of the assertion can be generated\n# from: \"4\\u{0C}+\\n\\t\\r7\\t*\\u{20}2\\u{85}/\\u{200E}3\\u{200F}*\\u{2028}2\\u{2029}\"\npackage.description = \"\"\"\n4\f+\n\n7   * 2/‎3‏* 2\n\"\"\"\n---\n\n//@ check-pass\n\n// Ensure the frontmatter can contain any whitespace\n// CARGO(fail): However, TOML cannot\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/content-contains-whitespace.stderr",
    "content": "[ERROR] invalid multi-line basic string, expected `/`, characters\n  --> script:10:2\n   |\n10 | 4␌+\n   |  ^\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/content-non-lexible-tokens.rs",
    "content": "--- cargo\npackage.description = \"\"\"\n🏳️‍⚧️\n\"\"\"\n---\n\n//@ check-pass\n\n#![feature(frontmatter)]\n\n// check that frontmatter blocks can have tokens that are otherwise not accepted by\n// the lexer as Rust code.\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/content-non-lexible-tokens.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": \"🏳️‍⚧️\\n\",\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/escape-hyphens-leading.rs",
    "content": "----\npackage.description = \"\"\"\n\n---\n\n\"\"\"\n----\n\n//@ check-pass\n\n// This test checks that longer dashes for opening and closing can be used to\n// escape sequences such as three dashes inside the frontmatter block.\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/escape-hyphens-leading.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": \"\\n---\\n\\n\",\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-1.rs",
    "content": "---\npackage.description = \"\"\"\n ---\n\n ---\n\"\"\"\n---\n\n// hyphens only need to be escaped when at the start of a line\n//@ check-pass\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-1.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": \" ---\\n\\n ---\\n\",\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-2.rs",
    "content": "---\npackage.description = \"\"\"\nx ---🚧️\n\"\"\"\n---\n\n// Regression test for #141483\n//@check-pass\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-2.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": \"x ---🚧️\\n\",\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-3.rs",
    "content": "---\npackage.description = \"\"\"\nx ---y\n\"\"\"\n---\n\n// Test that hyphens are allowed inside frontmatters if there is some\n// non-whitespace character preceding them.\n//@check-pass\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/escape-hyphens-nonleading-3.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": \"x ---y\\n\",\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-close-extra-after.rs",
    "content": "---\n---cargo\n//~^ ERROR: extra characters after frontmatter close are not allowed\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-close-extra-after.stderr",
    "content": "[ERROR] unexpected characters after frontmatter close\n --> script:2:4\n  |\n1 | ---\n2 | ---cargo\n  |    ^^^^^\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-indented-mismatch.rs",
    "content": "---cargo\n//~^ ERROR: unclosed frontmatter\n\n//@ compile-flags: --crate-type lib\n\n#![feature(frontmatter)]\n\nfn foo(x: i32) -> i32 {\n    ---x\n     //~^ WARNING: use of a double negation [double_negations]\n}\n\n// this test is for the weird case that valid Rust code can have three dashes\n// within them and get treated as a frontmatter close.\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-indented-mismatch.stderr",
    "content": "[ERROR] unclosed frontmatter; expected `---`\n  --> script:14:56\n   |\n 1 | ---cargo\n...\n14 | // within them and get treated as a frontmatter close.\n   |                                                       ^\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-indented.rs",
    "content": "  ---\n//~^ ERROR: invalid preceding whitespace for frontmatter opening\n//~^^ ERROR: unclosed frontmatter\n  ---\n\n#![feature(frontmatter)]\n\n// check that whitespaces should not precede the frontmatter opening or close.\n// CARGO(pass): not technitcally a frontmatter, so defer to rustc to error\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-indented.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-mismatch-1.rs",
    "content": "---cargo\n//~^ ERROR: frontmatter close does not match the opening\n----\n\n// there must be the same number of dashes for both the opening and the close\n// of the frontmatter.\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-mismatch-1.stderr",
    "content": "[ERROR] closing code fence has 1 more `-` than the opening fence\n --> script:3:4\n  |\n1 | ---cargo\n2 | //~^ ERROR: frontmatter close does not match the opening\n3 | ----\n  |    ^\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-mismatch-2.rs",
    "content": "----cargo\n//~^ ERROR: frontmatter close does not match the opening\n---cargo\n//~^ ERROR: extra characters after frontmatter close are not allowed\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-mismatch-2.stderr",
    "content": "[ERROR] closing code fence has 1 less `-` than the opening fence\n --> script:3:1\n  |\n1 | ----cargo\n2 | //~^ ERROR: frontmatter close does not match the opening\n3 | ---cargo\n  | ^^^\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-too-many-dashes.rs",
    "content": "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n[dependencies]\n----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n#![feature(frontmatter)]\n\n// check that we limit fence lengths\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-too-many-dashes.stderr",
    "content": "[ERROR] too many `-` symbols: frontmatter openings may be delimited by up to 255 `-` symbols, but found 256\n --> script:1:1\n  |\n1 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-unclosed-1.rs",
    "content": "----cargo\n//~^ ERROR: unclosed frontmatter\n\n// This test checks that the #! characters can help us recover a frontmatter\n// close. There should not be a \"missing `main` function\" error as the rest\n// are properly parsed.\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-unclosed-1.stderr",
    "content": "[ERROR] unclosed frontmatter; expected `----`\n  --> script:10:14\n   |\n 1 | ----cargo\n...\n10 | fn main() {}\n   |             ^\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-unclosed-2.rs",
    "content": "----cargo\n//~^ ERROR: unclosed frontmatter\n//~| ERROR: frontmatters are experimental\n\n//@ compile-flags: --crate-type lib\n\n// Leading whitespace on the feature line prevents recovery. However\n// the dashes quoted will not be used for recovery and the entire file\n// should be treated as within the frontmatter block.\n\n #![feature(frontmatter)]\n\nfn foo() -> &str {\n    \"----\"\n}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-unclosed-2.stderr",
    "content": "[ERROR] unclosed frontmatter; expected `----`\n  --> script:15:3\n   |\n 1 | ----cargo\n...\n15 | }\n   |  ^\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-unclosed-3.rs",
    "content": "----cargo\n//~^ ERROR: frontmatter close does not match the opening\n\n//@ compile-flags: --crate-type lib\n\n// Unfortunate recovery situation. Not really preventable with improving the\n// recovery strategy, but this type of code is rare enough already.\n\n #![feature(frontmatter)]\n\nfn foo(x: i32) -> i32 {\n    ---x\n    //~^ ERROR: invalid preceding whitespace for frontmatter close\n    //~| ERROR: extra characters after frontmatter close are not allowed\n}\n//~^ ERROR: unexpected closing delimiter: `}`\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-unclosed-3.stderr",
    "content": "[ERROR] unclosed frontmatter; expected `----`\n  --> script:16:47\n   |\n 1 | ----cargo\n...\n16 | //~^ ERROR: unexpected closing delimiter: `}`\n   |                                              ^\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-unclosed-4.rs",
    "content": "----cargo\n//~^ ERROR: unclosed frontmatter\n\n//! Similarly, a module-level content should allow for recovery as well (as\n//! per unclosed-1.rs)\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-unclosed-4.stderr",
    "content": "[ERROR] unclosed frontmatter; expected `----`\n  --> script:9:14\n   |\n 1 | ----cargo\n...\n 9 | fn main() {}\n   |             ^\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-unclosed-5.rs",
    "content": "----cargo\n//~^ ERROR: unclosed frontmatter\n//~| ERROR: frontmatters are experimental\n\n// Similarly, a use statement should allow for recovery as well (as\n// per unclosed-1.rs)\n\nuse std::env;\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-unclosed-5.stderr",
    "content": "[ERROR] unclosed frontmatter; expected `----`\n  --> script:10:14\n   |\n 1 | ----cargo\n...\n10 | fn main() {}\n   |             ^\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-unclosed-6.rs",
    "content": "---\n//~^ ERROR unclosed frontmatter\n🦀---\n ---\n\n// This test checks the location of the --- recovered by the parser is not\n// incorrectly tracked during the less fortunate recovery case and multiple\n// candidates are found, as seen with #146847\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-unclosed-6.stderr",
    "content": "[ERROR] unclosed frontmatter; expected `---`\n  --> script:12:14\n   |\n 1 | ---\n...\n12 | fn main() {}\n   |             ^\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-whitespace-trailing-1.rs",
    "content": "\n\n---cargo   \t\n---   \t\n\n// please note the whitespace characters after the first four lines.\n// This ensures that we accept whitespaces before the frontmatter, after\n// the frontmatter opening and the frontmatter close.\n\n//@ check-pass\n// ignore-tidy-end-whitespace\n// ignore-tidy-leading-newlines\n// ignore-tidy-tab\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-whitespace-trailing-1.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-whitespace-trailing-2.rs",
    "content": "--- \tcargo\n---\n\n//@ check-pass\n// ignore-tidy-tab\n// A frontmatter infostring can have leading whitespace.\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/fence-whitespace-trailing-2.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/frontmatter-crlf.rs",
    "content": "#!/usr/bin/env -S cargo -Zscript\r\n---\r\n[dependencies]\r\nclap = \"4\"\r\n---\r\n\r\n//@ check-pass\r\n// ignore-tidy-cr\r\n\r\n// crlf line endings should be accepted\r\n\r\n#![feature(frontmatter)]\r\n\r\nfn main() {}\r\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/frontmatter-crlf.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [\n    {\n      \"features\": [],\n      \"kind\": null,\n      \"name\": \"clap\",\n      \"optional\": false,\n      \"registry\": null,\n      \"rename\": null,\n      \"req\": \"^4\",\n      \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n      \"target\": null,\n      \"uses_default_features\": true\n    }\n  ],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/infostring-comma.rs",
    "content": "---cargo,clippy\n//~^ ERROR: invalid infostring for frontmatter\n---\n\n// infostrings can only be a single identifier.\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/infostring-comma.stderr",
    "content": "[ERROR] unsupported frontmatter infostring attributes: `clippy`\n --> script:1:4\n  |\n1 | ---cargo,clippy\n  |    ^^^^^^^^^^^^\n2 | //~^ ERROR: invalid infostring for frontmatter\n3 | ---\n  |\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/infostring-dot-leading.rs",
    "content": "---.toml\n//~^ ERROR: invalid infostring for frontmatter\n---\n\n// infostrings cannot have leading dots\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/infostring-dot-leading.stderr",
    "content": "[ERROR] unsupported frontmatter infostring `.toml`; specify `cargo` for embedding a manifest\n --> script:1:4\n  |\n1 | ---.toml\n  |    ^^^^^\n2 | //~^ ERROR: invalid infostring for frontmatter\n3 | ---\n  |\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/infostring-dot-nonleading.rs",
    "content": "---Cargo.toml\n---\n\n// infostrings can contain dots as long as a dot isn't the first character.\n//@ check-pass\n// CARGO(fail): unsupported infostring\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/infostring-dot-nonleading.stderr",
    "content": "[ERROR] unsupported frontmatter infostring `Cargo.toml`; specify `cargo` for embedding a manifest\n --> script:1:4\n  |\n1 | ---Cargo.toml\n  |    ^^^^^^^^^^\n2 | ---\n  |\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/infostring-hyphen-leading.rs",
    "content": "--- -toml\n//~^ ERROR: invalid infostring for frontmatter\n---\n\n// infostrings cannot have leading hyphens\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/infostring-hyphen-leading.stderr",
    "content": "[ERROR] unsupported frontmatter infostring `-toml`; specify `cargo` for embedding a manifest\n --> script:1:5\n  |\n1 | --- -toml\n  |     ^^^^^\n2 | //~^ ERROR: invalid infostring for frontmatter\n3 | ---\n  |\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/infostring-hyphen-nonleading.rs",
    "content": "--- Cargo-toml\n---\n\n// infostrings can contain hyphens as long as a hyphen isn't the first character.\n//@ check-pass\n// CARGO(fail): unsupported infostring\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/infostring-hyphen-nonleading.stderr",
    "content": "[ERROR] unsupported frontmatter infostring `Cargo-toml`; specify `cargo` for embedding a manifest\n --> script:1:5\n  |\n1 | --- Cargo-toml\n  |     ^^^^^^^^^^\n2 | ---\n  |\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/infostring-space.rs",
    "content": "--- cargo clippy\n//~^ ERROR: invalid infostring for frontmatter\n---\n\n// infostrings cannot have spaces\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/infostring-space.stderr",
    "content": "[ERROR] unsupported frontmatter infostring `cargo clippy`; specify `cargo` for embedding a manifest\n --> script:1:5\n  |\n1 | --- cargo clippy\n  |     ^^^^^^^^^^^^\n2 | //~^ ERROR: invalid infostring for frontmatter\n3 | ---\n  |\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/location-after-shebang.rs",
    "content": "#!/usr/bin/env -S cargo -Zscript\n---\n[dependencies]\nclap = \"4\"\n---\n\n//@ check-pass\n\n// Shebangs on a file can precede a frontmatter.\n\n#![feature(frontmatter)]\n\nfn main () {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/location-after-shebang.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [\n    {\n      \"features\": [],\n      \"kind\": null,\n      \"name\": \"clap\",\n      \"optional\": false,\n      \"registry\": null,\n      \"rename\": null,\n      \"req\": \"^4\",\n      \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n      \"target\": null,\n      \"uses_default_features\": true\n    }\n  ],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/location-after-tokens.rs",
    "content": "#![feature(frontmatter)]\n\n---\n//~^ ERROR: expected item, found `-`\n// FIXME(frontmatter): make this diagnostic better\n---\n\n// frontmatters must be at the start of a file. This test ensures that.\n// CARGO(pass): not technitcally a frontmatter, so defer to rustc to error\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/location-after-tokens.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/location-include-in-expr-ctxt.rs",
    "content": "// Check that an expr-ctxt `include` doesn't try to parse frontmatter and instead\n// treats it as a regular Rust token sequence.\n//@ check-pass\n#![expect(double_negations)]\n\nfn main() {\n    // issue: <https://github.com/rust-lang/rust/issues/145945>\n    const _: () = assert!(-1 == include!(\"auxiliary/expr.rs\"));\n}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/location-include-in-expr-ctxt.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/location-include-in-item-ctxt.rs",
    "content": "// Ensure that in item ctxts we can `include` files that contain frontmatter.\n//@ check-pass\n\n#![feature(frontmatter)]\n\ninclude!(\"auxiliary/lib.rs\");\n\nfn main() {\n    foo(1);\n}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/location-include-in-item-ctxt.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/location-proc-macro-observer.rs",
    "content": "//@ check-pass\n//@ proc-macro: makro.rs\n//@ edition: 2021\n//@ ignore-backends: gcc\n\n// Check that a proc-macro doesn't try to parse frontmatter and instead treats\n// it as a regular Rust token sequence. See `auxiliary/makro.rs` for details.\n\nmakro::check!();\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/location-proc-macro-observer.stdout",
    "content": "{\n  \"authors\": [],\n  \"categories\": [],\n  \"default_run\": null,\n  \"dependencies\": [],\n  \"description\": null,\n  \"documentation\": null,\n  \"edition\": \"2024\",\n  \"features\": {},\n  \"homepage\": null,\n  \"id\": \"path+[ROOTURL]/foo/script#0.0.0\",\n  \"keywords\": [],\n  \"license\": null,\n  \"license_file\": null,\n  \"links\": null,\n  \"manifest_path\": \"[ROOT]/foo/script\",\n  \"metadata\": null,\n  \"name\": \"script\",\n  \"publish\": [],\n  \"readme\": null,\n  \"repository\": null,\n  \"rust_version\": null,\n  \"source\": null,\n  \"targets\": [\n    {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": true,\n      \"doctest\": false,\n      \"edition\": \"2024\",\n      \"kind\": [\n        \"bin\"\n      ],\n      \"name\": \"script\",\n      \"src_path\": \"[ROOT]/foo/script\",\n      \"test\": true\n    }\n  ],\n  \"version\": \"0.0.0\"\n}"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/multifrontmatter.rs",
    "content": "---\n---\n\n---\n//~^ ERROR: expected item, found `-`\n// FIXME(frontmatter): make this diagnostic better\n---\n\n// test that we do not parse another frontmatter block after the first one.\n\n#![feature(frontmatter)]\n\nfn main() {}\n"
  },
  {
    "path": "tests/testsuite/script/rustc_fixtures/multifrontmatter.stderr",
    "content": "[ERROR] only one frontmatter is supported\n --> script:4:1\n  |\n1 | ---\n2 | ---\n3 |\n4 | ---\n  | ^^^\n"
  },
  {
    "path": "tests/testsuite/search.rs",
    "content": "//! Tests for the `cargo search` command.\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::registry::{RegistryBuilder, Response};\nuse cargo_test_support::str;\n\nconst SEARCH_API_RESPONSE: &[u8] = br#\"\n{\n    \"crates\": [{\n        \"created_at\": \"2014-11-16T20:17:35Z\",\n        \"description\": \"Design by contract style assertions for Rust\",\n        \"documentation\": null,\n        \"downloads\": 2,\n        \"homepage\": null,\n        \"id\": \"hoare\",\n        \"keywords\": [],\n        \"license\": null,\n        \"links\": {\n            \"owners\": \"/api/v1/crates/hoare/owners\",\n            \"reverse_dependencies\": \"/api/v1/crates/hoare/reverse_dependencies\",\n            \"version_downloads\": \"/api/v1/crates/hoare/downloads\",\n            \"versions\": \"/api/v1/crates/hoare/versions\"\n        },\n        \"max_version\": \"0.1.1\",\n        \"name\": \"hoare\",\n        \"repository\": \"https://github.com/nick29581/libhoare\",\n        \"updated_at\": \"2014-11-20T21:49:21Z\",\n        \"versions\": null\n    },\n    {\n        \"id\": \"postgres\",\n        \"name\": \"postgres\",\n        \"updated_at\": \"2020-05-01T23:17:54.335921+00:00\",\n        \"versions\": null,\n        \"keywords\": null,\n        \"categories\": null,\n        \"badges\": [\n            {\n                \"badge_type\": \"circle-ci\",\n                \"attributes\": {\n                    \"repository\": \"sfackler/rust-postgres\",\n                    \"branch\": null\n                }\n            }\n        ],\n        \"created_at\": \"2014-11-24T02:34:44.756689+00:00\",\n        \"downloads\": 535491,\n        \"recent_downloads\": 88321,\n        \"max_version\": \"0.17.3\",\n        \"newest_version\": \"0.17.3\",\n        \"description\": \"A native, synchronous PostgreSQL client\",\n        \"homepage\": null,\n        \"documentation\": null,\n        \"repository\": \"https://github.com/sfackler/rust-postgres\",\n        \"links\": {\n            \"version_downloads\": \"/api/v1/crates/postgres/downloads\",\n            \"versions\": \"/api/v1/crates/postgres/versions\",\n            \"owners\": \"/api/v1/crates/postgres/owners\",\n            \"owner_team\": \"/api/v1/crates/postgres/owner_team\",\n            \"owner_user\": \"/api/v1/crates/postgres/owner_user\",\n            \"reverse_dependencies\": \"/api/v1/crates/postgres/reverse_dependencies\"\n        },\n        \"exact_match\": true\n    }\n    ],\n    \"meta\": {\n        \"total\": 2\n    }\n}\"#;\n\nconst SEARCH_RESULTS: &str = \"\\\nhoare = \\\"0.1.1\\\"        # Design by contract style assertions for Rust\npostgres = \\\"0.17.3\\\"    # A native, synchronous PostgreSQL client\n\";\n\n#[must_use]\nfn setup() -> RegistryBuilder {\n    RegistryBuilder::new()\n        .http_api()\n        .add_responder(\"/api/v1/crates\", |_, _| Response {\n            code: 200,\n            headers: vec![],\n            body: SEARCH_API_RESPONSE.to_vec(),\n        })\n}\n\n#[cargo_test]\nfn not_update() {\n    let registry = setup().build();\n\n    cargo_process(\"search postgres\")\n        .replace_crates_io(registry.index_url())\n        .with_stdout_data(SEARCH_RESULTS)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[NOTE] to learn more about a package, run `cargo info <name>`\n\n\"#]])\n        .run();\n\n    cargo_process(\"search postgres\")\n        .replace_crates_io(registry.index_url())\n        .with_stdout_data(SEARCH_RESULTS)\n        // without \"Updating ... index\"\n        .with_stderr_data(str![[r#\"\n[NOTE] to learn more about a package, run `cargo info <name>`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn replace_default() {\n    let registry = setup().build();\n\n    cargo_process(\"search postgres\")\n        .replace_crates_io(registry.index_url())\n        .with_stdout_data(SEARCH_RESULTS)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[NOTE] to learn more about a package, run `cargo info <name>`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple() {\n    let registry = setup().build();\n\n    cargo_process(\"search postgres --index\")\n        .arg(registry.index_url().as_str())\n        .with_stdout_data(SEARCH_RESULTS)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[ROOT]/registry` index\n[NOTE] to learn more about a package, run `cargo info <name>`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn multiple_query_params() {\n    let registry = setup().build();\n\n    cargo_process(\"search postgres sql --index\")\n        .arg(registry.index_url().as_str())\n        .with_stdout_data(SEARCH_RESULTS)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[ROOT]/registry` index\n[NOTE] to learn more about a package, run `cargo info <name>`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ignore_quiet() {\n    let registry = setup().build();\n\n    cargo_process(\"search -q postgres\")\n        .replace_crates_io(registry.index_url())\n        .with_stdout_data(SEARCH_RESULTS)\n        .run();\n}\n\n#[cargo_test]\nfn colored_results() {\n    let registry = setup().build();\n\n    cargo_process(\"search --color=never postgres\")\n        .replace_crates_io(registry.index_url())\n        .with_stdout_does_not_contain(\"[..]\\x1b[[..]\")\n        .run();\n\n    cargo_process(\"search --color=always postgres\")\n        .replace_crates_io(registry.index_url())\n        .with_stdout_data(\n            \"\\\n...\n[..]\\x1b[[..]\n...\n\",\n        )\n        .run();\n}\n\n#[cargo_test]\nfn auth_required_failure() {\n    let server = setup().auth_required().no_configure_token().build();\n\n    cargo_process(\"search postgres\")\n        .replace_crates_io(server.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[ERROR] no token found, please run `cargo login`\nor use environment variable CARGO_REGISTRY_TOKEN\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn auth_required() {\n    let server = setup().auth_required().build();\n\n    cargo_process(\"search postgres\")\n        .replace_crates_io(server.index_url())\n        .with_stdout_data(SEARCH_RESULTS)\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/shell_quoting.rs",
    "content": "//! This file tests that when the commands being run are shown\n//! in the output, their arguments are quoted properly\n//! so that the command can be run in a terminal.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn features_are_quoted() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            authors = [\"mikeyhew@example.com\"]\n            edition = \"2015\"\n\n            [features]\n            some_feature = []\n            default = [\"some_feature\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {error}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .env(\"MSYSTEM\", \"1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] --cfg 'feature=\"default\"' --cfg 'feature=\"some_feature\"' [..]`\n...\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n\nCaused by:\n  process didn't exit successfully: [..] --cfg 'feature=\"default\"' --cfg 'feature=\"some_feature\"' [..]\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/source_replacement.rs",
    "content": "//! Tests for `[source]` table (source replacement).\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::registry::{Package, RegistryBuilder, TestRegistry};\nuse cargo_test_support::{paths, project, str, t};\n\nfn setup_replacement(config: &str) -> TestRegistry {\n    let crates_io = RegistryBuilder::new()\n        .no_configure_registry()\n        .http_api()\n        .build();\n\n    let root = paths::root();\n    t!(fs::create_dir(&root.join(\".cargo\")));\n    t!(fs::write(root.join(\".cargo/config.toml\"), config,));\n    crates_io\n}\n\n#[cargo_test]\nfn crates_io_token_not_sent_to_replacement() {\n    // verifies that the crates.io token is not sent to a replacement registry during publish.\n    let crates_io = setup_replacement(\n        r#\"\n        [source.crates-io]\n        replace-with = 'alternative'\n    \"#,\n    );\n    let _alternative = RegistryBuilder::new()\n        .alternative()\n        .http_api()\n        .no_configure_token()\n        .build();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish --no-verify --registry crates-io\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn token_sent_to_correct_registry() {\n    // verifies that the crates.io token is not sent to a replacement registry during yank.\n    let crates_io = setup_replacement(\n        r#\"\n        [source.crates-io]\n        replace-with = 'alternative'\n    \"#,\n    );\n    let _alternative = RegistryBuilder::new().alternative().http_api().build();\n\n    cargo_process(\"yank foo@0.0.1 --registry crates-io\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[YANK] foo@0.0.1\n\n\"#]])\n        .run();\n\n    cargo_process(\"yank foo@0.0.1 --registry alternative\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[YANK] foo@0.0.1\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ambiguous_registry() {\n    // verifies that an error is issued when a source-replacement is configured\n    // and no --registry argument is given.\n    let crates_io = setup_replacement(\n        r#\"\n        [source.crates-io]\n        replace-with = 'alternative'\n    \"#,\n    );\n    let _alternative = RegistryBuilder::new()\n        .alternative()\n        .http_api()\n        .no_configure_token()\n        .build();\n\n    cargo_process(\"yank foo@0.0.1\")\n        .replace_crates_io(crates_io.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] crates-io is replaced with remote registry alternative;\ninclude `--registry alternative` or `--registry crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn yank_with_default_crates_io() {\n    // verifies that no error is given when registry.default is used.\n    let crates_io = setup_replacement(\n        r#\"\n        [source.crates-io]\n        replace-with = 'alternative'\n\n        [registry]\n        default = 'crates-io'\n    \"#,\n    );\n    let _alternative = RegistryBuilder::new().alternative().http_api().build();\n\n    cargo_process(\"yank foo@0.0.1\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[YANK] foo@0.0.1\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn yank_with_default_alternative() {\n    // verifies that no error is given when registry.default is an alt registry.\n    let crates_io = setup_replacement(\n        r#\"\n        [source.crates-io]\n        replace-with = 'alternative'\n\n        [registry]\n        default = 'alternative'\n    \"#,\n    );\n    let _alternative = RegistryBuilder::new().alternative().http_api().build();\n\n    cargo_process(\"yank foo@0.0.1\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[YANK] foo@0.0.1\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_with_replacement() {\n    // verifies that the crates.io token is not sent to a replacement registry during publish.\n    let crates_io = setup_replacement(\n        r#\"\n        [source.crates-io]\n        replace-with = 'alternative'\n    \"#,\n    );\n    let _alternative = RegistryBuilder::new()\n        .alternative()\n        .http_api()\n        .no_configure_token()\n        .build();\n\n    // Publish bar only to alternative. This tests that the publish verification build\n    // does uses the source replacement.\n    Package::new(\"bar\", \"1.0.0\").alternative(true).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Verifies that the crates.io index is used to find the publishing endpoint\n    // and that the crate is sent to crates.io. The source replacement is only used\n    // for the verification step.\n    p.cargo(\"publish --registry crates-io\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[WARNING] manifest has no documentation, homepage or repository\n  |\n  = [NOTE] see https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info\n[PACKAGING] foo v0.0.1 ([ROOT]/foo)\n[UPDATING] `alternative` index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.0.1 ([ROOT]/foo)\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `alternative`)\n[COMPILING] bar v1.0.0\n[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.0.1 ([ROOT]/foo)\n[UPLOADED] foo v0.0.1 to registry `crates-io`\n[NOTE] waiting for foo v0.0.1 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.0.1 at registry `crates-io`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn undefined_default() {\n    // verifies that no error is given when registry.default is used.\n    let crates_io = setup_replacement(\n        r#\"\n        [registry]\n        default = 'undefined'\n    \"#,\n    );\n\n    cargo_process(\"yank foo@0.0.1\")\n        .replace_crates_io(crates_io.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] registry index was not found in any configuration: `undefined`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn source_replacement_with_registry_url() {\n    let alternative = RegistryBuilder::new().alternative().http_api().build();\n    Package::new(\"bar\", \"0.0.1\").alternative(true).publish();\n\n    let crates_io = setup_replacement(&format!(\n        r#\"\n        [source.crates-io]\n        replace-with = 'using-registry-url'\n\n        [source.using-registry-url]\n        registry = '{}'\n        \"#,\n        alternative.index_url()\n    ));\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                [dependencies.bar]\n                version = \"0.0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .replace_crates_io(crates_io.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] `using-registry-url` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `using-registry-url`)\n[CHECKING] bar v0.0.1\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn source_replacement_with_no_package_in_directory() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                bar = { version = \"^0.8.9\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let root = paths::root();\n    t!(fs::create_dir(&root.join(\"vendor\")));\n\n    let crates_io = setup_replacement(&format!(\n        r#\"\n            [source.crates-io]\n            replace-with = \"vendored-sources\"\n\n            [source.vendored-sources]\n            directory = \"vendor\"\n        \"#\n    ));\n\n    p.cargo(\"build\")\n        .replace_crates_io(crates_io.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no matching package named `bar` found\nlocation searched: directory source `[ROOT]/vendor` (which is replacing registry `crates-io`)\nrequired by package `foo v0.1.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/ssh.rs",
    "content": "//! Network tests for SSH connections.\n//!\n//! Note that these tests will generally require setting `CARGO_CONTAINER_TESTS`\n//! or `CARGO_PUBLIC_NETWORK_TESTS`.\n//!\n//! NOTE: The container tests almost certainly won't work on Windows.\n\nuse std::fs;\nuse std::io::Write;\nuse std::path::PathBuf;\n\nuse crate::prelude::*;\nuse cargo_test_support::containers::{Container, ContainerHandle, MkFile};\nuse cargo_test_support::git::cargo_uses_gitoxide;\nuse cargo_test_support::{Project, paths, process, project, str};\n\nfn ssh_repo_url(container: &ContainerHandle, name: &str) -> String {\n    let port = container.port_mappings[&22];\n    format!(\"ssh://testuser@127.0.0.1:{port}/repos/{name}.git\")\n}\n\n/// The path to the client's private key.\nfn key_path() -> PathBuf {\n    paths::home().join(\".ssh/id_ed25519\")\n}\n\n/// Generates the SSH keys for authenticating into the container.\nfn gen_ssh_keys() -> String {\n    let path = key_path();\n    process(\"ssh-keygen\")\n        .args(&[\"-t\", \"ed25519\", \"-N\", \"\", \"-f\"])\n        .arg(&path)\n        .exec_with_output()\n        .unwrap();\n    let pub_key = path.with_extension(\"pub\");\n    fs::read_to_string(pub_key).unwrap()\n}\n\n/// Handler for running ssh-agent for SSH authentication.\n///\n/// Be sure to set `SSH_AUTH_SOCK` when running a process in order to use the\n/// agent. Keys will need to be copied into the container with the\n/// `authorized_keys()` method.\nstruct Agent {\n    sock: PathBuf,\n    pid: String,\n    ssh_dir: PathBuf,\n    pub_key: String,\n}\n\nimpl Agent {\n    fn launch() -> Agent {\n        let ssh_dir = paths::home().join(\".ssh\");\n        fs::create_dir(&ssh_dir).unwrap();\n        let pub_key = gen_ssh_keys();\n\n        let sock = paths::root().join(\"agent\");\n        let output = process(\"ssh-agent\")\n            .args(&[\"-s\", \"-a\"])\n            .arg(&sock)\n            .exec_with_output()\n            .unwrap();\n        let stdout = std::str::from_utf8(&output.stdout).unwrap();\n        let start = stdout.find(\"SSH_AGENT_PID=\").unwrap() + 14;\n        let end = &stdout[start..].find(';').unwrap();\n        let pid = (&stdout[start..start + end]).to_string();\n        eprintln!(\"SSH_AGENT_PID={pid}\");\n        process(\"ssh-add\")\n            .arg(key_path())\n            .env(\"SSH_AUTH_SOCK\", &sock)\n            .exec_with_output()\n            .unwrap();\n        Agent {\n            sock,\n            pid,\n            ssh_dir,\n            pub_key,\n        }\n    }\n\n    /// Returns a `MkFile` which can be passed into the `Container` builder to\n    /// copy an `authorized_keys` file containing this agent's public key.\n    fn authorized_keys(&self) -> MkFile {\n        MkFile::path(\"home/testuser/.ssh/authorized_keys\")\n            .contents(self.pub_key.as_bytes())\n            .mode(0o600)\n            .uid(100)\n            .gid(101)\n    }\n}\n\nimpl Drop for Agent {\n    fn drop(&mut self) {\n        if let Err(e) = process(\"ssh-agent\")\n            .args(&[\"-k\", \"-a\"])\n            .arg(&self.sock)\n            .env(\"SSH_AGENT_PID\", &self.pid)\n            .exec_with_output()\n        {\n            eprintln!(\"failed to stop ssh-agent: {e:?}\");\n        }\n    }\n}\n\n/// Common project used for several tests.\nfn foo_bar_project(url: &str) -> Project {\n    project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = {{ git = \"{url}\" }}\n            \"#\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build()\n}\n\n#[cargo_test(container_test)]\nfn no_known_host() {\n    // When host is not known, it should show an error.\n    let sshd = Container::new(\"sshd\").launch();\n    let url = ssh_repo_url(&sshd, \"bar\");\n    let p = foo_bar_project(&url);\n    p.cargo(\"fetch\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `ssh://testuser@127.0.0.1:[..]/repos/bar.git`\n[ERROR] failed to get `bar` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update ssh://testuser@127.0.0.1:[..]/repos/bar.git\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH]\n\nCaused by:\n  [ERROR] unknown SSH host key\n  The SSH host key for `[127.0.0.1]:[..]` is not known and cannot be validated.\n\n  To resolve this issue, add the host key to the `net.ssh.known-hosts` array in your Cargo configuration (such as [ROOT]/home/.cargo/config.toml) or in your OpenSSH known_hosts file at [ROOT]/home/.ssh/known_hosts\n\n  The key to add is:\n\n  [127.0.0.1]:[..] ecdsa-sha2-nistp256 AAAA[..]\n\n  The ECDSA key fingerprint is: SHA256:[..]\n  This fingerprint should be validated with the server administrator that it is correct.\n\n  See https://doc.rust-lang.org/stable/cargo/appendix/git-authentication.html#ssh-known-hosts for more information.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(container_test)]\nfn known_host_works() {\n    // The key displayed in the error message should work when added to known_hosts.\n    let agent = Agent::launch();\n    let sshd = Container::new(\"sshd\")\n        .file(agent.authorized_keys())\n        .launch();\n    let url = ssh_repo_url(&sshd, \"bar\");\n    let p = foo_bar_project(&url);\n    let output = p\n        .cargo(\"fetch\")\n        .env(\"SSH_AUTH_SOCK\", &agent.sock)\n        .build_command()\n        .output()\n        .unwrap();\n    let stderr = std::str::from_utf8(&output.stderr).unwrap();\n\n    // Validate the fingerprint while we're here.\n    let fingerprint = stderr\n        .lines()\n        .find_map(|line| line.strip_prefix(\"  The ECDSA key fingerprint is: \"))\n        .unwrap()\n        .trim();\n    let finger_out = sshd.exec(&[\"ssh-keygen\", \"-l\", \"-f\", \"/etc/ssh/ssh_host_ecdsa_key.pub\"]);\n    let gen_finger = std::str::from_utf8(&finger_out.stdout).unwrap();\n    // <key-size> <fingerprint> <comments…>\n    let gen_finger = gen_finger.split_whitespace().nth(1).unwrap();\n    assert_eq!(fingerprint, gen_finger);\n\n    // Add the key to known_hosts, and try again.\n    let key = stderr\n        .lines()\n        .find(|line| line.starts_with(\"  [127.0.0.1]:\"))\n        .unwrap()\n        .trim();\n    fs::write(agent.ssh_dir.join(\"known_hosts\"), key).unwrap();\n    p.cargo(\"fetch\")\n        .env(\"SSH_AUTH_SOCK\", &agent.sock)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `ssh://testuser@127.0.0.1:[..]/repos/bar.git`\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(container_test)]\nfn same_key_different_hostname() {\n    // The error message should mention if an identical key was found.\n    let agent = Agent::launch();\n    let sshd = Container::new(\"sshd\").launch();\n\n    let hostkey = sshd.read_file(\"/etc/ssh/ssh_host_ecdsa_key.pub\");\n    let known_hosts = format!(\"example.com {hostkey}\");\n    fs::write(agent.ssh_dir.join(\"known_hosts\"), known_hosts).unwrap();\n\n    let url = ssh_repo_url(&sshd, \"bar\");\n    let p = foo_bar_project(&url);\n    p.cargo(\"fetch\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `ssh://testuser@127.0.0.1:[..]/repos/bar.git`\n[ERROR] failed to get `bar` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update ssh://testuser@127.0.0.1:[..]/repos/bar.git\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH]\n\nCaused by:\n  [ERROR] unknown SSH host key\n  The SSH host key for `[127.0.0.1]:[..]` is not known and cannot be validated.\n\n  To resolve this issue, add the host key to the `net.ssh.known-hosts` array in your Cargo configuration (such as [ROOT]/home/.cargo/config.toml) or in your OpenSSH known_hosts file at [ROOT]/home/.ssh/known_hosts\n\n  The key to add is:\n\n  [127.0.0.1]:[..] ecdsa-sha2-nistp256 AAAA[..]\n\n  The ECDSA key fingerprint is: SHA256:[..]\n  This fingerprint should be validated with the server administrator that it is correct.\n  Note: This host key was found, but is associated with a different host:\n      [ROOT]/home/.ssh/known_hosts line 1: example.com\n\n  See https://doc.rust-lang.org/stable/cargo/appendix/git-authentication.html#ssh-known-hosts for more information.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(container_test)]\nfn known_host_without_port() {\n    // A known_host entry without a port should match a connection to a non-standard port.\n    let agent = Agent::launch();\n    let sshd = Container::new(\"sshd\")\n        .file(agent.authorized_keys())\n        .launch();\n\n    let hostkey = sshd.read_file(\"/etc/ssh/ssh_host_ecdsa_key.pub\");\n    // The important part of this test is that this line does not have a port.\n    let known_hosts = format!(\"127.0.0.1 {hostkey}\");\n    fs::write(agent.ssh_dir.join(\"known_hosts\"), known_hosts).unwrap();\n    let url = ssh_repo_url(&sshd, \"bar\");\n    let p = foo_bar_project(&url);\n    p.cargo(\"fetch\")\n        .env(\"SSH_AUTH_SOCK\", &agent.sock)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `ssh://testuser@127.0.0.1:[..]/repos/bar.git`\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(container_test)]\nfn hostname_case_insensitive() {\n    // hostname checking should be case-insensitive.\n    let agent = Agent::launch();\n    let sshd = Container::new(\"sshd\")\n        .file(agent.authorized_keys())\n        .launch();\n\n    // Consider using `gethostname-rs` instead?\n    let hostname = process(\"hostname\").exec_with_output().unwrap();\n    let hostname = std::str::from_utf8(&hostname.stdout).unwrap().trim();\n    let inv_hostname = if hostname.chars().any(|c| c.is_lowercase()) {\n        hostname.to_uppercase()\n    } else {\n        // There should be *some* chars in the name.\n        assert!(hostname.chars().any(|c| c.is_uppercase()));\n        hostname.to_lowercase()\n    };\n    eprintln!(\"converted {hostname} to {inv_hostname}\");\n\n    let hostkey = sshd.read_file(\"/etc/ssh/ssh_host_ecdsa_key.pub\");\n    let known_hosts = format!(\"{inv_hostname} {hostkey}\");\n    fs::write(agent.ssh_dir.join(\"known_hosts\"), known_hosts).unwrap();\n    let port = sshd.port_mappings[&22];\n    let url = format!(\"ssh://testuser@{hostname}:{port}/repos/bar.git\");\n    let p = foo_bar_project(&url);\n    p.cargo(\"fetch\")\n        .env(\"SSH_AUTH_SOCK\", &agent.sock)\n        .with_stderr_data(&format!(\n            \"\\\n[UPDATING] git repository `ssh://testuser@{hostname}:{port}/repos/bar.git`\n[LOCKING] 1 package to latest compatible version\n\"\n        ))\n        .run();\n}\n\n#[cargo_test(container_test)]\nfn invalid_key_error() {\n    // An error when a known_host value doesn't match.\n    let agent = Agent::launch();\n    let sshd = Container::new(\"sshd\")\n        .file(agent.authorized_keys())\n        .launch();\n\n    let port = sshd.port_mappings[&22];\n    let known_hosts = format!(\n        \"[127.0.0.1]:{port} ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLqLMclVr7MDuaVsm3sEnnq2OrGxTFiHSw90wd6N14BU8xVC9cZldC3rJ58Wmw6bEVKPjk7foNG0lHwS5bCKX+U=\\n\"\n    );\n    fs::write(agent.ssh_dir.join(\"known_hosts\"), known_hosts).unwrap();\n    let url = ssh_repo_url(&sshd, \"bar\");\n    let p = foo_bar_project(&url);\n    p.cargo(\"fetch\")\n        .env(\"SSH_AUTH_SOCK\", &agent.sock)\n        .with_status(101)\n        .with_stderr_data(&format!(\"\\\n[UPDATING] git repository `ssh://testuser@127.0.0.1:{port}/repos/bar.git`\n[ERROR] failed to get `bar` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bar`\n\nCaused by:\n  unable to update ssh://testuser@127.0.0.1:{port}/repos/bar.git\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH]\n\nCaused by:\n  [ERROR] SSH host key has changed for `[127.0.0.1]:{port}`\n  *********************************\n  * WARNING: HOST KEY HAS CHANGED *\n  *********************************\n  This may be caused by a man-in-the-middle attack, or the server may have changed its host key.\n\n  The ECDSA fingerprint for the key from the remote host is:\n  SHA256:[..]\n\n  You are strongly encouraged to contact the server administrator for `[127.0.0.1]:{port}` to verify that this new key is correct.\n\n  If you can verify that the server has a new key, you can resolve this error by removing the old ecdsa-sha2-nistp256 key for `[127.0.0.1]:{port}` located at [ROOT]/home/.ssh/known_hosts line 1, and adding the new key to the `net.ssh.known-hosts` array in your Cargo configuration (such as [ROOT]/home/.cargo/config.toml) or in your OpenSSH known_hosts file at [ROOT]/home/.ssh/known_hosts\n\n  The key provided by the remote host is:\n\n  [127.0.0.1]:{port} ecdsa-sha2-nistp256 [..]\n\n  See https://doc.rust-lang.org/stable/cargo/appendix/git-authentication.html#ssh-known-hosts for more information.\n\"))\n        .run();\n    // Add the key, it should work even with the old key left behind.\n    let hostkey = sshd.read_file(\"/etc/ssh/ssh_host_ecdsa_key.pub\");\n    let known_hosts_path = agent.ssh_dir.join(\"known_hosts\");\n    let mut f = fs::OpenOptions::new()\n        .append(true)\n        .open(known_hosts_path)\n        .unwrap();\n    write!(f, \"[127.0.0.1]:{port} {hostkey}\").unwrap();\n    drop(f);\n    p.cargo(\"fetch\")\n        .env(\"SSH_AUTH_SOCK\", &agent.sock)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `ssh://testuser@127.0.0.1:[..]/repos/bar.git`\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n}\n\n// For unknown reasons, this test occasionally fails on Windows with a\n// LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE error:\n//     failed to start SSH session: Unable to exchange encryption keys; class=Ssh (23)\n#[cargo_test(public_network_test, ignore_windows = \"test is flaky on windows\")]\nfn invalid_github_key() {\n    // A key for github.com in known_hosts should override the built-in key.\n    // This uses a bogus key which should result in an error.\n    let ssh_dir = paths::home().join(\".ssh\");\n    fs::create_dir(&ssh_dir).unwrap();\n    let known_hosts = \"\\\n        github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLqLMclVr7MDuaVsm3sEnnq2OrGxTFiHSw90wd6N14BU8xVC9cZldC3rJ58Wmw6bEVKPjk7foNG0lHwS5bCKX+U=\\n\\\n        github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDgi+8rMcyFCBq5y7BXrb2aaYGhMjlU3QDy7YDvtNL5KSecYOsaqQHaXr87Bbx0EEkgbhK4kVMkmThlCoNITQS9Vc3zIMQ+Tg6+O4qXx719uCzywl50Tb5tDqPGMj54jcq3VUiu/dvse0yeehyvzoPNWewgGWLx11KI4A4wOwMnc6guhculEWe9DjGEjUQ34lPbmdfu/Hza7ZVu/RhgF/wc43uzXWB2KpMEqtuY1SgRlCZqTASoEtfKZi0AuM7AEdOwE5aTotS4CQZHWimb1bMFpF4DAq92CZ8Jhrm4rWETbO29WmjviCJEA3KNQyd3oA7H9AE9z/22PJaVEmjiZZ+wyLgwyIpOlsnHYNEdGeQMQ4SgLRkARLwcnKmByv1AAxsBW4LI3Os4FpwxVPdXHcBebydtvxIsbtUVkkq99nbsIlnSRFSTvb0alrdzRuKTdWpHtN1v9hagFqmeCx/kJfH76NXYBbtaWZhSOnxfEbhLYuOb+IS4jYzHAIkzy9FjVuk=\\n\\\n        ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEeMB6BUAW6FfvfLxRO3kGASe0yXnrRT4kpqncsup2b2\\n\";\n    fs::write(ssh_dir.join(\"known_hosts\"), known_hosts).unwrap();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bitflags = { git = \"ssh://git@github.com/rust-lang/bitflags.git\", tag = \"1.3.2\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"fetch\")\n        .with_status(101)\n        .with_stderr_data(if cargo_uses_gitoxide() {\n            str![[r#\"\n...\n  git@github.com: Permission denied (publickey).\n...\n\"#]]\n        } else {\n            str![[r#\"\n...\n  [ERROR] SSH host key has changed for `github.com`\n...\n\"#]]\n        })\n        .run();\n}\n\n// For unknown reasons, this test occasionally fails on Windows with a\n// LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE error:\n//     failed to start SSH session: Unable to exchange encryption keys; class=Ssh (23)\n#[cargo_test(public_network_test, ignore_windows = \"test is flaky on windows\")]\nfn bundled_github_works() {\n    // The bundled key for github.com works.\n    //\n    // Use a bogus auth sock to force an authentication error.\n    // On Windows, if the agent service is running, it could allow a\n    // successful authentication.\n    //\n    // If the bundled hostkey did not work, it would result in an \"unknown SSH\n    // host key\" instead.\n    let bogus_auth_sock = paths::home().join(\"ssh_auth_sock\");\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bitflags = { git = \"ssh://git@github.com/rust-lang/bitflags.git\", tag = \"1.3.2\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    let expected = if cargo_uses_gitoxide() {\n        str![[r#\"\n[UPDATING] git repository `ssh://git@github.com/rust-lang/bitflags.git`\n[ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bitflags`\n\nCaused by:\n  unable to update ssh://git@github.com/rust-lang/bitflags.git?tag=1.3.2\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bitflags-[HASH]\n\nCaused by:\n  failed to authenticate when downloading repository\n\n  * attempted to find username/password via `credential.helper`, but maybe the found credentials were incorrect\n\n  if the git CLI succeeds then `net.git-fetch-with-cli` may help here\n  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\n\nCaused by:\n[CREDENTIAL]s provided for \"ssh://git@github.com/rust-lang/bitflags.git\" were not accepted by the remote\n\nCaused by:\n  git@github.com: Permission denied (publickey).\n\n\"#]]\n    } else {\n        str![[r#\"\n[UPDATING] git repository `ssh://git@github.com/rust-lang/bitflags.git`\n[ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bitflags`\n\nCaused by:\n  unable to update ssh://git@github.com/rust-lang/bitflags.git?tag=1.3.2\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bitflags-[HASH]\n\nCaused by:\n  failed to authenticate when downloading repository\n\n  * attempted ssh-agent authentication, but no usernames succeeded: `git`\n\n  if the git CLI succeeds then `net.git-fetch-with-cli` may help here\n  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\n\nCaused by:\n  no authentication methods succeeded\n\n\"#]]\n    };\n    p.cargo(\"fetch\")\n        .env(\"SSH_AUTH_SOCK\", &bogus_auth_sock)\n        .with_status(101)\n        .with_stderr_data(expected)\n        .run();\n\n    let expected = if cargo_uses_gitoxide() {\n        str![[r#\"\n[UPDATING] git repository `ssh://git@github.com:22/rust-lang/bitflags.git`\n[ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bitflags`\n\nCaused by:\n  unable to update ssh://git@github.com:22/rust-lang/bitflags.git?tag=1.3.2\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bitflags-[HASH]\n\nCaused by:\n  failed to authenticate when downloading repository\n\n  * attempted to find username/password via `credential.helper`, but maybe the found credentials were incorrect\n\n  if the git CLI succeeds then `net.git-fetch-with-cli` may help here\n  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\n\nCaused by:\n[CREDENTIAL]s provided for \"ssh://git@github.com:22/rust-lang/bitflags.git\" were not accepted by the remote\n\nCaused by:\n  git@github.com: Permission denied (publickey).\n\n\"#]]\n    } else {\n        str![[r#\"\n[UPDATING] git repository `ssh://git@github.com:22/rust-lang/bitflags.git`\n[ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `bitflags`\n\nCaused by:\n  unable to update ssh://git@github.com:22/rust-lang/bitflags.git?tag=1.3.2\n\nCaused by:\n  failed to clone into: [ROOT]/home/.cargo/git/db/bitflags-[HASH]\n\nCaused by:\n  failed to authenticate when downloading repository\n\n  * attempted ssh-agent authentication, but no usernames succeeded: `git`\n\n  if the git CLI succeeds then `net.git-fetch-with-cli` may help here\n  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli\n\nCaused by:\n  no authentication methods succeeded\n\n\"#]]\n    };\n\n    // Explicit :22 should also work with bundled.\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bitflags = { git = \"ssh://git@github.com:22/rust-lang/bitflags.git\", tag = \"1.3.2\" }\n        \"#,\n    );\n    p.cargo(\"fetch\")\n        .env(\"SSH_AUTH_SOCK\", &bogus_auth_sock)\n        .with_status(101)\n        .with_stderr_data(expected)\n        .run();\n}\n\n#[cargo_test(container_test)]\nfn ssh_key_in_config() {\n    // known_host in config works.\n    let agent = Agent::launch();\n    let sshd = Container::new(\"sshd\")\n        .file(agent.authorized_keys())\n        .launch();\n    let hostkey = sshd.read_file(\"/etc/ssh/ssh_host_ecdsa_key.pub\");\n    let url = ssh_repo_url(&sshd, \"bar\");\n    let p = foo_bar_project(&url);\n    p.change_file(\n        \".cargo/config.toml\",\n        &format!(\n            r#\"\n                [net.ssh]\n                known-hosts = ['127.0.0.1 {}']\n            \"#,\n            hostkey.trim()\n        ),\n    );\n    p.cargo(\"fetch\")\n        .env(\"SSH_AUTH_SOCK\", &agent.sock)\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `ssh://testuser@127.0.0.1:[..]/repos/bar.git`\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/standard_lib.rs",
    "content": "//! Tests for building the standard library (-Zbuild-std).\n//!\n//! These tests all use a \"mock\" standard library so that we don't have to\n//! rebuild the real one. There is a separate integration test `build-std`\n//! which builds the real thing, but that should be avoided if possible.\n\nuse std::path::{Path, PathBuf};\n\nuse crate::prelude::*;\nuse cargo_test_support::ProjectBuilder;\nuse cargo_test_support::cross_compile;\nuse cargo_test_support::registry::{Dependency, Package};\nuse cargo_test_support::{Execs, paths, project, rustc_host, str};\n\nstruct Setup {\n    rustc_wrapper: PathBuf,\n    real_sysroot: String,\n}\n\nfn setup() -> Setup {\n    // Our mock sysroot requires a few packages from crates.io, so make sure\n    // they're \"published\" to crates.io. Also edit their code a bit to make sure\n    // that they have access to our custom crates with custom apis.\n    Package::new(\"registry-dep-using-core\", \"1.0.0\")\n        .file(\n            \"src/lib.rs\",\n            \"\n                #![no_std]\n\n                #[cfg(feature = \\\"mockbuild\\\")]\n                pub fn custom_api() {\n                }\n\n                #[cfg(not(feature = \\\"mockbuild\\\"))]\n                pub fn non_sysroot_api() {\n                    core::custom_api();\n                }\n            \",\n        )\n        .add_dep(Dependency::new(\"rustc-std-workspace-core\", \"*\").optional(true))\n        .feature(\"mockbuild\", &[\"rustc-std-workspace-core\"])\n        .publish();\n    Package::new(\"registry-dep-using-alloc\", \"1.0.0\")\n        .file(\n            \"src/lib.rs\",\n            \"\n                #![no_std]\n\n                extern crate alloc;\n\n                #[cfg(feature = \\\"mockbuild\\\")]\n                pub fn custom_api() {\n                }\n\n                #[cfg(not(feature = \\\"mockbuild\\\"))]\n                pub fn non_sysroot_api() {\n                    core::custom_api();\n                    alloc::custom_api();\n                }\n            \",\n        )\n        .add_dep(Dependency::new(\"rustc-std-workspace-core\", \"*\").optional(true))\n        .add_dep(Dependency::new(\"rustc-std-workspace-alloc\", \"*\").optional(true))\n        .feature(\n            \"mockbuild\",\n            &[\"rustc-std-workspace-core\", \"rustc-std-workspace-alloc\"],\n        )\n        .publish();\n    Package::new(\"registry-dep-using-std\", \"1.0.0\")\n        .file(\n            \"src/lib.rs\",\n            \"\n                #[cfg(feature = \\\"mockbuild\\\")]\n                pub fn custom_api() {\n                }\n\n                #[cfg(not(feature = \\\"mockbuild\\\"))]\n                pub fn non_sysroot_api() {\n                    std::custom_api();\n                }\n            \",\n        )\n        .add_dep(Dependency::new(\"rustc-std-workspace-std\", \"*\").optional(true))\n        .feature(\"mockbuild\", &[\"rustc-std-workspace-std\"])\n        .publish();\n\n    let p = ProjectBuilder::new(paths::root().join(\"rustc-wrapper\"))\n        .file(\n            \"src/main.rs\",\n            &r#\"\n                use std::process::Command;\n                use std::env;\n                fn main() {\n                    let mut args = env::args().skip(1).collect::<Vec<_>>();\n\n                    let is_sysroot_crate = env::var_os(\"RUSTC_BOOTSTRAP\").is_some();\n                    if is_sysroot_crate {\n                        args.push(\"--sysroot\".to_string());\n                        args.push(env::var(\"REAL_SYSROOT\").unwrap());\n                    } else if let Some(pos) = args.iter().position(|arg| arg == \"--target\") {\n                        // build-std target unit\n\n                        // Set --sysroot only when the target is host\n                        if args.iter().nth(pos + 1) == Some(&\"__HOST_TARGET__\".to_string()) {\n                            // This `--sysroot` is here to disable the sysroot lookup,\n                            // to ensure nothing is required.\n                            // See https://github.com/rust-lang/wg-cargo-std-aware/issues/31\n                            // for more information on this.\n                            args.push(\"--sysroot\".to_string());\n                            args.push(\"/path/to/nowhere\".to_string());\n                        }\n                    } else {\n                        // host unit, do not use sysroot\n                    }\n\n                    let ret = Command::new(&args[0]).args(&args[1..]).status().unwrap();\n                    std::process::exit(ret.code().unwrap_or(1));\n                }\n            \"#\n            .replace(\"__HOST_TARGET__\", rustc_host()),\n        )\n        .build();\n    p.cargo(\"build\").run();\n\n    Setup {\n        rustc_wrapper: p.bin(\"foo\"),\n        real_sysroot: paths::sysroot(),\n    }\n}\n\nfn enable_build_std(e: &mut Execs, setup: &Setup) {\n    // First up, force Cargo to use our \"mock sysroot\" which mimics what\n    // libstd looks like upstream.\n    let root = Path::new(env!(\"CARGO_MANIFEST_DIR\")).join(\"tests/testsuite/mock-std/library\");\n    e.env(\"__CARGO_TESTS_ONLY_SRC_ROOT\", &root);\n\n    e.masquerade_as_nightly_cargo(&[\"build-std\"]);\n\n    // We do various shenanigans to ensure our \"mock sysroot\" actually links\n    // with the real sysroot, so we don't have to actually recompile std for\n    // each test. Perform all that logic here, namely:\n    //\n    // * RUSTC_WRAPPER - uses our shim executable built above to control rustc\n    // * REAL_SYSROOT - used by the shim executable to swap out to the real\n    //   sysroot temporarily for some compilations\n    // * RUST{,DOC}FLAGS - an extra `-L` argument to ensure we can always load\n    //   crates from the sysroot, but only indirectly through other crates.\n    e.env(\"RUSTC_WRAPPER\", &setup.rustc_wrapper);\n    e.env(\"REAL_SYSROOT\", &setup.real_sysroot);\n    let libdir = format!(\"/lib/rustlib/{}/lib\", rustc_host());\n    e.env(\n        \"RUSTFLAGS\",\n        format!(\"-Ldependency={}{}\", setup.real_sysroot, libdir),\n    );\n    e.env(\n        \"RUSTDOCFLAGS\",\n        format!(\"-Ldependency={}{}\", setup.real_sysroot, libdir),\n    );\n}\n\n// Helper methods used in the tests below\ntrait BuildStd: Sized {\n    fn build_std(&mut self, setup: &Setup) -> &mut Self;\n    fn build_std_arg(&mut self, setup: &Setup, arg: &str) -> &mut Self;\n    fn target_host(&mut self) -> &mut Self;\n}\n\nimpl BuildStd for Execs {\n    fn build_std(&mut self, setup: &Setup) -> &mut Self {\n        enable_build_std(self, setup);\n        self.arg(\"-Zbuild-std\");\n        self\n    }\n\n    fn build_std_arg(&mut self, setup: &Setup, arg: &str) -> &mut Self {\n        enable_build_std(self, setup);\n        self.arg(format!(\"-Zbuild-std={}\", arg));\n        self\n    }\n\n    fn target_host(&mut self) -> &mut Self {\n        self.arg(\"--target\").arg(rustc_host());\n        self\n    }\n}\n\n#[cargo_test(build_std_mock)]\nfn basic() {\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            \"\n                fn main() {\n                    std::custom_api();\n                    foo::f();\n                }\n\n                #[test]\n                fn smoke_bin_unit() {\n                    std::custom_api();\n                    foo::f();\n                }\n            \",\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n                extern crate alloc;\n                extern crate proc_macro;\n\n                /// ```\n                /// foo::f();\n                /// ```\n                pub fn f() {\n                    core::custom_api();\n                    std::custom_api();\n                    alloc::custom_api();\n                    proc_macro::custom_api();\n                }\n\n                #[test]\n                fn smoke_lib_unit() {\n                    std::custom_api();\n                    f();\n                }\n            \",\n        )\n        .file(\n            \"tests/smoke.rs\",\n            \"\n                #[test]\n                fn smoke_integration() {\n                    std::custom_api();\n                    foo::f();\n                }\n            \",\n        )\n        .build();\n\n    p.cargo(\"check -v\").build_std(&setup).target_host().run();\n    p.cargo(\"build\").build_std(&setup).target_host().run();\n    p.cargo(\"run\").build_std(&setup).target_host().run();\n    p.cargo(\"test\").build_std(&setup).target_host().run();\n}\n\n#[cargo_test(build_std_mock)]\nfn shared_std_dependency_rebuild() {\n    let manifest_dir = std::env::var(\"CARGO_MANIFEST_DIR\").unwrap();\n    let setup = setup();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            format!(\n                \"\n                [package]\n                name = \\\"foo\\\"\n                version = \\\"0.1.0\\\"\n                edition = \\\"2021\\\"\n\n                [build-dependencies]\n                dep_test = {{ path = \\\"{}/tests/testsuite/mock-std/dep_test\\\" }}\n            \",\n                manifest_dir.replace('\\\\', \"/\")\n            )\n            .as_str(),\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                println!(\"Hello, World!\");\n            }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                println!(\"cargo::rerun-if-changed=build.rs\");\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .build_std(&setup)\n        .target_host()\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `[..] rustc --crate-name dep_test [..]`\n...\n[RUNNING] `[..] rustc --crate-name dep_test [..]`\n...\n\"#]])\n        .run();\n\n    p.cargo(\"build -v\")\n        .build_std(&setup)\n        .with_stderr_does_not_contain(str![[r#\"\n    ...\n    [RUNNING] `[..] rustc --crate-name dep_test [..]`\n    ...\n    [RUNNING] `[..] rustc --crate-name dep_test [..]`\n    ...\n    \"#]])\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn simple_lib_std() {\n    let setup = setup();\n\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.cargo(\"build -v\")\n        .build_std(&setup)\n        .target_host()\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `[..] rustc --crate-name std [..]`\n...\n\"#]])\n        .run();\n    // Check freshness.\n    p.change_file(\"src/lib.rs\", \" \");\n    p.cargo(\"build -v\")\n        .build_std(&setup)\n        .target_host()\n        .with_stderr_data(str![[r#\"\n...\n[FRESH] std v0.1.0 ([..]/tests/testsuite/mock-std/library/std)\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn simple_bin_std() {\n    let setup = setup();\n\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"run -v\").build_std(&setup).target_host().run();\n}\n\n#[cargo_test(build_std_mock)]\nfn lib_nostd() {\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![no_std]\n                pub fn foo() {\n                    assert_eq!(u8::MIN, 0);\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"build -v --lib\")\n        .build_std_arg(&setup, \"core\")\n        .target_host()\n        .with_stderr_does_not_contain(\"[..]libstd[..]\")\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn check_core() {\n    let setup = setup();\n\n    let p = project()\n        .file(\"src/lib.rs\", \"#![no_std] fn unused_fn() {}\")\n        .build();\n\n    p.cargo(\"check -v\")\n        .build_std_arg(&setup, \"core\")\n        .target_host()\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] function `unused_fn` is never used\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn build_std_with_no_arg_for_core_only_target() {\n    let target = \"aarch64-unknown-none\";\n    if !cross_compile::requires_target_installed(target) {\n        return;\n    }\n\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![no_std]\n                pub fn foo() {\n                    assert_eq!(u8::MIN, 0);\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .arg(\"--target\")\n        .arg(target)\n        .build_std(&setup)\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNLOADING] crates ...\n[DOWNLOADED] registry-dep-using-std v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] registry-dep-using-core v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] registry-dep-using-alloc v1.0.0 (registry `dummy-registry`)\n[COMPILING] compiler_builtins v0.1.0 ([..]/library/compiler_builtins)\n[COMPILING] core v0.1.0 ([..]/library/core)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..] rustc --crate-name build_script_build [..]/compiler_builtins/build.rs [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/compiler_builtins-[HASH]/build-script-build`\n[RUNNING] `[..] rustc --crate-name compiler_builtins [..]--target aarch64-unknown-none[..]`\n[RUNNING] `[..] rustc --crate-name core [..]--target aarch64-unknown-none[..]`\n[RUNNING] `[..] rustc --crate-name foo [..]--target aarch64-unknown-none[..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"clean\").run();\n\n    // Also work for a mix of std and core-only targets,\n    // though not sure how common it is...\n    //\n    // Note that we don't  download std dependencies for the second call\n    // because `-Zbuild-std` downloads them all also when building for core only.\n    p.cargo(\"build -v\")\n        .arg(\"--target\")\n        .arg(target)\n        .target_host()\n        .build_std(&setup)\n        .with_stderr_data(\n            str![[r#\"\n[UPDATING] `dummy-registry` index\n[COMPILING] core v0.1.0 ([..]/library/core)\n[COMPILING] dep_test v0.1.0 ([..]/dep_test)\n[COMPILING] compiler_builtins v0.1.0 ([..]/library/compiler_builtins)\n[COMPILING] proc_macro v0.1.0 ([..]/library/proc_macro)\n[COMPILING] panic_unwind v0.1.0 ([..]/library/panic_unwind)\n[COMPILING] rustc-std-workspace-core v1.9.0 ([..]/library/rustc-std-workspace-core)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] registry-dep-using-core v1.0.0\n[COMPILING] alloc v0.1.0 ([..]/library/alloc)\n[COMPILING] rustc-std-workspace-alloc v1.9.0 ([..]/library/rustc-std-workspace-alloc)\n[COMPILING] registry-dep-using-alloc v1.0.0\n[COMPILING] std v0.1.0 ([..]/library/std)\n[RUNNING] `[..] rustc --crate-name build_script_build [..]/compiler_builtins/build.rs [..]`\n[RUNNING] `[ROOT]/foo/target/debug/build/compiler_builtins-[HASH]/build-script-build`\n[RUNNING] `[ROOT]/foo/target/debug/build/compiler_builtins-[HASH]/build-script-build`\n[RUNNING] `[..]rustc --crate-name compiler_builtins [..]--target aarch64-unknown-none[..]`\n[RUNNING] `[..]rustc --crate-name core [..]--target aarch64-unknown-none[..]`\n[RUNNING] `[..]rustc --crate-name foo [..]--target aarch64-unknown-none[..]`\n[RUNNING] `[..]rustc --crate-name core [..]--target [HOST_TARGET][..]`\n[RUNNING] `[..]rustc --crate-name dep_test [..]--target [HOST_TARGET][..]`\n[RUNNING] `[..]rustc --crate-name proc_macro [..]--target [HOST_TARGET][..]`\n[RUNNING] `[..]rustc --crate-name panic_unwind [..]--target [HOST_TARGET][..]`\n[RUNNING] `[..]rustc --crate-name compiler_builtins [..]--target [HOST_TARGET][..]`\n[RUNNING] `[..]rustc --crate-name rustc_std_workspace_core [..]--target [HOST_TARGET][..]`\n[RUNNING] `[..]rustc --crate-name registry_dep_using_core [..]--target [HOST_TARGET][..]`\n[RUNNING] `[..]rustc --crate-name alloc [..]--target [HOST_TARGET][..]`\n[RUNNING] `[..]rustc --crate-name rustc_std_workspace_alloc [..]--target [HOST_TARGET][..]`\n[RUNNING] `[..]rustc --crate-name registry_dep_using_alloc [..]--target [HOST_TARGET][..]`\n[RUNNING] `[..]rustc --crate-name std [..]--target [HOST_TARGET][..]`\n[RUNNING] `[..]rustc --crate-name foo [..]--target [HOST_TARGET][..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn depend_same_as_std() {\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn f() {\n                    registry_dep_using_core::non_sysroot_api();\n                    registry_dep_using_alloc::non_sysroot_api();\n                    registry_dep_using_std::non_sysroot_api();\n                }\n            \"#,\n        )\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [dependencies]\n                registry-dep-using-core = \"1.0\"\n                registry-dep-using-alloc = \"1.0\"\n                registry-dep-using-std = \"1.0\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\").build_std(&setup).target_host().run();\n}\n\n#[cargo_test(build_std_mock)]\nfn test() {\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(test)]\n                mod tests {\n                    #[test]\n                    fn it_works() {\n                        assert_eq!(2 + 2, 4);\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test -v\")\n        .build_std(&setup)\n        .target_host()\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest tests::it_works ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn target_proc_macro() {\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate proc_macro;\n                pub fn f() {\n                    let _ts = proc_macro::TokenStream::new();\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\").build_std(&setup).target_host().run();\n}\n\n#[cargo_test(build_std_mock)]\nfn bench() {\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![feature(test)]\n                extern crate test;\n\n                #[bench]\n                fn b1(b: &mut test::Bencher) {\n                    b.iter(|| ())\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"bench -v\").build_std(&setup).target_host().run();\n}\n\n#[cargo_test(build_std_mock)]\nfn doc() {\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// Doc\n                pub fn f() -> Result<(), ()> {Ok(())}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"doc -v\").build_std(&setup).target_host().run();\n}\n\n#[cargo_test(build_std_mock)]\nfn check_std() {\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n                extern crate core;\n                extern crate alloc;\n                extern crate proc_macro;\n                pub fn f() {}\n            \",\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"tests/t1.rs\",\n            r#\"\n                #[test]\n                fn t1() {\n                    assert_eq!(1, 2);\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check -v --all-targets\")\n        .build_std(&setup)\n        .target_host()\n        .run();\n    p.cargo(\"check -v --all-targets --profile=test\")\n        .build_std(&setup)\n        .target_host()\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn doctest() {\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// Doc\n                /// ```\n                /// std::custom_api();\n                /// ```\n                pub fn f() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test --doc -v\")\n        .build_std(&setup)\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest src/lib.rs - f (line 3) ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .target_host()\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn no_implicit_alloc() {\n    // Demonstrate that alloc is not implicitly in scope.\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn f() {\n                    let _: Vec<i32> = alloc::vec::Vec::new();\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\")\n        .build_std(&setup)\n        .target_host()\n        .with_stderr_data(str![[r#\"\n...\nerror[E0433]: cannot find module or crate `alloc` in this scope\n...\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn macro_expanded_shadow() {\n    // This tests a bug caused by the previous use of `--extern` to directly\n    // load sysroot crates. This necessitated the switch to `--sysroot` to\n    // retain existing behavior. See\n    // https://github.com/rust-lang/wg-cargo-std-aware/issues/40 for more\n    // detail.\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                macro_rules! a {\n                    () => (extern crate std as alloc;)\n                }\n                a!();\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build -v\").build_std(&setup).target_host().run();\n}\n\n#[cargo_test(build_std_mock)]\nfn ignores_incremental() {\n    // Incremental is not really needed for std, make sure it is disabled.\n    // Incremental also tends to have bugs that affect std libraries more than\n    // any other crate.\n    let setup = setup();\n\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.cargo(\"build\")\n        .env(\"CARGO_INCREMENTAL\", \"1\")\n        .build_std(&setup)\n        .target_host()\n        .run();\n    let incremental: Vec<_> = p\n        .glob(format!(\"target/{}/debug/incremental/*\", rustc_host()))\n        .map(|e| e.unwrap())\n        .collect();\n    assert_eq!(incremental.len(), 1);\n    assert!(\n        incremental[0]\n            .file_name()\n            .unwrap()\n            .to_str()\n            .unwrap()\n            .starts_with(\"foo-\")\n    );\n}\n\n#[cargo_test(build_std_mock)]\nfn cargo_config_injects_compiler_builtins() {\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #![no_std]\n                pub fn foo() {\n                    assert_eq!(u8::MIN, 0);\n                }\n            \"#,\n        )\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [unstable]\n                build-std = ['core']\n            \"#,\n        )\n        .build();\n    let mut build = p.cargo(\"build -v --lib\");\n    enable_build_std(&mut build, &setup);\n    build\n        .target_host()\n        .with_stderr_does_not_contain(\"[..]libstd[..]\")\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn different_features() {\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n                pub fn foo() {\n                    std::conditional_function();\n                }\n            \",\n        )\n        .build();\n    p.cargo(\"build\")\n        .build_std(&setup)\n        .arg(\"-Zbuild-std-features=feature1\")\n        .target_host()\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn no_roots() {\n    // Checks for a bug where it would panic if there are no roots.\n    let setup = setup();\n\n    let p = project().file(\"tests/t1.rs\", \"\").build();\n    p.cargo(\"build\")\n        .build_std(&setup)\n        .target_host()\n        .with_stderr_data(str![[r#\"\n...\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn proc_macro_only() {\n    // Checks for a bug where it would panic if building a proc-macro only\n    let setup = setup();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pm\"\n                version = \"0.1.0\"\n\n                [lib]\n                proc-macro = true\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"build\")\n        .build_std(&setup)\n        .target_host()\n        .with_stderr_data(str![[r#\"\n...\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn fetch() {\n    let setup = setup();\n\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"fetch\")\n        .build_std(&setup)\n        .target_host()\n        .with_stderr_contains(\"[DOWNLOADED] [..]\")\n        .run();\n    p.cargo(\"build\")\n        .build_std(&setup)\n        .target_host()\n        .with_stderr_does_not_contain(\"[DOWNLOADED] [..]\")\n        .run();\n}\n\n#[cargo_test(build_std_mock)]\nfn std_build_script_metadata_propagate_to_user() {\n    let setup = setup();\n\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"build.rs\",\n            r#\"\n            fn main() {\n                assert_eq!(std::env::var(\"DEP_COMPILER_RT_COMPILER_RT\").unwrap(), \"foo\");\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\").build_std(&setup).target_host().run();\n}\n"
  },
  {
    "path": "tests/testsuite/test.rs",
    "content": "//! Tests for the `cargo test` command.\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse crate::utils::cargo_exe;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{basic_bin_manifest, basic_lib_manifest, basic_manifest, project, str};\nuse cargo_test_support::{cross_compile, paths};\nuse cargo_test_support::{rustc_host, rustc_host_env, sleep_ms};\nuse cargo_util::paths::dylib_path_envvar;\n\nuse crate::utils::cross_compile::can_run_on_host as cross_compile_can_run_on_host;\n\n#[cargo_test]\nfn cargo_test_simple() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn hello() -> &'static str {\n                \"hello\"\n            }\n\n            pub fn main() {\n                println!(\"{}\", hello())\n            }\n\n            #[test]\n            fn test_hello() {\n                assert_eq!(hello(), \"hello\")\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest test_hello ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_test_release() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                authors = []\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate bar;\n                pub fn foo() { bar::bar(); }\n\n                #[test]\n                fn test() { foo(); }\n            \"#,\n        )\n        .file(\n            \"tests/test.rs\",\n            r#\"\n                extern crate foo;\n\n                #[test]\n                fn test() { foo::foo(); }\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"test -v --release\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[RUNNING] `rustc [..]-C opt-level=3 [..]`\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]-C opt-level=3 [..]`\n[RUNNING] `rustc [..]-C opt-level=3 [..]`\n[RUNNING] `rustc [..]-C opt-level=3 [..]`\n[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]`\n[RUNNING] `[ROOT]/foo/target/release/deps/test-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `rustdoc [..]--test src/lib.rs[..]`\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest test ... ok\ntest test ... ok\nrunning 0 tests\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_test_overflow_checks() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.5.0\"\n            edition = \"2015\"\n            authors = []\n\n            [[bin]]\n            name = \"foo\"\n\n            [profile.release]\n            overflow-checks = true\n            \"#,\n        )\n        .file(\n            \"src/foo.rs\",\n            r#\"\n            use std::panic;\n            pub fn main() {\n                let r = panic::catch_unwind(|| {\n                    [1, i32::MAX].iter().sum::<i32>();\n                });\n                assert!(r.is_err());\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build --release\").run();\n    assert!(p.release_bin(\"foo\").is_file());\n\n    p.process(&p.release_bin(\"foo\")).with_stdout_data(\"\").run();\n}\n\n#[cargo_test]\nfn cargo_test_quiet_with_harness() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [[test]]\n                name = \"foo\"\n                path = \"src/foo.rs\"\n                harness = true\n            \"#,\n        )\n        .file(\n            \"src/foo.rs\",\n            r#\"\n                fn main() {}\n                #[test] fn test_hello() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test -q\")\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\n.\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn cargo_test_quiet_no_harness() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"foo\"\n                test = false\n\n                [[test]]\n                name = \"foo\"\n                path = \"src/main.rs\"\n                harness = false\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {}\n                #[test] fn test_hello() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test -q\")\n        .with_stdout_data(\"\")\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn cargo_doc_test_quiet() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// let result = foo::add(2, 3);\n                /// assert_eq!(result, 5);\n                /// ```\n                pub fn add(a: i32, b: i32) -> i32 {\n                    a + b\n                }\n\n                /// ```\n                /// let result = foo::div(10, 2);\n                /// assert_eq!(result, 5);\n                /// ```\n                ///\n                /// # Panics\n                ///\n                /// The function panics if the second argument is zero.\n                ///\n                /// ```rust,should_panic\n                /// // panics on division by zero\n                /// foo::div(10, 0);\n                /// ```\n                pub fn div(a: i32, b: i32) -> i32 {\n                    if b == 0 {\n                        panic!(\"Divide-by-zero error\");\n                    }\n\n                    a / b\n                }\n\n                #[test] fn test_hello() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test -q\")\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\n.\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 3 tests\n...\ntest result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .with_stderr_data(\"\")\n        .run();\n}\n\n#[cargo_test]\nfn cargo_test_verbose() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {}\n                #[test] fn test_hello() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test -v hello\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] src/main.rs [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE] hello`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest test_hello ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn many_similar_names() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n            pub fn foo() {}\n            #[test] fn lib_test() {}\n        \",\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n            extern crate foo;\n            fn main() {}\n            #[test] fn bin_test() { foo::foo() }\n        \",\n        )\n        .file(\n            \"tests/foo.rs\",\n            r#\"\n                extern crate foo;\n                #[test] fn test_test() { foo::foo() }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test -v\")\n        .with_stdout_data(\n            str![[r#\"\ntest bin_test ... ok\ntest lib_test ... ok\ntest test_test ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn cargo_test_failing_test_in_bin() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn hello() -> &'static str {\n                \"hello\"\n            }\n\n            pub fn main() {\n                println!(\"{}\", hello())\n            }\n\n            #[test]\n            fn test_hello() {\n                assert_eq!(hello(), \"nope\", \"NOPE!\")\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE])\n[ERROR] test failed, to rerun pass `--bin foo`\n\n\"#]])\n        .with_stdout_data(\"...\\n[..]NOPE![..]\\n...\")\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn cargo_test_failing_test_in_test() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/main.rs\", r#\"pub fn main() { println!(\"hello\"); }\"#)\n        .file(\n            \"tests/footest.rs\",\n            r#\"#[test] fn test_hello() { assert!(false, \"FALSE!\") }\"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n\n    p.process(&p.bin(\"foo\"))\n        .with_stdout_data(str![[r#\"\nhello\n\n\"#]])\n        .run();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE])\n[RUNNING] tests/footest.rs (target/debug/deps/footest-[HASH][EXE])\n[ERROR] test failed, to rerun pass `--test footest`\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\n...\nrunning 0 tests\n...\nrunning 1 test\ntest test_hello ... FAILED\n...\n[..]FALSE![..]\n...\n\n\"#]]\n            .unordered(),\n        )\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn cargo_test_failing_test_in_lib() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"#[test] fn test_hello() { assert!(false, \"FALSE!\") }\"#,\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[ERROR] test failed, to rerun pass `--lib`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest test_hello ... FAILED\n...\n[..]FALSE![..]\n...\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn test_with_lib_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"baz\"\n                path = \"src/main.rs\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                ///\n                /// ```rust\n                /// extern crate foo;\n                /// fn main() {\n                ///     println!(\"{:?}\", foo::foo());\n                /// }\n                /// ```\n                ///\n                pub fn foo(){}\n                #[test] fn lib_test() {}\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n            #[allow(unused_extern_crates)]\n            extern crate foo;\n\n            fn main() {}\n\n            #[test]\n            fn bin_test() {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[RUNNING] unittests src/main.rs (target/debug/deps/baz-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest lib_test ... ok\ntest bin_test ... ok\ntest [..] ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn test_with_deep_lib_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.bar]\n                path = \"../bar\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"\n            #[cfg(test)]\n            extern crate bar;\n            /// ```\n            /// foo::foo();\n            /// ```\n            pub fn foo() {}\n\n            #[test]\n            fn bar_test() {\n                bar::bar();\n            }\n        \",\n        )\n        .build();\n    let _p2 = project()\n        .at(\"bar\")\n        .file(\"Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"src/lib.rs\", \"pub fn bar() {} #[test] fn foo_test() {}\")\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest bar_test ... ok\ntest [..] ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn external_test_explicit() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[test]]\n                name = \"test\"\n                path = \"src/test.rs\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn get_hello() -> &'static str { \"Hello\" }\n\n                #[test]\n                fn internal_test() {}\n            \"#,\n        )\n        .file(\n            \"src/test.rs\",\n            r#\"\n                extern crate foo;\n\n                #[test]\n                fn external_test() { assert_eq!(foo::get_hello(), \"Hello\") }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[RUNNING] src/test.rs (target/debug/deps/test-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest internal_test ... ok\ntest external_test ... ok\nrunning 0 tests\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn external_test_named_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[test]]\n                name = \"test\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"tests/test.rs\", \"#[test] fn foo() {}\")\n        .build();\n\n    p.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn external_test_implicit() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn get_hello() -> &'static str { \"Hello\" }\n\n                #[test]\n                fn internal_test() {}\n            \"#,\n        )\n        .file(\n            \"tests/external.rs\",\n            r#\"\n                extern crate foo;\n\n                #[test]\n                fn external_test() { assert_eq!(foo::get_hello(), \"Hello\") }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[RUNNING] tests/external.rs (target/debug/deps/external-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest internal_test ... ok\ntest external_test ... ok\nrunning 0 tests\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn dont_run_examples() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"examples/dont-run-me-i-will-fail.rs\",\n            r#\"\n                fn main() { panic!(\"Examples should not be run by 'cargo test'\"); }\n            \"#,\n        )\n        .build();\n    p.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn pass_through_escaped() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n            /// ```rust\n            /// assert!(foo::foo());\n            /// ```\n            pub fn foo() -> bool {\n                true\n            }\n\n            /// ```rust\n            /// assert!(!foo::bar());\n            /// ```\n            pub fn bar() -> bool {\n                false\n            }\n\n            #[test] fn test_foo() {\n                assert!(foo());\n            }\n            #[test] fn test_bar() {\n                assert!(!bar());\n            }\n        \",\n        )\n        .build();\n\n    p.cargo(\"test -- bar\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\nrunning 1 test\ntest test_bar ... ok\n...\n\"#]])\n        .run();\n\n    p.cargo(\"test -- foo\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\nrunning 1 test\ntest test_foo ... ok\n...\n\"#]])\n        .run();\n\n    p.cargo(\"test -- foo bar\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\nrunning 2 tests\ntest test_foo ... ok\ntest test_bar ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n// Unlike `pass_through_escaped`, doctests won't run when using `testname` as an optimization\n#[cargo_test]\nfn pass_through_testname() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\n            /// ```rust\n            /// assert!(foo::foo());\n            /// ```\n            pub fn foo() -> bool {\n                true\n            }\n\n            /// ```rust\n            /// assert!(!foo::bar());\n            /// ```\n            pub fn bar() -> bool {\n                false\n            }\n\n            #[test] fn test_foo() {\n                assert!(foo());\n            }\n            #[test] fn test_bar() {\n                assert!(!bar());\n            }\n        \",\n        )\n        .build();\n\n    p.cargo(\"test bar\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\nrunning 1 test\ntest test_bar ... ok\n...\n\"#]])\n        .run();\n\n    p.cargo(\"test foo\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\nrunning 1 test\ntest test_foo ... ok\n...\n\"#]])\n        .run();\n\n    p.cargo(\"test foo -- bar\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\nrunning 2 tests\ntest test_bar ... ok\ntest test_foo ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n// Regression test for running cargo-test twice with\n// tests in an rlib\n#[cargo_test]\nfn cargo_test_twice() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\n            \"src/foo.rs\",\n            r#\"\n            #![crate_type = \"rlib\"]\n\n            #[test]\n            fn dummy_test() { }\n            \"#,\n        )\n        .build();\n\n    for _ in 0..2 {\n        p.cargo(\"test\").run();\n    }\n}\n\n#[cargo_test]\nfn lib_bin_same_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo\"\n                [[bin]]\n                name = \"foo\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"#[test] fn lib_test() {}\")\n        .file(\n            \"src/main.rs\",\n            \"\n            #[allow(unused_extern_crates)]\n            extern crate foo;\n\n            #[test]\n            fn bin_test() {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest lib_test ... ok\ntest bin_test ... ok\nrunning 0 tests\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn lib_with_standard_name() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"syntax\", \"0.0.1\"))\n        .file(\n            \"src/lib.rs\",\n            \"\n            /// ```\n            /// syntax::foo();\n            /// ```\n            pub fn foo() {}\n\n            #[test]\n            fn foo_test() {}\n        \",\n        )\n        .file(\n            \"tests/test.rs\",\n            \"\n            extern crate syntax;\n\n            #[test]\n            fn test() { syntax::foo() }\n        \",\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] syntax v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/syntax-[HASH][EXE])\n[RUNNING] tests/test.rs (target/debug/deps/test-[HASH][EXE])\n[DOCTEST] syntax\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest foo_test ... ok\ntest test ... ok\ntest [..] ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn lib_with_standard_name2() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"syntax\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"syntax\"\n                test = false\n                doctest = false\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"src/main.rs\",\n            \"\n            extern crate syntax;\n\n            fn main() {}\n\n            #[test]\n            fn test() { syntax::foo() }\n        \",\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] syntax v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/debug/deps/syntax-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest test ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn lib_without_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"syntax\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                test = false\n                doctest = false\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"src/main.rs\",\n            \"\n            extern crate syntax;\n\n            fn main() {}\n\n            #[test]\n            fn test() { syntax::foo() }\n        \",\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] syntax v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/main.rs (target/debug/deps/syntax-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest test ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bin_without_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"syntax\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                test = false\n                doctest = false\n\n                [[bin]]\n                path = \"src/main.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"src/main.rs\",\n            \"\n            extern crate syntax;\n\n            fn main() {}\n\n            #[test]\n            fn test() { syntax::foo() }\n        \",\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  binary target bin.name is required\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bench_without_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"syntax\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                test = false\n                doctest = false\n\n                [[bench]]\n                path = \"src/bench.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"src/main.rs\",\n            \"\n            extern crate syntax;\n\n            fn main() {}\n\n            #[test]\n            fn test() { syntax::foo() }\n        \",\n        )\n        .file(\n            \"src/bench.rs\",\n            \"\n            #![feature(test)]\n            extern crate syntax;\n            extern crate test;\n\n            #[bench]\n            fn external_bench(_b: &mut test::Bencher) {}\n        \",\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  benchmark target bench.name is required\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_without_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"syntax\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                test = false\n                doctest = false\n\n                [[test]]\n                path = \"src/test.rs\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() {}\n                pub fn get_hello() -> &'static str { \"Hello\" }\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            \"\n            extern crate syntax;\n\n            fn main() {}\n\n            #[test]\n            fn test() { syntax::foo() }\n        \",\n        )\n        .file(\n            \"src/test.rs\",\n            r#\"\n                extern crate syntax;\n\n                #[test]\n                fn external_test() { assert_eq!(syntax::get_hello(), \"Hello\") }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  test target test.name is required\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn example_without_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"syntax\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                test = false\n                doctest = false\n\n                [[example]]\n                path = \"examples/example.rs\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() {}\")\n        .file(\n            \"src/main.rs\",\n            \"\n            extern crate syntax;\n\n            fn main() {}\n\n            #[test]\n            fn test() { syntax::foo() }\n        \",\n        )\n        .file(\n            \"examples/example.rs\",\n            r#\"\n                extern crate syntax;\n\n                fn main() {\n                    println!(\"example1\");\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  example target example.name is required\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bin_there_for_integration() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            \"\n            fn main() { std::process::exit(101); }\n            #[test] fn main_test() {}\n        \",\n        )\n        .file(\n            \"tests/foo.rs\",\n            r#\"\n                use std::process::Command;\n                #[test]\n                fn test_test() {\n                    let status = Command::new(\"target/debug/foo\").status().unwrap();\n                    assert_eq!(status.code(), Some(101));\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test -v\")\n        .with_stdout_data(\n            str![[r#\"\ntest main_test ... ok\ntest test_test ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn test_dylib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo\"\n                crate-type = [\"dylib\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate bar as the_bar;\n\n                pub fn bar() { the_bar::baz(); }\n\n                #[test]\n                fn foo() { bar(); }\n            \"#,\n        )\n        .file(\n            \"tests/test.rs\",\n            r#\"\n                extern crate foo as the_foo;\n\n                #[test]\n                fn foo() { the_foo::bar(); }\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"bar\"\n                crate-type = [\"dylib\"]\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[RUNNING] tests/test.rs (target/debug/deps/test-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest foo ... ok\ntest foo ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.root().move_into_the_past();\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[RUNNING] tests/test.rs (target/debug/deps/test-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest foo ... ok\ntest foo ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn test_twice_with_build_cmd() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"#[test] fn foo() {}\")\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest foo ... ok\nrunning 0 tests\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest foo ... ok\nrunning 0 tests\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn test_then_build() {\n    let p = project().file(\"src/lib.rs\", \"#[test] fn foo() {}\").build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest foo ... ok\nrunning 0 tests\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_no_run() {\n    let p = project()\n        .file(\"src/lib.rs\", \"#[test] fn foo() { panic!() }\")\n        .build();\n\n    p.cargo(\"test --no-run\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_no_run_emit_json() {\n    let p = project()\n        .file(\"src/lib.rs\", \"#[test] fn foo() { panic!() }\")\n        .build();\n\n    p.cargo(\"test --no-run --message-format json\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_run_specific_bin_target() {\n    let prj = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name=\"bin1\"\n                path=\"src/bin1.rs\"\n\n                [[bin]]\n                name=\"bin2\"\n                path=\"src/bin2.rs\"\n            \"#,\n        )\n        .file(\"src/bin1.rs\", \"#[test] fn test1() { }\")\n        .file(\"src/bin2.rs\", \"#[test] fn test2() { }\")\n        .build();\n\n    prj.cargo(\"test --bin bin2\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/bin2.rs (target/debug/deps/bin2-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest test2 ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_run_implicit_bin_target() {\n    let prj = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name=\"mybin\"\n                path=\"src/mybin.rs\"\n            \"#,\n        )\n        .file(\n            \"src/mybin.rs\",\n            \"#[test] fn test_in_bin() { }\n               fn main() { panic!(\\\"Don't execute me!\\\"); }\",\n        )\n        .file(\"tests/mytest.rs\", \"#[test] fn test_in_test() { }\")\n        .file(\"benches/mybench.rs\", \"#[test] fn test_in_bench() { }\")\n        .file(\n            \"examples/myexm.rs\",\n            \"#[test] fn test_in_exm() { }\n               fn main() { panic!(\\\"Don't execute me!\\\"); }\",\n        )\n        .build();\n\n    prj.cargo(\"test --bins\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/mybin.rs (target/debug/deps/mybin-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest test_in_bin ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_run_specific_test_target() {\n    let prj = project()\n        .file(\"src/bin/a.rs\", \"fn main() { }\")\n        .file(\"src/bin/b.rs\", \"#[test] fn test_b() { } fn main() { }\")\n        .file(\"tests/a.rs\", \"#[test] fn test_a() { }\")\n        .file(\"tests/b.rs\", \"#[test] fn test_b() { }\")\n        .build();\n\n    prj.cargo(\"test --test b\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/b.rs (target/debug/deps/b-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest test_b ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_run_implicit_test_target() {\n    let prj = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name=\"mybin\"\n                path=\"src/mybin.rs\"\n            \"#,\n        )\n        .file(\n            \"src/mybin.rs\",\n            \"#[test] fn test_in_bin() { }\n               fn main() { panic!(\\\"Don't execute me!\\\"); }\",\n        )\n        .file(\"tests/mytest.rs\", \"#[test] fn test_in_test() { }\")\n        .file(\"benches/mybench.rs\", \"#[test] fn test_in_bench() { }\")\n        .file(\n            \"examples/myexm.rs\",\n            \"fn main() { compile_error!(\\\"Don't build me!\\\"); }\",\n        )\n        .build();\n\n    prj.cargo(\"test --tests\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/mybin.rs (target/debug/deps/mybin-[HASH][EXE])\n[RUNNING] tests/mytest.rs (target/debug/deps/mytest-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest test_in_test ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_run_implicit_bench_target() {\n    let prj = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name=\"mybin\"\n                path=\"src/mybin.rs\"\n            \"#,\n        )\n        .file(\n            \"src/mybin.rs\",\n            \"#[test] fn test_in_bin() { }\n               fn main() { panic!(\\\"Don't execute me!\\\"); }\",\n        )\n        .file(\"tests/mytest.rs\", \"#[test] fn test_in_test() { }\")\n        .file(\"benches/mybench.rs\", \"#[test] fn test_in_bench() { }\")\n        .file(\n            \"examples/myexm.rs\",\n            \"fn main() { compile_error!(\\\"Don't build me!\\\"); }\",\n        )\n        .build();\n\n    prj.cargo(\"test --benches\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/mybin.rs (target/debug/deps/mybin-[HASH][EXE])\n[RUNNING] benches/mybench.rs (target/debug/deps/mybench-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest test_in_bench ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_run_implicit_example_target() {\n    let prj = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"mybin\"\n                path = \"src/mybin.rs\"\n\n                [[example]]\n                name = \"myexm1\"\n\n                [[example]]\n                name = \"myexm2\"\n                test = true\n\n                [profile.test]\n                panic = \"abort\" # this should be ignored by default Cargo targets set.\n            \"#,\n        )\n        .file(\n            \"src/mybin.rs\",\n            \"#[test] fn test_in_bin() { }\n               fn main() { panic!(\\\"Don't execute me!\\\"); }\",\n        )\n        .file(\"tests/mytest.rs\", \"#[test] fn test_in_test() { }\")\n        .file(\"benches/mybench.rs\", \"#[test] fn test_in_bench() { }\")\n        .file(\n            \"examples/myexm1.rs\",\n            \"#[test] fn test_in_exm() { }\n               fn main() { panic!(\\\"Don't execute me!\\\"); }\",\n        )\n        .file(\n            \"examples/myexm2.rs\",\n            \"#[test] fn test_in_exm() { }\n               fn main() { panic!(\\\"Don't execute me!\\\"); }\",\n        )\n        .build();\n\n    // Compiles myexm1 as normal binary (without --test), but does not run it.\n    prj.cargo(\"test -v\")\n        .with_stderr_contains(\"[RUNNING] `rustc [..]myexm1.rs [..]--crate-type bin[..]\")\n        .with_stderr_contains(\"[RUNNING] `rustc [..]myexm2.rs [..]--test[..]\")\n        .with_stderr_does_not_contain(\"[RUNNING] [..]myexm1-[..]\")\n        // profile.test panic settings shouldn't be applied even to myexm1\n        .with_stderr_line_without(&[\"[RUNNING] `rustc --crate-name myexm1\"], &[\"panic=abort\"])\n        .with_stderr_contains(\"[RUNNING] [..]target/debug/examples/myexm2-[..]\")\n        .run();\n\n    // Only tests myexm2.\n    prj.cargo(\"test --tests\")\n        .with_stderr_does_not_contain(\"[RUNNING] [..]myexm1-[..]\")\n        .with_stderr_contains(\"[RUNNING] [..]target/debug/examples/myexm2-[..]\")\n        .run();\n\n    // Tests all examples.\n    prj.cargo(\"test --examples\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] unittests examples/myexm1.rs (target/debug/examples/myexm1-[HASH][EXE])\n[RUNNING] unittests examples/myexm2.rs (target/debug/examples/myexm2-[HASH][EXE])\n...\n\"#]])\n        .run();\n\n    // Test an example, even without `test` set.\n    prj.cargo(\"test --example myexm1\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] unittests examples/myexm1.rs (target/debug/examples/myexm1-[HASH][EXE])\n...\n\"#]])\n        .run();\n\n    // Tests all examples.\n    prj.cargo(\"test --all-targets\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] unittests examples/myexm1.rs (target/debug/examples/myexm1-[HASH][EXE])\n[RUNNING] unittests examples/myexm2.rs (target/debug/examples/myexm2-[HASH][EXE])\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_filtered_excludes_compiling_examples() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"mybin\"\n                test = false\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"#[cfg(test)] mod tests { #[test] fn test_in_lib() { } }\",\n        )\n        .file(\n            \"src/bin/mybin.rs\",\n            \"#[test] fn test_in_bin() { }\n               fn main() { panic!(\\\"Don't execute me!\\\"); }\",\n        )\n        .file(\"tests/mytest.rs\", \"#[test] fn test_in_test() { }\")\n        .file(\n            \"benches/mybench.rs\",\n            \"#[test] fn test_in_bench() { assert!(false) }\",\n        )\n        .file(\n            \"examples/myexm1.rs\",\n            \"#[test] fn test_in_exm() { assert!(false) }\n               fn main() { panic!(\\\"Don't execute me!\\\"); }\",\n        )\n        .build();\n\n    p.cargo(\"test -v test_in_\")\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest tests::test_in_lib ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest test_in_test ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] --crate-type lib [..]`\n[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] --test [..]`\n[RUNNING] `rustc --crate-name mybin --edition=2015 src/bin/mybin.rs [..] --crate-type bin [..]`\n[RUNNING] `rustc --crate-name mytest --edition=2015 tests/mytest.rs [..] --test [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE] test_in_`\n[RUNNING] `[ROOT]/foo/target/debug/deps/mytest-[HASH][EXE] test_in_`\n\n\"#]]\n            .unordered(),\n        )\n        .with_stderr_does_not_contain(\"[RUNNING][..]rustc[..]myexm1[..]\")\n        .with_stderr_does_not_contain(\"[RUNNING][..]deps/mybin-[..] test_in_\")\n        .run();\n}\n\n#[cargo_test]\nfn test_no_harness() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [[bin]]\n                name = \"foo\"\n                test = false\n\n                [[test]]\n                name = \"bar\"\n                path = \"foo.rs\"\n                harness = false\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"foo.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"test -- --no-capture\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] foo.rs (target/debug/deps/bar-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn selective_testing() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.d1]\n                    path = \"d1\"\n                [dependencies.d2]\n                    path = \"d2\"\n\n                [lib]\n                    name = \"foo\"\n                    doctest = false\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                    name = \"d1\"\n                    doctest = false\n            \"#,\n        )\n        .file(\"d1/src/lib.rs\", \"\")\n        .file(\n            \"d1/src/main.rs\",\n            \"#[allow(unused_extern_crates)] extern crate d1; fn main() {}\",\n        )\n        .file(\n            \"d2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                    name = \"d2\"\n                    doctest = false\n            \"#,\n        )\n        .file(\"d2/src/lib.rs\", \"\")\n        .file(\n            \"d2/src/main.rs\",\n            \"#[allow(unused_extern_crates)] extern crate d2; fn main() {}\",\n        );\n    let p = p.build();\n\n    println!(\"d1\");\n    p.cargo(\"test -p d1\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[COMPILING] d1 v0.0.1 ([ROOT]/foo/d1)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/d1-[HASH][EXE])\n[RUNNING] unittests src/main.rs (target/debug/deps/d1-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\nrunning 0 tests\nrunning 0 tests\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    println!(\"d2\");\n    p.cargo(\"test -p d2\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] d2 v0.0.1 ([ROOT]/foo/d2)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/d2-[HASH][EXE])\n[RUNNING] unittests src/main.rs (target/debug/deps/d2-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\nrunning 0 tests\nrunning 0 tests\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    println!(\"whole\");\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\nrunning 0 tests\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn almost_cyclic_but_not_quite() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dev-dependencies.b]\n                path = \"b\"\n                [dev-dependencies.c]\n                path = \"c\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(test)] extern crate b;\n                #[cfg(test)] extern crate c;\n            \"#,\n        )\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.foo]\n                path = \"..\"\n            \"#,\n        )\n        .file(\n            \"b/src/lib.rs\",\n            r#\"\n                #[allow(unused_extern_crates)]\n                extern crate foo;\n            \"#,\n        )\n        .file(\"c/Cargo.toml\", &basic_manifest(\"c\", \"0.0.1\"))\n        .file(\"c/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn build_then_selective_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.b]\n                path = \"b\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"#[allow(unused_extern_crates)] extern crate b;\",\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                #[allow(unused_extern_crates)]\n                extern crate b;\n                #[allow(unused_extern_crates)]\n                extern crate foo;\n                fn main() {}\n            \"#,\n        )\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build\").run();\n    p.root().move_into_the_past();\n    p.cargo(\"test -p b\").run();\n}\n\n#[cargo_test]\nfn example_dev_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dev-dependencies.bar]\n                path = \"bar\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/e1.rs\", \"extern crate bar; fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                // make sure this file takes awhile to compile\n                macro_rules! f0( () => (1) );\n                macro_rules! f1( () => ({(f0!()) + (f0!())}) );\n                macro_rules! f2( () => ({(f1!()) + (f1!())}) );\n                macro_rules! f3( () => ({(f2!()) + (f2!())}) );\n                macro_rules! f4( () => ({(f3!()) + (f3!())}) );\n                macro_rules! f5( () => ({(f4!()) + (f4!())}) );\n                macro_rules! f6( () => ({(f5!()) + (f5!())}) );\n                macro_rules! f7( () => ({(f6!()) + (f6!())}) );\n                macro_rules! f8( () => ({(f7!()) + (f7!())}) );\n                pub fn bar() {\n                    f8!();\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"test\").run();\n    p.cargo(\"run --example e1 --release -v\").run();\n}\n\n#[cargo_test]\nfn selective_testing_with_docs() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.d1]\n                    path = \"d1\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// not valid rust\n                /// ```\n                pub fn foo() {}\n            \"#,\n        )\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"d1\"\n                path = \"d1.rs\"\n            \"#,\n        )\n        .file(\"d1/d1.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"test -p d1\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] d1 v0.0.1 ([ROOT]/foo/d1)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests d1.rs (target/debug/deps/d1-[HASH][EXE])\n[DOCTEST] d1\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\nrunning 0 tests\nrunning 0 tests\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn example_bin_same_name() {\n    let p = project()\n        .file(\"src/bin/foo.rs\", r#\"fn main() { println!(\"bin\"); }\"#)\n        .file(\"examples/foo.rs\", r#\"fn main() { println!(\"example\"); }\"#)\n        .build();\n\n    p.cargo(\"test --no-run -v\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[RUNNING] `rustc [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n\n\"#]])\n        .run();\n\n    assert!(!p.bin(\"foo\").is_file());\n    assert!(p.bin(\"examples/foo\").is_file());\n\n    p.process(&p.bin(\"examples/foo\"))\n        .with_stdout_data(str![[r#\"\nexample\n\n\"#]])\n        .run();\n\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nbin\n\n\"#]])\n        .run();\n    assert!(p.bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn test_with_example_twice() {\n    let p = project()\n        .file(\"src/bin/foo.rs\", r#\"fn main() { println!(\"bin\"); }\"#)\n        .file(\"examples/foo.rs\", r#\"fn main() { println!(\"example\"); }\"#)\n        .build();\n\n    println!(\"first\");\n    p.cargo(\"test -v\").run();\n    assert!(p.bin(\"examples/foo\").is_file());\n    println!(\"second\");\n    p.cargo(\"test -v\").run();\n    assert!(p.bin(\"examples/foo\").is_file());\n}\n\n#[cargo_test]\nfn example_with_dev_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo\"\n                test = false\n                doctest = false\n\n                [dev-dependencies.a]\n                path = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"examples/ex.rs\",\n            \"#[allow(unused_extern_crates)] extern crate a; fn main() {}\",\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test -v\")\n        .with_stderr_data(\n            str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[RUNNING] `rustc --crate-name foo [..]`\n[RUNNING] `rustc --crate-name a [..]`\n[RUNNING] `rustc --crate-name ex [..] --extern a=[..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn bin_is_preserved() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build -v\").run();\n    assert!(p.bin(\"foo\").is_file());\n\n    println!(\"test\");\n    p.cargo(\"test -v\").run();\n    assert!(p.bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn bad_example() {\n    let p = project().file(\"src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"run --example foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no example target named `foo` in default-run packages\n\n\"#]])\n        .run();\n    p.cargo(\"run --bin foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] no bin target named `foo` in default-run packages\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doctest_feature() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                [features]\n                bar = []\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```rust\n                /// assert_eq!(foo::foo(), 1);\n                /// ```\n                #[cfg(feature = \"bar\")]\n                pub fn foo() -> i32 { 1 }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test --features bar\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\nrunning 0 tests\ntest [..] ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn dashes_to_underscores() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo-bar\", \"0.0.1\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// assert_eq!(foo_bar::foo(), 1);\n                /// ```\n                pub fn foo() -> i32 { 1 }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test -v\").run();\n}\n\n#[cargo_test]\nfn doctest_dev_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dev-dependencies]\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// extern crate b;\n                /// ```\n                pub fn foo() {}\n            \"#,\n        )\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test -v\").run();\n}\n\n#[cargo_test]\nfn doctest_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// foo::foo();\n                /// ```\n                pub fn foo() {\n                    b::bar();\n                }\n            \"#,\n        )\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"test -v\").run();\n}\n\n#[cargo_test]\nfn doctest_dep_new_layout() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// foo::foo();\n                /// ```\n                pub fn foo() {\n                    b::bar();\n                }\n            \"#,\n        )\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.0.1\"))\n        .file(\"b/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"-Zbuild-dir-new-layout test\")\n        .masquerade_as_nightly_cargo(&[\"new build-dir layout\"])\n        .run();\n}\n\n#[cargo_test]\nfn filter_no_doc_tests() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// extern crate b;\n                /// ```\n                pub fn foo() {}\n            \"#,\n        )\n        .file(\"tests/foo.rs\", \"\")\n        .build();\n\n    p.cargo(\"test --test=foo\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\nrunning 0 tests\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dylib_doctest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo\"\n                crate-type = [\"rlib\", \"dylib\"]\n                test = false\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// foo::foo();\n                /// ```\n                pub fn foo() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest [..] ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dylib_doctest2() {\n    // Can't doc-test dylibs, as they're statically linked together.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                name = \"foo\"\n                crate-type = [\"dylib\"]\n                test = false\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// foo::foo();\n                /// ```\n                pub fn foo() {}\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cyclic_dev_dep_doc_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dev-dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! ```\n                //! extern crate bar;\n                //! ```\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = { path = \"..\" }\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                #[allow(unused_extern_crates)]\n                extern crate foo;\n            \"#,\n        )\n        .build();\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[COMPILING] bar v0.0.1 ([ROOT]/foo/bar)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\nrunning 0 tests\ntest [..] ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn dev_dep_with_build_script() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dev-dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/foo.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"bar/build.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"test\").run();\n}\n\n#[cargo_test]\nfn no_fail_fast() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            pub fn add_one(x: i32) -> i32{\n                x + 1\n            }\n\n            /// ```rust\n            /// use foo::sub_one;\n            /// assert_eq!(sub_one(101), 100);\n            /// ```\n            pub fn sub_one(x: i32) -> i32{\n                x - 1\n            }\n            \"#,\n        )\n        .file(\n            \"tests/test_add_one.rs\",\n            r#\"\n            extern crate foo;\n            use foo::*;\n\n            #[test]\n            fn add_one_test() {\n                assert_eq!(add_one(1), 2);\n            }\n\n            #[test]\n            fn fail_add_one_test() {\n                assert_eq!(add_one(1), 1);\n            }\n            \"#,\n        )\n        .file(\n            \"tests/test_sub_one.rs\",\n            r#\"\n            extern crate foo;\n            use foo::*;\n\n            #[test]\n            fn sub_one_test() {\n                assert_eq!(sub_one(1), 0);\n            }\n            \"#,\n        )\n        .build();\n    p.cargo(\"test --no-fail-fast\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[RUNNING] tests/test_add_one.rs (target/debug/deps/test_add_one-[HASH][EXE])\n[ERROR] test failed, to rerun pass `--test test_add_one`\n[RUNNING] tests/test_sub_one.rs (target/debug/deps/test_sub_one-[HASH][EXE])\n[DOCTEST] foo\n[ERROR] 1 target failed:\n    `--test test_add_one`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\nrunning 0 tests\ntest add_one_test ... ok\ntest result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\ntest sub_one_test ... ok\ntest [..] ... ok\n...\n\"#]].unordered())\n        .run();\n}\n\n#[cargo_test]\nfn test_multiple_packages() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies.d1]\n                    path = \"d1\"\n                [dependencies.d2]\n                    path = \"d2\"\n\n                [lib]\n                    name = \"foo\"\n                    doctest = false\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"d1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d1\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                    name = \"d1\"\n                    doctest = false\n            \"#,\n        )\n        .file(\"d1/src/lib.rs\", \"\")\n        .file(\n            \"d2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"d2\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                    name = \"d2\"\n                    doctest = false\n            \"#,\n        )\n        .file(\"d2/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"test -p d1 -p d2\")\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] unittests src/lib.rs (target/debug/deps/d1-[HASH][EXE])\n[RUNNING] unittests src/lib.rs (target/debug/deps/d2-[HASH][EXE])\n...\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\nrunning 0 tests\nrunning 0 tests\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn bin_does_not_rebuild_tests() {\n    let p = project()\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"tests/foo.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"test -v\").run();\n\n    sleep_ms(1000);\n    fs::write(p.root().join(\"src/main.rs\"), \"fn main() { 3; }\").unwrap();\n\n    p.cargo(\"test -v --no-run\")\n        .with_stderr_data(str![[r#\"\n[DIRTY] foo v0.0.1 ([ROOT]/foo): the file `src/main.rs` has changed ([..])\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..] src/main.rs [..]`\n[RUNNING] `rustc [..] src/main.rs [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn selective_test_wonky_profile() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.release]\n                opt-level = 2\n\n                [dependencies]\n                a = { path = \"a\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"test -v --no-run --release -p foo -p a\").run();\n}\n\n#[cargo_test]\nfn selective_test_optional_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\", optional = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"test -v --no-run --features a -p a\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[COMPILING] a v0.0.1 ([ROOT]/foo/a)\n[RUNNING] `rustc [..] a/src/lib.rs [..]`\n[RUNNING] `rustc [..] a/src/lib.rs [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[EXECUTABLE] `[ROOT]/foo/target/debug/deps/a-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn only_test_docs() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[test]\n                fn foo() {\n                    let a: u32 = \"hello\";\n                }\n\n                /// ```\n                /// foo::bar();\n                /// println!(\"ok\");\n                /// ```\n                pub fn bar() {\n                }\n            \"#,\n        )\n        .file(\"tests/foo.rs\", \"this is not rust\");\n    let p = p.build();\n\n    p.cargo(\"test --doc\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\ntest [..] ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doctest_with_library_paths() {\n    let p = project();\n    // Only link search directories within the target output directory are\n    // propagated through to dylib_path_envvar() (see #3366).\n    let dir1 = p.target_debug_dir().join(\"foo\\\\backslash\");\n    let dir2 = p.target_debug_dir().join(\"dir=containing=equal=signs\");\n\n    let p = p\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.0\"))\n        .file(\n            \"build.rs\",\n            &format!(\n                r##\"\n                    fn main() {{\n                        println!(r#\"cargo::rustc-link-search=native={}\"#);\n                        println!(r#\"cargo::rustc-link-search={}\"#);\n                    }}\n                \"##,\n                dir1.display(),\n                dir2.display()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            &format!(\n                r##\"\n                    /// ```\n                    /// foo::assert_search_path();\n                    /// ```\n                    pub fn assert_search_path() {{\n                        let search_path = std::env::var_os(\"{}\").unwrap();\n                        let paths = std::env::split_paths(&search_path).collect::<Vec<_>>();\n                        assert!(paths.contains(&r#\"{}\"#.into()));\n                        assert!(paths.contains(&r#\"{}\"#.into()));\n                    }}\n                \"##,\n                dylib_path_envvar(),\n                dir1.display(),\n                dir2.display()\n            ),\n        )\n        .build();\n\n    p.cargo(\"test --doc\").run();\n}\n\n#[cargo_test]\nfn test_panic_abort_with_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [profile.dev]\n                panic = 'abort'\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                extern crate bar;\n\n                #[test]\n                fn foo() {}\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.0.1\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"test -v\").run();\n}\n\n#[cargo_test]\nfn cfg_test_even_with_no_harness() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                harness = false\n                doctest = false\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"#[cfg(test)] fn main() { println!(\"hello!\"); }\"#,\n        )\n        .build();\n    p.cargo(\"test -v\")\n        .with_stdout_data(str![[r#\"\nhello!\n\n\"#]])\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn panic_abort_multiple() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n\n                [profile.release]\n                panic = 'abort'\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"#[allow(unused_extern_crates)] extern crate a;\",\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"test --release -v -p foo -p a\").run();\n}\n\n#[cargo_test]\nfn pass_correct_cfgs_flags_to_rustdoc() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"feature_a/default\"]\n                nightly = [\"feature_a/nightly\"]\n\n                [dependencies.feature_a]\n                path = \"libs/feature_a\"\n                default-features = false\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(test)]\n                mod tests {\n                    #[test]\n                    fn it_works() {\n                      assert!(true);\n                    }\n                }\n            \"#,\n        )\n        .file(\n            \"libs/feature_a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"feature_a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                default = [\"mock_serde_codegen\"]\n                nightly = [\"mock_serde_derive\"]\n\n                [dependencies]\n                mock_serde_derive = { path = \"../mock_serde_derive\", optional = true }\n\n                [build-dependencies]\n                mock_serde_codegen = { path = \"../mock_serde_codegen\", optional = true }\n            \"#,\n        )\n        .file(\n            \"libs/feature_a/src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"mock_serde_derive\")]\n                const MSG: &'static str = \"This is safe\";\n\n                #[cfg(feature = \"mock_serde_codegen\")]\n                const MSG: &'static str = \"This is risky\";\n\n                pub fn get() -> &'static str {\n                    MSG\n                }\n            \"#,\n        )\n        .file(\n            \"libs/mock_serde_derive/Cargo.toml\",\n            &basic_manifest(\"mock_serde_derive\", \"0.1.0\"),\n        )\n        .file(\"libs/mock_serde_derive/src/lib.rs\", \"\")\n        .file(\n            \"libs/mock_serde_codegen/Cargo.toml\",\n            &basic_manifest(\"mock_serde_codegen\", \"0.1.0\"),\n        )\n        .file(\"libs/mock_serde_codegen/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"test --package feature_a --verbose\")\n        .with_stderr_data(str![[r#\"\n...\n[DOCTEST] feature_a\n[RUNNING] `rustdoc [..]--test [..]mock_serde_codegen[..]`\n...\n\"#]])\n        .run();\n\n    p.cargo(\"test --verbose\")\n        .with_stderr_data(str![[r#\"\n...\n[DOCTEST] foo\n[RUNNING] `rustdoc [..]--test [..]feature_a[..]`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_release_ignore_panic() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n\n                [profile.test]\n                panic = 'abort'\n                [profile.release]\n                panic = 'abort'\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            \"#[allow(unused_extern_crates)] extern crate a;\",\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\");\n    let p = p.build();\n    println!(\"test\");\n    p.cargo(\"test -v\").run();\n    println!(\"bench\");\n    p.cargo(\"bench -v\").run();\n}\n\n#[cargo_test]\nfn test_many_with_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                a = { path = \"a\" }\n\n                [features]\n                foo = []\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.0.1\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test -v -p a -p foo --features foo\").run();\n}\n\n#[cargo_test]\nfn test_all_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"#[test] fn foo_test() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"#[test] fn bar_test() {}\")\n        .build();\n\n    p.cargo(\"test --workspace\")\n        .with_stdout_data(\n            str![[r#\"\ntest foo_test ... ok\ntest bar_test ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn test_all_exclude() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"#[test] pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"#[test] pub fn baz() { assert!(false); }\")\n        .build();\n\n    p.cargo(\"test --workspace --exclude baz\")\n        .with_stdout_data(str![[r#\"\n...\nrunning 1 test\ntest bar ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_all_exclude_not_found() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"#[test] pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"test --workspace --exclude baz\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] excluded package(s) `baz` not found in workspace `[ROOT]/foo`\n...\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\nrunning 1 test\ntest bar ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_all_exclude_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"#[test] pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"#[test] pub fn baz() { assert!(false); }\")\n        .build();\n\n    p.cargo(\"test --workspace --exclude '*z'\")\n        .with_stdout_data(str![[r#\"\n...\nrunning 1 test\ntest bar ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_all_exclude_glob_not_found() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"#[test] pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"test --workspace --exclude '*z'\")\n        .with_stderr_data(str![[r#\"\n...\n[WARNING] excluded package pattern(s) `*z` not found in workspace `[ROOT]/foo`\n...\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\nrunning 1 test\ntest bar ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_all_exclude_broken_glob() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    p.cargo(\"test --workspace --exclude '[*z'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] cannot build glob pattern from `[*z`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_all_virtual_manifest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"#[test] fn a() {}\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.1.0\"))\n        .file(\"b/src/lib.rs\", \"#[test] fn b() {}\")\n        .build();\n\n    p.cargo(\"test --workspace\")\n        .with_stdout_data(\n            str![[r#\"\nrunning 1 test\ntest a ... ok\nrunning 1 test\ntest b ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn test_virtual_manifest_all_implied() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\", \"b\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"#[test] fn a() {}\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.1.0\"))\n        .file(\"b/src/lib.rs\", \"#[test] fn b() {}\")\n        .build();\n\n    p.cargo(\"test\")\n        .with_stdout_data(\n            str![[r#\"\nrunning 1 test\ntest a ... ok\nrunning 1 test\ntest b ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn test_virtual_manifest_one_project() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"#[test] fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"#[test] fn baz() { assert!(false); }\")\n        .build();\n\n    p.cargo(\"test -p bar\")\n        .with_stdout_contains(\"running 1 test\\ntest bar ... ok\")\n        .with_stdout_does_not_contain(\"running 1 test\\ntest baz ... ok\")\n        .run();\n}\n\n#[cargo_test]\nfn test_virtual_manifest_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"#[test] fn bar() { assert!(false); }\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"#[test] fn baz() {}\")\n        .build();\n\n    p.cargo(\"test -p '*z'\")\n        .with_stdout_does_not_contain(\"running 1 test\\ntest bar ... ok\")\n        .with_stdout_contains(\"running 1 test\\ntest baz ... ok\")\n        .run();\n}\n\n#[cargo_test]\nfn test_virtual_manifest_glob_not_found() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"#[test] fn bar() {}\")\n        .build();\n\n    p.cargo(\"test -p bar -p '*z'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package pattern(s) `*z` not found in workspace `[ROOT]/foo`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_virtual_manifest_broken_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"#[test] fn bar() {}\")\n        .build();\n\n    p.cargo(\"test -p '[*z'\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot build glob pattern from `[*z`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_all_member_dependency_same_name() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                a = \"0.1.0\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"#[test] fn a() {}\")\n        .build();\n\n    Package::new(\"a\", \"0.1.0\").publish();\n\n    p.cargo(\"test --workspace\")\n        .with_stdout_data(str![[r#\"\n...\ntest a ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn doctest_only_with_dev_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dev-dependencies]\n                b = { path = \"b\" }\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// extern crate b;\n                ///\n                /// b::b();\n                /// ```\n                pub fn a() {}\n            \"#,\n        )\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.1.0\"))\n        .file(\"b/src/lib.rs\", \"pub fn b() {}\")\n        .build();\n\n    p.cargo(\"test --doc -v\").run();\n}\n\n#[cargo_test]\nfn test_many_targets() {\n    let p = project()\n        .file(\n            \"src/bin/a.rs\",\n            r#\"\n                fn main() {}\n                #[test] fn bin_a() {}\n            \"#,\n        )\n        .file(\n            \"src/bin/b.rs\",\n            r#\"\n                fn main() {}\n                #[test] fn bin_b() {}\n            \"#,\n        )\n        .file(\n            \"src/bin/c.rs\",\n            r#\"\n                fn main() {}\n                #[test] fn bin_c() { panic!(); }\n            \"#,\n        )\n        .file(\n            \"examples/a.rs\",\n            r#\"\n                fn main() {}\n                #[test] fn example_a() {}\n            \"#,\n        )\n        .file(\n            \"examples/b.rs\",\n            r#\"\n                fn main() {}\n                #[test] fn example_b() {}\n            \"#,\n        )\n        .file(\"examples/c.rs\", \"#[test] fn example_c() { panic!(); }\")\n        .file(\"tests/a.rs\", \"#[test] fn test_a() {}\")\n        .file(\"tests/b.rs\", \"#[test] fn test_b() {}\")\n        .file(\"tests/c.rs\", \"does not compile\")\n        .build();\n\n    p.cargo(\"test --verbose --bin a --bin b --example a --example b --test a --test b\")\n        .with_stdout_data(\n            str![[r#\"\ntest bin_a ... ok\ntest bin_b ... ok\ntest test_a ... ok\ntest test_b ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .with_stderr_data(\n            str![[r#\"\n[RUNNING] `rustc --crate-name a --edition=2015 examples/a.rs [..]`\n[RUNNING] `rustc --crate-name b --edition=2015 examples/b.rs [..]`\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn doctest_and_registry() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                b = { path = \"b\" }\n                c = { path = \"c\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.1.0\"))\n        .file(\n            \"b/src/lib.rs\",\n            \"\n            /// ```\n            /// b::foo();\n            /// ```\n            pub fn foo() {}\n        \",\n        )\n        .file(\n            \"c/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"c\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                b = \"0.1\"\n            \"#,\n        )\n        .file(\"c/src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"b\", \"0.1.0\").publish();\n\n    p.cargo(\"test --workspace -v\").run();\n}\n\n#[cargo_test]\nfn cargo_test_env() {\n    let rustc_host = rustc_host();\n    let src = format!(\n        r#\"\n        #![crate_type = \"rlib\"]\n\n        #[test]\n        fn env_test() {{\n            use std::env;\n            eprintln!(\"{{}}\", env::var(\"{}\").unwrap());\n        }}\n        \"#,\n        cargo::CARGO_ENV\n    );\n\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", &src)\n        .build();\n\n    let cargo = format!(\n        \"{}[EXE]\",\n        cargo_exe()\n            .with_extension(\"\")\n            .to_str()\n            .unwrap()\n            .replace(rustc_host, \"[HOST_TARGET]\")\n    );\n    p.cargo(\"test --lib -- --no-capture\")\n        .with_stderr_contains(cargo)\n        .with_stdout_data(str![[r#\"\n...\ntest env_test ... ok\n...\n\"#]])\n        .run();\n\n    // Check that `cargo test` propagates the environment's $CARGO\n    let cargo_exe = cargo_exe();\n    let other_cargo_path = p.root().join(cargo_exe.file_name().unwrap());\n    std::fs::hard_link(&cargo_exe, &other_cargo_path).unwrap();\n    let stderr_other_cargo = format!(\n        \"{}[EXE]\",\n        other_cargo_path\n            .with_extension(\"\")\n            .to_str()\n            .unwrap()\n            .replace(p.root().parent().unwrap().to_str().unwrap(), \"[ROOT]\")\n    );\n    p.process(other_cargo_path)\n        .args(&[\"test\", \"--lib\", \"--\", \"--no-capture\"])\n        .with_stderr_contains(stderr_other_cargo)\n        .with_stdout_data(str![[r#\"\n...\ntest env_test ... ok\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_order() {\n    let p = project()\n        .file(\"src/lib.rs\", \"#[test] fn test_lib() {}\")\n        .file(\"tests/a.rs\", \"#[test] fn test_a() {}\")\n        .file(\"tests/z.rs\", \"#[test] fn test_z() {}\")\n        .build();\n\n    p.cargo(\"test --workspace\")\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest test_lib ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest test_a ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest test_z ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cyclic_dev() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dev-dependencies]\n                foo = { path = \".\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"#[test] fn test_lib() {}\")\n        .file(\"tests/foo.rs\", \"extern crate foo;\")\n        .build();\n\n    p.cargo(\"test --workspace\").run();\n}\n\n#[cargo_test]\nfn cyclical_dep_with_missing_feature() {\n    // Checks for error handling when a cyclical dev-dependency specify a\n    // feature that doesn't exist.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dev-dependencies]\n                foo = { path = \".\", features = [\"missing\"] }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to select a version for `foo`.\n    ... required by package `foo v0.1.0 ([ROOT]/foo)`\nversions that meet the requirements `*` are: 0.1.0\n\npackage `foo` depends on `foo` with feature `missing` but `foo` does not have that feature.\n\n\nfailed to select a version for `foo` which could resolve this conflict\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish_a_crate_without_tests() {\n    Package::new(\"testless\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"testless\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                exclude = [\"tests/*\"]\n\n                [[test]]\n                name = \"a_test\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        // In real life, the package will have a test,\n        // which would be excluded from .crate file by the\n        // `exclude` field. Our test harness does not honor\n        // exclude though, so let's just not add the file!\n        // .file(\"tests/a_test.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                testless = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test\").run();\n    p.cargo(\"test --package testless\").run();\n}\n\n#[cargo_test]\nfn find_dependency_of_proc_macro_dependency_with_target() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"root\", \"proc_macro_dep\"]\n            \"#,\n        )\n        .file(\n            \"root/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"root\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                proc_macro_dep = { path = \"../proc_macro_dep\" }\n            \"#,\n        )\n        .file(\n            \"root/src/lib.rs\",\n            r#\"\n                #[macro_use]\n                extern crate proc_macro_dep;\n\n                #[derive(Noop)]\n                pub struct X;\n            \"#,\n        )\n        .file(\n            \"proc_macro_dep/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"proc_macro_dep\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [lib]\n                proc-macro = true\n\n                [dependencies]\n                baz = \"^0.1\"\n            \"#,\n        )\n        .file(\n            \"proc_macro_dep/src/lib.rs\",\n            r#\"\n                extern crate baz;\n                extern crate proc_macro;\n                use proc_macro::TokenStream;\n\n                #[proc_macro_derive(Noop)]\n                pub fn noop(_input: TokenStream) -> TokenStream {\n                    \"\".parse().unwrap()\n                }\n            \"#,\n        )\n        .build();\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"baz\", \"0.1.0\")\n        .dep(\"bar\", \"0.1\")\n        .file(\"src/lib.rs\", \"extern crate bar;\")\n        .publish();\n    p.cargo(\"test --workspace --target\").arg(rustc_host()).run();\n}\n\n#[cargo_test]\nfn test_hint_not_masked_by_doctest() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                /// ```\n                /// assert_eq!(1, 1);\n                /// ```\n                pub fn this_works() {}\n            \"#,\n        )\n        .file(\n            \"tests/integ.rs\",\n            r#\"\n                #[test]\n                fn this_fails() {\n                    panic!();\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"test --no-fail-fast\")\n        .with_status(101)\n        .with_stdout_data(\n            str![[r#\"\ntest this_fails ... FAILED\ntest [..]this_works (line [..]) ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] test failed, to rerun pass `--test integ`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_hint_workspace_virtual() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\", \"b\", \"c\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"#[test] fn t1() {}\")\n        .file(\"b/Cargo.toml\", &basic_manifest(\"b\", \"0.1.0\"))\n        .file(\"b/src/lib.rs\", \"#[test] fn t1() {assert!(false)}\")\n        .file(\"c/Cargo.toml\", &basic_manifest(\"c\", \"0.1.0\"))\n        .file(\n            \"c/src/lib.rs\",\n            r#\"\n                /// ```rust\n                /// assert_eq!(1, 2);\n                /// ```\n                pub fn foo() {}\n            \"#,\n        )\n        .file(\n            \"c/src/main.rs\",\n            r#\"\n                fn main() {}\n\n                #[test]\n                fn from_main() { assert_eq!(1, 2); }\n            \"#,\n        )\n        .file(\n            \"c/tests/t1.rs\",\n            r#\"\n                #[test]\n                fn from_int_test() { assert_eq!(1, 2); }\n            \"#,\n        )\n        .file(\n            \"c/examples/ex1.rs\",\n            r#\"\n                fn main() {}\n\n                #[test]\n                fn from_example() { assert_eq!(1, 2); }\n            \"#,\n        )\n        // This does not use #[bench] since it is unstable. #[test] works just\n        // the same for our purpose of checking the hint.\n        .file(\n            \"c/benches/b1.rs\",\n            r#\"\n                #[test]\n                fn from_bench() { assert_eq!(1, 2); }\n            \"#,\n        )\n        .build();\n\n    // This depends on Units being sorted so that `b` fails first.\n    p.cargo(\"test\")\n        .with_stderr_data(\n            str![[r#\"\n[COMPILING] c v0.1.0 ([ROOT]/foo/c)\n[COMPILING] a v0.1.0 ([ROOT]/foo/a)\n[COMPILING] b v0.1.0 ([ROOT]/foo/b)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/a-[HASH][EXE])\n[RUNNING] unittests src/lib.rs (target/debug/deps/b-[HASH][EXE])\n[ERROR] test failed, to rerun pass `-p b --lib`\n\n\"#]]\n            .unordered(),\n        )\n        .with_status(101)\n        .run();\n    p.cargo(\"test\")\n        .cwd(\"b\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs ([ROOT]/foo/target/debug/deps/b-[HASH][EXE])\n[ERROR] test failed, to rerun pass `--lib`\n\n\"#]])\n        .with_status(101)\n        .run();\n    p.cargo(\"test --no-fail-fast\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/a-[HASH][EXE])\n[RUNNING] unittests src/lib.rs (target/debug/deps/b-[HASH][EXE])\n[ERROR] test failed, to rerun pass `-p b --lib`\n[RUNNING] unittests src/lib.rs (target/debug/deps/c-[HASH][EXE])\n[RUNNING] unittests src/main.rs (target/debug/deps/c-[HASH][EXE])\n[ERROR] test failed, to rerun pass `-p c --bin c`\n[RUNNING] tests/t1.rs (target/debug/deps/t1-[HASH][EXE])\n[ERROR] test failed, to rerun pass `-p c --test t1`\n[DOCTEST] a\n[DOCTEST] b\n[DOCTEST] c\n[ERROR] doctest failed, to rerun pass `-p c --doc`\n[ERROR] 4 targets failed:\n    `-p b --lib`\n    `-p c --bin c`\n    `-p c --test t1`\n    `-p c --doc`\n\n\"#]])\n        .with_status(101)\n        .run();\n    // Check others that are not in the default set.\n    p.cargo(\"test -p c --examples --benches --no-fail-fast\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] c v0.1.0 ([ROOT]/foo/c)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/c-[HASH][EXE])\n[RUNNING] unittests src/main.rs (target/debug/deps/c-[HASH][EXE])\n[ERROR] test failed, to rerun pass `-p c --bin c`\n[RUNNING] benches/b1.rs (target/debug/deps/b1-[HASH][EXE])\n[ERROR] test failed, to rerun pass `-p c --bench b1`\n[RUNNING] unittests examples/ex1.rs (target/debug/examples/ex1-[HASH][EXE])\n[ERROR] test failed, to rerun pass `-p c --example ex1`\n[ERROR] 3 targets failed:\n    `-p c --bin c`\n    `-p c --bench b1`\n    `-p c --example ex1`\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn test_hint_workspace_nonvirtual() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [workspace]\n            members = [\"a\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"#[test] fn t1() {assert!(false)}\")\n        .build();\n\n    p.cargo(\"test --workspace\")\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] test failed, to rerun pass `-p a --lib`\n...\n\"#]])\n        .with_status(101)\n        .run();\n    p.cargo(\"test -p a\")\n        .with_stderr_data(str![[r#\"\n...\n[ERROR] test failed, to rerun pass `-p a --lib`\n...\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn json_artifact_includes_test_flag() {\n    // Verify that the JSON artifact output includes `test` flag.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [profile.test]\n                opt-level = 1\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test --lib -v --no-run --message-format=json\")\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"executable\": \"[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]\",\n    \"features\": [],\n    \"filenames\": \"{...}\",\n    \"fresh\": false,\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.1\",\n    \"profile\": \"{...}\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"crate_types\": [\n        \"lib\"\n      ],\n      \"doc\": true,\n      \"doctest\": true,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"lib\"\n      ],\n      \"name\": \"foo\",\n      \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n      \"test\": true\n    }\n  },\n  {\n    \"reason\": \"build-finished\",\n    \"success\": true\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn json_artifact_includes_executable_for_library_tests() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() { }\")\n        .file(\"src/lib.rs\", r#\"#[test] fn lib_test() {}\"#)\n        .build();\n\n    p.cargo(\"test --lib -v --no-run --message-format=json\")\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"executable\": \"[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]\",\n    \"features\": [],\n    \"filenames\": \"{...}\",\n    \"fresh\": false,\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.1\",\n    \"profile\": \"{...}\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"crate_types\": [\n        \"lib\"\n      ],\n      \"doc\": true,\n      \"doctest\": true,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"lib\"\n      ],\n      \"name\": \"foo\",\n      \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n      \"test\": true\n    }\n  },\n  {\n    \"reason\": \"build-finished\",\n    \"success\": true\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn json_diagnostic_includes_explanation() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            \"fn main() { const OH_NO: &'static mut usize = &mut 1; }\",\n        )\n        .build();\n\n    p.cargo(\"check --message-format=json\")\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"message\": {\n      \"$message_type\": \"diagnostic\",\n      \"children\": \"{...}\",\n      \"code\": {\n        \"code\": \"E0764\",\n        \"explanation\": \"{...}\"\n      },\n      \"level\": \"error\",\n      \"message\": \"{...}\",\n      \"rendered\": \"{...}\",\n      \"spans\": \"{...}\"\n    },\n    \"package_id\": \"{...}\",\n    \"reason\": \"compiler-message\",\n    \"target\": \"{...}\"\n  },\n  \"{...}\"\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn json_artifact_includes_executable_for_integration_tests() {\n    let p = project()\n        .file(\n            \"tests/integration_test.rs\",\n            r#\"#[test] fn integration_test() {}\"#,\n        )\n        .build();\n\n    p.cargo(\"test -v --no-run --message-format=json --test integration_test\")\n        .with_stdout_data(\n            str![[r#\"\n[\n  {\n    \"executable\": \"[ROOT]/foo/target/debug/deps/integration_test-[HASH][EXE]\",\n    \"features\": [],\n    \"filenames\": \"{...}\",\n    \"fresh\": false,\n    \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n    \"package_id\": \"path+[ROOTURL]/foo#0.0.1\",\n    \"profile\": \"{...}\",\n    \"reason\": \"compiler-artifact\",\n    \"target\": {\n      \"crate_types\": [\n        \"bin\"\n      ],\n      \"doc\": false,\n      \"doctest\": false,\n      \"edition\": \"2015\",\n      \"kind\": [\n        \"test\"\n      ],\n      \"name\": \"integration_test\",\n      \"src_path\": \"[ROOT]/foo/tests/integration_test.rs\",\n      \"test\": true\n    }\n  },\n  {\n    \"reason\": \"build-finished\",\n    \"success\": true\n  }\n]\n\"#]]\n            .is_json()\n            .against_jsonlines(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn test_build_script_links() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                links = 'something'\n\n                [lib]\n                test = false\n            \"#,\n        )\n        .file(\"build.rs\", \"fn main() {}\")\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test --no-run\").run();\n}\n\n#[cargo_test]\nfn doctest_skip_staticlib() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [lib]\n                crate-type = [\"staticlib\"]\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            //! ```\n            //! assert_eq!(1,2);\n            //! ```\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test --doc\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[WARNING] doc tests are not supported for crate type(s) `staticlib` in package `foo`\n[ERROR] no library targets found in package `foo`\n\n\"#]])\n        .run();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn can_not_mix_doc_tests_and_regular_tests() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            \"\\\n/// ```\n/// assert_eq!(1, 1)\n/// ```\npub fn foo() -> u8 { 1 }\n\n#[cfg(test)] mod tests {\n    #[test] fn it_works() { assert_eq!(2 + 2, 4); }\n}\n\",\n        )\n        .build();\n\n    p.cargo(\"test\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n[DOCTEST] foo\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest tests::it_works ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\nrunning 1 test\ntest src/lib.rs - foo (line 1) ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    p.cargo(\"test --lib\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest tests::it_works ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .run();\n\n    // This has been modified to attempt to diagnose spurious errors on CI.\n    // For some reason, this is recompiling the lib when it shouldn't. If the\n    // root cause is ever found, the changes here should be reverted.\n    // See https://github.com/rust-lang/cargo/issues/6887\n    p.cargo(\"test --doc -vv\")\n        .with_stderr_does_not_contain(\"[COMPILING] foo [..]\")\n        .with_stderr_data(str![[r#\"\n...\n[DOCTEST] foo\n...\n\"#]])\n        .with_stdout_data(str![[r#\"\n\nrunning 1 test\ntest src/lib.rs - foo (line 1) ... ok\n\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n\n\n\"#]])\n        .env(\"CARGO_LOG\", \"cargo=trace\")\n        .run();\n\n    p.cargo(\"test --lib --doc\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] can't mix --doc with other target selecting options\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn can_not_no_run_doc_tests() {\n    let p = project()\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            /// ```\n            /// let _x = 1 + \"foo\";\n            /// ```\n            pub fn foo() -> u8 { 1 }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test --doc --no-run\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] can't skip running doc tests with --no-run\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_all_targets_lib() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"test --all-targets\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE])\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn test_dep_with_dev() {\n    Package::new(\"devdep\", \"0.1.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dev-dependencies]\n                devdep = \"0.1\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test -p bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[ERROR] package `bar` cannot be tested because it requires dev-dependencies and is not a member of the workspace\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_test_doctest_xcompile_ignores() {\n    // Check ignore-TARGET syntax.\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            ///```ignore-x86_64\n            ///assert!(cfg!(not(target_arch = \"x86_64\")));\n            ///```\n            pub fn foo() -> u8 {\n                4\n            }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    #[cfg(not(target_arch = \"x86_64\"))]\n    p.cargo(\"test\")\n        .with_stdout_data(str![[r#\"\n...\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n...\n\"#]])\n        .run();\n    #[cfg(target_arch = \"x86_64\")]\n    p.cargo(\"test\")\n        .with_stdout_data(str![[r#\"\n...\ntest result: ok. 0 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_test_doctest_xcompile_runner() {\n    if !cross_compile_can_run_on_host() {\n        return;\n    }\n\n    let runner = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"runner\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            pub fn main() {\n                eprintln!(\"this is a runner\");\n                let args: Vec<String> = std::env::args().collect();\n                std::process::Command::new(&args[1]).spawn();\n            }\n            \"#,\n        )\n        .build();\n\n    runner.cargo(\"build\").run();\n    assert!(runner.bin(\"runner\").is_file());\n    let runner_path = paths::root().join(\"runner\");\n    fs::copy(&runner.bin(\"runner\"), &runner_path).unwrap();\n\n    let config = paths::root().join(\".cargo/config.toml\");\n\n    fs::create_dir_all(config.parent().unwrap()).unwrap();\n    // Escape Windows backslashes for TOML config.\n    let runner_str = runner_path.to_str().unwrap().replace('\\\\', \"\\\\\\\\\");\n    fs::write(\n        config,\n        format!(\n            r#\"\n            [target.'cfg(target_arch = \"{}\")']\n            runner = \"{}\"\n            \"#,\n            cross_compile::alternate_arch(),\n            runner_str\n        ),\n    )\n    .unwrap();\n\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\n            \"src/lib.rs\",\n            &format!(\n                r#\"\n                ///```\n                ///assert!(cfg!(target_arch = \"{}\"));\n                ///```\n                pub fn foo() -> u8 {{\n                    4\n                }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(&format!(\"test --target {}\", cross_compile::alternate()))\n        .with_stdout_data(str![[r#\"\n...\nrunning 0 tests\n...\n\"#]])\n        .run();\n    p.cargo(&format!(\"test --target {}\", cross_compile::alternate()))\n        .with_stdout_data(str![[r#\"\n...\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n...\n\"#]])\n        .with_stderr_data(str![[r#\"\n...\nthis is a runner\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_test_doctest_xcompile_no_runner() {\n    if !cross_compile_can_run_on_host() {\n        return;\n    }\n\n    let p = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\n            \"src/lib.rs\",\n            &format!(\n                r#\"\n                ///```\n                ///assert!(cfg!(target_arch = \"{}\"));\n                ///```\n                pub fn foo() -> u8 {{\n                    4\n                }}\n                \"#,\n                cross_compile::alternate_arch()\n            ),\n        )\n        .build();\n\n    p.cargo(\"build\").run();\n    p.cargo(&format!(\"test --target {}\", cross_compile::alternate()))\n        .with_stdout_data(str![[r#\"\n...\nrunning 0 tests\n...\n\"#]])\n        .run();\n    p.cargo(&format!(\"test --target {}\", cross_compile::alternate()))\n        .with_stdout_data(str![[r#\"\n...\ntest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zpanic-abort-tests in rustc is unstable\")]\nfn panic_abort_tests() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                edition = \"2015\"\n\n                [dependencies]\n                a = { path = 'a' }\n\n                [profile.dev]\n                panic = 'abort'\n                [profile.test]\n                panic = 'abort'\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[test]\n                fn foo() {\n                    a::foo();\n                }\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_lib_manifest(\"a\"))\n        .file(\"a/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    // This uses -j1 because of a race condition. Otherwise it will build the\n    // two copies of `foo` in parallel, and which one is first is random. If\n    // `--test` is first, then the first line with `[..]` will match, and the\n    // second line with `--test` will fail.\n    p.cargo(\"test -Z panic-abort-tests -v -j1\")\n        .with_stderr_data(\n            str![[r#\"\n[RUNNING] `[..]--crate-name a [..]-C panic=abort[..]`\n[RUNNING] `[..]--crate-name foo [..]-C panic=abort[..]`\n[RUNNING] `[..]--crate-name foo [..]-C panic=abort[..]--test[..]`\n...\n\"#]]\n            .unordered(),\n        )\n        .masquerade_as_nightly_cargo(&[\"panic-abort-tests\"])\n        .run();\n}\n\n#[cargo_test] // Unlike with rustc, `rustdoc --test -Cpanic=abort` already works on stable\nfn panic_abort_doc_tests() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                edition = \"2015\"\n\n                [profile.dev]\n                panic = 'abort'\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                //! ```should_panic\n                //! panic!();\n                //! ```\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test --doc -Z panic-abort-tests -v\")\n        .with_stderr_data(\n            str![[r#\"\n[RUNNING] `[..]rustc[..] --crate-name foo [..]-C panic=abort[..]`\n[RUNNING] `[..]rustdoc[..] --crate-name foo [..]--test[..]-C panic=abort[..]`\n...\n\"#]]\n            .unordered(),\n        )\n        .masquerade_as_nightly_cargo(&[\"panic-abort-tests\"])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zpanic-abort-tests in rustc is unstable\")]\nfn panic_abort_only_test() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                edition = \"2015\"\n\n                [dependencies]\n                a = { path = 'a' }\n\n                [profile.test]\n                panic = 'abort'\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[test]\n                fn foo() {\n                    a::foo();\n                }\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_lib_manifest(\"a\"))\n        .file(\"a/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"test -Z panic-abort-tests -v\")\n        .with_stderr_data(str![[r#\"\n[WARNING] `panic` setting is ignored for `test` profile\n...\n\"#]])\n        .masquerade_as_nightly_cargo(&[\"panic-abort-tests\"])\n        .run();\n}\n\n#[cargo_test(nightly, reason = \"-Zpanic-abort-tests in rustc is unstable\")]\nfn panic_abort_test_profile_inherits() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = 'foo'\n                version = '0.1.0'\n                edition = \"2015\"\n\n                [dependencies]\n                a = { path = 'a' }\n\n                [profile.dev]\n                panic = 'abort'\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[test]\n                fn foo() {\n                    a::foo();\n                }\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_lib_manifest(\"a\"))\n        .file(\"a/src/lib.rs\", \"pub fn foo() {}\")\n        .build();\n\n    p.cargo(\"test -Z panic-abort-tests -v\")\n        .masquerade_as_nightly_cargo(&[\"panic-abort-tests\"])\n        .with_status(0)\n        .run();\n}\n\n#[cargo_test]\nfn bin_env_for_test() {\n    // Test for the `CARGO_BIN_EXE_` environment variables for tests.\n    //\n    // Note: The Unicode binary uses a `[[bin]]` definition because different\n    // filesystems normalize utf-8 in different ways. For example, HFS uses\n    // \"gru\\u{308}ßen\" and APFS uses \"gr\\u{fc}ßen\". Defining it in TOML forces\n    // one form to be used.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2018\"\n\n                [[bin]]\n                name = 'grüßen'\n                path = 'src/bin/grussen.rs'\n            \"#,\n        )\n        .file(\"src/bin/foo.rs\", \"fn main() {}\")\n        .file(\"src/bin/with-dash.rs\", \"fn main() {}\")\n        .file(\"src/bin/grussen.rs\", \"fn main() {}\")\n        .file(\n            \"src/lib.rs\",\n            r#\"\n            //! ```\n            //! assert_eq!(option_env!(\"CARGO_BIN_EXE_foo\"), None);\n            //! assert_eq!(option_env!(\"CARGO_BIN_EXE_with-dash\"), None);\n            //! assert_eq!(option_env!(\"CARGO_BIN_EXE_grüßen\"), None);\n            //! assert_eq!(std::env::var(\"CARGO_BIN_EXE_foo\").ok(), None);\n            //! assert_eq!(std::env::var(\"CARGO_BIN_EXE_with-dash\").ok(), None);\n            //! assert_eq!(std::env::var(\"CARGO_BIN_EXE_grüßen\").ok(), None);\n            //! ```\n\n            #[test]\n            fn no_bins() {\n                assert_eq!(option_env!(\"CARGO_BIN_EXE_foo\"), None);\n                assert_eq!(option_env!(\"CARGO_BIN_EXE_with-dash\"), None);\n                assert_eq!(option_env!(\"CARGO_BIN_EXE_grüßen\"), None);\n                assert_eq!(std::env::var(\"CARGO_BIN_EXE_foo\").ok(), None);\n                assert_eq!(std::env::var(\"CARGO_BIN_EXE_with-dash\").ok(), None);\n                assert_eq!(std::env::var(\"CARGO_BIN_EXE_grüßen\").ok(), None);\n            }\n\"#,\n        )\n        .build();\n\n    let bin_path = |name| p.bin(name).to_string_lossy().replace(\"\\\\\", \"\\\\\\\\\");\n    p.change_file(\n        \"tests/check_env.rs\",\n        &r#\"\n            #[test]\n            fn run_bins() {\n                assert_eq!(env!(\"CARGO_BIN_EXE_foo\"), \"<FOO_PATH>\");\n                assert_eq!(env!(\"CARGO_BIN_EXE_with-dash\"), \"<WITH_DASH_PATH>\");\n                assert_eq!(env!(\"CARGO_BIN_EXE_grüßen\"), \"<GRÜSSEN_PATH>\");\n                assert_eq!(std::env::var(\"CARGO_BIN_EXE_foo\").ok().as_deref(), Some(\"<FOO_PATH>\"));\n                assert_eq!(std::env::var(\"CARGO_BIN_EXE_with-dash\").ok().as_deref(), Some(\"<WITH_DASH_PATH>\"));\n                assert_eq!(std::env::var(\"CARGO_BIN_EXE_grüßen\").ok().as_deref(), Some(\"<GRÜSSEN_PATH>\"));\n            }\n        \"#\n        .replace(\"<FOO_PATH>\", &bin_path(\"foo\"))\n        .replace(\"<WITH_DASH_PATH>\", &bin_path(\"with-dash\"))\n        .replace(\"<GRÜSSEN_PATH>\", &bin_path(\"grüßen\")),\n    );\n\n    p.cargo(\"test\").run();\n    p.cargo(\"check --all-targets\").run();\n}\n\n#[cargo_test]\nfn test_workspaces_cwd() {\n    // This tests that all the different test types are executed from the\n    // crate directory (manifest_dir), and not from the workspace root.\n\n    let make_lib_file = |expected| {\n        format!(\n            r#\"\n                //! ```\n                //! assert_eq!(\"{expected}\", std::fs::read_to_string(\"file.txt\").unwrap());\n                //! assert_eq!(\"{expected}\", include_str!(\"../file.txt\"));\n                //! assert_eq!(\n                //!     std::path::PathBuf::from(std::env!(\"CARGO_MANIFEST_DIR\")),\n                //!     std::env::current_dir().unwrap(),\n                //! );\n                //! ```\n\n                #[test]\n                fn test_unit_{expected}_cwd() {{\n                    assert_eq!(\"{expected}\", std::fs::read_to_string(\"file.txt\").unwrap());\n                    assert_eq!(\"{expected}\", include_str!(\"../file.txt\"));\n                    assert_eq!(\n                        std::path::PathBuf::from(std::env!(\"CARGO_MANIFEST_DIR\")),\n                        std::env::current_dir().unwrap(),\n                    );\n                }}\n            \"#,\n            expected = expected\n        )\n    };\n    let make_test_file = |expected| {\n        format!(\n            r#\"\n                #[test]\n                fn test_integration_{expected}_cwd() {{\n                    assert_eq!(\"{expected}\", std::fs::read_to_string(\"file.txt\").unwrap());\n                    assert_eq!(\"{expected}\", include_str!(\"../file.txt\"));\n                    assert_eq!(\n                        std::path::PathBuf::from(std::env!(\"CARGO_MANIFEST_DIR\")),\n                        std::env::current_dir().unwrap(),\n                    );\n                }}\n            \"#,\n            expected = expected\n        )\n    };\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"root-crate\"\n                version = \"0.0.0\"\n\n                [workspace]\n                members = [\".\", \"nested-crate\", \"very/deeply/nested/deep-crate\"]\n            \"#,\n        )\n        .file(\"file.txt\", \"root\")\n        .file(\"src/lib.rs\", &make_lib_file(\"root\"))\n        .file(\"tests/integration.rs\", &make_test_file(\"root\"))\n        .file(\n            \"nested-crate/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"nested-crate\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"nested-crate/file.txt\", \"nested\")\n        .file(\"nested-crate/src/lib.rs\", &make_lib_file(\"nested\"))\n        .file(\n            \"nested-crate/tests/integration.rs\",\n            &make_test_file(\"nested\"),\n        )\n        .file(\n            \"very/deeply/nested/deep-crate/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"deep-crate\"\n                version = \"0.0.0\"\n            \"#,\n        )\n        .file(\"very/deeply/nested/deep-crate/file.txt\", \"deep\")\n        .file(\n            \"very/deeply/nested/deep-crate/src/lib.rs\",\n            &make_lib_file(\"deep\"),\n        )\n        .file(\n            \"very/deeply/nested/deep-crate/tests/integration.rs\",\n            &make_test_file(\"deep\"),\n        )\n        .build();\n\n    p.cargo(\"test --workspace --all\")\n        .with_stderr_data(\n            str![[r#\"\n[DOCTEST] root_crate\n[DOCTEST] nested_crate\n[DOCTEST] deep_crate\n...\n\"#]]\n            .unordered(),\n        )\n        .with_stdout_data(\n            str![[r#\"\ntest test_unit_root_cwd ... ok\ntest test_unit_nested_cwd ... ok\ntest test_unit_deep_cwd ... ok\ntest test_integration_root_cwd ... ok\ntest test_integration_nested_cwd ... ok\ntest test_integration_deep_cwd ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"test -p root-crate --all\")\n        .with_stderr_data(str![[r#\"\n...\n[DOCTEST] root_crate\n...\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest test_unit_root_cwd ... ok\ntest test_integration_root_cwd ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"test -p nested-crate --all\")\n        .with_stderr_data(str![[r#\"\n...\n[DOCTEST] nested_crate\n...\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest test_unit_nested_cwd ... ok\ntest test_integration_nested_cwd ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"test -p deep-crate --all\")\n        .with_stderr_data(str![[r#\"\n...\n[DOCTEST] deep_crate\n...\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest test_unit_deep_cwd ... ok\ntest test_integration_deep_cwd ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"test --all\")\n        .cwd(\"nested-crate\")\n        .with_stderr_data(str![[r#\"\n...\n[DOCTEST] nested_crate\n...\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest test_unit_nested_cwd ... ok\ntest test_integration_nested_cwd ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n\n    p.cargo(\"test --all\")\n        .cwd(\"very/deeply/nested/deep-crate\")\n        .with_stderr_data(str![[r#\"\n...\n[DOCTEST] deep_crate\n...\n\"#]])\n        .with_stdout_data(\n            str![[r#\"\ntest test_unit_deep_cwd ... ok\ntest test_integration_deep_cwd ... ok\n...\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn execution_error() {\n    // Checks the behavior when a test fails to launch.\n    let p = project()\n        .file(\n            \"tests/t1.rs\",\n            r#\"\n                #[test]\n                fn foo() {}\n            \"#,\n        )\n        .build();\n    let key = format!(\"CARGO_TARGET_{}_RUNNER\", rustc_host_env());\n    p.cargo(\"test\")\n        .env(&key, \"does_not_exist\")\n        // The actual error is usually \"no such file\", but on Windows it has a\n        // custom message. Since matching against the error string produced by\n        // Rust is not very reliable, this just uses `[..]`.\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/t1.rs (target/debug/deps/t1-[HASH][EXE])\n[ERROR] test failed, to rerun pass `--test t1`\n\nCaused by:\n  could not execute process `does_not_exist [ROOT]/foo/target/debug/deps/t1-[HASH][EXE]` (never executed)\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn nonzero_exit_status() {\n    // Tests for nonzero exit codes from tests.\n    let p = project()\n        .file(\n            \"tests/t1.rs\",\n            r#\"\n                #[test]\n                fn t() { panic!(\"this is a normal error\") }\n            \"#,\n        )\n        .file(\n            \"tests/t2.rs\",\n            r#\"\n                #[test]\n                fn t() { std::process::exit(4) }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test --test t1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/t1.rs (target/debug/deps/t1-[HASH][EXE])\n[ERROR] test failed, to rerun pass `--test t1`\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n...\nthis is a normal error\n...\n\"#]])\n        .with_status(101)\n        .run();\n\n    p.cargo(\"test --test t2\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/t2.rs (target/debug/deps/t2-[HASH][EXE])\n[ERROR] test failed, to rerun pass `--test t2`\n\nCaused by:\n  process didn't exit successfully: `[ROOT]/foo/target/debug/deps/t2-[HASH][EXE]` ([EXIT_STATUS]: 4)\n[NOTE] test exited abnormally; to see the full output pass --no-capture to the harness.\n\n\"#]])\n        .with_status(4)\n        .run();\n\n    p.cargo(\"test --test t2 -- --no-capture\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/t2.rs (target/debug/deps/t2-[HASH][EXE])\n[ERROR] test failed, to rerun pass `--test t2`\n\nCaused by:\n  process didn't exit successfully: `[ROOT]/foo/target/debug/deps/t2-[HASH][EXE] --no-capture` ([EXIT_STATUS]: 4)\n\n\"#]])\n        .with_status(4)\n        .run();\n\n    // no-fail-fast always uses 101\n    p.cargo(\"test --no-fail-fast\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] tests/t1.rs (target/debug/deps/t1-[HASH][EXE])\n[ERROR] test failed, to rerun pass `--test t1`\n[RUNNING] tests/t2.rs (target/debug/deps/t2-[HASH][EXE])\n[ERROR] test failed, to rerun pass `--test t2`\n\nCaused by:\n  process didn't exit successfully: `[ROOT]/foo/target/debug/deps/t2-[HASH][EXE]` ([EXIT_STATUS]: 4)\n[NOTE] test exited abnormally; to see the full output pass --no-capture to the harness.\n[ERROR] 2 targets failed:\n    `--test t1`\n    `--test t2`\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    p.cargo(\"test --no-fail-fast -- --no-capture\")\n        .with_stderr_does_not_contain(\n            \"test exited abnormally; to see the full output pass --no-capture to the harness.\",\n        )\n        .with_stderr_data(str![[r#\"\n[..]thread [..]panicked [..] tests/t1.rs[..]\n[NOTE] run with `RUST_BACKTRACE=1` environment variable to display a backtrace\nCaused by:\n  process didn't exit successfully: `[ROOT]/foo/target/debug/deps/t2-[HASH][EXE] --no-capture` ([EXIT_STATUS]: 4)\n...\n\"#]].unordered())\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn cargo_test_print_env_verbose() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_manifest(\"foo\", \"0.0.1\"))\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"test -vv\").with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] rustc --crate-name foo[..]`\n[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] rustc --crate-name foo[..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] [ROOT]/foo/target/debug/deps/foo-[HASH][EXE]`\n[DOCTEST] foo\n[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] rustdoc --edition=2015 --crate-type lib --color auto --crate-name foo[..]`\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn cargo_test_set_out_dir_env_var() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn add(left: u64, right: u64) -> u64 {\n                    left + right\n                }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {}\n            \"#,\n        )\n        .file(\n            \"tests/case.rs\",\n            r#\"\n                #[cfg(test)]\n                pub mod tests {\n                    #[test]\n                    fn test_add() {\n                        assert!(std::env::var(\"OUT_DIR\").is_ok());\n                        assert_eq!(foo::add(2, 5), 7);\n                    }\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"test\").run();\n    p.cargo(\"test --package foo --test case -- tests::test_add --exact --no-capture\")\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/timings.rs",
    "content": "//! Tests for --timings.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn timings_works() {\n    Package::new(\"dep\", \"0.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            dep = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"tests/t1.rs\", \"\")\n        .file(\"examples/ex1.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"build --all-targets --timings\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`)\n[COMPILING] dep v0.1.0\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n      Timing report saved to [ROOT]/foo/target/cargo-timings/cargo-timing-[..].html\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"clean\").run();\n\n    p.cargo(\"test --timings\").run();\n\n    p.cargo(\"clean\").run();\n\n    p.cargo(\"check --timings\").run();\n\n    p.cargo(\"clean\").run();\n\n    p.cargo(\"doc --timings\").run();\n}\n"
  },
  {
    "path": "tests/testsuite/tool_paths.rs",
    "content": "//! Tests for configuration values that point to programs.\n\nuse crate::prelude::*;\nuse cargo_test_support::{basic_lib_manifest, project, rustc_host, rustc_host_env, str};\n\n#[cargo_test]\nfn pathless_tools() {\n    let target = rustc_host();\n\n    let foo = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}]\n                    linker = \"nonexistent-linker\"\n                \"#,\n                target\n            ),\n        )\n        .build();\n\n    foo.cargo(\"build --verbose\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]-C linker=nonexistent-linker [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n// can set a custom linker via `target.'cfg(..)'.linker`\n#[cargo_test]\nfn custom_linker_cfg() {\n    let foo = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [target.'cfg(not(target_os = \"none\"))']\n            linker = \"nonexistent-linker\"\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"build --verbose\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]-C linker=nonexistent-linker [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n// custom linker set via `target.$triple.linker` have precede over `target.'cfg(..)'.linker`\n#[cargo_test]\nfn custom_linker_cfg_precedence() {\n    let target = rustc_host();\n\n    let foo = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.'cfg(not(target_os = \"none\"))']\n                    linker = \"ignored-linker\"\n                    [target.{}]\n                    linker = \"nonexistent-linker\"\n                \"#,\n                target\n            ),\n        )\n        .build();\n\n    foo.cargo(\"build --verbose\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]-C linker=nonexistent-linker [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_linker_cfg_collision() {\n    let foo = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [target.'cfg(not(target_arch = \"avr\"))']\n            linker = \"nonexistent-linker1\"\n            [target.'cfg(not(target_os = \"none\"))']\n            linker = \"nonexistent-linker2\"\n            \"#,\n        )\n        .build();\n\n    foo.cargo(\"build --verbose\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] several matching instances of `target.'cfg(..)'.linker` in configurations\nfirst match `cfg(not(target_arch = \"avr\"))` located in [ROOT]/foo/.cargo/config.toml\nsecond match `cfg(not(target_os = \"none\"))` located in [ROOT]/foo/.cargo/config.toml\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn absolute_tools() {\n    let target = rustc_host();\n\n    // Escaped as they appear within a TOML config file\n    let linker = if cfg!(windows) {\n        r#\"C:\\\\bogus\\\\nonexistent-linker\"#\n    } else {\n        r#\"/bogus/nonexistent-linker\"#\n    };\n\n    let foo = project()\n        .file(\"Cargo.toml\", &basic_lib_manifest(\"foo\"))\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{target}]\n                    linker = \"{linker}\"\n                \"#,\n                target = target,\n                linker = linker\n            ),\n        )\n        .build();\n\n    foo.cargo(\"build --verbose\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.5.0 ([ROOT]/foo)\n[RUNNING] `rustc [..]-C linker=[..]/bogus/nonexistent-linker [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn relative_tools() {\n    let target = rustc_host();\n\n    // Escaped as they appear within a TOML config file\n    let linker = if cfg!(windows) {\n        r#\".\\\\tools\\\\nonexistent-linker\"#\n    } else {\n        r#\"./tools/nonexistent-linker\"#\n    };\n\n    // Funky directory structure to test that relative tool paths are made absolute\n    // by reference to the `.cargo/..` directory and not to (for example) the CWD.\n    let p = project()\n        .no_manifest()\n        .file(\"bar/Cargo.toml\", &basic_lib_manifest(\"bar\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{target}]\n                    linker = \"{linker}\"\n                \"#,\n                target = target,\n                linker = linker\n            ),\n        )\n        .build();\n\n    p.cargo(\"build --verbose\")\n        .cwd(\"bar\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] bar v0.5.0 ([ROOT]/foo/bar)\n[RUNNING] `rustc [..]-C linker=[ROOT]/foo/./tools/nonexistent-linker [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_runner() {\n    let target = rustc_host();\n\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"tests/test.rs\", \"\")\n        .file(\"benches/bench.rs\", \"\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}]\n                    runner = \"nonexistent-runner -r\"\n                \"#,\n                target\n            ),\n        )\n        .build();\n\n    p.cargo(\"run -- --param\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`\n...\n\"#]])\n        .run();\n\n    p.cargo(\"test --test test --verbose -- --param\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `nonexistent-runner -r [ROOT]/foo/target/debug/deps/test-[HASH][EXE] --param`\n...\n\"#]])\n        .run();\n\n    p.cargo(\"bench --bench bench --verbose -- --param\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]`\n[RUNNING] `rustc [..]`\n[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s\n[RUNNING] `nonexistent-runner -r [ROOT]/foo/target/release/deps/bench-[HASH][EXE] --param --bench`\n...\n\"#]])\n        .run();\n}\n\n// can set a custom runner via `target.'cfg(..)'.runner`\n#[cargo_test]\nfn custom_runner_cfg() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [target.'cfg(not(target_os = \"none\"))']\n            runner = \"nonexistent-runner -r\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run -- --param\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`\n...\n\"#]])\n        .run();\n}\n\n// custom runner set via `target.$triple.runner` have precedence over `target.'cfg(..)'.runner`\n#[cargo_test]\nfn custom_runner_cfg_precedence() {\n    let target = rustc_host();\n\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.'cfg(not(target_os = \"none\"))']\n                    runner = \"ignored-runner\"\n\n                    [target.{}]\n                    runner = \"nonexistent-runner -r\"\n                \"#,\n                target\n            ),\n        )\n        .build();\n\n    p.cargo(\"run -- --param\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_runner_cfg_collision() {\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            [target.'cfg(not(target_arch = \"avr\"))']\n            runner = \"true\"\n\n            [target.'cfg(not(target_os = \"none\"))']\n            runner = \"false\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run -- --param\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] several matching instances of `target.'cfg(..)'.runner` in configurations\nfirst match `cfg(not(target_arch = \"avr\"))` located in [ROOT]/foo/.cargo/config.toml\nsecond match `cfg(not(target_os = \"none\"))` located in [ROOT]/foo/.cargo/config.toml\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_runner_env() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    let key = format!(\"CARGO_TARGET_{}_RUNNER\", rustc_host_env());\n\n    p.cargo(\"run\")\n        .env(&key, \"nonexistent-runner --foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `nonexistent-runner --foo target/debug/foo[EXE]`\n[ERROR] could not execute process `nonexistent-runner --foo target/debug/foo[EXE]` (never executed)\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_runner_env_overrides_config() {\n    let target = rustc_host();\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}]\n                    runner = \"should-not-run -r\"\n                \"#,\n                target\n            ),\n        )\n        .build();\n\n    let key = format!(\"CARGO_TARGET_{}_RUNNER\", rustc_host_env());\n\n    p.cargo(\"run\")\n        .env(&key, \"should-run --foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\n[RUNNING] `should-run --foo target/debug/foo[EXE]`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\n#[cfg(unix)] // Assumes `true` is in PATH.\nfn custom_runner_env_true() {\n    // Check for a bug where \"true\" was interpreted as a boolean instead of\n    // the executable.\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    let key = format!(\"CARGO_TARGET_{}_RUNNER\", rustc_host_env());\n\n    p.cargo(\"run\")\n        .env(&key, \"true\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `true target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_runner_target_applies_to_host() {\n    // This ensures that without `--target` (non-cross-target mode)\n    // Cargo still respects targe configuration.\n    let target = rustc_host();\n\n    let p = project()\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \".cargo/config.toml\",\n            &format!(\n                r#\"\n                    [target.{}]\n                    runner = \"nonexistent-runner -r\"\n                \"#,\n                target\n            ),\n        )\n        .build();\n\n    p.cargo(\"run -Z target-applies-to-host\")\n        .masquerade_as_nightly_cargo(&[\"target-applies-to-host\"])\n        .env(\"CARGO_TARGET_APPLIES_TO_HOST\", \"false\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `nonexistent-runner -r target/debug/foo[EXE]`\n[ERROR] could not execute process `nonexistent-runner -r target/debug/foo[EXE]` (never executed)\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn custom_linker_env() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    let key = format!(\"CARGO_TARGET_{}_LINKER\", rustc_host_env());\n\n    p.cargo(\"build -v\")\n        .env(&key, \"nonexistent-linker\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc [..]-C linker=nonexistent-linker [..]`\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn target_in_environment_contains_lower_case() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n\n    let target = rustc_host();\n    let env_key = format!(\n        \"CARGO_TARGET_{}_LINKER\",\n        target.to_lowercase().replace('-', \"_\")\n    );\n\n    p.cargo(\"build -v --target\")\n        .arg(target)\n        .env(&env_key, \"nonexistent-linker\")\n        .with_stderr_data(format!(\"\\\n[WARNING] environment variables are expected to use uppercase letters and underscores, the variable `{env_key}` will be ignored and have no effect\n[WARNING] environment variables are expected to use uppercase letters and underscores, the variable `{env_key}` will be ignored and have no effect\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\"\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn cfg_ignored_fields() {\n    // Test for some ignored fields in [target.'cfg()'] tables.\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n            # Try some empty tables.\n            [target.'cfg(not(foo))']\n            [target.'cfg(not(bar))'.somelib]\n\n            # A bunch of unused fields.\n            [target.'cfg(not(target_os = \"none\"))']\n            linker = 'false'\n            ar = 'false'\n            foo = {rustc-flags = \"-l foo\"}\n            invalid = 1\n            runner = 'false'\n            rustflags = ''\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused key `somelib` in [target] config table `cfg(not(bar))`\n[WARNING] unused key `ar` in [target] config table `cfg(not(target_os = \"none\"))`\n[WARNING] unused key `foo` in [target] config table `cfg(not(target_os = \"none\"))`\n[WARNING] unused key `invalid` in [target] config table `cfg(not(target_os = \"none\"))`\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/unit_graph.rs",
    "content": "//! Tests for --unit-graph option.\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\n\n#[cargo_test]\nfn gated() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n    p.cargo(\"build --unit-graph\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `--unit-graph` flag is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel\nSee https://doc.rust-lang.org/book/[..].html for more information about Rust release channels.\nSee https://github.com/rust-lang/cargo/issues/8002 for more information about the `--unit-graph` flag.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple() {\n    Package::new(\"a\", \"1.0.0\")\n        .dep(\"b\", \"1.0\")\n        .feature(\"feata\", &[\"b/featb\"])\n        .publish();\n    Package::new(\"b\", \"1.0.0\")\n        .dep(\"c\", \"1.0\")\n        .feature(\"featb\", &[\"c/featc\"])\n        .publish();\n    Package::new(\"c\", \"1.0.0\").feature(\"featc\", &[]).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            a = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"build --features a/feata --unit-graph -Zunstable-options\")\n        .masquerade_as_nightly_cargo(&[\"unit-graph\"])\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"roots\": [\n    3\n  ],\n  \"units\": [\n    {\n      \"dependencies\": [\n        {\n          \"extern_crate_name\": \"b\",\n          \"index\": 1,\n          \"noprelude\": false,\n          \"nounused\": false,\n          \"public\": false\n        }\n      ],\n      \"features\": [\n        \"feata\"\n      ],\n      \"mode\": \"build\",\n      \"pkg_id\": \"registry+https://github.com/rust-lang/crates.io-index#a@1.0.0\",\n      \"platform\": null,\n      \"profile\": {\n        \"codegen_backend\": null,\n        \"codegen_units\": null,\n        \"debug_assertions\": true,\n        \"debuginfo\": 2,\n        \"incremental\": false,\n        \"lto\": \"false\",\n        \"name\": \"dev\",\n        \"opt_level\": \"0\",\n        \"overflow_checks\": true,\n        \"panic\": \"unwind\",\n        \"rpath\": false,\n        \"split_debuginfo\": \"{...}\",\n        \"strip\": \"{...}\"\n      },\n      \"target\": {\n        \"crate_types\": [\n          \"lib\"\n        ],\n        \"doc\": true,\n        \"doctest\": true,\n        \"edition\": \"2015\",\n        \"kind\": [\n          \"lib\"\n        ],\n        \"name\": \"a\",\n        \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/a-1.0.0/src/lib.rs\",\n        \"test\": true\n      }\n    },\n    {\n      \"dependencies\": [\n        {\n          \"extern_crate_name\": \"c\",\n          \"index\": 2,\n          \"noprelude\": false,\n          \"nounused\": false,\n          \"public\": false\n        }\n      ],\n      \"features\": [\n        \"featb\"\n      ],\n      \"mode\": \"build\",\n      \"pkg_id\": \"registry+https://github.com/rust-lang/crates.io-index#b@1.0.0\",\n      \"platform\": null,\n      \"profile\": {\n        \"codegen_backend\": null,\n        \"codegen_units\": null,\n        \"debug_assertions\": true,\n        \"debuginfo\": 2,\n        \"incremental\": false,\n        \"lto\": \"false\",\n        \"name\": \"dev\",\n        \"opt_level\": \"0\",\n        \"overflow_checks\": true,\n        \"panic\": \"unwind\",\n        \"rpath\": false,\n        \"split_debuginfo\": \"{...}\",\n        \"strip\": \"{...}\"\n      },\n      \"target\": {\n        \"crate_types\": [\n          \"lib\"\n        ],\n        \"doc\": true,\n        \"doctest\": true,\n        \"edition\": \"2015\",\n        \"kind\": [\n          \"lib\"\n        ],\n        \"name\": \"b\",\n        \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/b-1.0.0/src/lib.rs\",\n        \"test\": true\n      }\n    },\n    {\n      \"dependencies\": [],\n      \"features\": [\n        \"featc\"\n      ],\n      \"mode\": \"build\",\n      \"pkg_id\": \"registry+https://github.com/rust-lang/crates.io-index#c@1.0.0\",\n      \"platform\": null,\n      \"profile\": {\n        \"codegen_backend\": null,\n        \"codegen_units\": null,\n        \"debug_assertions\": true,\n        \"debuginfo\": 2,\n        \"incremental\": false,\n        \"lto\": \"false\",\n        \"name\": \"dev\",\n        \"opt_level\": \"0\",\n        \"overflow_checks\": true,\n        \"panic\": \"unwind\",\n        \"rpath\": false,\n        \"split_debuginfo\": \"{...}\",\n        \"strip\": \"{...}\"\n      },\n      \"target\": {\n        \"crate_types\": [\n          \"lib\"\n        ],\n        \"doc\": true,\n        \"doctest\": true,\n        \"edition\": \"2015\",\n        \"kind\": [\n          \"lib\"\n        ],\n        \"name\": \"c\",\n        \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/c-1.0.0/src/lib.rs\",\n        \"test\": true\n      }\n    },\n    {\n      \"dependencies\": [\n        {\n          \"extern_crate_name\": \"a\",\n          \"index\": 0,\n          \"noprelude\": false,\n          \"nounused\": false,\n          \"public\": false\n        }\n      ],\n      \"features\": [],\n      \"mode\": \"build\",\n      \"pkg_id\": \"path+[ROOTURL]/foo#0.1.0\",\n      \"platform\": null,\n      \"profile\": {\n        \"codegen_backend\": null,\n        \"codegen_units\": null,\n        \"debug_assertions\": true,\n        \"debuginfo\": 2,\n        \"incremental\": false,\n        \"lto\": \"false\",\n        \"name\": \"dev\",\n        \"opt_level\": \"0\",\n        \"overflow_checks\": true,\n        \"panic\": \"unwind\",\n        \"rpath\": false,\n        \"split_debuginfo\": \"{...}\",\n        \"strip\": \"{...}\"\n      },\n      \"target\": {\n        \"crate_types\": [\n          \"lib\"\n        ],\n        \"doc\": true,\n        \"doctest\": true,\n        \"edition\": \"2015\",\n        \"kind\": [\n          \"lib\"\n        ],\n        \"name\": \"foo\",\n        \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n        \"test\": true\n      }\n    }\n  ],\n  \"version\": 1\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/update.rs",
    "content": "//! Tests for the `cargo update` command.\n\nuse crate::prelude::*;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::registry::{self};\nuse cargo_test_support::registry::{Dependency, Package};\nuse cargo_test_support::{basic_lib_manifest, basic_manifest, git, project, str};\n\n#[cargo_test]\nfn minor_update_two_places() {\n    Package::new(\"log\", \"0.1.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                log = \"0.1\"\n                foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                log = \"0.1\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n    Package::new(\"log\", \"0.1.1\").publish();\n\n    p.change_file(\n        \"foo/Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.0.1\"\n            edition = \"2015\"\n            authors = []\n\n            [dependencies]\n            log = \"0.1.1\"\n        \"#,\n    );\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn transitive_minor_update() {\n    Package::new(\"log\", \"0.1.0\").publish();\n    Package::new(\"serde\", \"0.1.0\").dep(\"log\", \"0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"0.1\"\n                log = \"0.1\"\n                foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"0.1\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    Package::new(\"log\", \"0.1.1\").publish();\n    Package::new(\"serde\", \"0.1.1\").dep(\"log\", \"0.1.1\").publish();\n\n    // Note that `serde` isn't actually updated here! The default behavior for\n    // `update` right now is to as conservatively as possible attempt to satisfy\n    // an update. In this case we previously locked the dependency graph to `log\n    // 0.1.0`, but nothing on the command line says we're allowed to update\n    // that. As a result the update of `serde` here shouldn't update to `serde\n    // 0.1.1` as that would also force an update to `log 0.1.1`.\n    //\n    // Also note that this is probably counterintuitive and weird. We may wish\n    // to change this one day.\n    p.cargo(\"update serde\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 0 packages to latest compatible versions\n[NOTE] pass `--verbose` to see 2 unchanged dependencies behind latest\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn conservative() {\n    Package::new(\"log\", \"0.1.0\").publish();\n    Package::new(\"serde\", \"0.1.0\").dep(\"log\", \"0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"0.1\"\n                log = \"0.1\"\n                foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"0.1\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    Package::new(\"log\", \"0.1.1\").publish();\n    Package::new(\"serde\", \"0.1.1\").dep(\"log\", \"0.1\").publish();\n\n    p.cargo(\"update serde\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] serde v0.1.0 -> v0.1.1\n[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_via_new_dep() {\n    Package::new(\"log\", \"0.1.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                log = \"0.1\"\n                # foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                log = \"0.1.1\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n    Package::new(\"log\", \"0.1.1\").publish();\n\n    p.uncomment_root_manifest();\n    p.cargo(\"check\").env(\"CARGO_LOG\", \"cargo=trace\").run();\n}\n\n#[cargo_test]\nfn update_via_new_member() {\n    Package::new(\"log\", \"0.1.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                # members = [ \"foo\" ]\n\n                [dependencies]\n                log = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                log = \"0.1.1\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n    Package::new(\"log\", \"0.1.1\").publish();\n\n    p.uncomment_root_manifest();\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn add_dep_deep_new_requirement() {\n    Package::new(\"log\", \"0.1.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                log = \"0.1\"\n                # bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    Package::new(\"log\", \"0.1.1\").publish();\n    Package::new(\"bar\", \"0.1.0\").dep(\"log\", \"0.1.1\").publish();\n\n    p.uncomment_root_manifest();\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn everything_real_deep() {\n    Package::new(\"log\", \"0.1.0\").publish();\n    Package::new(\"foo\", \"0.1.0\").dep(\"log\", \"0.1\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = \"0.1\"\n                # bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    Package::new(\"log\", \"0.1.1\").publish();\n    Package::new(\"bar\", \"0.1.0\").dep(\"log\", \"0.1.1\").publish();\n\n    p.uncomment_root_manifest();\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn change_package_version() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a-foo\"\n                version = \"0.2.0-alpha\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\", version = \"0.2.0-alpha\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.2.0-alpha\"))\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"Cargo.lock\",\n            r#\"\n                [[package]]\n                name = \"foo\"\n                version = \"0.2.0\"\n                dependencies = [\"bar 0.2.0\"]\n\n                [[package]]\n                name = \"bar\"\n                version = \"0.2.0\"\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn update_precise() {\n    Package::new(\"serde\", \"0.1.0\").publish();\n    Package::new(\"serde\", \"0.2.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"0.2\"\n                foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"0.1\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    Package::new(\"serde\", \"0.2.0\").publish();\n\n    p.cargo(\"update serde:0.2.1 --precise 0.2.0\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNGRADING] serde v0.2.1 -> v0.2.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_precise_mismatched() {\n    Package::new(\"serde\", \"1.2.0\").publish();\n    Package::new(\"serde\", \"1.2.1\").publish();\n    Package::new(\"serde\", \"1.6.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"~1.2\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    // `1.6.0` does not match `\"~1.2\"`\n    p.cargo(\"update serde:1.2 --precise 1.6.0\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] failed to select a version for the requirement `serde = \"~1.2\"`\ncandidate versions found which didn't match: 1.6.0\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `bar v0.0.1 ([ROOT]/foo)`\nperhaps a crate was updated and forgotten to be re-vendored?\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    // `1.9.0` does not exist\n    p.cargo(\"update serde:1.2 --precise 1.9.0\")\n        // This terrible error message has been the same for a long time. A fix is more than welcome!\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package named `serde` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `bar v0.0.1 ([ROOT]/foo)`\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn update_precise_build_metadata() {\n    Package::new(\"serde\", \"0.0.1+first\").publish();\n    Package::new(\"serde\", \"0.0.1+second\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                serde = \"0.0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n    p.cargo(\"update serde --precise 0.0.1+first\").run();\n\n    p.cargo(\"update serde --precise 0.0.1+second\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] serde v0.0.1+first -> v0.0.1+second\n\n\"#]])\n        .run();\n\n    // This is not considered \"Downgrading\". Build metadata are not assumed to\n    // be ordered.\n    p.cargo(\"update serde --precise 0.0.1+first\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] serde v0.0.1+second -> v0.0.1+first\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_precise_do_not_force_update_deps() {\n    Package::new(\"log\", \"0.1.0\").publish();\n    Package::new(\"serde\", \"0.2.1\").dep(\"log\", \"0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"0.2\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    Package::new(\"log\", \"0.1.1\").publish();\n    Package::new(\"serde\", \"0.2.2\").dep(\"log\", \"0.1\").publish();\n\n    p.cargo(\"update serde:0.2.1 --precise 0.2.2\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] serde v0.2.1 -> v0.2.2\n[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_recursive() {\n    Package::new(\"log\", \"0.1.0\").publish();\n    Package::new(\"serde\", \"0.2.1\").dep(\"log\", \"0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"0.2\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    Package::new(\"log\", \"0.1.1\").publish();\n    Package::new(\"serde\", \"0.2.2\").dep(\"log\", \"0.1\").publish();\n\n    p.cargo(\"update serde:0.2.1 --recursive\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] log v0.1.0 -> v0.1.1\n[UPDATING] serde v0.2.1 -> v0.2.2\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_aggressive_alias_for_recursive() {\n    Package::new(\"log\", \"0.1.0\").publish();\n    Package::new(\"serde\", \"0.2.1\").dep(\"log\", \"0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"0.2\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    Package::new(\"log\", \"0.1.1\").publish();\n    Package::new(\"serde\", \"0.2.2\").dep(\"log\", \"0.1\").publish();\n\n    p.cargo(\"update serde:0.2.1 --aggressive\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] log v0.1.0 -> v0.1.1\n[UPDATING] serde v0.2.1 -> v0.2.2\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_recursive_conflicts_with_precise() {\n    Package::new(\"log\", \"0.1.0\").publish();\n    Package::new(\"serde\", \"0.2.1\").dep(\"log\", \"0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"0.2\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n\n    Package::new(\"log\", \"0.1.1\").publish();\n    Package::new(\"serde\", \"0.2.2\").dep(\"log\", \"0.1\").publish();\n\n    p.cargo(\"update serde:0.2.1 --precise 0.2.2 --recursive\")\n        .with_status(1)\n        .with_stderr_data(str![[r#\"\n[ERROR] the argument '--precise <PRECISE>' cannot be used with '--recursive'\n\nUsage: cargo[EXE] update --precise <PRECISE> <SPEC|--package [<SPEC>]>\n\nFor more information, try '--help'.\n\n\"#]])\n        .run();\n}\n\n// cargo update should respect its arguments even without a lockfile.\n// See issue \"Running cargo update without a Cargo.lock ignores arguments\"\n// at <https://github.com/rust-lang/cargo/issues/6872>.\n#[cargo_test]\nfn update_precise_first_run() {\n    Package::new(\"serde\", \"0.1.0\").publish();\n    Package::new(\"serde\", \"0.2.0\").publish();\n    Package::new(\"serde\", \"0.2.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n\n                [dependencies]\n                serde = \"0.2\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"update serde --precise 0.2.0\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[DOWNGRADING] serde v0.2.1 -> v0.2.0\n\n\"#]])\n        .run();\n\n    // Assert `cargo metadata` shows serde 0.2.0\n    p.cargo(\"metadata\")\n        .with_stdout_data(\n            str![[r#\"\n{\n  \"metadata\": null,\n  \"packages\": [\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [\n        {\n          \"features\": [],\n          \"kind\": null,\n          \"name\": \"serde\",\n          \"optional\": false,\n          \"registry\": null,\n          \"rename\": null,\n          \"req\": \"^0.2\",\n          \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n          \"target\": null,\n          \"uses_default_features\": true\n        }\n      ],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"path+[ROOTURL]/foo#bar@0.0.1\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/foo/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"bar\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": null,\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"bar\",\n          \"src_path\": \"[ROOT]/foo/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.0.1\"\n    },\n    {\n      \"authors\": [],\n      \"categories\": [],\n      \"default_run\": null,\n      \"dependencies\": [],\n      \"description\": null,\n      \"documentation\": null,\n      \"edition\": \"2015\",\n      \"features\": {},\n      \"homepage\": null,\n      \"id\": \"registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0\",\n      \"keywords\": [],\n      \"license\": null,\n      \"license_file\": null,\n      \"links\": null,\n      \"manifest_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/serde-0.2.0/Cargo.toml\",\n      \"metadata\": null,\n      \"name\": \"serde\",\n      \"publish\": null,\n      \"readme\": null,\n      \"repository\": null,\n      \"rust_version\": null,\n      \"source\": \"registry+https://github.com/rust-lang/crates.io-index\",\n      \"targets\": [\n        {\n          \"crate_types\": [\n            \"lib\"\n          ],\n          \"doc\": true,\n          \"doctest\": true,\n          \"edition\": \"2015\",\n          \"kind\": [\n            \"lib\"\n          ],\n          \"name\": \"serde\",\n          \"src_path\": \"[ROOT]/home/.cargo/registry/src/-[HASH]/serde-0.2.0/src/lib.rs\",\n          \"test\": true\n        }\n      ],\n      \"version\": \"0.2.0\"\n    }\n  ],\n  \"resolve\": {\n    \"nodes\": [\n      {\n        \"dependencies\": [\n          \"registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0\"\n        ],\n        \"deps\": [\n          {\n            \"dep_kinds\": [\n              {\n                \"kind\": null,\n                \"target\": null\n              }\n            ],\n            \"name\": \"serde\",\n            \"pkg\": \"registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0\"\n          }\n        ],\n        \"features\": [],\n        \"id\": \"path+[ROOTURL]/foo#bar@0.0.1\"\n      },\n      {\n        \"dependencies\": [],\n        \"deps\": [],\n        \"features\": [],\n        \"id\": \"registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0\"\n      }\n    ],\n    \"root\": \"path+[ROOTURL]/foo#bar@0.0.1\"\n  },\n  \"target_directory\": \"[ROOT]/foo/target\",\n  \"build_directory\": \"[ROOT]/foo/target\",\n  \"version\": 1,\n  \"workspace_default_members\": [\n    \"path+[ROOTURL]/foo#bar@0.0.1\"\n  ],\n  \"workspace_members\": [\n    \"path+[ROOTURL]/foo#bar@0.0.1\"\n  ],\n  \"workspace_root\": \"[ROOT]/foo\"\n}\n\"#]]\n            .is_json(),\n        )\n        .run();\n\n    p.cargo(\"update serde --precise 0.2.0\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn preserve_top_comment() {\n    let p = project().file(\"src/lib.rs\", \"\").build();\n\n    p.cargo(\"update\").run();\n\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.starts_with(\"# This file is automatically @generated by Cargo.\\n# It is not intended for manual editing.\\n\"));\n\n    let mut lines = lockfile.lines().collect::<Vec<_>>();\n    lines.insert(2, \"# some other comment\");\n    let mut lockfile = lines.join(\"\\n\");\n    lockfile.push('\\n'); // .lines/.join loses the last newline\n    println!(\"saving Cargo.lock contents:\\n{}\", lockfile);\n\n    p.change_file(\"Cargo.lock\", &lockfile);\n\n    p.cargo(\"update\").run();\n\n    let lockfile2 = p.read_lockfile();\n    println!(\"loaded Cargo.lock contents:\\n{}\", lockfile2);\n\n    assert_eq!(lockfile, lockfile2);\n}\n\n#[cargo_test]\nfn dry_run_update() {\n    Package::new(\"log\", \"0.1.0\").publish();\n    Package::new(\"serde\", \"0.1.0\").dep(\"log\", \"0.1\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"0.1\"\n                log = \"0.1\"\n                foo = { path = \"foo\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                serde = \"0.1\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").run();\n    let old_lockfile = p.read_lockfile();\n\n    Package::new(\"log\", \"0.1.1\").publish();\n    Package::new(\"serde\", \"0.1.1\").dep(\"log\", \"0.1\").publish();\n\n    p.cargo(\"update serde --dry-run\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] serde v0.1.0 -> v0.1.1\n[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest\n[WARNING] not updating lockfile due to dry run\n\n\"#]])\n        .run();\n    let new_lockfile = p.read_lockfile();\n    assert_eq!(old_lockfile, new_lockfile)\n}\n\n#[cargo_test]\nfn workspace_only() {\n    let p = project().file(\"src/main.rs\", \"fn main() {}\").build();\n    p.cargo(\"generate-lockfile\").run();\n    let lock1 = p.read_lockfile();\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            authors = []\n            version = \"0.0.2\"\n            edition = \"2015\"\n        \"#,\n    );\n    p.cargo(\"update --workspace\").run();\n    let lock2 = p.read_lockfile();\n\n    assert_ne!(lock1, lock2);\n    assert!(lock1.contains(\"0.0.1\"));\n    assert!(lock2.contains(\"0.0.2\"));\n    assert!(!lock1.contains(\"0.0.2\"));\n    assert!(!lock2.contains(\"0.0.1\"));\n}\n\n#[cargo_test]\nfn precise_with_build_metadata() {\n    // +foo syntax shouldn't be necessary with --precise\n    Package::new(\"bar\", \"0.1.0+extra-stuff.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"generate-lockfile\").run();\n    Package::new(\"bar\", \"0.1.1+extra-stuff.1\").publish();\n    Package::new(\"bar\", \"0.1.2+extra-stuff.2\").publish();\n\n    p.cargo(\"update bar --precise 0.1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid version format for precise version `0.1`\n\nCaused by:\n  unexpected end of input while parsing minor version number\n\n\"#]])\n        .run();\n\n    p.cargo(\"update bar --precise 0.1.1+does-not-match\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package named `bar` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.1.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n\n    p.cargo(\"update bar --precise 0.1.1\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] bar v0.1.0+extra-stuff.0 -> v0.1.1+extra-stuff.1\n\n\"#]])\n        .run();\n\n    Package::new(\"bar\", \"0.1.3\").publish();\n    p.cargo(\"update bar --precise 0.1.3+foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] no matching package named `bar` found\nlocation searched: `dummy-registry` index (which is replacing registry `crates-io`)\nrequired by package `foo v0.1.0 ([ROOT]/foo)`\n\n\"#]])\n        .run();\n\n    p.cargo(\"update bar --precise 0.1.3\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPDATING] bar v0.1.1+extra-stuff.1 -> v0.1.3\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_only_members_order_one() {\n    let git_project = git::new(\"rustdns\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"rustdns\"))\n            .file(\"src/lib.rs\", \"pub fn bar() {}\")\n    });\n\n    let workspace_toml = format!(\n        r#\"\n[workspace.package]\nversion = \"2.29.8\"\nedition = \"2021\"\npublish = false\n\n[workspace]\nmembers = [\n    \"rootcrate\",\n    \"subcrate\",\n]\nresolver = \"2\"\n\n[workspace.dependencies]\n# Internal crates\nsubcrate = {{ version = \"*\", path = \"./subcrate\" }}\n\n# External dependencies\nrustdns = {{ version = \"0.5.0\", default-features = false, git = \"{}\" }}\n                \"#,\n        git_project.url()\n    );\n    let p = project()\n        .file(\"Cargo.toml\", &workspace_toml)\n        .file(\n            \"rootcrate/Cargo.toml\",\n            r#\"\n[package]\nname = \"rootcrate\"\nversion.workspace = true\nedition.workspace = true\npublish.workspace = true\n\n[dependencies]\nsubcrate.workspace = true\n\"#,\n        )\n        .file(\"rootcrate/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"subcrate/Cargo.toml\",\n            r#\"\n[package]\nname = \"subcrate\"\nversion.workspace = true\nedition.workspace = true\npublish.workspace = true\n\n[dependencies]\nrustdns.workspace = true\n\"#,\n        )\n        .file(\"subcrate/src/lib.rs\", \"pub foo() {}\")\n        .build();\n\n    // First time around we should compile both foo and bar\n    p.cargo(\"generate-lockfile\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/rustdns`\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n    // Modify a file manually, shouldn't trigger a recompile\n    git_project.change_file(\"src/lib.rs\", r#\"pub fn bar() { println!(\"hello!\"); }\"#);\n    // Commit the changes and make sure we don't trigger a recompile because the\n    // lock file says not to change\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    git::add(&repo);\n    git::commit(&repo);\n    p.change_file(\"Cargo.toml\", &workspace_toml.replace(\"2.29.8\", \"2.29.81\"));\n\n    p.cargo(\"update -p rootcrate\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] rootcrate v2.29.8 ([ROOT]/foo/rootcrate) -> v2.29.81\n[UPDATING] subcrate v2.29.8 ([ROOT]/foo/subcrate) -> v2.29.81\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_only_members_order_two() {\n    let git_project = git::new(\"rustdns\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"rustdns\"))\n            .file(\"src/lib.rs\", \"pub fn bar() {}\")\n    });\n\n    let workspace_toml = format!(\n        r#\"\n[workspace.package]\nversion = \"2.29.8\"\nedition = \"2021\"\npublish = false\n\n[workspace]\nmembers = [\n    \"crate2\",\n    \"crate1\",\n]\nresolver = \"2\"\n\n[workspace.dependencies]\n# Internal crates\ncrate1 = {{ version = \"*\", path = \"./crate1\" }}\n\n# External dependencies\nrustdns = {{ version = \"0.5.0\", default-features = false, git = \"{}\" }}\n                \"#,\n        git_project.url()\n    );\n    let p = project()\n        .file(\"Cargo.toml\", &workspace_toml)\n        .file(\n            \"crate2/Cargo.toml\",\n            r#\"\n[package]\nname = \"crate2\"\nversion.workspace = true\nedition.workspace = true\npublish.workspace = true\n\n[dependencies]\ncrate1.workspace = true\n\"#,\n        )\n        .file(\"crate2/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"crate1/Cargo.toml\",\n            r#\"\n[package]\nname = \"crate1\"\nversion.workspace = true\nedition.workspace = true\npublish.workspace = true\n\n[dependencies]\nrustdns.workspace = true\n\"#,\n        )\n        .file(\"crate1/src/lib.rs\", \"pub foo() {}\")\n        .build();\n\n    // First time around we should compile both foo and bar\n    p.cargo(\"generate-lockfile\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/rustdns`\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n    // Modify a file manually, shouldn't trigger a recompile\n    git_project.change_file(\"src/lib.rs\", r#\"pub fn bar() { println!(\"hello!\"); }\"#);\n    // Commit the changes and make sure we don't trigger a recompile because the\n    // lock file says not to change\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    git::add(&repo);\n    git::commit(&repo);\n    p.change_file(\"Cargo.toml\", &workspace_toml.replace(\"2.29.8\", \"2.29.81\"));\n\n    p.cargo(\"update -p crate2\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] crate1 v2.29.8 ([ROOT]/foo/crate1) -> v2.29.81\n[UPDATING] crate2 v2.29.8 ([ROOT]/foo/crate2) -> v2.29.81\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_only_members_with_workspace() {\n    let git_project = git::new(\"rustdns\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"rustdns\"))\n            .file(\"src/lib.rs\", \"pub fn bar() {}\")\n    });\n\n    let workspace_toml = format!(\n        r#\"\n[workspace.package]\nversion = \"2.29.8\"\nedition = \"2021\"\npublish = false\n\n[workspace]\nmembers = [\n    \"crate2\",\n    \"crate1\",\n]\nresolver = \"2\"\n\n[workspace.dependencies]\n# Internal crates\ncrate1 = {{ version = \"*\", path = \"./crate1\" }}\n\n# External dependencies\nrustdns = {{ version = \"0.5.0\", default-features = false, git = \"{}\" }}\n                \"#,\n        git_project.url()\n    );\n    let p = project()\n        .file(\"Cargo.toml\", &workspace_toml)\n        .file(\n            \"crate2/Cargo.toml\",\n            r#\"\n[package]\nname = \"crate2\"\nversion.workspace = true\nedition.workspace = true\npublish.workspace = true\n\n[dependencies]\ncrate1.workspace = true\n\"#,\n        )\n        .file(\"crate2/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"crate1/Cargo.toml\",\n            r#\"\n[package]\nname = \"crate1\"\nversion.workspace = true\nedition.workspace = true\npublish.workspace = true\n\n[dependencies]\nrustdns.workspace = true\n\"#,\n        )\n        .file(\"crate1/src/lib.rs\", \"pub foo() {}\")\n        .build();\n\n    // First time around we should compile both foo and bar\n    p.cargo(\"generate-lockfile\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/rustdns`\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n    // Modify a file manually, shouldn't trigger a recompile\n    git_project.change_file(\"src/lib.rs\", r#\"pub fn bar() { println!(\"hello!\"); }\"#);\n    // Commit the changes and make sure we don't trigger a recompile because the\n    // lock file says not to change\n    let repo = git2::Repository::open(&git_project.root()).unwrap();\n    git::add(&repo);\n    git::commit(&repo);\n    p.change_file(\"Cargo.toml\", &workspace_toml.replace(\"2.29.8\", \"2.29.81\"));\n\n    p.cargo(\"update --workspace\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] crate1 v2.29.8 ([ROOT]/foo/crate1) -> v2.29.81\n[UPDATING] crate2 v2.29.8 ([ROOT]/foo/crate2) -> v2.29.81\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_precise_git_revisions() {\n    let (git_project, git_repo) = git::new_repo(\"git\", |p| {\n        p.file(\"Cargo.toml\", &basic_lib_manifest(\"git\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let tag_name = \"Nazgûl\";\n    git::tag(&git_repo, tag_name);\n    let tag_commit_id = git_repo.head().unwrap().target().unwrap().to_string();\n\n    git_project.change_file(\"src/lib.rs\", \"fn f() {}\");\n    git::add(&git_repo);\n    let head_id = git::commit(&git_repo).to_string();\n    let short_id = &head_id[..8];\n    let url = git_project.url();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies]\n                    git = {{ git = '{url}' }}\n                \"#\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"fetch\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/git`\n[LOCKING] 1 package to latest compatible version\n\n\"#]])\n        .run();\n\n    assert!(p.read_lockfile().contains(&head_id));\n\n    p.cargo(\"update git --precise\")\n        .arg(tag_name)\n        .with_stderr_data(format!(\n            \"\\\n[UPDATING] git repository `[ROOTURL]/git`\n[UPDATING] git v0.5.0 ([ROOTURL]/git#[..]) -> #{}\n\",\n            &tag_commit_id[..8],\n        ))\n        .run();\n\n    assert!(p.read_lockfile().contains(&tag_commit_id));\n    assert!(!p.read_lockfile().contains(&head_id));\n\n    p.cargo(\"update git --precise\")\n        .arg(short_id)\n        .with_stderr_data(format!(\n            \"\\\n[UPDATING] git repository `[ROOTURL]/git`\n[UPDATING] git v0.5.0 ([ROOTURL]/git[..]) -> #{short_id}\n\",\n        ))\n        .run();\n\n    assert!(p.read_lockfile().contains(&head_id));\n    assert!(!p.read_lockfile().contains(&tag_commit_id));\n\n    // updating back to tag still requires a git fetch,\n    // as the ref may change over time.\n    p.cargo(\"update git --precise\")\n        .arg(tag_name)\n        .with_stderr_data(format!(\n            \"\\\n[UPDATING] git repository `[ROOTURL]/git`\n[UPDATING] git v0.5.0 ([ROOTURL]/git#[..]) -> #{}\n\",\n            &tag_commit_id[..8],\n        ))\n        .run();\n\n    assert!(p.read_lockfile().contains(&tag_commit_id));\n    assert!(!p.read_lockfile().contains(&head_id));\n\n    // Now make a tag looks like an oid.\n    // It requires a git fetch, as the oid cannot be found in preexisting git db.\n    let arbitrary_tag: String = \"a\".repeat(head_id.len());\n    git::tag(&git_repo, &arbitrary_tag);\n\n    p.cargo(\"update git --precise\")\n        .arg(&arbitrary_tag)\n        .with_stderr_data(format!(\n            \"\\\n[UPDATING] git repository `[ROOTURL]/git`\n[UPDATING] git v0.5.0 ([ROOTURL]/git#[..]) -> #{}\n\",\n            &head_id[..8],\n        ))\n        .run();\n\n    assert!(p.read_lockfile().contains(&head_id));\n    assert!(!p.read_lockfile().contains(&tag_commit_id));\n}\n\n#[cargo_test]\nfn precise_yanked() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.1\").yanked(true).publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n\n                [dependencies]\n                bar = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    // Use non-yanked version.\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"\\nname = \\\"bar\\\"\\nversion = \\\"0.1.0\\\"\"));\n\n    p.cargo(\"update --precise 0.1.1 bar\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[WARNING] selected package `bar@0.1.1` was yanked by the author\n  |\n  = [HELP] if possible, try a compatible non-yanked version\n[UPDATING] bar v0.1.0 -> v0.1.1\n\n\"#]])\n        .run();\n\n    // Use yanked version.\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"\\nname = \\\"bar\\\"\\nversion = \\\"0.1.1\\\"\"));\n}\n\n#[cargo_test]\nfn precise_yanked_multiple_presence() {\n    Package::new(\"bar\", \"0.1.0\").publish();\n    Package::new(\"bar\", \"0.1.1\").yanked(true).publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n\n                [dependencies]\n                bar = \"0.1\"\n                baz = { package = \"bar\", version = \"0.1\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    // Use non-yanked version.\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"\\nname = \\\"bar\\\"\\nversion = \\\"0.1.0\\\"\"));\n\n    p.cargo(\"update --precise 0.1.1 bar\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[WARNING] selected package `bar@0.1.1` was yanked by the author\n  |\n  = [HELP] if possible, try a compatible non-yanked version\n[UPDATING] bar v0.1.0 -> v0.1.1\n\n\"#]])\n        .run();\n\n    // Use yanked version.\n    let lockfile = p.read_lockfile();\n    assert!(lockfile.contains(\"\\nname = \\\"bar\\\"\\nversion = \\\"0.1.1\\\"\"));\n}\n\n#[cargo_test]\nfn report_behind() {\n    Package::new(\"two-ver\", \"0.1.0\").publish();\n    Package::new(\"two-ver\", \"0.2.0\").publish();\n    Package::new(\"pre\", \"1.0.0-alpha.0\").publish();\n    Package::new(\"pre\", \"1.0.0-alpha.1\").publish();\n    Package::new(\"breaking\", \"0.1.0\").publish();\n    Package::new(\"breaking\", \"0.2.0\").publish();\n    Package::new(\"breaking\", \"0.2.1-alpha.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n\n                [dependencies]\n                breaking = \"0.1\"\n                pre = \"=1.0.0-alpha.0\"\n                two-ver = \"0.2.0\"\n                two-ver-one = { version = \"0.1.0\", package = \"two-ver\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n    Package::new(\"breaking\", \"0.1.1\").publish();\n\n    p.cargo(\"update --dry-run\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] breaking v0.1.0 -> v0.1.1 (available: v0.2.0)\n[NOTE] pass `--verbose` to see 2 unchanged dependencies behind latest\n[WARNING] not updating lockfile due to dry run\n\n\"#]])\n        .run();\n\n    p.cargo(\"update --dry-run --verbose\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] breaking v0.1.0 -> v0.1.1 (available: v0.2.0)\n[UNCHANGED] pre v1.0.0-alpha.0 (available: v1.0.0-alpha.1)\n[UNCHANGED] two-ver v0.1.0 (available: v0.2.0)\n[NOTE] to see how you depend on a package, run `cargo tree --invert <dep>@<ver>`\n[WARNING] not updating lockfile due to dry run\n\n\"#]])\n        .run();\n\n    p.cargo(\"update\").run();\n\n    p.cargo(\"update --dry-run\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 0 packages to latest compatible versions\n[NOTE] pass `--verbose` to see 3 unchanged dependencies behind latest\n[WARNING] not updating lockfile due to dry run\n\n\"#]])\n        .run();\n\n    p.cargo(\"update --dry-run --verbose\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 0 packages to latest compatible versions\n[UNCHANGED] breaking v0.1.1 (available: v0.2.0)\n[UNCHANGED] pre v1.0.0-alpha.0 (available: v1.0.0-alpha.1)\n[UNCHANGED] two-ver v0.1.0 (available: v0.2.0)\n[NOTE] to see how you depend on a package, run `cargo tree --invert <dep>@<ver>`\n[WARNING] not updating lockfile due to dry run\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_with_missing_feature() {\n    // Attempting to update a package to a version with a missing feature\n    // should produce a warning.\n    Package::new(\"bar\", \"0.1.0\").feature(\"feat1\", &[]).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n\n            [dependencies]\n            bar = {version=\"0.1\", features=[\"feat1\"]}\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"generate-lockfile\").run();\n\n    // Publish an update that is missing the feature.\n    Package::new(\"bar\", \"0.1.1\").publish();\n\n    p.cargo(\"update\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 0 packages to latest compatible versions\n[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest\n\n\"#]])\n        .run();\n\n    // Publish a fixed version, should not warn.\n    Package::new(\"bar\", \"0.1.2\").feature(\"feat1\", &[]).publish();\n    p.cargo(\"update\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v0.1.0 -> v0.1.2\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_breaking_unstable() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name  =  \"foo\"\n                version  =  \"0.0.1\"\n                edition  =  \"2015\"\n                authors  =  []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"update --breaking\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the `--breaking` flag is unstable, pass `-Z unstable-options` to enable it\nSee https://github.com/rust-lang/cargo/issues/12425 for more information about the `--breaking` flag.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_breaking_dry_run() {\n    Package::new(\"incompatible\", \"1.0.0\").publish();\n    Package::new(\"ws\", \"1.0.0\").publish();\n\n    let root_manifest = r#\"\n        # Check if formatting is preserved. Nothing here should change, due to dry-run.\n\n        [workspace]\n        members  =  [\"foo\"]\n\n        [workspace.dependencies]\n        ws  =  \"1.0\"  # Preserve formatting\n    \"#;\n\n    let crate_manifest = r#\"\n        # Check if formatting is preserved. Nothing here should change, due to dry-run.\n\n        [package]\n        name  =  \"foo\"\n        version  =  \"0.0.1\"\n        edition  =  \"2015\"\n        authors  =  []\n\n        [dependencies]\n        incompatible  =  \"1.0\"  # Preserve formatting\n        ws.workspace  =  true  # Preserve formatting\n    \"#;\n\n    let p = project()\n        .file(\"Cargo.toml\", root_manifest)\n        .file(\"foo/Cargo.toml\", crate_manifest)\n        .file(\"foo/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n    let lock_file = p.read_file(\"Cargo.lock\");\n\n    Package::new(\"incompatible\", \"1.0.1\").publish();\n    Package::new(\"ws\", \"1.0.1\").publish();\n\n    Package::new(\"incompatible\", \"2.0.0\").publish();\n    Package::new(\"ws\", \"2.0.0\").publish();\n\n    p.cargo(\"update -Zunstable-options --dry-run --breaking\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPGRADING] incompatible ^1.0 -> ^2.0\n[UPGRADING] ws ^1.0 -> ^2.0\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] incompatible v1.0.0 -> v2.0.0\n[UPDATING] ws v1.0.0 -> v2.0.0\n[WARNING] aborting update due to dry run\n\n\"#]])\n        .run();\n\n    let root_manifest_after = p.read_file(\"Cargo.toml\");\n    assert_e2e().eq(&root_manifest_after, root_manifest);\n\n    let crate_manifest_after = p.read_file(\"foo/Cargo.toml\");\n    assert_e2e().eq(&crate_manifest_after, crate_manifest);\n\n    let lock_file_after = p.read_file(\"Cargo.lock\");\n    assert_e2e().eq(&lock_file_after, lock_file);\n}\n\n#[cargo_test]\nfn update_breaking() {\n    registry::alt_init();\n    Package::new(\"compatible\", \"1.0.0\").publish();\n    Package::new(\"incompatible\", \"1.0.0\").publish();\n    Package::new(\"pinned\", \"1.0.0\").publish();\n    Package::new(\"less-than\", \"1.0.0\").publish();\n    Package::new(\"renamed-from\", \"1.0.0\").publish();\n    Package::new(\"pre-release\", \"1.0.0\").publish();\n    Package::new(\"yanked\", \"1.0.0\").publish();\n    Package::new(\"ws\", \"1.0.0\").publish();\n    Package::new(\"shared\", \"1.0.0\").publish();\n    Package::new(\"multiple-locations\", \"1.0.0\").publish();\n    Package::new(\"multiple-versions\", \"1.0.0\").publish();\n    Package::new(\"multiple-versions\", \"2.0.0\").publish();\n    Package::new(\"alternative-1\", \"1.0.0\")\n        .alternative(true)\n        .publish();\n    Package::new(\"alternative-2\", \"1.0.0\")\n        .alternative(true)\n        .publish();\n    Package::new(\"bar\", \"1.0.0\").alternative(true).publish();\n    Package::new(\"multiple-registries\", \"1.0.0\").publish();\n    Package::new(\"multiple-registries\", \"2.0.0\")\n        .alternative(true)\n        .publish();\n    Package::new(\"multiple-source-types\", \"1.0.0\").publish();\n    Package::new(\"platform-specific\", \"1.0.0\").publish();\n    Package::new(\"dev\", \"1.0.0\").publish();\n    Package::new(\"build\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                # Check if formatting is preserved\n\n                [workspace]\n                members  =  [\"foo\", \"bar\"]\n\n                [workspace.dependencies]\n                ws  =  \"1.0\"  # This line gets partially rewritten\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                # Check if formatting is preserved\n\n                [package]\n                name  =  \"foo\"\n                version  =  \"0.0.1\"\n                edition  =  \"2015\"\n                authors  =  []\n\n                [dependencies]\n                compatible  =  \"1.0\"  # Comment\n                incompatible  =  \"1.0\"  # Comment\n                pinned  =  \"=1.0\"  # Comment\n                less-than  =  \"<99.0\"  # Comment\n                renamed-to  =  { package  =  \"renamed-from\", version  =  \"1.0\" }  # Comment\n                pre-release  =  \"1.0\"  # Comment\n                yanked  =  \"1.0\"  # Comment\n                ws.workspace  =  true  # Comment\n                shared  =  \"1.0\"  # Comment\n                multiple-locations  =  { path  =  \"../multiple-locations\", version  =  \"1.0\" }  # Comment\n                multiple-versions  =  \"1.0\"  # Comment\n                alternative-1  =  { registry  =  \"alternative\", version  =  \"1.0\" }  # Comment\n                multiple-registries  =  \"1.0\"  # Comment\n                bar  =  { path  =  \"../bar\", registry  =  \"alternative\", version  =  \"1.0.0\" }  # Comment\n                multiple-source-types  =  { path  =  \"../multiple-source-types\", version  =  \"1.0.0\" }  # Comment\n\n                [dependencies.alternative-2]  # Comment\n                version  =  \"1.0\"  # Comment\n                registry  =  \"alternative\"  # Comment\n\n                [target.'cfg(unix)'.dependencies]\n                platform-specific  =  \"1.0\"  # Comment\n\n                [dev-dependencies]\n                dev  =  \"1.0\"  # Comment\n\n                [build-dependencies]\n                build  =  \"1.0\"  # Comment\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                shared = \"1.0\"\n                multiple-versions = \"2.0\"\n                multiple-registries  =  { registry  =  \"alternative\", version  =  \"2.0\" }  # Comment\n                multiple-source-types  =  \"1.0\"  # Comment\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"multiple-locations/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"multiple-locations\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"multiple-locations/src/lib.rs\", \"\")\n        .file(\n            \"multiple-source-types/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"multiple-source-types\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"multiple-source-types/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    Package::new(\"compatible\", \"1.0.1\").publish();\n    Package::new(\"incompatible\", \"1.0.1\").publish();\n    Package::new(\"pinned\", \"1.0.1\").publish();\n    Package::new(\"less-than\", \"1.0.1\").publish();\n    Package::new(\"renamed-from\", \"1.0.1\").publish();\n    Package::new(\"ws\", \"1.0.1\").publish();\n    Package::new(\"multiple-locations\", \"1.0.1\").publish();\n    Package::new(\"multiple-versions\", \"1.0.1\").publish();\n    Package::new(\"multiple-versions\", \"2.0.1\").publish();\n    Package::new(\"alternative-1\", \"1.0.1\")\n        .alternative(true)\n        .publish();\n    Package::new(\"alternative-2\", \"1.0.1\")\n        .alternative(true)\n        .publish();\n    Package::new(\"platform-specific\", \"1.0.1\").publish();\n    Package::new(\"dev\", \"1.0.1\").publish();\n    Package::new(\"build\", \"1.0.1\").publish();\n\n    Package::new(\"incompatible\", \"2.0.0\").publish();\n    Package::new(\"pinned\", \"2.0.0\").publish();\n    Package::new(\"less-than\", \"2.0.0\").publish();\n    Package::new(\"renamed-from\", \"2.0.0\").publish();\n    Package::new(\"pre-release\", \"2.0.0-alpha\").publish();\n    Package::new(\"yanked\", \"2.0.0\").yanked(true).publish();\n    Package::new(\"ws\", \"2.0.0\").publish();\n    Package::new(\"shared\", \"2.0.0\").publish();\n    Package::new(\"multiple-locations\", \"2.0.0\").publish();\n    Package::new(\"multiple-versions\", \"3.0.0\").publish();\n    Package::new(\"alternative-1\", \"2.0.0\")\n        .alternative(true)\n        .publish();\n    Package::new(\"alternative-2\", \"2.0.0\")\n        .alternative(true)\n        .publish();\n    Package::new(\"bar\", \"2.0.0\").alternative(true).publish();\n    Package::new(\"multiple-registries\", \"2.0.0\").publish();\n    Package::new(\"multiple-registries\", \"3.0.0\")\n        .alternative(true)\n        .publish();\n    Package::new(\"multiple-source-types\", \"2.0.0\").publish();\n    Package::new(\"platform-specific\", \"2.0.0\").publish();\n    Package::new(\"dev\", \"2.0.0\").publish();\n    Package::new(\"build\", \"2.0.0\").publish();\n\n    p.cargo(\"update -Zunstable-options --breaking\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[UPGRADING] multiple-registries ^2.0 -> ^3.0\n[UPDATING] `dummy-registry` index\n[UPGRADING] multiple-source-types ^1.0 -> ^2.0\n[UPGRADING] multiple-versions ^2.0 -> ^3.0\n[UPGRADING] shared ^1.0 -> ^2.0\n[UPGRADING] alternative-1 ^1.0 -> ^2.0\n[UPGRADING] alternative-2 ^1.0 -> ^2.0\n[UPGRADING] incompatible ^1.0 -> ^2.0\n[UPGRADING] multiple-registries ^1.0 -> ^2.0\n[UPGRADING] multiple-versions ^1.0 -> ^3.0\n[UPGRADING] ws ^1.0 -> ^2.0\n[UPGRADING] dev ^1.0 -> ^2.0\n[UPGRADING] build ^1.0 -> ^2.0\n[UPGRADING] platform-specific ^1.0 -> ^2.0\n[LOCKING] 12 packages to latest compatible versions\n[UPDATING] alternative-1 v1.0.0 (registry `alternative`) -> v2.0.0\n[UPDATING] alternative-2 v1.0.0 (registry `alternative`) -> v2.0.0\n[UPDATING] build v1.0.0 -> v2.0.0\n[UPDATING] dev v1.0.0 -> v2.0.0\n[UPDATING] incompatible v1.0.0 -> v2.0.0\n[UPDATING] multiple-registries v2.0.0 (registry `alternative`) -> v3.0.0\n[UPDATING] multiple-registries v1.0.0 -> v2.0.0\n[UPDATING] multiple-source-types v1.0.0 -> v2.0.0\n[ADDING] multiple-versions v3.0.0\n[UPDATING] platform-specific v1.0.0 -> v2.0.0\n[UPDATING] shared v1.0.0 -> v2.0.0\n[UPDATING] ws v1.0.0 -> v2.0.0\n\n\"#]])\n        .run();\n\n    let root_manifest = p.read_file(\"Cargo.toml\");\n    assert_e2e().eq(\n        &root_manifest,\n        str![[r#\"\n\n                # Check if formatting is preserved\n\n                [workspace]\n                members  =  [\"foo\", \"bar\"]\n\n                [workspace.dependencies]\n                ws  =  \"2.0\"  # This line gets partially rewritten\n            \"#]],\n    );\n\n    let foo_manifest = p.read_file(\"foo/Cargo.toml\");\n\n    assert_e2e().eq(\n        &foo_manifest,\n        str![[r#\"\n\n                # Check if formatting is preserved\n\n                [package]\n                name  =  \"foo\"\n                version  =  \"0.0.1\"\n                edition  =  \"2015\"\n                authors  =  []\n\n                [dependencies]\n                compatible  =  \"1.0\"  # Comment\n                incompatible  =  \"2.0\"  # Comment\n                pinned  =  \"=1.0\"  # Comment\n                less-than  =  \"<99.0\"  # Comment\n                renamed-to  =  { package  =  \"renamed-from\", version  =  \"1.0\" }  # Comment\n                pre-release  =  \"1.0\"  # Comment\n                yanked  =  \"1.0\"  # Comment\n                ws.workspace  =  true  # Comment\n                shared  =  \"2.0\"  # Comment\n                multiple-locations  =  { path  =  \"../multiple-locations\", version  =  \"1.0\" }  # Comment\n                multiple-versions  =  \"3.0\"  # Comment\n                alternative-1  =  { registry  =  \"alternative\", version  =  \"2.0\" }  # Comment\n                multiple-registries  =  \"2.0\"  # Comment\n                bar  =  { path  =  \"../bar\", registry  =  \"alternative\", version  =  \"1.0.0\" }  # Comment\n                multiple-source-types  =  { path  =  \"../multiple-source-types\", version  =  \"1.0.0\" }  # Comment\n\n                [dependencies.alternative-2]  # Comment\n                version  =  \"2.0\"  # Comment\n                registry  =  \"alternative\"  # Comment\n\n                [target.'cfg(unix)'.dependencies]\n                platform-specific  =  \"2.0\"  # Comment\n\n                [dev-dependencies]\n                dev  =  \"2.0\"  # Comment\n\n                [build-dependencies]\n                build  =  \"2.0\"  # Comment\n            \"#]],\n    );\n\n    let bar_manifest = p.read_file(\"bar/Cargo.toml\");\n\n    assert_e2e().eq(\n        &bar_manifest,\n        str![[r#\"\n\n                [package]\n                name = \"bar\"\n                version = \"1.0.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                shared = \"2.0\"\n                multiple-versions = \"3.0\"\n                multiple-registries  =  { registry  =  \"alternative\", version  =  \"3.0\" }  # Comment\n                multiple-source-types  =  \"2.0\"  # Comment\n            \"#]],\n    );\n\n    p.cargo(\"update\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `alternative` index\n[UPDATING] `dummy-registry` index\n[LOCKING] 4 packages to latest compatible versions\n[UPDATING] compatible v1.0.0 -> v1.0.1\n[UPDATING] less-than v1.0.0 -> v2.0.0\n[UPDATING] pinned v1.0.0 -> v1.0.1 (available: v2.0.0)\n[UPDATING] renamed-from v1.0.0 -> v1.0.1 (available: v2.0.0)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_breaking_specific_packages() {\n    Package::new(\"just-foo\", \"1.0.0\")\n        .add_dep(Dependency::new(\"transitive-compatible\", \"1.0.0\").build())\n        .add_dep(Dependency::new(\"transitive-incompatible\", \"1.0.0\").build())\n        .publish();\n    Package::new(\"just-bar\", \"1.0.0\").publish();\n    Package::new(\"shared\", \"1.0.0\").publish();\n    Package::new(\"ws\", \"1.0.0\").publish();\n    Package::new(\"transitive-compatible\", \"1.0.0\").publish();\n    Package::new(\"transitive-incompatible\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n\n                [workspace.dependencies]\n                ws = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                just-foo = \"1.0\"\n                shared = \"1.0\"\n                ws.workspace = true\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                just-bar = \"1.0\"\n                shared = \"1.0\"\n                ws.workspace = true\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    Package::new(\"just-foo\", \"1.0.1\")\n        .add_dep(Dependency::new(\"transitive-compatible\", \"1.0.0\").build())\n        .add_dep(Dependency::new(\"transitive-incompatible\", \"1.0.0\").build())\n        .publish();\n    Package::new(\"just-bar\", \"1.0.1\").publish();\n    Package::new(\"shared\", \"1.0.1\").publish();\n    Package::new(\"ws\", \"1.0.1\").publish();\n    Package::new(\"transitive-compatible\", \"1.0.1\").publish();\n    Package::new(\"transitive-incompatible\", \"1.0.1\").publish();\n\n    Package::new(\"just-foo\", \"2.0.0\")\n        // Upgrading just-foo implies accepting an update of transitive-compatible.\n        .add_dep(Dependency::new(\"transitive-compatible\", \"1.0.1\").build())\n        // Upgrading just-foo implies accepting a major update of transitive-incompatible.\n        .add_dep(Dependency::new(\"transitive-incompatible\", \"2.0.0\").build())\n        .publish();\n    Package::new(\"just-bar\", \"2.0.0\").publish();\n    Package::new(\"shared\", \"2.0.0\").publish();\n    Package::new(\"ws\", \"2.0.0\").publish();\n    Package::new(\"transitive-incompatible\", \"2.0.0\").publish();\n\n    p.cargo(\"update -Zunstable-options --breaking just-foo shared ws\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPGRADING] shared ^1.0 -> ^2.0\n[UPGRADING] ws ^1.0 -> ^2.0\n[UPGRADING] just-foo ^1.0 -> ^2.0\n[LOCKING] 5 packages to latest compatible versions\n[UPDATING] just-foo v1.0.0 -> v2.0.0\n[UPDATING] shared v1.0.0 -> v2.0.0\n[UPDATING] transitive-compatible v1.0.0 -> v1.0.1\n[UPDATING] transitive-incompatible v1.0.0 -> v2.0.0\n[UPDATING] ws v1.0.0 -> v2.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_breaking_specific_packages_that_wont_update() {\n    Package::new(\"compatible\", \"1.0.0\").publish();\n    Package::new(\"renamed-from\", \"1.0.0\").publish();\n    Package::new(\"non-semver\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\")\n        .add_dep(Dependency::new(\"transitive-compatible\", \"1.0.0\").build())\n        .add_dep(Dependency::new(\"transitive-incompatible\", \"1.0.0\").build())\n        .publish();\n    Package::new(\"transitive-compatible\", \"1.0.0\").publish();\n    Package::new(\"transitive-incompatible\", \"1.0.0\").publish();\n\n    let crate_manifest = r#\"\n        # Check if formatting is preserved\n\n        [package]\n        name  =  \"foo\"\n        version  =  \"0.0.1\"\n        edition  =  \"2015\"\n        authors  =  []\n\n        [dependencies]\n        compatible  =  \"1.0\"  # Comment\n        renamed-to  =  { package  =  \"renamed-from\", version  =  \"1.0\" }  # Comment\n        non-semver  =  \"~1.0\"  # Comment\n        bar  =  \"1.0\"  # Comment\n    \"#;\n\n    let p = project()\n        .file(\"Cargo.toml\", crate_manifest)\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n    let lock_file = p.read_file(\"Cargo.lock\");\n\n    Package::new(\"compatible\", \"1.0.1\").publish();\n    Package::new(\"renamed-from\", \"1.0.1\").publish();\n    Package::new(\"non-semver\", \"1.0.1\").publish();\n    Package::new(\"transitive-compatible\", \"1.0.1\").publish();\n    Package::new(\"transitive-incompatible\", \"1.0.1\").publish();\n\n    Package::new(\"renamed-from\", \"2.0.0\").publish();\n    Package::new(\"non-semver\", \"2.0.0\").publish();\n    Package::new(\"transitive-incompatible\", \"2.0.0\").publish();\n\n    // Test that transitive dependencies produce helpful errors\n    p.cargo(\"update -Zunstable-options --breaking transitive-compatible transitive-incompatible\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specifications did not match any direct dependencies that could be upgraded\n  transitive-compatible\n  transitive-incompatible\n[NOTE] `transitive-compatible` exists as a transitive dependency but those are not available for upgrading through `--breaking`\n[NOTE] `transitive-incompatible` exists as a transitive dependency but those are not available for upgrading through `--breaking`\n\n\"#]])\n        .run();\n\n    // Test that renamed, non-semver, no-breaking-update dependencies produce errors\n    p.cargo(\"update -Zunstable-options --breaking compatible renamed-from non-semver\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] package ID specifications did not match any direct dependencies that could be upgraded\n  compatible\n  renamed-from\n  non-semver\n\n\"#]])\n        .run();\n\n    let crate_manifest_after = p.read_file(\"Cargo.toml\");\n    assert_e2e().eq(&crate_manifest_after, crate_manifest);\n\n    let lock_file_after = p.read_file(\"Cargo.lock\");\n    assert_e2e().eq(&lock_file_after, lock_file);\n\n    p.cargo(\n        \"update compatible renamed-from non-semver transitive-compatible transitive-incompatible\",\n    )\n    .with_stderr_data(str![[r#\"\n[UPDATING] `[..]` index\n[LOCKING] 5 packages to latest compatible versions\n[UPDATING] compatible v1.0.0 -> v1.0.1\n[UPDATING] non-semver v1.0.0 -> v1.0.1 (available: v2.0.0)\n[UPDATING] renamed-from v1.0.0 -> v1.0.1 (available: v2.0.0)\n[UPDATING] transitive-compatible v1.0.0 -> v1.0.1\n[UPDATING] transitive-incompatible v1.0.0 -> v1.0.1\n\n\"#]])\n    .run();\n}\n\n#[cargo_test]\nfn update_breaking_without_lock_file() {\n    Package::new(\"compatible\", \"1.0.0\").publish();\n    Package::new(\"incompatible\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name  =  \"foo\"\n            version  =  \"0.0.1\"\n            edition  =  \"2015\"\n            authors  =  []\n\n            [dependencies]\n            compatible  =  \"1.0\"  # Comment\n            incompatible  =  \"1.0\"  # Comment\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"compatible\", \"1.0.1\").publish();\n    Package::new(\"incompatible\", \"1.0.1\").publish();\n\n    Package::new(\"incompatible\", \"2.0.0\").publish();\n\n    p.cargo(\"update -Zunstable-options --breaking\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[..]` index\n[UPGRADING] incompatible ^1.0 -> ^2.0\n[LOCKING] 2 packages to latest compatible versions\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_breaking_spec_version() {\n    Package::new(\"compatible\", \"1.0.0\").publish();\n    Package::new(\"incompatible\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name  =  \"foo\"\n            version  =  \"0.0.1\"\n            edition  =  \"2015\"\n            authors  =  []\n\n            [dependencies]\n            compatible  =  \"1.0\"  # Comment\n            incompatible  =  \"1.0\"  # Comment\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    Package::new(\"compatible\", \"1.0.1\").publish();\n    Package::new(\"incompatible\", \"1.0.1\").publish();\n\n    Package::new(\"incompatible\", \"2.0.0\").publish();\n\n    // Invalid spec\n    p.cargo(\"update -Zunstable-options --breaking incompatible@foo\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid package ID specification: `incompatible@foo`\n\nCaused by:\n  expected a version like \"1.32\"\n\n\"#]])\n        .run();\n\n    // Spec version not matching our current dependencies\n    p.cargo(\"update -Zunstable-options --breaking incompatible@2.0.0\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification did not match any direct dependencies that could be upgraded\n  incompatible@2.0.0\n\n\"#]])\n        .run();\n\n    // Spec source not matching our current dependencies\n    p.cargo(\"update -Zunstable-options --breaking https://alternative.com#incompatible@1.0.0\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification did not match any direct dependencies that could be upgraded\n  https://alternative.com/#incompatible@1.0.0\n\n\"#]])\n        .run();\n\n    // Accepted spec\n    p.cargo(\"update -Zunstable-options --breaking incompatible@1.0.0\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[..]` index\n[UPGRADING] incompatible ^1.0 -> ^2.0\n[LOCKING] 1 package to latest compatible version\n[UPDATING] incompatible v1.0.0 -> v2.0.0\n\n\"#]])\n        .run();\n\n    // Accepted spec, full format\n    Package::new(\"incompatible\", \"3.0.0\").publish();\n    p.cargo(\"update -Zunstable-options --breaking https://github.com/rust-lang/crates.io-index#incompatible@2.0.0\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[..]` index\n[UPGRADING] incompatible ^2.0 -> ^3.0\n[LOCKING] 1 package to latest compatible version\n[UPDATING] incompatible v2.0.0 -> v3.0.0\n\n\"#]])\n        .run();\n\n    // Spec matches a dependency that will not be upgraded\n    p.cargo(\"update -Zunstable-options --breaking compatible@1.0.0\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[..]` index\n[ERROR] package ID specification did not match any direct dependencies that could be upgraded\n  compatible@1.0.0\n\n\"#]])\n        .run();\n\n    // Non-existing versions\n    p.cargo(\"update -Zunstable-options --breaking incompatible@9.0.0\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification did not match any direct dependencies that could be upgraded\n  incompatible@9.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"update -Zunstable-options --breaking compatible@9.0.0\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification did not match any direct dependencies that could be upgraded\n  compatible@9.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_breaking_spec_version_transitive() {\n    Package::new(\"dep\", \"1.0.0\").publish();\n    Package::new(\"dep\", \"1.1.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name  =  \"foo\"\n                version  =  \"0.0.1\"\n                edition  =  \"2015\"\n                authors  =  []\n\n                [dependencies]\n                dep  =  \"1.0\"\n                bar = { path = \"bar\", version = \"0.0.1\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name  =  \"bar\"\n                version  =  \"0.0.1\"\n                edition  =  \"2015\"\n                authors  =  []\n\n                [dependencies]\n                dep  =  \"1.1\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    Package::new(\"dep\", \"1.1.1\").publish();\n    Package::new(\"dep\", \"2.0.0\").publish();\n\n    // Will upgrade the direct dependency\n    p.cargo(\"update -Zunstable-options --breaking dep@1.0\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[..]` index\n[UPGRADING] dep ^1.0 -> ^2.0\n[LOCKING] 1 package to latest compatible version\n[ADDING] dep v2.0.0\n\n\"#]])\n        .run();\n\n    // But not the transitive one, because bar is not a workspace member\n    p.cargo(\"update -Zunstable-options --breaking dep@1.1\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[..]` index\n[ERROR] package ID specification did not match any direct dependencies that could be upgraded\n  dep@1.1\n\n\"#]])\n        .run();\n\n    // A non-breaking update is different, as it will update transitive dependencies\n    p.cargo(\"update dep@1.1\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[..]` index\n[LOCKING] 1 package to latest compatible version\n[UPDATING] dep v1.1.0 -> v1.1.1\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_breaking_mixed_compatibility() {\n    Package::new(\"mixed-compatibility\", \"1.0.0\").publish();\n    Package::new(\"mixed-compatibility\", \"2.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                mixed-compatibility = \"1.0\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                mixed-compatibility = \"2.0\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    Package::new(\"mixed-compatibility\", \"2.0.1\").publish();\n\n    p.cargo(\"update -Zunstable-options --breaking\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[..]` index\n[UPGRADING] mixed-compatibility ^1.0 -> ^2.0\n[LOCKING] 1 package to latest compatible version\n[ADDING] mixed-compatibility v2.0.1\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_breaking_mixed_pinning_renaming() {\n    Package::new(\"mixed-pinned\", \"1.0.0\").publish();\n    Package::new(\"mixed-ws-pinned\", \"1.0.0\").publish();\n    Package::new(\"renamed-from\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"pinned\", \"unpinned\", \"mixed\"]\n\n                [workspace.dependencies]\n                mixed-ws-pinned = \"=1.0\"\n            \"#,\n        )\n        .file(\n            \"pinned/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"pinned\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                mixed-pinned = \"=1.0\"\n                mixed-ws-pinned.workspace = true\n                renamed-to = { package = \"renamed-from\", version = \"1.0\" }\n            \"#,\n        )\n        .file(\"pinned/src/lib.rs\", \"\")\n        .file(\n            \"unpinned/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"unpinned\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                mixed-pinned = \"1.0\"\n                mixed-ws-pinned = \"1.0\"\n                renamed-from = \"1.0\"\n            \"#,\n        )\n        .file(\"unpinned/src/lib.rs\", \"\")\n        .file(\n            \"mixed/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"mixed\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'cfg(windows)'.dependencies]\n                mixed-pinned = \"1.0\"\n\n                [target.'cfg(unix)'.dependencies]\n                mixed-pinned = \"=1.0\"\n            \"#,\n        )\n        .file(\"mixed/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    Package::new(\"mixed-pinned\", \"2.0.0\").publish();\n    Package::new(\"mixed-ws-pinned\", \"2.0.0\").publish();\n    Package::new(\"renamed-from\", \"2.0.0\").publish();\n\n    p.cargo(\"update -Zunstable-options --breaking\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `[..]` index\n[UPGRADING] mixed-pinned ^1.0 -> ^2.0\n[UPGRADING] mixed-ws-pinned ^1.0 -> ^2.0\n[UPGRADING] renamed-from ^1.0 -> ^2.0\n[LOCKING] 3 packages to latest compatible versions\n[ADDING] mixed-pinned v2.0.0\n[ADDING] mixed-ws-pinned v2.0.0\n[ADDING] renamed-from v2.0.0\n\n\"#]])\n        .run();\n\n    let root_manifest = p.read_file(\"Cargo.toml\");\n    assert_e2e().eq(\n        &root_manifest,\n        str![[r#\"\n\n                [workspace]\n                members = [\"pinned\", \"unpinned\", \"mixed\"]\n\n                [workspace.dependencies]\n                mixed-ws-pinned = \"=1.0\"\n            \"#]],\n    );\n\n    let pinned_manifest = p.read_file(\"pinned/Cargo.toml\");\n    assert_e2e().eq(\n        &pinned_manifest,\n        str![[r#\"\n\n                [package]\n                name = \"pinned\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                mixed-pinned = \"=1.0\"\n                mixed-ws-pinned.workspace = true\n                renamed-to = { package = \"renamed-from\", version = \"1.0\" }\n            \"#]],\n    );\n\n    let unpinned_manifest = p.read_file(\"unpinned/Cargo.toml\");\n    assert_e2e().eq(\n        &unpinned_manifest,\n        str![[r#\"\n\n                [package]\n                name = \"unpinned\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                mixed-pinned = \"2.0\"\n                mixed-ws-pinned = \"2.0\"\n                renamed-from = \"2.0\"\n            \"#]],\n    );\n\n    let mixed_manifest = p.read_file(\"mixed/Cargo.toml\");\n    assert_e2e().eq(\n        &mixed_manifest,\n        str![[r#\"\n\n                [package]\n                name = \"mixed\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [target.'cfg(windows)'.dependencies]\n                mixed-pinned = \"2.0\"\n\n                [target.'cfg(unix)'.dependencies]\n                mixed-pinned = \"=1.0\"\n            \"#]],\n    );\n}\n\n#[cargo_test]\nfn update_breaking_pre_release_downgrade() {\n    Package::new(\"bar\", \"2.0.0-beta.21\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n        [package]\n        name  =  \"foo\"\n        version  =  \"0.0.1\"\n        edition  =  \"2015\"\n        authors  =  []\n\n        [dependencies]\n        bar = \"2.0.0-beta.21\"\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    // The purpose of this test is\n    // to demonstrate that `update --breaking` will not try to downgrade to the latest stable version (1.7.0),\n    // but will error because the dependency uses an exact version (not caret).\n    Package::new(\"bar\", \"1.7.0\").publish();\n    p.cargo(\"update -Zunstable-options --breaking bar\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] package ID specification did not match any direct dependencies that could be upgraded\n  bar\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_breaking_pre_release_upgrade() {\n    Package::new(\"bar\", \"2.0.0-beta.21\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n        [package]\n        name  =  \"foo\"\n        version  =  \"0.0.1\"\n        edition  =  \"2015\"\n        authors  =  []\n\n        [dependencies]\n        bar = \"2.0.0-beta.21\"\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    // `2.0.0-beta.21` cannot be upgraded with --breaking because it uses an exact version (not caret)\n    Package::new(\"bar\", \"2.0.0-beta.22\").publish();\n    p.cargo(\"update -Zunstable-options --breaking bar\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] package ID specification did not match any direct dependencies that could be upgraded\n  bar\n\n\"#]])\n        .run();\n    // `2.0.0-beta.21` cannot be upgraded to `2.0.0` with --breaking because it uses an exact version (not caret)\n    Package::new(\"bar\", \"2.0.0\").publish();\n    p.cargo(\"update -Zunstable-options --breaking bar\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[ERROR] package ID specification did not match any direct dependencies that could be upgraded\n  bar\n\n\"#]])\n        .run();\n\n    Package::new(\"bar\", \"3.0.0\").publish();\n    p.cargo(\"update -Zunstable-options --breaking bar\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPGRADING] bar ^2.0.0-beta.21 -> ^3.0.0\n[LOCKING] 1 package to latest compatible version\n[UPDATING] bar v2.0.0-beta.21 -> v3.0.0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn prefixed_v_in_version() {\n    Package::new(\"bar\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n        [package]\n        name  =  \"foo\"\n        version  =  \"0.0.1\"\n        edition  =  \"2015\"\n        authors  =  []\n\n        [dependencies]\n        bar = \"1.0.0\"\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    Package::new(\"bar\", \"1.0.1\").publish();\n    p.cargo(\"update bar --precise v1.0.1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the version provided, `v1.0.1` is not a valid SemVer version\n\n[HELP] try changing the version to `1.0.1`\n\nCaused by:\n  unexpected character 'v' while parsing major version number\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn update_breaking_missing_package_error() {\n    Package::new(\"bar\", \"1.0.0\").publish();\n    Package::new(\"transitive\", \"1.0.0\").publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"generate-lockfile\").run();\n\n    Package::new(\"bar\", \"2.0.0\")\n        .add_dep(Dependency::new(\"transitive\", \"1.0.0\").build())\n        .publish();\n\n    // Non-existent package reports an error\n    p.cargo(\"update -Zunstable-options --breaking no_such_crate\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification did not match any direct dependencies that could be upgraded\n  no_such_crate\n\n\"#]])\n        .run();\n\n    // Valid package processes, invalid package reports error\n    p.cargo(\"update -Zunstable-options --breaking bar no_such_crate\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPGRADING] bar ^1.0 -> ^2.0\n[ERROR] package ID specification did not match any direct dependencies that could be upgraded\n  no_such_crate\n\n\"#]])\n        .run();\n\n    // Successfully upgrade bar to add transitive to lockfile\n    p.cargo(\"update -Zunstable-options --breaking bar\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[UPGRADING] bar ^1.0 -> ^2.0\n[LOCKING] 2 packages to latest compatible versions\n[UPDATING] bar v1.0.0 -> v2.0.0\n[ADDING] transitive v1.0.0\n\n\"#]])\n        .run();\n\n    // Transitive dependency reports helpful error\n    p.cargo(\"update -Zunstable-options --breaking transitive\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specification did not match any direct dependencies that could be upgraded\n  transitive\n[NOTE] `transitive` exists as a transitive dependency but those are not available for upgrading through `--breaking`\n\n\"#]])\n        .run();\n\n    // Multiple error types reported together\n    p.cargo(\"update -Zunstable-options --breaking no_such_crate transitive another_missing\")\n        .masquerade_as_nightly_cargo(&[\"update-breaking\"])\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package ID specifications did not match any direct dependencies that could be upgraded\n  no_such_crate\n  transitive\n  another_missing\n[NOTE] `transitive` exists as a transitive dependency but those are not available for upgrading through `--breaking`\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/utils/cross_compile.rs",
    "content": "//! Support for cross-compile tests with the `--target` flag.\n//!\n//! Note that cross-testing is very limited. You need to install the\n//! \"alternate\" target to the host (32-bit for 64-bit hosts or vice-versa).\n//!\n//! Set `CFG_DISABLE_CROSS_TESTS=1` environment variable to disable these tests\n//! if you are unable to use the alternate target. Unfortunately 32-bit\n//! support on macOS is going away, so macOS users are out of luck.\n//!\n//! These tests are all disabled on rust-lang/rust's CI, but run in Cargo's CI.\n\nuse crate::prelude::*;\nuse cargo_test_support::{basic_manifest, cross_compile::alternate, main_file, project};\nuse cargo_util::ProcessError;\nuse std::fmt::Write;\nuse std::{\n    process::{Command, Output},\n    sync::{\n        Once,\n        atomic::{AtomicBool, Ordering},\n    },\n};\n\n/// Whether or not the resulting cross binaries can run on the host.\nstatic CAN_RUN_ON_HOST: AtomicBool = AtomicBool::new(false);\n\npub fn disabled() -> bool {\n    // First, disable if requested.\n    match std::env::var(\"CFG_DISABLE_CROSS_TESTS\") {\n        Ok(ref s) if *s == \"1\" => return true,\n        _ => {}\n    }\n\n    // It requires setting `target.linker` for cross-compilation to work on aarch64,\n    // so not going to bother now.\n    if cfg!(all(target_arch = \"aarch64\", target_os = \"linux\")) {\n        return true;\n    }\n\n    // Cross tests are only tested to work on macos, linux, and MSVC windows.\n    if !(cfg!(target_os = \"macos\") || cfg!(target_os = \"linux\") || cfg!(target_env = \"msvc\")) {\n        return true;\n    }\n\n    // It's not particularly common to have a cross-compilation setup, so\n    // try to detect that before we fail a bunch of tests through no fault\n    // of the user.\n    static CAN_BUILD_CROSS_TESTS: AtomicBool = AtomicBool::new(false);\n    static CHECK: Once = Once::new();\n\n    let cross_target = alternate();\n\n    let run_cross_test = || -> anyhow::Result<Output> {\n        let p = project()\n            .at(\"cross_test\")\n            .file(\"Cargo.toml\", &basic_manifest(\"cross_test\", \"1.0.0\"))\n            .file(\"src/main.rs\", &main_file(r#\"\"testing!\"\"#, &[]))\n            .build();\n\n        let build_result = p\n            .cargo(\"build --target\")\n            .arg(&cross_target)\n            .exec_with_output();\n\n        if build_result.is_ok() {\n            CAN_BUILD_CROSS_TESTS.store(true, Ordering::SeqCst);\n        }\n\n        let result = p\n            .cargo(\"run --target\")\n            .arg(&cross_target)\n            .exec_with_output();\n\n        if result.is_ok() {\n            CAN_RUN_ON_HOST.store(true, Ordering::SeqCst);\n        }\n        build_result\n    };\n\n    CHECK.call_once(|| {\n        drop(run_cross_test());\n    });\n\n    if CAN_BUILD_CROSS_TESTS.load(Ordering::SeqCst) {\n        // We were able to compile a simple project, so the user has the\n        // necessary `std::` bits installed. Therefore, tests should not\n        // be disabled.\n        return false;\n    }\n\n    // We can't compile a simple cross project. We want to warn the user\n    // by failing a single test and having the remainder of the cross tests\n    // pass. We don't use `std::sync::Once` here because panicking inside its\n    // `call_once` method would poison the `Once` instance, which is not what\n    // we want.\n    static HAVE_WARNED: AtomicBool = AtomicBool::new(false);\n\n    if HAVE_WARNED.swap(true, Ordering::SeqCst) {\n        // We are some other test and somebody else is handling the warning.\n        // Just disable the current test.\n        return true;\n    }\n\n    // We are responsible for warning the user, which we do by panicking.\n    let mut message = format!(\n        \"\n    Cannot cross compile to {}.\n\n    This failure can be safely ignored. If you would prefer to not see this\n    failure, you can set the environment variable CFG_DISABLE_CROSS_TESTS to \\\"1\\\".\n\n    Alternatively, you can install the necessary libraries to enable cross\n    compilation tests. Cross compilation tests depend on your host platform.\n    \",\n        cross_target\n    );\n\n    if cfg!(target_os = \"linux\") {\n        message.push_str(\n            \"\n    Linux cross tests target i686-unknown-linux-gnu, which requires the ability to\n    build and run 32-bit targets. This requires the 32-bit libraries to be\n    installed. For example, on Ubuntu, run `sudo apt install gcc-multilib` to\n    install the necessary libraries.\n    \",\n        );\n    } else if cfg!(target_os = \"macos\") {\n        message.push_str(\n            \"\n    macOS on aarch64 cross tests to target x86_64-apple-darwin.\n    This should be natively supported via Xcode, nothing additional besides the\n    rustup target should be needed.\n    \",\n        );\n    } else if cfg!(target_os = \"windows\") {\n        message.push_str(\n            \"\n    Windows cross tests target i686-pc-windows-msvc, which requires the ability\n    to build and run 32-bit targets. This should work automatically if you have\n    properly installed Visual Studio build tools.\n    \",\n        );\n    } else {\n        // The check at the top should prevent this.\n        panic!(\"platform should have been skipped\");\n    }\n\n    let rustup_available = Command::new(\"rustup\").output().is_ok();\n    if rustup_available {\n        write!(\n            message,\n            \"\n    Make sure that the appropriate `rustc` target is installed with rustup:\n\n        rustup target add {}\n    \",\n            cross_target\n        )\n        .unwrap();\n    } else {\n        write!(\n            message,\n            \"\n    rustup does not appear to be installed. Make sure that the appropriate\n    `rustc` target is installed for the target `{}`.\n    \",\n            cross_target\n        )\n        .unwrap();\n    }\n\n    // Show the actual error message.\n    match run_cross_test() {\n        Ok(_) => message.push_str(\"\\nUh oh, second run succeeded?\\n\"),\n        Err(err) => match err.downcast_ref::<ProcessError>() {\n            Some(proc_err) => write!(message, \"\\nTest error: {}\\n\", proc_err).unwrap(),\n            None => write!(message, \"\\nUnexpected non-process error: {}\\n\", err).unwrap(),\n        },\n    }\n\n    panic!(\"{}\", message);\n}\n\n/// Whether or not the host can run cross-compiled executables.\npub fn can_run_on_host() -> bool {\n    if disabled() {\n        return false;\n    }\n    assert!(CAN_RUN_ON_HOST.load(Ordering::SeqCst));\n    return true;\n}\n"
  },
  {
    "path": "tests/testsuite/utils/ext.rs",
    "content": "use std::path::PathBuf;\n\nuse cargo_test_support::{ArgLineCommandExt, Execs, Project, TestEnvCommandExt, compare};\n\npub trait CargoProjectExt {\n    /// Creates a `ProcessBuilder` to run cargo.\n    ///\n    /// Arguments can be separated by spaces.\n    ///\n    /// For `cargo run`, see [`Project::rename_run`].\n    ///\n    /// # Example:\n    ///\n    /// ```no_run\n    /// # let p = cargo_test_support::project().build();\n    /// p.cargo(\"build --bin foo\").run();\n    /// ```\n    fn cargo(&self, cmd: &str) -> Execs;\n}\n\nimpl CargoProjectExt for Project {\n    fn cargo(&self, cmd: &str) -> Execs {\n        let cargo = cargo_exe();\n        let mut execs = self.process(&cargo);\n        execs.env(\"CARGO\", cargo);\n        execs.arg_line(cmd);\n        execs\n    }\n}\n\n/// Path to the cargo binary\npub fn cargo_exe() -> PathBuf {\n    snapbox::cmd::cargo_bin!(\"cargo\").to_path_buf()\n}\n\n/// Test the cargo command\npub trait CargoCommandExt {\n    fn cargo_ui() -> Self;\n}\n\nimpl CargoCommandExt for snapbox::cmd::Command {\n    fn cargo_ui() -> Self {\n        Self::new(cargo_exe())\n            .with_assert(compare::assert_ui())\n            .env(\"CARGO_TERM_COLOR\", \"always\")\n            .env(\"CARGO_TERM_HYPERLINKS\", \"true\")\n            .test_env()\n    }\n}\n"
  },
  {
    "path": "tests/testsuite/utils/mod.rs",
    "content": "use std::path::PathBuf;\n\nuse cargo_test_support::{ArgLineCommandExt, Execs, execs, process};\n\npub mod cross_compile;\npub mod ext;\npub mod tools;\n\n/// Run `cargo $arg_line`, see [`Execs`]\npub fn cargo_process(arg_line: &str) -> Execs {\n    let cargo = cargo_exe();\n    let mut p = process(&cargo);\n    p.env(\"CARGO\", cargo);\n    p.arg_line(arg_line);\n    execs().with_process_builder(p)\n}\n\n/// Path to the cargo binary\npub fn cargo_exe() -> PathBuf {\n    snapbox::cmd::cargo_bin!(\"cargo\").to_path_buf()\n}\n"
  },
  {
    "path": "tests/testsuite/utils/tools.rs",
    "content": "//! Common executables that can be reused by various tests.\n\nuse crate::prelude::*;\nuse cargo_test_support::{Project, basic_manifest, paths, project};\nuse std::path::{Path, PathBuf};\nuse std::sync::Mutex;\nuse std::sync::OnceLock;\n\nstatic ECHO_WRAPPER: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new();\nstatic ECHO: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new();\nstatic CLIPPY_DRIVER: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new();\n\n/// Returns the path to an executable that works as a wrapper around rustc.\n///\n/// The wrapper will echo the command line it was called with to stderr.\npub fn echo_wrapper() -> PathBuf {\n    let mut lock = ECHO_WRAPPER\n        .get_or_init(|| Default::default())\n        .lock()\n        .unwrap();\n    if let Some(path) = &*lock {\n        return path.clone();\n    }\n    let p = project()\n        .at(paths::global_root().join(\"rustc-echo-wrapper\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"rustc-echo-wrapper\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            use std::fs::read_to_string;\n            use std::path::PathBuf;\n            fn main() {\n                // Handle args from `@path` argfile for rustc\n                let args = std::env::args()\n                    .flat_map(|p| if let Some(p) = p.strip_prefix(\"@\") {\n                        read_to_string(p).unwrap().lines().map(String::from).collect()\n                    } else {\n                        vec![p]\n                    })\n                    .collect::<Vec<_>>();\n                eprintln!(\"WRAPPER CALLED: {}\", args[1..].join(\" \"));\n                let status = std::process::Command::new(&args[1])\n                    .args(&args[2..]).status().unwrap();\n                std::process::exit(status.code().unwrap_or(1));\n            }\n            \"#,\n        )\n        .build();\n    p.cargo(\"build\").run();\n    let path = p.bin(\"rustc-echo-wrapper\");\n    *lock = Some(path.clone());\n    path\n}\n\n/// Returns the path to an executable that prints its arguments.\n///\n/// Do not expect this to be anything fancy.\npub fn echo() -> PathBuf {\n    let mut lock = ECHO.get_or_init(|| Default::default()).lock().unwrap();\n    if let Some(path) = &*lock {\n        return path.clone();\n    }\n    if let Ok(path) = cargo_util::paths::resolve_executable(Path::new(\"echo\")) {\n        *lock = Some(path.clone());\n        return path;\n    }\n    // Often on Windows, `echo` is not available.\n    let p = project()\n        .at(paths::global_root().join(\"basic-echo\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"basic-echo\", \"1.0.0\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    let mut s = String::new();\n                    let mut it = std::env::args().skip(1).peekable();\n                    while let Some(n) = it.next() {\n                        s.push_str(&n);\n                        if it.peek().is_some() {\n                            s.push(' ');\n                        }\n                    }\n                    println!(\"{}\", s);\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"build\").run();\n    let path = p.bin(\"basic-echo\");\n    *lock = Some(path.clone());\n    path\n}\n\n/// Returns a project which builds a cargo-echo simple subcommand\npub fn echo_subcommand() -> Project {\n    let p = project()\n        .at(\"cargo-echo\")\n        .file(\"Cargo.toml\", &basic_manifest(\"cargo-echo\", \"0.0.1\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    let args: Vec<_> = ::std::env::args().skip(1).collect();\n                    println!(\"{}\", args.join(\" \"));\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"build\").run();\n    p\n}\n\n/// A wrapper around `rustc` instead of calling `clippy`.\npub fn wrapped_clippy_driver() -> PathBuf {\n    let mut lock = CLIPPY_DRIVER\n        .get_or_init(|| Default::default())\n        .lock()\n        .unwrap();\n    if let Some(path) = &*lock {\n        return path.clone();\n    }\n    let clippy_driver = project()\n        .at(paths::global_root().join(\"clippy-driver\"))\n        .file(\"Cargo.toml\", &basic_manifest(\"clippy-driver\", \"0.0.1\"))\n        .file(\n            \"src/main.rs\",\n            r#\"\n            fn main() {\n                let mut args = std::env::args_os();\n                let _me = args.next().unwrap();\n                let rustc = args.next().unwrap();\n                let status = std::process::Command::new(rustc).args(args).status().unwrap();\n                std::process::exit(status.code().unwrap_or(1));\n            }\n            \"#,\n        )\n        .build();\n    clippy_driver.cargo(\"build\").run();\n    let path = clippy_driver.bin(\"clippy-driver\");\n    *lock = Some(path.clone());\n    path\n}\n"
  },
  {
    "path": "tests/testsuite/vendor.rs",
    "content": "//! Tests for the `cargo vendor` command.\n//!\n//! Note that every test here uses `--respect-source-config` so that the\n//! \"fake\" crates.io is used. Otherwise `vendor` would download the crates.io\n//! index from the network.\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::assert_deterministic_mtime;\nuse cargo_test_support::compare::assert_e2e;\nuse cargo_test_support::git;\nuse cargo_test_support::registry::{self, Package, RegistryBuilder};\nuse cargo_test_support::str;\nuse cargo_test_support::{Project, basic_lib_manifest, basic_manifest, paths, project};\n\n#[cargo_test]\nfn vendor_simple() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                log = \"0.3.5\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"log\", \"0.3.5\").publish();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    let lock = p.read_file(\"vendor/log/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.3.5\\\"\"));\n\n    add_crates_io_vendor_config(&p);\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn vendor_sample_config() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                log = \"0.3.5\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"log\", \"0.3.5\").publish();\n\n    p.cargo(\"vendor --respect-source-config\")\n        .with_stdout_data(str![[r#\"\n[source.crates-io]\nreplace-with = \"vendored-sources\"\n\n[source.vendored-sources]\ndirectory = \"vendor\"\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn vendor_sample_config_alt_registry() {\n    let registry = RegistryBuilder::new().alternative().http_index().build();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                log = { version = \"0.3.5\", registry = \"alternative\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"log\", \"0.3.5\").alternative(true).publish();\n\n    p.cargo(\"vendor --respect-source-config\")\n        .with_stdout_data(format!(\n            r#\"[source.\"{0}\"]\nregistry = \"{0}\"\nreplace-with = \"vendored-sources\"\n\n[source.vendored-sources]\ndirectory = \"vendor\"\n\"#,\n            registry.index_url()\n        ))\n        .run();\n}\n\n#[cargo_test]\nfn vendor_path_specified() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                log = \"0.3.5\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"log\", \"0.3.5\").publish();\n\n    let path = if cfg!(windows) {\n        r#\"deps\\.vendor\"#\n    } else {\n        \"deps/.vendor\"\n    };\n\n    let output = p.cargo(\"vendor --respect-source-config\").arg(path).run();\n    // Assert against original output to ensure that\n    // path is normalized by `ops::vendor` on Windows.\n    assert_eq!(\n        &String::from_utf8(output.stdout).unwrap(),\n        r#\"[source.crates-io]\nreplace-with = \"vendored-sources\"\n\n[source.vendored-sources]\ndirectory = \"deps/.vendor\"\n\"#\n    );\n\n    let lock = p.read_file(\"deps/.vendor/log/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.3.5\\\"\"));\n}\n\nfn add_crates_io_vendor_config(p: &Project) {\n    p.change_file(\n        \".cargo/config.toml\",\n        r#\"\n            [source.crates-io]\n            replace-with = 'vendor'\n\n            [source.vendor]\n            directory = 'vendor'\n        \"#,\n    );\n}\n\nfn add_git_vendor_config(p: &Project, git_project: &Project) {\n    p.change_file(\n        \".cargo/config.toml\",\n        &format!(\n            r#\"\n            [source.\"git+{url}\"]\n            git = \"{url}\"\n            replace-with = 'vendor'\n\n            [source.vendor]\n            directory = 'vendor'\n        \"#,\n            url = git_project.url()\n        ),\n    );\n}\n\n#[cargo_test]\nfn package_exclude() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"bar\", \"0.1.0\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                exclude = [\".*\", \"!.include\", \"!.dotdir/include\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\".exclude\", \"\")\n        .file(\".include\", \"\")\n        .file(\".dotdir/exclude\", \"\")\n        .file(\".dotdir/include\", \"\")\n        .publish();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    let csum = p.read_file(\"vendor/bar/.cargo-checksum.json\");\n    // Everything is included because `cargo-vendor`\n    // do direct extractions from tarballs\n    // (Some are excluded like `.git` or `.cargo-ok` though.)\n    assert!(csum.contains(\".include\"));\n    assert!(csum.contains(\".exclude\"));\n    assert!(csum.contains(\".dotdir/exclude\"));\n    assert!(csum.contains(\".dotdir/include\"));\n}\n\n#[cargo_test]\nfn discovery_inferred_build_rs_included() {\n    let git_project = git::new(\"dep\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n    [package]\n    name = \"dep\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/lib.rs\", \"build.rs\"]\n    \"#,\n            )\n            .file(\"src/lib.rs\", \"\")\n            .file(\"build.rs\", \"fn main() {}\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n\n                    [dependencies.dep]\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    add_git_vendor_config(&p, &git_project);\n\n    let lock = p.read_file(\"vendor/dep/Cargo.toml\");\n    assert_e2e().eq(\n        lock,\n        str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"dep\"\nversion = \"0.0.1\"\nauthors = []\nbuild = \"build.rs\"\ninclude = [\n    \"src/lib.rs\",\n    \"build.rs\",\n]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"dep\"\npath = \"src/lib.rs\"\n\n\"##]],\n    );\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn discovery_inferred_build_rs_excluded() {\n    let git_project = git::new(\"dep\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n    [package]\n    name = \"dep\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/lib.rs\"]\n    \"#,\n            )\n            .file(\"src/lib.rs\", \"\")\n            .file(\"build.rs\", \"fn main() {}\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n\n                    [dependencies.dep]\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    add_git_vendor_config(&p, &git_project);\n\n    let lock = p.read_file(\"vendor/dep/Cargo.toml\");\n    assert_e2e().eq(\n        lock,\n        str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"dep\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\"src/lib.rs\"]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"dep\"\npath = \"src/lib.rs\"\n\n\"##]],\n    );\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn discovery_inferred_lib_included() {\n    let git_project = git::new(\"dep\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n    [package]\n    name = \"dep\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/main.rs\", \"src/lib.rs\"]\n    \"#,\n            )\n            .file(\"src/main.rs\", \"fn main() {}\")\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n\n                    [dependencies.dep]\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    add_git_vendor_config(&p, &git_project);\n\n    let lock = p.read_file(\"vendor/dep/Cargo.toml\");\n    assert_e2e().eq(\n        lock,\n        str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"dep\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\n    \"src/main.rs\",\n    \"src/lib.rs\",\n]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"dep\"\npath = \"src/lib.rs\"\n\n[[bin]]\nname = \"dep\"\npath = \"src/main.rs\"\n\n\"##]],\n    );\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn discovery_inferred_lib_excluded() {\n    let git_project = git::new(\"dep\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n    [package]\n    name = \"dep\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/main.rs\"]\n    \"#,\n            )\n            .file(\"src/main.rs\", \"fn main() {}\")\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n\n                    [dependencies.dep]\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    add_git_vendor_config(&p, &git_project);\n\n    let lock = p.read_file(\"vendor/dep/Cargo.toml\");\n    assert_e2e().eq(\n        lock,\n        str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"dep\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\"src/main.rs\"]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[[bin]]\nname = \"dep\"\npath = \"src/main.rs\"\n\n\"##]],\n    );\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn discovery_inferred_other_included() {\n    let git_project = git::new(\"dep\", |project| {\n        project\n        .file(\n            \"Cargo.toml\",\n            r#\"\n    [package]\n    name = \"dep\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/lib.rs\", \"src/bin/foo/main.rs\", \"examples/example_foo.rs\", \"tests/test_foo.rs\", \"benches/bench_foo.rs\"]\n    \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"src/bin/foo/main.rs\", \"fn main() {}\")\n        .file(\"examples/example_foo.rs\", \"fn main() {}\")\n        .file(\"tests/test_foo.rs\", \"fn main() {}\")\n        .file(\"benches/bench_foo.rs\", \"fn main() {}\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n\n                    [dependencies.dep]\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    add_git_vendor_config(&p, &git_project);\n\n    let lock = p.read_file(\"vendor/dep/Cargo.toml\");\n    assert_e2e().eq(\n        lock,\n        str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"dep\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\n    \"src/lib.rs\",\n    \"src/bin/foo/main.rs\",\n    \"examples/example_foo.rs\",\n    \"tests/test_foo.rs\",\n    \"benches/bench_foo.rs\",\n]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"dep\"\npath = \"src/lib.rs\"\n\n[[bin]]\nname = \"foo\"\npath = \"src/bin/foo/main.rs\"\n\n[[example]]\nname = \"example_foo\"\npath = \"examples/example_foo.rs\"\n\n[[test]]\nname = \"test_foo\"\npath = \"tests/test_foo.rs\"\n\n[[bench]]\nname = \"bench_foo\"\npath = \"benches/bench_foo.rs\"\n\n\"##]],\n    );\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn discovery_inferred_other_excluded() {\n    let git_project = git::new(\"dep\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n    [package]\n    name = \"dep\"\n    version = \"0.0.1\"\n    edition = \"2015\"\n    license = \"MIT\"\n    description = \"foo\"\n    documentation = \"docs.rs/foo\"\n    authors = []\n    include = [\"src/lib.rs\"]\n    \"#,\n            )\n            .file(\"src/lib.rs\", \"\")\n            .file(\"src/bin/foo/main.rs\", \"fn main() {}\")\n            .file(\"examples/example_foo.rs\", \"fn main() {}\")\n            .file(\"tests/test_foo.rs\", \"fn main() {}\")\n            .file(\"benches/bench_foo.rs\", \"fn main() {}\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.5.0\"\n                    edition = \"2015\"\n\n                    [dependencies.dep]\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    add_git_vendor_config(&p, &git_project);\n\n    let lock = p.read_file(\"vendor/dep/Cargo.toml\");\n    assert_e2e().eq(\n        lock,\n        str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"dep\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\ninclude = [\"src/lib.rs\"]\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"dep\"\npath = \"src/lib.rs\"\n\n\"##]],\n    );\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn two_versions() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bitflags = \"0.8.0\"\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bitflags = \"0.7.0\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"bitflags\", \"0.7.0\").publish();\n    Package::new(\"bitflags\", \"0.8.0\").publish();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n\n    let lock = p.read_file(\"vendor/bitflags/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.8.0\\\"\"));\n    let lock = p.read_file(\"vendor/bitflags-0.7.0/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.7.0\\\"\"));\n\n    add_crates_io_vendor_config(&p);\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn two_explicit_versions() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bitflags = \"0.8.0\"\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bitflags = \"0.7.0\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"bitflags\", \"0.7.0\").publish();\n    Package::new(\"bitflags\", \"0.8.0\").publish();\n\n    p.cargo(\"vendor --respect-source-config --versioned-dirs\")\n        .run();\n\n    let lock = p.read_file(\"vendor/bitflags-0.8.0/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.8.0\\\"\"));\n    let lock = p.read_file(\"vendor/bitflags-0.7.0/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.7.0\\\"\"));\n\n    add_crates_io_vendor_config(&p);\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn help() {\n    let p = project().build();\n    p.cargo(\"vendor -h\").run();\n}\n\n#[cargo_test]\nfn update_versions() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bitflags = \"0.7.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"bitflags\", \"0.7.0\").publish();\n    Package::new(\"bitflags\", \"0.8.0\").publish();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n\n    let lock = p.read_file(\"vendor/bitflags/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.7.0\\\"\"));\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            bitflags = \"0.8.0\"\n        \"#,\n    );\n    p.cargo(\"vendor --respect-source-config\").run();\n\n    let lock = p.read_file(\"vendor/bitflags/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.8.0\\\"\"));\n}\n\n#[cargo_test]\nfn two_lockfiles() {\n    let p = project()\n        .no_manifest()\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bitflags = \"=0.7.0\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bitflags = \"=0.8.0\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"bitflags\", \"0.7.0\").publish();\n    Package::new(\"bitflags\", \"0.8.0\").publish();\n\n    p.cargo(\"vendor --respect-source-config -s bar/Cargo.toml --manifest-path foo/Cargo.toml\")\n        .run();\n\n    let lock = p.read_file(\"vendor/bitflags/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.8.0\\\"\"));\n    let lock = p.read_file(\"vendor/bitflags-0.7.0/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.7.0\\\"\"));\n\n    add_crates_io_vendor_config(&p);\n    p.cargo(\"check\").cwd(\"foo\").run();\n    p.cargo(\"check\").cwd(\"bar\").run();\n}\n\n#[cargo_test]\nfn test_sync_argument() {\n    let p = project()\n        .no_manifest()\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bitflags = \"=0.7.0\"\n            \"#,\n        )\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bitflags = \"=0.8.0\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bitflags = \"=0.8.0\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"bitflags\", \"0.7.0\").publish();\n    Package::new(\"bitflags\", \"0.8.0\").publish();\n\n    p.cargo(\"vendor --respect-source-config --manifest-path foo/Cargo.toml -s bar/Cargo.toml baz/Cargo.toml test_vendor\")\n        .with_stderr_data(str![[r#\"\n[ERROR] unexpected argument 'test_vendor' found\n\nUsage: cargo[EXE] vendor [OPTIONS] [path]\n\nFor more information, try '--help'.\n\n\"#]]\n        )\n        .with_status(1)\n        .run();\n\n    p.cargo(\"vendor --respect-source-config --manifest-path foo/Cargo.toml -s bar/Cargo.toml -s baz/Cargo.toml test_vendor\")\n        .run();\n\n    let lock = p.read_file(\"test_vendor/bitflags/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.8.0\\\"\"));\n    let lock = p.read_file(\"test_vendor/bitflags-0.7.0/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.7.0\\\"\"));\n}\n\n#[cargo_test]\nfn delete_old_crates() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bitflags = \"=0.7.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"bitflags\", \"0.7.0\").publish();\n    Package::new(\"log\", \"0.3.5\").publish();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    p.read_file(\"vendor/bitflags/Cargo.toml\");\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            log = \"=0.3.5\"\n        \"#,\n    );\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    let lock = p.read_file(\"vendor/log/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.3.5\\\"\"));\n    assert!(!p.root().join(\"vendor/bitflags/Cargo.toml\").exists());\n}\n\n#[cargo_test]\nfn ignore_files() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                url = \"1.4.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"url\", \"1.4.1\")\n        // These will be vendored\n        .file(\".cargo_vcs_info.json\", \"\")\n        .file(\"Cargo.toml.orig\", \"\")\n        .file(\"foo.orig\", \"\")\n        .file(\"foo.rej\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        // These will not be vendored\n        .file(\".cargo-ok\", \"\")\n        .file(\".gitattributes\", \"\")\n        .file(\".gitignore\", \"\")\n        .publish();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    let csum = p.read_file(\"vendor/url/.cargo-checksum.json\");\n    assert_e2e().eq(\n        csum,\n        str![[r#\"\n{\n  \"files\": {\n    \".cargo_vcs_info.json\": \"[..]\",\n    \"Cargo.toml\": \"[..]\",\n    \"Cargo.toml.orig\": \"[..]\",\n    \"foo.orig\": \"[..]\",\n    \"foo.rej\": \"[..]\",\n    \"src/lib.rs\": \"[..]\"\n  },\n  \"package\": \"[..]\"\n}\n\"#]]\n        .is_json(),\n    );\n}\n\n#[cargo_test]\nfn included_files_only() {\n    let git = git::new(\"a\", |p| {\n        p.file(\"Cargo.toml\", &basic_lib_manifest(\"a\"))\n            .file(\"src/lib.rs\", \"\")\n            .file(\".gitignore\", \"a\")\n            .file(\"a/b.md\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    a = {{ git = '{}' }}\n                \"#,\n                git.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    let csum = p.read_file(\"vendor/a/.cargo-checksum.json\");\n    assert!(!csum.contains(\"a/b.md\"));\n}\n\n#[cargo_test]\nfn dependent_crates_in_crates() {\n    let git = git::new(\"a\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                b = { path = 'b' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"b/Cargo.toml\", &basic_lib_manifest(\"b\"))\n        .file(\"b/src/lib.rs\", \"\")\n    });\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    a = {{ git = '{}' }}\n                \"#,\n                git.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    p.read_file(\"vendor/a/.cargo-checksum.json\");\n    p.read_file(\"vendor/b/.cargo-checksum.json\");\n}\n\n#[cargo_test]\nfn vendoring_git_crates() {\n    let git = git::new(\"git\", |p| {\n        p.file(\"Cargo.toml\", &basic_lib_manifest(\"serde_derive\"))\n            .file(\"src/lib.rs\", \"\")\n            .file(\"src/wut.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies.serde]\n                    version = \"0.5.0\"\n\n                    [dependencies.serde_derive]\n                    version = \"0.5.0\"\n\n                    [patch.crates-io]\n                    serde_derive = {{ git = '{}' }}\n                \"#,\n                git.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    Package::new(\"serde\", \"0.5.0\")\n        .dep(\"serde_derive\", \"0.5\")\n        .publish();\n    Package::new(\"serde_derive\", \"0.5.0\").publish();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    p.read_file(\"vendor/serde_derive/src/wut.rs\");\n\n    add_crates_io_vendor_config(&p);\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn git_simple() {\n    let git = git::new(\"git\", |p| {\n        p.file(\"Cargo.toml\", &basic_lib_manifest(\"a\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    a = {{ git = '{}' }}\n                \"#,\n                git.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    let csum = p.read_file(\"vendor/a/.cargo-checksum.json\");\n    assert!(csum.contains(\"\\\"package\\\":null\"));\n}\n\n#[cargo_test]\nfn git_diff_rev() {\n    let (git_project, git_repo) = git::new_repo(\"git\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let url = git_project.url();\n    let ref_1 = \"v0.1.0\";\n    let ref_2 = \"v0.2.0\";\n\n    git::tag(&git_repo, ref_1);\n\n    git_project.change_file(\"Cargo.toml\", &basic_manifest(\"a\", \"0.2.0\"));\n    git::add(&git_repo);\n    git::commit(&git_repo);\n    git::tag(&git_repo, ref_2);\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    a_1 = {{ package = \"a\", git = '{url}', rev = '{ref_1}' }}\n                    a_2 = {{ package = \"a\", git = '{url}', rev = '{ref_2}' }}\n                \"#\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\")\n        .with_stdout_data(str![[r#\"\n[source.\"git+[ROOTURL]/git?rev=v0.1.0\"]\ngit = \"[ROOTURL]/git\"\nrev = \"v0.1.0\"\nreplace-with = \"vendored-sources\"\n\n[source.\"git+[ROOTURL]/git?rev=v0.2.0\"]\ngit = \"[ROOTURL]/git\"\nrev = \"v0.2.0\"\nreplace-with = \"vendored-sources\"\n\n[source.vendored-sources]\ndirectory = \"vendor\"\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn git_duplicate() {\n    let git = git::new(\"a\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                b = { path = 'b' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"b/Cargo.toml\", &basic_lib_manifest(\"b\"))\n        .file(\"b/src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    a = {{ git = '{}' }}\n                    b = '0.5.0'\n\n                \"#,\n                git.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    Package::new(\"b\", \"0.5.0\").publish();\n\n    p.cargo(\"vendor --respect-source-config\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] git repository `[ROOTURL]/a`\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] b v0.5.0 (registry `dummy-registry`)\n[ERROR] failed to sync\n\nCaused by:\n  found duplicate version of package `b v0.5.0` vendored from two sources:\n\n  \tsource 1: registry `crates-io`\n  \tsource 2: [ROOTURL]/a#[..]\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn git_complex() {\n    let git_b = git::new(\"git_b\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                dep_b = { path = 'dep_b' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"dep_b/Cargo.toml\", &basic_lib_manifest(\"dep_b\"))\n        .file(\"dep_b/src/lib.rs\", \"\")\n    });\n\n    let git_a = git::new(\"git_a\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"a\"\n                    version = \"0.1.0\"\n                    edition = \"2021\"\n\n                    [dependencies]\n                    b = {{ git = '{}' }}\n                    dep_a = {{ path = 'dep_a' }}\n                \"#,\n                git_b.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"dep_a/Cargo.toml\", &basic_lib_manifest(\"dep_a\"))\n        .file(\"dep_a/src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2021\"\n\n                    [dependencies]\n                    a = {{ git = '{}' }}\n                \"#,\n                git_a.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let output = p.cargo(\"vendor --respect-source-config\").run();\n    let output = String::from_utf8(output.stdout).unwrap();\n    p.change_file(\".cargo/config.toml\", &output);\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] dep_b v0.5.0 ([ROOTURL]/git_b#[..])\n[CHECKING] dep_a v0.5.0 ([ROOTURL]/git_a#[..])\n[RUNNING] `rustc [..] [ROOT]/foo/vendor/dep_b/src/lib.rs [..]`\n[RUNNING] `rustc [..] [ROOT]/foo/vendor/dep_a/src/lib.rs [..]`\n[CHECKING] b v0.1.0 ([ROOTURL]/git_b#[..])\n[RUNNING] `rustc [..] [ROOT]/foo/vendor/b/src/lib.rs [..]`\n[CHECKING] a v0.1.0 ([ROOTURL]/git_a#[..])\n[RUNNING] `rustc [..] [ROOT]/foo/vendor/a/src/lib.rs [..]`\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] src/lib.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn git_deterministic() {\n    let git_dep = git::new(\"git_dep\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"git_dep\"\n            version = \"0.0.1\"\n            edition = \"2021\"\n            license = \"MIT\"\n            description = \"foo\"\n            documentation = \"docs.rs/foo\"\n            authors = []\n\n            [[example]]\n            name = \"c\"\n\n            [[example]]\n            name = \"b\"\n\n            [[example]]\n            name = \"a\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"examples/z.rs\", \"fn main() {}\")\n        .file(\"examples/y.rs\", \"fn main() {}\")\n        .file(\"examples/x.rs\", \"fn main() {}\")\n        .file(\"examples/c.rs\", \"fn main() {}\")\n        .file(\"examples/b.rs\", \"fn main() {}\")\n        .file(\"examples/a.rs\", \"fn main() {}\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    git_dep = {{ git = '{}' }}\n                \"#,\n                git_dep.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    let output = p.cargo(\"vendor --respect-source-config\").run();\n    let output = String::from_utf8(output.stdout).unwrap();\n    p.change_file(\".cargo/config.toml\", &output);\n\n    let git_dep_manifest = p.read_file(\"vendor/git_dep/Cargo.toml\");\n    assert_e2e().eq(\n        git_dep_manifest,\n        str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2021\"\nname = \"git_dep\"\nversion = \"0.0.1\"\nauthors = []\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\ndocumentation = \"docs.rs/foo\"\nreadme = false\nlicense = \"MIT\"\n\n[lib]\nname = \"git_dep\"\npath = \"src/lib.rs\"\n\n[[example]]\nname = \"a\"\npath = \"examples/a.rs\"\n\n[[example]]\nname = \"b\"\npath = \"examples/b.rs\"\n\n[[example]]\nname = \"c\"\npath = \"examples/c.rs\"\n\n[[example]]\nname = \"x\"\npath = \"examples/x.rs\"\n\n[[example]]\nname = \"y\"\npath = \"examples/y.rs\"\n\n[[example]]\nname = \"z\"\npath = \"examples/z.rs\"\n\n\"##]],\n    );\n}\n\n#[cargo_test]\nfn git_update_rev() {\n    let (git_project, git_repo) = git::new_repo(\"git\", |p| {\n        p.file(\"Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let url = git_project.url();\n    let ref_1 = \"initial\";\n    let ref_2 = \"update\";\n\n    git::tag(&git_repo, ref_1);\n\n    git_project.change_file(\"src/lib.rs\", \"pub fn f() {}\");\n    git::add(&git_repo);\n    git::commit(&git_repo);\n    git::tag(&git_repo, ref_2);\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    a = {{ git = '{url}', rev = '{ref_1}' }}\n                \"#\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config --versioned-dirs\")\n        .run();\n\n    let lib = p.read_file(\"vendor/a-0.1.0/src/lib.rs\");\n    assert_e2e().eq(lib, \"\");\n\n    p.change_file(\n        \"Cargo.toml\",\n        &format!(\n            r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    a = {{ git = '{url}', rev = '{ref_2}' }}\n                \"#\n        ),\n    );\n\n    p.cargo(\"vendor --respect-source-config --versioned-dirs\")\n        .run();\n\n    let lib = p.read_file(\"vendor/a-0.1.0/src/lib.rs\");\n    assert_e2e().eq(lib, \"pub fn f() {}\");\n}\n\n#[cargo_test]\nfn depend_on_vendor_dir_not_deleted() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                libc = \"0.2.30\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"libc\", \"0.2.30\").publish();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    assert!(p.root().join(\"vendor/libc\").is_dir());\n\n    p.change_file(\n        \"Cargo.toml\",\n        r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n\n            [dependencies]\n            libc = \"0.2.30\"\n\n            [patch.crates-io]\n            libc = { path = 'vendor/libc' }\n        \"#,\n    );\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    assert!(p.root().join(\"vendor/libc\").is_dir());\n}\n\n#[cargo_test]\nfn ignore_hidden() {\n    // Don't delete files starting with `.`\n    Package::new(\"bar\", \"0.1.0\").publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"1.0.0\"\n            [dependencies]\n            bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    p.cargo(\"vendor --respect-source-config\").run();\n    // Add a `.git` directory.\n    let repo = git::init(&p.root().join(\"vendor\"));\n    git::add(&repo);\n    git::commit(&repo);\n    assert!(p.root().join(\"vendor/.git\").exists());\n    // Vendor again, shouldn't change anything.\n    p.cargo(\"vendor --respect-source-config\").run();\n    // .git should not be removed.\n    assert!(p.root().join(\"vendor/.git\").exists());\n    // And just for good measure, make sure no files changed.\n    let mut opts = git2::StatusOptions::new();\n    assert!(\n        repo.statuses(Some(&mut opts))\n            .unwrap()\n            .iter()\n            .all(|status| status.status() == git2::Status::CURRENT)\n    );\n}\n\n#[cargo_test]\nfn config_instructions_works() {\n    // Check that the config instructions work for all dependency kinds.\n    registry::alt_init();\n    Package::new(\"dep\", \"0.1.0\").publish();\n    Package::new(\"altdep\", \"0.1.0\").alternative(true).publish();\n    let git_project = git::new(\"gitdep\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_lib_manifest(\"gitdep\"))\n            .file(\"src/lib.rs\", \"\")\n    });\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2021\"\n\n                [dependencies]\n                dep = \"0.1\"\n                altdep = {{version=\"0.1\", registry=\"alternative\"}}\n                gitdep = {{git='{}'}}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n    let output = p.cargo(\"vendor --respect-source-config\").run();\n    let output = String::from_utf8(output.stdout).unwrap();\n    p.change_file(\".cargo/config.toml\", &output);\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(\n            str![[r#\"\n[CHECKING] altdep v0.1.0 (registry `alternative`)\n[CHECKING] dep v0.1.0\n[RUNNING] `rustc [..] [ROOT]/foo/vendor/altdep/src/lib.rs [..]`\n[RUNNING] `rustc [..] [ROOT]/foo/vendor/gitdep/src/lib.rs [..]`\n[RUNNING] `rustc [..] [ROOT]/foo/vendor/dep/src/lib.rs [..]`\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] src/lib.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[CHECKING] gitdep v0.5.0 ([ROOTURL]/gitdep#[..])\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n}\n\n#[cargo_test]\nfn git_crlf_preservation() {\n    // Check that newlines don't get changed when you vendor\n    // (will only fail if your system is setup with core.autocrlf=true on windows)\n    let input = \"hello \\nthere\\nmy newline\\nfriends\";\n    let git_project = git::new(\"git\", |p| {\n        p.file(\"Cargo.toml\", &basic_lib_manifest(\"a\"))\n            .file(\"src/lib.rs\", input)\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n\n                    [dependencies]\n                    a = {{ git = '{}' }}\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    fs::write(\n        paths::home().join(\".gitconfig\"),\n        r#\"\n            [core]\n            autocrlf = true\n        \"#,\n    )\n    .unwrap();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    let output = p.read_file(\"vendor/a/src/lib.rs\");\n    assert_eq!(input, output);\n}\n\n#[cargo_test]\n#[cfg(unix)]\nfn vendor_preserves_permissions() {\n    use std::os::unix::fs::MetadataExt;\n\n    Package::new(\"bar\", \"1.0.0\")\n        .file_with_mode(\"example.sh\", 0o755, \"#!/bin/sh\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n\n    let umask = cargo::util::get_umask();\n    let metadata = fs::metadata(p.root().join(\"vendor/bar/src/lib.rs\")).unwrap();\n    assert_eq!(metadata.mode() & 0o777, 0o644 & !umask);\n    let metadata = fs::metadata(p.root().join(\"vendor/bar/example.sh\")).unwrap();\n    assert_eq!(metadata.mode() & 0o777, 0o755 & !umask);\n}\n\n#[cargo_test]\nfn no_remote_dependency_no_vendor() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                [dependencies]\n                bar = { path = \"bar\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"vendor\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\nThere is no dependency to vendor in this project.\n\n\"#]])\n        .run();\n    assert!(!p.root().join(\"vendor\").exists());\n}\n\n#[cargo_test]\nfn vendor_crate_with_ws_inherit() {\n    let git = git::new(\"ws\", |p| {\n        p.file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n                [workspace.package]\n                version = \"0.1.0\"\n            \"#,\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version.workspace = true\n                edition = \"2021\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"\")\n    });\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2021\"\n\n                    [dependencies]\n                    bar = {{ git = '{}' }}\n                \"#,\n                git.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    p.change_file(\n        \".cargo/config.toml\",\n        &format!(\n            r#\"\n                [source.\"{}\"]\n                git = \"{}\"\n                replace-with = \"vendor\"\n\n                [source.vendor]\n                directory = \"vendor\"\n            \"#,\n            git.url(),\n            git.url()\n        ),\n    );\n\n    p.cargo(\"check -v\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.0 ([ROOTURL]/ws#[..])\n[RUNNING] `rustc [..] [ROOT]/foo/vendor/bar/src/lib.rs [..]`\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[RUNNING] `rustc [..] src/lib.rs [..]`\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dont_delete_non_registry_sources_with_respect_source_config() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                log = \"0.3.5\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"log\", \"0.3.5\").publish();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n    let lock = p.read_file(\"vendor/log/Cargo.toml\");\n    assert!(lock.contains(\"version = \\\"0.3.5\\\"\"));\n\n    add_crates_io_vendor_config(&p);\n    p.cargo(\"vendor --respect-source-config new-vendor-dir\")\n        .with_stderr_data(str![[r#\"\n   Vendoring log v0.3.5 ([ROOT]/foo/vendor/log) to new-vendor-dir/log\nTo use vendored sources, add this to your .cargo/config.toml for this project:\n\n\n\"#]])\n        .with_stdout_data(str![[r#\"\n[source.crates-io]\nreplace-with = \"vendored-sources\"\n\n[source.vendored-sources]\ndirectory = \"new-vendor-dir\"\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn error_loading_which_lock() {\n    // Tests an error message to make sure it is clear which\n    // manifest/workspace caused the problem. In this particular case, it was\n    // because the 2024 edition wants to know which rust version is in use.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                version = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"b/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"b\"\n                version = \"0.1.0\"\n                edition = \"2024\"\n            \"#,\n        )\n        .file(\"b/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config -s b/Cargo.toml\")\n        .env(\"RUSTC\", \"does-not-exist\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to sync\n\nCaused by:\n  failed to load lockfile for [ROOT]/foo/b\n\nCaused by:\n  could not execute process `does-not-exist -vV` (never executed)\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn error_downloading() {\n    // Tests the error message when downloading packages.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bar = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"bar\", \"1.0.0\").publish();\n    p.cargo(\"generate-lockfile\").run();\n    std::fs::remove_file(cargo_test_support::paths::root().join(\"dl/bar/1.0.0/download\")).unwrap();\n    p.cargo(\"vendor --respect-source-config\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[DOWNLOADING] crates ...\n[ERROR] failed to sync\n\nCaused by:\n  failed to download packages for [ROOT]/foo\n\nCaused by:\n  failed to download from `[ROOTURL]/dl/bar/1.0.0/download`\n\nCaused by:\n  [37] Could[..]t read a file:// file (Could[..]t open file [ROOT]/dl/bar/1.0.0/download)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn vendor_rename_fallback() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                log = \"0.3.5\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"log\", \"0.3.5\").publish();\n\n    p.cargo(\"vendor --respect-source-config --no-delete\")\n        .env(\"CARGO_LOG\", \"cargo::ops::vendor=warn\")\n        .env(\"__CARGO_TEST_VENDOR_FALLBACK_CP_SOURCES\", \"true\")\n        .with_status(0)\n        .with_stderr_data(str![[r#\"\n...\n[..]failed to `mv \"[..]vendor[..].vendor-staging[..]log-0.3.5\" \"[..]vendor[..]log\"`: simulated rename error for testing\n...\n\"#]])\n        .run();\n\n    assert!(p.root().join(\"vendor/log/Cargo.toml\").exists());\n}\n\n#[cargo_test]\nfn vendor_local_registry() {\n    // A regression test for rust-lang/cargo#16412\n    let root = paths::root();\n    fs::create_dir(root.join(\".cargo\")).unwrap();\n    fs::write(\n        root.join(\".cargo/config.toml\"),\n        r#\"\n            [source.crates-io]\n            registry = 'https://wut'\n            replace-with = 'my-awesome-local-registry'\n\n            [source.my-awesome-local-registry]\n            local-registry = 'registry'\n        \"#,\n    )\n    .unwrap();\n\n    Package::new(\"bar\", \"0.0.0\")\n        .local(true)\n        .file(\"src/lib.rs\", \"pub fn bar() {}\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                edition = \"2021\"\n\n                [dependencies]\n                bar = \"0.0.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"pub fn foo() { bar::bar(); }\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\")\n        .with_stderr_data(str![[r#\"\n[LOCKING] 1 package to latest compatible version\n[UNPACKING] bar v0.0.0 (registry `[ROOT]/registry`)\n   Vendoring bar v0.0.0 ([ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.0) to vendor/bar\nTo use vendored sources, add this to your .cargo/config.toml for this project:\n\n\n\"#]])\n        .run();\n\n    assert_e2e().eq(\n        p.read_file(\"vendor/bar/Cargo.toml\"),\n        str![[r#\"\n\n            [package]\n            name = \"bar\"\n            version = \"0.0.0\"\n            authors = []\n        \n\"#]],\n    );\n\n    assert_e2e().eq(\n        p.read_file(\"vendor/bar/src/lib.rs\"),\n        str![\"pub fn bar() {}\"],\n    );\n}\n\n#[cargo_test]\nfn deterministic_mtime() {\n    Package::new(\"foo\", \"0.1.0\")\n        // content doesn't matter, we just want to check mtime\n        .file(\"Cargo.lock\", \"\")\n        .file(\".cargo_vcs_info.json\", \"\")\n        .file(\"src/lib.rs\", \"\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"a\"\n                edition = \"2015\"\n\n                [dependencies]\n                foo = '0.1.0'\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n\n    // Generated files should have deterministic mtime after unpacking.\n    assert_deterministic_mtime(p.root().join(\"vendor/foo/Cargo.lock\"));\n    assert_deterministic_mtime(p.root().join(\"vendor/foo/Cargo.toml\"));\n    assert_deterministic_mtime(p.root().join(\"vendor/foo/.cargo_vcs_info.json\"));\n}\n\n#[cargo_test]\nfn vendor_filters_git_files_recursively() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n\n                [dependencies]\n                bar = \"0.1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    Package::new(\"bar\", \"0.1.0\")\n        .file(\"src/lib.rs\", \"\")\n        .file(\".gitattributes\", \"*.rs text\")\n        .file(\"subdir/.gitattributes\", \"*.c text\")\n        .file(\"subdir/.gitignore\", \"target/\")\n        .file(\"deep/nested/.git/config\", \"\")\n        .file(\"tests/.gitattributes\", \"*.txt text\")\n        .publish();\n\n    p.cargo(\"vendor --respect-source-config\").run();\n\n    // After fix, these should be filtered\n    assert!(!p.root().join(\"vendor/bar/subdir/.gitattributes\").exists());\n    assert!(!p.root().join(\"vendor/bar/subdir/.gitignore\").exists());\n    assert!(!p.root().join(\"vendor/bar/deep/nested/.git\").exists());\n    assert!(!p.root().join(\"vendor/bar/tests/.gitattributes\").exists());\n    assert!(!p.root().join(\"vendor/bar/.gitattributes\").exists());\n    assert!(p.root().join(\"vendor/bar/src/lib.rs\").exists());\n}\n"
  },
  {
    "path": "tests/testsuite/verify_project.rs",
    "content": "//! Tests for the `cargo verify-project` command.\n\nuse crate::prelude::*;\nuse cargo_test_support::{basic_bin_manifest, main_file, project, str};\n\n#[cargo_test]\nfn cargo_verify_project_path_to_cargo_toml_relative() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"verify-project --manifest-path foo/Cargo.toml\")\n        .cwd(p.root().parent().unwrap())\n        .with_stdout_data(str![[r#\"\n{\"success\":\"true\"}\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_verify_project_path_to_cargo_toml_absolute() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"verify-project --manifest-path\")\n        .arg(p.root().join(\"Cargo.toml\"))\n        .cwd(p.root().parent().unwrap())\n        .with_stdout_data(str![[r#\"\n{\"success\":\"true\"}\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_verify_project_cwd() {\n    let p = project()\n        .file(\"Cargo.toml\", &basic_bin_manifest(\"foo\"))\n        .file(\"src/foo.rs\", &main_file(r#\"\"i am foo\"\"#, &[]))\n        .build();\n\n    p.cargo(\"verify-project\")\n        .with_stdout_data(str![[r#\"\n{\"success\":\"true\"}\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cargo_verify_project_honours_unstable_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                cargo-features = [\"test-dummy-unstable\"]\n\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"verify-project\")\n        .masquerade_as_nightly_cargo(&[\"test-dummy-unstable\"])\n        .with_stdout_data(str![[r#\"\n{\"success\":\"true\"}\n\n\"#]])\n        .run();\n\n    p.cargo(\"verify-project\")\n        .with_status(1)\n        .with_stdout_data(str![[r#\"\n{\"invalid\":\"failed to parse manifest at `[..]`\"}\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn verify_project_invalid_toml_syntax() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n[package]\nname = \"foo\"\nversion = \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"verify-project\")\n        .with_status(1)\n        .with_stdout_data(str![[r#\"\n{\"invalid\":\"TOML parse error at line 4, column 11/n  |/n4 | version = /n  |           ^/nstring values must be quoted, expected literal string/n\"}\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/version.rs",
    "content": "//! Tests for displaying the cargo version.\n\nuse crate::prelude::*;\nuse crate::utils::cargo_process;\nuse cargo_test_support::project;\n\n#[cargo_test]\nfn simple() {\n    let p = project().build();\n\n    p.cargo(\"version\")\n        .with_stdout_data(&format!(\"cargo {}\\n\", cargo::version()))\n        .run();\n\n    p.cargo(\"--version\")\n        .with_stdout_data(&format!(\"cargo {}\\n\", cargo::version()))\n        .run();\n\n    p.cargo(\"-V\")\n        .with_stdout_data(&format!(\"cargo {}\\n\", cargo::version()))\n        .run();\n}\n\n#[cargo_test]\nfn version_works_without_rustc() {\n    let p = project().build();\n    p.cargo(\"version\").env(\"PATH\", \"\").run();\n}\n\n#[cargo_test]\nfn version_works_with_bad_config() {\n    let p = project()\n        .file(\".cargo/config.toml\", \"this is not toml\")\n        .build();\n    p.cargo(\"version\").run();\n}\n\n#[cargo_test]\nfn version_works_with_bad_target_dir() {\n    let p = project()\n        .file(\n            \".cargo/config.toml\",\n            r#\"\n                [build]\n                target-dir = 4\n            \"#,\n        )\n        .build();\n    p.cargo(\"version\").run();\n}\n\n#[cargo_test]\nfn verbose() {\n    // This is mainly to check that it doesn't explode.\n    cargo_process(\"-vV\")\n        .with_stdout_data(format!(\n            \"\\\ncargo {}\nrelease: [..]\ncommit-hash: [..]\ncommit-date: [..]\nhost: [HOST_TARGET]\nlibgit2: [..] (sys:[..] [..])\nlibcurl: [..] (sys:[..] [..])\n...\nos: [..]\n\",\n            cargo::version()\n        ))\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/warn_on_failure.rs",
    "content": "//! Tests for whether or not warnings are displayed for build scripts.\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{Project, project, str};\n\nstatic WARNING1: &str = \"Hello! I'm a warning. :)\";\nstatic WARNING2: &str = \"And one more!\";\n\nfn make_lib(lib_src: &str) {\n    Package::new(\"bar\", \"0.0.1\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                authors = []\n                version = \"0.0.1\"\n                edition = \"2015\"\n                build = \"build.rs\"\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            &format!(\n                r#\"\n                    fn main() {{\n                        use std::io::Write;\n                        println!(\"cargo::warning={{}}\", \"{}\");\n                        println!(\"hidden stdout\");\n                        write!(&mut ::std::io::stderr(), \"hidden stderr\");\n                        println!(\"cargo::warning={{}}\", \"{}\");\n                    }}\n                \"#,\n                WARNING1, WARNING2\n            ),\n        )\n        .file(\"src/lib.rs\", &format!(\"fn f() {{ {} }}\", lib_src))\n        .publish();\n}\n\nfn make_upstream(main_src: &str) -> Project {\n    project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"src/main.rs\", &format!(\"fn main() {{ {} }}\", main_src))\n        .build()\n}\n\n#[cargo_test]\nfn no_warning_on_success() {\n    make_lib(\"\");\n    let upstream = make_upstream(\"\");\n    upstream\n        .cargo(\"build\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[COMPILING] bar v0.0.1\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn no_warning_on_bin_failure() {\n    make_lib(\"\");\n    let upstream = make_upstream(\"hi()\");\n    upstream\n        .cargo(\"build\")\n        .with_status(101)\n        .with_stdout_does_not_contain(\"hidden stdout\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[COMPILING] bar v0.0.1\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\nerror[E0425]: cannot find function `hi` in this scope\n...\n[ERROR] could not compile `foo` (bin \"foo\") due to 1 previous error\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn warning_on_lib_failure() {\n    make_lib(\"err()\");\n    let upstream = make_upstream(\"\");\n    upstream\n        .cargo(\"build\")\n        .with_status(101)\n        .with_stdout_does_not_contain(\"hidden stdout\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)\n[COMPILING] bar v0.0.1\nerror[E0425]: cannot find function `err` in this scope\n...\n[WARNING] bar@0.0.1: Hello! I'm a warning. :)\n[WARNING] bar@0.0.1: And one more!\n[ERROR] could not compile `bar` (lib) due to 1 previous error\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/warning_override.rs",
    "content": "//! Tests for overriding warning behavior using `build.warnings` config option.\n\nuse crate::prelude::*;\nuse crate::utils::tools;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::{Project, cargo_test, project, str};\n\nfn make_project_with_rustc_warning() -> Project {\n    project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n            \"#\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() { let x = 3; }\")\n        .build()\n}\n\n#[cargo_test]\nfn rustc_caching_allow_first() {\n    let p = make_project_with_rustc_warning();\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='allow'\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='deny'\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused variable: `x`\n --> src/main.rs:1:17\n  |\n1 | fn main() { let x = 3; }\n  |                 ^ [HELP] if this is intentional, prefix it with an underscore: `_x`\n  |\n  = [NOTE] `#[warn(unused_variables)]` [..]on by default\n\n[ERROR] `foo` (bin \"foo\") generated 1 warning[..]\n[ERROR] warnings are denied by `build.warnings` configuration\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn rustc_caching_deny_first() {\n    let p = make_project_with_rustc_warning();\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='deny'\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] unused variable: `x`\n --> src/main.rs:1:17\n  |\n1 | fn main() { let x = 3; }\n  |                 ^ [HELP] if this is intentional, prefix it with an underscore: `_x`\n  |\n  = [NOTE] `#[warn(unused_variables)]` [..]on by default\n\n[ERROR] `foo` (bin \"foo\") generated 1 warning[..]\n[ERROR] warnings are denied by `build.warnings` configuration\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='allow'\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn config() {\n    let p = make_project_with_rustc_warning();\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .env(\"CARGO_BUILD_WARNINGS\", \"deny\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] unused variable: `x`\n --> src/main.rs:1:17\n  |\n1 | fn main() { let x = 3; }\n  |                 ^ [HELP] if this is intentional, prefix it with an underscore: `_x`\n  |\n  = [NOTE] `#[warn(unused_variables)]` [..]on by default\n\n[ERROR] `foo` (bin \"foo\") generated 1 warning[..]\n[ERROR] warnings are denied by `build.warnings` configuration\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    // CLI has precedence over env\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='warn'\")\n        .env(\"CARGO_BUILD_WARNINGS\", \"deny\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused variable: `x`\n --> src/main.rs:1:17\n  |\n1 | fn main() { let x = 3; }\n  |                 ^ [HELP] if this is intentional, prefix it with an underscore: `_x`\n  |\n  = [NOTE] `#[warn(unused_variables)]` [..]on by default\n\n[WARNING] `foo` (bin \"foo\") generated 1 warning[..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn requires_nightly() {\n    // build.warnings has no effect without -Zwarnings.\n    let p = make_project_with_rustc_warning();\n    p.cargo(\"check\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='deny'\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] unused variable: `x`\n --> src/main.rs:1:17\n  |\n1 | fn main() { let x = 3; }\n  |                 ^ [HELP] if this is intentional, prefix it with an underscore: `_x`\n  |\n  = [NOTE] `#[warn(unused_variables)]` [..]on by default\n\n[WARNING] `foo` (bin \"foo\") generated 1 warning[..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn clippy() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2015\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"use std::io;\") // <-- unused import\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='deny'\")\n        .env(\"RUSTC_WORKSPACE_WRAPPER\", tools::wrapped_clippy_driver())\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] unused import: `std::io`\n...\n[ERROR] `foo` (lib) generated 1 warning (run `cargo clippy --fix --lib -p foo` to apply 1 suggestion)\n[ERROR] warnings are denied by `build.warnings` configuration\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn unknown_value() {\n    let p = make_project_with_rustc_warning();\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='forbid'\")\n        .with_stderr_data(str![[r#\"\n[ERROR] error in --config cli option: could not load config key `build.warnings`\n\nCaused by:\n  unknown variant `forbid`, expected one of `warn`, `allow`, `deny`\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn hard_warning_deny() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n            \"#\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"rustc\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='deny'\")\n        .arg(\"--\")\n        .arg(\"-ox.rs\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] [..]\n\n[WARNING] [..]\n\n[WARNING] `foo` (bin \"foo\") generated 2 warnings\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn hard_warning_allow() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n            \"#\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n    p.cargo(\"rustc\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='allow'\")\n        .arg(\"--\")\n        .arg(\"-ox.rs\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .with_status(0)\n        .run();\n}\n\n#[cargo_test]\nfn keep_going() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n            \"#\n            ),\n        )\n        .file(\"build.rs\", \"fn main() { let x = 3; }\")\n        .file(\"src/main.rs\", \"fn main() { let y = 4; }\")\n        .build();\n\n    p.cargo(\"check\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='deny'\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n[WARNING] unused variable: `x`\n...\n[ERROR] `foo` (build script) generated 1 warning\n[ERROR] warnings are denied by `build.warnings` configuration\n\n\"#]])\n        .with_status(101)\n        .run();\n\n    p.cargo(\"check --keep-going\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='deny'\")\n        .with_stderr_data(str![[r#\"\n[WARNING] unused variable: `x`\n...\n[ERROR] `foo` (build script) generated 1 warning\n[COMPILING] foo v0.0.1 ([ROOT]/foo)\n...\n[ERROR] `foo` (bin \"foo\") generated 1 warning (run `cargo fix --bin \"foo\" -p foo` to apply 1 suggestion)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[ERROR] warnings are denied by `build.warnings` configuration\n\n\"#]])\n        .with_status(101)\n        .run();\n}\n\n#[cargo_test]\nfn cap_lints() {\n    Package::new(\"has_warning\", \"1.0.0\")\n        .file(\"src/lib.rs\", \"pub fn foo() { let x = 3; }\")\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                edition = \"2021\"\n\n                [dependencies]\n                has_warning = \"1\"\n            \"#\n            ),\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -vv\")\n        .env(\"RUSTFLAGS\", \"-Dwarnings\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] has_warning v1.0.0 (registry `dummy-registry`)\n[CHECKING] has_warning v1.0.0\n[RUNNING] [..]\n[WARNING] unused variable: `x`\n...\n[WARNING] `has_warning` (lib) generated 1 warning\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check -vv\")\n        .masquerade_as_nightly_cargo(&[\"warnings\"])\n        .arg(\"-Zwarnings\")\n        .arg(\"--config\")\n        .arg(\"build.warnings='deny'\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] has_warning v1.0.0\n[RUNNING] [..]\n[WARNING] unused variable: `x`\n...\n[WARNING] `has_warning` (lib) generated 1 warning\n[CHECKING] foo v0.0.1 ([ROOT]/foo)\n[RUNNING] [..]\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/weak_dep_features.rs",
    "content": "//! Tests for weak-dep-features.\n\nuse std::fmt::Write;\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::{Dependency, Package, RegistryBuilder};\nuse cargo_test_support::str;\nuse cargo_test_support::{project, publish};\n\nuse super::features2::switch_to_resolver_2;\n\n// Helper to create lib.rs files that check features.\nfn require(enabled_features: &[&str], disabled_features: &[&str]) -> String {\n    let mut s = String::new();\n    writeln!(s, \"#![allow(unexpected_cfgs)]\").unwrap();\n    for feature in enabled_features {\n        writeln!(s, \"#[cfg(not(feature=\\\"{feature}\\\"))] compile_error!(\\\"expected feature {feature} to be enabled\\\");\",\n            feature=feature).unwrap();\n    }\n    for feature in disabled_features {\n        writeln!(s, \"#[cfg(feature=\\\"{feature}\\\")] compile_error!(\\\"did not expect feature {feature} to be enabled\\\");\",\n            feature=feature).unwrap();\n    }\n    s\n}\n\n#[cargo_test]\nfn simple() {\n    Package::new(\"bar\", \"1.0.0\")\n        .feature(\"feat\", &[])\n        .file(\"src/lib.rs\", &require(&[\"feat\"], &[]))\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"1.0\", optional = true }\n\n                [features]\n                f1 = [\"bar?/feat\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", &require(&[\"f1\"], &[]))\n        .build();\n\n    // It's a bit unfortunate that this has to download `bar`, but avoiding\n    // that is extremely difficult.\n    p.cargo(\"check --features f1\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check --features f1,bar\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn deferred() {\n    // A complex chain that requires deferring enabling the feature due to\n    // another dependency getting enabled.\n    Package::new(\"bar\", \"1.0.0\")\n        .feature(\"feat\", &[])\n        .file(\"src/lib.rs\", &require(&[\"feat\"], &[]))\n        .publish();\n    Package::new(\"dep\", \"1.0.0\")\n        .add_dep(Dependency::new(\"bar\", \"1.0\").optional(true))\n        .feature(\"feat\", &[\"bar?/feat\"])\n        .publish();\n    Package::new(\"bar_activator\", \"1.0.0\")\n        .feature_dep(\"dep\", \"1.0\", &[\"bar\"])\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                dep = { version = \"1.0\", features = [\"feat\"] }\n                bar_activator = \"1.0\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] bar_activator v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] bar v1.0.0\n[CHECKING] dep v1.0.0\n[CHECKING] bar_activator v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn not_optional_dep() {\n    // Attempt to use dep_name?/feat where dep_name is not optional.\n    Package::new(\"dep\", \"1.0.0\").feature(\"feat\", &[]).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                dep = \"1.0\"\n\n                [features]\n                feat = [\"dep?/feat\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  feature `feat` includes `dep?/feat` with a `?`, but `dep` is not an optional dependency\n  A non-optional dependency of the same name is defined; consider removing the `?` or changing the dependency to be optional\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn optional_cli_syntax() {\n    // --features bar?/feat\n    Package::new(\"bar\", \"1.0.0\")\n        .feature(\"feat\", &[])\n        .file(\"src/lib.rs\", &require(&[\"feat\"], &[]))\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"1.0\", optional = true }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    // Does not build bar.\n    p.cargo(\"check --features bar?/feat\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Builds bar.\n    p.cargo(\"check --features bar?/feat,bar\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    eprintln!(\"check V2 resolver\");\n    switch_to_resolver_2(&p);\n    p.build_dir().rm_rf();\n    // Does not build bar.\n    p.cargo(\"check --features bar?/feat\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Builds bar.\n    p.cargo(\"check --features bar?/feat,bar\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn required_features() {\n    // required-features doesn't allow ?\n    Package::new(\"bar\", \"1.0.0\").feature(\"feat\", &[]).publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"1.0\", optional = true }\n\n                [[bin]]\n                name = \"foo\"\n                required-features = [\"bar?/feat\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ERROR] invalid feature `bar?/feat` in required-features of target `foo`: optional dependency with `?` is not allowed in required-features\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn weak_with_host_decouple() {\n    // weak-dep-features with new resolver\n    //\n    // foo v0.1.0\n    // └── common v1.0.0\n    //     └── bar v1.0.0        <-- does not have `feat` enabled\n    // [build-dependencies]\n    // └── bar_activator v1.0.0\n    //     └── common v1.0.0\n    //         └── bar v1.0.0    <-- does have `feat` enabled\n    Package::new(\"bar\", \"1.0.0\")\n        .feature(\"feat\", &[])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn feat() -> bool {\n                    cfg!(feature = \"feat\")\n                }\n            \"#,\n        )\n        .publish();\n\n    Package::new(\"common\", \"1.0.0\")\n        .add_dep(Dependency::new(\"bar\", \"1.0\").optional(true))\n        .feature(\"feat\", &[\"bar?/feat\"])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                #[cfg(feature = \"bar\")]\n                pub fn feat() -> bool { bar::feat() }\n                #[cfg(not(feature = \"bar\"))]\n                pub fn feat() -> bool { false }\n            \"#,\n        )\n        .publish();\n\n    Package::new(\"bar_activator\", \"1.0.0\")\n        .feature_dep(\"common\", \"1.0\", &[\"bar\", \"feat\"])\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn feat() -> bool {\n                    common::feat()\n                }\n            \"#,\n        )\n        .publish();\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                resolver = \"2\"\n\n                [dependencies]\n                common = { version = \"1.0\", features = [\"feat\"] }\n\n                [build-dependencies]\n                bar_activator = \"1.0\"\n            \"#,\n        )\n        .file(\n            \"src/main.rs\",\n            r#\"\n                fn main() {\n                    assert!(!common::feat());\n                }\n            \"#,\n        )\n        .file(\n            \"build.rs\",\n            r#\"\n                fn main() {\n                    assert!(bar_activator::feat());\n                }\n            \"#,\n        )\n        .build();\n\n    p.cargo(\"run\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 3 packages to latest compatible versions\n[DOWNLOADING] crates ...\n[DOWNLOADED] common v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] bar_activator v1.0.0 (registry `dummy-registry`)\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[COMPILING] bar v1.0.0\n[COMPILING] common v1.0.0\n[COMPILING] bar_activator v1.0.0\n[COMPILING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[RUNNING] `target/debug/foo[EXE]`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn weak_namespaced() {\n    // Behavior with a dep: dependency.\n    Package::new(\"bar\", \"1.0.0\")\n        .feature(\"feat\", &[])\n        .file(\"src/lib.rs\", &require(&[\"feat\"], &[]))\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"1.0\", optional = true }\n\n                [features]\n                f1 = [\"bar?/feat\"]\n                f2 = [\"dep:bar\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", &require(&[\"f1\"], &[\"f2\", \"bar\"]))\n        .build();\n\n    p.cargo(\"check --features f1\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -f\")\n        .arg(\"{p} feats:{f}\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo) feats:\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --features f1 -f\")\n        .arg(\"{p} feats:{f}\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo) feats:f1\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --features f1,f2 -f\")\n        .arg(\"{p} feats:{f}\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo) feats:f1,f2\n└── bar v1.0.0 feats:feat\n\n\"#]])\n        .run();\n\n    // \"bar\" remains not-a-feature\n    p.change_file(\"src/lib.rs\", &require(&[\"f1\", \"f2\"], &[\"bar\"]));\n\n    p.cargo(\"check --features f1,f2\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v1.0.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn tree() {\n    Package::new(\"bar\", \"1.0.0\")\n        .feature(\"feat\", &[])\n        .file(\"src/lib.rs\", &require(&[\"feat\"], &[]))\n        .publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                bar = { version = \"1.0\", optional = true }\n\n                [features]\n                f1 = [\"bar?/feat\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", &require(&[\"f1\"], &[]))\n        .build();\n\n    p.cargo(\"tree --features f1\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --features f1,bar\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --features f1,bar -e features\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n└── bar feature \"default\"\n    └── bar v1.0.0\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --features f1,bar -e features -i bar\")\n        .with_stdout_data(str![[r#\"\nbar v1.0.0\n├── bar feature \"default\"\n│   └── foo v0.1.0 ([ROOT]/foo)\n│       ├── foo feature \"bar\" (command-line)\n│       ├── foo feature \"default\" (command-line)\n│       └── foo feature \"f1\" (command-line)\n└── bar feature \"feat\"\n    └── foo feature \"f1\" (command-line)\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree -e features --features bar?/feat\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n\n    // This is a little strange in that it produces no output.\n    // Maybe `cargo tree` should print a note about why?\n    p.cargo(\"tree -e features -i bar --features bar?/feat\")\n        .with_stdout_data(\"\")\n        .run();\n\n    p.cargo(\"tree -e features -i bar --features bar?/feat,bar\")\n        .with_stdout_data(str![[r#\"\nbar v1.0.0\n├── bar feature \"default\"\n│   └── foo v0.1.0 ([ROOT]/foo)\n│       ├── foo feature \"bar\" (command-line)\n│       └── foo feature \"default\" (command-line)\n└── bar feature \"feat\" (command-line)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn publish() {\n    let registry = RegistryBuilder::new().http_api().http_index().build();\n\n    // Publish behavior with /? syntax.\n    Package::new(\"bar\", \"1.0.0\").feature(\"feat\", &[]).publish();\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                description = \"foo\"\n                license = \"MIT\"\n                homepage = \"https://example.com/\"\n\n                [dependencies]\n                bar = { version = \"1.0\", optional = true }\n\n                [features]\n                feat1 = []\n                feat2 = [\"bar?/feat\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"publish\")\n        .replace_crates_io(registry.index_url())\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n[PACKAGING] foo v0.1.0 ([ROOT]/foo)\n[UPDATING] crates.io index\n[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)\n[VERIFYING] foo v0.1.0 ([ROOT]/foo)\n[COMPILING] foo v0.1.0 ([ROOT]/foo/target/package/foo-0.1.0)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n[UPLOADING] foo v0.1.0 ([ROOT]/foo)\n[UPLOADED] foo v0.1.0 to registry `crates-io`\n[NOTE] waiting for foo v0.1.0 to be available at registry `crates-io`\n[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly\n[PUBLISHED] foo v0.1.0 at registry `crates-io`\n\n\"#]])\n        .run();\n\n    publish::validate_upload_with_contents(\n        r#\"\n        {\n          \"authors\": [],\n          \"badges\": {},\n          \"categories\": [],\n          \"deps\": [\n            {\n              \"default_features\": true,\n              \"features\": [],\n              \"kind\": \"normal\",\n              \"name\": \"bar\",\n              \"optional\": true,\n              \"target\": null,\n              \"version_req\": \"^1.0\"\n            }\n          ],\n          \"description\": \"foo\",\n          \"documentation\": null,\n          \"features\": {\n            \"feat1\": [],\n            \"feat2\": [\"bar?/feat\"]\n          },\n          \"homepage\": \"https://example.com/\",\n          \"keywords\": [],\n          \"license\": \"MIT\",\n          \"license_file\": null,\n          \"links\": null,\n          \"name\": \"foo\",\n          \"readme\": null,\n          \"readme_file\": null,\n          \"repository\": null,\n          \"rust_version\": null,\n          \"vers\": \"0.1.0\"\n          }\n        \"#,\n        \"foo-0.1.0.crate\",\n        &[\"Cargo.toml\", \"Cargo.toml.orig\", \"src/lib.rs\", \"Cargo.lock\"],\n        [(\n            \"Cargo.toml\",\n            str![[r##\"\n# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO\n#\n# When uploading crates to the registry Cargo will automatically\n# \"normalize\" Cargo.toml files for maximal compatibility\n# with all versions of Cargo and also rewrite `path` dependencies\n# to registry (e.g., crates.io) dependencies.\n#\n# If you are reading this file be aware that the original Cargo.toml\n# will likely look very different (and much more reasonable).\n# See Cargo.toml.orig for the original contents.\n\n[package]\nedition = \"2015\"\nname = \"foo\"\nversion = \"0.1.0\"\nbuild = false\nautolib = false\nautobins = false\nautoexamples = false\nautotests = false\nautobenches = false\ndescription = \"foo\"\nhomepage = \"https://example.com/\"\nreadme = false\nlicense = \"MIT\"\n\n[features]\nfeat1 = []\nfeat2 = [\"bar?/feat\"]\n\n[lib]\nname = \"foo\"\npath = \"src/lib.rs\"\n\n[dependencies.bar]\nversion = \"1.0\"\noptional = true\n\n\"##]],\n        )],\n    );\n}\n"
  },
  {
    "path": "tests/testsuite/workspaces.rs",
    "content": "//! Tests for workspaces.\n\nuse std::env;\nuse std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::registry::Package;\nuse cargo_test_support::str;\nuse cargo_test_support::{\n    ProjectBuilder, basic_lib_manifest, basic_manifest, git, paths, project, project_in_home,\n    sleep_ms,\n};\n\n#[cargo_test]\nfn simple_explicit() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"..\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!p.bin(\"bar\").is_file());\n\n    p.cargo(\"build\").cwd(\"bar\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(p.bin(\"bar\").is_file());\n\n    assert!(p.root().join(\"Cargo.lock\").is_file());\n    assert!(!p.root().join(\"bar/Cargo.lock\").is_file());\n}\n\n#[cargo_test]\nfn simple_explicit_default_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"bar\"]\n                default-members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"..\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"bar\").is_file());\n    assert!(!p.bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn non_virtual_default_members_build_other_member() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\".\", \"bar\", \"baz\"]\n                default-members = [\"baz\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] baz v0.1.0 ([ROOT]/foo/baz)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check --manifest-path bar/Cargo.toml\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn non_virtual_default_members_build_root_project() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"bar\"]\n                default-members = [\".\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inferred_root() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!p.bin(\"bar\").is_file());\n\n    p.cargo(\"build\").cwd(\"bar\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(p.bin(\"bar\").is_file());\n\n    assert!(p.root().join(\"Cargo.lock\").is_file());\n    assert!(!p.root().join(\"bar/Cargo.lock\").is_file());\n}\n\n#[cargo_test]\nfn inferred_path_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!p.bin(\"bar\").is_file());\n\n    p.cargo(\"build\").cwd(\"bar\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(p.bin(\"bar\").is_file());\n\n    assert!(p.root().join(\"Cargo.lock\").is_file());\n    assert!(!p.root().join(\"bar/Cargo.lock\").is_file());\n}\n\n#[cargo_test]\nfn transitive_path_dep() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"bar\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                baz = { path = \"../baz\" }\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/main.rs\", \"fn main() {}\")\n        .file(\"baz/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!p.bin(\"bar\").is_file());\n    assert!(!p.bin(\"baz\").is_file());\n\n    p.cargo(\"build\").cwd(\"bar\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(p.bin(\"bar\").is_file());\n    assert!(!p.bin(\"baz\").is_file());\n\n    p.cargo(\"build\").cwd(\"baz\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(p.bin(\"bar\").is_file());\n    assert!(p.bin(\"baz\").is_file());\n\n    assert!(p.root().join(\"Cargo.lock\").is_file());\n    assert!(!p.root().join(\"bar/Cargo.lock\").is_file());\n    assert!(!p.root().join(\"baz/Cargo.lock\").is_file());\n}\n\n#[cargo_test]\nfn parent_pointer_works() {\n    let p = project()\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"../bar\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"foo/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"../foo\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"build\").cwd(\"foo\").run();\n    p.cargo(\"build\").cwd(\"bar\").run();\n    assert!(p.root().join(\"foo/Cargo.lock\").is_file());\n    assert!(!p.root().join(\"bar/Cargo.lock\").is_file());\n}\n\n#[cargo_test]\nfn same_names_in_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"..\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] two packages named `foo` in this workspace:\n- [ROOT]/foo/bar/Cargo.toml\n- [ROOT]/foo/Cargo.toml\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn parent_doesnt_point_to_child() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check\")\n        .cwd(\"bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] current package believes it's in a workspace when it's not:\ncurrent:   [ROOT]/foo/bar/Cargo.toml\nworkspace: [ROOT]/foo/Cargo.toml\n\nthis may be fixable by ensuring that this crate is depended on by the workspace root: [ROOT]/foo/Cargo.toml\nAlternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_parent_pointer() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to read `[ROOT]/foo/foo/Cargo.toml`\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn invalid_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"foo\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to load manifest for workspace member `[ROOT]/foo/foo`\nreferenced by workspace at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  failed to read `[ROOT]/foo/foo/Cargo.toml`\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bare_workspace_ok() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn two_roots() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"..\"]\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] multiple workspace roots found in the same workspace:\n  [ROOT]/foo/bar\n  [ROOT]/foo\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_isnt_root() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] root of a workspace inferred but wasn't a root: [ROOT]/foo/bar/Cargo.toml\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dangling_member() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"../baz\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"../baz\"\n            \"#,\n        )\n        .file(\"baz/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package `[ROOT]/foo/bar/Cargo.toml` is a member of the wrong workspace\nexpected: [ROOT]/foo/Cargo.toml\nactual:   [ROOT]/foo/baz/Cargo.toml\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn cycle() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"bar\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"..\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] root of a workspace inferred but wasn't a root: [ROOT]/foo/bar/Cargo.toml\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn share_dependencies() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                dep1 = \"0.1\"\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                dep1 = \"< 0.1.5\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    Package::new(\"dep1\", \"0.1.3\").publish();\n    Package::new(\"dep1\", \"0.1.8\").publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[ADDING] dep1 v0.1.3 (available: v0.1.8)\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep1 v0.1.3 (registry `dummy-registry`)\n[CHECKING] dep1 v0.1.3\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn fetch_fetches_all() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                dep1 = \"*\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    Package::new(\"dep1\", \"0.1.3\").publish();\n\n    p.cargo(\"fetch\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 1 package to latest compatible version\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep1 v0.1.3 (registry `dummy-registry`)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn lock_works_for_everyone() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                dep2 = \"0.1\"\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                dep1 = \"0.1\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    Package::new(\"dep1\", \"0.1.0\").publish();\n    Package::new(\"dep2\", \"0.1.0\").publish();\n\n    p.cargo(\"generate-lockfile\")\n        .with_stderr_data(str![[r#\"\n[UPDATING] `dummy-registry` index\n[LOCKING] 2 packages to latest compatible versions\n\n\"#]])\n        .run();\n\n    Package::new(\"dep1\", \"0.1.1\").publish();\n    Package::new(\"dep2\", \"0.1.1\").publish();\n\n    p.cargo(\"check\")\n        .with_stderr_data(str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep2 v0.1.0 (registry `dummy-registry`)\n[CHECKING] dep2 v0.1.0\n[CHECKING] foo v0.1.0 ([ROOT]/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    p.cargo(\"check\")\n        .cwd(\"bar\")\n        .with_stderr_data(str![[r#\"\n[DOWNLOADING] crates ...\n[DOWNLOADED] dep1 v0.1.0 (registry `dummy-registry`)\n[CHECKING] dep1 v0.1.0\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn virtual_works() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n    p.cargo(\"build\").cwd(\"bar\").run();\n    assert!(p.root().join(\"Cargo.lock\").is_file());\n    assert!(p.bin(\"bar\").is_file());\n    assert!(!p.root().join(\"bar/Cargo.lock\").is_file());\n}\n\n#[cargo_test]\nfn explicit_package_argument_works_with_virtual_manifest() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n    p.cargo(\"build --package bar\").run();\n    assert!(p.root().join(\"Cargo.lock\").is_file());\n    assert!(p.bin(\"bar\").is_file());\n    assert!(!p.root().join(\"bar/Cargo.lock\").is_file());\n}\n\n#[cargo_test]\nfn virtual_misconfigure() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n    p.cargo(\"check\")\n        .cwd(\"bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] current package believes it's in a workspace when it's not:\ncurrent:   [ROOT]/foo/bar/Cargo.toml\nworkspace: [ROOT]/foo/Cargo.toml\n\nthis may be fixable by adding `bar` to the `workspace.members` array of the manifest located at: [ROOT]/foo/Cargo.toml\nAlternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn virtual_build_all_implied() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn virtual_default_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n                default-members = [\"bar\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .file(\"baz/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"bar\").is_file());\n    assert!(!p.bin(\"baz\").is_file());\n}\n\n#[cargo_test]\nfn virtual_default_member_is_not_a_member() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\"]\n                default-members = [\"something-else\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package `[ROOT]/foo/something-else` is listed in default-members but is not a member\nfor workspace at `[ROOT]/foo/Cargo.toml`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn virtual_default_members_build_other_member() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"bar\", \"baz\"]\n                default-members = [\"baz\"]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", \"pub fn bar() {}\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"pub fn baz() {}\")\n        .build();\n\n    p.cargo(\"check --manifest-path bar/Cargo.toml\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] bar v0.1.0 ([ROOT]/foo/bar)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn virtual_build_no_members() {\n    let p = project().file(\n        \"Cargo.toml\",\n        r#\"\n            [workspace]\n        \"#,\n    );\n    let p = p.build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] manifest path `[ROOT]/foo` contains no package: The manifest is virtual, and the workspace has no members.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn include_virtual() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [workspace]\n            \"#,\n        );\n    let p = p.build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] multiple workspace roots found in the same workspace:\n  [ROOT]/foo/bar\n  [ROOT]/foo\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn members_include_path_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"p1\"]\n\n                [dependencies]\n                p3 = { path = \"p3\" }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"p1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"p1\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                p2 = { path = \"../p2\" }\n            \"#,\n        )\n        .file(\"p1/src/lib.rs\", \"\")\n        .file(\"p2/Cargo.toml\", &basic_manifest(\"p2\", \"0.1.0\"))\n        .file(\"p2/src/lib.rs\", \"\")\n        .file(\"p3/Cargo.toml\", &basic_manifest(\"p3\", \"0.1.0\"))\n        .file(\"p3/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"check\").cwd(\"p1\").run();\n    p.cargo(\"check\").cwd(\"p2\").run();\n    p.cargo(\"check\").cwd(\"p3\").run();\n    p.cargo(\"check\").run();\n\n    assert!(p.root().join(\"target\").is_dir());\n    assert!(!p.root().join(\"p1/target\").is_dir());\n    assert!(!p.root().join(\"p2/target\").is_dir());\n    assert!(!p.root().join(\"p3/target\").is_dir());\n}\n\n#[cargo_test]\nfn new_creates_members_list() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"new --lib bar\").with_stderr_data(str![[r#\"\n[CREATING] library `bar` package\n[ADDING] `bar` as member of workspace at `[ROOT]/foo`\n[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn new_warning_with_corrupt_ws() {\n    let p = project().file(\"Cargo.toml\", \"asdf\").build();\n    p.cargo(\"new bar\").with_stderr_data(str![[r#\"\n[CREATING] binary (application) `bar` package\n[ERROR] key with no value, expected `=`\n --> Cargo.toml:1:5\n  |\n1 | asdf\n  |     ^\n[WARNING] compiling this new package may not work due to invalid workspace configuration\n\nfailed searching for potential workspace\npackage manifest: `[ROOT]/foo/bar/Cargo.toml`\ninvalid potential workspace manifest: `[ROOT]/foo/Cargo.toml`\n\n[HELP] to avoid searching for a non-existent workspace, add `[workspace]` to the package manifest\n[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn lock_doesnt_change_depending_on_crate() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = ['baz']\n\n                [dependencies]\n                foo = \"*\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = \"*\"\n            \"#,\n        )\n        .file(\"baz/src/lib.rs\", \"\");\n    let p = p.build();\n\n    Package::new(\"foo\", \"1.0.0\").publish();\n    Package::new(\"bar\", \"1.0.0\").publish();\n\n    p.cargo(\"check\").run();\n\n    let lockfile = p.read_lockfile();\n\n    p.cargo(\"check\").cwd(\"baz\").run();\n\n    let lockfile2 = p.read_lockfile();\n\n    assert_eq!(lockfile, lockfile2);\n}\n\n#[cargo_test]\nfn rebuild_please() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = ['lib', 'bin']\n            \"#,\n        )\n        .file(\"lib/Cargo.toml\", &basic_manifest(\"lib\", \"0.1.0\"))\n        .file(\n            \"lib/src/lib.rs\",\n            r#\"\n                pub fn foo() -> u32 { 0 }\n            \"#,\n        )\n        .file(\n            \"bin/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bin\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                lib = { path = \"../lib\" }\n            \"#,\n        )\n        .file(\n            \"bin/src/main.rs\",\n            r#\"\n                extern crate lib;\n\n                fn main() {\n                    assert_eq!(lib::foo(), 0);\n                }\n            \"#,\n        );\n    let p = p.build();\n\n    p.cargo(\"run\").cwd(\"bin\").run();\n\n    sleep_ms(1000);\n\n    p.change_file(\"lib/src/lib.rs\", \"pub fn foo() -> u32 { 1 }\");\n\n    p.cargo(\"build\").cwd(\"lib\").run();\n\n    p.cargo(\"run\")\n        .cwd(\"bin\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n...\nassertion[..]\n...\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_in_git() {\n    let git_project = git::new(\"dep1\", |project| {\n        project\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                    [workspace]\n                    members = [\"foo\"]\n                \"#,\n            )\n            .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n            .file(\"foo/src/lib.rs\", \"\")\n    });\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"lib\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies.foo]\n                    git = '{}'\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\n            \"src/lib.rs\",\n            r#\"\n                pub fn foo() -> u32 { 0 }\n            \"#,\n        );\n    let p = p.build();\n\n    p.cargo(\"check\").run();\n}\n\n#[cargo_test]\nfn lockfile_can_specify_nonexistent_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n        .file(\"a/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"Cargo.lock\",\n            r#\"\n                [[package]]\n                name = \"a\"\n                version = \"0.1.0\"\n\n                [[package]]\n                name = \"b\"\n                version = \"0.1.0\"\n            \"#,\n        );\n\n    let p = p.build();\n\n    p.cargo(\"check\").cwd(\"a\").run();\n}\n\n#[cargo_test]\nfn you_cannot_generate_lockfile_for_empty_workspaces() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n            \"#,\n        )\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"update\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] you can't generate a lockfile for an empty workspace.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn workspace_with_transitive_dev_deps() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"mbrubeck@example.com\"]\n\n                [dependencies.bar]\n                path = \"bar\"\n\n                [workspace]\n            \"#,\n        )\n        .file(\"src/main.rs\", r#\"fn main() {}\"#)\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.5.0\"\n                edition = \"2015\"\n                authors = [\"mbrubeck@example.com\"]\n\n                [dev-dependencies.baz]\n                path = \"../baz\"\n            \"#,\n        )\n        .file(\n            \"bar/src/lib.rs\",\n            r#\"\n                pub fn init() {}\n\n                #[cfg(test)]\n\n                #[test]\n                fn test() {\n                    extern crate baz;\n                    baz::do_stuff();\n                }\n            \"#,\n        )\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.5.0\"))\n        .file(\"baz/src/lib.rs\", r#\"pub fn do_stuff() {}\"#);\n    let p = p.build();\n\n    p.cargo(\"test -p bar\").run();\n}\n\n#[cargo_test]\nfn error_if_parent_cargo_toml_is_invalid() {\n    let p = project()\n        .file(\"Cargo.toml\", \"Totally not a TOML file\")\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check\")\n        .cwd(\"bar\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] key with no value, expected `=`\n --> ../Cargo.toml:1:9\n  |\n1 | Totally not a TOML file\n  |         ^\n[ERROR] failed searching for potential workspace\npackage manifest: `[ROOT]/foo/bar/Cargo.toml`\ninvalid potential workspace manifest: `[ROOT]/foo/Cargo.toml`\n\n[HELP] to avoid searching for a non-existent workspace, add `[workspace]` to the package manifest\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn relative_path_for_member_works() {\n    let p = project()\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"../bar\"]\n            \"#,\n        )\n        .file(\"foo/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"../foo\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check\").cwd(\"foo\").run();\n    p.cargo(\"check\").cwd(\"bar\").run();\n}\n\n#[cargo_test]\nfn relative_path_for_root_works() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n\n                [dependencies]\n                subproj = { path = \"./subproj\" }\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"subproj/Cargo.toml\", &basic_manifest(\"subproj\", \"0.1.0\"))\n        .file(\"subproj/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check --manifest-path ./Cargo.toml\").run();\n\n    p.cargo(\"check --manifest-path ../Cargo.toml\")\n        .cwd(\"subproj\")\n        .run();\n}\n\n#[cargo_test]\nfn path_dep_outside_workspace_is_not_member() {\n    let p = project()\n        .no_manifest()\n        .file(\n            \"ws/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"ws\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = { path = \"../foo\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"ws/src/lib.rs\", \"extern crate foo;\")\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"check\").cwd(\"ws\").run();\n}\n\n#[cargo_test]\nfn test_in_and_out_of_workspace() {\n    let p = project()\n        .no_manifest()\n        .file(\n            \"ws/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"ws\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = { path = \"../foo\" }\n\n                [workspace]\n                members = [ \"../bar\" ]\n            \"#,\n        )\n        .file(\"ws/src/lib.rs\", \"extern crate foo; pub fn f() { foo::f() }\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"../bar\" }\n            \"#,\n        )\n        .file(\n            \"foo/src/lib.rs\",\n            \"extern crate bar; pub fn f() { bar::f() }\",\n        )\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                workspace = \"../ws\"\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", \"pub fn f() { }\");\n    let p = p.build();\n\n    p.cargo(\"check\").cwd(\"ws\").run();\n\n    assert!(p.root().join(\"ws/Cargo.lock\").is_file());\n    assert!(p.root().join(\"ws/target\").is_dir());\n    assert!(!p.root().join(\"foo/Cargo.lock\").is_file());\n    assert!(!p.root().join(\"foo/target\").is_dir());\n    assert!(!p.root().join(\"bar/Cargo.lock\").is_file());\n    assert!(!p.root().join(\"bar/target\").is_dir());\n\n    p.cargo(\"check\").cwd(\"foo\").run();\n    assert!(p.root().join(\"foo/Cargo.lock\").is_file());\n    assert!(p.root().join(\"foo/target\").is_dir());\n    assert!(!p.root().join(\"bar/Cargo.lock\").is_file());\n    assert!(!p.root().join(\"bar/target\").is_dir());\n}\n\n#[cargo_test]\nfn test_path_dependency_under_member() {\n    let p = project()\n        .file(\n            \"ws/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"ws\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                foo = { path = \"../foo\" }\n\n                [workspace]\n            \"#,\n        )\n        .file(\"ws/src/lib.rs\", \"extern crate foo; pub fn f() { foo::f() }\")\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n                [package]\n                workspace = \"../ws\"\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"./bar\" }\n            \"#,\n        )\n        .file(\n            \"foo/src/lib.rs\",\n            \"extern crate bar; pub fn f() { bar::f() }\",\n        )\n        .file(\"foo/bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"foo/bar/src/lib.rs\", \"pub fn f() { }\");\n    let p = p.build();\n\n    p.cargo(\"check\").cwd(\"ws\").run();\n\n    assert!(!p.root().join(\"foo/bar/Cargo.lock\").is_file());\n    assert!(!p.root().join(\"foo/bar/target\").is_dir());\n\n    p.cargo(\"check\").cwd(\"foo/bar\").run();\n\n    assert!(!p.root().join(\"foo/bar/Cargo.lock\").is_file());\n    assert!(!p.root().join(\"foo/bar/target\").is_dir());\n}\n\n#[cargo_test]\nfn excluded_simple() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"ws\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                exclude = [\"foo\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"check\").run();\n    assert!(p.root().join(\"target\").is_dir());\n    p.cargo(\"check\").cwd(\"foo\").run();\n    assert!(p.root().join(\"foo/target\").is_dir());\n}\n\n#[cargo_test]\nfn exclude_members_preferred() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"ws\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"foo/bar\"]\n                exclude = [\"foo\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\"foo/bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"foo/bar/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"check\").run();\n    assert!(p.root().join(\"target\").is_dir());\n    p.cargo(\"check\").cwd(\"foo\").run();\n    assert!(p.root().join(\"foo/target\").is_dir());\n    p.cargo(\"check\").cwd(\"foo/bar\").run();\n    assert!(!p.root().join(\"foo/bar/target\").is_dir());\n}\n\n#[cargo_test]\nfn exclude_but_also_depend() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"ws\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"foo/bar\" }\n\n                [workspace]\n                exclude = [\"foo\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\"foo/bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"foo/bar/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"check\").run();\n    assert!(p.root().join(\"target\").is_dir());\n    p.cargo(\"check\").cwd(\"foo\").run();\n    assert!(p.root().join(\"foo/target\").is_dir());\n    p.cargo(\"check\").cwd(\"foo/bar\").run();\n    assert!(p.root().join(\"foo/bar/target\").is_dir());\n}\n\n#[cargo_test]\nfn excluded_default_members_still_must_be_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\"]\n                default-members = [\"foo\", \"bar\"]\n                exclude = [\"bar\"]\n            \"#,\n        )\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\"bar/something.txt\", \"\");\n    let p = p.build();\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package `[ROOT]/foo/bar` is listed in default-members but is not a member\nfor workspace at `[ROOT]/foo/Cargo.toml`.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn excluded_default_members_crate_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar/*\"]\n                default-members = [\"bar/*\"]\n                exclude = [\"bar/quux\"]\n            \"#,\n        )\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"bar/baz/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/quux/Cargo.toml\", &basic_manifest(\"quux\", \"0.1.0\"))\n        .file(\"bar/quux/src/main.rs\", \"fn main() {}\");\n\n    let p = p.build();\n    p.cargo(\"build\").run();\n\n    assert!(p.root().join(\"target\").is_dir());\n    assert!(!p.bin(\"foo\").is_file());\n    assert!(p.bin(\"baz\").is_file());\n    assert!(!p.bin(\"quux\").exists());\n\n    p.cargo(\"build --workspace\").run();\n    assert!(p.root().join(\"target\").is_dir());\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!p.bin(\"quux\").exists());\n\n    p.cargo(\"build\").cwd(\"bar/quux\").run();\n    assert!(p.root().join(\"bar/quux/target\").is_dir());\n}\n\n#[cargo_test]\nfn excluded_default_members_not_crate_glob() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar/*\"]\n                default-members = [\"bar/*\"]\n                exclude = [\"bar/docs\"]\n            \"#,\n        )\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"bar/baz/src/main.rs\", \"fn main() {}\")\n        .file(\"bar/docs/readme.txt\", \"This folder is not a crate!\");\n\n    let p = p.build();\n    p.cargo(\"build\").run();\n\n    assert!(!p.bin(\"foo\").is_file());\n    assert!(p.bin(\"baz\").is_file());\n    p.cargo(\"build --workspace\").run();\n    assert!(p.bin(\"foo\").is_file());\n}\n\n#[cargo_test]\nfn glob_syntax() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"crates/*\"]\n                exclude = [\"crates/qux\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"crates/bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"../..\"\n            \"#,\n        )\n        .file(\"crates/bar/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"crates/baz/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"baz\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"../..\"\n            \"#,\n        )\n        .file(\"crates/baz/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"crates/qux/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"qux\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"crates/qux/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!p.bin(\"bar\").is_file());\n    assert!(!p.bin(\"baz\").is_file());\n\n    p.cargo(\"build\").cwd(\"crates/bar\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(p.bin(\"bar\").is_file());\n\n    p.cargo(\"build\").cwd(\"crates/baz\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(p.bin(\"baz\").is_file());\n\n    p.cargo(\"build\").cwd(\"crates/qux\").run();\n    assert!(!p.bin(\"qux\").is_file());\n\n    assert!(p.root().join(\"Cargo.lock\").is_file());\n    assert!(!p.root().join(\"crates/bar/Cargo.lock\").is_file());\n    assert!(!p.root().join(\"crates/baz/Cargo.lock\").is_file());\n    assert!(p.root().join(\"crates/qux/Cargo.lock\").is_file());\n}\n\n/*FIXME: This fails because of how workspace.exclude and workspace.members are working.\n#[cargo_test]\nfn glob_syntax_2() {\n    let p = project()\n        .file(\"Cargo.toml\", r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n\n            [workspace]\n            members = [\"crates/b*\"]\n            exclude = [\"crates/q*\"]\n        \"#)\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"crates/bar/Cargo.toml\", r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            workspace = \"../..\"\n        \"#)\n        .file(\"crates/bar/src/main.rs\", \"fn main() {}\")\n        .file(\"crates/baz/Cargo.toml\", r#\"\n            [package]\n            name = \"baz\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n            workspace = \"../..\"\n        \"#)\n        .file(\"crates/baz/src/main.rs\", \"fn main() {}\")\n        .file(\"crates/qux/Cargo.toml\", r#\"\n            [package]\n            name = \"qux\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            authors = []\n        \"#)\n        .file(\"crates/qux/src/main.rs\", \"fn main() {}\");\n    p.build();\n\n    p.cargo(\"build\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(!p.bin(\"bar\").is_file());\n    assert!(!p.bin(\"baz\").is_file());\n\n    p.cargo(\"build\").cwd(\"crates/bar\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(p.bin(\"bar\").is_file());\n\n    p.cargo(\"build\").cwd(\"crates/baz\").run();\n    assert!(p.bin(\"foo\").is_file());\n    assert!(p.bin(\"baz\").is_file());\n\n    p.cargo(\"build\").cwd(\"crates/qux\").run();\n    assert!(!p.bin(\"qux\").is_file());\n\n    assert!(p.root().join(\"Cargo.lock\").is_file());\n    assert!(!p.root().join(\"crates/bar/Cargo.lock\").is_file());\n    assert!(!p.root().join(\"crates/baz/Cargo.lock\").is_file());\n    assert!(p.root().join(\"crates/qux/Cargo.lock\").is_file());\n}\n*/\n\n#[cargo_test]\nfn glob_syntax_invalid_members() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"crates/*\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"crates/bar/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to load manifest for workspace member `[ROOT]/foo/crates/bar`\nreferenced via `crates/*` by workspace at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  failed to read `[ROOT]/foo/crates/bar/Cargo.toml`\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n/// This is a freshness test for feature use with workspaces.\n///\n/// `feat_lib` is used by `caller1` and `caller2`, but with different features enabled.\n/// This test ensures that alternating building `caller1`, `caller2` doesn't force\n/// recompile of `feat_lib`.\n///\n/// Ideally, once we solve rust-lang/cargo#3620, then a single Cargo build at the top level\n/// will be enough.\n#[cargo_test]\nfn dep_used_with_separate_features() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"feat_lib\", \"caller1\", \"caller2\"]\n            \"#,\n        )\n        .file(\n            \"feat_lib/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"feat_lib\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [features]\n                myfeature = []\n            \"#,\n        )\n        .file(\"feat_lib/src/lib.rs\", \"\")\n        .file(\n            \"caller1/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"caller1\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                feat_lib = { path = \"../feat_lib\" }\n            \"#,\n        )\n        .file(\"caller1/src/main.rs\", \"fn main() {}\")\n        .file(\"caller1/src/lib.rs\", \"\")\n        .file(\n            \"caller2/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"caller2\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                feat_lib = { path = \"../feat_lib\", features = [\"myfeature\"] }\n                caller1 = { path = \"../caller1\" }\n            \"#,\n        )\n        .file(\"caller2/src/main.rs\", \"fn main() {}\")\n        .file(\"caller2/src/lib.rs\", \"\");\n    let p = p.build();\n\n    // Build the entire workspace.\n    p.cargo(\"build --workspace\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] feat_lib v0.1.0 ([ROOT]/foo/feat_lib)\n[COMPILING] caller1 v0.1.0 ([ROOT]/foo/caller1)\n[COMPILING] caller2 v0.1.0 ([ROOT]/foo/caller2)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    assert!(p.bin(\"caller1\").is_file());\n    assert!(p.bin(\"caller2\").is_file());\n\n    // Build `caller1`. Should build the dep library. Because the features\n    // are different than the full workspace, it rebuilds.\n    // Ideally once we solve rust-lang/cargo#3620, then a single Cargo build at the top level\n    // will be enough.\n    p.cargo(\"build\")\n        .cwd(\"caller1\")\n        .with_stderr_data(str![[r#\"\n[COMPILING] feat_lib v0.1.0 ([ROOT]/foo/feat_lib)\n[COMPILING] caller1 v0.1.0 ([ROOT]/foo/caller1)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n\n    // Alternate building `caller2`/`caller1` a few times, just to make sure\n    // features are being built separately. Should not rebuild anything.\n    p.cargo(\"build\")\n        .cwd(\"caller2\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build\")\n        .cwd(\"caller1\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n    p.cargo(\"build\")\n        .cwd(\"caller2\")\n        .with_stderr_data(str![[r#\"\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn dont_recurse_out_of_cargo_home() {\n    let git_project = git::new(\"dep\", |project| {\n        project\n            .file(\"Cargo.toml\", &basic_manifest(\"dep\", \"0.1.0\"))\n            .file(\"src/lib.rs\", \"\")\n            .file(\n                \"build.rs\",\n                r#\"\n                    use std::env;\n                    use std::path::Path;\n                    use std::process::{self, Command};\n\n                    fn main() {\n                        let cargo = env::var_os(\"CARGO\").unwrap();\n                        let cargo_manifest_dir = env::var_os(\"CARGO_MANIFEST_DIR\").unwrap();\n                        let output = Command::new(cargo)\n                            .args(&[\"metadata\", \"--format-version\", \"1\", \"--manifest-path\"])\n                            .arg(&Path::new(&cargo_manifest_dir).join(\"Cargo.toml\"))\n                            .output()\n                            .unwrap();\n                        if !output.status.success() {\n                            eprintln!(\"{}\", String::from_utf8(output.stderr).unwrap());\n                            process::exit(1);\n                        }\n                    }\n                \"#,\n            )\n    });\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            &format!(\n                r#\"\n                    [package]\n                    name = \"foo\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    [dependencies.dep]\n                    git = \"{}\"\n\n                    [workspace]\n                \"#,\n                git_project.url()\n            ),\n        )\n        .file(\"src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"check\")\n        .env(\"CARGO_HOME\", p.root().join(\".cargo\"))\n        .run();\n}\n\n// FIXME: this fails because of how workspace.exclude and workspace.members are working.\n/*\n#[cargo_test]\nfn include_and_exclude() {\n    let p = project()\n        .file(\"Cargo.toml\", r#\"\n            [workspace]\n            members = [\"foo\"]\n            exclude = [\"foo/bar\"]\n            \"#)\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", \"\")\n        .file(\"foo/bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"foo/bar/src/lib.rs\", \"\");\n    p.build();\n\n    p.cargo(\"build\").cwd(\"foo\").run();\n    assert!(p.root().join(\"target\").is_dir());\n    assert!(!p.root().join(\"foo/target\").is_dir());\n    p.cargo(\"build\").cwd(\"foo/bar\").run();\n    assert!(p.root().join(\"foo/bar/target\").is_dir());\n}\n*/\n\n#[cargo_test]\nfn cargo_home_at_root_works() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"a\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"a/Cargo.toml\", &basic_manifest(\"a\", \"0.1.0\"))\n        .file(\"a/src/lib.rs\", \"\");\n    let p = p.build();\n\n    p.cargo(\"check\").run();\n    p.cargo(\"check --frozen\").env(\"CARGO_HOME\", p.root()).run();\n}\n\n#[cargo_test]\nfn parent_manifest_error_mentions_workspace_search() {\n    ProjectBuilder::new(paths::home())\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"home-manifest\"\n                version = \"0.1.0\"\n                authors = []\n            \"#,\n        )\n        .build();\n\n    let p = project_in_home(\"stuff\")\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed searching for potential workspace\npackage manifest: `[ROOT]/home/stuff/Cargo.toml`\ninvalid potential workspace manifest: `[ROOT]/home/Cargo.toml`\n\n[HELP] to avoid searching for a non-existent workspace, add `[workspace]` to the package manifest\n\nCaused by:\n  failed to parse manifest at `[ROOT]/home/Cargo.toml`\n\nCaused by:\n  no targets specified in the manifest\n  either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn relative_rustc() {\n    let p = project()\n        .file(\n            \"src/main.rs\",\n            r#\"\n                use std::process::Command;\n                use std::env;\n\n                fn main() {\n                    let mut cmd = Command::new(\"rustc\");\n                    for arg in env::args_os().skip(1) {\n                        cmd.arg(arg);\n                    }\n                    std::process::exit(cmd.status().unwrap().code().unwrap());\n                }\n            \"#,\n        )\n        .build();\n    p.cargo(\"build\").run();\n\n    let src = p\n        .root()\n        .join(\"target/debug/foo\")\n        .with_extension(env::consts::EXE_EXTENSION);\n\n    Package::new(\"a\", \"0.1.0\").publish();\n\n    let p = project()\n        .at(\"lib\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"lib\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                a = \"0.1\"\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    fs::copy(&src, p.root().join(src.file_name().unwrap())).unwrap();\n\n    let file = format!(\"./foo{}\", env::consts::EXE_SUFFIX);\n    p.cargo(\"build\").env(\"RUSTC\", &file).run();\n}\n\n#[cargo_test]\nfn ws_rustc_err() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"a\"]\n            \"#,\n        )\n        .file(\"a/Cargo.toml\", &basic_lib_manifest(\"a\"))\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"rustc\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] manifest path `[ROOT]/foo/Cargo.toml` is a virtual manifest, but this command requires running against an actual package in this workspace\n\n\"#]])\n        .run();\n\n    p.cargo(\"rustdoc\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] manifest path `[ROOT]/foo/Cargo.toml` is a virtual manifest, but this command requires running against an actual package in this workspace\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn ws_err_unused() {\n    for table in &[\n        \"[lib]\",\n        \"[[bin]]\",\n        \"[[example]]\",\n        \"[[test]]\",\n        \"[[bench]]\",\n        \"[dependencies]\",\n        \"[dev-dependencies]\",\n        \"[build-dependencies]\",\n        \"[features]\",\n        \"[target]\",\n        \"[badges]\",\n        \"[lints]\",\n    ] {\n        let key = table.trim_start_matches('[').trim_end_matches(']');\n        let p = project()\n            .file(\n                \"Cargo.toml\",\n                &format!(\n                    r#\"\n                    [workspace]\n                    members = [\"a\"]\n\n                    {table}\n                    \"#,\n                ),\n            )\n            .file(\"a/Cargo.toml\", &basic_lib_manifest(\"a\"))\n            .file(\"a/src/lib.rs\", \"\")\n            .build();\n        p.cargo(\"check\")\n            .with_status(101)\n            .with_stderr_data(&format!(\n                \"\\\n[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml`\n\nCaused by:\n  this virtual manifest specifies a `{key}` section, which is not allowed\n\",\n            ))\n            .run();\n    }\n}\n\n#[cargo_test]\nfn ws_warn_unused() {\n    for (key, name) in &[\n        (\"[profile.dev]\\nopt-level = 1\", \"profiles\"),\n        (\"[replace]\\n\\\"bar:0.1.0\\\" = { path = \\\"bar\\\" }\", \"replace\"),\n        (\"[patch.crates-io]\\nbar = { path = \\\"bar\\\" }\", \"patch\"),\n    ] {\n        let p = project()\n            .file(\n                \"Cargo.toml\",\n                r#\"\n                [workspace]\n                members = [\"a\"]\n                \"#,\n            )\n            .file(\n                \"a/Cargo.toml\",\n                &format!(\n                    r#\"\n                    [package]\n                    name = \"a\"\n                    version = \"0.1.0\"\n                    edition = \"2015\"\n\n                    {}\n                    \"#,\n                    key\n                ),\n            )\n            .file(\"a/src/lib.rs\", \"\")\n            .build();\n        p.cargo(\"check\")\n            .with_stderr_data(&format!(\n                \"\\\n[WARNING] {} for the non root package will be ignored, specify {} at the workspace root:\npackage:   [ROOT]/foo/a/Cargo.toml\nworkspace: [ROOT]/foo/Cargo.toml\n[CHECKING] a v0.1.0 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\",\n                name, name\n            ))\n            .run();\n    }\n}\n\n#[cargo_test]\nfn ws_warn_path() {\n    // Warnings include path to manifest.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"a\"]\n            \"#,\n        )\n        .file(\n            \"a/Cargo.toml\",\n            r#\"\n            cargo-features = [\"edition\"]\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2015\"\n            \"#,\n        )\n        .file(\"a/src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check\").with_stderr_data(str![[r#\"\n[WARNING] [ROOT]/foo/a/Cargo.toml: the cargo feature `edition` has been stabilized in the 1.31 release and is no longer necessary to be listed in the manifest\n  See https://doc.rust-lang.org/cargo/reference/manifest.html#the-edition-field for more information about using this feature.\n[CHECKING] foo v0.1.0 ([ROOT]/foo/a)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]]).run();\n}\n\n#[cargo_test]\nfn invalid_missing() {\n    // Make sure errors are not suppressed with -q.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                x = { path = 'x' }\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .build();\n\n    p.cargo(\"check -q\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to get `x` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`\n\nCaused by:\n  failed to load source for dependency `x`\n\nCaused by:\n  unable to update [ROOT]/foo/x\n\nCaused by:\n  failed to read `[ROOT]/foo/x/Cargo.toml`\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn member_dep_missing() {\n    // Make sure errors are not suppressed with -q.\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [dependencies]\n                baz = { path = \"baz\" }\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"check -q\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] failed to load manifest for workspace member `[ROOT]/foo/bar`\nreferenced by workspace at `[ROOT]/foo/Cargo.toml`\n\nCaused by:\n  failed to load manifest for dependency `baz`\n\nCaused by:\n  failed to read `[ROOT]/foo/bar/baz/Cargo.toml`\n\nCaused by:\n  [NOT_FOUND]\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn simple_primary_package_env_var() {\n    let is_primary_package = r#\"\n        #[test]\n        fn verify_primary_package() {{\n            assert!(option_env!(\"CARGO_PRIMARY_PACKAGE\").is_some());\n        }}\n    \"#;\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [workspace]\n                members = [\"bar\"]\n            \"#,\n        )\n        .file(\"src/lib.rs\", is_primary_package)\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n                workspace = \"..\"\n            \"#,\n        )\n        .file(\"bar/src/lib.rs\", is_primary_package);\n    let p = p.build();\n\n    p.cargo(\"test\").run();\n\n    // Again, this time selecting a specific crate\n    p.cargo(\"clean\").run();\n    p.cargo(\"test -p bar\").run();\n\n    // Again, this time selecting all crates\n    p.cargo(\"clean\").run();\n    p.cargo(\"test --all\").run();\n}\n\n#[cargo_test]\nfn virtual_primary_package_env_var() {\n    let is_primary_package = r#\"\n        #[test]\n        fn verify_primary_package() {{\n            assert!(option_env!(\"CARGO_PRIMARY_PACKAGE\").is_some());\n        }}\n    \"#;\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\", \"bar\"]\n            \"#,\n        )\n        .file(\"foo/Cargo.toml\", &basic_manifest(\"foo\", \"0.1.0\"))\n        .file(\"foo/src/lib.rs\", is_primary_package)\n        .file(\"bar/Cargo.toml\", &basic_manifest(\"bar\", \"0.1.0\"))\n        .file(\"bar/src/lib.rs\", is_primary_package);\n    let p = p.build();\n\n    p.cargo(\"test\").run();\n\n    // Again, this time selecting a specific crate\n    p.cargo(\"clean\").run();\n    p.cargo(\"test -p foo\").run();\n}\n\n#[cargo_test]\nfn ensure_correct_workspace_when_nested() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [workspace]\n\n                [package]\n                name = \"bar\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n            \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\n            \"sub/Cargo.toml\",\n            r#\"\n                [workspace]\n                members = [\"foo\"]\n            \"#,\n        )\n        .file(\n            \"sub/foo/Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                authors = []\n\n                [dependencies]\n                bar = { path = \"../..\"}\n            \"#,\n        )\n        .file(\"sub/foo/src/main.rs\", \"fn main() {}\");\n    let p = p.build();\n    p.cargo(\"tree\")\n        .cwd(\"sub/foo\")\n        .with_stdout_data(str![[r#\"\nfoo v0.1.0 ([ROOT]/foo/sub/foo)\n└── bar v0.1.0 ([ROOT]/foo)\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn nonexistence_package_together_with_workspace() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            authors = []\n            edition = \"2021\"\n\n            [workspace]\n            members = [\"baz\"]\n        \"#,\n        )\n        .file(\"src/lib.rs\", \"\")\n        .file(\"baz/Cargo.toml\", &basic_manifest(\"baz\", \"0.1.0\"))\n        .file(\"baz/src/lib.rs\", \"\");\n\n    let p = p.build();\n\n    p.cargo(\"check --package nonexistence --workspace\")\n        .with_status(101)\n        .with_stderr_data(\n            str![[r#\"\n[ERROR] package(s) `nonexistence` not found in workspace `[ROOT]/foo`\n\n\"#]]\n            .unordered(),\n        )\n        .run();\n    // With pattern *\n    p.cargo(\"check --package nonpattern* --workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package pattern(s) `nonpattern*` not found in workspace `[ROOT]/foo`\n\n\"#]])\n        .run();\n\n    p.cargo(\"package --package nonexistence --workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package(s) `nonexistence` not found in workspace `[ROOT]/foo`\n\n\"#]])\n        .run();\n    // With pattern *\n    p.cargo(\"package --package nonpattern* --workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package pattern(s) `nonpattern*` not found in workspace `[ROOT]/foo`\n\n\"#]])\n        .run();\n\n    p.cargo(\"publish --dry-run --package nonexistence --workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package(s) `nonexistence` not found in workspace `[ROOT]/foo`\n\n\"#]])\n        .run();\n    // With pattern *\n    p.cargo(\"publish --dry-run --package nonpattern* --workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package pattern(s) `nonpattern*` not found in workspace `[ROOT]/foo`\n\n\"#]])\n        .run();\n\n    p.cargo(\"tree --package nonexistence  --workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package(s) `nonexistence` not found in workspace `[ROOT]/foo`\n\n\"#]])\n        .run();\n    // With pattern *\n    p.cargo(\"tree --package nonpattern*  --workspace\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] package pattern(s) `nonpattern*` not found in workspace `[ROOT]/foo`\n\n\"#]])\n        .run();\n}\n\n// A failing case from <https://github.com/rust-lang/cargo/issues/15625>\n#[cargo_test]\nfn fix_only_check_manifest_path_member() {\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n            [workspace]\n            members = [\"foo\", \"bar\"]\n            resolver = \"3\"\n            \"#,\n        )\n        .file(\n            \"foo/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"foo\"\n            version = \"0.1.0\"\n            edition = \"2021\"\n            \"#,\n        )\n        .file(\"foo/src/main.rs\", \"fn main() {}\")\n        .file(\n            \"bar/Cargo.toml\",\n            r#\"\n            [package]\n            name = \"bar\"\n            version = \"0.1.0\"\n            edition = \"2021\"\n            \"#,\n        )\n        .file(\"bar/src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"fix --manifest-path foo/Cargo.toml --allow-no-vcs\")\n        .with_stderr_data(str![[r#\"\n[CHECKING] foo v0.1.0 ([ROOT]/foo/foo)\n[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn error_if_member_is_outside_root() {\n    // This test ensures that if a member is physically outside the workspace root,\n    // we get a helpful error message.\n    //\n    // Setup:\n    // root/Cargo.toml     (workspace, members = [])\n    // member/Cargo.toml   (package, workspace = \"../root\")\n\n    let _root = project()\n        .at(\"root\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"root\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    let member = project()\n        .at(\"member\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"member\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                workspace = \"../root\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // The error message should reflect that these paths are unrelated (Old Behavior)\n    member.cargo(\"build\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] current package believes it's in a workspace when it's not:\ncurrent:   [ROOT]/member/Cargo.toml\nworkspace: [ROOT]/root/Cargo.toml\n\nthis may be fixable by adding `../member` to the `workspace.members` array of the manifest located at: [ROOT]/root/Cargo.toml\nAlternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest.\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn error_if_manifest_path_is_relative() {\n    // This test simulates running cargo usage with a relative --manifest-path\n    // that includes `..` to verify normalization and suggestions.\n    //\n    // Directory structure:\n    // root/Cargo.toml\n    // root/subdir/\n    // outside/Cargo.toml  (workspace = \"../root\")\n\n    let root = project()\n        .at(\"root\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"root\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n\n                [workspace]\n                members = []\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .file(\"subdir/file\", \"\")\n        .build();\n\n    let _outside = project()\n        .at(\"outside\")\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"outside\"\n                version = \"0.1.0\"\n                edition = \"2015\"\n                workspace = \"../root\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // Run from `root/subdir` pointing to `../../outside/Cargo.toml`\n    // The workspace root is at `root`.\n    // The package is at `outside`.\n    // Relative path from root to outside is `../outside`.\n\n    // We execute inside `root`, but targeting the outside package.\n    root.cargo(\"build\")\n        .cwd(root.root().join(\"subdir\"))\n        .arg(\"-v\")\n        .arg(\"--manifest-path\")\n        .arg(\"../../outside/Cargo.toml\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] current package believes it's in a workspace when it's not:\ncurrent:   [ROOT]/outside/Cargo.toml\nworkspace: [ROOT]/root/Cargo.toml\n\nthis may be fixable by adding `../outside` to the `workspace.members` array of the manifest located at: [ROOT]/root/Cargo.toml\nAlternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest.\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "tests/testsuite/yank.rs",
    "content": "//! Tests for the `cargo yank` command.\n\nuse std::fs;\n\nuse crate::prelude::*;\nuse cargo_test_support::project;\nuse cargo_test_support::registry;\nuse cargo_test_support::str;\n\nfn setup(name: &str, version: &str) {\n    let dir = registry::api_path().join(format!(\"api/v1/crates/{}/{}\", name, version));\n    dir.mkdir_p();\n    fs::write(dir.join(\"yank\"), r#\"{\"ok\": true}\"#).unwrap();\n}\n\n#[cargo_test]\nfn explicit_version() {\n    let registry = registry::init();\n    setup(\"foo\", \"0.0.1\");\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"yank --version 0.0.1\")\n        .replace_crates_io(registry.index_url())\n        .run();\n\n    p.cargo(\"yank --undo --version 0.0.1\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n      Unyank foo@0.0.1\n[ERROR] failed to undo a yank from the registry at [ROOTURL]/api\n\nCaused by:\n  EOF while parsing a value at line 1 column 0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn explicit_version_with_asymmetric() {\n    let registry = registry::RegistryBuilder::new()\n        .http_api()\n        .token(cargo_test_support::registry::Token::rfc_key())\n        .build();\n    setup(\"foo\", \"0.0.1\");\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [project]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    // The http_api server will check that the authorization is correct.\n    // If the authorization was not sent then we would get an unauthorized error.\n    p.cargo(\"yank --version 0.0.1\")\n        .arg(\"-Zasymmetric-token\")\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .replace_crates_io(registry.index_url())\n        .run();\n\n    p.cargo(\"yank --undo --version 0.0.1\")\n        .arg(\"-Zasymmetric-token\")\n        .masquerade_as_nightly_cargo(&[\"asymmetric-token\"])\n        .replace_crates_io(registry.index_url())\n        .run();\n}\n\n#[cargo_test]\nfn inline_version() {\n    let registry = registry::init();\n    setup(\"foo\", \"0.0.1\");\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"yank foo@0.0.1\")\n        .replace_crates_io(registry.index_url())\n        .run();\n\n    p.cargo(\"yank --undo foo@0.0.1\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[UPDATING] crates.io index\n      Unyank foo@0.0.1\n[ERROR] failed to undo a yank from the registry at [ROOTURL]/api\n\nCaused by:\n  EOF while parsing a value at line 1 column 0\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn version_required() {\n    setup(\"foo\", \"0.0.1\");\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"yank foo\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] `--version` is required\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inline_version_without_name() {\n    setup(\"foo\", \"0.0.1\");\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"yank @0.0.1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] missing crate name for `@0.0.1`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn inline_and_explicit_version() {\n    setup(\"foo\", \"0.0.1\");\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"yank foo@0.0.1 --version 0.0.1\")\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] cannot specify both `@0.0.1` and `--version`\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn bad_version() {\n    let registry = registry::init();\n    setup(\"foo\", \"0.0.1\");\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"yank foo@bar\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] invalid version `bar`\n\nCaused by:\n  unexpected character 'b' while parsing major version number\n\n\"#]])\n        .run();\n}\n\n#[cargo_test]\nfn prefixed_v_in_version() {\n    let registry = registry::init();\n    setup(\"foo\", \"0.0.1\");\n\n    let p = project()\n        .file(\n            \"Cargo.toml\",\n            r#\"\n                [package]\n                name = \"foo\"\n                version = \"0.0.1\"\n                authors = []\n                license = \"MIT\"\n                description = \"foo\"\n            \"#,\n        )\n        .file(\"src/main.rs\", \"fn main() {}\")\n        .build();\n\n    p.cargo(\"yank bar@v0.0.1\")\n        .replace_crates_io(registry.index_url())\n        .with_status(101)\n        .with_stderr_data(str![[r#\"\n[ERROR] the version provided, `v0.0.1` is not a valid SemVer version\n\n[HELP] try changing the version to `0.0.1`\n\nCaused by:\n  unexpected character 'v' while parsing major version number\n\n\"#]])\n        .run();\n}\n"
  },
  {
    "path": "triagebot.toml",
    "content": "[relabel]\nallow-unauthenticated = [\n    \"A-*\",\n    \"C-*\",\n    \"Command-*\",\n    \"E-*\",\n    \"I-*\",\n    \"O-*\",\n    \"S-*\",\n    \"Z-*\",\n    \"beta-nominated\",\n    \"regression-*\",\n    \"relnotes\",\n]\n\n[ping.windows]\nmessage = \"\"\"\\\nHey Windows Group! This bug has been identified as a good \"Windows candidate\".\nIn case it's useful, here are some [instructions] for tackling these sorts of\nbugs. Maybe take a look?\nThanks! <3\n\n[instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/windows.html\n\"\"\"\nlabel = \"O-windows\"\n\n[shortcut]\n\n# Enable issue transfers within the org\n# Documentation at: https://forge.rust-lang.org/triagebot/transfer.html\n[transfer]\n\n# Enable `@rustbot note` functionality\n# Documentation at: https://forge.rust-lang.org/triagebot/note.html\n[note]\n\n# Enable comments linking to triagebot range-diff when a PR is rebased\n# onto a different base commit\n# Documentation at: https://forge.rust-lang.org/triagebot/range-diff.html\n[range-diff]\n\n# Adds at the end of a review body a link to view the changes that happened\n# since the review\n# Documentation at: https://forge.rust-lang.org/triagebot/review-changes-since.html\n[review-changes-since]\n\n# Adds a \"View all comments\" link on the issue body that shows all the comments of an issue/PR\n# Documentation at: https://forge.rust-lang.org/triagebot/view-all-comments-link.html\n[view-all-comments-link]\nthreshold = 20\n\n[merge-conflicts]\nremove = []\nadd = [\"S-waiting-on-author\"]\nunless = [\"S-blocked\", \"S-waiting-on-review\"]\n\n[autolabel.\"S-waiting-on-review\"]\nnew_pr = true\n\n[assign]\ncontributing_url = \"https://rust-lang.github.io/cargo/contrib/\"\nwarn_non_default_branch = true\n\n[assign.owners]\n\"*\" = [\"@ehuss\", \"@epage\", \"@weihanglo\"]\n\n[review-submitted]\nreviewed_label = \"S-waiting-on-author\"\nreview_labels = [\"S-waiting-on-review\"]\n\n[review-requested]\nremove_labels = [\"S-waiting-on-author\"]\nadd_labels = [\"S-waiting-on-review\"]\n\n[autolabel.\"A-build-execution\"]\ntrigger_files = [\n  \"src/cargo/core/compiler/compilation.rs\",\n  \"src/cargo/core/compiler/job_queue/\",\n  \"src/cargo/core/compiler/mod.rs\",\n]\n\n[autolabel.\"A-build-scripts\"]\ntrigger_files = [\n  \"crates/build-rs-test-lib/\",\n  \"crates/build-rs/\",\n  \"src/cargo/core/compiler/custom_build.rs\",\n]\n\n[autolabel.\"A-cache-messages\"]\ntrigger_files = [\"src/cargo/util/rustc.rs\"]\n\n[autolabel.\"A-cargo-targets\"]\ntrigger_files = [\n  \"src/cargo/ops/cargo_compile/compile_filter.rs\",\n  \"src/cargo/ops/cargo_compile/unit_generator.rs\",\n]\n\n[autolabel.\"A-cfg-expr\"]\ntrigger_files = [\n  \"crates/cargo-platform/\",\n  \"src/cargo/core/compiler/build_context/target_info.rs\",\n]\n\n[autolabel.\"A-cli\"]\ntrigger_files = [\"src/bin/\", \"src/cargo/util/command_prelude.rs\"]\n\n[autolabel.\"A-cli-help\"]\ntrigger_files = [\"crates/mdman/\", \"src/etc/man/\"]\n\n[autolabel.\"A-completions\"]\ntrigger_files = [\"src/etc/_cargo\", \"src/etc/cargo.bashcomp.sh\"]\n\n[autolabel.\"A-configuration\"]\ntrigger_files = [\"src/cargo/util/context/mod.rs\"]\n\n[autolabel.\"A-console-output\"]\ntrigger_files = [\n  \"src/cargo/core/shell.rs\",\n  \"src/cargo/util/progress.rs\",\n]\n\n[autolabel.\"A-crate-dependencies\"]\ntrigger_files = [\"src/cargo/core/dependency.rs\"]\n\n[autolabel.\"A-crate-types\"]\ntrigger_files = [\"src/cargo/core/compiler/crate_type.rs\"]\n\n[autolabel.\"A-credential-provider\"]\ntrigger_files = [\"credential/\"]\n\n[autolabel.\"A-dep-info\"]\ntrigger_files = [\"src/cargo/core/compiler/output_depinfo.rs\"]\n\n[autolabel.\"A-dependency-resolution\"]\ntrigger_files = [\n  \"benches/benchsuite/benches/resolve.rs\",\n  \"crates/resolver-tests/\",\n  \"src/cargo/core/resolver/\",\n]\n\n[autolabel.\"A-directory-source\"]\ntrigger_files = [\"src/cargo/sources/directory.rs\"]\n\n[autolabel.\"A-documenting-cargo-itself\"]\ntrigger_files = [\"src/doc/\"]\n\n[autolabel.\"A-environment-variables\"]\ntrigger_files = [\n  \"crates/home/\",\n  \"src/cargo/util/context/environment.rs\",\n]\n\n[autolabel.\"A-features2\"]\ntrigger_files = [\"src/cargo/core/resolver/features.rs\"]\n\n[autolabel.\"A-filesystem\"]\ntrigger_files = [\"src/cargo/util/flock.rs\", \"src/cargo/util/important_paths.rs\"]\n\n[autolabel.\"A-future-incompat\"]\ntrigger_files = [\"src/cargo/core/compiler/future_incompat.rs\"]\n\n[autolabel.\"A-git\"]\ntrigger_files = [\"src/cargo/sources/git/\", \"src/cargo/ops/cargo_package/vcs.rs\"]\n\n[autolabel.\"A-home\"]\ntrigger_files = [\"crates/home/\"]\n\n[autolabel.\"A-infrastructure\"]\ntrigger_files = [\n  \".cargo/\",\n  \".github/\",\n  \"build.rs\",\n  \"ci/\",\n  \"clippy.toml\",\n  \"crates/xtask-\",\n  \"deny.toml\",\n  \"publish.py\",\n  \"triagebot.toml\",\n]\n\n[autolabel.\"A-interacts-with-crates.io\"]\ntrigger_files = [\"crates/crates-io/\", \"src/cargo/ops/registry/\"]\n\n[autolabel.\"A-json-output\"]\ntrigger_files = [\"src/cargo/util/machine_message.rs\"]\n\n[autolabel.\"A-layout\"]\ntrigger_files = [\n  \"src/cargo/core/compiler/build_runner/compilation_files.rs\",\n  \"src/cargo/core/compiler/layout.rs\",\n]\n\n[autolabel.\"A-links\"]\ntrigger_files = [\"src/cargo/core/compiler/links.rs\"]\n\n[autolabel.\"A-local-registry-source\"]\ntrigger_files = [\"src/cargo/sources/registry/local.rs\"]\n\n[autolabel.\"A-lockfile\"]\ntrigger_files = [\"src/cargo/ops/lockfile.rs\", \"src/cargo/core/resolver/encode.rs\"]\n\n[autolabel.\"A-lto\"]\ntrigger_files = [\"src/cargo/core/compiler/lto.rs\"]\n\n[autolabel.\"A-manifest\"]\ntrigger_files = [\n    \"crates/cargo-util-schemas/src/manifest/\",\n    \"src/cargo/core/manifest.rs\",\n    \"src/cargo/util/toml/mod.rs\",\n    \"src/cargo/util/toml_mut/\",\n]\n\n[autolabel.\"A-networking\"]\ntrigger_files = [\"src/cargo/util/network/\"]\n\n[autolabel.\"A-overrides\"]\ntrigger_files = [\"src/cargo/sources/replaced.rs\"]\n\n[autolabel.\"A-profiles\"]\ntrigger_files = [\"src/cargo/core/profiles.rs\"]\n\n[autolabel.\"A-rebuild-detection\"]\ntrigger_files = [\"src/cargo/core/compiler/fingerprint/\"]\n\n[autolabel.\"A-registries\"]\ntrigger_files = [\"src/cargo/sources/registry/\", \"src/cargo/core/registry.rs\"]\n\n[autolabel.\"A-registry-authentication\"]\ntrigger_files = [\"src/cargo/util/auth/\"]\n\n[autolabel.\"A-semver\"]\ntrigger_files = [\n  \"crates/semver-check\",\n  \"src/cargo/util/semver_ext.rs\",\n]\n\n[autolabel.\"A-source-replacement\"]\ntrigger_files = [\"src/cargo/sources/replaced.rs\"]\n\n[autolabel.\"A-sparse-registry\"]\ntrigger_files = [\"src/cargo/sources/registry/http_remote.rs\"]\n\n[autolabel.\"A-testing-cargo-itself\"]\ntrigger_files = [\n    \"benches/\",\n    \"crates/cargo-test-macro/\",\n    \"crates/cargo-test-support/\",\n]\n\n[autolabel.\"A-timings\"]\ntrigger_files = [\n    \"src/cargo/core/compiler/timings/\",\n    \"src/cargo/util/cpu.rs\",\n]\n\n[autolabel.\"A-unstable\"]\ntrigger_files = [\"src/cargo/core/features.rs\"]\n\n[autolabel.\"A-vcs\"]\ntrigger_files = [\"src/cargo/util/vcs.rs\"]\n\n[autolabel.\"A-workspaces\"]\ntrigger_files = [\n  \"benches/benchsuite/benches/workspace_initialization.rs\",\n  \"src/cargo/core/workspace.rs\",\n  \"src/cargo/util/workspace.rs\"\n]\n\n[autolabel.\"Command-add\"]\ntrigger_files = [\"src/bin/cargo/commands/add.rs\", \"src/cargo/ops/cargo_add/\"]\n\n[autolabel.\"Command-bench\"]\ntrigger_files = [\"src/bin/cargo/commands/bench.rs\"]\n\n[autolabel.\"Command-build\"]\ntrigger_files = [\"src/bin/cargo/commands/build.rs\"]\n\n[autolabel.\"Command-check\"]\ntrigger_files = [\"src/bin/cargo/commands/check.rs\"]\n\n[autolabel.\"Command-clean\"]\ntrigger_files = [\"src/bin/cargo/commands/clean.rs\", \"src/cargo/ops/cargo_clean.rs\"]\n\n[autolabel.\"Command-doc\"]\ntrigger_files = [\"src/bin/cargo/commands/doc.rs\", \"src/cargo/ops/cargo_doc.rs\"]\n\n[autolabel.\"Command-fetch\"]\ntrigger_files = [\"src/bin/cargo/commands/fetch.rs\", \"src/cargo/ops/cargo_fetch.rs\"]\n\n[autolabel.\"Command-fix\"]\ntrigger_files = [\n    \"crates/rustfix/\",\n    \"src/bin/cargo/commands/fix.rs\",\n    \"src/cargo/ops/fix/\",\n    \"src/cargo/util/diagnostic_server.rs\",\n    \"src/cargo/util/lockserver.rs\",\n]\n\n[autolabel.\"Command-generate-lockfile\"]\ntrigger_files = [\"src/bin/cargo/commands/generate_lockfile.rs\"]\n\n[autolabel.\"Command-git-checkout\"]\ntrigger_files = [\"src/bin/cargo/commands/git_checkout.rs\"]\n\n[autolabel.\"Command-info\"]\ntrigger_files = [\"src/bin/cargo/commands/info.rs\", \"src/cargo/ops/registry/info/\"]\n\n[autolabel.\"Command-init\"]\ntrigger_files = [\"src/bin/cargo/commands/init.rs\"]\n\n[autolabel.\"Command-install\"]\ntrigger_files = [\"src/bin/cargo/commands/install.rs\", \"src/cargo/ops/cargo_install.rs\"]\n\n[autolabel.\"Command-locate-project\"]\ntrigger_files = [\"src/bin/cargo/commands/locate_project.rs\"]\n\n[autolabel.\"Command-login\"]\ntrigger_files = [\"src/bin/cargo/commands/login.rs\", \"src/cargo/ops/registry/login.rs\"]\n\n[autolabel.\"Command-logout\"]\ntrigger_files = [\"src/bin/cargo/commands/logout.rs\", \"src/cargo/ops/registry/logout.rs\"]\n\n[autolabel.\"Command-metadata\"]\ntrigger_files = [\"src/bin/cargo/commands/metadata.rs\", \"src/cargo/ops/cargo_output_metadata.rs\"]\n\n[autolabel.\"Command-new\"]\ntrigger_files = [\"src/bin/cargo/commands/new.rs\", \"src/cargo/ops/cargo_new.rs\"]\n\n[autolabel.\"Command-owner\"]\ntrigger_files = [\"src/bin/cargo/commands/owner.rs\", \"src/cargo/ops/registry/owner.rs\"]\n\n[autolabel.\"Command-package\"]\ntrigger_files = [\"src/bin/cargo/commands/package.rs\", \"src/cargo/ops/cargo_package/\"]\n\n[autolabel.\"Command-pkgid\"]\ntrigger_files = [\"src/bin/cargo/commands/pkgid.rs\", \"src/cargo/ops/cargo_pkgid.rs\"]\n\n[autolabel.\"Command-publish\"]\ntrigger_files = [\"src/bin/cargo/commands/publish.rs\", \"src/cargo/ops/registry/publish.rs\"]\n\n[autolabel.\"Command-read-manifest\"]\ntrigger_files = [\"src/bin/cargo/commands/read_manifest.rs\", \"src/cargo/ops/cargo_read_manifest.rs\"]\n\n[autolabel.\"Command-remove\"]\ntrigger_files = [\"src/bin/cargo/commands/remove.rs\", \"src/cargo/ops/cargo_remove.rs\"]\n\n[autolabel.\"Command-report\"]\ntrigger_files = [\"src/bin/cargo/commands/report.rs\", \"src/cargo/ops/cargo_report/\"]\n\n[autolabel.\"Command-run\"]\ntrigger_files = [\"src/bin/cargo/commands/run.rs\", \"src/cargo/ops/cargo_run.rs\"]\n\n[autolabel.\"Command-rustc\"]\ntrigger_files = [\"src/bin/cargo/commands/rustc.rs\"]\n\n[autolabel.\"Command-rustdoc\"]\ntrigger_files = [\"src/bin/cargo/commands/rustdoc.rs\"]\n\n[autolabel.\"Command-search\"]\ntrigger_files = [\"src/bin/cargo/commands/search.rs\", \"src/cargo/ops/registry/search.rs\"]\n\n[autolabel.\"Command-test\"]\ntrigger_files = [\"src/bin/cargo/commands/test.rs\", \"src/cargo/ops/cargo_test.rs\"]\n\n[autolabel.\"Command-tree\"]\ntrigger_files = [\"src/bin/cargo/commands/tree.rs\", \"src/cargo/ops/tree/\"]\n\n[autolabel.\"Command-uninstall\"]\ntrigger_files = [\"src/bin/cargo/commands/uninstall.rs\", \"src/cargo/ops/cargo_uninstall.rs\"]\n\n[autolabel.\"Command-update\"]\ntrigger_files = [\"src/bin/cargo/commands/update.rs\", \"src/cargo/ops/cargo_update.rs\"]\n\n[autolabel.\"Command-vendor\"]\ntrigger_files = [\"src/bin/cargo/commands/vendor.rs\", \"src/cargo/ops/vendor.rs\"]\n\n[autolabel.\"Command-verify-project\"]\ntrigger_files = [\"src/bin/cargo/commands/verify_project.rs\"]\n\n[autolabel.\"Command-version\"]\ntrigger_files = [\"src/bin/cargo/commands/version.rs\"]\n\n[autolabel.\"Command-yank\"]\ntrigger_files = [\"src/bin/cargo/commands/yank.rs\", \"src/cargo/ops/registry/yank.rs\"]\n"
  },
  {
    "path": "typos.toml",
    "content": "[files]\nextend-exclude = [\n  \"crates/resolver-tests/*\",\n  \"LICENSE-THIRD-PARTY\",\n  \"tests/testsuite/script/rustc_fixtures\",\n]\n\n[default]\nextend-ignore-re = [\n  # Handles ssh keys\n  \"AAAA[0-9A-Za-z+/]+[=]{0,3}\",\n\n  # Handles paseto from login tests\n  \"k3[.](secret|public)[.][a-zA-Z0-9_-]+\",\n]\nextend-ignore-identifiers-re = [\n  # Handles git short SHA-1 hashes\n  \"[a-f0-9]{8,9}\",\n]\nextend-ignore-words-re = [\n  # words with length <= 4 chars is likely noise\n  \"^[a-zA-Z]{1,4}$\",\n]\n\n[default.extend-identifiers]\n# This comes from `windows_sys`\nERROR_FILENAME_EXCED_RANGE = \"ERROR_FILENAME_EXCED_RANGE\"\n# `-Wwarnings`\nWwarnings = \"Wwarnings\"\n\n# Name of a dependency\nflate2 = \"flate2\"\n\n[default.extend-words]\nfiletimes = \"filetimes\"\n\n[type.cargo_command]\nextend-glob = [\"cargo_command.rs\"]\n\n[type.cargo_command.extend-words]\nbiuld = \"biuld\"\n\n[type.random-sample]\nextend-glob = [\"random-sample\"]\n\n[type.random-sample.extend-words]\nobjekt = \"objekt\"\n"
  },
  {
    "path": "windows.manifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<!--\nThis is a Windows application manifest file.\nSee: https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests\n-->\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\" xmlns:asmv3=\"urn:schemas-microsoft-com:asm.v3\">\n    <!-- Versions cargo supports as hosts -->\n    <compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\"> \n        <application> \n            <!-- Windows 7 --><supportedOS Id=\"{35138b9a-5d96-4fbd-8e2d-a2440225f93a}\"/>\n            <!-- Windows 8 --><supportedOS Id=\"{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}\"/>\n            <!-- Windows 8.1 --><supportedOS Id=\"{1f676c76-80e1-4239-95bb-83d0f6d0da78}\"/>\n            <!-- Windows 10 and 11 --><supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\"/>\n        </application> \n    </compatibility>\n    <!-- Use UTF-8 code page -->\n    <asmv3:application>\n        <asmv3:windowsSettings xmlns=\"http://schemas.microsoft.com/SMI/2019/WindowsSettings\">\n            <activeCodePage>UTF-8</activeCodePage>\n        </asmv3:windowsSettings>\n    </asmv3:application>\n    <!-- Remove (most) legacy path limits -->\n    <asmv3:application>\n        <asmv3:windowsSettings xmlns:ws2=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">\n            <ws2:longPathAware>true</ws2:longPathAware>\n        </asmv3:windowsSettings>\n    </asmv3:application>\n</assembly>\n"
  }
]